qbs-src-3.3.1/0000755000175100017510000000000015232633614012503 5ustar runnerrunnerqbs-src-3.3.1/.github/0000755000175100017510000000000015232633614014043 5ustar runnerrunnerqbs-src-3.3.1/.github/workflows/0000755000175100017510000000000015232633614016100 5ustar runnerrunnerqbs-src-3.3.1/.github/workflows/main.yml0000644000175100017510000010045215232633614017551 0ustar runnerrunnername: Build and test Qbs on: push: paths-ignore: - 'changelogs/**' - 'doc/**' jobs: build-linux: name: ${{ matrix.config.name }} runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build on Linux (Noble, gcc)', image: 'noble-qt6', options: 'modules.cpp.compilerWrapper:ccache modules.qbs.debugInformation:true products.qbs_archive.targetName:qbs-linux-noble-${{ github.run_id }} products.qbs_archive.includeTests:true', script: './scripts/build-qbs-with-qbs.sh', cacheid: 'gcc-qt6-noble', suffix: 'linux-noble', } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: 0 steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache - name: Pull the Docker Image run: docker compose pull ${{ matrix.config.image }} - name: Print ccache stats run: docker compose run ${{ matrix.config.image }} ccache -s - name: Build Qbs run: docker compose run ${{ matrix.config.image }} ${{ matrix.config.script }} - name: Print ccache stats run: docker compose run ${{ matrix.config.image }} ccache -s - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz path: release/qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz build-linux-extra: name: ${{ matrix.config.name }} runs-on: ubuntu-latest timeout-minutes: 90 strategy: fail-fast: false matrix: config: - { name: 'Build on Linux (clang_tidy)', script: './scripts/run-analyzer.sh', image: 'noble-qt6', options: 'profile:qt-clang_64 modules.cpp.compilerWrapper:ccache', cacheid: 'clang', } - { name: 'Build on Linux (CMake)', script: './scripts/build-qbs-with-cmake.sh', image: 'noble-qt6', cacheid: 'cmake', } - { name: 'Build on Linux (gcc, ASAN)', image: 'noble-qt6', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:ccache modules.qbsbuildconfig.enableAddressSanitizer:true modules.qbs.debugInformation:true', cacheid: 'gcc-asan', } - { name: 'Build on Linux (gcc, UBSAN)', image: 'noble-qt6', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:ccache modules.qbsbuildconfig.enableUbSanitizer:true modules.qbs.debugInformation:true', cacheid: 'gcc-ubsan', } - { name: 'Build on Linux (gcc, Qt 5.15)', image: 'noble-qt5', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:ccache modules.qbs.debugInformation:true', cacheid: 'gcc-qt5', } env: BUILD_OPTIONS: ${{ matrix.config.options }} QTEST_FUNCTION_TIMEOUT: 9000000 steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache - name: Setup Coredumps run: | sudo bash -c 'echo "/cores/core.%e.%t.%p" > /proc/sys/kernel/core_pattern' sudo mkdir /cores sudo chmod 777 /cores - name: Pull the Docker Image run: docker compose pull ${{ matrix.config.image }} - name: Print ccache stats run: docker compose run ${{ matrix.config.image }} ccache -s - name: Build Qbs run: docker compose run ${{ matrix.config.image }} ${{ matrix.config.script }} - name: Print ccache stats run: docker compose run ${{ matrix.config.image }} ccache -s - name: Coredump on failure if: ${{ failure() }} run: docker compose run ${{ matrix.config.image }} ./scripts/print-cores.sh clang-format: name: Check Style runs-on: macos-15 timeout-minutes: 60 strategy: fail-fast: false steps: - uses: actions/checkout@v1 - name: Update PATH run: echo "$(brew --prefix llvm@18)/bin" >> ${GITHUB_PATH} - name: Run clang-format run: | git diff -U0 --no-color --relative HEAD^ | $(brew --prefix llvm@18)/share/clang/clang-format-diff.py -i -p1 -regex ".*\.(cxx|cpp|hpp|h)" -v - name: Check diff run: git diff --exit-code build-macos: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.runner }} timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build on macOS (Qbs, arm64)', runner: 'macos-14', profile: 'xcode_15_1-macosx-arm64', toolchain: 'clang_64', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:ccache modules.qbs.debugInformation:true modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-macos-arm64-${{ github.run_id }} products.qbs_archive.includeTests:true', cacheid: 'clang-arm64', with_tests: 0, suffix: 'macos-arm64', } - { name: 'Build on macOS (Qbs, x64)', runner: 'macos-14', profile: 'xcode_15_1-macosx-x86_64', toolchain: 'clang_64', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:ccache modules.qbs.debugInformation:true modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-macos-${{ github.run_id }} products.qbs_archive.includeTests:true', cacheid: 'clang', with_tests: 0, suffix: 'macos', } - { name: 'Build on macOS (CMake, x64)', runner: 'macos-15-intel', profile: 'xcode_16_4-macosx-x86_64', toolchain: 'clang_64', script: './scripts/build-qbs-with-cmake.sh', options: '', cacheid: 'clang-cmake', with_tests: 0, suffix: 'macos', } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: ${{ matrix.config.with_tests }} steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache - name: Install required packages run: brew install ccache - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.13' - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install beautifulsoup4 lxml - name: Install Qt uses: ./.github/actions/download-qt with: toolchain: ${{ matrix.config.toolchain }} - name: Install Qt Creator uses: ./.github/actions/download-qtc - name: Setup Qbs run: | qbs setup-toolchains --detect qbs setup-qt --detect qbs config profiles.qt.baseProfile ${{ matrix.config.profile }} qbs config defaultProfile qt qbs config --list - name: Print ccache stats run: ccache -s - name: Build Qbs run: ${{ matrix.config.script }} - name: Print ccache stats run: ccache -s - name: Upload artifacts uses: 'actions/upload-artifact@v4' if: matrix.config.cacheid != 'clang-cmake' with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz path: release/qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz build-windows: name: ${{ matrix.config.name }} runs-on: windows-2022 timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build on Windows (Qbs)', script: './scripts/build-qbs-with-qbs.sh', options: 'modules.cpp.compilerWrapper:clcache modules.qbs.debugInformation:true modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-windows-${{ github.run_id }} products.qbs_archive.includeTests:true', cacheid: 'msvc', with_tests: 0, suffix: 'windows', qmake: 'qmake.exe', } - { name: 'Build on Windows (CMake)', script: './scripts/build-qbs-with-cmake.sh', options: '', cacheid: 'msvc-cmake', with_tests: 0, suffix: 'windows-cmake', qmake: 'qmake.exe', } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: ${{ matrix.config.with_tests }} QT_ASSUME_STDERR_HAS_CONSOLE: 1 steps: - uses: actions/checkout@v1 - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: clcache cache files uses: actions/cache@v4 with: path: ~/clcache key: ${{ runner.os }}-${{ matrix.config.cacheid }}-clcache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-msvc-clcache - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.8 - name: Install required packages run: | python -m pip install --upgrade pip pip install beautifulsoup4 lxml pip install git+https://github.com/frerich/clcache.git@cae73d8255d78db8ba11e23c51fd2c9a89e7475b - name: Install Ninja run: choco install ninja shell: bash - name: Install Qt uses: ./.github/actions/download-qt with: toolchain: win64_msvc2022_64 - name: Install Qbs uses: ./.github/actions/download-qbs - name: Setup self-signed certificate run: | New-SelfSignedCertificate -DnsName qbs@community.test -Type CodeSigning -CertStoreLocation cert:\CurrentUser\My shell: powershell - uses: TheMrMilchmann/setup-msvc-dev@v3 with: arch: x64 - name: Test qmake run: | echo "$PATH" echo "qmake: ${{ matrix.config.qmake }}" echo "qmake: $(which ${{ matrix.config.qmake }})" echo "qmake\\path: $(where ${{ matrix.config.qmake }})" echo "qmake/path: $(cygpath $(where ${{ matrix.config.qmake }}))" shell: bash - name: Setup Qbs run: | qbs setup-toolchains --detect qbs setup-qt $(which qmake).exe qt qbs config profiles.qt.baseProfile MSVC2022-1-x86_x64 qbs config defaultProfile qt qbs config --list shell: bash - name: Print clcache stats run: clcache -s - name: Build Qbs run: ${{ matrix.config.script }} shell: bash - name: Print clcache stats run: clcache -s - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.zip path: release/qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.zip build-windows-mingw: name: Build on Windows (MinGW) runs-on: windows-2022 timeout-minutes: 60 env: BUILD_OPTIONS: | modules.cpp.compilerWrapper:ccache modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-windows-mingw-${{ github.run_id }} products.qbs_archive.includeTests:true, QT_ASSUME_STDERR_HAS_CONSOLE: 1 WITH_TESTS: 0 CCACHE_DIR: ${{ github.workspace }}\ccache steps: - uses: actions/checkout@v1 - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-mingw-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-mingw-ccache - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.8 - name: Install required packages run: | choco install ccache python -m pip install --upgrade pip pip install beautifulsoup4 lxml - name: Install Qt uses: ./.github/actions/download-qt with: toolchain: win64_mingw - name: Install Qbs uses: ./.github/actions/download-qbs - name: Install MinGW uses: ./.github/actions/download-mingw - name: Setup Qbs run: | qbs setup-toolchains --type mingw $(which g++).exe mingw-qt qbs setup-qt $(which qmake).exe qt qbs config profiles.qt.baseProfile mingw-qt qbs config defaultProfile qt qbs config --list shell: bash - name: Print ccache stats run: ccache -s - name: Build Qbs run: scripts/build-qbs-with-qbs.sh shell: bash - name: Print ccache stats run: ccache -s - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-windows-mingw-${{ github.run_id }}.zip path: release/qbs-windows-mingw-${{ github.run_id }}.zip test-linux: name: ${{ matrix.config.name }} runs-on: ubuntu-latest timeout-minutes: 90 needs: build-linux strategy: fail-fast: false matrix: config: - { name: 'Test Linux (gcc, Qt 6)', image: 'noble-qt6', suffix: 'linux-noble', profile: 'qt-gcc_64', script: './scripts/test-qbs.sh', } - { name: 'Test Linux (clang, Qt 6)', image: 'noble-qt6', suffix: 'linux-noble', profile: 'qt-clang_64', script: './scripts/test-qbs.sh', } - { name: 'Test Linux (gcc, Qt 6, static)', image: 'noble-qt6-static', suffix: 'linux-noble', profile: 'qt-gcc_64', script: './scripts/test-qbs.sh', } - { name: 'Test Linux (gcc, Qt 5)', image: 'noble-qt5', suffix: 'linux-noble', profile: 'qt-gcc_64', script: './scripts/test-qt.sh', } - { name: 'Test Android (Qt 6.5)', image: 'noble-android-65', suffix: 'linux-noble', profile: '', script: './scripts/test-qt-for-android.sh', } - { name: 'Test Android (Qt 5.15)', image: 'noble-android-515', suffix: 'linux-noble', profile: '', script: './scripts/test-qt-for-android.sh', } - { name: 'Test Android (ndk r25)', image: 'noble-android-ndk-r25', suffix: 'linux-noble', profile: '', script: './scripts/test-for-android.sh', } - { name: 'Test WebAssembly', image: 'noble-qt6-wasm', suffix: 'linux-noble', profile: '', script: './scripts/test-wasm.sh', } env: QBS_TEST_SOURCE_ROOT: 'tests' QBS_AUTOTEST_PROFILE: ${{ matrix.config.profile }} QTEST_FUNCTION_TIMEOUT: 9000000 steps: - uses: actions/checkout@v1 - name: Download artifact uses: actions/download-artifact@v4 with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz path: ./ - name: Unpack artifact run: mkdir -p release/install-root/ && tar xzf qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz -C release/install-root/ - name: Setup Coredumps run: | sudo bash -c 'echo "/cores/core.%e.%t.%p" > /proc/sys/kernel/core_pattern' sudo mkdir /cores sudo chmod 777 /cores - name: Pull the Docker Image run: docker compose pull ${{ matrix.config.image }} - name: Run tests run: docker compose run ${{ matrix.config.image }} ${{ matrix.config.script }} release/install-root/usr/local/bin - name: Coredump on failure if: ${{ failure() }} run: docker compose run ${{ matrix.config.image }} ./scripts/print-cores.sh test-baremetal: name: Test Baremetal (Linux) runs-on: ubuntu-latest timeout-minutes: 60 needs: build-linux env: QBS_TEST_SOURCE_ROOT: 'tests' steps: - uses: actions/checkout@v1 - name: Download artifact uses: actions/download-artifact@v4 with: name: qbs-linux-noble-${{ github.run_id }}.tar.gz path: ./ - name: Unpack artifact run: mkdir -p release/install-root/ && tar xzf qbs-linux-noble-${{ github.run_id }}.tar.gz -C release/install-root/ - name: Pull the Docker Image run: docker compose pull noble-baremetal - name: arm-none-eabi-gcc-13_2 run: QBS_AUTOTEST_PROFILE=arm-none-eabi-gcc-13_2 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: avr-gcc-7_3 run: QBS_AUTOTEST_PROFILE=avr-gcc-7_3 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: riscv64-unknown-elf-gcc-13_2 run: QBS_AUTOTEST_PROFILE=riscv64-unknown-elf-gcc-13_2 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: sdcc-4_0_0-hcs8 run: QBS_AUTOTEST_PROFILE=sdcc-4_2_0-hcs8 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: sdcc-4_0_0-mcs51 run: QBS_AUTOTEST_PROFILE=sdcc-4_2_0-mcs51 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: sdcc-4_0_0-stm8 run: QBS_AUTOTEST_PROFILE=sdcc-4_2_0-stm8 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin - name: xtensa-lx106-elf-gcc-13_2 run: QBS_AUTOTEST_PROFILE=xtensa-lx106-elf-gcc-13_2 docker compose run noble-baremetal scripts/test-baremetal.sh release/install-root/usr/local/bin test-macos: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.runner }} timeout-minutes: 60 needs: build-macos env: QTEST_FUNCTION_TIMEOUT: 9000000 QBS_AUTOTEST_PROFILE: 'qt' QBS_TEST_SOURCE_ROOT: 'tests' QBS_EXTRA_GRPC_LIBS: 'absl_cord,absl_cordz_handle,absl_cordz_info,absl_synchronization,grpc,gpr' strategy: fail-fast: false matrix: config: - { name: 'Test macOS (Xcode 16.4, arm64)', runner: 'macos-15', target: 'desktop', toolchain: 'clang_64', xcodeVersion: '16.4', testProfile: 'xcode_16_4-macosx-arm64', qtVersion: '6.8.3', suffix: 'macos-arm64', script: './scripts/test-qbs.sh', } - { name: 'Test iOS (Xcode 16.4, arm64)', runner: 'macos-15', target: 'ios', toolchain: 'ios', xcodeVersion: '16.4', testProfile: 'xcode_16_4-iphoneos-arm64', qtVersion: '6.8.3', suffix: 'macos-arm64', script: './scripts/test-qbs.sh', } - { name: 'Test iOS-sim (Xcode 16.4, x64)', runner: 'macos-15', target: 'ios', toolchain: 'ios', xcodeVersion: '16.4', # Qt does not support arm64 simulators, # see https://bugreports.qt.io/browse/QTBUG-101276 testProfile: 'xcode_16_4-iphonesimulator-x86_64', qtVersion: '6.8.3', suffix: 'macos-arm64', script: './scripts/test-qbs.sh', } - { name: 'Test macOS (Xcode 16.4, x64)', runner: 'macos-15-intel', target: 'desktop', toolchain: 'clang_64', xcodeVersion: '16.4', testProfile: 'xcode_16_4-macosx-x86_64', qtVersion: '6.8.3', suffix: 'macos', script: './scripts/test-qbs.sh', } - { name: 'Test macOS (Xcode 16.4, Qt 5.15, x64)', runner: 'macos-15-intel', target: 'desktop', toolchain: 'clang_64', xcodeVersion: '16.4', testProfile: 'xcode_16_4-macosx-x86_64', qtVersion: '5.15.2', suffix: 'macos', script: './scripts/test-qt.sh', } - { name: 'Test macOS (Xcode 15.4, arm64)', runner: 'macos-14', target: 'desktop', toolchain: 'clang_64', xcodeVersion: '15.4', testProfile: 'xcode_15_4-macosx-arm64', qtVersion: '6.8.3', suffix: 'macos-arm64', script: './scripts/test-qbs.sh', } - { name: 'Test macOS (Xcode-less, arm64)', runner: 'macos-15', target: 'desktop', toolchain: 'clang_64', xcodeVersion: '', testProfile: 'clang', qtVersion: '6.8.3', suffix: 'macos-arm64', script: './scripts/test-qbs.sh', } steps: - uses: actions/checkout@v1 - name: Download artifact uses: actions/download-artifact@v4 with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz path: ./ - name: Unpack artifact run: mkdir -p release/install-root/ && tar xzf qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz -C release/install-root/ - name: Update PATH run: echo "./release/install-root/usr/local/bin" >> $GITHUB_PATH - name: Install required packages run: brew install capnp ccache grpc icoutils makensis protobuf - name: Set up Python uses: actions/setup-python@v5 if: matrix.config.toolchain == 'clang_64' with: python-version: 3.12 - name: Install Conan if: matrix.config.toolchain == 'clang_64' uses: turtlebrowser/get-conan@main - name: Setup Conan if: matrix.config.toolchain == 'clang_64' run: ./scripts/setup-conan-profiles.sh - name: Install Host Qt if: matrix.config.toolchain == 'ios' uses: ./.github/actions/download-qt with: target: 'desktop' toolchain: 'clang_64' version: ${{ matrix.config.qtVersion }} - name: Install Qt uses: ./.github/actions/download-qt with: target: ${{ matrix.config.target }} toolchain: ${{ matrix.config.toolchain }} version: ${{ matrix.config.qtVersion }} - name: Select Xcode run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.config.xcodeVersion }}.app if: matrix.config.xcodeVersion != '' - name: Setup Qbs run: | qbs setup-toolchains --detect qbs setup-qt $(which qmake) qt qbs config profiles.qt.baseProfile ${{ matrix.config.testProfile }} qbs config defaultProfile qt qbs config --list if: matrix.config.xcodeVersion != '' - name: Setup Qbs (Xcode-less) run: | qbs setup-toolchains $(brew --prefix llvm@18)/bin/clang ${{ matrix.config.testProfile }} qbs config profiles.${{ matrix.config.testProfile }}.qbs.architecture arm64 qbs setup-qt $(which qmake) qt qbs config profiles.qt.baseProfile ${{ matrix.config.testProfile }} qbs config defaultProfile qt qbs config --list if: matrix.config.xcodeVersion == '' - name: Run Tests run: | sudo chmod 777 /cores ulimit -c unlimited ${{ matrix.config.script }} ./release/install-root/usr/local/bin - name: Coredump on failure if: ${{ failure() }} run: | for f in $(find /cores -maxdepth 1 -name 'core.*' -print); do lldb --core $f --batch --one-line "bt all" done; test-windows: name: ${{ matrix.config.name }} runs-on: windows-2022 timeout-minutes: 60 needs: build-windows strategy: fail-fast: false matrix: config: - { name: 'Test Windows (MSVC 2022, x64)', target: 'desktop', toolchain: 'win64_msvc2022_64', testProfile: 'MSVC2022-x64', conan_toolchain: 'msvc_64', qtVersion: '6.8.3', script: './scripts/test-qbs.sh', qmake: 'qmake.exe', } - { name: 'Test Windows (MSVC 2022, arm64)', target: 'desktop', toolchain: 'win64_msvc2022_arm64_cross_compiled', testProfile: 'MSVC2022-x64_arm64', conan_toolchain: '', qtVersion: '6.8.3', script: './scripts/test-qbs.sh', qmake: 'qmake.bat', } - { name: 'Test Windows (MSVC 2022, Qt 5.15)', target: 'desktop', toolchain: 'win64_msvc2019_64', testProfile: 'MSVC2022-x64', conan_toolchain: '', qtVersion: '5.15.2', script: './scripts/test-qt.sh', qmake: 'qmake.exe', } - { name: 'Test Windows (clang-cl)', target: 'desktop', toolchain: 'win64_msvc2022_64', testProfile: 'clang-cl-x86_64', conan_toolchain: '', qtVersion: '6.8.3', script: './scripts/test-qbs.sh', qmake: 'qmake.exe', } - { name: 'Test Windows (MinGW)', target: 'desktop', toolchain: 'win64_mingw', testProfile: 'mingw-qt', conan_toolchain: 'mingw_64', qtVersion: '6.5.0', script: './scripts/test-qbs.sh', qmake: 'qmake.exe', } env: QTEST_FUNCTION_TIMEOUT: 9000000 QBS_AUTOTEST_PROFILE: 'qt' QBS_TEST_SOURCE_ROOT: 'tests' QT_ASSUME_STDERR_HAS_CONSOLE: 1 steps: - uses: actions/checkout@v1 - name: Download artifact uses: actions/download-artifact@v4 with: name: qbs-windows-${{ github.run_id }}.zip path: ./ - name: Unpack artifact run: | mkdir -p release/install-root cd release/install-root 7z x ../../qbs-windows-${{ github.run_id }}.zip shell: bash - name: Update PATH run: echo "./release/install-root/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Install required packages run: choco install -y pkgconfiglite --download-checksum=6004df17818f5a6dbf19cb335cc92702 continue-on-error: true # pkgconfiglite installation is flaky - name: Install Qt uses: ./.github/actions/download-qt with: toolchain: ${{ matrix.config.toolchain }} version: ${{ matrix.config.qtVersion }} - name: Install Host Qt if: matrix.config.toolchain == 'win64_msvc2022_arm64_cross_compiled' uses: ./.github/actions/download-qt with: target: 'desktop' toolchain: 'win64_msvc2022_64' version: ${{ matrix.config.qtVersion }} - name: Install MinGW uses: ./.github/actions/download-mingw - name: Install Ninja if: matrix.config.conan_toolchain != '' run: | choco install ninja shell: bash - name: Install Conan if: matrix.config.conan_toolchain != '' uses: turtlebrowser/get-conan@main - name: Configure Conan if: matrix.config.conan_toolchain != '' run: | ./scripts/setup-conan-profiles.sh --toolchain ${{ matrix.config.conan_toolchain }} which ninja shell: bash - name: Setup Qbs run: | qbs setup-toolchains --detect qbs setup-toolchains --type mingw $(which g++).exe mingw-qt qbs setup-qt $(cygpath $(where ${{ matrix.config.qmake }})) qt qbs config profiles.qt.baseProfile ${{ matrix.config.testProfile }} qbs config defaultProfile qt qbs config --list shell: bash - name: Setup self-signed certificate run: | New-SelfSignedCertificate -DnsName qbs@community.test -Type CodeSigning -CertStoreLocation cert:\CurrentUser\My shell: powershell - name: Run Tests run: ${{ matrix.config.script }} ./release/install-root/bin shell: bash test-windows-extra: name: ${{ matrix.config.name }} runs-on: windows-latest timeout-minutes: 60 needs: build-windows strategy: fail-fast: false matrix: config: - { name: 'Test Windows (OpenWatcom DOS 32 bit)', testProfile: 'watcom-2_0_0-dos-x86', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (OpenWatcom DOS 16 bit)', testProfile: 'watcom-2_0_0-dos-x86_16', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (OpenWatcom OS/2 32 bit)', testProfile: 'watcom-2_0_0-os2-x86', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (OpenWatcom OS/2 16 bit)', testProfile: 'watcom-2_0_0-os2-x86_16', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (OpenWatcom Windows 32 bit)', testProfile: 'watcom-2_0_0-windows-x86', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (OpenWatcom Windows 16 bit)', testProfile: 'watcom-2_0_0-windows-x86_16', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (DigitalMars DOS 16 bit)', testProfile: 'dmc-8_57_0-dos-x86_16', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (DigitalMars Windows 32 bit)', testProfile: 'dmc-8_57_0-windows-x86', script: './scripts/test-baremetal.sh', } - { name: 'Test Windows (DigitalMars Windows 16 bit)', testProfile: 'dmc-8_57_0-windows-x86_16', script: './scripts/test-baremetal.sh', } env: QTEST_FUNCTION_TIMEOUT: 9000000 QBS_AUTOTEST_PROFILE: 'extra' QBS_TEST_SOURCE_ROOT: 'tests' QT_ASSUME_STDERR_HAS_CONSOLE: 1 steps: - uses: actions/checkout@v1 - name: Download artifact uses: actions/download-artifact@v4 with: name: qbs-windows-${{ github.run_id }}.zip path: ./ - name: Unpack artifact run: | mkdir -p release/install-root cd release/install-root 7z x ../../qbs-windows-${{ github.run_id }}.zip shell: bash - name: Update PATH run: echo "./release/install-root/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Install OpenWatcom uses: ./.github/actions/download-ow - name: Install DigitalMars uses: ./.github/actions/download-dm - name: Setup Qbs run: | qbs setup-toolchains --detect qbs config profiles.extra.baseProfile ${{ matrix.config.testProfile }} qbs config defaultProfile extra qbs config --list shell: bash - name: Run Tests run: ${{ matrix.config.script }} ./release/install-root/bin shell: bash qbs-src-3.3.1/.github/workflows/release.yml0000644000175100017510000002436615232633614020256 0ustar runnerrunnername: Build release packages on: push: branches-ignore: - 'gerrit/*' tags: - 'v*' jobs: build-linux: name: ${{ matrix.config.name }} runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build on Linux (gcc)', options: 'qbs.installPrefix:"" modules.cpp.compilerWrapper:ccache modules.qbsbuildconfig.enableAddressSanitizer:false project.withTests:false modules.qbsbuildconfig.enableUnitTests:false products.qbs_archive.targetName:qbs-linux-${{ github.run_id }}', script: './scripts/build-qbs-with-qbs.sh', cacheid: 'gcc-release', } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: 0 steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache - name: Pull the Docker Image run: docker compose pull noble-qt6 - name: Print ccache stats run: docker compose run noble-qt6 ccache -s - name: Build Qbs run: docker compose run noble-qt6 ${{ matrix.config.script }} - name: Print ccache stats run: docker compose run noble-qt6 ccache -s - name: Get archive name id: get-archive-name run: echo "archive-name=$(git describe)" >> $GITHUB_OUTPUT - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-linux-${{ github.run_id }}.tar.gz path: release/qbs-linux-${{ github.run_id }}.tar.gz build-macos: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.runner }} timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build on macOS (arm64)', runner: 'macos-14', profile: 'xcode_15_1-macosx-arm64', toolchain: 'clang_64', options: 'qbs.installPrefix:"" modules.cpp.compilerWrapper:ccache project.withTests:false modules.qbsbuildconfig.enableUnitTests:false modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-macos-arm64-${{ github.run_id }}', suffix: 'macos-arm64', } - { name: 'Build on macOS (x86_64)', runner: 'macos-14', profile: 'xcode_15_1-macosx-x86_64', toolchain: 'clang_64', options: 'qbs.installPrefix:"" modules.cpp.compilerWrapper:ccache project.withTests:false modules.qbsbuildconfig.enableUnitTests:false modules.qbsbuildconfig.enableAddressSanitizer:false products.qbs_archive.targetName:qbs-macos-x86_64-${{ github.run_id }}', suffix: 'macos-x86_64', } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: 0 steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache - name: prepare timestamp id: get-timestamp run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT shell: bash - name: ccache cache files uses: actions/cache@v4 with: path: ~/.ccache key: ${{ runner.os }}-release-ccache-${{ steps.get-timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-release-ccache - name: Install required packages run: brew install ccache - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.13' - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install beautifulsoup4 lxml - name: Install Qt uses: ./.github/actions/download-qt with: toolchain: ${{ matrix.config.toolchain }} - name: Install Qt Creator uses: ./.github/actions/download-qtc - name: Setup Qbs run: | qbs setup-toolchains --detect qbs setup-qt --detect qbs config profiles.qt.baseProfile ${{ matrix.config.profile }} qbs config defaultProfile qt qbs config --list - name: Print ccache stats run: ccache -s - name: Build Qbs run: scripts/build-qbs-with-qbs.sh - name: Print ccache stats run: ccache -s - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz path: release/qbs-${{ matrix.config.suffix }}-${{ github.run_id }}.tar.gz build-windows-with-docker: name: Build on Windows (Docker) runs-on: windows-2022 timeout-minutes: 60 env: WITH_TESTS: 0 QT_ASSUME_STDERR_HAS_CONSOLE: 1 steps: - uses: actions/checkout@v1 - name: Create .ccache dir run: mkdir -p ~/.ccache shell: bash - name: Pull the Windows Image run: docker compose pull windows - name: Build Qbs run: > docker compose run --rm windows qbs build -p dist qbs.buildVariant:release project.withTests:false modules.qbsbuildconfig.enableBundledQt:true modules.qbsbuildconfig.enableUnitTests:false modules.cpp.treatWarningsAsErrors:true project.withDocumentation:true config:release profile:qt64 - name: Get archive name id: get-archive-name run: echo "archive-name=$(git describe)" >> $GITHUB_OUTPUT - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-windows-${{ github.run_id }} path: | release/qbs.*.nupkg release/qbs-windows-*.zip create-archives: name: Create Archives runs-on: ubuntu-latest needs: [build-macos, build-linux, build-windows-with-docker] steps: - uses: actions/checkout@v1 with: submodules: true - name: Get version name id: get-version-name run: echo "version-name=$(cat VERSION)" >> $GITHUB_OUTPUT - name: Create directories run: | mkdir release mkdir tmp - name: Copy sources run: rsync -av --exclude='.git/' --exclude='tmp/' . ./tmp/qbs-src-${{ steps.get-version-name.outputs.version-name }} - name: Zip Archive run: | cd tmp/ zip -r ../release/qbs-src-${{ steps.get-version-name.outputs.version-name }}.zip qbs-src-${{ steps.get-version-name.outputs.version-name }} - name: Tarball Archive run: | cd tmp/ tar czf ../release/qbs-src-${{ steps.get-version-name.outputs.version-name }}.tar.gz qbs-src-${{ steps.get-version-name.outputs.version-name }} - name: Download Linux artifacts uses: actions/download-artifact@v4 with: name: qbs-linux-${{ github.run_id }}.tar.gz path: ./tmp - name: Repack Linux artifact run: | mkdir -p tmp/qbs-linux-x86_64-${{ steps.get-version-name.outputs.version-name }} tar xzf ./tmp/qbs-linux-${{ github.run_id }}.tar.gz -C tmp/qbs-linux-x86_64-${{ steps.get-version-name.outputs.version-name }} cd tmp/ tar czf ../release/qbs-linux-x86_64-${{ steps.get-version-name.outputs.version-name }}.tar.gz qbs-linux-x86_64-${{ steps.get-version-name.outputs.version-name }} - name: Download Windows artifacts uses: actions/download-artifact@v4 with: name: qbs-windows-${{ github.run_id }} path: ./tmp/release - name: Copy Windows artifacts run: | cp ./tmp/release/qbs.*.nupkg ./release cp ./tmp/release/qbs-windows-x86_64-*.zip ./release - name: Download macOS arm64 artifacts uses: actions/download-artifact@v4 with: name: qbs-macos-arm64-${{ github.run_id }}.tar.gz path: ./tmp/ - name: Repack Macos arm64 artifact run: | mkdir -p tmp/qbs-macos-arm64-${{ steps.get-version-name.outputs.version-name }} tar xzf ./tmp/qbs-macos-arm64-${{ github.run_id }}.tar.gz -C tmp/qbs-macos-arm64-${{ steps.get-version-name.outputs.version-name }} cd tmp/ tar czf ../release/qbs-macos-arm64-${{ steps.get-version-name.outputs.version-name }}.tar.gz qbs-macos-arm64-${{ steps.get-version-name.outputs.version-name }} - name: Download macOS x86_64 artifacts uses: actions/download-artifact@v4 with: name: qbs-macos-x86_64-${{ github.run_id }}.tar.gz path: ./tmp - name: Repack Macos x86_64 artifact run: | mkdir -p tmp/qbs-macos-x86_64-${{ steps.get-version-name.outputs.version-name }} tar xzf ./tmp/qbs-macos-x86_64-${{ github.run_id }}.tar.gz -C tmp/qbs-macos-x86_64-${{ steps.get-version-name.outputs.version-name }} cd tmp/ tar czf ../release/qbs-macos-x86_64-${{ steps.get-version-name.outputs.version-name }}.tar.gz qbs-macos-x86_64-${{ steps.get-version-name.outputs.version-name }} - name: Copy changelog run: cp changelogs/changes-${{ steps.get-version-name.outputs.version-name }}.md release || echo "changelog not found" - name: Generate checksums run: | cd release/ find . -type f -printf '%f\n' | grep -v .txt | xargs md5sum > md5sums.txt find . -type f -printf '%f\n' | grep -v .txt | xargs sha256sum > sha256sums.txt - name: Get archive name id: get-archive-name run: echo "archive-name=$(git describe)" >> $GITHUB_OUTPUT - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-release-${{ steps.get-archive-name.outputs.archive-name }} path: | release/qbs-src-*.zip release/qbs-src-*.tar.gz release/qbs-linux-*.tar.gz release/qbs-macos-*.tar.gz release/qbs.*.nupkg release/qbs-windows-x86_64-*.zip release/changes-*.md release/md5sums.txt release/sha256sums.txt qbs-src-3.3.1/.github/workflows/docs.yml0000644000175100017510000000163615232633614017561 0ustar runnerrunnername: Build and Qbs docs on: push: paths: - 'doc/**' - 'examples/**' - 'scripts/build-qbs-doc.sh' - 'VERSION' jobs: build-docs: name: ${{ matrix.config.name }} runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: config: - { name: 'Build Qbs Docs', options: '', script: './scripts/build-qbs-doc.sh' } env: BUILD_OPTIONS: ${{ matrix.config.options }} WITH_TESTS: 0 steps: - uses: actions/checkout@v1 - name: Pull the Docker Image run: docker compose pull noble - name: Build Qbs Docs run: docker compose run noble ${{ matrix.config.script }} - name: Upload artifacts uses: 'actions/upload-artifact@v4' with: name: qbs-docs-${{ github.run_id }} path: documentation/install-root/usr/local/share/doc/qbs/ qbs-src-3.3.1/.github/actions/0000755000175100017510000000000015232633614015503 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-mingw/0000755000175100017510000000000015232633614020431 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-mingw/action.yml0000644000175100017510000000104115232633614022425 0ustar runnerrunnername: 'Download MinGW' description: 'Downloads MinGW' inputs: version: description: 'MinGW version' required: false default: '9.0.0' toolchain: description: 'Toolchain' required: false default: 'win64_mingw' runs: using: "composite" steps: - name: Install MinGW run: | MINGW_DIR=$(./scripts/install-qt.sh -d $HOME/Qt --version ${{ inputs.version }} --toolchain ${{ inputs.toolchain }} mingw) (cygpath -w ${MINGW_DIR} 2>/dev/null || echo ${MINGW_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.github/actions/download-qt/0000755000175100017510000000000015232633614017734 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-qt/action.yml0000644000175100017510000000126215232633614021735 0ustar runnerrunnername: 'Download Qt' description: 'Downloads Qt' inputs: version: description: 'Qt version' required: false default: '6.8.3' target: description: 'Qt target (desktop, ios, android)' required: false default: 'desktop' toolchain: description: 'Qt toolchain' required: true runs: using: "composite" steps: - name: Install Qt run: | QT_DIR=$(./scripts/install-qt.sh -d $HOME/Qt --version ${{ inputs.version }} --target ${{ inputs.target }} --toolchain ${{ inputs.toolchain }} qtbase qtdeclarative qttools qtscxml qt5compat qtshadertools) (cygpath -w ${QT_DIR} 2>/dev/null || echo ${QT_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.github/actions/download-ow/0000755000175100017510000000000015232633614017735 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-ow/action.yml0000644000175100017510000000065315232633614021741 0ustar runnerrunnername: 'Download OpenWatcom' description: 'Downloads OpenWatcom' inputs: version: description: 'OpenWatcom version' required: false default: '2.0' runs: using: "composite" steps: - name: Install OpenWatcom run: | OW_DIR=$(./scripts/install-ow.sh -d $HOME/watcom --version ${{ inputs.version }}) (cygpath -w ${OW_DIR} 2>/dev/null || echo ${OW_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.github/actions/download-qtc/0000755000175100017510000000000015232633614020077 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-qtc/action.yml0000644000175100017510000000066715232633614022110 0ustar runnerrunnername: 'Download Qt Creator' description: 'Downloads Qt Creator' inputs: version: description: 'Qt Creator version' required: false default: '11.0.3' runs: using: "composite" steps: - name: Install Qt Creator run: | QTC_DIR=$(./scripts/install-qt.sh -d $HOME/Qt --version ${{ inputs.version }} qtcreator) (cygpath -w ${QTC_DIR} 2>/dev/null || echo ${QTC_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.github/actions/download-qbs/0000755000175100017510000000000015232633614020075 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-qbs/action.yml0000644000175100017510000000063115232633614022075 0ustar runnerrunnername: 'Download Qbs' description: 'Downloads Qbs' inputs: version: description: 'Qbs version' required: false default: '2.5.0' runs: using: "composite" steps: - name: Install Qt Creator run: | QBS_DIR=$(./scripts/install-qbs.sh -d $HOME/qbs --version ${{ inputs.version }}) (cygpath -w ${QBS_DIR} 2>/dev/null || echo ${QBS_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.github/actions/download-dm/0000755000175100017510000000000015232633614017710 5ustar runnerrunnerqbs-src-3.3.1/.github/actions/download-dm/action.yml0000644000175100017510000000065415232633614021715 0ustar runnerrunnername: 'Download DigitalMars' description: 'Downloads DigitalMars' inputs: version: description: 'DigitalMars version' required: false default: '8.57' runs: using: "composite" steps: - name: Install DigitalMars run: | DM_DIR=$(./scripts/install-dm.sh -d $HOME/dm --version ${{ inputs.version }}) (cygpath -w ${DM_DIR} 2>/dev/null || echo ${DM_DIR}) >> ${GITHUB_PATH} shell: bash qbs-src-3.3.1/.dockerignore0000644000175100017510000000002715232633614015156 0ustar runnerrunner* !docker/* !scripts/* qbs-src-3.3.1/qbs.qbs0000644000175100017510000000212615232633614014000 0ustar runnerrunnerProject { minimumQbsVersion: "1.6" qbsSearchPaths: ["qbs-resources"] property bool withCode: true property bool withDocumentation: true property bool withTests: withCode property stringList autotestArguments: [] property stringList autotestWrapper: [] references: [ "docker/docker.qbs", "examples/examples.qbs", "share/share.qbs", "scripts/scripts.qbs", "tutorial/tutorial.qbs", ] SubProject { filePath: "doc/doc.qbs" Properties { condition: parent.withDocumentation } } SubProject { filePath: "src/src.qbs" Properties { condition: parent.withCode } } SubProject { filePath: "tests/tests.qbs" Properties { condition: parent.withTests } } Product { name: "version" files: ["VERSION"] } Product { name: "continuous integration files" files: [ ".clang-tidy", "docker-compose.yml", ".github/**/*.yml", ] } } qbs-src-3.3.1/.gitattributes0000644000175100017510000000014715232633614015400 0ustar runnerrunner/.gitignore export-ignore /.gitattributes export-ignore /scripts/make-release-archive.sh export-ignore qbs-src-3.3.1/.mailmap0000644000175100017510000000266015232633614014130 0ustar runnerrunner qbs-src-3.3.1/docker-compose.yml0000644000175100017510000000644215232633614016146 0ustar runnerrunnerversion: "3.7" x-default-service: &linux working_dir: /qbs environment: - BUILD_OPTIONS - QTEST_FUNCTION_TIMEOUT - QBS_AUTOTEST_PROFILE - QBS_TEST_SOURCE_ROOT - WITH_ARCHIVE - WITH_TESTS volumes: - .:/qbs - ~/.ccache:/home/devel/.ccache - /cores:/cores network_mode: bridge cap_add: - SYS_PTRACE ulimits: core: soft: -1 hard: -1 services: noble-qt6: &noble-qt6 << : *linux hostname: noble-qt6 image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-qt6-6.8.3_2.5.1-1 build: dockerfile: docker/noble/Dockerfile context: . args: QT_VERSION: 6.8.3 QBS_VERSION: 2.5.1 noble: << : *noble-qt6 noble-qt5: << : *linux hostname: noble-qt5 image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-5.15.2_2.5.1-2 build: dockerfile: docker/noble/Dockerfile context: . args: QT_VERSION: 5.15.2 QBS_VERSION: 2.5.1 noble-android-65: << : *linux hostname: noble-android image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-android-6.5.0-0 build: dockerfile: docker/noble/test-android.Dockerfile context: . args: QT_VERSION: 6.5.0 ANDROID_NDK_VERSION: 25.1.8937393 noble-android-515: << : *linux hostname: noble-android image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-android-5.15.2-0 build: dockerfile: docker/noble/test-android.Dockerfile context: . args: QT_VERSION: 5.15.2 ANDROID_NDK_VERSION: 23.0.7599858 noble-android-ndk-r25: << : *linux hostname: noble-android image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-android-ndk-r25-0 build: dockerfile: docker/noble/test-android-no-qt.Dockerfile context: . args: ANDROID_NDK_VERSION: 25.1.8937393 noble-baremetal: << : *linux hostname: noble-baremetal image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-baremetal-0 build: dockerfile: docker/noble/test-baremetal.Dockerfile context: . noble-qt6-static: << : *linux hostname: noble-qt6-static image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-qt6-static-6.5.3_2.3.2-0 build: dockerfile: docker/noble/test-qt6-static.Dockerfile context: . args: QT_VERSION: 6.5.3 QTCREATOR_VERSION: 13.0.2 noble-qt6-wasm: << : *linux hostname: noble-qt6-wasm image: ${DOCKER_USER:-qbsbuild}/qbsdev:noble-qt6-wasm-6.7.3-0 build: dockerfile: docker/noble/test-qt6-wasm.Dockerfile context: . args: QT_VERSION: 6.7.3 EMSCRIPTEN_VERSION: 3.1.50 leap: << : *linux hostname: leap image: ${DOCKER_USER:-qbsbuild}/qbsdev:leap-5.15.2_1.20.1-1 build: dockerfile: docker/leap/Dockerfile context: . args: QT_VERSION: 5.15.2 QTCREATOR_VERSION: 5.0.3 windows: image: ${DOCKER_USER:-qbsbuild}/qbsdev:windowsservercore-6.8.3_3.0.1-1 build: dockerfile: docker/windowsservercore/Dockerfile context: . args: QT_VERSION: 6.8.3 QBS_VERSION: 3.0.1 working_dir: 'C:/qbs' environment: - BUILD_OPTIONS - WITH_DOCS volumes: - type: bind source: . target: C:\qbs - type: bind source: ~/.ccache target: C:\.ccache network_mode: nat qbs-src-3.3.1/examples/0000755000175100017510000000000015232633614014321 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-touch-application/0000755000175100017510000000000015232633614021026 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/0000755000175100017510000000000015232633614027235 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/project.pbxproj0000644000175100017510000005101415232633614032312 0ustar runnerrunner// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEA9175FB2E800C857C6 /* UIKit.framework */; }; 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAB175FB2E800C857C6 /* Foundation.framework */; }; 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */; }; 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */; }; 14E3FEB6175FB2E800C857C6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB5175FB2E800C857C6 /* main.m */; }; 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */; }; 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */; }; 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */; }; 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */; }; 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */; }; 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */; }; 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */; }; AC83486F258674C900A9CBBB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC83486E258674C900A9CBBB /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Touch Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14E3FEA9175FB2E800C857C6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 14E3FEAB175FB2E800C857C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaTouchApplication-Info.plist"; sourceTree = ""; }; 14E3FEB3175FB2E800C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14E3FEB5175FB2E800C857C6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaTouchApplication-Prefix.pch"; sourceTree = ""; }; 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 14E3FEC8175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECB175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECE175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED1175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPad.xib; sourceTree = ""; }; AC83486E258674C900A9CBBB /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14E3FEA3175FB2E800C857C6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */, 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */, 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14E3FE9D175FB2E800C857C6 = { isa = PBXGroup; children = ( 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */, 14E3FEA8175FB2E800C857C6 /* Frameworks */, 14E3FEA7175FB2E800C857C6 /* Products */, ); sourceTree = ""; }; 14E3FEA7175FB2E800C857C6 /* Products */ = { isa = PBXGroup; children = ( 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */, ); name = Products; sourceTree = ""; }; 14E3FEA8175FB2E800C857C6 /* Frameworks */ = { isa = PBXGroup; children = ( 14E3FEA9175FB2E800C857C6 /* UIKit.framework */, 14E3FEAB175FB2E800C857C6 /* Foundation.framework */, 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */, ); name = Frameworks; sourceTree = ""; }; 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */ = { isa = PBXGroup; children = ( 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */, 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */, 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */, 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */, 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */, 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */, 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */, 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */, 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */, 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */, 14E3FEB0175FB2E800C857C6 /* Supporting Files */, AC83486E258674C900A9CBBB /* LaunchScreen.storyboard */, ); path = CocoaTouchApplication; sourceTree = ""; }; 14E3FEB0175FB2E800C857C6 /* Supporting Files */ = { isa = PBXGroup; children = ( 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */, 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */, 14E3FEB5175FB2E800C857C6 /* main.m */, 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */; buildPhases = ( 14E3FEA2175FB2E800C857C6 /* Sources */, 14E3FEA3175FB2E800C857C6 /* Frameworks */, 14E3FEA4175FB2E800C857C6 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Touch Application"; productName = CocoaTouchApplication; productReference = 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14E3FE9E175FB2E800C857C6 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1220; ORGANIZATIONNAME = io.qbs; }; buildConfigurationList = 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, ); mainGroup = 14E3FE9D175FB2E800C857C6; productRefGroup = 14E3FEA7175FB2E800C857C6 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14E3FEA4175FB2E800C857C6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( AC83486F258674C900A9CBBB /* LaunchScreen.storyboard in Resources */, 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */, 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */, 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */, 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */, 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14E3FEA2175FB2E800C857C6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEB6175FB2E800C857C6 /* main.m in Sources */, 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */, 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */, 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14E3FEB3175FB2E800C857C6 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FEC8175FB2E900C857C6 /* en */, ); name = MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECB175FB2E900C857C6 /* en */, ); name = MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECE175FB2E900C857C6 /* en */, ); name = DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FED1175FB2E900C857C6 /* en */, ); name = DetailViewController_iPad.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14E3FED3175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 14E3FED4175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 14E3FED6175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "io.qbs.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14E3FED7175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "io.qbs.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED3175FB2E900C857C6 /* Debug */, 14E3FED4175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED6175FB2E900C857C6 /* Debug */, 14E3FED7175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14E3FE9E175FB2E800C857C6 /* Project object */; } qbs-src-3.3.1/examples/cocoa-touch-application/cocoa-touch-application.qbs0000644000175100017510000001050315232633614026241 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { Depends { name: "xcode"; required: false } Depends { name: "ib" } condition: qbs.hostOS.contains("macos") && xcode.present && qbs.targetPlatform.contains("ios") name: "Cocoa Touch Application" install: true bundle.identifierPrefix: "io.qbs" bundle.infoPlist: ({"UILaunchStoryboardName": "LaunchScreen"}) cpp.useObjcPrecompiledHeader: true cpp.minimumIosVersion: "9.0" cpp.automaticReferenceCounting: true cpp.frameworks: [ "UIKit", "Foundation", "CoreGraphics" ] // sample code signing settings: // codesign.enableCodeSigning: true // codesign.provisioningProfile: "my provisioning profile name" // codesign.signingIdentity: "Apple Development: My Team Name" Group { prefix: "CocoaTouchApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaTouchApplication-Info.plist", "DetailViewController.h", "DetailViewController.m", "MasterViewController.h", "MasterViewController.m", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaTouchApplication/en.lproj/" files: [ "DetailViewController_iPad.xib", "DetailViewController_iPhone.xib", "MasterViewController_iPad.xib", "MasterViewController_iPhone.xib" ] } Group { id: bundle_resources files: [ "CocoaTouchApplication/LaunchScreen.storyboard", "CocoaTouchApplication/en.lproj/InfoPlist.strings" ] } bundle.resources: bundle_resources.files Group { name: "Xcode Project" files: [ "CocoaTouchApplication.xcodeproj/project.pbxproj" ] } Group { files: ["CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"] fileTags: ["objc_pch_src"] } } qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/0000755000175100017510000000000015232633614025241 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/0000755000175100017510000000000015232633614026770 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/MasterViewController_iPhone.xibqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/MasterViewController_i0000644000175100017510000002003515232633614033355 0ustar runnerrunner 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 {{0, 20}, {320, 548}} 3 MQA YES IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBCocoaTouchFramework YES 3 YES 1919 ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/DetailViewController_iPad.xibqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/DetailViewController_i0000644000175100017510000003170115232633614033326 0ustar runnerrunner 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 298 {{20, 495}, {728, 18}} 3 MQA YES NO IBIPadFramework 1 10 Detail view content goes here 1 MCAwIDAAA 1 1 4 Helvetica 14 16 {{0, 20}, {768, 1004}} NO 2 IBIPadFramework view 12 0 -1 File's Owner -2 8 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 81 94 97 98 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 98 0 IBIPadFramework YES 3 YES 1856 qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/InfoPlist.strings0000644000175100017510000000005415232633614032311 0ustar runnerrunner/* Localized versions of Info.plist keys */ ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/DetailViewController_iPhone.xibqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/DetailViewController_i0000644000175100017510000003517015232633614033332 0ustar runnerrunner 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 298 {{20, 265}, {280, 18}} 3 MQA YES NO IBCocoaTouchFramework Detail view content goes here 1 MCAwIDAAA darkTextColor 1 10 1 1 4 Helvetica 14 16 {{0, 20}, {320, 548}} 3 MQA 2 IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework view 3 detailDescriptionLabel 6 0 1 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 -1 File's Owner -2 4 7 9 11 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 0 IBCocoaTouchFramework YES 3 YES 1919 ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/MasterViewController_iPad.xibqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/MasterViewController_i0000644000175100017510000002063415232633614033362 0ustar runnerrunner 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 {{0, 20}, {320, 832}} 3 MQA YES 2 IBUISplitViewMasterSimulatedSizeMetrics YES {320, 852} {320, 768} IBIPadFramework Master IBUISplitViewController IBUISplitViewControllerContentSizeLocation IBUISplitViewControllerContentSizeLocationMaster IBIPadFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBIPadFramework YES 3 YES 1856 qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.h0000644000175100017510000000542315232633614031517 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface DetailViewController : UIViewController { id _detailItem; UILabel *_detailDescriptionLabel; UIPopoverController *_masterPopoverController; } @property (nonatomic, retain) id detailItem; @property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel; @end ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/CocoaTouchApplication-Prefix.pchqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/CocoaTouchApplication-Prefix.pc0000644000175100017510000000331315232633614033233 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #ifndef __IPHONE_4_0 #warning "This project uses features only available in iOS SDK 4.0 and later." #endif #ifdef __OBJC__ #import #import #endif qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.m0000644000175100017510000001212715232633614027575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" #import "MasterViewController.h" #import "DetailViewController.h" @implementation AppDelegate @synthesize window = _window; @synthesize navigationController = _navigationController; @synthesize splitViewController = _splitViewController; - (BOOL)application:(UIApplication *) __unused application didFinishLaunchingWithOptions:(NSDictionary *) __unused launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:@"MasterViewController_iPhone" bundle:nil]; self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; self.window.rootViewController = self.navigationController; } else { MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:@"MasterViewController_iPad" bundle:nil]; UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController_iPad" bundle:nil]; UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController]; masterViewController.detailViewController = detailViewController; self.splitViewController = [[UISplitViewController alloc] init]; self.splitViewController.delegate = detailViewController; self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil]; self.window.rootViewController = self.splitViewController; } [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *) __unused application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *) __unused application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *) __unused application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *) __unused application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *) __unused application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.m0000644000175100017510000001354015232633614031554 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "MasterViewController.h" #import "DetailViewController.h" @implementation MasterViewController @synthesize detailViewController = _detailViewController; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { self.clearsSelectionOnViewWillAppear = NO; self.preferredContentSize = CGSizeMake(320.0, 600.0); } } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem; UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)]; self.navigationItem.rightBarButtonItem = addButton; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)insertNewObject:(id) __unused sender { if (!_objects) { _objects = [[NSMutableArray alloc] init]; } [_objects insertObject:[NSDate date] atIndex:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView { return 1; } - (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger) __unused section { return _objects.count; } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } } NSDate *object = [_objects objectAtIndex:indexPath.row]; cell.textLabel.text = [object description]; return cell; } - (BOOL)tableView:(UITableView *) __unused tableView canEditRowAtIndexPath:(NSIndexPath *) __unused indexPath { // Return NO if you do not want the specified item to be editable. return YES; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [_objects removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ - (void)tableView:(UITableView *) __unused tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSDate *object = [_objects objectAtIndex:indexPath.row]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { if (!self.detailViewController) { self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController_iPhone" bundle:nil]; } self.detailViewController.detailItem = object; [self.navigationController pushViewController:self.detailViewController animated:YES]; } else { self.detailViewController.detailItem = object; } } @end qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/main.m0000644000175100017510000000327615232633614026353 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #import "AppDelegate.h" int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.m0000644000175100017510000000747415232633614031534 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "DetailViewController.h" @interface DetailViewController () @property (nonatomic, retain) UIPopoverController *masterPopoverController; - (void)configureView; @end @implementation DetailViewController @synthesize detailItem = _detailItem; @synthesize detailDescriptionLabel = _detailDescriptionLabel; @synthesize masterPopoverController = _masterPopoverController; #pragma mark - Managing the detail item - (void)setDetailItem:(id)newDetailItem { if (_detailItem != newDetailItem) { _detailItem = newDetailItem; // Update the view. [self configureView]; } if (self.masterPopoverController != nil) { [self.masterPopoverController dismissPopoverAnimated:YES]; } } - (void)configureView { // Update the user interface for the detail item. if (self.detailItem) { self.detailDescriptionLabel.text = [self.detailItem description]; } } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self configureView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Detail", @"Detail"); } return self; } #pragma mark - Split view - (void)splitViewController:(UISplitViewController *) __unused splitController willHideViewController:(UIViewController *) __unused viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController { barButtonItem.title = NSLocalizedString(@"Master", @"Master"); [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; self.masterPopoverController = popoverController; } - (void)splitViewController:(UISplitViewController *) __unused splitController willShowViewController:(UIViewController *) __unused viewController invalidatingBarButtonItem:(UIBarButtonItem *) __unused barButtonItem { // Called when the view is shown again in the split view, invalidating the button and popover controller. [self.navigationItem setLeftBarButtonItem:nil animated:YES]; self.masterPopoverController = nil; } @end qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/LaunchScreen.storyboard0000644000175100017510000001072415232633614031731 0ustar runnerrunner ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/CocoaTouchApplication-Info.plistqbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/CocoaTouchApplication-Info.plis0000644000175100017510000000357415232633614033247 0ustar runnerrunner CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.h0000644000175100017510000000531415232633614031547 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @class DetailViewController; @interface MasterViewController : UITableViewController { NSMutableArray *_objects; DetailViewController *_detailViewController; } @property (nonatomic, retain) DetailViewController *detailViewController; @end qbs-src-3.3.1/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.h0000644000175100017510000000553515232633614027575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface AppDelegate : UIResponder { UIWindow *_window; UINavigationController *_navigationController; UISplitViewController *_splitViewController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) UINavigationController *navigationController; @property (nonatomic, retain) UISplitViewController *splitViewController; @end qbs-src-3.3.1/examples/rpaths/0000755000175100017510000000000015232633614015622 5ustar runnerrunnerqbs-src-3.3.1/examples/rpaths/rpaths.qbs0000644000175100017510000000311515232633614017632 0ustar runnerrunnerimport qbs.FileInfo Project { condition: qbs.targetOS.contains("unix") //! [0] DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "LibraryA" bundle.isBundle: false cpp.sonamePrefix: qbs.targetOS.contains("macos") ? "@rpath" : undefined cpp.rpaths: cpp.rpathOrigin cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" files: [ "objecta.cpp", "objecta.h", ] install: true installDir: "examples/lib" } //! [0] //! [1] DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "LibraryA" } name: "LibraryB" bundle.isBundle: false cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" cpp.sonamePrefix: qbs.targetOS.contains("macos") ? "@rpath" : undefined cpp.rpaths: cpp.rpathOrigin files: [ "objectb.cpp", "objectb.h", ] install: true installDir: "examples/lib" } //! [1] //! [2] CppApplication { Depends { name: "bundle" } Depends { name: "LibraryA" } Depends { name: "LibraryB" } name: "rpaths-app" files: "main.cpp" consoleApplication: true bundle.isBundle: false cpp.rpaths: FileInfo.joinPaths(cpp.rpathOrigin, "..", "lib") cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" install: true installDir: "examples/bin" } //! [2] } qbs-src-3.3.1/examples/rpaths/objectb.cpp0000644000175100017510000000511315232633614017736 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "objectb.h" ObjectB::ObjectB() = default; std::string ObjectB::className() { return "ObjectB"; } const ObjectA &ObjectB::getA() const { return objectA; } qbs-src-3.3.1/examples/rpaths/objecta.cpp0000644000175100017510000000527715232633614017750 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "objecta.h" ObjectA::ObjectA(std::string name) : m_name(std::move(name)) { } std::string ObjectA::className() { return "ObjectA"; } const std::string &ObjectA::name() const { return m_name; } void ObjectA::setName(std::string name) { m_name = std::move(name); } qbs-src-3.3.1/examples/rpaths/main.cpp0000644000175100017510000000533015232633614017253 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "objecta.h" #include "objectb.h" #include int main(int argc, char *argv[]) { (void)argc; (void)argv; std::cout << ObjectA::className() << std::endl; std::cout << ObjectB::className() << std::endl; ObjectB b; std::cout << b.getA().name() << std::endl; return 0; } qbs-src-3.3.1/examples/rpaths/objecta.h0000644000175100017510000000527515232633614017413 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECTA_H #define OBJECTA_H #include class ObjectA { public: explicit ObjectA(std::string name); static std::string className(); const std::string &name() const; void setName(std::string name); private: std::string m_name; }; #endif // OBJECTA_H qbs-src-3.3.1/examples/rpaths/objectb.h0000644000175100017510000000522415232633614017406 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECTB_H #define OBJECTB_H #include #include "objecta.h" class ObjectB { public: ObjectB(); static std::string className(); const ObjectA &getA() const; private: ObjectA objectA{"A"}; }; #endif // OBJECTB_H qbs-src-3.3.1/examples/grpc/0000755000175100017510000000000015232633614015254 5ustar runnerrunnerqbs-src-3.3.1/examples/grpc/server.cpp0000644000175100017510000000707415232633614017276 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif // __GNUC__ #include #include #include #include #include #include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ #include #include #include class Service final : public PP::MyApi::Service { grpc::Status pingPong( grpc::ServerContext* context, const PP::Ping* request, PP::Pong* reply) override { (void)context; reply->set_count(request->count()); return grpc::Status::OK; } }; int main(int, char**) { std::string server_address("0.0.0.0:50051"); Service service; grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); return 0; } qbs-src-3.3.1/examples/grpc/client.cpp0000644000175100017510000000764215232633614017247 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif // __GNUC__ #include #include #include #include #include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ #include #include #include class Client { public: Client(const std::shared_ptr &channel) : m_stub(PP::MyApi::NewStub(channel)) {} int ping(int count) { PP::Ping request; request.set_count(count); PP::Pong reply; grpc::ClientContext context; const auto status = m_stub->pingPong(&context, request, &reply); if (status.ok()) { return reply.count(); } else { throw std::runtime_error("invalid status"); } } private: std::unique_ptr m_stub; }; int main(int, char**) { Client client( grpc::CreateCustomChannel( "localhost:50051", grpc::InsecureChannelCredentials(), grpc::ChannelArguments())); for (int i = 0; i < 1000; ++i) { std::cout << "Sending ping " << i << "... "; int result = client.ping(i); if (result != i) { std::cerr << "Invalid pong " << result << " for ping" << i << std::endl; continue; } std::cout << "got pong " << result << std::endl; } return 0; } qbs-src-3.3.1/examples/grpc/ping-pong-grpc.proto0000644000175100017510000000025215232633614021167 0ustar runnerrunnersyntax = "proto3"; package PP; message Ping { int32 count = 1; } message Pong { int32 count = 1; } service MyApi { rpc pingPong(Ping) returns (Pong) {} } qbs-src-3.3.1/examples/grpc/grpc.qbs0000644000175100017510000000561615232633614016726 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities Project { condition: Utilities.versionCompare(qbs.version, "1.14") >= 0 qbsModuleProviders: "qbspkgconfig" Application { Depends { name: "cpp" } Depends { name: "protobuf.cpp"; required: false } condition: protobuf.cpp.present && qbs.targetPlatform === qbs.hostPlatform protobuf.cpp.useGrpc: true consoleApplication: true cpp.cxxLanguageVersion: "c++17" cpp.minimumMacosVersion: "10.15" name: "client" files: "client.cpp" Properties { condition: qbs.toolchain.contains("gcc") cpp.cxxFlags: "-Wno-deprecated-declarations" } Group { files: "ping-pong-grpc.proto" fileTags: "protobuf.grpc" } } Application { Depends { name: "cpp" } Depends { name: "protobuf.cpp"; required: false } condition: protobuf.cpp.present && qbs.targetPlatform === qbs.hostPlatform protobuf.cpp.useGrpc: true consoleApplication: true cpp.cxxLanguageVersion: "c++17" cpp.minimumMacosVersion: "10.15" name: "server" files: "server.cpp" Properties { condition: qbs.toolchain.contains("gcc") cpp.cxxFlags: "-Wno-deprecated-declarations" } Group { files: "ping-pong-grpc.proto" fileTags: "protobuf.grpc" } } } qbs-src-3.3.1/examples/install-bundle/0000755000175100017510000000000015232633614017236 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/MainMenu.xib0000644000175100017510000014072115232633614021460 0ustar runnerrunner Default Left to Right Right to Left Default Left to Right Right to Left qbs-src-3.3.1/examples/install-bundle/coreutils.h0000644000175100017510000000470215232633614021423 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef _WIN32 __declspec(dllexport) #endif int foo(); qbs-src-3.3.1/examples/install-bundle/coreutils.cpp0000644000175100017510000000470115232633614021755 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" int foo() { return 42; } qbs-src-3.3.1/examples/install-bundle/main.cpp0000644000175100017510000000507515232633614020675 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.show(); return app.exec(); } qbs-src-3.3.1/examples/install-bundle/white.iconset/0000755000175100017510000000000015232633614022021 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/white.iconset/icon_16x16@2x.png0000644000175100017510000000123115232633614024673 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/examples/install-bundle/white.iconset/icon_16x16.png0000644000175100017510000000121115232633614024317 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/examples/install-bundle/Storyboard.storyboard0000644000175100017510000000530415232633614023502 0ustar runnerrunner qbs-src-3.3.1/examples/install-bundle/assetcatalog1.xcassets/0000755000175100017510000000000015232633614023625 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/0000755000175100017510000000000015232633614026543 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.png0000644000175100017510000000123115232633614031415 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16.png0000644000175100017510000000121115232633614031041 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/Contents.json0000644000175100017510000000053315232633614031234 0ustar runnerrunner{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-3.3.1/examples/install-bundle/install-bundle.qbs0000644000175100017510000000351615232633614022667 0ustar runnerrunnerimport qbs.FileInfo Project { CppApplication { Depends { name: "bundle" } Depends { name: "windowutils" } Depends { name: "ib"; condition: qbs.targetOS.contains("darwin") } Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } condition: (qbs.targetOS.contains("macos") || qbs.targetOS.contains("linux") || qbs.targetOS.contains("windows")) && !Qt.core.staticBuild name: "window" property bool isBundle: bundle.isBundle targetName: isBundle ? "Window" : "window" files: [ "main.cpp", "assetcatalog1.xcassets", "assetcatalog2.xcassets", "white.iconset", "MainMenu.xib", "Storyboard.storyboard" ] cpp.minimumMacosVersion: "10.10" Group { fileTagsFilter: qbs.targetOS.contains("darwin") && isBundle ? ["bundle.content"] : ["application"] qbs.install: true qbs.installDir: isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") qbs.installSourceBase: product.buildDirectory } } DynamicLibrary { Depends { name: "bundle" } Depends { name: "cpp" } name: "windowutils" property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle targetName: isBundle ? "WindowUtils" : "windowutils" files: ["coreutils.cpp", "coreutils.h"] Group { fileTagsFilter: isBundle ? ["bundle.content"] : ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_import"] qbs.install: true qbs.installDir: isBundle ? "Library/Frameworks" : (qbs.targetOS.contains("windows") ? "" : "lib") qbs.installSourceBase: product.buildDirectory } } } qbs-src-3.3.1/examples/install-bundle/assetcatalog2.xcassets/0000755000175100017510000000000015232633614023626 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/0000755000175100017510000000000015232633614026544 5ustar runnerrunnerqbs-src-3.3.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.png0000644000175100017510000000123115232633614031416 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16.png0000644000175100017510000000121115232633614031042 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/Contents.json0000644000175100017510000000053315232633614031235 0ustar runnerrunner{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-3.3.1/examples/app-and-lib/0000755000175100017510000000000015232633614016405 5ustar runnerrunnerqbs-src-3.3.1/examples/app-and-lib/app-and-lib.qbs0000644000175100017510000000473615232633614021212 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { references: [ "app/app.qbs", "lib/lib.qbs" ] } qbs-src-3.3.1/examples/app-and-lib/lib/0000755000175100017510000000000015232633614017153 5ustar runnerrunnerqbs-src-3.3.1/examples/app-and-lib/lib/lib.cpp0000644000175100017510000000503615232633614020431 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif int bla() { std::puts("Hello World!"); return 2; } qbs-src-3.3.1/examples/app-and-lib/lib/lib.h0000644000175100017510000000470515232633614020100 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB_H #define LIB_H int bla(); #endif // LIB_H qbs-src-3.3.1/examples/app-and-lib/lib/lib.qbs0000644000175100017510000000523115232633614020431 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ StaticLibrary { name: "mylib" files: [ "lib.cpp", "lib.h", ] Depends { name: 'cpp' } cpp.defines: ['CRUCIAL_DEFINE'] Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } } qbs-src-3.3.1/examples/app-and-lib/app/0000755000175100017510000000000015232633614017165 5ustar runnerrunnerqbs-src-3.3.1/examples/app-and-lib/app/app.qbs0000644000175100017510000000504115232633614020454 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Application { consoleApplication: true files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "mylib" } install: true } qbs-src-3.3.1/examples/app-and-lib/app/main.cpp0000644000175100017510000000500615232633614020616 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { std::puts("Now calling a function from mylib:"); return bla(); } qbs-src-3.3.1/examples/capnproto/0000755000175100017510000000000015232633614016326 5ustar runnerrunnerqbs-src-3.3.1/examples/capnproto/addressbook_cpp/0000755000175100017510000000000015232633614021470 5ustar runnerrunnerqbs-src-3.3.1/examples/capnproto/addressbook_cpp/addressbook_cpp.qbs0000644000175100017510000000044615232633614025345 0ustar runnerrunnerCppApplication { Depends { name: "capnproto.cpp"; required: false } condition: capnproto.cpp.present && qbs.targetPlatform === qbs.hostPlatform consoleApplication: true cpp.minimumMacosVersion: "10.8" files: [ "addressbook.capnp", "addressbook.cpp" ] } qbs-src-3.3.1/examples/capnproto/addressbook_cpp/addressbook.cpp0000644000175100017510000002271115232633614024477 0ustar runnerrunner// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // 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. // This sample code appears in the documentation for the C++ implementation. // // If Cap'n Proto is installed, build the sample like: // capnp compile -oc++ addressbook.capnp // c++ -std=c++14 -Wall addressbook.c++ addressbook.capnp.c++ `pkg-config --cflags --libs capnp` -o addressbook // // If Cap'n Proto is not installed, but the source is located at $SRC and has been // compiled in $BUILD (often both are simply ".." from here), you can do: // $BUILD/capnp compile -I$SRC/src -o$BUILD/capnpc-c++ addressbook.capnp // c++ -std=c++14 -Wall addressbook.c++ addressbook.capnp.c++ -I$SRC/src -L$BUILD/.libs -lcapnp -lkj -o addressbook // // Run like: // ./addressbook write | ./addressbook read // Use "dwrite" and "dread" to use dynamic code instead. // TODO(test): Needs cleanup. #include "addressbook.capnp.h" #include #include #include using addressbook::Person; using addressbook::AddressBook; void writeAddressBook(int fd) { ::capnp::MallocMessageBuilder message; AddressBook::Builder addressBook = message.initRoot(); ::capnp::List::Builder people = addressBook.initPeople(2); Person::Builder alice = people[0]; alice.setId(123); alice.setName("Alice"); alice.setEmail("alice@example.com"); // Type shown for explanation purposes; normally you'd use auto. ::capnp::List::Builder alicePhones = alice.initPhones(1); alicePhones[0].setNumber("555-1212"); alicePhones[0].setType(Person::PhoneNumber::Type::MOBILE); alice.getEmployment().setSchool("MIT"); Person::Builder bob = people[1]; bob.setId(456); bob.setName("Bob"); bob.setEmail("bob@example.com"); auto bobPhones = bob.initPhones(2); bobPhones[0].setNumber("555-4567"); bobPhones[0].setType(Person::PhoneNumber::Type::HOME); bobPhones[1].setNumber("555-7654"); bobPhones[1].setType(Person::PhoneNumber::Type::WORK); bob.getEmployment().setUnemployed(); writePackedMessageToFd(fd, message); } void printAddressBook(int fd) { ::capnp::PackedFdMessageReader message(fd); AddressBook::Reader addressBook = message.getRoot(); for (Person::Reader person : addressBook.getPeople()) { std::cout << person.getName().cStr() << ": " << person.getEmail().cStr() << std::endl; for (Person::PhoneNumber::Reader phone: person.getPhones()) { const char* typeName = "UNKNOWN"; switch (phone.getType()) { case Person::PhoneNumber::Type::MOBILE: typeName = "mobile"; break; case Person::PhoneNumber::Type::HOME: typeName = "home"; break; case Person::PhoneNumber::Type::WORK: typeName = "work"; break; } std::cout << " " << typeName << " phone: " << phone.getNumber().cStr() << std::endl; } Person::Employment::Reader employment = person.getEmployment(); switch (employment.which()) { case Person::Employment::UNEMPLOYED: std::cout << " unemployed" << std::endl; break; case Person::Employment::EMPLOYER: std::cout << " employer: " << employment.getEmployer().cStr() << std::endl; break; case Person::Employment::SCHOOL: std::cout << " student at: " << employment.getSchool().cStr() << std::endl; break; case Person::Employment::SELF_EMPLOYED: std::cout << " self-employed" << std::endl; break; } } } #if !CAPNP_LITE #include "addressbook.capnp.h" #include #include #include #include #include using ::capnp::DynamicValue; using ::capnp::DynamicStruct; using ::capnp::DynamicEnum; using ::capnp::DynamicList; using ::capnp::List; using ::capnp::Schema; using ::capnp::StructSchema; using ::capnp::EnumSchema; using ::capnp::Void; using ::capnp::Text; using ::capnp::MallocMessageBuilder; using ::capnp::PackedFdMessageReader; void dynamicWriteAddressBook(int fd, StructSchema schema) { // Write a message using the dynamic API to set each // field by text name. This isn't something you'd // normally want to do; it's just for illustration. MallocMessageBuilder message; // Types shown for explanation purposes; normally you'd // use auto. DynamicStruct::Builder addressBook = message.initRoot(schema); DynamicList::Builder people = addressBook.init("people", 2).as(); DynamicStruct::Builder alice = people[0].as(); alice.set("id", 123); alice.set("name", "Alice"); alice.set("email", "alice@example.com"); auto alicePhones = alice.init("phones", 1).as(); auto phone0 = alicePhones[0].as(); phone0.set("number", "555-1212"); phone0.set("type", "mobile"); alice.get("employment").as() .set("school", "MIT"); auto bob = people[1].as(); bob.set("id", 456); bob.set("name", "Bob"); bob.set("email", "bob@example.com"); // Some magic: We can convert a dynamic sub-value back to // the native type with as()! List::Builder bobPhones = bob.init("phones", 2).as>(); bobPhones[0].setNumber("555-4567"); bobPhones[0].setType(Person::PhoneNumber::Type::HOME); bobPhones[1].setNumber("555-7654"); bobPhones[1].setType(Person::PhoneNumber::Type::WORK); bob.get("employment").as() .set("unemployed", ::capnp::VOID); writePackedMessageToFd(fd, message); } void dynamicPrintValue(DynamicValue::Reader value) { // Print an arbitrary message via the dynamic API by // iterating over the schema. Look at the handling // of STRUCT in particular. switch (value.getType()) { case DynamicValue::VOID: std::cout << ""; break; case DynamicValue::BOOL: std::cout << (value.as() ? "true" : "false"); break; case DynamicValue::INT: std::cout << value.as(); break; case DynamicValue::UINT: std::cout << value.as(); break; case DynamicValue::FLOAT: std::cout << value.as(); break; case DynamicValue::TEXT: std::cout << '\"' << value.as().cStr() << '\"'; break; case DynamicValue::LIST: { std::cout << "["; bool first = true; for (auto element: value.as()) { if (first) { first = false; } else { std::cout << ", "; } dynamicPrintValue(element); } std::cout << "]"; break; } case DynamicValue::ENUM: { auto enumValue = value.as(); KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) { std::cout << enumerant->getProto().getName().cStr(); } else { // Unknown enum value; output raw number. std::cout << enumValue.getRaw(); } break; } case DynamicValue::STRUCT: { std::cout << "("; auto structValue = value.as(); bool first = true; for (auto field: structValue.getSchema().getFields()) { if (!structValue.has(field)) continue; if (first) { first = false; } else { std::cout << ", "; } std::cout << field.getProto().getName().cStr() << " = "; dynamicPrintValue(structValue.get(field)); } std::cout << ")"; break; } default: // There are other types, we aren't handling them. std::cout << "?"; break; } } void dynamicPrintMessage(int fd, StructSchema schema) { PackedFdMessageReader message(fd); dynamicPrintValue(message.getRoot(schema)); std::cout << std::endl; } #endif // !CAPNP_LITE int main(int argc, char* argv[]) { if (argc != 2) { std::cerr << "Missing arg." << std::endl; return 1; } else if (strcmp(argv[1], "write") == 0) { writeAddressBook(1); } else if (strcmp(argv[1], "read") == 0) { printAddressBook(0); #if !CAPNP_LITE } else if (strcmp(argv[1], "dwrite") == 0) { StructSchema schema = Schema::from(); dynamicWriteAddressBook(1, schema); } else if (strcmp(argv[1], "dread") == 0) { StructSchema schema = Schema::from(); dynamicPrintMessage(0, schema); #endif } else { std::cerr << "Invalid arg: " << argv[1] << std::endl; return 1; } return 0; } qbs-src-3.3.1/examples/capnproto/addressbook_cpp/addressbook.capnp0000644000175100017510000000330015232633614025007 0ustar runnerrunner# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # 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. @0x9eb32e19f86ee174; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("addressbook"); struct Person { id @0 :UInt32; name @1 :Text; email @2 :Text; phones @3 :List(PhoneNumber); struct PhoneNumber { number @0 :Text; type @1 :Type; enum Type { mobile @0; home @1; work @2; } } employment :union { unemployed @4 :Void; employer @5 :Text; school @6 :Text; selfEmployed @7 :Void; # We assume that a person is only one of these. } } struct AddressBook { people @0 :List(Person); } qbs-src-3.3.1/examples/capnproto/calculator_cpp/0000755000175100017510000000000015232633614021321 5ustar runnerrunnerqbs-src-3.3.1/examples/capnproto/calculator_cpp/calculator_cpp.qbs0000644000175100017510000000134515232633614025026 0ustar runnerrunnerimport qbs.Host Project { CppApplication { Depends { name: "capnproto.cpp"; required: false } name: "server" condition: capnproto.cpp.present && qbs.targetPlatform === Host.platform() consoleApplication: true capnproto.cpp.useRpc: true files: [ "calculator.capnp", "calculator-server.cpp" ] } CppApplication { Depends { name: "capnproto.cpp"; required: false } name: "client" condition: capnproto.cpp.present && qbs.targetPlatform === Host.platform() consoleApplication: true capnproto.cpp.useRpc: true files: [ "calculator.capnp", "calculator-client.cpp" ] } } qbs-src-3.3.1/examples/capnproto/calculator_cpp/calculator-server.cpp0000644000175100017510000001657115232633614025474 0ustar runnerrunner// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // 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. #include "calculator.capnp.h" #include #include #include #include typedef unsigned int uint; kj::Promise readValue(Calculator::Value::Client value) { // Helper function to asynchronously call read() on a Calculator::Value and // return a promise for the result. (In the future, the generated code might // include something like this automatically.) return value.readRequest().send() .then([](capnp::Response result) { return result.getValue(); }); } kj::Promise evaluateImpl( Calculator::Expression::Reader expression, capnp::List::Reader params = capnp::List::Reader()) { // Implementation of CalculatorImpl::evaluate(), also shared by // FunctionImpl::call(). In the latter case, `params` are the parameter // values passed to the function; in the former case, `params` is just an // empty list. switch (expression.which()) { case Calculator::Expression::LITERAL: return expression.getLiteral(); case Calculator::Expression::PREVIOUS_RESULT: return readValue(expression.getPreviousResult()); case Calculator::Expression::PARAMETER: { KJ_REQUIRE(expression.getParameter() < params.size(), "Parameter index out-of-range."); return params[expression.getParameter()]; } case Calculator::Expression::CALL: { auto call = expression.getCall(); auto func = call.getFunction(); // Evaluate each parameter. kj::Array> paramPromises = KJ_MAP(param, call.getParams()) { return evaluateImpl(param, params); }; // Join the array of promises into a promise for an array. kj::Promise> joinedParams = kj::joinPromises(kj::mv(paramPromises)); // When the parameters are complete, call the function. return joinedParams.then([KJ_CPCAP(func)](kj::Array&& paramValues) mutable { auto request = func.callRequest(); request.setParams(paramValues); return request.send().then( [](capnp::Response&& result) { return result.getValue(); }); }); } default: // Throw an exception. KJ_FAIL_REQUIRE("Unknown expression type."); } } class ValueImpl final: public Calculator::Value::Server { // Simple implementation of the Calculator.Value Cap'n Proto interface. public: ValueImpl(double value): value(value) {} kj::Promise read(ReadContext context) { context.getResults().setValue(value); return kj::READY_NOW; } private: double value; }; class FunctionImpl final: public Calculator::Function::Server { // Implementation of the Calculator.Function Cap'n Proto interface, where the // function is defined by a Calculator.Expression. public: FunctionImpl(uint paramCount, Calculator::Expression::Reader body) : paramCount(paramCount) { this->body.setRoot(body); } kj::Promise call(CallContext context) { auto params = context.getParams().getParams(); KJ_REQUIRE(params.size() == paramCount, "Wrong number of parameters."); return evaluateImpl(body.getRoot(), params) .then([KJ_CPCAP(context)](double value) mutable { context.getResults().setValue(value); }); } private: uint paramCount; // The function's arity. capnp::MallocMessageBuilder body; // Stores a permanent copy of the function body. }; class OperatorImpl final: public Calculator::Function::Server { // Implementation of the Calculator.Function Cap'n Proto interface, wrapping // basic binary arithmetic operators. public: OperatorImpl(Calculator::Operator op): op(op) {} kj::Promise call(CallContext context) { auto params = context.getParams().getParams(); KJ_REQUIRE(params.size() == 2, "Wrong number of parameters."); double result; switch (op) { case Calculator::Operator::ADD: result = params[0] + params[1]; break; case Calculator::Operator::SUBTRACT:result = params[0] - params[1]; break; case Calculator::Operator::MULTIPLY:result = params[0] * params[1]; break; case Calculator::Operator::DIVIDE: result = params[0] / params[1]; break; default: KJ_FAIL_REQUIRE("Unknown operator."); } context.getResults().setValue(result); return kj::READY_NOW; } private: Calculator::Operator op; }; class CalculatorImpl final: public Calculator::Server { // Implementation of the Calculator Cap'n Proto interface. public: kj::Promise evaluate(EvaluateContext context) override { return evaluateImpl(context.getParams().getExpression()) .then([KJ_CPCAP(context)](double value) mutable { context.getResults().setValue(kj::heap(value)); }); } kj::Promise defFunction(DefFunctionContext context) override { auto params = context.getParams(); context.getResults().setFunc(kj::heap( params.getParamCount(), params.getBody())); return kj::READY_NOW; } kj::Promise getOperator(GetOperatorContext context) override { context.getResults().setFunc(kj::heap( context.getParams().getOp())); return kj::READY_NOW; } }; int main(int argc, const char* argv[]) { if (argc != 2) { std::cerr << "usage: " << argv[0] << " ADDRESS[:PORT]\n" "Runs the server bound to the given address/port.\n" "ADDRESS may be '*' to bind to all local addresses.\n" ":PORT may be omitted to choose a port automatically." << std::endl; return 1; } // Set up a server. capnp::EzRpcServer server(kj::heap(), argv[1]); // Write the port number to stdout, in case it was chosen automatically. auto& waitScope = server.getWaitScope(); uint port = server.getPort().wait(waitScope); if (port == 0) { // The address format "unix:/path/to/socket" opens a unix domain socket, // in which case the port will be zero. std::cout << "Listening on Unix socket..." << std::endl; } else { std::cout << "Listening on port " << port << "..." << std::endl; } // Run forever, accepting connections and handling requests. kj::NEVER_DONE.wait(waitScope); } qbs-src-3.3.1/examples/capnproto/calculator_cpp/calculator.capnp0000644000175100017510000001105315232633614024475 0ustar runnerrunner# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # 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. @0x85150b117366d14b; interface Calculator { # A "simple" mathematical calculator, callable via RPC. # # But, to show off Cap'n Proto, we add some twists: # # - You can use the result from one call as the input to the next # without a network round trip. To accomplish this, evaluate() # returns a `Value` object wrapping the actual numeric value. # This object may be used in a subsequent expression. With # promise pipelining, the Value can actually be used before # the evaluate() call that creates it returns! # # - You can define new functions, and then call them. This again # shows off pipelining, but it also gives the client the # opportunity to define a function on the client side and have # the server call back to it. # # - The basic arithmetic operators are exposed as Functions, and # you have to call getOperator() to obtain them from the server. # This again demonstrates pipelining -- using getOperator() to # get each operator and then using them in evaluate() still # only takes one network round trip. evaluate @0 (expression :Expression) -> (value :Value); # Evaluate the given expression and return the result. The # result is returned wrapped in a Value interface so that you # may pass it back to the server in a pipelined request. To # actually get the numeric value, you must call read() on the # Value -- but again, this can be pipelined so that it incurs # no additional latency. struct Expression { # A numeric expression. union { literal @0 :Float64; # A literal numeric value. previousResult @1 :Value; # A value that was (or, will be) returned by a previous # evaluate(). parameter @2 :UInt32; # A parameter to the function (only valid in function bodies; # see defFunction). call :group { # Call a function on a list of parameters. function @3 :Function; params @4 :List(Expression); } } } interface Value { # Wraps a numeric value in an RPC object. This allows the value # to be used in subsequent evaluate() requests without the client # waiting for the evaluate() that returns the Value to finish. read @0 () -> (value :Float64); # Read back the raw numeric value. } defFunction @1 (paramCount :Int32, body :Expression) -> (func :Function); # Define a function that takes `paramCount` parameters and returns the # evaluation of `body` after substituting these parameters. interface Function { # An algebraic function. Can be called directly, or can be used inside # an Expression. # # A client can create a Function that runs on the server side using # `defFunction()` or `getOperator()`. Alternatively, a client can # implement a Function on the client side and the server will call back # to it. However, a function defined on the client side will require a # network round trip whenever the server needs to call it, whereas # functions defined on the server and then passed back to it are called # locally. call @0 (params :List(Float64)) -> (value :Float64); # Call the function on the given parameters. } getOperator @2 (op :Operator) -> (func :Function); # Get a Function representing an arithmetic operator, which can then be # used in Expressions. enum Operator { add @0; subtract @1; multiply @2; divide @3; } } qbs-src-3.3.1/examples/capnproto/calculator_cpp/calculator-client.cpp0000644000175100017510000003131015232633614025430 0ustar runnerrunner// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // 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. #include "calculator.capnp.h" #include #include #include #include class PowerFunction final: public Calculator::Function::Server { // An implementation of the Function interface wrapping pow(). Note that // we're implementing this on the client side and will pass a reference to // the server. The server will then be able to make calls back to the client. public: kj::Promise call(CallContext context) { auto params = context.getParams().getParams(); KJ_REQUIRE(params.size() == 2, "Wrong number of parameters."); context.getResults().setValue(pow(params[0], params[1])); return kj::READY_NOW; } }; int main(int argc, const char* argv[]) { if (argc != 2) { std::cerr << "usage: " << argv[0] << " HOST:PORT\n" "Connects to the Calculator server at the given address and " "does some RPCs." << std::endl; return 1; } capnp::EzRpcClient client(argv[1]); Calculator::Client calculator = client.getMain(); // Keep an eye on `waitScope`. Whenever you see it used is a place where we // stop and wait for the server to respond. If a line of code does not use // `waitScope`, then it does not block! auto& waitScope = client.getWaitScope(); { // Make a request that just evaluates the literal value 123. // // What's interesting here is that evaluate() returns a "Value", which is // another interface and therefore points back to an object living on the // server. We then have to call read() on that object to read it. // However, even though we are making two RPC's, this block executes in // *one* network round trip because of promise pipelining: we do not wait // for the first call to complete before we send the second call to the // server. std::cout << "Evaluating a literal... "; std::cout.flush(); // Set up the request. auto request = calculator.evaluateRequest(); request.getExpression().setLiteral(123); // Send it, which returns a promise for the result (without blocking). auto evalPromise = request.send(); // Using the promise, create a pipelined request to call read() on the // returned object, and then send that. auto readPromise = evalPromise.getValue().readRequest().send(); // Now that we've sent all the requests, wait for the response. Until this // point, we haven't waited at all! auto response = readPromise.wait(waitScope); KJ_ASSERT(response.getValue() == 123); std::cout << "PASS" << std::endl; } { // Make a request to evaluate 123 + 45 - 67. // // The Calculator interface requires that we first call getOperator() to // get the addition and subtraction functions, then call evaluate() to use // them. But, once again, we can get both functions, call evaluate(), and // then read() the result -- four RPCs -- in the time of *one* network // round trip, because of promise pipelining. std::cout << "Using add and subtract... "; std::cout.flush(); Calculator::Function::Client add = nullptr; Calculator::Function::Client subtract = nullptr; { // Get the "add" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::ADD); add = request.send().getFunc(); } { // Get the "subtract" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::SUBTRACT); subtract = request.send().getFunc(); } // Build the request to evaluate 123 + 45 - 67. auto request = calculator.evaluateRequest(); auto subtractCall = request.getExpression().initCall(); subtractCall.setFunction(subtract); auto subtractParams = subtractCall.initParams(2); subtractParams[1].setLiteral(67); auto addCall = subtractParams[0].initCall(); addCall.setFunction(add); auto addParams = addCall.initParams(2); addParams[0].setLiteral(123); addParams[1].setLiteral(45); // Send the evaluate() request, read() the result, and wait for read() to // finish. auto evalPromise = request.send(); auto readPromise = evalPromise.getValue().readRequest().send(); auto response = readPromise.wait(waitScope); KJ_ASSERT(response.getValue() == 101); std::cout << "PASS" << std::endl; } { // Make a request to evaluate 4 * 6, then use the result in two more // requests that add 3 and 5. // // Since evaluate() returns its result wrapped in a `Value`, we can pass // that `Value` back to the server in subsequent requests before the first // `evaluate()` has actually returned. Thus, this example again does only // one network round trip. std::cout << "Pipelining eval() calls... "; std::cout.flush(); Calculator::Function::Client add = nullptr; Calculator::Function::Client multiply = nullptr; { // Get the "add" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::ADD); add = request.send().getFunc(); } { // Get the "multiply" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::MULTIPLY); multiply = request.send().getFunc(); } // Build the request to evaluate 4 * 6 auto request = calculator.evaluateRequest(); auto multiplyCall = request.getExpression().initCall(); multiplyCall.setFunction(multiply); auto multiplyParams = multiplyCall.initParams(2); multiplyParams[0].setLiteral(4); multiplyParams[1].setLiteral(6); auto multiplyResult = request.send().getValue(); // Use the result in two calls that add 3 and add 5. auto add3Request = calculator.evaluateRequest(); auto add3Call = add3Request.getExpression().initCall(); add3Call.setFunction(add); auto add3Params = add3Call.initParams(2); add3Params[0].setPreviousResult(multiplyResult); add3Params[1].setLiteral(3); auto add3Promise = add3Request.send().getValue().readRequest().send(); auto add5Request = calculator.evaluateRequest(); auto add5Call = add5Request.getExpression().initCall(); add5Call.setFunction(add); auto add5Params = add5Call.initParams(2); add5Params[0].setPreviousResult(multiplyResult); add5Params[1].setLiteral(5); auto add5Promise = add5Request.send().getValue().readRequest().send(); // Now wait for the results. KJ_ASSERT(add3Promise.wait(waitScope).getValue() == 27); KJ_ASSERT(add5Promise.wait(waitScope).getValue() == 29); std::cout << "PASS" << std::endl; } { // Our calculator interface supports defining functions. Here we use it // to define two functions and then make calls to them as follows: // // f(x, y) = x * 100 + y // g(x) = f(x, x + 1) * 2; // f(12, 34) // g(21) // // Once again, the whole thing takes only one network round trip. std::cout << "Defining functions... "; std::cout.flush(); Calculator::Function::Client add = nullptr; Calculator::Function::Client multiply = nullptr; Calculator::Function::Client f = nullptr; Calculator::Function::Client g = nullptr; { // Get the "add" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::ADD); add = request.send().getFunc(); } { // Get the "multiply" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::MULTIPLY); multiply = request.send().getFunc(); } { // Define f. auto request = calculator.defFunctionRequest(); request.setParamCount(2); { // Build the function body. auto addCall = request.getBody().initCall(); addCall.setFunction(add); auto addParams = addCall.initParams(2); addParams[1].setParameter(1); // y auto multiplyCall = addParams[0].initCall(); multiplyCall.setFunction(multiply); auto multiplyParams = multiplyCall.initParams(2); multiplyParams[0].setParameter(0); // x multiplyParams[1].setLiteral(100); } f = request.send().getFunc(); } { // Define g. auto request = calculator.defFunctionRequest(); request.setParamCount(1); { // Build the function body. auto multiplyCall = request.getBody().initCall(); multiplyCall.setFunction(multiply); auto multiplyParams = multiplyCall.initParams(2); multiplyParams[1].setLiteral(2); auto fCall = multiplyParams[0].initCall(); fCall.setFunction(f); auto fParams = fCall.initParams(2); fParams[0].setParameter(0); auto addCall = fParams[1].initCall(); addCall.setFunction(add); auto addParams = addCall.initParams(2); addParams[0].setParameter(0); addParams[1].setLiteral(1); } g = request.send().getFunc(); } // OK, we've defined all our functions. Now create our eval requests. // f(12, 34) auto fEvalRequest = calculator.evaluateRequest(); auto fCall = fEvalRequest.initExpression().initCall(); fCall.setFunction(f); auto fParams = fCall.initParams(2); fParams[0].setLiteral(12); fParams[1].setLiteral(34); auto fEvalPromise = fEvalRequest.send().getValue().readRequest().send(); // g(21) auto gEvalRequest = calculator.evaluateRequest(); auto gCall = gEvalRequest.initExpression().initCall(); gCall.setFunction(g); gCall.initParams(1)[0].setLiteral(21); auto gEvalPromise = gEvalRequest.send().getValue().readRequest().send(); // Wait for the results. KJ_ASSERT(fEvalPromise.wait(waitScope).getValue() == 1234); KJ_ASSERT(gEvalPromise.wait(waitScope).getValue() == 4244); std::cout << "PASS" << std::endl; } { // Make a request that will call back to a function defined locally. // // Specifically, we will compute 2^(4 + 5). However, exponent is not // defined by the Calculator server. So, we'll implement the Function // interface locally and pass it to the server for it to use when // evaluating the expression. // // This example requires two network round trips to complete, because the // server calls back to the client once before finishing. In this // particular case, this could potentially be optimized by using a tail // call on the server side -- see CallContext::tailCall(). However, to // keep the example simpler, we haven't implemented this optimization in // the sample server. std::cout << "Using a callback... "; std::cout.flush(); Calculator::Function::Client add = nullptr; { // Get the "add" function from the server. auto request = calculator.getOperatorRequest(); request.setOp(Calculator::Operator::ADD); add = request.send().getFunc(); } // Build the eval request for 2^(4+5). auto request = calculator.evaluateRequest(); auto powCall = request.getExpression().initCall(); powCall.setFunction(kj::heap()); auto powParams = powCall.initParams(2); powParams[0].setLiteral(2); auto addCall = powParams[1].initCall(); addCall.setFunction(add); auto addParams = addCall.initParams(2); addParams[0].setLiteral(4); addParams[1].setLiteral(5); // Send the request and wait. auto response = request.send().getValue().readRequest() .send().wait(waitScope); KJ_ASSERT(response.getValue() == 512); std::cout << "PASS" << std::endl; } return 0; } qbs-src-3.3.1/examples/exporters/0000755000175100017510000000000015232633614016354 5ustar runnerrunnerqbs-src-3.3.1/examples/exporters/exporters.qbs0000644000175100017510000000502115232633614021114 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { references: [ "lib_a/lib_a.qbs", "lib_b/lib_b.qbs" ] qbsSearchPaths: "qbs" } qbs-src-3.3.1/examples/exporters/qbs/0000755000175100017510000000000015232633614017141 5ustar runnerrunnerqbs-src-3.3.1/examples/exporters/qbs/imports/0000755000175100017510000000000015232633614020636 5ustar runnerrunnerqbs-src-3.3.1/examples/exporters/qbs/imports/MyLibrary.qbs0000644000175100017510000000717415232633614023270 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.FileInfo StaticLibrary { Depends { name: 'cpp' } property string headersInstallDir: "include" Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] prefixMapping: [{ prefix: exportingProduct.sourceDirectory, replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) }] } install: true Depends { name: "Exporter.qbs" } Group { fileTagsFilter: "Exporter.qbs.module" qbs.install: install qbs.installDir: FileInfo.joinPaths(installDir, "qbs", "modules", product.name) } Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.versionEntry: "1.0" Group { fileTagsFilter: ["Exporter.pkgconfig.pc"] qbs.install: install qbs.installDir: FileInfo.joinPaths(installDir, "pkgconfig") } Depends { name: "Exporter.cmake" } Group { fileTagsFilter: ["Exporter.cmake.package"] qbs.install: install qbs.installDir: FileInfo.joinPaths(installDir, "cmake", product.name) } Depends { name: 'bundle' } bundle.isBundle: false } qbs-src-3.3.1/examples/exporters/lib_a/0000755000175100017510000000000015232633614017422 5ustar runnerrunnerqbs-src-3.3.1/examples/exporters/lib_a/lib_a.cpp0000644000175100017510000000474215232633614021203 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib_a.h" const char *bla() { return "Hello World!"; } qbs-src-3.3.1/examples/exporters/lib_a/lib_a.qbs0000644000175100017510000000534515232633614021206 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MyLibrary { name: "lib_a" files: ["lib_a.cpp"] Group { name: "API headers" files: ["lib_a.h"] qbs.install: true qbs.installDir: headersInstallDir } Export { Depends { name: "cpp" } cpp.dynamicLibraries: "z" cpp.libraryPaths: "/opt/local/lib" } } qbs-src-3.3.1/examples/exporters/lib_a/lib_a.h0000644000175100017510000000474415232633614020652 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB_A_H #define LIB_A_H const char *bla(); #endif // LIB_A_H qbs-src-3.3.1/examples/exporters/lib_b/0000755000175100017510000000000015232633614017423 5ustar runnerrunnerqbs-src-3.3.1/examples/exporters/lib_b/lib_b.qbs0000644000175100017510000000526615232633614021212 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MyLibrary { Depends { name: "lib_a" } name: "lib_b" files: ["lib_b.cpp"] Group { name: "API headers" files: ["lib_b.h"] qbs.install: true qbs.installDir: headersInstallDir } Export { Depends { name: 'lib_a' } } } qbs-src-3.3.1/examples/exporters/lib_b/lib_b.cpp0000644000175100017510000000501215232633614021174 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib_b.h" #include #include int foo() { std::puts(bla()); return 2; } qbs-src-3.3.1/examples/exporters/lib_b/lib_b.h0000644000175100017510000000473415232633614020653 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB_B_H #define LIB_B_H int foo(); #endif // LIB_B_H qbs-src-3.3.1/examples/pkgconfig-provider/0000755000175100017510000000000015232633614020120 5ustar runnerrunnerqbs-src-3.3.1/examples/pkgconfig-provider/main.c0000644000175100017510000000767515232633614021227 0ustar runnerrunner/**************************************************************************** ** ** MIT License ** Copyright (c) 2017 Aleksander Alekseev ** 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. ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { int res; if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } char* fname = argv[1]; struct stat file_stat; res = stat(fname, &file_stat); if (res == -1) { fprintf(stderr, "stat(...) failed, errno = %d\n", errno); return 1; } size_t temp_file_size = (size_t)file_stat.st_size; if (temp_file_size >= INT_MAX) { fprintf(stderr, "Error: filze_size >= INT_MAX (%d)\n", INT_MAX); return 1; } int file_size = (int)temp_file_size; int buff_size = file_size + 1; void* file_buff = malloc(buff_size); if (file_buff == NULL) { fprintf(stderr, "malloc(buff_size) failed, buff_size = %d\n", file_size); return 1; } int fid = open(fname, O_RDONLY); if (fid == -1) { fprintf(stderr, "open(...) failed, errno = %d\n", errno); free(file_buff); return 1; } if (read(fid, file_buff, file_size) != file_size) { fprintf(stderr, "read(...) failed, errno = %d\n", errno); free(file_buff); close(fid); return 1; } close(fid); uLongf compress_buff_size = compressBound(file_size); void* compress_buff = malloc(compress_buff_size); if (compress_buff == NULL) { fprintf(stderr, "malloc(compress_buff_size) failed, " "compress_buff_size = %lu\n", compress_buff_size); free(file_buff); return 1; } uLongf compressed_size = compress_buff_size; res = compress(compress_buff, &compressed_size, file_buff, file_size); if (res != Z_OK) { fprintf(stderr, "compress(...) failed, res = %d\n", res); free(compress_buff); free(file_buff); return 1; } memset(file_buff, 0, buff_size); uLongf decompressed_size = (uLongf)file_size; res = uncompress(file_buff, &decompressed_size, compress_buff, compressed_size); if (res != Z_OK) { fprintf(stderr, "uncompress(...) failed, res = %d\n", res); free(compress_buff); free(file_buff); return 1; } printf( "%s\n----------------\n" "File size: %d, compress_buff_size: %lu, compressed_size: %lu, " "decompressed_size: %lu\n", (char*)file_buff, file_size, compress_buff_size, compressed_size, decompressed_size); free(compress_buff); free(file_buff); } qbs-src-3.3.1/examples/pkgconfig-provider/pkgconfig-provider.qbs0000644000175100017510000000526115232633614024432 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ //! [0] CppApplication { consoleApplication: true Depends { name: "zlib"; required: false } condition: !qbs.toolchain.includes("emscripten") && zlib.present name: "PkgConfigProviderExample" files: "main.c" qbsModuleProviders: ["qbspkgconfig"] } //! [0] qbs-src-3.3.1/examples/shadereffects/0000755000175100017510000000000015232633614017127 5ustar runnerrunnerqbs-src-3.3.1/examples/shadereffects/shadereffects.qml0000644000175100017510000001567115232633614022462 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick import QtQml.Models import QtQuick.Controls Rectangle { id: root width: 320 height: 480 property color col: "lightsteelblue" gradient: Gradient { GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") } GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") } GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") } GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") } } //! [source] ShaderEffectSource { id: theSource sourceItem: theItem } //! [source] function saturate(x) { return Math.min(Math.max(x, 0), 1) } function sliderToColor(x) { return Qt.rgba(saturate(Math.max(2 - 6 * x, 6 * x - 4)), saturate(Math.min(6 * x, 4 - 6 * x)), saturate(Math.min(6 * x - 2, 6 - 6 * x))) } Grid { anchors.centerIn: parent columns: 2 Item { id: theItem width: 160 height: 160 ListView { anchors.centerIn: parent width: 160 height: 140 clip: true snapMode: ListView.SnapOneItem model: ObjectModel { Text { width: 160 height: 140 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.pixelSize: 118 font.family: "Times" color: "blue" text: "Qt" } Image { width: 160 height: 140 source: "content/qt-logo.png" } Image { width: 160 height: 140 source: "content/face-smile.png" } } } } ShaderEffect { width: 160 height: 160 property variant source: theSource property real amplitude: 0.04 * wobbleSlider.value property real frequency: 20 property real time NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 } //! [fragment] fragmentShader: "content/shaders/wobble.frag.qsb" //! [fragment] Slider { id: wobbleSlider anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.leftMargin: 4 anchors.rightMargin: 4 height: 40 } } ShaderEffect { width: 160 height: 160 property variant source: theSource property variant shadow: ShaderEffectSource { sourceItem: ShaderEffect { width: theItem.width height: theItem.height property variant delta: Qt.size(0.0, 1.0 / height) property variant source: ShaderEffectSource { sourceItem: ShaderEffect { width: theItem.width height: theItem.height property variant delta: Qt.size(1.0 / width, 0.0) property variant source: theSource fragmentShader: "content/shaders/blur.frag.qsb" } } fragmentShader: "content/shaders/blur.frag.qsb" } } property real angle property variant offset: Qt.point(15.0 * Math.cos(angle), 15.0 * Math.sin(angle)) NumberAnimation on angle { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 6000 } property variant delta: Qt.size(offset.x / width, offset.y / height) property real darkness: shadowSlider.value fragmentShader: "content/shaders/shadow.frag.qsb" Slider { id: shadowSlider anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.leftMargin: 4 anchors.rightMargin: 4 height: 40 } } ShaderEffect { width: 160 height: 160 property variant source: theSource property variant delta: Qt.size(0.5 / width, 0.5 / height) fragmentShader: "content/shaders/outline.frag.qsb" } ShaderEffect { width: 160 height: 160 property variant source: theSource property color tint: root.sliderToColor(colorizeSlider.value) fragmentShader: "content/shaders/colorize.frag.qsb" Slider { id: colorizeSlider anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.leftMargin: 4 anchors.rightMargin: 4 height: 40 } } ShaderEffect { width: 160 height: 160 //! [properties] property variant source: theSource property real bend property real minimize property real side: genieSlider.value SequentialAnimation on bend { loops: Animation.Infinite NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine } PauseAnimation { duration: 1600 } NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine } PauseAnimation { duration: 1000 } } SequentialAnimation on minimize { loops: Animation.Infinite PauseAnimation { duration: 300 } NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine } PauseAnimation { duration: 1000 } NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine } PauseAnimation { duration: 1300 } } //! [properties] //! [vertex] mesh: Qt.size(10, 10) vertexShader: "content/shaders/genie.vert.qsb" //! [vertex] Slider { id: genieSlider anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.leftMargin: 4 anchors.rightMargin: 4 height: 40 } } } } qbs-src-3.3.1/examples/shadereffects/resources.qrc0000644000175100017510000000031115232633614021643 0ustar runnerrunner shadereffects.qml content/face-smile.png content/qt-logo.png qbs-src-3.3.1/examples/shadereffects/shadereffects.qbs0000644000175100017510000000154115232633614022445 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities CppApplication { condition: Utilities.versionCompare(Qt.core.version, "6.5") >= 0 && !Qt.core.staticBuild Depends { name: "Qt.core" } Depends { name: "Qt.quick" } Depends { name: "Qt.qml" } Depends { name: "Qt.shadertools" } cpp.cxxLanguageVersion: "c++11" files: [ "main.cpp", "resources.qrc", "shadereffects.qml", ] Group { name: "Shaders" files: [ "content/shaders/genie.vert", "content/shaders/blur.frag", "content/shaders/colorize.frag", "content/shaders/outline.frag", "content/shaders/shadow.frag", "content/shaders/wobble.frag" ] Qt.core.resourcePrefix: "/qt/qml/shadereffects/content/shaders" } install: true qbs.installPrefix: "" } qbs-src-3.3.1/examples/shadereffects/main.cpp0000644000175100017510000000263115232633614020561 0ustar runnerrunner// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #include #include #include #include //Not using QQmlApplicationEngine because many examples don't have a Window{} int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); app.setOrganizationName("QtProject"); app.setOrganizationDomain("qt-project.org"); app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName()); QQuickView view; #ifdef Q_OS_MACOS view.engine()->addImportPath(app.applicationDirPath() + QStringLiteral("/../PlugIns")); #endif if (qEnvironmentVariableIntValue("QT_QUICK_CORE_PROFILE")) { QSurfaceFormat f = view.format(); f.setProfile(QSurfaceFormat::CoreProfile); f.setVersion(4, 4); view.setFormat(f); } if (qEnvironmentVariableIntValue("QT_QUICK_MULTISAMPLE")) { QSurfaceFormat f = view.format(); f.setSamples(4); view.setFormat(f); } view.connect(view.engine(), &QQmlEngine::quit, &app, &QCoreApplication::quit); new QQmlFileSelector(view.engine(), &view); view.setSource(QUrl("qrc:/qt/qml/shadereffects/shadereffects.qml")); if (view.status() == QQuickView::Error) return -1; view.setResizeMode(QQuickView::SizeRootObjectToView); view.show(); return app.exec(); } qbs-src-3.3.1/examples/shadereffects/content/0000755000175100017510000000000015232633614020601 5ustar runnerrunnerqbs-src-3.3.1/examples/shadereffects/content/qt-logo.png0000644000175100017510000002174215232633614022677 0ustar runnerrunner‰PNG  IHDRôxÔú#©IDATxÚíÝO¨Õg~Çñ¸›¥d?`E.V‚!‰sÛnl(A(¶À Ý$.n´5dá¸HL(©RÁ…!IÉ`JL„ Õ0‚$A\ˆHq! ÉbV§÷{çÞ`½žóÜóûýž?¯7|¥C;žß¹çûþ=Ï÷ù>O<ð3þé/f2™:rpÏ'[¼ø×‘ù…\xLN,ýg#³ ™ñ¡ÐO_»\Ä—²w!ïË…ûru!£È/_ÿÕh¡àv~ðÜhÿ¹ÙÑBñžf®.ä£%1ØràA0^Aß~_?ñ@!Mš5sF[ÞݼXð§\ì'É­¥•bh¾àÏ.ùr+¥¸?2¯®ͼ¹iè¢O XzÃß¹TðG]$Þö·ÝÒÅÒ~ßù~I ¢aïRŸÁZ_"@I…¿Ó¢¿\ø·¦ô¢O ÅýuKËûßwYøc©?Þø(ü“ˆÁòÉ„u¾ˆ€> ÿ‰N‹þR¢±¯‚¥þ>rÿ±Eb˜já_»ôÆßyáåþšûˆ ú⿳ó¥~oý}æþYÛ 9‹¿}1ä†/þëzmú[ȶ£[ !0°\è³ø;ï/ò310äÀ Åg¯KÿºþEL?0xñ_Û÷Ò¿Q¿"Sƒu~ȤÀÁ¾ßþ5þ‰r`Øâ¿®ïâïí_„^Nxû1ýÐ#ÀÛ§Y`Æ®ˆé‡Z{û×ù/R,ü=Ïú!Ê+þ½wþ¯™ÛàTÄ# ÀÞ¾ßþMý!~|áà–æ?R þùÓ_rô\ügú.þÆþŠˆé‡Àð0où_DJƒÙù§×ù1,ÿ‹ˆ!G†¹-ÿëþb /þb`ÈÚ€«} ÀöãÏøÑÓ‹ÿÚ¾‹¿ý!Àð0Û»¼ºÞˆˆr´¶ÿÿË×å‡BDˆ0°|Ô·lyw³‘Ÿ‹!Gè]n$"’õ#=èDF®ÿÉû˜¢b…iÿ "Bà@/ñÇ,"BÐØ  "B@DD„ xrßFÌ"" ÀC€DD! @D„€@DD! @D„€ ""@DD€ˆˆ@DD! @D„€@DD! @D„€øc! ""B@DD„€ˆˆ @:Í+§Ÿíüà¹ÑìüÓ‹‰çµœ'^]¿â³Ý´ëhö·;zy~×hÿÉ×óÖ‡‡Fg®œùYäÞ_nÞ»òSÎß<¾˜Ó×N\}m4y‡g# 2Íb¿íè–ÑÌ››FOîÛ8ö3üÅî£ßÞ±XàO}vjtíöµQ|ûÃW£ëwÏ/ÊAˆÁ;—^ð…@—=Ÿlm?þÌhý™Ç¾Í?¬àùôHoÅ~\bõ ¤àìãcWvyÎB ‘ýçfßò'yÃ_.ú±”oø%Bðù7Þÿâ +BÐ^^:ùìŸÞô'|>±‡oúµ«ÑK@„ êÄÿš¹ Ioû¹-ïO“?üñûÅ•èð=€æ 4òÝùîΨ%b›Àª€PüRÿ¤…?oü­þ‡­ ĉ" €ÕÑ¿x6?aÿâ—G B@@a‰=“~î±Ü_Ss_W"Ç }Ç„€€ì÷Lzœoù­¿õåþI{4  Ù4ùM2¼g91ŠiÄ©ÛB@À`‰Q½)Kþöú§³-C…|…€€^§ø¥,ùÇ¥<–ü­@CûýŽ÷u{‘û„€€N‹Ê~t¿%C„jûÎ¥Œ^ž¹|óòM‘Ø6q•3 ŠuD‘«é{7éw›'§„È¥Ûï-~~!R! VU€â¯ø×PÍ÷nÂï\\ÝË’Ÿ­Õ ø+þÙŪôæÀ¸.:Çã¥f1€&ºýÿ²›K–€”c¦}1%ÀQ¿Gõ ˜FRn‘ì@@ªNJ÷u4`9êG¦u©TÊhi@@À—ú˜ð—/q®¸Ó~÷Ÿ|š<—ôù¹ÑÏé€ifË»›'þž¹r†ÐgÓßîcsª«9SMJÿI_P]â30ß¿~r¿DhQD3Ýÿ' º¤œ¹îëØ¦KL¿ËyÊÝK'ŸÍzŠ€j²Øq°ôßWÓÚ:Ò„zê³S€€€¾–þ¡)0—ïcŸÛP€€T‘”ãV}v\£½~€Üe”]ÿ¨¢ §­€”c¨}ž& ø¤œµŽ?ºþë"§!A)ûÿ}Ï   üÆ¿„Ï©ÛÖ†&'¶8¢É1Þ.ãˆÙƒ‰Uø,jÙ Ée+ eõµÛ× ]6ZŬÿÚ—ÃÏ}õŸ6±*÷Ð÷Ù‰^ëVÀ¤[RC|' 0î·¢Âòî/€±B’rm¤R?§K·ßô{ùÊéç'þ¼C¼ ¾ý÷9i­ï¢·Ò›oˆ@ʲtt¦—¸=0䀠”aTClIÐÔÛmÇþâ­’}ïÅét KºyïÊ`ßÍ”—!&Q`èOÁÅ?åM7–¨S.©‰eê’NN UàÖÌm˜¸÷¢¥Ï‡€{ÿ«`µ#pcvBŠ”tiÒ½¿.âTÊPÛR€€—Ô¦¶Ößü[”€Ó×eÐPÛ+€€4q·ÿi6¸…Lºd=ÄÔºRVR†R Õ—B€©qöÆánŽ­UÜØç*@ÊŠJk=€˜ùŸQg{ÊѵRNUôµ °øý,èX* Õßø×÷ˆÕ®öýç/ïÈn|môV”°ºÒÇˆà”æÔ!唀b’²¼ZËàŸ˜ð—ë K [}ÌH¹hȱË€€‘”ñªµ4ÿõÙÈ–ºPÂ*K×ÓSfS ¹zB@ÕÍ5Ð÷Q¶”S%¬´|þÍÇÝ^TØ`*@@ŠHÍGÕr:ƶš^‹Ü»¼)0eÿèï' Ù'e¸J-sÿû~û¯} «Ï3eëdèí)@@Lþkðµ«U€!.µ™„¡œË Š¡û&È>­žýïzϺÕm—.š'ýŽæÐŸB@•Ëÿ¹¿‰æÐµÞű¶¡;ÛÇáÒí÷?¡7+@,ÿgÑü7­{ÞúðPSŸmÊvIŸ ºÿxKíso{èãmã0ÍÉ€)’šÃ  Õ ÿrºZŽJ3`·ý)’š€€d›Ô=èÈꦄg{fœ°j›$—ã’€€T5û?‡æªÕrýîù¬žC­ÛÑd™2À'î>ˆ>‚¸_à—/ÊNõåD‡ w'ïÕ¿6 ÃÙ‡ÝÂØSŸEªŒKœˆˆTˉïg.Ÿ  ŽÿeFn?Ì©§r¿ˆ)Þâ»ß3@ÿ+nÿ¿…Ó¯ýîh„ XÎüå ÎPôqo}_·1– d‡ÏlVÆù..'dáüÍã?%N©,‹ÃЫ@EPë’ó¸ûÒ9>“Zû~÷€)÷-,‹C4´†0°º@@ìÿËP·ÿµ*eѤGô€‚—›s¸\¥öÊZ/eŠ£{€(X Îÿk|Dâ»UêЛ•ˆ‚N€‚Ûf¿»†å®îª7™qeâ|> ÀÀI9—‰q'ôf¤B€‚0p¶ÝÒìüÿè–®ñtF —3Åèb@PØ æÎ—| …í™hV$ …5Ö0¨ɤFÀ4ã¸" ð†9ï\zÁ Í@ÄÀ"@ pJxFµžw/ ÈlÜlLs+Ü®ö$@î#ƒq§FîG[X¥w  0injÄmk%<£ýçf«½¨)Ž+³æ{%÷-4jÆÀ"@PHayëÃCUü@ž½q¸ê•šRŽj{Ë~ ܪg"  Ð]Þ¤¤4k–2­1†çË{£„!@-<«qN榆 ›Ê9 @@ì+7)5÷kÄG@ùÀZ~ˆK™ØJÃ& p¶¼J™¸Úa@±¼^»€€L)¯œ~¾é#€¥ @íÂö‡ÿ~´fnʽ'ñoy0!8ñ¼?1\€˜ðPJÜŠ¼ÿÅ+~WSš [_5 À-€¡¤1ÀËyr߯j‹àãžGаæøopµ¢K¡& À €J æS—n¿×„lÿ÷¿YüÛ‹Äó|0ËÛ OíݼøìîO Lšd„€€© @ü(0DOF-Z”ãß?i¢q”€3àôõCÅ=³õf@£PiðClÕfD@rm(Û}lŽèÛ €€”,-"yrìÊ.@@ü·&+=@0àXÙZ†%]¼ÚáM€` àûÍž[~G3 €BB è³\»}@@©r±JMc€ @ž\¿{ž€è&'­5o®4 €€Usïǯ‹ýÑLynqY  €$ À/vo¬F7wÞü†aøö‡¯@—Ùòîæ¦ï åmÍ@@ €€@  ,˜¿¼ƒ€ä$/Ïï"…>»’àQ’€("€€”¬™Û@  5¨}™üÄ騕]€ 'ˆÐ5úw°jþðÇï  €´&+@¨V¶ÝB  5Hù1\»}€A¶fÀ€pæÊP ùôHñÍ™€€€JŸ è8{>ÙÚ¼Ì_ÞQÜfíâF@2}“|ëÃCÕ@‰?ĵ Àõ»ç €f2?Ä­ Àù›Ç @çðêz@€ïhMRn•{y~(P.~y‘øÞàJààìÃÅ=³—N>[õ§•Š# p%pço›F8@@ª€”bò‹Ý  €€´&5Ý@òcÚý€€€)î'ßùîN°Ò™óš੽›  À8àeVš:—kfÞÜTm߯½¿& }ä•ÓÏ'7Šy€À4À©ðí_@hq áMå4e€ Ê‹oï Æ7@@Z€š†½sé+6…F@`P³?Æ€€L%ÛŽnizPI?Æ{>ÙZõ©.Ž­@Ìx(%]Tû³" Ì8õÙ©* ¤qÀ5 À83€}å©qéö{Å<§íÇŸ©v»fœ±Ì€`Êyr߯jÏ–OãÍÓE@y¬ÄG @e¾~ˆ€8 ˜WóQË£(€Lö–k¹˜”ñ €îò&kü¸k€ @f'ÞúðpZ£·> @ÐAÖÌmhö$@ ³R§–0¯aÜÏŸ€tõfš= PÂ,€š·iÆ9@@œ1oò(`͚Ǯì" C奓Ï&ý»/~y±xøÃ¿'hœÂ  í1ùôˆ£€¶hzY}! 5î>6ç$@¦3^|{GUý€ £·ÌMû·V!ã6¢98ÜçN@ì37u æ#€ã6GÍš; ú\roМ´ù’€Xjnª°Ö•™ëwÏ! ¹äÉ}«l6›ör´ÞŒÕ3éF@Ða¶¼»¹Ù«smL‘²Æ4OZ €@Í4î?7[íEM}ôB@œÇòí_iÌ̸é’€èèŒw.½ °ÎÞ8L„€è:χ÷¿x£ø €%ŒNi¸$ –›éxâÕõÕËL½|©ÈM2 Xuá©á^€œúj±Ï¿ù¸i˜ôø#@ögÏŸÚ»¹Šm€ùË;lÅdxÜ’€ôíÇŸIú®Ý¾V¼¤4¨iÆì¾Ñ²H]!p°c&Q›Ó@G>=Ríg[‹ä|ï Éèµ\<ôqÀmG·$}ï|w§ÚÕ•Z µ ’ û"TÃ6ÀÐck]þ_ME-ƒ`ÐÉ2´©€«Ë+§Ÿ¯rùµŸiMà( ° à4ÀŸeæÍMU^È´ÚU•š@# p c† ´Ø|YáðŸi,{×$ú@µ§J(HãüH÷½W›zö?wášÆÉŠ”-©œÇ"Oº"4é|Ž˜Í[rÿöûßÐÏ’t-CúlL}ûy~WöŸã´ö¼k€ÌÇm3Åw"šq×Ìm˜¸!ôÔg§~úÿ•ñý ç¼tòÙfï¸÷ã×Þþ3Zî®íb¤hŒ|P¢èÇÖÛ¤oûÑ{oûû>œIß@Jy3Íe õí¿„û¦ÙK‘ò=,a«éÈï÷- à$M·ÑøoúqúãqH@@ïo§¹¦w ë^€-ïnNêü/áóæiŠ”S)%Ï1 yôØ>{ØJF$zkâ?wñË‹ýß' @3`"]^à’zî¿„y Ó«œÒRÃVÔj! @3`&o²«ú—ûÞvW…'e%êþf8@@€ uÓÅ%.©Kÿ%ÌY袲¦Y€€˜ ØèV@êéŠR„ª‹æÉÚfPLRÞÀjÛ‡ÆéâjJ¥]ÿ]½ýÿtpÂÏ­„1É Õ®ÔôǶŽ]ÙÕ{ñ/éXe—G''=_Ëhj«K@ Å¿ëáI)×T×Ò‡B` @ X§Š—ýûxûOmFóõ€€«S•€q ^ÊñµØ».í[_£“'Øz ƒ¯Ô4à~bàÍÃæ„(¥Œ¯7Ö÷­û*4)Ç'[ž@@€ vsïCâ2—AŠÂ_ê*Is¦ùÝ«ån €,Ró ûTâÍ=öí6ÓýQ½ºÅ­$ºš”8Í Š5ï@ú¿# Æ¶T¢àÄ}$&ÒEb):þçI/tÉ™.ïJxTb•ÅT@€“òC©©¶L·%Ns(P‹«€ŒªŠKÊéŠWè,‹3Ú¶\ÔR~ÓãÐß½”#­­Ý„6[–þ‡˜IÑÚ` @²Ý hµ;»dVs´3óæ&s@JÜ håT@-œ½q8»Ó(“ Œ­€VVŸè%©÷Ü·<©­$>ÿæã|SM(Ÿ-¬>Å€¦¾g4€†“: H?@Þ|ûÃWYìû“€•‰;*–§Rfþ[A@ôè(¡¨PPš–€xÛïú6F@:Ù—uuk¾Å?§¦¿qzQRzJ¼‡!Ve¢'£9# ­]”ÐØòÅ-šÈ†ÝŠŠ†ÔÜW¢èÇøå’¤Œ€C‚ £°%å‡~ÿ&ÝŽŠ‹œŽ|z$«çWNü¦O@ZMʰ–Hn?ŠÙßÁIç„„ˆqScìçÇ[~©«/@V}i Pü§Ý›ßÅõf&nŒk›»èˆb]ûñ™W°¬O@„hø+ce ÆXÇÅBñw¼¸]0Æ–UA4¬>xÍsäþ‚ø<£ÀGb†B¼ÕG¡7ûœTÐÍv@BO@¼}Añ§0åÎro¤B@@–gµ—ç4]rï+  š´kyÿÕØàé,ù¿ÿž‹B@À0‰&¬”»4®®ó¼²3åB@@©}kæ6Øèá­?·ë|…À–@ÒøÖØâ:áñöú5ú  YLmbj[ Ëý•O”€êz&<.½1˜Å¶€Â/€¾-SÚ&/tQøE€ô(1E°öhî‹yò:û…€€jE ¶&=1[q×{m=ñ¶_ëÅ=B +_ñ:áª@ ŠíVârß!h6/|6Iâä@l”º2pýîyÏ_@dy¨Ðòõ®“ö Ä…C%­ÄÞ¿g. ò¤<Ó8JX ®ðyHR‡ •‚ѾB Iêxa}"€œíÇŸIz®%5zÎB dÏ'[“žkI“ßÿâ ÏZ“rÕpœ(é¦?ÏY²8# â>€ÀU¿B@€4Ø`$° öÜûñkÏZÖú¬ 2¥yq‹`IX‚ò‘‚ ½]”ò|/~y±( 0P ÉA @Ü 0å ‚æ/ïð¼…€YÎú3?ßMû·wMð·?|åyKîÙ«`ˆã€†I{™U°@¤·ì?7›ôŒßúðШDB ’L3£`ˆm€Ž·N\}ͳ—¼úq ¶úáæ½+. ’\rK±a¶^]?ñsÞ}lnTqJàúÝó‹ÇceàÀÿlíüà¹G&þ÷Ç®ìòÝ3@€ËZ#V|oÄ@P|âÍ6åYŸúìq€´v7À‹oï "«ÏZÅ @4i+W*Ñ H¤½Ì+T 2xfçŸNº!ðÎww€HZ¶+T 2xö|²µ‰ ‚€@d G[[ âü?¨s ¡ ¥U SÊNE @ôqü R所—çw‘ñrBªæœ¹r†ˆ˜þ %'žeKWqû @ºÊ^Å @²Ï¶£[’¾¿¼HDþ<ßkþb²þÀLÒuÁµž âê_ÐÌ©€'÷mt[ oÿ  µ¼rúyG €xû $`üùôoÿÞþA„ÑùiFj9HĹ䬙ÛÔPúé ¦þ€æO¤Œi%Ï 2Aæ"©{XPC[@Æ]ú×ø M¬̼¹)i`Pi±ô@ä!÷¤ˆÀìoÿvtê³S@œù€”.[ÞÝ<ñÖ@¬¼õá¡ÑµÛ×€”š‘…¼tòÙ?­ L(±*2CÃ`ýÈù›ÇG§¯ò\åQ¹jß@äÇ£i0NLrŒ0VânhŒži¯ÜûñëÅéö{‹Eþý/Þ¸úšg&“Nû›Qx@DÆÌΞ[ÌìüÓ?%¾Gãä¯Þþõè7ÿñ‹yã¿öŒŽýï¿.fù}9×ïž_,ìˉ♿¼Ã3Å€ˆˆ(þ @DDñ ""Š?‘¶»ý×)2 @D:ç﨑¶–ü÷*, @DÚÉKþ @DÚzëß©˜€i§ð´×@D¤ÜŠ}~…€ˆHEÞ™~ "u/í_X*ø;5ö©³s~iIÖ²>‘ú ý‰¥¦½Yoõ… @Dz€Qè@D¤Ó›ó>Rè "õúíÎÕ@Dz@Dz@Dz@D:yA¡©¿ÐǼûY?† " =@Dz€ˆ(ôéåNz…©´Ð»“Q耈(ô@Dz "ýÞI¯Ð @*.ôëü@¨Y¶/ä{ =´'3}J…” =4(@¦t'½BS”€µ ¹J$£B?ã* =4(@¡÷ùKÀG@zhSNYáNz…H¨¸ÐÏúC@z@C°“(ô@z î¤Ô.³)£ƒ €B(_&¾?€(ô€%€(ô€º$àPèíIÀX÷T*Š@¡ E …€D 8Q€(ôt '2…€!% cp'=IÀü”@¡  Ø™ =5HÀ#@¡ f6úËí =€‰ùAè–{ŠÜó(IEND®B`‚qbs-src-3.3.1/examples/shadereffects/content/face-smile.png0000644000175100017510000003606015232633614023321 0ustar runnerrunner‰PNG  IHDR@@úù­ pHYs Ö Öoyœ vpAg@@êóø`bKGDÿÿÿÿÿÿ X÷Ü;IDATxÚì|wTU×¶þ>…sè;EAcÁŠ0ö cW4»€šØ4šh,5ÆÆ ¦¨‰ 5KT41vÀ†‘"NÛåÍ9÷Zã7rÿùåæÝûÞïÞdp¿¬]V™ßlk®}®VøÏ?ÿÖÿüŸSEÉVbe[6à.E¹–X©(_%šeŠr¡àSEÉW`ùZŽü:Ž¿ÇûáýþGþ× VˆE9DiåøEXÆlE¹tUô›Aê%Æa‚Ð$Aœû BM– ¸Ï¿õ‚à ïØ& ‚÷-Ax’ øG~?Çßãýð~ù8|\>>¯ÿ(À?ŒèT„ E9[ ðœ¢\M†é~'g¦ ‚a(µC\àÏñAðë–÷¡þIAÐiÁÐÖ´„ð'¯^€daµ ´Ÿ$œÔÜ„ŽVa¯b„Î6Žü:Ž¿Çûáýòqø¸||^|ž|Þ|ÿQ€?Mø÷§Aè^@J)XÚsX !ÕVö›p¯DÊÀ"w1õ…ºŠ¿×ÑúÚ§t´ã‘‘'Š_==/,PôàÑŽZþiE9oÖïŸ~¨8áÑ­ÀGû K²óN6’¾¾_2-/?äü¡°’5yž„>yñÁáp½Aî’ Öû ‹Ï=J¯ÿÞ+ÉÝRkGZFɳ'û½ÞX<àõ°ÒLÇ_GžàãòyðyñyòyóuðuñuþÛ+€¢xBì­¼)>+Û$®‹ÁéŠ 8 ‚o< â+4…7Þjo(o\ïlyÇ»pÞ#¿¢ G 3® ª³o¨èl¹²øÃ—¹Þ³›}:bªç̆ֈmû{Ÿ {§CŸà!Þ®m¢—{yyÍŠŒèqÅi¡÷¡Ni½ëêtÞk;­ïÝ pL¤K÷Ïœz%´ ÏYÃÚuÐñݹ¿Ë,ǦËGL•¦Ø^„Ôÿ°¦x_îÆ†íö -îœw¸Ö± GÊí%%.CÞñæóäóæëàëâëäëærø·QHª¶Ä ÂaøÖ‚`ît J–Ӟ؂"}m_£¹ÙùDIì“r ï› ¾{ðÈ?k÷-ù²=ªÑÞ <êêÜa«wëi]¾w^ãžÕaß;ØÜ‰¶+G‚-Ž· ˜à½:469£vÈŠ)8ʆš)u ½)0yÊ=˜)@߆ßL¸"øÙÔûð\õw¦ô†¨ß$lñÄF@­ÍÓ‘ýÝFîPf:²uMçÏ`ܵþãB?ï°U"_i4rÁ‚¢^ wßz™ÿ´­gèû&¾¾.¾N¾n..—ÿ³  (§<„Æàu{@¤SÁ*[ „¥Â8ÁEˆl½ì¥æim÷øD©(ûQ»¹é; †6’FçúHoLo%ù´ñÛîhŸK ºZ-ÙÄy´q­qA@Üõ[Œú£¯ßĸr@­—g÷ß ÷Ynr‡}€—«i•¦5¿ øãª7æ2œD×§6»JÏŒw+‹Ä÷^{ Ý« ¿å¾Ïã}n:]¹È˜8`1—— ——Û?;Dhÿ)Û4šðé>(&øÛôõ‚; ß=ÂQe¡ 4ïôò—ç_¹ý0ùçÊÓ%óêÆ®ªã1¡ö®Æs‚÷¸ k•"ø¹Å×ñŸ€`»×ß›mä>¶ÃVL£Œ÷ŽÇ¹n³g6uÞ0Œ†^¦ý†Í!Ž Cv'<+Ÿ¦«r:aŠ4–0\>CèH× oJëé½Çò Â#r[\ ýo²æ©:®q.ÎC¿Çó,ÎËñrÐ,˜§·{TGX©®ªîüØ¥‚¶ÆÇÃ>aq˜[ׂ౪N¿Sðžê½¥Cê_XUçÕì‚"÷9“ærárârãrärý—U€ÿ§©_y¨ÄËàŸÁC¬ók¬ SëÖõÅÑÜ—Þ‘‹\äKV]¯Iw½£‚޵fìí4%Ôµ§ óå Š`qº7=nv°ÀÛo#ý_ΌŒ$Áï2UbÅu*ö„ŠíªJ¬ía„½¹zßFï áö„v•XÖ¾i/!Œf×ñ?êw;ë¯3a­žú¾Í™ÝHxD‚•¢oÐTà<µ_8ï@Û56õ@Åõ¸Ñq†Ž;ŒÆÜ¤Åöž+@Ú7:×쪱·2ÚÞ¨^‡Iw‹ôù>‰‹\¸œ¸Ü¸¹\¹œÿ=À©½0Á†‚P«,ÓK®DM–®I»4Bx~÷ù¾ –·rh¥_]gs¯IcƒD ‚ 5M{÷ôƒ§uµÍÑ©0¡ñNÓ‚?À˜¬oãúˆ–ÚMÎP ¶LE”ÍQ{lÍ—„‰5„5û³,ó[ö«Z›޳ž Ì´u" ´ÿ¢É0Õ>pƒ)޵áëeÂæ¯hü ³™ÚI5sÙø‘„KÍ÷€[ë~šw„rs ]°ËAXW¼S³Û°Î¾+£À3TÇ7­@”òª‚þ¦Î¯ª-ú9Çl$ÿÿî2\¬õ3¬ûµçã6@b¦† c’Az'íF»w¼ä¨«=2ÒR2/…oâ’ƒ\Ž\®\Î\îÿK @Û¹/ÕmK`L¶5è0=„vŠd´_lÊ ÷Z=GgX ëÛ/òž[—€%-ñ›ƒÆw¶ÃÀçÜË›OEâõ¾n;A§=•8Ût5r¿&ÁÍ,§’‰<³¢ 4½ò¦ß&Ö¬T‰µL&ÌK%´u$,c¡ û%Ë> ®Ÿb½ÍFxÖJm!Õ¶ƒ0É~€½·ˆ…g/Û:‚³0߼Юªù”Ú&_UA_F„y§¦WŒÃQa]­a1Jªm*„n…ëLÃ7nRómHi`bç‡@ïý€„æ?‚­o7<÷ ¼Wì’ê½qŽŽË•Ë™Ëóð—à¯Çzÿ0xý)LÄà\OøT†Ü9 eÉ´g­ÝêŒrÑl”7{OìõÂu]}çÆpG¿7 ­Ýï €åîî!+Ðt³0ËÄMSNô¨t1@²4¨<–Ú‡_ÏF”ê²ç/fX:2B¦1¢®ª«Ä l£Tâí3‹_¨†[=–”*LQbÙõ"H¢ú© DØ_õ6+á k_Ât ­CÎ2o!t7½G¨z„©kE`ŒôêÕ+T7¹+*…ªa(í&ÇÕÝ]ÄÆÊt+ü¥v€.#ëOÙ ¦ùŒéõ¢´qÁi·W£\¸œ¹Ü9œ—ÿðûd´[°åPÐÓZ°P°›Z/^?, 4[†®e@|2$Í,;D×¥ÊVTN°:Áõý[NN('÷²nwwsÃB–ç®ÆZô=êNmÏå¦û߯È×%/=ßœ¾†ËóÀyá<ý<ÀÓ›X$Ó*a.R@üuV•Ì|ö‹›ÇÛíô›õ3ÜLÁ>ŽS}Ÿ\‡©üæ7$Xol0Ööz ¸K»[BÉP¥n6NQS©EŒÓ$ T'®<‹Î\ìTÂX$„ˆžNΈñ`í@žÕs ·ª„z!D”UU”|ëjv_}^±:3ìÈ®×eIàBÖßT¦ÛY›õÇCˆ}»ßÍK'ŽÍ'‹r‡æDt9Zº¥„‹£‰¢e=ÉÁKû-à8F÷Èéœö–†ÊLà ¯ñ@оo…lŠ£ß ì}”¾™ûgÁºÒöÜóßnÇyà¼pžþa  ()L£ú­@©hr»a±}«ù¦ÉPË{Uv×[CBœmî>pWÿ›ïž€AXRu>à ®hnD…šqÚ]†•4ä`Çýèò´ÞN?zjZécJ*4 ±d±ÑJ ÅèLÁƒY˜'¼bkÎЙeùÜ‚G0û–©„Ê9V+µó¬W˜"ü@×Ó,€äa¶2γýXû>Sf„Ù¬ÿrÖ uÛçAHmRduÞ àéšãÓ  ý™„’ Ê'Nó­±7ÉåÇ"€(0ý ×AŽôÊÑi¤ï{XùôégNÍ<2¼7 ‚-Ö”êºHçóÂyâ¼ý<@·™áÑy0H{¡»tbÏÞW–‚·\ƒâcŒãŒ³œgº5<’jm Ïv[ç‡üDo"â—iÇëõ4T#ÇŽ„ÁÎHä,Írc!}BÑM¯ÖÙÐ2xŒV΂ ¿L`.ÒC)' ŽUÊÉ23™å>–ó­<;ïË,V #¤Ý#r¾zݲšÝÿ‘µ÷3\¥¾¯Þ—ó-êýÃÖ{ìýbfÑ8nS„#0^'ÊòËm‚=ˆaûW2qÞ,””&ˆkÑð=¢¶•a(ÉåWg’n°“y„ås©P­C»Ö~âææ÷6x€žµjÀ#d»lq[.ººÕŠá¼pž8oÿpø#Öä ´¿w o”Ùrª8¯í3Åñ¸s'·k0íoÝúlB5Þ5NFׯIVÊ‘ ÍíkÒøn~„‚~m\rä–ŒˆmªEš/fY ÿeç£%*Ю‹¤äX¬¤ ^·Î·N©n rŒßrì¤@7O›¶ào›~»ýàk$ìЂ3åh‹…ê ‰–:ˆÊ‹#C ázkÊI¢ ï%Yšb?·oßßýî™Ö?-Æ¿eKV Œ;ŲÀÔ½ ƒˆÎGQ+9,”0Ï#ç³pØRD˜Aux΂Ï)©Ò5TðÝI>^MHnum0h6xÕpÔØð[·D¬ßpé Ûg{íšgï>S8/œ'ÎÛ_TÚç'šÛpìß #”/Á ÓÊnkœ:u½®ÿD»ÏxÎ{ŽÃ$çzî7pX§ºN«qÂÚ]â té°pÔü|%B,eÉÙ"Ì‚åpª UHë+¢¥KRY: êðk-«¨u`ŠÁ-îß3W>[ò¬nzokߣ°;¸xñJ_Ü6FåÅÃWaú©%›  Sðþ‹‹/æ’”›ï¡e‚àW!ÊY ³!PÛŒíXE6¾WP¶ôÎîÉ?n‘v ‹ÉóºÔûê¨òAØ\°µÃQ?šÇRË|¶­Î꫘_á¡„%µ[ ÏT=£mo×ò$RÈ1˜»Gȇª{²RdœŠ›Qð€Í)wzS„usœâ< “C—EîctÃ{{Ï©ð*¹éœÕõ:ç‰óÆyü àÙxr¶½\Ji¸ •w_“åök½ãè˜d‡;`éÃàîSÇùÎ%H¼þm%œ’¹Ú¶…Ë]_ ”Ü*ÉÅK3Ê–xŠkŠÐ%ÇŠ-žShšé~ƒŠdD9Á\›¹dG†#˜g¨C˜–Yy¤b>ÿÕå¯F\€³š­Lóë‰_íÙ§—•N‘>ÇJß±vÇç_íG–-[ŒjéÖ<™eçoF±ÒîRËdz® Ç?úÞqÇ+uñpÇvÅŽÕøö¶«Øohhâ–pô?µ¡yŒ+OPKÆ0?²p+!(V¦M™b¿@”VvCÅâbÚC¬-p@ƒ°¯-¤ùˆ¡¥ ²%·ò À©åë§€)  H¥ÃJ%mÛq¾S_`f¥áC ¥Ö^¦Nub’9Oœ7Îã_Ps¥ÂB¾Å3kkC{©0¸îÙEŒ2 [ëà`¨1Þ…'Þ1ÜÑODW¦.[‰וAWhŸñò$`²ýÄ \xŠuäcª¿YûåŽ&\»DZ/*T]úëF꩜9’ Бm§,l}öjÝ«Wåp:WâRxìdÇç—ßz8øóúòçÏý¡<½¨è),ûwÃíyë‘y]ͼ?†óquVÚM©¹„£H3k@l¿=ÿuv~ô³¡xös$þË;Øï¹[?ôÁqJ®z• ó8ôÊUü’`^ˆëÍ—™B±y×aIç|Âtµ¤m?UT=­8?C›muîi4ëÈüh:™h^ð6zHû¨’$×%X(Ó,ÓÜ´ÖU<¨ #ÜnsVkÿ²»ù#Â(D²üB†wÿp½%^·-´•`2g_(žÆ~îì»Wû-ìS2DZ ·Õ…q1ϨŠÊ‰Ì*á±hù´žÞÜóP;QuõÒõWƒHNŸt#¹Ü°=uëýÕèI-ûsÝ7Ø;lL»”µ¤\(Ç´™JÉUÊX°óå+õ&À«Új½ät¢:²ükã¡PÎçñÏ*/øÄ€æTãvB‡¤¢¿å{“Ñ  K×ùèÚh'`ÅJ÷“ö<ŦV”¥gËiTÀ‰T¡lhñÇ€ ÖŸþJØ17=ƒÍùI<ÅþÐ’æ$uUU„±d‘$HFø †f&ÀKì¶I>½4ºgX2uËu]SK$52}`§^ÍóÄ%ˆî~s1GQ’™ËOªªŽWc Œ®©Q=O >÷Ž’Š ˜Uë(Ò}ÉŸú½­VjzÚg :öu)Åq}zxÞÒ}Çæ‰p¬ùgÕSÕ¼`×L‘ïªógžg§é-:Ô_Ö'¹ôê ˜fmžWFU…O°R˜ew)ÞŠr]Ëc(gˆ5=§íc¥õ*àr]°v0 8滿ÚnÜ–Îyãå,(ÄJ”§¼„ä- ¬þäêЉr^Ró•“È£D7ÅSxª¨iˆ¼(ïJku™µœ7Î#çõO(À]}u#`®©k#F‹ ð[[åì¯)ðŠ×6„cœõÇWöú¨¡òu³™Ð&ôX^bq¤m`y†›°@3]—h»õXnII]»Ÿ-»3—_Ä15[AsY[ÅÖvgž@6A=Áó¬>伟á±sjôÅ•EðÜàø>Ž.-h×qê…AµH(y€£ o3tàבÕì=o=í3Åuô{íâÞ"8ÿO›‘·åg¸¡o{i2›Ç{l^ï3|›ÍŸ{˜žL!¾dã|H®\fß/(fUN--E$'w ÷?d‚üêàu)‘îW¨ï)ˆFœ'ì#ZPñ7†œü9X«óŠç¼q9¯BZ¿Ç4å0VïìÝEÐãG‚’¨)4…OÀIzÀÝVJ†ôˆ\y¹ý€º§‚¬–N÷Ó~¿ÌºZuõ–+ª,SHyd™G@öÑ¢«UÁåq¬éÉæÇ,¿1l;&è&(ѵh`øËíKÓ•MÞÙ˜Yýûéªb™Ôþr!eH0õËñw~=÷=kaý¼¢~{Mh‹ã”H §qÅ¢¦Ì²'¶„÷‰pR$ÃÖsƒÍ;€%C0ҺݬÈ`òè‹§%€ÆÜ­?ÑxäZ¬ög³©ò¶÷#Lgb.&Da޶kîœ7Î#òúç<i&n)€¤O/¨*µÓÌVi2z P‡¸AI!Í=#íͲ^ZG•0E\¬îß雽l%Ã>ƒÎÁ`âdù¤ Y éÃq°p'È+æØnÀ“Ç,3Ý´‚Y\†ÙýÍ„9U!ˆPwRnò¥ö™jv>o á«"CÈû[É&D}Ç¡~ÚºUtSÛU>l\z^*ÃyÐûïRû0"ÝçŠt‘0œÖuÖÕ˜äq,œê`:¬l> ÊäX{©J´4€BF>+•’­—€x*qÅûà+¢)4ÏÒzqÞ8œ×¿»,yHè#Ï øN¾ð˜ˆÏ‘Ýä|"p©’O¥Ö tA˜ÿ+q¤±ÊRÂ|öUnºìOµó¥â@*?'…ˆ¢+SeÒð ǘ8ü™ Ï09 “Å2¢®W·ýѯLÕvÕB™=Út[í‰%Âð9S=뇷MˆRëÿºÉÝçï…¨ÄWïùƒâ–±y°ùKäú“dY­Àº¿¦Ü(ÁNË bòIÒ5’o9E{$ø¦¦(ä!ò•@4,{Ž:yä,ø7–~QP)(‚'çí/”‚kz¡CÇÀ•%-%ÂÓ$7•h |-(•PPÆi>¡4ßÐaNœ @?M¸ºH—¶ÊòÙdLŸ.{ÞVnIþÃC9L.0Èngt,"\Ï>ýJd‡,‰Ö„Q¬ëΦÌ\‹RÈè †F–lcí kTW^ÉÛ ›°íÜ%Öï]µ_fÁ–¦l>}T´ÐNž0Ç>’߃> I€<¾è«âíøÀ›7X ß3Q?ßC±àƒò!Âc„]è ÀÏn ËNÑ  ©(9]‡r”—’Bl%4<%K¹!$¾n(¬'8oœGÎëŸP€f6Œ+ê§ÇÒuøÈR³Q¾-¼-·¬¬”S”,(M*S¾ä¦i…šGçÔ¯y5™dùI€(€$–>ê„ëðÜ›Ë:ZªñÇQõ¶££ZŸ”™l)Bšå<Í›èø@’(„„ƒ€è0Ij@(öW‘)ˆ‡}šŠ6v˜òP-ñÚN°sü+ d8‚2õeØ‘]ïû7Ïï'<þô)G¤q8vV‘Í#B¬O¨V+Ѳ£Á²13‘>G‰®Z°ÝއBõ>®Ý×9pñ›ï>¤Ü)ŽÉ)I£ÒK ‘ ´‹úKSà¨í Üu-Ê=O:,ÄàfBp4`+5¨¬ä¼q9¯B®Kª¦ˆ üít˜«‡\Ö¤—ý4¿JýJȲ¥„£À„˜ìsM0CŽF(Áò»‘+# WÀЂ7(šJºˆ#öÙ×e $Oó;Lï×<È­ñw÷ÙàÔ«»ï©bà§Çöè‘ ›3|´¯†y cE‘¹˜µ†át†ýÿH(³ôrñ$ÃSüù¿U†¸Bñþ™HU<¥SmmW˜çÖ©û†¡‚ô¸0ffå-XÇ7wãL‹:ÍÐÚ=zt´ê«0D‚4ªâR…p@´üp4%SˆÖÆ«»)’c´ø‹æ[Âú:”sx‚FÀ¿|FÉ&ƒ$´OÐ9Ù>º3óÆyä¼þÛÀoÌx ɸ—¬.мtt´¼ý…xL~ g-OKƒä4L/ä1Dl¦8SwA=ßÖ*1âZ­NM^´OQƒÁx!alá)(-P!@A]ü´Ž#Šô°”;ý@X¨å¸õ>ƶ‡~6Ì !¡“}h{Üw~j¿Í6 ª dúIF"H€*¡‚#+'–˜ooÀ’5—¿ynWæQÖ0EÃû¡ŸêÍ5w¤t¬@l€¿CˆNqßô„´6_À$²f®å²Û²yŸÍÓ}&ï6 S’`¤¸¸nJƒ)w`íhmC5„’ÜRäÃÚÖxäúŽ/ŽÑëqo!=ÒvCÛ–º"ö‰ògÒÇÖb‡q‰5èöœ7Îã_8v©žî®䨿HÙ±‡pðiwë"¥¿}eî)é´”+CjŠà&§ …K‡ô›Ð¢¥04Nø¡~-`)- B Ôî&ED ,9ˆ)†"|Cçà§*ÀoŒ: Á´7z¯š ý;÷sÚf,‚,ºCñ×HøòMâ°€ÒFß·þtlÂ[³6¢à¿ª“•‚ÉÝ“˜'çÑB¥Ñ¢«Ô…'ûK1ù|öæ³="xŒ¬ò£{±¢™”½h-nïÚEö…®=5y]®vÕ/æÉ‡ažÍ:á asÛ§Å‚G˜:Â"6 Ë}TùDU(rí €^ã58?æ ΂|v“­¦hß!õë¬ß£ž‚\ñTp€M#’30ºK§å\0”<ù²-,÷ç‰óÆyü p6+¨ÃÒ p¼ÜœáÙÂH³»Æf™sÙ"ŽàϬEQì*uÅ$]#‚ˆ3 ÒÔGÇ(b^Ó?W+UÚÙäÚ<è41“\?U1v–V(BŽlí‹’ÄE~ þ±èPîtLZÇ>ç@Ð_KKˆ™º‰–y $£W^¸ÙøG“?¼ƒ§ˆqšÁ?á§WÖvþ¼DðöïCöT Ml9ãVþfy%ºcahö·IYXØI*ŸÑëo·ò}ÕnxoMç.øÃA)qG°ŸÔŠ”T3¬ëLÚ‰möNøTu5º\§0H­¢¢"{…AnrÒåðáIA¯Ë»,~ê¥þš¡¾cººñù´î#lÝ7QdžšjE‡@’^!žrxŸÎÆzc¶/…jƒQîÒüDLê < ;ï¯él©wÙÂyâ¼qÿnÐh&÷U³FÃ:n «3$erÇrËóó­/¤dñ¶é{ñšx -Í^*Δ£0¢J¯ X±ËG; §ZBDKcô=aIºïÔ:5³Y@A’ëãŠðÄŽÉ¥µîs~wážwÿůÛODA!e[Ç ÷¥0³vß·žDô•— Î6iŒ’ x@ ÃM¡–µæ*%£­ÃÊÚoÝ/øbåñfåùøËŸœ¸sOð'c¿ž¿°`ò²ß£1XÒ6ÜžƒŸWJþJ,`gy Æxç©R"ŽÓîh«Yá ÚÏî|^ÁeAØã»ããNà)Ü\Å;‘P?õ‚ÊIOëR2q½,àzcg‘GLÒ}KÉ_޾`²½>Éí¦8Àr @†ßñÝ~ ·•öS w˜¯e¾è#®7}/O1¾iYr~#ç‰óÆyüo|lƒ› Ã@=F¾=>÷Ý¿öß½÷º¥ô¾Ùvù²8ÊnØ+´°Ù°@+Îø¯ö®4,Ê#ùϣ܇ … ‚›¨Q¢F£‰xǨY£IÔ(¨\õJ4^ 90*ë"âñ÷@@ñDˆ€È=Ã1ÌÍ 3ÃlU ýa¿íóü“'»çË÷í·úWÕÕÝÕÕï𶢚;Žv ¢ÓóÑv@hðYú%ÁöNC(&…[(`YH„X {J(fÍÖåÔPÊÔ!y&`vkB4oäÈ}yÐcOOiŸžâŒmæÞ¤Ÿa(P¯¾²¤öí£Êš!S~ׄÚï2´$®7 B‚MÉ–Qø»)Ñá”Ú=ÃÙŒŠïH@WT´.âŸ\æý´ëdnÆíŸ¯ƒ M‘ÌÈñ}Ã6?ˆÇ0âø5Í…†·R64¸]j_5¶‹Ù©ø0k»y (6·’ÿ+©è²Í·tàl™° u ´—eh÷)n’›d84~d|‚I£¦eí\(W˜3ÚN<|ÈôÂôÄôö¤…g— ýrã,à¸Ûo{lvƒE•èK]/Á^Ý+[õ~F¡Q£o”Ê1 Ö¸Û˜ùñä (Nå0‚Ñöéd݆.)Ôes,>p§!\±ŽÁ@¥Žê¨&âæƒGH§9†£Á€å:]IÆç$^‡ '÷Ṇà\`I›àÌÆoD, .?¯-Lï «ˆkycÎz‚+/<ÿËOCar6óèò}0‡Y»öpÊë7™Ïîø<ÓÑÙ!§`HÝXc¹ 9<)3xlV-Ù¹* O1÷ýÉãú¹s8­’Ì9bF¯‹(¥íYó ÊæÝ 0.p È I–ˆ{"èáHñé´¾ŸÏ÷§ò›ûtH}D—2âé#{/ê@{¢in•ŒçLŽÆõ˜ÚfÐþÏ1è+¹Æ ýxm~Žvè•­L/LOLoÿoàr·C†£É2\N8œ|vWÔm¹K’åÊc‰ô^{¼vtn¸ñU{ N¾Œ»ô³1&n 6Î5L±êûõÖM—Þ”ù²Á¡€Žp>íú!B¢m)p¥>°²{JKHÚhôDßì‚@‹`ˆ¬`SÜv×­ø8ôìÁWfA¿n|/ä™<ÉÓÈÅà‰†Âûä@ý}~èxR„/¡RºnÆËÞ†—ÛO†È÷]<‚CWÛËWvØs&eü‡\Mr=§Íß©ÇSîÊO=Õê xn¤øDÁZÚ+qµ¥Í!³¼ë:ЍF;dÒ¦ÚJçÑÔq.áë'ÍwŒ1k<¤Ÿ ýðvûcŒdJÒÚiÒsÃAñ¨¦¦'¦·ßðl Ï ‰xwãÈãï®ú uñ‚d]ÂùCªPƒ»~’̾Ý[ÿP;”>§ÙމL°õq—,½Õ±ŠÐ×½Ű:ûRàÈÛ~8*”3_HRÆ‘r¡@ì~À»€ :=Ã4úý9kñE¤=³N Xe–áarÐÐp ç<CuÊ¿ Mã«ùŸf+k³|)cîô¤òm÷ÏàuÚ€âmtY_ëGY¹Ñª©´™“L!Þù°æ‰±")|~G6h (~uîr¢<Õ(·% ÛrC»f«WIñÁöËHñrgg«‡pëCõ pJgÆÉ)Þ¿Ù©èã¨`2Ä,êá5(Å!²èg(ÊI{!›¢îs[[ZÖ)ìnÓæÙH§Ú=}æ¶~OôFy5®.Xƒe¾"£­Tµ ¹îŒTªOÓOÓ«Ì{ê•úÕÝ)ãéé…ééw|?ÀÌ`¤‡›ÍñÛ%>×{@¿õ³OwÌ2¶¥&×NÕĪ–ç,4,Õ/Ñzr†w4?J7`zµn–’‹™f'[ÜÆuá*ݧÓéØioÅ“aŒòÜAù¸…“‡prÜDÄM¡¡Vv¶BZFÌ ƒðåûáÙ|$2•K I#ᬊZHc5@ô Ùè9#±ÞÎrv] Üà @õÒòžS Á›††rŒL°$ †àó@NO:Úu™ä†È§ã>Û?s›FÏqöü„º”Û[ߺváÏb.°Eï óÄ÷%&ª­†¿n[ $Šš1šïTÕ9 í>uœm¬HMe¼3=0½üÎ/ˆ`ž€úŠ g™]oCáhûÎñ…EÝ‹<ÝüýmCÜ»ª£4»Ëººjc•…`Á·”SÏ‚¨‡µ-UÉê%èK"ìïÖ sUx'{Çš¹‘Þ4i´Xz A@žû=@ØqÞD¿ßµß HÏÉCplbWZæ 4¤QüµÖÌWS~ŠBÏ’Åæ¼bÂl~x'¾OXÍ«#|F×EÁ÷éVOž ”¿–¯+é9àÊmcIŽU ¢ÒÎ*×ç¿“ÜÇÜùÔŽÖIV漃ñWþžËè{$¶Û’fŠ|E¼”`Þ¿¡Yµy2<Ô-ÂÀ‘è{u²z`Y­”×®«>r'p¢ïàùãééåw5€5„HOkluæL|<“ôÊvåó†Šò ªî?ÎhŠVßTÿµ~«!^ó¥¨×·:ש Á·4îÍï€èaëæ8,Šq[ ¸@pª×Gô ß)V¢|ŽÒdŠóÖ!"6Áã+rr ·\krj!œê°›0½ëAìÁÜÏ…ãɳ¸¿£ž^h{‘“mÓÏŠ‚û Y9]WC×]¶(„qh` àY¬^<ÎÎ[à°Œpµ“QžCrZFyþDrZÞºmõp$÷þ=ßÑ€1‚m½æQy¶Óâ[P.Àûj¾äSàåmà¥0^ý…>äVyÛÓ÷ã=’Dµ6èQ¸ÿp_MMÌuú¹£ynÎÎÖrƒémE- ©ü ”ãu|~˜_þÎ+öÿ ¿¶¯ˆ¬ ø^Q˜Ô)—0ÇfÞÏqáíÇcÜùxçÆ'ê“ÍåÔÎèr<±×$Ý]qðœzŒ ¸ZÚâ¤(¯L-óW(Z÷¤2ÞŒWÆóÜ‹"i¢1h¶OÈ g ÷á&éÀØÞ°# Ò„Ló æˆ.ûV·i=Ô;oßh¶o¹ó¸]³DuK~¦#Y7^ýzò]S|‘8ÉŽ”¶¾^3D怫“%˜Xxu®JÀ6Þ€9ÂþW‹„KQáì _PÂÒþï’á ë?€t½¿¢Í¸ ó€[lföÿ”p!•Óõ/á:D[@|aÕÃí²8'mµÂˆ·#°\ø ÌõóHï(—e…É„r_kfÊ =†GÒee2¦+mºYT¸C¶¡ ^óµê°ü\Gr‘cÓgò¯·Wk>V•ï¼Éxb¼1¯Œç?ÌþýI☛de6Ýñ¨eÈ Húncص±êÛܰ¶ßÎ|ð¥x‚Œ{ñãfUËy¦:\÷MKU-,£´± q…‰@X’ØæÉ  ¾ùö [¡Ši˜…oá34ëq¬·t¬.¢ž:Íu5y„û^s‹lgùú*»,ö/¬íRGøv`)Ê ˜ÄË»B9ý~®Ãûvú×ãw¡µžý‚o½–âÃïÏ¡e¥ðg\# ˜ôilW.h€ûô¿Hv½€!Ϲ+ ù7Šràû–ª:0Ôæä–Ø–êðüÍ¢¥I?Vá´Múv&ã…ñÄxc<2^ÿkÞÎ,•Ë ê€ UéchГ ¾àèeóFæ†BãrsÝ'›>Û‘¿¦)©åÓ]ÞÏëîɆÖ(ÃZ'JL¦¹ºŸ¥»_]"mÄ3žØÆÕªòN¡Äy fƒA²´D *cp×дQw½sã2ÛÖQ}&oªõEyËæ\¶óBä¦;ÈZŽC9®÷áupÚaÞ×Q`xŒ¹æ#ºÓx¦Ñ4WSû¤ôo%:C'¾ÿ C—_ç~ÿ>ȧz ߤÐÅ+ºµ7ËMsŸ}(+k+,Ì?ÕX.ì²w9ûšÆíÎ`<0^OŒ7Æãýÿp¹+øòó*cÆ|`   =,TËš~C¦ð8âã½[z›=Ûºo¾u²:K²(içs£ø„T^&”Ï•wošh\ª‹•_?z_|º ß^“{phõ¨ìç@¼m-/G Šy[´ýAwœ]7<¹ˆË«fCñ4À¿I3JÄ@q»tniá²R!+,oîŠ×éÿÒñTõÌ]ËoÃÓǵn9®ôœ•Ùxþ·5'r…ï×Å%fÀ3Rû 0¤–ò®MÞÆ¥Ïvм$Ê„·ª«¼%‚¤-çÌ×tF þ @ íÄÚÍx`¼0žþGÿ1„¶™[·''ôÆ-çŸÜ…@·pèY ¢qö¸9C"a`ì¯÷säðW5®×龈»ñk^ß“nH Ë9[}A²9ÿeehãf[ùÅjÙÑËŽ½Z‰Ý«vPÄWbÁójP¦6=?0¯úóœ"ÀúªªLG@Qåò;w»UõÊðìh(€rbUGf/@qõÊ»'ðúºôü$À¯ÄÏ[¡~O©×+ ÄÞÈ÷âs_6.i.“È\õ‰dHþËëÙ¯IßM k Ñ'é‚ân°v°v±v²v3/Šÿ ú×!b„-–-Ãü^|»Ïæû£r@¿®x‚9Ô‘U.Hçp3×Ù1¨cKž*›ú+§¯KI;Zv¦ùlÒŽ Û sÓȬK¾µ{š=*ƒËƒº4ž“gŠDMï‹·-’­“Õ9›ç)J jª-“Õ³¥Çªë8ÇÔã¥iˆÊéÒÌš4Ëdy¼Ä«Î×0öí÷áähò“wÀ!,×a›”]aùý¢9…ßÿM¸Í~™ñÌZQÝMm¸öÖŠ¨§ª¦¯•5qž‘ÕcåÆmWÓž•“ìKH‘”|ßô(i™ÜâˆÆ±ÉË»#ž/·–_:Zê!IÝ—á\í/—n»úôRÓ0eVœgÝ­ë.‡ç$®±ç29˜\LN&7kkkçŸþ_Ãþ}ƒ-ÅåKĽE÷è)0ÒÞ ±q€±óÀ„«!7`,ŽÚ9æÈ÷™1mÖð¯ çùLŠŠ€©Ø…¹ïÏ|ò‡–¾#;û|ÂOöí)¦‹Cû†Af¡?CVήc÷±zX½ì9ì¹L&““ÉÍÚñæÛef!—;Hżº‡ã{x\ãÖ@Oóî¹¹Ç[Ï 3BÀD½ö/‡ÁÔlåØñ>3a¶nRü{ è¡ QŽs´°Î~Á•³ëØ}¬V/{{.“ƒÉõæŸCÿp‰¤üw˜TQ—;$ 2ogÍÆ@3Œ½ù€>\®7Q²rv»ÕÃê}óßÁo>o àÍççóOÚÙGᮑ"zTXtSoftwarexÚ+//×ËÌË.NN,HÕË/J6ØXSÊ\IEND®B`‚qbs-src-3.3.1/examples/shadereffects/content/shaders/0000755000175100017510000000000015232633614022232 5ustar runnerrunnerqbs-src-3.3.1/examples/shadereffects/content/shaders/shadow.frag0000644000175100017510000000120715232633614024360 0ustar runnerrunner// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #version 440 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D source; layout(binding = 2) uniform sampler2D shadow; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; float darkness; vec2 delta; } ubuf; void main() { vec4 fg = texture(source, qt_TexCoord0); vec4 bg = texture(shadow, qt_TexCoord0 + ubuf.delta); fragColor = (fg + vec4(0., 0., 0., ubuf.darkness * bg.a) * (1. - fg.a)) * ubuf.qt_Opacity; } qbs-src-3.3.1/examples/shadereffects/content/shaders/blur.frag0000644000175100017510000000140215232633614024034 0ustar runnerrunner// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #version 440 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D source; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; vec2 delta; } ubuf; void main() { fragColor =(0.0538 * texture(source, qt_TexCoord0 - 3.182 * ubuf.delta) + 0.3229 * texture(source, qt_TexCoord0 - 1.364 * ubuf.delta) + 0.2466 * texture(source, qt_TexCoord0) + 0.3229 * texture(source, qt_TexCoord0 + 1.364 * ubuf.delta) + 0.0538 * texture(source, qt_TexCoord0 + 3.182 * ubuf.delta)) * ubuf.qt_Opacity; } qbs-src-3.3.1/examples/shadereffects/content/shaders/wobble.frag0000644000175100017510000000111215232633614024340 0ustar runnerrunner// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #version 440 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D source; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; float amplitude; float frequency; float time; } ubuf; void main() { vec2 p = sin(ubuf.time + ubuf.frequency * qt_TexCoord0); fragColor = texture(source, qt_TexCoord0 + ubuf.amplitude * vec2(p.y, -p.x)) * ubuf.qt_Opacity; } qbs-src-3.3.1/examples/shadereffects/content/shaders/colorize.frag0000644000175100017510000000111715232633614024721 0ustar runnerrunner// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #version 440 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D source; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; vec4 tint; } ubuf; void main() { vec4 c = texture(source, qt_TexCoord0); float lo = min(min(c.x, c.y), c.z); float hi = max(max(c.x, c.y), c.z); fragColor = ubuf.qt_Opacity * vec4(mix(vec3(lo), vec3(hi), ubuf.tint.xyz), c.w); } qbs-src-3.3.1/examples/shadereffects/content/shaders/genie.vert0000644000175100017510000000125215232633614024223 0ustar runnerrunner#version 440 layout(location = 0) in vec4 qt_Vertex; layout(location = 1) in vec2 qt_MultiTexCoord0; layout(location = 0) out vec2 qt_TexCoord0; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; float bend; float minimize; float side; float width; float height; } ubuf; out gl_PerVertex { vec4 gl_Position; }; void main() { qt_TexCoord0 = qt_MultiTexCoord0; vec4 pos = qt_Vertex; pos.y = mix(qt_Vertex.y, ubuf.height, ubuf.minimize); float t = pos.y / ubuf.height; t = (3. - 2. * t) * t * t; pos.x = mix(qt_Vertex.x, ubuf.side * ubuf.width, t * ubuf.bend); gl_Position = ubuf.qt_Matrix * pos; } qbs-src-3.3.1/examples/shadereffects/content/shaders/outline.frag0000644000175100017510000000153015232633614024551 0ustar runnerrunner// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #version 440 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D source; layout(std140, binding = 0) uniform buf { mat4 qt_Matrix; float qt_Opacity; vec2 delta; } ubuf; void main() { vec4 tl = texture(source, qt_TexCoord0 - ubuf.delta); vec4 tr = texture(source, qt_TexCoord0 + vec2(ubuf.delta.x, -ubuf.delta.y)); vec4 bl = texture(source, qt_TexCoord0 - vec2(ubuf.delta.x, -ubuf.delta.y)); vec4 br = texture(source, qt_TexCoord0 + ubuf.delta); vec4 gx = (tl + bl) - (tr + br); vec4 gy = (tl + tr) - (bl + br); fragColor.xyz = vec3(0.); fragColor.w = clamp(dot(sqrt(gx * gx + gy * gy), vec4(1.)), 0., 1.) * ubuf.qt_Opacity; } qbs-src-3.3.1/examples/helloworld-minimal/0000755000175100017510000000000015232633614020120 5ustar runnerrunnerqbs-src-3.3.1/examples/helloworld-minimal/main.cpp0000644000175100017510000000473715232633614021563 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::cout << "Hello, World!" << std::endl; } qbs-src-3.3.1/examples/helloworld-minimal/helloworld-minimal.qbs0000644000175100017510000000472415232633614024435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { name: "HelloWorld-minimal" files: "main.cpp" } qbs-src-3.3.1/examples/compiled-qml/0000755000175100017510000000000015232633614016704 5ustar runnerrunnerqbs-src-3.3.1/examples/compiled-qml/MainForm.ui.qml0000644000175100017510000000522115232633614021543 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.3 Rectangle { property alias mouseArea: mouseArea width: 360 height: 360 MouseArea { id: mouseArea anchors.fill: parent } Image { anchors.centerIn: parent source: "cheese.jpg" } } qbs-src-3.3.1/examples/compiled-qml/main.qml0000644000175100017510000000511115232633614020341 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.4 import QtQuick.Window 2.2 Window { visible: true MainForm { anchors.fill: parent mouseArea.onClicked: { Qt.quit(); } } } qbs-src-3.3.1/examples/compiled-qml/compiled-qml.qbs0000644000175100017510000000523215232633614022000 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: !Qt.core.staticBuild Depends { name: "Qt.core" } Depends { name: "Qt.quick" } files: [ "cheese.jpg", "main.cpp", "qml.qrc" ] Group { name: "QML Files" files: ["*.qml"] } } qbs-src-3.3.1/examples/compiled-qml/main.cpp0000644000175100017510000000520615232633614020337 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } qbs-src-3.3.1/examples/compiled-qml/qml.qrc0000644000175100017510000000023415232633614020203 0ustar runnerrunner main.qml MainForm.ui.qml cheese.jpg qbs-src-3.3.1/examples/compiled-qml/cheese.jpg0000644000175100017510000000572515232633614020653 0ustar runnerrunnerÿØÿàJFIFHHÿîAdobed@ÿÛ„      ÿÀ^^ÿÝ ÿÄ¢  s!1AQa"q2‘¡±B#ÁRÑá3bð$r‚ñ%C4S’¢²csÂ5D'“£³6TdtÃÒâ&ƒ „”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúm!1AQa"q‘2¡±ðÁÑá#BRbrñ3$4C‚’S%¢c²ÂsÒ5âDƒT“ &6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ûAÓo¢‡Ç<7‰éÔéâk)n£rM ðÈ‚¥²AZ†úFù"7P¦cåâvù`ä•ÁHØt=F V¤š1`¤ìkã’ ¬I’Q­È‘·ê„4¯ÅŽûwÉlIb:¯ž<¿£Ìmîï+84ha£þU6~§§ïNŸ~eøžž/'‡zÿÑû?JíÔöÏ §¨Qy?Ö=°ˆq-Òš„j{d¼&aÆpJ‘Jt"˜øtŽ0UÔ‡nÛŒ ;@ÞÚ ˆšbJƒÄѨ|ù +|µ=ໞYâäÈbBÿ!%OßÇ,ˆÅÖý̼IŽTôk+[-:Ö+ e¶´€)þQ«îNç!–|g•À§šÝNÊ=NÂæÍ¶€PžÌ7ÊÄD½'«!#a…i¾\’ݽ;‹vJÕÆÿÛ˜Ù#,G„¹-€©Ï ·¨J/çŽÚ9îfqP!yôEI9|HËY²h>Ró'æšõKébÐIÓlQˆÒž«Ýœƒ×Àe>)ŸZr#†1çºqå_>y¢Öîõ‹‡¾µ”"L`R¬v÷ȆíÄ%ÈSé›I–EŠhÛœR…daЩfA ‹ØZ¨=5µ„ 1€{|ˆ34›jzïNMïí<™†¸5 ‘ZW·Ë5µŒ¬ k-©­ð9$.ãN„ø}H%A]ÈÔøø×#JÿÿÔûCÉ)Øðzz…zt ôÉÄð›Ô‹K­´}Ní ¿U”±fŽZ”ÿ`À~'›<ûÆ\'¸Ý|ý+Ò†ÄZ'è«`¾¤«xÊ(!ŒÛ“56ÄiñBbRÉ]"þò@jñrO¯4*³Ü¹øª±<@Ø|€ðrä–Be.e”ˆ ª@?>”Ê:3s1 Ü.ʵýXlõE!Üo°&§¬ z×åŠUÐöë¡} 4ðÚ¸ÄyªrRO]öOL<;Õ£‰ÿÕû8ÀÖ£®x]½B“G^„×¹Ä*€·]Ù¶5ÛÄâ(VH _‰ºøòDŒx‚6ªc¢€6##Í’Ÿ¨T|@úâ`–ê\ñ=ÎB’ºª*¤×ß TJT{cJ»wQ·l•*àkþKxd$ÛÔoô`WÿÖû=Q×–xSÔ/$q$liÓÙRnK‹}Q»³¡º†mÁb4ö­r2‘$&1âºf‡æhîª5;É®9 $2HÅ¢„Ҟ؀@«t¢9=âÔ¹†'‘x4ˆ®ÉàXTŒÈɵ*Ƈ®ô4Êì³RcÇzn{âÔL½‡\°´&жþq¯õ–”¯Ñ€Á"j«)$PŽ»ä¦V¦%#š’y)‘¥ÿ×û;ÐPÇ<*Þ¡PPûõÄ«¤U(A^JÀ†SЂ(AƃanöÑGéÃaF¯Ùgäƒè¥Oß™~.!¿þý¿$LõTS#3™$¶ÔÙ‹“'¾¬€¦…jFÕ4`½ÇÏä”5Á"ƒ¹é’Ç»0/8ùÂÇÊvB{ Ó\KQmj†!jeEz岘€óc—Ïòþsù¦æê–‘Ckk_†10»1©ÊŒæz·Œ1Ròoæ<úÄñXêð¤rÌBÅs*9”“JøŒÌA©5Ï«dа'¥wtã³Tdô–µíN™ŽÜÿÿÐû4ÊÛýÆxCÔ¶ŒAZ‘Ö§$‚¨O&@¯°Û¯øTo@r*´ÍU AÔø{âW§A×®ˆC¼m+- Fãl³c7Ë¿™¶7:šeˆ‚ÖÖ¡bDë@?‰9‹’w77 ÆK,ŠF›uðË,Ä0 [!‡Ë2YÜE…Ò}[.Òi½1!ñ#¾lqJñ‚]|ÅJ“~'Óú2¾­ÿÑû9-üNxCÔ0/2k^e°Ôôû- F‹QŠxÚ{¹¦vP[øþÖÕ©öÆy죌˫?µvx‘ =t=A"´>ã$Fì¹A¹p¶ pU vß׆Q€ì—râ4à ‡™yÃËku¨&«lÞµåw*àSìrYôüQãÇËöì«ÒQZF†„§«â‚”¨Úž,Àã2<7»q¡»'m®\E|˜ìÔO†CI£žLüÞÏö°É©ˆ”ÏÒŠâ´‚ºˆÃÿ7ÄŸ¦™¸ÍÁÃCo–ßo7w=U9ÓM©˜öÝOÿÒûy“§9/Ññîøôa>Ý^ÚêÜeÓL+È$ÔB|wäGß•œÚ~+ž;;ÝHú~‰G-}[{•'ŸP–)¾©d–Öá}麻ñïSÊ´ñ É㙜%áDF5½o*ëw¿¾€ b ÄI>idâÅá”§!ðÔeiÿÙqbs-src-3.3.1/examples/rule/0000755000175100017510000000000015232633614015270 5ustar runnerrunnerqbs-src-3.3.1/examples/rule/rule.qbs0000644000175100017510000000171415232633614016751 0ustar runnerrunnerimport qbs.TextFile Product { type: "txt_output" Group { name: "lorem_ipsum" files: "lorem_ipsum.txt" fileTags: "txt_input" } //![1] Rule { multiplex: false inputs: ["txt_input"] Artifact { filePath: input.fileName + ".out" fileTags: ["txt_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName + " from " + input.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(input.filePath); var content = file.readAll(); file.close() content = content.toUpperCase(); file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(content); file.close(); } return [cmd]; } } } qbs-src-3.3.1/examples/rule/lorem_ipsum.txt0000644000175100017510000000055215232633614020366 0ustar runnerrunnerLorem ipsum dolor sit amet, consectetur adipiscing elit. Integer accumsan laoreet magna vitae elementum. Duis semper ex pellentesque nibh ullamcorper lacinia. Suspendisse sed diam magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In id maximus turpis, mattis commodo mauris. Sed bibendum accumsan leo. Nulla placerat. qbs-src-3.3.1/examples/cocoa-application/0000755000175100017510000000000015232633614017706 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-application/dmg.qbs0000644000175100017510000000655315232633614021175 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ AppleApplicationDiskImage { condition: qbs.targetOS.contains("macos") name: "Cocoa Application DMG" targetName: "cocoa-application-" + version version: "1.0" builtByDefault: false Depends { name: "Cocoa Application" } Depends { name: "ib" } files: [ "CocoaApplication/dmg.iconset", "CocoaApplication/en_US.lproj/LICENSE", ] // set to false to use a solid-color background (see dmg.backgroundColor below) property bool useImageBackground: true Group { condition: useImageBackground files: ["CocoaApplication/background*"] } dmg.backgroundColor: "#41cd52" dmg.badgeVolumeIcon: true dmg.iconPositions: [ {"x": 200, "y": 200, "path": "Cocoa Application.app"}, {"x": 400, "y": 200, "path": "Applications"} ] dmg.windowX: 420 dmg.windowY: 250 dmg.windowWidth: 600 dmg.windowHeight: 422 // this *includes* the macOS title bar height of 22 dmg.iconSize: 64 } qbs-src-3.3.1/examples/cocoa-application/CocoaApplication.xcodeproj/0000755000175100017510000000000015232633614025112 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-application/CocoaApplication.xcodeproj/project.pbxproj0000644000175100017510000003450715232633614030177 0ustar runnerrunner// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14ABF7A61717761200140DA2 /* Cocoa.framework */; }; 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7AF1717761200140DA2 /* InfoPlist.strings */; }; 14ABF7B31717761200140DA2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B21717761200140DA2 /* main.m */; }; 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7B51717761200140DA2 /* Credits.rtf */; }; 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B91717761200140DA2 /* AppDelegate.m */; }; 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7BB1717761300140DA2 /* MainMenu.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14ABF7A31717761200140DA2 /* Cocoa Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14ABF7A61717761200140DA2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 14ABF7A91717761200140DA2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 14ABF7AA1717761200140DA2 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 14ABF7AB1717761200140DA2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaApplication-Info.plist"; sourceTree = ""; }; 14ABF7B01717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14ABF7B21717761200140DA2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaApplication-Prefix.pch"; sourceTree = ""; }; 14ABF7B61717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 14ABF7B81717761200140DA2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14ABF7B91717761200140DA2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14ABF7BC1717761300140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14ABF7A01717761200140DA2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14ABF79A1717761200140DA2 = { isa = PBXGroup; children = ( 14ABF7AC1717761200140DA2 /* CocoaApplication */, 14ABF7A51717761200140DA2 /* Frameworks */, 14ABF7A41717761200140DA2 /* Products */, ); sourceTree = ""; }; 14ABF7A41717761200140DA2 /* Products */ = { isa = PBXGroup; children = ( 14ABF7A31717761200140DA2 /* Cocoa Application.app */, ); name = Products; sourceTree = ""; }; 14ABF7A51717761200140DA2 /* Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A61717761200140DA2 /* Cocoa.framework */, 14ABF7A81717761200140DA2 /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; 14ABF7A81717761200140DA2 /* Other Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A91717761200140DA2 /* AppKit.framework */, 14ABF7AA1717761200140DA2 /* CoreData.framework */, 14ABF7AB1717761200140DA2 /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; 14ABF7AC1717761200140DA2 /* CocoaApplication */ = { isa = PBXGroup; children = ( 14ABF7B81717761200140DA2 /* AppDelegate.h */, 14ABF7B91717761200140DA2 /* AppDelegate.m */, 14ABF7BB1717761300140DA2 /* MainMenu.xib */, 14ABF7AD1717761200140DA2 /* Supporting Files */, ); path = CocoaApplication; sourceTree = ""; }; 14ABF7AD1717761200140DA2 /* Supporting Files */ = { isa = PBXGroup; children = ( 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */, 14ABF7AF1717761200140DA2 /* InfoPlist.strings */, 14ABF7B21717761200140DA2 /* main.m */, 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */, 14ABF7B51717761200140DA2 /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14ABF7A21717761200140DA2 /* Cocoa Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */; buildPhases = ( 14ABF79F1717761200140DA2 /* Sources */, 14ABF7A01717761200140DA2 /* Frameworks */, 14ABF7A11717761200140DA2 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Application"; productName = CocoaApplication; productReference = 14ABF7A31717761200140DA2 /* Cocoa Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14ABF79B1717761200140DA2 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Petroules Corporation"; }; buildConfigurationList = 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 14ABF79A1717761200140DA2; productRefGroup = 14ABF7A41717761200140DA2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14ABF7A21717761200140DA2 /* Cocoa Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14ABF7A11717761200140DA2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */, 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */, 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14ABF79F1717761200140DA2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B31717761200140DA2 /* main.m in Sources */, 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14ABF7AF1717761200140DA2 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14ABF7B01717761200140DA2 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14ABF7B51717761200140DA2 /* Credits.rtf */ = { isa = PBXVariantGroup; children = ( 14ABF7B61717761200140DA2 /* en */, ); name = Credits.rtf; sourceTree = ""; }; 14ABF7BB1717761300140DA2 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( 14ABF7BC1717761300140DA2 /* en */, ); name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14ABF7BE1717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 14ABF7BF1717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; SDKROOT = macosx; }; name = Release; }; 14ABF7C11717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14ABF7C21717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7BE1717761300140DA2 /* Debug */, 14ABF7BF1717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7C11717761300140DA2 /* Debug */, 14ABF7C21717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14ABF79B1717761200140DA2 /* Project object */; } qbs-src-3.3.1/examples/cocoa-application/app.qbs0000644000175100017510000000745215232633614021205 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.Utilities CppApplication { Depends { condition: product.condition; name: "ib" } condition: qbs.targetOS.contains("macos") name: "Cocoa Application" cpp.useObjcPrecompiledHeader: true cpp.minimumMacosVersion: "10.8" cpp.frameworks: ["Cocoa"] Group { prefix: "CocoaApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaApplication-Info.plist", "CocoaApplication.xcassets", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaApplication/en.lproj/" files: [ "Credits.rtf", "InfoPlist.strings", "MainMenu.xib" ] } Group { name: "Xcode Project" files: [ "CocoaApplication.xcodeproj/project.pbxproj" ] } Group { files: ["CocoaApplication/CocoaApplication-Prefix.pch"] fileTags: ["objc_pch_src"] } Group { fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installDir: "Applications" qbs.installSourceBase: product.destinationDirectory } ib.appIconName: "AppIcon" Properties { // codesign module only present starting from 1.19 condition: Utilities.versionCompare(qbs.version, "1.19") >= 0 codesign.enableCodeSigning: true codesign.signingType: "ad-hoc" } } qbs-src-3.3.1/examples/cocoa-application/cocoa-application.qbs0000644000175100017510000000517615232633614024013 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.Utilities Project { references: [ "app.qbs" ] SubProject { condition: Utilities.versionCompare(qbs.version, "1.9") >= 0 filePath: "dmg.qbs" } } qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/0000755000175100017510000000000015232633614023116 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en.lproj/0000755000175100017510000000000015232633614024645 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en.lproj/MainMenu.xib0000644000175100017510000113401715232633614027071 0ustar runnerrunner 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu CocoaApplication 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: CocoaApplication About CocoaApplication 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide CocoaApplication h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit CocoaApplication q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help CocoaApplication Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 CocoaApplication NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en.lproj/InfoPlist.strings0000644000175100017510000000005415232633614030166 0ustar runnerrunner/* Localized versions of Info.plist keys */ qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en.lproj/Credits.rtf0000644000175100017510000000070315232633614026757 0ustar runnerrunner{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE0000644000175100017510000000275315232633614025661 0ustar runnerrunnerCopyright (C) 2017 The Qt Company Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/background@2x.png0000644000175100017510000065077415232633614026340 0ustar runnerrunner‰PNG  IHDR° 3à›sRGB®Îé pHYs%%IR$ð@IDATxìÝÙ²9’jfn™•ê÷9jUU×ЭáEZêIÃ¥.dÆ ]èe¦çè£Êdfÿbý;Hµt¤žLUå c#p8Àá¾ÿgÿé¿ý—Ÿžž^üðÃ/>|ÿý‹§Ï?ñã?¾øaçŸÏñý¤£ûâ‹/çŸ}öYÒš×û÷ï_¼øìÅ‹¾ÿáÅËW¯Âç󡓇^ï[ÊKS÷œ¼ðïûß¿xóæMÒ¿ÿáû?þðcähy±r-Ûsõã•0õ©[½=¤kÇ÷s4Ï9É”ÓN² ¥½š¶_ýõ‹×¯_?Ú¿><§½|9íÿ>¼ôWó•ÿ|èÕKN2+‡_e–özÚýî»ï¦ÿ^¦ÝÊ h>ú|d=å•S¾²é§wß½Kÿéÿ†—#ö+WþÒîýßû¿óç?]±úÿŒƒÕÿ»þwÝõí¿µÿŽ/À~dÛ²Yk7¯ýÿù‹§µÿ×ÿ[ÿoýÿëÿfqá Ö !¾Å¬ Öiÿ§øÏÓOÿì—o-@eìüå,Wîà†s•´òW¯ÐœHå‚8¼\_é¤)H"þìó”†f(™sñS/þç„ ªlŸMº2®´o¾x“kçxGŽ!z7:M¹«ÓRðúÓ´ð“?íÂyåéÜÂ|o£<} ] ê?þðâõ«×` xÕ:Ò/W¿¡—î¨ç|he.miŸ«¼½+WàL>o˜¼xõòUÚðå—_ÜúnÀ°<´!†Æ$ºn½Î÷þïýßùtŠy±óÿYçV÷ЫÿWÿw·¶X‹²–LÜô]ÿ¯~Ùõ?6ÆÚkÿ­ý¿öÿúëÿ­ÿ¿þ?âï‚ÿ<ý³ À²C‡£&f„A ² €¦ K˜—O‡¶†kË@jÐJ<ÉÿþûÙ¡4€ ¾——ÝCÛi¤ÞîŠÂ³¡à ™šŽöÃð)“Vž©kò€J”ä£l™]iÚðÚ:x—¿rhì³ãIºþ‘î¼}੬s£trÝÛö¨ghb¼}vhR>RŽŒSNPÿQx^ü*ËsÒ>; Êéùh+£tO‹ÉóúÍ×”«C~S{±÷ïç°ñÔq´óç?€þ®÷èŽÕÿ?æá€¾XýÖ¬%»þ?lc#aâ]ÿ×þû|í¿ØwùÕÚÿQt'›kíÿg?OÇè“„‰Ù ‚¾Zÿïø’úb:iý¿ËîÐëÿŸ±ñ»îÿ?ýá¿ùÅ[ Œ¶EÜ $.µ‘‰Ñ'ªÒ->ÂÃ8›ó:»›WZ>çX~&Ü”¡ŒÞ½{ÐÊ,Ðe÷’ ùzäºï.R<ñÇÇ<éM ³IC—Á<纤IŸC=WÆ£½'áÐ:ÇÿÓEE_I×oo²ó øFf€¹°ÊKõ«HÚÓçgÇ—¾!c ÔfòÛ>iäe]¹¦N×ݹþ­úíÀÂÊùîý»<ïöwéxîýŸ›{Ð~«„öåÞÿó_?Æ®ù“³3®åë3qóJ»óÿôáÎÿÕÿ«ÿÏZOOìú?àø®ÿÙo)Yûïzp»ößÚÿkÿ¯ÿ7>ZíîõÿÖÿ_ÿÿcü';°+ 0ƒQ (ªÚ „&“èrT7­ñÓËçïiHtY<{-Æ÷¤{¥ðÔŸô©Çßr"ü[#'t“^Þ¹~@iCü0 -Ÿ‚ó .?N=–Ð48Woù…çdJ×O÷à[]©ôÚÖ×°Ê×N+4ò‡r~’ÚN²OMᙺÐÜä”Qy´/‡~i Zyð³+îÔy^Cì½I%½ÿí½Ó§{ÿ¯y6ãU0~Œ»Ž-çMk¼óÿèŸÿç)©qcœ˜K«ÿWÿw<ˆÍ‘3.výï¡G­×óG[c®wý_û¯vªqa¼$ž?ÆŒcí¿gûÛ*0œÙtõQ:mþ迵ÿÛg ­ýt®^1ŸÖþ_û¿þ|õ­q±þÿÁ/ô‰þ¸ÇÿØþߨן™´ÞM?;ŠÞ$6 (œ¡| ª<5G^€ÆµéŽÜo6Þ„2>îÞÃþ»o¿ hæ5·/çƒç©kþ|õÕW³«ixZ¬Éq$"7PÆÇÛK’m¥Ê£ÁÿMÒs˜<ùŸÍŽ&|Ñëç6©€&Ö‘c8¢úM)mµ£IÐ/>-«½ú }rÝp4òí:#¯éâç­—¼ »º¤Wæö2{ÿ;&Îýë=ïý?£ÊXÞù¿óß8ˆÎ¹tÑ!mõÿêÿ¬9G]|dìíú >]³ëÿÚkÿ­:ÿ×þ_ûŸM¹þßø„ëÿ­ÿÙNÖÿÿ_à??ÿË?~ËàôtÜ«{›<ÉǤà†I‡e€›¼Þ§ggá¦ÈkàÐôºÎÍÝÑ)”p”üÚ!4 ˜0'<±—-s“7¹q˜1¿’~l¨?z®Çÿëÿÿbýÿ¿=þóô³?ÿÕ[*íFüºȼOÈNP@H•¾bçõ=Xòñ@Mò´Á3`Ëüa~ÝøÄ)ãù£²êÀ«AÙOƒüÈ9S~áp9”HÊOº¶¡q]ž)sñNÛ§L'[u‹RÚ7¯Ez5&;½Ì»¡Ð;r=ÿ\“K^ÚzÆìÀb œBÛúÈô)o¯þUÖòÔ†{žc«<]+'06^îWSÇ\ÛMN Ç\„nïÿp÷þïüßùÿlÑÑW­þ_ýo\ø'ìú¿ël‘ˮȠ˜?ì#:£6[mí¿³kí¿ ìê‰îc§¶zÇPíÙ^‹ÑÇ>^û?nÔÚÿëÿÕNë|YÿoýÿßUÿÿé§`ðì1¤ Mã2Xð%ƪóY<üS â: à„Q{ñŽ8§\»àô:ü/^ê+ø$? ÊÅ7õ#¸B¯÷Û+Y‡_; º; ?AºÃµÝ[‚Wëœ[0+kë÷Ë‚ò…×ÇÚÃwxÔ #C xíר„ou;wÌšX~ò….â• &ÝŽ,¡t¹˜?è}U±ùm3:ÆdÞ«:ùèõϵÁÞúš>îÓüKÛœ]î|â½ÿúvïÿ´Ææ5ŸÎ©ÿ;ÿéŒê¢:nèógÆMðÕÿ«ÿéÔ¬33nî¡ã¥ñ®ÿ§wvýŸñ2]AǬý÷ü¸:×(Yûoíÿµÿ×ÿ³VX?×ÿ[ÿßúÀ>¿Æ„ë¦ÇÎb§Ï¿ÿ›üÿ§Ÿýå¯ßôx„¯Q(nBÓ`Î.”È{ì‹®´²úAte}ï@ ‚nÎ2u^’>iœ‡Wõä;†écráÖÑúÊ×uCÏÅê@ -#.²ÛA ®Ô?¯ ÖÉ&‹sáÞ®ËÃy·(Ã{xiCvlMýéƒ C/H‹<ÓêuÞ´¶ïP^]=ùBèæ\¬ôBø]yç|êHÎùsÏ7]“™¬‚ëùó¸ŸM»·ýܽÉÙûÿè÷½ÿg/í»ôÕØ£ëÿeèdÌèÇúGXÿÿ·ßÿúù_üúm@èÀÆÇ Ô]!˜ 17€&Á;Îb“ô HÁ‹ž“‘ sYÐb´Üé”Ëvlj=‰|0X¡+ÜåqÞ£ùâc¡8ùø$\´çâÈ¥þVä(èä\z&:™æôt7¥ êV?Àk“ö¤ÍóÊ¡ å…¤L™†»ì©Ê¼»b2Ô”_úÆm'ŽMk¬íêÊû9oä¹õ‡üƒvíýïØÝûÿñÜ2v2–΀Êx‘ ùc'kç¿~¡K„ÿÓôË„Ž!sKÐ7÷¼Õÿ«ÿwý?±¥Wwý?z"ÊâúS"¾wšÚEkÿ­ý·öÿÚÿÑ —¾¨ž ;Øt¬óøH>3¾šóµÿŸõ«>ÓGBtëå/J[ûÿôÓúÿgÕ5w:‡Œ—έž‹ÿ>íÿ'¿B'bê¯ÓÕÁª²OCÁ’¤Ô×`NÙ¹Vö^ï^[L”¯Sw>.~¢7c´Å‰)àsë Ý#¯¼Ä®óáñaZƒ/mÚæ{ýOZÁ°ò/Ÿ(*ù@)ò]|Å”äͯ&Îd×Ñ1Œôš:c“ÐidC‡äœ|¥ðu¤/&–W™‡ûä$k]‰¯z‡IòÅw¾x”úòoZó½b(%y{ÿÓúCŸ‰÷vïÆJÆË5f’0}46ƒèÒs­ß ÆV¯wþïü72Vÿ¯þ§cwýßõß8p¬ýwìIëfVÏYC×þ{v†Öþ×3F±¹Öþ§7Öÿ[ÿÂ\ÿÿø]õï£,æ9rOëùïŠÿÿ2Æ0c4cãÕòžs>ïç²)ч‹:äüûù'®[gõnœÈsí( gൎžspÊí§õËkð‹i -ãZü^Îkx4H¿óó á»wï7Ú+a>°î咞º×áü½ïIMÿµ]•M¾«¥¬[òåµ¾²³kþÝe*ïµóZ¬Nþù÷™ô ŒœaœòÊ9>åuïÃjÔž~2˜÷þ§ßöþgH|4†îãIîÎÿ£̵ÿ«ÿWÿïú¿ëÿÚµñ¬‘kÿ‡Õú„Í[»·ódíÿËWZûÿá³tŒ¬ÿwìËõÿ>~ÀS¿¸1=»þÿï·ÿ?ï½£fÂÌÿ,ÀÐ"½¡¬¸‡¼€%” „|öã™|V¾±4N0‹ÓÛ×áºx½zùjÀ÷ç5¿‹ŠL Ï=®‘P3ÿ¾Ÿ«—Ž<§ ³óiÒ[tJ±¼Ébw”tuõ—´YÒ|äÒÑŸ·l›[Oå@«µ^»l¦Þð0Ìî­ìþò}¯É«óŸ²sÝ]]å‰Ï½žÓ›÷«>L”¿‡–—ž>¸â€]­º…æGžéï½ÿ¯26öþ±óçÿÿD·TÞuMôÕÿG±Î_:uõÿ1,wýßõß|Xûo²®ý·öÿÌ…µÿÏúhÁ\ÿoý¿õÿ¸_›Ú¼XÿÿÿyúéŸýòm£tÞ(Ùv ë»Óâm;›q’2ãÀJj°*OQ¬Ð‹½Žå0¤@)@ÊÀ'ø1úÅòò”±Ã„wëB¯Ž¡WQå`()çäßò-ÂϳãJ¹ü 8XêjPC^åO{®b=OeW}­÷Í›7‡ßiè€dê"oë&“ó–SïãÅ)weÌN+ «K.±r}Íí~ü7í½êìÇÆQƒL<Ä ênÿI«œ[F^ûýÞÿÓWí³½ÿ;ÿ£Ovþ¯þýºú×ÿ]ÿ×þƒ*vSí©µÿÖþ7j7²ë×þ_ÿ/ã¡~ÙŒõÿÖÿ_ÿÿàÁo`3/žþÙX&K>R â¼6gaEøùÓ ‡LZ_å>Ÿë÷òôûYh”…µ Í÷£f›,àC^¬‰ûŠavI¡¿<…Ö‘ÝQØ©¤<ÀF^/çx+OñKw­n´Ê4<Út¥)+¿<œ?}~ý* ~s­ŒÐ²bôAû È÷4åÈñj€/éÚàuÂòÒ#ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô×.°×¯^çUIiÀ&2µöþŸñµ÷çæÜ5ïœ b:E|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿÿÉGÜ9e×à.`¦ÀÆ÷;^Îáu‘î \1Ô¤qì@Ó\ã'OüþÝyEðl:Î Þ@‹¼²CÀ«uŠ•w@õµô݉¼Ÿ£+¡£8ÈZ9Ð 54ÃÀ9Äj'¼€^“îÚáZz1<€zv„ @ —O/Ó4ê¥ÞÒN;¾ûöÛìäd½~ý*‚Vö0"ßÔSùWîÐÜþd·›þ™2µah”m»ÅÚAN1~þµMuÊ÷þïýÏð2žnaçÿÎÿÕÿ«ÿwý?ƨÆ]ÿǾ[û/«äÚkÿ¯ý¿þ?jý¿Ûf’ñ;ùšëÿcýÿ). ÆÂ ‹øûÀž~ö¿~Pã <®§¢ûw«^ÍÀäР)˜••üʹïèH€+ ¤(W€­ôy(0ËVŽF+ë(m ÌŸ^‹ Þ8÷õ¦¡-]ùX| ìÈÏù Æ/çû\MG+àËx¨ì:k]n†Pþ÷vIwMɉñm~ÛÒr•ëÓ8¼oü] Êù'DN}@€­¼å‘>Yå“#<¦Üx”©<{ÿÏxÕ‡újïÿÎÿÿ«ÿWÿïú¿ëÿù„µQ`×kÿ}l×ê¶ÃÚǯÝÙ~ µ9×þ?v¸~ê‘þ¹õ‘kaíÿç~hÜ}šõÿŽo¸þßÁ:æš[ëÿÿvûÿy…0nžÙoá 0çUâ*Ñ(Ë:òQNÀðcÊ™eBÏeÌ´¼²ùÙì X±˜7à/¿uY@FxwÀáßzJ[Ôiø {R“vÏë9Z48±_*T¡s2ˆÉïÛW¾Uù>­Wˆ¼”uŒ0þÂçj[_ñ“ÿnvCá%ˆïÇIÌߤßûþ΄Š\­Ïë“î_cZû¨U9[Ú62‘Fy×{ÿ÷þWƈø>¥íü?:fçÿêÿÕÿ»þ[k»®v=î÷?³¾ŽÎÜõí?ãÄøXûo¾]²ö¿áð‘í_›<Æø•w·½Œê—µÿ Ì'l?ê+6™£iåõ<6ìЬÿ7>ßôKýøõÿÖÿÏ<0€žùmðÿžþðßüâmçY”b&ùhÐ*K M'¿óLþKiÄH3¦­ù¡Vx8§P”;ËDók…å…<çí¬GÇ ½´¼Â7%Ñâ%M·>1!*çd†Fk^^ %îåD¶‘åÃûùPüЬ’M=5@Û.ù•UYçò¨# uª‡ì↓“_Kôjâ¼’YÞÊ´=•ýÓ´^‹[gËTñG›û²é®„òLÿLЏýˆ@¾#ü¦ü\¤œ]­K™;´ùUEü¦mý–YûI~è÷þ§öþïüßù¿úõÿ®ÿvïîú¿ößÚkÿ×'ª-_Ûõ=­×âÚäÍ_ûÿø£ñoÖÿ[ÿïò_ùÂÂúÿÇŸÿ]öÿŸ~úç¿zëfW)ö¼ŠÓµÐü(Z¤àÇäP® ^±VQÒA·¦Ã/Õ5ÈZN¾s¯¹å›WøŽÁçÛLŒ¾C—w0*e"Ïáëfq0dlh{ÚéÊ},ß?ß®z¯G*ç[Uv3…F[3Ê ÉùÆ–ôÔ%+rœ:ÕSð§mC›¾™²‡üšhøÏQÙ£Qÿ§A~iÂIÙ!j¡o¹€ÿö‹ºBù4nÚ½Ž¦‰SîjgdvŸ®C¾°÷ÿôëÞÿÿ™#3_¢Gvþá/2¡zоq¾úÿY'ßû'uý¹ëæÕÿçIa—ç]ÿÏ é¼ÚõÿôG猸!:yí¿tǽ_þ¦¾jþÚgôè;xÖþ_ûý¿3ªW×ÿ[ÿ^üÇÀž~>ßÀ2ð1NÄF„QÒ@ =ÃPx˜š`Q‹àâE\K ¡}\O¾óGšòW=]0±éBé¯ò‘!õOCÓK™¦ ‚sï@§ms­~A¡õ~? 8ôW{~¡@Í¿Ï}H~øµŒ<|í´úp_ò•S<€ðMî)¼~´ðá# »éÒ>J¶¹y^D£s]™”éyŸÎT–¤§ç ¨°N%>IÙiëÞÿ3Þ÷þgpîüßù±úõ¿u*ëímýÌú"ãZ³\g Ûõ×ÿ'ñpÙÆOÒfȬý·öÕQ›µçbaíÿÓy:}Ng­ýß¾˜xý¿õÿø®ëÿÜ ºô÷Åÿú£¿üã·@ èi PJbÒ9ò”D לôÒB;çÒ&‚Á$ßn&ç‚k4ás•‡ËxÐ.«–-_ÀÓ£,º¹–§¾ÖÕºïe[—ø‘~ɯ|ŽÉS·ò}°mRNP6 €h®[Wå_€ O×òå"ë”ô}-e½¦èu;t}• Ä×4­CÙ„©8¼Û?CsߦÂ,Ó§BŒÂ‹ßÓ‚»|xö¾Jwíèî‡ÈÙ.÷mh÷þŸq¨ßöþïüPgŽÎxØù¿úŸÚ\ý¿ëÖÓ]ÿŸm¸±%Öþ[û/väÚÿÛÖ aíÿc;ЛÆÈúÅúæ?֘Ț:¾íúÿÇg_ÿÆ‚_!4Q|ÿ©¿\—3àH ŽÄ—bñjŽë *€Bsè¥ß•±k£>Ý8{Êù by‚:EB?}®Î_<ñØšøNl¹Ë>pÕ_MœÂ™òêdtˆñ6QÈD:÷ ­w*Dê6‘êk»ÈL/‡>ÍÇ]€j=À«¼¶xÕÕòœd(1¤•o®§^}Ø4t•ŸLvf_H;ߪBÛ:Ð$¨ËÉÞÿGÿíý?£ÝwÎ̃ö‡ñí|çÿqÎÍ¥ÿGë:jõÿê:ÃXè:æÚÑun2vý÷ÚÚô}Ú~éÚÜ~sí@#M°ÆçzæÛ®ÿkÿuL'kÿ­ýOO¬ýlsƒ®t¬ÿ÷ vŒèkñúgHõ§ñÂ^Yÿÿ·Ãÿ{úÅ_ýÉ[c¹ F8ƒiç1˜\_4v òj`¡±ÓXãp­<# 4ùÒα²­ó¸ÌÏÉdÚ¡W¢õ(_ÃÃèÖ]IM¿Ç•_ŒOCëvÝÁ+6xÉ«4Î_½òÔ¾OÝú$ånä"Ï£Ìðéýl¤ÝS–üÎÛØ )½¼ÊYöþ§§õÉÞÿÿæÏÎÿÕÿ«ÿwýßõí?ÆÁÚÇv_û^£]ûý¿±ëwÅy¸þð!â­ÿ·þÿŒ‘øñë c£~7¼âáËßqÕr·ôßEÿÿ`i§]í¬@=×D2™ú½¥tàжƒÒ?é¬qVæ_À¨gœ(¯Ðõ;P´RÀü|ÞQÕ:?ŠOý™àC;w-ƒ™,–A´dñúá£Ü\Kkˆ¬®/ZéhÄŒrèµü*7Y¹Ò8ïk†Ò¾ýöÛ F)àæ‹/¾@U¬ƒ„ŒÒZ‡²œÇ˜û“9»Ï¦Ðù¥ÆT%æûT#ëazJÃK‹¯Ô“54íu•¿ó¤»K¾/6õºnØû~©Q¿è«öÝÞÿÿæ«ñ°ó?~õÿêÿçµ#ëÍ®ÿÖÒ]ÿMS›Â'Öþ;öåÚtÄ æŠ5UüéÁžM¸ì°!Xûº`íÿÆK¢õÿ>ŠþÈ„9:ŸêǬÿwÆŠÞÑ7í·^SÒ„õÿ/ì@gÀ%èÞ9þoÅž~>ßÀrSï!€üs:JpeÊt¢d@Ìõ‰g \ü²] Ú€3W§¨Ñu°Oeh]Ò³]~be*‹4õ©£ƒO^ó•Ký“ßÖ׋xϲ{Ñk‚ýV`Ê ®±¡ ž¨Þ¼yó‘ J;.yÐyÍ ´Bd¹hÐ÷5,Oç r…ð¢ S§zŸ²Èºx=÷ÞèÓ¦‘Á9Y\kCû&ù“ö~Úç£õŸæµ~qh'Þû?;÷þg,ÞÇÇÎÿg{çõ~ãÕÿ«ÿÏŠ»ëÿ®ÿÛ„=rÙ5c`Ä&[ûoí¿µÿÏCîÚWlos¦¾ÌÚÿëÿƒ—ëÿ­ÿOM\P®8ß¿žóß'ÿÿe@’[(Î*MÊ40á]ÐvT”ëäM ¹?@P¢!„~Ä89&ìyÅ®OZ’?埕´oêÌ7.>Ò{”ç]¦ò&_e9¸é¹™Mo”g( áuRW­‚øq |6ímyeüúàppðÇnœ¯¾ú* Êu/<-ÈÚ ˜ÉÃÏ–áa”€F>ðìÓ€V™)Ô3òM Ú¡Mô&¶i“€ÎY—‰k¸¥qþÃÈëú>È+cúçâ·÷_¯îýßù¿óŸ^ˆ#¬þ_ý¿ëÿ·y×ÿç…ìv -q4ÅÚµ­Öþ›qÙ–Öç„­ýŸ%õñG߬ýÿ¬Sî>Iu‹ÎÊšxý¿õÿŒãD¸Û©Ö éëÿŸ¾ù]ôÿŸ~:qèâæÏOÆ uXœgÜbiÂ&×à“ôÓé¬;MÁй úCQO ê/MËMóÿy‘ú7÷òw:pï1^º6$ç'5uº4)ggC°T>¯¤2òï¢ûî»ï^|ù“Ÿ„oËjµ¾ »°®]Nøãé×ZMúëÙ™åƒÇ1~dø§ŽéðÉ€›:È0¤ä§§'v.„ÇõXi¡¾ úŽ ¹ÏSh§m{ÿ÷þ#;ÿwþôHuÊêÿÕÿ]ÛžW’ÇHÆŒÕ(ÏTG]ÛwýŸ‡V»þG·Ð/Æ«ií¿µÿª#ºþÌ"4ÿ×þç_4¬ý¿þß(Ïõÿn¾íÃN½Ò\÷xÌ>ðeȲIN8›8\ׇ_ÿÿGxôët–«puÞG>‚´è¦tmû÷ÙF¬nÿ‡°ÿž~öç¿zKX7²õWòšf1AüJ/v( 9×Ïï¹+ßmmδ=Gß­€É¼ÿ™<=‡^¨,ÊËëžf@–^ìXã.DÆêÚÆ\“#Æ”]Yó¡õ)ã:QÆdD/´¾ùæ›_~ùå£=½Ê­þBÌj=ÿuˆm™2®çâIo}§ü´aò€NÕ¦]d“§DxMÛR‡òsdœ|4çÒ§ŠðKùáÙºÚ7øIS'š½ÿ{ÿgHñv‰Œ«#;ÿè½óõ¿9"¬þßõ×ÿc?Ä®™9¡?zníXûoí¿Ø˜Ñ˜·?36Öþ?¾•yr޵ÿõƒÐ¸ºäž¶þ_¦Îú×Z³þÿï®ÿÿøEŸA ªÊà®jxPÎçÉ}r 8ÇfJ“…éR¾å%M~¯[FQ<úDN^è§š ÈáñPX žyùÅÃI|\x3¥þ{|XT;¼ ˆ?z`“W¥·NiÚ2õ8íEh¿ûö»¯_¿ž]U¯r¶äK;2?ƒø©CzꙜv‘®ã+/ØÒÐ ®˜'QúøÑw“ŽOË„çðÖ¶€S“¯®¢¢Ê9€ v5”_eÚû¿÷ß:&îcÅX”nÜìüßùo<Ð9«ÿWÿÓY»n:‚ž…ñ‘.éš“±s+£üY³výßõÿÙÖ1.„£kÖþ˺<ý!^ûoís#cbíÿôƒ5dý¿®¥³’Ìk®cý¿«¦ÌúÿӵŢ?Ænûmôÿ³‹Áä¸ÿ¼­×‰4¬  ‡U(¸ÓØn ©Î°+H°s© ÔXù%Bùʈm£W¦ QÊ\Ž1ú*¡È5×ʤŽËn]¶üáÙÐt2U>¼+_æÖ§tò©wÚ‰/Œå/<¡%ˆéå€_ÒìÀúbvdùp»WõAeS®?¾¾(ç×úÔ©È‚ö.Ã\„Fš lóÑ;ošó¶S\z»N¹ITãÞÿYüöþŸ±³ó?seçÿõzíêÿèÊÕÿçáN××]ÿwý¯}µößÚ͵ÿ×þ_ÿoý¿ø´ãú%Zçlñúÿëÿ³øVÅ$ŠYüŸâ?O¿ø·ÿü-ÐÃûævì|ÿá|¿ÉSu;“ùvu§Æ ô1ó¦Æà$! ¤Ô¸±ó‡ñOy¢‘_ ª þ~¸>tnÒ‡÷ó z©É—wä~Þ‚íƒÓyÝï*Y.:UúIz–uÎÛ‰`®›Ö]^zF^4y]hd2X¥?È÷íµûJ¿OÙÔ©Â viáÛ>‘†ß§rµ®¦çñÔ¯íbyÎ}ˆ¾¡ý/v('F§Nu§ÿ6>PŸþ¿½ÿ{ÿwþ›/;ÿç•çù·úÿèp»|«“Wÿÿ˜õn×ÿ]ÿ×þ[ûoíÿµÿù"ëÿ­ÿÇvŽÏ}ù§l¦úºëÿ¯ÿÿÿ<ýá¿þ£·WÏ^½|õ4(¤>mf´Œ€›:wö*®ÒÊ3ˆ{@Á[^êPHöȰLb Ò{¸V7p¨OzåÙyÕº†8 Rdz2£N}ÏÏ=]^Ö§ÒÚ^¼´E¾¸uºP6´&轜z¿þúë?™¼k·|ü^ÍñÍ×ç»Yß~ûmøµ, ËŽ7mT¿PYÛ—I»Ò+oehߢù4¨[H;®]5®SÏÔUÙ÷þ?ï’ÛûÆÅÎÿÿÕ_tÎêÿ³¾­þ÷MÉ]ÿ­¡]Ãk7X[wýÿøÚÚkÿÕFeë®ý¿ö¿5ôîÛ¬ÿ·þŸµ³¾­Xà‹­ÿ0=rïŸõÿ7ùOÿí¿Œí5ëÞ|ò¡òh»Œf ¶‚9íL->Ý:*¯tOæGè¾Kùu6t{%O(ñFçº Së²+j2Ì<üJ…»õÄgÿŽ'qO“ðÁ»íékŠÒð!?Ù•iŸ)']Yà:ôÿäŸü“Äú,rÎâ͘SîÝwïÂG¹¶“ ®ÕMÜʂבi^œ6 ×Îà{yt‚²} ÔwºÈ[º”“ðàѶ<Ê^m ;™öþïýßù¿óõÿêkK×­®)]/wýßõ?¶ÇØ'½Žm3¶ÄÚkÿ­ý¿ö?_£þŠsá~ݵeý¿õÿŒõÿ×ÿ7îøÏÓ?ýÓŸ¿e`œa¦ËRÆØ'¼ÿ0ßxzóEÎ)Jåó¡/ˆÂpµËý‡ ³FK• tŽîyÎ{„vêÂGÁï@ C¨²Ci¡>äq.½yÚ´Š,ó:HÂаO¥}È2i‚Äs¨·H:` ­×Ku¯=•Ÿ|À-Û'•!ûI›*_¼zý*×x¶]dÏéwAžºËoN’îOÒ&n¾4ç‚vÞÝKÙ¥ü|0ý JžÎRN=v1õÕÄt¨ºæh~TåÔIæÆèÉÕXŸxm0ßáºø÷‰ á•vÍk”Êôwø`›:œ—/ÚÞi=oß5͵£²§Ïn¼Ô+¿u ûˆöª]~ÙñVïÞÿ½ÿ;ÿwþÓ¯ôÊêÿ££õEõôê+Ç »þûb×ÿµÿ̈µÿÖþ_ûý¿ky\ÿo:býÿõÿ‹a˜li=í¤ýÿá?O¿œ¸[`ó tƒô|6¯¸ý;á‘?Û—ó {^!ú¼@«‚ d«L¨²†ÄW¨B‹ïy)øÉô÷”«{Šeð‡×\œVM {=ÀÞvŒ½|òý§pI#—¸ N˦ýS>ò\ùø£—'Ý9þÊçõ½¹Î®/5LšWv;©=‡¦Û¤Õ§þú¯ÿ:¯ʳ{Í®5}Ô'W耥§¿ÜÖ‚rŸtÏC Tþ¶ 2)MÀ“<òk›€FߥüœÛs´÷ÿŒ½ÿ"ùc íüßù¿úõÿ®ÿ»þ¯ýwìÁµÿÎkÿ¯ýÏg\ÿoý?ÃúÿëÿÿøÏgÿñ¿þçÇ$ xa7R Íœxà†ép úx=¯¿}7ßpš„¼=„`2ß|R`c‘Csçÿ„®ú8ÊhЪ?²L" Í=<øH#¿2t·—ëli½äÙY%¼ðƯØ‘¦.<Õjp-½ýAÎôÉ”_'nä½ê£Ô£ÜµãúPû_~ñÂw©ÔÛP¹]«ãÞWåQúÄ€¼kûzûHýÚ€lxœs:Ȩܣ¿®¾e„íý?Ÿ¾ßûæ~ÇpÇûÎÿÿtÒêÿ³®þßõ×ÿµÿèõÿΛw–ýàƒíkÿ¯ý¿þßñéÖÿ[ÿƲþÿñ1ÿ>ðŸìÀŠ1~½b x"¾À"×Y»u순‰Ó?´ "Àï>ùµtå‰/G( ã~Îu!1¾‚²ø ɿʓώ'ùø¥ÌðH}¯æXXŸ²ë©u–§kò’?íK-§N<‹òçÓWd “>rž6"¸êw`éÊsïoH~˜A¬“–ëKÎ) Tk»ÉSšÆxJ:‘‰ìBóå)O~çCthF|eÚ?Ê(¯œ´¾Ôk ×Þ½´÷ßøØù¿óõÿêÿ]ÿwý_ûoí¿ØÇ—íÉVlXûÿøìèµÿ×ÿ37ŒÇúÇ—âOÄ7¥Áuܯé’ú±ÎãË_ºFÙôå•οUÞ\[ÿÿ¹ß~_üÿ|Ë 1 ¡ƒR¦Cš&6`¤)××üÐ  ‹³c ÕùE_ïìúqÞ0ŠsôêìÂûÝûÙ=tÉÕ"Voüä;:°¥MÂ@5×d™ØyA¡äL¾§f‘Wþ9\ãoç“×üð~v©)3ùb“¦ôÊ8\“ƒœÊ5´å,ô~ùÏ+{ê$‹²Ù=¥þÊ€JÒq¸ÿºSùà}?¿÷±:OæUÂK†ÒÊÂwêä5TfmÐodÐïBúwbuISnïÿ/{ÿwþïü_ýO'®þßõ×ÿµÿjK±j­ý·öÿÚÿëÿ­ÿ·þÿúÿ7üçé§ñë· -çK ´¨3.®!Æ(·õÊçÛï¾µ:ÐFáày?¯¯}ñÅ…Í v.=ƒB€åìØúö¼æÒ_=TȀ璩²¨O¾Ðv Íuþà…üŽ.# P¨FÅÓÈ ÌÓËó‹…ÊðK{.ÙÑŸpÒÕÙ'–‡GÁ'çåzÐàLÓ6mò ­È6r´¿åÙv:œh å[Ù\ßÏÑDæIJu*K}y"pk·…ôå£^ç=*ÏÞÿc„ê_«Ïöþïüßù¿úŸXýÖñ®=»þïú¿öß±1ÍpìvÕÚÇ~¢+Öþ_ûý¿õÿÖÿþL ½¸þÿùÕkýÀ¾¶nþø_!dx2:5Äuл+ ]vò}¦ÙE”×Í&­²v89§˜ðy„9/p4²Ë SîþàrŽŸ¢^~e°Ø #€Ñ«—ϯÞMFhð oÜ®\ãaW9¿úê«üÂ" GzÁô^ƒT!]L çùs5‰\ hòde€8ýÒWðš/Vÿ# =YÕ©5ö|³K¿èk€ZÃGe'1²5sbõyÓ«R’v#9ió]ËWî½ÿ{ÿwþðÖœØùÿüê¨þp¬þ¿´éêÿtÄ®ÿ»þ{мöß±¿Öþ[ûŸ#¾öÿúëÿ­ÿY‹è#~ìéõÿ& âoÿ<ýá¿þ£·€‡ ö( ŸäèÓ‘w°ôûL¡¾¯Sój^ý‹¸°ë›n·OøM,ÍÍs}?Réõÿ¯ó›E½Ñ&GË–¾@Óù5¿Ãßî0*]šî¶òÑr¯æõãå•/ÙìvúnvC}óÍ7‘×®¨„iÔ>l^Ÿìýþµ1ãpïÿÎÿÌ‘Û$´óÿèÓÕÿG·Ž²=úÖØ¸wø¬þ?kX×@ñ®ÿgÍÙõí¿µÿæ!óÚÿ±ï­µ5Öþ_ÿÏцõÿÖÿ‡Ôç×;ÿ}ñÿŸ~úç¿zkh°ÐÉQ`@õݼÊÜø8МÊn KÁâ€>ùºÂ{h„7î°HHºn‚4ü9BxÉoÝÎñlÝß½ûnd;¯ùàëS`èéh ÍÝ x# å†çfOœ…BÚçsNçxpT²HçÂõüx$}Ê¡r~Žùã[^m›z‡í?|¾MvVõ^I×#Üùž—„9ŸŠNݹ$Éé÷´gò{*#¹ÊsïÿÇ÷G—ꟽÿ;ÿwþ¯þ_ý¿ë¿5¡kv×qîÿkÿÕ¶b­ý763»tBmϵÿg„°Åç¨.Yûÿ|¢€½½þßúëÿŸˆ£7×ÿ=YIož¬ì:¯àyÅ:;t,¾¦*Ùœï6aà»RvDÝÓÓáã1^^áÐY̤9”- Õ4tJLÝ‚rhfѤq*ÉfAôäRÞ«¹¤cÔŠo¯AÍEøáåûR^퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ§ÿr~•L#ú–é¹X;´[Üv©Ïù½ÿÚž‡¼“/('¨W »*ésvµ¿õâåð*fäUÿÞÿ½ÿÆãÎÿÿ£7躥ºBL'­þ?ëWuùêÿ3.¬=ÖãÆúç¾~Íâ÷X­Q»þŸþØõÿÙ.ZûïØµæÐÚÌÖµÿ…®ÁtêÚÿëÿÅ_]ÿoýÿÑ ¿—þÿ/çBŠp4ãç IwãxÚìcì: åcôYœKc¬2D«`ß.ù`‡Pöe“?¼Sçà>oE mi*OëÇ«òô[Vh@/“Úá#ð_óõ‹ï?Ä?iKéú‘füÓÆyÝoù€m*_1´ÎçO>\Zã[9ù~]Q9²>íׯN;} ](¯Ldkh_ë€Iê”vï;çäh½ø¹_‘ b5yx’Áñó³md«ü‘ïâ»÷ïÿÎÿÑq;ÿν ¬þ_ý¿ëÿ±+vý_û¯6ÛÚÇ^ÒìȵÿŸíðµÿg÷Ôúëÿ xýÿ ëÿÓ¸cÖ‡OTÁ%8ÿ§øÏÓ?ýÓŸ¿·Âaz\‡´žÛ¤â€FWz:iGô ð2€ŠP:å hÁnK@—‰5¢ƒ]~Òçƒê¯_×Dø’CêÛ!•²ßò–.è”7Cï× #—z&=çëu¢M®Î$gè&]è”J¥¾ H²óŒ\î𠃶‹"Å%Ë0¹v8 gm:ðvG✦®¶AŠþ« êhJË/v½ ~å©÷Cʃ†\sÿ´¡A~i=ßû¿÷çÿÎÿèÉK/T´Õÿ«ÿo·¬q»þgÍÚ:ýqv8ïú¯?Öþ[û/öçè6fmq±°ö­÷µÿù'ëÿµuý¿õÿkw¯ÿá??ÿ‹_¿-’W†f—NO‹‰<»š à„ö2Pïß©ƒ+¿êða” ãc¸ <$ßÂ…¶7¤×]ÐÄ&ìóñx‡piê¦ÐÜ@4÷s `Éâècä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/݇ðšóW#CiÑãߺ¤Ç4m»‡ÈxOøä<ò\«®š÷)×Úw…O¯s?'ßý:i?÷ÀíÑ:„½ÿ`ÝûúÁ˜06vþïü_ý¿úßœ¬×:ºëÿ®ÿ±ÆžaÛ°iŒZ"kÿ­ý·öÿÚÿtÿeý¿õÿ¼æe}¨¿¿öv½þ¿Ùò?†õÿÿfüçégów€pÇöWÁ êó+}>èΉíGÕt¦ü>1¦±s §G™$êPWyßce‹0Ko^Œæ§4Xl1ÈÈláÍPJÙ9ËCãè5ºò‡è!¿6kûIe;Jw®ÍäÒ×zÇ5Ëõã˜t¯é¨ `4i)7õ ¨€#íþb'ô0|LneÐÝS#îÅ£¼å{ñQVÂ-T¶&=è.¹Õå~ ëùÞ}±÷¿cÇøÛù¿óõÿêÿ]ÿwý_ûoí?ö'˜ Äkÿ¯ýßq°þßy¼þßúÿ}È·þÿ,ÿøÏÓOÿì—ouòÝi ¨‘ú ¥çU3NL¿ 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçø0 Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;h—78Źžó(šÉK;>œWkÛ—_~™úIÊÚÓã³yÕQ•µínÐ;Gß4õ§Îôî‘C¹x9Gß²úÊwÅäÝwáß Œ€Fèuë-|›khÈA®½ÿÇAÕ_ßïýŒ›ŒÃÿ;ÿçÁÁêÿÕÿ»þgY}¬ýgíÜõ?ëæÚ±Õô»·6—S®ikÿûÔßµÿ×þ_ÿïÙ÷£?Öÿ{Þô9Š¢>íúÿëÿ Åvž~1q7H$ú×Ðs¯™=ÀšÉê¯>Ú|•G׿Ü`ó¡tiê094ƒµÇ„SÿÔ3uõºYÞç³ËuP ˜óîý»€:­8¤eœçCéÚ7GëT~v¡Qv <äÓFåSÿäYhfâ>‰¬¬ä"óÄdΫ1hæ:u_òÈ#_$×êÐ9Ú&¹áßv\ôÊ¡>¥ŸË·¾öCùâw?oû’¶÷ïÿ5ðvþïü7VÿŸ‡«ÿg=ñ°ëÿ®ÿkÿ½‰@?²ŸÖþ;6åö·n¬ý¿öÿúñÙÖÿ[ÿ¿þ8¬AXÿfqP‹ƒIüí🧟Í7°t®íTà¦OŠ ´ ³X¦ `b´Ê\!Œp„úñÅO~ò“€3åoÇžè ÎñW^P®<\‡÷4`öÝ·ßåú€R^Ÿ›W9FÕ«×óKˆƒæ«G¼tvQiÃüÁúì*¸TöIïñý"YÛÔöåûWX£eênà‡w_%LþI|´¯¯vkwH}þG6|z¨]äâ¶W\¹œ7½uà›s¼RÉisNý™Pžb¼ÎñrÔKVqó´K›÷þÏøÝûŸ±ÒqhìtîŠ]ïü?;3_§?„ÿ«ÿƒÕÿ»þÇöˆ °ëÿÚY7­këÚkÿ BíüØ36Ä=ä¯ý¿þŸq ¬ÿwÞîZÿÃ¥?Œ‹"Õ)]gêãÓ'¿-þÿ“¸W¶AmHÏ,@Kh€hë¬J/`ƒŽƒ¨JPnh[‡4ߘRÖá‰î½å«ð™ò®½æV E¹Ê€¾²ˆLyZÇT~ê —L2þx’MŽ××Î+wPƒGÛ$SNZlÛ™eÏùäi¾ø£=Už~!We$oûí"J]¥ã‰/´-ß6û.˜þ¼ÓVæ~3ÌÏx~>4^A¤ÔôAÚ0é½/b<ï|Ô ÐC/¿¡}ß¶Io;ÚW{ÿ÷þg¼7ÆÜÄC;ÿŽÚù¿ú¿z³s¥s¤ñêÿ]ÿwý_ûoí¿µÿ×þö±êƒX7ë ‰ë[é+þI|”Ë·ñëïñbæzý?¾àúëÿ?àæP›ó·ÁÿÏGÜ *´U”Ms“¥U9 ï+vò ,í@aHëSEŠ¢åå½ûî]x1ÐDU>xÖh—8‰ã t‰|öÌ®-r„ÿÐH÷šžŠ)&òEžáÝïE‘Ímâ8IŠlhÈóáûH9—¦îÆÚ€_®‡Ç×íјüxÔý¼<ü„½ÿgìý¿ÆéÎÿèÿx«Þ«N£3Vÿ?¯«ÿwý7',¶»þ¯ý·ößñتkÿ{íÿõÿø¸ëÿ–MÉž:7æ$¾ññO×ÿ×7úbýÿóFš¾xúgówàäÖŒ’õPO~ÃT‡FZé -ˆ-#/@Ê Pßò:`Ðß@3‡¾å[–áwê82Hw ³‹¨ô@-þ€šæ+_~™g~$Í¡0È÷°7­C p*(¤hx‘Aƒç¯_D €tí(1V ×È霕”ħtâHyÂiãì¼òˈs]y©ïº•Uº2ÑËó+>¸¯/ìC7<Ów#?h¬åäÛIž¹ù‡ghõ¹ÁrÕ«žso>®7¼FàÔuÑ(#}ïÿõþÙû?s3£ûôGÇYÇÎÎÿÿGǬþ_ýÀÁ¬MÖ¢9ª/vý^÷­-úe×ÿ3>è®'1ýòç¬7kÿ­ý·öÿÚÿŸÕ‡[ÿoý¿õÿëüÿ§ŸÿÕŸ¼eô]ìg XPôc„@ D©‘4¦ÂG;ˆø¤ò´ŒˆU¾Q%O=~í ˜¥æ¦)t]ObÊ‘C¾Wà8µxå¸@ü[‡òå%ÆÂ-œ×üÎî­È'B^«Ú“ë Äq^Þx…ߤ5–ßôƇïNÓ6ÀWi¥× ‘Ösí€Â·Ÿ[Ÿôö¿´‚@øÈ{ÿáðÆ0&Q¯w^úVûî²â‘ûðÀ½<SiB<ZÒñþ@¨È6×êÖ–½ÿgl苽ÿ3Zvþïü¿tNôÒêÿè…êüÕÿ»þw,˜»þ;J_4˜#c\[cí¿µÿb[­ý¿öÿúôäú¼ÎY/æÿÝgޝz­]CÖÿÿÝöÿó ¬k#DŒ7À cÎŒL\ƒÂ€Ao"9ò$ë22úDc²nàPqй*r͈€R­«u'¾xÈë¾O_s>² }„K.9Éç]ir9÷º¡×æ"·zçp^þ¡¹€™»LL«/~úA&:´°Hríû>êt-]šYÉŸºÔá{YʵÒ^|µU|É…V}v«}ñæ‹4Sû=u–÷úÍù>>¾Çu¼ð™ÒÒÒ.ç¹g×üIBhöþ<&÷þϹƤñl¼SŽÿ;ÿ=Ť[Vÿ¯þÏXÈRrÖ1ëc×ÿ±.¹ëÿÚkÿ­ýO/Y;¯õsíÿË–¸Öúfb¡:4çc‹ÆÏIÎü¹ìÒõÿ˜ëéŒõÿÖÿÿöÿŸ~:¯VΨώÊ‚såz);y@væªP8nD@IDAT  C7Ê7—çš‚î!ô>n.þ~tüÕ9Sí+·óIzN“>GœæË–ÿp /ovœì«<ðø¤Ž¢¹öMµ·ýÊ¥ŽÉK›&J;/Ã3ùv£RùŽ–¶ ÅK;]÷Cƒvž}?}Æpó·ôÛðR§ò ÎÕù4€•và¯-Ê·ÿô±ð~ò¡ÍÒ_ÏÎ6´ú9m>åK®ö{îé\ËKþÄÒRÏÈ‚NŸ {ÿ¯Ý„{ÿwþg®îüb ÂôÇèŽÕÿ«ÿ­^Yˬ%»þa×ÿØkÿ­ýW»´ö«ucíÿKg®ýÿ l c¥¾‰8¾ÙØß!ºÖ™<@½Ðó—-¿þßùâßM§¬ÿw|]fëúÿÏoRý¶úÿùˆ»‰/ÄðÌÙ9w§€«K™Xx ¦ÜÚ(|¢dÎ.–€>Wž|×@‘—¯æÕ¹yïØ„z”:¡ò ~Õp²ÑÊ'×#oèæ" ‹QÒKƒŸkAYº.ùhŒC€Êá!Œä·tÍÃëó§);2 #—üðŸÌúëÿ­ÿÿ»íÿûÂc(<+“ß?‹(‘  ÆÎ!M¢K™¤Ü¥H(eñæ¼0Z âN ßÞÙ±3çQ:+Çù:'GøŒ ‘ãJ—€gø‹É7L '™xã«\hGªÓÞc9—//ÛMç\ý©oÒ¤+ëºé-¯]ΡJòÂÒ´)íºäl»b°MZ¯õÁŠ&qø”ï\=Îî9ÝÅ%u ¥éyùÈÝ,|q¦ŒëÜ—”›~žöú½ÿ{ÿ(sÆÈÎscçÿêÿÕÿ»þ[#wý_û¯¶•xí¿µÿƒµÿ˜»qü‹êÊõÿŽ_¨_„õÿÎ&ŽõÿÏxXÿÿïŽÿ<ýÑü !@ª`ˆEP4ê%y9&($ß«q‘<·DºðP‚×Uß4sÚAüaœD߆¢ôJÎuÑu<8çY4††|àmEø_ßošsN¨ôðöÚDö’I<å=”îE›úˆœ—®íQ¦òHÈ£/9½Ò UÞÒ—Ÿël©š²^÷R5èÃì^U|¶-ª7`ÖÕå- ?ß½ª<­çóÙ~¯ÐØŠßûTyöþïýï˜Ùùt…¹cþ GÑ!—îØù¿ú¿ú³sgõÿ®ÿ»þ¯ý·ößù‘¡ûz¹öÿysÂZQ{bíŸoYÿ¹þßúÿëÿ¼)çÿyúÕ¿ûoß½ð¥,À”,c P%"‰ $‘W Ê´XeÇS ¬óŠ^Ò¦ èÊÓ†(¼”Ã+sÞê(÷(õ9 °eÒ†øú0ú|Ûi˜á+ˆÉÖ÷šj®ñÔpË¢¡À)Óòa24®Õ+N¹¡wŽ×ÃIžäБwÎÉXyÅê͇J”=?•POúnÊhOÚDœK~WÙÒéd[ì‡  SxÏk”z_êW¶÷D¹Šd>òš†Þ¯V¶ó ”%0L$}ïÿÞÿ_csçÿÎújõÿêÿ]ÿÏ!¯ïìú¿ößÚkÿ¯ý¿þŸµ`ý¿Tó5ùœëÿ¯ÿ?¨I°‡bü)ÿ`øÏ¯þý¿x« IwWl‘Öï qf\›¸@¬î~âô0áüžÜk@­¿;ž4 öÉ0)“z&ö­ƒ~XOºs²hü‡³Ûjä$£ ,@«{ /¾:Œõ×9¯üâ$<¯;“‹¿t2µÐK ýœkGÁ'%FG©É«Ó9°ÈŽ6mÒyiÛœ'ob´xeaœº·Ÿ¤q"~@+ý?ùžZ´ïäEqL™a˜VxÚ¥Ý¯ß È8à•~P—ò(”÷«ˆ~±GMÞÈÐohK¿÷￱±ótßÌ+óÂá|çÿÀõƒ@¯­þ_ýo,æÉ®ÿ»þ¯ý·öŸµaíÿµÿÙ’]êÃH3>Öÿ;¾¬þi?­ÿ·þÿúÿÿsüçéŸþéÏß28¨Љ#Ä©£6×IŸ‰gL.àËGaÊ0\£†&€R¯¡ ÆròêvQœ ÉWN]@iŽïg×Pv$©è’É+ˆÒîõ++p5À¥‚7q:'-õˆS'àÒÈzàŸÉø$§m’…G¯ àù0»ö“Ÿü$<ÂsFé³ûç‘ÌQǼԙ8ç÷ëÒÈ èc¼Ï9š×€€;Lˆ*_ù‹ÉQ°‚,hÊÇwoü\2¹ÖeÈÐCé€Ò›7o"Âc—ÊÈ8ûòË/§µç„ÿði]‘ÏÙeF^²§´oÊþ êV^½Ý-'_: /}ß0̽TßÄWŸM 4i{ÿ÷þwíüßù¿úÿèW:rõÿ®ÿ–Ï]ÿ­ÅÖ`«¬ý·ö_íÑØ²ÆÅèËœ_1ýézíÿóКӱöÿúÆ@æÉÌõÿÖÿ_ÿÿoÿ<ýá¿þ£·‹Ç¨ái¢`wFx}4ýHx@¢™€è…ó›WÔð@É7©&vŽw< ‘ Ü:ïà ~òH‚<­PZ‹ºÐâ='É÷Ä•¶ £ÜCYÌùOyåÃæSNõæp>¯Ú%Øñ•0õœšÎb„™?|ä®r’þC@i §0"×÷æÜŽ(¡²9G£¼£<Oh\·Þ¶-÷lÊäûVCˆh(ˆFYê§Ü»ÉìÄA‡_úldÙûï»a{ÿwþïü_ý¿úßú°ëÿ®ÿÆÁÚkÿ±×þ_ûŸï±þßúÖ…õÿ×ÿÿq0«c›Á-þ1🧟ÿÕ¿-H°äz5ã`f Ž,аPe,(‹Øìê‘Hf$§Ôüò_æ:e'ˆ’Ø%íÄàÝ€—€OC•¤ëÒö•Â]ïg'y„îN*@ù†_yêØî¼ÊÇÌ•™2êKY¯(ެ^ÝSO¨‹ùÛO˜yÒ4|¾0KŸªÏ.e• ˆt*t~oÛ§m×}­ùx ‰'­|5€œúÇÑváFY°ìÍ€[øÉ»ƒthújæÞÿóÚêÞÿÿ;ÿWÿ¯þßõ×ÿµÿØcµéÖþ›ÏX¬ý»íÿqJÆa17Öÿ[ÿoýÿõÿéƒhüçé§öË·Nj¤z:ˆP€¯çu5r¯^ç¨âÚ(ßbÎXàÃ{Òñtî °¨üj 4&€ä\zwá縗ÅÓµ…=æÞ?ï cp$ !£Ã/üM8éyš¤>!»±nõ|ò+󚥺>}5QºvºI•·¿¬X™IwÀ®“˜Ü¾UU€)ÀÓU7YúÍ+çêî+ŠÊ•v2D= 0xµ4ýÐû£OÆ ¾¤½ŸvUn¼›N–ìô•ô«ÓÚç{ÿ÷þïü?¯&ïü_ý¿ú×ÿ®£Ykg]çÌîú¿ö{‹¶ö;rícá~¬ý|·útb:tý¿ã§­ÿ·þ?!´þÿ±'ª+ôý9;°þä-¢;†bxfòؘµhùöÛo_üÁüAÒ þ ÁÔa‘¨PÒ¾"OÙVZ£Îµƒ®„‚>ñL©ûÊô-)u ¦¾‚¨ŽðŸFˆñ¤#y&½í+þÚ °™ lÁ›ÉŒb´@ºÔq•ÃO=Ÿ x…kìø x=ê™k•‰\CƒŸóß|ý›ô½Ý[ý»t¯$ ÎñqèK±²‚Ö¹uMo19ÈW:i‚ôÞë½ÿ{ÿwþïü§#ªª/)µÕÿ«ÿ­!»þ_Nø®ÿ±€·ì vGl¶È\³sÖþ[ûÏØXûÿØÛkÿ¼aý¿õÿ¬ f }‘xýÿõÿg,4ü¯ðŸ§_þÛþÖ/ã1Pƒ1H85Ú«yíLLñ0d \?ú¬,Z±a(ïÝìZòs[J38/¡ ¦àñÝðóÄR9üÁ1Òe¤«ûC¿ÿ4;¿üÜ*Kh‘8çùCú){ýÓàNëÇï]€ÐU¯ôÔ;uöDe< ¨<ʑѢŒ¿š¼÷~®¦á¹ë0"Ý®/»³ðL?Í·°ðÕï¾;¿,x Ufôá1éÂãüªOùïm“&øž•ö ³ð ïpM¿y2(ìý?ßÛû?ãd†°q½óÿèŒÿ«ÿWÿïúŸ…rþìú¿ößÚkÿ¯ý¿þßúëÿ¯ÿ~ô®\câ`/ƒ7ücà?O¿üwÿâm@G_=c°å½nÀÀcþ|‘Wa¿þúë6ÝÙ$ó0eb_Á±/bà Ç@~ʈþÐS<€:èaÀ˜l1ðJyòv§ÙRÏö óªàËù š2‚òêî7 ”-xÔþØ3ôâÊÙ>9¿Ëw§‘—chŸö£}„§¯Q¶\bí¹ZÏÞÿsï÷þïüßù¿úÿ#}¼ú?kÊ®ÿ»þ³nÖþ[û )¬ý¿öü ~Îø4ëÿ­ÿg<Ð|Kñúÿëÿÿ½à?¿þÿê­Áå[LvJupõ=dß´*HÔ*ô°Yœ”-¯ÀåQ³CŠpý ½ó|khƒ7@ú \ÁÇn$y¶¦«K9qÀ˜)[P§eíuÊè/Z¼Kè(M»Å”ÅÛ'ô’¡õ¢qž6\ò¨³ë]†ðŸ<¼ôÉ"BÊæÁ'¡²K¾óòm-2JÓf‡ ‡j Vöé„ôƒ|²i#°¯í’.´ x ëk…v~ Ò„È?õjcûaïÿYlõÇÞÿw¯ïÐíüÖAæNæÕÎÿèØÕÿ«ÿ­%Ywf-ÜõŸ†ø8ìúýõØúBXûo¶®ý÷‘ýI¬ý¿öÿúëÿ­ÿÿ öÑ‹ãt<|wþÇúÿçÄ´åÓÏþüWo9©yÍnŒ NI ±5€+ÒQ•δ Jì×Ù†0ÆH€‘9ÈL÷ÆHQÖÑE©Æ‹o#$°‹èö®+Ån©¢õê°HzxN=Ò}¸¼@”Õ(u‘O=è\—_å dÁ›Æ™]‹ÃsÊŸ¥YG&ü¦¾†Ö‘ëçä <ò5?r¤¿®ÂêÊõä¡ý|ú¥¯Gj3`ËҨ׵vHßlå«Ç!/õ˘ Œuý~Eú{Úº÷îËô×Þÿÿ;ÿ0c.¬þ_ý¿ëÿY;ýµ–f‡É¬£ ]ßsýœ¼ëÿèµÿÖþcDzC…µÿ×þϳþ_æÃúG/¬ÿ¿þÿß ÿùÕ¿ÿ—ó ¬çÝTÀ,¯Ž Ò ÄNŒ†šÇæH^@i¥D’fb¬ h2ôÇ1´s Èr€åvºœßâ‚3å‡Þ¯ ¢E†Où·>å¦7"wâ)$ïÞøH{„¢¯bâ§M~Ññ«¯¾ Ýo~ó›€N¯íÈšBh? •CºvªO ¢ºšO¾OÝQš]XBΧ úå÷þŸo‘#{ÿÃj|'ÆGÇóÎÿÿtˆP]t‘‡¾siõÿtÔêÿè]ÿŸ–íúl6FÌÚkÿ±Á­+kÿ¯ýÏ¿©ÿõ°'ÖÿËü`w­ÿ·þÿï»ÿÿôGùÇo9§ÞM7!J£`ˆ4 Š…¥ÍÝ™•ï:¯¾]À žå£\¯¥éte¾øâ‹Ä>¤î:ü‡PžÎ•õÝ&AºàÕ–8N7À ŸC{^gð+„á94¾oÔºGŽL€¢WÛí†J½°ã\x¶?8bÒÏë#›„ÇðÑÊoÙЪÒî4ýuEü¢ÞÃç[Xù7åÒ¦á+è¿òÿáýäÂ=w ÕÜŸ‰ûQ~¼õÑhwÚ3p…ÿÞÿÙ¸÷?£§ó6ãbçÿÎÿÑA«ÿÏÃÕÿg÷²5Å!XWœïúÖê®Ïµsºf§³æÏ®ÿkÿuŒ¬ý÷Yìrý±öÿÚÿ÷ì]_âÿ¬ÿ—å£k‰ù²þß`ëÿg\ü¾úÿO?¸› 5ª ˆRÕ„iüt·‘4å,>ÊÔéõn7z@φŒ¹ÛhýòwâÑ©÷®°ðîûáò8PžVœÐ)ã¸Ó¥¾K^r+‡>í»Ú˜ER]O‚‘Ñ«’dÿñúõµÈ éRxùМr‡ß€"³öL‚kG”îðó*£ LöuÓ£´§Ló•ï‡Ü¥¹ÎÆ/Љ,‚ö&Oý C›pÕw_ÂîÀ½~¼¤7͵_ÇÞÿ½ÿZoF;ÄžÇÝÎÿÿô=b,¬þ¿^5[ý¿ëÿ¨Ë®í÷µ–u½ëÿÚcl=Æ=ºößÚÿÕÆÃÚÿëÿuÓÁúëÿÓ ëÿÏ¥_^¯¬ø˜ uD2YÆÈЏþk 2‰ÐÁqé9zç^ƒãæºþ¸PVVãÍÓÛ{°[Ê6bqäÁ{Ê©£2Š]¿™\x ®ÛQ¤~’Xýzê9ú ”|Ƃެ¾¶§,ÙúM |IMö¨3ç©ãjO¸þ´dw¸«ßyåEŽ·ºúQ`õ¨MëREwd¡š—‹!8½š«+館ïÓ£TäZWûVzä™§ðCî½ÿ{ÿ—Ž'çÆŠ±h¼ôÜxr¾óç?-d<¬þ_ý¿ëÿ®ÿÖNXûoí¿Ù½™AqýYûíÿõÿÖÿ[ÿÿl ²d®ÿÿ7à??»>âΨàp 50€>ùú¤_yC[§D™3@(¯Xpf¡ƒòCÏXIy·!wã2b.pÇ«¼÷®ÜU˜‚O”ÇWÙ:Ësñâý\ÊæuD`Ôð{õúüò`^3pJPÛåúñºÝˆUùå´òŒŽ‘u=ùäQøe‡æª'<†®}©|ë~äqôoüµ[Ð^áQvxyï߽ϮuË÷ °ö½2‘vx6–&T8WÏ÷–LBc²µ^çÂãþ9ßûŸñ³÷ÆÆ5ÎŒŽAç;ÿÏüºÏ%ýâèÜOÞÎÿŒ!:¦;ZWÿ¯þßõ××þ»*®ý·öÿÚÿÌŽÊúóVÓúëÿ¯ÿ6KðCq¿;]G_Œã5¯Õ=€žñ[)9F™&‡žó!–çh’‰6qw0•¿XÅDZ;Àp„ó«¬r¾ PP© Øw°ü"bΧ.ÎÐG½}bÃz7`O?ìî×ü(?25©¾Ÿr‡ç| ~Ê´žîÀ"§Pdב|²Eþa¤N2ÞÁ.yè ö$Ò„ôÛÄá9eÅå‚ëOåHÞÐ|˜>)?} ¡Ê¯/νѦòQNèõÅîQÇ=¿yâ»\=—9öþïýŸ±š°óçÿêÿ‡>]ý¿ëÿ®ÿkÿ­ý·öíx1»¹öúÚÿëÿulÔ·ríU@qóŽ}þÆïš1”¼õÿŽ:ý¡_Öÿ_ÿÿSüçéWÿþ_¾5u Òíy¶ó8×dËäBsí2)¥u"»À5¡Ë€»^»›ôî8zÐÏ‚Eø<>Ž;¼ b ‘_ð(²M%ýÂWpFî|3k®_èTP ½²m—k`žvmˆÊ¿t➯ΠxæX]”´#²L{ɉ‡C¾ÃyÛ:$Ðçü–׺ÅÀ²/àZèôÑß¼µ&±²Èl¡ôæUž–Eòiyu”~ïÿô÷ÞÿÿtÌÎÿè«Äêÿ£{«'Wÿ[õgݱVMÜ5ÇÃ#×Òwý¿LÜ×ô]ÿO¬ý·ö»´¶·‡Økÿ¯ýoLTG:Ïš»þ_|<ýñ©ÿ6ËËúëÿs[j‹¹0^÷üÓñóÛæÿ?ýl>⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹}J¬e¥§³§FOÁœ€ò=«¹¶~óÍ7‹ø*ç°s«¯(öfrRñ’ß4²‘ØÖòmyÓ'±ÚçB›SO^‡¸êk[‡uøú&IŸ:;Ú¤=ÂE›v e…Ȃﴗü•I~•[¦!¹ž?òò͉‹V™ôáÐáãx”Ÿ¼ð@t…´uh¥—Všs|öþïýßù¿óŸN¨Ž¤VÿϘ ÛWÿ?Ö”¬}Ó'ÆÇ®ÿgÝõí¿ÚZÕkÿ­ýOG®ý¿þݰþßúÿð…õÿþóô‹¿ú“·&F ¦`›#ÀˆqÙ¸(¨ä©ª×ðt¦]L£ÐÏ7©(\´Žò½ÇÒ)Žïç›Yo^Ÿ§-Czï/5à€d¾mÕWÃCPÍ>ÄÏk‚¯_½Î®,2`¹óô*!`*ÀÌð,E¶éƒ8`8¦Ný`çYäùE2œÅåh¨¶Ÿ´cx9Èà\ùÒÌ’¾<Å¥øÏ9yœëóž+_¾¥k›‡ôÑKîYiõ¿2BåQFØû?ìÞÿÿ3svþG%Dç¬þ_ýo}Ùõÿy­žÅ3kû®ÿc/®ýeiެý÷l×¾¬]»öÿ8Öþ_ÿ¯>ØúëÿÓ0…êIc#þüúÿù¶9_¬8PãéÿùÓŸ¿å¨7è¸v0£àQ@  `1Ñ€9bG;Ù¢ôr:_%BÆî\„®[Å]ü:å’?uã%°¤~‡ï[•V~ë&§ëÈ0eðà`ÔqŽö ½4‡:•W–œø(—zcêŸ<ÁÎ"A™@gùIrøØe èqÒÓÁÚ2‡vØá•_GÚ¶áݵÃKÝ…ö™üôãжÚ^|Ú?èõ/ÀÈ•¾ËõH2yÉ>x8Ðû–VÚŸšCòÈW=~Gö‰§?Úg•ïÿÿöþ@zçÿÌÇ3•‚g>>æÐÎÿÕÿ³ûvôoõçêÿ]ÿÙ»þ 6óB_Dg®ý·öߨŸlϵÿŸ?]b~¬ý|ÏúCëÿ­ÿÇÇgwýÿé:Vñûàÿ?ýü/ýÖÎ¥|¯‚:f¡ ìÈÑ1è:@!× q‹ŒtçÒ ¹>á€!øùvEH¤c”k}´&¿õµ×Ê~ýõ×/¾üòË삚B)gK|²–¾àÊëÙ©„·|²>hÜä¹.@Uðëó‘1ü¦®)–²Êµ*@0í8:¯ >‡ö+€É.µ‚gÚ‡ov©‡<¡&nž˜¼÷àZ: Š<‚ÅlC«ï&¬÷ ¾öoxëó¶oïºjïÿSÆIΗŽ}cgçÿÑ_;ÿWÿÓ÷«ÿwý·ïú¿ößÚkÿ×î^ûý?öòúëÿ¯ÿ6Ïü}ã?O?ÿ‹_¿Ë++€ÄÁympͱ÷ÄyÚ—byb0©³[à*ÉÐL¹À• .¯¿Ô= Ò3ÙïÎó¤ÙÑñþƒ×G¦¹Æó«¯¾zñÝÈ#ÏGÜß‚ÐÎ9ÈÓv׫‚ò6èÚrHo{ ò Ò>Þ úÈvÅu\•ä í‡\OQmæìûøûë‰åË“¦êѯÒ#§ú& ©,ÒË_^^{9ÈT9uMy—üIÌ=©Oø”/ðòÊ8œ7¸Öνÿg!r/öþÏ÷vþg^˜'ŸæMç¡9¹óÿú¥×Ñ!«ÿWÿ[{:WÌ›®QVéŽÎ!1=»ëÿ®ÿkÿ=ÛÌkÿ­ý_;}íÿõÿ¬£ëÿ­ÿ_¿ã÷Íÿÿì?þ×ÿücw@e.\N˜s¥>ù0ú¤w+oÁ4:¬LÿÉO~òâÛo¿Í¯û‰kŒ¢s^ðÄ9PÇ1l'hÔ›!­N@;”¦Œ \¿&ˆî¯ÿß¿~ñÅ›/Nù¡¹¿ÎdÇÖ=èR€§‹z¼^§OR¿ókG$}SW—÷*Ziá7²0ÊÉWKÝòÔKVuÆ€Ÿtý èë‰di¿*ãðêû è Z|œ£s-ßucùêä;—ÿ*»çF»±´m‚2åßÞÿ½ÿ;ÿÏŽÌÿçUîÕÿg·/=¹ú×ÿ]ÿÏæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—°VÖ79ëæúõ¹Öÿ;>î8žëÿÞ0Oøçp•õÿ®ñ?ò+ŽÙtœÎòÔsNžŒkRÊÇ }å)GYFòañ‰ïÀͰþ Aß@Ñ—§¸287ÁêîN%»¨Ôƒ¿ÅÒë‚ï²ÃÉGÛ•‹ƒ5Œóˆs­|”Ä”Ô.MÀǹC]òÉh@#ƒéBÏíp}xÎ÷±¦=‘s~QìZÀë7¿ùMèÐ ’&=ñ\£×gßM[ÈâÚî2íÁÈDÃ@]7Y%¡0·äôYé¤'ÿj—{†®€ÕÉòdžÐ¾W‡²)?ÌÒ¶©“Ìt…¯¼½ÿ{ÿQãcçÿÎ?pa<ÜCôâ$ЫÿWÿwlXFº¦tld‡ëŒc¦kÏ®ÿ»þkÿ­ýÇΰ¾¬ý,øè͵ÿ×ÿ[ÿ/¶ÄúÿcT]><;‹OGü.úÿO?ý‹_½|¤›K9€†K‹PÅëzGŒÊTZ–c"/ßÅFÚÝ¡æø¦Žã^Öy¯Ë»ÎÈÄÅ+ñò+a„FßYr&£• Çksìx²’?†³ïR Úy@«ôHø*O>ô•3<¯ôœ?ÒðòtÞGÛ]“9´“ÿæÍ€nïÎ7±ôMƒ|ßÝ_Ò >í;Ûy­Bÿ†×Ч¿Å¨•É;­ôÊÎyv¡Í®/|ûaz´øeÚ¼^™¸úògïÿÞÿÿ;ÿ]ýæ»ú×ÿ]ÿÏ+Á1Ø —í`~¬ý·ößÚÿkÿGŒnXÿoý?caýÿõÿk/ü}â?O?ûó_½-c1c$ß~šs †3o:ú=§=ƒvH„@;0¾ùæ›ð:ÍI-BGð hAïÚàNÞ¼ª'¤þI+@ƒg·äz²ÿ&¯½ýpd™kuÅk¯_¿9 Ó€2ùþÌȆ%>#ë¼™ú‡¿:-º‰‡mdš4Œò¤¥O&ÖîÒ¡iºøq­>´#£>I:srÿÈúÙ7ߨš ¯+ åMvGøÖá MÚ™'¥E'­ ˆúËo2 ¿¦UÞ$ÌŸ”:AÞÞÿ½ÿ;ÿwþ¯þ_ý¿ëÿ®ÿkÿM´ößyлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øËßÿ™_!üã·”.PCˆÑ#PdÒSñœ¬pqf@.à•M½³¡Ç?€ >@”Ù™$$C0×Ï»±¤ÉU‡²{òM« |X© æÃæÀœ¼Jàš×þRnÊ—«ç›x*ŽN]dÖäl<Éõ‰ë—¯æ£ïó¯txj >ÊáÙev{ ½FWã(`w>ÒÉ/ xY¦äyEïÚ3¿BèZÛt? ½ê”Å,ÉÃ{dtº'¿²¢%a¯÷þïý7fŒŸ[×q>ƒeçÿÎÿèÊcõÿê눵k×ÿ]ÿ×þ{¶÷Öþ‹qû’íÀÎŒmºöôåÚÿëÿ™æÄúëÿ¯ÿÿŒ ýïâ?°ê¬ú…‹LŒ‚?{&]žÐI<€—²œ˜×^}?÷”–#ÎÄðDP¶’k”þ±Û+PÊqœ¥)«Lœf&¸®¬®KCŽä2°KKã•+•'Ç órF>¡;”ð`ˆ‹ó]­ ¤#óT”6â#¨·úÐLzé€S—üúÔ¿ÊÞ¢« _À¾¹¾xø`»XúÝOtUtø´½é×Ó6¯’Kšü¼÷zÉZp.;ÍÔ‡^çØû¿÷ÿ_ÆÅÎÿ€ÏäØù?ã‚îVÿ¯þÏ8°Î\sc×ÿ]ÿ×þ; ÍÚkÿÓ‹Ç'YûßZ¡/ÖÿÿìúQ´õÿÖÿçW¬ÿ0ˆó°çàÿ'øO, FgÈÈõü2Q:@»Ÿú*_>0(º”tMóÅ›6J«À þ€–€+sþò鼂‡šs^žÊr—\ âž'áú¨!£x*Lª²ÝÅ•„a1¥ßÏ’O>å€U¯É§¬ïN‘É·±Ð4BþC'ß9¹Ú.i®#“ôÙ †·üæõÉ CÇ÷º€nú¦ík5`°_ꟴòÐ;øøR¦ý•ºæm~Ž^Ob®'íJsKÛû¿÷ß8Þù¿óõÿyHB_®þŸW×z¥/výßõ?óbí¿‡}¶ößÚÿlìµÿ¯5é‹õÿê‡ñÍÖÿ;»×õEŽËeSä˜EE ÿƒ¿šÔIŸ²Ñµ|Û)'Ä>ã—_4NÖÿÿÝôÿŸ~ñWòà én¤ÁÀút–ÁÄ¡Y˜Ìu'¥XQßÐ ¬©«±¼ûíxwÀþMùÊ;„ü9@ê«—¯RŸkyž :y5 9|‹ `ux‘¹<µ·» jœ“ ™§msØ¤Ž»ìåÙtJk*Jÿ„_ú㼉&Oï&ÆK¾k1ž?Úµ6m11MHÿ•’Ÿô<&®½®‰°¨fd#ãU‡ë½ÿ{ÿåÿÑ&Ñw;ÿŽ¥_VÿýºúÿÌkÆ®ÿ»þkÿûkí¿µÿ×þ?þ‹urý¿ñÀâ³5sý¿³Ùƒ¯É'®Ï©„ƹ¸®¥5½±|åëW§w‡nýÿkËô'¿/þ¬3Å Hó™×× xÌPÉn©¼Ê6ù|¾å½]×v K.fè ÀôWï:‰/@¥Âž?¤âí•Ù<—ÊåˆlÜ‘g Øãµ½kð»™@¨ ð¡ùò'_¾øúë¯OÑ™LuNðpt¢IWÞk}#a~í¯Ü=ê˜ò#Ðãš,•ñõüâàd¥~<•yzy{4®){@UÁ1Îúä«[—úÅÄ\_ò¨= Jú0J·’=ד¯>AwWÖÄWš¼Ð;¹ÂÞÿ½ÿ;ÿwþ¯þ?†Öêÿ]ÿwý??ÞÃD`[°+Öþ[ûoíÿãgÄξlyöu特²öÿ|e|ë(_#ý³þßñ»®1³þ_¦ÌsjŒ<ÆÊÉzäÝçÖÁ&Öÿÿ}öÿŸþŸ?ýùÛÐAùFÿÎИíàÒŸæU?àI»€|oÉ+”’'pœNôZ :ƒ¯€‘ÉÙü(¯x£w =uf䆶tëýÜuPg>sÚ]Þ)%SøOz^w¼äøØÒûÕW_Ä"?þ1P‡¦A»ÉÝpúáYï†?™•Á/mzõ ³‡LíS²´_üFù÷zXá1DÒuJv‚ ÕS°*´CAF|”k?¥?¯Š¤ã•²×=’¥ïì¶!?^•5<öþ§?öþïü¿¦QÆCŒÿ«ÿéÓÕÿ»þïú¿ö]Plí¿µÿÇ=^›zíÿõÿÖÿ;ø@}Ôõÿ×ÿ‡M8‚Wsok0 c¤ã„ÿu?¯?&.þóô³?ÿÕ[L)<À €Êuž©*%Jg»4„’þòË/ƒ°( H4é½VYÒ.à »ð= çoNó§ ù¦‚¿É»®=ä%«½Hv‘±|•!wh&þÉO~¹ùÃÇ®×çßìNškßÀjµC^Ûð©l){ÉY¾•¹y€2è;yú ˆä¼éꔑVÚd×›@¢^¨ b}WÙÄBóS¿ü¡kZ¤ ­Cº{ÿÝå½ÿÆãWÓó¿ãdçÿÑaGæVú‰î¸›_™S™¯'oçÿêÿêyccõÿ™æpþæ4>c½Þõ×ÿŒ…™CÂÚkÿÑ«,·X±kÿÿú“n]ûÿ¼5´þ_†GþÔ®§O×ÿ£Aü[ÿï·Áÿ{úÙ_þú­ë–ÙTCҠ΂0†¥­Â^t-Ýî*†7PÅëxÊËsÍAe¯¬‘§œWèÄ® ÞÄúÖ?LÃGÚ'çhÈ"ßGø[Èf—9šng ŠœÎSUbùX¹×&µmäõ­ì´Àç2¬™Iò=Q™Y~údø?M;„ôáE‹®idlÿTN“?íºcÌ9ù•wT~å°eاî)+n]`\L¹4¼9‘ ™!™r•Aš' ä+%Ь…Rvxüæ7¿ ˆ¥n V%ò¶íbõ™œýîCó6µ¾‰iò*ùýša§*`ÒÄÀ¨ðœþœ“|T¾_Yý,´ž¶ÈõGýªgãO¡å¯ìôɽ>úòì®+×d¸Ó£Ûû¿÷çÿùîŸ9âØù¿úÿ±ÞÌxXý¿ë×ϬÅ3&vý_ûoí¿OìÖ±'ÏüXûíÿãûñ7ê“Ä/q1ú“GSÿGºëÆ!Yÿ/ý£ÿ2§¦SÖÿ32Îfõÿ&r÷çÙ(BæÙœËûmõÿŸ~úg¿| çfhѰ~ëJc]û¦”s;«Úl3 &‘üûÑN³ 'ÿRMh\“CìWíø²#,uà£ð'í0 8ä#òû+jäÔãÆ|7»­Þ¼~ó˜Ø¯_Ÿ]bøx¢*¸©ß¹ÝYøsž0qåït^STG®‡P¬Ü‡÷g÷YÚxñÀ7²µ¿ô£x•kC£ñDcgØ£þICSúðÐgC§ŒºÄÒÕEÑ÷<×W]èº+KzÛ…¯ëðšsÁùÞÿéˆ[?íýßù¿óõ?]¹úÿ¬Y‹fÍØõ×ÿó§¶O批2‡ÀÎXûïììÔµçÖþ[ûŸÉæ^ûý?kêúëÿgѽàáèúÿC©-1‹ç‹§?þÿê-”òÁö3y°º #h¦P®§gv(£ü€7B.ÎMS¦i”~éébü²E?œ|€}Ùð–NhåúÊ ë¦ûE@ –6”ÝR^#üÿØ»³eMv#;ЇgçtÈb=N›©Š3kú9Ú$U±©ïú¢Íò¢/úÛ¬CVÏ™‡lÿ±þ™¢TªQÍâBflD‡8Ü׈@£=n~^‚Žov\ÉO‘ý·În*¢hP-€^všá|Ò.4øHÛòsn×0‹¬Û§ÓFeÕc± ò|rN.aË¥0ÓN›òêÄ;zçÛÏÎ%\Aº N¿9_ðlø÷þ0÷ ÷¿ó?s¦óÿúÁü ¿hzÄyõõ¿±!æÍ®Asž´¬­;~&½ë×JÆ…˜>©ýwlÁÚµÿéÎÚÿõÿø¼ë³Õÿ«ÿ_ÿÿacšO?üÅÏßR” ˆ*®ß¼y³` ¢lOç½æøŒ!*ß!̈Ù:/¶ùL9¶í¦p†½Œà‡As½‡Á;™,ãC;ç©/r…-:õm™! "¤§Ž]¦­Êj‡wXo oåµ…,úá^Ÿº¤ã#Ûù˜äû®”ßøÐ.¤Ò~5;Ìðšºòž0×küå¾€×ÉÏíÿ¯ïcðaªŒ#a¯¯‹í‹ß@#{ëºúµ÷@ɹ/éëÞÿÎÿÎÿ3'¢WÿTÿWÿ[×­a×Úä\èúvC?Öì®ÿµÿ®¹1ÆÖÎs¥ö{~»cÿÄ6¯ý_ûŸÍEæ}Ì뿘;—ŸÂgÉz»ä1’äͱeêÿm·l_ÌÙú„úñêÿÕÿÏøømõÿŸ~úWò–ðDÊÁ!]#ïJõÁŸrK7;ž(a†‡]Bhì„Ú÷b]“g'’Jæzó?Ãïæ0Žgw“úºêÊÔ»§+³2†Î¿ïÌ#~À¡ì„bTkC@µ¯¿þz í´GC|•çˆ&LêwCôˆÄ‡oÏŽªäËÓŽ€O®å…Çò¼Ú6S²Î=Žvê|îO¼ÂcO.~äðëäËÙ ÜÒn;϶??)#-íÃ#<ïürŽoîcïÿ,žÓ1¹w½ÿÿÿÕÿteõÿ©¬õÖ7kJÖ®ÿ]ÿÙyµÿžm·ØµÿjÿG_²ù×6g¯³ÑkÿïæýSÿﬧñÕôI‚óú§7èU}‘1SÿÿyóJÆÌê˜é§„Œ©\‡Îµ¾Œ÷Ûèÿ?ýä/ÿøm¦!i,£Ôµ&-JfÍJ¾÷G1^v7Ó€EI·œ+»åçBÇåPgvg-Ø2t;eMÖù" 2hÅòÅž 2Ÿ,=@–´€:€+é ÀM;ì x„úâÍ ÐEž…¿æÓ}Öð¶Î)»4ã¯þäéiÙöþîý»Ó÷A1¼R‡~¹ /à†ÿT²õäÅî÷:Ñâ/ÍýØÇ§O´)ÛJñ^C»ç£_Þ×ùDîiÎÃ;ùä MïïÿcÏX:ÿ;ÿé˜êÿ£ªÿ}Ðõ¾L<¡ëÿìf¯ý÷±S0kgí?vníÿÚÿõÿv¡`O_¾íúns]ÿ¯þ¿u‚ÿMOÄ—^ÿÿ7ã?O?ü󟽌x4Pç1@à$ /C]Љ‚N6É_Pi:Ž—ÇÁyŸG݆fÃ9ÏB+xÔïå‹—;‰Éà@C ˜àzþlÞæ_i›n}œ2òõ‡·vE6²úÕÃȬ¬wU­ìÚ6i1Ä  Jºó|eQyÇ:÷°‘!¼É’Ç*”Ùcø‹ÑŸ2j]r§-v¡y„9U¯ú):/¸w-Lmc<VÒR×òCsë·ä‰µ ½ÿ½ÿÿÿt½B'Ð ô†£úÿèÔêÿ®ÿ]ÿkÿÑ“µÿŽ]Yû¿ö?ÿ'>ÖúPõÿþ[ý¿úÿùßõÿxD°•þó9ðBxí%壈€Th/9×ñÒrR¡ka¯ç4Ê+[Ð@/¯ß¼^>áOþ‚XY4@ŽSÒ_Η¿øâ‹Ý¥5óÿM‘Á¤€&ÏŽ-ùQ¤xlË‹ÝÉR^9uk»k´w@ȹ4y©/mVîžÆñÔú´ô#ž”Ù>£}õEú-}tÊŸÝgk(“yÚ÷ù´Oÿ¨û€X,ܼãä;> IÇß¹r©³÷¿÷ßxéü„;ÿ«ÿ«ÿ»þg=§­—‚õSº ­ëí?c¡öߨç×+Hjÿ?¦öÿñ5Ì GB|qý¿ã_?ëúÆEýÿóJ'6Fýÿÿ6þóôÓ¿þÓ·c•í;>(\à‹ÉdçS ¸¯÷RÅKž²Ò :åN‡?ÿzOiIcþYØ–n®<(0/Z‚“¿u YÐHsÒ)ûp6í¬Âkòïò(ÿþÃ|¥pò__/¦Çò&4¹¶›i—ÉS'ÀHì=Y@¹<ˆF§ÎÄøx‡Wùò+m·ÒåRÚêKÎÕ`Úº¦(y÷ÑHïøšÚ¤|äp~?È ŒL€>•KמÍždòŽõ«÷ú¿÷Ç q¸Gççÿ¥'雌 ºƒ¡wªÿÏÚSýßõ¿ëÿ±/è úÅWû¯öß®3kHíÿÚÿõÿÎzi>˜õÿF?̾húD¿ñ›×ÿ¯ÿÿô¿üo?xëëƒÞe@pÜÇâØw,펡™TŒ10G0ˆ„]†n΋Af;Ú >e˜/Ùý´qÊdgZA:PÅ0MÙäVÈæ¶r^ΔrèÅ»ü=Ú˜Myd!õé„8•ŸGôÖкÚùäKw òrú­cêöq¾§óxŸk€ÑUsŽne»vmý#çY¾gN_å‚Ì®v Ò®\O‚h¹ÄÓ•¹Ê¡Ð.‡‘ãzozí'“`›öôþ÷þwþŸ—•›;æPçÿ|IÖŽÑK§ÒÕÿÕÿÖ¬]ÿ»þ³éKúA\û¯öŸ±@GX;jÿoRû¿þßõz™}Ç":¡þßóμ]C¬%Ó/ÑôˆPÿÿœÛÖÚñçëÿ_›Ž~·e(ð 'šmߤ‰¥·æb¯õ4P€-t÷rÚ-¯¤§­â;Ø„&}·}%ax% ÿô‹:#OêJ½F­òp<í°óêÊÜ:ðÛvôþo·ôþŸ(tþwþWÿŸµ-ú¶ú¿ë׿”×þ«ýWû¿öÿ¬ã§|‘øõÿNŸè¡þßY/ÖלqžÖO>â£Ç¿MŒBï9êÿ×ÿåò_á?O?ú‹?z @TqhEüêê:;¡ (ÊJº'/@Š »ƒsFz¨É _ç¨:=â·e§Œ€Fyqø1Vž«ð*ï­‚ÆQž;à'ËÚ5AÝv_­ÜÿǤ¹Êüj¶uúô5ž^ÿË/ùÙo¾8e/yL"ÊG°s)<É— ÷h{2®˜ Þƒå—uQîÚ´»Ãn´x.ß‘÷ôˆ‰{¶Yâ-¤^±{öõ7_ï–Bü\kcÚ, 8†‡k}¯~|zÿ{ÿ;ÿ;ÿé1zdõíèŽêÿ³±ú¿ë¿5³ëÿå N_°jÿÇ c[Õþ;?¸Öþ?ã"kÿ×ÿ«ÿwìJëFýÿúÿÿXøÏÓÏÿã¿~ë%zÖ:,ã¸ìûž80£‰]Ðú§\€“€=›7ùø \[ÜS‡ó€,sœçÄàeÊ-ÐsÕ#ý—¿üå|¡àÕÊñõW_}\ÿЫo*Û÷;á§|ê Ú =;‘ðEëúàùÒÝCÚHC«}[ÏìSG-e´Ù!¤Ýy'9ïý¹DןÓïºþôž^Ûg/GÖ½5ógø¤h":å…}¿ØÕŽ•Gò4ëÕëWódïïççÿè:ºp:‘Ѝþ¯þŸEdל®ÿVÒó*ëj×ÿÚµÿjÿ×þ¿Þ:ºÑ=úÃQÿ¯þ_|åø§ÆEüàø©ìîõi¯¸þìîúÿþóô‡ÿþ§o ¤tðXÇe™kÊè|¹î-è<ŠfÀíù åI=@É” X#ÎyÀ—-s-I£‹Òc J˵ú|F’3åq–ßÿýßßøÝœ¿~ýzÓÃ7õMalØ%=|Gø•0¥-Ú*˜ló7³±RPÂðRG”³óLDqúCyuá'Þ2ã úUN¾„mèäåËÒñMßà¿ÎäÕWáK>r¦¼z`zzµ×ùò˜¼È&^)ßûßûo¼uþwþÓ=ÕÿÕÿ]ÿ»þ×þ;¶äÚ\c/Ýí>iµÿjÿ×þ¯ÿGÔÿ«ÿ¿>uýÿÅôÅâãW æH¾¦ŒÃ:êHZ®ÿ6üçé'ówÄCö¥:LÆy¡ñ…=çyɵ´ux‡„Ž@Ò ~½?` ^¡W&õä‹}ò2òÄi<ÔŹúœ+G6 úÔ›úÐí Ê'-ޏt|·ã¦°ò&¸ãQÇ—¯^~öúÕë=G«ÜÃWP—òicÀ#Ýn[ iÚîŸ]VÊ ú+r¬¬“·ýƒöêCeÃð ü)·.9îíÄ×û®¤q6·×Ä‘§-©#}„à¸FéÐlÛ& ç½ÿ½ÿ™—ÿÿôˆ@7DGTÿWÿwý?6N×ÿÚ«GGÖþ«ý_û¿þ;©þ_ýÿúÿÿ<øÏÓçXÀÛá-Æ@1P0@¡˜¥;ÖÁ5IYC7ö+|)«º(s¼ï€ÐåÅPòíþ1á9Ëû‹ÿ¤©S Qd™¤ÝŽ*~È6åB—ºðˆ¬hw‡ÖÐyçÔ’fG×T|€í½ä%£ô?ÿçÿüÙë7om¶vA«áI&2ë²8÷bym÷^ºÚ&/²F>´>Šnûw®—ßðõ¥3ŸÇT ,@˵gÎmNùjøªƒLé“|ÎÚn,eñÛº®ûöQ=ó÷ÿŒÇÞÿÎÿÎÿêÿêÿ®ÿÖKG×ÿÚµÿjÿóMÖ†›ºöý¿úõÿëÿÿÏÅæŸ¼µ8>9÷àæPØ;ä ’¤ÉWnÎg@IDAT;œÐ„:瀣찲 ˆ´“þ¢Ý]Oð#¨caP‡@&A9²ìùÄ„> м•ib´Q.â€:‘OþfÚ<ùv`ƒÂë»ßûî­äpàîíÖF­€ ŒÜï?œ/6žúžß¶ž•ï4c늌òµÐD¶Ý%5ü¿ mß_5ËwÒ|9P†Ÿ4ò¡¾[M™‹§¾F+ MÝèÓ/½ÿ§ÿ{ÿw˜ì81ÆŒ„û<˜AÔùßù¿CÉ‘à¼úôíÌ‘™HÕÿ3ºþÍÔõ× ú¡ößù”~¨ýWû?¶zíÿú|µúõÿëÿÿ÷ñŸ°8& `„úàÆå„˜Dâ\çxç×ËË=¯èß#èñµ»'€O€“€/Œ[.ß¿;ï´Bo7’ÇÜÐ:;x`¡à/^\\´çô”SVPœïÉ•¾íž™Ç°D—÷B}óî›GÙÈA^A9 •v„óh£ÇôìPƒ}êÿõÈúèSmشӇν÷JÈ;ª¤i§ÅLØÝkè¦>àÁ£ÞIӯꖞ>×7xHo»'^¾W¼<¾ýXvi½ÿÇñîýŸqkL^ónâŒ!ãL<ƒJÂŒ×k|uþ¯þëü?úÍx¡Wªÿ¯5µú×!º£ëÿ±ºþ×þ£'kÿÕþ_“^û¿þ_ý¿‡Ï?¤þýÿ]+oøÏÓÿïÿë[àÆ‹ùª]Þ„HZ€‰Ñ9ªu“Ö‰44€åbŠ7L^Î}éN€‡¸b×Ò~Qp@3Þ2^ªãÅÓy”PÚ‡ZÖ›¦j'‹Gí×+çÐ%¸V¯xe§Oai'–ïO–ïÏ®/;«¤ÙÉ$äÑFåWÒåGÎìxBžäÝó)³ ÒH©ÍÊ….å=æ—jòíCûÜšó¤úT_ýõÖ^izò#~òÑo_NL´+ÏÄ®4Ê,è†ïÿ¾'Mßõþ?Ïc¶ó¿óß¼¨þ¯þ_}0cÁ?kJ×ÿóãU×ÿ³\?l¸ì çµÿjÿY?jÿ?¡öý?c þß/×ÿSbm‰Ì‹úÿg õNRÿÿôÇož~þÿÍ[‹K@ƒh•1@„ìÀxõ¼_™UÄ9G»€ÊÐ3x@Ð%@ú¶ž!Ü›5Ö·ÙMê(“~ç½u\²’Ï•™¨äœròÔ»¼ÉpMv=iWä²ðH$¿˜’GØzÄW[#_Ú˜zÕžsåœ;”÷þÝÆÒð!k\KÏ=Q~Û?õÕ»oæEôJÛ¤;_Pnòïu*°¢(¶ —,ʨmø¦®íËKÀÞÿÞÿÎÿÎÿQÕÿ£«ÿÏújyȺ!Îy×ÿ®ÿ숼“ÍáÇ´Úµÿè öæÚ™µÿuÇÚàtgíÿúüßúõÿéÈúÿgƒÓݶ|úáŸÿì-cBðHÞ‚{uƆð(4Š•ãò t|ü¨ÑÃh½x„Îå(@ 4n€EÈÍyùbaœ/ô`–Þ—ü¦~çÊ, 5u“‰¬ ¾Lù•-1ù&¨7;ªî2å|™­-ÜÃhe!O@¨<å1ÀÕ·f‘ Ÿ}„pÒÈÅH'ÏÒx!ûÔ䛽Bx'0èô%:çÊ8¶þá«Ýú Oõ3ø–öâ­ÌÊ3²G>`JpOOçB•“ SíÊ94èzÿ§ß{ÿ;ÿg^˜{ÿ4ÈÑËô…@g8è:+zÊeÎC·®?É«þ?? TÿwýÏüèú_û.­ýwœ³ÚÿµÿëÿÕÿ«ÿ6íÔÿÿÛñŸ§üâçoTë Ä²šønh[`「s¨ø2ûî›çÝLëÜ\¼q^”}H}õÕW \P€Y@txy40`Š|áªmÏñ!'|‘ôGþå„.ß[úòãqMXãqbW€(í èã\YAdùòË/7ºù*`€¥­chÔ­ýâ<Æ'ï¼ã‚‘rÞéµ<‡nÛ¡Ý×ù‚`#Œò9´Ñášlbõâ»×#×Ë‘Uº4rùË/w·˜4òÈOØ:‡ßÞ>_P ÍC¦NÜûßûŸá`,uþwþŸ¯¹}AqVÿŸ¯ÓZ#¢oÅÕÿgŒX“ôÇãèú¿*5k~Þ“éºëí?:õ1Wè‘ÚºäôÍÚ°µÿkÿÏܨÿWÿr #è…‡~¸ô&ûãž¾´—¿[ÿÿ_†ÿÿô³¿þÓ·‹Üð„ntFò‹ì¤³ÊîBk C¼´< /Å£wv êá Z0hÀ#ô_¼ùb•2:ùÒ-gÁ’úI˜]E1åDÆ¥¿d’®Î´eeœ4ñÒM{—ÇÐØÉ¤^»«ìÆ9ßù:á¾ÿýïöŸþÓúì÷ÿ÷WÎLuà¥/Ÿç¼LÂîf!¿t‡ÇLl„Êã&Êâ(áÈ—w‰¥-F<Òέs€¾}yý´Ñ.1»ÌÄò‚6Ù¦Êá}vcm{]LP¯vI³+‹|BÊ;L½ÿ½ÿÆ…Ðùv7š?BçÿÙ]DáTÿWÿ[;]ÿ»þ×þ«ýWû¿ö?;‰ŸQÿïøžú£þßlÿ–­PÿæÇõ.ñø[õÿÿvüçéG³‹b1ˆ:OB™ÇߣvH­³6/kâÌ.H£ìÚï̦;@¿ûÝïÎËØÏWñÐÛyK]qS·A½ïG˜:Ÿ|sÔåPnË^qÊ£u„¯rÎå§Îµ‰¯ðRWÚ„Nø½ßû½Ýe”6‰}æR,£ðwà;—{Žž€1à’€FþX:mÂwTŠÜ)£'ÿ;;чh땼Êã…î™rï0TfïÙ%>xËäE–Ô•¾‘ßûœŒ}Òûßùo®wþWÿWÿwýïú_û¯ößÙaɆ\û»öíÿñµÆ™áHÕÿÿëá_Ý|®ú·§œŒ• «?&®ÿ6Äð×ëÿŸõE_ü&üçéÇñGo;h&`D­8Ï$|xVÝT&eÅòЉ•p½ðÈÝH÷G î`>A9GêÞ?xÍn¦KêÙ-öC¿p¯_ÙÈâ\ý®…•ÿZ\?ª‡ü“oêà©^e¶®Ké(Ÿ2xFV†kÎÑç]^h‡´ßµüðÍcúÔ—ñÑ?úMêÔoÚﱇi›4Â+‡·t±Ç=Ö#Oín°« i‡:"û=–Žlìý?ã,ýÖû@XýÐùßù׿Ñ)ÆFõÿù¨ú¿ë×ÿÚµÿjÿ×þ¯ÿÇFZ›iüA>Eý¿u5¾h|Ïúÿs¨ÿÿ?†ÿ<ýàÏ~úÖÄ2©ç+ÒT îLšàÜDÌd|ùj^Â9`IŸxyB®ôó(ÛA0¹SÛ%ÃS ØÁ?À‰òBdã(ãZ@ûúÍë½v ÀgÃ¥(Ò¶“˜¬çöNá‘÷ìNÒôáéœcvo£<} ] *ÀèÕËWwzín+|'l¿\ýæO‡ôéÍ÷|h¤ ü´%}®>íϵX¹ “ò´@r~ñÅ ne7ÞxÈsszåõþ÷þwþ?ïðìüÖ¹Ñ=ôDõõ¿ÅÏ$ˆ‹ÝÙÛõÿy-×/]ÿÝSûïôCí¿Úÿ£jÿ×ÿ³n:ØVñÃêÿ­Iqì‰Ñ•õÿÞÀ¾Š ^ÿÿõgOxXû(Ý b43i'“‰µÉ4™déÀO‡Vº2) ‰A+M`À}ûí¼Ï)!¼ÝE4±¯çááN&/ž ™ÔdJ:ÚÃo¤Ü44@AP ô(+ã Ò´áæ-ÞáâÙñ$#+Ýyú ¿®Dfu“#m{ÔC91Þæ1Á•o®ýÖàŸX:þ DM¾z’–úN™06eÐè4ÊGFéyùü«×\S_òðDG^éâð ŸÞÿÞí}Ü;ÿg÷¥¾èü¯þ¾®þïúßõÿØSúA¨ýWû¯öíÿúõÿø•wÉ“CõÿëÿÃþ®øÏÓüûŸ¼ÂØqáyË€ŒŽ“Øœ4@Ëüg  Š6}SP$? GòBËÁcÌÈ_€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶oÃ.ð<ñ—îH½Ò“¶Ì†:0‘zñ¦IŸC=WÆ£½'á¹ þŸ‚JúJº~{=àOÚAf€ÐÇ‹¼Y9¦Ji—¶‘i*|äšy©[Ú'¼ûòõ%8ý§N-Èε´­úíÀÂÃ.·wïßí}${ú ]ïÿtà܃k$\½ÛûŸþØy2ÔxŒ]aÓ÷ìôUæ¡8y¡íüŸìü_ýG÷ÆIõÿ€ãÕÿ]ÿ͇ѱ£®ÿµÿjÿ±¿Ù¶µÿÏ“(Y?kÿ×ÿ«ÿ÷üÔTüZóƒOÇá[Ç/ošô9Ðl˜8þÎIx.cM®ÿÿÿOÿow`¹an¬›ÌàTX(â„Æ¨ÊÍwóOã§yÁ{”Äøpdñî|Oú<®3ÿÔ/0äìøx÷Í»•zRké&=¼÷zäÚ,ÿ¡c``¦üœ?hpñÕ¬8–hœ«7ü"³ôÈZï²€H¡×Gy +|í´B“þ³øl['N;–vå8²l]s­?"§º"O&§rú%-H䙯ïc+û¼[ì£IŽÙ„Íëý?qõGïÿ5ÏfÌ Æˆq—±å{Lû/ºsýÜ&õæA}‘v¢òN)ÊÀŽ&A¿ø¤¬öê—ó.‡|»ÎÈ…²ihܺ}·Õ¤ž>™Ê¥+û$‹œ§^òZøýª+=2§ï”éýϘ8÷/÷PÜûF•±Üùßùo¬Î¹tÑQý_ýßõ¿ëÿÚg¹8Üu^ûïüà£;jÿÕþ¯ý?¾Êü¯ÿwž$ªÿWÿßxöàÏÂYÿP¸Æuè¸Åâ??š¯28ü:îÑ=€Íîäâ€:u–)´÷é×áL‘—À¡Éuœ›»£:»4¾3ï‚Z~íZá†YÎ/,g±ßGæ†/¡ñ„ª ø‡4b¿Ê7i/MdØAÇuÊ>d½òÕ•¾˜B+KÊFerD.un_ yÊ}ﻼÞÿG_ëGý¥ÎõcïçÿÎÑBçõõ׺ 묵µëÿ±Õ¬µÿjÿÅŽ2O„ÚÿµÿëÿÕÿ«ÿ_ÿ†ÇØ>2¾ößÿÙw`1¾0²›IøÕl3”6ýÉón1Ú]O@)GŸ0$»UðpžðñB6%æÿîÄ‚}Áã>`ʉ×L¾ÉƒF}Þíäö¾¹æ^ÀÙΘrdqA/¸ÖWb!têXl^0ïìûoè·Ó‡.ƪ˜##ÆO_9Oàk<ÒoC¼´oì:»ÉãrdÚ¯0 ýÒM¬‚tmÍuúzåÙû9÷áªM Kü]“©÷¿÷ßXêü~¦¾óÿ€¸ÕÿÕÿÖ ëI×ÿ1º&XsÙâ®ÿµÿŒƒÚdž×ô…ù‘›ô\U<ÿkÿûYíÿúæ‹`Ž8¯ÿwüÚ£+VU¬ÿRÿÿàt¬`Ìü.úÿO?üóŸ½Õ»Ð\Àˆ¯‹éž¬&“r@sòVòˆÇ÷ÏØfmÂõ'  žÛÙó5ÂýºðIeg=û¨,peë»xäfÝùÊ_9`Ú/\L¦Iæ-?éÚ†Æuxnm™°mŸ2Ïuœ5Fé¶o^ÐîшÝéEΡM9çÊ-Ę®É%oÛzÆìÀâ œB›úÈô)oþEÖðÔ†{¾Ç$æ^¹VNð¼Ünsm7:aۮ̽ÿÀíý?kÆ”q³ãeâŒÁÎÿÎãÂ?¡ú¿ú×¢k]ÙA1ºþ{ªëí¿Úc?Ôþ_ªöý¿úc Ôÿ_½þÿÁ2ØÁjœ Á3ÎÕùûôƒ°tÚ#ó1Ò‘I_Çu°‹ï:+·ֿ9ñw¯Dœpj.¾”´sUi3:ÎÄ>W;tòÑ?êŸk VêKúòqŸæß¶ÍùÐõþ÷þ“F¥ñÐùßù¿ºéÒCôGtjõõ?‘µ(†;å±ëËè®ÿVè[Œý o²Óµ›ßõÿôÃÕµÿ¶;vœÔþ«ý_û¿þ_|Gš!k®óú¨ÿÿÛïÿ?ýð/~þÖ ^’q9GŒIqŒ¥Y7uÎ.”ÈsÌ¡­,òåÚóîÂ`xϹ‰ã5†'0äQ=ùÆš|2àçÜáܾ9ws±r¨¤Ks„Ùí Q×Ö? ÆÉ"‹sáÞá…‡G(Ã{xiÃîØšú•ÅûÒ½!/²F6qÂvõu½ts.ÖÇBäöñ1}&ßóP®ÉLVÁõüyÜϤÝÛNÞ ½ÿ~ïýwÆJççõõÿ®/Ö¾®ÿ]ÿÇhX;…2çµÿŽ=«7jÿ;zíïÚÿ;OÖ?–öqµØæŽÍ~ì­Úÿ§Oè•{å|ûjÖŸúg éõÿŽPÿÿ·ßÿúÑ/~þö:eð1(uW‡Ù,:£?ä-дIg!ÂkÙ àA³ü‡&¼ Y´îyÊíãnû%öñÂx_!<Ä÷#ùâ#ÉOä»äâGýh”U+rtr.}':™æôd7¥¸@ÕM€—~Qo¼u(/lÊä%DþÍ»ÊêÏmûÄdˆ3¾)³u\Œp¼§;×vußy‡&`›ëälª÷?c·÷ÿy~#±rÌ$œ´ÎÿÓOÿÕÿÕÿ–À®ÿte×ÿ£¶/fLÜ×k«PûïÙ&5oµÿ޽]û¿öý¿ú»PÜþÄßIýÿé›ßÿÿÉW-œîzŒ® ’û ÈyÀ’½€(+ØÜUèñ?‹’òu¼/eA+€àfŽ\+¯l…á¾çá%–·/¦Ê.è@ž É÷øß·ÝTÊ…OÊ(Y“¿Néð:_M9G­ŒÚ=ýƒæªG,è4uDø¯œ“¯”zÛËÃ'üÄË}ò’ÝóP.ý•¯¾;_yá§\ø'-ù¶ dÙ¼aÜûÆjïÿß;@>ù“±¶É3vfðì€íü~·\çÿóø¡[¢k«ÿ«ÿŒ®ÿ]ÿ­±µÿjÿvõÚÖ×5ûÂÚ!omÖ¹vžµDìºöí±_ÎØÉø¨ÿwÍvú„Ks^ÿïØ¨3ÆOlÕ虇o?»È'¯GYÅï¹úòASÿߤÛ~ŠŽNåúŸÂþáfí``\ƒ<‹Užôb*œ[8'•‰¾b4Ž»ü¯ÅIºk‡#ÒÕ‘snø ý´~y ¾˜–2®ÃïÅ<ˆG‚ô;?¾{÷ni¤{$Ì ÖBvï½çï½OjÀ ´+²©Ñ3¶xÚ±%_^Úøè+;»æß]¦ðøV;§ü|îpòÏ¿ïHŸä’¯¼rŽOyÝû0€šeO? ½ÿ½ÿ `_cʘ¸¡ûùæÍŸÇ 4®çºóÿèµÌÝÎÿÑG3.è:/z/z²úŸÚ-\ýÿX³2FºþíÚõÿc€'º5±µ¨ö_í?ã@X}::U`³Ð'µÿ?žCµÿëÿ­/ZÿoõEýÿßnÿž{㌎ҟÿ;°/ EzBXqyŒP¦ŒùίϰØw, 0 Ü’Çáâ¼¼|ñr ÷›?Œ—& ~ä¹Ç‘cåT÷üûv^¬:òœ6ÌΧIO=ÒÅáM»£¤[äò%5@–4/¹säó¶isê‰hµÖc— ÒÔ»| ³{k·Âz¾òÔ}Ê\õ_¨nxâs¯çôæÅýª¼î!å¥o\±> ­º…ä¯<Óï½ÿ/wlôþÕùßùÿßÐ-уw]Sý_ý? Ê®+]ÿϺÜõÿKµÿjÿ±1kÿÏìµÿëÿÍ\¨ÿwücCýÿÑõÿÿAøÏÓþì§o8 €(ÒîN‹s´w z@I –s}+ô€+[휆,j¥R>ÁÑ'–ç§ŒN@ ¼S÷þB«Î¡§Ð Jå‚üû¾ù…÷žgÇ•rûxÓŨ!/òo{®b9ßÊ®úRïëׯ¿ÒÐÉÔ;­¼©›LÎSN½îÁ^O¹s2íØG4çêÊ+—-Œ‡ðã¿Ûޫμl9ÈäÀCœÐûo'aïÆCÆiâŒù™wæMçÿÑ7úE_uþWÿïzRýßõÖ×®ÿµÿjÿÕþã`í¦ØSµÿëÿ ±ùuõÿêÿïxˆ_>ã£þÿoÆžþp,µ2¬#ê׳óXŸ÷ó§çÇÛäÒ¢|•û|®ßÈ“÷'¡¡”A0h÷ýQó˜žòÀš8î.)ô×§:vwÔ¸ÇJå6òx9¼&¾t×êF«L‚:¶MWš²òÃÃùÓç×W‡Öµ2BÊŠÑ;í³‹ìž¦9^ð%]}-ýõ ìÕËWû¨¤4`™€Z ½ÿg|õþwþæsALwˆïs½ó¿ú¿ú¿ëÿ]'tý¯ýWû¯öíÿúõÿÆf®ÿ_ÿÿŸÿÙ—¸sÊÁ]ÀL€o8v¼˜Ãã"ÙA¸b¨IãØ=€¦¹ÆOžøý»óˆ 7ÐuÅ"¯ìd,à•<±ò¨ ¾”Æ'ãý-X |²FŽÔrËÀ9Äj'¼½&ݵõôcêêÙ&^<½Øv Q'€hë í´ã›¯¿Þ\€¬W¯^® ‘}雩'ò%ŽÜKsû³»ÝôÏ”ù¨ C£lÚ-ÖrŠñó/mŠSÞûßû¿ÃËxº…ÎÿÎÿêÿêÿ®ÿç‡1ª±ëÿØwµÿv•¬ýWû¿öý?~Tý¿Ûf’ñ;ùšõÿŽQÿ` Ç`ÿøÏÓñó· jÜ”ÇõTvoÕ‚W3094hfÝ…rî=:àJâ)Ê`A+=AžZ˜åF+G£•u„v ÌŸ\‹Þ8÷õ¤¡ ]øX|ìÈßóAŒ_Ìû¹’ŽVÀ—ñ PÙu–ºÜ !üïí’îš’ã›ü´%å"×§ñò¾ñw-(矰rê3Úlá-|ðÉzÈ(ŸËcÊMG™ÈÓûÆ«>ÔW½ÿÿÿÕÿÕÿ]ÿ»þŸ×AXvPûïc»VŸ°jÿ[B¸/nžÙoá 0çQâ(ÑU–tìKCÀ)gr”Yz|.c&å•ÝÏ&_ÀŠÅ<ù©È2Â;ÿÔÚ ÞøHÃÝÚ´{^ÎÑ¢À‰}©D…ÎÉ &¿w_yVäû´t!ðRÖ1Â,ð·|®¶å?ùïf7^‚ø~œÄý»é÷¾¿ó¡V®ÔçñI÷/1©?} ÔŠœ©Û62‘Fy×½ÿ½ÿÆ•1"¾AiÿGÇtþWÿWÿwý·Öf]Íz쇟¬¿tf×ÿÚƉñQûï×çÉ 2amÐËÖX»´öÿö‹¾¸Û^ÆNôËdl^®c÷'Æ ú§öÿóÐúÔ¡oêÿ]soÆUý¿úÿ¿þÿÓüûŸ¼ÝEc&5¥(ØÑeIù-¨1éÎwò_»ÖH›2?-ùK?¬ðpNY(§ƒ€(¾V$¤VϹüÔ¹çs-ÞGø¦Z¼¤ âÔ'&DäœÌ¥ÑšPežòV¶‘åÃûyQüЬ$›zb€¦]ò#«²‘À…_u(OÈ.þè89ûµD&Î#™á­Lä‰ìŸ¦åZœ:S&"y´9ï!›îÚžÛ?“"N?"ïX~S~.¶\ïïÆš1sGÆÊ~UÓxš±wÙežÈ_úÎÿí‡Îÿêÿêÿ®ÿ]ÿkÿÙ½]û¯öíÿúñ‰ãËÅÆv}O˵86yòëÿÀkûRù ŸÊ¸‰·?òC³œ¦¼’é#¤ä¼ø§_RŸüðIœ´{I+›v®ÌîÓuÈzÿO¿öþwþg^¯éü? ÂßK×EOÑ7ΫÿŸu²nJÿ8O¸ëæê6‚µþô›uÎ:ž>[Ú+qçd×ÿí{¿ü¦¾J~×ÿ3xôCí¿Úÿµÿkÿ×ÿ;c kmý¿úôâ?þóô£y–wÀˆq"0èl˜E(ÂÐ[”s<LM`Ô¬èbhñp-0„öq}å=Ò”¿ê‰Á„M %çxx” [ïðø4$=4+Ó´ApîèmÛ\“EPFH½ßÅ^ú«½€Ÿ¥@ͿϽH~ø¥Œ<|í´úp_ò•Û>™<†4ðMîWXýÈðÁGÀã¤Kû(ý²ÉßmÂh´c®#“29×·ŠE–Mßvœ_À¼„u*yôÉ–¶öþŸñÞû?ƒgÆGçç?Rý_ýoÚõö¶~îú"Ãzt­'»†uýïú?ãÄøØñp ãgÓfÈÔþ«ýGuÄf͹X¨ýúa ùët:«öúbâúõÿØõÿn]ú»âÿ?ýø/þè­zº%1éyJ"†‡kÎ zi1N¤1LƒI¾ÝLÎ×h–ÏUÀâqB»¬R6|O²èæZžúRWê¾—M]âGú%¿ò{Lžº•Ï#€i“r‚² bˆæ:uEù¨ðt-OPne’Þ¯¥¬Ç=n….[É—øúƒ&u(»a*^Þ韡¹ï Ó?Ë,Ó§Â….Þ;¦wùðÌ}•îÚ‘Ý+f7º½oCÛûÆ¡~ëýïüPïñÐù_ýOmVÿwýßõ´ëÿ³ 7¶Dí¿ÚkGÖþü°m½jÿÛÞ4FêÿõÿÌ ~¬1±kêø¶õÿÏ^ÿÆ‚¯š(Þÿd÷A²fÀ‘_ŠÅ£u:.ƒ( Ì¡—~WÆ®Œú èÆÙSÎ'ˆå ê yIô¹:ñÄC¼ÀÖÄwz`Ë]–åsWùjâÞöÉ‹“‘A ÆÛD!êÜ;´NL¡«îí£«¾´‹ÌdðrèS»­ôkê^íc‹W])ŸÉI†ð“AZøî5ðdޤ¡‹üúÀÎ,ÀàËÒλŠÐ¦4Ôå¤÷ÿѽÿÿÿ£ƒ/Ÿù@¿9¯þ?à ]JFWÿwýïú_û9UûïùÇXk©#z’ ]ûÿüo=M¿Ä6¯ý_ÿÏXÈaŒÔÿãz×ÿ·®ìx»³þÿÁž~ò—üÖ¢PÃ@±ËÇBãü>ÐlÞÐË3Éä;ìôÖ8\+¯“ÑI“/Mà)›:Ëü H­!ˆv%RÏ^_<–ÏðeW’´OCä㓺]ü[lÉ»ý0ò;ùâ|6žÜÊIÛòÃι°ïΚXxõÃtÒCc±zÙr· r‘çQføä~¦?¶Ý[×)ŸþÃMèÑEŽ•¥÷{ZŸôþwþwþWÿWÿwýïú_û¯ö_íÆaíÞ\ý?þÒy¿sý?ã¡þ¿^x|HþCýÿéƒé–à Û'°‰+üj0‡€%Í¯È z'$\©`Þ·„™¼$Ècï\Rnr·ðæì#tyÔZ'yë¡ÐSß=~ŸºX!4ÙR×Vy¦ìÊFæ+<®É¥£] fÀÁõü9õÌ5ðmhœç1Ci_ýõ.DŒŠèÍ›7 P HDViBê\ çÁv1»ú*²¡u´à×û¥ÆTmþ0Ü÷S‘Wp Pšý•z²†FiGø£Ýô)±ï˜º¶ý[ª÷_7ôþ_cGgÌø˜²Gçÿy·]çõ?Ý]ýô5AGì:Üõ× •õ¸ëÿ8íó …ÚǾ¬ýÇG8ÝYûì+ÿÙYW¨ýχ¼Âô ŸemP¾ŠdkÍFõÿêÿñ_ëÿ›/Ñ«gŠ\>Ü5¢_þ%úÿO?šw`ÝAŒG̉Ž:¥ä ®¬Ñz:j'Ò\ŸøR8èñ ²C·Ê™²¾”ëaŸÊ ¨ }·Ë]e"‹4õ©C,ÈK¾r[ÿ¤çæ×ëðŒLcô˜`ÞÅ1bÄØPÏT¯_¿þÄZ J;.yÐyÌ´ÂÊrѬó3ùèº1r—ð¢ myZïSðê(qrá~Û£®z\kCúfó'íý´ÏKë?ÍKýâ¥Xÿõþ÷þgNBçÿ3ˆÝù½Ÿ¸ú¿úÿ¬¸»þfm²Íùê’9GÑõ¿ëí¿ó#ç.¬ó‡íņ3Oµÿjÿÿx]û¿þ5Qÿ¯þÿY/Ögÿôÿ_ì"9`‹È¢i1||g&Èã+~ŒNštÂÀ5€Ìc€c†n¹M•1à ݜÊóˆ]~iÙ|yø -GøÃ¼Y i÷cßey½sÞçôÔp «3™“¾ü‘Ï¡M eaÛwRRW©Óñë)ð}R^_Nü±ë{ßûÞ‚X(×¼ðÜGì¦>ÀH~¶Œ£ häÏ> h•ÑV»^V¾éoA;´i½‰mÚ$ s6½µq C÷14Î5òºÞû;eî2nÿ\üzÿ·[{ÿg ;g¼ÿÿÕÿ_ïÕÿÏ?¢Øu‹–8š¢ë×ÿ6;>Œ ëÈŒ•Úµÿjÿ³¨žƒ¹QûÿyM¹û$£8ëÊêé¶úõÿÌãD¸û)léõÿOßüKôÿŸ~0/q_ÐÅÍÿü˜qXw@ò®Xšp§ÙkTÛO§³î4K(ætE=œÕš”› æÿó"õnîåï2dàÞc¼tiÀžŸÔ­Ó5G9;“M€¥ðy5 • °ÿ.ºo¾ùæ³/¾ûÝ囲Z­–Ï€SyÄ<}ÝqA«©ãÕìÌòÂûu~døo+ìJ‡Ï¸©3 SÁöƒüíé‰ Ëc>_î:‡´}G†½ÏSh§m½ÿ½ÿÆHçç¿q@gD§Dï'–/Üiöš6ZUó¬oBÝ^ý??ZTÿ?Ö&ãÁªÙõ¿ëtDtË(˜ù_û}™Pû¯öÿ(ÏÚÿ—ûÂüˆ¿só†t0Êœp~Äw®þŸNúض‹Ý—øôÝÇ4[¦ö_ýÿÿ öÿÓÿügoMz9FD¾’—4Æà‡ú( å4çúù9w彈ì#Gq •>Ù º ÷?SŸ9^ˆ,ê‡×=B ½Ø5°Æ[¨KÌׯÃäÅÓ¼h}Ê,P6u«Œè…ôÑW_}õÙ_|±×èz£|I·¿Ð³R~èS‡øÑ–+o2—ôÔwÊŸ¾:-¨6í"›<%–×´më˜kñ@“¿¼.pnûâT¡Ð)?qêJßà'-4½ÿ½ÿ掷kÜ츚1Òù@ïÎÿêsD /«ÿÏúa-ôGÎ鎮ÿ]ÿׯØÑqû3c£ö_í¿ŒØ¢t†8ºäžVû§Níÿk­©ÿWÿ¯þÿ¬%ÿýÿÇ;°,vqD³Ü‡žqXç›?ëÉLà˜ Í.>x^Òäç:eÔ¹ ÏÄŸþ"+oé§šUHÃÇ ñ‚P¦1žyûÅÃI|\x£ÒÏú÷x±¨vxôÀ&!ý/v('F§Nuoÿ)0l¼ ~ûùõþ÷þwþ›/ÿóÈóü«þ?:Ü.ßèäêÿ_ïz×õ¿ëí¿ÚµÿkÿóEêÿÕÿc;¯Ï}ù§l¦øºõÿëÿÿSà?Oðï~ü–òèÙË/€…”_›í#à&΄=Š+´ò âPð–·õ ¨${äX&±é9\«8”_zåÙy•º†xA¤•qèÉŒF8õ=<÷ty9RŸvHK{ñÒùâÔéz²¡5AïåÔûå—_~öÝyÉ»vËÇïå_}yÞ›õõ×_/¿”ty¶6ª_ˆ¬éËM»Ò#odHߢù4¨[Øv\»j\o=SWdïýÞ%×ûÆEççôSýÖ·êï”ìúo Í»ÁÚÚõÿãÐjÿÕþ‹ÊÖ­ý_ûßz÷mêÿÕÿ³vÆ· |±úÿ#Ñ#÷þ©ÿ?¸Éÿùÿþßc{Ãú«o>yQy 4‹]F 3[Àœt¦¶î Ÿl•ºOæGè¾Kùu&d{$OñFç: Sê²+j2˜y2ø”Z>î>ÖŸý[8žÄüš„ÞiOS”†ùÉ®LúL9éʧСÿ½ßû½õÙÊ9‹7cN¹wß¼[>Ê¥dp­nâF¼ŽLóà´½vfßË£”ŠÉóž.ò†nËOú$© ÞMÚTùÙËW/÷Ï´‹ Ësú]§îð›“M÷gÓ&N¾4ç‚fQ–†PE~-ɋǥ¯ÜçcE9À'ÒBâã:`‰tàJqú;È"Í{­ÄÙFˆ6`ËSd¾ø{Ùyv/í®(åç…é‰Pòt–r걋)&n‡ªkŽäÇHUNdNŒž\‰õ‰Ç÷=\ÿÜ qÀ!¼¶]ó¥2yÁ> °MÎÃmœ§ï’æÚÙ·Ïn¼Ô+?u ûˆöªÝ~ÙñVoïïçç?ýJ¯Tÿ­/¢§«ÿ­'tý?öE×ÿÚfDí¿Úÿµÿëÿ]Ëcý¿éˆúÿõÿƒa˜li=í¤ýmøÏÓOç%îØýÝ =ß™GÜÎþå± ¶/æ {!ú¼@+‚EÈ&V™e ‰0„%P„ßó¶à'Ðß_R®î)¶ƒyÍ5ÀiÁª‰d¯XÃÛŽ±OÞÿt.iäÄIÙmÿ”_y®|üÑË“îå÷ñ½¹Þ]_j˜4;¯ìvR?zM¶I«OýÍßüÍ>V(Ïî5»ÖôQ~¹B·Ø¶óô—ÛPî“îy(ÈŸ¶A&¥ x’G^bmÐè»-?çöõþŸñÑû¿CdÿCÿÿÕÿÕÿ]ÿ»þ×þ;ö`í¿óÄFíÿÚÿ|Æúõÿ8 õÿëÿÿøÏwþÿçÿúõ˜d ^Ø´ fN;žäã·e†ÇÖwñ:`Ž…õiw=¥ÎðtM^òoû¶–S'ž‚Eùóé+2I9ß6"¸êw½ÀÒ•çz½¿!ùÕ bý¸i{}É9eji7yB“Oé@'2‘]H¾<åÉï|ˆ͈¯LúGå•“–ǃr ôêý×K½ÿÆGççõõ×ÿ®ÿµÿjÿ­}|ÙžlÅ„ÚÿÇÿ`G×þ¯ÿgn ŽúÇ—âO¬o:Jƒê¸_Ó%ñc¯/ée·/¯tþ­òæZýÿç~û]ñÿ÷X‰A`D2’4±#M¹<æ‡nк8;Zœ_ôøíà]?®Ñ;Fë½|»ð~÷~v]r冈•Å?ùŽ li“0PÍ5Y&vPhs&߯f+¯ür¸ÆßÎ'ùáý8ìRSfòÅ&Mè•q¸&9•KH=ÊYè}ùÏ#{ê$‹²»{Jý”•¤ãpÿºSøà}?¿÷±:OæQÂK†ÐÊ–ïÔ)ÈKˆÌÚ ßÈ ß…í߉Õ%M¹Þÿ3^zÿ;ÿ;ÿ«ÿéÄêÿ®ÿ]ÿkÿÅ–b;ÅþªýWû¿öý¿úõÿëÿÿÃðŸ§üâçoZΗhg\CŒQn"ê‘=Î×ß|mu^@…€çý<¾öæÍ›ÇÂæ;—žA!@ˆrvl}ý^sÉWÕG²,ÀsÉYÔ'_H;Ðîõþ=À ù ¸Œ,@¡O#ƒ2O/Î ”á·í¹dGÂIWïÊ>±<<>9ÿ«Ðƒ`š¶i“wh­l#Gú[žm§#ÀÙ6±¾‘ÍõýÍÊ<é‹Rʶ¾ýEàÖn )þèÃG½ÎsDžÞÿc„ê_«Ïzÿ;ÿ;ÿ«ÿéêÿ³Žgíéúßõ¿öß±1ÍpìvUí¿c?ѵÿkÿ×ÿ«ÿWÿÿù5%ôbýÿóÕkýÀ¾¶nþWø¯2¼âÀŠ8èÙ•„.» û~¦ÙE´›M>ZeíprN1áósàhd!—¿2L¹ïÿû{ŽŸ—¢^~d°Ø #€ÑËÏÞMÆÒ๼ s¸r‡]EäüÞ÷¾·_XôHxƒÞcê!¤ë“–óü¹šD®4ûËÊqú%à%_¬þGz²ªS;bìyg—~Ñ×µ„ÊNâʖ̉ÕäÝ^•²i7’“6Ñ¥|äîýïýïü?à­9Ñùÿüè¨þpTÿ_Ú´ú;¢ë׿"×þ;öWí¿ÚÿñÚÿõÿêÿÕÿ¿¬ÅGô‘?ötýÿƒ‰,ñ÷Àžþàßýø- Ç!ˆ½# ç9òëÈ»Xò~¦¥¾Sórý[pa×'ÝnŸå7±47ÏõýØJ¯?øùË_.P”Íar¤lè4¯ùþøf‡QèÔd·•—–{4///| Ín§of7ÔW_}µòÚµa5¿}´k,m•-õ,ý­ïeШÏÇÈ[Àhòî! Rú½z×1B‹!ù¡e$áBiéO|Djã#lÛˆIÚ;´õi€<<„íÞÿÞÿÛ®vþwþWÿ?ï¨þ^ç»þŸÝËYŸÙ±ºþŸ÷xÖþ«ý>öjlÎ5<çOíÿ÷k×þ?>•qQÿ¯þ_ýÿúÿY;²VÿyúÉ_ýÉÛŒñ ÈØyÞ¿{?»€^|öÅ< è‘ÎlÞû„©ó;È"߀cÌ1ÞÂlm”žÊ%¹ÆGì‘ÄÝR8´BxâlBÔÁ?Í·ô¸æ(ä¤K3€’òyYÛVÞKŽðJÇÙ5v¯ ?ya³«-Ú9ÄúôÁ^ÈŸ¶“ŸÔi›Ü›7ž éʧ®óxây<«”[ÙôÅE¿¼§½I÷+iÎÑ8ÜßO§“—_ zÿŸ¿6föþwþï¹MâÌIIÿGŸVÿÝ:Êöè[cãvžáSýÖ°¬â®ÿgÍéú_û¯ößüÈ\ûí{ëGlÚÿõÿü8’Pÿ¯þ?Ü þ;¿ÞùïŠÿÿôƒ?ÿÙ[“@ƒ…LŽªoæQ>àÀÇ>àÔîº,¨1á7?@×ò!ÃM§;,R $]7Aþ!¼ä§nçx¦îoÞ}3²Çüðõ ˆ© 0ôt4‰æî.x# å†ïÍžx iœï ˜sò8ǃ£*Eºx/\Ï?€Ç¦O9TÎÏñ1|Ã+mSà0ý‡ï‚oS§U¹WÒõÅwÞç%aΧ¢S÷^’äôû¶gòs"#¹Â³÷ÿãû£KõOïççõõ×kBÖì¬â„®ÿµÿb[±ÇjÿÍÌ.Û³öÿŒ¶øÑ%µÿÏ+ ØÛõÿêÿÕÿ?ˆ£7ëÿ¿X=Iož¬ÝtÁóKè*ÖÙ¡cñ0EÉæ¼· #êž¾><ãå>ÅLšCÙRICP¡ÄÔ-(‡`M§’lD¿\Ê{9 —t`ŒZÑáí1¨¹X~xy¿”Gûä+ç ‹t…_Ú¦B ÔÈŸô¬ÎÓ²m㯧ÿöü*»2\èS&çbíÐnqÚ¥>ç÷þK{òN¾ œ ^ìþP›>gWûS/^b®¼êïýïý7;ÿ;ÿGoÐ3tKt…˜Nªþ?ëWtyõÿÖëqbýs_¿fñ{¬Ö¨®ÿ§?ºþ?ÛEµÿŽ]kÕþc¶Öþ7²Ó©µÿëÿ­¿Zÿ¯þÿè†ßIÿÿ§ó!E8šqŽó IvãøµÙËØu ÊsÑ dq.±Ê‚}ºhä[€B Û”Ýüá½uîóxWÔІ&ò¤~¼"OÞe…Öô2©^ÿåW_~öáý‡qÀOÚº¼¤ÿmã9_y®ŽU×@Mû´×Úw…O¯÷~N¾ûu^Ò~îÚ£u½ÿ`íý?ý`LÿÿÕÿÕÿ~ÀÙµâZG»þwý_»aì¶ ›Æøˆ%Rû¯ö_íÿÚÿtÿ¥þ_ý?yYâï¯_{»®ÿo¶üסþÿoÆž~8/qøwl ¢ 0_éóBwNl^ª¦3ågð‰0‰3h8=Ê Q‡ºÂû+„YzòÖh~:@€Å3€Œ|ÀÞ ¥-;çbyh¹F—Cþ=ä×fm?é£lçEéε™\ÚâZï¸b¹~“î1½U MÚ–›z…TÀ‘ôG¾€˜ = “[tg÷Ôˆ{ñoùG|”•p ‘-IºKnu¹èrÞû¯/zÿ3vŒ¿ÎÿÎÿêÿêÿ®ÿ]ÿkÿÕþc²ÙbA\û¿öÆAý¿ópý¿úÿù‘¯þÿ,ÿøÏÓþì§ouòÝi]Pc냖žGÍ81y/à8妘Л¬‚4ޝ4à‘k‹ÞÆ&ß¹† ãÀDMÚ)+=Ox!L†´s DiçZýש#4gלfÝyA»¼Á)Îõœ¯¢™¼mLJó¨£smûâ‹/¶>@’2‚öäøÎ<ê¨ÎÈšv§ è£Ošú·ÎíÝ#‡r9ðrŽ>eõ•÷ŠÉ»ï:Ã?AëÔûn®¡!¹zÿƒª¿¾íýŒ›‡ÿÿóÃAõõ×ÿ]VkÿY;»þïºYûom5}ÁîÍeÄĆKZí¿cŸú[û¿öý¿gßþ¨ÿ÷¼écuæ(Šø´õÿëÿ Ávž~2/q7H$ú—s™=ÀšÉê¯>Ú|•G—æÜßY8•@IDAT`ó¢tiê094ƒµÇ„SÿÔ3uå:YÞç³Ëu¾È@Ìy÷þÝ‚:©8¤eœï‹ÒµoŽÔ©üì:B£ìxȧÊoý“g¡˜‰óKdd%°2OL6áì°ƒf®·îKyä €äZÝ:GBÚ$wù§½r¨Oéçò©/ý¾øÝÏÓ¾Mëýïý¿^çç¿¡Pý~D¨þŸõtÆC×ÿ®ÿµÿ^¯@?²Ÿjÿ›òaÛ[7jÿ×þ¯ÿ·>[ý¿úÿñÇa Bý˜ÅA-&ñ÷Þ~8ïÀÒ¹:4 P€›üR Å0£U.à a„#Ô¯?ûîw¿»àLøÛ±„‡_ôçø+/(®—÷4`öÍ×ßìõ¥<>7ÿ®rŒª—¯æKˆƒæ+Gš|©O?¡÷ÿŒƒÞÿkœvþ¯éü?À[ô^tQýÿ¼nTÿwý7',¶]ÿkÿÕþ;þ[µöÿ±±kÿ×ÿããÖÿ;>,›’=)dnÌÉúÆÇ?­ÿ¯oôEýÿóDš¾xúÃy‰»ŽYàäÖŒ’õPŽ%žü„3¨´ÐA[2SFÞ)3@½?Ê》þ.4sèS>e~§Ž#ƒt:»ˆBÔ2ìè I¾òá·SãÌM³CèG ò>,ÀMêœ )º¼È Áó×@ºv”ˆ+ÐkätNŽ€JJâ:q¤<á´qv^ù2â\‡FÞÖw݇È*]™ÄèåùJ£îëË#ûÐ Ïí»‘4–ròí$[ž{óÏ¥ÕçËU¯zνù¸Þå5o]2Ò{ÿ¨¨ïôOïÿÌÍݧ?2Î2v:ÿ;ÿŽ©þ¯þ?àà®MÖ¢9¢/ºþ?¯ûÖýÒõÿŒú#ëÉš~ûç¬7µÿjÿÕþ¯ýÿøpõÿêÿÕÿÿ­óÿŸ~ô—ü–Ñ#d±wœ `AÑe´ Z JŒ¤1>ÚAÄ'•/ eDĨòŽ*yêñµ7`–šc˜n¡ëz·9ä{ŽS‹×È‚êP>¼Äx@¸…ó˜ßÙ½µòÉŸ°Õ íÙë ÄqÞx-¿IK,?é‰ßœ¦m€¯ÐJ"-çÚ…O?§>ééið‘÷þÃá`L£^ï¼ô­öÝeÅcïç‚îå˜B³Äó'õo:õ²Íµºµ¥÷ÿŒ }Ñû?£¥ó¿óÿÒ9«—ªÿW/DçWÿwýÏX0?ºþ;J_$˜#c\[£ö_í¿µ­jÿ×þ¯ÿGOÖÿãuÎz1ÿï>óúª×º‘5¤þÿ¿lÿßum„X£Áp,Ð1ç ŒLƒÂ€Ao"9ö—¬ËÈÈ/“½à^Ç:WE®qP*u¥î/òr Ï¯¯{>² }„K.9ÉçYir9÷¸¡ÇæVnõÎá<ü—æfî21­~}ñÓj4Ô¡€@’kï÷Q§kéÒìÌÚü©KÞ—¥\úaÛ‹¯¶Š/¹ÐªÏnµ7¯ßl3µß¯Îò^½>/ÒÇÇû¸î}±çC#oùLiiÛ.ç{=ήûg–¦÷ÿã1Ùû?ä“ƳñbL9:ÿ;ÿýŠI·TÿWÿïXØ¥ä¬cÖG×ÿ±.Ùõ¿ö_í¿Úÿô¢q°kçµ~Öþ¿l‰k ‰o&¢C÷|lÑõs6gþ\viý?æúvFý¿úÿÿ¢ýÿ§Ì#„Q 3êwÇeÁ9]åz);y@væ¢P  C¼î*ß½<×tv¡÷rsñ·£x¤ã¯Î™jX¹OÒsšô9Öi¾hùúB`ðæ`¯“}•ŸÔñ@4×Þi£ö´_¹­cò¶Mm;/Ãsó/íF ¤ò-mA‹—vºÎ‹í<ûvúŒá*0æÜÒoWÀKÊ'8WçÓVÚ¿¶(ŸþÓÇÂûɇ6K5;ÛÐêçmûð _r¥ß÷žÎµ¼ÍŸXÚÖ3² ÓgBïÿµ›°÷¿óçjçÿ**LŒî¨þ¯þ·zíZf-éúl„®ÿkSÔþ«ý»4ö«u£öÿ¥3kÿ?ÆÛÂX‰o"^ßlìï%ºÖ™ýõJ@Ï_r¤|ý¿ò­7RÿïøºÌÖúÿÏORý¶úÿûw_XÃsÏιëý•pu) OÀ”»Â@»JŸU2gË‚>Wž|×@‘/çѹyîØ„z”:!ò ¾j8Ùhå“ë‘7ts± ‹QÒCƒŸkAYºnóÑ ‡”ÃCÉ%N=è’‡×çOSvd@G.ùËò” =£íÃûŸ†oÚ©ñÚÝa êrú`„Ozñæ}îyÓ©ç ¾¨˜:];w§Öçþ”–¼œ»&×WûS·ú‘­6áÞûßûolf|dldþtþwþWÿWÿwýŸÝá£'…¬£Î»þü؃>â¨Öþ;6jl°ÚÏþ¾`3×þ¯ýO_°=ù.«O/»þͨ‘ÍGSÿo}>}%lÿìÙ9w]ÿïà úȸY|ú¨þÿÿ?üÿ}„Сøãhf hܰ}ñ÷äÏrñÑ ¿ÆúFxl˜A>IÛ?év|v¡™—‰¯‚ ý¾—S¯r†®Gó„ÐPQR;‡Úä‹¡4Þñ¤žK3|Èa'Ó–UÇÅO½ J ÷SdÀ*¿´“¾2 _×ÎÑ‹—÷Ô« O¬Í 4bá›o¾ÁdŸe&¤žÃK¾zðIPνYLÞd໼¦.ôÚšvG&4ÒÐEn<ñÞë‰ïŸQUGxˆ…ÞÿÞÿG^ü?ÿ:ÿŸ+ú(s­óÿè•U7]=&¶õ¿ú¿úß\éúßõŸMÉv£ãØ£y)1:JM¾XÎEv´i“ÎÛ¶ÍùæMŒ¯]§nçé'iœˆ_  µý?ù~µHßÉ[Å1e†á¶Â¯]Úýêõ€Œ^éu)By_EôuļuóF–ý†6ô½ÿ½ÿÆFçÿè¾™Wæ…ÃyçÿÀõƒ@¯UÿWÿ Æ„yÒõ¿ëí¿ÚÖ†ÚÿµÿÙ’YâÃH3>êÿ_Vÿ¤ŸêÿÕÿ¯ÿÿ߯žþÕ¿ýÑ[@•B1q„uFâ¨Íõ¦ÏÄŒ€3&ðå£0e®«†f¥]¼†j1–“G0»ˆÖ š|åÔt‘æøvv íŽ$]2yQÚ½~e ¸ðfÎIÛzÄŽ©€³àÒÈzàŸÉø$'m’…G®ày1»öÝï~wy:—öúÍ›­leÙµ? p)•>~Ù»økƒzðw A|É­ïɰÛ/y²ûÌ}R½¼À4|Ô¹}¥Ðyú¹÷ÿŒÓÞÿÎÿhŸüéü¯þ¾74¢GéÔêÿ®ÿÆC×ÿKiŽí‘¹bnÔþ«ý·¶ç*Næ{íÿÚÿçÇ{c¡þßÑ›õÿÆ#¯ÿ¿ƒa}ó±)ÄõÿÿûøÏÓñ³·ïß½_`ÄBÈÒi”‹”6'{¾Š÷BGòâÜíƒg(/ˆ÷ù÷á±Ò¥×¯_¯]*#àì‹/¾˜Öž°ü‡OêZðœ]fä%ûööMB9Ã?AÝÊ«7»åäKB᥯ñ†{/•Åwã«OÈ&Pš€´ÞÿÞÿŒ£ÎÿÎÿêÿ£_éÈêÿ®ÿ–Ï®ÿÇÖbk°UjÿÕþ‹=º¶¬q1úrϯ˜þt]ûÿühÍé¨ý_ÿÏØy2s£þ_ýÿúÿüçéþÝßZh,F †_»{0« ¤ÉKÂ$š ˆ^8±yDí/”}'ÕÄÎñ΂42Sç¼ÁOI' Bk1PZ¼çdóýâ€Ú¶ £ÜCYÌùOxí‹Í§œ2êÝÃù<hw–`Ç׆©çÔt#üÈüáÛ#w”“ôå?Ô (Má탌È#ìã{snG”Ùœ£QÞž€'4®SoÚ¶÷lÊìû­†‘²ÔO{ï&3~Ûg#Kï¿÷†õþwþwþWÿWÿ[ºþwý7jÿÕþc+Öþ¯ýÏ÷¨ÿWÿϺPÿ¿þÿ¯#±:.b3¸Å?þóô£¿ü£·i,¹Íã¸,03€GhØYPe,h±ÙÕ#m!™‘œRóå¿M˜ë-;ùC´ ‰]QÒî@ Þ x ø$DIºm) Ðõ~v"‘GÈî¤4+ßð O›Wû2seæ@§Œú¶¬GGVî©g¨‹ùÓ¿0<ö—¦áóí€YúT}t[V™‘N…Îïmû´íz"uâ#/aãI _ §þq¤]ø£Q,{=à~òî š<šÙû[íýïüïü¯þ¯þïúßõ¿ö{,6]í¿yEíÿµûkÿS2‹¹Qÿ¯þ_ýÿúÿôÁ?5þóôƒ?ûéÛ'1ÒG = Ä(@Wó¸H¹—/ŽsTqm”w1g,ðË{Òñtî<`QøÅHL ɹôì<ÂÏq/‹§k )zÌ?¼ÞÆàØ€†Œ_ø›p Òók’ú„Ýu«à³_iœÇ,ÕðÉ£‰ÒµÓMмù²bd&Ý»Lbr{WU¦ž®ºÉ’w^9WwQT.´“±@ÔÓƒWK·rôÉ‚qC§ïiï§]‘邏e;}%ýê´ôyïïçÿy4¹ó¿ú¿ú¿ëÖÑ]kg]çÌvý¯ýÇÞb§ÕþcGÖþ7îGíÿã»Å§Ó¡õÿŽŸVÿ¯þ^!TÿÿØÑúƒþœXüH‘Ckxfò,°1kÐòõ×_öýïÓþ ÁÔa‘¨PÒÞ"OÙT£Îµƒ.„‚~㘶î+Ó»¤Ô-˜ò¢8–ÿ4BŒ'%¸r‘gÙÓ±2Ë_»6” x3™+‡-në¸Êá§žï x…kìø x=ê™k•Y¹†?ç¿üò—Û÷voå%ìÒ=’(8ÇÇ¡/ÅÊ ZçZÔ%=eÄä _è¤ Òs¯{ÿ{ÿ;ÿ;ÿéˆè„èKJ­ú¿úßÒõÿr»þ¯ý¼eO°;Öö`‹Ì5;§ö_í?c£öÿ±·kÿ¼¡þ_ý?ëD‚YB_l\ÿ¿þÿŒ…„ÿþóôÓ¿ú“·¾ŒÇ@=F`d@" Æ áÔh/ç±31ÅÀpyé³²hņ¡¼w³kÉ Îm)ÝÁy 0o†Ÿ_,•Ã#]PFºº?äýO³óËçVX@‹Ä{¾H?e¯ÚÜIýø² ºê•¾õNyQ¿DåÈhQÆ_Mžû\~®¦á¹ë0"Ý®/»³ðÜ~šwaá«ÿÞ}s¾,x[ÞC4‹Ìè—Ǥ ó«>iä¿·Mšà}VÚ3Ì–ßÒy×ô›_…ÞÿóN±Þÿ'3„ëÎÿ£3:ÿ«ÿ«ÿ»þïB9ºþ×þ«ýWû¿öý¿úõÿëÿŸþÁטx±—Áþ9🧟þõŸ¾ @èÈ£g ¶}®°ð˜_äEØ/¿ür›ìl’Çù]0eb_À±/bà Ç@þ–ügA#Lñê „cv‹é€WÊ“7;ȶõ\`:ú¾œ?À )#(¯î¼Ó@Ù€Gé{†^9“§î' k:dy-ó‘åÔ-lû'v­ŸñÔ¯Ú·isg‰,)“:||r~—ïN#oa }ÚöFœ]ÿ¯/P½¡/„Úóckí¿ìOz¤öíÿúõÿêÿ?ƒ}ôâ8ßÿQÿÿ¼ƒ˜¶|úáŸÿì-'u³ã‚S²†ÆØÀé€(ƒJgÚ%öu¶!\cd‘9ÈL÷®‘¢¬#‹RŒïFXÀ.¢Û³®@»¥‚Ö«À éà9õH÷âòIdPV£ÔE>õ s~‘ƒodv-^žSþ´h›udÂoêKH{ýœ¼|ÉÇÛ_Wauíõä¡ý|ú%Gj3`ËШ׵vHßlå«Ç!oë—1A;êòþŠíïikïÿÜ—é¯ÞÿÎÿÎÿ̘ ÕÿÕÿ]ÿÏÚ鯵tw˜Ì:šõ}¯Ÿ“»þþ¨ýWûËjÿ×þ_Ÿ§þß·úG/Ôÿ¯ÿÿ÷Â~öþõ¼ëy70Ë£cƒt,b'FCMXÇæH^@i¥,ˆ$ÍÄ X³ ÉÐÇÐÎ% ËR”Ø}èöüœ ?ô¾2ˆ>áŸúðXCsäd9—'>åÎ+çøIßz&ήé[‘Íœf!–º†ýð¤/ïKÂ¥MÛ‡æé¤‘cé¯2A ¼²^ ¬£ÏudAïúÏyÚòHÛÜgºÈ‰Nß o ™¼\«÷¿÷?c­óÿì*íü?ú«úÿ(Ö]#æ4zUjõÿÙílm2_ºþ›3óÏZ=G×ÿã¬ëvOí¿ÚOóãiíÿí‚]Kjÿ×ÿ«ÿ7ËåØSù¸×5{ËQÿ¿þ?‚yÇž~ô‹Ÿ¿±²Æy9úù¢b‡]R^(ð°HŒyç–¬ÏÉž¯ñ6e\Œœb´Ž1båðöòp#׎#u›È\gah"zõå—œ7¯ßì[ú•——|åâˆ{Iy¾¬¦ŽKC'ˆÉ±²Ù•4çkd,¾k˜OŒÖB“2ê:†ûÇp Ï*ïÖuš²×+ÞÃOžþûú«¯6Ï{¾¶Ì€†»+nÚ°ÿ†OÂÖ}] Í‘üÿ‘y2÷Q°m³ë9”OŸés÷UÞûßûï1⌇+ÿ;_:ÿ«ÿ«ÿ»þÓ‰ël×ÿÚµÿjÿ3ï­ ±½×€ªý_ÿÿ5>ÀV¸ûjõÿêÿ×ÿÿ‡ã?O?™¯îìš?€ €Çd `%ÙÉG#5vîFä8Ä4†Þ‡oÏKÉå‡ÿù/ÿe ‡ö<Îà+„Ësh¼ß(/u_e82Ѝ¸Ún7ÔÖ{;ÎÕgúƒ#&ý<>r€±Ix¼­ü”]ZõOZÂ&_WÄß9 êý8|Þ…µÿ¦Ü¶iø ú/üßxÿ¹pß—»-ÕÜŸ‰óR~¼õÑhwÚ3p…ïÿììýßÑ“y»ã¢ó¿ótPõÿùq úÿì^¶¦8ëŠó®ÿg­Îú;'kövÖüéú_û/c¤ößwÖ.×µÿkÿß`Ïú²þOý¿]>²–˜/õÿ¨ÿ¿ãâwÕÿúÁ¼ÄÝdˆQµ Ð€(1PM˜ÀOvIS.Áâ£Lœ^Ïv£ô á’1wS­/ßy&zï ï<.å×J€:ewº­ï’—ÜÊ¡ßö]mÜER]O‚‘Ñ£’dÿõõõµ•o¤HáåEsÊ~Z™µod\;Vé?2 ÊäH_'}•ö”I¾òy‘»4×û‚ñ t"‹ ½›§þ„¡ÝpÕw_–ÿÜ{ýxIOšk¾ŽÞÿÞÿ ­o fˆ=»ÎÿÎú‚1ªÿ¯Gͪÿ»þºÌÚ~_kiQ×]ÿkÿ±õ#ôhí¿ÚÿÑÆCíÿúÙtPÿ¯þ?ÝPÿ6(ýôz„0`Àlj#²“eŒ¬U¢ÇA¦#Ñ:8.9GïÜcpÜ\×ÀÊ Òb¼ùõöì–²X¼òà=åÔÅ®_ÏN.¼×Îí(R?ÉN¬¼H}ë9ò”|Ƃެ<¶§,ÙòN |IMö¨3ç[ÇÕžàú“6’ÝáZ¬~ç‘9ÞêÊKÕ£4©KÙ‘…^HÞ^ ÁéÕ½º’NŠú>=BE~!u¥o¥¯\#ó~ÈÝûßûo¼d<97VŒEã%çÆ“óÎÿÎZÈx¨þ¯þïúßõßÚ!Ð µÿjÿÍ@ØÝ›;(®?µÿkÿ×ÿ«ÿWÿÿl ²dÖÿÿ øÏ¯—¸3*8œB  Ï¾}Ò€/¼¡S¢L€ ”G,8³ÐÁGù¡g¬ly·aïÆeÄ\àŽVûÜ»rWy` >¦<¾ÊÆYž‹ÏÞÀ¥ì>ŽŒ~/_/îc†N êO»\?·±"¿|€Öþ#ã„cd@O>yÔŸ0nÙ¡¹êYC—¾T>u?ò8ú7þÚ-h¯ð(;¼Œ¼÷ïÞï®uË÷°ô½2+íðL,M¨p®žï-™„ÄdK½Îÿ?öîmi“Ý8ô"ÿÞ­µ$]΄-‘7’7s²EJöxÎ|0}àƒ¹Á‰˜ËpÈÁµéîEN>/êýþê=²,É’‰îúQ$ È|?T•ð¸Î÷þgüìýŸ±q3c§cÐùÎÿ3¿îsI¿8:÷“·ó?cˆŽéŽÖÕÿ«ÿwýßõßkÿ]?*®ý·öÿÚÿÌŽÊúóTÓúëÿ¯ÿ6KðC/q¿;]G_Œã5Õ=€žñ[)9F™&‡žó!–çh’‰6qw0•¿XÅDZ;Àp„ó«¬rÞ PP© Ø{°|1çSçè£ÞþbÃz7`O_ìîk~”™€TßM¹Ãs^?eZOw`‘Ó(²ëH>Ù"ÿ0R'ï`—LŸ”Ÿ>†Påë‹so´©|”z}±{ÔqÏožø.WÏ¥G޽ÿ{ÿg¬&ìüßù¿úÿ¡OWÿïú¿ëÿÚkÿ­ý_;^Ìn®½¾öÿúõ­\{Pܼc`Ÿ¿ñ»f %oý¿ã‡Nè—õÿ×ÿÿÿyúéÿþ¯Þš:ˆ@éö<Ûy œk²er¡¹v™”Ò:]àšÐeÀ]ÝMzw=h‡gÁ"|/ÇÞ± ÐÈ/xÙ¦’~ð圑;ïÌšë:TC¯lÛåX†§][¢ò/¸çÀ«€sžyV%íˆ,Ó^râáïpÞ¶Éã%ô9¿åµn1°lÄ ¸:}t£Å·oG@­I¬,ò#ÛE(½y•§e‘|Z^¥ßû?ý½÷ç?³ó?zÁ*±úÿèÞêÉÕÿVýYw¬UwÍñã‘ké»þ_?LÜ×ô]ÿO¬ý·ö»´¶·±×þ_ûߘ¨Žtž5wý¿øxúãSÿm–—õÿÖÿç¶&Ôsa¼4îù§ãç·Íÿúá¼Ä]#-]04RDY¸¸‚Åe“^ZiÎ5Ü#ÊI£tÊ·Æ+6å©Ñ( l²ÛKpíÀCç¢{?”X=ÊJOgO~sÊû¬æÚøõ×_d,⫝̸Ãέ>¢Ø›ÉIÅK~ÓÈFN`[Ë·mäMŸÄjŸ mrL=y⪯mÖáë\x$}êìh“ömÚ5|”" ¾Ó^òW&yøUnm˜†äzZüÈË;'.ZeÒ‡C‡ãQ~òÂÑÒÖ¡•^ZiÎñÙû¿÷çÿÎ:¡:’nXý?c‚n_ýÿXS²öMŸ»þŸv×ÿµÿjkUW¬ý·ö?¹öÿútÃúëÿÃÖÿ?øÏÓÿúÏßš.,˜‚mŽ#Æeࢠ’_U=†§3íb…~ÞIEá¢u”ï=–Hq|7ïÌzýêüÚ2Ä¡çyÿR~HæÝV}d0ü8ÕìCüÑù<&øêå«ìÊ"c–;O¦Ì /ÀRd›>ˆvcêÔvn‘Ež/(’á,.@ƒDµø¤Ã˹@çÊ—®`–|ôå).­À—xÎÉã\Ÿ÷\ùò-]Û<¤^rÏJ«ÿ•*2ÂÞÿ`÷þïüŸ™³ó?*!:gõÿêëË®ÿÏkõ,žYÛwý{qí¿(Ksdí¿g{¸öeíÚµÿÇᘰöÿúõÁÖÿ[ÿŸ~„)TOñç×ÿÏ»ÍùbÅ9€Oÿì/~ô–£Þ ãÚyÀŒ‚G.€ÅDæˆíd‹Ò‹é|•R»sºnwðgè”KþÔ—tÀ’úÞoUZù­›œ®#ÔÁƒƒUPÇ9Ú7ôÒêT^Yrâ£\ꌩò;‹e å'Éác—~< ÇIOkËÚa‡W¾Ž8´mûk‡—6º í3ùéÇ¡m?´½ø´Ðë_€+}—ë‘dò’?<|ðp ÷.­´?5‡ä‘¯züŽìO´Ï*ÿÞÿþíý?€ôÎÿ™g*5Î||Ì¡ÿ«ÿg÷íèßêÏÕÿ»þ³=výlæ…¾ˆÎ\ûoí¿±?Ùžkÿ?¿ºÄüXûÿøžõ‡Öÿ[ÿ=ÎîúÿÓt¬â÷ÁÿúÑ_ýì­K,ø^9tÌBAØ‘£cÐt€B®âéÎ¥0r}ÂCðóî*Š:HÆ(×úhM~ëk®•ýꫯ>ûüóϳ j ¥œ-uòÉZú‚+¯f§ÞòÉú q“çºUÁ¯ïŒá7uM±”U®}Pù‚iÇiÌÐyñ9´_Lv©<Ón<¼³K=ä 5qóÄä½×ÒUä,f“Zm x7éd½õµÃ[Ÿ·}{ÿÓU{ÿϘ2Nzt¾tì;;ÿþÚù¿úŸ¾_ý¿ë¿5x×ÿµÿÖþ[û¿v÷Úÿëÿ±—×ÿ[ÿýÿ³yæÿyúÑ/~öv,¯8¬çµÁ5ÇÞ¯ ÎëоË/f“:»® mÀ” \©àòðKÝ“ =“ýîªQÃvÒF½Ò àô±CiÊÊXñ5Ató_þæ³7¯ßœòCsœÉŽ­{(Ð¥Oõx¼NŸ¤~ç׎,Hú$¦®=^.ïQ<´ÒÂoda”“¯ —ºå©—¬êŒ?éú ÐÇÉÒ~UÆáÑ÷AÐ?´ø8GçZ¾ëÆòÕ'Èw.ÿevÏvciÛeÊ¿½ÿ{ÿwþŸ™;ÿϣܫÿÏn_zrõÿ®ÿ»þŸæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—°VÖ79ëæúõ¹Öÿ;>î8žëÿÞ0Oøçp•õÿ®ñ_ò+ŽÙtœÎò«çœ<פ”#úÊS޲ŒäÅâß›aý@‚¾¢/Oqepn‚;ÔÝJvQ©‹¥Çßd‡“—¶+kçˆs­|”Ä”Ô.MÀǹC]òÉh@#ƒéBÏíp}xÎû±¦=‘s¾‚(v-àõË_þ2tè…I“žx®Ñë³o§-dqmw™öàGd¢a ®›¬’ÐŒ ˜[rú¬tÒ“µË=CWÀêäNy2Ohß«CÙ”fiÛÔIæGºÂWÞÞÿ½ÿƨñ±óç¿\÷½8 ôÇêÿÕÿ–‘®)Ùá:ãĘéÚ³ëÿ®ÿÆÇÚkÿ±3¬/kÿ >zsíÿõÿÖÿ‹-±þÿU—ÏÎâßÓ¿‹þÿÓ~ñÓ·€4PcÓb)Ðpi±ªx\ÏàˆQ9€JCËrLäåýQâ!°ØH»;4ÀïÔqÜË:ïuy×ÙÀ™²x%¾@r%ŒÐè»#+@Îdôå òôxln‚OA2âÇpö^*A;h• _åɇ¾r†ç•ž‚óG^~÷Òv×díä¿~= Û»óN,}Ó _Çw÷—tƒOûÀv«Ð¿á5ôéoñjeòN+=²3Bž]h³ë ß¾˜-~Ù…6W柮¾üÙû¿÷çÿÎÿ£AWÿŸ¹@ç®þßõ×ÿóHp 6Ãe;˜kÿ­ý·öÿÚÿÑ£Öÿ[ÿÏXXÿýÿÚ ÿ˜øÏÓþÓ·e,fŒäÝOsÎ Äpæ @Gßç gÐi€(bÆ×_>@§9  Eè~-è]ÜÉ›Gõ„Ô?ihðì–\¿ì¿Îco¿:²Ìµ:ÈⱿW¯^Ði@™¼fdÇ Ÿ‰‘u‡LýÃ_ÝÄC62Mš@FyÒÒ'kwéÐ4]ü¸VÚ‘QŸ$9¹¿dýl›wTM†Ç…ò&»#|ë€p&mŒÌ“ÒÈ¢“ÖDýå7á…_Ó*oæOÊ oïÿÞÿÿ;ÿWÿ¯þßõ×ÿµÿÆ&ZûïüлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øË?ÿ™¯þÙ[J¨¡Äè€ (2é©xÎV¸83 ðÊŽ¦^‡ÙÐã@ ÊìL ’!˜ëçÝXÒäªCÙ‚=y§Õ¾¬Ô?óbs`N%pÍc)7åËÈÕÎóÎ <G§.2ër6žäúÄõ‹—óÒ÷ùW:<µåðìÎ2»½„^£«ñ°» éä—<Œ,ÓGò<"‰÷G홯ºÖvݯ†^uÊâG–äá=2ºNÝ“_YÑ’°×{ÿ÷þ3ÆOŒ­kŽ8ŸÁ²óçt å±úõ¿uÄÚµëÿ®ÿkÿ=Û{kÿŸŒ}Év`gÆ6]û?úríÿõÿÌ sbý¿õÿ×ÿÆ„þ[ñŸXuV}áÄ"S £àOÀžI—'tà¥,'æÕ€WßÍ‹ÆýJˈgbx"([É5ÊÿØí(å8ÎÒ”U&N³\WV×¥!GòFØ¥¥ñʈÊ/Ç órF>¡;”ð`ˆ‹ó^­ ¤#óT”6â#¨·úÐLzé€S—üúÔ¿ÊÞ—¢« _À¾¹¾xxa»XúÝ/žèªèði{Ó7®§m;$—4ùyîõ’µ á\>v𩽠α÷ïÿ5¾Œ‹ÿŸÉ±óÆÝ#¬þ_ýŸq`¹æÆ®ÿ»þ¯ýw@šµÿÖþ§O²ö¿µB_¬ÿ7þÙõQ´õÿÖÿçW¬ÿ0ˆócÏÁ!þ>øO, FgÈÈõü2Q:@»Ÿú(_^0(º”t/Mýæu¥Uà@KÀ•9ñtÁÃMŽ9/Oe¹K®qÏ“pýÔQ<&UÙîâJ°˜Ò÷gÉ'ŸrÀª×äSÖ{§ÈäÝXè ¡ÿ¡“ïœ\m—4בIúìÃ[~óúË CÇûº€nú¦ík5`°_ꟴòÐ;øøR¦ý•ºæm~Ž^Ob®'íJsKÛû¿÷ß8Þù¿óõÿù‘„¾\ý?;®®õJ_ìú¿ëæÅÚûlí¿µÿÙØkÿ_;kÒëÿÕã›­ÿwv¯ë‹—ʦÈ1‹Šþþ–¿šÔIŸ²Ñµ|Û)'Ä>ã—_4NÖÿÿÝôÿŸ~ü×þà én¤ÁÀút–ÁÄ¡Y˜Ìu'¥XQßÐ ¬©«±¼ûíxwÀþ¦|åBþŽ õå‹—©Ïµ<¿ :y9 9¼‹ `ux‘¹<µ·» jœ“ ™§msØ¤Ž»ìåÙtJk*Jÿ„_úã<‰&¿ÞMŒ—|×b<m×Ú´ÅÄ4!ýWFH~Òð˜ü¹ö¸&¢š‘ŒW®÷þïý7–wþG›Dßíü?:–~Yýôëêÿ3?¬»þïúo¬ýw쯵ÿÖþ_ûÿø/ÖÉõÿÆ‹ÏvÖÌõÿÎf¾&Ÿ¸>§>ç⺖ÖôÆò•¯_Þºõÿ¯ ,Ó?6žü¾øÿ°Î34f Ícd_+à1C%»¥ò(Ûäwðy”çv]ÛE$,¹˜¡/Ó¯Þu^€J„)<:HÅÚ+³y.•ËÙ¸#=ΰÇc{×àw3PàCóùŸöÕW_=~5Fg2Õ9ÁÃщ&]yõ„ùÚ^¸{Ô1åG Ç5Y*ã«ùâàd¥~<•yzq{4®){@UÁ1Îúä«[—úbb®/yÔ%}¥[ÉžëÉWŸ »+kâ+M^è\aïÿÞÿÿ;ÿWÿCkõÿ®ÿ»þŸ÷0Ø습ÿÖþ[ûÿø±³/[ž}Ýyb®¬ý?¯CŸÅ:Ê×Hÿ¬ÿwü®k̬ÿ—)sÆÆœ#±r²y÷¹u°‰õÿŸýÿ§ö?zû:(ßèß³\úÓ<ê<)b÷-y„€Rò œ§=ˆÎà+`dr6?ÊkF ÞèhO¹¡-Áz?wÝԇϜv—€gJÉþ“žÇ/ù>¶ô~ùå—±È Ô¡iÐnr7œ~8@Ö»áOfeðK[‡^}Ãì!Sû”,í—¿‘Aþ½^Vx ‘t’`CGFõ¬ íPåÚOéÏ«"éx¥ìudé;»mÈWe ½ÿé½ÿ;ÿ¯i”ñP cçÿêútõÿ®ÿ»þ¯ýGÔ[ûoíÿ1Æcצ^ûý¿õÿ>PuýÿõÿaŽàÁÆÛŒÂé8áÝÏ뉋ÿ<ýðç?}‹‰#…8P¹.À3U¥Dél—€PÒŸþyö%‰&½×*KÚ|áq¾çbáüÍiþ´ò#ß4Pð7y×5°‡¼dµÉN"2–¯2äÍÄ_|ñEäzä»\Ÿ³;i®½«mÔymç²¥ì%gùVææFÈ ïäé' ’ó¦«GPF>ZiC’]oN‰z¡2ˆõ]e ÍOýò‡®i!6´éþíýw—÷þg\MoÌÿŽ“ÿG‡u™[é'ºãvn~eNe¾ž¼ÿ«ÿ«çÕÿg^˜7Âù›ÓüùtŽõz×ÿ]ÿ3f kÿ­ýG¯²ÜbÅ®ýÿ·ô'ݺöÿyjhý¿ ü©]OŸ®ÿGƒø·þßoƒÿ÷ôÿúÙ[×-³;©†¤Aa K[…=èZºÝU o ŠÇñ”—皃&Ê%,X#O9Љ]¼‰12ô­˜†/´OÎÑE¾ð·Í./r4ÝÎ,@9¦ªÄò²rMjÛÈë=ZÙiÏeX3“äûEefùé“áÿ4íÒ‡-º¦‘±ýS9Mü´_èŽ1çäWÞQùñ¨†FºæQÃòB_YÛf´À†Ép9ÈÒã$^²ïýßû¿óçÿM‡­þ_ýo-Ùõÿ¬×ÖØ]ÿ×þ[ûoíÿèĵÿ×ÿ[ÿïáßòK×ÿ?8Aým¾ûúÿg³Î?þóô§õgo˜\»®ÚÙÒœ ŒXÛ ;‘'♼urÐ{¬ÐgBç–}öúõëSnhðù”_À–aŸº§¬¸u€q1å Ð<òæDþd†dÊUi~ah _)f-”²Ãã—¿üe@,uµ (‘·m«Ïäì{š°©õM L“WyÈïk†œF¨€I£ÂsúsNòRùN|eõ³ÐzÚ"×õc¨žk<…–¿²Ó'÷røè˳»®\“áNnïÿÞÿÿç½æˆcçÿêÿÇz3ãaõÿ®ÿ]?³ϘØõí¿µÿ>±[Çž<ócíÿµÿïÇߨO¿ÄÅèOMý鮇dý¿ôþËœšNYÿÏÈ8›AÖÿ?˜ÈÝŸg£™gs.ï·ÕÿúÁ_þäm€ž˜Q EÃú®+uíRÎí¬jG°Ì4˜DòïG;Í‚žüK5¡qM±¯ÚñeGXêÀGá+NÚapÈKå÷+jäÔãÆ|;»­^¿zý˜Ø¯^]bøøEU pS¿s»³2ðçvKyŒö¸ù} :¾Ýq%¿uTôß}8»©ˆ¢m@µjxÙi†?ðI»Ðà#-åçÜ®/`YÓ§ÓFeÕc± ò|zN.!åÚ˜i'€Myuâݽóô³s W.ˆÛoΞ ÿ½ÿì=Øû¿ó¿sfçÿ1$ôƒùAÑ&ôˆóÕÿ«ÿ Áø0o²ÍyÓº¶füLú®ÿ»þ³P:.ÄôÉÚÇ\ûoíºsíÿõÿø¼ñÙÖÿ[ÿýÿ‡iN<ýð?{KQ2 ¨¸~óæMÀDlOç½æøŒ!*ß!̈Ù:/.‚þ¦Û6)œ!F/#øaÐ\ïãaðN&ËøÐÎyë«\e‹N})3ä$@„ôÖ‘aÚª¬vx‡ð¦¼ðV^[È¢îõ©K:>¹Ižw…´|â @»I¤ýjv˜ðšºúž0×1þ‡2/ ÇuòË3ý?àÕá} >L•q4äúºH_üÙ©ëê×½ÿJÎ}i_ïýßù¿óÿ̉êÆèŸÕÿ«ÿ­ëÖ°kmr.ìúvC?Öì]ÿ×þ»æÆ[™#æÊÚìùtGþÔ6_ûí6ýÙ÷1Ç1w.?…ÏÒõ¦vÉc$É›#eÖÿK·¤/æ,>¡~¼…õÿÖÿïøømõÿŸ~òïþÅ[Â[<<!pT(‡t¼+ ×Ë…nvðgø=ÀÆñìnR_€¡«®N½{º2y|‘0tþ}oñu'£Z ª}óÍ71´Ûq ñ(ÏM™Ôï<†è‰ßUÍ—§Ÿ\Ë+ð¼ÚÐ6S²Î=Žvê|îO¼Ê#'?røuòåìni·géÏOÊHkûð(Ï;¿žãÛû¸÷Ïé˜Þ»½ÿ;ÿwþ¯þ§+WÿÊZo}³¦tÝØõ×vÞÚ϶[mˆµÿÖþ¯¾dóÇ6g¯³Ñ×þÏæý³þßYOë«é“çëÿÞ WõEÇÌúÿÏ›W:f¢c¦Ÿ:¦z]:×ú²vÜo£ÿÿôã¿þó·m˜†´±ŒRר´*™ š)Ô|ïb¼d7Ó€EM·œ+›òs¡ãz¨³»³¶ ]¦¬É:_T­X¾Ø3ÁEæ;¥È’VPp%=Ü´ÃŽ°‚W@¨Ïß|€®òþš_Ló­á)¤Î)š‰ñWóô´n{÷þÝé‡û ^­C¿\…¸á?•¤ž¾Øý^'Zü¥¹yŒqúD›º­ïðÚœOŒ>¼¯ó‰îiÎË»ùä+ÍÞÿ½ÿyê64 Wä¼7 ­àQ¿—/^f“Á†@1ÁõüI^ò¯´¤[§Œ|Aýå­]•¬~õpT2+ë]U‘]Û&­†Xù TIwÞ¯,*ïˆsÊ›,}¬B™Ã_Œþ”Pë’»m±{ Í#Ì©zÕOÑyÁ½kajÛà°’ÖºÂÍ­ßš'Ö62ìýßû¿óç?@¯Ð t½áXýtêêÿ]ÿwý_ûž\ûïØ•kÿ¯ýÏÿ©jý¿‡ÿ¶þßúÿùßëÿ?ðˆb+ÿüçûÀ áµ—”"RY ½ä\ÇKë h…®…\Ïi•W· ^^¿y>åOþ‚XY4@ŽSÓ_Η?ÿüóìÒ‚ù€¦Ê`R É³cK~)Ûúbw²†”WNÝÚîír.M^ëk›•»§qüu—¾íÀ£ýˆ'e–g´¯¾h¿µNù³û,†2™§}ߟöéu뀅É0®A¾ãÓÐtü+×:÷þïý7^vþ?Â;ÿWÿ¯þßõ¿ë9ýh½¬ŸÒi»þ¯ýg,¬ý7öùõ ’µÿ³öÿñ5Ì GC}ñúÇ¿~ÖëÿëÿŸW:±1Öÿÿ¯ã?O?ù÷ÿòíXeyÇ… |1™ì|ª—øz/U ¹æ)+Í Sîtøó¯÷”–4柅-ts-àAyÑzœüÔ1$dA#Í!H+@¤ìÃÙ´³ ¯É¿Ë£üûó•ÂÉ}½˜4ʘÐôÚn¦8/“§N€‘Ø{²€r}„ Oññ¯*$òõW*Ú¦ÚåZÛêKÎÕ`J]S”¼y4Ò;¾æŸ6)_9œß²# OåÒµ'ùÓLÞñ¢ríýŸþßûŸ1hæØù¿óÿÒ“ôMÇÝAÐ;«ÿÏÚ³ú×ÿ]ÿ}AWÐ,¾µÿÖþË:1ãA°†¬ý¿öÿúg½4ÌõÿF?̾hûD¿õ›¯ÿ¿þÿÓÿò¿ýà­¯zw”Áq‹#ïXÊŽ¡™TŒ10G0ˆ„,C7çÅ ³ mŸ2Ì—î~Ê@œ2Ý…VT1L[¶y€²9¤EÎË™R½Ø`—Ÿó¡­ÙÔGRŸNˆSùyD/†ÖÕžÊ'_ºk—Ó§Ž©KÈã|Oçñ>×£UsŽ.²]»¿RÿÈy–ÓW½ sÂÕ´BÛÕëIˆæ‘Kü“®ÌUýƒ6FŽë½]赟L‚]lÚE%¶œ@IDAT³÷ïÿÎÿó²rsÇÚù?_’µcôÒ©tÇêÿÕÿÖ®»þïúÏV¤/éñÚkÿ t„µcíÿñMÖþ_ÿïz½LžÀ±ˆNXÿïyg^ÖkÉôKu="¬ÿÎt†µvüùõÿ¯MG:/q7`b€Ì‚ãýOSFªü‚"¸&-Û…gÀ¡›9”»×˜Oçq‚&hríø)0Õǘ²kiʨŸ.Ÿ7óX!yð‘Gn¿x7(Kíp“?z)ûásLôhŸü~渠 ÐÄ¡ ÿa%ñ62äübZ¸ý•ú¦¬mÞ_•~Z²‡öÚv]™R?æ@ÓCÝ-K.ùÊ“MËÝïUyàFye¾›XH™Ißûÿ úµO|Érï¿~;ÿwþ¯þ_ýVÊ]ÿϣƻþµö_lŵÿÖþA=bÓ_¶¹4ö¤µcíÿãÓ¬ÿ7þõŒ þØú牟õÿiŠâŽÎ×÷¯ÿ~$ûÿÉKÜŽú€2:* Ç€DÎį́RÖÅ:6×3 ÅŽù“Þ×ѽydm€è©ÇàZ.u]“W! ÊdfQš9oŒ«Éî°; Ý»yä/ïmšó*‚Ðd§•sïÃÊù””õk‡Ãæ28ø’ÿõW_=·e(ð 'š´oÒÄÒ€[s‘ký# T` ݽœv À+ém«ø6¡iߥ¯$ ¯¦áß~Qgåi]­÷ÃÈ" Zþާv^]™©¿´cïºeïÿù€ÂÎÿÿ«ÿÏÚV}»ú×ÿ]ÿýR¾ößÚkÿ¯ý?ëãø)_¤þÆú§Oô‡°þßY/âkÎ8aO ñS§øèõo£Ð{Žõÿ×ÿåò·ðŸ§ýÕŸ½…Š ª8 ´‚"~uuÝPe%ÝÀ“W Å„ÍàœÑ‡Þ#jòÊ×¹ªNø¥ì”Ð(/.?FBä¹Ê¯úÞ*hå™?ù)kgÔuÛ}¹/þIs•ùÕlëôék<½0þ—_ýò³Ïß|~Ê^ò˜D”`çRy’¯¡îÑöf\1¼Ë/1ê¢Üµ)»Ãn´x†ïÈ{zÄÄ=Û,ñZ¯Ø=ûæÛo²¥?×ÚØ6‹ˆŽåáZß«Ÿ½ÿ{ÿwþïü§Çè‘èÛÑ«ÿÏÄÕÿ»þ[3wý¿Ôé vÃÚFÅqÂØVkÿ\×þ?ã¢×þ_ÿoý¿cWZ7Öÿ_ÿÿ ÿyúÙøWo½DÏÀŠÃ2ŽKÞ÷Ä è(Hð(è‚Ö?å œìIÞäã€rmqoÎ ²Ìuž?€—) çªGú/ùËùBÁ«ÈñÍ×_\ÿЫo*ËûðS¾u‹mÞHø¢u}ð‚üéî¡m¤¡Õ¾Ô3»ÀÔQ@KmvmwßÉEÎ{†èúsú]ן¾ÃSÀ+}ördÍ­™?çmDSÐ)/äýbW;"äi֫ׯæȽÿ{ÿwþïü]GÎA'R«ÿWÿÏ"’5g×+éy•€uu×ÿµÿÖþ[ûíÿëý¡£ýØ£?ëÿ­ÿW_¹þ©qQ?¸~*»;>í¯ÿ_»{ýÿ¿ ÿyú“û“·R<â¸Ì sM/× GÑ ¸œYžÔ”L¹‚5âž|I™ liš]•QZ¯Õç3’œ)³üÑýQâwsþúõ뤗oë›ÂØØ5½|GøÈ˜ÒmL¶¿ù›¿Il§”°¼ÔQåì¼QÜþP^]ø‰SfAA¿J#Ãé×ð£ÔN^¿ü(ßö þq&¯¾*_ò‘³åÕ#«ÐèÔ«½ÎÃcò*›x¥üÞÿ½ÿÆÛÎÿÿtÏêÿÕÿ»þïú¿öß±%cs½t·û¤­ý·öÿÚÿëÿÑëÿ­ÿŸzýÿ` ú"xÄø•‚9Òƒ¯)ã°Ž:šÖë¿ ÿyúñ¼Ä1ÆÀü¢4P‡ÉØ ¯4¾°çñiuÄÅè¤ã›Ž›ÂÊ'LpÇ£Ž/_½üìõ«×9G«\Žá+¨Kù¶±à‘n·ˆhš¶ûg—•²‚þª‘uòÒ?h¯>Tö8 ÏÀŸrápÉqo'¾Þw%³™6^Gž¶´Žö€cŒÒ¡IÛ& ç{ÿ÷þw^îüßùOtCuÄêÿÕÿ»þg×ÿµÿ¢GG®ý·öÿÚÿëÿ±“Öÿ[ÿýÿÿ1øÏÓŸÎ;°€+¶Ã[Œb `€B1KwÄÁ5IYC7ò¾–U]•9Þw@ èòb(ùvÿ˜ðœåüâ?iêTHTY&)ÛQÅÙ¦\éZ•mvh wN(é€avtMÅøÑÞK^ò0JÿËù/Ÿ½~óæÑf[aZ O2‘Y?ŹËkƒ¼÷ÒÕ6y•µò¡õéTtéß¹¿áëKg>©AY€–k;Ïœ ÚÜòÔðU™Ú'ýœµÝXÊâ—º®ûöQ=Ãsïÿ{ÿwþïü_ý¿ú×ë¥c×ÿµÿÖþ[ûŸozlêµÿ×ÿ[ÿoýÿõÿÿçâ?óáßZœ€œ{ps(ì‚ò IÒôNhÊsÀQwXÙDʤ¿h³ëé~¤u, êÈ$(G–œ_@Lé» È‹L£­rÔ©|ò˜ióäÛ *¯/¾ü"F+9¸{»µ…Q+à(#÷ûç‹§¾çÇ÷F ÔùN3RWe”¯•€&²e—Ôðwþf€´¼¿j(ÂwÒ|9P†Ÿ4ò¡¾ ˆ¦ÌÅS_£жnôí—½ÿ§ÿ÷þg˜dœcÆGÃ}Ì Úù¿ó?Cé‘à|õÿèÛ™#3‘VÿÏxØõl¦]ÿ³fÐkÿ@釵ÿÖþ¯­¾öÿú|µõÿÖÿ_ÿÿÿÿ €Åá0a#Ö€—b%0Ä'¸îñ0ί——{^Ñ¿GþÐãkwOŸ'_1¶\¾wÞi…Þn$¹¡u0vð,ÀBÁ ^8\\´çô”SVPžçäJO»çEæ5,Ñõ½Pß¾ûöQ¶rWPh¥@ á<Úè1=;ÔÆ`Ÿú=²>úT’vúй÷^ }G•4í´˜ Ù½†nê<ê4ýªnéís}ƒ‡tqÚ=qø^qx|÷±ìÒöþÇ{ïÿŒ[còšwˆ3v„Ž3ñ * 3^¯ñµó?úoçÿÑoÆ ½²úÿZSWÿg¢;vý?¶À®ÿkÿÑ“kÿ­ý“¾öÿúëÿ=|Öú!ëÿ¯ÿŸµò†ÿ<ýùÿñ¿¾n¼˜¯ÚõÝHˆ¤5˜£Z“'vÒÐZ”«A*N˜¼žûÒ2 pÅ®¥|Qp@3Þ2^ªãÅÓy”PÚ‡ZâMSµ“Å£v‚ëÈ9t ®Õ+ŽÌãTã)„vbùùdùðþìú²³JšLBmTp%]~åìŽ'´åIÞœO™€H#¥6+Wº–÷˜_w¨É· ískÎcêR}óÍ7©»¼ÚõôFüä£O_NL´‘gb×@eºá¿÷?ïIÓw{ÿŸçŠ1»óç¿y±úõôÁŒÿ¬)»þŸ¯vý?»ÁõCÂeg8_ûoí?ëÇÚÿÇOXûý?c`ý¿_ÆÿS"¶DçÅúÿg õN²þÿéß„ÿ<ýì?üë·—‚Qœ•1@„îî‘ÞÀxõ¼_™UÄ=G@eè¼Pt)P ¾Ô3„¹Y`}7@ÝD Ž2àwÞ©ã’•ÄèxFf¢’sBËÉoPox“ášìzÒ®Êeá5H~1%zÄW[+_ÛØzÕÞsåœ;”÷þ]bé øµ ®Š¥÷ž(ŸöOA}õîÛyý€RÀ6éÎÊMþ½NåVEÚpÉ¢ŒºÑ–oëJ_^îýßû¿óçÿ(ŠÕÿ£WÿŸõÕòÐuCÜó]ÿwýgGô}œl?¦­ý·öÁÞŒ¹ö¿îˆ Nw®ý¿þÿwý¿õÿéÈõÿϧ»mùôßÿô-cBðH^À‰\……±!< bå¸<?jô0Z/¥³@y' ›`zs^¾˜Gç }˜Ðû’ßÔï\™ZS7™ÈðeÊG¶Æä› ÞËÔó27Z[¸‡Qd!OA¨>å1ÀÕwf‘ Ÿõù¦Go Þ :}‰Î¹2ŽÔ?|µ[?á©~_h/ÞÊDž‘…<òS‚{zÚ8ªœ|òh#çРÛû?ý¾÷çÿÌ soç? rô2}!Ðz„ΪžrÙóÒ¥Àõ§y«ÿÏ«ÿwýïüØõí?ºtí¿ãœ­ý¿öÿúëÿ­ÿ6í¬ÿÿwã?O?øÅÏÞ2¨â Ô²šønh[`뀌s¨ø2y÷Íón¦87/DœeÇR_ýu€+ 0 è‚/L‘/\µårÙÈWYÐHä_NhøÞÒÃÇ5!ÆãÄ®QÚWÐǹ²‚:ÈòÕW_%ºù*`¥Ô14êÖ~qã“wÞqÁH9ïô Ï¡K;´û:6Â(ßC®É&V/¾¹¹^Ž¬Ò¥‘û«_~•ÝbÒÈ#¿!u¿¼}? š‡L%œxïÿÞÿciçÿÎÿó5×£/(ÎÕÿçë´Öˆê[ñêÿ3F¬Iúãqìú•Ú5¿ïÉt½ëÿÚtêc®Ð#kÿé’GÐ7±a×þ_ûæÆúëÿQt½ðЗÞdÜÓC{ù»ëÿÿnøÿO?ý÷ÿòmÁ"7¼¡†ÝѼÇ";鬲Yh `ˆ—–wá²xôÎî!A=áDƒÏy™„ìf!¿t‡ÇLl„êã&Êâ(áÊ×w‰µ-F<ÚÎÔ9@_^^?m´KÌ.3±<‡  @¶©rxŸÝXi¯‹ êÕ.ive‘Ohyç•iïÿÞÿŽGãBØùv7š?ÂÎÿ³»ˆÂYý¿úßÚáØõ×ÿµÿÖþ[ûív?cý¿ã{êõÿf3Èø·l…õÿg~\ﯿµþÿßÿ<ýhv`Q,Cç E(ûøcÔ©8kóòq1°¦Îl@ec¿0k˜f€~ñÅó2öóU<ôv^ÄRWÁÖmPçýSGù“¯`ŽºÊ¥ì·xÆ€Kù°tÚ„ï ¨T¹[F?0Oþ÷2ч(õJ^õñB÷L¹w*“{vɃÞòy•¥uµoäïý?ÎGlj>Ùû¿óß\ßù¿úõÿ®ÿ»þ¯ý·ößÙaɆŒý½öÿÚÿãk3ÑZÿoü¯‡uó¹Öÿ»=åd¬Lˆþ˜xýÿ³!†¿¾þÿY_ôÅožþô¯þì-pÁcÍDŒ ç„€Ϫ›€Ê´¬X:±’®¹é¾ó(àæ”s´îìøÁkv3XRO¶Ø=þ½~e+‹sõ»"ÿµ¸~Tù'ßÔÁS½Ê¤®Ké(ß2xVV†kÏÑ÷]^h ‡´ßµüòícúÔ—ñÑ?úMëÔoÚﱇm›4Â+‡·t±Ç=Ö#Oe7ØÕ†¶C•ýKÇG6îý?ã¬ý¶÷ÿ€°úaçÿÎÿ»þ­N16VÿŸVÿïú¿ëÿÚkÿ­ý¿öÿúl¤ØLãò)Öÿ‹«ùðEë{®ÿ0‡õÿÿÛðŸ§üåOÞšX&•àÜce@ƒ*àΤ ÎMÄNÆ—¯æ%œ–tð‰Ã r¥ŸGÙ¢ÀäzNmJ†§°ƒå…ÊÆ!PƵ€öõ›×¹v^ À'áRmÛIlÖs{§ðÈ{v'iúòtÎ1»·Qž>.`ôêå«Ç;½²Û ß é—«ß\ãé>½™8çC#](à§-ísõi¯ÅÊ™”ÐjxÈùùçŸÜê6n¼ñç÷ºõÊÛû¿÷çÿóÏÿÏ:·º‡žXý¿úßâg ÄÆEvöîúÿ¼–ë—]ÿݳöß釵ÿÖþ½°öÿúÖMÛª~Øú1)Ž=1ºrýÿƒ7°¯jƒ¯ÿÿú³§?¹¬‡z®ŒG{OÂsü?•ô•týözÀ!;Ÿ´ƒÌ/ Vy 9¦Ji—¶‘i*­|äšy©[Û'¼yùzNÿ©S ºs­íD«~;°ð°ËíÝûw¹do?¡Ûû?8÷à WïîýodžÌ5ÞcWHzÎN_uŠ›WÚÿÓ;ÿ£ÿèÁ8Yý?àøêÿ]ÿ͇Õ±£]ÿ×þ[ûï|ĈýͶ]ûÿ<‰ÒõsíÿõÿÖÿ{~jª~­ùÁ§ã‡ð­ë‹“&}4 ×ß9 Ïe¬ÉëÿÿÿÓÿË,7Ìu“€œ EÐU½ù®{þiü4/x¯ƒÒŽ,žÂïIŸÇuæŸú†œï¾}yШ§u¹B7éåë‘ hþC_ÇÀÀlùœ?hpñÕ¬:–hœ«·ü*³ôÊYZï²€H¥×G} «|í´BÓþ³ø¤­·¡G–Ô5×ú£rª«òtr*§_Ú‚ÖAži| Œìón±&9f’·÷ÿtÆÕ{ÿ¯y6cV0FŒ»Ž-çMk¼óÿèŸÿç%㦺mõÿêÿޱ9²ëÿùA¯s„µ^Ï]tl¹Þõí¿µÿŽý±öÿÚÿt£¯±WoæzÖ“ú_tèúçýÊúÂSQÖï–^ÿïÌŸõÿÍš26~ ýÿ±!ŸÕ£Îޢ׉ iâqeA•_ͧ±í D`K_\š„+­çxS0ÊxI™˜öí7ß4ó˜ÛçóU¿p›?_~ùe&\ø‡=¨ë¿&åÓ€bmHÊc…Ê£ÁÿUŽÄøä˜ö_tçú¹Mêí#‚ú¢íDõR”M‚~ðiYíÕ/ó.‡|»ÎÈ[…’44n]Þm5i§§O¦rmgdŸdqƒóÖK^ ¿_u¥Wæö2{ÿ;&Îýë=ïý?£ÊXÞù¿óß8ˆÎ¹tѱúõÿ®ÿ»þÇæ8ËÅà®óµÿÎ>ºcí¿µÿ×þ_eþ¯ÿwž$ZÿoýcàÙƒ? çúÿƒzÀ5®CÿÀ-‚ÿüh¾BÈàðë¸G÷6ÙÉ3Ä7tj–)”Çûôëp¦ÈkàÐôºÎÍÝÑ)]ß›wAE_;„"Üð"Ëù…å,öydnøO¨º€/pH#òU¾IÀxi|i*C×ñQ™ À Zk 9Jï:Ååb” ÒÑã ìpÍÑG#y~IuŽF_Û½%FÞ7>Ê>d½òÕÕ¾˜B‘¥e+‡2=*—:ÓWÃ_ž2dÏ}—·÷ÿÑ×úQé#‡sý¸÷çæèŒ açÿêÿÕÿ»þÓ]g­­»þ[ÍÚ¹ößÚµ£Ìaíÿµÿ×ÿ[ÿoýÿõÿa8pŒð‘ñµÿ>øOÞÅøÂÈn&áW³ÍPÚxô'¾Î»Å(»ž€R¦Ž>3¶`Hw«àá¼áã…lJÌÿìÄ‚¼àq„G_°åÄ1“oò QŸw;¹„<Â7×ÜË8éŒ)Gù‚kmp%J§Ž€dó‚y/`Ï¿¡O§]U1GFŒŸ¾rÞþÀ»×x´ß†8´oì:»ÉãreÊW†>tD#« ][{ݾŽ<¹Ÿs®:ÐÔ°Äß5™öþïý7–vþ??S¿óÿ€¸«ÿWÿ['¬'»þÑ5ÁšËFïú¿öŸq°öß±áõ}a~4Ô&=×cÏÿµÿ¿ûlíÿõÿÌÁq¾þßñk®ˆªˆÿZ²þÿÁ1èXÁ˜ù}ôÿŸ~øóŸ¾ÕYh.`Ä×ÅtO V“I9  9y+}ÄÎã{‚gl;È’pý)hƒg:{¾F˜¯ûŸTvÖ³ÊWRßÅ£7ëÎW~ä€)_¸˜L7’Ì)?éÚ†Æuy¦Œ¶LHÛ§Lâ¹®³Æ(MûæíÈN/rmË9W.cvþ¹&—¼´õŒÙÅ*8…¶õ‘éSÞý«¬å© ÷ =Ç$ö^¹VNð¼Ü¦Ž¹¶›¶+3ÇÞÿàîý?kÇ”q“ñ2qÇàÎÿÿÆ…ÂêÿÕÿY‹®u%ƒbþìúì©]ÿ×þ[ûo쇵ÿcC­ý¿þßúc ¬ÿ}ýÿƒe°‹Õ8Šgœ«ó÷é`é´Gæb´#›Çu°‹oœçCëßœø›ë€H€NÍÅ—’vn¢*ƒg¯ÃÿâE¤‚Oòª\|S?‚+ôºqß½Á" ¾v@uw~‚ôÖo÷–àÑ:ç:¬²¶~/Z—/|¸^Ö¾Ã=^d¨§ýÂãú›Ðà]z×1f'¤ßCÛÕ›Xùõµ`GVâë:ó£*–OÛŒŽ3‘çj‡N>úGýs Äj}M÷iþ¥m·nïÿÞcÒ¨4vþïünºôýQºúõ?ѵ¨†;å‘õetÈ®ÿVè[Œý oºÓµÉßõÿôÃÕkÿ¥;2NÖþ[ûíÿõÿê;Ò ]s¯ÿwð‡õÿûýÿ§þÕÏÞÔ1 —sÔ˜ÀMÜÔ9»P"Ï1—¾´²<Ê×kÏ» 1Àðžs«Æk 3N`È£zòŒ5ùdÀϹù£|{îºçbåPM—æ(²ÛA¢®Ô? ÖÉ"‹sáÞå…‡ÐG”á=¼´!;¶¦~eñ¾‡¶GoÈ«¬•MÜ®¾®C7çb},TiÓge2ñ=åšÌd\ÏŸÇýlÚ½íäMØûÿè÷½ÿÏãÎXÙù¿óõÿêÿ¬/Ö¾]ÿwý£!v eÎ×þ;ö¬ÞXûïØÑ±¿×þÏ<‰-~,íãj±Í'›ýØ[kÿŸ>¡WîýÕóôÕ¬?ëÿ¤?z¬ÿwp„õÿûýÿ§ýâgoqa SƒRw…p(Í¢3úC^€¦$…¯8²Àƒ&ü‡¦¼ Y´îyÊåq·‰ýûxa¼Š¯PâûÑ|ñ‘d€'ò]r ñ£~4ʪ¿€9 :9—ž‰N¦9=ÝÍE)¨ºÉðÒ/Êâ— å…¤L^CåOÞUV¦í“¡Î`ù¶Lê¸áxOw®íê¾ó.MÁ6×Í?ØÔÞÿŽÝ½ÿÏóËyŒ•3`&á¤íü?ý´óõÿêKà®ÿtå®ÿG¤/fLÜ×k«°öß³MjÞ8Öþ;ööÚÿkÿ¯ÿ·þ_ŠÛŸú!âûq#Yÿúæ÷ÅÿòB §»^£«ƒä>(z^°$×eE›Û *=ÞågQR¾ Ž÷¥´XnæèµòÊPî9//±¼¼x|˜*Ð<šïñ¿·ÝTÊ•OË(_Y›§tx¯¦œÇ£"£vO@ÿ ¹êѦƒÿÈ9ùJ©×‘¾˜X>å'÷É+HvÏCú+_}w¾òÊO¹òoZóm1È’¼a¼÷ÿŒÕ½ÿg|g€|ò§c-É3vfðdÀîü~·ÜÎÿçñC·T×®þ_ýodìú¿ë¿5ví¿µÿŒ»:¶õu;°vÈ‹Í:×λ–ˆ]¯ý¿ö?ÈØ©/gìt|¬ÿwÍvú„Ì¥9_ÿïØ¨3ÆOmÕꙇo?»È'¯G‰Žâ÷\}ù YÿߤK?UG·zýOaÿ¿p³2˜× oÅb•7½‚˜ çΉEe¢ï柣†ÿµ8Iwí0pBº:zÎÀ-´ŸÖ/¯ÁÓZÆuù½˜Çñh~ççÂwïÞ…FºG¼`Ý!t`wðÞëpþÞû¤ j»*›=c‹§[òåµ¾²³kþÝe*ï´sÊOÁç'ÿüûžô @.ùÊ+çø”×½ ¨Yöô³°÷ïìkL÷1t?OÞüyÌ@ãz®wþ½Ö¹»óôÑŒ º‡Î«Þ«ž\ýOm^ýÿX³:Fvý?Úu×ÿžêÖÆÖ¢µÿÖþ3„èÓÑ©›…>Yûÿã9´öÿúñE×ÿ‹¾Xÿÿ·ÛÿŸçÞ8££ôçö´Ho¨+î!Ï‚eÊ€ïýú, ‹¼cih€Yà–>Wçåå‹—½Oþ0MüÈs+GäT÷üûn^¬^:òœ6ÌΧIo=ÒÅåM»£¤[äú%5@–4/¹sôó¶msë©hµÖc— ÒÔ>†Ù½•­°žïŸr-¬ýÿÜí»O³þßñ ×ÿ;8ÃCÇ\skýÿßnÿ?æÅÍ3û-&ã¼J@\%e9@G^Ê~L9“£ Lèñ¹Œ™–W6ŸM¾€‹yþò['d„wþ­§´E½ñ‘†º‡!5i÷¼ž£E€ûR‰ “AL~ï¾ò¬Ê÷ièWÛúˆŸüw³ /A|?Nbþ&ýÞ÷wþ#Täj}ŸtÿãÐúÛ×@­ÊÙúÓ¶‘‰4Ê»Þû¿÷߸2FÄ÷1(mçÿÑ1;ÿWÿ¯þßõßZÛuµë±~ºþÒ™»þ¯ýgœkÿýú¼ŸÅÀ* ÙÔS´í’_Y•­¬.4øªCy²@vñGÇÉÉ×=š8d–·2•§²šÖkqël™ˆäÑæ¾‡lº+¡<Ó?“"n?"ï¿)?)·÷ïÇš1sGÆJ¾ªi<ÍØî»ì:Oä‡~çúaçÿêÿÕÿ»þïú¿öŸÝÛkÿ­ý¿öÿúõ‰ëËÕÆv}O뵸6yó×ÿ;xDüÛõÿ/ýÿ§üü§o¡=ïÄq-4?m&°Ã¹IÔ‰u(9¶ãôÎ?“4èÖ8³á—‹‹ Ê ò{Ì-ï¼Âw|ïf²èºèî`TÊDž° HÃa±¡íi;¤+ ôцロwW ½Ç#•ó®*¿f„f®ý»´|é©Kfä8tê©óß¶¡MßLÙC~ú¯ô¥ò>•1‰·?òKNS^ÉöRr /þí—Ö'¿|7í^GÓÄʶ‘Ù}ºùÂÞÿÓ¯{ÿwþw^Gìü? ÂßK×UOÑ7ÎWÿ?ëdÝÔþqÞp×Í«ÿÙÖúÓ;tn×9ëxCû,´Wbæä®ÿé{¿ü¦¾jþ®ÿgð臵ÿÖþ_ûíÿõÿÎèZ»þßúôâÿüçéGó,ï€ãD `ÐI˜E(ÂÐ Ê9‰S51] -®¥†Ð>®¯¼GšòW=5˜°©¡äò‘!õOCÓK™¦ ‚sÏ@§msMA¡õ~7@8ôW{?¡@Í¿ï{‘üðkyøÚiõá¿ä+—>™<†4ðMîWXýÈðÁGÀã¤Kû(ý²ÉÏ6a4Ú1וI™žë[Å*KÒÓŽó ˜—°N%>IÙiëÞÿ3Þ÷þÏà™ñ±óç?²úõ¿(ëímýÌú"Ãzt­'YÃvýßõƉñ‘ñp ã'i3dÖþ[ûê¨ÍÚs±°öÿé‡ò×étÖÚÿ틉×ÿ[ÿݱþÿÁ ªK_üÿ§?ý«?{kÀ€žÆà $&#OIÔðpÍ™A/­Æ‰4†‰`0É·›É¹àMø\å,'´ËªeËðô(‹n®å©¯uµî{ÙÖ%~¤_ò+ŸcòÔ­|l›”” ˆ šëÖU9ä ÂÓµA,OP' HèK¢ÏÕù‹'â[ßé-wYÂç®úÕÄ)œöÉ«“ÑA ÆÛD!êÜ;´NL¡«îôÑU_ÛEf2x9ô©ÝVúµõ¯òØâUWËwr’¡üÅdV¾¹žÌÑ4t•_Ø™| í¼«më@“ .'{ÿý·÷çÿÎÿÑÁ—Žï| ßœ¯þ?à ]JV¯þßõ×ÿµÿ˜Skÿ=ÿk-uTO²¡×þ??Ä[OÛ/µÍ×þ_ÿÏXèaŒ¬ÿÇõ^ÿߺ’ñ0vçúÿÿyúñ_ÿù[‹nA Å. óûB“¼¡—g’ÉwØé¬q¸V^'£“&_šÀ9R¶u—ùŠ!ˆv%ZO®/á3ñ¥pÐâd‡.Ê™²¾”ëaŸÊ ¨ =Ûå®2•EšúÔ!ä5_¹Ô?é½¹Çõ:<+“Ç=&ØwEqL€56”Á³Õëׯ?±DiÇ%:ÙàVˆ,MœŸÉGÇЭ‘‹v*|´å) ß§àÕQâäÂ}Ú£®z\kCû&ù“ö~Úç¥õŸæµ~qh'Ö{ÿ÷þwNÂÎÿg{çõ~ãÕÿ«ÿÏŠ›õ·k“õhΣKæÅ®ÿ»þ¯ýw~äÌÂ:Ø^l8óıößÚÿ†ÄÇ?^¯ý¿þ5±þßúÿg½ˆÏþ{èÿ¿È"9`‹è¢i1||o&Èã+~ŒNštÂÀ5€Ìc€c†¦\ReÌpB7§‡ò§§†]ÉÜôðG>‡61”…´ï¤¤®Z§â×Sà{ú´¼2¾>8œü±ëË/¿ ˆ€r]À ÏŒ ëÈŒ•µÿÖþ[ûŸEõ̵ÿŸ×”»O2Šã±®D‡L·­ÿ·þŸÙcœw?… "}ýÿÓ7¿‹þÿÓæ%î]Üüï³³k„A  wš\£J?κÓ,¡˜kÐ=õpViZn*˜ÿÏ;ˆÔ¸¹—¿ËÐ{ñе9?©©Ó5G9;“M€¥òy5 • Ý·ß~ûÙç_|¾-«Õú(|œê#&øãé뎭¦ŽW³3Ë ïãüÈðO6Òá“7u6a*H?ÈOOOì\ù|¹ëÒôrŸ§ÐNÛöþïý7Fvþïü7èŒê”êýÆò…;M®i£¨šg}SšêöÕÿó£ÅêÿÇÚdnˆ„2ñtÈË'ñq]àJ?ëßãÅ¢ÚáQ@üÑ›<ò(½õpJ»:íEh¿ýæÛÏ^½z5»ª^älÉ—vd~=ðS‡ôÔ3/8­‘VÇW^Lý¡k»5¿DêãGß]ím™ðÞÚ–‰:ùê §a¦œÃ½µ{¬¡ü*ÓÞÿ½ÿ;ÿwþÓÕ w]A7I§7Vÿ¯þïú¶ëÿ®ÿôDl—›Ž 'Fa|¤KjsdìÜÊ(l–µÿÖþ{¶u áèšµÿ³.Oˆ×þ_ÿÏÜȘXÿ/ý` Yÿ¿ké¬$¿ãþv`Y0¿º@©vòŒ’,èÂa î4¶[‡"UÆ® Á®«‚P³òäK4ò•{ŒB™‚D)s9Fè;#×\+“:.c¨uÙò‰g&ðEwv&M…wå«ÑÔúÔƒN¾#õÞúË_ xBK6Ó‹¿¤Ùõfvdyq»GõAeS®Ù?|7<LRÎ5 NüÓ–2£½Ë0Vô¤¡S¶ùè7ÍyÛ).=á]§Ü$ªqïÿ(¿½ÿgììüÏ\Ùù=^»ú?ºrõÿùq§ëë®ÿ»þ×¾Zûoí?‹æÚÿkÿ¯ÿ·þ_|ÚñG}‰Ö9›A¼þÿúÿl¾U1‰b_üçéÇÿî_¼zx߀;ß}8ïoò«ªI‚|;ŠºS Hcz™yÓcpŒRjÜØùÃøÇ§<ÑÈ/PÕFˆ?\/:· éÃûù‚Gjò幟/œÏã~W¹ÈrÑé¨ÒOÒ³¬sÞNìsÝ´îò Ð3ò¢Éã‚@#“qÀ*ýA¾o®ÝWú…|ʦNN°K ßö‰4ü>•«u5=׈§~mËsîEô í±C91:uª;ý§À°ñ‚úôøíýßû¿óß|Ùù?<Ï¿ÕÿG‡Ûå[¼úÿ×Yïvýßõí¿µÿÖþ_ûŸ/²þßúlçøÜ—Êfª¯»þÿúÿÿøÏÓÿ›?}Kyôìå‹—@ƒBê¯ÍŒvƒpSçÂ^ÅUZyq(xËK=êÉy– @,Az×êõ—^yv^µ®!ˆ‡žÌh„Sß3ÀsO—×£õi‡´¶/m‘/n®” ­ z/§Þ¯¾úê³/æ%ïÚ-¿—s|ýÕyoÖ7ß|~- èòmmT¿PYÛ—I»Ò+oehߢù4¨[H;®]5®SÏÔUÙ÷þ?ï’ÛûÆÅÎÿÿÕ_tÎêÿ³¾­þ÷NÉ]ÿ­¡]Ãk7X[wýÿø´µÿÖþ«ÊÖ]ûíkèÝ·Yÿoý?kg}[±À[ÿÿ`$zäÞ?ëÿnòþ?ÿר^ã°þjÀ›O^T^Íâc—ÃŒÁV0§i åѽáÓ­£òJðd®ñqp„î;±”oPgC±Gò„‚1kt® 2µ.»¢&3ÀÌ“Á? Tø¸ûXO|öoáxGðk>x·=}LQ>ä'»2í3å¤+ œB‡þþàë³È9‹7cN¹wß¾ åÚN2¸V7q+ ^G¦ypÚ€^;;€ïåÑ ÊÅäyOyK—ò“> mË£ìäáEv2íýßû¿óçÿêÿÕÿÖ–®[]Sº^îú¿ël±:NzÛfl‰µÿÖþ[ûí¾FýçÂýºkËúëÿëÿ¯ÿoÜñŸ§þ?zËÀ088'ÂL—¤Œ±!OxÿaÞñôúMÎ)JåûC_…áj—ú „g–*# @,è Ýóœ÷íÔ…4‚߆Pe‡ÒB}Èã\zó´ hYæq„¡ `'ž:JûeÒ‰çPo'tÀZ—ê^z*?ù€[¶O*C†w“6U~öòÕË\ãÙv‘!<§ßyê.¿9Iº?I›¸ùÒœ òí%ÙåµO’éϤX›zÕµ÷ÿŒ³ôÏôÍÞÿÿ戹³óõÿêÿ]ÿ³lΟ]ÿ×þ‹­¶öß±-Çæ\ûí>ÆúLJ]ÿoýÿõÿϦ¥bµŸè >•pÏsÞ#´ã{±»¥')½ùõôã¿þó·´ìú)ð1‹²4„*òkI_<.xåÆ8åüŸH‰ë‚%Ò+Äuéï ‹4ïµw!Ú‚-¦È|ñ÷²óî^Ê®(åç…é‰Pòt–r걋©&¦CÕ5Gók¤*§N27FO®ÆúÄcƒy×Å¿7H\p¯´k£T¦/¸Ã'ÛÔá¼|Ñö>Hëyû®i®•=}vã¥^ù­ÝG´W=èòeÇ[½{ÿ÷þïüßùO¿Ò+«ÿŽÖÕÓ«ÿ­'ìúì‹]ÿ×þ3#Öþ[ûíÿõÿ®åqý¿éˆõÿ×ÿ/†a^°¥ö´Cöwá?O?™—¸[`óºAz¾7¸ý;á‘?Ûçó…=}^ UA²‰U&TYCâ+ a T¡Å÷¼üäúûKÊÕ=Å2øÃk®N«&½` o;Æ^ê/W耥§¿ÜÖ‚rŸtÏC Tþ¶ 2)MÀ“<òk›€FߥüœÛs´÷ÿŒ½ÿ"ùc íüßù¿úõÿ®ÿ»þ¯ýwìÁµÿÎkÿ¯ýÏg\ÿoý?Ãúÿëÿÿ#ðŸïýÇÿû?ýzL²€v# ÒÌÁ‰n× WóøÛ·ó§IxÐÉ+ÐCø&óÎ'694wþ@誣Œ¦­ú#Ë$ÙÐÜÃï€4ò+Cw{¹Î–ÖK>`U‹o|å°ÀŽ4uá©@Pƒkéír¦O† ü:q#ïU¥å®׋Úß|þ&ï¥RoCåv­Ž{_•Géò®íëí#õkw²á tpÎé £rþºú–¶÷ÿ|ú~ïÿ™ûÃï;ÿwþÓI«ÿÏz¸ú×ÿ]ÿ×þ£×þ;ObÜmXöƒ¶¯ý¿öÿúǧ[ÿoýËúÿÇÇüÇÀ²+ÆøõxˆE(à‰ø‹\sdíÖ±# pR $NÿÐ6ˆ?Þûäk#èÊ ^ŽQ:ÇýëBb|eñ’•'ŸOòñK™á‘ú.^̱°>e×Së,O×ä%Ú—ZNx åïO_‘LúÈyÚˆàªßu€¥+Ïu¼¿!ùÕ bý˜´\_rNY ZÛMžÒ4ÆS:ЉLdš/Oyò;¢C3â+ÓþQFyå¤õñ ^½öþ륽ÿÆÇÎÿÿ«ÿWÿïú¿ëÿÚkÿÅ>¾lO¶bÃÚÿÇÿ`G¯ý¿þŸ¹a,8Öÿ;¾"¾é( >¨ã~M—Ôu_þÒ5ʦ/¯tþ­òæÚúÿÏýöûâÿçX‰AÐ`D2Ò4±#M¹>æ‡nÐ]œ­Î/zü2xg×kô€Qœ£—Ï`ÞïÞÏî¡K®Þ±²xã'ßÑ-mª¹&ËÄÎ %gòýjyåßxÃ5þv>yÌïÇa—š2“/6iJ¯ŒÃ59È©\CëQÎBïËÙS'Y”Íî)õPT’ŽÃýëNåƒ÷ýüÞÇê•q±þßúëÿ¯ÿßµ£kEñŸ§ÿ»ñö#cü26@ž÷ïÞÏ. Ÿ}>z$€3Û÷>aêü²È7àsŒ·ò›@¥·rI®ñ{$ñ€Fg·”­Pžø›Ðuðo@sç-ýÅ®9 yihPR¾Ï!k[ä½ä(¯vœ]c÷ºð“çœ]mÑÎ!~зBxý!ÛN|Z§mroÞ x6l¤+ߺÎã‰çñH¬Z.²é‹‹>¼§½M÷+iÏÑ8*Tk£@IDATÜßO§›×_ öþ?mÌ8Üû¿ó?sä6‰;'%íü?útõÿÑ­£l¾56nç>«ÿÏÖ5P¼ëÿYsvý_ûoí¿ù‘yíÿØ÷ÖÚkÿ¯ÿçÇ‘†õÿÖÿ‡Ôç×;ÿ}ñÿŸ~ðóŸ¾5 4Xèä(° úvåî|è Ne7Ð¥`ñ@ Ÿü]á=4B‡›NwX¤$]7Aþ!¼ä·nçx¶îoß};²Çüðõ ˆ© 0ôt4‰æî¼‘ÐrÃs³'ÎB!m‚ó Š9's<8ªY¤ sázþ<’>åP9?ÇÇüñ-¯¶M=€Ãö¾ߦN;«z¯¤ë‹î¼ÏKœOE§î\’äô{Ú3ù½•‘\å¹÷ÿãû£KõÏÞÿÿ;ÿWÿ¯þßõßšÐ5»ëƒ¸a×ÿµÿj[±ÇÖþ›™]:¡¶çÚÿ3BØâsT—¬ý^QÀÞ^ÿoý¿õÿÏâèÍõÿ_DOVGÒ›ðŸg+»€Î#x~ b:_S•ìaÎ{›0ð^);¢îééðáÑ/ð è,fÒÊj:€ %¦nA9´³‚hÒ8•d³ úåRÞ˹¤cÔŠoAÍEøáåýR퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ_Oÿåü*™F.ô-Ós±vh·¸íRŸó{ÿµ=y'_PNP¯@v?TÒçìjëÅËáQÌÈ«þ½ÿ{ÿÇÿ;ÿGoÐ3tKu…˜NZýÖ¯êòÕÿg\X{¬ÇõÏ}ýšÅï±Z£vý?ý±ëÿ³]´öß±kÍ¡µÿ˜­kÿ ]ƒéÔµÿ×ÿ‹¿ºþßúÿ£~/ýÿŸÌ#„áhÆ9Î/$Ýã×f/c×1h(Ï£Èâ\c•!ZûtÑÈ·;„¶-›üá:÷y¼+jhKSyZ?^•§ï²Bëz™Ô/ÿêë¯>ûðþC@ð“¶”®/iÆ?mœÇ ñ–øÑ¦ò£Aë|þäÅ¥5¾•“ïëŠÊ‘õÙh¿¾~8íô‚v¡¼ 0‘­¡}¬&©Sڽ£õâç~E6ˆÕäáIǯ~5;ÛF¶Êù.¾{ÿ÷þïü·óÿèŒÑ ÂêÿÕÿ»þ»b×ÿµÿj³­ýwì%ýÀŽ\ûÿÙ_ûvO­ÿ·þߨñ‡×ÿŸ±°þ1;†aípxE\‚óñ÷Åžþù_üèm¼ Ðã:¤õÜn$4ºÒ+ÐI;‚ 'H€—T„Ò)o@ vûXºL¬ìò“>/Tõò<.$—êP§Ø©¼}ø–·tA§¼z_'Œ\ê™ôœ¯Ö‰6m¸:“œ¡›tu¢S(•ú. ÉÎ3r¸Ãƒ Ú,Š—,ÃäÚá4œµuêÀÛ!‰sšºÚ)ú¯2¨£ý)-_($ì„{üÊS ¹æþiCƒüÒz¾÷ïÿÎÿÿÑ“—^¨:i«ÿWÿß~ܲÆíúŸ56këôÇÙá¼ë¿þXûoí¿ØŸ£#ؘµÅÅÂÚÿµÞ×þ矬ÿwÖÖõÿÖÿ¯Ý½þÿ…ÿüè?{[ % Í.Ÿyv5À íe ÞßRW~Õ/àÃ.(AÇÇpxH¾… moH¯» ‰MØ7óòx‡piê¦ÐÜ@4÷s `Éâèeä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/Ý/á5ç/G†Ò¢Ç¿uI!;iÚv‘ñžðÉyä¹:V]5=îS®µï Ÿ^ç~N¾ûu^Ò~îÚ£u{ÿÀº÷ÿôƒ1alìüßù¿úõ¿p²V\ëè®ÿ»þÇn{†mæ1>j‰¬ý·ößÚÿkÿÓü—õÿÖÿó˜—õ¡þ~üÚÛõúÿfËßëÿÿfüçé‡ów€pÇöWÁ êó•>/tçÄö¥j:S~ŸÓØ9ƒ†Ó£Lu¨«¼ï±²E˜¥7/FóÓš,¶˜dä¶ðf(¥ìœ‹å¡qô]ùCô_›µý¤²¥;×fri‹k½ãˆåúqLºÇô T0š´”›z…TÀ‘öG¿€Ø = “[tg÷Ôˆ{ñ(oùG|”•p •­IºKnu¹èz¾÷__ìýïØ1þvþïü_ý¿ú×ÿ]ÿ×þ[ûýÉf#ˆñÚÿkÿw¬ÿw~^ÿoýÿþÈ·þÿ,ÿøÏÓþò'ouòÝi ¨‘ú ¥çQ3NLß 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçø0 Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;/h—78Źžó(šÉK;>œGkÛ矞úIÊÚÓã{ó¨£:+kÛÝ6 w޾iêOéÝ#‡r=ðr޾eõ•÷ŠÉ»ï:ÿAÐëÖ[y7×Ѓ\{ÿƒª¿¾Ûûÿ7‡;ÿwþÏ«ÿWÿïúŸeõ±öŸµs×ÿ¬›kÿÅVÓìÞÚ\FLm¸¦­ýwìS×þ_ûý¿gßþXÿïyÓGtæ(Šú´ëÿ¯ÿo,Ûyúñ¼ÄÝ ‘è_CÏ=fök&¨¼úhkðU]šsƒÍ‹Ò¥©Ãä|Ð ÖNýSÏÔÕëNdyߟX®ûu@BA(`λ÷ïê´àz”qž¥kß­S=øÙu„FÙ)ðO•Oý“g¡˜‰ûKde%™'&›pvXA3שû’Gù ¹V·€ÎÑÐ6É ÿ¶ã¢Wõ)ý\¾õµÊ¿ûyÛ—´½ÿ{ÿ¯·óç¿¡°úÿüˆ°úÖÓ»þïú¿ößëØ ô#ûií¿cS>l{ëÆÚÿkÿ¯ÿŸmý¿õÿëÄõÿaµ8˜ÄþóôÃy–ÎÕ¡]€ Üô—¢-è,Ö€)˜­rW#¡~ýÙ_|p¦üíXÂÃ/ú‚sü•”+×á= ˜}ûÍ·¹> ”ÇçæßUŽQõòÕ| qÐrõàˆ—Î.*m˜?XŸ]×€ŠÃ>é}#¾/’µMm_ÞuU1Z¦îö~x÷QÂäŸÄGûú8`±v‡„Ðçd燺ÑEî!n{Å•ËyÓ[¾9Ç+•œ6çÔŸ å)ÆËá/÷@½d7O»´yïÿŒß½ÿ+‡ÆNç®ØõÎÿ³Ó1óuúCØù¿úß8Xý¿ë¿qpl˜»þ¯ý—uÓÚé°¶®ý·ö¿± ÔÎ=1cCÜCþÚÿëÿÂúçé®õÿg0\úø(PÒu¦>>}òÛâÿ?y‰{`Ô†dñÀ´„¦x¶Îªô6è8h€ª冶uHóŽ)e~ѽw |õâ>SÞµÇÜ ¤(WÐW1I Oë˜ÊOä’IÆ¡ÃO²©ÃñêÚyå.jðh›€dÊICë…íb;³ ì9ŸH&½÷EŒçºzèå7´ïÛ6émGûjïÿÞÿŒãƘ›¸chçÿÑQ;ÿWÿWov®tŽ4^ý¿ëÿ®ÿkÿ­ý·öÿÚÿÏ>V}ëf}!q}+}Å?‰rù6¾þ/f®×ÿã ®ÿ·þÿ3nþµ9üÿ¼Ä BPEÙ47YZ•ú>b'O°ÀÒ†´þªHQ´¼¼wß¾ /:€¨ÊÏíÒ'q|.‘oÀžÙµEŽðéÓS1ÅD¾È3¼û¾(²¹-@')C‘ y>|w)çÒÔÝXðËõðøÕõB{4&?^µ†G_/OZ‚:æÐ7xTnym£GSú*éè”i?NBÚæZP§s¥S‡þô‘ -÷i8PÞúgØ>š|©O?aïÿ{ÿ¯qºó?:dçÿÞª÷ªÓèŒÕÿÏëÆêÿ]ÿÍ ‹í®ÿkÿ­ýwü¶êÚÿÇÆ^ûý?>îúLJeS²'…Î9‰o|üÓõÿõ¾Xÿÿ<‘¦/žþd^â®cœ<ÀšQ²þÏêâÉo8ƒêÐH+´¥±eäH™êýQ úhæÐ·|Ë2üNGétv•¨eØÐAÓ|åË/Sã̤Ù!t€£yà¦uˆN… /2hðüõEÄH׎2cåzœÎÉQPII|J''œ6ÎÎ+_FœëÒÈK}×}¨¬Ò•iŒ^ž¯4zá¾¾<²ÝðLßü ±–“o'Yxææž¡ÕçËU¯zνù¸ÞðS×E£Œô½ÿTÔwúgïÿÌÍŒîÓg;;ÿwþ³úõÿ³6Y‹æ¨¾ØõÿyÝ·¶è—]ÿÏø ?ºžÄôËŸ³Þ¬ý·ößÚÿkÿ¯>Üúëÿ­ÿÿ[çÿ?ýè¯ÿü-£Gèbï8SÀ‚¢Ë( Z J¤1>ÚAÄ'•/ eDÔ¨òŽ*yêñµ7`–šk˜¦Ðu=‰)GùãÔâ•ãYðoÊ——·pó;»·"Ÿü y¬nxhO®/Çyyã~“ÖX~Ó¾8MÛ_¥•^'DZϵ ß~n}ÒÛÿÒ á#ïý‡ÃÀ˜4F½6Þyé[í»ËŠGîgÀ÷òL¥ ñüiýIÇcø¡"Û\«[[öþŸ±¡/öþÏhÙù¿óÿÒ9ÑK«ÿ£ªóWÿïúß±`~ìúì(}Ñ`ŽŒqqlµÿÖþ‹mµöÿÚÿëÿÑ“ëÿñ:g½˜ÿwŸ9¾êµnt YÿÿwÛÿÏ;°®1ÜxG€Ž902q ½‰äÈ/Y—‘Ñ_4&;à^G«"׌8(ÕºZw⋇¼èûëkÎG´pÉ@"'ù<+M.ç7ôØ\äVïÎË?40s—‰iõ닟~P£ ¤íì’\{¿:]K—fgVò§.ux_–r퇴_m_r¡UŸÝjo^¿I3µß¯Îò^½>/ÒÇÇû¸î}‘ó¡‘>SZZÚå<×ãLàš?IÍÞÿÇäÞÿ ט4žcʱóç¿_1é–Õÿ«ÿ3²”œuÌúãØõìƒKgîú¿ößÚkÿÓ‹ÆAÖÎký\ûÿ²%®5¤¾™X¨ÍùØ¢ñs’3.»tý?æz:cý¿õÿ§ýÿ§Ì#„U 3ê³c‡²àœF¹^ŠÃN9@ *(èÇÁòÍ幦 »C½—›‹¿Å#uÎT;ÀÊí|’žÓ¤Ï§ùr å?è Á›ƒ'û*<>©ã#€h®½ÓFím¿r©còÒ¦‰ÒÎËðLþE£ÝhTÞ£¥-hñÒN×}Ñ gßMŸ1\Æ|À-ýv¼Ô©|ƒsu> `¥øk‹òí?},¼Ÿ|h³ôW³³ ­~NÛ‡Où’«ýž{:×ò’?±´Ô3² ÓgÂÞÿk7áÞÿÿ™«;ÿ£¨0ý1ºcõÿê«WÖ2kÉ®ÿÇFØõ?6ÅÚkÿÕ.­ýjÝXûÿÒ™kÿ?ÆÛÂX©o"Žo6öwˆ®u&? ^ èùKŽ–_ÿï€|ñï¦SÖÿ;¾.³uýÿç'©~[ýÿ¼ÄÝÄbxæìœ»Î¯€«K™Xx ¦ÜÚ(|¢dÎ.–€>Wž|×@‘/çѹyîØ„z”:¡ò ¾j8Ùhå“ë‘7tsÅÎ(é¥Áϵ ,]—|4Æ¡@åðGFr‰[ºæáõÿ²woK›ìÆy ù¯î^I—3aËÜS²ì¹Ž Ù")Ëš3LDø`nÐsÚk×Ý‹œ|^ÔûýÕmʲ¬M2Ñ]?ª€D"™ï‡ªúîÓ”БK~øOž2¥g´½{;àÓðm;õ!^Ù6± .‡ Føt¡'è{ÈÛþh}h¼8_ðEÅÖéÚ¹C8µ>÷§´æõÜ5\^íoÝêsTn´Ú„ûÞÿ½ÿÆfÇGÇFçÏÎÿÿ«ÿWÿïú?»ÃGO ]Gïúÿþcúˆ£ºöß±Qkƒ­ý÷ìè 6óÚÿkÿÓlO¾Kôé¥cãߌI>šõÿâóé+!ý“³sîzý¿ƒ3è#ã&>øôÑúÿÿ{øÿy„Сøëhv hܰ¼ø{òg¹xo_c= 3è˧i¹ñ“n×À' ͼL< ¦ôSø^N½Ê9ºÍJc@UIe´ÍCi¼ãI==B3|Èa'Sʪãâ§Þ€RCãý°Ê‡vÒ#Óðuí½8¼§^e€|bmfp  ß|ó &y–™z/ùêÁ§A9÷& ˜¼ÉÀ7¼¦.ôÚÚvW&4ÒÐUn<ñÎõÄ÷Ϩª£<ÄÂÞÿ½ÿG^ü?ÿvþ?;VôQçÚÎÿ£W¢4nº¨zLlëÿêÿÕÿæÊ®ÿ»þ³)Ù.ct»c”Gí英_ÄŽµÿÖþ[û~_ûÿ¡#Ø^އ_6z„®¨‰³þßúëÿÿnûÿ¾Bx …ge`òûgÑeA8²£!ÄØ9$  @t)“”» å¢,ÞœFkAÀ ô[À;;væå;WóðŸkÎ_wqÉÇCBiz^>òC7 _œ†)ã:÷%妟§}‡~ïÿÞÿÊœ1²óßÜØù¿úõÿ®ÿÖÈ]ÿ×þ«m%^ûoíã`íÿ&Ånÿ¢ºrý¿ãêaý¿³‰cýÿ3Öÿÿûã?O?œ¯¤ †X”%@£îP’—cÒBò= ÉsK¤ o%x]eñM@3§ÄïÆIôn(J¯ôè\]ǃápžEchÈ'ÐFQ„ÿõþ¦9ç„JoýAd/™”ÁSÞCé^´©€(ÁyéÚe*4<ú’Ó+­ Qå-}ù¹Î–ª)ëq? Uƒ>̰áUÅgÛ¢zf]ýPÞÒðóÞ«ÊÓz¾;Ûïõ[ñ{Ÿ*ÏÞÿ½ÿ3;ÿ®0wÌ?¡ó(:äÒ;ÿWÿWvî¬þßõ×ÿµÿÖþ;º¯—kÿŸ''¬µ'Öþ÷ú–õÿؘëÿ­ÿ¿þÿû›rþG🧟üÕŸ½~óöMÀ—°S²Œ1@•tˆ4&*D^*Ðb•O²Î#zI›2 +/L¢ðR¯¼Ì}x«O Ü£Ôç<4À–IâëÅèón§a†¯ &[ïj¨¹ÆPÀ-‹†§LˇÉиV¯8å†Þ9^'ex’C?DÞ9'cå«7/* Pöü«„zÒwSF{Ò&â\ò¸Ê–N'Ûb?Â{£ÔûêT¿²½'ÊP$Óð‘×4ô¾ZXÙÞÍ)K`˜þHúÞÿ½ÿ¾ ÆæÎÿÿôÕêÿÕÿ»þŸ„<¾³ëÿÚkÿ­ý¿öÿúÖ‚õÿPÍ×äs®ÿ¿þÿ &ÁŠQð#¤ü£á??ù÷öZ @’î®*Ø"­ïAâ̸6qXÝýÄé-`Âù=¹×€Z ~w 04Θ\À—÷”a¸F! M¥,^CŒåäÕì.¢8A“¯œº€.Òßή¡ìHRÑ%“G¥ÝëWVàj€KoâtNZê;¦NÀ¥‘õÀ?“ñA OÛ$ ^Àóbví³Ï> OçÒ^}òI*‹l#»¶àÔ.µÒÇ/{mPþ!ˆ/¹õ=²íð’§»ÏÜG Õ‹ LÃGý•ÛW ·Ÿ÷þŸqº÷ç&Úvþ¯þ¯¾74ªGéÔÕÿ»þ»þ_JslÎscí¿µÿb{Fq2ß×þ_ûÿüxo,¬ÿwôæú㑯ÿŸÁß|l ñúÿÿ}üçéû?ÿÉë·oޱвt墥ÍIΣx/ p$¯ÎÝÙ>x(@€ò‚8Ï¿ðœQú«ÙýóÈæ¨c^êÌ œóûuiäô1ÞçMƒkÀNÀ¦D•¯üÅä(XA4åã½7~.™\kŠ2dè¡ô@éÕ«Wá±Kedœ}úé§ÓÚsÂø´®È€çì2#/ÙÓ?Ú7å ÿu+¯Þî–“/…—¾Æoæ^*‹oâ«OÈ&Pš€´½ÿ{ÿ;Žvþïü_ýô+¹ú×Ëç®ÿÇÖbk°UÖþ[û¯öhlYãbôeί˜þt½öÿùÑšÓ±öÿúÆ@æÉÌõÿÖÿ_ÿÿÿyúãóÃ׋Ǩá×DÁîŒðòiú’ð€D3Ñ ç16¨à€’wRMìï.x@#¸uÞÁüä1yZ¡´u¡Å{N’ï?TÚ2@Žre1çw>å•›O9eÔ›Ãù<hw–`ÇWÂÔsj:‹~d~÷í‘»ÊIzøu¥)œ>Àˆ U’®KÛG t½Häº;©Mä~å©c»ó*/3Wftʨ/e=¢8²ztO= .>äoüÂðÈ/MÃçÛ³ô©úèRV™€H§Bç÷¶}Øv=ÑÇ:ñ‘—xÒÊWÈ©mþh”€Ë^ ¸…Ÿ¼;H‡¦fîý?­îýßù¿óõÿêÿ]ÿwý_û=V›ní¿yÅÚÿ±û×þ§dscý¿õÿÖÿ_ÿŸ>øÇÆž¾÷?~]à¤Fúh¡ ÓXèñrW)÷âããÜU\Ûå]LÀ |xO:žÎý‚,*¿ÉD 9—ÞGø9îeñtm!Eù»·Ï»Â hÈèð…¿ Ç =¿&©OÈn¬[=Ÿ|¥q³TÀ§&J×N7©òöËŠ•˜tì 0‰Éí]U˜<]u“¥ï¼r®î>¢¨\i'#@ÔÓƒWKÓ½?ú$`ÜÐé;AÚÛiW寻édÁN_I¿:­}¾÷ïÿÎÿóhòÎÿÕÿ«ÿwýï:šµvÖuÎì®ÿkÿ±·Øikÿ±#×þ7îÇÚÿÇw«O'¦C×ÿ;~Úúëÿ÷Bëÿ{¢ºBП³ëO_)ºc(†×`&O€Y{€@¯¿þú£?üÃ?LzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç;^áãZ ;þ^zæGe"×Ðàçü‹/¿HßÛ½Õ—°K÷H¢à‡¾++hkP×ô–“ƒ|¥“&Hï½Þû¿÷çÿÎ:¢:¡ú’R[ý¿úß²ëÿå„ïúûxËž`wÄö`‹Ì5;gí¿µÿŒµÿ½½öÿûÖÿ[ÿÏ:Ñ`–Љ×ÿ_ÿÆBÃÿyúñ¿û—¯}zŒÀÈ€DŒA©1Ð^ÌcgbЇ! 1àúÒgeÑŠ Cyof×’œÛRšÁy U0o†Ÿ_,•Ã#]PFººßõýO³óËçVX@‹Ä9ÏÒOÙëŸ6wZ?~‡ì„®z¥§Þ©³ *ã׀ʣ-Êø«ÉsŸáçjêž»þ#Òíú²; ÏôÓ¼ _ý÷æ›óeAÀ[x Ь2£IçW}ÒÈo›4Áû¬´g˜…_輇kúÍ/ƒÂÞÿóN±½ÿ3Nf×;ÿÎØù¿úõÿ®ÿY(çÏ®ÿkÿ­ý·öÿÚÿëÿ­ÿ·þÿúÿç£p…à{¼áŸÿyúñ_ýÙë$€Ž>zÆ`ËsÝ€-€Çü+ø"¯Â~ùå—lº³Iç7`ÊÄ ¾‚c^ÄÀŽü”ü' ¦xuЀ1Ùb:à•òäíN²¥ž ìAçQ?À—ó4eåÕÝw([ð¨ý°gèÅ•³yê>pÒ²¦CÂ+ÌG–{P·öOìZ?ã©_µ/is]g‰,-Ó:||r~—ïN#/Ç0Ð>íGû#N£l¹ÄÚ9rµž½ÿçÞïýßù¿óõÿ{úxõÖ”]ÿwýgݬý·öRXûíÿøüœñiÖÿ[ÿÏx ø–âõÿ×ÿÿÁ~ú×ÿúµÁå]LvJupõ9dï´*HÔ*ô°Yœ”-ÀåQ³CŠp} ½ó¼khƒ7@ú \ÁÇn$y¶¦«K9qÀ˜)[P§eíuÊ è/Z¼Kè(M»Å”ÅÛ'ô’¡õ¢qž6\ò¨³ë]†ðŸ<¼ôÉ"BÊæÁ¡²K¾óòn-2JÓf‡ ‡j Vöé„ôƒ|²i#°¯í’.´ x ëc…v~ Ò„È?õjcûaïÿYlõÇÞÿw¯÷ÐíüÖAæNæÕÎÿèØÕÿ«ÿ­%Ywf-ÜõŸ†x?ìú}zì }!¬ý7?¶®ý÷žýI¬ý¿öÿúëÿ­ÿÿ öÑ‹ãt<|wþÇúÿçÄ´åÓ÷ö“לÔ¡¨±s7¢GÁ‘"¦5ôÞ}{^J.¿üÿëý¯€ð0É ’)S0«ËƒHgò-€Òäñ·á˘ :9 5é÷¦†'™S×€HP½‚d-ç}^­¿FkÛ§ÜôFäN<…äÝûi0BôQLü´É?ÿüóÐ}ñÅ^Ú‘5…Ð~*‡tíTŸ(Du5Ÿ|~ÝQš]XBΧ úå÷þŸw‘#{ÿÃj|'ÆGÇóÎÿÿtˆP]t‘‡¾siõÿtÔêÿè]ÿŸ,ÛõÿØlŒ˜µÿÖþcƒ[WÖþ_ûŸSÿëaO¬ÿ—ùÁîZÿoýÿßwÿÿ釿ø“לSϦ›¥Q0DšÅÂÒ ƒæîÌÊwGß.`ÏòQ®×Òtº2Ÿ|òIb/RwþÃG(OçÊzo“ ]ðhK§à†Ï¡=3ø ax÷õ¥îQ†# (@ÅÕv»¡Rïì8WžíŽ˜ôóøÈÆ&áñ|´ò[6´êŸ´†;M¿®ˆ¿s@ÔÛqø¼ +ÿ¦\Ú4|ýWþoß½}€\¸çån¡šû3q_Ê·~8²íN{®ðßû?;÷þgôtÞf\ìüßù?:hõÿùq`õÿÙ½lMqÖç»þŸµºës휮Ùé¬ù³ëÿÚ#kÿ}'v¹þXûíÿûì]_âÿ¬ÿ—å£k‰ù²þß`ëÿg\ü¾úÿOß›—¸› 5ª ˆRÕ„iüt·‘4å,>ÊÔéõl7z@φŒ¹Ûh}ùÎ3ñèÔ{WXx÷ùpy(¿VœÐ)ã¸Ó¥¾K^r+‡>í»Ú˜ER]O‚‘Ñ£’dÿõõõµÈ éRxyÑœr‡ß€"³öL‚kG”îðó(£ LöuÓ£´§Ló•ï‹Ü¥¹Î Æ/Љ,‚ö&Oý C›pÕw_ÂîÀ½~¼¤7͵_ÇÞÿ½ÿZoF;ÄžÇÝÎÿÿô=b,¬þ¿5[ý¿ëÿ¨Ë®í÷µ–u½ëÿÚcl=Æ=ºößÚÿÕÆÃÚÿëÿuÓÁúëÿÓ ëÿÏ¥_¬ø˜ uD2YÆÈЏþk 2‰ÐÁqé9zçƒãæºþ¸PVVãͯ·÷`·”mÄâȃ÷”SGe»~5;¹ð\;·£Hý$;±ú"õÔ9rô(ùŒ „Y}lOY²õ@ø’šìPgÎSÇÕžpýiÉîp-V¿óÊ‹ouõ¥ÀêQšÖ¥ŠîÈB/4/Cpz5WWÒIQ߇G©È/´®ö­ôÈ52Oá‡Ü{ÿ÷þ/OÎcÑxé¹ñä|çÿÎZÈxXý¿ú×ÿ]ÿ­°ößÚ3²{3ƒâú³öÿÚÿëÿ­ÿ·þÿÙ@dÉ\ÿÿ7à?ß¿^âΨàp 50€>yú¤_yC[§D™3@(Xpf¡ƒòCÏXIy·!wã2b.pÇ«<÷®ÜU˜‚O”ÇWÙ:ËsñÑÛ¸”ÍãˆÀ¨á÷âåùò`3pJPÛåúñ¸ÝˆUùå´òŒŽ‘u=ùäQøe‡æª'<†®}©|ë~äqôoüµ[Ð^áQvxyo߼ͮuË÷°ö½2‘vx6–&T8WÏ÷–LBc²µ^çÂãþ9ßûŸñ³÷ÆÆ5ÎŒŽAç;ÿÏüºÏ%ýâèÜOÞÎÿŒ!:¦;ZWÿ¯þßõ×?<®ýwý¨¸ößÚÿkÿ38*ëÿÍSMëÿ­ÿ¿þÿÙ,Á}¼Äýît}1Ž×]ý¿ëÿ®ÿkÿ­ý·öíx1»¹öúÚÿëÿulÔ·ríQ@qóŽ}þÆïš1”¼õÿŽ:ý¡_Öÿ_ÿÿCüçé'ÿþ_½6u Òíy¶ó8×dËäBsí2)¥u"»À5¡Ë€»»›ôî8zÐÏ‚Eø<^Ž;¼ b ‘_ð(²M%ýá‹ 8#wÞ™5×èTP ½²m—k`žvmˆÊ¿t➯ΠxæX]”´#²L{ɉ‡C¾ÃyÛ:$—Ðçü–׺ÅÀ²/àZèôÑß¼µ&±²Èl¡ôæUž–Eòayu”~ïÿô÷ÞÿÿtÌÎÿè«Äêÿ£{«'Wÿ[õgݱVMÜ5ÇG®¥ïúý0ýq_Ówý?ý±ößÚìÒÚÞ~Ä^ûíc¢:ÒyÖÜõÿâãéý·Y^Öÿ[ÿŸÛšP[Ì…ñҸ玟ß6ÿÿéûów´XtÁÐHeáâ —ILzi¥9×p('Ò)߯ؔ§D£,°Én/Áµ‹^ìýPbõ(+==5úÌ9(ﳚk àW_}õž±ˆ¯r;·úˆbo&'/ùM#9m-ß¶‘7}«}.´É1õäqˆ«¾¶uX‡¯wrá‘ô©³£MÚ#\´i×ðQVˆ,øN{É_™äáW¹µa’ëiñ#/h•I>ŽGùÉ DWH[‡Vzi¥9ÇgïÿÞÿÿ;ÿé„êHºaõÿŒ º}õÿcMÉÚ7}b|ìúØ]ÿ×þ«­U]±ößÚÿtäÚÿëÿÑ ëÿ­ÿ_Xÿÿà?O?úË?}mb¸°` ¶9Œ— €‹‚J~UõžÎ´‹ `úy'…‹ÖQ¾÷X: Åñí¼3ëÕËókˇžäýK ø ™w[õ‘ÁðãT³ñ{çó˜àË/³+‹ŒXî<=J˜ 03¼K‘mú ØŽ©S?عEy¾ H†³¸ Õvâ“v /çœ+_º‚YòÑ—§¸´b_â9's}ÞsåË·tmó>zÉ=+­þWF¨<Ê{ÿ€Ýû¿ófÎÎÿ¨„èœÕÿ«ÿ­/»þ?¯Õ³xfmßõìŵÿ¢,Í‘µÿžíáÚ—µk×þ‡cÂÚÿëÿÕ[ÿoýú¦P=ilÄŸ_ÿ?ï6ç‹çj<ý³?ÿÁkŽzƒŽkç3 º ˜#v´“-JOç«D(ÂØ‹Ðu«¸ë€?C§\ò§n¼¤–Ôïð~«ÒÊoÝät¦ ¬‚:ÎÑ>@¸¡—æP§òÊ’åR`Lý“'ØY$(Sè,?I» ôã=Nz:X[æÐ;¼òuÄ¡mÞ\;¼´Ñ]hŸÉO?mû¡íŧýƒ^ÿü€\é»\$“—üá!àƒ‡½wi¥ý©9$|åÐãwdŸxú£}Vù÷þðoïÿ¤wþÏ|Þ úÈvÅu\•ä í‡\OQmæì{ùûˉåË“¦êѯÒ#§ú& ©,ÒË_^{9ÈT9uMy—üIÌ=©Oø/ðòÊ8œ7¸Öνÿg!r/öþÏûvþg^˜'ŸæMç¡9¹óÿúÒëèÕÿ«ÿ­=+æM×(«tG瘞Ýõ×ÿµÿžmæµÿÖþ¯¾öÿúÖÑõÿÖÿ¯ßñûæÿç?ü§ÿøëî€Ê\¸œ0ç J;|òbôIïVÞ‚!htX_˜þÙgŸ}ôõ×_çë~â£èœ˜³ößÚkÿ?Áö[zíÿg_ÂZYß䬛ëÿÕçZÿïø¸ãx®ÿ?zÃ<áŸÃUÖÿ?¸Æß„ÿdV³é8åWÏ9y2®H>(G4ô•§e É‹Å'¾7Ãú=€}E_žâÊàÜw¨»;•ì¢RþK ¾È'/mW.Ö0Η çZù(‰)#¨]š€s‡ºå“; Ñ€FÓ„žÛáúðœ÷cM{"ç|QìZÀë‹/¾z!@Ò¤'žkôúì›i Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï¢ÿÿô½Ÿÿä5à# ÔØ´XÊ4\Z,€*×38bT Òвyy”x,6Òî 0Ç;u÷²Î{]Þuv p@&†,^‰/‡\ #4úîÈ 3}9¨¼=››`Ç“EŒø1œ½—JÐÎZ¥GÂWyò¡¯œáy¥§àü‘†—_ç½´Ý5™C;ù¯^ èöæ¼Kß4È×ñÝý%ÝàÓ¾°Ç*ôox }ú[|Z™¼ÓJìŒgÚìú·/¦G‹_v¡Íã•ùg€«/öþïýßù¿óÿhÐÕÿg.й«ÿwýßõÿ<ƒÍpÙæÇÚkÿ­ý¿öôÀè†õÿÖÿ3Öÿ_ÿ¿öÂ?$þóôýŸýäu‹#y÷Óœ3H1œyÐÑ÷9è´C DŠØñÕW_…ÐiNh:‚_@ z×wòæQ=!õOZ<»%×/û¯òØÛ¯Ž,s­²xìïåËWtP&ïŸÙð¡DÃgâcdÇ!SÿðW§E7ñУL“&Qž´ôÉÄÚ]:4M?®Õ‡vdÔ'IÇcNî/Y?ÛãæU“áqE¡¼ÉîßÃ: ¤I#ó¤ô²è¤uQùMFxá×´Ê›„ù“²C'ÈÛû¿÷çÿÎÿÕÿ«ÿwýßõí¿±‰Öþ;?ô®ýŸ±ð°•Ùökÿ¯ÿWßiý¿õÿ­ëÿ?ð¸lBþò÷Äæ+„òšÒj`(1z`ŠLz*žs€A.ÎÀ ȼ²£©×a6ôøPÁˆ2;“Ä€dæúy7–4¹êP¶`OÞiu/+õOÁ¼Ø˜“G \óØ_ÊMùòrµó¼³OÅÑ©‹Ìú€œ'ù½>qýñ‹yéûü+žÚ‚rxvg™Ý^B¯ÑÕø Ø]…tòKF–é#y‘Äû½öÌW]k»€îWC¯:eñ#Kòð]§îɯ¬hIØë½ÿ{ÿã§GÆÖ5GœÏ`Ùù¿ó?:…òXý¿úß:bíÚõ×ÿµÿží½µÿb\ƾd;°3c›®ý}¹öÿúæ…9±þßúÿëÿ?cBÿ£øO¬:«¾pb‘)Qð'`ϤË:‰ðR–órÀ«oçEã~¥eĈ31<”-€äeìö ”rgiÊ*§Y ®+«ëÒ#y£ ìÒÒxå Då—ã Ðy9#ŸÐJx0ÄÅy¯ÖÒ‘y*JñÔ[€}h&½‹tÀ©K~}ê_eïKÑÕ…/` ß\_<¼°ÝN,ýîOtUtø´½é×Ó6’Kšü<÷zÉZp.;ÍÔ‡^çØû¿÷ÿ_ÆÅÎÿ€ÏäØù?ã‚îVÿ¯þÏ8°Î\sc×ÿ]ÿ×þ; ÍÚkÿÓ‹Ç'YûßZ¡/Öÿÿìú(Úúëÿó+Öÿ?Äù±çàü'£3 däzþ™( ŠÝO}”//]JºÀŽ—¦¿úäU¥Uà@KÀ•9ÿøé<‚‡šs^žÊr—\ âž'áú¨!£x*Lª²ÝÅ•„a1¥ïÏ’O>å€U¯É§¬÷N‘É»±Ð4BþC'ß9¹Ú.i®#“ôÙ †·üæõ—†Ž÷uÝôMÛ'ÖjÀ`¾Ô?iå¡wð-ð¥Lû+uÍ5Úü½žÄ\OÚ#”æ–¶÷ï¿q¼óçÿêÿó# }¹úv\]땾Øõ×ÿÌ‹µÿöÙÚkÿ³±×þ¿vÖ¤/Öÿ«Æ7[ÿïì^×9.”M‘cý%ü7þjR'}ÊF×òm§œûŒ_~Ñ8YÿÿwÓÿúÑ_þék€0¤»‘: ëÃX‡F d `2×”`Ey|;@3°¦®Æòî´ãMÜû›ò•wù;r€ Ô¿H}®åùUÐÉ‹©Èá]T«{À‹Ì婽ÝePãœhÈ,˜8m›kôÀ&uÜe/ϦSZSQú'üÒçqH4ùõnb¼ä»ãùk»Ö¦-&¦ é¿2Bò“~€ÇäϵÇ5ÕŒld¼êp½÷￱¼ó?Ú$únçÿѱôËêÿ£_WÿŸùaÍØõ×ã`í¿c­ý·öÿÚÿDZN®ÿ7X|¶³f®ÿw6{ð5ùÄõ9õ‘Ð8×µ´¦7–¯|ýêôîЭÿm`™þ±ñä÷Åÿ€u¦˜¡1i#óøZ*Ù-•GÙ&¿ƒÏ» <·ëÚ."!`ÉÅ }˜~õ®“ðTê LáùÓA*~Ð^™Ís©\ŽÈvÀéq¶€=Û»¿› „ÊšO?ûô£/¿üòñ«1:“©Î ŽN4éÊ{¬o$Ì×þðz7ÀÝ£Ž)?=®ÉR_Î'+õã©ÌÓÇg±Gãš²Tã¨O¾ºu©/&æú’GèQÒ‡Qº•칞|õ º»²&¾Òä…ÞÉöþïýßù¿óõÿ1´Vÿïú¿ëÿùxmÁ®Xûoí¿µÿŸ;û²åÙ×'æÊÚÿó:”ñY¬£|ôÏúÇïºÆÌú™2glÌ©1ò+'ë‘wŸ[›Xÿÿ÷Ùÿúgþƒ× ƒòþ¡1ÛÁ¥?Í£~À“)vyß’G(%¿Àp:Ñcè ¾F&gó£¼fâÞöÔ™‘ÚÒ¬÷s× @apøÌiw x¦”Lá?éyÜñ’àcKï矋üøÇ@ší&wÃé‡d½þdV¿´uèÕ7Ì2µOÉÒ~yðäßë`…ÇI×)Ù 6tdTOÁªÐñQ®ý”þ¼*’ŽWÊ^÷H–¾³Û†üxUÖðØûŸþØû¿óÿšF2vþ¯þ§OWÿïú¿ëÿÚtAm°µÿÖþc<öxmêµÿ×ÿ[ÿïàõQ×ÿ_ÿ6á^Ìa¼­Á(Œ‘Žþ×ý¼þ˜¸øÏÓ÷ö“ט8Rx€•ëþOÓ!}xÑ¢kÛ?•ÓäÀOû…îsN~å•hh¤›a5,/ô•µmF l˜ §‘ƒ,=Nâ%ûÞÿ½ÿ;ÿwþßtØêÿÕÿÖ’]ÿÏzmÝõí¿µÿÖþN\ûý¿õÿþ-¿týÿƒÔßæ»¯ÿ6ëücà?O?üÅŸ¼`ríºjgKs.0bmƒîDœˆgòÖÉAï±BŸ [öÑ«W¯N¹¡ÁçC~[†}êž²âÖÆÅ”+@óÈ›ù’’)W¤ù…¡|¥šµPÊ/¾ø" –ºZ”ÈÛ¶‹Õgrö½ÍØÔú&¦É«<ä÷5ÃN#TÀ¤‰Qá9ý9'y©|'¾²úYh=m‘ë÷ú1TÏÆ5žBË_Ùé“{9|ôåÙ]W®Ép§G·÷ïÿÎÿóÞ?sıóõÿc½™ñ°ú×ÿ®ŸY‹gLìú¿ößÚØ­cOžù±öÿÚÿÇ÷ãoÔ'‰_âbô'¦þt×C²þ_úGÿeNM§¬ÿgdœÍ ëÿLäîϳQ„̳9—÷Ûêÿ?}ï/~ü:@Ï Ì(Тa}וƺöN)çvVµ# ØfL"ù÷£fAOþ¥šÐ¸&‡ØWíø²#,uà£ð'í0 8ä%òû5òêqc¾™ÝV¯^¾zLì—/Ï.1|ü¢*¸©ß¹ÝYøsž0qåïtSTG®‡P¬Ü»·g÷YÚxñÀ7²µ¿ô£x•kC£ñDcgØ£þICSúðÐgC§ŒºÄÒÕEÑ÷<×W]èº+KzÛ…¯ëðšsÁùÞÿéˆ[?íýßù¿óõ?]¹úÿ¬Y‹fÍØõ×ÿó§¶O批2‡ÀÎXûïììÔµçÖþ[ûŸÉæ^ûý?kêúëÿgѽàÇÑõÿ†R[bÏžþä¯ÿõk  (å…ígò `u5FÐL¡\OÏìPFùo„!]œ›¦LÓ(}‡SÓÅøe‹~8yû(²á-ÐÊõ‘A×M÷E@ –6”ÝR#D£=n~_‚Žow\Éo•ý·ïÎn*¢hP­€^všá|Ò.4øHKù9·ë ˜EÖôé´QYõX¬€ Ât@IDAT‚<Ÿž“KH¹öÁfÚ `S^x÷@ï<ýì\¤ âö›ó€gÃïÿ{öþïüïœÙù ý`~Ð_´ =â|õÿêcC0>Ì›¬AsÞ´®­?“¾ëÿ®ÿ,”Ž 1}²öß±×þ[ûŸî\ûý?>o|¶õÿÖÿ_ÿÿacšOßÿùO_S” ˆ*®?ùä“€-ˆØ žÎ{;ÌðCT¾C(˜³u^\,ýL9¶mR8CŒ^Fðà¹ÞÇÃàL–ñ¡óÖW¹ÊúRfÈH€é­# ´UYíð+àMyá­¼¶E?ÜëS—t|r;“<ï iùÄ€v&’HûÕì0 à5uõ=a®cüe^@ëä—gúÀ«Ãû|˜*ãhÈõu‘¾ø 4²S×Õ¯{ÿ”œûÒ¾Þû¿óçÿ™ÕÑ?«ÿWÿ[×­a×Úä\Øõÿì†~¬Ù»þ¯ýwÍ1¶2GÌ•µÿØóéŽü©m¾öÿÚÿl.ú³ïcŽÿbî\~ Ÿ¥ëMí’ÇH’7Gʬÿ—nI_ÌY|Býx ëÿ­ÿßññÛêÿ?ýøßýËׄ·xx$Bà¨PéyW® þ– Ýìx¢t »„ÐØ •÷b]“'I%s|àÏð{€9ŒãÙݤ¾CW]z÷teòø #aèüûÎ<âêN(Fµ6Tûúë¯ch·=ââQž#š42©ß!x Ñ#ï¾=;ªš/O; >¹–Wáyµ¡m¦d{íÔùÜŸx•GN.~äðëä‹Ù ÜÒn;ÏÒŸ”‘ÖöáQžw~=Ç·÷qïÿ,žÓ1½w{ÿwþïü_ýOW®þ? •µÞúfM麱ëÿ®ÿì¼µÿžm·Úkÿ­ý_}ÉæmÎ^g£¯ýŸÍúgý¿³žÖWÓ' Î×ÿ;½A¯ê‹Ž™õÿŸ7¯tÌDÇL?5tLõºt®õeí¸ßFÿÿéGù§¯Û0 ic¥®5°iU24S¨ùÞÅxÉn¦‹šn9W6åçBÇõPgwglºLY“u¾¨ Z±|±g‚‹Ìw K/%­ àJz¸i‡a¯€PŸ~òiºÊøk~1Í{´†§:§lh&Æ_ýÍÓ7ÒºíýÍÛ7§îƒbxµýrà†ÿT’zúb÷{hñ—æ~ä1Æémê¶R¼Ãchs>1úð¾Î'J¸§9/ïæ“¯4{ÿ÷þ?æñŒaçÿÎ:fõÿÑ «ÿ}°ëÿ|™x®ÿ³›}í¿÷‚Y;×þcç®ý¿öÿúY(ØÓ—oßm®×ÿ[ÿß:Áÿ¦'êË×G_ÿÿ7ã?OßÿÙO^F<¨ó „8éÂËPt¢ SMò*M‡£Ññò88oû¨ÛÐ$\‘óÞ(´‚Gý^|ü"“˜ 4äŠ ®çOò’¥%Ýú8eä ê/oíªldõ«‡£2YY慠ìÚ6i5ÄÊ  Jºó~eQyGœ{ØÈPÞdécÊäþbô§Ì€Z—Üm‹ÝchaNÕ«~ŠÎ î] SÛØÏ€•´Ö~hnýÖ<±¶‘aïÿÞÿÿ;ÿéz…N è Çêÿ£SWÿïú¿ëÿÚôäÚÇ®\ûíþO}¬øPëÿ=ü·õÿÖÿÏÿ^ÿÿG[ùûà?ß^¯¼¤|Êí%ç:^Zo@+t-äzN«¼º ôòê“WáSø4à/ˆ•E”á85ýÅ|)ðÓO?Í.­!˜ÿhª v š<;¶äW‘âQ°­/v'`HyåÔ­í®ÑÞ!çÒäµ¾¶Y¹{Ç_PwéÛ<ÚxRfyFûê‹ö[ûè”?»Ïb(“yÚ÷ÝiŸþQ÷±X˜¼ãä;> MÇß¹r­sïÿÞãeçÿ3 ¼óõÿêÿ]ÿ»žÓÖKÁú)]¶ëÿÚÆÂÚcŸ_¯ Yûÿø1kÿ_ÃÜp4ÔG¯ÿwüëgý±þŸq±þÿy¥cýÿ¿ÿyúñ_ýÙë±ÊòŽ øb2ÙùT.ñõ^ªrÍSVšA§Üéðç_ï)-iÌ? [èæZÀƒó¢õ*8ù©cHÈ‚FšCV€HÙ‡³ig^“—Gù·ïæ+…“ÿêz1=>h”0¡éµÝLq^&O#±÷dåú#Až:ãã^UHäë¯T´!L?´ʵþ¶Õ— «À”º¦(yóh¤w|Í?mR¾r8¿d)F&@ŸÊ¥kOò‡'™¼ãE=äÚû?ý¿÷?cÐ8̱óçÿ¥'雎 ºƒ¡wVÿŸµgõÿ®ÿ»þû‚® X|kÿ­ý—ubƃ` YûíÿõÿÎzi>˜ëÿ~˜ÿ|Ñö‰~ê7;_ÿýÿ§ÿãÿúÞk_ôî(‚ã>GÞ±”C3©c`Ž` Y†n΋Af;Ú>e˜/Ýý”8eº3 ­ ¨b˜¶ló+dsH‹œ—3¥z±Á.?çC[³© 2¤>œ§òóˆ^ ­«=•O¾t× /§OS—ÇùžÎã}®Fªæ]d»v¥þ‘ó,ß3§¯zAæ„«h…¶«×“Í#—ø']™«úm8Œ×{»Ðk?™»Ø´gïÿÞÿÿçeåæŽ9´ó¾$kÇè¥SéŽÕÿ«ÿ­]?výßõŸ­H_ÒâµÿÖþ3èkÇÚÿ㛬ý¿þßõz™ùýÌqA3  ‰CþÃJãmdÈùÅ´pû+õMY;Ú¼¿*ý<´díµíº2¥~2̦‡º[–\ò•'š–»ß«òÀòÊ|;±2“¾÷ÿôkŸø’åÞ;ývþïü_ý¿úÿ¬”»þŸGwý;jí¿ØŠkÿ­ýƒzþĦ¿lsiìIkÇÚÿǧYÿoüëü±õÿÎ?ëÿÓ'Äÿ!®ï/^ÿÿüHö!þ“—¸?õetT@މœÛ™Q¥¬‹ul®gŠó'½¯£{òÈÚ-ÐSÁµ\êº&¯B@•ÉÌ¢4sÞW“Ýawº7óÈ_ÞÛ4çU¡ ÈN+çÞ‡•ó)(ëׇÍ#dp ð%ÿ«/¿|nËPàAN4iߤ‰¥·æ"×úG¨Àº{9í€WÒÛVñlBÓ¾K_I^Mÿý¢ÎÊÓºZﻑE@+´üO;켺2S~iÇÞÿtËÞÿó…ÿ;ÿWÿŸµ­úvõÿ®ÿ»þû¥|í¿µÿÖþ_ûÖÇñS¾HýõÿNŸèaý¿³^Äלqžâ§NñÑëß6F¡÷ëÿ¯ÿ?Êå¿Áž~ð‹?y /@TqhEüêêº;¡ (ÊJº'¯@Š ›Á9£½GÔ䕯sTñKÙ)# Q^\~Œ„Ès•^õ½UÐ8Ê3~òSÖΨ ê¶û*r_ü“æ*ó«ÙÖéÓ×xzaü_~ñѧŸ|zÊ^ò˜D”`çRy’¯¡îÑöf\1¼Ë/1ê¢Üµ)»Ãn´x†ïÈ{zÄÄ=Û,ñZ¯Ø=ûú›¯³¥?×ÚØ6‹ˆŽåáZß«Ÿ½ÿ{ÿwþïü§Çè‘èÛÑ«ÿÏÄÕÿ»þ[3wý¿Ôé vÃÚFÅqÂØVkÿ\×þ?ã¢×þ_ÿoý¿cWZ7Öÿ_ÿÿ ÿyúé_ÿ«×^¢g`ÅaÇ%ï{âÀŒt$xtAëŸrN ö$oòñ@¹¶¸·çY æ:ÏÀË” ÐsÕ#ý‹/¾˜/¼Œ_õÕûõ½ú¦²¼ß ?å[·XÐé݉„/Z‡PÐ/È/îÚ&@ZíK=³ L´”Ñf‡Ðv÷\ä¼÷gˆ®?§ßuýé;<¼Òg/FÖÜšù3|ÚF4•òBÞ/vµ#òHžf½|õrÜû¿÷çÿÎÿÑutát"±úõÿ,"Ysvý·’žW XWwý_ûoí¿µÿ×þ¿Þ:ºÑ=úñþßúõ•ëŸõƒë§²»ãÓ^ñúÿµ»×ÿÿÛðŸ§ñoüÚ@  3€G—d®)£ó庴 ó(š—óA@ Ë“z€’)W°FÜó‚/)s-M£«Òc Jëµú|F’3åq–?ú£?JüfÎ_½z•ôòm}S›;¢¦—ïùSÚ¢­‚ÉöË_þ2±RPÂòRG•³óNDqûCyuá'N™qý* §_ÀR:yýò£t|Û7øÇ™¼úª|ÉGΖW¬B S¯ö:É«lbà•ò{ÿ÷þo;ÿwþÓ=«ÿWÿïú¿ëÿÚÇ–ŒÍ5öÒÝî“¶ößÚÿkÿ¯ÿG¬ÿ·þ|êõÿƒ1è‹àãW æH¾¦PŒÃ:êhZ¯ÿ6üçéGówÄCò‹Ò@&cƒ¼ÒøÂžÇó¼äZZÞ!¡#tŸ_ïƒWé•i=ýbŸ|€ŒçÊ‘ È£>õ¶>tyAù¤Õ£“Žo:n +Ÿ0yÀ:¾xùâ£W/_å­r9†¯ .åÛÆ‚GºÝ" iÚîŸ]VÊ ú«rDÖÉKÿ ½úPÙã0<Ê…Ã%ǽøzß•4ÎfÚxMyÚÒ:ÚGhŽ1J‡&m›4<œïýßûßy¹óç?="Ð Õ«ÿWÿïúlœ]ÿ×þ‹n¹ößÚÿkÿ¯ÿÇNZÿoýÿõÿÿiðŸ§Î;°€+¶Ã[Œb `€B1KwÄÁ5IYC7ò¾–U]•9Þw@ èòñPòíþ1á9ËùÅÒÔ© ¨²LR¶£Š²M¹Òµ.<*+ÚìÐ:ïœ:PÒÃì蚊𣽗¼äa”þ—ÿò_>zõÉ'6Û Ðjx’‰Ìú,νX^何®¶É«¬•­O§¢KÿÎuø __:óyLõÊ´\Ûyæ\Ðæ–/ †¯:ÈÔ>éç¬íÆR¿ÔuÝ·÷êž{ÿÏxÜû¿óçÿêÿÕÿ»þ[/»þ¯ý·ößÚÿ|“ØÐcS¯ý¿þßúëÿ¯ÿÿ¿ÿ™GôÚâ øä܃›CaìW€H:¦ïpBS>蜎ºÃÊ( R&ýE›]Oð#¨caP‡@&A9²äübJßE^dšm•‹¸ Nå“ÀL›'ß,`Py}öùg1ZÉáÀÝÛ­-ŒZ@¹ß¾;_l<õ=?¾7¥žÈwš‘º*£|­4‘-»¤†¿óOHËû«†"|'Í—eøI#ZàK±€hÊ\<õ5ZmëFß~Ùûúï†IƉ1f|4ÜçÁ ¢ÿ;ÿ34Œ‘ê ÎWÿ¾92iõÿŒ‡]ÿÇfÚõ?ký°ößù”~XûoíÿÚêkÿ¯ÿÇW[ÿoýÿõÿÿûøO,‡ á°ܸœ“(!>Áu‡q~½¼ÜóŠþ=ò‡_»{ ø8)øÂˆ±åòí›óN+ôv#yÌ ­ƒ±ƒg ^ðÂáÈàâ¢=§§œ²‚²xô<'WzÚ=/2¯a‰®ï…úæÍ7²•ƒ¼‚r@+í çÑFéÙ¡6ûÔÿë‘õѧڴӇν÷Jè;ª¤i§ÅLÈî5tSðàQï¤éWuKoŸë<¤‹Óî‰Ã÷ŠÃãÛ÷e—¶÷ÿ8Þ{ÿgܓ׼Ë@œ±#tœ‰gPI˜ñz¯ÿÑ;ÿ~3^è•Õÿךºú?ëݱëÿ±vý_ûž\ûoíÿÀ˜lôµÿ×ÿ[ÿïá³ÖYÿýÿ¬•7üçéOÿïÿó5pããùª]ß„HZ€‰Ñ9ª5Iqb'  E¹¤â„Éë¹/Ý)ðáÐWìZÊ4ã-ãe :>~:J{7@K¼éaªv²xÔNp9‡®ÁµzÅ‘yœj<…ÐN,ß!Ÿ,ïÞž]_vVI³“Iè£Ê®¤Ë¯œÝñ„¶<É›ó)i¤ÔfåJ×òóë5ùv¡}nÍy Rý@ª¯¿þ:u—WÛ£ž>ˆŸ|ôéˉɃ6òLìH£L@7ü÷þç=iúnïÿó\1fwþïü7/Vÿ¯þ>˜±àŸ5e×ÿóãÕ®ÿg7¸~H¸ì çkÿ­ýgýXûÿø kÿ¯ÿg ¬ÿ÷EüÏ1%bKt^¬ÿ–Pá$ëÿŸþøMøÏÓOÿú_¿¶¸ä0ˆâ¬Œ"twôÆ«ÿChäøÊ,¨"î9Ú*CÏà €2 Kõ¥ž!ÌÍëÛ‚ì&Èu”é¿óN—¬$FçÀ32•œZN~ƒzÛ ÐdדvU. ¯@ò‹)y„Ô#¾ÚZùÚÆÖ«öž+çÜ¡ü›·oKoÀ‡¬Up}DP,½÷Dù´ ê«7ß̋蔶IwPnòïu*°¢(Ò†KeÔ¶|[WúòpïÿÞÿÿ;ÿGQ¬þ¸úÿ¬¯–‡®âžïú¿ë?;¢ïãdsø1mí¿µÿè öfì̵ÿuGlpºsíÿõÿø¿ëÿ­ÿOG®ÿ68Ým˧ïÿì'¯‚GòNäê,,Œ áQh+ÇåèxÿQ£‡Ñzñ(Ê;Q€@hÜ ‹Ð›óâãy„q¾Ð€ ½/ùMýΕ  5u“‰¬_¦|dkL¾ ê펪»L= s£µ…{Eò„êãQƒ\};`™ðÉ#„“F.F:yBã…ìSÿ‘ozô áÝÀ Ó—èœ+ãHýÃW»õžêgð…öâ­LäYÈ#0%¸§§s¡ÊÉÐ)6r º½ÿÓï{ÿwþϼ0÷vþÓ G/Óá Gè¬ê)—=/] \š·úÿü(°ú×ÿÎ]ÿ×þ£K×þ;ÎÙÚÿkÿ¯ÿ·þßúÿgÓÎúÿ;þóô½Ÿÿô5ƒ*J-«‰ï†¶¶ȸ1‡Š/“wß<ïfŠssñBÄyQöq õÕW_¸ ³€.èðòh`ÁùÂU[Îñ!'|•ôGþ儆ï-=üx\by猔óN¯ðº´C»¯ó€`#Œò=´Ñášlbõâ›ë‘ëÅÈ*]¹¿üâËì“Fù ©søàí»ÅÐRF'_ å,XR?³«¨²œÊúK&éêl["㤉C7í ¡±“I½vWÙs¿óuÂýáþáGÿù?ÿçþèþ(rvr¨/õxù<çe²›…üÒ3±ª›(ˆ£„+_ß%Ö¶¼9ðh;Sç}yyý´Ñ.1»ÌÄò‚6Ù¦Êá}vc¥½.&¨W»¤Ù•E>¡åW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿ;þóôƒÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúÙgŸÍËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þàþ ; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi¾3 RånýÀ<ùßÉD¢Ô+ xÕÇ Ý3åÞ `¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ¿ ÿyúá/þä5pÁcÍDŒ ç„€Ϫ›€Ê´¬X:±’®=r7Ò}çQÀÌ'(çhÝÙñƒ×ìf*°¤žl±zü…{ýÊVçêw-Dþkq}¯òO¾©ƒ§z•I]—ÒQ¾e𬬠מ£ï»¼Ði¿kùåÛÇô©/â£ô šÖ©ß´ßc;Û6i„Woéb z¬GžþÊn°« m‡:*û=–ŽlÜûÆYûmïÿaõÃÎÿÿwý[bl¬þ??­þßõ×ÿµÿÖþ[ûíÿõÿØH±™ÆäS¬ÿWóá‹Ö÷\ÿÿ`ëÿÿá?Oßû‹¿6±L*Á¹ÇÊ€4UÀIœ›ˆŒ/^ÎK8,éà‡ äJ?²D1€ÉõœÚ” O1`ÿ'Ê •C Œkí«O^åÚyDŸ„KQ´m'±YÏíÂ#ïÙ¤ èËÓ9ÇìÞFyú@º@T€ÑË/ïôÊn+|'¤_®~s§Cúôfâœt¡€Ÿ¶´ÏÕ§ý½+WdR~@«ád ç§Ÿ~p«Û¸ñÆCž{ÜëÖ+oïÿÞÿÿÏ;è¯+•YÝähÛõPNŒ·yL0ò͵B þ‰¥ã jòÕÓ´ÖwÊÜ€±)ƒFß Q¾2JïËç_¾:àšúê—':òJ—_ùìýßû ½{cgçÿÙ}©/vþ¯þ¯¾^ý¿ëÿ®ÿÇžÒÂÚkÿ­ý¿öÿúëÿñ+ï6’'‡Öÿ_ÿîðwÅžþøßþè5ÆŽ Ï[Ü`t˜Äæ¤Zæ?](P”ô¤ H~Aæ•–ƒÇ˜‘€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶§ax„žøKw´^éM ³áL¤^Aœ4és¨çÊx´÷$<—ÁÿCPI_I×o¯²óI;È ðú8`•— ‘cª”öxi™¦Ò:ÁGž¡™—ºµ}ÒÈ›—¯‡àôŸ:µ ;×ÚN´ê· »ÜÞ¼}“ûHööº½ÿÓs®‘põîÞÿöGæÉ Pã]0v…¤çìôU硸y¥Ýù?¸ó?úÕÿޝþßõß|˜qPk1Úõí¿µÿÎGŒØßlÛµÿÏ“(]?×þ_ÿoý¿ç§¦êך|:~ߺ~±8iÒç@“0qý“ð\Æš¼þÿÿžþ_v`¹an¬›ÌàTX(ê„Ö¨êÍwÝóã§yÁ{”Æøpdñî|Oú<®3ÿÔ/0äìøxó͛ȃF=­ ȺI/ï\\@›ðú:f˧àüAƒ‹¯fÕ±DÓà\½åW™¥WÎÒz—•D*½>êcXåk§šöŸÅ'm¸ímä8²¤®¹Ö•S]•§“S9ýÒ´òLãóX`dŸw‹½7É1›¼½ÿ§3®þØûͳ³‚1bÜul9oZãÿGÿìü?¿(7Õm«ÿWÿw<ˆÍ‘]ÿÏz#ô¨õzþè¢ckÌõ®ÿkÿ­ýwìµÿ×þ§}½z3׳žÔÿ¢C×ÿ;ïWÖžŠ²¶x·ôúgþ¬ÿoÖœ±ñ[èÿ ùü¨…pv½J\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´o¾þ& ™ÇÜ>¯ú…ÛüùüóÏ3áÂ?´èA]Çø5)Ÿk@R+T þwÀ¨r$Æ'Ç´ÿ¢;×ÏmRoÔm' ªï”¢ ìhô‹€OËj¯~ ˜w9ühäÛuFÞ*”¤¡Ap èòn«I;=}2•k;#û$‹œ·^òZøýª+½2·ï”Ùûß1qî_ï¡xïÿUÆòÎÿÿÆAtΥ댎Õÿ«ÿwýßõ?6ÇY.w¯ýw~ðÑkÿ­ý¿öÿø*óý¿ó$ÑúëÿÏüY8×ÿÔ®qúnüçóB‡_Ç=º°ÉNž!.¸¡Sã°L¡<Þ§_‡ 0E^‡¦×unîŽNéìÒøÎ¼ * üÚ!á†YÎ/,g±Ï#s×ÐxBÕ|C‘¯òMÆKãKS2(𸎇ŒÊ\^Ðú[[ÈQzçèÔ). £LŽo`‡kŽ>éxÈóKªs4úÚî-1šð¾ñQö!땯®öÅŠ,-[9”éQ¹Ô™¾þò”!{½ÿ¾ÖúK9œëǽÿ;ÿ3GgL;ÿWÿ¯þßõŸ.è:kmÝõÿØjÖεÿÖþ«ežkÿ¯ý¿þßúëÿ¯ÿÃc䀌¯ýwÁò,ÆFv3 ¿šm†ÒÆ£8ñuÞ-FÙõ4”2uô™±Cº[ç ï/dSbþg'Öä#<ú€-'Ž™|“ú¼Û È%ä¾¹æ^ÀIgL9²8È È\kƒ+±P:u$›Ì{{þ }:}èj¬Š92büô•óö޽ƣý6Ä¡ýÄ®³›<Îñà W¦|…aèC7qA4² Òµµ×íëÈ“û9÷áªM Kü]“iïÿÞciçÿó3õ;ÿˆ»úõ¿uÂz²ëÿ]¬¹lñ®ÿkÿkÿ^_ÐæGCmÒs=Vñü_ûÿÛÖþ_ÿÏ|Ìçëÿ¿öèŠ¨Šø¯Õ!ëÿƒŽŒ™ßGÿÿéû?ûÉk…æF|]L÷Ô`5™tÚ“°ÒGì<¾'xƶƒ, ן‚6x¦³çk„ùºðIeg={¯,p%õ]äíÑ¿ÊZžÚpÒsLbï•kåÀ˽ñaê˜k»éÐ i»2sìý?îÞÿã°vL7/w îüßùo\ø'¬þ_ýŸµèZW2(æÏ®ÿÇžÚõí¿µÿÆ~Xû?6ÔÚÿëÿ­ÿ7Âúÿñ××ÿ?X»±Xs¡xƹ:Ÿ¾7–N{d^ F;²éq\ë°øÆYq>´þ͉¿¹ˆ8áÔ\|)iç&ª2xö:ü/^D*ø$? ÊÅ7õ#¸B¯÷ÝÜ(²àkTwgá'Hoývo ­s®Ã*kë÷¢uù»ëeíá;|ÐãE†:pÚ/<®/° Þ¥wcvbAú=´]½‰•__ vd%¾®s1Ð9ú¨bù´Íè8y®vèä£Ô?×@¬Ö×ôðqŸæ_Úæ|èöþïý7&JãaçÿÎÿè¦KÑÕ©«ÿWÿÓ]‹j¸SY_F‡ìúo…¾õÇØú¦ë1]›ü]ÿO?\ý±ö_º#ãdí¿µÿ×þ_ÿ¯¾#ÍÐ5×ùúXÿÿ·ßÿúþ/~úÚ Žɸœ£Æ¤¸Fhâ¦ÎÙ…y޹ô¥•åQ¾^{Þ]ˆ†÷œ›X5^k˜qrCÕ“ï`¬É'~ÎÎåÛs×=+€jº4GùÝu¥þyT°NYœ ÷>(/<„>:  ïᥠٱ5õ+‹÷=´=zC^e­lâ†tõuº9ëc¡rH{ÿ˜>+“‰ïy(×d&«àzþ<îgÓîm'oÂÞÿG¿ïýwÆÊÎÿÿ«ÿWÿg}±öíú¿ëÿ ±SØ(s¾öß±gõÆÚÇŽŽý½öæIlñciW‹m>áØìÇÞZûÿô ½rﯞ§¯fýYÿï $ýÑcý¿ƒ#¬ÿÿÛïÿ?ýàç?}}Œ 2x”º+„ClÑò4%é,DxÅ‘½4á?4åU`È¢uÏS.»Mì—ØÇ ãU|…òßæ‹$<‘ï’cˆõ£QVý¬ÈQÐɹôLt2Íèén.J1@ÕM€—~Qo¼u(/$eò*ò®²ú3mŸ˜ uË·eRÇÅÇ{ºsmW÷wi ¶¹nþÁ¦öþwìîýž_ÆÈc¬œ3 'mçÿé§ÿ«ÿWÿ[wý§+wý?ú }1c⾆X[…µÿžmRóƱöß±·×þ_ûý¿õÿ²PÜþÔßÉúÿÓ7¿/þÿ“¯Z8Ýõ]$÷AÑó‚%¹€(+ØÜUéñ.?‹’òu¼/% À p3G¯•W¶€ÂpÏyy‰ååÅãÃTÙ€ä™Ð|ÿÅ0¸í¦R®|ZFùÊÚü8¥Ãë|5å<µ{úÍU>è4uDøGÎÉWJ½ŽôÅÄòð)?q¸O^A²{ÊÐ_ùê»ó•W~ʕӚo‹±@–ä ã½ÿg¬îý?ã;äƒ?kIž±3ƒ'vçÿó»åvþ?º¥ºvõÿê#c×ÿ]ÿ­±kÿ­ýg8ØÕ±­¯kö…µC^lÖ¹vÞµDìzíÿµÿ9@ÆN}9c§ãcý¿kþ°Ó'd.ÍùúÇFí˜1~j«VÏ<|ûÙEnÈ%_yåòº÷a5Ëž~öþïý€})câ>†îçÉ›?h\ÏõÎÿ£×:wwþ>šqA÷ÐyÕ{Õ“«ÿ©íÑ«ÿkVÇÈ®ÿG»îúÿ>ÀSÝÚØZ´ößÚÆ}::U`³Ð'kÿ¿?‡Öþ_ÿ/¾èúÑëÿÿvûÿóÜgt”þüÏÀ¾€é u`Å=äY0 Lò_Ÿ„a‘w, 0 ÜÒÇáê¼¼øøÅ@o“?ŒCÓ…?òÜãÊ9Õ=ÿ¾«—Ž<§ ³óiÒ[tFqy“Åî(é¹~I %ÍKîý¼mÛÜz*Z­õØeƒ4õ†Ï€avoe+¬çû'OݧÌUÿ…ê–'>÷zNo^ܯú0ÁëZ^zúàŠõQiÕ-4?òL¿ïý‘±±÷À¨ÿ;ÿÿÝR=x×5«ÿWÿÏ‚’ue×ÿ³.ïú€¥µÿÖþcc®ý??²¯ý¿þßÌ…õÿŽÌ`Xÿtãúÿ/üçé{ñã×@œÀNiw§Å9Ú»ƒ= ¤˹>€zÀ•­vÎC5€R€”Oðcô‰å9ä)c‡ïÖ_hÕ9ô4zÁB©œC?Ê·¿ðÞóì¸R.Ÿ1]<ò*Úsíëy*»êk½¯^½:üHC$Sïy[7™œ·œz݃\O¹s2íÈ#šsu剕ëÆCøþß´÷ª³/GA29ð7ìý·“pïÇCÇiãŽùwæÍÎÿ£oô‹¾Úù¿ú?ëÉêÿ]ÿg}Ýõí¿µÿÖþã vSí©µÿ×ÿ3j7òëÖÿ[ÿ?ã¡~ùŒõÿ3þóô/ÀÒYy”!ލ_ÏÎc}Üï>=?ÞÆ —Vå«Üwçúí€<}Jƒ6ïšÇ$ð”kâ>b˜]Rè¯O¡udwÔ¸ÇJå6ò x9¯¼&¾t×êF«Lƒ:Ò¦+MYùåáüé»×W‡Öµ2BËŠÑ;í³‹ìž¦9^ ð%]€!^Bù¡o_Kwí{ùâe•”l P«aïÿ_{ÿwþgÎ]óι ¦;Ä÷¹¾óõÿêÿ]ÿï:a×ÿµÿÖþ[ûíÿõÿÖÿ›yýÿõÿÿ‘ðŸ¼ÄSöx îf l|;À°ãã9<.ÒT€+†š4ŽÝhšküä‰ß¾9r]7Y,òÊNF¯æ‰•w@õµ4>5ïçhÁJè䓵r´î– ÿç«<òzMºk‡kéÆÔÔ³#L}üôqÚF¢Ô[ÚiÇ7_\€¬—/_DÐÊFúfê©|+whn²ÛMÿL™÷Ú04ʶÝbí §?ÿÚ¦:å{ÿ÷þgxO·°óçÿêÿÕÿ»þŸƨÆ]ÿǾ[û/«äÚkÿ¯ý¿þ?jý¿Ûf’ñ;ùšëÿcýÿ)`W€EüCà?OßÿùO_Ô¸(ë©ìþÞª€W3094h fÝ…rî=:àJã)Ê`A+½Až Ìr£•£ÑÊ:J›ó§×â‚7ν@½ihKW>Ÿ;òs>ˆñÇó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõaÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿÞ·kõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ»ýÿè†Ô¤ÝózŽ NìK%*tN1ù½ûÊ;°*߇u ó‘€—²Ž&À_ø\më#~òßÌn(¼ñý8‰ù›ô{ßßùP‘«õy|ÒýkŒCëo_µ*gëOÛF&Ò(ïzïÿÞãÊßÇ ´ÿGÇìü_ý¿ú×km×Õ®Ç~øéúKgîú¿öŸqb|¬ý÷ëóä…™ô²5b—®ýŸ~ÑwÛËØ©~™Œäõºvc ªÖþþZŸ:ôÍú×Ü›qµþßúÿ¿þÿÓÿ۽΢1“šRì該¤üjLºóLþk·QŒ´)cð3Кúa…‡sÊB9Dñµ" <çò[gÎçZœGø¦Z¼¤ âÖ'&DåœÌÐhÍÇPVeÞò"ÛÈòîí¼(~èVɦž m—üʪlep¡ÁWÊ“²‹?:NN¾–èÑÄy$³¼•©<•ýô^‹[gË@$6÷=dÓ] å™þ™qû|GøMù¹H¹½ÿ{ÿ;ÖŒ™û82VòUMãiÆvße×y"?ô;ÿÓ;ÿWÿ¯þßõ×ÿµÿìÞ^ûoíÿµÿ×ÿ«O\_®6¶ë{Z¯ÅµÉ›¿þßÁ#âß®ÿÿ{éÿ?}ïg?y µè¤èy'Žk¡ù™h3™€ÎM¢N¬Cɱ§wþ™¤A·Æ™ ¿\\TxLPVïÜcnyç¾³à{7“E?ÀÐEw£R&ò„M@†Œ mOÛ!]Y 6|ûí¼»jè=©œwUù5#4síß= …àKO]2#Ç¡SOÿ¶ múfÊòÓx¥/•Ÿð¡ŒI¼ý‘_špšòJ¶’[xño¿´>ùåÓ¸i÷:š&V¶íŒÌîÓuÈöþŸ~Ýû¿ó¿ó:zdçÿQþ^º®zоq¾úÿY'ë¦öó†»n^ýÏF°ÖŸÞ¡s»ÎYÇÚg¡½3'wýOoÜûå7õUówý?ƒG?¬ý·öÿÚÿkÿ¯ÿwÆ@×ÚõÿÖÿ£ÿ)ðŸ§Ì;° ¼FŒ1€@'ai C/(ç$<LM`ÔÄt1´x¸–Bû¸¾òiÊ_õÔ`¦†’s<<ÊG†Ô;<> M/Mdš6Î=¶Í5Ye„ÖûíQ àÐ_íü„f5ÿ¾ëEòïeäák§Õ» ü’¯\údòÒÀ7Aº_aõ#Ã{.í½ôCzÈ&?Û„ÑhÇ\W&ez®o«,IO;Î/`^Â:•<ú$e§­{ÿÏxßû?ƒgÆÇÎÿÿtÈêÿÕÿ ¬··õ3ë‹ ëѵžd Ûõ×ÿ'ÆGÆÃ56ŒŸ¤ÍYûoí?ª£6kÏÅÂÚÿ§bÈ_§ÓYkÿ·/&^ÿoý?vÇúÿ7¨.ý}ñÿŸ~ø‹?ymÀ€žÆà $&#OIÔðpÍ™A/­Æ‰4†‰`0É·›É¹àMø\å,'´ËªeËðô(‹n®å©¯uµî{ÙÖ%~¤_ò+ŸcòÔ­|l›”” ˆ šëÖU9ä ÂÓµA,OP' HèK¢ÏÕù‹'â[ßé-wYÂç®úÕÄ)œöÉ«“ÑA ÆÛD!êÜ;´NL¡«îôÑU_ÛEf2x9ô©ÝVúµõ¯òØâUWËwr’¡üÅdV¾¹žÌÑ4t•_Ø™| í¼«më@“ .'{ÿý·÷çÿÎÿÑÁ—Žï| ßœ¯þ?à ]JV¯þßõ×ÿµÿ˜Skÿ=ÿk-uTO²¡×þ??Ä[OÛ/µÍ×þ_ÿÏXèaŒ¬ÿÇõ^ÿߺ’ñ0vçúÿÿyúÑ_þék‹nA Å. óûB“¼¡—g’ÉwØé¬q¸V^'£“&_šÀ9R¶u—ùŠ!ˆv%ZO®/á3>Ÿ'·rÒR~Ø9òÕYß @'½4«Ç£•y¿×Ù·?‘SÛ¯þ#‹CgÈs¤ÏGž.€·â©[Ÿ¤Ü-ƒ\äy”>½Ÿí´;uòí?lД]åˆ,{ÿÓÓúdïÿÎÿÿ«ÿWÿïú¿ëÿÚkÿ­ýÏ8\ûŸ7·þé¼ßyý?ãaý½ðøü‡õÿ§¦[Š3¤O`WøÕ`Kš_‘z'$\©`ß·„™¼$Ècï\RnrS89y„®ï  u’S…Þúîñ£øÔ`…Ðdk]©ò(?lÙÈFæ+<®É¥£ 3`Œàzþœzæø€¶4Îû˜¡´¯¿þ: £„"úä“OP+HDViBë Ðs`YÌ®¾ªlhÝ-øu¾Ôx€ªäüŸŠ¼‚k€Òè¯Ô“54êl;ÊmÒ§DÞ/0u¥ý)µ÷_7ìý¿ÆŽÎ˜ñ1$ÇÎÿón»ÿ«ÿéîÕÿGOPtDÖá]ÿ³~­¬Ç»þÓ>¯PXûïØ—kÿñN`w®ý?ö•ÿì¬+¬ýχ¼Âô Ÿ%6(_E²µ&Ñúëÿñ_×ÿ7_ªWϹ|¸kþT¿ü.úÿO?˜w`ÝAŒG̉Ž:µä Wb´žŽÊDšë_ Ý!žAv袜)ëK ¹.ö¡ Š Ò³]î*SY¤©ObA^ó•Ký“Þ›{\¯Ã³2yŒÑc‚}WLjQcC< P½zõê=+@”v\ò ó˜ h…ÈrÑÄù™|t ݹ!¼h§ÂG[žò}^%N.¼Ñ§=úáªÇµ6´o’?io§}^Zÿa^ë‡vbý·÷ïç”±!ìü±wþWï7^ý¿úÿ¬¸Y»6Yæ<ºdÎQìú¿ëÿÚçGÎ,¬ó‡íņ3Okÿ­ýoH¼ÿãõÚÿëÿQëÿ­ÿÖ‹øì¿‡þÿÇY$lÑ]4-¦€ïÌy|ÅÑI“N¸fy pÌДKªŒNèæôPžGìúKKòåá3´áwód%¤Ý¿ay½s^ÞçôÔp «3™›þÈçÐ&†²ö]€”ÀUë´@üz |g@Ÿ–WÆ×‡ƒÓ€?vc}þùç±P® xá™Gì¦>ÀH~¶Œ£4òg´Êh«]/‘oú[Ðm  71°M›tΦ·×0tKãüW#¯ëÜß)s—1ýsñÛûŸnÝû?cиÈ8œñ"ìüßù¿úÿëü±úÿù‡¢QY·h‰£)výßõÿÝc§MƇ±a™±²ößÚkÿ³¨žƒ¹±öÿóšr÷IFq<Ö•èé¶õÿÖÿ3{Œáî§°A¤¯ÿúæwÑÿúÞ¼Ä= ‹›ÿÝcvÖaÍ€0ä]±4áN“kTé§ÓYwš‚%s º‡¢Îê/MËMóÿy‘ú7÷òw:pï1^º6 ç'5uºâ(gg  °T>/¤2òï¢ûæ›o>úô³Ï·eµZ…Ï€S}Ä<}Ý1 ÕÔñrvfyá}œþ©#ÂF:|2à¦Î2Léùéé‰ á1Ÿ/wÝCZƒ¾#CîóÚiÛÞÿ½ÿÆÈÎÿÿÆQR½ßX¾p§É5mUó¬oJSݾú~´XýÿX›Œ«æ®ÿ»þWGT·Œ‚™ÿkÿ±/Öþ[û”çÚÿ—SûÂü¨¿só†t0Êœp~Äw]ný?ô¾mW»¯ñé»÷iRfí¿õÿÿØÿOßÿÙO^›ô&rˆ~%¯iŒ 4À¡ôUÊhÎõósîÊ{Ù1FŽâ@+½|º4 ÷?SŸ9^¨,ê—×=B*½Ø5°Æ‹ŒÔµGæëWaòñÓ¼h}Ê(›ºÕFFôBû諯¾úèÓO?Í5ú‚^Ç(iú =0«õà‡¾uˆm¹ò&3 ¤·¾Sþô%Ð) Ú´‹lò”¯i[ê˜kq  É¯ œK_œ*:å'n]íü¤•fïÿÞ3ãí7W3FvþÐ{çÿêsD /WÿŸõÃZ"èžÓ»þïú#£ãögÆÆÚkÿulÔ¥3„ÆÕ%÷´µÿ3uÖþ¿ÖšõÿÖÿ[ÿÖ’ßAÿÿñ, ]AÑ.÷Å¡†gVÆyòg=9 œã3¥Éâs'å%M~¯[FYx&þðYy¡Ÿrh¢†â¡Lc<òòÅÃI|\x£ÒÏú÷x±¨vxôÀ&õ “ïH½·>@GÆòžÐ’ Äôñ€_ÒìÀúdvdyq»GõAeS®Ùß};<LRÎ5 NüÓ–2£½Ë0Vô¤¡S¶ùè7ÍyÛ).=á]§Ü$ªqïÿ(¿½ÿgììüÏ\Ùù=^»ú?ºrõÿùq§ëë®ÿ»þ×¾Zûoí?‹æÚÿkÿ¯ÿ·þ_|ÚñG}‰Ö9›A¼þÿúÿl¾U1‰bWüçéGÿî_¾zx߀;ß¾;ïoò«ªI‚|;ŠºS Hcz™yÓcpŒRjÜØùÃøÇ§<ÑÈ/PÕFˆß]/:· éÝÛù‚Gjò幟/œÏã~W¹ÈrÑé¨ÒOÒ³¬sÞNìsÝ´îò Ð3ò¢Éã‚@#“qÀ*ýA¾¯¯ÝWú…|ʦNN°K ßö‰4ü>”«u5=׈§~mËsîEô í±C91:uª;ý§À°ñ‚úôøíýßû¿óß|Ùù?<Ï¿ÕÿG‡Ûå[¼úÿ×Yïvýßõí¿µÿÖþ_ûŸ/²þßúlçøÜ—Êfª¯»þÿúÿÿøÏÓÿ›¾¦€x·=}LQ>ä'»2í3å¤+ œB‡þþàë³È9‹7cN¹7ß¼ åÚN2¸V7q+ ^G¦ypÚ€^;;€ïåÑ ÊÅäyOyK—ò“> mË£ìäáEv2íýßû¿óçÿêÿÕÿÖ–®[]Sº^îú¿ël±:NzÛfl‰µÿÖþ[ûí¾FýçÂýºkËúëÿëÿ¯ÿoÜñŸ§þç?xÍÀ088'ÂL—¤Œ±!OxûnÞñôꓜS2”Êw‡¾ ÃÕ.#ôï.@Ï-UF€XÐ8ºç9ïÚ© i¿1 ¡Ê¥…úǹôæiÐ*²Ìã CÀN‘.×K¤W*ˆëÒßAiÞk%î6B´[L‘ùâïeçݽ”]QÊÏ Ó¡äé,åÔcSML‡ªkŽæ×HUNdnŒž\õ‰Çó®‹o¸à^i×}¿÷ÿÌýŽáŽ÷ÿ;ÿé¤Õÿg=\ý¿ëÿ®ÿkÿчkÿ'1î6,ûÁ Û×þ_ûý¿ãÓ­ÿ·þ?ŒeýÿãcþSà?Ùcüz<Ä"ðD|E®9²vëØ8)§hD€ï}òµtå‰/G( ã~Îu!1¾‚²ø ɿʓώ'ùø¥ÌðH}¯æXXŸ²ë©u–§kò’?íK-§N<‹ò÷§¯È@&}äüØÓëÿL$Ä?ÿyúwÿé'o9AìQ> ÈÑ_GÞÀÒ÷3…vú¾NÍ‹yô/ à®oºÝ>á7±47ÏõýH¥×ü¿úòËE½Ñ&GË–¾@Óùšßáow•®@Mw[yi¹GóúòòÊ€lv;};»¡¾þúëÈkWTÂ4j~/ú`×XÛ8„‘­õ„þÖw€2hÔ÷ÇÈ `4y÷P©ýŒ^½q †ÐbˆF~iI¸AZûß‘Úø©3˜¤Ü¡üÕ§òðÒ{ÿ÷þ߯0puçÿÎÿÕÿÏ»Vÿ?¯ó»þŸÝË]ŸÙµvý?ïñ\ûoí¿ÚðµWksÆðœ?kÿ¿‹=¾öÿñ©Œ‹õÿÖÿ[ÿýÿ®]+Šÿ<ýô¿üû7ã°ò¼{ûnv}úÉgó( G8³}ï¦Îï ‹|Ž1Çx+o° ´Qz+—ä±GhtvKYàÐ å‰?° =Pÿ4wÞÒ?½À5ç@!/ ÍJÊ÷9dm‹¼—åÕŽ³kì^~òB€³«-Ú9ÄúöA¯?äoÛɃOë´Mîõëφtå[×y<ñ<‰UËE6}qч÷´·é~%í9‡ûûéÓéÃæõWƒ½ÿÏ_3÷þïüϹMâÎII;ÿ>]ýtë(Û£oÛy‡Ïêÿ³†u ïúÖœ]ÿ×þ[ûo~d^û?ö½õ£¶ÆÚÿëÿùq¤aý¿õÿáõßùõÎWüÿ§þéÏߘ,trØP};òw>ô§²èR°x Æ„O~®ð¡ÃM§;,R’®› Ž^ò[·s<[÷·o¿ÙÎc~øzÄÔzºš‚DswÞÈh¹á¹Ùg¡6ÁyÅœ“Ç9U,҅ƹp=ÿIŸr¨œŸãCþø–WÛ¦Àaû߀oS§U½WÒõÅwÞç%aΧ¢Sw.Irú=í™üÞƒÊH®òÜûÿáýÑ¥úgïÿÎÿÿ«ÿWÿïúoMèšÝõAܰëÿÚµ­ØckÿÍÌ.PÛsíÿ!lñ9ªKÖþ?¯(`o¯ÿ·þßúÿçqôæúÿŸFOVGÒ›ðŸg+»€Î#x~ b:_S•ìaÎ{›0ð^);¢îééðáÑ/ð è,fÒÊj:€ %¦nA9´³‚hÒ8•d³ úåRÞ‹¹¤cÔŠoAÍEøáåýR퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ_Oÿåü*™F.ô-Ós±vh·¸íRŸó{ÿµ=y'_PNP¯@v?TÒçìjëÅËáQÌÈ«þ½ÿ{ÿÇÿ;ÿGoÐ3tKu…˜NZýÖ¯êòÕÿg\X{¬ÇõÏ}ýšÅï±Z£vý?ý±ëÿ³]´öß±kÍ¡µÿ˜­kÿ ]ƒéÔµÿ×ÿ‹¿ºþßúÿ£~'ýÿŸÍ#„áhÆ9Î/$Ýã×f/c×1h(Ï£Èâ\c•!ZûtÑÈ·;„¶-›üá:÷y¼+jhKSyZ?^•§ï²Bëz™Ô/ÿêë¯>yÿî}@ð“¶”®/iÆ?mœÇ ñ–øÑ¦ò£Aë|þäÅ¥5¾•“ïëŠÊ‘õÙh¿¾~8íô‚v¡¼ 0‘­¡}¬&©Sڽ£õâç~E6ˆÕäáIǯ~5;ÛF¶Êù.¾{ÿ÷þïü·óÿèŒÑ ÂêÿÕÿ»þ»b×ÿµÿj³­ýwì%ýÀŽ\ûÿÙ_ûvO­ÿ·þߨñ‡×ÿŸ±°þ1;†aípxE\‚óñ÷ÅžþíÿøM¼ Ðã:¤õÜn$4ºÒ+ÐI;‚ 'H€—T„Ò)o@ vûXºL¬ìò“>/Tùâ<.$—êP§Ø©¼}ø–·tA§¼z_'Œ\ê™ôœ¯Ö‰6m¸:“œ¡›tu¢S(•ú. ÉÎ3r¸Ãƒ Ú,Š—,ÃäÚá4œµuêÀÛ!‰sšºÚ)ú¯2¨£ý)-_($ì„{üÊS ¹æþiCƒüÒz¾÷ïÿÎÿÿÑ“—^¨:i«ÿWÿß~ܲÆíúŸ56këôÇÙá¼ë¿þXûoí¿ØŸ£#ؘµÅÅÂÚÿµÞ×þ矬ÿwÖÖõÿÖÿ¯Ý½þÿ…ÿüø—¿xS % Í.Ÿyv5À íe ÞßRW~Õ/àÃ.(AÇÇpxH¾… moH¯» ‰MØ×óòx‡piê¦ÐÜ@4÷s `Éâèeä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/Ý/á5ç/F†Ò¢Ç¿uI!;iÚv‘ñžðÑyä¹:V]5=îS®µï _ç~N¾ûu^Ò~îÚ£u{ÿÀº÷ÿôƒ1alìüßù¿úõ¿p²V\ëè®ÿ»þÇn{†mæ1>j‰¬ý·ößÚÿkÿÓü—õÿÖÿó˜—õ¡þ~üÚÛõúÿfËß ëÿÿfüçéGów€pÇöWÁ êó•>/tçÄö¥j:S~ŸÓØ9ƒ†Ó£Lu¨«¼ï±²E˜¥7/FóÓš,¶˜dä¶ðf(¥ìœ‹å¡qô]ùCô_›µý¤²¥;×fri‹k½ãˆåúqLºÇô T0š´”›z…TÀ‘öG¿€Ø = “[tg÷Ôˆ{ñ(oùG|”•p •­IºKnu¹èz¾÷__ìýïØ1þvþïü_ý¿ú×ÿ]ÿ×þ[ûýÉf#ˆñÚÿkÿw¬ÿw~^ÿoýÿþÈ·þÿ,ÿ øÏÓÿägotòÝi ¨‘ú ¥çQ3NLß 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçx? Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;/h—78Źžó(šÉK;ÞŸGkÛgŸ}–úIÊÚÓã{ó¨£:+kÛÝ6 w޾iêOéÝ#‡r=ðr޾eõ•÷ŠÉ»ï:ÿAÐëÖ[y7×Ѓ\{ÿƒª¿¾Ûûÿ7‡;ÿwþÏ«ÿWÿïúŸeõ±öŸµs×ÿ¬›kÿÅVÓìÞÚ\FLm¸¦­ýwìS×þ_ûý¿gßþXÿïyÓGtæ(Šú´ëÿ¯ÿo,Ûyúé¼ÄÝ ‘è_CÏ=fök&¨¼ú`kðU]šsƒÍ‹Ò¥©Ãä|Ð ÖNýSÏÔÕëNdyߟX®ûu@BA(`ÎÛwoê´àz”qž¥kß­S=øÙu„FÙ)ðO•Oý“g¡˜‰ûKde%™'&›pvXA3שû’Gù ¹V·€ÎÑÐ6É ÿ¶ã¢Wõ)ý\¾õµÊ¿ûyÛ—´½ÿ{ÿ¯·óç¿¡°úÿüˆ°úÖÓ»þïú¿öß«Ø ô#ûií¿cS>l{ëÆÚÿkÿ¯ÿŸmý¿õÿëÄõÿaµ8˜Ä? ÿyúѼKçêÐ.@núKQtkÀLŒV¹‚+„ŽP¿þäóÏ?8Sþv,áá}Á9þÊ Ê•‡ëðž†̾ýæÛ\PÊãsóï*Ǩzñr¾„8h¹zpÄKg•6̬Ϯ‚k@ÅaŸô¾ßÉÚ¦¶/Àª-Swû?¼û(aòOâ£}}°ƒX»CBèó?²áÓCÝè"÷·½âÊå¼é­ßœã•JN›sêÏ„òãåpŽ—{ ^²Š›§]Ú¼÷ÆïÞÿŒ•ŽCc§sWìzçÿÙé˜ù:ý!ìü_ýo¬þßõß88¶GL€]ÿ×þ˺iítX[×þ[ûßXjçÇž˜±!î!íÿõÿŒaý¿ót×úÿ3.ýa\ ¨Né:SŸ>ùmñÿŸ¼Ä½ ° jC²x`ZBÓ¼@[gUzt4@U‚rCÛ:¤yÇ”²¿èÞ;P¾zñŸ)ïÚcnR”« è+‹È$§uLå§rÉ$ãÐá'ÙÔáxyí¼r—5x´M@2夡õÂv±YPöœOž6á‹?ÚSåérUFò¶ß.¢ÔUz1žèðBÛòm³÷‚éÏ;meî;Ã|ÆóûCãDJM¤ “Þû"ÆóÎGÝ=ôòÚ÷m›ô¶£}µ÷ïÆ‹qcÌMÜ1´óÿè¨ÿ«ÿ«7;W:G¯þßõ×ÿµÿÖþ[ûíÿg«>ˆu³¾¸¾•¾âŸÄG¹|_3×ëÿñ×ÿ[ÿÿ7„Úœ¿ þ^âNP¡ ¨¢lš›,­Ê}±“'X`i CZU¤(Z^ÞÛo߆@Tåƒgvi€“8¾@—È7`ÏìÚ"Gøt驘b"_äÞ}_ÙÜ Ž“”¡È††<ï¿;€”siên¬ øåzxüêz¡=“¯€Zã/—'-Asè<*·¼¶Ñ£)}•ttÊ´'!ms-¨Ó¹Ò©C úH–û4(oý3ìNM¾ÇƒÔ‡§€Ÿ°÷ÿŒƒ½ÿ×8Ýù²óÿoÕ{ÕitÆêÿçucõÿ®ÿæ„Åv×ÿµÿÖþ;þ[uíÿcc¯ý¿þwý¿ãò)Ù“BçÆœÄ7>þéúÿúF_¬ÿžHÓO¿?/q×1N`Í(Yÿgõñä7œAuh¤•ÚÒØ2ò¤Ìõþ(ý 4sè[¾e~§Ž#ƒt:»ˆJÔ2ì è i¾òå—©qæGÒì:Àу¼ pÓ:ħ‚BІ4xþú"b¤kG€ˆ±ò½FNçä(¨¤$>¥w@ÊNgç•/#Îui䥾ë>TVéÊ4F/ÏW½p__Ù‡nx¦ïF~ÐXËÉ·“,éíið‘÷îýá`L£^ï¼ô­öÝeÅ#÷3à{y¦Ò„xþ´þ¤ã1üP‘m®Õ­-{ÿÏØÐ{ÿg´ìüßùéœè¥ÕÿÑ Õù«ÿwýïX0?vý?v”¾h0GƸ8¶ÆÚkÿŶZûíÿõÿèÉõÿx³^Ìÿ»Ï_õZ7º†¬ÿÿ/ÛÿÏ;°®1ÜxG€Ž902q ½‰äÈ/Y—‘Ñ_4&;à^G«"׌8(ÕºZw⋇¼èûëkÎG´pÉ@"'ù<+M.ç7ôØ\äVïÎË?40s—‰iõ닟~P£ ¤íì’\{¿:]K—fgVò§.ux_–r퇴_m_r¡UŸÝj¯_½N3µß¯Îò^¾:/ÒÇÇû¸î}‘ó¡‘>SZZÚå<×ãLàš?IÍÞÿÇäÞÿ ט4žcʱóç¿_1é–Õÿ«ÿ3²”œuÌúãØõìƒKgîú¿ößÚkÿÓ‹ÆAÖÎký\ûÿ²%®5¤¾™X¨ÍùØ¢ñs’3.»tý?æz:cý¿õÿÿEûÿO?œG«@gÔgÇeÁ9r½‡< ;s€@U(PÐ!Žƒå›ËsMAw‡z/77ŠG:þꜩv€•Ûù$=§IŸ#Nóå@Ë8Ѓ7;NöUx|RÇÑ\{§ÚÛ~åRÇä¥M¥—á™ü‹F»Ñ©¼GK[Ð⥮û¢A;Ͼ›>c¸ Œù€[úí x©Sùçê|ÀJ;ð×åÛúXx7ùÐfé/ggZýœ¶Ÿò%Wû=÷t®å%bi©gdA§Ï„½ÿ×n½ÿ;ÿ3WwþG1PaúctÇêÿÕÿV¯¬eÖ’]ÿ°ëlеÿÖþ«]ZûÕº±öÿ¥3×þŒ¶…±RßDßlìï]ëL~@½Ðó—-¿þßùâßM§¬ÿw|]fëúÿÏORý¶úÿy‰»‰/ÄðÌÙ9w_ W—2±ðL¹+ ´Q2øDÉœ],}®<ù®"Ÿ¾˜Gçæ¹cêQvè„ʃþqøªád£•O®GÞÐÍE@;£¤—?ׂ²t]òÑ ‡”ÃCÉ%n=蚇×÷Ÿ¦ìÈ€Ž\òÃò”)=£íý»Ÿ†oÛ©ñÊî°‰u9ý0§ ½8ùCß{@ÞöGëCãÅù‚/*¶N×Ωõ¹?¥5¯ç®ÉàòjëVŸ£r£Õ&Ü÷þïý76;>:6:vþïü_ý¿ú×ÿÙ>zRè:ê|×ÿ{ÐGÕµÿŽZlí¿gÿ@_°™×þ_ûŸ¾`{ò]¢O/ÿfÔHòѬÿŸO_ 韜s×ëÿœA7ñÁ§ÖÿÿßÃÿÏ#„n Å_G³@ã†åÅß“?ËŃüë‰ðH˜A_>MËŸt»Ž>YhæeâQ0¥ŸÂ÷rêUÎÁÐõhžPªJ*pø m¾JãOêéšáC;™RV?õ”ï§è€U>´“™†¯kçèÅá=õ*äk3ƒXøöÛo1ɳ̄ÔsxÉW> ʹ7ÁäM¾á5u¡×Ö¶»2¡‘†®rã‰w®'¾FUå!öþïýÏ8òâÿù·óÿÙ±¢:×vþ½¥qÓEÕcb[ÿWÿ¯þ7WvýßõŸMÉv£ãØ£ïvfø b²õð®&€škü5ܲh(pÊ´|˜ kõŠSnèãõpR†'9ôCäs2V^±zó¢ÒeÏ¿J¨'}7e´'m"Î%¿«lét²-öCÐ)¼ç1J½¯Nõ+Û{¢\E2 yMCï«…•íý|¡‘²†é¤ïýßû?૱`lîüßùO_­þ_ý¿ëÿùAÈã;»þ¯ý·ößÚÿkÿ¯ÿg-XÿïÕ|M>çúÿëÿjì¡?BÊ?þóóÿúGoÔ$é-Òú$ÎŒkˆÕÝOœÞ&œß“{ 衵àwÇ“Æá‘Á>y&eRÏÄÞuÐëIwNÿ~v[œd¤“huäÅW’ £þ:ç•_<‚ä…çáugrñ—N¦özi¡Ÿsí(øä¥Äè(5ùbu:ÙѦM:/m›óäMŒ¯,ŒS·óö“4NįÐJÿO¾_-Úwò¢8¦Ì0L+üÚ¥Ý/_ È8à•~P—ò(”÷UD_GìËQ“7²ôÚÒïýßûolìüÝ7óʼp8ßùpý Ðk«ÿWÿ Æ„y²ëÿ®ÿkÿ­ýgmXûí¶d׆ú0ÒŒõÿŽ/«ÚOëÿ­ÿ¿þÿߎÿ<ýÛ?þñ@•B1q„8#uÔæ:é3±#@#àŒÉ|ù L†kÒÐPÊâ5TÁXN^Áî"Š4ùÊ© è"ÍñÝìÊŽ$]2yQÚ½~e ¸Tð&N礥±cêà\Yü3ò´M²ðèuÿüóðt.íÕëש,²ìÚ‚P ¸ÔJ¿ì]üµA=ø;† ¾äÖ÷dȶÃKžî>sT/.0 õWn_)tÞ~ÞûÆéÞÿÿ™hýÙù¿ú¿úÞШ¥SWÿïúo<ìú)ͱ=:W̵ÿÖþ‹íÅÉ|_ûíÿóã½±°þßÑ›ëÿG¾þC|ó±)ÄëÿÿñŸ§ýòçoÞ½}`ÄBÈÒi”‹”6'9â½€À‘¼:wgûàY Ê â<ÿ><ÂsFé¯f÷Ï#˜£Ž x©37pÎï×¥‘ÐÇxŸs4 ®;w˜U¾ò“£`YД÷Þø¹dr­)Ê¡‡>Ò¥W¯^E„Ç.•‘ pöÙgŸMkÏ ÿáÓº"ž³ËŒ¼dOÿhß ”3üÔ­¼z»[N¾t ^ú¿a˜{©,¾‰¯>!›@iÒöþïýï8Úù¿óõÿѯtäêÿ]ÿ-Ÿ»þ[‹­ÁVYûoí¿Ú£±e‹Ñ—9¿búÓõÚÿçGkNÇÚÿëÿ™'37Öÿ[ÿýÿ8þóôïþÓOÞXh,F †_»{0ÂË ¤éKÂÍD/œÇØ<¢v€JÞI5±s¼»àLàÖyoð“Ç@ä h…ÒZ Ô…ï9I¾_üPiË9Ê=”Åœßù”W^l>å”QoçóX ÝY‚_ SÏ©é,Fø‘ùýwGî*'éá?Ô”¦pú`#òy|oÎíˆ*›s4Ê;Êð„ÆuëmÛrϦLÞo54€ˆ†‚h”¥~ʽ›ÌNtø¥ÏF–½ÿÞ¶÷çÿÎÿÕÿ«ÿ­»þïúo¬ý·ö[qíÿµÿùëÿ­ÿg]Xÿýÿ_Fbu b3¸Åÿ üçéÇþo Ò,¹Í㸘@ƒ# 4ìT™ $Ê"6»z¤’É)5_þKÂ\§ìäQ@»¢¤Ý¼ðði¨’t]Ú>RX ëÝìD"ÐÝIh"ßð+OÛWy™¹2s SF})ëőգ{ê uñ!Ûà&€G~i>ß ˜¥OÕç@—²ÊD::¿·íã¶ë‰>Ö‰|¼„Ä“V¾@Nýãh»ðG£, XöjÀ-üäÝA:4}4sïÿyluïÿÎÿÿ«ÿWÿïú¿ëÿÚì±ÚtkÿÍk,ÖþÝ¿öÿ8%ã°˜ëÿ­ÿ·þÿúÿôÁ?7þóôÃ?ùÙ›'5ÒG =Ä(@—ó¸H¹Ÿç¨âÚ(ïbÎXàÃ{Òñtî<`QùÕhL ɹôî<ÂÏq/‹§k )zÌß¿{ÞÆàH@CF‡/üM8éù5I}BvcÝêøä+󘥺>}4QºvºI•·_V¬ÌÀ¤;`W€ILnïª*Àà骛,}ç•su÷EåJ;¢ž¼Zš~èýÑ'ã†Nß ÒÞM»*7ÞM'ËvúJúÕiíó½ÿ{ÿwþŸG“wþ¯þ_ý¿ë×Ѭµ³®sfwý_û½ÅN[û¹ö¿±p?Öþ?¾[}:1ºþßñÓÖÿ[ÿ¿¯ZÿÿØÕúƒþœXøHÑC1¼Æ3ylÌÚ´‚|óÍ7Ÿüà?HzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç{^áãZ ;þ^zæGe"×Ðàçü˯¾LßÛ½Õ—°K÷H¢à‡¾++hkP×ô–“ƒ|¥“&Hï½Þû¿÷çÿÎ:¢:¡ú’R[ý¿úß²ëÿå„ïúûxËž`wÄö`‹Ì5;gí¿µÿŒµÿ½½öÿ‡Öÿ[ÿÏ:Ñ`–Љ×ÿ_ÿÆBÃÿÿyúÙù÷o|zŒÀÈ€DŒA©1Ð^ÌcgbЇ! 1àúÒgeÑŠ Cyog×’œÛRšÁy U0o‡Ÿ_,•Ã#]PFººß÷ýO³óËçVX@‹Ä9ÏÒOÙëŸ6wZ?~‡ì„®z¥§Þ©³ *ã׀ʣ-Êø«ÉsŸáçjêž»þ#Òíú²; ÏôÓ¼ _ý÷öÛóeAÀ[x Ь2£IçW}ÒÈo›4Áû¬´g˜…_輇kúÍ/ƒÂÞÿóN±½ÿ3Nf×;ÿÎØù¿úõÿ®ÿY(çÏ®ÿkÿ­ý·öÿÚÿëÿ­ÿ·þÿúÿç£p…à{¼áþóô³¿ø£7H}ôŒÁ–çº[ùWðE^…ýꫯØtg“<ÎoÀ”‰|Ç ¼ˆ'ù)#>øO@#Lñê „c²ÅtÀ+åÉÛdK=؃Σ~€/ç0hÊÊ«»ï4P¶àQû#`ÏЋ+góÔ}à¤dM‡„W˜,÷ n!íŸØµ~ÆS¿j_ÒæºÎYZ¦u>ø øäü.ßF^Ža }ÚöFœ>FÙr‰µsäj={ÿϽßû¿óçÿêÿôñêÿ¬)»þïúϺYûoí?6¤°öÿÚÿñ7ø9ãÓ¬ÿ·þŸñ@?ð-Åëÿ¯ÿÿO‚ÿüâ/ÿãƒË»˜ì”êàêsÈÞiU¨ Tè`²87(-ZË;¢f‡áúzçy7ÖÐo€(ô¸‚ÝHòlMW—râ€1S¶ NËÚë”Ð_´x–ÐQšv‹)‹·#Nè%CëEãt9¿Ågʽ¯ ¢E†Où·>ðq¯kö–cýÿõÿÙìÌ;þóôã_þâÍŒ•çåèç‹zˆvIy¡8ÀÀb 1æX^°>'9ñ6e\Œœb´Ž1båðöòp#׎#u›ÈŒ³04• ½úúKÎëW¯ó–~åå5_¹:â^RÞ/«©#“cbiè19"›]Is#kdða>1ZCM˨ëîNÀžUßÔuš’ëÈ÷ð“§ÿ¾ùúëäyÏWÊ h˜]qÓ†ü> ©ûº@Û£ùþ#ódæQ°´ÙõÊ·Ïô¹û*Hßû¿÷ßcÄ+;ÿ3_vþ¯þ_ý¿ë?è°Îîú¿ößÚkÿ3ï­ µ½c@­ý¿þÿk|<€­p÷ÕÖÿ[ÿýÿ<þóôÓù af×ül4€8&[+ùqf'PÔØ¹Ñ£àHÓzï¿;/%—_þÿý¿ÿ÷@x˜äÉ”)˜U€åÁ¤3ùÀÀ iòøÛðeLœКôûSÓ̩k@$¨^A²–ó>¯Ö_£µíSnz#r'žBòîý€´G!ú(&~Ú䋎_|ñEè¾üòË€N/íÈšBh?•CºvªO ¢ºšO¾¿î(Í.,!çS}ƒò{ÿϻȌ‘½ÿÇa5>Œã£ãyçÿÎ:D¨Î‹.ºÆÈC_¹´ú:jõôÇ®ÿÏ?–íúl6FÌÚkÿ±Á­+kÿ¯ýÏ¿©ÿõ°'ÖÿËü`w­ÿ·þÿïºÿÿô“?ûƒ7œSϦ›¥Q0DšÅÂÒ ƒæîÌÊwGß.`ÏòQ®×Òtº2¯_¿NìEê®Ãøåé\Yïm¤ m‰ãtÜð9´çq_! Ï¡ñ~£¾Ô=Êpd¨¸Ún7Tê½€çêÀ³ýÁ“~9ÀØ$<^€V~ˆVý“Öp§é×ñwˆz7Ÿwaåß”K›†¯ ÿÊÿÝûw ÷¼Ü-Ts&îKùñÖG@¢ÝiÏÀþ{ÿgàÞÿŒžÎÛŒ‹ÿ;ÿG­þ??¬þ?»—­)Áºâ|×ÿ³Vw}®Ó5;5vý_û¯cdí¿ïÅ.×kÿ¯ýÿ½ëKüŸõÿ²|t-1_Öÿ `ýÿŒ‹ßUÿÿé‡ów“¡FU@¡Qj š0 €Ÿî6’¦\ƒÅG™:½žíFèÂ1w[­/ßy&zï ï>.å×J€:ewºÔwÉKnåЧ}W³HªëâI02zT’쿾¾¾ù$@ //šSîð;PdÖ¾‘IpíˆÒ~e”éѾnz”ö”i¾ò}‘»4×yÁø:‘EÐÞä©¿ah®úî BøÏ¸×—ô¦¹vàëØû¿÷¿C+ã-Ðh‡Øó¸Ûù¿óŸ¾ GŒ…Õÿ×£f«ÿwýuÙµý¾ÖÒ¢®wý_ûoŒ­Ç¡G×þ[û¿úÁxXûý¿n:XÿoýºaýÿÙ ô³ë‚¤ŽH&ËYQ¢×­A¦#Ñ:8.=GïÜcpÜ\×ÀÊ Òj¼ùõöì–²Xyðžrꨌbׯf'^‚kçv©€d'V_¤ž:GŽ>%Ÿ±`°#«í)K¶¾_R“ýêÌyê¸Ú®?m#Ù®Åêw^y‘ã­®¾X=ê@ÓºTÑYè…æåbN¯æêJ:)êûø(ù…ÖÕ¾•¹Fæ)ü{ïÿÞã¥ãɹ±b,/=7žœïüßùO «ÿWÿïú¿ë¿µC Öþ[ûoBvofP\Öþ_ûý¿õÿÖÿ?ˆ,™ëÿÿüçG×KÜN¡Ð'/BŸ4àË#ohë”(S`å Î,tðQ~è+)ï6än\FÌîØa•çÞ•»ÊSðI˜òø*[gy.>y7—²y5ü^¼<_Ìc†N êo»\?·±*¿|€Vþ‘qÂ1² 'Ÿ<êo·ìÐ\õ„Çе/•oÝ<Žþ¿v Ú+<Êo#ïÝÛwÙÕ nùÞÖ¾W&ÒÏÆÒ„‚ çêùÞ’IhL¶Öë\xÜ?ç{ÿ3~öþÏØ¸Æ™±Ó1è|çÿ™_÷¹¤_ûÉÛùŸ1DÇtGëêÿÕÿ»þïúï‡Çµÿ®×þ[ûífGeý¿yªiý¿õÿ×ÿ?›%ø¡—¸ß®£/ÆñšÇê@Ïø­À”€£L“‰CÏùËs4ÉD›¸;˜Ê_¬âãØ`8ÂùUV9ï(¨TPì=X¾ˆ˜ó©‹óôQo±a½°§/v÷5?ÊL @ªï¦Üá9/ƒŸ2­§;°ÈéÙu$Ÿl‘©“Œw°Kº‚=ÉŸ4!ý6qxNYqy…àúS9’74ï§OÊOC¨òõŹ7ÚT>Ê ½¾Ø=ê¸ç7O|—«çÒ#ÇÞÿ½ÿ3Vvþïü_ýÿЧ«ÿwýßõí¿µÿÖþ¯/f7×^_ûý¿ŽúV®= (nÞ1°Ïßø]3†’·þßñC§?ôËúÿëÿŒÿ<ýü¿þ‡7¦Ž"Pº=Ïvçšl™\h®]@&¥´ND`¸&tp×cw“ÞGÚáY°ŸÇËq‡wA¬4ò E¶©¤_ |qgäÎ;³æúÓ ª¡W¶ír ,ÃÓ®-Qù—NÜsàUÀ¹ϼ«‹’vD–i/9ñpÈw8o[‡äñúœßòZ·X6â\ >ºÑâÛ€·# Ö$Vù‘í"”Þ¼ÊÓ²H>.¯ŽÒïýŸþÞû¿óŸŽÙù½`•Xýtoõäê«þ¬;Öª‰»æøñȵô]ÿ¯¦?îkú®ÿ§?Öþ[û]ZÛÛØkÿ¯ýoLTG:Ïš»þ_|<ýñ±ÿ6ËËúëÿs[j‹¹0^÷üãñóÛæÿ?ýh^⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹½J¬e¥§³§F¿‚9å}Vsmüúë¯?0ñUÎaçVQìÍä¤â%¿id#'°­åÛ6ò¦ObµÏ…69¦ž<qÕ×¶ëðõN.<’>uv´I{„‹6í>Ê ‘ßi/ù+“<ü*·6LCr=-~äå­2éáÃÇñ(?yáè iëÐJ/­4çøìýßû¿óç?PI7¬þŸ1A·¯þ¬)Yû¦OŒ]ÿÏ»ëÿÚµµª+Öþ[ûŸŽ\ûý?ºaý¿õÿá ëÿüçé§þ‡oLŒLÁ6G€ã²pQPɯªÃÓ™v1ŒB?濫pÑ:Ê÷K¤8¾›wf½zy~mâÐs€¼©¿$ón«>2~‚jö!þà||ùâeve‘±Ë§G Sf†`)²MÄ»À1uê;·È"ÏÉp— A¢ÚN|ÒŽáå\ ƒsåKW0K>úò—V àK<çäq®Ï{®|ù–®mÒG/¹g¥ÕÿÊ•Gaïÿ°{ÿwþÏÌÙù•³úõ¿õe×ÿçµzϬí»þ½¸ö_”¥9²öß³=\û²víÚÿãpLXûý¿ú`ëÿ­ÿO?ª'øóëÿçÝæ|±â@§óÇ?~ÃQoÐqí<`FÁ£€@Àb¢sÄŽv²EéÓé|•R»sºnwðgè”KþÔ—tÀ’úÞoUZù­›œ®#ÔÁƒƒUPÇ9Ú7ôÒêT^Yrâ£\ꌩò;‹e å'Éác—~< ÇIOkËÚa‡W¾Ž8´mÃÛk‡—6º í3ùéÇ¡m?´½ø´Ðë_€+}—ë‘dò’?<|ðp ÷.­´?5‡ä‘¯züŽìO´Ï*ÿÞÿþíý?€ôÎÿ™g*5Î||Ì¡ÿ«ÿg÷íèßêÏÕÿ»þ³=výlæ…¾ˆÎ\ûoí¿±?Ùžkÿ?¿ºÄüXûÿøžõ‡Öÿ[ÿ=ÎîúÿÓt¬âwÁÿúñŸýâK,ø^9tÌBAØ‘£cÐt€B®âéÎ¥0r}ÂCðóî*Š:HÆ(×úhM~ëk®•ýꫯ>ùì³Ï² j ¥œ-uòÉZú‚+/g§ÞòÉú q“çºUÁ¯ïŒá7uM±”U®}Pù‚iÇiÌÐyñ9´_Lv©<Ón<¼³K=ä 5qóÄä½×ÒUä,f“Zm x7éd½õµÃ[Ÿ·}{ÿÓU{ÿϘ2Nzt¾tì;;ÿþÚù¿úŸ¾_ý¿ë¿5x×ÿµÿÖþ[û¿v÷Úÿëÿ±—×ÿ[ÿýÿ³yæŸÿyúñ/ñf,¯8¬çµÁ5ÇÞ¯ ÎëÐ~: –_Ì&uv \ Ú€)¸RÁå5à—º'Az&ûÝyž4;:Þ½÷ãÈ4×x~ñÅŸ|;òÈó÷·€ ´sNò´äõ¨ <€ º¶ƒÒÛÞ‚<¨´w‚>²]qWeyBû!×ST›9û^þþrbùò¤i‡zô«ôÈ©¾ h*‹ôò——ÇG2UN]SÞå#sdê>æ ‚ÿ™æIç§yÓyhNîü¿¾ô::dõÿêkOçŠyÓ5Êj#ÝÑ9$¦gwýßõí¿g›yí¿µÿk§¯ý¿þŸutý¿õÿëwü®ùÿßû¿ÿßÿç×Ý•¹p9aΔvøäÅè“Þ­¼CÐè°¾0ýóÏ?ÿä›o¾É×ýÄ5FÑ9/xâ¨c÷QÚ¶“4êÍV' JSFP®ÀН ¢û«¿þ«O^¿z}ÊÍýq&;¶î¡@—:<] Ôãñ:}’ú_;² 铘º ôx¹¼GñÐJ ¿‘…QN¾‚\ê–§^²ª3ü¤ëO€@O$KûU‡GoÜAÿhÐâãkù®ËWŸ ß¹üÙ=7rØ¥m”)üöþïýßùvdîü?r¯þ?»}éÉÕÿ»þïú>˜³ößÚkÿ?Áö[zíÿg_ÂZYß䬛ëÿÕçZÿïø¸ãx®ÿ?zÃ<áŸÃUÖÿ?¸Æß†ÿdV³é8åWÏ9y2®H>(G4ô•§e É‹Å'¾7Ãú€}E_žâÊàÜw¨»;•ì¢RþK ¾È'/mW.Ö0Η çZù(‰)#¨]š€s‡ºå“; Ñ€FÓ„žÛáúðœ÷cM{"ç|QìZÀëË/¿ z!@Ò¤'žkôúìÛi Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄ¿Dÿÿ釿üùÀG¨±i±”h¸´XU<®gpĨ@¥¡e9&òòþ(ñXl¤Ý`Žwê8îe÷º¼ëì@à€L Y¼_ ¹FhôÝ‘ g2úrPyz<67ÁŽ'‹ ñc8{/• ´J„¯òäC_9ÃóJOÁù# /¿Î{i»k2‡vò_½Ðííy'–¾i¯ã»ûKºÁ§}`;Uèßðúô·øµ2y§•Ù!Ï.´Ùõ…o_L¿ìB›Ç+óÏW_þìýßû¿óçÿÑ «ÿÏ\ sWÿïú¿ëÿy$8›á²̵ÿÖþ[ûíÿèÑ ëÿ­ÿg,¬ÿ¿þí…JüçéGúó7e,fŒäÝOsÎ Äpæ @Gßç gÐi€(bÆ×_>@§9  Eè~-è]ÜÉ›Gõ„Ô?ihðì–\¿ì¿Êco¿:²Ìµ:ÈⱿ—/_Ði@™¼fdÇ Ÿ‰‘u‡LýÃ_ÝÄC62Mš@FyÒÒ'kwéÐ4]ü¸VÚ‘QŸ$9¹¿dýl›wTM†Ç…ò&»#|ë€p&mŒÌ“ÒÈ¢“ÖDýå7á…_Ó*oæOÊ oïÿÞÿÿ;ÿWÿ¯þßõ×ÿµÿÆ&ZûïüлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øË?ÿ™¯þÁJ¨¡Äè€ (2é©xÎV¸83 ðÊŽ¦^‡ÙÐã@ ÊìL ’!˜ëçÝXÒäªCÙ‚=y§Õ¾¬Ô?óbs`N%pÍc)7åËÈÕÎóÎ <G§.2ër6žäúÄõ§/æ¥ïó¯txj >ÊáÙev{ ½FWã(`w>ÒÉ/ xY¦äyDïÚ3_!t­íº_ ½ê”Å,ÉÃ{dtº'¿²¢%a¯÷þïý7fŒŸ[×q>ƒeçÿÎÿèÊcõÿê눵k×ÿ]ÿ×þ{¶÷Öþ‹qû’íÀÎŒmºöôåÚÿëÿ™æÄúëÿ¯ÿÿŒ ýÏâ?°ê¬ú‰E¦@FÁŸ€=“.Oè$ÀKYNÌ˯¾›û•–#ÎÄðDP¶’k”þ±Û+PÊqœ¥)«Lœf&¸®¬®KCŽä2°KKã•+•_Ž/@çäŒ|Bw(áÁç½ZHGæ©(mÄGPo"ô¡™ô.Ò§.ùõ©•½/EW¾€5|s}ñðÂv;±ô»_<ÑUÑáÓö¦o\OÛ“cçÿŒ ºGXý¿ú?ãÀ:sÍ]ÿwý_ûï€4kÿ­ýO/Ÿdík…¾Xÿoü³ë£hëÿ­ÿϯXÿÿ`çÇžƒCü}ðŸXŒÎ,‘ëùd¢t€(v?õQ¾¼`Pt)é;^šþêõ«6J«À þ€–€+sþéÓy49æ¼<•å.¹Ä=OÂõPCFñT˜Te»‹+ ÃbJ?ÞŸ%Ÿ|Ê «^“OYï"“wc¡+h„>ü‡N¾srµ]Ò\G&é³ oùÍë// ïëºé›¶O¬Õ€Á|©ÒÊCïà[àK™öWêšk´ ø9z=‰¹ž´G(Í-mïÿÞãxçÿÎÿÕÿçGúrõÿ츺Ö+}±ëÿ®ÿ™kÿ=ì³µÿÖþgc¯ýí¬I_¬ÿW?Œo¶þßÙ½®/r\>(›"Ç,*úKøþjR'}ÊF×òm§œûŒ_~Ñ8Yÿÿ_¦ÿÿôÓ?ÿÃ7`Hw#uÖÇ;° &ÈÀd®;) (ÀŠòøv€f`M]åÝhÇ›¸ö7å+ïòwä¨/>}‘ú\Ëó« “R‘û¨V÷€™ËS{»Ë Æ99ÐY0qÚ6×èMê¸Ë^žM§´¦¢ôOø¥?ÎJÓÐ@IDATãhòëÝÄxÉw-Æó×v­M[LLÒe„ä'ýÉŸkk",ªÙÈxÕázïÿÞcyç´IôÝÎÿ£cé—ÕÿG¿®þ?óÚ±ëÿ®ÿÆÁÚÇþZûoíÿµÿÿb\ÿo<°ølgÍ\ÿïlöàkò‰ësê#¡q.®kiMo,_ùúÕéÝ¡[ÿÿÚÀ2ýcãÉïŠÿëL1CcÒ4Ÿ}þÙ'_}õÕãWct&S<hÒ•÷XßH˜¯ýáõ~€»GS~z\“¥2¾œ/NVêÇS™§OÏbÆ5e¨*8Æ9PŸ|uëR_LÌõ%:Т¤£t+Ùs=ùêtweM|¥É ½“+ìýßû¿óçÿêÿch­þßõ×ÿóñ&Û‚]±ößÚkÿ?#vöe˳¯;OÌ•µÿçu(ã³XGùéŸõÿŽßu™õÿ2eÎØ˜Scä1VNÖ#ï>·6±þÿï²ÿÿôoþøÇo@åý;Cc¶ƒKšGý€'Rìò¾%PJ~3àt¢ÇÑ|ŒLÎæGyÍĽí©3#7´¥3Xï简:Ãàð™ÓîðL)™ÂÒó¸ã%?ÀÇ–Þ/¾ø" ùñ:4 ÚMî†ÓÈz;üɬ ~iëЫo˜=djŸ’¥ýòà72È¿× À !’®S²lèȨž‚U¡ 2â£\û)ýyU$¯”½î‘,}g· ùñª¬á±÷?ý±÷çÿ52 dìü_ýOŸ®þßõ×ÿµÿè‚Ú`kÿ­ý?ÆxìñÚÔkÿ¯ÿ·þßÁ꣮ÿ¿þ?l¼"˜Ãx[ƒQ#'ü¯ûyý1qñŸ§ýéÏß`âHáNT® ðLU)Q:Û¥ ”ôgŸ}„½@I@¢IïµÊ’v_xÜ…ï¹X8sš?m€üÈ7 üMÞu ì!/YíE²“ˆŒå« ¹C3ñ矹ùÃÇ®×çßìNškïÀjµC^Ûð±l){ÉY¾•¹y€2è;yú ˆä¼éꔑVÚd×›@¢^¨ b}WÙÄBóS¿ü¡kZ¤ ­Cº{ÿÝå½ÿÆãWÓó¿ãdçÿÑaGæVú‰î¸›_™S™¯'oçÿêÿêyccõÿ™æpþæ4>žc½Þõ×ÿŒ…™CÂÚkÿÑ«,·X±kÿÿ ýI·®ýžZÿ/Ã#j×Ó§ëÿÑ þ­ÿ÷Ûàÿ=ýèÏ~ñÆÀuËìNª!iPgAÃÒVaº–nwèâq<å广 ‰2‚G ÖÈSÎ#tb×obŒ }ë¦á‹Ç#í£s4d‘ïÀ#ü-d³Ë‹M·3 EN瀩*±¼¬Üc“Ú6òzVvZàsÖÌ$ù~Q™Y~údø?M;„ôáE‹®idlÿTN“?íºcÌ9ù•wT~ó Ø2ìS÷”·®0.¦\šGÞœÈ?ÌL¹Ê Í/ ä+%Ь…Rvx|ùå—±Ô Ô* DÞ¶]¬>“³ï}h~À¦Ö710M^å!¿¯p¡&M Œ ÏéÏ9ÉKå;ñ•ÕÏBëi‹\Сz6®ñZþÊNŸÜËá# /ÏîºrM†;=º½ÿ{ÿwþŸ÷þ™#Žÿ«ÿëÍŒ‡Õÿ»þwýÌZIü£?y4õ¤»n’õÿÒ?ú/sj:eý?#ãlYÿÿ`"wž"džÍ¹¼ßVÿÿé‡ò³7zn`F ë»®4ÖµwJ9·³ªQÀ0Ó`É¿í4 zò/Õ„Æ59ľhÇ—a©…¯8i‡YÀ!/ ”߯¨‘GPóíì¶zõòÕcb¿|yv‰áãU1ÀMýÎíÎÊÀŸó„‰+~¥ó˜¢:r=„båÞ¿;»ÏÒÆ‹¾¸‘­ý¥À«ìX}Œ';ÃõOšÒ‡‡>:eÔ%–®.Š¾ç¹¾êB×]YÒÛ.|]‡×œ Î÷þOGÜúiïÿÎÿÿ«ÿéÊÕÿg}ÌZ4kÆ®ÿ»þÇp˜?µ}2OÌ•9vÆÚgg§¾¨=·ößÚÿìL6÷ÚÿëÿYS×ÿ[ÿ?‹æè?Ž®ÿ0”Ú³x~òôùß)!@)/l?“g«Ëð¨1€f åzz6`‡2Êx#éâÜ4eš@é;œš.Æ/[ôÃÉ ØG‘ oé„V® ºnº/±´¡|ì–ò!íqóût|»ãJ~ë¨,è¿{vSEÛ€jÔð²Ó à“v¡ÁGZÊϹ]_À,²¦O§ÊªÇb ä øôœ\Bʵ0ÓN›òêÄ»zçégç® ]·ßœ<þ{ÿØ{°÷ççÌÎÿcHèóƒþ¢Mèç«ÿWÿ‚ñaÞd šó¦umÍø™ô]ÿwýg¡t\ˆé“µÿŽ-¸ößÚÿtçÚÿëÿñyã³­ÿ·þÿúÿÓœxúÑ/ñ†¢d@Pqýúõë€-ˆØ žÎ{7ÌðCT¾C(˜³u^\,ýL9¶mR8CŒ^Fðà¹ÞÇÃàL–ñ¡óÖW¹ÊúRfÈH€é­# ´UYíð+àMyá­¼¶E?ÜëS—t|r;“<ï iùÄ€v&’HûÕì0 à5uõ=a®cüe^@ëä—gúÀ«Ãû|˜*ãhÈõu‘¾ø 4²S×Õ¯{ÿ”œûÒ¾Þû¿óçÿ™ÕÑ?«ÿWÿ[×­a×Úä\Øõÿì†~¬Ù»þ¯ýwÍ1¶2GÌ•µÿØóéŽü©m¾öÿÚÿl.ú³ïcŽÿbî\~ Ÿ¥ëMí’ÇH’7Gʬÿ—nI_ÌY|Býx ëÿ­ÿßññÛêÿ?ýì¿üû7„·xx$Bà¨PéyW® þ– Ýìx¢t »„ÐØ •÷b]“'I%s|àÏð{€9ŒãÙݤ¾CW]z÷teòø #aèüûÞ<âêN(Fµ6Tûæ›obh·=ââQž#š42©ß!x Ñ#ï¿;;ªš/O; >¹–Wáyµ¡m¦d{íÔùÜŸx•GN.~äðëä‹Ù ÜÒn;ÏÒŸ•‘ÖöáQžw~=Ç·÷qïÿ,žÓ1½w{ÿwþïü_ýOW®þ? •µÞúfM麱ëÿ®ÿì¼µÿžm·Úkÿ­ý_}ÉæmÎ^g£¯ýŸÍúgý¿³žÖWÓ' Î×ÿ;½A¯ê‹Ž™õÿŸ7¯tÌDÇL?5tLõºt®õeí¸ßFÿÿé§þ‡oÚ0 ic¥®5°iU24S¨ùÞÅxÉn¦‹šn9W6åçBÇõPgwglºLY“u¾¨ Z±|±g‚‹Ìw K/%­ àJz¸i‡a¯€PŸ½þ,]å ü5¿˜æ=ZÃSHS64ã¯þæéiÝöþöÝÛÓ÷A1¼Z‡~¹ pÃ*I=}±û½N´øKs?òãô‰6u[)Þá1´9Ÿ}x_ç%ÜÓœ—wóÉWš½ÿ{ÿóxÆŠ°óç?³úÿè†ÕÿÇ>Øõ¾LDøÜÃ=Ú'¿Ÿ9.h¤4qèÂ@Éc¼ 9¿˜Ön¥¾)kG›÷W¥Ÿ‡–졽¶]W¦ÔO†9ÐôPwË’K¾òäAÓr÷{Ux£Q^™ï&RfÒ÷þ?ƒ~í_²Üûo§ßÎÿÿ«ÿWÿŸ•r×ÿó¨ñ®ÿcG­ý[qí¿µÿcPÏŸØô—m.=iíXûÿø4ëÿ=ã‚?¶þßyâgýšâ„øŸ£3ÄõýÅëÿŸÉ>Æò÷‡£> ŒŽ È1 ‘s;3ª”u±ŽÍõLC±cþ¤÷uto@Y zê1¸–K]×äU¨2™ÙA€fÎãj²;ìÎB÷vùË{›æ¼Š ôÙiåÜû°r>eeýÚá°y„ ޾äýÕWÏm <ȉ&í›4±4àÖ\äZÿHØBw/§ÝðJzÛ*¾ƒMhÚwé+ ëiø·_ÔYyZWë}?²h…–?€ãi‡WWfêÀ/íØûŸnÙû> °óçÿêÿ³¶Uß®þßõ׿”¯ý·ößÚÿkÿÏú8~ŠÀ©¿±þßéý!¬ÿwÖ‹øš3NØSBüÔé#>zýÛÆ(ôžcýÿõÿG¹ü üçéÇöo âH€*­ ˆ_]]w'”EYI7ðäH1a38gô¡÷ˆš¼òun€ªÓ#~);e4ʋˑy®rÀ«¾· GyfÀO~ÊÚ5AÝv_Eî‹ÿcÒ\e~5Û:}úO/Œÿò«/?ùìõg§ì%IDùv.•'ù:ámoÆ“Á{°ü£.Ê]›²;ìF‹gøŽ¼§GLܳÍo¡õŠÝ³o¾ý&[ ñs­m³€(àX®õ½úñÙû¿÷çÿÎzŒ‰¾ݱúÿì@\ý¿ë¿5s×ÿËA¾`7¬ýgT'ŒmµößùÁuíÿ3.úwíÿõÿÖÿ;v¥ucýÿõÿÿ©ðŸ§_üåxã%zV–q\ò¾'Ìh`@GA"€GA´þ)Wà¤`Oò&”k‹{ëp^Å`®óÜø¼L¹=W=Ò¿üòËùBÁËÈñÍ×_XÿЫo*ËûðS¾u‹mÞHø¢u}ð‚üéî¡m¤¡Õ¾Ô3»ÀÔQ@KmvmwßÉEÎ{†èúsú]ן¾ÃSÀ+}öbdÍ­™?çmDSÐ)/äýbW;"äiÖËW/çȽÿ{ÿwþïü]GÎA'R«ÿWÿÏ"’5g×+éy•€uu×ÿµÿÖþ[ûíÿëý¡£ýØ£?ëÿ­ÿW_¹þ©qQ?¸~*»;>í¯ÿ_»{ýÿ¿ ÿyúýÿü³7R<â¸Ì sM/× GÑ ¸œYžÔ”L¹‚5âž|I™ liš]•QZ¯Õç3’œ)³üÞïý^â·sþêÕ«¤—oë›ÂØØ5½|GøÈ˜ÒmL¶¿ú«¿Jl§”°¼ÔQåì¼QÜþP^]ø‰SfAA¿J#ÃéÃð£ÔN^¿ü(ßö þq&¯¾*_ò‘³åÕ#«ÐèÔ«½ÎÃcò*›x¥üÞÿ½ÿÆÛÎÿÿtÏêÿÕÿ»þïú¿öß±%cs½t·û¤­ý·öÿÚÿëÿÑëÿ­ÿŸzýÿ` ú"xÄø•‚9Òƒ¯)ã°Ž:šÖë¿ ÿyúé¼Ä1ÆÀü¢4P‡ÉØ ¯4¾°çñiuÄÅè¤ã›Ž›ÂÊ'LpÇ£Ž/^¾øäÕËW9G«\Žá+¨Kù¶±à‘n·ˆhš¶ûg—•²‚þª‘uòÒ?h¯>Tö8 ÏÀŸrápÉqo'¾Þw%³™6^Gž¶´Žö€cŒÒ¡IÛ& ç{ÿ÷þw^îüßùOtCuÄêÿÕÿ»þg×ÿµÿ¢GG®ý·öÿÚÿëÿ±“Öÿ[ÿýÿÿ5øÏÓOæXÀÛá-Æ@1P0@¡˜¥;âàš¤€¬¡›?ù _Ë*‡®Êï; tùt(ùvÿ˜ðœåüâ?iêTHTY&)ÛQÅÙ¦\éZ•mvh wN(é€avtMÅøÑÞK^ò0Jÿú¯ÿú“W¯_?Úl+l@«áI&2ë²8÷bym÷NºÚ&¯²V>´>Š.ý;×á7|}éÌç1Õ#( Ðrmç™sA›[¾€¾ê Sû¤Ÿ³¶KYüR×uß>¨gxîý?ãqïÿÎÿÿ«ÿWÿïúo½tìú¿ößÚkÿóMbCM½öÿúëÿ­ÿ¿þÿÿ¿øÏÑJîÞnmaÔ øÊÈýîýùbã©ïùñ½(õD¾ÓŒÔUåk% ‰lÙ%5ü¿ -﯊ð4_N”á'|h/Æ¢)sñÔ×h´­}ûeïÿéÿ½ÿ&'ƘñÑpŸ3ˆvþïüÏÐ0FªG$8_ý?úvæÈL¤Õÿ3vý›i×ÿ¬ôÃÚçPúaí¿µÿk«¯ý¿þ_mý¿õÿ×ÿÿã?°8& `„ÃpãrBL¢†ø×=ÆùõòrÏ+ú÷Èz|íî)àSà¤à #Æ–ËwoÏ;­ÐÛä17´ÆžX(xÁ ‡#ƒ‹‹öœžrÊ ÊâÑóœ\éi÷¼È¼†%º¾êÛ·ß>ÊVò Ê­´$œG=¦g‡ÚìSÿ¯GÖGŸjCÒN:÷Þ+¡ï¨’¦3!»×ÐM}ÀƒG½“¦_Õ-½}®oð.N»'ß+ï>”]ÚÞÿãxïýŸqkL^ó.qÆŽÐq&žA%aÆë5¾vþGÿíü?úÍx¡WVÿ_kêêÿ¬CtÇ®ÿÇØõí?zrí¿µÿc²Ñ×þ_ÿoý¿‡ÏZ?dýÿõÿ³VÞðŸ§?ü¿þ7ÀOç«v}7"i &Fç¨Ö$ʼn44€åjŠ&¯ç¾t§ À‡C\±k)_ÐŒ·Œ—êøôéLè}Éoêw®L­©›Ld ø2å#[còMPowTÝeêy™­-ÜÃ(²§ Tò à껳ȄO!œ4r1ÒÉ/dŸú|Ó£7Pï¾Dç\Gê¾Ú­ŸðT?ƒ/´oe"ÏÈBù€)Á==mœ UN>€Ny´‘shÐíýŸ~ßû¿óæ…¹·óŸ9z™¾è =BgUO¹ìyéRàúÓ¼ÕÿçGÕÿ»þw~ìú¿ö]ºößqÎÖþ_ûý¿õÿÖÿ?›vÖÿÿ»ñŸ§þòoTqPjYM|7´-°u@Æ9T|™¼ûæy7Sœ›‹"΋²c©¯¿þ:À˜tA‡—G ¦È®ÚrŽ9lä«,h¤?ò/'4|oéáÇãšãqbW€(í+èã\YAdùꫯÝ|°ÀRêuk¿¸ñÉ;ï¸`¤œwz…çÐ¥Ú}a”ï¡×d«ß\\/FVéÒÈýÕ—_e·˜4òÈoHÃïoß(†æ!S 'Þû¿÷¿ÃÁXÚù¿óÿ|Íõè Šsõÿù:­5¢úV¼úÿŒk’þx»þG¥vÍï{2]ïú¿öú˜+ôÈÚºäôMlصÿ×þŸ¹±þßú”A/<ôÃ¥7Ù÷ôÐ^þîúÿÿ2üÿ§ŸÿŽ)Xä†7Àp£;0š÷XdÇ U6 ­ ñÒò.¼@ÞÙ=$¨‡#\€(`ЀGè?{ýY”2:ùÒ-gÁ’úQ˜]E5åTÆÐ_2IWgÛ'Mºiox Lêµ»Ênœóø¯Ðè?øÁ'ÿí¿ý·O~ï÷~/rvr¨/õxù<çe²›…üÒ3±ª›(ˆ£„+_ß%Ö¶¼9ðh;Sç}yyý´Ñ.1»ÌÄò‚6Ù¦Êá}vc¥½.&¨W»¤Ù•E>¡åW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿ7þóôãÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúùçŸÏËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þÕ¿úWÙe”6‰}æR,£ðwà;—9ÇOÀpI@#?–N›ð½•*wËèFàÉÿ^&ú¥^iÀ«>^èž)÷vCerÏ.yðÁ[¾ ¯²´®öü½ÿÇùè8Ñ'{ÿwþ›ë;ÿWÿ¯þßõ×ÿµÿÖþ;;,Ù±¿×þ_û|­qf8Rëÿÿõð¯n>×ú·§œŒ• ѯÿ6Äð××ÿ?닾øMøÏÓOþìÞw<ÐL4ÀˆZqÞIøð¬º ¨LËŠå¡+ àúÔ#w ÝwÜÁ|‚rŽÖ?xÍn¦KêÉû¡Ç_¸×¯leq®~×Bä¿×ê!ÿä›:xªW™Ôu)å[ÏÊÊpí9ú¾Ë MA àö»–_¾}l@Ÿú >úGŸ iúMû=¶Sà°m“Fxåð–.ö¸ Çzäé¯ì»ÚÐv¨£²ßcéøÀƽÿgœµßöþV?ìüßù׿Õ)ÆÆêÿó#Ðêÿ]ÿwý_ûoí¿µÿ×þ_ÿ›iüA>Åúq5¾h}Ïõÿæ°þÿÿþóôÃ?ùÙˤœ{¬ HcPÜ™4Á¹‰ØÉøâ弄sÀ’>qxB®ôó(ÛA˜\À©-@Éðvð/p¢¼PÙ8ʸоzý*×Î 4 ø$\Š¢m;‰ÍznïyÏî$m@_žÎ9f÷6ÊÓÒ¢Œ^¾xùx§Wv[á;!ýrõ›k<Ò§7ç|h¤ ü´¥}®>íïµX¹"“òZ  9?ûì³€[ÝÆ7òÜã^·^y{ÿ÷þïüÞá¹óÿYçV÷ЫÿWÿ[ü¬A‚ظÈÎÞ]ÿŸ×rý²ëÿ±{Öþ;ý°ößÚÿ£Öþ_ÿϺé`[Õ[ÿ/&ű'FW®ÿðöUmðõÿ_}òôû€•Gé뤙I™L&V’h:ÉÚŸ>ZéÊ´,¤­4÷Ýwó>§>†84ò²‹hb_ÏÃÃ;L^<:©ÉÔt´ï‡ßH™44@AP ô(+ã Ò´áæ-Þå_âÙñ$#+Ýyû ¿®Tfu“£m{ÔC91Þæ1ÁÈ7×þ 1ø'–Ž€¨ÉWOÓZß)sƦ }ƒFùÊ(½/Ÿùê€kê«C^žèÈ+]\~å³÷ï?€ö>îÿg÷¥¾Øù¿ú¿úzõÿ®ÿ»þ{J?kÿ­ý·öÿÚÿëÿ­ÿǯ¼ÛHžZÿý¸Ãßÿyúwÿù§o€0v\xÞ²à£ãÀ$6' Ð2ÿèB¢¤'åEò z4¯´<ÆŒü$S½OfÚ,¡c÷ÒÎŽ¦³ý8 »À#<ðÄ_º£õJoZ˜ t`"õ â¤IŸC=WÆ£½'á¹ þƒJúJº~{5àOÚAf€ÐÇ«¼‰S¥´ÇKÛÈ4•Ö >ò ͼԭí“FÞ¼|=§ÿÔ©ݹÖv¢U¿XxØåööÝÛÜG²·ŸÐíýŸœ{p„«w÷þ·?2Of€+$=g§¯:ÅÍ+íÎÿéÀÿÑt`œ¬þp|õÿ®ÿæÃŒƒêX‹Ñ®ÿkÿ­ýw>bÄþfÛ®ýžDéú¹öÿúëÿ=?5U¿ÖüàÓñCøÖõ‹ÅI“>š„‰ëç2Öäõÿÿ÷ôÿ²Ë scÝ$`§ÂBQ'´FUo¾ëž?Í Þë 4Ƈ#‹§pç{Òçqù§~!gÇÇÛoßF4êi]@®ÐMzyçzäÚ„ÿÐ×100[>ç\|5«Ž%šçê-¿Ê,½r–Ö»¬ RéõQÃ*_;­Ð´ÿ,>iëÄmGh#Ç‘%u͵þ¨œêª<œÊé—¶ ugŸÇ#û¼[ìƒIŽÙ„äíý?qõÇÞÿkžÍ˜Œã®cËyÓïü?úgçÿùEɸ©n[ý¿ú¿ãAlŽìú~Ðë¡G­×óG[c®wý_ûoí¿c¬ý¿ö?ÝèkìÕ›¹žõ¤þºþßy¿²¾ðT”µÅ»¥×ÿ;ógý³æ„ŒßBÿlÈçGõ(„³£èUâGšx\ÙcPåWói¬F;(ØÒ—&áJë9ÞŒ2^R&f§}ûÍ·Í<æöÙ|Õ/ÜæÏ_|‘ þ¡Eê:ƯIù4 XÛ’òX¡òhð¿F•#1>9¦ýݹ~n“zûˆ ¾h;Q}§e`G“ _|ZV{õKÀ¼ËáG#ß®3òV¡$ ‚[@—w[MÚéé“©\ÛÙ'YÜà¼õ’×ÂïW]镹}§ÌÞÿމsÿzÅ{ÿϨ2–wþïü7¢s.]gt¬þ_ý¿ëÿ®ÿ±9Îrq¸ë|í¿óƒîXûoíÿµÿÇW™ÿëÿ'‰Öÿ[ÿßxöàϹþÿ pëÐ?p‹à??ž¯28ü:îÑ=€Mvò qÁ ‡e åñ>ý:\€)ò84½®sswtJg—Æ÷æ]PQàס7¼Èr~a9‹}™¾„ƪ.à Òˆ|•oÒ0^_šÊAÇuYûý?óE0Gœ¯ÿwüÚ£+¢*â¿V‡¬ÿp :V0f~ýÿ§ýéÏßè€,40âëbº§«É¤ƒМ<€•>bçñ=Á3¶dI¸þ´Á3=_#Ì×ý€O*;ëÙe+©ïâÑ›uç+?rÀ”/\L¦I攟tmCãº*‡´é³2™øž€rMf² ®çÏã~6íÞvò&ìýôûÞÿçqg¬ìüßù¿úõÖkß®ÿ»þÑ;…2çkÿ{Vo¬ýwìèØßkÿgžÄ?–öqµØæŽÍ~ì­µÿOŸÐ+÷þêyújÖŸõÿÎ@Ò=Öÿ;8Âúÿ¿ýþÿÓù‹7Ǹ0Ð)ƒA©»B8ÈfÑý!/@S’ÎB„WÙ àAþCS^†,Z÷<åò¸ÛÄ~‰}¼0^ÅW(ñýh¾øH2Àù.9†øQ?eÕ_ÀŠœKÏD'Ó€žîæ¢TÝdxéeñÆKP‡òBR&¯¡ò'ï*«?Óö‰ÉPg°|[&u\Œp¼§;×vußy—¦`›ëæljïÇîÞÿçùeŒ<ÆÊ0“pÒvþŸ~Úù¿úõ¿%p׺r×ÿ£Ò3&îkˆµUXûïÙ&5okÿ{{íÿµÿ×ÿ[ÿ/ ÅíOýñý¸‘¬ÿ?}ó»âÿ?ù ¡…Ó]¯ÑÕAr=/X’kˆ²"€ÍmP•ïò³()_PÇûRZ¬7sôZye ( ÷œ——X^^<>L• è@ž Í÷ø_ ƒÛn*åʧe”¯¬ÍS:¼ÎWSÎãQ‘Q»' Ð\õ胀NS‡A„äœ|¥ÔëH_L,Ÿò‡ûä$»ç¡ ý•¯¾;_yå§\ù7­ù¶ dIÞ0ÞûÆêÞÿ3¾3@>úÓ±–ä;3x2`wþ?¿[nçÿóø¡[ªkWÿ¯þ72výßõß»ößÚƃ]Ûúºf_X;äÅfkç]KÄ®×þ_ûŸdìÔ—3v:>Öÿ»æ;}BæÒœ¯ÿwlÔŽã§¶jõÌ÷Ÿ]䯓ףDGñ{®¾|ЬÿoÒ¥Ÿª£ÛG½þç°ÿ?u³2˜× oÅb•7½‚˜ çΉEe¢ï柣†ÿµ8Iwí0pBº:zÎÀ-´×/¯ÁÓZÆuù}:âÑ ýÎÏ#„oß¾ t„yÁºCèÀîà½×áü÷I ÔvU65zÆO;¶äËk}eg×ü»ËTßi生‚ÏNþù÷=é€\ò•WÎñ1¯{P³ìégaïÿÞÿØ×˜2&îcè~ž¼ùó˜Æõ\ïü?z­swçÿè£tW½W=¹úŸÚ-¼úÿ±fuŒìú´ë®ÿ<Õ­­Ekÿ­ýgѧ£S6 }²öÿ‡shíÿõÿâ‹®ÿ}±þÿo·ÿ?ϽqFGéÏÿ ì h‘ÞPVÜCž#Ê”!ßûõY@yÇÒгÀ-}®ÎË‹O_ ô.ùÃ84]xð#Ï=®‘SÝóï»y±zéÈsÚ0;Ÿ&½õHg—7Y쎒n‘ë—ÔYÒ¼äÎÑÏÛ¶Í­§r ÕZ]6HSoø f÷V¶Âz¾òÔ}Ê\õ_¨nyâs¯çôæÅýª¼î¡å¥§®X•VÝBó#ÏôûÞÿ{ÿŒÚù¿óÿoÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿž~ø'?{Äiì@‘vwZœ£½;0hÐJj°œëX¡\Ùjç0dQ(Hø?FŸXžCž2v8ðnÝù…VCO# ,”Ê9ù÷£|û ï=ÏŽ+åòxÓŨ!¯ò§=×±ž§²«¾ÖûêÕ«Ão€4t@2õŽ@‘·u“ÉyË©×=Èõ”;'ÓŽ<¢9WWžX¹na<„þM{¯:û²qä “qÃÞ; ÷þw}ú4õ@£LQÊ-íÔã›·o³’ õòå‹ZÙÃHÛL9•¯çÊšÛŸ¬vÓ>“çƒ: ¼­·³zÓ?ÿZ§:åûü÷ù§{éO·°ãÇÿêÿÕÿ;ÿŸƨÆÿǾ[û/³äÚkÿ¯ý¿þ?jý¿Ûb’ñ;ùšëÿcýÿ)`W€EüCà?O?üåÏßÔ¸(û)ì¾oUÀ«é˜4³îB¹¶€¸Òsù ° ß Mf¹ÑJQiy¥M†ùÓ{ç‚7®m Þ8´¥+“Oé¹ÄøÓÙŸ«ñh|¯5 ‘Ug-ËÃÊÿ^/ñî)9g|›Þº4_åúøÞ7þîùü"§6  ÀVÞÒÈ Ÿ¤‡ŒÒÉ“o2<òTž}þ§¿jCmµÏÇÿŽÿÕÿ«ÿwþßùÿlanØ5ÂÚÚµÚ„í°öß±Åkw¶]œ…Úœkÿ;\;õHûÜÚȽ°öÿs;´=î>ÍúÇ7\ÿïà s­õÿ»ýÿ¼B˜›gô›8(LÆy•€s•h”åÙ”0ü˜|GA™Ðãs3Í/o>›|+&óü¥·L Èïv8ü[Ni‹zã#tCjâîi½F‹çìK% tMgòÛûÊX•ïã2Ðy…HÀK^Çà/|®ºõ?éßÎj(¼çûq"ó7ñ÷¶¿ó¡"WËóú¤ç×3-¿m Ôªœ-?u™H#¿û}þûüõ+}ÄùÞÅíø?:fÇÿêÿÕÿ;ÿ›k;¯v>öÃOç_:sçÿµÿôýcí¿ßœ7/4Ȅؠ—­»tíÿ´‹¶¸Û^úNõË$$­÷µû{Æ úgíÿ硵©CÛ¬ÿw½éWëÿ­ÿÿÛèÿ?ýá¿ûÉ›L3¨)EÁŠž*KÊ/ ÆÄ»Îà¿VÅH›<:?­é¡Vx¸¦,äÓ@@_+RQÀs-½eæzîó ßäC‹—8Á¹å9¢rNbhÔæÓ («2o~‘mdyÿn6Š:€U@²)§hë%½²Ê[Y\hðU†üdì⎓“¯%z5q^É,oy*Oeÿ8®÷Î-³y ’G»Ù4WBy¦}&ƹíˆ@º#ü&ÿÜ$ß>ÿ}þíkú̽é+ùª¦þ4}»{ÙuœHýŽÿ´ÃŽÿÕÿ«ÿwþßùí?«·×þ[ûíÿõÿê×—«íþ×{çÚäM_ÿïàño×ÿÿ½ôÿŸ~ðg?{µè èuŽ{¡éh3˜€® ¢¬Cɱ§wþ¤A·Æ™ ¿Ü\TxLWîÚknÙó ß™ðíÍdÒ0tÑÝÁ¨ä‰=7î^Fãœåm=#³çtÒ…}þ§]÷ùïøï¸ŽÙñ„¿—®«ž¢o\¯þÖÉš©íãºá®›Wÿ³Ìõ§uèÜÎsæñ†¶Yh¯ÈŒÉÿÓ÷vùÛÚªé;ÿŸÎ£Öþ[ûíÿµÿ×ÿ;} síúëÿÑ‹ÿøÏÓf,ï€ãD `ÐI˜I(ÂÐ Ê9‘S51Ý -îņÐ>GœüW95˜°©¡ä¯ò‘!åCãK™¦‚kï@§nsOA¡å~7@8ôW}?¡@Í¿ïÛH~ø54|­´z_ÒåK›LCø&ˆ÷+¬vdøà#àqâÅ}HÙ¤g™0õ˜ûÊ$O¯µ­l•%ñ©ÇùÌ&¬SÈ£M’wêºÏÿô÷}þÓy¦ìøßñO‡¬þ_ýoÊ|{›?3¿H0]óIæ°ÿwþŸ~¢¤?\}CÿIÜt™µÿÖþ£:j³öÚYXûÿ´C ùërkíÿ¶Åœ×ÿ[ÿݱþÿÁ ªK_üÿ§ÿù½Ñ `@OcpPÏ‘§$jx¸çÌ WãDÃDЙ¤[ÍäZp&|®ü¯ZeÕ¼å xzäE7÷ҔײZö=oËr~Ä_òËŸcÒ”-_lää ˆ šû–U9¤ ÂÓ½4A¾È:9í¯%¯×½n…®KÉC|ýAÓ2äM˜‚ûí34÷UaÚ'üÈ2m*Ä(¼èp±ï˜ÜåóÏU¼{GW?DÌntynC»ÏÿôCí¶ÏÇ?€:ctúÃŽÿÕÿÔæêÿÿ3ŸîüÿlÃ-±ößÚ±#×þü°m¾Öþ?¶½©¬ÿ§S¬ÿglðcõ‰Ì©ãÛ®ÿ|öõÿ§/ø ¡bÿ'«ot’t˜Gjpä|)¯Öi¸v¢(0‡^ü]»w0êг'ŸOK” (ºIô¹;ñÄÃ9ÀÖœïôÀ–»,ásWýjâdNý¤ÕÉh'pÆÛ@!êÚZ§E&ÓUvÚè*¯õ"3¼ÚÔj+íÚr€Wymñ*«ù;8ÉPþÎdW¾¹žÌÑ8t•_X™| íìU„¶e IP–‹}þöÛç¿ãÇÿèàKÇw<Ðo®Wÿp†.¥G«¿Wÿïü¿óÿÚÌ©µÿžŒ5—:ª'ÙÐkÿŸâͧm—Úækÿ¯ÿ§/ôÐGÖÿãz¯ÿo^I»sýÿƒÿ<ýä/~ñƤ[PCG±ÊÇDãú>€Ð$mè¥dÒVúkîå×ÈèÄI'pŽäm™Çe~¤b¢CŽ–“û‹Gø OàPW%‰û8T~g|Z¶û‚?Î&[ò¦F~×/>=Ÿ'·|â’ع²wÖœ•Yß@'¾4&«Ç«•Ùß묌 ƒÛŸÈ©îWû‘Å¡1¤9Òæ#O'À[ö”­M’ï–@.ò<ò Ÿ>϶Gê²Nþ¶6hJ®rD–}þiim²ÏÇÿŽÿÕÿ«ÿwþßùí¿µÿÖþg®ýÏ›[ÿ¿töw^ÿOXÿ_+<>$ÿaýÿiƒi–â iØÄ~=˜ÃÀçWä€À WCÊØý–0“V€ÙalÏ%ù&5™“’WèºT­r(ô–w??²OYVM¶–•"€âõÃæld¾ÂãžüW<Ú1ÆîçÏ)gîhK㺯Š{ûöm&"F EôúõëTÁ ‘UœÐ2ô\ X&³«­*ZÏ@ ~“/5 *éÃ0ûS‘WpPšý{’†F™­Gù£MüäÈþSVêŸ\ûü5Ã>ÿ«ïhŒéÓArìø?{Ûíø_ýOw¯þ?z‚š #2ïüŸùhe>ÞùœöÙBaí¿c_®ýÇG8ݹöÿØWþ³³®°ö?ò Ó.|–Ø |ÑæšœÖÿ[ÿÿºþ¿ñR½z†ÈåÃ]ã§úåwÑÿúÑìu1 0èÔ&\‰Ñz*iîÏùR8èñt²CåLY_JÈ}°eUŸårWžÊ"NyÊp¤5]¾”?ñ}¸Çõ:<+“×½&ؽ¢8&@ŒòàY€êÕ«W€X¢Ôã’×lð@+D–‹&ÎϤ£cèÖÈ áE;>êòïcðê(qrá>õÑW9îÕ¡m“ô‰{7õ³iýÇi-ß9´sÖ~ûü÷ùwLéÂŽÿg{Çõ~Ï«ÿWÿŸ7óoç&óÑ\G—Ì5Šÿwþ_ûïüÈ™‰uþ°½ØpƉcí¿µÿu‰¼^ûý?jbý¿õÿÏ|Ÿý÷Ðÿÿ4“ä€- “¦Éðñ½ ¯ø1:iÒ × 2¯Žš|‰•0Ý Ý\ÊóŠ]iIº4|†–#ü~6A–CÜýˆñ–—Ñ;×å}.O º:ƒ¹ñá|ub( ©ßH‰\µLÄo&Ã÷ôi~y|}p8¸ øc5Ö_| å¾€žyÅnÊL‰¤ágÉè0J@#xöq@+ºZõù¦½õP§zs¶©“€ÎÕ´VÎ5 =ÇÒ¸þõÈë>ÏwòÜeLû\üöù§Y÷ùOÔ/Ò§¿;þwü¯þ› Vÿ?ÿP4Š"ó-q4ÅÎÿ;ÿ¿¬´IÿÐ7Ì#ÓWÖþ[ûoíÕs06ÖþžSî>É(ŽÇ¼2ͶþßúF~"Üý6ˆøõÿOÛü.úÿO?˜Mܺxøß?fgÖt@Úu'Üir*ítëNS°„b®A÷PÔÃYù¥i¾)`þ?¯ Ràæžÿ.C;îýŒ—€®Èõ‰M™î8òY™h,•ÏË© €ü»è¾ùæ›O>ûüóðm^µÖFá3àT_1ÁO_w h5e¼œ•Y6¼ó Ã?eDØH‡O:Ü”Ù@†) í =-=g×BxÌçËÝ÷× íÈç²ãÇ¿~@gT§Tï÷,]¸Óäž6ŠªyÖ7¥©n_ý??Z¬þÌMúƒYsçÿÿ«#ª[FÁÌÿµÿØ— kÿ­ý?ÊsíÿË¿©}a|Ôß¹Ÿã†t0òœp~Äw_ný?ô¡mW»¯çÓvÒ$ÏÚëÿÿ/°ÿŸ~øg?{cÐÈ5"ú•¼Æ1&Ð?„ÒWYÈ 9÷Ïï¹Ëo#²cŒÅV|ùt)h"î¦Øõqù@IDATû,÷è z£<¤i/ôÀ¬–ƒú–áü¨Ë•6‰a ¾åü§-NÕ¦^d“&GxMÝRÆÜ;ÇšôðºÀ¹´Å)B¦“Î-«mƒŸ¸Òìóßç¯c¦¿]ý&ýjúÈŽÿzïø_ýoŒôåêÿ3˜KíÑkºcçÿÿcc¤wÜþLßXûoí¿öÚ¢t†ÐsuÉ=níÿ µÿ¯¹fý¿õÿÖÿŸ¹äwÐÿìe"°*ˆ#ÚÉà>9Ôð¬ÃÊ8OúÌ'2s`¦4™|.ð¤¼ÄIï}ó(3Ïœ?þEVZè'š(¤áãØ ”iŒ§CZ¾x8‘ûoTú™ÿ‹ª‡WñGlòÊ£ø–Ã)íDê:´¡ýæí7Ÿ¼|ùrVU½ ÈØ’.îÈü zà§ ñ)g68­‘VÇWZLý¡k½=¿DjãGÛ]õmžðÞê–:éÊ §a&ŸÃ³µz¬¡ü*Ó>ÿ}þ;þwüÓÕ w]A7‰§7Vÿ¯þïü¶óÿÎÿôDl—›Ž 'Fa| Kjs¤ïÜòÈl–µÿÖþ{¶uõ áèšµÿ3/O{8¯ý¿þŸ±‘>±þ_ÚÁ²þçÒ™I~Çýÿ¬À2a:~}R12¬ä%YÐ…Ã"ÜéÙjŠT«‚«® BÍÌ“/ÑH—ÇÙkò$JžË1BßN¹æ^ž”qC-Ë’O<3€/º³2iʼ@(¼+_¦–§tÒ)÷ÖèÈXþ΀'´d1}:à—8+°^ÏŠ,·{5PT6ùêð‘ýýwÃcÀ$ùÜâœaêÒ@f´wæÆŒž8tò6½ëƹn=KOx÷É7‘JÜç?ÊoŸÿé;;þ3Vvü_¯×®þ®\ý~ÜéüºóÿÎÿµ¯Öþ[ûϤ¹öÿÚÿëÿ­ÿŸvüQ_¢uÍfp^ÿý6ߪ˜D1‹ÿYüçé'ùÇo€ö°bç»÷gÿ&¿ªZ™$H·¢¨+•€4:¡ÍÌG“`„(RãÆÊÆ?>å‰FzªVÂYð÷ýµÑ¹UHïßÍô8R“.íÈý äØp>¯û]ù"ËE§¡J?QϲÎu±Ì}ãºÊ+@ÏÈ‹&¯  Æ«´ùÞ^«¯´ ùäM™ œ`•¾mqø},WËj|îOùêî,͵èÚþÎùœÑ)SÙi?† êÓþá·ÏŸÿŽãeÇÿ¼ò<ÿVÿn•ouòêÿßd¾ÛùçÿµÿÖþ[ûí¾Èúëÿ±ãs_þ)›©¾îúÿëÿÿcà?Oøoü†òêÙ‹O_< ©¿63ÚuFÀM;{Wi¥éÄ=  à--å ¨${¤X&±ñ=Ü+8Ô_z¥YyÕ²†8 Rdz2£NyÏÏ=^Z–§âZ_¼ÔEºsËt lh Ð{>å~õÕWŸ|>›¼«·tü^ÌñõWg߬·o߆_óºl ­ŽÊ*kÛ2qW|å­ m[4e ©ÇµªÆ}Ê™²*û>ÿçUrûüO¿Øñ¿ã¿ú‹ÎYýæ·Õÿö”ÜùßÚ9¼vƒ¹uçÿ@[ûoí¿Ú¨lݵÿ×þ7‡Þ}›õÿÖÿ3wÖ·uøbëÿŒD‹ÜÛgýÿÁMþ¯ÿ÷ÿÛkÖ_xóÑFå5ÐL>V1ÌlsÚ˜:Z^Ý>]:*­tOæGè¾Kþe6´{%O(ñFç¾ S˲*jÌ<éüJ…§õœÏú-Oâ~MÂïÖ§¯)ŠÃ‡üd—§m&ŸxySèÐÿ³öÏrÖf‘s&oÆœ|ß~ómøÈ×z’Á½²‰[Yð:2Í+€SôêÙ|ÏN(&Í>]ä-]òOüD\ÿ> ç‚Cx¥^ó¥<ÝàŸlS†ëòEÛç ®×m»Æ¹wTö´Ù—r¥· tÐ^å Ë—oåîóßç¿ãÇ?ýJ¯¬þ?:Z[TO¯þ7sœ°óÿ±/vþ_ûψXûoíÿµÿ×ÿ»¦Çõÿ¦!Öÿ_ÿ¿†qÁ–ØÓAÜÿyúélân‚ÍèéùÞ¼âvÖï„GþèlŸÍö¼Bôy5€VAÈæ¬0¡Ê_aK  í|OKÆþ ¿oR®ìÉ–Î^sp X5gÙËÖð¶bìÓ'û?€K¹œ â4oê?ù#Ï•Ž?ziâ]ã/^ß›û¬úRÂÄYyeµ“òÑshºLZyÚèW¿úU^+”fõšUkÚ¨¿\¡ –zžöòX Ê}Ô<%Pù[7Ȥ8OòHëYÝ4Ú.ùçÚš£}þ§ìóOÉ}hÇÿŽÿÕÿ«ÿwþßùí¿c®ýwÞØXûí>ãúëÿqÖÿ_ÿ_?ø§À¾÷ŸþŸÿü›1É^X€H3'¸¡C:܃>^ÎëoßÌNñ “V ‡ðLfÏ'6&94wþ@è*£Œ¦­ò#ËDÙÐÜÃï€4Ò+CW{¹Ï’ÖK>`•U§ÞøÊaqÊÂS9€ ÷âÛäL› AùuàFÞ«eÕSË,O÷ä%ê—RN™x &åïO[‘LÚÈuêˆà*ß}€¥+Í}¼¿!ùõtb호Ü_rN^ ZëMžÒôŒ§x ™È.4]šüäw=D‡fÄ—§í#üò‰ëëA½zíó×Jûüõÿ;þWÿ¯þßùçÿµÿÖþ‹}|ÙžlņµÿÿÁŽ^ûý?cC_p¬ÿw|)þD|ÓQ|PÇýž.©ë:¾ü¥käM[^ñü[ùµõÿŸÛí÷ÅÿÏX:‰NР“íD2 Ò8gFœ|}ÍÝ !º8;:Z_ôø¥óΪ÷è£8G/žÁ.¼¿}7«‡.¹ú@œåÅ?éŽvlq1PÍ5Xæìº PR&ݯf‘Wú9Üãoå“×üð~V©É3éÎMéåq¸'9åkh9ò™è}ùÏ+{Ê$‹¼Y=¥üÊ€Jâq¸Ý©|ð¾_ßÛX™§ó*á%Ci¥ á;e Ò*³:h72hw!í;ge‰“oŸÿé/ûüwüïø_ýO'®þßùçÿµÿjK±j­ý·öÿÚÿëÿ­ÿ·þÿúÿ?üçé¿üù‡‰–óå ´¨3î\CŒQn."ê•=ÎÛoÞšh£ðð¼›××^¿~ý˜¸Ñœ`åÒ3(‘ÏŠ­·_ãu0—~õPyd KžK¦Ê¢<éBë6÷ù{€ò;¸Œ,@¡O#ƒ¹.ÿ+Óƒ`šº©“=´"ÛÈÑö–fÙépV ÍY(ßÊæþ~&2O|PªSXÊË/·z›HñG_>ÊuÝ£òìó?F¨öÕ°ÚlŸÿŽÿÿ«ÿéÕÿgïܳóÿÎÿkÿóØ Ç~`W­ýwì'ºbíÿµÿ×ÿ[ÿoýÿçmJèÅõÿÏW¯µûÚ¼ù7ð_!dx2:5Äuл* ]v ÙŸiVåu³IG+¯N®)&|a® ÜLäÒ#Ãäûƒ?øƒ\ãgStÂK¯ &;AeÄã0zñéó«w“<ÛÁ0×€+÷xXUDÎ/¾ø"_Xôˆ/xƒÞkÊ!¤û€Iá<®*‘«M~Y N»ô¼¦;+ÿ†ž¬ÊT{öìÒ.Ú ÖðAÞ‰ŒlMœ³ò¼iU1‰»‘œ¸ù‹®ù+÷>ÿ}þ;þxkLìø~uT{8Vÿ_Útõbçÿÿýмöß±¿Öþ[ûŸ#¾öÿúëÿ­ÿY‹Ó>üØÓëÿL$ÄßÿyúÃûã7€‡àl( Ÿäè¯#ßÀÒý™B;m_§æÅ¼úpa×7ÞjŸð›³8ÏýýH¡×ü¿úòËE}Ð&Gó–¾@ÓùšßáoW•®@MW[Ù´Ü«yݼ¼ò ›ÕNßÌj¨¯¿þ:òZ•0•šß‹>X5Ö:adk9¡¿µ  õý1òMÚ=Dj;£Wnƒ!4¢‘^ZF.d×öÄ·@¤:>BÊL%&*O(µi<<„´Ç>ÿ}þ·> \Ýñ¿ãõÿóªÕÿÏóüÎÿgõrçg6Am§ÿÏ>žkÿ­ýW¾öjmΞógíÿw±Ç×þ?>•~±þßúëÿ¯ÿß¹£sEñŸ§Ÿüå¿ùÀ¿€ € çÝ·ïfЧŸ|6¯z%€3Û}Ÿ0u}Y¤ëpŒ9Æ[yƒM â[¸(÷ø8{%ñ€Fgµ” ­Pžø›Ðuðo@sç-þÓ \s ²ihP’¿ï!«[ä½ä(¯6œUc÷²ð“æœ]uQÏ!~з Bxý!ëN|Z¦er¯_x6lÄËß²Îë‰çõH¬š/²i‹‹>¼§¾÷+i¯Ñ8<ßOŸN6­¿ìóþÚ˜~¸ÏÇÆÈmwLŠÚñôéêÿ£[GÙ}«oÜ®Û}VÿŸ9¬s óÎÿgÎÙùí¿µÿæGæµÿcß›?jk¬ý¿þŸGÖÿ[ÿnPÿ_ïú÷ÅÿúÁŸýìA ÂBG Õ7ó*pàã@_p*«.‹jLø¤è ï¡ÚÝ4ºÃ$ ézâðçá%½e»Æ³eóí7#ÛyÍï_Ï€˜²CO@ShžnÀé-<{Ι(ÄMpN1×äqGU ‹x¡çܸŸÄO>T®Ïñ!|Ë«uSà°í‡oÀ·)Óʪ>+ñÚb„;ûy‰˜ë)è”[’œvO}&½Ï 2’«<÷ùø|4©öÙç¿ãÇÿêÿÕÿ;ÿ›:gw~pnØùí¿ÚVì±µÿÆff—N¨í¹öÿô¶øÕ%kÿŸ- ØÛëÿ­ÿ·þÿù@½¹þÿ§Ñ“Õ‘ô&üçÀÊ* ó ž_B£Xg…ŽÉÀT%{@˜³oö•²"êŸ=ãå>ÉLœCÞRCP¡Ä”-ȇ`VM§’l&D¿\J{1 —x`ŒRÑáí5¨¹ ?¼ì/åÕ>éò9È"^Cá׺Ʉ‡Pµò7¾³óÔ,uüÍ´_®¯¼‘iäBß<½vVõvn½”çúÞ~­ÏCÞIä”+]Ç•ø¹ºêßrñrx3ò*Ÿÿ>ýqÇÿŽÿÑô ÝR]áL'­þ?óWuùêÿÓ/Ì=æãžµÏ}þšÉï1š£vþ?í±óÿ³]´öß±k¡µÿ˜­kÿë ƒéÔµÿ×ÿ‹¿ºþßúÿ£~/ýÿŸÎ+„áhÆ9Î/$]ã×f›±k4”gŒÑ dq-ޱÊ­‚}ºh¤›€B ÛæMúðN™ƒû<öŠÚÒTž–Wåé^Vh@/ƒÚaø¯¾þê“÷ïÞÄ?©KéºI3þ©ã¼nˆ·tÀ:•¯3´®çO6.­ñ-Ÿt_W”¬ÏFûõõé§ Ú…ò*ÀD¶†¶°˜¤Lq÷¶sMŽ–‹ŸçÙ V“†'¿þõ¬lÙ*仸îóßç¿ãtÜŽÿ£3F/«ÿWÿïüìŠÿ×þ«Í¶öß±—´;ríÿg;|íÿY=µþßúcCÆ^ÿúÂúÿÅ4Ãa‹*¸çãÿyú—ú£7ñV8,@ë×k«‘Ð芯@' ^PJ'¿-Xí` è2g•hg—žøÙPýå‹óº _r(C™ÎVHeCöá[Þâòjè}0r)gâs=¼Z&ÚÔájLr†n╉N TÊ»€$+ÏÈUà2¨°(R\² “k…ÓpV×)o‡p$ÎeÊjÄh¿Ê Œ¶§¸|¡°îyð+Oexb4äšø§ Ò{ˆëõ>ÿ}þ;þwüGO^z¡zèÄ­þ_ýûqË·óæØÌ­Óg…óÎÿÚcí¿µÿbŽŽ`cÖwÖþ¯õ¾ö?ÿdý¿3·®ÿ·þíîõÿ/üçG¿üù›)yehVéÔø4™H³ª©Nh/õ¾H\éU¿€«  Ãeà!é&.´} ½ï„ælÀ¾žÍãBÀ¥)›BóÑܯV€%“£ÍÈK“‰qâ&"usïP~@'ç %U• ×Êvî=PH~ñ~q¯¹~12”=þ-K| Ù‰S·{ˆŒ÷ˆ®#Ïհʨéñœr¯~Wøø>ÏsÒ=¯³Iûy6´Gëöù€uŸÿi}Bߨñ¿ãõÿê?àd®¸æÑÿwþÝ0ö Û†M£ÔYûoí¿µÿ×þ§#ø/ëÿ­ÿç5/óCýýøµ·ûõÿ–¿ÖÿÿÛñŸ§Î&îàŽå¯‚NÔæ+}6tçÄvS5)½ÏÓ³k §Gž$ÊPVyßÏòaß´ÍOh°Xb‘ØÂ›¡”¼sí, £÷èzH¢‡üê¬î'~”íl”îZÉ¥.{ –ûÇ1ñ^Ó+PÀhâ’oÊ PGÚýbô0| nyÐÕS#îÅ£¼¥{ñ‘WÄ-T¶F=è.¹•åy ëõ>m±Ï¿}GÿÛñ¿ãõÿêÿÿwþ_ûoí?ö'˜à,8¯ý¿öûÁúçàõÿÖÿï|ëÿÏDñ€ÿ<ýàßÿôF¾;­5R´ô¼jƉé¾P€à”‡`Bo° â8¾â€GîMz›t×*‚vŽ÷ t6q'¯ø<å…°yÒ®VýÐνòî)RGiΪ#8ÍLº³A»´Á)Îý\GÑLZêñþ¼êèZÝ>ûì³”H’GPŸß›W•YY[ïÖ½kôS~ÊLë9äë—kôÍ«­ì+&í¾ê ÿy4Bï[nydo®¡!¹öùU{}·ÏÿÑoÒwüïøŸVÿ¯þßù?Óêcî?sçÎÿ™7×þ‹­¦-ؽµ¹ô˜Úp[ûïØ§þ®ý¿öÿúϾý±þßó¢èÌQõi×ÿ_ÿ__(¶óô“ÙÄ]'é_C¯½fök&¨¼ú`ið•];škÍFéâ”ap>hkŽ §ü)gÊê}²´ïÏ ,÷ý: ¡ 0çÛwßÔiÀ!åÈã:¥«ß-S9øYu„FÞÉðOåOù“f¢˜9÷—ÈÊJ!2Ï™lÂYa5ÍܧìKiä+€ä^Ù:GCë$5ü[‹^>Ô'÷sþ–×v(_üî×­_âöùïó¿:ÞŽÿÿºÂêÿó#Âêÿ™O§?ìü¿óÿÚ¯b'Ðì§µÿŽMù°íÍkÿ¯ý¿þ_|¶õÿÖÿ¯?kÖÿ‡YÔâ`7üç釳–ÆÕ € Üô—¢-èLÖ€)˜3Zù ®F8Býæ“Ï?ÿ<àLù[±„‡_ô×øË/ÈWîÃ{* 0ûæí7¹? ”×çæß•Qõâå| qÐrõàˆ—Î**u˜?XŸUW‡ŠÃ>ñÝßÉZ§Ö/û_]`UŒ–)»m€Þ}•0é'òQ¿¾ØN¬Þ!!ôùÙðé¡lt‘{ˆ[_çÊåºñ-ß\ã•BNséÏ„òtÆËá/Ï@¹dunšz©ó>ÿé¿ûüÓWÚõŽ]g÷;þÏJÇŒ×iaÇÿêý`õÿÎÿúÁ±=bìü¿ö_æMs§ÃܺößÚÿú‚P;?öÄô çÒ×þ_ÿO?Öÿ;ow­ÿ?áÒúE‘€ê”Î3õñé“ßÿÿÉ&îU€­P+’És КàÚ:«â Ø ã ªäÚ–!ÎSò:ü¢{o@éÊÅ#|&¿{¯¹H‘¯2 ¯,Î@&<-c ?eK"‡<ɦ ÇËkå•§ ¨Á£u’É'­ Û­Ì‚²çzÒÔ _üÑž"O»«2’·ív¥¬Ò;ã‰/´Íß:ÛL{Þi+s÷ óÏïW)5m:L|Ÿ‹3žw>Êè¡—ÞжoÝÄ·m«}þûüÓ_ô}nÎíC;þŽÚñ¿ú¿z³c¥c¤çÕÿ;ÿïü¿ößÚkÿ¯ýÿìcÕ1oÖr®o¥­ø'ñQ.߯×ßãÅÌýú|ÁõÿÖÿÀ¡6çoƒÿŸMÜ *´U”óÅU9 ï+vÒ,í@aˆë¯ŠEóKûö›oË ªòÁ³F»8ÀI_ Kä°gVm‘#ü‡F¼×ôL1‘/ò ïîE6ˆã"y(²¡!Ïûï åZœ²{Vür?<~}mhÆàÇ+ Öðè&ðÒÄ%(cmƒGå–Ö:z5¥{P‰G'OÛq"R7÷‚2];ð(2´§ qyNÃòÖ>Ãî´Ñ¤{=Hyx ø ûüO?ØçõÓÿÑ!;þðV½WFg¬þž7VÿïüoL˜lwþ_ûoí¿ã?°U×þ?6öÚÿëÿñq×ÿ;>,›’=)tlÌE|ã㟮ÿ¯m´Åúÿç4mñô¯fw àäÖŒ’õ:POzÃéT‡F\é -íˆÍ#-@ÊtPûGy0èo ™CßüÍËð;eÄ;ÐYETz –n_@MÓå/¿ 3>g…ÐŽd?,ÀMËp8’5¼È Âó× ]+ÊDŒ•è5rº&GA%9ñ)s;¤4áÔqV^ù2âÜ—FZÊ»žCe/OÏè¥ùJ£ ÷µå‘}è†gÚnä5Ÿt+ÉÂ3ÿð ­6×Y®r•sžÍ‡å†×œ².yÄïó? ¢¶Ó>ûügl¦wŸöh?kßÙñ¿ãÿè˜Õÿ«ÿ8˜¹É\4GõÅÎÿÏó¾¹E»ìüúýÑù$¦_þœùfí¿µÿÖþ_ûÿ{õáÖÿ[ÿoýÿß:ÿÿéGñ‹7Œ¡“½kàL Š~,£€h(5’ÆTø`ŸTº€–Q£ÊUÒ”ãkoÀ,%×0M¦ë~"“ҽǩÅ+Dzàß2ä//g< ÜÂyÍï¬ÞŠ|Ò'䵺á¡>¹¿@×åWøM\ÏÒßóá;€ÓÔ ðUZñuBÄõZ= ðmç–'¾í/® >ÒÞ½?¼ñŒ‰cÔ«ã—¶U¿»¬xäy<ð,ÀTšÏŸ–Ÿx<†?*²Í½²ÕeŸÿéÚbŸÿô–ÿ;þ/½´ú?z¡:õÿÎÿí ÆÇÎÿÇŽÒ ÆÈÇÖXûoí¿ØVkÿ¯ý¿þ=¹þ¯sæ‹ù÷™ã«^óFçõÿ·ýÿìu-„ˆÑàÁ8tÌu€‘9× ÐaÐHŽü’uýEc’nàPqй rψ€R-«eç|ñÖ}}ÍõÈ‚ö.¹Hä$Ÿw¥ÉåÚë†^›‹ÜÊÃuù‡æfî21­~sñÓJ4€”¡€@’{ûû(Ó½xqVf%}ÊR†ý²äk;¤¾øª«ó%ZåY­öúÕëTSýýê,í嫳‘>>ö㺷E®‡FZøLnq©—ëÜ3kþ$"4ûü?ì“ûü§ƒ\}RÖ_ô)ÇŽÿÿ~Ť[Vÿ¯þO_ÈTræ1ócçÿ±.¹óÿÚkÿ­ýO/ê™;¯ùsíÿË–¸æúfÎBuh®ÇŸ“”ùsÙ¥ëÿ1×Óëÿ­ÿÿ;íÿ?ý`^!¬^Ÿ;”ç4ÊõRVò€¬ÌU¡@A‡8n”onÏ=ÝBèmnîüÝ(ñø+s†ÚVn×õ'~Ž8Í—-ýá@_ Þì8ÙW~àðIDsoO¥·þò¥ŒIKæ”z^†gÒ/õF ¤²–º ÅK=Ýw£A+Ͼ›6c¸ Œù€[Úí x)Sþ×Ê|ÀJ=ðWùÛ~ÚXx7éÐfñ/geZ휺Ÿò%WÛ=Ïtî¥%}ÎâRÎÈ‚N› ûü¯Õ„ûüwüg¬îøb Â´ÇèŽÕÿ«ÿÍ^™ËÌ%;ÿaçÿØkÿ­ýW»´ö«ycíÿKg®ýÿè l }¥¾‰s|³±¿CtÍ3ùõŠ@Ï_r4ÿúä‹7²þßñu™­ëÿ?¿IõÛêÿgw_ˆá™«sí>¿®.ebâ)˜rWh£dð‰’9«Xú\iÒÝE>}1¯ÎÍ{ÇÔ#ïÐ •ýãðUÃIF+\´¡››€,VF‰/ ~îy麤£0 (‡‡42’˹å k^ßš¼#:rIÿI“§ôŒ¶÷ï|¾­§6Ä+«Ãæ,(Ë!h€>è“>ô}äm{´<46Î|Q±eºwíN©Ïí)®i½vO†—Wý[¶ò•­:á¾ÏŸ¿¾ÙþѾÑñ³ãÇÿêÿÕÿ;ÿÏêðÑ“BçQ×;ÿøÚƒ6⨮ýwlÔÚ`kÿ=ûڂͼöÿÚÿôÛ“ï}z騸7£F’Žfý¿ø|ÚJHûäê\»_ÿïà ÚH¿‰>m´þÿÿ?üÿ¼BèÁPüu4Û‘4X6þžô™.>èäW_Ï „éôåÓ¸<ø‰·êà“‰f6‚)ýd¾çS®|†®Wó„ÒèPUR€ÃmÓ¡4öxRNÐ rXÉ”¼Ê¸ø)7 ÔÐØŸ¢VþÐN|d¾î]£wï)W Ÿ³:38Ð8 ß|ó &y—™Z/éÊÁ§A>Ï& ˜´IÀ7¼¦,ôêÚzW&4âÐUn<ñÎýœïŸQUFy8 ûü÷ù§Ùøþíøv¬è£ŽµÿG¯DiÜtQõ˜³¥ÿ«ÿWÿ+;ÿïüϦd»ŒÑqìŽQµ?¢/Æ~qv¬ý·ößÚÿó#øÚÿÁör<ü²Ñ#tEuH|˜õÿÖÿ[ÿÿwÛÿ÷Âc(<+ƒß?“(‘  ÆÊ!M¢K™$ߥH(yñæ¼0Z âN ßÞY±3×Q:s–7ŽóuMŽð"Ç/.Ïðw&ß0y€@~ÉÄ_ùB;RúãȵtiYn:×ÊOy'^^÷o~õr U’þ§N©×%gëƒmâz¯ T4‘ç|çîqþsÏùë*.éx(S(M¯ËGzèfâ‹Ó0yÜç¹$ß´óÔïÐïóßç@™ÓGvü;þWÿ¯þßùß¹óÿÚµ­œ×þ[û_?Xûÿ€I±Ç¿¨®\ÿïø…ÚEXÿï,âXÿÿô‡õÿÿþøÏÓç+„©‚!&e@ Ш+”¤å˜x t¯ÆABDÒ<ñBÀ@ ^W^|ÐÌe;ñûqí Eé•û¢ëxp"®3i ùÀÚ(Šð¿öoškN¨øðöÚDö’I<¥=”îE›òˆ\—®õ‘§òˆÈ£-9½â UÞÒ—Ÿû,©š¼^÷R5hì^U|–-*7`ÖÕå-?û^Už–óýY~¯ÐXŠßçTyöùïóoŸÙñt…±cü GÑ!—îØñ¿ú¿ú³cgõÿÎÿ;ÿ¯ý·ößùÈÐ}¾\ûÿ¼9a®¨=±ö¿í[Öÿcc®ÿ·þÿúÿ.ÊùÁž~öþäÍ·ï¾ øÒ &`J–1¨ÇD’H+Peš¬²â)PÖyE/q“teô! /ùðÊfîÃ[yå¥>ס¶LÜ_£ÏÞNà _Á™l=ìÕPs? &€[& Nžæ“¡q¯\çäz×x=œ”áIíy皌•×Y¹Ù¨4@Ùó¯ÊIÛMõIˆsɯãÊ[:l‰ýt ïyRë+Sùòö™È@‘LÃGZãÐûjae{?_h¤,aÚ#ñûü÷ùøª/è›;þwüÓW«ÿWÿïü~òúÎÎÿkÿ­ý·öÿÚÿëÿ™ Öÿ;@5_“Ϲþÿúÿƒš{(FÁó†ÿüì?þÉ%Iººª`‹¸îƒÄ™qo౺ú‰Ó[À„ó{R¯=´&ü®xR9<ÒÙ' À$OÊ™³½º±žx×dQù÷ïgµÕÈIFAÿ}þúÆŽÿÑ}3®Œ ‡ëÿ×½¶úõ¿¾ O';ÿïü¿ößÚ憵ÿ×þgKvn¨#NÿXÿïø²Ú§í´þßúÿëÿÿ×ñŸ§ù§?zÈà R(Žg¤ŽÚÜ'~`hœ1¸€/„ÉÃpBšJ™¼†*ËI«#ØUDq‚&]>e]Ä9¾›UCY‘¤ K&¯ Š»—/¯ÀÔ— ÞÄ霸”ãì˜r8—FÖÿLÂG<­“$6…óúÿÿmüç釿üÙ›wß¾ 0b¢di4ÊEŠ›‹\Gñ^@àHZ»³|ðLP€ùç¼ÿ><Âszé¯gõÏ# ˜£Œ x)3p®ï÷¥‘ÐGŸk4 î;w˜U¾òw&GÁ ² )ûÞø¹dr¯*ò¡‡6Ò¥W¯^E„Ç*•‘ pöÙgŸMmÏÿáÓ²"ž³ÊŒ¼dOû¨ß ”+ü”-¿r»ZNºx ^Ú¿a˜g)/¾9_mB6Ò¤íóßçß~´ãÇÿêÿ£_éÈÕÿ;ÿ›>wþ?¶[ƒ­²ößÚµGcËê£/s}éO÷kÿŸ­9kÿ¯ÿ§dœÌØXÿoýÿõÿÿîøÏÓþÛ¿1јŒ8.@ ¿& V÷`„—HÓMÂÍD/œ×ؼ¢v€Jö¤š³k¼;á à–yoð“Æ@¤ h…Òš ”…ï¹Hº_üP©Ë9ò=”Å\ßù”W66Ÿ|ò(7‡ëy-Ðê,ÁН„)ç”t&#üÈüþ»#w•“øðêJ“9m0€y„¼¾7×VD •Í5ùå xBã¾å¶nyf“'û[ ¢¡ e©òì&±~i³‘eŸ¿}Ãöùïøßñ¿úõ¿ùaçÿÿõƒµÿÖþc+®ý¿ö?ßcý¿õÿÌ ëÿ¯ÿÿ›ÁHÌŽAl·ø§Àž~ôô¦ MÀ’ëÕ<ŽK€™48²@ÀN@•é°@¢Lb³ªG\ ™‘œRóå¿DÌ}òNú$±*J܈Á»/Ÿ†*I÷¥í+…ºÞÍJ$ò]T€&ò ¿òÔ°]y•ÍÌå™<ÊK^¯(ެ^ÝSN¨‹ù[¿0<òKÓðùnÀ,mª<ºä•' Ò)Ðõ½n×]KôµN|¤ã%äŽÖ 4òÀ€e¯ÜÂOÚ¤CÓW3÷ùŸ×V÷ùïøßñ¿úõÿÎÿ;ÿ¯ýÇ«M·ößlc±öìþµÿÇ)‡ÅØXÿoý¿õÿ×ÿ§þ±ñŸ§üûŸ¾)pR#}´ÐÐiG,€ôx9¯«€ä{ñéqn€*î­€²pÆÞ§k¿à‹Ê¯Æ@Ïd¢\‹ïÊ#ü÷¼xº7‘¢Çüý»çUa Ž4dtøÂß„cž_“”'d5Ö­€O¾Ò8¯Y* àÓWÅ«§‡TyûeÅÊ Lºv˜œÉm¯ªLž®²ÉÒ=¯\+»¯(ÊWÚIõ4ÀàUÓ´CŸ6 7tÚN÷nêU¹ñnî²ã/àõ(gîq”'r ~®¿üêË´½Õ[Ý„]¼W×ø8´¥³¼‚Ú¹uogr¯tâñ}Öûü÷ùïøßñOGT'T_Rj«ÿWÿ›Cvþ¿œðÿc?oÙìŽØl‘¹gç¬ý·öŸ¾±öÿ±·×þÿp!Âúëÿ™'Œú"çõÿ×ÿŸ¾Ððßž~ú—üÆ—ñ¨ÇŒ H„Á$œíżvæLñ0d :\7}–­³n(íÛYµdƒsKJÓ9/¡ ¦àñÍðó‹¥|øƒcÄ òˆWöûîÿ4+¿|nˆ%´Hœëü!ýä½þ©p§åãwÈ.@è*W|Ê2û ¢<~ ¨<ò‘ѤŒ¿’¼÷~î¦á¹é0"Þª/«³ðL;Í^Xøj¿o¿9_¼…÷ÐÍ*3úð˜xáq}•'Žü÷º‰ìg¥>Ã,üBg®i7¿ ûüÏžbûü§ŸLÖ¯wü±ãõÿêÿÿ3QΟÿ×þ[ûoíÿµÿ×ÿ[ÿoýÿõÿÏGÿà Á5æìeð† üçé§ÿáOÞ tôÕ3[Þël<æ_Áiö«¯¾ `Ó•MÒ8¿SæÌà+8VàÅxÂ1ž<Îÿ h„)@t€0`L–˜x%?y»R€l)ç{ÐyÕðåúMA~ewOy µ=ö ½sålš²œt€¬ið ó‘å”-¤þsv¯ñԮꗸ¹¯³D–æi™>>¹¾Ëw§‘–c¨Ÿú£}„§¯Q6_Îê9rµœ}þçÙïóßñ¿ãõÿúxõæ”ÿwþgݬý·öRXûíÿøüœñiÖÿ[ÿO ø–Îëÿ¯ÿÿ‚ÿüü¯þÍË^LVJµsõ=d{Z$êúX€,®uJ“–Wà²GÔ¬"\w¡w½±†FÐyD¡¿À|¬F’fiº²äs3y ê4¯µNÙ€þ¢Å°„ŽÒ´ZL^¼qB/Z.שÃ%2ë°ÞeÿIÃK›L&"$o®|*»è;/{k‘Qœ:;-Tc°²O#¤¤“M}­—x¡uÀ]_+´òK'Dþ)WÛûüÏd«=öù¸{íC·ãÿY;W;þ£cWÿ¯þ7—dÞ™¹pçâðóÿõê±7´…°ößüغößö'=²öÿÚÿëÿ­ÿ·þÿ3ØG/ŽÓñðÝùëÿŸ=ˆi˧þÙÏÞpRóšÝœ’ckWÄ¢t*i”³¯³ aŒ‘#s ™æ‘"¯£“R{#$°Šèö®+Åj©¢õʰHzxN9âm\^ ‰ òª”²È§tî˯r²àMÏ:™Ý;‡çä?5JµŽLøMy -#÷ÏÑéxäk:~äH{]™••ûICûýi—¾©Î€A,K£\÷ê!Îù~`+]9i)_Ây¬¨ëþiï©ë>ÿy.Ó^ûüwüïø?ÀŒ±°úõÿÎÿgîô×\š&36t~ÏýsôÎÿ£?Öþ[ûËÖþ_û?>Ïúëÿ½°þÿúÿ'üçgÿñ_ÏXÏ«©€Y^¤#@ˆ• 5!ŽÍ¼€"âJ ˆ$ÎÀ,XÐdèchåå)ò ì>t¹¾ Δz_D‹ ŸòoyxÄÐyY®¥9Ÿ|g…•küħœ9wUøÈE¤C3—ˆÅư¾‚øð¾ä!\ë”64N'Ž¡¿òMðòÚ@Y.FŸûÊ‚Þýã<×­Ë#.©Ït•¶Þ@2i¸: ×>ÿ}þík;þϪÒÿG­þ?Š5sÄ\V¯Š]ýV;››Œ—ÿ™ùg®žcçÿã¬kvÏÚkÿ=ͧkÿ§ 2—¬ý¿þßú3]Ž=õ{ݳ·ëÿ¯ÿφ`gÞñŸ§ýòço¦¯ÄÀ8›£Ÿ/ê!vX%eCq€€EGbֱ̻l°>¹Žñ6yÜ댜b´Ž1Îòámóp=׊#eÈŒ³04• ½òúKÎëW¯³K¿üÒš._q›”÷ËjÊÈà˜³8t‚39"›UIs#kdða>g´ºšæQÖ1Ü?€É<³4¾)ëT%÷‘ïá'Mû½ýúë¤Ùç+y4̪¸©Cþ Ÿ†”}Ý íÑôÿ‘yó*Xêì~ùÛfÚÜsÄïóßçï5âö‡ô•ÿ/;þWÿ¯þßùŸNt˜gwþ_ûoí¿µÿ™÷æ†ÚÞ1 Öþ_ÿÿ5>ÀV¸ûjëÿ­ÿ¿þÿßÿyúÉ|…0£kþ6@ƒ­€•ô8³“ŽF(jìÚƒèQp¤ˆi ½÷ßMÉ¥—ÿù/ÿ%yA2y f`yðéL:°0Cš¼þ6|BA'×´&þ>ÁÔð$sÊ ªW¬ùìçÕòk´¶~òMkDîœ'“´{;à#îFˆ¾Š‰Ÿ:ù¢ã_|º/¿ü2 ÓK+²&ÚC寞ÊS…¨¬¦“ïã¯;г KÈõäAß ÿ>ÿ³™>²Ïÿ8¬ú‡~¢´?ïøßñO‡ÕyÑEWyèë¡1–VÿOC­þþØùÿùDzÿÍÆˆYûoí?6¸yeíÿµÿù7õ¿öÄúì®õÿÖÿÿ}÷ÿŸ~üçô†sêÝtB 4 †ˆ3¡˜X:`ÐÜYéîóêÛÌàY>òõ^œF—çõë×9ÛHÝ}ø¡<]Ëkß&A¼àÕ–8N7À ŸC{^gðÂðûuS÷(Ñ P âª»ÕP)÷v\+϶GLüy}äcñØ­ôæ ­ò'®áNÓ¯+âïõn>{aåßäK†¯ ýÊÿÝûw ÷lîªy>sî¦üxk‡# Ñê´gà ÿ}þ³pŸzOÇmúÅŽÿÿ£ƒVÿŸVÿŸÕËæ‡`^q½óÿ™«;?×ÎéœÆš?;ÿ¯ý×>²öß÷b—kµÿ×þ¿ÿÀÞù%þÏú™>:—/ëÿ °þúÅï«ÿÿôƒÙÄÝ`¨QPh@”¨Là§«ÄÉ×`ò‘§N¯w»Ñz†0dÌÝæ@ëËwÞ‰G§Ü»Â»ï‡Kã@ùµà„NÇ.å]ò’[>ô©ßUÇL’ʺxŒŒ^•$ûo®¯¯E¾IÂËFsò~ŠÌê72 îQºÃÏ«Œ‚<=ÚÖÒžÿ}þíZéoFÛÅžûÝŽÿÿô=¢/¬þ¿^5[ý¿óÿ¨ËÎí÷¹–u¿óÿÚcl=ú=ºößÚÿÕúÃÚÿëÿuÑÁúëÿÓ ëÿÏ¥Ÿ^¯¬ø uD2XÆÈŠsý×d- ƒãÒkô®½ÇÍuüq#¯ ®Æ›_oïÁj)ˈ#Þ“O•ÑÙý«YÉ…—àÞµEÊ Y‰ÕÔSæÈÑW ¤3LVdõµ=yÉÖ=ð%5Ù Î\§Œ«>àúÓ:’ÝáÞYù®+/r¼•ÕM•£ 4-K]‘…^hZn†à´j£¼R‘_hYm[ñ‘kdžÌ¹÷ùïó×_ÚŸ\ë+ú¢þÒkýÉõŽÿÿ´þ°úõÿÎÿ;ÿ›;:aí¿µÿ¦#dõf:Åõgíÿµÿ×ÿ[ÿoýÿ³€È”¹þÿß‚ÿüðÚÄQÁáj`}²úÄ_iC[§Dž3@(¯Xpf¡ƒüCÏXI~!Oã2b.pÇ «¼÷.ß•˜‚OÂäÇWÞ:ËsóÉ»¸äÍëˆÀ¨á÷âåùò`^3pJP~ëåþñºÝˆUù¥´òŒŽ‘u=éäQ~øe‡æ*'<†®m)Ë~¤qôoüÕ[P_á‘wxyï¾}—U Ê–n°¶½<‘vxö,N(¨p-™„žÉÖr] ççzŸúÏ>ÿéW?ÓwÚ]ïø?ãë>–´‹£c?i;þӇ蘮h]ý¿úçÿÿýð¸ößõ£âÚkÿ¯ýÏLਬÿ7o5­ÿ·þÿúÿg±?ô±‰ûÝé:úb¯y­îôŒß L È1ÊD0˜8ôœgi®&hsî ¦òwVðqì0áüÊ+Ÿ} *Õt¶–/"æzÊâü}”Û_l@ߨÓÝ}Íò#Sê»ÉwxÎfð“§åt9€"«Ž¤“-ò#e’ñvICW°'é'¤Ý枓׹¼Bpý©Iš÷Ó&å§!Tùúâ<u*ù„Þ_ìeÜÓ›æ|—«×â#Ç>ÿ}þÓWvüïø_ýÿЧ«ÿwþßùí¿µÿÖþ¯ïÌn®½¾öÿúíõ­Ü{йiÇÀ>ãwMJÚúÇöÐ.ëÿ¯ÿÿ1þóô³ÿø¯ß::ˆ@éö:Ëytœk°ep¡¹V”â:]àšÐ¥Ã]¯ÝM|W=h‡gÁ"|›ãï‚Xh¤<ŠlSH¿@øâÎÈ=³æþÓ ª¡—·õr,ÃÓª-Qù—ι×À«€sžÙ«“’zD–©/9ñpHw¸n]‡ä± }®oi-ÛX6â\ 6ºÑâÛ€·# ÖDVé‘í"ß´ÊÓ¼H>ίŒÒïóŸöÞç¿ãŸŽÙñ½`–Xýtoõäê³þÌ;æª9wÎñã‘{ñ;ÿ_?L{ÜçôÿO{¬ý·ö»´¶·±×þ_û_Ÿ¨Žt9wý¿øxÚãcÿm¦—õÿÖÿç¶&Ôs£¿ôÜëûÏo›ÿÿôÃÙÄ]%M0TRDY¸¹‚Ée"_Zq®UÜ+ò‰£tÊ·Æ+6å©ÑÈ l²ÚKpïÀCã¢w¶?”³räŸÆžý æ”ý¬æÞøõ×_`,â+ŸÃÊ­¾¢Ø‡ÉIÅKzãÈFN`[ó·näM›ÄjŸurL9yâ*¯uÖákO.<?e¶·‰{„‹6õ>ò ‘ß©/ù+“4ü*·:LEr?5~¤eω‹Vž´áÐáãx䟴ð@t…ÔuhÅ—Vœk|öùïóßñ¿ãŸN¨Ž¤VÿOŸ ÛWÿ?æ”Ì}Ó&úÇÎÿg‚Ýùí¿ÚZÕkÿ­ýOG®ý¿þݰþßúÿð…õÿþóô“¿øÅ£À… S°Ì`ĸl\Tò«ª×ð4¦UL£ÐÏžT.ZGùÞÏâ)ŽïfϬW/ϯ-Czý—ð @2{[õ•ÁðãT³ñ×óšàË/³*‹ŒXî<½J˜ 03¼K‘mÚ ØŽ)S;X¹Ei¾ H†3¹ Õzâ“z /×\Ë_º‚YÒÑ—§si|9Ï5y\kó^Ë_¾¥k‡ôÑJžYiµ¿ÿÿ3rvüG%Dç¬þ_ýo~Ùùÿy®žÉ3sûÎÿc/®ýeiŒ¬ý÷l×¾¬]»öÿ8Öþ_ÿ¯>ØúëÿÓ0…êI}#þüúÿÙÛœ/Vœ¨ñô/þôGo8ê ®Ì(xèX 4`޳£lRút_!BÆîÜ„®KÅÝü:ù’>eã%°¤|‡ý­J+½e“Ó}d˜môÚàäJÛå~$™´¤<èí¥•ú§ä<ÒåCß‘}ÎÓm³Ê¿Ïÿ€ûü ½ãÆãJA3chÇÿêÿY};ú·úsõÿÎÿlÿÇ›q¡-¢3×þ[ûoìO¶çÚÿÏ[—kÿß³þÐúëÿñ±ÇÙ]ÿÚŽ€Uü>øÿO?ú󟿱r©€ß« G€Ž™@(+r4 :€PÈ=CÜ$#Þµ¸FîO8`~ö®b )s€`Œ|-/€Ö¤·¼–á^Þ¯¾úê“Ï>û,« &SòYR'¬¥/¸òrV*á-¬yî PüúþÈ~SÖdK^ùÚ•? ˜zœÊ WŸCÛÀd•ZÁ3õÆÃž]Ê!O@¨97Í™¼÷à^< Š<‚Él"C«Žï&ž¬÷ ¼¶oxkóÖoŸšjŸÿéSúIŽ—ö}}gÇÿÑ_;þWÿÓ÷«ÿwþ7ïü¿ößÚkÿ×î^ûý?öòúëÿ¯ÿÏüCã?O?úåÏߌå‡@âà¼6¸çØûÄuÚOÄò‹À¤În«$C0åW*¸´üRöDˆÏ`¿;ÏgEÇ»÷^c™æÏ/¾øâ“oFi6qÿ„v®É@žÖƒ¼^”°A×zC|ë[§•úñNÐG¶ë\ÇU^AšÐvÈýdUgξÍß_ÎYº4qê¡í*>r*ošÊ"¾ü¥åµÇ‘ƒL•SÓ”wùHŸÈ<#™ò„ùÑÉ/Ãuƒ{õÜç&"ÏbŸÿìG°ã?ãÂ8éø4n:Éÿ×—^G‡¬þ_ýoîéX1n:G™mÄ;:†œéÙÿwþ_ûïÙf^ûoíÿÚékÿ¯ÿg]ÿoýÿú¿oþÿ÷þÓÿóŸÓP —æšAi…O6FŸø.å-‚FƒuÃôÏ?ÿü“·oßæë~Î5Fѹ.xâ¨cõQÚ¶4êÃW' J“G¯ÀН ¢ûÕ_ÿê“ׯ^ŸüCsÉŠ­{(Ð¥ O'åx½N›r#ÄÂ@IDAT¤|×׊,HúD¦¬=6—÷*Zqá7²0ÊÉWKÙÒ”KVeÆ€Ÿxí èë‰di»Êãðêç h Z|\£s/Ý}ÏÒ•'Hw-ýEVÏVc©ÛyÊ¿}þûüwüŸ™;þϫܫÿÏj_zrõÿÎÿ;ÿŸæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—0WÖ79óæúõ¹Öÿ;>î8žëÿÞ0Nøçp•õÿ®ñ_ò+ŽÙ4œÆò«ç\<× ¤”#úJ“²Œdcñ9ß›aý@‚¾¢/OçÊàÚw(»+•¬¢Rþ&K¯ ¾È '›¶Ëkçˆs/”Ää”.NÀǵCYüIh@#éBÏõpxÎþXSŸÈ9_Atv/àõå—_†½ iâsž{ôÚ웩 YÜ[]¦>øãh(ë&«(4£摜6+ø¤_õòÌа:©“ŸÌÚöÊ7ù‡Yê6e’ù/ó•¶ÏŸ¿>ªìøßñïúÃ=D/Ný±úõû†i¤sJûFV¸N?Ñg:÷ìü¿ó¿þ±ößÚì óËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï¢ÿÿôƒ_þì à#TÙÔXÌ4Üš,€*^×Ó9bT ÒмiÙ?ÊyL6âî 0Çž:Ž{^×½/ï:;8 C¯œ/‡\ #4ú®È 3 ÝTZ€¯ÍM°âÉ$HFüÎö¥Ôó€Vi‘ð•Ÿ|è+gx^ñÉ8Äáå×y›¶»'sh'ýÕ«ݾ={bi›é¾«¿Äë|êw¶óZ…ö ¯¡O{;_ VïÔÒ+;#äY…6«¾ðíÆôhñË*´y½2ÿtpååÏ>ÿ}þ;þwü ºúÿŒ:wõÿÎÿ;ÿŸW‚c0°.ÛÁøXûoí¿µÿ×þݰþßúúÂúÿëÿ×^ø‡Äž~øg?{SÆÎŒ‘ìý4× @ g^tt?§=ƒvˆ„@+0¾þúëð:ÍE-BGð hAï^çNÚ¼ª'¤ü‰+@ƒg—äúeÿU^{ûõ‘eî•A¯ý½|ùê€NÊdÿ™‘ J4|æ|Œ¬ó:dÊþÊ4éæ<ôh#ÓÄ d”&.m2gõ.šÆ;?vdÔ&‰Çc.Ÿåq³GÕ$x]Q(o²;Â÷°iRÇÈ<1Ý@¸N Ê/¿I/üWy1’wèiûü÷ùïøßñ¿úõÿÎÿ;ÿ¯ý76ÑÚç‡ÞµÿÓ¶2Û~íÿõÿê;­ÿ·þ¿¹býÿž×€MÁ_þžøÏ|…ðÞPº@  FL@‘‰OÁs °"ÀÅu˜¹€WV4õ>̆ÿ*øQfe’³ ‚¹^%Nª2ä-Ø“=­.ð`¥üɘÍ9y•À5¯ý%ßä/ WÏžxÊŽNYdÖäìy¢?h÷Ÿ¾˜Mßç_éðT|äó+ˬöz®ÆPÀê*|Ä“_ð0²LIóŠ$ÞÔg¾Bè^Ýt¿zÅÉ‹Y’†÷Èè>eOzeEKÂÞïóßç¯Ïè?=Ò·®1âz:ËŽÿÿÑ)”ÇêÿÕÿæs×Îÿ;ÿ¯ý÷lï­ýã2ö%ÛÛtíÿè˵ÿ×ÿ3.Œ‰õÿÖÿ_ÿÿúÅ`ÕYõ…“LŒ‚?{&^šÐÉy/y91/¼ún6÷+-#Æ9sÀAÞHîP&øÇj¯@)Çq'¯ÿ}þWÿÒ/vü|ÇŽÿét°úõúyæ;ÿïü¿ößiÖþ[ûŸ^<>ÉÚÿæ m±þßøg×GÑÖÿ[ÿŸ_±þÿÁ Î=‡øŸÁ`Q0³@Fîç‰Ò¢XýÔWù²Á8 èRÒvlšþêõ«6J«À þ€–€+sýéÓy49æº<åå.¹œ{ˆë †ŒÎS`båí*®D ‹ÉýØ?K:ùäV½'Ÿ¼ö"“½±Ð4BþC'Ý5¹Z/qî#“øY †·ô¦õ—†Žýº€nÚ¦õsVkÀ`¾”?qå¡uð-ð%OÛ+eÍ=Úü½ŸÈÜOÜ#”æ·ÏŸ¿~¼ãÇÿêÿó# }¹úV\]ó•¶ØùçÿŒ‹µÿöÙÚkÿ³±×þ¿VÖ¤-Öÿ«Æ7[ÿï¬^×9.”M‘c&í%ü 5±?y£kù¶“Oˆ}Æ/¿h\¬ÿÿ»éÿ?ýä/~ñà éj¤vAÇúx–ÎÄ¡q²0™ûJ °"?¾í éXSVÏÒî´ý͹öoK—ß!äïÈÒQ_|ú"å¹—æWA/¤"‡½¨V÷€™ËS}»Ê Æ99ÐY0pZ7÷èMʸË^ž§´¦ ´Oø¥=ÎëhòëÝœñ’îÞÏßXµ6u10 Hÿå’žø<&}î½®‰°¨fd#ãU†û}þûüõåÿÑ&Ñw;þŽ¥_VÿýºúÿŒsÆÎÿ;ÿëkÿûkí¿µÿ×þ?þ‹yrý¿ñÀâ³9sý¿³Øƒ¯É'®Ï©„žssÝ‹k|ÏÒå¯_Öºõÿ¯,Ó>žü¾øÿ°ÎÓ5¦#Íkd^_+à1]%«¥ò*Û¤·óÙ Ê{»î­"–\ÌЀéWï:ˆ/@¥vÂdž?í¤ÎÚ+±inåËÙ¸#>ΰÇk{Wç÷0PéàCóÙçŸ}òÕW_=~5Fg0Õ9ÁÃÑ&^~¯õ„ùÚ^ï¸{”1ùG Ç=Y*ãËùâà$¥|<åyúôLöhÜSö€ª‚cœåIW¶&õÅÄÜ_ò(= Jü0J³’=÷“®ÞÃD`[°+Öþ[ûoíÿãgÄξlyöulj±²öÿl‡2>‹y”¯‘öYÿïø]WŸYÿ/Cæô¹ÔG}å$=Òîcë`ëÿÿ>ûÿOÿâOôætP¾Ñ¿Ó5f9¸ø§yÕxR Å* û-y…€Rò œ§½ˆNç+`dp6=Êkz ÞèhO™é¹¡-Îz¿vßÔ‡Ï\v•€wJÉþŸ×/ù>–ô~ñÅ±È Ô¡iPor7œv8@ַßÌòà—º½ò†ÙC¦¶)YÚ.~#ƒô{¹¬ð"ñ%+Á†ŽŒÊ)XÚ¡ #>òµÒžWAâñJÞëIÒvVÛ¯ÊûüÓûüwü_Ã(ý¡@ÆŽÿÕÿôéêÿÿwþ_û.¨ ¶ößÚÿcŒÇ¯M½öÿúëÿ| >êúÿëÿÃ&Á+‚9Œ·5…>Ò~Âÿº_×s.þóôÃ?ûÙLÉ<À €Ê}ž)*9Jg¹4„’þì³Ï‚°( H4ñ½WXâ.à »ð½vÎß\æO+ =òM“vÝ{ÈKVk‘¬$"cùÊCîÐÌùóÏ?\ôácÕûóoV'ͽ=°ZGõÖ:|,[ò^r–oen`„ ÚNšv"¹n¼ry¤£7$Yõæ¨*ƒ³¶«lÎBÓS¾ô¡k\Ä ­C¼ûü=å}þúãéWÓó¿ýdÇÿÑaGÆVÚ‰î¸]_S¯'mÇÿêÿêy}cõÿÆpþæ2>c½ßùçÿô…CÂÚkÿÑ«,·X±kÿÿ ýI·®ýÞZÿ/Ý#j×Ó§ëÿÑ þ­ÿ÷Ûàÿ=ýðÏþFÇõȬNª!©SgBÃÒRa¯ºouèâu<ù¥¹ç 9e¯¬‘&ŸWèœÝ¼‰12ô-˜†/¸®ÑEºð7‘Í*/r4ÞÊ,@9]¦ªÄ²Y¹×&ÕmäµVVZàsÖÌ$é~Q™Q~Údø?M=„´áE‹®qdlûTNƒ?õºbÌ5ùåwT~æ°eاìÉëܲÀ¸™|his!ý@2C2ù*ƒ8¿04¯”@³fJÞáñå—_ÄR6P«€y[wgåœÝ÷¡é›ZÞœiÒ*ù}Í0€Ó0iÎÀ¨ðœöœ‹l*ß/¯vZNkäþƒv Õ³q§ÐüWrÚäž}yvÕ•{2ÜéÑíóßç¿ãÿìûgŒ8vü¯þÌ7ÓVÿïüßù3sñô‰ÿ×þ[ûï#»uìÉ3>Öþ_ûÿø~üú$ñKÜŒþäÑÔÿï¾ç¬ÿ—öÑ~SÓ(ëÿég1Èúÿ¹ûól!ãl®¥ý¶úÿO?ø÷?} çfhQ±îu¥²îí)åÚʪ6DÀLƒA$ý~´ÑLèI¿T÷äpö•@+¾¬KøÈ|w˜²I ô~E<‚r<˜ofµÕ«—¯ûå˳J ¿¨:Ü”ïÚê¬tü¹N˜såït^STFî‡ÐY¾÷ïÎê³Ôñâ/ndk{iGð*+Ö†Fã‰ÆÊ°Gù‡¦ôá¡Í†Ne9‹WEßëÜ_e¡ëª,ñ­¾îÃk®×ûü§!ní´ÏÇÿŽÿÕÿtåêÿ3?f.š9cçÿÿc8ÌŸÚ>'ÆÊ;cí¿³²S[Ôž[ûoív&›{íÿõÿÌ©ëÿ­ÿŸIsô‚G×ÿ?Jm‰™~7AÇ·+®¤·ŒÊ‚þ»÷g5QÔ ¨V@ /+Íð>©|Ä%ÿ\[õÌ"kÚtê(¯rLVÀ@Aš€O¯É%$_Û`3õ°É¯L¼{ wvv-â âç¶›ë€gßÿû öùïøï˜Ùñ í`|Ð_´ =âzõÿê}CÐ?Œ›ÌAsݸέé?¿óÿÎÿ,”ö gúdí¿c ®ý·ö?ݹöÿú|Þølëÿ­ÿ¿þÿÃÆ4&ž~øËŸ¿¡(TÜ¿~ý:` ¢6ˆ§ñÞ ó|Æ•î æÄ,w.‚þ¦Û61œ!F/#øaÐ\ûñ0x'‘e|hçºåU®²E§¼är B|ËÈ„0u•W=ìa¼)/¼åW²h‡{yÊ@n×c’g¯æÏùÐ.œÄÒ~=+ÌxMYÝ'Ì}Œÿ¡Ìô¸Nzy¦ý¼:¼Á‡©<ކÜ_7i‹¿…FrʺÚuŸÿ€’ó\ÚÖûüwüïø?c¢º1úgõÿêóº9ìš›\ ;ÿŸÕÐ9{çÿµÿ®±1ÆVƈ±²ö{>Í‘?µÍ×þ_ûŸÍEv?æø/ÆÎå§ðY:ßÔ.yô$is$Ïúi–´Å\Å'ÔŽ·°þßúÿí¿­þÿÓOÿòßÞäá•£B98Ä«ä]i¸×ù›/t³â‰Ò 3<¬Bc%TöźO’Bæ>éÀŸá÷sdzºIy†®²:ôîñòäõAFÂÐù÷½yÅ8Ô•PŒju(¨ööíÛÚ­s ñ(ÏM™”&è‰÷ßUM—¦ŸÜK+ð¼êÐ:S²®½ŽvÊ|nO¼Ê#?røuòŬn©·•giÏòˆkýð(Ï;¿^ãÛç¸Ï&Ïi˜>»}þ;þwü¯þ§+WÿÊ\o~3§tÞØùçvÞÚ϶[mˆµÿÖþ¯¾dóÇ6g¯³Ñ×þÏâí³þß™Oë«i“×ëÿÖ WµEûÌúÿÏ‹WÚg¢c¦Ú§z_:÷Ú²vÜo£ÿÿô“¿øÅ›VLEZYF©{l\•L:Ídjºý£/YÍ4`QãMçò&ÿÜh¸Êì꬀-C—!k°ÎåAë,ÝÙ;ÁEæÛ‘ÅÈWPp%>ÜÔʰ‚W@¨Ï^€®òþš_L³ÖðRæä ÍœñW~Ó´¸.{ÿöÝ·§îbxµ íreà†ÿ’rº±û½L´ø‹ó<òã´‰:uY)Þá1´¹ž3úð¾®ç”ps]ÞM'_iöùïóŒãé+ÂŽÿÿtÌêÿ£Vÿû`çÿù2ñ„ÿg5ûÚ:3w®ýÇÎ]ûíÿõÿ2Q°§/ß6¾Ûܯÿ·þ¿y‚ÿMOÔ—¯¾þÿߎÿ<ýðÏ~ö0âÕ@Ç 4ÀI'^†º  l’Pi†—ÆÁy×W݆&á:¹îƒB+xÕïŧ/2ˆÉà@C ˜à~þ$-éW\âÍ“Gº üòV¯ÊFV¿z8*™åµWUdW·‰«!V>hUâ]÷+‹ò;âÜÀF†ò&K_«'ÇðwFò ¨uÉݺX=†ææR¹Ê§èlpï^˜ÒÆ6x¬Äµ¬ðCsk·¦9«öùïóßñ¿ãŸN WèºÞp¬þ?:uõÿÎÿ;ÿ¯ýGO®ýwìʵÿ×þçÿÔÇŠµþßÃ[ÿoýÿüïõÿxD±•¿þó}à…ðÊ&壈€T&h›œkxq}-нû¹¬òê4Ð˫ׯ§<ðiÀ_p– P†ãÔøó¥ÀÏ>û,«´†`þ ©2XhҬؒ^EŠGÁ¶nìN6Àüò)[ÝÝ£½B®ÅIky­³|÷8Ž¿ ìÒ·x´ñ¤ÌòŽöÕm·¶ÑÉVŸÅP&óÔïûS?í£ìb°0iÆ5Hw|¿kùZæ>ÿ}þúËŽÿg@xÇÿêÿÕÿ;ÿw>§Í—‚ùS¼ nçÿµÿô…µÿÆ>¿¶ Yûÿø1kÿ_ÃØp4ÔGq^ÿïø×Ïúcý?ýbýÿ³¥cýÿÿ:þóôÓÿð'oÆ*Ë.ðÅ`²ò©\Î×¾T5äš&¯8N¾ÓàÏ¿ÞSZâ˜&¶Ðͽ€f£õ*8é)cHÈ‚FœCW€HÞ‡³ie^“~—Gþwïç+…“þêÚ˜4ò˜ÐôÞj¦8/“¦L€‘³}²€r}… M™=ãc¯*$òõW*Ú¦ZùZ~ëêK®•`JY“•¼y5Ò_óO䯮ïY „‘ Чpñê“ôáI&{¼(‡\ûü§ý÷ù§ê‡9vüïø¿ô$}Ó~AwÐ#ôÎêÿ3÷¬þßùçÿc_Ðô‹oí¿µÿ2OLÌ!kÿ¯ý¿þß™/ãcý¿ÑóŸ/Ú6Ñ.Býf×ëÿ¯ÿÿô¿ý?xãëƒöŽÒ!8îcqd¥¬šAÅssHÈ4ts^t2ËÁжóÉÃ|éê§tÄÉÓ•Qhñ@Ý´y›X!›C\伜)ùÐ;ëìÒs=´5›úÊ Cêãq ?¯èÅкêSù¤‹w²9}ʘ²„¼Î÷t^ïs0 P5×è"Ûµú+åœgúž8mÕ2'\õ@+´^½Ÿˆ€h^¹Ä?ñò\ùÐ?hÃaä¸öíB¯þd¬bSŸ}þûüwüŸÍÊchÇÿ|IÖŠÑK§Ò«ÿWÿ›7:ìü¿ó?[‘¾¤œ×þ[ûO_ #Ìkÿo²öÿú×ö2yÇ$:aý¿ç•y™CÌ%Ó.Õôˆ°þÿ8ÓæÚñç×ÿ¿ýx6q×ab€Ì„cÿ'©@#UzA‘\—åÂÓáÐM†ò݃ûtÌ‹§ë8Ashr­ø)0Õט²jiò(Ÿ.Ÿ×óZ!yð‘Fn¿x7ÈKõð?Ø”}ˆð¹‡ &zÔOz?s\Ð HhâÐ…ÿ0€’Çxr}1­ÜöJy“׊6ûW¥‡–졽–]W¦”O†9ÐôPvó’KºüäAÓ|÷gUx£‘_žïæ,$ÏÄïóýÚ&¾d¹ÏßJ¿ÿ;þWÿ¯þ?3åÎÿçUãÿÇŽZû/¶âÚkÿÇ ž?±é/Û\{ÒܱöÿñiÖÿÿzúlý¿óÆÏúÿ4Å ñ?Gg8×÷w^ÿÿüHö1þ“MÜŽú€2* Ç€D®­Ì¨RÖÄ6÷3 ó'­¯¡ûòÊÚ-ÐS¯Á5_ʺ¯L@•IÌ ¢4sÝ3®»Ãê,tßÎ+Ù·i®«B?@•V®í‡•ëÉ(ëׇÍ#¤s ð%ý믾z®ËPàAN4©ßÄ9‹nÍMîµ8P-t÷|ê-¯Ä·®Îw° MÛ.m%bx5ÿ¶‹2+OËj¹ïG­Ðüp<õ°òêJLø¥ûüÓ,ûüÏvüïø_ýæ¶êÛÕÿ;ÿïüï—òµÿÖþ[ûíÿ™ÇOø"õ7Öÿ;m¢=„õÿÎ|_sú {JˆŸ:mÄG¯Û3 ­çXÿýÿQ.ÿyúÑŸÿѨx ŠCG+(âWW÷] ¥CQVâuàU÷­‚ÆQžé𓞼VFMP¶ÕW‘ûâÿ4Wž_ϲNŸ¾ÆÓ†ñ_~õå'Ÿ½þìä½ä1ˆ(ÁÊ¥ò$_CÜ£îM¸Îd°–_b”E¹«SV‡Ýhñ ß‘÷´ˆ{–Yâ-´\gÏìí7o³¤?÷êØ:;Ëý¶W>>ûü÷ùïøßñOÑ#Ñ·£;VÿŸˆ«ÿwþ7gîü9¨Ó솵ÿôŠã„±­Öþ;?¸®ýúEÿ®ý¿þßúÇ®4o¬ÿ¿þÿ?þóôó¿ú×ol¢§cÅaÇ%û=q`F: < º õO¾'{’6éø Ü›Ü[†ë‚,:sçžÀËä Ðs•#þË/¿œ/¼Œo¿þúÃò‡^ySXöwÂOþ–í,¨ƒø®D­C(èƒäHw­ ­ú¥œY¦ŒZò¨³Ch½»'9ïí¢ëÏiwMÚO¯´Ù‹‘5fþ ŸÖMe@'¿ýÅ®zDÑS­—¯^Î+ûü÷ùïøßñ?ºŽ.œƒN¤"Vÿ¯þŸI$sÎÎÿfÒ³•€yuçÿµÿÖþ[ûíÿkÿÐÑ~ìÑŽõÿÖÿ«¯\ÿT¿¨\?•ÝŸö:¯ÿ_»{ýÿÿþóô¯þÝOßèHtðˆã2Ì=et¾\w€t^EÓár=dybP2ù Ö8÷ºàKò\`KãœÑUé1Åõ^y>#É™ò:Ë?ÿçÿ<çoçúÕ«W‰/ß–7™± °ãÔøòá#?`J]ÔU0Ø~õ«_ål¥”°¼”Qåìºѹí!¿²ðsNžqí*Ž § _ÀR:iýò£x|Û6øÇ™¼Úª|ÉGÎæWެB S®úºI«lÎÀ+ù÷ùïó×ßvüïø§{Vÿ¯þßùçÿµÿŽ-›k쥻Ý'ní¿µÿ×þ_ÿ.XÿoýÿøÔëÿcÐÁ#ƯŒ‘|M¡‡yÔѸÞÿ÷🧟Ì&îˆ1†ä¥: Æi¥ñ…=¯çÙäZ\Þ!¡#xŸ_ïƒWéåi9ýbŸt€Œ4çVêâZy®å#GyÊmyè²AùÄÕwF'ß4Üd–?aÒ€;^u|ñòÅ'¯^¾Ê5Zùr _AYò·Ž4»I,@ÓÔÝ?«¬ä´W刬“–öA{µ¡¼Çaxþä ‡KŽ{=ñµß•8Îfêx iêÒ2ÚFhŽ1J‡&u›8<\ïóßçßq¹ãÇ?="Ð Õ«ÿWÿïülœÿ×þ‹n¹ößÚÿkÿ¯ÿÇNZÿoýÿõÿÿiðŸ§ÏXÀËáMÆ@g `€B1‹wÄÁ5HYC7ò¾æ•]•9Þw@ èòéPÒ­þ1à9ËùÅâ”)¨²LT–£:?d›|¥kYxTV´Y¡5töœ:PÒì蚂𣾗¼äa”þõ_ÿõ'¯^¿~ÔÙRØ€VÓLdÖdqmcyuöN¼Ò&­²V>´>Š.í;÷á7|}éÌç1•#È Ðroå™kA›¿€¾Ê SÛ¤Ÿ³¶K^üRÖõÜ>(gxîó?ýqŸÿŽÿÿ«ÿWÿïüo¾tìü¿ößÚkÿóMbCM½öÿúëÿ­ÿ¿þÿÿZüg^!üÉ“3às…]°CZ"ñ@šîᄦ|йu…•P@¤ ú‹6«ž.àGÑJî^ouaÔ øÊÈýîýùbã)ïùõ½(åD¾S”U¥«% ‰lY%5ü]¿ -ûW EøNœ/'ÊðG>´À—cÑä¹xjk´Ú–¾í²Ïÿ´ÿ>ÿt“ô}Lÿh¸ƒéD;þwü§kè#Õ#"\¯þ};cdÒêÿé;ÿÍ´óæ úaí¿ó(ý°ößÚÿµÕ×þ_ÿ¯¶þßúÿëÿÿ·ñŸX0Âa ¸q9!QC|‚ûãüÚ¼ÜûŠþ=Ò‡_«{ ø8)øÂˆ±äòÝ·gO+ôV#yÍ ­ƒ±ƒg ^°ápdpsў˓O^A^õžÌkX¢ë¾Pß|ûÍ#oå ¯ ÐJ=€@ÂyµÑkzV¨Á>åÿfd}´©:$î´¡kû^ Ý£JœzšÌ„¬^C7ååNœvU¶ø¶¹¶ÁC¼sê=çð½Îáñ݇²‹Ûçï}þÓoõÉkÜ¥#NßÚÏœ§S‰˜þzõ¯ÿÑ;þ~Ó_è•Õÿלºú?óݱóÿ±vþ_ûž\ûoíÿÀ˜lôµÿ×ÿ[ÿïá³ÖYÿýÿÌ•7üçéÿçÿþ¸ñé|Õ®{#!×`btŽjMTœØ‰Ch‘¯©s¤õÚ—îäøph€+V-å‹‚šñ–ñÒQŸ>W Ž %Þô0U:Y¼j'¸œC×à^¹Î‘yœj<…ÐÎYºC:YÞ¿;«¾¬¬g%“ÐWå\‰—^9»â my’7ד' ÒH©Îò•®ù½æ×jÒ­Cû\›ó¤òToß¾MÙåÕú(§¯0â'}ÚrÎäAyæìH#O@7ü÷ùgŸ4m·Ïÿy¬è³;þwü«ÿWÿGL_ðÏœ²óÿùñjçÿ³\;$\v†ëµÿÖþ3¬ýü„µÿ×ÿÓÖÿû2þ瘱%:.Öÿ?S¨¿p’õÿO{ümøÏÓÏÿêß¼1¹äЉ⬌"tuøÆ«ÿC¨çó•XPŹ×h¨ =ƒ7Ê€. ”—r†0k¬ï²š Ô‘§üÎ;e\²’ÏÈLTrNh>éÿ{÷¶­Én\z“«û úyl™Ü"7%Ëý"²EJ¶ûÒ=F]ø¢_Ðcôcx¨Í}¨ªMv|9ÿ•U¦:¶Iªr!H 1dfƒzÛ ÐdדvU. ¯@ò‹)y„Ô#¾ÚZùÚÆÖ«öž+çÜ¡üÛwoKoÀ‡¬Up}DP,½÷Dù´ ê«·ß͋蔶IwPnòïu*°¢(Ò†KeÔ¶|[WúòpïÿÞÿÿ;ÿGQ¬þ¸úÿ¬¯–‡®âžïú¿ë?;¢ïãdsø1mí¿µÿè öfì̵ÿuGlpºsíÿõÿø¿ëÿ­ÿOG®ÿ68Ým˧Ÿüâ«7Œ Á#y'ruƆð(4Š•ãò t|ø¨ÑÃh½x”Îå(@ 4n€EèÍyùbaœ/ô`BïK~S¿sehMÝd"kÀ—)Ù“o‚z»£ê.SÏÈÜhmáF‘…<¡úx”Ç`WߘE&|òᤑ‹‘NžÐx!ûÔ䛽Bx70èô%:çÊ8RÿðÕný„§ú|¡½x+yFòÈL îéiã\¨ròtÊ£œCƒnïÿôûÞÿÿ3/̽ÿ4ÈÑËô…@g8è:«zÊeÏK—ןæ­þ?? ¬þßõ¿óc×ÿµÿèÒµÿŽs¶öÿÚÿëÿ­ÿ·þÿÙ´³þÿÿÿyúñ/þ†A¥–ÕÄwCÛ[dܘCÅ—É»ožw3ʹx!â¼(û8úæ›o\P€Y@txy4°`Š|áª-çøÈF¾Ê‚Fú#ÿrBÃ÷–~<® 1'vˆÒ¾‚>ΕÔA–¯¿þ:1ÐÍW ,¥Ž¡Q·ö‹ûŸ¼óŽ FÊy§Wx]Ú¡Ý×y@°FùÚèpM6±zñÍõÈõrd•.Ü_ÿêëì“Fù ©søàí‡ÅСåW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿÿsüçéËÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúùçŸÏËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þèþ(; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi~0 RånýÀ<ù?ÈD¢Ô+ xÕÇ Ý3åÞ`¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ¿ ÿyú“¿úÓ7À4 0"€Vœw><«n*Ó²byèÄJ¸^xän¤ûΣ€;˜OPÎѺ³ã¯ÙÍT`I=Ùb?ôø ÷ú•­,ÎÕïZˆü×âúA=äŸ|SOõ*“º.¥£|ËàYY®=Gßwy¡)Ò~×òË· èS_ÄGÿè4­S¿i¿Çv ¶mÒ¯ÞÒÅôX<ý•Ý`WÚuTö{,ظ÷ÿŒ³öÛÞÿÂê‡ÿ;ÿïú·:ÅØXý~Zý¿ëÿ®ÿkÿ­ý·öÿÚÿëÿ±‘b3?ȧXÿ/®æÃ­ï¹þÿÁÖÿÿ_Þ~ü—?{cb™T‚s•i ª€;“&87;_¾š—pXÒÁ'/@È•~e;ˆb“ë8µ(žbÀþN”*‡@×Úן¾Îµó ˆ> —¢hÛNb³žÛ;…GÞ³;IЗ§sŽÙ½òôt¨£W/_=Þé•ÝVøNH¿\ýæO‡ôéÍÄ9éB?miŸ«Oû{-V®È¤ü€VÃÈ@ÎÏ>û,àV·qã‡<÷¸×­WÞÞÿ½ÿ;ÿŸwxîüÖ¹Õ=ôÄêÿÕÿ?k 6.²³w×ÿçµ\¿ìúìžµÿN?¬ý·öÿè…µÿ×ÿ³n:ØVõÃÖÿ‹Iqì‰Ñ•ëÿ¼}U|ýÿן<ýË ÀÊ£t€ˆuÒ̤L&+É4díÀO‡Vº2- ©A+M`À}ÿý¼Ï©!¼ì"šØ×óððN'“φNj25íûá7R& PFT=Êʸ‚4mx„¹F‹wù—Æ£xvè¯+•YÝähÛõPNŒ·yL0ò͵B þ‰¥ã jòÕÓ´ÖwÊÜ€±)ƒFß Q¾2JïËç_½>àšúê—':òJ—_ùìýßû ½{cgçÿÙ}©/vþ¯þ¯¾^ý¿ëÿ®ÿÇžÒÂÚkÿ­ý¿öÿúëÿñ+ï6’'‡Öÿ_ÿîð·Åžþøßþô ÆŽ Ï[Ü`t˜Äæ¤Zæ?](P”ô¤ H~Aæ•–ƒÇ˜‘€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶§ax„žøKw´^éM ³áL¤^Aœ4és¨çÊx´÷$<—ÁÿcPI_I×o¯²óI;È ðú8`•— ‘cª”öxi™¦Ò:ÁGž¡™—ºµ}ÒÈ›—¯‡àôŸ:µ ;×ÚN´ê· »ÜÞ¾{›ûHööº½ÿÓs®‘põîÞÿöGæÉ Pã]0v…¤çìôU硸y¥Ýù?¸ó?úÕÿޝþßõß|˜qPk1Úõí¿µÿÎGŒØßlÛµÿÏ“(]?×þ_ÿoý¿ç§¦êך|:~ߺ~±8iÒç@“0qý“ð\Æš¼þÿÿžþ_v`¹an¬›ÌàTX(ê„Ö¨êÍwÝóã§yÁ{”Æøpdñî|Oú<®3ÿÔ/0äìøxûÝÛȃF=­ ȺI/ï\\@›ðú:f˧àüAƒ‹¯fÕ±DÓà\½åW™¥WÎÒz—•D*½>êcXåk§šöŸÅ'm¸ímä8²¤®¹Ö•S]•§“S9ýÒ´òLãóX`dŸw‹}0É1›¼½ÿ§3®þØûͳ³‚1bÜul9oZãÿGÿìü?¿(7Õm«ÿWÿw<ˆÍ‘]ÿÏz#ô¨õzþè¢ckÌõ®ÿkÿ­ýwìµÿ×þ§}½z3׳žÔÿ¢C×ÿ;ïWÖžŠ²¶x·ôúgþ¬ÿoÖœ±ñ;èÿ ùü¨…pv½N\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´ï¾ý. ™ÇÜ>›¯ú…Ûüùâ‹/2áÂ?´èA]Çø5)Ÿk@R+T þwÀ¨r$Æ'Ç´ÿ¢;×ÏmRoÔm' ªï”¢ ìhô‹€OËj¯~ ˜w9ühäÛuFÞ*”¤¡Ap èòn«I;=}2•k;#û$‹œ·^òZøýª+½2·ï”Ùûß1qî_ï¡xïÿUÆòÎÿÿÆAtΥ댎Õÿ«ÿwýßõ?6ÇY.w¯ýw~ðÑkÿ­ý¿öÿø*óý¿ó$ÑúëÿÏüY8×ÿÔ®qúnüçËù !ƒÃ¯ãÝØd'ÏÜЩqX¦PïӯØ"¯CÓë:7wG§tviü`Þ~íŠpË,ç–³Øç‘¹áKh<¡ê¾À!ÈWù& ã¥ñ¥© x\ÇCFe./hý­-ä(½stê—?ˆQ&HG7°Ã5Gt<äù%Õ9}m÷–Mxßø(ûõÊWWûb E––­Êô¨\êL_ yÊ=÷]ÞÞÿG_ëGý¥ÎõãÞÿÿ™£3&„ÿ«ÿWÿïúOtµ¶îúl5kçÚkÿÕŽ2O„µÿ×þ_ÿoý¿õÿ×ÿ‡áÀ1rÀGÆ×þÛà?yã #»™„_Ï6CiãÑ?œø:ï£ìzJ™:úÌØ‚!Ý­‚‡ó†²)1ÿ³kò‚Ç} À–ÇL¾ÉƒF}Þíäòß\s/ à¤3¦Ydä ®µÁ•X(:’Í æ½€=ÿ†>>t5VÅ1~úÊyûï^ãÑ~âÐ~j×ÙMçxp+S¾Â0ô¡›¸ YéÚÚëöuäÉýœûpÕ¦†%þ®É´÷￱´óÿù™úÿÄ]ý¿úß:a=ÙõŒ® Ö\6‚x×ÿµÿŒƒµÿŽ ¯/è ó£¡6鹫xþ¯ýÿý'kÿ¯ÿg¾æˆóõÿŽ_{tETEü×êõÿŽAÇ ÆÌ¢ÿÿô“_|õFd¡¹€_Ó=5XM&ä0€æä¬ô;ï ž±í KÂõ§  žéìùa¾î|RÙYÏ>( \I}Þ¬;_ù‘s¦|áb2ÝH2§ü¤k×å™2Ú2!mŸ2‰çºÎ£4í›´{4";½È9´-ç\¹@ŒÙùçš\òÒÖ0fW¨àÚÖG¦y{ô¯²–§6܃ô“Ø{åZ9ÀðroɨrñMý®ÐëÆ}÷7Š,øÚÕÝYø Ò[¿Ý[‚Gëœë°ÊÚú½h]¾ðþzY{øôx‘¡œö ë lBƒwé]ǘX~mWobå×ׂY‰¯ë\ÌtŽ>ªX>m3:ÎDž«:ùèõÏ5«õ5=|ܧù—¶9º½ÿ{ÿI£ÒxØù¿ó?ºéÒCôGuêêÿÕÿtD×¢î”GÖ—Ñ!»þ[¡oý1öƒ¾ézL×&×ÿÓW¬ý—îÈ8Yûoíÿµÿ×ÿ«ïH3tÍu¾þßÁÖÿÿÝ÷ÿŸ~òW?cPÇ€d\ÎQcR\#4qSçìB‰<Ç\úÒÊò(_¯=ï.ÄÃ{ÎM¬¯5Ì89€!êÉw0Öä“?ççŽòí¹ëž‹•@5]š£|Èn‰ºRÿ<*X'‹,Î…{”BP†÷ðÒ†ìØšú•ÅûÚ½!¯²V6qCºúºÝœ‹õ±P9¤}xLŸ•ÉÄ÷<”k2“Up=÷³i÷¶“7aïÿ£ß÷þ?;ceçÿÎÿÕÿ«ÿ³¾XûvýßõŒ†Ø)l”9_ûïØ³zcí¿cGÇþ^û?ó$¶ø±´«Å6Ÿplöco­ýú„^¹÷WÏÓW³þ¬ÿw’þè±þßÁÖÿÿÝ÷ÿŸ¾üåÏßãÂ@§ >¥î áP ›Egô‡¼MI: ^qd/€MøMy²hÝó”Ëãnû%öñÂx_¡<Ä÷£ùâ#ÉOä»äâGýh”U+rtr.=Lszº›‹R Pu“à¥_”Å/AÊ I™¼†ÊŸ¼«¬þLÛ'&CÁòm™Ôq1Âñžî\ÛÕ}ç]š‚m®›°©½ÿ»{ÿŸç—1ò+gÀLÂIÛùúiçÿêÿÕÿ–À]ÿéÊ]ÿ>H_̘¸¯!ÖVaí¿g›Ô¼q¬ýwìíµÿ×þ_ÿoý¿,·?õCÄ÷ãF²þÿôÍŠÿÿä+„Nw½FWÉ}Pô¼`I® ÊŠ6·AUz¼ËÏ¢¤|AïK h°ÜÌÑkå•- 0Üs^^byyñø0U6 y&4ßã1 n»©”+Ÿ–Q¾²6?Néð:_M9GEF힀þAsÕ£:Mþ‘sò•R¯#}1±<|ÊOî“W잇2ôW¾úî|啟råß´æÛb,%yÃxïÿ«{ÿÏøÎùèOÇZ’gìÌàÉ€Ýùÿün¹ÿÏã‡n©®]ý¿úßÈØõ×kìÚkÿvulëëš}aí›u®w-»^ûí±S_ÎØéøXÿïš?ìô ™Ks¾þß±Q;fŒŸÚªÕ3ß~v‘O^Åï¹úòA³þ¿I—~ªŽnõúÃþáfe00®AÞŠÅ*oz1Î-œ‹ÊDßÏ?1G… ÿkq’îÚaà„tuôœ[>h?®_^ƒ/¦5´Œëò{1âÑ ýÎÏ#„oß¾ t„yÁºCèÀîà½×áü÷I ÔvU65zÆO;¶äËk}eg×ü»ËTßk生‚ÏNþù÷é€\ò•WÎñ1¯{P³ìégaïÿÞÿØ×˜2&îcè~ž¼ùó˜Æõ\ïü?z­swçÿè£tW½W=¹úŸÚ-¼úÿ±fuŒìú´ë®ÿ<Õ­­Ekÿ­ýgѧ£S6 }²öÿ‡shíÿõÿâ‹®ÿ}±þÿï¶ÿ?ϽqFGéÏÿ ì h‘ÞPVÜCž#Ê”!?øÍY@yÇÒгÀ-}®ÎËË/z—üaš.<ø‘çWŽÈ©îù÷ý¼X½tä9m˜O“Þz¤3ŠË›,vGI·ÈõKj€,i^rçèçmÛæÖS9Ðj­Ç.¤©7| ³{+[a=ß?yê>e®ú/T·<ñ¹×szóâ~Õ‡ ^÷ÐòÒÓW¬J«n¡ù‘gú}ïÿËŒ½ÿFíüßùÿßÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿ÷ž~ü—?{Äiì@‘vwZœ£½;0hÐJj°œëX¡\Ùjç0dQ(Hø?FŸXžCž2v8ðnÝù…VCO# ,”Ê9ù÷£|û ï=ÏŽ+åòxÓŨ!¯ò§=×±ž§²«¾ÖûúõëÃo€4t@2õŽ@‘·u“ÉyË©×=Èõ”;'ÓŽ<¢9WWžX¹na<„þM{¯:û²qä “qÃÞ; ÷þw»ÈîiÊ‘ãå_ÒµÁã„å¥~+ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô÷×.°W/_åQIiÀ2µöþŸñµ÷çæÜ5ïœ bºC|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿ ÿÉKÜ9eÇà.`¦ÀÆ÷;^Ìáq‘î \1Ô¤qì@Ó\ã'OüîíyDèºÈb‘Wv2x5O¬¼C*¨¯¥ñ©Áx?G VB'Ÿ¬•£u·\ø8‡Xíä‘ÐkÒ];\K/0¦ žaèÅÓ‹´:D©·´ÓŽï¾ý6;¹Y¯^½Œ •=ŒôÍÔSùWîÐÜþd·›þ™2´ah”m»ÅÚAN1~þµMuÊ÷þïýÏð2žnaçÿÎÿÕÿ«ÿwý??ŒQ»þ}·ö_VɵÿÖþ_ûý?~Ôú·Í$ãwò5×ÿ?8ÆúÿSÀ8®‹ø‡Àž~òËŸ¿ ¨qP×SÙý½U¯f`rhÐ̺ åÜ{t$À•ÆR”+À‚Vzƒ<˜åF+G£•u”6æO¯Åoœ{zÓЖ®|,>väç|ãó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõqÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿ>´kõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ·ýÿè†Ô¤ÝózŽ NìK%*tN1ù½ûÊ;°*ßÇu ó‘€—²Ž&À_ø\më#~òßÎn(¼ñý8‰ù›ô{ßßùP‘«õy|ÒýkŒCëo_µ*gëOÛF&Ò(ïzïÿÞãÊßÇ ´ÿGÇìü_ý¿ú×km×Õ®Ç~øéúKgîú¿öŸqb|¬ý÷›óä…™ô²5b—®ýŸ~ÑwÛËØ©~™Œäõºvc ªÖþþZŸ:ôÍú×Ü›qµþßúÿ¿‹þÿÓÿÛŸ¾É¢1“šRì該¤üjLºóLþk·QŒ´)cð3Кúa…‡sÊB9Dñµ" <çò[gÎçZœGø¦Z¼¤ âÖ'&DåœÌÐhÍ‹ («2oy‘mdyÿn^?t«€dSO жK~eU¶²¸Ðà«åÉÙÅ''_Kôhâ<’YÞÊTžÊþqZ¯Å­³e ’G›û²é®„òLÿLЏýˆ@¾#ü¦ü\¤ÜÞÿ½ÿkÆÌ}+ùª¦ñ4c»ï²ë<‘úÿé‡ÿ«ÿWÿïú¿ëÿÚvo¯ý·öÿÚÿëÿÕ'®/WÛõ=­×âÚäÍ_ÿïàño×ÿÿƒôÿŸ~ü‹¯Þ@-:)zÞ‰ãZh~&ÚL&`‡s“¨ëPrlÇé&iЭqfÃ/”ä;÷˜[Þy…ï,øÞÍdÑ0tÑÝÁ¨”‰ÐoÎWÿp†.¥G«¿Wÿïú¿ëÿÚÌ©µÿžŒµ–:ª'ÙÐkÿŸâ­§í—Úækÿ¯ÿg,ô0FÖÿãz¯ÿo]Éx»sýÿƒÿ<ýô¯ÿìE· †b—…Æù}¡IÞÐË3Éä;ìôÖ8\+¯“ÑI“/Mà)Û:Ëü HÅD;‡­'×ðžÀ¡îJ’öq¨üb|Z·ë‚?b‹-yÓ#¿ó—/ÎgãÉ­œ´”vÎ…¼;kbuàAÖ÷ÐI/ÅêñheÞïuvF…ÁíOäÔö«ÿÈâÐòéó‘§ à­xêÖ')wË ye†Oïgû#íN]§|û4¥GW9"ËÞÿô´>Ùû¿óçÿêÿÕÿ»þïú¿ößÚkÿ3×þçÍ­ÿÇ_:ïw^ÿÏxXÿ_/<>$ÿaýÿéƒé–â éØÄ~=˜ÃÀ’æWä€À WG*Ø÷-a&¯ ²ÃØ;—”›ÜNN¡ë{ häÔC¡·¾{ü(>uX!4ÙZWª<ŠÇ[6²‘ù kò_éhÄ #¸ž?§ž¹> -ó>f(íÛo¿ÍBÄ(¡ˆ>ýôÓTÁ ‘UšÐ:ô\ X³«¯*Z÷@ ~“/5 *ùÃ0ï§"¯à 4ú+õd :ÛŽòG›ô)‘÷ L]iJíý× {ÿ¯±£3f|Ìɱóÿ¼Ûnçÿêº{õÿÑÔ‘ux×ÿ¬@+ëñ®ÿã´Ï+Öþ;öåÚ|„Økÿ}å?;ë kÿó!¯0ýÂg‰ ÊW‘l­I´þßúü×õÿÍ—êÕ3E.îš?Õ/¿þÿÓ—ó¬;ˆñè€9Ñ1@§v€–AQAz¶Ë]e*‹4õ©C,Èk¾r©Ò{sëuxV&1zL°ïŠâ˜1jl(ƒgª×¯_bˆÒŽKt³Á­Y.š8?“Ž¡[#7„íTøhËS@¾Á«£ÄÉ…7ú´G?\õ¸Ö†öMò'íÝ´ÏKë?ÎkýâÐN¬ÿöþïýïœ26„ÿÏ öÎÿêýÆ«ÿWÿŸ7ëo×&ëÑœG—Ì9Š]ÿwý_ûïüÈ™…uþ°½Øpæ‰cí¿µÿ ‰¼^ûý?jbý¿õÿÏzŸýÐÿ‘ErÀÐEÓb øøÁLÇWü4é„k™ÇÇ M¹¤Ê˜á„nNåyÄ®¿´$_>CË~?/AVBÚýˆñ–—Ñ;çå}NO º:“¹éá|mb( ißHI\µN Äo¦Àôiye|}p88 øc7Ö_| 庀žyÄnêL‰äágËè0J@#xöq@«Œ¶Úõù¦¿íЦzÛ´I@çlz+q C÷±4Î=òºÎý2wÓ?¿½ÿéÖ½ÿ3‹ŒÃ/ÂÎÿÿ«ÿ¿Í«ÿŸ(E‘u‹–8šb×ÿ]ÿß?vÚd|Ö‘+kÿ­ý·ö?‹ê9˜kÿ?¯)wŸdÇc]‰™n[ÿoý?³Ç8î~ Dúúÿ§o~ýÿ§ÏKܺ¸ù?ÿ<|[V«õQø 8ÕGLðÇÓ×ZM¯fg–ÞÇùáŸ:"l¤Ã'nêl ÃT~ŸžžØ¹óùr×=¤5è;2ä>O ¶íýßûoŒìüßùoÐÕ)Õûå wš\ÓFQ5Ïú¦4Õí«ÿçG‹ÕÿµÉx°jîú¿ëuDuË(˜ù¿öû²aí¿µÿGy®ýù7µ/Ìú;÷ø1oø@—£Ì çG|×õáÖÿÓIÚvµûŸ¾û&eÖþ[ÿÿÿûÿé'¿øêIo"׈èWòšÆ˜@üJ_e¡€æ\??箼‘cä(´Ò˧[A“pÿ3õ™è…Ê¢¡qyÝÓ(¤Ò‹]kŒ°È8@]Ûxd¾~õ&/žæEëS&@ÙÔ­62¢ÚGß|óÍ'Ÿ}öY®Ñô:FyHÓ_èY­?ô­CühË•7™a ½õò§/NÕ¦]d“§DxMÛRÇ\‹cM~x]à\úâT¡Ð)?qëjßà'­4{ÿ÷þ˜o׸ɸš1²óÿ€Þ;ÿWÿ›#}¹úÿ¬ÖAôœîØõ×ÿØ·?36Öþ[û¯c£¶(!4®.¹§­ýŸ©³öÿµÖ¬ÿ·þßúÿ³–üúÿw`Yì âˆv1¸/5<ë°2Γ?ëÉLà˜)MŸ <)/iò{Ý2êÌÂ3ñÇ¿ÈÊ ý”C…4|Ü/eãé—/NâãºÀ•~Ö¿Ç‹EµÃ£€ø£6yäQzëá”v!uÚŠÐ~÷íwŸ¼zõjvU½ ÈØ’/íÈü zà§é©g^pZ#­Ž¯¼˜úC×vÿz~‰ÔǾ»ÚÛ2á9¼µ-uòÕNÃL9‡{k÷XCùU¦½ÿ{ÿwþïü§ªn’No¬þ_ýßõm×ÿ]ÿ鉨.7AOŒÂø@—ÔæÈØ¹•QþØ,kÿ­ý÷lëÂÑ5kÿg]žþ¯ý¿þŸ¹‘1±þ_úÁ²þ×ÒYI~ÏýÿìÀ²`:~}R12ìä%YÐ…Ã"Üil·EªŒ]A‚]W¡fåÉ—hä+#ö…2‰RærŒÐwF®¹V&u\ÆPë²åÏLà‹îìLš:/ ïÊW£©õ©|Gê½õ:2–¿ð„–l ¦~I³ëÓÙ‘åÅí Ô•M¹:|dÿýð0I9×€8ñ#L[ÈŒö.Ã\XÑ“†NÙæ£wÞ4çm§¸ô„wr“¨Æ½ÿ£üöþŸ±³ó?seçÿõxíêÿèÊÕÿçÇ®¯»þïú_ûjí¿µÿ,škÿ¯ý¿þßúñiÇõ%Zçlñúÿëÿ³øVÅ$ŠYümñŸ§Ÿþ»õèá}vì|ÿþ¼¿É¯ªv& òí(êN% AèeæM#ŒÁI0BH©qcçãŸòD#¿@U!ü}½èÜ.¤÷ïæ z©É—wä~r¼p>û]å"ËE§£J?IϲÎy;±ÌuÓºË+@ÏÈ‹& LÆ«ôù¾½v_éò)›:U8Á.-|Û'ÒðûX®ÖÕô\#žúµ],ϹÑ7´ÿÅåÄèÔ©îôŸÃÆ êÓÿá·÷ïÿÎóeçÿ<ò<ÿVÿn—ouòêÿßd½Ûõ×ÿµÿÖþ[ûí¾Èúëÿ±ãs_þ)›©¾îúÿëÿÿcà?Oüoþä äѳ—/^> ©¿63Ú FÀM;{WiåÄ=  à-/õ ¨${äX&±é=\«8Ô_zåÙyÕº†8 Rdz2£N}ÏÏ=]^Ö§ÒÚ^¼´E¾¸uºP6´&轜z¿þúëO>Ÿ—¼k·|ü^ÎñÍ×ç½Yß~ûmøµ, Ë ´µQýBem_&íJ¯¼•¡}‹æã n!í¸vÕ¸N=SWeßûÿ¼Knïÿ;ÿwþWÑ9«ÿÏú¶úß;%wý·†v ¯Ý`mÝõÿÃÐÖþ[û¯6*[wíÿµÿ­¡wßfý¿õÿ¬õmÅ_lýÿƒ‘è‘{ÿ¬ÿ?¸Éÿõÿüßc{Ãúëo>zQy 4‹]F 3[Áœv¦–G÷†O·ŽÊ+]À“¹ÆÇÁºïÄR¾A ÄÉ Æp¬Ñ¹.ÈԺ슚Ì3Oÿ€Ráãîc=ñÙ¿…ã @Á¯IøàÝöô1EiøŸìÊ´Ï”“®,p ú?ú£?J¬Ï"ç,ÞŒ9åÞ~÷6|”k;ÉàZÝÄ­,x™æÀizíì¾—G'( “ç=]ä-]ÊOú$Ò~bB•J õ!séÍÓ. Ud™ÇA†6€xê(íC–I $žC½@Ò[h=^"¨xè©üänÙ>© ÞNÚTùÉËW/sgÛE†ðœ~ä©»üæ$éþ$mâæKs.È´—Ld—×>I¦?“`mêU×Þÿ3ÎÒ?Ó7{ÿwþ›#æÎÎÿÕÿ«ÿwýϲ9vý_û/¶ÚÚǶ›síÿµÿùëÿvý¿õÿ×ÿ?›–ŠIÔ~¢'øTÂ=ÏyÐŽïÅî–Vœ¤ôæ×ÓOÿúÏÞpвë§ÀÇ,ÊҪȯ%}ñ¸tà•ãüqD”ó|"] $>® –H®T×¥¿ƒ,Ò¼×JÜm„h ¶˜"óÅßËλ{)»¢”Ÿ¦$BÉÓYÊ©Ç.¦>š˜U×ͯ‘ªœ:ÉÜ=¹ë æ=\ÿÞ qÁ!¼Ò®yŒR™¾àŸlS‡óòEÛû ­çí»¦¹vTöôÙ—zå·tÐ^õ Ë—oõîýßû¿óç?ýJ¯¬þ?:Z_TO¯þ·rœ°ëÿ±/vý_ûÏŒXûoíÿµÿ×ÿ»–Çõÿ¦#Öÿ_ÿ¿†yÁ–ØÓAÚÿ ÿyúÙ¼ÄÝ›/Ð ÒóƒyÄíìß ü1Ø>›/ìy„èóz­ ‚M¬2¡Ê_aK  -¾ç¥àGÐß_R®î)–Á^s p X51€ìÕkxÛ1öâÉûŸÀ%\â‚8-›öOùÈsåã^žtçø+ŸÇ÷æ:»¾Ô0iv^Ùí¤~ôšn“VŸ>ú›¿ù›ãúëÿqÖÿ_ÿß8ø§À~ðÿóú͘d/ìF @¤™ƒÜ0 ®A¯æñ·ïæN“ð “W ‡ðLæO l,rhîü€ÐUGMZõG–I²¡¹‡ßiäW†îör-­—|À ;«„ÞøÊaiêÂS=€ ×ÒÛäLŸ AùuâFÞ«>J=Ê];®µúÙ§y/•z*·kuÜûªÝúëÿÃXÖÿ?>æ?þ“X1ƯÇC,BOÄXäš#k·ŽQ€“!qú‡¶@øñÞ'_AWžhðrˆ²Ð9î×è\ã+(‹Ÿü«<ùìx’_Ê Ôwñ:`Ž…õ)»žZgyº&/ùÓ¾ÔrêÄS°(ÿpúŠ dÒGÎÓFWý®,]y®ãý ɯgëǤåú’sÊÕÚnò”¦1žÒNd"»Ð|yÊ“ßùš_™ö2Ê+'­õèµ÷_/íý7>vþïü_ý¿ú×ÿ]ÿ×þ[û/öñe{²Öþ?þ;zíÿõÿÌ cÁ±þßñ¥øñMGiðA÷kº¤~¬óøò—®Q6}y¥óo•7×Öÿî·?ÿ?ïÀ2H ‚ƒDè ‚”馉 iÊõ1?tƒ†èâìhu~Ñã—Á;»~\£wŒâ½|»ð~ûnv]rõ†ˆ•Å?ùŽli“0PÍ5Y&v^P(9“ïW³È+ÿƃ®ñ·óÉc~x?»Ô”™|±ISze®ÉANåZrz_þóÈž:É¢lvO©€2 ’tî_w*¼ïç÷>VçiÃZeíprN1áós^àhd!—¦Ü~ô£œãç¥è„—_,v‚ÆHÇ`ôòÅó£w“<ÛÁ0ç€+×xØUDÎ/¾ø"_XôH/xƒÞcê!¤ë€Iá<®&‘«M~Y N¿ô¼æ‹ÕÿCOVujG=ïìÒ/ú ÖðAÙIŒlÍœXýGÞôª”¤ÝHNÚüE×ò•{ïÿÞÿÿ¼5'vþ??:ª?«ÿ/mºú?±ëÿ®ÿ~E^ûïØ_kÿ­ýÏ_ûý¿õÿÖÿ¿¬ÅGô?öôúÿ ñwÀžþøßüÉ@ŽC{G†Orôב·°ôýL¡¾¯Sórý‹¸°ë›n·OøM,ÍÍs}?Réõÿ¯õ«E½Ñ&GË–¾@Óùšßáow•®@Mw[yi¹GóúòòÊ€lv;}7»¡¾ùæ›ÈkWTÂ4j~/ú`×XÛ8„‘­õ„þÖw€2hÔÇÈ `4y÷P©ýŒ^½q †ÐbˆF~iI¸AZûß‘Úø©3˜¤Ü¡üÕ§òðÒ{ÿ÷þ߯0puçÿÎÿÕÿÏ»Vÿ?¯ó»þŸÝË]ŸÙµvý?ïñ\ûoí¿ÚðµWksÆðœ?kÿ¿‹=¾öÿñ©Œ‹õÿÖÿ[ÿýÿ®]+Šÿ<ýôßý«7ã°ò¼{ûnv½øä³yÐ#œÙ¾÷ SçwE¾ǘc¼•7ØÚ(½•KrØ#‰4:»¥,ph…òÄØ„¨ƒš;oé/.pÍ9PÈ HC3€’ò}YÛ"ï%Gyµãì»×…Ÿ<‡àìj‹vñƒ¾}ÂëùÛvòàÓ:m“ûôÓφtå[×y<ñ<‰UËE6}qч÷´·é~%í9‡ûûâéôaóú«ÁÞÿ篇{ÿwþgŽÜ&q礤ÿGŸ®þ?ºu”íÑ·ÆÆí¼ÃgõÿYúŠwý?kήÿkÿ­ý7?2¯ýûÞúQ[cíÿõÿü8Ò°þßúÿpƒúïüzç(þÿÓñÕ“@ƒ…NŽªïæQ>àÀǾàTv] Ô˜ðÉ/ÐÞC#t¸ét‡E*@Òu¤áÏÂK~ëvŽgëþîíw#ÛyÌï_Ï€˜ºCO@ShînÀù-7<7{â,Ò&8Ï ˜sò8ǃ£*EºÐ8®çÀ#éS•ós|ÈßòjÛÔ8lÿáðmê´³ª÷Jº¾áÎû¼$ÌùTtêÎ%IN¿§=“ß{PÉUž{ÿ?¼?ºTÿìýßù¿óõÿêÿ]ÿ­ ]³»>ˆvý_û¯¶{lí¿±™Ù¥j{®ý?#„->GuÉÚÿçìíõÿÖÿ[ÿÿ| ŽÞ\ÿÿEôdu$½ ÿy°² è<‚ç—Ð(ÖÙ¡cñ0UÉæ¼· #êžžñòŸ€Îb&Í¡l©¦¡¨Pbê”C 0+ˆ&SI6 ¢_.å½K:0F­èðöÔ\„^Þ/åÑ>ùÊ9È"]Gá×¶)„‡Pµò7½«ó´,müÍô_ί²‘iäBß2=k‡v‹Û.õ9¿÷_Ûówòåõ d7ðc@%}ήö·^¼ÅŒ¼êßû¿÷ßxÜù¿óô=C·TWˆé¤Õÿgýª._ýÆ…µÇzÜXÿÜׯYük 5j×ÿÓ»þ?ÛEkÿ»ÖZûÙºö¿±Ð5˜N]ûý¿ø«ëÿ­ÿ?ºáÒÿÿÙ` o†RÊιXG¯Ñõ?DùµYÛOú(ÛyQºsm&—¶¸Ö;®X®Ǥ{L¯@U£IK¹©W(@iô ˆÐÃð1¹•AwvO¸ò–ïqÄGY ·PÙšô »äV—û®ç{ÿõÅÞÿŽãoçÿÎÿÕÿ«ÿwýßõí¿µÿØŸl`6‚X¯ý¿öÇÁúçàõÿÖÿï|ëÿÏBñ€ÿ<ýø/öF'ßÖ€©Zz5ãÄô½P€à”›`Bo² Ò8¾Ò€G®-z›|ç‚vŽ÷ t6i§¬ô<å…°eÒÎVýÐεú®)RGiή#8Í,ºó‚vyƒSœë9¢™¼´ãýyÔѹ¶}öÙg©¤Œ ==~0:ª³²¶Ýmzç蛦þÔ™Þ=r(×/çè[V_y¯˜¼û®3ü”нn½å‘ws 9ȵ÷ÿ8¨úëû½ÿq“q¸óçÿüp°úõÿ®ÿYVkÿY;wýϺ¹ö_l5}Áî­ÍeÄÔ†kÚÚÇ>õwíÿµÿ×ÿ{öýèõÿž7}DgŽ¢¨O»þÿúÿÆB±§ŸÎKÜ ‰þ5ôÜcf°f2:À«¶_åÑu 97ؼ(]š:LÎÍ`-À1áÔ?õL]½îD–÷ÃÙåº_d „æ¼}÷6 Në©GçyQºöÍÑ:ÕƒŸ]Gh”ù´QùÔ?yZ€™¸¿DVVò‘yb² g‡Õ4sº/y䑯’ku è m“Üðo;.zåPŸÒÏå[_û¡|ñ»Ÿ·}IÛû¿÷ÿx;ÿwþ «ÿÏ«ÿg=ñ°ëÿ®ÿkÿ½Ž@?²ŸÖþ;6åö·n¬ý¿öÿúñÙÖÿ[ÿ¿þ8¬AXÿfqP‹ƒIüÝ🧟Ì;°t®íTিhAg±LAÀÄh•+¸Báõ›O>ÿüó€3åoÇ~ќ㯼 \y¸ïi(Àì»o¿Ëõ¥<>7ÿ®rŒª—¯æKˆƒæ«G¼tvQiÃüÁúì*¸TöIïñ}‘¬mjûòþ« ¬ŠÑ2u·ðû&ÿ$>Ú×Ç;ˆµ;$„>ÿ#>=Ô.rqÛ+®\ΛÞ:ðÍ9^©ä´9§þL(O1^çx¹ê%«¸yÚ¥Í{ÿgüîýÏXé84v:wÅ®wþŸŽ™¯ÓÂÎÿÕÿÆÁêÿ]ÿƒc{ÄØõí¿¬›ÖN‡µuí¿µÿ¡v~ì‰âò×þ_ÿÏ8Öÿ;Ow­ÿ?ƒáÒÆE‘€ê”®3õñé“ßÿÿÉKܫ۠6$‹ç %4 À ´uV¥°AÇAT%(7´­CšwL)ëð‹î½å«ð™ò®=æV E¹Ê€¾²ˆLyZÇT~ê —L2þx’MŽW×Î+wPƒGÛ$SNZ/lÛ™eÏùäi¾ø£=Už~!We$oûí"J]¥ã‰/´-ß6{/˜þ¼ÓVæ¾3Ìg<84A¤ÔôAÚ0é½/b<ï|Ô ÐC/¿¡}ß¶Io;ÚW{ÿ÷þg¼7ÆÜÄC;ÿŽÚù¿ú¿z³s¥s¤ñêÿ]ÿwý_ûoí¿µÿ×þö±êƒX7ë ‰ë[é+þI|”Ë·ñõ÷x1s½þ_pý¿õÿŸpóG¨Íù»àÿç%îÚ€*ʦ¹ÉÒªÐ÷;y‚–v 0¤õWEŠ¢åå½ýîmx1ÐDU>xÖh—8‰ã t‰|öÌ®-r„ÿÐH÷˜žŠ)&òEžáÝ÷E‘Ímâ8IŠlhÈóþûH9—¦îÆÚ€_®‡Ç¯¯Ú£1ùñ ¨5<úxyÒÔ1‡¾Á£rËk=šÒwPIG§LûqÒ6ׂ:;ð(:ô§ i¹OÃòÖ?ÃîôÑä{,›’=)tnÌI|ã㟮ÿ¯oôÅúÿç‰4}ñô/ç%î:&Àɬ%ëÿ  !žü†3¨´ÒA[:[F^€” ÞåqÀ ¿f}Ë·,ÃïÔqdî@gQéZ†}4ÍW¾ü25ÎüHšB8:`÷anZ‡àTPHÑð"ƒÏ__D €tí(1V ×È霕”ħtâHyÂiãì¼òeĹ.¼Ôw݇Ê*]™ÆèåùJ£îëË#ûÐ ÏôÝÈk9ùv’…gnþáZ}n°\õªçÜ›ë ¯8u]4ÊHßû@E}§öþÏÜÌè>ýÑqÖ±³óçÿÑ1«ÿWÿp0k“µhŽê‹]ÿŸ×}k‹~ÙõÿŒú£ëIL¿ü9ëÍÚkÿ­ý¿öÿêíÿ·þßúÿ¿sþÿÓ—ýgo=B{çÀ™ýXF!ÐQj$©ðÁ">©|-#¢F•wTÉS¯½³Ô\Ã4…®ëIL9rÈ÷§¯È‚ëP¾¼Äx@¸…ó˜ßÙ½ùäOÈcuÃC{r}8ÎË¯ð›´Æò›ÞøðÀiÚø*­ô:!Òz®Pøösë“Þþ—VyïÞÞøÆ¤1êµñÎKßjß]V² }„K.9ÉçYir9÷¸¡Çæ"·zçp^þ¡¹€™»LL«ß\üôƒM uh`äÚû}ÔéZº4;³’?u©Ãû²”k?¤½øj«ø’ ­úìVûôõ§i¦öûÕYÞ«×çEúøx×½/r>4òÂgJKK»œçzœ \ó' ¡Ùûÿá˜Üû?ä“ƳñbL9vþïü÷+&ݲúõÆB–’³ŽY»þ}péÌ]ÿ×þ[ûoízÑ8ÈÚy­Ÿkÿ_¶Äµ†Ô7 Õ¡9[4~NræÏe—®ÿÇ\Og¬ÿ·þÿïµÿÿôãy„° tF}vìPœÓ(×KqØÉ²3T…â8¸Q¾¹<×tw¡÷rsñ÷£x¤ã¯Î™jX¹OÒsšô9â4_´ü‡}!0xs°ãd_åGÀ'u|͵wÚ¨½íW.uL^Ú4QÚyžÉ¿h´-Ê{´´-^Úéº/´óìûé3†«À˜¸¥ß®€—:•op®Î§¬´mQ¾ý§…w“m–þjv¶¡ÕÏiûð)_rµßsOçZ^ò'––zFtúLØûí&Üû¿ó?suç¦?Fw¬þ_ýoõÊZf-ÙõÿØ»þǦXûoí¿Ú¥µ_­kÿ_:síÿÇX`[+õMÄñÍÆþѵÎäÔ+=ÉÑòëÿ/þÝtÊúÇ×e¶®ÿÿü$ÕïªÿŸ—¸›øB Ïœs×ù•pu) OÁ”»Â@%ƒO”ÌÙÅÐçÊ“ï(òâå<:7Ï›P²C'TôÃW '­|r=ò†n.²Ø%½4ø¹”¥ë’fÀ8t( òÈH.qëA×<¼~ø4eGtä’þ“§Lémïß ø4|ÛN}ˆWv‡M,¨Ë!è€>]èÅÉúÞò¶?Z/Î|Q±uºvîN­Ïý)­y=wM†—Wû[·ú•­6á¾÷￱ÙñѱÑù³óçÿêÿÕÿ»þÏîðÑ“B×Qç»þøØƒ>⨮ýwlÔÚ`kÿ=ûú‚ͼöÿÚÿôÛ“ï}z騸7£F’fý¿ø|úJHÿä윻^ÿïà úȸ‰>}´þÿÿþ!tc(þ:šÈ7,/þžüY.>ä×XO„G úòiZnü¤ÛuðÉB3/‚)ý¾—S¯r†®Gó„ÒPUR™€ÃmóÅPïxROÐ rØÉ”²ê¸ø©7 ÔÐx?E¬ò¡ôÈ4|];G/ï©W ŸX›hÄÂwß}‡Iže&¤žÃK¾zðiPν &o2𠯩 ½¶¶Ý• 4t•O¼s=ñý3ªê(±°÷ïÆ‘ÿÏ¿ÿÏŽ}Ô¹¶óÿè•(›.ªÛú¿úõ¿¹²ëÿ®ÿlJ¶ËÇîåQû#úbì±cí¿µÿÖþŸÁ×þè¶—ãá—¡+ªCâìÿ·þßúÿ¿ßþ¿¯CáY˜üþY4@@Žìhˆ1v h]Ê$å.EB¹(‹7ç…ÑZpýðÎŽ9Ò™XÙ8Î×99ÂgdˆWº´<Ã_L¾aòü’‰7¾Ê…v¤:í=Æ‘sùò²ÝtÎÕŸú&Mº²®›ÞòÚåª$/ü'M›Ò®Kζ+Û¤õZ¨h‡OùÎÕã<üçšó×]\òñP§Pšž—üÐͧaʸÎ}I¹éçiß¡ßû¿÷ÿ€2gŒìü77vþ¯þ_ý¿ë¿5r×ÿµÿj[‰×þ[ûß8Xûÿ€I±Ç¿¨®\ÿïø…úEXÿïlâXÿÿŒ‡õÿÿþøÏÓŸÌWRC,Ê€ Qw(ÉË1é@!ùƒ„ˆä¹%Ò…€7€¼®²ø& ™Óâ÷ã$z7¥Wzt®‹®ãÁ‰p8Ï¢14äh£(ÂÿzÓœsB¥‡·Çþ ²—LÊà)ï¡t/ÚÔ?@”à¼tm2•Gš@}Éé•VШò–¾ü\gKÕ”õ¸ªAfØðªâ³mQ½³®~(oiøyïUåi=?œí÷ú­ø½O•gïÿÞÿŽ™ÿGW˜;æŸÐyréŽÿ«ÿ«?;wVÿïú¿ëÿÚkÿ Ý×˵ÿϓ֊Úkÿ{}ËúlÌõÿÖÿ_ÿÿÃM9ÿ+øÏÓWÿþÏß¼}÷6àK X€)YÆ J:DH"¯@• h±Êާ@Y罤MЕ¦ Qx)‡W^æ>¼Õ'PîQês`ˤ ñõbôy·Ó0ÃW“­‡w5Ô\㨠à–ECS¦åÃdh\«WœrC﯇“2<É¡"±òŠÕ›•({þUB=é»)£=iq.ù \eK§“m±‚€Ná=Qê}uª_ÙÞå(’iøÈkz_-¬lïç ”%0L$}ïÿÞÿ_csçÿÎújõÿêÿ]ÿÏBßÙõí¿µÿÖþ_ûý?kÁú¨ækò9×ÿ_ÿP“`Å(øRþÑðŸ¯þß¿Q¤»« ¶Hë{83®M\ Vw?qz ˜p~Oî5 ‡Ö‚ßO‡Gû䘔I={×A_¬'Ý9Y4þýûÙm5r’QN Õ=_HF€ŽúëœW~ñ’ž‡×ÉÅ_:™Ú?襅~ε£à“—££Ôä‹ÕéXdG›6é¼´mΓ71Z¼²0NÝÎÛOÒ8¿@+ý?ù~µhßÉ‹â˜2Ã0­ðk—v¿z= ã€WúA]Ê£PÞW}±/GMÞÈÐohK¿÷￱±ótßÌ+óÂá|çÿÀõƒ@¯­þ_ýo,æÉ®ÿ»þ¯ý·öŸµaíÿµÿÙ’]êÃH3>Öÿ;¾¬þi?­ÿ·þÿúÿÿ}üçé_üÅ—oT ÅÄâŒÔQ›ë¤ÏÄŒ€3&ðåƒ0e®QHC@)‹×Pc9yu»‹(NÐä+§. ‹4Ç÷³k(;’TtÉäDi÷ú•8€àRÁ›8“–zÄŽ©€pid=ðÏd|ÈÓ6É£×ð¼˜Ý@ûüóÏÃÓ¹´×Ÿ~šÊ"ÛÈ®-øµ€K­ôñËÞÅ_Ôƒ¿C`âKn}O†l;¼äéî3÷HõòÓðQåö•Bçíç½ÿgœîýßùŸ‰öÑŸÿ«ÿ«ï êQ:uõÿ®ÿÆÃ®ÿ—ÒÛ£sÅÜXûoí¿ØžQœÌ÷µÿ×þ??Þ ëÿ½¹þßxäëÿg0Ä7›B¼þÿÿÿyúÉ/¿zóîí»#@–N£\t ´9ÉyäÕ¹;ÛÏP^çù÷áž3J=»yÀuLÀK¹s~¿.¼€>Æûœ£ip Ø ¸3À€¨ò•¿˜+È‚¦|¼÷&ÀÏ%“kMQ† =ô‘>(½~ý:"ûlZ{n@øŸÖðœ]fä%{úGû&¡œáß nåÕÛÝrò¥¡ðÒ×ø ÃÜKeñM|õ ÙJ¶÷ïÇÑÎÿÿ«ÿ~¥#WÿïúoùÜõÿØZl ¶ÊÚkÿÕ-k\Œ¾ÌùÓŸ®×þ??Zs:Öþ_ÿÏÈ<™¹±þßúÿëÿÿÝñŸ§?þ7òÆBc1â¸5üš(ØÝ€^] M_h& zá<Ææµ¼PòNª‰ãÝhd·Î;xƒŸ<’ O@+”Öb .´xÏIòýâ€J[ÈQî¡,æüΧ¼òbó)§Œzs8ŸÇíÎìøJ˜zNMg1ÂÌï¿?rW9Iÿ¡ 4…Ó‘GÈã{snG”PÙœ£QÞQž€'4®[oÛ–{6eò~«¡D4D£,õSîÝdvâ Ã/}6²ìý÷Þ°½ÿ;ÿwþ¯þ_ýo}Øõ×ã`í¿µÿØŠkÿ¯ýÏ÷Xÿoý?ëÂúÿëÿÿf0«c›Á-þ)ðŸ§/ÿúOߤ Xr=šÇq 03€GhØ ¨2H”ElvõH $3’Sj¾ü—„¹NÙÉ¢€$vEI»1x7à%àÓP%麴}¤°@×»Ù‰D¡»“ ÐD¾áWž:¶;¯ò2seæ@§ŒúRÖ#Š#«G÷ÔêâCþ¶Á/LüÒ4|¾0KŸªÏ.e• ˆt*t~oÛÇm×}¬ùx ‰'­|5€œúÇÑváFY°ìõ€[øÉ»ƒthúhæÞÿóØêÞÿÿ;ÿWÿ¯þßõ×ÿµÿØcµéÖþ›×X¬ý»íÿqJÆa17Öÿ[ÿoýÿõÿéƒlüçéÇù³7Nj¤z:ˆP€¯æq5r/_ç¨âÚ(ïbÎXàÃ{Òñtî<`QùÕhL ɹôî<ÂÏq/‹§k )zÌß¿{ÞÆàH@CF‡/üM8éù5I}BvcÝêøä+󘥺>}4QºvºI•·_V¬ÌÀ¤;`W€ILnïª*Àà骛,}ç•su÷EåJ;¢ž¼Zš~èýÑ'ã†Nß ÒÞM»*7ÞM'ËvúJúÕiíó½ÿ{ÿwþŸG“wþ¯þ_ý¿ë×Ѭµ³®sfwý_û½ÅN[û¹ö¿±p?Öþ?¾[}:1ºþßñÓÖÿ[ÿ¿¯ZÿÿØÕúƒþœXöHÑC1¼Æ3ylÌÚ´‚|ûí·ŸüèG?JzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç^áãZ ;þ^zæGe"×ÐàçüW_ÿ*}o÷V_Â.Ý#‰‚s|úR¬¬ u®@]Ó[FLò•Nš ½÷zïÿÞÿÿ;ÿéˆê„êKJmõÿêkÈ®ÿ—¾ëìà-{‚ÝÛƒ-2×융ÿÖþ36Öþ?ööÚÿnDXÿoý?ëDƒYB_$^ÿýÿ ÿ#üçégÿî_½ñe<ê1B#a0 §Æ@{9‰)†,Ä€ëKŸ•E+6 å½]K^pnKiç%TÁ<¾~~±TpŒtAéê~ß÷?ÍÎ/Ÿ[b -ç<H?e¯ÚÜiýø² ºê•žz§Î>‚¨Œ_*rd´(ã¯&Ï}†Ÿ«©GxîúŒH·ëËî,<ÓOó.,|õßÛïΗoá=4@³ÊŒ><&]xœ_õI#ÿ½mÒï³Òža~¡ó®é7¿ {ÿÏ;ÅöþÏ8™!l\ïü?:cçÿêÿÕÿ»þg¡œ?»þ¯ý·ößÚÿkÿ¯ÿ·þßúÿëÿŸþÁ‚kLìeð† üçégÿþÏß tôÑ3[žël<æ_Áyö믿`ÓMò8¿S&fð+ð"žp ä§Œøà?0ŨƒŒÉÓ¯”'ow -õ\`:ú¾œ?À )#(¯î¾Ó@Ù‚Gí€=C/®œÍS÷“5^a>²Üƒº…´b×úOýª}I›ë:Kdi™Öùà3à“ó»|wy9†öi?ÚGqúeË%ÖΑ«õìý?÷~ïÿÎÿÿ«ÿ?ÐÇ«ÿ³¦ìú¿ë?ëfí¿µÿØÂÚÿkÿÇßàçŒO³þßúÆýÀ·¯ÿ¿þÿ?þóóÿóÿxcpy“R\}Ù;­ u ý,@ç¥EË#pyGÔì"\ßBï<ïÆÁà …þWð±Iž­éêRN0fÊÔiY{òú‹oÀ:JÓn1eñvÄ ½dh½hœ§ —<ê¬Ãz—!ü'/}2…ˆ²9GðQ¨ì’ï¼¼[‹ŒÒ´Ù!衃•}:!ý ŸlÚìk»¤ mèúX¡_‚4!òO½ÚØ~Øû[ý±÷ÀÝë=t;ÿŸu¹“yµó?:võÿêkIÖY wý§!> »þ__ {C_kÿÍ­kÿ}`Ò#kÿ¯ý¿þßúëÿ?ƒ}ôâ8ßÿ±þÿy1mùô“_|õ†“šÇìÆ¸à”ÄÐ[¸"ePéL» Ä¾Î6„1FŒÌ9@fº7FвŽ.J5^¼! ]D·g],vK­W€¥@Ò3Àsê‘îÅå’È ¬F©‹|êAçºü*! Þ460ÈìZžSþ´(Í:2á7õ5´Ž\?'gà‘¯ùø‘#ýuVW®'í§_úx¤6±,z]k‡4ñýÀV¾zòR¿Œ ÊØQ×÷W¤¿§­{ÿç¾Líýßù¿óÿ3æÂêÿÕÿ»þŸµÓ_kiv˜Ì:ÚÐõ=×ÏÉ»þþXûoí?v,;TXûíÿø<ëÿe>¬ÿwôÂúÿëÿÿðŸ¯þÿžw`=ï¦fytlŽ!vb40Ô„86@ðŠH(% ’4³`M@“¡?Ž¡K@–¤('°ûÐåüœ)?ô¾2ˆ>åßúðˆ¡9ò²œËŸrg‡•sü¤§ž‰»«@úä"Ò¡™Ó.ÄRcØ_Azx_ò®mJš§“FŽÐ_e‚xe½@Y)FŸëÊ‚Þõ#žó¶å‘–ÜgºÊ‰Nß o ™¼\kïÿÞÿ޵ÿgWéÎÿ£¿VÿÅš5bN«W¥®þ?»­MæË®ÿæÌü³VϱëÿqÖõ»gí¿µÿžæÇÓµÿÓYKÖþ_ÿoý¿Y.ÇžúÀǽ®Ù[Žõÿ×ÿgC°3ïøÏÓ—¿üù›+10ÎËÑÏõ;ì’òBq€€Å@bÌ;7°¼`}Nrãmʸ69Åh5bÄÊáíåáF®Gê6‘ gah*zõõ—œO_š·ô+/¯ùÊÕ÷’ò~YM™KC'ˆÉÙìJšóY#‹€o ó‰ÑBhZF]Çpÿp¦ð¬Òø¦®Ó”\G¼‡Ÿ<ý÷í7ß$Ï{¾Rf@Ã슛6äßðiHÝ×ÚÍð™'3‚¥Í®çP¾}¦ÏÝWAúÞÿ½ÿ#îxÈXÙùŸù²óõÿêÿ]ÿéD‡uv×ÿµÿÖþ[ûŸyom¨íjíÿõÿø_ããl…»¯¶þßúÿëÿÿýñŸ§ŸÎW3»æ` Ä1Ù XÉ3;ùh„¢ÆÎ݈GŠ˜ÖÐ{ÿýy)¹üòÿ¯ÿõ¿ÂÃ$/H¦LÁ¬,~ ɶfH“Ç߆/cB(èä<€Ö¤ß˜ždN]"Aõ ’µœ÷yµþ­mŸrÓ‘;ñ’wï|¤=ÂÑG1ñÓ&_tüâ‹/B÷«_ý* Ó+;²¦ÚCå®êS…¨®æ“ïã¯;J³ KÈù”Aß üÞÿó.2cdïÿqXãÄøèxÞù¿óŸªó¢‹®1òÐ×Cc.­þŸŽZýý±ëÿóe»þ›³ößÚlpëÊÚÿkÿóoê=ì‰õÿ2?Ø]ëÿ­ÿÿ‡îÿ?ýÉ_ýéΩgÓMÒ("Í‚baé„Aswfå»Î£o0ƒgù(×ki:]™O?ý4±©»ÿá#”§se½·I.x´%ŽÓ pÃçОÇ|…0<‡ÆûúR÷(Ñ P âj»ÝP©÷vœ«ÏöGLúy|äc“ðx>Zù-ZõOZæ_WÄß9 êÝ8|Þ…•S.m¾‚þ+ÿwïß=@.Üór·PÍý™¸/åÇ[?Y‰v§=WøïýŸ€{ÿ3z:o3.vþïü´úÿü8°úÿì^¶¦8ëŠó]ÿÏZÝõ¹vN×ìtÖüÙõí¿Ž‘µÿ~»\¬ý¿öÿýö®/ñÖÿËòѵÄ|Yÿo0€õÿ3.þPýÿ§ÏKÜM†U…D©jÂ4~ºÛHšr eêôz¶= gCÆÜm ´¾|ç™xtê½+,¼û|¸<”_+Nè”qÜéRß%/¹•CŸö]mÌ"©®‹'ÁÈèQI²ÿæúúZä t)¼¼hN¹Ãï@‘YûF&Áµ#Jwøy”QP¦GûºéQÚS¦ùÊ÷EîÒ\çãèDA{“§þ†¡M¸ê»/á?wà^?^Ò›æÚ¯cïÿÞÿ­Œ·@£bÏãnçÿÎú‚1Vÿ_š­þßõÔe×öûZK‹ºÞõí¿1¶c„]ûoíÿêãaíÿõÿºé`ý¿õÿé†õÿgƒÒÏ®G V|L:"™,cdE‰N\ÿµ™ŽD èà¸ô½sÁqs]\(+H«ñæ×Û{°[Ê6bqäÁ{Ê©£2Š]¿ž\x ®ÛQ¤~’X}‘zê9ú”|Ƃެ>¶§,ÙúN |IMö¨3ç©ãjO¸þ´dw¸«ßyåEŽ·ºúR`õ¨MëREwd¡š—‹!8½š«+館ïã£TäZWûVzä™§ðCî½ÿ{ÿ—Ž'çÆŠ±h¼ôÜxr¾óç?-d<¬þ_ý¿ëÿ®ÿÖNXûoí¿Ù½™AqýYûíÿõÿÖÿ[ÿÿl ²d®ÿÿ[ðŸŸ\/qgTp8…@Ÿ¼}Ò€/¼¡­S¢L ”G,8³ÐÁGù¡g¬¤¼Û»q1¸c‡Už{Wî*LÁ'aÊã«lå¹øäÝ\ÊæqD`Ôð{ùê|y08%¨¿írýxÜnĪüòZùGÆ ÇÈ:€ž|ò¨¿aܲCsÕC×¾T¾u?ò8ú7þÚ-h¯ð(;¼Œ¼woßeWƒºå{Xû^™H;<K *œ«ç{K&¡1ÙZ¯sáqÿœïýÏøÙû?cãgÆNÇ óÿg~Ýç’~qtî'oçÆÓ­«ÿWÿïú¿ë¿×þ»~T\ûoíÿµÿ™ •õÿ橦õÿÖÿ_ÿÿl–à‡>^â~wºŽ¾Çk«{=ã·SrŒ2L&=çC,Ï9Ð$mâî`*±Šcw€!àçWYå¼  R@±³” Ä@IDAT÷`ù"bΧ.ÎÐG½ýņôvÀž¾ØÝ×ü(?25©¾Ÿr‡ç¼ ~Ê´žîÀ"§Pdב|²Eþa¤N2ÞÁ.yè ö$Ò„ôÛÄá9eÅå‚ëOåHÞмŸ>)?} ¡Ê×çÞhSù('ôúb÷¨ãžß<ñ]®žK{ÿ÷þÏXMØù¿óõÿCŸ®þßõ×ÿµÿÖþ[û¿v¼˜Ý\{}íÿõÿ:6ê[¹ö( ¸yÇÀ>ãwÍJÞúÇþÐ/ëÿ¯ÿÿ1þóôÕø×oLD t{ží<Î5Ù2¹Ð\»€LJiˆÀ.pMè2à®Çî&½;Ž´Ã³`>—ãï‚Xhä<ŠlSI¿@øòÎÈwfÍõ‹ ª¡W¶ír ,ÃÓ®-Qù—NÜsàUÀ¹ϼ«‹’vD–i/9ñpÈw8o[‡äñúœßòZ·X6â\ >ºÑâÛ€·# Ö$Vù‘í"”Þ¼ÊÓ²H>.¯ŽÒïýŸþÞû¿óŸŽÙù½`•Xýtoõäê«þ¬;Öª‰»æøñȵô]ÿ¯¦?îkú®ÿ§?Öþ[û]ZÛÛØkÿ¯ýoLTG:Ïš»þ_|<ýñ±ÿ6ËËúëÿs[j‹¹0^÷üãñó»æÿ?ýd^⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹½J¬e¥§³§F¿‚9å}Vsmüæ›o>0ñUÎaçVQìÍä¤â%¿id#'°­åÛ6ò¦ObµÏ…69¦ž<qÕ×¶ëðõN.<’>uv´I{„‹6í>Ê ‘ßi/ù+“<ü*·6LCr=-~äå­2éáÃÇñ(?yáè iëÐJ/­4çøìýßû¿óç?PI7¬þŸ1A·¯þ¬)Yû¦OŒ]ÿÏ»ëÿÚµµª+Öþ[ûŸŽ\ûý?ºaý¿õÿá ëÿüçé§ýgoLŒLÁ6G€ã²pQPɯªÃÓ™v1ŒB?濫pÑ:Ê÷K¤8¾Ÿwf½~u~mâÐs€¼©¿$ón«>2~‚jö!þà||õòUve‘±Ë§G Sf†`)²MÄ»À1uê;·È"ÏÉp— A¢ÚN|ÒŽáå\ ƒsåKW0K>úò—V àK<çäq®Ï{®|ù–®mÒG/¹g¥ÕÿÊ•Gaïÿ°{ÿwþÏÌÙù•³úõ¿õe×ÿçµzϬí»þ½¸ö_”¥9²öß³=\û²víÚÿãpLXûý¿ú`ëÿ­ÿO?ª'øóëÿçÝæ|±â@§þ_¾á¨7è¸v0£àQ@  `1Ñ€9bG;Ù¢ôb:_%BÆî\„®[Å]ü:å’?uã%°¤~‡÷[•V~ë&§ëÈ0eðà`ÔqŽö ½4‡:•W–œø(—zcêŸ<ÁÎ"A™@gùIrøØe èqÒÓÁÚ2‡vØá•¯#mÛðöÚá¥îBûL~úqhÛm/>íôúàäJßåz$™¼ä<è½K+íOÍ!yä+‡¿#ûÄÓí³Ê¿÷ÿ€{ÿ ½óæã™JA3shçÿêÿÙ};ú·úsõÿ®ÿl]ÿÇ›y¡/¢3×þ[ûoìO¶çÚÿϯ.1?Öþ?¾gý¡õÿÖÿãc³»þÿô«øCðÿŸ¾ü«Ÿ¿±s©€ß« G€ŽY@(;rt :€PÈ5CÜ"#ݹ´F®O8`~Þ]Å@Rç)ÀåZ_­Éo}­Ãµ²_ýõ'Ÿ}öYvAM¡”³¥N>YK_påÕìTÂ[>Y4nò\ *øõÑ1ü¦®)–²Êµ*@0í8: >‡ö+€É.µ‚gÚ‡wv©‡<¡&nž˜¼÷àZ: Š<‚ÅlC«ï&¬÷ ¾öoxëó¶oïºjïÿSÆIΗŽ}cgçÿÑ_;ÿWÿÓ÷«ÿwý·ïú¿ößÚkÿ×î^ûý?öòúëÿ¯ÿ6ÏüCã?O_þòçoÆòŠÃ qp^\sìý â¼í‹±üb0©³[à*ÉÐL¹À• .¯¿Ô= Ò3ÙïÎó¤ÙÑñî½ÇG¦¹Æó‹/¾øä»‘Gž—¸¿¡s2§í ¯GålеäÞöä)@¥}¼ô‘íŠë¸*+ÈÚ¹ž¢ÚÌÙ÷ò÷WË—'M;Ô£_¥GNõM@SY¤—¿¼<ö8r©rêšò.ù“˜{ SŸð1_à!:å•q8op­{ÿÏBä^ìýŸ÷ìüϼ0O:?Í›ÎCsrçÿõ¥×Ñ!«ÿWÿ[{:WÌ›®QVéŽÎ!1=»ëÿ®ÿkÿ=ÛÌkÿ­ý_;}íÿõÿ¬£ëÿ­ÿ_¿ãÍÿÿÁüÏÿé7Ý•¹p9aΔvøäÅè“Þ­¼CÐè°¾0ýóÏ?ÿäÛo¿Í×ýÄ5FÑ9/xâ¨c÷QÚ¶“4êÍV' JSFP®ÀН ¢û›ÿ÷o>ùôõ§§üÐÜg²cë t©ÀÓÅ@=¯Ó'©ßùµ# ’>‰©«@—Ë{­´ðYåä+È¥nyê%«:cÀOºþôñD²´_•qxôÆ}ô€->Îѹ–ﺱ|õ òË™Ýs#‡ÝXÚ6A™òÇoïÿÞÿÿgGæÎÿó(÷êÿ³Û—ž\ý¿ëÿ®ÿçƒ9kÿ­ý·öÿølï±¥×þö%¬•õMκ¹þ_}®õÿŽ;Žçúÿ£7Ìþ9\eýÿƒkü÷ðŸìÀŠc6§³üê9'Ï@Ƶ©Àå㈆¾ò”£¬#y±øÄwàfX o èËS\œ›àuw§’]TêÁßbéqÁwÙáä¥íÊÅÁÆù²á\+%1eµKðqîP×£|r$ÐÈ`:€Ðs;\žó~¬iO䜯 Š] xýêW¿ z!@Ò¤'žkôúì»i Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï£ÿÿôã_~õð‘jlZ,å.-@ë1*PihYމ¼¼?J<iw‡˜ã:Ž{Yç½.ï:;8 C¯ÄÈC®„}wdÈ™Œ¾T^€ÍM°ãÉ"HFüÎÞK%hç­Ò#á«<ùÐWÎð¼ÒSpþHÃ˯ó^ÚîšÌ¡üׯt{{Þ‰¥oäëøîþ’nðiߨÎcú7¼†>ý-¾@­LÞi¥GvFȳ mv}áÛÓ£Å/»ÐæñÊü3ÀÕ—?{ÿ÷þïüßù4èêÿ3èÜÕÿ»þïú ŽÁÀf¸lócí¿µÿÖþ_û?z`tÃúëÿ ëÿ¯ÿ_{áÿyúÉ/¾zSÆbÆHÞý4ç @ gÞtô}Nzí€"v`|óÍ7átš“Z„ŽàЂ޵Á¼yTOHý“V€ÏnÉõËþë<ööë#Ë\«ƒ,û{õêõ”ÉûgF6|(Ñð™øYçqÈÔ?üÕiÑM<ôh#Ó¤ d”'-}2±v—MÓÅkõ¡õIÒñ˜“ûKÖÏö¸yGÕdx\Q(o²;Â÷°iÒÆÈ<)},:i]@Ô_~“^ø5­ò&aþ¤ìÐ òöþïýßù¿óõÿêÿ]ÿwý_ûol¢µÿνkÿg, gãIþ O\¿x9/}Ÿ¥ÃS[ðQÏî,³ÛKè5º?@»«ð‘N~iÀÃÈ2}$Ï#’xОù ¡kmÐýzèU§,~dIÞ#£ëÔ=ù•- {½÷ï¿1cüôÈØºæˆó,;ÿwþG§P«ÿWÿ[G¬]»þïú¿öß³½·ö_ŒËØ—lvflÓµÿ£/×þ_ÿϼ0'Öÿ[ÿýÿgLèÿ €UgÕN,22 þì™tyB@'ñ^Êrb^ xõý¼hܯ´Œq&æ€'‚²\ ,ðÝ^RŽã,MYeâ4+0Áueu]r$o”]Z¯\¨ür|: gäºC †¸8ïÕº@:2OEi#>‚z ¡ͤw‘8uɯOý«ì})ººð¬á›ë‹‡¶Û‰¥ßý≮ŠŸ¶7}ãzÚæ±CrI“Ÿç^/Y Îåc§™úÐ â{ÿ÷þ_ã˸Øùð™;ÿg\Ð=ÂêÿÕÿÖ™knìú¿ëÿÚ¤Yûoízñø$kÿ[+ôÅúãŸ]E[ÿoý~Åúÿƒ8?öâoƒÿÀ¢`tfŒ\Ï ¥D±û©òå〢KIØñÒôן¾`à¡´ ¼àh ¸2ç/žÎ#xx É1çå©,wɵ îy®?€2Š§Â¤*Û]\ISúñþ,ùäSNXõš|Êz ]A#ôá?tò“«í’æ:2IŸÝ`xËo^yaèx_ÐMß´}b­ àKý“Vzß_Ê´¿R×\£MÀÏÑëIÌõ¤=Bini{ÿ÷þÇ;ÿwþ¯þ??’З«ÿgÇÕµ^é‹]ÿwýϼXûïaŸ­ý·ö?{íÿkgMúbý¿úa|³õÿÎîu}‘ãòAÙ9fQÑ_Âã¯&uÒ§lt-ßvÊ ±Ïøå“õÿ?ýÿ§ŸþõŸ½xCº©ƒÀ@0°>Þe0qhÄ@–&sÝIi@V”Ç·4kêj,ï>@;Þİ¿-_y‡¿#È@}ùâeês-ϯ‚N^HEï¢XÝ^d.Oíí.ƒçä@CfÁÄiÛ\£6©ã.{y6ÒšŠÒ?á—þ8C¢É¯wã%ßµÏߨµ6m11MHÿ•’Ÿô<&®=®‰°¨fd#ãU‡ë½ÿ{ÿåÿÑ&Ñw;ÿŽ¥_VÿýºúÿÌkÆ®ÿ»þkÿûkí¿µÿ×þ?þ‹urý¿ñÀâ³5sý¿³Ùƒ¯É'®Ï©„ƹ¸®¥5½±|åëW§w‡nýÿkËô'(þ¬3Å Hó™Ç× xÌPÉn©<Ê6ù|Þå¹]×v K.fè Àô«wÄ€ Ra ÏŸRñƒöÊlžKårD¶îH³ìñØÞ5øÝL TøÐ|öùgŸ|ýõ×_Ñ™LuNðpt¢IWÞc}#a¾ö‡×ûîuLùèqM–Êøj¾88Y©Oež^œÅkÊPUpŒs >ùêÖ¥¾˜˜ëKu DIFéV²çzòÕ'èîÊšøJ“z'WØû¿÷çÿÎÿÕÿÇÐZý¿ëÿ®ÿçã=L¶»bí¿µÿÖþ?~FììË–g_wž˜+kÿÏëPÆg±Žò5Ò?ëÿ¿ë3ëÿeÊœ±1§ÆÈc¬œ¬GÞ}nlbýÿ?dÿÿéŸÿÅ—o@åý;Cc¶ƒKšGý€'Rìò¾%PJ~3àt¢ÇÑ|ŒLÎæGyÍĽí©3#7´¥3Xï简:Ãàð™ÓîðL)™ÂÒó¸ã%?ÀÇ–Þ/¾ø" ùñ:4 ÚMî†ÓÈz;üɬ ~iëЫo˜=djŸ’¥ýòà72È¿× À !’®S²lèȨž‚U¡ 2â£\û)ýyU$¯”½î‘,}g· ùñª¬á±÷?ý±÷çÿ52 dìü_ýOŸ®þßõ×ÿµÿè‚Ú`kÿ­ý?ÆxìñÚÔkÿ¯ÿ·þßÁ꣮ÿ¿þ?l¼"˜Ãx[ƒQ#'ü¯ûyý1qñŸ§Ÿüâ«7˜8Rx€•ë¼hÑ5ŒíŸÊirà§ýBwŒ9'¿òŽÊG 44ÒÍ0–úÊÚ6£6L†ÓÈA–'ñ’}ïÿÞÿÿ;ÿo:lõÿêkÉ®ÿg½¶Æîú¿ößÚkÿG'®ý¿þßúÿ–_ºþÿÁ êoóÝ×ÿ?›uþ-🧟ýö×o˜\»®ÚÙÒœ ŒXÛ ;‘'♼urÐ{¬ÐgBç–}ñúõëSnhðùœ_À–aŸº§¬¸u€q1å Ð<òæDþd†dÊUi~ah _)f-”²Ã㫯¾ ˆ¥n V%ò¶íbõ™œ}ïCó6µ¾‰iò*ù}Í0€Ó0ib`TxNÎI^*߉¯¬~ZO[äú“~ Õ³q§ÐòWvúä^}yvוk2ÜéÑíýßû¿óÿ¼÷Ïqìü_ýÿXof<¬þßõ¿ëgÖâ»þ¯ý·ößgvëØ“g~¬ý¿öÿñýøõIâ—¸ýÉ£©ÿ#Ýuã¬ÿ—þÑ™SÓ)ëÿg3Èúÿ¹ûól!ólÎå}Wýÿ§ÿí/Þè¹Z4¬ïºÒX×Þ)åÜΪvDÀLƒI$ÿ~´Ó,èÉ¿T×äûJ _v„¥|¾â¤f‡¼$P~¿¢FA=nÌ7³Ûêõ«×‰ýêÕÙ%†_TÅ7õ;·;+Î&®|ø•ÎcŠêÈõŠ•ûøáì>K/øâF¶ö—~t¯²cmhô1žhì {Ô?ihJúlè”Q—Xºº(úžçúª ]weIo»ðu^s.8ßû?që§½ÿ;ÿwþ¯þ§+WÿŸõ1kѬ»þïúÃaþÔöÉ<1WæØkÿú¢öÜÚkÿ³3ÙÜkÿ¯ÿgM]ÿoýÿ,š£ü8ºþÿÁPjKÌâùÅÓ¯ÿþ?¼RB€R^Ø~&ÏV—áQc$ÍÊõôlÀe”ðF(ÒŹiÊ4 €Òw85]Œ_¶è‡“°"ÞÒ ­\tÝt_biCùØ-å1B4Úãæ÷%èøvÇ•üÖQYÐûñì¦"жÕ ¨áe§þÀ'íBƒ´”Ÿs»¾€YdMŸN•UÅ (Èðé9¹„”k `¦6åÕ‰wôÎÓÏÎ%\Aº n¿9x6ü÷þ°÷`ïÿÎÿΙÿÇÐæýE›Ð#ÎWÿ¯þ76ãüÉ4çMëÚšñ3é»þïúÏBé¸Ó'kÿ[pí¿µÿéεÿ×ÿãóÆg[ÿoýÿõÿ6¦9ñô“¿ûÕ[Š’Q@Åõ—_~°QÄÓy€y>cˆÊwsb¶Î‹ ‚… €)ǶM gˆÑË~4×ûx¼“É2>´sÞú*WÙ¢S_Ê 9 !½udA˜¶*«Þa¼)/¼•ײè‡{}ê’Ž@nçc’ç]!-ŸøÐ.ÂDÒi¿Ÿf¼¦®¾'ÌuŒÿ¡Ì èqüòLÿxuxƒSe ¹¾.Ò„Fvêºúuïÿ€’s_Ú×{ÿwþïü?s¢º1úgõÿêëº5ìZ›œ »þŸÝÐ5{×ÿµÿ®¹1ÆV戹²ö{>Ý‘?µÍ×þ_ûŸÍEö}Ìñ_ÌËOá³t½©]òIòæH™õÿÒ-é‹9‹O¨oaý¿õÿ;>¾«þÿÓ/þóÿý–ðDÊÁ!]#ïJõÁßr¡›O”N@˜áa—;¡ò^¬kòd"©d®“ü~0‡q<»›Ô`誫Sïž®Ld$ ß›Gü€CÝ Å¨Ö†‚jïÞ½‹¡ÝöˆkˆGyŽhÒȤ~‡à1DH|üöì¨j¾<í(øäZ^y„çÕ†¶™’uîq´SçsâU9¹ø‘ï“/g'pK»í1úð¾Î'J¸§9/ïæ“¯4{ÿ÷þ?æñŒaçÿÎ:fõÿÑ «ÿ}°ëÿ|™x®ÿ³›}í¿O‚Y;×þcç®ý¿öÿúY(ØÓ—oßm®×ÿ[ÿß:Áÿ¦'êË×G_ÿÿã?O?ùÍ/ßF<¨ó „8éÂËPt¢ SMò*M‡£Ññò88ú¨ÛÐ$\‘óÞ(´‚Gý^¾x™ILrÅ×ó'yɿҒn}œ2òõ—·vU6²úÕÃQȬ¬wUEvm›´båƒP%Ýy¿²¨¼#Î=ld(o²ô± er 1úSf@­Kî¶Åî140§êU?Eç÷®…©mlƒgÀJZë ?4·~kžXÛȰ÷ïÿÎÿÿt½B'Ð ô†cõÿÑ©«ÿwýßõí?zrí¿cW®ý¿ö?ÿ§>V|¨õÿþÛúëÿâ¯ÿÿÀ#Š­üà?ß^¯½¤|Êí%ç:^Zo@+t-äzN«¼º ôòúË×áSø4à/ˆ•E”á85ýå|)ðÍ›7Ù¥5óÿM•Á¤@“gÇ–ü*R< ¶õÅîd )¯œºµÝ5Ú; ä\š¼Ö×6+wOãø ê.}ÛGûOÊ,Ïh_}Ñ~kòg÷Y e2Oû¾?íÓ?ê> Ö “7`\ƒ|Çç¡éø;W®uîýßûo¼ìü„wþ¯þ_ý¿ë×súÑz)X?¥ Òvý_ûÏXXûoìóë$kÿ?fíÿãk˜ކú(âõÿŽý¬?Öÿ3.Öÿ?¯tbc¬ÿÿÏã?O¿ø/ÿþíXeyÇ… |1™ì|ª—øz/U ¹æ)+Í Sîtøó¯÷”–4柅-ts-àAyÑzœüÔ1$dA#Í!H+@¤ìÃÙ´³ ¯É¿Ë£ü‡ó•ÂÉ}½˜4ʘÐôÚn¦8/“§N€‘Ø{²€r}„ Oññ¯*$òõW*Ú¦ÚåZÛêKÎÕ`J]S”¼y4Ò;¾æŸ6)_9œß²# OåÒµ'ùÓLÞñ¢ríýŸþßûŸ1hæØù¿óÿÒ“ôMÇÝAÐ;«ÿÏÚ³ú×ÿ]ÿ}AWÐ,¾µÿÖþË:1ãA°†¬ý¿öÿúg½4ÌõÿF?̾hûD¿õ›¯ÿ¿þÿÓÿõÿþø­¯zw”Áq‹#ïXÊŽ¡™TŒ10G0ˆ„,C7çÅ ³ mŸ2Ì—î~Ê@œ2Ý…VT1L[¶y€²9¤EÎË™R½Ø`—Ÿó¡­ÙÔGRŸOˆSùyD/†ÖÕžÊ'_ºk—Ó§Ž©KÈã|Oçñ>×£UsŽ.²]»¿RÿÈy–ÓW½ sÂÕ´BÛÕëIˆæ‘Kü“®ÌUýƒ6FŽë½]赟L‚]lÚ³÷ïÿÎÿó²rsÇÚù?_’µcôÒ©tÇêÿÕÿÖ®»þïúÏV¤/éñÚkÿ t„µcíÿñMÖþ_ÿïz½LžÀ±ˆNXÿïyg^ÖkÉôKu="¬ÿÎt†µvüùõÿ¯MG?›—¸01@fÁñþ'ƒ©@#U~A‘\“–íÂ3àÐMÊ݃ë Ì‹§ó8A4¹vü˜êcLÙµ4eÔ‰¿Ï—Ï—óX!yð‘Gn¿x7(Kíp“?y)ûásLôhŸü~渠 ÐÄ¡ ÿa%ñ62äübZ¸ý•ú¦¬mÞ_•~Z²‡öÚv]™R?æ@ÓCÝ-K.ùÊ“MËÝïUyàFye¾XH™Ißûÿ úµO|Érï¿~;ÿwþ¯þ_ýVÊ]ÿϣƻþµö_lŵÿÖþA=bÓ_¶¹4ö¤µcíÿãÓ¬ÿ7þõŒ þØú牟õÿiŠâŽÎ×÷¯ÿ~$ûÿÉKÜŽú€2:* Ç€DÎį́RÖÅ:6×3 ÅŽù“Þ×ѽydm€è©ÇàZ.u]“W! ÊdfQš9oŒ«Éî°; Ýûyä/ïmšó*‚Ðd§•sïÃÊù””õk‡Ãæ28ø’ÿõï~÷Ü–¡ÀƒœhÒ¾IKnÍE®õ4P-t÷rÚ-¯¤·­â;Ø„¦}—¾’0¼š†ûE•§uµÞ#‹€Vhù8žvØyue¦üÒŽ½ÿé–½ÿç ;ÿwþ¯þ?k[õíêÿ]ÿwý÷KùÚkÿ­ý¿öÿ¬ã§|‘úëÿ>ÑÂúg½ˆ¯9ã„=%ÄO>â£×¿mŒBï9Öÿ_ÿ”Ë…ÿ<ýô·¿~ /@TqhEüêêº;¡ (ÊJº'¯@Š ›Á9£½GÔ䕯sTñKÙ)# Q^\~Œ„Ès•^õ½UÐ8Ê3~òSÖΨ ê¶û*r_ü“æ*óûÙÖéÓ×xzaüW¿ûê‹7_¾9e/yL"ÊG°s©<É×Ð ÷h{3®˜ Þƒå—uQîÚ”Ýa7Z<Ãwä==bâžm–x ­Wìž½ûæ]¶âçZÛf1QÀ±<\ë{õã³÷ïÿÎÿÿô=};ºcõÿÙ¸ú×kæ®ÿ—ƒ:}ÁnXûϨ8NÛjí¿óƒëÚÿg\ôïÚÿëÿ­ÿwìJëÆúÿëÿÿÏž~õ÷ÿÏ[/Ñ3°â°Œã’÷=q`F: < º õO¹'{’7ùø \[Ü[‡ó‚,sçÆàeÊè¹ê‘þÕW_Í ^EŽw_ýiýC¯¾©,ïwÂOùÖ-´Azw"á‹Ö!ôÁ ò ¤»‡¶ †VûRÏìSG-e´Ù!´Ý}'9ïý¢ëÏéw]úO¯ôÙË‘5·fþ Ÿ¶Me@§¼÷‹]íˆ<’§Y¯^¿šG ÷þïýßù¿ót]8HE¬þ_ý?‹HÖœ]ÿ­¤çUÖÕ]ÿ×þ[ûoíÿµÿ¯÷‡Žnôcþp¬ÿ·þ_}åú§ÆEýàú©ìîø´W¼þíîõÿÿ%üçé¯þæo ¤:xÄq™Aæš2:_®;@ :¢p9²<©(™rkÄ=/ø’2ØÒ41º*=¢´^«Ïg$9SgùÑ~”øýœ¿~ý:éåÛú¦06vDM/ß>ò¦´E[“íÿñÛ)%,/uT9;ïD·?”W~â”GPЯÒÈpúð%ü(u “×/?JÇ·}ƒœÉ«¯Ê—|älyõÀ*ô:õj¯óð˜¼Ê&^)¿÷ï¿ñ¶óç?ݳúõÿ®ÿ»þ¯ýwlÉØ\c/Ýí>ikÿ­ý¿öÿútÁúëÿǧ^ÿ?ƒ¾1~¥`Žôàk Å8¬£Ž¦õú_ž~>/qGŒ10$¿( Ôa26È+/ìy<ÏK®¥ÅáB`:I'üùõþ€1x•^™ÖÓ/öÉÈÈ·ñPçês®Ù€<êSoëC—”OZq1:éø¦ã¦°ò “Üñ¨ãËW/¿xýêuÎÑ*—cø êR¾m,x¤Û-bš¦íþÙe¥¬ ¿*Gd¼ôÚ«•=Ã3ð§\8\rÜÛ‰¯÷]Iãl¦×Ä‘§-­£}„à£thÒ¶IÃÃùÞÿ½ÿ—;ÿwþÓ#ÝP±úõÿ®ÿÇÆÙõí¿èÆÑ‘kÿ­ý¿öÿúì¤õÿÖÿ_ÿÿ þóô³ypÅvx‹1ÐC ÌP(féŽ8¸&) kèæO¾Âײʡ«2ÇûH]^ %ßîž³œ_ü'Mʉ*Ë$e;ªø!Û”+]룲¢Í­¡óΩ%0ÌŽ®©ø?Ú{ÉKFé?ýÓ?}ñúË/m¶6 Õð$™õYœ{±¼6Èû ]m“WY+ZŸNE—þëð¾¾tæó˜ê”h¹¶ó̹ Í-_@ _u©}ÒÏYÛ¥,~©ëºoŸÔ3<÷þŸñ¸÷çÿÎÿÕÿ«ÿwý·^:vý_ûoí¿µÿù&±¡Ç¦^ûý¿õÿÖÿ_ÿÿ/þ3þü­Åðȹ7‡Â.Ø!¯‘t Mßᄦ|Ð9u‡•P@¤Lú‹6»ž.àG:PÇ L‚rdÉùÄ”¾ мÈ41Ú*qAÊ'?€™6O¾XÀ òúÁ£•ܽÝÚ¨ð”‘ûÃÇóÅÆSßóã{#Pê‰|§©«2Ê×J@Ù²Kjø;ÿr€´¼¿j(ÂwÒ|9P†Ÿ4ò¡¾ ˆ¦ÌÅS_£жnôí—½ÿ§ÿ÷þg˜dœcÆGÃ}Ì Úù¿ó?Cé‘à|õÿèÛ™#3‘VÿÏxØõl¦]ÿ³fÐkÿ@釵ÿÖþ¯­¾öÿú|µõÿÖÿ_ÿÿ¿ÿÀâp˜0€kÀË 1‰â\÷xç×ËË=¯èß#èñµ»§€O“‚/Œ[.?¼?ï´Bo7’ÇÜÐ:;x`¡à/Ž ..ÚszÊ)+(‹GÏsr¥§Ýó"ó–èú^¨oÞó([9È+(´Ò pmô˜žjc°OýY}ª I;}èÜ{¯„¾£JšvZÌ„ì^C7õõNš~U·ôö¹¾ÁCº8íž8|¯8<¾ýTvi{ÿã½÷Æ­1yÍ» Ä;BÇ™x•„¯×øÚùý·óÿè7ã…^Yý­©«ÿ³Ñ»þ[`×ÿµÿèɵÿÖþŒÉF_ûý¿õÿ>kýõÿ×ÿÏZyÞþúÿûo/æ«v}7"i &Fç¨Ö$ʼn44€åjŠ&¯ç¾t§ À‡C\±k)_ÐŒ·Œ—êxñt%”öq€–xÓÃTídñ¨à:r]ƒkõŠ#ó8Õx ¡X¾C>Y>~8»¾ì¬’f'“ÐG•\I—_9»ã my’7çS& ÒH©ÍÊ•®å=æ×jòíCûÜšó¤úTïÞ½KÝåÕö¨§0â'}úrbò <»Ò(Ð ÿ½ÿyOš¾Ûûÿퟂúêý7ó"ú¥€mÒ”›ü{ʬ(Š´á’Eu£-ßÖ•¾¼Üû¿÷çÿÎÿQ«ÿG'®þ?ë«å¡ë†¸ç»þïúÏŽèû8Ù~L[ûoí?:ƒ½;síÝœî\ûý?þïúëÿÓ‘ëÿŸ NwÛòé'¿ùå[Æ„à‘¼€¹: cCxÅÊqy:>}Ôèa´^y„pÒÈÅH'Oh¼}ê?òMÞ@!¼túse©øj·~ÂSý ¾Ð^¼•‰<# yä¦÷ô´q.T9ù:åÑFΡA·÷ú}ïÿÎÿ™æÞÎäèeúB 3ôU=å²ç¥KëOóVÿŸVÿïúßù±ëÿÚtéÚÇ9[ûíÿõÿÖÿ[ÿÿlÚYÿÿ_Æž~üw¿zË ŠƒRËj⻡m­2nÌ¡âËäÝ7Ï»™âÜ\¼q^”}H}ýõ×®(À,  :¼<X0E¾pÕ–s|È d#_eA#ý‘9¡á{K?ׄ»Di_AçÊ ê Ëï~÷»Ä@7_,°”:†FÝÚ/îc|òÎ;.)ç^á9ti‡v_çÁFå{h£Ã5ÙÄêÅ7×#×Ë‘Uº4rÿî«ße·˜4òÈoHÃïoß(†æ!S 'Þû¿÷¿ÃÁXÚù¿óÿ|Íõè Šsõÿù:­5¢úV¼úÿŒk’þx»þG¥vÍï{2]ïú¿öú˜+ôÈÚºäôMlصÿ×þŸ¹±þßú”A/<ôÃ¥7Ù÷ôÐ^þîúÿþÿÓ/ÿË¿[°È o(€áFw`4ï±ÈŽA:«lZâ¥å]x,½³{HPG¸QÀ пùòM”2:ùÒ-gÁ’úY˜]E5åTÆÐ_2IWgÛ'Mºiox Lêµ»Ênœóø¯Ðè/ÿò/¿ø‡ø‡/~ô£EÎNuà¥/Ÿç¼LBv³_ºÃc&6Bõqåq”påë»ÄÚ–#mgê //¯Ÿ6Ú%f—™XžCÐ ÛT9¼Ïn¬´×Åõj—4»²È'´¼óÊ´÷ïÇ£q!ìü?»ÍaçÿÙ]Dá¬þ_ýoípìú¿ëÿÚkÿ­ý¿ö?;‰Ÿ±þßñ=õÇú³dü[¶Âúÿ3?®w‰×ßZÿÿ_Æž~:;°(ƒ€¡ó„"”}ü1j‡Tœµyù¸XSg6 ²±ß˜5L3@ðƒÌËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þâ/þ"; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi¾7 RånýÀ<ùßËD¢Ô+ xÕÇ Ý3åÞ`¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ ÿyúÙoý¸ƒà1€f¢FЊóNBÀ‡gÕM@eZV,XI× Ü €tßypó Ê9Zwvüà5»™ ,©'[ì‡á^¿²•Źú] ‘ÿZ\?©‡ü“oêà©^eR×¥t”o<++õçèû./4€CÚïZ~ùö±}êK€øè}‚¦uê7í÷ØNöMá•Ã[ºØã‚ë‘§¿²ìjCÛ¡ŽÊ~¥ã#÷þŸqÖ~Ûû@Xý°óçÿ]ÿV§«ÿÏ@«ÿwýßõí¿µÿÖþ_ûý?6Rl¦ñùëÿÅÕ|ø¢õ=×ÿ?˜Ãúÿÿ}øÏÓÿöoM,“Jpî±2 ApgÒç&b'ãËWóÎK:øÄá¹ÒÏ£lQ `r=§¶%ÃS ØÁ¿À‰òBeã(ãZ@ûúË×¹v^ À'áRmÛIlÖs{§ðÈ{v'iúòtÎ1»·Qž>.`ôêå«Ç;½²Û ß é—«ß\ãé>½™8çC#](à§-ísõi¯ÅÊ™”ÐjxÈùæÍ›€[ÝÆ7òÜã^·^y{ÿ÷þïüÞá¹óÿYçV÷ЫÿWÿ[ü¬A‚ظÈÎÞ]ÿŸ×rý²ëÿ±{Öþ;ý°ößÚÿ£Öþ_ÿϺé`[Õ[ÿ/&ű'FW®ÿðöUmðõÿ_ñôW€•Gé뤙I™L&V’h:ÉÚ/ž­teZRƒVšÀ€ûöÛyŸSCyÙE4±¯çááN&/ž Ôdj:ÚÃo¤L Œ ¨ z”•qiÚðsïò/Gñìx’Α•î¼}Ð_W*³ºÉѶ=ꡜoó˜`ä›kÿ„üKÇ?@Ôä«§i­ï”¹cS¾A£|e”Þ—Ï¿z}À5õÕ!/Otä•..¿òÙû¿÷@{÷ÆÎÎÿ³ûR_ìü_ý_}½ú×ÿ]ÿ=¥„µÿÖþ[ûíÿõÿÖÿãWÞm$O­ÿ¿þ?Üá_‹ÿ<ý»¿ùù[ Œž·,¸Áè80‰ÍI´ÌºP (éI9@‘ü‚Í+-1#?É”Cï“™„¶K`èØ½4„³£él?NÃ.ð<ñ—îh½Ò›fØH½‚8iÒçPÏ•ñhïIx.ƒÿç ’¾’®ß^8dç“vàôqÀ*/A"ÇT)íñÒ62M¥u‚÷‘ìí't{ÿ§ç\#áêݽÿíÌ“ Æ»`ì IÏÙé«ÎCqóJ»ó:pçôÝ#'«ÿ_ý¿ë¿ù0ã :Öb´ëÿÚkÿ±¿Ù¶kÿŸ'Qº~®ý¿þßúÏOMÕ¯5?øtü¾uýbqÒ¤Ï&aâú;'Ṍ5yýÿÿ3ý¿ìÀrÃÜX7 ˜Á©°PÔ ­QÕ›ïºçŸÇOó‚÷:(ñáÈâ)Üùžôy\gþ©_`ÈÙññþ›÷‘zZ+t“^Þ¹¹€6á?ôu Ì–OÁùƒ_ͪc‰¦Á¹z˯2K¯œ¥õ.+ˆTz}ÔǰÊ×N+4í?‹OÚ:qÛÚÈqdI]s­?*§º*O'§rú¥-h䙯ç±ÀÈ>ïûd’c6!y{ÿOg\ý±÷ÿšg3fcĸëØrÞ´Æ;ÿþÙù~Q2nªÛVÿ¯þïx›#»þŸô:GèQëõüÑEÇÖ˜ë]ÿ×þ[ûïØkÿ¯ýO7ú{õf®g=©ÿE‡®ÿwÞ¯¬/<emñnéõÿÎüYÿ߬9!cã;èÿ ùü¨…pv½N\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´oÞ}ÐÌcnoæ«~á6~øÃfÂ…hуºŽñkR> (Ö6€¤"¨/ÚN@Tß)EØÑ$蟖Õ^ý0ïrøÑȷ댼U(ICƒàÐåÝV“vzúd*×vFöI78o½äµðûUWzenß)³÷¿câÜ¿ÞCñÞÿ3ªŒåÿ;ÿƒèœK׫ÿWÿïú¿ël޳\î:_ûïüà£;Öþ[ûíÿñUæÿúçI¢õÿÖÿ7ž=ø³p®ÿ?¨\ã:ôÜ"øÏOç+„ ¿Ž{t`“r8×{ÿwþgŽÎ˜vþ¯þ_ý¿ë?]ÐuÖÚºëÿ±Õ¬kÿ­ýW;Ê<Öþ_ûý¿õÿÖÿ_ÿ†ÇÈ_û_ƒÿäXŒ/Œìf~?Û ¥Gÿpâë¼[Œ²ëi(eêè3c †t· Î>]ȦÄüÏN¬!È Gxô5[N3ù&õy·KÈ#|sͽ,€“ΘrdqA/¸ÖWb¡têH6/˜÷öüútúÐÕXsdÄøé+çí¼{GûmˆCû¥]g7yœãÁA®Lù ÃЇnâ‚hd¤kk¯Ûב'÷sîÃUš–ø»&ÓÞÿ½ÿÆÒÎÿçgêwþwõÿêë„õd×ÿ1º&XsÙâ]ÿ×þ3Öþ;6¼¾ /̆ڤçz¬âù¿öÿ·_¬ý¿þŸù"˜#Î×ÿ;~íÑQñ_«CÖÿ?8+3ŽþÿÓO~óË·: ÍŒøº˜î©Áj2é ‡4'`¥Øy|OðŒmY®?mðLgÏ×óu?à“ÊÎzöIYàJê»xôfÝùÊœ0å “éF’9å']Ûи.ϔі iû”I<×uÖ¥iß¼ Ý£ÙéEΡm9çÊbÌÎ?×ä’—¶Þ€1;°¸B§Ð¶>2}ÎÛ£•µ<µá¤ç˜ÄÞ+×Ê >€—{ãÂÔ1×vÓ¡ÒveæØûܽÿÇaí˜2n2^&îÜù¿ó߸ðOXý¿ú?kѵ®dPÌŸ]ÿ=µëÿÚkÿý°öl¨µÿ×ÿ[ÿo „õÿ㯯ÿ° vc±çBñŒsuþ>ýx,öȼ@ŒvdÓã¸Öañ³â|hý›s p©¹øRÒÎMTeðìuø_¼ˆTðI~@•‹oêGp…^7î»7¸QdÁרîÎÂOÞúíÞÍ¿´ÍùÐíýßûoL•ÆÃÎÿÿÑM—¢?ªSWÿ¯þ§#ºÕp§<²¾ŒÙõß }ë±ôM×cº6ù»þŸ~¸úcí¿tGÆÉÚkÿ¯ý¿þ_}Gš¡k®óõÿþ°þÿwßÿúÉoõÖ Žɸœ£Æ¤¸Fhâ¦ÎÙ…y޹ô¥•åQ¾^{Þ]ˆ†÷œ›X5^k˜qrCÕ“ï`¬É'~ÎÎåÛs×=+€jº4GùÝu¥þyT°NYœ ÷>(/<„>:  ïᥠٱ5õ+‹÷=´=zC^e­lâ†tõuº9ëc¡rHûô˜>+“‰ïy(×d&«àzþ<îgÓîm'oÂÞÿG¿ïýwÆÊÎÿÿ«ÿWÿg}±öíú¿ëÿ ±SØ(s¾öß±gõÆÚÇŽŽý½öæIlñciW‹m>áØìÇÞZûÿô ½rﯞ§¯fýYÿï $ýÑcý¿ƒ#¬ÿÿÝ÷ÿŸ~úw¿z{Œ 2ø”º+„ClÑò4%é,DxÅ‘½4á?4åU`È¢uÏS.»Mì—ØÇ ãU|…òßæ‹$<‘ï’cˆõ£QVý¬ÈQÐɹôLt2Íèén.J1@ÕM€—~Qo¼u(/$eò*ò®²ú3mŸ˜ uË·eRÇÅÇ{ºsmW÷wi ¶¹nþÁ¦öþwìîýž_ÆÈc¬œ3 'mçÿé§ÿ«ÿWÿ[wý§+wý?ú }1c⾆X[…µÿžmRóƱöß±·×þ_ûý¿õÿ²PÜþÔßÉúÿÓ7.þÿ“¯Z8Ýõ]$÷AÑó‚%¹€(+ØÜUéñ.?‹’òu¼/% À p3G¯•W¶€ÂpÏyy‰ååÅãÃTÙ€ä™Ð|ÿÅ0¸í¦R®|ZFùÊÚü8¥Ãë|5å<µ{úÍU>è4uDøGÎÉWJ½ŽôÅÄòð)?q¸O^A²{ÊÐ_ùê»ó•W~ʕӚo‹±@–ä ã½ÿg¬îý?ã;ä³?kIž±3ƒ'vçÿó»åvþ?º¥ºvõÿê#c×ÿ]ÿ­±kÿ­ýg8ØÕ±­¯kö…µC^lÖ¹vÞµDìzíÿµÿ9@ÆN}9c§ãcý¿kþ°Ó'd.ÍùúÇFí˜1~j«VÏ<|ûÙEn4Ò=æë¡»ƒ÷^‡óÞ'5`PÛUÙÔè[<íØ’/¯m|ô•]óï.Sy|«S~ >w8ùçß÷¤OrÉW^9Çç¼î}X@Ͳ§Ÿ…½ÿ{ÿ`_cʘ¸¡ûyòæÏc×s½óÿèµÎÝÿ£f\Ð=t^õ^õäêj{´ðêÿÇšÕ1²ëÿÑ®»þ ðT·6¶­ý·öŸq DŸŽNØ,ôÉÚÿŸÎ¡µÿ×ÿ‹/ºþ_ôÅúÿßmÿž{㌎ҟÿØÐ"½¡¬¸‡< F”)#B¾÷‡³€0,òŽ¥¡f[ú8\——/^ô!ùÃ84]xð#Ï=®‘SÝóïÛy±zéÈsÚ0;Ÿ&½õHg—7Y쎒n‘ë—ÔYÒ¼äÎÑÏÛ¶Í­§r ÕZ]6HSoø f÷V¶Âz¾òÔ}Ê\õ_¨nyâs¯çôæÅýª¼î¡å¥§®X•VÝBó#ÏôûÞÿ—{ÿŒÚù¿óÿŸÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿ?„ÿ<ýøoñˆÓØ)€"íî´8G{w`Р”Ô`9×°B¸²ÕÎ9`È¢P 2ð ~Œ>±<‡»ÈîiÊ‘ãå_ÒµÁã„å¥þ(ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô×.°W/_åQIiÀ2µöþŸñµ÷çæÜ5ïœ bºC|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿßÿÉKÜ9eÇà.`¦ÀÆ·;^Ìáq‘î \1Ô¤qì@Ó\ã'OüáýyDèºÈb‘Wv2x5O¬¼C*¨¯¥ñ©Áx?G VB'Ÿ¬•£u·\ø8‡Xíä‘ÐkÒ];\K/0¦ žaèÅÓ‹´:D©·´ÓŽoÞ½ËN.@Ö«W/#he#}3õT¾Æ•;4·?Ùí¦¦Ì'meÛn±vSŒŸmSò½ÿ{ÿ3¼Œ§[Øù¿óõÿêÿ]ÿÏcTã®ÿcß­ý—Urí¿µÿ×þ_ÿµþßm3Éø|ÍõÿޱþÿÀ0Ž+À"þgà?O?ù»_½ ¨qP×SÙý½U¯f`rhÐ̺ åÜ{t$À•ÆR”+À‚Vzƒ<˜åF+G£•u”6æO¯Åoœ{zÓЖ®|,>väç|ãó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõyÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿ>µkõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ¿Ûþ!Ì‹›gö[8(LÆy•€¸J4Êr€Ž¼”0ü˜r&GA™Ðãs3-¯l>›|+óüå·N Èï8ü[Oi‹zã# tCjÒîy=G‹'ö¥:'ƒ˜üÞ}åX•ïó:Ðy„HÀKYÇà/|®¶õ?ùïg7^‚ø~œÄüMú½ïïüG¨ÈÕú<>éþ5Æ¡õ·¯Z•³õ§m#i”w½÷ï¿qeŒˆïcPÚÎÿ£cvþ¯þ_ý¿ë¿µ¶ëj×c?ütý¥3wý_ûÏ81>ÖþûÃyòB‡Lˆ zÙ±K×þO¿è‹»íeìT¿LFòz]»¿1Õ?kÿ?ÿ­Oúfý¿kî͸Zÿoýÿï¢ÿÿôïþæço³h̤¦;zª,)¿€“î<“ÿÚm#mÊü ´æ‡~XáᜲPNQ|­HHEϹüÖ™ó¹ç¾)‡/i‚¸õ‰ Q9'34ZóâʪÌ[AdY>~˜ÅÀ* ÙÔS´í’_Y•­¬.4øªCy²@vñGÇÉÉ×=š8d–·2•§²žÖkqël™ˆäÑæ¾‡lº+¡<Ó?“"n?"ï¿)?)·÷ïÇš1sGÆJ¾ªi<ÍØî»ì:Oä‡~çúaçÿêÿÕÿ»þïú¿öŸÝÛkÿ­ý¿öÿúõ‰ëËÕÆv}O뵸6yó×ÿ;xDüÛõÿÿ,ýÿ§ÿæ—o¡=ïÄq-4?m&°Ã¹IÔ‰u(9¶ãôÎ?“4èÖ8³á—‹‹ Ê ò{Ì-ï¼Âw|ïf²èºèî`TÊDž° HÃa±¡íi;¤+ ôцo¿wW ½Ç#•ó®*¿f„f®ý»´|é©Kfä8tê©óß¶¡MßLÙC~ú¯ô¥ò>—1‰·?òKNS^ÉöRr /þí—Ö'¿|7í^GÓÄʶ‘Ù}ºùÂÞÿÓ¯{ÿwþw^Gìü? ÂßK×UOÑ7ÎWÿ?ëdÝÔþqÞp×Í«ÿÙÖúÓ;tn×9ëxCû,´Wbæä®ÿé{¿ü±¾jþ®ÿgð臵ÿÖþ_ûíÿõÿÎèZ»þßúôâÿ üçé§ó,ï€ãD `ÐI˜E(ÂÐ Ê9‰S51] -®¥†Ð>®¯¼GšòW=5˜°©¡äò‘!õÏCÓK™¦ ‚sÏ@§msMA¡õ~;@8ôW{?¡@Í¿ï{‘üðkyøÚiõñ¿ä+—>™<†4ðMîWXýÈðÁGÀã¤Kû$ý²ÉÏ6a4Ú1וI™žë[Å*KÒÓŽó ˜—°N%>IÙiëÞÿ3Þ÷þÏà™ñ±óç?²úõ¿(ëímýÌú"Ãzt­'YÃvýßõƉñ‘ñp ã'i3dÖþ[ûê¨ÍÚs±°öÿé‡ò×étÖÚÿ틉×ÿ[ÿݱþÿÁ ªKÿ\üÿ§Ÿýö×o €ÐÓ”Ĥsä)‰®93è¥Õ8‘Æ0 &ùv39\£ Ÿ«<€Åã„vYµlùžeÑ͵<õµ®Ö}/ÛºÄôK~åsLžº•ï#€m“r‚²1Dsݺ*‡üTxº–'(Y§¤÷k)ë1E[¡ëVò_дe¦âðnÿ Í}W˜þ ?²LŸ 1 /:\¼wL îòáÙû*ݵ£»"f7ºÜ·¡ÝûÆ¡~Ûû¿ó@9:ãaçÿêjsõÿ®ÿYOwý¶áÆ–Xûoí¿Ø‘kÿ?~ض^kÿÛÞ4FÖÿ3(Öÿ37ø±ÆDÖÔñm×ÿ?>ûúÿ3|…ÐDñþ'»o ’ ˜Gjp$¾‹Gët\Q ˜C/ý®Œ];õ èÆÙSÎ'ˆå ê }Iô¹:ñÄC`kâ;=°å.Kø\ÀU¿š8…Ó>yu2:Äx›(d¢@{‡Öé‘)tÕ>ºêk»ÈL/‡>µÛJ¿¶àU[¼êjùNN2”¿˜ ÒÊ7×À“9š†®òë;³ƒ/¤w¡mhÔådïÿ£ÿöþïüßù?:øÒñô›óÕÿœ¡KéÑêïÕÿ»þïú¿ösjí¿çc­¥ŽêI6ôÚÿç‡xëiû¥¶ùÚÿëÿ =Œ‘õÿ¸Þëÿ[W2Æî\ÿÿà?O?ÿOýÖ¢[PÃ@±ËÇBãü>Ð$oèå™dòvúk®•×Éè¤É—&pŽ”mÇe~¤b¢C‰Ö“ë‹Gø OàPw%Iû ­ÛuÁ±Å–¼é‡‘ßùËç³ñäVNZÊ;çBÞ5±:ð ëÇ褗Æbõx´2ï÷:;£Âàö'rjûÕdqè yŽôùÈÓðVuˆyÍW.õOzoîq½ÏÊä1F ö]Q F eð,@õúõëO@¬QÚqɃÎc6x "ËEçgòÑ1tkä†ð¢ my È÷9xu”8¹ðFŸö臫×ÚоIþ¤}˜öyiýçy­_Ú‰õßÞÿ½ÿSƆ°óÿÄÞù_½ßxõÿêÿ³âfýíÚd=šóè’9G±ëÿ®ÿkÿ9³°Î¶Î-¯Œ¯§ìÆúá 庀žyÄnêL‰äágËè0J@#xöy@«Œ¶Úõù¦¿íЦzÛ´I@çlz+q C÷±4Î?òºÎý2wÓ?¿½ÿéÖ½ÿ3‹ŒÃ/ÂÎÿÿ«ÿßåˆÕÿÏ?¢ÈºEKM±ëÿ®ÿ;m2>Œ ëÈŒ•µÿÖþ[ûŸEõ̵ÿŸ×”»O2Šã±®D‡L·­ÿ·þŸÙcœw?… "}ýÿÓ7ŠþÿÓç%î]Üüï³³k„A  wš\£J?κÓ,¡˜kÐ=õpViZn*˜ÿÏ;ˆÔ¸¹—¿ËÐ{ñе9?©©Ó5G9;“M€¥òy5 • Ý7ß|óÅ›ü |[V«õQø 8ÕGLðÇÓ×ZM¯fg–ÞÇùáŸ:"l¤Ã'nêl ÃT~ŸžžØ¹óùr×=¤5è;2ä>O ¶íýßûoŒìüßùoÐÕ)Õûå wš\ÓFQ5Ïú¦4Õí«ÿçG‹ÕÿµÉx°jîú¿ëuDuË(˜ù¿öû²aí¿µÿGy®ýù7µ/Ìú;÷ø1oø@—£Ì çG|×õáÖÿÓIŸÚvµûŸ¾û”&eÖþ[ÿÿƒýÿô“ßüò­Io"׈èWòšÆ˜@üJ_e¡€æ\??箼‘cä(´Ò˧[A“pÿ3õ™è…Ê¢¡qyÝÓ(¤Ò‹]kŒ°È8@]Ûxd¾~õ&/žæEëS&@ÙÔ­62¢ÚG_ýõoÞ¼É5ú‚^Ç(iú =0«õà‡¾uˆm¹ò&3 ¤·¾Sþô%Ð) Ú´‹lò”¯i[ê˜kq  É¯ œK_œ*:å'n]íü¤•fïÿÞ3ãí7W3FvþÐ{çÿêsD /WÿŸõÃZ"èžÓ»þïú#£ãögÆÆÚkÿulÔ¥3„ÆÕ%÷´µÿ3uÖþ¿ÖšõÿÖÿ[ÿÖ’?Aÿÿñ, ]AÑ.÷Å¡†gVÆyòg=9 œã3¥Éâs'å%M~¯[FYx&þüYy¡Ÿrh¢†â¡Lc<òòÅÃI|\x£ÒÏú÷x±¨vxôÀ& 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu CocoaApplication 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: CocoaApplication About CocoaApplication 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide CocoaApplication h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit CocoaApplication q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help CocoaApplication Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 CocoaApplication NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en_US.lproj/InfoPlist.strings0000644000175100017510000000005415232633614030575 0ustar runnerrunner/* Localized versions of Info.plist keys */ qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en_US.lproj/Credits.rtf0000644000175100017510000000070315232633614027366 0ustar runnerrunner{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/en_US.lproj/LICENSE0000644000175100017510000000275315232633614026270 0ustar runnerrunnerCopyright (C) 2017 The Qt Company Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication-Prefix.pch0000644000175100017510000000303715232633614030260 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifdef __OBJC__ #import #endif qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/AppDelegate.m0000644000175100017510000000337415232633614025456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; - (void)dealloc { [super dealloc]; } - (void)applicationDidFinishLaunching:(NSNotification *) __unused aNotification { // Insert code here to initialize your application } @end qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/0000755000175100017510000000000015232633614030162 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000755000175100017510000000000015232633614033247 5ustar runnerrunner././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000000253615232633614033257 0ustar runnerrunner‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000000253615232633614033257 0ustar runnerrunner‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000002605015232633614033254 0ustar runnerrunner‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000000074715232633614033261 0ustar runnerrunner‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000006455015232633614033263 0ustar runnerrunner‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.jsonqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000000242415232633614033253 0ustar runnerrunner{ "images" : [ { "size" : "16x16", "idiom" : "mac", "filename" : "icon_16x16.png", "scale" : "1x" }, { "size" : "16x16", "idiom" : "mac", "filename" : "icon_16x16@2x.png", "scale" : "2x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "icon_32x32.png", "scale" : "1x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "icon_32x32@2x.png", "scale" : "2x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "icon_128x128.png", "scale" : "1x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "icon_128x128@2x.png", "scale" : "2x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "icon_256x256.png", "scale" : "1x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "icon_256x256@2x.png", "scale" : "2x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "icon_512x512.png", "scale" : "1x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "icon_512x512@2x.png", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000000456715232633614033265 0ustar runnerrunner‰PNG  IHDR@@ªiqÞ >IDATxÚí[ PT×¥¨ic Ä’4ŽN&¶Ó1mCÆ8±Ú¦‰budb@ BÒVƫѶ”1±hŠ:iLkJ@ ­5‡—ÊK°‚€ò~¿ßï÷à ¿ç»sÎν¸À¢‹²3û;ß,³{îÝó}ÿãüçìu΃Ì`3˜Á f0ƒÌ`ÓÞŒT & sg10?c]“Ç MždXÌð4Ã3 ?˜EÀœ¬ÌÌt)¼>79tß«YoÒl›ë÷æñ¨Õ ùgV½ ä¹?âó6Òù³úBž ð"Ç@oÉs^bxâA0Ögò+€1¯ zKþaÀj±2øõ3òÅë²·ÒÞ²èhÍIòi8G'ëÏÐGÕŸ’Kñûz!‹á¹é~áy¿¥ðöhº;:HYçp—$ Dšè>(;H§Ï«ñ8XÀðÂt¾l{á.‰œ¶–ÙŸG69ïØ¬û«,»G..²žNÈ×6(&Ýï%t'Ó[B(¸õ¥õfÒðذb ¢E^˶,¼¤í}Z篘prO:mÊuºoœsáï©n°Q=ndl„Þ.Ü=¥“¥Ë¬ äërõdÛ¾é  9ŽŽE!cÿ„6¥þLä<ÒCnM5a]ö¶Ù#€}¾‹‚ÐÍAS^“w§H=¾l Rý¾¶¶!ç­Ù#€GÅGŠÉ¡‚Ou<ÄQDŽkkë³fXÒäf›÷Δנ'›« xÿËÖ0 wJŸ‹÷]Hm‹â#U^ØÐèVC”Èmwé_&-‚£ÐZ€Ð¶HõD{îõi51÷’ ‚,÷Ò_®tÄ©'Ú5Ü£ÕÄvïSô¬ôÖ_BdðÍèð¥À¾²õW€ -¡ŠÉNÔÞÊq°ò˜â¤Ä `,ãfÌ7{*­g“µÏwòšc5Ÿi\fP'ŽÓâù666–ëtÔümÒŠ® gYg' MÔøÆFÇ›¡ïpâ8ßøž»»ûÏÃÂÂÒÝÜÜ^ЉîŠÉ¢/˜êšÔÞ õø†¡æIšNç§A€• c|33³gOœ8áuùòå___~œ¯›½€|'X>P5©Çpf€b),²#þ¾1ŸÕ(p—"Ó` Î5öìÙã”IÌû]K—.ý{ÿ) ðŸæ‹Š cûûº†ܷܿ)³/W1ö½RÏ)Ûë¤î›t¨êcòªþ„>®õÑZkkkÿȸ¸¸Ñ«W¯8tèÐiÆíÇ<5t#€mî;Ô?rG1馡 k"߆/ètÓyŠéL ¾{ýŠ1×{R5ÞocÎvd]åÄ›!ÇÉÓ2ÝŽ&ž Fü^QQ¥¤¤Pvv6…„„ôZXXlàáoª3€ýå•Zam­èë2gÿ¨÷Wì2åf—¿ã¾ñ6™´;åÏt&î]¿~***¨­­¨±±‘ÒÓÓÉÓÓ3']Üû* ü®h¯TàFÇF§`·†Ð×tvpŽm€P'"ÚcèTã¿É«êïê¢Ò裂^ûœ¢b£)33“¨¯¯êêê(::Z`¹ßϼ¿Qæ}# O‰«ŽKÅ Kš›ø¿X¿ ¦t â–·7nÿ†ö&{ÒÉx_ŠŒ”<[]]M===q ¤¤„óÔÝÝM………tøðዌÓOù»ª@› ÇåZ¸¦½K‡“ŽÓùØ/)))IÊg{{{ÕäHŽŽêêê’Æ01†—/_nÏ8=ËO¼tz$¦-óò“ã‘Ú:Aç¸>syüÏ‹‘¾@×®]£¬¬,ª­­¥ÖÖV)¤AP ¼b—šš*}ÞÞÞ.¡¬¬ŒØúC^†ESyFRq·Zcçø^²…Æ…ÑíÛ·©ªªJÊ릦&jnn¦––5A/C„ØØX)2ð9¡€ÄÄıµk׺2>KµñþŒ \l»,­õšj€wâ'˜4•——KG1ƒ¨äAƒˆˆqéÒ%Âr‡1bÄB-ðóóËu„sg…áý%òXÂã555’õõõŠ(i€Ï"""¤ñbœ  lÙ²åºAþcñt¶Ã/>Jò2Þ¢ð˜*..¦ÊÊJ)ô!Àø(iï òB,ùxÜ‡íø Wð;§¶Þ—ÿ4¶âQ °?ùJNN–B¤ ˆ Bð¬oĘ˜i,Ä‚‰kðŠÈÑÑÑ“ñx~:Þ˜ò%c-Æm 3„í î>>>ʹ¹RÕ† %< Dh£Ò#MJKK¥±€M\‡¥ðÔ©SYÜû–Ó}NH<÷âê9®âLà‡ ?111ÙÈÂù.ÂZ^QÄÇÇÓ7¤ð0€B訨VùwN7÷5‰0/f3€ùüùÅ«W¯¶e5áQx½rå ¥¥¥QAAtwËA£täÈ‘~b>Ü×$ÂLÁXvDeîää´a “" ð^xx8eddR$//OB~~¾¹ h‹«LMM×óÖés‚3ñÄ)'-wíÚµž^Q€bǶ°RNão4:@NNŽ$†\Ú¿jÕ*7þxÜ·µéú·A€§vîܹ  رã+©9B1ä‚` K‘¡M›6y°ûýŒ‡þ¼ÙN^`éââ²ý¾b°B&å<¸uë–„ñ‚ܼyB ;;;åßb^·ŒçèAs[[['ôòäQ ‡Í 1ä‚ào¬õÁÁÁ]›7o>È¯Z"ïôE€ï.Y²äUæñ1°ÔhŒ!^ÑÞb9d!?ìíígeeåÈ+¾_YTúB^<ˆ~c«Þ,”GpŠ ÓCTøï±Õ`r{xx|µlÙ²ìº_ò‚gÁ=¯Wäå]'B÷•… ne=Á{{ûã®®®¾¬8ú³úð¹Ý±5kÖüI¥Rmeã~ͰšŸì>Í«ý<} {MÏ#/à¶£;\Á/PÐ^æ¯Öüýçùúnɉ›ê£×'ë:pb‹øþÝœ¿.âï/à¤çʈë5ùñBsbâ¿ä˜È~ÉUÉÂ\'¤ÿ¤›h”ÀƒAIEND®B`‚././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000001221015232633614033245 0ustar runnerrunner‰PNG  IHDR€€Ã>aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000006455015232633614033263 0ustar runnerrunner‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.pngqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appicons0000644000175100017510000017413015232633614033257 0ustar runnerrunner‰PNG  IHDR+ƒøIDATxÚìÝxdW}7à3õ•¶w¯{ïÆÆpÌGsòBB ‚ ùZƒ˜lbBŒLy )`=´ÐbÀš{Y—õºlß•V]óÝ;»kïÊiFšÍœû¾ûÌ£Ñh¤Õ½çÎèü÷œsC²*gÞFÁ.@gðú`" ð: Ã(À뀌 ($¯S2F °¼6Èa€"ÈðëÑ{@öŠpA€‚hòס×9@œ Mös€×Ÿ×2 XÀ  @¼îrMú{(Λïÿ(D€:¿Þr^ë̲ /ÌÁÿ‰¼Îjð½^ÓÙU¨ñó Ê¯±\ül²Sà×#8@^[~On^×Þ'澘ŸíÏ*ÔàwÀëªÊÏÏUáÿòZˆC5ÎêªôàõT…ç×âk^ÿ þj…Bx-Õ¨ðÏUñgy/hþ‚¦Å}¡FA€@^C³(ÖsüŒ\_çÞâ*ügó˜@T©øŸiá_­pÀû@óåê…*=G ¯þ•~>ÛÀû@ã‡3-þgûy5~G©â¶…5CïÍTzf¿0ƒçUú˜@™|Í”{¾ÜB¿Ú@-_ÿÞS…{íÞtEy¥÷+ùZ¹Û*@ô¯•jžáŸêþž[K…ÀL_ûÞ+æ&(˜É<þÉŠùÂîÛøîÛl!€ÿÿ•Üßû±´èoMní»o-»o•þ.Þ š+˜Iávüéç£Ém ¹ìL"ÕjÀ¬‹ÿrβ— Ê-üs{ÿmÉ­ëÌ/]ø¦Îýæ½ZP®ïžò…»ѽú˜…Ý÷ “<¶wŸSÐ @ñ?õc•œÝÏMñqÏ™ÿî3ÿý‚7'Åÿ«4j ûN#XüOVì禦 „Ètñ_nÁ¿÷Çü>Åÿ=—h"f e’>éT#„PüOóX¥Cû§;óß¶»ø“â€Yöus“üaŠ@ PFQ¯È€â¿Ì Ôcû?ã ŠªLWôçÊ Êýhêâ¿’!ÿ¹ €üÞÅ×=¯ÔDT9(5쿜À(d¾øŸéÙþ½ï?:ìÿŒë/økÅ?5 &ªtø%!€€@ _üW²Ø_©â¿œ¢ÿq þqýùoê:¨çÏ45 ¡ô¢€!Tg húâ¿Ò!ÿÓ{ù?ÿ¯»êUüPíþoK(½ÀdŸWs*€AQÿåœõß3çWñÿùóߨø ZBé)“…!ÔfQ@}ñ?ÙçûžùO‹ÿƒÿÔ¬<Ý!L=% ÔÏ5 @™+þ+ òŠÿWh"æ((L7(þÃãÏöO~æÿsŠ&˜„PÝQ )ŠÿÜ$o !”?Üï3ÿékpÞéŸ;ÿ ]‡(þ¨[žˆ¯ð{«9 @8 €¨Šÿ©€G‡ý§Å·â€úõ‹§[pº>s%£@Sÿå.öWê±=Åræÿ¼´ø¹& Nö.þ'Ž(LÓwžlxÿt£ÈDñ?õ™ÿK‹ÿùŠêÝ?žl$ëÄû…iúÏ…*ý.Âd ø?Tñ@Ã…÷'*g‘?…}ƒj± Pü+þÈT?¹eŠ~ëd!ÁtýéÜ4}ðœÝÞŒ@ñ_¿â^Rü¿^ñÀj ûÎÿ/Õç-LÓ·v†¿Iÿ•ÿåÞZÿ4Xyº³ÿ!L?`ºþ·³þ Èÿ3+þ§{óLõ½‡ý+þhÔ „éרóy˜ä9{>ŸêjSý>FÔ‰(þÿrSô…C‰>q5ûë ©ŠÿÅ?ML̤¿¢.þ­ö@³S…Sõ»Ë½Rˆºø™& ‰€rB€Éž¯à@ôÅ‹â€È€©úÌÕê«#€¦+þsŠÿy§ÿ«â€¦ ¦{N%!@n–¿hªâÿõ݇)þhŠ T_wªyÿ¹*üß@ñu¦šËŸ›¦O­°€âš¨ø%úÃ¥úÑ!”^$p&ýx ø€ö­seþ³í‡#Å?4PÊ*-îPü@ÿå\(þ  ûÙSÍëŸnñ?€ÿФ!ÀLæÿϤÿ0ýíé.ïWêk }(þ ÉúÞå† (þ ÉûÞ¹2¿& €âš°ï=Uq_é:¹*þ^Pü+þ Fýp‹þ @ñ÷Ãs3øž‰×s¤ÿЍq]/Å?4a_|&W@Š(þ Yúæ³] Ð(Þ`ÿÐ`}ó\Šv€Å¿â¼¯x€â2Þ—GŠPÔ#À‹â@€â_ñ ÑoGŠ À†â@€â_ñ @ñ¯ø€ÆêÏ#Å?¨à…¯ø øWüPü+þ ¹ê(þÿÿŠŠÅ?€Å¿â@€âŠŠÅ?€Å¿â@€â_ñ @ñ¯ø øWüÀöÿ øWüPü+þ(þÿÿŠŠ(þ ø øWüPü+þ(þÿÿŠŠ(þ ø@ øWü Pü+þ(þÿš¥øŸî{ÿ"(þsŠÙ ÿš¼¸Wü Pü+þd­ø/õ=Šÿ ü‰÷ÿ"/þseÜÿ0¨FñߢøÐþdÏ/µØŸâ@@ÿ3]ñºùþŠ TZüçBesþ»ÿÍ©Õ.hª¿ÞÅË>Åÿ¿÷†îCÿÍÈ€æ,þgò}åùWühÐp 7Åsf2ä?§øPÿ¿Ü⿜ÿK…{ßZ÷*þ_¯øh~Öh®â?Ì øŸ¬ðŸîÌë^ÅÿË5 0QWKgèÎw‡žäÖïÚ}^ñM$ýøè™\kñ¹{t´t„ÑÂh+Œ=úØŽ±¾Gï§ï ã…ñ°slgòµþâÇã¡l Ùù€L‡¥FTRøï{©?Å?dJ>—‹Z„%m‹Ãâ¶…aiñã¢äã¢âÇ%É­7ßzZçí.ôssò{‚$èK‚­£ÛÖѭaÓÈæ°ydkØ8²%ù¸ë–Þß:ºmŸ @@3øSù¥«tÑ?Å?d È_Þ¾4¬n_Vu캥÷ê: ìß±:´äZšbz[{Š·ô÷Ÿ.,xdxcX?üpxph×mÏý{ïOF ;(M”;ï¿ÜÿÿEÉYüû‡wë>8ÚuPXÙ¾<’ŸÏÌ>HÂ=AGè}|8ðÐð†pçÀÚpçε~Ü”ŒPÏ¢¾Ü¯M7ôªï+µÚ¿âšÌüÖÞpü¼£Ã»‹ýôc:”Ÿ©Ãý:Voç,<óÑÇÓ©{€ÛvÞ~Ówsqª€€F rÓ„¥n-Šh>é¢{GwNžB8¥÷„âYþ¹š“›týƒÓÚžN›ÿ„GK§ ü|ǯÃoûn ¿ìûmqZ@,Å$ÕSå/õqº[Ë^Åâ[GK{89)ôOR8±çØdÎþþ þ9´nh}øÕŽ›ÂO¶ÿo¸qû/à+ÐD¾{ÊÎM>lMn#Éml÷m|’“Ý “|œì&ÜSÜeêŠð•ß ]]Ø1Úg§QÇ&gÍ €¿‡UxN% ªX`†×t·W®ùã°0  –ÇZzéÈsžY Ò0@ÑD Zr-a¬0fG(QèO·øßdóÿË € Òu`xÍþ¯(Ó†zémí uÀ+‹ÁÓU÷}$Ü3x¿B“wrtAÙ,ìgúü©þs@¨²Ž–Žâ<ÿô²~­¹¼œ8¾çèðOG_þåá/†O?øoa´0j§Ð”ZrIÄ`€``VÏ)5ïªð˜ÆAû‡KþËâÙ˜ó?ܹÖð‡+/N.xR¸|íº¡õv MØéi±æ€wßæ ¦þŸ+ñX©‘@É[.9ãQøÈÑW(þi8Gt>zôû‹Ç(ÄÔÑ vŒhŽ¿Ó­þ?ÕóM€Xغ ¼ñÀW‡Óœlgа:ZÚ߯ù“pBÏ1áÊûþÑ•hé"€ÌÁû¯]0'}=‚\p˜‘Óæ?!\{ÌUŠšÆ“ž>zÔûÑ݇Ù4I‡H@ ˜ésr%>–z®JH/¹ö®CßTÍdyûÒð÷G\Î[|¶At@uAæ‚)ÍLUÄOuÆ_áä“•ý_ ¥~β§Û4­ö–¶ð¦ƒþ_8¸ë€ð±>“,²n™u´C“ÓPªÈ/UØOö¼rWþ7v›ßÚÞ~ðëÂI½ÇÙDðG$^¸âyauûŠðÞ{ÿ! Û)4œ]€9zÿ¥Y‚€rž;ÕâÓ=™t`çšðGþ­âŸèœ³èIáïg2e¾A“wsPê/¨³ÿP¦Ã»8âoªŽvQ:zÞáÉ1~yXÒ¶ØÎ ±: ¦2V¨Wã{sSÜŸêì5~'hjG&×P¿ò°·‡Î޹:÷KF¼#,ÐP"]P€` –?«T@™s|ÏÑáý‡¿=ô¶öØdÂþ«Ã|WXÕ¾ÜΠA: º ¦+îK áŸêì¿¡ÿ°—{Ž ï=ìÒÐï¶3È”•IñÿwG¼Ó”£Sc €€²çóOöy®‚Ÿm™”.ô—ÿ]-v™´¢}Y¸2ý²¸m¡Áw@uAÔŠyÿd^z]ôwò†ÐÑÒngié4€wúfAsÛ11@À¬‹ôrýsöŸLI?{Ï¡o =ùyv$ŽHÁ¼ì׆|.og0GÝ3 rÓ¥žë¯/Ñ›—ÌõO‡ý/o_jgÀ^N›røËþÌŽ`Ž: º ê@&´æZÃ;’aÿ‡thgÀ$ž¹äÜð‡+/¶#¨ÇÄSïÓ=ž«ðû!z¯?ðÏÃɽÇÛ0…—®~a8sÁíêÜÕ0[S…¦)ÿgéáüÅgÛ0íŽ\øëƒþ¢¸8 Ôó¸@@å…~©ùÿ¹ ‚ˆJ:äÿUk^jG@™zó=á­ÿUqÚ Ô¥šÓP«‚ÝÙ2£;ß.;øu.÷:jÞááûý¡" jõ³ ^¹ð†_öï\mgÀ \¼üYáÉ Ï°#¨CT@ h¯ÅÏÏÕùw9óÜeÏg+^`Lráu^–´-¶3¨í±æ*¦-òs³ü~ˆVº€ÙËö{‘³”®ðÚ^iGPã¨n € ›E}-¿ß¥ÉÈ )Þ˜¬bÞÕÒig@œ±à”pá’§ØÔî}Û"€ê\3A$ž¿ü™á„žc쨢W¯ùÓ°¼}©A: º!sÁõ~â-è'[ñß_[¢³ºceøÓÕ†þ7¢¡ñá0\.Þ/Œ‡cû|½£¥#´µìú3”Oþ¥Wp qÌËw‡×ìÿŠðæ»ÞmgPƒN‹. €€© z`’äë|UèL Iêc¤0Ö=6o F6…‡‡7† ÉmóèÖ°c´/ôõo;ÆúÂðøHE?;ŸË‡žü¼dú¼ÐÓÚ“Üï‹Z„eÉYèemKŠg£ÓÛŠöeÅçQ{{¦|cÓ÷ì ªûþm@U üU%ÒÂäÄžcíˆY7´>ܾóîpÏÀ}áÞÁÂÚäãúᇊgóka¬0¶n/ÞÂÐÔÏ]š¬R`×þá Îô¶&ÚuP8¬ûК„Tןí÷âðí? ýc;í ªØaÑU(Þëýsüõ¥i¥ÃÅ_¶úíˆ*IÏìßÔw{ømÿ­á–þÛÃMý·…í£;ö÷Ý8²¹xûùö_=úXGK{8¢ûÐp̼#±óŽ 'öS\ÑžÙY˜ŒÂøãUÿ7\³î“vUÓb*@¹^¼ò÷Ââ¶…vÄ,lÙnÜñ«ðãm7†·ÿ²éÏð¦kü¦ï–â-„/†–d•ñúg.xbr;%žŒpÖqfž·ì™á뛾î¸×Π*LP§¿¹vÍnMÇêdåÿ‹ìˆØœýßÝòÃð­Íß·í¼+êmM§*ÜžlczûÔƒÿZ\?àÜEOç->;Üu€ƒ¡éú —ì÷Çáõw¾ÓΠ*\@P–?_óÒd®··¯rFÃ÷·ÞœÁýNøÅŽßÔl£{$Y¬ðŸþ÷â-]3à‚d ‰§/yªie:eþ‰á¬…§'ëüÄÎ`Ör9SÔäo¬]@LN_prñÆôÒÅô¾¼ñ¿Âløz̗ؔç1w Üþ1™Óþ‰õÿ\ .^ö¬°çj;fé(€¶ý¼*Î € †Æ\x¹…ÿ¦•^žïº¯ßÜüÝâ¼xJ _ÚððŸ¾Y –þxÕï‡#“…™ÜªŽá™KÏ-î3˜ ‹¨uíMî)‹žé:ÐŽ(!]µÿ_þbøÂ†¯(ü+THþ¥g¶ÓÛ)½'„KּıV­üÝðMÂ%fÙ)± Àœ¿Íñf•ÌMÏÎòxépìϾþ³açØ€R%éB‰_IÖOøÃ›ÿ¼¸ŽB:B€Ç¼pÅóCGK‡ÁŒ¹$'€€JÿvBF´&— {ñªß³#ö²slg¸òÞkÂknk¸gð~;¤FÒ—ŒxÃS¼Š»,n[ž»ìév3 ˜Ì…É¥ÚVw¬´#v»mçÉõׇ¯nú¶3Óuòóí¿ /¿õµáGÛ~jgìö‚Ï ]-v3$L|“JæþÿA2ܘ] Õý[²Èß_Üö–°~è!;¤ÎÒÑo»ë}áCë® #…‘Ìï­óÃ3’+ÀÌ: 3á/(Q;kÁiÅKe]º°ß;î¾2|øO»ûJC˜ëùJø«Û/ ÛF·g~\¼ì¢bHw^7€‰þïŠgg~¤…æî|gøþÖ â¦þÛ«nûëpÿàúLï‡4œ{ò‚ÓÌ êü€`/ÇÌ;"¹™é}pïàºpÉ­o,®öOcypèáðÿnK¸9 ²ì÷VüsÀ„Â"Ûgÿӳ˯»ãíá¡áG *ñº;Þ~Ýwsf÷AÒe=¨cPS{¬l_^œÿŸåâÿ¯îx[Ø4²ÅÁÐàLJ›ïzw¸¥ÿŽÌîSu¨”€G]¼ü¢Ïå3¹í÷ >^sÇ[ÿMdçØ@xãîØ¹6“ÛŸ†uËÛ—:*ÓÞÒ.Xü”LnûöÑá-ÉÙä-#[M¦o¬? ð®°adSö:Épîg,yšƒ€ Ž€ qÎÂ3CokOæ¶;½¼ßÛ×^zÈAФÒQ—Þõžâ´€¬yÆ’sÍë¦lFvçen›ÓëËÿí½W‡_î¸ÉÐäÒiï½çƒÅ6Í’t À)½'8(¯*,¬îXNì=&sÛýÅ _ßÞü@$¾¿õ†ð…G¾’¹í~f2 Êa€ 'SÛ<<>ÞuÏÂÐø° 2#…‘pùÚ«2Õ¶­¹Öä5|¶ÆgúÀõû»kЈÎ\ðݤmQ¦¶ùÃ|*Ü=p¯ÆÔ½ƒëµë?›©m¾pÉS5r_ØðÕpçÀÚÌlï!]†;×hx¦d a]-áŒù§df{Ç ãáïîûpñ#q+Œ…Þÿ±L]à)‹~GÃ3uÔ]OZxjèhiÏÌöþû†¯%—‹»[ÃgÄoûn _ßôÝ OÒèLÉ"€ Þš¡3†}cýáÓý›FϘ¯ÿL² àP&¶5N€’P#@6õäç…S矔™íýç‡ÿ=ìíÓð³ydkqäGV˜ÀT¬07Zí`®µðôЖkËĶnÝþ㑯iôŒúç‡þ=\´ô¼Ð›ï‰~[Ÿ–|„ïœ|½r=¡÷¸G¯KFÌËwOùüt˜ô2“%;´É׺Z:¦üiØ<Õõ;“ïo›âÿhɵ„y-SÿžÝù®âóJiOþÖu$ÿÏ­ýw„WÝö×@dÏS™™mýôƒŸ ãƒ=£vŒõ…ëùrxɪD¿­«;V†ÃºÎÔ(ßióO.Þ²jnî¿-Ü5pOôÛ™Žò™ê²hEcF k²²Bø—Íý§„¯oúNôÛØÛÚS\ xLÁ€È’tèÿá݇D¿é¥ÿ~¸õ§œI}sógâʧfd­(—5)'õW\0úoÓ÷’ÕÞG58“Ú1Ú~°õ†è·óÄÞc46Ù ÷¸Llçmþ¾ÆfJßÞòƒè·ñ˜yG„Ž–v {‹ [À±Ñoã}ƒdb‘7fçÆí¿Œþ‘m¹¶pt»€` @dÄ’¶EaMÇêè·3 gv™½ÑÂX6¦ô«±aO` ²"+Ãÿ¿»ùG›òŽ•-?ÊÀë^{Œ@f€ œ ¼cçÚ°nh½Æ¦,¿ì»©xň˜Y3f ²âÄ Œøñ6—þ£|épà¶ý"êm´<¦à*€È‚%m‹“ùÿ«2ܨ±©È 8fŽï9ZCC° 2âØ œÜ8²9Ü™L€Jü,¹ÀHa$êm<ªû0 ÁUGÍ;<úmüáÖŸXà‰Š Œ†_ï¸9êm<:¯(+0™ºã/~²ýš¹!òcgaë‚°¼}©†&ó¬€èå’Gtõ6Ž%×tÿMß-›ùß¿‰~î6 \Ñ;¸ë€ÐïŠzoî¿=ìÐØÌÈÚû–‘­Qoã‘󬦉 zY˜ÿû‹ œÁ¥¶EÁ¯úâ^ÀB€` @d@:þ¿Øñk ͬüïŽßF½}GtZœ™Œ@ô@ä#†Æ‡Â-ýwhhfÄ=Š$t@ç~šlF fm¹¶p`çþQocZüF56³²nh}ôë¤ë@¦W@Ìì\Zsù¨·ñ·ý·ihªâÖwÆt Èx` ¢îðgàŒßͪv,ÝùûÁ™Ls@DíÈ;üigî&€2ߌ ÛÆŒ€ yÝ7ø@Ø1Ú§¡©Š[’`¬0íö­êX:[:44™U° bû€[ûïÔÈTÍ`rE‰{×E»}ée2 € /˜€Hõ¶ö„¥m‹£ÞÆ;îÖÐTÕk£Þ¾ƒ#¿*L€Xš¿îØ) ºîÚyOÜ€dXÁ@Äê È/ù•.x×À=šªº3òcê —$ÃÆŒ@¬èÜ/êí{`è¡°sl@CSÝ`çÚ¨/¶_ÇJLf\±ZÓ±:úB ªmÇX_xdxc´Û·¢}Yh͵jh2É€ˆVìgúî¸W#ãØª´’kI.¸\#“ÍÀ€ˆQz†/=Ó³˜/×ÆÜºoð¨·oµid50qvðWÏôÅܯ¡©‰û#Öt¬ÒÈd301Ú/òþha´¸ ÔÂ}CF@”€€ˆQìgøî\Æ cššˆ}z‰+U®€8€Î¸óÿ©¥£}aëèöˆ€Õ™L2QZý€42ޱJ}˜4° b´²=îË|­6ÿŸcCG»m­¹|XܺP#“½À@Ä&—ü[Ú¶Xq³ðÐpÜÇØòö¥™ìÖ@l´ö†Ž–ṽCD½}ËÚ–hd²Ì‘V»¨YÇ>ò3{Ãã#aóÈ Mm€ÈG,3€54>† #“~­lg²’ÿãçñ%ÿvŽ ”øyÃþ¼Í#[í`@Äey[Üû´0+ 9Qããl(ö`nF<í7ô~ùÎÉ×GÝîWÝ÷‘b=6Ù™ð¤°îëŸôûF £a0)Ì'30>FK\–µotòŸ7šü¼ñAo4€ Y;öõ²~È€ÔÞ¦d”I:Ú¤½¥-Êí[n @&}yã Pæ€5€Úuì#ÚûððLÍ¥EÒ†‘MÑn_ìA!@6ŽlÖÈÔéX‹7Xj€æûêÞ†7idê Ç6-i[Zrº# šÚÒ¶Åq#êD<Ú$ŸË'— ¯‘@4³Em ã†7jdêÄ6-j] ‘@4«Ž–ŽÐ™Üâ.ʬ@޵á¸5#@4±…‘wèwŒö…¡ña M}€Èæ…Í+öáÿ›G·jdêfËè¶ÈS@4oy‡~k䎷úF€Ð¡oÔ‚lD@ýìÃã#ñ¾_´ @4q‡>öÛ52u>æâ ˜ ‰€VTÓ¶ˆ9—ÐÔ@äS¬@ݹx—ÐÄzó=Qoß6#TMO~žд@kÜÀöÑ™ºêëvÛæå»40€æíÐwG½}}c;52u•^ V-¡5—×È gÇXŸF¦¾Àø@ÔÛ×ù{€x€–ÈGŒökdêŒÅÌ€h>¹ä_W¾3Úí+$ÿúÇM ¾"{h ÎŽ|r&/ bÕŸÌÿ/ŒkhêjçØ`ôï€Ð‘o¸êÄ}ܹ @b™úwÑ/èR€  fp|H#SÿÀ"€€h4]-qŸÉÔÈÔÝ@äÇ]gK‡FÐ|ùv…TYì#Ú[Ú42€æëÈǘÀœÉé%(cÕ‘3@óuäc0fõ—^zrx|8Úí3@3väsF@-Ä< ö‘C "íÈÇ}&/æ³°4¶þˆ/Ø! #ßhF £™91ñ±ûÈ!:òMh<ŒidæÄX!ÞcÏ šPì#Æ’ÅØ@På÷ #@4ŸØó5€9 â Ÿ,  µåâÊks%ê5LÐ|ZsùÈk0WÇ^¼áS‹. €&|cÉÅýÖ2f@{Þ7@B>ò·#pìU_.ù€fëÈçàØ«L>ò©C "}c@mŽ=k ä£à*Ìѱg @4ÖKÜo-1_Š"}Òb Í'—‹»#o€tHŒÐ|¢¿ €Ë"€ þ޼EqìÕ¢C¢K éä"kÌñN?ÉY@ó)„¸çÈç½u2WErÄ5òx°¶€&ìÈÇ}†<ŸËkdæèv¼Çž©5 š1ˆ|•ü¼Åʘ³c/Þ`ÜÕ5@4Ÿø§€ Ú\]@3vä£ `®Ž½xÿl ù¢_À['s£5×q`€¦3nÔèØ‹÷϶«€hBcA59ö¢¾ €@Ó)âžÐb@æ*p@4TG>¸ *c :òŠ0xô¶5Ð@†ÇGP­F ‘Œb¼u2WÇž5Ð@†Æ‡ã.Â,ÈœñþÙ3@óŽ=0Ç^ Þ7F40€f3Tˆ;h ¨þûÆøÐlb?“×ÕÒ©‘™m¹¶h·mP  €ÈGtå»42s¢;âðI # 6Ç^ÄáÓàø Ð|@Ü#ºóê/—üëhivûb¿z€8€Ø§´˜ÀwI𔆱2@ˆ¼#ßm æ"ˆ@  Œ †ñÂx´Û—®Änõâ>æLЄ É¿ØG¨·Ø§ž Ižà¼|·F¦®:#Æ52€fûB€FPgó"°c´O#€hFÑOÈ ¨ó1qè4Z3@³êëzûzó=™ú‡N}cÎþ€hZÛ"λ°uF¦®æç{#~¿Ø¡ Zí 6úmQoߢ¶ù™ºZØoèdþ?”%Wæó  Î@ÜgôŒÀ1WÅÀ˜I¡_É÷@ÍlÝõö-à˜@cüeÿ &¶EÄ<›Æ“ÏåCok¼ Oš€¢¿>€`&€Ôõx›ŸôrÑnŸ(ü€ a™@}€¸·£ýE¸ P±¯ÇnM†eC]€È§œ@Ä…C áµéÐ'szÇ ã¿›ç‚V—¤>bq²Ý(ü@ó*$ÿ¶G~VoQëB M]Ä6õ€ÂªŸWéMÔßæ‘-QoßÂ6#¨# )Šÿjû³ùYi­Ÿß}Ë €šÛ8²YQUû›"¯ úÂ?7ËïÍÕàwJ ÿ¶~ô£Çyä‘m{jW3-ÊÔIÌaÓÀø`ñMXøÏÅ÷N§ewßþéOú¥ù|~à¶Ûn»iÏÿ+j G´ ¨Ó±qàì?)þsux~zk[±bż«®ºê²®®®³ÿäOþä콟$jŒlŠzû–´-ÒÈÔ'h‹9Ø¢PøWgÎÇsŸûÜU/zÑ‹®MŠÿ'%gþŸ¿eË–áäñôÒ\ c? ËÛ–idêÐÓÈ…¥‡M2\øçªô»¥óý;_ýêWwî¹ç~º­­í;v|鵯}í÷“ÇÇö~²¨™ØG¬h_ª‘©¹Åm C[®MÍQüçªðóÊý?÷Ì÷ïxï{ßûÌcŽ9æš–––ù…Bað?øÁ»’LJÂcgÿs ¦6D¾À²ö%ų³…]#ª &–G4 PøÏ|¾rëþÈG>òûí·ß›Ã®‘aÆ ¾æšknOîŽì.þ÷I jbÛèö0R‰vûZ“uT­@퀸§šX€È‹ÿR—ù+瀹In-» ýŽäŒÿ’Ï|æ3×$Åÿ[÷ÿccc}øÃþ`rwxbñ_ì¿j[ VÒ3ã›G¶&Cåã-`Òâl£†ZcmK¢Þ¾ô="-ü«ñøÄç‹ÿ¿øÅ‡=ûÙϾ¶³³óø½Ÿp÷Ýw¿ó§?ýiÚ9Û+Èí¹oPSoˆzû¬@Í€ÈGľVQÿ¹i ù\™çÊüY{ ÿâÿw¼ãç^|ñÅ_›Xü üä/ÿò/¯“ ýßós@M­z8êí[Ù±\#SãÀ¨qá_iñ_îÏ™¬ÀÏ•ñܽ¿¾gØZüÏûЇ>ôÊ“O>ùŸóùüijPã7ÜpÃeÉÇÁðØÙÿÇý?¦5õÐpÜÀêö•™ÚcñcCãC¡l§F`.‹ÿjþÕ|,LRü·uÔQ ßò–·¼oÑ¢E¿7Ù7lÙ²å_Þÿþ÷ÿ"¹;Zâç@Í=ù€5«425µª}E´Û¶Ñhü¶Ånß³ç±â|ÿ?øƒ?8ìùÏþG“!ÿ'LöKŒoûìg?ûÞðø³ÿ!LX@ÔÔ‘ûu¨Åm Cw¾+ÚíÛ0lþ? ]üײðŸêg¤gýÓZ½ó²Ë.{Z2äÿêdÈÉ9ëÖ­ûà×¾öµõ»‹ÿÉ~æ£!€¨©Ø§¤—ìléƒÉPf¨¶Ø¦õÃid±ø¯duÿJ>/ç¹Åùþ݉+¯¼òUûï¿ÿs¹Òuûððð]W\qÅÇî…ÿÆ'ü\Wê+]àk`|0â¿"¹¨çh3×@ÜÇÖú!u+üg[ü—Z̯œÏ'»?ñóGÏúŸuÖY«?ö±}ò€xËTÅêæ›o¾|íÚµ;ÂcsÿsS…F5÷ÐÐ#áà®".ÒV…»îÕÐT]ìáRìk„Ð0Åÿl ÿ©+÷ŒÿTß“ß}ëxÍk^sê9çœómmmûO÷ ÷õõ}çÒK/ýÆ„ââüS€:wò“i1tî§‘ÌÀzs_øWRü϶Ø/u9Àô]É*þ/:âˆ#Þ™œõïœî. #ßýîwßÜ»†þ?n¸ÿ„@ÀU€zuòãæ{Pçþ™š8°sMÜï Ö`n‹ÿjœõŸî~©¯·ì¾µ}ôÑ‹Þô¦7½{ñâÅ¿[înܸñ_>ò‘ÜvýŸì¬˜Pü» P÷®»HëZ£‘©º–\KXÓ±:Úíëë;Fû44‹ìB ÿJŠÿjþ{LkñŽ—¿üåÇ_xá…W'—ø;²Ü_<¹ìߎ뮻ëìÿØ„}7ÕS€Ú»gðþ¨·ï€Ž5Åbm¼0®±©šÕí+CGK{´Ûg@ªÌöù3î?“¿¸Êrëzï{ßû¼cŽ9æÝ---=•üò÷Ýwß?|ûÛß~pŠâ² ¥ø˜«5wïຨ·¯½¥-)ÖVhhªê ®¸§–˜ÿÀÿ¹ÿS­æ¿÷c¹)ÛSøú;òÈ#—^{íµï=î¸ã>Xiñ?44to|"ìºì_¡ÄïS*°P{ÛGw„­£ÛÃÂÖùQkë†ÔØT|m W`Š"½Pæóf”{Ö&gú÷þøè*ÿ/}éK»è¢‹þ¡’!ÿ{»é¦›þvݺuýá±³ÿ{ï³i?ÔŽ‘O8¨óLu©ØG ˜QqŸ õ?ë?Ýc¥n{Îú§Cþç½ë]ïú½ç>÷¹_˜iñßßßÿ³·½ím_ »Îþ‡I~‡©Bˆ"P÷E> àˆîC42Uupä¡’5(³pŸlˆýl‚„ÜÅþl þ‰Å:â¾+™ç¿üSŸúÔU'žxâßçóùžîñüàïI>…]—ý›ìwœªø/Þ7¨‹{ˆzûPEéâtî' †"¾0Gÿo9—»’¥ó»kíŽW¼âO¸à‚ ®JÎú6› J.û÷¥«¯¾úîËþMÜ¿{ ¡ôÕ@½€¸G¬h_V\ã ]ëfëЮƒB>—vû†Æ‡Â#Ã5t†å“Y¨£…1;h„²~º"¿Ô×ZvßÚ“‚¿û=ïyÏK;ì°7ær¹ŽÙlTrÙ¿Ïþóv]ö¯0Eñÿ¸‚â}PŸ`àþè·ñ°îƒÃÛ¥±©Ê±³ôÒ …99!D£H/ÀÜÿ³=ë?ñ~ñ¬ÿù矿ÿK^ò’+,XðäjlX²èß'¾üå/§éÑ …}¨¤øOï €ºØ8²9ú+¤ÓTåXêŠ{JÉÝ÷iäÌ÷Ò-CŠõª%ÁÕ*üË)òKþé›ZºÐ_ç›ßüæóN;í´¿mmm]ZÝpÕUW}4”>û&¹_r{÷êæ®k£Þ¾#ºÕÈTéXŠ;X+ȼ¼ QUüOµ˜ßT_ß³Ð_çªU«ìcû›'=éI«VñŸºõÖ[?xÇwl _øo²@b²Ï÷Ùf#€º¹}àîpÊü£Ý¾cç©‘™µ¶\[8¸+î+¬¸WCO#"‘«x±ëfê±ç42Ð(…ÿd…s%gý;^þò—Ÿxá…^‘Ìû?ªš¹sçÎÛ“Ëþ]v]ö¯œ3þ{¾÷v@ÝݱóoiÛâ°²}yxhøÍŒ5ï°Ðù=w ¦5Z-†A±Šy‘K ¢"¾0ƒï)÷k³™ë?Õýô–¾‰µ%ÿ¼w¿ûÝ|øá‡¿a¶ ýMæÇ?þñ߆ÇÎþ‡ ÿ‰[TÓq=G…‡6 ˜¹ØG’¤klݦ¡§1^1Ÿ$oÓ³ðŸ.Èï¾u>ûÙÏ>ä…/|áûz{{O«ÅoÙ²å¿?ðü8ì:û?ÛÂÿQÞ}ºY?ôpèë=ùyñóŽ ßÚü}ÍÌ€ž¸€»ý/Kz‰¼Žˆ·¯=âÑ À”…z¡ŒÇfZøÏ¶øŸn¸ÿž!ÿ]—_~ùóŽ?þø·åóù5ÚWc_ÿú×?ö]øoâ6•ó¸˜;éœÖ;wÞNê=6Þ ç( Í,zF¹èG˜ÿ_fÏ/òKäµ·´kdÈV¡?ÝógòT«ð/Uôïù<¿»nn?ýôÓW\rÉ%ï\ºté3k¹zè¡/}æ3Ÿ¹%ýs0á÷,”ØþB¹í"êêÎd!À˜€tñ¶t„C:Ò*µ_ÇÊäR™ ¢ÞFW(Ϩ Ò²¾œb²¢ÿqgý/½ôÒ žøÄ'¾3Yáy-7p|||àºë®»&ì:û?^b[g| EPW±¯žÁ=©÷¸ðí?ÑØTìøž££ßÆ»å qÈr_˜á÷MõØlÎúOöùžËûÏú¿ò•¯|˲eËžê°:ËÚµk?ó½ï}ï°ëìÿd«ýÏŠ¨«[úïˆ~ŸØ{¢€‰ù2™»z.…pe‰}@GNŠþªþ“öSûÓÝO ÿ=Cþ»ÞúÖ·^xÊ)§¼£Ögý÷ÙüÁ~ð韽ŠÿB™ÁCYûXÔÕº¡Ãæ‘­aqÛBEìÓSIFôõ6Þ7ø@ÒØe+ŒF½}-²[ø—TRø—*ø+ ö>ëßqÚi§¥gýß¼|ùòºœõßãæ›oþè]wݵ5”žû?“ý½O@ êîæþÛÃY O‹vûÒyÜ«:V„“«@¹é:0ê`,•…@Õ Æ£Þ¾yùn qøåžíŸôõe• ý/g‘¿½Ïúwï>ëÿözõßc``àþ÷½ï}ׇÇÎþ×D‹ã¨·›úo~Oé=ACSÙ13?þcFPI÷4DñÞÿßÄb¼Ô×§+øgzK‹þâ"ÉYÿ5×^{í•Éœÿkê]ü§~úÓŸ^½mÛ¶°ïÙÿR·™r þ~ÛpÆ‚S—7þ—Ʀl'÷ý6Þ¶óN -@Ü¡Ba_Ÿ*0¨æ¥ýöÜò{Šÿ·½ímO?ùä“/›‹Â?µ}ûöß\qÅßJîŽTi_—$êîöäJÃã#Ée Ú¢ÝÆS矺ó]açØ€gZ]É|è“zâÒ×üÝ÷hì2D¾@½/·èÜ{‘ºB—ûÿÎd¥ÿéVùÏï¾uœzê©+/¹ä’7%sýŸ7‡û»ðíoûCaßËþM¶/\hÖŽíHÜŽë9*Úml˵…S{O ÿ½õ48Ó:mÁÉQb©ô5ûÊöÕ{x8/?O#C\A¡ÂçWòœ™,öWêÌZø§—!é¼ôÒKŸ‘Ìõ[[[Ûò¹Üy6løïüã7†]sÿg³ŸËjksâ¦þÛ¢ßÆß‰x¡Cªë¬ñ+¿é»ECW`ÇX_ÔÛ7¿µG#Csü•|=WáÏžjž˜¢¸o)ñyË^…÷Ygµÿ§>õ©«Ï8ãŒ«çºøýÜç>÷á°ëì¡Ä>˜­}‚#€9+~Ås¢ÞÆt€Ö\krÖsTƒSRk.NOFÄî×ý7kì ôE,n[¤‘!AAaBÑ^(3P˜épÿ0IðèYÿË/¿üyÇ{ì[’¿!.»³nݺÿüêW¿zWxlá¿ÉöA9gö “|^ØëñGï €9ñ«¾›Š‹\åsùh·±'âš®ð?ÛnÔà”tRïqÅc%fãÉ%í²°øg5ííZÌWò¼É>ŸîûË)ü§*úÃîÂ?½¥óë:_ð‚ýœç<çí½½½ 3änlllàŸøÄµaß¹ÿå*LSü—ü>0'úÇvW?fÞ‘QoçKž"`Jç.:;úm¼s`mñ5O@ä#–´  ÁŠûRÅw©âºÇJÝŸ®èŸê÷)w¾~wñßqÈ!‡,zýë_ÿkÖ¬yI.—k¨Åvî¸ãŽùÙÏ~öpØ÷ì%gý§ &%æÌÛ}ð¤O ½É\×£}œÇéhéO^xzôÛiþåúÆâ.z™^ P0  LuFºû“M˜iQÎpÿ}ùK ÿ§$óüßÖÑÑq`£íØááámúЇþ5ìºì_¹Å~ašÇ å|E9óó¿Š~Ó«çœs>ÖˆÅꦛnºníÚµ[Âcgÿ+Y8±0Mñ_jþ¿5€¹uKÿíÅK]Å^=}ÉSÃ7|]ƒó8ç->'úmLÁüåŽßjìJ€ÈG¤Vu¬÷®ÓØÐœEaš¯Urö¦ þíSü'Å~÷Ûßþöß?æ˜c^—Ïç4êÎ|äÊ+¯üBxüÙÿ\‰â>”(ôÃ4AÀ¤ß/æ°0+.xf2L>fGvŽšwx¸µÿΣ–·/ §ôžýv¦ÃÿLJ4x…b¿ @1h_¡¡¡1‹û™þ“ÿ•¬ü_iá¿g¸:¯¿ãe/{Ù.¸à‚wtwwßè;øÆoüä¶mÛÒ”·œ…ÿJÓ(É`Neehðï.–ÆfÏYöôÐ’‹ÿÏð϶ÿRcÏ@ìWH­îX©¡¡± þé öRC÷'>6ÃüK ÷O ÿ®#6ŒlÒèÿ{Ö’ó3±­7fä5^õ #Vw Tôç¦)öËYѿԀr~—rÎüï=׿ó²Ë.»èÄO|S{{{Ó¤‰?üá?>::š‹/cŸNu–¿Ô× ÓFs*ÿ¹nh}ôÛٚˇç.†§è‚dîzuˆØ=<¼!Ü5pŸt}”tý„˜Ô¹¿††Æ raêùù¡D±BéÅs¡ò3ÿé-=qÝ‘Üæ½èE/:áºë®ûä©§žú÷ÍTüoݺõ–«¯¾úûÉÝÑr õ B€ʼ@ú˜˜s?Þú³Llçs–^æ·öjðÌ÷¨ráùË/ÊĶþhëO“ÞGA£Ï@ºß6ŽlŽzWv,½ù UôW; ˜ÉÐÿIW÷O÷[‘÷Á þ?{çG}¦ÿ×ê½[ÕêrÅ4 ¤¹”#—Â%!„;ÒŽ$—ÜýÓ.—äH¹¦0¦cŒ1Æ`Ó1¶%Ù–mõÞ¥Õêÿ{FŒ¼Zm™í³3ÏןùlÑîÎÎoGò>oyÞË×çååÅ݈¥7Þª.&d~ï¿W_÷ž  Bˆ ØÚ¿ÝÇ™¡f^ÿsÉÇøÛœ Ζê´E¶8Öçû^â]Ö V—^ÍšØ þ@Kõ©¦Ï[Ò;[šr÷Ϲîºë>÷óŸÿü™ªªª«,XwÏ»ºv¨Ñ„ÈxMIàÙo‚?òÿÙÇ3@‰9o5JÏdŸ-Žõ²…ÔÜ߉=éßçK?e‹cp ÊÎá=üÐCÀž! µü  ‰­øbÞ›¸wø¤øOð üåx¹Ö5×\sÎwÞ¹nåÊ•?MJJ*ˆÓµv®_¿þ6™Éþ{ øþ¾Ä¿À9ûa€sPêúBÿ˶8Ö”„dù\é'ù¡Û”^(•iå¶8Ömý;djzŠzX½¬Ì\Êšsø „º%ÊñrÿÌ|à *cþ'uyw<¸ûû¢¥¥åù|p—xîý7"ü½=ÎhÀœû „˜D,l·Í±~°è"Yž¹˜ºÍÈHL—Ï—}Ê6ÇûtÏf~è!Ò9aý €S³OÔZ!¦  ,ߎýF³þºðGYFIIIáõ×_ÍÕW_ýDQQÑDâû„Ó霺ï¾ûîùcÿþTøºBˆyxeàMÍõÚÿ».oUý«6€Ø‡«Ê?§FAÚâXáþÿÆà.~è!Ò:Þnùc„1*Û‰™Ð7bÚg¤·ßˆð÷ ÐúüÕ–õÃþðcùË_6,^¼ø;‰‰Ê8É477?µiÓ¦f9^úï+KoÄÌOÄw€ß*!¦`rzR¶¼f›ã…ñÕå%—ñƒ· 'f-—,¼Ä6ÇûtϺÿ‡cm¶8Î3sNå‡MHì‚Þn{ „RþïšõŸíó¿êª«Þ½fÍšµgœqÆúY¦ONeÿÇUÃßÄ{￯콯*ßž‚ ³× „˜†=[lu¼ŸU^õé5üà-NjBŠVña§2ç Ý›ùÁ‡# *ìH¹¤ð|~Ø„˜#àM¸‹_òï*þõŒ¿Öçî¹çÖÞzë­¿úèG?º6++k•Õ¶©©éÑ×^{­Íƒø÷gÜç-àÍàoÚÇ6/À!Ä4lxUú¶9^þ¸î;Zo8±.ߨü²T¥UØæxßÚ%GÆñƒãÎq5!¥×òǹ(µ\–Ñ…XŠÙÿPKý]ûüÓ—,YRò‡?üáÚo}ë[O-\¸ð­¨IÇÈ7Þ¸Vfzÿî"<áhÿ¿xØÇœë BÌóÇR9†?Û»ÍVÇ\‘Z*ß®ú7~ø®ÿïW›x¤k?ø0rtÜmS#R !QþFzû>ƽÄß½Ç_þ©©©¹ÿû¿ÿ{Å/ù˧kkk¿¦úü³¬ºÀ»vízXUÀÉÕ!þ{õ½ ÿ`úÿ}2@1O÷?ÿ½òñâñ÷hïøºÊþÛ Tðlé}‘~94vÄÇyQþÙR¶ˆ8!±xº?Ð>ÿDá¯ü}÷»ßýÀ]wÝõ؉'žø“¤¤¤"+/æäääÐ 7ܰN|gÿ½ w#SŒT°€ìÞ+-cö+þ·E_óòÞÃÀ"%ÈOë¿§õÿÛ‰'»ŸÕ =Iøh=l‹ãLX WW\Á‘€„ÄVøkê— ó³þšÁß7¾ñsaðwÎ9çÜžž^o‡E}óÍ78|ø0ú·|eÿ ÿio¯+ž„¿~›BˆéØØ»ÅvÇŒ/½ÿYó Í-žÄ7Ùª¢ñ—‹(%) muÜ0«{”åÿaçàX‹mŽõÌÜUòÅl ÄDÂ_Äxù¿žõGÆ?ó3ŸùÌ©wÜqÇ _|ñÊàï»,ìøøxߟþô§õ2?ûo¤_ß_@Ä{5€§×ð„ól:B ¦€?­ûž4¤s&v¼‚Œ?2ÿ5i•¶;öm};lÓ¯MìR ó•ŠÏË HH´ÁT¸ôÓœý/½ôÒ†›o¾ùW—_~ùº‚‚‚˜˜à$''KfffLT¹þ¯ëè耣õ”^öˆË¿·×sß×¼K!¦£U¾zuð-[{vR–üfÉËŠÌ¥<⌴„TùYýÙ¶Šã¾Ž‡yDø*ôLöÙæx“$© ÚÊÅçòÃ'$6Â_ƹŸ«Á_ÆòåËË”³ÿw¯¹æšÇKJJþaÁ‚‰±þUUU¢ö/ÃÃÃQ_Ô±±±î?þñŠ÷ì(â_Ä÷(A÷ÏÂ!Ä”¬ï|¶Ǟ•˜)¿^ü#95ûDžqö™­²égÖ8²_ÞÚÍ!bë»ÏVÇ›¤tZ¢~¦Å)E<‰\À“Ø÷•ñw5øCÆ?£²²ráo~ó›¯]wÝu”³ÿ—¢o~á_]]-§vD¸9óÔíÛ·¯íëë’ãÙÿHˆ_•îO—Ú‡G!¦ãïý/KÇD—m¿ü!›üsõå÷ºƒçú^à ab&ÊÏþKsý·+kÛ×óDˆpà=¹ï²Ýqã˜OÉ^)Ow?'Oö<+{”Il¼üýNV-] ¦.HQí])êz†v™ª~65í­}Ûyb3‹qýN·çh™ÿ¬oûÛ_¶lÙ—”É—5ÿòòr©¨¨ééiÙ½{·(“iWÙÿ'eÆøÏéçáÁ–ýûsÿ7â30Í!Ä”8§òp×Sreùgl»ø¢øÃºoÉšö‡dõÑ¿ÙÒÁì¬ÌZ&?®ýŽ$çÙv ŽŒ·2Haö ï·í±§'¤ÉG^ªmÇ”ÇÄ[C{d×p“4© HÇd·ôÙ³Îä„$íï,Äyò‚dm_é‰é’¢®g¨Ë4uÞ,™êçºÏV¢âÞóó’Ôó2 ýÎ0@LX ÆÌÿÜ„Æ×¿þõ¬\¹òK©©©e±xójŒ &ú±%&&jYÿ;wÊèèhÌô…^¸WFå¸ó NÿþÆý‰øŸ /î?g€bZïÚ(W”}Jû‚eßÿ¡ȧK>&•©rÝ¡ßËÈÔ(O “ð‘¢Käk•_Òz–íÌ­÷i;9ìÖàòÔRm»´ðüÙû0v²k¢G§†Ä¡2ë£Îq•aŸÒ~–¢D{Fbš›Oծǒ̄t~˜ÄìAw៨ ý2¾öµ¯}褓Nú‚þå±þÈúã:]»vÉädìFÐ ýýï¿QfzÿC1ø æ¶x xbšBˆ©éSæWÏön“K ηýZœw†¬ÎøÖðæÐ.ž1Fߨü²\˜¶í×ÙM½[yRD"k¼(6É6SƒqYj‰”IIܼg#U„ÄPü'¸<&)???ý«_ýêO9å”+b%ü‘å/++å70+üAWW—455ÉÔÔÔ\•;=£ƒ•¡Ç×KOOkµÀ–-[îQïa\<;ÿ­ ¬ì?¨ì?„ÓóPç“ ¼CiJ±\¿ä'r¯ê·¾õØ-óE¢ Æ“}§úߤ0¹€‹¡¸«mÝl¶•D–7ßfÀ"`\(*‡P±@ˆ‰®Nÿ‰Jh§^{íµï;ýôÓ¯T‚ÙTÂ;vL80+öuœN§Œk"ÞA«€€2*”žžž°úûûþõ¯Ý"Þ³ÿF‚ÁVˆ—à€'hH‰`úôºúâ{Jö \ ™i ¸¼ä2Íë-7Ë+ƒorQ¢@^R®\Yñù@á…Úg@D‘ =›¹QâÍ¡·åCEïãBXx 8¹Ä ]økÚ0-- Âÿý«V­ú¬º“¨£/áÁ¿oß>ikk›÷<Tdddx|Í¥K—j?knnÛ{ݼyó—ì¿3ÌA€°gÿ „Äw¶ÝÇ€Õi‹äWjìÜ jZ­\”€qdÿ°ðýò/e—kýÃä87½“½ÿQPbà0 ˜õ €Ú)ÊÜï‚3Ï<óó™™™±xSº«¿k¿+÷púïíí÷3¸ÿã9YYYó~–’’"Ë—/u\Úˆ@÷ª`Aöÿ–[n î¤ñíì¿'ñO@BH|ñÚà[²S9?ÃqÌ•«²O’õªUâÞŽõA;b÷oF äܼwËÊ?-Ui\7ÞÚ­ŸHôèTŽ÷ô°P@M $† ë7Ìd•O½æšk.z×»Þõ©X ÝÕßpúûí·1no®úUb¾½½]rrr´¿¥a{ß›6mBïÿ˜ÌïýD @ <1ïq BâTü¢á\ ŸôS%U™êKå‘® ÚØÀ‚ûF´ AÎÏ{¯|¶ìR“VÉñøMbZþª²ÿ$úlïUˆ aÐ@H,¿:äææ&_yå•窌ÿ'•p.•ð_´h‘&þ¼>nppPsúŸ˜˜˜s?n=zT  ËïŽY(‹/ž}m¼N¸zÿUÅAóm·Ýö¢ûËìÿ< „Ä;^×ü–e.æbx ¤Ê'Š?¢ÆÓ]ª¦'lUUOq|˜A²T6îâ‚óäcÅPÖr.ˆžîyNÍaoäBÄ€^‘dÀ°¥ˆÄŠ”édùÞ÷¾w™2÷{¿rõÏÉ{Pb¢}þÞ2þ:púollÔÌýܸö3˜úyz ª««çLèè_»¤Êþûêý1iöŸBH\qgÛýò³úÿäBø ¤Èû•Y¶Æ‘ýò°jØÜûw5{Œ‹ãÆŠÌ%òᢋå‚ü³´ ñÍÈÔ¨Ütô..DŒxcp—ö0{ÿð3$Q?çœéròð29mäI=;åÓ1ù~’šªeüKJJü àÍé÷#“_WW7¯r@wú/-[Ô€×èîîËq¨)ûTï?²ÿfïý÷ `€7¼ØÿŠìVUËY`˜¥õjlÝ5òu5·þ¥WUeÀ6mÇã¶]“ŵrž*ó?/ÿ½R‘ZÊ“$ЊÓ=ÙË…ˆýùªšüqvÞ™\Œ8‡$ZäNe˪¡rÒè2IšNŒÉ{Ð…?D¹¯RW±¾ÿ~imms¿ÃáÐñW__?ïy*,Y²Dòóç6@üãùá@eÿת =û©~ÿpgÿ…BHÜÞã?¹Uþ°ôgÅ辪*¦vØÆ”øß>ðš¼2ð†¼¬Z+¬>A™ý“³Vhf‰gåAÑ$Í£‡e]Çc\ˆƒj,H`€D–…Žy×ÐJY6ª²ä’“÷¡ŽQ~ÅÅÅsJñ}áÍéhhH  zÀ=»\þ=®òõ¾ö©Þÿ—dnï¿ø÷ÁT øýAeÿ „Äè=FûÂü³¹A’¦± GÇÛ´`ÀÎá=šÏœÆãú‹µÊ¬¡òaEæRMôŸµD’$óƒŒûûõá?‹cÚÁň1Ûúwhí<é i\Œ8&-$BTL”ÈéC'JÝxeÌ’%áÈø/\¸Ð°ðãããšÙÄþ¬rUÕpîÇø¾šš)((ð¸¿eË–i•ž€Y Ù–cÛ¸qã½xIñÜû¬à×Ã’ýg€—`þøY¹ghYm†/ *#^±°T>ª¦€AÇìÙ+ÃûäàX‹´Œ“–ñ£ªm`ÂTï_lJRÊ¢´2©N[$K”è_šÑ •iå¬ 3v>®µß؃öŒ`d4¾Éd€„%÷Æ«å]Ã+µ@ÌÎk%Ä«ªª¤¨¨(àçkcþÐA5ÀÁƒe``@sóÏÎΞ÷¼¼¼ÔHA-ãï);oPXkeÿü:###ZÉ?Üÿ‘ÝG;;h€ ¿*T„ƒ 6Éþ‡³÷?ìÙ!qË=íÊ‹.ÒD!‰<äe)ÅÚæ‹ ç¤ M kÛ˜*SFÕÀÄ;A)U>>:53‰ EUo¤¼SÁ‘ ^_†Q¦Ë,µeð˱)@à纃Ð|#ˆy€¡g» È¡†Ä'ô !å̇U›Ûð I›ŽÝdß1j/'''è×hkk“}ûöÍÉÐðïСC’––¦‰ÿää¹Á~~´`Œ ?µ‰¡‚ìÿwÞé-ûï+j;€»¸)ûÏ!$n ùó‘Ûäµ×r1L2ò yRœÇŰkÚ’7‡vq!L<žìÞ$W”ý#Na †’É"MôÇÒØâ™~”úgeeý:ü(ïGo¿ë}¸ÝÞÞ®àôï^Ú)pú7Zm.ó¿§žzjËþ"øEŒgÿ§ý {1ýg€×À FvçF /{GšåÖÖ5\“òX×Fùlé'$qA"#.¬ F•²h†~g $“±ëï‡ðGÉ=Jý=•ãÊú÷ìÙ£eúu&''µ’j~÷Ò~8ý£"Àhà×}KOOÏÞ»îºëe™qþDà‡3û/†ì?„¸çw-7ÉÉÙ'H^R.ƒ0—ùŸ¼ž®ÿ&¦Kùo<×÷½â” V?¤L'ËÊ‘ÅZÎTVÌÞ2î(µ¯¨¨ðê²pä‡ÙŸ«Ó?Êô8 dÀè@w`0ˆ1âßáýÿ±gžyæ>u1.sGÿ…kÜ_T³ÿ Bâž>Ç€üß¡äê¿ËÅ $LüöðrX>sswÛrAþYœz‡dÒ€x!ß‘#«FNFk&±¥÷þÈø»÷à‹»Ó¿>⯥¥E»Ž¶‚ââù^CFœþ=ŽòÕû@9ÿïð!þÃ!ú£–ýÇÏ „Ä=Ûú·Ë¦Þ­Ì„èxLžîyŽ =$;^S;Vq1â w¹V=Q.',•Åc51 ê!îgüܾèëë“]»vÍ:ý£  ¹¹Y›€*¸ùçççÏ{žQ§wdèïïù}oÞ¼yÌdÿuþ7úX‘(fÿ„Kðû–ÕrrÖ N $v 7Ê GïàBÄw´Þ'§«‘¬ˆ/RÕ”$åßà˜žâbؘ gºVæáŸ;•Ó÷‚¾þòòr)--Õy8qwúÓúýáΟ””$ ûúÑ à©ÀÈþ»N†–Ûn»íïâÙùß]äkþÕì?„Ë0à”ø•\¿ä'Ú89BH`t«žòø5ûþãŒ]ÃM²¥ïE9/ï=\Œxª ÿwû7ˆþ# JŒÅÖȽõ(ó_¸paÀYv#>|X駃¬<úýQ €j8úcÜŸ+:ýÏS¹Jø‡£üëÖ­¨÷éîüoDè›6ûÏ!Är_„ÿtäVùfåU\ B¦ßÛ÷3ÍXŽÄ7½SÎÊ=]e”ùµ.žÈLH—aÀ.ÀÔãûNY!E“ù1?(·Gv=772&Ê(ñoll”®®®ÙûŽ;¦mzàañâÅZ€+ð€Ù_(#dÐ}‚E™¶þõ¯Ý"3£ÿü úP²ÿžÄ¾7röŸBˆåx¸ó)Y–Ñ ï/¼‹Aˆ¦Õ¿Ÿ7ÿNöäbÄ)­ãíÊ»áqùTÉG¹ñHÌä"Ø€‚©\9á2ÿ4gjLß 2ü±‡ŒvväZàæ¿{÷îÙ|dûQò¯JêµÛ999R__?Ïc ##Cÿ¡N@ËA¨¼øâ‹ª÷=&Þ{ÿžì¿ø øöF³ÿsÇ!Ärü¶åF©M¯’¥*@ñÍŸUÕ Œ4I|skë9;ï )O-åbÄ h]§•™_µœ2²\*&Jbÿ~”ÐFo¸Fùù}ýpúÇ%ÑÄ¿ž‘/**’êêêyí¨DX¶lYÈÆƒ>Àp0Ô{îTÙÿge~ï°Žÿ±Îþ „K3áœÔüþ¼ôRœÇ!Ä ··®•uÊõŸÄ?ãÎq¹^?ÙðÆ ™œ`9 ¹Úø¾•#K”Á_ZÌßîès?÷RûH€ ?œþ!ÂÊÿÑÿ¯›ñá}`s£ÿPŒDûA(ìØ±c½ `ŒÈÌè¿@ÌÿLŸýg€bY:&ºä?öýD®_üÉNÊâ‚âÚeno½— a!^xCê|B>¶ðƒ\Œ8€Ö IeûëÆ«´ÿêñrS¼'ô×ChCX‡ÛÑß—ðnjjÒÄ7ÿ‘#G¤½½}öçÈúÃhÐPœþ=~ÿ ÑüOM(èùË_þ²A,šýg€bi0#û?÷ÿL~½øÇ’–Ê!äžì~V~×r‚üåÈmZûÓŠÌ%\ ³XÏèNþËÇê%ÙiI…2zô÷ëž,®Nÿ‡C+ùœ1¸DÙ}w³AÜñh Ø'ZBáµ×^{TâE¦$0ó¿¸Èþ3@±<˜ ðƒ¿Ÿ×ÿ'ÇòŽøÿÕ¡?iæÄz`®üÏþVµ@]'¹I9\“Å€¸&~KÆj´Þþ…“¦xOÒÑþÈüGdû÷îÝ;›u‡øÞ·oŸLLLh·ÑÏq~îï NÿK—.ÕÌÉkÅA0(Ÿ‚Õûÿ¤Ì8ÿOIèŽÿ¡dÿ݃H!FAYì/þQþ_í7ÙK(þ)þ-¦`¬ãõK~Âê'“΀ø@ý¹¬ž(—£ Jü×j%ÿf šÆ~ž@¦ýþºÓww·{ˆ8ý»÷ûë"¿®®n^p¢¤¤D»?Nÿžµü_Ó“­­­ýÄ¿¥²ÿ BlÇßûwÈÿÛÿsùIýwÕ—¯4.±4Îi§üþÈjÍñŸØ“ú_–5ÿR~\û­ Š˜Ž4ùûf+ñÑpÎG™´ûû=ûÆÆF-ÓîÞïàE·w‘n§wP‘à„È]½zõ#2“ýw(úã*ûÏ!Ä–¼2ø¦\ÛôC¹®áû4É"–eÔ9¦•€#èEìÍKý¯Ê×ÿK~Zÿ=)N)ₘ&À €XR8™§eúWŽ,– §¹>‹””)++Ó6÷2úX±~ÍÍÍÚõžžíºÞïЖ€Í=€ žÆÿ…×öƒ`ؽ{÷ÓÊ¿ }ÜŸ©³ÿ BlKãÈ~ùwøyÃIiJ1„Xж‰ùþþë´Q˜„€}£ÍrMã÷ä¿ëþƒ#M`@´A/ÿòÑz9A‰þ‚©\Ó½¿¬¬,MôǬ¿žšT"eþª<Þc¿?²ýUUUóD~¤œþÝù_gggÐÏWÕ wÜqÇz9žý¤ü?î²ÿ BlÍÁ±¹zÏÈj¯•Ó²Oâ‚KðæÐ.ùñ_KŸ£Ÿ‹AæÐ=Ù+ßhú¾|¶ôò9µÑ5¶d° *`tßâ±j-Û_1^bºi@úèëG™¤ÅrâXöìÙ£eü=õûë~øÌYó´4Y±b…viúúú4?‚`Qc 7© Dôì¸zþM™ýg€b{”)àw÷ý|©üŸåò’Ë8&Ä-p÷°ãq¹áèíÚ,xB<~¡WçÆí­÷Ê«ªê»Õ_•òÔR.JŒÈL`@¤@Õx¹rðo†ñjI˜6_° eþÈôCøãºÙ×Ìþ†‡‡=öû#ÿx±jŸÈ˜{gggkcþ¢Õº€Ê„`QÕŽ»îºë!®žý7"úM—ýg€BdÆ( éûFšå;Õ×pn6‰;F¦FäW‡þ,Ïõ½ÀÅ †xkh·üË®oÈ?,¼T¾¨ 4E>l+‰JôW+Ñ¿Tù5¨ŒÊ´9'_˜±Ì߈þ;wj‚¿··Wë÷G©½2ûç縀 ‚‘rúwæA?ÿÀϽþúëÇdÆù?œæ¦Íþ3@!.<Û»M•ï×þ»T§-₸rÿ{ð÷Zß?!à˜vȺŽÇd[ßø´\Tp« ¢¦2$-HdÅN((ÉS1Y"KFkdÙX½2ó3g +11Q둇ðGÀÌÀéeÿ(ÿÇh=˜ÿ¹0$)i®ŒŒ´Ó¿'ðþ\A4¦î¹çže¦÷Ê€˜·DöŸBqcÿèAùÊžoËeÿÄ–bjPÊ}WÛ:¹³í>­Š…`Aðèç'Sçþö—ÿþí‹™‰™ÒïàBHÉd‘¬©WÙþ:Étš×K!==]JKK¥¤¤Ä4nþ¾8vì²âšøGÖÙWòòò´ž× ´œþ=xéè>ð}èС¿¿ôÒK-2ÓûïMì[.ûÏ!„x`Â9©µìxMþCõÈrJ1#ß?p6Þpqhìˆü¤ùÿ¤üX©|¨è}òᢋ%;1‹ A2TëE¿0ऊ' µò~l9Sæ=/!ŽaЇlaaaÔÊáCYtPö~ôý»‚ †{†Upúw7Œ0& Áüoú¾ûî['Ç{ÿžñ"áËþO‡"ò „ x}ðm¹r÷µruÅÚ—afĈ™¸¸à<HD86Þ¦AQ€ó G†ªtŽªu= ªÌPiv`ô°4«1­lÝñIádž,Q‚¹*ïÏwä˜ú½ê¦~ååå’š?^BȤ£ä¥ÿCCCšø‡ã¿+8&l®À`ùòåZ•C,@ù°>|ø¥-[¶4Ëqçÿp˜ÿyôf0@!addjT~søÍ\í«‹¾Hob.Ì?[žê~VUª¼ÎÅ ûû·¾óIm«L+—÷åŸ+gç)µéU\ ¤ÿ€÷®ÆÎŽ;'¸8¤L‰£HêÆ*eÅh½äMå˜þ-»fûÍjêç W§ÿÎÎNã9=õ¨^¨­­Õƺm§w`þ×ßô¨Ûé‡zÙÿ ñý¥ü߈ØzïÿìçÊ¿4Qaûݯ/p»î¾%x¸ô´%z¸Ä†ßؼ ^ùÇgøñbŒDeÖtÙÂ÷Ë¿”]®ú6éÞLbz·¿¸ë›2æçb¨Q¦Ú¢Þ›wºœ‘³JNÌZnÛÉ)£Î192Öª‰{dóõÌ~÷dO’Eÿ¢ÉR•é¯Ñ¶Ì)óÿÿªgûÑß« x¨@ôCü#£¿¶¶¶¹ßy”q!ýÝM èÀý± v_úI ø€$,Hà˜Š.ý¸Ürìn.‰([ÇßBlp±_šÑ 'gŸ +3—É’Œz)Hγ̱NNOª–ˆvi;¦Jø[å6u—ú¡‰~ݽéxm\ˆþxìí÷F__ŸìÚµKë÷‡Ùn»‚Ì>Æü¹7ÐP]]ÓcG˪‚eÆ ÉÜì Yþ`&xî1Éþkç2ÿEço†ûY@Hœ/½_©øœœ’½’‹AbF¹}y÷·47BÌ@Qr¨Ï¨ÑÚ¦*SËU A…i+úTÉ~Ïd¯tLti}ú3Bÿ˜–ÝoŸèTß¾§ù¡†$õõ³b¼D+ï7»{¿+èç‡Ã}¼õö{™~ôù£Œ~ïÞ½Ú¥+ýÈð£ÊÁ5øQWW§Æˆ¼ï`P>W\qÅwe&ûA×ì¿§¬¿å²ÿ3¿‹„B‚¢qdŸ\»÷G²2k™|ºäcòžÜwqQHô¿T/H’k«®–o6ý€B…˜‚.•ïêï‘¿÷ï8. Ô¿…)…RœR$ÅÉE³× ’ò$7)WmÙjËÑ.Ñn*¨Øž‘^G¿&îñžºõË µ9z¥s¢[ý¬OËò“È<$•ãešsÃX•¤L§ÄÅûFy;úÞ‘íÇè;«€5þNëŸ×Çý¹’““# sÊûcéôï‰PÌÿ6oÞ¬gÿ§Ä˜ù_0®ÿîß“pYöŸB ;‡öÈÿú_HÌ@öû /'º7q1ˆ)Ap vlþHMH‘µe%fjUÉ ’µv«Ì„t¯;453®lLõäCôãö8}1bFº3MjÇiýüµ‹$a:~Zå222´,7¶XÜE”Í755iÙsOf ¨¨h^y¬þÝ•àÆfªç¹ãŽ;^’™Ì¿/±ì8@‘àÇ*øC 0@!a@Œ]^r™¼;÷4Ž$Qã+Ÿ—ú_ÖÊ™ ‰gà–mÐ1ÄňrYR?^¥zúk¥ÂQ"ñTŒ³;”øCô#n5&''µ~gÿŽŽù£'afXQQ1GüÃüâßLw£Â@x饗Vˆ ºfÿb|ôŸSŒ—òÉèÇ$ûÏ!„D€·†vk[Yj‰|¸èbù`áEZi+!‘$G•N¥â ùÅ¡?p1!ÁíòÉb©­”ú‰*)œŒ¿2y\”øÃÍ?ÞÆ÷eddDvîÜ©eÎ÷ïß?otUU•qí04Óº„bþ§Ž¿çæ›oÞ,áËþK?ó'죒ýg€B"H«r޾éè]rÛ±{µ‘YŸ,þˆ¬È\Â…!ã’ÂódCÏfymð-.!$¬èýüÈôÃÈ/ËãpQÒ®gûãu|ŸQàì¿{÷nmÜLÿpâ¾¾¾~^o¿œþ=ñïp8‚zî믿þØÐÐz…(ùÇš™T1¨ ~pß»víÚ ‚ýâÙù?Ðò‘8Ïþ3@!1Â9íœõ ø“ ¼7÷t9/ÿ½ò®ì“ !ó™’˳=[Õ,óV.!Ä'iÎT©šPeßãåÚ¨¾ g|–Æ#ƒ ?¸Ù£ÌßJ.þ†¾W(¡¿wï^-SÞÚÚ*ÇŽ›÷˜ììlmÌ¿0ûËÌÌ4í±›ýW¦Êùÿ™Ÿý& œ/€?aÕì?„bàvýlï6mè+T`‚Ài*°$£ž D&%!Y®­úWùÖÞicÒ!ĕܩl©WYþ:ÕÏ_9Q—¥ý:®ýÈö£Çߎ 7Nÿ½½½ràÀ­ÿßd÷QâïZ aF§">hó?Õþð\cc#žìߥþÁøˆÄaöŸB1®•7©Ûe)År¦ œžsЬÌZ&Ù‰Y\$bˆS²O‹”ßÄÆž-\ BlŽæÚ?¡\ûUY½Êò:â»>55uVôCÄÚ™±±1ÍéýþèûG¹¼;0=¬¬¬œs|Ð `ööˆ‚`zݺuÈþÃaJÂcøç+ Ù!Ää´NtÈCOhÀhÁ3—kÁ€³–KuÚ".ñÊ5‹¾ ;^—~ǃ›‘6­JûUY½ÖÏ_%©Î”¸>d©u3?”ú›Í¥>`¬œþq‰òw³?€1X3WÌêô¶¶ ž§ü^ܶmÛA™ÉþÍú:P¼~OÂÝÙ!$Þj´ 6ŒzEÉrRÖ Õ*P'õé5RŸQ£¦ är¡ˆF®š4ñ¥ò–ß¾‹AˆÅÑ üR3¶HjÕV>Y¬Ýï¢&~Èö£„¢ÿ8]]]ÒÔÔ¤•ýÃéß=KîiÌŸÙþ=8FFF‚zîã?þ Ïþ‡jþçÏÐW ÀTÙ!$Þ¿LöȦޭڦS˜œ/uéÕ3µáú¢´2I^lË5BÅуrVî¶<þ½Ožê~VÞVÓ'!Ö"y:I*ÇË´ íø"ɞʌÿcR¢b¢⟢>0øC¯GG‡æú?==W#Âäåý®ífwú÷D°Ùµ.o©@ã;gb?˜@€ˆ÷€˜gÿ „ Ò=Ù«m(ýÖAhaJ¡”«‚²”uYªµTàRÝÎIʶı:†ä¨r¾oÙ¯m;‡ö('ü'ä_-þ‘f¬h7ðÙÿ{ÕWäê=ßÇôA‰s¬dà§'z]ð#c­‹~Š7•¨„>úüáòïÍéþÿ®†ˆñàôïÎÄÄ„6Ê06nÜøÌwþ÷—õd  Hœfÿ „»|iPÿ:&º´íuy{þ†„T)HÎÓªÐB€Ö\ê÷¡”„‰i’ž®.£7&jÌ9.ÃS#225*#ÎR×!ô;'»¥}¢Sk‰Àe›Êôã1Þø}ËM²zùolY *OTîi¿ „ÄI*Ë_?%ú×X"˯ UôôCø£§ß›àe`W§ÕßîQCàCü'%%͹oÙ²eÚzÇÈþ»W6AM@h¾ûî»_•ã½ÿá,ÿ÷V ‚â#`q‘Ï!„ŸŒ+‘­û %+1S ¤'¤i— é³÷Ë;_Ø%aN°ÿ˵½³)õÿ®»`sŽÉä´C»>ä–a%ø1!´Œ“{Û–Ï–~Ü–ŸñçË>©šD „bnå¯V~ý5’8h‰ãJOOŸývwï8ý¿ýöÛ288¨™ý Í{L^^žÔÕÕÍqõÇ}K—.ÕÊÿã §Ó)íííA=Wÿ­Ç×™ßûjù¿øþq“ýg€BHÐ M k[<ñ·¶ûå¢ü³µö»*oV]%ßÛ÷Sž¼„˜Œ$%ð+&J4Áß0^-9SÖÇÈÞ#Ò~ôžë¢ŸY}ã@ô#óK˜þÏ{Œ§1¸x\ëîîn ü¡ ;n¾ùf˜"MúüÁD3ƒ¨Š|!„A¥Ã„üNµ\×ð}[ÿ9§Êyyï‘çú^àÉ@HŒqÍòWW¨/åÖÈò#Ì3?²ý0õ›§z(í·sœþe``@ëýG€;é‡MkUSS#eeeq{Üð7†;v<¬¼PZ¨gÿ–ÿ:þÏŸp7möŸB!¶cûÀk²­»m§|­òJyeð͸«Þ $ÞA–¿rB ~åÖ_3V!yS9–96Wç~˜ø¹–¡“àÐþ@Ï¿{?¼>ÒÕ:Xw8ý»Þo {lqð‡ªŒèWÙÿâ9û®^O·==^ĤÙ!„Ø’?´Ü¬&œ,i ©¶;v;~¡ürm !‘EÏòc«QÂ?eÚ:&¤šè‡ØÌÎΞ¥$4 ô÷ïß?ëòïÉé& s|„Ó¼{+;úoçÎO*cDD¦$|åÿ"Ëþ3@!Ä–`Â]ÊàÊòÏØòø/[øy¦çyÙ5ÜÄ“0‚±›åpì¯ÔDÉd‘eŽ Fr(íÇÑÍÒ~»´LMMÉîÝ»5§ÿC‡Iggç¼Çxó‡` œþ]ï‹GÐâàé˜ Wj·ŠFû9rDúúú´ €{ï;޳ººZ­¨ƒ` Ìþ"åô«€Àèè¨GÏttt¼­â¹÷?Ðòw‘/bÌýß[° ª¢žB!$ê|B.-¸@gÔÚòø¿^y¥¼6ø–Œ:Çx2[‘ëÈ’ê‰ -Ë_;±H¦ãßäN/ë׿·²þHŠo–ö{BÏž=ÒÝÝ-]]]šÛ¿»ðFÐýþøütð™.]ºT›­õV@½ÿîû2ÂæÍ›]{ÿƒÍö» ùpJÁ€¨  „Â/dÓNùÍáäÏË®³¥!`qJ‘\Qö)¹áè<ˆµy§´‚®ýVӇ̰žåw5ï³äGÇÁ…‰‰‰Y§ÿÖÖV­ÀÓg‰~|®ºÓ´Åy¤ˆ¨L~ÀÏ8ú·¿ýmû;Wñï«üßh@Äxö_<<>ꢞB!$@GöÉc]åÃEÛòø?^üay¦÷yÙ;ÒÌ“XФé$©W~ãUÊįJ2-PÚ!¨g÷qiÆù﬘‹îô£;dý‘ýwŸ#„¾kNÿµµµ~×'^âp8~ÞŽ;™šš‚c¢CB3ý d"€/ןKäÏ „B"ÉMÇî’³óΔ¼¤Û{â‚D¹¶êjù·=ßSßF¦y2¸&C¹ö׌-’%c5R£Jü§ãúx\Ëú!ú‘íG™x´Å7Kûƒ}þ»víÒLþöïßï±ßŸiCCÜ,?\þuú·€€§*¨I }7ÝtÓ&ñªÈwößÔ0@!„¼Ã cHn:z§|§ú[ÿÒŒUq‰<ÒõOwäNekcú–ŒÖZµ½ÞºàÇ–””diñmÕ@Üíáðòÿ½{÷jãþÜAÛ²üzPdž`ÆÿÅRœGzŸýÀ@Ù¹sçSjr°Ì7ÿ §ë¿/ñ#øþõ‰É_)!„žì~V.)<_NÎ:Á–Çÿ•ŠÏjº'{x2ÓS8™§²üµ–èç‡À×Å>Fô™µŸÆQ3êµr•±–¦¦&íÒ’’©¬¬œ½­{à<ˆ¥8Æ>ƒÉþ£ìÿöÛoB|;ÿ‡ÒÿoÄì/ì¿éB‘ B!sþ§ž–ß·¬–¿.ûµ$-H´Ýñg$fÈ¿.ºB~Ú|=Ob:`ÒY9^úŽè¯’¬©Œø=%¸Pö ±±çjúmñÍÒþðc»ÆÆF­Ï_eªµ O}îUUUZ¿<àôKW±l%ÇTB3úOµP<§Æ&v‹ÿÑŠ~obÞ[ .³ÿ B!h=¬F>.Ÿ(þˆ-ÿÂü³åéžçä¥þWy2Sˆþò‰bUÚ_#KÇêâÚÄeýz–åýz¿7Kû­´@ŸÿîÝ»5q‹Þôüó‡s™T‚ÄZœGcŸ˜‚ÌÛzà‘ã£ÿÂÕÿ/>n‹‡`€ø˜Bä3@!„Èm­÷ÊùùgIQr-ÿ«‹¾$¯î”qçOSÑ¿L‰þŒ8ýzYYYZ–ßìãùX1:èg‡Ó?.1Ú-î è¡óB§¨¨hŽ@¬Åy¤÷‰ ‰§)þ8räÈŽ­[·ÏÎÿÎ b@øö¦Ïþ3@!„xadjTþrä6ùAíµ¶<þŠÔRùLéÇå–c÷ðd ýžž®ev±¡Ä߈Pbi䃑Fͥלþaö‡ì¶§þvT€`Ì.uàò_QQaq}¶··kmòôÓO?¬.•ž’ð:ÿ{sÿ72þ/®²ÿ B!>x¶w›\ª ÏÈYeË㿼ä2y¦çy94v„'‰Š©œ,“å£õÚȾTgJÜJ¶õ>~Ý­?šB,Ä·ÕƒÈöÃá_ÔIss³ôôÌ7QEÆÎþúùc¬««Ó²ÿfç‘Þ'„?&#Jww÷ÞuëÖ픹½ÿ¾‚F"ÆLÿŒû¸Èþ3@!„øá-7ËÍËO””„dÛ{Ò‚$¹¶êjùfÓ4sDBÂ…îÞÂØbÉudÅÝû׳üüF³üVêdÝéâýþ¨píûúÚ"€6œ;Ñ:ÌPB^k”mÛ¶!û1 ž²ÿÁTˆØ0ûÏ!„⇣ãm²¶c½|¶ô¶<þ³–«*ˆ ÔxÄM<HHdOeÊâ±j9at±OÆÕ{×{ù!úéåg–ܺA d²‘õGö‚×álïŽû˜?8ü£ —fçÑØg0£ÿÔºvÞvÛm/ˆç£ß- °›ì?„BˆþÖ¶N.Ê?GÊRKlyüÿZq…¼Øÿ²ô9x2€Èp*±3Z++Æê¥tb¡Öç/@äëeýØtÇ~«Ã …0Òýþpú—¦¦&íÒ÷1"Aü{rú7ƒ8ô>Qá)HâW_}õ1å­0*ÆFÿ…êøo´% .³ÿ B!€þïZn’ë¾oËãÏNÊ’«*>/¿<ôGž Ä€š©ž(—“F–JÃxµ$L'ÄÅÛ†èAi?úù‘éÏÈȰ¥P·zÐ"TÆÆÆ4§YlÈü»—´£b¤¦¦F ŽO‘ÁuŒþ ô}Z) Ìè?µ¶Ã·Þzë™ýg4Ûïßåû¾Jÿ½‰zoUq×Ç!„b€í¯ÉÖ¾írvÞ¶<~˜!>Ýóœ¼6øOâ‘|G®,­“•ªÄ?g*>úú!Ô öuÑo4ËÏ,¹=ƒºÓ??®ïÛ·ož›½§1eeesÚÌ(Î#½ONúúú~ÞîÝ»ŸVSP~æ-û®i"JÁÓ  „B òÇ#7Ëi9'IzBšíŽ¥Ûÿ^u•|i×µ29=É“Ì|‘œN”ºñ*-Û_5^%þh®®ý,ígÐÂ0¯kllÔÌþpýàÁƒó„±û˜?˜jkk¥°°0¢Ÿk<àüïþ<¨àŠãî»ï~Lf²ÿþ„~ ãÙñðxS‰z!„Ð1Ñ%wµÝ/_.ÿ¬-Qj¹üSÉ?hk@ìMÅD‰œ8ºDsòOvšÿë$z®õL?D?]ûí´×8p@ÛLÿàüïNff¦–ù×ûûõJ8ýëÂ×êÞöÏ„ÎÎ΀_WY¶íܹ3õ줲ýâá¾i/A1(äg B!fæ¾öGä’‚ó¥:m‘-ÿseŸçúþ.-cÇx2ØŒ$I”%#µò®‘•²p²ÀôïYXݵýüF„³ä Z¸¿WŒöCï:®=zÔã {÷18÷ þá)a&q}zÚÄ?*'}©‡~x½xÎþG:àI¸ÇuÖŸB!$HÓùÍáä·Kþ'®ÍÃEò‚dù÷Ê«å[{¤¾Mó„°yŽl•í_*' /•´éTS¿WÝÄY~W?Šo-‚uÏž=ÒÓÓ£­Ess³vÝ÷1¨ðçôo§€<<Mü¡žóæÆ÷‹ïòÿ`Þļ·@€%Fÿ1@!„„À[C»å™žçå}çÚòøOÉ>A.,8[[bUUyÜÉñX©ƒ]\º‰ŸÞ{m'¡Î Eø× #ýàô?<<¬ X˜ýÁôÏ÷1púGÏ?zÿãAœGcŸšx‘èÍ›7?ŒBŒ•þ; D|/÷ùËþÇU4œB!$þrôvywîi’•˜iËãÿ·Š‘íý¯ÉàÔO ‘æL•G–ÈÉ£Ë%×a^'ÿ´´4­ì‚+%%%î'ƒæ¢_õ‹š;¯¹ýcÌŸûìz|ŒôCÐIG¯ç˜±Ÿ?P‚Éþ«`KË]wÝõŠÌuþµì_ £Â>n³ÿ B!AÒ;Ù'·[#_«ü’-??9O®¬øŒ\ø¯<,@îT¶¬Z¡•ú'O›óë!D?2ýþz¦Ÿâ›A‹p_WW—æô¬?²ÖMMMó²×ÉÉÉZ¿Þb‚}ÕÔÔHQQQTÅy4ÎÿP÷744¤m²}ûöGÕńڦ$<ýÿžÄ¿xŽˆÅ²ÿ B!!ðPçr±jX–¹Ø–ÇÿᢋeC÷fy{¸‘'CœR4™/§Ÿ(ËFë$AL÷þÝ×ÝûQêo'¡nu̶n®NÿÈø#ó Wà1ñ¯WÀé¿¡¡aŽÓ´Äy<`ž(*àÒ·zõêgÅÿè?§^æïMä"ìã:ûÏ!„Ê—!õïw-7ÉŸ—ý–†€8æk«®–¯ìù¶2Gœâ G`ŒßéC'JÝx¥éÎ]dX!øˆ~fÉÍ%¾ãqÝðž!üèõGÏ?ª\ÉÊÊÒľnî§;ý£2Å âÜl±±1éíí ø5UûÅSªj`XRt‰-¿6½J>^üa¹·}=OÓ+Ñÿ™C'Kùd±©Þ2©ÈôcC65X5Šo-y,D>œþ»»»µÛ¸T³çç [´¸šû!0…`‚Ufç±è£AM^˜¸ýöÛŸùÙÿ@+Äø÷W`Ùì?„BHX}ôorNÞ™’—”kËãÿ—²’-½/HëDO‚ ÿòÑzyÏЩÚH?³1…q}W¸´‹P·:ñ²n0ùƒÓ¿Þ£ÞÑÑ!‡ž÷8÷1îÁ€xçîûŒäþÐ:ÑÙÙðóT%Ƶ!ãð"ìC­ð׉`„BˆÕ€þGï’ÿ¨¾Æ–ÇŸš*ߨú²|oßÏx2˜Lø×Ž-’³‡N“…“æxOJt Ã…l¿7Â,¹¹Ä·ÕÖÍÕéÇvôèQnõÕÕÕ²páÂ9Á€E‹Ed-âÍàÏXË@³ÿxKëׯDfÌÿûˆàbß[Ùÿ´UÎ!„0ðT÷³riáùrrÖ ¶<þ3rVɹyï–-}/òd0ÕãårÎ໤d²ÈïýÒèé7:¶â›A‹H=}é»wïF¹¹ö˜ææfmV½+îcþð:¨p Dc]â1 €u &û¯Z^ݼyóA™ÉþO‡qñߨ¸Ÿòg B!–ù«þý¾eµüuÙ¯%iA¢-×àk•WÊ+ƒoÊðÔOˆs?dü—Æü½è}ýý®#Ó¬*8-ÿ7Îë†Ì4 þðþÐÿë0ýsÅ}ÌÎc”üëÁ€Xˆóx @ü;Ž€÷÷Ì3Ï û™‹N—-OÂÝŸù_\Ã!„&šG˃Ë'‹?bËã/LΗ/”].wï½}¢SîïxDëÚ¨eÿIdX2V+õ¿G2œ‘aŒFíy¦ø¦ø6㺠jârrR» #:dþuçòòrmÓÅ0Fü¹;ýGKœ»ï3Þ'  å"˜ìÿ¶mÛôìÿ”„¯ä_Ä÷8@o¢ÞŸùŸå`€B‰k;–‹ Αºôê¸x¿FÉÚö‡eSïó☞â!R¦“å}ýï•å£õQþè{ŽGÁiu¸nÆcý öÑëPþž”ÿ» ]8ûÃ× ÛïÍé?bÙ û ç>±Öî‹FPÕ]·Þzëó23ú/Ð1FÄ¿'áïmb€ø ø\J!„âýË’Ñ¿k¹I~»äd˜÷‹»î胿iû$DbB‰£P>Ô{ä;r"dPgþèy¦àŒ®øæº…-0o¾¹¹yVÈ¢ýàÁƒs„-Ä~CCÃì9Ÿ””Ó?þAöß5àb”7ß|óÉÑ™ž O½ÿ¡D¼Wx „#À!„BæóÖÐne ÷¼\¬FšêKü;Žþw·= o7òƒŠ§¯ó”ËâtbÄö„^glf¡ß\7£ïëÀšéœ«Usäç<ÿpú×+]t§Ýù?žºYxŒ>q!T»ÆÈêÕ«Ÿ”ãåÿÑvù÷'ì-Ÿýg€B‰27½]Þ“{šd%fÆü½ ´ÿÙÞ­šð?4v„N€àGÉÿÊÑÅÝÊœKKKµÌ§Ù§Õẅ¾èëß³gÏœqsþî"bñâųcýt§ÿH™ýÙ5 € Ý{!TÛÆ&UÁÑ'Á÷þ‹ø/ý¯!bÓì?„BH”éì“[ŽÝ#_¯¼2fïaÔ9&Ot=£ùÀ D‡L5Öï²Þ‹¤traÄö,gYY™dggSp « ¬´€£?ÆüéNÿØZzzzæ<Î}ÌF[VUUEõó²’ÁŸ7ເ6Œ ž7µfÍšGåøè?#‚ß)¾3ûþÜÿö¶Èþ3@!„Ä€õjœÞ%çɲÌÅQÝoŸå‡}?Ðù˜ :†øAD‘²‰bùh匌ó>¾øçååi½þÑmFñÍu‹púGæãæzÎaþ744÷ï—û˜?T¿`‹¥XŽgƒ?_ÀsAÿ<¡¥¥å¥W_}õ˜ÌÏþ‡Ë0˜–Ûeÿ „Bbñ_ýƒ!àŸ–^' "/ÖZ':äŽGåQ5Êoœ£ü¢NÃXµ|¨ï|IŠP¿jjª6æ,XwŠoẙp-áojjšuúGÉ9në•:îcþõÏÏÏ7@·B@¯×ÞÞÔsŸxâ‰õb,ûh @ÄÿØ?ñòø@¿% B!1 qd¿<Öý´|¤èÒˆícÿèA¹¯ýyFò›â(¿˜°rd±\Ü–$Hd=Èú#Óéžõ§à¤Pçµ@‰¹«³?Úçô㽡¿¥þš¨Q~uuu;ý3 `eðYŠøö£>ºGæŽþ‹D¶_<ܨh·üø!„±úèÝrNÞ»%/)7¬¯ËQ~±£ß;xª¼{蔈¼>úœ‘õ4ÚëOñÍ E¼¬úû]þѰoß¾9#çpþÃì/++K»––¦‰Ýü/ÜbÙªýüì ¦÷<ÿüóÈñì¿3ÌA_O¢>PÏ!„§†äÆ£wÊT5ô/rïŒòû[Û:Ù5ÜÄűø?àLY¥FýE‚ÌÌL©¨¨ðëðOñm.¡ÎuóýX|dùûúúfïëííÕz€Èǘ?ˆ~€ X$þãAœGcŸø,ÆÇo!8zûí·¿$ž³ÿ¡¼‰x_†þÿ+ îg B!ÄOuoV†€È)Ù'õ|Ç´CòÛ¦ ÿÃcG¹ &ÿ¼[N^‘×G¹³»¹E$…z¼¯LåvïÞ-ÃÃó÷¡×\ÇÍyÊû!þõà~*++ç‰W–®UðòË/?ª‚;ˆøýlß¿·q€âå>Ûfý „BÌòÅ]ýû½2¼qùÿIÒã&q#S£òd÷&YÓþtMöp!Í"þû•ø ¿øGv3V%ÿß ZDrÝ úáôïš]†ðw7›ƒßÊüõL?a˜za±lõ€²ÿîæ‹FP~ƒ·ÝvÛ³b¼÷ßÈcÄ€ð€@îöq B!Ä?ÇZ”Kÿcò©’ú}lŸ£_ò{J{¦Fù=­FùMpÁLÆÙƒ§EDüëýþ0=£ˆdÐÂJëQ ±¯ W‡Ã!û÷ï×Lÿ\qó‡Òÿšší÷"\b™¾éïï—‘‘‘€Ÿ§‚:*ûÿ˜Ìdÿ§d~–?Ô²£.ÿÌþ3@!„˜”ôÿùÈmò£Úo͹ßh³Üßþ¨lìÝ"Îi'Ê„œ9t²œ1tRØ_β²2KNŠo®›ëÏQâôèqÏx ÀuÄJý!öõ1¨„Ù.)Σ·Ï`{ÿU0ç¹t«« ¾ìß]ˆ{Êþ 0ûÏ!„b>žëý»¼¤ ÏÌ]5;Êï…þ—¹0&Ydÿà z›uáCÁIñm•uƒ›?„>Jÿuà€1“““ÇŠÊô744ÌŽùCÆÁ€hTÂ0 påà?ǘ1—_·nëè¿HŒüñ_Àì?„Bˆ¹ù2ÌnÍ”½#Í\ “S3^¡™þ…| ‡¹Y ýÍV‘ ZXoÝ ðÝþ1òOe‰çŒùC†Nÿz¦???_óÀЋýüÑÛg°ÙUÝñʶmÛÊñ츂"ÆÚ" `€B!á§m¢Cm\³SèÈ“÷] ¾ÙãøÂ~ÿH8ýS|3hËuC¹»ÓGG‡>|xÎópî#ó¯gúQ ãÍé?VbÙ.dÿ‡†‚3š}úé§×Ëñì¿«øD ÀŸ¨ŸRð[60À!„BHd:Óå{.‘TgJØ^ýÎÿ˜›QpÚg-âyÝ`"רØ8Ç鿵µUŽ;6çq………Z™¿îô¬?²ÿ¡ˆeöóO°Îÿêón¾ÿþûß”™ì¿7ÁL @ÄXÿ ~ÚŽ# „B1*Ô§äz/’œ©¬°ŠÿÊÊJIOO·¼ˆdÐÂ^ëæîôK”ü»z¸üÃðLjì8œþ­,Î#½O´i¸Oc0ÊÖ­[õì¿‘ÑF«DŒWbþgK „B1ÈEƒï–²‰â°½¾¨‡"þ)¾)¾Íºnpú?räÈìmTìÝ»wNY9^ bÙ’’§Û'*4‚AµztÝ|óÍÏËÌè¿H•û{Êô-ó·}ù?„B!Y1Z/' / Ûë!ó2gwñOÁiŸµ°âºaßpõïîîž½½ÿÿ®cþéG¿¿îy‘‘‘!ÕÕÕÚ]À²Ÿ?úû„_C°Ùÿ×^{íQ5ÒqLæöþ»_†*þE¼—üsô„B!¡SƒíýWûw®]»VýÈØ¿@¿ûÞÊþ™ýg€B!Ä7 Ô¿‹ûÏ’Ôé”°¼ÌÎŒô9ÛIpZ+¯„~ss³–ý×ñ4æ¥þ(ù×Ëüñ{€±¨ Á_ä÷itÃÃÃA;ÿ:tè…_|±Ef²ÿÓaÜDü·*Ú§ù—‰ÛþŸÄ% „B¼sÒÈR©_–×JNN–ŠŠŠ ¾ü3Kn.ñÍu›qú‡Ðw-ǘ?xàÒõ¼_¼xñ¬Ù%*`ð{€ ÅytöitÁfÿ±‹‡~øA9žýwÿ.ñ/~ æ„B!„¹äLeɹ§‡åµ vÊË˵Œ'E$Åw¼¯>ÆüŽŽÎÞ‡ì1®cþéǘ?ŒûEEEZL ï™èì®U olذa¯ÌïýWÿ¿'ï)`¤ß?ó@!„B¬JÿS¦“ÃòZ=‘îu6›à´:v]7ˆDˆW¡1h@K€NNNŽÔ××kA/}äe Þ D7 Bö_6nÜøÌdÿÃ1úÏß@O¢ŸÙ!„B‚géh­ÔŒW„åµòóó51MÉ,9×-k¡¿oß¾9BßÓ˜¿ÂÂB­ÇÏG ªª*¬Nÿ „wŸèûGG0ôôôì¿÷Þ{_WW' Š#Â_<¹?ØÇ1@!„b%õ?ð̰¼J 1ò"’â;Þ×­½½Fo~Çü¡ÕÙ~¼'8ýCüë-çáßg8ö×ÖÖôs·lÙ²N]ÀôÁ5ûJÙ¿'ñ/ž#â?ûϪ!„BærÖÀ*ÉšÊùuÐ÷¯ !+ N«Ãu›/4QÞßÙÙ9{¿§1Xdý‘ý~Aü'%%ÙVœGcŸ¡î¯¿¿_FFF‚Ú·j9vë­·¾(ž{ÿƒû'D~ žÙ!„B¼S4™/§Ž¬Ëk•––j蜱ß\·à‹‘~(ù‡HÔ™œœÔÌþ\E#Êüaö—­ÝFË‹7§;‰óx ²#XÔØ¿‡Ô92f `${/bÜøÏ— ³ÿ B!„ãü3d„þHCßßñ¸nÚH?W¡?66¦Ý‡Ÿé ÌÉ’%³&—¨ÄéŸØPÁá:É!ԹгzõêgßÿF³ýVˆø®ð÷3CKÄ!„Bˆ i«–ê‰ÐÿPòɾŠo®[¤×¢ß]èÃ(Õ¨ бßâÅ‹gËüÃáôoç€@4÷‡ËPzÿ_}õÕGT ÀˆxÏþGj@0¢ŸÙ!„BŽ“0 ç¾+ä×Áx”þ£$š‚3òâ›ëþµ€Óÿþýûç8ýwwwËÁƒçˆÕ¼¼<©««ÓÊü±-Z´(¢U/,ß/øœÇÇǃz®jºù曟cÎÿDŒgÿ½ | ~!„B¼sòÈ2Éwä†ü:¹¹¹’‘‘·ë@ñmï úÁáìïš%Æ}GŽ™ó8”øWVVj×ásëhПÇò}sï¯ë>½!Þ~ûí§Ôy1 dzÿáÎö{ø¾\ÿ}n?c€˜ÿÿ)ü]à2B!‘<$gú—)U]TTDÁÉ EÜ­®Cø»Âá>dý‘ýwÎþÅÅÅÚuˆ~W§;‰óxtuuÍiïÕ2~Ë-·<*ž³ÿáÿç¯Ü?Ñ„B!„ãœ:¼B2é!¿D‘»ë9'…ºÙ×=ý釒p‡Ã¡õû«ïÙûpn£ä¥ÿF—ååå>þ0_@Ÿw(Ù5b“:_º$4ç£Uâð0r°c€B!Ä*¤N§ÈéC'†ü:è}ÎÊÊ¢àdÐ"®Ö“Ó?úÂ1æŽÿ:(óǘ?˜þ8ý#àìñÒà/vLj쿫‘c (_ˆ©5kÖ<"3Ùÿ) Ìõß)Ƴÿžn‹xo ù¶‚¥ÿ„BH¬:AÒ¦SCz d@}¹þSp2haÆuÃø7w§dü‘ùG€Êü1æãþðºèÿ—Ó¿f8FÿÎÎΠ_Oµ‰l{ùå—aá)ûl5€ø¸. {fÿ <á !„Ï ÷ÕÈŠ_ÙP÷hŠo-̼nýýýšÓ¿k&-ÍÍÍsÜÿQæ___¯Mµ@ «¢¢"¢Nÿ Dˆ×Ï7з|ÿý÷? .1š’ð¸þ{ÿbà9"Ìþ3@!„'Ž,‘4ghÙdEõžh+ NŠoë®JÀ]Gúá²µµUŽ;6çq0´¬®®ÖŽ-óçêôoeqnÅ€€Ý7ÏÐ1ZZZ^Ú¼yó1ÞûŠ?€Ï¥ Qð30À!„Bì†ÊgÊiÃ+C~£}Ðê\‹X¯îÃ8¿¶¶¶9÷yrú‡¹_YY™ö©©©Ú˜?ì*έÀ„‡P²ÿ=ôÐ:9Þûïîöªë¿»0göŸŽ¿#\B!d†¥£u’3ši_FF†¶Q|3haöuÃ~àôßÓÓ3{ÊÿÑï?888GdÖÔÔhm-Æ–(û7âôo瀀ÙÆŽ}}}AïûèÑ£¯>õÔSMâyô_ Yñ!þýU0ûÏa@€B œÓ†Oéùøòéxœßö[7úÁÕßu¤Ÿ'§ôùÃé_ïñGk ªâ]œGcŸf?F´x¸?>{ì±ûåxï(f"Æ«üµ0ûÏ!„BˆjÇIñdaH¯‘„Òh NŠo3¯~cc£_§xYÀé=þx}LµÐ«ì&–­vŒø¼]«<EµŒ¼ñðÃï’ùÙ_åÿFƒ"ƲÿÞZ(ø ÁþÍàB± g ŸÒóñÅ:ÜcÐÌ*"´ˆßuÐÊþ]…> :4G,fffÊâÅ‹µIxÏ(ùGé4ÛˆÜ>]=‚aÆ ®Îÿ¡–ÿ‡+ûŒ¦¡Þa€¢žB±¥“ eÑxiH¯‘››ëÕâ›âÛ ëæ.ô½9ý£Ì¿®®NëñG@wú·“8·r@ãGGGƒ~~GGÇ®µk×¾!3Ùÿé0o"Ƴÿâáñ„âö˱€¿„BÈ\N^ÒóñE=??Ÿ‚Ó¦â;Ö "ßUè{sú/))ÑÜýÚY þý¶hð?Ljׄó(¨ìÿ}êb\ægÿCqÿŸö!æý¹þû øÓF„Ó‹÷H½¶ü…"„B,EêtŠ,« é5ýG¦4ÞE$ƒÖ[7OB³ß÷ïß?ÇTUUi#,Zuú·S@ ^\½EGkÖ¬yM]uûN O+€/áÎÑ 0 `ðñì…!„BËÔ迤éà¿òxÊþS|S|›aÝ0ÒÏÝé€MMMsD D~}}½È¸ ‡Ó?æ:Fœ!íSý[+ž{ÿÃÕëïIà{ 0ûÏ!„BHàœ4²4¤ççääD5û¯BÝê˜mÝ ôáêï:Ò€ÈüCê ¼fÚmŒ±Œä(Kb·Ox@¸š?ŠÊþï½ûî»_‘ùÎÿ¡šþ‰Ûâ! >ù _'üüñ—†Bˆ¥)šÌiôŸ¯ì¿™D$³äöZ7O#ýù=|øð‘˜žž®ùCU¥¥¥Ú(K+ôº²O;#Ú>Üýå‰'ž¸GæfÿÃ]þïMøöÌþ3@/þÛø @!Ķœ<²,¤çc,šƒ4Šo-¢µèñFÏ¿Ó霽¯¥¥ežñ*WPöŸ˜˜¨U°”——k³ ×hìÓLjÏßõœ@Ú­zÿ_ÏÙÿPûûŒýcöŸ x/'ù‚^‡ÙB!öù’3(ËÆêBz ŒK³»à´ü—±8Z75žMŽ92+.!ø8 }}}s·páBÍðïUwú7ÚÆÂ€@üí#ÿ0ú/ž|òIoÎÿ¡D˜ýg€D5hàí¿„B,Ï’ÑZIs¦ý|ôL»ÎF…ˆd–œë¦Ï¡C‡æ”xÃäf®b¥þú9ŒÌ?ª(–­{Œmmm!½XÚuï½÷"ûïc£þ‚ ˆ0ûÏE{ØŸïk¤†«!„؄ǖ„ô|Ý1â›A‹X® ý`ì7888{Ÿ'ôø×ÕÕÍV­àüÕËÖ=FdþGFFBÚ·êý¿W¼gÿýœb¬ôŸÙH¾F² €BˆmÈrfÈ¢‰àÅÊ¥1'ÝÊ‚Óò_–,°nãããóœþáÐÜÜa€>öoxöðç¬éäRB±™ÎôÊÿažª`–œA‹@€ÉJü‘í×AÀáÇý:ýDu=ˆý>1‘¡ KÏoÚ´i¿„–ýwŠqã?_ÙÿPG—3`À€åF\ÿýôë.1!„+±d4<îÿßêÑX ˆ~8ýë%þxLKK˼ÑnîNÿÈúÿÿöÎôK®ê<÷»Z#HÍó<ÙÁ&ä.Ç^we%Yɧ¬ø[¾äËýî§L˱×JlÇ8v°c ÌÅÈ„0ó`l Â!BcKjI­¡Õ-©5vwÝýžÖi>}†½÷Ù§êTÕï·V­šëTUWuçyß÷ÙaÒ'‰åN7äòÞÞÞB­s†¶lÙò_ú¤|è’ªÿE–ü£úÒõá—£–py^@x^¾ð—_ùÜOÿ·>–ĘI×]‘C-å|-átü  ŽÇýoãÏPIj x¼ZÆù¼Óá±ü&Mû??üâÿU‹Õj—'&ÖiÓ¦u¤PÇ´hüûvöìÙ Ù?lñ—ciùŽѤÈKúÇh_CàôéÓ…—ýûä“O^zûí·»Uzõ?ÉQöKþùªþçi'Àè(s /ü/Í W¯_‰ ý¤C-Ãp1²v*1ÚÛ0¨žÏüÑëä7iÒÂ… oЇ®O<^Qm7Á‰iQdù6©ô‡ÂNBÝ$ìïÒ¥Kãn7þ|µjÕªà=ƒJÂþä¸Å2íûÅð±ìŸ6™.?üðÃaõ?oé?ÛÊYÕD>@Gû"÷O[ éË9ùò‡âÞG€²0|~ €Ö3Lªþ&@׵ߴ®¿ú«¿ú”®:G¡çˆoL‹¢·•eÛŽ;6®[–÷ñ û–/_®/^œ–¤©üûHúo–Xfž¿ò™)¸ìŸÚ¹sç³}ôQ¯òSý71”¢ú€Ð/å¾ñ€º2[ -Ð#JWìò®k§k±ÓñC=átÝ£Pã@ˈÿzÎeñ߈´Ñ¶DMuí÷¨ëÖ[o½ÅõIJKµkeµÊ‚ñ]÷MÄ[<é_*ºÝÝÝãD£´ù¯^½z,àO–¥# Ý:†€9.\FFŠ Ã&Ïßwß}?U£ÀÃ9¢¿H€RÙKýQýÇO†AÒÎRÝÓa$"ö•øÏêðe˜P  ë²<ñ_74ºt«ô§\Ÿ¤ˆ,„:¦EYHû¶„ý‰ ßé8zôèøóÉ“ÕúõëÇ>sæÌ ÒþãB’yþÎÙ¦à?áÝwßÝÚÓÓsFå·þ—Uý7öTÿ1@%·ø§íH%uýc;U1 Oü'JÐŽbÞ‡ö;ÿ=I˾©}á _X2cÆŒ¹®/,\Z­ÓÅ7¦…ÿÛJÒ¿„û…ámÒ çûûûÇÝNºPDüK¥<Ö‚ 2W¥hw±Œ!0Š|NâÙ¶hãéÔ=÷ܳU]Oþ·YîÏWõ?m€ê?‚_e·î×r./bÄEZë¿R€ùÿnÓyÿ¬jªø—ߨ?û³?û¬ë“—¥ÕÊjÿG|w¶i!k¶‹Øg·uv0ïv„Hþ„ˆÿ0éÉ’%FIÿU®TëËÙ¦|nNž®M„KÊ®ú_w4”PDðc `´½ÐOkLýѪ¬u8ÓÄ’ðOšùÏ3ÒvÞ’vkžv2 ºæ@ÚÿþøïC–ÙýMœpÙ_ÿõ_oÔ¢išË“±%3×UœˆïÖ~ßä9Kª¿þð¼¸9rd‚P”ªð'¡2ó/íÿzžÕݦ<Ž˜HñdzE?Æï·lÙò?j4ùßt‰?s IoPýÇF‰5 `b$%þ'íœeµý»´þ#øZ[èçÝÆ¦í¿– øÓ~»>ûÙÏ~ÚõÅHû¸“ŽPïÓ¢Œ÷M’þe™¿óçÏÝOÎË(@16lØ0–ô?{öì`É¿èç°™ÂqÞümúþ“Íÿä'?yL]oýQnóþ¦ãÊÀ("ø10ø=ÊÙéªgg þ¼ªýÚu¦âß×òì…´¦9àÒöo:rV¬XQùöªäíý¾]¾|9û“ãÐ eÿ$0Št›è¼Š±®“ùóç«›o¾¹RÂqÞ\£EfþO:Ux[{÷î}õ¥—^Ú«Ò«ÿ¶F€RTÿ1À» Ïªú§¥g}qj†F@VÕ?)ô¯®Ê ÿCè´¶àÏû¿ïCüõIëдIºzµÓ“×;àñ¤uÄ7¦…-Rñ—ùþ0¬M–ýÓâkÌ ‘Š¿$ýOž<9hõ_´h‘“…!ÐÛLÛÞ‰' ÿéû_~衇~¢Oʇ0¯úï# PE?Ɔ€Á"*þóŒ•bØT`ÒÄ¿IÕÑкB?ï¶yâßÔˆG‡¿Uµ¿üË¿\¥M€é./JB×5sÝŠB½íw´<¼o2ë/Iÿ¡˜ÓK­•ÿ¸€“JÿªU«Æ%ýûZzC } Y)b`` ðcíØ±ã—~øáqeWý·¹.®%¨þc€ƒ°wyœ¬²zÎé¸àW âß6õ¿¬öŒ€Ö3 òÂÿLÅô7jÂoÐm·Ýö)×',@UÅ7ÝÕß$¤M!²d[Ô ‰&ýKëYIÿ­¿Mù Egœ¹÷Þ{ªFgÿ³‚ÿ²ZÿGTvû?Õ (ÙHZÚ¯føÅ¨Å®Ïüqñß•¶Ã¥Ê›ýGä´®èW9¿.â$Å~ u’ú×'oÿG|cZ˜¼>9¡Mú?|øpкˆkÖ¬ þ œ\¸páØc4C¸"Ϋû¾öõõùþS/¿üò½ò„¬8tíÿ§mê^Û¿RTÿ1 á†@üËbr›´Ëâ†@™âßt‰(h-ÁŸv½©øW†¿5ñεšž£v2d‡ÝG@+ õ¶ßy*ñ}“Ö~™÷“þå¼ÌûÇÃþdÎݺujÖ¬YÁy ú‹&ý7K¸R­¯æö®^½:aµôcì}à^Qã[ÿmÂþLgþó:ò„=Õ „½Å}ÒBmˆî<% åAüWeÙ?ö†šó¿6í÷ÀTü§u¥…«Ø¨?üÃ?œ¯Eü—',â?k'*yµÄwÞ·+W®â?¬ÒJÈßž={&Tm¥Í_–ù ?c:¤RÝtÓMm)\Ù¦ŸíIëÿÈÈHáÍ>õÔShSJ>IÕÛÔÓêžp§ú–æ€I@ÍáK4¢&†*å âß¶z­#úÓ~LçÿÓ~o’Bjkþç~‹ë“¯zõñ]­÷MÂÙDüËò~‚tHå?<Oú—–ÿ"KMb´¿! Ÿ¥x‰ úóøÚ3Ï<ó¡º^ý÷Õú¯Õ hº9Õ`Û'ømÿHÿ豟u›"â?ë÷&ìùÿõ®/(mþ¿•…zÛï5é}ëïïfüà ­¬ÑÞÝÝ=AÔÍ™3'˜ùá/ÀâÅ‹ÕÔ©SK’ˆóÖ7ä3ÏŽpAQõ²«Ñà¿á ñï£õ_)ªÿPHÌ›\gÚPOØñª{xŽ.€/ÑÏ^@k.ËþeµÿÇ«ÿ¡ PÓ3Õ«\Ÿ¸IB½ü÷¢êý£GÏSÇŽ ÎÇ‘”I÷—×"¢_Ä¿˜åÖßf™Û“Ö™ÿ/ÊöíÛYöoØ@ü»Œ(Eõšj˜fÔ ¿Dõ”°ºÊnùÏÚÑËñˆ{€ÖûyÂßEüGoÿѱµš®¸.wÿ­$ÖiíoÎû&UIf¤R»ÿþ  .Fu'J0ç/HÒÿ‚ Æ%ý7J¸b´Öö$;âìÙ³…G§œ¸ûQ׫ÿy~ñ¯TþòiÂê?dˆn“ëâ?ÍHýµœ/_-e[I&€RåWÿ1ZÓðYýO:wXÕç?ÿùES¦L™åj´’Poû¡Š½o’ì/-þá\¶Th%ìOrÆíDë ¿ÌûËÜ¿ Iÿ2öü00¢¡—ê›ðX.<ûì³?Ò9ƒêzð_\Ü­ü×SÄ=Õ h²‰fd™õ á?_WÌýt²¸7½­Éo…Ië¿JÿAûÿç>÷¹µ®/Îf.›*yg"ö%ìïâÅ‹ÁùÁÁÁ ì/Þ¦Oú—%þL“þ10¤³DV‘(ŠGyï‘GyKVÿmBÿlÓÿ©þc@ Þäº$‘ŸgÔžG’ðÏë8ÈÛÄh_SÀGûÒÜ¿JÿÁoÐÊ•+ oˆoL‹8Rá?xðà˜Ø?sæLÐöxRññ?iÒ¤±¤¡’ü•¿Í*¼Fù|…£%EÐc)W~øáGôIYö/ü—×àög:@õJ0LGLFòŒ…¤î‚¤ãºƒ€Ð>F€I@Z¶LVè_=ÁC—ž³^ãôäõθm8â»ZB½ Æ’þÃöì#GŽL¸Tú%é?ü‰ø/ÃP¢Zß¾¯ñøñã^Zÿß{⦅¿ýöÛÝêú²e$þ›¤þ+•<*@õ,D¾Ë}MMŸßéKÚŽËÒQк@ü7"-P6J–øïJØ­Íž=Ûika@Ur áôéÓã’þ¥ @.‹#ÉþË–-Kúñ/&@#Þ öØžMáxIôÌÿ‰ï~÷»?Õ'/_û?9¢ü&þ tüaiÿ7 té(Hÿy_æ_x€¶3”Jî ËjÿW¦âÕªU3uËõ—'ï{]öª uL‹üÛ†ËúÉR‚^K=˜÷×âj‚(Œ&ýK»¿$ýKû§W âÈç+ü¬eëÖ­?Ô+HJåPñŸd¤Uò©þc@D¾ X¤ ÍÈÿ5ƒ/y-)ü³ÌÞ¤±´pÙ$á¯2ÄÿØNæŸþ韮UŽÝcÑvmªäkZHÒ¿´ü‡Ë°IUVÄ<˜Mæü%éÖ¬Ñ'ä84:E¸bøÙÞÉ“'ƒ“¢:tè­Ç|»ºÞúï*þ‹Œ˜vPýÇ€›qá^d ïtž¨¯ñEhYÑŸõ¿=ÉN[&þ[0¢’«ÿ*cGS:Vº¾ ªuTE|w’i!•ØhÒ¿´eKØŸ˜Q¢Iÿ‚,ñ'Ký’ˆór¶Yå×(KJÆ;K\П݋÷ßÿ£j´õØ“ø·øõ ñž×À¾?”`dUçm»Š ÿ²?yýÉú_œô;4:–õ¿;^ýÏ›7­éöëeN? zg½Q+ ¾«iZ\ºt)˜ñ¿råJp^ª²º¢:AØI¥_*ÿÒ Û–ÿo¼q^ámVõ5бtâÄ /Û{çwžúàƒŽªÑêÿpIâ_eüV*;ýßec€-e×t™ÉH@|G®^à9&št(þI´i¦nšÕoÿOÚÙLÛñºôzëNÀ”)SêlZH¶»»{,é_F’„Ùüùó•î2 ^Ÿ‹-*µsC ½_£|Æ|´þëq•ž»îºk›>yÅAü䈥ò—÷3íPŠê?TÆP*IÀ"ϱž#ô]·GÕ ù¿KIÿ“ëA-ç7-^ùîdÖ2žCM¯Ã¾ÔåET¹ýŸÖþrß·3gÎŒ-ë'Ù}ûöÍÿGYºtipÄ0Š&ýwšpÅ(Ž|Æ|´þËÓâ‰'Ðc+ƒÊlÙ¿¢Éÿy¢ß¦úŸ PP€§í˜åUk²N»î(Ö<¾Vh,yfn’él»¬m^»é„ùÝÂ?E§°/vyAIUêí,¾›ý¾I¶··78-!{öì F¢H¢¿$ýÏ;78/sÿ"þÓV@œcä!F“¯Ôÿ>úèù_üâ¨ñÁeˆ¥ìºØoÇ€’¾© ¶c¦ _ÏÑ·ýÊ2\§TÂïNÔ@ÈÚá¬é–j±æ´ÿ’f ÔÛó½×"Uÿþþþà¼Tb%é_B㟠û güu‡‰QÒ?â¼qÛlÅ×(ÆSÉ H3LMÛŠ´ÞïQžÈÏúýªçlcì¶ðༀ€ªˆoL‹ìÛŠÈ—y-ž‚óR‰•óq‘§»IñŽ‡Ìž=Û9éC€×"fÓàà —ç±uëÖj3¡ßƒøOê°É úÛé²éÈþyf€­øP)¿5ñÐÀ¼ T×âÅ‹W”a ¾ÛÇ´6YæïêÕ«Á6;¦Ž=:áv:LR­[·n,é_ªþ3fÌ@œcÚ¦Týeu èÏñ¯{ì±·UrðŸMò¿I RÙ•¥¨þc@K˜¦F€‰u¹ÉŽ´®hw]A¦–³™—ý½ªéíå./@DžÌy#ÔÛ©¼Ê²~"Â$y}ÿþýc#QdY¿•+WŽ%ýËùF„Db´ÿkñï£õ_Yguêÿ#úä¥kâ?-øo$Ãð1@õZÀPF@Öå6B¾Æ?€¶þ¦ÿû“*ú&[O8Ÿ–:Ý¥ç´}‹;Zû«÷¾IÒOOOp^ªÿöŽDY±bE°´Ÿ&ý‹ uˆór¶ÙίÑcê¿zá…~¤ ,IR׫ÿ6Uÿ¢3ÿYéÿTÿ1 b&@ÞmëbÝTÈ#øÚOðgýOÏ ‘­©äðÙ´û&IÛ:´°Ài‡grþ.â»uM \“ƒ ³×ö'&@éY»vm0ç/HÒÿüùóS;C¨ÖómÏÛéÓ§½<–YyÓ¦M¯©Ñà¿°úošúïcÙ¿¼¥õPa@¶;}>¾ð„Tó7&ïwZNLÖé¬ß%ÃzLÃéJþ<—ÖŒÀª õv55$é`` 8/]Òö|IIÿá’ˆs ¢Û”Ç“Ö;ñ`$\¼÷Þ{P[ÿËHýW&@üÿq^Õ (q­æñöyË=e}ik^T—¼pٸொ|“Ùÿøó¨iw“®äßà´Ã3Ùl—‡Öþj™Y·•9ë0é_n×ÛÛ˜qDô¯_¿~l DRþ‹$ýc`Ä‘œ‰‹/zy.o¼ñÆ–;vÈ,ËUåüg“úŸUåO›ÿwÙgß<5‡/^Íò Zã ÐÖÂÞö÷ ÉÈký·5£'<çÛn»m‰óÏäöÝåéDÓâÊ•+êàÁƒÁ±¶)ŸAé<ñ´þßyçϪÑÔ“6ÿ$ŸvY#–ýC`@ƒL›¹¤2Û@å°M¨Þo‡­Q&ü³N'm;É,Ⱥ\ÞµlٲŮ/¸ ~Þ7©øKå_:†††‚yÿ¤à5 ú“À?ABþDüO›6­aï-íÿ¾†'ñë]Эÿƒwß}÷ýjtîH%Wð‹,÷—×þŸ÷[AðTpg®h+~­À}]aï 5Œ‚´Yþ´ö~ßti·Ðé‡Fï¬Û,ˆP/ÿ½p}ßdÖ_’þeÖZZ®%é_*°ñ¿·,ñ'Kû 2ÿ/aQˆj=¯ÑÇ6O:5áóçŠNýd×®]ÇÔõÖÿ¬p¿"ÁJ±ì´ÝŽZ­àý)ÎùçP-lW‰Šþ¬$ÿ¢¿)µY³f9aû7⻵M iñ?~üxðüŰ¿øzëRé_·nºé¦›‚ó2÷/F@ž„!Àk´E (Yöχzû¾ûî{E¶þ«ìп¢Ái"Ÿeÿ0 ƒ€¼/,U{€öÿ IûŸoÛêŸw¿¼Öÿð¸kÆŒN@Ùíÿt ”ÿ¾IÕ?œ³–åþ´`špiï—¤YÞOП— ÀåýÆà5f!(’úïƒË—/|ç;ßyPoýw©ú(·à¿$#€eÿ0 Ã_zövÚç·$IÀ›Šú¬ß‡¬ûtÝpà NKJU¡ÞÓÂ÷û&þÇ«ÁÁÁà±å´qDìKҸܣ¤ü‡]W ßÛñ/ù>žÎÖ­[ÒÝ,§ÔhëÚÜ¿Ë쿯à?–ýÃŒ€†™ÐLa1ëŸöüjºÂ;ÛåΡ(D|·2[-•~]! Ä–´ü'µ\K•íÚµÁk—ÃܹsKKúïdCÓcù Š!å`ùú£>ú[u½õ?+½?ÏhFðûþÐ"F@³Í¨îïCÖo„‰èw1j ÷©Å®«éyn§ÅÛmßÕ08d¾:Lú@Âþ.]º4ávK—.UK–, zŒ&ý#\y¾·)¦T__Ÿ—íèÕ,Në[ßzDŸ¼¤Ê ý+3ø‘˜ÐF¿5‹ÛÛü–ØÞ¶¦çºõ(ÿä™./&è¡ÞÝRa “þey?Yæ/Þn-ÏeõêÕàvhuÎC<éáŠ!às›á’ò¹ôñ°O=õÔý:ÔR‚-†Ôõà?Ûöÿøì?Á€Öf¦d {×YjñãÏ|æ3sô±S)ßµ Åw³M ©®†Iÿ2g-#qÑ'†ŽÌûëU!‚ó’ô/âßôïŒ!ÀktA–ü»zõª—Çzÿý÷ŸyòÉ'§Fƒÿ† …ÿˆè·]P)‚ÿ0r¾ä˜e’´­š®öÎu}Àhâ»zGx{þa{õ‘#G‚óqâIÿ:2˜ù/ò7bžC ™ù—nèÕ,üû¿ÿûObâßVø».ùçügc``@‡6;r€Y`óûQÓÞ9¾ Äwµ i©––ÿsçΧ%쯿¿Âí$ÕݺucOé´„+¯±ÌmÊø‰Tÿ} ;.~ÿûß¿ûü¨›pUe/ùç*üóÒÿóöïë—€wÃÊÅe¯»Œ.€šáeÒ×Ý5{öì–0è.°{}ÒR-KûIÀŸ¬É¼¿G›p;iñ_µjÕXÒ¿þ<”žô!Àû*Ȳ“žæþÕ‹/¾ø£wÞy§[¥/ùgø7’p(˜·ÏβÐʺ¬ àjd þø*2tõ×ÙHš G¨7ÿ½Ñ/â_L€´°?A’þåþ-¥å_F®¼Æ²·)#)² …öíÛ÷Æ~ðƒ—Tò’Ib>MøÛVýÓL»\)Zÿ1 #Ì€fÎø›l[Vh耭.¾«nZˆà—9©¬ŠÈ:pàÀ1&»µk×Õþ`§U'üKêRÒ?ÂCÀ÷6¥e``ÀËãêñ–ÞÛo¿ý‡jtÉ¿!•Þúïsî_©ìö‚ÿ0 ƒ{×>c\w€NzwZЗ@Ç€¿÷B¸œš‹gÊ”)AÒÿŒ3ÆÎÛ$ýw²pÅô(Žt¥È*>Пó¡Í›7ߣG $ØBZÿ‡ ÿ¢-ÿÿa4<í߯@¨iè4ð5ÿPoì{.í'jrZªþaêIö—¤YÞ/osÿo¼ñÆ–mÛ¶íT£­ÿÃâݵÀµC OäÓúÐ03 i, 8è§€Ö~ÿ·íïï—ùçà6Ò â*Ž$ûKØß7Žz;ú'•ÿ¬àÆN®TëËABÿ’:S\8tèÐ;wÜqǶ˜ø¯+û—%•ð7mý c!Ÿ6ã_3ÿî«+ÂN­$ìÛ¥c@BÔBAµoß¾`®:ŽÌöË2bÓ§O÷–ô!€!`ƒ´ýK>…tÈeï׿þõûõIyÀ¤Ð¿¼j¿MH`‘Öÿ´Ûd7½0  ~Öy¯ÛÒIð“u%j™­ýÅM 9}ôèÑ@ðKÈŸ„ýIè_úkÖ¬ëÎ3 Ì¤  4dL%É rA^—7mÚô]=î"k[†sÿ&U}›Ù~_­ÿÿaTÂ@ˆ/¨æÍ›7ÝuC¾3ª*¾›mZHµ_ZýEðŸ?>XæohhhÂí/^¬–/_>v^fÿÀN›uGœ7w›bR>}ÚÛsx饗}íµ×öªìÐ?›¶Ûª‘ÖD=@é&@Ò¨ÀtÅxj+¿Ðvï!%â_Ž¥Z’þ“ÙêÕ«ÅÌ Î‹13{öì Iÿ$\çÙfÒöİòú÷ñÇ¿tÏ=÷¼ Fçþ‡T~èŸIÛ¿mÕ?ñ­P´þ4Aì+±_K8®éñiõjšRñ—tÿPPé´ ·‘P?™÷Ÿ5kÖØyÓ¤  ßÛ|†þõõõíû×ý×ÿ§ÆÏýÛˆ~q_…ÖÀ„}ùÛÐÎ@+ŠôVÉ#ÙiIú—%Ô<˜ØN-á~7n þ ý+’ô!€!P ©¼|ù²—ÇÒá:ñÿ.%p^Ÿû·ý#­ÿ*CüÛ~Ì €ÒÍé¨ä@'w ˆˆ’ƒÌù˼¿ÌýÇ‘`¿uëÖ‰}i÷÷ô!€!`ƒ˜V.\ðòXÚøºúè£ÞõÁôè³WTþ<¿ËŒ¿© $Öm«ý´þcxöµœÛL˜–6(n²qKñ@kömå2©ú‹’*ª$ý'-¡¶`ÁµråʱûKÒ8Ш×ÙLáŠ8¯Þû*ã*Þž×Ë/¿¼ù™gžÙ¡Fçþ‡•¿ê¿1€¸p§õ0 T¡ïíquùÔvxƒZ}©A™™îéé *¨YIÿ+V¬P‹-;/aÒ§WªõÕÚÞÕ«Wƒ_¡;wî|öî»ï~."þó„½Mõ?é>ÍLýÇÀ(dÔlŒƒ"€‹ ! 0Y@IØŸTýEHÉÌ\LI²ÿÚµkƒtÿð¼ˆÉ@¸b4k{b\IèŸdUø@‡]îú—ù—ÍúäE5ú7œ#ìóþ‹ü©áo*èiýÇhˆ!6wÉi7•·«9¦…ÜVD¿,ó'Õ~iÿ?zôè„ÛIÈ߆ Ô 7Üœ—¹1$ôáŠ!Ь÷U΋øOêTqAw¾ôjñ§^òrP%'þÛTÿóFF”YÕŸÖÀ€ÊˆüÂèJr¥÷WZ½µ? ™õ?~üxPEíîîNLú—ù~Yæ/û²¼Ÿ¤  ¢HP¥ë^K›—6mÚt—î„9¥Òÿ]ÃþŠ.ù§bAšø§õ0 ‚?5,PÎë:óÛ)­ýYô÷÷K»sÐþŸ–ô/B_ÚþÃ÷Jò¥ò_æ{GÀï« }}}‰•®Oõ¿øÅý¯¾úê'j4ñX™Wþó–ú³1ÒÄ9­ÿ€-iL¸_­ƒ•x³º z{{@’Ó%é?©ŠºtéRµdÉ’±Ç‘ö™ù ;ªõl³Û“´ÿÁÁAoÏí­·Þú¯Gyä7ñŸ'à]ĽmÊ?­ÿ€íg h!ÐåKT´‚øn&”&3þ"ž¤ýß¾}Aû ÷[µj•š7oÞØe3gÎ F®ÍÞ^øÙõ…6ÀÞøÆ7¾ñ”>)íW•ÝR~®•W3 MüÓúàG 'ù$h¡Ž‹4þ .»lúôé’þ®l³YÛ“Š¿´ýûÿòÔž~úé<ÿüóéÓ—#âߤêïZùQöIÿ¶)ÿ|À€† þB3R ¯×‡Ъ­ýY¢IZþÏŸ?Òö‹¥ÅݺujÖ¬Yc—IÊRÒ?ÂC ۓϬ˜Xq㪯¿þúã›7oþMLüûªúçÍý§& ¥Ì—üË}ûùYèŠÑP.PÞ«j`ÙFDÚm¥]Z–ù“´ô'N¨C‡M¸$úKØŸTûC¤ê=ß ÂqÞ¾ï«\/3ÿ>Åÿ‡~øüüÇüâšøRf¡6KÚVü}-ùGë?`@eÿоBÁZ¥µ? ™óïéé D“1âÌœ9S­_¿>èdÎ_æý‹$ý7K¸R­oÏ×(§e©?ù<ûBÞÕËý=¢F—ûRÙíü¶³ý.#6sÿÊQü@ㄽéí›=ЪDÍ…ÁÁAYÓ<3éþüùjÕªUc÷ “þË ûÃÀpA‚+¥ƒÅ½½½éK_úžö%Ód¹?Ûöÿ¤êü8­Â¯.óµäæ@eŒ€1ôŽùP;ew œ={6˜ù—ÊÿÞ½{3 ÎÒ¥KƒCˆ$ýËü¿l«Q] ¼¯yHå_B+=š Ý_ùÊWî8+_³Ä—Ð?ÛÊ\ô³ä`@G ;©µ"¾F!ÔË@Òå SIú·MKuíÚµA¥?Dfý£áU®ˆs ßâ_a'ÿíßþíÛÚ니1ï#ðÏÖ`î0 3LݶN ¥¹ ·Ñ­ÍêܹsÁA*ÿñ(™ë—°¿o¼qì2Iùžo7É6³·YÅ×(·—¶Ÿâ_bwÜqÇ7µ)v,&þ‹þe%ûXšÊ@èÛŠ ¨6E Ÿeu—Ûæ!B?Lú—¤ôîîî ¢KD¾„ýI«(¤ê/+´‚pÅèŒ×þùœù×£07mÚtÇöíÛ»•[Û^û¿Mõ_©üŸ"s0 Ú\)÷íÛ¨Jk—/_Ä¿ÌûK蟜Ž3gεfÍš±p?9–eþ|$ý#\1|m3¬üûÿÚ»ºyóæ;_|ñÅ"â?¯õßGÛž  R„¿R´þtuÝú[ láS¤càÂ… AØŸ$ýˆYæOZ¦£H¨ß† ƽIú—@„+†@•¶)·—e*¥›¥ tæÿðÿ°IwÉ ¦ˆŸÂ?­ÚŸgÄ…âs0 å ƒ h ÐšaÒN_¦PT\:u*h“–ç)añ%Ò$ìoÍš5A«ˆ¬Š iÿ>D⼜mvâû*ùbf•5zóÑG½ü¥/}é‡×ÒþÓÄÙ#*½Å?Mø#þÀ`g¶p@•‚£Hµ_ZþeY4NŸ|òI03E‚þ–/_>î2ép]qÞ¸mvÚû*Ÿciù/cÞ_رcdz_þò—7ë“Ä¿kÕ?/ðÏfÞ_)?‰ÿEþ_`@ËÁŽóµ/gÊ EÍ€˜ö'Iÿ"úu[sp:Dªý«W¯VsçÎ'æ¤å¿ìn ^£ bdIKY-ÿò2^yå•ǾûÝïþòšøJÿE«ýYsÿ¶iÿy‚?OÄ#ð*#ÌkžÇø¶çâ=ñ–T­@„’TþŘá´oß¾qÏQ¾ÌûK¥?jˆø&ý#\1š½M1­¤å_L€2Ð;ôË_þò¡xàU}ö’­ü»¶ü›¤ý'Uý‹ÿe'ý/¤õ0 ­ h0 ÉmëZ`T¾À©ö‡IÿúwðàÁq¢LæúEüKÀߨÛäÉAò4áŠ!Ðìmʪe¥ü z,æâ–-[îyê©§ÞÕg/;Šÿ<ÑŸ—öo»€R„þ€»FÑB¹P€Ì×7䉿ŒHµ_ÿ„'NÈ:æã®O û“nÿ6ÂŒ€¿ò·ÙÉï«t«HÕ¿Ìï•Îý8£«þw¾ð _ÿC–âß4ÀeÖ¿Ëý!þZOÌ«ñYí²c—ëYùBeÆFY¢Jªýb"üň’ö'Ar("ü¨Öó}mSNËøŠTýËjùôwåÀí·ß~§Å<¦Ï^qÿE–ú³­þ+År€m*Ú½íúþýûÏ_Ûïr1Rµ”ùùF¦¨0“óaÒ¿œÖ¯E9sfœˆ“°¿yóæ{™ÿŸ6mÂC Û ó*ʧéîîþŸ¯|å+÷õ÷÷Ÿ½&þ‡-¾kÕßt©?“ªšèwóˆÀ€J ý¤*Ía·Ã:l쬞‹Ÿ]DÀ4ˆ"¦Ãñãǃª©l_’þen:DÚûׯ_´øGEœˆ¹Îfe„+†@YÛóJ>·e-ï>ýßýîw¿üÚ×¾ö¸þÞ„Ëü\3ê†âßµêïÒþ¯”ùr$þ`"X¡F® S™ñ—9i1vïÞ=nô›o¾Y­]»vœÐ—Ó²Ì_–HCœ7f›þ¾ÊçV>Ãr(ÝYprÓ¦Mß{å•W>QÃþêʼõßEü×-Ä’ð¯çüßBüt”è·¹oæy1Š<¹FR1 “þõsÄ´‚ºhÑ"µbÅŠñ;d×–ù³¼FŸÛòÒÓÓ³óßøÆ½‡–/ÌU•öçZýÏÿI˺¤þg#þÀÒ¨ëjd_‘iÄJ:¸l,àOf¦¥í_rBA—ö'c 2€pÅhæ6¥SE>³ 2Êêï½÷Þõ«_ýIdÞXŸ÷÷Qý7ÿEçÿÿ€ üäŒíPëÊzU k'Ož ø“. ü «¨Rá_·nÒ# ãî'¿Ì\ ^cò•Ï­t«4Ýapþç?ÿùüã¿­ìæým ños@ü€¥PÏØ9NÚ ÑK.ò¤_Fª¾<®Ìû‡ª¯¯O8p`L°‰È—¤ÿ¨Ð“þÅo‡8/g›¼¯é÷oÔœˆþž|òï|ç¾]»vU£Kü åˆtWÀVü›eŠ h{3Àdy¬`‡û´¦è†¥ šºïãñ¤Aºô:æc×'…ýIÒ¿ˆÿø’„TëyئÜNæü¥ê߈9ÿp³Û·oßvûí·?©¿3¯‰ÿá Ñ_¤ú_EñoúZNÔ›\n³ãìt;v¬¯è“ôiˆˆêíí›ñ#àÈ‘#c×'…ý…ËüÉ1ÂC ‘Û ?³ þÒaÐ÷ÄO<ôôÓO¿§&¦ü—mTEüÓú€Q±#ß!Ñz…;$èLxQ$%]’þEdÉA„¿˜¡¸[µj•š?þ¸ûL™2%p¼F×m‰ð—VÿF AwÃüî[ßúÖC:å_¾»Ñ–ÿ<Ño:P/Yü+ñoò?ñ†;ÁÁÎ÷ÁƒÏksYWÏSóÄ(J4éÿšÈ[öOÚú7lØ fΜ9î>Òuà+éCCÀ”Pø‡]*BÚü_xá…-÷Ýwß+jbП/ â?oÉ¿¬ÓˆÀ€¶íµlcì´4ýZH/* L ‰4úRýÏïÛ·/0ø"þã#þ7}útÄy ÛÄôH¾¯ÿ‹/6\ø zTg×]wÝõ ú;¦®ÏúçsŸ@⿎ø ;£Àµý?¼lD'í2$¬Ïe%i–¤U¡ÈÚ»w¯Î'…ý ñ¤„+¯±¬mÊgTV¢C£[ým®]xå•Wž¸çž{^T£³þWcÂßVô»Tüó?â0x  ‰Æ€ÍõbH¯ý§Š)ˆ.ÉgbHÀ_Ø=VþCñ¿`ÁµråÊq¢,\æ/n \1|oSªü¡ðo===;¿ÿýï?¼sçÎpy¿°êŸ$ü}ˆ h p¯eœ·yŒ´ç¤®‘³gÏö.Y²¤Ð“!ojH+µˆÿ°¢mû¡')ÿ .wŸp™?“¤  WÄÈ’Ž”p Êf ¿çž{î¹-=ôЯUú¬£ €2’þÿ€P‚`rŸºÞ½E7nšMú‹ië_·nš5kÖ¸ûHÅßÇ*¼Æ$ĈSªYmþÑ—¥¿ ïÜyç›uf<áßFø›Š|ÑøÀGqžwyÖŽ®M—@=çò`gþäÉ“… PyèNÕ××7Nü‡3ÿÒ= añ`¿p™?„«Ÿmbz\¿½˜Vò¹õ±ŠEQô ‡Ÿxâ‰ÍÛ¶mû0"ü‡s¸m ¿IÈŸ–ÿF‰ èH3!ËÈ[g»®×?^¶púôéÀˆ °={ö—ÝtÓMAå?:Û/N’ÿåà0ˆ!€é‘´M™í—Ϫš\í¥ý~ûÛßn½ûÕFÄ5ò7¢®Ïúç ÿ"@-ÿÿ€#ú}<¦0òÞ{ï+ú`"¦¤¢*ûøåѤÿ¸øO û¤# úX´ïó‹~6¥Ò_dÉJßoÃîÝ»}ß}÷=©ÛþO^þYíþ¶­ÿ¶•~Ä?´€!4ûŸ8nçüèÑ£´0:§÷¬"OJVT´KZooï¸kcÒöîܹ@øÇÃþD JËZÒ?††€éc†-þýú;±û±Ç{\/ï·W.í7¤òÛïMŽm*ü¾…?â0šl ˜îLè ýÉ¢€ˆ­0¬ON‹ø—–ë¨(ñáµqãÆ aaÒ¿‹džC \޲b•þ1´éuâå—_þÙµtÿPø%m[ÀÆ ð=ë_OúˆÀ((ê³.7 L\ pppð„žÅ_[Ôôc),8AÈ8p ¸Í§?ýé a²€\æK`R­ïŒmV´½zuþ7ß|sÛý÷ßÿ’>-³0òD‡-…¸Kåßg»ÿH‚¸Gü`@ „¬ÓÁκE7$"Lýu¢ùѦƒƒ‘€[n¹eB{¿Œ Ä Ä2¯1 ù…íýUòËø>\x÷Ýwuï½÷þ·þ^œWésþ¶@‘ná?¢²ÛüóÚýÿ€`¸³[³¸ír€ñó#ýýý…—1&ËüÅééé „¢,óˆÑ¤ÿv®îŸ+ü¡ðo£jèçxyÇŽ/?øàƒÏèÏ~¿]Ö/«â_dîßEø×3žG^û¿Bü`@µÌ“ ÀèmGtRÿÑ2žŒ,ÿ'þeË–M¸NªþÒú߉âC û>¡à—C4G¢Êèçyù£>úÍÃ?üs½ÊEV²–à²ìŸË±ëÌ¿Bü`€?ñn3×orÿzÎŽu°ó¯—$;üÅ/~Ñë‹‘°?ÿóæÍ› Eüç%ýw²!ÐI¦G(øE臢¿•Šÿ®]»^“Šww·´À\Éþ.-ÿ>Ë^âñ¢Ýd‡8É$ÈzœzÎñÈ[o½Õ£[­‡uÿ$//J‹:ií—Tÿ(’ô/â_Ž[]¸v‚8/iéV÷[¥ÂGú{ÿý÷_Öÿ_é¥4¥Õ? ÷6×yíøeE—øËû‚ø @è+»j~Öý]+k§]B¯è¥{õ2~K}¼Xñö~¹lÚ´iÞ…%†@u· üpŽ¿UÅ~ý]9µ}ûv™ñ1îþyB»ìê¿mÂxRvÕÄ?4ÁPˆŸ¶ÍZ•µ°9êËH”ÚdNKû¿J9–n90Zï5Êu¡ÐoõÊ~§N:ðÚk¯=·yóæwdÞ_%/ç—gý÷Õæï3èñ¼Ð` é¼R9gÏž=ºpá†<ñPFç½C 4Ĉš­*–ÛÉ€íˆÈ~Tø·#2£—°ÜñÜsÏýê™gžÙ¥®Ï÷Û¶ùûªþþ.Ay¢¿n(öÿ€à(ô]#íXúÂÙ³~ýúæ½H-&C™Dh„Æ€kçíû¹¢wÜ!ùíVÑÏBÏ÷ŸýàƒÞxì±Ç^Ø·oßiu=ÑßDøÿ>Ûümgýó*þõŒÿ)ˆÀ(Yô'…¦d™#ÇŽ;\å7$4Ò„h܈ŸO3 :ň,¡¸~–ùÒ)ß¹ãÇòöÛo¿¶eË–·õ*#¢ÄBLûÿ6Uÿ,Ñ?¢Ò«ü6Iÿˆ ¨°q`ÒÊ;òûßÿþàßüÍß´ì 7¯¡ØC“ ¼,É(ð1†àÓE{ô¾Q1}/¢—Ç·£è\Šþ;w¾ùôÓO¿ª{Õøj¿mÝEü1Êj÷/:ïø Ÿ&èm—T9;õ#ï¾ûî Ô~nÊ”)³ÚöÍMζÄM„Ð3.àã糄xÒuI‚Š¡?ç—:ôþo~ó›ßþô§?Ý¡Ï_V«ýyÉø6ÂßUü—!úm+þˆ (Qôçí0ç‰ý´}¥ÒÛE< ë•Íž=û3üIÌMh ´Ù3tôèÑwìØ±ýÉ'Ÿ|[g^œSÉ-þ#*»MÞ¶ÝÞG€k«¿KË?â(ô]/¯ À¤â7Ü×××íô;yòä]»v½«[üßÜ¿Ÿº¾|ŸI ŸRvKè𹜟ÉkQÊß¼?â0J6’L•°³¯2vòÇ:tUôàÚµky·¡¥9sæÌ‘?üðí­[·þV‹ÿ“1ÑïRéw(Òà³Íßµåñ€-`Ô Ì€DsðàÁ}_øÂxG¡¥Ð«\Õ•~]àß¿ëå—_ÞþÖ[oIý¦•ñ"¡6¢ÞEð»üùhù75ÿ€PPØ›ÜÖt9À¤þ!жçoÿöo}*xçÊ•+ƒ:ÈïCÜÿþ¶mÛ~¯—ð‹Ïô+·Yx_¿¨ø÷]ñ7ýÌû`@…Òù´Ûe-˜$ ‚´½{÷ž9pàÀÖ… ~~ÆŒKùS@•èïïïÙ·oߺÂÿ»çŸ~¯TþÕø*4½?-Å_)3ÿ.+؈}[ ë{®”yË?âÀspÙO¨%œŽÇOG] ÇñÓáaRÆé)ú0]¦ýÑýÑ¢¿ø‹¿ø_«V­ºuñâÅŸ™5kÖ2ös ‘èU)N÷ôôìÖÆÔîW_}õÃkóü"ö‡Trrž.sæßÕ ðQé/º´ŸMË?â<ì+äiâ?ÏÈ:Ä €ð0ùÚaJx¼qãÆyÚ¸uÍš5-Z´nΜ9ë¦L™rNð,ø?ÁÿÚk¯íÒA~'Ôõ |¹>ÑÛˆ¶ý"€RÅæüÿЂ€‹ Ö 7¢¦@`Lš4iòŸüÉŸ¬ÐW®\¹^ ¬ÕK®Ð—OáO &œ;wîdooï¾Ý»wüæ›oîÚ±c‡Tø³æøGÄk#«þEýˆr7lÌ SÀô´­¨Gü?êŽ@šøW)Âßt Ið§™&ÝÁñôéÓ§Þzë­‹n¹å–•ºS`Í’%KVkS`‰Î˜Ç>RgséÒ¥³z™ÉÃÇŽëÖiýµàÿD¨üà>“5ëMEQ#`¤„ëÚ¥êø~Ô €¸ðWÊ< ­ –#þ³.7=LJ0&-[¶lÖÿñ‹)°\›Ëu·Àʹsç.×ÝSù8´W¯^½¨ûŽëê~·nçßóë_ÿz÷Ç|ZoãÏZžOÛfVþ}WöËø3­ô#þ0 û Íp1’: L·˜:?`òm·Ý¶pÆ K´A°hÁ‚‹u·À¢›nºi¾î˜ÛÕÕ5‰Jký¾¾¾cZìíîî>¢çö{ôÒ|Q±Îï'µñ›V­‹VþËÿ+Cø+UnÀ_^Ë¿©¨Gø?ê¼฿55 ÐåÙ09d ÿ$SB©ô.…IÑÓz”`òg?ûÙ…ŸúÔ§ks`ñ¼yóêÐÁ…7ß|óÂo¼qN­Vëâ#Ô0êÒ¾¯9¥…þñ'NÕKEö|ðÁGtU¿/"î³Bú\ÛÔ]M€FUÿË ósyýižª?´˜eä‰_&@-ÃÈ2j†Ï]ÅkÂvµ0Esuðà<=N0_3OwÌÕËΙ9sæ\}ýlV'°C üs:¿O‡òÖ"ÿÔ™3gNëYý“‡:©ƒùNœ?þJLÜǯ2û6‚?ï2Û–ÿ2 2™3þˆ ¨¨þJÙ˜„º˜6Õÿ,‘ŸõÚ”q>}nºS`êÚµkgëî9º{àfmÌÑÁMú0[Ü4mÚ´õaFxÜŽûoõz}äòåËç/^¼xîÂ… ú õý¹]ÉÐÇguË~ÿÉ“'t»þÉK1Ak²ÜžMå9í6e¶ý—!ø}Ïñûžñ/"üÿЄýÛ¥Ò+ðY]6¿Ö` í}°¹oÚèAü¹t-_¾|ÆâÅ‹gép™zÔ`æ mÜ(Çzašî(Ð>Á´ôaºœrg}<]ç?uêÔ ó@Ÿl»âÈÈÈÐðððUîz¶^¹ºråÊ%9?44tE_?,— ZØ_ЇKZÜ_Ї‹ºBA ûA}¸¨Åü NÛ¿ Ûôôã…óöiËÒůËã&"ÓÆð-üóD³Lå úmÿTý0 ÷|Œ˜ŒÔ,¿Mð_# •s¾fñ~*e6¦e@˜>7a•&ØŠˆá<Áž'] —ª¿oáo+ø}.Âßæ}**üÿ˜Ì[ž¨§ˆÈº¸´XÑŠ°º&æ“.Éëu@Y&f@^³¼ée¶@ÝñzSÑ^/p_¡oz™ëò~6F@Ù]J•/üM €¬¿±Ïª?âš ú]vÎk†"k$"ú£Â¿+fäµÜ§™J•×P†x7yÿk ü<¹]Q ‘-ÿ¦bßFø›ˆvSÀÅ`0y]yïKÞ{n*ü}|¦d D ‚<³ žbDüt\øçUþãâ¾®Šwø6Ê0eY‹½Ä¿Röíÿʳ€¯;nS)¿mþuÇ¿£‹ Gü`@ ‚Þõvq# K¤¦ µ$#ÀVø›´þ»Œ¸ÌñÛš.—7Ò@üþ®f€* þ} ÓÓ¶ŸÄ?TØ0íH3ÒF¢â?Ɉ›¶þgêùÊÈúðeøií,þm¸ïËMžË\áosÂZØÈúy"o$Cè+e>ïŸ×úï»ÀFø72Ô¯Ÿ…f &€Oño"ü}^f*þ]…¿‰ `rñ€-$ìMDZ€©@ …~žÕ}ë¿I€‹!`"ümDU‚Ë^%À§à·ý6†@Q# ¨¸/bV ü0¼™QC O”¦ ˆ¨ÿi§£&D—ÊoûwIÿ/+ÀÖ pû¾Vr("ú}[ Y9EM"‚ß·ðÏ3ÿÐfÂÞä>iݦąžàOö>’ÿ›è2àb ¸~>l¯·5š=ÿo+þ}˜Íüõï?Â:Ì0YöÏÖˆš*CüÛ´ügµý»Îÿ·b@Úýê?®F€oÀÖ pÿ>M×ÓE¿4Âñ€ú6÷I:V–F@TôÇ/«e¶©ÿšÿo‡,_³ÿeÿ""¸è(€oqï#³Àæýò%ümÅ<ÂZÐH ÿËp1âÂ_ˆSáßìù3 OÔךð(jTÕ(£+ ˆÐoT•¿QÂñ€-n˜ÞÞdi@SÀ5ð¯ˆè/*þ›5Pó,ÊZy ¨ PÖe¦·±}\…>íþ€ÈO¼mÖ(@R7@Ýâñ]fý« þ}Ž˜ ÿšçÏ‚/# Q«5\Í€¢×¹›ˆ}„?@‡Pã-€’ö%L*Üysö&¢ÝµÒßnâ¿VàoÕ(3 Ñ«Ø ã²M²Ä¾éue Ä?@ @4“¬PÀ¢i—™þ¹ši×ÿ­0ÿ_D(–5àKü—-â)ö]–ïCø´t@™û¦Ø$qߤror}Þã› ýªÿÕ<üÝ|Š8á˜'}UZükï“Ëþ\2lÅhÌß"Þå9æ]Wô2„??ÒM7\żë\E~™‚ßwտȾ ÏxWñêÛ(Ã4pݶËù¬÷áPIÀD|û¾Ì‡ø/Û(Ã(_+øÌ>M_"ßå5ç½ÇÀ€¦ïcØš®b¾UÅ~­„÷·UÄ¿O1ìºDž¯¥õšQÕ/Kô#ü0¼‹T—yû¢íúÍšã/k‰¿V0|‰ÛzÏûôýÀ€Jìkíða´‹ð¯Ú>^³L_b¼¬ ~+ˆ~„?@ÃLß"݇ /Kà·CÅ¿,# ¨`n¤aàCð¹áÐV&€/ñîSð·’è÷¹XVˆ\Yf@3/s¹ÑÐÖûEŒ€F {ߢ¾Ö€÷¯ÑÔ=ÞÖE8—aøüUý~ˆ*k”eØÞ¶ À÷mÊØô%}ˆ[qݬË} ~„?`F@ ——u]Y"¿Êûv¾Åm½×UeVÑÐû!µ ]׈ë}ì³5k_¯^òýê%^_¥–ýzþ&€д}‘Zů÷y›2öÛÊØÿkteºìñŸè €’€fˆõZ“_o£³ aY/éöõÞ¦ìׂè€BLâ-€6lï×l!_á_e¡Y¦x®JžÞBà‡ ’û'e òFŠ÷ZßÛVµõŠÝ¾LqŽè `?¥…{­bï[Õ…j#x½¯ÑÀþJ ‰ôZßv3êM|~À¨ð~K­MŸS;RoÓÇAô@ö_j-ô\[y®ÕÄs½MÞ `_¦ÉÛ`¬"¹ÞF¯€`¿¦Mö£Úi®S„7‚0Út‡ý¬æQç9ðÃìïðÜø~à€} ž7±üø°Obø±`_ ûü¨°}~¸ØÇD>?Nì‡â€öÛõÀ øß7D xàÿ¦'¶¸»OÌoIEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/main.m0000644000175100017510000000314315232633614024221 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **)argv); } qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/CocoaApplication-Info.plist0000644000175100017510000000225215232633614030275 0ustar runnerrunner CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier org.example.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright Copyright © 2014 Petroules Corporation. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/AppDelegate.h0000644000175100017510000000511415232633614025443 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface AppDelegate : NSObject @property (nonatomic, assign) IBOutlet NSWindow *window; @end qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/background.png0000644000175100017510000025114315232633614025751 0ustar runnerrunner‰PNG  IHDRXr5˜sRGB®Îé pHYs  šœ@IDATxìÝÙ²eÉqèª:Y™UA#kQˆ¥~Ž6I$E }§ ™å….ô‚2ÓcÈÐ@¡2kjÿþXÿ>+“$ª/šHÌubòðð˜Üÿ{íÿëÿüïß?==}ôÝwß}T÷Í·ß~ôôÉ'}ÿý÷}7ð'ó|;éè>ûì³Gøã?NZóñúúë¯?úèã>úîÛï>zñé§áóÉÐÉCÏ…÷­N奩{ù÷í7ß~ôêÕ«¤ûÝ·}ÿÝ÷‘£åùʵlÃêÇ+nêS·zûH׎oçiž0É”ÓN²rõ¥}:má¾üòË^¾|ùh7ü¾ùæ›ç´/¦ý߆—þj¾òŸ ½zÉIfåð«ÌÒ^N»ß¾y3ý÷"íVŽCóÉÓ'#ë)¯œò•M?½}ó6ý§ÿë^Œ<Ú¯üÝ®ü¥Ýñßñßõ¿ëŸ®XýæÁêÿµÿµ±ˆýúÑ_þì5ãÏÐrÂ/Ôøß¯°E—…7tŸ¾À18 àøá%~¥3 ¢Fœÿñ'x†ÚbÈ'Ìÿ~øáO±Ç]ø¨²}<éʈsh_}ö*qa¼#Ç=€ð ÜÕ¶¼þ4-üäO»ðÁC^y [\÷6ÊÓÒ9¢~÷ýw½üôåxW­#ýrõzéé€$?á¡y”¹h´¥}®>ò6ÎW®ÀN>:L>úôŧiÃçŸðõfÀZÚ <‰â­WxÇÇ×ÿÑ)ÖÅ®ÿg[ÝCO¬þ_ý_;϶°E±%ã7ýC·ÿOÿâXv8(¾Nb¤ bÀ@t‘½x:´íØ–e ÛáÒ8Ÿ„¾ývvx0àËÀËËîËøvjÔÛ]%<ëjüÉÔt´ß ?;9ÒÊ3uMÐ=Ê–Ù•¦ §­Á§ü•CcÍŽ‘tý#]¸}Õ Û‘’N®{Ûõ MÀåLJ&å#åÈ8å8eñPÂóâWYžËöyB+7#ÚÊ(Ú&ÏËWü)Wƒ~S:c±ã¿ãß5l>uíúßõïä]ïÑ«ÿ¿Ï‡W}±úÿØØ’µÿlóô'ÿŸX7Õø2ÄÇŒÛÜ02ÿ-0ŽÁæ’žÐ2ò«”›WZò–@0åп}û6 ÊˆÙý¡à_Ž\÷ÝeñÀ|<­WzÓÂlèÑlM˜Ã#iÒçQÏ•ñhïI8´Âø¿zô•týöjÀ‹#à̹=Zå%ˆúU$í铳c¦oÈØEšúÑL~Û'¼Ÿ @»$>rMâÝù ÿ‹Výv°ð°Køöë·G²·ŸðÜñŸ›1h¿N,®}¹ã?³sþëÎÜå²~:óZ¾>ã7¯´»þOîú_ý¿úÿØzzâÝþg‹Ž´ðÆV£™*É*V4ÒªH…›VÿéÅó}.FœCGÑâÙ8Ÿ“îÈðÔŸô©Ç'&w‰ÈƒÿÖ„…nÒË;ñáTHâ” gË£ãÐÈû~ê)ðAS'¬Þò ÏÉ”®ŸîÎ]1È)½¶õ˜¥|íT¡iÿu·N?µ¡G–Ô5qýQ9ÕUyÒ¾ÉWN¿´­ƒ<ú®bdŸ;ZWøÔ%oǿݑ¾Úñ7»ž•9bÞun 7­þ®ÿ£výŸyó§ºmõÿêÿξ5òØÿç£8w£ÎŽÌ«ø6éÆ1øAãSªU¬Í³“S`Õ4>‡7ƒ¯ŒËï|ˆàÍWoÂÓ1Öçs!;*è²Ã2„1ö3yWoé-#Ís„ÆÉûæë\ÀÍ<Â@XÜt<^ÎùñÉñ™²×\€qw›ð X‚ņÁ½NaîÐ⯧ÀJ~Ëðïr·|}eò>»|d!cwýÔ#Ÿü”oûXüëožA¦ãCˆ ˆSr|²Ýwï¤yêÔ1 z´IüNC~~¡‚éËGÛ¨Œ0ºÿÛü¾ÍÛŽ{ýÿ]ÿÖK×û®ÿÕÿôhçÃêÿc¥ôÉÝŽJú€ìî`éJÂn÷ÝìIËû0àÀ´L``v~”ÑÒ@¬F1BOÕ¡ó7%æv²&!à/@ LêoÁññ¿ËSçnY8†O\ ê÷ä8ñ’¥ò£­±$O&Á¤ñ¹Ò©C]ÀˆÎè¥qx á†|ùúJ¸ýAöƇã߆8´^ã ŸS^¸à¬2„^yÊh¶Ÿ”ÑÖÆñécð“ٹƩ þòñßñßñßõ¿ëŸ‚XýÙ¹ÕÿÏ6„;ÁfäÔhíìôï²ÿO?þ«Ÿ¿¶¨NïÅpÛ5RÚ¡ Œ¸f¨kø{„6p›éÕ°'áúS0†gÀÀ|›0ßÎËÝMqîeÕ‘ú.ʾïäGÎÙÅÊ7‡Ð sÊOº¶¡/ϔіqiû”‰?qeåMiß{:¢ËÎ9‡¶å„• @_?ˆ“K^Úznvþ€,;[dAÛúÔù>ïìÒMzûåÎ/BÌŸæiMǪý‚È-G„©câv¬Ðqiû„Ñíøïø›]#SæMæËøæ.·ë׿yáGÇT%áú³úÿ¬§Õÿ–ýúÑ, „2»ŒlŒð$4=Šu´.pÅ$<´þMÀßÄrð²è.¾Œ·0E­LDÅaÃ38B£ñMý¡8¯ß»_iC¢;HÝݺ·§õÛíâÜå.àAÛúƒöµß\—ÙÃwø£Ç‹ U0ÚÏ=â—!B£=¥ÏbŸ“~wm—:ÂdŠ»èíhq¥KdþTv¼[V^Û,LÙå^×ð,ïGýÃȺ÷—2©ÇPÏ¿´Mxèvüwüg"X™»þwýG7]:”^YýÖÆêÿÏþ¿pôõÑÑ fAe j è¤ÕøÖx…Zä×ÎÊ)º¾¥¼<ºëƒW úiÆ„î"÷ èë·_ŸOÈSf,}¨ò­_¸NZã|9 ß&ï*x(çHXô>__äNØÐU6õ åz,w—ÃÅVòr‡j:“Ø×Ž>êVgzi}MCÛ ­áT¨NåÇ¿Ëð½úæi;ж}Ò#ŸÄ‘»åøò¸ŒùøOÛµœÀŽÿŽ&Æ®ÿ]ÿ&³>¡Wª7¢WèBŠnôÆêÿóÅ&ý³úÿÌ“µÿïÚÿTª‰ìJ0ÈŒîm5lÅ K°È.×]©Æ›÷0ìŽ×†þŠcü•á¤áÙ00’o¹½œ‰;Çs=Â*0)] ÌŸ‚ ~]”@#—_iï@EmðrŒ(mgîTM¯äîÒðJ²dçkÚ„–Ì\Úw—,ä@+½òå>â«ÿš.©ýÀ¼CƒGù ×=ÊÝÚ}Ïk>?Ow ¥åø]u{ÿßñOíøf¸æ¿ë¢s³óm×ÿ®ÿΓ̉KOU_ù )ŒÆZáÕÿG—ßûmõÿÙÔø£³ÿä.viz)_š=;(]@Òcžg! Á;庘(gÀÀ»÷6z'_‹Î$ëñ[Ží®…‰)ir­;ò Àñ.«ï¾yþF#yž¾¬4‹zÊwG©|:±ËS>yÃ{|ùýÖceÌÚ0¨¼¡yÐNùÔ=<†€Ó¦Ô;¼êr!ý’±uל¼ã)Ó¼,Mý2õÉAË2>:ù9m'£§®wJ·ãŸžÍ8íøŸõÓ¹R?kb"»þ}(Ýõßy±úÿ\‰`?¢×Wÿ³;læ‡lÿ_hª‡YŸòÂó³ÆñÑ{ ¦Âÿ2îQÐC/-€gÊ™”­£á‚ Ò¿_¿ô:ßx©“ÞQoø XË›­'>ÛXI«qJÙ)ïRpAÜÅâÑõœÞ|0?ña¢üÝÝejÿðõQiÕÍ5_ú©cxÍÿ¤_ct(Ïßòæ÷‘“ò;þÓgž¶Ovü}pšu¹ë×?wéöÕÿlVTmt'ý¹úÿÜþÿèú±gÆ<ÚºÔúw0PÃ]C^…zâP¡·°“ ÷ÎÓã(n,;ÞŒOÊø„¤àݺ³Ã5ùèÍØÊa!+çá*sýòíYÓù}!h¾f mŒ Ð%¯ò§=Öðj8„󎟉9=t@œz'3e[7>÷rê5á¼$0À&G°¹òøÊ‘ëïsiïUgî]ò‘ƒL<øu;þvbwü;:OëwÎÈ7¿¸³Þgí]€êÄwýë‡]ÿ«ÿ­™Õÿ¦ýþ-BGU£@‚òdˆÝ?¢\«H¥UÙ&mâ_ ˜<”¥zÑGŽÁð”€5>0„&»Lè¯O®udwi¤‚ô•(ä W^à@º¸ºÑ*S÷hÓ•¦¬üòÎ%»áS ¡ ײ|ôNûìÂÝÓð!ǧ̤kC¾ÍxñÒ'0ºò§Pʩ˃Ÿg¤ÈÅÿS÷1hxq凾}-ý›kíå§/?å3Ü#ÐU—£Ê©cÇÿ€çÿ]ÿÖœõÄñéþ}­ïú_ý¿úíÿ]'ÜíÿÓOþýŸ½¦4Çp¨áýv€ €àëîût*_Çd/0óBǯÊ)¯\žÔ”ô: ¡´&#ùÍã+ïáò:Ê-±Ã§ z_áè䓵r´î– ¯ìbµ“G^@Ù¤‹{Ä¥¸èôiR|+O;Ш€I½¥v¼ùê«ì„Z/_~:>·#ŒôÍÔSùêWîÐÜþd·@ÿL™wÚ04ʶÝ|í '?ÿÚ¦ÿÿL/óéævýïú_ý¿úíÿÙ¸¡ÿûÿôã¿þÅëÝ›ćÙýÜ<àj ¶‡¦`«ú˜çò 7Šz†œ_C¯\Zéuò8%0àF+e=¥MùÓ8¿àBØó¦¡-]ùä•ü€Ùq{1÷à HÐrøê\€¨±k׺€+®üïí’.Ìðñm~ÛÒr•ë}?¼oüÅ9åüã"§>›XyË#Ÿ]ªÉzÈ(Ÿá1å¦À£LåÙñ?óUê«ÿ]ÿ»þWÿ¯þ_ûÿûØÿDL4Ã|Œô1&Œ,£"­ÆZZ.-%W¹îîÄ¡÷oòk”ZÖý¦þì\…âƒÖÓM™(i=¥í®6ÒÔƒÎÓ´úòF‹@äû¦¡ …µO~w¯ÜÁªüï×·WÛ?˜†ÏÔ«\ðÐxÇ—4ŽNbþ&]Ý­ÿΓ.ms¤©ßmñ¹Öß¾Ö÷•³õ‡÷ðØñßñ7oÌ“Á¼2Gø÷9(m×ÿÑ1»þÞ¨^®~Ê<ÝÈuþ˜7«ÿO¬þ~¿£9r·o±K£‚X°?ûÿ‚’H£êc—¾t ÄâjÁH'.oâhä¡—o!qâø?êH*öá[ã_z¼"ÏU^¾× í@ð\RÏÐ4M3B3¾÷i “ßSÆCÖoãØîe.¦T ȼ¿"í”^z>>øáãyûæù<=vŠ>þø\>Ýìzé3`L¾·Æóå‘!²O.ióMÌéµG¿UVþÉŸö m‡K¹„ç¾=ÿOÉãe‡GÇ£õÊÆÏ /Æ-CVnÇÇßœÙõ¿ë?ú`tÆêÿÕÿlÒÚÿcÓß·ÿù-B‹%FV`œpŸ“òœOÁNæã äLçê`O-t†>  M‘áLzQá1®åjܹ̓Âs€‰»A.¸×È£+Èy”‰<‡¯dR×Zä´=ü:uÛæ³÷í·Þgu.k›»R½è ¢7WC£vEŽC§ž’ʉ6}sÉUYÂÒ¯¯ºöÏ­êG[¤¥6e'Ü>’Þr½C¦ŽöKëC׺ê7Müý4yÊNÆŽÿô ±ã¿ë×ÿ꺱zñWÿ¯ý,ò“¹ƒeB0œù&Ù€#nÒmÆXàn®Ý 8 EÆÐâ!.pAûˆ_y´)ÒzîÆünÔñpTG†Ô;<ÞwM/Mdš6pÂî`¥m' § ×z¿µ#Ü0ôW{{¤—ݨ/~2àjåñu‡ë› œÉW.}2y pÈI÷•mýÈ0ãÃáqwÒ¥½“þŒ ³ˆs ˆF;n2)Sùz|[Y’žv `õbTã9ôí“”pû¸<„{ôÇŽÿŽ¿)‘õv[?™_×\1‡Ä3‡wýïúŸyò˜×Ü0’6sfõÿꪣ6«a>÷Ç`ÿó&w "ö2À—{³(‹ÂÃÈæÛ‚“$(e:ñ`|òÉ~|Çk¾½Všú“p7ÄØ_à%õN=xôžG¸´È8eÕ…Wéùå0´œ²O&' %/tòæv$¨Âò9¾²Ò§³C¹&/ß[~¶Àå*0¥OÇÈ|:ßDߣǧ¡qçK¹»S?‡Ö7IxÐ3}6‰yhÈ©/"ËÈ“rÇŸ¾z_!VMÇË'nG§_Où¦Ÿ20«{ÇÇßœØõo5ìú¯®Yý¿úŸ^XûÿûÙÿ|‹5†bÇû¡eÆ» ‹ÁvtÆPß ;# ر)øÇKÜCQÇ¡Næ¾äqê<ã2îS×Ýá‡_ýx‡~*{ 4y=ýÖ£2dâðÆ« C¹¶·€,w¸"Ýš|ô飫¾¶KÿCãѧ&¢~m=@ÐÔºZOižòç“GZù&>}§›†tÚbg pu׋H¥mhâÔ%°ãÿè¿ÿ]ÿtÒ®ÿÕÿtÁêÿó!~í?;ù‡Ûÿ§ŸþÍŸ¿fcktc¤ôy„ïN^—Å ¸òýŠЮ‹ïWYàMÙÖyTú3` *@;ÚZOâ2ôç8ÈT^Òï®òóñ©»Óœð)Wò¬ûIŸôÅä+'-å‡0Äqêh™¼äSziêzt’ûe·Ü‘SÛ§.õöÑò<éó‘§-•÷þh¹¦O.ò<Ê ŸŽgû#íž²Séióô›4Mé¥UŽÈ²ãŸ>Ò';þ»þ­Ÿ]ÿGÑùâÓ¥GVÿÏÉÁêÿ‡Íþc¶ÿ€Å:@©5æ"§(<½ïÏØNZ ¯|—ÑçïìˆL™޽ÉqXï!pä”eè[ßÝƨã?Ö<`K˜¹GO–Ô›úO\Z]d¿h¥+ €ï—_€Á8*Wá#Jûj^JnJ°ð{…Q vð.ˆ!#ÀÖ:”-(Æ£}u—ÙhÕ‘Ê$æ¨pêˆ>ôWêÉšöOòõÁ8ᤫy€¾âu;þÏß”|ôíŽÿY?3g²dΘM»þwý?tGôÍêý±ú´Ã171+®Ã|Èöÿñ&÷Y¾‰Âìê' èäÇøgQCc4ñã_€è*?ćßä<0öñ*êÇbUÁÍeÒŽ -SYÈ¥>2ò9yÍW®ã\q ËÕ>2ÌsÞÄîH`Òü–,’‚!eðì.—ß¼ƒ¬%í¸äAç´\d¹hÎ&ݤ‚°^´ú¬my eÐ8 ÝÕhðFÏϥѫqmhß$Òü¶£Kýïçµ~~hÇßñŸÖÿÌÅûüØõÿü!k×õ~ýÕÿ«ÿÅý­mb&ûÌVBùìÿ ÕuÊ”aþxòßÂÓ)óp'Æ@3>'­@†¡¢tÞ¡PÒòÊøöàp 8±›õƒü @/ Ã3GhSàÄ´om £84ò»÷º•ÑV»†‘ïj¥vhpɃÚÄ¡ ¿ÀÕ8–Fø»‘W<ã;eî2¦.~;þzuÇ×ÿ®z!zhô·úõÿÚÿ¯²Aò»ìÿ‹ Èi?¥2X‚ѵ ¸€+\Ÿ Ö|Hj¼öXøü¹âµ0ÑãçÒ5WCþôñ¹LŠºõ5ˆæ¿˜sd§Lv­|tÁßå¼+<ê¤GF•ñjk&9ù€ ßÎ ¤Ó @òm»K–ïÁ¡ûÕ¯~õÑþÉ?É‹‚œ«;RmÁZ`É7 ½ÿÊë|º±³õbÚf'Ìý.2å™Ò@­rjSö¾Ã•>¾íd=¾æ¬iåáèïãÃ/€jƲß<Æyœ2;þ;þŸÌ<༒d×ÿ®ÿ»^]ý?ß¶Žn««ÿ5ólÛ”à³%”ÇÞpüÒþÿø¯~þZãuFAE¿åÖ´ÉLÕØ—žïQ€8qgñÇ¥ƒ'OyamÃè{ÔwJÜþNžADÏUe¸úåuO£ JÏ·CE°È8†¤mLœvÆy¯•2ÙyšºÕFFô\ûè7¿ùÍGŸþù£=}Eù Õ_è àRפãß:ø¶\y“©xÒ[ß‘óô%Pä±ÃE6yJ„×´Ìâ|m‚ÃkÀ#9Ó§ …Nùñ[Wû?i¥ÙñßñŸ)õ˜/gNîú·Nvý¯þ·Vÿ¯ý§#9öòq‹’Èk(q1Ú“VÇÐÆ€Ï$VX< %¦üø;MŒóeÜC;̤ÝyKo^€š«tu¡™8š¦ác·Éº€‰«yùÆ Ñ.ú08†e/ÞÉsÔ‡?z`È‘¦ôÖcѤ-SR8´dоùêM^ÇðòÕË€0ÀK¾W4™ŸÛŒ_Ûžz®ß@Ä» S™ôúȉ{åØôè»IǧeÂ3@Jß@ª®pfÊ¥ŽÛ7oÞ„¯?åW™vüwü}Pâ:'™?抹(]x×ÿ®ÿê·ó‘nõ¿¦«ÿŸu=1 ã]R›“¹3z…ßð±Ylس­«þ9síŸý²ƒÅ {î_ŸÍ̧¡)õMª»*œ£«vÒô^¾I¨c•á»h­LALÊ\Š^@R䚸2©ã,qu9ÒóƠédª|xW¾dëS:ùžÔ{G¼82–?0BK6èÅ€3i>Á~6;ZŽÿ1êƒÊ¦\ ¾Ž sd8åÄÅÖ§N}PGæî ã5B“ð*+,¿4M“Þvò¹Ô5,ÄSnÒÔ¸ã~5@veS§ ÇÙå·}" ¿÷åj]M/¸’h¹#V×þç·ùèÔ©îJºß–þ^î»ÍßüœÏŽÿŽÿ®ÿëÃȵKÞ5¹ëÿûè»Õÿ«ÿ×þÿnûÿô'ÿöO_3ÖŽ–\¸®ÁeˆZqJ…‚, >ìP)‡®´òjÜïoy©g‡_i„îÙHï#]ÝÀK?)Ë{ç5r"ãÐLwê{ Ê6]^ŸÖ§ÒÚ^¼îíhûÐÈ ­þ¹—ÃÿË/¿üè‹/¾HŸ¶ÿ\ðûÍ—çÞ–Ëíø¶, fÇPÕÏUÖ{‘¾²Þehߦà{´…K;ÜϺõÁTö}Çÿy—qÇÿÌ‹]ÿ»þ«¿èÕÿǾÝuouxí]»úÿÝø²ýÿø¿þÏÿ>scª#¹1ð\A…tˆ·KcâˆË—f¢Õ`çÒõÐ÷hPzéÊO…zßÉJ¥×uÖ•·#7®`âG'^Ôºì*8x‡”c¯ðN°ß§ó»8»qøàÝöôR>ä'»2í3å¤+ <¡CÿO曆|}9H™lʽ}ó6|”k;É ®nV<<€¦6 ×΂¼{ytœ²=æuOŒ¼¥Kùá1 mË£ìÕ†ÿs ­_õÛŽÿ®ÿ]ÿ«ÿWÿ¯ý¯ÍümöÿéŸÿ›Ÿ¼fŒÆ”sTCi~4ø³WŸ ÆØçUC_#XÙ¥ÁË«8<˧Æ]:€®ÀæžWãß4† q åµÊð1˜<ÂÒ›§]@Ud™KñqC@ÉŸ:JÛz'1rÆŸ°zÉÁ‘ðBÛËòê®Qéòé|Ç£Êáí¤M•yuƒ8žmÂsú“WÃ.}2“îOê¿ùÒ„¹Ðޝ½d"{Û¨Ž‡úTuíø_ïkÓA;þ™?/»þwý¯þ_ýTãùu“OÖþÿNûŸŸÊa|³krð|3oÒj Ö'¶^ÌF \Âçaµ‰gc_@„®Æ)ã_ .ŸS_•º´¾è°Ç„h œ.àÖeðîþU*?ÊRRò€åÔa¨Gâ©käj~A”rê$s}ô꬯O æØÅ_Û9~Á‹xÚ5Ç¤Êø)<<€SGãè<é ·ïš&î©ìÊáW^ê•ß:нC{ÕƒnÇÿÌÿ]ÿ]g]÷õ­+k¬þ®šã¸Õÿ—þXýÛg Y+¢ýúÙ\rò ²A"ç7»TŽÏ({ç“#B äÕ®h”ŽE\pò8;Y×N®ÂâßóBôÞƒr¿Ä­î) ï¤ïöÈh_ðÃÛ'nï´ Ü›¸4rñ 2¼G Kû'y®|üÑË“.Œ¿òêÏ®ÙÕ6;Wv‹ÔžÂí1¨úôÑ/ùËʃþíúé£îü¡ @K;Ϥ; ßëž´ƒ<•¿m³s&Ó<òêk‡æÑþ Û³Ûñ?ócÇ?S$Ì¡]ÿ»þWÿ¯þ_ûÿ‡ÙÿÿËÿøoßO‘W»9@Ä<Œ # LxÄ™æ—ófò7s‡htò Dhåô¹s¤@vj` ¹ó–«>ŠMZõG–IÑÜà¾"äW†¢eñY^ò+v&¸¼bá:fTÇï§T@¥N½ÒÛêLŸ Aù‰s‘÷ª` øÔŽë"ûgŸ–÷g‘­®r‹«ãÞWåQúø€æuÜÙ>R¿vÀ oFQØ¢ £rþºúHÜñ?TßïøŸµß9Üù¾ë×?´úÿØÃÕÿkÿûŸ¬L–9^ã3Âüî1:â­Ý;J { uŒÒ”©`÷Ž|[]y¢ÁËS D‘{îqtâ,||9e0&œü«<ùìÉÇ/e†Gê»x°1;9ÃÏ®Që,Oqò’?íK§N<¹óΪ³L&»`äI\õ‹ø\y‘ùÂŽßyO×È´)¢ÞÈ9e¾¶[ziêã)("“r\óå)O~á!:4#¾2èÛ¾rÒ¯òßñàžžÝñ7/výïú_ý¿úí?[ÿûÛÿÜÁbGjt…)T®ÆÚ®ƒÝ4>…+M¹ã¡›Âbc5ڼ횈£÷4Y¼×}$4x¿ýzv_†?WÀÀWïÉG£LÓ&a Äi‡–´$gòíèD^ù7äÇËÎQ_G»|ÊL>¨+½2q²‘S™ºÖ£\vÒæÛ„ŽäÔIe³û¤þÙýëËHq¸;³|ð¾‡ï}¬ÎÓ†9*¼d(­<.|§NN^]eÞñßñ·nÌMëŽ3'8sMšy³ëÿè‹]ÿ«ÿWÿ¯ý§kÿŸ~ô׿xÍ3ª&ŸR­²à((¤°|Á‘€ñÕ›¯Xè(\`)†Êy?ÕgŸ}–21àCsœŸ ° ŠZ9;^_ý¯ƒ ú­õ‘,=þ¯,êçÚ´‰çï1 ä÷Ä Œ,@ á32(ãçb€°9üÒžKö´ãâÜz#û%GÂ剑xÒ'A=Ú¦MyY)ÙFŽö·<ÇŠ#ÀÙÁŸ+ßÊ&~£‰Ì“¥ÛçQ`xowv¯6–z…ûTžÿéÃkèØÿ]ÿÖÆ®ÿÕÿæÝy}8^ýÿaÛÿì`™ -Ãۉ˜րtW]Š#6.÷ƒfÆQÙ̦ìÆ(k‡H¹®û3õXxOÛ0@†)÷Ãþ0“?—Æ{ù•áL^éø4}Ij2'#ox_°Ççrõy­oH"Ò .”uÌ©BŠì„óü9UD®&¡ÉÎÔEý’>iæå«ÿá†~JÚQ0êΘ~Ñ×_Ý;e'1²5s|õyÓ«R’v#9ió]ËWîÿÿ]ÿçÃ…5±ëÿùhXxVÿ_Útõ:bíÿùµQ;j£¨ö?or4<ß%ÄÞ)t0þÞßÔûA¡-èºOçh/̘wÂy¦|ø/ ˆßŸTzýÁÿË_ÿ:@¦`‚ö´lé „Î·ñžåºCSº‰îÚ8ž<¯s8÷˜*_Üì½™Ý$?ØI^»JqÓ¨Ù¯xg×­mÂÈÖzB?ií»CN_yÁhÍäÝ]ANû½z3q‡Ð`¡‘_Z 2Hkâ[ ¬—:ÓˆIÊå¯>-ÐăKìøïøßæð®ÿ]ÿ«ÿWÿ¯ý?§ìæïkÿó[„ï_† F¾~;¿é7Æýó9êsäGÙöÞ‘Š„ï @>@Äð3Þåۭͬ‘^p$IŸ…)w@͹×ÁØ£åÊ`=К;oéÞ3U ÅýÐ àQÞÛX݃ҶÈ;|}–ÙÈ1ñÁ§õÉópvW[´sˆô탖㓿m'>­Ó‘ágŸ ¸6Ò•o]çøñâÓri£¾¸èÛÜÒ"Ë¡Âh<Æ×«,òM^wÝvüŸ¿-´ã¿ë×ÿêÿèRJ÷rÕÉ¢«ÿŸ7cj«×þÏFËþêç¯M™³óÂÕðPoæ¨Ng$ôí¼ì¦0Ì ä_ Þ û¸ó÷&ÁxèLØ–† …—üÖ-Œgë~óöÍãu˜=6u.O€(ˆyŒÉ¸¦²ÐQÆt yÄñ°8²Hçê'">ÿ(ä¤ãyшûQe®üùåÕ¶©°mÿ¡8œ:íLu¬¤ë mÊ„ O%™RädÍßÉïTFr•çŽÿ»ã£KõÏŽÿ®ÿ]ÿ«ÿWÿ¯ýgj³køuwûÿ °²‹2; ìàÄð 2< áÜpÜk²£tOW T/€C#ÏÐÏ£l“¸‡cð,usÊ¡è ò¤QzdSŸyŸ“,à†_ÛÜ ?¼Üort'_9Y¤7øµm U¶v ¸ü¦¹ÂL0•ðU62\è[¦a¾vh7¿íR¯ð½ÿÚž‡¼“Ï)ÇÄ‘ 0 ÀKú„®ö·^¼<ŽZ#ïŽÿŽÿ®ÿ]ÿôÑêÿÕÿc7ض¥¶‚Ï&­ýÿ=ì¿{®q׉Â7áûK4˜f´¥—–«éxᯤà‚MÀÌ ˆðL‰sŒ;w$LéxЧî.Ø`¬ÔK£N E\¸?ñóÒ}ªáÑ|u R5/_½Ìbò&?íª›ÒÑ’ÐÓ7ÒÈâÁOž€M{2Šj¾5)=Øñ¼Ê…nâP÷ö ]ûO{¹Êkâsú”ýt•]¸áÙݨÐÌEþþ,89ÛOúJùð˜ðÃMxÇÿÌ=}¢vüχƒû|1výïú¯Ž^ý¿úíÿ±ÿù±çTв´†<0èvC¤ÜI;» Òcü1F\逦P ­¸2,æsIŸ ç/?=Ǿä@¯N¾¦\XŸ²å-soÌOúøv¡4¦²?Œä%cÚ0u«? iÊãR:åœÔw);wä’ÎáAmûν.‰—,ÃøÚ!:;H}ã<þ!ËßóG]mƒýWÅ¥Žö§´|ÃðtÙ;eÔ}zácC+åÁ—\ó~ÚP׺K×øŽÿŽ¿u‘ub&ÍÜé<yÐÉ÷ ÂС @š´‡lÞÐ>quÔá¡,yRÇdè éâèåÇ O®rhoä¼èr&ßNÚÇÃ#}4}ëµûÀΩ‡g§Ç„\Ë+'sÜè°ñ´19Ïcˆ¾é©ç*‹¬é;þ‚wüwýïúö ™¾Ýñßõ¿ëõÿêÿµÿÿPûŸ÷`1À&Ñ}÷¦aÇH NŒÎmF¸zçèï*¦Æ]ò6diê`ð4ƒ €7îÔ?uL]£m9ï~ï·û·‚$`ÃoöS:€)ò^á\×¾yZ§zð³sQ`6•<äÓF¼Èæ:¾<ü++y¸È<>Ù¸óŽ­óN¯Ô}É#Oùqus襟˷¾öCùž¾>u´m´p:5ïøïø› »þwýÓ!Ñ#3Vÿ¯þ_ûÿûÛÿ§Ï,Æ·‹¨†™Ñ€yÝ"³;@1úw#®W£ýÅ_<”¿<ìˆq°tåÊCþYØнùêMâd x—®rýÓ—sá|йú @Uä¼ÀÉ ¬Ï®Üðâ(&Ý=.õ÷¥íå8ù\@Õ¤µ¤¡Íeúñ“Ó­_ù¹±SwDÇ$|ðjÝ脹¶7üFññûȇ´ëÆGÂ-½åÙzôµ0~ú`Çÿ€üÎïÿ]ÿ»þωÕÿcVÿÇVT?²µÝ|ñÝþç’{ ´ájhùJwO’9,®{gJ/ À €xünßÄ÷Ö¶/Ë4>á¥.LjÂgÊ‹;Æ*ÐS®2 ¯,|F#:…:ð“IÆ¡Sž­C=/¯«5åÛ& N9ih]hçÛÙr1:áÉÓ¦‚“ÔŸ*O¿«2’©ýF,r©ë':²¢myi‘cŽoû³8¥­ÌŽvÏ{¾OÎÑ(¹§Î-«¾>xråÃßñßñ7_:/Í®½ÎmiÇèvýïú_ý6'ºFº.ª¿­™ÕÿüöÿéÇó&w†´ί!o°pŸè{„&£TYnJZwe’–—÷öÍy¨ g÷ç†g•¸´|R€‚È7`dv½Èþ“'ÝN–Šì0gx÷¾ÙÀ†¼|s)h y¼'‹ï‘¦îúÚ ®Ä‡‡×/ ðÒ~øözÇTËé›8ũ3~å–×6:rì(éx(Cô“ðDòÕYyñ(:ô'§8i§áà«Áúgؾ“ïøG}xrøq;þgìø_ótæá®ÿ]ÿý`X½GwDGÎXýÿl7Vÿ¯ý!µ>þÅ\r‰a€‰1´þÁícQu1¡ß(—À«4dî/¹¿ èpè[¾eŒSÇ‘Aº]˜ÒÍg†ïdÉDÅÌG¼(˜ù¶VÞþ<ƨM]ô(¡Ô5rˆ;â¤å¹@%î‘Æ•WyØ!âÎ1ÞÙýŠ|Ë˱ٔ'_âÈ.o¼ÂoÒêËozýÃwÑ´í~7KzÚ†Él§®ýÜú¤·ÿ¥ÉOÚðáý͹û†à& ¨ÔÆ;/=¢}wYÓÿIÓ~cù·ïw¡oý)‹~ø3’•CÝÚ²ã憾ØñŸÙ²ë×ÿ¥s¢—.ÝL_¬þ¾n@WèŸÕÿÏ6›­áèÒùslÍ?rûŸ;X”bÜ4Jãªâ Çpß3øèMOv‚®NèŽvá3å|OÇU‘¸Çõ8¬ô‡ÇÈpñ GôÝJxdÉ`ˆp—\ýª=ùÜÁSØq¢c±È=²°•h.àÐöã¨<^/1q²ú"Šc€ 04€Eâ‰4;[É¿úÌ}-åÚ÷¶w·‰,ýîÓÌg¯ÎËVµ¿Ç”~ÚG¿âã>ؽ/Zyá£{´yú"}›ø 'aâêŠ,;þù¯?vügÆè‡™O»þwýWÏš«ÿÏ5ŒÕÿ³.ØXà²5t'ûãùPíÿyÖeX)Q;Œ°Åè4N:€bgHAës€@ÀÁ$Æ _k≣wù›ïµ Ò²Ô=e¤Ç¸_a¼i—|øäV ŒÏ¿z F`òÅe2è˜É??isŠ©C¹Ôq˜û“˜ôä_4¬.Z Ê=.m©¼Ú)ÞËÀ>¹};}Xq&[À×”¯ÃK=ú NXOs ªøk‹òí?“—ó6y»uÒýî"Ú¼žbèÓ¯_rµß3¦ÆxòRïø;þ ó¸klô£°ñÙñßõÿø µëß*™µá™?£;Vÿ¶úÿ̶éC·ÿ¹ä#’ubµ 1 G'X¡a„uX½rŒN ÏÐÊÏz›´,¸+¯q´@›× ¸÷ÄØ7ŸÏUž–‰?w¦ jä“랯>à€y”^üĹðŸ`òÑ XD xÈ##¹ø­]óðòn.Gr+#¶üʯLé-¶o¾p4|ÛN}ˆWvׯçÔåáô¶àƒVüä}Ç€¼xª«õ¡é4ûFdëÄWØÃZOš²\ó'ÃŽÿµó7ýÝ1Úñ?sNxÌsz×ÿùI×ã®ÿç¹Qý¹úõÿ‡bÿ¯iLJò2ÂD”§‹Ñ€Ëü»áXåëÅ7e˧iYX“n×XžŒ÷ú)|/§^å<€X_EPš‚Š‚|Ð6ŸEäõS:Oh¦.rØ ¸PÇRÔÐ44ÎÇŹG=ŽL×Åvaôüðžz•BùÚ|Ixyùêç.!õ9ÐUFtÞú> ü“†/ZmF¯­mw;ièÒÆp;²·Íù¢AåVËз Èwüwü3výïú_ýÿУtd_5$¼úÿØ•˜˜›-Ò7ßÕ–Ñþ¿ @Qž“$Ô¨?™<ó蘵MÙ±ó‚†f„O7Ã_#ÝNµs£s<ÒÉsÔøôñÙý¾ Ã)['œ£Äð?5H»Ótr+C²p¢îI?·½.çÛƒ×ÎÚòüú$x8r“/÷€F\»ä€vÃÈÀTù§ÑÝù ã”y´G~¨ÏŸÒG–ÁxŸ¾:¯~(¯ŽÛ]¾WV9:@ñÅÕÿglÁº>û^/}²ãÆsÇÿ€ú]ÿ»þWÿ¯þ_ûÿ·ÿO:ß"˜jT€ BïOuÎØîÉ·õ=jr'H>h$ h>ŒËâ‡f‚gcÔw“€‚Ò£få(TÈãÈÇnàþ×ý± Xø†·c½iWw«”ÁS^AIiS¿]¢qÂ¥«<è*4Ž<ŸÒ²Swñ–_úò/ªrœg"×éÃì üääK©þøx8iø¥•§õ|2 ²àÖµŽSåÙñßñïœÙõÿ¼“kýq]GÖž~òìú_ý_ýÙµ³úíÿûöÿéçÿñ/^û-?“£€Æ.¥‚’Î@KÓ…Œ¸¼)JˆÂq¶>êI4»9I›2R\(¢ðR¯îPuçÇD èúГ6đà =1×㓭»B.¡Šãÿ„Ãc¢²-&“!®^~ÊiÇ„ñz," ghõCä0+/_½ú+÷s†G±zÒwSFZÚDœK~àHÙÒédï@‚p²K¦÷Õ™]¨Éë˜(ÀK¦áƒoÓÐûÖaeûf^!Ì‘Q_&}ÇÇ×ÖÍ®ÿ³¯Vÿ¯þ_û6,r:6kâµÿO?ÿOñ𡤀’ad\ŒÁæ[l| Véî]ƒ8œ\Øà€uÇøÂ£yêR&õŒß£¶‚ÇnGo!ŸÝª‘“Œœt²Uw§#ðBÈp¨Ÿœ6“G~eGy†×I²O©ýƒmè'¬G.í¡ 0¾:Ñ3=³WyÛ—¼‘ -^šÂí'i&ùw¸Òÿ#[_мÛ)“6M¾]íöàJ?¨KymWÞ·}»ÑŽVÛ·ã?s9ýåÙñßõßõ±ëõõ‚¹°úÿ|@×{tY×ô¾úÐíÿÓ?ÿ7?yÍÐP€Ix:kâ™HÓyI¿ 7P<0þÀÁ;nÊèXåj.`“!8y¨Ý…É M¾rê ¤y¼×*;:*ºdrÄ(í^¿²€H?êã:Èc‡ Àø†Bñ·ÿ˜\m’‹Ç½â.®;~ÜOai¯æmêtd}GÐü´Ò2¾øk¾úÐÊø’[ß“A‡0áîÞG ªïÆÂGý•Û½+áöóŽÿ€ïÿ]ÿYeûÏ®ÿÕÿÕ÷fGõ(J7‹¯þ¿ÖÍØžöÕÚÿ7ÍYÝGýæËßd’x³: ÕIĈǸOÉx2¹¦tYCß]”‚y\@ÛLÀ)zÀ˜¸Oμð÷´>yás " $,ç­æÄШO9<”Ínؤ·|eÇ m¤»äŸ–¥éî]2Žû[1¼9Þ¼úД‡>x>ÿüóÔ­ï´#‡tG£@Þ@UÛž&Í=´ ð´”O¿ïg…Ú×Ò#£E}…-l Hòª Ç®ä.-?cÈ¿.ãë3Ž/mÇÇß¼Üõ¿ëõÿê¶¡¶4¶ã²©µ¡¬gmÒÚÿßnÿŸþäßþékʸë4ÆžÑæìŽ ÜIØË+¹^¢nÇP€åêܹšÊñÆ[N8®:шóñîÎTÊO½J¥…ÔUÀ1ÈÙ¹I[¤©GøÎ§¼rñ{Ê)£Þ<ÂÞÕ5—â9À0¯J[ð#³wi©CûZWøµ¾âÒ²äs9ž›pß[UÙ’7éÊ{ʳ`R¼õâåɘŸûU#S%^ÆÈæ†ø€âI'þ~é³ÿÿ]ÿ9bßõ¿úõÿÚöñjÿç”ê\žfhcp™ã çíä¿9Ø'[ ÇQ³ëaw§ÇoÙ•ñžœ1úÁbƒì <ÌØPRŽ«€üå§³C–S­SŸ´y á (Nì|K Ñ¼Æ Ä¾vt64ø…œ×@ @™:Ïô8¢ÀÆg2Gû㦬v ¡:KmÕüK¶nåÐ+ç¸Ïù­@ñÖGFá>M•á1à«¿•¨œ¶q-7èAÿ¾ë}3ô#Uv½€=´ÆEãÅÉÆn÷jvÚÈÝ,Q™ÿóÈ\Øõ¿ëÿÛÕÿ«ÿG¬ýÿ‡ÛÿüTN7 € Œ!NzÇèGñŽÁ~yG‰úâ¼€ágô»%JxL:° l Ë€‚‰óÑÕ'´Èؘtç]iñºóèÐc\/mŸÈÕ¦‰ô>—¶’S].»Y·zË|Ëòí¹hLM;¤+ÀTÞ~3²2MòÉ-|È|dÊkÉÒ;WÂÚkW r¥Œ€(?§£_¹ôáì*#L6a¼›ï§u*·¼¦ïø?ïtêçÿ™Y¾gýì»þÏ·‡wý¯þ_ý¿ö¿v4¶vì³/˜Õþ?ýdÞƒÅ2Û eP’1Œ{ ïµ ÂH»ôÃþ0é'5Ü1ÞS~2cüÝe’G!Ë{ðž°¸Ý ¡Ž‰GÿÚ%jž»Lêæ »Oøõ ÿiO \äGö¶‡¯œü´{ÚÊ)[p1™‘ƒˆLW9üÐ9}$Α¯G=ÇQ™È54ø ÿúË_§ïí~¦ÊI·ƒÀ ·úRXYNëÄ9w¶šÞ2|üÈW:iœôŽõŽÿŽÿ®ÿ]ÿtDuBõ%¥FïÐ!«ÿŸwúWÿŸÍ ö„݉ía‹&®oÖþûÿô³ÿð/_»ŸcNb¸Ä0ÄÓaûôÚ=ŒzñZçÚUa¬•EË&ä½]Û‹÷—}2î5öʽ~Ÿr™´—ñG×ÁS·£´Ð ¸r¬—ßÄk‰¹ü%ó„#í@¦yð*¿ÐNZËU/Þä¢ÇÎz»iIWh•Ã_Mß_w³„Û®a=¾ÒíšÙÝÂ3ý4Gxøê¿·oÎ7Ãð ®2£IçáI¯S‡“_çn–<íjûê7È›Ûñ?;‡;þ3Ofê˜Ë»þÎØõ¿úõÿÚÿÚÓ?Ôþ?ýl^4ZÎ÷n†€Ïù&ÝäùWp OýË/¿c²sSÃN9ÇØO ‚7ùåÁ¸›¸ò¹ø.È…²aŠÐPë7æÈ¨è&»mÊâ퉑¼dh½h„Ó†KuÖ ÞeÿÉÃKŸL!"¤lÂÞs•]ò—»=d”¦ÍNUYUvíkßóµqpÙ£])¨ìÈCn<ÐõØÐÎW‘ê½÷ÿŽÿé;sA?íø_ÏúÑ`@IDATŒfžìú?:¨kh×ÿõÍéÕÿ«ÿÇÅîŒíYû3ûΟ§ÿÕÏ_÷Ûh 3p¢ÃXiÆŸ‘”€ŠÅ.ÿ@0t€A ÷„;2œ²ž‚¦ð”>,FÌ.Ìí®`· ü=Œ\ Ý39õHw±»@‡ Ê\]äS:ñò«d”Ÿ¶\~vÄFfédÏ)m¬)rdÂoê«k‰?'C4‘¯ùø©/ýuN_àuÑúÝ@»Hœ6®X¦Œòóˆk‡4þýQN¾z<òR¿Œq‘aާ¼ô÷´ßÿsl»ã¿ë×ÿ꺒]¢OëèÒìÐM^]õ{âÏÉÞüèÞÕÿ–ýÿùúWsëy7 Ør4Èà›+9®»f’‰ÂQ>5à™‰#mL} ¶´‚yXÇpÙù,\÷ðTº„o~ÁCù©Ç·ßçüïà% aä´„åñO¹³C!ŒŸôÔ3>ÙÑJ?€1"=@ ººÏ¡å¤‡·–‘ž¶©GžÒðýU`-HuÁT) Ê‚><ëO^ÛrÏ»‡+':}ÇQ Ý8Àꀰÿÿε]ÿ»þWÿ¯þ¯ýZûÓù¶ÿO?ùë_¼Æ" "—ÇÏ7âÄ=v™\¸fÆšÑfÄ]@ŸÀàq JmÁ~€‚rÂ.WC!vl\\4r¡WŸ|áÏ^}vÞÓ3åÅ›¯ž —¸ûÍ(uÐ3àpŽÑqüÊì Ž,¾äá§ “†¦eÔ•üI/˜RR×…ÉÈP d;Užþûê7¿Iº{fòMêì*NòoÒêR÷)¿ò”Ü0™'^i³ø<ÊËKۦƕ“~¾<ðíŽÿŽÿ®ÿ]ÿ«ÿ£ãéD=»úíÿï²ÿO?oÆÂÎF—Á2L *ù1¶—aﮋ0 Ð§ÆûD¼¿v üõ«_ àaW« NÝ[~ Çä€ì’ã­‘Mc¹‚"á®I¿ . 2§®9vÅ âZÎ}²Öß¶´}ÊÙ±;ÿIqúïÞMK¦?#DZñÓ&ßÈüÁ~¾ÿõ¯PämìäEû¾«ÒµS}jØÈÖ|ò½ÿíLiv±¸„§ úºÿâõ‡9²ã>Péó¤s_|×ÿ®:„«Î‹.ºlÄC_µ´ú:jõtȇdÿŸþôßÿÙkÊ3¿Áw ¢Æš·€t‹ê®lå‹çhëx–rK³•ùl~™ï¢9?üoONÙ¼™|Âè8»êmâ™ú²_Ö*:šÏ»†øèãÿÿ¬Ç]ÿ×rÜõ¿úÿÌêZƒî]ýÿüe4}Òþ©]gþ±Úÿ¼hT£jL ª¡žYpŒüøµ¯1ÖâãÐ2Ä kÃø ÛaA%nwFDYNZ'—O?wg·É1?òà=åÔQùâ¯f' /N\ØŽŒúÝÅÊOÛ p"{ê9zÄ!˜`òCÉ×±œ²d³3U¾¤&ûtL8u\í áõ§m$»Gœ¯~áÊ[Þêê¥yõäµ.UÌòLYmäš—Èœ^MìJ:)ê{ÿ)ù9òà×¾•®2Oá‡Ü;þ;þæKç“°¹bî˜/ ›O»þwýÓBæÃêÿÕÿšýúñuɤ9aÎ1\.Š 3´ã’Ç`O¸J´ÀH²…NÙúôú(蔿@£ÍYtxB¨¹w¥ÜUž±Ç瀶Ê?ò¬lŽ¥á÷©ßJ?Lj×+ÈÚvá÷8NÐUùå\ù7aN9|ôü|*ùêFmš«žðºöeËU÷#!ºñ×nN{¹GÙáÍ@__Ï[ñ!zm—ïŸì\¤žõ“8jô'G®»/½õ–æ1~Cø¨Gù«<*ƒðŽÿY÷¾Üñ?GÓoµÕy¸ë?zÏZÜõ?_rZýÿÐÃlËêÿÜöÿqÉýnjx›=€ÈØUƒ#|ç)ð'̨عÀHùÇxr=†çÆ›qVV9çÒ=5P|÷°ú2êÎ(%áîxY ~¢§ß}o*‹LÚÅQ^MpxÎeù)Óz´14@Ä<€Œ]ùd‹üC N2> ¾W» F’?iz.<'Ì/¯d\*Gò†Æ»ÁÊ/`sØùö¥±ÑÏå£×øÅîQÇ=¿yü»\ K;þ;þ×¼…ÜwýïúޏtÍêÿÕÿlÒÚÿcãÙ^v³öšÿä=X5¨|‰5ÆÙ™ÀJ 3ã@“…æA+Æ„bœ•®ôîØË£Ã» «B~ÁMd¦ýá§°#wÎl'þb@Q½²m—80‡§]¯þÆ!šÒÝÃÀUÀã€;w°ðцö‡vw—Oùá¶M/é'|ËkÛøÀ܈ð:}t£Å·®2tMbúåÊŒlWXzó*OË"y¿¼:J¿ã?ý½ã¿ëŸŽÙõ½°úõÿÚÿßßþçMî *P@ÃðZHC+aà1‰I/­4a†ÙQ—rÒƒò-¸Â£<ù€Š) Ù‘á*Œ?z¾ûI|õ@LzÀÀÔ8ÍM@É}ª‰Ûûͼ_êPðÆÏcç˃g%Š—ü¦‘ `°åÛ6ò¦O‚*'Ð8íšzrÜyÕ×¶ëðu'¬rx¦' ϸ‹VÕ«,YðtòW&yê©ÜÚ0 IÜVsórçí¢U&}8tøxå'/<].mZ饕&ŒÏŽ¿ ;þæD׈¹±ëÿèº]ÿÏ:…ž1GÌÕÿGÁê‡[ýÿGaÿŸ~ú7þÚ Ö°2”œ¯ñ&Ã*o·Ê10a  ý܉²hЄnWþ|é¹@>þ·sgëÕËW)3D¡£ Ýÿ©{ð¹[Õ#Áð3 ‹<ÔqÏ1àËO_žŸöy î<Nà ð‰lÓ1xS§~°óƒ1m÷ H2ˆ“ûôÛ30Ã'í^Âa¼Û[òÑ—'¿´|4þ„É#¬ÏV¾|K×6é£gŒYiAuå9íØñßñßõ?+.:e×TFtÎêÿs÷uõÿÚÿÚêßfÿŸþó“×IB5îŒmÁ ekP lð=1Fc¬l/·¤¸úÜ㺌y'󀓡ˮŠüáW@Ìõ{ܯ Zù­›,â‘ÐQÿÀ‚a´8ôÒ<êl[ȉr0ÁLSÿ´ë%te PlLvø]?¥|Ò¡š´EßM;ìVåÛCÛ6¼½vÈ´Ñ(´Ï䧇¶ýÐöâJG¯ÒÞËÒ²–—rzazw¹ô™ëš¯,zòówüÏ<Ýñßõo­ìú_ý×™«ÿ×þëïCÙåØÿŸüû_¼¶óSƒ*«F6†xŒ+#lG‹áFp-â€@ ½°´ñ㎱ÆÏÝ©‚¥Ôéz”k}\S°õµqe¿üòË>ÿüóì"M¡”sd&Ÿ¬¥ðš´—³Óƒ·|²>h€‰@œ}â ñøM]S,e6¦|eЮ€´ñO†PöèÜIo¿@vù î´[;ÜSy’€+¯®»—H‘‡;GŒ‡V.'ýþ"Qtêkÿ†·>oûvüuÑœïøŸ5Õùb~îúŸ»þWÿϨýZý¿öŸ½ÿmöÿüáRpÅZ'Øa.@ñ#ÊP;ƒŽÞS`Upc…+yuøMÁ€’‡É+/¾ lGÌËÁ•YÝ©ÏO˼yä¹äþPA;a2(Ûv×Q <€¢² HGÏ„tiŸÞÃK9 ˆß…¥,'«ì‰OQmÞ\ŽÏÏß ?yÒôzôkÚJÎK4•…œåŸ:kŽžÊ©k”E—öNXþ$fŒHõqïónÑ)_¾•½4íÜñßñ7Ì/ói×ÿßþ‚ˆuÓuhMîú¿¾©MW]¬ïº¬:jº*ºK^û¿úÿœ^Üû,×Z¦?õÝêÿÿÿÛÿÿËÿøoßw‰Aí6°vHrq|&<#kPk¬ÑP¸½PþÅ_ämë¾ç­ëw^Â5îÂ}+º4õdM:P#¿i%vx¦>N¹~õ¡ûåÿóËütÊÍý¸ÒŽ×݈©'ŸÐ‡§ÇgúD^Â׎€5‰©Ë?í˜c¶ëG§¥…ßÈBi¯ oyê­‘Š‚™týÉ`õøIÛÚ¯Êx­Þßø£'—x}ùÚÈÉ–ï§¾›/ìøŸ‹úúgÇÿ¬?}a>íú·3~v´wý¯þŸEÝI§®þ_ûïËw¿Íþg+ŠãR¨>5˜D&§;85Ìô|ìxÞÝ$î\¼ÿ,(ë‚ å)î:lʳyÙ!:e<êîN](õàÄ9ôÛ}vˆ\jÇ#è¾™8qåb¦ §vi>ž.šwä¼@9€å¹â‡ç¼$tÚ9ç[Œ|qŽ,~Àz.@gÒãO½>{3m!‹¸Ý¹þN"‘‘’Ç@]7Y%¥ß&wF,åK'=ùÃ3a}2ÿ ¨Nî”'ó8ã²ãÍŸôÈ(ÿÌ)ëÜ5:—LHóÕ¼1Gåïúßõï¸ùpwÑ‹“`î¬þ_ýß¹ÁU§tnü1Ùÿ§ýõü!Ó\c¬å”èx] £ï8X°XlùÖµ,ú(Üñ‡€Ò¾/8`Ã}Ͻ¬pãå]ì,Pò€^ñ'<äŠ F†îh˜3F`øFžÉóÏ])ÎŽFFü ¬{Q\AQåÁ×#^Cƒîž.ÎIà ºíKLÉÚÉõj@á¼ U¹êäëøîžI~´ïÀ³mn¯õ¶]]ä ÎøŒ¬ÙÅ›]3|{q-~ÙÅ›#ÇüÚÔ—?;þ;þg›æé®ÿ]ÿ«ÿWÿÓ‹lÎÚÿc/k‡‹èKiûÿãù±g‰us÷hJ¨S)YOïˆLÒjŽÑîq!>@ÑXõëUVCSP!.œ¼9–ãRÿ¤Up<Õ©9>½Ê±ÖwG–‰«ƒ,Žò^ÎëðrNû#>QøŒ/þÉäP©ø«h‰?ùh#Ó¤qd”'-}2¾v—MÓù¸úÐŽŒÞÉ•t<&\Öiƒ#@Ž#¸ò&»'|ë!›Àtˆ6Fæ‰÷‚=:idF~?RŒð¯uTÞ$ÌŸ”:Nž‰²ã¿ã¿ë×ÿêÿÕÿkÿÇ&þö¾Eøg¯RFWAŽ‘íÄhOºðXÝ*€®„Wv„³¡Ç?F~vvøŽgÂ-M®:”-Én̪ ²^€*G…Øë¤Ü”/ L˜ÎLñ Q÷ÔEf}üË|·>ñé\ŠŸ¥ÃS[Ú‡xvg.@èG×ÁZìNá#Xʧƒ Gw£&Ï(Þï´çz'Ö$RèÜ¥Ò eñ+ˆ–ÉØñö*+ÚöAóñS¾Œ‘š„§ðŽÿŽæ”ɳë×?=Bw­þŸ£'WÿŸùÀ–°ì ÛÁmú€ìV) ¢ ´ NF®ŽÒgEüÊR²^…ॡ>åY|yxpø ÇH+; yì–ejÃ.MÙL\<*«´Ò#ƒ7ƒ˜ÀMžz ˜òÉëfÒ¸îðàAQðs¯kÚDÞȵ±eÔ‹‡¾mì$ xºä×§þE¾Ië¥auM²û†oâûYv²ô»O 褿ß^iÃx幨._™€7 HZA,y»S§>y?ÏŽÿŽÿ®ÿ]ÿtÎ8z-z{t ßíþ_ýŸyÀÎŒíXû0ÛkÜíVVMìetÏB:à‘·{Ô£º\À£®s1,ðp©üÕgóΩù€È+0âÿ {ƒ¹Œš<.Oe-gqŽßp®?€DøŒ?&UÙîº$aX©÷·ä“¯À jœ|ʺo@&eÐIWŽ ÿ‰Ë&WÛ%M¼m³›†·üæuçÊ@ä÷åÏÓöñµÚÄ-Mý“Vzß3eÚ_©kâhãðó4>‰‰OÚÕæ–kÇŽÿŽÿ®ÿ]ÿ«ÿWÿ³kÿÏ&ûú»ì~*‡Af¬»›Ãè*èÁäý,Æ™Âå1èG 40Ê ¿òøJ¯0 “Þ:ñàê'rÅ¥5½¾üÊ–°?C—·®«O_Ìû¹¦>qËÁ®š€WHw  º;üÈÌç´·ŸÒ Õ°1|9`¥mG ©£ró˳éúgÓ?/ß_Çh‚~ÇÇK~ûóð¢ä§nõû;ÿ•á’Ÿô³;˜ü‰;ŽEØ]ÁÈFÆ«ñŽÅŽÿŽÿL–¸®1ók×ÿY_»þÏú 3Vÿ¯þ7Öþûû÷Ùÿ¬³lŽbu¤åxªÙN‰Ý&Ÿ^8Š—Avɽ!q»0\ŒùÅ }B¿µV=)< ÇÐ&å9O´ÊÿÈv€žôƒ%9–øØ…’À†æó/>Ï›àïÀI{ª<ñðHSt´¹„¨L/ofÇ?u í?âd©Œ/烓•2x¢÷£Ôê@#ŒRGy©O¾ºu©o<&~Ƀ= $}¥[ËW¾ú8½ZYã_iòB/p¹ÿÿ]ÿ»þWÿ¯þg+ÖþÿïÙÿüáÃO‡ÆëÖëçXž€«1î5ôv[¼FÀ]'à‚Í@C‹.å ½ëS0ÁŽã-îA{êœ áz.{ŸxÃwè‡Ïû)Ûev2…ÿ¤÷}RäHÙy¼ŸÛ!¿úäeg Ïqú£Gohyk<™Ë/mzõ‘¿2µOÉÒ~ sü¯w+ÝëUxL¾t’´ ”©§`*´CAFõ(§\ú3¡òðJÙÉ/}g·JàUYÃ#lvüwüÏ©]ÿGìú?ôVÿ¯þ_ûÿûÛÿ'¯i`€k„íƒôE” cnÇ"ãÎvÍ0{Cº]ò€˜Ioœ­OÚÌ”gè=÷ðÝø_ø ^ƒ|áÆá€°FÈKVm°CÆòŌܡß[çÉõÈÞ>µ‰ŸÓÞ‰»ƒÕ6†~r+we©l){ÉY¾•¹y 7ô<ýä7]=œ2òÑJ’ì äXQ;%ŽãN•ßt~꿟L¥Õ¡õàáߎ¿°ão>žyµëŸŽÛõíîÒ‘£“VÿÝK·fè—[˜~N¾>y«ÿ?,ûÿôc?öã<ŸX¯×˜ nÁˆ£À¼4s”ŒtGd ?…c'Hy´â&hàLÈSÎ_¼àΛøßJ»ç#šÜµºMìðYì’E!^ÞΠDNaÀ© +—¹‹jÛÈëWvªð¹ä!|;RƒAtð÷"Ñ#ÊgÂèšFÆö^y&?íçºã&L~å=•H4Ò!G‰z«²UV~û¨œJKšô>'ñ¤d;þÓç;þg®˜»þwýÓ%«ÿŸuìêÿµÿˆýúÓyV úûñ f„-2Ç\ŒƒÃΖ.‚Þ±¡×ØñN””<ßç' Òû´.y@Ã|ˆGÞä30$7C ÍMùJ ÔµPÊ?cd©è*à¹aõ5½wÖü€¡Ö7>°'¯}B~ßF ¡vÆïqfîµ o—îÕNYý̵ž¶Hü~ Uº1ééÓIkù+;}r/‡—~¾xvתòßéÑíøïøïú?÷N».wý¯þ؛ѣ«ÿ×þ×~ÆÏœxúÑ_þìu€ÈQ™ k€pïZ) îN“0p€ž+ ê(ã*¢úòRv€DòŒ 89øymÂ|ûÍŽZê˜zRÓå·ÞaPbû^¾mkŽ<À8ø™W×[Þ¥¿|yÀ >>‘ðBõ ÛÝ 0›pÜø•¿Ò9† ðRnÓSò›¯Ïî]ÚxñÀ ÙÚ_úÂÓ¼©<}üZ¾]È©Úb·¯ôá¡Ï†_ÆlÂ|éê"Nüª‹LÝÕ’Þvá+^æ„wü§#ný´ã¿ë×ÿêºrõÿ±µgkÿφÎÝþ?ýÙþׯQ†hr¡]‡1½¯S 1é‰_X¸ ƒQ®¡æ{š†®ix÷QÓù z¶`SÊõó~*éêY[GÓ}£/÷ÀÈ}ñ±Ûä˜öä(rÂÊâÛ+ùbãWôÞö®NN»¾>¼ìÔáá‰i)?a»f:ŸôéȦ¬zm`•“ÇáÓ0¹¸”^i«ox-¨üCÑO¸²òñÑóGú°y'?¼®2wÃÇÇ×ÿÑQÖÜ®ÿÕÿÕ©«ÿŸï ³-ìÛÂŽ¯ýÿûíÿÓÿú¯™`Uƒ/ž`Ó‰ãS<~ŽæH¦³å{¸‚ €-? ÜŒˆü™´ €+Á`™Ì&292ˆ×}0áCÀºÖW¹.6¡S_Ê 9€CQ*ß:X¦eµÃ*ࢼðV^[È¢îõ©K:>y„AwZ>þð.ÂxÒkúi›²©‹aÃS?-Í}\¯>æ§ÿ\ÞbªŒ§.ñ+’¾ø;hd§®áË©ÇÿÌåÿ]ÿ»þ?{èÄêÆèŸÕÿ«ÿÙu6ì²MÂÜÚÿ¿Óþ@Ü@!:KØ.‰…ÅKã3ÂÝAb„„åpÍŽNA Sï…žhìô:'Ú<ÁŸáð°{¥[¯-£Þ»S¯8 ßÅh\È'‹ˆ£?ÏH»ì\)kG*|B?`ex8l[õCëw̨îó>¬ùáé«o `ìnqè=•1}6m:€)×(?…s.Ñæw'+}:´H˜üMÃOÿxa*×,2£¹?É¿ú·ò¤ÐõçN«Mâ;þ;þ»þwýÓ«ÿŸ¯N¬þ_ûÏlþCí^4Zãp3à€ Ä ¤Õ˜3ÀÙ PÒt4?‘»aǯ»[õ Q€‡rèùòù¾í§éÒ*¹È$­/…¦¥SÀµÇQÏKÙñ?si×ÿ®kaõÿÑ «ÿ>Xû?o÷wÙÿ¼‹ávôǸ2Þ,cØcXfA™H£Ë1ÌvŠäôŒBÃɳ¿îQÀ]^‚“¦.´œÝ*¯F2jüñ&G_ƒ >>çO¹Êí W°%¬]•¬ù¶Ü\TWV™‚ w¥"»¶M;b®öàƒ*h2©ðPÞã MZy+×mÓ¶«;wèO™³c…V9mô҉ܤ©WýúÈ87µMö3 ’ÖºÂÍÕÖ¦××^2ìø€Ýñϼ1¯Ì süñìúßõO¯¬þ_ýoD7ŒO7¬ýÿíöÿÆ•{5> `1ÀŽÒÒ“Æ—¦c9q.ñ À8ÚãüÍ>O™òÀ»/ޝ, boú§óM¿¼àíä»—ÁNÊ䣶ÓÐ÷#Hu“ p!³rxi»¸6ß‹°4yiãÕ6ßeÀqê(}ÛGûO`+wÄ®¾h¿µNùsü‰>2O~ºDÿ¨û€¬Ó&åÆ:ùž÷]ÓñV®uîøïø›/»þŸ?°ìú_ý¿úíí9ýÈ^rì§tNÚï²ÿO?ûñzJåŒÑ¤€;G­ þܥⷢæ)+MÅÊ —®´|â1ý¡›8‡Èp]Y®@² ‘æá¤À(ûP†4ì\ɻˣü×ßÌ· 'ÿÕ\X×FòPå·”Å%v™¦ÐôÃáËu䤾)kGÐý©ôÅÐ’=´×±j˧þ«¯ÐôQwË’ òäAÓr÷±’&ã+¯Œ×Bp)3éÊ„÷„wügΦ¯vü3—fžÜçÔ®ÿs”¸ë´éêÿÕÿ£+ÇäaOî®6)¶eòÄ?4ûŸKî v€Ä†éÑáÕ8þíuVžÖÕz½f‚C˵üÄD?ŸN®Ì´¿´cÇ?ݲã¾`²ë×ÿêÿcÛªoWÿ¯ýÿCìÿÓOæ·¡ÊpFßS#΀ûÔ*nrÅ`j:ð"¯†^¾Éhǽ#(yå+Ì€©Ó^ÊNòüò£ä#ÏU¸ê½)»Yà1ù){í&©ÛnLä¾øG®©ðRæ»9ÊóÕJ<]¨ÿõ—¿ÎëRö’ÇòŽ8;?åI¾ºÔ?u<ÚÞŒË'ƒ{XúD]€6ewíF‹gøâu¥÷þÞ\ë峯Þ|•#@üÄŠ`èÕ›û[SÇòÀGß«Ÿÿÿ]ÿ»þé1z$úvt]B?¬þ_ý;:s a‰:/ÖþŸÍŒôËôM1Ë=ýâ?ÿ«×.™ë°,¨YX¹od C<$ rAZÿ”«a/IÞäã ‰ uøXÔUîõÀ`ʈ\õH÷Í^¶Iޝæe¦ïÔ?ôê›Êr¿?å[7ŸSVº;H¾h=\A ^À˜Itwm ‡VûRÏ좩£€Kòy¸¶»wÂÈyïÏ]N¿ëúÓwxrx¥Ïæ§€ÎÐL¯Ÿ¶Me@§<§Ò¹È#y¢/_ÍÏíøïøÏ¼2WÓ]ÿçÈ×?3ŠbæEt }ré!seõÿê¶„Ý<óálF$<ócíÿôÇ¿øw?{ÍðpÌâ6t¸»Ç2ga¡sÔ¤C m‡¦UÆB,˜à7\p2xÌÓ4>º Å<¼¤åèod€lWÿÓúOã¿pÞE'\<[9â&kzùj2€“¶h+G¡þò—¿Œo§)çÅ/ôú#2Møî·?”W~ü”™þäô«42œ>ü¾I‘eòúÍMéø·o2¥]}U¾ä#gËI0¥Hõj¯°4|+[dp¥üŽÿŽ¿ù¶ë×?±úõÿÚÿùR߬.6wlôÝîKÿ­öÿ§sɽ…ëìÈŒ)êÊ(þ«9BËÏÒ ó(ä!VäÄ0Þ1ó#þ½§õäÕÉ=`Cà |ÜÎÏÉLX9²!êS/¾h<¹À=i‘ëªt|ɧ°òq“×oÓy÷Ö«—¯r¬‰V¹<—,êR¾m,¸Ñ: 4uú÷Î+¦ûk,  \eà@4¥Ûñßñ7÷výïú_ýÞ¸úímæÿŽýŸ#Ÿ¾fh1óÉäîÞ7Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×?øâµ‘£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃ‡hÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_¿=wªÐ{ï”c,´@38ø \ÞÉsÉE´\Ë5®lDåB'œvÏEo»m:—¾•}óöùçÄå‘—S®ŸøXÔþÜ2¡¦L^Ñ>Õ†¤>îo-öŽ”4í¶8à øSãö¨wÒô«º¥kKÚéNÜäIç§Ýã‡ïå‡Ç옃Ê.mÇÇßœ0W,sç±^&ë¸uÞÐ+«ÿ¯5µúÿè–é‡Åþ?ýùÿý¾¦P_Ì·Òz7‡¶VY0%;ihν¡sìe1鸸ÉkØ7Õ”HÐ0êv}òÀ%´9^ºÇq /ÍÑY"âó¥Ç“â‘sèêÄF‚Ì£ü2J;¾|™Èâ‡~”‰Ú â(ÌÀJº2•³;FhË“¼ );Rk³r¥kyÇ…Ýá“_ õÜšù¸é'm"ßW_Í+nF/m¦êéN ~x¡GË'Ú¶EˆT&FÿÿÿëèÜ<íÜÞõ?ïßÛõ¿úõ?uûB'ÐkÿÏæÊßgÿç5 ÿúuŒûe„kÀ«`hùÒët®ÿ“AÿÊl9~Ãhcð‡Þ€ÄÀ(() è XßP±S0¸‘Ásç:È0Îß6ô!3QÉ)ÿ’ M]ˆ]'Ç~híiWå 'od:œ#¼+_ÛØzÑ4¬œ°GyïáºË#¿m,ë _=åÒ~e¦¯Ü!˜éÂïÕ©<@Õ{m•¥m/ßÖE¦ºÿÿ]ÿ»þG‰­þ¥¸úÿØWö¡vƒßð‡lÿó&w;œ#·ÏĨñtØtœ…ÅàCüîQ£S/¥ ™;Y@ `àðI|~ÚÆq!ôv\&¬L×Ð’‰¬|CÙê“oœz»#u—©á†­#ºaYÈSÔãÛÜÙ}°E&|rD8räÈr!Ohæˆÿ#ßô裯ÿHÆ©G_¢VÆ“ú‡¯vë<Õ†öâ­Œ/¤ý#|À‰3¦§9©<úÈ94èvü§ßwüwýïú_ý?:uõLHú½àjc&°öÿ²¡¿ý„p&UŒLb'.X ÀØ_ŽçÇŽ™þžøøâ~ø@ô÷²à‰P€0ðåüDÍ_|q þ—ÉCww8(ŒoÇ廩  ñÚ†|[±2SG'y¦mC‡ì™÷sè€íV”Kx neF“Ü P’¢œ9ŠÄ3Ÿff/ŒÚ“oFNé'mÁ“œœvµoÜÕB Mm‡:.9êð&žì‘ï׿š·ÑÏ[éÄ´œzÚa´Žm¶Üc†òwüwü;·îóÅ\Úõ¿ëõÿêÿµÿ˜ýúùü‹×W #üP°cx)X¾N<p5ùh“ uŒ¹4ÁÑCΩ‡¢ö¨ @)¨úü³ó#Îè¢Ì§¼¼ ‰ï»A3xƒ«Œ"•_ · üÐMùðàJ½ ðt8 æ‡?üáGÿëý¯¼èT»”»óSËù¹S5üòK÷^6aŽÂIò¹×¾ÅÛ{®ðh;Sç¹€¢é»l2_ž‡Ó¯ÎPÍeÒ^‘qê-ÀÈǵ¼pû,€yøµ­ò*cîðD›|m (îÙñßñßõ¿ëõÿêvƒùàìÿOþú¯5œAd` XV®Ç[³{źƒ=÷£jl"Æí~Ûa€`— XøÙ»—eË’ã<Ð(œªÌªÀÇik‘@áFŠb?‡Œ R{¦A›å@ƒ~A™õcÐÐ@Ue]€öïõï³2‰KêˆôÈ\'n7÷GÄ^[ôŽ ²Ôã<~ë*ìÌLƃ?ù 6ÔåQ.e/¿åkàËW9aùm£°6‘£à O®uµMè¸ï~÷»Ùɸ´‰ï5 ÝU–ð÷àkGJŸô¯>ÐGã¤ËÀÒiãìr¡#kËèFêä{·×ùýEõrÀU™rÞË¥LÆì’§;]ò9y•¥u‘©}¸ãÀQç‰>Ûñßõo­ïú_ý¿ú>L¯ýÿ½öÿé‡ócÏ :Ã^ã 1ÜÓ/\#Ì00w¥ã‚úòÐñ•4ޱœ^Ä3àC`œº ~ijc2ivƒ |ðÏ=§É/@¸×OîÊPƒ(ÎEþ‘Iúõòí%á©^eR×䵞– ¹d¥`+7z»]š‚àEûÅå—/Àª¬>íë ô>AÃÉ×oÚï]2¶eïrH#¼rxkÿƒìÀÙ¶ÒÓ¾©¿üZ^Âo?ÒñávüwüwýŸ"]7»þχDý°úõÿÝþÖ¦˜kÿÏ&EíÿÓ÷ÿîǯtE ;6"Ü€Iã„u¦'Àa~Ž…1¯aæ‡C}¥Ÿ£ª³#£~q©-†|xòü«Ø•ç*•çоüðeâÂU„ˆú‡I ¿¶-¯?M ?mŸ6ᣠòÊSØÄ¹·Qž>ΠyñÁ‹ì¼á阱u¤_®~C/Ý#}z3~ÂCó(sÑhKû\}x7ÎWÐ’.? jÊR‚ät øê6½úÑÊ3Æ·^y;þ;þ»þŸwÈwý?ëÜêzÂÏqQ~tÇ—žñÕÿϺ\¿¬þ?vï³ÿOq¬•æ[$Óé‡!ÜÆÏ¥ó¡íÂjYº Ng‚åÕ =fyÙ…ß·ßÔëN‘Ý.<ëjüÉÔt´Þ95R& ÐÀÉz²GY—“Fþ‡›8Z¼Ë¿4ŽÚìI§h¥ ·º;U™ÕM޶íQÏÔç‰î-E¾‰ûÇE!/ÿ¥ÉWOÓZß)CÚg…†Fß Q¾2J÷Eò¸Ôžc×)WƒQžèÈ+_~å·ã¿ã›÷æÎ®ÿÛÏz]zÁÚÙõ¿úõÿ±Oú{WíÿÓŸÏOå >±2À5¾:å˜q›;æÁGLÒŽ«1®ß¼Ò :[~ ø”Á/ßÈ¥d‹3ù6ÛÐy³ø}wFY<ðÄ>ò¤7-Ì& #Ÿã'Mú<“t~Û{žËàÿ6èÑWÒõÛK/Rã8à0oC@Fn€Vy 9¦"iKídšJ ÒR?š¹ôÞöI#o.§‡àôŸ:ÉÝ¿¶­úí`áa—Ð;·TDööºÿéÀÿ]ÿ׺ª×µ´ë”Æü×ÝÅE&tôš|}Æo^iWÿŸ>\ýÿnÙÿì`Y#ˆ`lûª.’.,4Òº„›VßxÆ›«ÎB+š½ó=é³?ÿÔÏYŒŽÜúâL4ø· ,t“^Þ‰ÏÂ*ÂèñA €´<:¼¼aoç‹«·ü*³ôÊFóÇ]*È)½>ê1‹2œ*4í¿îÖé§¶#´¡?eR×Äs풯ʓöM¾rúå”:ÊPy&3Ç~âî¶\áS—¼ÿvGúsÇßìz6¬æˆy×ù+Ü´ú»þþÙõ¿úõÿÁµmï¨ý>Šóõÿ³#ó2~ %{Tí9^ê{ (Õ*V4À@/v‹sw0‚7ƒ¯ŒKÜ|ˆàõç¯êc}4ߎK]óç;ßùNAÀDhуbGéç³£E™q “cCåÑà4hŸFÿâ›úCqþ4^¿gÿiC¢;HÝݺ·§õÛíâÜåf4*këw Ú×N|u]fßá/2TÁô\øeˆÐà]zñ,¶ñ9éw×vV~}ÍÙÑŠÅ™?èKPÑ#Ãä]åFå)KºoAϰ¡«lêA˵]w9\ø%? w¨¦3‰}íxUvuð 'O_ÓÐ6Hk8ªSÛÇ¿ËðkõÍÓv mû¤G>‰#wËñåqóñŸÞ³k9ÿÿLŒ³~Np×?ÝÄu íú¿ôÉõ)võÿ{ù½ºúÿ§µÿoÚÿ÷©T»-þÅ 3ºãj°~t àì§á¸+¯J Ð>€â¹¢•$4 Œä[n/fâÎñ\° LJ—ó§2òëÔu€NSFÜ+x*Êh%úcDi;s§jJæîÒ”J²dçkêAKf®@íW—,ä@+½òå>âÉãš.Ü~à'W;æ)áºG¹[»ïyÍçãçé§iyA$~Wz,½&¾ãŸþÚñ?˼2gº.:7;ßvýïú¯¾Éœ¸ôTõÕêÿÕÿæ‚9bCC˜Îà¤Õî%ÿOÑþwqt!°î€HÓÓ×iö@ì tÉŠy 5…Þ(×Τœ9ïÞÛè |uºÎîñ[Ží®Á‡b7@\ëŽ<3(Þeõ«¯ž¿ÑˆFž§/+Í Nùî(•O¸<å“7¼Ç—ßo=VÆ¡ ƒÊšíÙÁ˧»¡à´)õ¯º\H¿dlÝõ'¯ÇxÊ4¯Î6¼ü´,ã£óŸÓq2zêz t;þéٌӎÿ®ÿ]ÿoêz#}2þꛫÿÍ níÿ¹*?Ä®†˜¾yŸ1al͘ñtÚe΢júÃKOîü™òÂóÓÌñÑx ¦Âÿ2îÒÅ=E±„’^ \Tú·ë—^ç/uÒ›W~¾¨¾:éw~À^ù¤Û¹p½ï‰"_xÍ¥üÊÚ:ø_€ðÚ®æ©ÑN—²yí…~úÉ·36=ò†LåñõäOÂç'ÿü{Oú¸‚,õ„ßÐ s“­iú]|jN?£Ûñ?ǼúhÇߌxÖæPçNç¥ÙõX™K»þwý¯þ^¥«Ç­þ?›)ú„Í«Ýë:yWìÞËÀØúŸ Ba^“$3eþTÁòûÈ‹òΛ‚!ͮȯÏËW}¯;ZÀ¥lJ™v®$ö^(ùÃ84ø Žm˜:&½õHÚÊ›,eÀÓ5@ ­]'O_ŸÐ6·žÊVkóþ­HzúD½á3`-o¶žølc%­Æ)e§¼K±Ú[žo·÷ôæƒù1lÃDù»kyéí¾>*­º¹æKWnÇÿƒôÃŽÿ¬Ïkž™rþvnñûÈÉüÙõ?ýpôTûd׿ÝÑË«ÿWÿ³q—m'íÿ÷¯{>ªô iU¨õï` †»†¼ êÄ B¯c“ ÷ÎÓã(nÌ;Þ”OÊØ!RðnÝÙá†~ðCèÉj •óp•¹~ùv‡¬éü¾4_3cFŽÑ•WùÓžkx5ÂùƒÇÏD€: N½“™²­Ÿ{9õ>.Ó2^‡a.Í]]r¡SŽ\¿Í¥½W¹StÉG2yðàש»ý'­rÖoyøsè¹ÿÿ̹̇]ÿÖÅ®ÿÕÿtæêÿwÓþ?ÿ¡£ªK1š%CìþãZC*­Æ6iÿr@ˆ;<¥Q–éE 9Ãÿ¬ñ!4ÙeB=a2ZGv—ÆxÛéQ W@&\yéâêF«LÝ£MWš²ióÅC¸?%S ¡ ײüÊ&]ûìÂÝÓð!Ç̤kC¾ÍxñÒ¿]ùS(åÔåÁÏ3Räâ?žÓC4xq凾}-ý«kíÅ/¥CdºêrT9uàÜþÜñÞÍÕ¯úƒëÿ]ÿ»þWÿßuÂêÿµÿµÿOŸüÃ_¾b4ÛÜ1Þ5»ÐAßÞ¸î¾Ow òuLù3 4qüL2~^¹0<Áñ:FœŒÖd$¿yügPá“0 w^W ŸNè{X€ ùd­­»åÂß+$†Xíä‘P6éâqénêx¼ uÂ@Šoåiuf7GûK;áןž0@ëÅ‹"heÇSLE©«2ò+whn²[4|•y£ C£\ÛÍ×ròñó¯m*hØñßñÏô2Ÿnn×ÿ®º}õÿùàni¬þû>öŽmYûÿ»íÿÓ~öÓW1º7ÿˆÏdºŸ›\M§Zph ¶ªp.ßp£¨çaÈù5ôÊ •^'Pn´rðWÖSÚ˜?óñä{\0oZa®|òÊ‚‹Fz@È츽?÷à HÐrøZ\Pc×®uW\ùßÛ%]˜áãÛü¶¥å*×Û~xßø‹sÊùÇEΉë?¬¼å‘Ï.Õd=d”OŽðÐ/·¾­<;þg¾êC}µã¿ë×ÿêÿÕÿkÿ¿‰ýÏa.¶Ža˜‘>Æ„‘eT¤ÕXKË¥5 „q¾ŒwACèñ™|®å•s¿©†?;W¡8À uñïÄÇÇ¿»H¥í®6ÒȈÎÓ´úi×E‡ €È÷MC “—O~w¯ÜÁº·ý^:GD^ÊzF˜Óð™Ô×#<ùÞñ%ãߟ“˜¿IW_ë¿óŸÄ¤·>Gš“2ý{|ZûZßWÎÖÞ#i”Á ÿ.ƒ´ÿ3Çvüwýïú?Þ¬…ê§è‘‰sÕôÆêÿÓ«ÿŸßïhŽÜí[ìÒŸýßÂH£ÆŽ}=îò¥[ Ýa¨u#ÍÙÝøzâhä¡—o!qâø?êHê1äÒð­ñ/=^‘ç*/ß·Ñv ø .©ghšFüÐŒï}ZÂêãðç”ñõëÏÛ½ÈÅt€ €˜÷W¤ÒKÏÇ?|<_¼~¾OF¢÷Þ;—ÏC7»^úŒ2–ï­ñ|ydˆ¬Ã“KÚ|szíÑo••ò§=CÛáR.áùC¹ÿX’9îQvxtÚõÿ¼&uSûG¸î¾6wý_ÈJ¡¯ž£ÇëÚgüº¬ÉÕÿéŽ{¿ü¦¾jþêÿ3{ôƒš¿Ïþ?}2w°9Ær ÁF3n˜0Ú&"cÁÜ\»A:=“TÆÐâ!.pAûˆ_y´)Òz: Øt …ñpTG†‚*éw×ôÒD¦i'ìVÚ6q²pÊp­÷k;rÁ Cµ·GzÙøâ's®–Q_w¸¾ºÀ™|åÒ'“g¡÷Ç_¥ûʶ~40ø”G×éøzîY'ú¢ÑމW¦´³qã0 *KhÒŽ¬^Œj<‡Gû$eÜîøŸù¾ã?“gæG×îÿ]ÿôQôíMF¿È .}¶úõÿÌó£6MØüIÚL™wÁþçMî”h ìe€­—ܳ™ÃÐè%›o N: \;¯ Ÿ »ñ¯ùöZiêOBÀc—Ô;õàÑ{>]ÀÒ"ã”U^¥ç—wÀÐrb¨øë@IDATÊ>M˜œ€–¼ÐÉ›GØ‘ 6 ËçøÊJ?œÎQäš<¾|;lùqè—«¼réÓQ2Ì7Ñ÷èñihÜùRîîÔÏ¡õÄMR.ÒôNŸMbArê‹È2ò¤Üðá§o‡ÞWÈ&4/;nŽN¿œòM?e`V÷ŽÿŽ¿9±ëßjØõ_]³úõ?½°öÿ›Ùÿ|‹5†bÇû¡eÆ» ‹ÁvtÆPß ;# ر)øÇKÜCQÇ¡Næ¾äqê<ã2îS×Ýá‡_ýxƒ~*{ 4y=ýÖ£2dâðÆ« C¹¶·€,w¸"Ýš|ô飫¾¶KÿCãѧ&¢~m=@YŽ%¯ºZOõ{ÊŸOž¶ħïôaëB'¶ØÙ\Ýõ"Ri[š8u ìø?úoÇ×?´ëõ?]°úÿ|ˆ_ûÏNþáöÿéGÿøW¯ØØÝéa„™ðÝÀ£±ƒÂÉ+@ã²80áWžaG´ëâûUxS¶u•þ ˜‚ ÐΣ¶Ö“øÅƒ ý92•—ô»«ü||êîô'|Ê•¼é‡‘_ØOú¤/&_9i)?ì„9 ŽSG@ãÈä%ŸÒKP×­óÜ/ûÍrGNm¿úOÝ!Ï“>y ÐRyÿ mwºô_¹Èó(3|:ží´;u:Ûx )=ºÊYvüÓÍúdÇ×?]µëõÿêÿwÛþ?ë¥Ö˜ŠLœ¢ðô¾O |<è¯Ô“54ÚÙv”?Ú¤«Ùý¶©K¼nÇÿù›’¾ÝñÏúÛõîVîú?úiõÿêÿ‡íˆ½Yû¯?Þ¶ÿ7¹×Èò2» 7PT-‹ñO§Cc4ñã_€Ý!>ü&?àa Ö$„¿xêc°”¹¹=2´Le!—úÔÁçä5_¹Ô?é…G5\í#Ã<çMìŽæˆmþK:©`H<  üÆà]É(iÇ%:Ǩx å"ËEp6ùè|º) áE;>Úòú6¸:ýG.¼ÑósiðªG\Ú7É×^`ð‡÷¼ÖÏíøúoÇÇ¿kÊÜàvý?ÈÚõ_½_õÿêÿcqck›Ø£ G—°U£GÞûÿ¾Œªp•)ãûÞÄßÂÓ)óDÁÎqÇscÖO¹¤ÎŸ¡Ÿ„tÞ¡ÝØÙzÚf'Ìý®öGxL]ʨMÙûWúø:MÛFþøóçÁÃÑß{úî€(}T‡oã<ÍŽÿŽÿ·gp»þwý¯þ_ý·«kÿçÛö£a‘?ÊþÿàïòŠÑ­ANxŒô=m2¯±oߌ'î,ö8<{l%Ì¡m}úN‰Ûßɳƒž»Ë'®,W^ÂM3AJÏ·CE°È8£ßäKœvÆy¯•2ùä1u«%ÇdÓ'\×gŸ}ö­>úèÑž¾Ž¢|Ðê/ôp©kÒñoüÊ­ñù£xÒ[ß‘sÚ0y@‘ÇÙäµìyo×)?OÖä£É™¾8U„_Ê¿ÖÕ¾!‹4u¢Ùñßñï¼ì¼Í¼š9²ëÿ¼Žf×ÿêk„[ý¿öÿq‹ÂÌk(q5º‰Ì†¶JUØäh‰)g‡p¨Òq¾Œ{h/>wÞ-£ž#4ÀÀÔ®îÔuŽ´˜&`p>`âªG^~ª‡h“–øÈÊ Ìˆ¼Â½x¯¶úñG 9Ò”Þz(Í´eÊ ‡v@Úן¿Îë^¼|ÐxÉ÷І#ó³QƯmO=×o â]ŬL°ÏÕvq¯\ {û¤ím™ðÞšð¤}§!V.uÌØ¾~ýZóãʯ2íøïøJ\çD"óÇ\1¥ ïúßõ_ý½:s$ºë6GÌ“™0o̥꜔½•1ώ΢ÞutîÔµú?ërúƒ¿úÿ}ûÿd‹ÁöÜ_ŸÄ‚ •+ø¨o·Ã@[8vU8»V]$³2òMBùÊð]´V¦ &e®E…^@R䚸2©chªàÕåHÏLº‹îììœ$VæÊ×EÝúÔ£¼|Oêv¢S'‡Gùó#´dÿÞp&ÍÎЇ³£åøÏ£>¨lÊáS¾Ž sd8åÔ(¶>uêƒ:eº; Œ×ü MÂC¨¬°üÒ4MzÛÉçR×°O¹ISãŽÿùÕ}ØñØñ?s¤kÉœ®¿ë×õëêÿÕÿìËÚÿgûÿô£ÿòï_Ã|v<üœ ÀàS‰N¾™îô@’ËÞM£t%‹m < }Ÿ|ñ)O| V„û4ŒwÉpvq¼ý<Š~èä¹/Ð1qòsœ7aå"ËEL”~’žep£¡~ñ¦u—¬MŽšy¾0¥?È÷ùµ{¥_ȧlêTá8»\ø¶O¤á÷¶\­«éACøWò-wÄêÚÿüö#:Õ]CI@÷ÛÒÿÃ+g̳vüwüwýïú_ý}½NIª“Wÿÿ:öníÿ7³ÿOþŸ~øŠ±v´äÂu .CLÑŠ›T&`Qða‡J9t¥•Wã~7ðxËK=3aqüJ tÏFzéê^úIYÞ¯˜8‡>ÆaÒ¸Sß3Q¶éòú´>íÖöâuoGÛ‡>@nhõϽþŸ~úé·>þøãôiûÏÿÏ>=÷¶\nÇ·e1;†Ú¨~®²Þûˆô•õ.Cû6ßú£-\Ú1u”oꙺ*ûŽÿó.ãŽÿ™»þwýWÑ«ÿ}»ëÞêðÚ ºvõÿ›ðßeûÿÞÿõÿüß37F¡:’{ë"·tˆ·Kcâˆ3ÖÒL´ìÍ }¥—.Æ}âÊx,ÔûN–IY§ÎºòväÆ,PüèÄ ‚Z—]¥É pð)Ç^á`=¾OgwdpvãðÁ»íé1¤4|ÈOveÚgÊIWxB‡þ»óMC¾>‹œ¤L6å¾xýEø(×v’A\Ý$¬,xxMm@¯y÷òè8e{ÌëžyK—òÃc<Ú–GÙ« ;þçZ¿ê·ÿ]ÿ»þWÿ¯þ_û_›ù»ìÿÓ¿ûÛO^1ÆÀ cÊ9?†þ Òühð‡/?Œ±Ï« †¾F°²Kƒ—Wpx0¼"@t65üÊÔø7aÃGH¹@­²| f °ôæiPYæR|ÜÐPò§ŽÒ¶ÞI ‹?aõ’ƒ#?à…¶—åÕ\¢Ò=äÓùŽG•!Ó6UæÕ âx¶]dÏé/N^ »ôÉLº?©cüæKæB;¾ö’‰ìm£:nè Pյ㽯Míøgþt¾ìúßõ¿úõÿQç×M¼2iíÿ±Õ¿Íþç§rßìš\<ßÌ›4†š‚õ‰­³ÑW€ƒðãyXm@âÙØ¡«1GÊøˆËçÔW¥.­/:í1!š‚§ x u¼»?A•ÊÏ…òƒ””<àC9uØêÑ£x깚_¥œ:É\½:ëëÇ‚¹vñ×vŽg]Ú5Ǥʼ?ß$ÄÃ8u4ŽÎÓqÞpû®iâžÊ®~å¥nù­Ý´W=èvüÏüØñßõßuÖu_ߺ²Æêïú§9Ž[ýéÕÿ±}Öµò.Úÿ§Ï%w ß $’ßöëJ¹|FÙ;Ÿ%/pÕ@#¡t,*à‚“ÇÙÉ¢€¸vrÿž¢·þ”û%nuO±€y ý*`ŒðÅ?¼}âöN«À½‰K#¿ Ã{¤±´‘çÊǽ<éÂø+¯^ñìš]m³se·Hýè)܃ªOýüç?ϱ¡<èß®Ÿ>êκ´´óLJ°³ ñ­îI;ÈSùÛ6;gÒ8<É#¯¾¶qhퟰ=»ÿ3?vü3EòÇÚõ¿ëõÿêÿµÿ˜ýï¿ýÿþë)ãj7'ˆ˜‡‘a„ 8ÓübÞLþzîMƒN^­ƒ>wŽÈNÍ 4wþÀrÕG‘£©C«þÈ2‰@ š»\Âw@„üÊP´,ž#ËK>`ÅΗW,\ÇŒêàøý” ¨Ô©WzûCé“!(?q.ò^õLŸÚq]dÿð£óþ,²ÕUnquÜûª#Ìïî£#NÑÚí°£Ä°×PÇ(M™:0qïÈ·Ñ•'¼<J¹çG'^ÀÂÇ—S6cÂɿʓώ‘|üRfx¤¾‹×³“3üìµÎò'/ùÓ¾ÔxêÄ“;ï¬:[Àd² Fž´ÁU¿x€Ï•™/ìø«²ú1iSD½‘sÊ}m·ôÒÔÇS:PD&叿ËSžüÂCthF|eз-|å¤9^å7¾ã?À==»ão^ìúßõ¿úõÿÚ¶þ›ÛÿÜÁbGjt…)T®ÆÚ®ƒÝ4>…+M¹ã¡›Âbc5ڼ횈£÷4Y¼×}$4xñåì¾ ®€¯,Þ“F™¦MÂ@‰Ó-.hIÎäÛщ¼òo<È!Ž—£¾ŽÿPWze<âd#§2u­G¹ì¤Í· É©“,Êf÷Iý³û×—‘âpÿvfùà}ßûX§ sTxÉPZy\øNœ¼ºÊ¼ã¿ãoݘ›ÖgNpæš4óf×ÿÑ»þWÿ¯þ_ûO'Öþ?}ÿg?}Å3ª&ŸR­²à((¤°|Á‘€ñùëÏYè(\`)†Êy?Õ‡~˜21àCsœŸ ° ŠZ9;^Ÿ†×ÁýÖŠúÈ@–‰Wõ‰smÚÄó÷ò{bF ð”ñs1@X~iÏ%{Úqqn½‘ý’‚#áò¿ÄH<é“ mÓ¦¼¬”l#Gû[žcÅàìàÏ•oe¿‡ÑDæIŠÒíó¨0¼·;;ƒWËG½Â}*ÏŽÿôá5tìŽÿ®kc×ÿêó€nˆÎ¼> ¯þ·ív°L†–áíDaLk@º«ƒ® Å—ûA³ ã¨lfSvc”µC¤\Wˆý™z ,¼§Ší ÔûÞ÷¾—I‰ŸK㌽üÊ€p&¯tüš¾$5™“Α7¼¯‰X‰ãáS¹ú¼uÝ7$éÊ:æT!ÅvÂyþœ*"W“Ðdgj€¢~IŸ4óòÕÿpC?¥Ní(ugL¿èk€¯î²“Ùš9¾ú¼éU)I»‘œ´ù‹®å+÷ŽÿŽÿ®ÿóášØõÿ|4¬?<«ÿ/mºú?±öÿüÚΨµQTûŸ7¹ŽïŽbï¸:ïoêý Ðt Ýs´æÌ;áüÆÄïO*½þàÿé/ S0aA{Z¶ôBçÛxÏÇrÝ¡)]DwmOž×9œ{L•/nv‹^Ïn’l&¯]¥¸iÔìW¼±ëÖ6adk=¡Ÿ´ö]Ž!§¯¼`4€fòî® §ýŒ^½™¸Ch°ÐÈ/-‡ ¤µ?ñ-PÖÆ‡KiÄ$e„òWŸhâÁ¥?vüwüosx×ÿ®ÿÕÿ«ÿ×þŸS vó›ÚÿüáÄ—¡(€‘/¿˜ßôãþÑõ9ò£l{ïHEÂw  bøïòfÖíÖH/8’$ŽO€Â”; æÜë`ìÑrå‰?0„èÀ¿Í·tï™* Ðâ‚~hð(ïm¬îAi[侎>Ë‹läÈøàÓúäy¸»«-Ú9ÄúöAËñÉß¶“ŸÖéÈðÃÜ éÊ·®süxŽ?ñi¹´Q_\ôáMni‘å€Pa4ãëUù&¯»n;þÏßÚñßõ¿ëõt)¥{¹êdÑÕÿÏ›1µÕkÿg£åûÿ“W& ƒÌÙyájx¨×sT§³úv^vSæ‹€rÈ/ o†}Üù{“`¼t&lKà ÂK~ëƳu¿þâõãu˜=6u.O€(ˆyŒÉ¸¦²ÐQÆt yÄñ°8²Hçê'">ÿ(ä¤ãyшûQe®üùåÕ¶©°mÿ¡8œ:íLu¬¤ë mÊ„ O%™RädÍßÉïTFr•çŽÿ›ã£KõÏŽÿ®ÿ]ÿ«ÿWÿ¯ýgj³køuwûÿ °²‹2; ìàÄð 2< áÜpÜk²£tOW T/€C#ÏÐÏ£l“¸‡cð,usÊ¡è ò¤QzdSŸy “,à†_ÛÜ ?¼Üort'_9Y¤7øµm U¶v ¸ü¦¹ÂL0•ðU62\è[¦a¾vh7¿íR¯ð½ÿÚž‡¼“Ï)ÇÄ‘ 0 ÀKú„®ö·^¼<ŽZ#ïŽÿŽÿ®ÿ]ÿôÑêÿÕÿc7ض¥¶‚Ï&­ýÿöß=׸ëDᇛðý%š@L 3ÚÒKËÎÕt¼ð—RpA&`fDø¦Ä9Æ»’¦t<ÅS÷ì 0Ö ê¥Q'".ÜŸøyá>Õðh¾º…©‚š/_ä1y“€vÕMéhÉèéidñà'OÀ¦=E5ßš”ž ìx^åB7ñ¨{{ކ®ý§½\å5ñ9}JŽ~ºÊ.ÜðìnThæ"Hœœí'}¥|xLøá&¼ãæž>Ñ?;þçÃÁ}¾˜?»þwýWG¯þ_ý¿öÿØÿüØs *EÙGZà t»!Ò î¤]é1þÈ#®tÀGÓ¨†V\™– ó¹¤Ï…óœã@_r W'ßS.¬OÙò–ι7æ'}|»PSÙFò’1m˜ºÕ4åq)ò@N껀”;rIç𠃶ýʽ.‰—,ÃøÚ!:;H}ã<þ!ËßóG]mƒýWÅ¥Žö§´|ÃðtÙeÔ}zácC+åÁ—\ó~ÚP׺K×øŽÿŽ¿u‘ub&ÍÜé<yÐÉ÷ ÂС @š´‡lÞÐ>quÔá¡,yRÇdè éâèåÇ O®rhoä¼èr&ßNÚ{Ã#}4}ëµûÀΩ‡g§Ç„\Ë+'sÜè°ñ´19Ïcˆ¾é©ç*‹¬é;þ‚wüwýïúö ™¾Ýñßõ¿ëõÿêÿµÿ¬ýÏ{°`“è¾{Ó°c$'FgŒ6£\½qôw•GSã. y²4u0øšÁÀwêŸ:¦®ÆÑ¶œw?‰÷Û}€[A°á7 û)Ày¯p.‹kß<­S=øÙ¹(0›Jòi#^dó‚ßNþ••<\dŸlÜyÇÖy§Wê¾ä‘§|ޏº9tžºö›Üðo;.zåPŸÒÏå[_û¡|O_Ÿ:Ú¶GZ8šwüwüÍ„]ÿ»þéè‘™«ÿWÿ¯ýÿæöÿés‹ñí"ªaftà£@@^·ÈìPŒþ݈+ÇÕhüñÇåoÇ;bÜ,]€A¹òö{t¯?8™^À¥«œAÿàÅ\8´A®>€P9/p2ë³+7¼¸ŠIwKý}AiûFy N>P5iíihs™~üäŸÄô_ë—D~®@ìÔÑ1 ¼Z7:a®í ¿Q|ü>ò!íº„ñ‘pK/Ey¶}-ŒŸ>Øñ? ¿ó{Ç×ÿ®ÿsEbõÿØÕÿ±ÕlGm7_ü]·ÿ¹ä^­C¸Z>…ÒÝ“d΋ëÞ™Ò (ð ¿Û7qƽu íË2 ‚ODx©ËÃñ¢ð™ò⎱ ô”« è+ ŸäȃÎc!¤üd’qèÔgëPÏ‹kçª@Mù¶ ˆSNZÚùv¶\ŒNxò´©à$õ§ÊÓ/䪌dj¿‹\ê:Áã㉎¬h[^Zä˜ãÛþ,Ni+³£Ýóž/Ç“s4Jî)‡s˪¯ž\ùðwüwüÍ—ÎKó£k¯s[Zç1º]ÿ»þWÿŸÍ‰®‘®‹êokfõÿŸ¾ýúÁ¼É!í€ókÈ›,Ü'ú¡Éã(U–Û„’Ö]€¤åå}ñú¼ Ô„³ûó óJ\Z>)@Aä02»^äÿÉ“n'KÅŒ@vÈ3¼{_‰l`C^¾9”´††<Þ“Å÷HSw}mPWâÃÃëÈ€xi?|}½cªåôMœ:æ‰Á¿rËk9ö”t<”!úIx"ùꬼx”Nú“ÓGœ´ŒÓpðÕ`ý3ìßÉwü£><9ü¸ÿ3vü¯y:óp×ÿ®ÿ~0¬Þ£;¢£Fg¬þ¶«ÿ×þÇZ1—ÜEbØ`b ­ÿcpûXT]Lèß6Ê¥ƒð*MAE™ûKîo(:ú–oY ãÔqdîAg¦ôÚ ihš¯|ùE¢#VÒ|Â:Àæ€+÷±‘ÖÁ'{A‹¢áE†´ÎqàUöúù ˆ¢Q®|„ÉQУ¨¼Òñ ˜Âvþœ6ÎΕo¶M¼4ò ¨„[‡°2õÑËó-K_HЗâ˜á™¾›Vèÿ–“o'.<3ø;þ;þÏëÌÖugm¾9ï2—L3sm\ËHßõ>ôèý³ëõ¿õTÝN¯×Y/ìãêüÿÛÿOþñ¯^Ýlx¨BDÆGI¢5jħùoìÀ0â,™(£˜ùèÝ‘’3ßÖÊÛŸ§Âõ¡©‹‚%”ºFqG\€‚´< Ä=Ò¸ò*;DÜ9Æ;»_‘oxq96›òäKüÂåWøMZ}ùM¯ø š¶ÝïfIïBBÛ0™íÔµŸ[Ÿôö¿4ùI>ü/¿:wßðܤ•Úxç¥G´ï.kú?iÚo,ÿõý.ô­?eÑF²r¨[[vüÏÜÐ;þ3[výïú¿tNôÒ¥›é‹ÕÿÏ× è ý³úÿÙf³5]:Ž­ù7nÿs‹RŒ›Fi@C<áîñÛ`½ÉáÉNÐÕ ÝÂ.|¦ƒï à¸*·à¸‡•þð.ä胾»S , î’«_µ'Ÿû"x ;Nt,¹G¶¶òÍÚ~ü•Çë%&N6ÀB_Dq ðt†°¨S ‘fg+ùWŸ¹¯¥\ûáÞöî6‘Å£ß}šùðåyÙªö÷˜ÒOûèW|Ü»÷EÂC+/|t6O_¤o?á$L\]‘eÇÿ1ÿõÇŽÿÌý0ói×ÿ®ÿêYóaõÿ¹†±úÖÛ \¶†îd<ïªý?ïÁº +%jǃ¶x€ÆIPìl)hâb}8˜Äô«sM;þ»þ´vý[%³6<ógtÇêÿcÃVÿŸùÀ6½ëö?—ÜcD²N¬–ã4fá褫14Œ°«±WŽÑ‰áZùYo“–wåãU#Žhó÷žûæó¹ÊÓ2ñçÎTA|rÝóÕ0ÒKƒŸ8þL>š‹è$ yd$¿õ k^ÞÍåH.`eÄ–_ù•)½ÅöÕ—ކoÛ©ñÊîÚøœº<œþÑ|ЪƒŸü¡ïOuµ>4ýf߈lø {¸SëIS–k^ÃâdØñ¿vþ¦¿;F;þgÎé¹bNïú?_"ézÜõÿ<7ª?Wÿ¯þWìÿã5 €ÉCI^F€ˆòt1p™w#«|ý±xâ¦lù4- kÒíÚ BÓñâC?…ïåÔ«œë«JSPQ0ƒÚæó¡ˆ¼ž`êAç ÍÔE;Aê¸@Šzš†Æù¸8÷¨gÂ‘éºØ.ŒžÞS¯2@(_›ï //_âÜ¥"¤ž#ºÊˆŽÃ[ߤ‘ÒðE«Íèµµí®bG# ]ÚnGö¶9_4¨Üjú¶ùŽÿŽæÑ®ÿ]ÿ«ÿz”Žì«†„Wÿ»s³Eú†ã»Úò.Úÿ÷)Ðc”gÇäýjÔŸLžytLŽÚ¦¿ìŽØyAÃ@3§ᯑn§Ú¹Ñ¹ éä9j|zïìþ¿ Ã)['œ£Äð?5H»Ótr+C²p¢îI?·½.çÛƒ×ÎÚòüò$x8r“/÷€F\»ä€vÃÈÀTù§ÑÝù ã”y´G~¨ÏŸÒG–Áx¼<¯~(¯ŽÛ]¾WV9:@ñý«ÿÏØ‚u|ö½^údÇÿŒçŽÿõ»þwý¯þ_ý¿öÿ·ÿO?œoL5*@P¡w‡§Æ:gì ÷äÛúž5¹$4’Î4 Æ¿eñC3Á€³1ê@ˆ»I@Aéщ3ò *äqäã·ð ÿëþØ„,|ÃÛ±Þ´«»UÊà)¯ ¤´©ß.Ñ8áÒUt•GGž‚OiÙ©»xË/}ù‰U9Î3‘ëôavÐF~rrŽ¥Ô‹|<œ4ü€ÒÊÓz¾= ²àÖµŽSåÙñßñïœÙõÿ¼“kýq]GÖž~òìú_ý_ýÙµ³úíÿÛöÿé'ÿôׯü–ŸÉQ@c—ƒRA HIg ¥éBF\^%Dá8[õ$šÝœ¤M).”Qx)‡Ww¨ºóc¢t }h€IâÈá…ž˜áËñÉÖÇ]!—PÅñÂá1ÑGÙ–“ÉW/?å´cÂx=3´ú!òN˜Œ•—¯^ý•û9ãŠX=é»)#-m"Î%?p¤lét²w  Á8Ù%ÓûêÌ.ÔäuL” à%ÓðÁ·iè}ë°²}5¯æÈ¨/“¾ã¿ã¿ë?ëf×ÿى׫ÿWÿ¯ý?9›5ñ‡Úÿ§Ÿü׿~ÅÐR@É0²À.Æ`ó-6>«t÷ˆ®AN.lpÀ ºc|áÑôp€"¾äÖ÷dÐÆ!L¸»wƈ껱ðQåvïJ¸ý¼ã?à{Ç×VÙ¿þ³ëõõ½ÙQ=J§ÒÍâ«ÿ¯u3¶§}µöÿõ·æ¬î[ßúìÓÏ2I¼YÐê$bÄcÜǧd<™\SHºŽ¬¡ï.JAŠ<. m&à =`LÜ'g?^ø{ZŸ¼ð¹P–óVóbhÔ§Êf7lÒ[¾²ã…6Ò]òOËR‡t÷.Çý­Þo^}hÊC<}ôQêÖwÚÆ‘Cº£Q  o ªm‹ O“æÚxÚÊ§ßÆ÷³Bíké‘Ñ¢¾Â6 $yÕ„cWr—–Ÿ1ä_—ñõÇ—¶ã¿ão^îúßõ¿úõ?ÛP[ÛqÙÔÚPÖ³6iíÿï¶ÿOþŸ~øJ‡2î:±g´9»#wöòJ®—¨Û±`9‚:w®f„r|g „ñVG€ÓŽ«N4â|ü„»3•òSoRi!$upL òDvnÒiê@ã¾ó)¯\üžrʨ7°wuÍ¥x0ŒÃë„ÒüÈì]ZêоÖþC­¯¸ôÁ€,ù\Žç&Ü÷VU¶äMºòžò,˜o½xy2fãç~ÕÈTE‰—1ò€¹!> xÒÉ…?‡_úlÇÇ׎Øwý¯þ_ý¿öŸ}ücíÿœRËÓ m .s<á¼ü³c€}²r5»vwzü–]ïÉ£,6ØÁJÀÃŒ %å¸ (`À_|0;d9Õ:õI«‘×®€âÄηÑÍk¼@ìKGgCƒßXÈy Ä”©óL lqö's´?nÊjWÁZ °ÔVíÀß±dëV½rŽûøœß o}dîó­©2<|õ·•Ó6®å&ð=èßv½o†~¤Ê®°‡Ö¸h¼8ùÑØmã^ÎN¹»ƒ2*³ã¿ão™ »þwý½úõÿ肵ÿ¼ýÏOåÔx(ÀÀâ¤'pŒ~ïì×q”øïŸ×0ÜâŒ>`c·@ I„í€aP0q>ºúd€û“îÜ +-^wz̽”“ë¥í¹Ú4‘ÞçÒVrªËÃe7ëV`™oY~qî„ZSÓéÊ0•·ßŒ¬Ì@“|r ßòŸ™òÚF²ôΕ°öÚ•B£\i'# ÊÏéèW.}8»„Ê“MïæûiÊ-¯é;þÏ;úyÇfF–ïY¿û®ÿóíá]ÿ«ÿWÿ¯ý¯­ûì fµÿOŸÌ{°Xf[¡ J2†€qá½vAi÷¾÷½ï%½à¤†;Æ{ÊOfŒ¿»Lò(dyÞ·›$Ô1ñèã_»DÍs—IÝd÷ ¿>á?àã©¡‘‹<ãÈÞöð•“ŸvO[9e .&3rðÑ‘©ã*‡ß:§Ä9²ãÏáõ¨gâ8*¹†?á_~úËô½Ý/ÀT9év8á¶S_ +Ëi8çÎVÓ[†ùJ'“Þ±Þñßñßõ¿ëŸŽ¨N¨¾¤Ôè:dõÿóNÿêÿ³9Áž°;±=lÑÄõÍÚÿcÿŸ~ü_þý+÷s, ÓI ÷€†x:Ì¢Óa\»'€Q/^ë\»*Œµ²hùÀ„¼/f×ÇöâýeŸŒ{½r¯‡ħ\&íeüÑuðÔí(-4®ëå·ñÀEb.É<áÈ@;i¼Ê/´“ÀrÕ‹7y†è±ó…ÞnZÒGFåðWÓ¯¯»YÂm×0‡_évÍìná™~š#<|õ߯Ï7Ãð ®2£IçáI¯S‡“_çn–<íjûê7È›Ûñ?;‡;þ3Ofê˜Ë»þÎØõ¿úõÿÚÿÚÓ?Ôþ?ýx^4ZÎ÷n†€Ïù&ÝäùWp OýÓO?c²sSÃN9ÇØO ‚7ùåÁ¸›¸ò¹ø.È…²aŠÐPë7æÈ¨[ZÁ‹¼N¬c¸ìü®{Hxª ]Â7¿à¡üÔã[‚‡ïáSþwð’…0òZÂòø§ÜÙ¡ÆOzêŸìh¥À‘ ]]€çÐrÒÃ[ËÈ?OÛÔ#Oix‡þ*°¤º`ªPŠGeAžõ'¯m¹çÝÕ¾ã(†îF`u@ØŽÿŽçÚ®ÿ]ÿ«ÿWÿ×~­ýéü£íÿÓ'?ûé+,*ryü|#NÜc—É…k`¬maFÜô €Ø ´Ñ à(('ìr5bÇÆÅu@ãx*zõÉþðå‡ç==S^¼ùê©¡p‰»ßŒRÇ=çHǯLÀžp@àÈÂáK~Ú0ihZF]ÉŸô‚)åŽ;€+u]˜Œ J¶Såé¿Ï?û,éî™É7©³«8mÈ¿I«KÝW¤üÊSrÃdžHx¥Íâó(//m›vWNúùòÀs<´;þ;þ»þwý¯þާ=ôìêÿµÿ¿Ïþ?ýh¾E ;]È0 ¨äÇØ^†Y¼».€BŸo<îñþÚòÿÅ/~€‚‡]­‚8ul<ø“ °KŽ·F6å Š„¸&ý€º0ÈœºäØ+ˆk9÷ÉZÛÒö)gÇîü'Åé¿{?4-™þŒ=jÅO›|#ó;ßùNúþ—¿üe@‘·±“íÛ®rH×Nõ©`#[óÉ÷ö·3¥ÙÅâž2èëvüˆ×æÈŽÿù@¥?Ì“Î}ñ]ÿ»þé®:/ºè²}=4ÖÒêÿé¨ÕÿÑ!ï’ýúá?üå+Ê3¿Áw ¢Æš·€t‹ê®lå‹çhëx–rK³•ùp~™ï¢9?üoONÙ¼™|Âè8»êmâ™ú²_Ö*:šÏ»†øèãÿÿ¬Ç]ÿ×rÜõ¿úÿÌêZƒî]ýÿüe4}Òþ©]gþ­Úÿ¼hT£jL ª¡žYpŒüøµ¯1ÖâãÐ2Ä kÃø ÛaA%nwFDYNZ'—O?wg·É1?òà=åÔQùâ/g' /N\ØŽŒúÝÅÊOÛ p"{ê9zÄ!˜`òCÉ×±œ²d³3U¾¤&ûtL8u\í áõ§m$»Gœ¯~áÊ[Þêê¥yõäµ.UÌòLYmäš—Èœ^MìJ:)ê{û)ù9òà×¾•®2Oá‡Ü;þ;þæKç“°¹bî˜/ ›O»þwýÓBæÃêÿÕÿïšýúÁuɤ9aÎ1\.Š 3´ã’Ç`O¸J´ÀH²…NÙúôú(蔿@£ÍYtxB¨¹w¥ÜUž±Ç瀶Ê?ò¬lŽ¥á÷ßJ?Lj×+ÈÚvá÷8NÐUùå\ù7aN9|ôü|*ùêFmš«žðºöeËU÷#!ºñ×nN{¹GÙáÍ@__Î[ñ!zm—ïŸì\¤žõ“8jô'G®»/½õ–æ1~Cø¨Gù«<*ƒðŽÿY÷¾Üñ?GÓoµÕy¸ë?zÏZÜõ?_rZýÿÐÃlËêÿÛöÿqÉýnjx›=€ÈØUƒ#|ç)ð'̨عÀHùÇxr=†çÆ›qVV9çÒ=5P|÷°ú2êÎ(%áîxY ~¢§ß}o*‹LÚÅQ^MpxÎeù)Óz´14@Ä<€Œ]ùd‹üC N2> ¾W» F’?iz.<'Ì/¯d\*Gò†Æ»ÁÊ/`sØùö¥±ÑÏå£×øÅîQÇ=¿yü»\ K;þ;þ×¼…ÜwýïúޏtÍêÿÕÿlÒÚÿcãÙ^v³öšÿä=X5¨|‰5ÆÙ™ÀJ 3ã@“…æA+Æ„bœ•®ôîØË£Ã» «B~ÁMd¦ýá°#wÎl'þþ€¢:zeÛ.q`O»^ýC4¥»‡«€Çwî`ᣠííî.žò=Âm+š^ÒOø–×¶ñ¹/à/túèF‹o]eèšÄô˕ٮ°ôæUž–Eòvyu”~Çú{Ç×?³ë?zaõÿêÿµÿßÜþçMî *P@ÃðZHC+aà1‰I/­4a†ÙQ—rÒƒò-¸Â£<ù€Š) Ù‘á*Œ?z¾ûI|õ@LzÀÀÔ8ÍM@É}ª‰ÛûlÞ/u(xãç±óåÁ³ÀƒÅK~ÓȆ0ØòmyÓ'A• hœvM=9î¼êk[‡uøºV¹¼NÓ“†gÜE«êU–‹,øN:ù+“<õTnm˜†$n«¹y¹óvÑ*“>:|<ò“ˆ.—¶­ôÒJÆgÇ߇†s¢kÄÜØõtÝ®ÿgBϘ#æÇêÿ£`õÇíþÿ“°ÿO?úÇ¿zePkXJÎ×ø“¿Ža•Æ·[å˜ ˜° Є~îDY4hB7 ‰+¾ô\ ÿë¹³õòÅË”¢ÐQÐîÿÔ= øÜ­ê‘`ø™„E긇çðÅ/ÎOûŒ<wžŽ §‡áøD¶éƒˆ ¼©S?ØùŠÁ˜¶û$ÄÉ}úí˜á“v /a0Þí‚-ùèË“_Z>ÂäÖç +_¾¥k›‡ôÑ3Ƭ´Æ ‹ºòœvìøïøïúŸ²ë?*#:gõÿ¹ûºúímõï²ÿOÿûß~òŠ"©S¨Æ±-¸¤l Ê€ ¾'ÆhŒ5ƒíå–WCŸ{\—1ïQàdp2tÙU‘?¼ñ ˆà£~ûU2C+¿u“E<2:êXÐ!Œö‡^šGm 9ñQî&˜iꟶq½„®LÊɲëÇ£”O:T“¶è»i‡Ýª|»qhÛ†/®2m4 í3ùéÇ¡m?´½ø†ÒÑë_€´÷²´…¬å¥‡^؃Þ].}Gæºæ+‹žüüÿ3Owüwý[+»þWÿßuæêÿµÿÇúûPv9öÿ“øé+;?5¨²jdcˆÇ¸2Âv´ntÐ"ÔÐ K+ ?îküÜ*XJ¾¡7`A¹ÖÀ5[_ëWöÓO?ýÖG}”]¤)”rŽÌ䓵ô^“öbvzð–OÖ 2ñ¨‚³o{C<~S×KÙ€)_´+ müÀ“á”=:wÒÛ¯]¾‚;íÖwÆÔCž€$`çÊã«ëîÄ¥RäáÎã¡ÕÆ€ËI¿¿HúÚ¿á­ÏÛ¾]ôç;þgMu¾˜Ÿ»þçÃÆ®ÿÕÿ3j¿Vÿ¯ýgï—ý?¿ExÜC±Ö‰vX„ Püˆ2ÔΠ£÷XÄØ_@¡ÀJ^~S0 $ÀaòÊ‹oÛóÆrpeVwêóÓ2¯Gy.¹¨ 0”m;Èë(P@QÙ P¤£ç Bº€´Oïá¥ÄïÂR–“ÆUöħ¨6o.Ççço†Ÿž‘5¨5Öh(Ü^(ÿøãó¶ußÎóÖõ;/áwá¾]šz2‰&¨‘ß´Œ€;íú·3~v´wý¯þŸEÝI§®þ_ûïËw¿Ëþg+ŠãR¨>5˜D&§;85Ìô|ìxÞÝ$î\¼ÿ,(ë‚ å)î:lʳyÙ!:e<êîN](õàÄ9ôÛ}vˆ\jÇ#è¾™8qåb¦ §vi>ž.š7ä¼@9€å¹â‡ç¼$tÚ9ç[Œ|qŽ,~Àz.@gÒãO½>{=m!‹¸Ý¹þN"‘‘’Ç@]7Y%¥ß&wF,åK'=ùÃ3a}2ÿ ¨Nî”'ó8ã²ãÍŸôÈ(ÿÌ)ëÜ5:—LHóÕ¼1Gåïúßõï¸ùpwÑ‹“`î¬þ_ýß¹ÁU§tnü)Ùÿ§ïÿl~‹i®1ÖrJt¼.‹…Ñw,X,¶|ëZ}øC@é ß°á>ƒç^V¸ñò® v(y@ ¯ø“FrÅ#Cw´Ì#0|#Ïäùç®gÇH##~Ö½(® ¨òà믡AwOç¤áÝö%¦díä¿|9 p^†*\uòu|wϤ?ÚwàÙ6·‹×zÛ®‚.rg|FÖìâÍ®¾½¸¿ìâÍ‘cþ mêËŸÿÿ3Mót×ÿ®ÿÕÿ«ÿéE6gíÿ±—µÃÅ ô¥´‡ýÿÁüسÄ:„¹{4 %Ô©”¬§÷‰D¦i 5Çh÷¸ h¬zŽõ€ª«¡)¨NÞËq©Ò*8žêÔŸŒ^æXëWG–‰«ƒ,Žò^ÌëðrNû#>QøŒ/þíÉ RÿðW'ÐòÑF¦IãÈ(OZúd|í.š¦óqõ¡½“+éxL¸¬ÓG€2GpåMvOøÖC6émŒÌï{tÒÈŒü~¤:á…_먼I˜?);tœ<eÇÇ×ÿ®ÿÕÿ«ÿ×þMüìÿ|‹ð/_1¤Œ®‚#Û'ˆÑžtᱺT \ ®ì5fC >>Œüììð9Ï„[š\u([0’ݘ TAd½UŽ °9ÖI¹)_@˜09œ™â¢î©‹Ìú ù—ùn}"þþs)~þ•OmiâÙ¹¡[]h±;…t`)Ÿ&YÜšd0FjžÂ;þ;þ™S&Ï®ÿ]ÿôݵú>ž\ýæ[Â^°7l?¶é²ÿX5¦€ŠN(Ð*8 ¹:JŸñ|(KÉz‚—†ú”dñåáÁá+#­ì$ä±[–©y »4e;0apñ¨¬ÒJCŽ Þ b^7yê)`Ê'¯ ˜HHãºÃƒEÁϽ®iy#ÿÕÆ–Q/>ú¶±“(àé’_Ÿúù&­—†Õ5 È?<ìfÙÉÒï>1 “þv{¥ ã”確|idÞ€"i±äíNúäqü<;þ;þ»þwýÓ9ãèµèíÑ%|·úõæ;3¶cíÿÁ8l¯5r·ÿXY55²—Ñ= é€FÞîQêr{ŒºÎŰÀÃ¥ò—Î;§æ"¯À`ˆbü'ì æ0hòL¸<•µœÅ9~ÃI¸þá3þT˜Te»ë’„aA¦Þß’O¾#€ªqò)ë¾™”A']9.ü'._˜\m—4ñ¶ÍnÞò›×+‘ßC”?OÛÇ×j·4õOZyè| Ì”i¥®‰£ÃÏÓø$&>iWš[¬;þ;þ»þwý¯þ_ýÏb¬ý?›Pìëï³ÿù©™±în£« “·w°g —Ä O-ÐÀ(3üÊã+½Â(Lzëă«ŸÈ—Öôúò+[Âþ ]Þº>¬>xÞÏ5õ‰[vÕ¼’@º»PÕÝáGf>§½ý”Vð¨þ€áË+m›8z`H•›_žM×?“˜þ)xùõu܉&èw|¼ä·?/J~êV¿¿ó_.ùI?»ƒÉŸ¸ãX„ÝŒld¼êïXìøïøÏd‰ë3¿výŸõµëÿ¬:cõÿêó`íÿ±¿¿Íþan±¨@IDAT`es«#-ÇS5ÈvJì6ùôÂQ¼ ²»Hî ‰Û…ábÌ/fè ú­µ‚ Àè)øHáùcÀ8þƒ6)Ïy¢UþG¶ô¤Ç (ɱÜðÀÇ. 64}üQÞNÚS則Gšz¤£Í%t@eâxy3;þ©ch‡ø'Ke|1ßœ¬”Á½¥Vq`Ø8ÊK}òÕ­K}ã1ñKtè%éÃ(ÝZ¾òÕÇéÕÊÿJ“zËíøïøïúßõ¿úõ?[±öÿÎþç·†x:4ÖX·^?Çò\q¯¡·Ûâ5î:lZt(Xè]Ÿ‚ voqÚSçd ×sÙûľû@Ç08|&ØOÙ.³“)ü'½ï“"@âÈΛàýÜùÕ'/;KxŽÓ=zk¼@Ë[ãÉ\~iëЫü•©}J–öK˜ã½[é^¯úÃcò¥ë”ì¤] L=S¡ 2ªG9íàÒŸ ‡WÊN~ùë;»Uú¯Êa³ã¿ã>Híú?ú`×ÿù ·úõÿÚÿonÿŸ¼¦®¶ÒQ€Œ¹‹|Œ7:Ûa 4Ãì évujÈb&½q¶>i0Sž¡÷ÜÃwãáƒxò…‡ 8À!/YµÁN Ë3r‡f|o'×#xûÔ&~þM{'îVÛúÉ­Ü•¥²¥ì%gùVææ1ÜdÐwòô#ÜtõpÊÈG+mH²k(cEí”8Ž8U6~Óù©ü~2•V‡Öƒ‡;þfÀŽ¿ùxæÕ®:n×ÿµ»KGŽNZýt/Ýšu¢_naú5:5úúä­þ·ìÿÓüØsŒó|b½^o`b0¸#ŽóÒÌQ2Ò‘1üŽ åÑŠ›@| sTX0!O9Gd|ñ‚ <84nâÿ*ížhhr×ê6±Ãd±K…xMx;[€9…§‚¬\æv,ªm#¯{\Ù©Âç’‡tòíH  ÐÁß‹D(œ £kÛ?xå™Lü´ŸëŽ›0ù•÷T~< ÑH‡%ê­ÊVYùí; r*U,iÒûœÄ“>’íøOŸïøŸ¹bþíúßõO—¬þÖ±«ÿ×þÿ!öÿé‡ó¬ô9öã 4Ì[d޹;†,] ½cC¯!° â()74x¾ÍOA¥÷i]ò€†)ø¼ È?f`Hn†@šš:ò•¨k¡”~ÆÈR?ÐUÀs Âêjzï¬ùC­o|`O^û„ü¾@4BìŒßãÌÜkÞ.Ý«²ú™k=m‘øýªtcÒÓ§“ÖòWvúä^.ý|ñì®Uå¿Ó£Ûñßñßõîv]îú_ýÿ°7£GWÿ¯ý¯ýŒ-ž9ñôý¿ûñ«‘1¢2ÖáÞµR@Ü&aà=W@8ÔQÆUDõå¥ì‰ä:qrðóÚ„ùö›µÔ1õ¤¦Ëo½Ã, Äö½|ÛÖy8€pð3/¯·¼Kñâ€||"á„ê¶»`6á¸ñ+~¥s à¥Ü¦§äW_žÝ»´ñâ/²µ¿ô…§;ySyúø´|»Sÿ´Ån_éÃCŸ ¿ŒÙ„ùÒÕD6œøU™º«%½íÂW<¼&Ì ïøOGÜúiÇ×ÿ®ÿÕÿtåêÿckÏÖþŸ »ýúËþ›WŒ(C 4¹Ð®ÃáÞ×)P€˜ôÄ/,\Á(×Pó=MC×4¼{‡¨é|=[°)å‚úy?•ô€u¬­£é¾Ñ—{`ä¾øØmrLˆF{r9aeñ펕ü±ñ+ zo{W'§Ý@_^vêðŽðDƒ´”Ÿ°]3OútdSV=Œ6°ÊÉãði˜\\Ê ¯´Õ7<‡Tþ¡è'\Yùøèù#}ؼ‘^W™€»á¿ã¿ã¿ëÿè(kn×ÿêÿêÔÕÿÏ÷…Ùö‹maG„×þÿvûÿôƒŸýô¬£jðÅóL@b:1€b|ŠÇÏÑ<Ét¶|W°°å‡Aƒ›ñ‘?“p%,“ÙD&Gñº&|èXC×ú*×Å&têK™!p(Jå[GËÔ¡¬v¸C\”ÞÊk Yôý>uILJ#0Hã®BËÇ¿ÞEOºcM?m@6u1lxŠã§¥¹ ëÕÇüôÿ€«ÃûRL•ñÔ%~EÒ¿Fv꾜úwüÏ\Þñßõ¿ëÿÇN¬nŒþYý¿úŸ]gÃ.Û$Ì­ýÿöÿ à ÑYÂvI,,FXŸî#$,/€kvt Z˜z/ôDc§б8Ñæ.žÀ ‡‡Ý+uØzmõÞòx=Àù.@ ¸àB>YDýy¦@ÚeçJY;Ráú+à ÀaÛªZ¿cFuŸ÷aÍO_}Scw‹C社é³iÓL!¸îDù)œs‰6¿#8YéÓ¡@Âäo~úÇ S¹îd‘ÍýIþÕ¿•'…®?wZmßñßñßõ¿ëŸ>Xýÿ|ubõÿÚfóµÿyÑhoÀÍ€€/PVcθ£j>`d7h@IÓÑ< üDînYÔCp4DÊ¡çËçû¶Ÿz¤K«lä"“´¾š–NY7vÔ?D=/ñüèÃÒÆ‡LS»ã½Ü㚺¸Ô M}Òñ¿)õKë±æ_~qúaÒõAZëv1ˆÂ_»ù½ø~¯-þÒŒGŽ)G| nñ¡Mx|ô®þ=Üüòáü!_éwüOßé“ÿ3—výïú·Vÿݰúÿàƒµÿófq¿Éþç=X ·£?Æ•ñ`ÃÃ2 ÊDâ]Ža¶S$? gŒÆHžøe²îòœ4u¡åìVy5Qã79úñ©ð9ÊU>h/À͸‚-aíªldÍ·åæ¢º²ÊT¸+ÙµmÚsµ´€TA“I…‡òžmÒÊ[¹n›¶]ݹCÊœ+´Êi  —öHä&M½ê×GvèĹ©m²Ÿ•´Ö~h®¶6½¾ö’aÇìŽæyeN˜æg×ÿ®zeõÿêó ºa|ºaíÿï¶ÿßf\¹—ã ì(-8i|i:–çŸ`Œ£=Îßüèó”)¼ëðâøÊ¢(ö¦0ßôË >ÑN¾Kñwìà LÞ9j; }Û8‚T7Ù2+‡—¶‹kó°K“—6ŽPmó]i§ŽÒ·x´ñ¶rGìê‹ö[ûè”?ÇŸè#óÔá§KôºÈ:mR`¬“ïyÛ5aåZçŽÿŽ¿ù²ëÿùË®ÿÕÿ«ÿ×þמÓì%Ç~Jç¤ý>ûÿôãúëWS*gŒ&p,Ø9jñç.¿5OYi*VN¸t¥åéÝÄ9t@†‹èÊr 4'­FÙ‡2 açJÞ]å¿üj¾e8ù/çº6rh”€*¯¸Ý ,.á© á»Ð4öˆ²|䩳>¾îp‘¯(ÀÂôCÛ¡\ëo[}“SXPꚢäËÑç€-=ªMÊsü·²¨å.Ü5•K?ßäœüáI&gÌê!׎ÿôÿŽæ y˜g×ÿ®ÿ™ t×yAwH£{VÿÛ³úÿy÷Û\1?ÌšwÑþ?ýoÿñû¯|{ÌÝ%œa™ÉŸì¸Ì¢²p<ÀÇsYj·Åe‘9îC‹Æ"TF÷v÷ þÝYBËeâ5á–mÃO6´Èy-våÐóÕ'?á¡í°"äáF¾çá&ˆ”F^åC#]ÜN™Ëÿ©cøp9®›—°¶o‡.²]»gød+¹çhôtâi’¯v åÒ–«­Íò©â:e®rè[6ôó§÷ÆÐk?™8»€Ú³ã¿ã¿ë×ÿêÿ±£wWÿ¯ýÿÿËþ?ýðÿêƒ[ÐàþQºtf>þeðÀ&-Ç 1FÝ£Ü݉{Âû ˆL8FýÚ1)pê1Ev}.ð@4u”χós7äÁG^@Ã|º®S–,Ú„ðÅ9ß–ñ‚1P™Ã÷¼Ul@”Ž8ÃøØešBÓX„/×Z“ú¦¬A÷§ÒCKöÐ^Ǫ-Ÿú¯¾BÓGÝ-K&tÊ“MËÝÇJš<ޝ¼2^ Á¥Ì¤+ÞÞñŸ9›¾ÚñÏ\šyrŸS»þÏQâ®ÿѦ«ÿWÿ®C’‡=¹»Ú¤Ø–É×ì.¹3Øòá1ºÂ>Ù\§“¸Â÷ÌŸôëÝÐçHjøö˜«åRC~•ÑùÈL¢>®Eã;ÒBç7sohÂò >;UÊöß•äðVÿÝ)GFùŸÍï)>Ú¢®áAN4•“/ñĤëŸôÛôUº{¹Ö \Io[ùwÃE6´}ңëqüÛ/ê¬<­«õz͇–kùˆ‰~>\™i ~iÇŽºeÇÿ|Ád×ÿ®ÿÕÿǶUß®þ_ûÿ‡Øÿ§Oæ·¡ÊpFßS#΀ûÔ*nrÅ`j:ð"¯†^¾Éhǽ#(yå+Ì€©Ó^ÊNòüò£ä#ÏU¸ê½)»Yà1ù){í&©ÛnLä¾øG®©ðRæWs”ç«•xºPÿËO™×7¤ì%åqv~Ê“|u©êx´½—O÷°ô‰º;mÊîÚÏðÅëJïý-¼¹ÖË7fŸ¿þ;þ;þ»þwýÓcôHôí躄~Xý¿ú?vtæÂu^¬ý?›é—é›b 6–{úé?ÿ‡W.™ë°,¨YX¹od C<$ rAZÿ”«a/IÞäã ‰ uøXÔUîõÀ`ʈ\õH÷Í^¶IŽÏçe¦oÔ?ôê›Êr¿?å[7ŸSVº;H¾h=\A ^À˜Itwm ‡VûRÏ좩£€Kòy¸¶»wÂÈyïÏ]N¿ëúÓwxrx¥Ïæ§€ÎÐL¯Ÿ¶Me@§<§Ò¹È#y¢/^ÎÏíøïøÏ¼2WÓ]ÿçÈ×?3ŠbæEt }ré!seõÿê¶„Ý<óálF$<ócíÿôÇ_üç¿bx8fñ:HÜ΋Ýc™³°Ð9jÒ¡ …¶ÃÓ*c!Lð.8H<æi]Èb^Òrô72À¶«ÿìÏþ,þλ¨à„‹gë#GܤsM/_íQpÒmå(ÔŸÿüçñí4å¼øâ…^D¦ ßýö‡òêŸ2ÓŸœ~•F†Ó‡À7©#²L^¿¹)ÿöM&°´«¯Ê—|älù!‰¦ô©^í–†oe‹¬®”ßñßñ7ßvýïú§#Vÿ¯þ_û?_꛵Àſ޾Û}iâ¿Óþÿh.¹·c™1ÅÀB]ÅŸc5GhùYša…<„ÀŠü‚Æ;f~äßã£÷´ž¼º ¹lÈ”›¢Âù9™ +G6 D}êÅ'¸'-r]õ¡“Ž/ùV>nòúm:ïÞzùâeŽ5Ñ*—ç’E]Ê·7Z§“„¦NÿÞx…”'^‘uU¸}¢ì™ÐÏÀT?GÎKŽ{;É4Ê0m_N[ZGû @Ð<4iÛ%“ðŽÿŽ×å®ÿ]ÿQ$—ž gèúzõÿ9Xý¿ö?kbÖÈo³ÿ±Æ2 Ê•QÄsçhp@á@øÍã«ÿ“og èPY}eg„_€ü¼1~êð#Ê_²†Ñ*÷þÔa÷E]w0!üþ¼ lá1õuÁ+§¼8ùmKzÐ}týPs.ÜOYt/îäÈ•z&íż™ý‹×_$ßÑYJߦ? `ôGý.Þ×é3ý7DuÜ™×XàAÖ´yú­ß8,ÏöWêÆÞН~mêƒ Ã#m¸ÂäÆIïÑ`ۢϓ>4¥Ûñßñ7÷výïú_ýÞ¸úímæÿŒýŸ#½bh1óÉäîÞ6Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×Çßùøµ‘£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃ»hÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_~qîT¡÷Þ)ÇXh€fpð+@¸¼“ç’‹,h¹–k\ىʅN8íž‹ÞvÛ8t.}+ûú‹çŸ —G^N¹~âR8`QûsÊ„š2yeDûT’vúP¸¿µØ;RÒ´Øâ€'àO}ŒÛ£ÞIӯꖮ-i§;q“'Ÿv¾—³cf *»´ÿsÂ\±ÌÇz™4®ó,éÒÌé]ÿé›]ÿ´ßùàÖyC¯¬þ¿ÖÔêÿ£[¦ÞûÿôWÿçÿñŠB}¾•Ö»9´…´:È‚±x¸(ÙICsî c/‹IÇÅM^þ©¦ @‚†Q·ë“o(¡Íñ¢Ð=Ž)xiŽÎŸ‡,=žœCW'þ0dåQÚñå{ÈD?ô ¤ôHÔNGa¨VÒ•©œÝ1B[žäMxäHÙ‘Z›•+]Ë;.ìŸü©çÖÌoÄM?iù>ÿ|^Ép3ziû0UOwñà =Z>yж-â@¤21 øïøïø_Gçæiç–ð®ÿyÿÞ®ÿÕÿ«ÿ©ƒØ:ŽXû6W~›ýŸ×4üÍ«÷Ë×€WÁ2Ðò¥×é\ÿ'ƒ&>þ•Ùrü†ÑÆà½‰PP S@ÐA°¾ b§ `(p#ƒçÎ;uaœ¿mèCf¢’Sþ%šº»NŽýÐÚ5Ò®Ê:NÞÈ>t>8FxW¾¶±õ¢iX9aòÞÃu—G~ÛXÖ#@¾z:&Ê¥ýÊL_¹C01Ò…ߪSy€ª÷Ú*KÛ ^¾­‹Lu;þ;þ»þwý[ý?Jqõÿ±¯ìCí¿áwÙþçMîv68Gn1ž‰ Pãÿè°é8 ‹Á=†øÍ£„G§^4fÊy/—2³KžîtÉçäU–ÖE¦öáŽÿG'úlÇ׿µ¾ëõÿêÿù0½öÿ÷Úÿ§Í=3è {+0ÄpsL¿p0ÃübîJ1Æõå¡ã+ic8½ˆgÀ‡À8uüˆgÇdÒìøàŸ{N“_€p¯ŸÜ•¡Qœ‹ü#“ô·ê!ÿäÛKÂS½Ê¤®Ék=-@rÉJÁVnôv»84)À‹ö‹Ë/_€UY}Ú×Aè}‚†“¯ß´ß»dlËÞåFxåðÖ6þ‹ìÀÙ¶ÒÓ¾©¿üZ^Âï>ÒñávüwüwýŸ"]7»þχDý°úõÿÝþÖ¦˜kÿÏ&EíÿÓ÷ÿö'¯uE ;6"Ü€Iã„u¦'Àa~Ž…1¯aæ‡C}¥Ÿ£ª³#£~q©-†|xòü«Ø•ç*•çоúèUâÂU„ˆú‡I ¿¶-¯?M ?mŸ6ᣠòÊSØÄ¹·Qž>ΠyùâevÞðtÌØ:Ò/W¿¡—î‘>½?á¡y”¹h´¥}®>¼ç+hI—P5e)Arº|u›^ýhåãÆ[¯¼ÿÿ]ÿÏ;ä»þŸunu=áç¸(?:ˆãKÏÎøêÿg]®_Vÿ»÷žÙÿ§?¿VŽÊÆ@ó-’étÈÀ€îãçÒùÐvaµ,Ý'3Áòê…3¼ìÂŒïÛoêu§Ènžu5þdj:Zïœ)“†hàä=Ù£¬ŒËI#ÿÃM-Þå_GmvŒ¤S´Ò…ÛݪÌê&GÛö¨gêóD÷–"ßÄýã¢Æ—Ž€Òä«§i­ï”!í³BC£oÐ(_¥û"y\jϱ딫Á(Otä•Î/¿ò €Ûñßñ¿Í{sg×ÿíg½.½`íìú_ý¿úÿØ'ýÀ½¯öÿéÏæ§r€ŸXà_r̸Íó¿à£@&éÇÕ×o^i-?|Êà—oäR²ƒÅˆ|›mè¼Yü¾;£,xâyÒ›f“†Œ‘Ïñ“&}žIH:¿í= Ïeðôè+éúí•©Îqp˜·¡ #·@«¼‰S‘´Ç¥v2M¥i©Í\zoû¤‘7—ÓCpúOäîÎ_Û‰Výv°ð°Kè[*"{û ÝŽÿtàŽÿ®ÿk]ÕëZÚõ?JcþëŽîâ¢?:zM¾>ã7¯´«ÿO®þ¿ìv°¬D0¶}UIi]HÂM«ï<ãÍÕGg¡ÍÞùžôÙŽŸêç,FGn}q&ü[ºI/ïÄgaá?ôø @Z‡F^^0wóÅÕ[~•Yzå £ùã.ä”^õ˜EÎNšö_wëôSÛÚП2©k⹃vɉWåIû&_9ýrJe(<“™c?qwÛ ®ð©KÞŽ»#ý¹ãov=VsļëünZý]ÿGÿìú_ý¿úÿà€Ú¶÷Ôþ?ÅùúÿÙ‘y¿À†’=ªö/õ=P”j+` »Å¹;Á›ÁWÆ%n>Dðæó7uޱ>žoÇ¥®ùóï|'€ `"´èA±£ôóŠÙÑ¢Ì8ɱ¡òhð¿4‡Ož){Ñøs›ÔÛ#@}9† Ô;MÀJÞô ‡OËj¯>ؼ ùvíÈ[À“44n]/¬wd+×vFöIã× ·^ò`vŤWæö2;þgü:†üÿ3«Ìå]ÿ»þ̓èœK×™ÒVÿ¯þÍ9êâ½·ÿc_Ïv.âhÊÌÎÊÄëy tA€tc?‹­qixKoie¾7ay~`ñaqƒðêϹäøLÙy8ÀhïÛÖóÒÓA (îu sU ‹Ï€IçZ†—»åë+£¿ô•4²hkãøÉ'щùÕ3ÈÌëF4 NY<”ã“HºxúlÒ¤×Efm¿=òKC~OË+—>¼xG>zat;þ·ù=}£_úè?anÇæÎ®ÿÇzßõ¿úŸ]ý¿öŸ¸ÛÿÜÁ29( ¿³Çå-é ñE¬p€.…¹¬­ #-é1ÁjÔU„žá®Cç9nJÌÿìdMB.À_€@eï.¦í&õ¹[”^1Ã'®†Æ'^²T~|k,ÉCfüù\éÔ¡.àÄ gôÒ8<ÐðC¾|}%ÜþÀ»ñáðè·!­wZÉç”.8«L¡Wžrší'e´µq|ú8ü¶ò½ê@ƒ¿|üÅwüwüwýïú§ƒVÿ_vnõÿ³ agÇN°ôÄÚÿofÿó[„ 0½Ãm×Hi‡00â:˜¡®áïÚ|ÖÇ&Gz5ìI¸þŒá00ß&Ì·ó¼ >ˆhØí½¬:RßÅCÙwüÈ9ßÐËû¢†Ð sÊOº¶¡/ϔіqiû”‰?qeåMiß\`·õÝ÷O‘¿å„• @_?ˆ“K^Úzn>ùY½h޶õ©ó]ÞÙ¥›ôöË_„˜?ÍÓšŽUûÅZŽSÇÄíX¡ãÒö £Ûñßñ7+ºF:§Ì›Ì—ñ­#n×ÿ®óÂ?ŽŽ©>JÂõgõÿYO«ÿß/ûÿôý¿ûék „2»ŒlŒð$4=Šu´.pÅ$<´þMÀßÄrð²è.¾Œ·0E­LDÅaÃ38B£ñMý¡8¯ß³ÿ€´!Q‡¤înÝÛÓúívqîr 3•µõ;ík'¾º.³‡ïðGª`ú®Gü2Dhð.½xÛøœô»k» +¿¾æìhÅ¿â‰Ìt¼[V^Û,LÙå^×ÐEöñõ? «õ5=òLÕ;þg§V¿ìøïú7²†.€±ë>@ÒM—Ò?Õ©«ÿWÿ[+æûò>Øÿ}}ë|}%FXGôÑ!\wt c;;#¡‘yuœ‹Ò=¾Jg^oîD?ÍXxÂ]„â>}ùÅ—1^xZ¨Ò•oýÂuÒçË9Ÿ¥¨è‘aò®r £rŽ%Ý· çNØÐU6õ åÚ®».ü’;Tәľv¼*»: xГ§¯ih¤5œ Õ©íãßeøµúæi;ж}Ò#ŸÄ‘»åøò¸ŒùøOصœÀŽÿŽ&ÆY?'¸ëŸn⺆vý_úäú»úÿƒ|áƒ^]ý€ÓÚÿ·íÿ‡TªÝÿbÝq5Ø ? º„ pöS‰pÜ•W¥h@ñŒ\ÑJFò-·—3qçx®GX&¥KùSùuê:@§)#î¼e´‰}È1¢´¹S5%swiÊ% Y²ó5õ %3W ö«Kr •^ùr ñäqMn?ð“«ó”¿pݣܭÝ÷¼æóñóôÓ‚´¼ ¿«=–^ßñOíø€e^™3]›o»þwýWßdN\zªújõÿêsÁ±¡!LgpÒj÷’ÿ§hÿ»8ºXw@¤éé‰ë4{ vPº€dÅ<šBo•kgR΀wïmôN¾:]g÷ø-Çv×ÀàC± ®uGžï²úÕWÏßhD#ÏÓ—•fP§|w”ʧ\žòÉÞãËï·+cŽÐ†Aå ̓öìàåÓÝÐpÚ”z‡W].¤_2¶îú‚“×cõ¿M‰Õÿæ·öÿ\ €b×CLß|Ș0¶fLx:mŒ2gQ5ýaŒ¥'wþLyáùiæøh<Sáwé➢XBI/.*ý»õK¯ó—:éÍ+?ßT_ô;?`¯Ç|Òí\¸€Þ÷D‘/¼æR~emü/@xmWóÔh§KÙ¼öB? ýƒÇä‹Û›yK¦òøzò'ás‡“þ} }\A–zÂoh…¹ÆÉÖ4ý.>5§ŸÑíøŸc^}´ãoF<ës¨s§óÒìz¬ÀÌ¥]ÿ»þWÿG¯ÒÕãVÿŸÍ}ÂæÕîu¼/ö?ïe`lýÏ¡0¯I’™2ª`ù}äEùNçMÁfWä×g‚嫾×-`‹R¶¥L;×{/”üaü Gž»_9"'Å?ÿ¼E½txŸ6L“Þz¤måM–ƒ2à鎠…Ö®“§¯Oh›[Oå@«µyÿV$=}¢Þð°–7[O|¶±’V㔲SÞ¥Xí-ÏwÛ{zóÁü¶a¢üݵ¼ôö_•VÝ\ó¥+·ãÿ"ý°ã?ëóZ£g¦œ¿[ü>r2výO?=Õ>ÙõowgôòêÿÕÿlÜeÛßKûÿýëÇž*=À£@BZjý;¨á®!ï‚:ñ¨ÐëXÇd½óô8ŠóŽ7¥ÄÇÓƒ‡2vˆ€¼[wv¸€‡¡üz²Hå<\e®_¾Ý!k:¿/Í׌Á˜‘ctåUþ´gÀ^ ‡pþàÃñó#Ñ# ‡ˆSïd¦lëÆç^N½Ë´Œ×a˜KóAW—\è”#×osiïUgî]ò‘ƒL<øuênÿI«œõ[Fþz@nÇÇ?s.óa׿u±ëõ?¹úÿý´ÿÏ¿Eè¨êRŒ&EÉ»ĸÖJ«±MÚÄ¿âOi”ezÑGŽÁðÄ?k|`Mv™Ð_O˜ÌŸÖ‘Ý¥1Þvz”(ä W^à@º¸ºÑ*S÷hÓ•¦lÚ|ñîOÉh(õ,¿²I×>»p÷4|Èñb€™tmÈ·/^úà7£+ ¥œº<øyFŠ\üÇsz(€/®üз¯¥uí¢½|ñ2`Q0D& «.G•SÎíÏÿçÝ\ýª?ø÷±Þñßõ¿ëõÿ]'¬þ_û_ûÿôÃø‹×ŒÆc›;Æ»f:èÛ×Ý÷éT¾ŽÉ _`æ„&ŽŸIÆÏ+†'˜"^Lj‚ÑšŒä7ÿ *|ôÎë äáÓ }ËÔ"Ÿ¬•£u·\ø{…Ä«<òÊ&]Ü#.½ÀM¤NHñ­<í@£Îìæhi'üæóϳh½|ù"‚Vv<õÁT”º*#¿r‡æö'»EÃW™·Ú04ʵÝ|í '?ÿÚ¦‚†ÿÿL/óéævýïú§ÛWÿŸî–Æêÿ±ïcïØ–µÿ¿Ûþ?ýàïö:F÷fàñ™L÷sÓ€«éT MÁVõ1Îånõ< 9¿†^¹´ÒëäqJ`ÀVþÊzJ›ó§q>ž| æMC+Ì•O^YpÑH™·ç~X Z_‹ àjìÚµ.àŠ+ÿ{»¤‹3||›ß¶´\åz×ïqN9ÿ¸È9qý€•·<òÙ¥š¬‡ŒòÉúåÖ·•gÇÿÌW}¨¯vüwýïú_ý¿úíÿ7±ÿ9"ÌÅÖ1 ó1Òǘ0²ŒŠ´ki¹´”0Ηñ.h=>“ϵ¼rî7Õðgç*´.>Òàøøøw©´Ý5ÂFÑyšV?íºèТù¾i¨BaòòÉïî•;X÷¶ßë@爈ÃKYÏ`>#“úz„'ß;¾¤qüûsó7éêkýwþ“˜ôÖçHsR¦Cëo_ëûÊÙúÃ{d"òâ"ø¢áße¶ãæØŽÿ®ÿ]ÿçÛµPý=2q®úƒÞXýúcõÿóûÍ‘»}‹]ú²ÿZiÔÒ±¯Ç]¾t ¤»3 µÎ`¤9»_O<ôò-$NÿGI=†\¾5þ¥Ç+ò\ååûv"Ú¿aÀ%õ MÓˆšñ½OKX}þœ2²~ý™c»—¹˜PóþŠ´Széùøà‡ç‹7Ï—àÉè±SôÁçòyèf×KŸQÆò½5ž/ ‘uxrI›obN¯=ú­²òOþ´gh;\Ê%<(·óÿK2Ç=ÊŽGë•7ŒŸ^Œ[†¬ÜŽÿŽ¿9³ë×ôÁèŒÕÿ«ÿÙ¤µÿǦ¿kÿó[„KŒ¬À8á>'å9Ÿ‚Ì1ÆÈ™ÎÕÁž:[è }@ÍÙ9ü²OrQá1®åjܹ̓Âs€‰»A.¸×È£+Èy”‰<‡¯d¦‘ñ¤þæ6©Û6Ÿ¸¯¿ö>«sù[ÛÜ•êE÷¨åæjh´3uÉ»úåÏ¥ht•múfÒJÃÿ‹îž.Üþ®ÃÏÃ…“²nIo¹Þ!SGû¥õ¡+ŸúM»×Ñ4¾²m§°¾SWëC³ãúµ€T_êŸÿ3g̡͑ñ:oÚG»þŸ×¤njÿ×Ý׿®ÿëùQ©1ôÕsôx]ûŒ_—5¹ú?Ýqï—ßÔWÍ_ýf~ðAó÷Ùÿ§Î,EޱC0€†ÑŒ&Œ¶‰ÈXp7×nNÏ$•1´xˆK\Ð>âWÞ#mŠ´ž(6Ha<Õ‘¡ JúÝ5½4‘iÚÀ »ƒ•¶Mœ,œ2\ëýÚŽ\pÃÐ_íí‘^v£¾øÉ€«e”Ç×®¯.p&_¹ôÉäYèýñWé¾²­ >å‘ÀõG:¾ž‡{Ö „>Ç€h´câ•)ílÜ8 ƒÊš´c«£ÏáÑ>IÙ·;þg¾ïøÏä™ùÑõ°ë×?}}{ÓŸÑ/2è£KŸD‡­þ_ý?óÄü¨M6’6Sæ}°ÿy“;%{`ë%÷lfÁ04:ÅCÉæÛ‚“$(×ΫÆ'Èn|Çk¾½Všú“pÄØ_à%õN=xôžO°´È8eÕ…Wéùå0´œ²O&' %/tòæv$¨Âò9¾²Ò§³C¹&/ß[~ºÀå*¯\út”Ì‹ùÆ ú=> ;_ÊÝú9´ž¸IÊEº€Þé³I,ÈCCN}YFž”>üôíÐû 9Є¦ãeÇÍÑé—S¾é§ÌÌêÞñßñ7'vý[ »þ«kVÿ¯þ§Öþ3ûŸo²ÆÀC¬ór?´Ìxwa1¸ÂŽÎê»ag¤;6?âx‰{(ê8tÀÉ<À—}tÕ×vé2ph<úÔDÔ¯­(˱äUWËã©~OùóÉÓöà‘øô>l]èä¡Ó;[€«»^D*më@§.ÿGÿíøïú§“vý¯þ§ VÿŸñkÿÙÉ?Üþ?ýøÿò5[£#=Œ0¾x4vP8yh\&<âÊ3ìè‚v]|¿ÊoʶΣҟSPÚyÔÖz¿x¡?Ç@¦ò’~w•ŸOݾà„O¹’7ý0ò ûIŸôÅä+'-å‡0Äqêh™¼äSziêºužûe¿YîÈ©íWÿ©Û£3äyÒç#OZ*íN—þ«#ye†Odzý‘v§®Sgû4¥GW9"ËŽºYŸìøïú§«vý¯þ_ýÿ~ÛÿÀb Ôó@‘‰SžÞ÷‰gl'-F_Á„g1Í¿€¥g“ã°ÞC àB?NY†¾õÝýGq`Œ:þcͶR×Už,.Á·ld#óåñ)/Ì¡ PÀ÷ŠãY€Á8¢-p¥}>/ %7ÐXø½Bá‚´‚ÀFZëP¶ HöUeCk Hê¤çoÊ$æ~”¾àćý•z²†F;ÛŽòG›t5»ß6u‰×íø?SòÑ·;þY»þÏÝÊ]ÿG?­þ_ýÿ°±7kÿõÇ»öÿñ&÷Y>Bf—áŠj åq1þéÔcÈcŒ&~ü ¡;ćßä<ŒÁš„ðïB} –27¡G†–©,äRŸ:øœ¼æ+—ú'½⨆«}d˜ç¼‰Ý‘À±Í?`I' )ƒg”ß¼+Ù%í¸äAç´\d¹hÎ&O7a!¼h§ÂG[žBßW§ÿÈ…7z~. ^õˆkCû&ùÚ ^àðž×úù¡_ÿíøïøwM™Ü®ÿçY»þ«÷ë¯þ_ý,nìom{4áè¶jôÈû`ÿ?Ô``€Q®2e|?˜øã[x:ež(ع"îxnÌú)—Ôù3ô“Î;”çJYù㦨¿šW0(!íþJ,Ÿe‚ð~ð˜ÀV‡®éᯞy”7\x]€IŠóõÖ™ûgSàƒ%-¯ŒoÁ€»YßùÎw²$ñ2p÷®S·2Új× ò]­Ômz8`°ã…NýÓ[ñ \ci„5òŠg|§Ì]ÆôÏÕW;þéâÿ™ƒæEæáÌnfÏ®ÿÙÉÞõtöÑ®&Æ„fŽ˜%g¦¬þ_ý~w—þÈü07®ðû`ÿ? мŒªWÀŒn:a:ƒ¡þZ‡Œ«OĪJŸå³žà•1ÙUÌèñséš«!úà\&Žõ5ß`€œ„@ðzò½Ë©ü>œ4ôYñã%<éˆÃO> Â·³M ù¶Ý%˯Á¡ûÅ/~ñ­ï|÷»¹cQóÜêç7£µÀ|“л¡¼ÎÁ§;[NÛ섹ßÕþ©K¹µ){ßáJ_G¢iÛÈþOzë;rN&(òØá"›¼–=ïí2åç Àš|4À#9Ó§ŠðKùá׺Ú7d‘¦N4;þ;þ—·™W3GvýŸ×Ñìú_ýop«ÿ×þ?î`Q˜yÍÂ%®F7‘ùÃÐV© ›<â-1åìðUº1ΗqíÅçλeÔ`„˜:ÐպΑVÓä .ÐL\õÈËOõmÒY¹‘W¸ïµÃV?þè!GšÒ[¥™¶L9áÐHCûæó7yÃËW/Ú/ù^Ñpd~6Êøµí©çú D¼«˜• ö¹Ú.î• doŸ´½-žÃ[óž´oâá4ÄÊ¥ŽÛ7oÞh~\ùU¦ÿ@‰ëœHdþ˜+æ¢tá]ÿ»þ«ß¢WgŽDwÝæˆy2æ­¹T“²·2æÙÑYtس®“κVÿg]NðWÿÿÏoÿŸì`1Øžûë²2ƒXP@¡rõívh Ç® gת‹dVF¾I(_¾‹ÖÊĤ̵¨Ð«HŠ\W&u M¼ºéá™IwÑó‚ÄÊ\ùº¨[Ÿz”—ïI½ÓNtêäð(>`„–là߇ΤÙúhv´ÿ9bÔ•M9|Ê×QaŽ §œzÅÖ§N}P§Lw„ñš?¡Ix•–_š¦Io;ù\êâ)7ijÜñ?¿ ;;þgŽt-™ÓÂõwýïú¯~]ý¿úŸ}YûÿlÿŸ~üŸÿÃëc˜ÏއŸs|*±³ÃÉ·#Ó HrÙ»i”.£d±M‡¡ïâ³s‚/>å‰oÁŠ0c_`€€ñ.Î.Ž·ŸGѼ#÷:&îB~Žó&¬\d¹è€‰ÒOÒ³¬.ð`4Ô/Þ´î’À Éq P3Ï—¦ôù>¿v¯ô ù”M*g— ßö‰4üÞ•«u5½ hàJ åŽX]ûŸß~ä£S§ºk( è~[úxåŒy`ÖŽÿŽÿ®ÿ]ÿ«ÿ¯£×)Iuòêÿ_ÇÞ­ýÿföÿéÏþÓ^3ÖŽ–\¸®Áeˆ)Zq“Ê, >ìP)‡®´òjÜïoy©g&,#Ž_i„îÙHï#]ÝÀK?)Ë{ë5r"ãÐÇ8Lwê{ Ê6]^ŸÖ§ÒÚ^¼îíhûÐÈ ­þ¹—ÃÿÓO?ýÖ'Ÿ|’>mÿ¹àÿÙ§çÞ–Ëíø¶, fÇPÕÏUÖ{‘¾²Þehߦà;´…K;¦ŽòM=SWeßñÞeÜñ?ób×ÿ®ÿê/zcõÿ±owÝ[^»A×®þûþûlÿ?ø¿þŸÿ{æÆ(TGrï\ä–n1àviLqÆZš‰Vƒ£¹¡ïÑ ôÒŸO\…zßÉ2)ëÔYWގܸ‚ŠxAP벫4™Þ!åØ+| ¬Ç÷éìî€ În>x·==†”†ùÉ®LûL9éÊOèÐw¾iÈ×g‘s€”ɦÜo¾åÚN2ˆ«›„• © èµ³ ï^§lyÝ#oéR~xLƒGÛò({µaÇÿCëWý¶ã¿ë×ÿêÿÕÿkÿk3—ýú÷óÃ׌1°Â˜rcΡ¿@ƒ4?üÑ«cìó*ƒ¡¯‘¬ìÒàåUž ï€]M ¿25þMcØðRî@P«ìƒÈ#,½yÚTE–¹7´”ü©£´­wƒÇâOX½äàÈx¡íeyuW€¨tùt¾ãQeÈðŤM•yuƒ8žmÂsú‹“WÃ.}2“îOê¿ùÒ„¹Ðޝ½d"{Û¨Ž‡úTuíø_ïkÓA;þ™?/»þwý¯þ_ýTãùu¯LZûlõo³ÿù©Æ7»&—Ï7ó&¡¦`}bëÅl´Àà üxVx6öDèjÌ‘2þâò9õU©Kë‹N{Lˆ¦` Àéh]ïîOP¥òs¡ü %%øPNvzô(žºF®æD)§N2×G¯Îúúı`î]üµããY—vÍ1©2Î7 ñðN£ót¤7ܾkš¸§²+‡_y©[~ë@÷íUºÿ3?vüwýwuÝ×·®¬±ú»þiŽãVÿ_úcõlŸ5d­¼öÿé'sÉÈ7ȉä·ýºR.ŸQöÎ'G„@É«\5ÐH(‹ ¸àäqv²( ®\…Å¿ç…è?å~‰[ÝS, AÞH¿ Ø#£|9ÀoŸ¸½Ó*poâÒÈÅ/Èð)@,íŸpä¹òñG/Oº0þÊ«W<»fWÛì\Ù-R?z ·Ç êÓG?ÿùÏsl(ú·ë§ºó‡.-í<“ì,h|§{ÒòTþ¶ÍΙ4OòÈ«¯mšGû'lÏnÇÿÌÿL‘ü1‡výïú_ý¿úíÿfÿ?ø¯ÿý¿ýzŠÄ¸ÚÍ €"æada`Â#Î4¿œ7“¿™;D“ð “W B+Ç Ï#²S3Íÿ°\õQähêЪ?²L"ˆæî—ð!¿2-‹çÈò’X±3Áå ×1£:8~?¥*uê•ÞþPgúdÊOœ‹¼W}SÀ§v\Ù?úø£¼?‹lu•[\÷¾*ÒÇ4¯ãÎö‘úµ;nx3ŠÂ•{ô×Õ·@âŽÿ ú~Çÿ¬ýÎáÎ÷]ÿ»þé¤ÕÿÇ®þ_ûÿMìv°2YæxÏó»;ÄèˆS´v;ì(1ì5Ô1JS¦€LÜ;òmAtå‰/OEî¹Çщ°ðñå” À˜pò¯òä³c$¿”©ïâuÀÆìä ?»F­³<ÅÉKþ´/5ž:ñäÎ;«Î0™ì‚‘'mDpÕ/àsåEæ ;þj€¬~LÚQo䜲@_Û-½4õñ”‘I9®ùò”'¿ðš_ôm _9iŽWùïøpOÏîø›»þwý¯þ_ý¿öŸ­ÿæö?w°Ø‘]a •«±¶+Â`7OáJS®Çxè¦p€˜ÅXc¶Ào»&âè=Mïu Þ_|9»/ß+`à+‹w€Æä£Q¦i“0Pâ´CK„ Z’3ùvt"¯ürˆãe稯£À?]>e&ŸÔ•^8ÙÈ©L]ëQ.;iómBGrê$‹²Ù}Rÿìþõe¤8Ü¿Y>xßÃ÷>VçiÃ^2”V¾S''¯®2ïøïø[7æ¦uÇ™œ¹&ͼÙõôÅ®ÿÕÿ«ÿ×þÓ‰µÿOßÿûŸ½f€U“ƒO©VYð RX>€àHÀøüÍç,t.°Ã?弟ê£>J™ð¡9ÎÎÏX†E­œ¯Ï?Ãë`‚~kE}d K¿Ä+‹úŶmâù{ ù=1# ЂGøŒ Êø¹ ¬@¿´ç’=í¸8·ÞÈ~ɃGÁ‘pù_b$žôIP¶iS^VJ¶‘£ý-ϱâpvðÆçÊ·²‰ßÃh"ó¤EéöyÔÞÛÁ«å£^á>•gÇúðš:vÇ׿µ±ëõ¿y@7Dg^Ž…Wÿ¿ßö?;X&CËðv¢0¦5 ÝÕAW…âˆËý Ù…qT6³)»1ÊÚ!R®€+ÄþL=ÞSÅö aÊ}ï{ßˤÄÏ¥qÆ^~e@8“W:þM_’šÌIçÈÞ×D¬Äñð©\}޺ˆô‚ esª‡â;á<N‘«Ih²35@Q¿¤Ošyù긡R§vŒº3¦_ô5ÀW÷VÙIŒlÍ_ýGÞôª”¤ÝHNÚüE×ò•{ÇÇ×ÿùpaMìú>ÖžÕÿ—6]ýŸŽXû~íFgÔŽÚ(ªýÏ›Ü ÇwG ±w\Œ¿÷7õ~Ph :†îÅí…ùóN8Ï”¿ñÅñû“J¯?øúË_ÈLXО–-}Ðù6Þó±\whJW Ñ]Ç“çuçSå €›Ý¢7³›ä›ÉkW)n5ûoíºµCÙZOè'­}—cÈé+/  ™¼»+Èi?£Wo&î,4òK ÄáBiíO| ”µñáRg1I¡üÕ§šxpéÿÿÛÞõ¿ëõÿêÿµÿçÔ‚Ýü¦ö?¿Eøñeh `äË/æ7ýƸø´>y.Àîj‹vñƒ¾}Ðr|ò·íäÁ§u:2üè£wÃFºò­ë?žãO|Z.mÔ}x“[Zd9 TÇøz•ÅC¾Éë®ÛŽÿó·…vüwýïú_ý]Jé^®:YtõÿófLmõÚÿÙhùþßýôµ‰Â sv^¸^êÍÕé,€Äƒ¾—݆ùâ ò Ä›awþÀd ¯ ›ÀÒð¤ð’ߺ…ñlÝo¾xóxÝÁfÏ€M]€ËÓ bcò®©ìtÔ_€ñCGq<,$Ž,Ò¹ú‰ˆÏ? 9éx^4â~T™+~yµmêlÛè§N;S+éúB›²C'aÂSÉC¦Ô#9Yówò;•‘\å¹ãÿöøèRý³ã¿ë×ÿêÿÕÿkÿÙ„ÚìÚ~ÝÝþ?¬ì¢ÌŽÇ;81ü€¨ H8÷†÷šì(ÝÓU(ÕÇ àÐÅÈ3ôó([À$îá| Íäw.@IDATKÝœrhº‚Zý¿úì;öÔVðÙ¤µÿßÀþû±çw(üp¾¿Dˆ©aF[ziÙ¹šŽþr@ .èÑÌÌ€ßÁ”8Ǹsw@ÒÁ”ާxêà‚½ÀzA½4êRÄ…û?/ݧÍW·0 UPóòÕË!&oòЮºÉ!-Y=}#,üäá Ø´'£¨æ[“ÒsÏ«\è&^uooÀÑеÿ´—«¼&>§OÉÑOWÙ…žÝ Í\äïω“³ý¤¯” ?Ü„wüÏÜÓ'úgÇÿ|8¸Ïóg×ÿ®ÿêèÕÿ«ÿ×þûŸ{®A¥(ûHk8€aÀƒn7D:@Á´³ "=ÆcÄ•øhZÕЊ+À2a>—ô¹pþòÅ9 ð%zuòí0åÂú”-oéœ{c~ÒÇ· ¥0•ýa$/Ó†©[ýIS—Ò)䤾 HÙ¹#—t2hÛ¯Üë’xÉ2Œ¯¢³ƒÔ7Îã²ü=ÔÕ6HÑU\êhJË7 O—½UFݧ.06´R|É5à§ u­»tïøïø[Y'fÒÌÎÓ¶ë×ÿùL§ùðY}Üy²úÿèq¶`õÿ`ögì%]– ó¹¤ÿ‰Øÿ§Î{°jè»ÓÒÅ¡±òìœ`„öê¯–_ãÎ0{Õg¡ªYˆ×±h»o‡ó)-¯.ðp?S7PPÐqU}Ç•]œÒdà†ß$<RšúÉÀFÛGåÂ_XÝüÆ)å¤ûĶ»VZôx¶.éú€lÚvw‘ñžðN8ò\«®Ky׾˽O»&ßxewk &jþÑz¸ÿó¡`Çÿôƒ9anìúßõ¿úõ¿ †ØŠËŽ®ýÿýö?V>¸q:ÍÜðø–0 s`40Þ_¯€y|éÞk%\ Ñ®Qo]­OýMÂùå9ºãFÂÜ™Â=àxàU€"üíÉ':ùôC:´H“öÍÚ'®Ž:<”%Oê˜ }!]½ü¸áÉUíœ]@ÎäÛIû`x¤¦o½vØ9uãðìÔá˜kyå¤sŽ6ž6&çy Ñ7=õ\e‘5}Ç@ðŽÿ®ÿ]ÿÑô‚çèŸÕÿ«ÿ×þ[ ìäjÿŸ¾ÿ·?y ‰ÞÕÃð2ÎvJfwÇ· { ‰aç3Þ€z`‚+Fñ€«äNþðÚùóÕ€ FRÓ ÊKËšÜÛ³Ú‰«ß#^PUš³ks…cµ®©›ŒÂBN;æ½SäÖ6?˜¬>€ @áä÷ñòÑtþäóÛîÈuÈ“Ž¾i:Ó»Ï`HYúøè=Êê1`J^(š»k ×xë-Ü÷rà½ãÿ|·Ð+GÒ'Ó·;þ»þwý¯þ_ý¿öÿµÿylÝwovŒÄàÄèŒÑft€«·Žþ®òhjÜ…!oC–¦ÿA3ØxãNýSÇÔÕ8Ú–óî'ñ~»p+H6üfa?e ˜"ïÎeqí›§uª?;fSÉC>mÄ‹l@ ãÛÉÿ²’‡‹Ìã“;ïØ:ïôJÝ—<ò”/ÀW7‡ÎS×~“þmÇE¯êSú¹|ëk?”ïéëSGÛöH §SóŽÿŽ¿™°ë×?=2óaõÿêÿµÿßÜþ?ý`î`1¾]D5ÌŒ.|Èë™Ý!ŠÑ¿qå¸íO>ù$à¡üíøàaGŒ{€¥ 0(WòÏÂþ €îÍço'SÀ ¸t•3è/^Î…óAäê(U‘ó'ƒ`°>»rË  ˜t÷¸Ôß”¶o”âäsU“Ö>†6—éÇOþILÿµ~Iäç ÄNÝ“ðÁ«u£æÚÞðÅÇï#Ò®K ·ôR”gëÑ×Âøéƒÿò;¿wüwýïú?W$VÿXý[QýÈvÔvóÅßwûŸKî5Ð:„«¡åS(Ý=Iæü±¸î)½€/âñ»}gÜ[Ú¾,Ó øD„—º<? Ÿ)/î«@O¹Ê€¾²ðAŽ<è<BêÀO&‡Nx¶õ¼¼v® Ô”o›€8夡u¡ogËÅè„'O› NRª<ýB®ÊH¦ö±È¥®<>žèÈŠ¶å¥EŽ9¾íÏâ”¶2;Ú=ïùr<9G£äžr8·¬úúàÉ•ÇÇß|é¼4?ºö:·¥u£Ûõ¿ëõÿÙœè麨þ¶fVÿÿéÛÿ§Ì›ÜÒ8¿†¼iÀÂ}b ïš<ŽRe¹M(iÝ•HZ^ÞoÎË@M8»? 0<«Ä¥å“"0D¾#³ëEŽðŸ<év²TÌd‡<û÷•È6äå›H@khÈã=Y|4u××u%><¼~ h€—öÃ××;¦ZNßÄ©cžœñ+·¼¶Ñ‘cï@IÇCò Ÿ„ ’¯ÎÊ‹GéÔ¡?9}ÄIË8 _ Ö?Ãîð|Ç?êÓÃÛñ?ó`Çÿš§3wýïúïÃê=º#:jtÆêÿg»±úí ©õñçsÉ]$†ý&ÆÐú?·EÕÅ„þ]£\:h¯ÒT¹¿äþ€r Ã¡où–2NGétvaJð¨ І¦ùÊ—_$:b%Í'¬l¸r‹i|²´(^dHë^e¯Ÿ¯¡€(åÊG˜=ŠÊ+¿€)lçÏiãì\ùfÛÄK#¿€J¸u+S½<ß²ô…})Žžé»i…þo9ùvâÂ3ƒ¿ã¿ãÿ¼ÎÌaýQwÖæÛó.sÉ43ׯµŒô]ÿçC~Ñ?»þWÿ[OÕíôzõÂ>®þ÷Áÿ߸ýÿá?þå뻑í U¨€ÈXâ(I´&Cø4ÿ­F¼“%e3½;Rò¢`æÛZyûóT£>4uQУ„R×È!îˆ P–甸GW^åa‡ˆ;Çxg÷+ò /.ÇfSž|‰_ C¸¼ñ ¿I«/¿éõßDÓ¶ûÝ,é]Hh&³ºösë“Þþ—&?iÇÿåWçî>€›4 Rï¼ôˆöÝeMÿ'Mû忾߅¾õ§,úáÏHVukËŽÿ™úbÇfË®ÿ]ÿ—Ή^ºt3}±úÿùº]¡Vÿ?Ûl¶†£Kçϱ5ÿÆíî`QŠqÓ(¨bˆ'Ã=~Ìà£79<Ù º:¡;BØ…Ï”cð=WEâ×ã°Ò#ÃŃ}Ðww*á‘%ƒ!Â]rõ«öäs_OaljŽÅ"÷ÈVÀVþ¡¹€CÛ? òx½ÄÄÉXè‹(Ž€NÀÐuŠ$Òìl%ÿê3÷µ”k?ÜÛÞÝ&²xô»O3½:/[ÕþSúiýŠû`÷¾Hxhå…îÑæé‹ômâ'œ„‰«+²ìø?æ¿þØñŸ£f>íúßõ_=k>¬þ?×0VÿϺ`[`ËÖÐìç}µÿç=X—a¥Díx0 Ó8éŠ M\¬Ï“ƒ~u®‰'ŽÞåo¾×&HÈR÷”‘ã~…ñ~¤]òá“wZ)0N< üBè€Én”É Oü`&ÿü¤Í*¦åRÇaîoxLbÒ“Ѱºh(÷¸´¥òj§x/ûäöõô`Å™l_S¾/õèƒ:au>Í1¨và¯-Ê·ÿL^ÎÛäíÖI÷»‹hózŠ¡O¿^|ÉÕ~ϘãÉK½ãïøƒÎã®±ÑÂÆgÇ×ÿãƒÖ®«dÖ†gþŒîXýlØêÿ3ئ÷Ýþç’{ŒHÖ‰Õr\€Æ,`5††Öa5öÊ1:1WyZ&þÜ™*¨‘O®{¾ú€æQziðç‚ÉG3`€4â!Œäâ·tÍÃË»¹É¬ŒØò+¿2¥·Ø¾úrÀÑðm;õ!^Ù]ŸS—‡Ó?Ú‚Zuð“?ôòâ©®Ö‡¦?Ðì‘­_awj=iÊrÍkXœ ;þ×ÎßôwÇhÇÿÌ9ýá1WÌé]ÿçK$]»þŸçFõçêÿÕÿï‹ý¼¦0y(ÉËQž.F.óïn„c•¯?OÜ”-Ÿ¦eaMº]`!@hx2ÞC|è§ð½œz•ób}Ai * fðAÛ|>‘×L=è<¡™ºÈa'(àBHQo@ÓÐ8çõL82]Û…ÑóÃ{êUåkó$áåå«Cœ»T„Ôsä@WÑqxëû€4òO¾hµ½¶¶ÝUìh¤¡KÃíÈÞ6ç‹•[-Cß6 ßñßñÏ<Úõ¿ëõÿCÒ‘}ÕðêÿcWbbn¶Hßp|W[ÞGûÿ!zŒòì˜|x@Bú“É3ŽÉQÛô—Ý;/hhFøtã1ü5ÒíT;7:€Á#p{Ÿð¿îMÀÂ7¼ëM»º[¥ žò JJ›úí.]åAWy¤qä)ø”–º‹·üÒ—ŸxQ•ã<¹Nfmä''çXJ½èðÇÇÃIÃ(­<­çÛ* nÝYë8UžÿÿΙ]ÿÏ;¹Ö×udíé'Ï®ÿÕÿÕŸ];«ÿ×þ¿kÿŸ~úOõÚoù™4v9(Ä€”tZš.dÄåHQB޳õQO¢ÙÍIÚ”‘âBù…—rxu‡ª;?&j@ÇЇ˜´!Ž^艾Ÿl}Ür Uÿ }”mù0™ qõòSN;&Œ×c9C«"ï„ÉXyùêÕ_¹Ÿ3<ªˆÕ“¾›2ÒÒ&â\òGÊ–N'{Ê<€“]2½¯ÎìBM^ÇD¹^2 |›†Þ·+ÛWó `ŽŒú2é;þ;þ»þ³nvýŸxý°úõÿÚÿ³a‘Ó±Y¨ýúéù«× -€ ” # ,àb 6ßbã°JwètÀá䬨;FÀÍS—2©güµ„8v;rx ùìVœd䤓¨º;/BF€Cýä °™<ò+;‚äÈ3¼îL’}ú€LíôhC?aí(8ri]€áÐðÕ‰˜é™½ÊÛ¾älhñ*Ðn?I3É5€+ý?²õå¡øÈ °2iÓäÛ…Ðn¯q®ôƒº”×vå}«Ñ·íhµ};þÓ9—Ó_žÿ]ÿ]»þWÿW/˜ «ÿÏtýÀ±G—uMßè«÷Ýþ?ýû¿ùák†€LjÄÓYÏDšÎKúe¸àñÞrSFÇ*Ps› A0ÀÉëDí.Liò•SP Íã½VÙÑQÑ%“#Fi÷ú•å @ø)¸P×É@;TFÀ0Šý'Àäj“\<îmwqØñã–x K{5oS§ #Ûðè;º€.à§•>ñÅ_ðÕ‡PÄ—Üúž Ú8„ w÷Î8Q}7>ê¯Üî] ·Ÿwü|ïøïúÏ*û×vý¯þ¯¾7;ªGéTºY|õÿµnÆö´¯Öþ¿ùÖœÕ}ë[Ÿ}úY&‰7«ZDŒxŒûø”Œ'“k Iב5ôÝE)H‘Ç´Íœ‚¡Œ€‰ûä¬ñÇ Oë“>@"JÂrÞj>@ ú”ÃCÙì†MzËWv¼ÐFºKþiYêîÞ ฿ÛãÍ ¡Myè€çã?NÝúNÛ8rHw4 Tá Tµm‘áiÒÜC»OûAùôÛø~V¨}-=2ZÔWØÂ2$¯špìJîÒò3†üë2¾>ãøÒvüwüÍË]ÿ»þWÿ¯þgjKc;.›ZÊzÖ&­ýÿÝöÿéÏþÓ^ëPÆ]§1öŒ6gwdàNÂ^^Éõu;¶€â,GPçÎÕŒPŽï ”0Þêp ÀqÕ‰FœŸpw¦R~ê-P*-„¤®Ž D>€ÈÎMÚ Mh<Âw>å•‹ßSNõæö®®¹Ï†qxPÚ‚™½KKÚ׺¨õ—>%ŸËñÜ„ûުʖ¼IWÞSž“â­/OÆlüܯ™ª(ñ2†@07ÄO:¹ðçðKŸíøïøïúÏû®ÿÕÿ«ÿ×þ³¬ýŸSªsyš¡ÁeŽ'œ·“v °O¶@@Ž£f×ÃîNß²+ã=9côƒÅ;ØA x˜±¡¤W øË³C–S­SŸ´y á (Nì|K Ñ¼Æ Ä¾tt64ø…œ×@ @™:Ïô8¢ÀÆg2Gû㦬v ¡:KmÕüK¶nåÐ+ç¸Ïù­@ñÖGFá>ßš*ÃcÀW+Q9mãZnЃþ]×ûfèGªìz{h‹Æ‹“Ý6îÕì´‘»;X £2;þ;þ摹°ë×ÿ׫ÿWÿ.XûÿÇÛÿüTN7 € Œ!NzÇèGñŽÁ~yG‰¿øð¼€ágô»%JxL:° l Ë€‚‰óÑÕ'´Èؘtç]iñºóèÐc\/mŸÈÕ¦‰ô>—¶’S].»Y·zË|Ëò‹s' Ð ˜švHW€©¼ýfdešä“[øþø,È”×6’¥w®„µ×®åJ;Q~NG¿réÃÙ%TF˜lÂx7ßOëTnyMßñÞéÔÏ;þ33²|ÏúØwýŸoïú_ý¿úííhlíØg_0«ýúἋe¶Ê $c÷Þk„‘vè{ßû^Ò Nj¸c¼§üdÆø»Ë$B–÷à=aq»)@B>þµKÔž¹È3Žìm_9ùi÷´•S¶àb2#-™:®rø súHœ#;þ^z&Ž£2‘khðþå§¿LßÛýL•“nn;õ¥°²œÖ‰sîl5½eøø‘¯tÒ8éëÿÿ]ÿ»þéˆê„êKJÞ¡CVÿ?ïô¯þ?›ì »ÛÃM\߬ý?öÿé'ÿù?¼v?Ç:Äpˆaˆ§Ã,:öâÚ=ŒzñZçÚUa¬•EË&ä}1»>¶ï/ûdÜkì•{3ü >å2i/㮃§nGi¡påX/¿ˆ×.sùKæ GÚLóàU~¡´–«^¼É3D/ôvÓ’®Ð82*‡¿š~}ÝÍn»„9ôøJ·kfw ÏôÓáá«ÿ¾xs¾†÷Ðu•}xL:÷Ozz<œü:w³ìäiWÛïøP¿AÞÜŽÿÙ9ÜñŸy2SÇ\ÞõtÆ®ÿÕÿ«ÿ×þמþ¡öÿé'ó¢Ñp†¸w“0|Î7éÆ Ï¿‚yÊ0èŸ~ú)“›vÊ9Æ~|¼É/ÆÝÄ•ÏÅ¿pA.” S<€t€Z¿1GFåÉÛOZø¦ž©C=Ê9Ê̺£•º§ §¼:/ôÊ܈{Ôß§r6OÝî 5Â+ÌG–»S/§¬¸6à©_µ/iïb&K˴ΟG•§‘—ghŸö£y¸¢Ç¤-hvüÖ÷þÝñ^»—úg×ÿ®:­'æÆêÿ£ïõ÷ÐÛ«ÿÓtëûbÿŸ~öÏýš¢ÌEôë()àãºåNUAŒŽáB?6,*G\¹£4;L€BÞ¬>é¹›5aFŸÑªñÇÇnŽ<çÚêRŽ_ÀPÐѲ3uG¶Ùuºhñ|ÐLvÛ”ÅÛ#yÉÐzѧ —<ê¬A½Ëþ“‡—>™BDHÙ„¼ã*»ä;/w{È(M›=œª²ªìÚ×¾çkãà²G»RPÙ‘‡Üx ë±¡3®<"ÿÔ{ïÿÿÓwæ‚~Úñ¿>Í<ÙõtP×Юÿë›Ó«ÿWÿ-ŠÝÛ³ö?fö­?O?ø»Ÿ¾î·ÑfàD‡±ÒŒ?# (=‹]$þ‡ÁÐ1ÜìÈpÊz šÂSú°1»0·»V@€Ý&<ð÷0r5tÏäÔ#ÝÅî2(Kpu‘O=èÄ˯rQ~ÚrùÙ™¥“=<§üµ±¦È‘ ¿©¯®u$þœ ÑD¾æã§¾ô×U8}×Eëwí"qÚ ¸b™2ÊÏ#®Òø÷G9ùêñÈKý2ÆE†9"4žòÒßÓV|wüϱíŽÿ®ÿ]ÿ«ÿéJv‰>­£K³C7yuÕï‰?'?tzó£{Wÿ¿_öÿ§ÿå?άçÝ(`ËÑ ƒo®ä¸îšI& GùÔ€d&Ž´1õ1ØÒ ^äubÃeç°pÝCÂS]è¾ùå§ß<|Ÿò¿ƒ—,„‘ЖÇ?åÎ…0~ÒSÏødG+ýƈô)èê<‡–“ÞZFþyÚ¦yJÃ;ôW€µ ÕS¥€R<* úð¬?ymË=ﮜèôG1t7â«Âvüwü;×výïú_ý¿ú¿ökíLçmÿŸ~ø÷?{E@E.Ÿoĉ{ì2¹pÍ Œ5£-̈»€>0Àâ”6Ú‚üå„]®†BìØ¸¸hÜOåB¯>ù½úè¼§gÊ‹7_=5.q÷›Qê8 gÀá)¢ãø• ØY8|ÉÃO& M˨+ù“^0¥Üqp¥® “‘¡@Évª<ý÷ùgŸ%Ý=3ù&uv§ ù7iu©ûŠ”_yJn˜Ì ¯´Y|åå¥mÓNãÊI?_xއvÇÇ×ÿ®ÿÕÿÑñt¢‡ž]ý¿öÿ÷Ùÿ§Ï·caç£Ëà&P•üÛË0‹w×EPèSãÇ}"Þ_;Pþ¿øÅ/Pð°«U§î‚­€?còÀvÉñÖȦ±\A‘pפßP™S×€»bq-ç>Yëo[Ú>åìØÿ¤8ýw%ÓŸ¢G­øi“od~ç;ßIßÿò—¿ (ò6vò¢}×UéÚ©>µldk>ùÞýv¦4»X\ÂS}ÝŽÿñúÃÙñ?¨ô‡yÒ¹/¾ë×?ÂUçE]6⡯‡ÆZZý?µú?:ä}²ÿO?ú‡¿xMyæ7ø.€TÔX3âðQƒnQÝ•­|ñm]ÀÏòQ®qi¢2Í!ó]4ç‡ÿ àÉ)›7“Og—' ûñ9´ç¸Ò·Ãshì¬õÒ{ÿÈÈÄÐAg7 `au·?( éçxð·I˜]¸ó®©–kÙÐ^y|þÜiúíHü…Õí% îbu÷ ½‡Óxz¼1¾ L¯d÷0TÁ}™ðÖ¾#‹o'ÚÝ{Vxïøïø›#\×mæÅ5ovýŸ/»þÏî?âáèáÕÿÏwlõIí\uv:kþXWò=«ÿÿ´íÿÓ÷璻Œ‘ï29ê“ìÚ\ ÊÕQÎÊT)÷• €È̤YŽ-ö¼Åüìä¨WWYz?Io· BG–"áÒ‰W^¾rèÓ¾«äL]Oõ‘ÑQ¨z½×JÙÈ ó ´ò«)wø€™µï’]܃WÚ1@‰S¦OÛ×ôì*M™æ+ß‹îÒÄsxräç2W¹$ø3ñ¸«¾ûŽUøÏÜëÇKzÓÄÓ?ÃG½íO¥"?GüÚ·ÒÕCæ)ü{ÇÇß|é|6WÌó¥aóIx×ÿ®ZÈ|Xý¿úÿ}³ÿO?¸.¹S˜"'Ì9†ËEqa†v\òì W‰8I¶Ð)[Ÿ^å/òH`´9‹O5÷®”»Ê3öøÂÐV™ãáGž•Íq#°4ü^ø­ÄñsŒx½ò€¬m~ã´]•_>À•æ”ÃGßÈϧò‘¯nÔÆ¡¹ê ¡k_F±\u?ò¢íæ´—{”Þ ðõå¼¢×vùî ñÉÎEÚáY?‰ó§F¯q2päºûÒ[oiã7„z”¿êÁ£2ïøŸõqïËÿs4ÝùöX[‡»þ£÷¬Å]ÿó%§Õÿ=̶¬þÿ·mÿ—ÜïF¡†×±ÙˆŒ]5Ø1—q.pyÂŒz€€ Œ”Œ÷(×cxpa¼ge•s.]ÐSÅw«?!£.àŒRê'zzñÝ·ñ¦²È¤]åÕ‡ç\–Ÿ2­GCDÌÈØµ‘O¶È?ê$ãÃ`à{µ«`$ù“Æ¡çÂsÂüòJÆõ§r$oh¼¬ü6‡o_ý\>Êq_ìuÜó›Ç¿ËÕ°ôȱã¿ãÍ[È}×ÿ®ÿèˆK׬þ_ýÏ&­ý?6žíe7k¯ùOÞƒUƒÊ—Xcœí)¬´034Yh´ò8`L(ÆY9àJïŽÍƒvÊÌàó¸<:¼ ² äÜD¶aÚo¾¸€¹sf;ñuÐÑ+Ûv‰sxÚõêo¢)Ý= \<¸s mhhww‰ð”ïn[Ñô’~·¼¶Ìx¡ÓG7Z|ë*C@×$¦_®ÌÈv…¥7¯ò´,’wË«£ô;þÓß;þ»þé˜]ÿÑ «ÿWÿ¯ýÿæö?orgP„†×BzZ ãILzi¥ 3ÌŽº”“”oÁåÉÈTLY`ÈŽ W9ð`üÑóÝOâ«'bÒ¦ÆinÂJîSMÜ.Øgó~©;@Á?/ž”(^ò›F6<€Á–oÛÈ›> ªœH@ã´kêÉqçU_Û:¬Ã×°Êàušž4<ã.ZmT¯²\dÁwÒÉ_™ä©§rkÃ4$q[ÍÍË·‹V™ôáÐáãy”Ÿ¼ð@t¹´uh¥—Vš0>;þ>4ìø›]#æÆ®ÿ£ëvý?ëzÆ1?Vÿ«?nõÿŸ„ýúñ?þåkƒZÃÊPr¾Æ|˜üu «4¾Ý*ÇlÀ„] €&ôs'Ê¢AºYH\ùó¥çùø_Ï­W/_¥Ì…Ž‚vÿ§îaÀçnUÃÏ$,òPÇ=<Ç€/_¼YKà5i/g§oùd}Ð!/€*8û¶7Äã7uM±” ؘò•A»ÒÆ<^@Ù£s'½ý Ùå+¸ÓnípgL=ä Hv®<¾ºîN\: Eî1Zm ¸œôû‹DÑ©¯ýÞú¼íÛñ×Ep¾ãÖTç‹ù¹ë>lìú_ý?s ökõÿÚöþwÙÿó[„HaÀ=k8``‡E¸Å(Cí :zOUÁAŒý ¬äÕá7J&¯¼ø&°1o,Wfu§>?-ófä‘ç’û€ Ú “AÙ¶ƒ¼Žå•­E:z® ¤ Hûô^ÊAü.,e9i\eO|Šj3ðær|~þføÉ“¦oÔ£_ÓVr^r ©,ä,ÿÔáXsäðTN]£,º´wÂò'1cÄ@ª{—/p‹Nùò­è¥içŽÿŽ¿¹`~™O»þÿõD¬›®Ckr×ÿõMmºêú`}×eÕQÓUÑ]òÚ‡üÕÿçôâÞg¹Ö2ý©ïVÿÿÏoÿ?ø¯ÿý¿ýº;H j'¸°µC’‹ã3áYƒZc†Âí…òO>ù$o[÷íü8õ8>Ó'ò¾v´¬IL]&øidz]?:--üFJƒ|axËSoT̤ëO«ÇOÚÖ~UÆãhõþvwüРÅG8¹ÄëË×FN¾°|? ô«ùòÀŽÿ¹¨¯vüÏúÓæÓ®;ãgG{×ÿêÿYÑtêêÿµÿ¾|÷»ìv°¢8.…êSƒIdòxºƒSÃüHÏÇŽçÝ@‚áÎÅëñïÀ‚².˜Pžâ®Ã¦<›—¢¡SÆ£îîôØ…Rþ@œã@¿Ýg‡È¥v<‰î›‰W> fÊpj—Æá#ìé¢y @Î D‘XžÛ!~xÎKB§=‘s¾ÅÈçÈâœÑ¡çt&=þÄÑë³7Ó²ˆÛëï$â)y Ôu“URúmrgÄR¾tÒ“?<Ö'ó¯€êäNy23.;þ×üIŒÙñÏœ²>ÌYó¨sÉ„4_ÍsTþ®ÿ]ÿ.€›w½8 æÎêÿÕÿlPuJçÆŸ’ýúþßÏo2Í5ÆZN‰Ž×…`±0úŽã€‹Å–o]Ë¢Â0(]áû‚6ÜgðÜË 7^Þ•ÁÎ%háÒÈC®8bdèŽÖ9c†oä™<ÿÜ•âìidÄÏÀºÅU|=â54èîéâœ4¼ Û¾Ä”Ì¡üW¯ÎËP¥‘«N¾Žïî™tàGû<ÛævñZoÛUÐEî‘àŒÏÈš]¼Ù5÷÷Ñâ—]¼9rÌ¿¡M}ù³ã¿ãæ±é`žîúßõ¿úõ?½Èæ¬ý?ö²v¸8¾”ö°ÿ?˜{–X‡0w&¡„:•’õô>Q€ÈÔ!¡æíâUϱP`54âÂÉ›c9.õOZÇSšã“Ñ«kýêÈ2quÅQÞËyÝ^Ωsÿadà ŸñÅ¿=ùTêþêZâO>ÚÈ4iåIKŸŒ¯Ý¥CÓtþ#®>´#£wr% —uÚàP†ã®¼Éî ßÃzÈ&0¢‘yâ½`N™‘ßT'#¼ðk•7 ó'e‡Ž“g¢ìøïøïúßõ¿úõÿÚÿ±‰€ýŸoþÅk†”ÑUcdû1Ú“.Ç€ã€pK“«e F²s€*‚¬ ÊQ!6Ç:)7åË&‡3S<@Ô=u‘Y$ÿò#ß­OÄ?|1—âç_éðÔ–ö!žÝ™ ºÅÑup€»SøH–òé`‘ÅݨÉsŠ÷[í¹Þ‰5‰:w©4HYü ¢€e2v|½Êж}Ð|ü”ïCc¤&á)¼ã¿ãŸ9eòìúßõOÐ]«ÿçƒðèÉÕÿg>°%ì{Ãvðc›Þ#û€Uc ¨è„­‚“€‘«£ôY@À‡²”¬W!xi¨O9@_¾Â1ÒÊ@@»e™šÇ°KS¶Ê*­4äÈàÍ æp“§ž¦|òº€Y„4®;ãO…IU¶».Idêý-ùä+0¨'Ÿ²îItÒ•ãÂâò…ÉÕvIoÛì¦á-¿yݹ2ù=Dùó´}|­6q @Sÿ¤•‡ÞÁ·ÀL™öWêš8Ú8üûŸŸÊaëîæ0º z0yw‹q¦pù@@ úÄÑ Œ2ï<¾Ò+L€Â¤·N<¸ú‰\qiM¯/¿²%ìÏÐå­ëÃêŇó~®©OÜr°«&à•ÒÝ…¨î?2ó9íí§´‚Gõl _XiÛÄÑCê¨Üüòlºþ™ÄôOÁ˯¯ãN4A¿ãã%¿ýyxQòS·úýÿÊpÉOúÙLþÄÇ"ì®`d#ãU‡xÇbÇÇ&K\טùµëÿ¬¯]ÿg}ЫÿWÿ›kÿýýmö?ë,›£Xi9žªA¶Sb·É§ŽâeÝEroHÜ. c~1C_€Ðo­d@OÁG ÏÆñ´Iyέò?² '=Æ`@IŽå†>va€¤°¡ùø“ó&ø;pÒž*O<<ÒÔ#m.¡*ÇË›ÙñOC;Ä8Y*ãËùÆàd¥ žèý(µ:Ј£€ÀÆQ^ꓯn]ê‰_ò C(IFéÖò•¯>N¯VÖøWš¼Ð \nÇÇ×ÿ®ÿÕÿ«ÿÙŠµÿÿcö?¿Eø0ÄÓ¡±Æºõú9–'àjŒ{ ½Ý¯p× ø€`3ÀÀТ @¹ÀBïúL°ãx‹{О:'H¸žËÞ'ÞðÝ:†Áá3Á~Êv™Lá?é}Ÿ¹GvÞïçvȯ>yÙYÂsœþèÑ[ãZÞOæòK[‡^}ä¯LíS²´_ÂÿëÝJ÷zÕ“/]§d'íeê)˜ íPQ=Êi—þLè€<¼RvòË_ßÙ­ÒxUÖð›ÿÿóAj×ÿÑ»þϽÕÿ«ÿ×þsûÿä5 p°}¾ˆ²dÌíXäc¼ÑÙc foH·«SC3é³õI»€™ò ½ç¾ÿ Ä+p/Ü8pÁÀyɪ vbÈX¾˜‘;4ã{ë<¹ùÃÛ§6ñóoÚ;qw°ÚÆÐOnå®,•-e/9Ë·27á&ƒ¾“§Ÿ€ᦫ‡SF>ZiC’]C+j§Äq|À©²ñ›ÎOýã÷“©´:´<üÛñ7vüÍÇ3¯výÓq»þ¯Ý]:rtÒêÿ£{éÖ¬ýr ӯѩÑ×'oõÿûeÿŸ~àÇžcœçëõzƒÁ-q˜—fŽ’‘á§pì)VÜâ œ£Â‚ yÊ9"ã‹\àÁ™ qÿWi÷|DC“»V·‰þ#‹]²(ÄkÂÛÙ”È) 8då2·cQmyÝãÊN>—<¤“oGj0H€þ^$zD9àL]ÓÈØþÁ+Ïdâ§ý\w܄ɯ¼§òãQ‰F:à(QoU¶ÊÊoß•S©bI“Þç$žô‘lÇú|ÇÿÌóo×ÿ®ºdõÿ³Ž]ý¿öÿ±ÿO?š÷`Šϱ¿` aFØ"sÌÅø0Ø1ì|`é!èz ]ïDI¹¡Áó]~ò*½Oë’4LÁ€xäM@þ1Cr3ÒìÐÔ‘¯”@] ¥ìðð36@–ú®ž;VPÓ{gÍj}ã{òÚ'ä÷mÄ¢*`gügæ^Ûðvé^Ýè”ÕÏ\ëi‹ÄßêÇP¥“ž>´–¿²Ó'÷røpéç‹gw­*ÿÝŽÿŽÿ®ÿsï´ër×ÿêÿ‡½=ºúííglñ̉§ïÿíO^ˆŒ•ɰ÷®•âî4 è¹ À¡Ž2®"ª//eH$ÿÀ¨Ð‰“ƒŸ×&Ì·ßì¨¥Ž©'5]~ëf%¶ïåÛ¶æÈÃ,€ƒŸùxu½å]úË—Ìàã  T¿°Ý­³ Ç_ùð+cÈ/å†0ý8%¿úòìÞ¥|Ñ­ý¥/<ÝÉ›ÊÓÇ åÛ…œú§-vûJúløeÌ&Ì—®. ²áįºÈÔ]-ém¾âá5aNxÇ:âÖO;þ»þwý¯þ§+WÿûX{¶öÿlèÜíÿÓ_üó_¿fDj É…vÆ÷¾NBĤ'~`á‚ F¹†šïiº¦áÝ;DMç3èÙ‚M)ÔÏû©¤ ¨{dmM÷¾Ü#÷ÅÇn“cB4Ú“£È +‹ow¬äˆ_YÐ{Û»:9íú øð²S‡?p„'|¤¥ü„íšél|Ò§#›²êa´UN‡OÃäâRnx¥­¾á9´ òE?áÊÊÇGÏéÃæ­üðºÊÜ ÿÿÿ]ÿGGYs»þWÿW§®þ¾/̶°_l ;"¼öÿ·Ûÿ§üýÏ^3Á:ª_¡°2<ȶ­ú¡õ;fT÷yÖüðôÕ70v·8ôžÊ˜>›6À‚ëN”ŸÂ9—hó;‚“•>Ú $Lþ¦á§¼0•ëN™ÑÜŸä_ý[yRèús§Õ&ñÿÿ]ÿ»þéƒÕÿÏW'Vÿ¯ýg6ÿXûŸÖøÜ 8àñi5æŒ;ªæ0Fvƒ”4ÍÃÀOänØñëî–E=„GCà¡z¾|¾oû©Gº´ÊF.2Ië @¡ié”pcGíñCÔóÏ?ú8m|È4µ;ÞË=®©‹KÀÑÔ'ÿ;R¿´k~ñå§&] µiã€(üµ›ß‹ï÷:Ñâ/Íxä˜rdÁ·àïðÚ„ÇGïáêßÃÍ/ïÎò•~Çÿô>Ùñ?si×ÿ®kaõÿÑ «ÿ>Xû?o÷›ìÞƒÅp;úc\ï–1ì1,³ L$ŽÑåf;EòzÆ¡aŒäY€_ö( à./ÁISZÎn•W#5þx“£¯AŸ Ÿó§\åƒö ÐŒ+ØÖ®ÊFÖ|[n.ª+«LA…»R‘]Û¦1W{ðA H4™Tx(ï‰ñÐ&­¼•ë¶iÛÕ;ô§ÌÙ±B«œ¶ziDnÒÔ«~}d‡Nœ›Ú&ûPIk]á‡æjkÓëk/vüÀîøgÞ˜W愹aÞxvýïú§WVÿ¯þ7¢ƧÖþÿnûÿmÆ•{5> `1ÀŽÒÒ“Æ—¦c9q.ñ À8ÚãüÍ>O™òÀ»/ޝ, boú‹ù¦_^ð‰vò]Š¿Ë`'eòÎQÛiè»ÆÀ¤ºÉ¸Y9¼´]\›ï€EXš¼´q„j›ï2Hà8u”¾íÀ£ýˆ'°•;bW_´ßÚG§ü9þD™§?]¢Ô}@Öi“rc|Ï»®éø +×:wüwüÍ—]ÿÏXvý¯þ_ý¿ö¿öœ~d/9öS:'í÷Ùÿ§ŸüÓ_½žR9c4©€`ÁÎQ+ˆ?w©ø­¨yÊJS±rÂ¥+-ŸxLè&Ρ2\DW–+P€,h¤y8i0Ê>”á ;Wòîò(ÿåWó-ÃÉ5Öµ‘C£<TyÅíeq O ß…> ±G”å#Oõñuff‹|EùÞ¦ÚåZÛꛜÂê€R×%_Ž>léQmRžã¿û¥@-wᨩ\úù&çäO29cV¹vü§ÿwü3ÍÃ<»þwýÏ\ ;¸Î ºCݳúÿØžÕÿÏ»ßæŠùaÖ¼öÿéùß¿ÿÚ·ÇÜ]bÀ–é‘ÜñÉŽË,* ÇlpŒ0—¥v[\™ã>´h,BetowÐàß%´\(^nÙæ1üdóH‹œ×bW=_}òÚ+ ’Aþhä{n‚€HiäU>4ÒÅ픹üŸ:†—ãºy kû&|©qè"Ûµ{†Ov°’{ŽFO'žö'ùjZ.m¹ÚÚ| Ï‘*þ¡Sæ*‡¾eC?zo ½ö“‰³ ¨=;þ;þ»þwý¯þ‹1zwõÿÚÿÿ¿ìÿÓþñ/_3¸ îÕ¨Kgæã_?lÒr0cÔ=Êݸ'¼¯p€È„cÔ¯“§Sd×çDSGù|4?wC|ä4̧ë:eÉ¢@_œó÷]/ó%‘9|Ï[ÕÉDé€3ü‡]¦)4ý0€Eør] 9©oÊÚt*}1´díu¬Úò©ÿê+4}ÔݲdB§Q`§MÙ]»Ñâ¾x]齿…7×zùÆìó7Ÿç?ñ‡"zõæþ֔ñ<ðÑ÷êÇgÇÇ×ÿ®zŒ‰¾ÝA—ЫÿWÿÇŽÎ\`CX¢Î‹µÿg3#ý2}SŒÁÆrO?ûçÿøÚ%s–5 +÷,°!`ˆ'#€„A.(@ëŸr5ì#É›||$q´á‹ºÊ½þL¹‘«é~ ÙË6Éñù¼Ìô­ú‡^}SYîá§|ëæsÊJw‰Ã­‡+(Á 3‰î®môÐj_ê™]4up)C>×v÷N9ïý¢ëÏéw]úO¯ôÙüКéõáÓ6¢© è”ç´C:y$Oôå«ù9¢ÿÿ™Wæ cºëÿùïú§bFQ̼ˆ.¡O.=d®¬þ_ýÏ–°›g>œÍˆ„g~¬ýŸþøóÿã'¯ÞŽY<À†·sãb÷Xæ,,tŽšthÂc¡í°À´ÊXˆü† RyšÆG×A²˜‡—´ý ð€íê÷ïþ]ü/&œwQÁ ÏÖGޏIçš^¾Ú£ à¤-ÚÊQ¨?ÿùÏãÛiÊyñÅ ½þˆL¾ûíåÕ…?e¦?9ý* §_À7©#²L^¿¹)ÿöM&°´«¯Ê—|älù!‰¦ô©^í–†oe‹¬®”ßñßñ7ßvýïú§#Vÿ¯þ_û?_꛵Àſ޾Û}iâ¿Óþÿx.¹·c™1ÅÀB]ÅŸc5GhùYša…<„ÀŠü‚Æ;f~äßã£÷´ž¼º ¹lÈ”›¢Âù9™ +G6 D}êÅ'¸'-r]õ¡“Ž/ùV>nòúm:ïÞzõòUŽ5Ñ*—ç’E]Ê·7Z§“„¦NÿÞz…”'^‘uU¸}¢ì™ÐÏÀT?GÎKŽ{;É4Ê0m_N[ZGû @Ð<4iÛ%“ðŽÿŽ×å®ÿ]ÿQ$—ž gèúzõÿ9Xý¿ö?kbÖÈo³ÿ±Æ2 Ê•QÄsçhp@á@øÍã«ÿ“og èPY}eg„_€ü¼1~êð#Ê_²†Ñ*÷áÔa÷E]w0!üá¼ lá1õuÁ+§¼8ùmKzÐ}|ýPs.ÜOYt/îäÈ•z&íå¼™ý‹7_$ßÑYJߦ? `ôGý.Þ×é3ý7DuÜ™×XàAÖ´yú­ß8,ÏöWêÆÞН~mêƒ Ã#m¸ÂäÆIïÑ`ۢϓ>4¥Ûñßñ7÷výïú_ýÞ¸úímæÿˆýŸ#¿fh1óÉäîÞ5Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×'ßù䵑£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃûhÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_~qîT¡÷Þ)ÇXh€fpð+@¸¼“ç’‹,h¹–k\ىʅN8íž‹ÞvÛ8t.}+ûæ‹çŸ —G^N¹~âR8`QûsÊ„š2yeDûT’vúP¸¿µØ;RÒ´Øâ€'àO}ŒÛ£ÞIӯꖮ-i§;q“'Ÿv¾—³cf *»´ÿsÂ\±ÌÇz™4®ó,éÒÌé]ÿé›]ÿ´ßùàÖyC¯¬þ¿ÖÔêÿ£[¦Þûÿô—ÿçÿöšBýp¾•Ö»9´…´:È‚±x¸(ÙICsî c/‹IÇÅM^þ©¦ @‚†Q·ë“o(¡Íñ¢Ð=Ž)xiŽÎŸ‡,=žœCW'þ0dåQÚñå{ÈD?ô ¤ôHÔNGa¨VÒ•©œÝ1B[žäMxäHÙ‘Z›•+]Ë;.ìŸü©çÖÌoÄM?iù>ÿ|^Ép3ziû0UOwñê4 þÌIDAT =Z>yж-â@¤21 øïøïø_Gçæiç–ð®ÿyÿÞ®ÿÕÿ«ÿ©ƒØ:ŽXû6W~›ýŸ×4üõë÷Ë×€WÁ2Ðò¥×é\ÿ'ƒ&>þ•Ùrü†ÑÆà½‰PP S@ÐA°¾ b§ `(p#ƒçÎ;uaœ¿mèCf¢’Sþ%šº»NŽýÐÚ5Ò®Ê:NÞÈ>t>8FxW¾¶±õ¢iX9aòÞÃu—G~ÛXÖ#@¾z:&Ê¥ýÊL_¹C01Ò…ß©Sy€ª÷Ú*KÛ ^¾­‹Lu;þ;þ»þwý[ý?Jqõÿ±¯ìCí¿á÷ÙþçMîv68Gn1ž‰ Pãÿè°é8 ‹Á=†øí£„G§^ùäü9.“‡îîp Pߎ˯¦.€Ækòm=ÄÊLxä™¶ ²gÞÏ¡F´XQ.á1¸•tL6r€@Ivˆ pæ(Ï|š™½42jO¾9=¦Ÿ´OrrÚÕ¾qW 6µêh¸tä¨Ã›ÞJP1»W©³AqØs>ªÎ6AÄ8âñÝ/g;L Ø¥,¨ƒÞcÂYÚˆsž´m *ìÌLÁ‹?ùlhË¥^êÞ´õëàËW=yåí£¼>‘£Áž mµOèÀ·ß~›,—>I½F¡»J‚%ü]øÚ‘’Ç'ú¥:€Wž‹Òìr¡#këÐ'uʽÛëüýEíÁU3õ¼—KŒÙ•§;]ʲÊÒ¶ÈTîøŸà¨ó„Îvüwý[ë»þ×þ¯ýŸ/Óëÿÿ«ÿÿðÇùcÏ:Ç^ç*â¸×/_'Ì15g¥8ãM•¡“ªi<Æàô ž >d´ÝàÇ}vLg7¨þ9ç4å ží“»2Ô!º‘d‚ÿ¤òO¹½$<µ«NÚš²¶Ó: H®¬ låFo·  i"xÑ÷ÊËWÀª.öuôC'h€rzÓï’±-û”Žðêá­oÒ¯²gÛŠ§Ó~ùµ¾6ä?¿àñ;þ;þ»þÏ‘®›]ÿçK"=¬ý_ûÿô¿õ)æÆúÿ³IQÿÿỿþé{ÊbH€¼ÇF‚7ÁÇà€´]X­ËAwÁÁ,¯^ècÆ¡Q–]˜IýúM»ÎÙí³PçO¦âÑzçÔHAP&è½ê*¸GþÌ=Z¼Ë¿4µÙ1‚ghá嫇îNUfm“£}{µ3íùE¢sK‘oîý1H“ÂãŸ@iʵS\Û;uHûfÐÐÐ õ+#¼Ç¡ö/w¯Ýò«Ìð•3ŒæÃY* È)=õ1‹:ÀNšê¯»uôÔ~„6ô§NÚšûœA»râUyÒ¿)W^N­c áÈ3…yìçÞÙ¶WøR¶ã_uDŸ;þf×›c5GÌ»Î_ùâšîú?ög×ÿÚÿµÿ'¨o{§þÿíQœŸÿŸ™IØ0²ÇÔžÇK}£ZÊF0ЃÝîÁ3Á›ÃWÇ!n©ˆà‡ü Îc¬ßίãÒÖ||óÍ7 L„½Pìý¼b`v´3 dòØP}4ø?4/À'×Ô½tçþ­OÚí#@ºˆÃ@ Ô3M‚•>z£€Oëê/$ؼ r»vämÀ@×ëÅ굟‘}pÒ‚|Û%¯Ì®|e®îÔÙñïœ8ã×1”îøŸYe.ïúßõoÄæ\[gvÀ­ý_ûŸsÌÅ»÷ÿã_Ïv.âÑœ(3;+s_à`”qÐ 쨠³¨@œý,¶ÞÃá ß:pe~7yeþ €Å%/ Lœ€WÿœKŸ©;¸Ü÷mëyééD (žmʃ„äÝÏ%ƒ­#}ÊÝúMÕ¡/º‚#‹¾ö?åäï£Dtîüé-ÈÌëF4Aœºx¨'%¼ûèlpð…ȬïKyiÈïj}õ¢Ã˃<ÊÑË£ÛñÌïÑ ½ô¢?y°ã?sg×ÿk½ïú_ûÏŽ®ý_ÿÏG<ýÎ`™Œ„¿³ò–tŽø« 8@—Ê‚9¬­' Çõ˜`uêBÏqйLùŸ¬Aäü ÔQ÷ qmyÐhÏÙ¢¼ðrˆ9>÷Z¨cÌãÄ+KåÇ·Î’òLÓ;þg§–^vüwý›YC7ÀØõ?_ Ù¦k‡è§6uíÿÚkÅœà_ÞƒÿÿÒ£¯_/£¯@‰¦ˆ^ê¼cK8ÛÙ «8¥ûø*ʼo—ï#ˆ~›±ðä»Ýûôã?ŒóÂÓB…W¿íËàz/Ur¾K ¢ SvëqŒêy¤(X2Ð} z΄ ]eÓZÐ~=åpà—ü¹C5Ê$öÝñªìÚlÀƒž<}MCû×|Ô¦¾Oú”áíÍÕ~ mÿà#äÈÝzRe c>é‡/ìZNfÇÇ?㬟“ÝõÏ6®¡]ÿמÜo±kÿ¿È>ØÕµÿ'pZÿÿ©ÿÿ’IµÛâ_2§;P‡ÝüË¡CÜ€C¶ßJä·¬FI !Š·È-œ ¡yÁH~åöõLÜy<×GX LJ— óQ¥m@§˜÷fŸŠ:úĈ¾äQÚÏœ©šš9»4õ%²dçkÚAKfÐ@íç+ 9ÐÂW¾œC©We2Î@€wÏmôL¾”NÙ}ü–Çvw`ðaØ hÛ‘gÅ»¬~þéíh”¹ú²Ò êÔïŽRùt€ËS9yÃ{RåýÕceÌ#´aPyCó¢=;xùv748}J»Ã«éWƶÝ4à”õ1ž:-«ƒ³ ¯|-ˤè\äú➌®BÏ”nÇ?šÍ8íøïúßõÿ©]a7¢“I×þÛ”XûoN€õÿç¨PâñCüúÄ£›/9ÎÖŒ©ÒÆ)‹ªø—3†Oé|L}ùùÓÌIѸL…ÿuîðî]b ß @¾APé?o¾à/ø–•Ÿ_j¯ÿä'Øëc>x; ÷=Qä ¯9”_YÛ†ôÇ  xíWË´h§Kݼö‚ž†þÅcÊÝÛ|"Syükʧá›ÂÉ?ÿ¾€h¥ðZyÐ{²Gïî§åèÝŽÿyÌKG;þfÄ›-0‡:w:/Í®× Ì\Úõ¿ëíì*[=°öÿl¦Ð ŸW¿×uò^üÞËÀÙúŸ Â`ÞI’™25°Ò^Êb|GyS1¤ÙùåL°üÔ÷žÑl1Êv Ô©rýAbï…R>ŒCƒ¿Áäy¦•#r2üóÏ[ÔK‡÷éô1ø¶/h+o²œ(ó<ÝQh¡µëäêëÚç¶S9ÐêmÞ¿IN´>¬åÍÖs?ÛXÁÕ9¥îÔw(VËóóþm¾˜Ç6LÔBëÃW?R:*­¶AËáÕÛñÿ*zØñŸõy×è™)ç³sKÚKIæÏ®ÿÑñSÕÉ®»;c—×þ¯ýçã®o—þÿ»ûÇž)=G ¸Ô¦Ï` Ž»Ž¼ êÜŸ€ =ÅzL&ß3O¯GqãÞñf”¤xºðPÇ‘ ï¶.ÁÃÐOüz²Hõ\ 27-ßî/í Aó3caÌÈ8]e•?ý™` ¯æC8øiþHôÈ!ÐC'ˆÓî¦nÛÆçYO»¯Ã´œ×a˜C󉮮\èÔ#ׂô÷¶™3EW>rÉ…‡´ íê®r6meøô¹ÿÿ̹̇]ÿÖÅ®ÿµÿlæÚÿ÷éÿÿ $ôn>4•IEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/0000755000175100017510000000000015232633614025330 5ustar runnerrunnerqbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png0000644000175100017510000000253615232633614027635 0ustar runnerrunner‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png0000644000175100017510000000253615232633614030213 0ustar runnerrunner‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png0000644000175100017510000002605015232633614030012 0ustar runnerrunner‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png0000644000175100017510000000074715232633614027643 0ustar runnerrunner‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png0000644000175100017510000006455015232633614030007 0ustar runnerrunner‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png0000644000175100017510000000456715232633614030215 0ustar runnerrunner‰PNG  IHDR@@ªiqÞ >IDATxÚí[ PT×¥¨ic Ä’4ŽN&¶Ó1mCÆ8±Ú¦‰budb@ BÒVƫѶ”1±hŠ:iLkJ@ ­5‡—ÊK°‚€ò~¿ßï÷à ¿ç»sÎν¸À¢‹²3û;ß,³{îÝó}ÿãüçìu΃Ì`3˜Á f0ƒÌ`ÓÞŒT & sg10?c]“Ç MždXÌð4Ã3 ?˜EÀœ¬ÌÌt)¼>79tß«YoÒl›ë÷æñ¨Õ ùgV½ ä¹?âó6Òù³úBž ð"Ç@oÉs^bxâA0Ögò+€1¯ zKþaÀj±2øõ3òÅë²·ÒÞ²èhÍIòi8G'ëÏÐGÕŸ’Kñûz!‹á¹é~áy¿¥ðöhº;:HYçp—$ Dšè>(;H§Ï«ñ8XÀðÂt¾l{á.‰œ¶–ÙŸG69ïØ¬û«,»G..²žNÈ×6(&Ýï%t'Ó[B(¸õ¥õfÒðذb ¢E^˶,¼¤í}Z篘prO:mÊuºoœsáï©n°Q=ndl„Þ.Ü=¥“¥Ë¬ äërõdÛ¾é  9ŽŽE!cÿ„6¥þLä<ÒCnM5a]ö¶Ù#€}¾‹‚ÐÍAS^“w§H=¾l Rý¾¶¶!ç­Ù#€GÅGŠÉ¡‚Ou<ÄQDŽkkë³fXÒäf›÷Δנ'›« xÿËÖ0 wJŸ‹÷]Hm‹â#U^ØÐèVC”Èmwé_&-‚£ÐZ€Ð¶HõD{îõi51÷’ ‚,÷Ò_®tÄ©'Ú5Ü£ÕÄvïSô¬ôÖ_BdðÍèð¥À¾²õW€ -¡ŠÉNÔÞÊq°ò˜â¤Ä `,ãfÌ7{*­g“µÏwòšc5Ÿi\fP'ŽÓâù666–ëtÔümÒŠ® gYg' MÔøÆFÇ›¡ïpâ8ßøž»»ûÏÃÂÂÒÝÜÜ^ЉîŠÉ¢/˜êšÔÞ õø†¡æIšNç§A€• c|33³gOœ8áuùòå___~œ¯›½€|'X>P5©Çpf€b),²#þ¾1ŸÕ(p—"Ó` Î5öìÙã”IÌû]K—.ý{ÿ) ðŸæ‹Š cûûº†ܷܿ)³/W1ö½RÏ)Ûë¤î›t¨êcòªþ„>®õÑZkkkÿȸ¸¸Ñ«W¯8tèÐiÆíÇ<5t#€mî;Ô?rG1馡 k"߆/ètÓyŠéL ¾{ýŠ1×{R5ÞocÎvd]åÄ›!ÇÉÓ2ÝŽ&ž Fü^QQ¥¤¤Pvv6…„„ôZXXlàáoª3€ýå•Zam­èë2gÿ¨÷Wì2åf—¿ã¾ñ6™´;åÏt&î]¿~***¨­­¨±±‘ÒÓÓÉÓÓ3']Üû* ü®h¯TàFÇF§`·†Ð×tvpŽm€P'"ÚcèTã¿É«êïê¢Ò裂^ûœ¢b£)33“¨¯¯êêê(::Z`¹ßϼ¿Qæ}# O‰«ŽKÅ Kš›ø¿X¿ ¦t â–·7nÿ†ö&{ÒÉx_ŠŒ”<[]]M===q ¤¤„óÔÝÝM………tøðዌÓOù»ª@› ÇåZ¸¦½K‡“ŽÓùØ/)))IÊg{{{ÕäHŽŽêêê’Æ01†—/_nÏ8=ËO¼tz$¦-óò“ã‘Ú:Aç¸>syüÏ‹‘¾@×®]£¬¬,ª­­¥ÖÖV)¤AP ¼b—šš*}ÞÞÞ.¡¬¬ŒØúC^†ESyFRq·Zcçø^²…Æ…ÑíÛ·©ªªJÊ릦&jnn¦––5A/C„ØØX)2ð9¡€ÄÄıµk׺2>KµñþŒ \l»,­õšj€wâ'˜4•——KG1ƒ¨äAƒˆˆqéÒ%Âr‡1bÄB-ðóóËu„sg…áý%òXÂã555’õõõŠ(i€Ï"""¤ñbœ  lÙ²åºAþcñt¶Ã/>Jò2Þ¢ð˜*..¦ÊÊJ)ô!Àø(iï òB,ùxÜ‡íø Wð;§¶Þ—ÿ4¶âQ °?ùJNN–B¤ ˆ Bð¬oĘ˜i,Ä‚‰kðŠÈÑÑÑ“ñx~:Þ˜ò%c-Æm 3„í î>>>ʹ¹RÕ† %< Dh£Ò#MJKK¥±€M\‡¥ðÔ©SYÜû–Ó}NH<÷âê9®âLà‡ ?111ÙÈÂù.ÂZ^QÄÇÇÓ7¤ð0€B訨VùwN7÷5‰0/f3€ùüùÅ«W¯¶e5áQx½rå ¥¥¥QAAtwËA£täÈ‘~b>Ü×$ÂLÁXvDeîää´a “" ð^xx8eddR$//OB~~¾¹ h‹«LMM×óÖés‚3ñÄ)'-wíÚµž^Q€bǶ°RNão4:@NNŽ$†\Ú¿jÕ*7þxÜ·µéú·A€§vîܹ  رã+©9B1ä‚` K‘¡M›6y°ûýŒ‡þ¼ÙN^`éââ²ý¾b°B&å<¸uë–„ñ‚ܼyB ;;;åßb^·ŒçèAs[[['ôòäQ ‡Í 1ä‚ào¬õÁÁÁ]›7o>È¯Z"ïôE€ï.Y²äUæñ1°ÔhŒ!^ÑÞb9d!?ìíígeeåÈ+¾_YTúB^<ˆ~c«Þ,”GpŠ ÓCTøï±Õ`r{xx|µlÙ²ìº_ò‚gÁ=¯Wäå]'B÷•… ne=Á{{ûã®®®¾¬8ú³úð¹Ý±5kÖüI¥Rmeã~ͰšŸì>Í«ý<} {MÏ#/à¶£;\Á/PÐ^æ¯Öüýçùúnɉ›ê£×'ë:pb‹øþÝœ¿.âï/à¤çʈë5ùñBsbâ¿ä˜È~ÉUÉÂ\'¤ÿ¤›h”ÀƒAIEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png0000644000175100017510000001221015232633614027777 0ustar runnerrunner‰PNG  IHDR€€Ã>aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png0000644000175100017510000006455015232633614030373 0ustar runnerrunner‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-3.3.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png0000644000175100017510000017413015232633614030355 0ustar runnerrunner‰PNG  IHDR+ƒøIDATxÚìÝxdW}7à3õ•¶w¯{ïÆÆpÌGsòBB ‚ ùZƒ˜lbBŒLy )`=´ÐbÀš{Y—õºlß•V]óÝ;»kïÊiFšÍœû¾ûÌ£Ñh¤Õ½çÎèü÷œsC²*gÞFÁ.@gðú`" ð: Ã(À뀌 ($¯S2F °¼6Èa€"ÈðëÑ{@öŠpA€‚hòס×9@œ Mös€×Ÿ×2 XÀ  @¼îrMú{(Λïÿ(D€:¿Þr^ë̲ /ÌÁÿ‰¼Îjð½^ÓÙU¨ñó Ê¯±\ül²Sà×#8@^[~On^×Þ'澘ŸíÏ*ÔàwÀëªÊÏÏUáÿòZˆC5ÎêªôàõT…ç×âk^ÿ þj…Bx-Õ¨ðÏUñgy/hþ‚¦Å}¡FA€@^C³(ÖsüŒ\_çÞâ*ügó˜@T©øŸiá_­pÀû@óåê…*=G ¯þ•~>ÛÀû@ã‡3-þgûy5~G©â¶…5CïÍTzf¿0ƒçUú˜@™|Í”{¾ÜB¿Ú@-_ÿÞS…{íÞtEy¥÷+ùZ¹Û*@ô¯•jžáŸêþž[K…ÀL_ûÞ+æ&(˜É<þÉŠùÂîÛøîÛl!€ÿÿ•Üßû±´èoMní»o-»o•þ.Þ š+˜Iávüéç£Ém ¹ìL"ÕjÀ¬‹ÿrβ— Ê-üs{ÿmÉ­ëÌ/]ø¦Îýæ½ZP®ïžò…»ѽú˜…Ý÷ “<¶wŸSÐ @ñ?õc•œÝÏMñqÏ™ÿî3ÿý‚7'Åÿ«4j ûN#XüOVì禦 „Ètñ_nÁ¿÷Çü>Åÿ=—h"f e’>éT#„PüOóX¥Cû§;óß¶»ø“â€Yöus“üaŠ@ PFQ¯È€â¿Ì Ôcû?ã ŠªLWôçÊ Êýhêâ¿’!ÿ¹ €üÞÅ×=¯ÔDT9(5쿜À(d¾øŸéÙþ½ï?:ìÿŒë/økÅ?5 &ªtø%!€€@ _üW²Ø_©â¿œ¢ÿq þqýùoê:¨çÏ45 ¡ô¢€!Tg húâ¿Ò!ÿÓ{ù?ÿ¯»êUüPíþoK(½ÀdŸWs*€AQÿåœõß3çWñÿùóߨø ZBé)“…!ÔfQ@}ñ?ÙçûžùO‹ÿƒÿÔ¬<Ý!L=% ÔÏ5 @™+þ+ òŠÿWh"æ((L7(þÃãÏöO~æÿsŠ&˜„PÝQ )ŠÿÜ$o !”?Üï3ÿékpÞéŸ;ÿ ]‡(þ¨[žˆ¯ð{«9 @8 €¨Šÿ©€G‡ý§Å·â€úõ‹§[pº>s%£@Sÿå.öWê±=Åræÿ¼´ø¹& Nö.þ'Ž(LÓwžlxÿt£ÈDñ?õ™ÿK‹ÿùŠêÝ?žl$ëÄû…iúÏ…*ý.Âd ø?Tñ@Ã…÷'*g‘?…}ƒj± Pü+þÈT?¹eŠ~ëd!ÁtýéÜ4}ðœÝÞŒ@ñ_¿â^Rü¿^ñÀj ûÎÿ/Õç-LÓ·v†¿Iÿ•ÿåÞZÿ4Xyº³ÿ!L?`ºþ·³þ Èÿ3+þ§{óLõ½‡ý+þhÔ „éרóy˜ä9{>ŸêjSý>FÔ‰(þÿrSô…C‰>q5ûë ©ŠÿÅ?ML̤¿¢.þ­ö@³S…Sõ»Ë½Rˆºø™& ‰€rB€Éž¯à@ôÅ‹â€È€©úÌÕê«#€¦+þsŠÿy§ÿ«â€¦ ¦{N%!@n–¿hªâÿõ݇)þhŠ T_wªyÿ¹*üß@ñu¦šËŸ›¦O­°€âš¨ø%úÃ¥úÑ!”^$p&ýx ø€ö­seþ³í‡#Å?4PÊ*-îPü@ÿå\(þ  ûÙSÍëŸnñ?€ÿФ!ÀLæÿϤÿ0ýíé.ïWêk }(þ ÉúÞå† (þ ÉûÞ¹2¿& €âš°ï=Uq_é:¹*þ^Pü+þ Fýp‹þ @ñ÷Ãs3øž‰×s¤ÿЍq]/Å?4a_|&W@Š(þ Yúæ³] Ð(Þ`ÿÐ`}ó\Šv€Å¿â¼¯x€â2Þ—GŠPÔ#À‹â@€â_ñ ÑoGŠ À†â@€â_ñ @ñ¯ø€ÆêÏ#Å?¨à…¯ø øWüPü+þ ¹ê(þÿÿŠŠÅ?€Å¿â@€âŠŠÅ?€Å¿â@€â_ñ @ñ¯ø øWüÀöÿ øWüPü+þ(þÿÿŠŠ(þ ø øWüPü+þ(þÿÿŠŠ(þ ø@ øWü Pü+þ(þÿš¥øŸî{ÿ"(þsŠÙ ÿš¼¸Wü Pü+þd­ø/õ=Šÿ ü‰÷ÿ"/þseÜÿ0¨FñߢøÐþdÏ/µØŸâ@@ÿ3]ñºùþŠ TZüçBesþ»ÿÍ©Õ.hª¿ÞÅË>Åÿ¿÷†îCÿÍÈ€æ,þgò}åùWühÐp 7Åsf2ä?§øPÿ¿Ü⿜ÿK…{ßZ÷*þ_¯øh~Öh®â?Ì øŸ¬ðŸîÌë^ÅÿË5 0QWKgèÎw‡žäÖïÚ}^ñM$ýøè™\kñ¹{t´t„ÑÂh+Œ=úØŽ±¾Gï§ï ã…ñ°slgòµþâÇã¡l Ùù€L‡¥FTRøï{©?Å?dJ>—‹Z„%m‹Ãâ¶…aiñã¢äã¢âÇ%É­7ßzZçí.ôssò{‚$èK‚­£ÛÖѭaÓÈæ°ydkØ8²%ù¸ë–Þß:ºmŸ @@3øSù¥«tÑ?Å?d È_Þ¾4¬n_Vu캥÷ê: ìß±:´äZšbz[{Š·ô÷Ÿ.,xdxcX?üpxph×mÏý{ïOF ;(M”;ï¿ÜÿÿEÉYüû‡wë>8ÚuPXÙ¾<’ŸÏÌ>HÂ=AGè}|8ðÐð†pçÀÚpçε~Ü”ŒPÏ¢¾Ü¯M7ôªï+µÚ¿âšÌüÖÞpü¼£Ã»‹ýôc:”Ÿ©Ãý:Voç,<óÑÇÓ©{€ÛvÞ~Ówsqª€€F rÓ„¥n-Šh>é¢{GwNžB8¥÷„âYþ¹š“›týƒÓÚžN›ÿ„GK§ ü|ǯÃoûn ¿ìûmqZ@,Å$ÕSå/õqº[Ë^Åâ[GK{89)ôOR8±çØdÎþþ þ9´nh}øÕŽ›ÂO¶ÿo¸qû/à+ÐD¾{ÊÎM>lMn#Éml÷m|’“Ý “|œì&ÜSÜeêŠð•ß ]]Ø1Úg§QÇ&gÍ €¿‡UxN% ªX`†×t·W®ùã°0  –ÇZzéÈsžY Ò0@ÑD Zr-a¬0fG(QèO·øßdóÿË € Òu`xÍþ¯(Ó†zémí uÀ+‹ÁÓU÷}$Ü3x¿B“wrtAÙ,ìgúü©þs@¨²Ž–Žâ<ÿô²~­¹¼œ8¾çèðOG_þåá/†O?øoa´0j§Ð”ZrIÄ`€``VÏ)5ïªð˜ÆAû‡KþËâÙ˜ó?ܹÖð‡+/N.xR¸|íº¡õv MØéi±æ€wßæ ¦þŸ+ñX©‘@É[.9ãQøÈÑW(þi8Gt>zôû‹Ç(ÄÔÑ vŒhŽ¿Ó­þ?ÕóM€Xغ ¼ñÀW‡Óœlgа:ZÚ߯ù“pBÏ1áÊûþÑ•hé"€ÌÁû¯]0'}=‚\p˜‘Óæ?!\{ÌUŠšÆ“ž>zÔûÑ݇Ù4I‡H@ ˜ésr%>–z®JH/¹ö®CßTÍdyûÒð÷G\Î[|¶At@uAæ‚)ÍLUÄOuÆ_áä“•ý_ ¥~β§Û4­ö–¶ð¦ƒþ_8¸ë€ð±>“,²n™u´C“ÓPªÈ/UØOö¼rWþ7v›ßÚÞ~ðëÂI½ÇÙDðG$^¸âyauûŠðÞ{ÿ! Û)4œ]€9zÿ¥Y‚€rž;ÕâÓ=™t`çšðGþ­âŸèœ³èIáïg2e¾A“wsPê/¨³ÿP¦Ã»8âoªŽvQ:zÞáÉ1~yXÒ¶ØÎ ±: ¦2V¨Wã{sSÜŸêì5~'hjG&×P¿ò°·‡Î޹:÷KF¼#,ÐP"]P€` –?«T@™s|ÏÑáý‡¿=ô¶öØdÂþ«Ã|WXÕ¾ÜΠA: º ¦+îK áŸêì¿¡ÿ°—{Ž ï=ìÒÐï¶3È”•IñÿwG¼Ó”£Sc €€²çóOöy®‚Ÿm™”.ô—ÿ]-v™´¢}Y¸2ý²¸m¡Áw@uAÔŠyÿd^z]ôwò†ÐÑÒngié4€wúfAsÛ11@À¬‹ôrýsöŸLI?{Ï¡o =ùyv$ŽHÁ¼ì׆|.og0GÝ3 rÓ¥žë¯/Ñ›—ÌõO‡ý/o_jgÀ^N›røËþÌŽ`Ž: º ê@&´æZÃ;’aÿ‡thgÀ$ž¹äÜð‡+/¶#¨ÇÄSïÓ=ž«ðû!z¯?ðÏÃɽÇÛ0…—®~a8sÁíêÜÕ0[S…¦)ÿgéáüÅgÛ0íŽ\øëƒþ¢¸8 Ôó¸@@å…~©ùÿ¹ ‚ˆJ:äÿUk^jG@™zó=á­ÿUqÚ Ô¥šÓP«‚ÝÙ2£;ß.;øu.÷:jÞááûý¡" jõ³ ^¹ð†_öï\mgÀ \¼üYáÉ Ï°#¨CT@ h¯ÅÏÏÕùw9óÜeÏg+^`Lráu^–´-¶3¨í±æ*¦-òs³ü~ˆVº€ÙËö{‘³”®ðÚ^iGPã¨n € ›E}-¿ß¥ÉÈ )Þ˜¬bÞÕÒig@œ±à”pá’§ØÔî}Û"€ê\3A$ž¿ü™á„žc쨢W¯ùÓ°¼}©A: º!sÁõ~â-è'[ñß_[¢³ºceøÓÕ†þ7¢¡ñá0\.Þ/Œ‡cû|½£¥#´µìú3”Oþ¥Wp qÌËw‡×ìÿŠðæ»ÞmgPƒN‹. €€© z`’äë|UèL Iêc¤0Ö=6o F6…‡‡7† ÉmóèÖ°c´/ôõo;ÆúÂðøHE?;ŸË‡žü¼dú¼ÐÓÚ“Üï‹Z„eÉYèemKŠg£ÓÛŠöeÅçQ{{¦|cÓ÷ì ªûþm@U üU%ÒÂäÄžcíˆY7´>ܾóîpÏÀ}áÞÁÂÚäãúᇊgóka¬0¶n/ÞÂÐÔÏ]š¬R`×þá Îô¶&ÚuP8¬ûК„Tןí÷âðí? ýc;í ªØaÑU(Þëýsüõ¥i¥ÃÅ_¶úíˆ*IÏìßÔw{ømÿ­á–þÛÃMý·…í£;ö÷Ý8²¹xûùö_=úXGK{8¢ûÐp̼#±óŽ 'öS\ÑžÙY˜ŒÂøãUÿ7\³î“vUÓb*@¹^¼ò÷Ââ¶…vÄ,lÙnÜñ«ðãm7†·ÿ²éÏð¦kü¦ï–â-„/†–d•ñúg.xbr;%žŒpÖqfž·ì™á뛾î¸×Π*LP§¿¹vÍnMÇêdåÿ‹ìˆØœýßÝòÃð­Íß·í¼+êmM§*ÜžlczûÔƒÿZ\?àÜEOç->;Üu€ƒ¡éú —ì÷Çáõw¾ÓΠ*\@P–?_óÒd®··¯rFÃ÷·ÞœÁýNøÅŽßÔl£{$Y¬ðŸþ÷â-]3à‚d ‰§/yªie:eþ‰á¬…§'ëüÄÎ`Ör9SÔäo¬]@LN_prñÆôÒÅô¾¼ñ¿Âløz̗ؔç1w Üþ1™Óþ‰õÿ\ .^ö¬°çj;fé(€¶ý¼*Î € †Æ\x¹…ÿ¦•^žïº¯ßÜüÝâ¼xJ _ÚððŸ¾Y –þxÕï‡#“…™ÜªŽá™KÏ-î3˜ ‹¨uíMî)‹žé:ÐŽ(!]µÿ_þbøÂ†¯(ü+THþ¥g¶ÓÛ)½'„KּıV­üÝðMÂ%fÙ)± Àœ¿Íñf•ÌMÏÎòxépìϾþ³açØ€R%éB‰_IÖOøÃ›ÿ¼¸ŽB:B€Ç¼pÅóCGK‡ÁŒ¹$'€€JÿvBF´&— {ñªß³#ö²slg¸òÞkÂknk¸gð~;¤FÒ—ŒxÃS¼Š»,n[ž»ìév3 ˜Ì…É¥ÚVw¬´#v»mçÉõׇ¯nú¶3Óuòóí¿ /¿õµáGÛ~jgìö‚Ï ]-v3$L|“JæþÿA2ܘ] Õý[²Èß_Üö–°~è!;¤ÎÒÑo»ë}áCë® #…‘Ìï­óÃ3’+ÀÌ: 3á/(Q;kÁiÅKe]º°ß;î¾2|øO»ûJC˜ëùJø«Û/ ÛF·g~\¼ì¢bHw^7€‰þïŠgg~¤…æî|gøþÖ â¦þÛ«nûëpÿàúLï‡4œ{ò‚ÓÌ êü€`/ÇÌ;"¹™é}pïàºpÉ­o,®öOcypèáðÿnK¸9 ²ì÷VüsÀ„Â"Ûgÿӳ˯»ãíá¡áG *ñº;Þ~Ýwsf÷AÒe=¨cPS{¬l_^œÿŸåâÿ¯îx[Ø4²ÅÁÐàLJ›ïzw¸¥ÿŽÌîSu¨”€G]¼ü¢Ïå3¹í÷ >^sÇ[ÿMdçØ@xãîØ¹6“ÛŸ†uËÛ—:*ÓÞÒ.Xü”LnûöÑá-ÉÙä-#[M¦o¬? ð®°adSö:Épîg,yšƒ€ Ž€ qÎÂ3CokOæ¶;½¼ßÛ×^zÈAФÒQ—Þõžâ´€¬yÆ’sÍë¦lFvçen›ÓëËÿí½W‡_î¸ÉÐäÒiï½çƒÅ6Í’t À)½'8(¯*,¬îXNì=&sÛýÅ _ßÞü@$¾¿õ†ð…G¾’¹í~f2 Êa€ 'SÛ<<>ÞuÏÂÐø° 2#…‘pùÚ«2Õ¶­¹Öä5|¶ÆgúÀõû»kЈÎ\ðݤmQ¦¶ùÃ|*Ü=p¯ÆÔ½ƒëµë?›©m¾pÉS5r_ØðÕpçÀÚÌlï!]†;×hx¦d a]-áŒù§df{Ç ãáïîûpñ#q+Œ…Þÿ±L]à)‹~GÃ3uÔ]OZxjèhiÏÌöþû†¯%—‹»[ÃgÄoûn _ßôÝ OÒèLÉ"€ Þš¡3†}cýáÓý›FϘ¯ÿL² àP&¶5N€’P#@6õäç…S矔™íýç‡ÿ=ìíÓð³ydkqäGV˜ÀT¬07Zí`®µðôЖkËĶnÝþ㑯iôŒúç‡þ=\´ô¼Ð›ï‰~[Ÿ–|„ïœ|½r=¡÷¸G¯KFÌËwOùüt˜ô2“%;´É׺Z:¦üiØ<Õõ;“ïo›âÿhɵ„y-SÿžÝù®âóJiOþÖu$ÿÏ­ýw„WÝö×@dÏS™™mýôƒŸ ãƒ=£vŒõ…ëùrxɪD¿­«;V†ÃºÎÔ(ßióO.Þ²jnî¿-Ü5pOôÛ™Žò™ê²hEcF k²²Bø—Íý§„¯oúNôÛØÛÚS\ xLÁ€È’tèÿá݇D¿é¥ÿ~¸õ§œI}sógâʧfd­(—5)'õW\0úoÓ÷’ÕÞG58“Ú1Ú~°õ†è·óÄÞc46Ù ÷¸Llçmþ¾ÆfJßÞòƒè·ñ˜yG„Ž–v {‹ [À±Ñoã}ƒdb‘7fçÆí¿Œþ‘m¹¶pt»€` @dÄ’¶EaMÇêè·3 gv™½ÑÂX6¦ô«±aO` ²"+Ãÿ¿»ùG›òŽ•-?ÊÀë^{Œ@f€ œ ¼cçÚ°nh½Æ¦,¿ì»©xň˜Y3f ²âÄ Œøñ6—þ£|épà¶ý"êm´<¦à*€È‚%m‹“ùÿ«2ܨ±©È 8fŽï9ZCC° 2âØ œÜ8²9Ü™L€Jü,¹ÀHa$êm<ªû0 ÁUGÍ;<úmüáÖŸXà‰Š Œ†_ï¸9êm<:¯(+0™ºã/~²ýš¹!òcgaë‚°¼}©†&ó¬€èå’Gtõ6Ž%×tÿMß-›ùß¿‰~î6 \Ñ;¸ë€ÐïŠzoî¿=ìÐØÌÈÚû–‘­Qoã‘󬦉 zY˜ÿû‹ œÁ¥¶EÁ¯úâ^ÀB€` @d@:þ¿Øñk ͬüïŽßF½}GtZœ™Œ@ô@ä#†Æ‡Â-ýwhhfÄ=Š$t@ç~šlF fm¹¶p`çþQocZüF56³²nh}ôë¤ë@¦W@Ìì\Zsù¨·ñ·ý·ihªâÖwÆt Èx` ¢îðgàŒßͪv,ÝùûÁ™Ls@DíÈ;üigî&€2ߌ ÛÆŒ€ yÝ7ø@Ø1Ú§¡©Š[’`¬0íö­êX:[:44™U° bû€[ûïÔÈTÍ`rE‰{×E»}ée2 € /˜€Hõ¶ö„¥m‹£ÞÆ;îÖÐTÕk£Þ¾ƒ#¿*L€Xš¿îØ) ºîÚyOÜ€dXÁ@Äê È/ù•.x×À=šªº3òcê —$ÃÆŒ@¬èÜ/êí{`è¡°sl@CSÝ`çÚ¨/¶_ÇJLf\±ZÓ±:úB ªmÇX_xdxc´Û·¢}Yh͵jh2É€ˆVìgúî¸W#ãØª´’kI.¸\#“ÍÀ€ˆQz†/=Ó³˜/×ÆÜºoð¨·oµid50qvðWÏôÅܯ¡©‰û#Öt¬ÒÈd301Ú/òþha´¸ ÔÂ}CF@”€€ˆQìgøî\Æ cššˆ}z‰+U®€8€Î¸óÿ©¥£}aëèöˆ€Õ™L2QZý€42ޱJ}˜4° b´²=îË|­6ÿŸcCG»m­¹|XܺP#“½À@Ä&—ü[Ú¶Xq³ðÐpÜÇØòö¥™ìÖ@l´ö†Ž–ṽCD½}ËÚ–hd²Ì‘V»¨YÇ>ò3{Ãã#aóÈ Mm€ÈG,3€54>† #“~­lg²’ÿãçñ%ÿvŽ ”øyÃþ¼Í#[í`@Äey[Üû´0+ 9Qããl(ö`nF<í7ô~ùÎÉ×GÝîWÝ÷‘b=6Ù™ð¤°îëŸôûF £a0)Ì'30>FK\–µotòŸ7šü¼ñAo4€ Y;öõ²~È€ÔÞ¦d”I:Ú¤½¥-Êí[n @&}yã Pæ€5€Úuì#ÚûððLÍ¥EÒ†‘MÑn_ìA!@6ŽlÖÈÔéX‹7Xj€æûêÞ†7idê Ç6-i[Zrº# šÚÒ¶Åq#êD<Ú$ŸË'— ¯‘@4³Em ã†7jdêÄ6-j] ‘@4«Ž–ŽÐ™Üâ.ʬ@޵á¸5#@4±…‘wèwŒö…¡ña M}€Èæ…Í+öáÿ›G·jdêfËè¶ÈS@4oy‡~k䎷úF€Ð¡oÔ‚lD@ýìÃã#ñ¾_´ @4q‡>öÛ52u>æâ ˜ ‰€VTÓ¶ˆ9—ÐÔ@äS¬@ݹx—ÐÄzó=Qoß6#TMO~žд@kÜÀöÑ™ºêëvÛæå»40€æíÐwG½}}c;52u•^ V-¡5—×È gÇXŸF¦¾Àø@ÔÛ×ù{€x€–ÈGŒökdêŒÅÌ€h>¹ä_W¾3Úí+$ÿúÇM ¾"{h ÎŽ|r&/ bÕŸÌÿ/ŒkhêjçØ`ôï€Ð‘o¸êÄ}ܹ @b™úwÑ/èR€  fp|H#SÿÀ"€€h4]-qŸÉÔÈÔÝ@äÇ]gK‡FÐ|ùv…TYì#Ú[Ú42€æëÈǘÀœÉé%(cÕ‘3@óuäc0fõ—^zrx|8Úí3@3väsF@-Ä< ö‘C "íÈÇ}&/æ³°4¶þˆ/Ø! #ßhF £™91ñ±ûÈ!:òMh<ŒidæÄX!ÞcÏ šPì#Æ’ÅØ@På÷ #@4ŸØó5€9 â Ÿ,  µåâÊks%ê5LÐ|ZsùÈk0WÇ^¼áS‹. €&|cÉÅýÖ2f@{Þ7@B>ò·#pìU_.ù€fëÈçàØ«L>ò©C "}c@mŽ=k ä£à*Ìѱg @4ÖKÜo-1_Š"}Òb Í'—‹»#o€tHŒÐ|¢¿ €Ë"€ þ޼EqìÕ¢C¢K éä"kÌñN?ÉY@ó)„¸çÈç½u2WErÄ5òx°¶€&ìÈÇ}†<ŸËkdæèv¼Çž©5 š1ˆ|•ü¼Åʘ³c/Þ`ÜÕ5@4Ÿø§€ Ú\]@3vä£ `®Ž½xÿl ù¢_À['s£5×q`€¦3nÔèØ‹÷϶«€hBcA59ö¢¾ €@Ó)âžÐb@æ*p@4TG>¸ *c :òŠ0xô¶5Ð@†ÇGP­F ‘Œb¼u2WÇž5Ð@†Æ‡ã.Â,ÈœñþÙ3@óŽ=0Ç^ Þ7F40€f3Tˆ;h ¨þûÆøÐlb?“×ÕÒ©‘™m¹¶h·mP  €ÈGtå»42s¢;âðI # 6Ç^ÄáÓàø Ð|@Ü#ºóê/—üëhivûb¿z€8€Ø§´˜ÀwI𔆱2@ˆ¼#ßm æ"ˆ@  Œ †ñÂx´Û—®Änõâ>æLЄ É¿ØG¨·Ø§ž Ižà¼|·F¦®:#Æ52€fûB€FPgó"°c´O#€hFÑOÈ ¨ó1qè4Z3@³êëzûzó=™ú‡N}cÎþ€hZÛ"λ°uF¦®æç{#~¿Ø¡ Zí 6úmQoߢ¶ù™ºZØoèdþ?”%Wæó  Î@ÜgôŒÀ1WÅÀ˜I¡_É÷@ÍlÝõö-à˜@cüeÿ &¶EÄ<›Æ“ÏåCok¼ Oš€¢¿>€`&€Ôõx›ŸôrÑnŸ(ü€ a™@}€¸·£ýE¸ P±¯ÇnM†eC]€È§œ@Ä…C áµéÐ'szÇ ã¿›ç‚V—¤>bq²Ý(ü@ó*$ÿ¶G~VoQëB M]Ä6õ€ÂªŸWéMÔßæ‘-QoßÂ6#¨# )Šÿjû³ùYi­Ÿß}Ë €šÛ8²YQUû›"¯ úÂ?7ËïÍÕàwJ ÿ¶~ô£Çyä‘m{jW3-ÊÔIÌaÓÀø`ñMXøÏÅ÷N§ewßþéOú¥ù|~à¶Ûn»iÏÿ+j G´ ¨Ó±qàì?)þsux~zk[±bż«®ºê²®®®³ÿäOþä콟$jŒlŠzû–´-ÒÈÔ'h‹9Ø¢PøWgÎÇsŸûÜU/zÑ‹®MŠÿ'%gþŸ¿eË–áäñôÒ\ c? ËÛ–idêÐÓÈ…¥‡M2\øçªô»¥óý;_ýêWwî¹ç~º­­í;v|鵯}í÷“ÇÇö~²¨™ØG¬h_ª‘©¹Åm C[®MÍQüçªðóÊý?÷Ì÷ïxï{ßûÌcŽ9æš–––ù…Bað?øÁ»’LJÂcgÿs ¦6D¾À²ö%ų³…]#ª &–G4 PøÏ|¾rëþÈG>òûí·ß›Ã®‘aÆ ¾æšknOîŽì.þ÷I jbÛèö0R‰vûZ“uT­@퀸§šX€È‹ÿR—ù+瀹In-» ýŽäŒÿ’Ï|æ3×$Åÿ[÷ÿccc}øÃþ`rwxbñ_ì¿j[ VÒ3ã›G¶&Cåã-`Òâl£†ZcmK¢Þ¾ô="-ü«ñøÄç‹ÿ¿øÅ‡=ûÙϾ¶³³óø½Ÿp÷Ýw¿ó§?ýiÚ9Û+Èí¹oPSoˆzû¬@Í€ÈGľVQÿ¹i ù\™çÊüY{ ÿâÿw¼ãç^|ñÅ_›Xü üä/ÿò/¯“ ýßós@M­z8êí[Ù±\#SãÀ¨qá_iñ_îÏ™¬ÀÏ•ñܽ¿¾gØZüÏûЇ>ôÊ“O>ùŸóùüijPã7ÜpÃeÉÇÁðØÙÿÇý?¦5õÐpÜÀêö•™ÚcñcCãC¡l§F`.‹ÿjþÕ|,LRü·uÔQ ßò–·¼oÑ¢E¿7Ù7lÙ²å_Þÿþ÷ÿ"¹;Zâç@Í=ù€5«425µª}E´Û¶Ñhü¶Ånß³ç±â|ÿ?øƒ?8ìùÏþG“!ÿ'LöKŒoûìg?ûÞðø³ÿ!LX@ÔÔ‘ûu¨Åm Cw¾+ÚíÛ0lþ? ]üײðŸêg¤gýÓZ½ó²Ë.{Z2äÿêdÈÉ9ëÖ­ûà×¾öµõ»‹ÿÉ~æ£!€¨©Ø§¤—ìléƒÉPf¨¶Ø¦õÃid±ø¯duÿJ>/ç¹Åùþ݉+¯¼òUûï¿ÿs¹Òuûððð]W\qÅÇî…ÿÆ'ü\Wê+]àk`|0â¿"¹¨çh3×@ÜÇÖú!u+üg[ü—Z̯œÏ'»?ñóGÏúŸuÖY«?ö±}ò€xËTÅêæ›o¾|íÚµ;ÂcsÿsS…F5÷ÐÐ#áà®".ÒV…»îÕÐT]ìáRìk„Ð0Åÿl ÿ©+÷ŒÿTß“ß}ëxÍk^sê9çœómmmûO÷ ÷õõ}çÒK/ýÆ„ââüS€:wò“i1tî§‘ÌÀzs_øWRü϶Ø/u9Àô]É*þ/:âˆ#Þ™œõïœî. #ßýîwßÜ»†þ?n¸ÿ„@ÀU€zuòãæ{Pçþ™š8°sMÜï Ö`n‹ÿjœõŸî~©¯·ì¾µ}ôÑ‹Þô¦7½{ñâÅ¿[înܸñ_>ò‘ÜvýŸì¬˜Pü» P÷®»HëZ£‘©º–\KXÓ±:Úíëë;Fû44‹ìB ÿJŠÿjþ{LkñŽ—¿üåÇ_xá…W'—ø;²Ü_<¹ìߎ뮻ëìÿØ„}7ÕS€Ú»gðþ¨·ï€Ž5Åbm¼0®±©šÕí+CGK{´Ûg@ªÌöù3î?“¿¸Êrëzï{ßû¼cŽ9æÝ---=•üò÷Ýwß?|ûÛß~pŠâ² ¥ø˜«5wïຨ·¯½¥-)ÖVhhªê ®¸§–˜ÿÀÿ¹ÿS­æ¿÷c¹)ÛSøú;òÈ#—^{íµï=î¸ã>Xiñ?44to|"ìºì_¡ÄïS*°P{ÛGw„­£ÛÃÂÖùQkë†ÔØT|m W`Š"½Pæóf”{Ö&gú÷þøè*ÿ/}éK»è¢‹þ¡’!ÿ{»é¦›þvݺuýá±³ÿ{ï³i?ÔŽ‘O8¨óLu©ØG ˜QqŸ õ?ë?Ýc¥n{Îú§Cþç½ë]ïú½ç>÷¹_˜iñßßßÿ³·½ím_ »Îþ‡I~‡©Bˆ"P÷E> àˆîC42Uupä¡’5(³pŸlˆýl‚„ÜÅþl þ‰Å:â¾+™ç¿üSŸúÔU'žxâßçóùžîñüàïI>…]—ý›ìwœªø/Þ7¨‹{ˆzûPEéâtî' †"¾0Gÿo9—»’¥ó»kíŽW¼âO¸à‚ ®JÎú6› J.û÷¥«¯¾úîËþMÜ¿{ ¡ôÕ@½€¸G¬h_V\ã ]ëfëЮƒB>—vû†Æ‡Â#Ã5t†å“Y¨£…1;h„²~º"¿Ô×ZvßÚ“‚¿û=ïyÏK;ì°7ær¹ŽÙlTrÙ¿Ïþóv]ö¯0Eñÿ¸‚â}PŸ`àþè·ñ°îƒÃÛ¥±©Ê±³ôÒ …99!D£H/ÀÜÿ³=ë?ñ~ñ¬ÿù矿ÿK^ò’+,XðäjlX²èß'¾üå/§éÑ …}¨¤øOï €ºØ8²9ú+¤ÓTåXêŠ{JÉÝ÷iäÌ÷Ò-CŠõª%ÁÕ*üË)òKþé›ZºÐ_ç›ßüæóN;í´¿mmm]ZÝpÕUW}4”>û&¹_r{÷êæ®k£Þ¾#ºÕÈTéXŠ;X+ȼ¼ QUüOµ˜ßT_ß³Ð_çªU«ìcû›'=éI«VñŸºõÖ[?xÇwl _øo²@b²Ï÷Ùf#€º¹}àîpÊü£Ý¾cç©‘™µ¶\[8¸+î+¬¸WCO#"‘«x±ëfê±ç42Ð(…ÿd…s%gý;^þò—Ÿxá…^‘Ìû?ªš¹sçÎÛ“Ëþ]v]ö¯œ3þ{¾÷v@ÝݱóoiÛâ°²}yxhøÍŒ5ï°Ðù=w ¦5Z-†A±Šy‘K ¢"¾0ƒï)÷k³™ë?Õýô–¾‰µ%ÿ¼w¿ûÝ|øá‡¿a¶ ýMæÇ?þñ߆ÇÎþ‡ ÿ‰[TÓq=G…‡6 ˜¹ØG’¤klݦ¡§1^1Ÿ$oÓ³ðŸ.Èï¾u>ûÙÏ>ä…/|áûz{{O«ÅoÙ²å¿?ðü8ì:û?ÛÂÿQÞ}ºY?ôpèë=ùyñóŽ ßÚü}ÍÌ€ž¸€»ý/Kz‰¼Žˆ·¯=âÑ À”…z¡ŒÇfZøÏ¶øŸn¸ÿž!ÿ]—_~ùóŽ?þø·åóù5ÚWc_ÿú×?ö]øoâ6•ó¸˜;éœÖ;wÞNê=6Þ ç( Í,zF¹èG˜ÿ_fÏ/òKäµ·´kdÈV¡?ÝógòT«ð/Uôïù<¿»nn?ýôÓW\rÉ%ï\ºté3k¹zè¡/}æ3Ÿ¹%ýs0á÷,”ØþB¹í"êêÎd!À˜€tñ¶t„C:Ò*µ_ÇÊäR™ ¢ÞFW(Ϩ Ò²¾œb²¢ÿqgý/½ôÒ žøÄ'¾3Yáy-7p|||àºë®»&ì:û?^b[g| EPW±¯žÁ=©÷¸ðí?ÑØTìøž££ßÆ»å qÈr_˜á÷MõØlÎúOöùžËûÏú¿ò•¯|˲eËžê°:ËÚµk?ó½ï}ï°ëìÿd«ýÏŠ¨«[úïˆ~ŸØ{¢€‰ù2™»z.…pe‰}@GNŠþªþ“öSûÓÝO ÿ=Cþ»ÞúÖ·^xÊ)§¼£Ögý÷ÙüÁ~ð韽ŠÿB™ÁCYûXÔÕº¡Ãæ‘­aqÛBEìÓSIFôõ6Þ7ø@ÒØe+ŒF½}-²[ø—TRø—*ø+ ö>ëßqÚi§¥gýß¼|ùòºœõßãæ›oþè]wݵ5”žû?“ý½O@ êîæþÛÃY O‹vûÒyÜ«:V„“«@¹é:0ê`,•…@Õ Æ£Þ¾yùn qøåžíŸôõe• ý/g‘¿½Ïúwï>ëÿözõßc``àþ÷½ï}ׇÇÎþ×D‹ã¨·›úo~Oé=ACSÙ13?þcFPI÷4DñÞÿßÄb¼Ô×§+øgzK‹þâ"ÉYÿ5×^{í•Éœÿkê]ü§~úÓŸ^½mÛ¶°ïÙÿR·™r þ~ÛpÆ‚S—7þ—Ʀl'÷ý6Þ¶óN -@Ü¡Ba_Ÿ*0¨æ¥ýöÜò{Šÿ·½ímO?ùä“/›‹Â?µ}ûöß\qÅßJîŽTi_—$êîöäJÃã#Ée Ú¢ÝÆS矺ó]açØ€gZ]É|è“zâÒ×üÝ÷hì2D¾@½/·èÜ{‘ºB—ûÿÎd¥ÿéVùÏï¾uœzê©+/¹ä’7%sýŸ7‡û»ðíoûCaßËþM¶/\hÖŽíHÜŽë9*Úml˵…S{O ÿ½õ48Ó:mÁÉQb©ô5ûÊöÕ{x8/?O#C\A¡ÂçWòœ™,öWêÌZø§—!é¼ôÒKŸ‘Ìõ[[[Ûò¹Üy6løïüã7†]sÿg³ŸËjksâ¦þÛ¢ßÆß‰x¡Cªë¬ñ+¿é»ECW`ÇX_ÔÛ7¿µG#Csü•|=WáÏžjž˜¢¸o)ñyË^…÷Ygµÿ§>õ©«Ï8ãŒ«çºøýÜç>÷á°ëì¡Ä>˜­}‚#€9+~Ås¢ÞÆt€Ö\krÖsTƒSRk.NOFÄî×ý7kì ôE,n[¤‘!AAaBÑ^(3P˜épÿ0IðèYÿË/¿üyÇ{ì[’¿!.»³nݺÿüêW¿zWxlá¿ÉöA9gö “|^ØëñGï €9ñ«¾›Š‹\åsùh·±'âš®ð?ÛnÔà”tRïqÅc%fãÉ%í²°øg5ííZÌWò¼É>ŸîûË)ü§*úÃîÂ?½¥óë:_ð‚ýœç<çí½½½ 3änlllàŸøÄµaß¹ÿå*LSü—ü>0'úÇvW?fÞ‘QoçKž"`Jç.:;úm¼s`mñ5O@ä#–´  ÁŠûRÅw©âºÇJÝŸ®èŸê÷)w¾~wñßqÈ!‡,zýë_ÿkÖ¬yI.—k¨Åvî¸ãŽùÙÏ~öpØ÷ì%gý§ &%æÌÛ}ð¤O ½É\×£}œÇéhéO^xzôÛiþåúÆâ.z™^ P0  LuFºû“M˜iQÎpÿ}ùK ÿ§$óüßÖÑÑq`£íØááámúЇþ5ìºì_¹Å~ašÇ å|E9óó¿Š~Ó«çœs>ÖˆÅꦛnºníÚµ[Âcgÿ+Y8±0Mñ_jþ¿5€¹uKÿíÅK]Å^=}ÉSÃ7|]ƒó8ç->'úmLÁüåŽßjìJ€ÈG¤Vu¬÷®ÓØÐœEaš¯Urö¦ þíSü'Å~÷Ûßþöß?æ˜c^—Ïç4êÎ|äÊ+¯üBxüÙÿ\‰â>”(ôÃ4AÀ¤ß/æ°0+.xf2L>fGvŽšwx¸µÿΣ–·/ §ôžýv¦ÃÿLJ4x…b¿ @1h_¡¡¡1‹û™þ“ÿ•¬ü_iá¿g¸:¯¿ãe/{Ù.¸à‚wtwwßè;øÆoüä¶mÛÒ”·œ…ÿJÓ(É`Neehðï.–ÆfÏYöôÐ’‹ÿÏð϶ÿRcÏ@ìWH­îX©¡¡± þé öRC÷'>6ÃüK ÷O ÿ®#6ŒlÒèÿ{Ö’ó3±­7fä5^õ #Vw Tôç¦)öËYѿԀr~—rÎüï=׿ó²Ë.»èÄO|S{{{Ó¤‰?üá?>::š‹/cŸNu–¿Ô× ÓFs*ÿ¹nh}ôÛٚˇç.†§è‚dîzuˆØ=<¼!Ü5pŸt}”tý„˜Ô¹¿††Æ raêùù¡D±BéÅs¡ò3ÿé-=qÝ‘Üæ½èE/:áºë®ûä©§žú÷ÍTüoݺõ–«¯¾úûÉÝÑr õ B€ʼ@ú˜˜s?Þú³Llçs–^æ·öjðÌ÷¨ráùË/ÊĶþhëO“ÞGA£Ï@ºß6ŽlŽzWv,½ù UôW; ˜ÉÐÿIW÷O÷[‘÷Á þ?{çG}¦ÿ×ê½[ÕêrÅ4 ¤¹”#—Â%!„;ÒŽ$—ÜýÓ.—äH¹¦0¦cŒ1Æ`Ó1¶%Ù–mõÞ¥Õêÿ{FŒ¼Zm™í³3ÏןùlÑîÎÎoGò>oyÞË×çååÅ݈¥7Þª.&d~ï¿W_÷ž  Bˆ ØÚ¿ÝÇ™¡f^ÿsÉÇøÛœ Ζê´E¶8Öçû^â]Ö V—^ÍšØ þ@Kõ©¦Ï[Ò;[šr÷Ϲîºë>÷óŸÿü™ªªª«,XwÏ»ºv¨Ñ„ÈxMIàÙo‚?òÿÙÇ3@‰9o5JÏdŸ-Žõ²…ÔÜ߉=éßçK?e‹cp ÊÎá=üÐCÀž! µü  ‰­øbÞ›¸wø¤øOð üåx¹Ö5×\sÎwÞ¹nåÊ•?MJJ*ˆÓµv®_¿þ6™Éþ{ øþ¾Ä¿À9ûa€sPêúBÿ˶8Ö”„dù\é'ù¡Û”^(•iå¶8Ömý;djzŠzX½¬Ì\Êšsø „º%ÊñrÿÌ|à *cþ'uyw<¸ûû¢¥¥åù|p—xîý7"ü½=ÎhÀœû „˜D,l·Í±~°è"Yž¹˜ºÍÈHL—Ï—}Ê6ÇûtÏf~è!Ò9aý €S³OÔZ!¦  ,ߎýF³þºðGYFIIIáõ×_ÍÕW_ýDQQÑDâû„Ó霺ï¾ûîùcÿþTøºBˆyxeàMÍõÚÿ».oUý«6€Ø‡«Ê?§FAÚâXáþÿÆà.~è!Ò:Þnùc„1*Û‰™Ð7bÚg¤·ßˆð÷ ÐúüÕ–õÃþðcùË_6,^¼ø;‰‰Ê8É477?µiÓ¦f9^úï+KoÄÌOÄw€ß*!¦`rzR¶¼f›ã…ñÕå%—ñƒ· 'f-—,¼Ä6ÇûtϺÿ‡cm¶8Î3sNå‡MHì‚Þn{ „RþïšõŸíó¿êª«Þ½fÍšµgœqÆúY¦ONeÿÇUÃßÄ{￯콯*ßž‚ ³× „˜†=[lu¼ŸU^õé5üà-NjBŠVña§2ç Ý›ùÁ‡# *ìH¹¤ð|~Ø„˜#àM¸‹_òï*þõŒ¿Öçî¹çÖÞzë­¿úèG?º6++k•Õ¶©©éÑ×^{­Íƒø÷gÜç-àÍàoÚÇ6/À!Ä4lxUú¶9^þ¸î;Zo8±.ߨü²T¥UØæxßÚ%GÆñƒãÎq5!¥×òǹ(µ\–Ñ…XŠÙÿPKý]ûüÓ—,YRò‡?üáÚo}ë[O-\¸ð­¨IÇÈ7Þ¸Vfzÿî"<áhÿ¿xØÇœë BÌóÇR9†?Û»ÍVÇ\‘Z*ß®ú7~ø®ÿïW›x¤k?ø0rtÜmS#R !QþFzû>ƽÄß½Ç_þ©©©¹ÿû¿ÿ{Å/ù˧kkk¿¦úü³¬ºÀ»vízXUÀÉÕ!þ{õ½ ÿ`úÿ}2@1O÷?ÿ½òñâñ÷hïøºÊþÛ Tðlé}‘~94vÄÇyQþÙR¶ˆ8!±xº?Ð>ÿDá¯ü}÷»ßýÀ]wÝõ؉'žø“¤¤¤"+/æäääÐ 7ܰN|gÿ½ w#SŒT°€ìÞ+-cö+þ·E_óòÞÃÀ"%ÈOë¿§õÿÛ‰'»ŸÕ =Iøh=l‹ãLX WW\Á‘€„ÄVøkê— ó³þšÁß7¾ñsaðwÎ9çÜžž^o‡E}óÍ78|ø0ú·|eÿ ÿio¯+ž„¿~›BˆéØØ»ÅvÇŒ/½ÿYó Í-žÄ7Ùª¢ñ—‹(%) muÜ0«{”åÿaçàX‹mŽõÌÜUòÅl ÄDÂ_Äxù¿žõGÆ?ó3ŸùÌ©wÜqÇ _|ñÊàï»,ìøøxߟþô§õ2?ûo¤_ß_@Ä{5€§×ð„ól:B ¦€?­ûž4¤s&v¼‚Œ?2ÿ5i•¶;öm};lÓ¯MìR ó•ŠÏË HH´ÁT¸ôÓœý/½ôÒ†›o¾ùW—_~ùº‚‚‚˜˜à$''KfffLT¹þ¯ëè耣õ”^öˆË¿·×sß×¼K!¦£U¾zuð-[{vR–üfÉËŠÌ¥<⌴„TùYýÙ¶Šã¾Ž‡yDø*ôLöÙæx“$© ÚÊÅçòÃ'$6Â_ƹŸ«Á_ÆòåËË”³ÿw¯¹æšÇKJJþaÁ‚‰±þUUU¢ö/ÃÃÃQ_Ô±±±î?þñŠ÷ì(â_Ä÷(A÷ÏÂ!Ä”¬ï|¶Ǟ•˜)¿^ü#95ûDžqö™­²égÖ8²_ÞÚÍ!bë»ÏVÇ›¤tZ¢~¦Å)E<‰\À“Ø÷•ñw5øCÆ?£²²ráo~ó›¯]wÝu”³ÿ—¢o~á_]]-§vD¸9óÔíÛ·¯íëë’ãÙÿHˆ_•îO—Ú‡G!¦ãïý/KÇD—m¿ü!›üsõå÷ºƒçú^à ab&ÊÏþKsý·+kÛ×óDˆpà=¹ï²Ýqã˜OÉ^)Ow?'Oö<+{”Il¼üýNV-] ¦.HQí])êz†v™ª~65í­}Ûyb3‹qýN·çh™ÿ¬oûÛ_¶lÙ—”É—5ÿòòr©¨¨ééiÙ½{·(“iWÙÿ'eÆøÏéçáÁ–ýûsÿ7â30Í!Ä”8§òp×Sreùgl»ø¢øÃºoÉšö‡dõÑ¿ÙÒÁì¬ÌZ&?®ýŽ$çÙv ŽŒ·2Haö ï·í±§'¤ÉG^ªmÇ”ÇÄ[C{d×p“4© HÇd·ôÙ³Îä„$íï,Äyò‚dm_é‰é’¢®g¨Ë4uÞ,™êçºÏV¢âÞóó’Ôó2 ýÎ0@LX ÆÌÿÜ„Æ×¿þõ¬\¹òK©©©e±xójŒ &ú±%&&jYÿ;wÊèèhÌô…^¸WFå¸ó NÿþÆý‰øŸ /î?g€bZïÚ(W”}Jû‚eßÿ¡ȧK>&•©rÝ¡ßËÈÔ(O “ð‘¢Käk•_Òz–íÌ­÷i;9ìÖàòÔRm»´ðüÙû0v²k¢G§†Ä¡2ë£Îq•aŸÒ~–¢D{Fbš›Oծǒ̄t~˜ÄìAw៨ ý2¾öµ¯}褓Nú‚þå±þÈúã:]»vÉädìFÐ ýýï¿QfzÿC1ø æ¶x xbšBˆ©éSæWÏön“K ηýZœw†¬ÎøÖðæÐ.ž1Fߨü²\˜¶í×ÙM½[yRD"k¼(6É6SƒqYj‰”IIܼg#U„ÄPü'¸<&)???ý«_ýêO9å”+b%ü‘å/++å70+üAWW—455ÉÔÔÔ\•;=£ƒ•¡Ç×KOOkµÀ–-[îQïa\<;ÿ­ ¬ì?¨ì?„ÓóPç“ ¼CiJ±\¿ä'r¯ê·¾õØ-óE¢ Æ“}§úߤ0¹€‹¡¸«mÝl¶•D–7ßfÀ"`\(*‡P±@ˆ‰®Nÿ‰Jh§^{íµï;ýôÓ¯T‚ÙTÂ;vL80+öuœN§Œk"ÞA«€€2*”žžž°úûûþõ¯Ý"Þ³ÿF‚ÁVˆ—à€'hH‰`úôºúâ{Jö \ ™i ¸¼ä2Íë-7Ë+ƒorQ¢@^R®\Yñù@á…Úg@D‘ =›¹QâÍ¡·åCEïãBXx 8¹Ä ]økÚ0-- Âÿý«V­ú¬º“¨£/áÁ¿oß>ikk›÷<Tdddx|Í¥K—j?knnÛ{ݼyó—ì¿3ÌA€°gÿ „Äw¶ÝÇ€Õi‹äWjìÜ jZ­\”€qdÿ°ðýò/e—kýÃä87½“½ÿQPbà0 ˜õ €Ú)ÊÜï‚3Ï<óó™™™±xSº«¿k¿+÷púïíí÷3¸ÿã9YYYó~–’’"Ë—/u\Úˆ@÷ª`Aöÿ–[n î¤ñíì¿'ñO@BH|ñÚà[²S9?ÃqÌ•«²O’õªUâÞŽõA;b÷oF äܼwËÊ?-Ui\7ÞÚ­ŸHôèTŽ÷ô°P@M $† ë7Ìd•O½æšk.z×»Þõ©X ÝÕßpúûí·1no®úUb¾½½]rrr´¿¥a{ß›6mBïÿ˜ÌïýD @ <1ïq BâTü¢á\ ŸôS%U™êKå‘® ÚØÀ‚ûF´ AÎÏ{¯|¶ìR“VÉñøMbZþª²ÿ$úlïUˆ aÐ@H,¿:äææ&_yå•窌ÿ'•p.•ð_´h‘&þ¼>nppPsúŸ˜˜˜s?n=zT  ËïŽY(‹/ž}m¼N¸zÿUÅAóm·Ýö¢ûËìÿ< „Ä;^×ü–e.æbx ¤Ê'Š?¢ÆÓ]ª¦'lUUOq|˜A²T6îâ‚óäcÅPÖr.ˆžîyNÍaoäBÄ€^‘dÀ°¥ˆÄŠ”édùÞ÷¾w™2÷{¿rõÏÉ{Pb¢}þÞ2þ:púollÔÌýܸö3˜úyz ª««çLèè_»¤Êþûêý1iöŸBH\qgÛýò³úÿäBø ¤Èû•Y¶Æ‘ýò°jØÜûw5{Œ‹ãÆŠÌ%òᢋå‚ü³´ ñÍÈÔ¨Ütô..DŒxcp—ö0{ÿð3$Q?çœéròð29mäI=;åÓ1ù~’šªeüKJJü àÍé÷#“_WW7¯r@wú/-[Ô€×èîîËq¨)ûTï?²ÿfïý÷ `€7¼ØÿŠìVUËY`˜¥õjlÝ5òu5·þ¥WUeÀ6mÇã¶]“ŵrž*ó?/ÿ½R‘ZÊ“$ЊÓ=ÙË…ˆýùªšüqvÞ™\Œ8‡$ZäNe˪¡rÒè2IšNŒÉ{Ð…?D¹¯RW±¾ÿ~imms¿ÃáÐñW__?ïy*,Y²Dòóç6@üãùá@eÿת =û©~ÿpgÿ…BHÜÞã?¹Uþ°ôgÅ辪*¦vØÆ”øß>ðš¼2ð†¼¬Z+¬>A™ý“³Vhf‰gåAÑ$Í£‡e]Çc\ˆƒj,H`€D–…Žy×ÐJY6ª²ä’“÷¡ŽQ~ÅÅÅsJñ}áÍéhhH  zÀ=»\þ=®òõ¾ö©Þÿ—dnï¿ø÷ÁT øýAeÿ „Äè=FûÂü³¹A’¦± GÇÛ´`ÀÎá=šÏœÆãú‹µÊ¬¡òaEæRMôŸµD’$óƒŒûûõá?‹cÚÁň1Ûúwhí<é i\Œ8&-$BTL”ÈéC'JÝxeÌ’%áÈø/\¸Ð°ðãããšÙÄþ¬rUÕpîÇø¾šš)((ð¸¿eË–i•ž€Y Ù–cÛ¸qã½xIñÜû¬à×Ã’ýg€—`þøY¹ghYm†/ *#^±°T>ª¦€AÇìÙ+ÃûäàX‹´Œ“–ñ£ªm`ÂTï_lJRÊ¢´2©N[$K”è_šÑ •iå¬ 3v>®µß؃öŒ`d4¾Éd€„%÷Æ«å]Ã+µ@ÌÎk%Ä«ªª¤¨¨(àçkcþÐA5ÀÁƒe``@sóÏÎΞ÷¼¼¼ÔHA-ãï);oPXkeÿü:###ZÉ?Üÿ‘ÝG;;h€ ¿*T„ƒ 6Éþ‡³÷?ìÙ!qË=íÊ‹.ÒD!‰<äe)ÅÚæ‹ ç¤ M kÛ˜*SFÕÀÄ;A)U>>:53‰ EUo¤¼SÁ‘ ^_†Q¦Ë,µeð˱)@à纃Ð|#ˆy€¡g» È¡†Ä'ô !å̇U›Ûð I›ŽÝdß1j/'''è×hkk“}ûöÍÉÐðïСC’––¦‰ÿää¹Á~~´`Œ ?µ‰¡‚ìÿwÞé-ûï+j;€»¸)ûÏ!$n ùó‘Ûäµ×r1L2ò yRœÇŰkÚ’7‡vq!L<žìÞ$W”ý#Na †’É"MôÇÒØâ™~”úgeeý:ü(ïGo¿ë}¸ÝÞÞ®àôï^Ú)pú7Zm.ó¿§žzjËþ"øEŒgÿ§ý {1ýg€×À FvçF /{GšåÖÖ5\“òX×Fùlé'$qA"#.¬ F•²h†~g $“±ëï‡ðGÉ=Jý=•ãÊú÷ìÙ£eúu&''µ’j~÷Ò~8ý£"Àhà×}KOOÏÞ»îºëe™qþDà‡3û/†ì?„¸çw-7ÉÉÙ'H^R.ƒ0—ùŸ¼ž®ÿ&¦Kùo<×÷½â” V?¤L'ËÊ‘ÅZÎTVÌÞ2î(µ¯¨¨ðê²pä‡ÙŸ«Ó?Êô8 dÀè@w`0ˆ1âßáýÿ±gžyæ>u1.sGÿ…kÜ_T³ÿ Bâž>Ç€üß¡äê¿ËÅ $LüöðrX>sswÛrAþYœz‡dÒ€x!ß‘#«FNFk&±¥÷þÈø»÷à‹»Ó¿>⯥¥E»Ž¶‚ââù^CFœþ=ŽòÕû@9ÿïð!þÃ!ú£–ýÇÏ „Ä=Ûú·Ë¦Þ­Ì„èxLžîyŽ =$;^S;Vq1â w¹V=Q.',•Åc51 ê!îgüܾèëë“]»vÍ:ý£  ¹¹Y›€*¸ùçççÏ{žQ§wdèïïù}oÞ¼yÌdÿuþ7úX‘(fÿ„Kðû–ÕrrÖ N $v 7Ê GïàBÄw´Þ'§«‘¬ˆ/RÕ”$åßà˜žâbؘ gºVæáŸ;•Ó÷‚¾þòòr)--Õy8qwúÓúýáΟ””$ ûúÑ à©ÀÈþ»N†–Ûn»íïâÙùß]äkþÕì?„Ë0à”ø•\¿ä'Ú89BH`t«žòø5ûþãŒ]ÃM²¥ïE9/ï=\Œxª ÿwû7ˆþ# JŒÅÖȽõ(ó_¸paÀYv#>|X駃¬<úýQ €j8úcÜŸ+:ýÏS¹Jø‡£üëÖ­¨÷éîüoDè›6ûÏ!Är_„ÿtäVùfåU\ B¦ßÛ÷3ÍXŽÄ7½SÎÊ=]e”ùµ.žÈLH—aÀ.ÀÔãûNY!E“ù1?(·Gv=772&Ê(ñoll”®®®ÙûŽ;¦mzàañâÅZ€+ð€Ù_(#dÐ}‚E™¶þõ¯Ý"3£ÿü úP²ÿžÄ¾7röŸBˆåx¸ó)Y–Ñ ï/¼‹Aˆ¦Õ¿Ÿ7ÿNöäbÄ)­ãíÊ»áqùTÉG¹ñHÌä"Ø€‚©\9á2ÿ4gjLß 2ü±‡ŒvväZàæ¿{÷îÙ|dûQò¯JêµÛ999R__?Ïc ##Cÿ¡N@ËA¨¼øâ‹ª÷=&Þ{ÿžì¿ø øöF³ÿsÇ!Ärü¶åF©M¯’¥*@ñÍŸUÕ Œ4I|skë9;ï )O-åbÄ h]§•™_µœ2²\*&Jbÿ~”ÐFo¸Fùù}ýpúÇ%ÑÄ¿ž‘/**’êêêyí¨DX¶lYÈÆƒ>Àp0Ô{îTÙÿge~ï°Žÿ±Îþ „K3áœÔüþ¼ôRœÇ!Ä ··®•uÊõŸÄ?ãÎq¹^?ÙðÆ ™œ`9 ¹Úø¾•#K”Á_ZÌßîès?÷RûH€ ?œþ!ÂÊÿÑÿ¯›ñá}`s£ÿPŒDûA(ìØ±c½ `ŒÈÌè¿@ÌÿLŸýg€bY:&ºä?öýD®_üÉNÊâ‚âÚeno½— a!^xCê|B>¶ðƒ\Œ8€Ö IeûëÆ«´ÿêñrS¼'ô×ChCX‡ÛÑß—ðnjjÒÄ7ÿ‘#G¤½½}öçÈúÃhÐPœþ=~ÿ ÑüOM(èùË_þ²A,šýg€bi0#û?÷ÿL~½øÇ’–Ê!äžì~V~×r‚üåÈmZûÓŠÌ%\ ³XÏèNþËÇê%ÙiI…2zô÷ëž,®Nÿ‡C+ùœ1¸DÙ}w³AÜñh Ø'ZBáµ×^{TâE¦$0ó¿¸Èþ3@±<˜ ðƒ¿Ÿ×ÿ'ÇòŽøÿÕ¡?iæÄz`®üÏþVµ@]'¹I9\“Å€¸&~KÆj´Þþ…“¦xOÒÑþÈüGdû÷îÝ;›u‡øÞ·oŸLLLh·ÑÏq~îï NÿK—.ÕÌÉkÅA0(Ÿ‚Õûÿ¤Ì8ÿOIèŽÿ¡dÿ݃H!FAYì/þQþ_í7ÙK(þ)þ-¦`¬ãõK~Âê'“΀ø@ý¹¬ž(—£ Jü×j%ÿf šÆ~ž@¦ýþºÓww·{ˆ8ý»÷ûë"¿®®n^p¢¤¤D»?Nÿžµü_Ó“­­­ýÄ¿¥²ÿ BlÇßûwÈÿÛÿsùIýwÕ—¯4.±4Îi§üþÈjÍñŸØ“ú_–5ÿR~\û­ Š˜Ž4ùûf+ñÑpÎG™´ûû=ûÆÆF-ÓîÞïàE·w‘n§wP‘à„È]½zõ#2“ýw(úã*ûÏ!Ä–¼2ø¦\ÛôC¹®áû4É"–eÔ9¦•€#èEìÍKý¯Ê×ÿK~Zÿ=)N)ₘ&À €XR8™§eúWŽ,– §¹>‹””)++Ó6÷2úX±~ÍÍÍÚõžžíºÞïЖ€Í=€ žÆÿ…×öƒ`ؽ{÷ÓÊ¿ }ÜŸ©³ÿ BlKãÈ~ùwøyÃIiJ1„Xж‰ùþþë´Q˜„€}£ÍrMã÷ä¿ëþƒ#M`@´A/ÿòÑz9A‰þ‚©\Ó½¿¬¬,MôǬ¿žšT"eþª<Þc¿?²ýUUUóD~¤œþÝù_gggÐÏWÕ wÜqÇz9žý¤ü?î²ÿ BlÍÁ±¹zÏÈj¯•Ó²Oâ‚KðæÐ.ùñ_KŸ£Ÿ‹AæÐ=Ù+ßhú¾|¶ôò9µÑ5¶d° *`tßâ±j-Û_1^bºi@úèëG™¤ÅrâXöìÙ£eü=õûë~øÌYó´4Y±b…viúúú4?‚`Qc 7© Dôì¸zþM™ýg€b{”)àw÷ý|©üŸåò’Ë8&Ä-p÷°ãq¹áèíÚ,xB<~¡WçÆí­÷Ê«ªê»Õ_•òÔR.JŒÈL`@¤@Õx¹rðo†ñjI˜6_° eþÈôCøãºÙ×Ìþ†‡‡=öû#ÿx±jŸÈ˜{gggkcþ¢Õº€Ê„`QÕŽ»îºë!®žý7"úM—ýg€BdÆ( éûFšå;Õ×pn6‰;F¦FäW‡þ,Ïõ½ÀÅ †xkh·üË®oÈ?,¼T¾¨ 4E>l+‰JôW+Ñ¿Tù5¨ŒÊ´9'_˜±Ì߈þ;wj‚¿··Wë÷G©½2ûç縀 ‚‘rúwæA?ÿÀϽþúëÇdÆù?œæ¦Íþ3@!.<Û»M•ï×þ»T§-₸rÿ{ð÷Zß?!à˜vȺŽÇd[ßø´\Tp« ¢¦2$-HdÅN((ÉS1Y"KFkdÙX½2ó3g +11Q둇ðGÀÌÀéeÿ(ÿÇh=˜ÿ¹0$)i®ŒŒ´Ó¿'ðþ\A4¦î¹çže¦÷Ê€˜·DöŸBqcÿèAùÊžoËeÿÄ–bjPÊ}WÛ:¹³í>­Š…`Aðèç'Sçþö—ÿþí‹™‰™ÒïàBHÉd‘¬©WÙþ:Étš×K!==]JKK¥¤¤Ä4nþ¾8vì²âšøGÖÙWòòò´ž× ´œþ=xéè>ð}èС¿¿ôÒK-2ÓûïMì[.ûÏ!„x`Â9©µìxMþCõÈrJ1#ß?p6Þpqhìˆü¤ùÿ¤üX©|¨è}òᢋ%;1‹ A2TëE¿0ऊ' µò~l9Sæ=/!ŽaЇlaaaÔÊáCYtPö~ôý»‚ †{†Upúw7Œ0& Áüoú¾ûî['Ç{ÿžñ"áËþO‡"ò „ x}ðm¹r÷µruÅÚ—afĈ™¸¸à<HD86Þ¦AQ€ó G†ªtŽªu= ªÌPiv`ô°4«1­lÝñIádž,Q‚¹*ïÏwä˜ú½ê¦~ååå’š?^BȤ£ä¥ÿCCCšø‡ã¿+8&l®À`ùòåZ•C,@ù°>|ø¥-[¶4Ëqçÿp˜ÿyôf0@!addjT~søÍ\í«‹¾Hob.Ì?[žê~VUª¼ÎÅ ûû·¾óIm«L+—÷åŸ+gç)µéU\ ¤ÿ€÷®ÆÎŽ;'¸8¤L‰£HêÆ*eÅh½äMå˜þ-»fûÍjêç W§ÿÎÎNã9=õ¨^¨­­Õƺm§w`þ×ßô¨Ûé‡zÙÿ ñý¥ü߈ØzïÿìçÊ¿4Qaûݯ/p»î¾%x¸ô´%z¸Ä†ßؼ ^ùÇgøñbŒDeÖtÙÂ÷Ë¿”]®ú6éÞLbz·¿¸ë›2æçb¨Q¦Ú¢Þ›wºœ‘³JNÌZnÛÉ)£Î192Öª‰{dóõÌ~÷dO’Eÿ¢ÉR•é¯Ñ¶Ì)óÿÿªgûÑß« x¨@ôCü#£¿¶¶¶¹ßy”q!ýÝM èÀý± v_úI ø€$,Hà˜Š.ý¸Ürìn.‰([ÇßBlp±_šÑ 'gŸ +3—É’Œz)Hγ̱NNOª–ˆvi;¦Jø[å6u—ú¡‰~ݽéxm\ˆþxìí÷F__ŸìÚµKë÷‡Ùn»‚Ì>Æü¹7ÐP]]ÓcG˪‚eÆ ÉÜì Yþ`&xî1Éþkç2ÿEço†ûY@Hœ/½_©øœœ’½’‹AbF¹}y÷·47BÌ@Qr¨Ï¨ÑÚ¦*SËU A…i+úTÉ~Ïd¯tLti}ú3Bÿ˜–ÝoŸèTß¾§ù¡†$õõ³b¼D+ï7»{¿+èç‡Ã}¼õö{™~ôù£Œ~ïÞ½Ú¥+ýÈð£ÊÁ5øQWW§Æˆ¼ï`P>W\qÅwe&ûA×ì¿§¬¿å²ÿ3¿‹„B‚¢qdŸ\»÷G²2k™|ºäcòžÜwqQHô¿T/H’k«®–o6ý€B…˜‚.•ïêï‘¿÷ï8. Ô¿…)…RœR$ÅÉE³× ’ò$7)WmÙjËÑ.Ñn*¨Øž‘^G¿&îñžºõË µ9z¥s¢[ý¬OËò“È<$•ãešsÃX•¤L§ÄÅûFy;úÞ‘íÇè;«€5þNëŸ×Çý¹’““# sÊûcéôï‰PÌÿ6oÞ¬gÿ§Ä˜ù_0®ÿîß“pYöŸB ;‡öÈÿú_HÌ@öû /'º7q1ˆ)Ap vlþHMH‘µe%fjUÉ ’µv«Ì„t¯;453®lLõäCôãö8}1bFº3MjÇiýüµ‹$a:~Zå222´,7¶XÜE”Í755iÙsOf ¨¨h^y¬þÝ•àÆfªç¹ãŽ;^’™Ì¿/±ì8@‘àÇ*øC 0@!a@Œ]^r™¼;÷4Ž$Qã+Ÿ—ú_ÖÊ™ ‰gà–mÐ1ÄňrYR?^¥zúk¥ÂQ"ñTŒ³;”øCô#n5&''µ~gÿŽŽù£'afXQQ1GüÃüâßLw£Â@x饗Vˆ ºfÿb|ôŸSŒ—òÉèÇ$ûÏ!„D€·†vk[Yj‰|¸èbù`áEZi+!‘$G•N¥â ùÅ¡?p1!ÁíòÉb©­”ú‰*)œŒ¿2y\”øÃÍ?ÞÆ÷eddDvîÜ©eÎ÷ïß?otUU•qí04Óº„bþ§Ž¿çæ›oÞ,áËþK?ó'죒ýg€B"H«r޾éè]rÛ±{µ‘YŸ,þˆ¬È\Â…!ã’ÂódCÏfymð-.!$¬èýüÈôÃÈ/ËãpQÒ®gûãu|ŸQàì¿{÷nmÜLÿpâ¾¾¾~^o¿œþ=ñïp8‚zî믿þØÐÐz…(ùÇš™T1¨ ~pß»víÚ ‚ýâÙù?Ðò‘8Ïþ3@!1Â9íœõ ø“ ¼7÷t9/ÿ½ò®ì“ !ó™’˳=[Õ,óV.!Ä'iÎT©šPeßãåÚ¨¾ g|–Æ#ƒ ?¸Ù£ÌßJ.þ†¾W(¡¿wï^-SÞÚÚ*ÇŽ›÷˜ììlmÌ¿0ûËÌÌ4í±›ýW¦Êùÿ™Ÿý& œ/€?aÕì?„bàvýlï6mè+T`‚Ài*°$£ž D&%!Y®­úWùÖÞicÒ!ĕܩl©WYþ:ÕÏ_9Q—¥ý:®ýÈö£Çߎ 7Nÿ½½½ràÀ­ÿßd÷QâïZ aF§">hó?Õþð\cc#žìߥþÁøˆÄaöŸB1®•7©Ûe)År¦ œžsЬÌZ&Ù‰Y\$bˆS²O‹”ßÄÆž-\ BlŽæÚ?¡\ûUY½Êò:â»>55uVôCÄÚ™±±1ÍéýþèûG¹¼;0=¬¬¬œs|Ð `ööˆ‚`zݺuÈþÃaJÂcøç+ Ù!Ää´NtÈCOhÀhÁ3—kÁ€³–KuÚ".ñÊ5‹¾ ;^—~ǃ›‘6­JûUY½ÖÏ_%©Î”¸>d©u3?”ú›Í¥>`¬œþq‰òw³?€1X3WÌêô¶¶ ž§ü^ܶmÛA™ÉþÍú:P¼~OÂÝÙ!$Þj´ 6ŒzEÉrRÖ Õ*P'õé5RŸQ£¦ är¡ˆF®š4ñ¥ò–ß¾‹AˆÅÑ üR3¶HjÕV>Y¬Ýï¢&~Èö£„¢ÿ8]]]ÒÔÔ¤•ýÃéß=KîiÌŸÙþ=8FFF‚zîã?þ Ïþ‡jþçÏÐW ÀTÙ!$Þ¿LöȦޭڦS˜œ/uéÕ3µáú¢´2I^lË5BÅуrVî¶<þ½Ožê~VÞVÓ'!Ö"y:I*ÇË´ íø"ɞʌÿcR¢b¢⟢>0øC¯GG‡æú?==W#Âäåý®ífwú÷D°Ùµ.o©@ã;gb?˜@€ˆ÷€˜gÿ „ Ò=Ù«m(ýÖAhaJ¡”«‚²”uYªµTàRÝÎIʶı:†ä¨r¾oÙ¯m;‡ö('ü'ä_-þ‘f¬h7ðÙÿ{ÕWäê=ßÇôA‰s¬dà§'z]ð#c­‹~Š7•¨„>úüáòïÍéþÿ®†ˆñàôïÎÄÄ„6Ê06nÜøÌwþ÷—õd  Hœfÿ „»|iPÿ:&º´íuy{þ†„T)HÎÓªÐB€Ö\ê÷¡”„‰i’ž®.£7&jÌ9.ÃS#225*#ÎR×!ô;'»¥}¢Sk‰Àe›Êôã1Þø}ËM²zùolY *OTîi¿ „ÄI*Ë_?%ú×X"˯ UôôCø£§ß›àe`W§ÕßîQCàCü'%%͹oÙ²eÚzÇÈþ»W6AM@h¾ûî»_•ã½ÿá,ÿ÷V ‚â#`q‘Ï!„ŸŒ+‘­û %+1S ¤'¤i— é³÷Ë;_Ø%aN°ÿ˵½³)õÿ®»`sŽÉä´C»>ä–a%ø1!´Œ“{Û–Ï–~Ü–ŸñçË>©šD „bnå¯V~ý5’8h‰ãJOOŸývwï8ý¿ýöÛ288¨™ý Í{L^^žÔÕÕÍqõÇ}K—.ÕÊÿã §Ó)íííA=Wÿ­Ç×™ßûjù¿øþq“ýg€BHÐ M k[<ñ·¶ûå¢ü³µö»*oV]%ßÛ÷Sž¼„˜Œ$%ð+&J4Áß0^-9SÖÇÈÞ#Ò~ôžë¢ŸY}ã@ô#óK˜þÏ{Œ§1¸x\ëîîn ü¡ ;n¾ùf˜"MúüÁD3ƒ¨Š|!„A¥Ã„üNµ\×ð}[ÿ9§Êyyï‘çú^àÉ@HŒqÍòWW¨/åÖÈò#Ì3?²ý0õ›§z(í·sœþe``@ëýG€;é‡MkUSS#eeeq{Üð7†;v<¬¼PZ¨gÿ–ÿ:þÏŸp7möŸB!¶cûÀk²­»m§|­òJyeð͸«Þ $ÞA–¿rB ~åÖ_3V!yS9–96Wç~˜ø¹–¡“àÐþ@Ï¿{?¼>ÒÕ:Xw8ý»Þo {lqð‡ªŒèWÙÿâ9û®^O·==^ĤÙ!„Ø’?´Ü¬&œ,i ©¶;v;~¡ürm !‘EÏòc«QÂ?eÚ:&¤šè‡ØÌÎΞ¥$4 ô÷ïß?ëòïÉé& s|„Ó¼{+;úoçÎO*cDD¦$|åÿ"Ëþ3@!Ä–`Â]ÊàÊòÏØòø/[øy¦çyÙ5ÜÄ“0‚±›åpì¯ÔDÉd‘eŽ Fr(íÇÑÍÒ~»´LMMÉîÝ»5§ÿC‡Iggç¼Çxó‡` œþ]ï‹GÐâàé˜ Wj·ŠFû9rDúúú´ €{ï;޳ººZ­¨ƒ` Ìþ"åô«€Àèè¨GÏttt¼­â¹÷?Ðòw‘/bÌýß[° ª¢žB!$ê|B.-¸@gÔÚòø¿^y¥¼6ø–Œ:Çx2[‘ëÈ’ê‰ -Ë_;±H¦ãßäN/ë׿·²þHŠo–ö{BÏž=ÒÝÝ-]]]šÛ¿»ðFÐýþøütð™.]ºT›­õV@½ÿîû2ÂæÍ›]{ÿƒÍö» ùpJÁ€¨  „Â/dÓNùÍáäÏË®³¥!`qJ‘\Qö)¹áè<ˆµy§´‚®ýVӇ̰žåw5ï³äGÇÁ…‰‰‰Y§ÿÖÖV­ÀÓg‰~|®ºÓ´Åy¤ˆ¨L~ÀÏ8ú·¿ýmû;Wñï«üßh@Äxö_<<>ꢞB!$@GöÉc]åÃEÛòø?^üay¦÷yÙ;ÒÌ“XФé$©W~ãUÊįJ2-PÚ!¨g÷qiÆù﬘‹îô£;dý‘ýwŸ#„¾kNÿµµµ~×'^âp8~ÞŽ;™šš‚c¢CB3ý d"€/ןKäÏ „B"ÉMÇî’³óΔ¼¤Û{â‚D¹¶êjù·=ßSßF¦y2¸&C¹ö׌-’%c5R£Jü§ãúx\Ëú!ú‘íG™x´Å7Kûƒ}þ»víÒLþöïßï±ßŸiCCÜ,?\þuú·€€§*¨I }7ÝtÓ&ñªÈwößÔ0@!„¼Ã cHn:z§|§ú[ÿÒŒUq‰<ÒõOwäNekcú–ŒÖZµ½ÞºàÇ–””diñmÕ@Üíáðòÿ½{÷jãþÜAÛ²üzPdž`ÆÿÅRœGzŸýÀ@Ù¹sçSjr°Ì7ÿ §ë¿/ñ#øþõ‰É_)!„žì~V.)<_NÎ:Á–Çÿ•ŠÏjº'{x2ÓS8™§²üµ–èç‡À×Å>Fô™µŸÆQ3êµr•±–¦¦&íÒ’’©¬¬œ½­{à<ˆ¥8Æ>ƒÉþ£ìÿöÛoB|;ÿ‡ÒÿoÄì/ì¿éB‘ B!sþ§ž–ß·¬–¿.ûµ$-H´Ýñg$fÈ¿.ºB~Ú|=Ob:`ÒY9^úŽè¯’¬©Œø=%¸Pö ±±çjúmñÍÒþðc»ÆÆF­Ï_eªµ O}îUUUZ¿<àôKW±l%ÇTB3úOµP<§Æ&v‹ÿÑŠ~obÞ[ .³ÿ B!h=¬F>.Ÿ(þˆ-ÿÂü³åéžçä¥þWy2Sˆþò‰bUÚ_#KÇêâÚÄeýz–åýz¿7Kû­´@ŸÿîÝ»5q‹Þôüó‡s™T‚ÄZœGcŸ˜‚ÌÛzà‘ã£ÿÂÕÿ/>n‹‡`€ø˜Bä3@!„Èm­÷ÊùùgIQr-ÿ«‹¾$¯î”qçOSÑ¿L‰þŒ8ýzYYYZ–ßìãùX1:èg‡Ó?.1Ú-î è¡óB§¨¨hŽ@¬Åy¤÷‰ ‰§)þ8räÈŽ­[·ÏÎÿÎ b@øö¦Ïþ3@!„xadjTþrä6ùAíµ¶<þŠÔRùLéÇå–c÷ðd ýžž®ev±¡Ä߈Pbi䃑Fͥלþaö‡ì¶§þvT€`Ì.uàò_QQaq}¶··kmòôÓO?¬.•ž’ð:ÿ{sÿ72þ/®²ÿ B!>x¶w›\ª ÏÈYeË㿼ä2y¦çy94v„'‰Š©œ,“å£õÚȾTgJÜJ¶õ>~Ý­?šB,Ä·ÕƒÈöÃá_ÔIss³ôôÌ7QEÆÎþúùc¬««Ó²ÿfç‘Þ'„?&#Jww÷ÞuëÖ픹½ÿ¾‚F"ÆLÿŒû¸Èþ3@!„øá-7ËÍËO””„dÛ{Ò‚$¹¶êjùfÓ4sDBÂ…îÞÂØbÉudÅÝû׳üüF³üVêdÝéâýþ¨píûúÚ"€6œ;Ñ:ÌPB^k”mÛ¶!û1 ž²ÿÁTˆØ0ûÏ!„⇣ãm²¶c½|¶ô¶<þ³–«*ˆ ÔxÄM<HHdOeÊâ±j9at±OÆÕ{×{ù!úéåg–ܺA d²‘õGö‚×álïŽû˜?8ü£ —fçÑØg0£ÿÔºvÞvÛm/ˆç£ß- °›ì?„BˆþÖ¶N.Ê?GÊRKlyüÿZq…¼Øÿ²ô9x2€Èp*±3Z++Æê¥tb¡Öç/@äëeýØtÇ~«Ã …0Òýþpú—¦¦&íÒ÷1"Aü{rú7ƒ8ô>Qá)HâW_}õ1å­0*ÆFÿ…êøo´% .³ÿ B!€þïZn’ë¾oËãÏNÊ’«*>/¿<ôGž Ä€š©ž(—“F–JÃxµ$L'ÄÅÛ†èAi?úù‘éÏÈȰ¥P·zÐ"TÆÆÆ4§YlÈü»—´£b¤¦¦F ŽO‘ÁuŒþ ô}Z) Ìè?µ¶Ã·Þzë™ýg4Ûïßåû¾Jÿ½‰zoUq×Ç!„b€í¯ÉÖ¾írvÞ¶<~˜!>Ýóœ¼6øOâ‘|G®,­“•ªÄ?g*>úú!Ô öuÑo4ËÏ,¹=ƒºÓ??®ïÛ·ož›½§1eeesÚÌ(Î#½ONúúú~ÞîÝ»ŸVSP~æ-û®i"JÁÓ  „B òÇ#7Ëi9'IzBšíŽ¥Ûÿ^u•|i×µ29=É“Ì|‘œN”ºñ*-Û_5^%þh®®ý,ígÐÂ0¯kllÔÌþpýàÁƒó„±û˜?˜jkk¥°°0¢Ÿk<àüïþ<¨àŠãî»ï~Lf²ÿþ„~ ãÙñðxS‰z!„Ð1Ñ%wµÝ/_.ÿ¬-Qj¹üSÉ?hk@ìMÅD‰œ8ºDsòOvšÿë$z®õL?D?]ûí´×8p@ÛLÿàüïNff¦–ù×ûûõJ8ýëÂ×êÞöÏ„ÎÎ΀_WY¶íܹ3õ줲ýâá¾i/A1(äg B!fæ¾öGä’‚ó¥:m‘-ÿseŸçúþ.-cÇx2ØŒ$I”%#µò®‘•²p²ÀôïYXݵýüF„³ä Z¸¿WŒöCï:®=zÔã {÷18÷ þá)a&q}zÚÄ?*'}©‡~x½xÎþG:àI¸ÇuÖŸB!$HÓùÍáä·Kþ'®ÍÃEò‚dù÷Ê«å[{¤¾Mó„°yŽl•í_*' /•´éTS¿WÝÄY~W?Šo-‚uÏž=ÒÓÓ£­Ess³vÝ÷1¨ðçôo§€<<Mü¡žóæÆ÷‹ïòÿ`Þļ·@€%Fÿ1@!„„À[C»å™žçå}çÚòøOÉ>A.,8[[bUUyÜÉñX©ƒ]\º‰ŸÞ{m'¡Î Eø× #ýàô?<<¬ X˜ýÁôÏ÷1púGÏ?zÿãAœGcŸšx‘èÍ›7?ŒBŒ•þ; D|/÷ùËþÇU4œB!$þrôvywîi’•˜iËãÿ·Š‘íý¯ÉàÔO ‘æL•G–ÈÉ£Ë%×a^'ÿ´´4­ì‚+%%%î'ƒæ¢_õ‹š;¯¹ýcÌŸûìz|ŒôCÐIG¯ç˜±Ÿ?P‚Éþ«`KË]wÝõŠÌuþµì_ £Â>n³ÿ B!AÒ;Ù'·[#_«ü’-??9O®¬øŒ\ø¯<,@îT¶¬Z¡•ú'O›óë!D?2ýþz¦Ÿâ›A‹p_WW—æô¬?²ÖMMMó²×ÉÉÉZ¿Þb‚}ÕÔÔHQQQTÅy4ÎÿP÷744¤m²}ûöGÕńڦ$<ýÿžÄ¿xŽˆÅ²ÿ B!!ðPçr±jX–¹Ø–ÇÿᢋeC÷fy{¸‘'CœR4™/§Ÿ(ËFë$AL÷þÝ×ÝûQêo'¡nu̶n®NÿÈø#ó Wà1ñ¯WÀé¿¡¡aŽÓ´Äy<`ž(*àÒ·zõêgÅÿè?§^æïMä"ìã:ûÏ!„Ê—!õïw-7ÉŸ—ý–†€8æk«®–¯ìù¶2Gœâ G`ŒßéC'JÝx¥éÎ]dX!øˆ~fÉÍ%¾ãqÝðž!üèõGÏ?ª\ÉÊÊÒľnî§;ý£2Å âÜl±±1éíí ø5UûÅSªj`XRt‰-¿6½J>^üa¹·}=OÓ+Ñÿ™C'Kùd±©Þ2©ÈôcC65X5Šo-y,D>œþ»»»µÛ¸T³çç [´¸šû!0…`‚Ufç±è£AM^˜¸ýöÛŸùÙÿ@+Äø÷W`Ùì?„BHX}ôorNÞ™’—”kËãÿ—²’-½/HëDO‚ ÿòÑzyÏЩÚH?³1…q}W¸´‹P·:ñ²n0ùƒÓ¿Þ£ÞÑÑ!‡ž÷8÷1îÁ€xçîûŒäþÐ:ÑÙÙðóT%Ƶ!ãð"ìC­ð׉`„BˆÕ€þGï’ÿ¨¾Æ–ÇŸš*ߨú²|oßÏx2˜Lø×Ž-’³‡N“…“æxOJt Ã…l¿7Â,¹¹Ä·ÕÖÍÕéÇvôèQnõÕÕÕ²páÂ9Á€E‹Ed-âÍàÏXË@³ÿxKëׯDfÌÿûˆàbß[Ùÿ´UÎ!„0ðT÷³riáùrrÖ ¶<þ3rVɹyï–-}/òd0ÕãårÎ໤d²ÈïýÒèé7:¶â›A‹H=}é»wïF¹¹ö˜ææfmV½+îcþð:¨p Dc]â1 €u &û¯Z^ݼyóA™ÉþO‡qñߨ¸Ÿòg B!–ù«þý¾eµüuÙ¯%iA¢-×àk•WÊ+ƒoÊðÔOˆs?dü—Æü½è}ýý®#Ó¬*8-ÿ7Îë†Ì4 þðþÐÿë0ýsÅ}ÌÎc”üëÁ€Xˆóx @ü;Ž€÷÷Ì3Ï û™‹N—-OÂÝŸù_\Ã!„&šG˃Ë'‹?bËã/LΗ/”].wï½}¢SîïxDëÚ¨eÿIdX2V+õ¿G2œ‘aŒFíy¦ø¦ø6㺠jârrR» #:dþuçòòrmÓÅ0Fü¹;ýGKœ»ï3Þ'  å"˜ìÿ¶mÛôìÿ”„¯ä_Ä÷8@o¢ÞŸùŸå`€B‰k;–‹ Αºôê¸x¿FÉÚö‡eSïó☞â!R¦“å}ýï•å£õQþè{ŽGÁiu¸nÆcý öÑëPþž”ÿ» ]8ûÃ× ÛïÍé?bÙ û ç>±Öî‹FPÕ]·Þzëó23ú/Ð1FÄ¿'áïmb€ø ø\J!„âýË’Ñ¿k¹I~»äd˜÷‹»î胿iû$DbB‰£P>Ô{ä;r"dPgþèy¦àŒ®øæº…-0o¾¹¹yVÈ¢ýàÁƒs„-Ä~CCÃì9Ÿ””Ó?þAöß5àb”7ß|óÉÑ™ž O½ÿ¡D¼Wx „#À!„BæóÖÐne ÷¼\¬FšêKü;Žþw·= o7òƒŠ§¯ó”ËâtbÄö„^glf¡ß\7£ïëÀšéœ«Usäç<ÿpú×+]t§Ýù?žºYxŒ>q!T»ÆÈêÕ«Ÿ”ãåÿÑvù÷'ì-Ÿýg€B‰27½]Þ“{šd%fÆü½ ´ÿÙÞ­šð?4v„N€àGÉÿÊÑÅÝÊœKKKµÌ§Ù§Õẅ¾èëß³gÏœqsþî"bñâųcýt§ÿH™ýÙ5 € Ý{!TÛÆ&UÁÑ'Á÷þ‹ø/ý¯!bÓì?„BH”éì“[ŽÝ#_¯¼2fïaÔ9&Ot=£ùÀ D‡L5Öï²Þ‹¤traÄö,gYY™dggSp « ¬´€£?ÆüéNÿØZzzzæ<Î}ÌF[VUUEõó²’ÁŸ7ເ6Œ ž7µfÍšGåøè?#‚ß)¾3ûþÜÿö¶Èþ3@!„Ä€õjœÞ%çɲÌÅQÝoŸå‡}?Ðù˜ :†øAD‘²‰bùh匌ó>¾øçååi½þÑmFñÍu‹púGæãæzÎaþ744÷ï—û˜?T¿`‹¥XŽgƒ?_ÀsAÿ<¡¥¥å¥W_}õ˜ÌÏþ‡Ë0˜–Ûeÿ „Bbñ_ýƒ!àŸ–^' "/ÖZ':äŽGåQ5Êoœ£ü¢NÃXµ|¨ï|IŠP¿jjª6æ,XwŠoẙp-áojjšuúGÉ9në•:îcþõÏÏÏ7@·B@¯×ÞÞÔsŸxâ‰õb,ûh @ÄÿØ?ñòø@¿% B!1 qd¿<Öý´|¤èÒˆícÿèA¹¯ýyFò›â(¿˜°rd±\Ü–$Hd=Èú#Óéžõ§à¤Pçµ@‰¹«³?Úçô㽡¿¥þš¨Q~uuu;ý3 `eðYŠøö£>ºGæŽþ‹D¶_<ܨh·üø!„±úèÝrNÞ»%/)7¬¯ËQ~±£ß;xª¼{蔈¼>úœ‘õ4ÚëOñÍ E¼¬úû]þѰoß¾9#çpþÃì/++K»––¦‰Ýü/ÜbÙªýüì ¦÷<ÿüóÈñì¿3ÌA_O¢>PÏ!„§†äÆ£wÊT5ô/rïŒòû[Û:Ù5ÜÄűø?àLY¥FýE‚ÌÌL©¨¨ðëðOñm.¡ÎuóýX|dùûúúfïëííÕz€Èǘ?ˆ~€ X$þãAœGcŸø,ÆÇo!8zûí·¿$ž³ÿ¡¼‰x_†þÿ+ îg B!ÄOuoV†€È)Ù'õ|Ç´CòÛ¦ ÿÃcG¹ &ÿ¼[N^‘×G¹³»¹E$…z¼¯LåvïÞ-ÃÃó÷¡×\ÇÍyÊû!þõà~*++ç‰W–®UðòË/?ª‚;ˆøýlß¿·q€âå>Ûfý „BÌòÅ]ýû½2¼qùÿIÒã&q#S£òd÷&YÓþtMöp!Í"þû•ø ¿øGv3V%ÿß ZDrÝ úáôïš]†ðw7›ƒßÊüõL?a˜za±lõ€²ÿîæ‹FP~ƒ·ÝvÛ³b¼÷ßÈcÄ€ð€@îöq B!Ä?ÇZ”Kÿcò©’ú}lŸ£_ò{J{¦Fù=­FùMpÁLÆÙƒ§EDüëýþ0=£ˆdÐÂJëQ ±¯ W‡Ã!û÷ï×Lÿ\qó‡Òÿšší÷"\b™¾éïï—‘‘‘€Ÿ§‚:*ûÿ˜Ìdÿ§d~–?Ô²£.ÿÌþ3@!„˜”ôÿùÈmò£Úo͹ßh³Üßþ¨lìÝ"Îi'Ê„œ9t²œ1tRØ_β²2KNŠo®›ëÏQâôèqÏx ÀuÄJý!öõ1¨„Ù.)Σ·Ï`{ÿU0ç¹t«« ¾ìß]ˆ{Êþ 0ûÏ!„b>žëý»¼¤ ÏÌ]5;Êï…þ—¹0&Ydÿà z›uáCÁIñm•uƒ›?„>Jÿuà€1“““ÇŠÊô744ÌŽùCÆÁ€hTÂ0 påà?ǘ1—_·nëè¿HŒüñ_Àì?„Bˆ¹ù2ÌnÍ”½#Í\ “S3^¡™þ…| ‡¹Y ýÍV‘ ZXoÝ ðÝþ1òOe‰çŒùC†Nÿz¦???_óÀЋýüÑÛg°ÙUÝñʶmÛÊñ츂"ÆÚ" `€B!á§m¢Cm\³SèÈ“÷] ¾ÙãøÂ~ÿH8ýS|3hËuC¹»ÓGG‡>|xÎópî#ó¯gúQ ãÍé?VbÙ.dÿ‡†‚3š}úé§×Ëñì¿«øD ÀŸ¨ŸRð[60À!„BHd:Óå{.‘TgJØ^ýÎÿ˜›QpÚg-âyÝ`"רØ8Ç鿵µUŽ;6çq………Z™¿îô¬?²ÿ¡ˆeöóO°Îÿêón¾ÿþûß”™ì¿7ÁL @ÄXÿ ~ÚŽ# „B1*Ô§äz/’œ©¬°ŠÿÊÊJIOO·¼ˆdÐÂ^ëæîôK”ü»z¸üÃðLjì8œþ­,Î#½O´i¸Oc0ÊÖ­[õì¿‘ÑF«DŒWbþgK „B1ÈEƒï–²‰â°½¾¨‡"þ)¾)¾Íºnpú?räÈìmTìÝ»wNY9^ bÙ’’§Û'*4‚AµztÝ|óÍÏËÌè¿H•û{Êô-ó·}ù?„B!Y1Z/' / Ûë!ó2gwñOÁiŸµ°âºaßpõïîîž½½ÿÿ®cþéG¿¿îy‘‘‘!ÕÕÕÚ]À²Ÿ?úû„_C°Ùÿ×^{íQ5ÒqLæöþ»_†*þE¼—üsô„B!¡SƒíýWûw®]»VýÈØ¿@¿ûÞÊþ™ýg€B!Ä7 Ô¿‹ûÏ’Ôé”°¼ÌÎŒô9ÛIpZ+¯„~ss³–ý×ñ4æ¥þ(ù×Ëüñ{€±¨ Á_ä÷itÃÃÃA;ÿ:tè…_|±Ef²ÿÓaÜDü·*Ú§ù—‰ÛþŸÄ% „B¼sÒÈR©_–×JNN–ŠŠŠ ¾ü3Kn.ñÍu›qú‡Ðw-ǘ?xàÒõ¼_¼xñ¬Ù%*`ð{€ ÅytöitÁfÿ±‹‡~øA9žýwÿ.ñ/~ æ„B!„¹äLeɹ§‡åµ vÊË˵Œ'E$Åw¼¯>ÆüŽŽÎÞ‡ì1®cþéǘ?ŒûEEEZL ï™èì®U olذa¯ÌïýWÿ¿'ï)`¤ß?ó@!„B¬JÿS¦“ÃòZ=‘îu6›à´:v]7ˆDˆW¡1h@K€NNNŽÔ××kA/}äe Þ D7 Bö_6nÜøÌdÿÃ1úÏß@O¢ŸÙ!„B‚géh­ÔŒW„åµòóó51MÉ,9×-k¡¿oß¾9BßÓ˜¿ÂÂB­ÇÏG ªª*¬Nÿ „wŸèûGG0ôôôì¿÷Þ{_WW' Š#Â_<¹?ØÇ1@!„b%õ?ð̰¼J 1ò"’â;Þ×­½½Fo~Çü¡ÕÙ~¼'8ýCüë-çáßg8ö×ÖÖôs·lÙ²N]ÀôÁ5ûJÙ¿'ñ/ž#â?ûϪ!„BærÖÀ*ÉšÊùuÐ÷¯ !+ N«Ãu›/4QÞßÙÙ9{¿§1Xdý‘ý~Aü'%%ÙVœGcŸ¡î¯¿¿_FFF‚Ú·j9vë­·¾(ž{ÿƒû'D~ žÙ!„B¼S4™/§Ž¬Ëk•––j蜱ß\·à‹‘~(ù‡HÔ™œœÔÌþ\E#Êüaö—­ÝFË‹7§;‰óx ²#XÔØ¿‡Ô92f `${/bÜøÏ— ³ÿ B!„ãü3d„þHCßßñ¸nÚH?W¡?66¦Ý‡Ÿé ÌÉ’%³&—¨ÄéŸØPÁá:É!ԹгzõêgßÿF³ýVˆø®ð÷3CKÄ!„Bˆ i«–ê‰ÐÿPòɾŠo®[¤×¢ß]èÃ(Õ¨ бßâÅ‹gËüÃáôoç€@4÷‡ËPzÿ_}õÕGT ÀˆxÏþGj@0¢ŸÙ!„BŽ“0 ç¾+ä×Áx”þ£$š‚3òâ›ëþµ€Óÿþýûç8ýwwwËÁƒçˆÕ¼¼<©««ÓÊü±-Z´(¢U/,ß/øœÇÇǃz®jºù曟cÎÿDŒgÿ½ | ~!„B¼sòÈ2Éwä†ü:¹¹¹’‘‘·ë@ñmï úÁáìïš%Æ}GŽ™ó8”øWVVj×ásëhПÇò}sï¯ë>½!Þ~ûí§Ôy1 dzÿáÎö{ø¾\ÿ}n?c€˜ÿÿ)ü]à2B!‘<$gú—)U]TTDÁÉ EÜ­®Cø»Âá>dý‘ýwÎþÅÅÅÚuˆ~W§;‰óxtuuÍiïÕ2~Ë-·<*ž³ÿáÿç¯Ü?Ñ„B!„ãœ:¼B2é!¿D‘»ë9'…ºÙ×=ý釒p‡Ã¡õû«ïÙûpn£ä¥ÿF—ååå>þ0_@Ÿw(Ù5b“:_º$4ç£Uâð0r°c€B!Ä*¤N§ÈéC'†ü:è}ÎÊÊ¢àdÐ"®Ö“Ó?úÂ1æŽÿ:(óǘ?˜þ8ý#àìñÒà/vLj쿫‘c (_ˆ©5kÖ<"3Ùÿ) Ìõß)Ƴÿžn‹xo ù¶‚¥ÿ„BH¬:AÒ¦SCz d@}¹þSp2haÆuÃø7w§dü‘ùG€Êü1æãþðºèÿ—Ó¿f8FÿÎÎΠ_Oµ‰l{ùå—aá)ûl5€ø¸. {fÿ <á !„Ï ÷ÕÈŠ_ÙP÷hŠo-̼nýýýšÓ¿k&-ÍÍÍsÜÿQæ___¯Mµ@ «¢¢"¢Nÿ Dˆ×Ï7з|ÿý÷? .1š’ð¸þ{ÿbà9"Ìþ3@!„'Ž,‘4ghÙdEõžh+ NŠoë®JÀ]Gúá²µµUŽ;6çq0´¬®®ÖŽ-óçêôoeqnÅ€€Ý7ÏÐ1ZZZ^Ú¼yó1ÞûŠ?€Ï¥ Qð30À!„Bì†ÊgÊiÃ+C~£}Ðê\‹X¯îÃ8¿¶¶¶9÷yrú‡¹_YY™ö©©©Ú˜?ì*έÀ„‡P²ÿ=ôÐ:9Þûïîöªë¿»0göŸŽ¿#\B!d†¥£u’3ši_FF†¶Q|3haöuÃ~àôßÓÓ3{ÊÿÑï?888GdÖÔÔhm-Æ–(û7âôo瀀ÙÆŽ}}}AïûèÑ£¯>õÔSMâyô_ Yñ!þýU0ûÏa@€B œÓ†Oéùøòéxœßö[7úÁÕßu¤Ÿ'§ôùÃé_ïñGk ªâ]œGcŸf?F´x¸?>{ì±ûåxï(f"Æ«üµ0ûÏ!„BˆjÇIñdaH¯‘„Òh NŠo3¯~cc£_§xYÀé=þx}LµÐ«ì&–­vŒø¼]«<EµŒ¼ñðÃï’ùÙ_åÿFƒ"ƲÿÞZ(ø ÁþÍàB± g ŸÒóñÅ:ÜcÐÌ*"´ˆßuÐÊþ]…> :4G,fffÊâÅ‹µIxÏ(ùGé4ÛˆÜ>]=‚aÆ ®Îÿ¡–ÿ‡+ûŒ¦¡Þa€¢žB±¥“ eÑxiH¯‘››ëÕâ›âÛ ëæ.ô½9ý£Ì¿®®NëñG@wú·“8·r@ãGGGƒ~~GGÇ®µk×¾!3Ùÿé0o"Ƴÿâáñ„âö˱€¿„BÈ\N^ÒóñE=??Ÿ‚Ó¦â;Ö "ßUè{sú/))ÑÜýÚY þý¶hð?Ljׄó(¨ìÿ}êb\ægÿCqÿŸö!æý¹þû øÓF„Ó‹÷H½¶ü…"„B,EêtŠ,« é5ýG¦4ÞE$ƒÖ[7OB³ß÷ïß?ÇTUUi#,Zuú·S@ ^\½EGkÖ¬yM]uûN O+€/áÎÑ 0 `ðñì…!„BËÔ迤éà¿òxÊþS|S|›aÝ0ÒÏÝé€MMMsD D~}}½È¸ ‡Ó?æ:Fœ!íSý[+ž{ÿÃÕëïIà{ 0ûÏ!„BHàœ4²4¤ççääD5û¯BÝê˜mÝ ôáêï:Ò€ÈüCê ¼fÚmŒ±Œä(Kb·Ox@¸š?ŠÊþï½ûî»_‘ùÎÿ¡šþ‰Ûâ! >ù _'üüñ—†Bˆ¥)šÌiôŸ¯ì¿™D$³äöZ7O#ýù=|øð‘˜žž®ùCU¥¥¥Ú(K+ôº²O;#Ú>Üýå‰'ž¸GæfÿÃ]þïMøöÌþ3@/þÛø @!Ķœ<²,¤çc,šƒ4Šo-¢µèñFÏ¿Ó霽¯¥¥ežñ*WPöŸ˜˜¨U°”——k³ ×hìÓLjÏßõœ@Ú­zÿ_ÏÙÿPûûŒýcöŸ x/'ù‚^‡ÙB!öù’3(ËÆêBz ŒK³»à´ü—±8Z75žMŽ92+.!ø8 }}}s·páBÍðïUwú7ÚÆÂ€@üí#ÿ0ú/ž|òIoÎÿ¡D˜ýg€D5hàí¿„B,Ï’ÑZIs¦ý|ôL»ÎF…ˆd–œë¦Ï¡C‡æ”xÃäf®b¥þú9ŒÌ?ª(–­{Œmmm!½XÚuï½÷"ûïc£þ‚ ˆ0ûÏE{ØŸïk¤†«!„؄ǖ„ô|Ý1â›A‹X® ý`ì7888{Ÿ'ôø×ÕÕÍV­àüÕËÖ=FdþGFFBÚ·êý¿W¼gÿýœb¬ôŸÙH¾F² €BˆmÈrfÈ¢‰àÅÊ¥1'ÝÊ‚Óò_–,°nãããóœþáÐÜÜa€>öoxöðç¬éäRB±™ÎôÊÿažª`–œA‹@€ÉJü‘í×AÀáÇý:ýDu=ˆý>1‘¡ KÏoÚ´i¿„–ýwŠqã?_ÙÿPG—3`À€åF\ÿýôë.1!„+±d4<îÿßêÑX ˆ~8ýë%þxLKK˼ÑnîNÿÈúÿÿöÎôK®ê<÷»Z#HÍó<ÙÁ&ä.Ç^we%Yɧ¬ø[¾äËýî§L˱×JlÇ8v°c ÌÅÈ„0ó`l Â!BcKjI­¡Õ-©5vwÝýžÖi>}†½÷Ù§êTÕï·V­šëTUWuçyß÷ÙaÒ'‰åN7äòÞÞÞB­s†¶lÙò_ú¤|è’ªÿE–ü£úÒõá—£–py^@x^¾ð—_ùÜOÿ·>–ĘI×]‘C-å|-átü  ŽÇýoãÏPIj x¼ZÆù¼Óá±ü&Mû??üâÿU‹Õj—'&ÖiÓ¦u¤PÇ´hüûvöìÙ Ù?lñ—ciùŽѤÈKúÇh_CàôéÓ…—ýûä“O^zûí·»Uzõ?ÉQöKþùªþçi'Àè(s /ü/Í W¯_‰ ý¤C-Ãp1²v*1ÚÛ0¨žÏüÑëä7iÒÂ… oЇ®O<^Qm7Á‰iQdù6©ô‡ÂNBÝ$ìïÒ¥Kãn7þ|µjÕªà=ƒJÂþä¸Å2íûÅð±ìŸ6™.?üðÃaõ?oé?ÛÊYÕD>@Gû"÷O[ éË9ùò‡âÞG€²0|~ €Ö3Lªþ&@׵ߴ®¿ú«¿ú”®:G¡çˆoL‹¢·•eÛŽ;6®[–÷ñ û–/_®/^œ–¤©üûHúo–Xfž¿ò™)¸ìŸÚ¹sç³}ôQ¯òSý71”¢ú€Ð/å¾ñ€º2[ -Ð#JWìò®k§k±ÓñC=átÝ£Pã@ˈÿzÎeñ߈´Ñ¶DMuí÷¨ëÖ[o½ÅõIJKµkeµÊ‚ñ]÷MÄ[<é_*ºÝÝÝãD£´ù¯^½z,àO–¥# Ý:†€9.\FFŠ Ã&Ïßwß}?U£ÀÃ9¢¿H€RÙKýQýÇO†AÒÎRÝÓa$"ö•øÏêðe˜P  ë²<ñ_74ºt«ô§\Ÿ¤ˆ,„:¦EYHû¶„ý‰ ßé8zôèøóÉ“ÕúõëÇ>sæÌ ÒþãB’yþÎÙ¦à?áÝwßÝÚÓÓsFå·þ—Uý7öTÿ1@%·ø§íH%uýc;U1 Oü'JÐŽbÞ‡ö;ÿ=I˾©}á _X2cÆŒ¹®/,\Z­ÓÅ7¦…ÿÛJÒ¿„û…ámÒ çûûûÇÝNºPDüK¥<Ö‚ 2W¥hw±Œ!0Š|NâÙ¶hãéÔ=÷ܳU]Oþ·YîÏWõ?m€ê?‚_e·î×r./bÄEZë¿R€ùÿnÓyÿ¬jªø—ߨ?û³?û¬ë“—¥ÕÊjÿG|w¶i!k¶‹Øg·uv0ïv„Hþ„ˆÿ0éÉ’%FIÿU®TëËÙ¦|nNž®M„KÊ®ú_w4”PDðc `´½ÐOkLýѪ¬u8ÓÄ’ðOšùÏ3ÒvÞ’vkžv2 ºæ@ÚÿþøïC–ÙýMœpÙ_ÿõ_oÔ¢išË“±%3×UœˆïÖ~ßä9Kª¿þð¼¸9rd‚P”ªð'¡2ó/íÿzžÕݦ<Ž˜HñdzE?Æï·lÙò?j4ùßt‰?s IoPýÇF‰5 `b$%þ'íœeµý»´þ#øZ[èçÝÆ¦í¿– øÓ~»>ûÙÏ~ÚõÅHû¸“ŽPïÓ¢Œ÷M’þe™¿óçÏÝOÎË(@16lØ0–ô?{öì`É¿èç°™ÂqÞümúþ“Íÿä'?yL]oýQnóþ¦ãÊÀ("ø10ø=ÊÙéªgg þ¼ªýÚu¦âß×òì…´¦9àÒöo:rV¬XQùöªäíý¾]¾|9û“ãÐ eÿ$0Št›è¼Š±®“ùóç«›o¾¹RÂqÞ\£EfþO:Ux[{÷î}õ¥—^Ú«Ò«ÿ¶F€RTÿ1À» Ïªú§¥g}qj†F@VÕ?)ô¯®Ê ÿCè´¶àÏû¿ïCüõIëдIºzµÓ“×;àñ¤uÄ7¦…-Rñ—ùþ0¬M–ýÓâkÌ ‘Š¿$ýOž<9hõ_´h‘“…!ÐÛLÛÞ‰' ÿéû_~衇~¢Oʇ0¯úï# PE?Ɔ€Á"*þóŒ•bØT`ÒÄ¿IÕÑкB?ï¶yâßÔˆG‡¿Uµ¿üË¿\¥M€é./JB×5sÝŠB½íw´<¼o2ë/Iÿ¡˜ÓK­•ÿ¸€“JÿªU«Æ%ýûZzC } Y)b`` ðcíØ±ã—~øáqeWý·¹.®%¨þc€ƒ°wyœ¬²zÎé¸àW âß6õ¿¬öŒ€Ö3 òÂÿLÅô7jÂoÐm·Ýö)×',@UÅ7ÝÕß$¤M!²d[Ô ‰&ýKëYIÿ­¿Mù Egœ¹÷Þ{ªFgÿ³‚ÿ²ZÿGTvû?Õ (ÙHZÚ¯føÅ¨Å®Ïüqñß•¶Ã¥Ê›ýGä´®èW9¿.â$Å~ u’ú×'oÿG|cZ˜¼>9¡Mú?|øpкˆkÖ¬ þ œ\¸páØc4C¸"Ϋû¾öõõùþS/¿üò½ò„¬8tíÿ§mê^Û¿RTÿ1 á†@üËbr›´Ëâ†@™âßt‰(h-ÁŸv½©øW†¿5ñεšž£v2d‡ÝG@+ õ¶ßy*ñ}“Ö~™÷“þå¼ÌûÇÃþdÎݺujÖ¬YÁy ú‹&ý7K¸R­¯æö®^½:aµôcì}à^Qã[ÿmÂþLgþó:ò„=Õ „½Å}ÒBmˆî<% åAüWeÙ?ö†šó¿6í÷ÀTü§u¥…«Ø¨?üÃ?œ¯Eü—',â?k'*yµÄwÞ·+W®â?¬ÒJÈßž={&Tm¥Í_–ù ?c:¤RÝtÓMm)\Ù¦ŸíIëÿÈÈHáÍ>õÔShSJ>IÕÛÔÓêžp§ú–æ€I@ÍáK4¢&†*å âß¶z­#úÓ~LçÿÓ~o’Bjkþç~‹ë“¯zõñ]­÷MÂÙDüËò~‚tHå?<Oú—–ÿ"KMb´¿! Ÿ¥x‰ úóøÚ3Ï<ó¡º^ý÷Õú¯Õ hº9Õ`Û'ømÿHÿ豟u›"â?ë÷&ìùÿõ®/(mþ¿•…zÛï5é}ëïïfüà ­¬ÑÞÝÝ=AÔÍ™3'˜ùá/ÀâÅ‹ÕÔ©SK’ˆóÖ7ä3ÏŽpAQõ²«Ñà¿á ñï£õ_)ªÿPHÌ›\gÚPOØñª{xŽ.€/ÑÏ^@k.ËþeµÿÇ«ÿ¡ PÓ3Õ«\Ÿ¸IB½ü÷¢êý£GÏSÇŽ ÎÇ‘”I÷—×"¢_Ä¿˜åÖßf™Û“Ö™ÿ/ÊöíÛYöoØ@ü»Œ(Eõšj˜fÔ ¿Dõ”°ºÊnùÏÚÑËñˆ{€ÖûyÂßEüGoÿѱµš®¸.wÿ­$ÖiíoÎû&UIf¤R»ÿþ  .Fu'J0ç/HÒÿ‚ Æ%ý7J¸b´Öö$;âìÙ³…G§œ¸ûQ׫ÿy~ñ¯TþòiÂê?dˆn“ëâ?ÍHýµœ/_-e[I&€RåWÿ1ZÓðYýO:wXÕç?ÿùES¦L™åj´’Poû¡Š½o’ì/-þá\¶Th%ìOrÆíDë ¿ÌûËÜ¿ Iÿ2öü00¢¡—ê›ðX.<ûì³?Ò9ƒêzð_\Ü­ü×SÄ=Õ h²‰fd™õ á?_WÌýt²¸7½­Éo…Ië¿JÿAûÿç>÷¹µ®/Îf.›*yg"ö%ìïâÅ‹ÁùÁÁÁ ì/Þ¦Oú—%þL“þ10¤³DV‘(ŠGyï‘GyKVÿmBÿlÓÿ©þc@ Þäº$‘ŸgÔžG’ðÏë8ÈÛÄh_SÀGûÒÜ¿JÿÁoÐÊ•+ oˆoL‹8Rá?xðà˜Ø?sæLÐöxRññ?iÒ¤±¤¡’ü•¿Í*¼Fù|…£%EÐc)W~øáGôIYö/ü—×àög:@õJ0LGLFòŒ…¤î‚¤ãºƒ€Ð>F€I@Z¶LVè_=ÁC—ž³^ãôäõθm8â»ZB½ Æ’þÃöì#GŽL¸Tú%é?ü‰ø/ÃP¢Zß¾¯ñøñã^Zÿß{⦅¿ýöÛÝêú²e$þ›¤þ+•<*@õ,D¾Ë}MMŸßéKÚŽËÒQк@ü7"-P6J–øïJØ­Íž=Ûika@Ur áôéÓã’þ¥ @.‹#ÉþË–-Kúñ/&@#Þ öØžMáxIôÌÿ‰ï~÷»?Õ'/_û?9¢ü&þ tüaiÿ7 té(Hÿy_æ_x€¶3”Jî ËjÿW¦âÕªU3uËõ—'ï{]öª uL‹üÛ†ËúÉR‚^K=˜÷×âj‚(Œ&ýK»¿$ýKû§W âÈç+ü¬eëÖ­?Ô+HJåPñŸd¤Uò©þc@D¾ X¤ ÍÈÿ5ƒ/y-)ü³ÌÞ¤±´pÙ$á¯2ÄÿØNæŸþ韮UŽÝcÑvmªäkZHÒ¿´ü‡Ë°IUVÄ<˜Mæü%éÖ¬Ñ'ä84:E¸bøÙÞÉ“'ƒ“¢:tè­Ç|»ºÞúï*þ‹Œ˜vPýÇ€›qá^d ïtž¨¯ñEhYÑŸõ¿=ÉN[&þ[0¢’«ÿ*cGS:Vº¾ ªuTE|w’i!•ØhÒ¿´eKØŸ˜Q¢Iÿ‚,ñ'Ký’ˆór¶Yå×(KJÆ;K\П݋÷ßÿ£j´õØ“ø·øõ ñž×À¾?”`dUçm»Š ÿ²?yýÉú_œô;4:–õ¿;^ýÏ›7­éöëeN? zg½Q+ ¾«iZ\ºt)˜ñ¿råJp^ª²º¢:AØI¥_*ÿÒ Û–ÿo¼q^ámVõ5бtâÄ /Û{çwžúàƒŽªÑêÿpIâ_eüV*;ýßec€-e×t™ÉH@|G®^à9&št(þI´i¦nšÕoÿOÚÙLÛñºôzëNÀ”)SêlZH¶»»{,é_F’„Ùüùó•î2 ^Ÿ‹-*µsC ½_£|Æ|´þëq•ž»îºk›>yÅAü䈥ò—÷3íPŠê?TÆP*IÀ"ϱž#ô]·GÕ ù¿KIÿ“ëA-ç7-^ùîdÖ2žCM¯Ã¾ÔåET¹ýŸÖþrß·3gÎŒ-ë'Ù}ûöÍÿGYºtipÄ0Š&ýwšpÅ(Ž|Æ|´þËÓâ‰'Ðc+ƒÊlÙ¿¢Éÿy¢ß¦úŸ PP€§í˜åUk²N»î(Ö<¾Vh,yfn’él»¬m^»é„ùÝÂ?E§°/vyAIUêí,¾›ý¾I¶··78-!{öì F¢H¢¿$ýÏ;78/sÿ"þÓV@œcä!F“¯Ôÿ>úèù_üâ¨ñÁeˆ¥ìºØoÇ€’¾© ¶c¦ _ÏÑ·ýÊ2\§TÂïNÔ@ÈÚá¬é–j±æ´ÿ’f ÔÛó½×"Uÿþþþà¼Tb%é_B㟠û güu‡‰QÒ?â¼qÛlÅ×(ÆSÉ H3LMÛŠ´ÞïQžÈÏúýªçlcì¶ðༀ€ªˆoL‹ìÛŠÈ—y-ž‚óR‰•óq‘§»IñŽ‡Ìž=Û9éC€×"fÓàà —ç±uëÖj3¡ßƒøOê°É úÛé²éÈþyf€­øP)¿5ñÐÀ¼ T×âÅ‹W”a ¾ÛÇ´6YæïêÕ«Á6;¦Ž=:áv:LR­[·n,é_ªþ3fÌ@œcÚ¦Týeu èÏñ¯{ì±·UrðŸMò¿I RÙ•¥¨þc@K˜¦F€‰u¹ÉŽ´®hw]A¦–³™—ý½ªéíå./@DžÌy#ÔÛ©¼Ê²~"Â$y}ÿþýc#QdY¿•+WŽ%ýËùF„Db´ÿkñï£õ_Yguêÿ#úä¥kâ?-øo$Ãð1@õZÀPF@Öå6B¾Æ?€¶þ¦ÿû“*ú&[O8Ÿ–:Ý¥ç´}‹;Zû«÷¾IÒOOOp^ªÿöŽDY±bE°´Ÿ&ý‹ uˆór¶ÙίÑcê¿zá…~¤ ,IR׫ÿ6Uÿ¢3ÿYéÿTÿ1 b&@ÞmëbÝTÈ#øÚOðgýOÏ ‘­©äðÙ´û&IÛ:´°Ài‡grþ.â»uM \“ƒ ³×ö'&@éY»vm0ç/HÒÿüùóS;C¨ÖómÏÛéÓ§½<–YyÓ¦M¯©Ñà¿°úošúïcÙ¿¼¥õPa@¶;}>¾ð„Tó7&ïwZNLÖé¬ß%ÃzLÃéJþ<—ÖŒÀª õv55$é`` 8/]Òö|IIÿá’ˆs ¢Û”Ç“Ö;ñ`$\¼÷Þ{P[ÿËHýW&@üÿq^Õ (q­æñöyË=e}ik^T—¼pٸொ|“Ùÿøó¨iw“®äßà´Ã3Ùl—‡Öþj™Y·•9ë0é_n×ÛÛ˜qDô¯_¿~l DRþ‹$ýc`Ä‘œ‰‹/zy.o¼ñÆ–;vÈ,ËUåüg“úŸUåO›ÿwÙgß<5‡/^Íò Zã ÐÖÂÞö÷ ÉÈký·5£'<çÛn»m‰óÏäöÝåéDÓâÊ•+êàÁƒÁ±¶)ŸAé<ñ´þßyçϪÑÔ“6ÿ$ŸvY#–ýC`@ƒL›¹¤2Û@å°M¨Þo‡­Q&ü³N'm;É,Ⱥ\ÞµlٲŮ/¸ ~Þ7©øKå_:†††‚yÿ¤à5 ú“À?ABþDüO›6­aï-íÿ¾†'ñë]Эÿƒwß}÷ýjtîH%Wð‹,÷—×þŸ÷[AðTpg®h+~­À}]aï 5Œ‚´Yþ´ö~ßti·Ðé‡Fï¬Û,ˆP/ÿ½p}ßdÖ_’þeÖZZ®%é_*°ñ¿·,ñ'Kû 2ÿ/aQˆj=¯ÑÇ6O:5áóçŠNýd×®]ÇÔõÖÿ¬p¿"ÁJ±ì´ÝŽZ­àý)ÎùçP-lW‰Šþ¬$ÿ¢¿)µY³f9aû7⻵M iñ?~üxðüŰ¿øzëRé_·nºé¦›‚ó2÷/F@ž„!Àk´E (Yöχzû¾ûî{E¶þ«ìп¢Ái"Ÿeÿ0 ƒ€¼/,U{€öÿ IûŸoÛêŸw¿¼Öÿð¸kÆŒN@Ùíÿt ”ÿ¾IÕ?œ³–åþ´`špiï—¤YÞOП— ÀåýÆà5f!(’úïƒË—/|ç;ßyPoýw©ú(·à¿$#€eÿ0 Ã_zövÚç·$IÀ›Šú¬ß‡¬ûtÝpà NKJU¡ÞÓÂ÷û&þÇ«ÁÁÁà±å´qDìKҸܣ¤ü‡]W ßÛñ/ù>žÎÖ­[ÒÝ,§ÔhëÚÜ¿Ë쿯à?–ýÃŒ€†™ÐLa1ëŸöüjºÂ;ÛåΡ(D|·2[-•~]! Ä–´ü'µ\K•íÚµÁk—ÃܹsKKúïdCÓcù Š!å`ùú£>ú[u½õ?+½?ÏhFðûþÐ"F@³Í¨îïCÖo„‰èw1j ÷©Å®«éyn§ÅÛmßÕ08d¾:Lú@Âþ.]º4ávK—.UK–, zŒ&ý#\y¾·)¦T__Ÿ—íèÕ,Në[ßzDŸ¼¤Ê ý+3ø‘˜ÐF¿5‹ÛÛü–ØÞ¶¦çºõ(ÿä™./&è¡ÞÝRa “þey?Yæ/Þn-ÏeõêÕàvhuÎC<éáŠ!às›á’ò¹ôñ°O=õÔý:ÔR‚-†Ôõà?Ûöÿøì?Á€Öf¦d {×YjñãÏ|æ3sô±S)ßµ Åw³M ©®†Iÿ2g-#qÑ'†ŽÌûëU!‚ó’ô/âßôïŒ!ÀktA–ü»zõª—Çzÿý÷ŸyòÉ'§Fƒÿ† …ÿˆè·]P)‚ÿ0r¾ä˜e’´­š®öÎu}Àhâ»zGx{þa{õ‘#G‚óqâIÿ:2˜ù/ò7bžC ™ù—nèÕ,üû¿ÿûObâßVø».ùçügc``@‡6;r€Y`óûQÓÞ9¾ Äwµ i©––ÿsçΧ%쯿¿Âí$ÕݺucOé´„+¯±ÌmÊø‰Tÿ} ;.~ÿûß¿ûü¨›pUe/ùç*üóÒÿóöïë—€wÃÊÅe¯»Œ.€šáeÒ×Ý5{öì–0è.°{}ÒR-KûIÀŸ¬É¼¿G›p;iñ_µjÕXÒ¿þ<”žô!Àû*Ȳ“žæþÕ‹/¾ø£wÞy§[¥/ùgø7’p(˜·ÏβÐʺ¬ àjd þø*2tõ×ÙHš G¨7ÿ½Ñ/â_L€´°?A’þåþ-¥å_F®¼Æ²·)#)² …öíÛ÷Æ~ðƒ—Tò’Ib>MøÛVýÓL»\)Zÿ1 #Ì€fÎø›l[Vh耭.¾«nZˆà—9©¬ŠÈ:pàÀ1&»µk×Õþ`§U'üKêRÒ?ÂCÀ÷6¥e``ÀËãêñ–ÞÛo¿ý‡jtÉ¿!•Þúïsî_©ìö‚ÿ0 ƒ{×>c\w€NzwZЗ@Ç€¿÷B¸œš‹gÊ”)AÒÿŒ3ÆÎÛ$ýw²pÅô(Žt¥È*>Пó¡Í›7ߣG $ØBZÿ‡ ÿ¢-ÿÿa4<í߯@¨iè4ð5ÿPoì{.í'jrZªþaêIö—¤YÞ/osÿo¼ñÆ–mÛ¶íT£­ÿÃâݵÀµC OäÓúÐ03 i, 8è§€Ö~ÿ·íïï—ùçà6Ò â*Ž$ûKØß7Žz;ú'•ÿ¬àÆN®TëËABÿ’:S\8tèÐ;wÜqǶ˜ø¯+û—%•ð7mý c!Ÿ6ã_3ÿî«+ÂN­$ìÛ¥c@BÔBAµoß¾`®:ŽÌöË2bÓ§O÷–ô!€!`ƒ´ýK>…tÈeï׿þõûõIyÀ¤Ð¿¼j¿MH`‘Öÿ´Ûd7½0  ~Öy¯ÛÒIð“u%j™­ýÅM 9}ôèÑ@ðKÈŸ„ýIè_úkÖ¬ëÎ3 Ì¤  4dL%É rA^—7mÚô]=î"k[†sÿ&U}›Ù~_­ÿÿaTÂ@ˆ/¨æÍ›7ÝuC¾3ª*¾›mZHµ_ZýEðŸ?>XæohhhÂí/^¬–/_>v^fÿÀN›uGœ7w›bR>}ÚÛsx饗}íµ×öªìÐ?›¶Ûª‘ÖD=@é&@Ò¨ÀtÅxj+¿Ðvï!%â_Ž¥Z’þ“ÙêÕ«ÅÌ Î‹13{öì Iÿ$\çÙfÒöİòú÷ñÇ¿tÏ=÷¼ Fçþ‡T~èŸIÛ¿mÕ?ñ­P´þ4Aì+±_K8®éñiõjšRñ—tÿPPé´ ·‘P?™÷Ÿ5kÖØyÓ¤  ßÛ|†þõõõíû×ý×ÿ§ÆÏýÛˆ~q_…ÖÀ„}ùÛÐÎ@+ŠôVÉ#ÙiIú—%Ô<˜ØN-á~7n þ ý+’ô!€!P ©¼|ù²—ÇÒá:ñÿ.%p^Ÿû·ý#­ÿ*CüÛ~Ì €ÒÍé¨ä@'w ˆˆ’ƒÌù˼¿ÌýÇ‘`¿uëÖ‰}i÷÷ô!€!`ƒ˜V.\ðòXÚøºúè£ÞõÁôè³WTþ<¿ËŒ¿© $Öm«ý´þcxöµœÛL˜–6(n²qKñ@kömå2©ú‹’*ª$ý'-¡¶`ÁµråʱûKÒ8Ш×ÙLáŠ8¯Þû*ã*Þž×Ë/¿¼ù™gžÙ¡Fçþ‡•¿ê¿1€¸p§õ0 T¡ïíquùÔvxƒZ}©A™™îéé *¨YIÿ+V¬P‹-;/aÒ§WªõÕÚÞÕ«Wƒ_¡;wî|öî»ï~."þó„½Mõ?é>ÍLýÇÀ(dÔlŒƒ"€‹ ! 0Y@IØŸTýEHÉÌ\LI²ÿÚµkƒtÿð¼ˆÉ@¸b4k{b\IèŸdUø@‡]îú—ù—ÍúäE5ú7œ#ìóþ‹ü©áo*èiýÇhˆ!6wÉi7•·«9¦…ÜVD¿,ó'Õ~iÿ?zôè„ÛIÈ߆ Ô 7Üœ—¹1$ôáŠ!Ь÷U΋øOêTqAw¾ôjñ§^òrP%'þÛTÿóFF”YÕŸÖÀ€ÊˆüÂèJr¥÷WZ½µ? ™õ?~üxPEíîîNLú—ù~Yæ/û²¼Ÿ¤  ¢HP¥ë^K›—6mÚt—î„9¥Òÿ]ÃþŠ.ù§bAšø§õ0 ‚?5,PÎë:óÛ)­ýYô÷÷K»sÐþŸ–ô/B_ÚþÃ÷Jò¥ò_æ{GÀï« }}}‰•®Oõ¿øÅý¯¾úê'j4ñX™Wþó–ú³1ÒÄ9­ÿ€-iL¸_­ƒ•x³º z{{@’Ó%é?©ŠºtéRµdÉ’±Ç‘ö™ù ;ªõl³Û“´ÿÁÁAoÏí­·Þú¯Gyä7ñŸ'à]ĽmÊ?­ÿ€íg h!ÐåKT´‚øn&”&3þ"ž¤ýß¾}Aû ÷[µj•š7oÞØe3gÎ F®ÍÞ^øÙõ…6ÀÞøÆ7¾ñ”>)íW•ÝR~®•W3 MüÓúàG 'ù$h¡Ž‹4þ .»lúôé’þ®l³YÛ“Š¿´ýûÿòÔž~úé<ÿüóéÓ—#âߤêïZùQöIÿ¶)ÿ|À€† þB3R ¯×‡Ъ­ýY¢IZþÏŸ?Òö‹¥ÅݺujÖ¬Yc—IÊRÒ?ÂC ۓϬ˜Xq㪯¿þúã›7oþMLüûªúçÍý§& ¥Ì—üË}ûùYèŠÑP.PÞ«j`ÙFDÚm¥]Z–ù“´ô'N¨C‡M¸$úKØŸTûC¤ê=ß ÂqÞ¾ï«\/3ÿ>Åÿ‡~øüüÇüâšøRf¡6KÚVü}-ùGë?`@eÿоBÁZ¥µ? ™óïéé D“1âÌœ9S­_¿>èdÎ_æý‹$ý7K¸R­oÏ×(§e©?ù<ûBÞÕËý=¢F—ûRÙíü¶³ý.#6sÿÊQü@ㄽéí›=ЪDÍ…ÁÁAYÓ<3éþüùjÕªUc÷ “þË ûÃÀpA‚+¥ƒÅ½½½éK_úžö%Ód¹?Ûöÿ¤êü8­Â¯.óµäæ@eŒ€1ôŽùP;ew œ={6˜ù—ÊÿÞ½{3 ÎÒ¥KƒCˆ$ýËü¿l«Q] ¼¯yHå_B+=š Ý_ùÊWî8+_³Ä—Ð?ÛÊ\ô³ä`@G ;©µ"¾F!ÔË@Òå SIú·MKuíÚµA¥?Dfý£áU®ˆs ßâ_a'ÿíßþíÛÚ니1ï#ðÏÖ`î0 3LݶN ¥¹ ·Ñ­ÍêܹsÁA*ÿñ(™ë—°¿o¼qì2Iùžo7É6³·YÅ×(·—¶Ÿâ_bwÜqÇ7µ)v,&þ‹þe%ûXšÊ@èÛŠ ¨6E Ÿeu—Ûæ!B?Lú—¤ôîîî ¢KD¾„ýI«(¤ê/+´‚pÅèŒ×þùœù×£07mÚtÇöíÛ»•[Û^û¿Mõ_©üŸ"s0 Ú\)÷íÛ¨Jk—/_Ä¿ÌûK蟜Ž3gεfÍš±p?9–eþ|$ý#\1|m3¬üûÿÚ»ºyóæ;_|ñÅ"â?¯õßGÛž  R„¿R´þtuÝú[ láS¤càÂ… AØŸ$ýˆYæOZ¦£H¨ß† ƽIú—@„+†@•¶)·—e*¥›¥ tæÿðÿ°IwÉ ¦ˆŸÂ?­ÚŸgÄ…âs0 å ƒ h ÐšaÒN_¦PT\:u*h“–ç)añ%Ò$ìoÍš5A«ˆ¬Š iÿ>D⼜mvâû*ùbf•5zóÑG½ü¥/}é‡×ÒþÓÄÙ#*½Å?Mø#þÀ`g¶p@•‚£Hµ_ZþeY4NŸ|òI03E‚þ–/_>î2ép]qÞ¸mvÚû*Ÿciù/cÞ_رcdz_þò—7ë“Ä¿kÕ?/ðÏfÞ_)?‰ÿEþ_`@ËÁŽóµ/gÊ EÍ€˜ö'Iÿ"úu[sp:Dªý«W¯VsçÎ'æ¤å¿ìn ^£ bdIKY-ÿò2^yå•ǾûÝïþòšøJÿE«ýYsÿ¶iÿy‚?OÄ#ð*#ÌkžÇø¶çâ=ñ–T­@„’TþŘá´oß¾qÏQ¾ÌûK¥?jˆø&ý#\1š½M1­¤å_L€2Ð;ôË_þò¡xàU}ö’­ü»¶ü›¤ý'Uý‹ÿe'ý/¤õ0 ­ h0 ÉmëZ`T¾À©ö‡IÿúwðàÁq¢LæúEüKÀߨÛäÉAò4áŠ!Ðìmʪe¥ü z,æâ–-[îyê©§ÞÕg/;Šÿ<ÑŸ—öo»€R„þ€»FÑB¹P€Ì×7䉿ŒHµ_ÿ„'NÈ:æã®O û“nÿ6ÂŒ€¿ò·ÙÉï«t«HÕ¿Ìï•Îý8£«þw¾ð _ÿC–âß4ÀeÖ¿Ëý!þZOÌ«ñYí²c—ëYùBeÆFY¢Jªýb"üň’ö'Ar("ü¨Öó}mSNËøŠTýËjùôwåÀí·ß~§Å<¦Ï^qÿE–ú³­þ+År€m*Ú½íúþýûÏ_Ûïr1Rµ”ùùF¦¨0“óaÒ¿œÖ¯E9sfœˆ“°¿yóæ{™ÿŸ6mÂC Û ó*ʧéîîþŸ¯|å+÷õ÷÷Ÿ½&þ‡-¾kÕßt©?“ªšèwóˆÀ€J ý¤*Ía·Ã:l쬞‹Ÿ]DÀ4ˆ"¦Ãñãǃª©l_’þen:DÚûׯ_´øGEœˆ¹Îfe„+†@YÛóJ>·e-ï>ýßýîw¿üÚ×¾ö¸þÞ„Ëü\3ê†âßµêïÒþ¯”ùr$þ`"X¡F® S™ñ—9i1vïÞ=nô›o¾Y­]»vœÐ—Ó²Ì_–HCœ7f›þ¾ÊçV>Ãr(ÝYprÓ¦Mß{å•W>QÃþêʼõßEü×-Ä’ð¯çüßBüt”è·¹oæy1Š<¹FR1 “þõsÄ´‚ºhÑ"µbÅŠñ;d×–ù³¼FŸÛòÒÓÓ³óßøÆ½‡–/ÌU•öçZýÏÿI˺¤þg#þÀÒ¨ëjd_‘iÄJ:¸l,àOf¦¥í_rBA—ö'c 2€pÅhæ6¥SE>³ 2Êêï½÷Þõ«_ýIdÞXŸ÷÷Qý7ÿEçÿÿ€ üäŒíPëÊzU k'Ož ø“. ü «¨Rá_·nÒ# ãî'¿Ì\ ^cò•Ï­t«4Ýapþç?ÿùüã¿­ìæým ños@ü€¥PÏØ9NÚ ÑK.ò¤_Fª¾<®Ìû‡ª¯¯O8p`L°‰È—¤ÿ¨Ð“þÅo‡8/g›¼¯é÷oÔœˆþž|òï|ç¾]»vU£Kü åˆtWÀVü›eŠ h{3Àdy¬`‡û´¦è†¥ šºïãñ¤Aºô:æc×'…ýIÒ¿ˆÿø’„TëyئÜNæü¥ê߈9ÿp³Û·oßvûí·?©¿3¯‰ÿá Ñ_¤ú_EñoúZNÔ›\n³ãìt;v¬¯è“ôiˆˆêíí›ñ#àÈ‘#c×'…ý…ËüÉ1ÂC ‘Û ?³ þÒaÐ÷ÄO<ôôÓO¿§&¦ü—mTEüÓú€Q±#ß!Ñz…;$èLxQ$%]’þEdÉA„¿˜¡¸[µj•š?þ¸ûL™2%p¼F×m‰ð—VÿF AwÃüî[ßúÖC:å_¾»Ñ–ÿ<Ño:P/Yü+ñoò?ñ†;ÁÁÎ÷ÁƒÏksYWÏSóÄ(J4éÿšÈ[öOÚú7lØ fΜ9î>Òuà+éCCÀ”Pø‡]*BÚü_xá…-÷Ýwß+jbП/ â?oÉ¿¬ÓˆÀ€¶íµlcì´4ýZH/* L ‰4úRýÏïÛ·/0ø"þã#þ7}útÄy ÛÄôH¾¯ÿ‹/6\ø zTg×]wÝõ ú;¦®ÏúçsŸ@⿎ø ;£Àµý?¼lD'í2$¬Ïe%i–¤U¡ÈÚ»w¯Î'…ý ñ¤„+¯±¬mÊgTV¢C£[ým®]xå•Wž¸çž{^T£³þWcÂßVô»Tüó?â0x  ‰Æ€ÍõbH¯ý§Š)ˆ.ÉgbHÀ_Ø=VþCñ¿`ÁµråÊq¢,\æ/n \1|oSªü¡ðo===;¿ÿýï?¼sçÎpy¿°êŸ$ü}ˆ h p¯eœ·yŒ´ç¤®‘³gÏö.Y²¤Ð“!ojH+µˆÿ°¢mû¡')ÿ .wŸp™?“¤  WÄÈ’Ž”p Êf ¿çž{î¹-=ôЯUú¬£ €2’þÿ€P‚`rŸºÞ½E7nšMú‹ië_·nš5kÖ¸ûHÅßÇ*¼Æ$ĈSªYmþÑ—¥¿ ïÜyç›uf<áßFø›Š|ÑøÀGqžwyÖŽ®M—@=çò`gþäÉ“… PyèNÕ××7Nü‡3ÿÒ= añ`¿p™?„«Ÿmbz\¿½˜Vò¹õ±ŠEQô ‡Ÿxâ‰ÍÛ¶mû0"ü‡s¸m ¿IÈŸ–ÿF‰ èH3!ËÈ[g»®×?^¶púôéÀˆ °={ö—ÝtÓMAå?:Û/N’ÿåà0ˆ!€é‘´M™í—Ϫš\í¥ý~ûÛßn½ûÕFÄ5ò7¢®Ïúç ÿ"@-ÿÿ€#ú}<¦0òÞ{ï+ú`"¦¤¢*ûøåѤÿ¸øO û¤# úX´ïó‹~6¥Ò_dÉJßoÃîÝ»}ß}÷=©ÛþO^þYíþ¶­ÿ¶•~Ä?´€!4ûŸ8nçüèÑ£´0:§÷¬"OJVT´KZooï¸kcÒöîܹ@øÇÃþD JËZÒ?††€éc†-þýú;±û±Ç{\/ï·W.í7¤òÛïMŽm*ü¾…?â0šl ˜îLè ýÉ¢€ˆ­0¬ON‹ø—–ë¨(ñáµqãÆ aaÒ¿‹džC \޲b•þ1´éuâå—_þÙµtÿPø%m[ÀÆ ð=ë_OúˆÀ((ê³.7 L\ pppð„žÅ_[Ôôc),8AÈ8p ¸Í§?ýé a²€\æK`R­ïŒmV´½zuþ7ß|sÛý÷ßÿ’>-³0òD‡-…¸Kåßg»ÿH‚¸Gü`@ „¬ÓÁκE7$"Lýu¢ùѦƒƒ‘€[n¹eB{¿Œ Ä Ä2¯1 ù…íýUòËø>\x÷Ýwuï½÷þ·þ^œWésþ¶@‘ná?¢²ÛüóÚýÿ€`¸³[³¸ír€ñó#ýýý…—1&ËüÅééé „¢,óˆÑ¤ÿv®îŸ+ü¡ðo£jèçxyÇŽ/?øàƒÏèÏ~¿]Ö/«â_dîßEø×3žG^û¿Bü`@µÌ“ ÀèmGtRÿÑ2žŒ,ÿ'þeË–M¸NªþÒú߉âC û>¡à—C4G¢Êèçyù£>úÍÃ?üs½ÊEV²–à²ìŸË±ëÌ¿Bü`€?ñn3×orÿzÎŽu°ó¯—$;üÅ/~Ñë‹‘°?ÿóæÍ› Eüç%ýw²!ÐI¦G(øE臢¿•Šÿ®]»^“Šww·´À\Éþ.-ÿ>Ë^âñ¢Ýd‡8É$ÈzœzÎñÈ[o½Õ£[­‡uÿ$//J‹:ií—Tÿ(’ô/â_Ž[]¸v‚8/iéV÷[¥ÂGú{ÿý÷_Öÿ_é¥4¥Õ? ÷6×yíøeE—øËû‚ø @è+»j~Öý]+k§]B¯è¥{õ2~K}¼Xñö~¹lÚ´iÞ…%†@u· üpŽ¿UÅ~ý]9µ}ûv™ñ1îþyB»ìê¿mÂxRvÕÄ?4ÁPˆŸ¶ÍZ•µ°9êËH”ÚdNKû¿J9–n90Zï5Êu¡ÐoõÊ~§N:ðÚk¯=·yóæwdÞ_%/ç—gý÷Õæï3èñ¼Ð` é¼R9gÏž=ºpá†<ñPFç½C 4Ĉš­*–ÛÉ€íˆÈ~Tø·#2£—°ÜñÜsÏýê™gžÙ¥®Ï÷Û¶ùûªþþ.Ay¢¿n(öÿ€à(ô]#íXúÂÙ³~ýúæ½H-&C™Dh„Æ€kçíû¹¢wÜ!ùíVÑÏBÏ÷ŸýàƒÞxì±Ç^Ø·oßiu=ÑßDøÿ>Ûümgýó*þõŒÿ)ˆÀ(Yô'…¦d™#ÇŽ;\å7$4Ò„h܈ŸO3 :ň,¡¸~–ùÒ)ß¹ãÇòöÛo¿¶eË–·õ*#¢ÄBLûÿ6Uÿ,Ñ?¢Ò«ü6Iÿˆ ¨°q`ÒÊ;òûßÿþàßüÍß´ì 7¯¡ØC“ ¼,É(ð1†àÓE{ô¾Q1}/¢—Ç·£è\Šþ;w¾ùôÓO¿ª{Õøj¿mÝEü1Êj÷/:ïø Ÿ&èm—T9;õ#ï¾ûî Ô~nÊ”)³ÚöÍMζÄM„Ð3.àã糄xÒuI‚Š¡?ç—:ôþo~ó›ßþô§?Ý¡Ï_V«ýyÉø6ÂßUü—!úm+þˆ (Qôçí0ç‰ý´}¥ÒÛE< ë•Íž=û3üIÌMh ´Ù3tôèÑwìØ±ýÉ'Ÿ|[g^œSÉ-þ#*»MÞ¶ÝÞG€k«¿KË?â(ô]/¯ À¤â7Ü×××íô;yòä]»v½«[üßÜ¿Ÿº¾|ŸI ŸRvKè𹜟ÉkQÊß¼?â0J6’L•°³¯2vòÇ:tUôàÚµky·¡¥9sæÌ‘?üðí­[·þV‹ÿ“1ÑïRéw(Òà³Íßµåñ€-`Ô Ì€DsðàÁ}_øÂxG¡¥Ð«\Õ•~]àß¿ëå—_ÞþÖ[oIý¦•ñ"¡6¢ÞEð»üùhù75ÿ€PPØ›ÜÖt9À¤þ!жçoÿöo}*xçÊ•+ƒ:ÈïCÜÿþ¶mÛ~¯—ð‹Ïô+·Yx_¿¨ø÷]ñ7ýÌû`@…Òù´Ûe-˜$ ‚´½{÷ž9pàÀÖ… ~~ÆŒKùS@•èïïïÙ·oߺÂÿ»çŸ~¯TþÕø*4½?-Å_)3ÿ.+؈}[ ë{®”yË?âÀspÙO¨%œŽÇOG] ÇñÓáaRÆé)ú0]¦ýÑýÑ¢¿ø‹¿ø_«V­ºuñâÅŸ™5kÖ2ös ‘èU)N÷ôôìÖÆÔîW_}õÃkóü"ö‡Trrž.sæßÕ ðQé/º´ŸMË?â<ì+äiâ?ÏÈ:Ä €ð0ùÚaJx¼qãÆyÚ¸uÍš5-Z´nΜ9ë¦L™rNð,ø?ÁÿÚk¯íÒA~'Ôõ |¹>ÑÛˆ¶ý"€RÅæüÿЂ€‹ Ö 7¢¦@`Lš4iòŸüÉŸ¬ÐW®\¹^ ¬ÕK®Ð—OáO &œ;wîdooï¾Ý»wüæ›oîÚ±c‡Tø³æøGÄk#«þEýˆr7lÌ SÀô´­¨Gü?êŽ@šøW)Âßt Ið§™&ÝÁñôéÓ§Þzë­‹n¹å–•ºS`Í’%KVkS`‰Î˜Ç>RgséÒ¥³z™ÉÃÇŽëÖiýµàÿD¨üà>“5ëMEQ#`¤„ëÚ¥êø~Ô €¸ðWÊ< ­ –#þ³.7=LJ0&-[¶lÖÿñ‹)°\›Ëu·Àʹsç.×ÝSù8´W¯^½¨ûŽëê~·nçßóë_ÿz÷Ç|ZoãÏZžOÛfVþ}WöËø3­ô#þ0 û Íp1’: L·˜:?`òm·Ý¶pÆ K´A°hÁ‚‹u·À¢›nºi¾î˜ÛÕÕ5‰Jký¾¾¾cZìíîî>¢çö{ôÒ|Q±Îï'µñ›V­‹VþËÿ+Cø+UnÀ_^Ë¿©¨Gø?ê¼฿55 ÐåÙ09d ÿ$SB©ô.…IÑÓz”`òg?ûÙ…ŸúÔ§ks`ñ¼yóêÐÁ…7ß|óÂo¼qN­Vëâ#Ô0êÒ¾¯9¥…þñ'NÕKEö|ðÁGtU¿/"î³Bú\ÛÔ]M€FUÿË ósyýižª?´˜eä‰_&@-ÃÈ2j†Ï]ÅkÂvµ0Esuðà<=N0_3OwÌÕËΙ9sæ\}ýlV'°C üs:¿O‡òÖ"ÿÔ™3gNëYý“‡:©ƒùNœ?þJLÜǯ2û6‚?ï2Û–ÿ2 2™3þˆ ¨¨þJÙ˜„º˜6Õÿ,‘ŸõÚ”q>}nºS`êÚµkgëî9º{àfmÌÑÁMú0[Ü4mÚ´õaFxÜŽûoõz}äòåËç/^¼xîÂ… ú õý¹]ÉÐÇguË~ÿÉ“'t»þÉK1Ak²ÜžMå9í6e¶ý—!ø}Ïñûžñ/"üÿЄýÛ¥Ò+ðY]6¿Ö` í}°¹oÚèAü¹t-_¾|ÆâÅ‹gép™zÔ`æ mÜ(Çzašî(Ð>Á´ôaºœrg}<]ç?uêÔ ó@Ÿl»âÈÈÈÐðððUîz¶^¹ºråÊ%9?44tE_?,— ZØ_ЇKZÜ_Ї‹ºBA ûA}¸¨Åü NÛ¿ Ûôôã…óöiËÒůËã&"ÓÆð-üóD³Lå úmÿTý0 ÷|Œ˜ŒÔ,¿Mð_# •s¾fñ~*e6¦e@˜>7a•&ØŠˆá<Áž'] —ª¿oáo+ø}.Âßæ}**üÿ˜Ì[ž¨§ˆÈº¸´XÑŠ°º&æ“.Éëu@Y&f@^³¼ée¶@ÝñzSÑ^/p_¡oz™ëò~6F@Ù]J•/üM €¬¿±Ïª?âš ú]vÎk†"k$"ú£Â¿+fäµÜ§™J•×P†x7yÿk ü<¹]Q ‘-ÿ¦bßFø›ˆvSÀÅ`0y]yïKÞ{n*ü}|¦d D ‚<³ žbDüt\øçUþãâ¾®Šwø6Ê0eY‹½Ä¿Röíÿʳ€¯;nS)¿mþuÇ¿£‹ Gü`@ ‚Þõvq# K¤¦ µ$#ÀVø›´þ»Œ¸ÌñÛš.—7Ò@üþ®f€* þ} ÓÓ¶ŸÄ?TØ0íH3ÒF¢â?Ɉ›¶þgêùÊÈúðeøií,þm¸ïËMžË\áosÂZØÈúy"o$Cè+e>ïŸ×úï»ÀFø72Ô¯Ÿ…f &€Oño"ü}^f*þ]…¿‰ `rñ€-$ìMDZ€©@ …~žÕ}ë¿I€‹!`"ümDU‚Ë^%À§à·ý6†@Q# ¨¸/bV ü0¼™QC O”¦ ˆ¨ÿi§£&D—ÊoûwIÿ/+ÀÖ pû¾Vr("ú}[ Y9EM"‚ß·ðÏ3ÿÐfÂÞä>iݦąžàOö>’ÿ›è2àb ¸~>l¯·5š=ÿo+þ}˜Íüõï?Â:Ì0YöÏÖˆš*CüÛ´ügµý»Îÿ·b@Úýê?®F€oÀÖ pÿ>M×ÓE¿4Âñ€ú6÷I:V–F@TôÇ/«e¶©ÿšÿo‡,_³ÿeÿ""¸è(€oqï#³Àæýò%ümÅ<ÂZÐH ÿËp1âÂ_ˆSáßìù3 OÔךð(jTÕ(£+ ˆÐoT•¿QÂñ€-n˜ÞÞdi@SÀ5ð¯ˆè/*þ›5Pó,ÊZy ¨ PÖe¦·±}\…>íþ€ÈO¼mÖ(@R7@Ýâñ]fý« þ}Ž˜ ÿšçÏ‚/# Q«5\Í€¢×¹›ˆ}„?@‡Pã-€’ö%L*Üysö&¢ÝµÒßnâ¿VàoÕ(3 Ñ«Ø ã²M²Ä¾éue Ä?@ @4“¬PÀ¢i—™þ¹ši×ÿ­0ÿ_D(–5àKü—-â)ö]–ïCø´t@™û¦Ø$qߤror}Þã› ýªÿÕ<üÝ|Š8á˜'}UZükï“Ëþ\2lÅhÌß"Þå9æ]Wô2„??ÒM7\żë\E~™‚ßwտȾ ÏxWñêÛ(Ã4pݶËù¬÷áPIÀD|û¾Ì‡ø/Û(Ã(_+øÌ>M_"ßå5ç½ÇÀ€¦ïcØš®b¾UÅ~­„÷·UÄ¿O1ìºDž¯¥õšQÕ/Kô#ü0¼‹T—yû¢íúÍšã/k‰¿V0|‰ÛzÏûôýÀ€Jìkíða´‹ð¯Ú>^³L_b¼¬ ~+ˆ~„?@ÃLß"݇ /Kà·CÅ¿,# ¨`n¤aàCð¹áÐV&€/ñîSð·’è÷¹XVˆ\Yf@3/s¹ÑÐÖûEŒ€F {ߢ¾Ö€÷¯ÑÔ=ÞÖE8—aøüUý~ˆ*k”eØÞ¶ À÷mÊØô%}ˆ[qݬË} ~„?`F@ ——u]Y"¿Êûv¾Åm½×UeVÑÐû!µ ]׈ë}ì³5k_¯^òýê%^_¥–ýzþ&€д}‘Zů÷y›2öÛÊØÿkteºìñŸè €’€fˆõZ“_o£³ aY/éöõÞ¦ìׂè€BLâ-€6lï×l!_á_e¡Y¦x®JžÞBà‡ ’û'e òFŠ÷ZßÛVµõŠÝ¾LqŽè `?¥…{­bï[Õ…j#x½¯ÑÀþJ ‰ôZßv3êM|~À¨ð~K­MŸS;RoÓÇAô@ö_j-ô\[y®ÕÄs½MÞ `_¦ÉÛ`¬"¹ÞF¯€`¿¦Mö£Úi®S„7‚0Út‡ý¬æQç9ðÃìïðÜø~à€} ž7±üø°Obø±`_ ûü¨°}~¸ØÇD>?Nì‡â€öÛõÀ øß7D xàÿ¦'¶¸»OÌoIEND®B`‚qbs-src-3.3.1/examples/code-generator/0000755000175100017510000000000015232633614017217 5ustar runnerrunnerqbs-src-3.3.1/examples/code-generator/code-generator.qbs0000644000175100017510000000755515232633614022640 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { // A code generator that outputs a "Hello World" C++ program. CppApplication { name: "hwgen" consoleApplication: true files: ["hwgen.cpp"] Properties { condition: qbs.toolchain.contains("gcc") || qbs.toolchain.contains("clang-cl") cpp.cxxFlags: ["-Wno-deprecated-declarations"] } } // Generate and build a hello-world application. CppApplication { condition: { var result = qbs.targetPlatform === qbs.hostPlatform && (qbs.architecture === qbs.hostArchitecture || (qbs.architecture === "x86" && qbs.hostArchitecture === "x86_64")); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + qbs.hostPlatform + "/" + qbs.hostArchitecture + ")"); return result; } name: "hello-world" Depends { name: "hwgen" } Rule { inputsFromDependencies: ["application"] Artifact { filePath: "main.cpp" fileTags: ["cpp"] } prepare: { var hwgen = inputs["application"][0].filePath; var cmd = new Command(hwgen, [output.filePath]); cmd.description = "generating C++ source"; return cmd; } } } } qbs-src-3.3.1/examples/code-generator/hwgen.cpp0000644000175100017510000000537015232633614021040 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char **argv) { if (argc < 2) return 1; std::FILE *f = std::fopen(argv[1], "w"); if (!f) return 2; std::fprintf(f, "#include \n\n" "int main()\n" "{\n std::printf(\"Hello World!\\n\");\n return 0;\n}\n"); std::fclose(f); return 0; } qbs-src-3.3.1/examples/cxx-modules/0000755000175100017510000000000015232633614016571 5ustar runnerrunnerqbs-src-3.3.1/examples/cxx-modules/mod1/0000755000175100017510000000000015232633614017431 5ustar runnerrunnerqbs-src-3.3.1/examples/cxx-modules/mod1/testmod1.cpp0000644000175100017510000000116615232633614021701 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include import Mod1; int main() { Customer c1{"Kim"}; c1.buy("table", 59.90); c1.buy(4, "chair", 9.20); c1.print(); std::cout << " Average: " << c1.averagePrice() << '\n'; } qbs-src-3.3.1/examples/cxx-modules/mod1/mod1.cppm0000644000175100017510000000233515232633614021155 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include export module Mod1; // module declaration struct Order { int count; std::string name; double price; Order(int c, const std::string &n, double p) : count{c} , name{n} , price{p} {} }; export class Customer { private: std::string name; std::vector orders; public: Customer(const std::string &n) : name{n} {} void buy(const std::string &ordername, double price) { orders.push_back(Order{1, ordername, price}); } void buy(int num, const std::string &ordername, double price) { orders.push_back(Order{num, ordername, price}); } double sumPrice() const; double averagePrice() const; void print() const; }; qbs-src-3.3.1/examples/cxx-modules/mod1/mod1.qbs0000644000175100017510000000130315232633614020775 0ustar runnerrunnerCppApplication { condition: { if (qbs.toolchainType === "msvc" // see https://gcc.gnu.org/pipermail/gcc-bugs/2023-November/842674.html // || qbs.toolchainType === "gcc" // || qbs.toolchainType === "mingw" || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "mod1.cppm", "mod1io.cpp", "mod1price.cpp", "testmod1.cpp", ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/examples/cxx-modules/mod1/mod1io.cpp0000644000175100017510000000176515232633614021336 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include #include module Mod1; // implementation unit of module Mod1 void Customer::print() const { // print name: std::cout << name << ":\n"; // print order entries: for (const auto &od : orders) { std::cout << std::format( "{:3} {:14} {:6.2f} {:6.2f}\n", od.count, od.name, od.price, od.count * od.price); } // print sum: std::cout << std::format("{:25} ------\n", ' '); std::cout << std::format("{:25} {:6.2f}\n", " Sum:", sumPrice()); } qbs-src-3.3.1/examples/cxx-modules/mod1/mod1price.cpp0000644000175100017510000000150415232633614022020 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include module Mod1; // implementation unit of module Mod1 double Customer::sumPrice() const { double sum = 0.0; for (const auto &od : orders) { sum += od.count * od.price; } return sum; } double Customer::averagePrice() const { if (orders.empty()) { return 0.0; } return sumPrice() / orders.size(); } qbs-src-3.3.1/examples/cxx-modules/mod3/0000755000175100017510000000000015232633614017433 5ustar runnerrunnerqbs-src-3.3.1/examples/cxx-modules/mod3/testmod3.cpp0000644000175100017510000000116615232633614021705 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include import Mod3; int main() { Customer c1{"Kim"}; c1.buy("table", 59.90); c1.buy(4, "chair", 9.20); c1.print(); std::cout << " Average: " << c1.averagePrice() << '\n'; } qbs-src-3.3.1/examples/cxx-modules/mod3/mod3price.cpp0000644000175100017510000000154015232633614022024 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; #include // gcc needs this module Mod3; // implementation unit of module Mod3 import :Order; // import internal partition to use Order double Customer::sumPrice() const { double sum = 0.0; for (const Order &od : orders) { sum += od.count * od.price; } return sum; } double Customer::averagePrice() const { if (orders.empty()) { return 0.0; } return sumPrice() / orders.size(); } qbs-src-3.3.1/examples/cxx-modules/mod3/mod3.cppm0000644000175100017510000000114615232633614021160 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** export module Mod3; // module declaration export import :Customer; // import and export interface partition Customer //... // import and export other interface partitions qbs-src-3.3.1/examples/cxx-modules/mod3/mod3customer.cppm0000644000175100017510000000216215232633614022741 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include export module Mod3:Customer; // interface partition declaration import :Order; // import internal partition to use Order export class Customer { private: std::string name; std::vector orders; public: Customer(const std::string &n) : name{n} {} void buy(const std::string &ordername, double price) { orders.push_back(Order{1, ordername, price}); } void buy(int num, const std::string &ordername, double price) { orders.push_back(Order{num, ordername, price}); } double sumPrice() const; double averagePrice() const; void print() const; }; qbs-src-3.3.1/examples/cxx-modules/mod3/mod3io.cpp0000644000175100017510000000206015232633614021327 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include #include module Mod3; // implementation unit of module Mod3 import :Order; // import internal partition to use Order void Customer::print() const { // print name: std::cout << name << ":\n"; // print order entries: for (const Order &od : orders) { std::cout << std::format( "{:3} {:14} {:6.2f} {:6.2f}\n", od.count, od.name, od.price, od.count * od.price); } // print sum: std::cout << std::format("{:25} ------\n", ' '); std::cout << std::format("{:25} {:6.2f}\n", " Sum:", sumPrice()); } qbs-src-3.3.1/examples/cxx-modules/mod3/mod3.qbs0000644000175100017510000000137215232633614021007 0ustar runnerrunnerCppApplication { condition: { if (qbs.toolchainType === "msvc" // see https://gcc.gnu.org/pipermail/gcc-bugs/2023-November/842674.html // || qbs.toolchainType === "gcc" // || qbs.toolchainType === "mingw" || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "mod3.cppm", "mod3customer.cppm", "mod3io.cpp", "mod3order.cppm", "mod3price.cpp", "testmod3.cpp", ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/examples/cxx-modules/mod3/mod3order.cppm0000644000175100017510000000133115232633614022210 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include module Mod3:Order; // internal partition declaration struct Order { int count; std::string name; double price; Order(int c, std::string n, double p) : count{c} , name{n} , price{p} {} }; qbs-src-3.3.1/examples/cxx-modules/mod2/0000755000175100017510000000000015232633614017432 5ustar runnerrunnerqbs-src-3.3.1/examples/cxx-modules/mod2/mod2.qbs0000644000175100017510000000135115232633614021002 0ustar runnerrunnerCppApplication { condition: { if (qbs.toolchainType === "msvc" // see https://gcc.gnu.org/pipermail/gcc-bugs/2023-November/842674.html // || qbs.toolchainType === "gcc" // || qbs.toolchainType === "mingw" || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "mod2.cppm", "mod2io.cpp", "mod2order.cppm", "mod2price.cpp", "testmod2.cpp", ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/examples/cxx-modules/mod2/mod2.cppm0000644000175100017510000000210215232633614021147 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include export module Mod2; // module declaration import :Order; // import internal partition Order export class Customer { private: std::string name; std::vector orders; public: Customer(const std::string& n) : name{n} { } void buy(const std::string& ordername, double price) { orders.push_back(Order{1, ordername, price}); } void buy(int num, const std::string& ordername, double price) { orders.push_back(Order{num, ordername, price}); } double sumPrice() const; double averagePrice() const; void print() const; }; qbs-src-3.3.1/examples/cxx-modules/mod2/mod2price.cpp0000644000175100017510000000167215232633614022030 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; #include // gcc needs this module Mod2; // implementation unit of module Mod2 import :Order; // import internal partition Order double Customer::sumPrice() const { double sum = 0.0; for (const Order &od : orders) { // ERROR with VC++ //for (const auto& od : orders) { // OK sum += od.count * od.price; } return sum; } double Customer::averagePrice() const { if (orders.empty()) { return 0.0; } return sumPrice() / orders.size(); } qbs-src-3.3.1/examples/cxx-modules/mod2/mod2order.cppm0000644000175100017510000000131215232633614022205 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include module Mod2:Order; // internal partition declaration struct Order { int count; std::string name; double price; Order(int c, std::string n, double p) : count{c}, name{n}, price{p} { } }; qbs-src-3.3.1/examples/cxx-modules/mod2/testmod2.cpp0000644000175100017510000000116615232633614021703 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include import Mod2; int main() { Customer c1{"Kim"}; c1.buy("table", 59.90); c1.buy(4, "chair", 9.20); c1.print(); std::cout << " Average: " << c1.averagePrice() << '\n'; } qbs-src-3.3.1/examples/cxx-modules/mod2/mod2io.cpp0000644000175100017510000000176515232633614021340 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** module; // start module unit with global module fragment #include #include #include module Mod2; // implementation unit of module Mod1 void Customer::print() const { // print name: std::cout << name << ":\n"; // print order entries: for (const auto &od : orders) { std::cout << std::format( "{:3} {:14} {:6.2f} {:6.2f}\n", od.count, od.name, od.price, od.count * od.price); } // print sum: std::cout << std::format("{:25} ------\n", ' '); std::cout << std::format("{:25} {:6.2f}\n", " Sum:", sumPrice()); } qbs-src-3.3.1/examples/cxx-modules/mod0/0000755000175100017510000000000015232633614017430 5ustar runnerrunnerqbs-src-3.3.1/examples/cxx-modules/mod0/mod0main.cpp0000644000175100017510000000106715232633614021644 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include import Square; // import module ``Square'' int main() { Square x = toSquare(42); std::cout << x.getValue() << '\n'; } qbs-src-3.3.1/examples/cxx-modules/mod0/mod0.qbs0000644000175100017510000000120215232633614020771 0ustar runnerrunnerCppApplication { condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "mod0.cppm", "mod0main.cpp", ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/examples/cxx-modules/mod0/mod0.cppm0000644000175100017510000000137515232633614021156 0ustar runnerrunner//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** export module Square; // declare module Square int square(int i); export class Square { private: int value; public: Square(int i) : value{square(i)} {} int getValue() const { return value; } }; export template Square toSquare(const T &x) { return Square{x}; } int square(int i) { return i * i; } qbs-src-3.3.1/examples/collidingmice/0000755000175100017510000000000015232633614017123 5ustar runnerrunnerqbs-src-3.3.1/examples/collidingmice/collidingmice.qbs0000644000175100017510000000567315232633614022447 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { name : "CollidingMice" Depends { name: "Qt.widgets" } property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle files : [ "images/cheese.jpg", "main.cpp", "mouse.cpp", "mouse.h", "mice.qrc" ] Group { fileTagsFilter: isBundle ? ["bundle.content"] : ["application"] qbs.install: true qbs.installDir: isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") qbs.installSourceBase: product.buildDirectory } } qbs-src-3.3.1/examples/collidingmice/mouse.h0000644000175100017510000000571615232633614020435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MOUSE_H #define MOUSE_H #include #include //! [0] class Mouse : public QGraphicsItem { public: Mouse(); QRectF boundingRect() const override; QPainterPath shape() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; protected: void advance(int step) override; private: QRandomGenerator m_rand = QRandomGenerator::securelySeeded(); qreal angle; qreal speed; qreal mouseEyeDirection; QColor color; }; //! [0] #endif qbs-src-3.3.1/examples/collidingmice/images/0000755000175100017510000000000015232633614020370 5ustar runnerrunnerqbs-src-3.3.1/examples/collidingmice/images/cheese.jpg0000644000175100017510000000572515232633614022337 0ustar runnerrunnerÿØÿàJFIFHHÿîAdobed@ÿÛ„      ÿÀ^^ÿÝ ÿÄ¢  s!1AQa"q2‘¡±B#ÁRÑá3bð$r‚ñ%C4S’¢²csÂ5D'“£³6TdtÃÒâ&ƒ „”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúm!1AQa"q‘2¡±ðÁÑá#BRbrñ3$4C‚’S%¢c²ÂsÒ5âDƒT“ &6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ûAÓo¢‡Ç<7‰éÔéâk)n£rM ðÈ‚¥²AZ†úFù"7P¦cåâvù`ä•ÁHØt=F V¤š1`¤ìkã’ ¬I’Q­È‘·ê„4¯ÅŽûwÉlIb:¯ž<¿£Ìmîï+84ha£þU6~§§ïNŸ~eøžž/'‡zÿÑû?JíÔöÏ §¨Qy?Ö=°ˆq-Òš„j{d¼&aÆpJ‘Jt"˜øtŽ0UÔ‡nÛŒ ;@ÞÚ ˆšbJƒÄѨ|ù +|µ=ໞYâäÈbBÿ!%OßÇ,ˆÅÖý̼IŽTôk+[-:Ö+ e¶´€)þQ«îNç!–|g•À§šÝNÊ=NÂæÍ¶€PžÌ7ÊÄD½'«!#a…i¾\’ݽ;‹vJÕÆÿÛ˜Ù#,G„¹-€©Ï ·¨J/çŽÚ9îfqP!yôEI9|HËY²h>Ró'æšõKébÐIÓlQˆÒž«Ýœƒ×Àe>)ŸZr#†1çºqå_>y¢Öîõ‹‡¾µ”"L`R¬v÷ȆíÄ%ÈSé›I–EŠhÛœR…daЩfA ‹ØZ¨=5µ„ 1€{|ˆ34›jzïNMïí<™†¸5 ‘ZW·Ë5µŒ¬ k-©­ð9$.ãN„ø}H%A]ÈÔøø×#JÿÿÔûCÉ)Øðzz…zt ôÉÄð›Ô‹K­´}Ní ¿U”±fŽZ”ÿ`À~'›<ûÆ\'¸Ý|ý+Ò†ÄZ'è«`¾¤«xÊ(!ŒÛ“56ÄiñBbRÉ]"þò@jñrO¯4*³Ü¹øª±<@Ø|€ðrä–Be.e”ˆ ª@?>”Ê:3s1 Ü.ʵýXlõE!Üo°&§¬ z×åŠUÐöë¡} 4ðÚ¸ÄyªrRO]öOL<;Õ£‰ÿÕû8ÀÖ£®x]½B“G^„×¹Ä*€·]Ù¶5ÛÄâ(VH _‰ºøòDŒx‚6ªc¢€6##Í’Ÿ¨T|@úâ`–ê\ñ=ÎB’ºª*¤×ß TJT{cJ»wQ·l•*àkþKxd$ÛÔoô`WÿÖû=Q×–xSÔ/$q$liÓÙRnK‹}Q»³¡º†mÁb4ö­r2‘$&1âºf‡æhîª5;É®9 $2HÅ¢„Ҟ؀@«t¢9=âÔ¹†'‘x4ˆ®ÉàXTŒÈɵ*Ƈ®ô4Êì³RcÇzn{âÔL½‡\°´&жþq¯õ–”¯Ñ€Á"j«)$PŽ»ä¦V¦%#š’y)‘¥ÿ×û;ÐPÇ<*Þ¡PPûõÄ«¤U(A^JÀ†SЂ(AƃanöÑGéÃaF¯Ùgäƒè¥Oß™~.!¿þý¿$LõTS#3™$¶ÔÙ‹“'¾¬€¦…jFÕ4`½ÇÏä”5Á"ƒ¹é’Ç»0/8ùÂÇÊvB{ Ó\KQmj†!jeEz岘€óc—Ïòþsù¦æê–‘Ckk_†10»1©ÊŒæz·Œ1Ròoæ<úÄñXêð¤rÌBÅs*9”“JøŒÌA©5Ï«dа'¥wtã³Tdô–µíN™ŽÜÿÿÐû4ÊÛýÆxCÔ¶ŒAZ‘Ö§$‚¨O&@¯°Û¯øTo@r*´ÍU AÔø{âW§A×®ˆC¼m+- Fãl³c7Ë¿™¶7:šeˆ‚ÖÖ¡bDë@?‰9‹’w77 ÆK,ŠF›uðË,Ä0 [!‡Ë2YÜE…Ò}[.Òi½1!ñ#¾lqJñ‚]|ÅJ“~'Óú2¾­ÿÑû9-üNxCÔ0/2k^e°Ôôû- F‹QŠxÚ{¹¦vP[øþÖÕ©öÆy죌˫?µvx‘ =t=A"´>ã$Fì¹A¹p¶ pU vß׆Q€ì—râ4à ‡™yÃËku¨&«lÞµåw*àSìrYôüQãÇËöì«ÒQZF†„§«â‚”¨Úž,Àã2<7»q¡»'m®\E|˜ìÔO†CI£žLüÞÏö°É©ˆ”ÏÒŠâ´‚ºˆÃÿ7ÄŸ¦™¸ÍÁÃCo–ßo7w=U9ÓM©˜öÝOÿÒûy“§9/Ññîøôa>Ý^ÚêÜeÓL+È$ÔB|wäGß•œÚ~+ž;;ÝHú~‰G-}[{•'ŸP–)¾©d–Öá}麻ñïSÊ´ñ É㙜%áDF5½o*ëw¿¾€ b ÄI>idâÅá”§!ðÔeiÿÙqbs-src-3.3.1/examples/collidingmice/mice.qrc0000644000175100017510000000014115232633614020543 0ustar runnerrunner images/cheese.jpg qbs-src-3.3.1/examples/collidingmice/mouse.cpp0000644000175100017510000001524515232633614020766 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mouse.h" #include #include #include #include static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; static qreal normalizeAngle(qreal angle) { while (angle < 0) angle += TwoPi; while (angle > TwoPi) angle -= TwoPi; return angle; } //! [0] Mouse::Mouse() : angle(0), speed(0), mouseEyeDirection(0), color(m_rand.generate() % 256, m_rand.generate() % 256, m_rand.generate() % 256) { setRotation(m_rand.generate() % (360 * 16)); } //! [0] //! [1] QRectF Mouse::boundingRect() const { qreal adjust = 0.5; return {-18 - adjust, -22 - adjust, 36 + adjust, 60 + adjust}; } //! [1] //! [2] QPainterPath Mouse::shape() const { QPainterPath path; path.addRect(-10, -20, 20, 40); return path; } //! [2] //! [3] void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { // Body painter->setBrush(color); painter->drawEllipse(-10, -20, 20, 40); // Eyes painter->setBrush(Qt::white); painter->drawEllipse(-10, -17, 8, 8); painter->drawEllipse(2, -17, 8, 8); // Nose painter->setBrush(Qt::black); painter->drawEllipse(QRectF(-2, -22, 4, 4)); // Pupils painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); // Ears painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); painter->drawEllipse(-17, -12, 16, 16); painter->drawEllipse(1, -12, 16, 16); // Tail QPainterPath path(QPointF(0, 20)); path.cubicTo(-5, 22, -5, 22, 0, 25); path.cubicTo(5, 27, 5, 32, 0, 30); path.cubicTo(-5, 32, -5, 42, 0, 35); painter->setBrush(Qt::NoBrush); painter->drawPath(path); } //! [3] //! [4] void Mouse::advance(int step) { if (!step) return; //! [4] // Don't move too far away //! [5] QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); if (lineToCenter.dy() < 0) angleToCenter = TwoPi - angleToCenter; angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { // Rotate left angle += (angle < -Pi / 2) ? 0.25 : -0.25; } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { // Rotate right angle += (angle < Pi / 2) ? 0.25 : -0.25; } } else if (::sin(angle) < 0) { angle += 0.25; } else if (::sin(angle) > 0) { angle -= 0.25; //! [5] //! [6] } //! [6] // Try not to crash with any other mice //! [7] const QList dangerMice = scene()->items(QPolygonF() << mapToScene(0, 0) << mapToScene(-30, -50) << mapToScene(30, -50)); for (QGraphicsItem *item : dangerMice) { if (item == this) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); if (lineToMouse.dy() < 0) angleToMouse = TwoPi - angleToMouse; angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { // Rotate right angle += 0.5; } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { // Rotate left angle -= 0.5; //! [7] //! [8] } //! [8] //! [9] } //! [9] // Add some random movement //! [10] if (dangerMice.size() > 1 && (m_rand.generate() % 10) == 0) { if (m_rand.generate() % 1) angle += (m_rand.generate() % 100) / 500.0; else angle -= (m_rand.generate() % 100) / 500.0; } //! [10] //! [11] speed += (-50 + m_rand.generate() % 100) / 100.0; qreal dx = ::sin(angle) * 10; mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; setRotation(rotation() + dx); setPos(mapToParent(0, -(3 + sin(speed) * 3))); } //! [11] qbs-src-3.3.1/examples/collidingmice/main.cpp0000644000175100017510000000727715232633614020570 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mouse.h" #include #include #include #include #include #include static const int MouseCount = 7; //! [0] int main(int argc, char **argv) { QApplication app(argc, argv); //! [0] //! [1] QGraphicsScene scene; scene.setSceneRect(-300, -300, 600, 600); //! [1] //! [2] scene.setItemIndexMethod(QGraphicsScene::NoIndex); //! [2] //! [3] for (int i = 0; i < MouseCount; ++i) { const auto mouse = new Mouse; mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, ::cos((i * 6.28) / MouseCount) * 200); scene.addItem(mouse); } //! [3] //! [4] QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); //! [4] //! [5] view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setDragMode(QGraphicsView::ScrollHandDrag); //! [5] //! [6] view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); view.resize(400, 300); view.show(); QTimer timer; QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance); timer.start(1000 / 33); return app.exec(); } //! [6] qbs-src-3.3.1/examples/helloworld-complex/0000755000175100017510000000000015232633614020141 5ustar runnerrunnerqbs-src-3.3.1/examples/helloworld-complex/src/0000755000175100017510000000000015232633614020730 5ustar runnerrunnerqbs-src-3.3.1/examples/helloworld-complex/src/foo.cpp0000644000175100017510000000476715232633614022235 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SOMETHING # error missing define SOMETHING #endif int someUsefulFunction() { return 156; } qbs-src-3.3.1/examples/helloworld-complex/src/specialfeature.cpp0000644000175100017510000000503415232633614024432 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "specialfeature.h" #include void bragAboutSpecialFeature() { std::cout << "I have a special feature!" << std::endl; } qbs-src-3.3.1/examples/helloworld-complex/src/foo.h0000644000175100017510000000471415232633614021672 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FOO_H #define FOO_H int someUsefulFunction(); #endif qbs-src-3.3.1/examples/helloworld-complex/src/specialfeature.h0000644000175100017510000000476115232633614024105 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELLO_SPECIAL_FEATURE #define HELLO_SPECIAL_FEATURE void bragAboutSpecialFeature(); #endif qbs-src-3.3.1/examples/helloworld-complex/src/main.cpp0000644000175100017510000000556615232633614022374 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "foo.h" #ifdef HAS_SPECIAL_FEATURE #include "specialfeature.h" #endif #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef SOMETHING # error missing define SOMETHING #endif int main() { someUsefulFunction(); #if defined(HAS_DEBUG) std::puts("Hello World! (debug version)"); #elif defined(HAS_RELEASE) std::puts("Hello World! (release version)"); #endif #ifdef HAS_SPECIAL_FEATURE bragAboutSpecialFeature(); #endif } qbs-src-3.3.1/examples/helloworld-complex/helloworld-complex.qbs0000644000175100017510000000641415232633614024475 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { property bool hasSpecialFeature: true Application { name: 'HelloWorld-Complex' Depends { name: 'cpp' } cpp.defines: ['SOMETHING'] files: [ "src/foo.h", "src/foo.cpp" ] Group { condition: project.hasSpecialFeature prefix: "src/" files: ["specialfeature.cpp", "specialfeature.h"] } Group { cpp.defines: { var defines = outer.concat([ 'HAVE_MAIN_CPP', cpp.debugInformation ? 'HAS_DEBUG' : 'HAS_RELEASE' ]); if (project.hasSpecialFeature) defines.push("HAS_SPECIAL_FEATURE"); return defines; } prefix: "src/" files: [ 'main.cpp' ] } } } qbs-src-3.3.1/examples/protobuf/0000755000175100017510000000000015232633614016161 5ustar runnerrunnerqbs-src-3.3.1/examples/protobuf/addressbook_objc/0000755000175100017510000000000015232633614021456 5ustar runnerrunnerqbs-src-3.3.1/examples/protobuf/addressbook_objc/addressbook_objc.qbs0000644000175100017510000000051415232633614025462 0ustar runnerrunnerCppApplication { consoleApplication: true condition: protobuf.objc.present && qbs.targetOS.contains("macos") Depends { name: "cpp" } Depends { name: "protobuf.objc"; required: false } Group { cpp.automaticReferenceCounting: true files: "main.m" } files: "../shared/addressbook.proto" } qbs-src-3.3.1/examples/protobuf/addressbook_objc/main.m0000644000175100017510000001506515232633614022567 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import "Addressbook.pbobjc.h" #import int printUsage(char *argv0) { NSString *programName = [[NSString alloc] initWithUTF8String:argv0]; NSLog(@"Usage: %@ add|list ADDRESS_BOOK_FILE", programName); return -1; } NSString *readString(NSString *promt) { NSLog(@"%@", promt); NSFileHandle *inputFile = [NSFileHandle fileHandleWithStandardInput]; NSData *inputData = [inputFile availableData]; NSString *result = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding]; result = [result stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; return result; } // This function fills in a Person message based on user input. void promptForAddress(Person* person) { person.id_p = [readString(@"Enter person ID number:") intValue]; person.name = readString(@"Enter name:"); NSString *email = readString(@"Enter email address (blank for none):"); if ([email length] != 0) person.email = email; while (true) { NSString *number = readString(@"Enter a phone number (or leave blank to finish):"); if ([number length] == 0) break; Person_PhoneNumber* phoneNumber = [[Person_PhoneNumber alloc] init]; phoneNumber.number = number; NSString *type = readString(@"Is this a mobile, home, or work phone?:"); NSLog(@"\"%@\"", type); if ([type compare:@"mobile"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Mobile; else if ([type compare:@"home"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Home; else if ([type compare:@"work"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Work; else NSLog(@"Unknown phone type. Using default."); [person.phonesArray addObject:phoneNumber]; } } // Iterates though all people in the AddressBook and prints info about them. void listPeople(AddressBook *addressBook) { for (Person *person in addressBook.peopleArray) { NSLog(@"Person ID: %d", person.id_p); NSLog(@"Person name: %@", person.name); if ([person.email length] != 0) { NSLog(@"E-mail address: %@", person.email); } for (Person_PhoneNumber *phoneNumber in person.phonesArray) { NSString *phonePrefix; switch (phoneNumber.type) { case Person_PhoneType_Mobile: phonePrefix = @"Mobile phone"; break; case Person_PhoneType_Home: phonePrefix = @"Home phone"; break; case Person_PhoneType_Work: phonePrefix = @"Work phone"; break; default: phonePrefix = @"Unknown phone"; break; } NSLog(@" %@ #: %@", phonePrefix, phoneNumber.number); } printf("\n"); } } int main(int argc, char *argv[]) { if (argc != 3) return printUsage(argv[0]); @autoreleasepool { AddressBook *addressBook; NSString *filePath = [[NSString alloc] initWithUTF8String:argv[2]]; // Read the existing address book. NSData *data = [NSData dataWithContentsOfFile:filePath]; if (!data) { NSLog(@"%@ : File not found.", filePath); addressBook = [[AddressBook alloc] init]; } else { NSError *error; addressBook = [AddressBook parseFromData:data error:&error]; if (!addressBook) { NSLog(@"Failed to parse address book."); return -1; } } if (strcmp(argv[1], "add") == 0) { // Add an address. Person *person = [[Person alloc] init]; promptForAddress(person); [addressBook.peopleArray addObject:person]; if (!data) { NSLog(@"Creating a new file."); } [[addressBook data] writeToFile:filePath atomically:YES]; } else if (strcmp(argv[1], "list") == 0) { listPeople(addressBook); } else { return printUsage(argv[0]); } return 0; } } qbs-src-3.3.1/examples/protobuf/addressbook_objc/README.md0000644000175100017510000000035115232633614022734 0ustar runnerrunner### Addressbook objc example This example shows how to build an objective-c application that uses Google protobuf. In order to build this example, you'll need to have a ProtocolBuffers library or framework installed in the system. qbs-src-3.3.1/examples/protobuf/addressbook_cpp/0000755000175100017510000000000015232633614021323 5ustar runnerrunnerqbs-src-3.3.1/examples/protobuf/addressbook_cpp/addressbook_cpp.qbs0000644000175100017510000000062315232633614025175 0ustar runnerrunnerimport qbs.Host CppApplication { consoleApplication: true condition: protobuf.cpp.present && qbs.targetPlatform === Host.platform() Depends { name: "cpp" } cpp.minimumMacosVersion: "10.15" Depends { name: "protobuf.cpp"; required: false } files: [ "../shared/addressbook.proto", "main.cpp", "README.md", ] qbsModuleProviders: "qbspkgconfig" } qbs-src-3.3.1/examples/protobuf/addressbook_cpp/main.cpp0000644000175100017510000001442715232633614022763 0ustar runnerrunner// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" # include # pragma GCC diagnostic pop #else # include #endif // __GNUC__ #include "addressbook.pb.h" using google::protobuf::util::TimeUtil; int printUsage(char *argv0) { std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl; return -1; } std::string readString(const std::string &promt) { std::string result; std::cout << promt; std::getline(std::cin, result); return result; } // This function fills in a Person message based on user input. void promptForAddress(tutorial::Person* person) { std::cout << "Enter person ID number: "; int id; std::cin >> id; person->set_id(id); std::cin.ignore(256, '\n'); *person->mutable_name() = readString("Enter name: "); const auto email = readString("Enter email address (blank for none): "); if (!email.empty()) person->set_email(email); while (true) { const auto number = readString("Enter a phone number (or leave blank to finish): "); if (number.empty()) break; tutorial::Person::PhoneNumber *phone_number = person->add_phones(); phone_number->set_number(number); const auto type = readString("Is this a mobile, home, or work phone? "); if (type == "mobile") phone_number->set_type(tutorial::Person::MOBILE); else if (type == "home") phone_number->set_type(tutorial::Person::HOME); else if (type == "work") phone_number->set_type(tutorial::Person::WORK); else std::cout << "Unknown phone type. Using default." << std::endl; } *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL)); } // Iterates though all people in the AddressBook and prints info about them. void listPeople(const tutorial::AddressBook& address_book) { for (int i = 0; i < address_book.people_size(); i++) { const tutorial::Person& person = address_book.people(i); std::cout << "Person ID: " << person.id() << std::endl; std::cout << " Name: " << person.name() << std::endl; if (!person.email().empty()) { std::cout << " E-mail address: " << person.email() << std::endl; } for (int j = 0; j < person.phones_size(); j++) { const tutorial::Person::PhoneNumber& phone_number = person.phones(j); switch (phone_number.type()) { case tutorial::Person::MOBILE: std::cout << " Mobile phone #: "; break; case tutorial::Person::HOME: std::cout << " Home phone #: "; break; case tutorial::Person::WORK: std::cout << " Work phone #: "; break; default: std::cout << " Unknown phone #: "; break; } std::cout << phone_number.number() << std::endl; } if (person.has_last_updated()) { std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl; } } } int main(int argc, char* argv[]) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != 3) return printUsage(argv[0]); tutorial::AddressBook address_book; // Read the existing address book. std::fstream input(argv[2], std::ios::in | std::ios::binary); if (!input) { std::cout << argv[2] << ": File not found." << std::endl; } else if (!address_book.ParseFromIstream(&input)) { std::cerr << "Failed to parse address book." << std::endl; return -1; } const std::string mode(argv[1]); if (mode == "add") { // Add an address. promptForAddress(address_book.add_people()); if (!input) std::cout << "Creating a new file." << std::endl; // Write the new address book back to disk. std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary); if (!address_book.SerializeToOstream(&output)) { std::cerr << "Failed to write address book." << std::endl; return -1; } } else if (mode == "list") { listPeople(address_book); } else { return printUsage(argv[0]); } // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; } qbs-src-3.3.1/examples/protobuf/addressbook_cpp/README.md0000644000175100017510000000127215232633614022604 0ustar runnerrunner### Addressbook c++ example This example shows how to build a cpp application that uses Google protobuf. In order to build this example, you'll need to have a protobuf headers and library installed in the system in locations where QBS can find them. On Linux, you can install a package to the system. On macOS, you can use brew or compile and install protobuf manually: - to /usr/local/ - to any folder, say /Users//protobuf. Then you'll need to set protobuf.libraryPath: "/Users//protobuf/lib" and protobuf.includePath: "/Users//protobuf/include" On Windows, you have to compile and install protobuf manually to any folder and use libraryPath and includePath as shown above qbs-src-3.3.1/examples/protobuf/shared/0000755000175100017510000000000015232633614017427 5ustar runnerrunnerqbs-src-3.3.1/examples/protobuf/shared/addressbook.proto0000644000175100017510000000232215232633614023013 0ustar runnerrunner// See README.txt for information and build instructions. // // Note: START and END tags are used in comments to define sections used in // tutorials. They are not part of the syntax for Protocol Buffers. // // To get an in-depth walkthrough of this file and the related examples, see: // https://developers.google.com/protocol-buffers/docs/tutorials // [START declaration] syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto"; // [END declaration] // [START java_declaration] option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; // [END java_declaration] // [START csharp_declaration] option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; // [END csharp_declaration] // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] qbs-src-3.3.1/examples/protobuf/addressbook_conan/0000755000175100017510000000000015232633614021637 5ustar runnerrunnerqbs-src-3.3.1/examples/protobuf/addressbook_conan/conanfile.txt0000644000175100017510000000012215232633614024331 0ustar runnerrunner[requires] protobuf/3.21.12 [tool_requires] protobuf/3.21.12 [generators] QbsDeps qbs-src-3.3.1/examples/protobuf/addressbook_conan/addressbook_conan.qbs0000644000175100017510000000060515232633614026025 0ustar runnerrunner//![0] import qbs.Host CppApplication { consoleApplication: true condition: protobuf.cpp.present && qbs.targetPlatform === Host.platform() Depends { name: "cpp" } cpp.minimumMacosVersion: "11.0" Depends { name: "protobuf.cpp"; required: false } files: [ "../shared/addressbook.proto", "main.cpp", ] qbsModuleProviders: "conan" } //![0] qbs-src-3.3.1/examples/protobuf/addressbook_conan/main.cpp0000644000175100017510000001441415232633614023273 0ustar runnerrunner// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #include #pragma GCC diagnostic pop #else #include #endif // __GNUC__ #include "addressbook.pb.h" using google::protobuf::util::TimeUtil; int printUsage(char *argv0) { std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl; return -1; } std::string readString(const std::string &promt) { std::string result; std::cout << promt; std::getline(std::cin, result); return result; } // This function fills in a Person message based on user input. void promptForAddress(tutorial::Person *person) { std::cout << "Enter person ID number: "; int id; std::cin >> id; person->set_id(id); std::cin.ignore(256, '\n'); *person->mutable_name() = readString("Enter name: "); const auto email = readString("Enter email address (blank for none): "); if (!email.empty()) person->set_email(email); while (true) { const auto number = readString("Enter a phone number (or leave blank to finish): "); if (number.empty()) break; tutorial::Person::PhoneNumber *phone_number = person->add_phones(); phone_number->set_number(number); const auto type = readString("Is this a mobile, home, or work phone? "); if (type == "mobile") phone_number->set_type(tutorial::Person::MOBILE); else if (type == "home") phone_number->set_type(tutorial::Person::HOME); else if (type == "work") phone_number->set_type(tutorial::Person::WORK); else std::cout << "Unknown phone type. Using default." << std::endl; } *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL)); } // Iterates though all people in the AddressBook and prints info about them. void listPeople(const tutorial::AddressBook &address_book) { for (int i = 0; i < address_book.people_size(); i++) { const tutorial::Person &person = address_book.people(i); std::cout << "Person ID: " << person.id() << std::endl; std::cout << " Name: " << person.name() << std::endl; if (!person.email().empty()) { std::cout << " E-mail address: " << person.email() << std::endl; } for (int j = 0; j < person.phones_size(); j++) { const tutorial::Person::PhoneNumber &phone_number = person.phones(j); switch (phone_number.type()) { case tutorial::Person::MOBILE: std::cout << " Mobile phone #: "; break; case tutorial::Person::HOME: std::cout << " Home phone #: "; break; case tutorial::Person::WORK: std::cout << " Work phone #: "; break; default: std::cout << " Unknown phone #: "; break; } std::cout << phone_number.number() << std::endl; } if (person.has_last_updated()) { std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl; } } } int main(int argc, char *argv[]) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != 3) return printUsage(argv[0]); tutorial::AddressBook address_book; // Read the existing address book. std::fstream input(argv[2], std::ios::in | std::ios::binary); if (!input) { std::cout << argv[2] << ": File not found." << std::endl; } else if (!address_book.ParseFromIstream(&input)) { std::cerr << "Failed to parse address book." << std::endl; return -1; } const std::string mode(argv[1]); if (mode == "add") { // Add an address. promptForAddress(address_book.add_people()); if (!input) std::cout << "Creating a new file." << std::endl; // Write the new address book back to disk. std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary); if (!address_book.SerializeToOstream(&output)) { std::cerr << "Failed to write address book." << std::endl; return -1; } } else if (mode == "list") { listPeople(address_book); } else { return printUsage(argv[0]); } // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; } qbs-src-3.3.1/examples/examples.qbs0000644000175100017510000000465215232633614016655 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Product { files: "**/*" } qbs-src-3.3.1/examples/helloworld-qt/0000755000175100017510000000000015232633614017116 5ustar runnerrunnerqbs-src-3.3.1/examples/helloworld-qt/main.cpp0000644000175100017510000000512115232633614020545 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include int main() { QTextStream ts(stdout); ts << QCoreApplication::translate("hello", "Hello, World!\n"); ts.flush(); } qbs-src-3.3.1/examples/helloworld-qt/helloworld-qt.qbs0000644000175100017510000000471615232633614022432 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ QtApplication { name: "HelloWorld-Qt" files: "main.cpp" } qbs-src-3.3.1/examples/flatbuffers/0000755000175100017510000000000015232633614016624 5ustar runnerrunnerqbs-src-3.3.1/examples/flatbuffers/monster-cpp/0000755000175100017510000000000015232633614021073 5ustar runnerrunnerqbs-src-3.3.1/examples/flatbuffers/monster-cpp/conanfile.txt0000644000175100017510000000013015232633614023564 0ustar runnerrunner[requires] flatbuffers/24.3.25 [tool_requires] flatbuffers/24.3.25 [generators] QbsDeps qbs-src-3.3.1/examples/flatbuffers/monster-cpp/monster-cpp.qbs0000644000175100017510000000046715232633614024060 0ustar runnerrunnerCppApplication { Depends { name: "flatbuf.cpp"; required: false } name: "monster_cpp" consoleApplication: true condition: flatbuf.cpp.present && qbs.targetPlatform === qbs.hostPlatform files: [ "monster.cpp", "../shared/monster.fbs" ] qbsModuleProviders: "conan" } qbs-src-3.3.1/examples/flatbuffers/monster-cpp/monster.cpp0000644000175100017510000000763215232633614023276 0ustar runnerrunner/* * Copyright 2015 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h". using namespace MyGame::Sample; // Example how to use FlatBuffers to create and read binary buffers. int main(int /*argc*/, const char * /*argv*/ []) { // Build up a serialized buffer algorithmically: flatbuffers::FlatBufferBuilder builder; // First, lets serialize some weapons for the Monster: A 'sword' and an 'axe'. auto weapon_one_name = builder.CreateString("Sword"); short weapon_one_damage = 3; auto weapon_two_name = builder.CreateString("Axe"); short weapon_two_damage = 5; // Use the `CreateWeapon` shortcut to create Weapons with all fields set. auto sword = CreateWeapon(builder, weapon_one_name, weapon_one_damage); auto axe = CreateWeapon(builder, weapon_two_name, weapon_two_damage); // Create a FlatBuffer's `vector` from the `std::vector`. std::vector> weapons_vector; weapons_vector.push_back(sword); weapons_vector.push_back(axe); auto weapons = builder.CreateVector(weapons_vector); // Second, serialize the rest of the objects needed by the Monster. auto position = Vec3(1.0f, 2.0f, 3.0f); auto name = builder.CreateString("MyMonster"); unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto inventory = builder.CreateVector(inv_data, 10); // Shortcut for creating monster with all fields set: auto orc = CreateMonster(builder, &position, 150, 80, name, inventory, Color_Red, weapons, Equipment_Weapon, axe.Union()); builder.Finish(orc); // Serialize the root of the object. // We now have a FlatBuffer we can store on disk or send over a network. // ** file/network code goes here :) ** // access builder.GetBufferPointer() for builder.GetSize() bytes // Instead, we're going to access it right away (as if we just received it). // Get access to the root: auto monster = GetMonster(builder.GetBufferPointer()); // Get and test some scalar types from the FlatBuffer. assert(monster->hp() == 80); assert(monster->mana() == 150); // default assert(monster->name()->str() == "MyMonster"); // Get and test a field of the FlatBuffer's `struct`. auto pos = monster->pos(); assert(pos); assert(pos->z() == 3.0f); (void)pos; // Get a test an element from the `inventory` FlatBuffer's `vector`. auto inv = monster->inventory(); assert(inv); assert(inv->Get(9) == 9); (void)inv; // Get and test the `weapons` FlatBuffers's `vector`. std::string expected_weapon_names[] = { "Sword", "Axe" }; short expected_weapon_damages[] = { 3, 5 }; auto weps = monster->weapons(); for (unsigned int i = 0; i < weps->size(); i++) { assert(weps->Get(i)->name()->str() == expected_weapon_names[i]); assert(weps->Get(i)->damage() == expected_weapon_damages[i]); } (void)expected_weapon_names; (void)expected_weapon_damages; // Get and test the `Equipment` union (`equipped` field). assert(monster->equipped_type() == Equipment_Weapon); auto equipped = static_cast(monster->equipped()); assert(equipped->name()->str() == "Axe"); assert(equipped->damage() == 5); (void)equipped; printf("The FlatBuffer was successfully created and verified!\n"); } qbs-src-3.3.1/examples/flatbuffers/monster-c/0000755000175100017510000000000015232633614020533 5ustar runnerrunnerqbs-src-3.3.1/examples/flatbuffers/monster-c/conanfile.txt0000644000175100017510000000011215232633614023224 0ustar runnerrunner[requires] flatcc/0.6.1 [tool_requires] flatcc/0.6.1 [generators] QbsDeps qbs-src-3.3.1/examples/flatbuffers/monster-c/monster-c.qbs0000644000175100017510000000045715232633614023157 0ustar runnerrunnerCppApplication { Depends { name: "flatbuf.c"; required: false } name: "monster_c" consoleApplication: true condition: flatbuf.c.present && qbs.targetPlatform === qbs.hostPlatform files: [ "monster.c", "../shared/monster.fbs" ] qbsModuleProviders: "conan" } qbs-src-3.3.1/examples/flatbuffers/monster-c/monster.c0000644000175100017510000003614415232633614022376 0ustar runnerrunner/* * Copyright 2019 dvidelabs. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Example on how to build a Monster FlatBuffer. // Note: while some older C89 compilers are supported when // -DFLATCC_PORTABLE is defined, this particular sample is known not to // not work with MSVC 2010 (MSVC 2013 is OK) due to inline variable // declarations. These are easily move to the start of code blocks, but // since we follow the step-wise tutorial, it isn't really practical // in this case. The comment style is technically also in violation of C89. #include "monster_builder.h" // and already included. // Convenient namespace macro to manage long namespace prefix. // The ns macro makes it possible to write `ns(Monster_create(...))` // instead of `MyGame_Sample_Monster_create(...)` #undef ns #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema. // A helper to simplify creating vectors from C-arrays. #define c_vec_len(V) (sizeof(V)/sizeof((V)[0])) // This allows us to verify result in optimized builds. #define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0) // Bottom-up approach where we create child objects and store these // in temporary references before a parent object is created with // these references. int create_monster_bottom_up(flatcc_builder_t *B, int flexible) { flatbuffers_string_ref_t weapon_one_name = flatbuffers_string_create_str(B, "Sword"); uint16_t weapon_one_damage = 3; flatbuffers_string_ref_t weapon_two_name = flatbuffers_string_create_str(B, "Axe"); uint16_t weapon_two_damage = 5; // Use the `MyGame_Sample_Weapon_create` shortcut to create Weapons // with all the fields set. // // In the C-API, verbs (here create) always follow the type name // (here Weapon), prefixed by the namespace (here MyGame_Sample_): // MyGame_Sample_Weapon_create(...), or ns(Weapone_create(...)). ns(Weapon_ref_t) sword = ns(Weapon_create(B, weapon_one_name, weapon_one_damage)); ns(Weapon_ref_t) axe = ns(Weapon_create(B, weapon_two_name, weapon_two_damage)); // Serialize a name for our monster, called "Orc". // The _str suffix indicates the source is an ascii-z string. flatbuffers_string_ref_t name = flatbuffers_string_create_str(B, "Orc"); // Create a `vector` representing the inventory of the Orc. Each number // could correspond to an item that can be claimed after he is slain. uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; flatbuffers_uint8_vec_ref_t inventory; // `c_vec_len` is the convenience macro we defined earlier. inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure)); // Here we use a top-down approach locally to build a Weapons vector // in-place instead of creating a temporary external vector to use // as argument like we did with the `inventory` earlier on, but the // overall approach is still bottom-up. ns(Weapon_vec_start(B)); ns(Weapon_vec_push(B, sword)); ns(Weapon_vec_push(B, axe)); ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B)); // Create a `Vec3`, representing the Orc's position in 3-D space. ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f }; // Set his hit points to 300 and his mana to 150. uint16_t hp = 300; // The default value is 150, so we will never store this field. uint16_t mana = 150; // Create the equipment union. In the C++ language API this is given // as two arguments to the create call, or as two separate add // operations for the type and the table reference. Here we create // a single union value that carries both the type and reference. ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe)); if (!flexible) { // Finally, create the monster using the `Monster_create` helper function // to set all fields. // // Note that the Equipment union only take up one argument in C, where // C++ takes a type and an object argument. ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red), weapons, equipped)); // Unlike C++ we do not use a Finish call. Instead we use the // `create_as_root` action which has better type safety and // simplicity. // // However, we can also express this as: // // ns(Monster_ref_t) orc = ns(Monster_create(B, ...)); // flatcc_builder_buffer_create(orc); // // In this approach the function should return the orc and // let a calling function handle the flatcc_buffer_create call // for a more composable setup that is also able to create child // monsters. In general, `flatcc_builder` calls are best isolated // in a containing driver function. } else { // A more flexible approach where we mix bottom-up and top-down // style. We still create child objects first, but then create // a top-down style monster object that we can manipulate in more // detail. // It is important to pair `start_as_root` with `end_as_root`. ns(Monster_start_as_root(B)); ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f)); // or alternatively //ns(Monster_pos_add(&pos); ns(Monster_hp_add(B, hp)); // Notice that `Monser_name_add` adds a string reference unlike the // add_str and add_strn variants. ns(Monster_name_add(B, name)); ns(Monster_inventory_add(B, inventory)); ns(Monster_color_add(B, ns(Color_Red))); ns(Monster_weapons_add(B, weapons)); ns(Monster_equipped_add(B, equipped)); // Complete the monster object and make it the buffer root object. ns(Monster_end_as_root(B)); // We could also drop the `as_root` suffix from Monster_start/end(B) // and add the table as buffer root later: // // ns(Monster_ref_t) orc = ns(Monster_start(B)); // ... // ns(Monster_ref_t) orc = ns(Monster_end(B)); // flatcc_builder_buffer_create(orc); // // It is best to keep the `flatcc_builder` calls in a containing // driver function for modularity. } return 0; } // Alternative top-down approach where parent objects are created before // their children. We only need to save one reference because the `axe` // object is used in two places effectively making the buffer object // graph a DAG. int create_monster_top_down(flatcc_builder_t *B) { uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; size_t treasure_count = c_vec_len(treasure); ns(Weapon_ref_t) axe; // NOTE: if we use end_as_root, we MUST also start as root. ns(Monster_start_as_root(B)); ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f)); ns(Monster_hp_add(B, 300)); //ns(Monster_mana_add(B, 150)); // We use create_str instead of add because we have no existing string reference. ns(Monster_name_create_str(B, "Orc")); // Again we use create because we no existing vector object, only a C-array. ns(Monster_inventory_create(B, treasure, treasure_count)); ns(Monster_color_add(B, ns(Color_Red))); if (1) { ns(Monster_weapons_start(B)); ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3)); // We reuse the axe object later. Note that we dereference a pointer // because push always returns a short-term pointer to the stored element. // We could also have created the axe object first and simply pushed it. axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5)); ns(Monster_weapons_end(B)); } else { // We can have more control with the table elements added to a vector: // ns(Monster_weapons_start(B)); ns(Monster_weapons_push_start(B)); ns(Weapon_name_create_str(B, "Sword")); ns(Weapon_damage_add(B, 3)); ns(Monster_weapons_push_end(B)); ns(Monster_weapons_push_start(B)); ns(Weapon_name_create_str(B, "Axe")); ns(Weapon_damage_add(B, 5)); axe = *ns(Monster_weapons_push_end(B)); ns(Monster_weapons_end(B)); } // Unions can get their type by using a type-specific add/create/start method. ns(Monster_equipped_Weapon_add(B, axe)); ns(Monster_end_as_root(B)); return 0; } // This isn't strictly needed because the builder already included the reader, // but we would need it if our reader were in a separate file. #include "monster_reader.h" #undef ns #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema. int access_monster_buffer(const void *buffer) { // Note that we use the `table_t` suffix when reading a table object // as opposed to the `ref_t` suffix used during the construction of // the buffer. ns(Monster_table_t) monster = ns(Monster_as_root(buffer)); // Note: root object pointers are NOT the same as the `buffer` pointer. // Make sure the buffer is accessible. test_assert(monster != 0); uint16_t hp = ns(Monster_hp(monster)); uint16_t mana = ns(Monster_mana(monster)); // This is just a const char *, but it also supports a fast length operation. flatbuffers_string_t name = ns(Monster_name(monster)); size_t name_len = flatbuffers_string_len(name); test_assert(hp == 300); // Since 150 is the default, we are reading a value that wasn't stored. test_assert(mana == 150); test_assert(0 == strcmp(name, "Orc")); test_assert(name_len == strlen("Orc")); int hp_present = ns(Monster_hp_is_present(monster)); // 1 int mana_present = ns(Monster_mana_is_present(monster)); // 0 test_assert(hp_present); test_assert(!mana_present); ns(Vec3_struct_t) pos = ns(Monster_pos(monster)); // Make sure pos has been set. test_assert(pos != 0); float x = ns(Vec3_x(pos)); float y = ns(Vec3_y(pos)); float z = ns(Vec3_z(pos)); // The literal `f` suffix is important because double literals does // not always map cleanly to 32-bit represention even with only a few digits: // `1.0 == 1.0f`, but `3.2 != 3.2f`. test_assert(x == 1.0f); test_assert(y == 2.0f); test_assert(z == 3.0f); // We can also read the position into a C-struct. We have to copy // because we generally do not know if the native endian format // matches the one stored in the buffer (pe: protocol endian). ns(Vec3_t) pos_vec; // `pe` indicates endian conversion from protocol to native. ns(Vec3_copy_from_pe(&pos_vec, pos)); test_assert(pos_vec.x == 1.0f); test_assert(pos_vec.y == 2.0f); test_assert(pos_vec.z == 3.0f); // This is a const uint8_t *, but it shouldn't be accessed directly // to ensure proper endian conversion. However, uint8 (ubyte) are // not sensitive endianness, so we *could* have accessed it directly. // The compiler likely optimizes this so that it doesn't matter. flatbuffers_uint8_vec_t inv = ns(Monster_inventory(monster)); size_t inv_len = flatbuffers_uint8_vec_len(inv); // Make sure the inventory has been set. test_assert(inv != 0); // If `inv` were absent, the length would 0, so the above test is redundant. test_assert(inv_len == 10); // Index 0 is the first, index 2 is the third. // NOTE: C++ uses the `Get` terminology for vector elemetns, C use `at`. uint8_t third_item = flatbuffers_uint8_vec_at(inv, 2); test_assert(third_item == 2); ns(Weapon_vec_t) weapons = ns(Monster_weapons(monster)); size_t weapons_len = ns(Weapon_vec_len(weapons)); test_assert(weapons_len == 2); // We can use `const char *` instead of `flatbuffers_string_t`. const char *second_weapon_name = ns(Weapon_name(ns(Weapon_vec_at(weapons, 1)))); uint16_t second_weapon_damage = ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1)))); test_assert(second_weapon_name != 0 && strcmp(second_weapon_name, "Axe") == 0); test_assert(second_weapon_damage == 5); // Access union type field. if (ns(Monster_equipped_type(monster)) == ns(Equipment_Weapon)) { // Cast to appropriate type: // C does not require the cast to Weapon_table_t, but C++ does. ns(Weapon_table_t) weapon = (ns(Weapon_table_t)) ns(Monster_equipped(monster)); const char *weapon_name = ns(Weapon_name(weapon)); uint16_t weapon_damage = ns(Weapon_damage(weapon)); test_assert(0 == strcmp(weapon_name, "Axe")); test_assert(weapon_damage == 5); } return 0; } #include int main(int argc, char *argv[]) { // Create a `FlatBufferBuilder`, which will be used to create our // monsters' FlatBuffers. flatcc_builder_t builder; void *buf; size_t size; // Silence warnings. (void)argc; (void)argv; // Initialize the builder object. flatcc_builder_init(&builder); test_assert(0 == create_monster_bottom_up(&builder, 0)); // Allocate and extract a readable buffer from internal builder heap. // The returned buffer must be deallocated using `free`. // NOTE: Finalizing the buffer does NOT change the builder, it // just creates a snapshot of the builder content. // NOTE2: finalize_buffer uses malloc while finalize_aligned_buffer // uses a portable aligned allocation method. Often the malloc // version is sufficient, but won't work for all schema on all // systems. If the buffer is written to disk or network, but not // accessed in memory, `finalize_buffer` is also sufficient. buf = flatcc_builder_finalize_aligned_buffer(&builder, &size); //buf = flatcc_builder_finalize_buffer(&builder, &size); // We now have a FlatBuffer we can store on disk or send over a network. // ** file/network code goes here :) ** // Instead, we're going to access it right away (as if we just received it). //access_monster_buffer(buf); // prior to v0.5.0, use `aligned_free` flatcc_builder_aligned_free(buf); //free(buf); // // The builder object can optionally be reused after a reset which // is faster than creating a new builder. Subsequent use might // entirely avoid temporary allocations until finalizing the buffer. flatcc_builder_reset(&builder); test_assert(0 == create_monster_bottom_up(&builder, 1)); buf = flatcc_builder_finalize_aligned_buffer(&builder, &size); access_monster_buffer(buf); flatcc_builder_aligned_free(buf); flatcc_builder_reset(&builder); create_monster_top_down(&builder); buf = flatcc_builder_finalize_buffer(&builder, &size); test_assert(0 == access_monster_buffer(buf)); free(buf); // Eventually the builder must be cleaned up: flatcc_builder_clear(&builder); printf("The FlatBuffer was successfully created and accessed!\n"); return 0; } qbs-src-3.3.1/examples/flatbuffers/shared/0000755000175100017510000000000015232633614020072 5ustar runnerrunnerqbs-src-3.3.1/examples/flatbuffers/shared/monster.fbs0000644000175100017510000000076715232633614022267 0ustar runnerrunner// Example IDL file for our monster's schema. namespace MyGame.Sample; enum Color:byte { Red = 0, Green, Blue = 2 } union Equipment { Weapon } // Optionally add more tables. struct Vec3 { x:float; y:float; z:float; } table Monster { pos:Vec3; mana:short = 150; hp:short = 100; name:string; friendly:bool = false (deprecated); inventory:[ubyte]; color:Color = Blue; weapons:[Weapon]; equipped:Equipment; } table Weapon { name:string; damage:short; } root_type Monster; qbs-src-3.3.1/examples/flatbuffers/.clang-format0000644000175100017510000000005015232633614021172 0ustar runnerrunnerDisableFormat: true SortIncludes: Never qbs-src-3.3.1/examples/conan-zlib/0000755000175100017510000000000015232633614016355 5ustar runnerrunnerqbs-src-3.3.1/examples/conan-zlib/conan-zlib.qbs0000644000175100017510000000050315232633614021116 0ustar runnerrunner//![0] import qbs.Host CppApplication { consoleApplication: true condition: zlib.present && qbs.targetPlatform === Host.platform() Depends { name: "cpp" } Depends { name: "zlib"; required: false } install: true qbs.installPrefix: "" files: "main.c" qbsModuleProviders: "conan" } //![0] qbs-src-3.3.1/examples/conan-zlib/main.c0000644000175100017510000000764315232633614017457 0ustar runnerrunner/**************************************************************************** ** ** MIT License ** Copyright (c) 2017 Aleksander Alekseev ** 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. ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { int res; if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } char* fname = argv[1]; struct stat file_stat; res = stat(fname, &file_stat); if (res == -1) { fprintf(stderr, "stat(...) failed, errno = %d\n", errno); return 1; } size_t temp_file_size = (size_t)file_stat.st_size; if (temp_file_size >= INT_MAX) { fprintf(stderr, "Error: filze_size >= INT_MAX (%d)\n", INT_MAX); return 1; } int file_size = (int)temp_file_size; int buff_size = file_size + 1; void* file_buff = malloc(buff_size); if (file_buff == NULL) { fprintf(stderr, "malloc(buff_size) failed, buff_size = %d\n", file_size); return 1; } FILE* fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "open(...) failed, errno = %d\n", errno); free(file_buff); return 1; } if (fread(file_buff, 1, file_size, fp) != file_size) { fprintf(stderr, "read(...) failed, errno = %d\n", errno); free(file_buff); fclose(fp); return 1; } fclose(fp); uLongf compress_buff_size = compressBound(file_size); void* compress_buff = malloc(compress_buff_size); if (compress_buff == NULL) { fprintf(stderr, "malloc(compress_buff_size) failed, " "compress_buff_size = %lu\n", compress_buff_size); free(file_buff); return 1; } uLongf compressed_size = compress_buff_size; res = compress(compress_buff, &compressed_size, file_buff, file_size); if (res != Z_OK) { fprintf(stderr, "compress(...) failed, res = %d\n", res); free(compress_buff); free(file_buff); return 1; } memset(file_buff, 0, buff_size); uLongf decompressed_size = (uLongf)file_size; res = uncompress(file_buff, &decompressed_size, compress_buff, compressed_size); if (res != Z_OK) { fprintf(stderr, "uncompress(...) failed, res = %d\n", res); free(compress_buff); free(file_buff); return 1; } printf( "%s\n----------------\n" "File size: %d, compress_buff_size: %lu, compressed_size: %lu, " "decompressed_size: %lu\n", (char*)file_buff, file_size, compress_buff_size, compressed_size, decompressed_size); free(compress_buff); free(file_buff); } qbs-src-3.3.1/examples/conan-zlib/conanfile.py0000644000175100017510000000107515232633614020670 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.qbs import Qbs, QbsProfile, QbsDeps class Recipe(ConanFile): name = "conan-zlib" version = "1.0" exports_sources = "*.c", "*.qbs", settings = "os", "compiler", "arch", "build_type" requires = ["zlib/1.3.1"] def generate(self): profile = QbsProfile(self) profile.generate() deps = QbsDeps(self) deps.generate() def build(self): qbs = Qbs(self) qbs.resolve() qbs.build() def package(self): qbs = Qbs(self) qbs.install() qbs-src-3.3.1/examples/baremetal/0000755000175100017510000000000015232633614016255 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/cc2540usbdongle/0000755000175100017510000000000015232633614021060 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/0000755000175100017510000000000015232633614023200 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/main.c0000644000175100017510000000533615232633614024277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" static void some_delay(unsigned long counts) { unsigned long index = 0u; for (index = 0u; index < counts; ++index) system_nop(); } int main(void) { gpio_init_green_led(); while (1) { gpio_toggle_green_led(); some_delay(20000u); } } qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/system.h0000644000175100017510000000630315232633614024677 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #ifdef __cplusplus extern "C" { #endif #if defined(__ICC8051__) #include # define system_nop() __no_operation() # define DEFINE_SFR(name,addr) __sfr __no_init volatile unsigned char name @ addr; #elif defined (__C51__) #include # define system_nop() _nop_() # define DEFINE_SFR(name, addr) sfr name = addr; #elif defined (__SDCC_mcs51) #include # define DEFINE_SFR(name, addr) __sfr __at(addr) name; # ifndef NOP # define NOP() __asm NOP __endasm # endif # define system_nop() NOP() #else #error "Unsupported toolchain" #endif DEFINE_SFR(P0 , 0x80u) // Port 0. DEFINE_SFR(P0SEL, 0xF3u) // Port 0 function select. DEFINE_SFR(P0DIR, 0xFDu) // Port 0 direction select. #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs0000644000175100017510000001026115232633614026027 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("mcs51")) return false; return qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil") || qbs.toolchain.contains("sdcc") } name: "cc2540usbdongle-greenblink" cpp.positionIndependentCode: false // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.commonCompilerFlags: ["-e"] cpp.driverLinkerFlags: [ "-D_IDATA_STACK_SIZE=0x40", "-D_PDATA_STACK_SIZE=0x00", "-D_XDATA_STACK_SIZE=0x00", "-D_XDATA_HEAP_SIZE=0x00", "-D_EXTENDED_STACK_SIZE=0", "-D_EXTENDED_STACK_START=0" ] cpp.staticLibraries: [ cpp.toolchainInstallPath + "/../lib/clib/cl-pli-nsid-1e16x01" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Linker Script" prefix: cpp.toolchainInstallPath + "/../config/devices/_generic/" fileTags: ["linkerscript"] files: ["lnk51ew_8051.xcl"] } } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.driverLinkerFlags: [ "RAMSIZE(256)", "CODE(0x0000-0xFFFF)" ] } // // SDCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("sdcc") } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/gpio.c0000644000175100017510000000525415232633614024310 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #define GPIO_GREEN_LED_PIN_POS (1u) void gpio_init_green_led(void) { P0SEL = 0; // Choose the port. P0DIR = 0x01; // Set pin0 to output mode. } void gpio_toggle_green_led(void) { P0 ^= GPIO_GREEN_LED_PIN_POS; } qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/README.md0000644000175100017510000000051715232633614024462 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different MCS-51 toolchains. It is designed for the CC2540 usb dongle target board (based on Texas Instruments CC2540 wireless MCU) and simply flashes the green LED on the board. The following toolchains are supported: * IAR Embedded Workbench * KEIL uVision qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/greenblink/gpio.h0000644000175100017510000000513215232633614024310 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_green_led(void); void gpio_toggle_green_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/cc2540usbdongle/cc2540usbdongle.qbs0000644000175100017510000000503115232633614024371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for cc2540usbdongle board" references: [ "greenblink/greenblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/stm8s103f3/0000755000175100017510000000000015232633614020010 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/0000755000175100017510000000000015232633614021602 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/redblink.qbs0000644000175100017510000000717315232633614024113 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("stm8")) return false; return qbs.toolchain.contains("iar") || qbs.toolchain.contains("sdcc") } name: "stm8s103f3-redblink" cpp.positionIndependentCode: false // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.commonCompilerFlags: ["-e"] cpp.driverLinkerFlags: [ "--config_def", "_CSTACK_SIZE=0x100", "--config_def", "_HEAP_SIZE=0x100", ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Linker Script" prefix: cpp.toolchainInstallPath + "/../config/" fileTags: ["linkerscript"] files: ["lnkstm8s103f3.icf"] } } // // SDCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("sdcc") } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/main.c0000644000175100017510000000533215232633614022675 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" static void some_delay(unsigned long counts) { unsigned long index = 0u; for (index = 0u; index < counts; ++index) system_nop(); } int main(void) { gpio_init_red_led(); while (1) { gpio_toggle_red_led(); some_delay(20000u); } } qbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/system.h0000644000175100017510000000651215232633614023303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #ifdef __cplusplus extern "C" { #endif // Define required registers of Port B (where the LED is connected): // * PB_ODR - Output Data Register. // * PB_DDR - Data Direction Register. // * PB_CR1 - Control Register #1. // * PB_CR2 - Control Register #2. #if defined(__ICCSTM8__) # define system_nop() __asm("nop") __near __no_init volatile unsigned char PB_ODR @ 0x5005; __near __no_init volatile unsigned char PB_DDR @ 0x5007; __near __no_init volatile unsigned char PB_CR1 @ 0x5008; __near __no_init volatile unsigned char PB_CR2 @ 0x5009; #elif defined (__SDCC_stm8) # define system_nop() __asm nop __endasm #define PB_ODR *(volatile unsigned char *)0x5005 #define PB_DDR *(volatile unsigned char *)0x5007 #define PB_CR1 *(volatile unsigned char *)0x5008 #define PB_CR2 *(volatile unsigned char *)0x5009 #else #error "Unsupported toolchain" #endif #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/gpio.c0000644000175100017510000000555115232633614022712 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" // A LED is connected to the pin #5 of Port B. #define GPIO_RED_LED_PIN_POS (0x20u) void gpio_init_red_led(void) { PB_ODR = 0x00; // Turn off all pins. PB_DDR = GPIO_RED_LED_PIN_POS; // Configure Pin as output. PB_CR1 = GPIO_RED_LED_PIN_POS; // Set Pin to Push-Pull. PB_CR2 = GPIO_RED_LED_PIN_POS; // Set Pin to Push-Pull. } void gpio_toggle_red_led(void) { PB_ODR ^= GPIO_RED_LED_PIN_POS; } qbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/README.md0000644000175100017510000000045115232633614023061 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different STM8 toolchains. It is designed for the STM8 target board (based on STMicroelectronics stm8s103f3 MCU) and simply flashes the red LED on the board. The following toolchains are supported: * IAR Embedded Workbench qbs-src-3.3.1/examples/baremetal/stm8s103f3/redblink/gpio.h0000644000175100017510000000512615232633614022715 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_red_led(void); void gpio_toggle_red_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/stm8s103f3/stm8s103f3.qbs0000644000175100017510000000502015232633614022247 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for stm8s103f3 board" references: [ "redblink/redblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/cy7c68013a/0000755000175100017510000000000015232633614017665 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/cy7c68013a/cy7c68013a.qbs0000644000175100017510000000503015232633614022002 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for cy7c68013a board" references: [ "nes-gamepads/nes-gamepads.qbs" ] } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/0000755000175100017510000000000015232633614022231 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/hidep0.c0000644000175100017510000002142515232633614023552 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" #include "core.h" #include "usb.h" static BOOL g_rwuen = FALSE; static BOOL g_selfpwr = FALSE; static void ep0_ep1in_reset(void) { EP1INCS &= ~bmEPBUSY; sync_delay(); usp_ep_reset_toggle(HID_EP_IN); sync_delay(); } // Get status handle. static BYTE *ep_address_get(BYTE ep) { const BYTE ep_num = ep & ~bmSETUP_DIR; switch (ep_num) { case 0: return (BYTE *)&EP0CS; case 1: return (ep & bmSETUP_DIR) ? (BYTE *)&EP1INCS : (BYTE *)&EP1OUTCS; default: break; } return NULL; } static BOOL ep0_dev_status_get(void) { BYTE status = 0; if (g_selfpwr) status |= USB_STATUS_SELF_POWERED; if (g_rwuen) status |= USB_STATUS_REMOTE_WAKEUP; EP0BUF[0] = status; EP0BUF[1] = 0; EP0BCH = 0; EP0BCL = 2; return TRUE; } static BOOL ep0_iface_status_get(void) { EP0BUF[0] = 0; EP0BUF[1] = 0; EP0BCH = 0; EP0BCL = 2; return TRUE; } static BOOL ep0_ep_status_get(void) { const volatile BYTE XDATA *pep = (BYTE XDATA *)ep_address_get(SETUPDAT[4]); if (pep) { EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0; EP0BUF[1] = 0; EP0BCH = 0; EP0BCL = 2; return TRUE; } return FALSE; } static BOOL ep0_get_status_proc(void) { if ((SETUPDAT[0] & bmSETUP_TO_HOST) == 0) return FALSE; switch (SETUPDAT[0] & bmSETUP_RECIPIENT) { case bmSETUP_DEVICE: return ep0_dev_status_get(); case bmSETUP_IFACE: return ep0_iface_status_get(); case bmSETUP_EP: return ep0_ep_status_get(); default: break; } return FALSE; } // Clear feature handle. static BOOL ep0_dev_feature_clear(void) { if (SETUPDAT[2] == USB_FEATURE_REMOTE_WAKEUP) { g_rwuen = FALSE; return TRUE; } return FALSE; } static BOOL ep0_ep_feature_clear(void) { if (SETUPDAT[2] == USB_FEATURE_STALL) { volatile BYTE XDATA *pep = (BYTE XDATA *)ep_address_get(SETUPDAT[4]); if (!pep) return FALSE; *pep &= ~bmEPSTALL; return TRUE; } return FALSE; } static BOOL ep0_clear_feature_proc(void) { switch (SETUPDAT[0] & bmSETUP_RECIPIENT) { case bmSETUP_DEVICE: return ep0_dev_feature_clear(); case bmSETUP_EP: return ep0_ep_feature_clear(); default: break; } return FALSE; } // Set feature handle. static BOOL ep0_dev_feature_set(void) { switch (SETUPDAT[2]) { case USB_FEATURE_REMOTE_WAKEUP: g_rwuen = TRUE; return TRUE; case USB_FEATRUE_TEST_MODE: // This is "test mode", just return the handshake. return TRUE; default: break; } return FALSE; } static BOOL ep0_ep_feature_set(void) { if (SETUPDAT[2] == USB_FEATURE_STALL) { volatile BYTE XDATA *pep = (BYTE XDATA *)ep_address_get(SETUPDAT[4]); if (!pep) return FALSE; *pep |= bmEPSTALL; usp_ep_reset_toggle(SETUPDAT[4]); return TRUE; } return FALSE; } static BOOL ep0_set_feature_proc(void) { switch (SETUPDAT[0] & bmSETUP_RECIPIENT) { case bmSETUP_DEVICE: return ep0_dev_feature_set(); case bmSETUP_EP: return ep0_ep_feature_set(); default: break; } return FALSE; } // Get descriptor handle. static BOOL ep0_std_descriptor_proc(void) { const BYTE XDATA *pdesc = (BYTE XDATA *)hid_ep0_std_desc_get(); if (pdesc) { SUDPTRH = usb_word_msb_get(pdesc); SUDPTRL = usb_word_lsb_get(pdesc); return TRUE; } return FALSE; } static BOOL ep0_report_descriptor_proc(void) { WORD i = 0; WORD length = 0; const BYTE XDATA *pdesc = (BYTE XDATA *)hid_ep0_report_desc_get(&length); if (pdesc) { AUTOPTRH1 = usb_word_msb_get(pdesc); AUTOPTRL1 = usb_word_lsb_get(pdesc); for (i = 0; i < length; ++i) EP0BUF[i] = XAUTODAT1; EP0BCH = usb_word_msb_get(length); EP0BCL = usb_word_lsb_get(length); return TRUE; } return FALSE; } static BOOL ep0_get_descriptor_proc(void) { switch (SETUPDAT[3]) { case USB_DESC_DEVICE: case USB_DESC_CONF: case USB_DESC_STRING: case USB_DESC_DEVICE_QUAL: case USB_DESC_OTHER_SPEED_CONF: case USB_DESC_HID: return ep0_std_descriptor_proc(); case USB_DESC_REPORT: return ep0_report_descriptor_proc(); } return FALSE; } // Get configuration handle. static BOOL ep0_get_config_proc(void) { // We only support configuration 1. EP0BUF[0] = HID_CONFIG_NUMBER; EP0BCH = 0; EP0BCL = 1; return TRUE; } // Set configuration handle. static BOOL ep0_set_config_proc(void) { // We only support configuration 1. if (SETUPDAT[2] != HID_CONFIG_NUMBER) return FALSE; return TRUE; } // Get interface handle. static BOOL ep0_get_iface_proc(void) { if (SETUPDAT[4] != HID_IFACE_NUMBER) return FALSE; EP0BUF[0] = HID_ALT_IFACE_NUMBER; EP0BCH = 0; EP0BCL = 1; return TRUE; } // Set interface handle. static BOOL ep0_set_iface_proc(void) { if (SETUPDAT[4] != HID_IFACE_NUMBER) return FALSE; if (SETUPDAT[2] != HID_ALT_IFACE_NUMBER) return FALSE; ep0_ep1in_reset(); return TRUE; } static BOOL ep0_std_proc(void) { switch (SETUPDAT[1]) { case USB_SETUP_GET_STATUS: return ep0_get_status_proc(); case USB_SETUP_CLEAR_FEATURE: return ep0_clear_feature_proc(); case USB_SETUP_SET_FEATURE: return ep0_set_feature_proc(); case USB_SETUP_SET_ADDRESS: // Handles automatically by FX2. return TRUE; case USB_SETUP_GET_DESCRIPTOR: return ep0_get_descriptor_proc(); case USB_SETUP_GET_CONFIGURATION: return ep0_get_config_proc(); case USB_SETUP_SET_CONFIGURATION: return ep0_set_config_proc(); case USB_SETUP_GET_INTERFACE: return ep0_get_iface_proc(); case USB_SETUP_SET_INTERFACE: return ep0_set_iface_proc(); default: break; } return FALSE; } static BOOL ep0_setup(void) { switch (SETUPDAT[0] & bmSETUP_TYPE) { case bmSETUP_STANDARD: return ep0_std_proc(); default: break; } return FALSE; } void hid_ep0_setup_task(void) { if (!ep0_setup()) usb_ep0_stall(); usb_ep0_hsnack(); } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/main.c0000644000175100017510000000563115232633614023326 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Allocate all registers once here (only for C51 compiler). #define DEFINE_REGS #include "regs.h" #include "core.h" #include "gpio.h" #include "usb.h" static void hw_init(void) { usb_disconnect(); code_all_irq_disable(); core_init(); gpio_init(); usb_init(); usb_connect(); code_all_irq_enable(); } static void hw_loop_exec(void) { while (TRUE) { gpio_task(); usb_task(); } } int main(void) { hw_init(); hw_loop_exec(); return 0; } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/core.c0000644000175100017510000000622715232633614023334 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "core.h" #include "regs.h" enum cpu_freq_clk { CPU_CLK_12M = 0, CPU_CLK_24M, CPU_CLK_48M }; #define cpu_freq_clk_get() \ ((CPUCS & bmCLKSPD) >> 3) #define cpu_freq_clk_set(freq_clk) \ CPUCS = (CPUCS & ~bmCLKSPD) | (freq_clk << 3) void core_init(void) { // Set CPU clock to 48MHz. cpu_freq_clk_set(CPU_CLK_48M); sync_delay(); // Set stretch to 0. CKCON = ((CKCON & (~bmSTRETCH)) | bmFW_STRETCH1); sync_delay(); // Clear breakpoint register. BREAKPT = 0; sync_delay(); // Set all 8051 interrupts to low priority IP = 0; sync_delay(); // Clear interrupt enable bits. EIE = 0; sync_delay(); // Clear all external interrupt flags. EXIF = 0; sync_delay(); } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/hiddesc.c0000644000175100017510000002756515232633614024017 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" enum usb_bcd_version { USB_SPEC_BCD_VERSION = 0x0200, USB_DEVICE_BCD_VERSION = 0x1234, USB_HID_BCD_VERSION = 0x0111 }; enum usb_ids { USB_DEVICE_VID = 0xFFFF, USB_DEVICE_PID = 0xFFFF }; enum usb_lang_id { USB_LANG_ID = 0x0409 }; enum usb_descriptor_string_index { USB_DESC_LANGID_STRING_INDEX = 0, USB_DESC_MFG_STRING_INDEX, USB_DESC_PRODUCT_STRING_INDEX, USB_DESC_SERIAL_STRING_INDEX }; enum usb_descr_length { // Standard length. USB_DESC_DEVICE_LEN = 18, USB_DESC_DEVICE_QUAL_LEN = 10, USB_DESC_CONF_LEN = 9, USB_DESC_OTHER_SPEED_CONF_LEN = 9, USB_DESC_INTERFACE_LEN = 9, USB_DESC_HID_LEN = 9, USB_DESCR_HID_REP_LEN = 56, USB_DESC_ENDPOINT_LEN = 7, // Total length. USB_DESC_DEVICE_TOTAL_LEN = USB_DESC_DEVICE_LEN, USB_DESC_DEVICE_QUAL_TOTAL_LEN = USB_DESC_DEVICE_QUAL_LEN, USB_DESC_CONF_TOTAL_LEN = USB_DESC_CONF_LEN + USB_DESC_INTERFACE_LEN + USB_DESC_HID_LEN + USB_DESC_ENDPOINT_LEN, USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN = USB_DESC_OTHER_SPEED_CONF_LEN + USB_DESC_INTERFACE_LEN, }; enum usb_descr_attributes { // Attributes (b7 - buspwr, b6 - selfpwr, b5 - rwu). USB_DESC_ATTRIBUTES = 0xA0, // 100 mA (div 2). USB_DESC_POWER_CONSUMPTION = 50 }; enum usb_descr_numbers { USB_DESC_CONFIG_COUNT = 1 }; static const BYTE CODE g_hid_report_desc[USB_DESCR_HID_REP_LEN] = { // Pad #1 configuration. 0x05, 0x01, // Usage page (Generic Desktop). 0x09, 0x05, // Usage (Game Pad). 0xa1, 0x01, // Collection (Application). 0xa1, 0x00, // Collection (Physical). 0x85, HID_REPORT_ID_GAMEPAD1, // Report id (1). 0x05, 0x09, // Usage page (Button). 0x19, 0x01, // Usage minimum (Button 1). 0x29, 0x08, // Usage maximum (Button 8). 0x15, 0x00, // Logical minimum (0). 0x25, 0x01, // Logical maximum (1). 0x95, HID_REPORT_BITS_COUNT, // Report count (8). 0x75, 0x01, // Report size (1). 0x81, 0x02, // Input (Data,Var,Abs). 0xc0, // End collection. 0xc0, // End collection. // Pad #2 configuration. 0x05, 0x01, // Usage page (Generic Desktop). 0x09, 0x05, // Usage (Game Pad). 0xa1, 0x01, // Collection (Application). 0xa1, 0x00, // Collection (Physical). 0x85, HID_REPORT_ID_GAMEPAD2, // Report id (2). 0x05, 0x09, // Usage page (Button). 0x19, 0x01, // Usage minimum (Button 1). 0x29, 0x08, // Usage maximum (Button 8). 0x15, 0x00, // Logical minimum (0). 0x25, 0x01, // Logical maximum (1). 0x95, HID_REPORT_BITS_COUNT, // Report count (8). 0x75, 0x01, // Report size (1). 0x81, 0x02, // Input (Data,Var,Abs). 0xc0, // End collection 0xc0 // End collection. }; static const BYTE CODE g_device_desc[USB_DESC_DEVICE_TOTAL_LEN] = { USB_DESC_DEVICE_LEN, // Descriptor length. USB_DESC_DEVICE, // Descriptor type. usb_word_lsb_get(USB_SPEC_BCD_VERSION), // USB BCD version, lo. usb_word_msb_get(USB_SPEC_BCD_VERSION), // USB BCD version, hi. 0x00, // Device class. 0x00, // Device sub-class. 0x00, // Device protocol. MAX_EP0_SIZE, // Maximum packet size (ep0 size). usb_word_lsb_get(USB_DEVICE_VID), // Vendor ID, lo. usb_word_msb_get(USB_DEVICE_VID), // Vendor ID, hi. usb_word_lsb_get(USB_DEVICE_PID), // Product ID, lo. usb_word_msb_get(USB_DEVICE_PID), // Product ID, hi. usb_word_lsb_get(USB_DEVICE_BCD_VERSION), // Device BCD version, lo. usb_word_msb_get(USB_DEVICE_BCD_VERSION), // Device BCD version, hi. USB_DESC_MFG_STRING_INDEX, USB_DESC_PRODUCT_STRING_INDEX, USB_DESC_SERIAL_STRING_INDEX, USB_DESC_CONFIG_COUNT // Configurations count. }; static const BYTE CODE g_device_qual_desc[USB_DESC_DEVICE_QUAL_TOTAL_LEN] = { USB_DESC_DEVICE_QUAL_LEN, // Descriptor length. USB_DESC_DEVICE_QUAL, // Descriptor type. usb_word_lsb_get(USB_SPEC_BCD_VERSION), // USB BCD version, lo. usb_word_msb_get(USB_SPEC_BCD_VERSION), // USB BCD version, hi. 0x00, // Device class. 0x00, // Device sub-class. 0x00, // Device protocol. MAX_EP0_SIZE, // Maximum packet size (ep0 size). USB_DESC_CONFIG_COUNT, // Configurations count. 0x00 // Reserved. }; static const BYTE CODE g_config_desc[USB_DESC_CONF_TOTAL_LEN] = { USB_DESC_CONF_LEN, // Descriptor length. USB_DESC_CONF, // Descriptor type. usb_word_lsb_get(USB_DESC_CONF_TOTAL_LEN), // Total length, lo. usb_word_msb_get(USB_DESC_CONF_TOTAL_LEN), // Total length, hi. 0x01, // Interfaces count. HID_CONFIG_NUMBER, // Configuration number. 0x00, // Configuration string index. USB_DESC_ATTRIBUTES, // Attributes. USB_DESC_POWER_CONSUMPTION, // Power consumption. // Interface descriptor. USB_DESC_INTERFACE_LEN, // Descriptor length. USB_DESC_INTERFACE, // Descriptor type. HID_IFACE_NUMBER, // Zero-based index of this interfacce. HID_ALT_IFACE_NUMBER, // Alternate setting. 0x01, // End points count (ep1 in). 0x03, // Class code (HID). 0x00, // Subclass code (boot). 0x00, // Protocol code (none). 0x00, // Interface string descriptor index. // HID descriptor. USB_DESC_HID_LEN, // Descriptor length. USB_DESC_HID, // Descriptor type. usb_word_lsb_get(USB_HID_BCD_VERSION), // HID class BCD version, lo. usb_word_msb_get(USB_HID_BCD_VERSION), // HID class BCD version, hi. 0x00, // Country code (HW country code). 0x01, // Number of HID class descriptors to follow. USB_DESC_REPORT, // Repord descriptor type (HID). usb_word_lsb_get(USB_DESCR_HID_REP_LEN), // Report descriptor total length, lo. usb_word_msb_get(USB_DESCR_HID_REP_LEN), // Report descriptor total length, hi. // End point descriptor. USB_DESC_ENDPOINT_LEN, // Descriptor length. USB_DESC_ENDPOINT, // Descriptor type. HID_EP_IN, // End point address (ep1 in). 0x03, // End point type (interrupt). usb_word_lsb_get(MAX_EP1_SIZE), // Maximum packet size, lo (ep1 size). usb_word_msb_get(MAX_EP1_SIZE), // Maximum packet size, hi (ep1 size). 0x01 // Polling interval (1 ms). }; static const BYTE CODE g_other_config_desc[USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN] = { USB_DESC_OTHER_SPEED_CONF_LEN, // Descriptor length. USB_DESC_OTHER_SPEED_CONF, // Descriptor type. usb_word_lsb_get(USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN), // Total length, lo. usb_word_msb_get(USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN), // Total length, hi. 0x01, // Interfaces number. 0x01, // Configuration number. 0x00, // Configuration string index. USB_DESC_ATTRIBUTES, // Attributes. USB_DESC_POWER_CONSUMPTION, // Power consumption. // Interface descriptor. USB_DESC_INTERFACE_LEN, // Descriptor length. USB_DESC_INTERFACE, // Descriptor type. 0x00, // Zero-based index of this interfacce. 0x00, // Alternate setting. 0x00, // End points number (only ep0). 0x00, // Class code. 0x00, // Subclass code.USB_DESC_OTHER_SPEED_CONFIGURATION 0x00, // Protocol code. 0x00 // Interface string descriptor index. }; static const BYTE CODE g_lang_id_desc[] = { 0x04, // Descriptor length. USB_DESC_STRING, // Descriptor type. usb_word_lsb_get(USB_LANG_ID), // Language id, lo. usb_word_msb_get(USB_LANG_ID) // Language id, hi. }; static const BYTE CODE g_manuf_str_desc[] = { 0x18, // Descriptor length. USB_DESC_STRING, // Descriptor type. // Unicode string: 'Q', 0, 'B', 0, 'S', 0, ' ', 0, 'e', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0 }; static const BYTE CODE g_product_str_desc[] = { 0x1A, // Descriptor length. USB_DESC_STRING, // Descriptor type. // Unicode string: 'N', 0, 'E', 0, 'S', 0, ' ', 0, 'G', 0, 'a', 0, 'm', 0, 'e', 0, 'P', 0, 'a', 0, 'd', 0, 's', 0 }; static const BYTE CODE g_serialno_str_desc[] = { 0x1A, // Descriptor length. USB_DESC_STRING, // Descriptor type. // Unicode string: '0', 0 ,'1', 0, '0', 0, '2', 0, '0', 0, '3', 0, '0', 0, '4', 0, '0', 0, '5', 0, '0', 0, '6', 0 }; static const BYTE CODE *ep0_string_desc_get(void) { switch (SETUPDAT[2]) { case USB_DESC_LANGID_STRING_INDEX: return g_lang_id_desc; case USB_DESC_MFG_STRING_INDEX: return g_manuf_str_desc; case USB_DESC_PRODUCT_STRING_INDEX: return g_product_str_desc; case USB_DESC_SERIAL_STRING_INDEX: return g_serialno_str_desc; default: break; } return NULL; } static const BYTE CODE *ep0_config_desc_get(BOOL other) { if (!other) { if (SETUPDAT[2] == 0) { return usb_is_high_speed() ? g_config_desc : g_other_config_desc; } } else { return usb_is_high_speed() ? g_other_config_desc : g_config_desc; } return NULL; } const BYTE CODE *hid_ep0_std_desc_get(void) { switch (SETUPDAT[3]) { case USB_DESC_DEVICE: return g_device_desc; case USB_DESC_CONF: return ep0_config_desc_get(FALSE); case USB_DESC_STRING: return ep0_string_desc_get(); case USB_DESC_DEVICE_QUAL: return g_device_qual_desc; case USB_DESC_OTHER_SPEED_CONF: return ep0_config_desc_get(TRUE); case USB_DESC_HID: return &g_config_desc[USB_DESC_CONF_LEN + USB_DESC_INTERFACE_LEN]; default: break; } return NULL; } const BYTE CODE *hid_ep0_report_desc_get(WORD *length) { *length = sizeof(g_hid_report_desc); return g_hid_report_desc; } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/core.h0000644000175100017510000001373215232633614023340 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_HW_H #define FX2_HW_H #include "defs.h" #ifdef __cplusplus extern "C" { #endif // Allowed range: 5000 - 48000. #ifndef CORE_IFREQ # define CORE_IFREQ 48000 // IFCLK frequency in kHz. #endif // Allowed values: 48000, 24000, or 12000. #ifndef CORE_CFREQ # define CORE_CFREQ 48000 // CLKOUT frequency in kHz. #endif #if (CORE_IFREQ < 5000) # error "CORE_IFREQ too small! Valid range: 5000 - 48000." #endif #if (CORE_IFREQ > 48000) # error "CORE_IFREQ too large! Valid range: 5000 - 48000." #endif #if (CORE_CFREQ != 48000) # if (CORE_CFREQ != 24000) # if (CORE_CFREQ != 12000) # error "CORE_CFREQ invalid! Valid values: 48000, 24000, 12000." # endif # endif #endif // Calculate synchronization delay. #define CORE_SCYCL (3 * (CORE_CFREQ) + 5 * (CORE_IFREQ) - 1) / (2 * (CORE_IFREQ)) #if (CORE_SCYCL == 1) # define sync_delay() {\ NOP(); } #endif #if (CORE_SCYCL == 2) # define sync_delay() {\ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 3) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 4) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 5) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 6) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 7) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 8) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 9) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 10) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 11) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 12) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 13) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 14) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 15) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #if (CORE_SCYCL == 16) # define sync_delay() {\ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); \ NOP(); } #endif #define code_all_irq_disable() (IE = 0) #define code_all_irq_enable() (IE = 1) void core_init(void); #ifdef __cplusplus } #endif #endif // FX2_HW_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/hid.c0000644000175100017510000000625615232633614023152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" #include "core.h" #include "usb.h" void hid_init(void) { // Disable end point 1 output. EP1OUTCFG = bmEP_DISABLE; sync_delay(); // Enable end point 1 input in interrupt mode. EP1INCFG = bmEP_ENABLE | bmEP_INT; sync_delay(); // Disable end point 2. EP2CFG = bmEP_DISABLE; sync_delay(); // Disable end point 4. EP4CFG = bmEP_DISABLE; sync_delay(); // Disable end point 6. EP6CFG = bmEP_DISABLE; sync_delay(); // Disable end point 8. EP8CFG = bmEP_DISABLE; sync_delay(); // Reset all FIFOs. FIFORESET = bmNAKALL; // NAK all host transfers. sync_delay(); FIFORESET = 0x00; sync_delay(); // Enable dual autopointer(s). AUTOPTRSETUP |= bmAPTREN; sync_delay(); } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/hidep1.c0000644000175100017510000000625715232633614023561 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" struct hid_report { const BYTE id; BYTE buttons; BYTE ready; }; static struct hid_report g_reports[HID_REPORTS_COUNT] = { {HID_REPORT_ID_GAMEPAD1, 0, FALSE}, {HID_REPORT_ID_GAMEPAD2, 0, FALSE} }; static void ep1_report_send(BYTE index) { if (!g_reports[index].ready) return; if (EP1INCS & bmEPBUSY) return; EP1INBUF[0] = g_reports[index].id; EP1INBUF[1] = g_reports[index].buttons; EP1INBC = 2; g_reports[index].ready = FALSE; } void hid_ep1_task(void) { BYTE index = 0; for (index = 0; index < HID_REPORTS_COUNT; ++index) ep1_report_send(index); } void hid_ep1_report_update(BYTE index, BYTE buttons) { g_reports[index].buttons = buttons; g_reports[index].ready = TRUE; } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/regs.h0000644000175100017510000006331215232633614023347 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_REGS_H #define FX2_REGS_H #include "defs.h" #ifdef __cplusplus extern "C" { #endif // // XDATA registers. // XDATA_REG(GPIF_WAVE_DATA, 0xE400) // GPIF waveform descriptor. XDATA_REG(RES_WAVEDATA_END, 0xE480) // Reserved. // General configuration. XDATA_REG(CPUCS, 0xE600) // Control & status. XDATA_REG(IFCONFIG, 0xE601) // Interface configuration. XDATA_REG(PINFLAGSAB, 0xE602) // FIFO FLAGA and FLAGB assignments. XDATA_REG(PINFLAGSCD, 0xE603) // FIFO FLAGC and FLAGD assignments. XDATA_REG(FIFORESET, 0xE604) // Restore FIFOS to default state. XDATA_REG(BREAKPT, 0xE605) // Breakpoint. XDATA_REG(BPADDRH, 0xE606) // Breakpoint address H. XDATA_REG(BPADDRL, 0xE607) // Breakpoint address L. XDATA_REG(UART230, 0xE608) // 230 Kbaud clock for T0,T1,T2. XDATA_REG(FIFOPINPOLAR, 0xE609) // FIFO polarities. XDATA_REG(REVID, 0xE60A) // Chip revision. XDATA_REG(REVCTL, 0xE60B) // Chip revision control. // Endpoint configuration. XDATA_REG(EP1OUTCFG, 0xE610) // Endpoint 1-out configuration. XDATA_REG(EP1INCFG, 0xE611) // Endpoint 1-in configuration. XDATA_REG(EP2CFG, 0xE612) // Endpoint 2 configuration. XDATA_REG(EP4CFG, 0xE613) // Endpoint 4 configuration. XDATA_REG(EP6CFG, 0xE614) // Endpoint 6 configuration. XDATA_REG(EP8CFG, 0xE615) // Endpoint 8 configuration. XDATA_REG(EP2FIFOCFG, 0xE618) // Endpoint 2 FIFO configuration. XDATA_REG(EP4FIFOCFG, 0xE619) // Endpoint 4 FIFO configuration. XDATA_REG(EP6FIFOCFG, 0xE61A) // Endpoint 6 FIFO configuration. XDATA_REG(EP8FIFOCFG, 0xE61B) // Endpoint 8 FIFO configuration. XDATA_REG(EP2AUTOINLENH, 0xE620) // Endpoint 2 packet length H (in only). XDATA_REG(EP2AUTOINLENL, 0xE621) // Endpoint 2 packet length L (in only). XDATA_REG(EP4AUTOINLENH, 0xE622) // Endpoint 4 packet length H (in only). XDATA_REG(EP4AUTOINLENL, 0xE623) // Endpoint 4 packet length L (in only). XDATA_REG(EP6AUTOINLENH, 0xE624) // Endpoint 6 packet length H (in only). XDATA_REG(EP6AUTOINLENL, 0xE625) // Endpoint 6 packet length L (in only). XDATA_REG(EP8AUTOINLENH, 0xE626) // Endpoint 8 packet length H (in only). XDATA_REG(EP8AUTOINLENL, 0xE627) // Endpoint 8 packet length L (in only). XDATA_REG(EP2FIFOPFH, 0xE630) // EP2 programmable flag trigger H. XDATA_REG(EP2FIFOPFL, 0xE631) // EP2 programmable flag trigger L. XDATA_REG(EP4FIFOPFH, 0xE632) // EP4 programmable flag trigger H. XDATA_REG(EP4FIFOPFL, 0xE633) // EP4 programmable flag trigger L. XDATA_REG(EP6FIFOPFH, 0xE634) // EP6 programmable flag trigger H. XDATA_REG(EP6FIFOPFL, 0xE635) // EP6 programmable flag trigger L. XDATA_REG(EP8FIFOPFH, 0xE636) // EP8 programmable flag trigger H. XDATA_REG(EP8FIFOPFL, 0xE637) // EP8 programmable flag trigger L. XDATA_REG(EP2ISOINPKTS, 0xE640) // EP2 (if ISO) in packets per frame (1-3). XDATA_REG(EP4ISOINPKTS, 0xE641) // EP4 (if ISO) in packets per frame (1-3). XDATA_REG(EP6ISOINPKTS, 0xE642) // EP6 (if ISO) in packets per frame (1-3). XDATA_REG(EP8ISOINPKTS, 0xE643) // EP8 (if ISO) in packets per frame (1-3). XDATA_REG(INPKTEND, 0xE648) // Force in packet end. XDATA_REG(OUTPKTEND, 0xE649) // Force out packet end. // Interrupts. XDATA_REG(EP2FIFOIE, 0xE650) // Endpoint 2 flag interrupt enable. XDATA_REG(EP2FIFOIRQ, 0xE651) // Endpoint 2 flag interrupt request. XDATA_REG(EP4FIFOIE, 0xE652) // Endpoint 4 flag interrupt enable. XDATA_REG(EP4FIFOIRQ, 0xE653) // Endpoint 4 flag interrupt request. XDATA_REG(EP6FIFOIE, 0xE654) // Endpoint 6 flag interrupt enable. XDATA_REG(EP6FIFOIRQ, 0xE655) // Endpoint 6 flag interrupt request. XDATA_REG(EP8FIFOIE, 0xE656) // Endpoint 8 flag interrupt enable. XDATA_REG(EP8FIFOIRQ, 0xE657) // Endpoint 8 flag interrupt request. XDATA_REG(IBNIE, 0xE658) // IN-BULK-NAK interrupt enable. XDATA_REG(IBNIRQ, 0xE659) // IN-BULK-NAK interrupt request. XDATA_REG(NAKIE, 0xE65A) // Endpoint ping NAK interrupt enable. XDATA_REG(NAKIRQ, 0xE65B) // Endpoint ping NAK interrupt request. XDATA_REG(USBIE, 0xE65C) // USB Int enables. XDATA_REG(USBIRQ, 0xE65D) // USB interrupt requests. XDATA_REG(EPIE, 0xE65E) // Endpoint interrupt enables. XDATA_REG(EPIRQ, 0xE65F) // Endpoint interrupt requests. XDATA_REG(GPIFIE, 0xE660) // GPIF interrupt enable. XDATA_REG(GPIFIRQ, 0xE661) // GPIF interrupt request. XDATA_REG(USBERRIE, 0xE662) // USB error interrupt enables. XDATA_REG(USBERRIRQ, 0xE663) // USB error interrupt requests. XDATA_REG(ERRCNTLIM, 0xE664) // USB error counter and limit. XDATA_REG(CLRERRCNT, 0xE665) // Clear error counter EC[3..0]. XDATA_REG(INT2IVEC, 0xE666) // Interrupt 2 (USB) autovector. XDATA_REG(INT4IVEC, 0xE667) // Interrupt 4 (FIFOS & GPIF) autovector. XDATA_REG(INTSETUP, 0xE668) // interrupt 2 & 4 setup. // Input/Output. XDATA_REG(PORTACFG, 0xE670) // I/O PORTA alternate configuration. XDATA_REG(PORTCCFG, 0xE671) // I/O PORTC alternate configuration. XDATA_REG(PORTECFG, 0xE672) // I/O PORTE alternate configuration. XDATA_REG(I2CS, 0xE678) // Bus control & status. XDATA_REG(I2DAT, 0xE679) // Bus data. XDATA_REG(I2CTL, 0xE67A) // Bus control. XDATA_REG(XAUTODAT1, 0xE67B) // Autoptr1 movx access. XDATA_REG(XAUTODAT2, 0xE67C) // Autoptr2 movx access. // USB Control. XDATA_REG(USBCS, 0xE680) // USB control & status. XDATA_REG(SUSPEND, 0xE681) // Put chip into suspend. XDATA_REG(WAKEUPCS, 0xE682) // Wakeup source and polarity. XDATA_REG(TOGCTL, 0xE683) // Toggle control. XDATA_REG(USBFRAMEH, 0xE684) // USB frame count H. XDATA_REG(USBFRAMEL, 0xE685) // USB frame count L. XDATA_REG(MICROFRAME, 0xE686) // Microframe count, 0-7. XDATA_REG(FNADDR, 0xE687) // USB function address. // Endpoints. XDATA_REG(EP0BCH, 0xE68A) // Endpoint 0 byte count H. XDATA_REG(EP0BCL, 0xE68B) // Endpoint 0 byte count L. XDATA_REG(EP1OUTBC, 0xE68D) // Endpoint 1 out byte count. XDATA_REG(EP1INBC, 0xE68F) // Endpoint 1 in byte count. XDATA_REG(EP2BCH, 0xE690) // Endpoint 2 byte count H. XDATA_REG(EP2BCL, 0xE691) // Endpoint 2 byte count L. XDATA_REG(EP4BCH, 0xE694) // Endpoint 4 byte count H. XDATA_REG(EP4BCL, 0xE695) // Endpoint 4 byte count L. XDATA_REG(EP6BCH, 0xE698) // Endpoint 6 byte count H. XDATA_REG(EP6BCL, 0xE699) // Endpoint 6 byte count L. XDATA_REG(EP8BCH, 0xE69C) // Endpoint 8 byte count H. XDATA_REG(EP8BCL, 0xE69D) // Endpoint 8 byte count L. XDATA_REG(EP0CS, 0xE6A0) // Endpoint control and status. XDATA_REG(EP1OUTCS, 0xE6A1) // Endpoint 1 out control and status. XDATA_REG(EP1INCS, 0xE6A2) // Endpoint 1 in control and status. XDATA_REG(EP2CS, 0xE6A3) // Endpoint 2 control and status. XDATA_REG(EP4CS, 0xE6A4) // Endpoint 4 control and status. XDATA_REG(EP6CS, 0xE6A5) // Endpoint 6 control and status. XDATA_REG(EP8CS, 0xE6A6) // Endpoint 8 control and status. XDATA_REG(EP2FIFOFLGS, 0xE6A7) // Endpoint 2 flags. XDATA_REG(EP4FIFOFLGS, 0xE6A8) // Endpoint 4 flags. XDATA_REG(EP6FIFOFLGS, 0xE6A9) // Endpoint 6 flags. XDATA_REG(EP8FIFOFLGS, 0xE6AA) // Endpoint 8 flags. XDATA_REG(EP2FIFOBCH, 0xE6AB) // EP2 FIFO total byte count H. XDATA_REG(EP2FIFOBCL, 0xE6AC) // EP2 FIFO total byte count L. XDATA_REG(EP4FIFOBCH, 0xE6AD) // EP4 FIFO total byte count H. XDATA_REG(EP4FIFOBCL, 0xE6AE) // EP4 FIFO total byte count L. XDATA_REG(EP6FIFOBCH, 0xE6AF) // EP6 FIFO total byte count H. XDATA_REG(EP6FIFOBCL, 0xE6B0) // EP6 FIFO total byte count L. XDATA_REG(EP8FIFOBCH, 0xE6B1) // EP8 FIFO total byte count H. XDATA_REG(EP8FIFOBCL, 0xE6B2) // EP8 FIFO total byte count L. XDATA_REG(SUDPTRH, 0xE6B3) // Setup data pointer high address byte. XDATA_REG(SUDPTRL, 0xE6B4) // Setup data pointer low address byte. XDATA_REG(SUDPTRCTL, 0xE6B5) // Setup data pointer auto mode. XDATA_REG(SETUPDAT[8], 0xE6B8) // 8 bytes of setup data. // GPIF. XDATA_REG(GPIFWFSELECT, 0xE6C0) // Waveform selector. XDATA_REG(GPIFIDLECS, 0xE6C1) // GPIF done, GPIF idle drive mode. XDATA_REG(GPIFIDLECTL, 0xE6C2) // Inactive bus, ctl states. XDATA_REG(GPIFCTLCFG, 0xE6C3) // CTL out pin drive. XDATA_REG(GPIFADRH, 0xE6C4) // GPIF address H. XDATA_REG(GPIFADRL, 0xE6C5) // GPIF address L. XDATA_REG(GPIFTCB3, 0xE6CE) // GPIF transaction count byte 3. XDATA_REG(GPIFTCB2, 0xE6CF) // GPIF transaction count byte 2. XDATA_REG(GPIFTCB1, 0xE6D0) // GPIF transaction count byte 1. XDATA_REG(GPIFTCB0, 0xE6D1) // GPIF transaction count byte 0. XDATA_REG(EP2GPIFFLGSEL, 0xE6D2) // EP2 GPIF flag select. XDATA_REG(EP2GPIFPFSTOP, 0xE6D3) // Stop GPIF EP2 transaction on prog flag. XDATA_REG(EP2GPIFTRIG, 0xE6D4) // EP2 FIFO trigger. XDATA_REG(EP4GPIFFLGSEL, 0xE6DA) // EP4 GPIF flag select. XDATA_REG(EP4GPIFPFSTOP, 0xE6DB) // Stop GPIF EP4 transaction on prog flag. XDATA_REG(EP4GPIFTRIG, 0xE6DC) // EP4 FIFO trigger. XDATA_REG(EP6GPIFFLGSEL, 0xE6E2) // EP6 GPIF Flag select. XDATA_REG(EP6GPIFPFSTOP, 0xE6E3) // Stop GPIF EP6 transaction on prog flag. XDATA_REG(EP6GPIFTRIG, 0xE6E4) // EP6 FIFO trigger. XDATA_REG(EP8GPIFFLGSEL, 0xE6EA) // EP8 GPIF flag select. XDATA_REG(EP8GPIFPFSTOP, 0xE6EB) // Stop GPIF EP8 transaction on prog flag. XDATA_REG(EP8GPIFTRIG, 0xE6EC) // EP8 FIFO trigger. XDATA_REG(XGPIFSGLDATH, 0xE6F0) // GPIF data H (16-bit mode only). XDATA_REG(XGPIFSGLDATLX, 0xE6F1) // Read/write GPIF data L & trigger transac. XDATA_REG(XGPIFSGLDATLNOX, 0xE6F2) // Read GPIF data L, no transac trigger. XDATA_REG(GPIFREADYCFG, 0xE6F3) // Internal RDY,Sync/Async, RDY5CFG. XDATA_REG(GPIFREADYSTAT, 0xE6F4) // RDY pin states. XDATA_REG(GPIFABORT, 0xE6F5) // Abort GPIF cycles. // UDMA. XDATA_REG(FLOWSTATE, 0xE6C6) // Defines GPIF flow state. XDATA_REG(FLOWLOGIC, 0xE6C7) // Defines flow/hold decision criteria. XDATA_REG(FLOWEQ0CTL, 0xE6C8) // CTL states during active flow state. XDATA_REG(FLOWEQ1CTL, 0xE6C9) // CTL states during hold flow state. XDATA_REG(FLOWHOLDOFF, 0xE6CA) // Holdoff configuration. XDATA_REG(FLOWSTB, 0xE6CB) // CTL/RDY signal to use as master data strobe. XDATA_REG(FLOWSTBEDGE, 0xE6CC) // Defines active master strobe edge. XDATA_REG(FLOWSTBHPERIOD, 0xE6CD) // Half period of output master strobe. XDATA_REG(GPIFHOLDAMOUNT, 0xE60C) // Data delay shift. XDATA_REG(UDMACRCH, 0xE67D) // CRC upper byte. XDATA_REG(UDMACRCL, 0xE67E) // CRC lower byte. XDATA_REG(UDMACRCQUAL, 0xE67F) // UDMA in only, host terminated use only. // Endpoint buffers. #define MAX_EP0_SIZE 64 #define MAX_EP1_SIZE 64 #define MAX_EP2468_SIZE 1024 XDATA_REG(EP0BUF[MAX_EP0_SIZE], 0xE740) // EP0 buffer (in or out). XDATA_REG(EP1OUTBUF[MAX_EP1_SIZE], 0xE780) // EP1 buffer (out only). XDATA_REG(EP1INBUF[MAX_EP1_SIZE], 0xE7C0) // EP1 buffer (in only). XDATA_REG(EP2FIFOBUF[MAX_EP2468_SIZE], 0xF000) // 512/1024-byte EP2 buffer (in or out). XDATA_REG(EP4FIFOBUF[MAX_EP2468_SIZE], 0xF400) // 512 byte EP4 buffer (in or out). XDATA_REG(EP6FIFOBUF[MAX_EP2468_SIZE], 0xF800) // 512/1024-byte EP6 buffer (in or out). XDATA_REG(EP8FIFOBUF[MAX_EP2468_SIZE], 0xFC00) // 512 byte EP8 buffer (in or out). // Error correction code (ECC) registers (FX2LP/FX1 only). XDATA_REG(ECCCFG, 0xE628) // ECC configuration. XDATA_REG(ECCRESET, 0xE629) // ECC reset. XDATA_REG(ECC1B0, 0xE62A) // ECC1 byte 0. XDATA_REG(ECC1B1, 0xE62B) // ECC1 byte 1. XDATA_REG(ECC1B2, 0xE62C) // ECC1 byte 2. XDATA_REG(ECC2B0, 0xE62D) // ECC2 byte 0. XDATA_REG(ECC2B1, 0xE62E) // ECC2 byte 1. XDATA_REG(ECC2B2, 0xE62F) // ECC2 byte 2. // Feature registers(FX2LP/FX1 only). XDATA_REG(GPCR2, 0xE50D) // Chip features. // // SFR registers. // SPEC_FUN_REG(IOA, 0x80) // Port A. SPEC_FUN_REG_BIT(PA0, 0x80, 0) SPEC_FUN_REG_BIT(PA1, 0x80, 1) SPEC_FUN_REG_BIT(PA2, 0x80, 2) SPEC_FUN_REG_BIT(PA3, 0x80, 3) SPEC_FUN_REG_BIT(PA4, 0x80, 4) SPEC_FUN_REG_BIT(PA5, 0x80, 5) SPEC_FUN_REG_BIT(PA6, 0x80, 6) SPEC_FUN_REG_BIT(PA7, 0x80, 7) SPEC_FUN_REG(SP, 0x81) // Stack pointer. SPEC_FUN_REG(DPL, 0x82) // Data pointer 0 L. SPEC_FUN_REG(DPH, 0x83) // Data pointer 0 H. SPEC_FUN_REG(DPL1, 0x84) // Data pointer 1 L. SPEC_FUN_REG(DPH1, 0x85) // Data pointer 1 L. SPEC_FUN_REG(DPS, 0x86) // Data pointer 0/1 select. SPEC_FUN_REG(PCON, 0x87) // Power control. SPEC_FUN_REG(TCON, 0x88) // Timer/counter control. SPEC_FUN_REG_BIT(IT0, 0x88, 0) SPEC_FUN_REG_BIT(IE0, 0x88, 1) SPEC_FUN_REG_BIT(IT1, 0x88, 2) SPEC_FUN_REG_BIT(IE1, 0x88, 3) SPEC_FUN_REG_BIT(TR0, 0x88, 4) SPEC_FUN_REG_BIT(TF0, 0x88, 5) SPEC_FUN_REG_BIT(TR1, 0x88, 6) SPEC_FUN_REG_BIT(TF1, 0x88, 7) SPEC_FUN_REG(TMOD, 0x89) // Timer/counter mode control. SPEC_FUN_REG(TL0, 0x8A) // Timer 0 reload L. SPEC_FUN_REG(TL1, 0x8B) // Timer 1 reload L. SPEC_FUN_REG(TH0, 0x8C) // Timer 0 reload H. SPEC_FUN_REG(TH1, 0x8D) // Timer 1 reload H. SPEC_FUN_REG(CKCON, 0x8E) // Clock control. SPEC_FUN_REG(IOB, 0x90) // Port B. SPEC_FUN_REG_BIT(PB0, 0x90, 0) SPEC_FUN_REG_BIT(PB1, 0x90, 1) SPEC_FUN_REG_BIT(PB2, 0x90, 2) SPEC_FUN_REG_BIT(PB3, 0x90, 3) SPEC_FUN_REG_BIT(PB4, 0x90, 4) SPEC_FUN_REG_BIT(PB5, 0x90, 5) SPEC_FUN_REG_BIT(PB6, 0x90, 6) SPEC_FUN_REG_BIT(PB7, 0x90, 7) SPEC_FUN_REG(EXIF, 0x91) // External interrupt flag. SPEC_FUN_REG(MPAGE, 0x92) // Upper address page of movx. SPEC_FUN_REG(SCON0, 0x98) // Serial port 0 control. SPEC_FUN_REG_BIT(RI, 0x98, 0) SPEC_FUN_REG_BIT(TI, 0x98, 1) SPEC_FUN_REG_BIT(RB8, 0x98, 2) SPEC_FUN_REG_BIT(TB8, 0x98, 3) SPEC_FUN_REG_BIT(REN, 0x98, 4) SPEC_FUN_REG_BIT(SM2, 0x98, 5) SPEC_FUN_REG_BIT(SM1, 0x98, 6) SPEC_FUN_REG_BIT(SM0, 0x98, 7) SPEC_FUN_REG(SBUF0, 0x99) // Serial port 0 data buffer. SPEC_FUN_REG(AUTOPTRH1, 0x9A) // Auto-pointer 1 address H. SPEC_FUN_REG(AUTOPTRL1, 0x9B) // Auto-pointer 1 address L. SPEC_FUN_REG(AUTOPTRH2, 0x9D) // Auto-pointer 2 address H. SPEC_FUN_REG(AUTOPTRL2, 0x9E) // Auto-pointer 2 address L. SPEC_FUN_REG(IOC, 0xA0) // Port C. SPEC_FUN_REG_BIT(PC0, 0xA0, 0) SPEC_FUN_REG_BIT(PC1, 0xA0, 1) SPEC_FUN_REG_BIT(PC2, 0xA0, 2) SPEC_FUN_REG_BIT(PC3, 0xA0, 3) SPEC_FUN_REG_BIT(PC4, 0xA0, 4) SPEC_FUN_REG_BIT(PC5, 0xA0, 5) SPEC_FUN_REG_BIT(PC6, 0xA0, 6) SPEC_FUN_REG_BIT(PC7, 0xA0, 7) SPEC_FUN_REG(INT2CLR, 0xA1) // Interrupt 2 clear. SPEC_FUN_REG(INT4CLR, 0xA2) // Interrupt 4 clear. SPEC_FUN_REG(IE, 0xA8) // Interrupt enable. SPEC_FUN_REG_BIT(EX0, 0xA8, 0) SPEC_FUN_REG_BIT(ET0, 0xA8, 1) SPEC_FUN_REG_BIT(EX1, 0xA8, 2) SPEC_FUN_REG_BIT(ET1, 0xA8, 3) SPEC_FUN_REG_BIT(ES0, 0xA8, 4) SPEC_FUN_REG_BIT(ET2, 0xA8, 5) SPEC_FUN_REG_BIT(ES1, 0xA8, 6) SPEC_FUN_REG_BIT(EA, 0xA8, 7) SPEC_FUN_REG(EP2468STAT, 0xAA) // Endpoint 2,4,6,8 status flags. SPEC_FUN_REG(EP24FIFOFLGS, 0xAB) // Endpoint 2,4 slave FIFO status flags. SPEC_FUN_REG(EP68FIFOFLGS, 0xAC) // Endpoint 6,8 slave FIFO status flags. SPEC_FUN_REG(AUTOPTRSETUP, 0xAF) // Auto-pointer 1,2 setup. SPEC_FUN_REG(IOD, 0xB0) // Port D. SPEC_FUN_REG_BIT(PD0, 0xB0, 0) SPEC_FUN_REG_BIT(PD1, 0xB0, 1) SPEC_FUN_REG_BIT(PD2, 0xB0, 2) SPEC_FUN_REG_BIT(PD3, 0xB0, 3) SPEC_FUN_REG_BIT(PD4, 0xB0, 4) SPEC_FUN_REG_BIT(PD5, 0xB0, 5) SPEC_FUN_REG_BIT(PD6, 0xB0, 6) SPEC_FUN_REG_BIT(PD7, 0xB0, 7) SPEC_FUN_REG(IOE, 0xB1) // Port E. SPEC_FUN_REG(OEA, 0xB2) // Port A out enable. SPEC_FUN_REG(OEB, 0xB3) // Port B out enable. SPEC_FUN_REG(OEC, 0xB4) // Port C out enable. SPEC_FUN_REG(OED, 0xB5) // Port D out enable. SPEC_FUN_REG(OEE, 0xB6) // Port E out enable. SPEC_FUN_REG(IP, 0xB8) // Interrupt prority. SPEC_FUN_REG_BIT(PX0, 0xB8, 0) SPEC_FUN_REG_BIT(PT0, 0xB8, 1) SPEC_FUN_REG_BIT(PX1, 0xB8, 2) SPEC_FUN_REG_BIT(PT1, 0xB8, 3) SPEC_FUN_REG_BIT(PS0, 0xB8, 4) SPEC_FUN_REG_BIT(PT2, 0xB8, 5) SPEC_FUN_REG_BIT(PS1, 0xB8, 6) SPEC_FUN_REG(EP01STAT, 0xBA) // Endpoint 0,1 status. SPEC_FUN_REG(GPIFTRIG, 0xBB) // Endpoint 2,4,6,8 GPIF slave FIFO trigger. SPEC_FUN_REG(GPIFSGLDATH, 0xBD) // GPIF data H. SPEC_FUN_REG(GPIFSGLDATLX, 0xBE) // GPIF data L with trigger. SPEC_FUN_REG(GPIFSGLDATLNOX, 0xBF) // GPIF data L without trigger. SPEC_FUN_REG(SCON1, 0xC0) // Serial port 1 control. SPEC_FUN_REG_BIT(RI1, 0xC0, 0) SPEC_FUN_REG_BIT(TI1, 0xC0, 1) SPEC_FUN_REG_BIT(RB81, 0xC0, 2) SPEC_FUN_REG_BIT(TB81, 0xC0, 3) SPEC_FUN_REG_BIT(REN1, 0xC0, 4) SPEC_FUN_REG_BIT(SM21, 0xC0, 5) SPEC_FUN_REG_BIT(SM11, 0xC0, 6) SPEC_FUN_REG_BIT(SM01, 0xC0, 7) SPEC_FUN_REG(SBUF1, 0xC1) // Serial port 1 data buffer. SPEC_FUN_REG(T2CON, 0xC8) // Timer/counter 2 control. SPEC_FUN_REG_BIT(CP_RL2, 0xC8, 0) SPEC_FUN_REG_BIT(C_T2, 0xC8, 1) SPEC_FUN_REG_BIT(TR2, 0xC8, 2) SPEC_FUN_REG_BIT(EXEN2, 0xC8, 3) SPEC_FUN_REG_BIT(TCLK, 0xC8, 4) SPEC_FUN_REG_BIT(RCLK, 0xC8, 5) SPEC_FUN_REG_BIT(EXF2, 0xC8, 6) SPEC_FUN_REG_BIT(TF2, 0xC8, 7) SPEC_FUN_REG(RCAP2L, 0xCA) // Capture for timer 2 auto-reload up-counter L. SPEC_FUN_REG(RCAP2H, 0xCB) // Capture for timer 2 auto-reload up-counter H. SPEC_FUN_REG(TL2, 0xCC) // Timer 2 reload L. SPEC_FUN_REG(TH2, 0xCD) // Timer 2 reload H. SPEC_FUN_REG(PSW, 0xD0) // Program status word. SPEC_FUN_REG_BIT(P, 0xD0, 0) SPEC_FUN_REG_BIT(FL, 0xD0, 1) SPEC_FUN_REG_BIT(OV, 0xD0, 2) SPEC_FUN_REG_BIT(RS0, 0xD0, 3) SPEC_FUN_REG_BIT(RS1, 0xD0, 4) SPEC_FUN_REG_BIT(F0, 0xD0, 5) SPEC_FUN_REG_BIT(AC, 0xD0, 6) SPEC_FUN_REG_BIT(CY, 0xD0, 7) SPEC_FUN_REG(EICON, 0xD8) // External interrupt control. SPEC_FUN_REG_BIT(INT6, 0xD8, 3) SPEC_FUN_REG_BIT(RESI, 0xD8, 4) SPEC_FUN_REG_BIT(ERESI, 0xD8, 5) SPEC_FUN_REG_BIT(SMOD1, 0xD8, 7) SPEC_FUN_REG(ACC, 0xE0) // Accumulator. SPEC_FUN_REG(EIE, 0xE8) // External interrupt enable. SPEC_FUN_REG_BIT(EUSB, 0xE8, 0) SPEC_FUN_REG_BIT(EI2C, 0xE8, 1) SPEC_FUN_REG_BIT(EIEX4, 0xE8, 2) SPEC_FUN_REG_BIT(EIEX5, 0xE8, 3) SPEC_FUN_REG_BIT(EIEX6, 0xE8, 4) SPEC_FUN_REG(B, 0xF0) // B SPEC_FUN_REG(EIP, 0xF8) // External interrupt priority control. SPEC_FUN_REG_BIT(PUSB, 0xF8, 0) SPEC_FUN_REG_BIT(PI2C, 0xF8, 1) SPEC_FUN_REG_BIT(EIPX4, 0xF8, 2) SPEC_FUN_REG_BIT(EIPX5, 0xF8, 3) SPEC_FUN_REG_BIT(EIPX6, 0xF8, 4) // // Register bit masks. // // CPU control & status register (CPUCS). enum cpucs_bits { bmPRTCSTB = bmBIT5, bmCLKSPD = bmBIT4 | bmBIT3, bmCLKSPD1 = bmBIT4, bmCLKSPD0 = bmBIT3, bmCLKINV = bmBIT2, bmCLKOE = bmBIT1, bm8051RES = bmBIT0 }; // Port A (PORTACFG). enum portacfg_bits { bmFLAGD = bmBIT7, bmINT1 = bmBIT1, bmINT0 = bmBIT0 }; // Port C (PORTCCFG). enum portccfg_bits { bmGPIFA7 = bmBIT7, bmGPIFA6 = bmBIT6, bmGPIFA5 = bmBIT5, bmGPIFA4 = bmBIT4, bmGPIFA3 = bmBIT3, bmGPIFA2 = bmBIT2, bmGPIFA1 = bmBIT1, bmGPIFA0 = bmBIT0 }; // Port E (PORTECFG). enum portecfg_bits { bmGPIFA8 = bmBIT7, bmT2EX = bmBIT6, bmINT6 = bmBIT5, bmRXD1OUT = bmBIT4, bmRXD0OUT = bmBIT3, bmT2OUT = bmBIT2, bmT1OUT = bmBIT1, bmT0OUT = bmBIT0 }; // I2C control & status register (I2CS). enum i2cs_bits { bmSTART = bmBIT7, bmSTOP = bmBIT6, bmLASTRD = bmBIT5, bmID = bmBIT4 | bmBIT3, bmBERR = bmBIT2, bmACK = bmBIT1, bmDONE = bmBIT0 }; // I2C control register (I2CTL). enum i2ctl_bits { bmSTOPIE = bmBIT1, bm400KHZ = bmBIT0 }; // Interrupt 2 (USB) autovector register (INT2IVEC). enum int2ivec_bits { bmIV4 = bmBIT6, bmIV3 = bmBIT5, bmIV2 = bmBIT4, bmIV1 = bmBIT3, bmIV0 = bmBIT2 }; // USB interrupt request & enable registers (USBIE/USBIRQ). enum usbieirq_bits { bmEP0ACK = bmBIT6, bmHSGRANT = bmBIT5, bmURES = bmBIT4, bmSUSP = bmBIT3, bmSUTOK = bmBIT2, bmSOF = bmBIT1, bmSUDAV = bmBIT0 }; // End point interrupt request & enable registers (EPIE/EPIRQ). enum epieirq_bits { bmEP8 = bmBIT7, bmEP6 = bmBIT6, bmEP4 = bmBIT5, bmEP2 = bmBIT4, bmEP1OUT = bmBIT3, bmEP1IN = bmBIT2, bmEP0OUT = bmBIT1, bmEP0IN = bmBIT0 }; // Breakpoint register (BREAKPT). enum breakpt_bits { bmBREAK = bmBIT3, bmBPPULSE = bmBIT2, bmBPEN = bmBIT1 }; // Interrupt 2 & 4 setup (INTSETUP). enum intsetup_bits { bmAV2EN = bmBIT3, bmINT4SRC = bmBIT1, bmAV4EN = bmBIT0 }; // USB control & status register (USBCS). enum usbcs_bits { bmHSM = bmBIT7, bmDISCON = bmBIT3, bmNOSYNSOF = bmBIT2, bmRENUM = bmBIT1, bmSIGRESUME = bmBIT0 }; // Wakeup control and status register (WAKEUPCS). enum wakeupcs_bits { bmWU2 = bmBIT7, bmWU = bmBIT6, bmWU2POL = bmBIT5, bmWUPOL = bmBIT4, bmDPEN = bmBIT2, bmWU2EN = bmBIT1, bmWUEN = bmBIT0 }; // End point 0 control & status register (EP0CS). enum ep0cs_bits { bmHSNAK = bmBIT7 }; // End point 0-1 control & status registers // (EP0CS/EP1OUTCS/EP1INCS). enum ep01cs_bits { bmEPBUSY = bmBIT1, bmEPSTALL = bmBIT0 }; // End point 2-8 Control & status registers // (EP2CS/EP4CS/EP6CS/EP8CS). enum ep2468cs_bits { MSK_EP2468CS_NPAK = bmBIT6 | bmBIT5 | bmBIT4, MSK_EP2468CS_EPFULL = bmBIT3, MSK_EP2468CS_EPEMPTY = bmBIT2 }; // End point status SFR bits (EP2468STAT). enum ep2468stat_bits { bmEP8FULL = bmBIT7, bmEP8EMPTY = bmBIT6, bmEP6FULL = bmBIT5, bmEP6EMPTY = bmBIT4, bmEP4FULL = bmBIT3, bmEP4EMPTY = bmBIT2, bmEP2FULL = bmBIT1, bmEP2EMPTY = bmBIT0 }; // End point 0,1 status bits (EP01STAT). enum ep01stat_bits { bmEP1INBSY = bmBIT2, bmEP1OUTBSY = bmBIT1, bmEP0BSY = bmBIT0 }; // Setup data pointer auto mode (SUDPTRCTL). enum sudptrctl_bits { bmSDPAUTO = bmBIT0 }; // End point data toggle control (TOGCTL). enum togctl_bits { bmQUERYTOGGLE = bmBIT7, bmSETTOGGLE = bmBIT6, bmRESETTOGGLE = bmBIT5, bmTOGCTLEPMASK = bmBIT3 | bmBIT2 | bmBIT1 | bmBIT0 }; // In bulk NAK enable and request bits (IBNIE/IBNIRQ). enum ibnieirq_bits { bmEP8IBN = bmBIT5, bmEP6IBN = bmBIT4, bmEP4IBN = bmBIT3, bmEP2IBN = bmBIT2, bmEP1IBN = bmBIT1, bmEP0IBN = bmBIT0 }; // Ping NAK enable and request bits (NAKIE/NAKIRQ). enum nakieirq_bits { bmEP8PING = bmBIT7, bmEP6PING = bmBIT6, bmEP4PING = bmBIT5, bmEP2PING = bmBIT4, bmEP1PING = bmBIT3, bmEP0PING = bmBIT2, bmIBN = bmBIT0 }; // Interface configuration bits (IFCONFIG). enum ifconfig_bits { bmIFCLKSRC = bmBIT7, bm3048MHZ = bmBIT6, bmIFCLKOE = bmBIT5, bmIFCLKPOL = bmBIT4, bmASYNC = bmBIT3, bmGSTATE = bmBIT2, bmIFCFG = bmBIT0 | bmBIT1 }; // IFCFG field of IFCONFIG register. enum ifcfg_bits { bmIFPORTS = 0, bmIFRESERVED = bmBIT0, bmIFGPIF = bmBIT1, bmIFSLAVEFIFO = bmBIT0 | bmBIT1 }; // End point 2,4,6,8 FIFO configuration bits // (EP2FIFOCFG,EP4FIFOCFG,EP6FIFOCFG,EP8FIFOCFG). enum ep2468fifocfg_bits { bmINFM = bmBIT6, bmOEP = bmBIT5, bmAUTOOUT = bmBIT4, bmAUTOIN = bmBIT3, bmZEROLENIN = bmBIT2, bmWORDWIDE = bmBIT0 }; // Chip revision control bits (REVCTL). enum revctl_bits { bmNOAUTOARM = bmBIT1, bmSKIPCOMMIT = bmBIT0 }; // Fifo reset bits (FIFORESET). enum fiforeset_bits { bmNAKALL = bmBIT7, bmFREP3 = bmBIT3, bmFREP2 = bmBIT2, bmFREP1 = bmBIT1, bmFREP0 = bmBIT0 }; // Chip feature register (GPCR2). enum gpcr2_bits { bmFULLSPEEDONLY = bmBIT4 }; // Clock control register (CKCON). // Note: a RevE errata states that stretch must=0 // to set OUTxBC. enum ckcon_bits { bmT2M = bmBIT5, bmT1M = bmBIT4, bmT0M = bmBIT3, bmSTRETCH = bmBIT0 | bmBIT1 | bmBIT2 }; enum data_mem_stretch { bmFW_STRETCH1 = 0, // Movx: 2 cycles, R/W strobe: 2 cycles... bmFW_STRETCH2 = 1, // Movx: 3 cycles, R/W strobe: 4 cycles... bmFW_STRETCH3 = 2, // Movx: 4 cycles, R/W strobe: 8 cycles... bmFW_STRETCH4 = 3, // Movx: 5 cycles, R/W strobe: 12 cycles... bmFW_STRETCH5 = 4, // Movx: 6 cycles, R/W strobe: 16 cycles... bmFW_STRETCH6 = 5, // Movx: 7 cycles, R/W strobe: 20 cycles... bmFW_STRETCH7 = 6, // Movx: 8 cycles, R/W strobe: 24 cycles... bmFW_STRETCH8 = 7 // Movx: 9 cycles, R/W strobe: 28 cycles... }; // External interrupt flags (EXIF). enum exif_bits { bmIE5 = bmBIT7, bmIE4 = bmBIT6, bmI2CINT = bmBIT5, bmUSBNT = bmBIT4 }; // External interrupt control (EICON). enum eicon_bits { bmSMOD1 = bmBIT7, bmERESI = bmBIT5, bmRESI = bmBIT4, //bmINT6 = bmBIT3 }; // Power control (PCON). enum pcon_bits { bmSMOD0 = bmBIT7, bmIDLE = bmBIT0 }; // Autopointer 1 & 2 setup (AUTOPTRSETUP). enum autoptrsetup_bits { bmAPTR2INC = bmBIT2, bmAPTR1INC = bmBIT1, bmAPTREN = bmBIT0 }; #ifdef __cplusplus } #endif #endif // FX2_REGS_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/defs.h0000644000175100017510000001135315232633614023326 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_DEFS_H #define FX2_DEFS_H #ifdef __cplusplus extern "C" { #endif enum bit_mask { bmBIT0 = 0x01, bmBIT1 = 0x02, bmBIT2 = 0x04, bmBIT3 = 0x08, bmBIT4 = 0x10, bmBIT5 = 0x20, bmBIT6 = 0x40, bmBIT7 = 0x80 }; enum boolean { FALSE = 0, TRUE }; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef unsigned char BOOL; #ifndef NULL #define NULL (void *)0 #endif #if defined(__ICC8051__) #include # define NOP() __no_operation() # define XDATA __xdata # define CODE __code # define AT __at # define SFR __sfr # define SBIT __bit # define XDATA_REG(reg_name, reg_addr) \ XDATA __no_init volatile BYTE reg_name @ reg_addr; # define SPEC_FUN_REG(reg_name, reg_addr) \ SFR __no_init volatile BYTE reg_name @ reg_addr; # define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \ SBIT __no_init volatile _Bool bit_name @ (reg_addr+bit_num); # define _PPTOSTR_(x) #x # define _PPARAM_(address) _PPTOSTR_(vector=address * 8 + 3) # define INTERRUPT(isr_name, vector) \ _Pragma(_PPARAM_(vector)) __interrupt void isr_name(void) #elif defined (__C51__) # include # define NOP() _nop_() # define XDATA xdata # define CODE code # define AT _at_ # define SFR sfr # define SBIT sbit # if defined(DEFINE_REGS) # define XDATA_REG(reg_name, reg_addr) \ XDATA volatile BYTE reg_name AT reg_addr; # else # define XDATA_REG(reg_name, reg_addr) \ extern XDATA volatile BYTE reg_name; # endif # define SPEC_FUN_REG(reg_name, reg_addr) \ SFR reg_name = reg_addr; # define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \ sbit bit_name = reg_addr + bit_num; # define INTERRUPT(isr_name, num) \ void isr_name (void) interrupt num #elif defined (__SDCC_mcs51) # define NOP() __asm nop __endasm # define XDATA __xdata # define CODE __code # define AT __at # define SFR __sfr # define SBIT __sbit # define XDATA_REG(reg_name, reg_addr) \ XDATA AT reg_addr volatile BYTE reg_name; # define SPEC_FUN_REG(reg_name, reg_addr) \ SFR AT reg_addr reg_name; # define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \ SBIT AT reg_addr + bit_num bit_name; # define INTERRUPT(isr_name, num) \ void isr_name (void) __interrupt num #else #error "Unsupported toolchain" #endif #ifdef __cplusplus } #endif #endif // FX2_DEFS_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/usb.c0000644000175100017510000000751715232633614023200 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "core.h" #include "hid.h" #include "usb.h" void usb_init(void) { // Disable all USB interrupts. USBIE = 0; sync_delay(); // Disable all end point interrupts. EPIE = 0; sync_delay(); // Disable all end point ping-nak interrupts. NAKIE = 0; sync_delay(); // Disable all USB error interrupts. USBERRIE = 0; sync_delay(); // Disable USB && GPIF autovectoring. INTSETUP = 0; sync_delay(); // Clear USB interrupt requests. USBIRQ = bmSUDAV | bmSOF | bmSUTOK | bmSUSP | bmURES | bmHSGRANT | bmEP0ACK; sync_delay(); // Clear end point interrupt requests. EPIRQ = bmEP0IN | bmEP0OUT | bmEP1IN | bmEP1OUT | bmEP2 | bmEP4 | bmEP6 | bmEP8; sync_delay(); // Set USB interrupt to high priority. PUSB = 1; sync_delay(); // Enable USB interrupts. EUSB = 1; sync_delay(); // As we use SOFs to detect disconnect we have // to disable SOF synthesizing. USBCS |= bmNOSYNSOF; sync_delay(); hid_init(); // Disable FX2-internal enumeration support. USBCS |= bmRENUM; sync_delay(); } void usb_task(void) { if (USBIRQ & bmSUDAV) { USBIRQ = bmSUDAV; hid_ep0_setup_task(); } if (USBIRQ & bmEP0ACK) { USBIRQ = bmEP0ACK; } if (USBIRQ & bmURES) { USBIRQ = bmURES; } if (USBIRQ & bmSUSP) { USBIRQ = bmSUSP; } hid_ep1_task(); } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/gpio.c0000644000175100017510000001126715232633614023342 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "core.h" #include "gpio.h" #include "hid.h" #include "regs.h" static WORD g_counter = 0; // We use this empirical value to make a GPIO polling // every ~10 msec (rough). It is a simplest way, because // instead we need to use a timers with interrupts callbacks. enum { POLLING_COUNTER = 580 }; // Pins on the port A. enum gpio_pins { GPIO_CLK_PIN = bmBIT0, GPIO_DATA1_PIN = bmBIT2, GPIO_DATA2_PIN = bmBIT4, GPIO_LATCH_PIN = bmBIT6, }; static struct { const BYTE pin; BYTE buttons; } g_reports[HID_REPORTS_COUNT] = { {GPIO_DATA1_PIN, 0}, {GPIO_DATA2_PIN, 0} }; // Pulse width around ~1 usec. static void gpio_latch_pulse(void) { IOA |= GPIO_LATCH_PIN; sync_delay(); sync_delay(); sync_delay(); IOA &= ~GPIO_LATCH_PIN; sync_delay(); } // Pulse width around ~1 usec. static void gpio_clk_pulse(void) { IOA |= GPIO_CLK_PIN; sync_delay(); sync_delay(); sync_delay(); IOA &= ~GPIO_CLK_PIN; sync_delay(); } static void gpio_reports_clean(void) { BYTE index = 0; for (index = 0; index < HID_REPORTS_COUNT; ++index) g_reports[index].buttons = 0; } static void gpio_reports_send(void) { BYTE index = 0; for (index = 0; index < HID_REPORTS_COUNT; ++index) hid_ep1_report_update(index, g_reports[index].buttons); } static void gpio_poll(void) { BYTE pos = 0; // Cleanup reports. gpio_reports_clean(); // Send latch pulse. gpio_latch_pulse(); for (pos = 0; pos < HID_REPORT_BITS_COUNT; ++pos) { // TODO: Add some nops here? BYTE index = 0; for (index = 0; index < HID_REPORTS_COUNT; ++index) { // Low state means that a button is pressed. const BOOL v = (IOA & g_reports[index].pin) ? 0 : 1; g_reports[index].buttons |= (v << pos); } // Send clock pulse. gpio_clk_pulse(); } gpio_reports_send(); } void gpio_init(void) { // Set interface to ports. IFCONFIG = (IFCONFIG & (~bmIFCFG)) | bmIFPORTS; sync_delay(); // Initialize the CLK and LATCH pins as output. OEA = GPIO_CLK_PIN | GPIO_LATCH_PIN; sync_delay(); } void gpio_task(void) { if (g_counter < POLLING_COUNTER) { ++g_counter; } else { g_counter = 0; gpio_poll(); } } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/usb.h0000644000175100017510000001567215232633614023206 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_USB_H #define FX2_USB_H #include "regs.h" #ifdef __cplusplus extern "C" { #endif enum usb_setup_bmreq_bits { bmSETUP_DIR = bmBIT7, bmSETUP_TYPE = bmBIT5 | bmBIT6, bmSETUP_RECIPIENT = bmBIT0 | bmBIT1 | bmBIT2 | bmBIT3 | bmBIT4 }; // Setup request direction. enum usb_setup_req_direction_bits { bmSETUP_TO_DEVICE = 0, // From host to sevice direction. bmSETUP_TO_HOST = bmBIT7 // From device to host direction. }; // Setup request type. enum usb_setup_req_type_bits { bmSETUP_STANDARD = 0, // Standard request. bmSETUP_CLASS = bmBIT5, // Class request. bmSETUP_VENDOR = bmBIT6, // Vendor request. }; // Setup request recipient. enum usb_setup_req_recipient_bits { bmSETUP_DEVICE = 0, // Device recipient. bmSETUP_IFACE = bmBIT0, // Interface recipient. bmSETUP_EP = bmBIT1, // End point recipient. bmSETUP_OTHER = bmBIT0 | bmBIT1 // Other recipient. }; // Setup request code. enum usb_setup_req_code { USB_SETUP_GET_STATUS = 0x00, // Get status code. USB_SETUP_CLEAR_FEATURE = 0x01, // Clear feature code. USB_SETUP_RESERVED1 = 0x02, // Reserved code. USB_SETUP_SET_FEATURE = 0x03, // Set feature code. USB_SETUP_RESERVED2 = 0x04, // Reserved code. USB_SETUP_SET_ADDRESS = 0x05, // Set address code. USB_SETUP_GET_DESCRIPTOR = 0x06, // Get descriptor code. USB_SETUP_SET_DESCRIPTOR = 0x07, // Set descriptor code. USB_SETUP_GET_CONFIGURATION = 0x08, // Get configuration code. USB_SETUP_SET_CONFIGURATION = 0x09, // Set configuration code. USB_SETUP_GET_INTERFACE = 0x0A, // Get interface code. USB_SETUP_SET_INTERFACE = 0x0B, // Set interface code. USB_SETUP_SYNC_FRAME = 0x0C, // Sync frame code. USB_SETUP_ANCHOR_LOAD = 0xA0 // Anchor load code. }; // Standard status responses. enum usb_setup_status_code { USB_STATUS_SELF_POWERED = 0x01, USB_STATUS_REMOTE_WAKEUP = 0x02 }; // Standard feature selectors. enum usb_setup_feature_selector { USB_FEATURE_STALL = 0x00, USB_FEATURE_REMOTE_WAKEUP = 0x01, USB_FEATRUE_TEST_MODE = 0x02 }; // Get descriptor codes. enum usb_setup_get_descriptor_code { USB_DESC_DEVICE = 0x01, // Device descriptor. USB_DESC_CONF = 0x02, // Configuration descriptor. USB_DESC_STRING = 0x03, // String descriptor. USB_DESC_INTERFACE = 0x04, // Interface descriptor. USB_DESC_ENDPOINT = 0x05, // End point descriptor. USB_DESC_DEVICE_QUAL = 0x06, // Device qualifier descriptor. USB_DESC_OTHER_SPEED_CONF = 0x07, // Other configuration descriptor. USB_DESC_INTERFACE_POWER = 0x08, // Interface power descriptor. USB_DESC_OTG = 0x09, // OTG descriptor. USB_DESC_DEBUG = 0x0A, // Debug descriptor. USB_DESC_INTERFACE_ASSOC = 0x0B, // Interface association descriptor. USB_DESC_HID = 0x21, // Get HID descriptor. USB_DESC_REPORT = 0x22 // Get report descriptor. }; // End point configuration (EP1INCFG/EP1OUTCFG/EP2/EP4/EP6/EP8). enum epcfg_bits { bmEP_VALID = bmBIT7, bmEP_DIR = bmBIT6, // Only for EP2-EP8! bmEP_TYPE = bmBIT5 | bmBIT4, bmEP_SIZE = bmBIT3, // Only for EP2-EP8! bmEP_BUF = bmBIT1 | bmBIT0 // Only for EP2-EP8! }; enum ep_valid_bits { bmEP_DISABLE = 0, bmEP_ENABLE = bmBIT7 }; // Only for EP2-EP8! enum ep_direction { bmEP_OUT = 0, bmEP_IN = bmBIT6 }; enum ep_type { bmEP_ISO = bmBIT4, // Only for EP2-EP8! bmEP_BULK = bmBIT5, // Default value. bmEP_INT = bmBIT4 | bmBIT5 }; // Only for EP2-EP8! enum ep_size { EP_512 = 0, EP_1024 = bmBIT3 // Except EP4/EP8. }; // Only for EP2-EP8! enum ep_buf { EP_QUAD = 0, EP_DOUBLE = bmBIT1, // Default value. EP_TRIPLE = bmBIT0 | bmBIT1 }; struct ep0_buf { BYTE *dat; WORD len; }; #define usb_disconnect() (USBCS |= bmDISCON) #define usb_connect() (USBCS &= ~bmDISCON) #define usb_is_high_speed() \ (USBCS & bmHSM) #define usp_ep_reset_toggle(ep) \ TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F)); \ TOGCTL |= bmRESETTOGGLE #define usb_ep0_stall() \ EP0CS |= bmEPSTALL #define usb_ep0_hsnack() \ EP0CS |= bmHSNAK #define usb_word_msb_get(word) \ (BYTE)(((WORD)(word) >> 8) & 0xFF) #define usb_word_lsb_get(word) \ (BYTE)((WORD)(word) & 0xFF) #define usb_word_swap(x) \ ((((WORD)((x) & 0x00FF)) << 8) | \ (((WORD)((x) & 0xFF00)) >> 8)) #define usb_dword_swap(x) \ ((((DWORD)((x) & 0x000000FFul)) << 24) | \ (((DWORD)((x) & 0x0000FF00ul)) << 8) | \ (((DWORD)((x) & 0x00FF0000ul)) >> 8) | \ (((DWORD)((x) & 0xFF000000ul)) >> 24)) void usb_init(void); void usb_task(void); #ifdef __cplusplus } #endif #endif // FX2_USB_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/irqs.h0000644000175100017510000000622715232633614023367 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_IRQS_H #define FX2_IRQS_H #ifdef __cplusplus extern "C" { #endif // Standard interrupt numbers. #define INT0_IRQ 0 // External interrupt 0. #define TMR0_IRQ 1 // Timer 0 interrupt. #define INT1_IRQ 2 // External interrupt 1. #define TMR1_IRQ 3 // Timer 1 interrupt. #define COM0_IRQ 4 // Serial port 0 transmit or receive interrupt. #define TMR2_IRQ 5 // Timer 2 interrupt. #define WKUP_IRQ 6 // Resume interrupt. #define COM1_IRQ 7 // Serial port 1 transmit or receive interrupt. #define USB_IRQ 8 // USB interrupt. #define I2C_IRQ 9 // I2C bus interrupt. #define INT4_IRQ 10 // External interrupt 4. #define INT5_IRQ 11 // External interrupt 5. #define INT6_IRQ 12 // External interrupt 6. #ifdef __cplusplus } #endif #endif // FX2_IRQS_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/hid.h0000644000175100017510000000633215232633614023152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_HID_H #define FX2_HID_H #include "usb.h" #ifdef __cplusplus extern "C" { #endif enum hid_constants { HID_CONFIG_NUMBER = 1, // Number of valid configuration. HID_IFACE_NUMBER = 0, // Number of valid interface. HID_ALT_IFACE_NUMBER = 0, // Number of valid alternate interface. HID_EP_IN = 0x81 // Active end point address. }; enum hid_gamepad_id { HID_REPORT_ID_GAMEPAD1 = 1, HID_REPORT_ID_GAMEPAD2 = 2 }; enum { HID_REPORTS_COUNT = 2, HID_REPORT_BITS_COUNT = 8 }; void hid_init(void); void hid_ep0_init(void); void hid_ep0_setup_task(void); const BYTE CODE *hid_ep0_std_desc_get(void); const BYTE CODE *hid_ep0_report_desc_get(WORD *length); void hid_ep1_task(void); void hid_ep1_report_update(BYTE index, BYTE buttons); #ifdef __cplusplus } #endif #endif // FX2_HID_H qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/README.md0000644000175100017510000000311015232633614023503 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different 8051 toolchains. It is designed for the target board based on Cypress FX2 cy7c68013a chip. It is possible to use the official development kit from the Cypress: * https://www.cypress.com/documentation/development-kitsboards/cy3684-ez-usb-fx2lp-development-kit but, a better solution is to buy the China's analogs or replacements, e.g. on Aliexpress. It implements a USB HID device that connects two 8-buttons NES (Dendy) gamepads to a PC. The gamepads are connected to the cy7c68013a chip as follows: 1. CLK - it is an output clock signal which generates by chip from the port A, pin 0 (PA0). This pin should be connected to the CLK inputs for both gamepads. 2. DATA1 - it is an input data signal which comes to chip on the the port A, pin 2 (PA2). This pin should be connected to the DATA output from the gamepad #1. 3. DATA2 - it is an input data signal which comes to chip on the the port A, pin 4 (PA4). This pin should be connected to the DATA output from the gamepad #2. 4. LATCH - it is an output clock signal which generates by chip from the port A, pin 6 (PA6). This pin should be connected to the LATCH inputs for both gamepads. Actual schematic and pinouts depends on an used gamepads (with 7, 9 or other pins connectors) and a development boards. Also, do not forget to connect the +3.3V and GND wires to the gamepads. Then it is possible to play 8-bit NES games using various PC simulators. The following toolchains are supported: * IAR Embedded Workbench * SDCC * KEIL C51 qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/nes-gamepads.qbs0000644000175100017510000001055215232633614025307 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("mcs51")) return false; return qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil") || qbs.toolchain.contains("sdcc") } name: "cy7c68013a-nes-gamepads" cpp.positionIndependentCode: false // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.commonCompilerFlags: ["-e"] cpp.staticLibraries: [ cpp.toolchainInstallPath + "/../lib/clib/cl-pli-nsid-1e16x01" ] cpp.driverLinkerFlags: [ "-D_IDATA_STACK_SIZE=0x40", "-D_PDATA_STACK_SIZE=0x80", "-D_XDATA_STACK_SIZE=0xEFF", "-D_XDATA_HEAP_SIZE=0xFF", "-D_EXTENDED_STACK_SIZE=0", "-D_EXTENDED_STACK_START=0" ] } Group { name: "IAR Linker Script" condition: qbs.toolchain.contains("iar") prefix: cpp.toolchainInstallPath + "/../config/devices/cypress/" fileTags: ["linkerscript"] files: ["lnk51ew_CY7C68013A.xcl"] } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.driverLinkerFlags: [ "RAMSIZE(256)", "CODE(0x80)", "XDATA(0x1000)" ] } // // SDCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("sdcc") cpp.driverLinkerFlags: [ "--code-loc", "0x80", "--xram-loc", "0x1000" ] } // // Common code. // files: [ "core.c", "core.h", "defs.h", "gpio.c", "gpio.h", "hid.c", "hid.h", "hiddesc.c", "hidep0.c", "hidep1.c", "irqs.h", "main.c", "regs.h", "usb.c", "usb.h", ] } qbs-src-3.3.1/examples/baremetal/cy7c68013a/nes-gamepads/gpio.h0000644000175100017510000000512015232633614023336 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FX2_GPIO_H #define FX2_GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init(void); void gpio_task(void); #ifdef __cplusplus } #endif #endif // FX2_GPIO_H qbs-src-3.3.1/examples/baremetal/at90can128olimex/0000755000175100017510000000000015232633614021165 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/0000755000175100017510000000000015232633614022757 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/redblink.qbs0000644000175100017510000001126515232633614025265 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("avr")) return false; return qbs.toolchain.contains("gcc") || qbs.toolchain.contains("iar") } name: "at90can128olimex-redblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // GCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("gcc") cpp.driverFlags: ["-mmcu=at90can128"] } // Note: We implicitly use the startup file and the linker script // which are already linked into the avr-gcc toolchain runtime. // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.driverFlags: ["--cpu=can128", "-ms"] cpp.entryPoint: "__program_start" cpp.driverLinkerFlags: [ "-D_..X_HEAP_SIZE=0", "-D_..X_NEAR_HEAP_SIZE=20", "-D_..X_CSTACK_SIZE=20", "-D_..X_RSTACK_SIZE=20", "-D_..X_FLASH_CODE_END=1FFFF", "-D_..X_FLASH_BASE=_..X_INTVEC_SIZE", "-D_..X_EXT_SRAM_BASE=_..X_SRAM_END", "-D_..X_EXT_ROM_BASE=_..X_SRAM_END", "-D_..X_EXT_NV_BASE=_..X_SRAM_END", "-D_..X_CSTACK_BASE=_..X_SRAM_BASE", "-D_..X_CSTACK_END=_..X_SRAM_END", "-D_..X_RSTACK_BASE=_..X_SRAM_BASE", "-D_..X_RSTACK_END=_..X_SRAM_END", "-h'1895'(CODE)0-(_..X_INTVEC_SIZE-1)", ] cpp.staticLibraries: [ // Explicitly link with the runtime dlib library (which contains // all required startup code and other stuff). cpp.toolchainInstallPath + "/../lib/dlib/dlAVR-3s-ec_mul-n.r90" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Linker Script" prefix: cpp.toolchainInstallPath + "/../src/template/" fileTags: ["linkerscript"] // Explicitly use the default linker scripts for current target. files: ["cfg3soim.xcl", "cfgcan128.xcl"] } } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/main.c0000644000175100017510000000530315232633614024050 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { gpio_init_red_led(); while (1) { gpio_toggle_red_led(); some_delay(100000u); } } qbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/gpio.c0000644000175100017510000000561715232633614024072 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #if defined(__GNUC__) #include #elif defined (__ICCAVR__) #include #else #error "Unsupported toolchain" #endif // LED pin number. #define GPIO_RED_LED_PIN_POS (4u) // LED port direction. #define GPIO_RED_LED_PORT_DIR (DDRE) // LED output port. #define GPIO_RED_LED_PORT_OUT (PORTE) void gpio_init_red_led(void) { GPIO_RED_LED_PORT_DIR = 0xFF; } void gpio_toggle_red_led(void) { GPIO_RED_LED_PORT_OUT ^= (1u << GPIO_RED_LED_PIN_POS); } qbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/README.md0000644000175100017510000000045015232633614024235 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different AVR toolchains. It is designed for the OLIMEX AVR-CAN target board (based on at90can128 chip) and simply flashes the red LED on the board. The following toolchains are supported: * GCC * IAR Embedded Workbench qbs-src-3.3.1/examples/baremetal/at90can128olimex/redblink/gpio.h0000644000175100017510000000512615232633614024072 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_red_led(void); void gpio_toggle_red_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/at90can128olimex/at90can128olimex.qbs0000644000175100017510000000502415232633614024605 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for Olimex AVR-CAN board" references: [ "redblink/redblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/baremetal.qbs0000644000175100017510000000554215232633614020726 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "BareMetal" references: [ "stm32f4discovery/stm32f4discovery.qbs", "at90can128olimex/at90can128olimex.qbs", "cc2540usbdongle/cc2540usbdongle.qbs", "stm8s103f3/stm8s103f3.qbs", "msp430f5529/msp430f5529.qbs", "cy7c68013a/cy7c68013a.qbs", "stm32f103/stm32f103.qbs", "pca10040/pca10040.qbs", "pca10001/pca10001.qbs", "esp8266/esp8266.qbs", ] } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/0000755000175100017510000000000015232633614021407 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f4discovery/stm32f4discovery.qbs0000644000175100017510000000503015232633614025246 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for stm32f4discovery board" references: [ "blueblink/blueblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/0000755000175100017510000000000015232633614023356 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/gcc/0000755000175100017510000000000015232633614024112 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/gcc/startup.s0000644000175100017510000002056115232633614026004 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ .syntax unified .cpu cortex-m4 .fpu softvfp .thumb // These symbols are exported from the linker script. .word _start_of_init_data_section .word _start_of_data_section .word _end_of_data_section .word _start_of_bss_section .word _end_of_bss_section .word _end_of_stack // Define the 'reset_handler' function, which is an entry point. .section .text.reset_handler .weak reset_handler .type reset_handler, %function reset_handler: // Set the stack pointer. ldr sp, =_end_of_stack // Copy the data segment initializers from flash to SRAM. movs r1, #0 b _loop_copy_data_init _copy_data_init: ldr r3, =_start_of_init_data_section ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 _loop_copy_data_init: ldr r0, =_start_of_data_section ldr r3, =_end_of_data_section adds r2, r0, r1 cmp r2, r3 bcc _copy_data_init ldr r2, =_start_of_bss_section b _loop_fill_zero_bss // Zero fill the bss segment. _fill_zero_bss: movs r3, #0 str r3, [r2], #4 _loop_fill_zero_bss: ldr r3, = _end_of_bss_section cmp r2, r3 bcc _fill_zero_bss // Call the static constructors. bl __libc_init_array // Call the application's entry point. bl main bx lr .size reset_handler, .-reset_handler // Define the empty vectors table. .section .isr_vector,"a",%progbits .type _vectors_table, %object .size _vectors_table, .-_vectors_table _vectors_table: // Generic interrupts offset. .word _end_of_stack // Initial stack pointer value. .word reset_handler // Reset. .word 0 // NMI. .word 0 // Hard fault. .word 0 // Memory management fault. .word 0 // Bus fault. .word 0 // Usage fault. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // SVC. .word 0 // Debug monitor. .word 0 // Reserved. .word 0 // PendSV. .word 0 // SysTick. // External interrupts offset. .word 0 // Window WatchDog. .word 0 // PVD through EXTI Line detection. .word 0 // Tamper and TimeStamps through the EXTI line. .word 0 // RTC Wakeup through the EXTI line. .word 0 // FLASH. .word 0 // RCC. .word 0 // EXTI Line0. .word 0 // EXTI Line1. .word 0 // EXTI Line2. .word 0 // EXTI Line3. .word 0 // EXTI Line4. .word 0 // DMA1 Stream 0. .word 0 // DMA1 Stream 1. .word 0 // DMA1 Stream 2. .word 0 // DMA1 Stream 3. .word 0 // DMA1 Stream 4. .word 0 // DMA1 Stream 5. .word 0 // DMA1 Stream 6. .word 0 // ADC1, ADC2 and ADC3s. .word 0 // CAN1 TX. .word 0 // CAN1 RX0. .word 0 // CAN1 RX1. .word 0 // CAN1 SCE. .word 0 // External Line[9:5]s. .word 0 // TIM1 Break and TIM9. .word 0 // TIM1 Update and TIM10. .word 0 // TIM1 Trigger and Commutation and TIM11. .word 0 // TIM1 Capture Compare. .word 0 // TIM2. .word 0 // TIM3. .word 0 // TIM4. .word 0 // I2C1 Event. .word 0 // I2C1 Error. .word 0 // I2C2 Event. .word 0 // I2C2 Error. .word 0 // SPI1. .word 0 // SPI2. .word 0 // USART1. .word 0 // USART2. .word 0 // USART3. .word 0 // External Line[15:10]s. .word 0 // RTC Alarm (A and B) through EXTI Line. .word 0 // USB OTG FS Wakeup through EXTI line. .word 0 // TIM8 Break and TIM12. .word 0 // TIM8 Update and TIM13. .word 0 // TIM8 Trigger and Commutation and TIM14. .word 0 // TIM8 Capture Compare. .word 0 // DMA1 Stream7. .word 0 // FSMC. .word 0 // SDIO. .word 0 // TIM5. .word 0 // SPI3. .word 0 // UART4. .word 0 // UART5. .word 0 // TIM6 and DAC1&2 underrun errors. .word 0 // TIM7. .word 0 // DMA2 Stream 0. .word 0 // DMA2 Stream 1. .word 0 // DMA2 Stream 2. .word 0 // DMA2 Stream 3. .word 0 // DMA2 Stream 4. .word 0 // Ethernet. .word 0 // Ethernet Wakeup through EXTI line. .word 0 // CAN2 TX. .word 0 // CAN2 RX0. .word 0 // CAN2 RX1. .word 0 // CAN2 SCE. .word 0 // USB OTG FS. .word 0 // DMA2 Stream 5. .word 0 // DMA2 Stream 6. .word 0 // DMA2 Stream 7. .word 0 // USART6. .word 0 // I2C3 event. .word 0 // I2C3 error. .word 0 // USB OTG HS End Point 1 Out. .word 0 // USB OTG HS End Point 1 In. .word 0 // USB OTG HS Wakeup through EXTI. .word 0 // USB OTG HS. .word 0 // DCMI. .word 0 // CRYP crypto. .word 0 // Hash and Rng. .word 0 // FPU. qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/gcc/flash.ld0000644000175100017510000001412515232633614025533 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /* Entry point (defined in assembled file). */ ENTRY(reset_handler) /* End of RAM, it is the user mode stack pointer address. */ _end_of_stack = 0x20020000; /* Generate a link error if heap and stack don't fit into RAM. */ _size_of_heap = 0x200; /* Required amount of heap. */ _size_of_stack = 0x400; /* Required amount of stack. */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K } SECTIONS { /* The vectors table goes into FLASH. */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code. */ . = ALIGN(4); } > FLASH /* The program code and other data goes into FLASH. */ .text : { . = ALIGN(4); *(.text) *(.text*) *(.glue_7) /* Glue arm to thumb code. */ *(.glue_7t) /* Glue thumb to arm code. */ *(.eh_frame) KEEP(*(.init)) KEEP(*(.fini)) . = ALIGN(4); _end_of_text_section = .; /* Export global symbol at end of code. */ } > FLASH /* Constant data goes into FLASH. */ .rodata : { . = ALIGN(4); *(.rodata) *(.rodata*) . = ALIGN(4); } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } > FLASH .preinit_array : { PROVIDE_HIDDEN(__preinit_array_start = .); KEEP(*(.preinit_array*)) PROVIDE_HIDDEN(__preinit_array_end = .); } > FLASH .init_array : { PROVIDE_HIDDEN(__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array*)) PROVIDE_HIDDEN(__init_array_end = .); } > FLASH .fini_array : { PROVIDE_HIDDEN(__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array*)) PROVIDE_HIDDEN(__fini_array_end = .); } > FLASH _start_of_init_data_section = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code. */ .data : { . = ALIGN(4); _start_of_data_section = .; /* Export global symbol at data start. */ *(.data) *(.data*) . = ALIGN(4); _end_of_data_section = .; /* Export global symbol at data end. */ } > RAM AT > FLASH _start_of_iccm_ram_section = LOADADDR(.ccmram); /* CCM-RAM section. */ .ccmram : { . = ALIGN(4); _start_of_ccmram_section = .; /* Export global symbol at ccmram start. */ *(.ccmram) *(.ccmram*) . = ALIGN(4); _end_of_ccmram_section = .; /* Export global symbol at ccmram end. */ } > CCMRAM AT > FLASH /* Uninitialized data section. */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion. */ _start_of_bss_section = .; /* Export global symbol at bss start. */ __bss_start__ = _start_of_bss_section; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _end_of_bss_section = .; /* Export global symbol at bss end. */ __bss_end__ = _end_of_bss_section; } > RAM /* Used to check that there is enough RAM left. */ ._user_heap_stack : { . = ALIGN(4); PROVIDE(end = .); PROVIDE(_end = .); . = . + _size_of_heap; . = . + _size_of_stack; . = ALIGN(4); } > RAM /* Remove information from the standard libraries. */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/main.c0000644000175100017510000000530515232633614024451 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { gpio_init_blue_led(); while (1) { gpio_toggle_blue_led(); some_delay(100000u); } } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/system.h0000644000175100017510000001050715232633614025056 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #include #ifdef __cplusplus extern "C" { #endif #define __IO volatile // General purpose input/output registers map. struct gpio_regs_map { __IO uint32_t MODER; __IO uint32_t OTYPER; __IO uint32_t OSPEEDR; __IO uint32_t PUPDR; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t LCKR; __IO uint32_t AFR[2u]; }; // Reset and clock control registers map. struct rcc_regs_map { __IO uint32_t CR; __IO uint32_t PLLCFGR; __IO uint32_t CFGR; __IO uint32_t CIR; __IO uint32_t AHB1RSTR; __IO uint32_t AHB2RSTR; __IO uint32_t AHB3RSTR; uint32_t RESERVED0; __IO uint32_t APB1RSTR; __IO uint32_t APB2RSTR; uint32_t RESERVED1[2u]; __IO uint32_t AHB1ENR; __IO uint32_t AHB2ENR; __IO uint32_t AHB3ENR; uint32_t RESERVED2; __IO uint32_t APB1ENR; __IO uint32_t APB2ENR; uint32_t RESERVED3[2u]; __IO uint32_t AHB1LPENR; __IO uint32_t AHB2LPENR; __IO uint32_t AHB3LPENR; uint32_t RESERVED4; __IO uint32_t APB1LPENR; __IO uint32_t APB2LPENR; uint32_t RESERVED5[2u]; __IO uint32_t BDCR; __IO uint32_t CSR; uint32_t RESERVED6[2u]; __IO uint32_t SSCGR; __IO uint32_t PLLI2SCFGR; }; #define PERIPH_ADDRESS (0x40000000u) #define APB2PERIPH_ADDRESS (PERIPH_ADDRESS + 0x00010000u) #define AHB1PERIPH_ADDRESS (PERIPH_ADDRESS + 0x00020000u) // APB2 peripherals. #define SYSCFG_REGS_ADDRESS (APB2PERIPH_ADDRESS + 0x3800u) #define EXTI_REGS_ADDRESS (APB2PERIPH_ADDRESS + 0x3C00u) // AHB1 peripherals. #define GPIOD_REGS_ADDRESS (AHB1PERIPH_ADDRESS + 0x0C00u) #define RCC_REGS_ADDRESS (AHB1PERIPH_ADDRESS + 0x3800u) #define GPIOD_REGS_MAP ((struct gpio_regs_map *)GPIOD_REGS_ADDRESS) #define RCC_REGS_MAP ((struct rcc_regs_map *)RCC_REGS_ADDRESS) #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/gpio.c0000644000175100017510000000637315232633614024471 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #define GPIO_BLUE_LED_PIN_POS (15u) #define GPIO_BLUE_LED_PIN (1u << GPIO_BLUE_LED_PIN_POS) // Output push pull mode. #define GPIO_MODE_OUTPUT_PP (0x00000001u) // Bit definition for RCC_AHB1ENR register. #define RCC_AHB1ENR_GPIODEN (0x00000008u) // Bits definition for GPIO_MODER register. #define GPIO_MODER_MODE0 (0x00000003u) void gpio_init_blue_led(void) { // Enable RCC clock on GPIOD port. RCC_REGS_MAP->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Configure GPIO pin #15 as an output. uint32_t value = GPIOD_REGS_MAP->MODER; value &= ~(GPIO_MODER_MODE0 << (GPIO_BLUE_LED_PIN_POS * 2u)); value |= (GPIO_MODE_OUTPUT_PP << (GPIO_BLUE_LED_PIN_POS * 2u)); GPIOD_REGS_MAP->MODER = value; } void gpio_toggle_blue_led(void) { GPIOD_REGS_MAP->ODR ^= GPIO_BLUE_LED_PIN; } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/iar/0000755000175100017510000000000015232633614024131 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/iar/startup.s0000644000175100017510000001621015232633614026017 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MODULE ?cstartup SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start PUBLIC _vectors_table DATA _vectors_table ;; Generic interrupts offset. DCD sfe(CSTACK) ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Memory management fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Debug monitor. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Window WatchDog. DCD 0 ; PVD through EXTI Line detection. DCD 0 ; Tamper and TimeStamps through the EXTI line. DCD 0 ; RTC Wakeup through the EXTI line. DCD 0 ; FLASH. DCD 0 ; RCC. DCD 0 ; EXTI Line0. DCD 0 ; EXTI Line1. DCD 0 ; EXTI Line2. DCD 0 ; EXTI Line3. DCD 0 ; EXTI Line4. DCD 0 ; DMA1 Stream 0. DCD 0 ; DMA1 Stream 1. DCD 0 ; DMA1 Stream 2. DCD 0 ; DMA1 Stream 3. DCD 0 ; DMA1 Stream 4. DCD 0 ; DMA1 Stream 5. DCD 0 ; DMA1 Stream 6. DCD 0 ; ADC1, ADC2 and ADC3s. DCD 0 ; CAN1 TX. DCD 0 ; CAN1 RX0. DCD 0 ; CAN1 RX1. DCD 0 ; CAN1 SCE. DCD 0 ; External Line[9:5]s. DCD 0 ; TIM1 Break and TIM9. DCD 0 ; TIM1 Update and TIM10. DCD 0 ; TIM1 Trigger and Commutation and TIM11. DCD 0 ; TIM1 Capture Compare. DCD 0 ; TIM2. DCD 0 ; TIM3. DCD 0 ; TIM4. DCD 0 ; I2C1 Event. DCD 0 ; I2C1 Error. DCD 0 ; I2C2 Event. DCD 0 ; I2C2 Error. DCD 0 ; SPI1. DCD 0 ; SPI2. DCD 0 ; USART1. DCD 0 ; USART2. DCD 0 ; USART3. DCD 0 ; External Line[15:10]s. DCD 0 ; RTC Alarm (A and B) through EXTI Line. DCD 0 ; USB OTG FS Wakeup through EXTI line. DCD 0 ; TIM8 Break and TIM12. DCD 0 ; TIM8 Update and TIM13. DCD 0 ; TIM8 Trigger and Commutation and TIM14. DCD 0 ; TIM8 Capture Compare. DCD 0 ; DMA1 Stream7. DCD 0 ; FSMC. DCD 0 ; SDIO. DCD 0 ; TIM5. DCD 0 ; SPI3. DCD 0 ; UART4. DCD 0 ; UART5. DCD 0 ; TIM6 and DAC1&2 underrun errors. DCD 0 ; TIM7. DCD 0 ; DMA2 Stream 0. DCD 0 ; DMA2 Stream 1. DCD 0 ; DMA2 Stream 2. DCD 0 ; DMA2 Stream 3. DCD 0 ; DMA2 Stream 4. DCD 0 ; Ethernet. DCD 0 ; Ethernet Wakeup through EXTI line. DCD 0 ; CAN2 TX. DCD 0 ; CAN2 RX0. DCD 0 ; CAN2 RX1. DCD 0 ; CAN2 SCE. DCD 0 ; USB OTG FS. DCD 0 ; DMA2 Stream 5. DCD 0 ; DMA2 Stream 6. DCD 0 ; DMA2 Stream 7. DCD 0 ; USART6. DCD 0 ; I2C3 event. DCD 0 ; I2C3 error. DCD 0 ; USB OTG HS End Point 1 Out. DCD 0 ; USB OTG HS End Point 1 In. DCD 0 ; USB OTG HS Wakeup through EXTI. DCD 0 ; USB OTG HS. DCD 0 ; DCMI. DCD 0 ; CRYP crypto. DCD 0 ; Hash and RNG. DCD 0 ; FPU. ;; Reset handler. THUMB PUBWEAK reset_handler SECTION .text:CODE:REORDER:NOROOT(2) reset_handler BLX R0 LDR R0, =__iar_program_start BX R0 END qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/iar/flash.icf0000644000175100017510000000702615232633614025716 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ define symbol _start_of_intvec_section = 0x08000000; define symbol _start_of_ram_section = 0x20000000; define symbol _end_of_ram_section = 0x2001FFFF; define symbol _start_of_ccmram_section = 0x10000000; define symbol _end_of_ccmram_section = 0x1000FFFF; define symbol _start_of_flash_section = 0x08000000; define symbol _end_of_flash_section = 0x080FFFFF; define symbol _min_stack_size = 0x400; define symbol _min_heap_size = 0x200; define memory mem with size = 4G; define region flash_section = mem:[from _start_of_flash_section to _end_of_flash_section]; define region ram_section = mem:[from _start_of_ram_section to _end_of_ram_section]; define region ccmram_section = mem:[from _start_of_ccmram_section to _end_of_ccmram_section]; define block CSTACK with alignment = 8, size = _min_stack_size { }; define block HEAP with alignment = 8, size = _min_heap_size { }; initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:_start_of_intvec_section { readonly section .intvec }; place in flash_section { readonly }; place in ram_section { readwrite, block CSTACK, block HEAP }; qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs0000644000175100017510000001216315232633614026037 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.startsWith("arm")) return false; return (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil")) && !qbs.targetOS.includes("darwin") } name: "stm32f4discovery-blueblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // GCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("gcc") cpp.assemblerFlags: [ "-mcpu=cortex-m4", "-mfloat-abi=hard", "-mfpu=fpv4-sp-d16", ] cpp.driverFlags: [ "-mcpu=cortex-m4", "-mfloat-abi=hard", "-mfpu=fpv4-sp-d16", "-specs=nosys.specs" ] } Group { condition: qbs.toolchain.contains("gcc") name: "GCC" prefix: "gcc/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.ld"] } } // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.assemblerFlags: [ "--cpu", "cortex-m4", "--fpu", "vfpv4_sp" ] cpp.driverFlags: [ "--cpu", "cortex-m4", "--fpu", "vfpv4_sp" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.icf"] } } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.assemblerFlags: [ "--cpu", "cortex-m4.fp" ] cpp.driverFlags: [ "--cpu", "cortex-m4.fp" ] } Group { condition: qbs.toolchain.contains("keil") name: "KEIL" prefix: "keil/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.sct"] } } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/README.md0000644000175100017510000000055515232633614024642 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different ARM toolchains. It is designed for the stm32f4discovery evaluation kit (based on stm32f407vg MCU) and simply flashes the blue LED on the board. The following toolchains are supported: * GNU Arm Embedded Toolchain * IAR Embedded Workbench * KEIL Microcontroller Development Kit qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/keil/0000755000175100017510000000000015232633614024302 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/keil/startup.s0000644000175100017510000001665615232633614026206 0ustar runnerrunner;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Copyright (C) 2019 Denis Shienkov ;; Contact: https://www.qt.io/licensing/ ;; ;; This file is part of the examples of Qbs. ;; ;; $QT_BEGIN_LICENSE:BSD$ ;; Commercial License Usage ;; Licensees holding valid commercial Qt licenses may use this file in ;; accordance with the commercial license agreement provided with the ;; Software or, alternatively, in accordance with the terms contained in ;; a written agreement between you and The Qt Company. For licensing terms ;; and conditions see https://www.qt.io/terms-conditions. For further ;; information use the contact form at https://www.qt.io/contact-us. ;; ;; BSD License Usage ;; Alternatively, you may use this file under the terms of the BSD license ;; as follows: ;; ;; "Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions are ;; met: ;; * Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; * Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in ;; the documentation and/or other materials provided with the ;; distribution. ;; * Neither the name of The Qt Company Ltd nor the names of its ;; contributors may be used to endorse or promote products derived ;; from this software without specific prior written permission. ;; ;; ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ;; ;; $QT_END_LICENSE$ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _size_of_stack EQU 0x400 _size_of_heap EQU 0x200 ;; Stack configuration. AREA STACK, NOINIT, READWRITE, ALIGN=3 _start_of_stack SPACE _size_of_stack _end_of_stack ;; Heap configuration. AREA HEAP, NOINIT, READWRITE, ALIGN=3 _start_of_heap SPACE _size_of_heap _end_of_heap PRESERVE8 THUMB ;; Define the empty vectors table. AREA RESET, DATA, READONLY _vectors_table ;; Generic interrupts offset. DCD _end_of_stack ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Memory management fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Debug monitor. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Window WatchDog. DCD 0 ; PVD through EXTI Line detection. DCD 0 ; Tamper and TimeStamps through the EXTI line. DCD 0 ; RTC Wakeup through the EXTI line. DCD 0 ; FLASH. DCD 0 ; RCC. DCD 0 ; EXTI Line0. DCD 0 ; EXTI Line1. DCD 0 ; EXTI Line2. DCD 0 ; EXTI Line3. DCD 0 ; EXTI Line4. DCD 0 ; DMA1 Stream 0. DCD 0 ; DMA1 Stream 1. DCD 0 ; DMA1 Stream 2. DCD 0 ; DMA1 Stream 3. DCD 0 ; DMA1 Stream 4. DCD 0 ; DMA1 Stream 5. DCD 0 ; DMA1 Stream 6. DCD 0 ; ADC1, ADC2 and ADC3s. DCD 0 ; CAN1 TX. DCD 0 ; CAN1 RX0. DCD 0 ; CAN1 RX1. DCD 0 ; CAN1 SCE. DCD 0 ; External Line[9:5]s. DCD 0 ; TIM1 Break and TIM9. DCD 0 ; TIM1 Update and TIM10. DCD 0 ; TIM1 Trigger and Commutation and TIM11. DCD 0 ; TIM1 Capture Compare. DCD 0 ; TIM2. DCD 0 ; TIM3. DCD 0 ; TIM4. DCD 0 ; I2C1 Event. DCD 0 ; I2C1 Error. DCD 0 ; I2C2 Event. DCD 0 ; I2C2 Error. DCD 0 ; SPI1. DCD 0 ; SPI2. DCD 0 ; USART1. DCD 0 ; USART2. DCD 0 ; USART3. DCD 0 ; External Line[15:10]s. DCD 0 ; RTC Alarm (A and B) through EXTI Line. DCD 0 ; USB OTG FS Wakeup through EXTI line. DCD 0 ; TIM8 Break and TIM12. DCD 0 ; TIM8 Update and TIM13. DCD 0 ; TIM8 Trigger and Commutation and TIM14. DCD 0 ; TIM8 Capture Compare. DCD 0 ; DMA1 Stream7. DCD 0 ; FMC. DCD 0 ; SDIO. DCD 0 ; TIM5. DCD 0 ; SPI3. DCD 0 ; UART4. DCD 0 ; UART5. DCD 0 ; TIM6 and DAC1&2 underrun errors. DCD 0 ; TIM7. DCD 0 ; DMA2 Stream 0. DCD 0 ; DMA2 Stream 1. DCD 0 ; DMA2 Stream 2. DCD 0 ; DMA2 Stream 3. DCD 0 ; DMA2 Stream 4. DCD 0 ; Ethernet. DCD 0 ; Ethernet Wakeup through EXTI line. DCD 0 ; CAN2 TX. DCD 0 ; CAN2 RX0. DCD 0 ; CAN2 RX1. DCD 0 ; CAN2 SCE. DCD 0 ; USB OTG FS. DCD 0 ; DMA2 Stream 5. DCD 0 ; DMA2 Stream 6. DCD 0 ; DMA2 Stream 7. DCD 0 ; USART6. DCD 0 ; I2C3 event. DCD 0 ; I2C3 error. DCD 0 ; USB OTG HS End Point 1 Out. DCD 0 ; USB OTG HS End Point 1 In. DCD 0 ; USB OTG HS Wakeup through EXTI. DCD 0 ; USB OTG HS. DCD 0 ; DCMI. DCD 0 ; Reserved. DCD 0 ; Hash and Rng. DCD 0 ; FPU. _end_of_vectors_table _size_of_vectors_table EQU _end_of_vectors_table - _vectors_table AREA |.text|, CODE, READONLY ;; Reset handler. reset_handler PROC EXPORT reset_handler [WEAK] IMPORT main LDR R0, =main BX R0 ENDP ALIGN END qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/keil/flash.sct0000644000175100017510000000532215232633614026114 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ;; Load region size_region. LR_IROM1 0x08000000 0x00100000 { ;; Load address = execution address. ER_IROM1 0x08000000 0x00100000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } ; RW data. RW_IRAM1 0x20000000 0x00020000 { .ANY (+RW +ZI) } } qbs-src-3.3.1/examples/baremetal/stm32f4discovery/blueblink/gpio.h0000644000175100017510000000513015232633614024464 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_blue_led(void); void gpio_toggle_blue_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/pca10040/0000755000175100017510000000000015232633614017405 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10040/pca10040.qbs0000644000175100017510000000502215232633614021243 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for pca10040 board" references: [ "greenblink/greenblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/0000755000175100017510000000000015232633614021525 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10040/greenblink/gcc/0000755000175100017510000000000015232633614022261 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10040/greenblink/gcc/startup.s0000644000175100017510000002226515232633614024156 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ .syntax unified .arch armv7e-m .thumb // Define the stack. .section .stack .align 3 .equ _size_of_stack, 8192 .globl _end_of_stack .globl _stack_limit _stack_limit: .space _size_of_stack .size _stack_limit, . - _stack_limit _end_of_stack: .size _end_of_stack, . - _end_of_stack // Define the heap. .section .heap .align 3 .equ _size_of_heap, 8192 .globl _end_of_heap .globl _heap_limit _end_of_heap: .space _size_of_heap .size _end_of_heap, . - _end_of_heap _heap_limit: .size _heap_limit, . - _heap_limit // Define the empty vectors table. .section .isr_vector, "ax" .align 2 .globl _vectors_table _vectors_table: // Generic interrupts offset. .word _end_of_stack // Initial stack pointer value. .word reset_handler // Reset. .word 0 // NMI. .word 0 // Hard fault. .word 0 // Memory management fault. .word 0 // Bus fault. .word 0 // Usage fault. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // SVC. .word 0 // Debug monitor. .word 0 // Reserved. .word 0 // PendSV. .word 0 // SysTick. // External interrupts offset. .word 0 // POWER CLOCK. .word 0 // RADIO. .word 0 // UARTE0/UART0 .word 0 // SPIM0/SPIS0/TWIM0/TWIS0/SPI0/TWI0. .word 0 // SPIM1/SPIS1/TWIM1/TWIS1/SPI1/TWI1. .word 0 // NFCT. .word 0 // GPIOTE. .word 0 // SAADC. .word 0 // TIMER0. .word 0 // TIMER1. .word 0 // TIMER2. .word 0 // RTC0. .word 0 // TEMP. .word 0 // RNG. .word 0 // ECB. .word 0 // CCM_AAR. .word 0 // WDT. .word 0 // RTC1. .word 0 // QDEC. .word 0 // COMP_LPCOMP. .word 0 // SWI0_EGU0. .word 0 // SWI1_EGU1. .word 0 // SWI2_EGU2. .word 0 // SWI3_EGU3. .word 0 // SWI4_EGU4. .word 0 // SWI5_EGU5. .word 0 // TIMER3. .word 0 // TIMER4. .word 0 // PWM0. .word 0 // PDM. .word 0 // Reserved. .word 0 // Reserved. .word 0 // MWU. .word 0 // PWM1. .word 0 // PWM2. .word 0 // SPIM2/SPIS2/SPI2. .word 0 // RTC2. .word 0 // I2S. .word 0 // FPU. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .size _vectors_table, . - _vectors_table // Define the 'reset_handler' function, which is an entry point. .text .thumb .thumb_func .align 1 .globl reset_handler .type reset_handler, %function reset_handler: // Loop to copy data from read only memory to RAM. ldr r1, =_end_of_code_section ldr r2, =_start_of_data_section ldr r3, =__bss_start__ subs r3, r3, r2 ble _copy_data_init_done _copy_data_init: subs r3, r3, #4 ldr r0, [r1,r3] str r0, [r2,r3] bgt _copy_data_init _copy_data_init_done: // Zero fill the bss segment. ldr r1, =__bss_start__ ldr r2, =__bss_end__ movs r0, 0 subs r2, r2, r1 ble _loop_fill_zero_bss_done _loop_fill_zero_bss: subs r2, r2, #4 str r0, [r1, r2] bgt _loop_fill_zero_bss _loop_fill_zero_bss_done: // Call the application's entry point. bl main bx lr .size reset_handler, . - reset_handler qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/gcc/flash.ld0000644000175100017510000001162615232633614023705 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x10000 } SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text*) KEEP(*(.init)) KEEP(*(.fini)) /* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) /* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) *(.rodata*) *(.eh_frame*) . = ALIGN(4); } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } > FLASH _start_of_exidx_section = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(4); } > FLASH _end_of_exidx_section = .; _end_of_code_section = .; .data : AT (_end_of_code_section) { _start_of_data_section = .; *(vtable) *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN(__preinit_array_start = .); *(.preinit_array) PROVIDE_HIDDEN(__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN(__init_array_start = .); *(SORT(.init_array.*)) *(.init_array) PROVIDE_HIDDEN(__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN(__fini_array_start = .); *(SORT(.fini_array.*)) *(.fini_array) PROVIDE_HIDDEN(__fini_array_end = .); *(.jcr) . = ALIGN(4); /* All data end */ _end_of_data_section = .; } > RAM .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; } > RAM .heap (COPY): { __end__ = .; end = __end__; *(.heap*) _heap_limit = .; } > RAM .stack_dummy (COPY): { *(.stack*) } > RAM /* Set stack top to end of RAM, and stack limit move down by size of stack_dummy section. */ _end_of_stack = ORIGIN(RAM) + LENGTH(RAM); _stack_limit = _end_of_stack - SIZEOF(.stack_dummy); PROVIDE(__stack = _end_of_stack); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(_stack_limit >= _heap_limit, "region RAM overflowed with stack") } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/main.c0000644000175100017510000000531015232633614022614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { gpio_init_green_led(); while (1) { gpio_toggle_green_led(); some_delay(1000000u); } } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/system.h0000644000175100017510000000604115232633614023223 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #include #ifdef __cplusplus extern "C" { #endif #define __IO volatile struct gpio_regs_map { uint32_t RESERVED0[321u]; __IO uint32_t OUT; __IO uint32_t OUTSET; __IO uint32_t OUTCLR; __IO uint32_t IN; __IO uint32_t DIR; __IO uint32_t DIRSET; __IO uint32_t DIRCLR; __IO uint32_t LATCH; __IO uint32_t DETECTMODE; uint32_t RESERVED1[118u]; __IO uint32_t PIN_CNF[32u]; }; #define GPIO_REGS_ADDRESS (0x50000000u) #define GPIOD_REGS_MAP ((struct gpio_regs_map *)GPIO_REGS_ADDRESS) #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/greenblink.qbs0000644000175100017510000001216215232633614024356 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.startsWith("arm")) return false; return (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil")) && !qbs.targetOS.includes("darwin") } name: "pca10040-greenblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // GCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("gcc") cpp.assemblerFlags: [ "-mcpu=cortex-m4", "-mfloat-abi=hard", "-mfpu=fpv4-sp-d16", ] cpp.driverFlags: [ "-mcpu=cortex-m4", "-mfloat-abi=hard", "-mfpu=fpv4-sp-d16", "-specs=nosys.specs" ] } Group { condition: qbs.toolchain.contains("gcc") name: "GCC" prefix: "gcc/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.ld"] } } // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.assemblerFlags: [ "--cpu", "cortex-m4", "--fpu", "vfpv4_sp" ] cpp.driverFlags: [ "--cpu", "cortex-m4", "--fpu", "vfpv4_sp" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.icf"] } } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.assemblerFlags: [ "--cpu", "cortex-m4.fp.sp" ] cpp.driverFlags: [ "--cpu", "cortex-m4.fp.sp" ] } Group { condition: qbs.toolchain.contains("keil") name: "KEIL" prefix: "keil/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.sct"] } } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/gpio.c0000644000175100017510000001063015232633614022627 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #define GPIO_GREEN_LED_PIN_POS (17u) #define GPIO_GREEN_LED_PIN (1u << GPIO_GREEN_LED_PIN_POS) // Pin direction attributes. #define GPIO_PIN_CNF_DIR_POS (0u) // Position of DIR field. #define GPIO_PIN_CNF_DIR_OUT (1u) // Configure pin as an output pin. #define GPIO_PIN_CNF_DIR_MSK (GPIO_PIN_CNF_DIR_OUT << GPIO_PIN_CNF_DIR_POS) // Pin input buffer attributes. #define GPIO_PIN_CNF_INPUT_POS (1u) // Position of INPUT field. #define GPIO_PIN_CNF_INPUT_OFF (1u) // Disconnect input buffer. #define GPIO_PIN_CNF_INPUT_MSK (GPIO_PIN_CNF_INPUT_OFF << GPIO_PIN_CNF_INPUT_POS) // Pin pull attributes. #define GPIO_PIN_CNF_PULL_POS (2u) // Position of PULL field. #define GPIO_PIN_CNF_PULL_OFF (0u) // No pull. #define GPIO_PIN_CNF_PULL_MSK (GPIO_PIN_CNF_PULL_OFF << GPIO_PIN_CNF_PULL_POS) // Pin drive attributes. #define GPIO_PIN_CNF_DRIVE_POS (8u) // Position of DRIVE field. #define GPIO_PIN_CNF_DRIVE_S0S1 (0u) // Standard '0', standard '1'. #define GPIO_PIN_CNF_DRIVE_MSK (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_POS) // Pin sense attributes. #define GPIO_PIN_CNF_SENSE_POS (16u) // Position of SENSE field. #define GPIO_PIN_CNF_SENSE_OFF (0u) // Disabled. #define GPIO_PIN_CNF_SENSE_MSK (GPIO_PIN_CNF_SENSE_OFF << GPIO_PIN_CNF_SENSE_POS) void gpio_init_green_led(void) { GPIOD_REGS_MAP->PIN_CNF[GPIO_GREEN_LED_PIN_POS] = (GPIO_PIN_CNF_DIR_MSK | GPIO_PIN_CNF_INPUT_MSK | GPIO_PIN_CNF_PULL_MSK | GPIO_PIN_CNF_DRIVE_MSK | GPIO_PIN_CNF_SENSE_MSK); } void gpio_toggle_green_led(void) { const uint32_t gpio_state = GPIOD_REGS_MAP->OUT; GPIOD_REGS_MAP->OUTSET = (GPIO_GREEN_LED_PIN & ~gpio_state); GPIOD_REGS_MAP->OUTCLR = (GPIO_GREEN_LED_PIN & gpio_state); } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/iar/0000755000175100017510000000000015232633614022300 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10040/greenblink/iar/startup.s0000644000175100017510000001753315232633614024177 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MODULE ?cstartup SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start PUBLIC _vectors_table DATA _vectors_table ;; Generic interrupts offset. DCD sfe(CSTACK) ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Memory management fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; POWER CLOCK. DCD 0 ; RADIO. DCD 0 ; UARTE0/UART0 DCD 0 ; SPIM0/SPIS0/TWIM0/TWIS0/SPI0/TWI0. DCD 0 ; SPIM1/SPIS1/TWIM1/TWIS1/SPI1/TWI1. DCD 0 ; NFCT. DCD 0 ; GPIOTE. DCD 0 ; SAADC. DCD 0 ; TIMER0. DCD 0 ; TIMER1. DCD 0 ; TIMER2. DCD 0 ; RTC0. DCD 0 ; TEMP. DCD 0 ; RNG. DCD 0 ; ECB. DCD 0 ; CCM_AAR. DCD 0 ; WDT. DCD 0 ; RTC1. DCD 0 ; QDEC. DCD 0 ; COMP_LPCOMP. DCD 0 ; SWI0_EGU0. DCD 0 ; SWI1_EGU1. DCD 0 ; SWI2_EGU2. DCD 0 ; SWI3_EGU3. DCD 0 ; SWI4_EGU4. DCD 0 ; SWI5_EGU5. DCD 0 ; TIMER3. DCD 0 ; TIMER4. DCD 0 ; PWM0. DCD 0 ; PDM. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; MWU. DCD 0 ; PWM1. DCD 0 ; PWM2. DCD 0 ; SPIM2/SPIS2/SPI2. DCD 0 ; RTC2. DCD 0 ; I2S. DCD 0 ; FPU. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. ;; Reset handler. THUMB PUBWEAK reset_handler SECTION .text:CODE:REORDER:NOROOT(2) reset_handler BLX R0 LDR R0, =__iar_program_start BX R0 END qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/iar/flash.icf0000644000175100017510000001174215232633614024065 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ define symbol _start_of_intvec_section = 0x00000000; define symbol _start_of_irom1_section = 0x00000000; define symbol _end_of_irom1_section = 0x0007FFFF; define symbol _start_of_irom2_section = 0x0; define symbol _end_of_irom2_section = 0x0; define symbol _start_of_erom1_section = 0x0; define symbol _end_of_erom1_section = 0x0; define symbol _start_of_erom2_section = 0x0; define symbol _end_of_erom2_section = 0x0; define symbol _start_of_erom3_section = 0x0; define symbol _end_of_erom3_section = 0x0; define symbol _start_of_iram1_section = 0x20000000; define symbol _end_of_iram1_section = 0x2000FFFF; define symbol _start_of_iram2_section = 0x0; define symbol _end_of_iram2_section = 0x0; define symbol _start_of_eram1_section = 0x0; define symbol _end_of_eram1_section = 0x0; define symbol _start_of_eram2_section = 0x0; define symbol _end_of_eram2_section = 0x0; define symbol _start_of_eram3_section = 0x0; define symbol _end_of_eram3_section = 0x0; define symbol _min_stack_size = 0x2000; define symbol _min_proc_stack_size = 0x0; define symbol _min_heap_size = 0x2000; define memory mem with size = 4G; define region irom_section = mem:[from _start_of_irom1_section to _end_of_irom1_section] | mem:[from _start_of_irom2_section to _end_of_irom2_section]; define region erom_section = mem:[from _start_of_erom1_section to _end_of_erom1_section] | mem:[from _start_of_erom2_section to _end_of_erom2_section] | mem:[from _start_of_erom3_section to _end_of_erom3_section]; define region iram_section = mem:[from _start_of_iram1_section to _end_of_iram1_section] | mem:[from _start_of_iram2_section to _end_of_iram2_section]; define region eram_section = mem:[from _start_of_eram1_section to _end_of_eram1_section] | mem:[from _start_of_eram2_section to _end_of_eram2_section] | mem:[from _start_of_eram3_section to _end_of_eram3_section]; define block CSTACK with alignment = 8, size = _min_stack_size { }; define block PROC_STACK with alignment = 8, size = _min_proc_stack_size { }; define block HEAP with alignment = 8, size = _min_heap_size { }; initialize by copy { readwrite }; place at address mem:_start_of_intvec_section { readonly section .intvec }; place in irom_section { readonly }; place in erom_section { readonly section application_specific_ro }; place in iram_section { readwrite, block CSTACK, block HEAP, block PROC_STACK }; place in eram_section { readwrite section application_specific_rw }; qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/README.md0000644000175100017510000000055215232633614023006 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different ARM toolchains. It is designed for the Nordic pca10040 evaluation kit (based on nRF52832 MCU) and simply flashes the green LED on the board. The following toolchains are supported: * GNU Arm Embedded Toolchain * IAR Embedded Workbench * KEIL Microcontroller Development Kit qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/keil/0000755000175100017510000000000015232633614022451 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10040/greenblink/keil/startup.s0000644000175100017510000002021315232633614024335 0ustar runnerrunner;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Copyright (C) 2020 Denis Shienkov ;; Contact: https://www.qt.io/licensing/ ;; ;; This file is part of the examples of Qbs. ;; ;; $QT_BEGIN_LICENSE:BSD$ ;; Commercial License Usage ;; Licensees holding valid commercial Qt licenses may use this file in ;; accordance with the commercial license agreement provided with the ;; Software or, alternatively, in accordance with the terms contained in ;; a written agreement between you and The Qt Company. For licensing terms ;; and conditions see https://www.qt.io/terms-conditions. For further ;; information use the contact form at https://www.qt.io/contact-us. ;; ;; BSD License Usage ;; Alternatively, you may use this file under the terms of the BSD license ;; as follows: ;; ;; "Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions are ;; met: ;; * Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; * Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in ;; the documentation and/or other materials provided with the ;; distribution. ;; * Neither the name of The Qt Company Ltd nor the names of its ;; contributors may be used to endorse or promote products derived ;; from this software without specific prior written permission. ;; ;; ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ;; ;; $QT_END_LICENSE$ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _size_of_stack EQU 0x2000 _size_of_heap EQU 0x2000 ;; Stack configuration. AREA STACK, NOINIT, READWRITE, ALIGN=3 _start_of_stack SPACE _size_of_stack _end_of_stack ;; Heap configuration. AREA HEAP, NOINIT, READWRITE, ALIGN=3 _start_of_heap SPACE _size_of_heap _end_of_heap PRESERVE8 THUMB ;; Define the empty vectors table. AREA RESET, DATA, READONLY _vectors_table ;; Generic interrupts offset. DCD _end_of_stack ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Memory management fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Debug monitor. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Power clock. DCD 0 ; Radio. DCD 0 ; UARTE0/UART0. DCD 0 ; SPIM0/SPIS0/TWIM0/TWIS0/SPI0/TWI0. DCD 0 ; SPIM1/SPIS1/TWIM1/TWIS1/SPI1/TWI1. DCD 0 ; NFCT. DCD 0 ; GPIOTE. DCD 0 ; SAADC. DCD 0 ; TIMER0. DCD 0 ; TIMER1. DCD 0 ; TIMER2. DCD 0 ; RTC0. DCD 0 ; TEMP. DCD 0 ; RNG. DCD 0 ; ECB. DCD 0 ; CCM/AAR. DCD 0 ; WDT. DCD 0 ; RTC1. DCD 0 ; QDEC. DCD 0 ; COMP/LPCOMP. DCD 0 ; SWI0/EGU0. DCD 0 ; SWI1/EGU1. DCD 0 ; SWI2/EGU2. DCD 0 ; SWI3/EGU3. DCD 0 ; SWI4/EGU4. DCD 0 ; SWI5/EGU5. DCD 0 ; TIMER3. DCD 0 ; TIMER4. DCD 0 ; PWM0. DCD 0 ; PDM. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; MWU. DCD 0 ; PWM1. DCD 0 ; PWM2. DCD 0 ; SPIM2/SPIS2/SPI2. DCD 0 ; RTC2. DCD 0 ; I2S. DCD 0 ; FPU. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. _end_of_vectors_table _size_of_vectors_table EQU _end_of_vectors_table - _vectors_table AREA |.text|, CODE, READONLY ;; Reset handler. reset_handler PROC EXPORT reset_handler [WEAK] IMPORT main LDR R0, =main BX R0 ENDP ALIGN END qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/keil/flash.sct0000644000175100017510000000534515232633614024270 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ;; Load region size_region. LR_IROM1 0x00000000 0x00080000 { ;; Load address = execution address. ER_IROM1 0x00000000 0x00080000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } ; RW data. RW_IRAM1 0x20000000 0x00008000 { .ANY (+RW +ZI) } } qbs-src-3.3.1/examples/baremetal/pca10040/greenblink/gpio.h0000644000175100017510000000513215232633614022635 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_green_led(void); void gpio_toggle_green_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/pca10001/0000755000175100017510000000000015232633614017402 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10001/pca10001.qbs0000644000175100017510000000503415232633614021240 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for pca10001/pca10024 boards" references: [ "greenblink/greenblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/0000755000175100017510000000000015232633614021522 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10001/greenblink/gcc/0000755000175100017510000000000015232633614022256 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10001/greenblink/gcc/startup.s0000644000175100017510000001362515232633614024153 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ .syntax unified .arch armv7e-m .thumb // Define the stack. .section .stack .align 3 .equ _size_of_stack, 2048 .globl _end_of_stack .globl _stack_limit _stack_limit: .space _size_of_stack .size _stack_limit, . - _stack_limit _end_of_stack: .size _end_of_stack, . - _end_of_stack // Define the heap. .section .heap .align 3 .equ _size_of_heap, 2048 .globl _end_of_heap .globl _heap_limit _end_of_heap: .space _size_of_heap .size _end_of_heap, . - _end_of_heap _heap_limit: .size _heap_limit, . - _heap_limit // Define the empty vectors table. .section .isr_vector, "ax" .align 2 .globl _vectors_table _vectors_table: // Generic interrupts offset. .word _end_of_stack // Initial stack pointer value. .word reset_handler // Reset. .word 0 // NMI. .word 0 // Hard fault. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // SVC. .word 0 // Reserved. .word 0 // Reserved. .word 0 // PendSV. .word 0 // SysTick. // External interrupts offset. .word 0 // POWER CLOCK. .word 0 // RADIO. .word 0 // UART0 .word 0 // SPI0/TWI0. .word 0 // SPI1/TWI1. .word 0 // Reserved. .word 0 // GPIOTE. .word 0 // ADC. .word 0 // TIMER0. .word 0 // TIMER1. .word 0 // TIMER2. .word 0 // RTC0. .word 0 // TEMP. .word 0 // RNG. .word 0 // ECB. .word 0 // CCM_AAR. .word 0 // WDT. .word 0 // RTC1. .word 0 // QDEC. .word 0 // LPCOMP. .word 0 // SWI0. .word 0 // SWI1. .word 0 // SWI2. .word 0 // SWI3. .word 0 // SWI4. .word 0 // SWI5. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .size _vectors_table, . - _vectors_table // Define the 'reset_handler' function, which is an entry point. .text .thumb .thumb_func .align 1 .globl reset_handler .type reset_handler, %function reset_handler: // Loop to copy data from read only memory to RAM. ldr r1, =_end_of_code_section ldr r2, =_start_of_data_section ldr r3, =__bss_start__ subs r3, r3, r2 ble _copy_data_init_done _copy_data_init: subs r3, r3, #4 ldr r0, [r1,r3] str r0, [r2,r3] bgt _copy_data_init _copy_data_init_done: // Zero fill the bss segment. ldr r1, =__bss_start__ ldr r2, =__bss_end__ movs r0, 0 subs r2, r2, r1 ble _loop_fill_zero_bss_done _loop_fill_zero_bss: subs r2, r2, #4 str r0, [r1, r2] bgt _loop_fill_zero_bss _loop_fill_zero_bss_done: // Call the application's entry point. bl main bx lr .size reset_handler, . - reset_handler qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/gcc/flash.ld0000644000175100017510000001153615232633614023702 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000 } SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text*) KEEP(*(.init)) KEEP(*(.fini)) /* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) /* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) *(.rodata*) *(.eh_frame*) . = ALIGN(4); } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } > FLASH _start_of_exidx_section = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(4); } > FLASH _end_of_exidx_section = .; _end_of_code_section = .; .data : AT (_end_of_code_section) { _start_of_data_section = .; *(vtable) *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN(__preinit_array_start = .); *(.preinit_array) PROVIDE_HIDDEN(__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN(__init_array_start = .); *(SORT(.init_array.*)) *(.init_array) PROVIDE_HIDDEN(__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN(__fini_array_start = .); *(SORT(.fini_array.*)) *(.fini_array) PROVIDE_HIDDEN(__fini_array_end = .); *(.jcr) . = ALIGN(4); /* All data end */ _end_of_data_section = .; } > RAM .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; } > RAM .heap (COPY): { __end__ = .; end = __end__; *(.heap*) _heap_limit = .; } > RAM .stack_dummy (COPY): { *(.stack*) } > RAM /* Set stack top to end of RAM, and stack limit move down by size of stack_dummy section. */ _end_of_stack = ORIGIN(RAM) + LENGTH(RAM); _stack_limit = _end_of_stack - SIZEOF(.stack_dummy); PROVIDE(__stack = _end_of_stack); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(_stack_limit >= _heap_limit, "region RAM overflowed with stack") } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/main.c0000644000175100017510000000531015232633614022611 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { gpio_init_green_led(); while (1) { gpio_toggle_green_led(); some_delay(1000000u); } } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/system.h0000644000175100017510000000575215232633614023230 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #include #ifdef __cplusplus extern "C" { #endif #define __IO volatile struct gpio_regs_map { uint32_t RESERVED0[321u]; __IO uint32_t OUT; __IO uint32_t OUTSET; __IO uint32_t OUTCLR; __IO uint32_t IN; __IO uint32_t DIR; __IO uint32_t DIRSET; __IO uint32_t DIRCLR; uint32_t RESERVED1[120u]; __IO uint32_t PIN_CNF[32u]; }; #define GPIO_REGS_ADDRESS (0x50000000u) #define GPIOD_REGS_MAP ((struct gpio_regs_map *)GPIO_REGS_ADDRESS) #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/greenblink.qbs0000644000175100017510000001164215232633614024355 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.startsWith("arm")) return false; return (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil")) && !qbs.targetOS.includes("darwin") } name: "pca10001-greenblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // GCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("gcc") cpp.assemblerFlags: [ "-mcpu=cortex-m0", ] cpp.driverFlags: [ "-mcpu=cortex-m0", "-specs=nosys.specs" ] } Group { condition: qbs.toolchain.contains("gcc") name: "GCC" prefix: "gcc/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.ld"] } } // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.assemblerFlags: [ "--cpu", "cortex-m0" ] cpp.driverFlags: [ "--cpu", "cortex-m0" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.icf"] } } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.assemblerFlags: [ "--cpu", "cortex-m0" ] cpp.driverFlags: [ "--cpu", "cortex-m0" ] } Group { condition: qbs.toolchain.contains("keil") name: "KEIL" prefix: "keil/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.sct"] } } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/gpio.c0000644000175100017510000001063015232633614022624 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #define GPIO_GREEN_LED_PIN_POS (18u) #define GPIO_GREEN_LED_PIN (1u << GPIO_GREEN_LED_PIN_POS) // Pin direction attributes. #define GPIO_PIN_CNF_DIR_POS (0u) // Position of DIR field. #define GPIO_PIN_CNF_DIR_OUT (1u) // Configure pin as an output pin. #define GPIO_PIN_CNF_DIR_MSK (GPIO_PIN_CNF_DIR_OUT << GPIO_PIN_CNF_DIR_POS) // Pin input buffer attributes. #define GPIO_PIN_CNF_INPUT_POS (1u) // Position of INPUT field. #define GPIO_PIN_CNF_INPUT_OFF (1u) // Disconnect input buffer. #define GPIO_PIN_CNF_INPUT_MSK (GPIO_PIN_CNF_INPUT_OFF << GPIO_PIN_CNF_INPUT_POS) // Pin pull attributes. #define GPIO_PIN_CNF_PULL_POS (2u) // Position of PULL field. #define GPIO_PIN_CNF_PULL_OFF (0u) // No pull. #define GPIO_PIN_CNF_PULL_MSK (GPIO_PIN_CNF_PULL_OFF << GPIO_PIN_CNF_PULL_POS) // Pin drive attributes. #define GPIO_PIN_CNF_DRIVE_POS (8u) // Position of DRIVE field. #define GPIO_PIN_CNF_DRIVE_S0S1 (0u) // Standard '0', standard '1'. #define GPIO_PIN_CNF_DRIVE_MSK (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_POS) // Pin sense attributes. #define GPIO_PIN_CNF_SENSE_POS (16u) // Position of SENSE field. #define GPIO_PIN_CNF_SENSE_OFF (0u) // Disabled. #define GPIO_PIN_CNF_SENSE_MSK (GPIO_PIN_CNF_SENSE_OFF << GPIO_PIN_CNF_SENSE_POS) void gpio_init_green_led(void) { GPIOD_REGS_MAP->PIN_CNF[GPIO_GREEN_LED_PIN_POS] = (GPIO_PIN_CNF_DIR_MSK | GPIO_PIN_CNF_INPUT_MSK | GPIO_PIN_CNF_PULL_MSK | GPIO_PIN_CNF_DRIVE_MSK | GPIO_PIN_CNF_SENSE_MSK); } void gpio_toggle_green_led(void) { const uint32_t gpio_state = GPIOD_REGS_MAP->OUT; GPIOD_REGS_MAP->OUTSET = (GPIO_GREEN_LED_PIN & ~gpio_state); GPIOD_REGS_MAP->OUTCLR = (GPIO_GREEN_LED_PIN & gpio_state); } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/iar/0000755000175100017510000000000015232633614022275 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10001/greenblink/iar/startup.s0000644000175100017510000001116615232633614024170 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MODULE ?cstartup SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start PUBLIC _vectors_table DATA _vectors_table ;; Generic interrupts offset. DCD sfe(CSTACK) ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Power clock. DCD 0 ; Radio. DCD 0 ; UART0. DCD 0 ; SPI0/TWI0 DCD 0 ; SPI1/TWI1 DCD 0 ; Reserved DCD 0 ; GPIOTE DCD 0 ; ADC DCD 0 ; TIMER0 DCD 0 ; TIMER1 DCD 0 ; TIMER2 DCD 0 ; RTC0 DCD 0 ; TEMP DCD 0 ; RNG DCD 0 ; ECB DCD 0 ; CCM/AAR DCD 0 ; WDT DCD 0 ; RTC1 DCD 0 ; QDEC DCD 0 ; LPCOMP DCD 0 ; SWI0 DCD 0 ; SWI1 DCD 0 ; SWI2 DCD 0 ; SWI3 DCD 0 ; SWI4 DCD 0 ; SWI5 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved ;; Reset handler. THUMB PUBWEAK reset_handler SECTION .text:CODE:REORDER:NOROOT(2) reset_handler BLX R0 LDR R0, =__iar_program_start BX R0 END qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/iar/flash.icf0000644000175100017510000000644315232633614024064 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ define symbol _start_of_intvec_section = 0x00000000; define symbol _start_of_ram_section = 0x20000000; define symbol _end_of_ram_section = 0x20003FFF; define symbol _start_of_flash_section = 0x00000000; define symbol _end_of_flash_section = 0x0003FFFF; define symbol _min_stack_size = 0x800; define symbol _min_heap_size = 0x800; define memory mem with size = 4G; define region flash_section = mem:[from _start_of_flash_section to _end_of_flash_section]; define region ram_section = mem:[from _start_of_ram_section to _end_of_ram_section]; define block CSTACK with alignment = 8, size = _min_stack_size { }; define block HEAP with alignment = 8, size = _min_heap_size { }; initialize by copy { readwrite }; place at address mem:_start_of_intvec_section { readonly section .intvec }; place in flash_section { readonly }; place in ram_section { readwrite, block CSTACK, block HEAP }; qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/README.md0000644000175100017510000000056515232633614023007 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different ARM toolchains. It is designed for the Nordic pca100001/pca100024 evaluation kit (based on nRF51822 MCU) and simply flashes the green LED on the board. The following toolchains are supported: * GNU Arm Embedded Toolchain * IAR Embedded Workbench * KEIL Microcontroller Development Kit qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/keil/0000755000175100017510000000000015232633614022446 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/pca10001/greenblink/keil/startup.s0000644000175100017510000001163015232633614024335 0ustar runnerrunner;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Copyright (C) 2020 Denis Shienkov ;; Contact: https://www.qt.io/licensing/ ;; ;; This file is part of the examples of Qbs. ;; ;; $QT_BEGIN_LICENSE:BSD$ ;; Commercial License Usage ;; Licensees holding valid commercial Qt licenses may use this file in ;; accordance with the commercial license agreement provided with the ;; Software or, alternatively, in accordance with the terms contained in ;; a written agreement between you and The Qt Company. For licensing terms ;; and conditions see https://www.qt.io/terms-conditions. For further ;; information use the contact form at https://www.qt.io/contact-us. ;; ;; BSD License Usage ;; Alternatively, you may use this file under the terms of the BSD license ;; as follows: ;; ;; "Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions are ;; met: ;; * Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; * Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in ;; the documentation and/or other materials provided with the ;; distribution. ;; * Neither the name of The Qt Company Ltd nor the names of its ;; contributors may be used to endorse or promote products derived ;; from this software without specific prior written permission. ;; ;; ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ;; ;; $QT_END_LICENSE$ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _size_of_stack EQU 0x800 _size_of_heap EQU 0x800 ;; Stack configuration. AREA STACK, NOINIT, READWRITE, ALIGN=3 _start_of_stack SPACE _size_of_stack _end_of_stack ;; Heap configuration. AREA HEAP, NOINIT, READWRITE, ALIGN=3 _start_of_heap SPACE _size_of_heap _end_of_heap PRESERVE8 THUMB ;; Define the empty vectors table. AREA RESET, DATA, READONLY _vectors_table ;; Generic interrupts offset. DCD _end_of_stack ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Power clock. DCD 0 ; Radio. DCD 0 ; UART0. DCD 0 ; SPI0/TWI0 DCD 0 ; SPI1/TWI1 DCD 0 ; Reserved DCD 0 ; GPIOTE DCD 0 ; ADC DCD 0 ; TIMER0 DCD 0 ; TIMER1 DCD 0 ; TIMER2 DCD 0 ; RTC0 DCD 0 ; TEMP DCD 0 ; RNG DCD 0 ; ECB DCD 0 ; CCM/AAR DCD 0 ; WDT DCD 0 ; RTC1 DCD 0 ; QDEC DCD 0 ; LPCOMP DCD 0 ; SWI0 DCD 0 ; SWI1 DCD 0 ; SWI2 DCD 0 ; SWI3 DCD 0 ; SWI4 DCD 0 ; SWI5 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved _end_of_vectors_table _size_of_vectors_table EQU _end_of_vectors_table - _vectors_table AREA |.text|, CODE, READONLY ;; Reset handler. reset_handler PROC EXPORT reset_handler [WEAK] IMPORT main LDR R0, =main BX R0 ENDP ALIGN END qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/keil/flash.sct0000644000175100017510000000534515232633614024265 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ;; Load region size_region. LR_IROM1 0x00000000 0x00040000 { ;; Load address = execution address. ER_IROM1 0x00000000 0x00040000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } ; RW data. RW_IRAM1 0x20000000 0x00004000 { .ANY (+RW +ZI) } } qbs-src-3.3.1/examples/baremetal/pca10001/greenblink/gpio.h0000644000175100017510000000513215232633614022632 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_green_led(void); void gpio_toggle_green_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/esp8266/0000755000175100017510000000000015232633614017372 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/access-point/0000755000175100017510000000000015232633614021762 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/access-point/user_config.h0000644000175100017510000000535415232633614024445 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ESP8266_USER_CONFIG_H #define ESP8266_USER_CONFIG_H // From ESP8266 SDK. #include #define ESP_SSID_CFG "HELLO FROM QBS\0" #define ESP_AUTO_MODE_CFG (AUTH_OPEN) #define ESP_BEACON_INTERVAL_MS_CFG (1000) #define ESP_CHANNEL_NO_CFG (3) #endif // ESP8266_USER_CONFIG_H qbs-src-3.3.1/examples/baremetal/esp8266/access-point/access-point.qbs0000644000175100017510000000106015232633614025056 0ustar runnerrunnerCppApplication { condition: qbs.toolchain.contains("gcc") && qbs.architecture === "xtensa" Depends { name: "esp8266_sdk" } cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // This required because ESP8266 SDK includes this 'user_config.h' internally. cpp.includePaths: ["."] cpp.staticLibraries: [ "c", "crypto", "gcc", "lwip", "main", "net80211", "phy", "pp", "wpa" ] files: [ "user_config.h", "user_main.c" ] } qbs-src-3.3.1/examples/baremetal/esp8266/access-point/user_main.c0000644000175100017510000001037015232633614024111 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "user_config.h" // From ESP8266 SDK. #include static const partition_item_t esp_partitions[] = { {SYSTEM_PARTITION_BOOTLOADER, ESP_PART_BL_ADDR, ESP_PART_BOOTLOADER_SIZE}, {SYSTEM_PARTITION_OTA_1, ESP_PART_APP1_ADDR, ESP_PART_APPLICATION_SIZE}, {SYSTEM_PARTITION_OTA_2, ESP_PART_APP2_ADDR, ESP_PART_APPLICATION_SIZE}, {SYSTEM_PARTITION_RF_CAL, ESP_PART_RF_CAL_ADDR, ESP_PART_RF_CAL_SIZE}, {SYSTEM_PARTITION_PHY_DATA, ESP_PART_PHY_DATA_ADDR, ESP_PART_PHY_DATA_SIZE}, {SYSTEM_PARTITION_SYSTEM_PARAMETER, ESP_PART_SYS_PARAM_ADDR, ESP_PART_SYS_PARAM_SIZE} }; enum { ESP_PART_COUNT = sizeof(esp_partitions) / sizeof(esp_partitions[0]) }; LOCAL void ICACHE_FLASH_ATTR user_init_done(void) { os_printf("esp: initialization completed\n"); } void ICACHE_FLASH_ATTR user_pre_init(void) { const bool ok = system_partition_table_regist(esp_partitions, ESP_PART_COUNT, SPI_FLASH_SIZE_MAP); if (!ok) { os_printf("esp: partitions registration failed\n"); while (true); } } void ICACHE_FLASH_ATTR user_init(void) { os_printf("esp: SDK version: %s\n", system_get_sdk_version()); os_printf("esp: reset reason: %u\n", system_get_rst_info()->reason); const bool ok = wifi_set_opmode(SOFTAP_MODE); if (!ok) { os_printf("esp: set softap mode failed\n"); } else { struct softap_config ap_cfg = {0}; ap_cfg.authmode = ESP_AUTO_MODE_CFG; ap_cfg.beacon_interval = ESP_BEACON_INTERVAL_MS_CFG; ap_cfg.channel = ESP_CHANNEL_NO_CFG; ap_cfg.max_connection = 0; ap_cfg.ssid_hidden = false; os_memcpy(&ap_cfg.ssid, ESP_SSID_CFG, sizeof(ESP_SSID_CFG)); const bool ok = wifi_softap_set_config(&ap_cfg); if (!ok) os_printf("esp: set softap configuration failed\n"); } system_init_done_cb(user_init_done); } qbs-src-3.3.1/examples/baremetal/esp8266/qbs/0000755000175100017510000000000015232633614020157 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/qbs/modules/0000755000175100017510000000000015232633614021627 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/qbs/modules/esp8266_sdk/0000755000175100017510000000000015232633614023605 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/qbs/modules/esp8266_sdk/Esp8266SdkModule.qbs0000644000175100017510000000353715232633614027211 0ustar runnerrunnerModule { Depends { name: "cpp" } Esp8266SdkProbe { id: esp_sdk_probe } validate: { if (!esp_sdk_probe.found) throw "ESP8266 NON OS SDK not found. Please set the ESP8266_NON_OS_SDK_ROOT env variable." } cpp.systemIncludePaths: [esp_sdk_probe.includesPath] cpp.libraryPaths: [esp_sdk_probe.libsPath] cpp.driverFlags: ["-nostdlib"] cpp.cFlags: [ "-Wpointer-arith", "-Wundef", "-fno-inline-functions", "-mlongcalls", "-mtext-section-literals", "-ffunction-sections", "-fdata-sections", "-fno-builtin-printf", "-fno-guess-branch-probability", "-freorder-blocks-and-partition", "-fno-cse-follow-jumps" ] cpp.linkerFlags: [ "--no-check-sections", "--gc-sections", "--start-group" ] cpp.defines: [ "ICACHE_FLASH", "USE_OPTIMIZE_PRINTF", // Target specific defines for the external 40MHz DIO // SPI 16 Mbit FLASH (2048 KByte + 2048 KByte) FOTA. "SPI_FLASH_SIZE_MAP=5", "ESP_PART_BL_ADDR=0x000000", "ESP_PART_APP1_ADDR=0x001000", "ESP_PART_APP2_ADDR=0x101000", "ESP_PART_RF_CAL_ADDR=0x1FB000", "ESP_PART_PHY_DATA_ADDR=0x1FC000", "ESP_PART_SYS_PARAM_ADDR=0x1FD000", "ESP_PART_BOOTLOADER_SIZE=0x001000", "ESP_PART_APPLICATION_SIZE=0x0E0000", "ESP_PART_RF_CAL_SIZE=0x001000", "ESP_PART_PHY_DATA_SIZE=0x001000", "ESP_PART_SYS_PARAM_SIZE=0x003000" ] property string _linker_scripts_path: esp_sdk_probe.linkerScriptsPath + "/" Group { name: "ESP8266 Linker Scripts" prefix: esp8266_sdk._linker_scripts_path + "/" fileTags: ["linkerscript"] files: [ "eagle.rom.addr.v6.ld", "eagle.app.v6.new.2048.ld" ] } } qbs-src-3.3.1/examples/baremetal/esp8266/qbs/imports/0000755000175100017510000000000015232633614021654 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/esp8266/qbs/imports/Esp8266SdkProbe.qbs0000644000175100017510000000133415232633614025073 0ustar runnerrunnerimport qbs.Environment import qbs.File import qbs.FileInfo import qbs.Probes Probes.PathProbe { // Inputs. environmentPaths: Environment.getEnv("ESP8266_NON_OS_SDK_ROOT") // Outputs. property string includesPath; property string libsPath; property string linkerScriptsPath; configure: { for (var i in environmentPaths) { var rootPath = environmentPaths[i]; if (!File.exists(rootPath)) continue; includesPath = FileInfo.joinPaths(rootPath, "include"); libsPath = FileInfo.joinPaths(rootPath, "lib"); linkerScriptsPath = FileInfo.joinPaths(rootPath, "ld"); found = true; return; } } } qbs-src-3.3.1/examples/baremetal/esp8266/esp8266.qbs0000644000175100017510000000507015232633614021220 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for esp8266-wroom-02 board" qbsSearchPaths: "qbs" references: [ "access-point/access-point.qbs" ] } qbs-src-3.3.1/examples/baremetal/esp8266/README.md0000644000175100017510000000206515232633614020654 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using GCC toolchain for Espressif ESP8266-WROOM02 MCU. An application is designed to be flashed on the external SPI FLASH with the following parameters: * SPI FLASH size: 16 MBit (2048 + 2048 KBytes) * SPI FLASH mode: DIO * SPI FLASH clock: 40 MHz * SPI FLASH map type: 5 An application is running as WiFi access point that discards all connection attempts, and has the following WiFi parameters: * SSID: "HELLO FROM QBS" * Authentication mode: "open" * Beacon interval: 1000 milliseconds * Channel number: 3 An application requires the ESP8266 NON-OS SDK: * https://github.com/espressif/ESP8266_NONOS_SDK the path to which should be set via the ESP8266_NON_OS_SDK_ROOT environment variable. To convert the ELF application to the final binary image (and also for re-program the ESP8266 MCU), you can use the open source 'esptool' utility (using the SPI FLASH parameters, provided above): * https://github.com/espressif/esptool The following toolchains are supported: * GNU ESP8266 Toolchain qbs-src-3.3.1/examples/baremetal/stm32f103/0000755000175100017510000000000015232633614017617 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f103/stm32f103.qbs0000644000175100017510000000502315232633614021670 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for stm32f103 board" references: [ "greenblink/greenblink.qbs" ] } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/0000755000175100017510000000000015232633614021737 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/gcc/0000755000175100017510000000000015232633614022473 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/gcc/startup.s0000644000175100017510000001513515232633614024366 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ .syntax unified .cpu cortex-m3 .fpu softvfp .thumb // These symbols are exported from the linker script. .word _start_of_init_data_section .word _start_of_data_section .word _end_of_data_section .word _start_of_bss_section .word _end_of_bss_section .equ _boot_ram, 0xF108F85F .section .text.reset_handler .weak reset_handler .type reset_handler, %function reset_handler: // Copy the data segment initializers from flash to SRAM. movs r1, #0 b _loop_copy_data_init _copy_data_init: ldr r3, =_start_of_init_data_section ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 _loop_copy_data_init: ldr r0, =_start_of_data_section ldr r3, =_end_of_data_section adds r2, r0, r1 cmp r2, r3 bcc _copy_data_init ldr r2, =_start_of_bss_section b _loop_fill_zero_bss // Zero fill the bss segment. _fill_zero_bss: movs r3, #0 str r3, [r2], #4 _loop_fill_zero_bss: ldr r3, = _end_of_bss_section cmp r2, r3 bcc _fill_zero_bss // Call the static constructors. bl __libc_init_array // Call the application entry point. bl main bx lr .size reset_handler, .-reset_handler // Define the empty vectors table. .section .isr_vector,"a",%progbits .type _vectors_table, %object .size _vectors_table, .-_vectors_table _vectors_table: // Generic interrupts offset. .word _end_of_stack // Initial stack pointer value. .word reset_handler // Reset. .word 0 // NMI. .word 0 // Hard fault. .word 0 // Memory management fault. .word 0 // Bus fault. .word 0 // Usage fault. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // Reserved. .word 0 // SVC. .word 0 // Debug monitor. .word 0 // Reserved. .word 0 // PendSV. .word 0 // SysTick. // External interrupts offset. .word 0 // Window watchdog. .word 0 // PVD through EXTI Line detection. .word 0 // Tamper and timestamps through the EXTI line. .word 0 // RTC wakeup through the EXTI line. .word 0 // FLASH. .word 0 // RCC. .word 0 // EXTI line0. .word 0 // EXTI line1. .word 0 // EXTI line2. .word 0 // EXTI line3. .word 0 // EXTI line4. .word 0 // DMA1 stream 0. .word 0 // DMA1 stream 1. .word 0 // DMA1 stream 2. .word 0 // DMA1 stream 3. .word 0 // DMA1 stream 4. .word 0 // DMA1 stream 5. .word 0 // DMA1 stream 6. .word 0 // ADC1/2. .word 0 // USB HP/CAN1 TX. .word 0 // USB LP / CAN1 RX0. .word 0 // CAN1 RX1. .word 0 // CAN1 SCE. .word 0 // EXTI line [9:5]s. .word 0 // TIM1 break. .word 0 // TIM1 update. .word 0 // TIM1 trigger and communication. .word 0 // TIM1 capture compare. .word 0 // TIM2. .word 0 // TIM3. .word 0 // TIM4. .word 0 // I2C1 event. .word 0 // I2C1 error. .word 0 // I2C2 event. .word 0 // I2C2 error. .word 0 // SPI1. .word 0 // SPI2. .word 0 // USART1. .word 0 // USART2. .word 0 // USART3. .word 0 // EXTI line [15:10]s. .word 0 // RTC alarm. .word 0 // USB wakeup. .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word _boot_ram // Boot RAM mode for stm32f10x medium density devices. qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/gcc/flash.ld0000644000175100017510000001325615232633614024120 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /* Entry point (defined in assembled file). */ ENTRY(reset_handler) /* End of RAM, it is the user mode stack pointer address. */ _end_of_stack = 0x20005000; /* Generate a link error if heap and stack don't fit into RAM. */ _size_of_heap = 0x200; /* Required amount of heap. */ _size_of_stack = 0x400; /* Required amount of stack. */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K } SECTIONS { /* The vectors table goes into FLASH. */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code. */ . = ALIGN(4); } > FLASH /* The program code and other data goes into FLASH. */ .text : { . = ALIGN(4); *(.text) *(.text*) *(.glue_7) /* Glue arm to thumb code. */ *(.glue_7t) /* Glue thumb to arm code. */ *(.eh_frame) KEEP(*(.init)) KEEP(*(.fini)) . = ALIGN(4); _end_of_text_section = .; /* Export global symbol at end of code. */ } > FLASH /* Constant data goes into FLASH. */ .rodata : { . = ALIGN(4); *(.rodata) *(.rodata*) . = ALIGN(4); } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } > FLASH .preinit_array : { PROVIDE_HIDDEN(__preinit_array_start = .); KEEP(*(.preinit_array*)) PROVIDE_HIDDEN(__preinit_array_end = .); } > FLASH .init_array : { PROVIDE_HIDDEN(__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array*)) PROVIDE_HIDDEN(__init_array_end = .); } > FLASH .fini_array : { PROVIDE_HIDDEN(__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array*)) PROVIDE_HIDDEN(__fini_array_end = .); } > FLASH _start_of_init_data_section = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code. */ .data : { . = ALIGN(4); _start_of_data_section = .; /* Export global symbol at data start. */ *(.data) *(.data*) . = ALIGN(4); _end_of_data_section = .; /* Export global symbol at data end. */ } > RAM AT > FLASH /* Uninitialized data section. */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion. */ _start_of_bss_section = .; /* Export global symbol at bss start. */ __bss_start__ = _start_of_bss_section; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _end_of_bss_section = .; /* Export global symbol at bss end. */ __bss_end__ = _end_of_bss_section; } > RAM /* Used to check that there is enough RAM left. */ ._user_heap_stack : { . = ALIGN(4); PROVIDE(end = .); PROVIDE(_end = .); . = . + _size_of_heap; . = . + _size_of_stack; . = ALIGN(4); } > RAM /* Remove information from the standard libraries. */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/main.c0000644000175100017510000000530715232633614023034 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { gpio_init_green_led(); while (1) { gpio_toggle_green_led(); some_delay(100000u); } } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/system.h0000644000175100017510000000704715232633614023444 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #include #ifdef __cplusplus extern "C" { #endif #define __IO volatile // General purpose input/output registers map. struct gpio_regs_map { __IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __IO uint32_t LCKR; }; // Reset and clock control registers map. struct rcc_regs_map { __IO uint32_t CR; __IO uint32_t CFGR; __IO uint32_t CIR; __IO uint32_t APB2RSTR; __IO uint32_t APB1RSTR; __IO uint32_t AHBENR; __IO uint32_t APB2ENR; __IO uint32_t APB1ENR; __IO uint32_t BDCR; __IO uint32_t CSR; }; #define PERIPH_ADDRESS (0x40000000u) #define APB2PERIPH_ADDRESS (PERIPH_ADDRESS + 0x00010000u) #define AHBPERIPH_ADDRESS (PERIPH_ADDRESS + 0x00020000u) #define GPIOC_REGS_ADDRESS (APB2PERIPH_ADDRESS + 0x00001000u) #define RCC_REGS_ADDRESS (AHBPERIPH_ADDRESS + 0x00001000u) #define GPIOC_REGS_MAP ((struct gpio_regs_map *)GPIOC_REGS_ADDRESS) #define RCC_REGS_MAP ((struct rcc_regs_map *)RCC_REGS_ADDRESS) #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/greenblink.qbs0000644000175100017510000001173415232633614024574 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.startsWith("arm")) return false; return (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("iar") || qbs.toolchain.contains("keil")) && !qbs.targetOS.includes("darwin") } name: "stm32f103-greenblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // GCC-specific properties and sources. // Properties { condition: qbs.toolchain.contains("gcc") cpp.assemblerFlags: [ "-mcpu=cortex-m3" ] cpp.driverFlags: [ "-mcpu=cortex-m3", "-specs=nosys.specs" ] } Group { condition: qbs.toolchain.contains("gcc") name: "GCC" prefix: "gcc/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.ld"] } } // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.assemblerFlags: [ "--cpu", "cortex-m3", "--fpu", "none" ] cpp.driverFlags: [ "--cpu", "cortex-m3", "--fpu", "none" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.icf"] } } // // KEIL-specific properties and sources. // Properties { condition: qbs.toolchain.contains("keil") cpp.assemblerFlags: [ "--cpu", "cortex-m3" ] cpp.driverFlags: [ "--cpu", "cortex-m3" ] } Group { condition: qbs.toolchain.contains("keil") name: "KEIL" prefix: "keil/" Group { name: "Startup" fileTags: ["asm"] files: ["startup.s"] } Group { name: "Linker Script" fileTags: ["linkerscript"] files: ["flash.sct"] } } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.h"] } files: ["main.c"] } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/gpio.c0000644000175100017510000000727515232633614023054 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #define GPIO_GREEN_LED_PIN_POS (13u) #define GPIO_GREEN_LED_PIN (1u << GPIO_GREEN_LED_PIN_POS) // Bit definition for RCC_APB2ENR register. #define RCC_APB2ENR_IOPCEN_POS (4u) #define RCC_APB2ENR_IOPCEN (0x1u << RCC_APB2ENR_IOPCEN_POS) // Bit definition for GPIO_CRL register. #define GPIO_CRL_MODE_POS (0u) // MODE field position. #define GPIO_CRL_MODE_MSK (0x3u << GPIO_CRL_MODE_POS) // MODE field mask. #define GPIO_CRL_MODE_OUT_FREQ_LOW (0x2u << GPIO_CRL_MODE_POS) // As output with low frequency. #define GPIO_CRL_CNF_POS (2u) // CNF field position. #define GPIO_CRL_CNF_MSK (0x3u << GPIO_CRL_CNF_POS) // CNF field mask. #define GPIO_CRL_CNF_OUTPUT_PP (0x00000000u) // General purpose output push-pull. void gpio_init_green_led(void) { // Enable RCC clock on GPIOC port. RCC_REGS_MAP->APB2ENR |= RCC_APB2ENR_IOPCEN; // Configure GPIOC pin #13. const uint32_t offset = ((GPIO_GREEN_LED_PIN_POS - 8u) << 2u); GPIOC_REGS_MAP->CRH &= ~((GPIO_CRL_MODE_MSK | GPIO_CRL_CNF_MSK) << offset); GPIOC_REGS_MAP->CRH |= ((GPIO_CRL_MODE_OUT_FREQ_LOW | GPIO_CRL_CNF_OUTPUT_PP) << offset); } void gpio_toggle_green_led(void) { GPIOC_REGS_MAP->ODR ^= GPIO_GREEN_LED_PIN; } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/iar/0000755000175100017510000000000015232633614022512 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/iar/startup.s0000644000175100017510000001251415232633614024403 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ MODULE ?cstartup SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start PUBLIC _vectors_table DATA _vectors_table ;; Generic interrupts offset. DCD sfe(CSTACK) ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; MPU fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Debug monitor. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Window watchdog. DCD 0 ; PVD through EXTI line detection. DCD 0 ; Tamper. DCD 0 ; RTC. DCD 0 ; Flash. DCD 0 ; RCC. DCD 0 ; EXTI line 0. DCD 0 ; EXTI line 1. DCD 0 ; EXTI line 2. DCD 0 ; EXTI line 3. DCD 0 ; EXTI line 4. DCD 0 ; DMA1 channel 1. DCD 0 ; DMA1 channel 2. DCD 0 ; DMA1 channel 3. DCD 0 ; DMA1 channel 4. DCD 0 ; DMA1 channel 5. DCD 0 ; DMA1 channel 6. DCD 0 ; DMA1 channel 7. DCD 0 ; ADC1/2. DCD 0 ; USB high priority or CAN1 TX. DCD 0 ; USB low priority or CAN1 RX0. DCD 0 ; CAN1 RX1. DCD 0 ; CAN1 SCE. DCD 0 ; EXTI line 9..5. DCD 0 ; TIM1 break. DCD 0 ; TIM1 update. DCD 0 ; TIM1 trigger and commutation. DCD 0 ; TIM1 capture compare. DCD 0 ; TIM2. DCD 0 ; TIM3. DCD 0 ; TIM4. DCD 0 ; I2C1 event. DCD 0 ; I2C1 error. DCD 0 ; I2C2 event. DCD 0 ; I2C2 error. DCD 0 ; SPI1. DCD 0 ; SPI2. DCD 0 ; USART1. DCD 0 ; USART2. DCD 0 ; USART3. DCD 0 ; EXTI line 15..10. DCD 0 ; RTC alarm through EXTI line. DCD 0 ; USB wakeup from suspend. ;; Reset handler. THUMB PUBWEAK reset_handler SECTION .text:CODE:REORDER:NOROOT(2) reset_handler BLX R0 LDR R0, =__iar_program_start BX R0 END qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/iar/flash.icf0000644000175100017510000000650315232633614024276 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ define symbol _start_of_intvec_section = 0x08000000; define symbol _start_of_flash_section = 0x08000000; define symbol _end_of_flash_section = 0x0801FFFF; define symbol _start_of_ram_section = 0x20000000; define symbol _end_of_ram_section = 0x20004FFF; define symbol _min_stack_size = 0x400; define symbol _min_heap_size = 0x200; define memory mem with size = 4G; define region flash_section = mem:[from _start_of_flash_section to _end_of_flash_section]; define region ram_section = mem:[from _start_of_ram_section to _end_of_ram_section]; define block CSTACK with alignment = 8, size = _min_stack_size { }; define block HEAP with alignment = 8, size = _min_heap_size { }; initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:_start_of_intvec_section { readonly section .intvec }; place in flash_section { readonly }; place in ram_section { readwrite, block CSTACK, block HEAP }; qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/README.md0000644000175100017510000000056315232633614023222 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different ARM toolchains. It is designed for the stm32f103 "Blue Pill" evaluation kit (based on stm32f103c8 MCU) and simply flashes the green LED on the board. The following toolchains are supported: * GNU Arm Embedded Toolchain * IAR Embedded Workbench * KEIL Microcontroller Development Kit qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/keil/0000755000175100017510000000000015232633614022663 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/keil/startup.s0000644000175100017510000001327515232633614024561 0ustar runnerrunner;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Copyright (C) 2020 Denis Shienkov ;; Contact: https://www.qt.io/licensing/ ;; ;; This file is part of the examples of Qbs. ;; ;; $QT_BEGIN_LICENSE:BSD$ ;; Commercial License Usage ;; Licensees holding valid commercial Qt licenses may use this file in ;; accordance with the commercial license agreement provided with the ;; Software or, alternatively, in accordance with the terms contained in ;; a written agreement between you and The Qt Company. For licensing terms ;; and conditions see https://www.qt.io/terms-conditions. For further ;; information use the contact form at https://www.qt.io/contact-us. ;; ;; BSD License Usage ;; Alternatively, you may use this file under the terms of the BSD license ;; as follows: ;; ;; "Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions are ;; met: ;; * Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; * Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in ;; the documentation and/or other materials provided with the ;; distribution. ;; * Neither the name of The Qt Company Ltd nor the names of its ;; contributors may be used to endorse or promote products derived ;; from this software without specific prior written permission. ;; ;; ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ;; ;; $QT_END_LICENSE$ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _size_of_stack EQU 0x400 _size_of_heap EQU 0x200 ;; Stack configuration. AREA STACK, NOINIT, READWRITE, ALIGN=3 _start_of_stack SPACE _size_of_stack _end_of_stack ;; Heap configuration. AREA HEAP, NOINIT, READWRITE, ALIGN=3 _start_of_heap SPACE _size_of_heap _end_of_heap PRESERVE8 THUMB ;; Define the empty vectors table. AREA RESET, DATA, READONLY _vectors_table ;; Generic interrupts offset. DCD _end_of_stack ; Initial stack pointer value. DCD reset_handler ; Reset. DCD 0 ; NMI. DCD 0 ; Hard fault. DCD 0 ; Memory management fault. DCD 0 ; Bus fault. DCD 0 ; Usage fault. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; Reserved. DCD 0 ; SVC. DCD 0 ; Debug monitor. DCD 0 ; Reserved. DCD 0 ; PendSV. DCD 0 ; SysTick. ;; External interrupts offset. DCD 0 ; Window watchdog. DCD 0 ; PVD through EXTI line detection. DCD 0 ; Tamper and TimeStamps through the EXTI line. DCD 0 ; RTC wakeup through the EXTI line. DCD 0 ; FLASH. DCD 0 ; RCC. DCD 0 ; EXTI line0. DCD 0 ; EXTI line1. DCD 0 ; EXTI line2. DCD 0 ; EXTI line3. DCD 0 ; EXTI line4. DCD 0 ; DMA1 channel 1. DCD 0 ; DMA1 channel 2. DCD 0 ; DMA1 channel 3. DCD 0 ; DMA1 channel 4. DCD 0 ; DMA1 channel 5. DCD 0 ; DMA1 channel 6. DCD 0 ; DMA1 channel 7. DCD 0 ; ADC1/2. DCD 0 ; USB high priority or CAN1 TX. DCD 0 ; USB low priority or CAN1 RX0. DCD 0 ; CAN1 RX1. DCD 0 ; CAN1 SCE. DCD 0 ; EXTI line 9..5. DCD 0 ; TIM1 break. DCD 0 ; TIM1 update. DCD 0 ; TIM1 trigger and commutation. DCD 0 ; IM1 capture compare. DCD 0 ; TIM2. DCD 0 ; TIM3. DCD 0 ; TIM4. DCD 0 ; I2C1 event. DCD 0 ; I2C1 error. DCD 0 ; I2C2 event. DCD 0 ; I2C2 error. DCD 0 ; SPI1. DCD 0 ; SPI2. DCD 0 ; USART1. DCD 0 ; USART2. DCD 0 ; USART3. DCD 0 ; EXTI line 15..10. DCD 0 ; RTC alarm through EXTI line. DCD 0 ; USB wakeup from suspend. _end_of_vectors_table _size_of_vectors_table EQU _end_of_vectors_table - _vectors_table AREA |.text|, CODE, READONLY ;; Reset handler. reset_handler PROC EXPORT reset_handler [WEAK] IMPORT main LDR R0, =main BX R0 ENDP ALIGN END qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/keil/flash.sct0000644000175100017510000000534515232633614024502 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ ;; Load region size_region. LR_IROM1 0x08000000 0x00010000 { ;; Load address = execution address. ER_IROM1 0x08000000 0x00010000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } ; RW data. RW_IRAM1 0x20000000 0x00005000 { .ANY (+RW +ZI) } } qbs-src-3.3.1/examples/baremetal/stm32f103/greenblink/gpio.h0000644000175100017510000000513215232633614023047 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_green_led(void); void gpio_toggle_green_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/msp430f5529/0000755000175100017510000000000015232633614017776 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/0000755000175100017510000000000015232633614021570 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/redblink.qbs0000644000175100017510000001063415232633614024075 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("msp430")) return false; return qbs.toolchain.contains("iar") || qbs.toolchain.contains("gcc") } name: "msp430f5529-redblink" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") cpp.driverFlags: ["--core=430X"] cpp.entryPoint: "__program_start" cpp.driverLinkerFlags: [ "-D_STACK_SIZE=A0", "-D_DATA16_HEAP_SIZE=A0", "-D_DATA20_HEAP_SIZE=50", ] cpp.staticLibraries: [ // Explicitly link with the runtime dlib library (which contains // all required startup code and other stuff). cpp.toolchainInstallPath + "/../lib/dlib/dl430xlsfn.r43" ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR" prefix: "iar/" Group { name: "Linker Script" prefix: cpp.toolchainInstallPath + "/../config/linker/" fileTags: ["linkerscript"] // Explicitly use the default linker scripts for current target. files: ["lnk430f5529.xcl", "multiplier32.xcl"] } } // // GCC-specific properties and soucres. // Properties { condition: qbs.toolchain.contains("gcc") property path supportFilesPath // A path to the MSP430 support files, which are // provided by the Texas Instruments separately: // e.g. 'c:/msp430-gcc-support-files/include/' cpp.includePaths: supportFilesPath cpp.libraryPaths: supportFilesPath cpp.driverFlags: ["-mmcu=msp430f5529"] } // // Common code. // Group { name: "Gpio" files: ["gpio.c", "gpio.h"] } Group { name: "System" files: ["system.c", "system.h"] } files: [ "main.c", ] } qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/system.c0000644000175100017510000000523315232633614023263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "system.h" #if defined(__ICC430__) #include #elif defined(__GNUC__) #include #else #error "Unsupported toolchain" #endif void system_init(void) { // Stop watchdog timer. WDTCTL = WDTPW + WDTHOLD; } qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/main.c0000644000175100017510000000535215232633614022665 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "system.h" #include static void some_delay(uint32_t counts) { for (uint32_t index = 0u; index < counts; ++index) __asm("nop"); } int main(void) { system_init(); gpio_init_red_led(); while (1) { gpio_toggle_red_led(); some_delay(10000u); } } qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/system.h0000644000175100017510000000506615232633614023274 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SYSTEM_H #define SYSTEM_H #ifdef __cplusplus extern "C" { #endif void system_init(void); #ifdef __cplusplus } #endif #endif // SYSTEM_H qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/gpio.c0000644000175100017510000000566315232633614022704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #if defined(__ICC430__) #include #elif defined(__GNUC__) #include #else #error "Unsupported toolchain" #endif // LED pin number. #define GPIO_RED_LED_PIN_POS (0u) // LED port direction. #define GPIO_RED_LED_PORT_DIR (P1DIR) // LED output port. #define GPIO_RED_LED_PORT_OUT (P1OUT) void gpio_init_red_led(void) { GPIO_RED_LED_PORT_DIR |= (1u << GPIO_RED_LED_PIN_POS); } void gpio_toggle_red_led(void) { GPIO_RED_LED_PORT_OUT ^= (1u << GPIO_RED_LED_PIN_POS); } qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/README.md0000644000175100017510000000045715232633614023055 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different MSP430 toolchains. It is designed for the MSP-EXP430F5529LP target board (based on msp430f5529 chip) and simply flashes the red LED on the board. The following toolchains are supported: * IAR Embedded Workbench * GCC qbs-src-3.3.1/examples/baremetal/msp430f5529/redblink/gpio.h0000644000175100017510000000512615232633614022703 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GPIO_H #define GPIO_H #ifdef __cplusplus extern "C" { #endif void gpio_init_red_led(void); void gpio_toggle_red_led(void); #ifdef __cplusplus } #endif #endif // GPIO_H qbs-src-3.3.1/examples/baremetal/msp430f5529/msp430f5529.qbs0000644000175100017510000000507215232633614022232 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { name: "Examples for msp430f5529 board" references: [ "redblink/redblink.qbs", "nes-gamepads/nes-gamepads.qbs" ] } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/0000755000175100017510000000000015232633614022342 5ustar runnerrunnerqbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/hidep0.c0000644000175100017510000003464115232633614023667 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" #include "hwdefs.h" #include "usb.h" enum usb_ep0_action { STATUS_ACTION_NOTHING, STATUS_ACTION_DATA_IN }; struct usb_ep0 { uint8_t IEPCNFG; // Input ep0 configuration register. uint8_t IEPBCNT; // Input ep0 buffer byte count. uint8_t OEPCNFG; // Output ep0 configuration register. uint8_t OEPBCNT; // Output ep0 buffer byte count. }; struct usb_ep0_data { uint8_t data[EP_MAX_FIFO_SIZE]; uint16_t length; uint16_t offset; enum usb_ep0_action action; bool host_ask_more_data_than_available; }; #if defined(__ICC430__) #pragma location = 0x0920 // Input ep0 configuration address. __no_init struct usb_ep0 __data16 g_ep0; #pragma location = 0x2378 // Input ep0 buffer address. __no_init uint8_t __data16 g_ep0_in_buf[EP0_MAX_PACKET_SIZE]; #pragma location = 0x2380 // Setup packet block address. __no_init uint8_t __data16 g_setupdat[EP0_MAX_PACKET_SIZE]; #elif defined(__GNUC__) extern struct usb_ep0 g_ep0; extern uint8_t g_ep0_in_buf[EP0_MAX_PACKET_SIZE]; extern uint8_t g_setupdat[EP0_MAX_PACKET_SIZE]; #endif static volatile bool g_enumerated = false; static bool g_rwuen = false; static bool g_selfpwr = false; static struct usb_ep0_data g_ep0_response; static bool ep0_in_response_create(const uint8_t *data, uint16_t length) { if (sizeof(g_ep0_response.data) < length) return false; for (uint16_t i = 0; i < length; ++i) g_ep0_response.data[i] = data[i]; g_ep0_response.length = length; g_ep0_response.offset = 0; const uint16_t setup_length = (g_setupdat[7] << 8) | g_setupdat[6]; if (g_ep0_response.length >= setup_length) { g_ep0_response.length = setup_length; g_ep0_response.host_ask_more_data_than_available = false; } else { g_ep0_response.host_ask_more_data_than_available = true; } return true; } void ep0_in_frame_send(void) { uint8_t frame_size = 0; if (g_ep0_response.length != EP_NO_MORE_DATA) { if (g_ep0_response.length > EP0_MAX_PACKET_SIZE) { frame_size = EP0_MAX_PACKET_SIZE; g_ep0_response.length -= EP0_MAX_PACKET_SIZE; g_ep0_response.action = STATUS_ACTION_DATA_IN; } else if (g_ep0_response.length < EP0_MAX_PACKET_SIZE) { frame_size = g_ep0_response.length; g_ep0_response.length = EP_NO_MORE_DATA; g_ep0_response.action = STATUS_ACTION_NOTHING; } else { frame_size = EP0_MAX_PACKET_SIZE; if (g_ep0_response.host_ask_more_data_than_available) { g_ep0_response.length = 0; g_ep0_response.action = STATUS_ACTION_DATA_IN; } else { g_ep0_response.length = EP_NO_MORE_DATA; g_ep0_response.action = STATUS_ACTION_NOTHING; } } for (uint8_t i = 0; i < frame_size; ++i) { g_ep0_in_buf[i] = g_ep0_response.data[g_ep0_response.offset]; ++g_ep0_response.offset; } g_ep0.IEPBCNT = frame_size; } else { g_ep0_response.action = STATUS_ACTION_NOTHING; } } static bool ep0_dev_status_get(void) { uint16_t status = 0; if (g_selfpwr) status |= STATUS_SELF_POWERED; if (g_rwuen) status |= STATUS_REMOTE_WAKEUP; ep0_in_response_create((uint8_t *)&status, sizeof(status)); return true; } static bool ep0_iface_status_get(void) { uint16_t status = 0; ep0_in_response_create((uint8_t *)&status, sizeof(status)); return true; } static bool ep0_ep_status_get(void) { uint16_t status = 0; const uint8_t ep = hid_ep0_setup_lindex_get(); const uint8_t ep_num = ep & ~SETUP_DIR; if (ep_num == 0) { status = hid_ep0_in_is_stalled() ? 1 : 0; } else if ((ep_num == 1) && (ep & SETUP_DIR) == SETUP_INPUT) { // We support only one input ep1 in. status = hid_ep1_in_is_stalled() ? 1 : 0; } else { return false; } ep0_in_response_create((uint8_t *)&status, sizeof(status)); return true; } static bool ep0_get_status_proc(void) { const uint8_t bm_req_type = hid_ep0_setup_bm_request_type_get(); if ((bm_req_type & SETUP_DIR) != SETUP_INPUT) return false; const uint8_t recipient = bm_req_type & SETUP_RECIPIENT; switch (recipient) { case SETUP_DEVICE: return ep0_dev_status_get(); case SETUP_IFACE: return ep0_iface_status_get(); case SETUP_EP: return ep0_ep_status_get(); default: break; } return false; } static bool ep0_dev_feature_clear(void) { const uint8_t feature = hid_ep0_setup_lvalue_get(); if (feature != FEATURE_REMOTE_WAKEUP) return false; g_rwuen = false; return true; } static bool ep0_ep_feature_clear(void) { const uint8_t feature = hid_ep0_setup_lvalue_get(); if (feature != FEATURE_STALL) return false; const uint8_t ep = hid_ep0_setup_lindex_get(); const uint8_t ep_num = ep & ~SETUP_DIR; if (ep_num == 0) { // Do nothing. } else if ((ep_num == 1) && (ep & SETUP_DIR) == SETUP_INPUT) { // We support only one input ep1 in. hid_ep1_in_unstall(); } else { return false; } hid_ep0_in_clear(); return true; } static bool ep0_clear_feature_proc(void) { const uint8_t bm_req_type = hid_ep0_setup_bm_request_type_get(); if ((bm_req_type & SETUP_DIR) != SETUP_INPUT) return false; const uint8_t recipient = bm_req_type & SETUP_RECIPIENT; switch (recipient) { case SETUP_DEVICE: return ep0_dev_feature_clear(); case SETUP_EP: return ep0_ep_feature_clear(); default: break; } return false; } static bool ep0_dev_feature_set(void) { const uint8_t feature = hid_ep0_setup_lvalue_get(); switch (feature) { case FEATURE_REMOTE_WAKEUP: g_rwuen = true; return true; case FEATURE_TEST_MODE: // This is "test mode", just return the handshake. return true; default: break; } return false; } static bool ep0_ep_feature_set(void) { const uint8_t feature = hid_ep0_setup_lvalue_get(); if (feature != FEATURE_STALL) return false; const uint8_t ep = hid_ep0_setup_lindex_get(); const uint8_t ep_num = ep & ~SETUP_DIR; if (ep_num == 0) { // Do nothing. } else if ((ep_num == 1) && (ep & SETUP_DIR) == SETUP_INPUT) { // We support only one input ep1 in. hid_ep1_in_stall(); } else { return false; } hid_ep0_in_clear(); return true; } static bool ep0_set_feature_proc(void) { const uint8_t bm_req_type = hid_ep0_setup_bm_request_type_get(); switch (bm_req_type & SETUP_RECIPIENT) { case SETUP_DEVICE: return ep0_dev_feature_set(); case SETUP_EP: return ep0_ep_feature_set(); default: break; } return false; } static bool ep0_set_address_proc(void) { hid_ep0_out_stall(); const uint8_t address = hid_ep0_setup_lvalue_get(); if (address >= 128) return false; USBFUNADR = address; hid_ep0_in_clear(); return true; } static bool ep0_descriptor_proc(uint8_t type) { uint16_t length = 0; const uint8_t *pdesc = hid_ep0_desc_get(type, &length); if (!pdesc) return false; ep0_in_response_create(pdesc, length); return true; } static bool ep0_get_descriptor_proc(void) { const uint8_t descr_type = hid_ep0_setup_hvalue_get(); switch (descr_type) { case DESC_DEVICE: case DESC_CONF: case DESC_STRING: case DESC_DEVICE_QUAL: case DESC_OTHER_SPEED_CONF: case DESC_HID: case DESC_REPORT: return ep0_descriptor_proc(descr_type); } return false; } static bool ep0_get_config_proc(void) { // We only support configuration 1. const uint8_t cfg_num = HID_CONFIG_NUMBER; ep0_in_response_create(&cfg_num, sizeof(cfg_num)); return true; } static bool ep0_set_config_proc(void) { const uint8_t cfg_num = hid_ep0_setup_lvalue_get(); // We only support configuration 1. const bool is_valid = (cfg_num & HID_CONFIG_NUMBER); hid_ep0_enumerated_set(is_valid); return is_valid; } static bool ep0_get_iface_proc(void) { const uint8_t iface_num = hid_ep0_setup_lindex_get(); if (iface_num != HID_IFACE_NUMBER) return false; ep0_in_response_create(&iface_num, sizeof(iface_num)); return true; } static bool ep0_set_iface_proc(void) { const uint8_t iface_num = hid_ep0_setup_lindex_get(); if (iface_num != HID_IFACE_NUMBER) return false; const uint8_t alt_iface_num = hid_ep0_setup_lvalue_get(); if (alt_iface_num != HID_ALT_IFACE_NUMBER) return false; hid_ep0_out_stall(); hid_ep0_in_clear(); return true; } static bool ep0_std_proc(void) { const uint8_t request_code = hid_ep0_setup_request_get(); switch (request_code) { case SETUP_GET_STATUS: return ep0_get_status_proc(); case SETUP_CLEAR_FEATURE: return ep0_clear_feature_proc(); case SETUP_SET_FEATURE: return ep0_set_feature_proc(); case SETUP_SET_ADDRESS: return ep0_set_address_proc(); case SETUP_GET_DESCRIPTOR: return ep0_get_descriptor_proc(); case SETUP_GET_CONFIGURATION: return ep0_get_config_proc(); case SETUP_SET_CONFIGURATION: return ep0_set_config_proc(); case SETUP_GET_INTERFACE: return ep0_get_iface_proc(); case SETUP_SET_INTERFACE: return ep0_set_iface_proc(); default: break; } return false; } static bool ep0_setup(void) { const uint8_t bm_req_type = hid_ep0_setup_bm_request_type_get(); const uint8_t setup_type = bm_req_type & SETUP_TYPE; switch (setup_type) { case SETUP_STANDARD: return ep0_std_proc(); default: break; } return false; } static bool ep0_has_another_setup(void) { if ((USBIFG & STPOWIFG) != 0) { USBIFG &= ~(STPOWIFG | SETUPIFG); return true; } return false; } void hid_ep0_init(void) { hid_ep0_in_nak(); hid_ep0_out_nak(); g_ep0.IEPCNFG = UBME | STALL | USBIIE; g_ep0.OEPCNFG = UBME | STALL | USBIIE; // Enable only ep0in interrupts. USBIEPIE |= BIT0; } void hid_ep0_setup_handler(void) { USBCTL |= FRSTE; g_ep0_response.length = 0; g_ep0_response.offset = 0; g_ep0_response.action = STATUS_ACTION_NOTHING; g_ep0_response.host_ask_more_data_than_available = false; for (;;) { const uint8_t bm_req_type = hid_ep0_setup_bm_request_type_get(); if ((bm_req_type & SETUP_INPUT) == SETUP_INPUT) USBCTL |= DIR; else USBCTL &= ~DIR; const bool success = ep0_setup(); if (success) { hid_ep0_out_clear(); ep0_in_frame_send(); } else { hid_ep0_in_stall(); } if (!ep0_has_another_setup()) return; } } void hid_ep0_in_handler(void) { USBCTL |= FRSTE; hid_ep0_out_clear(); if (g_ep0_response.action == STATUS_ACTION_DATA_IN) ep0_in_frame_send(); else hid_ep0_in_stall(); } void hid_ep0_in_nak(void) { g_ep0.IEPBCNT = NAK; } void hid_ep0_in_stall(void) { g_ep0.IEPCNFG |= STALL; } void hid_ep0_in_clear(void) { g_ep0_response.length = EP_NO_MORE_DATA; g_ep0_response.action = STATUS_ACTION_NOTHING; g_ep0.IEPBCNT = 0; } bool hid_ep0_in_is_stalled(void) { return (g_ep0.IEPCNFG & STALL); } void hid_ep0_out_nak(void) { g_ep0.OEPBCNT = NAK; } void hid_ep0_out_stall(void) { g_ep0.OEPCNFG |= STALL; } void hid_ep0_out_clear(void) { g_ep0.OEPBCNT = 0; } uint8_t hid_ep0_setup_bm_request_type_get(void) { return g_setupdat[0]; } uint8_t hid_ep0_setup_request_get(void) { return g_setupdat[1]; } uint8_t hid_ep0_setup_lvalue_get(void) { return g_setupdat[2]; } uint8_t hid_ep0_setup_hvalue_get(void) { return g_setupdat[3]; } uint8_t hid_ep0_setup_lindex_get(void) { return g_setupdat[4]; } uint8_t hid_ep0_setup_hindex_get(void) { return g_setupdat[5]; } void hid_ep0_enumerated_set(bool enumerated) { g_enumerated = enumerated; } bool hid_ep0_is_enumerated(void) { return g_enumerated; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/wdt_a.h0000644000175100017510000000510715232633614023614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_WDT_A_H #define MSP430_WDT_A_H #ifdef __cplusplus extern "C" { #endif void wdt_a_stop(void); #ifdef __cplusplus } #endif #endif // MSP430_WDT_A_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/ucs.c0000644000175100017510000002105515232633614023303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hwdefs.h" #include "ucs.h" #if defined(__GNUC__) #define __delay_cycles(x) \ ({ \ for (uint16_t j = 0; j < x; j++) { \ __no_operation(); \ } \ }) #endif static uint16_t ucs_source_mask(enum ucs_source source) { switch (source) { case UCS_XT1CLK_SELECT: return SELM__XT1CLK; case UCS_VLOCLK_SELECT: return SELM__VLOCLK; case UCS_REFOCLK_SELECT: return SELM__REFOCLK; case UCS_DCOCLK_SELECT: return SELM__DCOCLK; case UCS_DCOCLKDIV_SELECT: return SELM__DCOCLKDIV; case UCS_XT2CLK_SELECT: return SELM__XT2CLK; default: break; } return SELM__XT1CLK; } static uint16_t ucs_divider_mask(enum ucs_divider divider) { switch (divider) { case UCS_CLOCK_DIVIDER_1: return DIVM__1; case UCS_CLOCK_DIVIDER_2: return DIVM__2; case UCS_CLOCK_DIVIDER_4: return DIVM__4; case UCS_CLOCK_DIVIDER_8: return DIVM__8; case UCS_CLOCK_DIVIDER_12: return DIVM__32; case UCS_CLOCK_DIVIDER_16: return DIVM__16; case UCS_CLOCK_DIVIDER_32: return DIVM__32; default: break; } return DIVM__1; } static void ucs_fll_init(uint16_t fsystem, uint16_t ratio) { const uint16_t sr_reg_backup = __get_SR_register() & SCG0; uint16_t mode = 0; uint16_t d = ratio; if (fsystem > 16000) { d >>= 1; mode = 1; } else { fsystem <<= 1; } uint16_t dco_div_bits = FLLD__2; while (d > 512) { dco_div_bits = dco_div_bits + FLLD0; d >>= 1; } // Disable FLL. __bis_SR_register(SCG0); // Set DCO to lowest tap. HWREG8(UCS_BASE + OFS_UCSCTL0_H) = 0; // Reset FN bits. HWREG16(UCS_BASE + OFS_UCSCTL2) &= ~(0x03FF); HWREG16(UCS_BASE + OFS_UCSCTL2) = dco_div_bits | (d - 1); if (fsystem <= 630) { // fsystem < 0.63MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_0; } else if (fsystem < 1250) { // 0.63MHz < fsystem < 1.25MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_1; } else if (fsystem < 2500) { // 1.25MHz < fsystem < 2.5MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_2; } else if (fsystem < 5000) { // 2.5MHz < fsystem < 5MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_3; } else if (fsystem < 10000) { // 5MHz < fsystem < 10MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_4; } else if (fsystem < 20000) { // 10MHz < fsystem < 20MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_5; } else if (fsystem < 40000) { // 20MHz < fsystem < 40MHz HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_6; } else { HWREG8(UCS_BASE + OFS_UCSCTL1) = DCORSEL_7; } // Re-enable FLL. __bic_SR_register(SCG0); while (HWREG8(UCS_BASE + OFS_UCSCTL7_L) & DCOFFG) { // Clear OSC fault flags. HWREG8(UCS_BASE + OFS_UCSCTL7_L) &= ~(DCOFFG); // Clear OFIFG fault flag. HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; } // Restore previous SCG0. __bis_SR_register(sr_reg_backup); if (mode == 1) { // Select DCOCLK because fsystem > 16000. HWREG16(UCS_BASE + OFS_UCSCTL4) &= ~(SELM_7 + SELS_7); HWREG16(UCS_BASE + OFS_UCSCTL4) |= SELM__DCOCLK + SELS__DCOCLK; } else { // Select DCODIVCLK. HWREG16(UCS_BASE + OFS_UCSCTL4) &= ~(SELM_7 + SELS_7); HWREG16(UCS_BASE + OFS_UCSCTL4) |= SELM__DCOCLKDIV + SELS__DCOCLKDIV; } } void ucs_init(enum ucs_signal signal, enum ucs_source source, enum ucs_divider divider) { uint16_t source_msk = ucs_source_mask(source); uint16_t divider_msk = ucs_divider_mask(divider); switch (signal) { case UCS_ACLK: HWREG16(UCS_BASE + OFS_UCSCTL4) &= ~SELA_7; source_msk |= source_msk << 8; HWREG16(UCS_BASE + OFS_UCSCTL4) |= source_msk; HWREG16(UCS_BASE + OFS_UCSCTL5) &= ~DIVA_7; divider_msk = divider_msk << 8; HWREG16(UCS_BASE + OFS_UCSCTL5) |= divider_msk; break; case UCS_SMCLK: HWREG16(UCS_BASE + OFS_UCSCTL4) &= ~SELS_7; source_msk = source_msk << 4; HWREG16(UCS_BASE + OFS_UCSCTL4) |= source_msk; HWREG16(UCS_BASE + OFS_UCSCTL5) &= ~DIVS_7; divider_msk = divider_msk << 4; HWREG16(UCS_BASE + OFS_UCSCTL5) |= divider_msk; break; case UCS_MCLK: HWREG16(UCS_BASE + OFS_UCSCTL4) &= ~SELM_7; HWREG16(UCS_BASE + OFS_UCSCTL4) |= source_msk; HWREG16(UCS_BASE + OFS_UCSCTL5) &= ~DIVM_7; HWREG16(UCS_BASE + OFS_UCSCTL5) |= divider_msk; break; case UCS_FLLREF: HWREG8(UCS_BASE + OFS_UCSCTL3) &= ~SELREF_7; source_msk = source_msk << 4; HWREG8(UCS_BASE + OFS_UCSCTL3) |= source_msk; HWREG8(UCS_BASE + OFS_UCSCTL3) &= ~FLLREFDIV_7; switch (divider) { case UCS_CLOCK_DIVIDER_12: HWREG8(UCS_BASE + OFS_UCSCTL3) |= FLLREFDIV__12; break; case UCS_CLOCK_DIVIDER_16: HWREG8(UCS_BASE + OFS_UCSCTL3) |= FLLREFDIV__16; break; default: HWREG8(UCS_BASE + OFS_UCSCTL3) |= divider_msk; break; } break; default: break; } } bool ucs_xt2_blocking_turn_on(uint16_t drive, uint16_t timeout) { // Check if drive value is expected one. if ((HWREG16(UCS_BASE + OFS_UCSCTL6) & XT2DRIVE_3) != drive) { // Clear XT2 drive field. HWREG16(UCS_BASE + OFS_UCSCTL6) &= ~XT2DRIVE_3; HWREG16(UCS_BASE + OFS_UCSCTL6) |= drive; } HWREG16(UCS_BASE + OFS_UCSCTL6) &= ~XT2BYPASS; // Switch on XT2 oscillator. HWREG16(UCS_BASE + OFS_UCSCTL6) &= ~XT2OFF; do { // Clear OSC fault Flags. HWREG8(UCS_BASE + OFS_UCSCTL7) &= ~XT2OFFG; // Clear OFIFG fault flag. HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; } while ((HWREG8(UCS_BASE + OFS_UCSCTL7) & XT2OFFG) && --timeout); return timeout > 0; } void ucs_xt2_turn_off(void) { HWREG16(UCS_BASE + OFS_UCSCTL6) |= XT2OFF; } void ucs_fll_settle_init(uint16_t fsystem, uint16_t ratio) { volatile uint16_t x = ratio * 32; ucs_fll_init(fsystem, ratio); while (x--) { __delay_cycles(30); } } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/main.c0000644000175100017510000000631715232633614023441 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hwdefs.h" #include "pmm.h" #include "ucs.h" #include "usb.h" #include "wdt_a.h" static void hw_clocks_init(uint32_t mclk_freq) { ucs_init(UCS_FLLREF, UCS_REFOCLK_SELECT, UCS_CLOCK_DIVIDER_1); ucs_init(UCS_ACLK, UCS_REFOCLK_SELECT, UCS_CLOCK_DIVIDER_1); ucs_fll_settle_init(mclk_freq / 1000, mclk_freq / 32768); // Use REFO for FLL and ACLK. UCSCTL3 = (UCSCTL3 & ~SELREF_7) | SELREF__REFOCLK; UCSCTL4 = (UCSCTL4 & ~SELA_7) | SELA__REFOCLK; } static void hw_init(void) { __disable_interrupt(); wdt_a_stop(); pmm_voltage_init(PMM_VOLTAGE_1_85V); hw_clocks_init(8000000); usb_init(); __enable_interrupt(); } static void hw_loop_exec(void) { for (;;) { usb_task(); } } int main(void) { hw_init(); hw_loop_exec(); return 0; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/hiddesc.c0000644000175100017510000002531715232633614024121 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hid.h" #include "usb.h" #include #define usb_word_msb_get(word) \ (uint8_t)(((uint16_t)(word) >> 8) & 0xFF) #define usb_word_lsb_get(word) \ (uint8_t)((uint16_t)(word) & 0xFF) enum usb_bcd_version { SPEC_BCD_VERSION = 0x0200, DEVICE_BCD_VERSION = 0x1234, HID_BCD_VERSION = 0x0111 }; enum usb_ids { DEVICE_VID = 0xFFFF, DEVICE_PID = 0xFFFF }; enum usb_lang_id { LANG_ID = 0x0409 }; enum usb_descriptor_string_index { DESC_LANGID_STRING_INDEX = 0, DESC_MFG_STRING_INDEX, DESC_PRODUCT_STRING_INDEX, DESC_SERIAL_STRING_INDEX }; enum usb_descr_length { // Standard length. DESC_DEVICE_LEN = 18, DESC_DEVICE_QUAL_LEN = 10, DESC_CONF_LEN = 9, DESC_OTHER_SPEED_CONF_LEN = 9, DESC_INTERFACE_LEN = 9, DESC_HID_LEN = 9, DESCR_HID_REP_LEN = 56, DESC_ENDPOINT_LEN = 7, // Total length. DESC_DEVICE_TOTAL_LEN = DESC_DEVICE_LEN, DESC_DEVICE_QUAL_TOTAL_LEN = DESC_DEVICE_QUAL_LEN, DESC_CONF_TOTAL_LEN = DESC_CONF_LEN + DESC_INTERFACE_LEN + DESC_HID_LEN + DESC_ENDPOINT_LEN, DESC_OTHER_SPEED_CONF_TOTAL_LEN = DESC_OTHER_SPEED_CONF_LEN + DESC_INTERFACE_LEN, DESCR_HID_REP_TOTAL_LEN = DESCR_HID_REP_LEN }; enum usb_descr_attributes { // Attributes (b7 - buspwr, b6 - selfpwr, b5 - rwu). USB_DESC_ATTRIBUTES = 0xA0, // 100 mA (div 2). USB_DESC_POWER_CONSUMPTION = 50 }; enum usb_descr_numbers { USB_DESC_CONFIG_COUNT = 1 }; static const uint8_t g_hid_report_desc[DESCR_HID_REP_TOTAL_LEN] = { // Pad #1 configuration. 0x05, 0x01, // Usage page (Generic Desktop). 0x09, 0x05, // Usage (Game Pad). 0xa1, 0x01, // Collection (Application). 0xa1, 0x00, // Collection (Physical). 0x85, HID_REPORT_ID_GAMEPAD1, // Report id (1). 0x05, 0x09, // Usage page (Button). 0x19, 0x01, // Usage minimum (Button 1). 0x29, 0x08, // Usage maximum (Button 8). 0x15, 0x00, // Logical minimum (0). 0x25, 0x01, // Logical maximum (1). 0x95, HID_REPORT_BITS_COUNT, // Report count (8). 0x75, 0x01, // Report size (1). 0x81, 0x02, // Input (Data,Var,Abs). 0xc0, // End collection. 0xc0, // End collection. // Pad #2 configuration. 0x05, 0x01, // Usage page (Generic Desktop). 0x09, 0x05, // Usage (Game Pad). 0xa1, 0x01, // Collection (Application). 0xa1, 0x00, // Collection (Physical). 0x85, HID_REPORT_ID_GAMEPAD2, // Report id (2). 0x05, 0x09, // Usage page (Button). 0x19, 0x01, // Usage minimum (Button 1). 0x29, 0x08, // Usage maximum (Button 8). 0x15, 0x00, // Logical minimum (0). 0x25, 0x01, // Logical maximum (1). 0x95, HID_REPORT_BITS_COUNT, // Report count (8). 0x75, 0x01, // Report size (1). 0x81, 0x02, // Input (Data,Var,Abs). 0xc0, // End collection 0xc0 // End collection. }; static const uint8_t g_device_desc[DESC_DEVICE_TOTAL_LEN] = { DESC_DEVICE_LEN, // Descriptor length. DESC_DEVICE, // Descriptor type. usb_word_lsb_get(SPEC_BCD_VERSION), // USB BCD version, lo. usb_word_msb_get(SPEC_BCD_VERSION), // USB BCD version, hi. 0x00, // Device class. 0x00, // Device sub-class. 0x00, // Device protocol. EP0_MAX_PACKET_SIZE, // Maximum packet size (ep0 size). usb_word_lsb_get(DEVICE_VID), // Vendor ID, lo. usb_word_msb_get(DEVICE_VID), // Vendor ID, hi. usb_word_lsb_get(DEVICE_PID), // Product ID, lo. usb_word_msb_get(DEVICE_PID), // Product ID, hi. usb_word_lsb_get(DEVICE_BCD_VERSION), // Device BCD version, lo. usb_word_msb_get(DEVICE_BCD_VERSION), // Device BCD version, hi. DESC_MFG_STRING_INDEX, DESC_PRODUCT_STRING_INDEX, DESC_SERIAL_STRING_INDEX, USB_DESC_CONFIG_COUNT // Configurations count. }; static const uint8_t g_device_qual_desc[DESC_DEVICE_QUAL_TOTAL_LEN] = { DESC_DEVICE_QUAL_LEN, // Descriptor length. DESC_DEVICE_QUAL, // Descriptor type. usb_word_lsb_get(SPEC_BCD_VERSION), // USB BCD version, lo. usb_word_msb_get(SPEC_BCD_VERSION), // USB BCD version, hi. 0x00, // Device class. 0x00, // Device sub-class. 0x00, // Device protocol. EP0_MAX_PACKET_SIZE, // Maximum packet size (ep0 size). USB_DESC_CONFIG_COUNT, // Configurations count. 0x00 // Reserved. }; static const uint8_t g_config_desc[DESC_CONF_TOTAL_LEN] = { DESC_CONF_LEN, // Descriptor length. DESC_CONF, // Descriptor type. usb_word_lsb_get(DESC_CONF_TOTAL_LEN), // Total length, lo. usb_word_msb_get(DESC_CONF_TOTAL_LEN), // Total length, hi. 0x01, // Interfaces count. HID_CONFIG_NUMBER, // Configuration number. 0x00, // Configuration string index. USB_DESC_ATTRIBUTES, // Attributes. USB_DESC_POWER_CONSUMPTION, // Power consumption. // Interface descriptor. DESC_INTERFACE_LEN, // Descriptor length. DESC_INTERFACE, // Descriptor type. HID_IFACE_NUMBER, // Zero-based index of this interfacce. HID_ALT_IFACE_NUMBER, // Alternate setting. 0x01, // End points count (ep1 in). 0x03, // Class code (HID). 0x00, // Subclass code (boot). 0x00, // Protocol code (none). 0x00, // Interface string descriptor index. // HID descriptor. DESC_HID_LEN, // Descriptor length. DESC_HID, // Descriptor type. usb_word_lsb_get(HID_BCD_VERSION), // HID class BCD version, lo. usb_word_msb_get(HID_BCD_VERSION), // HID class BCD version, hi. 0x00, // Country code (HW country code). 0x01, // Number of HID class descriptors to follow. DESC_REPORT, // Repord descriptor type (HID). usb_word_lsb_get(DESCR_HID_REP_LEN), // Report descriptor total length, lo. usb_word_msb_get(DESCR_HID_REP_LEN), // Report descriptor total length, hi. // End point descriptor. DESC_ENDPOINT_LEN, // Descriptor length. DESC_ENDPOINT, // Descriptor type. HID_EP_IN, // End point address (ep1 in). 0x03, // End point type (interrupt). usb_word_lsb_get(EP_MAX_PACKET_SIZE), // Maximum packet size, lo (ep1 size). usb_word_msb_get(EP_MAX_PACKET_SIZE), // Maximum packet size, hi (ep1 size). 0x01 // Polling interval (1 ms). }; static const uint8_t g_lang_id_desc[] = { 0x04, // Descriptor length. DESC_STRING, // Descriptor type. usb_word_lsb_get(LANG_ID), // Language id, lo. usb_word_msb_get(LANG_ID) // Language id, hi. }; static const uint8_t g_manuf_str_desc[] = { 0x18, // Descriptor length. DESC_STRING, // Descriptor type. // Unicode string: 'Q', 0, 'B', 0, 'S', 0, ' ', 0, 'e', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0 }; static const uint8_t g_product_str_desc[] = { 0x1A, // Descriptor length. DESC_STRING, // Descriptor type. // Unicode string: 'N', 0, 'E', 0, 'S', 0, ' ', 0, 'G', 0, 'a', 0, 'm', 0, 'e', 0, 'P', 0, 'a', 0, 'd', 0, 's', 0 }; static const uint8_t g_serialno_str_desc[] = { 0x1A, // Descriptor length. DESC_STRING, // Descriptor type. // Unicode string: '0', 0 ,'1', 0, '0', 0, '2', 0, '0', 0, '3', 0, '0', 0, '4', 0, '0', 0, '5', 0, '0', 0, '6', 0 }; static const uint8_t *ep0_string_desc_get(uint16_t *length) { const uint8_t index = hid_ep0_setup_lvalue_get(); switch (index) { case DESC_LANGID_STRING_INDEX: *length = sizeof(g_lang_id_desc); return g_lang_id_desc; case DESC_MFG_STRING_INDEX: *length = sizeof(g_manuf_str_desc); return g_manuf_str_desc; case DESC_PRODUCT_STRING_INDEX: *length = sizeof(g_product_str_desc); return g_product_str_desc; case DESC_SERIAL_STRING_INDEX: *length = sizeof(g_serialno_str_desc); return g_serialno_str_desc; default: break; } return 0; } const uint8_t *hid_ep0_desc_get(uint8_t type, uint16_t *length) { switch (type) { case DESC_DEVICE: *length = DESC_DEVICE_TOTAL_LEN; return g_device_desc; case DESC_CONF: *length = DESC_CONF_TOTAL_LEN; return g_config_desc; case DESC_STRING: return ep0_string_desc_get(length); case DESC_DEVICE_QUAL: *length = DESC_DEVICE_QUAL_TOTAL_LEN; return g_device_qual_desc; case DESC_HID: *length = DESC_HID_LEN; return &g_config_desc[DESC_CONF_LEN + DESC_INTERFACE_LEN]; case DESC_REPORT: *length = DESCR_HID_REP_TOTAL_LEN; return g_hid_report_desc; default: break; } return 0; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/hidep1.c0000644000175100017510000001500415232633614023660 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "hid.h" #include "hwdefs.h" #include "usb.h" // We use this empirical value to make a GPIO polling // every ~10 msec (rough). It is a simplest way, because // instead we need to use a timers with interrupts callbacks. enum { POLLING_COUNTER = 888 }; // Pins on the port 6. enum gpio_pins { GPIO_CLK_PIN = BIT0, GPIO_DATA1_PIN = BIT1, GPIO_DATA2_PIN = BIT2, GPIO_LATCH_PIN = BIT3, }; struct usb_ep { uint8_t EPCNF; // Endpoint configuration. uint8_t EPBBAX; // Endpoint X buffer base address. uint8_t EPBCTX; // Endpoint X Buffer byte count. uint8_t SPARE0; // No used. uint8_t SPARE1; // No used. uint8_t EPBBAY; // Endpoint Y buffer Base address. uint8_t EPBCTY; // Endpoint Y buffer byte count. uint8_t EPSIZXY; // Endpoint XY buffer size. }; #if defined(__ICC430__) #pragma location = 0x23C8 // Input ep1 configuration address. __no_init struct usb_ep __data16 g_ep1_in; #pragma location = 0x1C80 // Input ep1 X-buffer address. __no_init uint8_t __data16 g_ep1_in_xbuf[EP_MAX_PACKET_SIZE]; #elif defined(__GNUC__) extern struct usb_ep g_ep1_in; extern uint8_t g_ep1_in_xbuf[EP_MAX_PACKET_SIZE]; #endif static struct { const uint8_t data_pin; const uint8_t id; uint8_t buttons; bool ready; } g_reports[HID_REPORTS_COUNT] = { {GPIO_DATA1_PIN, HID_REPORT_ID_GAMEPAD1, 0, false}, {GPIO_DATA2_PIN, HID_REPORT_ID_GAMEPAD2, 0, false} }; static uint16_t g_poll_counter = 0; // Pulse width around ~10 usec. static void ep1_latch_pulse(void) { gpio_pins_set_high(GPIO_PORT_P6, GPIO_LATCH_PIN); gpio_pins_set_low(GPIO_PORT_P6, GPIO_LATCH_PIN); } // Pulse width around ~10 usec. static void ep1_clk_pulse(void) { gpio_pins_set_high(GPIO_PORT_P6, GPIO_CLK_PIN); gpio_pins_set_low(GPIO_PORT_P6, GPIO_CLK_PIN); } static void ep1_reports_clean(void) { for (uint8_t index = 0; index < HID_REPORTS_COUNT; ++index) { g_reports[index].buttons = 0; g_reports[index].ready = false; } } static void ep1_reports_update(void) { for (uint8_t index = 0; index < HID_REPORTS_COUNT; ++index) g_reports[index].ready = true; } static void ep1_gamepads_poll(void) { ep1_reports_clean(); ep1_latch_pulse(); for (uint8_t pos = 0; pos < HID_REPORT_BITS_COUNT; ++pos) { // TODO: Add some nops here? for (uint8_t index = 0; index < HID_REPORTS_COUNT; ++index) { const uint8_t pin = g_reports[index].data_pin; const enum gpio_pin_status st = gpio_pin_get(GPIO_PORT_P6, pin); // Low state means that a button is pressed. const bool v = (st == GPIO_INPUT_PIN_LOW); g_reports[index].buttons |= (v << pos); } ep1_clk_pulse(); } ep1_reports_update(); } static void ep1_report_send(uint8_t report_index) { if (!g_reports[report_index].ready) return; if ((g_ep1_in.EPBCTX & NAK) == 0) return; g_ep1_in_xbuf[0] = g_reports[report_index].id; g_ep1_in_xbuf[1] = g_reports[report_index].buttons; g_ep1_in.EPBCTX = 2; g_reports[report_index].ready = false; } void hid_ep1_init(void) { enum { USBSTABUFF_ADDRESS = 0x1C00, // Start of buffer space address. USBIEPBBAX_1_ADDRESS = 0x1C80 // Input ep1 X-buffer address. }; g_ep1_in.EPCNF = UBME | USBIIE; g_ep1_in.EPBBAX = ((USBIEPBBAX_1_ADDRESS - USBSTABUFF_ADDRESS) >> 3) & 0x00FF; g_ep1_in.EPBCTX = NAK; g_ep1_in.EPSIZXY = EP_MAX_PACKET_SIZE; gpio_pins_set_as_out(GPIO_PORT_P6, GPIO_CLK_PIN | GPIO_LATCH_PIN); gpio_pins_set_as_in(GPIO_PORT_P6, GPIO_DATA1_PIN | GPIO_DATA2_PIN); } void hid_ep1_task(void) { if (!hid_ep0_is_enumerated()) return; for (uint8_t index = 0; index < HID_REPORTS_COUNT; ++index) ep1_report_send(index); if (g_poll_counter <= POLLING_COUNTER) { ++g_poll_counter; } else { g_poll_counter = 0; ep1_gamepads_poll(); } } void hid_ep1_in_stall(void) { g_ep1_in.EPCNF |= STALL; } void hid_ep1_in_unstall(void) { g_ep1_in.EPCNF &= ~(STALL | TOGGLE); } bool hid_ep1_in_is_stalled(void) { return (g_ep1_in.EPCNF & STALL); } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/ucs.h0000644000175100017510000000661715232633614023317 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_UCS_H #define MSP430_UCS_H #ifdef __cplusplus extern "C" { #endif enum ucs_signal { UCS_ACLK = 0x01, UCS_MCLK = 0x02, UCS_SMCLK = 0x04, UCS_FLLREF = 0x08 }; enum ucs_source { UCS_XT1CLK_SELECT, UCS_VLOCLK_SELECT, UCS_REFOCLK_SELECT, UCS_DCOCLK_SELECT, UCS_DCOCLKDIV_SELECT, UCS_XT2CLK_SELECT }; enum ucs_divider { UCS_CLOCK_DIVIDER_1, UCS_CLOCK_DIVIDER_2, UCS_CLOCK_DIVIDER_4, UCS_CLOCK_DIVIDER_8, UCS_CLOCK_DIVIDER_12, UCS_CLOCK_DIVIDER_16, UCS_CLOCK_DIVIDER_32 }; enum ucs_fault_flag { UCS_XT2OFFG, UCS_XT1HFOFFG, UCS_XT1LFOFFG, UCS_DCOFFG }; void ucs_clocks_init(void); void ucs_init(enum ucs_signal signal, enum ucs_source source, enum ucs_divider divider); bool ucs_xt2_blocking_turn_on(uint16_t drive, uint16_t timeout); void ucs_xt2_turn_off(void); void ucs_fll_settle_init(uint16_t fsystem, uint16_t ratio); #ifdef __cplusplus } #endif #endif // MSP430_UCS_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/pmm.h0000644000175100017510000000534315232633614023311 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_PMM_H #define MSP430_PMM_H #include #ifdef __cplusplus extern "C" { #endif enum ppm_voltage { PMM_VOLTAGE_1_35V, PMM_VOLTAGE_1_55V, PMM_VOLTAGE_1_75V, PMM_VOLTAGE_1_85V }; bool pmm_voltage_init(enum ppm_voltage voltage); #ifdef __cplusplus } #endif #endif // MSP430_PMM_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/usb.c0000644000175100017510000002064415232633614023305 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gpio.h" #include "hid.h" #include "hwdefs.h" #include "ucs.h" #include "usb.h" static uint16_t usb_khz_freq_get(void) { uint16_t freq = 0; const uint8_t selm_curr = (UCSCTL4_L & SELM_7); if (selm_curr <= 4) { uint16_t fll_ref_freq = 33; // It is 32.768 kHz. if ((UCSCTL3_L & SELREF_7) >= 0x50) fll_ref_freq = (4.0) * 1000; uint16_t flln_curr = (UCSCTL2 & 0x03FF) + 1; if (selm_curr == SELM_3) { uint16_t flld_curr = (UCSCTL2 & FLLD_7); flld_curr >>= 12; flln_curr <<= flld_curr; } const uint8_t fll_ref_div = (UCSCTL3_L & FLLREFDIV_7); if (fll_ref_div == 0) freq = flln_curr * (fll_ref_freq / 1); else if (fll_ref_div == 1) freq = flln_curr * (fll_ref_freq / 2); else if (fll_ref_div == 2) freq = flln_curr * (fll_ref_freq / 4); else if (fll_ref_div == 3) freq = flln_curr * (fll_ref_freq / 8); else if (fll_ref_div == 4) freq = flln_curr * (fll_ref_freq / 12); else if (fll_ref_div == 5) freq = flln_curr * (fll_ref_freq / 16); } else { freq = (4.0) * 1000; } return freq >> (UCSCTL5_L & DIVM_7); } static uint16_t usb_delay_250us_get(void) { const uint16_t mclk_freq = usb_khz_freq_get(); const uint16_t delay_250us = ((mclk_freq >> 6) | (mclk_freq >> 7) | (mclk_freq >> 9)); return delay_250us; } static void usb_cfg_access_allow(bool allow) { enum { ALLOW_KEY = 0x9628, DENIED_KEY = 0x9600 }; USBKEYPID = allow ? ALLOW_KEY : DENIED_KEY; } static bool usb_pll_enable(void) { if (!(USBPWRCTL & USBBGVBV)) return false; if ((USBCNF & USB_EN) && (USBPLLCTL & UPLLEN)) return true; gpio_pins_set_as_pf_out(GPIO_PORT_P5, GPIO_PIN2); gpio_pins_set_as_pf_out(GPIO_PORT_P5, GPIO_PIN3); usb_cfg_access_allow(true); if (!ucs_xt2_blocking_turn_on(XT2DRIVE_0, 50000)) return false; USBPLLDIVB = USBPLL_SETCLK_4_0; USBPLLCTL = UPFDEN | UPLLEN; const uint16_t delay_250us = usb_delay_250us_get(); uint8_t j = 0; do { USBPLLIR = 0; for (uint8_t k = 0; k < 2; ++k) { for (uint16_t i = 0; i < delay_250us; ++i) { __no_operation(); } } if (j++ > 10) { usb_cfg_access_allow(false); return false; } } while (USBPLLIR != 0); USBCNF |= USB_EN; usb_cfg_access_allow(false); return true; } static void usb_reset(void) { usb_cfg_access_allow(true); hid_ep0_enumerated_set(false); USBCTL = 0; USBFUNADR = 0; USBOEPIE = 0; USBIEPIE = 0; hid_ep0_init(); hid_ep1_init(); USBCTL = FEN; USBIFG = 0; USBIE = SETUPIE | RSTRIE | SUSRIE; usb_cfg_access_allow(false); } static void usb_connect(void) { usb_cfg_access_allow(true); USBCNF |= PUR_EN; USBPWRCTL |= VBOFFIE; usb_cfg_access_allow(false); } static void usb_pwr_vbus_wait(void) { const uint16_t delay_250us = usb_delay_250us_get(); for (uint8_t j = 0; j < 4; ++j) { for (uint16_t i = 0; i < delay_250us; ++i) { __no_operation(); } } } static void usb_pwr_vbus_on_handler(void) { usb_pwr_vbus_wait(); if (USBPWRCTL & USBBGVBV) { usb_cfg_access_allow(true); USBPWRCTL |= VBOFFIE; USBPWRCTL &= ~ (VBONIFG + VBOFFIFG); usb_cfg_access_allow(false); } } static void usb_pwr_vbus_off_handler(void) { usb_pwr_vbus_wait(); if (!(USBPWRCTL & USBBGVBV)) { usb_cfg_access_allow(true); USBCNF = 0; USBPLLCTL &= ~UPLLEN; USBPWRCTL &= ~(VBOFFIE + VBOFFIFG + SLDOEN); usb_cfg_access_allow(false); } } void usb_suspend(void) { usb_cfg_access_allow(true); USBCTL |= FRSTE; USBIFG &= ~SUSRIFG; USBPLLCTL &= ~UPLLEN; ucs_xt2_turn_off(); USBIE = RESRIE; usb_cfg_access_allow(false); } void usb_resume(void) { usb_pll_enable(); USBIFG &= ~(RESRIFG | SUSRIFG); USBIE = SETUPIE | RSTRIE | SUSRIE; } void usb_init(void) { const uint16_t gie_backup = (__get_SR_register() & GIE); usb_cfg_access_allow(true); USBPHYCTL = PUSEL; USBPWRCTL = VUSBEN | SLDOAON; const uint16_t delay_250us = usb_delay_250us_get(); for (uint8_t j = 0; j < 20; ++j) { for (uint16_t i = 0; i < delay_250us; ++i) { __no_operation(); } } USBPWRCTL |= VBONIE; usb_cfg_access_allow(false); __bis_SR_register(gie_backup); if (USBPWRCTL & USBBGVBV) { if (usb_pll_enable()) { usb_reset(); usb_connect(); } } } void usb_task(void) { hid_ep1_task(); } INTERRUPT(usb_ubm_isr, USB_UBM_VECTOR) { bool wake_up = false; if (USBIFG & SETUPIFG) { hid_ep0_setup_handler(); USBIFG &= ~SETUPIFG; } switch (__even_in_range(USBVECINT & 0x3F, USBVECINT_OUTPUT_ENDPOINT7)) { case USBVECINT_PWR_DROP: __no_operation(); break; case USBVECINT_PLL_RANGE: wake_up = true; break; case USBVECINT_PWR_VBUSOn: usb_pwr_vbus_on_handler(); if (usb_pll_enable()) { usb_reset(); usb_connect(); } wake_up = true; break; case USBVECINT_PWR_VBUSOff: usb_pwr_vbus_off_handler(); ucs_xt2_turn_off(); wake_up = true; break; case USBVECINT_INPUT_ENDPOINT0: hid_ep0_in_handler(); break; case USBVECINT_RSTR: usb_reset(); wake_up = true; break; case USBVECINT_SUSR: usb_suspend(); wake_up = true; break; case USBVECINT_RESR: usb_resume(); wake_up = true; break; case USBVECINT_SETUP_PACKET_RECEIVED: hid_ep0_in_nak(); hid_ep0_out_nak(); hid_ep0_setup_handler(); break; default: break; } if (wake_up) { __bic_SR_register_on_exit(LPM3_bits); __no_operation(); } } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/gpio.c0000644000175100017510000001327315232633614023452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hwdefs.h" #include "gpio.h" enum { INVALID_ADDRESS = 0xFFFF }; static uint16_t gpio_port_address_get(enum gpio_port port) { switch (port) { case GPIO_PORT_P1: return P1_BASE; case GPIO_PORT_P2: return P2_BASE; case GPIO_PORT_P3: return P3_BASE; case GPIO_PORT_P4: return P4_BASE; case GPIO_PORT_P5: return P5_BASE; case GPIO_PORT_P6: return P6_BASE; case GPIO_PORT_P7: return P7_BASE; case GPIO_PORT_P8: return P8_BASE; case GPIO_PORT_PJ: return PJ_BASE; default: break; } return INVALID_ADDRESS; } static uint16_t gpio_pins_adjust(enum gpio_port port, uint16_t pins) { if ((port & 1) ^ 1) pins <<= 8; return pins; } void gpio_pins_set_as_out(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PASEL) &= ~pins; HWREG16(base_address + OFS_PADIR) |= pins; } void gpio_pins_set_as_in(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PASEL) &= ~pins; HWREG16(base_address + OFS_PADIR) &= ~pins; HWREG16(base_address + OFS_PAREN) &= ~pins; } void gpio_pins_set_as_pf_out(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PADIR) |= pins; HWREG16(base_address + OFS_PASEL) |= pins; } void gpio_pins_set_as_pf_in(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PADIR) &= ~pins; HWREG16(base_address + OFS_PASEL) |= pins; } void gpio_pins_set_high(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PAOUT) |= pins; } void gpio_pins_set_low(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PAOUT) &= ~pins; } void gpio_pins_toggle(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return; pins = gpio_pins_adjust(port, pins); HWREG16(base_address + OFS_PAOUT) ^= pins; } enum gpio_pin_status gpio_pin_get(enum gpio_port port, uint16_t pins) { const uint16_t base_address = gpio_port_address_get(port); if (base_address == INVALID_ADDRESS) return GPIO_INPUT_PIN_LOW; pins = gpio_pins_adjust(port, pins); const uint16_t value = HWREG16(base_address + OFS_PAIN) & pins; return (value > 0) ? GPIO_INPUT_PIN_HIGH : GPIO_INPUT_PIN_LOW; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/gamepads.ld0000644000175100017510000000526715232633614024456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ g_setupdat = 0x2380; /* Setup packet block address. */ g_ep0 = 0x0920; /* Input ep0 configuration address. */ g_ep0_in_buf = 0x2378; /* Input ep0 buffer address. */ g_ep1_in = 0x23C8; /* Input ep1 configuration address. */ g_ep1_in_xbuf = 0x1C80; /* Ep1 X-buffer address. */ qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/wdt_a.c0000644000175100017510000000522415232633614023607 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hwdefs.h" #include "wdt_a.h" #define WDT_CONTROL_ADDRESS (WDT_A_BASE + OFS_WDTCTL) void wdt_a_stop(void) { const uint8_t st = (HWREG16(WDT_CONTROL_ADDRESS) & 0x00FF) | WDTHOLD; HWREG16(WDT_CONTROL_ADDRESS) = WDTPW + st; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/usb.h0000644000175100017510000001233515232633614023310 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_USB_H #define MSP430_USB_H #ifdef __cplusplus extern "C" { #endif enum usb_setup_bmreq_bits { SETUP_DIR = 0x80, SETUP_TYPE = 0x60, SETUP_RECIPIENT = 0x1F }; // Setup request direction. enum usb_setup_req_direction_bits { SETUP_OUTPUT = 0, // From host to device direction. SETUP_INPUT = 0x80 // From device to host direction. }; // Setup request type. enum usb_setup_req_type_bits { SETUP_STANDARD = 0, // Standard request. SETUP_CLASS = 0x20, // Class request. SETUP_VENDOR = 0x40 // Vendor request. }; // Setup request recipient. enum usb_setup_req_recipient_bits { SETUP_DEVICE = 0, // Device recipient. SETUP_IFACE = 0x01, // Interface recipient. SETUP_EP = 0x02, // End point recipient. SETUP_OTHER = 0x03 // Other recipient. }; // Setup request code. enum usb_setup_req_code { SETUP_GET_STATUS = 0x00, // Get status code. SETUP_CLEAR_FEATURE = 0x01, // Clear feature code. SETUP_RESERVED1 = 0x02, // Reserved code. SETUP_SET_FEATURE = 0x03, // Set feature code. SETUP_RESERVED2 = 0x04, // Reserved code. SETUP_SET_ADDRESS = 0x05, // Set address code. SETUP_GET_DESCRIPTOR = 0x06, // Get descriptor code. SETUP_SET_DESCRIPTOR = 0x07, // Set descriptor code. SETUP_GET_CONFIGURATION = 0x08, // Get configuration code. SETUP_SET_CONFIGURATION = 0x09, // Set configuration code. SETUP_GET_INTERFACE = 0x0A, // Get interface code. SETUP_SET_INTERFACE = 0x0B, // Set interface code. SETUP_SYNC_FRAME = 0x0C, // Sync frame code. SETUP_ANCHOR_LOAD = 0xA0 // Anchor load code. }; // Standard status responses. enum usb_setup_status_code { STATUS_SELF_POWERED = 0x01, STATUS_REMOTE_WAKEUP = 0x02 }; // Standard feature selectors. enum usb_setup_feature_selector { FEATURE_STALL = 0x00, FEATURE_REMOTE_WAKEUP = 0x01, FEATURE_TEST_MODE = 0x02 }; // Get descriptor codes. enum usb_setup_get_descriptor_code { DESC_DEVICE = 0x01, // Device descriptor. DESC_CONF = 0x02, // Configuration descriptor. DESC_STRING = 0x03, // String descriptor. DESC_INTERFACE = 0x04, // Interface descriptor. DESC_ENDPOINT = 0x05, // End point descriptor. DESC_DEVICE_QUAL = 0x06, // Device qualifier descriptor. DESC_OTHER_SPEED_CONF = 0x07, // Other configuration descriptor. DESC_INTERFACE_POWER = 0x08, // Interface power descriptor. DESC_OTG = 0x09, // OTG descriptor. DESC_DEBUG = 0x0A, // Debug descriptor. DESC_INTERFACE_ASSOC = 0x0B, // Interface association descriptor. DESC_HID = 0x21, // Get HID descriptor. DESC_REPORT = 0x22 // Get report descriptor. }; enum usb_ep_size { EP0_MAX_PACKET_SIZE = 8, EP_MAX_PACKET_SIZE = 64, EP_MAX_FIFO_SIZE = 256, EP_NO_MORE_DATA = 0xFFFF }; void usb_init(void); void usb_task(void); #ifdef __cplusplus } #endif #endif // MSP430_USB_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/pmm.c0000644000175100017510000002155315232633614023305 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "hwdefs.h" #include "pmm.h" #define PMMCTL0_H_ADDRESS (PMM_BASE + OFS_PMMCTL0_H) #define PMMCTL0_L_ADDRESS (PMM_BASE + OFS_PMMCTL0_L) #define PMMRIE_ADDRESS (PMM_BASE + OFS_PMMRIE) #define PMMIFG_ADDRESS (PMM_BASE + OFS_PMMIFG) #define SVSMHCTL_ADDRESS (PMM_BASE + OFS_SVSMHCTL) #define SVSMLCTL_ADDRESS (PMM_BASE + OFS_SVSMLCTL) #define PMM_OTHER_BITSL \ (SVSLRVL0 | SVSLRVL1 | SVSMLRRL0 | SVSMLRRL1 | SVSMLRRL2) #define PMM_OTHER_BITSH \ (SVSHRVL0 | SVSHRVL1 | SVSMHRRL0 | SVSMHRRL1 | SVSMHRRL2) #define PMM_CLEANUP_FLAGS \ (SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG) static void pmm_write_access_allow(bool allow) { HWREG8(PMMCTL0_H_ADDRESS) = allow ? PMMPW_H : 0; } static void pmm_interrupt_flags_clear(uint16_t flags) { HWREG16(PMMIFG_ADDRESS) &= ~flags; } static void pmm_interrupt_flags_wait(uint16_t flags) { while ((HWREG16(PMMIFG_ADDRESS) & flags) == 0) { ; } } static uint8_t pmm_level_mask(enum ppm_voltage voltage) { switch (voltage) { case PMM_VOLTAGE_1_35V: return PMMCOREV_0; case PMM_VOLTAGE_1_55V: return PMMCOREV_1; case PMM_VOLTAGE_1_75V: return PMMCOREV_2; case PMM_VOLTAGE_1_85V: return PMMCOREV_3; default: break; } return PMMCOREV_0; } static bool pmm_voltage_set_up(uint8_t level) { pmm_write_access_allow(true); // Disable interrupts and backup all registers. uint16_t pmmrie_backup = HWREG16(PMMRIE_ADDRESS); HWREG16(PMMRIE_ADDRESS) &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE | SVSLPE | SVMHVLRIE | SVMHIE | SVSMHDLYIE | SVMLVLRIE | SVMLIE | SVSMLDLYIE); uint16_t svsmhctl_backup = HWREG16(SVSMHCTL_ADDRESS); uint16_t svsmlctl_backup = HWREG16(SVSMLCTL_ADDRESS); // Clear all interrupt flags. pmm_interrupt_flags_clear(0xFFFF); // Set SVM high side to new level and check if voltage increase is possible. HWREG16(SVSMHCTL_ADDRESS) = SVMHE | SVSHE | (SVSMHRRL0 * level); pmm_interrupt_flags_wait(SVSMHDLYIFG); pmm_interrupt_flags_clear(SVSMHDLYIFG); // Check if a voltage increase is possible. if ((HWREG16(PMMIFG_ADDRESS) & SVMHIFG) == SVMHIFG) { // Vcc is too low for a voltage increase, recover the previous settings. HWREG16(PMMIFG_ADDRESS) &= ~SVSMHDLYIFG; HWREG16(SVSMHCTL_ADDRESS) = svsmhctl_backup; pmm_interrupt_flags_wait(SVSMHDLYIFG); pmm_interrupt_flags_clear(PMM_CLEANUP_FLAGS); // Restore interrupt enable register. HWREG16(PMMRIE_ADDRESS) = pmmrie_backup; pmm_write_access_allow(false); return false; } // Set SVS high side to new level. HWREG16(SVSMHCTL_ADDRESS) |= (SVSHRVL0 * level); pmm_interrupt_flags_wait(SVSMHDLYIFG); pmm_interrupt_flags_clear(SVSMHDLYIFG); // Set new voltage level. HWREG8(PMMCTL0_L_ADDRESS) = PMMCOREV0 * level; // Set SVM, SVS low side to new level. HWREG16(SVSMLCTL_ADDRESS) = SVMLE | (SVSMLRRL0 * level) | SVSLE | (SVSLRVL0 * level); pmm_interrupt_flags_wait(SVSMLDLYIFG); pmm_interrupt_flags_clear(SVSMLDLYIFG); // Restore low side settings and clear all other bits. HWREG16(SVSMLCTL_ADDRESS) &= PMM_OTHER_BITSL; // Clear low side level settings in backup register and keep all other bits. svsmlctl_backup &= ~PMM_OTHER_BITSL; // Restore low side SVS monitor settings. HWREG16(SVSMLCTL_ADDRESS) |= svsmlctl_backup; // Restore high side settings and clear all other bits. HWREG16(SVSMHCTL_ADDRESS) &= PMM_OTHER_BITSH; // Clear high side level settings in backup register and keep all other bits. svsmhctl_backup &= ~PMM_OTHER_BITSH; // Restore high side SVS monitor settings. HWREG16(SVSMHCTL_ADDRESS) |= svsmhctl_backup; pmm_interrupt_flags_wait(SVSMLDLYIFG | SVSMHDLYIFG); pmm_interrupt_flags_clear(PMM_CLEANUP_FLAGS); // Restore interrupt enable register. HWREG16(PMMRIE_ADDRESS) = pmmrie_backup; pmm_write_access_allow(false); return true; } static uint16_t pmm_voltage_set_down(uint8_t level) { pmm_write_access_allow(true); // Disable interrupts and backup all registers. uint16_t pmmrie_backup = HWREG16(PMMRIE_ADDRESS); HWREG16(PMMRIE_ADDRESS) &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE | SVSLPE | SVMHVLRIE | SVMHIE | SVSMHDLYIE | SVMLVLRIE | SVMLIE | SVSMLDLYIE ); uint16_t svsmhctl_backup = HWREG16(SVSMHCTL_ADDRESS); uint16_t svsmlctl_backup = HWREG16(SVSMLCTL_ADDRESS); pmm_interrupt_flags_clear(SVMHIFG | SVSMHDLYIFG | SVMLIFG | SVSMLDLYIFG); // Set SVM, SVS high & low side to new settings in normal mode. HWREG16(SVSMHCTL_ADDRESS) = SVMHE | (SVSMHRRL0 * level) | SVSHE | (SVSHRVL0 * level); HWREG16(SVSMLCTL_ADDRESS) = SVMLE | (SVSMLRRL0 * level) | SVSLE | (SVSLRVL0 * level); pmm_interrupt_flags_wait(SVSMHDLYIFG | SVSMLDLYIFG); pmm_interrupt_flags_clear(SVSMHDLYIFG | SVSMLDLYIFG); // Set new voltage level. HWREG8(PMMCTL0_L_ADDRESS) = PMMCOREV0 * level; // Restore low side settings and clear all other bits. HWREG16(SVSMLCTL_ADDRESS) &= PMM_OTHER_BITSL; // Clear low side level settings in backup register and keep all other bits. svsmlctl_backup &= ~PMM_OTHER_BITSL; //Restore low side SVS monitor settings. HWREG16(SVSMLCTL_ADDRESS) |= svsmlctl_backup; // Restore high side settings and clear all other bits. HWREG16(SVSMHCTL_ADDRESS) &= PMM_OTHER_BITSH; // Clear high side level settings in backup register and keep all other bits. svsmhctl_backup &= ~PMM_OTHER_BITSH; // Restore high side SVS monitor settings. HWREG16(SVSMHCTL_ADDRESS) |= svsmhctl_backup; pmm_interrupt_flags_wait(SVSMLDLYIFG | SVSMHDLYIFG); pmm_interrupt_flags_clear(PMM_CLEANUP_FLAGS); // Restore interrupt enable register. HWREG16(PMMRIE_ADDRESS) = pmmrie_backup; pmm_write_access_allow(false); return true; } bool pmm_voltage_init(enum ppm_voltage voltage) { const uint8_t exp_level = pmm_level_mask(voltage) & PMMCOREV_3; uint8_t act_level = (HWREG16(PMM_BASE + OFS_PMMCTL0) & PMMCOREV_3); bool result = true; while ((exp_level != act_level) && result) { if (exp_level > act_level) result = pmm_voltage_set_up(++act_level); else result = pmm_voltage_set_down(--act_level); } return result; } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/hid.h0000644000175100017510000000755015232633614023266 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_HID_H #define MSP430_HID_H #include #include #ifdef __cplusplus extern "C" { #endif enum hid_constants { HID_CONFIG_NUMBER = 1, // Number of valid configuration. HID_IFACE_NUMBER = 0, // Number of valid interface. HID_ALT_IFACE_NUMBER = 0, // Number of valid alternate interface. HID_EP_IN = 0x81 // Active end point address. }; enum hid_gamepad_id { HID_REPORT_ID_GAMEPAD1 = 1, HID_REPORT_ID_GAMEPAD2 = 2 }; enum { HID_REPORTS_COUNT = 2, HID_REPORT_BITS_COUNT = 8 }; void hid_ep0_init(void); // Called only in interrupt context. void hid_ep0_setup_handler(void); void hid_ep0_in_handler(void); void hid_ep0_in_nak(void); void hid_ep0_in_stall(void); void hid_ep0_in_clear(void); bool hid_ep0_in_is_stalled(void); void hid_ep0_out_nak(void); void hid_ep0_out_stall(void); void hid_ep0_out_clear(void); const uint8_t *hid_ep0_desc_get(uint8_t type, uint16_t *length); uint8_t hid_ep0_setup_bm_request_type_get(void); uint8_t hid_ep0_setup_request_get(void); uint8_t hid_ep0_setup_lvalue_get(void); uint8_t hid_ep0_setup_hvalue_get(void); uint8_t hid_ep0_setup_lindex_get(void); uint8_t hid_ep0_setup_hindex_get(void); void hid_ep0_enumerated_set(bool enumerated); bool hid_ep0_is_enumerated(void); void hid_ep1_init(void); void hid_ep1_task(void); void hid_ep1_in_stall(void); void hid_ep1_in_unstall(void); bool hid_ep1_in_is_stalled(void); #ifdef __cplusplus } #endif #endif // MSP430_HID_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/README.md0000644000175100017510000000256115232633614023625 0ustar runnerrunnerThis example demonstrates how to build a bare-metal application using different MSP430 toolchains. It is designed for the MSP-EXP430F5529LP target board (based on msp430f5529 chip): * http://www.ti.com/tool/MSP-EXP430F5529LP It implements a USB HID device that connects two 8-buttons NES (Dendy) gamepads to a PC. The gamepads are connected to the msp430f5529 chip as follows: 1. CLK - it is an output clock signal which generates by chip from the port 6, pin 0 (P6.0). This pin should be connected to the CLK inputs for both gamepads. 2. DATA1 - it is an input data signal which comes to chip on the the port 6, pin 1 (P6.1). This pin should be connected to the DATA output from the gamepad #1. 3. DATA2 - it is an input data signal which comes to chip on the the port 6, pin 2 (P6.2). This pin should be connected to the DATA output from the gamepad #2. 4. LATCH - it is an output clock signal which generates by chip from the port 6, pin 3 (P6.3). This pin should be connected to the LATCH inputs for both gamepads. Actual schematic and pinouts depends on an used gamepads (with 7, 9 or other pins connectors) and a development boards. Also, do not forget to connect the +3.3V and GND wires to the gamepads. Then it is possible to play 8-bit NES games using various PC simulators. The following toolchains are supported: * IAR Embedded Workbench * GCC qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/hwdefs.h0000644000175100017510000000621215232633614023774 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_HW_DEFS_H #define MSP430_HW_DEFS_H #include #include #if defined(__ICC430__) # define _PPTOSTR_(x) #x # define _PPARAM_(address) _PPTOSTR_(vector=address) # define INTERRUPT(isr_name, vector) \ _Pragma(_PPARAM_(vector)) __interrupt void isr_name(void) #elif defined(__GNUC__) # define INTERRUPT(isr_name, vector) \ void __attribute__ ((interrupt(vector))) isr_name(void) #else # error "Unsupported toolchain" #endif #include #include #define HWREG8(x) \ (*((volatile uint8_t *)((uint16_t)x))) #define HWREG16(x) \ (*((volatile uint16_t *)((uint16_t)x))) #define HWREG32(x) \ (*((volatile uint32_t *)((uint16_t)x))) #endif // MSP430_HW_DEFS_H qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/nes-gamepads.qbs0000644000175100017510000001162115232633614025416 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ CppApplication { condition: { if (!qbs.architecture.contains("msp430")) return false; return qbs.toolchain.contains("iar") || qbs.toolchain.contains("gcc") } name: "msp430f5529-nes-gamepads" cpp.cLanguageVersion: "c99" cpp.positionIndependentCode: false // // IAR-specific properties and sources. // Properties { condition: qbs.toolchain.contains("iar") property path dlibIncludePath: cpp.toolchainInstallPath + "/../lib/dlib/dl430xssfn.h" property path dlibRuntimePath: cpp.toolchainInstallPath + "/../lib/dlib/dl430xssfn.r43" cpp.entryPoint: "__program_start" cpp.defines: ["__MSP430F5529__"] cpp.driverFlags: [ "-e", "--core=430X", "--data_model=small", "--code_model=small", "--dlib_config", dlibIncludePath ] cpp.driverLinkerFlags: [ "-D_STACK_SIZE=A0", "-D_DATA16_HEAP_SIZE=A0", "-D_DATA20_HEAP_SIZE=50" ] cpp.staticLibraries: [ // Explicitly link with the runtime dlib library (which contains // all required startup code and other stuff). dlibRuntimePath ] } Group { condition: qbs.toolchain.contains("iar") name: "IAR Linker Script" prefix: cpp.toolchainInstallPath + "/../config/linker/" fileTags: ["linkerscript"] // Explicitly use the default linker scripts for current target. files: ["lnk430f5529.xcl"] } // // GCC-specific properties and soucres. // Properties { condition: qbs.toolchain.contains("gcc") property path supportFilesPath // A path to the MSP430 support files, which are // provided by the Texas Instruments separately: // e.g. 'c:/msp430-gcc-support-files/include/' cpp.includePaths: supportFilesPath cpp.libraryPaths: supportFilesPath cpp.driverFlags: ["-mmcu=msp430f5529"] } Group { condition: qbs.toolchain.contains("gcc") name: "GCC Linker Script" fileTags: ["linkerscript"] files: ["gamepads.ld"] } files: [ "gpio.c", "gpio.h", "hid.h", "hiddesc.c", "hidep0.c", "hidep1.c", "hwdefs.h", "main.c", "pmm.c", "pmm.h", "ucs.c", "ucs.h", "usb.c", "usb.h", "wdt_a.c", "wdt_a.h", ] } qbs-src-3.3.1/examples/baremetal/msp430f5529/nes-gamepads/gpio.h0000644000175100017510000000741515232633614023460 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSP430_GPIO_H #define MSP430_GPIO_H #include #ifdef __cplusplus extern "C" { #endif enum gpio_port { GPIO_PORT_P1 = 1, GPIO_PORT_P2 = 2, GPIO_PORT_P3 = 3, GPIO_PORT_P4 = 4, GPIO_PORT_P5 = 5, GPIO_PORT_P6 = 6, GPIO_PORT_P7 = 7, GPIO_PORT_P8 = 8, GPIO_PORT_PJ = 13, }; enum gpio_pin { GPIO_PIN0 = 0x0001, GPIO_PIN1 = 0x0002, GPIO_PIN2 = 0x0004, GPIO_PIN3 = 0x0008, GPIO_PIN4 = 0x0010, GPIO_PIN5 = 0x0020, GPIO_PIN6 = 0x0040, GPIO_PIN7 = 0x0080, GPIO_PIN8 = 0x0100, GPIO_PIN9 = 0x0200, GPIO_PIN10 = 0x0400, GPIO_PIN11 = 0x0800, GPIO_PIN12 = 0x1000, GPIO_PIN13 = 0x2000, GPIO_PIN14 = 0x4000, GPIO_PIN15 = 0x8000, }; enum gpio_pin_status { GPIO_INPUT_PIN_HIGH = 0x01, GPIO_INPUT_PIN_LOW = 0x00 }; void gpio_pins_set_as_out(enum gpio_port port, uint16_t pins); void gpio_pins_set_as_in(enum gpio_port port, uint16_t pins); void gpio_pins_set_as_pf_out(enum gpio_port port, uint16_t pins); void gpio_pins_set_as_pf_in(enum gpio_port port, uint16_t pins); void gpio_pins_set_high(enum gpio_port port, uint16_t pins); void gpio_pins_set_low(enum gpio_port port, uint16_t pins); void gpio_pins_toggle(enum gpio_port port, uint16_t pins); enum gpio_pin_status gpio_pin_get(enum gpio_port port, uint16_t pins); #ifdef __cplusplus } #endif #endif // MSP430_GPIO_H qbs-src-3.3.1/examples/main-bundle/0000755000175100017510000000000015232633614016514 5ustar runnerrunnerqbs-src-3.3.1/examples/main-bundle/main-bundle.qbs0000644000175100017510000000630615232633614021423 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ Project { // Main application bundle Application { condition: qbs.targetOS.includes("darwin") name: "MainApp" Depends { name: "bundle" } bundle.isMainBundle: true Depends { name: "mylib" } Depends { name: "cpp" } cpp.rpaths: ["@executable_path/../Frameworks"] files: "main.cpp" } // MyLib framework DynamicLibrary { condition: qbs.targetOS.includes("darwin") name: "mylib" Depends { name: "bundle" } bundle.publicHeaders: ["mylib.h"] Depends { name: "cpp" } cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined files: ["mylib.cpp"] install: false // skip installing the framework since it will be embedded in the main bundle } } qbs-src-3.3.1/examples/main-bundle/mylib.h0000644000175100017510000000031515232633614020000 0ustar runnerrunner#ifndef MYLIB_H #define MYLIB_H #ifdef __cplusplus extern "C" { #endif /** * @brief Prints a hello message from the framework */ void mylib_hello(void); #ifdef __cplusplus } #endif #endif // MYLIB_H qbs-src-3.3.1/examples/main-bundle/main.cpp0000644000175100017510000000023115232633614020140 0ustar runnerrunner#include "mylib.h" #include int main() { std::cout << "Main bundle example application" << std::endl; mylib_hello(); return 0; } qbs-src-3.3.1/examples/main-bundle/mylib.cpp0000644000175100017510000000020015232633614020324 0ustar runnerrunner#include "mylib.h" #include void mylib_hello(void) { std::cout << "Hello from MyLib framework!" << std::endl; } qbs-src-3.3.1/release/0000755000175100017510000000000015232633614014123 5ustar runnerrunnerqbs-src-3.3.1/.clang-tidy0000644000175100017510000000423515232633614014543 0ustar runnerrunner--- Checks: > -*, bugprone-*, -bugprone-easily-swappable-parameters, -bugprone-narrowing-conversions, -bugprone-throw-keyword-missing, -bugprone-unchecked-optional-access, cppcoreguidelines-interfaces-global-init, cppcoreguidelines-pro-type-member-init, cppcoreguidelines-slicing, fuchsia-virtual-inheritance, google-build-explicit-make-pair, google-build-namespaces, google-global-names-in-headers, google-objc-*, google-readability-namespace-comments, google-runtime-operator, misc-definitions-in-headers, misc-misplaced-const, misc-new-delete-overloads, misc-non-copyable-objects, misc-redundant-expression, misc-static-assert, misc-uniqueptr-reset-release, misc-unused-*, modernize-avoid-bind, modernize-deprecated-headers, modernize-loop-convert, modernize-make-*, modernize-pass-by-value, modernize-redundant-void-arg, modernize-replace-*, modernize-return-braced-init-list, modernize-shrink-to-fit, modernize-unary-static-assert, modernize-use-auto, modernize-use-bool-literals, modernize-use-emplace, modernize-use-equals-*, modernize-use-noexcept, modernize-use-nullptr, modernize-use-override, modernize-use-transparent-functors, modernize-use-using, performance-*, -performance-no-int-to-ptr, readability-avoid-const-params-in-decls, readability-container-size-empty, readability-delete-null-pointer, readability-deleted-default, readability-identifier-naming, readability-misleading-indentation, readability-misplaced-array-index, readability-non-const-parameter, readability-redundant-*, -readability-redundant-member-init, readability-simplify-boolean-expr, readability-static-definition-in-anonymous-namespace, readability-uniqueptr-delete-release WarningsAsErrors: > bugprone-*, cppcoreguidelines-*, google-*, misc-unused-*, modernize-*, performance-*, readability-*, -readability-container-size-empty HeaderFilterRegex: '' AnalyzeTemporaryDtors: false CheckOptions: modernize-loop-convert.UseCxx20ReverseRanges: false qbs-src-3.3.1/tests/0000755000175100017510000000000015232633614013645 5ustar runnerrunnerqbs-src-3.3.1/tests/CMakeLists.txt0000644000175100017510000000022215232633614016401 0ustar runnerrunneradd_subdirectory(auto) add_subdirectory(benchmarker) add_subdirectory(clang-format-test) add_subdirectory(fuzzy-test) add_subdirectory(lspclient) qbs-src-3.3.1/tests/fuzzy-test/0000755000175100017510000000000015232633614016011 5ustar runnerrunnerqbs-src-3.3.1/tests/fuzzy-test/commandlineparser.cpp0000644000175100017510000001142215232633614022220 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include static QString profileOption() { return "--profile"; } static QString startCommitOption() { return "--start-commit"; } static QString maxDurationoption() { return "--max-duration"; } static QString jobCountOption() { return "--jobs"; } static QString logOption() { return "--log"; } CommandLineParser::CommandLineParser() = default; void CommandLineParser::parse(const QStringList &commandLine) { m_profile.clear(); m_startCommit.clear(); m_maxDuration = 0; m_jobCount = 0; m_log = false; m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = m_commandLine.takeFirst(); while (!m_commandLine.empty()) { const QString arg = m_commandLine.takeFirst(); if (arg == profileOption()) assignOptionArgument(arg, m_profile); else if (arg == startCommitOption()) assignOptionArgument(arg, m_startCommit); else if (arg == jobCountOption()) assignOptionArgument(arg, m_jobCount); else if (arg == maxDurationoption()) parseDuration(); else if (arg == logOption()) m_log = true; else throw ParseException(QStringLiteral("Unknown parameter '%1'").arg(arg)); } if (m_profile.isEmpty()) throw ParseException("No profile given."); if (m_startCommit.isEmpty()) throw ParseException("No start commit given."); } QString CommandLineParser::usageString() const { return QStringLiteral("%1 %2 %3 [%4 ] " "[%5 ] [%6]") .arg(QFileInfo(m_command).fileName(), profileOption(), startCommitOption(), maxDurationoption(), jobCountOption(), logOption()); } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throw ParseException(QStringLiteral("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) { throw ParseException(QStringLiteral("Argument for option '%1' must not be empty.") .arg(option)); } } void CommandLineParser::assignOptionArgument(const QString &option, int &argument) { QString numberString; assignOptionArgument(option, numberString); bool ok; argument = numberString.toInt(&ok); if (!ok || argument <= 0) { throw ParseException(QStringLiteral("Invalid argument '%1' for option '%2'.") .arg(numberString, option)); } } void CommandLineParser::parseDuration() { QString durationString; QString choppedDurationString; assignOptionArgument(maxDurationoption(), durationString); choppedDurationString = durationString; const char suffix = durationString.at(durationString.size() - 1).toLatin1(); const bool hasSuffix = !std::isdigit(suffix); if (hasSuffix) choppedDurationString.chop(1); bool ok; m_maxDuration = choppedDurationString.toInt(&ok); if (!ok || m_maxDuration <= 0) { throw ParseException(QStringLiteral("Invalid duration argument '%1'.") .arg(durationString)); } if (hasSuffix) { switch (suffix) { case 'm': break; case 'd': m_maxDuration *= 24; // Fall-through. case 'h': m_maxDuration *= 60; break; default: throw ParseException(QStringLiteral("Invalid duration suffix '%1'.") .arg(suffix)); } } } qbs-src-3.3.1/tests/fuzzy-test/CMakeLists.txt0000644000175100017510000000033015232633614020545 0ustar runnerrunnerset(SOURCES commandlineparser.cpp commandlineparser.h fuzzytester.cpp fuzzytester.h main.cpp ) add_qbs_app(qbs_fuzzy-test DEPENDS Qt${QT_VERSION_MAJOR}::Core SOURCES ${SOURCES} ) qbs-src-3.3.1/tests/fuzzy-test/fuzzytester.h0000644000175100017510000000543215232633614020604 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FUZZYTESTER_H #define QBS_FUZZYTESTER_H #include #include #include class TestError { public: TestError(QString errorMessage) : errorMessage(std::move(errorMessage)) {} ~TestError() throw() = default; QString errorMessage; private: const char *what() const throw() { return qPrintable(errorMessage); } }; class FuzzyTester { public: FuzzyTester(); ~FuzzyTester(); void runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log); private: void checkoutCommit(const QString &commit); QStringList findAllCommits(const QString &startCommit); QString findWorkingStartCommit(const QString &startCommit); void runGit(const QStringList &arguments, QString *output = 0); bool runQbs(const QString &buildDir, const QString &command, QString *errorOutput = 0); void removeDir(const QString &dir); bool doCleanBuild(QString *errorMessage = 0); void throwIncrementalBuildError(const QString &message, const QStringList &commitSequence); void loadSettings(); void storeSettings() const; static QString logFilePath(const QString &commit, const QString &activity); static QString defaultBuildDir(); QString m_profile; int m_jobCount = 0; bool m_log = false; QString m_headCommit; QString m_currentCommit; QString m_currentActivity; std::queue m_commitsWithLogFiles; QStringList m_unbuildableCommits; QStringList m_buildableCommits; }; #endif // Include guard. qbs-src-3.3.1/tests/fuzzy-test/fuzzytester.cpp0000644000175100017510000002753315232633614021145 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "fuzzytester.h" #include #include #include #include #include #include #include #include #include static QString resolveIncrementalActivity() { return "resolve-incremental"; } static QString buildIncrementalActivity() { return "build-incremental"; } static QString buildFromScratchActivity() { return "build-from-scratch"; } FuzzyTester::FuzzyTester() { loadSettings(); } FuzzyTester::~FuzzyTester() { storeSettings(); } void FuzzyTester::runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log) { m_profile = profile; m_jobCount = jobCount; m_log = log; runGit(QStringList() << "rev-parse" << "HEAD", &m_headCommit); qDebug("HEAD is %s", qPrintable(m_headCommit)); qDebug("Trying to find a buildable commit to start with..."); const QString workingStartCommit = findWorkingStartCommit(startCommit); qDebug("Found buildable start commit %s.", qPrintable(workingStartCommit)); QStringList allCommits = findAllCommits(workingStartCommit); qDebug("The test set comprises all %d commits between the start commit and HEAD.", int(allCommits.size())); // Shuffle the initial sequence. Otherwise all invocations of the tool with the same start // commit would try the same sequence of commits. std::srand(std::time(nullptr)); std::shuffle(allCommits.begin(), allCommits.end(), std::mt19937(std::random_device()())); quint64 run = 0; QStringList buildSequence(workingStartCommit); QElapsedTimer timer; const qint64 maxDurationInMillis = maxDurationInMinutes * 60 * 1000; if (maxDurationInMillis != 0) timer.start(); bool timerHasExpired = false; while (std::next_permutation(allCommits.begin(), allCommits.end()) && !timerHasExpired) { qDebug("Testing permutation %llu...", ++run); const auto &allCommitsImmutable = allCommits; for (const QString ¤tCommit : allCommitsImmutable) { if (timer.isValid() && timer.hasExpired(maxDurationInMillis)) { timerHasExpired = true; break; } m_currentCommit = currentCommit; buildSequence << currentCommit; checkoutCommit(currentCommit); qDebug("Testing incremental build #%d (%s)", int(buildSequence.size()) - 1, qPrintable(currentCommit)); // Doing "resolve" and "build" separately introduces additional possibilities // for errors, as information from change tracking has to be serialized correctly. QString qbsError; m_currentActivity = resolveIncrementalActivity(); bool success = runQbs(defaultBuildDir(), QStringLiteral("resolve"), &qbsError); if (success) { m_currentActivity = buildIncrementalActivity(); success = runQbs(defaultBuildDir(), QStringLiteral("build"), &qbsError); } m_currentActivity = buildFromScratchActivity(); if (success) { if (!doCleanBuild(&qbsError)) { QString message = "An incremental build succeeded " "with a commit for which a clean build failed."; if (!m_log) { message += QStringLiteral("\nThe qbs error message " "for the clean build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } } else { qDebug("Incremental build failed. Checking whether clean build works..."); if (doCleanBuild()) { QString message = "An incremental build failed " "with a commit for which a clean build succeeded."; if (!m_log) { message += QStringLiteral("\nThe qbs error message for " "the incremental build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } else { qDebug("Clean build also fails. Continuing."); } } } } if (timerHasExpired) qDebug("Maximum duration reached."); else qDebug("All possible permutations were tried."); } void FuzzyTester::checkoutCommit(const QString &commit) { runGit(QStringList() << "checkout" << commit); runGit(QStringList() << "submodule" << "update" << "--init"); } QStringList FuzzyTester::findAllCommits(const QString &startCommit) { QString allCommitsString; runGit(QStringList() << "log" << (startCommit + "~1.." + m_headCommit) << "--format=format:%h", &allCommitsString); return allCommitsString.simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts); } QString FuzzyTester::findWorkingStartCommit(const QString &startCommit) { const QStringList allCommits = findAllCommits(startCommit); QString qbsError; m_currentActivity = buildFromScratchActivity(); for (auto it = allCommits.crbegin(), end = allCommits.crend(); it != end; ++it) { m_currentCommit = *it; if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Skipping known bad commit %s.", qPrintable(m_currentCommit)); continue; } checkoutCommit(m_currentCommit); removeDir(defaultBuildDir()); if (runQbs(defaultBuildDir(), QStringLiteral("build"), &qbsError)) { m_buildableCommits << m_currentCommit; return m_currentCommit; } qDebug("Commit %s is not buildable.", qPrintable(m_currentCommit)); m_unbuildableCommits << m_currentCommit; } throw TestError(QStringLiteral("Cannot run test: Failed to find a single commit that " "builds successfully with qbs. The last qbs error was: '%1'").arg(qbsError)); } void FuzzyTester::runGit(const QStringList &arguments, QString *output) { QProcess git; git.start("git", arguments); if (!git.waitForStarted()) throw TestError("Failed to start git. It is expected to be in the PATH."); if (!git.waitForFinished(300000) || git.exitStatus() != QProcess::NormalExit) // 5 minutes ought to be enough for everyone throw TestError(QStringLiteral("git failed: %1").arg(git.errorString())); if (git.exitCode() != 0) { throw TestError(QStringLiteral("git failed: %1") .arg(QString::fromLocal8Bit(git.readAllStandardError()))); } if (output) *output = QString::fromLocal8Bit(git.readAllStandardOutput()).trimmed(); } bool FuzzyTester::runQbs(const QString &buildDir, const QString &command, QString *errorOutput) { if (errorOutput) errorOutput->clear(); QProcess qbs; QStringList commandLine = QStringList(command) << "-d" << buildDir; if (m_log) { commandLine << "-vv"; const size_t maxLoggedCommits = 2; Q_ASSERT(m_commitsWithLogFiles.size() <= maxLoggedCommits + 1); if (m_commitsWithLogFiles.size() == maxLoggedCommits + 1) { static const QStringList allActivities = QStringList() << resolveIncrementalActivity() << buildIncrementalActivity() << buildFromScratchActivity(); const QString oldCommit = m_commitsWithLogFiles.front(); m_commitsWithLogFiles.pop(); for (const QString &a : allActivities) QFile::remove(logFilePath(oldCommit, a)); } qbs.setStandardErrorFile(logFilePath(m_currentCommit, m_currentActivity)); if (m_commitsWithLogFiles.empty() || m_commitsWithLogFiles.back() != m_currentCommit) m_commitsWithLogFiles.push(m_currentCommit); } else { commandLine << "-qq"; } if (m_jobCount != 0) commandLine << "--jobs" << QString::number(m_jobCount); commandLine << ("profile:" + m_profile); qbs.start("qbs", commandLine); if (!qbs.waitForStarted()) { throw TestError(QStringLiteral("Failed to start qbs. It is expected to be " "in the PATH. QProcess error string: '%1'").arg(qbs.errorString())); } if (!qbs.waitForFinished(-1) || qbs.exitCode() != 0) { if (errorOutput) *errorOutput = QString::fromLocal8Bit(qbs.readAllStandardError()); return false; } return true; } void FuzzyTester::removeDir(const QString &dirPath) { QDir dir(dirPath); if (!dir.removeRecursively()) { throw TestError(QStringLiteral("Failed to remove temporary dir '%1'.") .arg(dir.absolutePath())); } } bool FuzzyTester::doCleanBuild(QString *errorMessage) { if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Commit is known not to be buildable, not running qbs."); return false; } if (m_buildableCommits.contains(m_currentCommit)) { qDebug("Commit is known to be buildable, not running qbs."); return true; } const QString cleanBuildDir = "fuzzytest-verification-build"; removeDir(cleanBuildDir); if (runQbs(cleanBuildDir, QStringLiteral("build"), errorMessage)) { m_buildableCommits << m_currentCommit; return true; } m_unbuildableCommits << m_currentCommit; return false; } void FuzzyTester::throwIncrementalBuildError(const QString &message, const QStringList &commitSequence) { const QString commitSequenceString = commitSequence.join(QLatin1Char(',')); throw TestError(QStringLiteral("Found qbs bug with incremental build!\n" "%1\n" "The sequence of commits was: %2.").arg(message, commitSequenceString)); } QString FuzzyTester::logFilePath(const QString &commit, const QString &activity) { return "log." + commit + '.' + activity; } QString FuzzyTester::defaultBuildDir() { return "fuzzytest-build"; } static QString organization() { return "QtProject"; } static QString app() { return "qbs-fuzzy-tester"; } static QString unbuildableCommitsKey() { return "unbuildable-commits"; } static QString buildableCommitsKey() { return "buildable-commits"; } void FuzzyTester::loadSettings() { QSettings s(organization(), app()); m_unbuildableCommits = s.value(unbuildableCommitsKey()).toStringList(); m_buildableCommits = s.value(buildableCommitsKey()).toStringList(); } void FuzzyTester::storeSettings() const { QSettings s(organization(), app()); s.setValue(unbuildableCommitsKey(), m_unbuildableCommits); s.setValue(buildableCommitsKey(), m_buildableCommits); } qbs-src-3.3.1/tests/fuzzy-test/commandlineparser.h0000644000175100017510000000464615232633614021677 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FUZZYTEST_COMMANDLINEPARSER_H #define QBS_FUZZYTEST_COMMANDLINEPARSER_H #include #include class ParseException : public std::exception { public: ParseException(QString error) : errorMessage(std::move(error)) { } ~ParseException() throw() override = default; QString errorMessage; private: const char *what() const throw() override { return qPrintable(errorMessage); } }; class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); QString profile() const { return m_profile; } QString startCommit() const { return m_startCommit; } int maxDurationInMinutes() const { return m_maxDuration; } int jobCount() const { return m_jobCount; } bool log() const { return m_log; } QString usageString() const; private: void assignOptionArgument(const QString &option, QString &argument); void assignOptionArgument(const QString &option, int &argument); void parseDuration(); QStringList m_commandLine; QString m_command; QString m_profile; QString m_startCommit; int m_maxDuration = 0; int m_jobCount = 0; bool m_log = false; }; #endif // Include guard. qbs-src-3.3.1/tests/fuzzy-test/main.cpp0000644000175100017510000000624415232633614017447 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "fuzzytester.h" #include #include #include static bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommi, int &maxDuration, int &jobCount, bool &log); static bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log); int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QString profile; QString startCommit; int maxDuration; int jobCount; bool log; if (!parseCommandLine(app.arguments(), profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; if (!runTest(profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; std::cout << "Test finished successfully." << std::endl; return EXIT_SUCCESS; } bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommit, int &maxDuration, int &jobCount, bool &log) { CommandLineParser cmdParser; try { cmdParser.parse(commandLine); } catch (const ParseException &e) { std::cerr << "Invalid command line: " << qPrintable(e.errorMessage) << std::endl; std::cerr << "Usage:" << std::endl << qPrintable(cmdParser.usageString()) << std::endl; return false; } profile = cmdParser.profile(); startCommit = cmdParser.startCommit(); maxDuration = cmdParser.maxDurationInMinutes(); jobCount = cmdParser.jobCount(); log = cmdParser.log(); return true; } bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log) { try { FuzzyTester().runTest(profile, startCommit, maxDuration, jobCount, log); } catch (const TestError &e) { std::cerr << qPrintable(e.errorMessage) << std::endl; return false; } return true; } qbs-src-3.3.1/tests/fuzzy-test/fuzzy-test.qbs0000644000175100017510000000076215232633614020671 0ustar runnerrunnerQtApplication { name: "qbs_fuzzy-test" type: "application" consoleApplication: true Depends { name: "qbsbuildconfig" } cpp.cxxLanguageVersion: "c++20" cpp.minimumMacosVersion: "11.0" files: [ "commandlineparser.cpp", "commandlineparser.h", "fuzzytester.cpp", "fuzzytester.h", "main.cpp", ] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } } qbs-src-3.3.1/tests/lspclient/0000755000175100017510000000000015232633614015642 5ustar runnerrunnerqbs-src-3.3.1/tests/lspclient/CMakeLists.txt0000644000175100017510000000025015232633614020377 0ustar runnerrunneradd_qbs_app(qbs_lspclient DEPENDS Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network qtclsp qbscore SOURCES lspclient.cpp ) qbs-src-3.3.1/tests/lspclient/lspclient.cpp0000644000175100017510000003557715232633614020364 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include enum class Command { GotoDefinition, Completion, }; class LspClient : public QObject { public: LspClient(Command command, const QString &socketPath, const QString &codeToInsert, int insertLine, int insertColumn, const QString &filePath, int line, int column); void start(); private: void finishWithError(const QString &msg); void exit(int code); void initiateProtocol(); void handleIncomingData(); void sendMessage(const lsp::JsonObject &msg); void sendMessage(const lsp::JsonRpcMessage &msg); void handleCurrentMessage(); void handleInitializeReply(); void openDocument(); void insertCode(); void sendRequest(); void handleResponse(); void sendGotoDefinitionRequest(); void handleGotoDefinitionResponse(); void sendCompletionRequest(); void handleCompletionResponse(); lsp::DocumentUri uri() const; lsp::DocumentUri::PathMapper mapper() const; const Command m_command; const QString m_socketPath; const QString m_codeToInsert; const int m_insertLine; const int m_insertColumn; const QString m_filePath; int m_line; int m_column; QLocalSocket m_socket; QBuffer m_incomingData; lsp::BaseMessage m_currentMessage; QJsonObject m_messageObject; enum class State { Inactive, Connecting, Initializing, RunningCommand } m_state = State::Inactive; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const QCommandLineOption socketOption({"socket", "s"}, "The server socket to connect to.", "socket"); const QCommandLineOption gotoDefinitionOption( {"goto-def", "g"}, "Go to definition from the specified location."); const QCommandLineOption completionOption( {"completion", "c"}, "Request completion at the specified location."); const QCommandLineOption insertCodeOption("insert-code", "A piece of code to insert before doing the actual " "operation.", "code"); const QCommandLineOption insertLocationOption("insert-location", "The location at which to insert the code.", ":"); QCommandLineParser parser; parser.addOptions( {socketOption, insertCodeOption, insertLocationOption, gotoDefinitionOption, completionOption}); parser.addHelpOption(); parser.addPositionalArgument("location", "The location at which to operate.", "::"); parser.process(app); const auto complainAndExit = [&](const char *text) { std::cerr << text << std::endl; parser.showHelp(EXIT_FAILURE); }; if (!parser.isSet(socketOption)) complainAndExit("Socket must be specified."); // Initialized to suppress warning. TODO: In C++23, mark lambdas as noreturn instead. Command command = Command::GotoDefinition; if (parser.isSet(gotoDefinitionOption)) command = Command::GotoDefinition; else if (parser.isSet(completionOption)) command = Command::Completion; else complainAndExit("Don't know what to do."); if (parser.positionalArguments().size() != 1) complainAndExit("Need location."); const auto complainAboutLocationString = [&] { complainAndExit("Invalid location."); }; const QString loc = parser.positionalArguments().first(); int sep1 = loc.indexOf(':'); if (sep1 <= 0) complainAboutLocationString(); if (qbs::Internal::HostOsInfo::isWindowsHost()) { sep1 = loc.indexOf(':', sep1 + 1); if (sep1 < 0) complainAboutLocationString(); } const int sep2 = loc.indexOf(':', sep1 + 1); if (sep2 == -1 || sep2 == loc.size() - 1) complainAboutLocationString(); const auto extractNumber = [&](const QString &s) { bool ok; const int n = s.toInt(&ok); if (!ok || n <= 0) complainAboutLocationString(); return n; }; const int line = extractNumber(loc.mid(sep1 + 1, sep2 - sep1 - 1)); const int column = extractNumber(loc.mid(sep2 + 1)); const QString insertLoc = parser.value(insertLocationOption); int insertLine = -1; int insertColumn = -1; if (insertLoc.isEmpty()) { insertLine = line; insertColumn = column; } else { const int sep = insertLoc.indexOf(':'); if (sep <= 0) complainAboutLocationString(); insertLine = extractNumber(insertLoc.left(sep)); insertColumn = extractNumber(insertLoc.mid(sep + 1)); } LspClient client(command, parser.value(socketOption), parser.value(insertCodeOption), insertLine, insertColumn, QDir::fromNativeSeparators(loc.left(sep1)), line, column); QMetaObject::invokeMethod(&client, &LspClient::start, Qt::QueuedConnection); return app.exec(); } LspClient::LspClient(Command command, const QString &socketPath, const QString &codeToInsert, int insertLine, int insertColumn, const QString &filePath, int line, int column) : m_command(command), m_socketPath(socketPath), m_codeToInsert(codeToInsert), m_insertLine(insertLine), m_insertColumn(insertColumn), m_filePath(filePath), m_line(line), m_column(column) { connect(&m_socket, &QLocalSocket::disconnected, this, [this] { finishWithError("Server disconnected unexpectedly."); }); connect(&m_socket, &QLocalSocket::errorOccurred, this, [this] { finishWithError(QString::fromLatin1("Socket error: %1").arg(m_socket.errorString())); }); connect(&m_socket, &QLocalSocket::connected, this, &LspClient::initiateProtocol); connect(&m_socket, &QLocalSocket::readyRead, this, &LspClient::handleIncomingData); } void LspClient::start() { m_state = State::Connecting; m_incomingData.open(QIODevice::ReadWrite | QIODevice::Append); m_socket.connectToServer(m_socketPath); } void LspClient::finishWithError(const QString &msg) { std::cerr << qPrintable(msg) << std::endl; m_socket.disconnectFromServer(); exit(EXIT_FAILURE); } void LspClient::exit(int code) { m_socket.disconnect(this); qApp->exit(code); } void LspClient::initiateProtocol() { if (m_state != State::Connecting) { finishWithError(QString::fromLatin1("State should be %1, was %2.") .arg(int(State::Connecting), int(m_state))); return; } m_state = State::Initializing; lsp::DynamicRegistrationCapabilities definitionCaps; definitionCaps.setDynamicRegistration(false); lsp::TextDocumentClientCapabilities docCaps; docCaps.setDefinition(definitionCaps); lsp::ClientCapabilities clientCaps; clientCaps.setTextDocument(docCaps); lsp::InitializeParams initParams; initParams.setCapabilities(clientCaps); sendMessage(lsp::InitializeRequest(initParams)); } void LspClient::handleIncomingData() { const int pos = m_incomingData.pos(); m_incomingData.write(m_socket.readAll()); m_incomingData.seek(pos); QString parseError; lsp::BaseMessage::parse(&m_incomingData, parseError, m_currentMessage); if (!parseError.isEmpty()) { return finishWithError(QString::fromLatin1("Error parsing server message: %1.") .arg(parseError)); } if (m_currentMessage.isComplete()) { m_incomingData.buffer().remove(0, m_incomingData.pos()); m_incomingData.seek(0); handleCurrentMessage(); m_currentMessage = {}; m_messageObject = {}; if (m_socket.state() == QLocalSocket::ConnectedState) handleIncomingData(); } } void LspClient::sendMessage(const lsp::JsonObject &msg) { sendMessage(lsp::JsonRpcMessage(msg)); } void LspClient::sendMessage(const lsp::JsonRpcMessage &msg) { lsp::BaseMessage baseMsg = msg.toBaseMessage(); m_socket.write(baseMsg.header()); m_socket.write(baseMsg.content); } void LspClient::handleCurrentMessage() { m_messageObject = lsp::JsonRpcMessage(m_currentMessage).toJsonObject(); switch (m_state) { case State::Inactive: case State::Connecting: finishWithError("Received message in non-connected state."); break; case State::Initializing: handleInitializeReply(); openDocument(); insertCode(); sendRequest(); break; case State::RunningCommand: handleResponse(); break; } } void LspClient::handleInitializeReply() { lsp::ServerCapabilities serverCaps = lsp::InitializeRequest::Response( m_messageObject).result().value_or(lsp::InitializeResult()).capabilities(); const auto defProvider = serverCaps.definitionProvider(); if (!defProvider) return finishWithError("Expected definition provider."); const bool * const defProviderValue = std::get_if(&(*defProvider)); if (!defProviderValue || !*defProviderValue) return finishWithError("Expected definition provider."); sendMessage(lsp::InitializeNotification(lsp::InitializedParams())); } void LspClient::openDocument() { QFile file(m_filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return finishWithError(QString::fromLatin1("Could not open '%1': %2") .arg(m_filePath, file.errorString())); } lsp::TextDocumentItem item; item.setUri(uri()); item.setVersion(0); item.setText(QString::fromUtf8(file.readAll())); item.setLanguageId("application/x-qt.qbs+qml"); sendMessage(lsp::DidOpenTextDocumentNotification(lsp::DidOpenTextDocumentParams(item))); } void LspClient::insertCode() { if (m_codeToInsert.isEmpty()) return; lsp::VersionedTextDocumentIdentifier docId; docId.setUri(uri()); docId.setVersion(1); lsp::DidChangeTextDocumentParams params(docId); lsp::DidChangeTextDocumentParams::TextDocumentContentChangeEvent change; const lsp::Position insertPos(m_insertLine - 1, m_insertColumn- 1); change.setRange({insertPos, insertPos}); change.setText(m_codeToInsert); params.setContentChanges({change}); sendMessage(lsp::DidChangeTextDocumentNotification(params)); if (m_insertLine > m_line || (m_insertLine == m_line && m_insertColumn > m_column)) return; const int newlineCount = m_codeToInsert.count('\n'); m_line += newlineCount; m_column += m_codeToInsert.size() - (newlineCount == 0 ? 0 : m_codeToInsert.lastIndexOf('\n')); } void LspClient::sendRequest() { m_state = State::RunningCommand; switch (m_command) { case Command::GotoDefinition: return sendGotoDefinitionRequest(); case Command::Completion: return sendCompletionRequest(); } } void LspClient::handleResponse() { const QString error = m_messageObject.value(lsp::errorKey).toObject() .value("message").toString(); if (!error.isEmpty()) return finishWithError(error); switch (m_command) { case Command::GotoDefinition: return handleGotoDefinitionResponse(); case Command::Completion: return handleCompletionResponse(); } } void LspClient::sendGotoDefinitionRequest() { const lsp::TextDocumentIdentifier doc(uri()); const lsp::Position pos(m_line - 1, m_column - 1); sendMessage(lsp::GotoDefinitionRequest({doc, pos})); } void LspClient::handleGotoDefinitionResponse() { const lsp::GotoResult result(lsp::GotoDefinitionRequest::Response(m_messageObject) .result().value_or(lsp::GotoResult())); QList links; const auto loc2Link = [this](const lsp::Location &loc) { return loc.toLink(mapper()); }; if (const auto loc = std::get_if(&result)) { links << loc2Link(*loc); } else if (const auto locs = std::get_if>(&result)) { links = lsp::Utils::transform(*locs, loc2Link); } for (const lsp::Utils::Link &link : std::as_const(links)) { std::cout << qPrintable(link.targetFilePath) << ':' << link.targetLine << ':' << (link.targetColumn + 1) << std::endl; } exit(EXIT_SUCCESS); } void LspClient::sendCompletionRequest() { const lsp::TextDocumentIdentifier doc(uri()); const lsp::Position pos(m_line - 1, m_column - 1); sendMessage(lsp::CompletionRequest({doc, pos})); } void LspClient::handleCompletionResponse() { const lsp::CompletionResult result(lsp::CompletionRequest::Response(m_messageObject) .result() .value_or(lsp::CompletionResult())); if (const auto items = std::get_if>(&result)) { for (const lsp::CompletionItem &item : *items) { std::cout << qPrintable(item.label()); if (item.detail()) std::cout << ' ' << qPrintable(*item.detail()); std::cout << std::endl; } } exit(EXIT_SUCCESS); } lsp::DocumentUri LspClient::uri() const { return lsp::DocumentUri::fromFilePath(lsp::Utils::FilePath::fromUserInput(m_filePath), mapper()); } lsp::DocumentUri::PathMapper LspClient::mapper() const { return [](const lsp::Utils::FilePath &fp) { return fp; }; } qbs-src-3.3.1/tests/lspclient/lspclient.qbs0000644000175100017510000000033115232633614020343 0ustar runnerrunnerQbsApp { name: "qbs_lspclient" Depends { name: "qtclsp" } Depends { name: "Qt.network" } cpp.defines: base.filter(function(d) { return d !== "QT_NO_CAST_FROM_ASCII"; }) files: "lspclient.cpp" } qbs-src-3.3.1/tests/auto/0000755000175100017510000000000015232633614014615 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/dllexport.h0000644000175100017510000000304715232633614017007 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DLLEXPORT_H #define DLLEXPORT_H #if defined(_WIN32) || defined(WIN32) # define DLL_EXPORT __declspec(dllexport) # define DLL_IMPORT __declspec(dllimport) #else # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_IMPORT __attribute__((visibility("default"))) # endif #endif // include guard qbs-src-3.3.1/tests/auto/CMakeLists.txt0000644000175100017510000000035215232633614017355 0ustar runnerrunneradd_subdirectory(api) add_subdirectory(cmdlineparser) add_subdirectory(blackbox) if(WITH_UNIT_TESTS) add_subdirectory(buildgraph) add_subdirectory(language) add_subdirectory(pkgconfig) add_subdirectory(tools) endif() qbs-src-3.3.1/tests/auto/pkgconfig/0000755000175100017510000000000015232633614016564 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/pkgconfig/CMakeLists.txt0000644000175100017510000000022615232633614021324 0ustar runnerrunneradd_qbs_test(pkgconfig SOURCES tst_pkgconfig.cpp tst_pkgconfig.h DEPENDS qbspkgconfig qbsquickjsheaders ) qbs-src-3.3.1/tests/auto/pkgconfig/tst_pkgconfig.cpp0000644000175100017510000002606615232633614022143 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_pkgconfig.h" #include "../shared.h" #include #include #include #include #include #include #include using HostOsInfo = qbs::Internal::HostOsInfo; using PcPackage = qbs::PcPackage; using PkgConfig = qbs::PkgConfig; using Options = qbs::PkgConfig::Options; TestPkgConfig::TestPkgConfig() : m_sourceDataDir(testDataSourceDir(SRCDIR "/testdata")) , m_workingDataDir(testWorkDir(QStringLiteral("pkgconfig"))) { } void TestPkgConfig::initTestCase() { QString errorMessage; qbs::Internal::removeDirectoryWithContents(m_workingDataDir, &errorMessage); QVERIFY2(qbs::Internal::copyFileRecursion(m_sourceDataDir, m_workingDataDir, false, true, &errorMessage), qPrintable(errorMessage)); } void TestPkgConfig::fileName() { QCOMPARE(qbs::Internal::fileName(""), ""); QCOMPARE(qbs::Internal::fileName("file.txt"), "file.txt"); QCOMPARE(qbs::Internal::fileName("/home/user/file.txt"), "file.txt"); QCOMPARE(qbs::Internal::fileName("/"), ""); #if defined(Q_OS_WIN) QCOMPARE(qbs::Internal::fileName("c:file.txt"), "file.txt"); QCOMPARE(qbs::Internal::fileName("c:"), ""); #endif } void TestPkgConfig::completeBaseName() { QCOMPARE(qbs::Internal::completeBaseName(""), ""); QCOMPARE(qbs::Internal::completeBaseName("file.txt"), "file"); QCOMPARE(qbs::Internal::completeBaseName("archive.tar.gz"), "archive.tar"); QCOMPARE(qbs::Internal::completeBaseName("/home/user/file.txt"), "file"); #if defined(Q_OS_WIN) QCOMPARE(qbs::Internal::completeBaseName("c:file.txt"), "file"); QCOMPARE(qbs::Internal::completeBaseName("c:archive.tar.gz"), "archive.tar"); QCOMPARE(qbs::Internal::completeBaseName("c:"), ""); #endif } void TestPkgConfig::parentPath() { QCOMPARE(qbs::Internal::parentPath(""), ""); QCOMPARE(qbs::Internal::parentPath("file.txt"), "."); QCOMPARE(qbs::Internal::parentPath("/home/user/file.txt"), "/home/user"); QCOMPARE(qbs::Internal::parentPath("/home/user/"), "/home/user"); QCOMPARE(qbs::Internal::parentPath("/home"), "/"); QCOMPARE(qbs::Internal::parentPath("/"), "/"); #if defined(Q_OS_WIN) QCOMPARE(qbs::Internal::parentPath("c:/folder/file.txt"), "c:/folder"); QCOMPARE(qbs::Internal::parentPath("c:/folder/"), "c:/folder"); QCOMPARE(qbs::Internal::parentPath("c:/folder"), "c:/"); QCOMPARE(qbs::Internal::parentPath("c:/"), "c:/"); QCOMPARE(qbs::Internal::parentPath("c:"), "c:"); #endif } void TestPkgConfig::pkgConfig() { QFETCH(QString, pcFileName); QFETCH(QString, jsonFileName); QFETCH(QVariantMap, optionsMap); if (jsonFileName.isEmpty()) jsonFileName = pcFileName; Options options = qbs::Internal::PkgConfigJs::convertOptions( QProcessEnvironment::systemEnvironment(), optionsMap); options.libDirs.push_back(m_workingDataDir.toStdString()); PkgConfig pkgConfig(std::move(options)); QFile jsonFile(m_workingDataDir + "/" + jsonFileName + ".json"); QVERIFY(jsonFile.open(QIODevice::ReadOnly)); QJsonParseError error{}; const auto json = QJsonDocument::fromJson(jsonFile.readAll(), &error).toVariant().toMap(); QCOMPARE(error.error, QJsonParseError::NoError); const auto &packageOr = pkgConfig.getPackage(pcFileName.toStdString()); QVERIFY(packageOr.isValid()); const auto &package = packageOr.asPackage(); QCOMPARE(QString::fromStdString(package.baseFileName), pcFileName); QCOMPARE(QString::fromStdString(package.name), json.value("Name").toString()); QCOMPARE(QString::fromStdString(package.description), json.value("Description").toString()); QCOMPARE(QString::fromStdString(package.version), json.value("Version").toString()); auto variables = json["Vars"].toMap(); variables["pcfiledir"] = QFileInfo(m_workingDataDir).absoluteFilePath(); QCOMPARE(size_t(variables.size()), package.variables.size()); for (const auto &[key, value]: package.variables) { QCOMPARE(QString::fromStdString(value), variables.value(QString::fromStdString(key)).toString()); } const auto jsonLibs = json.value("Libs").toJsonArray().toVariantList(); QCOMPARE(package.libs.size(), size_t(jsonLibs.size())); for (size_t i = 0; i < package.libs.size(); ++i) { const auto &item = package.libs[i]; const auto jsonItem = jsonLibs.at(i).toMap(); QCOMPARE(item.type, *PcPackage::Flag::typeFromString(jsonItem.value("Type").toString().toStdString())); QCOMPARE(QString::fromStdString(item.value), jsonItem.value("Value").toString()); } const auto jsonLibsPrivate = json.value("LibsPrivate").toJsonArray().toVariantList(); QCOMPARE(package.libsPrivate.size(), size_t(jsonLibsPrivate.size())); for (size_t i = 0; i < package.libsPrivate.size(); ++i) { const auto &item = package.libsPrivate[i]; const auto jsonItem = jsonLibsPrivate.at(i).toMap(); QCOMPARE(item.type, *PcPackage::Flag::typeFromString(jsonItem.value("Type").toString().toStdString())); QCOMPARE(QString::fromStdString(item.value), jsonItem.value("Value").toString()); } const auto jsonCFlags = json.value("Cflags").toJsonArray().toVariantList(); QCOMPARE(package.cflags.size(), size_t(jsonCFlags.size())); for (size_t i = 0; i < package.cflags.size(); ++i) { const auto &item = package.cflags[i]; const auto jsonItem = jsonCFlags.at(i).toMap(); QCOMPARE(item.type, *PcPackage::Flag::typeFromString(jsonItem.value("Type").toString().toStdString())); QCOMPARE(QString::fromStdString(item.value), jsonItem.value("Value").toString()); } for (const auto &item: package.requiresPublic) qInfo() << "requires" << item.name.c_str() << item.version.c_str(); const auto jsonRequires = json.value("Requires").toJsonArray().toVariantList(); QCOMPARE(package.requiresPublic.size(), size_t(jsonRequires.size())); for (size_t i = 0; i < package.requiresPublic.size(); ++i) { const auto &item = package.requiresPublic[i]; const auto jsonItem = jsonRequires.at(i).toMap(); QCOMPARE(item.comparison, *PcPackage::RequiredVersion::comparisonFromString( jsonItem.value("Comparison").toString().toStdString())); QCOMPARE(QString::fromStdString(item.name), jsonItem.value("Name").toString()); QCOMPARE(QString::fromStdString(item.version), jsonItem.value("Version").toString()); } const auto jsonRequiresPrivate = json.value("RequiresPrivate").toJsonArray().toVariantList(); QCOMPARE(package.requiresPrivate.size(), size_t(jsonRequiresPrivate.size())); for (size_t i = 0; i < package.requiresPrivate.size(); ++i) { const auto &item = package.requiresPrivate[i]; const auto jsonItem = jsonRequiresPrivate.at(i).toMap(); QCOMPARE(item.comparison, *PcPackage::RequiredVersion::comparisonFromString( jsonItem.value("Comparison").toString().toStdString())); QCOMPARE(QString::fromStdString(item.name), jsonItem.value("Name").toString()); QCOMPARE(QString::fromStdString(item.version), jsonItem.value("Version").toString()); } } void TestPkgConfig::pkgConfig_data() { QTest::addColumn("pcFileName"); QTest::addColumn("jsonFileName"); QTest::addColumn("optionsMap"); QTest::newRow("empty-variable") << QStringLiteral("empty-variable") << QString() << QVariantMap(); QTest::newRow("non-l-required") << QStringLiteral("non-l-required") << QString() << QVariantMap(); QTest::newRow("simple") << QStringLiteral("simple") << QString() << QVariantMap(); QTest::newRow("requires-test") << QStringLiteral("requires-test") << QString() << QVariantMap(); QTest::newRow("special-flags") << QStringLiteral("special-flags") << QString() << QVariantMap(); QTest::newRow("system") << QStringLiteral("system") << QString() << QVariantMap(); QTest::newRow("sysroot") << QStringLiteral("sysroot") << QString() << QVariantMap({{"sysroot", "/newroot"}}); QTest::newRow("tilde") << QStringLiteral("tilde") << QString() << QVariantMap(); QTest::newRow("variables") << QStringLiteral("variables") << QString() << QVariantMap(); QTest::newRow("whitespace") << QStringLiteral("whitespace") << QString() << QVariantMap(); QTest::newRow("base.name") << QStringLiteral("base.name") << QString() << QVariantMap(); } void TestPkgConfig::benchSystem() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Not available on Windows"); QBENCHMARK { PkgConfig pkgConfig; QVERIFY(!pkgConfig.packages().empty()); } } void TestPkgConfig::prefix() { const auto prefixDir = m_workingDataDir; const auto libDir = m_workingDataDir + "/lib"; const auto includeDir = m_workingDataDir + "/include"; const auto pkgconfigDir = libDir + "/pkgconfig"; Options options = qbs::Internal::PkgConfigJs::convertOptions( QProcessEnvironment::systemEnvironment(), {}); options.definePrefix = true; options.libDirs.push_back(pkgconfigDir.toStdString()); PkgConfig pkgConfig(std::move(options)); const auto &packageOr = pkgConfig.getPackage("prefix"); QVERIFY(packageOr.isValid()); const auto &package = packageOr.asPackage(); QCOMPARE(package.variables.at("prefix"), prefixDir.toStdString()); QCOMPARE(package.variables.at("exec_prefix"), prefixDir.toStdString()); QCOMPARE(package.variables.at("libdir"), libDir.toStdString()); QCOMPARE(package.variables.at("includedir"), includeDir.toStdString()); QCOMPARE(package.variables.at("usrdir"), "/usrdir"); } QTEST_MAIN(TestPkgConfig) qbs-src-3.3.1/tests/auto/pkgconfig/testdata/0000755000175100017510000000000015232633614020375 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/pkgconfig/testdata/requires-test.pc0000644000175100017510000000040515232633614023534 0ustar runnerrunnerName: Requires test package Description: Dummy pkgconfig test package for testing Requires/Requires.private Version: 1.0.0 Requires: public-dep >= 1 Requires.private: private-dep >= 1 Libs: -L/requires-test/lib -lrequires-test Cflags: -I/requires-test/include qbs-src-3.3.1/tests/auto/pkgconfig/testdata/system.json0000644000175100017510000000060515232633614022615 0ustar runnerrunner{ "Name": "System library", "Description": "Test package", "Version": "1.0.0", "Vars": { "prefix": "/usr", "exec_prefix": "/usr", "libdir": "/usr/lib", "includedir": "/usr/include" }, "Libs": [ {"Type": "LibraryName", "Value": "system"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/usr/include"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/whitespace.json0000644000175100017510000000155215232633614023427 0ustar runnerrunner{ "Name": "Whitespace test", "Description": "Dummy pkgconfig test package for testing pkgconfig", "Version": "1.0.0", "Vars": { "prefix": "/usr", "exec_prefix": "/usr", "libdir": "\"/usr/white space/lib\"", "includedir": "\"/usr/white space/include\"" }, "Libs": [ {"Type": "LibraryPath", "Value": "/usr/white space/lib"}, {"Type": "LibraryName", "Value": "foo bar"}, {"Type": "LibraryName", "Value": "bar baz"}, {"Type": "LinkerFlag", "Value": "-r:foo"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/usr/white space/include"}, {"Type": "IncludePath", "Value": "$(top_builddir)"}, {"Type": "IncludePath", "Value": "include dir"}, {"Type": "IncludePath", "Value": "other include dir"}, {"Type": "Define", "Value": "lala=misc"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/non-l-required.json0000644000175100017510000000060215232633614024127 0ustar runnerrunner{ "Name": "Non-l flags required test package", "Description": "Test package for checking order of non-L Libs & Cflags", "Version": "1.0.0", "Libs": [ {"Type": "StaticLibraryName", "Value": "/non-l-required.a"}, {"Type": "LinkerFlag", "Value": "-pthread"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/non-l-required/include"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/requires-test.json0000644000175100017510000000113615232633614024105 0ustar runnerrunner{ "Name": "Requires test package", "Description": "Dummy pkgconfig test package for testing Requires/Requires.private", "Version": "1.0.0", "Libs": [ {"Type": "LibraryPath", "Value": "/requires-test/lib"}, {"Type": "LibraryName", "Value": "requires-test"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/requires-test/include"} ], "Requires": [ {"Comparison": "GreaterThanEqual", "Name": "public-dep", "Version": "1"} ], "RequiresPrivate": [ {"Comparison": "GreaterThanEqual", "Name": "private-dep", "Version": "1"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/sysroot.pc0000644000175100017510000000050115232633614022437 0ustar runnerrunnerprefix=/opt exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include sysroot=${pc_sysrootdir} Name: Test for sysroot Description: Test package for testing sysroot Version: 1.0.0 Requires: Libs: -L${libdir} -lsystem Cflags: -I${includedir} -idirafter ${includedir}/after -isystem ${includedir}/system qbs-src-3.3.1/tests/auto/pkgconfig/testdata/empty-variable.pc0000644000175100017510000000045415232633614023645 0ustar runnerrunnerrootprefix= prefix=/usr exec_prefix=${rootprefix}/${prefix} libdir=${exec_prefix}/lib includedir=${rootprefix}/${prefix}/include Name: Empty Variable test Description: Checks that empty variables are handled correcty Version: 1.0.0 Requires: Libs: -lsimple Libs.private: -lm Cflags: -I${includedir} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/base.name.pc0000644000175100017510000000036015232633614022551 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: Base Name test Description: Checks correct baseName detection Version: 1.0.0 Requires: Libs: -lsimple Libs.private: -lm Cflags: -I${includedir} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/variables.pc0000644000175100017510000000040015232633614022663 0ustar runnerrunnerprefix=/local exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir="${prefix}/include" cppflags=-I${includedir}/foo \ -DFOO=\"/bar\" Name: Complex variables Description: Test complex variable output Version: 1.0 Cflags: -I${includedir} ${cppflags} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/lib/0000755000175100017510000000000015232633614021143 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/pkgconfig/testdata/lib/pkgconfig/0000755000175100017510000000000015232633614023112 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/pkgconfig/testdata/lib/pkgconfig/prefix.pc0000644000175100017510000000036615232633614024740 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=/usr/include usrdir=/usrdir Name: Prefix test Description: This tests prefix auto detection Version: 1.0.0 Requires: Libs: -lprefix Libs.private: -lm Cflags: -I${includedir} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/simple.json0000644000175100017510000000076215232633614022566 0ustar runnerrunner{ "Name": "Simple test", "Description": "Dummy pkgconfig test package for testing pkgconfig", "Version": "1.0.0", "Vars": { "prefix": "/usr", "exec_prefix": "/usr", "libdir": "/usr/lib", "includedir": "/usr/include" }, "Libs": [ {"Type": "LibraryName", "Value": "simple"} ], "LibsPrivate": [ {"Type": "LibraryName", "Value": "m"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/usr/include"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/system.pc0000644000175100017510000000031315232633614022242 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: System library Description: Test package Version: 1.0.0 Libs: -L${libdir} -lsystem Cflags: -I${includedir} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/special-flags.pc0000644000175100017510000000060715232633614023436 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: Special flags test Description: Dummy pkgconfig test package for testing pkgconfig Version: 1.0.0 Requires: Libs: -L/foo -framework Foo -lsimple -L/bar -framework Bar -Wl,-framework -Wl,Baz Cflags: -I/foo -g -isystem /system1 -idirafter /after1 -ffoo -I/bar -idirafter /after2 -isystem /system2 qbs-src-3.3.1/tests/auto/pkgconfig/testdata/tilde.pc0000644000175100017510000000011615232633614022020 0ustar runnerrunnerName: tilde Description: tilde test module Version: 1.0 Libs: -L~ Cflags: -I~ qbs-src-3.3.1/tests/auto/pkgconfig/testdata/special-flags.json0000644000175100017510000000214115232633614024000 0ustar runnerrunner{ "Name": "Special flags test", "Description": "Dummy pkgconfig test package for testing pkgconfig", "Version": "1.0.0", "Vars": { "prefix": "/usr", "exec_prefix": "/usr", "libdir": "/usr/lib", "includedir": "/usr/include" }, "Libs": [ {"Type": "LibraryPath", "Value": "/foo"}, {"Type": "Framework", "Value": "Foo"}, {"Type": "LibraryName", "Value": "simple"}, {"Type": "LibraryPath", "Value": "/bar"}, {"Type": "Framework", "Value": "Bar"}, {"Type": "LinkerFlag", "Value": "-Wl,-framework"}, {"Type": "LinkerFlag", "Value": "-Wl,Baz"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/foo"}, {"Type": "CompilerFlag", "Value": "-g"}, {"Type": "SystemIncludePath", "Value": "/system1"}, {"Type": "DirAfterIncludePath", "Value": "/after1"}, {"Type": "CompilerFlag", "Value": "-ffoo"}, {"Type": "IncludePath", "Value": "/bar"}, {"Type": "DirAfterIncludePath", "Value": "/after2"}, {"Type": "SystemIncludePath", "Value": "/system2"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/private-dep.pc0000644000175100017510000000030215232633614023134 0ustar runnerrunnerName: Requires test package Description: Dummy pkgconfig test package for testing Requires/Requires.private Version: 1.0.0 Libs: -L/private-dep/lib -lprivate-dep Cflags: -I/private-dep/include qbs-src-3.3.1/tests/auto/pkgconfig/testdata/whitespace.pc0000644000175100017510000000056115232633614023057 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir="${exec_prefix}/white space/lib" includedir="${prefix}/white space/include" Name: Whitespace test Description: Dummy pkgconfig test package for testing pkgconfig Version: 1.0.0 Requires: Libs: -L${libdir} -lfoo\ bar "-lbar baz" -r:foo Cflags: -I${includedir} -I$(top_builddir) -Iinclude\ dir "-Iother include dir" -Dlala=misc qbs-src-3.3.1/tests/auto/pkgconfig/testdata/base.name.json0000644000175100017510000000074415232633614023126 0ustar runnerrunner{ "Name": "Base Name test", "Description": "Checks correct baseName detection", "Version": "1.0.0", "Vars": { "prefix": "/usr", "exec_prefix": "/usr", "libdir": "/usr/lib", "includedir": "/usr/include" }, "Libs": [ {"Type": "LibraryName", "Value": "simple"} ], "LibsPrivate": [ {"Type": "LibraryName", "Value": "m"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/usr/include"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/tilde.json0000644000175100017510000000033615232633614022373 0ustar runnerrunner{ "Name": "tilde", "Description": "tilde test module", "Version": "1.0", "Libs": [ {"Type": "LibraryPath", "Value": "~"} ], "Cflags": [ {"Type": "IncludePath", "Value": "~"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/empty-variable.json0000644000175100017510000000102615232633614024210 0ustar runnerrunner{ "Name": "Empty Variable test", "Description": "Checks that empty variables are handled correcty", "Version": "1.0.0", "Vars": { "rootprefix": "", "prefix": "/usr", "exec_prefix": "//usr", "libdir": "//usr/lib", "includedir": "//usr/include" }, "Libs": [ {"Type": "LibraryName", "Value": "simple"} ], "LibsPrivate": [ {"Type": "LibraryName", "Value": "m"} ], "Cflags": [ {"Type": "IncludePath", "Value": "//usr/include"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/variables.json0000644000175100017510000000102515232633614023236 0ustar runnerrunner{ "Name": "Complex variables", "Description": "Test complex variable output", "Version": "1.0", "Vars": { "prefix": "/local", "exec_prefix": "/local", "libdir": "/local/lib", "includedir": "\"/local/include\"", "cppflags": "-I\"/local/include\"/foo -DFOO=\\\"/bar\\\"" }, "Cflags": [ {"Type": "IncludePath", "Value": "/local/include"}, {"Type": "IncludePath", "Value": "/local/include/foo"}, {"Type": "Define", "Value": "FOO=\"/bar\""} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/sysroot.json0000644000175100017510000000123715232633614023015 0ustar runnerrunner{ "Name": "Test for sysroot", "Description": "Test package for testing sysroot", "Version": "1.0.0", "Vars": { "prefix": "/opt", "exec_prefix": "/opt", "libdir": "/opt/lib", "includedir": "/opt/include", "sysroot": "/newroot" }, "Libs": [ {"Type": "LibraryPath", "Value": "/newroot/opt/lib"}, {"Type": "LibraryName", "Value": "system"} ], "Cflags": [ {"Type": "IncludePath", "Value": "/newroot/opt/include"}, {"Type": "DirAfterIncludePath", "Value": "/newroot/opt/include/after"}, {"Type": "SystemIncludePath", "Value": "/newroot/opt/include/system"} ] } qbs-src-3.3.1/tests/auto/pkgconfig/testdata/public-dep.pc0000644000175100017510000000032015232633614022740 0ustar runnerrunnerName: Requires test package Description: Dummy pkgconfig test package for testing Requires/Requires.private Version: 1.0.0 Requires.private: Libs: -L/public-dep/lib -lpublic-dep Cflags: -I/public-dep/include qbs-src-3.3.1/tests/auto/pkgconfig/testdata/simple.pc0000644000175100017510000000037615232633614022220 0ustar runnerrunnerprefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: Simple test Description: Dummy pkgconfig test package for testing pkgconfig Version: 1.0.0 Requires: Libs: -lsimple Libs.private: -lm Cflags: -I${includedir} qbs-src-3.3.1/tests/auto/pkgconfig/testdata/non-l-required.pc0000644000175100017510000000027615232633614023567 0ustar runnerrunnerName: Non-l flags required test package Description: Test package for checking order of non-L Libs & Cflags Version: 1.0.0 Libs: /non-l-required.a -pthread Cflags: -I/non-l-required/include qbs-src-3.3.1/tests/auto/pkgconfig/tst_pkgconfig.h0000644000175100017510000000334015232633614021576 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TST_API_H #define QBS_TST_API_H #include #include class TestPkgConfig : public QObject { Q_OBJECT public: TestPkgConfig(); private slots: void initTestCase(); void fileName(); void completeBaseName(); void parentPath(); void pkgConfig(); void pkgConfig_data(); void benchSystem(); void prefix(); private: const QString m_sourceDataDir; const QString m_workingDataDir; }; #endif // Include guard. qbs-src-3.3.1/tests/auto/pkgconfig/pkgconfig.qbs0000644000175100017510000000065615232633614021251 0ustar runnerrunnerimport qbs import qbs.Utilities QbsUnittest { Depends { name: "qbspkgconfig" } condition: qbsbuildconfig.enableUnitTests testName: "pkgconfig" files: ["../shared.h", "tst_pkgconfig.h", "tst_pkgconfig.cpp"] cpp.defines: base.concat([ "SRCDIR=" + Utilities.cStringQuote(path), ]) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-3.3.1/tests/auto/blackbox/0000755000175100017510000000000015232633614016402 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/0000755000175100017510000000000015232633614022145 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/0000755000175100017510000000000015232633614027563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/ctest.c0000644000175100017510000000000015232633614031037 0ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-b0000644000175100017510000000550715232633614033161 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication Project { property bool supportsCpp: { if (qbs.toolchain.includes("cosmic")) return false; if (qbs.toolchain.includes("sdcc")) return false; if (qbs.toolchain.includes("keil")) { if (qbs.architecture === "mcs51" || qbs.architecture === "mcs251" || qbs.architecture === "c166") { return false; } } return true; } BareMetalApplication { name: "c_language" files: ["app.c", "ctest.c"] cpp.enableCompilerDefinesByLanguage: [] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; } } BareMetalApplication { condition: supportsCpp name: "cpp_language" files: ["app.c", "cpptest.cpp"] cpp.enableCompilerDefinesByLanguage: ["cpp"] cpp.enableExceptions: false property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; } } BareMetalApplication { condition: supportsCpp name: "c_and_cpp_language" files: ["app.c", "ctest.c", "cpptest.cpp"] cpp.enableCompilerDefinesByLanguage: ["c", "cpp"] cpp.enableExceptions: false property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/cpptest.cpp0000644000175100017510000000000015232633614031737 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/app.c0000644000175100017510000000004115232633614030502 0ustar runnerrunnerint main(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/linker-map/0000755000175100017510000000000015232633614024204 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/linker-map/linker-map.qbs0000644000175100017510000000033215232633614026750 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { property bool dummy: { console.info("linker map suffix: %%" + cpp.linkerMapSuffix + "%%"); } files: ["main.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/linker-map/main.c0000644000175100017510000000004115232633614025267 0ustar runnerrunnerint main(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/preinclude-headers/0000755000175100017510000000000015232633614025710 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/preinclude-headers/main.c0000644000175100017510000000006015232633614026774 0ustar runnerrunnerint main(void) { return PREINCLUDE_VALUE; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude-headers.qbs0000644000175100017510000000107115232633614032161 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { condition: { if (qbs.toolchainType === "keil") { if (qbs.architecture === "mcs51" || qbs.architecture === "mcs251" || qbs.architecture === "c166") { console.info("unsupported toolset: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); return false; } } return true; } cpp.prefixHeaders: ["preinclude.h"] files: ["main.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude.h0000644000175100017510000000013615232633614030213 0ustar runnerrunner#ifndef PREINCLUDE_H #define PREINCLUDE_H #define PREINCLUDE_VALUE 0 #endif // PREINCLUDE_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-listing/0000755000175100017510000000000015232633614025426 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-listing/fun.c0000644000175100017510000000003615232633614026361 0ustar runnerrunnerint f(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-listing/main.c0000644000175100017510000000007015232633614026513 0ustar runnerrunnerextern int f(void); int main(void) { return f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs0000644000175100017510000000070615232633614031421 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { condition: { if (!qbs.toolchain.includes("gcc")) { console.info("compiler listing suffix: %%" + cpp.compilerListingSuffix + "%%"); return true; } console.info("unsupported toolset: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); return false; } files: ["main.c", "fun.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/0000755000175100017510000000000015232633614027522 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a2.c0000644000175100017510000000003715232633614030170 0ustar runnerrunnerint a2(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/b.c0000644000175100017510000000006715232633614030112 0ustar runnerrunnerextern int a1(void); int b(void) { return a1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/e.c0000644000175100017510000000006615232633614030114 0ustar runnerrunnerextern int d(void); int e(void) { return d(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/c.c0000644000175100017510000000006715232633614030113 0ustar runnerrunnerextern int a2(void); int c(void) { return a2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/d.c0000644000175100017510000000011715232633614030110 0ustar runnerrunnerextern int b(void); extern int c(void); int d(void) { return b() + c(); } ././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/static-library-dependencies.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/static-library-depe0000644000175100017510000000173615232633614033320 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary Project { BareMetalStaticLibrary { name: "lib-a" Depends { name: "cpp" } files: ["a1.c", "a2.c"] } BareMetalStaticLibrary { name: "lib-b" Depends { name: "cpp" } Depends { name: "lib-a" } files: ["b.c"] } BareMetalStaticLibrary { name: "lib-c" Depends { name: "cpp" } Depends { name: "lib-a" } files: ["c.c"] } BareMetalStaticLibrary { name: "lib-d" Depends { name: "cpp" } Depends { name: "lib-b" } Depends { name: "lib-c" } files: ["d.c"] } BareMetalStaticLibrary { name: "lib-e" Depends { name: "cpp" } Depends { name: "lib-d" } files: ["e.c"] } BareMetalApplication { name: "app" Depends { name: "lib-e" } files: ["app.c"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a1.c0000644000175100017510000000003715232633614030167 0ustar runnerrunnerint a1(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/app.c0000644000175100017510000000007015232633614030443 0ustar runnerrunnerextern int e(void); int main(void) { return e(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/0000755000175100017510000000000015232633614027226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/main.c0000644000175100017510000000006415232633614030316 0ustar runnerrunnerextern int b(); int main(void) { return b(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-a.c0000644000175100017510000000003615232633614030355 0ustar runnerrunnerint a(void) { return 0; } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libra0000644000175100017510000000213215232633614033345 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary Project { property string outputLibrariesDirectory: buildDirectory + "/libs" BareMetalStaticLibrary { name: "lib-a" destinationDirectory: project.outputLibrariesDirectory Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib-a.c"] } BareMetalStaticLibrary { name: "lib-b" destinationDirectory: project.outputLibrariesDirectory Depends { name: "cpp" } Depends { name: "lib-a" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib-b.c"] } BareMetalApplication { Depends { name: "lib-a"; cpp.link: false } Depends { name: "lib-b"; cpp.link: false } files: ["main.c"] cpp.libraryPaths: [project.outputLibrariesDirectory] cpp.staticLibraries: ["lib-b", "lib-a"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-b.c0000644000175100017510000000006515232633614030360 0ustar runnerrunnerextern int a(void); int b(void) { return a(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/shared-libraries/0000755000175100017510000000000015232633614025365 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared.c0000644000175100017510000000047715232633614027007 0ustar runnerrunner#include "../dllexport.h" #include #ifdef __DMC__ #include #define EXPORT_FUN _export BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { return TRUE; } #else #define EXPORT_FUN #endif // __DMC__ DLL_EXPORT void EXPORT_FUN foo(void) { printf("Hello from lib\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/shared-libraries/app.c0000644000175100017510000000022715232633614026312 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT void foo(void); int main(void) { printf("Hello from app\n"); foo(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared-libraries.qbs0000644000175100017510000000140115232633614031310 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication Project { condition: { if (qbs.targetPlatform === "windows" && qbs.architecture === "x86") { if (qbs.toolchainType === "watcom") return true; if (qbs.toolchainType === "dmc") return true; } if (qbs.toolchainType === "msvc") return true; console.info("unsupported toolset: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); return false; } DynamicLibrary { Depends { name: "cpp" } name: "shared" files: ["shared.c"] } BareMetalApplication { Depends { name: "shared" } name: "app" files: ["app.c"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs0000644000175100017510000001275615232633614026064 0ustar runnerrunnerProduct { Depends { name: "cpp" } cpp.positionIndependentCode: false Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "stm8" cpp.driverLinkerFlags: [ "--config_def", "_CSTACK_SIZE=0x100", "--config_def", "_HEAP_SIZE=0x100", ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "rl78" cpp.driverLinkerFlags: [ "--config_def", "_NEAR_HEAP_SIZE=256", "--config_def", "_FAR_HEAP_SIZE=4096", "--config_def", "_HUGE_HEAP_SIZE=0", "--config_def", "_STACK_SIZE=128", "--config_def", "_NEAR_CONST_LOCATION_SIZE=0x6F00", "--config_def", "_NEAR_CONST_LOCATION_START=0x3000", "--define_symbol", "_NEAR_CONST_LOCATION=0", "--config", cpp.toolchainInstallPath + "/../config/lnkrl78_s3.icf" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "rh850" cpp.driverLinkerFlags: [ "--config_def", "CSTACK_SIZE=0x1000", "--config_def", "HEAP_SIZE=0x1000", "--config", cpp.toolchainInstallPath + "/../config/lnkrh850_g3m.icf" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "v850" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=1000", "-D_HEAP_SIZE=1000", "-f", cpp.toolchainInstallPath + "/../config/lnk85.xcl" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "78k" cpp.commonCompilerFlags: [ "--core", "78k0", "--code_model", "standard" ] cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=80", "-D_HEAP_SIZE=200", "-D_CODEBANK_START=0", "-D_CODEBANK_END=0", "-D_CODEBANK_BANKS=0", "-f", cpp.toolchainInstallPath + "/../config/lnk.xcl", cpp.toolchainInstallPath + "/../lib/clib/cl78ks1.r26" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "sh" cpp.driverLinkerFlags: [ "--config_def", "_CSTACK_SIZE=0x800", "--config_def", "_HEAP_SIZE=0x800", "--config_def", "_INT_TABLE=0x10", "--config", cpp.toolchainInstallPath + "/../config/generic.icf" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "hcs8" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=200", "-D_HEAP_SIZE=200", "-f", cpp.toolchainInstallPath + "/../config/lnkunspecifieds08.xcl" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "m32c" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=100", "-D_NEAR_HEAP_SIZE=400", "-D_FAR_HEAP_SIZE=400", "-D_HUGE_HEAP_SIZE=400", "-D_ISTACK_SIZE=40", "-f", cpp.toolchainInstallPath + "/../config/lnkm32c.xcl", cpp.toolchainInstallPath + (qbs.debugInformation ? "/../lib/dlib/dlm32cnf.r48" : "/../lib/clib/clm32cf.r48") ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "riscv" cpp.driverLinkerFlags: [ "--config_def", "CSTACK_SIZE=0x1000", "--config_def", "HEAP_SIZE=0x1000" ] } Properties { condition: qbs.toolchain.includes("iar") && qbs.architecture === "m68k" cpp.cFlags: [ "--no_div" ] cpp.driverLinkerFlags: [ "-D__FLASHBEGIN=0", "-D__FLASHEND=1FFFF", "-D__RAMBEGIN=800000", "-D__RAMEND=803FFF", "-D_CSTACK_SIZE=200", "-D_HEAP_SIZE=1000", "-D_VBR_ADDRESS=0", "-f", cpp.toolchainInstallPath + "/../config/lnkm51ac128.xcl", cpp.toolchainInstallPath + "/../lib/dlcfcffdn.r68" ] } Properties { condition: qbs.toolchain.includes("keil") && qbs.architecture.startsWith("arm") && cpp.compilerName.startsWith("armcc") cpp.assemblerFlags: ["--cpu", "cortex-m0"] cpp.commonCompilerFlags: ["--cpu", "cortex-m0"] } Properties { condition: qbs.toolchain.includes("keil") && qbs.architecture.startsWith("arm") && cpp.compilerName.startsWith("armclang") cpp.assemblerFlags: ["--cpu", "cortex-m0"] cpp.commonCompilerFlags: ["-mcpu=cortex-m0", "--target=arm-arm-none-eabi"] } Properties { condition: qbs.toolchain.includes("gcc") && qbs.architecture.startsWith("arm") cpp.driverFlags: ["-specs=nosys.specs"] } Properties { condition: qbs.toolchain.includes("gcc") && qbs.architecture === "xtensa" cpp.driverFlags: ["-nostdlib"] } Properties { condition: qbs.toolchain.includes("gcc") && qbs.architecture === "msp430" cpp.driverFlags: ["-mmcu=msp430f5529", "-nostdlib"] } Properties { condition: qbs.toolchain.includes("gcc") && qbs.architecture === "m32r" cpp.driverFlags: ["-nostdlib"] } Properties { condition: qbs.toolchain.includes("gcc") && qbs.architecture === "riscv" cpp.driverFlags: ["-nostdlib"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/BareMetalStaticLibrary.qbs0000644000175100017510000000005715232633614027207 0ustar runnerrunnerBareMetalProduct { type: "staticlibrary" } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/0000755000175100017510000000000015232633614026515 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/main.c0000644000175100017510000000004115232633614027600 0ustar runnerrunnerint main(void) { return 0; } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/compiler-include-paths.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/compiler-include-paths.q0000644000175100017510000000036715232633614033255 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c"] property bool dummy: { console.info("compilerIncludePaths: %%" + cpp.compilerIncludePaths + "%%"); return true; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/defines/0000755000175100017510000000000015232633614023562 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/defines/main.c0000644000175100017510000000016015232633614024647 0ustar runnerrunner#ifndef FOO #error FOO missing! #endif #ifndef BAR #error BAR missing! #endif int main(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/defines/defines.qbs0000644000175100017510000000021515232633614025704 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { cpp.defines: ["FOO", "BAR"] files: ["main.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/cosmic.lkf0000644000175100017510000000000315232633614024111 0ustar runnerrunner@* qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/target-platform/0000755000175100017510000000000015232633614025255 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/target-platform/target-platform.qbs0000644000175100017510000000132215232633614031072 0ustar runnerrunnerProduct { Depends { name: "cpp" } condition: { if (qbs.toolchainType === "keil" || qbs.toolchainType === "iar" || qbs.toolchainType === "sdcc" || qbs.toolchainType === "cosmic") { var hasNoPlatform = (qbs.targetPlatform === "none"); var hasNoOS = (qbs.targetOS.length === 1 && qbs.targetOS[0] === "none"); console.info("has no platform: " + hasNoPlatform); console.info("has no os: " + hasNoOS); } else { console.info("unsupported toolset: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); return false; } return true; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs0000644000175100017510000000200315232633614026667 0ustar runnerrunnerimport qbs.Host BareMetalProduct { type: "application" consoleApplication: true property bool dummy: { if (qbs.targetPlatform !== Host.platform() || qbs.architecture !== Host.architecture()) { function supportsCrossRun() { // We can run 32 bit applications on 64 bit Windows. if (Host.platform() === "windows" && Host.architecture() === "x86_64" && qbs.targetPlatform === "windows" && qbs.architecture === "x86") { return true; } } if (!supportsCrossRun()) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); } } Group { condition: qbs.toolchain.includes("cosmic") files: "cosmic.lkf" fileTags: "linkerscript" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/0000755000175100017510000000000015232633614027251 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-cosmic.s0000644000175100017510000000010315232633614031461 0ustar runnerrunner_main: movs r0, #0 bx lr xdef _main end qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-gcc.s0000644000175100017510000000021615232633614030617 0ustar runnerrunner .global _main .type _main, @function _main: push.l r10 mov.L r0, r10 mov.L #0, r5 mov.L r5, r1 rtsd #4, r10-r10 qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-iar.s0000644000175100017510000000013615232633614030752 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:REORDER:NOROOT(0) main: MOV.W #0x0, R0 RTS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-cosmic.s0000644000175100017510000000010115232633614031620 0ustar runnerrunner_main: .dcall "2,0,_main" rts xdef _main end qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/78k-iar.s0000644000175100017510000000012315232633614030613 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:NOROOT(0) main: MOVW AX, #0 RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-iar.s0000644000175100017510000000011415232633614030633 0ustar runnerrunner PUBLIC _main SECTION CODE:CODE:ROOT(2) _main: BRA _main END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-gcc.s0000644000175100017510000000015115232633614030751 0ustar runnerrunner .global main .type main, @function main: link.w %fp, #0 clr.l %d0 unlk %fp rts qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-iar.s0000644000175100017510000000014615232633614030711 0ustar runnerrunner PUBLIC _main RSEG `CODE`:CODE:NOROOT(2) CODE _main: MOV zero, r1 JMP [lp] END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-iar.s0000644000175100017510000000015615232633614031140 0ustar runnerrunner PUBLIC main RSEG NEAR_CODE:CODE:NOROOT(0) main: MOV R2, #0x0 MOV R3, #0x0 RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-iar.s0000644000175100017510000000014115232633614031230 0ustar runnerrunner PUBLIC main RSEG `CODE`:CODE:REORDER:NOROOT(1) main: MOV.W #0x0, R12 RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-gcc.s0000644000175100017510000000013115232633614030752 0ustar runnerrunner .global main .type main, %function main: ldi r24, 0 ldi r25, 0 ret qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/sh-iar.s0000644000175100017510000000015415232633614030620 0ustar runnerrunner PUBLIC _main SECTION `.code32.text`:CODE:NOROOT(2) _main: CODE MOV #0, R0 RTS/N END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-iar.s0000644000175100017510000000015715232633614031104 0ustar runnerrunner PUBLIC main SECTION `.near_func.text`:CODE:REORDER:NOROOT(0) CODE main: CLRW X RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-iar.s0000644000175100017510000000015315232633614031142 0ustar runnerrunner PUBLIC main RSEG CODE32:CODE:REORDER:NOROOT(2) CODE main: MOV R12, 0x0 RET R12 END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-iar.s0000644000175100017510000000014115232633614030772 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:NOROOT(1) main: LDI R16, 0 LDI R17, 0 RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-iar.s0000644000175100017510000000015115232633614030762 0ustar runnerrunner PUBLIC main SECTION `.text`:CODE:NOROOT(1) THUMB main: MOVS R0, #+0 BX LR END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/cr16-iar.s0000644000175100017510000000013115232633614030754 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:NOROOT(0) main: MOVW $0, R0 JUMP (RA) END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-iar.s0000644000175100017510000000015315232633614031333 0ustar runnerrunner PUBLIC main SECTION `.text`:CODE:REORDER:NOROOT(2) CODE main: MV A0, ZERO RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-keil.s0000644000175100017510000000016515232633614031140 0ustar runnerrunner THUMB AREA ||.text||, CODE, READONLY, ALIGN = 1 main PROC MOVS r0, #0 BX lr ENDP END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/xtensa-gcc.s0000644000175100017510000000031715232633614031472 0ustar runnerrunner .global main .type main, @function main: addi sp, sp, -16 s32i.n a15, sp, 12 mov.n a15, sp movi.n a2, 0 mov.n sp, a15 l32i.n a15, sp, 12 addi sp, sp, 16 ret.n qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32r-gcc.s0000644000175100017510000000020015232633614030742 0ustar runnerrunner .global main .type main, @function main: push fp mv fp, sp ldi r4, #0 mv r0, r4 pop fp jmp lr qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-iar.s0000644000175100017510000000014115232633614031122 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:REORDER:NOROOT(0) main: CLRB CLRA RTS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-gcc.s0000644000175100017510000000021215232633614031117 0ustar runnerrunner .global main .type main, @function main: stm --sp, r7, lr mov r7, sp mov r8, 0 mov r12, r8 ldm sp++, r7, pc qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-gcc.s0000644000175100017510000000027015232633614030670 0ustar runnerrunner .global _main .type _main, @function _main: add -4, sp st.w r29, 0[sp] mov sp, r29 mov 0, r10 mov r29, sp ld.w 0[sp], r29 add 4, sp jmp [r31] qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-gcc.s0000644000175100017510000000026415232633614031317 0ustar runnerrunner .globl main .type main, @function main: add sp, sp, -16 sd s0, 8(sp) add s0, sp, 16 li a5, 0 mv a0, a5 ld s0, 8(sp) add sp, sp, 16 jr ra qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-sdcc.s0000644000175100017510000000012515232633614031212 0ustar runnerrunner .globl main .area DSEG (PAG) .area HOME (CODE) main: clra tax qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/r32c-iar.s0000644000175100017510000000020215232633614030751 0ustar runnerrunner PUBLIC main RSEG CODE24:CODE:REORDER:NOROOT(0) main: MOV.L:Z #0x0, R2R0 RTS RSEG SBREF:DATA:NOROOT(0) END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-gcc.s0000644000175100017510000000023715232633614030765 0ustar runnerrunnerr8 = 0xffef0 .text .global _main .type _main, @function _main: subw sp, #2 clrw ax movw [sp], ax movw r8, ax addw sp, #2 ret qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-iar.s0000644000175100017510000000012115232633614030765 0ustar runnerrunner PUBLIC main RSEG FCODE:CODE:NOROOT(1) main: CLR.L D0 RTS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-cosmic.s0000644000175100017510000000010115232633614031465 0ustar runnerrunner_main: .dcall "8,0,_main" rts xdef _main end qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-iar.s0000644000175100017510000000014015232633614031046 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:REORDER:NOROOT(0) main: LDHX #0x0000 RTS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-keil.s0000644000175100017510000000024715232633614031312 0ustar runnerrunnerPUBLIC main MAIN_SEG SEGMENT CODE RSEG MAIN_SEG main: MOV R6, #0x0 MOV R7, #0x0 RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rh850-iar.s0000644000175100017510000000015115232633614031051 0ustar runnerrunner PUBLIC _main SECTION `.text`:CODE:NOROOT(2) CODE _main: MOV r0, r10 JMP [lp] END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-sdcc.s0000644000175100017510000000012715232633614031242 0ustar runnerrunner .globl main .area DATA .area SSEG .area HOME main: clrw x ret qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-iar.s0000644000175100017510000000014015232633614030775 0ustar runnerrunner PUBLIC _main SECTION `.text`:CODE:NOROOT(0) CODE _main: CLRW AX RET END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-cosmic.s0000644000175100017510000000014315232633614031601 0ustar runnerrunner scross off _main: .dcall "2,0,_main" ret .scheck _main xdef _main end qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-gcc.s0000644000175100017510000000011515232633614030743 0ustar runnerrunner .global main .type main, %function main: mov r0, #0 bx lr qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-gcc.s0000644000175100017510000000011715232633614030732 0ustar runnerrunner .global _main .type _main, @function _main: mov.w #0, r0 rts qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs251-keil.s0000644000175100017510000000024115232633614031366 0ustar runnerrunnerPUBLIC main MAIN_SEG SEGMENT CODE RSEG MAIN_SEG main PROC XRL WR6,WR6 RET ENDP END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/c166-keil.s0000644000175100017510000000023415232633614031035 0ustar runnerrunnerMAIN_SEG SECTION CODE WORD 'NCODE' main PROC NEAR MOV R4, #0 RET main ENDP MAIN_SEG ENDS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m16c-iar.s0000644000175100017510000000013615232633614030754 0ustar runnerrunner PUBLIC main RSEG CODE:CODE:REORDER:NOROOT(0) main: MOV.W #0x0, R0 RTS END qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-cosmic.s0000644000175100017510000000010115232633614031545 0ustar runnerrunner_main: .dcall "2,0,_main" rts xdef _main end ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/one-object-asm-application.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/one-object-asm-appli0000644000175100017510000001037115232633614033104 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { condition: { if (qbs.toolchainType === "cosmic") { if (qbs.architecture.startsWith("arm")) return true; if (qbs.architecture === "stm8") return true; if (qbs.architecture === "hcs8") return true; if (qbs.architecture === "hcs12") return true; if (qbs.architecture === "m68k") return true; } else if (qbs.toolchainType === "keil") { if (qbs.architecture.startsWith("arm")) return true; if (qbs.architecture === "mcs51") return true; if (qbs.architecture === "mcs251") return true; if (qbs.architecture === "c166") return true; } else if (qbs.toolchainType === "iar") { if (qbs.architecture.startsWith("arm")) return true; if (qbs.architecture === "mcs51") return true; if (qbs.architecture === "stm8") return true; if (qbs.architecture === "avr") return true; if (qbs.architecture === "avr32") return true; if (qbs.architecture === "msp430") return true; if (qbs.architecture === "rl78") return true; if (qbs.architecture === "rh850") return true; if (qbs.architecture === "v850") return true; if (qbs.architecture === "78k") return true; if (qbs.architecture === "r32c") return true; if (qbs.architecture === "sh") return true; if (qbs.architecture === "cr16") return true; if (qbs.architecture === "m16c") return true; if (qbs.architecture === "hcs8") return true; if (qbs.architecture === "hcs12") return true; if (qbs.architecture === "rx") return true; if (qbs.architecture === "m32c") return true; if (qbs.architecture === "riscv") return true; if (qbs.architecture === "m68k") return true; } else if (qbs.toolchainType === "sdcc") { if (qbs.architecture === "mcs51") return true; if (qbs.architecture === "stm8") return true; if (qbs.architecture === "hcs8") return true; } else if (qbs.toolchainType === "gcc") { if (qbs.architecture.startsWith("arm")) return true; if (qbs.architecture === "avr") return true; if (qbs.architecture === "avr32") return true; if (qbs.architecture === "msp430") return true; if (qbs.architecture === "xtensa") return true; if (qbs.architecture === "rl78") return true; if (qbs.architecture === "m32c") return true; if (qbs.architecture === "m32r") return true; if (qbs.architecture === "m68k") return true; if (qbs.architecture === "v850") return true; if (qbs.architecture === "riscv") return true; if (qbs.architecture === "rx") return true; } console.info("unsupported toolset: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); return false; } Properties { condition: qbs.toolchainType === "gcc" && qbs.architecture === "msp430" // We need to use this workaround to enable // the cpp.driverFlags property. cpp.linkerPath: cpp.compilerPathByLanguage["c"] } Properties { condition: qbs.toolchainType === "iar" && qbs.architecture.startsWith("arm") cpp.entryPoint: "main" } files: [(qbs.architecture.startsWith("arm") ? "arm" : qbs.architecture) + "-" + qbs.toolchainType + ".s"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-sdcc.s0000644000175100017510000000020215232633614031271 0ustar runnerrunner .globl main .area PSEG (PAG,XDATA) .area XSEG (XDATA) .area HOME (CODE) main: mov dptr, #0x0000 ret qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-gcc.s0000644000175100017510000000011715232633614031214 0ustar runnerrunner .global main .type main, %function main: mov #0, r15 .LIRD0: qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/0000755000175100017510000000000015232633614026227 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/main.c0000644000175100017510000000013015232633614027311 0ustar runnerrunner#include #include int main(void) { return FOO_VALUE - BAR_VALUE; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/system-include-paths.qbs0000644000175100017510000000023015232633614033013 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c"] cpp.systemIncludePaths: ["foo", "bar"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/bar/0000755000175100017510000000000015232633614026773 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/bar/bar.h0000644000175100017510000000010215232633614027701 0ustar runnerrunner#ifndef BAR_H #define BAR_H #define BAR_VALUE 1 #endif // BAR_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/foo/0000755000175100017510000000000015232633614027012 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/system-include-paths/foo/foo.h0000644000175100017510000000010215232633614027737 0ustar runnerrunner#ifndef FOO_H #define FOO_H #define FOO_VALUE 1 #endif // FOO_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/0000755000175100017510000000000015232633614025232 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/0000755000175100017510000000000015232633614026524 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/sdcc.qbs0000644000175100017510000000146615232633614030156 0ustar runnerrunnerimport qbs.Probes Product { id: product condition: qbs.toolchainType === "sdcc" Depends { name: "cpp" } Probes.SdccProbe { id: probe compilerFilePath: cpp.compilerPath enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture } property bool dummy: { if (!product.condition) return; if (!probe.found || !probe.endianness || !probe.compilerDefinesByLanguage || !probe.includePaths || (probe.includePaths.length === 0) || (qbs.architecture !== probe.architecture)) { console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/dmc.qbs0000644000175100017510000000164415232633614030003 0ustar runnerrunnerimport qbs.Probes Product { id: product condition: qbs.toolchainType === "dmc" Depends { name: "cpp" } Probes.DmcProbe { id: probe compilerFilePath: cpp.compilerPath enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage _targetPlatform: qbs.targetPlatform _targetArchitecture: qbs.architecture _targetExtender: cpp.extenderName } property bool dummy: { if (!product.condition) return; if (!probe.found || !probe.compilerDefinesByLanguage || !probe.includePaths || (probe.includePaths.length === 0) || (qbs.architecture !== probe.architecture) || (qbs.targetPlatform !== probe.targetPlatform)) { console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/watcom.qbs0000644000175100017510000000206515232633614030530 0ustar runnerrunnerimport qbs.Probes Product { id: product condition: qbs.toolchainType === "watcom" Depends { name: "cpp" } Probes.WatcomProbe { id: probe compilerFilePath: cpp.compilerPath enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage _pathListSeparator: qbs.pathListSeparator _toolchainInstallPath: cpp.toolchainInstallPath _targetPlatform: qbs.targetPlatform _targetArchitecture: qbs.architecture } property bool dummy: { if (!product.condition) return; if (!probe.found || !probe.endianness || !probe.compilerDefinesByLanguage || !probe.environment || !probe.includePaths || (probe.includePaths.length === 0) || (qbs.architecture !== probe.architecture) || (qbs.targetPlatform !== probe.targetPlatform)) { console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/toolchain-probe/toolchain-probe.qbs0000644000175100017510000000016615232633614031031 0ustar runnerrunnerProject { references: [ "probes/dmc.qbs", "probes/sdcc.qbs", "probes/watcom.qbs", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/two-object-application/0000755000175100017510000000000015232633614026523 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/two-object-application/fun.c0000644000175100017510000000003615232633614027456 0ustar runnerrunnerint f(void) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/two-object-application/main.c0000644000175100017510000000007015232633614027610 0ustar runnerrunnerextern int f(void); int main(void) { return f(); } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/two-object-application/two-object-application.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/two-object-application/two-object-application.q0000644000175100017510000000016615232633614033266 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c", "fun.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/0000755000175100017510000000000015232633614025661 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/main.c0000644000175100017510000000013015232633614026743 0ustar runnerrunner#include "foo.h" #include "bar.h" int main(void) { return FOO_VALUE - BAR_VALUE; } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/bar/0000755000175100017510000000000015232633614026425 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/bar/bar.h0000644000175100017510000000010215232633614027333 0ustar runnerrunner#ifndef BAR_H #define BAR_H #define BAR_VALUE 1 #endif // BAR_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/user-include-paths.qbs0000644000175100017510000000022215232633614032100 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c"] cpp.includePaths: ["foo", "bar"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/foo/0000755000175100017510000000000015232633614026444 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/user-include-paths/foo/foo.h0000644000175100017510000000010215232633614027371 0ustar runnerrunner#ifndef FOO_H #define FOO_H #define FOO_VALUE 1 #endif // FOO_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/0000755000175100017510000000000015232633614027422 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/main.c0000644000175100017510000000013015232633614030504 0ustar runnerrunner#include #include int main(void) { return FOO_VALUE - BAR_VALUE; } ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/distribution-include-paths.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/distribution-include0000644000175100017510000000023615232633614033506 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c"] cpp.distributionIncludePaths: ["foo", "bar"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/bar/0000755000175100017510000000000015232633614030166 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/bar/bar.h0000644000175100017510000000010215232633614031074 0ustar runnerrunner#ifndef BAR_H #define BAR_H #define BAR_VALUE 1 #endif // BAR_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/foo/0000755000175100017510000000000015232633614030205 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/foo/foo.h0000644000175100017510000000010215232633614031132 0ustar runnerrunner#ifndef FOO_H #define FOO_H #define FOO_VALUE 1 #endif // FOO_H qbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-application/0000755000175100017510000000000015232633614026473 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-application/main.c0000644000175100017510000000004115232633614027556 0ustar runnerrunnerint main(void) { return 0; } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-application/one-object-application.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-baremetal/one-object-application/one-object-application.q0000644000175100017510000000015515232633614033204 0ustar runnerrunnerimport "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { files: ["main.c"] } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxbase.cpp0000644000175100017510000002574515232633614022435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxbase.h" #include "../shared.h" #include #include #include #include #include #include #include using qbs::Internal::HostOsInfo; using qbs::Internal::removeDirectoryWithContents; using qbs::InstallOptions; using qbs::Profile; static QString initQbsExecutableFilePath() { const QString qbsInstallDir = QString::fromLocal8Bit(qgetenv("QBS_INSTALL_DIR")); return HostOsInfo::appendExecutableSuffix(QDir::cleanPath(!qbsInstallDir.isEmpty() ? qbsInstallDir + QLatin1String("/bin/qbs") : QCoreApplication::applicationDirPath() + QLatin1String("/qbs"))); } static bool supportsBuildDirectoryOption(const QString &command) { return !(QStringList() << "help" << "config" << "config-ui" << "setup-android" << "setup-qt" << "setup-toolchains" << "create-project") .contains(command); } static bool supportsSettingsDirOption(const QString &command) { return !(QStringList() << "help" << "create-project").contains(command); } TestBlackboxBase::TestBlackboxBase(const QString &testDataSrcDir, const QString &testName) : testDataDir(testWorkDir(testName)), testSourceDir(testDataSourceDir(testDataSrcDir)), qbsExecutableFilePath(initQbsExecutableFilePath()), defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot()) { QLocale::setDefault(QLocale::c()); } int TestBlackboxBase::runQbs(const QbsRunParameters ¶ms) { QStringList args; if (!params.command.isEmpty()) args << params.command; if (!params.settingsDir.isEmpty() && supportsSettingsDirOption(params.command)) args << "--settings-dir" << params.settingsDir; if (supportsBuildDirectoryOption(params.command)) { args.push_back(QStringLiteral("-d")); args.push_back(params.buildDirectory.isEmpty() ? QStringLiteral(".") : params.buildDirectory); } args << params.arguments; const bool commandImpliesResolve = params.command.isEmpty() || params.command == "resolve" || params.command == "build" || params.command == "install" || params.command == "run" || params.command == "generate"; if (!params.profile.isEmpty() && commandImpliesResolve) { args.push_back(QLatin1String("profile:") + params.profile); } QProcess process; if (!params.workingDir.isEmpty()) process.setWorkingDirectory(params.workingDir); process.setProcessEnvironment(params.environment); process.start(qbsExecutableFilePath, args); int exitCode = 0; if (!process.waitForStarted() || !process.waitForFinished(testTimeoutInMsecs()) || process.exitStatus() != QProcess::NormalExit) { if (!params.expectCrash) { QTest::qFail("qbs did not run correctly", __FILE__, __LINE__); qDebug("%s", qPrintable(process.errorString())); } exitCode = -1; } else if (m_qbsStdout.contains("Memory leak:")) { exitCode = 27; } else { exitCode = process.exitCode(); } m_qbsStderr = process.readAllStandardError(); m_qbsStdout = process.readAllStandardOutput(); sanitizeOutput(&m_qbsStderr); sanitizeOutput(&m_qbsStdout); const bool shouldLog = (process.exitStatus() != QProcess::NormalExit || exitCode != 0) && !params.expectFailure; if (!m_qbsStderr.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDERR"))) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDOUT"))) qDebug("%s", m_qbsStdout.constData()); return exitCode; } /*! Recursive copy from directory to another. Note that this updates the file stamps on Linux but not on Windows. */ void TestBlackboxBase::ccp(const QString &sourceDirPath, const QString &targetDirPath) { QDir currentDir; QDirIterator dit(sourceDirPath, QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); while (dit.hasNext()) { dit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + dit.fileName(); currentDir.mkpath(targetPath); ccp(dit.filePath(), targetPath); } QDirIterator fit(sourceDirPath, QDir::Files | QDir::Hidden); while (fit.hasNext()) { fit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + fit.fileName(); QFile::remove(targetPath); // allowed to fail QFile src(fit.filePath()); QVERIFY2(src.copy(targetPath), qPrintable(src.errorString())); } } void TestBlackboxBase::rmDirR(const QString &dir) { QString errorMessage; removeDirectoryWithContents(dir, &errorMessage); } QByteArray TestBlackboxBase::unifiedLineEndings(const QByteArray &ba) { if (HostOsInfo::isWindowsHost()) { QByteArray result; result.reserve(ba.size()); for (const char &c : ba) { if (c != '\r') result.append(c); } return result; } else { return ba; } } void TestBlackboxBase::sanitizeOutput(QByteArray *ba) { if (HostOsInfo::isWindowsHost()) ba->replace('\r', ""); } void TestBlackboxBase::initTestCase() { QVERIFY(regularFileExists(qbsExecutableFilePath)); const SettingsPtr s = settings(); if (profileName() != "none" && !s->profiles().contains(profileName())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' could not be found. Please set it up on your machine.")); validateTestProfile(); // Initialize the test data directory. QVERIFY(testDataDir != testSourceDir); rmDirR(testDataDir); QDir().mkpath(testDataDir); ccp(testSourceDir, testDataDir); QDir().mkpath(testDataDir + "/find"); ccp(testSourceDir + "/../find", testDataDir + "/find"); QVERIFY(copyDllExportHeader(testSourceDir, testDataDir)); } void TestBlackboxBase::validateTestProfile() { const SettingsPtr s = settings(); if (profileName() != "none" && !s->profiles().contains(profileName())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' could not be found. Please set it up on your machine.")); if (!m_needsQt) return; const QStringList qmakeFilePaths = Profile(profileName(), s.get()) .value("moduleProviders.Qt.qmakeFilePaths").toStringList(); if (!qmakeFilePaths.empty()) return; if (!findExecutable(QStringList{"qmake"}).isEmpty()) return; QSKIP(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' is not a valid Qt profile and Qt was not found " "in the global search paths.")); } QString TestBlackboxBase::findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); for (const QString &fileName : fileNames) { QFileInfo fi(fileName); if (fi.isAbsolute()) return fi.exists() ? fileName : QString(); for (const QString &ppath : path) { const QString fullPath = HostOsInfo::appendExecutableSuffix(ppath + QLatin1Char('/') + fileName); if (QFileInfo(fullPath).exists()) return QDir::cleanPath(fullPath); } } return {}; } QMap TestBlackboxBase::findJdkTools(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-jdk.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-jdk") + "/jdk.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return { {"java", QDir::fromNativeSeparators(tools["java"].toString())}, {"javac", QDir::fromNativeSeparators(tools["javac"].toString())}, {"jar", QDir::fromNativeSeparators(tools["jar"].toString())} }; } qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath) { QStringList arguments; arguments << "-query" << "QT_VERSION"; QProcess qmakeProcess; qmakeProcess.start(qmakeFilePath, arguments); if (!qmakeProcess.waitForStarted() || !qmakeProcess.waitForFinished() || qmakeProcess.exitStatus() != QProcess::NormalExit) { qDebug() << "qmake '" << qmakeFilePath << "' could not be run."; return qbs::Version(); } QByteArray result = qmakeProcess.readAll().simplified(); qbs::Version version = qbs::Version::fromString(result); if (!version.isValid()) qDebug() << "qmake '" << qmakeFilePath << "' version is not valid."; return version; } qbs::Version TestBlackboxBase::conanVersion(const QString &conanFilePath) { QProcess conan; conan.start(conanFilePath, {"--version"}); if (!waitForProcessSuccess(conan)) return qbs::Version{}; return qbs::Version::fromString(QString::fromLocal8Bit(conan.readAllStandardOutput()) .trimmed() .remove(QStringLiteral("Conan version")) .trimmed()); } bool waitForProcessSuccess(QProcess &p, int msecs) { if (!p.waitForStarted(msecs) || !p.waitForFinished(msecs)) { qDebug() << p.errorString(); return false; } if (p.exitCode() != 0) { qDebug().noquote() << p.readAllStandardError(); return false; } return true; } qbs-src-3.3.1/tests/auto/blackbox/blackbox-apple.qbs0000644000175100017510000000103415232633614021773 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-apple" Depends { name: "Qt.xml" } Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-apple/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxapple.cpp", "tst_blackboxapple.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/blackbox-baremetal.qbs0000644000175100017510000000101515232633614022625 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-baremetal" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-baremetal/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxbaremetal.cpp", "tst_blackboxbaremetal.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/find/0000755000175100017510000000000015232633614017322 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/find/find-android.qbs0000644000175100017510000000572215232633614022375 0ustar runnerrunnerimport qbs.TextFile Product { property string packageName: "" qbs.targetPlatform: "android" multiplexByQbsProperties: ["architectures"] Properties { condition: qbs.architectures && qbs.architectures.length > 1 aggregate: true multiplexedType: "json_arch" } Depends { name: "Android.sdk"; required: false } Depends { name: "Android.ndk"; required: false } type: ["json"] Rule { multiplex: true property stringList inputTags: "json_arch" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { filePath: ["android.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; for (var i in inputs["json_arch"]) { var tf = new TextFile(inputs["json_arch"][i].filePath, TextFile.ReadOnly); var json = JSON.parse(tf.readAll()); tools["ndk"] = json["ndk"]; tools["ndk-samples"] = json["ndk-samples"]; tf.close(); } if (product.moduleProperty("Android.sdk", "present")) { tools["sdk"] = product.moduleProperty("Android.sdk", "sdkDir"); tools["sdk-build-tools-dx"] = product.Android.sdk.dxFilePath; tools["sdk-build-tools-d8"] = product.Android.sdk.d8FilePath; } if (product.java && product.java.present) tools["jar"] = product.java.jarFilePath; var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } Rule { multiplex: true Artifact { filePath: ["android_arch.json"] fileTags: ["json_arch"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("Android.ndk", "present")) { tools["ndk"] = product.moduleProperty("Android.ndk", "ndkDir"); tools["ndk-samples"] = product.Android.ndk.ndkSamplesDir; } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/find/find-nodejs.qbs0000644000175100017510000000167515232633614022242 0ustar runnerrunnerimport qbs.TextFile Product { Depends { name: "nodejs"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["nodejs.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("nodejs", "present")) { tools["node"] = product.moduleProperty("nodejs", "interpreterFilePath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/find/find-typescript.qbs0000644000175100017510000000176515232633614023166 0ustar runnerrunnerimport qbs.TextFile Product { Depends { name: "nodejs"; required: false } Depends { name: "typescript"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["typescript.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("typescript", "present")) { tools["tsc"] = product.moduleProperty("typescript", "compilerPath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/find/find-jdk.qbs0000644000175100017510000000213715232633614021522 0ustar runnerrunnerimport qbs.TextFile Product { Depends { name: "java"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["jdk.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("java", "present")) { tools["javac"] = product.moduleProperty("java", "compilerFilePath"); tools["java"] = product.moduleProperty("java", "interpreterFilePath"); tools["jar"] = product.moduleProperty("java", "jarFilePath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/find/find-xcode.qbs0000644000175100017510000000315215232633614022052 0ustar runnerrunnerimport qbs.Host import qbs.TextFile Product { property bool isSignedByDefault: { // on Apple silicon, apps are signed by default return Host.architecture() === "arm64" && (qbs.targetOS.includes("macos") || qbs.targetOS.includes("ios-simulator") && qbs.targetArchitecture === "arm64") } Depends { name: "xcode"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["xcode.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; var present = product.moduleProperty("xcode", "present"); tools["present"] = !!present; if (present) { var keys = [ "developerPath", "version" ]; for (var i = 0; i < keys.length; ++i) { var key = keys[i]; tools[key] = product.xcode[key]; } } tools["isSignedByDefault"] = product.isSignedByDefault; var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/blackbox-java.qbs0000644000175100017510000000077115232633614021622 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-java" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-java/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxjava.cpp", "tst_blackboxjava.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxjoblimits.cpp0000644000175100017510000001765615232633614023521 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxbase.h" #include "../shared.h" #include class TestBlackboxJobLimits : public TestBlackboxBase { Q_OBJECT public: TestBlackboxJobLimits(); private slots: void initTestCase(); void jobLimits_data(); void jobLimits(); }; TestBlackboxJobLimits::TestBlackboxJobLimits() : TestBlackboxBase (SRCDIR "/testdata-joblimits", "blackbox-joblimits") { } void TestBlackboxJobLimits::initTestCase() { TestBlackboxBase::initTestCase(); QDir::setCurrent(testDataDir + "/job-limits-init"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Skip test in cross-compiled build"); } void TestBlackboxJobLimits::jobLimits_data() { QTest::addColumn("projectJobCount"); QTest::addColumn("productJobCount"); QTest::addColumn("moduleJobCount"); QTest::addColumn("prefsJobCount"); QTest::addColumn("cliJobCount"); QTest::addColumn("projectPrecedence"); QTest::addColumn("expectSuccess"); for (int projectJobCount = -1; projectJobCount <= 1; ++projectJobCount) { for (int productJobCount = -1; productJobCount <= 1; ++productJobCount) { for (int moduleJobCount = -1; moduleJobCount <= 1; ++moduleJobCount) { for (int prefsJobCount = -1; prefsJobCount <= 1; ++prefsJobCount) { for (int cliJobCount = -1; cliJobCount <= 1; ++cliJobCount) { QString description = QString("project:%1/" "product:%2/module:%3/prefs:%4/cli:%5/project precedence") .arg(projectJobCount).arg(productJobCount).arg(moduleJobCount) .arg(prefsJobCount).arg(cliJobCount).toLocal8Bit(); bool expectSuccess; switch (productJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (projectJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (moduleJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (cliJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: expectSuccess = prefsJobCount == 1; break; } break; } break; } break; } QTest::newRow(qPrintable(description)) << projectJobCount << productJobCount << moduleJobCount << prefsJobCount << cliJobCount << true << expectSuccess; description = QString("project:%1/" "product:%2/module:%3/prefs:%4/cli:%5/default precedence") .arg(projectJobCount).arg(productJobCount).arg(moduleJobCount) .arg(prefsJobCount).arg(cliJobCount).toLocal8Bit(); switch (cliJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (prefsJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (productJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (projectJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: expectSuccess = moduleJobCount == 1; break; } break; } break; } break; } QTest::newRow(qPrintable(description)) << projectJobCount << productJobCount << moduleJobCount << prefsJobCount << cliJobCount << false << expectSuccess; } } } } } } void TestBlackboxJobLimits::jobLimits() { QDir::setCurrent(testDataDir + "/job-limits"); QFETCH(int, projectJobCount); QFETCH(int, productJobCount); QFETCH(int, moduleJobCount); QFETCH(int, prefsJobCount); QFETCH(int, cliJobCount); QFETCH(bool, projectPrecedence); QFETCH(bool, expectSuccess); SettingsPtr theSettings = settings(); qbs::Internal::TemporaryProfile profile("jobLimitsProfile", theSettings.get()); profile.p.setValue("preferences.jobLimit.singleton", prefsJobCount); profile.p.setValue("baseProfile", profileName()); theSettings->sync(); QbsRunParameters resolveParams("resolve"); resolveParams.profile = profile.p.name(); resolveParams.arguments << ("project.projectJobCount:" + QString::number(projectJobCount)) << ("project.productJobCount:" + QString::number(productJobCount)) << ("project.moduleJobCount:" + QString::number(moduleJobCount)); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams; buildParams.expectFailure = !expectSuccess; if (cliJobCount != -1) buildParams.arguments << "--job-limits" << ("singleton:" + QString::number(cliJobCount)); if (projectPrecedence) buildParams.arguments << "--enforce-project-job-limits"; buildParams.profile = profile.p.name(); const int exitCode = runQbs(buildParams); if (expectSuccess) QCOMPARE(exitCode, 0); else if (exitCode == 0) QSKIP("no failure with no limit in place, result inconclusive"); else QVERIFY2(m_qbsStderr.contains("exclusive"), m_qbsStderr.constData()); if (exitCode == 0) QCOMPARE(m_qbsStdout.count("running tool"), 5); } QTEST_MAIN(TestBlackboxJobLimits) #include qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxtutorial.h0000644000175100017510000000344415232633614023023 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOXTUTORIAL_H #define TST_BLACKBOXTUTORIAL_H #include "tst_blackboxbase.h" class TestBlackboxTutorial : public TestBlackboxBase { Q_OBJECT public: TestBlackboxTutorial(); private slots: void tutorial_data(); void tutorial(); }; #endif // TST_BLACKBOXTUTORIAL_H qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/0000755000175100017510000000000015232633614021703 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/0000755000175100017510000000000015232633614022512 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs0000644000175100017510000000236115232633614025773 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { WindowsInstallerPackage { name: "QbsSetup" targetName: "qbs" files: ["QbsSetup.wxs", "ExampleScript.bat"] wix.defines: ["scriptName=ExampleScript.bat"] wix.extensions: ["WixBalExtension", "WixUIExtension"] qbs.targetPlatform: "windows" Export { Depends { name: "wix" } wix.defines: base.concat(["msiName=" + FileInfo.joinPaths(exportingProduct.buildDirectory, exportingProduct.targetName + wix.windowsInstallerSuffix)]) } } WindowsSetupPackage { Depends { name: "QbsSetup" } condition: Host.os().includes("windows") // currently does not work in Wine with WiX 3.9 name: "QbsBootstrapper" targetName: "qbs-setup-" + qbs.architecture files: ["QbsBootstrapper.wxs"] qbs.architecture: original || "x86" qbs.targetPlatform: "windows" } WindowsInstallerPackage { name: "RegressionBuster9000" files: ["QbsSetup.wxs", "Qt.wxs", "de.wxl"] wix.defines: ["scriptName=ExampleScript.bat"] wix.cultures: [] qbs.architecture: original || "x86" qbs.targetPlatform: "windows" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/QbsBootstrapper.wxs0000644000175100017510000000065115232633614026411 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/de.wxl0000644000175100017510000000011615232633614023634 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/QbsSetup.wxs0000644000175100017510000000254415232633614025030 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/ExampleScript.bat0000644000175100017510000000002215232633614025754 0ustar runnerrunnerecho Hello world! qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wix/Qt.wxs0000644000175100017510000000020415232633614023635 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wixDependencies/0000755000175100017510000000000015232633614025021 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wixDependencies/main.c0000644000175100017510000000003115232633614026103 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wixDependencies/QbsSetup.wxs0000644000175100017510000000276415232633614027343 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/wixDependencies/wixDependencies.qbs0000644000175100017510000000423415232633614030651 0ustar runnerrunnerimport qbs.TextFile Project { WindowsInstallerPackage { Depends { name: "app" } Depends { name: "lib" } name: "QbsSetup" targetName: "qbs" files: ["QbsSetup.wxs"] wix.extensions: ["WixBalExtension", "WixUIExtension"] destinationDirectory: project.buildDirectory } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } destinationDirectory: project.buildDirectory } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var j = 0; j < 1000; ++j) { // Artificial delay. for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } } }; return [cmd]; } } destinationDirectory: project.buildDirectory } } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetupDependencies/0000755000175100017510000000000015232633614026236 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs0000644000175100017510000000464415232633614033310 0ustar runnerrunnerimport qbs.TextFile Project { InnoSetup { property bool _test: { var present = qbs.targetOS.includes("windows") && innosetup.present; console.info("has innosetup: " + present); } Depends { name: "app" } Depends { name: "lib" } name: "QbsSetup" targetName: "qbs.setup.test" version: "1.5" files: [ "test.iss" ] innosetup.verboseOutput: true innosetup.defines: [ "MyProgram=" + name, "MyProgramVersion=" + version, "buildDirectory=" + project.buildDirectory ] innosetup.compilerFlags: ["/V9"] destinationDirectory: project.buildDirectory } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } destinationDirectory: project.buildDirectory } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } }; return [cmd]; } } destinationDirectory: project.buildDirectory } } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetupDependencies/main.c0000644000175100017510000000003115232633614027320 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetupDependencies/test.iss0000644000175100017510000000032215232633614027732 0ustar runnerrunner[Setup] AppName={#MyProgram} AppVersion={#MyProgramVersion} DefaultDirName={pf}\{#MyProgram} [Files] Source: "{#buildDirectory}\app.exe"; DestDir: "{app}" Source: "{#buildDirectory}\lib.dll"; DestDir: "{app}" qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/codesign/0000755000175100017510000000000015232633614023476 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs0000644000175100017510000000256015232633614026003 0ustar runnerrunnerProject { name: "p" property bool enableSigning: true property string hashAlgorithm property string subjectName property string signingTimestamp CppApplication { name: "A" files: "app.cpp" condition: qbs.toolchain.includes("msvc") codesign.enableCodeSigning: project.enableSigning codesign.hashAlgorithm: project.hashAlgorithm codesign.subjectName: project.subjectName codesign.signingTimestamp: project.signingTimestamp codesign.timestampAlgorithm: "sha256" install: true installDir: "" property bool dummy: { if (codesign.codesignPath) console.info("signtool path: %%" + codesign.codesignPath + "%%"); } } DynamicLibrary { Depends { name: "cpp" } name: "B" files: "app.cpp" condition: qbs.toolchain.includes("msvc") codesign.enableCodeSigning: project.enableSigning codesign.hashAlgorithm: project.hashAlgorithm codesign.subjectName: project.subjectName codesign.signingTimestamp: project.signingTimestamp codesign.timestampAlgorithm: "sha256" install: true installDir: "" property bool dummy: { if (codesign.codesignPath) console.info("signtool path: %%" + codesign.codesignPath + "%%"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/codesign/app.cpp0000644000175100017510000000003115232633614024754 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetup/0000755000175100017510000000000015232633614023727 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetup/inc/0000755000175100017510000000000015232633614024500 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetup/inc/qbsinc.iss0000644000175100017510000000000015232633614026465 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetup/test.iss0000644000175100017510000000016415232633614025427 0ustar runnerrunner#include "qbsinc.iss" [Setup] AppName={#MyProgram} AppVersion={#MyProgramVersion} DefaultDirName={pf}\{#MyProgram} qbs-src-3.3.1/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs0000644000175100017510000000130515232633614026461 0ustar runnerrunnerimport qbs.FileInfo Project { InnoSetup { property bool _test: { var present = qbs.targetOS.includes("windows") && innosetup.present; console.info("has innosetup: " + present); } name: "QbsSetup" targetName: "qbs.setup.test" version: "1.5" files: [ "test.iss" ] innosetup.verboseOutput: true innosetup.includePaths: ["inc"] innosetup.defines: ["MyProgram=" + name, "MyProgramVersion=" + version] innosetup.compilerFlags: ["/V9"] } InnoSetup { name: "Example1" files: [FileInfo.joinPaths(innosetup.toolchainInstallPath, "Examples", name + ".iss")] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/0000755000175100017510000000000015232633614022205 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/job-limits/0000755000175100017510000000000015232633614024256 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp0000644000175100017510000000533115232633614025710 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #if defined(_WIN32) || defined(WIN32) #include #include #else #include #endif static bool tryLock(FILE *f) { const int exitCode = #if defined(_WIN32) || defined(WIN32) _locking(_fileno(f), _LK_NBLCK, 10); #else lockf(fileno(f), F_TLOCK, 10); #endif return exitCode == 0; } int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "tool needs exactly one argument" << std::endl; return 1; } const std::string lockFilePath = std::string(argv[0]) + ".lock"; std::FILE * const lockFile = std::fopen(lockFilePath.c_str(), "w"); if (!lockFile) { std::cerr << "cannot open lock file: " << std::strerror(errno) << std::endl; return 2; } if (!tryLock(lockFile)) { if (errno == EACCES || errno == EAGAIN) { std::cerr << "tool is exclusive" << std::endl; return 3; } else { std::cerr << "unexpected lock failure: " << std::strerror(errno) << std::endl; std::fclose(lockFile); return 4; } } std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::fclose(lockFile); std::FILE * const output = std::fopen(argv[1], "w"); if (!output) { std::cerr << "cannot create output file: " << std::strerror(errno) << std::endl; return 5; } std::fclose(output); } qbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs0000644000175100017510000000610715232633614027042 0ustar runnerrunnerimport qbs.TextFile Project { property int projectJobCount property int productJobCount property int moduleJobCount JobLimit { condition: projectJobCount !== -1 jobPool: "singleton" jobCount: projectJobCount } JobLimit { condition: projectJobCount !== -1 jobPool: "singleton" jobCount: 100 } CppApplication { name: "tool" consoleApplication: true cpp.cxxLanguageVersion: "c++14" Properties { condition: qbs.targetOS.includes("macos") cpp.minimumMacosVersion: "10.9" } files: "main.cpp" Group { fileTagsFilter: "application" fileTags: "tool_tag" } Export { Rule { alwaysRun: true inputs: "tool_in" explicitlyDependsOnFromDependencies: "tool_tag" Artifact { filePath: input.completeBaseName + ".out"; fileTags: "tool_out" } prepare: { var cmd = new Command(explicitlyDependsOn.tool_tag[0].filePath, [output.filePath]); cmd.workingDirectory = product.buildDirectory; cmd.description = "running tool"; cmd.jobPool = "singleton"; return cmd; } } JobLimit { condition: project.moduleJobCount !== -1 jobPool: "singleton" jobCount: project.moduleJobCount } JobLimit { condition: project.moduleJobCount !== -1 jobPool: "singleton" jobCount: 200 } } } Product { name: "p" type: "tool_out" Depends { name: "tool" } Rule { multiplex: true outputFileTags: "tool_in" outputArtifacts: { var artifacts = []; for (var i = 0; i < 5; ++i) artifacts.push({filePath: "file" + i + ".in", fileTags: "tool_in"}); return artifacts; } prepare: { var commands = []; for (var i = 0; i < outputs.tool_in.length; ++i) { var cmd = new JavaScriptCommand(); var output = outputs.tool_in[i]; cmd.output = output.filePath; cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output, TextFile.WriteOnly); f.close(); } commands.push(cmd); }; return commands; } } JobLimit { condition: project.productJobCount !== -1 jobPool: "singleton" jobCount: project.productJobCount } JobLimit { condition: project.productJobCount !== -1 jobPool: "singleton" jobCount: 300 } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/job-limits-init/0000755000175100017510000000000015232633614025217 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-joblimits/job-limits-init/job-limits-init.qbs0000644000175100017510000000071315232633614030741 0ustar runnerrunnerimport qbs.Host Product { property bool _testPlatform: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxexamples.cpp0000644000175100017510000000762015232633614023331 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackboxexamples.h" #include #include QStringList TestBlackboxExamples::collectExamples(const QString &dirPath) { QStringList result; QDir dir(dirPath); const auto subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); for (const auto &subDir : subDirs) { const auto path = dir.filePath(subDir); if (!QFileInfo::exists(path + "/" + subDir + ".qbs")) continue; result.append(QDir(testDataDir).relativeFilePath(path)); } return result; } TestBlackboxExamples::TestBlackboxExamples() : TestBlackboxBase(SRCDIR "/../../../examples/", "blackbox-examples") { // setNeedsQt(); } void TestBlackboxExamples::baremetal_data() { QTest::addColumn("example"); QDir baremetal(testDataDir + "/baremetal/"); const auto subDirs = baremetal.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); for (const auto &subDir : subDirs) { const auto examples = collectExamples(baremetal.filePath(subDir)); for (const auto &example: examples) { const auto relativePath = baremetal.relativeFilePath(example); QTest::newRow(relativePath.toUtf8().data()) << relativePath; } } } void TestBlackboxExamples::baremetal() { QFETCH(QString, example); QVERIFY(QDir::setCurrent(testDataDir + "/" + example)); QCOMPARE(runQbs(), 0); } void TestBlackboxExamples::examples_data() { QTest::addColumn("example"); auto examples = collectExamples(testDataDir); examples.append(collectExamples(testDataDir + "/protobuf")); examples.append(collectExamples(testDataDir + "/flatbuffers")); examples.append(collectExamples(testDataDir + "/cxx-modules")); std::sort(examples.begin(), examples.end()); for (const auto &example: examples) { if (example == u"baremetal") continue; QTest::newRow(example.toUtf8().data()) << example; } } void TestBlackboxExamples::examples() { QFETCH(QString, example); QVERIFY(QDir::setCurrent(testDataDir + "/" + example)); QVERIFY(QDir::current().mkpath("build/conan-qbs-deps")); QbsRunParameters params( {QStringLiteral("-f"), QFileInfo(example).fileName() + QStringLiteral(".qbs"), QStringLiteral("moduleProviders.conan.installDirectory:build")}); QCOMPARE(runQbs(params), 0); } QTEST_MAIN(TestBlackboxExamples) qbs-src-3.3.1/tests/auto/blackbox/CMakeLists.txt0000644000175100017510000000376015232633614021150 0ustar runnerrunneradd_qbs_test(blackbox DEFINES ${QBS_UNIT_TESTS_DEFINES} "QBS_VERSION=\"${QBS_VERSION}\"" SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackbox.cpp tst_blackbox.h ) add_qbs_test(blackbox-android SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxandroid.cpp tst_blackboxandroid.h ) add_qbs_test(blackbox-apple SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxapple.cpp tst_blackboxapple.h ) add_qbs_test(blackbox-baremetal SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxbaremetal.cpp tst_blackboxbaremetal.h ) add_qbs_test(blackbox-clangdb SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_clangdb.cpp tst_clangdb.h ) add_qbs_test(blackbox-java SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxjava.cpp tst_blackboxjava.h ) add_qbs_test(blackbox-joblimits SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxjoblimits.cpp ) add_qbs_test(blackbox-providers SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxproviders.cpp ) add_qbs_test(blackbox-qt SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxqt.cpp tst_blackboxqt.h ) add_qbs_test(blackbox-tutorial SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxtutorial.h tst_blackboxtutorial.cpp ) add_qbs_test(blackbox-windows SOURCES ../shared.h tst_blackboxbase.cpp tst_blackboxbase.h tst_blackboxwindows.cpp tst_blackboxwindows.h ) qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxbase.h0000644000175100017510000000706415232633614022074 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXBASE_H #define TST_BLACKBOXBASE_H #include "../shared.h" #include #include #include class QbsRunParameters { public: QbsRunParameters() { init(); } QbsRunParameters(QString cmd, QStringList args = QStringList()) : command(std::move(cmd)), arguments(std::move(args)) { init(); } QbsRunParameters(QStringList args) : arguments(std::move(args)) { init(); } void init() { expectFailure = false; expectCrash = false; profile = profileName(); settingsDir = settings()->baseDirectory(); environment = defaultEnvironment(); } static QProcessEnvironment defaultEnvironment() { auto result = QProcessEnvironment::systemEnvironment(); result.insert(QStringLiteral("QBS_AUTOTEST_CODE_SIGNING_REQUIRED"), QStringLiteral("0")); return result; } QString command; QStringList arguments; QString buildDirectory; QProcessEnvironment environment; QString profile; QString settingsDir; QString workingDir; bool expectFailure = false; bool expectCrash = false; }; class TestBlackboxBase : public QObject { Q_OBJECT public: TestBlackboxBase(const QString &testDataSrcDir, const QString &testName); public slots: virtual void initTestCase(); static QString findExecutable(const QStringList &fileNames); protected: virtual void validateTestProfile(); void setNeedsQt() { m_needsQt = true; } int runQbs(const QbsRunParameters ¶ms = QbsRunParameters()); void rmDirR(const QString &dir); static QByteArray unifiedLineEndings(const QByteArray &ba); static void sanitizeOutput(QByteArray *ba); static void ccp(const QString &sourceDirPath, const QString &targetDirPath); QMap findJdkTools(int *status); static qbs::Version qmakeVersion(const QString &qmakeFilePath); static qbs::Version conanVersion(const QString &conanFilePath); const QString testDataDir; const QString testSourceDir; const QString qbsExecutableFilePath; const QString defaultInstallRoot; QByteArray m_qbsStderr; QByteArray m_qbsStdout; int m_needsQt = false; }; bool waitForProcessSuccess(QProcess &p, int msecs = 30000); #endif // TST_BLACKBOXBASE_H qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/0000755000175100017510000000000015232633614022226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/0000755000175100017510000000000015232633614031107 5ustar runnerrunner././@LongLink0000644000000000000000000000017700000000000011610 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-p0000644000175100017510000000157515232633614033347 0ustar runnerrunnerProject { qbsModuleProviders: "provider_a" name: "project" Profile { name: "profile1" qbs.sysroot: "/sysroot1" } Profile { name: "profile2" qbs.sysroot: "/sysroot2" } Product { name: "product1" Depends { name: "qbsmetatestmodule" } property bool dummy: { console.info("product1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); } // multiplex over profiles, sysroot should not be cached qbs.profiles: ["profile1", "profile2"] } Product { name: "product2" Depends { name: "qbsmetatestmodule" } property bool dummy: { console.info("product2.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); } // multiplex over profiles, sysroot should not be cached qbs.profiles: ["profile1", "profile2"] } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-provi0000755000175100017510000000000015232633614033452 5ustar runnerrunner././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-provi0000644000175100017510000000036515232633614033460 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { property string sysroot: qbs.sysroot relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", sysroot); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/0000755000175100017510000000000015232633614026227 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/providers-condition.qbs0000644000175100017510000000065515232633614032745 0ustar runnerrunnerProject { name: "project" qbsModuleProviders: ["provider_a", "provider_b"] Product { name: "p1" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule"; required: false } property bool dummy: { console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/module-providers/0000755000175100017510000000000015232633614031527 5ustar runnerrunner././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/module-providers/provider_b.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/module-providers/provider_b0000644000175100017510000000042515232633614033606 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false condition: moduleName === "qbsothermodule" relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); return ""; } } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition/module-providers/provider_a0000644000175100017510000000042215232633614033602 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false condition: moduleName === "qbsmetatestmodule" relativeSearchPaths: { Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/0000755000175100017510000000000015232633614027517 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/providers-condition-probes.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/providers-condition-0000644000175100017510000000065515232633614033526 0ustar runnerrunnerProject { name: "project" qbsModuleProviders: ["provider_a", "provider_b"] Product { name: "p1" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule"; required: false } property bool dummy: { console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/module-providers/0000755000175100017510000000000015232633614033017 5ustar runnerrunner././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/module-providers/provider_b.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/module-providers/pro0000644000175100017510000000062615232633614033546 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false condition: theProbe.found Probe { id: theProbe condition: moduleName === "qbsothermodule" configure: { found = true } } relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); return ""; } } ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-condition-probes/module-providers/pro0000644000175100017510000000062315232633614033543 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false condition: theProbe.found Probe { id: theProbe condition: moduleName === "qbsmetatestmodule" configure: { found = true } } relativeSearchPaths: { Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/allowed-values/0000755000175100017510000000000015232633614025152 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs0000644000175100017510000000013115232633614030600 0ustar runnerrunnerProduct { Depends { name: "qbsmetatestmodule" } qbsModuleProviders: "provider" } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/0000755000175100017510000000000015232633614030452 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs0000644000175100017510000000054415232633614033016 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false property stringList aProperty: "zero" PropertyOptions { name: "aProperty" allowedValues: ["one", "two"] } relativeSearchPaths: { Helpers.writeModule(outputBaseDir, moduleName, "from_provider"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/0000755000175100017510000000000015232633614026435 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs0000644000175100017510000000071215232633614033353 0ustar runnerrunnerProduct { qbsModuleProviders: ["provider_a", "provider_b"] name: "p" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule" } moduleProviders.provider_a.someProp: "someValue" property bool dummy: { console.info("p.qbsmetatestmodule.listProp: " + JSON.stringify(qbsmetatestmodule.listProp)); console.info("p.qbsothermodule.listProp: " + JSON.stringify(qbsothermodule.listProp)); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/0000755000175100017510000000000015232633614031735 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_0000644000175100017510000000040415232633614033647 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { property stringList someProp: "provider_b" relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsothermodule", undefined, someProp); return ""; } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_0000644000175100017510000000040715232633614033652 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { property stringList someProp: "provider_a" relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", undefined, someProp); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/0000755000175100017510000000000015232633614025271 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/conanfile-probe.qbs0000644000175100017510000000103115232633614031036 0ustar runnerrunnerimport qbs.Probes Project { Probes.ConanfileProbe { id: conanProbe conanfilePath: path + "/conanfile.py" additionalArguments: "-pr:a=qbs-test" } CppApplication { consoleApplication: true name: "p" files: "main.cpp" qbsModuleProviders: "conan" moduleProviders.conan.installDirectory: conanProbe.generatedFilesPath qbs.buildVariant: "release" qbs.installPrefix: "" install: true Depends { name: "conanfileprobe.testlib" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/conanfile.py0000644000175100017510000000036515232633614027605 0ustar runnerrunnerfrom conan import ConanFile class Recipe(ConanFile): name = "qbstest" version = "1.0" exports_sources = "*.cpp", "*.h", "*.txt" settings = "os", "compiler", "build_type", "arch" requires = ["conanfileprobe.testlib/1.2.3"] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/main.cpp0000644000175100017510000000007315232633614026721 0ustar runnerrunner#include int main() { HelloWorld h(42); } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/testlib/0000755000175100017510000000000015232633614026737 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/testlib/testlib.cpp0000644000175100017510000000010415232633614031104 0ustar runnerrunner#include "testlib.h" HelloWorld::HelloWorld(int x) : m_x(x) {} qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/testlib/CMakeLists.txt0000644000175100017510000000034315232633614031477 0ustar runnerrunnercmake_minimum_required(VERSION 3.15) project(conanfileprobe.testlib) add_library(${PROJECT_NAME} STATIC testlib.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlib.h") install(TARGETS ${PROJECT_NAME}) qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/testlib/conanfile.py0000644000175100017510000000153015232633614031246 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps import os class ConanModuleProviderTestlib(ConanFile): name = "conanfileprobe.testlib" license = "none" version = "1.2.3" exports_sources = "*.cpp", "*.h", "CMakeLists.txt" settings = "os", "compiler", "build_type", "arch" def requirements(self): pass def layout(self): cmake_layout(self) def generate(self): deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self, generator="Ninja") tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): self.cpp_info.libs = ['conanfileprobe.testlib'] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conanfile-probe/testlib/testlib.h0000644000175100017510000000014315232633614030554 0ustar runnerrunner#pragma once class HelloWorld { public: explicit HelloWorld(int x); private: int m_x; }; qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/broken-provider/0000755000175100017510000000000015232633614025336 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs0000644000175100017510000000043415232633614031156 0ustar runnerrunnerProject { qbsModuleProviders: "provider_a" name: "project" Project { name: "innerProject" Product { name: "p1" Depends { name: "qbsothermodule"; required: false } Depends { name: "qbsmetatestmodule" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/0000755000175100017510000000000015232633614030636 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs0000644000175100017510000000013515232633614033476 0ustar runnerrunnerModuleProvider { relativeSearchPaths: { throw "This provider is broken"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js0000644000175100017510000000160715232633614030313 0ustar runnerrunnervar File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var TextFile = require("qbs.TextFile"); var ModUtils = require("qbs.ModUtils"); function writeModule(outputBaseDir, name, prop, listProp, boolProp) { console.info("Running setup script for " + name); var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", name); File.makePath(moduleDir); var module = new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); module.writeLine("Module {"); module.writeLine(" property string prop: " + ModUtils.toJSLiteral(prop)); if (listProp) { module.writeLine(" property stringList listProp: " + ModUtils.toJSLiteral(listProp)); } if (boolProp) { module.writeLine(" property bool boolProp: " + ModUtils.toJSLiteral(boolProp)); } module.writeLine("}"); module.close(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/QTBUG-51237/0000755000175100017510000000000015232633614023567 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/QTBUG-51237/qtbug-51237.qbs0000644000175100017510000000073715232633614026106 0ustar runnerrunnerProduct { type: "custom" Depends { name: "mymodule" } qbsModuleProviders: "provider" Rule { multiplex: true outputFileTags: ["custom"] prepare: { var theProperty = product.mymodule.listProp; if (!theProperty) throw "Oh no!"; var dummy = new JavaScriptCommand(); dummy.silent = true; dummy.sourceCode = function() {}; return [dummy]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/QTBUG-51237/module-providers/0000755000175100017510000000000015232633614027067 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/QTBUG-51237/module-providers/provider.qbs0000644000175100017510000000037415232633614031434 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { property stringList theProperty relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "mymodule", "from_provider", theProperty); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/0000755000175100017510000000000015232633614026311 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/subproject.qbs0000644000175100017510000000151315232633614031200 0ustar runnerrunnerProject { qbsModuleProviders: "provider_a" name: "project" Project { name: "innerProject" Product { name: "p1" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule"; required: false } property bool dummy: { console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); } } } Product { name: "p2" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule"; required: false } property bool dummy: { console.info("p2.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); console.info("p2.qbsothermodule.prop: " + qbsothermodule.prop); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs0000644000175100017510000000022015232633614033075 0ustar runnerrunnerProject { SubProject { // This strange construct tests QBS-1836 inheritProperties: false filePath: "subproject.qbs" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/0000755000175100017510000000000015232633614031611 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_0000644000175100017510000000044715232633614033532 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_b"); Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); return ""; } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_0000644000175100017510000000032615232633614033526 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/0000755000175100017510000000000015232633614030016 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/0000755000175100017510000000000015232633614030747 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp0000644000175100017510000000033515232633614032323 0ustar runnerrunner#include "libA.h" #include void foo() { std::cout << "hello from foo: "; #ifdef MYLIB_FRAMEWORK std::cout << "bundled: yes"; #else std::cout << "bundled: no"; #endif std::cout << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs0000644000175100017510000000246615232633614032417 0ustar runnerrunnerimport qbs.FileInfo Project { property bool isBundle: false DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.versionEntry: "1.0" name: "libA" bundle.isBundle: project.isBundle bundle.publicHeaders: ["libA.h"] files: "libA.cpp" cpp.defines: { var result = []; if (project.isBundle) result.push("MYLIB_FRAMEWORK"); return result; } qbs.installPrefix: "/usr" install: true installImportLib: true installDir: "lib" Group { files: ["libA.h"] qbs.install: !project.isBundle qbs.installDir: FileInfo.joinPaths("include", product.name) } Group { fileTagsFilter: ["Exporter.pkgconfig.pc"] qbs.install: !project.isBundle qbs.installDir: FileInfo.joinPaths("share", "pkgconfig") } Export { Depends { name: "cpp" } cpp.defines: ["THE_MAGIC_DEFINE"] cpp.includePaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "include")] cpp.libraryPaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "lib")] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h0000644000175100017510000000076115232633614031773 0ustar runnerrunner#pragma once #if defined(_WIN32) || defined(WIN32) # define DECL_EXPORT __declspec(dllexport) # define DECL_IMPORT __declspec(dllimport) #else # define DECL_EXPORT __attribute__((visibility("default"))) # define DECL_IMPORT __attribute__((visibility("default"))) # endif #if defined(LIBA_STATIC_LIBRARY) # define LIBA_EXPORT #else # if defined(MYLIB_LIBRARY) # define LIBA_EXPORT DECL_EXPORT # else # define LIBA_EXPORT DECL_IMPORT # endif #endif LIBA_EXPORT void foo(); qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp0000644000175100017510000000020315232633614031441 0ustar runnerrunner#include #ifndef THE_MAGIC_DEFINE #error "missing the magic define" #endif int main() { foo(); return 0; } ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-modul0000644000175100017510000000017315232633614033535 0ustar runnerrunnerCppApplication { name: "p" Depends { name: "libA" } files: "main.cpp" qbsModuleProviders: "qbspkgconfig" } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/0000755000175100017510000000000015232633614031160 5ustar runnerrunner././@LongLink0000644000000000000000000000017700000000000011610 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-p0000644000175100017510000000026015232633614033406 0ustar runnerrunnerProduct { name: "p" Depends { name: "qbsmetatestmodule" } property bool dummy: { console.info("qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-provi0000755000175100017510000000000015232633614033523 5ustar runnerrunner././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-provi0000755000175100017510000000000015232633614033523 5ustar runnerrunner././@LongLink0000644000000000000000000000021000000000000011574 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-provi0000644000175100017510000000033615232633614033527 0ustar runnerrunnerimport "../../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_scoped_provider"); return ""; } } ././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-provi0000644000175100017510000000033215232633614033523 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_named_provider"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/0000755000175100017510000000000015232633614027054 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provid0000644000175100017510000000051615232633614033300 0ustar runnerrunnerProduct { qbsModuleProviders: ["provider_a"] name: "p" Depends { name: "qbsmetatestmodule" } property bool dummy: { console.info("p.qbsmetatestmodule.boolProp: " + JSON.stringify(qbsmetatestmodule.boolProp)); console.info("p.qbsmetatestmodule.prop: " + JSON.stringify(qbsmetatestmodule.prop)); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/0000755000175100017510000000000015232633614032354 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provi0000644000175100017510000000130215232633614033432 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { property string sysroot: qbs.sysroot Probe { id: theProbe property string theValue: "value" property string dummy: sysroot configure: { console.info("Running probe with irrelevant value '" + dummy + "'"); found = true; } } isEager: false property bool found: theProbe.found property string theValue: theProbe.theValue relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", theValue, undefined, found); if (sysroot !== qbs.sysroot) throw "this is unexpected"; return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/0000755000175100017510000000000015232633614025154 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/0000755000175100017510000000000015232633614027313 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt0000644000175100017510000000044115232633614032052 0ustar runnerrunnercmake_minimum_required(VERSION 3.15) project(conanmoduleprovider.testlibdep) add_library(${PROJECT_NAME} STATIC testlibdep.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlibdep.h") install(TARGETS ${PROJECT_NAME}) install(FILES lorem_ipsum.txt DESTINATION share)qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py0000644000175100017510000000160315232633614031623 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps from conan.tools.files import copy import os class ConanModuleProviderTestlib(ConanFile): name = "conanmoduleprovider.testlibdep" license = "none" version = "1.2.3" exports_sources = "*.cpp", "*.h", "*.txt" settings = "os", "compiler", "build_type", "arch" def layout(self): cmake_layout(self) def generate(self): deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self, generator="Ninja") tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): self.cpp_info.libs = ['conanmoduleprovider.testlibdep'] self.cpp_info.resdirs = ['share'] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h0000644000175100017510000000003515232633614031621 0ustar runnerrunner#pragma once int foo(int i);qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt0000644000175100017510000000007015232633614032404 0ustar runnerrunnerLorem ipsum dolor sit amet, consectetur adipiscing elit.qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp0000644000175100017510000000007515232633614032160 0ustar runnerrunner#include "testlibdep.h" int foo(int i) { return i * i; }qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs0000644000175100017510000000055115232633614032075 0ustar runnerrunnerCppApplication { consoleApplication: true name: "p" files: "main.cpp" qbsModuleProviders: "conan" qbs.buildVariant: "release" qbs.installPrefix: "" install: true Depends { name: "conanmoduleprovider.testlib" } Depends { name: "conanmoduleprovider.testlibheader" } Depends { name: "conanmoduleprovider.lib-order-test" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.py0000644000175100017510000000052115232633614027462 0ustar runnerrunnerfrom conan import ConanFile class Recipe(ConanFile): name = "qbstest" version = "1.0" exports_sources = "*.cpp", "*.h", "*.txt" settings = "os", "compiler", "build_type", "arch" requires = ["conanmoduleprovider.testlib/1.2.3", "conanmoduleprovider.testlibheader/0.1.0", "conanmoduleprovider.lib-order-test/1.0.0"] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/0000755000175100017510000000000015232633614030010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/CMakeLists.txt0000644000175100017510000000051615232633614032552 0ustar runnerrunnercmake_minimum_required(VERSION 3.15) project(lib_order_test CXX) add_library(C STATIC C/C.cpp) add_library(B STATIC B/B.cpp) add_library(A STATIC A/A.cpp) target_link_libraries(B PUBLIC C) target_link_libraries(A PUBLIC B) install(TARGETS A B C ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/B/0000755000175100017510000000000015232633614030171 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/B/B.cpp0000644000175100017510000000011115232633614031047 0ustar runnerrunnerextern const char *nameC(); const char *nameB() { return nameC(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/conanfile.py0000644000175100017510000000250015232633614032315 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps from conan.tools.files import copy import os class LibAConan(ConanFile): name = "conanmoduleprovider.lib-order-test" version = "1.0.0" license = "none" settings = "os", "compiler", "build_type", "arch" exports_sources = "CMakeLists.txt", "A/*", "B/*", "C/*" build_policy = "missing" def layout(self): cmake_layout(self) def generate(self): deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self, generator="Ninja") tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): # Component C self.cpp_info.components["C"].includedirs = [] self.cpp_info.components["C"].libs = ["C"] # Component B depends on C self.cpp_info.components["B"].includedirs = [] self.cpp_info.components["B"].libs = ["B"] self.cpp_info.components["B"].requires = ["C"] # Component A depends on B self.cpp_info.components["A"].includedirs = [] self.cpp_info.components["A"].libs = ["A"] self.cpp_info.components["A"].requires = ["B"] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/C/0000755000175100017510000000000015232633614030172 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/C/C.cpp0000644000175100017510000000005015232633614031053 0ustar runnerrunnerconst char *nameC() { return "C"; } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/A/0000755000175100017510000000000015232633614030170 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/lib-order-test/A/A.cpp0000644000175100017510000000011115232633614031045 0ustar runnerrunnerextern const char *nameB(); const char *nameA() { return nameB(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp0000644000175100017510000000027215232633614026605 0ustar runnerrunner#include #include #include const char *nameA(); int main() { HelloWorld h(42 + hello()); std::cout << "Calling: " << nameA() << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/0000755000175100017510000000000015232633614027773 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h0000644000175100017510000000006215232633614031372 0ustar runnerrunner#pragma once inline int hello() { return 0; }qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py0000644000175100017510000000056315232633614032307 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.files import copy import os class Recipe(ConanFile): exports_sources = ("header.h") version = '0.1.0' name = 'conanmoduleprovider.testlibheader' def package(self): copy(self, "header.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include"))qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlib/0000755000175100017510000000000015232633614026622 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp0000644000175100017510000000014215232633614030771 0ustar runnerrunner#include "testlib.h" #include HelloWorld::HelloWorld(int x) : m_x(foo(x)) {} qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt0000644000175100017510000000060515232633614031363 0ustar runnerrunnercmake_minimum_required(VERSION 3.15) project(conanmoduleprovider.testlib) find_package(conanmoduleprovider.testlibdep REQUIRED) add_library(${PROJECT_NAME} STATIC testlib.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlib.h") target_link_libraries(${PROJECT_NAME} conanmoduleprovider.testlibdep::conanmoduleprovider.testlibdep) install(TARGETS ${PROJECT_NAME}) qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py0000644000175100017510000000162315232633614031134 0ustar runnerrunnerfrom conan import ConanFile from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps import os class ConanModuleProviderTestlib(ConanFile): name = "conanmoduleprovider.testlib" license = "none" version = "1.2.3" exports_sources = "*.cpp", "*.h", "CMakeLists.txt" settings = "os", "compiler", "build_type", "arch" def requirements(self): self.requires("conanmoduleprovider.testlibdep/1.2.3") def layout(self): cmake_layout(self) def generate(self): deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self, generator="Ninja") tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): self.cpp_info.libs = ['conanmoduleprovider.testlib'] qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h0000644000175100017510000000014315232633614030437 0ustar runnerrunner#pragma once class HelloWorld { public: explicit HelloWorld(int x); private: int m_x; }; qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/0000755000175100017510000000000015232633614026567 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.q0000644000175100017510000000034615232633614033315 0ustar runnerrunnerProject { qbsModuleProviders: ["provider_a"] name: "project" property string dummyProp Product { name: "p1" Depends { name: "qbsothermodule" } Depends { name: "qbsmetatestmodule" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/0000755000175100017510000000000015232633614032067 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provide0000644000175100017510000000044715232633614033467 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/removal-version/0000755000175100017510000000000015232633614025356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs0000644000175100017510000000033415232633614031215 0ustar runnerrunnerProject { qbsModuleProviders: "provider_a" name: "project" Project { name: "innerProject" Product { name: "p1" Depends { name: "qbsmetatestmodule" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/removal-version/module-providers/0000755000175100017510000000000015232633614030656 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs0000644000175100017510000000053315232633614033520 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false property bool deprecated: false PropertyOptions { name: "deprecated" removalVersion: "2.2.0" } relativeSearchPaths: { Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/0000755000175100017510000000000015232633614030673 5ustar runnerrunner././@LongLink0000644000000000000000000000017500000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-pr0000644000175100017510000000052015232633614033302 0ustar runnerrunnerProject { name: "project" Project { name: "innerProject" Product { name: "product" Depends { name: "qbsmetatestmodule"; required: false } property bool dummy: { console.info("qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); } } } } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-provid0000755000175100017510000000000015232633614033402 5ustar runnerrunner././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-provid0000644000175100017510000000044715232633614033411 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_b"); Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); return ""; } } ././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-provid0000644000175100017510000000032615232633614033405 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { relativeSearchPaths: { Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/non-eager-provider/0000755000175100017510000000000015232633614025731 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs0000644000175100017510000000067315232633614032151 0ustar runnerrunnerProject { Product { name: "p1" Depends { name: "qbsmetatestmodule" } Depends { name: "qbsothermodule" } Depends { name: "nonexistentmodule"; required: false } property bool dummy: { console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); } qbsModuleProviders: "provider_a" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/0000755000175100017510000000000015232633614031231 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.0000644000175100017510000000045615232633614033371 0ustar runnerrunnerimport "../../qbs-module-providers-helpers.js" as Helpers ModuleProvider { isEager: false relativeSearchPaths: { if (moduleName === "nonexistentmodule") return undefined; Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/0000755000175100017510000000000015232633614025526 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs0000644000175100017510000000267215232633614031544 0ustar runnerrunnerimport qbs.Host Project { property bool dummy: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } readonly property string beginning: "beginning" CppApplication { name: "app1" property string chooseLettersFrom: project.beginning // This indirection tests QBS-1747. Depends { name: "mygenerator.module1" } Depends { name: "mygenerator.module2" } Depends { name: "othergenerator" } moduleProviders.mygenerator.chooseLettersFrom: chooseLettersFrom moduleProviders.othergenerator.someDefines: name files: "main.cpp" } CppApplication { readonly property string end: "end" name: "app2" Depends { name: "mygenerator.module1" } Depends { name: "mygenerator.module2" } Depends { name: "othergenerator" } Profile { name: "myProfile" baseProfile: project.profile moduleProviders.mygenerator.chooseLettersFrom: product.end moduleProviders.othergenerator.someDefines: "app2" } qbs.profile: "myProfile" files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/main.cpp0000644000175100017510000000030515232633614027154 0ustar runnerrunner#include int main() { std::cout << "The letters are " << LETTER1 << " and " << LETTER2 << std::endl; std::cout << "The MY_DEFINE is " << MY_DEFINE << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/0000755000175100017510000000000015232633614031026 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/0000755000175100017510000000000015232633614033362 5ustar runnerrunner././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/p0000644000175100017510000000255015232633614033546 0ustar runnerrunnerimport qbs.File; import qbs.FileInfo; import qbs.TextFile; ModuleProvider { property string chooseLettersFrom relativeSearchPaths: { console.info("Running setup script for " + name); var startAtBeginning = chooseLettersFrom === "beginning"; var moduleBaseDir = FileInfo.joinPaths(outputBaseDir, "modules", "mygenerator"); var module1Dir = FileInfo.joinPaths(moduleBaseDir, "module1"); File.makePath(module1Dir); var module1 = new TextFile(FileInfo.joinPaths(module1Dir, "module1.qbs"), TextFile.WriteOnly); module1.writeLine("Module {"); module1.writeLine(" Depends { name: 'cpp' }"); module1.writeLine(" cpp.defines: 'LETTER1=" + (startAtBeginning ? "\\\'A\\\'" : "\\\'Z\\\'") + "'"); module1.writeLine("}"); module1.close(); var module2Dir = FileInfo.joinPaths(moduleBaseDir, "module2"); File.makePath(module2Dir); var module2 = new TextFile(FileInfo.joinPaths(module2Dir, "module2.qbs"), TextFile.WriteOnly); module2.writeLine("Module {"); module2.writeLine(" Depends { name: 'cpp' }"); module2.writeLine(" cpp.defines: 'LETTER2=" + (startAtBeginning ? "\\\'B\\\'" : "\\\'Y\\\'") + "'"); module2.writeLine("}"); module2.close(); return ""; } } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/qbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerato0000755000175100017510000000000015232633614033615 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerato0000644000175100017510000000124315232633614033617 0ustar runnerrunnerimport qbs.File; import qbs.FileInfo; import qbs.TextFile; ModuleProvider { property string someDefines relativeSearchPaths: { console.info("Running setup script for " + name); var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", "othergenerator"); File.makePath(moduleDir); var module = new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); module.writeLine("Module {"); module.writeLine(" Depends { name: 'cpp' }"); module.writeLine(" cpp.defines: 'MY_DEFINE=\"" + someDefines + "\"'"); module.writeLine("}"); module.close(); return ""; } } qbs-src-3.3.1/tests/auto/blackbox/blackbox-joblimits.qbs0000644000175100017510000000075215232633614022674 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-joblimits" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-joblimits/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxjoblimits.cpp", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/blackbox-clangdb.qbs0000644000175100017510000000077015232633614022272 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-clangdb" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-clangdb/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_clangdb.cpp", "tst_clangdb.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/blackbox-android.qbs0000644000175100017510000000100515232633614022310 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-android" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-android/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxandroid.cpp", "tst_blackboxandroid.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxwindows.cpp0000644000175100017510000002720615232633614023207 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackboxwindows.h" #include "../shared.h" #include #include #include #include #include using qbs::Internal::HostOsInfo; using qbs::Profile; struct SigntoolInfo { enum class CodeSignResult { Failed = 0, Signed, Unsigned }; CodeSignResult result = CodeSignResult::Failed; bool timestamped = false; QString hashAlgorithm; QString subjectName; }; Q_DECLARE_METATYPE(SigntoolInfo::CodeSignResult) static SigntoolInfo extractSigntoolInfo(const QString &signtoolPath, const QString &appPath) { QProcess signtool; signtool.start(signtoolPath, { QStringLiteral("verify"), QStringLiteral("/v"), appPath }); if (!signtool.waitForStarted() || !signtool.waitForFinished()) return {}; const auto output = signtool.readAllStandardError(); SigntoolInfo signtoolInfo; if (output.contains("No signature found")) { signtoolInfo.result = SigntoolInfo::CodeSignResult::Unsigned; } else { signtoolInfo.result = SigntoolInfo::CodeSignResult::Signed; const auto output = signtool.readAllStandardOutput(); const auto lines = output.split('\n'); for (const auto &line: lines) { { const QRegularExpression re("^Hash of file \\((.+)\\):.+$"); const QRegularExpressionMatch match = re.match(line); if (match.hasMatch()) { signtoolInfo.hashAlgorithm = match.captured(1).toLocal8Bit(); continue; } } { const QRegularExpression re("Issued to: (.+)"); const QRegularExpressionMatch match = re.match(line); if (match.hasMatch()) { signtoolInfo.subjectName = match.captured(1).toLocal8Bit().trimmed(); continue; } } if (line.startsWith("The signature is timestamped:")) { signtoolInfo.timestamped = true; break; } else if (line.startsWith("File is not timestamped.")) { break; } } } return signtoolInfo; } static QString extractSigntoolPath(const QByteArray &output) { const QRegularExpression re("%%(.+)%%"); QRegularExpressionMatchIterator it = re.globalMatch(output); if (!it.hasNext()) return {}; const QRegularExpressionMatch match = it.next(); return match.captured(1).toUtf8(); } TestBlackboxWindows::TestBlackboxWindows() : TestBlackboxBase (SRCDIR "/testdata-windows", "blackbox-windows") { } void TestBlackboxWindows::initTestCase() { if (!HostOsInfo::isWindowsHost()) { QSKIP("only applies on Windows"); return; } TestBlackboxBase::initTestCase(); } void TestBlackboxWindows::innoSetup() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); QDir::setCurrent(testDataDir + "/innosetup"); QCOMPARE(runQbs({"resolve"}), 0); const bool withInnosetup = m_qbsStdout.contains("has innosetup: true"); const bool withoutInnosetup = m_qbsStdout.contains("has innosetup: false"); QVERIFY2(withInnosetup || withoutInnosetup, m_qbsStdout.constData()); if (withoutInnosetup) QSKIP("innosetup module not present"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling test.iss")); QVERIFY(m_qbsStdout.contains("compiling Example1.iss")); QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.setup.test.exe")); QVERIFY(regularFileExists(relativeProductBuildDir("Example1") + "/Example1.exe")); } void TestBlackboxWindows::innoSetupDependencies() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); QDir::setCurrent(testDataDir + "/innosetupDependencies"); QCOMPARE(runQbs({"resolve"}), 0); const bool withInnosetup = m_qbsStdout.contains("has innosetup: true"); const bool withoutInnosetup = m_qbsStdout.contains("has innosetup: false"); QVERIFY2(withInnosetup || withoutInnosetup, m_qbsStdout.constData()); if (withoutInnosetup) QSKIP("innosetup module not present"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling test.iss")); QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.setup.test.exe")); } void TestBlackboxWindows::standaloneCodesign() { QFETCH(SigntoolInfo::CodeSignResult, result); QFETCH(QString, hashAlgorithm); QFETCH(QString, subjectName); QFETCH(QString, signingTimestamp); QDir::setCurrent(testDataDir + "/codesign"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); params.arguments << QStringLiteral("project.enableSigning:%1").arg( (result == SigntoolInfo::CodeSignResult::Signed) ? "true" : "false") << QStringLiteral("project.hashAlgorithm:%1").arg(hashAlgorithm) << QStringLiteral("project.subjectName:%1").arg(subjectName) << QStringLiteral("project.signingTimestamp:%1").arg(signingTimestamp); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (!m_qbsStdout.contains("signtool path:")) QSKIP("No current signtool path pattern exists"); const auto signtoolPath = extractSigntoolPath(m_qbsStdout); QVERIFY(QFileInfo(signtoolPath).exists()); const QStringList outputBinaries = {"A.exe", "B.dll"}; for (const auto &outputBinary : outputBinaries) { const auto outputBinaryPath = defaultInstallRoot + "/" + outputBinary; QVERIFY(QFileInfo(outputBinaryPath).exists()); const SigntoolInfo signtoolInfo = extractSigntoolInfo(signtoolPath, outputBinaryPath); QVERIFY(signtoolInfo.result != SigntoolInfo::CodeSignResult::Failed); QCOMPARE(signtoolInfo.result, result); QCOMPARE(signtoolInfo.hashAlgorithm, hashAlgorithm); QCOMPARE(signtoolInfo.subjectName, subjectName); QCOMPARE(signtoolInfo.timestamped, !signingTimestamp.isEmpty()); } } void TestBlackboxWindows::standaloneCodesign_data() { QTest::addColumn("result"); QTest::addColumn("hashAlgorithm"); QTest::addColumn("subjectName"); QTest::addColumn("signingTimestamp"); QTest::newRow("standalone, unsigned") << SigntoolInfo::CodeSignResult::Unsigned << "" << "" << ""; QTest::newRow("standalone, signed, sha1, qbs@community.test, no timestamp") << SigntoolInfo::CodeSignResult::Signed << "sha1" << "qbs@community.test" << ""; QTest::newRow("standalone, signed, sha256, qbs@community.test, RFC3061 timestamp") << SigntoolInfo::CodeSignResult::Signed << "sha256" << "qbs@community.test" << "http://timestamp.digicert.com"; } static bool haveWiX(const Profile &profile) { if (profile.value("wix.toolchainInstallPath").isValid() && profile.value("wix.toolchainInstallRoot").isValid()) { return true; } QStringList regKeys; regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\") << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); for (const QString &key : std::as_const(regKeys)) { const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); for (const QString &version : versions) { QSettings settings(key + version, QSettings::NativeFormat); QString str = settings.value(QStringLiteral("InstallRoot")).toString(); if (!str.isEmpty()) paths.prepend(str); } } for (const QString &path : std::as_const(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/candle"))) && regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/light")))) { return true; } } return false; } void TestBlackboxWindows::wix() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveWiX(profile)) { QSKIP("WiX is not installed"); return; } QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); if (arch.isEmpty()) arch = QByteArrayLiteral("x86"); if (arch.contains("arm")) QSKIP("ARM is not supported for the WiX test"); QDir::setCurrent(testDataDir + "/wix"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.msi")); if (HostOsInfo::isWindowsHost()) { QVERIFY2(m_qbsStdout.contains("compiling QbsBootstrapper.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe"), m_qbsStdout); QVERIFY(regularFileExists(relativeProductBuildDir("QbsBootstrapper") + "/qbs-setup-" + arch + ".exe")); } } void TestBlackboxWindows::wixDependencies() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveWiX(profile)) { QSKIP("WiX is not installed"); return; } QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); if (arch.isEmpty()) arch = QByteArrayLiteral("x86"); if (arch.contains("arm")) QSKIP("ARM is not supported for the WiX test"); QDir::setCurrent(testDataDir + "/wixDependencies"); QbsRunParameters params; if (!HostOsInfo::isWindowsHost()) params.arguments << "qbs.targetOS:windows"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.msi")); } QTEST_MAIN(TestBlackboxWindows) qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxwindows.h0000644000175100017510000000371615232633614022654 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOXWINDOWS_H #define TST_BLACKBOXWINDOWS_H #include "tst_blackboxbase.h" class TestBlackboxWindows : public TestBlackboxBase { Q_OBJECT public: TestBlackboxWindows(); public slots: void initTestCase() override; private slots: void innoSetup(); void innoSetupDependencies(); void standaloneCodesign(); void standaloneCodesign_data(); void wix(); void wixDependencies(); }; #endif // TST_BLACKBOXWINDOWS_H qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxandroid.h0000644000175100017510000000310115232633614022566 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackboxAndroid : public TestBlackboxBase { Q_OBJECT public: TestBlackboxAndroid(); private slots: void android(); void android_data(); private: QMap findAndroid(int *status, const QString &profile); }; #endif // TST_BLACKBOX_H qbs-src-3.3.1/tests/auto/blackbox/blackbox-qt.qbs0000644000175100017510000000076115232633614021324 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-qt" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-qt/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxqt.cpp", "tst_blackboxqt.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxqt.h0000644000175100017510000000557715232633614021615 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXQT_H #define TST_BLACKBOXQT_H #include "tst_blackboxbase.h" #include class TestBlackboxQt : public TestBlackboxBase { Q_OBJECT public: TestBlackboxQt(); private: std::optional findShaderTools(bool *hasViewCount = nullptr); private slots: void addQObjectMacroToGeneratedCppFile(); void autoQrc(); void cachedQml(); void combinedMoc(); void createProject(); void dbusAdaptors(); void dbusInterfaces(); void emscriptenHtml(); void forcedMoc(); void includedMocCpp(); void linkerVariant(); void lrelease(); void lupdate(); void metaTypes_data(); void metaTypes(); void mixedBuildVariants(); void mocAndCppCombining(); void mocChangeTracking(); void mocFlags(); void mocCompilerDefines(); void mocSameFileName(); void noMocRunAfterTouchingOtherCppFile(); void noRelinkOnQDebug(); void noRelinkOnQDebug_data(); void pkgconfig(); void pkgconfigQt(); void pkgconfigQt_data(); void pkgconfigNoQt(); void pluginMetaData(); void pluginSupport_data(); void pluginSupport(); void qdoc(); void qmlDebugging(); void qobjectInObjectiveCpp(); void qmlTypeRegistrar_data(); void qmlTypeRegistrar(); void qtKeywords(); void quickCompiler(); void qtScxml(); void qtXml(); void removeMocHeaderFromFileList(); void shadertools(); void shadertools_data(); void shadertoolsLinking(); void shadertoolsLinking_data(); void staticQtPluginLinking(); void trackAddMocInclude(); void track_qobject_change(); void track_qrc(); void unmocable(); }; #endif // TST_BLACKBOXQT_H qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/0000755000175100017510000000000015232633614021312 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/0000755000175100017510000000000015232633614026553 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/lib.c0000644000175100017510000000024415232633614027465 0ustar runnerrunner#include int foo() { #ifdef __i386__ printf("Hello from i386\n"); #endif #ifdef __x86_64__ printf("Hello from x86_64\n"); #endif return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/app.c0000644000175100017510000000015515232633614027500 0ustar runnerrunnerextern int foo(); int main(int argc, char *argv[]) { (void) argc; (void) argv; return foo(); } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinki0000644000175100017510000000333515232633614033416 0ustar runnerrunnerProject { minimumQbsVersion: "1.8" StaticLibrary { name: "multi_arch_lib" files: ["lib.c"] Depends { name: "cpp" } Depends { name: "bundle" } property bool hasX86Mac: true // cannot use xcode.version in qbs.architectures property bool hasArmMac: false bundle.isBundle: false // This will generate 2 multiplex configs and an aggregate. qbs.architectures: { if (qbs.targetPlatform === "macos") { if (hasX86Mac) return ["x86_64", "x86"]; else if (hasArmMac) return ["arm64", "x86_64"]; } else if (qbs.targetPlatform === "ios") { return ["arm64", "armv7a"]; } console.info("Cannot build fat binaries for this target platform (" + qbs.targetPlatform + ")"); return original; } qbs.buildVariant: "debug" cpp.minimumMacosVersion: "10.8" } CppApplication { name: "just_app" files: ["app.c"] // This should link only against the aggregate static library, and not against // the {debug, arm64} variant, or worse - against both the single arch variant // and the lipo-ed one. Depends { name: "multi_arch_lib" } Depends { name: "bundle" } bundle.isBundle: false qbs.architecture: { if (qbs.targetPlatform === "macos") return "x86_64"; else if (qbs.targetPlatform === "ios") return "arm64"; return original; } qbs.buildVariant: "debug" cpp.minimumMacosVersion: "10.8" multiplexByQbsProperties: [] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/overrideInfoPlist/0000755000175100017510000000000015232633614024761 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c0000644000175100017510000000003115232633614026043 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist0000644000175100017510000000052515232633614030510 0ustar runnerrunner DefaultValue The default value OverriddenValue The default value qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs0000644000175100017510000000064115232633614031140 0ustar runnerrunnerCppApplication { Depends { name: "bundle" } cpp.minimumMacosVersion: "10.7" files: ["main.c", "Override-Info.plist"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: true bundle.identifierPrefix: "com.test" bundle.infoPlist: ({ "CFBundleName": "My Bundle", "OverriddenValue": "The overridden value", }) } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/0000755000175100017510000000000015232633614024621 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/deep.json0000644000175100017510000000701615232633614026435 0ustar runnerrunner{ "A": { "extension": ".app", "directories": [ "Contents", "Contents/Headers", "Contents/PrivateHeaders", "Contents/MacOS", "Contents/Resources", "Contents/_CodeSignature" ], "files": [ "Contents/Info.plist", "Contents/Headers/dummy.h", "Contents/PrivateHeaders/dummy_p.h", "Contents/MacOS/A", "Contents/PkgInfo", "Contents/Resources/resource.txt", "Contents/_CodeSignature/CodeResources" ], "symlinks": [] }, "B": { "extension": ".framework", "directories": [ "Versions", "Versions/A", "Versions/A/Headers", "Versions/A/PrivateHeaders", "Versions/A/Resources", "Versions/A/_CodeSignature" ], "files": [ "Versions/A/B", "Versions/A/Headers/dummy.h", "Versions/A/PrivateHeaders/dummy_p.h", "Versions/A/Resources/Info.plist", "Versions/A/Resources/resource.txt", "Versions/A/_CodeSignature/CodeResources" ], "symlinks": [ "B", "Headers", "PrivateHeaders", "Resources", "Versions/Current" ] }, "C": { "extension": ".framework", "directories": [ "Versions", "Versions/A", "Versions/A/Headers", "Versions/A/PrivateHeaders", "Versions/A/Resources", "Versions/A/_CodeSignature" ], "files": [ "Versions/A/C", "Versions/A/Headers/dummy.h", "Versions/A/PrivateHeaders/dummy_p.h", "Versions/A/Resources/Info.plist", "Versions/A/Resources/resource.txt", "Versions/A/_CodeSignature/CodeResources", "Versions/A/_CodeSignature/CodeDirectory", "Versions/A/_CodeSignature/CodeRequirements", "Versions/A/_CodeSignature/CodeRequirements-1", "Versions/A/_CodeSignature/CodeSignature" ], "symlinks": [ "C", "Headers", "PrivateHeaders", "Resources", "Versions/Current" ] }, "D": { "extension": ".bundle", "directories": [ "Contents", "Contents/Headers", "Contents/MacOS", "Contents/Resources", "Contents/PrivateHeaders", "Contents/_CodeSignature" ], "files": [ "Contents/Info.plist", "Contents/Headers/dummy.h", "Contents/MacOS/D", "Contents/PrivateHeaders/dummy_p.h", "Contents/Resources/resource.txt", "Contents/_CodeSignature/CodeResources" ], "symlinks": [] }, "E": { "extension": ".appex", "directories": [ "Contents", "Contents/Headers", "Contents/MacOS", "Contents/Resources", "Contents/PrivateHeaders", "Contents/_CodeSignature" ], "files": [ "Contents/Headers/dummy.h", "Contents/Info.plist", "Contents/MacOS/E", "Contents/PrivateHeaders/dummy_p.h", "Contents/Resources/resource.txt", "Contents/_CodeSignature/CodeResources" ], "symlinks": [] }, "F": { "extension": ".xpc", "directories": [ "Contents", "Contents/Headers", "Contents/MacOS", "Contents/Resources", "Contents/PrivateHeaders", "Contents/_CodeSignature" ], "files": [ "Contents/Info.plist", "Contents/Headers/dummy.h", "Contents/PrivateHeaders/dummy_p.h", "Contents/MacOS/F", "Contents/Resources/resource.txt", "Contents/_CodeSignature/CodeResources" ], "symlinks": [] }, "G": { "extension": "", "directories": [ "Contents" ], "files": [ "ContentInfo.plist", "Contents/resource.txt" ], "symlinks": [] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy_p.h0000644000175100017510000000233215232633614026444 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy.h0000644000175100017510000000233215232633614026125 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/shallow-signed.json0000644000175100017510000000437515232633614030445 0ustar runnerrunner{ "A": { "extension": ".app", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "A", "Info.plist", "PkgInfo", "Headers/dummy.h", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources" ], "symlinks": [] }, "B": { "extension": ".framework", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "B", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources" ], "symlinks": [] }, "C": { "extension": ".framework", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "C", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources", "_CodeSignature/CodeDirectory", "_CodeSignature/CodeRequirements", "_CodeSignature/CodeRequirements-1", "_CodeSignature/CodeSignature" ], "symlinks": [] }, "D": { "extension": ".bundle", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "D", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources" ], "symlinks": [] }, "E": { "extension": ".appex", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "E", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources" ], "symlinks": [] }, "F": { "extension": ".xpc", "directories": [ "Headers", "PrivateHeaders", "_CodeSignature" ], "files": [ "F", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt", "_CodeSignature/CodeResources" ], "symlinks": [] }, "G": { "extension": "", "directories": [ "Contents" ], "files": [ "ContentInfo.plist", "Contents/resource.txt" ], "symlinks": [] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy.c0000644000175100017510000000236415232633614026125 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/shallow-unsigned.json0000644000175100017510000000335115232633614031001 0ustar runnerrunner{ "A": { "extension": ".app", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "A", "Info.plist", "PkgInfo", "Headers/dummy.h", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "B": { "extension": ".framework", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "B", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "C": { "extension": ".framework", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "C", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "D": { "extension": ".bundle", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "D", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "E": { "extension": ".appex", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "E", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "F": { "extension": ".xpc", "directories": [ "Headers", "PrivateHeaders" ], "files": [ "F", "Headers/dummy.h", "Info.plist", "PrivateHeaders/dummy_p.h", "resource.txt" ], "symlinks": [] }, "G": { "extension": "", "directories": [ "Contents" ], "files": [ "ContentInfo.plist", "Contents/resource.txt" ], "symlinks": [] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs0000644000175100017510000001256615232633614030651 0ustar runnerrunnerProject { property stringList bundleFileTags: ["bundle.content"] property stringList buildableProducts: ["A", "B", "C", "D", "E", "F", "G"] property bool enableCodeSigning: !qbs.targetOS.includes("ios") || qbs.targetOS.includes("ios-simulator") Product { Depends { name: "bundle" } condition: { console.info("bundle.isShallow: " + bundle.isShallow); console.info("qbs.targetOS: " + qbs.targetOS); console.info("enableCodeSigning: " + project.enableCodeSigning); return false; } } Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.includes("A") name: "A" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.includes("ABadApple") name: "ABadApple" bundle._productTypeIdentifier: "com.apple.product-type.will.never.exist.ever.guaranteed" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.includes("ABadThirdParty") name: "ABadThirdParty" bundle._productTypeIdentifier: "org.special.third.party.non.existent.product.type" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "B", "ABadApple", "ABadThirdParty"]) name: "B" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } StaticLibrary { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "C", "ABadApple", "ABadThirdParty"]) name: "C" bundle.isBundle: true Group { name: "public headers" files: ["dummy.h"] fileTags: ["bundle.input.public_hpp", "hpp"] } Group { name: "private headers" files: ["dummy_p.h"] fileTags: ["bundle.input.private_hpp", "hpp"] } Group { name: "resources" files: ["resource.txt"] fileTags: ["bundle.input.resources"] } codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } LoadableModule { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "D", "ABadApple", "ABadThirdParty"]) name: "D" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } ApplicationExtension { Depends { name: "cpp" } condition: buildableProducts.includes("E") name: "E" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } XPCService { Depends { name: "cpp" } condition: buildableProducts.includes("F") name: "F" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning files: ["dummy.c"] install: true installDir: "" } Product { Depends { name: "bundle" } condition: buildableProducts.includes("G") type: ["inapppurchase"] name: "G" bundle.isBundle: true bundle.resources: ["resource.txt"] // XCode 12.5 does not support com.apple.product-type.in-app-purchase-content type anymore, // so use older specs from Qbs bundle._useXcodeBuildSpecs: false Group { fileTagsFilter: product.type.concat(project.bundleFileTags) qbs.install: true qbs.installSourceBase: product.buildDirectory } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/bundle-structure/resource.txt0000644000175100017510000000000015232633614027177 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoplist/0000755000175100017510000000000015232633614023321 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoplist/main.c0000644000175100017510000000236415232633614024416 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoplist/infoplist.qbs0000644000175100017510000000011515232633614026034 0ustar runnerrunnerCppApplication { cpp.minimumMacosVersion: "10.7" files: ["main.c"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/0000755000175100017510000000000015232633614021704 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/0000755000175100017510000000000015232633614024051 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/main.c0000644000175100017510000000237015232633614025143 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs0000644000175100017510000000036215232633614026726 0ustar runnerrunnerCppApplication { Depends { name: "ib" } Depends { name: "bundle" } property bool isShallow: { console.info("isShallow: " + bundle.isShallow); return bundle.isShallow; } files: ["main.c", "white.iconset"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/0000755000175100017510000000000015232633614026634 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/icon_16x16@2x.png0000644000175100017510000000123115232633614031506 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/icon_16x16.png0000644000175100017510000000121115232633614031132 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/0000755000175100017510000000000015232633614025752 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/main.c0000644000175100017510000000236415232633614027047 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog1.xcassets/0000755000175100017510000000000015232633614032341 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog1.xcassets/.keepqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog1.xcassets/.kee0000644000175100017510000000000015232633614033074 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/multiple-asset-catalogs.qbs0000644000175100017510000000022615232633614033224 0ustar runnerrunnerCppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog2.xcassets/0000755000175100017510000000000015232633614032342 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog2.xcassets/.keepqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog2.xcassets/.kee0000644000175100017510000000000015232633614033075 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/0000755000175100017510000000000015232633614024356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/MainMenu.xib0000644000175100017510000063673415232633614026616 0ustar runnerrunner 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu Test 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: Test About Test 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide Test h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit Test q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help Test Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 Test NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/EmptyStoryboard.storyboard0000644000175100017510000000073115232633614031640 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/main.c0000644000175100017510000000237015232633614025450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs0000644000175100017510000000171015232633614030615 0ustar runnerrunnerimport qbs.Host import qbs.Utilities Project { condition: { var result = qbs.targetOS.includes("macos"); if (!result) console.info("Skip this test"); return result; } property bool includeIconset CppApplication { Depends { name: "ib" } files: { var filez = ["main.c", "MainMenu.xib"]; if (project.includeIconset) filez.push("empty.xcassets/empty.iconset"); else if (Utilities.versionCompare(xcode.version, "5") >= 0) filez.push("empty.xcassets"); if ((Host.osVersionMajor() >= 11 || Host.osVersionMinor() >= 10) // need macOS 10.10 or higher to build SBs && cpp.minimumMacosVersion !== undefined && Utilities.versionCompare(cpp.minimumMacosVersion, "10.10") >= 0) filez.push("Storyboard.storyboard"); return filez; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/0000755000175100017510000000000015232633614027350 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/0000755000175100017510000000000015232633614032151 5ustar runnerrunner././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/icon_16x16@2x.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/icon_10000644000175100017510000000123115232633614033241 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/icon_16x16.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/icon_10000644000175100017510000000121115232633614033237 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/0000755000175100017510000000000015232633614032266 5ustar runnerrunner././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/icon_16x16@2x.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/icon_0000644000175100017510000000123115232633614033275 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/icon_16x16.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/icon_0000644000175100017510000000121115232633614033273 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/Contents.jsonqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/Conte0000644000175100017510000000053315232633614033262 0ustar runnerrunner{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/Storyboard.storyboard0000644000175100017510000000540615232633614030625 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconcomposer/0000755000175100017510000000000015232633614024404 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconcomposer/main.c0000644000175100017510000000003115232633614025466 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconcomposer/iconcomposer.qbs0000644000175100017510000000042615232633614027615 0ustar runnerrunnerCppApplication { Depends { name: "ib" } Depends { name: "bundle" } property bool isShallow: { console.info("bundle.isShallow: " + bundle.isShallow); return bundle.isShallow; } files: ["main.c", "AppIcon.icon"] ib.appIconName: "AppIcon" } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconcomposer/AppIcon.icon/0000755000175100017510000000000015232633614026664 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconcomposer/AppIcon.icon/icon.json0000644000175100017510000000065715232633614030517 0ustar runnerrunner{ "fill" : { "linear-gradient" : [ "display-p3:0.24168,1.00000,0.91171,1.00000", "extended-srgb:0.00000,0.47843,1.00000,1.00000" ], "orientation" : { "start" : { "x" : 0.5, "y" : 0 }, "stop" : { "x" : 0.5, "y" : 0.7 } } }, "groups" : [ ], "supported-platforms" : { "circles" : [ "watchOS" ], "squares" : "shared" } }qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconset/0000755000175100017510000000000015232633614023350 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconset/iconset.qbs0000644000175100017510000000012715232633614025523 0ustar runnerrunnerProduct { Depends { name: "ib" } type: ["icns"] files: ["white.iconset"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/0000755000175100017510000000000015232633614026133 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/icon_16x16@2x.png0000644000175100017510000000123115232633614031005 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/icon_16x16.png0000644000175100017510000000121115232633614030431 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/0000755000175100017510000000000015232633614024051 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/main.c0000644000175100017510000000003115232633614025133 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/0000755000175100017510000000000015232633614027712 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000755000175100017510000000000015232633614033144 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/58.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000672715232633614033162 0ustar runnerrunner‰PNG  IHDR::á»J(sRGB®ÎéDeXIfMM*‡i  : :£««ô AIDAThíZ t•Õžìû‚ …°&"„ˆ° ([T,(hsZiç(Õ–ºU=­Ø(ÒŠ¨@ m QQ(ÄÈA–²„„°$aɾ¾¼,Lç»áþù_x/É I<œ:'ÿûïûÿ{çÎ73÷Þ™yqa!ê ëúúzruuUWMÓ*¶.ôÊ•+äââ¢.H¢ãÙA®í=)šA%%%QFF¹¹¹)Ðx÷£,Ú$¹¶¶Ö`µcÇ;v,–ñüùó¹¼¼\½°Œ«3‰Úc²ºº:ƒMvv6Ïœ9SH±¤Ñç„„£/ÆAAAí‚VUUñ›o¾É]ºtQÀd- Ñvww7ÇÄÄðž={:Ÿ1Çu…ûÁ*Ë–-ã~ýú@ÌV„Uõ%»¯íG}”á°jG[Ö©ÍQ½l6f©¦¦†¬V«ùq‹mFÕÕÕTWWOhk@ùúkûÝ Û¶Ð¨kaó(--ãW^y…ýýý•á®°šHÊM]wôèÑœ’’Ò쌢P±r³]œzÙ¢ëÖ×_‘²aÆšÚ:~wå×¼ÿØi5Éɳ9ù‡t›Ý6==§OŸ®¤ym½—¯XÁuWùÉÁ“Ù¼`ù:yÖ° oÞ‚Ï\(4@è¹ml8Š5#ne°ýzÇ!3k>ÓÓ99õ¸z~0ý<Ïz'­ùŽOœ¹ ÏM°uëV9r¤ìççÇ/¿ü2ü.–ð«%rà˜85óuã9x=óþþrû.«´Ïaáë!w{‹@xJÈæ"‡¼ ÍL‘z‰0µtK›(FŽ“Zqq‹µV¹¨#k˜…Âñ„eq©¨”†Fô¡žø•„‚uêº?:‚úõ¡2/1„µÍ<œmÛìºæÁZã%åUJ¨‰£‡@F…÷1ºyzxЯïJѽióþ4J“£ ¼½d-½p{X© ¤‚~Ö5˜^€qÜ'G·Ñé¶>ÝE!´çÄYúî`:Éü¾^žJ‰F§64ì…@Ð8ÎÒ;Â{Óó¿y˜TÓÎ;iÕªUGÑÑÑÔW{òá‘t83—¶¤ž¤ …eÊ­Íî ž¥Uêü|ròXzîñ¨w÷PŲÊb¡÷âãIwúã¼yäïç§Îá!ý{ØS´÷ÄåA²I¶™dÓ0¨öjÈ7çí|óø§øÃ5[¹ÒRm¼ÏÊÊRIµX‹TűsæÌ᜜£O•ÅÊÛ¤ó³¬å¤ï«çyÅÜíþ9<ñ÷ïò¾c™F_4yРAŠxFDDðêÕ«múœ½XÈK×íäç¯å‚Ò õ!ª3„-ß =XÎQ–sÔx^&% Ø$Õæ`½k×®ü×øx¶XcÓ‹Ee|òì%Å£ ¤œ7l?hðC#55•|ðA ø™y"9ß½Û69?z:׈Ä©"š~Y³f 8ШiRm.**Š7lØÐ”…Í÷ /òÓO?m€?ÎÁ¢M“óÙ³gsnn® ¶|±±(Àªµ’Ž]ºt™ÇgôððPy%„izÁ•ñ^?衇¸¨¨HUÀUˆZ¹ 4///Õ›*MÇï´Ñ^¹r¥JåÀ«-t PͤªÊÂRª4R-LމõúÔBá»ÏÆŒÃëÖ¯gÙ`4+uà3gΪtÍ^]IóÃVÕV äyóæqffæu•[ìE‚­ 9éÒ¥K9,,̰˜¶„¾C¸¾}ûòòåËm’j‹µF±‘ÜFH©óòŒ3løAa¸Ì<§M›ÆÇ7ä¾ZItÓ©» Pͯßù_–ôˆ+Īš.çç+Íz{{ ’ê—$©.(l¬ —ò3ï|Æ ?ߨ†Ë¹É[û=ËÊ“ï»err25ʆx>œ¿ýö[=µºoÛŒxæÎÊiØ$MÄí]+ ãÞþ‚¬ÜÌ{g«5«g=zô(O™2…ø±ÇãiiúK‘Œ—¯Ká¨Ø™Oã7–}¥Þ—UòóK¾â¹‹Öð?6íåÜübc F±gϞܭ[7^²d‰ði´Zú™<Ž›ÿ‰ªD„ŒŸÍçä¨9 ÔnÀ .$I³!*JøÏJM;K¿>n »YU äì#Y34`À1@!©~kÅÚu$CrXòï@nWƒU˜ 9$èð©AÝ3D’ó¨þàçCRð¦I“&©$^Ž*Õ¯¸´‚þž¸>NÚFE~‚'"1Á¨Þ;ûa(˜ˆ¢ÉÝÝ•üÜ<)+¯€>Z·S%¾ˆm»Jâ¬@ʤéç.Ð_>ÛHIÉÔÜHª¡¨:‰‚Ì"A@$¾Þ*éÞ"Éù¡SçU¬|—”`BBBÔx«$ k¿;@ ?ÿZªy,‰H ÕHYÔQ¤¶ðá(ÆAyŒÜBï“øóXÖzê‘ÑÔSêBÒ²è‘?¼G倫R‹D¸HªuMÉÞÜàB©¤¼ÒJ«6§ÒéÜzüþhõüùÅÿ¢ÅÿÞ"àüE¡®^ñT/¯ã£Åì¼a X¬BjHHÛ}”VZD ¥g4Þà1n„d:_‚|x®,©lH­ÉGyÄÛPv{P«€ê‰ ÖN”Q&AN +¶…´;{ÈÑä%À1”ÛžÔ8ƒ‰+@æ!×yzôÃÕ”`d+M…5g3æ1föø¡/ø½W/›ù° õ¸¨ª šÊÍð1^ÁÂBR¥lFpK¦V9‘œk†‹eR"ü`iÈÖ² —„v±³N;”ÜE‹(uÀ²ZXG“@ãè'™ ùÉ[üÂ4sÒ½ª»¿'ýnâÏip¿T) ”¸·¡T∙<‡W@i)•âx?l%-œKÝCƒm”× ›W×ìºÖG*;4<Œ¶Håà‡ôsʺ¨ÛB3©R‹h¼HÎ=¬¯§¦Œ£g%©ëÖp\À¢ÖQŸî!4KÀ9'Éyå\.Qu`½ÞÍ<±k£ÄZT^Aƒné%‰ÿDš3ÂÜÅéö5@5¸ ίؘhq{_úfï ÊÌÉ'‰Z °°²¥ZŠcð‚ƒéE)µ Ô_³ ÄµkéùóiذaôÚk¯Q¯^½è93oë}3í:–MÛgJÕ¡Üè‰`¡K˜?½;…æLQ( ÞfO16 } ‡9Ô’‰_]¶‘f5ä‡IÉ©5k–ᦨ ”ØôŽ$]'ê ¬ùßqÚ V„Ó@õ@}‡ËUTTð§Ÿ~ʽ{÷6Ú³¨ùYll¬Jª<:š®¨YÀqa”=tr®K"f€ö’j3Žj·Pó!9Ÿ–Nÿ”@}oA=Û5cý¤“Xý©gÏž´gÏZ¶l½óÎ;”˜˜Ho¾ù&M˜0ªV­*åª?¿Z÷íQúçÒMtêìEª^5ˆBªUq)AP%~÷.m=IÇc.Ñ¿u~”:?ÚXÚ%Aw@Aì¢"«5Õ‡Aн|ÛLkv¡kB0153ËÒX³±zTÙŸ2Y³×‡Ÿ¢c¬Q~ÝŠÚ?RŸØc#ZÊö•^zé%â­.%''‹V£ž,Ö¸î Œ”cQç¹C7ÒÎß3оT;$XXå2ð®ÊÀLªÂŸ”’N+v¡ÃQhЯ[S³úµä”ñö¶`·àv'=“æ­ÞEŸ}µ›oßA¯C0ç!Y ÐlzíV }±õµiú+Ô¥55¬S]^)¨Q£†¸f»+À&ܸE³Wl¥å[#(3+‡BX[Ñel÷¥m®ø™Ï Ÿ¯wˆ‹¿AŸ%ì¥'Z6’®dõèuàT=ÆWï>L³xFž¿LÕª´U´Å´Ehêäi›õ%æyþ*ea»¶nBý;=JÁA•į‹ª,€\´á[údÕº|ýwh Tq˜“"°ËWÄaËf s02Žù_¡ÞšS¯PÀ½¹ ßK¥¼q ®ç?ÿc­äI+8°’ C˜ˆ‚†aQÛ"‚ráÀ?‚Ùøîä9:yî2ÖÔ‘ —qôÜ[ŸÐwlÓCÔZ!UESÁ¿4~ ˜©œÜ»´qßÌ;žþ:¬UåÎ…ByʸZ€p2æ‚hTåÏûì³Ô¢E ù®Ml«ŸéÝ:·j,îGl»}¸£xŽí8€¶ƒÜÚ\h*46‘‡apPeš5~$}óÙšÉKc–,YB;v¤·ÞzKü³cÆŒ¡K—.Éïh<ÊÖ¬D#ûwbsÑ‹©_›Ò2² ´ÇèP˜vxSã_Õ¢ÿyû/´é£×XÔ› YFF}ðÁÂ{êÔ©Ä‘az÷Ýw¥£áÚ„™‚#¢¿ü¶;…éÊ&%X掣Øgyhü‚x¨ ñ>^=6b²ªÒóe5qÎ u™C)šÌ ûbûde¤1†ù¢5kÖT³fÍR €¼Š°ŽàÁá¨85sù5zÖ—êtl‚®^]M¼­j>5FÕ}Txx¸Á;¯s’RÒÔÿ…+;pu+ ¹š›¹e»ª¦M›¦‚ƒƒDc©ÁÅÙYP$Ü!ñNÂî®Èäe"/_¾¬^y募s‡š¼ÑÑf»B9^‡¸&3žçIÕõ»Ô\ý#Î`ªAÅýÊ•+Ƕ\j§)˜ó5ÕZàã¸qãçá¢J!L뢶÷:ùe³gÏVµk×.6oŒNF›qFäÙ Íkš¯§ÎnÁ…оHr¶«ºÁÎ@vojò¾Þ{ï=•”ä‹; ‰{höÒ¥KŬèzÍȰ~V”³É›WêóÏ?—¹€=o¼hð<¹]-0úÜn¢èèh:vì˜\³¢SäÅøÃ€I”¯pÆ"EDDg͸¬<¸céĉtúôi)ÃÉìïò7QÞÅÄÄ›'YE°Bó?‡œnª(ÞÏîú š«5êÚµk.ói™£ ¹ÂÎζ‰tÛ·o·Øc¡ù臦©àÎUÏ=÷œÅZXÔ‘ãÌù¾H Ôd&¶ègž8CûŠD¼²Ê9g‚c˜&¨9ëÕ«§æÍ›§xÝ)õ!Ç´éãÂäáÔ~ dw¼M✩n.é v»,\Ž1©ý?ĪôLG† l¯)(–VXbi5AÄ3só÷÷Wœ‡  ý h©¹ Ø~Bй` –ÌëÚ§c­,t†^ãzþüùª~ýúò6Û‚I“aff¦ÔzL9–o‰P®ÜßœGÕ \ .Mûb«úÏÅ[Ô‘¨<ÁÑ8=”°9À&›dS¸aÆå†æz5:.A…N[¨|:ÿAmÛ—7T‘ë5ñ¿ÖJ:TT\ÞZ h®_¿®&Nœh¥”¢3ÁWóÆyìØ±*>>Þ‚ÆìÐðÑjиªÀî¡*êüe)ƒÉÍSTè„´%…GiÅÎ#4oÝ^ŠMH”½><[Ø‚VªT‰Þxã ™tF-ŽLB8Ú·oO6l× ŒLFHGB0rÚ¯驱3é«°ÃyÕ5ÌV|°Èä¹Ä!õ…›öÑÒí‡èjRŠ„åÙIjk$±Fo(høðáR·æ=pà@:pెk8'—d£Zñ ±eÌÌÅ4|âÚꬤ `«íirë¸aå/”?ç ¡b~B8'T4Ì—PÐ6lH¼´¡Q£FÑŒ3¨W¯^ôÚk¯IÚk9ÏxJ| ˜”—m‰à$-sñ*…pD NÌàFQ>ùXC%Ÿ`žàt$ÞÁQ÷ÇšQ?N‰‚‹åQ7ÛRZ¿~=mÞ¼YœFÈÜyþùç¥.´ N%t(êóÖpbËš0ºq;%_b‹ë|í(é[pQ1„àÁ"y_Î ½9¡ ptéÒ…ø»«=Ú ‰È+›É {á'Ï08œ_ÆéHдÂò 4à: Úɳñ’DÒ¥MIìã Q\›H…ÂB[Ìü²Õ»Ò¬e[(26¾T‰-Ryÿ \]鄊MœP×á@ÎûêÈ®D¬4  °Í“aøSü5+¿ Ï‘±ƒP@E à<éP<ÙѪÝG9ï+Žs:Tó†uä7gÞhÏÁÎI~Ù7G"Ń&ÊÀÖ¡R™þ \Í‚Ây]…*“ÓÄúñ îÖšÕ©ÁÅY+°« Ö†É0¼™œ?¿L×UÜ3xc˜Ãawå&-Ø!‹®Å†‘…¶]¼z“>\¾…Vmß/.Íêlzà»ÕZ\¾%)_b+=‚ 2ˆ‡xd\‚h„ÃshïªíhÊÇ_J§h+k-o JÒÎ|b•Ø—[‰Þߟ#Œ"f)¦¼?\¶™æ~¹Ml3üÐ0zäå«ÌÆ›ƒ«Û$‚2hÈÃ…cÝ$8¢ƒ8#šfÇ0XüObcÖ$\U²!pt¨YwQ¯ó£QÔ·\”s¥‚¡ì$W¼Áï~ªeõ¸ºÂŠsà2N%R^¹CÚ“É®Ú+APþ¡&X˜ùí$É¡`Fv˜.·àâÛDhAž“¶|” Û]MxŽ#S•P‡' ƒN½Å;CÇÎñ1‹GyTt…îJO=ÑR–2œF€K+(`‚@ÈåBÈþ‰VMhóǯSÞÚ:V¼Êà5ôا{Ê· ÈMÀgX’éSJŒÑvðF~rÛ~Ó£mþd’$—xz”¸‰Ð2T«RÙ)¡‚ÿÿîñ’&T`bÍ™È{û‡ëס‰œõÇ¡=¥NlYÁ`·…t¨?îBQÓŽCQtþJ"oµ}emmš‚Äù9FBgÜÜJO¥Ž-›ÐäÐaôÛ{‰-Îe=q_ ¸ºr±}¼1Ð §øÛ…œ÷Ï_Ø`£Œ;rØm/†XÔ#·ìo#qZ~U±w¦uaë €A­×¥– ¢‘±œ–C79ëGç}I7  OáM¥úœò÷?ÿŽF?ÝW¶Ãº“ì˜WÜ‚ËJÄÚäð@|;ÖºI] ?õí9ÃûüLÞ¡9Ü\ɨ‡!¶Âäé>DcÚ<Ìß 1ÁR¡"##iÊ”)Äásš9s& 0@Ê %‰# âk߬…?CûOŸ§tþŽ¡ ï 2SÚ®&±éAfΘß÷£Iø Õ«íø4 ë`o¹W3ÖÀ&bËÛ§o@»ŽDÓQþhOÛc]g8NàÄwk’_ÆÃp`·vRD\ €½yó&±Ãø!ŽÈïðÇrÌŒ8?‚Zµj%Ï2üÃ{´ã/!qÞW”|î”ãðŠI¡{ZFfÝöN§þ]ÚJÂ`§VMåW˜%´ÍN`…ñ7Ðz(êÓ¯ö¨,Ù&a¥ào×ÔCýǪ…_c}ÍŽ˜+ïò°—ð6û‚aXä@ô€·rÕäÉ“%üŽ—Ø.[ïã)PÓ—nSó×íÅ­ÅgG7Z>ýºZÿm^ bux¿¬ö®Ä„†òвÞç¨9ÎÅÜ{r<:ŽcS‰r‡²fˆe×®]ªk×®¨®ZƒÞ¸qcµhÑ"‹k±jBÞWÌ¥ëÂWƒ·ÿTŒÂ×ô i§¡ V%6_” \Ý6-¾w>CxM‘1 ²É±î5˜úŒßÌ.½®ø+v]´´8]@[ïy\ÝxS‹ñ ÷Z8ä—½ýöÛ*((H€4‡¾²°3@65ùÅ_T±±±ÂæÅ¹ƒa¶œŸév–ÕÙ£à:7Z ÍB+Ç  ššX ®~ÀøOˆôo0Žaÿ4ÔYn}oß:„¥×+ þ?mˆsˆóey9æHDf¸Dñ3<7\"¿ÕªU“e[ÿþý¥Í«x5Ú\Z£\g$Üñ:¶Ø¦ÁÙ$Œ9R9s¦,š\*¶š³e:} Ï¢¢¢Ô /¼` í‚&5€jšnݺ©Ý»w[ÕbÅp¿íªÕe.x¢iÇŽŠCñÈærÌœ¼5j¤.\h‰Ž‚=/ïT¦àj0ŒÖd\ó×?ªAƒÈØÊ•++þxEñN^Eçè÷t]åù|_ÀÕ€˜@ݸqCMš4I!a§ÅŸ;)ö5è¢ù4ÞzXÎ/¼Ð>›çL·Õ3ÈVB4ÿ?¹Ä vÄÿ5¡¼‡ß°²(—«7’• pÑFô1–i„k–_*•p5€@kõóñ\îÀ}A,¨Íî˜+H¢rô¼\;£Ü pmDÀƪ+4·\°±ê Í­×Fl¬ºBs+Àµ«®ÐÜ pmDÀƪ+4×Fpÿ‡ì$›ÃqŒIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/32.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000345315232633614033153 0ustar runnerrunner‰PNG  IHDR szzôsRGB®ÎéDeXIfMM*‡i     ¬†bó•IDATX íWkLTWö ‹XM+Š%6µAÁ†¢ÕÅjjjúŠQhlÚÑØƒš&­hSÓ´iQ¢6b­Ôç ¨5‚ E¤•‚(²ø(‚Öø¶¨¼öý`w§3ïWäaýÙIî¹÷Ì™3ó9g¾{o’ÀÅãñ€J¥’­½^/( uƒ}P d‚ÏçÆÉÁM&äææBCC(•Jœ<µpú .çççcdd$g 5 feea[[›ïi'OÀ¯ì1ag¯ieÈϵ§Natt´ÌÁ)Hi}½^›óòºmØÌc[à¥tóž*{ìmdÄ(HH˜AA:‘i ¶„;ƒ “âÄYðQŸçòEy¶ý6=—/!·:œ¸js!VŸ½„×ï¶ciíEav¹¹ SRRÅÊ££c°´¤XèýyØUŒn Êë°¥Ý,»í±ƒ²®çÃÃ#ý}ay-äì> §ŒÍ8ity|°·ü444_‡äÄI°o_Ôœ< ¯OŒƒ[ívøð‹¡ ¤ 2æÎ5ʺ¦Pù$ÄŽ…„ׯBVÝgT„F8\]°píÏðke„ê‚ th((E:Bƒ¡Ýâ€M…åûrd|ðl=pVäîÕ  @ð£ Ò€ÝÙeµp¦ù,x/F "¶Œ·Æ_Äà‡ÓU Í :rÆÀ¤]dŒZµ’ôZ¸r§ø T› Ëëƒaœ}ÝÖlËÀõÁZ ­€û–îqÑ>ÞȇA„èAA ]]°˜­ÀõÍ—ÀyÄá$ µ8p!A V)ÁK-¸Ü]ÂÖárƒ“æ³hh\E‡¹/‘G¯º•óÄM_fÀ[S&À؈çá£YZ"‚Íáwáì-6'tRð…)IðÍÒù‚˜>MI„ðaz1Æ ©$úŠ2¥Óíö@Frœ+Z‹ß7À²e™°|ùr0¼ò¬]2âcÆÛqš­v'L?~Û’ Û²Á‘ƒ…žžÎÖ›ðùü·!}ædÚ6â~XR* “ÕŽÆæk¢»ý—|1"œ7U\£Gã®;ÄØõ–v¤tc}ÓUÚvijÆ38}ú›²­R©ÂÌÌL4u´c§Õ÷:,bÞC>]¹¡Õ `;¾Û­fœb0ÈΘnù’€L£@6‹Y°Û¯Y³Fc;fHz?NŒ5ÕÕl&Û‹Ž_#°ÎÝåA;P}ÝiLNN–KÁSSS±ñüY´Ùèt¹ÑîtaËÛ¸:;CˆŽ%;¾3IØ_„» Í6‡_ÈG»TRÝ ³Í‰‹*ñÒív¡(=\‚ãÇGcLÌ~»û2韨Çé ¿Æ Wÿ¦;wlǨ¨("›¥‚lX¹çèi,:nD+•hü‚¯pëþ ¤Ô ûþF' Hùî$Æë0[‰XõG%ÆÇO¥uv³#ßÃGŽÄŸ¶ä¡ÕlB‹Ý‰ô"BfTIø³®?y€d,}ù|Ý**Ž¡BÑÍpjµZ0žV«•Á¬&Fd‘æ $°˜@M¯¤A¾K¦8oÞ<9(g 66‹‹‹‘þdº•@ôôÑ×s¿ü'—••aRRæää Ûíöt?€gôz:ý”´2¡á?¡žÂ,üƒò´2`R(}¼ü×ß2ö9hgu4ŸÏÊë üüà_”o²ltÊIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/167.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000002732615232633614033160 0ustar runnerrunner‰PNG  IHDR§§tLìsRGB®ÎéDeXIfMM*‡i  § §5^¹Ò.@IDATxí]|UÅÒŸPBè‘®ôÞ‹`¡‰€ <±#‚ŠØžòPlèóaCÑ6|" ò¡(*Ò¤Jôzï½…ûÍnv³9Ün’›ÜÂÙáìݳçìÎÌgf÷l‰RÈ .B™B°Nn•\\pº@Y¸à YѸsÁéb d9%dkäŠ]ºtIjE™2¹m8âˆr{ëIÙPfΜ9I"ÒPÕ ÇW%$ðúòåËdsøðáôÔSOÑÖ­[¬¦Ö¦'žk¼$hÎk90(Õ…  æÎ«š5k†±_ùË›7¯zë­·ÔÉ“'%TáÏ éÏJÿ"B·„‹/šÊ±†T=ö˜%›v•%Kó»B… jäÈ‘&?ž°Ý~¸&Áik¿øøxÕ¯_?•?~"›o`j͉ß6H[´h¡æÍ›g$­ë‚Ô°# ‘k œ‘­-G­*W®l€hƒRƒS_¹Cd@ ÀvïÞ]mß¾ÝÃ~¯It#iâÀ5N§_¹hÑ"ÕªU+JhFN1¹+¬ó(P@}ðÁ ÚÁÖÈi’Šû°p âÁik´]»v)î  A#&F_÷l-[¥JõóÏ?H¹þ¨aEš" N[‹={V 0@.\ØÑ—/^-Ýé¶nÝZÅÆÆ¸þ¨aEª"N§ ÿõ×_UõêÕ (íÎÍÕÀçï}ÛÅûŸyæµ{÷n#[{›D7rUD 8 \²d‰j×®]Pj_Ñ_Ð¥4Ÿ­‹)¢>þøc­`kò«JÅÍ ˆpÚšiïÞ½êùçŸWY³f`B«¥Ö¯L)8u~[;׬YS;ÖÀÍõG +®‰p‚ÊóçÏ«Áƒ«¢E‹mik2 œŒºBKÛå·oß^-[¶ìªq3$r ¬Á S~æÌ5jÔ(U§NÊ” ¥7XmÍ#GñG7lØ ÷¨¿|s l'~0IŒ+"öéˆÓiéÒ¥ò›)4ô}I â @™ÍÄ ¥Ó§OÓ÷ßO+W®”…JƒÈžä‹öÛðº3mÚ4Õ AƒÒž¶ÖŒ‰‰Q/¿ü²:zô¨0ÖÕšWÇWX›uMzÂèl|ùå—ªxñ⤶ßÇÍÔ¤§gÜéovêÔI­ZµJW×Õd8‘|$"À íûÔ‹/¾¨²eË&`´5XzƒÒî©×­[WMœ8ÑHÀ”7¬ð+ràDá"kÂäú —ø¦/³hÏÍdßNuìØÑhKhÑôë´5ôõ×_¯>ýôS3O Gkw§T<´úîN_´:ßi¿C œ¾è‹é©·aÚ ?~¼ª]»¶©­ÝÒªIm­­zöì©öíÛgªekt“ÈÔÝWýí|:ž’¼ú™p¿†8Áxh¾›8GmÞµ_~:µòÍ]¹Y?uFg÷)dû« ÆA °qP§_‰¯Qö8¦Ý8LE9z.^L¤uìÌÅjÞò ’å񴀮¦c‹ÖnS{3¯¸–@Tp:5wùzugÏ*[£®jåÆWLK¨ßwSÔÿ¯æ­Úl€‰w9¬óÛÚ _ž{î9ó æÚ/%ÔÖ¼5jÔðû ʵ[w«GßúJQ‡Ô¨Éó¥ªö} ¡ãç©^ƒÇ¨)‹Öª3çÎK>×­šæH¸mi03Ÿ2óØ_æÌQ´uÏAðÝ=u]º|‰ äÍ%é ¯!GöhÚôý4c)ÅÆm§Ö ªP¥Ò×I^Æ(EeŠ"{$PÆ?ù ñ—$êÖ­½ùæ›ÄyΟñQ¼‡µ11؉g8Ñ«¯¾JÏ>û,qÇ‹,òäq†DZ3Ñ‘§hÐShèØYæ,åÊ™b²úCölÑÌE“®¡%ëwÐíõ+S½J¥ˆO‰A*t²w¿3|àPÌS,€²ù“ïÑ·æPölY)wŽìtñÒeÎ㛿xG–Ì™(göl´cÿQúßøyôÝäE´ÿÈ ^Âë&gÔ å/J4aÂúå—_ˆg- àpyœ5«¬À0>žuDlÂé…^`"yðgÔ ­ˆƒÆ¦=Þcš'rº¢|yrÊ}g]ïör1­‡Oœ¦‘Scé‹ßþ¢-{Q&¾ºð®H WJ"¨„à! áçi±Ôÿ»ñ´zó.ÊËÚ£ kK€2YTZuãW‰P²%h¥vRÜöýts²Ô¬vyÊ-¹Q®­YÀ´¦»ûmÛ¶ôÙgŸÑ‡~H‡’çt\¡)î¸ãzçw¨~ýúòé¸?;­ ˜ÌÜ€ áf-‰£~ÃÇѼåë¹^Ù¨P¾Ü¢ÙÇ´K6fÍ’™¢ùo㮃 Î9¢A[Õ¯Däà/)!ÝÁékTff\ìšÍÔoØ8š»š²Eg¥Âùò°Ùºìf*¸ Œ0Sc×Ò²;éöz•¨a•2Í€r¤ZËAëñ×êÝ»7=øàƒ¾¯¿þZÀƒ÷€<ÓúöíK÷Þ{/’äž÷¦eMxmÚ¹Ÿ>1ž~™+ uäN¼'¥ÿVP›ù†ø‚Õ[iõÖ½Ô´V9ºµf9Šæ†ªùaÓšÒrB%º‚3QP™h×þ#4àû‰ÄÎ?»p‘òskWi”“Ð, L=÷äiÔŸ‹=þhÃ*T¾DaÉîM³@ëA )Y¢!C†/¦×^{ø«ñ`>ñ<Êž=»Ñ¶NM‰—CGEqdТüÏFO¥¯~NGŽÇ³ùÎÁu‹Ju”Ê[ÿi7 'ûÞ˜—ãæ­ft'µb´v…’yPf8+Òt§ø@ŒŠ{˜ôÕ/3賟¦ÒÞCÇ(_îœÃ-?%&Í’ËU£(; &p+ûeCÆÎ¡:JR«•YKç2‚³Í´ŒöG2þFOÓ§O_¨P!yFû›Î ·vWÐøÐ×mÛCùråàÎ]ÎPÞ/­ #ƒô౓ôíä…Ü ‹Rkn¥‹ðЊ<쇇c(8!$K ê÷YKèƒoÇÓŠ Û)·åWò(_ºò õ@h( =úµÛöÑ-5ËRSöG%]ªàÛ…Ù0ugÇ©-…V¼ö+ç­ØÀîÊï4ki›Ýèw…{ö)ð+Sà ”•;rÑ,Íu;öӦݩAå2ܳ¯Ä $»¼r±djÊÊègN0è2 Aû•ËÖm“Àä+EƒJ£_™Z¦@ 0ðó0³lÃ.š ǰÙCoþ(À‡à%ÒÝ•(ÚÆÃ`ýel¡±@ž\uWPž?A$g„? šøC­Ú²G:‡è$Â’hšÂÅM38•IÌöÀ‘“èû‰sé4›s˜5¸ð©íø#òˆ?*æÃ1ñ4rJ,kÓmbþn,æ1Ûb"-óçM€ž÷xÜ•S§ÏÒ—c¦Ó?ÿIxÌ5?»+x&½ÜèD»Až=~ûk-æñÑ;Ø­©Q¶¸¼ÆÓ CßM38aÂϳSþõØ™4˜—w8" 0ÜP ×Õ†c’«¯öÝÆð0؇¬-WoÞ™ªa°äÊÔ=Њё\9²Ñ¾Ã'høÄ…Tõ†ë¹AV¦Eòª˜t}OªÁ)>›© WÉÐÐ’¸-̈ìT(a¼2Ô€©¹h›?huŽaó×´vº¹ú<¨žU̼Ϋ6‡‹×n¥÷†åa°5< –%ÍÃ`vé‡cCLp]0ì´q×jTõj^·åey)¾ªÝ¥T¦ þå˜i éá7†P^vºe`™‘Þ€@ Ñ6˜ž_f/£Ý<šÐµuCéL±Ò‘ Ý–åÜ©ký|ºxáRÀ‡ÁE“¯÷虃äôÅëå SÏ{›É—6€8šô{›/êéž®ÉZe®1J­aÙCú§69øvü™ó>ëúœhÐ|¹Ù]a0kpû| oè:çägØÕ¿C°ªR¥TS“%¡¨?êôp»¢±AP™­‘“ýÍ>TÝg}“û-´jÓ\Æ ßK8ÃQS&Çom|å¹Ú}_Ï…bz8Ð’&p†"ÓÝ:E\pFŽ,#Žœ'ÒÈ!ÈgäÈ2â(qÁq"‚\pFŽ,#Žœ'ÒÈ!($Á©çƒúb3æ%†Á²¯ê'I­Þf@éL¸—Ü}/¯!N Êc'ãeñš/†ãÓ¾áëYB¾ò…r:ꎿ“§Nˬ._uÅ’ÌúÒ_¨|å‹Äô'4!&’÷ê©{ZPéë É·l[k$Ìÿ• ´˜’wŠ¿w#„Ó oЃeÍøŽ”ç–>ئ 5®YAhµ›žˆÑ˜g•¼®äù£øìhç‰D@Ú4¥jV’ý‚´Ä!(hËxÞöÜù‹Ô²A5êóØ]Ô jY¯¯åì<§†dUe•2EevÍ‚5[é4kRLÜÀ½Pþ¤ Pže:2ÐêU¹^íÖžÚ6©%´¢îHЛE¼X¼9ýµ|ÍZ¾‘NÄŸeZyZ3#Ô'naiø/hà„ `®°Fõ²%éå®íèž „=MÍ] „’›gBu¼µ&Õ«\šx«Z½e¯h̳ÄÆPúvŒš;E%yáYßÿ î›É@°Dá|ôx»Æ²^f ;€Ä0@~>˜Áã'FÑ1ö+¡ÙŸa:Aïõ…òIµ’k„ºÞ´ ¥O×»¿E]jÀëñ'sƒ\ϋٰÒ4:+6‰.­º¾¼f8¥‡Í€¼¦ÀéÚîzé‘vtC1Ïšr-(˜n;`:žgM¸g§}ù¸k´Fõ‹Qe6sWn¡™K70 ÎÈö6(7£Í…Fˆív.\¼D­oª!îJíŠe¤ú˜š‰y€úè#âCO©sçÎÄgøÈîç óçé4•â!˜w5¡nmR‘ü¹ÙÌž  O ‚Ö„z YLë¿j-ÀD#Dg™ SkKÐ2bÄâÝ—e¯¦n¼=#ãÂ… Årà>¤hš)>t{=1÷X*(g¹¢;#ÞPp‚‰Ð–'OŸa朣ZßDÓ‡¼F¯?ÖA´L8òئ D‚éZCà-;¹a¿¢#GŽ0òaXćȾšÐ2ЬúY›Y\„÷ðW‹Íü¿îkNšTí ÁžZ¸ö³þÆ=´f–ív`›׫Jõ¦A½»P n •‹¾B[¢>èDýgÏžM·Ür =ú裴uëV¡éاqãÆÔ£G±0÷(Ókƒät¼ -W¼0ý³ÓmÔ¹U}^Kï F=¤' CCè…7¬VŽ~û¨ }£;•/Y4AP [·XÒׂÓ!¿ÿþ[4ä}÷ÝGk×®5 ÔZyN:%Úûk~÷Ýw ®gSWh#;à½øƒÐ°u †cz1Hó`|a—&yRÐ’ƒÇNÐ%ŠÐˆ¾OÒØ½d|štÁ¯t¾Ï ,mË–-ôÈ#PÓ¦MiîܹB? Z‘´â=ØñµÿþħÕIº¶0vñ^Ђg°KóÂýͨu£*Ü@¢ØççÉ÷SJ«]FFÇÓ Né!2C± àk}ñê£4ùÓ—©)w| (Ã#¨¤°ÅÇ?ˆ¬7ÝtM™2%‰ 4³Áû~Ùm·ÝFýõ—ÏgðœÖðG ðŽo÷7¯CÏÜ}+U(YDv&ñ×üÁ]pÑáK¾ýä=쮼.㳨'Þ¯ó \&ÜàNžv@‹r±¡˜¸¦<Ã[ü)ªù€*uçóêÍ!c ͼ  x ÌPsì Ž{æ€â-¬ÑÜåeâ:ÍÛ•…“äàSªÚ¼y³)’5‰Û€ÙGé‹×mWŒœªzô¥xÇ`ÉÊYLÐt,X¹QE7êª µxR=ýþ0µu÷+ò˜„„hµë1räHU¾|yCŸ¿´2àƒÔ<צMÅVÆçë|#Áî…É·nû>5èç™ê™£ÕÛÃ')¶tr/1‡É´¼ Î/ÇLSz T¼ÝŸy‡½é¾Iä@a Ç<óv׆á6ó½ÑW áá~Þ¼yï<¬X;IÑvC°ë‚8ê£AÈ{ ©ñsW©¡æKšNG> ο–®SÍŸzOñnrH–>à=΀4û4 6ÛªyóæIhÕuöE—·t»A‚_¼½b«cŠ·ùk9â¡ÕSOT—‡¤gÏ]lWR`?¼xªÀ©‰áÙC¦æ¥?‚Âq(8E3ß—NKÍÕÖB*T“„uå 4ouÃ}v=t6Å~ç3?“Dxã.þ*ê ¬ýœÑȶmÛT÷îÝMãA°ÔÐg?cÓZ¤HõÉ'Ÿ¨sçÎI5’kvÑ })›ž`ÆSN»ÂºM´}ÏŽÂR8H Œ†!([hNó×¢E µ`ÁS¥dÍŸ/Tš§=ß[°A¯Þÿ}•?~¡õ²e×9-qÛÚð›úý÷ßMÕ|ÑŠ ¾äe‘HšÀéSY~%˜ÄG«(¹§‘‚ÒïÆÕ6ÆO<¡vìðœk¾ÛÆ–ƒÖŒvšŽãž·ûàý¾Ÿ~úIU®\9Ãhu¿C‡jùòåºÚâ^x““7ZÌC!I84€ ¶¯…CIq8©Z:˜©§÷Õn T<¨¯xp_ªmk:'þüvÒ«ø´ C[FÓj["X§^½z©ýû=§à»ùC_(ä (85A8¾™P š œ ·Í_ÕªUò몦ùºk×.õôÓO³hwÅIOr¿íY¬X1õù矇%0!˜€€Z›6m’›+W.¦Ýš“chF܃ƶAÊg©3fø4{¾P«i… ¿’O„3ÐFFÐä« '­|ƒ4HÄ÷Ù1ôEo0ÓN˜HmذaÆl¡",-D-kÖ¬L÷Üsâ/N2îŠúû4­üyÑtxÐmàëò‚yuÒzóÍ7ËiƺþþÐì<'ˆÐÂEÇãñÇ7¶™@œš„?}ª?þø#Õ¼×´ò÷}Õ§O•#G޲¶RÀ°Ú?üjZƒù`ÀÀ "Ð*u˜3gŽjÚ´©)4 @’ÑÚÄL0Fp¼5‚]_]o¯ö³qqqŠçÚPf°hÕåâƒÄ[o½¥Nœ8!$¡AéFå/ÁÎPp‚Íîòä U®\¹$‚Ë€Úþ.L9ŸÂ¦pœµvuZJ¯¶=:Áóü;M_F5HÐj7Â.]ºˆÿ¯é ­ú]yM8!_º`ˆn©0ÿùÏTîܹEphÝ`¨b ¯x·-(|Z²d‰á©¯ÁiÔUª4™­7SñYìB¯­ÉPðeÊ”QÇ7ÕA=l·ÃÜàHJhµŸ FõÔSŠ×™b} BLè¼A ßOœ£nhßSÝÙs€<«éÃMKܶ½BëðI ÔîƒÇLv^“È'HǯxÒ°¡ÕÖòÉѨï9Ý•x@­[·Îé‹V¬ÕQý}ÖbU§óëêÆ»z©Ó Rä ŦɯX0–•'ÊâœÅGÏ”%¹2q—g²2±òÇÌ5Ád&Öâ>9ÑÒ¥KåøhÖ2yyð—\`AÉ$\fª<ÓªU+š?>±¯G%J”0ëm°I^ƒ2L2ù“‚gó!ª­ŸëOÏ|0‚ö:Î'çH’ßþÙï8ÐuŦÝ4xÌ,7w¯I:'w‘Åkg—I¿ @™@Œz²ïK‹-¢AƒHñ€³ŽI^Â?4­žº_¢FÑÔ©S‰‡‡¨bÅŠ¾iågA+ž­K×m£{_L]ÞB¶ï¥‚|šq¨‡äQp•Ú 9>•s笠ÿþ<“VnÞ-Lc 4‡ÜD ¸Çš”xæõë×/^LXžAâBCg@:ÊeMA<Á‚F-³çq 5Þ‡{…óY#(Ù¦ûé‰w‡RÇ?¡E«7ó±Ó¹dmòø  ïÆæÓ–¬ã9ƒæ­Ú"4ê%ÈcÝØP75³ÛyÚ =÷Üsòé:ýâ6­%K–¤¯¾úŠæÍ›G·ß~»Ð >y¥•ÓÁ9¬@À1â½ÿ;ŠÚp#œÂåæå=¦²ó9Dáp˜YšÀ©™ÉVÁsÎböÄs‡ŽŸOì§%¬Ññ,ÙÕùõÕf~¥J•’škJ 0Ô‰ø3rbó§úÑ“PΘl²­ @é•®£óª5d.¦›ký4c)}ÊštÝöý‰ ’ù‘¢IÍÉã­²ºòÎ;ï4 RMƒ´ÆÄÄÐK/½D4»éF ~8- ä ²`M‰õ\Ÿó¡±M{¼Ë‡ÇN“…‡&»)’ÇIW(þ8A„ÆÀÔgç5Ó8gñÓ_fÓ¯|jí ¢^ý§…«™fkóaØ&š‡cŒÙÂ=è±ÇAae&™ ¢…©ß‰+òB¸‡2~˜²@õî7¿ñ’Ù‹¬-sŠÆCžÔÐ S«±·Àù߸yôÝäE´ÿÈ ¡šË­R7¦‹ô&L˜@<ª@<º`hÕÖ£S§N²è‹ÛxV•Ð ZL;xÞZ=K'Í[N-Ÿ~Ÿ^úïtìäi9úòI-­vY8u¥Á(Eï„6kÙúøÇôïH!`aæ"þìé!®Ü¹!ž—(Zƒ'’ÈB6¬Rüæ›o¨téÒF¾%BäwÎ_¹‘Úýë#êþÎPÚ±ï0 *1f $¤Ù¸Ab±¥v²[3‹&Î_-«ÍÂ:­`„Ü›ò((P€jÖ¬I<ÝÆŒCÕªUóM+3ÐvWVmÚI½þ9=ðÚg|¢ñ.¦57üÌl¯\ßoó>TãQ ’¤(ñ£¦Z):B?Ï\&ÚiÞò]¼x™Î²™)Ã;¬aw ­ŒCPWz–ž]= Qø{=•*UJâ¯Ö†’`ýðÃùGؾ÷}øí=u¡'ï‚ÝçœÚ yñ 6Ûjws-ú¡ß?p¶¦È6î<@_ŽÃ ÄN¾iå:ÃËp‹ÈM·×«$›ni-Š+èuÝ ‘γÄçñQ®‡G«ƒ^g°i=Èç½2j2 7[:iúœ{o2AùçxIt©¢iÞ7ÿÿôx«—³ÌŒþ®ÛÑ€0(3o“+K4ñ ñ"29” -V(¯Ð«Án`‚i L§¦ô”‘Ø+Åf_Œ™&~]r<'û½Ñ¢aì÷§Gtz8ãü8o$6êÏÅǧ 7¬BåKx6,“o;x÷Ê):”¥}\ôêÑX&-\C˸ãt{ýÊT¯ûÑܸ®@ëÞiГièØYì2œNø`Àþ<¿3RCPÀ©™é1™ÄüaGb ÇÔ*W\:M×ñ®ÇÐ<¶ìðƒVñ¼×ç°ßgÓà§ò—£²a4´e¨Ð ­æð‰Óôý”XÖ¦Û¨Mê¼nÁ+hJ™`ŒW¢S÷ÑÈIüñ`Ÿ ¢çσ¯i ÕÓÈC•æ´ÖëÊn`ZߘÂç8N†cØ']²~' âAíÇN 0µ+ày­GÀ=Þý†þ5p¤ìŒ­ÿðŽP¦ÍÐ _štÓîCB+o#´âžzˆè½a¿S×¾_Ñ>îÜÉ0<’üJM¯·kÐÁ©+åñÑ” ÚN]Ôèþ$!‡£Y­"ƂǖŒ¾Â&Bï‡À]I„¯¯'"'=dÀ©Y ¡Áüyëè<èõCS&Õªúnø\µ?ªÇT½Õ›ï‚':¯·<‘šràô‡ÑáJhÔy®%Z5Íú–àÔ•w¯‘Íœ‘-ß°¦ÎgX‹/²+ï‚3²åÖÔ¹à kñEvå]pF¶|Ú:œa-¾È®|šÀ‰6É –‡ë@‡sö“³þöt>ç½pú Zõ¤ìP®wšÀyg¸cV5„Î ÅÜKÐq’Àù øJƒƒeAgxÓꙤŒ™ÿ¡RN–L¶¨Xªˆ,¹8ŧÕÊzužáNSÑöó¤Š2|^d—;oºìiê"¾g_ϳöëW)-Ç âÛ?>9‚á )¡DpÀ¦*>Ý©Eóº'| ÕÆ–ª)sš˜ë æ•scùèè?ùi¬<ÄÊKš&Tƒ‹xŒ§®aRQ}¡sžõ“[„e›o¿<9cø€×Frñ”ص´uïaŠáuèY²„6­ŽIJhĸã&zµk{*Wò:itš¾P”UªÀ© ‘ï¾LpÖ(ÕË£™¼ÒrîŠÍ²òGÛðPš° …sÉ/]¾Dío­M¯=zU/WRHÂd’ä|1Ð[¥LQ‚Ř¿z+ñv<<73^6Z CŠV¦K=Μ;/gÝß\«"õaZoãc®F«d òi§Ö  4&ÎY¬ÇÔO‰£ew i8BåA Xc~–§áå5ôõªÜ@¯òyèm›Ô”:a~$´irÀDFÐ Z‘ï–eebôô%hÁê-tš}Vì2¥ÑÊ›ƒó,€EGù<Òr|0î‹·¥GØe‘úcB6Óq5ZƒS󤥦 œúUÐ"6å8×¼Ë äÔZ€t3O¨ÎêYì S!@K:vŠJòÒä¾=î¦î›Êb;]í{jzpÅêG€ ÚG7B¤k“æÎCo©Aõy¹ÅäEkiõ–½r¬aÇ2äŒnžÑE8b˃_~¤=ÿ`k>ŒÖ³/R8hKðX‡€€/ƒ bí£µFE^ „Sy®ÙÊû ­çãŸaþ²Šð4(t%ÒãjüJî•B£={oKz±K[*Z0ŸçKPz­¸½úÑÛ2]iŒ>@°xá|ôx»Æ´jËš²(Žvð6<°ÐÖA+üJlþwj^_Ü•JeŠyheË€ÚÒÆBÀÀ©_ªµ 4 xSµ©F¹âŸÍçM¯pî7üQ dýl ®Ae’%Ah}S ñµjW*#¯îEP¨ @¨7r˜4i’ìÂÁÛuË&¸àÚ eò¸Q&6Èê7£Ê¥¯ãÍ&¶ˆÿ}ìäqwÀð#=†ÁΞ?ÏîÊ9jT½œ€òö†Õi…»Âô†c885ló—“—·oRÍ_i1z:1,´@É š gŠÃ¬ÕªPŠ^éÖž:ÜV×#(êäMPZ3˜¼ç%ñFÿôã?ÊsÆ £7Þxƒø€U&ò¢ØövƒXšÖ.OµË— i‹×Ó¢µÛèïÍŸ\\Ÿ :ÐÐñZ«Š¦~϶¦níoKÐÖ ~e˜‚Ò`HGÒë @@(ÐE æ¡nmÑí›P 6…؃÷5SŸ–òa®ŒáåΑúýó>š>¤å´ê]òâ¶`tj~Ó ¹¼¼¼ýM§¦µx¨íVªÌ=üÓ<€ Ä<î†]‹”ÅuÇí7@”a°Yÿ{ýèfL¸+¨Ÿ®KÊÞZ¹ÓMsÚdŠ? 23 ¬ Ž¢x£¬ãÎÆcŽÐK]î¤×rŒ_‰ XæYƒÉ#FŒmÉGPK.€ÀÕ;@ØØœ¶eË–ôÐC¾@|¾äÕZW~$üáý ¶×¥Ç]Mˆ·ì¦©ÇñZûcÃZZ>%Ï`ì² ƒÕI: †¾n~er<Èpê ØæLLŽYÏÃ1[é ÇÀ½Ì‚H.x…1¼ 2Ž×²A5êóØ]Ô jYyÌ34t¥ €Iû•|òýûßÿ&ì^‡€tÜÇŸúaÔ¨Q4nÜ8âƒO‰$ >ïG€x¥? o4ѯ®Åf¾ o`6gù&šµ|#ŠŸå5ìÑ~i8¸ âóíyìFkÏÃ`µ¤>Z½»+’!ŒÿKYó ¡ÚäÀäz†cjÒó÷4¥jÜ¡@ñy09|<‡y ¯l‰"4¢ï“4v`/&4¥G#ÂÌ'­,žP37oÞL<ò5kÖL€ MéËTë·|€|$!½óÎ;²¿æ·ß~+ïµµ­~W”‰?ÐÍK™[Ô«H/ÜßœW¿Q–5ƒ^Ü÷ø1:Á~%–Bô¯Î4í‹×˜pUÄ]am™Üó¾Þé,Ì f°9Yµy·ú`äTµ}ßa©ÂÔ1Öê®^Õ[_ÿªN9kò Ý[`Pš ùqšYß¾}UžÒì3ØŸTÍ›77 d¿2Mç9Šß:´)â8s’M¾:yÒ*4üy Þêï-Ÿ­ý½ÝÔ´§?Œö%T[SqÏ;ÃO/¶µ1NëåΓ!uóUo“ÉK$5ÏxyMX&…%8œ¶µS||¼zÿý÷ÍYèÐh6h¼i¾@¦9ýÑ-Z(†2UNÎ5™Üˆp "À©eùÓO?)>›È˜ðŒ¥à¶? À>ñÄ gÑ»Á„58aòpv:ÎÒlÓ¦ezø•NðùûÛn EŠQï½÷žÚ³g˜økÙdûѰ'‹¿#GŽ(¯4ÀÄÙêºsâ/€Ò;Šzér0r€ºÛ>²?ºÖò„-8‚‚ÀË–-k`k, ŠŒ¾Ú¦eóÀ¿Ú²e‹TàtCòˆpjA?~\½ùæ›*wîÜRhP$£Aéìñ¤5sæL# _CK&ƒD8A‰m"7lØ :wîl@ -šQ¦ÞÖØeÊ”Q|âœêèӰ㪑ˆ'(…µàyŠ›jܸ±izv” ¡µ–æã¹UŸ>}ÔÑ£GE¨—Ýx®*7ƒp ¢À©e í¤Á` :Tñy™¤¶vK«É‡F¶ßwÿý÷«¸¸8]S“àFüæ@D‚SS€jôðáÊOV|Ò°€ÔÖt©¨Ó¯lذ¡š:uª.Z4¸.Û$º‘q ¢Á©9¡µ(~¯Y³FÝwß}I´hJýQ[S–(QB 2Äø’(Ëõ+5çÓv½&À A‹Ùþèü¡4h`@ê?jkÛ˜˜Õ»wouðàA#»˜D7’j\3àÔ²ýQ€éóÏ?WÅ‹7 µµ¢6÷N¿’ÏGW+W®Ô¯Lz“èFÒÌkœšc¶–;pà€zá…Ÿq~…? ªAZ§N5aÂý ׯ4œHŸÈ5 NÍN¤+V¬P:t0`Ô ä3ÐÕàÁƒå;>žƒöuýJÍÁô»^óàkáÚ ålªF¢I{öì©öîÝk$`ç3‰n$]8…·²†ps€A*|àŽ9sFÖ¬W¬XQÒ”²fýO—WÄœ^Í&[€ˆ[ˆ¬.(½0*“\pú`0 þL7‡.8ƒÃw·T?8àª?˜äf \p‡ïn©~pÀ§Lr³‡.8ƒÃw·T?8à‚Ó&¹Y‚ÜÁá»[ªpÁé“Ü,ÁဠÎàðÝ-Õ¸àôƒIn–àpÀgpøî–ê\púÁ$7Kp8à‚38|wKõƒ.8ý`’›%8pÁ¾»¥úÁœ~0É͸à ßÝRýà€ N?˜äf \p‡ïn©~pÀ§Lr³‡.8ƒÃw·T?8à‚Ó&¹Y‚ÜÁá»[ªpÁé“Ü,ÁဠÎàðÝ-Õ¸àôƒIn–àpÀgpøî–ê\púÁ$7Kp8à‚38|wKõƒÿ‰t÷‚꨺IEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/216.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000003672715232633614033165 0ustar runnerrunner‰PNG  IHDRØØ‰ -ísRGB®ÎéDeXIfMM*‡i  Ø Øìê3j=AIDATxí]|Å÷tBï]½Jo"M:H³ ŠŠØQ± þƨˆ +ˆÒ±Q…Ð{©¡“€z ô¢ûßw™usÿäî’\Ù»›ùär{»³³3oÞ÷•Ù™7 N¤“¦€¦€O(Ñ'¥êB54„`š4|H 0W­) ¦y@SÀ‡Ðó!quÑš`š4|H 0×¹èþù‡nÞ¼Iú͈3eB÷wýÌ÷ûï¿ÿR† 䣞°eÊ”IýÔß!J­Á|رÐTRÆŒ\¿üò 1‚®\¹"àððÑ)t) 惾°` BkAKmݺ•ºuëF=zô W_}•êׯOÓ¦Mà|¡6}Ð6(R›ˆ^î«éwòäI>|8}ùå—tíÚ5PR‡èÝwߥ Èoœ LBƒ`^êGeê)ôõ×_Ó°aÃèèÑ£òàCR&£ãSO=Eo¼ñ•,YR®«óòCÿ j h€¥³û”Ÿ•9sf)iÞ¼yôÖ[oц ä7Î0É™€VÐ.\˜LÏ>û,eË–ÍôÍF‚—`éè;˜t X»ví¢!C†2hµä€åüH”¡ÌÆš5kÒ;ï¼CÝ»w—l§ÒxÎ÷éßö§€XúÈÊôgÏž¥‘#GÒèÑ£etPie2zZ¼Q@ëÒ¥‹øgµk×–"´æ)%í•O,ý¡4´4Ó÷ßOC‡¥ØØX)Åjò¥¢Ø$Y­Íš5+=óÌ3ôÚk¯Q±bÅ$ŸöÏ’Ëö?4À<è"g?kñâÅô¿ÿýV¯^-w»ò³<(>Ù,V°/^œ^ýuêÛ·¯˜¤J;*0&[€>i 0óèä‚lš™W÷ìÙcôêÕ +Àåà 0Ø´3«óÞúFÙ ^³üzõê³gÏ6냺1ØÌßúÀ~Ð,9gõ³ÎŸ?OŸ|ò‰|.^¼(ï©à3)M’B^;gA[¡NHwß}·øgÕ«W—ßÚl2ØòŸ˜S·Xý,\?~<½÷Þ{tàÀÉi5ÝœnõùOe¢ŽôÜsÏÑ+¯¼B… ’gk ù¼ Rÿû)ÕÀÔ¦Ö7̇/_¾ÜhÑ¢…ižÁTó¥9È=g>ËÝ1LS•§T©RÆ7ß|c0¸¤î0Õ±Ù}0 `4,ì“ÕÏbMeôéÓÇd`03kó·bì@;ûg76¢¢¢Ì¾„°€ÐÐ)°k€AÒ+&dßÊ`SÐÈ›7¯€ lÕTJÏw®çý÷ßoìÞ½Ûä*«ð0Oê¿Q ¬¦¨ eË–1¿’¼cÂ@®kbá`Ž6FFFÒ‹/¾HO<ñåÈ‘CšÄ/X›”õË™¤ @;wî¤õë×KÇa„N/({2±Òh^|#ÅÄÄЪU«d©Lâeýåo p‡„eR¾W\\œÁ3ØMËjjq_˜f£Ý=î¸ãƒÁ–}k§F‡µf`Mf´oßÞ”†åÝÛê3–/_Þøé§ŸL³¶Ñ<©üF°ôÁ¬VSZfdÀwAš>}:½ýöÛ„å'HVŸFNØèŸÕ¬Í“' 0€H8vn—ª^Uñ”mþ Ù«´—/_6x5²‘?~ÑhÎCáÌ!¦¦ ıs}|ðAcß¾}&…µÖ2Iðƒ°6“£¾•9yÀà8sL15(`Y'ÿ6mÚÔà™ýf3ôËe“¶9j€a BiO(ú‡3P®uÚ Zµjej­@øgV?«L™2Æ?ü`6BÁS:ÜLœReÞìâäRƒA.²éK.(´>Ø?ÿüËþ‘ã-ƒõ8%Ÿy…2&¾²§”ç™nIü³‰'Ê,ö½{÷ÊmþðÏàg!1£SΜ9©ÿþ4hÐ *P Àÿ«ŸdLáÚ Ã6cFÇ{06”ÉE¼—™÷rØT^EBáútÊp>[^²Jà3ç/ýGþdü±t£ÔõæMÇ„WkÅ•ž»f§µ>š%=³ 'œW׬ù“;¶úg.\08f†Á ¢Ñœý!¦´©éÒsì\î}÷ÝgDGG›Õ³š²æÉdÐF+]¬Ýn<2äkãÒ•k’ZÊšMΜ¿dŒ³Æ8|ü¬yYÑÎ<¡ÜR h^4CŠBªBê2ÐØ™Ë¨ÕÓC鳟çÐõŽ8ƒÉ‰n¤‹W®Ñ´%›é³_—Ò®˜¸ÿÖtq†Ä,ŽŒÉü‡Á‡F< I¢FmÞ¼™z÷î-Zç¡Í”¶I¦O1°äE1÷œ<¯Q£F„HUS§N¥*Uª˜±íñ¬=ˆß7ÉZ1L³jÖ¬™€ÀÇ, 0uZ’µ|ÄH3fŒ„%à÷s©*õ@s¬ó/Óû?üA­û£)Qk…¹sDH;ÜÕ1‚c‚À¬^¶e}2u -ÿk?×ÃÑ >:¹¦€cNë<»ŠÎ“dbp쉣áãgÑïK6 óÌ›‹˜“éKVOx0köÌô//§ÚºÿoÚsø5¹µµª[IåhÊWK®\¥aLlPóæÍ‰×ŽÑ¸qãèý÷ß§ƒÊm 4›'Ii>äÏž=;õë×OBl#V"’ÒîÊBÝÁôÊ·š8o5}Ä~OÌ1Ê“+È““Ø4$ø_ž$%trFd¥ËW¯Ó¯Ë¶ÐÆ=±Ô¾a5ª^¶¸<Ú?K™š¶Lp»p™>ŸEßþ¾˜â.Q¾Ü˜´šnZ9RnÞÿ¿¢$oŽlYL 7ûþ¦Öõ*Sãeå¹J2»ÒDVPàøÑG¥»îº‹>þøc5j]ºtI4Ê“K¸†{q?b"Þzë­’šÑ9ˆúŠùÌô‚ÐYù×^6n-Ý´›"²g¡Bùò0¨xë$¦YZ’£ì ”33,€óôÃìÕT£\ êШ•(”WŠt'˜ÒòÜP¸ÇV³J`殤&Ì¥½±Ç)o®‘À&I¿i¢¤3ÌÆ„ËWiêâÍ´a÷afšªT¹tQ“iWŸb~€$_¾|^€_ü P¦L™âÐ(¬Í”ÆCÁ(÷@¸¯nݺ’¿sçÎò\œð.wIBËÇ;ÅZ~6M[¸–Ëþ— æÍ)Àã!)†›æÄ–¶dÍâ¨Ó¶Giï‘“t %'ÐI-)‰Ý÷`Òü>ùå,WlÙC°^¾yO¢Î. ìªÒΙYòÃé=q–¾¹ŠjW,EíT¥¢rË­ž0 ƒvŒ˜%pNñ…0ÈáϤ$oŽìYàó×í¢¿ö¡6õ«PÃj‘R'0Æ•t¶úg vO¹çž{ddÿþýbF:‡Äv.ð3h&ƒ> äu;ö³Ÿ5“®ßIÙ²ÂÏÊÅu†0ò/ͬÀáñôí¬•T«B),€<Ò}î“?ûØßÏò;Àœ%ðT:É#]»²f? £ƒþÀ® ¦ÜÍ•#²\¡I 6Ò†h–ÎìÔW(åÙ 1£»’Î 4ÐN ”ÁõÜ´ùYéȉ34ò§94yþºvãåç‘A‡–÷/°T;ð ð£_•°eïÚ{‚šòmK¡ÍÉ )æ7€9KàµÛ÷‹Ÿ…÷Z ?ë_¿K`éùþ‰tfß,K–LtðØióÇ ªW¹4ûgUDcxÊ4š–D­ûøRx´œÆó`˜ƒ&ÿö·ÅôÅ´(Š;}N´|vÖ\þÖò®ê›ÄøÇ ù¢i ж©_™Uó|„ÖÕ3‚íš_öŸŸ•‘bãNË»Hà7ÿ±H`ÏÞù›À`03Ѻ]1´“g84¯YZÔ©`žG&Wf£˜Ã 4O’€‘ËS~ÖK7É;À­{c)·øY×ò®Ú! Œ,žç÷”“nb À1B[ñ–"r«ä ÿ̧s–À_ó(×—<ÚuüŒCGð»(;I`—L”qÂKWžÛGsÖî Í쟵eÿ¬~•ÒòþÉÿÌÕ3ð„Ù‡R~ÖæÝ1âgÍ_³O2±Ö„–÷¿ŸåªÎ®®¡ÿ3³PÁí!¬_ÏXIu+ÝBíØ?+Ì>#R¨›>˜³þmÉÁïg¶1CæÎ™Ý~–+ÆpuÍ!Ó®xB,MˆZ/þY{~V®„#„uZ˜Æªåa~Ìïÿ~ž³’._»NùxfLú{Ã<½ælÀ—ÝÅ#´Íj•§µ+Fh²Ëµàéóì–Ïë3…6F¢acgPÔºí,Å2'J`{ùYií ’9+ûgûøõ|4h²¶ìŸaJ˜Ë•Ù¨ò€Á`^»~“¾Ÿ±„>›<ŸŽœ<+À¸@Ó`O:H9`ð Ïܵ; ƒ!m˜^ ª”á+Ž÷gîè%…Ñ?¯ F9v*žý¬¹4áÏUtU$0t‰¶§Ÿ•ÖþJ"¹í«w¢‡âX2W æüÉêÁL 0ÿÑœ•ч?΢M,”rçÈN…Ôhj€ËJß$@Âeš8ƒ9B«,kþ`?öÀÀlH?ü±”†ý83q¤+݆†vÕÑJ:Ã?»ÆKgf­ÚAyÚU÷浨 O»JN“)zcsðåO'ÑlXfNzŸåª}¾¸fZlìûû[ËE“uiz+a?„N($¯,W´ ‰ñýåôtòl;±¹Å¶óÆÓŽÓdb:äæ÷gGNÆËˆ#îuˆž¤¥” Ù_{bï1‰Ùa>y¶qzÒÒ‚ó„ èÁ#´ Y¹ý :‡ý׿up¶*i­½0k‘yÙgÈÂSŽ‚Ñ!·¶#­Ç€†I±êÅ««²à›‚f¸ŸpLÊÈÁ®– #m¼0h,eþ#A¼UgÐÀ: O8iyWôU@s•'Ø®y`ÁF]_M_R@Ì—ÔÕe‡=4Àž4|I 0_RW—öÐ {Ðð%4À|I]]vØS@,ìY@À—Ðó%uuÙaO °°gM_R@Ì—ÔÕe‡=4Àž4|I ˜c=•ûµ ȧ“ƒžN¨Õ4K?Ç5À‘÷GÈuµ}‘"òa®º§Ì¥î ¥o´1†À]Â$d%B¤^-šÜQ+åëA 0¬š†t=Åa¢‹ÈKeŠ;ba¸RR% åㄹÀhá$A¬·ºrý%ðvFu*•‘•çŒ!Y{•„=83Q¶¬™©DÁ<²¯íh:¥ž^[ÑœúG§þwtÂÅ+ã‘ÎÍèÕGºPébeiˆŠ¨k-Ù+¨)‡Á¾¥h~š·vEóf`8ÄÓ@ÐÎP^…-5Q|BU‰,Aƒ¾“îoר!`’ÁŒ:…ØóÏÜÕŒVñ"È%›÷Ò9¦9Ô BqY‰•g¼yƒΔ1ß¼FWY ßQ¿ ~´+5©YQhsÆ•FÂýÖeŠ §»5•`˜¼,oÀwN‚ž‚ Cm±#´<èr–·|*'½ñxwzî¾v²K§ „ >-ëT”Í0°ÍÓú]±tMm‰Å… |\SÀöSø,KàjeKÒ˽!o“Va¡"€©ê.9@æ`ˆ:¼{JµÈb´|ë~Ùµ1áÒUÞ-$‹”ìÒYèÁZþ· m­^íÓ™*ÞRÌA³Ä¸‹î襮ƒù8¤ù½-ëPêehÞºhÞ#N"‡ƒ èÖoÛÌ”À{° ©|뉻¨_¶¿’äIMRZLƒåüZaFmØ-AjX§/ؤ3D Âq_á hú¦µ+Óë¬å[Ô«*$B€W˜ËjššáÅäb3Ú Òl<ÕõvÞão¦Y´lÇ‹ˆÇ(3Ô,€ÔÐÈU^Û  Fplº‘zul"~VùRŽË`t¨‹«Æ¥tMi<0bÞߺž)÷9aúgÁÂ4 ¢ ÇŸ»@n)JêH½ïlæð—öišZ`YiMˆ±D%t°Z5ÞBv[KyÿæP²¬íöƱmæ,›Õ©"~V‹ºU¤žJ`0v.Ým°àq r &ß³ìÔ#ÜÚÖhq¼Á:¢ÙY:£þH²µ.Îy…Íçþ´Ÿ Æ04²'ZÛ"9¶FÊäRp)¡ +ûgØÙ²NÅ[„^wÇÒÍ ¶„>øg €ý'¨béâ4è¡NôP§¦¼Â$°¸7mÔ&vjëU0 Rr£‹Š–(l*Ò™·F¹â"™Wl= ÃÔØ/ yì⟠=àgñ¾j¨÷=­Ðk}ºRÕ²%¤YJË»îUÀR4RÛ*)0):Y¿M €ï/'õl]—÷Oƒ¶K6–W#´ÁbXÛæíã€ÌÑ©Fâææ9ÙïBý{¶—WÐPé|ü,ä³(õÝwßQ‘"E¨[·nB/l׊k®˜F]ˆàW`/°ú¼U|M{ŽHùÙ㨠½Ý–æE´äxö³ר Z¾m£r·§Z™•0]öìÙC³gϦ‡~Xèf½.§ðÏꟕ-^žéÞŒiuX|Ú¸3ö·Rh–WO»W ^}œ£003F±·ð¥+רG›F´hÌ`òäÝ.0 ’’ªŽ»þÿ0:Àƒ|`”… Òí·ß.;JvïÞî½÷^Ú¹s§lëŠg"¯»$LÙ4DÙíÕ¶õíޔʲ yéÊuñu”iæ®,o^W>Ôiö³ çÏC£_z˜¢¾|.h Ôy” HéÙ–F <2;dÈjР 4ˆêÔ©CŸþ9Ýàý@O.|\%&«øz(f)öOx_+ê|[ ñeA3ÔIi=We…â5¿ f$0¦6>‘êU-KÓ‡÷§qCž¢ÊeŠËVFŽÎw_-0Š•wîÝ»—zõêEmÛ¶¥Õ«W  º_ýU˜çµ×^£3gÎÈy”{]%ÔÓ!Œ[‘Xž»»ƒ­>Gà`³ñº0“?€†g -ç.\`¼Ø«-ýö zò®;DHÁÏ’<àt @QZ tûù矩^½zôî»ïÒ… „6ÇŽ£þýûSãÆiΜ9ò\<‚ ts•P&j c¶(pß¼ñ^¤LgÃûKÐùÂ)¹çd/QC ¸,H`ìÝûÅËPÔ¯R›†À,)¹cR+ÏŸ?Oo½õ–0ÊäÉ“’2‘!P&¤ð•+Whøðá"¿ýö[SzƒÙÜKg‡äs/À,z¶¢öÌ<‘]'…±|À4(Âè2ƒùob×¥YÑXô»O4˜ÒòžøYV-¿bÅ jÙ²%õîÝ›°_4üU< yð šmÞ¼™:wî,ûJoß¾=Iwì 4´ªÃ¨Ï@3* €é…ÑN&wõô×uŸÌ”À<£²kàƒY¿Iuk!€rHàŒnMg <~üxÍ{ï½G/^Ƭ ±j¹#GŽÐÓO?MM›6¥E‹IþÔHgt„¦Ýy[uz¡Ç²™6{À^Éh§·pómOŸ¿@5xCñÉô£ICûÑ­nI³–?tè=þøãÔ¼ysZ¶lY²íWÚtÁç·ß~£† ÒË/¿L§OŸ î,ä=P>J¦~÷´ ÅÈÁ®Á5>ïȃ¼¡œ|0‡Î(>$p·–õiû ï?ÛñOûY0:R+—/_N-Y÷éÓ‡À4J§Ôéè`«t^³f µiÓ†xàqîÝÝoí|1ù€V´@nêÝ¡‘¼xÅ,ñÏ_æZïIͱ¢Ìçü<:÷Ñ ½háWƒ©ÓíµYp@xx¦å!dÐnh£K—.ÑСC©nݺ4vìXSK¹Òà¸ÜõêUúè£äþo¾ùÆ<ïê~Õfð>4>Ù-€lth\ûÝ·€ªC ¿}0˜6"y§ŒšKÓ”aÏÑ„÷ž¡êåK%‘Àî¬qt¢•͘ƒÒ#ž$îXÎûdeÜ`3ÐÈ›7/žÁà0 rŒßiýXË(W®œ1nÜ8³jÌ4æóÍ“)0ó›Wø½”1cÅ6cð73Œ§GN6&/Ø ×¬yTfÞåQ£Öl3²6~ÄÈÛâIãÞWF›£©,û+<Ùß}ÝyäÏÌÈZÚà“6¬¥…ni¥Urt¿ÿþûèèhó™Öç›'“9@{¬|°;ö„1zú£ÿè鯀Ï5xÛ'¹ m …©î¤HÁZKÖäxƒ7:7ËUÌdžHáDs«4qâD£R¥J&£XA‘fQ÷¬`>õ›ýƒýõxaZO;Ú ¢c§Ï_ý¶ÜøiÞ:)ËzM®h2sùf£FÏWË6©K®yú\+½XËìg¬Y¤M —:VmLï7ÊSeæÌ™Óxýõ׳gÏJÝûÏlP2ȫڈïÕÛC~˜c:vÚ,+™Û‚î”W¦ZÍêž tJýL³æ¡vƒý$“ñÁ(Cz™#¥ûÁ0Vð²)jð›¥ÿÞ<™ÌHg‹ä=}îb2¹§s<{Þ`UNâœUº§x3_°jy)5FŒa*TȤ‘µ=)µ;=ç­åGFFcÇŽ5«› €Ml³œP8ð*ÀAÒ*ccc'žxÂ:QIËô0ƒ§÷ây È0Iù‘ÉÁü³Nµ3¥oäUZ=¥<Îç•Fs>ïüe[µô5jÔ0eÕÈž¶;­ùœ-¡5–,YbVf#êëIJNË{rŸÝóx`žÊ*/_¾lð»*£`Á‚&£X%dZ ­÷YŸ ¦ªJ`nO™Æ“|Èãi>«Ÿ³qãF£S§N&½¼ág¥•^ÎO¹J›àUWŷ׿®Õ`&«ž6mšQ½zõ$Œ’ÖŽöæ}ÎÒ¹uëÖLW•R#Õ=iý¶Ò+..ÎxþùçMßÌíO-ïŠÆV Ož<ÆÛo¿mðt,i6ú] \¥•ÁxŸß[%ð† ŒŽ;šÀ²vŽ«Nô÷5«tÆñ“O>iÄÄĘ}me~ó¤—¬ZþÚµkƧŸ~j+V, ÍüMOžgµ*V¬hL˜0Á¤èN@ó À¬LxôèQãÙgŸ5%0:Ã.ØóX@Œ?üЀi‹d‚ÉIé8pF³fÍ2j×®mËŸ~–+š¸ºælÜqÇOÓ2©âO À|hü0´ xÔ¨Q/#1Å*é\u–®Yë Óvúôé>ë¶­[·¼* ½Ô Œhâª.V ùxºV ÀgijIÁ>$1Oµ1~úé'£V­Z&£Ò!wÅ ž^s–Îx©ËKeD“¡ÍiM¸Ÿˆ–Ï‘#‡Ð L ZÞý¬^'¼ñÆÆñãÇ¥½é¡YZií¯û|2UŠ àʇMY§ÅÒ§eî T®É‰ ü‡¶¡ Ì4Rû Èô-Õæ´6 ÷#>|˜Ø,$6Aå7ƒKž'?‚ôŸ•^˜8Œž§N’Ö¨viÓ\W›ç—´~ýú$/ƒU‹A{YÍÄûî»ÏàÁBCoHbUÆõë× ždk.\ØÔüÖçr¯šçí~l­wÙ²eüÑä9Õ^óDˆ@“ø7Óˆìü‚„NP!B`^ÉE–ìY²Ð–½Ghôô¥4{õ‰¨‚À0Ãp®”3„9Ûƒ‰L­Zµ¢•+WÂa—.]Ú ²Âr!n®à^Ôå׬YS“af"/á®1%8Ž«¢$œÛe¤#'ÎPÿ‘?Ñ/|DK7ESî¼¹$·«ûÕµœY%”Ùô%[hô/Kxÿ­ãòlЂ1&o”UÞä¾ÑäEÝXÄËDˆ……„ÂF[¨fšäîwwŽ*Á‚P~Ö¬Yé…^ -[¶P¿~ý„N8¯ò¸*KhÎuA^ÔwjÔZº£ïPzç»ßycÅ›²Ó«ûƒñšWH‡r§bÖ¿Ûý“©‹iíÎCrM˜†Ï#Ÿ«„Nã óx¥³t*¢ôò=9ïI§ZŸ¡@‰2y>9’x† ñ(¡0¡bDÔÑUÓ£mˆ…ࣣ&þI-ŸJ?ÌX*;fæÉÁõsSuUŽº†ò @;rò}7kÿsÅIpD[âŒxž»¤k4bS‘x(-^¼X‰£ÍhŸ'‚C=t@™¸Ÿ®]»Òºu눗ÍPÑ¢E=v¨:è!å1ÍÖnßO]~L¿÷Å;-aü ¤nržPK^˜"˜lš+"‡#»B“n¢/~[N{œ4C(ƒiܱ :¦áe"4lØ0âµdw^u¼Ê£žíüm+ò"ü$0â±gË–Íc°Šf&@ˆ1hä?–n¢Ö}? 7¾š.qö ²ÖRRÚ¹î~ƒ A3l ˜7ŸØ²ï}6} Í^µCb.* ÀÐ@+€´¨xðC,€±cÇRdd¤Ç @Žö:´üï¿ÿN3fÌ ^6#åâš'`µjùØã§‰ÍfêüâG´lÓnÙ‡mðˆ«[ëŽ~v½î3€©‹t潤 Å¡of¬¤‰QèÇLÓ„î˜e©ЪU«F¼L„þüóO‰< FJ®Ã™gBHìzž‰A<#Ãcfƒ0%0KZvĉC¬ÑÃo¡½‡ãD#¤7$0Ú,<7jc4š¶˜ÖìpX ™Êº¤”¬Bù}ôQ ‰=xð`âhP)  $ЙçAÒ'Ÿ|"Z›ix*Ðp?úÏuhùkô kùVO@cg.K“–G™Á˜|0„Á³³t†¶!:–>¶Dö“º’¸)€Ê犈΀éСƒæË/¿¤%J$ Ï£T­Z•„sþüù.™Ü³Eó˜0q¼iúKŸN¢ŽýGRÔÚí¼wqŠ` øBƒ^Hbpdä)‹6Ñç¿. tÀG˜Xr¥üOiwÐ_LÓ|@σzöì™0ÈPBXáø™gž-?`À€ÔkyÖžŽ@¢è·%¨kù7YËc'ôhù”[iß+~˜j¾˜„Ìô9X›AÚÏ]»“F±†Ý‘„iø:€á*Y¥3˜WH 3 8Ðd0 Ïu4Šg½'a(<ËUó¢¾À<•¾˜¶€Z<õ>q0UÖ¦)/ƒ àS@pUVz®¡|åŸÅÄ àçùëédü…TùgV €§ZIdc«À½ ¡ ´^ü«¯¾¢’%K&Z®Ú.3µ<Ó ZþžW>¥G†|Cû— BÕÏrE—€lÀ¦C:Ç'\¦ l2®Û+1˱ ò@ ºJ¤36Üûøã%¼6/æi­y"##%’ÌòÃÅ?¥mÁ HsVþEþ8“&†rshlìáÀÍ.Jñî%0/ê…m°É]tìqjV³<µ¬Sɱq;.pW‚×4 åÁdFœ~Äœ‡†ç`:²£ н Èß]‚  ÍŽžŒ§'Ì¡ ®âoˆ–g‘éóÙ]=ìxÝ=õ|Xk‘ÎìŸeáÏ£§hÌï+dWɶ «PAÞœ ZD9ø)UEIg0†Ý±XQ%€@T`Tç¿¡3ÿeà€I2eÊ@Ûö¦aãfÑœU[(sÆL,ž¤PFQšþ´ÅŸkwñë¿©Mƒ*²‰;¤è±ä h’:0ñAÂ3ðqG/äEÿáaJË÷ûúlJý}ê,ƒòòë€/œS@ÂK‡ò7F“ éÖðpþŽCqÔ¢vjÎŒªq#§K¦C)2kJ­>Ÿ ù³–ËFð³ì&@Ê•ƒ-Þ˜oÒ‚ â×vhT•ÊóVAHžZ ?hÐá4tN”-÷„‰@µb ÿqmÞ¨åy4ÕßZõ²c 8ÀQ y‘0ÚxƒµÎ¬ÕÛi3ïÜŽµYJ·ð•ÔIg)ÌÍ?y&?ŒÂÓ¼hp}:iÅÄ ) Ma×dZY-€?Nóže¥…f…˜É‘ÜYJ0!¯;­…2µ< ´­{¡ågÒÜÕÉf0Ÿ­åÑ;%ÛLE$/wü³S¼OO¹¢u<êˆMÉ#‹lžHgU^rß© 3ˆM%6q0"FY·ã€h…Bùr³þÇÖàRí €9_YëvÅЮ˜8Ñþ-jWtXÈÌÌfRe&÷mõ³NðçŸLú“ÆÏ^!#ƒvÔòɵ!çl0’’g‹o–•ý³=‡OˆÖ°jj[¿ªì“Œ|î¤3ò8'h$ågí:x”0fïl"*ÿI`×{8;—i‡ßI-€dŠ,€¶ ªò>\l˜þYêvâ„0CRZ~ì Öò“çQlhù@÷-¦ˆ"Ò™DÀ?c ¼rÛAÚ~0ŽGÎ*ÊGpjˆùÇeRZà:ËšLò3 6½ƒ)ˆ2¼ñ¢Øe%üp턦‚púü%úyþ:ZÏ# a/(5ðT0)­…›æ­ÙF<)—Öï<tZÞdOñ¶˜ªµU:c·ú?Vl•¡êv,kU(©²¥ø bÈåÀ¬ùdÂ\:ð÷IÊËÀÊÏ£•?Ë!©S,$È.h@YÙ?Ãô´ƒGOSX<â˜_ŠûAkAËÃ|ž¹b³Œæ³–wßbïç €©fƒi2%Jç<öǹk©ZÙbtWóZ2C¶¥³&sHt¢»ÑkŸO¥5Û÷ñ4¤l2½ ÃÔvÄPíNë·òÏ`@¸¬Ú~¶8&ƒ x‡–’æÇ}ô>~}Å/Ö±i9„Œ÷PÐòi¥gZîóëLŽ´TÐùè‘Î<|!›ØÏØ÷÷)ŒU$š‹IïcÁdšÌK#­ßNE ä‘éZ2½)iÖý¥,€\9²ÊìÿÅ›öÊhŸ³0.Ð+'hõË"Tþ¼9et×)u:€©æ9¤³!þYæÄ÷1êZrß9²e¥œ9ËHpo8&±ø%:6"w—2ŒfbÓ:”µ¼;:¤÷zÐL5ÒÙ¸ ŸóKhUF8}C¶(æ®ÝäSYäŽ4_z€yÜRQS Ð Ñõ#Ç`áÓ׺¥ €Xˆ®>Ð Ÿ¾Ö- 4À@týÈð¡€Xøôµni( ¢ëG†4À§¯uK@ °]?2|( >}­[ x`˜$ª‚`éŒ{Z8òiŠéÙ=É‚ŠX^Øõ7…±>áU.Sœ=܉ìx»Ü¢V»ºš12îkU—V+ÃbDÓîØb2!žF¨­"†`Á"΄KW…z´iD¯õé"´@%|\Ñ-X®y`ªÑ⨷kXUÀµ~7=,àÊΫiAÄ`_Uì?mÐY–ÀØÌƒ~þþvŽXìÒ>G´\E“”¾¡ý„,µ#‹¤¾ÝšÒfÞ4jÃn:Æ»¹ ž†2£R*#ÎC¸"°é•k×9lÁ5º­fEܧ+µnX]ªUÓÐh¡.4Ì'S~€†³½ÚÖ7¥ó>Žp¤¢£tN"™kz¶mL¯²®Tº˜É(D† ÿß,” ÉüȘµ…[ÉÀò¿ö‹pƒÎäÈžEò£züçÏ%P¹’EhÀƒ©O—ækQx€ÛŸœ ©‚î”O¦¨ Iì >Qc¦?wwaŽÑK Y:çðˆ ·`š³nR«’h­Võ«Is•N£(é-õAˆ5€-jC´÷Á~‰ÉO  Àá{g s¼ƒNnÈø`'z±W‰è¢Yã. CðŸOziÀœÊAtÞ[Ë• %[ör Ñt‰÷8F@$»2 @ƒáãøsd¤kàC¨÷M…+s=ÂÄ¡î6X0-]Ã`ÑmبIóÖïâ½¶@ûgJË_¸|U„g·–uŬ^¾”ô3„èáêÉçS´Jgh®N«ËVEó×GÓ_ûþfÆãøêÙ;©ØhÊÏÂHWÞ\2€ñÂ1¹ažJ`lǺ¹‚Ú:HÑ'¹ohE‹ò% Q¿»šË.* 6²ÀÃÚvôÏï³nR<ƒ«aõr2€Ñ¡I-iž7´|rt²ó9¿LAÌFþÆ)Âï<nßUcé¼nÇŸ?-‘há£Òl´J`ÄÈ¿ûŽÂ(ÕÊ9¢{*ÑFIm¡E‡¢'Ÿ|R´®áY + %ýV‚É´ ·[¡]±•-Þ–ÛØÂJ¤ºœæ½·KsˆîwŸ¾‡ïÞRümÕ—žhù¤­þ_~Hfã(é\é–"T±TaZ»3†nÚC§x{T ëC‚«Îñ©±™ùÕë×Y_£F5Ê‹ŸÕ®ñ­òøÔH`¥¡®ýû÷Ó;ï¼C&Lr~øáÂî›Ø® y2&9éôO]ˆ``·™z•K,€-<êZ:Fh±žÓÍ>ü)#Ü£çxŸ²œ1ùùžíd£XÁ¼òTOµ¼«Т0Õb+Ó@³ÝV£,ÕäXó‹d«v”(´~òÏþ“À¨LñBôþ3=èÑ®-R-X`^¸pF%[Û&$$€p~Æ Ô±cGêÑ£‡›´#a7N¥íœ¿M €5kaÞë¡v dwËùüþl?ïŠwgþ°ÐwxŸu‘5(¢$wº½½þh7ªÅû“!‰0 ?˹¬¿ 0UÓ©gÑ›“5W—Ûo¥úUÒyÛþ£Â˜x¯)ímél•ÀØ‘ä…Ú‹.’?TÏS ? õS~´´Ô¾}û¤œø"eNŸ>æÌ™#{#¿òÊ+T @)Cí4©èãü-€Å?sXExŸëC´pã:Ƀ1L€/,øY×x*\|ÂUªS¥ ½öHêÒ¼®I/ôg8šƒÎý„ß¶˜ª˜)™Q‹³‰Ñ§ccŠŽ9.þYÌñ3,³°töΰ¾)Ù¼ùï?Ô¹imz_ת˜: P8Jó¬^½šÞ|óMZ²d‰4 çq•¬ƒ—/_¦áÇӔ)Sèÿû=öØc©öÏ`6‚v«—¥[Ë—¤%›÷òF¼nÈ+Þüý4oÿT²p~zã±nôÔÝ­dó?ñÿØ4 ‡‘AÕž|Û `¨°³V5²¿Ä-B«wÓñ,¿S¢´ž'tÎóßHתWµ,¿(î*C¾´úY111ôÞ{ïѸqãLMðAc¥”::k·ØØXzâ‰'hìØ±¢ùZ·n-·©MÜ•9\YŠ`rX›Ô l`ÚÕÖó-èê´9gÐòddIÌðóžfP âW%‹8v5µ<:O§$°ÀTíCi ±ÝNmöϱ¶fG ]æ¥ ØÏYåS÷¹úVÒõ $03Ç[Ov§'»ßÁÓºÛû€ÿ<1mœ5ÐèÑ£iäÈ‘oƪ±\ÕIí€é ئMzðÁiÈ!T±bE¹å)ó3¥òL €ý³¢¼‹Ì#Qtl‚v(îŒL_°¤T€ÓyÔ Âè ¿«¼vý&µm\ƒý¬®T¿Z¹Ä:9¦ƒ)º:Ý®2l 0Õ;Véœ;GvêÞ¬ûg`š]´+ö8©õg*Jß(ç"oÉ“'gõ½§µ¼Ó*^(¿d÷T VÿhÚ´iôöÛoStt´”£ü,OÁe­«252Oœ8‘fΜI  RÞ¼yÓäŸU-SŒ*ßR”ÖðΔض(ŽßŸy²À…vœb®n•Hz¹wgº§U“^ §'ÂÈÚÆ°<æÎ šÄ»Á`0ë»ãà1ãÝqs ö7ä›wæ5uÀ3ÝåpЧ“ŒÖ}‡›wR—Œ›|ÍRœyÞù€AeܸqÃ<½nÝ:£}ûö°·äÃ~–Á iþVçÓóÍ`5Ë+W®œ1~üxóùl6ÌüæoWVzñÌ ã—¥[Œa?Ï7X0%{ÚŠtüÌy£æýƒ ބϸt媜õäh,õ¿d)©t ­WÁñ —¥ ÿ^¿'v¤˜c§Ìvò°²y¿y2…0³JGŽ1úöík(æÇ7kéTr÷´¯ºÖ²eKcùòåª:zEód V ±V2”àI!»€êèɳæeÐL§ÔS ná ÊÄàIõ`cS^`»k03®dÉvíÚ5úâ‹/èÃ?¤Ó§OËyeº+Ç×Qe²¡¼>}úÐ[o½EeË–•â=ñÏ=ÝÔ”Ù-7»ùóùñ|RO š+Òÿ¹ë‘#`74B>€ Búý÷ßÅÏÚ¶m›üư»«‘AÉ䣨ê†:æË— D/¼ðåÊ•KÎã±£»„û=Œ§ùÜ=/¬¯3ub ÀÔ²úY›7o6:wî üÊæ L6õ;ߨ‹z~åʕɓ'›}“mÑÉJÌÛ¤³úYqqqFÿþý,Y²ÃÇÂG1´]¾v«Ö¶m[cÍš5&i ,4ÐLrì ¬†‘8.0ägŸ}f+VÌ“USØXÎõøU=qüÔSO‡6JµÏ<¡üJ°˜¢ôìÙ³zõê™ÀòŰ»30¼ý[ å*TÈ1b„qåÊÕDý ý 3TªÓZîÁ¬ fDy¡‹̤æ Bª µÉ ÖA˜5jÐK/½D={ö¤ìÙ³{4°a“f„L5Ü9…LSÿkˆ¿SJ.œW×þË\G²ÈvìØA˜±ÏšL~{Û¤Aö/,ƾŠtÓàÁƒéÀôÐCÉ´ C‹y2„m·~F,€ˆý.ª_¿>Í›7O–Ã` ®c»ìFçTׇ;$l“u`Ñ¢EF“&M‚Ò³ú_Å‹7ø¥¸ùÊ9z41p,öƒÖ‘D0â÷ßoDFFš@³2/K/ó¼Ž1jˆê’5kVãÅ_4Ž?nr“U€˜'õ_)–ƒÉ©yø.0aFaÙ ?xØž° R™”0!íPGÔ uFêÒ¥‹¬E«U˽ &¢òÃìPß°®ƒ_á³Jý;w7ÃÔZÐfÌÜæof¿3pÌg2 Œ?þøÃ¤*ê®ÍA“¶8Ð,ñÊ=#ÚAiùóçËr~«AÂyhäóWÂà‹ÒX… & Ðôëר4LÕlL[ªAR «¶uëV£{÷î¦?ÄÌî5ÿ e1Ëȧzõê‡&0)¤ý,“Aq 5X*…÷ªø<ÐHî˜|VÿL=NûYŠ¡ý­æ§þUf#/p¬ü1?=^?&@Ð áõcÃa2 <ºV·ÒгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,4ÀB¶kuÃì@ 0;ô‚®CÈR@,d»V7ÌгC/è:„,þ6˜<³‰GIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/114.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001711515232633614033153 0ustar runnerrunner‰PNG  IHDRrrÝ…}sRGB®ÎéDeXIfMM*‡i  r rp~’·IDATxí]|UE³!$ÔÒ{¤ ‚€(¡èGù *|OÁþPÅöé{€åÉ'*¨ˆ ¢¢JèU&Mz ¡…„B öÍNöpr¸IîMîMn.w¹§îÙ3;ÿ™Ù=»;“"ŠùS¡ç@@¡¯¿ÂB¤ß ’\h€W¯^¥"EŠÈþf´P©,Z´(¥¥¥ö4==nV@ ×®]#ü@›8q"Ý~ûíôüóÏÓéÓ§©X±b¦†ÞtM'K°×'O]¹rŤsÁ‚êŽ;î@oÛüU¬XQM˜0A]¾|Yò±Ö*ün–SäÕ‰5Ϥo×®]ª_¿~&x¬™ŠMªÂ^ƒÚ¢E 5oÞ<óÁד×iðܹsêÕW_U%J”À~<ìí€öéÓGíܹÓÄÏ×õ: a5ˆ8ž2eŠªV­š šUû¬@êc+ÈAAAê•W^QgÏž5Õe›|äÀk€´·ƒK—.UmÛ¶5䎌h,§½ð*Uª¨I“&™0}­ýô ­LÝ·oŸ0`€  nsÎÑ}˜[€¾wçwªE‹™:èKÚYà@êŽÈŋ՛o¾©BBB„ñV©ÈíÞÞ~>òÈ#êÀ¨~¿‰n!=(P ¡‰`$>'Ê–-kh5‹¹ÏÑs«†¾ûî»bn­¡â¨ t@€5…ùMÔ¸qc2d•*UJ>ø™™ÄL—{îÚà]ø±9•"ûöíK]»v•kšw½«@Êñ& Ü»w¯êß¿¿Ù¦å¥}dfJ9 R&-lݺµŠŠŠò¦j»…›Vm>Q ³ªÖ‘›%K–¨6mÚ˜€ºÚcÕ ZMtåÊ•éÝÐsÅûÓ³ºZH<¤AWÒ3—Y™faì ëž$Ž'Ož¬ªV­jjFƒåhoí(/^\ >\9sÆ”%ýŽt M—¯\ABFàgB}¼9¹HÔ×Ê »©G_ÿ\8/|Ðþ}æ¼úzþzu*.ÑäÏÕ«³4£q#66V1B  Vì ÂŒZÁîÝ»·Ú¾}»Y¾Ý —„‹—ÔËÏP_þºRòv‘7ß-ݬ6ìŽ6ŸÓšW½ãÀ­= ®(wˆg'ˆ£áϤû_øVlÞMÅøš5!ß¶ƒ'hÂO«hþú]t)õ2wpŒÎO‘ŒŽ:&áááôÑGѦM›èÁ”Îk‡9u…2ÑYaó ¡”¹ÉæÍ›Sdd$ýöÛoÔ¬Y3îà\•{¶ï?* /Ji ,4ÕQ’g™¡%ŠÓ…K)ôò?ióÞct›FT¿ZyDò0XÐB¼¯GÔ­[7âö“ÆG§Nm:t(½ñÆT©R%yŽÛXÑZ6×¢éE‹¡Ã'ÎÐßΧŸ—mÍ,_:T€HLJ–.®F]¿’A†P¬ûëýuä$ÝÛ¢Ýݬ.g ‘ šZ)W@‚ôkÌ H8´}ÿ1–ðHŠZ¿ƒ ÅáeJ xéœÇ™°Š±öáÙ£§âÅ”5¯W•î»ó6ªP6LŠàVÑxH/¼ðñ§ M:U€åá7ÉÍävR &ƒFÉÄ—Òä9ËÙ\&‰Fñ ÏnòÑ ÍCCXàÒ®¤ÓÜßwÒŸû3}¨YÝ*òò°á…ÂHrHhL(t:.‘ÆÏ\Hß.XKÉÜÆ• -ÉVÌ «RW¤Lç? .Îm?½…µ÷Øiº»i]Ñ€AR& Aº*¦”‡õä:Æ=€(f™‘~Xü}4c퉎¡ÒL_ùÒ! ¼Lr8¿ëÀH…–¢³ç/Ò7 7P£š·Š©^±¬TPæÖi 5£"JÐW¿­¤ ß/¦ã§ã¨ ·øÁŒå5H!Ü6q'–¢6즭þ–¶éNn£¤³Áyh²h 3ûiì´HZùçnŽât‹‹V"«z€:þ.aëQŒM+‰°¡ýlÃm;ÚøÒ¡%äQÐæŠ gõ>g¯; $ˆ‚Ù€ù|ŸÍèæ=G(´d 6£¡"áîÑJ4¤V*´d%\L¦YK6Ó¦½GéÜ~Ö©r‹dMèìè!;vú}Èí 4¦³l©Pa¼¶:o^÷"Ø\H‰âbÖì8D;ÇP§–õ©CÓ:N™ì¼Ò`}þ:¬W-Ç éø™8ýùlš·v»ôðÂË„‰Æ8ÛZŠtéPÚÏbÜ.¥Ã1çhÒ¯k©UÃêÔ«}ÖÚ .Ë ÚûÅÏËèc6õ±ç/°…‘ŽŒ»ÌN¼iA¸ýLáO˜_×l§ÍûŽQŸ»›RݪÜaË'ÍÌüqg§’ÏÁ Hþš­ûé»…ëXÂKr£$Ò®Avð˜[/A–(¤¿x`1Z»ã0Åð§ , úÐ;þ÷w‹èBR [‰0ÃìfÑ[v+q…IûÉ¿0þÜŠ>G슋bˆ™'Þ˜¹ÌÔÙÁÀ0î,€`ü "iéÇ瀣ï7t¶ŠqÏ×ÓV"«ºk¯ðËÏä4о¬¾ó“`¼Kj/èË/+a·õ4ä7Ni%Ôì}ðé}˜äŠ"?¹b›÷=”/@¢Wé(eqÙQV^ŽhttÍ£„ä¡p a,“'mohü¥ótksƒœ‡:¹ô(†ñ•í Ó_³0ê1 )ŠM¸H•o)CÁ'ìŒuç9ÞÏ_¸$ÂVµb9)^Ó‡“òeBdZC’-p9ÕÝí@bà•ƒ ‘£žx€LÉ3!L‹±:_¡á<…4ü‘žªCé¬)üAæzZúQ>fZð>ÐØ±åm´bòhêÑZ¬ÀݺG"ZÒ÷·¡Òü‘Ÿ”’&cHÞ ¨Û¾ZÁ LÎ^LN•ƒ¾ZÑkƒ FµŒi€‡<˜WØHeÂJÐÃZò„mMZ´qíãÙ0¹8ÇybÐÁ0óW)þB5®]•F>ÞƒéÚVh©}úûOêS$@ÛԮL+· ßy>³<%x@Iç•“Þ¸H0?õòe:Ïf²Ííuèu°[Û&R5=±‹JL€ˆ 0ª3 WkÞZކõî ³K6肋±‰Ì¬@1}îƒéx\bÝ«†?Ö—ž{¸+Ècå‚ññz0°Žº F™ãQ,¬èÑîvã]´i/íà%*L¼1å&ÏË#ºÉ0Cê·ƒ5*…Óÿ>ó0 é}0C`S¦èYŠ'N¯Œ“JëI`C²‹PËúÕ¨q­J´fû!Z½ý kw31ÛPÖdf˜« ¦ïOä‰e€9¨GõxOªUÅX} §½´•ˆì¹EeÊ”‘¥"ZàXWe¥b¹Rbj÷eXh^Çë qwœ«õ³æÏU æ€1˜^ƒ_p­þòMzºo„€!/G͈û÷ï§G}”5jDÏ<ó P\‡&€‘¼“²‚xŒëb†÷ ¶kÉܧ´Ÿ\ò:“ͰWD Û7­O‘ã_¦É¯!| ”†wCó‹`üøñ²ê½ÀhñâÅr],¯:@™Z{Ö¨H/>|¯´¡X„ö ‚SPÉ% ÁH0(9å2aKÏÍiÉç£hÜóýyI/ïƒP17ÆäoBBaŸ]ÅiöìÙÄÎ:²Þ+ݰ:.555Äñ7@†ÖAºË— ¡]î gìÈÓA·È*;|@@²Khñü¹„ „žèÔ7þI ?}•:4o cÅ<”qõš±¢@Í;—°T„})‰jiÛ¶mtÿý÷;ûО={LCýDðPó¢}“Úô2 \ç;IÉi¼¯;+pÙÕÃå{,eÙ&½°xöÒ *è®'TèÝÿT†¼«æ¯Ýf>g¬½–i1nN›6MÕªU ØÊ%ÿÏbæ æÌ™c)++ÐyÁ26‰'•Õ˜ÿ,R/MøIý÷§?«ƒ' çU¬QEº”œªš­Û>®ªwQ½÷å¯ kV‘¤,YËš9¦zõêeÒÇBècpMhxI¿öÚk*>ÞX— Ú¸IrXÙc› ët_þlŽzæãÔ˶y,u03{àæ"Û¤œ>oªÐe˜šôÓ2Åsò *‚*g]ò¿råJÕ¡C‡¤Åž¥6“OF÷îÝÕŸþiÒ¢ ¨WSÒ.+îݪW>ÿEí9zJ®j y•ªßw„ôÖ$uà¸q dÆþúJrŽ¢^zé%Å‹¸„F+pV!xú¼Fꫯ¾’ºêò¸ 5VÈ[ÀÚ}JýÏô(õÍÂ?ä½Va” Úä$‰´ïèIk’¡¨¥7:¤ dVŒ“43í­L„Fp¨uòäÉëïÑÒoaV§ŸKL’<𾤔Tµi×aËs†Ë˜­i„p|öÙgŠ—Lš4YÁrDŸ]àÚµk§–/_n¾'“ÀeÐ÷ƒè“çÌ<ùq#v"  iÌ üÂ… ¾†ì' BåsbiÖüµòÉ'Ÿ8 µ’“„ã>~v+aé¢Í¨Ž¬Îíuzì±ÇLgYðH KNôÙùé®s§c4‘Z @ÄÌ™3U½zõœ–ð¬…ëvé·‡ZÑïÅžÿnHºÍÒù᯿þRì ™‰>¼';:²» ¢Ÿ S¼ê]%&^÷_ÑDYiÐ×<¹wHM„&pÆ *""Âdˆ«ž³ìÒÏ> 1vôû5=ö½¾§Få”óOv´duÏjAêÔ©£fÍš%VÊNO~»¤6§|ð ÜÖrj³bFN×Á,”¯ó}ýõפ6cv&iúvìØ¡`žñhÓ]Ž»ö8+}è'%%ejvì4zêÜ% !íøÅÄĨ1cƨòåË ³ìäFY%Nªü±.>Žš†¬‚ûÉÉÉý M‹;-Ê„€hQÿÁƒK€&hÈïäv⢣£¥šY¨X^µÏë2õb5 ΰ úÅ_äÊYV×ɾh K_ïØ±£Z½zµ&ËÜç7˜.©5ÂúݸvíZuï½÷š•Ëô۵ߕ[¶ÕàŽîæœì’îYͯ+β G{­¸W»vm5}út“¼O›öœh4rãÓ@òôùZ£{ot<¬ ›1c†ª[·® ¨µâŽ£¯Yóe=Ò“Ù×?‰Gr¬ ì›i^Ò€Z±éÐq²¾¤Ï³ÚÃBè|¡¡¡ˆ‡å]l1§|¦p#>ã;W2åÃ&G u—~㞣jÂO+ÕßgÏ›dé{R‘Œv]ñwÞyG¡kÆ€ÚTÚeíí‡~¨RRR¤|Hµ–p+ƒÖï< "†Qì¬*ùô½K)ijüËÕï;›¾ÿ†ÀÝøM9þ|Õ²eKÀ¬,ˆÝJ "þ›õ7´X‰³ñ‰ê™±ÓÔsïcÐg¹g>è§Ü²ï˜úÑ÷jÔ¿©ŸWmS IÃA“–~«v(Å.|¬Íê<è4 ÌE‚Orêš³z;sXI»¢O á 9Šò<£«S§NÄ!âo@ªY³¦€Õ°aCúþûï‰#@æþÀ@# â=˜ᘳ|u6†Þšü3¥ð ¸Š#[¡Ã¾y`pp†ïÅæ}Ç铟Vˆ%<¥P&’UàX#‰5“6nÜH={öZ8<(9R@~ê©§ä™ë KV d»œ oM¢þ¯}F;CøMò0¦<“Ÿ›\­³àrZ,ˆNžK$³BX×rû.V /-ôcVÝXA`Ìû!D¢rptFâ°)T²$‚ @ á®ìÌìÍ»H°†¥wQkŠÕIUƒ‘“ p(h'7QÅë¶8!Öè34^G¹F<HyY~°˜/EÒòCrŽ:aEÄ'ß/¢isW‹[;\ø¸; ÎC¸_)W@‚PH?´C{ÁÉ“Û%jw{mŠà‰Ö0vPEB¨0 áÀĹ®íÂ\1Ã!]à&>+j»É¥³ _HžœT!pà?–]žçÕ 3ÅYÖ6Q§J¸ÐY‚ tòèŒI4ôƒF¬ˆÀþÛykiü¬…t$†—„0€ ‘Û`y¦ 7¹R­Û*‰|ÁÀ.g?Êí‡NȬ9@…™ÔfSÌbF;$ZÈùÁ „t™2g}6{1kx‚k€»¸»@–á,K_ü¶†îhPºµ¾Mb  .Q ö0ó@HbÁ•}=»´£i‘€\wѨù™Û}žÔ/Öí§,:æÊO+·Òn£îksÝVãVÉqoP?ÂÆ·È!]¸DŠ'ËÌ|î8€ñŸt–`x7ì>J< L9Ì Â­hË‘DøXÈ?MãØÕþו[ä:\íy.½@ÚA! ‹Íu®f‘ÁÕË"ýl&¹ýäoNš¹ŽZ±ô?Ô©…Á,p“Stœà*ÎqñèÈÉX¡OH`BAkäê­¼$ÓpeG~Ý9Ë/]yÛ5ÒúrܾÿÏšðÍWšÃ‡$s 6ZàðÙ`Oo†UƒåÊn§'»sh¤ý…ÚœY¯CòÑ™ð†¤ÎN „,?­„ýý®œç ®äÏ›;øÌß¼î)?^IîrHôUì–ܽ2ïO¡·éˆG×òþ6×KÉÏä4éé×xÀ;gß O¡·Ë+Îù0³«8z Á‰< ¨Œ/s' ³6ù™r’ù"©b¹0– W7\pfðÚxÒ=[ˆ^î™ø Ô¨vªrK9©h1ïש.!­/g\~ê4ü2@¦ûîjRÏ=w²'€4…QºPG?ãòËóÌÐÀIs‘ÿÚ—VMyƒj#`'0€á{ïÉîmi0ÿÂ9&+bà³ÇÓ&ΰì¡ÆðPëÞ®¹¸íaó ¡ÞÜøìà…`¾û0ŽÚ›£b*®â &!X.g@w%” $0€µmP÷4ò‰žT;ÃIï1‹"³|Œ×·`gÙFnt–Í®>3<ŸœD-֢מìE=ïn!ˆ1Mù•œÄ€&…çÊ<ç8¤Ç]2è @‰çÉÜ@7|óB<ÞS”ç'“SÓ¤-¼‡ƒ5À•ýî†"f°þˆ×ƒÜzZ Ôβ-T£%ì*ްÕè†;»Ô›<$X ^ $ó’U*”¥7ÿ«=ý`'hŽÝÊïAò´%°“ï4xL†!Ó£poX½"I8,Á0ç‡@ Ð&G£9ö—ÛÏÑb ;þÂjP£Ôƒþ£½dCû¨µ#.Àõë×Ë$°u¢„‚¡†³l+º“£/Ú°Gþ[ÜÄslàÀ $r=^fØCiÄÀî~ƃmN{Ù+–ç9¶‘Žh@eðXè¥ÝÓ¼{îv¦Ž¼õ² äq&Á4¤øDļ)J£÷ævðMBàpZ‡2"ÿcYiо}{â¿$ÿJBÊ᲌|° ü,ÿÐ z®oGØ­5•ãx³j…¯;«5x'èÂr“žµéÚ¦ E}:’ÆL@„•à⤳ãL}=‘Ç%´æ"<ü~÷4'ć¹Å\*Èæ6+85ƒ.r°¤þÝÚШ' úÕùK0‚"@2@˜ËäDï¿ÿ>ñh%^ 'í#;øÿmâEÍôÞ{;ÊÃ*€.„iEÛÞ¤NeZµí !tõ%v¡G¨m]20׈f!l¦‰Ú5«ÏZøujÕHîëvÏh3 Pð¿>ÆŽ+ÿë’îìà|áÂ…Äÿ M‚MŒ=š°° ÉÚ~¢ç‹ÿ+‚‹j…§ØR3¾?%³msžÿOÝabæ‡õë,SnÒl°ÚÈóÃë¾ÄŒ7X°ÖsÙ–}êÝoª¸Dß޲HÛöU ûPÓ"WózSf 'Üc)—ç­+ÄuRe`ÑÓ¼±°nëW‘LcÁ³ïÃõƒŸUãf,:qZ ”êóòx5ø_SÔß§ãpK’¦_Ÿ{ËfÇ# ÌÐ)!)Yñÿž’SÄáÑ—cl4ƒ¬æÖIÕº¸Øî,Ë#B"( CÓˆwƒk½c§®»c!´¥JÖ¬^qì1 uí4³ô¹}¯dÓiÞâ)Š×•æÉI•Û_s5;´´OŸ> ~“:iÑ‚¥¯Û÷ÐМòØŸ)ˆs‰J9’dè¥A0¼ê\ñºRÓDZÍ¥6›®ì¹'kº*ðÂcűtG·º×ittñ†'½ãB¾™]U&GR¼ê\yÒ1Õ* Žð~»@eG¯·Þ+P aNÁÄüÑÔ@¸r[™îŠö唿Z©ó!Öh€%(ì©@ó$Ú«U«V)xÿj&£ÃÆëó¼î­ÂQ³fM‰Ê_ÐFð±ÀÖ4mÚ4Fkà¬èk®ì­m$‘!Ò"~øZò µ™ƒÏŸ?¯øƒ^…„„ V0œÑÞk}衇ÔîÝ»Müt¯Õ¼PȼHÍG+ƒ÷îÝ«øŸ}fÒΜÌ-î[¿#[·n­¢¢¢tñ¦“ªyÁG¼HðU·›šÇ;UñÀ¸ hVí§Õ #¤ËĉÍÐb¾Ò©Ñ<±ï½HM$z“ Ç<Öê0ÔŠÕô¢W:|øðLߊº ]®/î½HÍp+ŽB­èv“hOoéÇÄŒš'>~P(€ÔXÛOë8l³fÍTdd¤Î&Zì+Ÿf¥r8(‚û,Ñ…&\6³¦Ÿå¦M›¨iÓ¦,S^¨›ÚBSwZè€Ôg“C ÀåÎŽ¾}Óí -)0ù³C_º)÷…È›5•¾ùLð…K~ }E®ƒH?>©†_#ý@ú|¤~ôé#ð‘jø5Ò¤pÀGªá×H?>©†_#ý@ú|¤~ôé#ð‘jø5Ò¤pÀGªñÿKÁ+äÑÆe+IEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/55.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000653215232633614033154 0ustar runnerrunner‰PNG  IHDR77¨ÛÒFsRGB®ÎéDeXIfMM*‡i  7 7I…ÌW ÄIDAThíZ T•UÞò”—€("©˜9A2Z(¢É"‘•£¹–©Îr,séZ“+Ëfœe¶&ÍrrÌi\Y>zŒ6ڀA"ÄAD@@ðò3û;×søáÞ‹ hÓ¬Îâ¿çñï³ÏþöÞçܽϥ‡àBw ´´´;;;ùÜ%nʲGwƒƒ®ÊÞÞ^/~ýúu °Gzìn4ìºs€ËËË£Õ«WSQQ‘ìcïïjån·°Ð‚­%ÙTWW‹W_}UxzzÂÝEŸ>}D\\œ¨¯¯—ïA‹çnºÝE(ðÙ±c‡ ’ ÌÁÁA·CBBÄ®]»ôrwàmSÀRRRÄ„ 4€b7”}ÔF“'O'Ož” Õ|¸›]ÇS577K÷zýõ×5('''Á§£îÃzêÁ8Þ«þ† x~‹ÅWvºé£Óà ˆµRPpA,_¾\xyyIÁa©öù€Ñ–ôõõ«V­EEÅì°m»äMÁa±ææÖàBé)T]C£¨®kÐæääˆØØXmR¬ÐóçÏùùçõœÒËUšÇ•«5zü:¯i]•š¤S ›àÀÜ*#§@Äün¥xqý‡’qaY…XþÞ"éäYq­±Q/vøða1vìX À¢££Å±cÇ4MM]½xóÃ2ã%qþb¹ß¶ï„ØŸ$J¯\Õt¶¼EܤáÀ‹[ÖÙsdaooG¼­ÛþoÚ‘xœ.–^¦Q!’ÞßÕÔ_£GÒ)íL!Å„ £îíOQQQ”œümÙòmݺ•,ø =õÔ,½Æ¿Ž¦QÜÖ/(5óõëíIŽæ/{»tòl^ª¤1Á÷Ò£ÝOn=ä<Æ ¿?5“N6,À!°¦æë´y÷ZÿÑ>bW¤>^îäîá KßX]¥@›÷§ÐÀ4ñá¡äß×›æÍ›'%Gzv>­ú`/%Ë€úzyÓü˜ÐÕ™Á0û©ÙhôÃÃ(4\Yó—+«éÍéý½IÄû”¼Ü]‰ø[¢©©…o(J1ä­Àïˆ×t&S]}|(NdÐäˆ`ºÏ¿/“uÍ‚:ü‚=xÓËu–nø„ROŸ#_ï^¬ejnJ £jÄ0à°÷ø÷”W|™-kO‡R3)nËç’[.Ïç…šjµÆ{Ìȳ…e´çØw,HÍòYdePƒ3¾ssq&7f PÊšÆ÷¶Ú ‚{)EÙñ^òðp#®,,o‹Ʊ.ø9;9jÏèˆÞÚ;«àÀOû"Ó—ÖÅ;;CÛH+ÝË0kµçðØÛª ¯¢ÆP+¯0Žu¶ÝʽƒR>I›ÉÓ½'Màã mi^Üø€¥ ü•«µäää@/ΙLÞ첂Éã?ðž>T]ÛÀÀ…¤3ν•v›ÓÒÈÚÅÙXYe¢À~ôÂÓ“(vRßæ)8hû @¾É¦Sy¥]œ-4ààWiª“ïfÅ„K`÷ö×K ô¥…¿OÿÉ, #ßæÐS-Ï9wÙ+4CnX‡½TÁÚíß׋–üj ý~F4õõö”ó²²²).n57ŽžyæàëM¿þE8}®„öó÷Ó…² ¹_Õþ¥`y¯(œ€—ç>N†K^ѦMïg ôÊ+¤!Cî•_!éO_¦çRJæyöŠ&éF¡;Ýæ½#‹Šåg…ÍY&f¾ü¶ÈÌ+T¯Eyùe±téRáêꊳA>‘‘‘âèÑ£š¦áZ£ Ç^zg·HÍ:/Çßûü¨8i¡ø`O’h4„i‰ûö‰Ñ£Gk^HnW¬X!®šLšâØ¿}–$Ö}|HŽñ!×¥‚ ݦ°–Eú³`xøróæÍ" @ ‚ü A±9wî\‘›—§ùT˜jEyUµìç–‰U9}:SÌœ9SÏc¾7tèP™ô*zÔì ÁtW‹8Å ¾¡A>>$.{RS¿Ñ‚TU׈µÛ¾>Q Äg‡Så8’ÙÅ>G¾=#ê®iÚ¯¿þZLœ8Qó‚åׯÿ+Ó´f÷ÉéÙ"rþkâ‘gWÈ̼«Wßs}\8XÍ.(ãï¬J5,€¢F‘§;-Y²„ÏÙôÆk)""‚f̘Á†ø¯…>=”Jk8 ÍÌ/æ>ó¸‘h"BXµ;ù¥f_ ÎÑBý)<<œöïßOÛ¶m£S§2hñâÉϯŸä—WXJk·'0ÏTÅ!ÚccBe>Mt¥X€Ãd6žˆp)ùT.:w‘¢FQ'Ž ·ÞzK¯‘ò].­|<ñ½Œàûzõâè¢FÞl*²g!})½b¢- )Ì{LØýàçCsæÌa^xˆL5u´i×aÚøéA*¯4I…¶´¸È4ItñÃ*8ð@¤? %Ä'g°æ hÚ#Ãi°_oªåÄóµÍ»9 MæÄ³™¼{¹û§I×áêr®ú@Y¬ˆxõt~ åpž6îÁû$HįGÒ²èå·?¡ìóÅÔËÍÕ Œù £¸ÕÒaà ¦ÊžC¨^n=)¿ä §ÿÅ敱þX ìÉÙ5²t¥[Â4h\9þDˆ¯@xåÈ ÿy …2ÎP?/yws³ÙÖÆñ›‚±QóêJ1£Gô(]Õ®R‚1©…Û¢oÍòr‘[ø° ‡ ïX°ƒæ.g æ“P0•,¹µº>hà! 4úª€—5YÔûŽj«àšš[¨¡±É,”¶"­Á­ÙU>dae  ßã¯â.åhP€WcS“äÓÕ6à ž'£Fа€~ò^ÂÂ;*J»Hk\z:Òº?j£kΞ=[äææJ6j¾‘gw¶o QšGIæˆ#4Hc:fÌy':ã<óH÷Þ68%¨ºãÀõÝúõë…ŸŸŸ9hÐ ñî»ïj+ƒînƒ\ÝúïQ,´üo!ÞSTRRBlIâ»êÝ»7”ÈñcÛ›Ý,Ý ‚Za}'Á´çÝíàÔ©@!šù!Ê÷C€i¿f›¬ ýË{ÿ'p?V þd¹Ÿ,÷?¨ÿk·ü/±œ·¬ 0IEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/172.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000002762315232633614033160 0ustar runnerrunner‰PNG  IHDR¬¬æ1GØsRGB®ÎéDeXIfMM*‡i  ¬ ¬÷œÙ.ýIDATxí]€EÖ~„]‚DÉaÉHDTD<ÔÓC=Åp¹Ãpfá~T 'Š( "ž" HÎ9g—œsX’XÿûÞlµÍÎl˜žÙ™¥ f§¦»ººÞ{_½úººBżài J43JÊéÓÓ€hÀ¬„¨Ò€ب2—WX°¢J`Ó0ןþIüñyϦi(*L§sx½©kXsåÊe\¸p!Åos‹„Mž‡MEÕfŽ9œ[¶l¡ÁƒÓÉ“'å7€Œó^È x€µô @«ž:uŠÞ~ûmjذ!=öØcT¿~}úꫯ Z¤÷B˜5Jp¹žbžjÔ0jÔ(U­Z5¼P‘OîܹM¼U«VjöìÙ&íùóç®÷Bx4rÙ €ÓaþüùªM›6œ*Sù3gNŞלëÞ½»JLLÔ—¦¼9èE\×Àe XÛ£nß¾]=úè£  „W0u\{YýsÄEŠQLó[1 Ó…B§Ë°6¨NŸ>­úõë§Š+f<§íE5HSû¶ÓÅÇÇ«o¾ùÆX •Á£ F®F.À:yê˜1cT­Zµ2 T¼ð´6¿mÛ¶­Z°`1Ço*\‹d{À:yê’%KTûöí Pmžjƒ1#q›ß"Þ£GµcÇc$›~˜ƒ^$SÈÖ€µ²{÷nõä“O`ùã©«Ö¦ Å‹Wýû÷W 6É”¥¼‹DÙ°68Ξ=«Þÿ}U¢D ãUm`Ù€s+nÓ„Úµk«~øÁÀÍã·F™Šd+À:yêØ±cÕµ×^k€êFóŸ^P;ùí­·Þª–.]jŒdw§™ƒ^$M dÀÚÝI+W®T;v4@…GÕ]Qéœ[élê£zöì©öìÙc c—Ûô"~5-«»:¤ž{î9•'O« ·˜Ù|lR²dI5pà@Óg«Ëï×JÞ £¨,< >räHg€j$³ sû:'M¨T©’Z¼x±”ßó´“#Q?ø…AÀ¸"ªW¯Ý{ï½k¥°‡•s‘òåá‡.)ÎUW]E÷ß?]sÍ5ò[Ë)eØr„sž\´h‘ºùæ›  çƒÙÜ׎ƒšh/ûðëmÛ¶E¡v³¾ÈQO ´ =ß}÷ªQ£†Œ ¤PÇàÆoTóæÍÓE–75êHW$ÛVK .¨ù`RR’êÓ§*Z´¨ píûT­ZU1BQFvy@5êÈP$"+Þ2£ž.ðÖ¿`¿åÚºu«z衇L×À„f:y£b ïB… ©7ÞxC8qBŠ ¹ter–Û ™yfÇߨ?ÒT§!ü °;èçΫZ·nm€ê&¿µy*ÀÚµkWÅÓkLQí d&GþøãâD”9=!½éÒ“W4¥‰À^¸ð§’w2éŒú÷ ÑjÚâµ¢KÛ+iCÍ]ý»šºt£Ñ5Žësæ`rÇmÀ|ýõתJ•*¸vóQ¯ëä©-Z´P3fÌ0E4b ri|=qJýkà(5{ù¹65™g,ߤf­ØdòFEõ'³I”Í"YÞïÃú$V<åÌ™CæK}7eµîчÞ<†NŸ=Ïøñ=zKqÀŒÃ‰¤34jòúpÌLÚ¸}Ÿ\Ëà!öOò¨îKåû‹ã JéîÂýÐįIéõ×_'n¶eR¡Nc_—Vy"?tUU¬X‘† F3gΤ–-[Jž &b/.e³óB}2çäsD_M˜C­}›Þýb,=ïëöJS.ã䎞H¢áÑ ÿͦ-»PN¾XdþÓNmß)ûų °0{UQx.îŸ\°z3uxvuý¿”¸û.r…€ØŸÊsçÊAqùbiÛÞÃ4dìújÒ"Úwä„ψ|@á è…Ù{QÁ‚é•W^àvéÒE€‡ã!Ò v>  —_~™–-[FLæ#•“eÐ ó¬eè–žý¨GŸÏi×#T´0Ë û ¹s礸ü±´…õ3èÇ94jÊ:tì”ÑSj2ûÉ*jçΊ’ûÀ`¹rå¤í{Qÿ¯ÆÓ¨‰óèܨÈqİbïz.`Ñ€Gn)O¾Üò½tãvZ¿m/]_»µª_•ò剑ë€ÔÚ3 ü¶‰†Nxô$)˜_Îý¯›™!ÊŒæi! þq6mÝsè"¿MEæÌÞ/® ©‡…®|Þ‰AÁ^féúDêÿ.XM1¹sÑ•ÌÙ`0x·Œ˜›óމÉE¿ï>(¬_­,µmOÅ¥éõñ['WÔÞ ,\¸0½õÖ[nûꫯҔ)Sˆ_§Ò?ÿùOâ—¾ÊÅéô5vÙ2Ï_µ‰Þa™§-YGycc¨¸È|Áu™¡ÏXþlܱŸÈR£êå¨M£xñâ(¼²Sf»ÜÑ`/r¶œ´›(þïë ü4<—yÚ9*\ ?³,~ºf£‡"À»8î³p=s½­ÌõêV¦p½Xÿ\ ïÈeãÅ4ˆgÃÒþýû ƒUàiA%R«-ó¶=…›3i¾4ÛàæŠ+SHeæòåƒÌ,áæ ;üËÎ6,q±#üvÿ‘ãôÅ„…T³ü6º¹I *[¢ˆ”!5™ÃR¸ n4`aŠ?Ù(j.î]¹i;õeÎ6~Î ÊÍÍkñ¤ &TMaFd‡4×û»–¶üÀ\/¾,s½êTôŠü’Uj\ÏÙ„67_²îwáæ“¬¡XîZòñTw¹yFäÔiaÐn˜Ѻ­{i¿phR½<ÝĽ(… äó+³Î#Ò¾ƒ,|Àºÿðq0â6n:}Öâ©î=P¹¡™‰_xœ¥N½> çÞAÇùE@1¦Ç8å™ ¹dýŒ»áÚxz‰enT£’_™1f3&/ÙHxš8 }D‹Ìnè8Ë a ÉÁ£'¨Bé+©Ï·P·Û[øü cÃ+5äÙµ*–"^sŠfó ä“§ÏÉúB'€ê (;¼ä‘ãÇ©JÙRôüßÚS—[¯XZÈŒÙMkV :•JÓ´¥¿ÑÜ5¿Ëú€„Öˆ€7ˆ’“YXxü;zü”Ìzæ¾vôÌý·ÈÜ/èãKmÏšš>Ác1p1©ð×Eëe’! ——½¾# ·¾9bгÌèÞûÁÔóÞ¶G9yi·´ef^ECn»®5¬^–&-\G+7ï–éye6pdÉœšÝ‚9vÀ‚§æb°ò …2׫CËúôB·;¨V%ߌNx[xÝ´À ¡ÁÿàG1oéJH}ÛFÔ˜çãO\¸ž6óÜ¥X^›^)«›L-ó‰Sg¤¼ojÂ`½ª•+%¶32çHû‘B(df„—,zu½¥©,Ñ4‘»uÏሑY ÁŸ°ÖÇSÏÓk£Åh·\W× ÆXŒí g³âšÿ|n«\sUæÏB^wjÊ’ ´Ÿ©F~n2³‚ë¡l˜m‹)5à©ÍêTáÊÙnlTE*Hf]Ëu‰ÌÖ¹êåJRµkJÐ<¦Ó–n¤ƒÇ“|ü–Ód·¡a¬ÍSË–,F¯=Ò‰î˜ #üµ÷K ¨0–ovjʉz-+T‡ày›Ö,Ï\ïjš¾ì7š³zKعÞE™SÅÒW1ÝiÏÜü®8Ɇ\ôôȬåJSf®´×ש$k𺹼P\"%qEAe•Vœ#„KÝ™‹B‰÷`ãµ®ÀIŸ¸» Íò2=Þù&+Ž! >ÎÁXðPXʲ]»v²®+/ÿ.‹Yà·p½€ ®wkóZôTçVT¿ê52a]a¸Ÿ…ugAý ñ7Gx– ™º£¥72; €ÊiËÌÛØoâA=ôíܹ3Ý2än±Ž7Ô¡ü¥¥<œæ)=¡–9(…eðâxX ½áiø–æu¥)¼¶Z9)8[N?< H±Â oqI¼© ÀÓÍÿ9îýàƒˆ76¦>úHÀ ãsôèQú÷¿ÿM 4 Q£F‰×XatÍ÷tñq1"ßçâË• žèîÖõe5š“Üç‹ ½²üÈÄÝM…%4ëV)Kß¾óúšåXm™YÛ2ó6õôî»ïRýúõé¿ÿýo²ž|2fœC³z pù8Îi~{]íŠôì=­é¦ÕDÏàz8OF‚îÉP1sxÀ³÷ÓäO^ vÍëHÏD ™!‹–ùûï¿§FQïÞ½‰÷ËMUfÈ·zõjºë®»è¶Ûnš”^™Q¡ðÒá™{n”ÅBP.P€6£2gD?¡H4`!4€xìT’p¥GîlE3™³=õ×vÒ*œÓâ©àªU«èÎ;ï¤:ÐòåËSÐ`(al Ka^wÝuôè£ÒŽ;ÄØ0á Ú«¸xcÔáú:Ôó/ ò ‚5 ×s^èø YÖ£'O 7ÿÇ=mDæwÝ(Ýh†§:¸¹.;ʇ²/Y²„Ú·oO;w¦µkך²C>;à:àãÇ—JÍ;ƒÓÞ½{ÍuiÉ\(./ÝÅžü¶Fù’Ò{qNtÉÀµoÉqVF†7er oŒ¡ªÞùœŠmÚUÝùü{jÑ{›Ÿ‹;¤8oÀ1‡x)Kõì³Ïfzn6¼<³ŽU±bÅ7«Š›WÉŸ `_,Åç|r 1/M©|;U=Ú”8zº\ñ¬2»µ`·— žQy›=¨îyáCµ|ãVI‹?ؾȾƜseÞµk—züñÇWT);dà hä€,>¶ÌØœé“b%·KSædÛ!ñŠM;Uÿ‘SÔ#ýFªOš#×kÛÊüƒæ3ÃA uøøIÅ›J(^ÕäÁüÕ×LŽ@™¬øþä“OTéÒ¥qlC2XjçìkkÕª¥¸™5·Ç½t™ÍÁäŽës(û”ÅÔÐqóä˜ >æÀ‘ãêÖ§ú«ÿM_l² Z@0'8bèìÙ³jÀ€Š—ï ZföÒðÐó}ÅtÊÜ:ÐvK¶Ì4lì,®es^ˆ5x­Ì {ïÛé´pÝVI‚² ?”ߺŒ \‘™ÁJ Z6lq·š)#ƒÏ¾ÌoÜ™_BBÍž=›†JåË—˜ƒQòÅ€ûÃ<3äÕOÇP›Çû6uÎà ’DC °ZÀùcéÏúnÚ2øý Ú°m¯™r`¤4!¶üô¸‡ñáŽ{Zºt©L¾ãfM «Óè{8¿a`€ ç÷ö2÷kþüùtË-·HžÈ@E>vÊÂç0k3`¬V¾M/Mì1©H¡8;ù%qÈ‚±hp9y }4f&mÞyÀL9IMföˆR¹™–r3=i.˜ŸÆÝl)f\rÓä¶Ì•*U"îC¦éÓ§¿¬‘ëýÉŒŠ„s˜%ø—ãfSËÜøxþý'o=wIEóW†¬>î `a Ü²d,íà½W‡ŒK_N\(‹´É”j–Šr1..Žø•¡±[·n¢@‡‘Fû~«$s¿0¥†ßÜ@qN£¯Á7îÎ|ÓWY8?ìÀÝ©×ûÔõÕÁ´yÇ^^9æ –!ý;údÎÉ+,ÆÒï»Ñ gÓˆ_Ë"md†<¨D('?ˆÑo¼!•óÓ*Vr]~È£¯)X° ½úê«¢§¿ýío¢'}­'‘™u™Q1qnÆÒõÔîÉwéñ¾_ÐÞí±xá‚„é H-á"‚,1ð#bûK4/ËÛAŒžAãç­‘E,ô|*g“‰ÛÚž£B… ôùçŸK3ײeK1, o‰6*æ~-\¸xÈ ñ~ñ´:/§(h áÑî:p„žð5µïÙŸ¦,\#Þ%¯_À\6Ã^FËŒ5­ ÷âõÛèýÑÓy½«õ²/dFEIKfîú¢#FÈü4î~™q ä…n 3~ X£áµ×^£+®¸BÒÈN B~‘™ÏAæM\!~ó3âiL´híïT¬P)¯ÈŒÄQ\¬–ŠÅ‹XÀ«Nâå00¿ÅJ$üS<Ž# x Hx4s3fÌ áÇš?4ýøð¨}âÑûôÓO?”cÈ ×:*î…¦ÛÃÈ»o'<ò ùaÅðº[… øvGº`‚–'?{[~ ¡ñó×§ÇNÙ¨(M§±ïã” gÌ;W¦yswœÈ]`’å´iÓ„T®\ÙÈ 0;ƒ7dey{ètc>ôͯó).o™ÑŒµwúwæ©¿/µ²K%„ëñìÔc¼@ñ¨)KÅa¥A¬… i˜K"Ú[覽K—.Ô±cG™³æ h€ À0©Æ@Þð.?ÏZF}¿GË7$ÊJ‰ð00÷–Êy·þˆ< NðÛC¼¾Õ׿.¢EìuÛ5©N¯..·AP;8e~øá‡e:7Ö)(_¾<ñ›*IhÛ×#®+€Š0râ<êÿÕxâ^*ÌÓÐe#g‡£ÄQô'd€Õ:€À ±Š V\üÓº–— º¹quYqé lMôuÚ{ÀHê[o½¥OIS¨Ï›ƒÉð1Û«¯ümõùb,ý2w%;s6nFèb8ç….þ†Ì«ËlÚ¹Ÿ9îAY˶m£xn•–ÌEŠ¡¾}ûšRA©É ü¡òJåäÊ2wåoÔçóŸh&óÕ¼¼®¸ù…?/„\fSÐGBX”ŠÅZ®h|—°×Y·u/µ¨[‰Z^[EVÏ–F™ÁƒØFÂõÚ»À¥f8Þ†Ûwø øú6n–ðgx.íÒµ ì{¹×2cepÜ{þšDZ›¸‡´¨ÌrW àqÐ ™w ~ÜŠ|7y€³(·"¨8á”ÙMýùË+,€Õ7‡WA׃'äéŲqö<âËì‰çdm#úk‘Œ‚°b¯¡?Í ÷GM¤íìÍ Ì/Ÿ¬| Ö2£7 uŒ³š–nÜAm¹…¹¶ ÖÄÕ2cEþ¤%3ÒBf¬³ûÉ÷ShÐè)´ÿÈq* %ãÚP·"KÞXX«EÈ pp½Ãàz“Ó¢uàz5¨Riÿ\O_o'O8õåæOÁx©$tÙÀ»d%XíòBfÐÈŒý ¾üeË\Rd.W²¨$•4~kç!2s¥×<õû) éÝáãhí–]tE\>yúÏ<Õ–ÙÏÀêBÀ@šëmá³Ñ—‰¥ßÛ6ާbü(À‹€§®Ý²“Þ6–¬–ËÃLq^‰o¢"±)D[€ÕÂEf渶ÂW/Ohe ÈHdñœ¹Xî…k¶Ð;\9§,Z#]ˆ¨œáàæ ¦“Y XȨ¹žß*éþ×K¸¶²,Л‡û7N4ï;į?à¦èO3é÷Bâ¦|0šB‘™K ~ Ê0gÕfZýûnj]¿ 5¯UQRfíÙÍ}ÈýØ£¢àìù To¨"´rj{¹ýíz?lf ÃŒàzðŽßÏXÁÞ¬š"oÝ!£½5x 79¤óOÊðØÑ´\Ø ûo}7m9mÝ{8™}fÃÇÍ¡<æ»Æb º£óˆ&¹ƒ)kÄV СÙÃTi…8öªèÓŒžšVyý™™Þ`³¼@²BfTÜË1D`aøÉôxÍG¢ßt#½2G¿´™— "›yq¼+³»<Àfw g3ù<Àf3ƒfwq<Àfw g3ù<Àf3ƒfwq<Àfw g3ù<Àf3ƒfwq<Àfw g3ù‚¬sàu´ëïðõ ²\Ž2ûÓE¸X¼‘ÂŽzÙÁˆzÛQ ¦ñ0påôÙì%3Æ’ÙŸ.²âx¦‹±Sx•ËCä°K6Þ…'±Z{”QV”™{£â=ýÞãJïàíF% F& X1ª¬~µkdT˜lÉ×á\´Œ©…­9!ãh;µn¯¹3=¼FÊ•#'ÝÙ¢®Œœÿ…wÉÞÈã;1 s™¢aä †Ñ^ÇOÐÝÓ¦ õ~°U)[RÀéœ,ˆôËŠÍ•QQ±3ø&^@òâx4È,N2Ÿ<ͶÊI]n½žþÕõ6*õ•>™aØ™¬– 6Ê—*Fu¼§~l§É‹7ÐîƒÇdäæWE¢aÌ ;Í›"'ñj/ÍëT¥»w V kˆXT£Gõk9íoxÚÊe®¤'Ë´”¥Š¦ðRMûxz †ý¡D¤Ìp09s‰¼ 4 âYæ;躺UÓ%³-Vƃ,j, ˆ¹I˜-P«ÂÕ4sÅ&šµr3H:+[žc"wzF"…C¨Do{„›ÿJe®¢gïoO]o»A(L¯˜)ÁÓBÈÞ¤Fyª]éjš±lÄÞBI¼½;æ@ðé%R¾<)xê‘ãÇ©Zù«©W—[é¾vÍå"=¾8P œ{xÏ XD€óð*(˜`ðNZ´ž'n“—Çz×YeDݼ9~ŠÐÈGÏwi/;Žc^åõM£N¹hÀŠ™ó³gm߬¦‘yÅær+ÂàzÈ ÄŒÝÃÇNQQ^3ì¥îéIÞy ˆøÊuq~XV”/3÷t°úƶ‹±‚îkÓ=P9æzëé7žŸ‹õ ÂÌo5Oåå@¥âtjÕˆyêíT£bi)6Ãë¦æaôZzª9Œììò’†s¹E ÒíS“í>™±–0ŠÉ^j¤eÖÜüÞ››‰Ì•¯)á“9™òhG£í ß®V ,F„gá•J_IOtºRV@á²i/¸¯Ü‚ „¡æzxiÉW)H]nf®ÇOØèËܲ \/ó}™46VAAÀ­×ד¦°N•²Ri Óà©XTn×®]Ä{Ð!Cˆ¯öºˆƒ*|öÙgôÃ?ïŸ@={ö$ÞKAŽãF—ð[® È£T±BÔ­}SY¢ 2oÛ{ˆòÄÄ0ð3Ço}2çàž˜3’ÿ]Üñÿ÷!Çs/ B n. ¢ôOØ ý׃Ù€UyÃ*ÜŸ¹`íVš²t7g'e3xŸôO=Ë<õ$Õ¯@/0O` gKƒ§ò–ôôñÇËâkkPÛ{ê8Žó¥Ô»woY ôõ×_'ÞS!ù~ióÛåK2Ç½Šæ­þ¦.û=c’´<ñ€>™ÏÐ^õ¼i­Ê"s›&µ’ËàŸ›K‚(ÿVÀj]Á; h®×¬VªS¹4M[ºQöI׃µbºI=xì•,V˜^ù{Gú{ÇV²Š~°Ñ\Vßߨ,v7Ö™}å•WhÕªU’ žô@Ô¾qïÆÀ屩sçÎB°’v£F$9®°µœ8¨ãÂ%¹5¸„E˜Ê2ãá /1Ò–ÙÇàÀÍË”(Jo?~7uëÐBÞ.ʃ"+,5™¥PÙå0ËsKS†=)^wJõøÏ(Å«xËqû$I’ *Ar>$áÈÜö_o-=ôí¿éîvogïºaofg{zº«ê­êêé®Î¦8‘M––Bì–––(`qöÌR€, ¬X °€0ˆaO-, ¬ X °€0ˆ‘žS Ö={–þûï¿ôcï2²Ùa×ôsàܹs”#G§ |Ïž=;e˖͹fObƒÖB¤ƒO°ø IIIôÕW_ÑöíÛå;À`Ø[°€H¿Ð=ÒV–à矦 PŸ>}äøÆoÐéÓ§4ixŒ½%@—ɦÐ(À­Μ9ãd^ºt©êر#ÞôË'gΜÎy­ZµÔO?ýääeÿBá~›ÜMrwõÜS;´N»wïV=ôÒà.“bK!`à®’Âw ’N:©¿þúKß*€²ÀpÈáºëT1Ëèò ¡k”œœL}ô >œöíÛ'×á?øò ÷çÊ•‹î»ï>4h•,YR®ãÜk“Ë(à:ˆº¤BÐâ¦U˜0a‚ªS§Ž£ùa` ˜?¦µ`0¨#F(vÀ¥• …Mî¡€í2yñ@0ý„•+Wª®]»:B&P_w¯p½nݺjâĉΓ­á"ê' L‹°ÿ~õØc©Ü¹s à#h?ÁöÔœ{û7Üpƒàt2Ÿ¯¯ÙcÆRÀ‚én‹F?üðCUºtéV!5‚,¯ ®ûì3<"Å\£´ kFÞ‡nê­ŸùÀ(žFbßr§åð|ÉÔÓ¿Yò µk׎† BEŠ!~ -ó‹XÈä7·ÿA=ÑÔÇÞ½{Ó]wÝ嬹p{ýc®~áÁUl”’ n»í6GÓº¹ÛäÝ]jÑ¢…š={vl:†k™©»Lš/è6™ó“fÍš¥Ðgí%·9Ö¦C]±bE5zôhÝe²NµCްŸd @hªAÌaKøÁÑÀ0Q_ËÈ£9äš/_>5xð`uøða©>@mÖ]·ÉÃK˜D8FW XºŒñó:„ð›B™Q`@÷Èã-·Ü¢Ö¯_ïp:ðšÑ®ÅsÈ•®“˜+Hu–5|¨én’LAÃ[á›o¾9…µ€ FÞ~BãÆÕôéÓZ£›§ë\ô:9w.x;õ-(+²èìYò€0püäé€Bræì9…’G ò˜þæ5jÔÈB¤ü Ó"”-[V}üñÇÎ0*€ÌO@½½é"m––ÿÿ?§’’‹©‘sS9q5 À8­é“’Ϩ׾œ¤z~ß§ kÍwôÄ)õÎØYjé†í Q†þݹèubúHÌ<Å Tm!LÖ×Òr4»d˜ú=`ÀuàÀ§6¦Õr.'hÇÙó€ÇåÅk·¨v÷¿¬~[¼Fr™ Á-ü“®Vc¦.RGŽŸ’|ò[0¢89³Î‰+ã™üÄBÌ똳Qv{Ÿ49µàzò¯éß#'ËÁãöÓ—SÑ'ãÐö½‡¤ .†ß?@¾}'Œ÷³ÐËúh±zÙ²eÄkˆ7EØß%¾ÊÝ£aiºuëFK–,¡×^{Š+&QÿPží/&hGŽÙéŸ}‡è‘7ÆPçþoЬ¥ë(W€ûPãˆæ®ÜLïŒMs—'ÐÙsL_. ´ÆÇ&rº‰`ËÌ(0<3kå¦4ü‹ ôë—3'-\råô/0h ÊÈÅyãóÄÑÆûhó®Ô°Zjß *Î,"_I $[ *^¼8!Æâ-=÷Üs4nÜ8¹y¸Ë’ i °æPÕ«W†J¾FÊÂu”Ç]3_Õ‘kdAË]úä§YôþØé´ç`"-”Ÿ å‹©.ùóÆÑI¾ÿ§y+héÆtMÃjT³Ò%žg0(²áŸo²ø­[fûÁ?2¸¥Ð~`8À°ÿÐz뛩ôÅÄytâT’r6¶GŽ ‰ñÐx¢¼q¹ˆ½ Z°j ­þ{µ®S…š×¾T@¥µ"ÖW‚zÊù8Æ’#›4i’– B àè²¼ËAøB_ªT)♫by…€Òexß§¿ëv€&HãçþE¯~1‘VlÚNò奋 0z ]( 4É‘#åÏ››vK“'OvW»vmÂõ×_/×€ ê'pnbò™³ôé/shÄwSi' ˆ¥dÿ'Ô®‘S‘N´…²8ÎÝÓf/£%¶S‡†Õ©ZOP5äÉ*þE†ÂÔ~ÿ9N#¾JŸŸKGŽŸd¦çcöé·äà‚fä~<3zîŠZµeµáîB³Z•D iFhK6ò +Å1–¾Å/¿üBo¾ù&uéÒ…yäé*é®V ‹à)}{O7 °”K×meK™‡-e~¡I$À`Ò V4'×!WÎÜ´s"š¸jW.ÍŽwu*uQAÉšºQÑB,@Ð~’/'Íç®ÀÚºk¾"ó…¥kd28عԉ3Á¿@wä§9<ò²Á3òRƒ»SHÈãO3šþÎa ´EÀ½° €òõˆû «7ïK9yþ ¦S6‚ÇRFVA ®:qsè¹Ù¿@Z‘ðmܾOEkVùòä–ë™D íÇB3kÉ:aúï+7ñ°¨ÇO€à„ÃON¥áø,ùrÆÑ®‰ôé¤ß©6E^Ó¨:]R¬PPоƒî𸠦¥‘GÔ¾žJ[wðø Q°”^ULñ`@Bûœ8EßÍüËã_°²¨Röbù-M$CŒý ;  !³eó¼OHä÷ï}?FŽ›E‡ž¦£ i?!­FÅ‹¤Û;6“Ù”Þ“È  q-¯‹nZ«¢œEfÓŒh¢…`iîíQõJedö­·]©°\‰¢tìD’„÷ÌÊá*=ñý7Ý „|›þ«"Ȭ͎?%áûu½Šžì}•-q‘OÆã‰à=¥K³Z„5¿S­§u,;:À*óRúkš±% }Xopøè)ªSµ=Ý· unበè«&ZT.Sœ»¥-Í[±YbQ=qš×väbše“à ¾îÍŠ×\0Váäé$ŽÇz†Ú6¨A™ékUþ`Š9~”0 !*ïîÜ”Vqø”iKÖsð­Ã².å½ 'PYnù mæ].è ‡ú/Ím{¦_Wº»[iÚ e …ßW±f!Žò JaÝ*eiÓd Ç¡=±ŽŠ"Øú_åf¶k®„5ùÌ9Ö~Ç¥ ‹Ð£}#¡9« ÈŒ|š¹ˆ>‡Œó9øÞ7 ‘µÞÈ ëÄRr]á'`¡Ñ½ÝÛзwâhÝž˜´¡(ÐDƒÊ hÁxº¹m=jX½[Ñu²m@NÓ— aþc݆¢µiO®„ŒÍPŠsX“G{v£z´—Õf¸ÎÿC‚IGøfì)ѦnªËݨK7Òb^ڙīÙܬµ¥šq€µˆ¶fD{!€]¢h!À]Æûol+‘=D0ƒXJ´OAÓAÓÉ …sªÁ‚²sÇå”ð:õØ¿M`5P^žókÇù4K¤ ´6F9|ô(U) ÷‡;Òm×6bCûy´}`íFé‘_|ñ…l}Õ©S')CïÁ ™mr1…fd€ÔaæcŸÏÈËf J‘ñŒµ¾[2:QùRźˆrð;³Iι|ÐeÍš54{ölºãŽ;¨@"Ø(ΠƉcEÙ@´ñžíëKŒ%XÑ„ˆongVèFù—<ƒ`á8CÑ=:Äãæ9™¸¹?<ç“ÁhaòÀ|øH„]ž7oµlÙ’úöíKØÙ‡7;§ 6H¨z>Ä_ÒÀÍÈñí9ÈÖ£7·¦&5*2Xÿ£S<º…ºú•¿2ÓrME— £ixŸpUÝËiâÛÓûOõ0ÀR‚6Á,¥V¼ ½ìTÄû]˦.ب嫯¾rº” ‰¶¤¾ê‹6£,ÐôuoI½…9ò"ºQ¨ òdæq@@¨`ûÅÝܾ1Íüh ¹ëzéÓƒé mâ}Œ”rx_†¿ÿþ[4ÀP Ë„{¿ÿþ{ª_¿> <˜>,Ì  >ÀEjó–võèZÐe, 'O%‹%‹”€&cy0ñ¨ÿ§Cî04©}™ …¢NèÂ6¾mÓ–ò³Ï>“½*^yå:qJ''mÙ²E6tiժ͟?_ò‚VP, ¯:ƒ.x>F¢»¹l ‚0ýxˆ<ødÆ1@€\Ð~˜.€>qƒ•èç×ûÓgÏÞMUÊ•”Qfó_0Ý“'?~œ^|ñEaú—_~) 0€¹b]ø‚ðòË/KžÑ£G;y‚jFf.ž!¨tI1ÅUÔëš ’xQ;ÅRòó0¢†—…CîºA,å-W7öÔÛ¬óø8ÔÅ´”³fÍ¢-ZÐ]wÝEÛ·ow,¤™gîܹtÕUW‰5ݺu«“'Te‘—ƒ?wlRƒú÷h-8xŠ—ƒ+ê«–±{Í¿4¦£MâœòýQÉ‹ ÑûOö¡iï=I­ëWá½ ý|k0Ì‚6ƒ&úæ›oÛÙbëª#GŽøÔþȼЌ۶m£;ï¼S}i'T͈gC76¸¼<=Ú£€}‚-Ê×V%µäÁ}KyJ¶Æ½íÚ¦4ûãÁòÒ;Šjÿ õô—Ì6&$$Ðm·ÝFmÛ¶¥… JQ?Sû›V¿ÁßÂŽG/½ô’(Ðyðñ—PoÐèƒp˜çŒ|†úvi))C†ÌpB¥µ˜fýñÇÔ®];êÕ«mÚ´)¨fÓ÷C¨pÿ‚ ¨M›6Ô»woÚ¼ysÐûÑd<0…`„¥ï…͈@¾ÐŒèï{4£o0{“‹K™Ä3ÂR6©uýòæ£ôÉà;©R™‹Ï[ÊÀ~mC›Žò`ÄóÏ?/ â믿ö€”Û ° ¯¤Ãý‰‰‰4dÈé^~÷ÝwÂÐKçñu?Z*ÀàòñŒªåJÐÃ7¶â—{u© G&„”€6@ÀÌÃG€¯Ð­u}šñÁÓ4ô¾=›£°A æB¡áwìØA÷Üs5kÖŒfΜ)‚LÃËÎÿÑš÷ Ì1cƈaGÐcÇŽIy`l0͈âŒâ<òÒëêâ¼Õ¯s™T«V­œö³ÒÚ¤•¸AæÐ笀+"ç™ K°¤i‚|¼¼útâBǫ̃‰Š£ÜzždÁŠqÕï0éN ̼eÔé¤d) â-$ÞÓM¢ÿðêzõê)˜ž†{ß pAôõÖ­[+îR9Õ‚¢N’)üv]mÝsP²{ߦËÙº{¿âÍ"¡ ‚%“&<¢¦úöíëÔÀ†ðê6„ãh*‹‹.ºH½úê«¢˜POSYù«7(fÒ%aç~u*é˜ýÝçÖëa„Ù¸Ôj¿%K–¨:8L‡ö $(¦fD¾~ýú©­[·:M0Ò¹èub €×O>¿‚&$>3ðESøxDM 6L)RDè.Kˆ.&0jÖ¬©~üñG§ª I°úãwoÅàC'aŒh¦°íÚµK=ðÀŽÙŽ„ö &4äàñp­âa[a)œþx æk/~O­¥dGW]~ù厂05P{Âñ›7ð:v쨠°t ÅŠ£‰.˭ǰ"PMKJJRo½õ–ºøâ‹£ÂtoÁ1®ZµjŠ_ð9M E3:™SyÁ1ýQSìà:4‰´¥ô¦ƒùVTwÍP|PAéd*6}-³# 0Ý$Þ/¿ü¢®¸âŠL7­soÿâꫯV‹-rxŠft2‡pbÒŽì½÷Þë`F[Ê@47•E‰%ÔÛo¿­ ÐL%B“c&KÄašÎ+V¨.]º¤‚î®bHFÿfú†ûî»OíÜyÁ)6Û”^Ÿ:uJ½öÚkªX±b]LÌè¶û{ž·²¸òÊ+Õøñãæ‡“&N¡Q<‰ 4‘öíÛ§üq'L7M±?¸áº)˜Å‹ÍFÒmK Ïp/>¨Zµj¹Þ|ðö/n¸áµzµgˆ==4I #yOØ¡kX 3‡<½‰íÖï¹rår„šq÷îÝ"ÐiÐ%99YÝ}÷ÝN™Pn´”ø^j‡|x§z˜ÝÀH l¤Ë; Pa/Ù&Ož¬š7oî@4Å@LöþÍ»›ÀÓË^ŽA ÓM€‚g ª'žxBåÍ›Wè+V42-gÅŠÕ'Ÿ|¢xÊyš•D¤…;-åGfE  \Ù²e`˜„õÆh7ëV£F …†‘H+W®T]»vMA·Z ´òSO=¥ô¼”Œm¢YfDašQpÀ€®ÕŒ‚H¼±ÅX9$€Ÿp$Xs¸u„ Ý1­ÜÔµ=Lqã7*^çÁl‡s1ÆO" M“ppĺwïî€)ˆZ(2òhŽ,Ax]âuºêë› ÃPæ;ï¼£0´©Ûn ¢¾–QGÐÁ&/¼R¿þú«C“pC;»à$l€`Å0ykFø¼ÆÁ€Œö/¼™Îë Ôï¿ÿî´!¦ó'@’ dI88í=ô#ŒfW%£À`ñ’K.Qï¿ÿ¾cÑL;„ò: F¯ì®û6@ e F0`˜D…н÷Þ{ªT©R0L†DJÌgT©REñº‡1èæc*æ2ËãÈ'Áæ>¡,ÓŠ.]ºTaÚ„nF( |¹sçV>ú¨Â°¹Nf÷W_3à{°ylf~·ž‡ЂÏic°ù;ÈhxïÞ½ªÿþÎpžÉ-á8° («P¡BjèСŠ×GH½!”Áüä1g¬:rÜi³¯^8£8*·S~0yÊ¿0íì0ÑN·Ý²¾–Þ#èa–‹¨2×)Kiáàá£<ÛÕ3ëY—KÇtB3s῞¾8%0 6$ÜkjÆåË—«Î;§-Àéa¼é' œ>}úÈ𧮚 N}Íûhaóνªûo«×¿š$Ù8¬NŠìÚ"¬ù{·>fšâ€ËÎïëâ|õybZQ8öx£ G_ÓÀ`}--G³ï7Ð!YJcšRòõö7STã;žS¼tXÚ¥eÃg#]z1¬€¸çµoÔó£'«9ËX3z„D Fün e¸æO-L `’%&[¦fŽ’‡_”À¤ùËT‹»†ªœz«ªÝžP‰Ç<£sšnN£cà$lKH™)”?on^Fx†~š·‚Fü0›XC¦XvÈ+}&\YÂÈ”e<>O<¹ŽÞ|óMb†É²FÜÈŒôy¿¯‹ÈËô—{+UªDŸþ9éè,äòî›Ký|Ý϶M–y²ÐIž¯§,¤V÷ £a£ÇËæ$ù9lM°„öÆqd )^±ù¦Éš°pµ¬AÖËOñÉl¿Ç!~Ÿ#°ì3”6x—‹¶àƒ{ÑvžÅJl•‰ýâ·Ïr]çñ¾ßQSî =HbUºuÐûüù€ÖnÙ%KmÐ tÕV@°¢çuÓÙqÄK é³ÉÈ¡"!Xn‹<þ’fÆŽ=öØc´lÙ2âu\‡ Ÿ¿„ß0äÍŸ??=óÌ3RÆÅŒ Vx ¦£¾X¾`ÅFêøÈëtϰѴsß¿Ìô‚ÒFä %á™zÄJEúmézëûYôûš¿åº¬»æßý ÚáÕuG²éÓ§Ó·ß~KU«VuÖ@RÞ çÚk¯•<‚D<’Rlõ$ø€°ÿÐQøþ÷tÍC¯Ò¤+¨PþxŠgž#‡¿v„B+7äñ/Yi¬ÄB¯5ãê-»éÝçÒøù«8A’™!TÍXºtiúàƒ„¼²N–Ä[»›LS°€žGk$–;ÐrŸÎã¯iÂt-˜¾u׺oøhêòØ[´pÅ&*Z(Ÿhzv ™éþJð]+XQbø~æ2zé²qǾóʳxß_ѺîÚŠ"R!Ú‡2… öÛ>me øÍ;ñ›wâw u×@+oZš­Ÿ<ŠÎÎÑÈŸgQ«{_¢ßNŃҠ›nŸyo,ž‡š 4>ñÊqf.ÛDo³f\Àû4€xÐŒ:¾Ç¨ ,ÂqÖ×¾œD­ïFc&/à½$⨠â&±ö b³îÎñ,ÄgÊÇuû¾CôÉ„…4fêbÚÇ[†‰å›=Ç´¢°€ˆT+êmµÅ€Ð³CNˆèǫ߈ß63ý=]Sä}%ÐC[J„—áàÔþÁW¨ÿ›ÿ“x[Å ÛBµ”¾žáÆk„n¬f.ºQÇ8Lͳ—ÓˆçÐúm{…`ò„ªoºé&aìðáÉ£s0Øù¤råÊÑÈ‘#%b9A|Y]/…é,:ÎÒ¿-bí7Œžùæýé.*”ßÉcÞ—Þsn®(DîÃç¯M;hÄØÙôëk%ˆ™(‹óõó÷,­ùÑvžh'>’Žw‹¶ãððìZ Ï?"ž‡ä\Ôí„{,RvÞ’lõ~öcêñô»´bÓv †œ‹•,efLýÛ£³ñæ%q²½Õ¨‰¿v÷éаG÷+(´0 ¾’f OO?ý4õìÙ“ž{î9é2 øâÑlbžú*Ë#Ø?šñó­ÙL/>f.^Ëaás‰Ÿ€núÄ‘L¨+ü Äyºx=-OøG¶½jÄ1UY*EY€"¾49®Á:ø( !-çÌ™#àà™Ä³j >€iË!½þ Í°’  ‚ª¡[ôÙø9²{ºF\‹ˆÓÄ«Jþ5Öÿ`´"ÒŠ„܇ÞKÍj]J­y‡Ÿ|çÏ@ÀКB«€Ñ#–Ô0Nòë_M¦o¦ý.QùŠðÈ6NÉhíe¡‡Mä­³¾™±”–¬ß.Q…)MLeösèùà>m)I,4ó`@]¾œ<ŸÞú߯´åŸ}ì0ç#ÐÅÓ5òØ_9™áº*E°u¦f°AÇ ÖŒmyCÀƬµ*øÓŒ`¼ÖŒÈ¡À5 ÏÔ騤åãŸgÒûßÏàm¤©H|¼a †#küÕM_GGC—ï>H_@õª”¡«ÙŠãîR `èöHžnš€x&,¬Ñì¥ëÄRþ¾r“lÒRŒGÔPV´é"É ?Q„n›)fĶZßýö—£«”õl«…<ÙØ©óÕ‘ÒšQ—çë(L?¯ýðû/s–Ò«_L¤•<†Ž Ã4tø5“¯Û3üꋪàÝj´ˆ-ÅZö·®º¢2µ¼²²s™|) TX#På!äÒeä-‹ØJ¿Â4ùyöy6|'tá2ÚRªoFýU@èFz4cvÑŒÛöðÈ kÆ+yƒÄkX3"â4R ͨË1¦ÿ4ÓYû-Û°^æ—jÓþ\ÅÏÉÉÎ!k¿ ðÌ:¥æíEB7ÓÙá^¶i§ÄQ­y9ÑèÈãÏ¿ð÷,´9{6Ÿ€Mßýn:7KTæ÷ Y¤}'usÃuW„ÿ¡±×ö8[Ï›"¶¨})µªSE¶ÒÅuäñ§ñ;’éòt â)4æ×…›u P 6¬ñ½¹m=f\¼Nú¢»õÀ± rto޲Ÿ€vÝÚ¡ =Õ§3U.[Bh§ƒx[“°úeéîC^^³Ò%4gyÍ_µ™W÷%óâž8Ÿ+Ýôýn:Š¥äz‡§•ʰE¸Žz´o$UMÐV‰ñä¦J§².a„~®øˆ qÿõ-h)GÐ€ÅØóïÖŒ¹„hn1xK(:ɰù•UiPß.Ô²^5i´€’Ú‘SYäåÕm×6®Nõª–åmº’(°¡<¹=!ïqî¶„öBÑ!¼eñ"éÑ^ÝéÁ›Ú9¾ŸZš¸­º>a †èn¡úUËQÍŠ¥Ø·ØLóVnæÛI®ó/ ÙÿèpâQ¶%éñÛ:RïNÍ¥-ˆˆvÒ~ȃ‚§ù  &Ê‚éƒÅýˆ7uÛÕ ÿbË®ƒbAYÃ-ÊõÕ~¬ÃíL§Ø*T,í "§»GðZ¨bù@h‚hBA»`=4‰f\¼Aâ.A³äaÉéVèû2òè^åêz’»FßrÚEwüÕ m`Y4t4ÿAöÐ~¹gº£sKÙÑG¬W,Ÿ€úèîڃ݌žþyZ¿~½4!ça>ýôSúùçŸiÀ€ôðÃË~Dº[%7+ÊÏ(Y´ õ¹¶‡òd+ÊÀغç_ B†<á¶¢¢ñÙRâ½°ysûÆô4[ÊËÊ•”ÚiK™ãÁf…”á€ÐD# 1ôرI ªÇšq: ÀrhF¾îñ/Ò¯å 1Ã0‘µÞ¢>ÚóZêÏŸâç)‡â' {‡uY¼x1=ûì³4mÚ4i®ãw€ y`-HcÆŒ¡ç4Øù)¨ÁtÑŠ Zù’T•‡z±A㬿6ÒA®?hð€néI >ê©GÔš^QEFÔZׯ.Åff?!Ý¢])G3òÈK ÐÛ;ðÈËŽòüfw½Ä/Å» ÏV¯úŽÐZûaTë,÷;·¬Ë~BªU¹¬¢µ_(~„~×®]²Éá¨Q£D°!P^ ]3=ž k°nÝ:êÑ£aÃÈ¡C‡öÊC Ù¿`í0•WT.C308Nò 1#­ðŒ¨ýÇ#jÇèRž]ð¨õéÔ‚ëË»·f?AóÉ×1ê€@¥ ­Ì‘—ªåJÐe<úòçÚ­4“G^òøw×ûÊää©ÓtŒ‡¿»µn ~BõJ”ç7Oa°dùĚ̵‰5¹S7Þ^}2~¾zë»™ü^ëÿ'*¹xøè U­ûÕÿÍ1jÏÁD'#ïáœû:ÁýgΜq~â­nÕu×]‡^‰|Šë|××S{dkà”qÅW(œóL¶hJ·Ã¹èu‚ßužE«æ.OPO}ô‹Z·mäd-ŸâäAzöãÕ•· T¿-ZíüÎ/"²œ‹Yü}`W'ðׯ?û+o¦› 8qê´Z÷÷.ç’‡éÎWŸ'DöìÙ£xdHåÊ•K—µ¶Â'µ‚(?€e£sçÎ Ô ÀÔB¯¯yMðF*ê𱓒Š\ŽçÎMÛ÷(žŽ"_ØR¥ ©wÙYù»ë¡™ãÑŒú[ð#,BP¡ÁðhÐäädõî»ïª’%K:Âo m Oëo&ØâââTÿþýÕÞ½{Æ™@u.z˜ÀðúÉç×`–ÒçMYèbÌBó$˜#_0!Af÷hÒ¤IªnݺÂÕ= (&ðJ•*¥Þ{ï=€J[ ÐÊDYø¸n^MB¡yOV<9@¤—I¦Ö]µj•êÖ­›f8ü„P`æÃsD}­^½zŠ7_wšŠád¶'i¦@–„ :UO<ñ„Ê“' ÙuÑ­£·ѽ{wÅ#\ƒÍv8íIØ(eŠA˜>þøcU¦LG›Ý•hÀ×sMæÍ›Wñ4uðàÁ°1Þä›™Ú_øí·ßT“&M d´ŸàKèC¹f¶\¹rŠçI©'NXÀ·<§ûj¦„îwóË0ü",ìè¡vzò …zë2î¸ãqº1|jSx)©_M²ve"êÝ»7}ûí·T­Z5™†ÁVÃït ¹ÁEt0}¤hÑ¢4|øp™BÂ.èÛi5#vª^|¹»´cÇŽ©_|Q.\X´­·Ë\s´p´ÏáC˜Ý¥¾}ûª¿ÿþÛÝεËÔ]&“?æèÌ–-[ºZè!x@ý=šGïá×V­Z©yóæ9M å-¶“Ùž¤šY Œv°5•æÎ«Z¶lé!ÚŽ¶i.½ôRõå—_êªÊ™õrDì$KBS‚eZŒ/¾øBAµe0S_‹äÖ –Ï(P €âÅGêÈ‘#R]€Ø¬«nƒ=F†Yš”z ßÕ!CTþüùE0! ‘îFyû ½zõR›6mÒÕ³@p(‘q'YšÌ¦Þ¸q£êÙ³g k¡µw¸¬„·ŸÐ¬Y35sæL]™gË`SÆSÀâ<ͽý ¼ÈkÚ´©ŒpùfwŒ£r(^Žê¼d0­Ÿñ 0Ÿ˜ _XóÙtž ( yO#"h¼ôÒKw YX .õGHîÉO(?>>^¢q *Þ-à9¸Ž²mŠ2˜6ù €é_`ÑSO=¥0§ˆÙ%¾E¨þºG¦UàèjíÚµÎÍîšsÑžD¶Ë„ô¦ÀBo¼ñF§A÷ç_xû 6ThÀyš 8ç¢=‰:, B`·1eÊÅád`xû¦Eàè s©4°à#X?!¢G)‹õ!RÑe5ý p9r$ 6ŒvïÞ-¥`~òàƒhˆªèÅ‹—ßÖOH½£‘Õ" T7{ÿþýôÊ+¯HxLÀCºþúëé…^ ÚµkËw€3w£ä»ýã^ X@¤‘7lÑe´ V‰—£Ò;ï¼C]»v•®8]²@5b#Y@¤“OºH°:á;’jÕ×íÑý°€€ÉG˜Š·Åd, 2ˆÐö1±AL½b.6X`ké& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§€DÔY`+à& X@¸‰¶.Q§Àÿ EõÅ‹ÐjIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/144.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000002243215232633614033151 0ustar runnerrunner‰PNG  IHDRçFâ¸sRGB®ÎéDeXIfMM*‡i   ?? ˆ$„IDATxí]|ÅÖ?ôŠ@èÒ{Uª ("MÁÞ@}úI±<õù±ðÙù) ú¬J± OšE”^EŠ ”DJ¨PB à|ç6³™¬÷&Ù›[Ãän›Ýÿ™ÿœ9»;sN>ʼn¼äI @ äð<ï4O"@r%@¹ŸwrÁ MçÏŸÈùòå£üù½ö“Ûú¿`ô×_‰¬ (`Ë d‰@&/&<ßñyîÜ9! Èòã?Ò<@¿üò L Ž{£‚˳‰‰acÛ²e‹ºë®»ðÊBþ ,¨zè!µ{÷n;™ßÞé­d)}Zòs·¦ð祜I Ooj‘O>ùDÕ®]Û& wYö:d©yóæjúôé¶ÔΞ=k“ÐÞé­üMy‚@Ð6¨p.\¨®¼òJ›, 4Ö:æÒ©‘®¿þzµvíZ})¹®ÖföNoÅ–@ÌÈÔ8Û¶mS÷Þ{¯Mh6œím“8ÎuäÓy .¬üqµoß>[Pæ}ìÞŠŠY™¶Jjjªzùå—UéÒ¥…,Ð*ÎîÊIÛæy•+WVï¾û®­ÝÌ{zܱ$sBwbjƒ/¿üR5hÐÀÖ2&ü‘$»ýÎn­U«VjÖ¬Y6g<ûÈEìh §³|ùrÕµkW›8YÙ9ÙÆßq§&»ùæ›Õ† lé™v—½ó[‰9 ´sçNÕ¿Û^qcçø#JvûMû¨hÑ¢jðàÁ*99ù£Šo¸QO hØû÷ïW#FŒPxo£+<Ý•¾VN–æýjÔ¨¡>úè#•’’"ûê“ZÔH®C† ±‰S¤H¿å9!Bnò@áþúo½õ–È´Ë|·Õ¼¹7ê ±kÃyæÌ™ /ütå™/õ¾P-†uÇŽÕ‚ .h탺‰ ¡ ::uJ½ùæ›*>>Þ&’Ùµ„‚@æõÑu3Fç‚_Fœ@çÓ¿Yùª §]av»víRƒ ²ß÷ ’õ‹À`‘È4ž‹+¦†ª>,EÕZÑ,·,æy±¼1Iäࣥ³Rpžùø¼råJÕ½{w[ãqÞùø~ë­·ª7ÚõlÞ;Åb_0†W"B sç2¾vïØ›¬Îß±´,OŸ9«Ž?©7•/"™iâĉªQ£F6‘Ìn'§Éiç´iÓF}ÿý÷v|½@4±ü¹÷ :}&ÍίWN§U)Y`ÑùbqV34Nò‘ãjð¾Tíÿñ¼M ôfhÍH‡ŽžP/Ž›­æ®Ú¬ÒÎZãzpL×ÂÖOiØ>qâ„>|¸*S¦ŒÉ©I²"’I¸ªU«ª>øÀ~ã ¢â>f«¤J>–ªžyo¢jÙ÷Yuü¤5,ÄÂbò¼4~¶š³r£:ÃdB2±Z¹bó7,#YÐÄ„ ðˆ@,ÇÍXHW |…Þü|6“ýRZ @>:}ö,ÍX²žÞš4Ÿ~MÜ-£™„ëñIl§ÈhC®`*^¼8=ýôÓÄ_ÓéþûïGã ìgrøÿlžÏçôÄOÈù>ø œç<ßÄ‚B|úíbºjÀ«ôú§ß“Š ø»H äÏGgΞ£o–n,kv1<& QlýþmËoUà_”Ÿ¥òÌ[õ;õxäuzäOéÀ¡cTþ¢R"DMóÖØW€Ï+Q¬0H9Nãg¯ f.¥ûSäz¨nÅö) îÇÚ‚øI‰ÆŽKK–,¡Î; ‰XsÛGr?œ"âìÇß 7Ü@?ÿü3ñà2â—•ö0WäArbY¸z]óÏôÐkãior Å—))åB>gÒX⊡ƒGRéÓïWÒèKhǾÃ>±8Ïæí ª?ž5·Fh’„{éµO¾¡¯çÿ"²ˆ/]—NžNËR6¨ ¤PÁT˜ÿ6ý¹w¤Ëפ®­PéÅä|´b¤I@Td‡hÞ¼y4aÂzñÅ)11Qò#ˆíÒ¢E z饗¨W¯^r ûAäÑÉÄ’¸k?½öé74õ§Ÿåå x|:-MÆÊêsœK'–Í;÷SbÒAjÛ¨&ukÓ€.*Q\NÑXœçGëv†”‚TBtQ¢q˜4”p$'–…k·ÒúÄ=tuËúÔ¡Ym‘·‰%eÊîHÀh¡#>û–6mO¢Rlç@ëq¤Â²»upƒHqÜ­“篡U›wÐ5mS£š–­ãëŽË~ªÁïr6lÛE¥ã2°ðëC_§…tŸ‰OªS®¥_KËK÷Ò›»¼¸+éÖº>q=ûþ$ZÀïBŠòÓD(ì—8ììÚ‹+X„v8B³”š×­J×whFeY£ Ai,™üϼ7‰~âwTE ÞM¡; —µ îcÅÂ’€%‰m½1ß.£fü°Ð›± ±"K$“«‰„'œÏøíë¬EkYØ%…@°s"ÐPýÊ eAYaÁ_þÛŸôÛH¶ÕXÇeâÜ•4sÁ*ÁRŒ da ¿ÖñÆÄRœ±¬Øø'­ÿ#)ç†c¿+ ¤ TŒŸHJÄ“–ªÕ­>MK±)˜ ° ¦¿r–´wYÐ:±ŽÅ‰-Û®4. ÇJByýé,¯`‰D}D HÔ»gtJÀ#PtÖKÌ”Ê#PÌTUtÔ#PtÖKÌ”Ê#PÌTUtÔ#PtÖKÌ”*¢Âfý)Á—Ĭa~Õê«`>öå%,>àùÝ;œzò 8}Æoáx:å‚Ñ:”×XN¤cñGw`áÉQÅoEdq ì*ÈÃ(@ Œs¾¬imzë_ýd^èáS*„Wy8FQº½Kkùæ“ÊGq<Úˆ„FpöÜy:ÈXZ6ªEï¾— ó›í ,øtB2néö®­¨"›ŽV,Yp$ËC}ÊÈòŠ~bè†E`ÈGÊñôʃ·Òý}:±&Â`¯ÌA$ ¨oÕ }®DÖ°è×m"||B+äg=»$™ÈW«TŽ^p=pÃUòí o¼M-¤E‹zÕ¨qÍÊ´pcY—ÈÃ`ÎPñ¢…0È$¢XüTWŽw‡œ@Ðø‡ñÑjñè=艾=©BÙRRH|F@…øJ ¾UaC«ÕiΪM´fË.iáEùûˆ‡Ö®¤±M=Éã³ Ó÷u£÷ëI•ÊY£ ³ÃR„?îvoÓˆZÕ¯N?0–Õ<„õ<ôÅXïpc –ÌBF tE Fê©Ó<â<]×ñRzæ¾ÞÔ¼^u)»=š1< †˜â< ú’%š/')þ¢Ô·[™ÅðýÊ2;£p¡2_ÞC™L,è²z^Þœž¾¯µhPCn ,ùYÃꆖr<¦úή­m, »Ȭ“BŒ'ÔX‚-§ÝŒÆ”“©Ô²a-zßõÔ«c Kجqðä%c¨ÓÑèAíæŒ½Y•šÔ»¸<ÿu¢•<¬áÇ_6Ó~¶?  0y/‡ƒI)ÇNÐ¥L˜¡÷^O½;µ”’CãäKªñôðMWÒªM;ˆgàÒ>)XxXm(°H¡ƒüT¡òäcJ>zœ.®P–†õ¿‘úßЙjñ\-ÑÑlÛ¤kàȘ6S€ØÓ*±2âiÉôè£ÊxeGÒ úD‚FÀܰfuªÐü5[i)OÁÈ= yr›,,ŠñžÊñ±öìCoºš×[ÓqÀfXNžya M{ó_Ô¦ImÑ8¸>l6} ;º¢Ê4j„’ò‡…ãpÌIc¯‚eò…Úµ~µ ôÏ›;Ñüþ¨4þ,Ü£ŽH,œ'~‘¼O³+j~»ªã¿ÕÈ ³Ï‚ý¬ÞÙ Ã7 ÈvâÖý W:!ù«^½ºxEÅõ˜höuõípàfeÆâõêéÑ3Ô€_ªÅ¿&Ê!]>啱ÓKÝžP<ÃD¥ÚîY²ÆW{¯¿þº*W®œ]F³¼ºÜziƒû˜?ü0K÷1&È—={¨gFÏTý_ÿR-X› ‹Æ‰%ZoŽ“:tϰÕ®ý‡ìsYÙëXaǶuÅ]K¦¨:íÛ·WsçÎÅ%%ùrú¤I‚ {“ª÷¦.TüOòëcË+c¦©»žyOÁÑ•NÙa™2eŠjÒ¤IŽˆ£ „¥KÛ¶mÕœ9sôm}vÑåE&~JSL[¤æ­Þ"ç˜Çì‹„yÅtÙøÉD¯2IØÑRFÃâ˜.àØeŠêÑ£‡-lîÂrÑ á›­˜m … r:A#™ EÊÔŠO[ZÒ̃u¶wì]Ùaá(‡Šm³ c¹í¶Û2¹ÐËKºÆ· Á•€„ò‚ýÐ2f2# ;i²+•Ïv-|³eºYÇ5@&œƒ rÏ=÷œBP9$§ÖÓûä`?ÒõfeÏž=ê‘G±5a0±h™°s,Åα²tâ |™%ž¨0 ˆ@Nâ˜v"ÿÁ o¨=ʛڨV­Z ÁåtòeécÎeVXΜ9£Þ~ûmU±bE›øæ}Ý?«¼æ5n„Ý`qb Çv@òW°iÓ¦…Õ¸Ó¦@9› F‚SóK/½Ô&ºÞ¬HÛcN,ìK±s¬`@ é5rE ´Þ´´4;§OŸ>¶€Ñ¢t7“[Áæä|tf+fÿˆjÓ¦MbÄ;5Œ?i"l7Ø9ˆÊ£ïi, ÇïÂ\añ‡1û&º-þ“ÙQ“Âfo_¶ðu%„k‰Hƒú^7VIIIRÆìH¤±À(Ç#6®RF <ñ‹.g(ˆè5&n¨+!˜B[„ ’^×Ê%î¥ï§=Ê#\%ʧ˘€t>ÿü-Î6˜Ík‡ƒ¾¶y?ÖÏ>û¬:pà€+,Ùa æñ\Ñ‚Ç:¿Îº×x-X_Kt“f×uÓM7e ‡2¹I&–U«V)þgk´@_?ø*·¯}N,ðŽ®+ÚS@2 €Ø6áùƒ¢jذ¡-|³’} Ïí>§ÁÙ²eË,CRrñ2ݬ”ì°Lž<9 —†9ÅäÄ’w|”×YfO¸×".¤ˆù8@¸¯¾új@^ã³¾IFØ^ï¼óŽ;ü¿.#öå$e……‡g¨×^{ÍþláÔY•7«c&–*Uª¨÷ßßnˆ¾ßoÈs‚+Ôy"ù&/áÐÂÍdj£íÛ·+<iABhÚ^Ñûr²4m·=öX–a¹Q.-p,÷:*Et–!tÊ –p› Ê ,^ÇÞñ%"£.‡)?ì3± ìƒþ„äÄ¢ÏçÒô·—)óת·'Íg )vYõ1½-Úü¤±xñbuÕUWÙDÊ©MáTñì\­Y³Fß&Ó=°÷5 ,]— .çxc¦Ï—sô70]Þi‹Ö©QRì5^ŽãGÓ;œX–-[PÀ_§æÂ«uëÖéÛd‹…=શ÷ S£ø6’Æb_ +_¹ñ…û©§«) Öª#©þ£ê  1[ÔgŸ}¦êÖ­kÉTãNMd¾¼C¤B¼¨Ô ×tv;Zã Ï»¨¯ŽUå»>¨¨å]êóYKäT-tM’o—m°±Lš·&˨:93¾¹!äxýúõ]cÁ J¼¨Ô);,‰»ö©^þXÅw$X>˜l}LÖXôu"± h<TFblÊ"ž¦2jâ<™®"ƒ¸xÐ Žã‰»#ÃD’}wß}· ƒÓï’%KÊxn™’ONà&•¬²`%nâW ŽâYp%Ú£q+¹6®ñp q7Üyà«ìì|‰Ìx€75îe%¯ó»1cªá5Xàé•+'c,vú¹¸ʦˀÁcü†P ¥K—¶±èòã^zXø“ñ§âg2ÈL_y2°Xa€å؉S⧺ó áô_vvÇSšâx¾œ?,NláØˆ@(˜©:§NŸeO¢ëè?“ç§û"´†ž"®7-$ ^ã_àaŸÜÉhD Âdc“ ù1#úA‘tp.‰?$œÇöo[÷›4wGz•^øèk‰ôcűÈÞ™”“¯øâ5~ñ¯ô6cA8T,þL,º (Ð¥aÆ ~kl•‰÷£üøCàⱂ…m7ž|XøoXp} ‹5#å¿s–s Wèå±ÓeFkYvª‰)ùˆ´`( äÑ BEÅ£ErWFŸþ¹ŒJD`ìƒÀyø±A³‹øÍ°ìÇ98‰W9_z &ÓŠ ‰Ôû‰‘tÿK³“ðƒâierëiU°pE{óÍ2ööš}„ ÚµkÐ%þGüMNp Æuc¸ë»ï¾K•+Wö#,Ógw0–eì¿×ãoRÿ—ÇÐÎ}‡Äùg X´¼C½ Ê zÐ#“×xn¹ æržº|5;üöå5­­ Ä@H&„fâ8ì2“¡oß¾‚€Ö޼:¡•B½cˆ)üû©FkMã.§ ÇãÈ­Gy'– ¯ñµ$BP)îB  d>ÎÄò€DãÆ“øewÜq‡ä÷‰…‰Þñ¿eïøË…øexîXn±ÈCü“Q3A¸È€ Àl ø§5[d¦DŽª2éñ˸ºÝA¸Ð. RÈuø|­q°S´k3SxþoêOì!ÿÖGÅ£<¦ô %+e`±¦ñð0RöŸÄ "Ýk<—y|aAÀ;$X ™AñŽÏ^þÙ0Žˆw|)d.~‚J ] ]f¦Ú^ãyŠr£–×xÓg`ën DBe`K$T®â Mã˜cˆÉ±~ëN*ÉÆ±öŽÏ¯ åx°L,â5~Á:öoEÕAP$äAys„]> 1ÇéÐòŽz,rÓ ÿ„„@ºŒ f<Ò^ãg.c¯ñU‡ÃT*g͇ðÍ®@Ÿ‹¥Ý]qå¬Þ´†ŸI?¬XÏÓ€ ¦{ÇŸGy±xÆh\Á”tðˆxoÎ{0–*ñ¥¥Ø9ÂÂ×Xµñ~ºšAsWþÆsÏ ŠÍ¬nm6SV‘Z) ŠZ^ã‘ÖmÝM[Ø>BðÎ-È£©ðñ­³‡+kä„YòHΑœ¥»Âõø3B»ËÄmƒ .[vH·õê‹ÆõW`I:p˜Þà¸c_|·Œ§KŸ ŠÍæï~áÚri ¨t$¸gAkþaÕÂìËk¸[kÝð¸,Y„p ÈØé iä³Yð)"lIJ¦cÝÍý/°ÆòÓêÍÒ0zp¼²¶ÕÕ·0¼–Ç ³+.­+B_“`zϾpi‚t¢ qez‹wü¢Eè©ûûÐu.•—’݇¤±täºú²:a§ àÂ7*TT´¼À´±°×XŒ³z’µßÖå²LXP„~\È*e<–ëÛ½Æ7®A߯ÜdyçÏ‘ö´R€ >ÆÂ;þÓ,ðKÒ½ã›2ÖŠ³,b¼«[kö; ,)a×AùÄ/øú[—y^¸Ö-,–§ ð¿¦}sñôߢaÍp!G÷qE }E´N´ÒzW?x‡§uDà)Æ_ÛQ‰á¾x”Ocò<+£% yè?Ø;þéÞñ1æƒ×4k4^B£MªåÙk|§ ¯ñ)ì5ž¿c¸iD°ˆwüTº¤>{Çg,}:µ’Rヲ?,¬°­D T: ëâ5¾6¼Æ'Ð’ ØžÖ"Ô]ÆÙðÜXv7œÊþœËÐsÜ@Ø98†~èŠ×#Q=•FϬ§€FcÉðŸÀ^ã·‰Ÿf Û@ Ó;~oÀÞñ1\Wl8&»‰E ៀ¤Ë¬[4ÀAÈ×]ÞTÆöÌùy“Ãk|ð…¯[áQFïøƒnaïøý®¥*åËHñôhF]VT>Èƒá²æXl¬KƒH×NÀbyo"‚~`,ky4®å5>XÐ YCjïøpxˆÁìéÿ⊾½ãkLѰÌ4<CÀ¨¤ŠÆ ^ãÛò¨CØÛ÷$ËhD ÝÐAŸÈ• ­s‚ÇZ§=OÝÛ7ÛΑDÅóÓò ¡Lk™ f°Ç êß¿?5mÚTò`:‘žùab¯ñ=Ú²­WS°lK–àE2±  K×¶Mé6øÛ²ƒs$«»ÊÀ";£ì'(&tiˆVó Ùk<¼­/ÿm;ý´z `Iµg³J$±sXЇy ã§8rÎ[‹H¡qPù¦Š×³=@xÇGüqãÆI1…èᇦ¡C‡R||¼u &š è7° a¢­Ht»K<A æ Ì5­S†ÜÛ‹néÒÖ/9…?A#Æ!¡+@…bìó%u«;ǦeL&UGçÓçeµ„6A9§b¹ÒBœAÐE†”ò} þ´Æ‘{s^$‘sØŒDÏ9|ø°„bo²„)ӎ®‚eJòë™!vׯ×ÑXÚ7©EÍëTe[o GʰõÒ!Ë=³û1±T([šÖ]KÝÚU‚ñ¡ñމ%»ëEúxÐ ¤½¬¬ % {öP<õÈ..+œ[uêÿ2»˜Ylœë ­7ìÉÛD¶'1³ §Î¤ÙQ€P¬ Ìò­÷Á;>Û3AñŽÏÚv³üÕ¬YS;Ö¾/Ȫï©wþ KzD#}KŠŸe(㼆ˆÑŸˆHËʾÞç\¢¥š d2µÇá ºw|îrl7¿ “Ók¼ÏA9Ð&N,&®X]( ´¬”¸î´pM—ypsÇ‘mmÁvNнã£[35R¿~ýGVÔÅÉDd·Xì‹ÄøJÄ äV~p ›Ú+½i»è®'ØKÜZ ×e¯jŠŸìÔ±cÇÜ=Oæziû'%%EÜàêP¨LS;›4¾®gÞ¾'L˜ Ž?ž§l·,zÁàÄǵ»+¸ÆÕÁWE‡r´î¯ï1jÔ(‘y^2ŒÝ(ê 0ÐBxÒ‚ü Ø•gj]¡¡Z: ëÖ­[«ï¾ûN¢9m57ëyc‚@¦a{°WTÅ^Q…H¨ØPɼ¾öŽ0W^â·±±$óñ=11QÝsÏ=™´º—`j Ó@‡w|Dñ¯“Y½ïB[ÆP9è.ÌÇù (D*ÔÄ Æã¼S«ùòŽ!w[f#‰9éÂÃh55 Uµ8vª&’Ùíè}9Yšç5kÖ,[ïøº<ê2f ¤+ $ÒÚÑ›Å9..NˆdvAÙ‘Ç$#pð©S§ä6úIPßÓ[fH æ ¤¡˜ÚhóæÍŠý3gÒFþûA2M, $e}]Wïó–È3$§}4wî\Õ®];›H¦}ä|,硊cXØ’ñõ½Ë>è­ØÈSÒ¨Lûë£GVÕªUËD$Ý¥5jÔHMœ8QŸ*v•îíÞŠ_ äIi´f·–œœ¬† ¢”ä)[¶¬>|¸:q 8çÙ9Zjî–ùš§Éžu±aÃúúë¯é¾ûî£êÕá^³2FæiA„ÜA È í„»&{x*ö8lDËøhl{ɽ.iÑ€Døqðç¥ÜIà‚#PîÄå픀×ñ¶]IÀ#+qy™ð䔈·íJ\‰ËË씀G §D¼mWðäJ\^f§<9%âm»’€G Wâò2;%àÈ)oÛ•<¹——Ù)@N‰xÛ®$àÈ•¸¼ÌN xrJÄÛv%@®ÄåevJÀ#S"Þ¶+ xr%./³Sœñ¶]IÀ#+qy™ð䔈·íJ\‰ËË씀G §D¼mWðäJ\^f§<9%âm»’€G Wâò2;%ðÿšX?ft1¥IEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/72.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001065515232633614033155 0ustar runnerrunner‰PNG  IHDRHHUí³GsRGB®ÎéDeXIfMM*‡i  H H1FïIDATxí[gtTǾ .QBÑDG¢šŽ!Æ>ÇÇT'€b›S|hŽclŸÁ´Pmºí`ƒ   ÍEØ£J1!ª  Ôûä~³š§§]­Úî ~htV¯ÍÎÜùî7í»ok NT“Ì"`oö‰ ÊÒá›ÚµkS­ZµlX›eEW+@àØÙÙ•°º  Àä^‰ Ïñ¢vuÔ `òóó%SNXX9’–/_N¹¹¹§˜U6U¸6Þ¦‰ÑÊ¿s玘<Ð0yÞl²:@ªA`ðaÃ40ìííKt-=H8×çíí-Ö¯_/T÷Tej¨Uã‰URÝjÁ‚0CŒA1¾F×C~u¿[·n"..NŽIÏ $‹*((ºå爘˜1}útáää$«ïFªñÆG€–©ûýû÷{öì<~å Üú:mM¦*oæ Àe)†®5Ú\7Ów¯¦M›ŠuëÖiÝ«¬ò«ƒU• Q)âÊ-qòüUu)bâŽG)òº@7½ƒ ]ºt)˜¢gè?üP<|øP~_9õí:*ž¥gÊûéY9"*öŽV'ØdK * 2–%§¤‰yÿ'\^~W¬Ü~X3vß©‹böšñcØ‘•“+ï+@³²²Ä²eË„‡‡‡”êN£G.\ÐÊQ'Ç£Å+ïýS´>K(5#K|¼~¯X½û„¸~×&ò£»ÛbõTîJš+5lxÏÄ΢o‚~¦W'/¤ßÿ@<-‘«‹3·Óœˆí¤B¯ÐÊ]!q5žWɆ*œœiΜ9Ä@ÐÔ©S‰»ñ Lû÷ï§}ûö/ÙY†=Zl|"Mœ¿‰Æ}¼†Î]#únÚ~Ç*®Ó‘n'&ÓÆ Óôý‘z”’Î{ºZ„ìµf2»C5…Ø7qÙ¨ˆËôùöÓ/¯“›‹yº×¥¤Ç)%¶0FÖqu¤'©™´=8‚¯ÄÓÐþ¨mÓFÜ© ©yóæ´qãFš9s&µiÓ†\\\ˆw¹ÝHIÏ¢µÿ ¦-{OPJz&5¨çF¹y”Ïvèg”ð˜xº—H¯toG¯õhOÎŽ 4r³-VØ› 8ר›‹· ½'"¥ÜëH–p—“{yÓèà`oGŽvtãÞ#Ú°÷$õêèCƒûú’7šÇ âÅ£ö­Úµíè»C§hŶÃtín¹×q¥†œlDÞÒ’táÆl€‡C/Ó¹kwip?êíÛ’¿b…À …>÷uZ»óm ~Fö¼«‡ô¯¯÷ÆäÙ 3ΞÙ`ž™ªÌÒŽŠµu¨K·éÇðnGi9+wÏ„AêëðŠ{]7ÙÍ`´¥ °ã2]K…ëºn‡ H9x”x^™ |¬E·F2a¾P^cXl´¾<4ßx–ÁuU˜©/×øÜÀZËÀVe– Êdî–éÇ ym.³÷1[链Ný}[œW {žáxD9¹yš]¸æu¶œ~µ›œ`·ãq*#+Gc2ºQn^¾àù±ÍS¥‚ÁðàçiäÕ >ùµn*aXÚܳcÒ3sdžªz Ç žÅr,ÖC};·%'^÷ ë` ÷iÒ2rrå oÌ.k#fv6®Þ„1Ïx1ö¼3â7ôÉ»#ÉÇ»‘Ô›±îèÑ¡95ó¬O¼Õ  7îÉ"œí¥÷¹mJ(;7¿€§ìTòkÕŒ>~ן~ÿF?9Nñ¦‹ìÙ†É#Êⱈ«ÒQ.ÎŽÌ´Zœ§‚•TÈC¦rRÞÌÌÎ!Þ_Ñk½:ѧ“FÑ€î´j°mPÉ‹’ï íGýî<@ݺŸ,½ŽY¥,ÀLtŸÇÏ2ÈƒËøì½ßҌ߽!g8 â¼ãWUH°úwjEÝÚ4¥s×èÌ¥›”™K.<#V•µZáF'Å-3z€Kx«Ù§©iÔ±USšóÇôÖÐ2'èV%$$мyóÈ™÷ZóçÏ'OOOÙ:¶lLí[xñBð6‹Š¥ägéäÆ Aã.¡;¥ffñšNÐÛ\þ'ý©móƼ3¬¢±^bE€¶nÝ*÷qþþþÒgG;òÐ…úðÊùǰºx#A®­Pk•Ä^+‘Ô®ýhè%A=ß>þ³/æ´Ý´’AKÛCËùòË/…ÜUÞ´ÌltêW1wÃ>1}å.ÁM­Î³— êñ1lÖ2ñsTŒv_@SÒK·ÜhÝÿÅ‹UÞã²»8ÅÄ%‰5'Ä”e;Ħý§å=fŸ}ÄÑ£G u±P_GUÏͤ"œh$Œ‚'½Yšñê ò»»»‹)*¶€A8OKKcÇŽÕ€Ad¨rÊ:"äZ•g„ "“ÕK”ki÷¨fRôOJJK–,Mš4ÑŒPVF•vÔça‘L¬X±Bê͈PèY–r|^üôÓOÑUUÀ-$c3Fœ9sFärTõX#™ȸpžÎÅû￯1”ÖÍôÝKEJrES`` èÚµk  hêh LÏž=ÅÁƒ+ZE¥ò™¤h‰è¦M™ ‹#ááábÈ!%ƒ6޵+«‚ÏþªÍŒ˜±Îq„‘ $5`c Áo~ˆFiõ(Fª#À«×®]+hø¾5,‹ÀÙŸ[”LRô¿t‹§Y^³ì8!X—•èC9»wï~~~Z”w e^3J-Xˆ“l.&аèÚs÷Å?¾:(XÔî©Fݽ{WL›6Mc*œ€z0FaÒPÌTclÿöàIá3b–Àú I-´Â+ybv³êÀ«hl !º¯ÚBÁ¬ÐåÀ>Ötx…ûæ›o/âhñâÅT¯^=â77ˆÇb†/ä¤lмÏ2²éŸ_í¥×§}N»…± ïÌbVñÞÍÙAJº;ŽDÒºÀ“tó^²a\$ðoذΞ=Kƒ–Û¼W„÷‹Ö¬YC7Frõ|"ò ±”f,ý–K“Y€TÁhS›=ï$7’R/ å´öö†¶jÕJe—{­Sçcéóo‚ˆ£®„¶^ˆ×2êNàÔ#C6Ràc?‘±¸ÿ*‡rœxŸŠ<ˆñ"÷€©™ÙôÅ.*ì ¡§i2¨€ÈÄ~äµV* U B9×ÒÍÀdêãçCCúúQ]ËÅ„‡O8vDÇÂy“[È¿:²á<•ËbÊÛ?¢ñHRàgÖ<MQÊÖ¯ukÛŒY‘/ctÌ–Å£»ÆÌ¬_"2D[X÷fVY3Uª4åiˆâˆy¼Jç¯ß•F!†öݡӴy÷Q̙깺HoªFWÆhÅZÿài*íùù¼TymDi<¦}´f‡Œ¬z²`‡{q(ª2µT,o…¤/NÑ H*9Ø×&7Ž„H0ÈÒ 'vˆ>Õç(HžŒ¸rˆÈz½I_…v^)iß*:1fŒµ0úz¶ñ˜‚:ŒëÖÇšçf/08[;qúbmQ¬6æªÚ³å³—X–°ZEE ñ9y¬aw?D(ô]µªÁ÷¤tËG,'¬‘LRœÁËž¬ ³(ë±Ä#Jº}øäù¶ö&¯†õ´nÓŠ— k²9|d‰T €Q¢ è’ý8bd2H+Ê{{Ô§Æ¿N!Q×è´NG¥Æc‚9CŠ…øtjįËÌ›2†¦Cˆçø9ÊÑÈ] ú5Þ)2üvr9Ð*’ÀL;~;D^íéGŸþy4 ä ì´Ä±¨ß e—Ío[8’ÿÀ.ÔÛ¢øú•C9ЉC90Ì\RÞ|Æoˆ¤ ÃÊQ›f^!^z»8JÑÅýöÍ=éìå8¹txÄ¿œ!y §2^ !"î¢uôñ–A…·‡ ”f©™Öœ½o  M¸KLÖŸbâ“$Pq‰OäÖÀØ;À ãL6Æà êáKŸ4š^éÑQ³Û–niÑ¢E4hÐ ù"¶%Øß èÒšºó‚0ä\,‡rnQfVž\o)V«B:ê~Â@bÏõéŸFÓÌñƒå¢ö˜c2z¨¯Wêh ”‚Ã8TˆäçÓ„:¶hL¿Dߢç¯s('ƒŸÉGòÂÎé¼°ëвýeö[’9x€î‚±/Ù´i“ÜÌîÝ»—¶mÛF .$~V–áâd/»]o_Þ _áý_3?„‘¥=Óù3~pÉÌö-›È‡xC Vc@ ߬ân|…¯?´¼å@ 9y¡XºXÁ/tþuåv“Qvv¶X¹r¥‰¯×v ^ºtI+Ÿc9ò<še—M áYI^?|’*ÆÎY-Ž… #)KW€UNÁŽJ'½Æ¢—6y&2) Ú4"öŸüè…vÜÓ+|ü¢§HN6„…ôV}}ÐôN3©Ü 7ªê™ô P¶¨€ £F* S_»V€©£žM,›ˆ-[¶¨"µÀ`ñ∋þž-Ϋ PiÆ ¯ò˜¢aÉo5Š·Z„¢4›Ë»gU€À(„`á”)S´¦€¥ üŠ=8‚]úî׫W/±sçN‘‘‘Q*SËk˜µž[ c£BCCK¥›Ì…rôÝ‹eT±zõjMˆ7.³º¯m˜¤^\@ƒÀ___ (ˆ~€x3f̉‰‰ú2´›Õ|b€Tä,Ã])==]ðâP ªº”êbøEÞâP o‡”6¨çÕy´)@ª!z&ܾ}[Lš4IŽ9:u’¿ Óç{Q€Q6Õ {Òæ Õ0£äXP"íÚµ#77ÃOp»/Tª6€T«™!`­öJ@ã1I=~áŽÕB@aÏdÕ}“*ÜŠÇçÛ`Ó¢^¼NoÓæV¾ð€ÊÁ¬ €ÊA œÇ5 ª¨Êy\à€ÊA œÇ5 ª¨Êyü` *KÇoIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/76.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001126115232633614033147 0ustar runnerrunner‰PNG  IHDRLLÇ—Q+sRGB®ÎéDeXIfMM*‡i  L L¹ÇàIDATxí\ xUŵ^äý$áQ^‚D 塼«P4‚øA( ê½ …‚ЖVü@¤å^…XZ)­z©ªP$B("Abž„D äMÞ0wýëd6;'9‡œœBïÍú8Ùsfï=kæŸ5kÖc-5S½p«÷“ðàõëשªªŠpýw¡M!aj€äîînàtíÚ5rss£-Zu·cá–J€‚D€uøðazá…(%%E¾£÷ok‚„Ý b 6YYYjöìÙŠ% úSùûû«%K–¨¼¼þøcÕ§O3P¼k7|øpc¼‹vÐÞí@˜ÜñãÇÕ¸qãj€ ]Ö,QÖmFý3Ï<£ÒÒÒtS·ÅÕå€AðIJJ=åãã# ­³¬²þÐ4¨­ZµR‹-RÙÙÙÒnSKšËƒÎÁ ¶lÙ¢ °Ì’c P]ßÍK¶sçÎêàÁƒÒnSë4§0UÕ Ý¼^tv½_|Q9"eféÂæ€M¢¢¢Bš¯ª²lf^׸·’ ˜¹óæ²€yéœ:uJMœ8ÑÐMfP´t™õ–ã¬Y³Ìеk7@©4™'fšocƒç0`ÝýÜ‚bõ›7ÞSÛcb~>•®¶ˆWe–Ò¼SîÚµK 8ÐËÎz‡5j”bƒÖhOÛc9WòÕœðõjÏ‘o{1ߤªÏ'¨ÊjÉ€f]X¨·¥Ï Ï"¹³ûˆQÄg(ì—+hÍû»¨¢ò†u^Á–úçGèÍ-1t<9‹" žwK:zô(­]»–:tè u<¹†††Ò¦M›hïÞ½tÿý÷-ï±pÑ[[¿¤°Ù+è-{¥rƒÿ”–WÐöƒñ´fk <}N<žB_ù_£e4všÆ€xâØual¹3ѱ‰ôZħtødøRËàÀþ:àëMW ¯Òû{ŽÑ±¤L;ôêÖ©-ŠýEwš?>M™2…V¬XA;vì ¶úiÁ‚Ä?ñ’#OÙÓÓ“"¿Š§?Fì¤ãIéàOÁÁ-kðr«æu1·""Pï»: ¯.íZɈÐo77×ú¦vÓåîÞ‚R³rèwÒ¶èXéL›à°èji-¸ÑQOwò`Ó¾¿DéçÒ ^]é‘ÁwSë–~Ä;µk׎֬YCááá” °NÎæIùŒ>ÿ× i£-O 3£âÒ²ºyyzðs‘CiÙ—hhï=¨µô÷‘ç!q×d0H–_Aq ýåÃ=´n[ å±Ôó€Ñùªkˆ6Ø^ÑZ2}½<¡'éHB%¤_ ‡ú÷ ÷öàwI€ƒT±ž’¥{)¿˜þ¼é YîÅ%eèÏÖ-/Yðâ¾Ø"áÅ<|½=e9ˆO£oÏœ£‡„Òð¾ÝíöÓV›¶êë ÀŒoÝû5­Ø°ƒÒXº‚ü¨uŽ;o1Òm5Y³³ ò÷õ’åöÙW§D·=ö@êsW'í:/37Ú¸ó ­üÇN:{á åÇã/÷j¶fÿ›æ•PZVIÛœ¤Ø¤,?¬õ¼³½LT†3TkÚ0>4ʦý׺Oè̹KÔ®Uè X c'ú„Û ôó¡ó— è‹£ß1’Ù/aåýßë¶Ñ®ÿQ«–Â@6”,:¼¼)3ç EÅ&7´©ZïÕÌüD¿aI±)á’]²†Áx±ÎñævÍ F=x¹‚0ñ/n×Ud0(}-æ®bˆvdÉW/UÝ.x¡ÞÕT/gxج¾ ;§êË[MÓ“S€aç ªX:4A"Qç¬rÕíé«Ìü’¨ K|\ÍK·_×µA€¡ƒ°± ÙÃFý£ÉÏ›wC®+gëF£³Rû ¼òÙ¼Áòjéï«Y‘ï¼ð2ðqµj0±*8¬ a –UTP^I9 íÓ^~îg6豥䠞wÊF±ûëDÊþ!|Ø6€! Ž€f'JÊÊÅ1 ½üìãô@¿¼`cøúPÔ±$ºp¥@ì0؆Žòr¤_õ ÁV9¿B:ýˆV_¿ýöÛF:Î;–˜©–þ}§úó–hiÓ±2ˆn Ò€±²UEUeå–@`Eu@sÜJõìÙS:ŒN›ãõ, F}¿~ý‡oŒöõ`J¹Í¸ä,#¼Í¾Úúåׯ uH/"OÂùJ æ…É1ó2dˆÚ³çÆ$h^,µê›”,—kfŒ®ŽÂ‘#G"¢ºóè°–*]‡«õ`ƯNœ8QG‹¶«¢££/ñzñÒ ‚7ÇÙ$ce»eçîØ ñs„ˆù샚;w®!Iè`}RfxF?Ç‚âs*##CÚÔ‰Ý}ð‚T$$$¨3f@5„W@@€Zºt©¤æÀÇ•™&›€a½ƒ2?ÈDk òòò2ʺÎÞÒ°ô3cÇŽUÐh[ëÍ+''GÝwß}ƳÎòš>}º*++»5€aæ1(¶{Taa¡Zµj•q& ˜—Ãúj~¦}ûöŠcùª¸¸Xt—9Ó^ÿÊ+¯9MðÒRjݾù»™tÞÆ,ð±–fðk(Ù”°º<{ö¬¤¿0tÖÖr1/Eè9Žá+65¤ISƬ.F]jjªzê©§ i/Í× ”™vÑÅ‹ èhÈœž3v²`°rÖ'lpª¼¢aQUmNà Ò`#GŽ4£•?dÞ¹}ôQ…³š Aç~Pý(ŠÓc–ïWKËUó*â ¤w8”m)ð2K”}bb"^‘4àu–XP™lÅ!v¯Úb’ú†þ± ÄxÙú]êåuŸ)Ž‘³¢¶tÀ<˜œ3€Ó3ß»wo…Ó:š´™SeÍæÝªÃ#Ï«ŸÌX¦o«’² µøÂïpB:/MË-3¯wß}WuíÚµ/˜»wï6ÚÒïä]U+ÖïPÁÍR#ç†Ë}¨gɶ¥Ï]C¾„cãŸì§79÷÷]Æ…~Ü“O>IqqqÄ:G2?lħö‰¥Š&Mš$1|QRfŸî£‡ç„Ó’¿m®™ü9_È–þGûâhíÇû)5û‡¼Ø|î¹çˆMbV\0ä5ßzë-9ÅËŸ\iŽ%œ>øâ+zhör çÌ¢)ȸŠlžq…£½êÃ}t¹ XBÇlÀŠ;Ô·['ÉýujÄ ]N`°o:}ú´ ®D ´ëóMr&wüS⌵¤Ðž3>¤w7Úó×Eò.²ôÆæ/%†ô\i¹eðýÜY|ÄvpŮòœ‰…‹lIs?áVŧRø†OéÀ7IâìúùRnQ1=ÌÑ”í«~+ýw6ÝvSç›ÝAîìu ~,ÒW)Y?Ð}{JÒ–wSêÑ£‡tϲ"æ„F>­þg$½·ë•±ÿ̉XKÊ ù¬¬Údá¥È‡cðxNtRf ¿·;…õeÜ%5׫W/y™µ•€•Á‰š•ïí¤-œåB4£MP€L«æU›357L7ŽA‚7¢ ¬ hßñŠOûžFqÂtðÝ] 廊J+*é½ÏÑ››wÓ÷s©/o0b -yòÅÆ´B´’¾ûh"±*‰àþ¡4¬y“ uÛ£å(Á¥¼Bæå/‘Ýrçøœ«É¶³ÁI&€SX%¥rà» D',aä2ç…¯'dÄ‘±ÆÐ5X6š´YÍ:Z¯‚â2Šøâ(æL:ïŽÂoŸïXô§DWŠT1Ð åe³V7L¿Áxx¸‘¤á,{û»8e^ÐmÞ|Þ‚7oÝÉú³# ¬¥Ê¸ÙH…†þ`å`©š%Ÿí#™e[zª¡ã•p‹xÙë£S€Ùkøÿê=»€Ar 1®&IÏYµ >ÇËu#° X%‡wù$¡ìl® l €…A¹5F)î+¯¨N͹`ްãƒôÆá*ª0è&0›6r …viDZvÄÆkÇáëÛ € ÅŒƒWØ?¢?½ñ›ébžÀVòòò §F¦­ÙT(gÞðƒpšr8ž5môPzmþT‹®­o‡í„Kÿâ\#;Ëœ½eŠ¥‡ó©¨v­ƒ8·8ŽæNÅþ©·ø}žlÍŒôôtêÖ­›°„û3¼_wº·GgíƒWÂØKÍáEáÅîåü"êܾ5ýaÖ4ë‰0ñNôÄÖÇ`Öã¶w­sIêÔ ˜ât߸û{Ó‚)a4€s˜I}@?+Þ‹cp‰fŒAûÿçeIÆúz[æ`ÅÇŸ¤ &ÿþˆž}öYÊÌÌ_ràãIÿ´ýzòCÔ·Û¼”+EÇA²Í¤u¢è)–Òç>Ь[J󦌰`Äj]f~Ï©2KQ½ˆ—E€\òÙõ—­1ê+?P¼d6碾SÔÏ~÷'õÕÉT£žs‘R¾xñ¢âÀÊ:üÌδZ¾|¹Ddñ Ž•¡|êÌ9µúÃ}jÖ뛤Œ:Ðòww(ê7UM]¼VÅ%eHþ …þ6A:Dg‘áot\ŠJH·DSQ÷Iô1µn[4ŠB:=‡8BÔ;v„ÉGõõHßmÞ¼Y¿nŸÛs,IqØÇ¸÷ÏÈCêý]‡ŒïTuߌJLógq×Å:¯ÈhŠŒŒ¬ó 8\y)׈Ö"‡´ž&L”-’I¬oìÛV#õ¬o0`º}ë¸9:¯3ÖøEÛäÉ“kH€1e]FŒ^KÊsæÌQçÎv:ê«yƒ—u¾×XW§³î$ ‰ˆˆ0€¾Ò Xdë;r:?€wñ/D¤]³äZó¾ß]ÀÂÊç+êÒY¶@Òõfp¡Ó6lØ òóó¥]´Ý”ärÀ¬ƒåÄ'z i1§Å4@úŠ{zÉâ·–Ë–-SÖM6é÷FLgp0ÂØØX…´›ËMƒcÖ[¸ÿôÓO×øé²NÏ5)RÕÌ0ðÀ2é7¤áÌÀé2Ÿ © €7õÔ}Ñ×FL3‚²Ö »¤¤D­\¹Ò8zòoðß/èqØL³ñ¬7 1h“Gã|ô€ØF#ä7‘6ãNI†Š•~£ðvE£·0tº.`Ì@ºb`ÕF“¦ÃúÉ(Þtõm}mRÀnkdltÎnxÇÆ;ÿ¯«›spú›kÌA|¼Yšso–°fÀDÀÁÇ›%¬0pðñf s°ÿ!S|ªåÔIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/180.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000003023415232633614033150 0ustar runnerrunner‰PNG  IHDR´´=Í2sRGB®ÎéDeXIfMM*‡i  ´ ´VÕ–y0IDATxí]€EÖ~ä°d#ž„\¬ QDPDÃ,êÝ(ˆéŒgއxÆ("ø«DAD\@ X`É yaaIÖÿ¾7[MM33;3;Û;3Û³SS]Ý]ï½ï½z]]õª€âDnr9'('t¸d¸¸€vWpWât‰qíb ®8à:DqâÚ}Ž‘iVw$³âsçÎQ䃼›¢. ƒ‰r¡B…hÏž=tæÌBåüñGWp«8ÅÐ8 °âðž8q‚^{í5jÔ¨µk׎fÍš%å ¤³gϺnH>:zˆ»R7Ù8À V R«tüøñ*)) / ¼>ýû÷W)))V=ó«ÐÍ8ÊX7eq@fwÂâÇ¢E‹ÔÕW_m¸páŠ}hÅVY¾ð„„õôÓO«Ã‡Ëyve°.æfဠè,6›ÖuÇŽjàÀŠ] 3¾b»…ÖÇQ^»vm5jÔ(Kh¸ûØÖo7ã ò= : ¼ÌÌL5|øpU©R% ¼&hí€ÆoXlXn}¬}ûö*99Ù’,>¬¶›œá@¾´Ý5øî»ïT“&M,`š Õ` ô n‚ÿŽ;îP©©©–ÍÀ*t3ç@¾´ÝO^¾|¹êÕ«—au7Ð1€ZŸ_¦LõüóÏ«ôôtî­{ƒˆKÒ½ p _Ú´’<ž¬†ªŠ)"à……õå'o c¦µ®W¯ž;v¬9׿¶XñL¾´é'ç}çwT•*U,+l‚/HC=f÷¯»té¢æÏŸo Ñõ¯-VD,×€¶»S§NUÍ›7·€¬‡áBj¨õMÿ ¿÷Þ{UZZš%D³ç° ÝLXˆ[@›ãÉ«V­R7ÜpƒdÓÏ œ9©oÞ·B… êÕW_U"8³ K’îI¸4¬²Nû÷ïW<òˆ*V¬X®øÉá‚Ûtq6l¨&L˜ ›ìõ†Ò*t3As ®m‚yäÈ‘ªF^V9\æÆyvÿºGjÙ²e"8“Ž %éVÄ  Ñe˜[Áˆ, ;å'‡ zø×z¤×ÀÈËéÓ§Ýá½04nfÛ±Åc<ñè 4ˆêÖ­+¿ù‹4’¶?h3ÚÆþ¾4­wïÞľ¾”iz¢­ÍQßž0!êOÃd¡'Ÿ|R&±dŒÖùhø˜o"›6mª&Nœõ<…ÆËa2Û[¿~½Â4O bs¤A—9ùm>V®\Y½ùæ› sHÜ‘SŠáåãÐ`üisènæÌ™ªM›6°ö­Ñ;h0ã›Ý"µk×.Kj¦Z…n&dD= Ïâa/Y¥;g ÕÙ«Âêi° ÿá‡::úák4cñâÅV3½-„R‚þ@ uðq“‡Q èsçXP!H);ÁjPã’ñéâÅ‹‹Å†õÌ ÿÚô“1Þüõ×_[¡=€˜­ ee Ô¡ðË~~¼üŽ:@CȦ0'ü¸Pmß{@øm@çÓöTk¶ì¶äE”L7dõêÕªoß¾–)ÿÚ¼ÞòZĠߢýºÇÉ8™©>Ÿ:OáÉ4ÄšþÕ›w©íûY$ës­‚|–‰@CXgÏžï^¯Ù¬®h„Jhw·Z¿Õãkš`Õùe¶«AÃÿ§¾œ¹Dý~ø˜%¾@‚¥1Ö N›6-"s ÷$X”úÓŸèí·ß&^ñM¼’E¬$»€çàšmÙ²eÅ"óêºå–[¤í8G×±Ó ŠÌíE¯túÌYzÿë©Óß_¢÷' ÖGA3hG½`ꢷJ(Q”¶2ÍNü…Ø £ýGŽ Ÿq þ`¯‹õu9 «{-T€V¤¤Ñ+ܽÎ`‹T¤p!ªX®´X­³ öp‹k-RˆRwî§vÏ£– þLÝZ_B•IËB°P$3œ°¤P6€±Y³f4eÊâ7xôì³ÏOA•꺀ŒtçwÒ3ϵoRW(QŽàš)kz¦"¯g°¼öÙdÁáˆÒÒ#ñKÀˆ='˜í %owæ°¶œÇ¯¯fkÝ,7,”ûäU݈ÚÓ½òxªt¯ˆøö·îÞŸÕ½&8n‘²c¨)ØL~3iÞ*ö¯·S÷VIÔ$Ñó2uF®/¸´©È‡Ò3äÏ GŸúá«çdäæ‚F @|g& ÜÚûÜrÃÒÅU*ÈbÑ¿Î1 aÌdŒÙ,î^1 —×Ýk(ò¶ükØ{0FO_H kU‘§š•Ëu)(2ÀQŒÞ¤îØËcÉ Tž‡ =®…Çâu1+wÃx˜“ýëvÃR³Ü°nì†Á×µ”#@£kF7œ’¶›ýÄ)ܽ.•ßxà‹†î5XahÁâí$œŒµ[÷ÊÃS›†µéª–õ©lB Ÿ—Үɼè¥O'Òüß6RÉâxà-Ã@vÞOöÙÈ Ax`wÃ:³Ö¶q;Þtq¡(¨6 uw´vóNºúþ×£º{ –ÏZ°%‹‹;{ùF~xÜKCÿÒ™ZT|níWko9û?ùžÏÑÅ"ÏA}ÚË2¢™KÖÓžƒGe*',&ÅJ‚‚beD ÌØ»±K+¡ÿ’ZÕ|NÝÔnFbõJôð_»ÐÜßR)yÅ&Jg`cú+ŽëYƒ±ÂƒH´3* ðq F:|$kV¡‡oëI·_{¥¸˜ŽªC ø"XÏ‹jÞ &5ª]•æü¶‰æ®Le`œâ9Ì,Xþí‚EÄ#(r+òå—&Ò“¬È]Û\*äêå]¾hGÀÀ:Wµh ¡~\’"aÐ0•µü‰‡)­þè·—ç) =@Ut˜×á!ØÌ£wô¢¡7÷  ¼t ‚ÈN˜ F[j€A¯æ5Íëÿ™~dk5‚°ÒÅ£T°ÚO>ÀŠ\»Zevkº«wGq¹d^¹XíÀ^¡¶Ô +×ûuiN­’.¦­“%UPD‘Š¥ÞÊÒP~ç  /è^¯jEßy%Õ®&m׫A ¸P˜ÚÚhAjbõHW‘Ý›»¶äÓŒEëiãŽßeÍ\‘(¬çŽxeð"Õôà-×Ð0þT*_ÚC?÷JþF7@¿vœ„k✬ÚU/¢†¶›Ý0,¯Š57L˜âÇ ‹‘yú4f—àòƉâ'vÓÝ+w“ ï+™]̼Y×l]ö/÷­$AefqW¼÷PºtÃy%ØóŠ|Š-æ9êÝ¡9=q×uÔ8QœŒ0>†êVXm¿í®®gC×Ën˜0$Œ?Žú|÷zŒjU«D/ß׃\×A"fZÝk Cxfzz:ñVT´hQ0h$X–ºqjòÐ4oU*ûª§ey„ï”íQä3¬È™Ô’ßÈ×´k*"CŒ"ƒ~ÄÖ«T©’XiOÏn±õo»6sñzŽq·]Ö=Æ«íÛ ›#óGÅ`<Â~2,ǃ·ô 9=M»¡³€~2©]󮺶ÄÒgŸ}Fˆ+׺ukš>}ºç<>‚«džÌyS°à5—7¤yÁk+ŽFб[Äã@ût=Ûéù©]‡Gޱ›@ü…f}ð„€î>Pv_mý  @>~ü¸‡ä½ZtþöÛoVˆ_ðÈWÒ<°á†ÝÒ­¥Œ%V¯(k%ñ úã)å ! Œ'ŸàE¦ÄîuæûÓ+ƒû‰¯«„¤n2BHµUž3guèÐ @Û·oa"êþM7ÝDk×®µ‹s|%¾%ÀS™ýÔÛº·¦\%ÕªZÁ#XD¤‹ë6›Òîוù)ºï/]%ì–G‘RìB@iEýà#‚¨7oÞœþõ¯oxDS§N¥~衇è÷ßÀƒî@ÀOlÖ‘n½º•üF¼êp‹ Aÿ%µªÒ/¢¯_ÂgµÄJkEöS‘y£!â ‡¨]»v4{öl¡J¬]+³îîÝ»éþûï§+®¸‚f̘qA]»(5`a­=nX#z°ßy7ì”~£ÀŽ ­îõw¯ls·:g$º×nÙv¯2¤»×qãÆ 5ÿèÑ£" ]Ç.S°pEþþ÷¿Ó•W^){œì&ìçš‚Åþ,½Ú^JCnêDÍêÕä͊ΜŸá }¶‹ÁÚâzøuué’%è•ûûÑOÿ}’®ïØBºyñ“³êØNÔÊyâÄ ‰? ÷âÓO?õRd»ÕOpÜ´.]ºT³ÿå/ñrÃÀ#_I÷D¶—Æq틊éËòu­¨*cÆ„•˜`9oÑêTU²ÝU¦Ã½ê¦ÇÞVËÖoµ®‡mÚ˜a> Èkëâùóç«.]º ?”6­daY¿u¹¿oÔeÁZõ98¹JII±îÍ·òö ÚÈ>­U¼.mzküluÿ[Ô“#'«ôŒ“r mÖ‰]*É~6e®¢f7«*Wß§†£vì=¨«xí·hfep-³M&LPIIIVûMZüÑl–³òZ›‡–(QB±¦Ø “»Ùïå«-š6|/X½E½ôùt5ðß_©ÿLøÙ^=ªç +i@Ï]ž¢šÝò¤âXÖupL3È*42¦ ÓÒÒd??-ÂÑ¿Cý6[ªT)õôÓO«#GŽÈÝC,÷4jîÊMê•/~P‡ÓOXçk24 ?úv¶â Ô’u[ô!ÙoÑÀ¾UŽ Ú`nþ‰m’»wïnѪ"Ûùc*ŸÿügõÑGY²ßÙb{µÇüa*5ö<Ĉï~“loÖÖ|Ø€Ö¶Š_[«ã'<;‚!‚¿fj†r÷ªxO@…V!»…µ *Ôߦ`ëÔ©£xÈÏjV(‚å­#ï—h«3°¼Í„.‹¬"ïܹSÝwß}V¯’SE6ù^B1tû×jÖ¬YV;í/ŽJ&°?éõÛºH”f´m±íåøm·Œè^±÷µf¸ >]‰o»`yèO%''[M E°ÖI~2Á*rff¦zóÍ7UåÊ•¡ßä-o9§6lØ`Q`ö”VaVfɶýx´þÎ1 a©üY%_Ýk=,Aæ´{ ôpCLÁòVlЇ-™¬ÿGÎþªØéç-âT“&M¼è–†œÔË™f±)&29´?*MØ»W“Á9T¨çÔ°Ú87ËT<4¨ŽóìnºCþh ¶ÜdÞSñÛ=/ ëv„JCNê›Jª,íy]/ 0µŸìd÷Š MÁÖ¯__ñ›8K¦"Z…!d4í8eïÞ½jèСŠç˜óJ‘MÞørÃøM¬EaNé·.”G™ˆZÓ1yòä<é^MáÊÛËoäÔÂ… uóÃú†2#á›7êTU«Vµ¬²©DÚåÔ1»v×]w)Œ8éöK&ÿD ÐÚ2ïÛ·OuíÚÕ¤S~r¸@€`Í6##Cz Ð`ä ËŒú+V¬P‰‰‰1C?M+”¬Z–ÁÐmu"ò¦Á$‰B<ö+;®6jÔHʸ “7YYU¢ê íe@Ë74 ³ø®½öZ*Rij&ǃMºnõêÕeþI•*UäTÐ{DcÒmfe”æá-#¶|FÒÇäG,ýÉ- Ëíqfæ±eÃÉk«„skÔ¨¡>üðCË÷Oð Xè7`"“ׂ¨4°x¡€zä‘GOš·šo¶Ý* !ƒî:7ßæܦ"‡ú&16äYÕ\4¨± 6§s5r*H(”)̾}ûªU«VYŒ7Ahæ úMåpêe’?>™ŠŒ¹=ö˜â¹ÕB¡½­9 ;ÏOÍ1 ñ\è’YcÇŽUõêÕ³º^dþ„‘“r{÷Ê3ÙÔ´iÓ,Æz[Ú½ÅE@>þõP6ñº¿|ùòB¿]ÉrB§¿sí÷¸ñÆ/аšH‘Evæ~X‰¢LŽ­iL³¬>ÎëÕóÏ?¯Ê”)“«‚5•Chï¼óŽâ‰ñÒdhšó;Ыl³žÎC©àÚËZà »çž{¬—?Sòà‘cjÜôùêL€©·áQ’ ÐÚÍØ´ów5xÄx5jÚµk¿gš&h E°˜0ÄÃE°Ã»¶w¯½zõRxí¬S@÷‚{ÌßÖiÁoU÷û_WÕ{ܯxŠk㇦痢„þïæ®T˜™¦“æþm~T¦REÊ 3o'‡ ¦ð^@'óžºLÛyÜŒªþ «6wþKW‰‰ïbcF,åYµy7½óÉ4iÞ* Ã¥W;0N¸·ôN }¼–7ù%{(Û;ÿbuúÇËÄ«P8|XQ^<[‚Ûx‡X}>}‘„á E° 4 ¯¾úŠfΜI—_~¹—µp!›—/ѯ¿þJ|ðñ¿lºWO¸-€Â\²v ÝðÈ[tç³#ióÎ}T±\A¸V‰1ÂíR²0±äVmÞÅ֚ݰ_V1pN‰O¾€‚6™ti7lÔ¨Q^nê@A;òƒ&ž?Bì/K4)­à¾¬ºVRÃý¾žµH€üÜGßPæ©3¢Èh\°XM4¡[¬Ha Ú½bÓ醧.X#ñBñ¯»uëF<@#Gޤš5k `aÉxA)?^–îc AÈ–=™~ò.ö ‡½ùõd_ñ§%k%¢Q‰¢Ee¥3®‘Ó„kpÃДŸ–mÿzþê-øPܰx¹a ÊÌ %D‘yVñHF6ŠŒg <'xyÑšÍÔçá4àùh »EF†Ø²–Yf~X„À ˜­{ÒûßÎáÅž‡2}aóæÑ,‰\¹\iêÚ²µáøn¶¾½/âÚâàø¡C‡èå—_–'~ÓEüÆK„‹z¾,Ê¥›çû ­°B#¿MɮÀa2Ê}Y$ÜÁrà~ÌõlVˆßó‘?q]Ð5¼B\ ¹njK¨‡k>sN"ƒvo“DI{&/¸×…*è¹è×îÅÆ ϼ:žàŽ!™üñœáý´¡7BÚ±ï ý{Ì4÷à ÓP–CórŸ=ÚŒ^¥u£:ñÊûªÑûË‘`4ÿaÁ¾šµŒ–¬ßFÝÛ4$D0B’:ÌD»`µ0a™xA-ñôF©?¦°­Â¬Œ¶’Z˜“ç.§×>›B+7¤Qi~Ø«È@…Eâ:û©ÿ Úà†!0¹¸aSPSÞFÀ®R¡ŒÜu"{ýB “#¯â–*(ÃGóÇ~®f‚~DqâÕéôî„™´÷À*Çq¤Ñ#e÷Àk¿f,üvК¦`·î=D#'ýBÍêפî­/¡Jl¹‘´å×çèo¸Z°(ƒEö%LÀó*†à ±å[±a½:z2M_ð› Ý+¬–ÓÝ+ô퇆7,eû^j׸.ui^ŸwðŒù¢´ÂÕÀGÿÆ·=yx {¬òÄä¥ô:?ô­Ü¸MFmÐãx9öÝ ;íøí( qC-Øâ,X€o)[jìBí›$R§fõdLå¨h˜$ûJº{…0÷rïc¿§ÏùÉ ;`ðŒßú:Õ±2 ††}aøM+»a—°VË¿F;ýPb®®j)2¶,OI£WFM¦®’`ï•òH‘A‡“Éq@kâ`‰Jòhº¾é‹ÖŠÕêÆ‚Å– ,M±Ö°AvÁʉÆé^ù7ºW„ÉýtR2½ýÕ´}ïAé^f_~²q dzh3h;ï†-e7,ÍÛ ËRê í°wsMEÞÃ.Å›c§ÑÓæË3K´(²w‹sïWžZ“$‚eðB°‡ÒOÐØ™KhqÊ6êѺ!‡~­¨«ùý†^hßnÅ«£§ÐÒu[¨TÉbüô^Z,r´Ù$ÆË ÛcºaI솕2«úÍC‘dñ“ï~¦·ÿ÷íÜwHBåâ¡/ši÷KPä9 uÛ!X<4åÏæûé¿»çQ ÞÙêêÖIt6âŠvK…îÖ{í–ܽN¢©óVJ—\‘€î<¯Ý M[vßPJÐRœ7=pÃÖà kšHøƒá?ÅÄû¢çÍøu5+ò$ZƾTÉâ¬ÈY~2ûÛù-E  Áx-Î/%ûumáMãPŽº/ æãÚýÀÃüÉ…«SeÞ"†Ê0Ÿçô_¤@ã冱BN¿F6<Ü·?àz¿29ùdb2Ý÷Úh¡=,r¬Ò >zs)WŒÀ5 XþÏnÏà±c€Õžpi?ÇbÆ.øé„¥õäqÃx~?8b˜SÝ]ûåE½…Å2£G‚QÈÏ)*­ÁbèM[e]n~)Œá;ϾØfy<ädXá@I¿ÐBå&~žŠv&dgo`âÙ*egpã™öp°õ€‡(÷œüËÐùWöqI¹ è¸kþ%Êtþ•}\Rî:.Åš‰re—”»€ŽK±æ_¢\@ç_ÙÇ%å4–1ÅcU˜É(á-f 7™Îöc +;ú£†ÀÒ ¢µx=}’çZÄ›`!H¼¥ÄôÞÆa­àùý±ƒ`XŒTÁ+wÐúc)… hÇ>ÑÍyÕIÞô“ë179– 6zÌ 9‚Äd§[¯i'jÓkëñšÈú5*Ó±ŒS<ËÍ÷ºÀXtî?|œ'|%н;Hó)u4ÑöôQíd”æ‰ôz^Ak¶ì¦¯§mû–WæIC±4ó B„0323yvßYêÖæRzòîë©UÃ:>å¥Á]£R9z°_gâý±iö²t0=C–‘A±c‰~(rnsúñ“2/ý®^íé±;{ÑÅU+ÊÌGM¯OfDQaØ€6i€ö^Z§]ÂKó{âgvøØI`™Q¦?š×É«<ºW„8”~œ'Ö¤ÇîèE7]ÕZš+ÈíÕMêRÓÄêêÀaÁ…)š­7é+Äí=%a:µLEnÛ¤^PôK¥(ú@C{õTÇŽ—%ÒeõªÓ¬¥hѺ4±væ÷$Ú  ¢Ý§ÊÊÒ#·÷¤A7uå¨OŤ­|( ˜!Gm¹`Kój‘ëÛ7¡–¼&ò‡Eëh5÷Z{1¬Dá‹ázÑ”D‘ÙO>”žNIµªÓ£w\K7w¿BšEm”9šhÑm‰ q1 ‚-Ëq/nìxµfÁÎ`Á®ÛºW|k,Ïk¹šÝ+\£;³º×ZU+ Ú*g‘$eúVJ d]C+mõŠeéîkÏ»aÛÙ Cø‚hqÃRHáàÑ Y®õ̽7ÐýýºI˜âyâÞiÚbé;b€ÖD‹`Y²`XÍÊåéo½ÛÑo©»Ä¿Þ¹Ÿýk^^Ëþ%ª»WŒÌtnÁÝë€ë©mӬ5I¼¸=AИD¯cè%`f=¨4€®AÞ ÛÌnØÆâ€á?bX‚…oÙ°Vš·j3%¯ØÈCA™Žû×Au¯¬h¾’ŽÐ09‘‡8B*€ï/ —¶Þçݰzì†ÕÈ37 ðDÛ1_¹}³ôÄ€ë¨có$!a$ôXs/|ÉÊ·}Õ £ ‚łŊnDÖ¯ G ª#Cb°’ÒýCr)AH¸º×¢}é™{úPòGO‰¯hYݬ:ö&À k«ŒPdŒØ°aCêÔ©“JH@Ži«l^÷E2ݰnìH kWap¡Ó|€”{ÔÈžç„GÒ©ZÅrôß'Ðôw0Ã"C6¨£•Ðl,æsÅBÛa ¶<ÇUë×¥¹å_§lßÇ.‡/àHø‘tC DÖ?ß½^Aÿ¼³7%Ö̾{8a}~ ‰7Û‘`䈲ÄûµP»víèž{î¡gžy†x¿?)×–\~ü¹a3y˜sG.¹ažKŠx ¶Ú‡ôïNå³BBh÷Âhf\d´æ”)ØZU/¢}ÚÓò;$‚„#¦²X~p 7yº×‚bѽ^yYö“¹{e)»îÖ@ÆgÍš5ôì³ÏÒ·ß~+çÂ"kßߟ|ò‰C$TÞ˜(`4TkŸnØoYnXFdܰóŠœ)mÆðãw]G jU•ß <Ž÷B²ýqи··` È[ÆFµ«Ò\Þ›dÎÊM²?KÉâ¼×6ÿCwJ‚ xã:Ì¡ kV¡GnëI·_{¥t§°H"l®ã+ië ó†”ôÆoлï¾K™ü¢Åcí<ÑNq.ê"àñûøãÓ˜1cè¹çž#ì—„:8ÏÞ•ëß–Ö¢>¬¬A?.I¡%1ꊪEFO?Ûk\Á±á'wm}iV{²üd?ôK¥8øã8 5ÏLÁbH«[«KÜ^¸lñ„Å1~Äê|ÖãɈåöXV÷Z!ˆî–.†¶¾ü±l‰Á{uKSQ®¬Û®¿QîQ’B´nÝ:êׯŸ"á…¨U«VR ×Ðôêsý»aë%*)ž9@S0Iz5®ÈÛ°Qíê•è¡[¯¡»zqp/èã›K>˜kÅzßæÊAª,Á2¨.â¹7wmIƒØ©Ë‚AÔPX\;ÌæáXïérœ?è^gý÷ zîï}%@9ºWqAðölPîǤ¶mÛÒÀ `†¥ÆµýY_Ï~3fo/[EìÚµ+Ûëh7 Ûã†]Iwôh#ñ«³¥ÅõÁZè瘀HÃníAÉ#Ÿ¦{®ï$F¯$ÊŽn1¿$fXÔ$¶&^Û,/^—¦^ülºÚñûai#Žë¤÷œ4g™jyûÓê§Åkô!ÙoЬkÈÊ0­¢””õ׿þUÞ‰°Ìe?p‰õe¡|X9¬ú•*UR¼™b·EîÇÊam“l5ÀÈ ÍšÄÌÓgÔ÷ ת7Æý¨xn‰QË“å™p’yñ“‰ªç7ÔÚÍç7?Õ¼¹à¤|P uÉ#[iÅ~ámÔu°Û)‡ “ãl‘½Â~€¬ÏcßWñöqŠ·²%‹èöÄlá-`ókjâĉVsmŠJlY­ºØÌSƒ×*42ûx'_dMŸ.ËoßQ h-S°ºÌß7ÇuówH¬¢i•G¥jÕªe릭XãìêÂÒ›ÀîÝ»·â«¬v6 ,ý1”ÙMìŸE;²„éÏ*¡\ïq :þùçˆlÁœíÇMë-‹|ðAµwï^‹õ¦²Y…YÃXÛÉo´û¬œ £ÐáÊÀIjjªºýöÛ½,2@f^nÿ6{‚ªU«†´©|¸|ÈoçÅ M‹žž®xÿlÅûg xᘠÊmûº¾Ý iÑ¢…š6mš…;S­B74â Ðf÷ûå—_ªzõêYV8¯l·]¹n¼ñFµ~ýú çVô͸4†ÄèM›6©–-[Z@ÆCÀcT´ü†ëc>8òktuúôé€Ã{¾Eé–‚¾q`IÇbbÐJ³±9gß¾}e»`p./¢‘&´™-mDû:uê$”iz¢±ÝQݦxÕkž§xÂ*R¤ˆXgXB|XQñ1] ¸FcÇŽWQ8JWܸ&×Ì¡ºåË—«^½zY òÒRéûãa­xxE‚Ëä>š’ =—€öžªš4ibÛô[°Ú²i•1ŒˆáD\ kNäì;n­ÙbΟ8yò¤>|¸ªX±¢ld¹lXcSyÚ·o//xtû½-ÔuÜïà9÷€Ö¬0- ϦS<«Î²˜unø×¦²Ô®][=Z7G\ (››"Ë|h° >ªé_/Z´HuïÞݲ֑âƒrhÁä'L‚:|øüŒAS¹"+N÷jù ÐZÜö‡¯ñãÇ«¤¤$ ئe Å {ažÛ¿…é©:¹@֜Ƚï| hÍNÓ¿ÎÈÈP¯¼òŠ*_¾¼ÛÎ@À¶ûÉ—_~¹š9s¦¾ô P"7å>ò5 5{MË™––¦î¾ûn/k­Ý_ 6-r5ÔÈ‘#­·|¸®ë'k.;óí:‹Ïvÿú—_~Q;w¶€m÷¯M?¹D‰êÑGUû÷ï·¤f*‰Uèfr. m,†E5ÁøÅ_¨ÄÄD/`›V“ŠV¯^m]Å|è´ ÝŒc(€;qWê&Ø2Ï‚ýc:vìñÚ@ùð[=©ÉÓ> «»{öì)¿Y d±-ê»)ï8à:ÞØl‘¥ÖæÍ›%ÄAãÆ%° »!²* f$›+¹‡à€ è ¸ŒNŒ}l ØúìºÌýÎ[¸€ÿµöÐ`‘]÷"æ9TÕ´CŒvoã \ÇÏ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆ. b´{g8àÚ>»wqˆÿš˜~ÖòçIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/40.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000466415232633614033160 0ustar runnerrunner‰PNG  IHDR((Œþ¸msRGB®ÎéDeXIfMM*‡i  ( (zæf¬ IDATX íX{PÔ÷_î88އÀÅþŒ5 ͸â×Û0lñãØl4c·uŸúó?qçá*¼Þía4^ÃÕ«WcQÑr¼ÜÐ ÀÚ:,øÄ ¯£&³V}*s¿ùË!,{û}llë”ßü1Ñ+äKbl2?§‰ö®^xù­Ãþ§ÁérCL”\Dk†Ð¸bì†æƒÿ¬»æÀŠÜ…°gÏq™›²Ëvý v> dm7è!D§“µð°P0vYáoÇ>†{æ%Aav:ÄÇFJz_öõ!9Þ\]“ÈjÐÙÛ±‘á Ñ›bK‰Ž!ÍQÀGõ­p©ÅY*((Ù ¿0BlT8ÄEE@·uPÍJY~¨.Xö] =õ­ðDѽ0N<°L%FÇ(—„®ƒXÈl3›çC ø¡ p£2ð!X S¤!ìpé.k…O« —øh/ïgâo–ÇOñ9È3½6YSOïûõ¥Ï€[¬ Ö€Žª+`¡ÁZ Ø.ÊÀ\n¾µ¤˜Ä°UxðÃÖf>VL%Að~åd>Ú#$>-˦›? ØE²D +p{¼ÐÕ7©Éa€0ƒv§Ï-”÷+ÄÐ`Ò/^¸3iÌIˆPsgGƒÍé7•A> ³ù±*"Æüè;%€…â'2\[ñc8õ÷ßC\t$DP oz¬Š/± ;Å’lM~ø"õºmãpþí­pOÚòÔùPœŸ QäÞ!: [Uqÿ˜¨ü'i³š÷Þ;s‰ÒÊÜPööôÛx «ÏœÁœœÌËËÃsçÎÊÜà° ÷WÔ`ɶhìê“<³tþdÓ¼rÕ—Jš›š¨ê¬ÄE‹áñãÇ…?ÞùøþrûA´bË€ {ÉeLçΞÅüü|Õ$LÆ…X[{Aö´šº±³ÇŠ”N°}´üµµµbqqñ—ø23³°²²Bø,ߟ_˜ÅÅ\ЙZ;pã_cåY_¬ðÜ055ÓÒÒ°¼¼œ§„^~óÆç¯Çêº/pØåƯÆò“Ÿ¢k´ÏøïÉ“˜‰‰‰øÚÎ ¾yìCL.,Á×} s”ÎÔµ±j-fs낵à¢ÒöÎé8÷Ù5ª™ `ÕªUP´lhȽz½}P/½q[M’¹ÞrêæTSUÛ u-·( r—.ÊÐ×ß1ÑÑðáùϤV×4´À°Ó J[¡€tÉòz}ÕRüãÝjHŸ;~ö` Rðèï¶AÅ'õR5fEGQ©³Kœ)Џ)àÊS^U 5—Û`ͲÅ0“À­i7ì;~Zâyft%òA©D ßxßy#—±*îT< ¡Í,ÉÕh¶À‰3u0‹ê4•5~9òYŽù”òÇÕ$J§‡æŽ^2@P0=uÂèСdm_9œx¢¸Å¬˜rEakòÃ%ŽË“Ž\æ«Ë\O¹¬Q3A}¨ðP$ùÊ àr÷¢Ôêá‘ÅÍw謃KéD( ƒá’e§º©wRÌÄŸJwÃJzûm³ú`À/ÒúÊ™R= púø8Õ0àþ!»x nF„¬²åÇ#è07!~õÈàî¹ ’{Aÿv‹›û°K”Þ›U»JáÛ©)FìÆâÈšŸBŒèV Ÿ¢œù¸³é±Áwî¾N¼ú ,ÿþB±*{bÅÀø}Øÿ8++KúˆÇ%¬þõÖóIùf]üû–y‘ë e%üân6w!¿”+VÓétòÒοy¬Ì§§§cSS³ð0¯òÏ2'Kãôæo‰}ûöá¼yóT@Üñ0¸øøxrót»ÝÂêÏã/k2ã d¡¬PQJKKKÑ`0ˆKJJÐd2©º•}êÄAÌG§Ÿ‘»å¿@fjll›Í™™™"ƒÿ¡˜œ”¼ñ6O äs‘•T  š{@¥÷OédÖ¦ PQ ™Üí i¼ üeÞžcûk˜æøÿ§i@øÆ[ðQòXà…‘±”IEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/120.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001706615232633614033160 0ustar runnerrunner‰PNG  IHDRxx9d6ÒsRGB®ÎéDeXIfMM*‡i  x xâUî IDATxí]xTÕ¶^!ô¥÷&H‘ŽÒ¼R.ൠ¢ˆ¢ ^õ=Oõªø)ŠˆDš H/"AéUB‡@h@Bgßõ¯É>Ù™Ì 3É™ÉI˜ýe2§ì³÷:ëßÿÚ}M„â@ác5+ǾYøÅDa€sxAÈ޵̵k×äU"""(W®p¹Õ¸Fd÷:øêÕ«©ßG¾q ì=dÛ¢Æjpq&XžÀôuM³qêÔ©£¦NjqÖ¬¬‹9äÀqC¯§OŸVC‡U… pÁ@³žõ¤¯{HÇlˆuéÒEÅÄÄä(=¿†c†YNJJR'NTU«VMÃZ_ eäžY?ƒÙÏ=÷œÔÏ0×9­æ€u]øòË/[ÀæË—Ϫ;3¢?ÏäÍ›×ÊݪÀ9 dG …ⓘ˜¨ÆŽëwKÙ=Å1 ³=`Àµk×.ipå$pa´°{íqâÄ 6çÏŸ_ @‚Q·k×N­\¹Ò={•“†CB0Xqõªwµ]ƒSÔlv6oÞ¬zõêe™m»ZÑÕªU“º^#‹V´î.]¹Î°&dÍN!¨CW®¤ŽŸ¿p)n.]N~Ô…ÂúçŸV7¶€Îh?¸hÑ¢jذaR@䣻eÈ[ƒ°/âˆkçðÉ!h› 9r}¹Ú¶ïˆNB „Óa¶}ºõÁ“ïŠ"y>öÂ¥Ë4jÊj÷ô»4~Ú"ºr-ýôƒM¿¬ÙNÿ°˜~ߺ± ÊÅS}¬8™Ïe dÚYKÏ>û,­_¿žžþyâ°\Ç}|tàF!.'÷[·nMK–,!î~›fb`Q¨)Ï!s!“<"#sÑÆ¿öÓC>•϶½q”'wÚ9æHN÷@ü)=s%ýç—5*QäÄŒ3duj°mE”&À²²f¯XOÃ'̦õ;öQñ"©HTð¤pÁ¼tæÜyš¼ðZ»c?uiV›ª—+-é M€ô™ÍT¦L™û}ì±Çèõ×_§Ù³gK¢hN'[ ¬ÈÈfÂz÷ë™4oÕFfR$•`‰Ød{}o€ˆ¸…8½q'èË+©QòÔ©im*UXžƒbÁLWAºF·ÝvÍš5‹fΜ)@nÚ´Iâ*THέpŠŠŠ²â£m]`9ÆÍ\J#'ýBŽž¤(.„øp;AâxyãSˆ À–y~ÌvZÿ×!êx{-jV§Rªå¡.LžRýµL,L`óh1á;fÂìå”ÄJŠ*\gà•›;…Õ¾^Ïœ¢ṵ̈%fû~Ú¶ï(µiP•Ú6¬n]G³¡Gt÷ÝwÓÇL¬®Y³¦Ük×eæ]…uOóWoâB8‹ÖnÝÃÖ#ŸB@T ð+\ ŸXžI¿þ!ò¦³<¹²å ŒD@= &Œg&|<™™p$• þ*K2þéú¬Pf +}îê­b;1KšÔªH âÀÜâQó±• ®T€kZ—­{Ñ{ ììåëù~[˜¸ñìÓºX‰z8pYž\”'O¤wËòf¥Ù`Í20L€Âb¶îf&ä˜ tf]–0€`Ø©Ädš8m KêP•›KJ<Ĉ.¹\ìè¬QÏž8}–>á8næ2:›tžŠ)ÄÏXÿk åá€ñ“ü¯kyR ¥‡$‚z) €]Ê‹ f3Ö¥0¡H¦˜àë "Z´y™%»§=q+˜ÉŒ.Q@Ô.PÍt`]P…|3{}ôÝ\Úsø˜ÅÏdÔº˜é»{·<µE^Xž¬~ † O8+Ý4Nìf‚¯—Gþ¡€ÔÏŠVoÙK[öÄIÝÜêÖªR?ký ›9òòu;èq3é·Í»¸Q„z¶¨˜ó`€kÊžÞòİåÙGw7«K•¢KpÔÐ6ÀR;¦”éŽ]õÝÓ!…L@_/ª–hWý|¦-Ý@3WnypŒ›Qet{aý¹c/•,V˜ÙŸ[êÙÐIÊ]¦˃7,Ïg?-£¸“‰–¬¡Ò™Ÿ»Ä9—|J°ÂÐ@ 6|)ÊC?¶`¾—D·×©"Ò ËË—..3eÃöÆr?² i¿†*•HJ932‘'ñÁÞ¾÷´¡Áv¥ŠÑ%™XíኻgˆÊ•*Ϋ:¶Ñ¦Ý‡…!ùòò¼/fà~°ƒËº\å sT»ÒÍô ËyÇæ2k…¼uqËÇäOõhEkxÕÉÂ?wÒ‰3çx %¯È«û¹Á–5#éÛ 0LWd®HJ¾p‘.ðꈶMjÓ~Ý©eƒ"›0‚#áÌÁqôME©ßßšÓÖ½Gd}OÀçÏ“‡'øsm(ÖEèä™$º‰Gç†öïIÏÞßQF¿ VË yñLË[«Pýj·Ðbù7O¾x‰ 0Ðú½äÄ!ÿlX3!!1‘j1^îÛ•ìÜB^SƒÙz7ô±VLÝÊÑT«bž ØC‹ÖýE ‰I¢<‡Âx…¤,¿Ñʃ¢1Aå!½6 ªQƒjåh³dõÖ½²xæzÓ…!P ‚‘Èï<3¦õm5iÈãÝéÎFµ%) Á¢^Åkº°<ñÙ)RDâèërÜ\²[ž!µ<¾w†Y¬=›|^Z}º´¤Å£‡°Òz¸PâàÅ@|°Ž ë©x¿/-]ºT”ˆëˆ£Í"&ŠÊO=ïh@ÿìÝ–êU¹™¹ìjÅ2:ž¿/ 9QxNœN¤è’QôÅ«ýè—Q¯¸°.R°'e6 à;vŒ^xáª]»6½öÚkÄ;5a`´«zа<Ïÿ£-ÝÛ¶¡,ÀC+–'«CÀCd´8Ñe8É fõªÑŒ_¤¯^{‚ª•+“2¦¦€†‚À Û°auïÞ]ÖPmÛ¶Ö¬YC¼u„úöíK»wï–8( ®å6Pžk2¡\é(z¢kKêwOs*Ëuõ9V¯b_Oy®BÁ ¨$± ƒÙ/óõíÚ†å¼`‚¹p!3mŽQÐ>ýôS)„Ÿ|ò >|˜Þyçjذ!}ýõ×R`µå¸Y[ž;ØòüÏýíyžº†0«4¥Á™…@0@s1á¬0ás̈́ƵEY& |O/¾ø"5kÖL–¸j&ãÊÁzåFÑ›o¾)æʃâ®ñj(ÇøÔ¯z ½p_;au~ne£[…à‰%Ð'X›ÄÓ›˜â¼÷®¦´ð‹ÿ£7ô¢â)+:ÏšÖ…=öPóæÍ‰·“Ò‘#G¬B‡÷Ø·o=þøãÔ¦M¿,Ïs½ï¤zÌlt½.]v1^õ?VÞu›L -û SQmŸToŽ™®N9'×pOïb`öY[Aü݉À€JÕÊï­°gèÛo¿µäaå[{†˜mÖõ„³ÉjÚÒõêÙ¦¨1³\›Çp_˱à÷ÍŠ>¨: zOýºf³õ¶Ñ0SåÜܳeËÕ»woKÈÄ…Ï:‡l\ -Ÿ8ä‘GTll¬‘¶k ’7eÝ{H}0i¡øá÷jOÜ ‰oÞ·ÒØáWÀv“áf©M»Xñõ¾#(ÍTØÜ¹sÓø®b¤S”¤?P&âès÷]H[Ãu»•ì¡cŠ»+rŽûúޚͱjÔ÷ó­s<­Tv1¾òÊ+íbÐ|ìubËãq¯òÐù@w b¶«ƒÇ,Y­—òߣdê¦XÂNÉüa‚ÑÓ·;Kú÷ï¯Ø4êl-ëY4`ÖM/šÕ¦uÁñèÑ£Uùòå­BeZO²¹_3ãcó¸?–Ç‹ˆA½ì7ÀB˜Â OLðæ»Ê]9×;7MdñâÅÕ»ï¾+îRepmȺ ™ZBYt™c×BÓºüú믊ëY ØëY_²dyL†˜Âù8 €Ýer3Ë_ 4YÂÝ5eÊwü>ß±c‡zà,`ÍBäKî]Ïòø-d" 0@½xñ¢š6mšmLð¥Dw–têÔI-X°@̵'öjá>p~öÒK/)ø°D>H€øÊ3£÷ÌBS²dIÅÛhT\\œÈáKV-s0¾BÂLÃѧé¿*Ož ¦Ù’æ1ðL[OÖ…‡_-˜tßyëñëfüƒã]uÈ'%2EP“Íh­>øàƒiX¢Óìôôm2÷½÷SG¬ý¶½‡S¤à—rt21Iñø³u] 6™²fÔò¸[³uoz݇ »Å«8öU‚`ZB¹Ä~ æŽø~‘úbÆ wâ´%’=rg‰¿ýMw&´÷âßù›LøcÛÕþ©wÔ#C?Y L 䦨Ãjð3Ôò ±Ö3O+Ö~1M˃‚æÍò¸[¯ýs&ƒÎ+éü5âÛŸUtçgÔÊõ®Q7xK‘A:ð`ä?êÇejàˆïÕ«_ÎP3VlTg“/Xbiåš,Á±¯~²ÉO£AZI¦BÅŸR/|8Q•í4HQ£>ê©wlj &ÀÛ÷Uÿ9U=ÿÉT5bò"Å;ÓÈ©™n²ÙW?9£ÖåÇE1ªiß×UÁVýTÔOªµ[w[²Zù  Ù$–EÖ!aª “ñMYL«xõ“ÚùaFÊ/ƒ+³Eì&P<ãð˜/ñH—µŠƒ•&Ç<ž+3IÜ:¦‡zΚºãCk*{þýý|j;à_4zúbYW”ÝD o÷€4°9 +/Ÿ8McçüFã^Mq'Έœ˜òÄs\À$?ZÜ>Lž<™ØòÈŒäG:Ü3ypŽéMöŒGcÇŽ%îÉLâ¤ñØÃïÅÖ…z½4’}ãKŠ=/[WõLœ»¬Á>`£ å1ƒé‡ÅëèßÓ–Òö:pñÀYy8†ònºé&zÿý÷iíڵij6,³“xF†Ö­['~5°jB <Ǧ_æ|1¥7‹7šßÅ®˜^õ½,µë€ÏVë~;äÀÖQì+Æ‚¾O¦-‘í¦˜SÖ«"ϱC‡Ä?@lyˆÇªE~¶.ÄcÍ´xñbjÕª•%¿<Ç‚ ÀÀÃÇ螥»ÿù-ŒÙBØb[€w²u‘ÂâUØ ÞÈð’(s®Ø}àXñ´5¨^Ž:³gœ²%ŠŠÈ‡€RðêÖ­K<FsæÌ!öCIP& ؤ™eÁcφûÅYʼß6J>²‰›AŲUÄñ' o€ˆ%?lše±ÜÆØÃtWãšÔ¢neke •¶*ø†åa7Š„9âž={û®–÷@Á„¬x7¤‡°.cتÀ'ØaÖEñ¢eS: )ÒΪa€!0¿Ÿ¼4Ö #¬gÿQ`rk^yØ®Qªÿ(“%ˆ×µkW|±’\ ÀFí»êèIø®šKßü¼‚×O¥õØ#fàÀ@(dXžµìɧK³:²Ð÷ à@äáF±2¸‡s)„Rµ¤0¸±`;÷Q‘‚ı ±á±,™XK– À”$þ£v¢MÜüGE`‡KYˆ¯ë@<&ÀcÏØKÅaŠé»J3Ïd6 /O–§ [ž2Úò€™ ´¶<8ÆrXÖ…=ãÁMª?0v‘b]2+£ÏÛ°ÊC€gœ3¼,U<×± °¤zy—ç:܇²æ  ÿò<ö̤µÜ@±Ûcdfüó×ò@6Xn<[—ìÔå›9öY~0¾S¥·1uK"¥ÞÜ˾³¾dÿŽ k”£{ZÔiÈ 5#Lá.ne3æ°ëC4|໑Ò0±Q$I™–yÎ_»Ö±åC³&5+ð3®Â'LfvN`=ügdŸ•Ú3žÖÅ£™¼è_K%™@)[>òçËMË7ÆÒf^ ¶ê{`ÈĹ+i×µh˜ ~Dý¥Ÿl3ôäDa+">¹’höªÍR]@VÔÝ31é½1úGÙgUª¸k´ÓÁ…2‚Â`SËK)8Lá}<ÌP÷—·¨JéÏjï'TçȽt«<¸gDÄ'»„ 1Ø]ºë~ÀWÖ=~°Ïź°Lžä µuñ$G ×Bp B…ãÚ§0ÀöéÒ‘)…v$,ö Ø>]:2¥€v J¤o gÕ›¡Uî©ey<íYÊ*9‘/Fê²BsŒAu 'zSj¨(#L<ª„mšç’][5ͼÑÝÁÎ{(4«–Ý‹,GÂÙ$þ€Ðw¯üX÷îâ „ÒÅ Ë4!:Y4Æ‘1ýÏž[á,¥;¥ë¢­ äªP¶¸üÀÞâŠB 9q?” àòÏóÐE–ã¹:‹t³BYèüèкiÈ?”Q«bYZÂîVlÚ-3=¡òOe¡/}âô9º™=ó é׃žîÝ^FÊPÍ1”"ì}¾OÇÛ©iíJ4»Ä²;ß¼<€×ûÁLAA‚¬¼TG€íØìVñ$€Â˜Á/€µ`P0&°ÿÖ¢.5f¯ëóù÷Ž6ÄäÛ<ÿéš÷…²í Â>NLÀ°ç€^íèåGî¡[Jù¶kÊó·˜z;dˆ¯ã¸Z¹Rô\¹;iÍ6öŒóÇŠgwN(ðÑ  a]°1{êW+Ï{ºQïö·‹œ$œ¡µ#U´?¸8*Ãã±}»4¥f*Š ¤=q'Åí>†úìP^z&Ô÷š ÎÅ E<=W Mê9fA†ÌøÉ›[«ÞLK×í ŠåÑÖJ—(F/±šA½ï¢‚<¶Ž‚ÆÂjA:Äÿb0dC Œ`ˆà|\³BªÁSp–²ètÜÿQš Ì„zUËÓàǺ2š"{Ö”úÁÕÀ‚µ»Ù Äž={¨cÇŽO¯Á ÆÂS-Ï6¶<‡%^f,ä€.ÄìǺÝA¯0¸ð†Ö|Ž–e!`€µ¤`ä†ÙÆ‹¶¬W…°›¸?‚$´bµgýÌõ¾Ó1MñÀtß\±ì&˜æøüùó_XóG)XfwõêÕ“ì4ætÓZžflyâÓYZKçŒÏ´¬_]ëÂÀâ}²:d`-8ÀEK0Ý×½Õ­ì½®‚ü¡ö\W Ÿ¥X3ò;%{½1sÈšµÈsêÔ©4lØ0‚S0yúôéÄäwñ[JXvƒp-eÉ'˳-<×á÷®×3€|˜;>y6‘êT¾EÚ¸ùów½˜ä¶1(åL‹¾ þ£šÓ“ÝZ|Q&%_b`\óªîïƒR'¥pzÖ¦aMš=ò%úlðcbæÀ L”z™AÄêÌ.]ºÐ}÷Ý'à‚¡f]|áÂúðÃÅ3VG‚ñ…#=ȉg`yà§CãZ"Ö€áº{À%\gß$â·òõ'zÒ’ÑÿOiJü.ºÀ»?Ÿeç,œí_ÖZÙé+6ƪ—?ûÉò§ÁÀñïóº¶SòRXU¹ëójÊ‚ß-9ð Ò@``­ëØÔ…Í] –X\|scJŽYÖ7‘f»){øQóçÏ·ÒÑû†pëIë:vl|5{•z}ìÅýg¹®ïOHTYÎ~oŽQ»Æ[Ï@V'”¾ ­d€ýB‡¬½9©ûsþܾWAy•Y&ÇøÖÇÌHÙŽ‰m™H ²>÷ô  Íx÷߿ھ}»¤ºðb:¸ß¬ØªÈ©¾šÈ¿ ç.:¸\Dè»úªó¾ƒ °~]h}Íý[3 kÅ#ÎŒ3Týúõ-`Ù[Çž@õt ,×LÇîÇ!C†(ì†D0óÃ1>¾ ‚?ïã+PÞ Àx!oʃ´RM`ù‡ U·nÝ,0ÁD0Ò€þ^3Ù\©R%5~üxK×È[Ë¡¿­›)&ËÝï9õ\Á7%ÂRÏÊËzùë\ò³e` Q@e®—™M좟ʖ-+ïÂàÊõlùb6 ­Öz0ÁÄ1×Ç'íuüé;G À´!â†Ö„ßuß5Ók²®›Cˆ"„õ¬hGL6x-|Õ „¶C‹N# °ƒÁ±C´0ÀvhÑÁi„v08vˆØ-:80ÀÇÑÂÛ¡E§ØÁàØ!Z`;´èà4Â;;D l‡œF`ƒc‡ha€íТƒÓì`pì- °Ztpa€ Ž¢…¶C‹N# °ƒÁ±C´ÿgF:ט.cIEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/152.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000002475615232633614033164 0ustar runnerrunner‰PNG  IHDR˜˜ !sRGB®ÎéDeXIfMM*‡i  ˜ ˜é_×)XIDATxí]€UÒ®%ç "qÉÑ% ("I=Ã(&@=ÿ9À‚ŠéΈDA@Pr”°dTr\Xr\`ɠﯯf«y;̦ٙÝ饟.Ýóúuw…ïÕ«~©¢ 'ò’'0I W˜žë=Ö“€HÀ˜„°JÀXXÅë=ü’ØüAþù§‡„0I O˜žñUPåÎ[hÐråÊEQQQO»›¼ä,>šÏŸ?/` æÎK7n$ àм: \Rx¢}ú8ÊO¯Ÿ•˜R»f7µåÊ•3ï½÷ž9sæŒ@Én¦=lù$àJ€ôS§N™·ÞzË”)SƱZ¶òSI(®ÙþYãÆÍ„ žâ\(>Z·‡6ìØOW6¨FšÕ¡b… È-P@‹¤ÝÜt ˜úöíK·Ýv½ñÆôá‡ë8eF;|¸›\âz饗èÐ _Á§÷€¶?•/~ÿ²uqôú—hZìïT¨@>*Z¢åIШó1ÏQçiɺm´fÛjÓ¨&µm\‹ äËÃ- Þbäú>7Ã0(1* ÀÊŵù$}ðí4úìûYtøè *Q¬åÉ•›;ަ:Eùá@TAÆÍ#ÍY¹‘~Û¼‹Ú7«MW7¬.ÏÖû$µT 'ÑÛo¿M÷Þ{/ñtiúᇜ2>ú|÷Dü‘@?þ8=ýôÓTªT)¡KÁ*7%ý:`…Á¬ïÛÃ'шÉóéô™sT¢ha΢ēgRå Kãæ¬¤eëã鯖õ¨A5_Ï9Ê@>È4›PzÙ¿ÿþ{úé§Ÿh+V¬ç)8ÿú׿Rÿþý©~ýú’¯ÀR°"“](¹¾Ø§Ï~˜MŒžF;¦’E Q~¶Ä*Uzž š‹0_‡¸â Ÿº„–¬ÝNZ×§j——–Ç  š`·¥̧Lø:,`Úü_7ÒÀ/ÇÓÜåëÙ奲Ülüñ'7C ®`„ Q8O~Úuà}ÁþYLõŠtc«zT¡Lqy,€¦Í&”h“صkWºñÆiðàÁ²š>zᑇ«‡ò6°’ñÅe~š·’Þ6‘V¬£¢… R™âE|Ædޝ¼yr³»›6îÜO[¾?H-êV¡ZÔ£Rlí‘l¾$#Âÿ )À.4Q·û úê'3}‘Ë00øk*$"1ƒÒóåõ±ðÛ–]ìŸí£«¸ÉDÓ k€d+ÄöÏ0ŽùØcÑ]wÝE¼Âˆ0žÈÏÂ3lÿñ·MñâgMšÿ+[ÇÜT¦DQ®0à+x`ášÀxƒÆg´pu­fß¾Y›F5„_\w‹€ùL<û=Ül?uš>3ƒ>;ƒ$ãf£°˜() A*T ¯4_3ØRþºy§|\Ù°šX1-£~ ,ò`ÑàŸ!is(?’þ¹ParÑ>þ’}ï›É4lâ<:qúŒ4ó@¨€e¿ç¨H… ò@ú¹ó4aÁï´bC»9Ôg/ãçÒGM¡í{²_HþÂUa„PëЂ¦|í?’HÃ&/¢úëÊS'æ«Êe¥¾"Õ? `Nífæ¯ÞB‡Ž§™K×P~6í>?ëϰÕnKþB!è€/³}_}6a5®ÉþYËútY©¢R Rk¦G}ò…ßScWÑëÃ&Ðæ¯H¡üÒ¢‰Ï*p)M¨:p/òrw ÷`кíûhÓ΃Ԫ~Uº¡y]*^¤ µùÒ{³ûÀÀj÷Ž}‡é­¯¢QSÒ®é%‹…ÖÏ V8 ÿç/:{øô‡R®‰aÿ¬iùØHéÙàkmÜ.ñ³&Ì]!_ne¸ŸÎçg…ÆLéÝiå _\þšÐy¿m¦U[vÓuMk1o5¹b¥ÿË5­w…êz†&Ñþþãl8d<íg? ý>ÐG&?+Xf}´Â?Cÿ™¡iKÖ±³ƒn¾6†bjT?L-Ê¢Ì ®0ïžJ'¸™-Î|Á™—Ÿ,_ü³ütŠûÝ~øåwÛÚ5¦jاd^”¯`ߪû2 y§rÈsxx#‘Ê–,*ŠBÓ©I|/&®h¡´/!‘–®Û.¤ú¼6èç8ÓC'Ì%ÿ¤’ì?â#@ý±Hä ´aÈ©háüÇþ!¬üK±Bp†¦tçÎRø‘V»•¾@G(¾üÄ”:¡´H³Æ)Ñ‹J¾Ð]£]6)•ÍŽü ‹¥MPvì;Asjtûø öéÙw_Z|eeA,»öÞë. xs—¾\G­0שÌ]{s—¾\G­0שÌ]{s—¾\GmÄLçn’`¤ôJ¢-µ¾=7×t ™£¾OÂõºO®{´G™ß5}ÙzÞbàXXý3_…ÉÅk2ÏÈGG‡ è…û»S«†5… á+@…oÊ—íE&Œ1œZà†Õ+Pݪåiþï[höŠt„,cÑ1À(–Q…æ‚ã ‡ˆXÍA^ €Eï=u7Mÿøy¬ „2 ¼ å1(W­ZEݺu“UØÆEÎ⢠ñÕ|_óÑ¢^Uúçííé¦Ö D‘èòÀ=(ª?Ëç?&ò¬Ñ²4´_oÿî¿\:uIøJz!À¾`­*gCíÛ·§§žzŠx«)ÉC™ä|¡ËÂ"¼¯]“Zô¯;ÚórµZb™Oñ—4xB·¤L, óHâIÆcwv¤9Ÿ½D}z´—fJ@[é*\Þù†8 ÂGh=¬¼þú믩I“&²§‡q…ÀÂÙM( Q´XÔ{¯´ùçí×QóºU¥K]xgfôæïŸ_¯_ï4ûÓéöë[‰Ï'V7©Œ*|áðÅ;R¯^½¨M›64{ölz÷Ýw‰70¦Ï?ÿ\Š|(oó¥2B…Ä‚Ž[y*ô?nmKõتä¯ïs\ïúÎH=f`"H¬öžè|ucšúá³ôæcwò*žâRëáùûY¢˜$áb€ ÂÇæ$:þPÓyS9jÞ¼9ñÎÒb ` mN XG! ´²üápwÇÔ‡»°ìþÄ©³2ë@ËHÂ3aEŽq?Ý)î,íÙåZ¾‹ðÔkTðz4'ÐÚ{1(›6mJ¼Y”U¾xoâ@[ÄÛÊÎ=ÈÇs`ñ’ñ•ä U¹¬$õî~5õº©•+YŒ×Ÿž!Þ¶O*¾?™òÁ lÚ`5­[M¾¢º^ÛDøLÉÏ8P³‘x/zùå—iéÒ¥òù¸Ž?$(ÂǦ¿¼©œ,íõÕW%€(®_äŸqyUPíÊå¨V¥r´xmÍX¶×§Â¼ø#- ñ#dÙ¬ïñEmšÖ?ëšÆuðJ©0x†]aðN­0(3jÔ(êß¿¿DÒÅoðàÏÅ!‰CÊêr”¯]»6ŠKY܃z`«||EÉ¢[t×`EÑœ•›¸œæ5“>ÿLnˆ´˜ð R‡‡jöwS»Çÿ^…cNŸ9+Ïa`ÜHÁ༻òF#0lòÇÂLus8V†³Ê>üðÃfçÎÎóìgk&[=5\ÛÍÄ«Ì ŸN0}4ç,–kZ†Á!¿Ù ›˜;Ÿ7¹[ô4Mþö‚1i¾ó l §å5÷Ù›Þñ~d¦C‡_\aÒä‹+‘”/R¤ˆáí¢’íž˜_‡0ßÎ\nžùøÓû­‘fRìj_¬ƒHI¨Ntû¾MßC o]äܯ»ø9|!©:dž{î9S°`A*€ƒ?ZZG€KË”-[Ö¼óÎ;æôéÓò:¶·³´A±÷Ð1ÙUðËI¾`£zMéKðÀfÛ¶må6mNf„ 0tSø÷ð™F4z¦Uø*,ýŠ£ ¬† šqãÆ9"-þ>~ƒÎ”R î”×{0r€Œ$(ý¡æË¿Âð43þ…a«@®) Ñ¥ÄgVå 0%0BlÅ"2ÆØ0Ö…ØÍ˜*(˜£­T†4hŠ]6 ”N eÙ×ís`Êý XM بÒc(Ü}d±‘ ÇHÒW&vÓL®/âKï˪cPƒ¢Vrô3žq tBi)dÆ †÷¤OVëÕ¯ÈÀìfç}úô1<1Ñ‘—mA5Ó×3ïûÅÛ‘›‹}ƒÂJ³Zbž–#|i¾XihÐJ¸f»‹/6ÀÁá+XwÀRyð¾ý†gW˜cÇŽÉ›ñΔøRÒÖÅí23–$ vûѬe²ãÀ@è#¦™W‡M6¿m¾0«Á§älø+dúôéæÊ+¯Ì°Bü› ŽÝ¬/(`³Å$5‡€É7“˜è.O˜{^ùDˆ´¯!ÃŒ‹÷¾e6Æï“2ø'•öWú˜1cL½zõ¾lK”Z²+ ÊõìÙÓlÞ¼Ùyw `ÙCtÇOr“=b’)ÑöAóìû£å>ŒGJ º›ëîçýN‡MZ$[…Çó–ᘤ‡ž Ö+ËÊ—2ÿ‹"óœ0ÿ Ó?ûì3ªR¥Š|v³0dΔÞãde¡"HY|ž=š¦M›F­Zµ’gâ[çS¿Y BæmÍ[¹^Âö}ýKÚu0g‰ú²ø¿¿±.nÏ!útü|1m)àydö„F½|.ð…?Ä9â Iƒîn¦…” ”üåríµ<¡‘g¼b&/wV”‹ð%]%¾n‰±3—Ðu}P¿OÇÉ:S>è}Ù•4À¢¼¼Œ ‹ÖmÛKŽ›+Á©Q'õ±ÕpøâšêL¼C&Oo!£zæ™gýLPÊàO”EàZ‰%hÀ€¢Ä;î¸ÃQ¬–Ñ{,ŸòsÑÖ]û©Ï€!tóSïÑÂß7Éj$¬¶f‹¤Å/:‚f,ËÇK9Ã{cfñR²µ²È@åÇhˆÔÆÓ‘ˆÝ%  è¾°‚þ|á['ªV­ :”8ö7µã~-<€M^a|…/~×’5[éæé¾þŸÒæ±,‡³Áz€ÔøºˆÑ,ʸ Í ^!A!˜Pý³,ßývÍå™–ØXÂ×QN“‚,]º4½ùæ›2£1Õ@¸(‡2¸÷¾ûð T¸paÉ÷#²t"ÏòD *Ôî“ÈŠi¬ÇM6-J“ÿeð‡°ÜÂÒ¤Ø5‡®e(|óÿN½¸ A¬IžžDüå' =lÐ(ÁÇ‹/¾(• üá^”Ãsl04ü:ákçþÃôäÛéËoѬek8baYEÅM½ÜïA'™˜ò¡– aö°%À¸_~¥ÿ~7[Ö÷Ai)¤Aƒ2çžÇ eþ=”a£F£f£†GGG§«ÙøvÚ"j×ç5ú÷çßËjk¬l}ÁÔn€ÊE”„c'iÄÔ¥ôÑ÷¿°Õ8˜ª; `Ñ9÷ˆ–‹éÐà •xùòå2g–¼Šubpi»A7šxÈôʦ]ï×è3ŽO+ŒP=°Ö*{½/ÒŽ™š“ïÏ „‚-ÀWgÏAƒüs,5¬~9uâ0.XTЍO¡ÂZAèP Oƒ‘¡D¦ÅÐw,Ê=ª”ÕÄÅå>X,„]Ž]µ‰ÃÙL0ÍØ÷!aõ]à ‘Õ°Èvó®ôÉó8`heYeŽEÀHþ|Á/ðÈc†tË-·Ïð Î;Ë=ÊáOä ÀBÞø¹ËéM¶Æ¿nÜÎûáÛa-ó©7Gàñ‚ÆBDØÆrwÔ24'°1þ!òY³‡`H¶B´IÐ&‚çtI)ÇJ²€´Ù” Iÿt(`!}ÏÁäßä`§¿oŽg_¤ 6{’îÿ`GS¾9A_OYÌñ‚8 2GÝ.Ÿ™éñwlʤÂpøÂÞg_ŒŸCÿ9•ƒŒ’èN Æw´ß‘Ýça˜2(~ ‡AΛ'íÜ„>ç0{1fþYùÒÅ´XÀ#@?kÙÚ­žyM_´Jš¤ì Bg¸h°ñʆø}üp€wÉá0{Ø1¼SK°âH“ü&a—ñN,êE]X,·ƒ ¼eÀð2X#øgH¿nÚIë%Ì^  kÀ8r’6¡»$лÜl Ÿ4_±ãó×"¥Ù-àMÃì-XµU¾ ¯kZ[|OŠÄך-;i Ç£ü™ãçÊ¥á™ág¹³9tgd)Àô½ ŒÀü»ZzÌïëÜZ€‹ë GÖܽýÓœåëèrÞƒ _ˆø<ĤAæïßÎ\![Wu¿&FüGõ;Á×QÞÃã¯Ï} ±Í5b]N–ê'[¦/W?ðA% û^”âþ,$74à+7»è€ÆÎ‡:}á3"¦9Êk¥ TÖÍy!éhͬÔÉOé9PV¤Z­”hF“™_h2!|7T˜”xLO~D,-B¡¬œ˜r([ÉTå €%£Øûá* xs•ºÜG¬0÷éÌU{s•ºÜG¬0÷éÌU{s•ºÜGl¦¦¹nb[ÌS¢ýSèiwSµiñ•]ü 0tºißv(ÀIL<‘bç&uîüŸ2Þ‰a7à óÇ0pvœùŠÄ”a€¡Ó·µkB1‘Ó"yßv€ »a'ž<ÅsõOу=:ÐÓ=»ÊÐŒZ` ¾¢¨N•˨o»:)Ì`ˆ¤0.¨0öÉçõ— ‘ðÕ˜£¼EbÊ0À” ßଵo;‡Ø›Ã¡ö°o{v‡ÙC³ýû8œMÍÊ—It·{º\#M$švX®”ü,ð…ëW_QÃìU¤YËq!ƒ ‘k1(ª“]ÓˆÿtæÜ9^€rZ>ËÑݺ·i**I‹/Õ[Vƒ˜*ºùxÂ]‡æu1§s˜½¥ëãÅÏñÍ_Ï:…ø¦W ˆ©ÆÏÜÛ…¿³•Âü1–,”àï ÛÓ³!|‡/¶Â˜Ÿ†©6Mƒ`¨¿oÙ%à“0{Ì7šÕ¬H r>x4‘Ï””®½9D¦.!Ìùó•t¥çAL®~ šÅRÅ Ñš9aö6ìØ'Q3ÂfO› „ „u¹µCKzžkwÝè B&fbÈb V”&]ñ£óã4T&s·¸0žW¡LqÂ\µ5q{hÛö"Ì^^´^w@--"©äg0õùK{ú¿ž©b¹R>¾´ÂDŽË¥âuŽ™˜>É7™•ÉHŒ ‡ÿr- çÀ¡ëiOà ;aÙ'iÍaõ^`?ëúV } ``‰3ÌM¦&àR`Mœ8‘*V¬(1…PKÉtµôÀi“Ø€C¸Ô­zaÆê¬å)lYtÌeÄ’èK2yôU_xfÌ'ëØú á«yýêòdT˜\ÌS¤Z-›ý e9ËjŸB¢xí`jP­‚/ 2¯ú>α#1‹ŠË¬B`‘ h„ Œæ¯¾ÞN÷uk+_Œ²,Œ‰AM  V ะ¼¿_¿~€åË—x7DzöÙg‰÷ý’[PVA¨V 4C©mÕ¤Æyûg‹9æv(à ã# _…‡9I­[·pDg9p*o*'VlðàÁRù¸O×0â9úL¸Øh¤G›FôØ­m%`=V_ /ã\ù|(È a ÈO¯ö½f ~QÀ>ñN€[ÁzÜBjÁü¶R†§<ÿíƒÌÁC§,YK›v8ÌéI,j÷Qîˈºñ׺®àZŽ”’Ÿ…k š>€gàÀÄû¶"[ò|(ÛÊo*G_~ù%!ª66FÒت\Û¨T®$=Øí*ùÀ‡ÀŽý â|çc0¤'AF°H˜£Õ㽺µ¡gîéJU//#·ë‡ *¬Sú´›IÎ| wFT³RYúG¥¶´dí6Bdl„:¯` ô* ݹv7­Í|wº‰ûÄb%)Iïµ›CäaÏ‹W^yEöƒÀoX2 H(@pô—,Y"¡Bðßÿþ7aË($”‘ pÐ{‘bjT”už™7Á’‚R~øýãóÏqLËÓÔ®y}ñ³®Œ©%¥ÄÏbZÜàgù±•ü' (K79Îû¸”CЭ1ÿ|¬yìÉ×ëZ ¿Üþ¬©ÒåqóñwÓÍ™¤]Y¼U¦–r™l'@ìßߣG @þÎ.‚šèÈ s¶Ãä-™ E5Õ¡Áxá…Ig t'3vÎJóÈ;ßšo¦-•|¥Uù;t$Ñ”»áøœámœ{yeQÀÝ".;A Ì–d+d×#fΊÉ«êÂ6ÿ9ÙìÜçS0ˆ…ü“­tÏlž~úiS @– ˜@€J)€ÔkÑÑÑfÈ!Îkñ>¶hÎo=Q á÷ÆûMìê­rI¥ÇƒGŽ™ÿŽšb¸ ¹èyrÑÅÿdÀ 3€ÈZ 9*Ðp áõìßȃR\8g?ËT®\Ù† KFŽÜÄ%Û"·d2³fÍ«%ÚºÆ,-¾ô~Uûº›Ï³`*8Ôj­Ùšg5(ooÆ‹½_yKMXìg¥«9L/Ø`m°Þ}÷ÝfÓ¦M™ r'ƒO‚á˾?'œGÀ2*H[™ëׯ7wÞy§¬ôúYé–9ûùˆ(Ç}i/<P6må+'–w%À ˆ„„Ã[PÞwKÀ¬Ÿå ôþ¶­YÍš5 "Íyéb ¸`ÚÜàkŽw¨6Pª‚ÁV¶æeÅÑß?C˜½©S§JqÐë%c¢ VFÄ'V˜ô)±ƒMÝ»w'åŒr³”mô£Ÿ ýjì £’&L˜ QÞp —rJ_wsHˆ›@¡‚­qT7;DÀ…kz=+Ieˉ@ÀU¡Búøã‰…Î=p%iÂmfÜnz²*~6‹ÊiŽqnû{×ëÞ1ó¸¤ñ¡ÉDòšCCÈÿÉ’ek!§:„ô€Bax”k¦ë ÝËr<€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚ=€¹@In&ј›µçÚÿÄÜ#‡œû‡)IEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/512.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000012102015232633614033142 0ustar runnerrunner‰PNG  IHDRôxÔúsRGB®ÎéDeXIfMM*‡i    øµ…@IDATxì]`TEJ!zïE:HAšEE{åWEŠ]QTTDņР"AšôÞKè½·@íþùæ²—BÊ]îÝݬ†\Þ½²ûí¼é;›ÎÅ´)Š€" (Š@H!>¤F«ƒUE@PA@%E@PE P ']‡¬(Š€" ¨ 4 (Š€" „ ª„à¤ëE@PU”E@PD@€œt²" (Š€"  €Ò€" (Š€"‚¨‚“®CVE@PTPPE@PBUBpÒuÈŠ€" (Š€*JŠ€" (Š@"  @NºYPE@P@i@PE@ATÁI×!+Š€" (ª( (Š€" (!ˆ€*!8é:dE@PE@¥E@PE P ']‡¬(Š€" ¨ 4 øK—.‘Ëå"üÖ¦(Š€SHÇŒÉå”Îh?`BàòåË”>}B¯~<Ó¸u,Š€"$äNÑgí¥"àh àíÂÔ¨QÔ®];š0a¥K—N„¿ñ 8z Ú9E@jTêéÕÁ¥%üìFÈ/X°€n»í6êØ±#ýñÇÔºukjÛ¶-­ZµŠ2dÈ çiX -gHŸ¥(v4`GC?+)D‚Bm×®]Ô·o_6l˜å €R¯”„ˆˆêÒ¥ õèуòåË'ר¯—ú" (>F@¬·n Ô!ÜñGC† ¡ÐdàP ìV¾ýï%JÐk¯½FO=õ”\{¡i~€À ÿ(Š€PÀÇëíƒç7Vÿøñã©wïÞ´bÅ °]Ð{"`BF1hР½õÖ[Ô²eK9Ç¡àüðCúòË/éÂ… –ÛÞóäàcW²fÍJ/¼ð½ôÒK”+W.¹ý¹É¹¯ž«(Š@b¨:ú"À¡·<¬ò¡C‡R¿~ýhïÞ½‚Obîþäk÷G+S¦ ½ñÆôè£Êßö>ÈýGPT"  @*Ô˃Owÿ¤I“ÄÝ¿dÉ´Ýr÷ žù7¦·ß~›š6m*Ðüo!­÷QU”« `w»cÝ~oNð7nœœé ÁïÙ³ÀXþ=ô½ùæ›T¶lY9Uó<Ó¿E ¹¨\Äôü FÀ.øø€vîÜ)ãµ b`ϨP¡‚xxà銽ïþè›>SPUsÞ´×^BÀ3Î?mÚ4zçwhþüùò„´p÷'u(žùÍš5“ü€† Ê-4? ©HêyŠ€"TP:YìqôuëÖ‰à=z´àa<PœÖ<óžxâ zýõשT©RÒUû¸œÖwí" 8Uœ3Ú“4BÀç?vì}òÉ'ôÙgŸQLLŒÄù!`qŽÓ›Ý;‘'OêÞ½;uíÚ•²dÉ"a (/FYpúX´Š€"ö¨ö˜ëý„€g¬|äÈ‘ôÞ{ïQtt´ôÈßqþ”Âbïw•*U$,о}{¹Æl*¦ôþz" 'ªç¼ê¨lxÆùgΜ)îþ9sæÈYvKÚvY@}ô̸õÖ[eéb½zõdšPÓ©UÒUÒf}ˆ¿°ÇÃ7mÚ$ÿ?þ(Ý1îqãðW½ù\û˜ðù™gž¡W_}•Š+&±‡?¼ù\½—" ªÞœi“€€Ýâ=yò$}úé§4pà@ÂgOk9 · ¸Sìa PÏž=©sçΔ)S&͸ÙÔ+¾A@ßàªwõÆš7–ðÏ?ÿL}úô¡7Jì‚ÑO]LÓÇÚÇ[½zu Üu×]Ò»’”¦Ò‡)Š€#PÀÓ H-žqþ¹sçJœÆŒrë`ˆó§#OÇwÞ)Š@Íš5å–ª¤Y½NlTìùÓÞ3ö8ÿ¶mÛèý÷ß§#F6Æ`<¡ ˜‹°°0zî¹ç¨W¯^T¨P!EóB™:t졈€*¡8ëA2fû·3gÎРAƒèã?¦£GÊíîï ²W†aÇ¥H‘"ôÊ+¯P§N冢d”¯©FÀgÞ·o}øá‡ôå—_Ò… ¬mm0JõÃôIFÀ®teÍš•^xáz饗(W®\rû¼%ù¦z¢" øUü>Ú#Ô[†°ÿꫯDøïÙ³GÀQw¿3hÄ>eÊ”¡7Þxƒ}ôQéœ}Ñ[í…" \U®‡~ï3<Ýýpó¿óÎ;´dÉy¦ÝòôY'ôÆÉBÀ3? qãÆ’дiS¹æ$ N=Yð+ªøþÐ}¸Ým¼råJüãÆ@Tð;Ÿ.ÌJcù?ôÐCôæ›oRÙ²e¥óšàü9Ô*ª( ¤)vÁ¥|  !C†–øy&¥iÇôa)BÀÈ‘#½øâ‹Ô­[7ŠŠŠ’ºPpŽ6E@pª8oN‚²GÆR4g†N|ðíܹSÆk$A @Ê>åË——Õ<ð€ŒÚ>÷AƒO(T¨é ¼ÎzÆù§M›&îþùóçË` 8 pž¶ÀFÀ3? Y³f’аaC˜æöüjïƒU‚oN3"{xíÚµ²aÏèÑ£¥Æ ‚ß1Ó嵎xæ<ñÄôúë¯S©R¥ävºðÚCõFŠ€"lTH6dzÁõ€Eo„¶æýä“Od«Þ˜˜ó_¼ úÞîÝÉ“'uïÞžþyŠŒŒ´ö0tDÃÖ¡(ƒ€*3UÑQXôp£9’úôéC[·n•¿±ß<¬?m¡…€=? J•*hß¾}h £Uˆ€*œ”@í’qçÏ›7ºvíJXÞ‡f·ulÚïÔ!à™P¯^=ÙØ©Zµjâ PO@êðÕ«” >%é5ŠÀÕ0 @öìÙ©páÂW;E…(P }àsÑ¢Ee© à0£…F‡­ø Uü}ð=V˜yÕªUi„ „Œì$‡ìo0„”Ùß¼'6"Ì·ñ!7¤yóæ4wî\úí·ß¨téÒBJ‰!¨ß)¾C@C¾Ã6dï aãÖýúë¯éý÷ß§;v&ö˜pÈ‚·ç|T¬XQjÜwß}2r] Ct<ª8~Š·ƒöª‡¦þýûÓàÁƒ)..βüL‘˜À¥öÜ»‚‡pP=¤B v„bˆ9Ç9ÚEÀ¿¨à_üƒþé`øP` ¢­^½Z ;Vþ6îaœ§-°0£Ô=øàƒ’ñà 7ÈÀtý`ϯö>øP øæÔ‘#ò´ü&Mš$ŠÀâÅ‹¥¿PL®€# º&ˆáCøcþаC`ïÞ½©I“&ò7Ž›ü9 ÿ(Š€#PÀÓ:0Ö!>:TöØ»w¯€`w‡*;R{œ–>v|øá‡e@ö¹ÜjÏàE@€à[G V¡‰8p€úöí+ëÂá&öt%;z !Ú9{è•ý° *ýaG@4ûü†(D:lEÀñ¨àø) Þzæ,[¶L\ÇXBˆf2Á‹B`ÌÓÝß¡C‰ó#ËMãü5ŸÚÛÐF@€ÐžGŒÞ3?`üøñ¢¬X±Búgw3;¢Ã!Ø ³žß”rnРþ-ZçA¢Ð!<ªüÏ3† ÁÏùóç%$Я_?:xð  Róü3×vÜK”(Ao¼ñ=ùä“ÒóûgNô©Š€7PÀ(ê=¼Š€=~¼{÷n)"4lذÅ…Œàñêƒõf @.¼3øÉ”)“ìïЫW/ÂÎ~höyJp¡þ¡(€*1M¡×IÏü€… ʲÁ)S¦šà;šðŒó·k×NÜý(ñŒ†0ðÇyÚE pP pç.$zî™0fÌQÖ¬Y#ã×üï‘:»‰ó×­[W«V­ä!ç÷Öz'EÀ ¨à„YÐ>\{~@ll, 4ˆ @G•kíqêëÞLOøvüŠ)B¯½öuêÔI–dšp‹YžùŸ‹õ€" $ªä´…n§íqçíÛ·Ó{ï½G#FŒ@Œ€2+tQJúÈí˜Á›Ò¹sgzå•W¨@r;ÞI¿«ž©(€€*0KÉè#„Ÿaêɸ캧Â愸¯g~À¼yódÙàŒ3¤°fƒé³Ô àçoݺµ¸ûkÖ¬)ç9)Î9žöÒ{9ç@(šïíšN09ú‡"F¨F@ûú1`’HÉò53Ãs¼ÍˆSŠg~À/¿üBï¾û.mذAn©ùWGÖŽK5Dðßu×]r²“âüû—]¼s ¯Fðes+ŠX~ê˧è½ç!àÛ7Ëyã º‰5 «Ÿ¹„ÿ¿«6SLì9§7,`síûŽÒɘXKø«ÌŸ€b¼&v~Þÿý„Í… DEEYÉl8G›»²"p€uŸ?~úôÓO «+ üá1Á°òµ™”¹¸Ä}@†ðß¶ç-ݰ].»|Ùí‰JÊ=®uŽ¡éã§ÏÒöýGe¼x–húZ}Ö㊀/PÀ¨¦Ñ=/]rΓܼs?=ùîpzèÍ/èÂE÷®lÞè†a·Ë6í¢FÍ ewÉm¡p€‘fêg¥ôFhA°aÏylH³téRÂv´hN²jS:ÆÔ\‡~ ÿûßÿŸ^x¬ã¾%·ßðÄ iÐñˆñ³éæ'ß¡)óWÉ­àðV;}æ}õç<ýÏr:vꌣ”[oQï£$†€*‰¡ãÐï`¡eÈžNœ>C|û'µêÚŸ~ž:ŸÂ8‘+Ì/·ððŒtŒ-¦Ÿÿ^J_ü1‡¢÷Ž·œÒ Ã6Š‚—›¬ÛÁµ …‚;Óýøã4sæLjÔ¨‘•`”…dÝ8@O6cÝc9ßüùóéË/¿$dú'àå‰ÌÓuúô¼µ0Óï´…«é¶çûS÷?ÑÁã§(2"“×gï0š·z þ}6ý³|³(¢ÜòÓœ Üz}ÐzCEÀ†@FÛgýèpŒ‹ÒÄDGM]@Ÿü4‰ÖoÛKQ‘Y(g¶Hp-ò…0v±e–1czŠÈF[XøÃuZ£lQj^³åÍ™MƒõîÏfzèGÓ¦Måçûï¿§>}úPtt´tÏ÷g}õl3>yðyûí· }ÐŒ'À ‚ß݄ҋâº&z7}ôÃDúkÎr¡ãLÓ±qXó>Uó«"-Kæp:sî<›·š–oÞM-kW *¥ !¡&^ Ðü7Rúo°!  @Ì(,ãEwç­ÜDý¿Ÿ@³–n ð°Œ”+{VÈ}ºpá¢OGcú‘9ÿüó! sèÁœvõCø>~š>ÿu*}û×Bl>{d `(+¾_Íá~·ÒQd¦pÚwä$};iU,QZÖ)OÅòç’ÙÃ9ð hS‚ U>›`€Æ:Úºç [ü“iôß‹è< ûìY³S7¹i5ãÍ’9Œâ¸篥•l95¯]^¼àÜîsüo9aˆ½êQ7 cÇŽRMð·ß~a‰s}Ù ]á<ñIJiOÉ’%…,Œ"ä„?ñd±Â áËþû‰séÓQSiË®ýìÉŠ Ù²ˆà‡ }åoš…B¶nÇ~ŠÞ{˜êV,AMk”¥YY!ᦊ€À ÿ ª8t"!ÜîìôtúL,}5v¦üì?rB&$oÅçøk`ÞÈ7ˆŒ§C'b臩‹iɆԂR…ÜÆ8…ašüàŠ½ëýõWzê©§Dø÷ßBœAiášœç‚Fì^ŒæÍ›SïÞ½ Ûõ¢Añ‚c¡äÜÛÛçWЃ„°Ø˜ž¹d{²&òÊ•M”‰½Jðda~ Ðú«™¹àþ ¯³Wl¡5ÛöQ“ê7PƒÊ¥D‡²ÀD"ï§¿ú©ÏU¼€*Þ@Ñ‹÷âÿ…©ã¶cf.–˜èjŽfÈL9£"…A^ÂIhb9±"–1…QÚ¸ë mÛw„j–+FÍ8? wvÎKàæÄüìeŸo¾ùF<;vì¾BXBpz³Çù¡Ô¼õÖ[tß}÷I·Ñ(8Ç ÍîÉÚ°}}üãD7k™Ðrެ‘¢tùSð{bá–…•ÛÓgãhìì•´lçpX ‡4?À1ý;pwDä¼ÜgðSô¡Æ…k¢%Î?cñ:ÊÈ1Ò\Q°Žáî?ë(±!{ZNó×nçü€ý’ÐóàZ–Êõ·Úî.‡°’÷¶oÓ¦ }øá‡4xð`Š‹‹“>¢Ÿ°HÖŒ‚ë>{öìÔ£GzñÅe ¤XÙÜgœã„/•‰ó;C_Œþ›¾ùsᘇ°@ëþöd%†Þ¹ŒÒQX†pÚsè8}3aU)UH¼\EòæKâåJlú"p5T¸*i|ìŠu”žvî?BžB¿p†lÜyʆd(šNüžPY–çœåìíñÿ®¡œЂ3«o,SØQ–„$&¬eìqÍ…~øa Œ;V¾Ã9PŒ‚ã9Þ´üÛ®¸à¹¨s€ì~,yDƒB‹ß Âßиû¹o?Mþ—éz2ÁúMçˆ÷dAñuzC±¶Æä¬ŽÞK[v¢z•ÜùÙ²d–!¨"àô™Ôþy"  €'"iø7¬ X@Hò‹åeHÃþø‡¾øýoÚ{è˜$C!!ÊÉÖQbPal’À™Õû¢‘“Rv"? DçdVÃʇÐ4–3–ÌaËáI“&‰"€Ê‚h8Ç_ùžqþÆSïÞ½©I“&Ò7'¹ûG–˜FðÏY¾‘ðŠ•ÙüÛ¬Xq²'K½Æ?F ÄRX„àfpÝ€Õ[÷I’àM•JÊX·Bã/×5† ‡¨Ž´ùŒŒÂ¬™Çšg,ë[¾q§<ÉÅÖÑEvõªð7(¸ÃXÃYx¢!$°•3«kWàü€å$ÛÇ`9AÈk}ºýöÛé¶Ûn£¡C‡Ò|@{÷îÅa97­Xöx&,}T9„—Í„'œ`ñ£?Wûì3)&ôÎ;ïÐ_ý%ã0BÚ(8r0•ÿxºû;tè îþ *ÈçǸ1£ÆÝú¨â·vëÊÊqqçwÊŠ•TNÍU/I…L¨À¬Ø¼‹6±÷£>/lÌK³Æ—0VEàªðéA?#  €'VŒZ0ɸóys“Y\ñlíA#8³ºr|fuÑ|9åR'0Lc{~@Íš5iüøñòE`ùòåÒWã¦OlÌ×ûÏ‚BaÜýXÇ?,SDƒ"ÏžåïÁùOwfÁê-î+KÖóœòŠYÏ8‰«ÞÀÓ(¬Ü^¼ä¢iK6Òª­{%ÔU·Rqñ@Y€ºào/—7Æ«÷üÏM‚ÇÿŒB¬#~ã»x2ïfÖäZ²~›XÀˆóÃâ5áo€3F&³z 'Smám_ëV,)IUÙã½"NQŒµþcû\ä $Я_?:xð  ç@P'·™ë üK”(!üžä¥‰h&Ì€sœÐìqþûKœÿ×é 靸@Ò*¬à`÷d%6FáGq¬c§ÎÒ¨Kié&Ǫ@e‹æãK5? 1üô»´E@/ã %ÿ2 vÄC¡é¯Ü¼“°[tÒ¼•’„B>`ÁçO)Œ–åÄ™ÕöØ‘ •ך²ûô¦Ê%ÅÊtNþ·œŒ2!.kïÛ·o/I‚_}õ•e¥ #¸Ã÷Ãøq¿L™2¶çíÙ³§,IÄu8îÁoèú ‡­†ý1“†bÅ {p øyÅJbs”Ò!á\ këÞ#´cÿ¿Tí†"Ô¼VyÊŸË9›g¥t|z]p   €çÑŠó3“ú裲lpÊ”)2n(FÁ‘ƒñÿ@1„ð7ÞìÒw?– ¢Á€ë üÑLY±‚ê}ý0VðÜ ¾mU¦ä±jKˆp“üN‚ˆKx•*e6¨ÂùÕÊðΚár¼\ {®… ªxa¦ðBLô"[mßñŽfƒ8ÉKÞ¢8 ›ö„ª«?¹ðÂr2™Õ»§¯ÿBfµ»òZ¡<Ω¼!nϨW¯Mž<™P@ù«W¯–¡Ûóp „º‰ó×­[W«V­ä\(P œçg/†ëÊŠ„®š¶hxeÌŠUh¯OáF Ì›xM^¸žVnÙËÞ€rT«|±øü· Ѧ¤ª¤i¼Øþ& zú¢µ²¬oÁš-”™]ĹçgËH…ò@6–“;?ÀÅÌrmÚ}˜ês±dVgË’InèËÉuXûø k}РARYðèÑ£Ò×0Þ¼éÂ… "ü‹)B¯½öuêÔI¾ 8ÁâGg¯ÄùÓÓîƒGe§¾Q\Éï «ÂŠˆ*ü2­ÉúÇÐ+¼\GNÆÐOÓ–ÈæYØ_ tá¼r/œ:R5 YÐêÉ)D@€w…I¦£u¼ìé#ÞÜdüìå¢`s¼ÈçO!¸ñ—Ë ®Rà=}Y|fuͲ²M+ÖžCY€£Õß–“=? ""‚^~ùe¾>}úзß~+–}çÎéÕW_¥üùóË(ç?wþ}3ŽW¬ü6]”óÇe*\]’Aò6sâëv.ÿ]#~ó¬¼9²ÊŒ²ÊÇéåŠ@¢¨(<ÿýÒç?râ4 a9bülÎø=CXÒÕ]-þÿâ–š#n«È]yíDÌYúeÆ2Zºq—dV—+æ¬ÌjXñP\ ØK–,I#FŒ ÇœÆ'µûkÔ¨!P89΄Õ¹@Õ2.T…š ’¸Â+VRC»×º4eÀl;¼pÝ®”y€ÝX†rq,lìåöZcÐã€*IœC!4¸ûñòþ0qžlÚ³y×~É€ÎaâüîÓ’xW=-9Øó¶±Õ4ü/ά.ƒÌêrT w”ÜÊ –¼&?´Ò°aCùAççÐ…{Å qbß^Ï?‘¦ð’U8¡ÍŠu÷'‡J“w®á+Yxó,x]þâͳ–ËæYå©:¯€EÂo&+mŠ€WPà:pâåÃKjâü³–®&9wåFÑÒssÑó_D/~ ^讼æÎ¬Æë\yÍdVgÉì¬ü(ˆñãaÇÄù!ø¥?éiÿ‘’´ ¥+0tÅŠ 6‰·‚r+›gq~À!Þ*ùû)‹8?`‡x¹JÌ-wq‚r›Äáèi‚€*‰L”=ο‰7²ù˜ãücÿY*±}Äù¡hœ?}ø•Û*r—¾pñMY´A2«›±7 NSyÍíŽqB~€Éð!$Iº5 ,Iàö-‡¯seÊí\Ô'*K„®XIо9 ÔjòÂ(mØyPjÔæ•·Ô,G(†¦Š€À ÿxU®¢=Μcû_rÁ“áœuøø)aÌA5ÎàüpÈ-ÐÒIý€£U-]„Zp¹ì‚y²Ë€œ¢ÜºÁÑã QÀ!øñ³‡]üŸšJˆ‹ÆÄÆY10µŽ‚ƒh}5 0C4T^‹‰=Oc笢eœ€Êk•KJóÌjñdqLœÿ·é‹$»íÖ=”5Ë•8?ܽÚ«!ÒpožÅ¬žÿX±ymbï– 6楃YÙ#ЦŠÀÕÐ þc¯Xq~üq¼æÞÜäó_§ÓÎG$Á/»ÆùƒŸŠ½‡™‘]XØ qþ@žÅÀë;&~2râ©/?–³Æì‹gè=Oà宨Fõü^ÿ>|ÃÁÒ'¦W¬lѦø_‘ž ~¿L§>”ðM+¸ÎD  gBª½RE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤zCE@PEÀù¨àü9Ò*Š€" (^G@¯Cª7TE@Pœ€*Ο#í¡" (Š€"àuTð:¤þ»aºté(}zßM)î¯MHk2ø˜¦•ªÓzFõyNAÀwÒÂ)# ~€eÈžÎ_¸H§ÏÄ’/ڥ˗éÜù %@ * 1}z7­Å2Mƒþ|Ñ@Ó—.»XqöÅ[ã‹ë=ï!  €÷°ôË`¹øÉÇNÆPþÜQôæSm)k–Ìî¾xÁb7l±nÅT«\1Š;Oç/^¢ôPü2b}h°#t}&6ŽbÎÆÒ£w7¡vMk“‹ Ý;.7åæË™•ZÕ­H™Ã3ÒÙs¬Ü2°ªÜ;uéøìd´ÿ¡ŸÀ̱N±u™9œ:µ»…^ìxÍŸ[%Fâ mbá¼9èéÖ huô^š¶d#í>|œ2…e¤Œìy¸Ì”6E µ@_…€?wÎS½*7P¯Gï¤u+[·ö†Úiôâp¦ßµËÓe ÓßK7ÒŠÍ{ÄÓ9<Œ•jþOÉÚÂ]?'ªؼB Ã] ënÑ–õªP¯Gî¤Ú•JÉHpÌ1S¸!?»*3ËòÅóÓ¼5[iÎÊh:ËT˜x.+Ç 0jrNwA³/]bz:C¥ 祮÷ßJµnÄ f]ùÊ:ǽóåÌF[Ô¦ÚŠÓ´Åi˞â؆‡ñ³U¹u‘hO¼Ž€*^‡Ôw74qþ31qtcÙbÔóá;èî&µä`T°l|!üñã Às`9ÝR£ÝXºÍX¾‰–mÜE±œEM”ù¤ÿ(‰#`bï'cÎRTÖz‘?„þÜÙåB_)´¦Wð¤¹é5ÝP$Ÿü,^¿“éz#8zZÂx§T¹5ˆéï`B@€˜M0 0Âã§ÎPá¼9é•ÇZÓ3mo¡ÈˆL¼`xFêëá˜ç€!æÎIšÖ Úœ€°ÀÆ]EåäbEA=¨¾žÀ½¿åÉ:{Nè䮯5¨+´ÕÊ—A]ºt™ÒsxÉW ­9K¹eš†BP§bqªTªÍ^±…æ¯Ý.Þ6Qn-eÁ~µ~VUä•5ßZ‡êT8(^®­{PXÆôü£ù‰a¨ßª8lžLœ?æô9ªRº(uøvº·y]é%,± 8$à¤f¹PÙíW)2««q²àŒe›Ä+p=’Y­ùNš·´ê‹ dOVV[=wosêúÀ­T$_.邉óûÓu- ðž]Q\ÓQ¹bù©lÑ|´`Ývš¹|3>#´ž;­ù×BQ;U2C&ÑèÇùóqT÷[ÑÿÚ7—Ä(X"`2iM `ôˆû£¿y9³úþ浨–dVoÌjô_3«Sƒp`]ky÷5? ¥èêu¾D@¢Ë2ŸãØÜä<>¹H n,+EOn©UQžèqþ”Bg·œÀ<ëU*A•KŒÏ¬Þ&b4³:¥èúþ:(ªv¨LY0w)Iͨ²EFÄÇù±½®³–ªú~×™–‘ãÀö>oÊ•“ž¸ó&Z³mMçýv:F™8É7£æ¤ÅTè3’ˆ€*I*¹§Ibs““§c¨L±ôâ·Ñ#w4”(Ibå Ø-þëaf·œ°>üÎú•Ý™Õl9­ÞºW.WËéz(¦Ý÷˜/(oX±‚ý @ÏÝyÅJé"ù¥Æ“e¼´ë™sžÄðp»’€%ƒå¹†À¿¼yÖìÑtœ÷<Ðͳœ3_¡ÞU¼L’áŒ8?¿è9³eW?*žåÍ%OrRœk³Á¬ýͰÅrbtP(Ovz´U]Ú°“3«o íûÆgVkå5/“j’oú]›+MjUe}7W+gÑ4æÐ q~÷Jÿ{ Ì;e¹-Mª—åͳ¸8' .å%±ºyV’ÉOOô!ªx \Ã$çÇçvMkòæ&wR•2Eå Æ:r‚Õ& ៷ZE»Äž óYøáŸùŒ_…â$G`![ù‡‹®>#Ë!h4? í&BýÇùOœŽ£Š% ‹Åÿ­7IÌ<8¦Ñ!CÇxÿða#ˆÓ±„O2KUΨHº§IuªÅu¦-Ý@yù úÎ ‚(. /Õ¿Ÿ#  @*!f^#/ñ9ÎøEU°z•ËHœ¿e½*rgce;Å:cÌȱHüÍ›7SáÂ…)22Ò1±[ðÁ0!Xpfu¶œþY±™®Û¡™Õ©¤×¤^ì1²b…½W]9„õì=ÍØ«å¼+F؃¦?NG¥2eÊÈP/^¼(´nè*©ã÷öyâåŠÏ(Q0=Óº­ŒÞ#ù{Žœ „ºtó,o£®÷»¡—©s=D’ñ=˜$o&ÉP¸|ï'ݢɟ÷"·•ívEú›ù`H`’è„ÿÞ½{©sçÎT¥Jºùæ›éÏ?ÿ”ï`à<ôÝß  B(*23µ¹¹*unÛ=*…¤Â²ÏqNüiþînÐ<˜‚®O³'+Žwì{€­ý)ƒzÑkß%ž,4œãï:½Bðƒ¶GEuë֥ʕ+Ó«¯¾*Šèßá<7Ð*ú"Ö>¿bÕÊ¡®÷6¡»¸ª Šbaó/4Cûþî¯>?øðÿ[€퇟“çÇïçïkIÓ†¼BÏ´kÊëÙ3Èz~¼èÆýçÏ!ÂaÜý.\ O?ý”jÖ¬I_|ñ?žV®\Iwß}7µnÝš–.]j1SXNNQ  /Eòqfõí7qvu=þœƒÎ²×åâ%(YneÁŸ8ú³!œà¥:Ç4râôYª_µ ýþaWöÆST®DA¡iÌS)^®¿ÿþÛú÷pŠr #ÿ¢j™ÂÔµ}^5À™Õ™5³Úà ‹Þª£(ßËù*»óŠ•Á=©EÝÊŽŽóïÞ½›:uêD 4 iÓ¦Y´n„º_R~Û•[$ >üðÃÔ´iSš5kVªî›”g'÷Qnù"x¹òåÌF[Ô¦gÚÜLe ç•ä× /«r›\Põüÿ   € þ‹ì>>ÆÛy¢èÉÈÞÿ£ßúu¥Úl)yBȸ“¡lùá#úagf°ˆÚ·oO·ß~;-Z´(u„sSÚìqW¬øè£Är>|¸ÜÒq–÷ ó–n©QN\¨õ«”’y Õüx@ðƒ+°þ»Ý+MgOÖS¼]/ò(œç½}òÉ'’2lØ0÷»Çý5Þ®”Ò4Þ»Ò á%Ê@ttt‚w'¥ÏðÖu0òÝ^.ð"lœõ\»FÔ±y-Ê=‹ä`<8G›"T`Ô ÔÑçGLù½çî¡©ç¿»IMaÏQ5þ úÀü@9ð·¸ð¤©%K–ÐwÞ)u)V¬X‘€¦|EOF©€r{âÄ zã7$ÜõÛo¿É»÷ ç8…¦”ÛÈÌ™èö›*Sçv©' ^àœ¤8®áºW=ÀWÔ|÷ IB ná“1±tKíŠôÇGÝhPG¨D¡¼ñq~·»ßßSÆdâüÓ§O—uÍO=õíØ±#ÍãñöþÇÑ£G‹"Ɖ2¬`¤8n«?ñ#D_Ðgþ_vDå5ì:˜9<£Ô€ *”Y¨^ÇØ“•7G xáQh[Õ·¯XqÞz~Ôxþùç馛n¢‰'Z´ž–‚×®ÜB¡½ï¾ûdé –B á§(˜g(Hx…b‹Ø’óÄm+ýï@IDATÇÒüò@zvÈ)çgŠ¢'eŠæ§oÞzJ„ýª7È …Œ/¼¿›)mذA˜RË–-e]³Yå/¦d,I|¬Ë†ë‰‚ßÿ½À¦i¼þÆs‰éD(+8ZÔ.Ï™ÕM¨^Åt‘-b(‚nËÉÿsž¬¬8?V¬p{öžæ¼žÿeùm{êÉ‚€G½ ÔøüóÏEiô'ÝØ•[¼_(„RÙP¶úr”rËóìör¹•[l9Ü…ó:ÜR²g 3\VJB°(· kmÞG d#Ô±¹IÖ,™éí§ÚJ2Ô½ÍëŠVo’¡œ øõlÜ’o¾ù¦XÙv·¤ÀÞ'‰äÝÑ®¤ ‰êÑG¥Æ'¨Ì–––\b½‡ 4–ЬÜÏÉT ”-’O”Sy-±{8é;Ъ;Ξ° e«úUiüÀ—Äò/œ/~Å w´ïïæ)\aéÃâG½ Ô­£Ú÷gâ e á6()  sçΉGãÁyþn–rËýÁçú•KÑ \«9—ÎÀK~ëµNàkþÆJŸÿ_üÏþÛ'¯ xúl¬¬~èö›iÊà^¼c_kÞd&‚Ž;Îï&éÉx~øá±ªß{ï=Ç%&Ù'É0w0XNsæÌ‘Úì>ø ì8hw¡Ú¯óÇgØøW,'—,«z–7Bfužì‘“Y Á…îþJ¼[âïN7-p%ÎÏçø»jâüÿüó5iÒ„yäÙÜÄÉLÒŽ±ŠŒåôóÏ?‹çâÝwߥӧO‹•gÆj¿ÎŸAøÃD«]ÁYݪnEά氆C3«¢Š+Ø_þƒçî¥iŸ¿B­9Ëß¿3+S¢~D=d·>Ô•0Ê¢S¼C‰Ñ ]AA,_,¹MìùÉùέܺ“_ çÍ!…±ž¼³>×0É©ùÉ2DÎõ¿ôóÐüpé;C%81fè«OȦ=j”†¦F &äïfg.p¡?ôÐCtË-·ÐìÙ³ý’ å <ì–Ó©S§èí·ßOÆ/¿ü"˜CAp ã·[NY2‡Ómõ*R—ö¨VùâîÌj+?ÀȤüè'D¬XA.ÃÓw7aÁÿ2½ðÀm\ð(Üòd9mÅ ”Ô€ ýã?–(1ÿFYL9"i{¥Q\’nŠna[ml¯í¨ü€x—?ú õ¶b‰ô<¯hߤEeáüÞ_Íоü¡ÿ„$A¥€ùA¨#Îýµ_å=̧ y•:¶ª/“kâüN |#Á8LyR0ÉŸ~úIú &iBJ™vå›°<ðÀÀö­æ ç€Qù»&L~@\Q²Ë3w5 R…9³š•€‹*ò‡pFPhc¹0ÎiþÍêT¢qwãJ~SqVnAÓ€çø»y É©S§J½Ôصk—£„dJ±2ï¤y?±­6Þ[”ÝÆvÛæ¸còx bð0}4¬Zšë4¦¦ÕËÊÐP-Ž•Ò¹ÆëüÏ5¼€*˜7,zln‚ZÙ÷µ¬G“õ¢7ž¼›rq\׉››ˆ JêÖ­KNÜ Ä S#ÂÊŽ±œ°m+¶o}üñÇiûöíŽ óˆÊÍ'qÔûo©)¢$³š…mZ)êãW¬”-V€F¼õ4ÀMxÏx·uÄLÒ!Ö‘IΛ7ÏÚ¢Ô³N0Ò ÝrÂø°+,§~ýúÉ2B ÇXNÌ Á0™-R½J%$³ºE­ò\dÇ÷™ÕP–ÀŒOœ:+‰ªï<Ó^âüí›Õ±02Þ.Ó !¼ðd¡Ä믿.yصÇ1ãíòw_}ñ|û;}½­·}ñüäÜBžIZh9OÜq=Æ?…yoä¼\º¤›g%Ï`87 Œ£ç/ÊKž÷zT¶4½¥VE±Žœç·3IïyòÉ'©aÆ²ÎØXÆÁÌ$í/ Ɖí\_}õUɬ3fŒã†ÝrÊÊ•!Q@•ת—-*[ÃròE‹‰_±òÈî+=¾ƒ²ÙV¬€füÝ<º‘#GŠàÿàƒ(66Væ×) ¯±Â8A׿]?~¼xõºuëFt–—‹K(fè3B^ð<Ïa»ÞÈÕÃél|~€¯1Óû;&„€kìÒ—>O_´ÆõÊà_\‡Ÿ²ÆÀ.S볿?0Sp1£”np±ׇ~èÊ;7Þ;ùa«×úlŽ…ÒofD.;¼Ý«‹K [ÓÆ1U ?ë Ÿ>`Ù£d=}Uô׸¹«\†­/RøÁÜùÂ…‹®w¾ãú{ñZëN iCGÖA?}@?Øêµž>cÆ ‡t,:fÅÎ…y %:ö«¦‹)ââí¹™NÜ| ¿Íg D?~°Ó/o‚æ=s¹kÇþ£Ò#§Ðœá úGC ØfööÏþ'“dëÖUµjU‹)‚Iz2Pþ›-'~€„oÿêâ¤1kíÇ:觘[›à³7ºdgºP8ìJ‡7{@!3mÓ¦M.Nê´èóê‚ßþ û{Îy>®I“&øD‰²Ïµõ…Ÿ>ØéÌþÙOÝÑǦéð&Ü€mÌ#Ù¥åŒJW€’µ{qùPlÍÛ»woš2eŠà‹87¿ôâ~ XÀ}ØqàüÐòåËG¯¼ò a™Uxx¸ÛeÉøÂÍê„Æ»Ï’ñF²š! ~N+渳P“zئKúPÛÇð™7'ô×I}ðħ]»vªT©"ÝDèçù»Qà„¾ø‹Py~À+N™(0@¼Èh{öì!ÄB‡*‚Ë-m×Gù`ŒhÕ«W—:mÚ´‘¿íÂHè?>C4kè…úôéCXÒ‰fŸ'Ÿu"Hn <ñ“9sfêÚµ+õìÙ“òäÉ##´ó ²#`‚Ô– øÅµbzçÏŸw 8Е?~Ë5ÊÌÓúÌô Ÿ“ˆ[! ò¸t¬‹KÇZ3å¤ü«SAò®i»»Ÿ‹R¹¸8•E» iÌÒsòßg;?(Q¢„‹÷°¨ÆÎK¬ƒúAð!ÐHµ¥0I{lúÏ?ÿtÕ¨QÃbŠöøŸ2Êä3Jƒ[NV~˜'oëâÍc¬³ÏuP?¤;ž[·nu=öØcMÛçÂÌþN>mCy²ó‡ ¸x›okÎ0à/Ú_#  @2ö´Ž–.]êjݺµÅ$Õ:J>CLб[N… rñö±–¦–S2‰ø*§C#tΜ9ãâ–+W®\ è:)ó¤ç$þ¡@©2˜uèÐÁÅÛ~[³c÷ÂXõƒ"àETH˜vëhÿþý®^xÁÒäÕ:J:ã3 /¹¿=-§Úµk»&L˜`Í ZNIþàéÉ=z´«råÊ–P²[ªÉ/=?iï„ÝhÈš5«‹·ÿv8qšC;ß±êEÀ ¨í&>sýoWáÂ…-&i·N•é%é¥'(vÌï¾ûno3kͤæXP\óƒ§' õZ¶l™€¦sjæI¯MÞ»`W¶n¸áonÍŸYõƒ"JTH@Oëëx±ž×06¼°Ê$“Çä vÞø ¯‹ÁŸ— ºx»YסC‡¬UËÉ‚"Á;.;wîtñf=ŽêÉò=ãðTn›4iâú矬ùS/—…~ðª\DOëˆ÷wµmÛÖüv—7™Þ#uL×î (^¼¸kذaÖ¬ªådA!«U@Ûhqqq.^Ëïâz èZi1u´è-ü<1Þ&ܵeËk25?À‚B?¤U<À³[G‡vñZ]W¦L™„IB;Nj魗\ïã=f‹¹±»Pëׯïâíh­Ù eËÉÓ“õǸªU«fѱ7¥IïѤ7°´+·9räp½÷Þ{.Þ>\èÚs^-b׊@P (OKñ믿va®y‰í/¢9¦¿Å,1ž.Ô{ï½×µv핺ú¡”àéÉZ¼x±ëŽ;îH@ÓÀKéØytì9'v%­bÅŠ.ÞFÜbñ¡¬ÜZ è‡!ò €§=mÚ4ÖåšPãüÎgŽf®ì¿íùY²dq½öÚk.Þ}ÐzIìžë`}°uºtéb%Nzº—í¸égçÒ»§rÛ¼yso+nQm()·Ö õCªiÀG[¿~½ ëp Ô8¿s¡™£¤ü¶[NeÊ”qñ¶µÖ ãéõ±¾àö1A @½ÔM0X©'+ðéÚSãíÅ]Û·o·¨Ö®üYõƒ"pBR°¿ Çw½ñÆ®ÈÈHa’žZ¶aœú;p§çœbûZlckèž @nžž,ÔG@C·vEÈÓßKÓ˜;»2‡mƱÝxll¬1èÊ 6E 1BJ°[Gåûï¿wa½­a„Ê$›!šy¼Öo(ö$ÎŽ;º°­­iv9æôß`ôö~¯X±Â…ºõd7Mcží| ÛŽcûqÓ‚A¹5cÑßÞG ¤ßÌ™3]7V&ÉÌÊPúm·œ¢¢¢\¼e³ëÔ©S†<ò7êtïÞÝ…z˜KOe'”æ7ÇêéåjÕª•káÂ…IËÚé´C $XIØ©oݺu®GyÄzž±´Pd¡§ÇOMÿúôécÑ0êU`x*·³fÍr5mÚ4M¿k)UzÜJƒÝSS¼xq×°aÃ,:¶ç2…)ë0½Œ€*×Ôî"Þ¹s§«S§NVÜM3«ýǯ&Œ<™äW_}em„¢Lò {bñã?ºÊ–-k ~»•y5œõXÚѽ=„…BU=zôp¡Ü³ivþdŽéoE ¹¨b°œì.Ôùóç»n½õV‹ajfuÚ1Ä« ;“Ìœ9³ÔÂ?pà€5£Ê$-(|°ã‚úo½õ–+kÖ¬Bמž”«á®Ç|G÷žø·mÛÖ…º%¦…ª'Ë` ¿½‡€*IÀÒÓ…:zôhWåÊ•-E@-'ß1Ä« O&‰¢NØÏ48e’kÿ¶+·6lpÝÿýMÛ•««Íó.̓¦í|[9£N‰iJÓ ýíMTHšöüÔÖîÛ·¯+W®\Ó´»¢•Az—AOOÁ¯L2Ä{S=•ÛéÓ§»n¾ùf‹¦!”€»Ò³÷éÙ`jç… –º$ÆKã¶¹Æ4êaE E¤ÃULˆÚ’¿”Ä/­\±mÛ6â Yè»ï¾“¿Ùr’ßÌXå·þã€7pGc&I/¿ü2ýïÿ£°°0©ã{|Ö–<@¯`†®¹^‚ÐõöíÛåFvü“wg=ûZzöÀ÷¹çž£W_}• ,(—Øù̵î¡ÇÔ   @ Ñ³Ä Ê’ÜaΜ9ôÎ;ïÐÌ™3åo¼Ð†©¦ðz#`g’öúþPДI ^ûÇŽçÑ£GiÀ€ôÙgŸï5  ±7ÀR¸¼öл0]k´;3Þ~ûmªU«–üÍÖ¿(8O›"àSàЖrXÈ'Ø_€w”s•/_Þr™Úãz<‘Öqýœ8p;³eáuÇw¸/^lM”ÆD-(¼þ4mÏX½zµ«}ûöÖ\`^0?JÉÓðÕð±óƒêÕ«»x'Gkþ”¦-(ôC! ~K½Ñ ÍC«‡Ö~êÔ)8p }òÉ'òÇì¿7žÌ÷€÷ÄXGØæ¶wïÞÔ¦M²ç`ÆÀ cc$Ö>æmòäÉôî»ïÒÂ… åox¿08O[âØišëŠÐ+¯¼B;w–­É~Œ·+ñ;é·Š€÷xÀÍ{\ŽÙÿî;Ø´i“0Lì3†ܼìÞ›Â๓IæÏŸŸzöì)L’—øY¸9…I^â¸-úâ+'-ñ¥ôq#”…fè—‹ÑÐûï¿O»wï–ãöy“ú…€¡W`Cà™gž¡×_Š-*ç@2 –u‘Ÿ>°ã‡ûHŽá¥~‚!¤Ð ÀÅK—)c†ø¤;f˜xÁ|Å“CòxáÍ‹¼ä O Çñ=ÎÓ–0ΆùôÓOK2W>xÅ$AgÜ+Ц0þ£üÚ øÑŒð˜g¥öÞ©½Þ>¤~ýúÑ!CˆÃîw0ÊBjŸè×cÎ@ËÀ 뇈'«^½zò·“âü¯˜Î2pÑÎ_¸HáaîÜ&9 ÿ/<ùרú’>¯Ý¶ÏõÃÔE®ÃÇO[c0ßYüø_~«"ºÁ+\Ø‘Ž©I~ìñ@s,”~3“LçG‘%[2ÍI1Ql®‹<Ÿ¦ûg©kàÏ“y~/{µæ3_×÷S¹–oÚm%÷'yë˜??Øó–/_îºë®»,šfå6äóìïu•*U\¨bš“h}ºxñ M¯Þízôí¡®…k¶HwAÛÚ‚·Ê ú GÎháº4xÌlš¾d#;A,'Qq™¹ãD6úóÏ?iüøñT³fM+'À„ÁRúŒ@¼ôІ÷šëƒˆ‡dÑ¢EtÏ=÷^Æ+蚎ëd`ê‘§éac©U×4fæöp9Áˆx}hpgÉNçØ9qþZôûlZ±y73L·‹LÊz€¸üÑÃ?…"À;Õ9Ž1øš„ “„àÏ;7}ðÁ’Tf°Àq(MNc’ÇNƸ™äóý…IFFd¢ÈÌá> î×LáaÄ.úò9ôÇœUt2&Ö 8AÀü`.!ÔðÓºuk™ÇAƒÉ:vÐ:š™oŸå›z*ú=öñ¶â²\5""B”"à…óüÝ@;ø2 ž4rÂ\jñ\?ðýDºÀs–#[wQŸŸ†øŸ"S9X!f~¹²D„Ó¡ã§éû©‹iØøy´}ÿQGYN`vË©R¥JbõòŽuÄÛ{&°œœ üR9-ÿ¹Ü“I>þøãë…O"##-oˆ†Ib ?LšG·<ûõÿ~3ÉK”#*K¼àó—É­¸º(‚•[dZÂqœçïfŸWÐ÷óÏ?/ÂîøÎ(tN~ÞÆÊS ºå–[$ÏE”J•*%49rM£’¸ E„þYºžnaué?’v:J¹²GŠ7 ô¥-txS6ˆ Ö°Œ(3[Nv¤¡ãæÒè–ÓÑSgm9µlÙ’æÍ›GȬFÒ,'§0 o¼Wc’³gϦ#FçC$P|¼ñ¼ÔÜãjLò6¶øŸíû-íeW|îìYÓ”IBA‹dåöôÙ83{¥„»ÖïØo%"¢Ïñ§¥f詾B}ý¢HÓçŸN , Ûo¿Ýòàœ`QníÊ<×ý ¬ô™1c5lØ0M;a¼öÖ&¦§ßûšî}y-XM9²f¡Ì\` ÕN £T¢Þ Y…`Fìf†l9±€ïß5Û8,0‹f.ßÄ™­ìZv¨å„¾"ónÃîÝ»ËÚ`XN8È–“'“äíg…I6jÔÈqB!“Üéf’÷€I®ÙB9£"Ù%ŸÑoLÊmÆ ìåbÀîCÇé› è»I iïáŽörÕ©S‡&NœHcÆŒ¡o¼Ñq‚Ñðäü6Ö<¨¨(Y݃pÞ< Þ[§(:°øÑç?ΆÐ#þ¤Ûºö§_¦.S¶,™Å+`Íäà çA¥˜)1…c´±ç.ПóÖ°å4‹VoÝëhË)oÞ¼ôÑGI~ïp' ÅI‰Cßëý6 L2{öì²ü Åc|ðA‹I×ñõîåëïíLòdÌYúàÛñtk—iÔÔ…âMŠÊ‚.ǹýláñèòð³*z/ ;‡þbÚ>}öœc½\PÊÛµk'á”Γ'O@z¹Œ2Ö±cGQØy+eÊ–-›Œ çÁ×t›ØýA'ø1ËúF±ÀoÙ¹½Ï @l\‡°"Ýïa¼‚ؽô»àF (3e°œ2pVu$[NûŽž«éë¿æsfõ1G[N°–þøãâí@‰w¼ ËÉu0I0~0IÄùQ犧0IôÏMîWà—i ©Ù³}éýoÆÉj’œçÇ9FA04åïßè~"2…/ࢿ—m’ü€ùk· Ó/+ 8Çß ô€ù=dÊ”‰zôèAK—.¥§žzJº†ã†füÝ×k=ßÐ+ð„2ï\ý?ýô•-[6Á»y­{¤ÕqôÑ矻bÝõÒÇÔéýohû¾ÃçÏÊüU65ΟVsâôçµðÁÅrâüdV¯ãØÌ¥±O=qú¬c-'0®/qTÄS *äXËÉ0IôÙ“I–+WÎyL’ úŒ%w`’­»}LOõN;˜I"ÎËÉéL4ÅZÈÀ ßf.§Ïy9ìÆ]ylîU08Çÿj€{%„@ä¹ >\ò^Z´há¸Px†iöV™2ehäÈ‘„ü$ûZ7Þ.s¿~ÛCXÑ{Òsý¾£ö½>¥9Ë7RvÄù™÷á'(†þÂHŸû_‚^0Cáãùhs8£ùsVFsl×¹ù`0Ȩ†åÔ¥Kq1:Ér²3I$õ!ÚñL’c¢Ûöb&ù-µëù)Íe&™3[¤0Iw2”Ħ¡ÜÄ»óÒK~ÀŽÇ®x%Ì~öxÁ%Š€¿.;­4hЀ¦M›F¿þú+aEŒñá7㹀‚z¨Û8ÿ#<"]sÒûE| qþÓgbiÀé¶.ýéû‰s9):#eC йhÀßóªÏÿ/!£˜¡›ù§cϳ'` æúë¶;;³{„?ažÄÓ³E6“o]gâÜ€0ãòM»èó±³iÒ‚µ2^(h†öå?ýc÷ApuèÐAÂDï½÷åÈ‘C¼èš?béž}Cm $æ¢nGΜ9ýÚ7ÏévPþÌ{8fÆbjÑ¥õ6†sBb%qç8-„å9ýÛ¿„œ`àv[NœY9Œöp6õ7\u Õ×öp–5x¦S¦Ýržáýõ—ä  [Z[NÀLÇX`’Xî&‰Â>°šÜ‰»*šÁÛ¿¯0IÌg:;s1Çù? ·‡Ž¡˜Øs²ö9˜˜$Æ[õ¸Ä+M]¼Q¼\‹×ïø˜zAlaë+´aÇP—õ9P²bÅŠiþŽ%ö®zu¿‡éhášhj×ãSz‚«SnÙu€rEeå#çO Cýî !«æ—"ä¥ò[O«£÷ÑÎøsÞj:uÆÙ™ÕX%€Ìú?þ˜°½()š¯,'0ÜÛ-T/KÉ^Ã$QÊ×®ˆà\6Ì«‰‰"Î&Ù–™äc½‡ “ÌÃÍ$áîÆÅs€ü€£§ÎÒÏ/¥/xÅÀæÝ‡D±Åw8Ê‚¿›]ðš8û¬Y³¨iÓ¦iâå24÷Çä'üûï¿„úþö²yΡiä¨ìØw„^üøº»Ç@š±dÁ‹.twT›"BZ0‰åÄ/ 2«ñyæòÍ’Y:âfc†‰wÊ /–qùAà†ó ÿÒK/I~@§N„éûÂõn˜$î &ùÕW_I—s™¤{íó®Gè…~ 6Ý?¡™KÖJ2T‡~-Îoè4¹¿A»a‘FÑ{ÓðñÿÒÏÓ—HÅL§å€ÆŒÀmܸ1aMÔðU¦½ç{„úð@8q…æ¼!¬³çâè³QSd©ê×ãfIžG ÁLJ›" T°e\þ¨ñ~ŠjPIp0ÇR7ì<à8ËÉeX.Ø[|èСËÛŽFŠsRcÛ™dæÌ™¥HâüØÓßùBÙ°MG²>Ú™$6…úì—©çÿfÜ?’ՙŠÅÌ4”dè+`°uöâ »¤šàÔÅxM¸{ó,àáåÖÐú„ºÊXk<Ð:ètÒf®Ç;‚1·mÛVüPu8ð ·°Mù3RÚ7ÏëÐ1@Ø‹…~Ÿ½LÿkCFÓñÓgØÝ)—hœß9ý;©¨p¤ðÒY¢òÚ®øÌê‘SÉ.mN³œì.T줇õxûQÙaLç$§y2I„ç“ÌŸ?¿åîO #NN;×Í$¹>~<“ükÎrjÎëù_ûüWY扵Ïh¡Î$Tä¼Äñ~“ü€eœ0ˆ†9—sø<7CWƦÚûï¿_úhOô9© çÚßÔ×@±cÇ:®J!fôŠ>ƒ®—®ßF^L¼=”w£Ü+¹+({¬!¬¤Î©ž—zT¸†àƒ°œÜ•×2ÐJÞep{&ð®ƒ1œIîäÌjl? K½oß¾²-))ša¬×²e]A€É&‰¢DÕªUK ø“Ã|¯õ¼ÔÇü˜˜(¬F7“D¾ù%­g&‰õü•Iþb(·X° ?àð‰úqÚú’÷ÍØº÷ˆÌ?æÕ‰ù¨·?jÔ(úûï¿éæ›o/èBýz´ºÇ¹xìû Î†·¼eÿ:…Dðóµˆóï9tŒz~ö3óù„¦.XMY¹t/V/ézþ‚«—ýUþIÂn«ˆ3«%vì¢éKÝ™Õ ×í`‹Š—á0Ä0Âyþnv—=Ö/¿òÊ+âB}, Kó “„à“Ä’C„Ë$ÙøCLtßáãÂ$QÌg 3ɨHf’,ÜB%Οš¥B0›g!9ð«?çѯ3–ñÞð1BÓ°­qŽ¿„;h‚´Ù¬Y3š;w®l&UªTâ;îá}0!ÜþS!þ6žœãï¬ÁC øã8„õÅèéR¾÷ËßgˆçÆçw‡üÝW}~ð àÊ,ñ‚2/’=àqÁ_f.“ZìN̬6˜dbÅyìL2Œw“„÷E‡ð·S™$¶åúûßÔü¹¾Ì,ÿ+0;Çù1ON\@ÖnåÖ] ®æ¬Ôæj‚/Ý$as’rk„6°}üñÇ%vÿòË/òS@§P@Ïv¥Šêf`ÅÌ Aƒõ4ð^ˆ°e%Àß ý½kô{òüU„({ ú…•±Óç“õ–¿ç)XŸ¯ @2g/+Š­dᤪmì6Æ™Õp£8æìÊk¦†9¶-…; ÓÍ|Üå{aéÏŸ?_˜$<æ{0]7ô ÐÎ$Qȧû§?‹Å w?š2ɔ͔I~E~@,[ŸÍ_CƒFÏ¢•[ö°P²ç¤ìþ޼ʮܢîD¿~ýÄËÕ¾}{‹ž…^˜¾Q'cܸqR7õ3 M'%làÍ>_í^ð­\ a¥ããNzð/¨ãëChÕæ]RÈ•üÄ“uµè1EÀ $/;Ì  †[ˆUÄŽ9dVÃDZºq'mÜyn®RŠU+#q:ŒŒÕä økÜÆóƒu„mKa 8°;<ï¾û.µiÓFºhÎs‚àG‡À$áêGÜz3ÉþßO¤‰óVŠ`‚à¿Ä ™&Cy‡º ÜJ~'¿<~šøºxÃNjY»•(˜Kâš6 }°ðQ‡â÷ß—Ø7ß|“¶oßNøýì³ÏÊRY(øq MsŸáê]8z’óŠ•‘\º÷ïé•5BpÝkS|€*©@L «.°[qò¢õ´2z5«YŽjW(Ÿà>‚ØŸÍ0?¸?±})–V=ƹ¹rå’%VNf’‡Ž¤OG1“ükŽl}‹x(ŠÜ«à÷>EZA È£ ²v+×=7«QV,S<Õ¸­½ßƒ¤ßÑ(·PÐn»í6Ù¨çäÉ“²¤ǠЂöýýþ¡/À t áýG¾czÄÂøFq‚6íQ/Ò–V¨à¤aÁ ³úÈÉ3RyméÆ]Ô¢Ny*S8¯<Áœã_5€¬¥P`šÅŠ“¾9ŠIÆ+U`’èã·Ì$?ýyŠlÞƒ¿Å$Ýz•fOoq5Œr‹Í³@»sWoå%hû©qõ2Ô JiQd âiÿj÷H«c&‰tŒâXXÏï$O°† i´é ׈'kÁš-R¶97¯ç‡àWáŸV£Ï1¨`ðÂohø°œÂÙrÚ¼çmß„j”-JÍj•§¼\~ ŒÀ)aXcEyaø©ºÅ˜ä¢µôáÈ¿hÁêh ©ˆ»ŸÝ¢Ê$Ss²/½¢¡8Ö™sç鹫y³¡=¢ÜV)U â1€iëg'—XúFq1¯dØËØCXk·î¦~œÄ}– fØøª'ËË ëí’Œ€*I†*i'‚eËiáú´ž+ 6¬Z†ÞXZ¶œuóT·× iwõÍYÆròÍÝ“~W;“\·uliŠªgÀ1Wvf’¬X)“L:ž¾8s!{¹2„ÓÞ#'è[Þ<«RɂԂóŠåÏ)tŠrë‹ñ'÷žPTMœÙüŸÿ:¾?›°‚({|K•Ù䢪ç{U¼hüýŒå„ÂçÎ_”B+¶ì¦ì ¨Î^XLnkÅÿ–“ ¸îmíLòèÉÌLr×7?cc’š u]Óê(®PoQ m-‡¢÷¦:KPSÎÈŸÀæE ­0ñ|Žyï!üñ~?qž„°6ïÚÏ5*"£ø8¿Û±ây¹þ­¤)ªøn±œâó¡ï§.vgVs~@É‚yä顯0íLüÀLòãŸ&ÉN}Â$³1“„àW&écêLÙí››ga.g­ØBk¶í£¦ÕËRýÊ%%»]¦Ž¿sBò]ÊF™¼«€ °0qþ–®ç8ÿš·r3¯Ê(•)¡ðªÕŸ<\õlß"  €oñ•»ƒºâóY½q×AÚÆÛyÖ*_ŒnáHB vEàjLòÑÌ$Wlr'Cɲ>T|Ó%PBÿÇ(rH~=}6ŽÆÌ^IØ[ %+·KtT~€/¡´‡°6îØGsœÿ–JØ ?è^CX¾œ½wJP ¥È¥à:ËrŠÏ¬ÆvÃk·sf5׸¹Jv­rÍrÜ7-';“ܼs¿ÄùÇ2“Äñœ燂¤L2Då€KàåÊÈùaÂh÷¡ãôÍ„„ÁµËSá¼9¤‡Á¨ÜÚCXÇO¡/¹2åpÞ}ò×PˆbÁÁž?µø@ Ú…k"  À5¡ñÝÆrB~@ì¹ ôç¼5´b3gV3ìZºpPYNv&y’cûC¸Æù°±Ì$¹æ|vŽÃE¬¿ïh-­îÌ:k‚ü€UÑ{ e²oªT’šÔ¸²ñ:w´`PÌûkÜý£¦Î§O~œLë·ï¥l¼E,ëcÅö@Ѧ8Uü89’À5À#¹Ð¾£§è»I Åu E xçT^K Dðv€ÿ&ùË´…ôÑiƒ0É.(ãŽó¯HJž¡×83ŸÈ€ü{Ù&Z½u/5­Y–ê±2`6Ï‚ºhù„¿¡é¹+6Ò®L9kÙIŒÄÖÓx§U¡u]j®Ž€*WÇ%ÍŽÂFc çú,.iÝάæÊ`u¸òÚ-Ȭæ„8´@±œìLëÂçr|ÉPHŠÊÌ¡S¾W™¤LkÐþzEÑ+äœ8K¿Í\Î%³‘PÊËÏ߸·†àïâXI™Ы)I½ç Xü¿ÿ½ˆÎseM§Ý+M'I=ÇIü¿½3³¢¸öøa“}Wv6aØA@eG‘EÐèÃAãÏFㆉ¨@Ôbâ§‘ï3š¸DIㆈDaDdÉÃÈöÎÿÜ©¡¹OÚYnßÛ·ï¿uf˜ÛKUýª¦ë_眪¢Imà‚íð¯•ëtšÕV]y­®¼ÖJ}¬áð¾$?×…˜ÿ7ùóÂ¥ràÀAÁ¢'(#ýü!ipIÊF,> ¼ÆT ÛvÊï_~Wºµm*Cu:lãúµ,a·GË*/{TÈüöù7dÞsoèþ¹Öñc?úù“Ô˜˜L P$iÙˆ—!ÄìÉו×þµR–ëî`Ø ¯`¹µ˜XÏúxÉc´ÒÞüyT·ç}ô¹×åk]ã#Œüù’,[»Hç»Ñ¤±~@e¬ ¿,×™˜ ƒ)ƒƒ»Ÿ¬V‚ÊV¼0 ü!ßn±¬¿¼¾T]X¯ÊªÏ7JªUlO^úùÓ¹e2ï!m±‘S,²zóöÜXdu]yMGNÍ„cåµ£/ɘ÷ù7–Úç«Öm’ôUOƒ¡0âçK2¤,ÉÙŠ WµriÌËÁƒ‡dÁÒùHƒ‡ôÌ–Ó:ºÍ³©ÔÅ "ðóCÔ¾·jÌÒ©ª ?øD—ù.¯mš~þ$7&  €á–õÑxW^ûhÝV¬þFƒ©tå5u ÔÒˆcÉ9!_0bÄ—ä}Ib>ÿëK?¶½œŸŸæþ²¶€hÞö ß?â¾Ý½Ož^¸Ì¶ÔFðk»æ ´Ð©‰ðº°6lýFWðû»<½à}Ù_ð­â“ýüÑl“™Z* €4¨ù£#§ØÊko,_«¦H¬¼v²ôéÜZÍ”p   ÁœŠ^’ÚùoܶCýü—?-xÏ^’ ¥y`ÇŸ*Y„• £jÀbKÜ _}«Ëd7³Í³Ö­i9L†¸õº°öí/Ç^X$¿Q7Ö]Ó –NUÅê”ta… Á0 '@p¤Á=/CØ™m—$ýyñ Y¶v“ÆdK‡¬Fz&Äô*µi õï/8 ó^xC~óìkú’Üi‹žÔÒ­zù’Díð( 4i‹Ð8¨Ø¥k6Êš/¿–þ][ËÀnmÍ]¤¸EçPݧÓúV|ú¥Å%`#*sa©µ‹ D‘@Öj,> Y½±0²º«FV#> É‰µ)‘ÛÂø¥-—ûÔÜ¿âÓ  …¹Ï|I‚<£ê¬\ÕªT’5òê{«eÅg[d˜.•ÝS—̆¸ â@ç¿lõÖñ/Xò‘ýqÊ Hó™a$@ÆZ)FžÜÈ)¶3Ûù·ZÖjdu¿®mLTR³*ìe}m:óèê/¶È¿{^,YeRôó£’xI‰  ½U(ŒÀj‘ó_û@Þ_³AÎÐUÅm5”ÝÍå¤à»2ý÷ÏËã/ýKW䄟¿ŠýÍÐÏ_âjã iJ |šæ›Ù.$€—Ä@Uu ÐÈêE§SñìÀ‰2‡¶€­(ùç{6ý©šoaÔïFmeL‚·“À1Ðj! báîZ©–ļàpn0û¥ ß¼Šõûÿðâ›Њe©išH— d  €ˆÔtl¤^Î ¢H°4TÓ`(¤Ã—d„ùÌx1q«ëh|@E Lô€ÀU¸¿’hº|^:Hü_U:”:ÂyLÔ)^Æ|IÆSáïÉ à¬\A¤…6CYYã3I p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'@8b&@$@$@á#@¾:aŽH€H€H p#f$@$@$>á«æˆH€H€'Ö œâÁHrå‚i}A=7Œ˜fz@Û ¨Y§ˆ ÉmZ €ƒ‡Ë¡ÃG¤|ù`^ÄÒXÌ@{Ëò»Kxgñ.?pð=ŸB x¼xUÙ  Ó¯P¡¼µéƒ—ý|BZHKàºûº5«KÍê•eoþw»<¥kZ4ºtÍ$:d¼$ÑÞÐù·lrb‹‚6ܸ~-)øî€@PÜ&1G Bùò¢c)Ù¹+Oš7¬' ë×¶+ø:Á_ÓS¶Ì êʵç–¾[Ë‘#G$__š1–“¬1)%Ðñ¡¢TÔ‘ÛaYÒC»Žµ×r’Ý¢¡Æ4%êX´|­lÏÍ3ëD½ùãAñ\§KV5µ(M<¨ùú›i°ZˆmB<2@d€«;4x×ÉŸT·¦üxh/é% 4>à³MßØÈ ñ99bü‰ :Ð\õó7¨W[n?B®ÖeíU­óÅ9\“ª£HÜj>`èÛ¥µtiÓD/ÿLÞûd½äP!€?e'R•S¦Î’µWcGk'?¼OW³dõîØÚ²³d•Oi» «LÎGä*óØ‘“HÛf'Ù×k¾4_ê¶»5 ª¢5~Žœ2·ù;?ÿž}ùjN¯(ãGô“'Œ”v-ççÇ; ò‹m¶fµ*rNÿ.rJûæüš#«¾Øjç`2úâž ¾;¨3H ,°.¬±ƒzççO¥ ÍèÊ Yá#)ãø‘SïYÒI#«ßÔÈêwV}!yú·ã±ÌøéFGùêç/P“ÿ S²å/-õ'ŽdùùKKÛâÌâDšžTG.yº¬Þ°Mh|À†mßš˜©T‘Á¯¥å›®÷¡SGÛÝ©–¬¦'Õ•[.#WþhˆT«rýüéZ©ç;ÒÀ±óŽœðÇ0âôNÒãäXdõ¿×mÖÕa©R ñú]©[$šŸ_ØÉÝ“/Ù-›˜¹‚Žüq8kP:ŒŽbÆ€B“¿þÒ±e#i¯ñï~ü…,^ñ™ìص×baÐö]¹"Y¡,Tl ­g7c励ƒlÆJË&'gÉŠµ#£2B¸âÚÈIAPU#]mmÂðÞY‹ø| "«Ë3²ÚÁŠØO‹ Qq?ý:55 z¨EB׫]ÃJê‚¡Ò­Ø^+ÄÍ€nm5> © .]½¡0>@­\z0ø5Ýj×?¿Î’µo`ùÞ31cå'£¤O—“íÆ"?À3Vüsɳa&Qql|@9iߢFVŸ$KôeùƇˆ¬Þc ®0²:ÌͶøy³—¤}òöí—òú"DTÿM”Ž­šÚCÜè(Fý~¥öZ¹êhðây»IÏö±Å±>Yÿ•Í&`|€Áô:±‡å¨ótÆJ—¶-dжé Î<Õ ‹ÞséÞ¦Ó«FÒ3·'\5yGNxyöéÔJº´ÒÈê•×òUUcFV;béõæN¬¨·¿à;]øä ôíz²®â7Úæõ£$a÷ó—–¶Y¹ ãZ4¬+WŒî+«>ߪ³`rdãöRYƒ+2> ´xS~:utðX™²qý:rÓ„Q:ceˆÔª›±+Ú=(ŒŽwä„å]G÷ÅÊkÍ,²ú#}qâàÈÉÑJŸxIbÝþÜ=yÒV×í¿^×8¿dtÿج¬ ©â Ê££˜¯÷h|¦ fg5ÔÀ×ÏåÍëd§®ýŽàW´}ƤG›F]aЂ+'èJ—Œê/7Ž©í»¡ÀY²ÜÀ&=JÅ\¦š@Æ WÞ‘Ö|ÿɈÓeÍ—Û䟈¬þj'ã¨ÿt‹ž`s“:5«éèh¤Lw–Îí¯e¹NW?i‘»Î ´”ƒ½uˆv+0ùêÙÁf¬ èÑÞŽª%+Xª|º#@àHèOý[Ã÷ØËPéÕÈV^{+¯!²ZW^Ã*ƒ9y …àŸî% ??ªðÜÁ=uÑ“Ñêmn¹s££(úýªí„@ÝZÕå‚Á=¤WûXðkŽŠ\˜Œ¹y–ÁÔœ;:ce¿tP÷äº@ÕEg÷µÌ8ËM¦¶éÔÔHôR¥øž:õŽœðÖ¿k‹¬^¬#§%«ÝÊkŒ¬þtIýÝûöëJxùêë?­saÕ3X u‰)ضŪô8"-ד«Æô“¶ÙÜ][¾É•¸yV(š Þ9èàáçÇj¦×^x–L¼`¨‰7d0Ó,Y¡¨”ˆf‚À§b½#§ÚÕ«ÈØ]‹V^ûXW^Cç‚a>½X}ÆS %€—$FöxI¶Ô ÿçÂárù˜Afêvõ–`¨C€¶‚|U¨P!¡Jú°˜1 ÐÊ¥ö’î'7“-Ê[+¿Ð¯u²kï~[%“V®’’-ûõ`Žv²G-YXÍïÇÃû˜ ëUàÈtKVÙ ó ñ(â‰|ÏïøÃŒuðG¤yƒºrù¨>òñz¬^š#_nÛiA9\yí{ÀðÑQ?¾ÔTQ6yÜ0¹Vƒü·ÃŽb](Á#Z Žvúø GªÅ :X¶².‚5´W{é®›g½®›g}øé&)8Äø”„o¨ ´X±°„oÝyÛôžÑ«£¥N?*!C“ (fÅÇÞ—Gã:«O»³½ó‘®¼¦Sÿ³gŸTqäTL %¼ :ÿ½º½3FÒ£t—©’S²[Ú“0:ÂK4 >Qä½í¿øâ‹ò׿þUÆ/C‡-Ìï!˯ëˆKˆ#a—ƒ)¼Èó‰ujÈ…gö”^…›g­Ý´Ýx2> a¸ÿ߃Ð^1cef¬´h,7ÎXA»° ËT„¡Mÿ¿ŒóƒH (a5º6|tÕœ;¨ÇÉÒUGNXD胬þNwfÃþzà¥Ê£ìàÃ/P®û4ú”ìV6:Ý¿»=¸hs“øù<¨óìu£)mË—/—;ï¼S^~ùeËëOÌÙ(¯©Eà«»ÌÕ³´uJ¥OŠw0K–¾ruÆJ]±2EÅìdõõŸ¨«Tâp–¬ÂËùƒ!@PJ¬éã°Èjý>pw陕×rdÍ]yMGVXt/UÊ€ÒA6?¿Ž¤áço®û—ß~å0ùéØ3l&ãª`f7¿§!bIDATK t)$î.øùÑé£óÿúë¯eæÌ™òðÃë­­sÅ9\óÌ3ÏÈßþö7¹ñÆí«víÚ– wârTò'9q ¶ø7ÚsÇVä_ð¶Zºö¨õ¥ªÆ¼èÉ"±PòT2ûpE›µ+úïó‡ô¶Uü:·áŒ•Ìn©)=@¹{ãZ6ª'WžÓWV®Û¢B`lÒÈj,"Ä‘SÉ ƒ©þo››T«RY~¦;ša1ŸæêÛƒ\0®Iõá|úèàÑqΛ7Oî¹çÙ¼y³eÍuü8 òòòdúôéò§?ýIn¿ývs à:3à:b»!ß\ú·U+Ÿ ÃOí¨Á‚Íåõe9²bífÂÊÅͳŠ_9h«´ù…3Vútik3V†ÞÅB?ñYòÊÄ HËXGäFE夛º°òÚÛ}n‘Õ¹yŒ¬.f7:Ú§Û4Ô‘ÿYúrÄ^æ§vjc·Ç^’êç¹½×Ïÿ÷¿ÿÝ:õ%K–X^ÑÑcT/ïá,ˆWX»v­L˜0Aþð‡?ÈwÜ!ƒ Š•SïÁy×{ïOæ¿MÜj‚(kCŽvÑ0Ý<Ëârä³Íߘ°E|ÝþµóóVsÿ^iÓô$›±rÙ˜æB„È‚‰~~†<  €ru/l¼1ò?³'"«›FVoäÊk>¬Ñ©c¥³½º¹I·vY2E;þó÷²;ŠüüÚ)¦ú@gˆNÝùùW­Z%wÝu—<÷Üs–57’w#þï˯{:y‹-²¯K.¹Ä,mÚÄžtRyÀÈ‚vØ<«…,ÔøÄ¾9rØÖÈÄøXK`ÉÚ_8c¥W‡Ö6ced¿nÖŠ,Y!paY†ø-ã PÜt0 ÇQjO}YvÌj,oi|ÀÛ]½;Ã"«ÝèSú¨ÉHïN 5Júêâ'8 …Ýëç_¸p¡™ûß~ûmË+:ltÞ®·ËðÍðÉ'ŸØ”Áßÿþ÷Я_?{2®àp#ò2$W¦[½ñë×’‹‡Ÿ*½;|m³`>ß²#ã6Ïr–¬»ó$«Ñ‰2I¨ºbì`>©Á’ÚŽôÿÐX²ÊTñ¼9R(’Tî…Q6:«w¶ôÐ`Á…:ÏzùÚMfŒEVGwýŒŽÐé窟Óžnš0BÆ ;Ýj#JA…ÀÏ 9ÿ;:Ûœœ¹óÎ;m Îa$Ž—:®IôçBP¸ø€×^{MðõÓŸþÔ,YYÎŒ›v˜èôKò¼øø,ŒÕNã–|¢›géºÛuó,Xw*¨ Žj|Lýà°{o¾TS‹Öì¿î¿Ï–f:m-ÄAl `ñ „†@’«/  X‚>~<´WadõùlÓ7fBŒZd5^€èrÕÏ­yoÐ]Í®>¨ÔÖÀ(eë¹°øCÑù¢ÓÇè~×®]òÀÈìÙ³mê^Ìz=Žì¢ ÅÇÀ€§M›&“'O–*Uª;ðsb!ˆ|ç™EâyÑž®oçÖÒ¥uY¼ü3yOŦ¾Aà@~£pÄÚ‚úù5öu… ¨`ÉêÕ±µ¯hÆJHm˜³ ‰'@x¦?øÄcGN"m›d_Ø£}á2DVïŽDdµóócsìG?~d?¹iüH9¹E#cäüü!¦úðv¸ÈËüùóåî»ï¶©zø‚#þdtþHÏH DÉŽ;dêÔ©–7L<ï¼óBP³Z9§—¢Í³VéæY80;&Ýã°®Ç~]³öYÖñÔÓÊWäçgÇo<ø-Ü(RX?ñ#§Þ²¤“FV¿©{ ¼³ê {Á¤cdµ嫟¿@MþƒNɶEOêOaöó/^¼Øüüø‰/ÄAæ~K ß0jFú1®åeåÊ•ò£ýHFŽiñ§žzª=× ¿®]ãÑ\bñ6Ð?"MufÇ¥#O—Õº:&6ÏÚ ›gA ¦ãæYE~þ]{¥©n vëecäÊ!X¬ uãFXf¬R±|häP„ JñÂÄ3yµ*'ȈÓ;IvÍÍ€ýÚkduݱ-FNæç?xÈüüÙ-us5÷O `s~à°˜ûÑabdNsݺu¶ÏSO=euáÌêÉñ[âÇù†Nùqy{õÕWåÿø‡Lœ8Q~þóŸKÓ¦MíN\ƒ2¥òˆ5éÂàWý¥£¶…öÍÊ»¯—Å+ÖÊíD ƒ¶ïÚE*óë—¶ý}j>á篢+#^qî ›±Ò²ÉIv›³dÅÊì÷$ž#p Q}ØÈIóƒ}#õ•O8+¶ò–^·å›Â‘S8W^³ØåîÞ'õuW¹Iÿ5L¿†J½Ú5Œ° † nŒè1JFç¿wï^™3gŽÜÿý6ùC禎?ž™×]|>òÈ#òüóÏËÍ7ß,×\s•Ë]ãÄBü3’õ»³F “‡8ЭtiÓD-_+Ku1¡0ÇÄ,.åt*]™òàa9Sg¬LÕmz±Œ/Ž0Y²’UŸL'Z(BVŸÇÆ”“ö-hdõI¶òÚëY­+¯©5 ‚†aäd/IíL±¹Iy}ÁvšÜtñHÝDÆF±-n8=°BÇèFÇÏ>û¬™ûW¯^m­ U~þÒ6A'RﯾúJ®»î:û œsÎ9öX\à:âÒ¦UÖû¼V®:üyÞÀnÒ³}lq¬OÖëæYچ€6‹•)ótï.mZ؆=œsµÐÏ_ÖÖÀûÃB€ ,5—÷ÂF'—çéZéÊkY­ñ0£æë¨$YíÖˆ{@À¿j–¬cÙ_ðDõíz²®â7Úæõ#é0ŽœéÜ™ûßyç¹óÎ;óúq@@¤ÒÏo)å7o|À²eËd̘1ö…2öèÑÞêÜ¥L"a·™•«0> EúrÅè¾²êó­²@wÑܸ}§í Y±bê¶v3V°2e£úudÊ„‘:cåL©Y=6cm)ÕV•„U”ñ(BÞ¼#§Õ*Ëè¾Xy­™-¸ò‘¾8q${ä„—äAYæîÉÓuáÉuºSß%£ûÛT>ŒŽ01:,~~Œ€ÑÁ£óÿòË/-²›ïàp/r7’¶Óô›9(þ%…±AѤI“Ì5аaC+™ã‘ÊbB<-Ž¥¿À%€Í³ÞYõ¹Æ¬“ÿèÚùUu×ö“‘WKKó²g_¾œ 3.Õ_nÔ+m5nÇQ?¿e>Yb$8 €À'&ïÈ©‰n&ò“§Ëš/·idõYÿ"«ËÛîl‰IíûŸ??¾¾Õ®º5«éB>#eò…gIƒºµì†0úùÑùc­þ‡zHî»ï>›J‡Ìâó(tüñ5å|ÿ(ß,¾Ýzë­rÕUWY;pŸ@ñÏHÖï^+f îÑNº¶i*oh|¦Äæ« ¾ºźë‚Èží¦õ较zv°+z´·äÂdÉ ¢ü|ff H£ú9uÈjd+¯½g‘ÕŸÉöÿìQSe[™,ÑÅ‚ÛSûÎÜS77-]Ú6·dÜè( £~Œ~½~~ÇMŸ>ݦÎ!³éæç/m=BÜ sƒØ´i“\}õÕòÄOØ´Á³Ï>»°ÞÂP¯Vu¹`pé¥óëhðëÚMÛå@áÈÒ²8Þ}àN;UÐvÖ¶|ÃEgËEg÷µË]|MÚôñòÏÏI ¬(ÊJ0÷»‘EV«É·×66rz]—^e…a†Oð Nº·k)÷]‘ ;­³=m¬“ ß6½ï¿ÿ¾øÁ Ža:ûù­%ü1äX²d‰Œ1BÎ?ÿ|]ºt±'âðqíª„É$ìr¯•«eãzrÕ˜~°Eþ²øßòN-MôqðÐa©ª†[.c–¬º5«[a²d%ºÌ| x ”Ó—Dâ{ o üwà\  Ú¢» Ö­QM×À&$êi-£ËÍÃg·IÃúµ¥VQ0Tx=ñúµ·lÙ"¿üå/å·¿ý­uøÎÌíLãWFˆpñ¨S,%ŒYXY°~ýú–k/ÇT#öZÂË"{tŽ<Ý4 ›¹öX–ü¹gÀßÿµ®ºÙ¶Ù±~þ²<›÷’@: H§ÚòÉkLÆÅ:kŸËÊ|*L£#ש£cƒ¿ûÑG•{ï½W¶mÛfåĨc x¹´jÕÊ6ºüòËí"/ÓcïJÍo^qTPfˆÜT[@‚*ŸKÇ#@p<2iú¹Ý$:û±, e4)$ cÈ ^ÚèÈp¼üòËfîÿðÃíwçç·_øí{  Áæýû÷7·ÀСCíw'«pÔ7²”xq Ó'ڒͰRó d €Ìªï´/­w>ûòåË­ãÇ”7èÐ œXIûÂ&¡èàñåFþ^x¡­‘Û·ÁË; Ùa$@I$@DØLªô¼þ鯿þZfΜ)?ü°`éç/=Ww§W<Õ¨QCn¼ñFûª]»¶]âåïîáO ô&@ÞõùÜ»‘© `›7ožÜsÏ=²yóf+;:.úù× ¼î“víÚÙ²ÂãÇ·¼u‘¸ù$ T Hy¦ëK ÞÏé|˜Ï©l8ÐQ¡ã§¹ßc©NÂ%Áå„Õgœañƒ ²çáó°Ä”ª€¼‰HÀP°!„Š:tt0èàq¬ZµÊüüX͇×Tmð[`â]+_|±YÚ¶mki2> 0ô|0 $…@R03‘â@ÇÇ·ß~+³fÍ’¹sçÚR¾ñÁjÅy¯I ¯›¥NÝ gʹþúë¥zõêfhsb!1)ò)$@É @ ÊL×@¼oùñÇ—3fÈúõëí>oäû ž ”€7> S§Nf 7nœ¥I·@ èùp„@ XùÐâˆ÷óc{Þ»îºKÞ~ûm»~þâPLî5ññÆ ³ø€~ýúYFà€`ÃuóȦˆQ^æ0ó¾þúëòÊ+¯Ø¿ô…—?,|ÙG¶ú¿·`¨og‚…hÀ€Ö6^~ùeÉÎζöÀ6ñ½èø! N€.€Àg^xÑ〠8pà€<úè£ò«_ýJ¶nÝjŸ{ƒÃì~‹$o=·nÝZn½õV¹üòË­¬Î]ÄÎ?’UÏB¥  €4©¨țwº×æÍ›eæÌ™2oÞ<[0Æù|XHÇò1ÏßOu ‹¾°càµ×^+7Ýt“Ô¯_ß>CCð H- €Ôò|êè¼/ü¥K—ÚÌ€W_}ÕÊîÌøŽGzÀh_NÔ]pÁ¶c`—.]¬`Þu!Ò»¤Ì= Dƒ@4ê1ô¥ˆ/¾ø¢M[¹r¥åÝk.}a˜Ác ÓǨ}úô±‡n¿ãsœ§¹ßp𠄆@hª"32‚Ñ¡)æççË#<"³fÍ’íÛ· ôjÞújÑ¢…­øwå•WZ‡ï,ÎÝ“^%cnI ú(¢_Ç¡,¡7>`Æ rï½÷Êc=f>b×a¸$”ÈðL¡Ž`ÕÁWåÊ•eÒ¤I2uêTiÔ¨‘‘ñÖo†£bñI ´(B[5ÑÏX¼[àÝwßµø€ Xá¾6oî;v¬™û{ôèa™¥¹?|uÆ‘ÀñP ?O7’t#ÿø%„½fæ¤eŠ C ¾ãïÕ«—ÅpŒ5Ê®cÇ .þBiA€ -ª)32éíDòòòdîܹòàƒÊÎ; …@jÚ—{“&MdÚ´i2qâD[ÉϹiœxKM™* @iP”†ï ”€wº¶ž1c†<ùä“–¦ëh\ÇhF2üá^ÖØÐÛúbG?në›á ƒÅ  €ÈTe´ ðæ›oZ|À¢E‹¬ Œ®¾ãÍý#GŽ4sïÞ½-Q¯¥&¸\ðÉ$@A š0Ÿ_&n¤ïF£óçÏ—»ï¾[Ö®]kÏõn5[¦„x³ðšû»wïn~çž{®cÇÏFBÑ"@­úŒli¼Onn®Ìž=[æÌ™#»wï¶u p Òðvü 6”)S¦ØÔ¾ªU«M÷s"¬t)ð. ° [0?¾¼ñ9992}útyúé§ítPnFïCx²ˆ€ëÔai鋸ÜrË-’••e×@TAð ˆ €èÕiäK€­‡ïºë.yë­·¬ìŒøá&ïç?묳ÌÜß·o_»Ùkqùá§ñ  t$@޵Æ<øø€Ç\î¹çùâ‹/ì<㾿¡xÍý:u² {ÆWÄâ_}úØ|þáÇ[VèçOv0=ˆ €hÔ#K‘ ]»‘öþýûåᇶ©ƒÛ·o·’-¼éµhÑÂvêÃŽ}n}dʹ+„€!ÈRÑ,fÉxã6lØ`‹=öØcæcw®3Å—ìÉÅ»Úëç¯\¹²Lžû¬LŸ>]>ùä+¼×L_Zñ¯^½l±¢Q£FÙ#Ùñ—–,ï#8 €ã‘áç$GÀÛ çååÉܹsåÁ”;wÚ•¥Þûš4i"Ó¦M“‰'J¥J•l<܉¸,ñW (5 €R£ã™JÀ;Ýnݺu2cÆ yòÉ' ‡ë¨‹ྲྀbÅŠrõÕW[ç߬Y3{ýü™ÚÂXnH €äpf*#ðæ›oZ|À¢E‹¬¤~ññæ~˜ùï¸ãéÝ»·Ýëµ4D ‹C$"!ª f%ý¸‘¾ÍÏŸ?ß,Ÿ~ú©#{X Üá5÷wïÞÝ:þsÏ=×N³ãw”ø“H (’A™iDž€·óÎÍÍ•9sæÈìÙ³e÷îÝVv¯ÀT>Lé›4i’T©RÅ ½A†‘‡Å’ „‚@(ª™ˆ o|@NNŽÍxúé§­x°\qŶiOVV–}F?Tjžå ô#@~uƇœ@||Ö øóŸÿ,Ø©¯oß¾–{¯Å äÅaöH€"J€ ¢Ëb¥ž@||r„ÏÜRéÏ!s@$É(2¹öYö¤Àh‡‹þOJ¢L„H€~€Àâi  ˆ"òQ,ËD$@$@$àO€ÀŸÏ’ @$ PD²ZY(  ð'@àχgI€H€H ’("Y­, ø ðçó$@$@$I‘¬VŠH€H€ü PøóáY  ˆ$ €HV+ E$@$@þ(üùð, D’@$«•…"  þ|x–H€H€"I€ ’ÕÊB‘ €? >M’ùûêÕ«'þ›o¾YÊc†iÒ,½©!—ðê½á… è‹/¾ ·ß~›öïß/9é=©Ë¬ƒ&º¿àî»ï˦J•*RFü‚¦Ð¦ ž0à6]ð'Nœ(J±téRÉ!˜Çù.ªxUTÝ’Á£ÆÏ<óŒY¹ˆ!ŠsUBó%d0಩֭['óù¿ýö›¤ ¥q¾ËªÚÑu«¦téÒòÜÂ#<"¿ƒ`1˜šH¢Ý à'Nœ аaæ¿êùÔ ‰lBþgÿ¦  DÍ›7k@áòMg0{:lpxTTåÈ‘CR¤ÇžO‘!Ù²esˆž‰¬ ÀeËà >ìÍKæ1#œ-}PµjUy–áÎ;ït‰œ‰ŒpÑ*˜ƒ³aÞ¼y2ž5k–|G' î߀ã¯_¿~ôôÓOSDD„MxÆô—æÙC.›==z|(ÂÈ‘#Å"غu«|×{K¹‚/PjŒù1ëwµ»P©R¥¤6úlHVÏYCÀ€†›P¥(±±±ôÑG‰S Ÿ¡4ø qB)ø;úZ¶l)äÖ¨Q#©†YJ­é¬¬†œá”`,½7ܲe‹(̨Q£$¾nB'˜Aü [.ÑÑѲơK—.R:삤¸¦)„€!€C(‰òÌœ9Sü8½!˜ý:IÁ³ß§Ozî¹ç(22ÒŒóS@6‚=‹tA—®l»Ñá‚5Ý“ØMð÷`¯?lÑ™½—u“o âªá‹¦<øàƒ²À©lÙ²r;ݲqs`1|ÎR]fòtÚ.Îr4±Ü ÖEÆ„ÝKð*œºÉ|üøqÙû{ž9sÆ.KZMúó›4i"$…w¯ã|ÔÇ+θ¯W¬‘ÖïxÓ ï÷K•”¬ól’ûÛ€PÎZºž&Ì[)÷¾|9ñ­¶AóVo£#'YY¯tcN7== D€£»ð°¶ÃC5Pü©8nòMn\Üõƒ’£§>|8áè1(?ÊŠra¸âÆòA~Òë_!ÙoÇÏ¥5[wKQÂMÁyâôYš»j]ä{kä…?R°#Ÿ¹s;#í9tŒúM­{¼KË7î¸"”¾Ýy¯1D¿xC }ð¿i4sÅfºpÑ»pê W¹reúñÇiòäÉrjÂîVá®Uñ‡{blE—-[Fݺu“2à:Êꦇž*’ÍÄy/\³•nï;ˆº½ö‹=#EJX™}J޶ú}î*üÓLZ»}Ÿ`üA†’jÕ”ùÝ·ª%eòJÓ\¤gçq'„ñlüyúê÷™ôñSèбXÞ 73åÌá|ÙjDö¬þý1w -ݸ‹ÚÜP™j”/.õƒpò!^,¬Îª †’£w…BàhoL¯a@ì¸wï^É ELÉ€{+ÅG¾÷ÝwŸ¬âƒ—A)>îí&@q3H6æÀøÝúßä¿ÄÈ—;'eÉì,?à™#+í;KÃ&üEÕÊ£›ëU¦âóHqЦ3:ÚML\· T>”…~ììåÔêÉw¨ÿÇ?R왳”?*R/)ÓßF„? n&Î Âyàh,˜¸¾·€v:.÷àŸ$Žž&©ÏPD¥äxòÉ'iåÊ•âuÇV\PFÄqÓ 'tOE:‚ çÛ°aCš6mš=åÇ¿¹U|à"鸜gÎÅÓGßÿI-›†MÙ²f¡Ü9sH[ ŽÓ€<³fÉDÙ9ýêmûh诳iÌÜÕt*«ø”?¡¡„Ó{˜x #²Dì2óÑ AYWlŠ¡wGŒ¥?¬¦Ì|­@žHFïr/ù#}V¶ †ëvì§Í{Qƒ*×Q«º•XسK¶Nå+pr¥tPBÝ5pà@êÚµ«Ì»3F²@e18ÉSƒ´ ä_²dIûÑ]e (rÐÓ$õ z¢×GømÆzÿ»ñ´zË.ÊÅJ’Î b/Aòç„Ù²È}f.ßL«¶î¥–u¢©aµ2r_E*(¿ )‡@H€n‚8z’>5‘¾›0Oz¥<‘Äý”gÅ÷‡‚2ÈqE8g¯Ü"=UóÚÑtãõe…l¼'†"ø¬4x´ö÷ß§ñãÇ ,_¾\Š8Pf•¿ÙôïÊr@|¬ÕÇy€X»Ÿ?~IëŠ|ôt‰}ö'Ù¥vÐ;ÃÇÒ”…k(+›ùòä¥÷J²þ÷V=}N¶¼NŸ§Ÿg® %<»…‡•¯ób‚8 CþèyûR ÌxôDç/\¤oþ˜MCþ7‰v )0¿ 3gÊÀ¾„¬2ìújüª^þ*T4n‰¬ÝX^*oó~5!AÒSj&èŸ V±¹?Ž–¬ÛN‘Ù¨@T.™J ”òëA83±pædáÜ{ä$}ÃÂ)Ϋúì¼*pÅyåR8õÞ§ô`ë-LªF¯µ J SJ^·n]™Ï¿å–[¤¸¸†|Ý*¾,w¯ ÙsìUÎÔ½<£Å‹¿ÔÀ™!Ë%ÁVnÙC›v¢F<$hQ§"ådG-‚!ÁóKЦšÔ8-Ï/CñÇÍ]ÁšAç¦'JU%œð Àyµy÷!¯¶dጼ2ãàV8¡¬ ;(/Îí2dˆí˜0a‚ÜK)4â@ù‹-*[x?þøãöl"ªx’ÈÁ‹?ÉŽgŒõò;)WDödóášQÔð33 §©K7^ñT¤U¯+@Å1þkB˜èÅ %Ý=râ =‰†³·ù{ö£råäJ¥Ü8?Q„ùQ žr^ÍXö·óªAÕ²BR*ŽSáD<Ý?€“|ဇ¬Y³FJ„ÝxzôèAýû÷§B… É5‚kÅ町3uåf8SÇÑÄù+)sFŒó“çLM>W?‰eÂ)@®'Y~˜¾Œý1t Á¢Kúê/C0ãp…kÐ^7˜ p.7‡þ“¶ï=ìçó<3¬‚` Rf.œW˜¾úi;¯6°óŠ…³RéÂRT·Â©L|Ì ÜqÇÔ¶m[yäNB,æ©Q£†üKŠïVùu’=Èë%>úž©¼’¸¿ÇùA†µø2ÉZƒûÑÌ£šJÈúBys ÀÚøŠ$_‚†ÐSúÆ×<ÕÄcÐé‹×ÑÛìq^¸f Edçq~ž\b›òë£üºóêËqó©F¹â"œE<:¯tÿÖ `cRÔ8ƒ› zSì&aìLü¿É³ÿåÉÅÎTþ fœ!+è'²eõÕ{é¦]´!æ5®^žšÕª 36ÀñœZ^n𠧸î$'@5·Çùì\Û¸sŸ˜ cf-“Õv˜cöÍç§î8ßkU!˜<åX±e7mÜuP¦ [ðÔ!Ʋn{)ôî>’ôõÈÊBpSN_z81}óù“ÿZMïðÚ‰Åk¯8S™d±.?˜•_¯/ꃇ Êõ'mÙu€§™rP^{œïcø´(cJÝÓ'œðøœWÿ›ÆÎ+øT¡ %|'ð Èy¥“ìÑ“§ÙŸ2I–îÆžŽ gjJbç°HiûŒ>3‡jW,ÅÏrTâ©âH¹ °6þ¿OU¸ÊeŸ³|£Œóç®Ø(¦±Œó/‡Ž ú7ŒIdf3ºƒÇÚŸ™Kµ¢KŠpÂy¥“,zÿo'Ì¥A¼v/gÆ\~›d“.{(Å€Œ¡ÛÀ³x_´n'­çeÜMj”§&5+ðu^‰ q<3,HE @7A·î>(kÉ™¾XçCA0þ ç ÂÉÒ§„ÓXvî§Æ,œMY8±Üñ¼ §?ÉÎX²ž—ïþA V‡Ž35%d@3ÂÌ é¿`-gÿ@k¶ê°UÀ_‚9²3%ÊlyÜÀ4–oìšQžÎûô§©ôù¯Ó æ(¦šð[¨Žó½6¦-œì@Ý'.¼"œüÑ •uç•;áÔIvSÌ~zçóŸ¹Tz¼Ps¦zÅÖ?oÆOvFd•M^FN^ÌC0ßî2EóKtÄI¯þ€€šÆÂóây=ù†û(7óñܸ(>÷vé5ØÂ çUl}?Åç¼ÂóåŠùœWn°wÿ;Á>fgê—p¦²cSz¡ìLuSÿÄâkåØÄ«6·í="d ‹ ¯`”Xêðý-` ÌÝEk·ÒÛÃÆÒÌeëÅôUãüôÖë'&BºpnÝs˜¶ï›+f*„3V=B…À:žŽú•‡Tðæ›ÃЙšpíÿ"2ÉÑs°VØü5Ûe'¢fµ|gç!Xb8;¿SèÄ (“jÛžƒtÇóƒ)ŽW–Á³o¥ƒq¾×¦W©üóVoåÍHNR¯»›'êµVf?Öîw}õsÊÏsùŠdñ› ÿDÀ‚±à<û~š±œÎÄÇS‡F×»^ŸñÏÜCëJ@w:c´yŒ/O±0*àC ¢Ô-­Â‹[`%9!a´œüd$‰p¦:M—ºµ ®»¡£Â“À —§ÇPPžlÌE›às§ã ‹X 8N˜Î#‚(}X»;Œ0 („N¦*°DÀ@X6«©”AÀ†œádbÂCaÙ¬¦Rgp†“‰eK „e³šJœ!`ÀN&–A ,0–Íj*ep†€!g8™X°DÀ@X6«©”AÀ†œádbÂCaÙ¬¦Rgp†“‰eK „e³šJœ!`ÀN&–A ,H€óÜ<[} Ô^aÙêª0Ön‚ÁÚ Z)×]k¥üýš£Oñ3Ð>ãâEç›’`éøó¾ÝŒ 8k¢Ì¼!éEÆící&œcœwzÝ•× Vˆ–€Ýq ±qgù´Þ³ÔýîÖtßÍ e¿}'=T‡«ñ©¾Eèô¹xj#œ ‹ž"Ylóž#[Vú Wª]Z°Î˜áÚâRÅ^ÐQ‘ÙéÎfµdWÞ3¼o$®¬Æ:¿dSÐ@ÔIž,Wl‚f¢8Vܳñ¨iíJ4ࡎԸVE'Éía±_|ÏÎMiÑú4mé&:t Ú¾Q5Ù }Êâõ´jÛ>!cÿ-»%p€¤·(!O¾ƒG,9[x¨=}ÏÍr äFŽé5î‡p¬mÛ°*Õ®TЦ,öð‹Ž){¶ô'œVamlå2Ũï¿n•¡°U$«ŽwŠ7ˆíE/š?7=ضmˆ9@“mà3Ê1ëY2ËË)žnã…,@I3Á=sN<üw·n@/<Øž*–.*¨žÈɘ?!Ðtá,œ7ýëæzl”æsè7ÈÉ2Y³øû ÷a0„‚㓆pÄØ+ÞNO±_%wÎWzhßIÏ á˜ÔuØeâ³r¨Ìþ—蒅诵;hƲÍt”ï‹­»Ñf×c(Å^BŽdìȧìb|ŒõU¦w¤lŠ"@ñáHrÛ%„¨¿pF—,LåK¢…|êìôeéð‰Ó2,À=àp¨W왳üž‘ºÜÒˆúumOå…5pVSB:½®ò’ƒtnª^ŽjV(AÓÙó׺Ç~&e18Í×ÄK"ß8ÿ2?qŠÊ±>w[zðÖÆ¢ì8„¦@J)¾?dºpB1U+C5Êçj-àž*œœW\=q¦žåÓrβßã¦Z•èEv¦6a§*BJ“¬?ÖÀDÉç&ÞÖ¸:Õå!Ød‚­Ù¾O,ãðGÍÛ÷ uÀè 6s猠¾´£^]nsÕö2·I{‰OÐbgb‹ÂiÐ…§÷t¸ñzŸpò°`õ¶½’_( §d}ãü p¦>ЖþÕî&©—W’E:ü¡U[:ÁXcT`ñ¿âóÐ÷6”³üà‹‰9xœ²eÉL™À ” Æ jådôTÜ9kÞÞ¼.õïÖª–-!ò:·âCé3göUßçiÆÑמ·¾z"œüƒÏyEÝÚ5 õ;ÙyÅ^ìû…œóÊW÷+ÎT>-÷…níév¦Â±Šà•d¡øÀZa ìñYYT’y"/0xÂQpF´juóÚ8ò;ØWŠdc™d3p5îlYOH¶ÒuŤNÉ%Y`½gÏ1buèÐjÔ¨!ù^¼xÑ&`¹Ä‹" 0Ñ´fÛ?°×kÄŸ¿(Xÿ@@úýì¼ËóK¨¯j „Çùù£rÑ ÞÐÔOû‹òÃɆ?8ˆ”@8)‡2÷ÑóàoìØ±T¿~}êÝ»7Ý}÷ÝÔ±cGZ±b…ò…p*¥v’?ÒàO9¯×(O½ïiAÍkGs>$Î+X nÊìä¾É‰ƒQ6H‡bb_ÝÊeè—÷{ш×'(?¨öpz/eîCñÏž=K|ðÕªU‹^yåjذ!=ÿüótäÈ[ùAºn‚=c9ˆâYˆNMkRÏNM©J™"²øë·—>/‚›œÓgÜ !4ûÄ©8¼gîmC³¾|™ïÜBVšI¯ÏqÏi€C™¡xÈ•+WÒm·Ý&øŒ!®7Ž4h@Ï=÷:tH®#Mr„3WDvºWOßÙ”Wº¥³¼hÊ  ¥1d çËMCûv¥I¿@-ëU‚"séÝ÷'Ùß~ûêÕ«Gýúõ³„0pà@!„Ï?ÿ\ðþÀYYgNÛ8¢(k©Âyé±7Ê0¬pÞÜtš—_âëndÅé}Ã-^š &]ÜÙót’§›n½©&ýÉÂøîÓ÷ŠpJOĨƒÜ•äÍJ¥Fo%Gï¯,âA1$ùä!\W=š›{ëÂY‚W´o$¬b¢X8ϧ™p¢\¨;œ©è"1‹’}äöfÒ6Ér›8 þ$»lÙ2ºõÖ[©sçδvíZ›Lƒt1$xòÉ'éÆo¤)S¦þ(—{ËË·$eÀfezÝÝœn¿©:/ÝÎLgke58­SzŠçN«R˜ xìÏ¥W)[œF¿Ùƒ~x»'?LRJœNhTôVÎÅ‘{„+g(/ ã|(õ Aƒ(ž§µ®¥Ô:Yìß¿Ÿž~úi1WÿüóO›,åq Câ(¼"œXïþÌ]ͨS“2—šÂù7ÉÆÓ)&ÙÛšÖ¡ÉŸ¼@oõ¸‹ äÉÅ$è{R29${àÀzæ™g·‰'Ú¸éJ ü -ZD7ß|3ÝsÏ=´aÛ,€µ›€úáÖ@ÖÌ™¨EŠôÜÝ-èÆëËŠÁú ¶!˜›ú2nš€´£'OÉ’Ý÷ž¹—¦}6€Ú7®%˜ãüI“&‰0öìÙ“ Ôèy $ —¿p.]º”Úµkg÷dØÄÒ'ÔHºpfá<šÕª ÂÙ¸F9©+Z ¤púHö¢ìõJÑïô¤QL´×—/yÉ&Tþk]×IV·œ>þøcºpáÂ5IVÏX£”%öÓO?Ñ 7Ü@/½ô?~\Ò«8zº¤>«žò“—g2înQ›žêÔD³q¼pÌÝâe¹6ÖÁJ²þí TåÊ•­üÑV:ݪ±/šÿ@ (@gíS§NYo¼ñ†åAƒÃÄÖÚ_‚õ»^æ *Xßÿ½ ~Z §N²›7o¶î¿ÿ~[ñuò V\ýËå?kÓ¦µpáBk¯C0;ƒ0ÿ¦€žHH(IttôUéßà¡ôÝ_8[´haÍŸ?ß©ÔNtàL}õÕW­\¹rÙ$ ÖUbm¯Á@dO<ñ„Åë6l¬u9³/šòUªÃào‚.X°ÀjÙ²¥­ø¡b‚&&úoºp‚}ôQ+&&ÆÆ= ëJÏÿÛo¿µÊ•+gc­[*z™Cõ³^Ÿ X¼Å+9kÝÒ´ÁOçÒÔ€<öØcö‚4^¨÷D‰)ê@œ|ùòYï¼óŽÅkàSEçÌ™c5kÖÌVüp#YÜQ?uíú믷ø™ŽTÁ9Ôn’ª€žûöíçX¡B…¤‘ :s«† ×wáÄ'¼ØÀ&¥‚š×ê[˜‘Pø†;Éê2ã?ã} ¬3fˆE”’X§T›¥E>©J0Á<¦ötå×BoÀpý ÁÌ’%‹ÝCñ>y?#Ø£”*Ÿ?üоpVD®Øú× ¥Ž5?nñ#ÌA1“íœÜC8a¢*A W=‘òoäÈ‘ÃâÍ1-ÞH”Pê@<<Õ¨Q#kXáH:ÉVªTÉúá‡ÌWÉž}1HÞx}Å–Ïb­"‚pN(˜.:u²Ö¬Yc‹œ® öÅþÂU÷î¼§UªT)k½| ÿP|G=¡åÉ“ÇzóÍ7-¬+AzǓ‡lviF 1]8qmذa¬QªÂéo‚Ö©SÇš0a‚ªvš8¢@ÊÒÀšÞ@ÅŠˆˆ¬u Ea*ï(».'=ôµ#ž°+Œ?¤9(luáÄ£µ¼?œÓI ›¾ûî;MÈ1÷m8ýpP&g¢¥ðûÑ_8§NjñžþA+œè‰tä#°¬åË—ÛµòÚéû)Ø™%ð˜yÁZ·HPN>Á*V¬˜µ^¯` [¬²P°”Kš“»SpsƒuM’—N@Å'œîñÑýøüÅ_X˜:S‚˜ÖÂéo‚b>̘1vEõa}ÑÁ£eFÖ^Ÿm×-/X-|J’•-[6ÁZ·lö©ýîO²xˆ 3© —_]sòîuó'y‡Bœ€ÀÉÓgy;°£6^YVo\La Si´N| ,haÁ͹s¾=õ^Õ®¼ƒPzµÇ¢¯ÚÃ3%‰ï3ÈI$ì9|Üâ3þ|_øÕ+è33XEÈG©]E¸ª÷M-ð'Y<¶ŒÕ|*$ǺR${,ö´µh­oïuMåîï!âžCÇ­ç?ýÝúyær‹Ïü³±ô*œ:`* SjJ¡©!œ:á`œÜ£G‹º²ë¦—Ѿèàƒ®øØK±s¿!V“Çþ“¤% HuƲMV¿ÿþnÍåýíT^hÕŠ`GA½|œšÅ§+ÙX£Þ ÷@¾ë$‹J°a‰ªÊ¢u¤nZºßf,±¢ïècõxw¸d¥°s›o¨Æè¶à8Ö ûÔÏ]µý4ƒf­ØBx;olÃÌ€É ãÀ!i¸á©Zµj²ÿ?Ž¡ª[·®ìÑ뽇OÐ7ãЈ‰ iß‘“¾}ï92îé&èŠÈ³ijrÂ2Ž[Ñ¢î*Ž›|Šëß¶¼))ñò]91ˆ·þ’û©8 åq­ë Ylû’Ýsð=ûáHºµ×4mñZŠâ#ÄrdÏ"gT\+m¸_ ((ðØ¢¤LÜ‘LÈo&ü%Tß¡ 8&Ê»pòÃr 'Žü†BXSB8¡ø8äÅï?¾KK–,!&”VøJUפޡ¨l¶K½¡<³–n [ž~Ÿz¾?‚=ɇuææß|½URyùÿýް²±õ°rëÊÖÀØùkø°‘x¹'Ò¸%E€lv Éâ À¿þúKŽ_óŠƒ^v` BñasIˆ ¢áâ¾>‚sg] Ô'N峇ü0™š?ñ}õûLÊÂEåŒÅw+{zÙCýsª@‚z+á„i»fÛ>ÎÙ4fîj:wN† ˆ—á„y 3•·„’c«¼ 'BÅGà <ˆ§õ¨ÿþÄ+ç<“ ß׃e¤Í»Ð#o|Ew†Ÿ¨ëØÙ˩ՓïЀ¤X>X«8~Ð¥»¯©F Y%Ȇñ-ÑÌå›E8ç®Þæk4¾ˆ8øsü…³V­ZÄŽ+â)9â©9[8!H‰•ÊÏ[xï?/G±ÊsOaD}`‚â`T>ÀƒòmúqêB6Ù³Q®ˆìrXª›:'Võ›êÙ`yÅ2Éþ8c9}üëlÚ´ë ê‹¶pŽ4]!°L¶rvîÜYÌô÷Þ{òçÏ/¸áþPìÄ‚:çìÙ³SŸ>}dœÿä“OÚä«â$–þêa“,“øŠM;éžþÓ¯|Fvîcë*RŽOÃÁ´&øHuPÀ«žþÓgÏÓ/3WˆE°açNžÂk€§èˆ§êu^é=ïKH£F¢éÓ§Ë9€R(§Ûžu„òÃ…²ús>5ëþ½=l¬œœ77óÙLEœ@Üg4ë1v>}7i1<+=$NÅSíá´J9 ¬¢~ýú‰wïÞ]ü¸LOÀ×UïŽCFá`8p`’m¤çãÿ¢ Y ¥ú ùµå¡ÕÄ«§1Ââ§4Éú—#Ô¾_Ý:iPzŸpúœWy"Í8?1<ÓœP8%œ¶ój œW³iœW|¤8ˆÁ-(ƒ‰—·Ê”f ôñ%‚‡Sh—-[F¼´”x‰©$”Þ¿“‚$ò"=§CO´}ï!zâaÔ±÷G4åfÊÇçÓggÿ‡ŒóÝØÝ‰ÜÏíO¨+þÐ#ò‚Cš²x= bÿÀ¢õ;9+Kˆ8#ŽÓœ äHåæ[‰—oÓèÑ£©bÅŠöÐ ¿.\˜,–YûöímKÀÉrÛÉ8ŸÇúÎ_E­{¼K}&^ØC¢rIñm]9Å(Xã%>(NåR+¡ƒp‚Õ§.Ý(žìVu*ÉqÎÊy…b9í‘uᄲcêf8¯øPOÂôÒ»ï¾KM›6•Ú‚, Œøs7î…žNÍÏ~žFÿåÞèðñX”ÊLcOàËEĉSgiôÔ¥´dC ÝR¿ •/QPª.qX¹œÚ>Rÿ+æ=2à\Å;dÈâ=¨cÇŽÄOyR‘"E$‚[œ‘–3Kk¶î¦wGŒ£ñsW0ödœbÉš4XéœS}ÒùI d aØ4–ÍÌ™Sý3ØýÂÅKlÚ]¢rÅ ˆpF—,$ÑKáN…SåEE@ÏÎKweÊŸ!ŒÈÏmº¢,P|„ŸØ±÷þwˆF§Ül~f͜ɵâ£Þ§ãâ©^Õ²4åÓþ’oB/PRÄŸÇNÔŸÙ‚q>®¹ Çs.0ž©NÅÔú†ÊTf¨Ÿ²ÂÜä«+8o'‹z^‘,îë& 7W89qŠžÄë'fÓ)öìG1É‚q[w `=uWkz¿×}6¹¸)W(Ç * ÀH4&œWYX‰vîgçÕó¨f…Ô¦^e*œ×gâ¹N¥àNøtAõ/CBßY'Ä|U=¯%çÞô%ëÄÌÇ|>6˜zý„ëâ› ÈÎë)@‹ÖÇðJÂÔ¤zyjZ«¼ÔG(…+íFiÑ» A2XÑœR³1þåD£`P~ôì#ÆÍ¡Á¬üÛ÷fë*‚ò°355ý)þå åïAMVÚž_²eõué¦]´!æ5®^ŽšÕŠ¦<è‹çM8‘Ö­ªz"(ÿ®Gé^½÷äÏÖ <ûVˆš ¢hŒ¬^O®egán¶*QÝJ¥0îkv—Ó΄¡ˆÀ-Î>òðMŸÂÔ›¾x½=üZ¸f+û0²‰3¤b”Rì-=¨jArÂyÅcÀI‹Ö³pî¡Öu+Q½*¥¥g‚ètÚK9'7æ1/ùè‰âØ9ùůÓ铟¦ò´Ó çgÏæ+›Šªï¨'°‰ä5 GcÏШ)‹iñÿ@Ùbù¥Zˆƒ¡‡Óàk{œŸ)mܱÞýv™µLˆ yÌ8ß)ò‰Ç PÕP‰4ü„!ž¶„–lŒ¡›ëW¦òÅÿv^¹N•wBïþãüßg.¥÷¾O«¶ÄPîœ9deL}~6-¡,Bò:°Æð ~Œ-üÀÌö}GÄhÃA>¶tÜÁ’B·®Ž3ù åå»_™)m sŸé=$†UIÕ3X~9PÀA83³`B@·ñXðó1G¨vt)‚pbÅBr…ê|Yó8/Û°ƒÞ>–&/\#JQ0„Æùˆ‡pÀòm|þkíZ·c?5­YšÔ('Ë—•u涗׋#ÃÎÖ>œ0>úþOÚÂK¦±C+Ÿ©^$«cŸC––NÌ­C,0—½žƒmR£<5aÍÎ~(·Â©÷Dûç§ô&Òȉóè\üÂâ¨EzšjeŒáÀ‚›±óÖÐröÇ´f‡l-vÌ" ŽÿÒ  Aæð§À¾Ÿ³|#óÇÒÜe­M]ºlÆùÀ*!¤ @¢ '¦ Ç/øÛyU§¢Ïy"p:b…P¢'Š?ÍÏYb†î9tŒò²âg‹L¿Žo(+¦##²Ò¡§éÛ?Ñb&^¬(]$Ÿ4‰¬AÌ™xœ¿u÷AV£_g,‘{`œ{¥'’ðRù%,@a@EFd£#'ÏÐÈÉ‹íÅ-×Í/Ö@R$åGæ¯sù†œ_v^Y)cOXé=@Á1Ó¡üùá¢m{Ð •KËŒA6Ù“ 3:|ÛcùîçìPå-Íĺþ¡0}šTCá÷°"8ˆ@ çfv^A@ïkY‡êW-ãëÁð^KïÆ¿ øäGFæ`Åg‚Ïãl_á«ÞÕ þXaXŒ´fÛ^êqG*’?·˜÷Pfÿ€t°Çðhîm}>¢…«·ò2éHq,ŠâËïþ©Ì÷@ Ï¢b2e¦æøý0›«N–—¯€žéX§©Ó_<5ƒåuòÌ9^ / @Í à ±°Ž"?“,|¦×O­À][PA8ÑeÎ켪9˜4„@Œ¹¯`tô *3çNÁÂ:À`ðî’uqŠGr®)~ëÔÍyÀqP=šã&¢€œ‘È(¾ ]š|H7&èš›‚CAÞ@¦x@"` èš¼ AŽ€!€ o S<ƒ@ 0HtMÞ GÀ@7)žA $º&oƒ@#` ÈÈÏ H ]“·A È0ä dŠg$†‰®ÉÛ äò2Å3CD×ämr y™â‰@À ÀË‘R¬p¨ägå±/¡Ó€ø×Ú}Çiúô2êtƒpÃɹ„y¨9žõ>Ë»èbCCÎÄqhØ [f9 Ø 5žwë… ³<›à&°ÆñègÎúv1r,¬¢„,ößÀAØ(ò< ç9ÞþÉ'œF:’ ôø Ê#¼}¹ï–F5±M3T¯CS+òß©3ñLîNíI¨<á|Š ^ò¶Õ+”¢Û›ÕåÍI°Qiú’Ï€m #øÜ¾.­ë2 ”¢I 7ÐV>À#kßaØ>Ê:mËûéáó½mÒ Ý:P…’…eǜĄRÉk±QôÌ]Íh!Ü1}Ù&Ùç&‚t ÖKš:xäï]€˜}®{[>¸•ìÿHoC€€‚½W……¨|ç‚rpÇ´¥›xƒÎS¼éfVÙ>= 'Hfže4î\<ÝT³"½øPGjZ§²À§'QX&öœa=4º¾,Õ(_\H`“Î0ć‰Y‰å¿› B²gÅ·ò@»©_×öT–er˜Þ”õ8 ÷Â{h€¼-wõrÅiÆòÍ4Íöt-œ² .Ž3–çž¾÷ým©ë­¯ôؼ9ãåÖ (‚ÌXãÜÄŽ7UçsüJÓäÅd«n´NX ðÿt¸ÚŒc&!XœêÔ¤v%zñáŽB¶’BñÓ£ò£þ'ÜÊ"ˆàÓ}Û7ªFuùÄç*ÞG¿¦áÌ(ž}‹pð%Ž{¾ë­Ôë¾[ìÃ6Ýôúªß °†~CÑ1,x¨]9ËXÇ8FÙx^ìœ,/›dcOQté"Ô÷[éþvXÞ2Èø¤(G’ùa˜ž¾¦ (@uáÄÁ¶­OcÊQß;ö•-¢³„©pаqOs*îœôÀ[Ô£þÝÚSå2Åû8lS Wÿw*î§LþªeŠR¥R…iþÚí4sÙf:Ƨ*‹€ã„ãÈB²L€ YœbŒaUÏ{ÚˆSä˜\’õÇ;”¿§*(á¬Tº0;» ±ój;Mç¡ÁQv΄›pfæqþ9çŸàq~ýjåi dëúÕDn” ˆž$€%Gþ84µ&ä9ý0 ×±àüEqÔ*‹A"‡ð‹"YŸ3•èžÖ ¨ßƒí©bé¢R«”$ن骢§:¨»_%œÜ3ÞX½Õ€p²GPÇñx ³¡,œP:Ý‘“§¨LÑ‚ôV—[¨[Ç&”… ALpÖO·Š™§®Ð³Ãyè4ØC0vtåæÓŽîhRƒn¨ä‚­å£¾ñ» Áøwàj4§;SÕˆ–^¿yÝ*R•@’l¨aå_Þ4#U[8Y¨#Ùyu›8¯X8±ójû¾¿…“çÿ!|¥ rð%ŽËz–ÇøÏuiKyÚ Á‹ ¥‡ò+ÅÇgŸOA>&ù‚rC¨y‰Byé‘öh5û`¦°`÷Áã” óã¡ä^¼xYœ©åØ£/ÎÔöÅ*1¹¹%Ù$ £iN Kñ\ÎâòÐ÷6$ôNS­§g8¯” zšÏƃ’wh\‹Çùy¡II©¦Wô¯ „âãoÏž=´mÛ6jÚ´©äyñâE¹®,*…gBïÀ ¦ü˜•©Ì2ì9kÅ:qúlH Átgj;Sûþ«8Sq¬8‚’M³p¾4ý…³šr^ñ”áLö?ÿ@V± ‚Íy%ã|^íxœ|u«”¡þv v7ÕÙ0‚àÜöDª—‡â_¸p>ûì3zë­·èСCt×]wÑ¿ÿýoªZµªïWHB¾8xQ„q’róÚÑT+º$M[²‘oˆ¡øK §þÂèRdá Û€GQ$«œ©w4¯Ë$Ûª–-!÷öJ²/xÞ ¨@a¤ 'LÒ¦5ËS-öL[º‘®ßɧʲp‰sõPpŒóKÎO¯u¿ƒ¹­©ùÈì+«ÝÌç(zýÌ™}Í3aÂzõÕWiùòåz¿Ÿþ™pýé§Ÿ¦~ýúQ¾|ù$>LPx&önÁ¸¬y"sÐÍkÉòíIlymààÕ›Vø|${žIÎÔrìLí@mT—ê™q~b­œðoy áÛ¹ûEÎÜ9³S§¦5ééÎM ÓZxÈè‚zøÅ]¶)ãi(ö‰ÓqB=îlE³¾x‰zÜÕZ”_z}Žãv Lz ”Íš5Ô©S'jß¾½(?,ü¦”<..ŽÞ{ï=ªU«}ýõ×R/Äy(ëÁie•Aé"ùèñÛn’iÚB|t÷é¸ó¾Å\\Ÿ´ÊrÉÈ“‹õy€¦|Ú_”$‹?ÄQGZ”1T?˜J8á¼*ÉΫG;4¢U[Ùyµ„W‡Žó²âÔs^AȰnOá ¼¶ «SžÖ«]é:)¶ôD,Œn{}5·â9rDû“O>¡sçÎÙŽ>ÄQŸ¥,¬ð»ví¢Ç{Œ†No¼ñµlÙR¢%×?««êuEhΪm4{åyV33BBð&8 Ýñï¯[€ƒøžËï};*”/·ÜÙŒó“ß!A¨&ëÝUÎ+¬w¯ÂÂ9WœW›éäésw^ÁÆ#·ÇcÏQÍèRôóokVÇF¯ã|˜üªçþꫯdœg‚º._ü^NY ,X°€ZµjE]ºtÿ@tt´¤Päâ—<Á¯ª'…5•¯­êV¤ÚÑ%˜p7ÒÒ»Äâ ¤@‘,œ©yxÕž}) ÙüÔ‚W’M°Âéø‡!ÕFºpÂyÕÎ+øà¼bá „ó ½ùeë2/R:ME ä¥ٳ߽S ÊÁËšÅÉ¡Ûßœ?uêTzå•WhÑ¢ERUXP\½×Wø¿«¼Ô”àèÑ£iܸqôì³ÏRŸ>}(***Ùþ¬¨»·eªWù:Y¹¹y7ü™Ä? |þåòò]w¦Öá{dÛól ‚Wgª—r¤—4AíH¬tÿ@^Þwவé©NMdÉ+6x€yî3!Ë%ñßT~òL¿p‰½½9ÍüâEêÅ z üJ q7A™ïPò7Ò=÷ÜCmÚ´åWã|ôìPl7ã~å8uêýç?ÿ¡ÚµkÓ·ß~kpïäøÊËO=îhL´©Gù£rÒi ¡œn1ð¯—"У<ÎG{¾ÿ̽4õ¿DùA²2Îg"V€zóÝ!gøW‚=àº+Ϋå›wÓT¶ö>ÁOÆñ´¡K…¡':{þ<åÇi[ò²]ôúõØóŒàó8{磗†’?~œHC† ¡3gÎ\sœï_W§ßÁà>Û·o§nݺ‰„иqcÉ&YþƧ.¯$¬V¶(Í^±•æ¬ÞÊŽÂxÖ«¹h(ÿIv¦bæä‰Î-©Ïí¨XÁ¼’‹=Îw—­‹¤ï¨!Oh¾«ýx¼ZRf æ¬ÚJóØu„Ÿ/p @xL·A Ô›…ñ®Võ%¹êñ•WÚižèqÑKB!† &½óÎ;å;®ãž)p?(9„6{öljÒ¤‰†eË–•Ûᾪ\Nî¯z`ôÊp¾Þ\¿2Õ®X’ w­Ø¼‡Î±Ä) 9C>DçIDAT/,fRnÅ8ŸçóëT.s¥\xL×=É:©ƒ‰£!À‚vÕ®?\d}3~5ñ¯µr{oû7ÿ¬¨ré_¯|fýûó_¬Óqçä;®'–Î?õéxújÍœ9Ӻ馛`×Ë,Vû»ºˆwVrû^yò䱨°x˜ ecàú]²ËéôÐÒqÙºç5ðÓ,öøòÕÚAÏSá¼ÿÈ «Õ“ïX?O[dÿÌ{!Zêwû¢ù02 gÂê#ËŸmþcgìETXe†=ùl4©„~¿ë=ëÖ­[eznäÈ‘ =.îÂî—*ð_uk£bÅŠ2[pß}÷ÉQfe1¸) ê!‚Ï„I×g\’‡‹’Êã<[ H‡eÞ’q;\Kêæ÷Äk@Õ!XÊt•/^”¹ï:¦D±±±4hÐ ú裟‘ Š––å`ˆ€€©C¬hذ¡|wëDü¬Ýâ…´^IVÝ×¼{G ì @ApêGò"ÈèÍ‘Š…0jÔ(zýõ× ½?‚ÞóÊ… xQ½½êùy䙊,Y²¤”N·bU\ð3ó‘ i„@º!€@á ¥‡¢`JaÞ¼y²nŸÇûò]Íç#^°“"°üùó˳={ö¤ˆˆ{˜²0!ü0Œ6Õ{Hxô1Í?” JŸã|¯UÒ­ø@æöƒeœï¡Z’Ä¿ümÛ¶ÿ@ݺuåw¯þ¯å1é‹€!øª=%ÂO?ýD¯½ömذA¾ë=¨\áeòƒì0ŒyüñÇ饗^¢¢EÕþzîÖ„0a]tCšëõñ|þ”)S$u(Œó=TS’è¤V¨P!êß¿?õèу·Ëæ5K“.ˆ0à 1ÐóãÝ~øá‡²3ÿ+«ÀA6!Ú6Äóð´nÝš²ò OÆ/²MK†’h;(8ÂÁƒe¾|ݺuò‚žŸHO$k'>>^ª ‡çC=$ŽN5dHOx„C]ÍÜN­¨z·Â… ÓäÉ“©wïÞbþBù!ôéAðæ@ùëׯ/X<ðÀb¥ ’“ýÙXšnÅŠâ?~¼¤FϨæÑ=dÔIt@±bÅÄؽ{w{ÝCPÞ.I $ ÑßÔxJ0fÌYK¿zõjù®zI5l‹!ú¢zu~O=õ”8 ,(5R>­ž)ö x}öìûôÓOe¿Ã‡Knz¯é!û4MsÊG¸í¶ÛÄáW£F ùnÖ aób M©÷‚{÷ü¾üòKQ½MÆ-R-)Ä¥<ýØižþ:HPWÔIùDR­`æFEÀ@2á…¹å€ù°xñbñÀaˆ¥ vÿ€n±`®À€2×™ÝÚ‘ ™—°BÀ@ 5§¿«у®_¿^î +Y Ý2ÙÙèVJ–,Ydµß‹/¾hVû%ÙÐÉÀ@ ·•Þcªç°÷ß±cÇÄ|ÖÇ×)|kÇÙùóÍzÇÐ…]DCjRÝ?c?)KÖ€²tû³Õ-‘jÕªÑkü,ƒyâ/A¸ÂþClbÿÀüùóeôØ+@W|õÌ?ÎÌ‘#‡çP‚=kC©ÐBª·‡"|ÿý÷âزe‹|וS.¤à‹òÜ+/þ£>J/¿ü2¥æ®?)X“U #` …M,;¥„ƒãàì¨ýý§õ°ï6,iРÑÌç'ÖRéç7CiÐÖº ;ëvþÅ8ÿÞ{ê$”U7· 2 ¤QƒøûfÍš%ëæÎ+%ò²¬НÖðÞÿÔ·o_êÕ«EFFšq~µs°ßÖ@·RXåÀß0ÕwìØ!%Ó{󄊪ó§[·nB&eʨSvÌî= a—Þ¯ ÐMó„Î Tk T‘ýÇùM›6òðzþŸÊ×¼§ Y[ëþœŒÕ„?üðƒ”R7ñuË \¹rÒãwíÚUâ!µØ'ȪgŠd²AqüýS§N_¸p¡”&?¬\¹rѳÏ>K}úô¡¨¨({q‘NaÕL‘‚ CAÖ zqtÿzõ¯¿þZL|aËsRGB®ÎéDeXIfMM*‡i  € €HŽw!°IDATxí]`UUÒ ´„* ® DÁBQ¥ò#(¸ ¢¢Xü­(6l¨¸¬å_,(ê® ‹`]iJ¨ËÒ«ô*z¯!„Êùç››¹œ\^È{á½¼—¼w ï¶sÏ3óÍœ¹§Ì-d8Q,E- GmÍcÄå@(@«vòäIеn9£»À‚/T¨)RD¶8Ž¥ì9P`pêÔ)Ñzš?räHÚ»w¯A-BölˆÞ+ùî‰'¨páÂ"ì &Ðu×]GwÜq]sÍ5ôù矋t X%–,0ómbÁ»´¯\¹ÒÜ}÷Ýx¥•?¸»ß´iS3yòd7ïñãÇ Á=Žæ˜Ë|— xàþýûM¯^½L||¼œ-Á€À¾€±Ð¹sg³víZ·¾6€Ü“Q¶“¯À&ÜØBcónªW¯îjº-lµØöK—.m^ýusðàA5€d—eò7ù̶¦)S¦˜fÍš¹‚‹‹sl Þ»oä’K.1_}õ•) À¢-E<líüã?Ìý÷ßï UsïvvǰŒ^oÑ¢…™6mš+÷hó"¼¶ó‡2o¼ñ†˜oB Tð*pÝâ~Û"<øàƒfÆ .là¹' àNÄ@yýõ×_›5j¸k M…y.[”§þAÙ²eMŸ>}ÌáÇõñ~q€Ögdd˜éÓ§›o¼Ñ¼¿í|nÁ`«V­ZføðáæÈ‘#¦ û5ûãÇwµ²hÑ¢YÚìÜ ØŸûÐ,/^Ü]ÿþýÅäæ ¢nëkÙ¼yóL»ví\a䥸ꪫ w%›ôôt×)¨mAÄÀËèüÑÀ$«Û¦ZÏËÖ.¯bÅŠæ½÷Þ3Gõ’Q`óŽvgÿ®}ÒêžEÛ«í/Úâ~ýú™òåË à´Ù‚Ë ì·ì?ñÄfË–-® m³´X´¹™xçõmÅ>Ÿ_öó `¢¿Éf¶-ˆ7šGy$‹5€ð€· M›6fΜ9.iv?è8yÒ¿1󹊌Qæd?aÞûæW3¥ó¾-Zž©YË6l3Óÿá²ÅÖ,h˜Ý8sæLÓªU+Wðþú¶Õ¸âŠ+Ì?üà>OPœðZª_g,2GL’¼¨‹jü¡Ô£fìÌe[M6xõ\$oC6Ì•æá×SMJZ: Ÿ¼ægú—W«ìÐÌõ*Äà 7 €ãéÂÁ+Lû¥Ò‡ÃÆÓQSÅY*—)̦—ig;†fA·J²€ýYË6Ðò Û醫/¥æõj 8Tû hì£ý‡3èó94QH#&Íc­CË×o¥² ñìh–íçž ¹¬€ÎmѸâ´i×úlôLºúÒªÔ†ÛÊåKËcÔŠë™–0ÀDhÜWc¦ÓûßþFë·îb/Ê—IŠöœ­x.üƒcÇOШéKiášÍÂÐú5«º·:Z~ú•PŽY»ç­X/íü¤y+¨8ƒÉiçO‰ðÝ›ƒ¼’Èâ™þè]¹q'5¿ªµdÿþF8“ß­âŠÌX´†=äQ4‹¦øN;3 Óé/# 5EX ðv8Ì^÷\~õÚDðªž_Ž‹q^½Ô*lݵŸú3X¿KšIÜ%`Ím;ï/Þ|JK|‰bÌ+CIóVÒ"~Enݰ5¸¬*['ôUxï ý±_¯ÐqŒ¯ä Ù¥´còZ„¾HH"xnêá#ÙvË8.½‹‘Bs | 9”‰{¦r] ðÂýtõ剙‚.,£‡x®sñŸ¨C³+…þ´ô Ѫpiž ÀN;J‡¥‡;¶¢ç:ßì‚×Asw…ß{ãµ2°ƒÑEœËo@¨'0tÁœc¸Sª0òØ-©g×[¨jåóÎ( Mà>ò[šÖ¥k®¨Fã箢%<©=$%¸§ Œåÿ!O°;=<Ê–(-ý5«wõz¨µ¼¶öÏÍüŸêóè^-ž6mñ:ú/ÏÄÜÆxîšæ«9vNQhN` ´þ3æñ¦Fu赇o£FujHõÐ,³pøC¶H¶…|1@sÁyeèÛ6¦U›ª 6ìØ+B·)ºOC•@Ó‰§èÀÁªQµ2½Ø¥=о¹3G€éD½¤«YÀxz~"z pÌXjpùE2…máš-Ò[*ÃרW^ 7—Œ *`63ŽŸ¤ý)©T·FUzå[é®› iÎ<g2áCÛ0šÀ|*³jU¿€.¿¨2Í^±&/XC{SŽÈL!§n_)ÔÏ5Ù¸|Ì[ìÙµ=õ¸ïfž XJ¬è ‘tr À€}…Þ <$~ßM×RãÚ‰4nîJZ»y·3™…ç8†¼~VÕg¶  ‚Pöñ‘óË—¡ºÜIOvj-#^Žù>=C™á¯[·ŽJ°_Pµª3–¯×@)ʃpš]Yƒê1˜&/\C³–'SZF¡“Ê(X|Ö,‡“Ž¥*Ä&;]„Ó±UCêõà­Tëâ*r§Zª"…¸n™– 4§¥¥ª zõêI>L0Åy/lÔ%V¤§îøš¿zMœ¿švîK‘qX™HÂ99ÐFT*…¥tn7a2ÿóÙ_èåÚ‹ðÁDÕ³xý=½õÖ[ÂÄ«¯¾š>þøcâ…r ÌÆÊFÃ0î[ó«èÙN7ÐU5ªPºåyçæ}!ŽiÀ Óú—U§ïD‰Vbóxš‰¦j6…Åú›o¾)Ú„`Ž=zô 0vìØ±.³uê¶£YªT,Kßr=Ò¾)]Èû©ÌPÌ=T3ž/Õ÷ØËí|Ų¥é׺ÐįR›&W è6̓çƒ^L8]´hÝzë­{pùòåŒ/¾øB€€E&¼vñ ð‚G(ÓܱV๻[É\FLHIÇ4w¶nÈî0ÐΣb{x&ÎET Á½¡_?ê)3ÚK˜n›‰:/—s/ç’¹ûëׯw5ÇËäŽ;Ò²eËÜë¦w¸&–˯˯Œ=:µ¤;[Ô 3²Ó,Ü‹fêàá4^ûþLS÷¦nw´ ‹Âב`UšvíÚåœjÉ8ÒõîÝ[Rò23¾e8‹RGhfºÀ¯J<¦K›†ôÄm×ÓŞǫ£2è8+ ò„51¡9&fäÙºkŸ)ß²›©òç§MŸ!#Í¡ÃiržµÜ]É‹,49ŸäädÃ+rÄÉçŠÊª^f’{ŒsøÃ9= /¾ø¢Ù½{·[Ž]¦Òƒ‹Ü±d~žºÈ<ÿŸÌëŸ5XˆŠy¶’ìßÛë†t6÷÷þÄ,Y»YÎáçĉ“’û,x—nD(áfÉ\pÁ.Üt¹ûJ3%KðŠÖ­[›Ù³g£8IöBSáQ&AÛìåLŸ¯’L·w¿7<ÁUòÛõrJý/4"Ǥ„mÞ±×tï7ԬݴýLÔ&â)55ÕôíÛ×ð¼|a˜å‹‰ÊLÝÚyªT©bè– hùx75ØHÚ¸cŸ6iáwx9ÆÐ ž¿õ¯›ç:ùW¯Âà­½ð”›!Ãm¼+lnÜh%J£w à*ÝØïÖ­›Ù¼ÙÚi…P^‚îðð®Þ´Sh³¯É‰<øñ J‡Íp/m Ū[¬¾UF)sô8§­W³5jd’’’” 4 ÉÖ,=– >~K•y_·ÏÍŽáøÂYh9Ñj_G=õž *˜wß}× 6a+H³y©uñArÈO%\‰á6±Îëí•)þhæõµõZ ÄFL`M6è@KvŒÄymp/îÓ¼{öì1/½ô’á×Q¡ÛnŠ|ÑäÏ9ðuëÖ5?ÿü³’œåÙÀp8´Þ%†w€}³î#²"lhè¾? Ë)-ÄFl`ÄÎMRÁC#?ýôSÃ}.`mÁåDSN×½V ñŽxIºK²ÒážÓN® Ä#t /Í6ˆ­£ &µLÝÚe'&&š/¿üÒm”¦³ñQóLæÈáMš4qi>WK¥ôùÚ¼J7žÃ¯¼fÇLJRzÎFs¨¯  퇎¶Y+]¬X1w_Ï…b ͲŸÍB`GÐt6†êuŠVºð¶LK¥åúÚBø ø¼œÝñ_2æP :»ò £Ñö/\¸ÐÜwß}.CQAu‚|1á\ÏÙÚ„ç<ú裆;f²´«ÙUT»}ûv 8!€”£‚9Wú|Ýò!|½Ö¼ysqh‰ìl€Í®Á>Ÿ+x‰€‡n[ƒ`›T/o¸á‰$ê¥#ãädÿú'Tp¹ÙÚÀªV­šÞÙñî®Ì² çÝÚe f0bk³ñ\$h“íék½¦Ú†­ýæÂ‘C Gqix½Në+¯¼böíÛ'$ VGhVÚlšój?`(aöë‹‚×à OC®ÚÌDø¸š{ð‘D GÔp$_L” 9üd^ÜöÍ7ߎ(âÁž¿t{›“»îºË¬X±Â¥Ê^¥Ã)x%Ê/(¡9Úô%ëXëOk^ÃÖ®à’%KÌí·ßî2Ô_ͲÛy0ßÀw4Ù`SÇ×xDÒ|9f÷®“¬§érº]wîOÑ"²¼{£<ÍËA¦ R™2eÊÝ^foÕ°aCÃJÜç/ú l•È0|Âl›·^òjÿŠ{cì€ý)G¸ÏýgóÞ÷“ÜþkÐè Ù¡´0fÌã9ÁËD|_Ñt3M?®ÿ4yž¹òžWÍe_â±€ãr èP¦üešyáŸ?›‰óWÁ<ã:NØÀà8®K3¬€é ¶¥@ó÷É'Ÿ¸e¡ÌÓM”Ó-çŸEk6£¸æ~ÃA´ä´ Íêm@£¾,ÅÁ¶ï=HŸECMÛöf†Å‚”‘…~ç)[ Ü'϶i@p)nˆH Ä,4à$„;òÇÍ=ÿüó2lüä“OÊÐ0èF™ÈÇM?ˉž¶“£‡½üñ0Žžö›µ„ƒhÅ»Á¥\‚óp' €.V,!óÝ–®ßF˜J£f,åXyÇÜ¡M0Õf‡|§gŸ}–/^LÏ<ó á8 ƒ˜YÜÃGÜÃ'LD¤/"Ka¢3eëîýÔ£ÿ7Ԯǻ4eÁ ø€YBÙ…¦=Öä#àÔ×GàÓ‘Ó‰dY€ÀõÂ@xñlÐWx9̓|·Ýv›üƒ> J•*e8x…?€Ïý4™nèÖ‡þ9|¢œC\"u W  ƒ©Ð,0Óµ>`Íš¹l½Tãòȃ?[³xxUfÿð˜ÝrË-Âd0±S§N¹“G‰BËy÷ Q3³u?–$LüË$Vbü€‰ '§„²0¹t¯á€SŸü{ý8åw:Àót\^Á‹g¨LbRÈk¯½&@eÓ.“ZF-³„0= ç×¶T(I³–ÒMÝûÑ‹%ó%+–sâîp§sš¨L‡f>ÊѰ˜™óWm¦›×"LêDÓU³À 0Sª0ûgĈT²dIB3&‚ñ Ñž€‚4ú¿ émŽD¶ˆC¶–I(ÉL<Ø)»‰ r£ç4*pj&œZƧZfœ@ t f 1Ë_Äß2 xÀµÈÁã.b‚A¨%u Ê,Â@fô4<3霠@P˜)„hX›w Á «m0Í y  j> h¾sÍÑa"sÑf";KØi4%Í^*Ú¬ÀN ^ 85’N-`ßáiëÕt&†"ZüÓ€œ=~¥¾GÉ씢ϋèiç‹ @‰Pó)ѰXë'Ì_%Ñ2oâh™k;Ñ25¯ Þ=f&bÒäç#§J[¿…£{ÁK.Ë¡l/¡X”‚P¯ÐøUÆmÝÖ=Ô¸N"î²ÜähRçǸOšÐd=×÷‹Q4{Ù:Y2†(©x(éVšÎet(1Ð0S¢a±6i¡êµImªY¥_9=+ ÁìÞIs—‰¹_°jk¤ÕÎ瑳: TÄâïÈ›N«—S¢•¢éBR ¯Ù´“}“ÑôËÔ|–Ûy^P‚ºÛRÉCCð“«·€@è࠭ݸs? dÏ[ðLF»¦&ñ;q‡> É[ÅK†3®6t!!|=¦¾›¸@–©NÔÇ~!^‘Nw¾ü! ?›J³•(ÅaåA³‚#>…+oÈ€ŠŸ`ÀŠ^Æ8hæpÐå÷X4]ºøÎ B£MàØ7øFÀò:–2J;qìK]ÛÑsôA;©–+jV­DÏq@‰YË9àO^Ù¢€Sg>hàð¼ X¤Ö•ä/ Økj]|¶ÛB~Ío(%èòÄøö=­P#þ|[GÃZ³ióó§ÝB Ëa¢Ø©åµôꃨö%™ŒjZÑ£ˆ‘;$Õ®ëùCM˜§p€8u\f¡3yB• 8úž teÍjLs{º£eCyzA§‚6T4dWnÀ€öY`×ÅüÇî·7—/w!Övž Š~s1Í ”`&§Ï <÷°qÝÀ±}&:Ú |m á;@xKsÀ©Û9àTCH™ÄŸ¥ÅççÐŒáÓ-&Õ#º¿=­r…²Ô“ƒgu¿ëFùØ–t‹óÃÀ«p¦€b¡‰hÿUkð¡çº_(‘2§-YÔh™`ŒÀNÕÿT‘útïDßÖB?gÜ€Ïy@ ¦”aV„¿mÛ6âiÚB«N5sÀëÐ]¥R9z„Nã›xîA ž¬wî¡ÜäM‰%…Ûù¢LÏCZHä4ø)Hh6ÅR‰aN¹€Ò¬m,Ð Â0ßǃPJ°Eà ½7§-„…섘¼ÏrðÆ:·£ó3§˜¹Lä‚tj„ÀNo¿ý6 :T‚Rýíos§p)@@·‚·î%Ò<Z§ü¾Vž‡Æ¢^åD«^ç[X°K£¤ÂÁkÅ!fá˜6¹²¦d±-•Þîí9@‰³`:aBñ¹÷έ¯¥Fµê•£enÙ#sùà9%æ>U<ö“Ôþúúb´šÜ*LdóÊšABã!\ø@˜YÌëï%ïÈ‘#‰®ÒÓO?M¼>8Žä×&™ d´Ñ-ê_Jøøä$öæ®ØHǸ<4g r)ð,?(_9ßÏŸ°¯ÍÁ&+ñž6Mä€< ·¹÷E~Ð X3õÀT¼v=Õ±ÝÏ¡Ñà4úM‚çÕ1bîáØ}ß÷)Ö÷i‚ð!xGØL2—Ãy‚ðûí7′æÂ‡%€àp-==ú÷ï/Ó¸ ¬†8Šœ þAÙR%%ôÜ3w¶ÐiÇŽsK§ÿ@2ùø!\´ó°‚o<Ö‘¦þ«·Ï°‰“öÞýA€– Æ«ù„ÂãMÑ21ÉÌ:¡à}%0+…gÓ"^ï»=:ÓäA½Xû¯Á@8Д Ác !#hãwÞ)k 8V\ó <Yónݺ•ºwïNM›6¥ &H^å!¯ ^LíÖ¡=Ô®‰„¾Å¢ÐàM(Y`ò»´m&QR_åp³¥yf‹ëú&â½7b޹ò!MÌ·|î°1Ÿ™iÖlÞ%çØ4žQ#û?Nœcý¿ÁfÇÞn~{¹7 Ê]ëÇÑEMÏž= ìÄÂȧV­ZuúYÖ’mÖZ÷Y|þ×YË ¯~rhæúà:Òîý‡L§W>6Sث»Ü[ àèy»l ¨Ðíshy÷‹$3y,‹+!|$ÖhóÙgŸ™‹.ºH\Ö¢,BÅqN¬‘îBÏ„„ë}Ü€S¬>Kž§D𯅛oÙ$¬t~KyeŠ­YzÎÞ$ª]ØÚ«ŒÙl5°û.XÍ!C\R€ IÀ›ƒ`mKå’OvòþòD™ü«W¯6÷Þ{¯+,æ<'M÷ç:Êa_Â-Ë»$ݦÃ_Úó[¾ˆ€Zkà@Ìf´M·? $ʶ-B×®]Mrr²ÈRéÉo‚õ—Þˆ4 Ÿ:uªÑ(^Ž­¥6мý¬Aƒ =Ùý5™žë„×&¤ZµjÑË/¿,]¹ yUcáäº\nd AäYˆU€x­8¼=’ÒåO9ù.¿¦"ùÓJ¸Z …E`&íÏëpÀÃ,ÂQݰ<3¢šåšû 1v9 „+t˜iî\`›ûúõë›Q£F) òü‚Þþ£² •`¿—#ê6¢o«àmÇMÏù³µï;ÿüó%Þñ±cNt1´÷¹ÍWÞê6¢ DÚBAˆUÄá×Õ°¶@ÏÛÛ‡ö?õÔS†‡õ1YÀæž,à;ù*Ûà‹?þ¸ëœÍ?ð¶ómÛ¶5óçÏ×b£ÆÜ»¶vò@·×?À7zð­Õ|¯`[‡:uꘟ~úÉ­> í¼[a;ùZ¯àýL ô)¼óÎ;†?ú(·ÛMŠ–­Û| ˜-L|¨ªOŸ>†C͉E@›ÿØceû'-#š·…Py6Ÿù>1dŒÙ´iq/ž|ì‘>‘ØÜ»óäDìG8P`€ÚËÜ4¸@À9½|ìâ0–<(PкøƒàñKÙs @ ûêÆ®x9S/G¢ì8€(¸·º1x9eÇ1D™À½ÕÀË‘(;Ž Êî­n ^ŽDÙq Q&poucðr$ÊŽcˆ2{«€—#Qv@” Ü[ݼ‰²ã¢LàÞêÆàåH”Çe÷V7/G¢ì8€(¸·º1x9eÇ1D™À½ÕÀË‘(;þ_ÂÙH1ŠìÁIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/48.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000527215232633614033154 0ustar runnerrunner‰PNG  IHDR00Wù‡sRGB®ÎéDeXIfMM*‡i  0 0Û7l $IDAThíY{P”×?° ((I4†ZD’1DMd&°˜P­cÉh[±ZuŒÛ:Õ™¤í´ý§­S'j‚ÆDÅè8E£ ê¨((÷ìùT©Ñt£M`<û{ìì飉_dˆgÉ8l^[òÙ™VoËw:Jýƒ°'% v&Ÿº–Vî"%ÔæÕ@yý ˆzñx5ìذaÄÅÅCZZ*ÄÆÆ‚¿¿? ã“cxôÔ]o…À) £0ô“UX ¥uˆž¯¼LïF´•ºÅ".OçÃßö¥BAe=øùxÃþØS"Gš¢`‚·ôô ÀñÜb(¨j‚×_š/<ýX½zµ’šs¶}ž…õàË~M9–}d¦ ã Ã8G³ áëŠFX>B§=IoMFJ¾ÑZe2…XpŸÈ†76• ˜äï z½††­7"ò6èunÀJ\oë€O¾¼Jjò=Íz&Äný7TÖÈx‰aZèZey„qçÂËë…‡ø3¤ Ì7Û;ÀËÓƒfx)>,f^¾ÙraA㈟³S7y„1´ÞíO½sÊ,“1ºzûGŠõÙÊR@„’fûg`ÿf(N2er§C&Žo¦Á`™L,˲2@1+©§œßM³BÙÇ´H¥Rq±0­8éô‡ÁpEyæµ2@詤xn½Ó/…ÁÎ-¿ïq^0ÞËÞž ûAW_?ÐNawÖ´s㣭+EXqÈ ŒI„A“3†ÔÇ^k‘…˜Iî”mw» `Òcð—u±°öíh Üjm%èàÅgÏSZÍ-ª†œâ¡9K…•ôŒÄøóÚ·a],cÐú –F3͹ŵÐÙc‹Wšö”Öö[y §×HYgcükµûx/þuÛ‰»vAجY{÷í-¤Ôù›¸ñ£é"Sqh1õ°g†îÑØ× s÷û°ñŠ»vï†YfŒÏöîÕ`DAĬ` ­’£ÞS¼ ’ÛyúùB¼XR-»ñä©S¥q¨ãüùó1#3SñU5ÝÄÒk×ÅóWy…˜_\¥Þq¹.ÆÉñÜr©q.#CñU7ݲ:ƒxv¶Øã…i“Š‹KpùòåJ(W”ä^qñ½TdÕªUXþÍ761JJ®âŠ+¯=Œ•T’—•—ÛÄpÔia×4ƒT¬]--Ã)Sž‚Y¨‡‡‡RB*Î}Ë¢Ú´iXQY%ÆòÁ…1JËÊ1 À%ŒJÆ ñ¬‡³da€vPUU5®^½F).g•–`¬[·kjjµCÕ}uu5®Yó«Q1oýúõX[kCÙ¹QȘ+ªnÆÊÆ›Š=;Ûú¸È^ˆŽŽÆÜóçßÙKWñä…"ñLµV4ÜPïøÈ¥ ‘^äcçù¼<Åwæb ¦/ÏrMª—vn”r@j^ nØþLθ‚­w:Õ°ýIIˆÓ§OÇÏTýµM7pã?ö£ûܟᶤ4ÑŸ’[dÆøŸFÒÈáŒR5|ÏŒñ÷ý©¢PsQŒ6n¬ö®a8ç_,«ƒ«×®CdØÓT2? «à­7ß9Ü××—vg#||ä,ì>ží=0nœ'x÷¤Éðî„QOx•RdÔìHX¹R`¸Ñ>à;q"í}ƒ‹¿öN3á¸BV‘ìð¡*³ŸòzZ~)•ËÍóòs0;$P`qî2l;¥×šE¹ý¸Ÿnwˆ¢ŒL@ž#=¿ «[,0Žž»D_A™ g°ÚÈä@®u´½N¤ºŸ•;–S"6š;Ýð»Aeã ˜ü˜Ÿ8çÚ*·Ç #»˜Ê“aèèê…Íÿ: U‡R{­•Fg¬‡•—§^” ¼Õs©=H»õýrÛTÔÉ2€Ë I¼rmaLô! ªµìaÈñŽZ+ ™Ëhmù,ÃJ‚±B|I⣠?ÉRBzäa0$¶£ÖÊÿ Þ¢¾ï£ó¬(Ê4³9Œär»£»—â` U¨|"óó/Ö3ìµû( H–3ŠX 5T±²¬D®yQžºTõ†6uRÒŽbp®JûEáï¯Z ?~ùyÁIYë Â8óuÔnSV2¶la F7ó ãkÞ‚È93„ñüíÉR0³ŒÝOBÈÔÉ”¯AÆ•*¸ÙÞ>t0ñ˜>HµÑ±‘¿TüvùOà—o,ïZZZàĉˆG”Ê3‚ž‚<*·³é Æ-:WxÓY„Á§8.·Cƒ`óÏ +—ÌkŒ'Q®%Áìè‡âÛŠ´ßgºzx,»ÿºÿ$Rlãí»]8cÙüà£d$#ÄX£Ñˆÿ¤O“'O&ñ j ;vPM4(ÞSˆ!b Þ Ú;»qfÜVüÃÇG°½£[ðб”ð¯Ä úawÙ%¹;3Í ÐÛ×µÍ÷KcÇ#ÕøBqV^ûenîܹ˜–ž®ðo¶wŠI襯sZ í@Åìäͨ0e:ßðüXRfV.Z´H).‹=6‚B@|ü¼téRÌ3×<²æb4žqí³¥çž®^œmŽtáœnúSãjI dee‰>>"2IÙÊþŒŒ (--cå;šñ%Î¥xRFü Ë$gÍ`0 }RT³-KmnÙ>3lÚ´ é,dÈq. e€Ã²7VûËåË—1&&F…+¿dÉ,(0•ÆŒ¡å·‡ù ýl ãÕ*–œœŒ‹/Æ””¥ ¿3/ŒÉ¿”¤ ª“d„’±&ä:ýcÝŽ‰R):Ëš7£ïØÿÄÒ€o£u˜F¿ ¥\‘ù½®ÌÖ£àýÞbV]ÁüÎ{àÿԉ䪥:IEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/20.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000176415232633614033156 0ustar runnerrunner‰PNG  IHDR‰ sRGB®ÎéDeXIfMM*‡i   ²Ýðý^IDAT8•TYHTQþî¥Ò¦Ò,ERHjD°²²Ò”°$¤"£‡ ‘¨hˆê!_…Â@¤¢z(2‚´‡6™2Ç%b°Æ-µÅ©1µÅÄg¿sOÿ9:·-£Ÿ{Ïò¯ßþÿ‰aATTÔ4¡"9xëWU¨ô󹯯ÅÅÅHKKCQQÞ÷öBQüàñÕé0p„¤Àü~>Ž“Ïëaû÷qäÚ¿{×NÆùãÚ4ª¿õv|–ø@ù°¹ £'R’!K ]–”_ºŒãGˆK^ û—a¬]f€Ç§`•!!`2ËÜߨÅc¥È;QŠžƒøþÓ+ÕMˆJ΀©ÎŒ~)ÛN\@K— £N®Õ4¢²Ö‚1—GK!àU–$ Ÿ‡~ ªö9à÷S’Œ”¼^/ê,í° ~ÃÕÛàu¹„ @ùÂúö“,7(Iˆ¢H²·Ç‡œMéÈÏÉÀŠ¥‰X™’Ä}CG}~é©(Øž”ÅñX·ÜˆDSHœ¡mà6µ"sÉ|œ=}JTñÌÙspèôˆÖÏB}K2 ±(+-Áà—¯()9÷Œh">fž@È3¤( !fìå‹&­¢$`¤@¼f!{ÓÙÆ"##Bäõ¦GB°dN‡áŸc›±õõϰqÃzlÎÎBƒÙŒÎ!¯mýf³a2=AîÖ-ÈX»uOM°»#ÐóqÜžüh©‹3TT†ê†ØÜzT߯EùõJ”ÝoÇÉ‹·àUT<¶ôÀ:ܨº‹Š;÷p£ÑŽ#çobÌ鎂†Mp¦“Ñôª ‹ÎÅÓ­¨ydFll T*•–ŽwHŒ™ƒ^{?*kL˜3W/ZFƒ6± >ô3‘šOU“Eˈˆ²{󲜴ëÓRÎc“27 /7sãæ‡„4BnŠ¥ÛŽð0Z»{M"Ü_q¡¬GBrú&8¨‘?|ú §Ûƒ;²&ƒßAÚͤ;êW|Ìxø áY‰yÏî|ær:êÔÛü>k[mÁ!kD¯Œ¸ô¼::;™Ñhdôt±ÂÂBfµ¶2ŸOa\‡^Ífò"Äád!ß ü‰ýW^È ÉJô_s’eÑeÁjSÖuÐäNµk`N3ÿ3äÿ8ãq~m-˜E÷ùÔQIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/88.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001323015232633614033145 0ustar runnerrunner‰PNG  IHDRXXq•04sRGB®ÎéDeXIfMM*‡i  X Xç€HIDATxí\ |ŽWÖ?Ù%±‹}W±}©µµb¦ÕjG‹j‡ŸêhËàW>ª˜Öî§ã3ªZ[Õµ«ZZû®‰¥–X"D‰È†ûÿIî“Ç+oyŸHæËáͳ¼÷¹çÞÿ9÷ÜsÏ=Ï뤘¨€,CÀÙ²šsPñ“ÌóÀ?¦G‘““áŸüNy`hìÇÉÙÙ™\\\èÆrŽkÜÏÏýÜÖëêê*À6ŒêÔ©Cï¼óîC£Q._kÇs!LáJHHP³fÍR¥J•„k||||ÔĉULLŒ”c“¡X£å<¿üÁðËU²iݺuªAƒ¨¬±Š5V±©0îÕ¨QC-_¾Üh'@F=ùràääd“ÀÀ@Õ³gOD ¬Yƒ4îë{;vTû÷ï7ê@}yè\ÈܼyS}ôÑGÊÍÍM€ã‰Lá£ALïˆïÍ=hÐ uåÊè¼ ²åëÎ'&&ªùó竲eË`šAKXÛ{(­ÆýbÅŠ©iÓ¦©¸¸8Zó1PÏ#'–ŒNc"»}û¶jÙ²¥¬»»»”-ˆY¹ÖÚ²µk×m6Ošy[i†CNoÞÈIIIêàÁƒêÕW_5@6kcV@E[›Ü¥KµsçN…Ñ>yQ‹ðÃT—+=í1¿aÃÕ¨Q#hó$–ÐfsR«V-µbÅ ƒUFà>237žÈ½“ŒhÍNHJó’’Ó|Ödv­´ ›3gŽ*]º´´@3ÐfM÷õõU“&MR±±±‚ø&šøÅÅ'È=|È~v*¸ ÀxÀ¢“gmG'4í8«º}8M] ×·TÈHõÏ5»Õ•ð;ƽ$“«ÆKbÅ+7Øڣ°õ  xegÔ“˜dœŸ S½>™¥¶8aÜ»w?^ýóÇÝêTðuãÏmïù™–ÊÜP^¾Ç œéRØ-<å[ê=b9Ln.®¬€)äììDçCoÓÿ®ÝK«wRtìrã¥/ˆ}Xb‚æÍ›G‡¦îÝ»Ër˜µM–Ç8²†R»víhÏž=´dɪV­%%%C)ÈÃÝ"£cé毦.N£{È…cš\˜÷È{´hÓAúî§CrîÌæfƒ¬‹Y~LC# ¬Ðižh¤#1qñ4oÕvZ°æWŠŠ‰#ßžäÊt^Î<'Úê2ý|ƒ:4®EmT'ö$Za5iÒ„¶lÙBkÖ¬!^ÓéÓ§Ì &k®T—œüPx»s}xfÉÆ=4{ÅÏrý6÷õ!ß"ÞOñvws0Á‚n]¯*ujúùxzH [IY ¡1ZCVn;D3–m¦sWnPÑÂ^Tœ;—üð=rz:¼(ϱÞx{ºSƒ´~ßI 8J]›ûSƒêå%jƦFÀ{íµ×¨G´iÓ&êܹ3-ZT„À(¹³@@¿=C_,ÞH‡N]¤Â TÉ¢EØ¿P¬íOóÖíö*¡(ú5ð<¼Fš¼À`WcÞN†P 8VP¦C[¬ 7à wê‹ï6ЮßΑ§‡•âÎáû‡étζ±lþ¤€r3*†‡íaª[Õºµ¨CK“â<R¡B…èõ×_O¹f3Mwgþ篆ÓÔ%iÝ®ù®dÑÂÀׂ·å©¯ÁÞ±ñIl®ŽÓoA,äþä_ÙO¾³J›3€Æ_ ¤iK7Óªí‡Ìâ¾<¹Ñè\vÝÄsîl‡˜óÙ›t1,‚ZÖ©B/7­ME¼ ‰FiSpa·ç®ÜJ߬ß%çE}¼¸§, Õ¶mÚ•Í•›«;…Þ¾Kßl<@ kT ýŠóH°€ì ‰bJX¸nMY´ŽîÜ»OE}¼Åf¥7³Ó6Nì3ðÙsâ¸F½^l@MkW⪘3˜­‡NÑÈ9+ØÎFˆ‡)J-)™žº,³!z°}¿xÎ^ CÈ GZ‹´iWªNû‹F+~>ÀàÆQ©b>Ò0˜GÀùxyÐÝû(m3H„ËÌ7ï=NAÜy¿¾"ج˜"© DÈÌß›ÍF⑳WXè¬T6ÅvÖmôõöâ!åòLCRבÙ1eè:‹ëe.ëÍÀà Ï®³æŸ>oŒÌ)VP¦Cc!m«I]3t^k¹ù¾çVñÉ`+:óÿ©N‡ ¿ÒlÂRì¸ùŽuÐÊ*ÍÆ€ZåÛf§qåeóƒ„$ñMuàÜcà­"ÔŒ$™ˆƒK˜\§¼Q(Nr 0€ÅJ,ân,5¨Q‰|}<Åf£ƒðkýŠûPl\¢Üs4Ј…À§¹uªW(M•Ë–Lå;¶› U*SœâXèÉ/ÑßßéAeK•G‰ÃAtãÜÃÝ•ºpÜ¡ñ •hûÑsp!TVsx6=ÏÁ_܇p%‹}À1 EêД>}·Õ©VÞà§y#!´¬[•êsÌcWà:ð{°˜1Ow)ŸÞQ–Öv6.>Al[×V hì ÞÔ¸vi,ˆˆt¡ƒaaaC(S¦ŒhüØ’¼¼þ kS‹:•éç#géâµ^2»p9^ZIþI±³It÷A"5¯[M€E@c; ÞÑÑÑt÷î]ªZµª|‡(œw!wEX%n=rŽNqÀýð­¦,™ØY,#¢c¨f%?Z>y(ý8ý#€¶\Þ© ÎСúõëo Ñ×_-# Q®zùRôá«í©_—f¼ôæ¡Ë€_{CvɼKø¦9#ߦó?%€‹:Á‘6h+o#QãÆ©^½z4qâD⌠ ‡,Ù—G ñ†Ý[Ð_{µ¡ `âY@Ùã-Œsú‡‡IºÄ’û=†ÏPÔø/ªÆŸF¨ÙßoQR¶e°›‘È›™šÖ®]«X`õħyóæjÛ¶mºo€¦%‹°×¡~:tZ[¸Q ™þƒZ¼å”Ó[M£æ®TÔè-U¾Û‡jÌW+ÕÍ;Ñò=Ú–ÀÛNšö8 :uêô_´£zõêjÙ²eº˜B¢ Ú b…QûN^RŸ/Þ¢†Îü·š¾b‡±Åd<à€hXº„Nàƒm A“ªk·Ò¶}Ì PÃ5:ÇÃTvy>‘,Ò·o_uîÜ9ƒvš5ݾ«nܯm: ·4ÀÃg,S݆MU§.†ê¢ lÚsH>yï½÷ ÞzË ¼Ñ-ì:¨}ûöu€·V ¶çŠw[Ôôv(FGØ xH+Þ10x%rçRôZ©ððp5|øðL3t°·†:ëå奯Ž«¢¢¢¤NtÒ¼GljQ? \ HãÍš¯7M‘lòå—_Jò 굦|Í›©ï¾û® 1êÄhÒÄÑÂÜX3ÇpÒ‡ôçΫüüü 1wBwÎöh.S¥Jõí·ßêê¥nÆÚ.AКV­Z¥üýý³ÍB@›x—DM™2EÝ¿_Wi‰iЕg¨Á(ÄÁ±W°_¼o¦xÿÌèœ6¶`Ú»¶ºmÛ¶U¼¡)#ÔBÔÃ5„ €;¦xcô™y£Mf!CH«W¯¶½#:g¶ƒ“'O~Òšì¬æ…£t˜)€’Ý Ms‘8ˆÉ“´&+¼]w†£spc4™]«   õæ›oeÐ °íL>pà@uùòe]ånWÏäfz‚7ƒ«Å|ëÖ-õñÇ+˜ ð2hæmkó_yå…ÄoMfwóνXö“ÓR½t™œíŒÎ@qÿµ~ŸZ·÷/0RüO€nvo¶oßþDjªº¶kß¾½Ú»w¯Ñ^qùRGg訿M_ªÞŸü|<6Ðv*ÎÊQœØ"×øcòñãÇU¯^½Ò²ÙÆv\HZk±púrñFõòÐ/ØeLá«©Ëçä˜!À¨ù]Cf¬TÿX¶U>bð¤%Ž ‚—ŪbÅŠFgµ&qº“Zºt©ñü^ VU߬۩ê÷£¨a_5ð³RNw €¿NûA_´Yí8vÎHô?³‘±Ù°aCƒ·6E%K–T3gΔ—lP1Úl~níÎcªÕÀÏ”S“~ªù€ l SÜAGœi,‚Ë O?ìøæ­ÙÃùhò>BXã£ÌàÁƒ‰5ŠF%OOO?~<ñ¤þýûK<AÄ%¸ùåèiê‹x¢«7£èo¼‚À›Ý/Úqä4ÁÆëô(;ÓMÆLrømŽ4Z…¬s³'àêêL…YÃa¬ê !@WÞÕЄv\|‡Ïó¢´9 ¶ 2æ¹Ö9ð¶…ñy«át(ÀºÒ‚c™lòi9þ |l7qÿç eÅU|–†d 0V@êVú‹’Ä v˜Í„…¯ŠŸÞ\&§çX¼ÔcÙ8Õ Õ«VNÞBÞ™£ó¼8 &àáu,d߼ܢ®SšZËðDÅïU0ðÐdG u!%‹¸o=^l$4l¹#]?‚æb¥ä_Ŷ>K§CÂ%³ ;|jRɪ@dèÄÄ%È#}x‰Œ Zœso„ßý¯£ /Ç«•+!AÇØÏXd@ö¶jÖyóû}Î.âÆÅ'&QǦuh'дjPSêÔÂÍj}™•³ 0LYQ…REéýž­‰ßš¤mœþt_ ÁÒC;;354+,t I­¹SŸêE/5«+íDPG^TL]…a©]ŒóÞú¾Ô„šó‹2rе[ü²£‹$÷e‡7 ½Iœ¨Å )þUÊÓèþ=èÍ®­„7ê²ä‹þÉ`Ô ‰jmÁ{mu8в—¨»Ž_äü´xI½ÇpÓ«+{íÁp„?Œ jåKÓˆ~¤=ÛJpÙ™.W°{÷njÓ¦ŒS€ÆV-[‚†þ¹­¼c·ýX…ß¹—ú’#[¹Tsf—7›",¡ñ®I NMxÿÏ4ìÎb–ĽãQsee©V€Œ@Dˆ²#¿­9¢o'ycÃ6ž'B{öZ‰™ œ ¹{áxÔ»½<ÃñY©àâ•YÌÿt µjÕJÞþ„Æ#¼‰ˆ´ ñŽœ±Ù£Uæ›h3´6öA<§±&R¿î­iׂ±bŽ`óÑv”± \ô7S F!Mz’Ј`õéøjæ_™¶=Ëo}Þ”¡Ëí5‡)HJ~D½%²'Õ­VA¾‡w‚•rÚ‚ƒƒ‰ß¢'Ns’ï*g É[ŸüôùçŸK¾¾DXÏáMQ€ŒM¼Š•À÷myà ÁëgØÎÂÆ·kœòšF’¼0´ò‘g"l±Ï^¸¦¦~¿óÇî÷Žœ¾¤ZòŽÁÖƒ'{Ø®ÁŽ?KÀà©"EŠÈ¼Å1v~Íûlüö§â@¾â8¯<'ÛV¼3¢éRØm5ƒSŸÌoÖߎŠQ/¾7I}·a.&ÛDæ6_Xxûš#Bg5Îw5¶uPil\¼qm"óv ~P£fÍš,+,ÎÍÖfãºB… jÁ‚†€P'¶@h‡Þ7Ä5rØÀ_šôi®s °nmFšaîÜ›LH½IjÕöšmÞÄD~6[5\{dæm¯Œ•÷0iÛM\xhÙ… Ô!CŒŒ h&Ì€-˜]›MÊõë×Oñö”Ô/#É©Œ€·)jÙ¥C¶m%:{‹_âÄhLϘ}‡ä€2È ¡m»m;žçµ¥£c¢Y tdd¤üeáÂ…”] 6O|ï+ü,æñ<´ÇÛr€mŸ?^½õÖ[†6ÃThm´§µ¶¦?Ɉ¤“ü@¹0´ ¹eš~ùåÅ‹ h{“yrÈ®_¿^W!õ¡Þ¼L¹°vÒìZ!u•·Ù  µ[¦Ðjüì-~þ?ƒ ByÑÞê>š¹°fµöݹsG3Fq6aŸ,@þàƒÔõëi?Í¥…£ëÉëÇç°Æ Ø™3gTŸ>}ÄçíÖ­›ât(],_˜£±¦»©S¬A¹FÜŽ´=’Ä0e ©nÝ”&î³÷ A™\kå €uØdÈ)èøàOÃÒn†P² )ƒà^&×õë×¹C‡(///†u5HÇ;”‹£>44”cbb¸T¦„žZ‘ au·œ+‚°_}õÃj Ùš¨H ÔßߟçÏŸÏÙÙÙ®Xr¹(·¾©F€ËËaÕŠÁ‹ŠK8öì5qAVnx=í¾²Ž î9sæLöööVÀõÜ5ƒ;v,_¹rEwQ÷Ãñ œWøP•Sîfpv~‘ñ¾>?0\«¬¬Òª{þ{»þqúh™!Ìò­‡xÉwûùZê=©«´È¹sçxøðᆵaáž={òž={¾(\ü9•ÇÌYÉm†Ï䬼õ.êèEþxõøøådÃÊ]sÜ"‚8%±¨<äjB—’nÑßÖGӞ㨠¨˜"#Z}ü}¼()ÝJßüxœº¼ø,½ÑóeúU³ŠŒŒ¤èèhu­X±‚FMS§M#/KÅ÷3siå–}´áÇX ÑúYò||ôôõ¶P~Q m;t–â®Þ¤a½;RÄ ajLQ)yÔáˆê0ÀZ³óhùæ½´>úˆÚ,$H’DÛ`àíe!¹â¯ß¢„Ôûôj—éµ®/R ¿/1B]ºƒÍVJw¾{èæ+5 ¤Ð O¸<-¢è?oJ»ŸMk¢ŽQäK­èÍ^)ì™ ŠFµü­X|Š–”Òæ½ÇiÙ¦ÝJ(\!”xV•¡ÐBøz‹B˜öºJçü±vW±ºÅâIÄcbÏ%Ò_×GQÜ¥¢ j¬€Â›IØ)^P$èìceö‡2#Û‘¿¯œÏ{Uÿlw–.“ÑD>Cï.ü†²r ”P`ãL(GöZ~>”WXLöÄQâ-«:C§ÞϤ?Ì[Eg¯ÝžÊµeÕwdQåÊÄå/ÊÄvuì"í?sMÕãUéô„Š*F[[iø‘¯·ÙʪÊ‘?ñ«Â:J‰Ò@?ò~~ުαOuÏàéáÑ„ü}¼Å+ªzYuýõ{§€aeY•›ê†æ;Þkª,隊»¶ŒnŠ>Êõ][žàŒ©ãjL{ œ?Ù¹´ó&•µÊSyXK´U³.B`„{cÞ‚Àc™•Pñ¦î¿5l‘ ^Ž”[PDÏ„+ª¿¬¤E%6’ÝZ¹œ;"AyPT¦¬Áþ~²2{(/Àêl“±0µàÆõIN]Ú<„’-Ÿ2ròéÙ¡ôÅìI4ñ­~²~Èb" ÇŒ¤çš‡Òáó?ËÖU"‹‹—€x²Ê#Ä‚Pæõûã†Ð‡o%?™Ÿ°êo:†SliûN%ÐÝŒ\©÷Rg³\µ-» ¡àj™9J¨i¿D³& £çÚÙàç«¶ŸÈ—ž£˜3‰Ÿ˜¦\[”£KâV,,.¡Ù‡ôîLóßA=;µ5x"Sâ-JèÞþyê ‡£oPì…$uÁVV—CqêÒp£b›²óŠèõ^¯ÐåM0ÀÆÆÆRß¾}iàÀ§„mDã÷ ÷Fõ§vϵP65/5hÜÆš“GíZ…ÑÆÏ¦ÑŸ`€½qãM˜ð'êÒ¥ mÛ¶Mñô¥½Ñ«}0v õéN¥¥åôP¥yªFîþÈÊiPéãsóš¹ý¨Y¼ód&d?Д””Ä“&M‚'‚ƒ©S§rZZšn¦Â¼Ó 7ù“µÑw%EÕ_ü9Ãßú€?ÿ×OœWPäææòÂ… 9$$Äà þC† á'N((ˆ?ýôSNMM5RAš'„ÌÌÌäµk×rxx¸ÔlM  4×Oœ8‘Ï_¸À%¢ÄºP ƒYQ±=ÓË—/³Ä³vB G¡ÆÏ ×ìäÑYŒ›ä¬L)"«5ƒçÌ™Ã~~~vÊOóéׯK"ߎgv^åúb÷¢v€õªwüR2¯Úq„Ó­9v,vïÞÍ=zô0€kkÀÕ8`×ö|b*}ÿï¼ãà)UŸv?‹ÿñ} _N¾#Ï•+ÿ%ejž­[·æuëÖÙe\îX³ùÝ¿|óWlV<ÍÙ»ÁŸðàð‰Ë)yevëÖMMŸyóæqFF¦fÉE‹yÕÖýÜaÌl¦ÎãxÖ²ïÔ»ÚvyÒÂ'ĘøD:Ÿ”N¯ÿ:‚zux¼$䓉ƌ£¾ p1 Q±œ§7üt”VH†$í^&5 ¤à (T½Ç ™œ”.$ݦĴûÔ÷•¶4°[; –Ptذa$ŸeèîÝ»$ó[õÁÏ®cçiɆhŠOHQ™‘ IˆÛïÝ-¸,ë‹â…`>_òX[ÅÓé„TÚ§#µoÕ‚ÂÂç˜$Œ<w™M§¯"“á+~ê˜4xä6̃Lü5Qæm,Êìñòó$«üc°,y´Û´Xòh»Žž“㨧JDgM’OR‚KÀºÃù×ËâC·dÓ×;cè¡räƒ ,X½]RA{UzG§l ‚WdV&’‚›cÎÐ¥ä;4iXoò–ÄÁÎC’qùë:•þ /‘?ð„u¥q€;BH?9ÔËD2ÿÔgîs‰©*¸”ðBi®‰`J™¥¬ôŒ ?)¾‰©wIv 5-ÜÓ ª ÏêÚÔ°f‚lsQR.ÊUE°ÚR¦üxKúVOM„ŒˆÔ§Dmø;öq øIa˜ÙŠZ ŽŒ±¬8º5xjPŽíÍÕ¸ÚW±*—”"Q xÍ<œ†ènÇÓݧ°4a…·l¦2Èúï—üÒ½¬<åfË茣Ur^]_z>¡F˜„’oÇ$5Š^{í5zF¾`@™=å³/.A”ù@)Úl-”¡„ ±hXÓúdÊHš*)&äÉÕŠ-†5Ëàhæ’Ýè0¬XŽ”N'ð¬/wð×?Ä}½·˜Ã†Lç/åèWXTñ¹/³²²xÁ‚¨ô"ÜLNN6ú""“/Ú¸‡çÊ1V8êÝgkw²¥çþhù&¾-gpM²íéb­ï°dµ„,ƒ&±2ŸÏ˜ ßFædÉhBþý¡M›6Ps€/þ‹-² æÕ7çóI\ gfÐGÏòù^¬ gæJ tmíî5¬Y›ë:óýÈ‘#Ü¿§@aas|Á[¶l1w¯R†Eµ‡UyYË ·c ³›£ŒL‚ý‘#G@ÌY¢ enÚÅ»½zõRÿÆppq[9üØmK5™üXLÌ«*¶!ú[µj%à Ã%+ôÕïQÖýÌ[ÊŽ‡— Ý}á €:=&$$ð¸qãì,- Ô3îæLÆ€Sài“Û.íL@åÚ¦9Ü·o÷îÝÛnÚ¶m[Þ°aƒÁæiÿ b½ÖÒcêÿµBJqYÛ¶©œœŠ´”¤ÛêþOãÞƒ¸; ªk/`å<í©šI–’6nܨ2òÏkªÎü¾:^õý¾Ak!á«Æ¢ Pp `›pct¿ñUî(Q?ÿ¸Üèì±p£› øÅ ¬àFgÿgáÿ£:°‡¦6+IEND®B`‚././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/100.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000001477415232633614033163 0ustar runnerrunner‰PNG  IHDRddpâ•TsRGB®ÎéDeXIfMM*‡i  d d/»ÞAfIDATxí] |M×Ö_IH"‰™ši 5-ŠzxJ5”öuôª ¯ƒŽô«NOùÚ¾öéü«å)-­Y«¨9¥†˜J1¥ADCÈ<ˆýÖì““ûÝ$7qïÍ/Ûïæž{†½×^ÿµÖÞ{íµ/Å…ÊŠÇpÀÛc()#D8P*_»v²³³ozؼ<Ùdˆëׯ“ @ñòò"oïR!K&ÝŽxl¯4ãÆùóçéwÞ¡Í›7 8sSÐO* „Â%##C}ñŪvíÚ˜x(Ö ¢NžšùÖo˜.hŒ>ׯ_?µsçN\Z)@`b4øž:uªªW¯žÉ`«h¦Ûû`ú^?ûì³*66ÖF·až(%ˆæËêÕ«UçÎM ¬ã„=ò;§AÁõ5j¨O>ùD&ºÒôíV@`FðÙµk—4h  3”Ã=o5c-[¶TsæÌQ™™™¥Ê|¹u’ʼ%YW8p@Žñ =}ÍçÈ·u,ÁýO<ñ„:qâ„Ù/C3ÍŸrÀŠê‘Åé& ¿–³°³×ãl\·,æNŸ>-ƒ1˜ f}\¶³­=z¨M›6™Í¢‚h(Z@̇JøÀ©€\»f¬°Ñ§‹W’˜ñ¹¿³ø8%-Ãì.fZÖõÇŽ;¦¯„Âx«6«Ù³g›u  †^ñgf]S—“åº )%ݼ?;›Ç6óWÉ8tÜìhjºšôÍRÕÿÅÉy¤3-=S}<ƒÚøÇQ(­MVY°`,ø40VÆã´GkP`` zûí·UBB‚Éì,h…E~Û©ºŒ|G­Ü²Oî8(«¶TSú]»œ(¿ñÚ[Ò¥w²Ø…‰'îùä ¤‹Öï OæþJ»#ÿ¤ž··4Ï£oo/JMϤ¥›öQø±ÓÔïÎVÔ¦qòáu0¨2¸?üðÃ4xð`bñCÌì<Þ]܇òÈ#ФI“¨yóæò›AåÙ7•Ëñ ‹9Gÿž³‚–oþƒ®&¥’où¼]=û˜ŽØø+Ô­M0õ¾ã6 ô÷•º@7ÓU¥X³,¦—x]0vˆ¢!ã>¥wgÒ‰³¨F•Jì•ÍÛ!Ø"0?(Àâ.%Ò¬UÛéÛUatæâUé>å oº’œJïýç'êóì ªàÇmúK¶ `ÿ[·ë0}¶0”v:Á÷±ðä ÚuwÉ+6´Îj-’ïÃ9w‰>ž»’æ¯ ##¨j¥@f)QRjºt̶:t­K+3_ùPÄŸqtôt÷¸€— oår›ìf0âââè¹çž£V­ZÉNdzzºÐèÆJ¼kÖ?ßE!÷u¥ÚÕ+QrjÁ‹í®I@wHCŒÎ{ó˜&š?b`wz}ä`j\ÏØÄ’E :D'N¤¥K—š‚Õ³gOzòÉ'%Ï#88XÎc·ž\ø­†þ¥unÑHÌØöUA jÞɪQ®Áu­hÛ´!½ÎãÄðÞä¢ÖP€ å@9úúë¯éÃ?¤ .È=¯½öq½ûî»4|øpã9®Oko»&õîÿ-Ò&_yà÷emA./,Ùùî´\ûû„iŠÚ?¢î{ùcÅ›@æý&@P›9wñâE5~üxåïï/&˜j%0¨r®J•*êý÷ßWÉÉFK§„1#ÍzFǩφªÑÿþAñ¼œ×Á aÇ•W§ªÉбêÓy¿š‘,xÁÖH–ŸþYµoß^ÚeFJˆè°F88PíÙ³Çlσ&]’RԢнjÜ”¥êéËÍö,äê[òN¾E3éͯªéK6˜÷(tD̘1C5hÐ OçÁë‡Çó7'(ÞÏ­õq½¨ …™jíÎHùà·¼RaŽ«ÑïÍT1ç.â´„Yà½xÅf[öBŠ´°€>\á…›5]¥!$Lƒ.ÑqÕì_ÃoõÊ©Dcm\´‚¥H8Pݺu+°óVPl%´oß¾*,,LW'ŒµJ¨Hßæë’«¡Æ™sçΩW^yEùúú =V¦[i°[…¤V­Z’±…Ì-{Ú«…ÔhÑù ÔksVéÅyŽ›U>ú¨ :¦Í’µÃùƒYšxîé§ŸV111f“"¿ÎC{pMƒí˜2eŠªS§NzòkÛÞy«Cæ2¸t0hË*˜úš³¿DwþêÕ«Š0UPPÃRhúœ¿«W¯.ñ¾<’~ê6íuZ_[»v­êÔ©“ „=ó¤Û*ìÛV{ï¿ÿ~uðàÁBi±G_qÏ9ˆ–ˆˆU·n]ˆòåË›Œ(¬³…]·Ö…Tµèèh‘J«ùÒÄ9¤<óÌ3fû0SEÑЂèh³‡û¦OŸž/-š&g};ƒD"É’§²NI²Ñ ±•JL¯\¹R¥¥¥I›ö: ZJdd¤âµ…Ò`‚‘0…ºîâ|£ lÍš5%¹ƒ=ÚÔZi&gsƒ˜Ü&!_~ù¥™®ŒŽ[M£Œ°>Ó°aC5sæÌ<Æ8ñÂZðËvlA~aQµíÑg;¦=Z:uÊl<ÐËó¤ D· æè©.ÎaVóÒK/™êȬ̰ÞW¡Bõú믫K—.I3è¸mÀ´nßúÍ· ƒ¬ô #æN3Ü ¸>gûm«¡}úôQÛ·o7›Â„³9w•Ѳ¹çHŒŠOH2i‚¹°Îû÷îÝ›'E-¿·2éÁT¼ª7ëEÖiíÁ¨Ójõöýr]KgÜÅ+Šƒ¤Íg´è±f9ìÈeómÛ´b¥¥Y³fê‡~0ëÕë,­¡X˜~¿j‹b·‘Üã*óU Ú4pàšzõ«e*”S ôŠ &X%tÙ²eªmÛ¶¦„Z§’Öc$z"áS-…º“‰ÉijòœªRQêÕÏ &évÆœWc>] ¾]¹]Å^0ÒP§ø·=à­0_/8ÖãDåÊ•»PTR’!pbšdÑ›«kÃ"T÷ÿUµú‘¼Ô¯iű3‹CÎE„Ýd²ßiùÖú|Ño‡ ·wP\ê Œ46ŒvïÞ-Î;NU“÷‘pÇ™'$ÇÑ&3‘8õX»i„ ÄÓxyŽÍp‚r;‘ÑgˆÝF˜·ŸCgkp¨ª«½YÂÊ`¤°0>!‘fÿºƒfp¸çéó âpc‰cž!n+›8ñŸ^}õUI%@¤::ÎÚAcÇŽ¥ððp3fŒt˜M<ƒgáEf û)zï?têìEr®Èçs®-ˆpuâ™Eà°F ög 7ÒVv‚™ÔÉÚ-ôÀÓJsçÎ¥¦M›Ê98:9õ¾ûî;jܸ±Á&tÂ; oö„iK¨ï˜é§M{¨" bÓ\”‡n:äíÅÐ}t¸<3—Ÿt˜‘£b/P—Ö·R_vWIÎM%¨_¿>M›6FŽI<-7<êa'{:`Ìÿèû•´`]_»NÕ8:{ Ìϯ@HPt öb ÔŽáT‚–â©•D ®BFŒAœŠMœ:'Ú‰gq g¸ØÑ¿9+§Ïæ­æÕóÕ h®¹£8 ˆ&Ò*ðf˜²9<Šó<ÎÐݜԽ-öÌ ÓƒNà^$Ø G §‘M•ASo¤¯¯§øËFJƒ·_nt¤}Ç»T•ç…6±ãŸ`j#Ç£6jó¾¦0ó:§'°§ÙŒÜ”†ÐÝ‘ôáìå´mÿqÑ &gÀ 9ÚìæiØE?Š ˆ¦#WB})£I–n'žöÍÛpîs†½ m—†îæ4Niˆ:Íš•0Í设Hßx àë°Óðã±tôÔyêÞ®‰%UÍGî h³†F܃ԷeœfRƒóAx~ *'Üü§Ø€h:!¡’ªÆ66ŽÓÓf­ @tmIujTáÙRˆÔOfBåxú F4¨U•ž»¿5äo¤5Àáç !AÁ|~¥ñvý­ï´dòKT)ˆ½ÏÌ\wE)t¥Žv±ò…KäŽÛÈ‹Zöò[t`:üÙ-o€v#E$ ¢0ý LÈ ˜FÙvj„—6ç@ífü.3P›WÝXû@Hò›r…>8>Ó95Ýúw¶iBo>5„îíÚ¶(UûÞBÑ5c‘…÷~<Þ¯3ÝÙêV‰Á…·/’)n*'RÒÒÅDõëÚŽÞ B[K³†» J3zNJÑPÖ&j·ç7>ðÆmç(z˜Uì• è±F~8øG/ñvˆFœ?òÞs£Qœïí”Õ? §+,ƒ•<‡‹6ðÓÍê×äO/ÚÉùëwá=’$a^É䨶èqNíšqÀ4o³0;0ÞQ¤üQ¢è±§ÂûÜâ$„{djwâ@íµœJÁ›J`ZQR ´†Â§èïG/=ÒÆ=>no±±€„9uGqÉ„å08԰ßöã ¢hyKPw×ò+Æ8a¤4Ô®^…sKKN‡8¹^Þ•ú±©…‚·MäHz~¹¸Ï±ù…Í.~›K-6¡Ø=Î̪[£2=ÅixÇZ~ÿÕI~u”?ïÃø–ÏŸ‘ Ú‡wlàûþÒÞbóAAÝÞ<ޏ ´Y$@ðŠf8ì5y_·6Ô©9KhNª’yì©6:†÷RUð§6¯å¤¾¡NtžwªMÓ„ÝEü+V¬Àe9åÊÙn7oMš4IÞ*‡k0c:• upjѨm;À©jfCŒ4͸´„ lžÚ3ÖÔ7‚-L˜Û Kû %OœÔ‘SçÔG?®Wÿú~Ô‹ë(x&Rî}a²â7Ð'ù/Bl¬Á -zùå—ÍÈAv—›Á ÌÔ<©…jsÞ£úé÷põâ‹TDÔi3ƒ#[P&ò{!kÞýŒšºx½JÏ0Î1ÿ'Lnv㘧6f$:ÆI7yË’ÓÒÍ4ˆ°D¬°tKûˆ>v¸=¿ûyïƒ|à‡þ“;óx÷½wï¹çwιËïð9.ÔK¥¥¥…p999‘ƒƒC/ÒµX‡Þ »)pJ…ææf V=ßË»£½x ÞËÉÉ¡ØØXjjj’Ïʳö³Kyð¤= ƒ¸PL&“xóÍ7EŸ>}0Ddd¤HHHІill X{îí ÝíP–=¥‰‰‹‹Ç—àÐÙÙY«Ï;W¤¥¥imõý´—½P¹kJ§“'OŠèèh ÀqØÊgGGG  ÝÜÜÄŠ+Ä­[·d×{áу„rϲ²2ñÌ3Ïhàx.j€Já›îëë+>ùä)C…¹2˜½ïÝZxŒÂz[ g3f 8P¾d… · ´Å¥úGDDPHÈ^……U{ž©Ò2j »Üm±šœww´oºS×/ÅÅ%2 ެ˜ô¦ Qxïp…††ŠmÛ¶Y «ä53bUš›[ëê]Oï†+†ij²¬˜ 5몈Y³Y••ËñöŸ¾(ŸË ¼ZªráÂ1oÞ< ” OÏ5kÖˆòò ÕT–Šßþ\$§åÈwg/ˆÇ΋Úú­=æl‡ •u1ÚͲ ±ú£xá÷äøÔDIy•TbGbªXô^œøhG¢¸xµßµZ[ÆèÑ£å\°`à=SöÁ“¹F|÷·B8Œ}N$Ý™œ‘'å½ûÕqú‡«Z{xønÀ:ÅžÚ¼rrr /OWú±¸œ¶ìM¦ÑÃÑô±a4п/Íž=›¦OŸNYYYrÎZÆ´;1…Þÿê[JË) >ÞžäßÇ[SsÖÛÓ*ªk(îÐ9:s©€fF Ð ÙË7évi1Ø“éôî— töbìAþ}}©®¾x®hƒ`P,nîÎò~>çeܤICé‰ÑCÉÇËæfåÓ»[è@r:¹¸8Ky«¾¡I“‡ ä9;;‘—“#]),£Mßü {ˆžN~}¼äÄî.N+Òƒo}¾›Þþb7{Εñ!^ˆÃ×Jý”Ååéî*Û8s‰2ò iñœIÔ×Û¾aïýþ­-²K_(j‘çØ[ `Ý]]dÛ3ó)ãÊ Z2g2 ~ÐxRPG}õz©ºá’UPH®lmx°‰=‡Am)P Vöá»m2SmC£<³^¹QBõÔŸ=C¢-`04BØ\×Àa\gK·vm AzÀ‚,'{»¶„Š 97em7–çèè`êíwòòœØëN,£'Å$,hTœXq‹u-ßUØE^ ¦V²±¸¡¨ñÐë®¶ÅX£¶­ŒŸ A¶m /à*¯2“3S(\PÈO;µõ2¤ñÝÖÎl°Js _7Kä¸ñidZÖÐØ$dz]bç#w R)c®­§ªêZúuôxÚñÞr¹àÛ“‘¡ôì´±l5·AQ!j4,”†¢¬¢šÆ ¥=¾B?,½72äAZ4k¢ÜVªkê- L7Œg4&ÞY­®úFPV­dpãG¡?/œM3'ŽÖšÔÖÖ’§‡M‰ÆJ¤ÄÔ:Å«`}S IÏh--K¨•UVѰà@ZùÜ/é·OM”Û Z˜Ífòòò¢ÈáÁöД”q•Ž_¸L&ëíáÚ©ñÚ ÕîÑГ˜?•U¼/yÓú¿£ý¯ÒfdfÛhÔ¨Q´uëViíþ¾^ôô”HZ6ÿq H5¼ŸÂ@*Ü0ÅÌ•f‚¯.˜EG7½F/Ìz\,,,¢åË—Sxx8½óÎ;dª®æ­È¦{˜þø›)ô‹Q!,«E®ÔSµ Ã<·´¢Žr‹ÞÚ"^þÛ?µ3*—”ˆÕ«W www¬Ú5yòdq41Q“чw>ˆ÷ãŠkÅ·åûuÛþ+æ¾ò¸tõºÖ®¶¶NlذA 0@“¹ ÜÛ·o×Ú¡’w£T|DÊųþ ç® v¥¬Â¤½ãù#6oÞ,‚ƒƒ5egÔ³‹çŸ^\¾|Ùª_]ƒåà~«²Z{JBÂ^™QÆR[ŸE˜6mšHNN¶êWS×zp·úÐŃ!Hô©6›Åž= bÒ¤I8¥ŒRw=îׯŸxã7DAAKàAWĉIbþüùš<}_%ôLã-Y²Ddddhù#H›«í@‚¥ó|¹yy",,LSÈÅÅE«+…Ôйººjßׯ_/e ‡öyåbæÌ™Z´çZ{V²pÇ{½¼¥K—Šººz)Çfdº†í@꾉ššZ±nÝ:áçç'•ÁàÊÊJ}ˆ1óà“ø6>>^ 6L×™¼ &ˆÃ‡w$Îæ÷V U€]Ì/¦š:MÂoñâÅZîŠéÁq*CìÚµKkʱsEa©…\çòÂQ|ÛÂAñ­²²R¬]»V Ïcd¬Aƒ‰M›6‰ú;s}Îþ'2s¯¡ÚmniR­ZŸ%$‰×·ì`êú´!2rXThHO›™«’•CĬýLô›º˜WÓòõ·É™â•¿GR²EMm½jÊ U®¡Vò°r¯\¹RÜ,.ÖÚ±¡þòé„çıóðiù^Ÿ­ÐvR1< xò1«Üâz–‰k>ÍN¡ƒ(**Š:Dœ£¡””úÓªU4((ˆu$º]i¢;Ðg»Ž¯¦Ì8¼%/Ä7w×ø”“p"ƒÎeÈ=pÌÐ *3ì .¤;wÒKK—Rï¿(õ¼×Æ~—D¶ï£k7o‘Ÿ|<Ü\å·îþ1‰³ ˆ+óÃË×K%yûðÏ(úÑáÀü’· ya0dç➢¶}Ç„¹ù£'õ÷õ–tŠ+õ<÷@™JÊ«)vßi:;øA6ÞÃ’N:•p©rðT:½·u/Êa§õ¥R>œ@NOŠ!H‚‚ 8’vñÞ2ó*×BŠ~d8MŒ‘Ô'=÷:½¾q}>KZ9€•ini6<°C=P7Ï•¯Kù7Ù€%52„fpÊÄÍÕ™ŠJ+诛¿¦=ÇRäéÈ¿¯·$áv[@ëôa=ЋÏõr`ýµœ²à-…þµ/‰ö'¥Ñý}%‹‡2][á|‹óñÑ”l*ºmb’îBÇS³iÛÞï%ðâ|Rw»^ç¶õ.Aª’¸ò¼ðäy¡Î¤¨{syŸî†’jй áÃáŽoF„]éÒÝ»!HÐ(\m ¼¤”Ã7Ô‘Î0*Šã[GòðM/^îLž‘NÑU1‰ XDwˆ°H«à¼Y¼çYˆ°ñT_£»"ìUœ¦íI± ßA­¨‘ƒeî´Ê\' [À¢ 8c%+ƒ¹ùÒÓÑèçË[G#b2<‚/“¹^~³E¼†9ËûªÌH<;s"1Äf}ôưZ]! Áб/?™‰k.õ#Ýhe‘;R”2‡…iFT½Æ{ÜÈ¡Ú8ÁúÓËó&Ó¹ìktø\6•T˜äjÜQb àÌ ®¦š B¯Å̦_M£ÉënÅ $:Û˜'È·Ìà„î#aÁtðL¥râ–¢ Bûd)+="$ˆ^}aÍŸ:VKs9r„iÙ²e(·‹‘Lª¿OË£WØK Òû*‚•‡™êÉHZ³x>-š7E¦Gúh×£yɓݰ0P¦7øk)¹×KäÿQUmy‡à•úãˆ1˜Im]ëyçÚØ}§Ä²ÿ-8ë.å}¹ç¸p°@¬þG¼vîÅ6®üÞÓ?ˆñN ¨’:Ó¢ajöü‹²û’ÓDv>þÑc)|ðÖÿV€­nuçÿcJŽªÚãžy¥3•òÕéÌ\‘t¡õC8£¶šYß«{õ.A*qÛY…ÒÿV -…Ò?ã·™Šƒçº¯ÃÎl©ú*¯B ᢢ"ñØca½’È5<¨žõwk=ùÝ‚ Åt ûnCSé©¿w¤¾3€rjR0ƒÌP4`Fi}Z^‰‰‘™{zM¯ŸªßH%wxcãÆ"((H 0mç%³ ÎõœÐwíõº]@ªpƒ¶%œºÄOXÔoT¸¶ý­úô¶•õìR Ã/­TIOOsæÌþþþ2ÕQUeIBô^»ÿ€•— ‚C•HTZZJœ&‘uÔ{ùâý±;H¥7{LcÇ OÏN+Jà]Ü{ ¤Ò žíÑQL °ÃÝèÌm±­"î7@hÒë [áÞ¿ÚO ïŸíí;òOž´¯=Ÿ}xíÚµ\WW×)9÷Zì&á&¡ÄJ\RRÂ/½ôûûû+¥%„Ø @ÜÜÜ @C‡åÍ›73¼‚õ]MíÚ#"TN#&½e]]]¨¾¾nQyy¹ŠYljÌ3“¹oµZ©¸¸XÍÁzMbÝìÜýn–¾³^u­=<êê¿‹õSiicX^Á%ÀÔ˜——ÇÆÆ²ÕZlˆª­³ï­zïF±Tg¨ÍÐj0¹ÿ†µ”Ÿ_ù!ÿcÏ1%+1í2oI8ɶە†ì;wrDD„HÌ˳gÏæóç/s’ÏgòS¿{—¿¾R Æ>>”ÊGÏd©pÅÂWGÈÍÑŸÂDÀY$TÄr÷ï£ôþŽDºœuÆD†©éMôÅ™,ʹn¥‰QÒc‘ƒiÎÓOÓôéÓiýºõ”p˜bc_¦˜˜ij~Þ7ßÒŸ·|FŸN¦šÚzr³Ø#º¼ª†>ML£ 9×)zÔ0:(XÍG¸¹:ùîiæÄ¹û¿v:ƒ–oÜN¯Ÿõð¥ñ$Öi‚Hô½=Ý ^8+¹”w“&=Fz'+гï~7N-0„7N¦çÐö„T ô÷%ï"¼û¨U.Zw7òòô “—ò麵LºÒŽ#'éTF.õë –·(­2‘A{83ùˆ<„í±sÙT+§"<߆è¬ è'PÊß×[%fë)€‚îÜô»"ÒƒeÝdo|$d|$üà³!4Ìqä£é-Fq– è…*G¡îª;, !rìª~Cƒ('-Ç ‰ðоÃ|³!°{<Ÿê…}OÚ ¤å|œ¥@Ì ðâÂéURVAžâ©ûúôá ÔËß›,bÎ*Ùìc¶²y½nàoKoSHPOµ¯Höíé«NÆ:i›_’z3÷¡…ÅP q]VY¥Ÿ:v½²è)9üÅ{ÌðÁàC '3)³ HÍíáÑ’•6„U øÿíühzáS©Ÿ@Ågî¤GhpH %žÎ¢›ÅåjOvP é`„ nµ•ÓC ØgchöäÑJp‘¤$ûöí#yÑQè}}iɬ¾têR}EJ쩊öîæ”]B„¥"ÍÍW]]ÅÛ·ïàQ£F|̆0óìÕ«¿ñÆ|-?ßQ•võ›WäTââ’Rž:uª!ÜÃÃïàŒëþÌ™3ÙVV¦ê Ô’æóÙsç8$$DÍA6l¡×aÜÌç5kÙµ³Õd3 ŽÐ7ÇÇshh¨¡¬¶ Ùáááüé§[—ýÒR¯xí5öññ1Ay lÚ´iŒ’ £dÑ{$« ˆ“ÎeüJm6~Mñóó3Áš¼r幬¬\ÍÅú÷wá__Q}ðÈÈ»aðÉȸÄóçÏoÆ|†Î[·m3æÝ”’áO›ö°õÎ^ÓzÚh@tas&3Ÿ¿ý oØuœ/›¹œ™ÉÏ<ó ûúúòsÏ-âìl»Âà›˜z§.{‹éáŸógÉç•(œ>KÞÝÊ’¦sQq™!þðá)‡G`` ¯^ýWTØkš:)¶>Ü•Èa?}‘ûE/ey «5íÒâ=‚óß×Ûƒää ¸}Vz$|=þh8 §øøxÊÏϧŠ1‰._½Nk6¤ÝGO©—h`O?r“ŒäéáNî:‘‘Gs¿¡ Q¡4qă=…&OžD(}ûõë§æ xzç_ûéÄŵ„³Ô| ™¯¹’Ñ^£ I­'D=@ã#Cki9} uŠ®Ò²JꉔÅÕBR1ÂÃJÜÑ„Qêëé@Jº¤é…ªnyxÈ@"=§€Þþøí9~Z¥:AbˆšºõBvH›¹–¤J)/j¢ÝIçéŒÔ âjÚr8…^ß°ä´¥@IUÜ1ÑÔŠà™ll•_ݲUPü‘4•Žè«ì¤Í¾”‚Ë[²å-2eÍ£=÷q\E,’¶ µ†­åÄQÙ©OHå‚ã’VûàƒA{ àƨñ ÂXG©…G ,š™b Òqð€V ãÈ‚‘§é1ÚA1<ÓÏ5/GOœÃ2=õ®÷@`}|t€¥Û“‰B(2eI)¨¢ªVµa]•æËð;Ö-­i„9ðpY2î¦v­1ó1€€„L ŸC~RáUTת¹mB¡„°¸%™òý}é£?,¦Ç¢ÂUøEB1c‡+T ð7{Y+¡ Q#ÆCÝó“Ñ¿j ùùz©µ­­ÑkÍ÷f{LñÁalÄ`õED¾9ÑWr¨JÒq³"†«XN¬øê/gÐoæM‘‚ËW ÏÎΦ°°0š9!JŽïûéHZ}-G0xàHÖH­ 1dPˆ¤úOÒüè±ú±SwÃ#æUØ(„ž”/"/ÌD?  ¡c7ÌCeXUYK?¡ O+~5K8zôÉyŠŒŒ¤¥K—RAA! îMÏOGÏÇŒ‘ 3@¼Œp³ï7[y¥ª<__<‹ŽÅ­P ð ^všda«$ÌŒzPgȇ45wïñÓ¼ÿË3ƺ̬l^¸p!¤7»‚‚‚x$UÕöºF 6>v6›¥äUyò;ùÒU;O0Ó5‘Á؉¬sWBŠ€«5²I¶êÍ7UÞÏÆ7_sB8bÄþÏž=­±PcЖŒ69<¸'=¹„á/¤ØWóòxذa†ÜÝݶö €yzzãøã§VªMý·<¤«L-§£÷v1 ”¿ÉÉÉI:;YH„‘E–hgØDà Œ<˜O•A@uä{:òŠ" ÌSð½a‘egX¶„E0$$,$l²ïPïüÕÔM¥m:Kw‡ð½éÜê{ëÖ9õŸSË9§ZÁDµTe\«ü¦_¼sçáó0’éA ã¿{÷.¹¹¹I1ðW×¡× Aó@$H%%%äââ"Á‹ŒŒ¤U«VÉïÖˆ:± ÕJ œÁ/%%EŒ7N0@K<ûì³âðáÃÆóââbÁj|¯‰hºZˆ­JàÊÏϳfÍõêÕ“À@ƲÌ(Þxã ‘œœlÈ¥ƒnܬ!§ Òøé§ŸD»ví$X°:“Éd”¢²Æàà`ñå—_J°•®€‚éêÃïøñãbàÀXN õ*À芔«ïúê4x©©©b„ †¥aˆâ£f­ pu þÉ“'%^ªí ø;@X :¹{÷nQ§N Àбšµ{ÛÃÃÃs'Ú®)–èÑ!Ý*Toß¾-¾ýö[b  k`YÞxj˜ˆI“&‰¤¤$ ^ɽIY¡Î_Ý«Ž«Ý–”˜WV[ÂfffŠO?ýÔ°F€bkã¹ôðáÃEBB‚-òÙ©Èr«9´B•Ô- 5-S\½yÛ,-3WäæÊïØË):{ö¬1bDkTëCYæÝºu;wîT¯‹‚Bs›¸qæÒÕÒûEÅâÆílãû;Õ·w¬4€Ð²åe›ö‹fƒ&ˆ4Oðèő؋â“E›Äñ„Ò½\QQ‘ÑÁ]»v‰îÝ»—R·¸&Mšˆ… ÓB¡öntìÑóõibì´EF{Y¹ùbòâÍb}ä)‘sOqxùœMö…Yö[»^ìý± ¶çXÍX²‘Çœg×ë.y{¸³™ÉÝäFiYyôÃöhŠŠ»DžjK7 –‹Ù…ëÓ§õîÝ›/^LÓ¦M#Þ4ËgÞÞÞôî»ïÒĉ)((ˆXQäʼ<ÜÝ)%5f}¿…VGDQjZuirÉ:ÐFÄÑxúåÂUêÞšºþ¶™ùþ=—­Û¨ïÈB…@ÎÍÍ…Î%_§™K7ÑÚ=GÙz‰‚êÐíì©ú7›V½Ùÿ?oÚ æ/7++±ZÁ%øYNarDzT7Ù ‰÷‡ð,2xhIy¼ÆpÁ¼æ(’À1HÙÙ¹T¢íÁ[¤"þ€Ÿã8–/y•TIËÌ!_/Oúê½Wè©v-åŠ ÐÚ6kHÿÉÛXEnA‘±Ê–/ŽõhÊÊÎËgO#ŸÆ íCï¿2P*ˆÃXäÍψg:QÃ`®SHr¨â¬Ke¾ks¶|ÃÒ…5 ¯Äƒ·"c†ô¢^D{þòÞñâÍ/üßðÖMh{ôú™÷_Ö‹7±¸ò¿ ,‰ƒ ÒË+(¤§;„ÐG£Ÿ§^áfw ”‰íUû(´iŠÖ€Þõ9úÓÀßËö•»ð ÉÓÓS‚äÆÊíBO„´óU ÔÛÔó {÷î<ÇÙìˆê®è¤žãèß¿¿ˆf0)kTß-¯W®\o½õ–¡ eq:˲®8(ÊV¤÷Eݳ÷j@•ßEBûÅ_42iéˆÞ1}˜!Ç;jÔ(9ÌxR&¿ @Á3--ML™2E4hÐÀP–ŒÞ¶µ²¥âœÚ°aƒ}:ñy@â•[ºP˜®<ÙýJà¬ÞkSÒ°‰_Óñ3És¼hK'_Ε ‚óãÞ4wÍ^ŠãŒšª·0<<œ¶lÙB|fxS  —_~YÊðÙgŸB’À‘#Î){éìì.—•Þ¢9–M†¨¼¼MÚ|Ê ‰b/^§[R¯Ž­“ÌíúûûÓÔ©S‰Ï½pNÖDl‘Ü1’Ï@ºÍñ»¹œ,Z´nepÙ6'n¤gJt¶<²9ÒãJ&òòÍ Z´é …µøŒî \…† :t(ñ¾’Øë ¢ øæž2i…„Ø—ßo¦ØÄËìûð_ÉG’M#„ƒ iX#BG[–µ~CeÈ õ9iݺµ| séÆŸå[Ðì¶ÐY>Ñ€œr]_sPÀåþøà‡ìèÔùË”œJÝÛ7§g8· +eÏ‚^¾<^ädØ àE>OÓ¿ÛH»ÆJ«·'+™—ó§Bª6`<çÈÜ.ŸÀ¢åÛpö%‰þ£k[jöh°Õ'uŠä\òôÅë)òd‚<â!;ÂåùU5Wî ‚pD¼wrˆêÔ¹ËÔ·S(u mÂÃCýÎÄ•’¯§Éäÿ?·¢"DdXQ‚ŸCá 'E³¨RJIø:ƒ˜Žgœç\î¼oÐ;:jÞ¨ž¬ÂÁòþߥàì †¿êˆj£2Wð!—œÍóÚ÷Û¢ä\<øéö Œ+±MCþòw:}þŠÌa#[EUF˺6ËÊúwX†¶ ‹îåóIE˜ó`©HŽßï쌪[™«R¤݃À‡£GÄz8áÀÂ8zž³%c•TDž…Ãê ÇÍâðAôY@Ä´eU7Ù  5©VkOsϲ}5_:¦õŠ·b@h–ÿ9Ìí—e€{Î$ki{øÙyVŽ%8%Eˆ} Ú/ÐæNÌqÎÊí"Rs§= éïZPA3>–ëÇÇÑÀ÷ôyNo¤2eu¾/•7ÑSXËÆrâǰ¨ãMM 2çvLGX dO¤b¡ ÞÌ)QË) 2}ÐëZÝÆ`A‡–¿¡Æõërn7ŽE¦°wïåvÍ]½¡òÊÿÁÁ6cüûÒ_^HHï2€þØ‹Ä$Òž ”Îu±ÊµX•ÇG=‡ÂÝ\ÝùdF.ùã1C¨{X+¹9ÂÀË*€x€™såÞ·=Õ¶m='Ï<Ë= çwÕþ õïGP†ON~Ün èF¾öz2´™|^¼–RÔ“]EÍÅÆùRç„<àYQ«Á.[›ô¬, mÖˆ“ÿiÄ€î’dv„e+yuÉÕ=ã*-‘A„àØ$¿=´O’§á¯§eÉN¹²°÷#t$¯¸ˆ;’CCšÒ_G ¦ç{†ËêÊoÅöƒÃí„õøñãåv„­|&Ú“†öìȇӛÒ6NÊÃÇÖÅÛ‹O܇!ËJg/ Ç'±Åýù…~äÏ–­¶?»ÏÛU»m@4 •5b"ìÚ”Ú7oÄÇ'ÎÑþSç³/üÈ tï¥eäÐ#Aþôá¨?иa}äÐEDÅñð[ccciòäÉ2²‚—9ŽGˆ¨p¸J¶…º˜B^ü4ûÃWh¹r+Ã|öEgȵ¡,œÿüRÿnRY-7íÀ+Á<™N¬™J¢ÉŠðë ;¢e /æBiü‡­…{—WÅÍY.R®§Éêˆj«|ó­[·ÿDxyyÁ¸e`Y”ñáH‹ˆ‰)Í «¤:¯Ð2ÿþ7kŲ­G”"-3[4ìÿ¶è=nºØ{<θïŒ¾Ñø½L»J¤{ñš¸|£ô§^GcËtDåxÄ\°`hܸ±–MÖ£Ì÷ƒ>„ ¯J-ÜdÅq„Æ›ˆÕGŒ*ò8º|FE'ª d ¶"»°E8vãÊÊ`q<¤Œïê>®:¨{þüùx DÕ®åàU'Ù ÚÖF¶UeÜðCŽ@œû§ƒˆ:ú°Fn—0ɶ¢¥…8]%›³¯ÐRH• Â/-¼pe¨òÊÖ||ÍPÎÚÀêÁ£&SDÇÐIœ¤Ú¸q£àco¶†®%˜úPnÔ¨‘˜7ožœË›:ªX§¨w‰ô¹s犆 @êàX§/&°\þ§¸~ýºÞd);@}¨ü( @ÓÂwËyoРA‚3~XP„­E˨X§ˆ¾ Óè¼"€2xðà2Ö¨æJÙ¾}{±víZU]Îw5 8%\µ¨˜Ý"×­[' ÕÙ™‚óɹÚVó¶DÉZÑ« *²Ö«•Hɇ0á´~/Œ\#9Ï‹…|ÆàI¿¸Z«³ ’ÓH¸`y>TÕjôõd0”E4€÷0ÑðaËš¬—º­õàß«ÐNÔX  Øùz­Öh'v¾^kµÚ‰€¯×Z`-€v"`çëµX  Øùúÿ{Yzˆ“òôIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/64.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000762015232633614033153 0ustar runnerrunner‰PNG  IHDR@@ªiqÞsRGB®ÎéDeXIfMM*‡i  @ @FQB°úIDATxíZ tÎW¿dˆ”Ô–V‰ J¬ajÔRë NËGZj:SÔK©mLKËÔ(δ–Úªµ´ uD )­(!vEB± ÙW‘Äû{éûûñ%¾|I8§ÇÍùòÞ÷þïÝwïïÝ{ß{÷ÿU`!z „ið©X±âc˜Íö)‹4÷ïß§ *(åóóó¶‹X¾=ˬ8Ö«~åÊrppP`äå啯f6r/ 8ĪCለêÔ©5nܘ&NœH‰‰‰äèè¨D@O”DØ2%QÜàÇÇGŒ±øÔ®]›—,Y¢¼ê‹1ºn ~Løc™‘øºâ•™™É³gÏæªU«*ÅÅX,QÊÊ`´mÛ–ÃÂÂŒùŸe 4Ù¸q#7jÔÈPж ˆn8p Ÿ?^¡A4P)çJ©€ÀX¹„„îÚµ«¡¬“““Zq­¤µR‚#£Ÿ~6þ|ÖüÊYoƒ½]A0_¶5á r“ tòŸ*UªD£G¦:¨öÜÜ\#⫆Bÿô΀~...4räHêÞ½»ì[¦îŽyô\º­LK *¢¸Z¡âºb—/_Î~~~ÆÊšÝ pèÕ«9rÄ*Ë‚ˆRðs—ÙäP*/¯ bCˆÿíŠäëvò숌âS±×ï¨ÈVÇ“'OfwwwÌÝ›4i›6m²“•Ã3—m柟Qí)Y¼iÏq¾“’aô+k  €YñS®rð?35ÄŸµÂjÙÖý[³VoßGwT/ÏJTQ4IJËT§&Ýó ÝC€HHͤovDÒ¡¨ËÔ#(€žó­¦»Ù]>€Væç£ÑôÉŠ-tðԙ܅|¼<)OŽ­ˆÒE„Åbx¸»PJF6­ ;¢„í)ÂúÕ¨ªV,ç^}#JK ¡ë·“©ªX“‹‡S_ÓÊ›çÔàíäè@Îò9w5žboÜ¡6ü¨k«eaÜUw{ Áb„ò¥)YVa؇KépT,=Sµ29‰‰Cy[ Â:ÊÀÃÝ™b®Ý¦5;Ó=ÎÙɉ~:Eïý{¥gÝP+«Õ†¥ÙBfïæì¤ÀØuäí<­@Ç3{è! LâêâDùn¢øƒ=¿$(aE/ëèXQ\¤`t¾€ãéá.`¨y¶ƒjžòÁ-Ü%f”–,,À̬@ÛVÆ<®pÂjåñ fŠ·wÅÌüÁ»´T$Å1F€,ìoX‘Òܼ̈́6|Ê‹,g{Ä,Jq&==“òL~ ŸÏ’H^ae»Í—HÍÈ2¶5¨“›G÷äS±"6¼²'›€b0=+[öälúëë]hì ž"pžJ|`K xNÎ÷k£´ÔÄÔ r“¸3oÜjßÌ_øäÊwGܵÕô©BéÙ9$gQDYÂ`5ê `yˆæYwsÔçåæ iÊÛ}©c‹uUúV󤡽‚(:î–:ÄÝJ"Žœœß"âœr5M¶Kloo÷éHÞìMu}},x7©W“üëT§ý§.ÒÏÇÏ‹…d+ ÊÂå0Q‘à+¿“œFõëÔ ÷ƒ{Ñž0ò{r¥%KËMΕ$룄nôœ/5¨ó <G»ž“CM–D{±µV0 €ŠÃO¦Û¹uMÖ—‚šÖ×](>>^x/¡nݺQ»víÔŽÑ©…?6¨M?ÊÖw(:N¹‹r‹ÒƉÆéóµ(ÍÕ_Á5ºä—nâÄÔt£*Èâ!«OÇŽyïÞ½}pŽß¼÷$ÿâ{žº4„3å¢Ú¸ëÓKop›7§óú°ƒÒ"±ü7º›“à ,`___Å·Èwß}—¯^»¦»¨2îf"/ݲÿ6gº Qv‹>¶~ÁvdàfB ˜½’£.ZÞð¢Ïžedo´â¸Ý™¯ºC‡å‹/üP¹ŸÄßî:ÂrðQíÛ÷ài 7°Ä‹~[·nåÀÀ@ Þz\ æÎËÙÙ<ôÀƒg.qèÁ‚›£–]?³µ´@’ã®®ª2))™§NÊ’ôPâj‹ H Tß½¼¼øã?æôtK«ÑZrf>yò$÷ë×Ï*/ð7_¡›6mÊ›7o¶­´_¬¦ÈÔâNÿå—_rýúõ-ÔŠ.ÍÖÀ_ý5§¤¤Xf|ÅTssó8&&†Çg‘/0ƒjæ pÍ@ôéÓG¹\ޏŒÖ^ ¬ ç~%txx8{zz*塜Y³€æ:úhE`º‘‘‘¬ùi`‘Cœ9s¦ª³³³1ÆÌË\è§Ûzôè¡ÀÅB•«˜ÑD²süøñ,y;5yaó×™ÛÝÜÜxÊ”)œœœlfõPýرc E4€§]I·¡4[–¿C^¿~ýC¼ìm° 2/Éi–øjß¾} aµßC`³€Èþœ9S˜´PWãYIêkJz–‘ÙÑÏ%ab5•®çUªTQV“V(¶\¼~[³±«´@ï$r—ç¾Ú®"¬\s áæÍ›@è•jݺ5‡††ênªLIËäéK6rË!ÓŠƒ"£âø£•ÛùW•C|õË”jÕª=Äû­·ÞâØØX5^ÿCz®×è9<|Æ2Õ7³‡¬€-kÚ²­<…ZsÓ7&qÆoÛౘ«<ò³ïxìç›xiÈ~µMš¿|ù2¿óÎ;Êß%ÅÎá…Îñ‰©<éóï¸V÷˜ñ¨OW©áöP£e¡†ƒUzVýçÛ]tOÎúùy÷%Í•O ëÖ mèùg½uwºqã†ÊýרQÃhÛwâÍZBáÇ¢%'è¢N}¾ÞžôËòé’ q%@ÒZ‡TŠ+3ûž—Ô=¢K«†T¥’›Á'æÜ9jàïoÜeç U?üBóÖ…ÒeÉyK2§à^/Ó†ª+vᛤÁ¬˜J‘GaŒÁ-çtsõ6Å^O Ö’†ê&¹¾ª•ݨfÍšëK"Ô§«¶Ò†]‘*½å]ÅC¬‹Hâ‰*ŽRæàË8…Ÿ¸@âÔ¹ECj×äyr’c¸ÆÆ#O ¨[(òt¬J·!='Y†bÓsÆàGTŠc!,Af“Fœ¾H'/\§×;6SgsôY½}?MY¸A­ˆ—d{$0ªLÊâʃùͺ›K›ÂÓá³—iH·6äSÅ]n„ù4vÞZ¡²J>^²Òòê],w•² ›¹@XÈ[Yži™w)úr¼ºÉöG¡'×YäÑÏÖŸVÖààPAx»Òʼnt+)U¹.KÛ÷Ÿ wIÊz¸ÛŸžÓóX+m@†°Ž",®»šàÛpäí%€ ÞÈ"÷‚yJ\(pûy'S‘g¾Ö;•àæï…'4ßÝáÅy†v9Í£8k‚ƒ™yë1%)­‘ž*m "2#S¤‚•È.YêÌøŠ˜ŠwI.Ü÷!ÀI ßj•Iîðv§¡ô@./)-ƒêÕVïäÌNÞò/N2d«…%”tÑ.‚-²6y¯Éì' ÌÊUÞóè×A"} Ôˆ{j[„ÕÑ9!%M^|xТIÃhÝ'#ÕL¼ÎzP jü¼XÙ}Ê–mÒ–Ìd¨9Ò·m“úöÅ4fpe]öœ ÔƒH¦T|ðA /8 ÒPgåWåˆùV’—¢Ö─‰ò"AqÌàž4V„{F^vj’7Â$¯Ë• ìÚ’ÚøQ¨¼GŒ¹r[Qo°â‰éiä_÷Yš€ôœ€@p-kòXãc­Í wÀ–VÅÃú¿Hï½Þ‘ùÕPéodƒÍÖųÄJÒÄ,ÿüǶpÍõCyÉQpp°ú™ÜÂ… U&sÕ«éC#ÅÒ‚»·¡jòÒ5C\g ­v¸,kòÐ>¾tšRq .¥û–Ýæï‚`±$È[äÛNœ¿ÆÿZ±å-­1nÀÿåf'ñŽˆ“F*iii=<<Ôê‹¢%<ÍÉÕfÍšñ–-[ÊR„ñ²ËŠšZMH{<Øp˜»9"“„_†"»‚©—·¹kÙÌe™Æ*&˜Òc»wïæöíÛ@`õGÅ’M2ä0g4>¦J™ åÆjš[¼x1÷ïߟ=ª»¨<¢¦Fãc®XäË#Ø*¹aæ67ÍÏw½Ü€B²¨êØŠ:”.÷ÈŽ‰l¤Ç€²<‘nå¼É>J4éSJ×ï°óS ø.j‰Tzj%‚ëwØù©üµD*ý½­sÔ¹ËÄ)IEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/29.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000315415232633614033151 0ustar runnerrunner‰PNG  IHDRV“gsRGB®ÎéDeXIfMM*‡i   Þ{QÖIDATH ÅVkLTG>ûb×e]Û›+ÐTKSi±&Fk‹i›Z¥¦6”j!ö•šˆh¶¶bLˆÒj5F£ØX ÑU0¦€F1ŠÑÂ"kQYÀ]Ø÷ëî½{zfè½EDýÑ“ÌÞ{gΜïÌÌù¾’Á],‹qµZ­xŠ¢T*•Ò7Ú—ÿ¢Œ0ƒ±VSSÅÅÅ`³Ù@«ÕÞ ‡a+l±¢D?´B¤¡ÕjÅE‹±áÍh4bII vwwóqæÇÚh ;J’t[WKs3&&&q0ÚN4 øŒY ø‘ùœÑ‚+ |UÿJR Û:ìE°§×ƒ—ÛZqáÂ… ˜^oÀÒÕ%èîsbË•äÆî^¯’,›?’) ²Ó©‹—1kéüxývôè—`Ã_í|¸æˆ‹Š>ÀëíWÐpùÛ1³`†…(þ¸«wXNc¯‡V~ÓÒ8?[§Ûk*÷þcàèõ@Ö´4*DE öÔ6B}Ó%X{6,¥$ÙQ¿Z™Ó·ú ndOâÇÂÉéòÂŒgRaç×Ë) &¥ýbrøÀªbïÁ°€UÇÏ¡¥ÑжŽ.œóÑz¼pµ ªÖ5¥«1##wïÚɧ]¼æÀÍO I&¾þÅ&¬Ü|p¸!¿Y6ŠÉ•Ì:H¸1Hmn·wü¶'O~L¡eŽÙÙÙX{ÔB>!.Å@æ½xÐËm lŒ1H¾ª°ïÖV+¦¤¤*€:R(ÊZÞüùèõxE û Èfow€t•‰Ížååå8a–™™‰‹Eqe@£“'ŒÊœd`ön·ÛqïÞ½ü2ƾï¶Ìg(S±Î;ªkPs!p~Ï•‡ð¶o¹4ÏQÊdpv¾ŸK¶çž@åIúTéAÝËüÿô\öEÃRÿIEND®B`‚././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/16.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconse0000644000175100017510000000145315232633614033151 0ustar runnerrunner‰PNG  IHDRóÿasRGB®ÎéDeXIfMM*‡i   4Uqò•IDAT8R]HSa~Ž;nM·©G÷ã\δdHÔ…?¥‰eAå…´+#ˆ ê*"è&$(C¼ˆ¢DMéÊÚMZš8k­Zù®mêÜg_ß÷¹³¦ ôÂ9ï÷ó¾Ïû½Ïó‚$-A½,³ÿº¹ÝnøF–e’øw¥„pö—ÓnW–—ˆÓé$¢(³¥<ë|šJH¤Å)‡"!@† ¾&câûtZ l6LÆ”í*F\PÃýs’A³dÀfê¸w -·ÁQº 5ûñgUFM™ cÞÜêxÖ3uD°äàTu4™"ÇhaZ\@ÏÐ'¸zßÁb2"× Çó÷˜ Åð «Ÿ]#Øa+€>×8ü¡U°Å8”¨Ê€ój3*íyØ]ÄŦïF°ÓfFÓˈ,xqÐQ.²¼¦ä®{ư?$m7®Q6h!úÝl»N"ÑùâñÆ£õü¬Ðl"ý½„rEÕ’‰Èž DZ§bª«*¡Õ¨QTâÀèW²µjT×ï÷4êja>,`~1«1©Ç[áã?fáKxÜýß ZÛ;q6ªA¡Õ ãÞzôœ¿€®Á¸ò°}å»Qd’@¹§TAÖˆ>K‹Q÷7Œz¦ÑÝï¤ë#ÊK‹!åèñfh¿‚¸ÿä‚K!.3ëI1.c,.cpx™*†F& å`†« Kê|è(Õ/Þâܱ*Ôpð§³Ùá–bƒ.¢±™›'§OžHzïn;Y G6—žÃedÓHHjQD¾”‡æ–K.‡a·ÛÑÐxYt:itä¡Êà]+@`h©Ý ’><éaá’7TçõŠI¿U2 ÿ¯¤Wܼþ 2…™mlÌñIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/appiconset/appiconset.qbs0000644000175100017510000000043515232633614026727 0ustar runnerrunnerCppApplication { Depends { name: "ib" } Depends { name: "bundle" } property bool isShallow: { console.info("bundle.isShallow: " + bundle.isShallow); return bundle.isShallow; } files: ["main.c", "AppIconSet.xcassets"] ib.appIconName: "AppIcon" } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/0000755000175100017510000000000015232633614026447 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/main.c0000644000175100017510000000236415232633614027544 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/0000755000175100017510000000000015232633614033036 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset/qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/o0000755000175100017510000000000015232633614033215 5ustar runnerrunner././@LongLink0000644000000000000000000000020400000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/o0000644000175100017510000000123115232633614033214 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚././@LongLink0000644000000000000000000000020100000000000011574 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset/icon_16x16.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/o0000644000175100017510000000121115232633614033212 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚././@LongLink0000644000000000000000000000020000000000000011573 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset/Contents.jsonqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/o0000644000175100017510000000053315232633614033220 0ustar runnerrunner{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/multiple-asset-catalogs.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/multiple-asset-catalogs.0000644000175100017510000000022615232633614033213 0ustar runnerrunnerCppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/0000755000175100017510000000000015232633614033037 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset/qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/o0000755000175100017510000000000015232633614033216 5ustar runnerrunner././@LongLink0000644000000000000000000000020400000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/o0000644000175100017510000000123115232633614033215 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚././@LongLink0000644000000000000000000000020100000000000011574 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset/icon_16x16.pngqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/o0000644000175100017510000000121115232633614033213 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚././@LongLink0000644000000000000000000000020000000000000011573 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset/Contents.jsonqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/o0000644000175100017510000000053315232633614033221 0ustar runnerrunner{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/0000755000175100017510000000000015232633614023160 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns0000644000175100017510000524214315232633614025154 0ustar runnerrunnericnsDcTOC hic08Ðaic10 Ègic13Ðaic096/ic12›ic079êil32Šl8mkic11 Þis32os8mkic146/ic08Ða‰PNG  IHDRÓ?1 AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ@IDATxlÝÛ¶m[Q¬a@DQÄ…÷$ä– @»¢<°¿ÚþÞcÖ5¦YÊN¢FFFfm½>æš,Ü_þ×ý×?ýéO_úÒ—¾üå/ÿÙŸýÙÿþïÿ:~å+_ •D¤#PDbÄÿ÷k‘>kGb-;&ˆ—E<Á¬±Ål›ŒLùÕ¯~ó?ÿó?²Þ‰»Á=ñ>â+Õ˜m]Ü”š…l…öJ?ÿó?ïHlC9^n7$PÉ#²Êß±®MIŸF5ÛdZf›S`ä@Õ˜Fâ'¦¥U‰á¦¨>ÝçiÃÿõ_ÿÕ2r|z`]i0‚lj]H¥í°ã|²2´Þ#åxdþYÉJ¬äaÇz1ÂÄîÈ–ì8üà?P¨3 k#Ñ@‹ÖY Yd“"åÝ!Ï–V,ÑqOßImÂ+ŽB¯¬ã(ý<į´^<Œ]°]KÆ áÚa?Q²#gYÔ¤?FÏz*ÍI 2l Ðó¹mo²¹ÚS #/2™ >»¾°®¶]»RëÉ‘€È¶ªc%&{••hº©jÌi~¾/ú|/ ‰iäÚ,òéxý˜¥¬$;–›Õu <³ÅhÙãJ€Ü2L#‹Ó¶2•®Í¤À£?î]ö‰âo‡ÄrzÙSö¼*µÊd÷Ù9À³ ³*(]~Ó}?Yl]‰ÓDêðºð¢Û!g¢ŠÇÈáÖ^ËJª­Ñožx e›l%&â6Ñ.b4ž…žèóU #¦.Y‹À¬±cz¼#ÙGýÄíÅTøÈÚ‘yâóÁJøJr&•ä@ž.âQLà!gBƒ„3 |£[&™RžôÄ—#ù;ªš0: ¸€µÐŸO‹¨Íìú´¼>þLI‘5`:‘ŽÞoŸÍÄÓ[Â0ÎÙÆc1Pä)k‘‘”#jíwßù ëA‹z»Q4€¡²è´ÆÃ‹ËHÜùÀAyûÀóe-=<Ù£K#{†Ú)‹&Â@'v¤,ÃiÚª®ôø4F×È$ã;ŽÉ“2 »H¸)ô@žø5jùãÿ(÷Vô(ÄHâÆ!¼ÄõûRJéñ»i²¦Ëø4·!Æ1¦a¤ ÏgP9Çšs!ʱžd¶tt+Ù©„T…§É§+µ}™g-;fèØ8ÙZ½(µgN ôx׋Jò‡.¢q)Ó?•O%½x$†ÿÜWÂw”{@#*•‰Ü8Êž3¥‡&’9а¯ 2nŽ¢F“¾[çœ2>Í2@³Ý‹‰€…‰0 üÐ÷Op+c íRŽ¢MŒYÉ6ÝÏÍJ=“Ƨ¯„ L™çª5ÚR©'ðÂD¡K®å!Ž$ð¹Än :Ç©áŽc“ã3>Ʊg¤Ý~X )×xj8òÀcͰ{>Å×ëÈŒ@{âùªµGnP¨Vò’aˬØÂªÓðB·¡Ue-M”ÃHÑ-²Ú Ø”ºš ›•ŒÏ<){ždx‚rGRFb"µ ÀªòžjKbXKƒÒ;™§l¥p;4}³"u äôøJõªô¨NŠ”ã•j”EŸõÚiŽôOý| "F^tG2‚ó‡fúôžÄ— >RgÃtù´º#Y9=MoUü®‘FŸÀ3~{ˆ›•Rnçz7:sEL(UÀœ¦{5înɳì²Aµ Xh7‚Ìíž²7U5fV@!«Ë&ùÙëõåJISc#00¢Ñ+uG ÀJÖNvzÞ#”0a¹jzÇÜÚ[’`Ëk™>²¾ÒÔ^‰’¬Kä¿)ñ)ïÌg-@7ªËãÅX/¼@öj²láÈ!|÷jÐWþð‡?(¼ÏßNÖŒ©¡æÛN©IÇòùxÌ ÈDvì¡è­]&˜&ò¬öDǪÂ*7ß1Þ-Y˜ h€fHi+Qo#d‘ÉZ0ð¬<)Çl$Óä¬WUŽiCLwÇ“‰d‘å1MAb„£mex$ŒŒ™(«&㵎6´Ì>šSmÖi{ÏêÑE/;¶I¶å·KV©Fæºz†µÇÓ¬V’‰}F{’í¦ øS¢ì b>YËvh´#™^GÀy~F?žÏÒ1²a3Ò`¹šiÚfÃTuÙø6¬…˜‰,v½j ˜¬x´çí Û¤5šÞДñòvÎD.È2§É6°j#ä"Ô˜œ»ÚZVÅÀeÊnãØ\G˜F~9ÿéCp+ÓT‚UÅ£=†ý’dë˜&°j]ÍBô^…µ^ < $(e sßÐfaD¯° µèÂÀ²§Çhþô?ôknÇde½í“3Ãð”ùŽwÄÈz-CV»Þפ¦ ‹|g×Ñ}|ÍóTëÂôS˜¾1Zƒ'[U ·l¢¶"È¿FX‹èHŸ8ÞQɺ*É·y2™€RÕnu1Ôˆ¬×±FYlbsã7¯ÑQ.RzDF›"L½d|TUë*#²–fŬ% %2®kx `¨ ¬E¬%G‘ÌhѪ< &ÈZ -p] îAÞ-øô·§Þ¬ò̇,pV|Þ½m¥ÇÃ@¶ÓwÄOiXqÜjî¶jmæ¸jŒèò. ÚJ€R³e¥LrPrìuìÛ¢‰ª‘€?Pù}°êÍ`KÖÜ@ãháJ@UVJ{« xbjI&Û'F¦.5Ã]2Á‰›˜+ŒÛeŽì90lÕ|â³Ê¤'ÉM`ôŸ3ªø6nhâ0AÆ€‡ÉêJ/·CdʧfSú $5XÔÙBkö…=/d<±‘OÓydñaÀ7©J†‘Š4·¯LC ãad&˜/òqT*OýÓŸší[õzÛãijL +É"܆€À´ ”Cß^Jò.Õñv£Çëq 9TÕŠdå¹ |‘R& ã›%´mL0}Lƒï» ÛÈ'=’C-ô}uÎ9qdžk×;“Z6ëö_o†L€²®$×wN&ŸwqÒØ^DX©þmOéÏŽ‚ *ÐÍËJxd Á…kãÅÈ4>E@î¡'H³Œä`FØX×#]5–•2|èOïžSU%0‰ì.‘rß­DÚÓ×%= «z-Xãð‡#žX—)õbš‚gUc²0åùGÉj= M• ÎN¿è3Í~èó¶¹I—ñÈTE³“9rë)Äg…¼J¬Ô~ª hDÌ]M¿Í7Ñ?±ô@[ Ý´7‚ ÏÒïŸÀ™71g홫x-áJÝ(=>C—Ši¼GAÓ [2™.³G‘aæ˜567CUÇ Í°Ñ° Û2âHUL½öõCŽÉó^^#±ØtXWn³ª×ш­¡7¥Œ¼§ÇgâÃuÜ@ãÆÕÛÐÈVª…gVÍê=‰œ ÝF“þð‡9) rÙ5ªÊ˜Œ€ûE×UI5±0~íJd‘Rî&eUz½zz8%CŽjÃ܈{dªÄÞ¡ûAÓz&”&ú€Í¥l(MǶ}<ÎæÀµ/ß2;ä@0«zÝÇVuž¦c¶eGì'$’ŒóVD]M¬š§×$˜ù6líår%Cíý|æÀ™  q9l½zå6Qª1óô0Ix<½´ô¬T9w”'CÂŽ× ,·FÇ9gr÷ªžN¡0 ÐßÑâˆÞ_Õ0†E2S'î]Ìdzú´7^¾I¼¡{ÿ€<ËëÚ•ŒhI°à&€Z$[É{ÓQo&«”˜üñŽ ¼F;–‘™Oå•ê­„ Ô~ŒñÏî¯o¸².¹õ²Û5#ðÌGx9R 8ölÓq g’Ì*âR:R’ ‚b³T+Gbz7}ÿ*ͦÐÓ8Æ8úÔ`ʇ{ñ«æ¯…À3z’øZb³dŒcþð)áÏ?yäË"©¶÷ÔijðÓFIÃOS{@#ðûßÿ¾¿Ñtù^¾º4Šu!ÉdnBInVz½HØŸû[òô?A‰ÍMö*<&0gh碣ªcƒ`ng‰ç‡¡Ï8A¶YÑ;¦Œ—óÔ¦tkxí€hPkI¯±#Y )Ï ¾?Ú“Á;æÐ>™g›æÞ$ >YþáJri2¡¹Ž¾Í^ÜkhÉó±o%¥x½Ù: OÏ›Ö8Ùr%þu-¯ñ.ÁZDû”9Äh©ëüA?öÙÿüsOdž¥“{ ­Õºû„¸/8ˆÆi$Ëœ°Ï¯Ñiâa ¡µä#gRéÞm†r^{;ë²p¸^y‰³j Ì¡PÒ(2ìvµ;’Õ+kÇËIJpŒ—s9+|%âB‰l-^®Ež,œ›B +Å”#,O€„SÊðýb´õŽ”ϰ÷£xèóßK›ÎCCÿh_(«zkÄœ§ðþÐçàÉà÷´›ž§jǧû$J™r‚Fà1‚ùü)U•ΖýøÖOÌÆ8z4®3\5™l€l‰@ÇäFÀ uUµI7Ÿ‰Þ}[hÉYho¾Ïÿ¸ž”XûH¶¯ È•Föø¬aüa²Y«ÖÞÂ1=€ÜPÇFáHXI/ýS<)Cþ™L`ÕĬ­TTÊ¡çF Sõ6\ P•ý'H#'¨jbGÁÓ1Ž‘w 8AÓ‹|º”õVMOÖs¸Í‘oDÈQµ)i`½ËÍ-GžûÏ™¨†{Ò½^¹×6­cÏÈJW&]!^©.d‹Éê’+µäVl Müä8êUÚОƒý[,7šd­4¬ZØ¿«=Â×—¨’c‚Å0q”Ûœ¦j¯E¤ên—ìfتz{˜ø]$ ¯w –Ï?Ù­¤‘sè±9ûh'`¨$ÂHÙCk(¦Qæ€Ñ§)µËh§Âéåöì c>L¯Ï![¸8ë.jN¡W­¹*Œo¡p;ÁµlLLʬzRd÷ýéMGÊn’y äŸ!A‘`ùç HÙµ7š@‰¦ŒQš3Ûp%Uí‚Æ«lÃe]JpY—0"gÀq 4ÓðGýŽHV¸U™·ölU‘™ëª±zJ"M`XïS|}”fÕŽ×ë(’àï ¾’œ3ü<Ÿú§dnú“õ¸Êí  #zsD$A&1X‰,ž¾Woí²ó§oÇΤ\v“:«Â5“Åp%’IÇ||U‰HkµYæx]rèèAÐÔN†,À™8Æ$¨1¼v†°Y2q|£ËUu9úÚvŒÑ8Ùœ9 E×ÑØ`‘IGz±àÊ|z>”˜œéË5†É´¤Áúà`šF`æ–¿ê6dáæº4â—ã1íÓQ·-ºð=¢ª¨÷¶¥\XžÀÏa2|é3Ì-¬ªÔ‡‚É'ññ…* ýõ?€p uNºa^‚«R¹IxæϱñJŽá9!Ròðr| ½€}×ÊE]SÔ‹'Ç:[¥ü1yæ37bTj=2-µ÷FÚAi–úThjlnKnI):Êl“±ê— ÃLÈ”tõôÇvƒãsM8ò1> ÆO ]PUäœ,M*OØÐZns‘µlVWèH“­œl]ÓÇL ˆ™4˜m̪Ž3lVG Å–ïÑEö`wÌs-ŽçU;ÿñ¼s¤¢‘²ð9eêÓb‘24£öŽr2 °×EÆóŸ¸…w EÿÂ)>>”¬0°Ì§ª®1k<÷yªs „‰c(¹ÝSyöÒãýÝ+MæëÂÓÜV™´€,òi“•ªÊÂ>§íŸ·÷Üš+t íý¬ÖU愇 r Ë6Avlt»¹`-•Ò„9ª”F+‰z×…¡‰ºÑãu‰ëòX?V^›­ªª« «>ò“s³áöÄèê¬ ›Þ|ýfÏñJê8/ïD¯E^ £äEfp¶x~ljŸX 9ÖÒô|Õëç#¦ì˜Ö%|ð¢éÌñr-ùË ‰$ã0Cà±H²H&°\ G¼–B ¾Æ<ß•Oˆ R¯«õ{²7“Cüåz[㩜R ”ïcŸ)RËÊ"ÏÄÂȪvëxËôRö´É¬­Š|™øPŠ=Öåzjk­Z"¹‹d6вu3QJ騽-{Žø42Ùž©£Rʪ™›UÐÎŽ‘-O†Ÿ¬éJ5”Ébd³ä‰Ûa;·UÓÛÊ ýY<žíVÝ€ê Y;Ä/#[u ¥­æ WŠ/cDš²c#wîI¦—‹ùô:ö$æ)«&ˆ!¨=O]ŽÉ€p˜ e¹’Œ§9„e2{ûcŒöHLß&üZ`¶µ4+ ,à¶:íH$;w[å˜tJ€ ìäØl.ÕÒ0UXŽz øcôþÁudRdAÐPØnŽJržpS<‹•Zæn¬…C#”r–•ÀG5· ªÊJțӧّ27Œ’iúŽÄ´@]ý“\KZj—»T¼,ª–ûäÈð²ÈJUðlJ]0AÓU§T] O÷§¤%²öGòZc˜C@ì:‹l%™2¼1[Lµ‹TН%¦·ÈÝ7…¾Ø¸Ž[Éqƒò™òõ]²ÎyÝ.ªø,º•c/¥?~à[«Ü¨/¹.œØ*gÞ~òžÿâ6“ˆZÔ±ÐÛñ{"ÜbäB ©Ë±^ ò¥xŽJ™´¤5îjÓ(a`Éa½ít¤ï˜ ‡€Ô¸R„x&JÂñ™ðú³VÕáæf.ÇÔ Z#óm¿ÀŽ”¢v`V‘’•*XTÚwSkËû—_àlk)kœ çãw Åd)#·ªã°^¸Ÿ‡^?Ǭ ÓÀ;jG–çÿjé?båýj†5°¨di1™’h°a¢'â^“ÙLïH¹^@(=/ÿ¬dþM$‡ô>uçܺlY¤œ2FY)-,ÀJÆÅYëýsŽï˜C&Uù3l(IŒ„×É6q²™hŸµw_ÇÚ-JŽöc#“-o·d5Ê0 ë½/Ÿyï7ÞMYÍV®*ÏÆdBÓe%ŒÒŽÖH_îžIVÍÒèØ2p†} yÎ)Ò ±È°‰x¸C¾þT!þ>¼D©?x9š! óò@¬·×àP#e¸=äÙâU16]µÈ12®xÇ»‹^µY9« ?‡Ç÷‰{Õ”²J˜ƒ…_Ò÷¿ÂA•!¾¼¹Ž.Hyö~Â'Úoâun1%ÛFĨ¦ÇMTêßJ a bdkÇ'ƈ)a|Ù·a8Ü·$ ^c?TŽ¢ëlÏr½ù9ÆÈzª€ÒÄLð¶Ì™Þ1ŽtÌm|sWÊ6ÜQþôæUã( δåXLѱR™‘’Æþtëè¡8î'[•2Y‰FÔ%ϳ_A)ñ+¥¯Eæ Ô'T¯c¶Á>ã“ɵËÜüÀ4¢ÕöaBà —rÍlÛ$1,Š^”ÆáõŠf1r‚øJÆ ¹<Ï‘µSÖU ž@Ö¾å“MбõÚáé>IKÎ.+bš{wmÐfÕ/t 2ŒY€#Y»=Ås¿R 5Èl‚ „Ì®‰)ð‹Fœ×HÄÚ¸¼Ï>ÁÛäh,-ãÉðZàî´\äªè!V]£c?94•ùIëjÛ­×Î|dG2ÓáÚÃxÛÖ{?V ™Üˆ5n.ç¬4¨–ö—MÏVuþiZVr ™žóçÊJôd ŠŒaB ó$kVÙÑ•‰i*}È-,ÓËL;ÂU÷u†\»ܱv8½FCÅS?ûTê:4m[ÙºrÓ^hìš›K©”ì&7‚@Ko²X‹êzÏÇé,7޳ꀪf^6îû’l-JazYDŽÇÔ4ƒ8º·’>>F®·¹›ô(' 赘ËÛ‹&Î6O<Ã}¯oÛ¶Ò¢T¤”ÛDôÇcšÛ,ëP"“Çå ‚ôxXÖ˜aw—E-ô4é)Ÿâù@ï¸I¸’^&pkl(f†dý”–IÖÐY)aÄ=4ŸZ(UeÑÎ97ýi}ÝŸLI¯ w¯¶]Wy•n¬¤7®H¶UÏÆj•ÕŒ ÍH¸Ïƒ»?ô·z“hˆE½›¡«Æ1ÉtÜÒTÕRµ}"åÇì$_H•b&8çIS´§ÜÎõâ9×…Ñ+“8´IÇœk[éÐ+˜¨Öµ»#õæ/*2 FbÇZQ—Mf;çªzáë%X¯ÆÂÐzÉê ¨âéåwqÄs–‰k÷m‚ ÷ÛèÏýñ·sr+©ºQ½1Jô02YÃö1w‚Zî®.B¦Ÿ^ž”ÊÄ1¯ʨ[…ºU2j!Ù½U°FÙ³d=dÏb-|¾0õy ZîGÖBÌ‘ù4h‡öIÀ\P6V]tÔËÎ$ãÈPÐËU?üûÄä|£§Ilz¿Rš¥”mSº«ž;Ò³Ú†Äu1© hJæÄíÖJ•(|,OY¯¬Ý/hRve8qΪ÷‘¿£,2Ÿ,ÿ™tl"eÕÑQ¯ªÀÚ&H£Ü¸ë7:qírÊ[Ÿ8A×ló5&6¥ žÁÏËP6Ågo·cÎå³.ߣþ¹‚ GÓQ£°lž7 ãªÓ+ñ©7CùOì…è¨Åå“þÐ"º6A ´¡ZZ£×nJ-{ò‘U•,­AŽ­!wlP™i‡lsƒ‘íÖ2» A±ýßÄëñ&“­¤4çø|dË´çÜp™y€R(ebCÊžg#fî$Ã0ïsáÓ=‡Jµ0¤Ç‹Ú‰aß#ELJù”•€¬”ª§«O3O™F%Y`˜ø¼Æ¬ x½…t¤·ÇzðéI…•ªêí p4É­bžúIÚóϰö˜2˜è3¦´·Ì_0§ïߥñ3¶oâ|r€luÅsÈÖ‘@éq}½.dípor·kéú”@ž›¸^2çz{¤ù;ji.<ÍÜ8Ö¨«‡–?Ò‘a2¿Y¹¤ª€ñcxŸ/2戞0´Ÿê-CÎy<9ÿœaK CClJÕâ•Òì8óÀ]…‘)ç ž=¸F2Øò¶Â$[¶žWEéÞÓ±û~á'LOÑêÙ5 O_‰RîY§1Æ ŒP|v<[B vL&±ª—),‹>¿6‘ko 8´pL ß8’¬Ú'Ëʱª ÝtÕÌ‘®) dæÕÑn‘rQ—¬TÆëÛðxž‰sÈs½€–¶ºIb»—.2 M¥ÄµW’•<Òn‘2r²¦G’µ’ªØ8UG¥‡> Ö(<ù®ö’dU^U+̺¤%óTj\€ƒ£§áâ1d)Óß]¯Y hÌ:‰ÇÈÆ›Ž¢£ñ@˪M­ëvƒUmiP³˜$`#ÓÄ÷MÿÈÏÿmˆFÓЛÕ'½®ª–¹­ˆ Ti¶@³æÐo‘õ&ƒ›B g•Ò±èH@);òT‚ V½v+©¶›,^Fï«^™¾%a@Ÿ­q{Q0Mo[½ùlÀÏm÷R¥l¾rÞh‚¬šžàö¯q2¥U•zÁSV%–ó´LäŽMÌSK×o¥”Jâ˜>†þ°&^Îá8'ꬹH¡`d¯ ÿc'=Y‰£ÜOMŒûˆV× «ôU¹äÖa-€,sKïh›ˆµ3O¯‘L‹è޹%@V•+ñ©KU|‚”ké(/Ⱥ ÍzUk ÜímN9ÆclgX¨ æóp/¾éh*¥ôx="dæHWðiö!æƒxYÌ  ¼ ¥ù0ù^¥œ5b dŸu†ùÔ%Û¡AuÍ„’ƒLv¤™CÇ‘ÉTsãÃ<Ï4ñåó²fZöÜwaм2¹×=k¹cp,ÈŒé2eüo˺Æ×»*Q#“‰c’­dåƒ×Úpû˾çÈ€².Á–(ÉÈŽäÓܲ¦xoÒ´Þí†÷<1‘wæ#2)chžÊ Ô…l32‡ÖVêès„wM8†É”HŸ ýžIž]Yµe¦TÀø2FȘÜÚ'&eUÊièÅJøÞÚ@C[#šòÁ°)Y5·-µÓ,ÙO§Ôw@jº:}„š Àw? ªŽÈ^S]ÚÉ6&, ¥ªit‰ÌY%Ã86+2F;žF[d•2§?î蓶ðÝ«~wÁ ÂYñð6z¿‘Ä)p¤—'ƒEâãþ$˜­¢£^ ¾' œæ÷‡*¾.27ªSÆÄ˜}æ6!p,FRb”ºìd¬s¦d;ç£1ÆëѸ<7:AG]>zwá3¯C¶v;ˆô2üyûëÍð&1¯¶6P»g(;úó“`aFÕŒn;ýü {!èHÑ`9 ê‘ Ǫ̑ݳY÷= ƒ×¸j'KéØh‘uÉÙê+‚ø4Ès‹w)Çþßý5Á¤O1«®{ r†&†Jöȡ.SeG¡¥®ûšêDÊĽ…tÍV)Y¶¬ô"›î+ÑÄÈ­1ÐÙ"é‹lcjQEæ ˆô›eŸG#TeÊpûgX °LÆŸ¦vÇJ«bºT¥–_;Y¡ú…wÛÞõga¡>ø£~®az w Ó®F65¥R ±Õùã1ŽeQãcð…_‘ùgظºð5öCجdV6¹™êdåºu½Ñí<[2½n‡½ëŽd C•&Ë37í¥XKØ‘FL#&îX;LÐÁˆFäPµÆeb|2z¼˜'Æl«•n?1™P’ë•Ež¯ß¶Ê(ßô=&5ýËUeŸw¾5k™õí“©öYÖ‚í!‹4ÈÜa]é'H&÷\2y Nòɵ³F Ðgûy•ƒ “iÂêrìÂÌÆ‹66ÏgÌv¨«}hÒøöþ½OçKËñƒ .æªÛ6 ²Þªp†”=–‰gËpLHãþû]½ª 2lx?$÷3Ç·UVJý>Ä ½ÛÙ2"dGƒ0­´¡Jz³“hL¶m–j©*7ѸÌãÏç¯rï7æƒcrÚ8׫…æKƉIß¼Èá} 57[™ Mã:NãØæ£/ðÖ«J–2ª¨‹s¥™;’Õ ´Œ}ï+ÆQU$Îg-ù+Í0ÁUZ׎[)+þY5h¶ù éëõÙmO8A{nôýSŸ·¶AMYWË;zbp“:öU1Ë™ÈvkP-­¤ Š4"1]ÀTâëUjùõ&#Ð(‰õbfUéÓ©î)Dézä,ô(ÉŽy)å‹ìJÚ‘»s-}*µÈ_©YåÖ§ih1 B¶Uík‰¼5[ã~¢<5&¾ó>l»Y”í@Fü#A-H/D†² ‘ñº,GzDŸ—0‚¦xÖÏßã~€³R[!û,»it”»OÁ³ÞîÈg…ì( G¶ÄÂQÆÈ™ÇÀ"@Êd‡}ø0^ØÓ±p$¸qþOßIJ2rüÄJ6tä–ÌÓ±)ç ìª w¤n^¾™ndzÙûä“èKÂQäLÓ§Ò‡Ôì>xæ@xHÌ•’!>à1¦“탡W’Ÿî×׆m¦F™ œmz¸‰îe#RûéeL6+L|>pË4±RyækÉJµˆ'ëÊŽb‘m·&nz#â‘=I¹M䬺K½˜‰f™¢]VòZ¦)‰Çð$km¸®ª”%ÇÏKH½ر.G¼¼hçŽ0Y'jt‘À|¦Çœï‰ÛÚQ¹kàyÉt“5à>f'ç“CÈ»Æ÷7­^V›eŽOà@–-†ÎV‹ÆJès¢I k #}fŽ[&[Œ_4ûÀ¢5âåôûMÒ/(Ëw™²•bö`;ÒØ°¡güûm«kW#ÞãjmŒ ×Kœm]ø=XLšGþzùvG€’FUvÜÓÈo\™OúcT;—•€òĘÈñ³wÌ!g¤­v#¸Md‚Ö¶ùq Ÿ=½Üøà#¿Þï Î4¨:MLÇEÖ…¹”·1€ÙBÉzMaí¦ â¬dX¸L]»ƒRnueeVúªp¼£’ì!ÂîXî)Gæ&/4žžâ³³²¼^ÇÉ'ˆ„E¼^ÏA`jß >Æzæûú¶vìÉÔ~h7¢¡YÁ ý•®®ø˜°®=¢¦ð4ÞtÊöÙ”˜ã¡ºSf~/IÊî>[佯Öž²#É`¥Þ–œÛ0%¾+Ð`ÎAƒ‹y2Œ©¦YÀÈpJ‰É—#f¤’PâŒÏAÆ´J²£~Ëjqh([f³”r“²åµJâ˜>O!,«Šx9,O|¯:ÙªµäÓÐiŽïÛ9ÁY&ü5†é;öbµլȚR&ÆC‰Ó”»2Ç1écdÇÏŸ$g¤_È@ÓÝ»é€vA&m2fSúÝ®JÖP€§)Ž….‚zø óI¶¼‰5ÒäIm÷šO@unÌ{D+9äsîãÌÍ´mïÌ1Gd?¸ÈÅfo¤’S0á Ì=V¥†1‚ÒçíKNªµ+¥|T'µ€|/Ùè”]|S”º&¦v <Ï4™Èªa†Ê€Òìqy”eš˜à‘Y}Ј qŸ_ô[oŸ>åvÃǨÖëxw9“õ$«–Uźö¨zªº0ª€Ü¶äJ˜LæßM7H¯Bèx¥â™л)0¦Ræ0}_(@ÊHÙ17+ÑÀ•^? ÷ÔIL4âÕö`dó€{!îJQc A2· ›p2$ Úµ.ÿíD|GÙ¬¬àû÷f¤•èkámøT^Z w”UÃF‡µä&‡å#èÖ ë…3$}üu9Vj;òt”»ZKÂuÉ‚Lf"(ËOå4:&ÀäS»£má<É0°L¨=‡Lâ³Ú ‰{þ~ž)ÙÎa•ÞÃÙt@°º?k²²}úÎ"ÜÐp™Ø;9Y|WCP¾þ•),‘ànj Yô쀶! sNùùTê¢t«˜Çì IUÉ b¡»sã>ïŠQm㎲õ¶O“§#ÏÄ{{5kOÖ 6üœaëû‰Õ<bL¹ó4¬éiœ¦ö¹) %Ùç‚71-há(öp:n:«<aC¶€ï]X•Ó“1Iܶen@qË0Ùæyïß•_/MW*ò‡õê"Ûæü.ÞM1íCY— WmîKŒD³Ç õÖ~ty…‘Çéx¢ðø=KO ¬ )¯1Y/}a<¦{z±2—=ˆ6“‰= ˜²)h"“9#q> ß4“•5ª–i`¼£Ñö´dL$Ûܸõ0b&>’g @¤7zÊúœËµìvHá(zVrVü‘MÙÜ % Y<+|ŸŽ’#>9€¡i\&2r 9æl“|l3LŸ ºœ2r#€b2ÀP$e¤ìØ-"iªâ#åO3ÅšI{)),aõU1ù6ƒ#ê L{·éX¤4Y´÷ãq~“µÓBŽœRÖÞoG¸>Àü³íÎa&Är 󋜫#óª™o:F¨â|#Ú$Y9hn7z ^ÍÒÜ”2ñ¦×ˆÜáÄkD›ÔRÞ’Žp2¹v›øßÊÁ¦l¨WH–&±öÝÂ1¥ks‘ô{p2¶~ºè;¶ÕpíKÓÓÎ?¼å#ëÝn¤J¹ö6‰¤QrG½‹JH‹dr€r]«¾þ ‚³Ó`^‹ðÏIÄJ=_XI.ªÎ¤c%-™T½Iiﻤ×èd5b˜ }lÂ'½%8ÚjCk÷i5z?f<ÍJ™XûÁô}ÇÔ[i™­öÌ[rW£Ñ®„É¿cþgÿí©‹¾Þa] úÐN#´ãWâÐ2rn²v>€•(§Ñ^#æX¼]-17/w¬´Œ.‘8ãøµ0i%]FUpˆ·<&“žCŒê£=Ë„ÛJ&Æ ˜låÄ1³:‡¨ 7#5‹f( ŸåU½ÍÃçX£j@NpúŸ¸?òª²¨šX¶FHÉQæoJ8XlnXf%×ÊðíÖ³Å`¡KfÕÐ<Ë•Ü=^ûi{âŒ|ÂɪŽ-¦£}\á-9Ï ÓVûá$˜ÏlõZÉ’˜ü{P)•ðMÉ_‰LµK)‰ý4Hø)ž·V ΰYŽ™;k\WŒ¬K¤ot%̪”0C¶|ÇJÈÆ!¹Õ(·LþŽ·'²™á§Y"Tjý0޳Р{¾z¸IÄ"\ußràvÀˆ »äªR¯hJ{ÂIÐzad-Oý•0! h?^×–j‚H™øþqÔïGÌAÐ÷ªeÛ#²†cëÑÃñÇD&bÓÃ7Ȉ˜Ž·~æ°¨§÷Þt›¤qT…Ƥ?åçFr ãÏÅÞ_™MT=žÒixŽé'@êJVN&ûàÆ´d½J"†°óýL"×r—8ogšY”"fþ¹ÉöD ‚Þ´×/ŽXåÝMYÐa*Á;ªJwø‘¼.ß#[‚ƇdE-E²ª²# žÎO_„•)s[/¾Û’²÷UÔ(§ È‚‰G'Ûôø=;UÇž€#™Ìñ8¾§?õ×'­…lJÇ;(»Iíp%ÕJ²¨jº¿ÓìH è‘2ÜGœC£4F²eÕgÇóƤqlP#À…#™pÜë”æ¬ò|‡â ¬D£ôê|_6d&õFjøŽ@8M-À’>åÉ*9Ÿ‡–Oßô•±«¿%ôŽ>k¿žÈ,Èq,ž]ñ@Çe ™œ,%¾à„Ï“y&½ï`ÒÃö<µw(5÷ÔÚ¤®&<Ùݸ.@dP†˜œ¨&·V¯øÝV¦§XYïÚæI)ð1ðZ"g¤Ò¦œž'0žiA/#ŸÖ—§cŸbíUÉö=DÌ¡–­3·>ckôLñ•¸‰p½|0ðç¯ÎJ«W»£ÜÝן¦­tù+þ^äï ¶­,Æô 憫n´’È3ÜóO£D°¯9#DÏgÙDšynC qþ~†³z ^ÿ÷Â0zeCÉ”àZZfwI˜¯±ñZê (ÝzäLÖ¥óËBìlé¶qU.¹÷ªuÕ&qð©E;¼ê|R:ª†iì™Ã `aº¼)Ã@›—gˆgè.Í•o‡fÕ›•ª…­ÑsËßž0eÑ ½è.2ž&qíµð÷ܲ5]>=ÙÓzR›ÒÚ‰s£qäp+­9+ Rc¤LÙ1Û ½A%±¬šXÎPFdK l˜[¤jkh:’™â1Î' וÃ#Óåcô|*r%¹7xНo¦œ1›>ŸÄw)½ªP5ÝóMà¸o 8žáÄ@þª"YW2Ù¥¸±ÝÐÖÆÔ+‹ª9ï è5TdN6§Aý 5&HÏ$2çã@¦PíØ(~¿¾`]vÈg£Ì×›•`˜hº•O–f~îf¥ßÂuÑçš«±®Ó±€ÐPO9Lƒ!ÈdíJv}ZÏ3Âô#žÃ@V¦{òõÒÔN ”ðYÕ¾·g$Á4ZÈû "x‘žÀªÇú7Ô.ºTäϜׯ$M¯ ¬ê('ö̉aÙ“¥™¾®†zVE†UéóÜ29Ⱥ6&vÄz©h-¬œo:y‘xÇfÌeü.†É Ëy—Ar(Â4ÞQ æÖ¼;Ϊö‘7¢Òãñ…ÔÜ5ùOßCáfsâø~o(¥oã½dÓ‘™È½‹4@V2YÊlëfîÕ5“îˆ `Zòž”yÇéäÏ$ºv—)‘mŽ2åíyo¥ôaPË´¥È6Yɹ’ëç?Ÿ{¤£ cmЙqý²ÊÓóН(¼M87(|¾Ú;4n ´m•0±,²ËDi-É€"Ü*e|ÃHÇáÙ’Éðå>鎖ñ"z”3¹ßK#* G1°•0ps½âyjšb4,kÙ']{¶ ˜4(œ(Î6¹c¥2SžÒ8—ÝJýå_þeÇ­„$î˜# ÁÄQ„» >M¥zæ áíð˜½Þ$‡˜ “É"CUíp+e¥êX#¦’\4&£ÑK#‘)c¶9Põðþ_Ñl˜Em‰rL/oXâÙ‘Á‚¦ROgÇ›B#öaÄG¶¼¡7ÙÆUš¨Ýs/ZÀ×áJÀÞÈÄM¿+^»^`»d|7UåÆƒï¨&nº¼§q3Yqée±{Á{Dm‚ дp½íó8½^èð69¾×«æ+Àÿ,¸Í)Ûjž›ÕæŽöÏPv›NãˆçùŒ:¯S¤L™²q1²cÌÓq|:N<ÛGxÆY5ñUã ,ÜÎ1<‘›Eù釦šrî2S¤ðJÉ7±£ q$X aäÚ·¼šü‘°Ðg¥$´àeá‰`´Ã40ñÓºíI);Îv¿â™oJnòJ@VüaÑý¨´IJÕzå|˜·áøÇã¤Z²…Ìbî8“» o4²”Ý¢+`”ZàLº¶ÊŠØ™½LÖ5-¼^¡« PÍ¿¹ºt‰¤#a>rÏÿöäL–RnP½faÖ2MË'nb†°8%«Fç)¿^÷3ªYã:iº*‹é§$»•6)•êu„[(½|‹kiï5jašLú´´+mмüÅœ®îßò—ý}à¿üNéʬ ÚVpâ42F(Íí¬øþ\µÞ4y&#@Š$N «Î¿có‘û€Èjì6M½ãå.˜3ìúçãvèÅÂp«—V®¼[;È)É:b6ø¢UᛇÛ\n%‚Üê‚3Ú¤Ë:¶L2¤cæöÏÄÄ­7°vàxr÷¹„+ Å|õ M²á†åpkŸ‰ª.+„§ÇÃd•âÏŒ÷£ Èý¦fÒ†²Àë¹Àd›aX© Uõú¼ûƒòþ;ŒÒÝ¥eLU#WA#vL¼·*A›lŠM`¥97¨õà>lGøÎô÷8¸êÚ«&˼%\t&žyz¥¬¶^L9C‚;²•‘2“pxG@u‚–¹e½Ü§ç½-¥£Mì0ë ȧíýíF‰yýËa [-£ÚÒqWµRÞµaïzš6˜&FµÞdy–9abÙOx]L¼©Öà âÕ™•&xǵ×x†½¿ÀŒqô6ða»R]1#itqà›n(àXLFÌÁQnzúHŸkdǘ;šÞE"³%ÆOìhmÇLdâ0} =,ÂJd™4«å Ö…éXK]€¡Ê¨%CXÀ²ªœIä°cŒöd@]•æ†ë ۄ¹4ªf‹Ù øëQvÈ4¦¶æ-G¶nFº|xÚ…ª÷— fâûÕBüôDÖWšLÓƒL§LæX(²&&`+·6ê«"iðŽ"Mí9Ü|J™ ¿¡Ùn¨Ò>dWÒ×^žÃ]]o¶rs;¶ð˜ÖÛCsTºò­±L/€voœMh˜w²iÚŠXDÎMW?ØU3‡Ï˜çQ‡e-| Ç7<_ê¹Å8îæð8O-eb8OU;«æé¨$õ~úï>Cmu™¢Œ7x[®Ô`™RÆËÂÔÄ9DÎín‡Í-kézôµËm•3¿‘‘K‹Û$\ M@&s@Gƒ`ÙqLÓïc¿ÝjLo «Ö h¡T-çì úLμg¥s^cÇJua8d…é.s¼p-¶)@˜˜ [ŒLl *bÊ>Çû‡'˜mnO÷iŸ§£ÒnFæ´X@N™,ÏH¨«? SFÊL ØSr|¥.Žä Ëçwô ¸8x¢f(±Ø§˜&k%š¬'ÈÇQ¤l„¡˜Ö­4%¾p|½›;2`z&kß8-ÍŠÏg2 ÍÝN ·Y9ȶÞl”þrX× [Ãè 4÷¬[ܸIJ¨Öµ+d^v)/͘&îÉàÃLºA¤Fd§å8½k:öÄ@J°˜Hãš‘¸öðrâ|Âr‘Lp‡[ôÖˆ.h)Ý©<¿†Æ~YgJÙx÷wL|,ž Û&’cVã§!PZÆ'ö‰3wÄ-”˜EfÞD<®‹¸õÖUîeu©ôµë™”sˆ¤IéÈD¬7P#çôŽ€ÀrØ>;EæpCe˜C>yb]éáªrãÊ|dd&åziFdè:Öy€F;Ÿ¶÷çBÓq½•+eŽZ¨%¹[¬ñÿH äIϤ. ,øG:˪Ýèl¿†zR”“â‹úç󉦲k?U4e·J¬´ÈËäv† „Æ@UÇÚïí Éd¶i"ûtvÔøÚó^ΡvÕ¸™M$ÐRP÷1½J²0ºý•V «’…Ë”ôHžrs;ÞÛ®¥ö|f èUUŠŽšmÇž®¦#="YdÅ^8î=mKO£Úæ)µ'Te2EU-…ýsèÈ'½–ÄILи€F¥”ÃJŸr`ü|*i4E¨qd₎!ñ@S>•³ðÚ«§Üô×?ŠD°LýЯ”iŽJ›PŒ!°ecrȰýn›?%AWòáºZö6ô;ù÷éN–!™ h ½Ž~ü ˜Óg®”Ax›ÓïÈJ­DFP´0+@¼éó©Ð;Sbn>A+…[Ø@hÌ6,ï8ê’y&4)0]“›cžå-ÓÉ#?€³®¹GJ/2´$R nŸõvÇF뢤Á»2,òð4ÛÓ‰ÉüÃzJ]<Ù2 x¶y¶‘a¥'› eº ü…?Í è¶ÝKƒ7¾m{_±ªËˆ[l˜£R«È”2䔹µåĪܞԖ1‹¸^™#’Œ¸5ZŸ¤#Y4ˆFnFw¤qFnóøÇæõ;AU`dUÑ1Ÿ^ná63&ük‘Í=Íï—IŸ&2MׄUáéÙæ/˜ÙÖÃSTªK&x÷ÿL“L&h dQ)P®½ÑshÖixÿñ†•Þv3ð úƒ¸R&ñdÚ æœÓèL@IDATq+9Þ>Ä妫z,Äð¬š. ¤’´;âz3,[C)ßæñ-°;2é.3ÁÜíñ2^d è‚…ܺ²#e®ÅbýŸu\ÞÉG¦”³•…#™q@Y£ì£A®«{ah]ù´½MjTíÉÌŠX©ˆŒO'òÎùÓLÄè™r7££ ¬.š™)%£.@7U¾=;êy¶óTïX™¬Ä¹–pb%¡äXè²O<ÆQ<7xý¹S5¾eà~<˜>F;€—E½™ µ¤L@ìØÓ A¦/w”õf‹lÖ6Ä<3ÏP$œ?>s@Éþ&ªæ`%/ë”ñJ=@<,4ÊyÎÌPË#?kQÊ>«Àé¿k¤I–›Æ”ÞQ®à¨‹pG]˜Ö^WÇɲªÄ0Æñx=Ÿ‚ìe%çãjމl§Çáõ æØO»Ä}Øk¤Ñ(³Ý~Ž1‘ÝY5“à`ÖZ2Œ©½’¿®ŽSBKª÷£1B;A¹/¿ŽzUÛvÓ³Ò’@µbb «ÕÈ*Oú¢^h n‡áYå£ÔQ бòؼ~ø»/A0A GÖÞ>,üÖFæœaú» ®äîÛ¨±;fE©Z´O‚Ä4=F¶4@@)¼5Ö®ZWUÊZ( Gb¼(tçyFÊs Dn?ÿº¼¤d9%`‘R™ÊŽ:½^ƒädð°à k$Nƒõ«:ůJ<.O8®àš›¦öƽzž‡ÐtLšÀŽZ ¿þõ¯ÿÕ_ý•ŸÞE~ýë_ÿîw¿£$h °¿]—u+ÁŒŒ±¶h$AG-yŽéH ÐôSm\Ô1󜑎‰ ºä>Sü™ú¼3Lи۪q1ÄL`Žäãƒl´Ò®Ð†|ÒW¢lÕæ:¶#>ÏZnOS´Çg«*žù¯×&ìáP ÊH½¯Ç”KpG9¾ Z1œ˜]²ÇùFvª|2IV)¬40q¤,"{ pÏ‘ÛÝÅÐ1[¥ZÒp¨J0ÿÀZöèñÙÆdùìrn!¼ñþ€ñ×ý×¾TTÿñÿ¡‘qY©ÆŽ3ÑÈDö UKú_'þû¿ÿ»Ê×…Ù‹ÒþæáMd#{,›‚¡w̪^8ýÖ”ü¸Kõ¦dÛ“w$K¯È\£h.PW¥Zmâ(”¶ ÜÚkLÓ±)–©+L#E½å Ü& "F —rÕóèó•³H4_)÷ ëмMðŽôyîˆÔëÈh£*TE $P²+2 €ßëÊè¢L&7ˆeá<>¤èå´ãµˆ6);fŸò;ÌUj[¿!ó›ßpÈ'>!†Æ&ÚýÆøÆ7¾á—†5æÿö;ÿùíoûÿ=Q—F»5ˆC³LfNÉ­¯7$,O³Mæ³[0Ú‰‹aD³XMsW›Ž™˜CäUŒ£„-¦%±ÜžÉcÖ«´FØVMtã+idâLà¢*iúù1êŒjpjd?"Û ª6rËÕ¥$§×C)7, oKÛ3ÄèUÂ8Âû´ŽxLXnõi2œ&WÍñ6á»–X(‰ u¹ Ð.”:*ÑÃ2_öþÅ /™¯çÿüÏÿˆ³r»cqý¥ç†ÏLïßüÍß|ó›ß´‰#AÎŽw÷ÿðÖþ·û7Ž.KÌ*ÞGÛH-ƒUï}b(ÂÌk¾÷½ïµ &g&?ùÉO\VÆË9|.øï|G©czЉe˜¶bRŒltwŒ Ï-O›à= —å–¡|ïS#RË.è8~žUÏÀ¨ÚtÆTÒ Ø¸jÃZès<« ´Ã2ÕÀ¬ª*¥oŠ|w5ݳz 0Ƌ޻ð4ñj!ó á'þ€ª½ÄVíc¨^¸é~„¼²¾°Ðþ‹_ü‚ƒåŽ&Î'€^ýo}ë[|üðüìg?ce´[æ^ m—µø}âå#k¥F0ŽãÃ@wä92[ï ’/ #û‘sÙMXÀÉxÚ£½.8&ÿ0éÇûöñÐ42©=q Ë·R©ª¬ÄP¶[šŽ•úŒðH;´FÙ†4°ÜMÁÀª½!½ ¯w%‘€:6 ¯n/˜ ®”H@TJ™ àƒÀQcU@`ûA¿aΟ"|f^¯þ$]—LàcóÆ{ÛÜP¶"¹K©ÂxÏ¥·Ä{é4BéW¿ú•?’0¤É ™Éœ10²ìh Ëÿýßÿ=^e&^ýî’•ç韛Mü—ù—´/\í·¿ý­ ÙŠZªö`]bU`í‘F$ó#71Àmï¥Ëþíßþíô?ÿùÏ™‡ì³îé|ˆ¿ûÝï~þö»Ÿ¢d¡§­cð}<I Úò‚¬š'±–3à=‚•*M<ÁªiúS|þÀ$ºìÒ…Ûö°X°«9_L$%2F¦Çxd –d"×Ò¬J1ŸgUÂï÷lëâ†µÈÆyѽd½ô}¿òï3ökak7”ŸÞ•"½ þîåSbè%á>†ékÛA{OI;€ÄL¼ý€e~úÓŸúGÛóá€Ñ®ôË_þÒ×'æn™'cë(¹ÉZda™@̽UV d®ÏŠÒgäë?|O÷04q¼.>F8öÂŽxŠŸó»öð}ý·’Ü>Å0wô|¼‹HÇ^Jžš&:R–‘pGL&)‘ÛSðÁ“Ùú0ª•^ÿ¦C+*dä’aYOãÉDýx$™Ü׃1Éú2Hœ ¼Ë0Ýdé[#†+Ï·?‚[ƒ¬ ö õOnt;x¬ÄýÚ_{›e†€^?]ŽJ><ï%`“Zd¶ª˜îR©£)‚¦? ÷' ß~„ú9Ô"šE&`-²Yæ6Ú±èoT»Ô›{ý¸òÑ.«*uì.‘+m7 ¥Ü«fº<_óøæö`=1Êá˜y<OÕ׿ã?B¾. rh >«a>˜žO×ì3ýào ûë„*Y]@ŸEækl%-ª˜Oÿ Py=-ª9Ó²#~ŽH÷—ÙiÇÈ/;Äc´ÈéUç³÷Þk±Þ4Þ 6b-Vr¥Ö&Μ™ÒD€²M\áÿñ}‡!u±íþcd⺄F %[GŒq}ñ;{õ½IHÑ,9±Œ”côú-ñý￟X|j±µ4B6qoO$=‡J€# P¯M0 +¨z¶÷w§zs?1¹É¢Ëš¢Ô¼_tý¼Mü¹ÑŒÑÚ˜v“kwGÀ24é-É_0G*&˜¾çÓ5U5Láw¤a¥2 zþ CÊÑO°$YƒsÄ0MŒ'†e;xXf`"ñÄÝ<7üºÒ8>ï¢ïãÍ›þ’oq¯…ðe?£#k1³Âl í»?Ü ÖN÷ÏÿüÏûô‡(o¿Ä|–ékÁt@DzP¾ò}rÓ¥ « Ëí?7µç~ô#g®ÑÛƒ§ïRîÛ¥üvK€QòØ“ñ×Þ”Äø ¨ ¿ñöôÞõ/ùÇôÆ%[»N£µ ]5ºõç?Bž†~ízM)Û-ðL>dÁ' s¸+Ää`\›Ô˜¾é˜Ž ôŽ ¨º‹AŽ4°5þÂ**«:õ'r¥@ó’Á-§´-û™i^&ª@Œ<\»c퀗ÞÓôÁm)kñ§pß(~)÷齯{R4s³µ9Fci¨ªU`;øÀý'`#~üã÷ÈêÒ1Ÿ{·Üðþ’ÇïC™gÒªJ˜Bc½üc¯>MŒÜW/fÎïîO¿ßÉTi Ç‘vJí¯d¨ªŒ¬x\~Yõ㺀<¿µÎ¢×»»F‚žs-4žÏÛv -ªípß/h”ä.•tTËö7%qšpþê¢ÑÞ“ÏGcÕ2Rèrä>ÿ@à,³ÃÙÕ‰OPud[&ƒû$Úo²ª2>+K´\wðêûM*Ÿ ÞAïûÞGâ`¶€Åºƒ£ß”H¥Z›¢ ôÛ™@¨–•|ŸýÓ?ýÓý·fùÚn²]pM¼ù¯Ç­M¼^¦JÞ˜Q­=7X–Y €F»X øÿ|ÝQ®4MR¤áafXÛÁºûšŒæ‰|ëØ‰Îú—ˆö077÷ˆŒÌʪóuƒY Ÿåã£[`Êi.Å”¬Õ­½!Ö›OVÔÑ×öSäwpt<þÑÆãÛv£i¥nû×%º^Œ£J¹úY°J„ÁiBžø\Vàö ¿-±8>Χ Ñ”“¶'¤¦VôN¬îy‰sn9ÉÝÄMzzèg…m …!¬bF>æƒC®ï|WÂSÿ>ˆåzÅ÷ ñº_­„t¢ošðN?ÇW‹8«ÛãZå3;ø·û·÷óÏé÷ìÚÒ0[ðÉ;:ýó}Qqô}ëà‡N(އµüFàr£Ù˜p/Bš—U´t8ÓLx"M† 4..Zó¢S††ã£¯DÓÙ_þòns 8åæ·çùF:hß¿\¹ÛE×_Ãý4B¡Y‰®#„râô[ˆ±-‚ ˜"pXk‰‚h¬Äh¦­HÑ»ÿ÷ç’å@³tá išJŠJV ‡ U&‘%ò[ B²8^y ΧÞó£ï)‚–8˜ø8ñ-Íc¾î‰»œ¥‹êÜk«¿zMÓK‹Çvƒ&qS¹ÕMdâ²D]NŸ!ûò g7@‚%–ÕXüDRˆÜ¾©È1ÞüZZJÍòcZQ¾)§+²6€µ ¡Ã‡xÜøí?ÎFn&‹Ì_ÊýL¡Àœþî8N¿Ë×ÞJg‘ãèkÃb[d"ø¢pÈÛþ ZÓt6Šo!BE…*Íù|(0ÝZaMÒÇ {èòI°"­ÍTÇ%JÌ¥ì+ãëÁÖ_ˆó‘µAd¹MBë AœHŽQ®1gEE=õ÷7m0wΞý5o¬„h¹Æ‡{Ú&‚àÜÓé‘&ä;Ÿ ~äF u>5NvZ|¬¢Õµ„{XK¦t”ŽlÊø@Fª1ΑhDŠn ß/?=¹;‘åªU"ÂLùù>ô^×N´÷U"úOJÅïþëœH]݉ªcr¶35 ÊÉRà·´M%²¦FFÇ(— Ñl-Æß_m×rŒÒàÉ5uúMíã¢u³qäê­pú¦Øþö¹gg‰ZéF¦GæÛµ¢mƒüÒGHEÖ=ɰ-ujß§ßãÊé_‡ÄµQ! 5MŒ²(óâëô#Çtú=ùDRWVŽÚ“ýÑY3˜R(@Ê•¨>«hOwSEás’ªU–…ÀWÔ”ƒÆ€!ž;÷§_éúß ²ü.4¤ÛâòùÆ_âFé~ø/ÑX]óíÈ=…#ËÒÛº…0Kƒ%‚ÙT:2B‚œš99׉O’ƒœ~Sþï¯@j´ÑPVN¾PSi–ÚEåŠ?Ž©”8MœB§ÿu z )#3 zÕÇ”?ñ6nI!†ãô]°ÒëJÝšéͧ(£ã[¯¬”§SEc+å´-¤˜‡Ÿþ×§¿¿—¥fL$&?©Sì¯OĈPuµX`‰áFíV 'Rè(D*A|Îÿôòãý9k{‰Ü&·(Çwß×åÃt y$y¨!˜"+=) i8¿æ![E¾,ȲL;⥴?qlW¹¦õI¡Òð!ù8§NœQþij¬0¿üNyµ‡p ‘ Õ¦Î™¿¨ÑÃãõþ-êGž?ÿù϶¯ŠÓ7%’¡1¾hÆGh#ô .ò¢¥Ù Â#s"žXÞzëí®"Ô´µlªŠt?û½ô{ü£©’IlC\9~­W—GÖ ÇTŒ¬ÆÊrûA)=~)i–R–¡žùSÖar¼¸CDgª8»Mij^o‰7.$‘ˆûß7·¥çôòC_:-K Ü8 )&Nͤ^ÊVA 30eø8·)&…áðË2å´±‹ž7Z¬KR¾é$8M·;•Älm¥ˆæFâ°h¢Þ˜=;U oô³ƒ—»Ó¾#—BÕÃøÍÄá“5å-‘pé¦ßŸ9žÜ.[‰•–B-uY…B„<ùèH0¿x:ýåF6ŠE{™1M3©OöšÖjãÄ9©!ß~j@ÕK1¶4Û¥ø¦mÇï ¯×N –à@ ³ª¯1‰¦kïû_=ìB£ º®äšÖ‘]‹šAc4Ë ¿Ç% D3R3]o¦ùqÖ0æ8Bð§ÎçÑ–lš'öJF]ÇHÌ4‡Ad15VÆGîœ'õômŒ^_À)ñÓ…˜Ò™tdÈëN TÃÐpz®Ô0ZŠ@Ðz}òjô‰ß{‹éYÏ£Y“²¤C$rÒ4õ³ 4eõÃÑéãçÓ/SQ´=Mø¤*$jzrÇùˆ\Tˆ ¡€€ 1Ògqš‚ŒÃa•+K´Nôÿý'[÷°­À_Š,ûÐ\W>@^;‰ß?›K!&©a׈A˜Ƙ- ®D|Ñ*š¶Š'ã³{ A0Ö•!fše¥–²åä4ê ³—+ÎçÚˆ6ÞB+£×8D™e wR9Õ.';×íÿþ_»ÿúé èÙïà´‰üÒ©µàB[¨Ñ7ÑüÇô©"å.ma­MŠ<±|jÿôrþÓ7 ß¶Cä²ü”ùÕ­ £eúÞâô«ÓÛZ?›V×È„YY5°(§«®"ÿµ.Y†ÃÇ9ûû³Ã¦”#Ä1B¢ñ¥,1Ú:Áøå'Zí]5ƒ@L…ÊâàÛÈ·ˆ/Qß?ü»üÅ&šø–F9ž`EM×0'°QbÖ´ýI>Nk4ÝN‡ƒ‰ +>gþÄõ#שÛ=iz.F9…MWN:Â=ªäœÕБxnwé“’8¾¿?ôVbãÿ÷{û—X‰ðê+J¡…‰n ¸g0Çûè]¹‡J ¢l+Ô—º™[È(ÔÞIä‡4öí¹• Ñ÷©åÀÌ€ Á¹ID"GnÜ!àëð¡ÿî*°,¸(ƒÔ^̦&šf¡ùJô„"…ƒ)TÿBøïÕœþž>»jåìR.×XÃFÓÿÿ-„³–(Ô˜NtE§M6eB¥ ©VmÞcõÓÁÀ»É¢«˜¬‘µ] ðVÍÿ| Tu•LÙB z£dN&‹Sˆ#T[ø¦žÁ¶ f£­÷’xY•+÷«X™Oߥrÿ8¥ÛèžÜ¢•úþÁÛçu]ÆÁ´­ÂX¢!ˆ¶}륜¦PÿÊMÑhðR9 Ò.…ƒ_h›%¶„I'žlRùƳðq—®4…lþþ¥F:ƽüô´–˜Èr5Àòì÷1¸ôœ~ùÑrü.Ò.)ÜkD`ð“ùó¤·"ÎøEuB3©µ‘~âh²ø¢œˆY‡BÝ@H¥O¡ØæVá¶R]><­Ê˜j% ǑȄê¸>åï?šxü·N„,…²èh‘Ï 7fÊáWÔÅó)TQQ…â Àý™Ö4fcW=åÖÛ(ÚqW:µ×·g—Ü'ÏjÝkä·"|¦±ê6]4ÐTÿ•S‹cd-'‘Àü²–‹Y4qÓ{±@QÆùÃ'wO‚cú öÔh+ÊåxÛü~ùñ‚—ŸåjûÔ»º|'ž¥–Ÿ,eN­5Í&h,QoeŽRø-?Ó¥êâ“âqèœÛ—W>¹xÕ3Š"1ÎýAV~µG[yj|Ř¯M¯oNÀ^ë>)%8²ªUW¦Æj!°¢¦…€¬Ò.Ø÷n¿x HÁgäê†ç ™*íôß÷Wꪋ24)¦Û½©2eOͳã@£kbÊŒ@-ÄFu]ÊÂL!‘²âDŽ â+ÐÿôäNAnå8úOÐØm€ãQâŠS‡FÊ632+DDé:é°š²¢Ñºè'ï3D h^iˆ©ºlM ,Ë´êÃ9•Fàl¥² ¢ÎU¬ eÖë¡ s¬­d>›Š\ÌšVÒTU·1f£‡¨‡ÐRo£·ÎuB§ÞpªXÑ ! 3„@ˆoÛ~²¬V£,oÍ,"wjhUDstî긯ε¡í‘Cêa >:\¦ŠZ~ÍhCÈh´Á†4M¡4-ÄÑÂ@¹ýï—ŸÝÆ©U‘ –V ˜²EÙÉï[È›¤—XEK_4“•Øâ$^‡8-‡CĨ„89F8KÜØ¾-T4AÑôãð¿ü:QKJœOs ™hK p=åKæ@’¨û#ÿˆšª!!Î|S'»b½…?ÄsvSûnc‡µŽ,˜¦À‡hÆñ¿_ý]õ~õES½fê¿KU'GÁ·ÆûÛ3~?ûTÒvç§–8ŸHH…Z`ˆ­íBKd|N%8ëJ 0)¹¦ñçAP’Ìö_QXišýò#*¥6€k M!ó)ú} ÙI0šD”ãÈb¦RäºâšSä?zŸ#Ø34F„ï»x«™ñ3!´dù•F(%f;fÚ7~¹˜í-þûõÎ\IðKNZQ83å#p2Y¦ÈE1ù·iEºÄÊ IÌš–©`+A@vñ¼°z­Oyµ<¹»®áFïþbÇXçD\*â}Å÷òzåõéá w¢m0üJÐY.Çæb µ!qd Í…7Jg-œç³Ê5m”^J¡|!Íð“’îàÞŸ`h¬'÷” ®§)3ߣùIý öÊn´|Ñm…D~ïÉBµTši–80gxk7­=>æödN𦷵À[?²Y{R.÷Ü÷üžbDZZ¯ r8¾tßY|í \B‘9L.¯. ;3õÒŒ3*|+O”ßö!D+™Tpé98Œ?~ˆ±§rOñ·#'íI4ºÀN¿/Ó˜¦˜¿_~üÜÔï6zÖU‚F×ÞTlÍCœþJ×j¼˜ókøtó³ÔÐ1Ŭ(ç{.²P4cŸÈ@œÆœ©á°tøé<ðð³B6Gõìü§…¸‰X¾¢]ÇÒák‰ïòYz+ð= X%L+¡-Ù´”ÉrÚCL!SÆß(En¡Ô„L“¢Ü”ásòMYÓÆ4Ã[]È­O…ª•Aѳ鬘î_’F Ëf*‘o„í]…êmgM»º§Æc¶ž`U4î’,Eˆ ¿,~ß̼ÎkÌèô»Jiì¯ eA꟣16$ÐK³ _nüþ© ë o¬4ŸÕm ' 1ÊbOüwP]¨(_ Z>ûÇÈ*$…o9@)Oð“͈óýGwY½üœª?V @úü¡ï7I·ÝÒf]Y¯©Ñ{f¹p§¿ö( Aâ—Ò5*Î()gñkB–ùÈ»ÄàU阉âàÓÉÁ1UThʉ>ò„™VŒ±«gÊ1ZU•†p2xe6ý‰œÿôœnÔt©ŽÄÄ·Mt€3)5_È73'Õ/Ùíñ¥ÿò#×ÒaâK¤ÈEëMôüÑø¯ÿlì«ó¾c”^?]`HFs» !¹+òY¥9âJçÔÕúÁ¤¶•¾ºE­ÂTZoß/?Ò×Ö ÖƒÏN^ÛtTñ|ù~ùqúêüÕêÓÑç$ì:Ö¤(„U4²BÌ=€ª¾+U:‚¡Î40\ú¤8;±Ï•+AÖVÍ)—ÄL?¿HŒ·ZõÁ6Õ Z m»‡ˆ{à'ïü§L!˜Rh Œi¦S:‡Å·þ4ëw$_Ågß/?ýÙ A¢±tªbìbC4ìÁÿRpyzàÉ=M?Ư“]žÉŠ ¹ ê3­„¨n¥ùž¦ü³OoÊ™t!£iR¦SS̲8zàsU(ñï_~| ZHR’K!ƒWÔ”Úk+D½>õ,¨a êJ1Z D¢ôµÍiù_ ŸÕ¼Íaùµ$-Mº»Ë˜ø“úÙ.úhBÉršÖíP3œ|)M?OÜ&Ôc4¦›¨òxà—‚hÌ/w Ǩ•”åim³ÖŸÐD¢ mµRjÂñ_f‡üå/Á1åÛ>Ÿ×íQú®:5ÕM§V ^|Í|ÿÙ¸ß:ð×ê²JIJ –Dø#‹cÄÉF(¤CÌ…šn䌃¦D†C8ß/?-!“¥£Ó#ÊL¦þðå§ŸNÉ¿~ Hé3áQúÜÿ÷wH\Õª®D¸æ=k,šmLSÈ=f\:)K†dð*žæžöb¶-üé 55b)üoº'ñ ¨FhH •‘mUøÎ_ ŸS±¤ø¾ªÚÁ@£SâR‰¶œ;—o[‘E5ñ¡üÿðVõ_ÿõ_ŠÚ !„ïW Óo×Z …•€ Ôg¥=ðîWѾ:—µã•Bu+]ˆßi’8$š>…ø4YE9ñç¤<N"UXQ%ä†ß…ÔUåû7ûý„Îzã/—Z¾Áf¾~FCv u•ðYR@—©ÕIÇJ¼©Qç«ËaËzÄÎܪM%¶^£ÓYkÇ)T¹dqL‡T1M,ðsmš?äÏŃ@bIä»á…4”Â@S¡åx·ìm®¿4¹ñúã”­ë —è“Ý à\zõW½ã%‹¾ã[.~ækïîÛ)¶=¢ Cæ}÷õêïÎéaü'õ¬eéù¬fš:È#˜:µpˆöFˆÉ3 M¦ùê–x§‹†/ôýäöòÓï8,Mmäè\cüBF{ò‡ßl»KSz Gñ9OÆB[‡¡QŸ‡÷³pS&¤ydB>¤¬ž %.K”>“"ÄZ8$N#üa¡ˉÙþ1mŠ€v>k oLq9œh˜B¦’!|  ³Ë@ðý;dSÏ~>šfŸ @HåRKJ!‹øÎ¨kéµÇop]‰–!Ñ3ïõòCÁ‹‚Ñ ™)P-NjÎ ä¶¾:w1AFh-¶‹OÐ(º)BG‰òM³DòÓ`BL‰s2!S7?q'Ùub‹öp†ûå'ñºJä³… ôhCžìÏÐ-d5ŸO!ÿû=âIÕ|å´]9mCL–ƒé UÉHªåR4"ÀeUÔ˜SÝü;Û¥DL‰@cýp¦@vôÕk—w-¡HUB…0ÓùåYÛ‘ÓR‘MK7ÖŠKâñìÔzå@ð¼ñ\÷1mý>â¸:ArÀýñÅK‘{/l¢¿tþáÍ _‡,’ K(‹cºfZ¿ àÓ£UŸ5<&×§G >¬Dݶ¿‘ÑLSã¨ÎéYnº, 1Û™dãË 4Í7íº„ o!r9˜p4 ù¾­böÂ'˜•µ±–ŒîŸ×'!Îþì¥P¯”%’²v#<þ4ÃBí‰>CíÖŽY™¸§³´Åb"Ф&³ så—¿B)×’Z¿ŸUBÅ`iqNÏ=ž"4¼ë]täNÄqwš]_…ý[G܃¡¢UA¶ÝÎb7Œ)Y%Œì>ñ^¤é gR´º9J`¶S¥ÝcËå ôòS!×Ùþ˜ÒÑÀÊñYå&~WÁiÊ)‹¬‹mùFmÔƒr~Ýrj­=Ž,)8™N8¢ÈBL{ß·±ÛÞB0åªUiYøùœÖâqÓU¨“Æ®TÇCîÎÉV”B­I±Éæ×€•*a¥Öû°Î¢4é3)]”U‡h¾VSFH¹åÛ‡8z`”Mç2æˆ  ±عË)\=x¢|¡¦÷(äâÓrÍtÆøÈ¥,·ô r™Y)Drj€‚.ɦ)K´gƒ-ã§ãÕÈžÞýð)øL@È7æ¿hM·ÆE½ìú€ªPcu¡-ãÉ2ˆ¨“a¤)„Ã6mÉ]?‡À³ÖÍã¸û|#âŽ%ë¿O¼²(Ô''Ùœ@ˆ{Øûç¶~ù¹{(Z.Ÿ#Ê8útúk`"ó*h+ZZ|¾”Ãä7ŠL¼ÑcN{¬Ë×qG6µRÿÈÔÂ]eÛîf“B_Å4ë-eˆÝã7½G)¦•3fË i-]¯Ý uñZ¡´ÂÒØìùÏ8ŒVN­;4r…ˆë[bU×Pšh޵©©ö‘C-_¢¨S’P–'Ê÷ËΟþô'Z"‡Q#žÍwÿxpÖF£ô~쓈”k\bS!޶PØrð8nW=;ýrPƒÈp {]ùû¿ÿû6ÐzÇÿ÷_éÓŒoš¯(ò÷ËUì/h9ùÆÛ ZzÝB@Ú‰LcšR3…k€c!.7Gc)Cˆ›´Øþµ\·´ÓŸH›ãëŸÿš5K0ºß¤ÓIœ‹ÌQ% T¥ŠÀÛ²4­%N׈“,ä¯Uâ³$„£VÞXHNëµ$­3ѺÙf)c:é4!8øFœUŒ‡/„³í®«Fg·D´™ô]B:N´rùãphêm¯I ygp+ …Й“ßÒ€9tÖC;;©²ßþ8 *šzÔõx–ûÄÏ)Ù6:b zðìô?NýO³©\Î÷ËpÚ„7nS:9)¨îM2ÎFMêA¤¶r·d¸U— bêÙÔW;>ÄÓÝ ic[ °–hz¿ý»¿û»D< {IDc)s$®zK§ÈÖ*?Á>S4uéœÃ€ç?­KlÆ‘cV ÇH‡‰òEÌ%§ÙÆ-ÔñjyMŒ#‹£Iίï@¸Ír>7º`.[:O Õª\`E9.¹—Ëñ‰ï•L:}äêÖÃÝ\‡Ú®óµD3ÚÆz ìYè˜*qÉˆÚ N Ø”,gV{q€Ñ8µT¢·ˆÝ3KìÉíXCÖŒ¬ SŽÐaýÞŠý \9|L=p:=œ¤€]2Aë>OÙåîÁRnLéîUŸT½ Ò÷ÓˆOEBÈ#Õ€(…¶¨Ò¦E1»ME‘e•r$ž6Ek*wšçC ”®QíH«ªLiFœI U “4fÇ/„–¦('Ø'F¹UœoŠŒ¢Å-l )—öû·j‰.¼D&±>ù;Q~j¨ïsãYÿ8jÍHñw1äš¶.~ScûðŸ'Q«½]÷+° ¼Ý@¨PÝ"ß øí@R+ÁÉÇÿ~ù± %’ª‘6ÍÁ’x_Êz«½•ºK»j•–ÎI‡‚iÛ"e ¾—onö6)Ï#ÿë ´ÈÆÔ8iú´@Èuq9‰(‡ÖÈóSCà+Ñ‚£VŪá…Ò±E…€ŸYË)- ãÊàñÕF™å§;f`:h)Ѳ[ …øéç‹r˜DScï‹ nôÑéq’Ž-_bš òýú$·å«·eqزª55w2)øhÈ@Çð8ìdÄP¥¨1'¾Ýp=z]® ¾s¼]š~QSm|?¹éÛ²‚ƒ_!ÓUliBômEšû9)†I§Ñ”nä{ê;ýá¦6Ó³?…{ªùõ <óuÙ{,áû¤THcYÑv†/ÊGàò×­]Æ1Nç|Ou*Y¦˜i ºc%›._n)nD•Á_O8°*OÐXÌŠ\é4=-^O,LO/?Œ‰­ízq©¾_Ÿ<8éø¸°ŠÈ:©O£¶[fͬPM®ù¢štú‰˜ÒüóŸÿ¬I„diÂYRÄ}úGïKB>òÌñ Ò·£Éê¶\‡æUÄØeBæè™9²¯—Ì^~*¤Ö#ðy_’Rÿ@:Æs+ê?îZôÒÇ/œš‘á—˜o\Wp&…õa%ª¢±ëX3´¥óãmŒ Ÿ*bú9ÔŸ_BCÛ ¶)•Ê¢ÅI¢Júþn®JáùvBÝâ|ˆ§ÒjU®Ñ^—Ré4m·¬[ ¹ÃEùšt©–›ãÁéóz‘9Ô9BÀj 7å³¢ý¾ÇZœ~%î£ßYÇ×’Ñcï>Í}ý­¨1A†ïSåûådzß*ÚÞÚ–X Yp`SÁïG‰¨[hµîêº(¢|·r«pŸ[/r¦sozB '“%ʯŽi>Ú'óù½9îÛϯy‰5OPb²tX|#Í3"Ј&ëÅ Œÿy·©-Ð΄¡ÓåÐÂÑ"‡ÕB¡(¿@“k¬°éVd¥s²)HtJöЉ–í#›Žê–/«êuÕ£Bï$?Ùç?)”¥çD€µ´)~8'ß4_”ßÔp:CD½{ö§ÖX-~o>û]r3÷ ž`µÊmWûJ¡Ñ#Ómciîp²) q¤W‹¸)ŸˆÍñø-?ÅzïXŸÆtl g`—Oç÷é—îô×jm—^VUè³8¾¬jìr㘢±S`;SH ÑOÌhùES¨t~d>+øy["-@…A·T`Šð„:ÁœœUªc÷1§\ã “)מ Õ™1«÷:@Ž«ëñ_'q_ÑÚ KÍXi‰‰CHÝÚD(øñ§öâ'•O‡ÓÎŒbŒÙ(Êññr½v”‰·øµ‘¦º–ì_w#Èuˆ/cw!xYœpOnf:£ì †)‚gs»Á‡3› ±~)BNÿëäu át¡óÓá§fª+÷ùý:JÁݾ*]ßD€/§Nh~?ú.$ÝZjÛ¸­“HM¢^'>Bý¿XöpT¥B1!|fÊâX x´ ­ðÌì!žÜ°hF™ÆSêÙ/£þŠJ)”“l:Æ'ãl1Žg•k0úDÓñKQ޾ÓϹC|½²*ZµºZœp§MÑ—‚Ç^ÍÛMÌßMy6Yn‚q€iVB4š_úïï”^º9eaœªóåº[‘÷ñ2BŸ4ÝTñ1—È1­É:±÷ÁEëåÇ{ZAX)­‘BŸ-pˆ64o½ñ ”~ã:wì2:øk)GŠZ‰äèÍ]!K'~Í ´F¡LþU¥þídjE%rð3j¦]ˆá¿÷ɯäÂFZ ­ §å–X¤M·ù[ ÜÉj×ð›BT1¶~¹6å~²’bNXo|:Ä)¶~0Eáß)Db¢áårZ©P‚pþ–ÏgU9Åž?¦Þ§ßY웉ҢõÀ§`ê!‡Ü£ÎeóAáçð ‘Åyä~‹Ê1~¿ü8µž”—X«F&ÅH$‚)Ú÷÷¨¾?´áÈh®…QKÉò)SWÄ™ó¦w ü˜ó×›^L‰"ùR8‰4µL;ÿÑ8ÿé%ÊcÑsÁgÂtnN>‹Ò†ÏC÷ž“€Ìô_-þ˜œå#°ö~n€ “¨!F*À,霙tÝôJƒlÚˆÐ2„HU5°\Qf»¢À¥shvñ¾_~ºð²âO_¡á¢²Mߟ¶N¿“ÚNI‰YÝ»¸Þ2Ñí ¼Z^@_¯ÔÎtÔÞÔ\]/ͽ7»Ø^xœ:ÝüœuÎgôÕåÐñxÝÃ@'o…"ãsl ¡çüûåG~²Ô€(÷™Úàäk  $JÓoh¯¯à>EýòS§– -|ˇ´9^]8·ÑQÝûŒ{ÀDÛ-ßB^;ã™èq ONo_h¤T×vmðKçÔƒi‡ªP)ç^/ß\¸ä„²ÀÆ–¡’8¦ ùgç~¢µn:"ÈLÂøp‚cŽç‡ç6¾Ý‘'nÔ~j…øBß @7€q¥K„pT§Æ©C 'q!NQ‡£7œŒ¬ÃÍOÙÈ:ú½{tb<õ‰LS•–Ò´ºÒ_ÇŽ¾'wÈÚ Vœ;ÀÊqàj šQ Ï‘MeñívE™ëñÜÆ–å*¸Û…€ø@ŽŽ¾5êÊó¨ÏÀtŒŽ¾»‘ ÐeKÝÞîl¦ôî@Yz³ 3ˆÇ‡¨´rH×C ¡ÆÃ9âM$oaÅ„Ššr°é²¦ñùr‹ZáIxLôÖ„A’¥cŠl𠱬F8Có¼éyyGí kS뤳BªSàÛ²ïŸì5+E-Yõã2ÔR¹é‹âÔäZ ñºÿQªtB.KÓ; ¸´®™Óß«&q0Ié–²†»ØRêÐSÀáCžQHJÍ×v>Μ4!òú˜ÚFï`BÓ)QѺÒO Aú(~µ¡¥ë92&e ©”MgÙ–`æ¬[/ïuÿùŸÿÙ× 5æ£q> 0}V ‡Ó¬4„q€¬)§UTHÔ4DâçøÎ‘V*^i!Ô8Æ8!GFà§ *åÔ.¼"T-Ž)Ð:/y·N¯×‘é-e"¦¢Ý™n€—ˆ¨ƒ(ªDd~×òtö_´9h‰@âK÷ {=SqGÓ…ß¹ÇtÈ5Oë´hÇ=Áv£6Z—ÑT!µÜ`¯*¢Þˆ´dNR5™ 0 ßIz½v Å‘‚Æ5@3YHÞuÈñæÍb¾R–˜ˆiZú¯iÃic1qÜZN¹ûMÛ!VáylqÒ©m»jKqˆT®EáD[ét€‘Ï PÂÂÛ…ä¶;Mã·õùpÑŸ‘’%šŸÓ˜¸9ßœ?—D–iyìÝ×ÒýV¨rMÝüU‘G¨ M‚®ð6|‡²uÕ‘N'‘tŒ)ç-ˆ¦Äëþ„«è_8ºlÈ.•cÚ›`ÎtZlÝv]%Öª)߇LYáÆn§6ÁtÑd! r´DÇçÏëƒîÕßy’"Ý”qªž#HŠÚ뛘7Õ2ÅﱘlþeÊ÷Fúº²êü¢µÁa=5\)¾,!޶p!ú¦[é:²tŒYdü¤BŒŸL''‰%çÈ—Ã*)!|L •75š²üøý#kÊðCªeôä~ _ýö*õ´vúY 5¾¢ÀŠêóõuÓ-䈃Ì"[]--ä!òúÊZ\ |>¾ÜîK€µÇ™Çyõ³çfäœÆµDŸE¦i:½­e:…ÊhÊ>¦KôoJ®%…[ä¢9£IaøFe8F›¾5„ãCäÖ¢ÑIú~¸z¦zè€Æ$È©Ÿª„P«MÎk¯qàÔ„œ¾[ˆŽ,cNͤŒv–ñœ08'qç²…D3îÛ-ši´ù혱,ûÁˆ“ñ+ˆãåçUÅk±/FШŽ—:!ep ÑÙ}½º y½^.>¤ërW—Ûnpþp±öŸÅ$Ò*BjÆHĬ²Ï´E9tÜKp~ ¦rùéëУÇA«b!«^ÊÈÓ©>‡!°ß× Pù‹ WIN×ïä=Ƭ6?‹á!žærÚˆ`²£—¨Š'Ä÷õ?³«"‘fj‰Ð‘.d¬Ÿ8|‡›ÕÀFOf*…Žê¦R¤3åßS )²›êõDTËѤ9|8Î1ÅÙØ®B„XéÕýè=ð?ƒ¿Zj£û'ñ% Aý]C¼ºx«–K ‡#«|&Ý”óhœöëGd¸»AbÛŽÏI$M~:¦õSԾݿȉúRg$Åh.1¿6íÕ¶k¸t¥r…Œ«Ë×@UDK<¥ýŸ ˆñÅJ€´ÈBòÉÅéÁY)᩹_·¤¤¦<…r×(‚'Öë×:Q{ä9ŒP­Ös UÈ®ˆ·ç85ÐHÊ~í™XKÈH-™²9Vd]^Ï8á4{ùAk[£uÙv pø5Ì(+šÿýÓï—7Onã´ Yó˵.š‘×÷›ÓßÎp0YÕ‰°Ô ¬Öïź,¶¿,¹4'¿¡Í4Jy=þ=ûm¦¨Á¸'=5ø4…ÁSæÿ…Ù˜@Ž\äøF4«ˆi¬[Ì©}~-ºpɦ+9Ÿ“œ”]ÔEñ³…¨Ùh#“8fS4ŽjFÛ\3Fdo>^Ù%bŽ&eËã µRRƒH±G“šãú‘e ¦#«ÄJˆrò»£¢ÑtªÔšZNšñíÏîócâ¬VÌôÛ%âJ|¿¹Ù¿9¢I¯‰§ÅŸ‹Ê)Ôèäûç/ ^üZ_ncW§>‰8ý:¹/G!Ÿ!@äÞ!ùÈvé´òs?¯·]5ú^Æî­³"w£µ1eñ7&²)ñ¢ÈLEuºZH""‘«4 ù|³ˆ§ROšu&g ž¢È˜ÑõÚ¥#à3Ózå´›B6èuÍ\°~^ßøŒ”Œ”ăçëöÞî'ï ž^#S ®™Àh@âüB½G!x£à×ÌÆ½—’ÅtUcÄubL0ŽA–¾ŠîØþ{âÝu+!äAДüE‰4]9}~€¸K}ÝÔ rf+Øúi?… :ñ/U÷£ûjáxfÝ3gyÏ YTbSNHÊ­Q?÷{£º~‡&+ŽDNþ*¶ä¢{SÈÎÜ @ÆÄ¿§iV÷ÁûÍÖŽí·¬8‰`š¬`f*:ŸƒcŒÜ4D?ÄÓÏÁŒœžŽêÍÎGºASçìUØ‘õ…NËÓÂá0Þ‰øZ7Ú/¸ZU¥<_Ô§í½A8N¿ ÖÎ"¤¹~î=’-[Vå/×õ.QQ#ZÌ”‡#ólñ´­½Qø¡ÓbU_"§CÀ©«t"„$2YÓ‘âØF;à%Ǔދ0£3ç ªûtw.*DZ–š DÖ§Íôp%2Nß}ëÁ˜ÇîEƒpôÖéw}õzý‹7*g9Ö¾ÒuU?¢¬•ý!ÂEÁg¦”é ÔÆJ‹R+k~=Ã9«•S"f:Ë¥ Ìî”àñ#œ'R¼ÛǶŕ™¢}‡û‘Î+»ýÂd~²°é­*5|ŽQ´sӦȅLÖ§m‰é~ϼÓÓÏÅîJK©Ÿ¦DLÝZÆÈôSn…ÀiæLÇ4Ÿ“2§Š‘ù-ÇÑô§{—Í[ÄNLœt4Ca¸Ö'sbZ¸1²*·ƒëýÄsÑAy}°îg [fjM‰­yÛèôû‡4š®môS£¾±êu2\zÏ~¤¹hNßY]MSRª´Š-ŠÈ6Óêö>†FÙÛ?œ‚‘Å—Ø´[…¸idz¨qW''ü-^HzÑÈ鹟çJ‹AÆã@Œù9X*¶øõèÃ×ÍS++¥©VnÐj½kîTIô1Ò{¿¬t8mŠ©ôû‰k T:gâYð—!«nÅ É7¶jxÕ9nr/¯N¿‡(½4 †$…`¥ùÛ‡XÈBø ±]ô=üW‡=þéðïÜêîØÉuÛÇo9ü">£È¾¾JÙO#ÉÊms$¶êú‘Õ#L¹^óð…^‹E+^­´Nn°r>CvN0ýCË”¸5Î!«}‡ÁJ9¦R¦\3ø]£ø¢ Èò›"‡ ·Ì¢ËJÙô¼¡êi9bã6®0¾GÎJÎÑz䮦iÑœ¢j._+#X³€6h+¯ÊDÂÉ2>ë2P $µ×­e¥_QL)åB8í_ƦhfO/§¿{’`´Yu…’…'.g8á@d÷•OQGó?þã?Œ¸2Çã?2j[cššÄi­Ú³Ç=æ.šŽæ%ÖOk2ÜÍé#Îr¾waÂ%²ép½§“ên¬¥q8-°/f>Be•˜ “Yæê>”ÏÉ‚ñ#—ÞÞÆjsÆi±À4«ej“'•Î9¯0/dÒ2•ß (ô‡fõ”º,›ˆ_ÊzÞ8ý=ÚIùÊåô{àá˜"i·tcåÈvkÕ^µø+’²Ê5.¢Dc 4jU¢çÓß³ÙGvýËú֬њ'Ø’l嚊:厾pàË¡f[L…Œ¦'vY´¶·¨1PŠ6ÛˆiˆÐ%s^ѵ±hœOá¨Õ -–î„8pêÊpœ'cïši£!Õ+=…²à@Æqô÷“°‡“£ï9'DY þšŽÒž~„t!2ܪtUç¹D˜~^ÿîYb{çHÿ¼½p€*GÓG¶Ë¯°–øvйÜÂ+熱>B"ú‘U«ùVíAËé[~ueIç³jõ QÊÆ!eŠãP:a^~\×¢E‰2kDà$èójiú@é>=¬ñOú“¿¬J(­®×'÷ØZR·«\Eœ®ˆ©\|Nßš¤hÌÅí;Œþ!øÆõRˆŽ»q„œúá»CZ°ÝhED ñ7e«Â‰3¿,ÓsÜVf£0§d $Äü°`»w-û> âO™ŽƒâôDѽO †³CŒV }ŽÒ9|!û«„_Wp»lºZí£h·¨Ñ¶¦iä«å¦ÁÜ>Š:šô‰ä¡•¬¶«ˆ¬ ²‹ê‘/q²n3÷¿@–ÎAæ[¯Æéuì›®¤O¡5âsœ×ûW ­«ê‰»E¦Ï7އ¹mè·Éeiã¾|@+uÿøöä²YÀŒøz³Û|«›š— ^Tb×BÁ2þî@‰VŠvzú9Žd‰ÛdÆ/”Ó"XÈ(Ë΄7Bº.ùpS~ |L͘ß8µÿóOÿôOu EÍjtx4K%Íñ,´5vÓè²AØZG+…޳5.›+až+ž¯NÃ4á4¥ˆjΆäˆÚÜd£Õ[QYDÔª„)C¾ŸÖ¦ÈêE+A îÎô„ ßé´áS3br¾©O-Y>£fJÇ¡4å kÕ½äe€yÇP´ß@žŒ“’ZSüëá]®@IDATèÀ¥L§ÇŠ)²uùs¡ÏO²N-C #±•&ҳ܆Ã%šê !M"®S7¹û6ñšiŒI™ñÝQVÇ'èZ“J0²¢ ¡•òõì⺦ÙÒH%ظhåŒ3%*‡sûM£ñ“åäÃ9Æô7 D>¼Ÿ,Ñ¿ùçþgM/ðA´L£æØñtM™D£ ÆzH8vǨ׊O V !»Ã8B¬K˜¬kCMîÓçùÄà(Ç0Œµ*E ˆh|¹ñ9@ŽDuíñg]xéøÚvV,)žmžýÉ•olE|‰²¼XÚd9š¯.…Dœž^û&jQ5œ¦‘”±År¤û†@Y禎‘í"¥s/×Í©Ojq(Ô§¢Úðs~ï™B…ï†$âVT‚‚rkTˆTÕ¿©³KZÚGSwpY™ÃÒªö\\!âÝ-ÓDÎ7¶Þ¦ÈjáoB€4«ÒˆSȘ¥¼ñ4ýœ–¢öAQ²¦8¥ço½ó¯ÿú¯ƒjÈH% £´±í-¦Ø1å—‚o\!#ÃOS³»ÂÈŸ~ÓøêBš·mPx¾…jñã$M”¹x>ñ«’¾(œ²: ½™ˆ¢=IŸLjë0¾)C³äVMJnQmX©sÀ8i'Å©DN‰5ƒfjÝ“œ3„©CronN‚Ò8pcÖn,Ä‘èõ`&µ¨f¬TW.J大C³ÓR¦èJ¤`¥ ºî85FJoîs¯R‹¦“È4‹*QÑøYóóù¥0¿qäjáUo]@›À8Èj¡1 $çoþå_þ¥‰±uËhZ2Pšõ«Ç©@·ÄÈ«95nz:I…çñ ù–fŸæ@¶ÍBËÊ LÁ£hñŠæxDõåôU¢+ÇQ"Y£ÄôóM·d>«½üŠòoàh|V‡%b–¨ Ä4‘]9Ó–³*¥—ed F4†&Ë(¤"'ŠlZ'hK¤Ÿ#+}øQŒß¢Œ6ÇÈj \Vz~S4üp>PÖMã™ÃÇl¬VÑeÅL_hÑ[¿BõIxŽrãÃ;v«©çÔøi †‡àH,«ÅgðI• !UÑÄùB¢|Íh;þê–ˆ\n`‹â‡Ë-kÊÑŒcŽl¯hfeád@£ƒoª±À_’6’³ì ׇ|9EáSZ¡ÆEM#7Â1{Ï–hzw@Ÿ©…ߎ†,”P÷5ödœ!)¹]<ˆ”m_®éº… rLÑNìy=HŸcÊÉG¨z|~ûÐÎnOLk_b‚ÆRà‰#]¹hB-¤ŠõƒIy¥…˜išRrŒCL‰cÒ‰/´0ù-y'BX ¥ „WÝXów4>¦¢ðV±D‡¥od¦B®)~;nl‡›¦ÆÇ¡9'ÁhJ˪PÈÆÏ× &¿…åC¤qŒIçiÅás”¯­ú4Ö‡lü5‘#ÄAS+ZRáU‘Û”ÂÚãgBÒwú—ÈÏn!HúS¾Œí”§@=‡+‘šq¸+=µJ ŽVâ“qRæHAnZ–ÒÈ‘YSx¾1?ÙÃx4»R…hš†Ô9ͬ®±«_•ÚˆçäÿìØ–Ÿx´ü*brÆŸÎdCîK¥Ü%˜‚i~ES€°DîfBVy~k„Üþç­€b'X[þg£cëCÔ› GI ¡¬燗‹`šT!x+Ì1ÂO ŸTgjsðe­_¨¨‘xM"ÄDЀi›XõÕ…`ÊZ•²„2œå—kd@#²©U7­+ÎE‘ I±Ÿ|N«ª™øF–HY¦9F>2gÓ:‰vòŸ”c…e¥çGƒÜü{Z!dú| é9…²Šë'ÄȪˡP kïY ­·‡ûWç„8­Ïõ?)¡E'^Å©iRb†¼«ÀŠ~>p9r0*YTô Ç®ØÆrã;m¦8%*…¯9õŒá­g%ÐDm "(TÅbò‚)#•AàËŠfÄ1Ös#$/ÄnÐTtä'þ9p…žF>+ÕymÁ¦Ñ&^ÛÖÅjµ®ž.>ÖÏôÉJLJpÊâgk>üÙøñU„÷PUÏ+ÚÓ !~ üV4¼Ä½swסE02)Õ ¯¿ZºjÒ’΀ÀZ©)Ž){"Ÿ'œ­±jÀ™`¹˜˜JóÃ9íñªWÀ^LE2ë·ón¡6údþ<óp(˜V›ÎüLm™\&T!cüѳ¸Ÿ•?ô³Ž£AÖênÑð•0•¥íÚƒC&¿&#Üx @Ú¬åÖUEn›fÍÔ€ÄRÒ4â°é óþÊA“S´ÕÕ-påàjA’’ a²B œ¦èÝ šëH ž>æ6çfF0²6“>§æU¯.$ß”ÕÐFIá|Ó…›¸¬m¬ÐRÔb)ë$ИΖ0…%ä×ÒKóóO H0Òx, S ©;Ua>«Å|8i>&~û+„ áËJßhZ¡U1Ŭâhpü»ládM…êßhg¥Ä¬–~jÀˆ`ZKi¥@ª ”˯ŠP"¥Ì/%0¿»a9•6åÜkR-c$°ëZ.ÁÖɤ¤#Ä1…76”Þp —+‹’rÓüEk¦¢,Aná„s:!j^]¸ø¦éá8ésZ Š#ó¬r‰ï0¬ |d4#Ã1ž‡½€ÑDaá$Lå˜Ö:‡gÍ™RXíŠ!3:¬bpfJŠSÑrÚ'øûËq¹åsJ¬áÈ©Q /dš¾,!£ÐH¤Ü|SCfù|‰6$e4Vbj‘ùé+j£"ˢ×­U˜Âo9Gô§deµ!9pŽ'¾\úªCLceIÙŠòE38Žr)¤(Qh‰œhdV'œ89‰C(äÃós$ŠÖ°VM'u+cÂÓ.+?§*ü9¢í[[*”Ý]A>Onì2æ‹©:‰š‚Çá¬cæ«KÑø¥SFæ³zÕß*N9Φ#‹Ÿµk1¦p+Q?ø¦§ØÏ]W“ÃË2âäãp¤*|­:Ü/°*ñ· ¦1Ã¥°¥C-}#…¦ò“ͳ1µ¦¤LÑ”órÊ…›Òœ>~ӻʘ¦8r9LKÆWˆå'~†¢õ ʈÜ6¯J4# '0f´F!`µNÉŸ‹Å i™r5cd‰5í•û<´P[d¤©t9m«L*egp)ÒCøú0¶;ðѧÃÓ=¤©±¢ÈÀ]¶”k,qS Ʀqöªc*%ªRÊÆÚ0®‡ÓJJŸd¦mVâ­K9#„‰‘?+ÚJGîYK…p"ß["d¬D D"ãT‘BÑœ®§\8Ú6vuá0Yš¢ü”ø×G`RTìs&©øS…·¾lä×dcâ7NVž ‡­:ÿ©|†ds€#ó»ú'ÿçÉ2çä?V«F«0–ò¹óƶJP’s„BÈ7ROÖl%6áÛµeE(‘Ïè$Þñ2ž2¥P­ÆÈF–2"AScWˆOÄÚXY¦5&¿*gd!ÕdE]Q‚±&©±8ÑLEéh f ˜€¦ÚN³>#ð“:Ëøù¸ƒÆâ´ðjJIa!Ì™NÐŒ:)K“MS(ÎÚ.d*e~´¦F—lHU(çˆ&¥JWv"þÕãÈK™2Ç!1ª®D \ 8KŸs¯9YNV”_ú9p¯Â¿1Õž©ãÒVcYÈB«Šz¹,µJLY<?eŽ'º…õܪ9! kZÖr©Ù;œš\Š©Í‰ÀÉp"W´c!ÕÛÜñ+ÃÑpè3 Ñ´èdÃñCJä6„ØXÊ£ý¹ÌHMºÒ¦Ê±[/%‡³”MBj¦Vn~úø¤¦Ö ²ê|)BíRS¾Ã8B¬åĬÖdK $¾U(H„Õ^jRrKÙBª2©Deq*Í)å³Y/* T}t"—OH 'hê¤n!@´Ö_"¦)ýRŒ Ó$e4m²²bâ×dxã³{¿×¡Æ6rò“ª 19)¬BzcRJå1`m䊎̑ )«BÕ­JRÆ»::±Vº'ÂêÆ¬Ä¶º©Zh1ÓŒ\~4#S%&M⨻¥!ô|Qèè>WMKgÈó¥³¶+Ü´,UЊrž&®S"úÊ…„K"aÑHÁÖsBà¦ÆMó‘ÂHI˜Ÿ„ñ.mP•eµMÈÌ4‡TVbY!²nàÄ„ eA’ÅéÓ0~)|'#¤%”[!¥@¦ÏǓӊ0Y·´hÓ9MÂÓ¯´i"ÈÈùUÒâ¯íZ­+‹¦åO™œg¾P7Œ”À©Iis88OÒéÝ ùzרhd».8•Hsåà²Új>Ç~Šž—•àdùøœJ+ºZq 7¹”euÐo>å@ãùHÕ“ph>„\K=‚GòiÎÁd¢$Ñd¢ò6 A—«µ…mPé™”Fäú6-±røÀ²ò19ɦì:ŸÃgs˜~ˆÈ꯶Õ%^´*!F"²±ÏÁj¥F̵Tóh¥¤ÌG{Úùôƒ KtcVn*Ô4² bÉpj)‘Ô*]o1£ ݲé'N6rŽPÌRT„WN­Š7“A²hR€ÈF=¼‡¹)Â8þÑ8ÿù$}6'…éÜx²Ÿÿ¾ÂÍXÆ)ø,²zÈBÑŠ*Ö†P ‚ññ]"0¤ÒÆ›èñ“¿D‚|¹Dà}P_'ÿg‰ —ÕÃL¢,†ó4õ;E7/ËNĨgYÑšº%&ˆ­”tÐrR3â„ÔX„ÓñÓs/u| [cKˆf„´>{ò>÷?P.¿ýÉW·¥Áç#cÖyQc½)]‰Dâ´Þ‰´ÿRpB¦¬fL™\{¥%ø8ñ… ¢h!8üù*‰Y"­%ÂFN½qd±RhÖy8“/dZÖçl€˜äHÆT8ñ„L_Î8p¶&šJA°­Ö 'QÆgÍÁ©­¶L®i¹¥$lï„"ŒÓ´¢µÑO“™V ˆ°m-¼D¸©”rËJ„_Ôˆ€–™*h]œ4‘#Ü:[±¢wnK–…@DˆÕRS¹ h¤P´ºeAšNʳômB馉EËMÜÈtbŒÓ3"}QN·1¿f  /H0ãäW?&ñ›Ð*D¥§É7Öqû/Ë´ºqÎÝYf•$ÜÒ@QÔ¡¦hµkª§r‹ò'²bm\”a6Bêc )åÕâ3¸[hå&ØÖ P Æø[pé@é­—>ƒ$rà|`: Á!÷£±Äiògøª§I^i–Rt4 –ÎW(…pé‘Ó,½f\´\ÎÀ¦‰$+W]Hú@=˜õ€¿h‚F„…v!Ò¬Ѳ’5ͺ|QÆAbÌ 1¦SȈŒPJR3Ѧ¸t×+Â#ÿÙ7>ZˆèùhÂa]cŽ!†½2¦BøEÛ)`H`äŽ „C§tYišF¦ÉWº«Îç´fä– ¤)12¼\#<°¢p‰øiq 1¥W%¿®(«Åçsdi¡Ž©Äh¦K7J‰&dúª˜TãºJ¹n“ÂÙò!¦hÒLD¨B…¤ÀÛO8kR’5bFM¹©ÿr‚Ž©§¯ñå ¬jéà@šBª„ˆÄl<5ž*éð•ÞÛ—” =¬Ïð(}ðÐRFJ b€çT »M1]—‡ñcÉápdmåM±€ü—‘ 'Ëò7BèHy‚¿»Y«eÈ%;Í:¬V¥EM‡Ûâ¢ðžUµ`u©á0œðµWi´é1WH(ƒ'H„ñ­MÏåcÊyˆ2>…¤ð·Ò[¡8Û(ƒ ³B9åÖ( ä×[!´E+ÙIÇ” ÷“2Áì¡|ŽS䙸¢:AKyÑ”ÛÉD ‘«bl&^b Ä‰Eÿæßþíß,‰®ù­Ë+3BrFŨ¬é¤ÓµG]BÈüÔDÕŠ a/)µ¤qDk '¿imœäŸ›'ÎDjO¨@]õ`KgãI{6´¥áÀùÓ—²æùÑpê¤ñhý2H>òŸa‚ñïD´å[‚d»‘T#¼MNd#çÔøë›-Ä-g`ULk¬.:\?|ähL™Êú\õ 5¶éâoš³étˆÏe«ÅO GKá|xæ§Ð8)þùZ€ÚþbD€äO‹“…W2gå«þ"Ç7ž²ß(ÞTúhü@Q–r‡Ã-f~„¥$Ž6~:'ù§z×OJK€§6‘RFÛ¾‘ee!;—¦ðùÔNÎL‰¤"*qg]ˆ/“Z'Ï´DQ`m$Ž0Íeqt’2¿–&[¢‚35H{U(Z5Å42ÓÔŠòsŠ6â KÉ1ÆJvYi&~—¨«KÁääÃ9–g)!Û%d«Àÿ´e^srøõT~«ýî?r¿+©Œ±¢ýK²huÀgµ[ß|V•Ò8E#MYuñÃ9)‡ Q3 Ùðý7"ˆŽ€“_‰M—˜ÈÓÂçpW"Ĥ·]¶‚¥#]¡ÕâÄ|2>]a® '+e뇡Ÿ½Ub”ìÓà%Þ"°)HydÎò×0MÎðJIYã¯JÌtà¦FRñof$…F9ƒ›¦C!‘jÝé “qª…Ï7íZWáa}î˜ÑŒ‡´4‹­^Scõ´(4‚dS´pŽƒ^а¡VUTV!Žþš6Â1k©¹Àq(À&]4BMò뇃–)+Úz¨+`OkÓZ…ÔC½E+]ˆQÛ8ütóóøiíMR–Bÿa'7²PQ#BX«ue¢ÜæDF3%e\J»QõÕ’ŽÐ4…5LŠƒcíâ¯V¡»"¿i„І§#zxÑâ8›Ö¹*ëÏj.…•ÛUæ¯4¾¯|ÃK/š2Âù|¬›ØÂŰsŒÌ´zMIì‡àT@ˆ™)K7Å `J|8ßTõã—.+fÑDR+4$p#‡)Qé˜4MKiÜÖG~’þ`@¾Õ6åÐâd µ«Õ–˜Ão9¦åÖRÄd…8øøŒ~!Q7-dš²‘Õ ‚eÞÌøÆÙÝ3)äF"üh!˜mÚøt–ÏçtlLWt ¢ìÎÂmO8w–PK‡Szü€å%R«ç‡^v‡k%ܸV¢Ýx>BMHŒCS"p-Bú «D4V[hS‚<”ã$¾û­{¡qEM+aŒSÈhÙzˆŸ&0¾Qt);(‹ÆßuÅd®çhMù dÍ'%¿–ÒÁLvâO/)ø²¢Ub#'Md;ƒVVUª '‚&´Š)”;‘MñmQ?š%"1ÍFÌ0–8šh| GF~ýðY´‘9¢…V¥éðU\]kÐØ8‹ …˜6ž_Ç Ô½.ï&Æ»…j"ñÞñp MQ1 W¯ZŠcôâßÛD6M3B ùU䬖‘Q2ä­°ÕÚx Hïx¥i”+´D)8v"±,`‡­ŽtZ:SÛ~öE?ýŠ&ËJäP˜,P®i¯”ÀB)›fëY.~=´«D˜Bá|`µR³]uþÐ9@‰Õ• )7rȈP!‰˜üø˜ Ñ!gÓRæOÂÏ–â³IñjÇôáž!#°N8Jó£Uóó Z7|á©ìHn5m!?YEsfwU)Mãð™,&ÔG„¬z]ÈØÃ{½ÍÑI)F:)ÙÊÕ*A8AL~%á@¡“ù<´j£©S.Ë…d8Z²uÀœ cÄI–Ï)úè}.U ‘ÝBÚötʲùõX?q~›Æ‰““ÚöD]ÑÒ: –©èÝ3ä.WÏÀÌ4§\>r=/”`SÊ©µ|8Û´ÒÑŠ­‡×*…'郘"”øòÑ RÊú}ZIi·iÝT¥„*3½0!´–ZýoG¨æ’MP7í{äÀ.•º•KÓÎL·T>DÔ3ž9¢õ“BQãÓ¤ +ß4YcÓRâÂg8­Bi¸á-*ø &Q”Ãà*5oŒžBäú7zm]‚ÆÔÐê­ºFÈ©÷sŒîÆÒl 7šæ—ÈÏFS ²1GT]åì‰Z[&g²M!h|Yþ_:|jü*xÕO„fð‰‹®"¤fº²çß«Tæîbª c¶ü¶Œ „´¨Uñ+IÔ›Lx„r]NWåv¤w^Ò,…FS²Ò' Y '¿hmX­)kÁ˜ó$? 1‹®¦Ëâ¼rÕ¢)„ÀŽîÏUŒOÒJ98|æ矄'?¿~Dm#Z›Ð5Be"8Y‰Æ¦mÅȘRè@Œ8cÆ$?ÿcÉBE[_º¬­q)B“m±u»1…’…#@j¦­(jÌIª•B**1ÿ~v€Sÿ8ü˜%X)ÔÎŽC›—;°´ª‚˜Ê 4ÍšRch,%ùŽ8¼‡HÁ/¥.qÑ8‘Öcø«y8& ¤èü¥À#@øÆŒŸHÍläÀ MñYޱܭ¨h:-6ßvÅAà”È/jÊÙG¿Š ùjaúÿždOÖ$›ZšÈ¬º…Ô­%|¹ÞŽL…ê‡ÃªX­t€õóSç³-§Bœ|4NÑR¨UˆäéësЛëSîkšl%R€°4‘ë™S”ÃÌT ),¾ñcÂ|ìjä«%ИÏQÅØBJ‰áóß°–cžé;Ò¨B a5íüäÿJ·Ô“5šÊbmAø¶#¾h ¢YY@!þ¢9Cì~«-D°Þ8ËÂY à‹ñ8D@ã³ÈÆõnzëÔ¤lQŽÐÔD¥›вZÊÝŠ¦ümÜÑv-Ç­CÑÿÿã-úª‘¦è +å0¨$Ì3g™’‰A¾`èw‹ïÏϦoUíF7Ž,³í3rTÞqn˜¶J¬ÈB£¥/›÷ëÙÂx4¯8F Y&è饬±*1ùHã´kYn“<¯üÈ EþJF gîˆTŠo–oFì5ù\R¸¶RüŒ«Ê6`Ú±ýè‹ø·«Çù3¨ö.Ü›­—¾Ò¾Ç×Í êVVe"ó7K¨æC‰”3L@Lƒq”7pÔh™pú|RΙÉüôcšÛ±q]ÃA4¢åõ #ðÌ»­Râ6±'%‡ãu¿yùqάªr%&í|†]±MZ¦£Ühæ”}y¾2šdr-²ÐE–a&1)[2Y5^Æ4]œÀhwÁÈ09Õ™ÀmØKÖ訴öd¿âÀÐÈíìCêØ’ùÔÕç§Ñò ÅøžG#"û -Ímù~ùK#tiÏA“¿ÜˆJWrrniòÔ„æ&ø¿]í@ЬZÒgEÀÁ]oô×L+iòîX)ç®‰ÔØhâÀF;6N R»_pÉ‘>xû U[¸ŒêËÔÞÂo/þߥFÛ­’¬QWÇlÏ—,*n¤c3äDËÉbâÓv•‘‰#Í=U8U$†™xSjéBÒˆiT¦/’°#Àž2=L#Ÿ†û‰â…ÑŽíÓ&²õdÕ¾¢ÚÜ rÓÕ¬ÆÉ»ò¬+‡»\»£ê|fE @@™?ì}Êp·H–R)[/·y&&}ñâ½.2 ·F¥e†ª¢ÝÈ`ÛÈÊ1rGŒvy‹)Mtä<%àX ‘¦`Ž—&@ßËÓVøz¨Š”cÎ ¬£d¢È—‘¼âéYkq¬:€·Pp@UÐ×RŽl rb HIãª}º²%€—óIßn1}Ú½ õÊÍÒ«ê(k„e9×õý”B¡íàÈE$­Ú$•;zF|r¨*·R˜M¯K4ÑåOÖÿnO“’£ªÙñ­æVnÜ ýAQ{½eŒ–2€,Rš)(OV;Ò¸•øhÙ³½NßWHU-âüûºí˜¡ýç¬X6”ÆóÜ4}ß­Z‹’£¼µ}4ÜÒèíóÍPW²ÆíØg¤Ô—Y-=‡¦Ó« ŸÌá"2+¥Kœ­(a >ÏËÙôÄkÔnºŸ9g2Y潊.Å™þ•Á5gãþÒ k¨Ü•ÃEÀ]c+Þú'X©^úYa(ù§DüGU{¢qLàiÒ;fŸ˜rb<Ò”‘€£ç3{{‘”>²—HœÀñá(”äxbѳÚgo—’iL¿MßÐöÇL\•R É-Ì#i*cÈzh¯3¬—€~’á]-7X»L“y•ÎeîÓÀ "5vdX‰FtU±A”¢*ñžçÓtœíªF¯7 Vª÷LºËí ×^®¥Ló:Ãß7޼z@y)ª¶rŽô[Ù‹åYÀdu…×¹1϶7äÏÇ‘IO³ˆ’ „Û0+@>ª-I üQƒY/,Të-×Û\ÕÈ+ü_ ÿ›ÕQî:Èuå6Á<1Ÿ€Ç¢±¯U˜ÀJÛÄ£ˆi%Í*¨úžº. ­VÒÂÊ%ÊZ .ÊÞ >Msçœa_} éì!t´­ªpì90Öëâ)Ó˜¸qô4}Qm¥L¶^üJ™ë"CæüæÃ mÂm{”é”Ê,jÃXhSÄÇå¾Ö]8M½‚ù½UÇdª>û$SÒ SNžs;“UãÈÄîø¨”Þjz²øå˜¦GšÎ_‹¼#¬J†Y•²[øÂ371R¤Ù‡]üÕ×µÝvSbÏʱç“ L Ä0¤WzõýìQ£lP[½íH½y¶‰L°.†®ïH¶MrË&‡ŽbhúQø®š-™3wYÌE+…‘¬"É-÷1a|"çU@U~ñõpi€Nšk¬JO“U½² ÐÕ*2&¹,Ú©Cæ½°jS`]¦„ûð„§d²ŒOÌŸ8¾Ñd9A@IÀ†ÊLG MäÈÄËY%–Å«dˆ©ýå_X[»1ôáL:ºMž4rkàý›Ä{ιÕ8¥ž­÷Òwb3gN™&CGñê»OÓÛüªþùWQ¶Æ†6â•…)i&,Fl"íéˆHšü‘ç^j«AYÄÔ“Fß ÀmÀ4AcÚŒ `Ò*@ÊÚ#«Ú j4…­£È$Xoû¤t¤é›&q¤,b´ÀlÅu=ˆ^&À„iÌ…%Lwj¿œœ­Æª›¢Z°*ˆÉ€í£” 0+LïGïV³"öxs#®W£‹èŠñމfØ8ž>sGÊ=Ûº´«¶ÕdµW"sœ¬ž ò,§É]°v>âýsI— ñßtêc¢LÖ]à4‘ybâeúwFïùààV€Ÿ®H±Öu„•ä’…ˆ ™´Üx2|‘ŒL2_K]vÄ-™¯°•«:âû#•\I/œçvÆÀHµ[ËŽá^©~P®¤q)ˆ·€Gjî.’CË=ó°£’Þ}º¶uÜWTHƒˆ³ÕÛ‰§TYåZ”à4²è˜~†ÈÚmÒ†Ú]özå¬Ýz™ÏYc äv‡œ•DL³ì©öÄÚ‡`] *㉛˜&+b>²c Ÿå-ÙÐzaa%-çy%ÒÓ×\d¦ó­i!¤#™ÆÄkI0£1Yi‰'Æd˜?œFžg‚eJQ# ¡H¹Æ¬”ÌÝß–zi4&id %ÐÏè@†È€A¦ïÓ‹JeGS˜pˆ©Ý1&PV¢yùŽœœà?ÿù‰aY¨ÞÉgÖ«ör(°í 7 ¨Q®¤]8š‹ ô0=@z˜“C«ºjÉ?^ÎMKÌgJ>˜ZšFa½F³ªZ/2@‰Ï?Ì9=¦ ÎgJ|3üžÎ¯å{“zLµÁªamGØYüãø[Ù¼Ö…wCâ‘o/ìr—¬Ð»•Tõö õ«*(‘éiDšÈ½1xúF8*]ƒsG%9°ü¿çíá2LжX½=®h±kyÌ{i`LxWhzÇ j®L_ Gí—>@(¥l®@ ¸Üõ;bì3g·æƒ”‘VjÿãþûR5gdGsD¿5ôvÓîÒíÚ¸MÑ¢ºö&¾Õ<¹M¶€mø§ÅQ4ñ¬õ‹ï/Á)\¬#,*ÉU»€£7°‘€°´Y¹vVª‘sp™RmÈŠ-ŸÄ@nÉv´ÈZ(UáZð/Ø|h„–¾„(#U…Æu-Uc’Õ¯ô~ùqN $h½ ÚA{ñåÅÓh̤GíH¦êÈg†Y9ç&¦!vÌÍ«–I%VMÔ+RÈñ@b< EŽ<¢ûdävªžÂï f®—Ï@†mK£$á|R&“[ž&* 0Uÿç”PÞ¼c¥•ð1òë¢Ú$dŸ€µÔ¥4 ¦)5Òs&§í÷u¸òT¥ï›ŠwH4I@é9ÒôÇ.œ3ÍÜøhU•ª6—lJšªr¸‰ e"å¶ðªʦìS@ôüñžR]°.¶dÈz᎘°Ühí•4ªÖˆá‹6™fLsu‰ÈÌ3ùƒ_zŒFY´Ì»*AÕºhj‘Û$^_©Í嶺öŸ?Üs›Ã€Þc´sý²Í®zt77ïx<[8Á”½7È èõL…’54ŠºšŽ€U‰¯êÈ´ ‹0ÛöDÎô4u%ÎsüH`㪲í=SâüG`D¶º9«H½µÜ]Î2ž˜Ü†;R LXν6¨µ÷ðGÖ… Н„|¹9ÊñÇ$YW« i8׋ñŸ.†1Â’®²‰Ju5ˆ3M̹Òï—T˜å; î±| ®³ž ²ãfOÖo3ŒÀп™ « @d®´#iÒ—i„jÙsuÚÜQÕJÉz½0ølY‰MW®EàÆVUÔȳ}zjñJ“aêݬ9—[Å”1ýŠÝYðâ—Av´€Ð.7V¥÷ly-¹Éµô;Ç6÷‚~ÑN ”IØQ„Ó;f.ð>f’Ò±vù]¯ët5 åû{9÷ʶF‚Ÿ'€ó‰ÄØd³ö³õdq^Gêfˆ¬1MM 3B¦0VìøvÁªÄ¢j½²À4.LéS ÆÜz@øM¡¯½–¾šK¦$+½-°¸Æç‘ÑèJ·@dSd¡…F•X¤t¬ÚÆx·ì™x¶ÚÇ÷ÙÀ^2½ [‘ Œj÷í8¦Osnò8o™¦Ùe¬ hçô Â8ʙҠí Eµ#ü~"Y)Õâ(®Á?Ž96tÙ”wnιÞL0³m½ºä¬4ô° Sr÷ô°È è(kÁŸ=¨«5 +0Öè¬õ‘myt¿/Y Øp‚˜¶Œ™,#z T‰ÑïsjÃÖ­½.¼ðæ!‰óŸ xæp²²«¿ ¯öûMË6¡ÄgËóÔ8Ø>¹l§áPLÌA/YàW?ƒà2«”14Z¬£¿5M™¿,òW"ËŽJvY#ú{Wo¿#žÐHܰÐXd3¡$ ¶U È€°Aª5F:¶[‚æò¤iªÞĺÖÒÊdáªùôTÖÿù5h­^g ]ÚÁÇXW•²·²*A%]¢ç8q ñ‘2Œ÷Á¸@‚ ¦ª®å¸ü>*¥ #-³ç»®5ö…§é؈|:VåÉv#|Gs ©4>PöQsiÒta¹…ä–ˆÉA&nœR?eβH Tˆ#m²§#óqÁ‹vã@  ¬Ë1ÏØ¥ÚÖ‘‡ª „˽LðÈÜÀ®So¥L*Á@sÓ¬Z{GXœQ×P§…˜€¬ä¼ÂïG4/Ök$ÈGÝ'p†ýB—»­P•oÓ÷>1o™óxîÊ­^ÕÄ=Jšö);Ö.k‰Ô²)VEŠã~´*7ߢún‘3ÁÚ‡w/ʦ´ŒÌªÝh½àuÁ‚¡¯½Ân€€æ@ú”¼F$ÐMÓ´~û×KY8æ ì²y:úù¶ÞŸüŸ¯=ëe%Ó×%ïÖ°ÈÁ”ŽH™>¥A ×E°Ñ ¸ãøÄ•Â]‡ƒF9ð àMI|¾³Z‚iò/«Â€à›¦'ž©ÔÆYÉ}Gˆ» ]‰×3Û í4¹y_1U1º­”ÌGÕ Ä‘°eઽî bÛª2Ì„ëm.ܱg¢±w"Ù[ÍS©ã–ßÚýxÐÂ4"\îi¿!°@wÁߎóÓ÷]Hß`U2¹°O+Q¾`Ï I™s)'Î3Y¾Gš¦ÅZC à0ÏebGÕ Úa ¨N–á^µq”@ŸÎºˆ óÏAþ¾»äÕ¸ò à½X¹`·WînŸE¬j8«3û÷S5¦¨®Ý1‡‹qªËH‹U­«œ ÎÙ’õ:¶Ïô˜½Í«º 0B Ï7ÂHo›À‘YßJ¯Xµrãö¸™`Ü4e-án6…žRÐX Ã2¦jí5Îs>³eR£.‘ÀChJ¥H™§¬…²A¯s¼/cþhÉåÙnVæŽ4È…£YJ˜mW>ºçÏÒÛ}Y£ÃuQ^+ä÷mc=…‚lW¿¯ð'ìŒøº°£8Í¿ŸÛš§WØCµu[ôÊÏçT‹,r(µ À1™)¬Žî÷,,óg¨R#åkn²È¡éÄ<Ý}Åu…·†£ÑÞÂЫ$gEïØooâ•„®š )Ž›U FxÉšÅÁþiâ[?ÓŽ)»²ÞÜ€>”Žª‚>²ýk”3lŸd0¾ÞxË\›ÿIiäœSZòa•­Û b‘ ’c;Ýâ÷ÂäPo|ºŠ™¤ì»¾®ÖÐ’~?RŽá£«# ÈÎPµ@Ì£h‰ÆqAfdä(WÂJ5ÆÔB#0JÉ<{G“ÍßsL/#EwÐLÓ ÈF§Çion-{çðZvGš3ì÷yžõÛÙÇ,c¶?æÅ±¸{Ò¼æ£ÑÕKL¦Ñ¡*ÏΤŽâF jÌF¬·†Ó¬Ô†›ëï"1@»bVÕ›3Æt퀄R`]J°ÐX/c<ýi¾ËAã"¾Ý'p7BÕÑ£Võ`ñVª_K&_c tÎÇò®Õ5ú`*U•{¾5ë­½\/Ü6­u¿+ ;·À4œµ·+€·nãÚ[©PZ¤Ä¯7#ÿFTÂ;2ÔÛ¬P¼½ÄM¤ÄSâ{Ñá˜Lä}ý´ &M†‰·óþÇ<’’~h=˜&q>Û QÉÖC¦vÕUÀ¥%¡TtqX YaêíÝZתÀÌWÕ5“¦¤‘g8¾‰ÇXr‚¬lîkظJõ}C{)ÙbÎÍý£—À0=«1ZP« bd^Y¤Ï§] 6;½ª_/ÓYOÓ;±é5zôÄ"$1MWúl€ø<éV…sèÖ˜¢ª’ckÔ+#1nç4ÞfáY Ì6II,â õÈš.ã‹dF«†‹¶‚µä€{VJM¯±<¥â[9C@ ?FoY¯,r+ Ld@£jí@Šf‚@þyb¹õK-¸#ÞÇ׎Ä4ôJN FU´ÞsF¸ÜDøŸÿš…¿¾hS{d¹ÔN`*Áú½mñëÊŽåz»€yŽãÿ ê"S¢LŸs>žæ._;Í&zÃÖ¨K¼#ÂñZÂÚå<+…eo¶* ±ÞÞO) Œ.Õ øû’ ©·ý òl–L‰<þß×mæÆéâ §Ôkh”<™f%“12ÿU 2ºÃÜÈR(Áã· U|+M†)ðÛÓñWüþyÆü¾ÿ¦¡÷„û(]Jx’ÈÚ·¡q˜×­=O¶[Î\¶üÑø?=5›$0²0žÚ*úÛ ¹È ž yøôe†òŸ0CœÃoþ?ÿÄ;Ì?Ǿ[äfI³˜8&ža™TåûôŽ•âçÙÅ3¡©ÐÛ³V² YÊW Rl¥–©En\aEÙ\”ªbÊ0=8“®C2&>GŒ’˜aŒãJªþå³¶ÛdJÝ1™!`†¦Þ÷viTÓïYeB\ä ka%úa#j§ä häJ”pßµ14 •;Ê0¨ëÍUÏŸµ³¤Vvô‰‡zõØÏeG ¦1bSðª)Ó(UM)ã#Ûª¶ddË·pþ˜HGJOÿÞ«jþôžlþ¯¾}æÆ¡*Pc&›BÐWÓØSêÉ8f¸vGzÇz ²H 7ZÎ6 ‡ÙVª1¼%„ lP¶} ­J³R<v)G¸¨±/F—PÚ>5æ¬D zSjQ97¶˜Ó ½|Ú1ZèÇ)WÚ»N§øÕS¶v½íL0·Zz¾Y ™OÇf!s¶À*%Læ(ÓäLädcÉôrÓØ·ªjLÓ8XÔÎSôÌÓ;U³íêéåö'+a@̼FG€›|BÁa³ã(âå»Ïyâô[‹ ß«ý?O¯q>µ;2¾?eÞ¬ÄVô ‰Fl‡ ]ÚÉj)§OÞ†)À4rU¦G·¦_æ0™3Ù¾­6¨?|6”žÃ<ë­½Yù‡É€>ªZÚ$7Jíù››‰<ŒƒêÚmÈ©=^æÓh™Æ¿ÖQ—£¥£Ô˜[x펔åÛô¥1@8°LǤRÁ!²c·»Ü!…•Ö•ž† WCóú¨æ£Ö›?,ßûMÿûK0‘žr5#€:s)ã‘ô}<0>&ýÚë-Ó\Ë“0i¦Ú591¾’cw®‰¬!ãE&fUŠ”së= n2zGí"LC 2‘˜Ú÷öLÚû$ê2·’#ÐæÈÝßSÅà±ÞºÊÚ9Ë4” r\ÈŸÀWE†ͪENC Ë…o.[[/ÜU²dnu©¾£ã“)Õ%'Ë!OdbY8âÝe¶@ô])+b¼Œ—7 Î!AaàÏDçGçSÈîR éU$;Ïí´ *o³l{ž>™’'ރȆ¶: g²œ«ÂÀÄp¦ÜtUw—™ïÚ0Ù«ÁäÀ­ªãÛ¾YwÂÙªA@æõ¦tÄ3® 'ð2ƃ­·ÏÛ11’I½0}LiàŽ”"Ÿ%¸­”<=³Âs0«/?dük{½OªªÔ2z‘ܫʪ9$ŽAö‘9öç<Zë’û_{0m˜ìØÜñ@¹Ý4v£· †gïMêX-Ǽ0i;þŽÈ-AœÀUù„ŸÙ÷‰÷èÝsIŒõdØ>s¦'ÎM©jnHÕr¶²Y~ñM 3ÄÈŽü'´ ärãûœõž%~ŸëÄÌžøÖÏcÜ"1(Á<÷c^Œ^|–žŒÜ89}nã[és<ûöO¯ŠÙ§ÿjˆ³]V%kçU‘”DVÃV2KhßÓ¶|;ãé ß|#E>®¬T¼Û—?¶‚LÆræôŽ”WrEÎ…Z¬ æ˜i.“J_ÛÓ$«¤±ã¬rC¶„ö¶Ç›xš[bDSh¬ž2+g%¸Èví›bOÎŽ¢ÅÚ¤™¸>e%YµôVÂÀMQa°5¦O,cz†yÒÔÒQ•æÚ|>úމכ cú2ðúÀ¢*çŽ1án±­2ï( ‘XUðÁH ;¾ná¿ Ü]d dÕzÄŽkgŸ¬R_p&ÄÀ¦Ô’ƧyÜÕôÊo3ý¯šé¬;Âzï¾/GX¹ÄŽ)ë­šyŒu)ëM&¿ cþõÒ›.€”€G¿‚°ù«ú&½®x¥ÂQÌ­‡x‡|ÏWµçC?Yß¡É0祸_*¬ñÜ8ŒjÏ&™Ü ³7%ì(ªf‹/"UÍ’‘4} #1‚21>e]“9öÁ2ߣÓÀ\ºDW¾sN„}­*­=~ÇWt}#ÄëxJÀóïSÖøÏwPmŠSë)úTò¾¾ƒ72Jí[ѰÜðí$#E©‡Ø}wDÊ—É3%@&k‡wáHyËØðÊÞ½à9G†)O™ÞÑGNײ)˜¶"@ wLƒÑî§[>kßh#arëÉÄ«¹ÞG“RÖΙ!}-mB#2'SÚ½xÒ œÕ™tyY—ª,˜¸‹ ñ2™¦{QbÈzVU7"Í58©ÅÞ‘ÙÞ±ßè‰shâHzŒ07ÓÚ˜ Î7ž²å0¢½‘ðÔ» àÁÑTµÄé¹Vóž^{¸U(™ x›tl |K6¨R$F ‡”Ëkñô›’ƒ^{ji[2A€'€Ëñ瘃üŽcE)㙄ßÞÍJI¶j`S´ç“f†[5+Ï¿Aëý÷Üž*esÛei0±¾Ë5V¢O‰ÿÉ¿÷>Û sÓÄ=mL«b2Ç„eʶMï(ÈôÖ£*Z¬g²c²2ç}mc¶s&˜FÿE$g.ïCéýžúÌü½¦HÍýX ³vÔKÐ17£*àŽ²ªøévešIDATäÙæ3< ÀAn½ÉÙêöøÎ°ß·Æ j½ Ò\íYh¹R$¦až"L€w”_ñ•RP­]ÉžL¬}&Zʪ½v˜¾ŒÉ`æ™ÈÒ#aÜ5ôlp™¦³ªå0ÍÖÓûs Yi-É­A“³ÜÜdilXxIXÁ^§­ÇVÐ×[£Œ´|¥Ä¢RL™&Þ1æ 2æmÉÐÂÖHF&;¿ÃÂòú7`Ö—S®ÅñU:¶M¤#e]}œ h&”Ç;¦·r½À«oú¦(mz éa·¨½or®ÓCÐÅέÑ=8íõÖˆLƒÜ¬Ë=OÇ [€¸Ð®T–W0 o.™3 [%Œ[8‘ù;jÙ¬p&rwQ½ zá-“9æŒÉ„¦/Ë”»&àñ"íz䑪4ñ}á¥\×ÄëÝ>9üá[#‡Ä3‰ÔH#ÿóÛ5WXmßB²Àˆ|‘yazúªW{RóZ(²ÆjÄ;Îà3r?½ôÕ8} 4¨)dïÙ™ËÚ'°“mø ’)¥Tʪ¯ŸªæöU1ɺf¶1Ë5&^K;4‹’gWƒ¶J€ÀªqOIVÊ@Î-¢j#’y_ÉÚ_UUº§èdÓtBµ£®d5*Õ+G’ Xc e-Ħ +Ñ#1"󑎹ÍgVÄÉÖ‚Éçûëvg¢WGݺñ4€É4@ ôD]Snd`ƒáµtÁB©À{4¹Å—[ÌD`z þ5‡wœ'†R»wEvœÉ4£«ö¹Ö%#U±OþskŒ)]Ší€^Ñ à¸iäé‰ñÍÂo( ôn…IÙhøOµv2æç—çÞöõ¬J“l A-˜ÄL¦Ë1Y ͆«†ÝŸ Ã#€ŽµÃv{¼%HQã2MJ@{†i "p4¢‡žçJ 1Ž2 –+ñlÛ5ÚN¶| >·¾=÷çF†åzmÕ 1o‡ªóÙ1 ×8ÃË„-LfúV­Ô±ö=s-Ã@J]¼¡=|J¼ kÛ×N ‘O‚üåÖ«Öâ¸F¤£ÿ}Ø2ª·åSÖˆ´U³0"\æùý~=¶~mîÆÝߥºXRU+u™6Àl>Ž2e»†ãkOœ oL¼û$C ˜F„½þ¤FfhÉ4W{¦·a÷Œäl\GÁ6"C™^5åŸõȲ•[&qssÃrÐà¼ö›Å÷xóAáueÉD¸‹¬7ò4ü>¤’cKfظFçF†”x-øžÆKÆ÷ûŸü Q?}b<Ò%cv  ßM+E¤Ùòc2ƒòt„÷[{ãOL ýYô†#>üýrÐ9V.ºðÖ¥f§4 —²R ÕN¬w‚ùŒÑž›Û"õÒ``þã¯ä©õ,8´d]¾x²2…ç;¥*[A ëåüjÚ­öùר 9>“9BiU Íå>Üc11±#M¤¡HGzït¤#2Y¥i±Uko(Ð%ð0F{šª‘ᦄÓ÷L´¨*µ¾–¦ÀÉAI¿,1ï;¯30ðÖ’ŒO·ÈV1ôÄ«nPšåïçç&Yö’½ßß%ànÎ1` ¡Ë¼|ðù°ÕXÑk/(½y?âü“RVd½ÜŒh þŒÿ}±æ_#²®ªxíLÖ¤QMïØE0¯é•f;‡@Kªç™O-¦Jþ(S¸^¹x}°ésØE´4 iP Ôò^I¶X#æ?±eÚ'Ï6ÜЙ¬Jì÷9Â\ÁÁþ‚€9¦)ŽYmbüÈmKã(hbd±ã¶B’UBj\‰8&Rþ/…!‰f‡Þ>IEND®B`‚ic10 Èg‰PNG  IHDRð¼Ô AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝ[¶dG‘„aŠjî°ãqYŒ•7†ÁU $¾ˆ?Ój÷Y˜››{ÄÞ™çTIMúÓŸþôïÿûûßÿþ7ß|ó¯ýë?øÁ·ß~kûéÓ'¼­õ»ï¾ûáø½ï}ø|I!£ÿß äR´²ÿüç?­x¶|¬Ñ2Áçù£ýˆ ”‚³oÅX™ä9ç[z–²€1¬j5ÕÑúõ×_kª—Õl‰­ŽIÐV•íìq Wnf¶ZˆN'…QÛ¶FY%“5d3TËÙaSv)­ByàCöJŽç³Vw2ÃX›9Açrä¶²º37@¤ÃÒ JYg„ÿñôDØj§¶I¤hÄ{Às½È§–];Y&÷R¿ùÉO~¢‹”Ûè’ lûô$V"‹ì%áFÖØ¦¢á“u"%Æî ²&‘ÍÄæl0k†JD0LÔ;Eo F–íiðé“#à)Ù”¬»›¡!ÎJVÈÂÄ(0lÛZ¯÷ù\óYÁ”§æ>‚OüãÝW-u*¡ÒWª­J-g€YJ.ªFJÙº‘ÎvG}½ ™ÔâÞÏùx0g«ÊÉõ2œ’æ¶â µ sƒ¥´°vþç½È&¨¼10ÊYé¸×EêCÖÖ0fkU=Eµ1Ô(€†!U!ÆUÙÂøŠÂ^bÀ×¢1ž§’fþ;êÅ™FÖZÀ›„,Èò´œsÞW‰¬9{eÿüç?Y¹imÅÚmHq°Úê»'Uwž€ØHméõ’U‹É¡Ëq|ÏB ŽéÇ6åOúSÃPö˜4ªiÏ…²#äV­—jb¤>¶•Rµ‡U­Q5ÍóYB\x|‚¸©j*¥¾3Êv^[$%Ð<ôÝ' *A#‘u±ü] Ò$Ž 0ìq¬EçEÊrf…¬4€’l×ׄ‰ûùÌ*ˆV²™‰=“4UnV2AÖ¹LËA9< k~‡u„žc-h˜ð´mrV«ªpo妪㤉ÛjKfåÆ![è†yV…Lßœ)­¶N¡¶y¬†©ÖÀÎ[¹ñ¶ùX)•˜¡1`d%lU5Ls)ÀÍô}é)¡™²T+sAÙ6+[âšâö&ý mùtó]u2ú”Jà^Åø9ë+r3³,Œa¨¤¦@&V‘¦Qmµsj[Q‰vxx}m›ps–U’ÃÓSwñv}¬š‡Û=+²NïûªdK©ÐE6[ó\Õëw}µÄ†'ckíö`æ¶L0§`…é ÍHy’Á|hºá=’? ^Va&ÈóWÕoÒøŽ)k[3jd­Q¯+E %™ð¤Z`xʦìJaÙz¥iBM•È*!ÐhTšÜÈR",ål‰3ÏáJ^ ÞÝd“iZ¡µ˜S>·p†Ö@ÕênªµnΤ/.vþ|”[ŸÇlV“R6Ò´€rÀaºRYA_­“NÓ‰0úv“J:TwBY#dÀ Þ„pz}a¤•2ÆCϹW¯K£jJÐÙUIõ54-qº õRb©º49=Òº,½‘Ô*ÑÂ*Ë@ʪ£Õlãa)>ôR"VÕjJpy_`cØ‘9wϪÔJi!zÄ¿øÅ/UYYµëŠÔ s5dwEÌùl*o%VËŠOkjÛ„ 6›Q=zx2Y³õzd(ËAp¦23``¡©­ª­#";ðù«¯¾BñmÏÅ.KN•°”À?»šOoRJØžþ7ðÔFj‘g>MàPë&#è #æÁ_Ê`˜Sš­‘0JhR"Ÿ!uv£î†áFÏDV— ó·XY)éä—!N½FR=)ØÊ¸»âFOœ^ àtýz÷·¿ýØV¡•RÐÈ7<ÿT( (O#{D÷#§ä9€yLÛ=ªr7 ØÒ¨5§BØEÙv?¶jñ{_õR…¡‘µ%p Ñ£±å™-™yàfk­dµ þVœ¿uÓ—••¬•c%ØðJJ!ÝF€ 6ŒÖܺYÛž ÖJ¬ =‘4 ¿©8U™Øò)42 ¬Ê$RÒÌø®w¤ ¬û>JÈŒ«Õޏ)þ<­_J ·*§X•º?J¾eÌæì•$`+ð4ª`|S5´ Æ?§JÖ'¢Bšu—…Û–ÕËËïŒnµ›i*J ÿ.¼7A­ÏˆŽSÇ<•õ㬅I”ÓKu'º(¡©…Öj­maóÀjuǯ#;+|G ÞÅjJ#”™t d@ª¸Â󆳒bâË_ ðá*èiè­Fâüö8_ †WXljmc¬HÑIUqp9¶R¶RóRm ·¥tŸM‚Mn$VLú£ïN‚ÎÞ¡RÊÖˆŸ¦›oH%ÌelxgÇèØA|KÃL )UB‘‰U`˜8…tñ½—¦WE•r‘˜¿Pµ#g‹I¦s½Ï»MŒéí2¾Sׂ)œ4ÏÙÄd²Æ“­¯!‘²FÙšʾ™(×¥Z¸.émV†¶ôü›?Óº‡º¶™Ðˆ~à•wR˜In€•••À*´ÃH#{CÜ?sÝõÒ‚³ƒ4!ezÎ=&'•R+èyZi¬$Œtd=\­§”‚Ûæ/ëÍQXGãq¶Å‹¬Rê.ų«¦ÏʶۥT€+‰!6RURâ4¸b¤’ÙÆ«5²’Z«2›ÕÖu¹FØqÈðôWˆ!æY•rÛÈÚ!…mC1ôü?ÿú×¿Ž¢vMÌ…»u$`,ŒJY››×€[³dšá¹­±Î|¬=r‚ú*ÉÐ ÷¤Æ3ÆèYnì 5:[µ°~±0F½[)õM)Ë 3ÏÎb ä~:Ó÷ZKy0L²µb„^0žÌ̆Ç4Ï”>ó7<¯ l%à 6-Ry®AM¥Ž¬¾9 ›ÇŠGæ¦ öÜÍïZÜmdÕÓÉgU‚U}»%«@ðìrl«í7<[xYVÊ3dî¥7䳬J0d¢ÀŠÇ(t·Áy§8Ÿ¥ÍoÔóÑyÿ ;ËZ–UxŽtZ˜‡F¡-ðο~<¨Õ«Üfà_¹™Õv±Ö>LdÀ™4¹ŽLœ1ÛR°›¡7C+…Ü`¶Vb@9,Û£O†I¹rí¤0•›Öw“aXÝ¿Ü %†§ë,»p&‚‰ µ³Ò Œ.ÜàRfàã0²E†…R #ÕQÕq|Ï4!™‘`« @æ0@š‰söp‘úÚŠ iÚš™›B&İ褔H[b+7²‚@ðT¢£SèHŠï×]GS‚´"­O†ÏvÆàÓÊ–LV#ÀV-lý0m²¬d»ºŽ ¼PhÃôòäo[ùÖÚ¥DŠ®h­;7ü3Ū.Rž{ßHÈ3\_z[Ø0e¥I™¸g×ûŒÑ®ñL¥Jm2[xnHÛ ÑIekZG]„[š‰lï*À>Ÿn¸ášDá3ÅMÇd²”¶©šîþ1¥`)‡²*Û˜Ú5˜™Í€± 7•-^èkÕš§¾—; ñ† Óà‘"½Žø ­ <™.1ÉôŠïãÉV¶{¤gkU°©ÚÖÚeÎo+:š?Jô”œ3'¶5¡Šæ—jB> ùÈÂËî‰Èº@þVáæiøãÙÖbÃTNC€¤Çܺ×/²º(ÑÎ%ÐxdÈMH?gJÙºøÆÈÜV9^V82½X6C)ÊÆXI×eYMe÷#e)•ÃR4u÷³&=”FÐ#%€x°Ê:Ã}'~NEÙµ#é5í~òϰ‘Ô óXi¤š Px&¸34^ouVxdþ0±³­E/%[2‚ž»Iœº^›_U3½·³âÆoå#0¶Ú +\Kc[&R­T¸ÆH”,ËÃ* † Æ‹ÎX•UŠXøV)ã)·VNï}øü»ßý.¯.MÝiÚx¡^eó«®x@êúþ­!ô+¥\Ø µ"ŸÖã{›âF2oË6qÎ×ãå#EÉ™À´ %l‘NìÕ—2ÃLRcèm•¤Q¨ [z<€!#Τ1lUÄÖÚ集›·ª*zX*¥Z<þ¬DLÃ4g—#[SZ1<{j¾’ØÖè~ôòµÂ£VIzà •pHÜlVgÁgkËÄÖŠ!P°¬‚'gÀK¦høºøWVôuC °ÇD tçŒÁÇXÃïî°Áê;ÑV_Y>VúÜJ™M¹”‘:æfS.+j¡Ê§´`bá,V[<¥ZÉ¡”.|`Y²¶†¯Ø*éÛŽç™­£È›ëB¦g"´Æ§$ckH!{G~ý›VÕÖ.gâH7V“Ži{ÍÎ ¹RlÆ5šfOªSÐL¯Dt? [2+¬–ØÚäÜ܉°¥R5Ò‚‰*Œ×YyÓâ1R•àºXy(ÜÀ^B²” LÛ<] ^Ž ð‘åÌÇKR¹&A)¼˜a“/ÅJ—FBv"Àa­RÄÅ0Þ=@ªa*|kÏ©Ó[Y™“€² ‘jMb+¤Žúý#m3pƒÉTRǪ`UɦÁP.ðk4¶ÃŠîa¯2†¶0P÷µhKé,‰ázI…w3¶†¡ ØÂmáŒË¬<##b²’5\‰•B$gz‡Br¸ÕǯJIV ,‹Ü ¶Jr¦”òâ)deªP")1°f)+†yþ0Ïl­ª–eu3ç3ØO†™3é˜Vb±r؜ⴹoÑæä&(›G ['J ×ìõ#;^­…­ÚF%ΗÂýZ°­$“úb8×ö JõD0œ•+™ÐȪEšÆ¶Âø.ÄÊÙañV¼lÀ¹6OÎY&[‘ÆOáx[€›ñ²5X¤!1ɬZ“™täem“X1ú&lñ9ØŠ|z¦¾´óe˜ Ò Jø¤ìß\%ÆtQ^•F¥”ÒKù±¾·ûQÅèû“XS'M°c"›3-Ã9›A‰µ¦”MΤ_fðZUo5@ ÷˜:˳¬ÊÁõêhb¸Ç¡‘ÀÔØâa…Ù‚[þH¸¨°S‡ËžqïP2M•3İ2Õµ|½~“Qâ•càÎ4F|•[Ù¶âéµ s@-zç!ŠD)¨?øÆteŒlkÙŠ1 U¸ö”14Žê¿öîíñf”r/MFf\«È01fÀhaµmT%ôpnV˜¡ªžñ¨cµuñ;%%R91RôÁàßHkQ¶yàü†nÏÇʇ›0ž­ ÈikµUÞ-M_£†aK¹ªuix< UÈ&NØ&ÓÔUÀü‘Zc(Ü‹èÓÛT4}kŸ܇Rá!;° ú2™s„ÂîC`+ôÕÝ–U³ÁP•óüÉ f¥®Æ=×Åð‘7yž>†ÀÕZðYwXJh”?}“˜Š§m‚Öe›Áø§¦#ÌP;c ™4²¦ixÛëé(I̦u1*¤ÂZRüEwˆWXy ¥Â®Ô D™mX1ÝC%¶No¥/J±’ÕËV;W]ßÞ‡°•,8=Æ=°²  õ ¥”¬Ö–fåÍÓ$J²U¥´šÇ©­f™³ÕHSϪªF•[…ÙŸLŠ'™ÚÊa”ºpŽ©cLzµÀµ<³µÅ _úËÎÞØø@VV©šZe­õ"륪idJåÎë¹H1—Âä Û %§Ž0qCZÕâs–j %H‘¬-ÜéJ…} €5§{îAôôëî Ê1”—‰l‘Rd&õbˆiª¥Tù´æW"”xO`¶°Ö>ŠË7ƒT¨ŠooÛË6Y…x§ÛZl<嬈™7v&Ü6|YV¢ÉeЉ¥Èl¥©µ°º2)?ˆ­µs½°T%§Ç}aX‰{èó…ß³ Æ4Þ1½Aйš&låcUU—NW#)ãÕkµ‰›­á‰ÕvKVOèo] ´°®#Lo­„výõDV|‚L4ñ4(ht$èV‹L©„†Ò[¡>Mãm§¬‰–§Úz‰sÆJA£ ŸRZxÁj„äé3pfÛOdRJ ˜•¬õÍ}¹UL l€”;’ài£våL܉­Âô° Š1Ò¡e“©Jf­…¦Í£–2Œ´%°Õš8¦ŸAH·¡¾Ô‡ª¢;>M S°5Ló4ƒ¾Ï ^(o­L>ÿö·¿uøŽGAÝL9 p$¶²Öõ ‹±†94tÛø†Àÿìg?ëOÀLú€Qt¯±.3¤‘Mb%VâÊø‹†‰×åŽy攢¼’òLoÕn«T½ðL&ÏJú~¡¬ªr‚…”r'bE¼O#¾{3sVüUq°fhEž£Þȶ”ÏÐÊ$BÁªÈAaꢵL\GbµLðJȬª”àeuAз%@Z™x;ë®D¶Ö4Yü˜¶4¢FJôÒg$€IÙlÖÈ@nFB*7^}·J n˪¬Â»‘m[2ÝËÂ< ÖLð#õ µ¶R™¨ºÂ×ÒÙK±Jœ&ª¶ò¥—7¿¾Íà\R)7‰áe…l¸*b†•Ðã׿cª ìMð3µ1z7zÊÊ)iTyÄ}µ®ÙËÓAl…¾²&!Ãë¸g*Û<¤–' XÚp-ø 9˜°CÉæO©c€Qµp!µÈà¶ùØ*a«ä&Ï“ mùKùÉj…ýdÚØ<7óóQHÖkGƒoë*`µ¶d¨—•¦#t4‱{¬JðÀ„‡U.ðJDGëDU5vYŒ¸ÆçSVØrài ó¬)À—%«$7+•§Uʪ$½T@¶ª+tv†é«%À€ÎS­çâ…„ÝMÈR6aÃÈÒpMV‰¬¬‚>+²¶&ˆ³²Š|²å@Ó°ÛšS!¥U0TXS¤ZAìý¡l¯÷ëý¯_¹™(e;¦- [[¤.Él;‚1èì*¯e]‚I/3ÃŽÓØ¾‹êå¶s°6 Ô:¸rdÄÄo<¬ èm}(ôÊʶQ;Èf–e%û¡…Q1ÏTVôjY}î‚ }ÐæÄ+Ü…Ø*iøÌU‘U«c%R”ð¶ÞC†dx lk:²BíbÔfªÀÔ"<âùéë ¹½ÎhÄ'&g)åHú<·ÍvH_‚¤L¯GJ&ÕâsÛ¶›×7&%7[c ò'„Ùê.Û„ô^9X(Ô¨•˜†ÞJ³ZsV¯ À§<^7›*k­0R;Ú”V£&« cáÑWh~¤hN¤¾£ n<«± „²ÕrÃÀ ÝvbJ ™¬- Qµd ]8 4ám â«Êsš¶¹5¼”¼ZȦ:è<öDZ²#íÌH¸Cv0ÛL)pgè<È?ìõ®JïÜ+¥{Ñ kÄoknó°µ Ô–U…¯»™tãˆRÚÖÔ NŸs¶d"ÿ›T¿BYæ½Iš®Q†dªÂ×òÜžà@r膑ôÄïVçŸNjNw%Ó¯ÐV¨­ O_ÇÎo<ÙÈzQ6 #[-¤ès“enmå9Ó‹%21}<*Û&çLÀ¹§#kÛ0V¤ªºôa€?Ð`¶RÔN6lËĜܚ¶.ÝÒ6¦¬0[kÁÍvþ4p‘¬¬^ÈL˜;cÝ­ ЖÀœU5ƒ5¬¼û¡¶xUô€J[ ˜eñJ:K©ü×ÅkIO£ Õœm­RuiÚ K ú²)HÀÓ4¥ fV Sv Œ Ø`ÆJ`íàp[ë­8‹”U¯Üô¬4zY æ»Û†¬6¬‹×¬ßþëþüŠç£|}U_ÇŒl TÁ"çªlÙºíçYúNP(‹_ È\ “ ­°”ÓÁŽ9Mæ•Ãj“Éç–†X)°bˆïŠº.Û&ÏvÛÀÅvÇ”<‘5ek‹L£Wžµ¶ÄÍéËß3Mœ²“Â@÷P¥dógÁP/QkJ€IdÇDz•Å>¬Âµ4 `3½¿0]r7’³BØê1‡œãŸ!LR nj÷Ä•ã…òRĵf%«°³Ð°Â\˳T 0$Àì=q“XE“ø¤¨‚Eg‘ 0i€¶rîËI™Æª/AL[ÐÅVT˜¸“²]÷ZØŒFpnÚ¶pU¹ÙâU™ L†z¶d)á F™¬‹µ6r<½Fj¿ü€N”°ÖOeêñ= 8 <#µ”‘;ûú\“¨JúæCÜa0@½`…Ķª(½7@½ZiJ©ê'tåVþ4²4n4Üd <€[+M2dþ‘ÍŒq…=¹Lâ×1²r‘@åñëJµJš*¸Í&ÀÄ<&Ìöÿí©a…”øÚqÀÄ+±%³v´d¶<ÃV3ÐÄØ †#Ð3ÇÛÂ"M¦ÔKÄ·¶µú„øs#Ò ~c3pÔw<&ƈÛö|}Œ¤i’ø‚€´Â‚Ië5> ¦oÀ[z½D8.Ò«Ü’žF9¦Zk¸Zb[ÓKШOO€aYž)­¶B¶Ÿå0ÒÏ~YŒBŒ5¥Fxá6Žé=T˜ƒ€­duQÛ§ÏÓtvÙ.`ȧÖ@nø°5.ˆ‹Äu¿—znU*¦¦z¥ÙTf#ë­ ö†¼¬ï‰è]~†ñã¥bàÉg‡ÒI&V‚Ôª„ Ö42óôÖŽCÎ!ñÜ|ðVJÝ­ ‹RYñ·m]_²™)9,(mAS¹-ÃþŒÎí¥{Ÿš-Yë.$ ²Âñ®E;>ë²òHYŒ,OØ c†!¦ŸÓÔ¥V…)ÔJÅ÷(ñÎ(•^µUJ•”¦OÀ$?ç^¼’ŽIo+h(k‘ÞÖ›&ƪœF lµ:Ô<#iÔú’)Aš°e¶4; LÓë þ@¶Šçê£T¯ºäI“­”ÚnFy,øPÖk…ªê•8“&q( ÌS‰Iô¶ôœ­H‘!Fʇ:q:ÀÇðV)Ę̭†¼£¥i6UÆØâU‰€†-++¬Š¦i­ =2þ²B “ Ð…0”Š—bÒÑ€‚`ÙLxš0™°õI‰¯]<ì>q2j'ãï,᪻"‡ ¨Uó¡·*‘j«VªòÌ-†‰é ¬l‘•›UÔ˪;M]º(٪匧Œä™ÀŠ·” —Åt Î|”çƒ'ȹUª¾¹Y…T¶éÝÆëÇ“a-¬”°d¶< PJ•­BL²ø[t–^HdÏ"3¨ê ™`ÔŠÆ£¶ª¬H+ÀZ !•#br8ÿ3 6ÕXg‘®U.Е#F•8}ÞÛNäÐè™ôòeb5Sµ²±r!ÛÙCâkÔÀHáºUyÕÊZÅ&!PBó[stiM+AÚŠ dù䙃- ª¬azŽ=ŽL¤¤)0E‡…ñò­:ÿ,e¤³ ÊœdŽñóÞÚ¡34œOÎ}·Â²j›Ù0iÊêÅMùy*7[ó ¬„„aÛ9ÛÂþWd»"·´S ÛšÖ¹Ž§ï>þVЭ…áRÁ´‚ Rß”‡ÆÃg+¥–U蟂x©â¶=粅ƨÄõ­Q#u´xbz^.ÄTgèûG)M^¡@¶ò'«u§ ë«Êï¸4ý¨¸6ç €F­všªµ-r³Ê b¸ƒØRÒ#1BJyÔïWšLÈâ³"6›ƒDâ+?.÷–ZgbÛœ'ý~±19`8dbÛ&i0&ºS4RzŒ­1lï€gÂuq®Kª¸ö§œ¿«)2kΘfˆ‰´6 ºŸ¡cþ­”â)k°œU­EUNaÍg…¹Õ¥ŽR¢ùÓÃåÞ^U3`d­X¶r ŒIY•m†€ ÑW T.•ÌŠÉn+«d†×à|úÈD|U¶«ºÉ³P¦‘‚ 0+)GîÔ°#då™–ªª1`®]Ö³î®`)<@©¶oK²fˆá磤Kk[©žió×&ÓÎ÷!ç´*YšÎUÊç˜Zøö š }™W¢–›”µ.J+¥5+€æ¼¾ÉÒu±ÚªÕ"F!\£”}Ä0BŠ9e×h;ÃL”¸7#‹ÄÐ÷Cµ•Ãm)Ôs##¨VŠ_Ö¶±ÆvQ#[z¸0Ì|”¬Š¡!‰eóW. ph Àb c÷tX¥A欋³pè[¦¹ƒœËLo% Ï*[¼lÑ.Ê_íx4ýÜ‘ê¹XMÒ‘ª©À7pkÛœ10ÍŒ´Õ½ìkä¬0‘ziMÉŠˆ·åótîP52U½Öϧ ¯÷ëÇåܤhjÇVáZôÁ—"ð¾YUYu±kÙͬõÚÉæF™‡µ@zˆ94†>Ì¿— S%kÏc®ªÃêÕUä_!H4-YñÀùFm&i.é$•Ù”ês·"éUñ’5 Òÿr…%Ë¡l½`«ròÐ|‘²uáÖ„˜H2ž"ÀYìÖhðkÑ#i”Øf{‹ÎãÏ\ VµB':=î«Ü‰”È’‰ÊY d[2Øq€²V[>4@ó +Á$°½Ý^ŸØJb`QyØš¹“οTïn·¡D¶áS2$³Ï$pc»lµŽŸÆ ¸ÈdãI%hHξh¬xJ%x«m·T«ÁdYõ%îë©1Z Ï™ q&¾³˜tždÖnž !‘ÂÖw™rB%M1d¶cªÊG¶7s]*<=î…çÜœ˜af|Ý‘…Z|¥¾ ®Ùÿû™!Kl•JS-F/n|žµ)9»a+hˆmM¢„žØjK€±l© È âŽÐYÉv 4ẚ™ST»’RdÄe›V*²Ûs ÊÆÈc«ªÁ(¬¹QÚŠ&d‹‡tif¤¨<ÆjkÅs€½¨+CVÂUH™líÆÓJ–•­rL˜ ,+‚4£JYÅ cŒAFoÛãfˆY ¬¤ÈÇjr§+kU’•ôùUX/è#“!m3¡aÕµÈÚZ á]2¤F ¹Z€²1Xù-¨må ŸX9«ôiê^–ƒÀ#w"'AödiÎ@¿úÕ¯På*Ëù ©ÝS)%õÃצ¶²™´ªºó#çp&CO¢^°ë 7*ìô¶b€¹væáFìyäÚÜO…ª9!а€Ó¯» Ícµ ¡„[¼äøp¥LHc+¤0Bíð‡TåÖxå £Ê×e…p>;².Uõæ5^M»%CàÞqÎR+ò” P67ŒmV˜g-R_þx—LæýîÓekøn¿¿éI†ÉJ-¤džgk-A4 ‡L8(ilUaž²”¹…wbAœm>VUx%ÖŽ¿Ù0VÙ¬NýdíŠ nßÛ.Ó`J¡©F¶æ±%€;&à2 XI%«£a²ÊÁÊ–²U!ŒLFi‹Ä„žÈx«B‘€@ZU ŒÇW®‰æ`²êDÇ÷þÐMÓߌ Iùl´.€lOv ÚÕÝ‹T ²[²å&â5ÍÖö4¾‡Âèž!+aI&*Ñk™ \}‘‰­…yÞºs®4²J5gYzÙªVn›2Æv©äja-dÍ6ÁS,+êN  ÃeåP»@)W3©¤*JäÙ†RE2¸*€ ’¦l…R¶fÓ½Zk˜Àý÷åœØšÉЄjiØVØöÐ״縳¨…³"£五B–'€)´ëKï–žEÖ)\i?Ú0”M%¥m²ª&‘%@µ—»?Ý/Ù)üëA-:K¶¾s¤º“ÊMÂJèÂJÇ”xJ©NZ¶FcÛ–¬F°¦ÅØâÝeçÂdÂC&Õ¥Q Û«[BÆÔˆX(DbD‡jB|)dÙdu—ŠeßÄFsÇ—Å߉Nw`z[ÊÎ^m²NT!ž€ÌV¶Ÿ›”¨ÜJæ°dUe^U%iÈ”‹'Ùö93g$1ÀÝXï^¹­j¶›A– S6ÀGªÛàœy¼±¥€}wLâôçä÷OÂV‚œ{å”cÈ®äËKeÔ˜¬Èh(m;c‚d&H«òΫ0¦mß ÍŒ'ƒóÉ„ “ƒ,CY[`†m§¡TKàŒ>° ¬¯U&•9eL€Rô˜¤jÄMÔE6ÐTù<³ùgâ°çß(àÕªð = 5€úçÐãe²N¬ÄÄ9ú"m“aŠ4¦c mÍoÍ'½u­a² ­0%2^G¿q6 CßJŸX•”¾€R#Ok¯ˆlGHLf+ð4¶­²Zà³’µ†©E Œ©K&øªˆSZ+LF€éÞ6¨07 ™TC"µ#HL/¤œ—;Kør_>ºxå^ÀûÕ°’ºÈbÜüÜ4ůš{4Û i´³ÎLªzÃó4É|¬z»àœ›ÙŸ ûéYÖR¹v1¡ÄÖ¡d¹!a…x+,š¿É ¦1[ÛèQß²Vo/óR½ó<;ŽÚçaâoÏóI¬oƒiÄgçêÒ¹Ú6 ‡l˜úl}vµZ¸­•¸QÍpé/ïÞsÙŽCÃÓmcÔvÒ†lød²l}TmSÚÖ ¨½°U^à1õÒ¥-âmÅ-z½Q•#;²BÊ4úÖ Ëa«‹¶MûÃZKñ„¹Uµ-’¡m“XõµV%+%Æ(˜ô˃@b:]¸^„2X9ÒÌKi*‹±Ør¶ºIbµ”VOª«È“ÞéaRµP¾v·â,…òž©O\-dýâëZ§Ç7ƒ- ˜³!óiBh€uWޱpaKo­`‹±„»¸ZJg´}?˜çiR¡,€'VX»ÖÄÈR”·§—Ђ¦çrÚÜkl¶n’-”UØvXUš¬€fž!½Â†Éðôx?Ç;Âù[cì°Ÿÿûßgdm”m3ºçŽþtAºòâžžR —Qî›E7µ#M@3ž²Rœó—e™PâHVX¶Ö‰á<[W˳ J ‹¯i+8 ‹Z×·5)€íHV‰¸Ñx·0¶záãªhz<¥6Y…Õ*Ç줶BŠg%esÈŽF&ÇÛŠžK?·A°i÷«å‰ñ­Mk•Âóð÷@çÙöL|ÿÖ ¦¼ÝÎRŠ2™­€}AÈ*IܨÚQ"“IÁY™ÙgS*Y+O¼rÛl[›_*IY ç°•² ½„-¾“ÒYÁxJµº¸ÕªFÚÒ$¶rëý_¿õÈ“5€vD¿ˆiuQ¢Ë'®<¥mãQ6ö¬âUij*ÙÖ4‚+Œ-¬Š(ËÒ”2‰Þ¶ãÞ|ä†gcêžåi”÷Br†y*qW4ä€ÉÍvJ¶ý-K?~lÉ8qk¤*Ñxñé°€Žm ”TµÃJq@X#Y±óV•¬Tx<2¦ñ`½¸Y¥JØ`KfïÖibZÉj”Ûg¯Ü(Ó$Fvp%낱UŽÓ¨ÍÓ{ÛÅRbˆ½HUákaU+¥u}aJ©É´ðЙ ÄsÈ&ÁÈR–‚ó†¦räu:­uì…4^O¶ÜTi¯‘Ë¢Ö;27L2Y]6an¢Qe¯ÇY0 €¦¯ ‹¥ïrl°µ³(„µd°µÂú¶eÞGIU«rC Yk†yZÍ–a²üÉên‹‡1dE&);^#@$1ÏúÚÈ:2F”%r#`X ÃZ”ÅÀ@žÝ†3Àšg'ê°LfH¼¾“C½à¦}‚xzž3Q‚‘ñV$FRv]ólª40±i”8>œ,s«­ŠÚ#;/ÐåçL¦£î@+0s-êE †9XEU²€¬•žOæðN‡ĘdJª¥”²&¶ OùáMP(ÅV¤¯/Ÿ¬ÌLc;Y¼T ^ël™».½(a¼10{lÕâM[…HzkL©Vsà«JcÛOü|rè=ð¢#ã+[&V‘ØV—N†‰Ü½ñÁ4Mâ0øÃêaåxê®;‘€;Ø@dš\Ìm‹çû¢iPÍðHà À6¦ÿíŽRJ臓y æ)•y‡ae»Ã+QHÌ_Š2ƒ¯ÄHpÑHø.Eùó 4àÐÜv¨b}:0¡QÒ)dŶHåôZGfˆ±@Ç[1#³²ít©–'½”o[$™³¦ÀÈœ šG9¼kDz;­Ü„*Ñx‘•ÓïG)Fj+ÀP(Ä[ëþä‘ùǧñèu‡‘Z}&é “ôŽ$«µ¬­ ·ÿk†ü+'Æ’!' `Š”÷ôç·ÛæTHPvyúÝ0°N 'n­)}W-ËdÃÓ`ºÕ.m#5¶ÚÏ­£6«@%p?õÕ;ÿf¨V!%™­”m}1c•—8˜&¥ÂÊ­ñ­x@h—¦ª 1blµÐI3ìU‘RÜ:ó¶1¶¯iÞ% ¬ó¤T"êH4sŒ½FÀ+lÎx)2!Kc XEÓÒËÚZáŽl[£ú¶*¯o)«8FW<[Ý»=ë4“ú:FZñÌ#á&·MÏ0Æx›A©iµL|~;#æõzÍjG/6$}c#a-bxºˆ ‚2¦Y u,[ªÖÙ`u±í’½$þª’¸*>d° ]lY™‡²¦”Ûž—ÞVÜêó…ï6lÉR*)l}(¬YÑàéµã†4¤í)»!h")…^”eñ4«`«‹TŒ,†³óbLM­Rº[ÍŒçìfâWŽ ñµh#­LªuÃj‰ ðH)˜ çc[mÓ†!‹0°Û ë‹Äl’ÆH Å“s ¾ͰB&bÎøe• ÙÄœaV‰ÈV²¹UN¹Z%bLʲÅ0ÌÄ 'Xk  ,U¶Ø…gÒ«Nc›sÊ é‘ ÏV ¶ºö@²™dÓPŠ4¾—Ÿs¯ƃNð¬‚ùp󮞼GFRÊÃlëÞ–• ТIÊÂøp©+<ÏYV)Œ­Õ6 øÕþ¾¨eÔ1¼’ôÕ¶j$˜ôwÿyN,Å™ÞcêÛÀýÐdëC*+EF³«[y2zHúZ#Ç|Îl»1ο¨¸Uq7,¨s·v›YXaµ­R ÍÚ—ˆ­ 8$Þ7w3µf×¢óÛfbí<JíØR•c6'²+–ZAV˜^Íj›n«¯ƒP RʳB6~†Í™ ²9)çÞ§œËÂlsV› óF*Ec+ðãeãµäSÒàoÝëç–# 7’ÙŽ@p¥H”(šFVØ0|êB k•ÝØÛÆKÀÈjõº#µîh†|d ‚ú¶•5¦@¼& P ß6}&ÈÒW6’PKÐÚfÓ…C3ÞJÏ3Æy‘ÂÑzXºÇÊË¶â… >˜ÖÄ4AÎ•ÐØ 3 [< PÓy"‡RÖ¬<·ªíhôpóÀô¶éP›8Ÿü[ÀšI¤ZJÑ`ÊE½êÂS¶Cm‡­ª Ì­¯  ÖT¥”˜'Fy¼Ž}SRj­×ºr¼iz—ÜH@UͰSŽÀÇÌ‚xÑq¬4¥Ö—¶*dX ¥€­ø@}'ÞÀ€ ä<ÛÊmc8ÓÔ@º™”°ŸL4ºXmoéYˆÃÝ€.ËRJMO)œ±±Kaz|}ùÔ¢¾”4ls†‰ Zm í’-¦*[A,¸™*UʪzW­H ÙlU¬d¯åëAµÅÚVXÓù×bb²‚Œ³Á¤„ŽJ0xø9†-rÝSÚÒX9TÒï&'J££¬ƒ×ˆ~&f ±Í'@PwYLsƶø¬2i†šÊv(Ý1ùtðÆóq®‹*†Y5,RÊ Ðg“ÈRZ}f™Èò§ì"E7çÆà‰˜@UÌŸ[¸Á€æ³U+„l…»–æŒî8V<“²yZw4VMB ¤D¸IÖ«d1Wõú0ÉV oHÓ2DV+Ä÷tð>Ý®ÎJOC KÈ”­) UV¡l¥FVc[“ÕîúC!ÅgCŽ¡¯$‚ªøÓð´µÂÍC–yÀÈdÈJèÙ6¹5@Hõ‚ù˜ô7ª”3IÖ µ  “UUG`zX¬°;,Û´ûl ço•¥_6’Ò${ á~<4X­[9tX†M˜¦^1Íi•ª{ŒÚ #%âÍ ­Õ`ÂYˆ Œ“¥´"¥V‘Ê×ûÏB‘²)ȹ,[󾄫¾Äaqo9%ã±*ÕH ¬ªâÉh\;ä_j­Éh¬d3¡Äðé\x&m›“^ÔÈ–Æ:Ð01Y•bâ°ÚÙú"0üanü¥`dL&;xÿQ–Žui …¶VJ)¶Ä§£C¥G® H0e)J]¬‰kGY Sá5­E½d1 ÛV2€¡,±PnÝIÃ4µk[µ‚  [Y²Jlc¶ÍÛZ(DfB&`×à)gE: 0U%ÀõŠ©)|ýŽOþÝ’Z‘ž)2±b4êN*W›!&e`¬@IÆßºƒÀ sÛT6Fz}kT—VzåBª¦i*ñ›‡ª5šÏëõŽñ©©Â%ó¬dºÔÂýcv n óu”š²±ñJ`ï$1}¶ù¤ÏG#z¼Ð ÎÜg­CµJ€‚U¶ôªxbÜ0HOÜqbÄmx&§I€!£ÑÚº*1Œ)¬Ýõ8Waë·gz€@k) 7 !‘}e‘‰Ê @ƵZ·àÉàĪZ£FM¹ƒ¨¶ÉßÊí(Þo)7£V]¤šçªÎÒ5$†²QÓã‘akå P»RiêõäëK#ª²&Ž±Ú M¥6F¤5‡R‘4sšP ”·Z[ó21·½ã`ºgµîI2é‘‘ÁRÍ ªµÕ%¸ªJÙ‹DS «Üd 3Cj!…‡;ÀHÍReÏ9ïwQC"{W‘fÛYJ<@ÆV¬Y†H¶1 J©0V¸í5>‹íœ#Éró\yÚò”ŠLßÌÇëš{Àµ°m@Ƕ ÆHÏŠÞ׫­.Jˆ‘eSb²*K/‹Ä¶ø°µ’&Ÿ É#R‹U…³©doN—P#b)çê¶‚Ìv­?ÌüÖ¿*yÐHUyê•^ðÄ*ºIdzä¦Lœ2«­Õ²Z«Z;U<‘”4”B‰Ë¤‡_½ï“¢˜€ª<•¨…P;ÎÊöv8w•Y³)¡´-`åîGáø=rV4¶j9ÇpÎÜJÌ!R! Dme‘ME¯cgOS^4C@%‡Ê¤a\fVVµB¡UÖª¶h‹If8[¹5a²;™¡-@£» —MßH†OÆC (iêØu5v#Y¥*„ù‹¶d1[æR¶i0‹|¤Ê’I‘ǶÃñyg¥/ ÅÁA"+<=Þ“cœK#$“gǰ•Œ`€R¡ŸgRü­M‹¶Ba8‡îD—øLÚv!ñ•à3)…Ĉ¶ˆƒQ èydÉ8(œ m¶JNåý8ï5Ø@˜ŒC[…ümÄõÚf°š/è;—lµ@)+ŸL¬šbå€-¡)Ì,…¹³ëŸ£,çµk€fS…'¶ ²0-œ¡­ãeñ¬š­ù?˜Ó [ME&ž•ógÅÓäBïb1½N‘€T퀷ì”Yiá÷$¨ªPU}­"O`&Ð#YÝÒsŠ:ZUýÏÂRÇ÷†¾•Ø=K""ÓHhTа"]N>p?h*±¦áÓ[{'sSÛœ¶9«úÝ9rAÖy1j1Ög$À®PÉž`]ºÃp%ªè…,2žfðwåÖH> dcp€É6ŒÂ©YO§;C2úæg"k~ŒUkÍœ©Pßæ·úaâoÅë]¢y–0!¨JV—áâÿ#Es P¨\ha¼×äœ9–c¤lv+»nçŽÈ"§”â`›ƒ,¦HkdW¾‡UæñÖX-X»n™!ÒÔV˶XE¼5&1ì"Fª¶§·…[ D3'«†€LØ–ê=!¸§9—“i‘ÆôJ``ÎHaÊË\¶ki»Qm…T®0¼ª|d¯ôºW5½­”­.ª Fl«ŠU>Vl¥¿ÄyEUQ €= ºØάï«Ã>3(ÛöÜ¿ÔeKì% ÀdÖ:®»²Ât.†kQm‡RKÌD–¦;©;² Ù<€msoÉùeèéO ˆ³Õ±BzUÂVи[ÊF2ÈMÊa)1×ò¼?LÊâ Te ÐŒ©ŠïKY·æ D`ÒÃÊ…î²M(«„T#!oõ9æ³—l-âK¥,ŨWn×ø8 U³.×2«4ÊsÀ˜€¸¯)‚îÙc‚ÉhŽÍoµ­—Ôdibi¬ôHV°Ù`±×U '¶)Û"aþE¼ªîÓðZˆi»wV%[wx2 ÃîÈ[¡#¥í5>oNþ¹Y¹E&~~ÙX2ÛΕgµ·Ïi$€¾BL Y3 +ùàÖÇå}áJ²ðçÛ‡º3ÙÂÚͶià]ÊÄ“åNæ–¾ÞEþéçÐ#­•Ô·t6šU5J,Å3™T o@[Ñ0€ªZ¸DÑ¿4G¸y3ÒØJ5ƒÀ-:éú¶Æ?É©=½ß?lcV%²L8èˆlûÈée‹L@\‰U•µ8 î“êÌO±%à úHã+a…¡é'´ÖA W˜g$>óãu¿³d<¥úvè7¹®ˆ 18ÈÀ“Ä, &%¸%æ€$°6\_LYmÍÃDªX(%4³U`ð²™´f‹$hM¹1nó×·¿’ct•®‹FGÛ®ÑÃJXÙ–µ%P‹YkµÏ›1F¨mN ­µ1²âãiÒä–^mƒÅ[ù[‰ Dµ<-`+j`"c:]½0 ÙYlk-¼Û\ŽU¶Zš)YÁ]æ?lÝÑ’l9‘¬ácÖwƒñ˜ ¼ivF<[&ZÃÖ ÕwáÁ-e†øZH•=3Ýß`è½Ä[z?!¤øWÒŠ!&‰É`)œߟë i[*$Jqý>w>òí9™nmá~„ïý°ƒ¨ÅØêØ UÁúŠÊÉÊz½zYÎVm‰ 0ô¥²•$ƒ…Ž 3!ëG¬­ñ˜°2In@cl%kžÛ•3¯M- {è,xq9OÈ\y©SBO\ ¾*YÁc†“:ªZck$ÌÚ%PÅ@ @d×B—œ­¢l-Xa8Ó%b>#iò_Ù$dls¨Ê–Õ0=œ³U`ê[ájïŸ"=Jd@zkQ¡+"†®FÖ%™F¢¦¶̳Q ¤D]”ÀÍÙI1¶(i’åoµ¥7€·ÑêɦT‹W›IúÌãóá<€¶uÔ.½ÚÊ £‹UÙH¶ªdsCòAVÙ@Œ­©Ff2±m÷ã»ÝÑè™g¢Q€F£A¿ ÕÒÃmÉs‡i1FÂá[ôùÜI±ê>+§t¯¼vʽÈ|:)¬™ó îMþ?Ø+EßÁSí'¢­¨uÃ0ˆ>óD’á+Ñ®*n}_HÑM63™È#E ´â“欄CÊ­™µ×XXPÆ+‡5’jž0çþÄKL)Õ˯;|ƽÑÀVú~c3a;g€‰ YkçR2po”°¦)+¤Ô4½G |G Zï8¥ˆKY6<™¶Hzæâm§ÖV­¬U#…•;81=e[n×é“} á¦8p#朕•O˜hìúR ß´]RV¤Üä&º#ËZ1 i¥ÄÑþŠÉl€Üæ:ÒH),Ô’ÁéeÛ&öŽÙ"mµö¼D UÉ¶Ý žKµô¢,†¿í§ë÷eVžY­›#lënµ0+^#å•D†‘uTÁ«Êw«$ÍIV-F_J[š&1Œì…‘ÂÛ&V Ôq¼­ Ç„9+a’CÎe JªBö©Qxʲž1Á|l ^ø”°T9¤q.½¤ð¿üíoÓC3:îõÎÚŠ¬P®l'´…¥ªb•¯m]«R’>1¥mó¶ñJªª¾cä 7¦‡­P/«B)‘çs|¿¤”xÞ”ý€©+%o¨¾.²ÄÈž–Qy)%âö?HÕ¹-À¡;—ÍO¼Uà­•§sn-uµŸ×"½•UæðJ0¶ú6ÏÈÖZÖJ *}8Xµ(U!=NçèÕZ•µî€B¡Dx:b&øµCvÿYÙRp˜&AÝ­”j­Z(¿­ÎA`b‚•`ðjiP W[ %¶}„Âe­ÂÇLV ‡øÌmu “1'« þ–~^`UuDΙXkJ%¦*@dð’s¾h8(ìÔ4•`üí«ŸaǯœØü•cÜž5+©.Àð‰ß¦â&8HͶ¦« ïÓGf[*C++&@üœ•„Ì|äm{îP*ÌÁµŽÃÊ¡B¤)éÒ¶²¢ iæ #ùLÚR4•Ûºd[cà†,C[2ÛF*…©…­{°Òw-׿·wUV̘ ã\=‹€‰mÝëxmN£z Œÿ?ÅÌñ ­pÎë>gnæi›3¥€›Ä-˜£Ül²ô0[[g‡ßZÛT©åƒÒX+)Ei[6%†¾±d<Í•¦mYÊ&l%nHJÀ‚­ýÕðj1"C&"&x³¿_çÌךI•Ù7šdHw½HúÜ|!øô5ƒñ€0 œ,ìz9p£lN]h´ð=µ²x ½ÚF²UUÔEjâå“m—¦ÊV$°¬ a<[áÒÃf‹™>’!P4AYÉm{du(e­0} L\Ö‘{jøRÊe #à:f¥<Þ6Ù;dV4ó [KUbÍg&¶®H£À`Ï¥’x­)u쀵®êÇðªPU@PŠ6CnT6>Y<àPÊ×é·ïÏkÿ[ húùª¼~‚O¯DY/üÞµF– î¶R°Kaú°T%Õ{eû>ßÎ…ÌÍ6š°•eÛ¥ ÔŠ™2`ോaˤãNj«V¬û|0f2J¶˜VêÜȯ¿þ ‘ÂÚ“N—); Óæ€3ÊÞ(”iÜ`!Ûœ~÷=#Ãäo5 YžÖ@¼U‰‰@1Ãk|Jâ1¦ŸssNÐÛ ¦B%éÎÁš …_•BŸ"#›9°F•(¤¬o$F„Uɘ3ý½%U€5¾-L,*¬{þ×ïótb”ϰ^UÁ®Ñª¼ ekaT·wF¹¡ã+ )µ°MC#…,’¦rí0yÆ“Ùz•¥’å)+ªÊж•$ÞCi›æùvlL¿ù½C6Œ5óÆH¿‘¤0 tœ9Ã^H¶²N¡µHTpÀðTî¾Ö`ÑðdøÚYE²0˜Ô7Py½à½¬4U_~Þï Úò(uTÂG;€C3d…/Ôv¢e%² 1|RZÛ²‚Ù`LnÉøÍ­’™Ä+oZ%ù4­íô@wøÞP¨ˆä@l‹ge c`ú¶۠™XJ/Û1@S½`Î {Iúê¨vÇ—Õ¢Ù¤þùD¶†_CÁGmwΧ±3ÄËöÇ-`z]Od%mém ˜>Æ*èoݹ([ï5[«{&èõÜ2±]J¹ `Á¤šx³!Õ&²…+4€°õˆ»áªa  G*¯PÊV À)%4²¥ïÚñ°Ö]q[‚[úÙÔÈàáZlaU d·•Rˆ©]×óö­uãU¢  µT5ÉÎX A†k±OJµ ™cëÝ+Å_À&u×®©`ñ•œ±ñ¢y I³,ÿªxj'\µvªlÓr“BnTË_(·nK&0d«JÓöÔܨ{n†Á¹ë™ï¬ÐíÑä‰ab+R2ðÞpX iˆ¶^0´’Ákˆ1»“Ê—=mî§•9|«Ž°/‡ýë_€,™ZÙ[q0Õ)g”*GJ)´.2OcåCÌ9lÀ©i;«È†yIøÌÛÒ ËÍêz›“IÝUº˜d¿ôçz¥Ö‘Ï”d]ì{ü¦Õ½+†ŒæßGi}REæHJ%@Ým»jÓë%S9 P*ÏT«ªmŒµ->ç_þüç?“bKäem…Q“K0¶‚ã•äÓ”V?óÜ‚K¡á —µÊæ‚·4mëR÷Ö”²"+Ì¢cW%[$–*^²ï2L%)sFÎ¥ ¨Öqô‚éÐñ‘ôVdp:…@Vo—éëe”"L\tEpWÚ‹âöl¥D…€yö[f>ѬhxYÏ…˜@Ø2ì¡Àd5LµÖ;Ý磞†ÀŸÁ4µˆ)Å­«.Å c[}·àéûÄAÖºU”€ÚRp]¶v²>{xغÚ˜«õ:"ã ´®Pk£&Pxý~S;Ý^i)ÑÚ´å×þür¶Á'¥•¦sµ¾“3!À4 @#”;ïÿüÏÿôg’¶JLIƒ¦ŽV[ú +é)¨Õ.ý³\§ó¶‰@4F0!#®¯ð¶‘J(ù¬ ˆ‘ÄUÁ”øÊÕjc¤æÌ “¿lMž¾_ 1…B«ÂÖZÀÊ‘¢.Vd¸ñඬ ÂùÀYÑhä¿`—¸îùhaK&hlû{YY|§€ñ^0@Ö“¢„R—l2

]Ô*lU•U%dR™¼2X[ªWˆ~ówå ­²uÌÖZdžé#Õv •÷Q"*9ï…¤—ÌÇLˆ J]ÉY¤˜ XU$ (9¹?ýéOGû½,y‰Ó†f]± ²4t?·|õg¥¤ªVg¾uŸZ2VLL¦ÜUvÚ •H $†F9=ICÓÏmš2¤Ç—ÂÛÖÓ´5J\w|Ñ¢F@)@‰ÖuGÚ: …¤3ùëeÍ xÙüMkηW8MU‰a]ÊZ‘VŒèGòôLUJ¶›ÏÊZU>ž }ÇiYA†§ùdˆñÖY—@v†¸c ÓÀJ¬"7?a¼éÁ¥O¦ug‰´æ$p^˜¦7MvÓÞnŸYtLì~ ß¶&émï\Rœá”AFßV Ƴ!m›¶†]—B«mn™¯o²j¥¸a¸1¹=Ï—i”#7R%¶ô†9ëE†ÕÖ«• ´’mx ”*Y)q=βZd*¯û¬´Ã¯öŽöÛ·^n×þÆ…Z­çˆÆÂôÂÓ÷³Í¶Q­³šƒÊJVN6žaC¦±-8¼`ÙLx2AÒPnrY'ía!eMT¥£–’ÞY8‰]rJUJ­5F–s Ð$¶Ù1¥jÚœ ˜4†Ádw¢™twž=¥è‘Ö¢ÙÊ´•jìCGnzSØVÖVÐø Ë~Ú|'i0ö1¯$M3XE…+÷ð'÷ýÆV«°5nÛœVí„ÂnÆjË,lNµUa´k›¡UmzÊãþýR’jlŒBë9ö}ÐyÊfˆŒ¸å“ÿ”ë"‹!«#ÒÖê®°¨–™5 ™l3XÉʪ•…eaÑðcl¥hüêï~jQ‰5©–3F !Ÿ Ã#•Ó`ÒÀZUá{¥inþÍVp€Û¶4°•ÀÖZ ãe^SæÆÐ…„½rÄiÞr©¦j0š&Ic+Ö¨¦¥ØEš rJÛw‚©¯Ò¿ÿif²¢á™Ó÷uÝãnZX-¥ XÓHëe£æLÏiņ‚fU+‰iû6ªPI>*äg¦ûµÎ§ÛP›Æq”wLÚyÊÂÍ/ ðÏ!™mŒ-1zi àÍ£…mnÞðÄÖÙÊr¶¥‰”E*ìk*çüš-E°al55@¼•2GÖ¶Ž<µhHü¹:Hd#-GZàÖNÐC¤Á'S(ˆ;3^ÔC#k[ûJ˜ ùÔÕäI#+‰Yáióý ª=|ÆúVU< ¨ÒÈ3OY©F*µñA™CÛÖÚ튇çcžœÜ¶*¡Iõ¾¦çI©HµHX-s!›ÏR˜‚À»ŒÂÆèÉæ‰1¶rÛcT’9̧aJÑçC_;å4H%p }mkÃS&®ÕVµËߊÉ-µ.×㜮¼FüEgÇÜþ¿½´¶ÍÚüïÿú¦KðÊ”óLðd°^xØÊö=>~ShÑÊÏŠGò‘ÍD¶*þ>Æ4¶¬ð§ý Û¬…Vt$17b‚ý8aB=¾^[+}1nx'ê>ûû¶ÆN“[½l) lU M‘% JG+špžm1 cèE…ÀĘb €±ÎÉ:Âeù ‘½êýw­ðM%[!A}s€if{;|–.Ć@Uô=_Œ°®„LØjÈ*J¬»™ ñýÊ…Ô”½.Þ ì‘¢ì†Év¼Âf»Ú³$Àsð;SÇ{‚úv¤HÙq:Å›"載 ˆ™èˆ0"°¾xa;†Øqg!³e´å 3ªêrzÿ›¤¬*A`Ers">“a`Y+½˜3™-½·y“çÙÁç7"­vZ»L]d+±íRΘž8L[µË@÷H Ìg†›²: 1¦Ù”S L&u‘ýªác‚TÞoóF…nµ€mÚUΊrW‰¨i'€|Ì©‹mâÏ åG‚J‰¬ß :dÖ˜,‹VÌJ TKVEZ¢¯c%d¾k0΋¦¯ª^È”¶²BÇks.¢îß>ç?‘Öñ•X™¨ê9%Дg˜X Xd’ƒ-çFŠ©OÎøRdYý7ÈÍšUó¨¢ge[Êí4çÛˆÒÀR‚¸ Ào`$OÛ¦²šó–žñ`Y÷Vi×S³U‹OÐÁj‘MüèU;]Þaò¯°10 ™ÔŽÀ¨j6`[)[ʵ iõMA +€5Êʺ,ÞÖÊ3PÖGBmå!]BÕÖˆawR£¬ª‚Éò¤ñVw¼ÚæO?B†¶"Mó$ã&0KÑÛÿ1ÑîUb}Îáj™××éÌÙ¶ŽùÊF¦çÐòƒAVIÈ ÊîÒô‚›¹¾¢•¹ `bUð9ê÷ÛF‹dVæuimK¹¦°rÛÙRŠÜø []  Dên«Pùjkmx<¼¨WMm;@\#)·å,…V[d†¶ªÚ¦ÇTB`a0¸÷Ymæx…°”ÂæÜŸdºùZLc+(Õ†êeK£o¿áÕƒ¾R˜> +¯D Ph™äœILç%àÙ1ɪýïõúýöV7§’Ê%VSõÔnX¶Ö­mu·5˜À슪e…™“Áô¶ ÓÌ™o¼ÜF^ƒÏ’Ï”¶cÖE!]ʨ¿‰€iJÁ²RΈ|Gè‡&€¤¤±žNß c• nÇlJ<àïWÙ¥éÞC'êºUªaY¶øÝ§”ðáJfò•cê¨D¡*Û"œ¿’ÆÊ*+« ËÞ>g©µ¬B«.ÕÚj¿Õ¶ˆ‘j~d}ñ€Úæä 4€un”¶ F?d4"ga sÂ=¸÷P°p󲞋.ckeÕ%ØÂzõåO›¥Âe #å, V5¼Ù&Ð:¦É‡L*,Ëžç{!xA#› ©¬ºKm[ßw$ÙJ\‘¬«ÅTÈ“–Eš‡UWšg¯MF êneËATÂ3l¥÷ÔJ#››FÊó„·}‡Q[‹Âf€«ÍÓÚlil»( Z«Ö 0eY³©ÅH!› ®…”°µÊJeÒÚVVÐ#µ¦DƒÙ’ýò—¿ü% ºÊºJ$]"kFmÉ€pÀ¢û­*ž£\UÎ@½R ÒÚo!yvB%x+%ÞŸ‘[†uéTM•3M}mipS®°­–ÅÓ[ëÎ'mnm›2Y©Æ€ñ‚ØV-FfEÜ”#•K àu&è8§Á½|LÃ×IÕ•œŸ£¶akª6’ráVYQÒÓ¼¦’ù¨/žÒV–‰HèÙURy+g¡mg¡¿÷¤³dËÙhàL6XÃdU/ž¶‚Ni¥©W‚iôÈÞÀ„åç`÷=Q‹Ï ²ÙÖ7±-P#úLš¼Ö 7$ÁRpž˜%\ë² má†!°´jz3Ÿ¯'¤_J9£ûô_àÜqªM·­E¿²˜I,ʪõ)æÆV¶ ¥:# Ò³ííÒ—Ì–³UÖg¿Óám3y{‘5$·x̵ÿ|ºiÞ<ønIGz/6[ú4ÖøÜjšmõÊ#%rpRŒ{SK â<,š­BkÇDÖ³Ú€ٛƟž#²­ ç‘45Â(OoE•þmÊ“&>L– @¿6+Ì4d4àPäIà•?J0¢±_ÜØZÛºV¶ÖÆp¦±2·J"*¿"[ñÄ‘aÛ^-Ï+s“#¹‘aðu×QJ•m AJÛx[±ÉÛ¾Ì+S• ITe‹ÔÔT>‘£õÙÜIÍ \Êa‘™dk­œ@d²5[T!ûÙŠäÀSTpîN¤Yቯño•2²*Ÿ²FêÞæ™3eÁ°ÒK™0[næä–Þ¦pÇwÕlñ9àeaú|néç‹TJ»œ3§±@ lò˜iÁöRÕt< 2: ÜÀf yõ÷«þœüF$Hð¡¾8&A…|[«¬™­Â jõÂSÚZñÈ>¶pkzšâÔß PŽ8¿zyÛV@Ô%YÃÄÐdKc£Ú6'æVBƒ'€…rk3´äÉêJþã•k‚Y?†æY_nŽfk g +I†™sd/p]ølæLê•?¦Q‘áÀ¢* Ü1)yî0Ö~®i 7Œ’&´n< [M‰ì—¿þõ¯z¹,/«­Uƒ:å… õaãšÃ6“dª”kit Û´õÝáó£)UJ˜àPí¶œ‰ñ­²;[šÖ&‘úŠøn-^G­;lckM‰!6då ³3Úâ‹‘¶™ÍÖ é9÷»¬™Ã|+$9[]Bn0¥Ô[§l†[zŽÓV¶‡Èa· #¥8«u€mÎV!Å_dˆôÔ\ZM n¶}-ÚjD °J†a’mÎõ’%#N–mJ%”°,þ­R‚ßœ¶)š3½-0†R£«:|>€u9ùÔVW¥hÎ<+Á$Cšs8ÙJòq§å÷×z2M»–Sy·ª =Sú<<2>7)<aBFJ kÛx[€²¦­x ÈÍjK ˜Š>+@w©H€Àaó¯Ä*«:Po ”3XkÀ‹.#ŨJ°HiU%…Ÿ ¼,ÌÍX•lJ[¶ ¥4:ŽßP"Vž¾#dlfbl- x[%¶•·mÍ$^Ój¥>9Ó¹h»3r†‘MY΀ñÚJ•%H,%`]Ku©ÊJP ±­ Y e{4”øLjQ¡Oˆº1µ]uÊFBVr¬ŸÏ³©\ˆY30‡i"­Ý[Ue‘ñ¥š¹Ôpz2àVE¬±U`"ém­RÂx†è™xLŽv+>šª0d=YbJ|> U5²y¬=ŽÞÃ=²®.=™àÃä5Ô ŸmJ+†Fx~µ%SÈð¶ÍIÆÊÐÚ“u.«øz|&TNCß0pí&ÎG•”©èÅÆ€W.»Q‘4µƒ™ˆ4^P:¬±ñ9 ƒ-½Ƙþ(bÛHÂêÞ2?³Þ [¥šV—& àC2½t)kåÓÃÅÓ`€ªðmQy¿t"mÉÜèi¬ñYÕ.sJÑÌVé¼ o«„I©†ÁH@¡K&«‘*)}1( TUa<ÛHX#†ã¦5•^­‘ùÔ(Ÿqx®»mg¬{sb¾~çt¢É‰ñ¶™ õYëæi¤.Dª‡e›m†01k!ekŒ K)쥢Éè3M3ø_BŒ´5!+AI V'ˆ$.l‘ `$Y7Ó¶ËÑÑ R†Oß m³ê­›UcÔ®¯ªp&°ZšÆ°ŽÓUTB)J5’F ²Á”JÙFÍ9Ðí0Ö…›Àˆa€ƒ•¬*Ÿ5‚ |ågÙldpdâu3+dWJ [9HÕnYJ|¤µZþjE¶ÖL€3Ç÷ÓšmžMG¦´]÷píhRª¢|{á× çä£õ»…c€á3ß=‘5ràª>÷ QOs7`Œ”Rp™ƒT‘2™€ñŸ&¯0r&ùÌ ²…½N9´UÞ© üs<©¬v=#<=2šš‰•L̳,¥0ya«mJ[˜§ ÓÂÚ¥õª“•U%ë½µU%Û?²#®ÖéˆÍ¼^x¸_É”ˆŽÔ½1tl¤&©é è /l9¶é‘³%†E…­µ:ÓÜ›´nŒ4ey2—uê#ýÊdñ®ŽX4‰,R¯dx2½€­Kª!oѲۦ¯Ê¹ºÞdª(‘VšEYµÌ…’Êñ¥ô²­˜w6ιRp½šyå¶œ[…^<Eéb(š-žf˜½ÀtYz²¹UÂÁg!¥•¦w¸OJžˆ³"°]YÁÙj+›ì&??•ënE:‚ï+†Î Z«j~[>RHžÖމ!H\Ó<‘5Ê<“p‡u¢ù…ÊÎÁÊo’ ]L#ÒT%+0}¬*a‹)T‰aY#a*”µEî°î#:xåZ…ÔZ¥lY]úÞÚl lakcx¶<™Àš2·¶¥‡½Q¥|1 ·w¬1RZy7*C@pJ0E²s†{ šÌmVzQêè¾@-Û¬€Ó}N°ªÄ >ÿÀ E9R·Ð¥à›µ!ºÓ|k)â]"M‡Q\™+øç?ÿ™&}YX¸M§]—¾Œˆ›ÄJlZ퉬Ä0~°ÖîýÞüçeÒOz¤îÔŸŠôuᙕ.«Ú¬ÙÔÒ ­²¢³G†„§±Â|ªvóbrHß h$Û=à]Zí¦'ƒ*s8[ÇÐ ÓÀfè @µ²Í¬ÑŽƒR¥m¶4=>)ØZßN×äîP`dµîñe΄^¬dÌ1V“3†[[&Êm€Ä3cT!é5‚ñÕv„œ]&[…ôñV[%ýù!Yk“À¢^UÙ2µÓ]i«„Æ©1zÅ[‘VUÇî±·Ò 8(q†„û¢‰±(Édã9¾F²¹µ¥ìZÞª†g›Iz†ɹßÅ—RÂPjg d’gúÆÓÝð¬ÆJé®ê¥6’Ò`ÂÁl)a Ç ·Íªm­­¶ü­:ð@ç%€YYi¬"ç^ƒÍ–•,F700OÓ 1“î$)kÛ$L_;Reéš;ÅYò9¦_²±ÕòÑW Ðl€VøLùýyÙ{˜[úã~õï]Ê¿ZÏL÷’­²j+±¶Î 0ObøLüý6¤a0óÉmžÚ&nÛÀVµ3'Àˆaµ4ZüûßÿÆw9ç n$V‹GWE‰t« 1Íc¥ñt\޳àm ­us® [ªx -ð¶øÈ¶ ¥´ö¦õÁ³^UÁ”4Â‡ŽžCcàiL¥D0))»Àçð!¶m 8ÒV”¢1OÎ01«}ƒÑ“ `¡¶”@¯(Ry¶VaË6CwëDY!Y9—¨£m-†•ïDdHU‚~%Hبøæiµ]-$s¤µ©d¶HQÓJ¦ižÙ"Hâ3Ç}жBÖ<ãm‘MX [zŒ¾>ž.„¦ïy¤ K`­œhk¶µC¬×ò,­™“¥´n`‚æð9+yq)¤l†@[² ª Ò*4º‡øŒ 7U)‡%èØIñÜ\QÓ6›vÑ ¶]o¼@•¨¼ªÖH†Úq¦¼À·âÓÅbròLF ÒšÌZyþ­Jš³!k*Yáôm¥[«”|ÅÏjÏ(yæß<ñ3q¢fî !8à{¬»ÞšJycùdeU›ÿ9,h˜ó<Ø»ÚùH…­Äªv([Mä™ÀÚ Jda²Þ1 ålcëV²Ú:žƒ=öšÒ# S/%V‚”ÒW£x_ ýVŠw:" … ³VXÇ&¬5F´’­°xcKYe­R]T½¤š³u©*Ûõ +ÇD¦•·b’I>¶BUλR ±‘Σ½wh<†B6P£J`€˜Õš–ÒQVà»äœùH%L‚7æNwX¡v•·¦Z)å"Ͳñ•èt 3èÅCœyc¯6g©lñ…@Ju¬‘•ìÌq5+…µ(K&h<â®Ý0^¹f«Q}›<1FJØêÛDɬ ­LdJl)5͹Z«hTY…¶}*'°µ¶)‘§þ2áª0 f2^J»îðT~cžR½F•¬)s¡Pj÷ ›-% ›Noír¶­„gnNÊp­eéù]”TžYꕉ€RInJ!U6Ö4”µø¦LÏÁxV½ˆ+·Ö¯ª '9Håi…µ+e+h)cdùûßÿÎ×ßÇϤÂ1d½¸æ”ùÞÄÃ4¹l3U¨ ˜’^ÊêT"Z&F@‘'%Ï 9DV"KVTnK)•2lµ@£&€}/ô/}*D’oV3Á”MÆ'ç^”þªVX#Uë@WøùšÖÚ0˜4V%U43¨<†>qݽE²UÌ‘µ®JJ”¯,’¶2´å ÚâõbÕ$æd‚F„ñýdp$¦Û¶ÍvœRnÕÖW·UÑHGSV Üp#Y…mµ0ÁÜŒ$Ûû@–aáÎe¯°ù­‹¬¬1sÀí¼ö µƒe[¥œÚê÷ åæ‘0F c%îà1¶4Ö<¥Û1jcæ€é4e9Ð88†,+)ÛºÃÞ<+IiݤB©Ê7¡l#å6AÃh$8Æð&ƒ îyq€à‰Õú`î“X +¾gt"7‰¿M>ß]É^r[]zÕɘaLgTE,ÊÚ¶Ù—í\áiUlw"£ÖŽßkÚã{ ™*‡òÁN,EÏ#C*lÝ¥š³±;‹5“¶9üò믿æ(ÊÂ*8v*¼2Aƒð—8K§Ú4 ‘dÐÁ M#” Y¢oÀ¿÷P ð®lÛÆÃRÑJ€l÷ ;š™’ {ÎMŠg†Êa'gí¼?¬TYpw¢„ØÛÈAÐËÂ0”'óÎøaCIc†3ú½åR¯~ƒCCZ•HõèñZpÛ'̪ eÓd[¡Õo€æQÒ̺`Ô:²òzÊÎÎ÷·°¶Æ#0I‘#%Ø×1ÆÓGö5Ñј ÎÜ<@)'Âh¡Äuñ„óWÒy ÒXɬùp¨œ#”ÀH&²Äi09§ùLs·Yß±J‰küÛ'çÌë‹!ÓB4ù­;ÿN°Û(ËDIãɶÄÙ:—ÀÀsð8(=Ga?üúNɳ.ôÌ1d®àü”/#e»¨„ƒ ^ÖÖ„˜øa…AªSïodç ¨bUdåDFu¤³À"sÌûNÂ<­ S4I/^U² cÅÿþ÷¿à;ÛF´5?ЄŽÀœÀV¨eÕ¹Èƶ¬*b[¶VKƜɭøüMaß0þÀF™†Þ¹jdå B]ÔR6‰•i%ê6Âøz•ð§aØ#iÜ3ÒebXÉr`÷vÁÈjó$¶%P’^ð)ã)ÃÄ‚LÇÄf£¯©cÖÂ*»i•¬Üåä4U×kà.if‚³•^»d”›r«. h %©¢m`liH‘à 1ËIô8º4˜0A¼rẠ)¥ª­&0óÛxe·Ž°’2d/Ò–ÕÜð•X›-O6%ÉÊqÌY¤,E¦)@Ê*Rò¥:8†›,F”=W&EÀdƒ5 %Oà{æàkH³©*Çgˆœù8QåË"zyv|„SKÙöšZE—ÓªJ‹x«ãÔ(Ìg `k$ *…¶Õ"Å|€RÛ„Ê•4’l©Æ6[ ¹Ñˆ<ÕÒ7††až¥&fHùζ©ÒÐgÛª—ÁÓ3òJØöad(ïh4Jš¡{–Z¯f¶Ö%óZ—Úç<É8ˆ;Âù~Æ7aUÖĦ:WóýÃ0Ÿd|¸…ù”ôx² Ó¯PªÙâÕ:~¤5@‰õ;#²‡»¦UÙÒÈöNšä”ÿíoúq_:trtNkŸÓIŒ(ÕpR bs¿¬¥6«­½ ì³á»8F 3œË¸ÃJìüfÐÂÁºÙ›ÿü„›Uwg*b$ `¶ÂÍ`ee0 s*'°:cŸy²0’Œ¹móÈæ<Ùq¼Q‰• 5¥dC"× ¨ÅàyæŸÆº^4æT‚ìAT’gc›\P ÊÄV…•tuV>ÄÊ»(@T"uŠ¿½’!ÓBUQφ—ª¶§/»#HµÅ¼µÇîk®JJÇþ±)ÌÍð™L h'å RV…HJ%­«²bd­M—€«­ ÊŸ^Ê(&Ókb%BJàéú—ÇÐÇKZDXôò+I&S¶eãó‚W+…4ž­Ž(ÛZEzÙ¶·É¹®~³QRU'MÏ“Ì*5°í\­1VænÞúÎ\GJdn&˜43,E`+%X‰ú*l zªê%ëH²R0¶4V¤•F•ÚÖ®ÂRô‰¬z }*' L0†X¡F5åSÈ"[s  7 SÄôP¤hVnë8IJÓïûçU$FHå8‘ÃªÂØödil}‘Ê" àVÿö]Dƒá(Lf .RYa:i<Û3Ö}dNa»#TKVäV9F#bÓZaÙHXÀùÆ´pFJ‰vWõyÐðNö‡¨‡~ʸL¸Fi`Ý™+箽îH†ÈRMh Ô×únGæ ׂg˜&g[¡œ igZL)GØC”¢)ËŠF40p-?O3>†sÀJl[­I€úršî Pض.1Fm#É6amit±6’TÀ„`´ó›I¤,iæÆfôDZmÉð¶bO¹Z+†‰‡Nã&'00ž@ÔÝ¡ô"[HÁ–F/‚4¥¬ÈOb[«e·Áެ°Û¦¬2>eÛ:&°"Oï{m1¯gURl‡éaäæwKe¥*7LÏý燉-…ñ s¶À¹¨c%kQ‰-¨ÊÖý>•ÊÕšÇcÈjQ¹µG)µ.BJDZˆ´ÕÈv/ ¬*Ù²Í&…QhÛüš6›òF"èÕÚg“¸»U˜£ é}FÊ10ÙÈÍ)Û;Sk+Y3̼ZÃã;Ùn€ln•w=ÿ¦æ¶ùl˜¦#! Ì „J…lsRæuoL@³ †õâãs®B-TÐËbô­5ÜÕZá{ÆXùÐÄ‚CzWŸÉñù× išœ’@ªÚ†WkB«À[é­“É*·Æ$K ãAQFÒ À+"´s¶UÑFTn6óÃ]µŽIŒ© )Œg+[Ç45’4’RX*½T¤õ¸ÜOuë”l«M K žÙ6­³Ø²µšÙx4tÏ÷…ůQ)`k‡Ò‹‰-ñ&¬P#]ˆµÊÓV¡Tï€-qA#à S/[²7îÅ~y¥—²ê¶-F­ÈÈi`€³˜ ")uÙ½JeKã!*'ÈSJ¦o¥lÝ"«Í\¶*üËZeÛZÓì®*d"ª"ø¤Õ–oå`TXÊ[ªÜï°’@ä†i8(1 7$ÆVÀRÍi‹§Ç$¨6ž¡€‰ñ …0VXIšÖds΄F(§RZý˜ äæDÆ ¨WcÛz;,=lõŒ2ïŒîA fæô¶²lãaƒõYˆa +YêeÛøÀ­9´%” Ù9÷ÖÕ_ +bẴ°ÒL0Óv«”¶3g’ìíH†Ëšº–>òM›€Ø–° J«,˜ë[ L1}€ÌröÈlÉlMέß+0Äùôr†Éøw|ÊÎ +têúªš Ÿ¡ïÀÌÍ`uLþ>­¬¤",+8÷VàYͤl+^ÀÚÁ·Û¹ŸFʪEµëûj ?ž^¡mΑ¶¬¬üªÞH‰•7á|ðÂV”cË„¦IÚâ1ͯLSÀ²p%óŒ¬pÙ†d¢¤­µm‰m…vôJ“õž[i< þ eëÕ*c%á¶Ä…-aª¤¬õ@jZ!±l3˜æÐë¤QÃWÞ—*¼•,Y…ýbÀ­X¡œ´70±B ÕpM•‘rÛîJǽ']‘‘UíÔÚþòÇ?þ‘…´á:g—nmt:ÙLaÀ–2»4V&¥â ôÞe%ÛitïR0†¶RÎ&¨; ÖnŒf¶UÕT&Ü ¬Ê$BG ±àe`%xA¬ªÚœ^y™·MÙØ0n;&M[æÂ£/àÂ5e¨V4I ¼•¬aC¶¦„sâ>EzJL¡nËS‰vÈ¢©4m°ët–ñõ"ÆÀ¯ÌVSbYi0žl…e5…ûlw´¬Îom`íT½wb+6ÃÓ‰¬Ê™ûf÷sNV¼§HÌœŒX¶’dçþ>JæJ\­#´Íð”"€­˜Úáÿ{-2¡©<Æa뙹Z 0¤ñ¶( 9[é¥èa‚@z‚4R4½`‘UÑ×Q–'’ÎAÌÊÚ^$³Âdº7€U ÿ0O§Ï©0CzâàZž›ª„TØbUÈWÌãÅôr:[b}ФòÑØMÊ’aævÛžãÇ·¥9`6|)Ûåø.A¹¬B“æ´Â^Z%4NGCgÒH°·ºrçÊ:K/KÇ!PuY£²™ß‡|>n‰ZØ[ °å[9@;z) kÄw.@¾¬cv(<¦.î I¦¶¬UÈb¬‰5d¨6ÿHk“DZŸ0çH>FÊÊ… <’L¹ÁlLžFZ5MÓ¨Ví0›0[ÿ~ÛÊ{=Ò3¡oͧ—$±ÿ:Ò,ê^—l­M®#¬Qo/OŒng@ÊÖynáûO~ü Ze• Œð½@£"7+’ÒŠdo*U>û1o÷†Lv›|ެÜVÈ ÈÄ e¥º·”MH ˆ­ôÍOVm&ÃÉ(›Ê„; M­™ge ¨ŠŒY¯²™Ãø&Lðú˜Š Ç Umç‰T"¤Dæ¬àN ·¥èó$Ð׊좜®-%~O‡À"@–­v}³Ý¶ñ~¬Ìc×ËõÕ‚ùJj”f<@¬oíà¶ +s÷[ìmoòNáP™ÌÍ·SÝe•[ñ"༲1õ…Í€´Õ%™-°µ’RÚ‘¥Ïß<ùœÿ#°rìøvõÝò:eD€©GkY3)1 ˆ‰¼ùÏ“¨c 0†Ã$ö´EöCQ­T‡OcTÀ‘øÔ¢éoïzZ) zØÆÆTHLÃS¢É_w2XtVUÖYÑ”¢ ·"Z 7[Ø*®÷ù{¸s©Ò”XÊj[±'Ò0˜lé3±&c%…? ®­7L9 ¶æ/ëžUÁJ 0@oÛšsO FVw£…À̰ßH˜à­µÓÝ‘ÝöLêk=C|?®€î]K˜€yþzhøXkí€RZ7ù±û=@À@M‘µ¦*¥o­›çU˜«Âwl2üéñýÂÀ¹00óá½N “êWÃô«¶VYb«àÉ¡#HÙÖú4{psò¤¡—â€ì~šú¿Bó;O<%†rÇÄX!’FIq†¸¡ªT}ës·U¨âÜÙyC†R$œZa†VŒ•^$SBÀ§ ‘Rð•œ[õšé# ·*ñíLàõ“}ôÌFprÞÚÌVƒ- OÖqªÅWE™>Ÿô:Š· [Óö0­«p(bžYtÒ 9h‘ (IÜ1ë¢ÖÍ€!ܺ"LU½fHYd¼*óô¤hð¶¹ÕѶ×õ\ž ´åou̘ L,(sÀŒŒJ ¼ÂNÍSÈ"Å)¸A,jdZ}mešªnzÕ/Ë@YÊL(‘a«HC[m9À)³ÝYlËZ#­ÌñÚ`$oª®ÚO+¶¢‘ªµ %Ȱªj­‚¾0A£Nc‹ì)p¬\1ÍívÎ.¤leG*ÌŒWå]b[;|…YÙÈÖbÝ'S•ržô²¹Õ7¤#´`­cÜÐlªÜ€WCÌÍ# &k¼nn;@YpÓ—LÀ d‚PÞûi»r ç¤™Išµîy™–¬#tW;—Úé›vÛÿ3•fnµf[Õæq:X–RT•/b* ǯ¾‰­i’É&nþ4H-Ⱦ/˜ÒÊ6±52+8s ‘€üÖ dhÕÑC¯Dk†Üd/OÁØxÙßlxØ32^@'ŠQkn6…¶|úøËf¥üß<²xzÛjd+ª`„Td½bàñçÿŒå `8ëëð¹zwé+nÖdLÆsPÒÝ5ÓÎCÓ(çlmP4ƒ­‘šuÊjaVþ&ßH…¶xÎ0‰ã;×ç_)Afõ«@Y2-:)+zÑx€y:Ž„B©ĶãÃÖbbÛÜ0VRS&;2>sì\wsvÀ¬¤0"1À¶St´RV·DS;k&;o)žRYm<µH)LUæL`Í Êe­akåHM…r>YU;PâÁu´6gÜDc»·Jðž/Ríµ¶Ê®<7+!Å­ ±ºOkÎ4Yð¶Æ`¨í p‘[M3ÁóDz­J„©¤¼þ3zKÙ*ñøè;©•¾ç[¡[êÕ0­˜lŒhHkÇçIÐoÆŒ0”PZeuÁÃ1¶1²€ò¦¦ÊùpènU§øûKÏdµSkëŒA•;aÒ©¥4ZÆÐxúôç%ûþ¢£)ç<• ë÷-L¯ŠÂ²Mskx…a ¬œ^KÃÜ›¡7 œ2ñM~~' xCÊœLðLà `ŸùîwÙXIã]×iùýΩ‹Ù€jÉLƒ f˜¾çµˆd(v ôpß“•°Mp…Ÿ·"f”˜Öu/ÛœRN!Åm<Œ$ˆñNزòvÁ]¸Qế`¸ÖZ`ÚvŠ.¤ÛëÒà&q±ëÛÖ®}SQŒ,g@h!0oÓæ”•¢D Ø…ï`ÆP6€cfnà&'PÛ¶”íëÌP $@,•§±ñlùô¯íȲÊ'gëZK5-Ðg0çJrà†l€|lcl e⦒m$)ØH|Š¿d|”-uL¿ŸV¶ÍÜãKf­lCß÷£$K™¡µÍ$sÖµíDdyZ¿6ç?3ck*a$&Àz…3Ù+mæ ÐhWpjÎJ Y©lñ€vRÓ``…Öƒ%Ã3I¯Òùô*Ú"Õ"ó¡H¡DxUòÁÔ%úC™ln}®3¯œ9% P X¡H€iKi…×”m%)mk4O†H—‰)eËä“òß0;éÖn™"/Íö$àšõ³±Æ0Ùdb)¶S¯²Wu «Õ·Öúb²¥Â]š=6ΆÇ󧯑•lÊbzZÁ¾2”Û†I¯–ÆÃb¼ªU€¾Vø=cL2«’ÓãûÊæÐºtÒÎN`¥QÕ`Ó—Í™¸ѯJªX @Öo]YÁôʯiO_6[6CÊ ­ÈxÎá}¿kGÀS(߇ S—lcÂÖl‡†­­¸6Ÿ==ÆaÝ¿O¦ßçš6Í”«rŠcñýúଋ<ÿÎX•m×Î"åRfóp Sþ¸Ø¬ª¥É ­¹)!耽E iœeM+¤p÷ÓIÏaîkÙVV-Y†V&¯F Ã!ž˜i«¤èeñ„s¨67……B˜XêKŸÿ´=缂~ã÷«€Çäy™“ód=@ Iì)Kogk?Ü1Û†³……„’Æ®ß v¨1ÂÖ4€'èད)è¨ÖÚ„•ll<¦×îZOúE$ÀVH­)±”ɭȶz!<\•Ï[O¶ÁʼÑY04˜p(|ÑxÌ›Ê*̘­[ „¤©7¤T§@^ãÿúØd˜Ië1½¶|„ò40¾ô糊©µKÐ]S-êXÓU%³v´&¬2ÏÌŠ)ïž“|t䀷mm%9àÕ"¦mÔ«,ž³ «K†² ̵9>HتđÛzQ½ “5O[[g[+lBc¨å$ÃgK±ø€óºg[Y¡{µ¯Sç2^&V‚ ‰mÉ0”¶Z[eñeÓWŽ™OVdç¥ 5mkµí³z[2UÎK ~‚&ìP fª( zpMm+¬µk±UŨ–Æ6Ï~Uμi¤vý&¢Tk*n¾ÃYÁ½lËÒd^—ab¸•†§ŽÊÃ97g+±.xþ‚X(@æ²¢á €”T\ùç%‘ÍŠ-¾¿®†E…•ØÊÂJÝÎçiÎþ 2ÙV]QL3x½=))…øšr¶­;R`¬ÕþtII 7¤*4Øäz9,@à)GèoÂúÒh Ëvp¶¶ ãáŸx˜†gÏ¢©:Zo‘•ƒ‘4õ¯ ®|×›¾Èl¥l‰3„ù#c½xZ¥tWU#[%ES í™äVSšxk8ñ-úV«µvmµVKʶ* sUhµ¥ç?[/ÔZ ‘È_ oë§ìù4­ y,n §4R¦{Ø0YuëÒ¶ƒ¼2Û®®/møGÀM¸«dL´Û#…XÊÃÂsóàl³%Û19à ›9òü×±5Ðüª¼$>ÕJÑ‹ÌSª"«.j4% +ô% /e˼WQI˜¬·ãHƒ¡@¯Yx>mÍ&« o%f®\Óf“M `2ïJõÜJU{þg@³¨LA5óíRôV —Evï–/™áRÖÆ·ÁVJ9¸UʳO)E lEJk‡±eèWòùob´–Jcebë‘Ãu϶Q¥T²Q‘â½8µæLßA†ëeë„ÂR€T‘3f3Ähá]¡i»B½XáPJ¡U`hDÀ)üÍ¥Ïg¼Â¾1óDMBæåÃð‰il‘Reë"%0l›¿1h+[»•„ åÝmY|a›í)»Ó’MY-e³¹Š4àcqÿcJ‡ô›v%„dÖu¤4Xâ9¼¶uÉP÷4Æ›&†àãA+ɳ÷6±Ú•ÔPå½I©™X•`˜?,qÙ CFSJ¹íîO)•@Ö¶Èït?=Œ”RÆ8r}Ùi´ãÏÁ*¤lë½êíåã¼}üB–­C1gÒ ¨j‹WEÓél ½l¥Dn%Ö‚Ÿ‘F2ƒH¯Ü„W¯øN$…•KÁ#0™7*½aªÂ r°æ eø¬¸¥ä†»4µÍ ¼:õåÎÍ3j1@W‘Ø!Ï”÷ FjÑÓéé ºó £5ÒíY™$Vh«‹,=C¼y¦i*-ÜÀm­mul’¦U¾-7²VþÀ iòL cnVÊdp7–†³^L:Ž*X áVb‘CkÍÐmilã‘·èT) ç¦i|)|g”‚¥„I¬`¼à¬ÑNVV WB)VÎxæ a8}‰ì‰ã“Íp-$ÏV³h›CØ:ŸÞ®Æk&FÂû˜›¡ÿ&’§@c•eE)òéBò‘Õ·.˜u©Jy…RdÈ”•ØzÜlj-Ûñ1Jl‘d‘‰{g¤YÑH;²Ô‹†¿”ô•U¶vUå9 Ûˆ±6sVRôݧÔúfk[*±me]2ÞV¨íêÚv‡È³â‘c*·Vè8á4Äd:š¦ïÂe‘s”+4pGæ\jÃÛ¦±*©]z3t- ɼvñž¬ð fõL3ä 0lé­ï1kÔT9§OÙ`Ö@óø[Y]ºsV3ÁÃZÃR§ì¶³Ja˜[».n9Ó`¬¾ü¼PŽäSyb[@4üIýóŸÿ´iûì =4Yh€¬øš|Zâ³ ÐpSkËM-1Ò¶˜8Ò*([euôë)@“§)ѱ‘²¶Öõ{™Ý…”hÎøºÓ Mâ1Ù®*þÚ|¾> )ðµ~S1™ð^3CÓ`åÕô%Èç­ÅcØjæé×麼mfsl9äsç=ߤ¾¿`%Mo`úx«Âl[u¤/bèñ¶ª-×4²’Ú׳r×ÎX|í?²×°.ÖæDΜð‚ƒ›1[) BÛ·ðLsO„çOS$¬ª±s˜-1ÜVªKvöj•¸|ó䃧Óý…ƒ@­ªFâP`ÈêK©<œÌ*«3½•æ q?9T^ SV¡`^2¦ídøaÛ>_^3át¥£áÉ„.daël2áKPIb‘¦SXE—€ç¿ÇÄ[UIi è À«…â›Á*eíö @Sªç¹5˜¾²}eJ¸5¿UU2dÃs“EbŒAvs¿ýŒŠ _îÌY¡µ“æÖMÎàÓéê®EY hË [@ÈÖK¹kO;l…ÍY_&%²Ä&¶×ìch<È£ïD”ª¬7I¬&”Z€lq¼¾¡l äÙ“âf›ƒ,[$¦™5°,† QVÉ0=»lEciju±òu‘¥m­™ÇX ~%0>·°­¾ ¬ôý R9%OcÓ¤· ʦ½Î=ÔH•ld¸íÒqèÅ”üãjg€ÝO«gJÓ$»ÙJ#j=`K dJ­Ûâ ÃYjÏÈûc+ªò%ãhþÿûßUõµÓCaHß³3a]”ïŒ5êàV¡jcTnÛËÜÙ™ÌVyzš¦rùyjJF̳¾M^ɪ²²6^Ð…: Œlá¶Ì RZg’϶4aS¢BÎ¥ÚÂÌÀ¦-bøÛV®vÙ|ÑHø°òÙj$Ñu7I3¤L†„meØ ôÖ9ˆB«× Bž@AÖä€Èßv¥ ‘@U°µzÕ)µóèÚÒhĹB©Bë kªŸB¯‘µ€îÇxª’¢ß`©X£4‰ñ½–µ ì8L"1¹i­Vߘ¥´ O|'²R»ºZð™‰*˜’›P÷ah ¸s©z‡‘Å×Î*l94Fâ‘¶‰Uy|˜÷beë•Þ<>”†‘ZH)´b§ÄDZñ²ñÊshòJ83‰^ªª&W‹‡ª¬Ü2D® ð‘<—­P;‚ºÀHÑ!…+ò:+› dØq01 ª'xåG6€Lð”Ý@†ÄÎ_ñfS¶ê çYíip#ˆ¡¤i¼æ/˹hKOIà %‰¯k!è€ aäºcøøB¤÷~â™T‹¯Ðâa@;¸ÀLóàs‹´í,Ö -üLÌÀ„&s@8ìµ<ž¶V3Äâ(.Y÷NÔJ¹Iʲ5 \JVk$àÛ‰ ’‘u´â­¢ÖÍÉ“¬…¥nlV5%‘V‚Ln·Ï•«µ&°ö<2­1@Crc ¼£œ ”UØÊ.0p+@¯PÇšÆg¥ÿÖ|¶ÒÀbsã#¥°wµò;5h0©š6F¤µÂmÕÖQaÎRÀOVwºsvY¶dBÊOX÷‰'dÓgE3€ïqÇTb-®ß§5+dõØZ]ÐçÈüPãáÚêb«Q§³EV¸@“KÕbkM­{My6¡*XÅØên£Ü§ÀU@_[”%¶‘b¥ #EC à…v| š*LTÑ(¤©]/yÓ6R µyæ–²-“¶€*åÆÃèe­ <>™ÛÈÓÚx™¼U˜&Œl0Ø´x]z7*ÄY2c»ó–µv¢®ôË# ‡ÂöZžg¡Ê*˜ËVcªj’+9ǵ(‹ì•ãf<—0 >™Uªl½¬”ÜLc1Ï“ %¦¿âñn`+dUm37C—¦<k) FxzCæ k [ûcÆüiØâÕnTJ±ª0Ï£Fn02µ"ÞŠaë&«MP‹˜0>“j‘âüÏ€Ú{“lŽë}S{שMŒ7à¦0\˜¦„Ç ~—ÎqÚªˆÓ7œ ™ª›ÊëÒ·îóÅW“ØÚvn lƒ M8ÞV¡U$À»aÛ¨—­UP¶ºþ°Êñ¶Â{"_)dRéÛÖ/F²&«±B‚°UªòVU#›˜ƒÃ[»Êd9˜„›±åFcÏJ£ŠC² SëhÊøº+IÏÃd”i´ À) ÀB*€Ù´ñÖ§q"7Э¢”,l0YÑÁó©;@cu̺#‹côýNÊvÉÝañ •óŸ§rb+™î›³^bl_V%¼ô†a®œR %W{>á͆OÜé& “š¶Ö|bT U¶ ‰›Y_M…¸GI—Íjž•—eKãÜä‰aà5lk%.«vÀ0R¶²x…ü‘¢RÀox“ XíRÈR”l{îŽ ²¶ôÀÊ¥æ¦)ŸnÆÃ"3¥¦V²”Jl?¦&wÆÏoºÐÏožþïdÍÖ¹1‘……ÄÚ#Ã#­Í<@°l“S¬¦ÖîªB†Rk-E ¯HÑ$`[Ê%ÀyZ‘™#ÑR¢£é9g.›˜&ÆÖ ”YÀÛîCi5R¼”@Z•[õ²*LfÈ—$ ä©„­gÁ§rc%ëiбVX_«@æi=-op+Öñ›ù|ꢜ@¬ È À'ÐižH8Þ #«Š,‹fbë>w4`>da⬜d‘iò¯—•ÌZ­5q—Ö`²„­Me¥×à³y”ÓtÕ5•å† …Bë‚Ǭ#^`ê½K™ßn‘˜úú¹·7CU>†”4]{>­Éà› ô¢1² –e C«r!e+dëNKÑ”Š¡lþZ;&;´Í ©< à¤>zœÇ¤áÈꦩv4²gÐÝFMdUYÆJŸÏNÚ¹[ñî\Ð÷5¢ ¬Ê0@gá“Ûœ¥(90,E“¬³à»bš¿ÖJ´ i0då¶ÄÍÄ)†émé[1b%@C:JÕ•LL™Ø*ÛË©é{(˜ƒÖ: )­ _S&4ÊÝ$†Æ–¸)+rM+¤é¤¶ ä[‹WžÃ¬€4²p­§1¶‘üöO[Äh«ÄjËPÛÓ °? î-­£µ.îÅsÈ­y*yõøF®ïŸþö·¿‘Ê©×Ïè¶²/)dF[ÕÃ)ë䨙æ6AÇ«0e© ò©¶KÁ” MÎÁv?½-}wACŸ³…‘4ÂõY3ïU³%#@ºwäÑ}Cy7ΰ1Þ¦TªD "Û”máÌ®62L&f7ü¥ÿxâWþ¶€ñb&˜yö¥:yœ”’ Ǭ¶gª ïeënÅ‹õª ÷þt¥;x…²°Ö¥­ò&‡ßÈ![Z`XYeÇÉœÒ*”ž4­@%ù/…ÜlÊùø8¸¢LȶVX0fh°Ûùü7³%­déSZ›RÈP»¶¬ê{ÜïËi€!™Ø#ôƒ­iés ÛÑêKà50äþÒ/XI±²ª­þô»£*¡áôÂßdhJ`%”øv£Ĭ0²4Â`µFnZ|%Wr†©Ü6±-2ýËTØx²@%4€¦=šÜ*_S +U”Æv¼3:,¥lZm{C²’߿;—-åRH“s$Y]¬dá•(±6•³ÀEãÀ«Ý#àÙ´ÖºTHI§Ì¹ÙÂÄ&h°zÅïìiÈ:QÛ4aUewÒi¤t”&±ÒpXçSö•I%æàh͓޴”båq€*`ådÈ%OL“Lézs|†¹½æ¦‹ì¶w¶ÕZ»ÛœÉ„ŽsޱbDÛa]¦çÐØV¼­ó4¶Umx]ú·#0.¤†²mg·Ȳ‚‹x/ê¶ên•Ým§Ä+´HÓlÔWÖ‰(•øØ’Á&!nžªÂõ¢É?`Å“ùºëNl½ÒÍVë²?Õ”LtQ R;cä ` z3iÚdV>ô²3„iâ×"Mç’ªH9@æ,eá)ùÀ¦j ‚‚¦hK$n$Ù˜n¸Ü篻(¥0s[¶b$ƹI‘ÕÖŸÈÍ Sjd†ÝpØà¯¶ Uµæ,ðšøJ`ñêa©Z[ðÉÜ °0 \¶÷*ç lù0¡¯ ÆÔ% † ÓŸŽTõEÝV©Lja›ÉVŒT|-JÁÂH>æa÷&u~ÄžsßëX±#ù€Q‹Ô¦=¬¬’ø:)ç%lwMÈ”K½2©NBŸsVý"B)~VÛ­4€Éi€VUî¼Fëþ‚Í€U1áÐ+n~$ÐýÀ›*`m†ñ¶áWÌßYeëÅ™, Fô†`\…”#Þ´žµB³á)«­‹µ®Çù''5Ê„qóNAϧ£)Y­ì÷ø~€‘ñ±rØ5rP‚!îc°ê·ÿ®CÐTR@k½ØÒãéSÂ)åËRÇÜà†·íï %ô¦%¦iH†¯g‡Êp'U¨œL‰”m+@S‹ »FUíã;òçÆJÌV0éþÿ¡Òîÿ–Gò¤ôkí°4îœÆj»Sl`àíkKLYwÓ6OcKi]m†Í™XÖ+¤q<,%l…FÊ?Ïž…U*gYÀ¶*ú&Ab`1Ÿðåδx˜²ÛHŸøMåi%Ð.ðú¯Å<׈ž91ÆÝ- &+|dÅZGέr$f8M$^ÀœáÖ²mÓ ˜¶d^ʳšÛ¨ éBTÓgÒ½åöbLÊõu!=Y À ˆì1ÿú׿ú3@UÖ‚ /ÐÅÖ&v1 ~oµQg d¦÷Ó£Lfë΄¹7Ù¶í~øt3I‰ ´µzÕïIµJö¶7$1’ƒ¾0=O@U]Èla”é+±¦©粬ð²‚s+CV¶€ ¶íÁ4LbÙSù?ר ÑÂ?á!á i¡|[ʶŽ9Á9BV`Ðé(¥ªE&Ò(kŽWnp Æë¤­”ôuL@Œ´"­'+ ¦*¤aœCC¶Á‘L¬ôV)åuÌÖZäo4‘zõ>4 r¾EgàÈ4za?«j­óˆU‘áûS^‰ÂN”yåµHÿãœÌºyvj׎o$7y~00PÞuÛ:éç+Õ;”™¨@Öp²ùb€Ød•¼«ì[R/Œ'ºßKÌc“dEÓ•ÇýûBÖS‹›ü|Àd9àû•%L€gŽ_U˜ Kȳ^ÖÎe$²L¢ò™l)J‘¦1:+ ¤à<ÓŸ²ïóÓ‚RÈZ=VÊEž€T«,O÷Èø,0În{ÚÜF˪¤rþÙ’á­ZœÞwTåɲÖ}až^§ôVáÔÈNݧñ÷<ÛZ»ŠLJ©ªcåVUÓ˜Ž‘ª©-`Ýül ÖîAþd)[ù¤¨c׈4¶B3haõ²5F—# H%uíÏ©ÃVa›†¡£a¥D.y2Ù>³YñeÊ1 Øö¼˜+gŽ7a¤_…aŒ¬êÒ$mùôï i˜à;²ŽH¡JJt!¾4ê•L/k¶°*ÇÑÚ¶š$+«¦‚µ|”Ø @*~ÛÎÕVyŒ'VÕÖÍtH¡„9Ò ¨2žcmHg ”¢wÆ UaÌCƒ¬e[&Êmc´rV©*O%MÈóþþ›£CÖnú˜Ä›Í–3 qzþ;°¾Rü13áàBnÑQÆ7ç ‘ñÉàzY2=ð2È”øS©#gñò’YeB67ü²ùǸŸª¸Ñô8à 2±.r°ty!™”D>•X¥˜÷¼Â•$NŸ,fVÉüeXéÎ-²BLí¦L†Ìó'û’°GIàÑ{K½{@ì#æ³L–§^{úõUÕ7½BJàmQwëÆ“m‹Y$ÛYlsë¬yÒÏ|+i¢‡ªø¶ýÖ« æmm3´òÜ€qÛ 'Óô¸ÁÌ€T`꫊DŽ#á4ÄÑàk”>Ûµ¶ÅŒÌT@& ™?Ûº“å0¾Âq>]‹­Pµõ‡!nÅð«Ìßµ¦sÂLP­I“mâüM²#ÃÞ1¯¢!;;†¸réÕíDx¡ÖZGMme›Öu5ÆM_æ7¤ÉÁ¨ä§9q++³Á+áƒ4 Òq’Qî,iªJL >gU7M)…Ž XTN(GŠ €o˜ ÆGJ YµôRÀŸþþ÷¿K¼-§¸9Jaê¤X 1…-±àÅ1ÓÄdHXÔR P\§3zU&e‚IJ|¤RÖ.qWã‘ÆhË•B0Á;c²îBªG"K£\À14H‚ÏÐßÇÀ@RVAP¿[Híˆñ÷ÂÎ ´9Úê.Æ“iQëœaYQ»ZÐp6sǧٔȎCc«H e0k†e•cxšÄ@‰T]jáJòé~ˆ!+¤f{ó¤h ÓÿØsY†x«.¢*©NižR;Z@ hæÊ[ïŸ9i"3„é­âkpÉlkÔv“«Åàý‚…!¶uúZUarë°H‡­£§P²¾Ädm“ø"«]Ùm™çoÕº×`30RJZ7?F/ÎuÄĬøeë˜@à&6&²ózÊÆÎf½”pŽAÚÒøKG«B¼à3@p?Ÿk%ïUÈ âw0²*¥„(ª¥ÙÆ7?HX4­Õ«Ž×Â…÷ÚÓ0iæK@ÓëѶ— ~õ9œQ¾Á§yá2ðÿÆ4RFm›~ΚI õŒ·žCÞZ˜ÓÑT’É„!²s­¶{@b½•$Oš˜+<‹l­a»’ÄHÀªµT¯ºZd«ÞV¼å²½Æ&Ç×nš®ÚLhÄu:“7›ÔÊaY« ôVn¢Z©–²¦r[qm>‹!›³òXbžœ‰›ÊÚ¶‘l¥Þñò9î_Þ¹‡O›ûÝ’ç™øþX¤ÄÍ`µM¦E†Ä±Â7  o+U Œ7XÎdød½m†Umøú6Fí1’LµoSw«jøkp¤*‰É'l­•Òëm­£µã«•…k¡8ÿG`u²Ç*öÒ—æ"”Ñ,Ö P(ÙG‰-° Ì­p†p[J@V_¢ÃÇguµgÛÚÅŒ—R%øXñu©3ÁýÁ_k¥ú9š R#“äÃA¨ám¯ñ‰¬ª"“iÊpw%‹œÿ…‡Eš|(ùlÅçlÔÓ«%+:Bú¾ïºçôHVM¶{ |Äl‘>–¦î²Ä²n®]&ÓH…)i€é»UÖ¶Ó!•;Tßæé€LÀM[‰-²“Y×—æý¾uø½$9¼k%õÂf6R¿*eÛÀÖHg¹'ûü¼Y9A‡âSI[&˜'%º^d-z”]s…øRù+ñ묵­Iê’Æj;O&5UW¨*sÊÞ J)ʺO % V‹JµªbØ“M“Oµ½<”H«­Ö ËÆ«j¶ ‘·ç#Ê.`¬R‘›ÃÓê®Õß— Ù} æà>ßKKFyŽq‡·"ù·èo†ÝLžÉ*I©„¾.›3A…°u]¸Õe£¶Õ”• ¤ß›@Öÿ"¥JªH/› í7y.?ÆjTå"Æ6«£¸¡ )츅­J¬²·É/Œmd‚ôH‡âЖ “®E ÿ 1MÕ«{oåóô™x²+!cXp¨°-YCj‡o‹­µm<¼ûïËÓ¯=}(2·v–Ó(cêÈg™m;]çbI æŸFv3gku–^aÃôB¹ƒÛ/[•µÛ8 FÝY;¦9¢ìqý~c Õ–›5üfͱŸ,™FÚ…Èž¹˜sÙ=Ëø}«ÚZSªâ! ,´hTâ:Ênþð°…·5[JkåZtõŽVkÙ0¡µÚ¹)‘m[Ê0È&{;Ò5•êB¿_ˆº#Y¤©rU0R»:¡“æ&?oê§ëý²ND@Ÿ[Ø–ÄJc€Žœ¡3š²§ë÷/B:¥±+Ï­Úl‰ÉðÊ+Ä ‘¿íÀpíll3±Tž§mQ/«ûÑT–°u‡ÊÖV¶Ášã80Ò*[G¼ò˜|ð¢¯! ¥ÂȬ¬5ÍD*†¬Áò±Õ n[?D;Qž~EÆžd‘sÆÀRøe›\ C<Àœlg§gë_úô›7M±;±…i’)ó×¥±¹ ©ÄxqµgaÒ¨L4‚}­!iT9]a€¶VšÄ6l…Ö4“ÝžŸ;‘j€À4¶ÂV6le5±Id f.뇱éÑH7)ë15¿ô$ÆÓ梲m­di§ª©0°*wޝœ¦îUqÃk§/ÀXE‡ŠÌ–2c[y¹Á…B¤˜ °UÞTñWrUõ +O@{Q]\VU‚æT[ŠFÊ%Ç#Åþ,Û0pe %Rá-úüŠiæî–LÊ*[‰­,¬#,¤0L„‘’É&ˆA.b2¤‰ÖÂCaØq'³Úê2+Ýa|—éhLFHÑÛ®EÓb:‚mþMþVû:ÔWÉÌÌc¤vo9Þ6 PÕÃmŒž™oE¼mΔ€•Lª-«æ¤7|‰¬³ï¼@&ô ÖÕFÒpözvUH@IDAT= ¸í¬¼{ÙêKy¬jUÑô Âs.˜÷ÔhZeñ•Øê%ÅDV„ñ°*!•É|¼Ô:²­ `q >Þ–ÆåœŸúùÚ×R}ÞV©%GYúìZ§±&KŒ·Æ«re/OF€!h*¾}¸•˜Œ¾’Z·n’s˜+^}˜j¶­ÜD3dïv]ÔÒXÍ#hr£¯Ö}â¨j[J<&€¼óžÛ^/P¯]Î[)“剷ÍAU)­Éné×#X»J¤T Ó û–„1b>ÜÈðE˜ áiÂZ4Y]h0ù„«"P•›, \ªÏƒÒ– ^&‰[× #¦Qå¼Öe‰«µ’µC)âi–襄‘HóˆRze»ŽK,kU›Œ>å˜îæ•nÒM¡©$· a‘- J0ÙpÛMH–s3t]Þ+%¨Kn çÍÁʹ'’¡-=·æ Çwp¤ H©‹ïSÔ®”ª¶€ÃÊVëì@ߘ•T• -s`kG`Hã€mU±µ"ÿóŸÿDZºÚîÇV­ –Ü¥íÚé%…‰¬õ|Y‘UÛ²|ˆE¶Êݧ¾ZLv%¨»-Y<ÙmþùêekÍÙ®õÚ)OÙ•Âouåܲr£,liØæ–`š¶RyZa¤ Ó+̧™¥D)¶@ÙaYL­¶ €ä0P¡5îY³µkjŒúbðÝÒ•|µ?SIÌG;[šfPÞûœ§»Ý€é׈’¾Iòd‹¤iŒŸ³ÐdÛ<õ ×ÅZ «¥áxdùx¼{p%¹mDæÍZ§W$°î\‰Oñ-×"l¥±vä²ÝÞEu°pWùÃôu»:[ÈÞd€Fðdh[—ª`´ oŒw¼µŽ¹%ˆ”­/P‹ö•ÄÈ*éà=MŸYL|Ýu©]%jÓ“uÆuqÆaâ Ól1OÙ¶@$@)Jé K%€Ç kóöõtzU2·Úz@³ZÓz.0«‚)ÄHíJa ßÌnƒ9†z¬¶5BbˆgÕéò„µ€ ¡·b¬#&"«°©¦¯C½r³’í,¶²ª`‚¶0çZÃ(kMp>í9vNpïèÔø,ðp0oì„‘õ£ð‚Aï` £›xÎjy %²’n0O2å9-±­òfHl‹”uØL¬ YJ²è²"“Ť±íqʺÀ!Í`õ!Ô¢ßr0=?@­î~ÇÐ(϶Â÷ªá.AJ bÐ7P`ª5‰#mÍ)*¡‘…E3¶•TÞÚÀ²ºXÓSÆóWâ8RlÅwœ3ž,= ¨K²|¬HVd@Ø6ÐIµjA/˜d.µ©j]Gšôù4X…x‘,ÜZ6%Æ–asælY‰,ÐZ¹©„¦ãž›Ÿ œÏĶ=Jzš•Kå`…}3Z&ÈÍ:V‹ïwk7#/UU¤lUK/+l•ˆ¥h¬øR° 1€æ‘Å·ö°˜ôhh®÷ù:†É¦ñ_§–Å0ÌÙ*N¿ï·e[ëC2.³×O!%l;ˆ aŒòî À¨µ… êp›CƒQÖ4ÏcýD#=Ä9,‡¿¦ü£Þ©Ï/è€,F € à-€1š*¬6ÐØ²ôžš.Z&V¸áMe«–Õ¾|:lÓR …²ƒØ [Ê´RU!YšWõYî8Ÿ ¦ÊémÍ H›³•SÓ4¶Jð‰ÉÖÓ*ò´ ‚¢­•ÌÚ¡Ú*©6«úªÂ랎W‚­”ÁЬ„¾¬­°-K ¼I„ uì%äO†W‚Ä‘©Èp2V¦Of-N¿;^˜¡&šÀ; ÏTI FZu±J5Rç ³zŽÞ XVÐ×Ó0ü«ÂÈÚRƼӎT"ˆµ®$`ÔÌ­ÄR™Ûv JSe•3A¶”.!’gÿ”r÷I?[ñ1lµ^_)˜O-Δ?ñžQŠL(É܃ài²zÉjd%®¶Ó­y,n;«r!KÆV`ëh¶1+±U’³vøp_JVXk[dúÀø&<3Ý©^75-eÝV9L@ï-ŠGÚêXûA¸"'j%‚™é['¢'++…)E© Æ–^À<Éð½°,\J–ŒÕFl¹•Ú$øRÊ‹ü­Óøb´~åŸßÇϪ!¥˜U`šdHVñª2olÙý½ØùÚr6ê¤tŒ:3l [ÁÈö'JµJå³ÕF6Ù+ã¯W¶œ)»kØ 4™ø˜g+ýje=r ˜^ ™XUuËÈj‘”õ…»ÕVHí«M9¦Ö@G#àÆDŒÔZVÊ0éyÖ4ØÃþ·qÈVósè~‚OVÌf€;cŒ4 o>0[Ù&l“27|ÿ„tMñH+“·¯BÎUYa%^eïtb|íˆëˆ4õm¤p)8ÐÌlºöʹ5m‡êºè7Ic3™lXaÎ3i YŒ5šÙâa­{™«ª°U! J–Òv“Ã.Dª·ÑVœâ £@hd€@Ìô¶0A…0F¡£»òd)“¥ô‡O…†žÌTï?_ß½BdÄ9À aÀ:`k€˜ÖÆ&®)7n>@zÀ”r]”¶Ú^ ŸÍVygÔŽÒòr+L` ÐÜ(Ùl¯ÁYú\˺%Yâªtøâµ… Ý·Râ­¶ >ÅßÏB‚ί¼°Fá.@xG"Ai[Ó­kت£’Í–¹#°j[Ê<^ënL;ÁÇåH…é™|µ¬0yÞ¢S%&ƒvºS|‰<—~?VŒïFõ¥çƒœ‰mþš¾ß¶I¬âô¸¯„¦D†É°Ž«¨°i‘ÕcÄ|ÊúÖNࢼóbÎß7ÓoœÎ耘Ý3 z¤ÂÙÖtY/zAßûƒïÆ2Ä VøúZß+mNbåVV²ê¥®°ŽÖkùyÛ7*P‹üÕða"29 DäÜŠÉ$ÐÁ͆ìµl6«”îî*Ãx[XªZx†z•eÎS-}Ú®u†Öfs?ÜŠ”Ýsné» %|È 21ܺ|#¥0¼òSöߟ)2½ܵÀ ­ {z1*Ç[ xµ#áWSGLóÈ*D‹¶xMǧT[9>ežÍ3±Âôf”$Æ0xŸÇqêa²íYÈSn XÌPS·Të”ï½ü•4['³*ñ­Ø1yÚZñæv;Ÿ R” MK&dm#3ì,1Ö‚¬rÀŠ©{[Œ[ÓGÂLY™$¥ ¥zzgÎa¤%LF- P@–¢¬¾i T•'«lWÕïFéa3ç¡îÀzåœL­S(gØ'°Ún$%¶&ðlF Y¬Šg¶xú”YaȦ”m›³ÀÖ¯M7ž¾°R˜~QS’‰¬h°ôxg¤ïѸ4·•ʪ°KhH+½¤Œ·ðÂV„Þš…¬ÚÒT`¼Iuo-e”¦-›‰vHŒ¬”µl‡’u ZÓÐM’Þ*¤Ê¶r 7¤¤š$9çºï2SNÜ–`eØåChí3èDôаM)Uw@ þ<#mYÙn¼R‘Ê [nÓÔKÓÆÀ …" Õ `Â~Þ`X)MÜ–sð fU‰µÎd¯‰FJhþ­bè6dµh¥Av30qµ)cº¸ `KPw+^aÛx+Y£ï{ÏôšºmUd­HâoŸóŸ™Ç„ ^’ª"_=¦l‚×-¾gmµ•í ƒÉ->ܘd¥´¥œÎ×¥ÃJQ6ÉëY•,}ÌLletK”B‰ên x…l‰½]›„²¤hl ªU%µ-C#† Ê_97]¤0°r87J˜ M“m)L…ÚNz;Ÿ –jª™”j€º”b%UÔHùüWžÌ:ÀDUó€Rtü4¶¬ê…± çß#>5O0¤$À±ê V‹©c[k@ ¥”*_ æÙÓ$è\Ú5Lb|ðíNÖk| HV>>s«¼µ£ôd‰Û^Ï…TÈPjI$v|†9c2wFÀ{…hrÈ­Z‚™,‹ÙYpæ±å¹©è™ €çLñÃ4›d0†ƒ­’àÎH ©²Vˆ¶AÛÖ¶VÄùXÉð4Ib¤ÐÝʳyfÎÖƒËæL€ÊoMéaÈ&6*Ò–†UJ ƒc6*`k$»‚Îy§>?ÑçLßA8¬ ‘uôe‚†9ðF†yRnfb[+A]¬ÙZ‹ø^‹µRÈ[a“`jÍ|&˜f¶Ò ©d máÖ”]‚^H†™Ã5LµÜ¤šxæ"òb<ß)ýrO,[G©.!ž¦saTašZ[µÈ\ßÚ1‰Œ·-jãÎá}CdSabJëŽ9CÊLR¶ãaów“0Jã5!ÃÄÖøZ·mÅ,êRyVœ ÿ£'¨ß]ùAµ»LAŸyx'ÅÃ3„1·âü{LºÿˆÆH˜ËbÒ'Ã9Ã?|Ù÷hmKåfÅ;¯Sh‘›µ7mWÝym9ˆdémòé=„cŽîûEF/hœTÞš¾­*‚­·ôó%¨JHyiÝŒªÞašr¶º(þ4ÄJÌìöÞ!ó§D®—í¢¾l1 Ö¨ zL]Åê9+#Á Pw…¶‰MÞ´éÃd@˜Ha” ¡#×7%~΀&².Æ}ü+\ïÙñlíÖ“L [AF´Î6›ûQV»þÙKJV€BVdð çIIˆœm§ HÍNŸø”=7&¥—µÚ¶)ùˆNÑõ¦,ÛŠùÖ·w‹wiLl™À¢K ó)5Ÿu/Vb› †snVíd{š²^*#¹v¤õžæós‡’̪Šf†0Ù:ÖBÓH% 0Þ1Y£+-:f¤æsãÙ„²°µòp+©é²€Ð%• Ó–©ôÅX³¦‰!˜´5‰ðªSÈôLàœ'½2Obš•ÔQVTe¥O@)–ÊÇš_6½¤0 £aô ÐoSµxñ”|‚ƒÈ­I–’¥VV1§ìûÖ±i LÿPάvjx&ë¥V´ w„—T%øKuj³)Ñ è™`t´MÓ Ê*r#€[û £LŒÔ=ÙÄÍÖù3OãC˧i3dBÐ'vùÖdUUî8ægˆlË‹<)ûRBÌ<°íFUR¶™Û†ÏÊG![¯-«V²†O€FªVE ÔFZk‡Ì¤‘V"›&ì°BªB ðŠµ³íàR…¾ó'@fîme•$¨¼-¦ .ðdËÕ`aY…VL¶.Íڟбl²‰ÕJ‘½&×%K¹O&}>™+¡écåŒùËJ‰Ÿa"e©£eø“"9¸€XT»,¦‘0pú5 ¤é&;qM«"‹‘Ý|¶¶”ðÌ)Ó¯¶¦­Ä”ªjj­ÜÊÖZyY%”˜u¬©µX9%1iËÊš25CYÇDö4ã=,†0²gâ†Ì°îÇè{ø°XÐ(myzUà?ýãÿ J}öÏ«S™”~bŸ¾U*e†»©}½;jŸ}»—98dW€”#˜ Œµ‹.kK#Ta(G}§-5³)·}­d©ŽÆdCÆXE-2ß:’­ƒ°^ð}àŸÆÚä¦f8€éI•eU­lŒ72O ~| `kW”O&É`@/G ´N,õFn˜4ŽÐWÌ{R½ÍÃÜ6O@Ôn¸ñ ‡é…âœi0Ö†±J¥ÙšOÝWEæŒR‹õt·JXN‡Õ:²ŸcûœžƒÀÛ6XåĦ*&mâ"fÓæ`Û«eë*Ì_ |ï†-,¸Ù’!P/XJ¬#Ü—  _JIàgK#%ø×âØ}¿%d‘u¡Q[Ö× €Ñ ð‡d¦JÐÌ •Xs¦‡4C©¢dï¼3vL&JêÒ$j „-‡¶p½¬eÕ"&–í†km%î}ЈxæMXíÄ×ïóh6‡5…‰óQOÙ+êÒrÞØéiè‘k™óJr®Ä:>€©u8ÀM-ˆ©v[£ÊÚH˜Ò fÛqxbÈšªk¬Dk@Ôך'Fm[ŒÀ´6@V;ª3í+3OÃk$• Œ\/|7MbÛJòDr3F0YW•U˜’^UÛ ½º˜&I@ÃÍÏ@½ôa4Vz«MÇ¡0i—`JÀS®©¯OßÖÂ)+'`•9“ui$n1V²Íl­p`%óa.4*è«­,&@S/³ÍL_-€™¿½Àª—Zù•…–ÂŒø—j-›pš•d‚§TÛ#F*q·Ê3èÍN¶*Œv”u©‘l¬pó¼%øÆ[ ¦4F_[k%Ö+üœ}íh Œ™»·p'mUÛœÄ0·¶ÙÂÛvðôNÔ‹€¸ÀhÔ¥ÝÒ?R CV#Ê Ó¡dWheXá:Æ+¬$7Û†”]#sâ&RÇN¡ª¬ãt¥kY‘ µ5µ·ß/®„I©?ýíoƒnÓó&uÎ5«$Ð2™õøÝˆ¹­ÏME6.R3$³ÍS{¿x ª*ìHÕ*ßTÊ™¤IOÓÛ†˜o‹ s n’†Ùšæ=¸‘ò‘j` P•Õ¶Q¤VL23ÃVA“&€*ïMµEªeÔ%`ýºî`[²œH¢è gÀÂbQPŒ{K'ÂRÕí•ÉÜÜÜ¥{#ÞËŠ"ÿ&Ô‰Ùf½*ÑBÄ—ŠIœa­Ó`º+WÑ„ô‘3iÈÕÚz{ªŠZÀRýý &s ÌÙ€)5å6¦VŒlGÞô§ ­‚rÙÖ¨Ö°ƒtç}%€ Þª„Uú••BÿÇ_@Õ*¬–˜’IW ¨ªP—RH%ÂÖÊS(¿Üç}8³Þ© O϶-qJåºÔ÷zœEÊ[)M3¯Äбæ#Øf¥0l-2>+zc`J‘ÙZ;T¸” .}‘i'SKÖT<‘Óoù¤ù qÇ[‹^²f®VhÎiZ «l²UËÄoEý’¤0¥iÉšyc¨}µÁêRGšºl%°¤ÊrØZ¥Ä‹©„ &3žÚ•4­ZÊVLb«PžUYµ€ª©• ˆi6²½±Ý€T3ïÚkw:}R‹¶6OZ©±KmòñªÌ᳓Ñ[åEÎR¶‰1gˆo´µÔŒÙÚ R˜d]ˆŽÀZàSÒà­¦Šl6žräĶ €5òq`å­³íáJû©]|Ï¢1Ôþ2íõû¹(Ó4jݵӫ‹ÂgÅ–¤ªøLÂõmxLAP À&«©ùað#Uí2'ØÁ‘Ä¥€’€u9M¸TäRHó”Å/dÓÏJIáf”O†L¦<\m&­K­/ضÖÛÌ{g`JÛ¨ V’^J„ÓHaL¸yš–†Àê˜l­Ý3ÆÍ$ÃX1 Î0’?ðÇmúHCV/]DåÖFmµ«Í£VÅÊÌ\ùY:fÀºÂމ^2=CÎR¶yÎø?O=“Y妪/^Ì-gk3ÄÃ@ä«Çw3 hd= dóÛJ) $h€d1+·•µ6^¬œ ÌèK¦T/©¿ÿþ»ß õ½êÙ‰|ëùóÆoò,ªÐ×i©ÎðžMJ£œB–ILg AöU&0C‡± ¼ˆ·Â‘ám«âvÔ÷ ÉÜeMadŒ@ YLKxÁ„˜@æo=î7à‚LìDÄ id»½€f ÀO¯j%o‹á©÷ƒ3ÆJàïZxv$Ïߪ#säŽMœ¾iYáÃd°Z[OÊÖ]ÁH%À9)ŸÆOtŒm²]d#Áùp”ÃM¸Ôº3AÖ®ìfšs@¿ÁbÈ0  i‘}¦”Ùê%à_=e-ˆ;PÉzÙv'®·ÛN3ž¹øó$¾E­uil[¯–òÆn0ãÝ{ÅÛ #j ¨… t1!Ðë´1”‹Ä×ãóé£ÔÙ„™7XVªP¶TJ˜¡5 ÃTˆ/U¶B[Ó(š­Áò‰‘zgn[‹Þ¢ÜhªUÅiÛSPrÚ#[;‚bµ)‘=ëx[¼°_›Ï©ch2\¶1– 0qŸ ¯¤I¤„Ž,Õš[[Œ-kÅÖÅ£)E™xgìè r4J_y%²&î»h ’^¬Lót"¶9$@îc¤®ÇçÚ»OH… ô¥é#lŒ|VäS#ÛôLƒƒ¦>Vwà;c L6=\¬‹­.ë5HVvL¶sðÁÓX²¦†ok… ü™àêK#g8Œa˜'È3¾•Cž²+L‰#ºI&ðÌU‘a¬0±UÄcÜ|˜Ã1ºÁGÓHÁ1ëÔh@iÌÇåû²!iDx¹IÙö£g‚›aä&^K²Ü¤´˜Rm¯ÓÇMi“R!¬°Ø ¤A2ɦ|·1²…l Þ–}a[GšWI<ý ÜzÒ·u#©[ÃûhXaLgéi*Ä7˜Inõç¼mi€Ì‡}`ù û¶QE#ˇÛß~û uÐýˆ.(“ªß@•HŒ¨À×F¡mCªÂ_öêúj !P[»ôp_.xwA¬pþ¶©++&ó!(0²µËÙ`|d#g›§Fs“EÚZ•Ì –ª;Ÿ°µ¦e•ˆHk˜2,*¸ÁýœXaK¥œ¸>ßAÚŽW%â«"ˆï°Rn ž¦Q»¥Ç´ÚZ×7L9C²Þ-&e­"í(÷ 0]`š5Mö® è+<¦78û'ÞT½Q˜H s«-«Æž'ŸR²mr±ã ˜? q)@mÎy®]|-`|)«ZbVV]8ÃþTFœ?€§Tˆ‰þ5Å£¦o ½:Q$¼¬Z˜¹µF|ôÝl€l>d˜K c]DÞäÏOÊM¦Ê—@7ãaé"Uqíd¥0=‚¦­)\¨%£é +úü³§-q¿îÀ¤D&Aà˜ Ì À[w]°Ižè ræ&ÈZs¨WUpïÀÊY)—}ú)(õºÍ3[zŒš§W+Ãó„‰4²BëºÃÈ6'·¾Ó«59Þ6+[QëÈ ƒ¤äÓHñÌ_­*¤ ïȶó*D˜YS…€ ®êÈFÖ¢¬5Þ:¦*«¾Ä¢™ï­œE ÉÙq@ *´åVUš¶Î‚t(%Ä.Á–MâkvRT;°–%Ö£DÀx@ÒÍ÷tJ5õ0·Ë}þ7~¶ ¯\a-L‹Ü”ÀÈœ(Ï9[X­Á¤0Vã1¬l­þžhŒ&¡Q(0l•z#fó´ÕhÊZ+É9%hM£¤Å̳B)÷cVæ0YÑaë²r‚²ZX þfž­rY2À*[‰‘ ,«d´ªhèád¤{>ÄxV¾a¬”µ#h›C£&SÅg!%’½$1’›µÀ´Í'R‰¦V)ƒ €a·Jg Há‘dÈdFª,78HÎ à£Älµl}×ÑV¹- Äef¾ÖxÁ_ÖÚS†ûD—JO)%2 K1‰ªHk§PÂ\tÆLl)¥ªÒÔËjK¦Ü(mEål$ ˜ &e<JYd8¸m KV®Ýq¼_µƒñªlùtáHßMĶNÁ·;ð*ժʿÖM¢ omÛJÐ Vºg‡Ý* ©”m—V(°ºÂó8”#¥àf^#@¤´ØjdUÕZ‰r €a|bJ[ç ´=¹{F…@7smΧ [|¯Æ:æÍV(;·yF6’,€©ElE-òwä¾rÓŸck ø¢ á#{ýÀ[ô焺cˆßàf{]X‹p[¶•,»*†NÔ‹Ô`ˆдŸ[M­ùKáé ÷ówÀÞ„UɦTKP!`; @6²^˜¨°¾¥b†¹)ác¤’ºx$Í<Óar09œC‚l}:Ÿb€-ϾâªÍ¿vþ’€(¬W&õŠ/ |ÛÌÇ ð”Ú6+¿U4Éúh¯)ñzEO-YÊšJ‰N$[ Wû©Á¹¬u“lZƒ¥Çl1”½{D7ÈÒÀs˜g>­šÒ„ssÏ< i+¤hZab©w†xkírƒë[ ÌŠ (k­¶²H[Ðw†9HÍ9[«‘ð” 7P/…õÂ+¯cÙn«Jß.~¬¨¢™ˆšæÃgú列˜aÛ|<,)Uf~kç†ÔÎ$BI¡Š LÀÁ›ã_ã[¢­5=%,øÓ[+4<ܶãÐìÍ¡!À+Á³Jl«—#4ÈÿøÇ?(ìE5V¸©Ž·q¯ð,ø,zÕvé‘e&ØÕ·Ÿè¯ðzÙ ØÚÖ¨ÁšóJ΂ßíô`I‰á'ë´ºKÑ7öÌbhŒ±.™gÅM`”P€m (´Ö1qWO cµ¹a„¬• 1P-Ð6}ÙÓéF]ÀüÃøèÈ‘é™ÈjÔs„…9ÍcE’Ñ“q»ØϪ¦Ê¬ªz±úÓd¶ÕâeE¿å#Ù2¡¶"«ºÄœ)o#[“”ª+¤l·7°TBOVíÄ¢ÇI£ÄíYÊsè6ºU6XšF"p˜†'A¼­îéù·µb”WâÆ²²J %Yµ%.J‘õ!RŽGÃ&‡åaYXßf0XÛ4ÓïWI „TÃÀÖ—œsâ­œ3Ï?,•9 Q§Á½¬¼FÄÂV”Ýä@¶jemé­^ĘHŒ€ó‘êzÕâmÙÂÖ¶J[+C…Ýíôx¤Žû7긾²ð¶€’¯öüó&Ï䵿©VèutW`» Êæó)¸ƒÑ›–Uç’å ©d€{€=Ù|l²€­7ÓÚSÀªÛnBk ñÊ‘”Zx(ô¾Ä»d3!h˜&̪IÜL}yªRoK,º¼*)«(«¯jVx¤uJâV( 1‡•Ï!œœÛNW•l©j™chÖ%Ac»^ú›Ebíhl¥[×åZ¹Ò0M˜•.ÄUa–JVXG[¼¨€¾†!0gµ4ñV¼,«NÑ#šÁ*(UÉšß;‘K¨;q[â”9à1Ùâ…m)+¾T$&mŒ,¶ù#ÍIS£È<ëB¼™ª(Éê¾LŽ'ÛØ:ŠÜÚVÞÖºÓøc!Ð%äŸ'¬V!1ÆJ¼`¢Jä‰'n"kÝãw/]Š ê8e†²@n‰mRÆ# ó;>YJY£jÔ–F‰Çj­;óf°º[Ể1É£Ù`™ÛÎ<=±¶Ö|€píØú°À}ùÃæ½{01¡¦ÔåX|Ÿ&©‘ : >}B3¤”"¶%æÉ$’¸¶E)bÛš†mOïÿý4•ÇÈžÆ÷f®êsöšÊvEi`‘¬rÃ¯Ö ˜³îÈú¤d˜‰mY‚h©ªl5Ê c«ÊvçêÝî€ÒØÂ…¾YuKù§÷àºs†º‰Êm½]u‘%ƒß-åf†¥b¬ú£{Ûi0ùËâ‘ôžcÊ oÅçyU;+ÝEâ3Äý(Y †òÔ‚3¥Wñu躪" Ó:s¤¨uþ}|ôbgÛüî$gbV3É¡m>V‰´®ðrç–8X PV ‰©ömLÏÇC÷gcÿêúJ åxk7³ƒHeK,{µ+Çá)ôDºUå|ºµ4Mxþ`ƒ¢Ã–h)<ÌBdm5œŸ©@¼’žSá5ÓOs¶µÂÜN{AièE ½Ž"g< e |¬ÃÐÓèXuIO@Œ¬H«’ïD‚ZçFO6J 8Ûpúbr˜Ò¶Z+,²î;…l¡ æfºb¡ðœ…Ì‘7€†x7Ü%ó©6ÏÆCÒ#­‚¶ª¢éµƒë˜y'²fh…5å–9YMM>Y¶ÄdÑ“U"•¿­ŽÍ¿.¶&%à …‹ m‘%К ÿJ¯JósçÉyåõ•r¥Öï8缂ÌÊÖªpŒU˜­†Ìª$ åƒÊÓŠ)²jž…ª^Ÿ/_HUH%]8\£î–²â›3Þª°Gl[VdŽFΓL¯<7<,zëæbµ9dRI)XÜÒÏãƒÉdKÁjYYý&[_¼Q­ /[äFSêKŸÆLÏ“˜'Þ/aÖ¯A—Ð)è'A/ €ïµleárêÕʶòÛzúFJ×nE[YômÇgÒSHƒ:µÞ–¬òª€døÌ)‘oÜêóe»BÊlÇØ"Um­ Cã•Oƒ©Wk •$Ãx{ÕºÉæÉmž§\Àü…l¨PŠ[Ïæ/8çÙ–@#z+†Œ€O˜ó:ÆÔˆ”m'æ°Hf•å@/å±ÂZªiáf#6Xé«}­b¤¯K#¨…«À²Ê1X÷l­¯¦ƒ4LæYám‡€5Ò*ø«êEeØÛ¾¯‹z)8PÒ‹LVØòi¿!HÁ¦í~|•5yâzÁy²­ÿ†ìÍ ©x «ñR¶øÎh¤Ê‘@û–Ø'T!±ie[;/R¬iµ‰ñla—6X þÃa>°ÿ7w¥ÖUXó'[Îù¼ÙùTEˆ½ü˜^•ÛTL8Ky(HÛ©[G€‘² )1¥FR•X×B¹À,”TK+$ȼªôÝ›ªdVOÄY(Ê ‘JºL†ªàj)¥ˆEŒ-=™ve1R™XJ%³6e ÞSÐÊ3´Zóo»Z ^æ‰4§Þ/%ŽÜEz1l (,luyõdRå²_áy”¹%@HÙ2?ÿPÒ¦´¿TÚ*=-ù:†¹Y(±²‹§‘ÊÓJ©„Fv&¶R”²€r«Ÿ¾>lÛ”ËÚº 4jÉà<ñ9hZ ¶¬iÁª¦V© ø™aþ(eñ•À›¡­ ´Ú 8C˜R•õª~.ñö€ioÝç60bRV¶†8‹²lá¦".»^UáÓXu‘}ƒOUºãpWÖ ;BnH†V…¦Þ![JŒ ¶ÖÎû@ß“BfKÜ»¡F`†»ŠF*k=¾ßHœ'[ÇWiÕÔ 3Ì m ¸YÍlT|W1 –r>0FSQ!P¶m8Y-è¥OÙ[z^xÀI] ^xëîžwUömŠiŒ&¤ôæ'HÙ04ݶ^ Шo7\mŸG&l­Þÿy&Ð]•Õ–‰Uè#E x|™¸îüE©Àj¯ÁY\E_L Ý =) TËóÜH`mT©U!雜9@#Ü!~Îl`U:ºÛz!»|X Îäí"+î8«<ãK5Xæh³ZmÀŠÞØžKÛ. æ¦VÀu‰´f¶Î>2©æÁ3i»iá>”B[µ•[WÛÌ4pcÃŽP ò­­Qå­› ˆq^Ai’HÓÖš¾Ið‘­xšÅ©¶Ræ±*‰„}ŽŠ.-ÁÆ{ a²sòñ÷Il•w‡œiˆ1ÖŽ#™X +ŸÈ¶yVÒœ `â"ÏÌ1 Sâm¹/ê…§·¥Ì0¥¬¨ Ž“ ÀDZ9(,Nå÷½=nè«Åí`BÜ+¡Ü©jDZ%8 ¾/6¦-YY‚Óéo÷/wþ9YVc ÿØ"¾9=š¦JÖÀ^åÆN“¹Tƒ!cÈ"­<‘‹UÝ•haë=I€!þË_þòŸÿü'}Me›d¶”5í ôDÝ;e/aʆ¬\ë~Õq"äP¨„ÌJh—€¡ÀÔOÌÊŠÁ³z« …鉜sVfn‹W…TBÖUÉ|äo6àŽóùÏÌ«b‚„;5Ì!äi|[7  ÜUÀÄÉ®ãÄ4Ã;Ùü4Ö1fæù̿ɻ@)[zóWe¥DzF~R;95Âw'ÍGVÞÕEVÀËÆÛâÙOyœýk@—Ó&Jª¥ms«1â¼Þ¯ƒ6AÖsç£Ü–[ÎVX°‚ý<XõØè‘˜fÐ]ð´Uh$ÛcC þ€Âƶ…›¤¬Hлw&V2$OŸ­FYáß@ÚR …uËÚ.E©EVUÁ1gŽï÷ò5û,H dXØRXùÄеèÞ _—•pP…×·ùÛ ¯Q$}¥\pjkG‰l€›ÿüR‹ÉÉÁ–òÎ~~ß…ÃÃ%Àk—U§k° C–I‘aXh­ÙZ¹µmUeÇc`]:Z&°ÐÎëç¾ ÇÃe¶Jê¾?ÛÒ[“˜¡×,qnHåZü.-L `úLÈ8xí})cŒÔ ÃL(ÓRZÓK9ËÆë‘@“Ægè?XÐ(ê®PµCYs#ÐWÊ6FS$e+€Ùv`ÒÌp¡)¥Ô:,\¤ìª)_²Ÿ P–¬TzÖ¢­T㞉4BÆ cŒú²Åh„¹Ú#Æ[ ¤ÂL>¾÷…^Ón^•²µíÇë¹´Ê•pvz«H™ç[›!ÂFÂôÐ[+lr«WÕ:g€ ² ržOÇ!˳Ùâi˜»º«Ô4€Àä³µò»@z¶p§[ €7[2}mé'¸ƒŸ%k¸µŽ#µVnfå \ÓÄyf^áz!Ó€I>™ô‰yËm¯öómÙÑÏJ_a+q&øÚÑhZ+ML-š¼9› C#+(3äæU÷Ýo]I†dŽ µTc$Èj3ž5=¬„L<2‡2O#Ù6 ±#ÕYSë@3HÑćmÓLÙ”¼2¤­ŽëkÛÑL˜§ÕœŽVm¤™É Ù|œ´ÑX šÐw»/a}+ÁkM 07 v l…™mUMß½iÑå—Ͷ¾¨!eÊ:WÓb8`r–Åtê:Z‘a%Uµ¥,«\ØÊúpJ[Ù&iàÆ —êË¿.4”4Ŷ¬Nï{ÃJlczo»Rú"ëî8ý°öÂwÃRMK@ïr0™W‚$ÈÊŠ4Þ má]ËÄH¸52ÌÙ6+’CÇÄ;>?CØH~}²6O+*úNáŠbÜ’_'¤ÈÔZkAFÐHWÑö´ûë_ÿÊ‹‹µb˜NêÌE}[ʘ~Óê9Õ,}žÖŽW×Z7¢,ÌV˜ÆºcóÁÔ´Tþj¥(õµ|hšŠ Âª…Yu F~Ò|ð…-p韩 ˜”¢‰l03HÁõm˜ÄVAßä­L<`S >&!€­Y÷oKÌ¡¾ÄRÞf³ƒ«’"«„@dU ŸÆ#0XzØ’‚kšÖ.Ó‹¨sNr_&+ƒ‡É`Œ^<‘LøgX¶-žRÔq+MUchN³ïÁW˜[ÙƲĮŽœ†!s^­_ŸYÉ.t79¥à`+`…4Jºm)˜' /@ ’¸Ù*i*<@#‹¤çÓWYVÊi càû ­ =¦Ž²=¯¯üç¥I5­ =Ûš6!°6'[²õAРι‘(¶òÉÍVÖ6Ÿæ$ο™­/v!‘Û:ç~zpœ¥šÙ0Ä0+^¶;·Õ%q-lá"¬P(QËÍjK©c81&ÿL¤€ «µ%†? îÑEznHúî§,œ`$ž†XºKUÕãh{?™h'Ía«ÓuK•­†›ºÊd4ñÖÆè–dsHö®ñ|Ãsp]Êm*Oÿ¶ƒ7' ºðL*± žR¬jš¾±­uA¦±’UÚ1q@”µÖ4f‚´bˆ·­oUH‘¸ÃjAŸU‡íYD÷ù%À > Åúr ÃS:N­eû¯ÐHšæOÉ-²©d}åfN©O\¶Õ6ÆZaé›Dy©ù¤'¶¦/eu4ÌÛ®³äi#jJÜGP›`LVÈ@“Ão · Ó‹Ä­ŽÆVªÖÍÜÀt4[J©í[Q orVÉ€¶ëU—ºÓˆ¬òÇÖNZ Œ.M¥NãqÀ”dYѶë,UmbÊ>õÊ››Ô^ž~´ñð"ýŽÈÒ7 Ï+<‹¦µ¦ .k•G}ƒ¦ c.ˆ›Jž2ÏÜ(Mn¶¾CÌVU-( ”Ûv?|*,k%(ðB/¹ãGŒÂª6F˜¿°,¼•¡-+_m©²a&«¦é[±Z¸Qé+﹬äÊ??ï4®® ‘UÈMªŸ×ÊêHlKl­c½¶Ïáý[€Ô0RlÏWÚV(H.]„-@ÐãÑÛVy2×gÊSsÏ +§Q³š¦}Q*QHSa%dÊ#3X:I@IDATˆ†l½NǪƒ46}…4ù$n*óweN‘¾adÅÌÊ_XIÊñGqß}!OšŸ ‰¤R"±1úæÊ¶&ê ÈZ+,Å̵0„i}…WÌöÒŸßDUÕˆ (öX›°F +ñÔ*™ró¸Þ&©„Ʀɹ*kÛM8&€Uaà•ßÌÏ/&Ùèø&¡ÔÔ$”m dßÂÜZe{½ ¼¬¢ç…‰){áùsæ)ÕyeiZ·å€$¦TÛ;ŒÌÜ {?ºdæž ªRT±m$¤ QŽ”VµZ°•²­Êé´V([!\9ž¸Ÿy͆gÕÑ:£ªægˆ'Ø ù`¤š¿‘³iutÀþöÏ¿vÕÒk'l4O–Þªm5s12À\HQ &ÀŠ wÛÄ® ãYä e¿Âe1‘ÙZ5¥LlÛ‰^}+’¬ÓeÒ…H]ƒÓŽÛipǮШ< ¤\)O“¡UHYijÑHï$x‘³•§µW(™­òÖ™ÃRZ0Át„.°# +¯KkóÀgÄ{3ĶN!¥{U˜"J[XÄ7•Ú•¬]$M§*·Öt&9,RÚJ @Sæm4ú20b×K ÷PÔ6ŒUH1‘"P'î7<=¾Z)Q÷V[íÔŠ¶pÊ& #%Þ´­µÐ¥yˆE…VX0`KŸÛÄØ;cõîåÐ0R=”;éçw”L¬ÍS#kþÖð t´išnÓm‹Í\‰¦]Z)d@Iþ²^]+Æ·“_{“™ÀNÚGŒFyæLdà Åli„*WaÝ3Mo+ ‹ ™¤çÌø¥¾Ânî92á VVLæJ¤ø˜ß7›-lLh„’Ui­W«­’RÉð†«œZ;L¿éMÅAÕé}yôebL7ùy „^PThUU6)Ûxݧִ Êzš”ÆcK#H­;ÃyžÞß'UwÊÄÖu¬;«™ è‹ï5 ç¬uJk@‹dª0œ †¤lë.áÌt£9Ù*ì\d$10ÛjOë¿ÿýïå<i3I×/jHqéc;»L­&²SµU(`-ëÍ–¶2÷ÔÄ–L¡1â­:t*Û|Xá¹¥´Å§ì½Q‰‡óÁÕÃÎÄØ¶BUž&óf0½Ô·îü³¾†\¹SsÈD‹ eB8>ííÿù{&¶V|}›ÍV¯jey®5[MoŸÏïJ( “ú"k×qu©™PBL† i北E2TõÚҬʾ:{µh„Á„¦€K Ü¢Ïó­þ¼ÓȦ­‹ µZSÊâ ¶kt¢†Io• »Íz9dÙÉ2o 7 YcàUÁ¼¤„ZbódR¹ùû£*'0 ¬»_j¡ )ø'†iŠF̧B]’PN3XøShOœ¾ÉõUUwSÊⵆZ;rƒYc¬ ÒŠdå¹jÁÇy¸ûɪª†ÑPËAÔS”…9—Šáƒ´ Up#9)Lƒ, ›–òSïÛ©¬TšjÃ[‘oÄ+©‘h ”r[íD’okݵkÏÄjÈHU™·»IQß49ÀH«’œÛ*$€Ý!`+´‹ðVd½r‹©Kk¶wê3¶-^æ8~¯"1`%`nôÆnÈ4°õh¬ùWeeˆ4›lOCßÀ°јëôy%TiÊ!ÒJV¬ï²cÒc`Y‘^iž†O“¿&™ñ µ˜Þ7bJŒ93©ÛZäÖŠ!vÒR» -8Ï6~J8K‘©… b|ôlÕJÙ*!Þ‡Qªá¥6C嘀vël);žy§$++•ÆV_kž ˆR48^­-¥À´&˜g‚H‚¶ »–•J^öÎÒåøˆÍ“ ¯¤*<ÛwæÎÛÖĪ’uÏùøžÙ4Ì9«Óï^ò|l¥h„çÎðJ>í´1Sm0ÇÇÈ?ˆÖÒŽdÑ—È®/w6˜µSVLˆm)Oúû³Ù©»û ‹:R*á`›5 PÀu¿®Ÿ'|rHy ®Ì€·{Û®L•±y4Öp]0<ãÉ:HO&`qú݈=©*`…Ûò!Žéìx¿h¤ÜšVIS‘¹sU@3¥r¶öË’†9½ïÍ+ܵo#U²V¼¯'µ@ïç÷£‹×ygAÂl‰Ó7Ø×éóÁÞö¬lWˆlívRd-Œ- Ð L¤LÕ·RVm/6¾*s⻩‚8&“§©£±8ÉJ6yæ¶"žoÝïô™ Õ¬y²Í ö•PflLí¦7F½²JPŒÀ40gµRHŒîÂãv|<²I\[â ë¨]¶ä‚!œ3†™3™ûrSûßÿþ÷<²•BzÉ3g[ AÀšs3'¨D•”*ëD1dLàÙkבû€ˆº Û nV¤*±l†ñÜÚZÓT¥#àÆÃP6›#ðqoodJ@Š^ÐÛjwnùû·9î¹³ÐËjÁ‡Ø‰‰i [ Û%Âx¶…BÎp§³ÒW…_»ÄjGbdéŬÒcVÑH€1¬L¦çvº‘”U"`“Ø2Œ‡+É!^¡må㛹(eÍÙZs[ v~Óe2¤­¨v+½.ùxd>)ÉNj¥llJ2ˆÍFÖËÜ…4’f/0̧B-¨‹U!’àô¸÷Ö×N£–b¢$«]¦­òx¸Î›¡B&ý±4BkSµe"‹¿ªÏãª$ò ÷˜šÂzí®²ÂÐX3©FÆX‹dTyÕÚ„]²;q´w$†”4xM߃$c»,`K¯c#¹ RJº1[dÓv.©dµà°YÎ@MÍcl+dB é¹`̬6±ŽÎÛ6Ãd²º^²1 f äbJµ;µ¬-%ÆØºØ&æIèñ§ßõ‰ì¤ÄO€)ÀÍœÁ$M/$q×Õ0ô‚¬.°Z)Œ*Ûž»mŒr$AÇÌJj%ªrY!þ ɇ›  hÌi•CìíJ™[3ÄX)ñ@Ž„¹-4s`(l&l»ã›Êåc”ï®Èr;Å÷Z”+!ð'pXßRVµ•[M%ÔØÊÖè(n‹ÖÊu'ðÄÓ¯J¶GÀVJ•ÖÃVm s[­‘BysZmh„O†Ï §WÎ?qMÕÊbD ›± ¸És¶U«Pøª~þê™”P"€™ÀJ̤$Xhl«ðþx|ô¾çÉ"wv<½‚egÕ¹b4jkÍAIØÝB² hÄÖÖºje­uÇóì cÒs¦¬Ðê,ÉÇ™Xy¸F¶ª¬ ƒvbVéë22ó)ñ æy²êDÀ(¯…’:rP%ê5@I_I)°z:d|[k%<­"¥­·=R#€Øe ŸÆwf©f^G9c–jZþô5Í“†OM­"M“Hj­kš¾/2¯¶K3$®V‹J²ÂÖæ·ÒP*4 YwàÙ:T<%²zJš¢r-€9¯cnúv‡Ä,ªª¼Ž øÓ›°ÁÈDR”¶ cÚ•³ÅXsKcm`+-ggTKÖÀ@[ˆºó¶É<_PÉX¤lÛ10¶½´˜3¥™LÈß*EFcmlÌ.?‡lemÃ@]Úš0k2Y$YïI>RÂü êBàÂGŠ,«Î‚Éð¥LV¶RV¥ð ` ØX;šÉÕº ó  Û€i„lnU^MV¶V%V¯eæpŸ¸x…›Ý–Œ¦¦ÀŽ “iAÖ$¬¼p¿Ñ‘=z2ú ›Š8«PEYÀš¶ P$NÆÇü½üá¾ióÑ7@¦–¡*ŒÈ¼1Ö[+¡dÈv<&«43ÔKI[óÐ`|Z)ͦ°v4$,M?»]ˆ^ ¯¯Zž˜J¬cM1Ä WhoÛH˜Þ “~akNþH‚xX 2X¨ÕËZ`v¶š6Œr¼âsˆ‡ódÂÁ6YšÓæk˦‹ƒ;ˆ5%$“lcKŸîÇwŠvdH@¯Zpk¤È§Ëq'Rµ{g;ƒÞW„°v: &:i`àf>Å$>êZ O ¡õá,n{…m 4Ê?·¶la%V3óÁØz(j;þ1½O§h¤Ž©ªxÍ Ò”ª4ã£Å¹ÄçCÇMª9­jç¯C =ÌlñY¶WK ‡ÕÈnK\#@©5å¿ÿýoæd²xŒè[‘¦Á¤``D[k#a¦1g­óÄÛ’ßÒRÛRp#½þpgéBˆ‚•ƒ`4 “¶u‰´ò²V#õj)·upw¨uV¿’·]µÌu—¬H&ÊyŠî°¬+2ñ™àûËY¤B@¸8s%dZóRÀÛ”a[”¦¤ï„<Ïctöóøß <ÅÞ¹Z$¦§é¾ê¢Eç,%+”{@o˜-qëÿç†Ïg¯NÇA:>7`)V̺ €On>n•R‚t.nH‘ž&ÃÁRÇúû¢(4 “H[˜Æ*ð¬¸Á‚ ÿ…åæÄhê{pÛÎØãæ^ífоNg1|bn‘H8[â ðü¥0 L³à ”ç“C+±H90¶šS9[-üyF»þ¤Šl šn˜l¥º4[µÍŸ¾ßøÝ†ZÀyv[L23Ør°µ7íÌm7F37OJU7¡-Ï ûÏ+\£7‰ÆZp`%e¥Ab †ÜˆeÑÖÙÉR¦I`Eªõ‡p«)+…4R R iK¿q<†F;ç¥ÑTJS@*+MwN&l+„‘µ%®]µzÙv-Z¨Õ×V„‰ zA&åhÕ(°—Ç Ó·r6Þ×és²d‘€è“ Cgl6nsÆW»±™49MAó–˜ÖZVJ¸[&0ÀíÍœ;ÇÐó1 ØÒÀUQöja:¸Â@&ø¬l›\aUd›Á#%2éZc`V9´…ÉÉ!ÃÜ2œ@¶*0Yn;^)Û:’d¬àZt¯†åpÊ€u¶x²žšòxUøµÆìÁ#êÎõU"øÐàaÀð@—€ šPŠs­}©ûB|è€TRU‚p]¶N¦¤*åu÷j‘i—!,è»: žØýKy ]Ëý~TÊÞÎ+ÇoKy[}^d}& é6’íÕ]Oce•˜F ѵ° ¤•,eµžÐYd9×q•x2z+ò8Þu3®">½Õ%t?ÜØšMØö_TS [­cl…™3Ô·v&äKÁByª:À§±«ÂP^û³ÐcF6^»´”ÔëÖ[¡‹h€JˆE|¯kn45ݹY¥^ „Óð´5ž¦ð>,wŠscªàJdMþ§?ý‰Rwd‚ìI©‚•3Ÿ8PSXyæ­ù s%Hú†ÊÒÃM»ZJ˜2=b”µ¶í;<} ¬éç‡Í÷÷6n||l9äCãXÉ*q@‹ôVÊiJmgo]ï*@¨JÏvV²°T Yælk¾¦‰ ŸwÿÙ£S{4”d€¯ Y¸ÎÐB*pp+’37Ûax&&¨#BŒ^²pcÇtØLæ!7Ê°¬0|š€©,h’q«c QÃôÓàFl°<­R½ÀQr¶j‡ô¢²ÍXª*§ € Q— mée3䲃{˜Ód([‘kVµ–ªmØ„94|%9X鉳µÊN +lëO#â{Ž›ÙÙË&+‹ñ‚alÅéq¯îüùU@ÚyŒ"€ŒRtj¼%Ý&¾×êç#ÉD|ÊvMRÊûª}íŒËœ‰¾|øˆL¬Øv˰ ‰¤øÈê⣕9 P¶•!@¦¨<™_}˜À ÔŒ ó¬”)‚@Ø–R 9gl6boõYÊvVª”[»d"d÷áÌÜš9ÏÌ×Z-,A SH†lH«aüθ„Ì+ä°»š‡4V8†”¹ ½Tžø&‘-dZó©…ÆJ/R2—µ­ªnæHҴæS «À(TÂÁ w Äñ«µ¥±–jβ ù(䃱”4fÀ䙆ìv>ƒÁšr¶nùN"¥dþ¶ÞUZÔ+C-h^T%Õx ½uÙÁ¥ˆ¥ÍÙëí‘FVà9k$ˆ­Ä"C \ЍPvàÊÉ*=[úZ7pÛyd‹0Ð`ºÈ’5Ã;*,dK5FVÞÆÚI MñÄan}‡\ƒŸ_”²R‹JØ&“åi*« í÷-(Ê1½ù‘ÚÑ+ô d¢¤`PÖÔÀd¸qèÒ:Až@ïPäÉèØÌYÅÃY“4@µÁͨÊ0Œm$åè15ÀÌ ¶f%Õ{ø:«"jÎZ[Ï@÷êê›ç ÍIc+Ô¶­SÊÊÜZ™Ø’ ˜&æÔ_}% F(ñáĶõŸ¹l|%œR÷l×}…†WKiN¤µm㩘¢´°U¹7åVdãÁï=³%e­P à²u«ÕŽÆql›hkæ†!Ve5ðJ`ƒåÖ„Røµæ„é90ôù¢ÁXÃLt$ž>b µÖ4j¬(¥{Ÿ\²¦v훳­¡|&ÕjŠdX•,Þü\ V‹¬Ð—€ùñ ó4‰,[ÿýY€b’³•>L ô  )o‹þ;f’˜†Q-)¶ëí×Eünµ;´ UÖJàŽðÔßñ×±”’5­W>H@Ú©&Îͪŗ²*IoΪ0e;Ñ”.­‘ÁúýGJ¨Â×·àLZs¦ì•ëhÛ„fKv¼¾¿ðìh¥ºÀÙꘀž Ÿ­½^½$”ôšKuŠ^ƒ%ÎÇ*μfV¯“•Ûù·)S j¸Æ°²~>IuBÃ-àÄÕÚö¦fÒªEwÊÄèx$¥9zq Ô2Ĉœ3—R²LTÙò1aw×uø {zÛ^¤šæC™¹C iªw Pªµ§–¹1”+¡„AV‹æìtp´¦´Ö½ì=ÐçG2¾á»|ž ëE<}Ç)‹$¨»aÒó¼òó˜0S½#È6Lb> ó Y52X¸¬• 7ëÞ$Ì»an™œQî×¾âQÖªÊaUÁR”†¶Öž> … `R‚FJ¹IoE:K%¶)V‘>™-@“œ9ÐØuLfÌïifÃôCøñûï¿gdÓÜ,0Ö˜}?Ö{]µ,0@U€ª˜.NU-¯_¬MCà …1вUåÉDÌVEìåë—Nå k!•‰-ÀŸ>`mBÌ êÅ<š*€‚®Â–¡­rn¯KÛ²@åJ V![dGvê¬le¥æÜ–OnJúµ¬¦ âü#­¶ôn©.ÕRr³Êv:€ÙuÛM¢ùª1“¥Z+t{ ™ÃkÁGU·µR ¶ÊbrC–åp%Ÿï…°•U%€?G%æ#ÅÇx0«ô²µÆ¨êdÌ1Õ6¶TJ«”-=ËLo;Oüømû°0q JšÄvJÖPÞI)ÁÔ+ç1ó¬Äœ>Gª8ć lÃÍ–•ãHux Öº×´›ÁÛ0ŸV€ƒµñÂLÛdeM‹¯/ÛÀëC“Œ@ °10ÙVÊV8W2½ÊVž¦—ÿu.[_Y%L"óÁt(̲•œ–߯-† Y«1DsÚÊZy"›YIŸ&5’òg!% sÆ/”ç†QkÛš›Ö&G дSL ²NDC a…ƨŬdÍ#EY [2L½¿ÓÒc*™µ»"^GsRÒ [†²V‘í¶@8C‚¶Wûs‘Õ†oÝçn€ÈÖdÝ0ŒÌœÒl¹¥ÄÛ6'Ì6Mšï¼S"»F%HnŸsM¥zú :F(xä¢^³rà 2[7¼¿’ãàD™Û¦´vážC)Góƶ-…,îtg<üB‹<¤ãèˆC@ŒZOÀY Ù)“½ŒÓ)I–ƒ•,Ÿ¾æÙ‡n]ª Ü +[…ncS©_—J6 ðÞFše•ËFZÕ¦çìÅëò1+v–®¥Ú9§¤‘M)Õ¨¶Â¶€‰».˜IüúÀZEÎHúU9ŽT$`+ÕÝ!vŸ§þÎàŒÕvánŒÏF*ÔËZª9»ù÷hº2)kÄð‹–Z­³ê±j] %Yk2˜sbš;õY`)z€ cB)[¶ùØ.•£]²VÛR” mûßçœÿ P9¬ º©†PP?‚†ã¥= ¤-l¾”¦¡xØ*åkH ’¿ßØèa¼;»;A‰ì¬DŒµÐŽL- 1‡®FVp³š3Òx¶dB‰µ-\/k>x Á¶ ̇ غӋ_¬¶˜T˜!¦ñÚ2´å`Z ÂÆÎö¸¿š&$£±íæH-,Þ3ò¬u¤Z…{)9°²À­h£$YMy ©Aζd³”­¦—>Ë4o9Þ¶{èºÈ0 mÌ“ GÓÖšÌ*+Úæ¦ @Z7ÿ5;0$LïiVåø9T^kXS‚Là µºOYQ  èþ½3pƒ)ç"·d+©¶V7 6’~Ï¡’Ö”ŠéàÀ°*Íɼ¯YØV‘˜†Rß_BöŽüùF¶%XmgÙY``« ÁØêÎ#¬RÈîê}nàÌw#pL\w®VUÁ<Ùñý¾–˜®T‰ÎÇæfUÈ €Cë²~~w“9T¨Äö~«}þ^™§’Våš$ŸF‚Y%ãÐä¶=£Ö3ý}šï4yEÓÒøK …€È\ŠCú¦•Ò öå€w{4Èžû©¼O‡c0-*î8Çî›î–ÈêE²Z˜€¬»ÌöޤpG¨–¶V˜ÎVÛ{ôJ5ª…ñ€ea% +) ‹jënÝ'&}£f7Œ*zÀüû<ʆ9çifµH2óЋRu‡\ ¶«Å(±ê[;XÐãÉâ+ÑhWÝQ’·îø¨Í _#d`³5™*'²J­Œ‘í xñv±Mc-èyZÊsPIik °1`š&OÓÌÆ6}bš;ËY0BÆÃeù¬6Až=ÁJªr·¦…ÛÂÄÍi†):–%{O-Û0²dY1±¥,eíYÈC*µ”e‘m™l’îêœèŸÿü'äëC u5L饼(4¬hb€Ÿˆ€,7+·Óà^·‘êI̪.¶É´”Vd¸¾Ž§İN ¤¯6[©†Ä˜¼’)d4 @Sm+žsÃ$ï)>sk}c¶Íé¤áF²ºüÌ+/«<ÀE‘q¨WÝ­ w01AJÛ¤r¼GS ¢*¤ ³JñïzµÆ´ÅóAêŠL®Kí6•mL† s3gá™-2µ¬0ÿÃ×,Iv;^héux¥ðÃÛ;Gø#ÿ* §å{sAH$2ÉsªºG²,âYÈ [UÄ MGÞüo¿ØÍ?«*d<=_SÁ#2œ¹­¬5rU 2Ϊz—€¶M~»}þÝ|>HJåÕöÍKP#@pଜiÅØ6Ì$e%ÙVh•íÔïÙuL¦œŒQn[ao*)$™/0"ܪp.èÅ;Þ<…T%¶ßŠóWÛŽfíõ³îޔؒÉVeB%u™Ùm~º;x[—6$úžKØ¡¸Áô?¬:¯”àI Ð$ºD6lTaÛÍàw2Û‚² ñ+=Ð$pþÖJL¿ª^ŒPH£°ÕÅªŠ¸ÈHæ ȺWb+¥ÊEu¶"}¶ÖZ·U+6ÿ¬0°Ú×)è+ÉÓ);¸>ü¶1ã9h$88ãipßm[šöÁÇ“a®üó+2’IÓ’Á¢*)üÇâyçñàÐW’‰l½€k|n€þmë‹÷’eÈG*¾sá3§ï ž¦—ÇããÐ[JÙã–í ßVŸxµØ<1@a€šÚ¶1VJdð¤1P ’̶`›Hi°BЋ$ [yúE O¤µ€‘”ªø¤_žVå=ÏâEnñMžRaþ)߉`Y½Tu½¨rÏ¢TÎÊe‘j ÆJc¥±2‰§”M¼‘ê(ÒT«Š¦”yjg%ˆ§W[yâR)ëÅÊý('³*Áˆ~bVë+%+%ÄÁheÛ/¤Pˆ´eÛÒá­lSÊ:N<óØêbµ%«c3Ç”uØù`l+dEÙ¼9{=rÀßž§©,\ª­U4’c&ÎoËÄ・:©áÍÐ™È CÚŽXÑ•,XYmã5ª/r&°ÚÎNæÁÙ2ɹ²úãÿø‡´¿]ÄQÚjŠ,ºGÛzXÅAkCï¨ëoùÃôUòŒç¬©ŠDŒ•XHy<¶üµ÷îHİ”5qÊ1µ°ƒFª€Èè»’9ÐAgš;OcÈ" 8 [Œl˜x¤’W#»k,ŧxÈ^Ó²3‰´5§’xV¶¥”à}cÚúŸñ¡!°ÕÚ 7XÌúv@¤ëR•Ï™ãûzM!¸ù#VgÎƈ°•˜ŒyÎÀÓz¦js¨ªå3ã½U[ÔîbËæ£ ¯‘èÝøÔÜ Ñô5_‹}y™YaV;¦93—•Ú1»ašæÁ§§‘r¢ÆÈ)(wð¶Jv©fFÖ«™oéçK0žj•ÔÚÖœª„™#µ?b æà5MY_>…m>mO§ûØJ9Z¶¶øÆ 4Œ5²r8žSÇ€ 픕ÒäÓ*U¶·¥Kx•™Ô4XIåut.…ÖH2·mkŒ »||©¾òaE3Uº ÌBçšÖEÊÀ0Ð+]/VzIô0ASYsæ¶ùÓÐËróÝkMÐk¬ÜV!¥`í®0ôZP60†ÞšÛúF6‰,ÃlanÉjá²üm¡Ô õJIO@_ RÀVYJxz [©+<IF K ‚fèh= ª’ÁÉlöµKöƒ”K•­]­«­åÆúr# [i.ñù振Jª‹2Ì¿¾•¬’Þê!&PÕ2[?Ö•ïsT­UŠC­a)€ÍŒÇÔÙ!UÙÞÒ³”"fn;[#ͧÉ)ÊÄAš lz‚æOÜx°Ã*”=]o#b¼ŸÖÞù^<%R ©dª¢¬¶5 LŸ2~ÇÄ [¡–¿ÁTÙ6IÙV “«=K¶€¬BYÂél)ñV²Z³íC™ƒµG©<}3ç©vGhªÚqº¬…,†^¸I× Í“¦¬­*?lÉš–`—/«°.3'Ë¿L# PvQQ À ]ʶ½’Ïw]š74sÌç>’'7¶¶Äu)µ¹ñ:©U$¨)‡=ëôñ°'èÈî„¿Œ`HЯ²=J€†Á«l«£ªðZ"Ò‘½ÞpJÛÎEÐÁµ“2‰Ö:&h6©Zw˜>ÿ7 D| ç0ŠI[ë×8 <@¯ea«ª±T¹Y¼ijÖXV) ™”¨—ÚÌe¬`2Ѱ [¢rb‘àÃÙò=ªœ‰1ªu˜3Í÷û4@ƒ§˜0 s À[ RÆ[ Py˜ X8E .ðªŠ<áÈdÖ†I¯<0g[% ð¬eS¶òî'™,ÐÅÓ´µ:2å^JÙV`ÃÇt¨Z4ü”¶‚yO ó'VåÝiÛ$é‡7F­ÖV˜ ÌÁïà¢×2%’?1 š³˜aœZß <Äù·í xÁ™ç±¾Sñ²NÑ$0…•XÓ¨ )EoHÑlj2½¦¶Jêâ¡ëk DÚ6êu:­¥ú¥3Ïþ5åd½ç8‡ÆSàSG+¥Utùz…i[oþ·E•HL@¬\/dUá¶²”ø†IlÍÑÈV¶–ê2}åñ]]x-<£~‹ÒQÊ%ˆ)ÙR > eà ÍiuÉ¿ùûõB_¡À¶@&ûÀ,ŸÚ±Õ±;!¶RùX‰i¼34ɾÜq?àe{çé‰ÓpNÙZ#¸aÎybÊá>§Éð @¯# Ó±»"@b€Œ §Ÿ #Ë&K_“¾FÙÒã :W î9`(Ebd)ÛÈÖ²ÖÙY´œ·*†˜4ÝvÓ¶ÒH©¥Ç¸4i $0ªˆ!Qmþd0.xŒ··,ÛRÉð{ ÝL† I#øì¹Ñ”Úš>ž?  Hß̳ŠÜS°íÈæoàÊ™Wk UázY»J)4+¬ ÏZìÈš#‰®ªñ`¼¬˜ÀPGÚbl…-±­€EM1MØüYäÖ$ĶF p¶•"Ë_mØV0éKÎêŽsþ™¤BXíkØ»áÃÎ/T1‰‡ñb_zlmëH̶.]&‚kszQ˜È@GPåDzI9,d“å¶*â4Ùr &%¶ëÎS\ã3s©n`z¼-Y­[õŠg²—¥²Â+ñX+d«„V%µ¾ëCL ‹Þs§T%vJ†dRïÚCÓÛE¦V ׎L– s¤­Ázp02=,›æÜ£ÿ »¤r0Ò W@š:S-OÙók 1’8k 3óTbh«À‹&Ž©*Þª*œ†›.)7 C4>“ÍÐÌßlôH ¬ª*Tk<ú ðjò”Õ+MnpnL”¨­2¥Â¦Ê¶Û«J 1A%CYÀg¸ïå—² ¨XéËV- «¶ +Ä;±m‡"èAXŠÌ¿°÷ÞØÊÖˆyµV8€c­]%¶B»H2&d…КFЧB ~%V•ž91L™Of#Ë4N´Ö¾þzˆ1Z™4’a`>­æÉskL+U07kÂ^~©²»íi‡yªà8ûb$èŒS²ª¶Öðf¨»ÕäÖš–å°²Ö«¾”¶ÌûšÈ¹›é8ôB!òå1›|†M¥øÀo;šdzØ^îónd®P•©rH\/O Höò!+ðºÙ¬ /ËS¬°7Ì+Î?ÏJôu9#‰òLLàYÛfEÕ¶™mµð¶Ú4ë„é™X•DzXa”›¤^m1FÂ󜳔è¤5Ãø°€Q[—^€ÈÖŽOClÕZGã)4¼£Ö·ñ­$1·Ê3|¿pZ_ +c UVÎRs SÐ8È)øF?•à*1g-ø÷“úzœ¿6ÆV ²µ-Ì 9dë—*©îzQ £ ©x%j+”Å·…•póY;[‘ Hoek-èÉ´”dk¥Q²“ÓT’Õpã-‹gh­¶^›Ÿ Ÿ°Ž4¢o n²¢©ðuÁäƒà`ËV¯š’¤ÂÄyVÅO¬ÜJÀAŠ&+_Tn¹Rùôñþt^&RsëP†I_ªÂܤlñ¶jémM…¹aà<¥‘•,°o [ÈZa+ï›§ø{¥NW/ Öz)'³%¬°i¥ 8Ÿô²Éô‚™ É¿ÆK‘µw¥­ÇâÛù d9Xáz5O-X5†^Ë"‰ñ‚¸Âª8‹¶ “ÌZ Ì09O)†ÚYeXÓtdà&?/g3}²5U¥‹wÌ ó|mÛrñ4ë¸;QŽ÷ôsˆ¯—÷v†²Ýpþ @¯‹QÞiV@„o‚ÍÁúÒs ñåbEš2Ͻ+›U67L‡‰É )8K”—8Œy`'D T"Õ3ÐK•­ „Éj¡¶¯NüN¬+±…wÞ0·.®F²f¨ÆHdŽó_—&SB£ÖÀ=°i€æ!cEi åµ³’åO#ÅG`l»Š”¶Ê3'°dýgžð¶Ö‚ ¿ÿTn5[n]Åâ¼|BI³©²­äf>Ÿ„úæ WÒÕm$†îAYßµ„m²+1<¬µÐÔ6Mâ ¤¤ÁkmÛÍ [ÕÊ66ünë[êÇ*U¬…-Ãæœ8†-˜“Éš¼K³mÚH+Æœ”p)ŒHÀðMe /hJ:,RÖÅV{µŸ Ìù4x>‰dÄÊS£§Æg2ApK?¯"F­À+‘J`]m‚欶¬U*O¸½ƒà#m &d5íZ”t“ª¤¬”ù´U2O|dµp]â­Ê»„dÆhKÆÙ`ekd7œCÓj¡D¹¯J€¬”ãKuó@$àúNμCÕ%kW' Ê#vHž Ïß„‰ë+U_%x˜Þ`azÛ™Ò*êh­ÿJTÉ 38£mqzßXŠƒªVþ)­lé)[1”ÈZ¨µ•Mi PÇLÔ"u·6snù(¤  a<¬„OšÄ¦Ç w©¬-2œÕ<Í Ú‰jÓsHÃ(¥ŽÇœ9ýw ¤_P*³¤ÈÂNEæGÚ-=K£h“ ÃÐj«ZibÊâ Û—·ÕBIúü1‰ñÄ•XsdaLVazÌ@b©@<1ÿÊ1¹Y1”µ†Eþ40”^4ɬþgï„°—›^Ê繇m›'‘íq¿G–Uuÿó9W­P*Û¬lñÍlxä¬Tá­H³QJõËF ÆïégBÿB ªRü1Õ²µ%®c«,R‰X­TV’³¾º+Ï„>[J'•µ­» Ïö ÁpVµãh»ójmëh%S‚oU+2‰$ˆÿf3Ääè)`1cØÒb‘E:¾±«‚ŸÆJ#+ÕÚ­’a*t®ý¬ˆb(+ÁpËŸLÈ&0”’Rûòm¼)»XVdÜ2„1,¦ÖÖÌÎ9ÄÐ4R½Z1´Âœ›§™½ RÉ”4‰ÔÊe£P ;>åºTnfLÎÄ¢Wbbˆ›ÆØŠªè1áîªyœi]Ç4¶]#)ÑKðÇt? ¥D‘2§'B W®o¸ )ãUá­¶µ>Fßû>¸ïOš¬˜pRÊ'ÐWÈ*§RY)Lo›P “ÅXY%p¯ Y¶”RÎRB ÎÜ–8²¬©Œp^$Τ,¥·ÚŠs Ì"7µ•—M0|Μ•Ó;#²‘È`;8g }ùÃñ•)aÏŽ'#凗uÓ"5’­Š•ŒôëÉïç;±O=²À÷ÁÉÇðT([¹5`Ä%² ESñ¤i°&‰1 ž¬# +ä€Q+tÔZ• ´ö"dÖó•TŽ„ žŸI 2|ã‚ >â4j0Ù{áôdèf0[$±Z¸òd|náô¯¦rŒ„ÏA …Âa»ÌU¥i²~F‚¾vÝRj'’ÂäÙ<Ö¶l[@ ¬…޶€mg9ãs†•xFJdZÐ…°õ¨Eý”ÁV¯QÿþLT½ L†'ެA¾Çôû?2‰9 ®­”Hæ&Õû G¶âßm¿ør湦&Y>7…³­ÿÍm8RvÁŸU]”ÇϤ­,Ш$™³HÕ¿’.½9)]fcÓ›ï©û;ñ™d^ îz ±•ð~kXÉz.Me¥×%šÎK†¹É صĸؿýíoþkPbÙJ¬ú2t—åÙ@*×T(é ÙŠ‘RkK¯ “¾³ÔÅjB]Èt4ªÔª’‚1᜕xÝQ6%As¤•Æë Ã%­R—8LVñï6MÙÎUG«^&?wý¼Š”]š¬Ÿ a¤ÚÊ1¹¹£úÖ€‘›?}×bl[-¬0Míl›}õ(qÛ¬(ivX$‡®ÈÍà ÌÓúºI‰î0^-†³-ëéú½ÀpLOCßð»czCVSU€É™ç/ ¨ù`ÖƧDV$Ÿø˜ém½íN¡‹6^O¤k±¦WK@¦°#¸FSY ð{p”pCsdhT«’>_0¾cja +´ nc¦Œ¤I¦ˆO§kU!’aƒQJÙŠ[÷©Í>ó›Uåª"­Jà9œ³HÁù+uV…±b¬”JÊÂ.ÇÊÓ#8m¾O ˜Uå}#»U¾-Yå 5¶&TBÐT[‘džcÝAÌÐVÉôÉJ­6ómZà_r¸ñŽÁÐíáU_bkÊ×§SÐSr0§mùd@IDAT‹26q[)¼Ú,EÐÙ¯OövwÒš°"Âl)FÂ¥ŽânñªD å‹+´êB)à ["Ã+ì6l_·Ñ“’Ý dû„¡ÚÊ­¶™Ó}«À®È}v{ uIYw…E-Xu{H rd_’¬ð§ÖÜDÇi ½0›àà )e°”~I€1ýŸvyjT«•è•“aG#v.i`Kd¶VY‡BZ±r[¡^²k­¯ ˰-L¦$2gX!ebJL+>P‰­¨^¶R¢ò1ª0VA)€n€˜ƒïyz)&.`–BÎ!óôeaVôd²”xë@¤Ös£l†1•w3²x¡ªBÎcÈx+O©f°Æs‹—"ƒkgNQ¡goT2±9³²žï£Ú[³6‡ëc °ð3²bÊÅZ6 Œ§ákËPmñ°s~õR›• È“ H•,[¤^@âšú°á™k$è1>Wq‡GR+%¹­/‡ðd”4BÊj[_ÛÍÓ Ú­£4婼¯©Bâ.¡Úf`»I(‘‚‰•XI&°sc®äó–諼™e‰e1RòD0¥•Ào'~'öÐ}æ×EmUzÁžeS1¯ F4C«-ÿdÀ¶›™’9Ÿ0 5O3`ò$à“ÕŽ`Vë^y¿;·eˤT‚ Ü&Y¹ìkØü‚[zŽ_p+ÛUèKÐE5vVÄRV2ÑVaÿY7šRMž¡rãŬ©#2[€£¶ÚÒÄÓÀV13„‘u©Êú?r˜‡¡\ð4€qŸ5jZdåUYiÂ;Ž-,Ç÷FˆÏ;fGc‹Wbí2kT-%YPZ«­#åz• %¶ýœ“ŠÑ6‰U(·JŽHaþ §]˜Ø*ìŠ èÈ3=ÆV)±0s`žõÊÓJ/ p£ñ‘©„ ™y2üµÿµ`r6=±­l¹4•c~d+GR¦w:$Ü)¤ÔιIÍ¡¤ï™nCI/<0=`ӊɶkÉjz©NÄi ³´Å˜¤À76+ÀWŸIvÚáϪ@-’›­”U´µ¾@UGs®4+Ô–Í-ÿÊsÀü%1œ¾ežgW‡á »Ø;×Y¸!eõ­„žg­kÔ¨#KÙþ?üRɬBakiu„F’zÛÉâ×y«í¼™'(ëø¶Ä€Cñ?f°Õ"Ù ‘žo÷¦¶|7“>Y«*-ðLDíÚZÓø¥¨Ö=‘:Ji¡“Æ*Õf’(i6kÿA)k/Œv Á0ñ¶R<ÇÀNÔÀ›‡9$H\aÃà&èSYIß]RbŒòpkCælU‚¬"qåHÖ+°å#à4Ö©=2¸r2Ùj+ÉÄJ€/•C)Lµ®¨î¶"Ÿôø€UÈú0ŸV‡ÊYJ Ã|àî®D­@Z«¢Lcuiý­v˜¾OeT¢ªs3’¾¶uìP4ù#M^Š/<Ù^$âfèai}¾‰¼XÚËõÔõøÊÌ¡¥•QÅVÖ1Húz[‘j1ÞE©ÚàÒd7)åÌ F^ÕY0Vë̳’ÊDJybÊĶÂdÀÚb`ÃãÉ:Eà”ݾ)­²]V[»+<-l›8})<½ió§Qk[wJ¶ÓÓ¬ ¨6& F/µHbX9° “²Ò$ëaÕ×Ú“%À» …ô” \fØO±è?µ›r€"ŸšÂÙAJ›9çxŒ¾ü9wQaï¡TLz¸ZæÝ‡uï,Lj h( #˜s³åV¹îÞmšù„+4ydš òäßÑz”:Ö”-¸ÍŸ8½¾Áð}Ž”µ°²ª ‡djF ’À&¶:Š×‡ÉZÀd­·â”TÈþøç?ÿ™W‡oÊè@%ÒJÍ£¼Ì”L–C—%[ À‚œç¶«Ì _/>0±µ^R–_Š /†õY¢±¥‘‚s“…E×d 첊ÑNV\ïóeD֢֜¸Ù^×3m8ò=KÒÐ7R—Æ‹´V%›8so ¥Ó)"aµ,ð"V"þæÏVîaù³`¿X÷—U­áj;»m>DÊ­RñiÜCgI!7MadCöjj;¸^¢« „‰V•aµ<ò øàÏ )e»7bÙÖ.$PIk¼¾Gú ùð8®!{ÜÝg³áFp€y 3øRèN”wX¤Ð޲{£ Nåeš‚.ÅÇ`H©†ÁÌ0O†Ä‘p‚|` Ž&áœ8fM•S”uu<ÓI©œkDÐÙÛ²¢Ì–JĺÈJLà.A6Ux«­rØJptj<²¾o LJ«èµq«mÓWëàüE½p2xn_Õo½>ß 3™˜‰°Ý9[‘¥´è\Ûj‡QbHÏ¢ŽÑ÷ûªF²¢ò:4¼ÚÞ4¾y$1À+ìÔ€àœCGnEV(·ºCåôÕ*y«ò±ãSª§8/ÓˆKž» uTÀ?“R6ýĶ©Šï½µùKógÎYa†V©ZI™[ ðÌcX#ßb çOHùÜZ#­ÈU9Œ²mâªð¬nþ,R¢F‰WHc<óÍöÖvÌ|fK®µ¬mQ .•\#-¤¬¶)å½n@»4xUĵ&vº®ï×Ù É0V§ä€iŠî3fY[!kÕ‘Fð‘dœ¥˜èŽGJáÉê^ëÈ|ð"CJÃdÀjUõmD¹^R¶5R^kH8Œ‰¤ ·6' „‰¶V­mfh’l½–4ÕêE&å3!.Ø^3ƒãÀÊ}jŽãóNâ;‹¬`Eï\4x«ÚþDQUš P ¤*äË×_!ÐevF[µ•’ÉVb+ÎX×?ÃÄ0’À¨4ªl¥€nF4€,È"­ ‚æ±äV£—ÉÞvU M¿B¸1ÞKRª#4|SÑæÊ¶Õ“¿ÂP›MgWÓè%¼˜Ì9À&$àl üXë‚4VµJŠë}`Þa•ÐPfEözn[_)3W{zܶ:Eíèk×Ñlñp>Êe ð^ѵùXb±Ž0ÒÖš8‰‘Ú…TåD¯^38…±3oM£67²æÇ˜Ù¶sÑp°¨Ì¡*ÌFU;Lðöªãèž®TÝa½úÙ4&½T§¤ªÂÔÝêµ1LÙœe{ ¦,ÒœdÎ21&O÷㫾ï"ÙÎÈàÉ¡kÁðu—"Ž´†!•Ì ›ç”ݶæ;™ã¼ý¤&HÃc2¨’ÅÇØõ2UVpÓ:Køôû~—¾nó!#¦Áð?C\+[n§om{¦¼ót·HÁØf˜ÃÆpL$ÍÚÝ??zúøwQ ›œ§1»—¶ª&7jb¶d]H)å¬t lmb)bÛRJÂs£‰l`ëÆ£tRÛÕ²b(Òà5Ub$bÙ¶ ÒÍ€¬K2%mãiq¶4ÙxØß(TÒ» H)£F1J€ Çhänë‹´Õ«­“&kæFJ µ¦Ž,ÖZaíæVaM­ÍßðÊé+ßßl-¥œ§ ÃæÁ)i˜m‚FM/«\ÖÑ[3—¢7ª³dn=/¿ä^¿¼ÔÓ1íEÔ¬2.9f‡WÕª½TßSªðL8P&€™ØRÊ:-¾”m†@‘&¨“¨ÊðZ$(¥Eå¶;TgÄT`LbK“‰m¤¬È“U&Ro}›_ã=Z¼lŸs©&Ì¡•à¼áÉÛ Ÿ îü¬¼”d™#öÍOÌGT.›@! éZ¤jħçBP;©4¬v„f0j&)P•ÔȤ•FÀª*ÌÄ*<ñÜtñíŸ>C ÚÊaâÊ ýôJf`ÏŠn~-4…‘W¡l-0ô¶ LFõ0qå9›Ao¸TƒiÑ‹²»î&  \‰¤ÈDX˜þIÁ;áÕ~ÆË<½gÁ\‰µ£Uh%Pe0í ãKñ7|]L%ÈZÄdí¬!»C)-|+¯‘µÃö#„F­h© €)˜mÁŠÀª]Ê4«Z/úÆÓˆ˜LªûémQBcµ•¥q3˜}ûKÑczÊd¬¶ /¥Š¾Ó1)²¥iÛnFÖëQU½0dÖÁ}]èSÓÚYu'æ`ÑéJÙ7ó Ò0U-›†^ʪ£v¾¾”mYèE Ør«°¥”šG-l•͇ jTÏ'œ-FÄl˜|¬˜Î´UÅYk<¦µŽkͲ› Ã+§¤Y×%«²°vJDüÖômÃ<+q“4§mÇÜTuÏy™Pš¶©Ü[µÉ £;†Àë„$k©ZÞ[VpWAƒ!H“À™ç“§lÇIcÅ#õe«‹èËŠÌçO Ø£ï)¬<ó¶­Í™Ì ßT °Säÿ¦è;ˆ”ZûóOæÁqÝ;Z_阙Ðçb"`Jµp…< ü˜ð)¹üÓØJUˆáiÛYà ñbÛ®­î¶†É­rd7†¤$y†3ën«0e)†õRE#XÁœ l‰á<› Gjﮈ d¥šŽl¼¶ô¢9‡¥ÔŠ—/; +¸u©ôHa +0ƒƒ+o*-fr‹>?, ÐÌwгde壄€3 4pæžEwk•¥¦4¦9­xUž‰mkVÝjcWÂDp Rx ý¬2”U.•Fötõ!Wâx\L øèÊæŽÍ lezŒ¾§RÛ+’ FÊ]ÖmfK ª«‘5†,²ãI‘EZmÓÀª*ÇÛV(¥œƒm3Lƒ‘µúnZJ¡ªm#q”d˜²íJ-O2 r Ûž:ŒËæ3gßS¡l3Ô‘Cch‡Åµ<žkwÛýäi%³Ö(LÌÓ)Tä@àKÊY˜Ô±?¹öJ(If¤¦j­\Ê¶ŽµcU‹hà4 ð9ØÊÂÞ}rCºáFEÊŠL”Ê oTãõÂÈÖ‘èh9g‹õm0ëbÔÎÙ0ÃîÄ¿)a7£*™­Üß®Ðnf…ëHÎpo 8ižéµÀ“)oÀZv·-j´I²ª¼î·çç× n¸î”`€ÞÚlH`}“Y1‡^¶+WÕY2omÂwUU/ ‡Õ–ž ™¸™[Éh:¦î=ˆÄx…e=,Ø•æ7gά¸UÉÌ à>βñ|Z j‘5É_çLl¶¿:(‘ÅËg…äÖ3퀬ֵµHf$©‚gÛRµPU‰*Ñú¼à)TâÒ~|ÆÓ+$¨ ƶϬ ~Ó¦D2ÏÙJ`»!ià¦Í S Ýÿô‘‰'òt]ô+U‹æÄÔnkí¬½ æÏÓ¨&AîLvjb$F÷:ª]#€€¬TSýè®Pw‚ Sn­E¬Öš ²SW»'ˆŒ±* ©¤#Xièyж®ºWnMßa æ¢ì°ÃÆCÖÈ<¥4’j$·‚RÊŠô²ÑÀ9ZçÙoÊœ]£Ö ¦ŠUb¸©l Z‰u”²-h„9ûâ%X–q×¢£­.Öœ*ÄFú°ôUS;$1LimfJ`&P"ë•-&e«¬à“LfÍ$.¥²ª‰Î=—¥ò$v^¸Kè•èb•H¥O†oÚZ°UX2cà³²…Eå¬ÈlÓ[Kµæ \ÌG¯LdaƒÉÒ(›¸*ø†^øúV[÷õbß0xÓ"ýÖØ%V·!ˆÓ×.ÿÜbŒjNAŒïÆXñ_aúl‘"Eó`cÊéEb$FÜ¢so˜c;eš­i~ýcÐ×¢·“‚…éÅ–]¦¥Z‘j tàŒq`%Õ&°b”†ÓËïIuTKLÐè0R4P­rÁ™¬I(»k[AÖí+”Š TNfµÅg¨‘-~þ¶‚¬Á¤q>R"RG)«î§3Ð`*¡áƒ±z“}Æ×½×»_†¸U« °å¶•¾Fåß–ÒÖj«…(eËAÊ*ðjØbhO$Y<âmŒ•Æy¼*åd°¨/rg¯J#ÙÜ”ËιZ²”¶Ãúæl{û«md[ë Úþ¨íz3i$ÃdR„ã¨r„ ™0líÙ»®ºt^|‰©Eä …Œ©Žy{õ úÉ®°SÖ41 ð´þÀ?+©¾=R6MJÛÆŽGVB0¹Úµ¨Äj;L)Ú6¶r‹¿ùÏoDRæL\6+¸F™ °ÝÍÈ6€r)¼mO °Ö·Úôn’ rëÛ¦©©Úa€RdH°ãÔ]¡,Y Ob™3|º«15žŠí~°õȽӆ­ÄùæË &îbÕ •¸AÏišÍçGß–ü#*̶Ã5e«D9ÐÄaÛWŸIU¥dß9ašLrðÓ·Qý ζ'r-•×¥r…5r2Ø¡¤`)'R輯›ò”J¬”ݘr|nÄ¢FsË¿Bµøëô±n¤ZÄ…TU:jäà˜žކÁ¶~$Àû^ ƒ¥ÜØÄü1dëC€¶õôKYžæqcÝs7&+¥¶Âkóùé‹©5@CÉ91¾£5¶­0Û¬²EbTm†—/›yØ„Äî®*´f«‘Z)Ê‚RJ‰ã8”’~¬:‚*Á¹¾ÖȶvŒ*>b…•󯑭ÃvÞ¬8‹ég»FR°BÆø+±Mlx+(ò¤lÛ¶†Á4ƒ10O¤’@>ÙÖHv[XUþH€æG£ª¤š*™&s½]ˆ¾ÈœgeªxϨGS «-™àcÔ|bLÕ¶’Ž D¶ñªU§è\Ž”tϰÐ.åÔð½0ïT”¬Z«ª]ƒÍ°$MŸMæÍ‰ìh1‘d",«\ ÃVVáíð|Ä5ø<Á0 ¾×€`ÛœùT ¬š6rd…±Vò?Ë¥øÓd¢Ë«¼9oT)X”5-ÆÞ $C<dƒuä†!“"‹¬K)¸P~ÜŸÀoþ¦i¶Z9ËŠÜØ™EÆ$ƒ‘ m›¿ÉËšV»4d°€¬”Óu–¾¯tÁ#i¬ŒüÛv-É6Pð†Bú^EžL6¡eó¨µÍ À烶Èjmi™X¯ðó¶ËêkUbÍöýã;T ÿJl)ËæÀ\Š e2Û—WRV!ü6¥´>œ†~æµFÒˆ GZ…Âj³ÅPf7ÒÑ=ß3Jr§ÌIp¯Šîý½’~SbÐð$^ȤɇñMØ;=`Kiå `ȪCå‰fÛ/ÙÚæ`+ÔmKµæ >Vµ"ÏŽ©¶‡"Ë!ЇE^9%’ƒr×"›3,`+ý>wd‡Tž¦v9×´ÓØ”ÃÍZ9RêuXI¤íÛe$À­ÔçÄÆõAí¨|;€6¤¶Ö0Ç¢Æ[e•SYwo³xb²VY¯šŸâ¢_˜ü=ƒdRëU£oó_3ð±I(YU[÷娑dEWiUŽ1§èi™é3 ›„ ?Rʲ¢Äl ˜þN}Z'àÖ ×‚¸§m}ÒpPR˜¤ah¤D‡úæÏ_«mßV @ÞÚ1ÏÙÌÑÕƒ÷&õ2u€€U±~D“ 4V 8ÔO‡±ºúÞ0)|«Ãûïõ£Ý‚ ê¸TŒµóo«%™k²võ€ØÌpO¥r[]ôíO–®Â6R Û`›!¦;á Õ³é·aUÚa &s4…¥`ÁÁ¶ÛÐEÀ JåY+“°m}+·eÒxyÂ]…”°]m¶ø4˜‰a)Ûž,ŒÑÌ×ìTe‚Oßù }}¥D©˜zÅOFŒéê;€¦•r3`´³ X&ðì¤0 W‚á#”[)©6G¶"èû¡õrºâ;“'óJ¬°ìd@¸.8A’ )[sÊ·Ò6=@ÖVá<1ÜÜO¥z¥¯ñǼ¬ÍÛBí¥(KqvÌaEÀ¿×ÞgǓŧﰲ˜ú*¤‡‘4ñ֑À S°òDò'V‹— çf¥$ëÅð—5a/›ì;¥¬±­Fº ¼ãsДî d)9Ó[ñ©ÐÖÚT²õBʺ(_A¨]]žÌ•lžÀ6†½“ÖÝV—Zð虜Ä]±Tc´b6sŸ÷«)çÙÚâsS;fð—ÕTÖ*KŒ´íD0¾È<%RV`6°-ÆÚœ9¢WÈ'ÃxµÂyûÂGÂl)kákÝ$j;µª 4ùŒ§OP» ÉØr¥læk­eþ¨y×΂áÌM,Û ñl)“áÀ,Ò›æ#(ï£a†>¼”݃µBVÓÉ!åÙ¾ Íþœm{-s¶p+7-zçt]Ì+Ï[ñó#‰lÂ4|”ïBæßUФˆ­fã ‹Ûp'Í“ l¥!&³ŠšÚ^§Ï÷U¤•Àœ7†?C Zc½¥È.ªÙ”ä <ýÛ&Là¶ôm™¡Y_8+Ø€éÛô2¸:¼*ÎÉ&ÀË )‘³^pþ‰;½m˜À³Å7d-¬/8[ Ðx‹TñqW€T3õ%*·ÂRÇîkÈ$AŸ_˜UÙNa›FaµÍÖÌ=£Ž@àÍQîåa%˜ä e«ŠØ€ÀÝsK”J¸u™ô”d@C¢a¬ hbÊæ ËÂRb q$€ÑŽžFëÏmv}~—•ÆÖ5##’*®>¯R”ÙÙš¸¸ã‰WU³n™Œ¡çê§Z—Xk÷ˆÇ(´ªÝ /Èj+¥àÐ]”ª†a»ß+a[Ø®µOP&ªéñÍÐæ)˜èeë)Ã+|ÅyøžI`UkU $Pòv¬µÕÑ6F-ÚÆ7 ¾ŽÖ¡Ú&oT3tQÕö¡&PnEš‡FØÆRH¹%2«äcÍ¡›Ôw@­-%†y#Y黲ê*LåA g^Ó”ÍÃ$sÓ†µÈÙJiUEÓ:MçÒ…s© á¶R=[â&$`ÌVSd½¡J6’Ñ,ʲê€me•W‹©i)ÀHeóÁÐÃx++ ¬ÜVÖç“LVH僴ÍYU—€·§àœÆ°–U³ê¤¶EÙ>ò< ÞkÁØ*‰'vE|zÂHt@c”SjÔ$ï`)i šUaàµÆv"Yš¶jmá0ÙÂ"l%¬¬]û%Îs!kZY)Û *ij]-¬j7°.MNVŠ HV@'m»S˜dÙHb¤­ðŒà Y²”m¯ö¼0€Ïh˜ñMe 6M)û%Î_oÅçíb[Þ¥‰•Ù&0O|2©ct£òæ¤OYjd¼O™ØŠôji^^Ê6AøÝzˆ#jÔ¢µ-œ¬—d¤§PGÎæùQH,‹¯/¬0?à´ƒ‘oU%ñ†ÇÔÀ þ9Ü|TKÕ‚íœñZ¹UX+‚4Uá‰Ãeé s§Àç›Wc?`‰*»†gâ1ȶÀ¬U›@íLRzï½µ¢«§X鎴0·ú®{©‘¶; /YX#ÙÍÉÊ +,KÖðm 8Ð4mWOS!ЙØ  j“ÔQ Áº'noUu²˜ZOi¿i˜ýÙXa÷#¥©¬I˜ô«¿ù£|²iÑTªj§Ö´È~§×‚RŠyJ[â40[%¾£‘m§Ö.[[µ¦`˜žyJµ4kÑå#Ud ¾ç™J5 œ`o)«< ÌÐw/€t.÷_ ·šÖÎJPàÓgE)Ëg[ œE¶y¬«"ÀÛ–‚±QµPÛ?ÛðÄø°mçÊÉîÒ¤à”æá ž bšP(¤j„¡ ã+´…­‚¿2™žƒŽ5•mª”R^#U=”ãøý t42¯™[GÀs£‡1xQ­l ÐéŒA¦‹UUC¶°¢ôò“mÎÄÖA„yVµR]²ÕHSe«Là¥jxúfNùžH éS‰„Õf¨|MÕ†G )…Y¹’˜j'•2¦‘4µ­õΕ¼}my*Œ$€ÙZ;ÆYšf‘Ÿ³-'í/RVTÀSò$[_p+~ÝÒdLJ¥÷Pl»d -@oÕBJÀFRŸ,‡$6˜S#ç#e˧µ1fXy+R¤Œ#m9ÛjúZ¥oBÔ”²ªÊ».ϧ-@\!1²ù3´J2Ì­Õéð“ôÉ"“åÀ³±¥!«ÊVŠÆg!œEåý@ICÆ´zj•ØJJ±U¨ŠÆ67+œ½* ˜€÷î•­fxUŸ_BT%°Â‚’ À /Fv3˜@2Û@÷cÔ~¾ÑTvø¨ÆÊ®¡ßõíJ³ëÓ€L­UÊŽ©Öv†HÙ¶°wN)´®ÄÄÕ>`] e§­pµme‚n SÛâ»,L§Û…b”ZÛŠ•+^aׂ/Õœ” ù ;‚¾˜Ä²*¨#¼ñÒ`vëå£;FÐ(Gr«¯,¤¬ÎpßßÒ¿ëëPR9·Ãç¥\I@/[õ ·µx ¬Vñ̽–xÓn`d†‰a̧•©ð&Ï ñJÄ‹ búWøƒÿduou ¿. ßænÿóìÂV‚Z(a⇮lo”*‚š&³%ÆTbUÕ)¬pâºÔ‚g/OÇ!°=ã~·«*/ `_Cù¬EÖ:êÞT¯, ¦îµ³öÔ*,ËÖa­&ÉÇyÌLrÖ(Ð$Ý ÆïД3‘¥äFPÐ`ÀÜïX€ÙNj°.Y­PkNš¶ 4€*½%[χÃÆÔÅš h˜jÛ6L8+µŒyd·•Bjd-ªµ"{¬õa’O³)ÇOÀ\‰TY†ÞÒ4HŒíº4’,gVÖôÄniS5j‰)• +) -Xy@– ¿›)ØŠR¹*$Ü#S…Ä4Iæ§ìþñ`)†”¬x­æì6ðÄA•U‰UßÒb|}mxVÎ^ÕÕ~ÞRšŽfÙÆ H¼Ô;À45µ[udkH€Àc„-¶1ª?àÁ.,'òùògfó$¶ôh8d›^ªñêk»hú”mÉš­y¬}íøˆÁjÍÃ?P/¼hB@Š•”@R´½Â£z%¸ %¥€aU¹+MΛ-Ù;ù4H%ô1M›¿UV˜‡?·‹!½”µ—¤kŸ±n(ñWåYd1𲘬tÉIPaÛ0%°rÛÂ$ôßÝçë%ç áf¦‘…-P;˜ s‘hΆyÉ«ú|™p`^Ö*6Œg'ëhÈüm«µ-0@-ÊZ{”ª:Z…•œß£¥le‰ÝaŸM™¬V ”UÎiTÛªdÅiö}W©"ìŒÄà€™OYë€rbí€ÄRš¶Öb×¥¤Â¦…9 m™üùçŸ>ð\Ú;L=€¦”¢€z«ÐÀжU±ƒ]"™Ó–ÃÈd•×SwúÎÐçĶF3×½ÂziÇÜÊ¡vV‘a`3°ºÉÏõÁlÕ6›5O«Ôë_áÆV7@™`[m€¹ZÎ]ézQ )Œã(k ¤ï®¬˜4ª”[å9Øj'XÁ4eîû¡å@œ!²7P[wk˜²Ž¶°[øÌý}Ê}%§Ó·WbÙŠg[ÓÀÊóEUÖk|Rĵ8§}>ég˜&}ïRÎ5ª0qÊ­š&ƸbW¨Q…ÍFóFY e|ßÝxŒI|:úUR–C2-ºa2z«,rn1•à÷óÞœ²ÜqiÚ@¼³Àjµ¾Àl m+çv|¯3½­ TÎ\uV¶ ¾í@Û”Üð½uµÎM­ Ivz|C¹ÁT©U7X¶V©"«í²llÕ*dÎÁêø"™m%æ‘Jš³F¶aJ eµõÍÀe4@Vš2ÄÓãéX¡mg$ c.®ê4%#¹I¬(‘9Ã^¶Ù'wc²îA¹çŒÙ<¬»(†»7µ¶²ô…­¨0±^Õx(þ›µ¶Ì…BJzJYXDr.lÌÖ€T²zÁ˜LضÅèå·m+R!šZsØz3g¡ñ@U€\È25…eýBß0ýê/eÛG (³ÔæOV9FÈjT¶uÛÄ+´mZ ñòŸ'¥ai OPÉ. _S¤ ·"×÷T~Ž$NÖNÇŠ³8ÓÿÄnÛëäËP91°Â+¸^V&#sF4F}òޢjµCR&¶b*7˜` ÿôHŒŽ¶‚•p3ù[4,;qVH½à4ÃmÇ“YyY«¨OLCùòa«¬H./Oƒé8pž oëÖ€“º“0~>†iž©æ·yâu¤äcÕqV›snöûªà1`ÒV ·Ÿ`ÝÉ8X›ª÷Ö¶P5 e…ybª2y&­²Õ‘F  L)Uùcd‹q埅’Þ¸Þ·™ Ï™‰¾Vçßi€I‰€ëùëeŠù1Y^Jvµ<=†ÆÅ§±m´€±R"áþǪàúÖî]ãûl‡­ZÓ$c¥ÎxY c6Ãd·âóµÒyRVØÌ•,›@!¾ÓZ³r[רŠ™_S+=>ÿa%RVUÄuIƲRÂ6ÿׂ$°*O\ÓxÑMexµ¶€¾Jd­‚²’•‚ï•%>5‰Ð›çÕʲ-j' „eµkxø}=”ä“úHLd£ÂÎ µ0Æ6ƶ'èZz.>? ³B]`¡¤›ά߿WªÇáCy“Ÿ&0Ãj½*ü9P&{ÇÛé /kË­G¦ €¯E÷CÀV ýÿêüwcšÙÊÇ$õÝÍ(db$0s[%%Å5åûû¶d½K¬®äó×]9[>ôu¹ó~¾’ÈŒ$h¬¶€•Ò*͉ñ¤8¼[Êx2éÚa¼9¿©Ú½%÷Ömàú.¤#3)”Ë ãìM¨j³¥áPÐ[vÛ•ËrP(Ká#)‘‚)òÇÀÈœsCÚXô\Œ¡I`¥©6L£OqÏ.í4»í¬u! ¬œs²€ŒpU;=¾`‘asrVØ ©V‹”°H¦¬š¿ç¶¾Ú„‰mÕV X9·&7AsvaJ<¦zn®0mÕÂ^¤nLyæ¹É’Ä;~ AGÎç]ñVaf)ÀÊ­£q³¥éZ¬fÀÐtÉuôǤ²¶¢“ h¤ÖTd½áȶÌáÊën©Mo¼øùð}dùtQ)×Àˆ¬º+퀵ãæQ[$.•Ì7OUR”|ÒÔÂm ’ I P4!Þ*KÓÊŠ+üüïL`VÆ Xñ+©i>¡µBëf:2À­BVôøüáDšÖf³*7ƒ3{ʹÙVµŽ¶¯ œƒU–ÓšÉ+V«‹Ð¢•RU†Í£ûxï˜mc”ïkJß ²È4¯£w»ÚRuߨÊD %¾ªª2•L×…¯Q³)$“Ê'óÆð¸ãéÊ YÁ?4ÊX×I&°ŽMÅŒßRüýïGù.ðû·‹èºs—rWÌ«xh6YÖ²UUnÛ±mà 5jâ&³åœÌJf›-,”ˆlM8 OóFø´{xuT(è«¥(ÇÓ\³ÏÒ‰Ú4̲IJ5…|*±R–5¿Tó ¤0=9J¸Kïì¶dV©Ùvù€ßK¬u*tR_$æÃà‘ˆ)¥<²{0Rϧl+’Un;Øš #à3Ó¥€1p² ×ÿ>¼p‚RynHØ)ÌÜÏ3·ä¡§á,5gbU®ZxA³aºdŒ#fÐ+—ºÕGy&»ÎÖÈK|¾ÓQ6,Oˆ ÛÂ+äcëÈê’lœ=ËQµÁZóÇÛZ‰û†XpÀ[‹²îÙ7`&kšm>]N&ÊÕâm²”ÊÉ`£|y !3,«¤.¶šv3™ 1e´ÍC&”(ì ‘ÍpÏôù2¥ðF<ù$è\u—J–¾Säiæ¦ÍÜv<œ> yLŽL¬EGS‰„ß}Ícøem}‘þûßÿö÷ :ÁÄH+U” 7l¶pÙpdØZœMÒ˜&ÑB î¤V±­Wdåd37úŠÊɲµm ªÖ¶ ÒÀ=¦jÉðEƒYû¤·%ÐBÐ4j²N„!†ñ~¦¼o,FGb$™-Ð])©jz]ò_ßôRV[‘OcÛ*áH½núÊšï•Ê*·JȇNš³Um˜LJ—ÈwŒÔ«±í½iúÊ6@ ‡ø ú‹×-ÆšÌJÙ$KjÚ´iˆ]» fh 2d7N# ¸µcliˆ70 ˆsh6s«;džHØ$Ȱ’sŸ˜3ßï_¤²iò¡¡ì»âZø¬Ieûù7€ÿõ¯ùq(]ËŒlÙÑÙ†•ÁUÂ5ÃÌ.†IVN¢+†&™r2)¼—LÖð˜ª*±ÖÔŠïîL„FHž‚ÀÙú—«ðµNCÐ zI)Ás¨Qn ÖÉ*×þŒ©5àƒÑPØ05­D-ÎçøÞ‹5!¶6‰{° óäÏíY*¶x[¸¯Q)[dþ›dO¡vø ÐxkhUµ-0\yÌHMk÷‚ÚÑè7ØJñ;ldVªUnØaÓXýØö£ “lëZݺ)wëD»LYÑH ÙfØ])DvÉÖÅ–›À¨ÚªÜœÇôž·vü)a2<\Gbµ¥T9)ž¦,%ŒLŒÀÐ$³õ!·Ú2áf`k¯„¸© €L°Caðd40ÒœmÏIîß"E&+¤Ö0,Ì f‹5‚ñ”J<8â0¾±Ôš²­i«²€9_î¼G€ÙåK)´•jgAjÚÇ/:`†ô€US‘ídUÉbø$PÞ®Qµ²@“¼`U¹±Rˆtinïô¾§VÒŸRl³¢xa «Ô&,õ_¾î&I²ÜHÖè †$wÉ ÿJȽs&ÕòL¤A…ššš÷ºGdV‘M‰”²êNc ‘¶ï–2”r?V&é3±bÒWbyµ§€­R"ßÉaôšI ú5õp+,•[c`ÔbÔšY—”â^°¥ÁÏP9LOdeíÉ"iT™0M­WŽ\Wµ”|xâa$I¤8Pæ@ÓÇ­7ÓVw)€FUÃÏ*gkoN³³¬|§àiWª‘û=@Éæ@îëûà0°I¬9Xc"ÕrÀPÂú ¸­•!FJ\úÜLzV1¬iÌi[–8Ì|€ôÿÿ•¥h»•3Ã`jg€Þ Ön£ñª¢O0 z)·ÑTm­¢.d]@)Ù¾Äl+dH6M/YåÇîJÀæW›ÌÊÄ$MÎiýÖy`d2 ­UUå4²Â—s…ð`€ÄKåsÊ®Ø;W³áµhr-„ù ©—T_z¬d­J¼è œ Íð”‰5ňæ±V‹Y ¦0‘Ö”VK&®äV¸Z3°Å0™ƒWXGn4k‡gbkå È–F­l$†€a—@c+»£qHI0 ÖVnµFÂZæýŒI€—óºèX¦iÛ6aU1Õ61²^å‹ë›&gÙúZÅÌY‰j)E]"[çVUFkáÜGT ’ÏûY#)[2V7ókžd¬RÖ1 ñíy–ÊëNC/»á÷ºIò¡ñÄ­ôf0+…•sVB¼Q+Œ¤©5€/š„mâ4H¯œ&sÁÙ”íÇôûɪÄú–ØÒcÜvžŒ•Јc ['9k'V.kíÈ{c‘ ¼#0ø¨U"ð m[¹‰˜”kj¼î°2`gçÖÆH‰×nkÕ}…¶aå dÕ2¼çû=}ÛÄÑo½k¤¼kTÛž¥ª<áæ¬WߟÇë«Éßš`íTÁ›JÖ֓ұǟÆêî{Žæ é –ð˜;¶>³@ƒµ:#ŸÚah„ó^ãÏ‚'¨Ð…“eÎŽhz7Cï£Ú`RkàÉGap34[+~By†”çÙÙèÔˆÖs”ï·°J8kv§É÷+²ÆôÆWEÆÍ8ö±»a«=O%°+ȩΠÏðôû¾‰k×Ì)­H¶ûraž[%VJž½,ñ U¸×÷v>²ÆC†_=F`TÅwR†Ep^A`Û 0ÞÖñµK&%`èÛåð¯P¸ªØ pz@w^[µ'"Ãb~â‘Ã1Ö7ÊZ‹†¬õ<ée#W‹i˜˜¶ÍÙÀø•8Z‡JlxQG7 îý}qâdp÷I)L4BJÙvŸV Á&©|zbYµ”V_VRVJ@H‘ÑäGz èa¼ç«d†1”˜ª|R`QùlU -¤¬…o=¶ù«ê}hÔÈë÷ëoß3§üÚÏH3)$09íŽ ‹‘g {ŸžŽEV&éPJLˆ1p  „meU%F*1I3ØÊÚÖTGÀuÑH©âOÀGª'ÛAh”“Ù6@2ŒTLUH¸ÈFò02ÞVm4Mc-¤¬”†•gb 2´mþ›ù|YUÞÕzýº"©Æ`Ò— Ö‘€Œ>ŸÉhRÖ:+Y¼ƒH¹X¤I0x†¶RÛJ¤<}Œ,’C%²RøLJ¥!0*Û²ª”Ãm•íh\ ̪ùÕV^•^;q-Ïm0ÉÜ%ô€Ϫ¬µvVå4œ?Íȹ™î/ léó1lÍM-\9ÃæQ˜áÜš_U_*˜­UV-l] Ï0’^``ÿ†}‘°HÙ0¾1(݉µùë‚¡§4Ímæ˜7(·¥´}™Rj )¾SÓïDÙNÄXV(ol8­ ±µâ‰Å|š!Þé¯ê#+[I|+þÚ~_GÒÔÂÊ “¿­pÕ1)7ƒF–ÆÛŠî$ÒË9Cï¼° ¶5L[«í† §±æ 7†Çª*l¯‡5ÊÄü (u¯iš ¹uÄYY)½Wd²}vñ™KÑ´VÈ_ Ü0 ënËßV¬cš xʺ+-ôVþH *«l&p‡jòþd … m}»º`¬Yi7¾OVYüBù Q4•ÃÒTƒ’ ¾9dØØMcmÚ¶R€ò4R¶Uñ ¬„ì·¿þõ¯¤®Òyõ*®,w2`×ú•ª„!+÷•°…­œÓhçäÌÛvËœ¯}>Ê‘iÔ…)mÅ)»17àËZúª|„ó’z5Œ¯µÎ.‹„ó‘áÆJªB<7 Fù(lþw %²È…ÛòÒÀ¦‡œ•lU¥ˆ'ëΩîõæI°!1Lüö–?çJrãS//ƒw©ÒmØÊŠäl$‚ÈÌuÏP—Zc¤D&)€OYŠJ¤69¦½÷ÙJv@oò¬¬_ïóø8“ÕšH†ÔÅ ÐG–µ µÍ/eKcÍA €1áKâ…k7­[åßlɺ7ÙŽ ½- ‘5Ûm;x‚WI–¸u[ž œ¼”DSí¶1µ ÞÖÔA¤š¹ïÛÙL¤¬¯­­T±a:²f$€OÙ%¤qGöV|>)ßû•—µÒ “[V•»|!oKV;ü)þ2Ha[y²˜‚wWõ9lÙÊ6~&¦l•ºzѳðZY¯«M+[kA#•§*A¦JV*¬ˆè{uçP–P¥U¸C7f‹çHÃ!Á½éóèØbdÉÜ liúòôR!¨JfÕ+LFa[Á¶’†ÁØJÒÛ ‰QHl+¤DV¶eÕ®|z€2>óq)µN `‚ðœëeKÜÿ÷¡1¾h”;²»êrðœùûEÑ*d)]T˜ÐWtÛúƯi|úæï‘ÁR ©0ýaþñdê³-íÿ9)@”µÕ(˜Ûýܦ!0¶•#E¾HÏŠ²/d¯¬C‚Æù†SÞd]UüéO²RöÅJÐ$}ÂaQ••7«Ö•X19PJYݯ„RTHŒéÒ3‘Ú#§ÊoÅy LòÁÔÈAh"3·b¬%‡d•ÄX ¬úf°v-Ê©¶@ŠªjÇM`l}ð0øøç¿ 9øfI–9ý†…l“XE[ Ã]Ë|تÜ*"þöç… ã™›v² z@¦%µ–UbZFèKǶoœZHÕˆ^ VË 67k) %å^¹ž¾ìë–-F6Ì#œ+O|k§ŠyM}Öê"%(Ên[ßëwîÊ–­,°-æÉ€O€÷?e-ðj­¶ÀHU×ï,HkÃÝæ†¤„ý®)ÕÙJj]­•̧¾FÒ÷VËÂLŒJ ‰µypW[¶V[Á¿!)g‚ñXmùãi„¼™2À„&+gì›7F‰B8åµùø°Ê°rXT%…l‹™ì§ Ôš† V‚ÉÁ[gζŽÃÇ躩B ÉA‰•lW*…‰t ·­W÷/Õç…¾ï|}1dRœµ0sÓ€¨¯Âð{dU¶Z°êƒs+>‹BÙ.ÄTza2é‰ÏªêcÍ¢oƒ|0LVÞ%ÄXZ;ˆÖÆž[wEidM‘d‰éº[ÊxMé½-ÄN ‚à5WBO¼ÓÁd5r zÛ[n£¶.ÖÐH²¥`­¥6€.0¾î‰éiά·o[‚?ÿùÏž¾¶²žþUñ’YgÂ9sš²l'›òǨ¶s0ÙaÒ¿UÃd)ux ƒôÔ²û$.DÖÀ³"ÀXÅÈÌm‘ùWÆ/®0~µi¬»X6aÜsþ»äÞ )Œ±ÍŸóî²H&Üàü1ñ o‡O—Fêi¢z”ˆ¶K)ôå £ŸHÁ&e/$üΣ¤¦Fk¤€•Þª<½•³Ï`L¶Þ´}ñÚæSk…"e ©8Ôb[úJb¶­ÊvøyÁ¡Qi“ì&?‹²«šmJÛR1Ö.¹¦:¾%Zh×¥ÁRÄ¦Ä ØïÞ Ü§²ñ:2s)Vê«)¸!ka+FæÀ‰F²˜÷)ù׿þÅT}GâÞÿ"_½Õ6†¬ÃpÁ§Ù*©ý&äïU¸™ó¹U¯ÄÐç(7ºP ‡>•«íŽ$lù`è9ã cêB&ª^²Ÿ=ô²¥œtø”Ý@RZ³mìº|%ç+@0ŸÒHøºK‰ü[•˧W.:–ÅÜ̹4˜8F9žgUîÐóÒ±ÿîW2%‚R¶#d%o›O|ØÚ¨ËbÖ° „㕤 ë(lEæV (¤T5˜ishK€ñb UéØÝÚŠÈÍ–˜•Âl'@VˆÑ—`2ØxùX „l‚zñoËVÖJÙŸr)ólù3LÓZ üõ>?†ñNÔ pΓL Éí*7šÆ³60@ìú…L™U 9[a@G¡pa›€&¬V6±ñð…l¯l£Èbúù÷=Ða§ÖPÂYÔÔ*VG³–¹Ç:Ôe àg †2A¯Êñq9²Ý­ñÈdɬ‡L¬R s渓tR5%À3±UÞHÛ¨l%S£Kæo)¸;$J1欤IòqF|…¦d É[¸0•€=àº~~‹¥ÌœC €Ô¨P˜…ad…ªâ»„øJv"JU¦Åð‡1«˜(‘Ò±*¸ª¬”jj«DÊ=µL¬€i²Åôkn’á9(¯¤Vb¡VÊ<@ƒÙ6‰r«,&[c×YYáj­ ­½„RÊeù„ÛþqÕâ8ÞÓÉ2±"&”bÛA¸™öĺ!)ɬ¶þ7@{¶"[@Þvi*©ÚI)·Ú €@Ä´-eŇ•›­1ÌŒÏðTÞP(2\ùH’p+G³Ö`n`YX¤×nÇÁèHКÜum[ë;Ñÿt$ˆLÐððk¨¯­¦€”•LdÞxùÐèÛ ›ÜCÉJoÛª#“|Vž³µF4ÀVH/KoÕ]ŠmÏ@bÈ*Ï)`È€Z€8“|àÄ7`ˆ«Âg‚T¨ûæeé½ÿ•̳”â­†´7,¦¯ F¯‚,ewR £{çõq঑À«:ÿ«=Íî#ÖèŶ% z[³ñì“%+`¤JY‰»® ÷ý¿ÂîJG 1‡ Èpí˜Ô—Ù¨SºF‚4 ïÈÍðÛ?ÿùO:”ö}àýú’{)½m+€Ùá)sÄÛ6bí1Â@‘BÛR€Úpµ4˜°¬¨)ÐÜHÊü3Ÿ1’gWÖ×}…4µ¶b%RðÔÂêÞ­kÃxÒd>MÞ‹¥JTÅ9ÏZ4ŒÕ6 @y+>ßw°š?ò¥Vk {.€a†/˜Ha™¨\ h6cwºŽ#Õ1Ï ¿PQˆì€ )m,®ñq.êë.È<¶]WƒuÃÕ�§¦ôµ%¦ôÊÑØZ9ç@ Wb»¾)×Ô”ü)cUb¥¬]˜À®WΉÃM8Ù<ÜÎuß'Ø'¥‘ü™ÛœôRuäßå#©a í&ifkW—rYž¢™­‰&^~)i†F…‘É*ÄÛ*±í6¶M¦ö=5¥’já¾(‘™˜°G#¤öÐùü0¯¬sYa>ï1³mNoTm}qqæàŒ½/•le•RvÛb8™íšêâ/ØlëHŸÃ@÷ck b“cl$kJŒ,XMÞ¶ù½ödªtÁ$ÛxA r°ÊZ=$Lcù1¶"LÈd(4X>@1±­òà`f¸î¨ƒçé,‰ÕŠ®‹¬ØWõëÑÐcÌе¨²´*¬™!X¡¬mLÀJlf‘ØÚSÀHu kª-å°Ä™è2žÊ­"~U²Öp‘,ÃLNñ£„ \ˆIºµWòy”m7gµ|R!àD]зOßÕ©s¶6a³©j<ð”ʤ¿$N£„¦aZm›ª-mLåëÕ¥jæ ˆß„¶¿Û¸ªÓo==î¯vV©u¯Ýd)»ØkùùL±u^_hBGqýΗ¼”èJ•ç EÖ‹²i9TUëÆnÚOAyž¶aY2«UÕ«FpMKYuAÒ5ÊfU °"ÇóD:¦¾1\Îÿ1í«p.‚Â( :•••]ßk‘µQ’’Œ!¦´ðì­JÜadÉ蚎C&`S¬dF¢L¼ugûáùª“7"­B#Ö¦¬P‹.DªLlÔ®+}•ØòÉ0ó‡ÿ²j­BIæÙ"1­H-ðÝÒü›j?uhšŸ­ß&Žô3T®ÐjKc`À–ÌVÇŽ€,R†›'fÖÈ‚‰Έ¡1Oæ”ce$¶ÀxnÊiø8¦’é󆧌¤tdµ”VÀM¢„@Yn1Wr¦* 3IOœfÎM‘ýúâ¼J\/ÏFšO<±9*±v.µþ‰<¥\ãm§¬£•/*4†Ž‚&LF £`ÕÉ «TúÆ9t@Ýt\[X•'ÀÁl1 5%“ª¶™g)ÛÍ (Ä[S. ¿AF#4ÂW¥5C¡°Ã6 1²+†ÃAy&VzÇôŒÒ{Uú8Lf›³FÚá;c&kT/[šÆƒ‰»(Yv9¶4 ³0JÚšVŰÙrÃØ"K)WU_¼™À¥Èò™‰­ÞW1¬”K€•—d…Ñ‹¾ ‚ŒC˜ŒC#¶‰ÝÛ†ýÎ¥œ¹mcØ &Jÿ¾¢•›FVAÌVÖ3ŠÌPŠ­U–CU<é{1ð²—€Y¹ux€PÂ$±¦)ñL6UƒÙÊ ŸY§öÁMÕG¦r†JqVë8NjÚzÙÈ2ñD4‚„4Bž¿ßÕK9Y[@fèî£J póëF6Oc(1R%R›j†H±°³\îؾâæl5’ ¶1Ð$Z'À4m ^Ǻ¤ èn¥ÀÌyŠ•ÄW‹ß¹ð Êsµ9X5B&N¶T`µ²ê²RE²rœV|â¾|zjþªèɼR=;[8R#¯+‚ÜøxŽï`µ–m[z«À¸=k}1ù4dúÚ…É,®ÍǪ” ÿ&Œ…W‹­vm•'³M&…t"ñ92¬iUbKÓA(ùPòüÌw µ¶u{xþp½NP 5C[Ø$á• .µ®ÄZð§Tb o0nèîPH˜@! Û¨ àË#ÅP¶1³mÊÄH¡/±_¼­Îî&ÍoûÛßöH*°ú #X‹Ú`„'áñUHè“°¬¿TSH‰I²­3윲¢ÂÎFÉÜQAY¸2M¥ŒD¼*4į³Òp“IŸ¸#`ʪ0¶ÈÄÝCV)Ó$0U)UY«jføs†ûi¯CfŒÛ#h`àÕÀ‚¾Ð lfÀ…ë® ±â­ UY+cïÀPª¢Ì6#èsK‰/ð¹5›*1 CXSWAÐTÜX¥ß PªU%+ˆ»ØÜ˜²‚’.¶ÖÞ ÄÊ¥ÈòÄ“Ix1CoMÌŠFU½Jm#­¶‹x@Ræ'óÍΑðp¤a«ðù¢I–§I(¥X5U“ìÕµ³pºçR \Çõݨ‘U!±ZíôÊäŒuÿXÅYÖÚü0½”BëUëÍCóÖ¢vôÈV a1å &ÒÙmû© Ä¤P$v“4|¬¯£`jÚVŒî­‘”fÒ©;x$Lì§L w„HØÁ½oz•%HÓ *ì±24¡TGP뇬ÚNÑð½rpÓʶj àøœÕ¶RºFç%Ƭ VtÀL` Vªî@rV.`|†²Ö µ€…ZX!1L¯µ1¤àÍߣ¤¹EŸß6ò9m.oK_÷ 1º[UѤïi’adS‹{ØH%RȪ²í°W{¾â*!5¼­“öL•Ç×z]=`Cz]»¤îVŒlV¶²‰ïtGÐxÀ/ÁZ›¡—_Vè˄܊糳gR·ô˜w´˜ñHÓ¿ó„ñf¨ ¥îH[—Ó$0¾»r™œ;‚‘+gV; †¦Ž •sS2™=ÒjzY$€$Ó#ê¢#àbib€0UpÓêEÐ÷m˜ r³jZ Ö.Mãuðdšâù+Yk¸k!@6 ¥RZ9“±²Åg8©is`+ªRR´­D–2q}›?[ÝEüuú¸EÖ—òÖÍ`[_ Ãi*´&…oÿÏé”m¶Êž8qåla'²up{…Æãî5 t4JA)4€”­¦ª„«¬B‚°Z2̹ˆï?›mnUËÌmrÛd¬ðgšûE¶Åk'ØŠuÄpS¨/p%ŸÌÕgð5Ìjø>­<;ˆl¯÷;ƒž˜›ÐëNq¾HÉÌYw @Ê0¥¶ˆ+Ç{ÃmÂ"Ÿ4 ëec]/âKN¿ŸÖ •s£Ñâý"r.“4ÃüÕæ`E–%ËS9˜m%pçJ°’JCfèŸuóirâ>¿ç¼„W ¥Ÿ•(w+iÓ+vÛ,2•¢éö«ÅWΓ8f‘›Udn%æo­£•>>Ù®@/)ß#Væ²ðW)È®5™­ÛIÆÜ¶ˆiŨ€Žµ¶bº¯›üüÉ3&™çÁ¶ÚÈÖºÇç¿.µèhuÔÅ$«këþ݃ÞÈf¨]†@ zÝgÈ­±10Ag‡óÇ+|ñRã6[]ƒ¬¨i&…­¦Vá-Ê¡µ¿å"klnÖ‚›Qs‹ôÈ&¯V @ÖÂV ëdº'ðÖü+Ñ%}¬« £·ºˆ×_–˜‰•¹5´Õ. `ë¤VÙ…BVºó÷"…­ÍÙaçàÕÖ.=1Ïn›&¬D_V}("w9ï$”²Ìëclʑҫ1L|â²aY})…ö½ÁMG pj+Æ:±,&«Äª2Ôοê*ëã$®Ðé´€y®…¬°Í!¾gŒƒ/=…œLVE¬¦ªg·²œE€CX!“4VÚ <çVJ)ÛSCy‰á½4²é)}î V—ÖjÉd1½;ñåÓ÷*+2<`]IÛJ:‘÷°Ž3o 1 `Õ.s¸Ž¶0‡Ú1,TIÕZ¶îRø²°×Œ'ƒ­Ø0éms37$ f½*—ÕZaÊ<ãÕFZEs‰c"çÖ6AÎJ‚žÓ¹0Íæàø£b åd½ÞÎ^¯ῪÏýÛÖŽ@p¦çÜuÁ[˜Á*›•-ÁVn²é 8‹:âÇÃĆônðçÓ»Á_(D&V.ˆ­1œéÉj‡oBŒMµLàºÐëÕ´de´•²¬lsØ&EJ-™m&m›DVðáL Ðê\H%‚Œ‰á8¾/F¤@bÔr lkµÅ‹Àx !;Ü–L¯d0PäPJ;)aX¡lÓôõÈZeϪ£•rßróaÂÖ©ûý÷ß©íË%•s`¼bX–—Tç¯^?3½ !èi¤Úî`€’‘ÃiÛµfÈdzŒY÷d®0íÛÉÈœ¿PòǨ]V ÉLb d¢¤ì%˜î7Û|¬½L9TXSå‘ lfL¤*¤µKð#°Öé‘nžIb  e—JÏ¡úîĶ›”j `MÜ%Þ@°ÅçiÅðù˜Êé‹” “ÀîtZ¬By}i©0CL-ð™Ûv"÷œ­T³%õµí!1Ò‹ÁGŠXem¥¼çªlUVU"7­[Ê4ªÒ4 DZìâMÂÁŠlT]ȸáKQjä×S27Æ¡ñÈ:ÞŸM’‰iÄdÄLüÆ ¬¬¯ÈŠLUo,F_åšFyVHÙpÎVµU)‘}mÕÚ/’¬¬Õæf›9+¼Ø-Áª pêœÉÆ-ÉÂRÖëñ)lÂÖœSú|íÔî°¿û (Û¡¬é4sï€&RVY…3ë%mYyjaZ³å)ÅÐÚ¨9To‹4ÖÚ•Ú 8¾õÍO «*)àCÊx[J>FŒOãMÛ5^Ë£ìliDgÄ·e8X-PUŒ´•š->+WÄ­™iðÉòŸI|)bbzdm ïÇ™µ.Äú6[‚æa…¡QŪvæEo0 Ðd‹I¬¼ã̃Q"óÉÓ–ØJ£0Û•×NáôæL†¤LŒéÞJµbDgÁPZUõ˜€®H#2¬ÙZbº±ºX)éù:Z¶æw!°à£Kn~ûŸ­OG<’žaž­šj×w`Cê‚éËÙjzÀÚ0mc’)•'³b¬"U¹Ù­akÛd™[m¥Èdm«Ä˜ž ‘4ù[ÉrŽÜ7Cߪ8¨¢„­‚R^ÀÌ|æüwî\L•ÀÖZ÷ª¬¢9kaË's«Ú•Û&¦DÎð ôýU°—S ½¬¾x­"[2`F³Ž ë¸îªÊöˆë‹É6g%˜0>Û×äLy­¬R|¼ØS"s®ÊH|‡C&²RÆ‹±bª²œW$ÃÔ…O% i­0`Žöö…+„òwmÎ<ñ§÷=ã…›¿ÖkQÊ„ÀŽÓg“#”ð´=ÿÀè²°Â}$²õÏÇ á# eas1*”™`úÊØ4ÊÓw xn0†L–•5Á‹ÉÎèwZ%°§X¹Z%ღÙؘEb[ ³PγQ¥DåõâìtV…sVÅ¡ÏFïz¶iªžØ³´ætØ4²½»<¥&+2SÙn†º ék!E€Il‹·MÙÖŠIéPzÅd %4o`„”v½ÙºˆÊÕnÔšfn*åµ` T˜ 1²’~]ÓBªðÄ0Vj›ÄµÛ’4ÖÝ0M ½X  Z$ÐêÛoÏõÕQäOæ'“¨{>Í#•Ò wN·9#ÕVÎ?e‚&Q^à5°vjkÉ»m<…WÜSÇq^šxŒ*í9¯“>FIóô ¢­’Ng-X!­²æl¶dšÂ"óðt·¶ª4RëÉMÀ åþjû,Ûv¨dHž"C .4ªÐHjÛ2G J…¶V¸;„zΕdHo¶ ´ÝI• É̬ªÂxV5ª{µ ÙðÄjcò±–jlkàƒ­mMW¥E­ñÂqbœ¨aØâ¹Uâ>ûã+…VJ+XRž]SɲjfV²Ä ñgÊïµÓË"U €R mɘ ÕZuxš'g l}»ØóaU s©leñ™øMâNd¥ô"NÓä™d] ³Pv'im’üÍ4‰¯‘¬gNðšïtÍã.  瀵vµu±l‰×” !kj-åZV• ¾.ÖÍæBð<™7€*%f ©DjY%Ý-ºy÷–˜Àµ3'óÚ k'‹)˜)á&&s«XL€Q"Øz¬†§#mW X»:ÙEÓ<‰ñ‚¬¾M(%¯Êš¦ŽeÙ6Ißç¶QÕ i¤”a) C½²ò$ÀÀ])%ÌiŒ&¡É­SD¦´ÊƬ0`*!ëñYESÕÎ*‰ë˜2s)¡œ’Uz½ø4­ìJR4ÈV>¾ŽðÌ;89Ra¡/ð€Õ«B̰l¼”’šIiK Èš PR/²Jô"ÍCœ>P‹zÁnx²vŸÄ²H€-`J¼¨…Wέ¥¬9œÊ‹M¥QÃp óÁ3éå1ü런c!5"5ÀÚGÔ(xõx$_Y[J©|‘b[ü™ñûÝ ¹¶eüdH¸oV%¢óh ©5 [»| †\a$FÀ?ÉPpãÓUvM)oÝ) g¦ï÷²ójgU(K)X9K•̇Òß%¶Òh'Ëжª|ˆwíid [žžwÎj1üv!õEŠFµêheÛç~nôpk$«æ±ªÝYlɬdø4ºÛn¼È‡¸#{Óâ1Ãxó |¬•K¥T…×NDö>wWa%µhrã‡Â ï¼_¯Ûâeua‚æÙÀY2%f³&Æ7€Tƒ¥±šVTØý¸|7#µv†Ï‡m>;£­¬Bƒ‰Ži€€*J†€‹”V|>Îb«J–¬ƒÀÚái0V‰7ÌVàÕÒô»Îªº‡u ~­i)M­6’@ÉG¶`‹ß0mµp@£Ö ©Pè%ˆ lçlUV½Ì`•Èœ+Ÿ[t¶d˜søû©ÌiKc ÕÈPÊT¶BŠ>ì0ø·Qz<7k]*üÑ‘’[)ºÀ™ûiá,²+o+›­­{s±º#•Su´ÅÓxz4 ª0ñ¬ ¥ hJlÜ`k7£YYLäÖºç@&8\Õ秆TC"ó´·ÕçKÒV*sJeiT‚Þ©S|ß4§àIé¿ b<ÑTN$2^gãÑ»gµµÈJ‹Ê#Ua >Ç +T—²ÚÝ}%OýšXªCáÒ‹Sw$±­²jžf€uXõâ&«°m˜ œŽÆšUSá ¤€i˜ Ó˜ vÃÖ4/RØ<¶Þ®J¶æ±ÕKI#5ƒf>Aµù[u·Æt]jQwæ²ÓÔÔV‹ª0”Í€Ù6l5}>­2¤ST˜Y%ÍÀ–Ùê¯YM¨@¨µV¶•%ŽD­“åßýwZ§TKÐ`4¸, Ÿ¬ê’,¬êÜøý£ZÌ_ë<#sÀH)DÄR#éXkØç¹*‚B‡fë/#z7ô4µ&˶5¾*« 3Œ€Úu„¥TÙf5·>ת0}Xˆ+lH+ÆÑ:A3ÑÎVJ—f†eµî¬ˆ³%Pb ¸(Ý}ô@ ¤ø¤T^G€©Äj@/€@ U•å@ܘ&9ÿŸ€‰ä)†åD^\zŠ*KaÈŒˆQ.b,’€’IUÊ1M@9PïQ7kpP¥nÈÌ›£ÓÝ•² )…­@¤µòd«U!‹™r9½³[Ϊê^!F˜™a ¤þò—¿ÐôßGÄp–ÅÓÂյ9Ãç/û’i¤âÉ„n‡Ž0˜[/7A>Vo?&‰ç“ÞúÇ`¨Ü¨;‘r‘2Ò–³_û¶°ªÖFÂc´s||UVh¯_×B e¥ ÷í[k¯kƒ%fÒÙ«"+8‘3賜@9Üå$ÖšokZªå¯/e)5ú"[«µÂåû¡ØsïħT%p}+‘Å÷p}QÖâ:=c5’’.PG)«FÝq†u©sŒrÀ ÓË ˜]&’¸C%ËAVt/žkì dvvCˆü­A¬àFÓï°©ÚJ Ó´åcÎNDÓÅ" lñ[b]L%9à§ébm9¨åàQZi”ô’ØÊZe²Æˆ´"k”¢Ä7À È,ŒGXîHad&^Öx¶®¬BÃÜq²â@ÖåÈ ×¥ÖãËGÓLb‚˜ˆ¦’‚ã lk _Õgq´šöŽe[U« j)ó007¸-±ÀkW£!;%r[‡bå™X;¾r Ïpæë•Cçâ K/`‡’}®¾ 6AoÑÊa«çø€s¦Q«°#´v|dY%1ª*±Êj¤Öã«*¤,£#¸!¥r³º¢ºÈÖÉ™ÌÚ‘3‘"Seë»=™›±eh%«;gú̓§¤ïeÛÀ€ÙðªÅÛŠá³-vê¶ahšü-'ˆ\ªŽZdµì¬¤š“ƒ/(ó‹x½œ×ªEŒ•ãÔ®ÎVð'håSt4YÛLúö#CÊâ5êŸWçg.Õ‡‹R!MVÞ<€’bh€ô²€* Žl²p†­‘½ÃH¡Äš2pØ ×H lNï|wª@æ¬(7ÛäF\ëHæ•¿­‰›¼ƒ|\îAÈúÐi'ÔÊÖN ÐK óOC JÔHªlæ¥*žfƒ²u_9RøùØ#ÖNª‡ÎÄýðh°[‚Ó°²ÕÂÖléÉš°ˆK¥9ÿŸ€™ÚQdš‘^•5HãTêáªô )“YÞÅŗ‹°’îÔ6`ÍxO¢Ã`ªÅïR0^!l0kŽÉŸŸ žÀ”’õ´®¯,Pdý±Í)½5M_”„[רmppo}†˜žeÇ”… î³”£)÷¶úuŸ3ç Êö*%0VάØÀjBš&QE€/¦®åç&sŽŸɤwYÖ¶PŽ)`d­}séÕÕá‘|z•}0™ a>­RU)Ù#úž‚AÂÉ&hY|þ r×c ÁŸ¾>¶Fåì˜sKP_¸a€Ù¶v¶=nÛª´«g…ç–2lBYæZãÝ<ÏRz«ÈÐ"s¯–¯ZÝó·²¢Q K5sVñ°Øó§ÇÇü˜D¯œ ´3­­ùEJ+ðguû|U¢Q•ÔÓx[cd1­ #Ùr¶j¡´Ê"Ú ˜²9§'«#FØf[—•>A`ž²¶páÝöÇ¡U*`%Î?œ‰µa¡]­ºg׋$ sXY'êÎ; 1AßúÛ‘’ÞlY¶éwcJºŠ>ÔZd2+YnVÑT¶dùdØ`J*šárçÁdò1¹Ù*›ŸR_+±á‚Œ¿áw]ª0¢9Éèsˆ·VŪ¯b—©ŠÌÖÚØZsÄ"2žµ³Mf 饈•Åg¹KJYEÙ”ÛfÂO ¤l3‘õôu—"ë%ÇÜy ü#«–Xm€¡­’@4§ v"¶þÒÇÀKáeakn€Ib”ëKŒ‰ÄcðĘÎ4Œ¬²bd›ÄöÔ?¯S²L(˶5U ZYAOf[*䔵ÓY\îr*Ÿ›Ôip5O%>³lÉ04ñ »:ü¥´ tp«¨ 7ØÊ@”íUY÷™?,»ñ ]>+Af‹oN T§ÎdåÜvüf–ʪy2ì xAi­¶±¥6ájSÚŠ0Òoòø+ü|¯N&KÙ`H¿Š8š-q)¤°ebmZÀÙ1Ä5‚ÑÃ(]@̧àÙ6=¼ííóž²BY¯q§°ÅÃ{%*ÏÖH@½b °’276þÌã¿PA+Vtõì(ly)6Ä4祸?BàÅ-ý|VûØcT½>ÌOãï a|¿€™«åYy`£ÚpšÉÔžQ¾Ÿš|š$œ 5DÙ-[d‘þ»;ÿ™2P¶’~ú:NÍiëÛ¿,OCªÅl†æ·b6Ìéq/ßÓb¥ÊVJ­GÓgÖm“e‚Ùløž)dkÙFíÑTX–ëšRÚ®0+þôVʉMk+›€Ü$`–Šg`¬ÎëÝ^•4˜Ö”†^ë{ç× [Ù¬n«Ï¯z9He­E)ØHü}ä|ÀÞÃJÑHMŸ ·~ pêžIkJ*´v Í¡ªî¡Ë'VUªªFÊÊѤh8È [1ËZsÃ×S…LzF=/ÎŽÐÙZݪZ‚ yîVùd%E#d1msp{ZHá›V9 pê¿?³×1!Û„WxšPiÄèÎÓÌp>rÛJ0Ü8TÅÖl­Ü¬xÃûÀZÕVn•í€Êá²%¹Y›ÜŠôf–ºŸ¥î6ÝM_îm+´¦ÎÜ„9ÓÀÎd¶qCLæèàÞÓç‹0†Æ£¹Qö©ñáˆZ³Í¹dÀZ4’Õ ¢Q¥â+×ËVTB[AX*†x$Œ<•W?Ÿ”3·ÕZ¶`(°u"k¼‡IY¼*OÁÖcÍ3ža³!·‡gÕ{‚QbËJUÍïÔ% e÷ÇÖã ÃÀRLjñÚªâOOIoþF¢iT áëXk$}Œîl‰Yaš–Þ–^6}VVd¸K¦ÔÎд„ÏÍðLúnÔ—’¦¦R¶Zã^ `+l oóªà¶ `UM`¤ZUBVÄàºL™ 2O²R9À€*|úRã»'ªE+qVÖ.ŠÙ¨.VÀ9×e¶xJÑ$Ž/…dÕý«²Å{‡2)‘žsLùÐôæ(TE0=L†¯{[+†I>áj&¶:xg‡E>€ªÜ:µ9Œ­ÕHÆ S;kg9^÷€e‰kÈœ¸ÂO»°•!ýš®o‚²¬„á­žŽïR<Zñ™¸.»ÀZÃÄ¢rJ8s)G€§ÌÓÐX¯ÁçÚkêQª’õmS÷n#½”À7éÕ2I¯AsÊja ä` °=°á¥’‹ª‡›²Š…£Óüþ}†™)Ü×ùÜxåýˆj[€†  lcê¨$&:ÀÓ‘dÉrÈÐÖldÙ‰®ÓYˆ­/9XEó"Ø Ðh (^Œ±åo5Œ0 Vý{ä~Òû—üXÉ’éÕ=«MoEJ)Ö4=žq&¶‚f2ÛÓ–>ù!ë¾{£¡GºsDƒå 7ƒZÌfvä&Þ.ýªDÆYª{îg@ÿhXŠ+²*$б~ Ó›­^Í ›AÐ{Á¬Yú0XjƒÙŠe ”è.ò· ¶V…&/«*1^¹P*FöŽs^#Y ƒŒ™LÕâÎG–R r$pJXÉ6|d¶Z$e†˜ÀÁ­ ‹”L€ ýšëÚMÛãPþÕž^F"ãÐÑT 0‚Æ´…É€ P‹[t.ÍH¹Áj½÷ isFf+%øÈ¢h˜ä¬;½¨°a¤´eR¹1XUãaJØUð‘uuý@•¬R™‰æ¸_ÿÖf p«>ì7ùùZG6M@¹vº8#¦yŒGÙ0+ož¶JêEÙ²B+ÃZÀPE¬K)Ê>\Þp)áD¶¬0”•[aåRú¶ ³È€rXŠ j'‹„1€¸ÉϗƶéÉÄU}–ª2™ÆÖ$mÓÁ&Çë¾ÉŒá!•ù@2‡Wb¥!v)R°¬Ÿ¬F¦¥ï ë´ÈND¯ÖvA çÜ10¶ÞáRB!Æ@êr%ç]aåcì~õoKܹªÕRÛqGàcÃÛŠiz™#¥V•!ÿE)+7‘@/øºžÅ_–¹È6XÀ”³˜ߴܺC)o°ãS27ƒ ì÷•§‡ŽOiKüvaE¬¼.Êemñ|z:¶xŒÔ/U ÑédEÀx€lk€?PëzõP@ª˜ƒ­^²€ŽèŒ4x«@j‡'6€â‘¶­Y•2²ª.S¶T2åR0IȰFV1^ÀoÿªpS±â`«ªB«?§õ,dbê{»_,LÌ D6-Ùô0Ú¬„-g \m­•Û^Éáó „ÉÑ0¯gV­JÄl›Ù0ù7’Uª#Tëµô«<1ž˜k =,ÐàaÎý}¼­vgÄï'¨vV¼S»üiXÕô°Zšëq^-í1«ê8 Ó•bÒkG€,ËMj·4l šyÏt¯Š›!Ú5Ïíüë·>L„lÀšFU%•7F87JÛª0K™§TY+â4º›Ü¶‘J0‰ï,²ªY7 Ñy#5RëÒÆ4ÏÄÖ*ØÛZq$ jŠ÷C!%‡J„¦Â´xz2?éÍ“þÚ|~¨)$V%“ÙFª1ÆŠér*±&¸=Ϩü›¤Öž~%”ÊÓ[ÉÖ‘Fmå §ªÕh­µð™RŽiå@OLV!¾vñV@ž@óïZ*ŸæÊ¾FmW«JÇÈ W©(gÅMàÍIo›¾¦m§qo²”V×ë*Èd­Ç÷Ž0[aëV{.bL+€Ñ:åúÊ&0$ Á Êf7M_”p¼5ÿ4¬Æ)b)²JÃÓô|‘½ ݃”Ú&QB [•c«D$+e«EÆŸ!î ðœ“,|Ug ã%æ 5íÐàeû<ÊJY;`âõ¥„ ˜`LV¶R" Á™ã è%d)Š4: ¼­•ƵiÊbÒžìö9c¤TÁºd®ÐV [ÎLúü~þKÀì(Ôç{õŸe‘ €Î£MXºv¼Hmêu4B‰HlûÇX­×‹ ±ÓöA‰G®Q]êÈsÈ‘ô¶•‚F­T[£]Ì®;^9ñª¶¥ór´3°×ÝyÛÍïDü1ÒðWe[Ø ˜I½Ona>üU1‘Jd­UE¦gèg‰”*µVÙ.™‰ XdbýŽvN*0¢vm›D $7zÎZØê ØæO,*W‚ï©Hµ*a÷KåCÆJ [€f†daκϹòÏZã­&Á¢St™ÈJðsÐ72åÖx2UZt9 a#õø`zJ2¸‡·¥šI2L-0p% ‘¹µ&K _ÊŠ±æxQ•× ïïÊÖöRuáuÌáGS¤h0%yÒsÖEÔ"`5• HimùHÑéJ <&Á©¿2“c‡ÚÁ«y”ˆdýžã=Ü«ªÜJ¦µµø5R Iö#µ¾4™oe…´ŽQž)[¶"‡>ζUµ3d“dÏÓ6ÆÍØŠj°¬G¹-7Y È Øv½îe~Ñ—µE¦§éA´ÍÊ„il»êzÙZÕîÂé¬Õ¬ÐVœÈ(S#§Yý¬,¬e¹ÈZ1ÕVUm’5wÛ²<½)šÒ38ýotfÐ1¬<1uO¿ã%h˜Ü^ @!­IŒ/µîUt +¡e•¶ù(,‹¶ï]mÈÎèøemk×ÿâMVÆ£÷ùÉIŒ´6 ,º"%é×&&š"S*á`ÍüNtæ,h*á0™ó*§¤A†+|Ëɬ4Ez0°B8m†ÆÀ Ln@Te5‰ò4¶©œ¬­±]—,ˆšòw3œidùÔ×–2½uc«’R5Ÿ¬šR¼…¶5Bš'ÜíÕ¢ÂõMOVÐH­{ Ü©XIVdËÄx¶€ö³Ó*k›ÞªÖH]QÊÄÖIÖŠQ¾áÜI#½‚Êù«-[wív9x” Sbˆ)°-C82±òæQè0TcÈŠÊÊmn@óÉd”pÛªŒQ£ÄÙ6 ,µBú²@}+!žIædçý¾¿<½JV"“”j14Ý<<dƒÑרT<’xw8ÏøùðJf ÐpÖQ¹w ¦ÉM?ýŽŸ‰B)a«6O·AVYÁ°‹¢§l$Uv™Äx€Cšcñ„Z‚Ró)¯Kµ²‚>²mµV|Ù ÓlÍ)›³*¸vpC®;¬èW‚á#0nï=ˆ’§Hê¿_\JÚºÀ?íü‘C©fVècåu øöžFaƒå¿#ì€øÜ¤žJ¬ø<ÆfK#θ÷&ûI¯^awb`[¸ÉáºÔËŠcˆmã_Ó«ú\#õeÒj+½¸s› ´Nó’³Í¡V¤â­pï)âEY±#ä4UÛ¯êü'™Qõ’â`- ¨âƒ´Vž ¬„€8eÀʾK£,K‰·rÄ«o%ôaBÉ&±­u¶wà ?_§Ä‚¿BÙRÀÀ"¦h„^šîíJL@¼1|óU• `HÜV*絶圀f…UY‘giÅëkR0¢¬ ÃR—>—ì,5B’a2$†Y9 Ð3‚«%£ÁWUÓÖåýÈv¢ºàKéµl¡–Ì6bµVÙR<áJ•0R§“&ÀÃVšóyoOTd]c¸­N"Lf+ _çá Õ¹IùUéóFYÊVcécïÑTË@IDAT6±ÙŸÿüg&msÐÈ ½@æ&Ó]ª 怤%A˜&@´5jn‘†Qsȳ## ¤l©ÿsÍYª3Ú*Ô¥‘\š¯r)Mûã27˜žÀ[»…î )Ë)Õ‘‰¥D])þaJ2Ñ¡˜dÞ¨½:0¾àOlÛxëN ³ZGæ ¥>M ûdäÓ`8µZó8ˆÙZ¥ü7´im;lc[ç‚¡m½(›PSQ/ÙM€´À?î3RSIÖ¨ÿ®;Htí¶•(ÚH/3MÇ™|ð¹¥zŒœ], Ï‘î}vc É3ÚbæÝêY«ÍdƒEUoS%uÉv…]…¦²ßngøŽ¨;Æ–Æ*4‚­]T7à>¥XñÇ8šƒF— ;m3Ó0w"µV%e°Éðød@_9—m$í6•^R ÌPì•à#%TUØófõº’söÀô1MUJë‘“àó„…ÙÛË=†²çÒ6=q`žµËGŠ•µƒw™—JœIo+láVÛ|¦žBú”˜@2kèŒ.™ÀûàHXùÒ¶ñʪ´é÷Ë-ÆqªêÓm˜î‡›r|ÎÖ_Êv8Æš¿•yÛYJ|âaYa†Â0}Š‡Ê–†¾{SNŒ™O£„¬mk%¬Äª(áÿú ?}ù[=Î}®»:[d¿î›Ö`œ•àa\k@HYk ÷(uïSyGû|'“q柞­ì¦UO€×‹@6ÒÚåfÐÈÀÉ: =ñN¤¶È¿F /Å“ B)¼rz¸oN2½¬Ó4˜yÔJa9cR‰!kJƒ´r{+’‰lÕbdRÊ‘¶1¥v±ò¯Åå>¿äŒGÖ×HJéb<+\ `Vü•$ãÀ¸%©3â÷ëIáp†¸o~Ìæä¬D# ²Fm §´'àÙN¬\d…TBƒq(…¶:ʦožôuž¾v¬j‰»“ª*Ü Æx™ËòÇÈöªtº‘xøõ +шŽûi™[Su²º#e•M¥]ÏNw$œ˜Ȫé+𢑪ºY%R‹[tžg©>bøÝRóëŽ!“bÛHl«kï Ÿc}ÇSR‹ ©öœÅ¿@¡~‰ÆõîxgQI]WbŒuÇ€…*+Ò-Sú^Û›?‹¬F”S—<[3d®WnJNûÛ®C"™T"E)åó 8?%>MÝ1PÕ"AY%ݵUx”ÈNaþl¯¤³T‹Ù%kgëPœõm«¢¡O‰aomZÇÔ®;Q(l¯Ù¹ ¡Dìhy*'xA ð ÿë¥$NVÖšs]œ+g+ÞªÀ°”©š¹1jG $[k@¸jVH `åМpÙÀ™þûÜ*—ítV©ky~åË6¥P%Ùp%‘ òÉÁx4=Íß · œÆg•­KèRA 3ÂL›3 œ¡I¹¨W&9¬Ð›Æ˜L_q ýj³µVˆgN œOÂýúS¥/F-%²QUÜ ¤m‘-PÎØ—ƒ,«4ôl§TµHà&ON–mLʪZé;xç­#hí ‰i…Jf¥ówÎn¯ùÉàÕ‡5ª}“[7¹™Iš¼ÔÜšM Ÿl*«kÄÀj¹t)‘#bên«ŠÞýû}43ГÙ´Mvêo(ÁäL\tŠºcd»“xu•T5[|ð"Aµ­¥(󩪵#4B&NiËÁAò”ú&OYG^H7iKÙj¾ŸbÝI/9óüõúÿ‚¿na+ˆ1ñ+Äs3^ gJàCjKÓà )kòü Ó4?‚ºçiUR¾cúÁ­°*‡†?7qN~¯ZJ½ck%PVbZL[ !E J€:êÎ ÙxÖa g¨n’ð;aþ=ÙJ8×(?sžý8&“‚ÕîY#™UbxQª›m2€‰‹µ²UPæ@ƒÉ³#ÐÛj-0"r|87x•¾¯°ÓYµ³æÙ-©¢¬]†ô¢Â<ÁèÏïH ¸+X¯°Eþjê¥Õ¡l×’¦v E…%F8M$ž»µbnݧvå9»«ÂVG…ÆÈ*“·*õx¤Ut™µ³fËŠ, ÔÝ chDåµ CÉÓJiŒ^•º8Û”sæP/+YcÓÀý솰¥×ŽLà1¶ºô¹ž9 ¥„Éù€½i˜vŸçì€[ÕXEÓ4¬“~~¨„;¼8ñõø¸!µÎÙªVø{@\y…²1ú6!^pãd2C­uW+œ¹Q™$¨#¬\ÐH …­ÕZmɺV1åz”R4:»û·ð»d-DµVY[Ý΂<ã~ï6+ÛÄÀ5øLh«°ã$ÐW Ū2ÁkTÖÙ ð‚!l•RÒêSaþV|Û¦µª-kë•ZÇ ­¹ZÓ²•º®Ü”L#kY‚¬¤(™t«x¯ ,LÏA`ÂH[Uùd’[%p)²Ä1H¡PPöPhê‹)eÍMjæ ‘¢ìuú\)Òðé "&e…ó'†¥€¾‰ÕZ‘v!p1ö“Ùªª{¯bdíæì˜l‘nú|YÜ·z]ðÌYe[9=²òxVÕÊagaèë"^‰ÁÄz‘e%%Úbèm›­ñ’e‹nÅç)À™«ÍÌ6±¦îÄõ²5$#TY;KÝÕf‚ì}SÂÍÖ*%ࢾ6€ % såJr8-ï$˜ôKBIG€æ¶Ád™ $2Y—\÷ÍF‰´ %²D¯\äÃdAÞðj#‰ÓÈkV¹aˆ ©fFÖq *+e…°H` Ë ™Øz3mº¼ü9ê}Ä\Ö• { i8°²ÍÄ*ºgµïåà« ÀmÙ)à Çà¹ñÇÈ Ûe еT~zïÁMìD/˜¨%€ Ÿ/¤ZAÜGÃÓ ”½ R°¬”’^«l¶²ÒÌ3¦ÂdºØºCX ÎÍ uçÜ1m»ÆÏF † Ü$Úå³”¤«¥Wkµ-KМ1M§”šRÔ¢Z¶d¢!‰cZs®ÄqÜÆñe•[;…r€lå§Í€F‰¨EÛdL¬È1”Yåi‘ÕZêqRÊe3ÁÙ ¤ÙÚÄUu ݦíFJ¯\„ó$ÂVµf6’÷ÖcnÑçûÖ‘ùJÁv7©¼™‘á9ÔŶ٘` >J0²¯-^à­MBß“¥'–*[Y@¦¬W«-ñºS Jpcn-(kT‰« # ä,*‘¥Ïs‰/€)+·U¥dÝ¥øO/Û‘ùÿ㯿þò9«‚>á€m¡™âÛôÅõ®Ä6A-ùrðT´WN/´_Ø*”¥ªE*·TÁ€”Fa©²Öœ‰)é‘Í–ažôRVYáê•´5,kàXe 3É“NUÏp{Kb¤ª²Mf«Å©ù^]Jå1&pGÓëH¿O¹p·½^µkÅç¬DØâj;s¸y®ñYʶm‚!WÃSö¯.¦BÖ”@£^Aåó\kd&JÖ¨ñðdÊ+„ù4v ¬£*”m—eˆ‘ÚüpY@ª#×w€éD€-<ý Ó'“m6[ñŽa;çLrHÓJ£W¯(Ÿî-Ÿ¦m† 3ÁÛÆÃª6¡­Z&˜VÏÅ*ÊVÞª5+8@$æÃÄÖcxbà=e$ðµPF°MŸ­”ª•ÂðÌ _÷€•#KÞvÇÄô¦Xa©Ú•’UÒ*ë,âÚ|>­æÏG(Ï!çÈda+½Ó9µ{*é¼R¶ôñm1+Û¶†É)•3’ &ÀmŒ*G³-à€=\V¹¥É¬¥®ä¼T€U;k!ƒõ²®ê-|Ë YóüØ]ój1@“Ðó‡ ÊNƒQÒÌÈáj½rçqÞëš'M$@fÕ…2ÏuŒGŠŽ‰JràJÎÒшEã¹vÛôy ²xçyöýeÔO£ÊœV)$|z|ߤ`Å ˆ1‡Øo ¹Õ£ÐGÏ/îôHúª¬ÇýV‰-Û yžf÷éàmi¤èã¿Á€ëw:öK¥ZU•”µÚ‰@ +[©€¼.¶és£ÁˆÊ‘a«T/üj1 8ì)P"7öN‡Ìœ3=þªmõ (U97v“àG¦y}tìhJô"h  ñUm6ÉS! ´`Y…< ;Ñ[•‡L¬dN àó!+kÎÄ_ô ï³5^÷ÀÍTià&W(‰{‡™à}‹®£ZÃd"ÅÇTJ໵±msNy%pb&Yà¶:Šj•Òt.½m†H¸™×Óqž‰v²Ö™ð„E­)ÓdhÛ¶O¤ñT¥iR×ìð½þñ¯ý«´=@!ç®k‰pm"õˆiËÅpN«\a T xÑñÔEJ‰ïsïÁ=Âñ¿Ïˆ©Ð—ž¿-2O&¬”çIÐØÈ¬®Íùe¥¯ê!Áñ³­jb>]Û4µË¿ßÌ”µk[0C&³Ê¹ÙtRwÀÿúûp™TUÇü[«Ò%Œ”VÒHï`™ÈR6ƒìܬ^½±U!ÞÚ‰ÆØ"=ÍZÃE-`)˜Œ³ªÚaF9ÃÉà”¶œEßÀ+ »É?$¦™YÁ]i %FØ €Y#Ì߲˼uçÛ³IÊ91 …#c¼´HQß:šG ccUrwLƒiWÇ^Z Æ À¬/€qÉ9×¥‹Ê?ÜH”¦R"ÕlV]â3‘íê*LL TÙꨢ•ËÞŸ7J!,UI˜L­ Rºô‹ˆ-qdãÉ ³YÇ9àÉ6^ä­8Ï]¶ 0sz‘•Ù<@¼µÚ¶Jl;xþóA²@AX@Š˜I½Ü«iðn€ymÎTn‹$¨5 ~}3!®m_’4¯Œ©5±è°@Ós†ßÈ'Vbѹ¬Èæ£-⬤`A‰hÎ_vVo9L“8GkB)€¹•Æœñ€›9sßW1© Y¹:ún£ %p#UH)`¤àc] ˆ™g[/U°gM0ϬZ‘ÊûêÀôV(ÉÜ0µS~r^¶³ ÐP*¯p@Ô"¦#܆§µ.˜p>î ãh «µŽ§,hÊÚjsƒ¶{ù} ˆE-h`ædV¤u…RçŸè:Šþʵˆ‡1™4^ƒi¬cUFjHYMê=AU×!q}k¤™anib¬‰É`Gà9TYŒ XKµ¶møÚá#·õ²Œ]Ib‚=G|Øç®óæCYInVÓbÞïÌRZô-Ô‘›ÓJo­uJ[bxÎ@ä€lL\¦›·ÆçPî°¯n@ÕJù¾“J·k8Q}ÀÔšYßd½“ª¸³¢\U-l›³.M5©nRmž`¸ÉsV+`dÁœ­µèKL-Y>R [¡ªÖ€­*YHg¹’£Á#ÀÁZS€UæJ(i¬ÌO [EJ¦ïù>g´åéÑLÓjs[wž¢G̰ãàé³R%ekÅ€ ¿«®¶FRÜ`« ‡fbÊNtN*Þ6qVÚÕqžm«‚3ɹBÎβŸ"W÷@ÕFÖÚŠ‘åÆ èøMbÅÓOLƒi›&¿Pg"ÛÀ3éi2—"ë}ˆß ¼d£–²RzÖá94O·-•@Ó¥&“ª{£fË)lñ#×颚4¨Êƶ¨–#š6çN¡„mæil Šú2\k8Þª‹¾"^j1·1õ²Í|·/eUe%íÝè&7d—f)Q•’Æ 4‰µgMFoËM-YÛ.§±kš3L™­9é­¶ÍÃad7V6ž¬@¾<Üßüç.<F1^ð·z¾=M˜‰ì®Úöèžu5e8Oƒt¡Ì¿V)oþóë`…þžúJvÉè»êÜlûì«ò\«*¥ 6Fw¤iVuX>a >d&q-€Z'“º’3[ü®|)ŒªJj ˦„kZÛ&Ñ% ¶¦·æ,ÛA”t:|µ1•и¨¥ª% X‰Å¬øsëO¦+‚Zo»ùÈ&P¥\ À™ …€@*é»FêE¯|2ÛR˜f¨jünfYOM‹ Ã[ µ€µ*@VÓ<­ÍÀÛ† ­pCˆ—Œ1óÊe#­Èøf³R.KÙ·{ÎÓ–¦s)4¼ Oc›C]ê+Ûö4»×kͰ¾›0GD½dûWÝTåÏ¡gÄÁ>˜ ¶yê2sâ°•9%0‡&™¿-Ü×7áì˜æ” •ã{Km;à ¤VK Ù‚ž=¶êkªº²þ/ïüMFÓJ‰4Öbå_âü5+-`‚"2Þ¢mk4R·ª¤Ÿ&n³i»+YÀ0ç Ý'ÎÇ– nTÝÍ€²¶x¡ªÙ`þ›01fWªIFƒÏǪ ÃzÔÀÈR†µ)1•·¥ÄLY¶ªðk^‰Õä²-ôðëÐU95 ¡#Ü 4žB|Ìž¯â ñÀÀ=»:×HÝ…mçU˜-RV)¯êÈ’e›&&"‡ôÍ–˜,2¥ùe“µÎ “˜[ÙNDF/eBŒ-«fl黢¬Ý’ìœÏˆ÷ ªÏTÌЪÙš­ò Y/‡V³I¡D¦X0*(l‘ÊhlßW–F•ƒ )'!0~í›’#Ê"é›C¹*]ló(cXZS4o#…|©YeÒ„R![8@£ Ï3å÷[ [)³"PBìÛ~Ÿ žr²L0øª²RØ‘¥ÌSw¿¥õ0"+W$ú{ÌĪŒ‘U÷gb ØVÎ3Ûdúv:$eYüîÐ4h_—Èü·Òð1g6FV¦’ ±ëª‘’¾ˆ‘4¶Vµ[RHÁ°€³ò?‡©Åƨ¯|q ÎsTh5€€'Þx¥Â¨Vª“"cË /l ¶ÎÖ„)=zÿ ­}§8ÿ¶¢!É:Päç4Ï'ýüE¡”âòÜ…ØêXV ˜À‘^²Ê³²%fN°TßqǬj£Ñp°Ý]5 â·®ŠÉdo nŒ)~dÍö’Sjꀞ _D<ÏH;æ²a3Ôkclg ½¦É¤^ôR1(¬µG ä-ÌÖªûx[‘ÀDmcè‹q«²p— ÔÈŠï¤ ñBӞ¦BÎ$Ÿ­€ÈHI ôzŒ 诋îQ"U4šæÖl²¢Z|ÛZHa¤Àt-U)éìšê’ ™í”|ÊZá10Á_*g)§l-µ5AÛ9èk{ZÞ_wÜOßê>þpUVX­s‘ýçb`“¼Î˜Ž„9 &ÁÁЬJøÈòºpå½Nî ±ÙÈ0Ê ”[é) Žõµµ"e¹ÁVQw2XJ$kKÏÖ»zIùè1Oï–#¥¶îÀÉ­maÁybzL K vá¥àº´*!CÆ“UžÎ Á§­”0†Zä1§ã–>Jo¶–¢×"åøÜ¤#X)má K!;Ú }‚M Å;*’ƒp¢a”µ°ödɤ„}ÜÆà])½-±ï@ddž²'Ø`V‚M$¶ŠLÖØSf¢#·7ja pPxÎé(ÕÀ]¯.5J@‰·`€Îh¶ 1¢™OC^³³Ð'KÙ$0[|-êØTY…kT¡5}@*†nÀÚ`ù¯KÎùtU;/CO°,RUæž#qJ<•Ù5gþ9¯¦iæƒ1'R$àcØÛÒ•šÁª¤k*i˜º¤TÕ`4ñ³ÍðW‚‘ª#F¨m2“ÚI[ X…ëR9²/‚ô9O‰Œ?F7b"­ ¦¼o3åù[™»„J‰œiîíYu÷78hº®uÏÉV‰m€§`%%8”%ÀgkDïC·î¼Mˆ$nþ¦²-‹¤@þµkf[ c%%F²¶eè{Þ×K7LV•B‘?¿yhÄÒØÖu‘²¥Áˆ+ÿ|öYø\h*k-¬Wûù™¥<ÿ¾ÙÞ·ÄÍ¿Qé;)$ì\‰¥[ÓpÐÒÚ…HúJÁu´5›ò¶Ù6Xšž/¾­ü9ÔE¶36€ HOi»v|ÒRÖ‚&°ìÀWrþZkbæ#‰­p÷ßVMYêLúß³j)5M²ÎIgàÙ494 ài”DZñû˜ÙÊ npþ™´Ö:YGó›b½C-àEŒA@Æ$™Tü˜x+FëjáfhÅ >¶@ÙJøH ‡¶|ÚIU$‡ùWßðp[n˜ºtUedBV—f°U˜nÚf˰’î¡Ë±%–˜RjçÙ·!b¡jþ}D{CúoGÐð$žgojæxY)2œû¤á™ÄVYU”Æ5±8ˆ¶eØÚÌLÚé'nÈïý‹¬ÞœˆV ¸šÌ»Ï9¨¥˜Z,P4ÀÙš¸,s1¨„.…i[9²sÊ~ öqã‰XÓzy².@*À¼‘ˆ»®RHç%|ûg8R"[)óäÓÊ °Š4‰ÛbgÛksfª?•÷°ÍVy…Éêˆ7>˜Ó6Ûn†ž§¸þ,¢TÙ7œm÷PMÿÞ³1z7hl¸Õ¹û™&“N çÜð:61F­™i`ü€Ì­]w2ŒžÙVneU‹)­d.'² üZU[ J7á&)ù¤’Ö4ú£;mG€5jïsÃ_Õ9¦g?óe1Í\аñÈꛟ`[µHˆ>Yµ#º(}¶@#P•ˆ¬WÝ‘‚§Â %n«ÏWAÃX«í‰Øº²º(IfžjÓÃñu &Jè)Œ,’RØæ–¯O|¦Äaª¬øpVÊ t™sd¹å£Ü¶o¡²V·§PJИÓW†FpÈ$ŒWH© “íõøünY¹B†½Q˜Ú•ª)-|zÜ`ÎÁA8E¸ë²*•›ám«j6ëÚÅŒä ð½.bAƒ—5Ò²H)[)aß‘?/˜mY6`Mie‫z;Ö"ÆjTJ/¶’n†y¶%ôlw>bs¾‡ÂgRa¸Áè‹j­y"ÉDŒõ ­m)=n+Ù׿SeË&×éóåЛÉAvžLz^” ¹òd€h¤ _®$ ÿ¶ ]©­Q»[ ­ '®E…ÿø÷¿ÿ­G P›I ©”4aO±*YÑû-ÅšÃ+¶¡O@OVy)<€)lkèTNòfyJsHLïDÛÒx0jeaâs€o9€<¿?2Œ+‘M†1f2XÐ7°¤l¶H3ø›„¡*ž}6ÂdƆ•ˆ.9Ì P§'†#1¢9§ygК€g7C#ÌlËAÈFΧF¶¥š)´«£rµ‚kv>À”Uià+ï7¡UUH#êÒxþîàÛßå¬@)+d­µF—Ⱥϳù‘ò²¶V©°ñ0&´òÄ„«ª/1@A|íŒ Ô«r2¼B¡°˜ÆöŽüyúßüçV¥(yj$Â|0×ïÏGŒ2ÿÞŸ²™+,k…Þ=Œ‘ú¯{–­o“¨õésùHïªð0’&²ƒÈ’Ev^Œ’OÃ`oá#ˆm)iÒ7>’f‚¥*Ls\¾>9¯o¼#7›UJž2qäzÉî³×1e+/N×ïï—Æé¬uï˜ZGžfßÏ ­*àf> }äip ¹%hr+ÃHÊ<­ 醲Rd0pδ¦m…‰Õz:@β¶HÛFJ¯#­¶ S#©¶Î^mU²âŶã&Ï– •U< 0½Gq¯ÑÞg«Â^N|]0JzˆKÉâ8ÔÚõ˜êÕúúŒ¯v倓 嵃‘úš £…mUȶÓt«o#>™#“ÙŠÆ£°Ê SßôÖ®i€œ• …m`[2ØZ$€uL`¤^Ö…-M†>[ g[…î|&y&€9tºÊs˜x©Í<™¾)mÇ(ÉÖä‘Vå¶R9X½ ðb$nM Ç'cÒ„D£éÇ7)2±‘6°{pÿýü" äP‹yÒDv“dÍ ô©‰GVh+U4«¶ IÖ;¿'Kƒ¡y™õb¿m#uc˜ü­Í™ ƈ9è+t±–ºÄY²rµRið¶1¢S$ÓŒÄÓhW!c[!,˜b })@j& 0UÙ†Ø62¥µaj]6Y̦•z••—µ²M™s<,åñu®žòÖÛè!*ìÅH°ŽjáÖ •µ8ÿ@Ù¼j#¨ihÙ¹¬qYÍ“éËÚ`ÑÝñik­p[æjÅRpdæp/.A)ðûöÌ¿vJYÊU!;辺V[$OM¬V ÓU¼&Èô 3©]‡Z—¶Üjj ˲â\-F#¹Ñ[¥^L€ÉŸžÆÖÚ„•ÈáÀ»r[_Ä3§¬Ü(*Ǭ5P8ˆH†¡$‹Ü·¼mZç á|-ŠYI©’ê~l•TÒÿÈ¡íüÕò·Ö芺œÆ+eåSq€Bè•[ªB²NaeÞ–¸b„¥€1ÞU4;…,R6A>0>Üu)!Ut¼­JÁȲ™Àuì¥jà™ÐdbµÎ«¥çz ){ZÞÓ…ýÁ€’Œ˜¹c<Ò¶¦)mñ²•K)¬£’L¶GS¡­"À'[yµúÆÈvŸ?ΫÒž³*óˆ (›²-`µñÍc+õbŒ¬¢‘f8Ϥ€{ ‰u!똶†q󮽪d™[™ccЉ̳òÞ^UØÌ‰ã‘UÍO`ÝØ¥’!ù …duGö MDŠp£r[X–žI¶‘˜æôø¾ízñ‘*dmA‡lËòŽßúºU$AzWu~”¥d…l+²^—þ“*+µ aoè¸p2Ø„†¡ñˆTÞºm/•m]øluº¶µ£gÛ=¬¼["ËÍüyn†)³µ2!  m‘þÖŒ­¯k×…¬;1\ÀZÄÈæã†×÷r€Þ³éÞÌ4M¢Š·ºÔâV¾UÉâ™°òi€ª’)I`›sUp)|ÃØ²“Å›á<¥hlZžB[k“tÀôMX¯´*wÛK’áü›¤iŒÊM%ˆm3§i<€y>­¶1¥6IYÛ½™Éšn €^‚˜€• HYnE)ë¶²•P"ô&ÃkA3C ËDµ^eµ®<÷]]b”šÖ•´­iæUaD²ZuwŠ4uäÀÃ?Ù¶¥š–¦ª)LOŸ-A¤vV…‘Ý<\ >ç4éÝ£ÊZm™¼†ñ>}È”çsç¿lCª bÁÔHŠ:Yc,ú ö,§ì}¢ì<ÄUÕFa2e ­(1ÚI)¤_k[d|²L"µˆø˜ÇV•ŒU©Öf7¡µ¬BŠ`혭“u{52À”@wëûpW]Ã'†Òðdz ¼µ{ÈC£cd[šF’Âü=ðß«×:½µÀ)MU [$Ïw¥˜Çꆔ¤m)Ûô™Üüç»Æ÷`GÓ°6CÃdãUi“ óÛù7<¦¨ÄjŒÿ ¬JìYP*—Z¡­¶é­&¬WsòQ[{ ²0sÀ§.ÌÏSØÒ42Y¶Ö|áz!3Q˹Zik-ðZx2‘êL›ÀVÐX}L0”NalU¶ H–æP6¥Ëi¬Rxd­1°.Öøl3©ÖZ•Ô”ëˆ µ°’ñ7³Œ­°í8²0ÃyÊ"+oªYI©2Ìœ×wd […bš…¡¹™3¡Ë [kg%0O|Û:âÛò”EÆ[ñHA£QŸ‘id‘²®‚@Ha0ÀäeªÅœ÷BzCz·1¯Ø´&w„ÏßáÖ‹ FÖÇå¿«Ò#ßal)ÚÆtöxLž‘+i›§Ö¦µÊöÐñ«2?«.ª‡Þ‰²¢\pØa‘i”s{‡,e¥çim¶=S¤›ìršÖš yš¬¤˜èßTR¶b“¶gU¥…µÉ1J¬4È0°kQ^ÈJÙæßYàž²-Ü–,ç<ÖnïCYbnõ¢ñõbEZI„‚i¸í“!¥D2æ‰ó¤™ãE­eSbÊrËŠ^–!†&@¸Æ(Åad}Û®5’Fä™md8%ì}ËÚÖ½6€Fd‹ìfnŸóp ”ã1‰­e­¥d¯ÇÇÇ9çiÕ‘LT˜¡­”ÂHú"}šü1ÂT=xÃÁxJümrº„²m†µ“™4FÖnVJ²@[UÅÄ`ÁÓZ#kÛe¥/†À‰„SâZæg¾ë–’µ6ÃÈÄRøÍÀ9Œ'°µæïƼ!ÎUªÂô4¶0%†D*ÂVÙ®=FJ±Büçd[½¯/,ðjº…Söý"¨ìLém€)Ô Ó1Úf˜¹5À¥0é÷šýùŽÐÅ™ý7ÎiŒÇœIdÓò¡„ ˜ÆÚxâ=‘-ŸÙÚø£þ^®-¾-`ËßÊY;@£9t ¿‹ø¿B3$1Ab2%uAò´µ’ùÒ¬EþpÑ)àÒ$ñ•|Þr[µ"M— #¾Ž#üzG9óJ´ÀÄg2™Ï ir¤Àˆ‰1pdJÏÅ`ôêPgב¦Ún nN&Fm6Yy|¸Á¬”øYm+o° Môhâ«ZyWÍc ÉtQ‚o5R|]dÙVbÍg¤’R•ÃRÉJ­o We†]å‚OÊÎÒ=7‰µ.Äø>0=[zŸâ¶U÷/i(ô€’™p†ô¶²fnÅ/ŸU…0eÙF²Fnæ|6s€­XV•­UÖV%’•W«ÇŠ_È 2& îÁ:žX¶îæä†±x2…‰SΜ ,€TkŒJNñ ¤¿’ÅdÞ0xñÚÒÛÊ @V¡°5Xbá+Ô3BÇèŽjëtš*×é\¤VÙ½Jlèþ ÖZ_ïC…&úf" ˜²B«l…ÖBmïpz‚µ&à@ ³Õ‰±Ò#›_*&[!51‡H%E&¢ÁZU1‘%S¤-€RÚFJVe«]7öγU¹èêÂJ“ðçÃVÔ×úÓ—X U lUýL;·²VzÁY=k>ÈR5ÂÓˆH?0{y`$¥uÀöô¸E07Ú5a€ÒÖTB¹ŸP3g[#k²Î².ù·åœ†öâen+Ö‚Æ•`SYmÇØ³õÏ<ͦÜ„×õ˜è‚¤@¬c×Ë!Ãî°%`Hn²Re3³²½–g|MUVüJFÖNy'0 +l€žB–*Òã¦1ª-5’@vFúd%üÜdmUá³²RË|Í®SIâ té–ƹ”÷ï ÷1ÍvóŸÏE˜¤'£S6ŸZÇ준(e-«Æw]HæHQÓž2LÖËö¶ðUŒOi•ÚÑ2ÜåzORZõµzåŒæç¿P3,‘â®Þ¶zã{K0}ô‘PÕXƒLÜCßÛ´lb|]9(´¾ç”Õ—Œ@àœ?fï+^ä€o6[sö·$e›M‰È¤2-0?“ÈšÄ*%4ÄpÓ^ú3ŒC•e…0™Tµ¥lèûÒÀÈýd…EG®Y­ðXܧØAdN¡ÊÙËâFÄ0œÚŠ”þjÏ’•, åÒšá¸ÜX¹]”köùš€Ý +Ú†e­xÌ9ü½1÷ïrú*ÑÅ {ȺüaOÍñyÒtg‚ï·RMk‘çÖeJØ6¡^x«.J’Ün‡ó¬M%‹·!&+<,”µvp­ã›Ÿ9 ­]TUÖÑHÛ‚ƒ¨Q ‡ªðJòÑt“‰34¿Bd})m¥„ZÙáøl#}*= ŒTåÀú¦7szΠɲR°kÚñ#'è8H‘¹’þW¹¶B•XJj‡ÙÙÀ±»YµK©BvEe¥˜ÛêÜ0¥+]»Æ D6 àk¡#'@2±òÉ¿Éu¬‹mw^£4S&¶Žy;"o£¾±Ó¨2ÕÖìÙšD•T[Ù” ‹ >¥ª42^-Ò*Ô’u±H[$F0´E¶”[E¯Áçã\Š’Un[«{®‹Ÿ½T ‘»ùüs«Äj[¶”î¶a‚>>¬r“"®Ð¶‘èùé~4Ô OŒTÈÊÀZä‰ibØÀU±ÊÍJv.â *LF¹ÀÃ?å •ï\Ü•™^I†µ†9tWRµÆ¸m§±¬lùûm[ PÕ¡*§Á‹ºÖ4P‰ª¬t¹Þç©yoµ(l•7' ÷Gåm)­B ¾‡’s¶™X hZ[Ý׺9­"±h[ë à+,[ ¼­8Wÿ•8=e‘à ?_ñ iµUN§aŒ& #…’Öך@-P +wc®®4óQÅä[w¦Z–Æ Ð<V…+úõ 4^<¦+â‰Ù;y§8 Òj€j'F*AêÕ<”^_k†EÛãx mM®D9Fa¡Qk%sÌ.AÖñôdÂTV$, lÍ!±mÃïG­R(ñѳ 1¼8e§¸–D_½¨µ¬­,k«A¥ÂÖì:bH¨åÀß#Aò1™ÖÚò”-¥¤ÙdE]à&É8ÆÙX)áÙlx€-¬­¬mVL05ÍÄZGd¤ò”µ¦‘ºÛΦºˆ°lçRÂÍꧬ¯@ªãtH£6¬‘Úl‰ñ0‡[›“Ubñ¥Ú6¿Ö”ÖÝŒn7Ùõ2—]£ºóaxÏÝŽ$Ëæ@Ó$µ–ÂTn̵ë¶m;2 nKS/åõŠGbTY›p˜Œom~ “4[eE>LÌ S¦'ˇhN²[t¦*‹W¥ÖC„eó1†-̧'¶4Ä4…Ÿ®lA#U i¶ÊùT%E†©Va€?l¶?kÙ“i¥Áïtmýs)‡’êk3`ŠN¾ØÓÈêP´­ÐÚ¨ ™Ó4‘”˜l»OŒ”ð©Ç³MleeëW)M1=°m“Xë(„yêehHxåøVLµª„­2˜àÖÌ™à}üéi´³uÿ¾ l)ñ˜¥TË™›l½VQÓÓû[V óoUU¡u©Ì«âC‰©èYÓ¸L¶µË“ി߇uL «K)3;]z +²¦µ ¶-Ûx|Ddn¶¥ÔŠWÜõÖ‚†'†ž&+FU§‹'ÀЋ ªzm›IXHuJÀVw6@‚üÓ7³MLŒP‹ÔBð„ÛZ‰€^tXnR 1¶^øô°È€ƒW®o %¶È=1PØfî©Á}9HÁõRN¿UH‘Ã@SQÀäš6äj‰ñÈšvLYÓ²ïxÀ^3¡„½Ÿ]²¾<1¶¥¾ë’ÕŽ ó•4¶lÎ }‡T'3‚ è¤Rô­ë0ئe%h¬²B•-€ìh¦ÈÜmw@bøH«m§–åÆœÀgµ‘³mÓÏ?CJU²ñµ®»B)a[¹IÈ0d²ñY `ž|Ê&ƒÛf¢ÜV*ÉJíR²yb€œU½æž‚”©Å˦T¢\ÄîG–?\kkÙ.äï]d‰ÙªUXm%ÈZXùô™š’@Ïj$—¦’þfþ<-ÞM àRU-0Üj-% ‡5:¿Ž˜ÆÞ†ZÀÂÒa€ºîåi¶Åtó®y¤÷ócM™¡­!›ÓH¶Z/Þ0¤Ìspjšž#žL!ÍIÐY²}M0b“ÀJ„©¬máŽ@V ¨{—i ¿î¼YÑ„sÎ)0¦—>ƒ•妶.@J S¶<_Föèžo´Eë[ñ~0§OS6gL¯I<ŽÈ‰õ­¤(WKߨ}½häY$ˆWÂG¹˜-Ü„²;,†`²V [±ja‡â +ê¥]­ [M¥&V \ÏÉÞúLu3ü€eÜØ 3`"¹™ ža7Ó–ao- q—70Áœ_[2|£ÒÍ(Œ¯Ð:q<ó·DëÊ o‹„Õf[¯®Ë3\aÃ#+RÚÝ9Xè^Äp<ò0†Ø‘¹ÁL¤®ÁçU‡çVÊZ¡”WÑV MVUñg‹d‹Èò‰¯S6Ašš6Ìèj”B¹¾]&¾ª|¬{ ‰­4‰šÄhʪUë‚ìauX[@ÈÂjï÷LÎxY>2€„}äuáÓ¹©*@lµÄ¥²²Ú?SliTMC‰·J ÷U4˜U*[ë‚?>W¯Ò½©ŠA¶=hÀ‡¿ŸDxV#æ ððÝ€Á6rÙÍß;£VÐtc@[&€ªÂV” C nªH‚“š. >®' ^aÏhªøÉ*ÉÁZmިɪ…1°XIÛÖ>hR¶¹^ÁÜ  ]áUÆ® À bÓÔˆƒHF Ø(wêª:Qc”¢—ÂX=5þ‘žÏ:çß#Sh˪Ô’©ͰUjÿ™?bL3Ô—¡kÔ+÷Þ&£ß0Ê™Õ.¥-¥”C –EÖCÿ㯿þ"’NATãwÇ*›OÔg >ò]º”±8H aKP8$¾sâ…­”U!1Œä3¸6g Ýýžê`®F•’&Üu(irk†uÄw_5j«V zxÝcº%xA P¯ZÓHÕÑ*ÚúÖ Žˆóq:µø¾Ö“UâùPÖQ¹ ±4…’}@—œaz>d·ô³TnHcPP"+„éIX; í»&Nƒï€ï` ͆ñEúia,¤˜ ±ä¦2-LãE•UEVIØ–[ÎÕ*¯ +l 2äxÎp$LÃÓÖq"m» ²® ãi›2FU£ EO öAˆÙÙóé€ =§áÙxÆÃcˆÓï{¥WòyKsK£d€Æ¶Ÿ o<âF s¾§£°UX‹†orØ—šF¶Í¤ŽL”c¬¢mnÚª"a`úZ¤T>%MÛî!l<@JT8}ã%ãµÖŽ|‰³(!(:Z† Yþµ A~+Îë —JÜ'½’î$¦B<`í †1g[«Y>ž BX/dq*/cUÈÓ[×ÿÚÞV$èšSJ9ƪEa¯ŠÕ¶¨ ’[˜CV™Ìüj!`’óÿDgSe:‡ÑFp‘Ò&Tœ»”€¥(# Ö_6Aï:F V.By]”+l+…´6Øéqßu&4~ï÷} Ø2,`¤*¸`‚d"4•¤¬ð1½YŒ*aÛól•LˆÎ¢\6·~Æt{é—²¥ì¤Àl5åà—Wk4ÒÊmáR¬„.VŒUªyâ#ëbU+¬¶eâl‘HéVî´ráf@ÚòœŒ¹ ×½ «}×xkMÛv¢‘uáÚZûLM k‹µƒ› `²->Ž7Ò4¢íšrCZ=\šÌ§Á¸gb+°•ÔiËŠƒU!¦*@¨õÐ˪…—M¿¬w,ÛLdÏôøÏþÓ¸*ÑÄDÂÖÊhë”Ù¥Yo[¤*)ˆG@IDAT+2`Mãä5Ò©;^Àj~Ï–êoü#ûRžRŠÞʳ[°í„ZàßÕ¶V¯ ^$Ækzæ¸a‹+'KfžšJupÀ¡¬ªÈ:/e†˜Z;ÔleE(ß é5Ϭү5®öVœß)k”Jò$Õ6³¾ Œ·%«¤ñÔVØJ#2±Ž„ÛúL*RºR˜+9 ÌGJGkžs™!¥üXµúL+¬Q«òbJµHŒhk]Uïý¡7°w¬ëô*z] [<Ûx+#œÔœ¬èaVRî6Akå°¬Öd«Ué+©EÃÀÀÛWá9Ø |)²qq3–—„WeBØ$V¸‘xÓXj°æÑ—¿³ÀHÙÞÛÄLÔr“"v-*/T²b-d;H­¥ÚÖTöÙ´x-¤xÖ£– °ÍÐ*xâ5Å›ÜV¨mY© ½™7D [¶SVeX9=ÿfÊ ƒ·Å+‡(Dò´ÝWŸ’¢Fe €0ž€gåò©…c&Û€ØkF \;zJ©ÚÙ >YIµ•Õhc_Õyñ¯>Ü9˜Éàô:Z 4Ê|¤räôeözä)ÛÇ–ÓýXkÝð÷Üçu²µ49l$YÄc" *qi°O–? ÂÄ'™mY 7¯°7- [ÙÜj¡<Ÿ¥Ô"{@ ñô|ðÒHi`Y¡£h¶â뮩Á0Ûy)—‚‘ EVb<ßØÖŸAl¥´ö2GæÿT5óÉ(i š¢a¾»s¨ '®‹µ‡NO`x%õm› öò¬u©º¨"àÓÙW¸›ù‰ [|‘ã+±jÁ‡³’Õ—¸H¼”§ö>³5  ïEí 1°ª¬àȶj|€eÔëH 0Ÿó?‚(ª§VlkÝI±9Ô' 2aˆF‘™Ëæ&˳ù”·â<`A£Kyù<]¸Ï•Ô&¬•˜I ÕÖ7gæR]kµº‡iš¼yô ЈÎâBóÁha%h0«P5vÙª"óhý^Ø'ªSGU &…iìuO£Q ¥¸­ÎEÕ±ƒèÛÛàê«Ê¡­Ñ ñ•d XÙšæ#ö¶HÙJ nüŒ„ÃX)×K-\S@ŠàžµT×X*¥5žXŠF¡91À -ÄnCa-*Éœ‰ Á¶@ó,¶-CÙÆ¶JÑÈŠ¦*kKl¶Ü`|¿aHyšË(+·%°˜ÌHPª±+ìt5í6àdRñ懲­ÚŸ@x µrÓÑÌÆb›oŒl`(Qk+TÉz±ÛÊJašÉS-ž’-^¬µT¤hàœk÷6•µUX;[%­y6Fíê8ÃRVSeÛ¶ôz¡KÎ}6KÉ" hÔ z¤5Û¬\ *Œð¯õ»( ½ÂÓã> >¼ÀHõ *¿ÝNkßäª8{?m+´¦—ÂG2L VÖÚ²°l|À*˶*)8}ÎUYóòÔ‘ÌV¡ Á6O¼­€ûbä/ˆujš,ž-·#ºA ˆ•”V™k$a‹×QøÒइë‹ÉÐV¨Jdá&Ñ©6ò܇¨JJÉÚâm=èž mnN7ç©¿Ñ£¥:ˆj„”4Ùiö½(ÙlŒ²¨*7bۢ뢡ÇÔô›<}Ëem•8}ÑyÍÓ ™tŠÍ„­ô&¬En‘õ’"ƒYž¹-‹Í µmªJœIcÄÐ3>¼†¯WþægU¹ g›X9@³ah`z©Â¶è˜VÁGV¯Ìëˆ_ %²9ð÷)ÈY;2zïÌôŸNÏC©V!Í.œL;Î@&[æ^Âx[æ0Abh›ƒí¬dE†áÄéanéiD[YSYû–ÃÛ:Ú•œ‘”8 È8[ekD#â¶óRÖ±^á.^d¢³Ö ÕxêžØÚV l¶måy¦N ÊTª„”µi‘µÈÊA2ït”pz[b«Pnµœ1s[í5ÿ˜¤fhÕH»5Šù²“S/4ð)'l•¹ êmaóÙªâRh/¼¬ÄªXu6$|óŸŸ"jùuÎJêÕÚ<°HÌ„C¸¾94€‘Z¤¯u©õÍ­óšÀpP ÷ƒG¹­Â5Í  WÈœ#âé…^!ý°*wiluÄ“u…€¬èó/gÃÖ‚ÐrèJ­d}äTÙzÝæ£D£3ÜOa'ÍYU@áîDIÎõ¥×ګ¡¾¶ÊLÒØÖ#l•ĤÌ!e)i´šîêx:N2k›ÖðÝ|ÎLjô³’ÕÎדT%Zð¯§è~ˆa“4`KÖ ”J3äÓŸOxvŸ†'`Ðè(…iŒšâëh[/€›ˆ )[ÊHY<Üö«ú#þaÞmV19°À<=h-šVªÚvÛÆ³ ä¦<>ÐJãÿô ÿ'«Ê+Yßm›Ç$]^ ±.¶ÍÅ[CUoEâ]H€¦G)«ÉÄÑàºàÞØ”‘<ëem*YU=k%ƒd+3—R2žþÖBA mتJJDb`×ÕÑd©]$SI#u lùXeið5êûP¹ªrd«¿+,Uwzµ4¹!ï†OÑx¶R9[ECzã9¼gLpìn••CóÇÐ SÑ}â1R¶Vc èøBs¢xkš«ý¿õBæ–ƒBb] #h¤`-d=boTí˜_ÕGYyJ¡VîÇÖ–m…¥l‰á†q´ihG_•UÉ&éï:u‡f£ìì4w„óš5'«™ E÷3òŸÁèeº˜G#˜C—d ,Õ„ñÖÊ­†i$×bk$]øÏ‘@rÐ… £Yá™”O“®¨!e.ÎùsƈFº ÏñÖ±u´¦G:žC%éñÊc¬HQ‹¶VÛdRm[ms#8e߬-ÏL–ÚäÙ§¹u§£ ïv.|ó' ”ò¤±À7‰•Ò–¯—­h$Œ·¥´<”çŸÈ1U&îí§³ýèî/|õ&KÏ Ö¸«±Í7«Là^唎Q¶^3·UÎ*Fk²f…miÊbÑFÍÓeá¾}%V¼Ž€’æ¤ÞZÙ†¼Ç\ÖxÎ.š“F/)Çì¤VÖZÈÚfbÅ Rh|œ`_ÀLªÕKUÃÐØ Ub¿ˆ463üê‘Ü’i!d[3ñaÖÆ’2«ÖÆCŠf´RŠ›¾ôYm­l‰cà•w'¶R¸U&úrÁ“±RØ´ô²š0¯œƒ°¥/l+œ?Ð$ý4"ã“-¥m«B`AÐ;>±Ùø²5‚ñJ)Ä8H€ 2O *VO©K§CΙÆ¦ÇwX a¬‹ZTõC¶Í6ì|*Ñ¥iµ0§SôP0°lz[bóTØð¢¶ò² ðk±5AàsN©*C@t™SÚ"9Īv{À†©–^ÄcTª„”Z̓‡xâȪ@ï=lÍ*>[«ë5 C<qzÙ1Ý&­ã¨RnÅW" ‹NØ(¶U%4õÝ¢¶‘ú@ám¥¾Eg¤®%™µ‚ÂÿÇ×lÙrKxè<ðòòûø¤¿*NÑpoD(222¥ª½»Ï1$7€Àñ9°ªy•îý„ÛZÉè…Ý ÌG”ÍŸLG¸ÿjY-êh‰ñ”Ë*Ñ´QI*}e+Ô–5‰ò¥\‹‘0‘™c%M•`¢‘ÞÃÕŽ8½AcÝÌœ1"¥ÕUtتÊ*á\•U\×_/f&§Í}4S‘f¦if$&OX*7kú¶ÙªRb-…l¶Í@V•ÈÖJf[mà¤ßû Xº@¿)òq?¶œU ¯íyï½Ñ³e.Û0UŠƒ€›@x]‘=5ÛRé­RÊñp1ÍáùÔÀ ¬œþ›Šçåp¿–Ïg3A$[>”ØÏ#µ{ç#Y­• âkG˜›m]œ:±-ö¾Á=ýdªx¦¾X ¼î4° JGÀ*Ë0YJ+Ø äY­r•›ÕžO²Y¢©¬p—°îyF2)˜T…ªFõšçœI+fÛ@åjm™Xa‘ÀyZ+DôV7O¯¯1·õr"eÝF©la@¸"=5[8[]hs ~J$ÏJðªhš­y~ûûï¿]…\ÓHç®h ›,‹”xz<€·r”Â$ã hï#Oâ ¥”ï¿n9çÜ"Uål (”²¦·âµ³²ÍÙŠ×=`[UcàsS(¶­ižµ–âæ©>.WVPö)’õ‰m«ÉÙ¶*w }ªaVd²YUn’Na[ÊŠ)˜Û YæE “¶RáÉ̃áÐ%ô# N™  ˆ‘¸Úõj†”ÝO+Y¡ PÂ3=Œ´v9ÇM®;€¤DVmñ|Z¥€ âµ0­«c.õ=EÝÉVƒI+žÆs±…E|í*l¶.h;#YXyã°…­²ªòÇ(´n+[àÍϧw s‡:SÙ ¼r+¥Pó' '«j+Ø6 †máï·pÙ!e›ÙE¹¶Ç÷ŽjKÉ$1R;2+Ò*Û4¬¬u'Ò"Y‡Rk[ @Vaí’ÙvÕ4âŒx<ÃK)©<§i%¦”òFÕ7ñV)|[€>ýÞ㉘\Àl•È^ÔÊ¥æ£\lK™þ8Þªžo¤Dºù4¶xc<²áñ4 ÛNLV/«”/U@ß<¬l3TBCXïiÎ7›¬Søq¥ª¨¯ÓIa2T%vdkMi6Û SJyóé»®¬¸)œ?eÛ|l“)ÁcN «k­/Y­³ÒÔߌÂZS*”íÞÚ2¯¤9aáºe#îÄÊM‹îªñ|Xa6’¦"Û2QÇÛç¼Zm Râ¯êù8'«EXÇÖx Zívœ4Ù*Q+%h`úܬ Ù¡òü¶S’)VõÚOƪ‹uKn®;A‘-‡dH&ù«•mNßT|Âé5{¾ȸ1ñ€¤¼ð~ë0½”•[†áæŒ!P[ËÚµž²÷«&O஬Bë•ôb¬ãLJÓz!³2¤ZÉTuö¯§’.§”mµÄ®ÅJŒ1L)7€Þ ØÒðgB)à`QŠƒTk&R»]¤h¤¬²•dåDHÝ¥¬xÛ|êb§®Kµ&£D¦¯¶.°`X z¸-lpݵ«QJÛëñ,•ÞJ/$è#‰k`¬¢I€¯Œ©ŠI“ô86IÙR‰@ÊÒ«ÂR=/æxb|J©j­®m](½{ªš éé;æ·?þø 9s¾Š1DÕ¯lÏXvÕ²öxm¬‚@Y@0À²R‰YUšHY©1¶º´­nkrÎnO…é{;Mn˜ÄR ég˜­ZX¹UâFµEbDŒÐô"‹q97sfp>ÍV‰µ¬œmóñÄóé‡k×úVÕ«Ð ñ7a+;CŒ-‡›<ð È¿¿ˆ‹L8˜Äo&ñ–(±%`ÒÓÇÐ ¥€œs o*@;dY¤-“ªÛRÖ"¦’13©¯lãµðˆEnœAäk|þS¹¬8M#5p§à\¶#[SêU;ž¢£Q¶Ëf®ÊHÌklY)«-^6 |wH°×òÛ/Ìo­ª9Õx+ç¶¥¬²Ilab혜ùîãV8ˆu#…éuTh+l šÖñ¶µ¨£—¬ªxõ0Éúø$æ,”°²vXå²¶J݃lóà ƒ)¥€ú*ÉG–²cb2A’e› 7Ù<³²e(Òäœ-C£Öq¡ÚŽÆ\–ƒ•ß5i04¾hÌ"ÞvÃa©:fb$|zäiËDw2Ÿz%׿y¦øô[UÑï˜@gÏ­­sÙælE¶ÝH ib|ž”ð i*Ä+¡·uE@Jâsé÷§Ib>u,EÏ-ÿZÈŠp½hªŠ‡òOØæëbUb5F[øºž‡¦w.Ñ6X¡GoÍpzŒ.Lðlé1²€@ª"€™7sUư*±bèi¬dµ¶²5²¦Ï­B»FY‘¶æñc¥u”RôHñrσh…e­™LvÇ<ïçï¿ÿ^y…š`|)µFÕ±!;¦í<;Æ`²Ý¤Ú†ÁPpÀ®¢”_C“!”Æ®×#IÊ6FT…ÉÍÚ´”H ûáëK@VbUk%¬Ä9È:”˜X*F ܹRª]¸´Rô°5ÿ1U1QçLÙ<éa¼5`›ªªdªDVkÁYmM1€¯ @¹••,¼³²ºY«*k©*C”ã‘@µ1ÖJÒÀ² ƒ}ri:‘-A!;0 :;PS€àÇ6滪rF&½ µë8¾9¥t‡¯l)&²l›“ s¸yÔ YÁS•TO­.xÏâü@²ªt*{BÚTIÝ—lsÐHÕ£ãHù*¡¡—M©½”­è¹fµ9>V> +·]¯H³ÕN SŒ‘åßõe˜'¾­l%»Ž|Ú6›ÁºÇ&…*Êf˜ ;Üxn,½BžH 7˜X»f\{)%¶u+§ì¤ YÊV­v4ÕÖwÛYÉFb6›Il×±. E‡ÒeQV 7>À:²ôR†lemEl™TB,jÔÖ´C¡Ö14 â¯ñóÉÇÓPÞ¢ç§ãùù&"–êð€_ʦ•ƒ»ØœMH¦*ŸÖ.±l©:n­ÅWÖTÝÉæÿêK–¬IŒˆ­Òó4!Md·!P%+ªB®EM­1Jˆm½{ÕvÞleÉdÖgb!ÛÙ“Y‘4HUœÞœÜÍÀ3- ÜOÄR¶¬:£`†ß.4BIU ½˜Ôš•l÷/Û`Éð‰Ž&› +JP 6 ¬æ ˆ1¾›AX14áÊÏ¥ °ƒÀô¬ªRnþªbÒ“I©Ò‹€¹m—Ћe»„|ÔúÔW¢‘*Äw„:Ú¦¯# Ãú&ÃSšÁV6&%ÀœÀH@©yª2C[/aåJ…ý- ªÁr@ªµe Ð7@ÀË~ý (­H¶MO|²ÚÙþ(Çh7Ò67-zßü;#k’ÐJ Ð4UØHÈ"1Yb«Ú©;i>ÄÂ:ú_Cù oHzU®Ý=\ƒç_ÿ%+2ìŠÔv¨uX)—…óTÛïì@&ÊßH×ÒØp!›~nÊa¡¤*8=[íl× OƒñÐkJàD·ôùÀf%‹´è™`èØÖ~Ç|.kQG)>ÂöT¾¨ÐgÀ<»%²ù˜ÇYdâÙŠ<;>‡Â–ãSdR‰UÁ4Z·Þ)Îo$ãáx Ì$ŸH&†¶Ù6R°*]xª‚Ûëq>¢ø Q!7ŸÃž^Uªò3çQòyóÏbF*ùŠçà34€ñ`ÀZŠƒ^"æ’Ø‹ÚÙ3Qø}ÍÚv¨ÜÈèùtX[!›¹¾"7@£U±Âà› ÀÇ0Tž›ÚzI™¶Q‘ Åd€ˆlZU³ ù7'’½mYβ鳭Њd(Ö:Ð-áùdb…Y97µ¢­TÝmáRùpðjmUÛ‘»JzÁÉÊ6“ë HžÄ|0Rp2C 05òɪ{åHñCƒÑTyç寻Àc:‘•'+A¹€Ú¯!Y“(‡Ö)ʆYÉj—›US©¯^–¬‘êb»¯k ‡J8‹˜”­HU@£*6^‚Î[k…]E2åJš v‚¦vùà1Ý6ÜßbªU.èEJ)‡Rk+˜cRßÄÖ i_Àø[z®´’¶0dCŽTˆT(húí­Zn·ÿóeK0s)£R: œ¿5Yf%[áÈlÓ8iJë|–U‹7ªáwôHµ{.§É‰mé¿«­BæÙÎ'çº#ÀpvW’•¬°ÄÔH¶ÛÎL‰r7æž `©kpµó аMÀ Ù$±@:{<@Ó5UhUÞ¶€•2`­˜Ò601Î3}3PâeÕÊv®|ð¢¿í®Ä$ÀÃô X 2L<2g©& i˜l9ðTØðß @Y|]²²r“jûMám9k!œÔ:±”PUí•üÊ")õ¤<î½ =©†ä@Ö pUyÖ=A-ð  VÖâ ­ûñ^TÀ«"Ùª"YÕ:]‚z!ã)ñßÕVwñ(l¼¾‡5âÆ +iŒf³Šºä¦¤Kva¡Äuw^«àÙ Üî§ÏÂoÿú׿jPÂc`”T™À‹/€Y¤1#ÛUí÷ic5“U‰3‹¬leË$€Of`K£EÓÅTŇƒ)è tÁc²J&åØVí¡¼‹ë… ë8Öët¬ `_+[JV;…-sZ]ã-:2[JÁ¹²Â®nã¢/‚Jl•V+"›gc¸¥NGŒ %p§º"Ý™³Õ‹ €‘Ü80”µM©¶"s¶pr°µÖ‹‰¨©•³B¶°—ÄA`Îøô)s½[g*~(‘c |cèµaÊ`Dç5 °Qe› wغ·Ž‘¥x%U±¤2´ŠdHÊÝO7#¥„ÆßQùMÈÖýÔˆž•vV[Jk%€‡Ëz+±Åí€lÛR ŸmβR°”²Ú3÷û-U™ÁäÞX%p-JÁ^381À!O-`¼­°Š2ÁM8”ãha‹W˜¸ùáÄ”ÊOå <tŸe»±æIƒ‰µ@êe$_p/L/Õ ¸B†}˜ßÍË6<Ö”sU²4ü…ªÄd1™›Ó‰ÈʶÍ!7¼-¬PÀè“ÅG­Ö’eU_¤rX(±=w6Œ-«ºx”°!­W~^?æxz˜,Ш­È@>Ù®)‡0CÂôH4^åÖsÕ¬¤4µÚvº|ø” ÊœRIïdžÈ¦å£0U<1bžõ"îAã‰Ý0ÂÛê×Ò¥:Q&NTí¦jÁ\Šá ×:ÿÒ7§u³‡GÙH悬y4⃑%xÛ{åç×îÞv0 RÙx+ý i¤6ÙHž¥šÊêDcêè¤ÕZ¥&.«KïïÖ §Á¶QË2T.€˜ñ”ßQ»gï÷%íV™ØÙ´[˜›TsÃàEs†k$›ØV(HØðÖj‘0å=Ó¯¿…Dư…²ôÄ@-@å #T%ƒ3)ÛêøN×s/KÖw©*í¬ið°õ ôd¸¬-Ûp:S­oG nfHªµH)ß/`hd«ÍÊ(ªšà›JÀP‹Ä|øc§Fá=G…H%­¶ªF¡Ü[§ræ#eKcµµæ¯œ¿ÐÔ…»ÕiŽàÏ?ÿÌ (£“°­’—š5N@ÉñŒv£c(¡\{Í$óaèEW ›Ï6 ’?21[XÐ4²©È8ä¦)hºeí”O©–Å7m²úJˆl«Š±ªN`uûLJž'’9ÓÿAB)b6<²CõkGw(+”Ó”…Q–ÆÕéÕä º+¤J«’Lò±vY€ƒQ«êö™gŸ^Én†mV[ Q+Y/ Ø<½ƒhäw,{€¦Q•4¢BÛE½lKÙšÙJÜ%à YÀeÍ&«Š21ýLˆã«•²…QÖTmUuÀJœ­ñÈÙvåug(%hægL ßÌp/RÌZËrãIàsvFLcÐãe)…ÂÀV ±ÀlÚôñ|:šmþ¶ù7IVëÕÖð1j%‚¾“¦ñܹøDdë 4õjŒ 9”jK ˜X1×¶vaY&^òÈZûˆíTù<‰á¦RÕÖ<=ÛôVaJ)¶ÚuçõÅL̰?èJ5&™C ØÊoa,ŽôÉêÒ홳¼-~ím;E­gnÔxžß”Q¿!kkí,+`  µ! 8 4Û×VVà7‰;$h¼ÜTY‘ÜRæ:½QVùLdxª­Ü¶És°íCÑdØ´ÖM®–€PÂßÊÁZT#[ÔBÊ0ÖjÓpdÎ!½‘ß·0}šè˪%hN«÷Lϯ¶œ1VQ¯Æ–zÇ-2ž}jG,*—ú1‡L”'#ôM¹g‘¬97Ìd²µ!Ó("µS76¬¦é#–^!e¶À¹Þ¿þú‹JmõË+5 $k‘RÍ÷$p)O.™•¥Ëª¼ªÈÝ…ŸR¼•íisŸ}$sÖ&^w «ÌÍ–f²jµóˆKÕÌ%ÖN”'@RbŠð|2>akVñnœ>%`K`§öQw3Èî-™œ0€÷‹ÝC½¸À]~DZÅk‡Ä0iÅÀVQ¹­Ø#nr«9ñÚÝü*´r3À?·J¤ð ÓXñ ^Õja¤UwÀa„¦ÁβVŒÀÈü¥¸ÍIÊÄ•'ÊÕÙZ‘ùàN‰ÜñMX7d¼Bb§9Ëf‹o’õÊValÕfœÀ*ðÕJe‹„­ÍsD¯~³az4”dZø¯ é˜Vâ²V˜†R¡­, Q­CÐ8]¶V½¬²‘­ù°rL)cÎù³ÂÔ“9†@ |ˆGºi”þJ aAƤí< #˜°•­5ò ̉iæïÛ”V Íʵ£0«4ùt±§Ç}ÐRLÒæ5ÊY¶R”•LÓ–[·m«8ÿ•Ø*±%Hð5%|X8sð8ÎD!P»†éÛ›L£æÈ0‚-Ù¶ ð9Ô´^ª*ìhëHy…í0›ß56?An­Û蘲±5ŒUèkM–ÒÈ%l$UóWÞ1°hÔf»–g¡„á"‡ª¬é{˜t"_*=Þñ…Xý÷¾Xñ×Th!u†xTÉr8CÜsqÈĉD•¬* Z&‘V>¦ÕK-ܪüÌô~ÉtAÊÂÊk „ëÕ²øá0±ª4sÌ<‘YudRH…þ‚ƒ­‘Àüôõµ4¢áeÕZ)}iYóó©$’¬ lžL(“µ¦„ñðÈaLVµ°Ú24XÑW"ÒYðfv@U²Û<š¦Y/Uad¸UÕ4óúÈϳîmuì8”xÚîg’¬T¸ùÇ•)7­ò…Ád…ÛFÒ%aV½ŽL™f2UÖªò¬ÜJßä=Ç4œëhkX ‹µlÍ)+¥ü”øßH¨MÐd¶*¦"áj`%SBƺ*«îzŸ·ª¾kžsÎPa¡\Ôxéç?ùtBûdVVç<Ÿ¿nǤTNfT³I)TÒ]H”ÀZ¨-0‘JjÝÙ·Ì,ð"í\²wKŠ’’o%Yz<Ò<€T‚ÚÕ½B%™¸s>jmÉ3vî‰á‰©­‰m•Xý½ãÚŽÜ—^†™¬)½@ €^5EòÇV—ãæá²V曳ùm3ñ?BµÝOnx«hˤ¾­Hg”û‚´e]5½­cí5KÀ<7…@ÖÎ/”t4]lñ¦À™§àöê {pJ`åV—C†q'jc4ª©z•$0[]rPÞF‰ÀäÄ[™ÓÛ•hÔ‘fÖÅlúÖ‹Œ€R /ÊZ „l…µ 3@‚&¡Ü0þ /8 ­ZØ2¹ôUI…É£âç,›¹ee `”t· 0BÊ0RHÝ1€­¯Gîs/å¤pJnjm»UÜ‚²0Oµ cmB€‰Ûº“Uh·…½·ÿ«JÝu¬‹Ð FГ Ýë•Ic(²#ÀdéoæÜ^}éE“Y14Ê ç_;[µñ€IðOi ðDRöFeNO&Eà¤ÈóOìõ µÏvã`W'šfjÖRLd1•À49+±@EzÇù¨ÊÊŽ“YªÏaãa€V2Xjw½²Ã!’¦cFJ™&ãÇÐY‘¹µî áVYz8€ðJ¤a'°Ò3!`NÐ1smk…Û~õ°oŸÌe»Uþ}ÅÛÂ< j¦¿òkâΕÆô4«JPy³éH  ÙJ¤¶úZùÛ¦çàÓ‡,àUZÐðQÅ6Œ¶#OË÷&—U%\&Ãx eÃ8ÜS£!€1x³ÁMR/<ÒÊa-f+• ¨EVVíd¥‡¹•ó˜ R2œx¶xŒ‡‰Eƒ:¬ª³v@2Øêª×ò;ò§ät9påNjxš¤v×éXõ°ŽÅûÅÈ2¡W ÐñœábÒ(Ñ™¿u À0[«P¨Dt·lë Ö47å@âlakýv ¯€Ù$e­Ì‹Þ(&ž)ÆTR‰Õ$¹Â&Avj«Ð‚ÒÀ4Mžl+²yt!óz{ÿH ɤ áÀJÇŽ9O YgA–½ÍOwþzYC–C  hxdb«TS5¤mšYL&ôZk:}©D!AM›“'A?•øì®`!El%¶íPp]ÆÐÀ)Y¶ÍàNlýH–Ẍّ́<ÜÁ™0lHLdÝ‘€,1¬QæHn"5 7y–¶a`þ˜¦Åµòw(©< Ù 1‘=L¬ôêÄô_q¬²¬tïÉÚ}êùä`›OâZ`¤Ôr|04‹¬J„’ÄùÃHâÈõ²EVeÛR%š@ötüB"o¼‚H¼¨•@Ê ã†rú[ínéyëúLŸU™™3t:%”ÎÙ)D­‘”Ìë‚a…ÙæLV÷H[Ÿ\“ÈbZ•t ”•”4l19`àu‘Rkí¢0²ù{áñʳ⠻•ªo]T™ŠCC¶’m0À6&¿•X wQ¶xM­œ¥r¶øî0™l§3˜ä¢04:†×š@yú|Èl‹RVnÝ0 Xk´¦e­¦âÀV‰HF/xÖ·?^~bå4J6ÕpM¿G†¹¾þ @›µaͨ^¹;vÓìnJ©ôLT‰{œ³TåänÖªI€oëxå™dž C YÁñ¥`L¸›Ê`šZã'ÀÀ¬âmc¬ô˜¶ ´âëˆSs??¬ ƒ!³ÚZ1@ŒíBÉ<¿úH²ªZ'¨¯•Ó|ŵ«îÞ:…mÊæ0&^p+6[üVUôNäÙùÆÑ¢Ÿ¶xU{&”"PÒË0O€aO¶aV¾Çm 2å <Û”¶HLƒÑnu ãm˜ ,¦ZkϽê¨D š~%ðÖü•À9 m1Ô>|2”ÊŸXÀB6 VàÎSSk!ûÂç—B“w ¬`%ÊùÀùg(+…”…#SÚæé8g²j‘`)@¹ãè…i0åµÀäŒçFl› C¦’Ø {aòOSm_éÄHk€^Ðó1^)µÙÒ$0•lþÙøˆ²‘¬ ò7 O«± xW'°…Ùò‡ üë…!h0<دMi¤DgLpч‰-O£—ªŸƒlcØÊ˜ÒAh:~[LAFXZ. #UEjG¿¦ÊᢦV‘a<çÌó/&Ø)$sz)wÕxÉX cE’õø¾íNûñV¸­S¨mž.Î >¥§L€q¥&šÍÚv>”4ž‹BO¿y¤„­Ñc3t¶[«mNIC `!¥…?vZ;Ū²Ô…‰žÀ7†ªÜl›ÓÌÀBJPZ)…ÔåÎ=T9¯.-¬ Oll‚þbضOä€áI ÔŶ m—Šáœyšzõ Ø Ì™òÎ9ç¶²ªxfn­LCÜ@Jk1ma½œB‰çh‡ÜÌÃx3{4@m)EžX”µrÐT;): LÎÈï„M‚Égcj¹•òù j´Ž”4¶E…4JDÃð [“á2±Ù00 ÒÊjLå±Û®Ë jçM«£r×Ç“Á¿ýãÿ `䇱„[vkÍa¥sY7 ýCOÐ[%«ÄŠWÐ}ìáqžõªn+UÔK¹-CkLMëòHïw1ÿÈ|È€†ìÍH[·„ì°V˜ S ¤œž'C“8å¬DÛRd@HeR㲉ÓÔBÖËCà®”WØAN§ÿ|ju¤Á«2FŒr‘¿[ÒE [k†»·Ä `ÙÈ­õÍ2±­(eÝ6†@jDVû-‡¥ÄR°|¡'³ɤÁºmäJt±m€Öe;ißzɤXõ3 CÀ°GÓE²u'À¨òP:KCªR"Å$¥/œ³ÂSò±&[žJZ¥²²•­»B'ˆçoŒUŠp:kµdHk×Ï`¤ª¦š­w£i³²*ÌŸ8Y©ºcê‹õâYV‰¨E8ñnÏ11™ a±{`âº%åe+™ìÌaŒT3˜¾ 0¶fP›^Jàmkáºht_ [Á™ ²³¸=…Óu±úqÆÆ£áæL˜Ã)ú±¬òºH ú=\!M¤µîSšAyVR¦uvt´šbÀö{Æü³µVضã7†´À;‹· L6ç:v$·þ8š‰­ªÎ’Æ¶y‘0=óüUek€Æ³ý¦ò”å P–ȧòø˜†á@³¹Áò©Üç©Ez…øYaµÈºX b&âG O`U+d»[8[©/“^ŠUUuìÙQvR˜ÚõANß[úuþ“²¨ L©Ö)XÓzí¼ö²¶Rþ›]d.„C]šœÌÇØR*IÐÖê+H¹L¬¶•Ä“R0Cå cÅc¬jµ°"»z©4ZÓ8ó¦ÂÛ"1®¨Q“d(•[[¸ÙÒ4œykóPd4EÃÀ«ÚÆX*%L-Ö=†mºÕÖ”x—ïèaúø lÖz—FF¬¤ñ¬UµÊJÍ'˜UóT"ÕT‘<Ê.?\j÷æåñS IcUÞ0j›“ßÛËC¥,«|V ÉâilaYÔΪW[«v”½Eja††l*[×K¦„’¬’>h²ÈF=…þ-@t¾8JP idÖxÏ€{OÂX¥˜ŠÆ¥c”4·ú5™Õd²÷tÏ?¦DJZ3”j[™#‹Ìá:H„Eø´å†ažÌ*8Ô¨¬õk.E“ƒè*±;g…ÕFëûlÈšÄ6ÀÍ<ïq%V<™Z½ 2£â}õð*”õ:® ®Œá`ÕŚɆ$¨¾¦Rõ%¶N‡!°µÒ#«I¬"eØZ÷y’yšÙV˜6€ÈßœdÚõ,øˆ¶ú’)ÝIçÂÓ 5­ÅÎ;Û F™m&0óc­–§2¤ÚðjW%V‚oëáæ´bhº=¸Gp=Î"%€”Vé~øÛ‚ƒÚ}nmÏ»x¢t«óT’³•L­Ba +±jÑ1‰¥ ÖY*T…orÊefJ>ô²VAYÊZª¦Õ‚­”­¿ÜŠQe¤Ÿy²úgbûˆÁ«ôj`[-D#IÁM°Å«-øW`  —µÈò4ªr3†ia@ª.²EÃÈ¢,À³1.ý|ÀùÄ[•;¯/XXÔIÃ$¦99à›‰Iå?xŒðq3³Ú²;`÷ïûß¡’åÖ´ºxåúD×]¶.V†§!ÆÊ§HYT‹lMl ÄÀ ¤¨ И¹-ó^'že‰a¬µ[+¾¶¥ÁTÕÀ4¬¬uAºx3H±Â |]84É VAßxJ*oxž½T5m sƒUUhK/¤Äí||hü+„+9g‚ÆŠ‘í€mÁ³ì–-|»îkÁ Ó–‰@ Vé1FÒ–ÛRð©y»Ç[1œ­ëÛœ”8©Ž–8Ãu XC6A]¼í<áod‚™£\‹dø[ÝËζ¬`íc §$F 'bl €ÖTL°-”ª;=+%øž¾;É¡Q™ˆ gÞW©dyv-Ú©1Í6ÏzYõU[V‰€wW1™[ùÓ›PGßxV +0ùÔ6ÀîêjŸßI`üšÖ®U-s‡«Âe›ÊvíJ 8‡fhM©£­QÓ¶ù$°b˜”²¶MâÚÝ€ɲÂÏœ¬BÊ€ì­><±øŠ¥0Š/l‘RÞ±ÊÓ4˲n€‰TpæS ££*L-0¢”Áð~‡Ç4$¾¿wc’L­1Îÿ O…S•ýùÀ|Hgfa>¡€FR,xmˇ¦­°B‘³UتÁ —åVSLæHþxAcŲx˜U½X¥Q›†€Làa؆s §Ç,uNûÎw4«^M›O%V[&ˆ“a¿Ñâ){é›ÃöZX}ôZÀzóH&½”ÙbºsJ¼FÖ@˜^ îV3´åŒ¿{+{ÚÜ·JŠ@вòÜðe+·ýZ)1?F•ÕÀ9â¬l÷Yê,Y¥¯/ÌR ÓÊ™Õ6 \– Y8‘I0ÊL,ds~…ÏVІ *® ³Xm¶¶R9§©P#«ñÌà°4щVhK¦ª 0ܺ«ïçË94010Ïl•3ì&maëJ½LØßÇtW¶D “Æhræ1@c¥©;¬ ˜“é Y!uÇÎeÅ×±Cb +¤•s3ã1ª0µîÈV1^¶Ho•*Âe_î¸ ]°ucú†±6¥B[+€¬K¦o놽“O­ctÁ8QJ­‘Ì1\¶FÍS Icå_aL[Ê.™8 ó4xßB—žF8…YÃ(i Ûš:Ú«šê(Þ+"CÊ¦ï˜Ø^K@IDAT1Lœ’ÒÉDtíH81`•X­¬Œ+‚»±3Ü}0À~·Ì IÿÛŸþ)§Ms  ×+^:]å°¬°­1™ƒ‘ÑpÂÛN4žÆý6œò;Cå ¥„mchÎÍœÊÉæ–'7g))¸Y•o=ìËT.+Ü×ümiî,g™þK–5 ¸ÖÚ„L¤ð½[&(ýÁ€F/bÇi%k€oËa×åIWN/êh%k55†M²æ¡ÔiåYÄ#Ì©¹¢ËÌ™›lG†,ŽÓE*Ä4< 0¾ ÒxÌ•g~ú½…”‚ÆŠ¼»³U ½:5¬»'Ȫy£Â•  CÄÜ)žåô¸Q‚lmÑu¨ÝXåRxçjló$¦k RI ¿’Ìix¦i<7œ˜¿à#8ˆ ‘J¬¹}[w3Mb `ÒW¶ëf¡°*å_«ÚeK¼l%BV¤Ô±-%`xíü¨êg–lR <ÇJzókU/'1PS 4™X¿Afªæ¡¬Ê‘sXJ92«™'F[_À}}¶}:˜(©)` Ë*æ¶Â ”²rhKïN<_nÍã¤Õ‰Œ˜0 MÊ¥”j†dÓ—µ€ Zm¿ŸÌlL:ŽvÛbÔ¶B¡•ž›¬j÷ÃYtvÙÞ}"õbÕkIÉŠ- ,•aÀzšý¯(•ÌDvß©:²50†•’¾÷ Vžè6lù7‰ZbXÔÔš!N gðdîàJº ¯¬Êš’&€Y Y1ÿ4¶ërN{ÿ]ÊÚ=oKÌçü€> %]è'ôÀ[‘V  °6—jõk«HLSœf÷}Uf¢ˆ­¥èea %M&W&JÅ4fVg‚{Â&¯¼µTÙÀŠÌœOŸs¯£µ³æ¶©Èb`þ¶p8ÃU˜®Å“†‘m= e§âŒT‹i<ŒyÀ~ý‘}K6‰•ƒ±i÷ÈtOƒ¶m$%˜î¶9ã“­oŸU$&2g À6^mLz|2¼f³ºm/^‰™ç0&ìd3!ÆÀúú({¯üwàÚn ½V«‹¬‘%5¥„70,ø«*Ú*´%^ ØH@ƒWÔ/+lF6òÛ#»Öë⌎F¹*VµhU(š­ Ù3ÚEõ2ãÉ„IúŽã ¶GÏ¿U¥´ÜñOS±E÷è\W-ðWõ|Šu!6¿Žº÷¨œŒØÀÖ<õeO“¿”@ÚZñ1þÝW"&ñøS|c €hÛ{h›?`NðÂ]&=¦Zbq]O¡q¹çrÊN〠}HɸY{ÐøKMYk— „†ÕZUÝëK)¤¬˜.¿âx«’ª¬ˆ8+Î…Öþ›£ÛÖ†”Ís{>O‰mãI)´=Í>/g%s¨¼*…é;]ÊÞOÎÍÏ ·åcÛØÁ#,Œm˜ùÈf…10bo`ƒÉä|ì>!Û®òÌ9¸¨îª*kA Ô]m¸ªRVÛÎ’¹­ ”2!ÐHŽƒï~š^áó‘ì°J Ÿ;…sÀg…Q(e=wt#«È9Ðã­ÿ“!ž ±ƒð£—í)Tkkò>éý›¾ðªDJ[…¶d— ûÒð‘qq¤ïÏS ÛË=/¬Ð RÝÉ #Ûñµ‹W«EÃãÖY³•D¼­`[G+^LÓ–¦‡åæ‰oÑùUÞéðºÐÛZÛ¦±úªD~K¦I°.œÓ7 1fSxwç®Vh UÌ'l‘Óç‰×W »=xA4­¶5ªÆ tF— r¦¯YW¨ÅÀ"O€²mü@>F¾æ¶ßà™¦U ˜'ÌPÀ:‚dÞ%%ž¬&ާì™ö”­jl—&k+:Z7@)ŒÉj3¯–@#©²MˆìÝî='hø¬lÆö·þóŸÕwº¼äL“i=J‘é‘Ä#ãmñÖÍÝˤïAšIVSÛJ⬤ÜTV)|77I$ž¦ZnYYa‚­¥ð"qάÈ`G6!læ^e%x«¾ª²ª¶91@Ýëuíÿ£…¬ÈÁ‹îÔ¶]/Ð0fèfvܤðü#•ôä4%¶•"³Â†¶>9° ©/¥ÒŶ©¶ÅPòÉ™¾穉lewµÈ²”Ùu2ç#¥Ð0Ä@kil rK™ e¶°Ö˜H%º ÜßýÓÀEóL 5¾iÏÚ}¦AblEÃ×"&ÃÍj»5 <ÍæOF¿”]²Áh( r±Z ¥lwhû-ÁÛ šÞ nc¤nOS)Û9ÎNÖuñ¤Tá+̶¬Fx¸ÐNÀø‚˜g¿âgEOWÈÙM ²Sk«2OL2µˆlU%þ'ÖHÊ*ûÿOP®… V#˜Àvód•8ML½È¦üjR¶:]êµî Ú²]YÉ_ü&’9¾É1C…ÈîÄVäÐd ½?H×b­?%²Ù.ÉГUU#L$uAþ1™hT òæÜê8ù«ˆÉ`}«…‘9Ÿ î`•k ˆŽÓ»(¸ïÙJ]ƒs´'ëÅMðÔô»Êfe%«)Lߨߕ82ü¹”÷‹ðÚpP ‚~X8ŽP.+EF&¨]&z øš7Y €Œ¯ê ÏÀ¶•0š™ƒ^µËÆE•m*³Ùls6*s_ ç‰ðñeâ[𦍗©lá;àY”XùÔ VÛ1lH–Ø È¹ùÃäÉ0ídõRÞ¨¶Ê[ÿ{BU}§5[nÄaš ÀÛØœœ#­¢©jGø1žg— QÊ ,h`ƒ³FÃñu± †Hµ”ÝX£"‹fHfL†Ïd¤TCZaÃóQ8ÞÖ„ª-Ë­c¶ÚJu'œ‰Ó7R%² ¤0ù[E© ¾5¦M¢—WkVÕÊ*õTUžÒÚ @0AÓFr6›w†8@Îhxü77g’‰¾4üÁ›IóŸ?P(î‹«ØÖL HibdP&–í×å¶B{«>x宩#)—¨’JÀd<2|ß‘*ç¹1ð›ܶÂãoòù,Å“›­^ªDšÊ× ÓMñÈ"[3·áªè¯’m£”UVGñ`L¢œ@U>Úu^²²Ñ̪àÄ5úVÁœ­ pëž×îJó!èhLða$™µë’>ÌÙ¶¾)‰‘|}›0eY)Aß¹üŽ®Þ=<-‡&„É`ÑýÀœ¬*-™Xû_VKYéÕfØ •d(+Õ0Äʵ Ä×ÜV‰•,e8“˜UŒ^œEb«ò‚f-ðBIåy®ïÈ@›žr!‹ÔQÝÒH—ì D6Œ#K©íìHØ` [¯ƒÔ¢;!è{¤TþY­/’Ȱ-½^@-òDrÓÑxô Ó¥º¨|2Œá€´ MÃÉV2AüV`X9¬DÇük}nðý¥¶ÏÑ&¿=OUó¯w’lÝ3϶ô)1µ»ç¤ˆéqè›’l†f€¥¬Ý†»âFYdõÕËv–šÖNS-\öžòüÉÀhm*Y[þJh²OL š¤lí¬xnMNóÌ<}¶5²U…áÐ6å4î–?² L³vdîSd2ÿܬ"s ñ2x+Û~~ý7Áõ8K¸”Õ6¦Q“ÅÜ̯ödMb»‘TuoÖZ8,sÃô¡kHŒpÌ9gb%s.åï³õ»¯l$€± ú0o~J[dd­îÓ…—µÂ|’ÙÒl›FTN&²[-‹÷ËFµ¦5ªU0!“mÎ á:JÅ(œ±¬mµï­¨œR¨ X9wÉŽ& ¨¯••-}ÙÜ0À²úV²² ªÂ c£¶’4Ýÿ¹…÷—‚~7SËÊx:+µ¢ù+¹¥Ï/HZt'u¹=ŸïdÙE)©o[žR¦•زêÛ•Sš îl•dk5-†C׋”jéu@)+ÄÚÚé[ÉjçFüík+VhìðæÄcοˆNWáE´jFTûŠ“f§‡È @¦ÁÀåñLV ‡¡Ùñ0½úJê dhË„à<óÉJÙjQµÍÌa&1i’-k«…àa#ñ1Uþ½g˜ ž~}Û*Ĉú¶­Ò3ë±aø{‘ yröKp&j3°­WâºÃB kíâé,ÕU¨-Òk½Á0Ìcˆ”Ò–Bc[¯ñãL¶;©/}M3·ª çc `´ £D/d[<[kO™^6Þ`€¬• FÍY¯nչϘU%< V “!²¾ÖR¶²ù0¹ùg€ñ•×" ó”ÆÀôÚ•äfýF…Ö‘LòYU©¯fb ™¾ÙþOm¶Jz»æÀ¹ŽôÕÚŠóî¾ÿ¨Z@ªa®êùÎR¸m¸5O—¬©o"€ƒàà*h\‹©b`ÀŠWXÌMj¸^mɤ¾ÿA[špÎ+”]Ê„ñÈŽÙƒƒ¿&9`L27×Åg¤T˜43ïs‡”ªuzU3¡ïN|#æȤvõÅäF@ÔÂj[$«ÄÓ¡çOƒi ë+l9ØVØx¯Íó²©ÂçI¹?„gÒÀßî+dË'fíl+ÄäcÎFŠWbÈÞ" 6äÿ壪CQÖ”§ç Ó6XÁëþµÚüj ¤D>ÛÒ wœ|vœ²#5º¾gí8M™ÀÀ”²9‘nMbU+0•h!ÔJYEüfk[)n¢T€ØÖJƇIYxd½leaQÉ”‰ úfX¬^V¹3ž!‹pÎ4uUaã)ÙaéÝáköüj«„XŠÒs·ÝäH·‡¬¯ucdž³GHõ=¦„a}+á)†ÛNóWÒ/g†gå'—Ö “’ ïÆŽÑ;°ªÆî°xž˜+y…áÃR¬ÀPÄH‘ [b¤ØâmóTu+žK…é­ÄÊi6€B*IPG¶]ÑZpè,Jd+¤‡¥ê[—ܤr°mBå%þ;9«²€m­¢mkYëÜú2ד‰ÛU0¡·vœ¹a`§kg*Ûô+,k噸Ûët3ùúÀ›™8}sv«˜m·gÌù€bil¸ñ—ƒTèG œ¼ÿ¬úYU!e; †¾O,ð²:5w†x{ïñ3¿Îû‘gàÚ÷™±-b`>ÌÁxN„qÒm{ñ ûhGZÅfhL?m»±®Há§÷÷CT¡\Å|to˜R²Õ‹YÅ(©µm «­ø7å×£.Vžid>eaQŠ [Y­e{¾˜WY÷ u ¯oèk¼U¡1‚g·!Õ6ÐýX{…*´U·µb"ñã€låàïS/ TÈ @DZç&e[*[ÃÖþèHy†¸A©FUš9ã+L¾©(ëˆ XðíÌÆAIÙŠz½«¬­àÆ2é»B-¦*/­« ñíg-¦¬µ ØxÙâ#9c"[¿EŸáÉ0Ké›é74k¿'3@‡¢ÁS)0p&y憩oä ŒÈ¶ÚÍ“§³÷d3·%èVÅ!Y#ÑØö»Ph”¯Êö—?ýéOŠé°õ3«„‚¼à÷ûÅöÌ{##2ÚXp>¥¦:$ÿÚU¸ â):‰2VÃ*®ð?ÄÈdg ˜ð+õÙ*!®i28ïhaëL”î×uÁ^bÊÌa-ºúzõn w½¦ +©{&RÝXVR¬‰†9žc¿­PBÓÊ!fž[Î:Æ”Ô7gu»¥TUðC,0Yu½pïBtL‚·æcm@ J²ÜjÚÁ ÒH˜'»™ãÓTákÑc*iBY3X•KÖm#F‰-,t‰© ™X*l}KªJ<ÿÕªf’þ­âãŽÜAÒÃÎëôÊ©u™®(s)š.hŒMn›RI'’R"Ù¢'À÷¤d¹©MÖAªÂôŒ²µUâ{_V‰-·Q_þ¹µ” +U3ÙÍÿúóIâæT®WV™è`r˜mÛZ„fb wW¹5¶'JtœÒ¶C1•ݼ,r>°Gٴٖʼ•ƒÚköëßH‘!•wXµ1ıT†d@VxY)['²Ú ‚RZçØöঠԔ d̶9ÿØ’ YS«y˜ÌG/AÆœ|Êbθ÷öÜDJ «¶˜. ‰Q.¤àÞPHŒÉ'œ2üŠ1‰^ ÈGyá\Ïû 2Ïdjè L§ë\úâwÆJø$³ÊÚ6^[âÉJmH÷,´0$¾¦ÙôH˜&ÙLÔb 1(‹ áü+,¥‘¬h+¥QØH@G&²çØ_9 ©÷~T­Q#ŬK¶Jdë‚ÙTÀ¦ÚAxÑúRÂÙ„õÝJ@fTÒëE,&«;¦ïŠFªöôû~lYQ6‰Õƒ³E Û”p?gçO#Å ”RáHŒ*ŒƒX‰­4H?nh00è¤AÞÓŸ¯)ÀJL ýö›JÊUôÃK­ù•àé+Ñ·*Y@¶ÐZÈnÛœo¡R¤1O&Õ"‰e­x Ãæ×ËÖ`dÍ“Ob©H@¹P˜É˜ì ’9¦­Ÿ!™*«”FmÇD6ÀÛÓÌÈ<­ç¨4`D„­ G[k¯…il¥èë-e;Y)[YnÄÂÖíD¦, 3Ô+`…¥\À”sÛ” Û˜@åµF(Y6A© üd¥—Òéš`Ì.¹órsF!+*ÏÁEeî饬0O©KyÙja@‰@¶4°P˜2Œ×Ū}þWxÒ´6’Õ<)ù¨ÊCˆi¶U‹€5°F03éÒ0ÖJ|ÈZ÷JÈêîJ½!Y%¶JÕN‰m ²Z@UŒ¾}„’Ye‘"Loçµ¥okÍ ü¤ )Ú¦o+˰SO“À*e5™uå/ªp@2Ù¶šE­¶F1ɬ+$è%ĸÏ“$CŠÌÕ*áìV{I~; fb°U  …,å!Å“@–ßÃõb$¦OSwV ”«µјd V4†š2© `Þ$µ†gøíðùP0¡4 0e©°vvÙÞ:µl+s)k׋M›Y)—#jA/¤R6ƒ¬m7)›rÝÓ뵪&«$+²æÑòÅR Ù I†çÄWhí9nª”ÄÙâ1Bmnx÷t"‹¦Û«™õÊ*÷F‰¯Öz-?Ÿ#‚ÜÊꢊ Û 1FÒqÇL?[>¢ªp0¶päR•Ç[ÉŠfÓK4Få°Á¶» dÙÞã¹Ì­þ|»¸ î}°Õ‘2ÿ5²ÉÓCŸØ¶±µ±ÉÌ›_•€³Âd9ä KãÄj)KáÓO¶m%¶i·¾øÍ·åL©WþÚÁÂz·a‹÷ ¹áUÁÏ?²ƒóW ×N¼·¨F|€Ê ˜­J©Æ«R‹cwA¸÷ !9$PK¦^{ú¶ÎE–FIo,€!«,ÌS;kà &ÞTÍLŒ4<^ä4²T$}d’¹-à JÔZ ðÈäilz‘¬¿ï ñ­²]Ž­”m+&»"ü¶áH†QN ʶF:Ïž½Å·%muì’s€ä­%ÄN´ƒ7<·lé›Ä–Æ…Ì£WJU ¥4ÅØæÀD$3†,, `µQøË_þò”2F€5‘öñµ$å¨ µÏ…LÄ' dØ@ ‘MCVI§êN†©Q«1¤Æš0%fÜ6¡T¤5l%l¥©"­ ÖV5+/:…ÁÆpÃç‰wãV[—‰a‹T•¦Á2”Ío ¨]‹Sÿ}êgˆ{®ZX{Õ*)KÜ FJÀfˆI¯#P¯º[ß-±mµ3¤¶4VÛÖ²ùúj Œ]yúœ­ž‹yË6ük5&%±ñtT;7ÓØÉ`×¶ðÇ@J4­F2™OàŸåVœûp‰Ê»ùepúUÅßü¯—¶-œ>ÒºFe³rR‘ÒðÞëjá®n)z«²•yÊòy¿>Öº^ý+z²R«mËÐUø¾ܼªž>gLö82ÁkÇ6bUÄ u˜ ¬jÑ6ª Ë"ÕŠj‘€•§Æ#ic¤¬†ÇÀVÛ‚9&ý—û|¤ðkÁŸ˜m [ÊÎU/)âRÙÖ—†’>×åG¯MÂÒJƒZÙ}èRšÊZEbdkgeeUR LÓlÓL¼6öÊÉn;0Ãlã‰ñ¬ªêétRïÅ#MU LFc ˆæ϶@ŒZU=ˆÚah˜àA|Í~u³%ÃÓXaLضÀRæ`f}­u©¤q©{¸Õ f« ˜ŒI— ¯Ð6®±òH2xMma1¸óbÚ҈ȲgEƼçBÙlÊ1¶p† ÔŽ/›-¨Q«s%NŸ@ RS«È\Ê$“¾Xd9¸óJÊÒ‹=bkФ¤=‚¾Çüøâ€Oˆ±"»aàß÷ÍzÚ<Á3ÿÉ$•×ËjZ©² [²÷˜¶ñjÍf¥$[yš1R—aXé‹HL`[YøLöý¼ÔÑq¸ùÕFß9žL‰à†øX1ª0×Ô‚ÒÏ©æ!èEÀŠÌV—R™¢” ¶Í*‡Ü0yÖ”b%4JÚÊRæ‘*‹Œw1ÎÒm³Â$tKL„Ùxâ=PJ!íÍŸ—™Uµ]šZ‘Oz@žÿˆ¥qCç"‡17_ÙµWU×úåƒÔiµ¶Í¤¤*SZ1€P%ˆ­k$€à–~>B/Î\m&VQ»kùYÆ«í"1¾*ÌÆÃÔ  Ù$Ý`ú;ò™v!Þµ0„=›ìŒëXw2@ÔÔV¨ê¡”R‚|5 1çm>5W ¬,PG)“gR †’l/ŽË½s«òVÊÀÆZ¨ªK Ma‹¯0 Ô7L™Œ•‘”[½¾HŒ-A³åiTfHÀS‰T…»ÚÈ0e…mVk•"ë 0i’Ù2‘* ¿[$Y©Y5'ç9Á<×âüÝ’ÈÜóÝy+ܵÈ*ÄÄ«*Taª²ê…'‹êùNB°¨ÜöŽöùÝ6g%L*œŒÎS €¡O™¸B)€ iÅÛ9—b”µÊ %záÓ÷›kA¦¿Úó‹¸móÏ Î<™m…yv® »j|¿s²êÈ•ÌGžy_ܲ šA–’À`ÖbSI%V^ªëÂÏÖ®hzÇú{ÞLrP‹W» lk•ê°)›§•^V‰”S[a)ú.¶ß–0”€á«©\ØÆÀª¬ô‡ï˜¬B–¡è©…ñnR‰˜•Tú•`:,€LÙª¡¬0E×õóyÇ#E‚3ÐéSðü#M—¬ë‚ʾ'iNYXð«6½-€‰‡wL%Ó»°•RµÒkm<#‘៚˜L¬:Šj#õ¥ÊçSðýà¼ì «J@>§T‰Î…,õ£Ð04ÊeßIè=ÐH<µÂÙü'à™#d…=/™Ôi[97z¶­€¬°5Ù°ÏEæ€/"Ä.³¦™ã‰a¬‘uר³ûÎÑ)àÊa YåiêòúÀô+é8c6Ù @GS‹pX‰ 3Ja¬;2`¼ø3ýóám)‚ «¬ajÑLPÖ0eÉtì€ÓàŠJðdÀ:†KÑôàɦç'Ž”U¢E7SR¼7pÚy’RkcË$þíËïEÔ…¬ùÉ”çS»ô CPmëž²œeyò4^v`%4•9D¶¥ªhL’aúÜd§ßÀ¶ýÕ2 ÜŸ€û5ËC'Ã3\äÃVÌsÙ”UN9þÖýZضóNX_>‚F¯L9²#×%Ãxâ>ꕬ4ûÛ ¬%Ú1Çìºöî!MØã«µZ¶H…VimžÖ Ãl9X]uµ™Ôº]æ²¶jÆ»>Ÿ/¤Â…­¨ .¥Ð#ŽÇ\ÕgàHkÃ[ f5Û”·Ùk˜!=“º·Ja^2±ªŽÓÿ$Žž9è°ázuÕRÊ1¶Ö]]Ób4R€°¯VóQk«Ö¢oÓéhð2ÙÈ\¹€òrÞ?8XDz׺!¹õ[NJ‚°”m­O{" ¾K+kÈ WKï RcÒ\ùÑ _qþbÃÛªŒº³œ®÷kÓ:²vl…IÇd;l3or©5ÍG_]´ÃŸß°åIPnkª /Ù6ç ¤”‡ñæ©\#íÊâ3ð&I£J-’-²Zé5µbªD&¯ŒÕLdyÊvdÀVÛ+5½l†¡–F¡^ ×Hjþ@[@4†UÛKŸ+¬«…uOÉYßô®ÎIùD¬¯-œÞ‡…R!&¼ªÄVÁÆ*rn +9¼>”y(»1d¯VJ;˾V°aæHŸ²ñÈxζ³ê8jÝCd>Ê ƒŒ·UXx·³ÅÛZ™É¥òÁ°í'Íš"7’LIžáf{/AÉk[bå9w3p3ï¢lY+`¶¶‰­‚Õ¶§æÆË«Á_ÀH@U €1ᕜ/¢°{𻇤G-ÜG #çÜ4€àfÝ®Xà5È+ À‹,š ÇJÑŠd[aÃÐH©m d˜óV`1ý«D¶ ´j!2—€ñ® gШJ´ ‘Ú`HØ*JÑdu¬Ÿ»k<âkƒÌÁ3p«0Aš¦*k­œ³ë’¢AÚ¬ÚÖ+ò¸Ü£â†Ç×=+>‡˜EÓæÃ?¥, €ÓãûZ¯ê· Qß.MK‰ì ¦a…¯ð8¬OHé ûxÀJ"aV²€Šlµ ¥hòŒqÿ€ë¥Ü0¦ñ²×û×›T"º ë ÚþX›P»€U¼#å?[Ùê"»v@âÈJFî€õÂÏŠá|êîZ6FßÈ *É £Ãp@ªè#Ü 4@š˜¶V&ôÖÝ™p½f M¼1 E¤Z¢aJY›–>¦ÂÈÖª8 ^ëJʶbíÈÞ ¤Çx+˜Ð˜ÙÊ8¦F™#sN&•žÀÚµ»º3©jµJ2Á%V%¯\w =M“o9ˆ¬-@,üŒ;N å+@æv\n¡Iht××ÚIidN×i˶ «­)RJI@v˜ )T!EÃÐK•Õ] “Ñs&6L&%`+‡ô£Zâ ’U»v>½¨+d%™×¨^x…Õ CIf¬r«)¥ ñu‡÷€úFÂØVÛJ¦œmàš}n2ec¸ )%Ç÷–Øv ¥ƒLœÒö …5¼NŸÓÕw#e˜®ãº+›ÊŽ1g—ƒœºçXGU„'P;$@àê#¦:ãZL€ É"9´UR6v30`m¼µ¶È ikŒ²¹ÑpVÛYÅ$–jZ…«%R}ÖŠf+±!ÓÚª¤lb I™92Ð*”j¥”ÒÑ`µÄ‚€x-fXÊ6Æzå§éRÀ²5ŠÑˆÌê þXÕqVE™LÓãþýðâ»4 ‚Êã£Òw[[šb¶¶oªÛÕÑT­¶d|å/ȹñó$ÐÙðm\i2©îÁV9ŒéªcÖš› Ìñ­b¡–ƺª˜¾¬âÚ…dÍŠ¸±ÏW'ÄLÜŸÿ×<¶4èâš#R›@͘Ú"9ù:ë/œµ4"ht+fk ·­È‚R¬]ÓO-(U!Í÷W¿¶OöØ=\¡mU¹•µJa6\Êó©iǬ‹Ö¾Ô¬É¬µx»T°¯?) oúöÿ*+‡Æ¨;¬.#»ddâ4­˜f°m†ªˆñ}Æ0Âv¶1¶ª#l•J–ᔵn%XÓ ‰Ñêf¬d®«Úü»1ÉÜVVÊ #»a&j9ä´ÖÈjë}£éS‘aM7gš½K¬ÒTË /–²ÈŠH˜€•€#a^|%ŸOòo•yæV!‡Ï(÷Þ®‚ ¿ŽëÕ•Í0MÀµt|YU‚Ó‹$+ZXñʦ’Â#1‘¶ âô4BS[þ ÷n«¶ª& ,E&È#ÖëÅ4¢*|W¤¼ƒ§òkìãfBU^åÉdG‚WX Y/¡E&d t¼h0² #ÓçCymÎow[SµB•ÀÃx¸ªzÏ•ã4@fîÚ)•Ð`œIxš0d]¬BŠ!ÐeÂÕbj}DW¦¶‘¶Ý¯¶Jj!¥jak¤ •Û¾!eÛaÛôÖÄs.‹tF§ÈPVض" çÑÔŠdVí*Çw!ÈÆ>v÷n9ôdc¶ÒwáåªX1Dž_µ=t Ù¶BL ò¶²¬xJ5˜lמÕ`:œR­*ÌŽP»4R¶ª„«£Éª)Û8Ã¥0}š’Õ"ÍÞ|¼`’¹µ™uL܃pšÄkQÇÝ™ P+èiÖJà×kO?Û™×ÈÚ Çèþkn«P¡»- «—#ó¡Çàá€5¾q&¶À0M[¶~ÜÃUuŠVdc›AVà­¬¬5ÂäCc$n¢Öi8¤$Kl;ILд°g§LL&tIc%&PÈDžØ0˜þ¥ ÆTr¬ïe¦7<=«x Ž€m…„íΕ›U9}b[ب¸!mµ«£¬PIÃY ‰Iß0Öà Jk)%¥"{+|¨e­¶Üº˜L ̦íWe¼,™pF¼ÿ’*e¤¦%ó)ál›GVèk%f"ÛÌç©Ý PÎ43‚ek‰É—¬Ÿ"ùZ1”d°H‰á,żÿ5+)æÉêˆ!k}¼mú `»¦pÊ ç@,ñ]DW ¯(eÔ¶­‰&˜>°ÙdcÇIm¥´àf…eÀÊZ$³¤ÔºUUÈÄÈLiLu‹>3#ÛV%[¡mÊm1‘Öš*±6§œ2¼-A½0bJâÅoïÙeÛZsÀ˜pÎóAºÏ†· [Ùðž`úl‘‚€s„)ñ|¬:RZÃR›Ÿø5gE³uLM§æ0’X”’êøº!›jUËþ¬”w´ÙVe›¿-ÐÖ1‰m;2²Ï¸W®{ÆH @xñÆ4@Ùlkgàœ# )QI—cLßôd$[# YUknÖܪj{<\•l1™Z[!ÕÀu”ªÑRýö©Qß«²+éªuø[‰;8-±BßQÌC£DP¦©Ï„ lÇ$°å&5YŒ£vR"ÖÕzdjµeme­êð">¸B@ª*@¶*]*¬]åÄEµïl†§Ë&Î f^Há1ª\NÝ»XJKJ A©*@\ØÖ€¦lÓGÎÏêKÑà5…;ød”Yå¶á1­Ê›*gÁðñà0píøäO#Uv£¦DÒÜäY2ȇXJ-±áyâ7Ò©¼ƒ½g‰i€M“ÓØ*OÐÊ C ;»/v²†oæf ·ª «%P‹Pß#úÐñš”Ÿ~)ÎHÛŽfK {[ =íïð™dŽÑ(¦ÕHùs+v:V>ãZ9)Àèu¥qEÙâm÷F­c½îMü_ߪWí6ŒBæzúÝ_F›SŠà†ÇXµË\¡-ˆ¬D6Rv[s:éx׈¡iÂØœ¶ ;2O-tV<Œ«âOßYDåáwÅ+ä à¶éa Qó´%ÃpÞ$Ê1)¯Á1ì ù(Áv.«g@¡—¼¯L¼•¥ì°š:¬•ÞÖJ¦``+sL¼­ÉmhŒîù‡Ã/ÿû߉(¤z\`«‰õö+Ff§Ÿ­h‚š5 RV­»:ÐÐH 2nz—oØf… [ñ4¢b"¹é%¥‘YÑk—Þ…NL/lcêB¶vF%°2Arn>£\Þù‘$f"Nïß|ïàkW¡Ùú.è×…H½´€‡àÓa]€žh %ÞÚ£\@Öºø·È¬¬ýŽSI<¬… 0j¶ß¢ó. $€¯6¥­Ô|Ú&°Æ;‚¨Ü݆-2AV˜ÈõÒîývÀwQôöŒŒÍD!1 Scu·æœ>R6r+žÛÓãûc@Iå   £ãL€áüsÎ~™Ð¨Âæ¯c+F訖&«&±•Š'fâÈnC–ªAU‰7’-’OÁ¸€W‹Ù6B½^7XßJ÷É…µ0aÀ çL>]o£¥hÓe²ÛèŠZ T)Ñ”RI©×O†1 †²,€Ê»: œ²ïIÙd¤­µa:¬‰i¶L`%01ó®Bk¼ÎȺ¼½ÕÖ”^À…¬è,ñÖêëxb@È*o ò_þð‡?×oH7¢U±3˜Û¿ ´Ö‰ G2€Uu|¤-^K«Bïbö” ^døšÀˆlE#ákd2«À˜ª¬™¦ÖåF€ÔŸ¸09\§ÏB ¤hŽçmíZe‘Sª'›°m (±%ó“ž­yDU¦•%ãé¿°â›j‹i…Jè [ 6-L³Øv@j[9X›³ t½©N]—xk%” [sS’!ˆ$ )ñ=¯xþdS–%Æ4Ùñú¾¶u± Ûîçv8Ó6y·×ErHT{L¿¶/æ)i|¿F=ʾˆ{FɶҼ·mŸØH<\—æLY•³øc¤s4Ƚ &÷ž´%cBŸ-òm”gLGKfež•lÛÆ«D*0ΑZ‹fËÁjÛ ôµ³ÆcÔ ] ©¢-™-™À¬ÊƒÆ°M@£— Æ%Øj+a¨Ê3¦F°+AÙ™¯Ïmz]0BagñVÈÒ›ªT¶¶œ†`–šó½“+ÿL›†l>€ÀÊîD¹Juœ¦MÙð°¼1€ùTk%°¦‰Tµ§ŒQbÍ¿Q“•Z_[×Ò`dU1¸Y7I&`‰³Ý–•à©°ãU¥ÁÔS`6psªº+šf õe…L#E 7d€OÛ4R¸Ï ¬¨|&s¨/Aja¤@¶#ä7áªÒwÀœ7¤Reë2)Ñ¡š–mÍŸ£`n$o¸°ÁÏɪUØ$¶ fM_¯PžÌ–ì¿…)ådB‰Iò4d} ¤(;­oQŒ-A¤vEåßÝùxþ8”*ëZC Ð=)¡]«ÐWÃR°^Ië ¥ Ïζ )JÀZÐ ³ÝÉr˜‰ª ²j›,Oba6[ ³0ìÓ§i'²Â4­ýå¬IŽÅ÷›\mg$àYmãÑl &šŽ!X4ž•†^ÀVŒ°-*/…IYÇÈZmŒdÍÌÀx.4ÞvŒ-ìì½lñ°ß÷š°’°lM¢³3!BÖ‘Ž@†ï,ò1&©‹Öx«ÈÄz¾X¹ôe gê ýÍt^I 2¡¬ñÖ¶ÄÊõk>¼HtªÖ›9#ÊÆä–¹g …·í=£ÇdR‰¬Ž˜ÞqD)ÃÐ7I¶M"›•*Çì¤ð&i¶¶üÙå •Û¶°¨ÐZ—¶¦ªQ÷ÃmÇ©¤F4zÍÉœCÙ¾§ªM)[*Ù&yòm9ÿÀo¶Q'0!s/FW$K&¤ÜªÕÑleW¬‘”Ñ.ÕaB­‚›”àë‚ÉÜVJm)åR¶&4^-àž»mVu!0'µR§ÙóM‘²ñè ‚—©—µ,«²­xŒÖµHÖH«úzŸâ¼$ŒŒoB+O+²¦Üªz ðÞ Ýý— ON ¯–ÃÎÞvQ”¶Ä<רò3Ç÷+R¶è,ÍÀRJZs³bÊ’ €`GÀ¤i•5’B†˜H&9õý‰m¥”ØnxgIÖjë[Ë¿ƒ¦Éœ“,«­¾½H”uôgb`<0^9PžÆh‹”ÂL3±²®‚lzÀ «%#@ŠJˆ…€: 5ÒJ@ßYÚ&£Édž!ë¢dÍœ[­ka.ü®ôRjyZáF‹¥0ýÑŽc L0`³ññàš‡ŒØäž->Œ ›ßßïâ‘0™ gh¼¶7 ´2pÓâÆ6laŒ-@ ªMÓVÓܺ^M¯ðÓ4‡Z7d« Ó”µNèûƒQŽYЄÞ¨æA šd0<ÐvUnµsa”{LÄn>Ude5­D†em¯ð³´åÖ¾ª ÞÚ‘@<Ûœ«B] ì¤É¬«u„41½?º#§—ê–6•.L8c–ª5¦ŽMÅÿÌôýP ×ûüqöLµÖÔ·ò.Ù/W 7¾‘ƒ•§B€VN3™g[|% Lù#h0–ÚÑlòº bCZù!Ë0pÙfs Û5ŒU %sbªJ)…i$]xÂj‰…ŒGÆ °µF²ReK…ÕÖ½.¥`×®DSäÿ’†i$@v;œIü,æP9Y/ͣljj¦nBVL|Uâ Òh§g¤ Àp“Åcš HÉí—¿ýíotšqTéã K»kêHÌmqÞ'‘)ÀšFŠ€i…² ð¾j Øbd§OlÛE‚†'ýéñ5§äÓeÕˆ€˜[ Ã¬„ Occ¼^.(ƶÒ7 &0瀛­1”H©Å š5J†d Ȇ­d ýÕ¾vÛ@£&´"­N¡©*8ÿ­È:ïn†²GY;Yt„˜¿¶ÃÍ6¥”aÝOP7¼{ÐÎ$J´Ã[sã‰iZѹ¦œ~Ù[tôLfk+¶íŒj3Ì¿^˜‰1] ½#”BÚª}ýáÊ¥t±ÚÖÑÀX„(´­cÎ{.Ⱥd­i”Œ ”…Û’r“Õ)RÖÔÖ¡hnæ,ª2×Ú–ØV(‡ÛJÙžNÏ‹]ŠùVK/h²Eê‹™^ɶ§Í Vþ™X¡’ôY)Až!¾ïj¯™­—<òänäó¶øfÎyé™÷©÷á’òÜ+q9¶œõ¢ä7@ëóæÜ¨²¢Ã†‰¥C q¼µñzk²VCö3¼!=7Ñ´JÈd•#8l[Ê*( bÀÊJ)õÂgbí Á¨…«‚µX‹Hbà#_&^ài0‚³É1¦²Í¡Âɤ<‹æ8t„kvF倧dX¹F” UE¦ßíù²r½nÏÍ–LÔeM›³Q_œ[ ϪÊĦ’m˜Èw8ÒªJëN/¥VÀ²T2“˜4ɬLX!ÖôRáR¶Ä½f ¬˜"Æ;ãYÐ#¯ÁgÉÁœ²)KÀ…-M²0% k5ç¹îo )¿O#™4R°õ3+¶"Ûü~ˆ)sh2“WbÕ¨’ÖRª(•¤!ÃØ"ÃxÁ*Û|d‘ÕNÆ/)< P.ÙÊ?Cy3ñ§Ç•½¸1ú À7%VAÜ`‘V”B£V$eb¸³Û&¦Äá, 0LY½V«ªƒŸÊï—­»ÏÒV +l&ÞF«ƒ`2”½6gŒ,?“É&¦Ü.Â@IDAT\U…5ÚÐTÇÈ/Ô" †aÛpbå‘nZ|g!ÈMn¤4˜¥/"?jD_ 1’²T½)«”·â×…x£v@-X UÆ#°6¦J%¿üñ”C¹5ýøLŠ”§®¬ášF| *X‰Wܶ»&®\ Ù… f›†a-L,òWBO™Æ0O/ ×÷w¿ûmÿëC†©œÛzè«âaÛÍC#US}K‘UÛ¶I0×à<¿ÂØ@b‡ô¿9+ï”×ÂýãÍlKYdKÃ_!eÎ`$VXS[©e2¡¡¬Ä:€äÙ“ _ÿã·%ý4ÍÊJ–‰“Ã"½•gŒî˜eãÃRÝ’F¤oåL âw€H3K湋ƒ±»ö½Ü8ç dJÌ:œ¥r<~³‘ZÌy¶Ú˜J€/÷1·å +€7a+€×rUnÞ<²•HÁNªŠæÌ}_]äü¹çLªìô§ë÷SF)k˶F¶^æúþúãÓ¶^¬È”ˆÚy žQãI5@)XÔQ¡ ™Ç¤ÄˆÆ³ª"&à)xÚ*©£UÅ@ŠŒÞËÀçõùn±%fx‹”VLžMr3gÉ<‘5Ï4¶d4;>,´sud°•ÌêZð¢mµÖ4¬J%ÃÙ”0 e’dô< ÙÎnT ©ª•Ú6`ͳ-ÏÀ«ÜTÈžÅJÖš•h0ÊÌ]`%öÅB Œ,1>`Õ¶î[1ME ~l¥„vžµlOÐß¿Ô77VÅ58‹í ÕM.åêÄu¤ÙÑhÆçÌ ”µÒ[c`oBU)³µæIFï–¬fH“‰Z3À@%4•·ªmkA&%(ÕZ] F*ÿ:ÚöÍ™Iâdõ:.·ªz n[Žl2@Dš„ éP:Ú*ɪ¯V‰r¼lU×ò,“É Œ)êØªÊY¼i3Ù­8ž4ÇëÖf‚ÙͰڜ™¯ÅªšJ%òöÿ|r3or)ÀqÜRšÚe(+E kEvWpžFj*[€3MÊóŒ” s M!eÛ´=¯4V‚LZ™‹Uü8)“ÜhÊ&€¥˜wêÏïýž»7Yиv‘ôL„”îHæ¶0sÊj‹¿Ã~ža'"ÀèîÅVž €lò k7œ 7§ÖY2d_æ ›3/àôÖZ çtL‚îçÖ}jeu‰2éI%†iz‘J2Û†±EÒˆü­°ãŸ;|£ù² j;’-©Ôd¬uåžo˜àYc}%døz±m&%Bád™ Éè2zÀ6Ó¶Ú–50+µùtl Lƒ¹±…3·:—^Ä™”%È<…-KY¤ìZŽûõW%èSòTèVc¸õÒÈ ÊüÝôkM#›ÌŠ_ü·-}íVËÓTç½¹©…,ÿ®Ë#­ªÈêÛ„ÜÖËüÛ"›9ÀMVI‚ÆÈ!g½ .ú>>U P¶Z<`$b+Œ©ä-ï°›*‚‘¸ò&ÔNÖl1É*‰Äýa/&¥¾¶]EÀjúŽl[ @¨*«eH|3ÿ±(IÙÙëNÇÌÏ„RÊëÚÏŸ ßJ“ÌHHAÃD½3Ò$hK/l™¯0`Å €U£Â{3á¾û’Ñ8/Ò‘­l…ÿÓ&«­î€yˆOk%ùç`Åw´sœdûœž£~¿Í( ¬ E&~ÇíÇô¿ÚTÄuaÛ‘MÕ5È&ØÀ}'”R¢–8çª(»} z…òIlK¦Q6²È–o TÆS2Li˜®I&Û×Å:bh¬d•X‰‘ÀN(q™RxbØi½³|=,‹Œ¯/¬Kk…õíÿ°*çaˤr+M³5RŠ@„ñ‚@P¶rÐQPâ• SZSn››1hš¾*€a[ ¥*28½m1ñ@±FÊsPâ5·¾åvùÊy:EO¡*|çª|V@ÿ~û_ÿú7VHJV ˆž‹F™Ð#ÉÒzUgÙ@©´TJX¤·^§ÏW>[‡ÚÛŤû”e[I·jµíçE½hº%bþËÖÏÊyëÈÁ11¶ª¬¢›¤Rã-xfb]”U (².Ö&¨D•r[¤1:‚­.{¦4RE…d¢/ OnVë9¦ñlÄWγã 1‚9Ü–-y©FÂ4°Za[+=F£jÉ6‡”ÖÁøkvÜ0op°ÍPBÓ„°*§°­™pÌZ8» •73¼;§‘e¢ö O‹Þ@[Y[©­íÖüÉrfK\_¶]{]¤ÆÐ Œa˜ø· ›¯~.üãÿh8û¢¾&ÜõþV†Q5 Dyý?/4XµW•p`æo…yú²ðB«bke{,nx#kJ‰0L†CV ¡ª©´(¤Tõc CXyAiK&ªÊ?Y†˜ºÔJ鈑5†¨0Ÿzm•*‹QE³3ÂÜð;@Ì™žXäFÓmá:’9TÙæ±¥I–‰,RÿK0”%kfãaý&á‰H9׈Àït·ÏgÉmŒ­ «ÖÊ?š²Ö°µy¶RV‹‘UnÝ1Â9¿]jẗBR†yyÂÒGZzñ4Œ_¯”ßä9‘’•·¾úáÆÈAͿ򪂥zß`-ð4a[%0ßëÑ%¥#*Éœ8 [ض Ó6sø+<ˆÉLe«¤^Éú°„7ƒ×æ϶Sl dn`ßÊUe¢QS½k­½™ªð”ÉbŒ§\pËv¥Um×’‰òLl_Ðçᨠ[ùTNÖýÈêe+Òó©51L&ÈzXÍC Ð ÎB–ofkŸ>pAIÀªÂºÀ@%° n«¶­Â]N¿û‘µȆ'À¼­†À*Ø—0,UaG–Úäî[¥_ÍÝ•¬çµŽ±5úZç[}ü;NÎ4¢§¸.zǤ=}µM›g<,šVǶv„Ú1¬p@Ix…sf+¥µô…³ÅsÃPbŒŠáƒLƒï,@Óla²æi´r“*àŽc«„ ¯ ¨6Mb¶ ƒ¡·ÚöhèanHQ—™tÉ:žO÷<7`…jUµ%#Vkž"ÛÛáÈ $Ñö«ýœå«ú*ÿÄ0' —ZÛ½¶x+<½3’Ùæƒ\»4Sf;‡’€g÷fË-+‚ü+ôª;xŒµñ0>Ä| V˜xJQmŒ”m§SR#þ@¡ükvbX- %`Ï"^I©mdÛR¶©5[©®.M L¼a É3’CLÊzu–u™¡QÞâ7Ú6a0gwhÚ„dm1]1™ Y ÜT9+Yw˜§òºô=+Y̺0é¼9”ª¦Çš˜ ¥¬Qm»=@4F3óÜ0õ%âÓV—[t<ñ/ùË_|Â!ê—fÄÖßq,Ë"M÷U=ßNâš MœumjÜŠÑ>ÃîÔJþùÏ*!Uˆüµƒé;m]ü°Õ´‹6ƒB2@àOýu#b´ãæUÃð©…pl;%Þvú`ïŠ|}Û:žòœ3 šÄ ÷ÙŽd[ª{˜ÙÍÖ´¶ÎES6·ac[»1¼À9Ô ÓȤm%VS¥ÁɬBJ 2x%fË­w·­Ú@2‚™s—3Á<[²H‚JlÈ<#hÚMÚÂÓ&oBnB9@oMÜ$¶uL+×t}³µ¦XÁmÉ€iÞÉSŽÙ„ñ™”µv:šÆ¶F#Ë&ÖÙØxÙ3ë÷[2#0qÞæTRÔ7ÃwýæÏób’O‚ l½Àœ1ÓSêî“Ò ÚÕ Ù*¼ÆçIÑÐwLž}3Úµ³ Ê@žÊ1|„r«-gY)[À¶. ¹õ+—ÝF/@³µ®}VVæsÞ«*e«‘uÛ.Ç zÆZÊJ™?g@Ö$Õ’56™è{I™ ãÐ`¬¶d0«°å)Yüf“Mf6¤HÌ'½-\¡µˆI ¤aJµµÊƺt@Œmªˆ1Þ3Øz(Ö~-kTU4)2—£¤Ãbø[3Ìœ8½-@omž=ä‘Þ+²²Ê-¦ [Y¶_xžÚ)þ~üÁsë@/01F÷ôÍŸÛ·Ó‰kùù˜‡Æœ Û@åV$†³*Y+Fõª„ @ºm¸.«*qLþæ±”æÄ´í*¯]zæd‚¬4’¢T+lsC*ÄWŽD¼ZIÏÍŠÀB­°e¸Ÿ÷jÌ}»ÀwSâbýÂÓäñÚáS"Í@°¦Àº ÇX)7ÒLø~ß`< (­9kêµ÷_,GÒã•Ü7âóŸasSˆ‘%“µlùôæÐTÈÙH˜°Ldgì+%7nŸR—¢ aàËò‰Ô–âÐÃ65ó˜ëkà.éµ!"7k€¡µåŸ Ù¡d@¿aŽÅã~£aL µü¥öÄ3ÐETõu:ÿÄTXŠ™+ÓÀG}ˆ;¬/ «í[¢ÛÃà ‰ì–½Z«I(××À¹IeXUØ*è‘ç0óó«’‹Nrƒ'dÛw1Aç´ÊªÏ½3DÂS Ø–›Þ½vÀ4U¥Ô­œç[¢5FªŠ¬’éÈZÉô¢qžm¦!­õZ‰g@Ö$Êk 㸔`d™Ø  r¶­—y&‘2 ÅDw%` àáüÕ*±&Â×ì|¿œÊïŸ#­ÕZ‰•̘,@\ãó¯\ÄÃká2™$[-OŒVΤ’²yFâS2ŒQ‹¼?C z±3¶%Unµ­ à³[Zª™kWVa¶ Ùˉ,†ÀVŸl­¢mk Ù@þm­º1 ÿ[”å6=ÜðJÎEÜ€ñ Çá™p¶ʦ—…Å®ŽR¨oÅЫµ†Gú}{ßT¸Ú:&«Ñ[ÒôRø@Wd$@ a#t"@T²•¦r  oilãó$À«òp$\¬QYŒ¯szÛ×4Ÿ­x%ZÃ}§Éß¶ïÌTGüLšÓê—cHuv%­È^€މi àɬsv³¹=žÝ ”J.qž©h’¶Ä11'5ƒ vE¬hlUd Á~Ï…ÄЈ4Œ§)ÒÓ²:õ2ÉNALÓ$d°,€·Ò›¹.fÅ ©Š€2sµU¥´JDš¯é~ðÉ´e7X³5y-®ðdÍÏ­r«’ÆîïOûßK#æ#‹´:{M3ð±ÙzÛ‘0«8ÖÿùeÅ¡#XSÖ¯ ÙÖ=pÖÈÖjL2ïa±ÓïéxßP¥DȆ³­»… D Ëõ±J%ƒšÌÊ ë«JØF2·jOã«·¥ÌÙ\¶¬+‡1Ò—Âà­HUYÍMf-ˆßÙœR˜æ|AÝ­yêEÓ˜ô³•U‹oªy*HzYáDÍÌJ ŒfÀ(d+˜Â¶oƒ²VV^`d}“Õ &ˆ·"us³¥ÛÊRÎÓØa©®¢ÖHÙzaÃí ‚(&k%¶àƒTˆ§±9(ÌŸÚ?ýéO6ÊòÂf×Ç8;)qlntHëÆJÖô•c …Ú¸YæÂ¶cÇÙú¼ñ†eiú’ʃG¦dHÕ}Y}Ò*Ë!½‡š o@äÌ*l…¶†á(iK ËʨýÛê}1ÑÐËÒüa}ûa¦En ñ ‰aeUKÐ̘ºXÃZ š5ÊÁ*åZ˜4˜*Œ­5L#h’×±¦+‰‰Ì¡ãÄ(l`šdV-ðÖaš:6°³$A¡o­#Ï”7dña©ó}_E[ú{5˜º×TJ¤Œ¯KY-,%8wmkd­Ð¨²´¬@Ò ‚ެ£Tb xI©Ž€°à`%Æt †¶øôÚv:)‚²ú~þš¼Û7V:+\XÍíuÅÖL9Ža•  L`_H>Î(Wë7iC ÊÞŒ a ¡¥àwt}ÙŠàp<6À¿P+« }0l)™Ë²å#g‹NmTÊ¢9½Ù)•TÕlp7C/r@æfEž‚o£¦Ò¯ r˜9²[VÚÆD6<¥¬µ,ÌÊa­| LfÛœ4ø•x #ÆãèT%x¶ÒÔã«ÅkAiuÏȺcêB°Fv8Oí\61¼^ê…Tk›§ó6˜­,,ŒA `¶ÃÜj±.¥¶­UD^¿óÂÔ.½Uvš•Ï­l[”Ö¶€Æð-î#@,+¥Pª#tºøŽÙ ÀÆ«WìJ¹—åŒT»¶1”3‡ n6†©Èªµ²•аUU%<¿Ésºw–sQÛ‘V%}Kháíê¹§d•™&½, …¤Qkgæ°,&qÛl‰…lŒgÕA¬ôÜð4Á›ÐcM ¶Ò·]ÖÍ¯Š¸ûV‚Íã QB¦¯À¨JKYôôŽOà ¯0½a Ûø}oSŠæggKœ³-,Úæ£)þzœk)tq'øØ<¶fÈŸL¯¯üüSÖH<}¡í_ÃÆKͦ¼"»vLGÃüqܯ¿,1ÌjÊæi6 ºüÞ1Á«µ zø<’ïï@dx2Ãðï£ ´­0C%ȆqÒž¦ò²°väÆc¿¾…p·A …Ö;þgÉ$‡<1ÉÄ3÷àÀT¢Ÿ‰Ó‘¸TUÿmeµ.+«¨»-Ì 7Ö± 8,[Inée2W¤$[¤@–ò‚9‹¬B$·G`»¦pÛë‚’^•çÈʆ± |ÞéèÕ’áµöƒRÓ.¡÷ÄU§§1ÕÑW ôk•¿€UáZ[e›)˜›°Jí´h5½nÅgiÛ¨Q›`ËJ- ˰җ­Åœ#)NšFšÐí@Ï+70>ÄÈ|6?OŒX7М²’íëŽI†®hzÙu™s¶Y©¥† YÕTÊE­ïªâ <޲ü•ˆ¶VÁVH1T tWyÚÒà#½Ná&]TgT«ÐÊö—ßÿþ÷tPC\ÿS,Ì!TÖ^ ëÜ­w÷¹” 1dÚ(Ñ@­ÚCºÆŸ?$ÑÈjAлdÛÁ¬ŽDЄô‰Ñ(þ- —åÓU%Õ´ÖË2Çt€r-l…”-9‚÷?q€ì6¸ƒ+¯]CÞ¶vd¶dª² `(E ªŽ¥‘$Ni½ç_÷²V‹WU|á¹Û†:;Câ¢27€À·l‰¹E–íYì¼@Ç|™ÈÊ0|*ø;2 `¨ÝȶJ:Ë«¤Yàilù1‘LDbüªV‚q94j ™ÆZàcqĶ­&=8821| žx«Êª-lZ»§ÆÓà]cÙŒ›ÖÀ·úó-€'°"KuíÄYåVIâa)Ld&a‚KŸŽd<‚ «lK/²Âä“ Œ4l{?½Ï5ÝJàm»–ùdN0&óF’ÍÀ«Õ‡ÆØò„µž-ÞrF2Þyz$•¦ÏiŒTÓó!³¥‰o˜Zã;ZcÐ`D)”`„*¶x¤¸ò__i<™ŽVYãY;ÎñºrYùý†Æÿ•Yþuç@ŒôÖÁŠ1zÕRÊ€m OåÈM$ æ#0dH‘˜^– Òc²ÎŸ^$ ÑKI Ï6!2LŒ±b¬Èœ9°­@ÊZ…mLÛ­E†­˜Ä¥ˆ¥lut×S£áÉJª—¼Y¡ÄšÏªªµR"gRw ½ªVæ¥èA°W´Ë¡ï9d]NV•Xñz Y[J‘-æl­zÙzaL‚„ßIhŽË ¸ª4RBß–ÄV£iø ›Ydeýá<ÙÜÒàóÔ¨ZŒusÆÛjỢWÙÄL²9€,²Rë6 w2©…#Kes&kÎÄ;£\J9F0 T…ì‰ÝaM5¢ÔÈ– ßh4µÅ3ÅŽÀP#[‚Ìg¥°  l<2¼Uh*²jÕB–§Â•Õ–¾P¶Úcôe˜ÀÖJ8Ð$nYÇ•Hý%™ª3âý×lýŽjËA ¥-™*+>0ÛÎ…$o-ðFU5Od+pù¾Š‰…mÊúZ³Åà e­aë4=t €J €)«Ä c-œÿiÑÃrj«_Ùæh²40^a´é]«ÿI~Œ_ñÓÓLìm0Jo³ÂJÔn$‚¡1A[Yb+Œ4ªU—¶x¶½ÁR«¬ª4ž&±Uëeé=[ãÕÝ$ªüöïu´%Àp[‚^©¦â£jߢSÅYàéÆŠ7Œúd¬Œ,qæÖZã#ɘÕkc´•RˆwL«!Ï@ßÛä E©#Ûõ’ óiªzµÊÒk§—àV Ù ÕVNS ©&ÜÕÑö5¯–¸PR|‰ÏI7md™4ê9çýT×hæmiFªª5ï;Fíq¹>•„7ü•œSàSv?æQâ=÷¬V©—ƒ<Ÿªðw¢óŠ6 ^P&“ÈW™' ”:eWÃG!¦¿&QKƒÙ1ðÌe…©*oækv²¾åØ’©uLb8OšpCÂZw ¦”øòÌD6Íét}Èx˜§€‘Öf>ÒÊ 7€°j®£,ždMÎ&h¤’¶Q‰µm3̳÷¹F˜¥`á•¶ªb%ÅßšmdYXÓô•å[Ú´4ÕÂR¢É5Š奨Ø0þrŸÁ¦§;lâ1²ºà÷”1ÊÍPÀ²Èj­®¢1’Yë¹UIJ>΂ßí¥a 0é°@âuÓ#PBàÞĈ«ÊP‰ã0¤j¶°PÞ6þLà~lM£œÌš>±5ÐÓÑK-lU˜- ªíôù´M01Þš¦-çR½0nß/ÄÈæ¤¦Ú:êU»Èø€òšŸF#‚LógaÒ/1²JkM²ÝIïY—ãe0vúZ·â)™t@¯DaÇY•#ÓXa¤µW"M¤¬Id7kü%>42ž¸¦ á, ñ"ŒÇÀf†›67|ÓæVÏŠCVÖ@Ý­¶Ù‚2ð®·è×Obüõm0ŒÖuWèI­{†•4Fn¦ÊÁÊÄ*”7°-¥ÓY‘Ræ2„ (Çð±íZઈӓ‰‘”BŠ Ä–›­.ÌÓãþå¯ý«2cQ÷“ž>×N¥Pv:Ü7ŒL1F•ÏY‡´R¾”ø™ÚoÀ¶j‰» µMS#Yz3õ«îUϳÁj„‰´Ýœáî&PÒ„V±+† „Z#yÆ@þ@¼Zóhm¶Âlôýâli2$èøgÕTmæÄJl³ÊÁ ëEl%«DUõ"«Ð–F¼—)ËÇJ°Pãy*áOi k `:²ã7a‡²ªÍ Ÿ½PkU(ð|êŽ/l‹+?Ê<ùCªF™§ÉçZ~>!l¹¥±æ ¤g2òGŠ 2eÙiâi:uÃg[ÊZk]¬˜zám 8ˆCèÔñ™˜/Fy³ñ̶¤y¼EÝ PzܶpŒDÛf˜-GY;+ åjc2±Š;Èg˜¬êkŒþXôà”WRвSX5’å š ‰¡y«›¼òÑVÁªt´ÜOMÓXYeH­ž°u!Êó$.Ì™¡y*ɯ#ñî\-MUx€¦‹Å7 åô‚IÎ.¯ªZ…Y)Ä#Ra]øÀH&pzL¯]†ÛN†Q+«¤F@ÁŸìRŠ,ŸLlL)XdÈA‰”XÕÇýÛ.A—©Ð6\¯Äj…¬aÆꕳ^Ê+3¸ ¡C´rh•­Ö¶Ôf^ )Þªún•ª*¼î1yÚ"=k$ŒôL‰kZ#CøQh+EY­5·w€RdÙ¦÷*n$ ó|l™ oZ¤•FÊ%0±šg¸ùÕÒ˜PÀªúÔ׋^À41Çë~eQbD[ÀI9x"§ë7®üóÅ5ò–~~*©Âkÿ-ýü”²5‡Äô)‘É`Ám@ !FöÔjת[å?&AæÓš¦ÃV!“½umW’ÿíÿùÓiL/r%ëÅpþcf+Fª‘¼`jw^zÛ&°Mœ’y“Ô–mÍy¡ï• –µIiU¾*˜x¶]2}7ÌPjYJ… àhÃ]…‚•Ó¿þm·2w¨ó4».Ù7”·¥æÖAtYkÀõ’²R`Ë|Ä¥ˆcn›[$ßò>ï¶›PK&² dXªò+9³•r!j…*O‡o6@è.¥Y…w¢Ï‚ Ñs`›}ªÇ“áÐl°^0F/Û5'ìI…}múÛÆ#æFœ§r]ÈX50 6CY©{«`«`×([[$Ɇ¥šDßzaD²×À¥ñ, ¶ù‡^ª^²RdV~ &›¬•s§Æs¨;€ßÀȉ†©*‚,‡Lr€9—M<‡móo«Š^¬?C¢…Kc¸!#«rÞxàõoŒfîN60=\»J6¦7f/qšÖfNl þJˆ­Ê=Á˜~¬À4‰•«’–ŠWîhBk4/PE@‰ä\ª/¨ºoþjo·_ïÙH}•X§É-d‘ Å&0ê›omÔ){  "Öqåþ‘µ6ª¨)&ÌÊd•Œá[…lZ|ó_›ÏÿÍÑúVë‘eë[(qn²ŽÀÖv3´µ …"MO¶Ÿû•+ák#›¬¾’¬¶fN‰i°RVU"` -ˆ¥¼*HS•®uU”Æn*ÙlU Û|¬¢m ™*2>7ÿÑ¥ÌR¢£W'ÅTn%˜Ù6 Rªí^{¤™^¯Þ‚Ûùó‘1•^Ê|k€ƒ-aŒR2¼[áÆˆÜ:^¹ÈŸaxëjÏØþóŸÍŠýÁË@Æ5PÃùuD戧›ƒL–;Òð7å.Â@¬(i¼d€lÎÆ**—²•Rûy©Ð—gŒÉÉ“ÉÖô²˜LêX C$}Jéb-u¯Öü `KPmÝÞ/Е#yÂ93i¤lscžÏZ7$Â4ZØ66™¶60CÿÏHÆG–UnH ê"‹u±ÂÁ̯sU14|ÒÁÏþOßmÌä4½ËF’ÝÙÿÇðõe茭˜jÞ˜Uš'-‹ŒoÛZ­µKÖ1gÊ–/••• Mw‚!£OSª¦˜)»º•T5YQv«¬ 䨧Æõ"{dxJ «¨uµ0NOÙ[Š)eíÚ1‘¶YY+oÚ̳²¦´ )š§mU{ð˜>;¥¬5m†zxÁ¤l=n)€¡Ðß1n#¤ðj+g« OœïÃÄ¢ò.°ñý†Â^6šŽÐÚÜz«ê5è8²”XSßZ ÐûL øj%3𦪩U/z©ü1”"¤€[•LÓ–8’f…Ó¨­ÜȶÎN\ùüÕ–͇XÉÛ…Ikd;=1mÝSºäzYUqÃŒWe ØºŠ Û†Çt“™d¨—˜-¥-·V@*Ï:ÖŽ¬òÈcqÿ¨[‚X Ľ<¬0] Õu×S ³#hˆÝ=7ŒUØŠ+ù,•´æ#a†J×(’­ÐÅëš³µ·«B¸¯J²Æ“Zà…²ÖRm›‡@k}Å~"+‘ÅP–5ƒz&YÁ˜œÉܤôiš“@ÐT úÈÍ™!¾PË­Àh ¯¶ªÚUNFl[‹°U­Õðdªädd•fh•ÊAy&À­ø|¢ÛªKÁê…²‹µeU ;o¯tzµ¶^-‚CÂÂG¦;ÉV6Þœém‰Y Ïͺ1̰¬u`>Ády)»"ŒÚâ1IJ0F*À5€p#µmìÆ€#mcnéYj½­ ´K ”톯Á/“u‰oT%ãa§LdÉöøüìF¦Dz°K¶R*!NÀnk ©ê[¶”òÂh}eòLœ £]‡EžÿPlm|ž¥Í—º'ñÇ?þ1—Ü¥²è¶¯ ¯YúNÅ9·†HC³êh TNÀÊë+0Äñ€¼hkÍ :Ë«ïÁ`Ì 8À Ä<$ŸÎÒMuÞjekdå ¥PU45M¼y6j]’)É ¸ã|^}UÌŪ€Ä@˵° ü(QU!¥4V3D›¤Ú+ü|’ ÈúåÌÑh±ò°U¥^7›d8=zþFÊM­­ èD™¬]V|R ›s­á1ôȲ Y‘ 1}¶ë5Ãü•`X4aÀئõå+zë*TÕ‰*Gjgp0¥¬àoŒ^x ™•ƳЂ@ÄÓ¯<Þx‘¶R¶€*o8 ÅGSQªãhÍ.î,çCd«JßøA€±Å–'1ÐÐë(®3™î±òÆSH&¥6†@ZÕ0V2æmv:‘?^äf§R[£¶]‹5q“T®ÐVØj“}‰óˆÉØ®Q-ª5!žÆZ-ÜhD§èÞ&11ÈœfULĶ•GòŒ¯ê69¿Uçc%ö^Y™»ÀÌdôHа§4’æí²F€ã$PHÌ?«ÚU…Y(©ŠÐ`ÐÀ+ õ6†+e$,à¤qxX0ïu‚)ߦ@ÎJk%¦¢U5ešoÑÇ_ö´¹²|Þµs°JaÔÞŽÍ3Û4ôÖ<RÜ0]µFæ) A%Z>s«À¬j‰¶2Hé±j ûK1¼Ù¤ÜFJyµ”RÂVÐH‘ù~8¨õµÙÛHV +z‚9 a"L“2 +zszë8DZi ¼l{¶HÝ“UÕ–¿l P»H[šweØ H @œÆßo¡°*!Å™¬©l;¯í­>?%Ä=D©˜ TšÓé¹·Þ±EÕíy^‰.8[$eCZ Єin‡ÏBY‹ÈH2€B &ÏžŸ;©*z‚ê¢Ã£]ßz0°Ut.ÿézŸ%=ÆÚ¤ti6Î?ý ¤•^À9à‡<«;ιŠF’Rh èTbµµ2AZ ”È™3ê#ÕY¬esØéÈ™l3Ôým#›³*°*& S¸-«1ø¶e'S+¡€'X­ÔU}¾¯X›*À_pnÛIýu¯«@º /sïs)G#XíºØ*Ì­ pí?'R‚ôÑ`®Ê¶¸EçNÞ¶§àæy"1® Û²†áIPJ9&¤¥ÔÖôL š&´­*ëš$V;\TRÊ–Ìlܸ‘RÊ ¸¦V–êÈÄó,ËJ ¬‹,2Y„=2ßER.ŸRÀôByWdm0¤snXÉ•½.10þmÊÄD²ª‹•›U‰Ð7 ¶ád¶<­‰éá:ÂÄm­4˜w›CÎzí]í645¡<ñBIUÝÉÄ+ `ØÖ×j+¥ÊјÛê«EÝ•`¤€œ‰Mã•iÛî$‚¢ã©P9²U¡éâ&€mÎ0ýJÈP. È*Ì_Od‡„Ô1ú~gÚâëB“­l2†È&yKÒ—Çý^Ô„þ+ùü>a°Ænþ”MÛ5zJº=ÊΕ BÙºkkd;P"ˆ}‚daïj'Rb +!hH%97Œ«Ùb¼rFÔ’ëû( <\kÎ}fEÌÁJ/[‰rä+Às 3Þ«„Eí”4OcH)lr<\;2½T Ùx)Q ¦°E’YU |%Rà hþ™¨"Nc… /ÛBòIÜ´0Ð`¢­’à †V¼¦@Λ­m† …·¾|ª*K)Åd%ð¶²EŒÚª8ãó߲“íõƒU¥4C|ûˆž¯¿m&ÉÚbŠnCªIÜÞyýÈ0x3ô¤ †€¨Ö#ÐÔ¶Qém«zçÁŒrþNêŸè¥VÊŠÉd…=_Y% SÓãuOÜKY€ž•íúóëù­”ü«rðšú¨:POË…ÂJÌTJÀV¼ÐI±HyóŸ/M¤fÝZØ÷…Õv‰šOϹIÐ7º ÛÖ±Ià3Ê󡚌@VÔ4sr^9yÀ§ÇC#hD7 Û$rK`+Èl5jÎ¶ÜÆ÷FÙÕûH÷íƒQUž„ r–mK©\Ø"e)Meæî 1Ò¯*R‰ Á[0±â[‘<õêÔôÈxš®  yÚ‹x­ß¥€YæŒÙ`‚Ü`Y¼rØ s¢ñ)‚40ÍÍÿZÊ:š€­å8dˆZHÁÖ¬"UQÂÞ(ë},Ÿ?M%° )]S8·ÓàyþÉœ “®t¸Žd¬´Èp˜¬(Å¿€Ô%>w¸ZÝáÂ[dË¿G·UΤm%½$œ5…‘†ô”™ô?©§0þŠÆš­òMáøÈ¶ïð Òœ¡K[YÁ¿©( >%ý"Èœ¬ÍÖî_­BÉ€.”"CµÙfH&E  àЈæ0xÙ:&hÍ0‰È„³iñ Å>SÙ&;cÝÁ0Í@ÉœƒØbàZÀRÈ&G?¶È_|‰#†‘µ †yÏBƒl ©5¢AÆ´*ÇXÓ8Ù)ˆDšH“hç®*÷ sãP­ qúMUG¤r×ÐÃH6<`+å§¶ßúxºvâÎeÛ<ÍÜH êŽÿ ôý‰Ÿž'КÀYLÒqÒà31ÀŠ€Ì¶îÊ{[ÎTW“"Œ¯lJmÂC–RI]5óâbÈ`u‚ÎfJ$¬¼ŽÍW9F¶·!™l…J4–‚cÊ"qëÎ7²<5µv"Y¤Z¶+O£¶1¬"+ g%"Ìätú†^&Ä4h@S¤”½Ö½Ë!JL&rV‹œ1ÛH‚x¼ÀLÌl ,h*1ÀmrºÄ &²ÙZÆÉTåc›ÿ¶Ñ÷”10¥1œÂye;N-¬¢.€7‡CíØV˜<¦í­;…ø9,{®æ¾ýVYš¶À0Æ"0 d‡Ò–3`-å!° Rª¬Um`€LÇîd‚Lú]Ÿ 7ιù3ýUî5ýgà^n²­Jê…1 ,iM²Å¯°ª«ýõMjÔd ¹sÙ ­U!i ÀÏœL´­Áž{µN¤ÄTdÍF0)ÁÄŠ´ª"Ó”a3ÔÔÀ9 +' V‚ùà /wžˆ|;¹vX­múf®+¡5™è\ÜdÃ¥”çOS ¨Q$  piŒÊ9(aK€¶p̪"e¹]Õçñ…ÇwáÞ(óT˜§3ö:Áô”‚²dÃ1dŸŽdØA¬u7*¾»•xŒò4îm‰—rR8ÏÎ[-^àKÕEªwÆX¸vÎE©6·°^Ô)lñJj0f$ íV›˜ ýÕ~>€«•¢7Fm¶­Gëþi”Ûv¨×*\‰Öc+ÛÌ»4Ûܲr ÝÍÀÖ5êD¹5a½Z3§z!ÅšzÄza*Lûà e•O èëÈZÖ `¬Ž™¬! ¥D@_'¢W»Z÷±m…¢B2€ŒC&ƒI ©ÄxVFþð‡? ¥ÈtÄ ·ªozš®—Õ4Ñ& ‡­¶‘°Úb´N€Ï¡£Á/(ŠF’ÁHØ$æX½Š4f˳¹ÉªºÛj;Liª4u¬Ö*Ò wÞNd%¨u]Ü-9šžÈªhJDY3”}$åèÛ½­uAß}j‘ƒ”îù$+…yOŠj›ÙÄ0|aäºϰ`‹ UÙæ£W>RÊ‘¶H¸ ŒAŠÄ1Ä4­9Ã^á\¥ŽŽSSz¸Ôoÿüç?›RÊZ"Û·™2!+Uㆶõ ){‡<ßk~ð Âd]( qM3¡ÑËJÆ+ËĪŠ2[bñ£;}ÃPZù—e¥ 6Fg´…­dx¶V©/®Ó¹)A2óôøºT¢ À ðo}Y’õøpöl¬ 7kÁ“, Äé<¶¹qVîf*<7(ûö3gÕÂ)]Q2&¦²µ¸ê³HYà>AU5R…l L…TàEæ ;¾™³ÄÓo~…" E%cÂzYaÑ0%ÜÍXspiZk·‘*©K†d‰EÙ[çî*7J ¾¦¬6¹òúý:þºHe‚ISªÇ—‰F}¥¸ü©2}3àš*ô¡³N‰§1< Ö@Y+[Ì&fÎP¿oè‹QØô¹Ùž·‹Ú.ÓS09A ±7Ã[©”:ÂLò¡ÌÍŠ?#Þ'k•j•"æŒYG¸óªÑÌ £V¡•,+[Ьræ&dÅJ09Ó‹0LÓ§C;¸ZA`[S-^·)9TR÷ eæÚ±¥'[àÉnÃÏŸ¥1¶½”ªòQ²ÐSnÈ4xî +i¤pX4¤l[zØÚ¨e]²ßÓ0 EÀB jõ2€€ëE¹îø¬0ô9Pâɘ»d½Óá‚&1%[$ÆŠdÕ–°-`ä·]kµ…”€•äÜT¶ÄMrþ Gd¬È­Pä(Ås»œÛfj|8q×—ØZû·)|ê|š£Üx]C°,Ü1¼ZPÖ=eUVUú Ÿ¹-@#”“e×­u)kÙTa¬ºXû¤µº)þ3áST%ûFçeËJI#…*%Y•z )‘˜JÈ€0Rj³ÁÉM¬„8¬Ñð4«ú‘­ÄJ åÔ€'2hrV¦ê¦NQ÷Š·5ja³yÜF Ldó\áçÇ<[æi𼩑Lg¬¤ª”d®iÿšDY³ùÜ®c.K_ ˜¬ÈÄ¥ e‘|ú$KÕ h2Ja|Ý;NzJ})+©QM‰{ ¾Ú[½XÅÓ÷°tá óêÛ*…„‰aµµàÃC €0A¼¥Z3©ÑÄLà†¯5Y>¶ ›ƒÏr¢¶¦ÂDb¤ˆ­9÷-Ô©)^¿†¤wja[Sµb3ËÚvnÒV/â c s² ésÛJá§ K¯Qg®0+]hˆ­4õ²ÊŠü¥d×=gü.#• Rað¥jŠác ø1Û™O€Œ§!V.Źm2«Ð¯W%”4nÆZ–€M½(s+ wWô)ñYmÅ4mGËê%Õ(Gêe+Úb`YÀT#“! cH­ ˜¡¬hz©V“¤‘͇¦TÀa‰Éš¡ÿv`­ç–>On¬àbMÛn*ÀYjsvÀ4‘ÉÛNÿʈ›s3p˳Õ<ô«íÏxZc|âºsÇl'mfUÅ‘UÁ}ïÌ f%Ñ m•Óû Á<› œd¶€¦ 9Øßä]E¶SÐøôi´ás ¬È0‘u‰´.dÓk[Cµ€ ÐNUúȹªRU©<Òv%p§sípƒMc»’€5’XØ ¢$Œ„y&{ÏN?Эïv‘YM«°ì|¤0þ O•ðj)œØIaâÈžeU­)sƒÅœçí2×( OÏvù]Ž”Fõ=c݆*¤!1æ!zâGô}Ђ-½pâJøXùø‡™²¶gâçé4†IšSŠ~¡DêVœÏ*O[Y½tÔ6[­ûý÷ßùbP«0@^tá T˲¼jˆL–ª$Û0 7þ€!jÔsRæŸ=°%Î ©<ÏÌ¥˜'®4@XV‰5«[ªi€g¨pµ@Mk]~ æ@ +Œdm†¶0²y0”mñf€ëkKS9-^Tb•Ejg¥ðWõù² QÛ-QÂ" gí¼WnÈ µ"±ªl1”VÙx8%à&¨¯, rÃczçÓÄ3´¶†´0†ž³Ý›Yª¦²œ{¾Ä)«r®ëq®KëïC!Äw´óíÓ„Vgi ñ}&Ï’!A¶x†4ñÕªâ@,•ØZH ç²hü½ˆm†>¾ ²˜ŽcKÉÊŠlkZÝÉlCJ`l‘¢W-½ÿžÂjÙVEŸ žÜñs6•-M-ÊÚÆL¬œ`&²Nj5 ’•Ö|l3'ælf¼—aµ²pú‘ºÔ.†¡-R-† ¨e&üm#maJwÏSw·ÄŠOVpÁ3Yþ9p‹ŒÁS9\­-ÙÊmE³|¤LEƒÀºs[ n²Äs뮚G¶ß)3§é‰Ó3j¥€x%†Ô+’O)Ê<ã­‚^¶…ãß*Ûnƒ &qÝ¥0½ú"ûKÁÙ§lå&Ê*D g+ì˜V¶ ûêÙš«©Ä*0°m…‘°ŸâÓKi¤©It‘ì • Sæ!#h°4ÊÊ¥ºyU4Ö>s«  ­]B[Lƒñ´M9¼ø„iº[2)c¬¦×ì?ÿùÏŸþô§ÜîD^€ƒF@奌!ˆ¥Ê⛓Þ×lÿÆ…RJÐsv3ªhð5jB£ö‹iOßðÝ!q€ù¨'‹§é’^'@È  k1¦Û@ØV4RoÂ9Õý·IÉ6*5ÌI9·.G‰Ks¢Z§4v2k|@G[+Oÿ¦Ê2a›I3׺k„eša)[VÄ5’&6Ü—@IDATC PI½¬»Ìm…îYñußxž41²†•X[ùlPt´Ûç×çôÝVÛ™ðg^y·ÝT¬¤hüûôðR™ CP#k[­Õò±Õ¢ /«ÄEÙÊz€.yóðGö°Â®¨V6gan¶V%€˜O[kY>%cE&ASvŠ bàî§Ë±å‰™gÀG,’`…@/#kçƒ,Û`5µ°•x$Ï—›+>1ÍjAi¶~¡4-ŒqÆ&ÌðœÿûS»’ÖÍ D#ëË˪ɼmbÛ¥©æŒäð7GÊÖ`€©ºR2zÛ<Ó ‹#µñ*A*×¥S#ilo‹µ}¯²@Ê [kŸ>ï!ÿ×SйocÚüüé1Fj*+}+±ò“x>•0½BÕ @¯ƒË&xW©esf…1Éoÿûß›^qõ:­Ôé€ÚX•í}µ}SÄ®À*¤´!`â™çƒ$PÒËS5 |Æúþæh'.÷ùú0ŒB×Á*½m-¬˜ø4jdA š­ª0òöùõéšgm™ä¦»‘®ÙéHÓ«3A—з¬´U¯k ÔÚš!s¼SèůŠ`æx²¢l†2åMk…1m’1Q"êØ`px&4¢rÛ L)ú¶Vª‚`J`g™sHLæ9"E½¤Ú2¡É6r‚ t„ÆVôÜu²"CkØZйGÓÝ–Â{-1€ø †1ÌE>; Ás01²ò|`þx?udhË 3C¤Ôé÷5ôÅ!›¸vªd»`ç:5_>%g2<‡†ÌÓü¬ul~½d­¶”ÉÜPG%pèK):fxfú¾*n¦lM{è³ê³¬* 8g®Ä–U]ò´âEÛÄÓñJœv!LèsÖZT. “•êêÅéñýì8E>uì¼uTR¶Õö‡lR¹^GVn]»ø¬¬fKãa9ñNÔ•òôÍÉÆ¿·&¸XY¡Š­aðV¼l?™øs¶JQVBL°‘dájá¶Ä#MȶFHµ€ÈJšp¶R ¬ÆS»÷¿¥’0À8¦m¶Ril;æ~ŽÄWR/2Îâš#DZÓHØî6„-^0Ï©$¾É³äÏIY!%·ô˜ [WÒã¶½c~žBÙ 9¨…Ô¾[ Ï6 ‚)Ͷ•¦Ùdu·ŠÈ&½ô¶¢WÈ<^-¤Ÿïô†=zOÙºþŽƒ´âÅmòùa("•Üü©ÕbçU ó)dYåß´è3¹~ŸïÀe³j å"ü5>ÿà No}AX­Žp/*`+tç Üê) €¸dÌsæø†m‡õ!í¶múÎEXmVÖ²Èܺ@“PÊ®»I(‘|ð@×E‡j1ÃŽƒ‰¤a’-è€xA\SݳŠ'+õÒháK1©Öºª¯ÁùOâ¶«ª ýó,ybÒÐw[óç¿!·MÖLˆ1²Jª Håไd•ÈÒב )ÛÚvgT+¤ …R4 øÃ55í‚§”¢21Œíùn>ºBcmkD¸~,Ô㹟âï÷ÎŽQ{Û¶}UJl=K[˜§È„ëµ’Ùg‚á ‹dÖuQÛlñµ£DfO6%C¶VUÈ>ºÊ—†¡-š¦Ø6’Æšg€ ¹“¶rÖZÌöÔm{oøkT lû+%"’¦‘:)¸›\êòŸ¶æ¦*ž­ZiYÖj[ŒçLé‘®±_Mdñ‚ÆjKɰ‘næ,øÙ)µÀ‹˜œ; x€,qz+ñ5ø¼™i:,kN2L¤«hlžBJt| ^ãëÅ_H”lñý•|wÒ%÷cò˜ÞW¨Z«BAœUæ½ `U…OO¦Êض/ 7 œÈc$¥`…pµšJQ"lx¤^:fÕZöŒ~¯9æž@¸ÉOÙ=u½”ÈŠÌ¥ØâÓ0ªúrl`zJáD]r&ÚÑ\ïs3dV‡zýgŽŸ¦r†zñ xÊÆ«)›¤íè«¡$PUÊTFÅØ’lÙž»Já­j‘~𫲑BŠEÏÜVÖ“åÖ$f®K«lí¸¶Ùz©bÂJvA†×=ϦEŠ ûÖ‚;f7 ÓR] ^¬j5êhx2âs°û'j嶉³Å$³ªxU%+…RBæ µHúŽŒ`b<+AÉ1Aú) ”Ä7!g­­^Uέ ª"Àü˜^¹UJPêNùê9`š_yÙôVzHõI'Hã’›Ó–ÀÊÿäžI:Ž•À*´cųm%K!’²m}á}gbz+¼ç‘ôÜÜ„­.BÖ¶ááM )†4œ­·è¼!}¼vH/v§¦OlíCDÜUgÛHºt€m½:lµHÙ˜ZcDŒ*ž<#´í…lËP;w’®QÈ S릒uܦ'ÀÛªDb+“£ößvÄ ën0žMKYkÙy" ú/ü¼–ù×Ë*0Ù*g…±E6pLäQß  Y«.”ÝUÌŽœØš †é­‹kükÁÛ$v4Gög•9Œ”-M3dkxÃt' Úl§Äë¢Ü*…*ïÚ㥔·rC& GjXYyIhl³"»L Ir¶4øælJ`οýõ¯½VgÊFT©lV˜Z½R6½mk| Ö8óôÖ6¾Ofíòo²<ɤTQ*‡;¤,Æ ]šŸÐHH%ΣÐG´¦ºù(”ô•Àª¬ R’!Ó«åŒÄ ÞšRV!\@kJæÎEÞ ˜B¡¬ÄÄØZÕ <™œ’R²îŸaUV%Õâ Ý}jg}ȶ ŒèD[cÚ¦±z:˜~5Ïê´¼ŸF¼+j`Xy曡rmO¿{ ]W¿êars¬¤\uXûVб5‰^€Ph«FœSÝ÷Ö69ÍH˜¦1[M­½·|zÇú© ]ådÖÊx­Íií'VY©ÎRÓ÷ÈxÙ7ºøÊMÒ d‚ìZ: 2žIó´Ê†oÎZ'[óvG Úô¬BkAoµ% L“Ï‹ ºpåf¨Ja%8=¶’IqVËÁÖž¥l>0Ò¶j…·K9Aí¬Æh’&Ïyn4R­x¸ÇÝj[GcxpbJ¸îjFèÕV#%¢nR&Ä$ÆÓUùH9>¸fÇM¬ Ð<ª˜Ø;òË«µUE·r£¬‘U­TÂH%Vç Ð´10` dNf s0U½à•¬Åª¤vŸ)¥êÅU&óß7@êeÝ0ª„ªXÓ¬—ñ ¸µå_÷üeûwáµHkÀ´… Uð±eb J}…{ƒ‘0e+ÐÔ7gÀ*8øÞeNÜ«·];Ê1@|}­¶ÚY»`GÓÑV¹Á^=q¯ñ^xã!kGÐüÛvL¤Tc”R^G|)Ûúé‘„¬wLÖ t]üñ<;\¡UÄ(á#Ìü V) d…ñ0dV¤UPJ™ë΂¿gác ¤³LtKY«ÂÚVÄ[7Rí¤ênåsµ1|ÇùŒ—f…¹‘ÅpÀÀ3œÈÙZ¶-,*È.q–a`cïÙ¹&RaÃóÍPyí\ ¾-­uÎ@…Z¸y‚‘€PÞšœ¦·WÕÝèÍVÇÔ–ªvxbXT[^h´w@¯îä·ÿûß«ïóÙ¿œ€¤¶v/ÖÞ@ÄhP³ÒÅø€Qúâ†ÕÒ4}¡ë%ËGVJm+7o¤Ï§,ܸ€-ϯÙç× {ºs›“aΔ7ŒP©^G¤U¹£iúê2²^UÁ®Ž@–‰Fë ó¬–Øv{[z7€éî„2LcY‹fØÀLª¬?f¶E2·Î È¡ª†DrÈÄ]m‹³zwYU²uL¹B€F¶™ÛÓà>\+¦Ù`â†)«¤„œ¬{nÚHÃ(,æ&U‰´î–ðulÍٜȾ²™H |©˜ÊÇÌÍÖàd@J·DãÂÙúð·¥<»Ä}î"k—iwN Ë™^ôJ#5B cµµ~WYµ{î¶Ê‰ÊÍ3 Øâ †¶…¾ù79œø›ÿJDØšžI“¸IÂŒ*ë‘Ðã *Šš¶bd)‹z™?‡¶4uä [FÉL”ø~è–\IJÑ©Ú;F‰ôG;Ííùƪ¼ŽÍO€T…d+ÛÈž­*!“€ÂR¶°òÚÕWI4¶U!™*ëÞ[Î@ž¶JØ9(!p4Ù²r4”É¤Ò a<ÁÛ”[1ç·»ªL*ì\ôMRI[U¦7[]"1¥ÞÍì™BЦÁÔòÁ(Díl‘aJ¼Bk7ç UäS÷ž‹«@ŽGfÞœaksVÒ×Nð¥¬)U#5±,l¤|tŒäV@È’ &øZÛVÕ¶”0ŸÈÖ܎Ž–Ž´íBÒ»á†Á{=¬0”𢣱­6ŸV)$eM­uR‘Ù&›†²ËÁ8µ1^+å¶cº[[<ŸÌ‘˜7ÅÓ–¡KÎa­wuyº‡jõUÒµ˜‡ž£K+ÆEq¦²½@ÌVú5En tc|l[žL*ÁTÒ-]Éç‹wšI­d˜†aUå«ÁW[ 4 ìÒ";iJ¸SÂx½ð"}>˜šÂ¢ÙvœÍ£\JmÓ¶¥¯¼W¢TµYÅ´÷ï§²‹MÉóÝê(”4,…ïøW€ÒyHÒD~T¬FJØ*h¥Á× ¯V2 ¬ˆ÷i¶ ¬|D…¶§Ów2V¹Ñó±@”RØ2‡ Ž×÷si ¤'º`V{+>¸¬†‡AVœ™ž¦d~u³Ò˜‡†UƒÁ¼í0”¶øiºd½êB £•U%œ r>LZ_ÆWeËS F9ÓIx[Y1†²½›)k­5}Ç$S"¤bôФéV^ n}c82CXà­¶îK#”àÜ0—>80ÛñMEP»x«mÃ4žE­¥š–¬Sà9 1¥0õ")1@&@VX éÄ3…xq=Vëê73×b$)$\G†x—p*¿?kecú»+¼mJMyÂ4 ·íDæ¡‘B*„ù—ºÂÏǤI0™XixŠd:ÂÜš$O˜ŒØÁ­”xqëÎ<‘0 «ZÀHV7 Ë IoNÁ­-O˜@(Uµm6²w¶dÕ‹zU2L ¯-ÞJ†I`";‘¬^Z[³•Jl]íš";,å<&g²ªšbJÙvÚÁøVà ôhUaÛ. ÃA(1°F@óSÒ0´Åמcæ¥hr‹l©e‚‘ì&ÏF6@ó/›[ó$Ä+q„5Bš³B@l)¸ªnÏHkÑ©­&©KVJÚj7öRUé‚!³]‹­HkJoÛ kš •œØ·“¾žVE@ØfÛúãÈ9H5yå 7j]¬¹™J÷Cƒìh‡.2lUÒ×Kw¥KcÈv[ ¾¶W¨y@Öq´¦,¸ Sþ˜ßôi˜Ó¨²*±&è ¹ÁHzÛ(öchjš¸Ft„žƒWR/“à­d•à4I+Pjå ÙUÈfbk¶Ä·ù9”’·KŒ•,@`”`DŒÉÙú¡<·V¼›‡É¬„ôP„-«L”w|L3àËÚµ S•9RØÆlY²²ÖÄÆH‹>Oyå@Ç™f&N¡e-˜Kmž¶Ê šY ^- ìøó´Ez”]K  4ÝI 1Êj—Ûlñ¶Ä‚³-Y¼mÿø½»µí’VV…aU4«…ãîÄ*¬‘—ø¼*ž(«ãñùÛßþF‡Í«¹m¥UrÏn-ÛöÊfm¸NH£P ‹FG š”°CŠ™wnnŒ*†VdY«P‚!à›¶od­­ÉšÞ‰¤ªme’˜Uåµk+ÿÓòFJ½ª•ÂXɺ[å¬âHa àÔp&R#lúXÊÄE¸y `Ë0 sU_á¯1’rÑÖšÿZpà“?^`: ÜéÖHëJÒÃ4ô€Ãvíb’!•û»‡J´°õ=këõ£„19sÛ!Yõt2¤ž’X—uXüÆèà4”¯–£Q>•˧¯<Œ1Ó«Bæfë Tás[&uéŸÁZ[³ê€ª„r¤;„×HyšÌK!ÿûÓ´ytJ:~%²iÎ:™³…•Àm¥RZ«Ê®\ F—’ù#Ù*!î*Ǔќ±n8ï[ØÉ•sðDJåó:4OcXFä@)­|6†ì¤o4FMñËA­T|ò†0ÄVâx-ê’y<7[Uܼÿ=#2Ù9È|È„l#Uüú¥6ÃfhZß4BJ4On|4 “)g• ²2pÛœ­È•37dÝk¡PÆ7m«mVÖ¬ð:*2!–Ê ªèµK\aƒÉª:çüfWX/Ûëqn{™4j%ô)'Ë¡•žìÖ}jÛ¤geHä4ÓøHîG°*¤B|¶V†#+€¶( J)Ì“† y¤¯ ñúÊ[µ®»,C_Þ@–8M©”+,K§ßÛK`I L(­xkÎsÈdVA`xbå°¬­Fe­†)“§ì¤¶ªðM›“zÙŠL0x[€Þgʪ6_Êù#e[‹¾r1<ã¹UkÛYŽãuëOPÉb¶Ì/ëÑ(4p-8+Äw¢œm'ê(Ý¡°šÊ–^¶Ãbl«%ÈÍZ#ÝEíÂR…­Â¥œm;šTQþ[wž¬Àch¬¶MÛ6eš#ýþømK KÌÊ©E˜Œžfž¯LíÓÛúï\¹¥Éœ-]èHµÅ#m+±¤0¢‹RRùf#XðO¬°™U5íž>g&@%lžlb«ìoùË_¸•V¢ýúÕ49æeµµˆæk& {{ï¢6Jœ\áH+²{Û €QØ<Äü ]-Ò2Ì¡TkX•wËd¶ZVë@©Ž œ•™uT‹¬ÄŠ@¶²M¥ÀV:ÊÚ*Ÿ‰*¼Ï~M•(çŒô¿“@OÙlu'@Zi¤” å4H|t™4"€  þe• ³)·×.%Úu¢¾2É/`§ë÷/±(c˜ÕJ“ ®ðžæ|›ã)½Õ¦A:Z“ä@Ù´•TÙ)Ç멼0­”耺ãë‹dKЕâƒ^–a[ A¼Ú )Kƒ{FŽÙ_ÿËò‘m63&q… ø̪¶¾¶+¬‹T%xÉ›”­€1m}Æém­e«òò¯W©`q½?ß_|vRXª©È€Z«˜Ô(TU‹¦ŠçüÖÂM»™sÀ«ªÐxAf}ètÈü[‘‰Ž¹ª +Y_<¥Ô²·QØz渓ppcJC"oÏót+žÀê)`øßÒ3ÿÄ5 7CÀ[Ú`L²åS÷ñjaQ_ «.¤`#I)a¨ Fd¶H ó méÕ%•Û.RvÆ}YÕšXвªÙ"1ã‰aÙ|Z‘|çV•Âô¶îU"•ŸVÊPJÙÖ7™µàPhŒkp†Ä µÖYq𯶠ðÖÞ4Çâûùe.*(a+\aëHo¼>+AHøyVHl_Vô)“ô܉«ÊI¬7„XÔŽðJÜ\ÙjY©]ÕÆmŒwE*ÇeÒCáÖH&1†vVdמgUp©¦¥𤕬T[M£Q½ ¯\ kS¥±Ýq0¶­)3Éèd|Z+¡±-’Ñåu|1¶p ªîÓʧ”ÖFö-ѳ°6ž¬^Wuþ¨(Ù[Óçýý ÕÔª ¹9s‹WRÇ[w–d4E2ä¶ÙªÂÀB<‡áj‰wWHQ E ²Óeu…g‘Ý@«[«ã[ÉPy%)a×È*È„*<=åønYUJYOÁ{å½­JUËÀ#ȶ€4"sÌ0š’õ‘0}X~ûÇ?þ¡½ÏgíDg Þrj.pØÍ¨M)]ë@v`$Ûr >&4üý5°ŽªúS¬íŽDÝèVžxQÓszÑ–“I©˜‰›AJ 1 £ÜlJ1: ]t¿ÝÎo‡²Ì#›óÅô 0±2(á–^» ñç„ß÷ _­g$Õ ´i1a«h°b[‹¶?Öü‘d°•sÛ|ºw@¯‡¬T¦¢\z‘² [±,¥m>²Ê}·&ƒAþmµr˧gj¤&¡¤¬M•CÌR€H°eƒAïåce]RJ9>eYä l¥ 9sµû²¸mý`ðøœÅ‘é¥àZ´f‹P6 g@ YWg‹4eµ¶á@& À0††›¶¦uº&©¶g-k+[¯R•[ybòT <[4¡*[1Úu!˲‚[&bY@(gEc-‹„…ÆÊ9ÆZÖlRø ã‘O­ß„”ÂUÏ$>»µ°•²F­•\ƒÿwWÚ­6ójÓsFêÒ6«NTkÌf Iæª`@Ø:ŽFj•ˆ«ý,fˆo˜²ëB¤Éǵéë[—Ú½%²‚Xj‘óxó04a/P>M¶r%5•â¦Ê67U»@@a& ¦0·f°R}¦æÉ„À*›Û;@Y©8çãõýÐ¥·Ýð˜&´´@&°²­ª5 ÐJS AßöÙš6•T…™H™ãhj»Î…©D¶ª|lÉr&°M¦P宊²S Ÿj‰‘¢ª¶S£ædUÇ”R„jJÀ<TÞV*[°F¢™ä¶4”¾3‘n<ó™ ýâaËÁ* ãòñªò‡…ºÃ4R¶‹²#m4ãa|n¦å“Cže+„½óc¤‰¥2´Ju˜ÀÖ„02·4pY‚` àKØ%è(K웟+@¶W±yŒJÓðRëHYs0p ¾©TéKÈ&Àˆp)Y¡°S‡'ÀªdµÄpQ!ÏÛሠ,dáÖ™à4ŒÃzsß¶1€j—ûY#¨o«ŽE¼BU%€I6až™ôcn*2n€j­BJ°‚¹d¢m.ž,ñ4áž,@PÇ“õÿ`{sK°^SòBJ eb˜R¨·âïî<3Íœ³¾´»¨ÖªªB«íÄõÒ]aÇbhí–ªD–få¶áµµfn|CH˜­U¤ÑBd«—Fɬ ¸a”›VÓ@½¸É"Ebëôù`Œ¯ŠB$¦9yJ•Åd‚³Z̵ù¼ÓYe{›Ÿ…ÌzNxÍáJ¬1ÖÚ5-| ¾¯ˆF¥´Î0ŸJL¨µ 'su²Àt˜ ±-¬žXLמU«BA ê4¨‹ÖEd9…ížÿÜv³Å(ïÔ¶sôÝєÅLäLî6¼Üž`‘·îsöªÈŠJlKÅÔ´{ðË6IXJTH,rh[`½ÖC–Æš'Ÿj{ŸÕÎ9€‘".rËGJd(Ë_äü•ÿºŒ <»ªœ”޶¢,™È3ܶ&vÿ6†@-RdE K ©}`•(ÏЫ{+N ÆïÈ™´J-ê²H“O݉~e!дyÖÚ6¼#F%¾#Ÿ‰jÍI_ŠŒyÊ nf˜X(œ29㥽­”pÄ€]Z+1®ê¼íd1qJæi¶â˜²<¥Ï*6Y¤5=±_Éjäy5@nVÙ H y¸ß×;BWDoû!ee+´Óè-‘j µýZh „mõµ Hâ¥0zuÃMkKIðßqô0Ã^K┳Bjz¬þõ¯9€³òòÿ÷ÅA!NóÛ U9/$ìj»€€À ›Óò†íΰŠúvõªÎß·³Òð°½ç ËM­¤$ÜH°à©JŠ €¥5q³UR¯&_Id@ʶ¦·ÕùŸBâWkÕ:Ûÿ.QØ#”‚­”§ªÁXÕH£id-À*”>a%ÂV(:ŽÉlã2i†Lªj0#Uë᪒jíyöܳµÒà³ål ×®;ÁDZ 6ž^[+}ÍöÎÐ)’ß–ž^¬æÖT ,µ©Ô¾Û"i+¦û‡g^ŠŒsþÀk‹1Ö”­¶ýí”m> èsš3da»À„|U< Ù·ªIÌ/KæÕhð¶BʳàÎ$½ã#­‚¾`Þm «òóF(ÄÈ6q½˜XñÈÍhÅoì°Õß´jc ¨©ácX­K›g¼¬°å<2†"Ò™>ÞŠìDÖ|¬µèBŒ¤C [a< ’­µX‹1Ödê'wµÓO€/¥#²À Ÿn6nWþákCc+ª*2±:E]¦‘U(ð#ûz´Œ· ŒP%Âj›€FÊöª>Ýc×N×âD¦²æÓÀÖ‚¸íüSnK×÷[ôëöˆKÑ4pOdÊZÅ|€ž{­¥è­Ýó¡”â|ê¿×4$žØÖбMœÆ Ÿ žž³Pâ[˜GØ"–Ê_‰8êo è€.Ùœ²”Ì›_Ó Â àúWQÖöÕ—å–¡.¬ØNϲ£5•­ÓwÒÄÇëûR5ØÄk7LÖqê[S—à;²Z2ëγµÚÆ4ƒÂJÚJ¹*W‘yJY¯ÓçÛ¬ÙVh*Y÷QÎJ­¸£J„i:i_Œù[²JCÏÄŠÑeÃIÖxV-J)1†ìv>‹-s‚µ€“É*±mEbR‹Û–d«ªÐNàÞz«ÏKh¯*Üx_›Ï×B&?Jþ ?c+Ùíu󰩺. ?_QîB<µd^‰,†8Mgi«iÛ¦EfµlWŠt(ž"O‚º¤<ÿ ”µÿM(5'­°þ$k/Ÿ*¿ï²‚õ³•õêæ? M/ðV%Ä|è«M\­-.Å °âE¼mnÇúûçÔ²VŒµ‹pû¹aòi¼È&¡''³=¾ßï;)U­RsÈÐA03'È#`§#0‰¦Ã2g(››­£쀔g‚¯ M@c«Ð ‹èÈøÆjr$Ϯ݃ƒÅf`B d&Æ3å•}êÞüj‰+™_g)™ãúŽœOþRø5ò?cÝ'Žaµ@þ/ß:À´.Õ¶c²ÒÚÑšYгµ±‘†ÌÁð€g×)”¨|:{U4ª pJ)z$½OÌÓŽ‘‰)•ÈZ)U‰[`Qª¬”€[i`&<#1¶Wu^¤îÜV¤•&l· 13ª•U[Ô¹\ý7sþá^Y|]d;¯-Y>0@ó#Ìß³ €EUVÊ&pSíÎ#­”"~Úœ|fŽ'hS ÛÈÙÚvo˜"²©ÊfËŠÞAÜ?+%Í_«rk} lóA×½BxÊÜÊò×”XS‚:VžíšÚæIÙœ“­)Y\¯@­še Ò` [³‰xßE‚¿Ó½æá 4!ÜݬÀp³îÒRí¼Þ̹ÉÚîµ~K8' |f½7CV©¶sK¬°²›3qóÇXV°Âw^d‚WrûüzÐmiæÿPVJp²œ…21 \Õy{ï­~é§Te•ÕE4†mæÕ"¥r“g-ZiîŸInÕzÁh`«v޼yª­ïõyÙTU1Ç# ©Ñ¦mNþõÂ÷nÛ´ŽùÀxÎVµ‚¦)ÖHß:¾ÃÀR9§é…”.k„ן­ÕV6ÈâÔß:ŒZnØN9PSÙdÇëûš5¡ZÌjõíýq?‘dɬ ¹aRÚùS*i«È9Ã/¤ÇD¿ªj)›‡¡ˆ´UMÀ ¯¤,=¦ûÇh‡i’4¶@Q‰µñÖeskE®W òñó1[Q_b™€íd@†p +¸1zÿɘ#=&ÌžÔÊ‘™×Î: ,( `…ÀZhDÜA0iðìH€&™•,1 –EÊZ )M݃oŒ”Ûô• Ó”p2ë)Ôø/<ÿ)U XÖȪQ+A‚Q•¿ÁÈl‘˜U)+—Z¶Ú e)$P(¼ío¿ÿþ{¬¨¤Í¡^` ×|me‹ôÈÞ•ÉXÁ~É«G²&kš3ï÷óOé-¬/²NŽéü>­kp>¢ùÄl›’9ŒWÅlº¸r© j„§é ²‹ôfÎGV#H!‹X娠D™«j«Š¦1¬¢BJ½Dd֢!1·Ãç³Z ß´ÆëÕZ¯p§àP¡¾yÒt:©ô½Ö²6§‡(|kw@«ƒX(§Ì`„\h À ÌÇ<‘@I`$F—†GÒ¶1"›ã5¨É0JeEJ µ5"«¦,²tQVAl Yíè›Ü6Ÿy.Õ‘‰¥˜( ´ŽIiÅ”R%Ú{†²æáƒl˜.D­Tñº…+‘åÙÓ÷vImžHLS)©ÙýgÎFèÛ„óÔZS»º˜ªþ®{Y’î¶™5<ОøpŸv„áðÅÛžþùV¥¨–7H$@®UÕýé`S‹ÆÁQ²øJ…wØ7NÁ™ØbLp7=orGNC€[3D»(ÆiV„z«¢áã(!$ÂJ@U½ŸÁ¾ÓÚ(€7z² Rèí;P£h´çÈ"Ä2R|:´˜|„¶Ýtœ]ây¸LN§õÞ×#©˜b¡š*#ΜW(Y¨‘T§À<«|¿ÑpX²‚ªÈijT*v9ø·ã0ÑLÌ3d–ŽÒKnʪ—x.&tí‰G®“­*²ÀVJ˜bž#ÆAà{”·~Öö‰30)äRAg¤œTqkoâiæñÚ™'ƒDt@i¥e¥k¤¿ © ÎZ²˜'[£?›)yš÷é}þ}-w• ¼õ=x:‚w+;HÏQïm¤…Gƒ,ôq6!)AjªYCyiS 6%奟ÎûVÄäU‡'Åê,zß#ñù v!!é ÄI³4UJ|j8ª@AÿÜÕ?¦¿Ë)Hª »%]@H%´âð¼)À®BVÌy ” vd¾Æó?*) Øé»@#Å—ªêÜ6FHAêËK*`oRƒ#œ_«°)ü]{TqI!H;‰A¥wæÙG)‹¢Ú ¾ˆ„ä•f ˜ªÑ[Ò,²fI;cUªZ‚ð³ÄE!¯T´˜¶j†JSk–¡}™–6Ÿ%B¹XªÑ8­”Îrw=àRAljV¯8ûÀòI©fGúû¸ )È|W䥧¹KK¿ÞÝL .¦ÄO³´%ÿ§p[?.ñ–Ñ"½;ž „Øpsk‘FP É•Ä è!ĉ½?ã$® Ô«K옔„‰'D» F^ªšr?½ ‰kÛ™ÑgYSÐàÅ<+ÑŠ8ºpï^‚ñ iF®ËVuiQÍ'‚6PÀ Y ÞöQµ[ÕÛñ¹(1 v“!zë"U™·˜R—ªVª15„î¡öhZ Ö"ÅÔ‚¶–Òq” ª ˜[ص L|GDè\4¾Ë@4Δ,ÓÎáûÀ®·F)k¨F 2D¬WÊĆ ”€¾FŠUñÍb/¹–8Õ|S`¸ÆL•¦‰¼Rx--éD]@†)U*…Cp¤b"ª~q¬‹,°ónCH ‚Dx²µ+ùЉ|Ét^knßb|†0q¥x#x)‹aõò]¦ ÙŠ)ñÒÈ}'4«€kéÚУ{‡šËÎÈïïa!-,½õÏåk”¦&ÆŒF™Áµ„‡ ”ZF (e£!ØVUà£Yi: ¦ê8R%©v8Ñ&H<&ŽxRî‡>N`dL½tX8ϤçZï·w³ÒWÂ)†·6A±Æ˜¶BC&rÔ¿Ÿ ö© DŽ'ØV—þ»–·½Þv¨]!gíS¬Ás´­F÷Riétv†ó†P£¸A<„ 5J‘!ÉÆ‘2:8L/ÀÓjPÏE—_§ýÛ/hŠR)>„Aø@^ªÄO6$óm´‰5FÖòG›`GFHJoÁ½–³Ù×¶@—tˆËlPRõ$p!oJYËô‹õÖ¾)³‰ðâ.Ù'®ªs_Yð”@tÅ .îØ¶lcBÀ6Pbp)µ‚>fðvRbk$.†D–úÓÿ;°*¿YÈ–ÙG±’–D UB6®È ­v@6T)p%íhLŒL‡ÄŒ,mm4ˆMì~zQªjܵÔHSo¸«V…§/Ø>â”ëÒâWgÔ!‚™””µ^^‰§ÏÓ· ²˜­(U5±Äx;„CèÓ‰¯ôJŇ4H‹˜idþ§¥xgA¶ƒTœæ6APZ*>*_ÙF·ƒ”âÿè’šÒ Ú!‘Ç¡C¶×[P£m;Âh=585GðwS¤ž¾qh@Ö¬Km;èõG-JÔlOþÕÁ¤CP»X@„EÀÛŠf!tØ¥ŸûQª½^9qü¥>\Öc-ÇqE8Ö.0uRÌómr¿%Äq´ŒN?_ú.Fˆi(Y:A(ó.ªÿ~ ‰Dðö—†[²}Bxû‡$¾C! Gµ•ˆ0+ñ•T/ëì®t¦~/A H¹8>A)_ ¥sX%¸T죽&UD,ÀAÖ•…+Ik7™ÁÝd»Iº%ŽÓ…SNMŠ ŸI)t¤¿ïÓ•2½JâRñ4Úˆ©±Þ8¦×= óbHñÚ½¶RUPX‡¼G'œ'ΜSЈnà]µ´4÷6}~ )Íš‚Ã¥mÂo\±"À·Ÿ ±†¸#tó6¡/@V-€xŽ<çé‡f?AZ@’©â@˜˜o1`8ß¶´¨J™Ø fáPN¡–ÈÅF×(¥ããlUq³0 Vêmy²J넱j#x¹{(ˆ¹³õò¤€Ý³Âpæ\GôÊâKµ#(­$ÖRW¸˜-®+$¯E5[;Á&¾Õ/ëŒO˜„CĆªì¿’Sì)à÷%P£.U¸SÃqà@A µòT¥˜•í\W´>ò@-Ì<Žî!e´¬1Z6 ^© Åͽz‡yëlj×+Nj"†6}|„6AFsê)ôLc¢-@h¯dâÔêµ Ä§Ày]òº"KM¬½FÓY R4>ý”ñÙ¢”B‡Û„Çï÷O çÇ *(R»¦Õ~p»².¿m´1á€âJŽ×9‘‰ðJtš"ž¾‰ŒB´‰ÚÎÀ£á0í Âd+¡µ ΖDŸ†kZT)3A ?G÷*tSª~ÆÔRI#ƒK¼j7.n[ˆ³Ðð¾ãðáb¸€ÈL ¾ö»éq7ƒÐ³è–§^1Ax7,3Áª˜‚ÍÂ'.EãwuÕ‚àPâNd‡ö×û¶·vÊpü3û{Ép?­×AšKîP¦3qwBfC_ÙbÊÑ óÛªÑpAd¥µp½öé=ni†,pp-–Lçï{@í¬ßá´‹ó5æMäM¡ÆÈ!°T/)÷Ð¥µ¹ ^*+…$¥Eª‹álDq²@šã´¡ý¥ Œ\W…벿À·$E"Ç·U1¯-BK:\9&q:•,¦Ê÷yAè¡´*&5U^ ff AËV‡D®Ý†fyë(k'Å ÚGLOgÕp:‚RÊÒZÒ8uá(ÅT«öÚ;¦} ²’ÀJÑt!ˆ1 2Ò7²MÔ"ÅçÅðJ·ûü2M¼*Ķ€¡ñ=‚ø<œÔb‡:…RAd^‚\ÔËñZ ĘbœhUyË·¿jO­Ç‡öÇ–m¥ŠßßWl18Žú˜K©E¶mk 1(nÙV,š@)…Ú â_Êq5"ÇáY]¬¥-é ôÖžl+¡U2Žu34=J ÍÚyU)P¼Ò‚JU×BDLÓhFÁw…TP£®ö¯eã ¦Y‹·­S+Šé;Ei4LœæAh–Ý"Ô’H1Y¥6ä'«*M3¦“ ²úN¹j X#A^üøÝ_[5Ï6«» µâ>ñÀ­G" Á±-Ðam®Ôèm³…!õº%½‘ø]B½<išOgm%p3©íõHPšf÷Ù&<ÓbZˆ`n´®dí tFÞ¡ &Ž)^Š æëzGc õù(ÅL¡«Ðe¢j© *¿à‹[¾mA"g¹k¶C‹}+Ÿ…¥¤(hì~ bH] ŠMLêmQ¢Q¸pô—¿ÿýï=þü7Æoo@óè6¹#ù®QÕdoB'ÃOaWnF (“BPjJÓ;'I¤Ym%ÆkI¹)q€ïP„m Ç?Û_£Ã„¼#ÂCnvÒ†–Æ„b^ãL‰¬dkèL-e%œ¾¹\ŽÔ±>«‘4$È DtU·@]pA²)3™µÜ÷û.¨„v)Ÿw§w†”™ˆ8³¾¸.#àÀ[¢«=;f;@vAñ¦«6e¯Öb|ÓóÒë„Ê ZpΤJ‚<0&$MçR/©ÝI›§~{jŸ%§`x:1«’µq8BW×Yº™ð6)n‡mKgH¯Y#zÜ-³Æ†¶I¼¡ÍÞpíÝù”[•`›«62°€²*“6WPjIAH‰â˜m‚_Ð,%ëìÒ.Y—UKùõ¢I‡jÄ—6yƒÂêÚbÃMiPjp÷Ž ï8ùÈ•L±yd1ƒ/h“¼ËPPÕÞ—FÌd§$%ˆÌ€”¡³Hqеà@,L­};ud¾ ‰ª,Ò¥ÑàYäÅ]Âþ€ ìöìaüñµª† Z»7A\`‡Z¤‰w?©)w9ÔÕèÉ’"Â6º†óöé;i‚ÈJ|¦Tuü­*h"­ÑRd&µgíâ^©A¥ü4áb&€3ûPcµÛ\Õm°VRoúÒðÔ¼6RRÝmW„áUë=Ãî8Þ”WYü¦mÛ,½È-MíJ.ÞˆŽct½ït‚Ôò¥<#ÎpR,"`JðNšæ|ÂþgZ‰¹ ˜·Õ“¶L¾c¶);w9 ¥\c©Ò¦É¿AUà=‰a×Kù^ÕùN lÕýí6|œDÄhŒ`øÿŒUã“== A0]…>O¶ã[¦MÚb£5¢3&Ø8]üRÃ|çÖˆ #*ðÒ¶Rß @–lû à‹[IµÈ™ô5-YÌ>¿zá5v.`")üòüÃzú„ûˆ¦E\¿X'6¯T ¥EhK«6ƒo½ªñC 0CÑt‰‘7AZ‹@5Íótb&Âëê…6‡!`@h¦ßcÐÄI¡}ò@Aß\ªRÈÅë˜ÈÁ”"Ãd‚þXåGšj"vpÕªÄ1<"F`ºjÓ÷àâÓaÚ«òÅ8Œ`üR*ÕÞÚGúÞ†ÎÆOMµR/îÕ>Ž`þ |D´‹àŠ ¡NÏ÷ÇpHdãzMaÑ€L;fñ‚¥c*aRk¤ª S2%Ÿ)!»C麀Ý*° [lWM™Ôh!<>0©Òí Wì¥0Û¸¼®ƒN“ >Ï*ñ)ÀSÈG;ìÛØò”{"Z ^¿®Z Äq¤µ éÊ‹ ŽÉ"MDÐP ¨‹‡KW*€¸âLÌO¿–‰(T L mHÓõøF:&5¿«ÚGœx¯J4{O!Å„°3¹X©€¦kwÛb#Îà;z©™…ãï*ªM¹}ÇY©’ÀÚ}öíÝS¶ƒ^ÌáPnVg,Õ. ™&YˆmYȪü–ãÔ¾ýã(½¦¥ÓµÀ=ÁyÁR¨‹×›   ³FÀTB“* ÐòJø F#£½F^¬Ä$žòÌk¸|‚âÎ%ړ׈F¤å¥h3L½)HuõMcä–Œ)Ef@4>Û©£gJ êå0}„Ô ¦ D x¸”ÏêÍ'¸j`7Ð)’hÕÉJ›²­Já‰`ŠUHM•'åÒºäL|‚o–Ÿ§t˜—ïP˜b-ÒÆ5sú!=Öm’B[!0Röá‹34%žl`Ìù%<æUý|¿­+0ß’öha‹Yµq¥žB/ÛN„Öh>µ‚ðN‘ „>Ž޹gsy:•-?Ù½mˆœ¥°Àh!U›»Up $Èëmt ÒÚÓ)6=T:+mÊI 6´^íÀé$î–\»’´¹Ó«®yⲡ¸·̓Øw&œ§ TÕ%ýå×_íRHÈyŒ“ó#¤ß>+m!Ò$„oÝN(B-A>…ZŠ[—gu¡!¨*8Í·q1š*¯¥cK™5xäˆsÞâoîÈ}ß3šÉ’r~¼ÑÚ­R½FàC\¨Ø ~јNARý;‘›¢×YtÕÈk‰ßb)oJ½<‚cÂq؆Bð‰ð‘+Á#ÄI\»A•‘’ p:/DÜ,± eÕ˜|²|íIMÀj²j¥Ë:fúøŒ¬*¿ÓhDn+È ¢«´F)2VâÓyEà˜|`¿7Ðý³¶UZ{]R j ºJº&Í#˜øºpúyƒ­ËD É£„˜(Í0íßÎÈfAØ—uþЦ‘·r1áI ´L|ÊÈLéʾ¢ñìLº³Ÿ`¸®8DUùm‚&Þ¸ †cB2´4¥íO3}¥8^˜®bãàD4B˜*¯+5ÕzqXd„AjŒoIi1µø ‹-M%:q¾êd1!U•¤ÅÉJMdábƒ¾É7+BÇ×»vL4¦š¾Ýüî¡D 9N´©ÕŽ“xid¾?œ$¥TUÊœ¨xúJô lNMŒægùvŸ«h%>«ñUÖ.%Ë‹ûØ"Cº“ÈK ‚·Fšbf&ãX©'¶O~û”öa×Òmlm)&¯TKsqZ‹YJ™ª>SUrŸÅ¢Õ•N4ŽFy_Añ‘ÓŸlß<º<}Pmzãĺø,eˆ*k pàÛ«:ÁVrdA±*¾˜l:­‡S)©Èt˜ã¼LqœÀNPÚ>©?ƒ¿_ÔIÅA0”it!8!ÉJ'%’Å䛋3DÀ¯×D‡"˜fjcv·/@IDATÆy«) Ýe?¿‰g:ˆóJÓ‡ˆiRG)“I‰x ø bíV¯´Ñøzk/h"JÈGñÞ[)Ó›W… 5bkq"ëJŸO!|U`ä<<¾ AÁµ”íe(2„,P;°ãÜúoŒŒÜ7°–Fµøú²@kwF‚y¼÷ ­öb×(h:ZßÌHY/CÓ(íó+6šeÁçoüëŠÔ·³À¿¢J¢òíWÐ*m†©$6rÈøÄ#ð@ÇN!M1Ãô£Ñf;!A7UªŠÓmF¦F‡‚ÏlÞŒÑ{}M‡ÛA#¿j|Èq(Ûb+U¦«¸û ‰‘&DܽkÇâï_q†8]dx-1• øi¦ÏScUĦ0],)-LIšˆXuíðR<‚“ÒÑ(ÅLÍa!R{2i"Ýs;O-f ÚYd²˜RSToå”fÀ¤ ªRÖ{h= ÆÈU ¶$©$`ªtpH킦«¶Ìº¯ÕŽÌ Z†Ž8_ˆŒæ~ê ÁGkr¸ ´ý3P÷ùNÑ˨±bdñ¶R®´ #ãʶ*Ü–ªê‚$R` í&`µóJ^¥L—G ‹Åüü<>¸.¦Z¬±=¥#¯·~¾ímˆ¹.ù•¢çÃéàtX &)è…ô2C¼fK÷‰°ÈÆl.ejÓq¤pÁ»[اÌ7ÀûQô>#øwÖí@¤ÛtóúNÁÁÄ¥-©±Sk¬·C¡Õâ>AÜA¤D&Þƒ0n|̦´’)!dÛÂgÅÛ*ðnýùÂ…ob4¾¹˜ZܵØÙ¡(°~<µ}½KL_Ťõ €ö×B¹R-½câ?Adƒ:‚RK[CÚÝâ4B Þ)ÚG`ÖzŒ2|qL]Òf .ñ8„JbÛÁ#´¹} nIUÖ) JùV>?Ÿo+´ m´éµORyCNÍm+¥ÐÜ<š*|í©jÏÔ (‘ª]ÉAzˆëUmðÚy]¤ºb šXé½=üF(u.iÊ•ô2ûh‡gtd >ñôµd@V¬$"€”.Ø@S>BßãLM`4N£Ñ¶ƒnÛ“ 4*Q§ pEMLÿõi×ÛíõëB@Î ßðü• }š—¸T2Á|kl7A1þ4ß^âg³ûzðJµô@‹·‰T‡¯·@¼»…2Îzb>Ò©7¢SàèâX³âÔU™™TíïrX/¸ÅБ X_ïR„&öý§ÌÎ6¿ÿ9+¥`̼”ÁM9¯»ÍÔäÊT¤ R ƒ´‚3Nƒ{–#k×^I/P£.¥1Kí »æš\M|-€ËJPIÀ, G7”ŽA˜ÍMj±˜ÀÈÀî®eLTÀwéÜ5Ïž}Å[@`"¼Æ³Ü÷ì‚pÊ~V‰1âĵ@(HyúÈc¤ÌTÒÂÄÔ0¤Ý_ j‡8MÔÂÆ!G£suùNGëVÅ4A?zµCÌv%?²6©]ªQL.n´X;\ $(Uíùzâpüáv«K‰,Zo0MÌâyxÓ¤ '²MB¶I"f:ÅRUq¶*r4U`Ò¡¬a ²*S-¨½b--ÌGn·âé“ — ìÜòÖ.€`z¯`³ÜÉÞ"†Ò§³7‚N%œ&òô]5OŠß1µ°¦Û¿#`Â{ýZ˜g—þ™"&¢EPW—#ÕžTSªŠœ‘[&&‹¿¹h±µÐÁð¬ÒÁoz%`C‘qFFªõÄà›ŠÏ´KhùR>$ròì|{J_Î≇-†—ZFJ!0ßÁ#t"OVÙý áZº=`šNRJ$Ф”¬¡´´gU`]MWeÀ¬øbÇaÖ"ÕųpAâkà°­‡ã)@ÆÑëh½öp£ãÇQ…‚F/'Œ\!®k¸”Q`‚F°†vÕÅJ7B0M²8˜Dü.H‡Â•ü8HWÐâkA@§/s4A˜!“nºæ @%k8‘€dá»"ij-C‡Ñ{ÞmNç%41Îåþöã`£ÃüáWjIéÅ#&° ¼å¥´ãÄŸ)4œ‚˜8 )†'>0fšq’Šæ«êb^€ªpäÌ=(Aˆ¬š ´Ë,åGS’¾W a›(FàïuÞb ¬K‡ARk„Í!]WÊ5zU€è €ÔÎ#ðl ^÷#-hV À“Ú&h¬ë AfÀÞ=Aƒ>ÿpGê044O°=ÞbLGÊ, Æ”ô2ƒãð¬–7ëÂtMªV≿Ÿ´ôÉ"»n1°m}- *Umf‰!,Y ¬’¡Z˜”Õ%EN?Üb˜¾cªR0.ei»Åç¥<¦^1§Œ,€Ô^ZcqÕŽ êE&e¨M|-]Uäµ´g)_ ¿ƒì°.âMA/öX‰/Ø&M©Ôz8¬SÇye1ÉBpø»H‚¥¯>f]­§‹íDªÈ@1Û8b–²@õv^Ý<ƒ¿„!½ÆÏM€iR!MäUuʼnÐo?â}@šŽœQSÝt)Ãq¢Z~lµöhÒ†¶­4Yš•è:N³âhìM&šÕõâ§ß,)‚*Ï\‚H` TÌ›.¥ïÍ´U`SЯ‚˜UEc!˜¦„fMLÓ†8ÀDø>MùîAŠÃ‡8 Á­”8£ ª´4œ5—ˆªØÑežˆ¿WÇ;)\ì,ý¾R£ÞnÕ L¾¿ƒÌRnžH JÚ_S…KS O–­Wœæ­|~p(éÄÅizû«kÁ©‘)>&Pš&šôŒL ¨s‚Òöy¥ ,ri#ÞG¤“T„u!7(Nâ³­'mm4xj@Öh¡b%NS.åóË7„ÄU™*dy½®çÖ®10ñp U¥L‰ €íS5Ð[]©%¥#Ó2Ó‹Ð÷yéjÕ©^Ì}T·† oßç×¼5Øh˜&Š­: Î×—óFóÄlLA7o·Ô LÀ#¤ASBóyôY€CœKÀTÍj„$Ø>Òª@äíMµ‰šéÄIP˺6·åSŠÆ"4”8k[ˆÑ[U×hxˆv†|ÆßûT%’/eª>˜0N¯.%j‚àªéÀ¥8ÛæQ¯®*M¹ 52U½^°4M6=s5F#3 À˜­¨jaã∛¥Ô vè¢R¸Â¿=Üù¦ãP`hżöÖ௄S{š¯·2¦M´82„²R»¥S¯¡YRq›àødw11K\£A|¹›^Õm0ƒ( øh‚šÑÉzXÒî`¾¹¼”¦ÀkàóèßuoC:@¥µ ¼Ì|›4i,v„m™µŸÁ b çŸø‹Žmt'G•v)‚ òzZ‰"(5øHßw¢Þ=¡„™¯%eÌ”5ÒlD"bHB<ƒ ’ !"ndÉYiûˆik/¾MçërGÚn=$O.N'¢YŒ¦i¨Ôjï×Â[C—ýŶþMÁô5×ßQNFA Ï€îíMÐÒòµH1yf}xg‡K‹ÅÌt¶Yãlb4Õ ¡©¹Ço@Êâ¨Ö+(æ#ˆˆÃG2i"n DjÛz;B1f„&òh,Á­a[´R¥À”žl©SØŠ„¹Xœwáh-)¦¦E.`º€£Å”2-¶Â‘ò†“…+I¯Øçž!‹l74iíM—â(yÓ &«jn;(5¢׿vDˆCSÊZCÐåHïœÏwñ½­s‡«âÓ¯Jª[²U% ˜ÿaMDˆ,EØh $Ÿ¸Rd8ó)ãµ/ðù]GÚèÆíŒ-¬JMI‹ }©81fU[c¥–q)·dó-f"« ^A:‘N‰£ 7N|Ò÷otA²é#L?/ŽÏ‘J¼’ôH,mª„·mdí!>)톯7pû‘t¤-²+îk34ëåxíñ›ëöèí ‡ÄáõvnŒ`jzL‹ûéOhÄ·*št `2 B½bA[%eº‰Ô€bL-n~]í38Do¾qíÀûad=jL&BœÈ Z,Pug΄DŽh4ˆ÷TáâÍí­CSí'Έ£%5R¦ r–¾%83Z)µx×NGéÏÛ%…»: ¢”`½Òæ+ÁY «nDYÖnõŠõ¶mÕt¬'2B:˜k¬‹?ã¿ï >¤ÀÔòô3©RâÈY |pA„ºòÖÛm»¨.¸ê¼®.BªF` ¸ÒZÐvoÀðÖ0BÉ ÐÏhC·ž›~]¥îAÀ®Øgbs_¤ö.­ ßÍ!™¡¤”¤ÈlsÅíƒ °dú}¥à•z©øÑïãÛqú'B-‘3õÎm¸ñç?ÿ¹¹JÉJífÕæV}Eà ¹=yör:)óÿY©RlÞlGj!¥š_Q1k­;ñwß\!USv_ø=cƒÅ4[ô=÷tBæ+˜'‚©³,)èÕ¡ÜíZRÆÔ5Yk¢GÓ8šøé÷.^ú¡µI„uÕËÃSkºïÙ¾:©½Sš»×ÈDRzwRC;x#ð•(ð2Äy!ÆáðLËŒŽ­h)sÀÎÌ(UÅé@TIñgÀMqÌÚ¤`w´¾_»‰Ÿ߇¥W5A±.:R @ÚƒKœl/Iâ^N´¦kdèDªBߤtIq” µ|ÅN ž7MÜþ‘³ÞSë°=ÏbRšû9 ¡éÞL`¢ñ-@Sš².½ÑbŠkhAƒ¯"eU‹ùd#÷K@sñ;©´jÌ«ôù\ê¡ÐHûæÂ̺±¶¥Ô¾ÅÚ¤ÅÚG 3]|^q½RLÈKw M)nt|^{ãH±ÅJ[`Ûºœ«Í Rnd1¼€ÜÙÙ2 R%¢êÅcHDUɇ·¡wµÏnÈÖˆ–”tpˆ´.L:ãvÀ¦ó -¦âÔBDØ’¥§{ÐUpeλ¤*v"û¨JIö$ˆ‰Ó2õæ‘•\¯Þ>{— ZTwAxSŒ{cÛ·³é˜Ú{jbU¾Cõ- Ac‚L5ⶉq4“¥3‘Ä Œ¦7jÍ=þ·tæÝ‰)ÖèÒœ¨×R{ß2½4µ$W¢Ü8)~¾UK‰S˜².¥q ž‰‘/öùÃLJ™øÎ+Prºs• äl<Ñž„~1¤I“ÛÈÔK zB;@©WJɬNžì«Ñ.HV¯]™.Ç "è¦|…h „‹·m`Õ®8qø î^àV5ÞÜüîq"³g×e¨X{;k !…¼}¤p:Z"c €Ý¹à[ižxúÈ@j¤ØôßUÓoOªw÷Ï—²F JÀD:H Ÿ‰8]!…ßîßÂ)àSËð¥hÖ€tQ‘)0U AxÐÈÔTý* F¨šxkI9Ÿ¸R-FÓì\àh8tè‹\ŠÃXiÇQM\f]1ÅÆ¡Qf" Ù«siÔåÆð¥bFI‘µc–Rk"¾*¯$5bà™q¯H Î1Ô ç;)|A‚ÚÅht2g±³­êvþs;έ :H:ü&¦ùŠ}–Ô‰–Žãððfñ} ¨F†èe¶Â$IªF´¤šØh ‹¿%)ô¿Èæ6Ò‰–>DÐÛN°C < %¹L ë2D{%s 6½U#4zU¯ YÚ‹KùN±@•%X`DKâ0£CpÇa[è"hDC`ðtÚyËôžÛ]í³!+~}dípBYÌ *…KÚ/ïm#HëåIñï,V‚´9‘FDÓ®Z ÈËñUÅ.áOúïú—¿ü%Ü8̆’­ YŒÉ·[G¨ Ì(@,–HŸµ†“å‘w(q!¨Ù…à°žWäDÄiâwc¶\W-~†ú/°Ñ˜Í+ÑAèôþç?ÿ[ !ñJ)ð8ªÄí¬ ¤ºT¥LŠ“&})Pà€¤´ áÄí¦%ƒÔ’r^ Þ#€8ÞZi©€Ñ'‹'„‚`:Ò›˜š’¼…Ûj OŽØq&‚YU°‹['Zø­lz‰›Uû˜M‡{EëÚmDã0©‚ÔZ¯ÇáƒÐ8¾–í uœ)èRŠÃ'µ¡J¤ZºÿyLë·;vjJY‚>q¾«=ñ~UÀi¨’®,…”MVÊzU"ð®çA¼×~âdÅ[&6T@RÃG–Ö%¶aÊ=Jh1U™¸…-æ€zµðpüC½qOD)²*‘bçr¿¯4‚Mê­ôùßN ä1$*î´‚,Ñ<¤ E-_ÖyÒL¯‹`bßéFHÛŒo]þ Þj›èBS#r韟s@Ö8ÎÙbùÌÚ‡H—b϶jaÕ¦H½ýn_Õ‚y:J¥mÒn¼NÕb¾å«RnÛR"“*™å‘v£ƒ¬$`pïG-[IjÄŽ/f@F¡)µãô‘6.æøZš¢šQ`À­½›ISµMíVªê)+Q—:‘ AÔðw^°ŠÃ}G (›ÕƒÀÁ÷Xy;ðIE€°?ŠG¦€†@“oCAÕºÌjP 4¸§×È4Öû¶×« Ä”j, !¨+^ÊCpZÀ 8Ƥh¬‰éSFcVPZ¡ƒK÷s]°fp|C“ꔬ’Wˆ8܆šqøìݤ…ј5öª@0!.§“¢ùò!gm«„³Å M’¸”`ëõc²÷‡B²cBÄøY„~è†+Û˜AØN×ÁlhD Kuab†ÜÁy Ãvðá‚…Ÿ¦ß3ø¶µ†Ø‚§ —vê.§Íu‰MLˆŒÙ ±Àû›t¨!XŒi”2íÍMPŠ ¨¶¥6 il:Ï0Íå;&œ&(…D! ·¹”-êJP —òÍ…Ç·ŒÝLÄa@%L4'_•ÃÏ€|)¯JÄuý ¬«)Zb";‚MâS3]‰iy]ÕöO7ÈAÛ6¯—ákWͤž»Y­'eJ||±v)å<¸4q(mJœâ4•àf ,ßþ§Fü jçãëeé0gÞ˜M‚S¦¦EªÚˆ«ñ»…ÖS2Bû‚@ijº(ð¾åŒK*2pd1õb÷!"KÄž<ƒb"¨2¥Íž²vÕ63)Ÿ¸‡ 0ùŸšôHßÅÚ*Z'ªÊgc.@ ¬±»òÚØ¡. `! „Ô¸ö¤è(áôy\¾´³4ÈMÎ(°Î¯åÇ  ŒÌ»FÛuõ嬑/¦)ž 0\‹v¥Þ«N×¹”˜˜µÒÙìû#Hp»ÄLVI¯Øž4D¨1Aˆª+ XšU'‹öÚ@ËLI¿ƒPì÷­ttáÀ[€ ×^³¤”ùÍ­X‹ÛnhLR˜õŠÛ GÊ+ 7"2p©%\ÀlžÕ¥Ä¤Y%øtTÍRÂoÕÒºÐݹ¯GHùô{‰ ýOHY 3“AXSpše“~øÁy%620|‚˜Öˆý%Ћ5N€ŒÆëröh<ë­®K_jó–'"€X )bL: ª T‰ BünцáæJµ£­KÊ/NY\¯êꃠnD]œd5JÓ„´*ßUûÎ÷ï…{KûÁí³Àv‡䌹fP"4Å)« vFx†3¤¡î'°}^&…RL¦‡8¸•šØ2@#Å.ýðÑJµ8.è€i*5‹wuÑ(0HÁK‹9)#¢ÕÅ¿û;ì¤j—Æìø{èpk0ˆ˜Äï¡´•^`âU-•‹A«šT1‡_ Qà¤|OAªÑ1YR˜Èb8Ó•Õ•8B¦Ô  kÑEŠ7Ž7î=¬K OJÐòâ; ²*r²øl#J_¹õ:„,Z#RK’á˜EJª4nœT—Ï;‚ *Áø-€Æ6Σ—Ò¼ðùc[§#n±D4JÃi h–êJ6­ ¡Y;Ž.~C)Ÿ€×xmj<’k$¤N)ŸÖª!üĪ’RÍ:!)8oHã OP€ÀBxGª¥Å4n=†¯´.±k’Z@ÌÚAÐ&ÒÈUÑ\Ð/"<…1?‡ù~ÑhÇ´I Èàí…À‘¶!)©Ø±5ºªj̤4û¼íµ0ˆŽ†’ÞÍÒB3Y±ÞîªãHY»é"¢Y Ç„¤ÞAL24¾õh8bÍyvfß'8&ì]€@Ö ºà]KÌv€`BÈŠ5‘ÅLlm%ø|­vH]k`†óÒÖh(Ä[H¦v¥,å8b Mœ¤.[M¤_XË[Ec”;²gÑtšÈâ+ùù´q®à–Z'K35HN1öшb›Ž´S;Tå{:mè¨Fà×EVKü564ßb|½‘ñÛ­*¥¦$eÔká©*€àdb” X|ˆ€Üaá‡z¿©üÔà˜Ë’]Ù’Þd]JÔxñöék¯ !Ñh4Ö ¥”’UêÚ?f1&kÖÆI?>»•sLM-ƒz”Z”¤ºøÈ`L„{%FVMS Îõ™ÕÐÚÃ)HÃS«…”û%jân@ÚzzÅhRq üPÖ¥”šcvÒ†bj‡´ph¸ßÒR¥Þp1K$æþü8K‡ KLGЉ¬*ð]Í3 ø66N€£A;„A:š¡Z:A l8N¶x:ÚÃé_âq¦[“TjbÊwÇß~!ÖâBèlÂë21‘Ž/í ­Š£ au«Âk÷þú׿ªï¼ÒZ€LÏ”¯‘G°ï§)ÝCÛ&K$>#úN"íœZ½ù–éö¬])>©ÑbíÇGàã#÷r*U-Hß{&h]JU‹I±vÐ+àñh¼8\¬…IÃÅ}Þ¥1MÔU|¹¾¿ÆLŠ/pFAK¢YøÇD¥½*í3~â‚«w–´ƒkáqˆ.o#ÜÎðøJL é‰HVº•”NÃ}at±†/ÝÜî^#?~"¼Ýø8††·!ÐV-FÊŒ¤{@H-my"Ìaû •¢¹q,A‚~×Õ2âæ^îq”IéÂT Ûýò¯ýË_”ÕR³1.íó´ÒÝö·¯)²ã™4Po±Æº õÖüö»­¿ý-p‹ÖžGv§‰‹3²zÅÄ;ØæÖ.Õ®KŠVì¦ìÀ§&€³¥ˆÓ±ÒFˆ“Ý25ºFAãz¢ÆIµëí*JÅJ¼£%‚ÀŠSÛæk`L^LêÝH“q¸ê’&®Jm ˜h­Ô7Ávp'­Ç³Vª·}µ ´ð­$nÖÈ b2›¸¥]¤X Kl®À2¶ÚÐÓyß ½ŒàÄ1m¢¤·"M¿µ¥‹ã4+5½K ¶švGî]Éý7¨§\ ²Ý ˆà;8ZË[•C®Ú HÊ¥˜mÒJu GKY¼eÒï AVU".vÕbÅ2âÝ?Bã´×RŠÜ>Ò¶‚ü0³BÚdŸ¾†šH3YÞÜ ¶3ZÌÖ3ˆaÒ$(Î7B*ˆŽibx]¥8fu˜J>&³ ï{Œ¶…õzoüža·Zx¹@µAôUA^ÕÝ0BãZ»F ¸Í•ª¶L)Çd-ISРDÄæ°¼ÞÍUÒhLqFð~~ƒÔd›+ Øèíƒ,V5¥AëìpƒÎ¢÷9ò8%¥…* ïš.LY tŠ@]µTJ-Mø41½º™8‚É´H³ÒÄ!R#"x¨u:¿ò:r„|»Õ(VżÇúü›Æ…㣑r]!RÖñ{ÄF«VÒ"nÐ.GIl f_ø¦ð݉€ ï.ãhú§p–O¡YF@ˆ™¸´Kà Ñzèáb8e)Ÿ‚X dtšUU©Uu Š;£–4+ĺ %÷¯Êº(íµ4±éÀ]µX “"4ˆâRÌÎ…A†°ª¤TÓçá4oý|Q ;&&PÕnb7_{1O$‚€A42qûàK{C &â£9‚RÛÂm¨%©vC—TÏ((ÁyúV%E.Ö¸wr›ôÚ ozW‡ij@±óâóáMlh²8‚4›Û•À™.†–) ˆd/ˆæ4ж•Z ÓJÓ çS†#ô«5ð7‡ÙpR¨W 9o ¹‰ª•,FD×ZÞAZ0k„³Æéó™v†©jçÄ{»ôbžÿ#0¨=4Øà(ÝÅy)!ž ^ Á!~ju! ˜ ^B{&Òñ¢åëšdøÌµZÆÃ{oa;S°F:È5v9± Îní½vœ3ò^½ï%‚JG @°jÍ£ÁãG‡ôb9…Þ@x{Jšl"©µ¡¸µµ8?CÐ¥ªËn˜þk0ÿ3´M™TjR³˜`kŠqÈòÒ˜yˆ¡¼Y‚¢”!°ºxÊWìó1VÂFðìÜ¡U„¿Ýg%´†ò}°<Îiø’£•VåMoœ–• JíßÈZ \‹`g´-BZw+Eck,À´ƒÞª#”¶sS ðJL‰Î@4¦j6ôcò@“gµ»ü@~¿éZ>CÛÕQHD)…ÝR ¿Î,½Lq²'•eíb´v6]êµ{ôU“ê8õRcÈFtžIS¨‹ïÑ(Äâ÷f¶¾j‹á×óîÂÚÊ&Úɺä1‚4Ã4+°vsgÍí’NW¡SW zkäÅð¥o02Ž˜2Cè€V¦É+I=ÄË=H#Æ„kWªK*0ea¸@ÉC‰Ÿ&ãàªJmÕ=Ø¡[â·@LdL:JéwU_ ÅhDTzÍêÁuØ“QP-Y8A hZ;K„<¡A}QC42‡JÜí#Ŭ:‚_Dà¦k·Éb`KÒt¥VÅÅÈ@SšTÏ×8)2‚€rdx×+¨*5 ÇÏ/H[E&Û>8íPdZ€t˜@ +щéc²1á OM°YÚyñ¦ÔˆvÆÜAµ`:2)íb·$`@>òŽ[¯¡­:N"5F¦/ˆP¯}Ìj\„©òzùzuYR*ðÜð= HIdºzj„5 Xœy[i‘&hÊÞdi-hÐÚ2Y"ÈHµ9Á³ãÉòvÖë=áãtŠé8ŽvÑÎКµ¡¤Ì*¡ñ¬{Öe„{[I£jßá@1~ï縙tB‡8>\lí>YV…Ó¬ªD(@À1ù4)8Ëø4áÒf!ÃMdN,%hŠët"R©íˆ˜ZUÈ­øã¤hs·Ãùo4T(´býÔ¥-dj«¸ÖfuÕŒìat8ÝE‡4 HóhÝÝœ³1KÐ’NÎÖ¥W ¹X©F^c ²ØùklÊZxf¢–º-‰O³¡•à×¢ˆ”¶²o:ÃLÓaÅL‹Rj¥â[ùüQ¡5]˜5ºÀÖ8º×´ø«šâþÅyëuÒ^8„™.Êh¦à´³ ñ4ÃãðíVIªj1Òò‘!ÑZ;ò@%xÓ‹‰àØ–‡»7›ÁRÖžíðƵ<ÜñqzW¥âô1h‚¼¸·Îh%†“•†ðø<>Ch"o½sßÛâÑšuû>÷œægÌý ñZ*! =ÁfAÔ˜&i0~` ‹¥ª˜jîä½ÏDÒAS‚°w5J-ÉT‰kaâ–äª<¼.&FC6šAq¼À)ˆ{¥áŠ•¤þíä}Ë£©jOªÑÄã«BÄ|—&˜¡1LàSpóiv-JD ºñyÈp¥6´[L^£¹¿'©2|  )%&u|¥w+F@ð·ñ·½eZøÿçé·*¯—Ѽc».ekÚ(åá 3Uíhbj­=PDk¿}g¨@º§qÀ,¾8}„^ 7àg„F¥8Jé`~šeH7ŸNMoí8â^ k3qÞnf1qju•j/Ehm1µ›¨BS@ îc¼}ìÉ ñk·üÈ=”L¤Í›B*½ªÍ‚4+>¯ZsÓo|[ù´‰*™ÕiCçgÚdƒˆm[Ú)d˜‘ªÈ»ÃtÖ•rSZA•udAIßPß¼Fší¬¥qp4)¯J°¹ijiPR)·€Fi½‘‹R½À–L'$PŒ’fOB${BΥ߯Gg2 >‹0ÄÕ“5¨XŠ@V`1`wØö„˜(Å銌K®‹AÈ $MH4ÓuùœVwX~jZšEÓD%]éðÈô×"FÖ%ˆC¿‰CΊ÷töWBPööšÒbðN'0—”›(^J ŽG`P^‰xsà †KÅhn•ÛS5Å>Y )©F·§ër?_/Zêꇎv&€c:”^ƒÚ"¨¥Ò-)CXÌy;D8Êÿüç?;^Ò¦ÌÛhj)/ÕâºÍî>¤#˜%f¦ˆ;Nš­A”vF*r›4K‹™¯Q€œ²Þö—’CXœæòR¾R=RZ ]ziŠ[rº?Ÿô¢µg:N-k™&"ÇotñÅ>ïvûð@½£Q¶d_ÄmåJÑÐZ¦w£=k ðÏ—†O X#/fUù¶%(7¸YZXf.ͶrÒ8–¤€Ã‹SèŠt9D¤Yh– ßPŽ•z.†Ù8jZº+-ª<„B½‰k¡€‰Ðbq¤ ¹Ÿ†zUy»5W³¡p‚p¼ ì‰Ã§FÎôfp)¼^ ø—u\ 4>SÚJªÛM;›rŸA÷†“i·d#/h ^H:/ ÜYìCÓ’)ot|ûãˆÉÚ95íR»)éR¥áIAàRñëÆJÅÈy…õž?H:[Ô:k7ÆNŒ,¶>H}GtH…î‚/Õå<ÎFªX¸Š1U;$ĸ#}?rÔš…Ðnèè"ËÃ¥ù½pñ{ƒ&zQŒÃDà{HbË׈ÃÄmËKµÄ§ÉK×RÚR%Dûª‚Ó N܉Œ‰“ÁÜè®Eê,º˜ŸŒj¯Ë;.‚ªˆÖþ˜@q›ë !Ò¬¦7‘gÈ@â ÂÇì2‹á=—<ÏR@Šk‘Z£¾§s¦à¸d†©”5.€t?ÎoIû1⇂SIÀºž5, VÐÂÒŸ‚’Ñ™@ªZ¯ê‘¾Ï½…[lH½RÌb ZØD%)ÍdÑÖX Çl%›¬8eKöåØª4ªî˜ÀVª7æ}žB)š¹”[¬A©5%¯„t:Ö¹€±Ómy½b¯(Ï4jé ÔˆÜP¾+Ý&öŒoA©Lqid1°}BHÕA܉âð;f½ªo[½Ô˜ÀÂ5&‚ŸY¬‰?‹‘­Q$+ ÅSh1£Sòb½ÑF~ ¤Ü¤kÇG0‚¯— ^¶ÍcióÔötªòÛG€“&qRø@²âgïhÝr"ÚqêýŸ›´ƒU :NU{ b¥Ö˜f§Fîë’»[I1y]F¡ í Hñ7BšAˆ#ôA«`/0Ac– ØVv ¡CéeKIãÿv/[’ÝFEJ?ªçZúwrÞ8F(KÝíÈ`nnîÀ½™U¤¤6XŒÕ-Ñl 0ir}™ÇXa©€7X‹šò1RŠa#¹%Uf“íWêZ+Li›=Òâ;øyʬŠF"nT)…þšS @ä\­’2e«.HÑ ÖÛá|QÈrž¹^ž‚tÏP¯æìøœñ  ÈŸ€©/Mägå±bæFPC•ì™õN‹ÄDZ)ñ+7% PÓæ©ÊZ\³sv¡JIÝa7ï€ø†Opt÷)„›Òlæ÷Èè¥\WV ”×£©(oTa Ù^ø²z…YØy#áî0ñ¾~3¦«àI×´rX»Z7Þ/½T¶Üª’jWc%к;‘íD8*ndV°&ÂæH&”N1C|ÇÜl]”iá)Uf¶úÄÙÊÖ®Z|·¡¬ÊÚ Ä+CüR9l ¬œò·þóŸö¼¬­¬ Ô¸«=i³—¯ ¤ÌÃØÐxJ[2>Æ9‘;*±’ìEÑ´{9ÿ7²m˜C7@¬›[b䂬FVX–¿ì{› 1j‘é1€m@ÖVTN‰q.Ùf̼̀³ÔR¶VAŒáÄk'vŠ<1ÄÝÒÍŸwKÀªðô0†¬aWòùâ“¿F°”ggõ¤0Ö~;©„’Li kæ i+:~b%ñÖÊsH†é/ke讬d¢ZnZØ6dbX ³B*H ~3`4z£B%”zI9µ-ÞVÀÊ…”{³f'H9ñ²ôH«hlJÙ)9db¥±ìa™Š²ÙTq *‘ªê¸GIc[_‚4u”}Örž‰»6Ÿ…¬FY…YuÒHµ•›ÐÌJ(™ ‹É”ÌVwdBÖ?è´UhŒZã{¹mìÙv-€óîDçÆê«¦Idni*É-†˜F¡ð¦â#¥$~“ð4Lº72ØŠoŒª®ð|] ‹zu|YU°hTXêý„fγÈΰ”u ,ådcêBéh°îŒ1e·ç€Æ¨…µv@ÎVUe€#(d’ ÖdH«Ÿ¦‚¾©é»…š!7þ¶d-ÜE©’2@¡ÐH0 0†o³L¿ß‘²fj†[‘C2J79LS¡w ÏÖ‡T;Ýme›¼7#4–œO€2Ï#º!+"•Û¾&ÙÊ*² ‰ìø+Ïꇹ’µHi»`.:)7ž½oLðÕÂô~,4Í€&•?Fj8óÁlT8’¦B  µZÀkЭbvR¼°µ&Sn+8[ß¾u§ä,ÚZÛvoŽ)j¤öuÈÓÇß;W8ܶlµàP­g«B<œF,œK#«ªÆ«Y e‰Uu.X*F#±ÖÄRÝ…™äOF\Ç”Y!\¶mã)¤‰ñ1©¶_Dˆë¢èz ›A£¢¦ÙTÖšr ©…rÀК>g|…IJª0Å ®Á¹¦õŒ2d…äiž4êÞ½Ùv"$%1«¨¬ÜÃÚðz©ƒEå±UVd’i› qÛÖ¦mÎ ¼Fœgžx¶@˜Xk÷9A妑a­wj;£T¿“01 PÕœ¶0ÃŽôÎ÷¡)qVd0+[‘= ”g˜žc€°0IYzb Ä“™<±-’° ²R­ž©Ú•‹Þ€F P—¶nZ¨2I[ ­•¾ªº79^ä³,Ã÷l6—Æüò¾œ­JyºJŒmžua+"y¦lmK,h¦±Ž‘U‚±ÖZíoÿøÇ?$ ‰³¿s"5>(ð²H}å s¯ªg‚NØKãI8!’ L–›ÂµLCŒáÀªÂ0&^ A+f˜ ÌœØûêÉy<@¶øÆ£ ,{¡‹­BËjAÜœ@> ;B[â^@4CÓv4G„lÅc€Îk¡I %ê[¡m-Wòùôr5¿8ýnøÏwÍJ/çb.•ž! ›¾S»CÊfÈD¶mc«Â·áYÔò!¶pG‹¬Ö*+&}ž­uùv8'U›Òzš}O7VX¶a:šÚÓì>¦Í@Ö0‰ëˆ)£Önód4¥¬1HÀVÈ [΀”׬IZ¥T‚hÖTüØV¥P gLc ôÃ@²<1E$ÃÆ«)ÂV˜@¡UU|½ªºò£‘ò©0”€O“Õy; ìþemšÌ§)Èb:±·ŽRªŽÙZÓw@‚ú"'@*i~¸¨Ðj+•> r‡tÇtoñ†¡'FZ!Ì*1½¨‘Ta›òKœÀü¤Ô@IDAT÷¶ªÌUVÊÊ[2Û mcFÆXt$(•[z¨Fß:Z× _67¸h ˜²”rQ6¼§FßVQ-PÖ³Ö×M®»+åÜ&r%È#¨ ›˜^4FOÊû&Ûªi…ÖB;@I…V2[§ÈY–ƒˆ*äIf[:B@öеPØð•Û*71%,¦a.ò1RÃ$Þœ|lUi `à:b´CÆ#>ÈZû¥cÛèˆ1mó0ÉÖKØZK)ñó£$“ À ÏĶˆ¡GÖŽà›<Ç WbÃs“Ä´µ²â 8ˆèEºuÇ pd€@¬„a« ³–B†¥ò±ª]6«Öu!ÈǶB@à­³ºÜgÙËé>YQö ¢i+?£ƒ̰,çÈ}¬Ÿß"ÖZa-°ê ‡…lWá¹Ø:þ J &eKÜÅ2煮›¼Žœ™XÕ63@&FÖVˆdÞ 9¤D’aò©6g¼1š®KU•X+—ÊÙŠÉÖ®Zâž{[²9 õ¢&³šj}ݪ­ªd Y%°`âqgŽWî³òOWÈê˜^­-L¼¯¦ò.§ÕMn’<Ûæ`e˜’•ÏïçkÎX†0Ù¼¤aÅ"£¶,0°i;&Ž\K†4‚>ÛÆM֔ʑ ´›U‚´RŠÞÑctyb䬘 Ò`ÒÁVãY»eØ+n<š «–ƒ—ÅâÎï±¥LÆÓÖc3' ¯iØÌ>êš2©ï±¾!¥D&°Z%Õª`Yk$ÃX1jé+ùºžÿüÊÏ]¹í4»=& dž[3 2GëOöHÌq¿©f@hÑUà‘­”ùߢ3•F4.Dk$X‰l2 žÌéÖ´¬µ]¥Àà `¥|ÖÈ Àˆ )‘Ʀ¡ÇóA ÍÎ3:m¾çšPh](¯;qäµ<ä˜+ÒÍÌÇÖqº¢×'%+àåW8@3Ù¦ò¤üfœ¦›áCÖ€TUøº\Z®áÓO¼’œiè¡ÛîóÎÓWêŸuÊ6ª>˜†Ô”ƒ,ÀGªi›P—?þøƒ¸ÇÚÓi¤(ŒX-Øa¥P¨ªcr«6’F­T!n’¬dmsP•²Z[2à ծ\ lM`åÓ_:ð®‹Mó§Ä#‰¦3YGYO_öV|þ§j×5µuó4ä\ a„ÃNŠÉ¹#ƒ-MúR*ýRdú6¬…üï;o]n·3¶Ü L8Ô¨‡…1OíÈXi´@ê‚ÕÂýÖ¥JJkkâja²Óðj P_©0’€Cš°5‡VÙ^?ÛLr°ÂjݳVÇ·6^dB&vœ Íð4¦#—š¦*>9ôîœØ3w!…Bÿu>YJã¥G 8s€c`qó§µÌ€K°"yšÇR‰­­ø€‘È8K•Å7•-¾-C“œN÷¶Ô¦‘¢Ñ7eSÁoëoëôVóÙ)Òó:…îd 3Ùúy¦‡é‰E_JmwnÛ«BÃDH‰+üܧÚàÅ+ (1›Ž¢a*ÁÀdšæà»—'&Þj«Jx7zå…/‡Tq a+¥Ï@b¼VVH¬P`KYm'²*Á”"Û¿ “ƒ•@T®¤÷j$^ ׺Áliš(keŽ´ÒÃʼ1ñ–h¡PXUM¶uuVÛîY¹¦°eb5’<±™…ëEd “¬^ÝÏYÏb—Iƒ´*©Ü¶°Z5*½K>ÿ%ÝZe'¬˜Àv8ewª¥T È4N.t¥±ºJ< lŒÈß*Øb„Úp)ÌÌÊZßøá€ò½X”œÐÌn6†¸.¶aa»bÔ2´j‡ir%>0VçµâeKLàÊ7$&¾Ë÷þqÈÜéÈ0:Z…-+Û‚I HYñª>eUi¬›„ž8Ùº i8ô;Z2ÊÚow[µ½¬“Uh[Ô¥×à8ÐÜy?KÝË6¦£¹^Œî‚ÆV6_t|J¡¶òÄ­xå7d¾@ÕÍ©g+¾5AµÖÊ“¹Š1e²JºÛÜT•-U_ãUέù‰›àæ€a’-¬°‘h”ÈÚáE[«Fxã½å‘x¡6`¥Ï |Vz¼r†½BÝsƒ1§·"1²µ°*¡¯0·ðíðY0 “eÞ0øRm‰9P—À†´ Veûkh¤)ž Üä·íYÖËáF©ÊÒ“RÕÁk$EÆ$¥Õñm;š¬ò®%}­'«PGAÆÊ²À𑚠=OÙ@§PÕ×Kb)ÀZ ¸‘á‘‚¤CuÙ&'F–µÞêÏ¢* ž•­h`Ša€ç=Óç“ô óÜ ¬0_)a+es3ê†a‹—èó”Uåó2²ZY3½ÆsÎx§@ÁVb> e…­PŽñô› Ù> ÛEþ iA6B¡© ®Ådõ²¦—¥sÀ ¶ÖjY×ò€b[…‰OVHÁŽ“3} P‹™c`âz¥\_¼@ … $M[8 +øÔ|ß¶˜OY«$«= ù¼+ÒÁPNI­ã1ÜZµkÂ2[Q•¬gá÷øöçO2þdV)«‘¬BI$¦I ÄU# jW¯ÉšÍšƒl‚ñæ)Û`l»%MªÔ¦×TÊ…Ôšƒw,Y>²"±l r%ºÈnxó0!*âaþÂܬ”ÆÀÓH‰d3ÏA–­BYLU毲O½- ±Îáe´èf?ɰ%Ö›BbJµŽ—L»µÆ›I¨—›¦á|¿ônaæÌ“y[†°p5 m%áZl­¼Á(ña«ªn\­­º…@½\BOŽXéKß ‘ñHn°gæ•c8#µ¶…’ F!`+ iªe›XÓXkT-œÌjÑ(ÌÜ87›Êæì¼dÚxd¯ŠIÝm…ÿ%~>93‘Rb›¹)ºRY7£Kü²97v[3ðÑ‚!^Ô÷Ø}/ŠƒÇACéåÌ k—Œ@¡UÊ©» $¥Ú¦­ fBC,TQ¶¥gh€fh[X„oþ¿~4FU­ g%B£LRÖE6Áʵ TØ*[Ðð¹!ǯ—ìl91[`>™ YÁŬ”cš³[RˆÁ#É…k÷‚²@%jýMƒQ/†ôFê±Rz(”¶V8!Ý1AXV¨µø¸YÕö¾uÀ kÝ©uçé¡Ká[¥òÑ´úk­õ"“¢çÃ(Dvð¶]£¬À4¤¬2阔 —m0%Zð'ÈÖµ@V‚©œžæöù|¸†Uktþ²çû7/ewb}é¼°m2+Ü5R24L>ô"%~!KÓ„ML…Vƒ±Ê¹?”ª'œg‡ÅcÜžè¡p’˜låmù˜ÁÚÅÓ¨µ"«ª¤^šYQº1>e¥D[ ÐKZ(¡±RGú½)—ì­ëªÝ¬–¹It¡Ì æàm—ÂB‰«“°ê¶×QVÄógr3ç‰XÁÊ 0ŒÑl™×‹fJ†9›­™¥ºöŽYI};Å9ÿ þÄ ç9„²†©)f%?€T§¨‹ÌÜxÀžE> ~}̰á¶Í¶ ‘  Ãé[We€zU[Ç&Ìd7oHY+ÆMÊÈü›³‡ w'RÃjmUåŸ!œ…d|žWŽÞã3aCöÑ–EÂÄ.³î ×—žÏŽS¡TâVšƒÅpÞÑ0ã™§4*Ò︾j€L¶÷Ê̦Ï×zd†VAcmTJ ‡xk©øVwj<ò:}^%Rn¤”­±)uŸ¾Tâ²î®#p#ËA‰©ºº(Hk“§‘Òújêk’ªR*T…‘%ίˆ¯ c+ÈDcJA`[!ÊNDܶ²ª­ÇWN#åóiëÃ;ož“1Vcã[1+%H ?&s3Ô‘ÌJ°6¡û!ð*Jq³vcÜ´¨ªa*ô¹ýk$dªÙ¹¬?BJ!R;n)_ ’57a’xã a ZY`n@ØÊM¹z²”«ºÂsK¹ýÈæ™&C2“›Apž¾*Cbò!¨Ð–@!P9Y)>Y„7R`«B‚ùÓKiŠd«¦a\Žc"e‘0™fgôè¥xö™Uë=”òLi˜$KÏÍÏ9%ôøÚ)ß<·­QÝ¡­cß L0Êy*´õ#Š!`ÝŸÝ*q<ÍJŒÓe­:v"¶…ªÈFå¯J-ž€23Y¤mÎ_›3!RŠOºp†BVÓØ00Ãȶ•S4¨6[šÊ« çC 4Ü`VWd• `XU5D;N¬4éÃHضj›ù½´úÊöGˆ&¡W(šäô¾ leUujV¶°àfkõ¹¨Q ÁæÁh§»Ïì£ç3È­kÁˆ<ûö?ÏÅ–´–µâ­‘¬„ŽÓÒ‹;‹Bþ•+„½Æ•›/*ás½??ñÉò·brøôøNÛ‰ÉbÜÒU#ã­É2ŸFÝX£võ£ÙüÊ;Wn•ÃmëN@¯)CØK(Ki5ÆT²â™b`…¢G¬VÊ\/Ù^*z87 vMbË07€Þ61L k‘' ˆª2+Ux«­#dÒr/˜Z¤ÂH#šß$µãŒd5¦F™Û6@ ²8®ñig»áj‘Ì­ º%Õ’åcÅæô‰=©~É6^/ƒ,%™ ÎúúkM«Ëñ˜:B- Ã>Ws9±ÔV¸lwb˼Ðö·ÿûßÀŠ × )Lf ˜@޵əذm UJ@©N蜜CY%pAÖuÔËVÀ ÚjT¯øZ¿“CJ­èðZª0L“åƒa.U•m±Ž€ '¬È^޾ª ºè(èi4rRÇôž®•ÀgÀšY.[»ÙÒì ÊÖ˜LI)Ué3GvH¸‘Rª²­ gƒyíÈú‚+%+¤Ú$²Ö†·%hÚðÝÂÇèF& î» 3­¯ró(…im«5™ £•€Iáôð_þò—Ɔ®ˆÁíüùl7§u©œžFa¤ªe Xõó8²­U(oæj‰HcÃîÍ6ohªJÒ`Øæc¥ÄˆÙÂe¾”9”|‡òB%BªŽo—µS"hÒqêËÇ‹á‰X™Há÷†ãy6OO-C¤B†¦BŸµdÝ@&ÎEFLFLð–H7•B%¬Òô”òÍiÅ(;ÐØ²A²Š¡)»*¼@VÓWÂ9^*Cã…­4Õ¶‚¦‡H¦¶ùÍ Lþ” q-‚“Z#Åõ;³eîf€ÝЖ°2AžÊMRÓP†XT>ózYS¦1¡¦”ÈuŸC]:N½&SŽÏdúu4g¤µŽ•U²IÈ2ÁP¼Uȉ»C)…ÄÎ.ÕÓXñ Љò,«…B¼“^]bŒµ1¼Þ‰mª„-·@Vç‘ß¿k@bÔZs£M’§99hlUu3pq‹NV!+[óÈÂX0xJŒUål•µfLdørŸ%žÏ^Z…p“ ½žRG|G®ÐŠq«”4Ù6!…šej1zu@…R¶V‘çíy²ñ0RJª²ò¡ç)ògKmo+˜È%0ƒø49s _¡­òM7¿-\œ6÷ëB-gÁï,°,½>5— ò힘Fë”uï˜Ù8¤´*Çô Âd L¤I ¼]`—†ìÒ‰áÜ0Õ&Vè~ é‰ë.ëÕÂDv…d;-¶’ѧÉ“¿Õ`¶² PIURwOÝmñ”©¶ò \mJ+¾h0O-Lnu·êÞ½fÕ*W².YY‘¬Í^ØZk݃KŒ+ìÅæ™~&.¦4•¸ƒ•Ëœ¸ÇŠçC殬0FI‹ØŸ¹µÇ‘IC6OU²H Lie"ʶ%³E @bÇ jûÛßþö79Á.ßL•a蔩i›2Yz©dN+` pM¶þ^ƒB¶Ö¦‘%ë×ß÷ «AÍW‰c˧ÖÒ*bl ξµmÇdE X9CÄ×Y-2† Òªj-ÂÄüa² UÙ:¯d…T[YXBU>¯­¬m唺#­56Rz>Þ¼kïqØ å½š0±O>B Él)7?^´¦\S¶MÒI­Ì "ÿV"ÃÖk%Z+÷nô½ÒØrÍÌŠìâœÂV—²ôÊç ôšY•Y‘J”Vz«B©>fðíö燳¤”hTU>Ìù`” ]l…”ÕVy]‡¶Íäæ?_£J˜$à ¤-Þ)ðyfR!Í›If%«WÃÃã¥`1—$fëk>¬0ç@âcss™Þ*¼™{ î¼. fMcrwIÃ-¦wÆP2îATkÛ©g¸Ùð½4<ÍsŠo¹^¶V<°rP¢ ‡7BV‰¾RœVà[”#‹¶­7sRCÀ¹­“6dŒ¬Iª:í¿ß6Y)1scÓì6ÈøØ Yk澎°ù)¥rÇ8Ò0 •¸›ÙK’³T€š*Ÿs8e8«ºh-Jýá¼±52óþÍ+&U•°*”çP_“ÛZmaÎh-àRÖëq&×½r] ³ç‚ï‘áaæÚ<˜|hº@ª›ïÃ^az‡mTUrj˶5=`+Û·A˜yžj7 ½Ös³%Sî2}›ª.iZ+'3•Ë'P˜,L&àÖRUæGÈ–š~Ul…1”M»oÊøJøØlÖ¶Öœ™oÐtÆÓæ†í†F™ÛJlÚ2lmKŒ‘­víibÌfKÌ3f+€égÅÁs©£”€­”JŠ÷Ý›²É•Sˆ¥…]”,e¿tÁ³ºdï)J¤nÿ³à9—µ*)x½Hàz­J1[n13W…'À/¶Õ×`VŸþÚáé‘ [©Þ–°gØšÞ*Ö d¸ãÀj¯öˆßò¶ïMbLX¤,kH­3dÕHVAf•zŸ Œß0JÌÐϔʥŠëñç… ¬æI6PkÝXØÚCÿü¯)ÎËË©n8•\òUIÐJæÞ{*ir'Þ@xïG<2[¼‹à …`.…äf«Äšs¼”h>‚ |/È6qM­¬Èhj$Ö=LÀ:™cpKÖšyÎõ…_å뻦Ó÷Qq.2åxØÃö±Ü-R4$™Ðš¨ãå>$±º[€^ éEÝm)ÕÒ m=; Œ‰¬‹ WÞ#ÀØÖ"+É2©¶V‚‚aíZ‰W‘0qÓ2„¦¬üößR6Tw^%&5ÂÓØfÅÇÖœ©ãX뮪 iUU ¾i»"âRx½šÜã½®ª„ŽRem3·ÂM¨„¡a¤:/±T%”°v·,²=î÷ ²øn/CqK?ß81[Ó7¼×C_ñíðç"&“zÙrH(YÖ®›¹£}¾ÒSêÿV)ïžeÎ49”æ 4I)+2±ÕáS¡­nV”âÀ'Èy[YÝ­‚y¡ l0€ž 7Ê¥ÕŸžsàÚœñÌGŒÌSG+CäUQU¥o~[Y+%Þ+!²µVèÚ‰“š¹ªmì1‡! ÔÊÕ [´V®) ‘¯; º¼ÈJ9¾!Sæyj¾”9Wè— l•åù•>_¥4­l‚&eY«ÚFJv:Ý^™Of+lw^VnB#!ÛÅ Ã*Y3LæÆ|á«ÅWæCÜ¥‚Mïù"UEÒdå­ë,•À< IF ¿nGʤÇ'k›†C¡°jaÔ]аÊÖ¨¾ïAVH ¿ÛL Ì¿¬µ^ùäCÖM6ÀÚ1 “uÛäóU~W2ÑKt [3ó‰É'Û«: B)X 6|ì¾p­¥ ïB>µH¯P`¬·Ïçƒ/‹á#`«målMku·ŽÀV¡mz ².‘HQΊ¬ñ6ÐÐËòOo+eò˜ÎÅPÀ”x%Lt©öüwÛO w ¤b‚²¼rÑÒ¤zY%/zÔbšÛç4ª)£K— ¼m¼­Ð]( FIsRË"¥Ü‰m%µHlå&€+WØ[ëÆðB­5å™àûyÈ^¡U_'UK@¯5Œ·…eßRA¼*€­”µså9F¯ñ ëÕ$ÖPUS!ó÷ó‰I€I>«µUR#«IÌ& ë¸Lgªá­4: ½”,’E6[%£d<{aøäpŒ¾oš*‚¨¤vÕâV]˜wõ¥lf&L¹™møªÎbšÄjke+–‚i µ‰eñYIíP.Íü•Ј cÔn«9MÏӵ㠈ÓÀÊ?¾r Y#âô r0Òå#ë‚ÑE–_yž¯3e‚ë}Ö”C¤aëÙ5 ¾Ø$¶|Ò ›* óÆ+K ÒpVUdÕ²jgÞ<ªd/FµÈÅúÆ”õyá&UV*À oËÙé³mÚ3åý†ì¥u )¡J¨Ê Ç[+ñÈ–z«r¶F:p¬¯Éó¼Ö .¦¬»FzsDÒT¾•@Öõ2’ÐÅÖª)™µ*̧Ó=ŽS«]dHƒ+1p$>À_pcN`T«ˆïÔ”Z`â÷ÙÏÏÐÀR°µÚ6ç ¹©*0â½[CÃGtð®âjϫŰðïíôX)c^MJµž€Ì)þxæ)K³v°è"[…ù¤Ì°TŒµ-4²•zÙ ˜ÿåŽ!q~;Òß1Ï«+ÎdÿÈÌ­ 2©Š6A©4µ‹)›L‰­rÆÛ&«°kØ*d3w ¶ ÓÄ7@…ñ˜^Z|µîÔ0¦Zw•L¹ oóÏßzÔ:æ£V ’9,"#] ,˜ >[dŒÙãÓ̧-7â=Žõêç ¤QeñþHpúÝç²r€XÊÚ`Jd `»©bl)iÒ—mÅ)Á¡Zø-Dn쬔ߢó&nE¦´ú0\•­¨Wj¦tp«Z&”0 å}«#Ì`UYmzx!›ÆŠdÞðÕ6m‘­‘¼‘àL Ù¶€ SåÅnËJ‹H²Ru©|ÚÖCi ÔÆd~þà.R[Ý‚2¿’æf‘¬öºˆ¥Úb^½T>°ÂÎo©Ê!u‡‘Ó¬Fmá º…ŽA/rËY•@¦(c``bü{¶²ÅÊçSß² LŒÇeõlN#ÑT Tm»©V"U6ð™éûºÔÔ «âi%—E˜­“Æ…[¥ iÂÎH 4°TÝÉbl9X3ìc#«#ÅJÖZmÎ<»(ÛE2¼rkÝ‘mãâá~%‚; ^àk Äøá³al; sX#¶¥ ûu¶¢F9Ø­œÅɶaNÙ}âÄ"@¶º´æl€#ºa›gå"E‚4ȶ¬t'¬ª¿+Ò‘«Š¯6qþ²‘§ß„!€¬ÐÖ—’Õ–[Å-­·Ž¡¬yÔ¯‘T‘ùÆKF‰! Of+•,gždH1ú<+4€%=Æ`ùàU¥±æO&Òài: Õ_ ¾ãW[÷ÆhÍ ¯P•îôRy¦Á›'çôùËÚZ]™‰Z<Ì­ŽuGvÿɪíÃ讚¡¾ Â<Él+¦1º[%dx¤( K* @ žÉ¬oH(1 ‹)0þõÔ·B©æDãk— %l$_/üe«TM1p­ÏÐß¿£qÒNÔ±Ž9ð·Ým0Ä—…CÙ@kÉF¢ÖjÃÈFÒÜüYXÑcdiüM_Êãõ=WàL¿oënÍ (È4ù#Åó–Ї•'°f3Û®¢l­§´íATÂMÊI‘p-l³ÂЧÌ^4‰µÀÓˆÍï8õB®  ï¤oaO*¥¬”gx%ÈŽ6ž> *©_ƒ™¨ËÖ™¤ÙU8ȂƄÞ:&Ó«*k£0=Æ–›¨o‹e#«­o+æG¨!º³ísÄ#‹Ì÷| ¤š– {#@20é{Ä•wö “Ñ“Åp4oñnabVôÚ xµÆšF èŒp@ÖTò$¨¼!m¥VÔ««n$q‘^‰ÈG—†ÇT…‡«…žfB_!ÆVV¹Ï{Ûc5‡…¯ƒ˜|¥X`r‰ô„(½R&+i¾ÆÕ /(;ŒU!CX3L cŒæá°6[†° ¤dE+ižúZ‘dô°5±¬Öú~)ã‘Vkx‰™Ë6v+C«ê¤Ä m»ôdl$á,ð#i+› [ž_íC#8(ÑQ¶h+¥K¶ãÆ–¦¦€9•Kõ”ðaÒÍ÷àl¥0J°ñjQ;V”sÖH`hè [”[‘]gåéÕ²u‡Hâ”R”ÎŽ„ëkxŒr†iÆI`{…çõ`”0·µÂG†µ(ÛR:ŽlÚL¤h`£®[M3;HÎJÒðÔ@JÙvóŒ¯W+&²I] ÿZä K‰é;ìZz©Üæùë6Ÿ•+ÌпZ›ÁZ]ˆ#t¨æ±rÛ$Ú1©¯ç+冽+‘ZI³µ­uMÇ 1¢ïøÜ¤æ³ZLzŒ+¥*´†þÒŸ'Ž!ˆ±2ÁdkjÛ)6€ŒêÔÛbÌœ2çÄø‚³¬ÕEIM9s2o Ô%Cþ}”vŸ4yugSS¨œ¦ÉÔ1Üò‰wÈ>2€0¼7„!mæYÁUÑð˜-*„çYözPU¶vgï)WR;¸à@Üu… âKÙ %e‘Ûš ©…3F63ÜH²ô^?va·:‹USÛpVºäÓZÓªt¡QbÛ Í¼Á”TEXé#P¹ªu¡ã­pž © Rd›g†N4>ÃÆÈR`ŠH8ÞVÔè×Z²Hb½’Ý)>/^µ}úÊbÖn€¾ZmÇt´ÍóʆËf¸õHŒäÜ…¶aóïAëXjþÿÀA¤Ï™°vÝŒ-Û­J:ÆÍt9ôĘ|2ÁøH÷Å‚ôvù*T) À€­òæÉÇú#êÙ m5êȤQùdkMß‹]™-TcÄØ6@÷Éœ³+/CVÖló$®IÌ!åbžp)âÈw-…‰l¼fÃt(ã2ë˜!Fí){Â$Q–ÀÖZ |`§ÎÊvµ²ž‚{!˜l­Ù¿ýç?ÿQñÏLFæHÛŒlÉÊZUzEFÜ¥¬¶ât» R–Xù²Óø§ ²”ÓÐ V­”eÍój"^#Ê4gŽÿžD6òzÞžf`"k]»W9ìRª*êçYG“x 0Z‰©ÓJtôBÐ`ˆ{GÛæYk¤H¶h€Ø*Rêż§†i6kY|‡µ*Dvu)adÓÆ™ ÆïD¶9Ï¡ðoÐà³M€!`Ë$#!1Å&0Ä™]¬y:{VL*‰ï¬«JLã…¥X%Û–8}…®×ÙnO,Hm  ¦ÈÎÞJ\Çø†OI`h4…™VO3YxÃg’C%KÄLDÝYÁ½‘uÃ>ªüᎣ„žLÀÖºÓÇ7§­&ÀyÃÉeM+RÖTŠÃå~riêB3ÏÆvº¦*EpË6±•mÎx€Àý¤\£zV ÿ£½tÉ YªÊo6þ4¶"« Ûª<†1 jñ49h¤¶ò0 öD~ÿýwÿ¼®ã#+Q+”l­P‰À§líNðÍé2c¬»p>uméªÞõY#Çw„w«\/ŒU(‰1ª-^t(ÛŽyÔ÷V+¡W(ÕZÕΟAšÞ.&²pb«­¯ŽóÝ.—»ÊpF»ze¼f¡cJ‚ ¤$S€OgX(WeÛ™c_=ñœ)ïägɰ?¨åiEŠlÍ@o‹Õz}õr6AP6™-’€¿Fx%¶™0o‹yÏΤ¾§Ùóé"÷⮣5€§©J0€WÜïÖF²}ïGI}ñ0}Ñ6±Uà r®j…²ñ“t®4ÀDâú@)ÿÊ,eØÚmב'½“*1?°’Y; Pã ”`l ¸îº°BÚÆûyYÇ~–`fÞ ×Q/ÛîPΖò:¯Ø æÕò"MÐ`4Lêkm6VxJ)Àl€r‚lm³tGJ‰nÃGyn¥j×ÊS \—”‘Vå3·íìHSåÜT)­óŒÏÖº¾€v<•ÃJZÓ[s@¾€X€‰€{Üðº4F »²fX¡m7„­],“Êé•·Q‚!;¿Š–ꞯÓéB#l­²ÆsiùP2¡©$«”Í  Þ6½ëbU¡Ö±5¾![iDUd4̼̓Z[cTõú¼˜€Ø$È· Rp°2·öXë^kk'ê…éÞÈ7%u÷ŒøûþiȺT8ŸºsˆQ¢–¦áCOüëÀ”²G¼³ÃÆcè#Ï– †^4I'µŠ†¯ã¶Èx-V΄[ÓîUØØÄR6€oà&TìºNïï7 eÝÚÕ/øˆ0°g `‰ P-2qÛ˜zÕN–9I 0÷ПŸëŸÆÑR§ÇTÏM¬Ÿb mþ˜@âÙö°\T¶uQ(h*±âµÎ–ƒm+v9Èâ+DR:Ž­r!‹L &€Eo»‘ðÔ9 Eb a…‘qDÿñduÆÀ´­+o¼Ä²ãxá,&Ô¶ÚÖ³-ež•Ïabvï0“öÚgnUâ~h}+·ä§¼µªdFšå5íJÙ2¡A2!д1`@Hå Um)xÇT óY¥ÌAO 0}Q„×4Okå>Èú¶"sî} {ƒ§l½*•À†yKþ'&[døÊfE÷¬͆ױ’Îe;CúŽL0AU¬:r²ñ™ïžLÙº»UäùÁàîäü<Ð²ÜÆ•Õ’„‘ôºRªx¹h >˜>`ËU%¼‘¶ªÊr#&˜Ìazš>ä4’BÂ@bzµBÖÊ™À‰š*eY¸ÚÓæûd˜S|O¤OV¶u$85ßoöôïRȆØ*4ŒI’يξ1~)'%];[Îé#‰1?†Œ!(k³ÖùÈö]ðÊÖŽ_j½ÜI£ÔbJ[-:µŽj׉I]?©Ä) l=âžÕ hÇß:åkU«Ð«?Ô©ªè…é1DMU ¼:•ÄÀøÞg¸“º´fëó‚ô`^y¤-Û÷ìômßT_Éô@W-Õxª„m}Û“‰é§ ë&emÙJ ¸v«²¶Y!,”ãm­R>ï•K™ÿJ΂ìËš>A—Z÷xžÖTÝYÕKJh±76YâB‰À#­Â6¬ÖÖÊ?k {glkW£H¶V© {ؾβ4‚F$ÞZÓôH†pYbÛ[ôYl #Ûʳ+êŒp]¬9ä¦8ÿÀÎB†ïsÔ§ƒ^¡pY)L²ÈúÂx“+—íÔHΑ€^9Sª¢Y‡ ¼ƒá hZæiæ³Â”V‘g¸• ’§Õƃ½'Ê;#ÐØ²‰6¿-€÷Íl¤úzu9Ð(h¸½¤FBŠ v&®ª,JûM+ ©,X£MUÊ8ý®O'â`à< ”Ëf»m€¦,@ÃßÖº[Bbd &¶kJ gN`Ô>€@J>°×À`™&RÕ*t·V2×èkγÖÖCЀF|œ#(^hmMЉzɉ߱aq+Îë·ˆiÍÓÊmþ”²ÖüÄY¥I&UÕkîPKÊ2ÆÚ­ÒÃ9ÿê¾`(¬ÝÌÉ0HéZ"»%äÄ«y–%Pn+òim€¬t×Ú£lKÀd…Èp%²¶áæ¯l|½l…lï Ÿ£lÛjeÅü¥ &VÀ§± ›¤û¤Ÿ37Ù †sæ°Œä€ñY€w¼1ÍC¤‘Ji+2!àc²ÄéÓ¼ú9j­û–(åsW•mŒmØCôô >_ô½.rºvøÚ·ÕµÆ>á* tR"›c·câLŒ³­¼i¬;ª xÆÀô͇éØÖz)© +¤Ö ÚÖ¥ZX¨jZ…0¦imp«,2>@̼àÙ0‰ 0°,¾Ž0° ¡‘²åcfb MwBiëÛ0CJ‘¡”Ù¶Ùæ†)2„‰+¶m* ì ÂÄÎKÆ–Ft3™ùK ·GÖ¡€u!Hl%Ãç6€ÇÔî2eE$&’lVž~)zÍR*ÜÕÑ VWøùÐRæ?gn§å½|sâÚ¶Êòäp%’¬ïD$ÿ.Á Waí~ò¹ôYèñ"&Ï&ÁÔ±T«”æ4Þæ©W¤†á•d‹ ̶֭+$ó4ç#µçÙ¡lcjJÐ ß„@$7÷C³,Æ– C#ë¤p>ÍÀÀz:ݳËRÒçbcK¥Y­RJIÿÓ.žšì-:A Ëg…o ÃPbt§o’»¢f+›+½È¤D)µ$ˆR²”È™µ¢¡Ì Àˆ ðc=¾ÿÕqÿ~©æl$gñ©QÛI•ÐT%EæCÈ:Úºù=‰Rª¾•`”¬|c(D–Ê„R¡•sÚ®®P˜Ø ñVaëb @Y#€Û&If› -+b…•DZmK±­£*ó$ðM˹46*ÜJ6ž+-ÜX¶²¶ ¹5+[¯&=±=Æ¡š°-†9ÜVaJ]€V‚ü¹‘ÙâEdV)κ§±Ò49¬ï-:& ÔÎÊyJBYw…²[󬪎d õ³#s¨j]’yµTeI©å€L?@H©íÿìÙ#Ó"ózÁmß‘0¶žçZ××ÊðV| 1#”[G Í“yü|é9Hï@n)çœ[Ý‘dѹvç­cÙ· žl¶¶4%dÍ&›ŸO+AŒ5ÐG@•-²z¹:)8æÊÿ´Â'–­;Ü«J 7ÞÊœXdR¶Éã­Hˆ´¥±n*åu9Ò"íf›P•·îý,Ïy 2g%ñ[ Ð 5ZS‚:VN££5Yå¶“a(­1­ÉàüÝaØ<1éëØŠiÚZótÒJ}­‚Fë˜Ò–ýù2ím¦cámpk¥­*EÙµúü”0(°öà{<ðz+V¤vMC©¯Ú›ÿ|ØÚZ§ae$ŒÂf ýsæÖAr€i¤,€˜¬jŠoëà@¡µl©dßÌ™Jè%0OÀQ­jR#ëŽW•@J„k×–€¡s»ªó^àëû𤡳‚3Œ±5¶r¤›4O|>ý\ÑB–2PJ;…p[kL½¬Bg!Ë9¦HQÕ<Ö.°-ÂÄë_þ‘r ¦ò UІCnÖL0ELkz9ôò¨mb…ÖÎË\‰” È z‚Ä1Ý ˜xµÓ`Ì œOå˜@c¬<™­®¼Ç ³WUßd³9¾Ãb€Yuk—ü—– 2ÃfFväRVÎî äÏS`TYY“¤'µèÕÂ+ R=n×ç£K%ùtLVæéÞ–þ `K&ESw@ù°]G<¬ R‰¦ÊÄVY|Œlb)µ²Ö€I’uÀH}ó )>VÊ|xÂMXá&Ç—Rât|*OÆ„CL)LOGÖð”¢I’ÙZ1¶ô¶‘U¤oMƒLé°ÊMe‹„ &y"Ãøx#ùý C“CSáe}Z{èÕbAÇZ[}&@ØO,[|ÊÓxO€ÊßÁ0ØSV®Vt:)€èDÝ'-ÞV°µ"1õõ&cœÅ–²¾ XÕ%@i;MzL¶)eÕÆ4ªmžÍcòhð¶V‘g8+«+2LìŒÌ ” ³5œ-@Ù£ñ8t•¤$ÃRôüÙâùãm‘U)äÖµ°õßûêÆˆ5’µeг‚3©èKLV•µR ½uaÃØ2€­À Lkíêe%c{%G37‡Rkl/2!nÚøjaYC:Æ»vJkA³^UY+l’ë([G¼î+ +ïD0sM)먶gj¤Ê1Uå`?s€ ¦4¶bâx«FÕæöjÂ[¥rëʺEú.^6ü«[};F@%kÐ _ Nf˧וUÙwmª>È”óÌa>n^ŠøíòöªìîÄ)OŒÖpšLj >¢­ óW˜†¹7iûÇøïéI_ëIûl×ÞZ'k.¬û{”.¢Ù ” ³†;mcÑHkz&Ä"es¯û ä€ÇÐà”"­‚ÆÙ¬4ºtl<ЫWn­ö”}9 FI3§o›ÙWIŒMØØª0h00}·‡y=•+Ü0²‚ÈZäæ%ã䃯„~A)jiÛ…ØŽÏ#›Œ› ”B€TµðL’Iõ2áÍS¨Ä¶r[ú­sS ÎÁÑ<‚˜¡×r²fs ÍcíJÉ8˜‡†C%²¦çVGL>ôjMBŸŒ²ZÛÀô<Ǫ˜haëAô¥ H‰”ÍÏGðG×7Ó¶ÓÁ…l]æ`ÎMÞ¨0åJ¾ÕŸÿl†š’©5ƒ5s¢H€¹Ø¹¼3ÏŽƒi<%ÌÇ%Àn†&“úº;—áÛŸ>’O%”½Þ ý¦HÐÿ1™TšÄ­H€Ì£WXw[J à½?ª <½U£lU [½¤9p3ç&e1€ˆ·ÕHØ"mùÓWS6½Ž²F­ ¾*æ²Jj—u½ ,èÉja•ZPâëb+Õ¯ÚÌ«J‰§!®Äê¥Èzð5²„›üüꯄ¹É{ ªx¾V·îSËP9¯ÖUØÖ®¾p•XU[?}TuÌæ'ÈÈ\íœl¥tQâ€ñ`¤xŸiúf[ÍFf¥´½Eçº8˜Ävúfˆ‘r3ôe'ʇŒ›Ê¿alÉDYs¦·EÖŽi~¤·Úê)[kdBæ™1 ªÅت’ñÇh”¸B‚‚i†4V†§Í [å=ú^¹dô =»>ÑÅÓÔ1 ž¸!3´•Ò!AWÑœ­ejMV‰*#+ê¸u§(ÕVájrŽ19+š‰ñ™[ïœ /;FU²Õú°ä#«¤B&•o]‹4d9V·­F`¬”båᶉ9Pâ‰c†WˆÏŸfM¬¼*‚¢îpúœK½¶ø·ÐöÕÀ¿"•ä_6Ãjµ#h* à¶Ó—J¶’¤}@dEz{—2´Ê¦o5LÏ´O½Âj­‰éÝ\£Ê×Ô¶ëMPU´*·SÍJYãY)Q+›­»ËHfK\6+<£0r@‰ÈЊ!(╈•ÃdµFTkuÈ4§mØô"s¼›‘bعú:“E J)[c¸îm¥0¾ÁSHišRß`9ãµóPê  Yn”«PÒ ÂÖÚÉòH«Â¨»#Rø}3X‰ç W Ϫ÷'ñÊs Ž&h¶R0!èn ðeá†$ÈÙi¬ ãx+²!kA/Â[cÈ2o0¸ñLEÀ¼n9PÎÊT™ R áx¶de­†­¶ë%Ƥ„ëÒÝLµR"žÞ•rÃÔš’ƒ­ŸºøaO V*F^ؾޖFö4»í`×B© †ùËJ 8 6,õú0ìb*7ɱþ~#·e.(4Cæ01ÃÆ€ã1°*+ØœØãÁô¦à`+¤¬Mˆ´5L%ï¹ÚÒÓd0@vÍ>_ßÈl‘²¢,^‰ÆÊÐñ]µ•@j÷`KLà\™Ô¨-= i¡Ê–§?àÕ_£z!S6‰µÀgîõB&ë\‘sgA6¤•Ø–XI[[8‡«,™°å&[_ëæ Œ²õÆúý¬sÏG£Ú ­dj Ý)›¤Ù”—RKÜû/%`âþäRdM.•m¤µÐ7@wÒaMem»%nÌڮܦá1@VRj'Ø›©œ²,FI7Óàm‘îY–Øv%ÍÓÖZ¨U(øï¤¥pHPS[¼È¡ë‚QÕäoI¶†$jUåOÜ“Úü½0dÜ(ùH0²{Æp¨£U¤Ì–‰ZØ«JV[U?ÞØªÖ.O2åpóØ¢ÂY»Fé(Œo›¹S(¶ÖômdÎFu o/Vó/››¬­B+†ÆÑ*TU YÉDÀ™ÐÃD×"…·fì{X&ɤvdYY‰õíX€T'•꣧)(„É›˜?\#Sõám<«T¶ùзՑ'Ÿ [‰‘õUKÙ¥Å[™ +œ¡Ža« ëtVåÄHØ ÿ9JY…Öªt·ÆøþÏÖê°¹¥Œé†+Ä£`B#ÕðV8X—RVŸ¾òÚQ®o²+?o…Û°6Ælé‘ñHb¶+II@Ž[»šÊÎx%™çi­cCºlSfB³;!Ê4­9çf»çg\IÝç  EæVíDÀZ#+±!{(Ú YAŒ_Iü±¸&œ^ùy"+Lï*†Æ`.:OÁg’mX‰m¸a¬Üˆ¥¦©#eÎUM¤œ¨5ÌV­U­øü‚¥S T:û¼QëWKÙdÈþò0I¼NxÌfŠÇ(}5¸¸î.Û¬6FL[|[+Ïœa¼ ÁteùÃÈ”R†!¬°”ÖV‘C†¶xߪÆÃ”M©Šg3²%ƨu{ÄH©&\—r¿Bq¦‘•ÂÏ£¼UJ„Ué.lé»®ÎÒ ЄdÄsnÎÌñœ›¡å U‰œ‘ô¶€Å›a[Xa M&ÀúžÊ;3F/«`[­Õv­ XaƧlkuieã­jùKÁÆØ¢•^”§ߩ `Á™ÆÏOç]gz©FbBŒéÈnCá1Rp}SÊÖ—>¥5ebk€è*ÂH 2© µr˜2¬87Ik3T…¡´"ç`«‘ª–!Æ[À·ý±Ê–ÚÊnkþp ‘›’s˜û”x½T5¶Šëôùf Cò‰l’j1Ä]Rk&ÈÛi”Hek°ÜjDfb"gÒ¶^LÐ;Æ¿.}ð™w‰Œ‰ÉÖV„ Ò(4 ™T+IFƊɨ¢/ÅœÀj+êd×7Y$Üvåôëæÿs*Md‚Æ£ñ’HÁ"M“dØ1O¿çÉRV’[§ë#X¥:/p‹>sJ1Äp бòl=£ÊÛžÉî÷Œ’pþðëF—– B;&NÇüó;qM+( 2JR&ÜUaX#…BkbU°õ}–CPô™ü!³­ Íja¹Õqgnl²f°ŒaE’Á>ƾÄ}§WÞédxYU°PhÛYDS½µ‘Lˆµp4«Ÿy4¢ e±²mªëwºãEWqÛžÓÕ]¹èç·ø:V•p¦âÕ–"ž&²7•›áQ—®¨¤Õ¶.=5Øaa êÅ\°²UÂyà 1›œŒsY+ÌÊÚHd]ÙëÌA4*žL•𼦜^–²ïq$úç Я)d¶‚€Ò< ÈIŸ œR‰îþÏ5éKu|kĶŽä“3’CØj+Å <}?SL”’m­Ue•¬ImÒ'°ÖÍce"òôÔ²µu?d ó¼E¿ž/*åz©â¬°aœB  H‰étõÊí]7*€o0€gæ[˜óRÖÆàßatªªµlå 8(„½$”ðô^¨ Ϲ¤ø³2†Ìl s“ d¥¶;ééphYÊæIÖEáÅ:ô‚_kXH½“Àm;²¬¾¯sÌ— ¸Y‰ë•=çÎX +ÛfèB(mÕ¾…Üúæ´½ýú1Á6’L Œ¨/½òΑD¯Ø`2©:]B[‚7¾M`ËÊEѲ¶wÀs^Ue‘¾‚`¤µ§T¸à 0rnL¤ZÕÆÓ¬5rdÙú¯’@Ћúz‹0Ì•xÖÜ`kÃHÁY…¹r¸N纔‹¶}ôÈÒà™<ÆÊDÀ`(¦¦”° ±ÒÐwb–Âoy[åÝÒŒ/Ås&|àÆÃ÷©?mî§Ìé€Í™’®E!\À”F²­ &2FŠOVp§#xg«—,’rnp2‚µøâ[c¬SÀ [1ÎÕ$˜õ¤L…i`¨í kýn‰Ñ=”µÅÃzu7–)*lN…e›!7kÁŸyµ˜AþsØ»'ż*Û:få*3q34anéÕVB¬\Gšµ+e2©.-qóÐô:Á²ãi¤jd­ÐêÞêËP ™¨i[XŠ&¥,P9RVØÆÔt‘ÖÆ¦üüÍýirC®öyáXÐEêä0nÍ–qÙýÎ4kJUý,i Ýuζٺ»Ü²…5Unåv‡:KƒU«P`F&¨jOb“÷äˆÍìý&£Ñîœóô‘d"O«^adØJ,òlÛ0éS&Ð ©¯[¢é˜‰É À€ë}[ÄoÔ4d44ÂÖ)tö80݆.R)«ªÓ¥Ùê’I+Þ_Ðw J@4CY-`âŽi[I½¬1å²9À 5•ÂpH9g)à•”%›?p¦¹?08˜ÈæAvv[¶@+>[áä®:¸›G YR\X¹.V¡Q€ s£\ÊÚÿý0’¹-‡‚P2+Abâ­ ¡Z2|²¢ H¥oå#¤ô­ÁÇ÷û?˜ý"BŒN£*[Œñfˆ_z§nà°.¾ÎÿæÀ0 àÑãnJXu 0>þÑã,”ú*ɰ¦FF¢¶V2ŒcjÍ\m¶°ª ŒµZe1"™TL]–B2Õ*ÔŽ†#*·ݘ•Òqü~FìBbøªêr ~}TmUIÕE‹dœ›Syƒò!. „­j݉U´µN°Ö²0‡eµkZ@ /«xâ€xwò0Yþ@&€Xw ˆ„uQB,˜ŒO¹bG³%#¾EgÔªd1‹ 6azU͆ÏÇú¶ƒ· ¿Ûj1µñ¬ €éC‡¡±5! v9ô@côª›­FÝpΕñÈÁÆÇT^‹²üÜåÐç‰lÚ‚†©6[k`†yŽÌÙŠÑšìÜ0FJ_Î¥”éd"¾yðm+IÌ2Ò*j±P­”ª?‡¬Àw sÈÇv3ÀÜD¤O«”ƒˆÊ­UYS¬ rHvÎö=^àUYÍ£DÖHø>)0R¯ÜdïÏÒÙZ² ­ …Bø„ƒF ïë±v‘ýh“¨RûâFâ Õäi`Al•5 ¥h0¸Âßþõ¯‘ ‰Æ WXUV|ëNa²V$w%6®”mU>r€-%ì䔉wÑR¢Â²dª0 i+”';Ó#±Ëm$@‚4ƒZ`µðd•«‚ÉòÞ–É\¬]¼FxšÌ;£ÇL™ÐTÛÖË=ªø¨’5µ#ç“ùšW’ s[-º(e)sH?`#W’ ¾P3ÙîIF`ÍV»Æî5N ‹dU ¤-LSÑØ €ÀäBIΕÔHa-æ9ÛʽÛôM4Ø4uÄoÂÌSZŸnÌšÁ»™w*$=«ºô,ˆ_M×WJIz¸mæ‘g‚ç3똶R”ç‚nh±Ð½éfèes†ûé5)ídkgÍ¿*[‚|2«0zY‰ñLò ÈôòàlµÀg¨dMËb [“×xZE «»T3ئgÈxUk`>¶ÍÓñ±}qz ^¡´¸³|Þ ÛÆ $ƒUY«^`DL8+r+¥-[÷fåf¥ï5nÛðót0­¶›§ëòŸ¸èA4™¨ªµ“"'ÈÍŠ±êb «Á|.6ÆôQвieoÏs}–ëK&•#òÁD¾#…¬z­J­m†HX;+«ºÇ¸“à M%ʉ_Ï×jYpÛÖ•Ôô&?§ž &ŒÐј@+>¥myVˆ¬°l)XÇïäežÈk•˜¡µnøîC3óãûu>5ß#Õ b¼•C tÃYÝÒÏ÷yúæ,kåÓlpïp%|l{aÑœõµUEIàÛfc½UÐÀ?:Ú2d’!€IŸy¸‘*' Oc†&l½I|•{ñ8c8 Ums€RÍ- (—Ь¯-œ¬É}{Cßó€F±5q"ÃE¶•-4™JñÅÛMÿc&ÊŽZ•-0~¶ ño÷ÛóógVsoÚj[•žÄ›™•£"­î×JCoHÛæ´•õC}oFç˜Þåœe¹I©J S;[ÎkM&”Ç«¥'‹W(ÚtF ÇãØ)俯 R Cy½Ïôa`%¶ÄÕ”MXÇ«-C²Í +LO [ÃãòŒþý[̓¯©ì"²S3¡Ä4Æ{uÓ#aJÀÊЪD¤oxXÔΊÉèáR[‘¿- Û<YÛôW{ĵ³dÝ ’Fd"ÅçÕKÕ¥ò<› .lYU8±BY¶"‚È4pÛ4Öº×Hª.¶€Cô(mÓXÉÂz)÷‹n•CžõÂÖ|à"F-^pÆ/F7–F;2¤s¯ªònö[½ó« “e¥D½¬ ií³Éy&¸iLcتÕ×)Èr¤¬Èu÷YÈ<ÿÍÀ2‡<û'fÓ{^¼Q•70=8çÊáJÚº¢*!¨E£Ú6ddšœ¥ ŒU™–!Ü©p+Ñu™ ôsYªWh­1ÃRakµÖÛü,‘óÔn$¬Á˜Ø ³åmá É~²Ä‘ÉÞdjHŒ¡Q"bl«M 8™™EJ¼*1œckU4H2ÌjóOÙŠ‰T…qù ]ŽZGŽÌ°µK›CdÅ*˜(·] BÙÓòŽÝä<³%Ž¡© …JÅ+T!æföÎà‰Àô埭)”Àªf³²leiXÙŠjåR¶jdÍ(;Íoüñ‡œbsä‘»6beyIe¡^.ll¥T%ëÓžUçCž˜@dUª­ ’R> Ép#ms€k Í` 4ZIa„FWx†‡e]¥@ož†aB©»m ñBy€†RdÎ-g Bëø0—ÖhT@L¯P÷.&3¡UŠ óÄ•Ké+Û —Ìl‚LV yn<)žk]¹mÁVwš¬›ÆÛ¾)šM•-Ì–Þl›!Œ¤¤1 xVâEÍŸ¦nÂV²ÖªT¥GjT–°å_-e]€È)»gÙÌ«¥!h€Ö rÈDIaŒ€l…›Ö6Æš ±¬¾‰ËÚ3iZGhJUHˆÄªòda³õ½àA#yÆOY_z1Ö²mùdÜšÓpY|Zª÷ ¨*­Ù¯„¿,)×—®„y<™X-e%H}»Æ+9ÕԨ{ƒ¥TebKct˜Ž€¯€ó¾s3_(”H5¤µgä–f…˜ü­º'0 FÐ[c¶ÖÈV$èn;åB¿yªªc_Ëš@#UJ„ÞHH†iðÞ+b¡Ý¾.Èà~ÐKqPØu¬ò¬)½È¶¦¶üé‘¢øÔKÕ­8· ».€xž)Qɸr…úÒ·…¥ ò‰1Rb<ƒ)©¾òÓì^&FÀj%mû¿A“W cNïÛÅŠÝC)˜-ÒZ xwžRª;lNÛ7ŒP!hû2§åõo•R²Jš°äiM 0¨‘‘§‘u¢­akURá¶i¬Râj?2>^ OÇô#ު괹ˆU¹±Ì¥8gÛÑd…*+qï­uÀ–C¶È3Ä÷b‘pJÀV‹º#Ï«y¿´añ¶¯9¦ ±{;mn£JÂô”­†*†È'løÆl…Âd5ĈŒéöª²¾%ù0ïéa«›´ö8Œg»ªdÌû†±ÝTÍÓÌɘl ø¼š÷>eÅ<9TÛphìñ—¦[YÁDp —}•²Ä«°5Cb|%Z•3i%úöÉ%(i œö7jŽ' bζxXt"“üö÷¿ÿÝ^b=‘R¨é$¨•x˜òøÝˆä#`åNX'>ÈßY¬R˜"C2M¹õmÀ­çE“[>jõ¢iBëüñÊ›D•gÁŠÞ1eã1"[@V¹é W˜a¼Z梻š†’eA 7€¬*|% ÜZmSÑ¿&³M˜L”«"Ó¨-~‘ª¤GÐy1z°P’ç:"[8A…Y/¶p“"A…áÊa± ˜‡jñ€m‡òƒ>€”‚ ¦ªŽÏŽ)æ©c†ô°ìÍ÷£‡žÛœmÉ`…@VªÄ•|þð\‚lu'¨|ÔâÚ|^0ÌÈ~[È_ß­˜ “[µ€’·/Æã°6¤›QÂÓ $Z&¶²µs Xd[‹RÍ€§©Š¥5C)‘mN«@bv –,g²ªbÒÔ¨>s…[+-rïsz<2 &«ZPJõ`’QÒgI†çߪ.0ݘ&Äx«ÚÜjg4ÄV©70|04@øÏ²•ÔQ;š†ÁèX 2¼ç+•¡­©¬½ È¢QaÀªpÝY V݆-5½ÂN¬ÝçÏX“N™œUøWPú ¿føæÈ·ÆH ÌÈdgÖ~ß_‘¿ÿþ» ‘3½öíüï]3ì 9¯W-le;¦à)E¤¦U±ÕÈ**hˆ›Ðêà¶ô¾úL¤l×¥B2QS+LàÞTmxÀ¥aœtbŒH0díÒð·e¥¼¸çͰ݉)Ä•Ò(iERÒØ¶bdu)w^2¸³ìì¦Ïxç¡Ü¶7dGض©b”ØpLÈgów- VÓÆHwŠÜš /ðõrŸ²m벎Uå™Ç©ÐT½EHÁÓVkóXm‘ªÈÊvŠÜj„Ä(¥°¾VNД=eß/DMžÆ#&–ª;C)|¯iVµ+E¦JÇR™ÃÕâ VÕq¤l$ÙEU¶RY¹ä¦jM [ói;+äx)ÎVQߎÐ8:ÚZMní?ÒÑïöd¹Uµñ(…­µ#p³…‚¸™Õö5%5²Á¬°^Ëó”U €çxJAƒ™9AÝ‘‚  Wb++@•ÊÀ;/À+Á‡3lÕŽƒ¿/èö”·è˜Û60Œ‡3±e.k[(AÂdÚ¹¢D]ðpΉ­‰­5êõóTÏ'ÀS`´9׈^ì7ÑTÓØ"k÷6½ÚÏ'Fpkí(«jcð‡ÙŠz™³KÆWn~…H)€Œçš*ŒŒÉdŒmΕ´m˜3ÞHV‘ƒ9E­iô²d¶Eþ•`NñýkÇ'¨¯ÕÊmZ_B‡J‰<>º§'¨Ö¶.¶×UP"¥@nHÙªr† ~LURÄ>?‡Â­RB¹ÙÖñok†¢¬uÎ4Üè­ó±% /Õ-Ù6m&R¯aM#yºZðd÷ÄmgˆÏVGåùX™ô],E#dE3D6d)åJjD£¯çØ[JlK&«¤*ø˜Þ?ËY‘2µ°½¬pŒ¬Àú¶i0¶ÔÌM˜ÀH3±UÕý4píòœyóÔ¸ù{wQ óÌtðlnµ h°d‘ÄP§m†°ª éš“ ïh•ÀA†i퀶¢l£Z1•S’ÉÆÀG}³É [®al5̓À[ñ€¸ÕŸï Ê3¬5q%|l<²¶ºKíË~Ÿ#Cšzá‰+$ëÏ  ¬]÷âeR!Ü´[)«TÙJ¤¸ V‹Œi$+FSO èmi溼CŽÏ¿KC2´Úêî€~gèNl‹¸àè~l…B ,ÛA"ÙþøÁ­¬U* ¬ÐÖœ†zådgõ>J¤Tc’Õ:O+ì>iVÒEmrâ¾mtoB)ú|*|×¹QÂªÊÆç<ÜÖêJwôo•lÛªô%0ƒ­³G¤É0 Ù[b‹ÏÍñ{miDVxÌ.9OÛ.™¬T¼S ,ºU]Žã÷_øì­³%h0-²²-2¡1,ðô×Öü@LUô¶ ;r˜lLµ-Œ¤;¦¬­yl‰ ˜²—S‹>ÅJ‚5¨m]È„m·z&ûŽ ð±vºó€\|®¼å]b ‘zL³Ú6– |ÁN4wî¶].£÷‡xY®¶ù²‚ýÂÝg¬Á3I‰rÖyÂYÛÒ›LÀµå,äN$KœölÒw(çokLà a«ªdj!ˆE†.Ayc`da !U 8±*Y%g²ï¬ ȳŽô4•äcÅÄL””òœÝÖ¯˜ ¬ÂC×…²CÇ#1 )Û<9ˆ4²À;ƒr³5ñ0™BübXUkm~)¸*Œ³7ÒjeáZ(‡;ìÊõEæÓ7Up¶°P•‰µãBªÚú¶ÅÛâUís~åŸ×ã8ÞºëEïÔm«ÍHåÀV„e;]#uÉRR¶ekg%ÇNo•*;}ÛKP#Xð'¨¾k<ÃÝñ­d:Ò¨jŒ¨Ql¤Z_À¢ò&Ìœ˜ùf¶¥O™¡^·ô|ÉHQùs•à÷Èæ92Ùºd^S˜g&NA $RÉüÑôÿþïÿjÉ_¶ƒsÎG HeÈ? ¤ãØÂvíyªÅckâ0A<`-˜×ÑöJÎ}v¢˜0²îUÍ)lÉÌ,ú›¾l‰ëNc$&}>ô€òãr}ÉJ5ráU¬°•˜ÃzUk•U%Õ‰\”ÚÈ&wcH„•x Ìʪà@…Ûk`Ø"ÿl À i‹¯ÄoŤ—ÁÌÆ°Úæ32)@Ö*ÒØÆ”ÅÛJ±u"]j4 Û»JO†¯£9•¸ &+ e<ŒY÷3Ç‘)›|#©bÞUäF_6ÿRœò¡i@Šg]€—ç™ Ùô®±”߈œÈ–ma+“ù ×Ã-Ã:ZsFNéhHqµg9lùÛ²ÙéýÑy‰ó¯ç¬Ùxô¶ây6 @˜DضFZ鑪òô½Û¿ýãÿ@i&$µÂj€FggëŠaëô@zYa,Û daÁ°B†‚Û¬;ìuQBP À I&"ñ¥¬QʰI.÷ùšs÷Ŷ¿Špþh•Rk……Bž”§ÁЛienÚd­—˜C[©JðÌá¤^0Ù&Ò¨ µÐ«Áà_I£Òcx²"n$@”8×ȪŠ^¤¯) ¾BÊÖ¬½h€x3Ì–¦­Z˜F6}À*ð5j«0C%õÂ4O<½ VUtäY!ÃôbCÂÆ°Á<2æ=h2¥¼lRÐKŠ>ðö ã•ð©)‡¦Å ¶œ­4˜ÜVËy%pA,ˆóDªb•2^ª¦ë[/ÙþINílUÑ0 TþétÿG/-˜(Ü‘]Wµs ÏÐv…µc˜+qsƒL¹‹e àdù¨‚­0·L¤˜`ªõ˜”Û6@Mc¬B•ˆ'ÃÔBy$Ù«EÓ—8ç1ù[çŸg“ ¥ø˜Õ¶Èx+RIM•râpÛpþÂ&Ñ+ÀƒñH%V·ÇßÚTåúîfàÌÊÚHŒÈGUsZ‘4z¹“12¡™zÝeÉl -Œt±¥´Ö´ÁX5X«l7¼¨©róL€¬/>M­m¶Ä@²­JI²”Ó×kb2Ãð¬ÃMBÿ¦0JYížVã5î4H%uÇ»«;§¬6s$Y+àYßçbÕV˜?&R9¥0*œ¬,=`Á§©hò¤¬0Ü$ÙÊ Œ­u€ŒÀÀ²Êù'.>õÿûâÉFæÇôF™ÊËÀ I$þ1OµÄ FœÞVT’³m§¶½És¶*̲4}IJ0`$|ÃØîÓçÙ5­ßÍß…P*ô eà s~[÷h( )VœUæTµÆ+É€§vÓJXYEí‚R„­4³Ol²i*´Ž/ÕÖÚ-éOÙ{ˆ¶Rü)g K9K—à•P:—[ð0TU0Ðð²dWÁM(´bÜ`47yx%j›ÁVSÛKˆl §È6†Y† &%¤Š&‘%# Äð·âb¤h$ʲô¹QÂdR^3“CbTuÃJ$MØ" ò EæøR•˜ ¶ÒH9#óßþú׿öªe¡, Ïè`RWu–zŒ±5‡“Hhl«í¨Æ‚é‘pãbeÃRH©VÌÐ×0ŽI@¬mM›°TìñRJ+Ï­dk‡ìiå9™y£¾ñJèã­œ;Ëœã»"dm‰‹¬*i†²ÃyúUµ—F#LdM;x¶ªŠÀ^z2Ý» SS€OUª•%2O™¾F9HekNz)½˜È*´ÚÒR°Õ¶Ð¨Ð*ÅÓÇèdaôÔ´Hߨ1^èR_&5¥©¶òFꈩ„¾’”•`ˆ»<Àû6à8#g>RI¶²º0¬Vw €$+k¥¬Ò(Gö(uǤ±*l¥—å)hÔæiÅpP%jgb%jÙ|Ã¥´ÆSZ1¼?öä–?7ÓU¹†Ýû½´¦”Ê;WÊÜ&& LL`Ëáë}þsþÀ .4E«m¾Cc1¬#ô¦ª%°Ýñh²:mï}YOûûû‡Ûlh¤Õ)‘ª8H÷¢õ"°Ž½£g›mµ&ÇHé‚Ù ¡V/«aʪ*lëI0A†Óg¨8£ÜΖm–RÕvµ1¶•ƒñ1­*½¤˜¢îRÄÜJUÖ é{¬WÄ&ÛfP4‰”ZÏ¢ÿl‘*[< œ9¥`· »|[í0ñÇY [bn|rp–‚E+‡[ýù fÛ„¥¦xöÑ­Q݉9×Îl}eûý£ì|ja»i "{yŒ×¨iz@†³p49Øv"Û†ÁP UH¡ ‰Ã²¦—mòdYшz5‰¬ªx@TÌ Så6ÜL“#…BÛÄo;©¶Wu–c}Ymëh…™ >Ì×n…9ȶÚÂR»L¼«b{\¾_J˜s³?˜»„îÊdôk©„y©ÜT)A6Ææ—m`bä®è4~>>‰˜Œuþ@g™ÌV¸v_ë|j§¶ò&é&k¤d0&=†sÌ •}—©ž¬Ègb&JDµ40ª¤êbý4þfiˆ­ø4‰#{.Fâæ¡XÉŒŽ0Ê&ǸÛ¹5Yå¶ Yy2+¾Ž²9`¬.Aó”*˶ó6 ™ H+Ùa÷]G,h„¦]Å­;UIá1ž…ï(Ð6žÀ– 4IkãµÒÔˆ­¯#1*Ç›G¡vç÷6òÁ3ç#TY0ØzÎs Ñ$KY%%‚ÉÜú£œCV²°µÂ”Æ6jåÉâÓϰu  *Û 0Z8þl_ÏH ¡ãJlᮽÛ3›ç›UbO­‡E/VNI ¶ÁZ¹ÑäÏÄâ[R5%#PnÛ& ¥­Qñ‚Xغ4¼™Ã¬ˆ ²‡…'ª`%¢ylŲM%™`š¶u7' +dè!ú­Ôœ²žEb<‘›­“v-ý:Æ +F‹·ɳl²yÚÂÄ"ÒŠl¶¾KÕ.[¹#cà®NI¿yÒ@/ sbÑüÍ`ëÈÙrˆd¢©à\*“Z°RUw-à”úZ+ÇËr£'¨—•[ÛUaÈ U‰ Xñ&! Ì£% ðÛ_þòŠƒnT&çxjªÏš 2 |ì¿ghˆ¬h¼¬…ÍŠwBXʪ½€}̸UËŠžíœ14jXmOËûÈM(ØÚŽg.8”Ëjzj¥úuÞÖÊÖJm+¦Q‰É²Í¡b²UBi@6XJUµè¼n¬ª.Ê Ì)Á0rQwk_•X‰…ÓIÙZ5XU+‹ÛÄ4 (‘•7’^4{^o ÞÀ4âŽök6žãu$¶mHÃx» zq†»O¤mg‡éa&Äæéê(‘uÁ3Ï¿µ*b…ªÌLæh„ŒæÐ­žÞ7¤”€²RM˜mJ}kmÅðá¯DÔ¨î¶ÌaAɰim¥##…ì 0ž@†Œç }˜À`p>0½,Y&˜ô-Ú’‰ ó”ú|•¥Tb•ĦÓ6ƶÙJi*L"Ëʉ69%ž-ÁJ0øYen¥a((O¥ÚVUÈ|hè¯ê³ÔéP £JL)ÅÐJY$kŒ˜üÓÈÊ¥VUwL³9l…dBëNÚÛ¨Ša&º[µ–…‘‹M2†³ü›–¿l'×À˪%n]¹ldíZiHm+d…ÙI'Àˆ²ùÈx«ƒX…·‹Œ¦÷Íñ…á™{`¿‡ÁB¡*€sÄX›!^JÀü»yþõ-E/0:^ã9².V)âdÖ ñª`Y@‹ô¶4u׫g'%ÈD eQyš˜pþÖ[zº4¿ãôW‰ž©ë’U•!q—Ù–À M…áàÒX«Bæo¥·R ÙZ+/ö*VK ˆÄ¹Á;œFÓ&ÇÀÜl«zõuĈ¹q€}Tw™É¬±Â÷ÂÃ¥Œ´Ùàx)¤P•,,Kc*ÑYи΂¯ÜJßYš's2Á@6¬Šæ´ü¾üÎ%‹H[Àó2GÎóVœ»åðÁ0€Oo5€µŽ•+LF?œ±Cé˜3™’‰_=R ñ4påªlM’ b¸î”ŽPÖŠì){W1Àh›aÓ¦'n˜ÎËÞîGë(¡€ñ#iÔîs$k+d 2_ðÉÝa3¼)‚Æ@j”1`$¬œs6ÞK^ª™ùÐ[úÊmáœ;Àû’„ ­«¦Íç·ÿüç?¤ëêÕ¨'Òj¬]Ù¾”¿†ŸÏR=˜RJõ9Œ´rp®8snÄdÍA#`YbÀ°6† s®<Œ¤$;¸ØV “3ÐÖš`âw‹tjã’¿õØ}¿1 „s3Øü¥êè¾cVΰ3v¢¥ê.eµuG¶™0W҉”5?ßjÊWƒác%PârtÇ2¤UÖ%ôñÃä_IVB [I3X³’Ê0^¯E&¹ÕÈVPÎG_ÛzÁb…•˜_ÀR¬uäŸmÎN×Ý*ñ#Žl͟˱HµiJÆÖ*cí”K±¢„eÕ؉F 1¦i$M]ÂV©€R4•³R; Ì“¬, Ô ¼ÃÕb’mþd^;A/•˜I[óµ¢l«-Mï+É–R+eÛ„€­”•x^mȺKaÜíô¶‚¹¿Åá©<“ø­g‚ïO¦d>q²°BåœÃY0Ñ])Eo¼lm iÝvµÄHošr¤òÉØÂ˜¾è9ÀëkÈÆà€·¥_ÉŽ,êNƒé­30[[t×®…®ãWUCÚÂEU”/4BR&6-†HCß *žÆ1«F"@òÉ )ˆ™”÷Š&Ïcw'‘”4¤UU)kåZ(@¥Òb-`‚ªj«J¬‹,Ì ßÚC„óÁßÁÏ .¿˜Içri–—rí€Mll%¡‘­à™?Ì¡}¶k‘3’X–Õð‚ƒ¨@)ÈXÙªê{tßÏ)–•`[kg äh„±ÕzÊ@z¶4ÙÂÕzú@÷Ÿa[2³ÅŸQ¾]VŒvu€Tº±Æ3R­e“ÍáØýoPFèNìÉŒg+/+J¡¶{j*+C_ ¦0ž¬áã—¸%€}î|íÌBjËAw«¬`.:Z¸¹µš™L/+né§Üÿ4A©æÇd•à–~¾%L¥ÙÍCŸX X£ù0Á7çæéŒ4UëùW€P>‹®ž ¦ a%–mn‚ìí‡7º•’s>”Ý/ +¸5Öjõª£¬*|Œ€›,V+rnÍ0+8µ‹”+ÇóôžŸñ0Þ?ï(˜¾Ͱ]áÍœ_Ö& 9GÆ ôɱEæÏȹùÙêHЪ¤Z­EèjÂZãU!múxb¤I´ÈÀÐÛö=¦ßi-úµ¶H†ôÄa%|:{¤lóä6%³BCJÙª2§•ÆŠ/k-È"1égUS¼9Kµ6'Ò:—ûÑ•â cl9×ך€X¡­¨£.#ç_ëyâéý‡>\±¬.VÄx‘¨iŒm}Ž:iŸzÊdgØH¶fÎX‹RpW”Cåç0÷YÛRv!^0%Z÷©LÙ;ƒ!뫃@-U¢°¾¹ák­¶â…*[Àä›°•º’_/L“ Š6CÓ"e™çOŸ «m×w÷“)h Ï$¦0RI2 ûÔ±ÁdÙÒWhß6g¤ùÇôrŒ[Xß”Ù÷•¢Pª/œ.¼ÇA`°FRRU“„ewcúÏÖÛ%«ªBz¼X!˜,Ò–•Õ˜j1B!~‘Þú^QçB¾²&¬|U«Z6…N‘ÀeÕ*^Ï ³jlzšªÖÅ+/U “B Yµ­HLš|0¶HQ‰_RÃëEØ*…聾10&^#L÷\U…œ»R[‘@ `0Y]‹*¸#à ëeE¦T"[}kmµÍ¹”­^­õZ¹ªi´#³ê… §ÏÉî¤Ý$}%; ”B‰ÀÀFró)ð“Ñ/â>}©b«éõ8%˜jéó´ÂRÓÌ3M…1ô¢ ܇ FkÕn>Ì…mLÛ” óïãéÞ„”ˆ·f«\¶3"y¸ ØjN×B¿–g™LI[å׊L!V52dÙjÏú·¿ýMÎ4)ò²6ÄN¥Œº‡G)‹©¤®¥`µM,ðÊñ‰ÒkŠéýÃôÒc„B%µ°*ÄX…l|þð¶4°ñÈ”'&›'fb¥¼‚»e©°륤4sÙŽÐ}á®`"zÆR@~… £Š^¯¦¥ÇËêð9hjÛqƒ’9˜Pk)<,:V¯ƶ ¥úáDü>ÓÌùóáIœsžx¬ŠX(7@a ÐÞŠÏ—c¯\¤A*”‰Ç‘-2qV²©b(1BêµjK4§ÕüÖZà…ÂÝ 0’¦À˜„L#µ¢ª¤”Û2ßqøŠaÝÑJ)ÑHTëÑñl›Ž¢rJd|ãñ'nŒæÉ^H!­»Ï7›ƒl­0C±F4ƒ¾)¶V©Ö«:K…é8åŽö¶ÐïU¤Y‰DÓüw¨³älÕËut"2´õ•’¬‘*l0†ÄÎÒ[=7åj1 ÷°V®ªI¤æ3T%Û`•'ÈV ÏP%dÕö!¢¯µ#Ðà14ÕRÚÆÝê3ªà&kTUnƒR  ¤“zý:{Ýù«ª5 V(É #nÃsÛ|¤€4É”côRK“LðjàÝ€¬Ö"C«=ÍîŸCd7¦v@ÎUå‰ÈЖ gX÷ùà‘˜ø.NCš™ EGP zeE,ÒäÙ¡šÍØžiÃ+—‚{(~(Ø*aHc›BAlKIà¢hˆu¤Ý?¾TÙiå|êB\ Û>,Äô·ó¯»5ª”¾ª [½RVƒ´%³–µfþúÏ!q—™¸ZL'BfÀwÙ"×kžHY[¡ÆñÈÂV,TÒ1¥È´.M*q@ Pâ¹Xmݧ !®ÐšIâ¶Ä Ã1•Lï¼RÄÖž;^yöÁAê’§Ïx@ ²•mÚÂEcЈNWá”ÄpASµ&™×ãô¯c½Ún­µ}EÛþþûïž¾­—\ €›¦ðÈ0mÕá”V `†L€˜ÊÉV+墔ôþëå2 @cÅ ¨ÜJ&Ax:Ö=Ù«!N ð!k¼ÓN¶™ñ+$6[¿4ö= V–æLsß8s¼àÓÚ <ɘxm0€- TQž¨{$öYcNî·ßü ³ï&eFõhEžYž=FInidõceÛ¸VWŒÑE»²-0õ’ê‚*ÌÁŠÄp†Å;†B>Îl•"ui[z)sºY÷B&k†ò§'®c.L²•:VNÙ]+'óO¸8ô+`(Ä7F“(Q+êeÕ–¾y0&,‹W%€²ºÛòäÓ‰¼7¶²¥¤æÓqðÈ”RÆö\X•mHæ ƒp€,s+† @ Vâ€þ±Õ]I¼’|Xåã{qeÍI¯KQ-\;ØŠo˜úbÄfh þB_©6˜­r<Nƒ1 r…. YëÊëå6ðð S6Ҫخªy0 «èïPŸÏqQÇÙ¦ù±2$®\¤™I>²¹9 ÒÖJ\#Ø¡ªÅ¸Ÿ^o%B¶+ñ—þ¸9š·B–UOdµ™Û:x(7CW´•ÍÓ¶{kf¤vðÀÖ„½0Þ*d ¶Ö·915²%ÖN¤Ì¹ò¸FÉ`]ÌÙêX•O9+ÛHUôþòµ#Ø:²àÕºÓ 1•×W  O)µV¸ùcë{ÐH¶À³.Vóà)Éð »g¸mæž:’R!¨µ­lo3нøžN]”ø-ÓoÍPßðJøÆgh 4' v-˜äFPh-“Øv²°­ZA ÄÈ~áÖHŠFX ®÷9Z%•ã•wÞ™'¶ b«”‹L:c<“«úõ•2 ÞÛb¥¹ƒ|~Ð6FSYm z|0ecHí2õÝÑ: [3¿¿ýc”&5eKã6jÏ\H L%˜²Ìõê6tçã¶²æ ýo­*™mäôÁ5R ‹yn ‚”¬ÛdVÛMbÛSÖ.žÒðªæ@𮢦ª­Ë„e€g¶”§#«#“~«–`U°.ô>¼@7iÁÖV9¶ª²J©ÂËNPÊV/k#Ue«ª©ÈMï$“þkƒ™#Á&˜4Œ*+¦Ÿ©Ù2!‹‘¢µ³¥ïï#È\ˆŒ.4V[š†EüP•˜LØ*§O×Ká°£¹gA¯–•P‚·Jœ ({¬¿Ÿ)V/¶M¸Âχ%¦µîpÛâ5Ò^ëÑHôi‚Ò;¦l¼­øÔBŒ'Æ[}®­„«î»—† ¥;±bd‘Ķæô¾ß'°WV¢‘u¿?Õ—€ÿ®ˆ ­,ÐT½í4²©æÄØêH)l[ Žz´ÖèŸA¶Tâ )E…UÎîPÝ•ò9.q9ÕšðuÐ¥|˜˲‚“Y%¦ïoeżÛfˆEn²vLz"ª„çØä)²J6-Ÿ”®]Öél5²*!Þ$€¬BYwE`«¬Š> [d'šÉ¶ÄB¡”¾J¬F%€{ WN†§'¶ê­UIÁĶù·bŠ«=#ÀÎÐG€¡Öþå­éë+Û` E½fC#Ö([·âDй-<¤*[FoÐV˜^V‰,¦€‘0¾v_É9&R0¡iÔÈ ¥lKY9+/ 1’À 4ž'â§ŸR²øRH2ŶµîøZËÒ]òøFâ ðüÀÿ4Áÿ£ën¶eÁm <ô“ºý÷ôžç“vZ.¯pÀ@ Rª:çÞn;‰¬A œÎ1)—¾.UåîA[®1ÄLTñ”Ì{¹k¦L€Ô%w1†ñ”íõÂ”È åB0dÌ10Rèj%ÎŽrΔôHzN™ùdgÆ÷q»EYË܈ûÔÍʶ7´‰£eúÁ3Ž•ŒÜ­á¦7î}dËàá¾4þ% ÈÊMäÐákÝzþ0@Ò·U$¨°óF; šPÒ‹iPÎÙÊŽ\8¿nà-ÀG‡«DÐ1Çzé÷¤˜kðù;^#+?‡z1JýY7T©`µqª|d¯ä¾]™ÌEê°j ßY€Rl%X{¶áÄLüêoÞ1Ã6”u5.<(´z·I‹­Zûöo &eÀ³ÛÄ•í\ô¥šsbG1 4èT1Ž{.›(á- ˆ6/÷dý‡ôa9Šœy"¶dò©ÔE&„ªgoOÑgʉªJ¬µËZÈä”@ ( Xµë”;’™¢EÀ­l¥€,TË@a ÿrû´$†Ï~ªüe]ªÝ‹Ø‘ ¹-Y»Œ_èûw®¿ yÚ!XÀ<‘v4NûdV?G¤ ³’Mä“Iâö„UaJ³d¡Ñ'®…g7BÒ´†J6‘¤DV¬DïH‰‡EJ› e²Ÿè…éFd¨EpÄ‚æ¹{!!ï›`çþÎTªÚ}™8¶ @™Ûöý‘Éö´Ýx?&šÈîµ»óÑ%' ÌÂXR¸Â_ÿúW7]oÕlÓ˪xú5"¼–·TKÌÚµŒWrì³”‘÷)XC¦±Å$vk½Bµ–Ž4Éd¥¢ÒÀU}’#Yzƒ8û³Uþy 2o(ãí `2½ôJ|¾ñ2Æ/4†dG}õz}î) §”Œ’Ü7в?µ=…Aû>b2%-ªŽ‚s›…ª€UÛÆh¡^ò®y¾)ĦԎÉj/°MŸ¦Æ³Êý× 4GàÏÀ‹Ä]¶qM#0¬ˆÇ …®JœUïÀs}XIVíY»¬ª)^ÌKzÛ|d|íx]å"AbLJ>ã#5Æ´UzÙ&âÇ ã)(ùÈ}²öìƒÖå£1(C½ýɨ«¹ªºŽï÷·tbzü^Æ‘³pYJ>§áÿømÐùƒ¡Ñß®10e¹; Õ­‚ïõv\ПÙßÜPá¸qdƒr4·w! WMàXí—øó'“C³øØœž¾ª:bÈz¬®–`&Äé‘"Ћ¡Ë@ã¬×GBг¡ñd Ð0ä€ “%@ÂØûtÎ6wÿÜÈh0d€ö}{ˆµ¸R;Ÿ>>YY‰Üh™,Ï|T‘²)#ãSf%;R*µašùhâé…µ‰Ã ¼[ 0ìÖ®€qì¦dxn=ls9 ]ÈÞOƒÚ´ƒ¼ªgñ ³'¢ÜJ3«)52I0%¦)€­v ±ÿ¤–³ÄýרÓÇXL»éxפÜSP¶¿,h"åd ð×;«6Ä›%p³|k䉯%çdr1ÒÊæz#ëÊD&ÛÊDG|¿ã†1kÄiûþðôšÕ#›¨±QÉg„Ñ…éRpJ½®\;RµU3gâ(Z é³›UÓëÝДȾ€’l€ñ—ûü8WB Ë8æ–øþùjt‚4.¸»hÁ$¨]Í î²˜ùŽmåX‹ª‰p-®ˆÞAc%LrËp¦éíC€Q‚i~0F¬êór¬¥Üâçá†6´ e£Ñ–º)“r‚†æÏjo˜•ìæ.Û,¤à¦7ƈŸ)ª4µw¯ô”Ž&Ú°¯¨}úƒ˜l¯åyÉ;íP¸+¤ô\xJ›×„ȘiˆµàÿòÇøìÔåHÝëx¤Ü@㽯cûª‘)Ñc3A:Ò‹ªÉ ²øið9PÖõÕOŒ* »^]¨Ëzɶ?V¢w`‹Q øà¹¹‘¿ˆÐ + eï㣠À¦4}·p,š««™² ÓtnJ–¡1:’)¬$«Ö¢Æ\{"ëe “)51«¶Râ¹5")Oz™@Db`z¡—žs#Ú¡AÊ‘º•"7C_v¤‰¬—Ûd퓲¹‰Ãª9[ÕSÀ1ª;¢’Oz¹‰9󌈹ùg`%_AÙ;§¹~'çÊ1adÎYiÄÐè%S‚ùËôªd>>š‚@À‰aÊò-Ÿÿ§íû?Nó÷ãËDÆó†ŠäH¥. [Ì·¨RU/º²c =@#€¡q) r5ÓœÎ-ƒOé{ zûx|ßg/“oÃ|äô@î‚çïX0Ï2^έ}檉á>ôŽ™#»f·Ë™PTÙ Ëkqe%¤|»Õ e ¸ôùKCGíù;6½‰9ólsG¡Kn Àhר¬|`í¶¥t„@Ðï–v µ3â‰õ¸)r#íÓ8rNÆSézŸ5^O6¥*azƒj·|;·ÞHíÄbƒl›R)¥}ºj‘ÅœyÐ#ËùÔŽ¬Úbò”0ãÙû.VF*õzÎD™›Þ¯qJáX/²tÄÓó÷ªºÂxŒ#6…¬•úL-/‚F#=óñ•r“ÏÛñéâƒÌüÖ0±¨‹¿PʳŒq}ÓØËÄdŽ2æ,q—ÏDFÊö—ÉÊÉbئ©º5æ–‰wDþ-–ñ³Uj¥Ma…) Ú§—¯PÚ§dúªrÀo<|»ÅhäŒô›­F]Vrä–3Ö‚¤WMìWbŒ¼ 'ÈP#Þ—¡c% ۹匡D‹á3”ÄL¶•¯´}ðl ¿usf…\»eb´ç& W¦É$²éóÁÇèEj¡ñ2ëz¨wÄ|l%Ò·0œ ÃZ¶'~7i–,&@¶^]í” &³Cæv€‘¾Tëjbídô²%1]ùÀ^îsóÏ`ç¿Å·PÈ”.f¾Ž¹Óô:æY®y†9Ò8ÖH,û#pTÂwŸ“´ˆŽõ&“W%àP •jáyš¿?9é˦¼+u±eï"w oMF“Œ Ž4leáXIæV/²¹r@UX^K¤c%]ÞпèÓTåsov¾sJ-0 ³Š±ªc£É§çƈ»iG]&P°5ö>)³Rjnûöªôï ÐdÛb²#¥¼[ÃLºÑU#å@³2Œ‘³Ò(Ü]v##ܶìvJYož¹QFr`Û‘@ožªzcVdªÂÑD%‘¿×h7LVSn4>R¯%5:ª^›“eL$½ã>q¤Ž¢MNÏ÷1¤ÜXhéeຶ›…OóÝ¿«¹uß)µ´ÆÕž´#Ùnhã`%·Ëhó:Ê|Œó#`ºÑþK¢VuDÒ«Š àYØÍ >¢­èõvÍ&¦QEªF¶¤\/nO9RŽaòbä ñ­AÀ¨Ò8 Çs“ï/ÇÜâ)wLŒȾ– r/}}X4FˆŽJ­]¤´‹Í¢„µ Ùrhb™>Aí÷ç)a%@4nÉ"kg¾jVonÏ4`h.’¦€7Lw,ãµw£CL«jìHì÷m7í­VÚ]´t-z­1wnŽ|U UߢöÔˆ”ódÂA‰ÆÇ*÷§»v-d‚!†LÐg¾«5…2g€€•.½‘5¶É1ý~I(ù¨ýÛâ®ój&Ž,ÓÇËÝ¥}ŒSzïØˆmˆ´ŒÐîâ†Öîv˜î>3Ñ.`Wëvl«x˜,«˜±jÌÄh€¾£j@ÖX°êÓ Àª~kÌÊ »hlÕ>Ǧ Ó'ÞPGX¯ $Æí<0’‰½OXÖ•¦’#ýZûÙ¡=^h‡eQ)ÀÄt%Ë·ùº2§©š¬Uû MÕÚ1âÎ<ß´fd¨¶ù~pÌ|êªÅzVÊÓh¥žkëU•3!¨ä¨«‰Uã·'Óf&Æ“Õ>‰ ž/&p¬½ìhá>A-=LØ{º;Ù”zñ9ëê—[íidU|>07Yã_þýïû†1eáLªÖ½½š£’‘Í h×ñUÙQvìM)»’‘d2q,('VŠÌìg c%™L»}ý>ßò‰yР䢋3hð°UÉìÌ­‡îxš¿¿sÓB  ×ŽÏªM‘°ÆñHL&žNÖž “9*9¦D’ÑË=> ¦À(éª1@Ó½²EZ»?{te¢D6$¬K¬d®ó!‘<1L0ªÂ•aï)W’ñk‡ée¼v¼£.X‹À(4oØêÖ?Ë'<àß(X Höæ¬x †§í6ÂFûuÖQ‹–¡Ìö6}~{Sú,h¼¤œ¦ëÈÄx9€ì;àèMlØÀO&}7t5+æœÛ‰ö!pãj‰”w¬ê" >-0eâü‰ùV‚µ¤L OSãu=?;âÕ4Åã”d5ò$+·dÇÜzLJÿ›aoB™UË#E/S&dÖîkFÀ“¾•úa©‹R Võ÷ŸµÈÏOVr-r€@täCì˜ pDöÎUS¶dÊ]©ª7^ºUåx™Ø#(ñwìǶ)Z’žvëùcê%”úÊq®«AÞ0 ×ÞªÃùhZR©jM¯K­MO¦që5BÞ×·…L‹¬…>[>°Ø_¦)ú¸5æ_Þh¿jo.Ç™;Âb¼­taXµôÈ3¯WÕþ”íÜGÆ/®÷ç›ct‰Jrû—û¯FTâIJë‡kÜ,ÊÄ­„w¤l‡=/¾Ñ€ÈÓ³ø_4L‰™ Ãã{#^þß`e–h ¬ÊJØ' ×HæŽÆ9FÒ¤Çô‹”F#;æì.‹çãØ7¹ÏWC¤è4nܻ̕|þ^oÃWihkؤ)‘ŽÂ ð»Ûf!yžkÜïmŸlû§çÐ\‚†v$F52Yw‰Ä[ÿÀèjLß Ù1O%Gâ@#ëêérCúõHlJ>uÑ`ÌâÀΊÐ+b%‚zé}¸]0½ªP¥QÒØSµ5`¤@Ê×ûãLã¹9Ê"½#¥Ì*e9ϳÁÝ&^´†RÎŽ -ß­ñ4Vx7ÁÔUIµx:¾$™Æ¯ü˜{[™•¿£ª^ûØp$È ì˜ê–ÑEÓ]h”ú8þò÷¿ÿ=»ª~?]F@{4² è÷›÷^ îJù„Íô?Êœå<Ó¸ªÌA aѸ@Ù2"“ZÒ¬ËÎðH€l-UgÀ÷5¶5º˜¡ãºÊ»ÂyÃZ¦œƒ¡É²5KÉßQd]ª1ï±)ôB•ç{»VêRû¥ÀØÜ2²)zû’–œåÄÚý—Ñ{¤c溊¦ÀGàÊZø›¥Äª D0&²v½¦ ËO/ó‰1‚Ò1L z‰O/^XL¸ˆ–ªdŽ"Y(ahüb X6Ëô–'P ÓŸþï7Ðo.¼Y ^—#ÒèÄgÆóm¿Ýgòsùû?9Èí„¥Ö€{>@äO ±8ý7rhg뭅ƪ)_[‘%øvŸÑÉôª:vå]¡é²H£Ä &Fæyë'Íß èÃò)hÜ2JZˆ§wl‡^ C&ŽÉÚŽôét?z1õÒ8Öehè|šÛ•m…‘9 @»¨¥Œ,¦ç±ƒX©¡4=>Y‚ù«Â½ä¾¢4{"ïÖ†›î(hrÎ6¦?ÔûÓ Õ3ÖBê¡J[&s‘J{ž §ð HЛ8ÿݱ+LÑÐÙÍ•ÉT1_íyO)dHGY˜^cØÚÂV"=ž ¦ì¨´.Vx2da kùÔÛ•›¨Z{‚nŠÁ“ -V2F:2ï(0BIc#ÂôkYѬzU12²Múô…R]¾?€)Ö¨äÈn+bwI³L#:Ò´­ãZr£ÉßV²HI#ôÊgØ} Ûº”F¶¢W¢Aè„ý+íg›ï>4”‘ Ú@ ýlýéÃʱ8›ÝÝ|u7 ¨¥Û–/WMÀ„&+L—êeðk$Øsá[UÖÈ–'#n+„ÊÈnÔ툭ݛÀ¢.×äYrí¦´­|žï~»(uÁ×à¤d[©MÒpëHhÖîyáxJë9öñQrsa¤£…Sâû,k [Æ?KÆ!8Tåٱ̜IëÑdJHGbc–\ôkF @pë(k"Á@b¶ëMP^£fùþ»~½mâ÷?M/ƒ‡åö‘w  ÔØO}]®f–®>à\5ênY3†BVm-$¼PJcö99n­J=h½J‚g% <»ª ÊÖH`Û=a¥îßÎu±EúöšÞsà‘³j„“aºr&g›çSG’ÉôBiícVÅÀܲ|,€Žx7‚Uc|ðôŽ1p]Y¹‹gáĨö޽v°gAæ`çZð±­`ÿùÏ0lû{ÆQ6kk´•%µd«ÔFßÎög¢Q¦i áxVùþž”¼†.íÀ!ÛV‹À´Õ޹!,k}£\œ’‰F€  sAÎþÅ›’¹pC‰aVÄJ@½é‘ݪødpëÑ+áEí=ø~Èk¤O_>[7úߪmÒ2ºÖ°@¿O=ÅÙã~È®¿ïÒÚAÐÓ¦ @¯LtdÞhdUZø¯%L Ðw x[ndHX& „åªü]ª€Í›ÓDLÿ±ˆãû~ªùˆ[ÃV°Ì§ëô>Ml¨A‰µ7«Ṁ‰Y/ãÉ´´g‹)”ª"‡åÛýùãêuK¯ÚO„=™Ì‘ bHCì(ؾ#⻋^G¸‰ÄUéáî¾^¥¬òÏYckdn#ÞwiV~-ôeðó5+@—M-Ö,L+eóäÐJ•Òh§i1XIî+aG™²ï ‡~­™"T‹¬øH 2,§ïÅŒ«Q&k¡ŽícJÇLÞœ3V<}|Âææ+ÚcblÞÅÛ­‹¤—‘”†²Ún«¶^8JÁ“Þ¿î!¶LÏk´R¶^ì¸R> 1á&öþ Å‚C³ªj‰—3$`RNã˜!Ð3+EÊï^#á­h´¸…«‘ÍOÀÙ+Y nÐ2²ª. ŸHÞé(jÑÞ‡ž¬ 6KµM²Õ®kË8ˆÌuvp È}4½FW ¯Ü´Xµåå¾Ex>-  XžÞ”Ī¢’.%ÑD#Ü+Œ î¨ÀÐÜÎ_ÿò”¯ë™K# •í1…Ò@ÔŽM„Lÿi°ëp@êÝþÄ•à#Ëü'ã)š›,4dœ i[£ŸG%ŒHi7’{ùëqv ð·+UYIVrÜV1í©j\-&¶¼ð+ïHïhOâô޽ÿHÊ^>žMVÚ™Ã4ç?hÝ® „e 7!Ð ôÐõ·_Ž-A¨²pÔ%²ŠwäVJ»²âs޼Å@—›+ÍŸ8s½È£æ&ÓÆåsíÝŽ˜m€!v”›ÎMc##膥qíèXµ.¸pÌjŸ‰qJ2¥ÌD;à•ÌŠ¼78¤®4}/5&HÉ“Æ;Ê-oÕ0~üX‘1§lgG&0rkTºÚ'JG|ƒШM!ã`²®»ï¯2 hD€ LAϪY˜4§çvUÒ¢Tî³6Ñz#‰ÓŒw$® ÷\Xä à ´÷È™#jÔEÜÏÚ.’ AÉ0ŽÜò—yÒI,篘¸¡JÙÊH˜««é^`²×|ÎFûhTõ}–7Kc¼Ñ¾)³Ý­¡¤Q°……^-ŽvóÝÓÅJ#Eb¼p$S"p¬- ¥å;áŒ`nç€Yp/'üBOßæœw»Z˜ÈZ´49·^GË`,¦QÀZD²@ß4> ˆÍUâ#w)úªlE>ª•zšnÇAµÝ¦§,²ÅÓ›.{çÖ&Pü·œ3òûC MÑ%`;Tmáª޶ª!>=qwTE Lû[Ø>}(×þó7 n˜¦ ßLБó@¸çmDÊôM'&˜ TÆ(ñ”‘fk[wLïH,^JGY˜«E&ã gÅ¡…Uen²7ÑøZèÇhU7é˜Æ 𢪺Œû†ÀHUG2ÇLÒ‡‰ JŒeË—óWú‘a„ªÍýyílÛÙ¯q¹QjO¬äاãî[5°qŽ‚’-ÏŽÝîýèU3OSûHÇ!ŸU¹Ñ×"·9MÑÑÂWr~!`Z˜,Ä•È8çVU©Ëqž€öd}.‰1ù0©ߪõªÎ­¹ø€^ïßCaðÂ0@¦DÀ­‰˜Ì1-ÓôBIÙO77U¤¨½.˜-\)8}V0†Ì±ŒYp)óQ¢7é©]A´êφô1ïz'æÀMNÆÓ ÀmØh¹‰Ü„ûr£©—²v ðŽZzG@£?Öa#ऱh‡2Í+a ½a%½LÌYV ¸O-r@éeZ㽋ª%é¿üë_ÿò¸ztòåˆlR¦tª²$A%²ì™àëj•.#׫½qŽ ‰EÎi×NC¼'Ø4Äd)yˆãµD÷»§@&Ó8 †2±@ZÃ1=¦Ucò·  $Èan@]ÄdÌ=ôí8)R¯.˜y׉)gHÌ S@ßn}ùð”]pŸeþJ^™Ø/Ö†ª* À¶lÜ ^8¶­’8Ö÷ 0’¹F™qËô“ 3Rèz3ž¦+x©Ï|Acùþ!*7VªsÓ¢½¨}2Jx ·Ãª&Ò³2Ñû+ùpkfÉ‚,‚ºZßòÍj1J-}XHAF£ª¡Ž½€j$fzšºÆ8š^‹œ?RÔžÞh&ùd¢.úvÐÂ9R&ë²ë¥÷86ªf•O]¬YIcÇ<ɲÍ0=&ÍÏLJ¯Ï¬b¼5´[/Y 44¦è"ÐÌÖûÆðIŸ!±F¸g4¨Íå6×(vMX»h½xJ0CëÑ-}±fM¡77qÎô™È"’8Y}%UŽ¤ì¹æCÐb~-h'n2Xtš"²µÇhÈ®‰gÛááÄ€RÓYÁE½˜ët~é›EÐ1eo뾎–”ÉZRï<µ 9í‘gŸlÕñ4"2]m’¡RÓåÚ³ªý­ÒhèUa€xØ eL_Èe%]dL0޲–ºr.7Nny‚ôWûç¯G³DÎÙúô‘ù³j"5Âc€d€Hð2lݨ¿úÃ=ÐÏÿ6éR­ÑgÚ-ðްØ7hDææ:Ö2Ç®wÄPÂÜ”67¾Æs‡Ç­c;Ë󌯥v gÙpÇ42ٛͥiÉn´=×¢½ 1܈uÁÙ6·Gh%š‚¦}Ú6’UÎŽz=`/rö&ªJ9gVýp½—"È“˜I-²h$O¸w®”§¼‹PѳÈþ´5®ºŒ*Ÿø2A%ÕfqjŒéˆÑSeâvD]–4Q¼2UÇ~F˜¼o’ó58£ÉDƒd>fu#JŒÀÐ/c”Š;ùŒ¾Â3¨O8¦Mè3!€'8ãïç?YíÙ6t;˜{þÿ(÷ùùºÀt¼l¿ÈZÖ$fáh˜LÔÈŽÀ~˜ U)ãiR¶S7T"hhJ2`†JL bG%½½B÷…’FÈ^µÑ4Ú‡²Mœ)+á|t©Ö+wŒH†Ô(8ˆH¦ôƒÄ묷½4Jš®4ŽF‰CÕËóogUÀ‘`†­¹>«K/“Él»TÙô¾ U‘4Lô2AátÌŸ¦+·L$Má˜IÇ:ºBÎHÇyNÓΆÚJاxÖ(ïÖ ZoÇ?R¦_(ù ×n´ì)º¾)pÛ&žs•c`úÞ0·†"™ súìY‰÷⪮Ô}1Ž-C7ÎÄ3àŽ@2g•¿c/“ƒ£Pá¦èÕ‚!kÿU•ÒhɤA)eGbwá`·>Mbx†{LoÒ]Èt4z7—€Ò]ºN;ÀÍÊ€C]é“…U[’¦ ‚‘||èýÃ*«dHV52Il"*_?⦨*ñì+!cæã¨½U‘t)õ_ú>}¼è%÷£Jßny†åfÔ•9FÕŸÁ÷óïûOP—Lz߫܌ n¥öÝèuN¿v ArÛêJŸ-¼/[p”¬`d9ÐEjÄ´›cz ,Ñ23¡˜•SÀ|Rú¸mXCïY,‰qä (XP½¡LswùójŽåÖîˆ!æ_/·~õq¶I>˜ã~Ûõ‡sƒ‰åÖFÆÏ¶åɰûæï sþ«%èrðÍ dÑŒ¬Ã4uzùô0Rps3ÎA²/.Æ‘²R™•) Òpâ7ÔQäåGÆ ÉcC Ad àóL–ÀëÓT¢ßµÐ´s¥fѨêBø~»l(h ÙðVz—Ì™Lð¡¡çnÏíT³ð¾¦5¶v·éó#š‰L“ nyǾú@{Ê Uó§- $(cÌjœ#ÐbŽ™Bï{$è(·dã88z´Í=îÏ^ɪ’Œ÷Î6çæp»ÓÎèF´ eǪfÑV ÎÁýª8òi[y<oá€jnFc³‚Y!«==0Zài„ÆhŒÏAο#œ “níF¢A7â£3ò~Û5V5ÂÄ- T’™´Cã(^’F¯l·í.Ji”&Î!,`yëQæ9¾Þ«=‹uSÕdMq4r¤FG¼c$nJGX´$€\ÖÕu|F|º&Ab›ÀmNÐh²@š‰y¦Ä´ç@ÔHÓ÷A{æ•"U»ˆc>éý¼Øs&»l›PÄý©‡÷aùjɺ¸­×H™ }l´‹ÃL€õA#´¨ L†lâôßïe{I²- sX#^0¹ÆçL¬š9Áª½IàÇÇÜ@2Õ cü¶ì5Í*›Ó GêÅ[[fÞoZ ϲ.a\K ̳×fÛ›[F—cz}LŽÌ#[r#° ,ß±Ÿï°ªhh†4}|ƽR—Ñ-ÃJ`Û‡@;ßy–oYG]BK½°Rp„ÅøŽô}¸)•ÓÃ^,b@˜EfϦHy£È–÷˜Ú ^ÿ˜<Û$[½‚¸Ÿ—ºǧ–¦§Ì³­øDdzåp#ÊÄBµ’–cЩýíoSËݰƗ‰ðp=cBW[žF»ïß&õÂ;çƒg˪²ê4ašLªÊdV6‘m»ÍUgÛU›¥åU‘<x¥¦wÙ<‘›h¨OËe9P6‹À-´“Ý—8_”~ºZ¾=7Ðû–ˆ}uŒã ×9}{6NW+Uz¯ŒdåÚµßÊ)iÇc€fõv¬.›ôÉÆèdÝQKwlzn°ÈV¦o¨L?Ì_i£ã#“Á‚U¿•ˆóLi{ó;h®<ó6ÔÞgg[ÁV “u]®€qLLÓW¢¬A#;ŠëtÞóźÒä/÷ ’Á²È§£^L[©æ¦jÿHÙQÜî“0À[ †#{:#¸exŽ%†ç ">±L”YÕ T¥äã»»ç\1Po¼,bªº2 Ç"gØG@ Ð šž (”|䦨¦ØâËz †õ®è @ï.”À4b˜Ë™çk´-F‚wÍnA ä¯G²pŒÑ⓲eƒ*éE½šG¼@Ê Žï½™è ­“q“ š{µÇÖÑ_ïh`dÎMéAW¥µØY8öh«ÍšUɆxž½ÜÎe¼oýlë%ºò¡!–s@6! +uì HÇiZƒ§ÈÞÈD.rëƒþÄä«:kG¹ )È=Ú4«·*†¬^Ùæ¢¯gÒ,y$1j{&àY ž-#R¸”Ü#ã}O”Z€8+&ÂU_×f‘!eÁ¡ÀÄϦÏT;¥à6dVøz3I¦ÚJ@;¨b`bXëÅcòÄ×bñã`=>ĵ8 J»ëj™nš&Ð#*‹ÚM!&dx Rk;¦¹MŸïçQß« èZD Û5ÈÂLò©Åu€=»‰ª²ÐÂd÷%Ë“a@ 1g¸Ýð•í q ÛHz%¸#¬ ë•ÐÇ7HN“asiᆦÄd.c²¢üâ’}eqÆ£¤éa•íãû‰wÝà™˜‰ÑÞ ½-ИH°‰JHGÐ B5+Œ`(ÂJ¦‰ŽíàH£ÑD ?#To÷I)U úJΤ`b™Ím¥2Áç ŠŒÌ#Õvnpÿ2ábÛfŽõw²ÆL©ÊMµGi›<‘+Ù,šH-°ìùw¸A€^¸5ˆ9à)…Þ$»´[Ë!uÉLç€Ñ®·tÔ«$ˆ4üy:êjŸ.ÒÄô”9È™g2g-¾Ž&büûHz_ëþ{Éi4è¥ç“^„ì#Ä&ŽíP¶›®øU3¤oDIµô·.¸…•˜Ó¤£Œa’¹ˆ—m‚¬ú*1o NŒgÛØ>ÚwT*”,掵ÇÈ|t5K# èò«ÓßÏ4Fj)Ú§q˜ÍmO/7Ž õ0¦ÈâÃr&øþJ¡Ýø|dц”U1™¤Ì$žU%Àt-ý’êH +¹©ªWrlÃz$;ÆÜË÷|üdýuV‰Ìþ‰›eœ®í°U2GØýT"m‚ÏßcÒÔ ˆ4ª¢Í½­G@œ0\tl@f±cñüÉÔCµ6’ö³m MÀõ[2qût/¼£é¬¼6î"µ8ŠÝ(q½°h [ã*e•Mq-Ï3:&Ãô ¦PudËÐE,1¢ö¬tÅkñ»Èo$dž–5R¬|—Ä ånW»³hŒà£D€ŒÈ`÷…÷WÀ&vY8½Ä>&Gz]5êÂä´†Åj§i¥å–F I¦K4´Œ§©dnÕWï=UÉÜÎJ}^mh´^úÆUµ'}-JÚU3éR¦àËL>1ˆÍª ©Ôªr2U-UåJ¶ú¤ ”«Vêë„TíÊæ–Æ JfñéÏ-zñÝ%…iè5b¶-q l=¥B»j˜sJ½í#cdÁaÊ.« +Á¬„^™lí}"µ(áÃ{¥õbTÝ%¾xaެı×à†‘›(ÓPÆd%ªSùç ˜Â™£IzV¼6ÛÐ)mÞQ˜7#Çö¸•óR1µgEà>|°^2&ë%Ë k1MdSnÏv“³­μFù\ø~«jw¤ñƒ! %ëÙ­Ç„¹™¨jÜÏ ,ŠŽBIÖ›¡%5: |í5Rvã'[Vר…F‰ábR"3éȰ}†ršVUm‡µïø 5ºow!ó«d¹Åjœ‰®ã—Gài·5®e]€hs-¦Ëd¬*é ¦ékigzŒ¬w¥Äx¹"aþøÌe«*5°snx+aèsÈJ.ÈêUÕža>|䆦‡µ¼ M¿`sx«Fûèeƒ8Ëžð¸•d˜¾ªcûׂ'Χ• • Tõö‰ ·å¦#»rS2— ¥Ð+ú]AÌ0±lÊÚÚÂÙ¶0†ªÈlåv# wdnYxÊF0!Ö¥”y­'ÓÇxð^ Åjß F ·ÕUjr¶ÚOÉÁ={óĘA/Ÿ-å Gžî"»;FÀÚiC5ŠHYÐ`Ú‡²è¨j"¦F6¥#`–œ ª¬+“x™¿)¬G€¬ÀZø8=@Œ!èÓq$=Ù¢®üµ$£o#’Ø›¤L3ҔܴÐÇ≅ƾýT¢¯E)ܽªp&r/@°Âˆ4S«ù§‡ÞQ#gIÖ½4â™Ñ@zÕ;ä¼³PbT])Ÿøœ 9œÿgµ5XM4R'¬3p+g6½hŒvŽ}ºJÂ±ÒÆç ´/.¡êóHÖ¬vÀ"R¶€F¡ËPm4·xHƒz&ºdAÃ9eN¬ŠY;¾Uû‘shö™Óã[¾¥ØÎëêRª@k'ë.xVô=H²ZȘÈ]¤Ñ™ ¬$tuË7ºFú®cÖ…‡ñýkGÑ|Œ`눬 ßi&uMö2.¢«ÛÕö­ð”ï>ŽÆuµªynÍ>A>ÚE$€ç–¡Þ¢õ¬¤êîA£eä<é¯ßç§¥µ1øLÃ;bˆS"[C Lßhk`êê.ŽõÊ‹íÃS‹UÊœ«#ŸlÉYA–Àôß_Ç4€.& 0@»µ&^^¦Gr?,0qI6í6ÄÀ4ÝnŠ,!ÃÉ(E;˜¬š ËŽwôO.Ø,>íIà#`…÷# 7Ÿ&ÒÖ##¦Ì?¥LІJ0f1"e¸wÐ`L—;¶ŒªàS—WňzåpàV>¿dr–™ûPlb"[>d<•†98aÙQôzíScíŠ!Sm–®)[ÃtLdoRÖ•ÏëÉVàéËŽ)™Ã¢Ýø·ã¼vÛªÖbíx˜L—mU…AލQÆ7%`:&'åç 49àµèÅÈ¢ýÉ0zßÈôJv#nLŽ×em$¥®<›˜3ž>Œ¿Ò<‘¨±c›Èl[ N¯‘2€´C?P-ƒaB/Èe>ô™—‘ †"d»l™8ŠÄíIì«r»ÝçvŽ0À H`´Å0Lj$€U>~!¬äH)—g†LòTÂGЫJ¬Z#xoxz®X&#ÐÙÂZ„’ G-ƒ¾òó˜ZRâ)›8‹kÒ†µÃi>Hñ2«e³áõ¦Ç|>ÉÇ÷¹)죌i¸…õö§~Î]Á»©"9 ×ÙzHz$ÁÏLÄŽd ½ç“0>çÚ![RÕÿE蔉Û4BîË =YŸ~?þZZ‰! ÈêU¢Ä(ñlISZ Åè‘J<åŸPjÏlUçÀSܱç}D% “¦#$cÚê/ÿüç?!ýÊmDéXPç•À50TErоyaG™˜U«™´ + œÈÄ-C#b´#Éü}fŽWmÜ2éËdÝEc&øàuP¥Áä l+@¼—펹áUó—‘"À'«r¤AÚ{[ÿ<²®ŽÀü×Ý#`&ÂÄ l«¨Tuÿˆ†" ¥Ú-¯º®nÚx¶'=q³€Ž1‰ ú_Æ·—›`+ÚÀÀ}ûažZd¶ò²éÇñù@ Ý\-07‚û‡À Þ­¹í̼’¿ž¾?9x¸èÚÅYèV'æ€!Ã'ÃcÞ•l•1dÊwÂç©#UyömÔ…Äœy÷û6^i$“<[CÉ ˜?É2ñ>”]A.(yÊ2ym·!OnŽºÈÒä $0Ç+ Éßi8ÈýÁì/+¹àÏì{ñV…)áþ߇‚uÑ$n%¤£P2º?™¼OœØ5q2¥Ä”ü`šEÆg¸®æÊxJ»%ËPNÀJ/¬ »`[ÑD:Âeš:Â9DÊ­šá&"á2@F YY¯¹«n¬š9q7¢p>r£‰™Ü ¼¸ô'çÓ×ÌSû ³2È2Þ9 Y‹±2Î1Þ1‡HÏ}]Ü2ÁäLÓ>dá-Ÿ9#X¸/€vÄÈ•ê¥Ô+ðí¨oóv¦ÉV&ȇ lO¡…Æ‘À³xU˜Òðu1lŸ<‘@¯´}Z»5ø82§äÏÓè^8ÛþÑ—†2Až#ÒÐ+a.·Oϥʧ.U%XÅgïû€ÝQ.RÊ5¶g«7ÿ}X9–c˜µÃy¶°£‹¨:2Wò%D èŘÒã×F:ÂeÇfõžÇèFU#€ö¯½+hq,42ÑTKïL†„ãå}ÁZ’80+L÷ê8˜®ûô†v J]Èf5Ô‘H,§Yc© ¦Œ©%·Já|Z£.Œ€5-ÓŒéè 󯤋l³´ãfæ1åËfÁE]=×vPÂ7Ù—àßûÀ{·Hú>5¥†¶ÌÀ4h£ÞD¯ ¨·ÑpnéËJ"™ÜQ£·›A€–9¼Kéç½?÷i|¯þü;kc²®‡àØÑ¢¾I0žX&6ž‹_XªRÆ;V¥Ô¢1I Ë~ùô'#2q«ïH]r-Ü(¹Õ¤•0›^/Y?›Øë4—a½-Öc–¬t…ã»&}-yVœæ»í­ŸÄA¶Œ¨$g+ß9ç=ìïèþI”²eWPB&Sê«iÌp¶5âç- %·Žïg Óá"º(:½}ö8¦o+2Œ^<ÿþnÍDÐËMÔâhD|m[Làí“Ûª²vÁ‡a¯16±›Úª9ª*Uµddzå ÓûÒR ßþÉ´×HDnDÕU储ÂpS´(µpJžÕ¹õ&r&dm«‹¡ô0YÁD•)ûúiì»G€ÙuÍ$·zí°5è…£R˜L¯ÑSË3§ðÄd¨·ïŒjÓ½¿m ÚYÎ!}ew¤iœïYOd †lÜäŽ4ÂQ)¦;bA@Æ úº0&b aÙÚv¨åg™45v_½µó'ö¹ô{ z‘^&à¿Ó¢—` ¥£€«jq$sl=Gþ|ŒëGµ… záMÏЪ}ʰ cÕèâGÒ$“5fØçå³n¶ñ­MÙqy¶@wYÉÑ2x]Éj7«Å27Ѹ]öó×5ÍÝŠ£2ÜMÀ]Àòl] ¬d0Ù¬jé 2ÇÓˆÒ$#èéÝ®”€È?ŸŽ2Ÿ¦™3™êóUÏß¿Ö\ïcžóFÓÇÖnz]Z*ë:Ê‚À˘ž ìXcŸG_¬^ î³Ñ“R ¦[È~ηY5KnÞ¹.S|ÅkWeØ;Ç·’ÛÑ`È,ŒäP ÓãèÚWj7™iyÑCUÚz‘3¤Ë0Y Ñû4™À«ÎO)cz® j[{¶R½ÞÊ/ýF멬·(›ëwAº\§]„“§L jX‘ácœ¡i”< ¾j>õfŽ©+A¥ÿ/Û*½^s%²Í™¼Ë¼Gª€•tÙŽ™Þæ1KÓ YIèz±£ ÔÈU™ú^ `,œ¹ÏÂ[8*•UYÅkaˆ-Ö>ù4EÖÈäN;wtÁ¾­¤š¼%óé»Ñ’ â£Ô§¡¬ðkgk´Ø¥4uQ®…ŒCídBµÞ­Ú1ÿ)Udz…•Z’’#g¸#,jÇÐËףĸ#œ›#å4zÝÔ»!óé=sÎD£›x+U8Û ›ËŸ'FVeÈm%>ñ€Bð³Ù>µ4ÞQ#%~ (ionS¢ls»N%¹–ÖÓBIøÖ)Á¢¹]œÒPQ#‡øÆmí ›¢ ¶½•._9%CñyÂ+©: ³j9PûÝè|Ö.nt]€F¤Ñ‘1sk+¥ÜäÚZz[õÉÂH‚ ë S⋘n"`¢L),Ó>˜”2×èÙ *ðôH;ôƒ9žVdVuô"é…^G`%Œ ù(´§)L:Ê­J1YJ8%“È^;Ã~«ØVI;ŸzµÀ=>¤#Ðû ÅÖSå ;4H¦ïZÓ2ñ~ŽÚÊ¿Ulz#8PÊaVÃ6pã"ñ&Ê‘µsµÈ°»‹%”¦á¬9Ocó^)·6éqè+™ÞM×Þ}éɪʦéwm%J¡%ç­Ôª9Èxú>Öd4ªJ³‚M©N&«fb:‡p¤jâºäÖ8.ß )´;’ÀVhlðhpÎ8UãQöÏ[. ¥ ª `& À#Æ+d‚–@ö³=™j½­åÈöm 7HvkC¸o6sØõä¶Ú;ö÷¹<‘¦Ë»H| ü u$›£à/Ó‹K&Ò‘>ò'§‘›ûV»‹)…’…3ì+Žñ¹iaÁ§ß€H¥æ&HÉÍQôìuá ®Çùì'3…Æ2ZäŽrQ ÖÒSÓè‘ï¨ó2B©/R[™•ad<«ôŽJm8Ò¿ßÔ”²‰…FkÔ8ÆqL€[J;”mâhCG&½­qµd‹Äøí©K‹èÖûh˜øé5‚^JÙ’]AÖåw +¡”€Ò±é»1& @#án!ÚSÉ (‘“àØLäµ™~9qbWíâ¦dî®d„ªÂdJFX¯ ›+ë’-ÃßÇ­*ç£K{Î-ui îÀó˜^Þ‘rLz%æ¦t$ÀÖr?›G;8vŒw³6¦’#R/™<àØª#É„F (õþ-S¯ô-ãÅi»Xn1ÙUc΋Ü‘ÆbpÏÈÍ‘†8åñº>4•v4—,¾‡Ò‚$パ-,ïË£ô:7"[9çÈdòŸ1^öya ’»Z˜Þ8XÀ‚@ÞVŽJfYJûˆ‰o÷'9¶³¯œæ¹öŽy¶RËwȱðÌ›%וOŸ) 2¾U$ËàÉ®ßç×x<­”´xz Æ°*À)goµÀÚµ‚@:z1VBUF¦‡¹GË 1åJÝN>m·Ñ>MoPí]Á-úW”ZßÑð.Ø\šYÊB) €AFãû’ôãìËàKh"^c²ôŽ™”µÛ¡#¥#“.Õ‘ó>&kÏJ‰L(µ‰^ÎßHd’F\óÓ7+$¥ðžÙŠwÍ6'Nþã?Ò9ò„Ï@ÖIïçã?î·ªíéÝÙ[|<¨˜§×±ÏUÆçôj9È¢*“4º^f‚îÖ bLJŒ.Jæ<²G!˳YJ€ö‚Ìòádô“²å•>Íßÿ¡Z|‰ó?ÙÎÙD½ö"és³€žÀ&e|æ”@Ç3àûË¥›Ö"g»§PõYðÄ« ˜kpF`T9÷ÁÕ¨K¨âS’åœC¤ªãYýùÍ‚¤$@‚FÎ øú!…£Arz%Ç02™²cz ¾«a¼­ÍMé¦þž¡DO#“ ÊM„;ƇÏrwDdJy*á¹ÚØÌ{ÏZ*Q:.p°˜Èò̬É«j¡[&O±c«â{zbÑžøFhAnV‚Ž07Z`?ø¬½5ªŠºÚ!Ü”-ŒL©±}šÞ&æIÐBc ¡°Ÿ²£.ž€Ð¢”snuÉšB–&O#¹õzpíµÈ‹ÖöËÀôüåWÐ+e•fnf%î¦áH˜¹päÐ>¾Þž]‰ÞP¹P¥IFozÙ¸€F]ȼ% È*ð"}CMì)úDT››¬£ÌmÎÚiD|ƒú9¥\‰@`\Ù¥|¦ Y €1P ^—¼›â›•·ªYиšìjÄîu^üûGXSÈöÙ1'«Q5 s®Ëxaèæö\FPöScbžD¤ âoý|(<å+ù3ÅLÉÓ>Ž·™Àsΰ ºš[(õnÈFo@]µŒtÄw¬Ô”2>“r?ªÍm¨–4Fã †žk<%œyz)zÕ=¾c/Ì•."óÁ­]Iø·Š}X4Ý7~þíß>° ¤Áp“)k¯  J‰)ò™¬£ rÎL½¹v`æ]¹£ÜÀ]ø¸³ë™ëªTc‚z79·¦× ×5ývÃÀ‚òŘY­Ýäåí†ï#h\A{v…4ºZRn:†-\ÀéÚ•ìãÃêÊ5Â"ÏmëkIßÇ pkº§cXc £v|Ï‚É'OC•“2 ðÂh$P/¬k‘Ì/„„‘ù>\‚ybΤïO·’Yçÿ ¨ ¯o]µÆgäh-ÃÞ=[(S™,Ê‘í„Û{|-<»s&Óxñ) ÂU³ÕØ'áÈ¿¹dÂQvd½Ä j¹ª“²ÊÁ±=åbž@ã(a&Žá)ñþ-}ÍÎÿÄot@Ë5†[cL†J¯^#Þ\¤ÌÓ÷Ã× o6Q£’ÞÄ>ë~– –ùLIϧõjm{¬¿?'º¶ RL‹¥„…j?TyÆÜÊ¥×\Á7¡¯~¼%[£ï<,*± ³ôÆ4®‰\t$xƒÌ‘FK>ŽÈ1ºzaL™y‚z3Œ‘ 2@oûóFà ]ß‘cFd>^Vª¯‹­ÁàýBñ²‰Þ<‡zóaB¬Ñ±.bÑUšdÍ•EL½ŽYͺçkÐ1ÿdZz6T2©ÀÃåº,†wMG@¤‹ F86Ó/ä˜fµù«¼­'íâ™sÆà7…UGÆóŒÄ¼/ªÊŽ€à,›‚Á›Ò §ñÑc8 UÙñ6ý~ÚÝÑ «¹Ñ3÷Â@]rÜ”dÑP-@ú4ua $†ž¡ wŒ±s?ƒª¬ d¼Æ¦X›.‚lÄT"Ø0<%9·¶ÄÐȉshzV²ÐnÄøH¹Y²pìñ›ÕJpǦóï[—g;è”d¡TÖØ•¯ÇçwfnˀѷïsÇJív÷:‰`H3Òè6W2QµHרŠVLñ-°L_\ùù±Z ÓQnJ¶‘¾´ÞÇ_ûÒ3Çw—¦t&в[ã‹HC)‹la@¤I¼«wU8sâ4ÒWŸI|Ç}oèôd¢Ðz?|_Œ}?}Õ=ŽÀSÎVoëE6BµA&m+‹ªgƒï—-7ΔB/YþŽm(GÒ47«Äž(j¯J¯×]j”Úœ2;aädiôz¤På£οYH‚=HG“ÕE¬—I¿£TM׈T¢ñ…T•…’P:³¿ÏK“§Å&¶R)ÿøyÖKÈp>Èxn¦º* ØŠF81¬DXîX•çm=oh ÿJç?ð罇0O]ÏWÃL+éqa%Gv@¿ïÚFÖ+t‘ ©‹© €ðÁä_;Þ‘a>ðÕž¿„µŽ µ°cb³²Å šC²6ab«3þþ±4·”m"k40Ÿ¾>×û^ðÇœÓôJ?™`+õ lEžÝKK%ÀôŽóYé,÷ßÁä\é¶È]! 9ˆÄÀ ?û$v¬ä¬Å ™F ã[ `ræ@¬WÀÈ#úŽr%|C³š¿*Ʊ½p½Ö‹Ô;2Fîã ¬W.bÚÃ$7Y+k7Ô‘OÓ]•d¥ªSޝ*´·^zÇF§§é⎵L–ò:}Ò>r¶­-Û°‰4‘làÝ0²xß%C·Ã|0]Ü7ʈl5Ò`DG>¹áµÌÙQM2zË EÓé1µ`ÂUáªø¸%´È‚ÖVMàˆÔÓ×R^ ‡¦ÔèX ÆÑ〬ʎ}^Ž1õ2gÞ7²¥`Hœ3>ìØ@ë1½›ÇÓÔ^‰ƒ€U•DÓjq€íƒÌd½µoܺæF‰ŒGòÑâ‚|Fv$ë¿t  'ûÙ-q£aÕ°à£KÀ›è«ŽªßUd²@J‚ct¾ðý?ZJ¶^Uß+™ÕL¶ ²ºct?d&µôÓG&bä-ƒl €²÷‘áÖæéØ>)õfµq™°M`=‘aXV¬d% ®Ìk¬tt×J6b²@Êø+ü3ÔØ†i`@—*ÐÑ>¾ZuzÞþýEϘI91™£‚L2l gVª“EεgÕÚåÄ)³µƒþHÏ G-Ek„ñ™;6Ë3¶#LÀY°€Òªáçf4½ÞªúÑûº.¶9ïvYµŒR`ä•Zfÿ?ûì¹`ÍδfÇú‘ôݪϠ-ÉðõÒŸ ß?®T1}Ìmée{â ÊM †ÞÇ`Jâíà(ðÙD²0ze‚ö!ÛžôJx™LãÜ|ÌÈ®@ˆ Ó×ÂM`T10\pþrç"‰ ¶Ž2`%Ó`ĺ`³r[Õ1Ám=7™àÛJcÏRI•ŒÇ4"ЫúŠ÷[ÆõíÙ5É|jŽÈæjdH£äHYu?B û…¾^‚6‘‘Ž1LØÊ…߆Z)gšt4ˆ ^¤H 8ÊVîH)Ãø2Ð5­ç£Wȹl«2 ±Æ¾6‘zÝ]N0‘UëaGd·hsGκ’…ϰ/V¥ÝbUŒ’c€¿AÂÆW•[ ïoÿŽvXïöñì«‘ŒFèí. ŠÌy÷í(7—fVi”€·kZ¸o`ƒ2Ù7ÙцÄõæL)6BÏ ä\Ÿ«ý|ý2§LdB“‰,Èø4QV•‰ t‘Åõ«ê‚ö5Û&µÈJ‚î£Ïв5xÒ0j駠ŀ¾ 4×õü~¦‘óDæFïVŠ—Sþ|£Œkm ªöŸY™¸f¼‰Ítá~ŠaLÑÕv…íðQµdd·†»5ÁÓ&¬ªæFƒ@¡E©÷”ÚM5Ã$²Å<…R‚ãuÝ0xOŒ±gSÚ_Uf•>²#+-x9[<à Ï .'€û¥D ÄGæŒ_Pö&UÀü›K¯L®+L†¶?9@qûÎbŽ0O&Ú&VÍ UUœíÓèg-éUEædZ䪔bWnI2;ÑTÅ/r“1òpG8Æx|>ʽ!PW2šŽ«wϨo ±é0²˜'2,+ukod/€ir&4ÆÕÿ]w³$[nktÐ3‰Ï)#)šzÀWçÏèšÝ|™~À¢ÐáááÀÞ™Uçt“ì*LUa}ñަ¬éÓŹr[†²¶ÄÂvÎdªš‰»«UuÉÛV¤WˆôžF”­»UÜŠ_u[ÎeUUضÁÂu™çls£ÓÕ:cå aðVbYvNíOY¹Éº«. Ô ˆçÓ}âGÂÌx)…¶l•7 r}c…:6Õ–Æ è‰ß&¿–z(XõµVŽi +@ÂÕÂ@Ï%±T‚ esF ¶Ä™K¶Rp%V&ù4 FTeíN”DbÄ•üZ"óÉ9+µmKÙR†­Uàyiá‰×HyÑü–êÍɇP››®iO/ÕÀ“ek](<ÿ ½²ÛýóÓ£¬öb½æ™,Fƒø4UՈƵÝa`ÊÚÁ L,o¾ÀdÕâMŸU…RaÜw+|NøýI/[ }ÐkGcm;·ÈFÚüùïejÛ)تÁŠC? Ô”ÅO/š–2ðêÓ¬WgI@œ-ÒØáŽ k”\aðýò‡]>¶y¾nô‘¯‰Ir°öƒXªÖ7’À  vÄkë^ ¦SÐcláü›$ÌSJl¸.L*·å`UÂmž:¶Å9SªeI³ÉùÐÈ YJÛdúºFž˜†Q(eUpW¢’l¥>µkÈ c¬ <À¼&¶ù§Ô‚†­!M•[’íª»·ÎÒ<€Ž@\£L2—ü‘“EjAsæ»Q¯j)UÑ“ÀHH²˜4­‘4âõ‡r?×9(q|<óº`®ðs®4š îŒd5³­”h²Ž40^w%j­¢ÃÒÕö>`dóf›çZ‹œJšŸ².Ö°Öl)ÓÌ$&ÒÝO%çå»× +ºtîÐÉ“U¤,ÆÊ¤wF6f}eC’É|>ôÊ­²‹ºdeCr£± L8AŸF oŧ_az¤Jm­Äj¤Æ³*l›CšU!(K/è1N‡,‹ Û ˜@Óä¶V tœŽà¼<ûëÿu×ë= - †U¬ ™UgЫ7ŒjoH8²ì«7äÌûÓu…¯ ÜY”W›fnm­k`k2…€!1Äv.‘ 1äå>¯V RS%³ÂÀ”ñ¶5ª‹- ´W[ ¦^=r#aþÊ1éÛfØ<4¶™3=[UE2$€¡ÉÁ¶¦V!ÅJÖ)ˆ ì˜«Å3É¡Z)‘}m "é‘)[cô@ëSß4xå¶²V?6˜ AÎÑ•ŽÑ]¹*b˜@JÀ•ÇÛ n×ã<ˆ4W{ÄﶦMÛÇܳHÓs„Ù²¢ÔV…R[ ´#h¶^ kµ>×Jl­™4F„™(‘µµ°Â4h¤Ó"çL:ŽÖ”>s« +Ûœ‘1¬% ðÉ™RÖ$dž”­' 4 ð¶þb•˜,¤œÉþwVx-¼#cVÙC>Í¡¬*>¢—Ÿ&=ÀA¤È`†ÊÕÚrk$nZXOÁ³Uˆ/•F–!FŠ’-Ÿ¬®öó°`†@í¬ŠôÖRmÀHfå•#W‚¤1€mÃ4Ùð3Q–â €©È|ÜÀ„ÃL(wF)%IÉÊjÇÛæS2ÎÉ0‘ º½ú,§¹Í?/FžJÌ ;lVpÿ§³¶Ú]׳äÃC™! º€2fM—•â–!Œßû Œ?ý¾|V¶À¥Ïð²b«F¸{6ƒàYJ&¨ïôúîÈ9¤‰·ž'z?³d¶²BXðÑÅ–&€ñßéë‚@*Þ¡¤„.Ž™I g#[iTuiøÈ†Ì¶TOíŒuß%«¬¯£”V2“88,®ð³Ha¬²b «¶ÜYÇl Ò^«#¸„ —­U\›s Y[gë(Ç;ŽÕüdHUÁ¾ŽC„­ô|0µPÐ ¸m€Y†°ˆWN¼ª ‘˜ÈV¼Ú×A9“æf›e³yܽ®¬jçæÞ˜œNσ8Ã}ÇkÙ€u©@¯S¸îM‚anŒ¶V×e»—m%ÛŽÖq Ù o*äJàlÉDS©-R&ÖNvó«²µ–¥”ª pQÙ®WÊÄÖ@í¤¦Ofí>#eëÕ³€76,´«ûœó'SÛÕÁ"ýlKBkÊÎkň rÀ”Ö†„“M™†ƒp(—,VT‹‡‰cÓšJ$óæ‰žL(ÑߥÁuÁÀÙVRJáju‘RˆI£‘H`mž˜l™Ô¨c[;b†F"¸£‹Í¤9k4["qÉ&z•§!Ã7TQ—ïîóA¶UÒz|[„+±fèhç¿z7XÚZMsØ®VÒèÍjÛpÕÚÆºÛ/ÀÁ*˜™¦Ö·ÐV(§¯5±µÈøù§4gCY­­HïD0™ðozpƒñ›Ö0l;]jW…±µ¦¹ôçíDÆ×Nù®‘º#­éÛÆXM%êÞªïôJV¤z]bœ‹ž ën­ýˆZkÛÝ*RI—À–âd’¡^•Ÿ7éÛC)eª®´ d’¦. Ï`BÀ­!3Á¿ž07@ó™€aGhf[Á³áÉ6ªr[)?ª †ÿ®µCæPV “4Œé%orXkd§ƒë2>âŒõ¼!‘ñMbU+J@6“pg¯ðš}^ ¼Ž)ûP˜¤aš`+[Óòt ¶°w£í«¬E«¦•×=óĺ«ÅäÜjK_­‘Œ'´Ãp ¯–8ØôVµª8°¢Afø;l)$F!ÀgR#Pk•*ȺÙúb`²WùHÊd45Ú ¼²æÌªaÄÌá4—>Kæ­¯U‚ eÅL†é]©i°Ó]íc¬¶#yfÒªÖVÊUÕ×PØ#ó†UÝU¿OÐ`ºRúLhŒ'§øêɘ,6&ñë©„^ êB–a<ìê„óV« I&b¤<ån&ó”ÌmëR£[}ãÕ×j›¬Ö1UßT@Q#X_nBÓ<¥x&ëÚÒ”² zkjªpjú†RÜ¢£¼+R-e†¶p—`xWd…gŒZ½¶»´Y Ãá ±Â<{ ]¦vñV¡_´Uެªk‘ÅÈæ¶ÅWRÊ– q²2?ÒÕ¥'î‰óÙ£¡TR>Á¶9ßüçG$mþ óÉy3ØVˆÉKõNúÁ³" ží{|‚4V‚"fnj3iH<-l³­ __¤ŽeáÈ÷Ô§å š@ÏÞ°¬-ÀY°HÝÓ¾€Ö>/kR¢*sÁon É<¹~•$Þ/ ML¿ö³÷Xo†ù[Éfï¾…+ÄH [ѶpÓN(—êjbdß>”~“ë§H媔PâýõOå5ŠGöìOûïÍàÉÊ ¬8XmÉà…-«z)¯Lëz…/Cß´H·T9ŒÌFòÁh$8”R )XJ-líꥊ†²ò°›¤ÄúHzÛÕâU!'°­ =™­1Qy†)sÓåC–À*æ ~}/Øv9ñjõMØ ÛFÅJ+CH’‰gºbà ìÔŽßØ4¬Ôn=Ö×üÌw/G6½nò×W!£Øe+¹ÔísNQ;“˜J‰¸‡8§Ev"ŸˆJbzéEÖ*åUJ²m2zÁOÜ=Ⱥ“Ä4xÁÁ¶Ùè ܤòx2Y2w+ËjÙ²xa$µVâÊm…”ªeR»R”²ªÈôâé\½MØI3d¢V¶ZÛNÔ$V2¤BndðÌWÂçÄ 3…™4ƒ¬PK %¶ï–ÀV$ShqK=_URVN†!ëøøec2lJ·‡ÉÖz¦¹ËVTåaSYaBþ4ë¾ïÆL(»±Êûó³uÝùÀ(™hXyƒÕÔ# LܨĔpµVV;ÃyVõ–H1϶÷P°*×Ñ1eáõ¢÷†ø˜à“½Ã@`"®ác6IžüÝ?¬Fl'¦ü]—A3ÄoŇVkÛÌaëèómwùsÈŠ@ÓðÀ4å £¦0PXÇÄÉàÆvAóf9È*ù¬/±›ñ v!4¶Óóïê4E6€ª4½C¡V_€€R¶"ù -óm2üf­Öjå@á·j2zߪý@"°u³ýD]G¶ÚoÖ­«± æÌëN#lñ ÚÊV$ÿ#ºÛ΋ÔFZÉ|A'n ë®iw¢Ñuú|é$ÛÀxA‰±6-¦Žþ]Ûj”ÒåhW¡TMÕÂB!FÀÈñôRcµ-l‰aÞUØ"Ý@ OÝ‘dma3ðÙEÍHœ -¬0Þeö_¨ïø1¬/^~*©©U¯p€6L .§îR¶}}`RæY¡µŽ9Xe,™ZÀ«íNlÝUå!ÕC2Ä¿|_c[¡M—¬n†¦¹Úϳ#ÄÓ©9ɲ0d+g±íNJ!U…]Š&Ÿ¿• q©ªhgQó¯W¸Z©‚9@“ n˜FåÃPÉæétdµæ™yÛx¤PÕ ‘œ=,VëuÛžã÷m¶o%ÊñSÂSñü1’˜g$¦ÆF&¦”"¦Á4 ²,ÿH>"\mÊÖñ¶j­âU5 ¼[}Eï§TÉFZ«²ÂøŽÃS¸™c6C"s›s]fHƒµ³ˆ14½Z¶½-Ý¡G€©MzŒZžsn0O­©XI‘‰J¬ÖÚ¨”Bëâ°žì¸üëãcÞðÜ„m{—Ôö–*Áèk[ ÒªŠ²36a[)ÛºçòýV‰5 P‹FµU®KׂÈÖœ­µ–Õ…¿«îÒ´Ø*UmªfÛVU…V)b§îec›>+[¸ ¯…•ÒüøÉ*Üèàx…Ö×~÷ Õ€>¼¬r°ÂÍ– ôîÁ=#2À6[ÀàÉ¡-Úø¦õŒÌ@S¬PvÏÆ+|WÛxOd¶ui<«˜-¬<¸ZëBŠ8+ ­[‚ÍlÓ´µjÊÏ VeuÉÀ*([1ùïŒJl™äC™A…º ¶ŽVAS÷¶͉_ä‰7Y³ÕŽ^–ÒV#IVªlÛx8mLÂÙ‰L sæó†Ï$[Qw«IòTËÄØÈpš²j‘ù”…ÝZ÷¾ l² ¸Õ:qc“W›=s|©Ü2ÄÛ≗¥WˆpJ½bZûë_ÿZƒ†èAR ¾YÛ†[ùίë€,U{iŒ!l²¶xPŽé¡É( dóXSûTøèJiZ”µÞ|þ¹’ Ÿ®@/€I/•SL­1€ªšÊSV”òKüúOåx>¨Ú½µ ÛJÕL/Ã/…o‹Ž ÈÖ0“¶Ä4y®+[ž]¸›o$š¾ÌFÉJÀ›(æYaJ«m½˜ [d8M¶Öüi´ÈÐl¶²J`!¥Ö¶Àl»Ù27àøxȤ÷b\S‚HŒ^•ÂH7Öíèë60²H%¶Fð×ÌxLÁßÊ$}[%Uå@¯Þó¢/óÄ(W¡-@#lcÒÀ¥´–Er+àšZã‰mUÑ  .ME÷g3[¶žQ|MUв¾Ö3â=f¼I©ÜSî‹>R&ÛM˜xµzé¾ OP‰¬¨J_@È"7F€þGóMXz2£2Áœ߸ö¿>°d •Ë«Úk\üüa‚˜&œ±r«W+Ò¶IRJ)´ê…Û¶â7¶B3éÕHýšE@œ-¬D¼&5R%k5ЧÄd Øâ½ò».¼Ð(M…ÖBŠß)Îç4gÛSü|wm«|¸ˆu±æ¨`ŠoóÏ7skåea…dní-5•,̧Ÿb0s¤UISfKÆÌ*@ –ÆÛŽwo¤ÖFdˆD@k€CÑv Pðáo k g>2XÛ¦%ƒŠRZHe˜ìS c"mrˆi]Uíè}K{É)ý$ÒQU¯½Z «m¤Ya`µˆ½VØd™ðô.Ÿ@”­9ÉlÍ&Eüö­‘•¦ˆµ^mY[¡œ&Ù»Ö—RࡇM•ÅCÀ­¶ ¯oâeY!+¬Öš×ì¸åoO#¾r­z¹+,hêÞI)+䃙mäu:¯™­Zš}>x‚&Ä#÷á’²• ²BwŒTcÔb«T‚4L„BdãÍM‰”C`?òœšrÙ>Î.“ß »«Úítdbž™¸=$%™rkÊãÛμÊxnÃäƒ0ý€Þ÷èç[hó¬Kà·ÿú¯ÿrãkÌ(kŒ`Š +`d[c$† ì»N™Àá3éç7ÜVÖÍQG>î=O<²^SJað˜ü­H…[…¬Òô¤=Î «…+wä~³±]£|8¤ÉG‰Ð¥¦Rœ¥Ê"‹dV[+Ïøüc¬ªðïg)%ÿš6§•¸{‹·ªíPyºLL2¶YÉâ«j[¡ÜJ¯ *²ã85qµUå@#0ÝLoÕ‹À:J‚ôl=« èéШJxè‡ y¿·¨‘*&i ŽJÜ«O&ªR­HU­Hk[¼Û0[«^ »[Ú*òç Ô h¤ËGÀ“¦.¶€¨*LŸ ì›ÊCÓ½iá®æS—Ês#C6y…Ä#T’³µvçH÷P‰ÈVŸÎóì‹"78M‚œ´"n6â€^j­• «º.VgôcÕ×Y&}T˜>Ÿú’¹a<’¦l­ ™ck%#îgPнHÀõøõ”uQ(½dé[¶ ÙÖ²ôÄ9/µ, ‘,ÃÃ+©K³UR÷ÈÓj†J†¾F¼)çÈ~û¯cï›lçå¶7¶±›°IÈ5­ Ö"Æêx àfSˆ†ïD­ÖØkСǤV‰¬rQGÛüŠÁïBðJF/ Ö#Ô"Rµ8º;?1Ù¬d¦Y­ñˆ‘¢v&¿g²”ͼ-ÁÌ9T^•­sajª$ÿµN–•µ¦ù§lfLW×½ R‚ùAµþ>€@ ¤ÔðúF. ”b(*lBƒÉ6¤TVuW"Ò×Ñ¿šâàÈdî¡ÇP#†RȦÍ_Џ±a¤ìR°À+Æo¿Í˜S˜s÷£j¶Äï$f–ò¥yÜ¿ßhôb2†úª%ó"¦Y!@&e•r´œë‹7a}ñÑAhÖ‹ o @ÔŽ­’°5s Mž]j}KÏK…¡‘b(u;ŸŸ©+Š–M`+ xº[Ø$¶N­¯-€i%‚OY ß0xdzҽކñ4Yñh¬²ã“qÆÀ‚•À䧯ûM~~lWe¥¨)@/ÛÌuÏv…lù¤o¶ÄnC*|Æú*OwX 2]lw™Q-½ZÛ¦ªïõ;ÃÓàEþ¹ÁÜÌÉ6¥ò÷6“N·—-=+Û ²W®i¯öœ7AÊšbGè™SF²ÅÿóŸÿäƒl˜²pâZXm×Âui*J<,€ô@ÐÀç/hÝ2;  Q×FÙ ‡d§RJ¦U¢3wMx²uš£5s«^ýžØê0Vž”é™ê¨Jh—>Ò¨]„ª‚'0”.ð’±U­_ɯGK,k•½ÕHñ+±NœžX,¥ÆÈ2éŒ]ŵ56MzÀ„9·yJ­uâ&Ô… ެœRSãæû~¼ùs¢†¬Š çŠlë(”™Ì§B3CÊÀ~93Œ™™#xÊ&äÖÌÛb8#•7*F• a.¤f’^ @O“²ãðÁ#뢰°5˜*£©`e}ö­•w´™¯5ýîA_%ÍÓ0V·§JÓf0Y%­ÝŒyXÁJ`úÖ4e9̰“Ú ¼À4qäüÒvb3ˆ ‘R4€«ðÈø0>±­ñ F&˜I UV[†˜Þ¦Û2°Ò„­G³5Õœ9Ô"«S|ÃÖ$ÜêÍQÒm$€KÊš ž#sÃk$œ+gÀ–L9Ê[²µàÙòMku®5 dÂ\ Obkþ†F$ ÌM6€×Ê›“Y£Ö«: @À–¡*& ­¥¶b‰I_Š?,ŇCµ>bH)‹tÍC‰„^xX¨ÍÐgG­­Â>Gý‘oVº µ Íf #3´šç ÏÒG)´+Êòº±<[{ý:cz|]ˆ­ÐÚ`dÞ7YÃ0^ ™¬v¶Ãx #ИA• ([IŒµ1r  ­•ä°ò&´MÌ'ÜAózr”›ªZ2U)óÁˆ²®ŽŒÀÉÊÚ„HÛ=8eí¦ªR¸Z¤hË  ùqpþÌÉðVƒ™V o£”ðF §¬µÕö4»£* mãwKðW…OK5¡Uß°vø”}@2ä¯/`++@¡*a+ðæ·=“}?ÔU!ƨ2™UJ£[k† ¥€YÆ– Fùº'h‹§áÃ0Yw“²ñRuì€jû€ç0YVñ•ÀZ(ɹ‘Îè÷5ÃëÅD$ÀhGöÎYßšs2X”jN[àób¦";=jl«+>&#ÿñø»s¿ 4„µKìúL8Ô õ ~%v)jñ=¼ÑôxXyíà"ÛVBÀÍx|Ó5Un ø+½Æƒ)+ñºÈªEò·ŠôgÐûeåPd¢ÖÄEbx…˜c÷oG`ÿ±¸µ0+S  ÖzÁR5•RØýÔ·,qíZ‘ôÄxQ/§@šß‘÷`%hòYaå ¥^ϰ¬”/ÖF¤Ì\# œ%}>Ö†1CL}#UQš§©ø½€ý€J™AR¡Ul˜¬çeNbï›Ö°rJIÆÓVkÃ_›ÓZm扭Rjãmð&³R^;«Òš?mOÐv×]‰1„-C+œó:xÏ®9Y‰ô¹ÁÍÏM*‡Ö3å÷‡¬i+INÓÚÉòL8“Á *Ák;¦µ¯9$^9œ•-M­‘ݼÀ‰º½œ5êÒlv¢<ëîøB-7‚IaP(!`‚ì­ùh×7@LÐ)è¤ìÅ á3·Óæ>zcàMh `Ϻ»âP¤ÏÄ ‡”] À+ÎÆ$cÈ¿Úx[zó#×·”9‘ÂVêmGÎÈ!HOŒÄtXcà»®µ[°J‘r_,µˆ—ê¢ÚVÞz/ûÿõ'1½liº=LGÓ0Rµnr%€²…-òmŽ—*˜àaë 5Íö-=bkY«*åÎk6µJ€>È™Kuº|h*¯ܽѽé{'â;xcWBÃʲÖÌ­ùR­^x 5³u…9ˆþ°‘aÖ€JVÂ1f­Ã)ÉRVR*ÒZ‰ò4™¾m¥8X'®ÏG[ÓXmËæ†a8©p]b”DZ"{’5 ¾CQŽÇôv{=Þa0”žÑjŒXßmÂJ:]Êá¬;QøG }ÁëkËÓ j1‘ý„sè ¶‰Ýfz@ô1d¸—3•¿Up3ØŽ øLø‹>ì| ÏL÷íªœÏ˜<ÛšªF<~½?ß™¶3¡ìà~Gª 1žÆÖ`}wÁ¹½+Yzc§¯–¦.»YcÛJ¹g+gâÎè\R<‡m„¦y[½8ˆ‘1Ùú&!ÈP¸àSy ×ôó—7nÕÏ3eÕc•]¥­T+R§‚]îÝBcÕ)‡C»V;r2‘?À¦_—þP‘CÝ›.xdòUÍÍq¯‘jTkKìL( \/†Y5!\ëªd×4Á; ¦@u…@žH}9”"¦„­Í#%ºÙ*„Ùj °åðÞRtXþLú¬VÅ!+)ab$\Ç0g[^-[0ÒÌÖ ‹š6ÏRkQ|“0Tb˪›éÞ0”"ACfr›|~¤á»=úAw‹iš0·YÁdš²íòµƒM}ëµ,Ù€®EJ«ÂFê¡sCúm˜@J«ï« Ìnȶºç©`56¨ÜÌ9—bX•4$¬°ÿ絕c)èk½Ÿ îžz]¸9Z[)…AlÌ@žâ{«²xLÏ0˜5s§8cÀN„Ÿ³r|çŰéÂJ£?rǨ²6­òº¼Ãô›ÌV²Jb2á†qQn S Y ÆxšZÉŠ²a2`VRýBF/ðœy®#ªª…Uv! §¦‰Ãæ,ÜU&&AŠªÚ*0Jz'µ¦É§r+·ÂÊ“YO!™{¨ é\dc+%1sÜX¥”Rå~(i &8‹p²†‰'#Ƴ¢iB«l­‘Y‚¶ êÛ0é³’-”¶ÍÏ„S‹ÈµûK¦´M°Fj#WGÙjÍsnç~Fž¸™Ã ¤É‡3€üîÞí¹XÌ~®×EaJ©j[¯åY´S¨5+šBmåÄoÈv(Àð4 9\ùYðÖ1eÝ ö‚©ÊÄ/š¾¢wvb2½”p¨°ÖùXiÊVQ÷°¯]×ÒÝ6˜rV«J©©-YŸýR㼦²xÛbÍœÌËlÛAOŠ8¦ù«µ¦Ì|%†)“…UG±ªE½N0¦’p%ÈSsßYd|+ÙT0gzÄx¯ _»WFI&VÞëg;¦^Yu9+™,Æ$Ú!‰U×ÛÁñ5²l¸^x½Êò!˜²Àˆ¯W«ªœ)s£ÁÀðB6Òx ¬QÊ¥l9à«·:”UË ¨©mÓZž˜À c¸Õ+`åÜš‰ñ˜Ìpúj‰YÑôgÝ7R[n†—)%ÛHÖóc@Ht ]FNÀÖµ=¹ïÏ…Îéy¤Û©-¬V6Ó3¤ï§~ÏÃI0N•¿5™­ï”]+ža%nÄ–•mc—í¦|iªÒ±FRù[«jN+½¾”Þ´}íÒ›Ÿ’#˜Ô7·Ö.M–˜ÉÄÖÙ c[ÓR­È€Ôñ½ï.F¨Š‘ÒËJŒÉ§B¶=Ù¾B%UuóRÄoGd-N¿LM’ÅÐ׫}OÁ“Ò«KÈ8I3D¬Wyê²{ ˆT":Áù33Þ©µ#†›Y•¦pk#)ϤyT5€×²Z¼PÕ%—õªt?¶9ÞzYõâà*(ñla_–›™9ÛZ³ +é€Z©œQ®8d@!\„;¾Ù¼{†'›™~Ên¦` ”Žþb*Ï¡ZYaBÑ`(ð·uÌuo|V¶”0OkO¹¾4Nlž*W‚´jdRGX‰P><1’Þ¶vf›,g47JÁDªB[`¡¼l%†'€³UÕóÅ(i¼sž· MÊ)É0kZvžKQÂVJ Ö°S;l#m¶Êi´èau«T}kÔkâR];[b‚J”×·©ð4Í‹†ìÔ9·bRòo[&0F!ÜAL¢$ çn©4¶0A4Äi2œFŠYS`CÒÄ«´ñHµR9FÓu0ÐEq×àסµ–…óo¤R‘VÚìã“›c6L[J©ÜÀß½5žl©[÷¹ŠdZ×ݶ“ÚyÌÖ(@@ ÓÔ/îtñVÛ7;>Ðq*!›xL7F¬o‡­Ä6½‘ ƒl°x«ó(±ÚöG) É­p?îÝ9ÿa|÷Íàk¡.ùÃ;ÜóÚ dµã ÕÚ„FJÀD¡ÐK-2qæ9#ÛZ1¶(>?'«¤$´±~¨ 0šIy-h({Ã|Æ&3 Ys¸ #Õˆô‘ø~ß*›³•Òšmº” Ï­I€éŠe}¹xB¶àŸ[3#Fª‡Ê¹iÁßa$˶·Öù¨ª¶Õ6··ÛdRp³av€¿P%(‘&i¤:"iºØu!“µ%†ÙÚºLJ@0¬;†[…ÖšÞ†g‘ñ¶À`²R+˜» ×Ë\»LHu–¶¦+3¬WÀúع”[k¤ÄVHñ©©”¾ÆØ%ØN¹ùµVh+€¶µÃÍÓjŒGÌÐVÙSv?K5Æã(µñŒU 2«`¥Š` pkš3¾™3„…Þªü½7̲ôi4Rc€î„pEªg‡«¢x¤ò”VÛ¬"Åa1RB‰SH!ÕÓ73{1ŒíËŽ¾WW÷L0ul[˜€¿µß™Ó£vH”¶BJdn+U–aÎWuxc<ó‚&±rþ«gdzaÈ`J)`…ñ˜kvÜ8WˆÔˆ†³¾Ÿ²;3²@ÊÂ@k¶V†˜&´M€éñVü²Ý@$™SÀ„y€ËA¶FxÀÖ¨%ÜâdH-^hW¤Ùé ç@,h”[1¢-¦vÀbJ)a«K÷Æü-Ç«JnKc|×^‰- V¹5¡ÐÖ S8æ&OV-L³F¥&¨Ö–@0Á`> ¿©?P4Šw]j»C ·–åÜ×…Ï‘òÚáwÒj‰ïgfX˜\G[!ÅÓÖgªÂ4H)Ê&MÓXñ4Ö°•IJ†ëò1“}÷bÔH¡” óÔ]-,EvéÏ‚c–e«Ä*¸Y3!Ž´Âõµv˜¿ÿýïñ…R&´ 7ìiÎ+gèw™¡’̓)kj•Mpì¾1 \Öʶ{PÞw£1²ºÕŸ«V’ÌÚ¨ÀLÂ4ëŒò}RŸ¶ ¬£ÈÃ[‚O# +lKÖ+ZÇqïO—Ö¨ªÖW9\ÀîD¶1‘Ö¯üóqKcŇçc­Ë”™l@›áÍFš%UµÖÎIÝsßz=Âv3 †§·Š>ì²R}¾ö,dñ”&dzáòmßj×Úѧë÷ûªg”¹Zζ­o©c˜óìX ‰>Ÿ+“"@’2JÜI¶¥éšðHßÖ|¬È~#÷>)÷ÓI–s>:ÚŠZxXðŸ¦yl[>Ý)L\w½l­Vµs˶F’R«Jôlü7TºD[U&–UË0­BLÁª1¬¥êEcÛ¯}:Âü5U› ù‘fÃÛ’Y)u´& ‡ë«K˜:Œ B)!Å©üß×WøùúNÿžk¸v| ü®Qjcã ôr–¯ö\ˆ³[ñ:ÒËÂ:ÚV5ç”M7'%ì˜Ô¶ìºkJ¦‹ê¥„rddLM‘¢ûçæ«_­-™U¤Ð·Ž.î¢i~€IM¥Ò°z‘8xšR~íNÆH‰Ï§Á¸ákd嬵Ôôlx%@­ѹ00yŒs5miŽúþÖe<-º²j¥Ípµçެ»ª|xª’꼬`YÊÚÉôHa›I[8]ÀÈvEk„ÁרõúÚŸGF`àÌYÛ¾£v™1µààx.R¬:iž òáYw2¼èAX-M+° ðV8e ½B˜¬ºRbL)d=0˜, ÕkvUgaÒ%¸/§U• vºüÌ­…™Këž™ô dy à4¸cªÝ6™5ÙœoÝ9ÏÄzÉZ›Öq`af2¯iUh0¼ªu¡Ig)L‚`üñ­ à¶ø"F¡’4ßÌçý4«R4æñM¨ S•9 ÐdVO*Y[Ùj¥ LíÈ<þª>/¦Ñ%Ûç¥rUÊu!è3Õ¯!™˜ÀÍ;‚!‘  ©F 9تjÛh0R€¨¶›W‹‘Úä >½lΕ0I¨\¯²&¬{“ Éœè³ ‹ñÁ÷­E2Œ²­/C]ÞÀäŒ$®/Œw¢¶j @_ÌpZÃ+áJ“©å å1mUN™@Sëw*| ÃÄ m]d[è›ÞÊ–(ÞÏxÙ²úæO墪ÕbhÚÂdÊ+L #™ad7 `BÊJÜCŒÂ?°mŒuÊ<ë¸ùLÎÍœ~²H,’'²0*‡(`ëÔ4JhÀÛ…ÇH1q^¼@r@b„”m…° ëÛZu Ëv¨dj…¦¶ùØÛRxzílùœbCìê%2jea$ðÑ€^t¬+T"`ÎxØw™_GíVH šŒÏð¥¯6²[@ä©/kLI?Ô’ xþM‚Q˜cë*z¨ž<}WO\Ä[Õf»î:¥¾dpb[ÊóÌïo“‘L[¹e(•ÌVÉyHßï¾dVÇ”%[I FUµVÑ% lHÁ„ØTo‰¬îd²Vµ€È¤Ö×HøæM*'VŽw{×à¸å“íëûÊ2) 4Œ.|27*,èñH  ÈÓ‚[®WŒ•ÆlÈ+?T´&ÆóÌÖW! Þa{ Ȥ*ä÷h:¯I”3ér”ô.‘ùC¦.Rµ&ødÕÊXlyÊR­”4œ‰;ËÌ1¢9{^1 …œ# IcàׄL6±îÑ6ÏÎÈŸ‰Ö~˜d[y ˜4p©ÆÞXM&åóK/Ìf»ÂA3(!(»1˜kÑY€  <Ž÷Î˪jæ¥dabÀ*¸#óÌ<Þ¥Iƒ$ÞËÐaÓÃ"àŒr»Àm•«ÝqÒ'£Q«Ñj+lU%å8®(Æ‹ç±ªâÆ¡§clêÒÑâÓÄ(áC¹î¶R rk2Œî²Äv±£#«RÒÚ²’¥é€€¨WB#eEJíÁÍÓG5Ÿ4†²ÖkvºÃÍŒ©Ð%ðOЪ\È®jL CÛN>+—©‹y8„iÝÛ«Iìo aÀVÙ ‘ ‘dbcÔÅ–,ÁbL#ÁÆè~Râeû—ê…énm{è¦ÕËäu—e‚ñI¬üŒrŸ‘­àL@ pÀ$¨\ £i€¦@”Â"Ðj¡P¼ÙÌ1 Òô& yºÀîPG€Ò ØÌyvê”HI™À“âFÃßU(”]mJY LYªÙ"eŲÀßþö·Þ_þl›VÇÜ\]Ã¯Š¸'BX9 …Êή #+gDZ‰Í†ì)({ ðo!œy>µP®¤Ö§Áu¶bÒ73+̺4Òõ:Ž”hžãr}f¢<éÔ ™ôà"«Jù­×àó½½ÓMŒi"µÀÀÝÒ”ñN×AðÉ$‡ŽÓ/™ý|¯/« Øð3GvWÜz²Ž)”`òÜ<3ÚZ3·V(1•s[€UQ±°µÒÐÓÀ¿ýå/¡0n uØïS!’õÚÌ4`d·ÑyðaålËjá[ÉÊ¿)›¯±h¶ $ƒ¥Â­¶M%¥ +2g­aÑ@U²fCfn ¨í‰ö›™§R;2U²½l­ ‹<;¬UU+ÀP¤·¥„Yål­ é ×ZÐ UÉV ¤—⌬/R`l­œ§.•L¹-Ì!+úšêh†š&¶4æI ܃µ¾Ra>ý¢ÖYúºÂÍÌeóÇcJ3²UÕ1=Fª™­H‰ÌP_¿ZÈ*¶/£o&×à,4V$ ëÑ0¦5q>4›°çè6Œ·Ni +ÖnûŸÿùŸH†}ÿº@žô9—² ƒÍVÒ‘‰e­{9Tb°f“­Ä¶B‚¢¶¨D6% ªQaß`¶R&Q«ð­U…¼G#ÜŒá;¥/F‘ s!ÛjÎN„áV-=²O±Zždzu@xQÊ*‹ädË!\Ð0l¯J¶©lHÏSU@`´4ñIÜ/Ù0Ík…/FN©‰1[gi[˜2½s.Êm¨Ú›™UGË-ÆG¦BVœ _Ë‚&ž,š¡’¶°¦·Z\ùgªðÖþ±UÂD­ö437€,&sXÓaãûÀr39™ èhœiÞUЉ•LJ4®6°Ù–µ²_jŒ¾L0ÂÖºû´-nò# 'HÜÏñ‰û%ž¡§F†YÓ@«Ðaè¼Í µèU‘êáR2lBå>qºÈº[Wª$œìët~•”BÖÑjˇ¹UIJBü9ó ζx×xåñRl»L†Íó*y ÊÛá×Nø4•É{Çl])Ì„+¼@ê…çVv¶µ«jSup&sVΰ3¹19ã«bô‘TÞ—žvÙZe½VÓ Îj; ç’–m1 Tý87ç¥Ç[«UU!¦Bkh’ñ'àÐHsóŸ… ™AÛn¸Â±ÍÙ6= ÄJ&ÊÖèjϲ‘6'PTÛ½aøT•9†•,ÈÇj°:Z)«ªœ8€TÒªÄl”ù7'½ª|èm‰1‚¾%Æ{²óÏœ¬™ DÎ4E˜ìNK L@¡ˆ”À­@cä/ûÛï¿ÿ^¥äfQ«J“Y -e˜Øæe- ¨ê%Ãøºa»9ú–QžŒ PÀÜJðÍÓ™á&ì¦l™Ãz%–Õ1µÛvŠ˜²>Í€ôÁ³6b&Â_ÙÂLij¥lBXDn¥ä_#÷I °™ÓÔî“©)¼»‚…òë}þR­u©²Å&4¶Z|2…°Fò4C÷†$X* qÒXë…$Hƒ1¹# ¸+í®Œ$U!¡vs è¥Ü”¶ZÀ#ma°²1mõ]`*?“ÝÇt«=;ÊzeB£/œ092< ꕾZLÛ²‚q·e#1<ý]ÀŠ¡kñʹ.-òï`U!R‰íZÛ ‚¦õÌtz¥ÇÓT‚¡™ÐH àÔ?ÈšfH`«­/&A>&'83Ý_S*OÐ÷'CÑ…ha§&(¸E2²’aÙÖÀ€[m«–@Õ=ÊY”´íÔ1VÊܬ“sg¿ JU¥¼Ç C H 0=žØ‘;> ›É»"ãi<›„•è $#¸òÏG¯ÂzY….¶Z}®KŠl­=¿Ž\ïójy w(JHq«ÐºT}mšÄ¶â–ž%ýË4gâÉ"{ÿõ»·:Ja> OÀ8mÇ„{ßr Q˜!fVd°¬#¿$7úº0$µmÍaØV*r) ÁÊVËÓ¶ [iú,xbL ^ ‡]ˆÖ~qôŒêB†©Q`[$,h`nUé¥KþlÍ@ã»Èš'Ð@Yw¥|7F[‹ 37m![ Pþ’x,TÑàE¶[#[§IfÅ0_¼þ3*ÑËðÎÕ•Úº–^µBC–C¤¶Ö²µ–Dn@Ô²µbTßïg¯Üj„WÞE4‚» \ä¬×F°Å°Ji«ð4û†*] X#Øl@§î*ÈeÕ †V¼“nx í¬UV¼8ÄäV/]€Z[ókÄEÙl1d0‡õRB‰/r³~\îH4̓';mî³c•¿5‰¬m0üÈÖE]á¯QJd€?@¯{ó;LÐÖ:ÐcÈfR¹Ž u_Çù‰§QÊ×Çx½!þ|åŒV§3§w€CJk˜OÇy'4†lÃÔÈVP"»F<ÀÙÍÀøžBØV‹°*Ýc”ˆj›GVèŽç l‰­ÛN€O™s-¬ñÖÓqôUk+øË¥.÷™ϰ¾øË—’UeeXë4—’M&{ÎyO ;ˆ5±µË,«©Ÿ‰ =µ™bþ²‚É@-täÆÊŠáVa§Fz:V[…R0Ï€ª²HLå²xz[QSN9+“KÍ–£Ã'·4JÄ1½‘²ùV$I«­øÔÜÿÀ«µª’‚Ûbl›¤ÚLÒàßKhûÛÿøGo!#÷( *:|FR>?,¼ûÚ(H¡*/«­r‚Èx[@˜²$†U#*ÁÛV¸#aüe+KOÆ Œr!Û¿VáÇF³‘É ²4aÊŽ` Hæ$ã ¼ƒ3©¯kQrš}}Âü³ÍÁŠG²¢pŒµù‘&×®’þÜo{åçAêh¥ÑÝŠŸC¼µ™ñæ´í˜Àp<†‰xGmCÊZn…@ÑÀ fµµª[;Våcdª: 2bLíO © Þ*Õü t2‘ˆÝ’ª“’ד&«^úE2†üi”çCPß ék¨‘²â)exXtÛ,ó¬ªJ©WGȾGLÓel­"g+1¥µŽV[< (mwœñšRYÁ?^á58Çu¬ ¾{Fv4nð²ô4Üj4@—ª”¸UÛÌ¥~åÌà„˜L#«xË뾦Ùäù·­/~‘OOÁ6%7¯«9€mU¢¯51Ƅĕ¨y•u¡§¥8T£™ƒU$î€=©×DÖV/…áÚUØxé1¶®.+[U¥0ªD'µ¥¬m­üз. ›!+|†ÖÜô¬ˆEž)e·Å•”Âälkr+[¤ªÆî^ÛÊ1 ˆîÛ½N5Åo‚ZÕ*¯ª•RmX! F`¬j‘sVuUGö#¸1Qµ‘rKãûiSv²Ì{¸^N[ÖjÉX <}(Û¶V˜¬ÉµpÕÌm»=€À$+„}”2¤=2ØÌœ+DRâÉ`do›s3G9Á˳²Ý L©õNè»TÛœ­†‘B:‹mUÎÎ-å9ÕWS¯ÄnŸHo{Ôß·èBvi¥Ì£W}1jEÛæD¶ÝAâù›Íêï ÀÇ6O†ÞêH£ÄvYb‘³”H£³,²h0YÛ0zµÌ+\‹JlSš¦·šÓvë •ð)*ç¼XwLçb•­”îBÒŠÉH+¦^qà [¯öפ!­ª|óaöY°õÎËr°VÞ¶îp­)1É`%éën˜†§KgiËaþ«”I&f.0“^ ©ªBaâT‹/¤ÊÚ*QN`˜ßþüç?»}lTîr© zØx Oˆ¬¡„¬#q%ë·[[©]¥®¶ÄÖMSŠ'à„fÅ_É~Om …²xþpÿš»&¦Ì¤Öp[¶EÌjmaaŸ=ßk0Ob†zóŸwÏY•o;lk€®®Qâdl+1¤+ª^VP"§x‘ƪЖæÒ§$·ñ9¤¶åÙ¨VÇ‘ªuå3Y#€¦ùWXÏI—Œ´­Ÿi[¼HéZu¯jb-¥•›Xª8”u'lYQÉõøe"«ÄZIYÛÌ¥¼]VV=â0™-2g[XJ¸±ú*Äc’0½®+{jîMÒÖÚóåO&åZJÙ ÙMH37½d¥t•ç†$#(®Íq¶ ËÒ¤”_âCæfø,eFʇ ÚZ)•¬ïµ??–€Þ^k>j˪“Fªù{²l1+æõµí ²p>˜Ý²ÝÏÄÉ84Uξ+¼Q¹xx !a@`˜ç€­P›N0ñ¶R+T+Nå÷”öiÚú‡Z&Ä3?õ7Ö(óºÃÞ‡ÿÏÞ½µ\—IgèKOˆ7ê…OñS ŠŠ¶z=¿ªÿÞñ®ÞíÈœ‡a&aª£"##³j­½Ÿç탣Ø`ùsêË€†ÞÚ­—²ÝlÝyÃ0¬…ª|*Ùœ«Â7a©ÖÄÖjI Xl«W«µ0¹IÔœg¨c™U' K©Í$q÷À­.d ò¡Éßv€€”U!ÙÜZÛÂ1VL„îp—ÜØ4Ùš Ðèéˆ Ó4 CV•h2À¤­U•†½êY©EÖ‹ 7Jï?,øPö¸ (K寖F‰Õ§U †•XH‚¦–‚Ç0¢TµV©3Ó ˜³yÒà0¶ TÞv˜&™*%ÉÌLК FØv-V‚°B|µw–s¢\W2 ÍîDIU“`*Ì­¾0²Fê)HÊ Ká….Âï'aÏ¥ŸÊ…§\#¸Iˆ× î¹Ì£…Àˆp%‘Fe˜&sJÝ¥0€, ØÅõ{}—¦É0ñzEV7^÷ƒŽ5Uˆ¯ÜjH+Ú€.”O^ª‘²R¾0Me…k‘¿­+m¤®¢ò5²Í'Ý•#À‚ÀšÒ¡àÌ•l¤™+¬¤F­˜~$ekÍmVØ–Ú t @½ºŸ ›¼*ó®¸Zšd¶cd9×Ù¿úïÊ(3!ÍÙZ ©ã MEß„Ñ<¬úÐöé%ëUh•êñDbŠ;àyÕÈhÔâ‘dui’Ä›  “Yb*Qž>Ïç´·î<ˆ'˜¸al›¹©àx@•,^5Å{”4È0યðõ“ÞœxÙZÀm»Òœ­¶øjK­5€GêÔˆ8>[|¶ÚzáO¤^€]rÙJhT1 DZ܆ɜÚͤ¸9o“è%›¡¦Fm[vo ¥Èæg"ˆ­ø–&¥ñd[‘{èk×;f+Lbeb¸Õ ä`+Û‘aƒÑØêk›Ãz1;ZVôwÆ×™ô 2[k7ó#Û¦±nþ‚^-œ¡5 •@6S9€± Œ¶…é¶Â²¶¢ìÚ¹çŽÜr Sól»¶Ö]]²”9`2$Sèe°ÒÓ‘«‘šÊA"µ«/%ð¬‚i„.¢- ‡ÄR•Xùð4à¤ÄÂ0Žÿ”)dE/ÓûडŸ[í®Ç!Å:&Ãpð– ótÉUáÙö¤né뉆RÖ„”+@È }…dùÛVŸÞËßœNÔc*Ûév¥È®‚Œž•.x@j‡§ÙŠ4y…+ÉMÇJ¬éó±~œ3eÇÑ47βZ4Ì\Ìo[ùÓÖMJuüx2nóa•w ½¤*Ù0µ¦ÏÓ6†iZ+ÊðË“È[å ÞéìJ$ {iJÓ‚>¨Ü´‡‘€âа!h¬ÁhJï„-,EæÀÊZ­îªàFÊVG…”ª`°aȬÈ4ÕÖ®ZJYá· ÿÀ€•&ó¶ôµ³MiŒü­n¸ÿCl°~‚Ò›M¤œÏ³{ä˜3îûsœàÐØV[d¿kºXþJŒÁXMbk]¬‚†R„/wžoG³¥u±ÂÄ@€ƒ£é8[_v¦‚?PmkdZ÷ƒõ¢„§ZÑ5Ê5ÕÑ1kwógò¥®ÓùYîe©„•<}pgik¶m9ÇPê»B¤@Z•;HVô&¿Érxn i¤2‘í1Qƒ§låלV)¤¯œ,íŽÃ0R¶Ö1éùó]KÓ^ãó4)1‚ƒy’µbæ¦VØ*pǼôkIl£°Zc; ¦Jà•tjzðÄ«ÊëRtLó‘êf0xÆX1¹5Ik%|la&•cÖEªmƒÁdË®un1UY ­ö-DÖV¡hHo \#@” Of Ä'fnzàÜk“äãM3yåz[ó“uFkY@Ê hDlÎΈ©V±x“Ð4Ï<Í“‰¹ls6˜Õ…$XaÀ*2 [Ó[ i] xb¤mSU# à†aoMÐJp“gÉ0«!Eç%~*;ÿYÁnÃ퉚ª•µm WèÒCYÓúªÕQ¨ÍúzYÅÓÓ°M` È=bXùš5?1ïÐ$pG£ìtæÍlxU}=òÙ´e1‚àc*[!•O[k-g¬÷ÇjÙ…Æ#ÓÌ<¥>J2§çšêÕíÐËö'à†±Ö¥Ï -}&j ª")i:?PH [ªê`Ú®ãÈV[£léñ‚‰S4†¦Z3¨Â7LYႲ&pÆuDv-1*>¶4R¶ÏB)(;lâ +i° emE$ 0™øv@N@_£ïZÛj-ELÓ-µ…É:x?™h’Í  ÙÓ‘eXÀ§Í½+²*«ToÅ”ÈBSÙÞƒ!ý ´åйd‘ʦeb`šm *¡‘µ $ †Åîý>ñßZ*±÷D;ÃôÖ)—µ%f¹4À‚½-MΔ]¬Ù|VH}ÚVNœž•ÚRµ¦)›À_ÕV%x3”0"%2Þ6Faƒè\üãièñ¶L¸¥I0‡¶” F ¬ f>«@Jž²­RÅ™ò>qó`zÄñV-¬ª¬4ÜÈÊ `àÆP(ÂÕVÞJ_ÊkϩР‹9« çV*ÆŒA Jyç%Kc-uæ¸ÿ³³VäÝ}ù°(DZkÄ é£ÁÙ=h—›Ôî­±«"R²šÛ&¯©µâlþçW=ó4²9[›oQ¯[32 œÒjS©MY9r8Òš> uìn¤oY>ðŽ)hûM¼>VHÌÁ*0VƒiÄÊ À˜WËû—J€ÈÂÖ^Ë5 ào«ãÌÀZ · ×¥³˜ì ¼œVds"›ÇÊÇjrVþf™¬ |J¤¬5}À@Û7ýïd¯z—ïå´UؕԺ÷¶ð3:…Õ+×ä0`¥4jnVxþ¶j™ó„wÀÄ”‚NJ0>Zd›ªL ÐkW•ÛÆ0iøfk<ªJ@àÐ4[“Û&n’^›ô‰«’ͼîREå0ÌÓÊ¿ÐÚéÔV.%KUb+»U¡bòè…ò® ãéÈ*LR» LÐãæÐ$4Rܤà¶5·:‹dòÑSÓ[ôúÜÁjñ áΘ¬¶åuÄÈ&°ª-§Ç˜ m;8r­eñ­Hšæ±ÂÊGv!”¢2|ÚÂdâLyjð_ýâ¿`'׈.…;pK^ÿ­)²ÆF¶ZÒXÙzÄ01 “'Þ ¡¼K¤ÁÐØö²JÕË*·*/òºka`$B#l…­ ®’LÒxðªDV•XÉNý»/ ¤ÚpÛ|b¬|šàLßqÈ4*Uw)âùÔ71>çnÆAl šl*Û4É:8g¼u2|ÊRÄÏv°p¥•Ô…Þ´HÛls›íHY䜬DVðïgLÇZÕÖÅ Ë6m·aUn˜¶@í¬”9 Æ×cµ <&&¢¯'…IJªM2«BŒÌ<Ǧ^Él•S¦©oû»)°ÀSÝ€•­5CY&!ˆáôÇ-)¤D&ílÉx6IJX\ù—³ñŒ$ë6¬”ÆpÆÜ×ã| [s¨#Ò¶µ7 RQa@¶{Ó®©Áò¤D +>“Y‘]Ëãù1Xz‚}¾ŽÑãZè¥Do°|6€±’u±c69l 4v[éËVŽ'¨¯,CxýX¶.Hb¤ÀÀñ•Ø )«ëÜ2ì¼î–³hš'£¶` ™ùx¬UxÊʑߞD_$Ùf#¶EæˆHV¥Nƒë¦Æ?гeEfM“åMk%k¤Ì­Çè^…²Bxäí|f‹±-Ûq˜ºda]±ª”§ÍûŒÄVá¦jk£0ŸZÃ5Ê'À<ƒÒ–X Àx7¦P‰‹Z °EÖ‰'ÈM•ðJt|Y¼‡…’>ŒÜ©Ç‘'r©¶ù[];Ò·“ÚÙ )&Va»Ô˜«ú²J¬õ%í\Þ$ÍI,…ô¶ç¨JÀH‘ æfÎ7 Õ¶v d?»Ç÷eUÉFGn$·Ô=pÀÃk­£’®¶Oýܘ[&M¨²2Q([!Û@µ²¶d¶ùçc»V‹©°™mOV¹¿­n+hJá Pí°ZA RZ+įÖ$M®PTH©UÒ–LÖy·aáuê ·Éë³#@é7‡ú‘ Ü`“Ûf˜R‰¦z)ß0î³€FÄp¨Êºa€”‘é­Ä¬š&r×h+ˆ f…)eë[ÉR¶æÿLÈ:^LeU­ Ðßl²H˜ø¬þà/éä°Ô¶ T·5 ›¹À|´TÛÙT)¡ôÒÓtã<ÁJoÛ=nVÎsþH åÄ c`þ i˜FVà‘Çè~ë5I[kbJ2 zÃ×_ŸgGåà™(¯$Po¶x2ØëŽÔ¦ì¶Ï wV‚Ä0^¶ñÖµ–rXLÑvÇÔ(‡¶Í\ÄÐ}ÇA(iÈDU¶é1C6p™C†²@>ý‚›O& ‰;,>ek¡¶¦ÕZm­²"Y˜mš¶Ö^6z‘˜>Ü6 Æ hÔ/U4Æë¡p¨2s]TÁ@ï¼Â>{”¼ï#2æé#ÓÈ þzÈ-É!Må˲š¦É„“3œI„µSežz‘HÎ!1 ; ¤Þç¯U1dÚ)ÑK£Üžž m³UB g¥hþz¹«úây2t¥°¬5“@Ýém…-r€e™¨™ÌZ‰TOÇðHípÈÄVw‡0ÃÓïŽ×«¾T Ó‘¥äï˜`:‹Ÿ^dº×ÎO#®Çë‹q晘„ ÙT¤š #ºFµåÜ ÿ,t½ÕÊÒëØÖj+”«mà¥r“RUÀN‘3@-Y«`ÒK¢¤£Ô‚³ 0Úy怔R|d÷îËKeÛl@õP•ÞúRªè[×%Y-ò±>}êÅ_8šTÙ§ÿ®´Y…V̆Œ¬ 7[)AyíÏÙûûk9ׂqiºª8ìC"W¶V[‚õbH‰¬]¼­ +`ü{wþzó¯'²mäRxU:>``Žüžï4ô² šfH̤,1²-¦S'¦äïÃåÔ´Zkz>p)ë¶pÛÚ¥Á¨Â0§>G}rã^Öî%Ww̺'hÍ9CX¬#U½Nj#I=KªÚMÚÊ*´r›aØl¬l ɰªZdÉ–ŒAo­ Ó¥—ÂH¹“Jö;Àóþ•ˆj­B¡©ÂRÄ ëe+{ î5ÒH‰Ä»vÀ³ú¦¤³½¯ÙÊ#­˜¹=I¼èøÉÊ³íº–²º¦m[9œ¹mx+¦¦«ëàHÛ©|¬˜Î[Õ•|é…¤1•œÿg®þˆU†Í"mst_á”VYñœ`bz= ¤3Ó [Ì6£ DH°m_U«Ð+e…a$Á¶¦·–ò’uÌÉPÕ<úºYü9Õûv*ç°.O絫JªáóO 3q4Ø6‰^>p_ x“xªˆ«ZSbÎRøV)A*çÍŸ ùWžs)óÌ ŸSv [˜Cú>«{¸ô¢‘€L¬aVÀs½Wûú‚`+XñTX1+ÁtL´Ö 4U'mH2À_9e†ÝO-¬: hBd>Jb˜«%¤udkŒ¦²­Ælm«¢Ÿ;2½µŽ 4jr+FSæÜ„­P‚T^àúŽi+UëHV˜<­˜&a«¯,R_Xª1ò|®dÞCæM¨S Œã`Øæ@&0‚¦-`K`Û úblÓØr`+‹of¸m2w |Øö» å EÇ©öX¼û¦© ²Ï~­¬d¥é¤0[ŸY÷Ú‘a© ™L&•ÁΫæ#ˆ­4VU@ ˆ|:`Uëe+¦i[‡…Ëæc0<†LÀn{ŒîïÙÖ”²€Z +#õŠ*l*Ùs´h•r˜Þ*£ÚÓì}÷CÖñmKÕ: C3˜¤¦²a+“Ö¬l«µ*/<ÄÝ3²àŒ—e+øH5ÀŸ¬–š¸pÆ&‰L#…­€ ´6YÓR ¶¢'+%*¡ÍLÓ^JøÉÛÙ9Öd€,„É´ž!ªµ3`^# ­SÀée².gÙü5êãLLfÔdYY1ÈÁÐçCà•ˆˆ9 e{j€¦JDnÄ”¶”¾àôøX‹%̤.4€…ea@#á»Àœmó·âYÝêsW¶°Â<¥ÜžnÝ dRÈS•ŽJúE V"«VkÊd¦ÓˆÎ®°ã`šéŠØb¬6‰¡ÁXᘆ T€§­Bw¶yfwoÆJÃyW´ãhDÃ*ò‚ƒBÑó”5¤l‚ÄÍceEæ%ǶuT…#¹Í'ÞÖ$ 4RkãälLÛœuÌ™ ÀcL+Õ̹É*×ÈJU}ÏÙæŒòŽ!zØÊ9+ÎRäZñçTïßK4òª$–Ī˜¸êZm¸¾4éOÙ-ÌG¶T3{Ž|xÚ®¤‘˜a]˜pÉ€l NƒwÄG¶Ò׋„U¶ÈãuM¬µØZaO™wY¸¬*&†gØ-Ñ€²i«B:/¬ŠPKfõÝmþ²Ï5eó4ùJ0‘4šjd›-F4Y¿K5†5Ïú692$¦‡Z0aX÷Í“Æh ÇjKS¡•L°ñ¬â1ó”:Cß³XÇçÓ­O)ðHJ˜†²°Õa¥àª’‰‘@f½¦Â™ÔˆUb—‰ñåV/¤ƒ«ÊP!Ÿ‰abJ² Òø˜Öâ)xsç¯xÎÖ¢î™D`RZkêñþ§ŸL¸9ÀÍ,Œlr>E½dkÄV¤!Þ#lUYÍ£P•¦˜ó}$ܚ焚E=ú¨(óœÊÚÊ~ ‡l«ö¢OfJÛ`1ÌÁ–sï.L°’ݲè$ðzå£EÑ ‘V¤µk«J4UYlžÀôÉ ä¹Î÷`Œ¬->À Hv+΂¤™Öm½n©«îòÃJên Ë2¶õ匧è@Š ‡Üb„ò>x^9ñnɶG_¡”’fK_kÙü{|Ês–§Í=ÈV$9Z¨)Í-z l€ª§¿0Í3E`$VÊ«zÎ)¥\H¥”µ5p&ªÒØ"ÉDsúD ‰mMŽa…Ü”ãûK-P‰*2«mbJ©ªlVÖ2ÛbËŸósY<[@ªIj„øÛíõfJaÐX¡¸ô—W%«ø|0ª„yˆmo‡×óÕ%F°Ýض1ªÜm·äq»"ŒG¦ «æäŸU-ªU"(m ¤CáúÖOÖ õJœ,7 ·øÃ(Ìa‡J`CÐÖšƒFNá3‚ÍCS÷u´ežIåj1‚&¶‚F­á+±Ú’-›ÒÊ!LÜmabU‚&CÀŸcKÁ¥ôˆù«¬.d“ UÝäëMóçUYŒ•Ø*pëi*©ŠUJšÈÖJz‚º7Æ—gÏ=Á޳vøvœðzK åV¨Ä¶³7Œ¾²ñRÈæ13¾^H ¬Ñ@V¡Ê*õ<CÎxUGô¶Kõâ©’%.ÅÇA`YJ#ÓÄèˆìIÁB9=¦œ óg9,ÛÁ•ßÒó·ÌÕ–?fÑÅJat±ÖÂZ»˜Ì«ml©†ÏÖ*…!ÙJecÚênB|szEU‰éÉÚZ×ϬætR…t$SW£Ä«‚a›³Hok˜kò ðaJa+õiÔšÇu§QeN¤T€s3+¯Ë k­¼™•;Ì ¶ÀS+bè9¸½ekd µÍMT‚a›3²–0‰2×8 OÁ#{¦¶™h½»[©çSÃÓè=¤™3Ùj[Û†Y-¦T‹ô® ,Jx$‡H¼¾½*x}­6'F°U%A‡3‘*;Є5‚ bó§„ù0an…—Z! ñ«þ} OFªÙÌù´Åkñí³ñlZzµ”Me<²À'È-¾Feé 2lÔgÓ9+ ˜ìt0¾¦²ø ñóa‚¯¼kÇÄ·æÜaÍCœs@(`'Ý¡ŸL¬½ô}af¨¤© æ GªZmu¶dLø§o‹‘"ó —e%ð![\×ן‹Ô¶Èp…î§cZ)’~J‡òÓM6½ %P„›“X`îh_ÞÆ·öõ­»òzÙ*×%–jk ãqÀ³…׫.d‘e­JÆ–@9`…b”xÇ”b¢©ÓÁ@ Sw.$†@À¢î],S_UÏa¤*Ì­W… ’¾°­ãéq£*« !PnNa«£h €¶Ö¹ÁÊ^ ¼;ãëÒ ô)Iî@IDAT3Ç$ÆHµ)me`JÅ[…”©˜;‘a0;QÛþ T3S®Fä8Ë%¾ñ®PUY+lž"Ad«¬ðø¬Çч٦ƶ€Õè*MIdhë·?oà3…•dªJ‰ˆ$HC&ô”»Ÿd¾Äm»Ÿ”mU<{èô¢aè|­—ÆŠy’›–­ú3ÖV–•øx‘ªDS=/£Ð<Ú`@ª‘`@‰•[tW. \¶B<Ò`²üÞ¥‘ùXÝ¡^¢0gJš|j'E¬Jy2¸¿+°.Ž ¥—•Cw» Á#¥ØÎÙ–¿ÁΧ ¡DÒ‚üSv.|šúfØz‹^¯™¬mžpžd‚›”i²²5g𦑢A š[÷:©­Úõ’RÅBæ\/«@®ŠmX‰W‹“#`%YÆVLƒŸ \6½-½ƒÛ¦±ÏÌ#msÃԚƃóg@ªÙ¬ :§OŒÌ™ØV_×ãUI&ð¶ù·µ*<¹÷¡¶Å˜J¤o­ÜüÝLG«»•L˜ðVx>€ÈC%ÏyÎïÀƒÄû°`*Á—M»ÛCŠô>¦Ò] †RkŒÕTÍc‹·Õ%`•²>ƒ§­U£ €™U><ÃþÌ“m«¬(K@iÛ“‚©æt3W{ÄÚÉ  9»Ož¶dÖ UÍ<`%h`ë²j+T[9¤ð0eØ!rˆÛf p!æš_yÙLއg¥—Ú®RP†óGæïÆðùXy %+OzY¼€‘Ö1²Z”µš$gµ›!†C‚z‚ô5e%`z²VAПdš$=åÜh¤"ea«È6@“³ª›|=tÛRñiV"…ï–¤„m¯Å:6a† ³ƒ'î·½Žà Pb]¬o&4·ùY´°Í¡´PXÊ*‹4Í# ïÇ_攋Êñ>5‰¥8´u|å‚ÀC‘ʨÐTÐÀ"ÞªäÎòúB(kE~<ýÊ9l²¾—˜è˜-@ l÷ó—ïÞ˜Ç[)·²¶™p0InŽI™ ¬•`ѹIQÎ9½­¨ÊÚ¶Ö㫲Åë8YzáÅô©.6œ2ÁÇúU ŒŽÑ‡H­íW?ÿùÏõn”Ù‘²Ë1ã}æ± P& ±ÕÏ6A_7J+”í`Z7P7žI'ŒgRGY±Vžaú;ï¹J3×îV¼Î"U—εÅ‚aÇW"ò·v()É­­¾pëd ¹duôû¥Z}˜¿÷X-™^ÓLÚæ¯$}ëô<Ô'i‹·&Þ<¶1Ä…F<ËŠ”ê©ÑÍ ›¿•!Ò) _UŸÏnxîA6ñÛìõWdb>L°óT"ðÈ:ÆÔ—Œ8eÌHŒÈPž?¦’¾UI9¬9Éú»#˜ )E• ³²jdM Õv…RHl0 m #g’˜[>®ÅeöV|4š™k±BYLÛº(f“MÀO&U6\-M™¯¤,²8^ï0 ’§ˆÔN m×ðqhrY­+œ2çôw´sc¶V‡%™’Õ¦¬5^(Ab`ú@¿7t±;NæVA¦êvx=Y˜CSÕwØVI“4@½"YIÁ5"èÎ;‚”W³OŒXÕ6‰’ÊéEþ­›!}%œãmi2þÂÖÚ;Ï| »1ÜUåuW"|d¬¥‘áÎ…?=n—4VãqÖ‘ ¨ hCß¶3¡d;R;gìB^ŽoÐæóCÚÕ¨W£¸ ÞV ™øår_)¸”µêDlÍö8ù4‡}ûÈæIÏŠ²*ž¢&`¢6«Á²j0ÃV $ì·ÿÌ‘B‘ Ir §!aÙfCÂÖÌÛŽé F ×B#& éma«m%)á5¥·-àn¯l¿Ð䌑…¹eò\eµ Lë²åŸg/‡±kÄ & 4”L6,› lå̇¾ 3·]a½âWK¹rïa7Ãêv8ÿvÍs€d•+ìu"¨‘^ué,¬l‰>€­”B>V¸Â 5Åä »Z×Ò–˜²BÙ†g)|R/$B+}[xÎHa€Ê™ Y[# @¹¨6Œ'Ëx¦li"«µ ÌHÛ4‘|JÕ¥õ½>Mé÷t­ Éa†™XtÕ4žZG›y|å°sYEWj…µpEÖÌW; %g«°õ:YÅÆKleB‰_yØšžC“O\³óÚ¨•mk†9ÜÁÏhè¥î8ç›p“( rÈÙ­ª%kxä3˜Çë ‹æGæVßJàzÙÊúÿájx…Re½uîªÏÃL(üO¿˜ªð"¥õ™c´«‹”¾Ä&÷èa«mÇwÞÀ$˪òH¼Àã ’@Ã#{-L‡•5É­þÆo­ŠlÛÖúƳZªF¶yjQ*€¬K#M6ÀJX…&å:¶uFx ½mnÓF6€è~¬ÂµºíjóWÞ Rj누ÒÐ ²Ì­¶ô‚¸U¶9mÝ'Íslú¬d¥`ŒÚ^]ÛBªa¤àaVu™->O È3ÛH+¾îÖÚ•Í* ,k†4È®Ì^ÓúZéÃ3§©j«Sp#È3¬.­óˆ 4ÍfU‹o+û,ä ˆiJm’˜Ö†¬þ¹U%0nvuŒñJ¨±æ P† À$çÌË"KEwжõÍŸ½l¹ø9y>#É`Ô  Qñ"=ggÁûÇÄ 7àÁô—;‹!r&N€Á3´-e[Tkµµ*Ý$02n°5A«Öœ#çL6’ «Õ…o° 1²¶Îx~ê@îxßyùâ NÀןꧪ)o»×?5®q!…ÉŸ'¬Àt’L×XzYm•Sô¾M:m<­ÚžP¶¥ðœã•#Ë"þ}1õmÈ9^Õœ†¸.@AP°UÕl˜j‰E'µÊª’5 >R_¼rÝ6Ï)¯Í9]ÄáÚÙ4€P•·‘aå3˜Ïj›Ð$„‡Í– Ÿ¶^ b<%ì&ý«Ìúš¡ o°Iaw.)arÙ&ét™¤$Ȇ³BY%›ÄxZsÆ×QŠ2AÊJê…0 µLª¼Ò5JæIUÕ‹‡˜îØl½¸qHl{…¯//˜’ Ú4œÕR6€“jñ|+vUMH,63š®ˆ¹+k#={Qâ1‘pú1h„,«‘°EޝÄv%^XSó î£4›^²p\§/ßþ™ìÞ2G’5dÌC# ”ª¦[Â×ekÃt')­ýkÄËV°%æð½ï}Ïkì?†½ ³Uáßþö·?üá:VU!\¹Áôâ<†²i1…l#)ÏCŸ±î³õíÔ9Ì\!’©'Œ ÈŠ:ÀœaJ2ŒÐˆ^¯˜¬ðZ8f®:Ê¿{°åödle¹ -j×J†!È?%FÌPJÓZ›¯+G1lõPÈR†aY %«>L„îó+‹$n < › /ø´}’øZ#ï,ç€@âª` Áßu ÇÓ˜N¼K°5žm7 ]¶x« NLJ,7Ö²ÝÆ3õç:b¶ ¬ÞÊç0µ³Š¬h*ß‘m…,O¤u©Êúêõ)îDuQ•ÀÀd¶"7k>me•4M@J!,àÖd½´}mâ•O ¬tQ"XåÖ–,åÚ5¡*YæAk½à[úúhde•MOwj¸{h6¼0åJjÝé…Z+ VréciM³×ƹ*§¨ËŠZzY7Ãü+O©<µ›!KOlÛ$k½.5¥¼E¯ïp¤måñmc¬]En¶ô0ÕVXÖ)4ÏÂvUFje‘V[EðÇWÛlî³B]ð¥ê›9¦ªÆˆÌîÉîQžYïCÁ{-Ë’ÑëÎБf"Éhjª, ÑZ꘾¿£RnB@ z2…Z¬ &°Z€ >²KȤ/"a!+l­:bXiº­Z¡ª’L¬ÈV×T’¡S£ #ÙÂÝ,ÝŒ*!• ?„`Ò á¶Ö4s*<.o¥Zäis#“² †nNÏð¿¿ <å¶:’ÉZ_OWbÃ9â,´® ¤^ì=[ùó<ùËRús§ÜÜ»Õs‚k‰iVŒF­ ·í±mN¤*o¹ÂVÝÙbÈ‚:ÚζBš°JQâÉRÚ # r¶e­Hzk kx‰{*H²¬åe15­¼±‰e1b ­õô»oTóÇ$†ýDô©êB–㹘'¤Fi2‡3I—í˜é•xjL¸Á4»C7Ö§”ÝÊ$%&ÃVÛZXéÅÄ/+H€Rä–ÆZTg«0¥U;%ýlÆÛ"÷¶À‰Õ„ã0! ,kÔH%€@Ø>¿þ´ ÍLƆøŸ¥mLJŒ‡hoN«r©Baí¬™·rðeT•5%²Ö3èû·Õ^ ’a)² ;o…sÈ„5­Ý±~(2Ï9%Œ$SÛä¶ÈfPxJöYKßµp¤¸¹sÿžÏ÷¿ÿýï~÷»‰ÿ+gWç‹«s}»/O)2CŨð9ùû§Nå 0™¬7I¯Üz+Î=tW•ïh”d™š*Ñ‘ˆ·V.›¾¯$&CX ¯*™vÙ˜ ü"‡Îˆ”0¡¶¦*C¡I¦K†ûÚÉÜ=x½;†ŒOÌœ P îA÷µFó1$C_}¿ Þß€Ö ×îÝêü5Ÿµ(Á›¹{¶Å7 >ŽÎ5Âc Ÿ- h¬Ý›SxÁúïÓæ¹3’!m÷rê/™a“дµb*GênÕ)¥0ŸôdU×õËW4ÞaÍÆ(›©¼¾¥¶ML&«¤,RèëÔÁPbq&@Ûz! […ÝÁ3nBb óÒ·%ÈD!RÐXÍ`BY`«ZbÛ+gb‘¡T@Pb-ÆÔ|l)1 až€vȾH¥=h[íš¿gñì®êY…¥ÌP Ì«ëýK[Y׎´Î_ îøx[Ø$pw^ÖŸçsì ­; AÊéÙ 1Äp3dޱ•ÂÃU5[Ë<&Ï–¦*«pEJ:»”XS€ °åcË“9 TÛðR|ð¥h0üA)¤ÙVÞÇ_ŠF‹«z}ã‘!·VHÓ÷‰^¢-À­-“Ö@…ªtŸáñ_¤lû¬… íd×¢ƒ#Ï(÷kS6’°­Ð¸ãÛº&ƺ^a[¡œ'h ˜Á¸ªó¸Yñ÷CGzáïPçý×ÎVöy@Xt¨¬Øb(+0Vå̦ì-=ËåŽç d¾Š})9ô³Þ0ª*ÉD»¼!鑆ÙvŠôÖL¬ F¨¢œ9Y!¥„¿€õ’Y14J¬§÷û%¬%9±PŽ §±ŠL”»„^i?/È2lB8€o0@kåg¸{.­í¦Ê\mUVÎi`¼h›U[©N*ÕUc¬ SÂN×›¡{P"‹I ÓHa¬Êñ0R #ªrÀó÷YýÞãkÝoT5Àà‰VÖÄNËnÀ–¸NuŧI ÜtÙªÕÈûç§&O«*% Á³ ¾©Èâ­âÝáü•U[¼Á*¿{áLy«Ï1 xVh+(ÕŠ¶ÖL0=¡ ^á™À§Ô˜­^Y]€‡'«R­h+[‹øÊ­bøØ  Æ kZ–@oÍ6ÆêZ]»Ln Âxµlm‰Íü_@ðì…#¨/2†0>$sâ ›<œ,†&‡ÞUo [äÆÈ¹÷¶­²xSy1L¯5g¶pbÚ…*WB<ø4xÜ$œ¹”F”iÖšÛ4M›³Ö™ë8C)xkUiˆ™7‰vRÄõ‚AÇA …9¸=ÛZù¦ãp%‡ÄÀ¾XZY¥éWÉðÿŠÕ;Ö—¤u{Ý ì¶‡-™è†÷’ôŒ*—u·Ä¶ðǺ‹e¥ª—%†¸K戄ëõ·ö[Ký'®ºû÷©„;ùýïÿç?ÿ¹Gß«rÇ9cl­‡wbçòqCŠ ­YÝ[8þœíÞ•T¼mµ˜›<÷ÓRܶ^Ö¶—>²ÍƒiŒHüËâýnÄðÇk·7Á$ ­˜4¬lW‘]÷Öܬ"}ÁÙ*a­-A«T²˜‘Ùvª’Eڊܪ’­0}ñ ÉÜyï?A²Ý¦ “jU&HšVà9dÃXWK9r ¬`<Ã䜱KØJnL¤!pŸ0F(2Ù H¸H•Z@¸ Vª4Í .0/Ó·‰‘”àÒX 0ðUÒ ðÔ+¥F­#÷”Óg #¹%SÕ ¥XåÓ [b<€‘"´~xÚçlÍùù>ÀHnbÂJÐ Ö4ÈÜ0%ÍO<¯ÄÍ^nª„^­u©µ{óµÐlx&g¦|¶õ«Â0‰¯‘µKVÔY(7 Ìœ>·šSJ¬|/@¤˜%RœŸ?îs¾¯ïa7@æ­&æ¤þ’©áÒùîG-A䆎QU&p@c&Ód#…-ÌÊõˆX 1ÆjeÈÍʧë“bR¯ëwÙ˜[z[Q9Ynº”}–›D• ož¶3Q"¥|Öb”ŸN7¤úœ#4ÅTŽ}ò]5^-lÛLÒÃøRáÖe;š* gJW#ÇË:”5† šM‰Œ„âÞ'¼@*L¶a0•ŸùÞŸLb¸.sà÷/ʲád0 œž¿ëÍÓjHÙ4FšOZ]»—V•`¢$AµÝƲ¬tì°¶ž=1Ÿ^[¼@ €¾m)d†¶ü°²ªŠÆ`lýÎRnu§ &È*lµÕ‹87Ìóh¶‚B})“Õζϯ£q Ñ:“YEôýâÞ$m lîß Ñ”ŒþVÿ]üÀîÁ͸‡®¢K뺺Œõz|·,Œ«†=—4VŒo]2åÕ&Èù´¼qÜð€z7Èjáù/•½l~õ¯ê¿zuÌÿøÇþ‹êßýîwþi@“t„hRÛ6äs§Á#;WŸw˜‰P^– Æš[Û®äÿl¦‘j «Ïˆ0à8m®€¹‰ßår³­6O-È"áúÀV†²Ãç ù×N­”ÿÓûý-ƒG nV[n¾SˆKqTÕËú²"à [¹u(Øý A¦dxëN»ôÖŽ¹”*/} ‡Æ äSa›<ÃVLg¬c² a ›éò熹¹;’^÷¶ Ö¹¬»ºdÄh©ú29XñÃGÀdø° ÄðéqH¥œ'™lzÙ–²ÖZÊx4Z1B¶î+¯d[² á ®qÀ 7yÃ#WعmÀY¬~#¬ÖË¦Ò ßéþùWÝ€ßþÿô§?¹íâYã>m{š²)©7ʃ"è¹À=”Èž&“|”Ôhß=Jbí¤ÔbÒûß3õˆýim?¨Èþ;Cߟþô§þóèßþö·>ȽÀ½f»[a*+hB St(¸”µpRÊ®@æ e³MœgXJØÂÙÂ}ü˜3¶;´-Û$õªJІ €ZÑgžg)Ì ãÉ8Àé³âVlë­pu¶Eï†BÀœ Èçmp¦RÒV—­jwØd¾ábk€ÛjµƒûfhxëÌ«¢GV¡ìÓêøÞ #î½ü†©\ÞlLÚ2¬ 0U‚ØØÈ0µ”ôÈRÄá&„9Ãd1Ö˜ÄÜbø7!¦’—Fº>påþHÐÀÙZ9X) zš½cÄÌ‘dL€¬ÆPµa6§,\-½ÀD6pkz¸‘Àý0®I£<™T…ý;YÉâÕҜ⫩ŠßÕ ÓØÓc8¤ß¶|ܤ”àìNlYÁn©ßôªµ z‡mÎJâáZ£{9V2A #O…9Hñ‘R"ð¶1<¥Ž×u+ ã'æÜ¶’xŒ¨èCê\pg¯uâÆƒOÍý´Ò«…Éj—¾á9Dn°ZÛŠªêÒÖêõû« ½ÃYk‘ ]þù‘ilúýOÎ10B¶zõ쌥RåÞÚ¶4‰•Ç[ù0QX{̵yý¡­Ãd[Ç™Dæ#¥]×ë霌çôÜl‰“¨‹Ú4K ‚Ä0ÞAö®]²&éUUHw™<ñµ 1pQm-b”8¨­ECZ¥¬µ+L)nç×铆T•Øäæ§×ÂË—rµyÒX9Ðt®¶VÛ|*Ç…T… `×.ö]ÓĪ OFc‡»Œ0 %O÷i ½:ÝK€8«ôÍ· ã¯ñq0èyÁ>E°{j¤”V})sâ›Ó`€0Xwh$åÝ[Lµ;ñœ¶óÔÈE±š@ ÉS‡Ä5õw t¡ì_¶‘R»Ëùð¼ÏÎïµþ¿€y{³ò,â¹í‰Há[Ä{dİÇOÃÉöÄ­y ~áðÄ…,Ò³îý„…~é÷oö[1 ó?»zö³Ÿù3€#È„¢3î¢œÅØîA$°v'ŽàŒñ§òjiÄ0@CÌŸŒ­°MÈ™ËV ¸[¼«†»aúî@*è‘%pn³ÊV#ÌÈ YVI&Í“Û4ªÂ•Ð+Ša—Êêïše%»Påb½T o¤ðŽÍM!&M@ªùó4Ra+¤„Ž5ÂÈ*T%l»gLoµ,>= £V–’Fæ'–J†§$À”beKYm%ÍwRuœ&7kÁÍ„påœmÙº( ,üDÀÓà¾ÚZXÛÆ[͉ª¼Ÿ²’•µ¥."E>[Í ÄЋÈðx€yÛ3ñý»È­h~íê8â^sÂ}ç˜Ù]Y¥èe<ÃsþÇ3*K©Ëp6 1`åÜŸ dm‰Í£ 6Íóø4²Ífk¼†Qek¡ÐT•ã™0¤ÁØZ…B¤ðýÙ o$媺+šôñ ð¼Y…Õ6€•S6Û”óÄ ÛÌ­Æ8F7¤üuS9B}‘·î,J&†óïZÂBÐ…¤'+º„ÈfØ…¿>`ÊëzZ½ÏIªÒÖ¬°š¶°‡¼¥¯«ïN­šæÐ@)ËÂM“I>k„éŠ|zÓ²‚oóó¦îvJK¬5ÞA¦¬œ ³3'°m’”Ú+(õ|)›¤Z½ê`¹M–­U ëÎÖà?tWé›vp×e«,{äF&ËYŸßœRá·FWÃv-ˆa5!'¬—&åÌkÁY Î1gŸ@×èoKœmUñ‰¥Ì–¿¾ôšb„”¨Šù€¦ñ9P ”GÆ µ@Ä À§¯ ŒV‹ß%×”›®#¦±27’ù‘A}më‹„“æîn–$¹Š,ŽoæaèÃ@ Þÿ…X $¾ `ìÇæwã_y:¦Zj•¤*ÁŒ/\~?î÷FDfVvu‹·„käˆTi'PåûÝÔüvZ‡_ßÿ¾c·wÛá;ûÖ†tnßã'œýÛ“­]KúN›¥ï fýÑ¿ë‚æBð˜8ÌeϤPPÒýCteí·»"¦›_¾^®o²] œÔ ‚Ÿÿüç>÷iþÿo¿~#È}ëG&›bÞxö%nwLŽ¥}Y¶å86ޱؾ££Ö! Óqª]šéïžOï¤ÒG(vb))8ëbÕ+2©Ô(Lm‚|&…7É;{l !5eZ „O!ƒC|º^?ˆÍçÛ&<©,ÅÞcYßÛŽ#UBP–giZ2-Œ ¬Ðð@%Ô€ ›¡jm_À4ÑÇ©ÜN¶F©A8åÄ,ÜS µ'…2ÁM,Ä„<¤1êbȤÙ=Ó?f±) Öó^k)åçÊ]÷Œ¦JV;Á6µÆKS,(+îêk±lR–jg cY­.» “ŠóÌ'+‹V9or¸¦Æ ã!ê›%\€‰SªÙ"L³sèH,y%h¦‹8dò»é¢N¯áMØJîF°B%ÈZX2Yd:ÅÉZ®]j–@±s(åFB†XÚŽ¥‹KÈh²¶Ãwá ]Ê8 ¥:·Î–šTUu±Ô7>@JJ¬“fUã—mÚ TR¼ÚV®dÛ/æË¦¶¥àtη‡í­‚&æ»0RÝ=Ø=Ìn' 箞h_-Ž€ Ó¯#“m `1ÎÊcv±uQñBàŽQÕï ¿’˜ÅíSYÌ‘©%¾)UÑ*oTÞͣʋ‚á)t‘á–ÚQj-‚]4LÄJòRb†I¶›ÍÁH5‚°D*DÐE̲DðÅ”¯¢ó#>2°©Äh¼ìž"Uiç„ý…lÙ˜tð»œ×ÂÒ%`µ®Ñ<)Ö`5w–j÷ÑG9AY8ÓH¡(‹×­‚†#VÛ<õRg@µª,Å8g”ÇË\Éæl©Ê2)#@¯@F™¯VÐHÄÅLJ\Jl²-e£Á!pjÍÜÀ@Ö[ŽtbŸòUAR®ïšwÍßT6h¹ØØþq o¥ÖAñŪ:×Ô9À¶]+wøReCxKç)«ÜýéÆpJõzß#ë«». à~>Š/•蘚 ½¸+n©ð }{ ÂÔÓiÈáh—̹úŒ¬{Á·ñ–ͣʲÖbV/ À¨Ç-á/Ýúi°÷Nø¬ýìg?³GЄ;–vÜ6{XœL oï¿ØE¤ã¢Û»#rÌi¨ŠÃßk[R@«ÅÉÒt¤¯»@‰vN+…<¼ SÀ¯‘¬B`xœFűLPÌp,‰Ãgð&±ÍD {Ý+«E#a*òȺ4Ž“ÂäMB¶^‰·ÍháMá½ÛBü‘Ž»®Ô+z÷†¿;Þ0÷SíX\q3wE4E3R¶c„avÂ6ånAèèÚoçŒF Âî4^–‚*Ë^ÜUɧŸ~ê%Zðºö÷¿ÿýÿøGší·Ž&1[q¸ñ ¹u€í½}™\`ïæH][7Û ¸ÛÒ=`)¶  ¸}aváb©öÕ?í…€Ü~0҆l™ˆed¾@è|ü–‹›–‘zßLåÛ}íÜ?»oшè_j¥øú plsHLþšèÜB²ùdùvÇÒ¾xR¥ê‚©f{ç{² ‰Ô…OgΊQûå/ù“ŸüSüÂ|jt]þõ¯ÙQÛŽ ¿mBlÊr×h»Ã„{î<›Ñœ›ÓW(Èœ°@¹[B\Ií0™˜&Z|%N˜ l² fšÖ GÀcŠãl†øÅ¥¢…ˆ)PæÃõºJñj¥ÐŠ™náªÚ]š[»ÁxU–µÎ[²º—µT[Ì‹’Gï->ý»1ö÷éXwMí‹™Ð`–¬iq!E²C°ÁD\ñ ãK!x9ò²ï*·k%u$‹#ki¿)ÈÂñ-ïŸþ¾}x‹Oÿ^»|úoƒ†7ÏΡ­ñ²ü=hÙ–Íf ªXL˜ß tK)'¥\ \Ð!@R‹ fqBø{ÓÀgŒ®Ž¦U <’Þødw½¢‘b‘ PŒÌœ?ߨ›ä¢Ÿóé(ÅÂu¬)¯C¸°ó5ŠªŽBn1Y!1kZ DŠ8¯V‰rÞ’a¢µ”mÀì.¨DùUzγÙ,Åü£âL+ˆ?š¸íÓÊ+—e ¦'e±!ãD†P;w9Ô)8 K Íœo q—*!äÎBq1‚Ôæ+lŽ¥(8Gx·‚.ñáɶäw|«Õ®l]FÐĬiSñ:òáM%Þ²ò ©£‘´`>|˜ÖÉlZw°'ªv¦bb&hƒ:6¤.ô™e7Ö¡S „Ž…H…¤pHÞ„|ˆ.b¶.ð¶ [ ËDpFS¿ïeç0}RvÚ·nÉvªâSƒ÷T4I#_ÝÎä—egb0FÁg8R©=1Û™!mÐÞmÓ² ×½ a6âˆè§&ªâ;±Î¼#U"ÀÒŒ,&¾K¦0“m*ƒùÆÑÑ9CÈû†ìo—2;jZ]Ô2úÀû0¶|Á1κ_uOŸB”«5)µ˜šÆ—B¨D¼ÉÑJAÈ8üZëHS Ò;MHL¾ã;%Þ¯ú|ôÑG]I}kà4Ü®>Ähá ”×¢^–ÎÖOV6ò­R¯Bð3À_|AjÇb˼ÀN;«Íy?ت ²á]‚ðÀ.¨¬ûÇÞYR6[ÊÞ £Ïz"ßwŠf‰ E‡F RLЪ é#ˆ!õMMÌ€¬™Ráøô!Ä‚€ÁÝëX cµ˜^ÌlSUOA›R^-z#CmUÝ–âÔ&KÍIRð÷LÄð×5¿ùӵК5•‘†o€ÎÍÓ ˜|·´íXJ™Ð¾zpètžøâÊ«Eƒ(Á„·Ü8LS? 91ÊΜZU²Zû·nßâ@ü6”^”¯)žžŽ–ššÞ! oÍ#¸ÇÍf`Uâß6-CðÊ”1³éD“=Ò× Ó)æeñ•ë’¯­â3-~L3ƒ-›Ü`}d³®ox£Ú]‡i6%v+úthGf¦Ð¾Ð;ÃâYmg" (@†o×zÕ¸¬€x×T¹!)@—VVß?aé£]¾o~nñOp2åµ®i[¨/q#d¤xsBtai‘· ´¬µÀ G`É*ÁÔÞÞRõ] 2A)fØÙ"1§Ó褀4ÑîsÆOúÓFJðÞ¸kÊœ’O0éh hW“ø‘ YgÎ~„SÝi}ÛÂ9”Ûk…QÙN©sØGÞ²óïÎÚM%]/Y:¬ýJ‰Ï…8‚v‚ ¨¼+AFhÔÄ¿a,°X…–Y-šJ–,AK…~â¥Ðb1•£¦,À!RIâu;.¿åÏRÆù°Qs8n ï:j§¬Qó¤/ÖÂc_4¿ýå‹X?ø¶ûð0ÈúØ´LòŒi<äwÆ1Û³l§j¿‘+ı/æÞ†;áöÞ~áø³½; ^á†Q.^£º«Pc‘!#5cˆáU µŽÔÎå¿n•z…CÔvP“ꎒMªÂÔ@Ì6&h'™º1”àÐgb ‚ÉSã (à‹q;F_ÿŸÆ¯j”û]ªõÒ½™yqã ¼Ø:|¶ÁTYâ„ 9Ìʲ–»(²Èîy~÷2ÄË }LKÇ‚)pÅtè;¢4-‚ßÄ+~Eo6¿ 5AËz mBáRFe‚N€_ŒÃšœ›™Çßb_|"N €’bân+UÜ$u©°¾³º›*Ÿ ƒX¶54²–À 8Ž—Jƒ‰e¥Ôºd `Y nYßÈ®2¼û¼^bœZH¥/ÕRpŸKñ{¤¢™ È½Š’Í&î¦2‚†ä¥š¶Fb%p¾8ß²¸yj ) irž°çÂƳd5jžºK1qK^VaO‡)ˆÂ£,M΂i#m«¼ ð€eÅúå;Íâä -ÇÙòŒùØv˜–ªÚUâm¯‰Û^8&0Üꢄ‰kÄ(,h$qå÷ªmy3(A³}Èú2¯Žb)B}Å[âŠ4MËšG‰lÉR¦4}!L€£$>Ä ‹á¬QËÚ‚v4&«Í´¬I,†¸ª)¹sÚÀã î¯D”ÃLj–•ÈniøR–&¬Š¸î²,Aú0å¼í#èÞNÏH›‡ ômë‡ÿ D‹Œ¦ïþ¥;Dœ¨—˜¦” S+€JÏñþþ÷¿ÿì³Ïº@O ^û?®s°hïÆh’µj#ÆÀ)Ætt<ÎýÄpl“Ø—ZUm)¯µ¡Ž838®Z´ä[^>9"dé7Ÿ;IU`´‰4ª‹r)L±TKX*´ŒÏ£YÅŒ²e… Z&ˆã¾ê⇫¢Ì‰+¯V ¼åÓàêXS?ºd¥^ÑßùgMMe^ßæ1¡™Íà ŒŸ/@ˆŒÐ^d;©b—^6f%̽ Žì õí!­u"ÈÌCow µÐ®Ž†ØWó46ÄT¼ŸY _¹ªKééQÒHµ¤ßÉ[ ˆ#ÔB‰ 4KfIDÐÍ&hŒðâ)§£–fWg3L¹’4©µ_Ù:*2í´hø|øâJÚ‚Ü+›«¬ŠÏàµk0d ÁØú&[÷²…½sm©†Æ·…î±"hQSšýéHqªEµd#CŠéDƒØ7§èV¬V£,‹eÍÌ`)63ÑÈÓ´ⓦ"ªA'^¼TŠõ24žâ¶'›u±i",¶‡È8^!O¹] jÚöŒ‹€I¤îUU¾¬. AŽÓeî€bÚÉQˆ¥Üv”¾ZˆÂ‹xhƒd ʺa*¿ÏI§—&K„)Ça‚ø&ć+gåé-,² aåp£Úˆ ©l9Ž€ì¹ÑýÇB˜;¡@^}ºð;tmI ˜@jì\pâwí¥V帪HéÂT!³hÏàÝÊBŠ;©‰“eðæl‰\²-ëÞ!¨B0‚”1 )£—•ª©l-ÄÛ&>DIƒ EÛDèTqĺô,)ʉ+WK™Iñ^Ê!¤º_SkZ"*L1dœ6(†ÐAhwh§Áí焦B~¶µ Ö«2]jGP¬HLYŸ6üê0“2I‚¤•”M'H Á[Ž&€tªÄD}§„£¶F–fpüð›Ð ã1î}×ë·Ã®N)³e†ïøm$AÐTUyl_»F‚é´_| s`Ü6J|,3ؽÄ+‘åY²u6$¼!-•‹U1‡éX;µ}.Wë„}·í£"ð¤úÖ¿™»xˆ3µRÚiAÙCTÊÒlm°ZdÞRŠr‡ciû.„Bj•¤l©2}µéX.›$‹1D 0ÚÁ«â‰Ùódá{V,šDÕÌÝâ'"_Ø·)L Z('"h*Ag–›³w)döÅ_üö·¿€óêæÐ¥ãµ}3Xš*Dß!_ÊhgâÇû.Bœ² ¥’;6ÛQà08U@¯=;{wÀ–,‘«É¹Ž‚Aª›D/FY¡ì5Ý»;s|¸ª–<~j‚¤jj)+%P“>ÄmƒID£Ê”ÂĹ·2ÌF5§ÀNïDp¶ ] {§ß)Ó´¯?þxµ¯èõç?ÿùÞÑ$ÆnwÞ®©a–µó·åªìÑühøel¡ùÕ–Ô‘”BÇ®?šr¦,«c%ªJÑd~MîµÎa:Z8–ºÏ曳i›ßT3%hÓ/.¥$°MvnÅ| ¸¾J´®_€`|æLx(»*]Xš"Nì¢?}´H"›lYj€x²Y²D,Ý¥ ZvøbÊ@…hbA}¥ti 10ÒäãQuW¶ŒŒÃ¤TÑik5â5ÂŒÓÖ¼˜ ɨbF¿Fš¶lãâI ÐBø RwKV³˜§Ö ¼FS± ¥ ^¹@•  oƒR)¹`¨^l©b’XMöêÙˇÓÑ^– pL¤%ЬûccÁqà]Âø–ÊùŽ ¹íáèÈ y–>¯ȯ…%&ÌãØˆ˜•ÒQЭ¦Kc@˜ÞOŸÍֱػ^÷¦RkËfWo¤ÓìñºFYö£-¨…(±ÌL^ A¸Ž<++Кݑz¥øKM3oZ)]¤TÕ±,~›j*ž¡)Tµi•×N¶a:pÌøb~8#Þ„e5Ezì 1é$ÒÌ©A1#7N„í¢›ÐÿêüîÄ4rª¾öYßmì³i´Kû ú.½Öfëd ZÕH†Ü[J )àïpp:¢†w*gµw†]÷vHDw±*šK‚–&_@ÁÌDâ#87Kø41»"Wѹ8¦uÚ¾Ûv¡àÞH~ÖH>éR`ÈRÜîÚrG¡»aÄñydZ½J¡±jÍV åy‡c®èd¦S_š:Š #àÓo³ ãml:ŽK 0¾¾bGá6p,>÷¿ðwýˆoý;–4u׎ץy([šÜRScXòv§ï@&C(hfñþðÿË'Ó†¿®7exÌ`°^„›GÊ^t4UeÙ„J\hZj¥ŠÃyKfÙ¶`Ë]1XUK¸1.ã€ñCª ˆWˆ`ÉVèôRkà²È‚:n×p"Ž%Á ]¶AñÚ…¿Å/ÿ¸óýÉ^êÒ0‚b£6\€fl3›ÜÀµT‡ ;dd:²]Y2Ž€…ÚùÓ³jáæQ¢\,Ð.¾SÁ?Å{Á¯é àÑnT¾ bó˜ßð (;ߎâw2)Dpnæ/$2ñtª ÔK‰XpW3å vï9“ÎYÀ¤îCBšd] bœÔðGÐnß·»X^z‰P¥îÑV.ËlgM×­ ëÒKG' „뛿º ÔÝ…6[c\O¯§j+Gîi »‹Ä¯r Ù&ÇD¨V_VÄq/)±ôoeø¡«Žßê˜/þ©ékÔôy…f…È–&›‡·€uáRJBÇ1^ ”ä¾¾¼Ö-5*[_žAXO–OJ,ÈkF_ÐlîIŸþ=ƒ6%ý- fp?‰ÔýGG)"],%kžÚi#q¶)ß„jñ#ûÛûÛßÞâ_;ÑÅáëkŒ.‡Ž–®ßä iª‚ oìÈ@rœœR|†ÃFp˜NÒ­•¦¤Ìf*í”wש%[ív³I”Ǭ5f„v¡D@Vð4Ùã^š¬ ÔòiN¿ådál´ZË2{´5¯ Al`^—Þ ¯ªmò¿úÕ¯îËá?0ðŒ79óFjrôIÃÒØ¼ לnxYqÙDÔ^[|z'•b)K14×1¾¸mºô®r'CVU)~…‚@‚Ê?ûì3^üºæ—42O9¿`ƒ…´ ž)`À:Y´î7Èh–ù‚˜¶LŸOg¾,ß ’íÀéŒF²F-ùžW3¦‹Û„‰Éæ»+à.Í{“{˜qHKH·‡ûÙ0– Ѻs  Š¥ǤópdÅÌb†Öز˜ó‘ù²u‘¥¦P@GV£Jz$!-u·)¦äk»$[•Xíh@±BVÌ3²¹¸’‚˜êøôÏ¢aô¼™[â^Ü|®AõvÒepĶ'†‹‘IÁµ¹ïáMÀïh𥴮ŽT“5¸¥T›±¬WKjÕ*dâ–²¶ô &b;IaZ4vYIÄ ¥)zY2ʪ*œ×z±ò8²¼,5磣îDâl`µf†@^œ¦ÎÎ%0‚¥vчìŽNjº“’Å„ óøÝˆð<5Uø•¤S‰¬%³LœöÈ™Îî§dI65ä¬åÀš&+^V­’‚!µhi#@j@ëÏX¼¾ó†™Â}Üwz>0ÒæirÞFxHÓZŠq ¿™› ^?·×ãVO­,/ ¹ƒªà”+¤lãÊÝ]ÍÕÊ®]R|„dk¤ÐÝ.¶AAL`·V»À‡,Ågºû_>ùŒ[£oõÇ?èëmRÊ©5¶¥F<‚KÜB'ß`ªdõm’D¤ѺCHLK:nÊ^yRS†0å²@4%Z¨š­v<ÃwþÅDjJªÀG¿fù­æŸfÚ?•H‡ -ºÉ©Aøtàú::w£îp¯ámÁÒœëÛ„8mD05ÿ^§‡ÈÏã¿b`HÝu´—¶æœíØ RN»;adÈFÀ´l× ÖF’K1[³w&Í2²NI 3ŽÓÓ—ß§’î: -›ÊÄÈt¥R†6vd†ÏšgDÒ—E†hND XáZ˦o#öåÕÉ„Ýða)„Þâe'ÒiñúùÂ[tÿ$ð£¬×“&ß¹‰Ø^:Ã&l6YºFî»hË6Õí¡³ ¢ ëpêåîRŽfwþ@¹ZÙdu0) Ï’}»1|3ðÎ_;Û\_ y ¶k`BȼmËR– Y!‡ç»í•tã@Öú(^š 1gµ³Œ`ªÎŽÉR®O肊1ˆ Á·DîžAP™‡³ZðÚᛟW.®;Ïp”Ää› în‰©¼‘RF@cÀ¦Mö4¾t¤@¹^›62œ×¥*Kœg"‘©dWK\ŠA¦`¹ŽÅpFß9𖵨ª!! cÉp:„óïš[Q±/-à¨p“yxО4 â¨CT5R™*Kž!78¾JY2šL“¼.k-ì kš—j*»£sD¯—L©4!–ÅÈÞ»ºXÚµ#’½f9cÐq³ª³£x½à3ˆªf;@:fˆÖQÄWŽÆ7’=fÉbª‚XäËRS.Vdh÷¸̓Œ‰Á~mǾ:µeIÇHw}üjÉÆ7ŒrKvïk§ö»#Ež5-~xÂ¥º¸zE+h>B]dö¡ß.¦ÿÖ^¼¡ÚÛHõÚð‚Æ³5©vÑ´ðRr 8Va÷g×WKR|aO®”Úݨ:•7RwT˜•D³4šyXFöÎg b©n©Y±D †ð>ú+ñû¯>æ¶/:5Ê\VOV·S­á‚g»hl©ÆhžëdÙ”e°;4—ÒNÛ8Ê :U1Ó¢¦I:Uˆ%k°˜ÉŠeÉííoú¾ü×ý}ôïk/tÀÒ¦LÂîìÈØíëlïñÝ”Q‘ ’ÕÂF,CìB@„ÿñüüóÏÚÔ+zóœ–×<uP^+-›Á.Äð¼¬-Ä¿ÞÝÌ xÏZU…K±ëlÎÛË$äqˆ›Í ÉœCç&HÝE€‰oâªê¸Q› ¹«Ã+©êç©M -f-–8Ío™D°ñG­ØÁÖ´­!Þ Y‰1á?£Š_×Üi~Áfc Œ§— km©{{)ÛeÍß•«2¿«Ö›o)†O*£PyR@U¼?™¬PÇ8‚²ÄÓÑN—OÞàïþ:¯~u×N÷†´5¶La;ZIøûK2Kí}šÝU…SŒ)°Dί)&3[AKD!¿’)V2p¯9jƒË—ˆÖm³çÑRÐ{º¸sdÇ’,‚彋µÀ“Eƒ÷R¶ùÑ2äR4›ÒvšYŒy÷–K!Ç*‡cò4C€ oɤ øÆ@`F%’κàHYò e+É'5„¾ãên¯ªòâ:¢YŠ™,{úß9) zãÉéÍ[zÝì¤T&q•ŸË/à»6Å–|c-™ M½,zŒlµígäRá›­MŠ¿JÏ5H°*^ëJ±)åµJ°WµL#Ëv:Yâ¶Öîx8få- £‹X—‰«Bã›.ÀaðfK™g™ì†4OËö…°^Ê£%‹¿›»ç¬î̓¡Y¬J9kŒd¯yŸÄÆ H!+¿oJ¿SëÔdJ:%“ãˆïó£¾ÍW¾ZAßÊx)ÿ>ôÛˆ/ÌXßôëÞ–Ô^L(æ¥Úfb;8p±í‹!1-‹‘m¼ÚgÒ9¤PÌ'…ɤŒ! # Òyâ8vlj/«–m*µâDp,Ý–8Ô˜»%ŽZ¯ÑÔÐà.}w‹%²ñë"/ùç}âó4ý’‰¯™íW#äé Ìß=fH ¾e¯g3dø¶ÓÇ ¯éwM Œ)¨…ŸÇ,V+…qÎÀp %TøDâøÕïT \S|È)ôE)³åz tLYe38ŸÎD ÈgpMB$0ß±ÄáYÃG+¦ÍÏ!Ÿ~ú©Ôk™ví¥}YR6ª©¼¾án)ˆeÈ6(€7ÏÀ!ïÏ)Åž©Õ—²a”” t†±}3ˆ¯þçqpùXjª&¹_j¦š—-ÆoòŽwóßSµ(U…ª¬”ÁÊZÍÒ³c¤n“ëuÕ=ÝôûÍ„È5} ï‰ ïmÉKŒ^`m¹ÖviTÜçi/²8LÖ®-‚øÎïšV…©U8¯VÖ’­\PlÚF´ÑH5€@J;½tÁT„ØZ{á‘›ÓÝEIJ‡÷ê’‘Bö—¿ÓG‚ýr‹¾ÌD´c–uרñÆÐ ؾâD7a-Y–•Hiljyvìhƒý!€¾² ™GÖÝfÐÊ›,»èÇÁ;µ%ž5*òÂ_¤q§ù¡È™ ÖBÜüº L[ YKfÙŽ†w´Œ¦J@”õ°»·•ã«]¯/Ž¿–íÿà{:½†9sgÒ¼á©êµ[×ÒíÑ,Åh|¦¤Z"! ,K…«ÌgpdæL0yÒKÐå6!¦{ôÇ…f WÎw¼ ç(^7?<äÞWª, .K³ç#Ô1P tVŠB,7LR&é^ʦ¼`bÚZ·qYÛqWùn±ÔËyos~kп^ÕxM®W'¯;ÄfÛm×TÒ1¶YˆFÚm¶ßÞy±¬ªÎ‡Î[üÃÿ~Â÷°×W }MÛ¦Ú 9YãÁKYvy„û’ˆåªÄ…âwf©ñ-O³ëÖ­…TÙRÕv ¤œ,>üœøõ¶¼WA®ÁÏó%È7.`W¡|H ÏÚ²!õÂ4ŒîÝBý\¾j•6ƒ%¿¬ϲZYL±@bÙ„ ™æ}†z…¤¯ÓYVJ!A ‹1êÎS#’f´¥&~—-Æ”R+ RL?5lx›õ4AdTuþ.6äËõÉRÐÁ+®SB ¯„®§ZJLM o)K¿¥rU˜ © ßü”+GP%¦Ïâ[²)xiÃqÂz IÇT¬O9 @Í“€f41q ’…d–™*ˆ4äŽEl[H‰M¾g ²ŽU=\:–f ŒÁ ´=ÿ5›ßIõ¹_pÇ_=v•}'íC3Uؼm6¡Qõ…0ÛÛB`K"…\*Ã:C¾eÇ"/¨²#" øfCfȼ,q3[^Üÿå”À…†lk†4­Så‰D“‰Äé)—ê7ÛËÿõúMCÍW_ŽW/jm‡Û^´–bÍ`¶í:¦e²ª€÷@j4 í ÞZ³Ú™'5%„º ‰# )«Zš1¥BŒí£Ã ÿ$j>øôï¨"H*Ù”ÃÅ-6Iï.&hì^ØÅø@È6K<%–òØòÊÛµOo>D¾Ö£§¯“iŒµ6Ð’‰wÉĘÎaG!_|§•Í×È5µœHU¼F@MwÑ ™,ЉuŒ½”A˜Ùj´ivò@)F¤Ör"8b3œš‡a>£££å3fKžH£V¥—’™Ð¦ 6訑&ýjeýU×u|­Àѹ±žfãåÝTµ6¿sšª‰™ìư”b@±[´K °«E.[-ßöem\m{D¨’f)°t\Làî6ÀkÄî¯Q3,@ËÆÓ®‡(60Û ÷ˆS•[h_@²–rå²ñ[ŠÝ˜ ïúkP §mY*q…pÙÆhq˦_‰¤¾}ܲ«KMÃï©ú†Ä¡ß’ YKÛa‘£Yƒ¯¯y熃¼F‚âp©²j tÛ`ââJRfR˜½2ÎçKPý|kåmCÞXâ ²ÀÈ]xBð6pQΕ(唲$b²g3©ÕHªUvo¡H“Oa4µÌ<@œôÑzeiÙ3f8_ ÄWXPöh]Ÿ~̃€†_9¦À‹—ÖfF®9e{D`p`8¾Ú–ªšÈ" ³ ¶4I³ñŒ2}ÊJ,ù/.âdÑ‘k¡BØ­OÒÖ¦–&ÒÉ&’>N´n]ˆ³áÝTZÍ•ˆÄš²¬^>ñûÜχ¼…™Ä‡~¿â›×úšßHpÖŽÎg×m§Ë ÐàM…,° 41)…<T·Èµ…ªœå@üZXâ'ÕÕ éyAŠ xÙL̈ӤÀ,¥xÓöÁN6¤©p4%hxYW ¨âÇH_lC¾Óñ‡*ýS?ui³ºÔšT}kd O^¬P•£]@6ƒÜ­ýæ+Ái_ éh‰”rÌ8‘m¼¦øÃÑTñ•ó✪îêÍöÀC~Ûž,Ó7YjJ,Ö«5• m…Óv»ˆ¶©¤C×1ÍjyUýûúßÖ*IP¬)ÔÚ$Τóá-ÍPU[CÞ…Se¼û–‡ …Ï«’µ$h×>ÑâØ‘ÛX ÑA/±CfÁùZ n)àʼn{yùß¡t,_~ùe¯  Å.eÝÉJ1l{ß&æ÷ñúI­Ë§v1ÍLÊÆ¥ðú¥¿€>œGÓB¹”ŸR\šøxöÿ<ª][ãõÒb¯¨Ý–Z‡Ø$Ì2¤]ç!R›_Œ/%à»”ãèD†ò6ý.î]8ìtZ®J Ÿ¥ŸhÙxµP•‘m€ Þxí!‹˜ŽS’ÒÑÛ¤FýÓæÑ(‚0ƒòÄM޲ɣ ·4°î—ðÓëŒI˜*ÙI„óø6Ò¡5öâ¬o"•ÇiÈÆèw-Ô6'qƒˆŠÊžéOYÕå±z÷_µR•C-›·>D€ƒÙ¾u·£v*ËÐØÔÅ•#,É£©­{XPV iÈyû×»ƒ¨¬ Š;2l/:ˈD)…‚m ŽäÍŠa”!:f¤Xµ]ÈFÄ1(…Dxˆ”à˜|ˆÔCìÜF,}²ðbà#ƒT/1=–WÝSm¬ª<sÊ2 Ÿœ¸˜×yä˜f®WøùYãå»6¥’kM¿¾–4íT@Ÿw><“2[Ç’—%׎²9Å›DP d -'Ø ª4„Sv)+ ±kÁ5×q>÷ûkg?ðƒÅ™ø›Í¾|út >úcé~¿VgÎ{l‰™ 'efKþlìzbÅh4?D`ãNn×ȪÎt¥”(T…àJQ|å §IÉÑ)×&²4ûu¾8 &$A¸€ÁŤ˜›Íâ×±>þøãfÖååæû?ûª­]-o_ŽË²© ,ý˜Aæã*ŒI!)Ë,“mI "F€ÛW…B¨áXöÈ„HÕYP ̪šÇFnfÁKÌoù¡H¯pÈZ6˜%YfI­¸aôM¸À$–Ry¸BKÖ~Û¸e‚–8m$^mwšìÄwÅu÷ë[þ÷ÀÝ¢«zyàéë»ÏfhB²nQ‡ #ÓÚ^@€ã›+ÙÉšY•x[‹i ïHÑFˆÌOS°XmUÊS0C‘E1Ùº+ć³D,³– #¾O‹`ÉS«c:ü Á±ðÛΘIu8À.²Zc4g:æÔÈ”°šZ*‘bÈ~°ÿ®¦·Q?øÍ±ôÍÌî'Ó½g#™„Ùˆùñ]ñ^•˜sovJàÚ¡‘²<Ó_ï†D,1-I©Â!ŽLDàIK5­,\Œ¯vï•~€÷ß¿iöFRS}df£2Ãti úáS Ž\U;êy©á !,<ÙZe'hI“©BK*„O³%‚ Z¾Nd†Ó^ è'•Î¥q%âJJ‰ †Ä©DVE([k…p {@Ö®UIAàLÜ´‹C0q:)úÊÕv5O-ƒGS²àY—R•Ô=Bü.J ²RµXð,‘ÀuŒß’ß„w~Yˆ`"‚úNpˆÇ*òÙüuÈçwH«‡$a)¶7®l¯ËÈÉyz‘¦¥ka¨ò” ÅoĦG Ï”w C” 0%'~wŒ@#²öÎÑ!¨JŠBóH7ªeYÊÕ®ª 6Œ]§Ã3L%<³¼|zµµÔN\`)è•ÍœÎP€PSú¬8)UJtìåO ®Ð<¼x‡¬ÐÁêÈ‘~pZòøMØ |A»h™¬8°Ô]9MxRY©æT¨*}KˆÀT‘ûý~¾^oá às¿ß9öún æI¡É_è п{¨‘’:®ÖÒ<=•Úµ…Ý-hæacT¾Q—M“¯¼’.´¦ÔjÞ~ÕHuD"R–^«úÒ²)Ö ‚ «m Ép¢ÉBšv©‚Ia¶ ˆÑνͫr@–N4 Îp4 QHr†¸½sôÑGüšÎWÝßœÝií×ÒHyÃÛuApóóŠþÐkŽc‡Pª¤QmGÐÞwYäju³í“"«/QÈ4õ¥îÛ¨ïñçœ óï—èèëh6Þ¨ƒiUu>R~ð0¡‘xËÆk×h ×h™Hx·¸å Â)(IP`×h|ó@pøkwGÄiòNÁõF™šøN¸’Ç%^ÊÆ»Ž.÷Œ3Ùí‚8„OØüâb¶’ƒ$XU:•ó²î “À[&Õ-d°^…,ÓçcêÒvÖ±Fõ’r˜@ÖH•XÖ()΀øu!Ò T"…#KvË,Y ñySc†CWŸ‡WûDÖª 6ÞŠãåÌ­étðwuB "åìê­‡€µ Ïy"]ð5•²ÔÚ+˜áDhÄQNüêóîaÀOG¶ÚéËâßxõíÄ‘{…`Jé.¥Ü$½HI…óp´&´¬ ‡ïpÍ\‰€Eƒ`"ŒLßl (‹IÙRëÎ ‚£ÊH@…@XžÊëOÂÑ€<©¶_#1‘f¦£ Èë Ac ”KñÅð‚f+‹TkÙ–ÓÔBìCcúŠÅ÷ý¾®òꦑßðñu£/Y××ëôx{qZ#Ã-Üçé("À©1Ûd^Ê!t:‡AGWMm„8+×®«œHÅØf#ÒT  VM G,U¶ MÇN'AHW­ÂÅ–æÄPÞvx/ôÏ0ßÉh~ùå—}㛲—‹íˆT±“í¢Ôh*±BY±t˜!Rp±” ‘vaÔpA§Ì€<ÓQ+„àX¦€ÃzÖM¥ yv_*ô›Ó¾/\öÃî~+Úý©‘gA¯vÚ @™Ñ”5€/†d–ðŽ h›LÓ@ÂK±TS‘bŤ<ÁRg‚ÇK‡@m1š—#?½|úÿϺø2˜¯{RbØ{gN¿ éîYÜUÙ=#(_J\V DŒÿþ¥,Û$m"X‰˜u𲦭 Ü’­‘ ²gxËù8Ïü³¬%Y-®žB,7‰@*ZRe¤ ³B3A|Þ²¨µôTú¥5 å+Z÷yÃkÑÉÐo#X“à8O©Ù—5!ë¨eÛ‘Öåcc+‘%‹@-LµRb–>MÔåUÁSЙ¹ñ<Ñoq ~Ê$ú·}55¼å&ñéØHRbY3[´“!ìÚây‘,F`íZ€¦)ßfy µøûQ\zï^î,eqf‘Ó ÄÔâ^aÆÐ¡Ž+¯–w]lV¶9ñKÕÞ’”ÀÞí®Šée‰Ãjw×QÕ™Dvh-nZ…Rn$âb#¥¤¿K VËãŠyäfd RéÄW[9O*~"™¬y œô£Ur÷+гtÄæßx@MyÌÆ@ø/÷ŸONÞ™<‡ŸŒ‘º)$< ª!A±;¯ÇoW…\“Õß’¾m½ËvÙxˆÂj»3€íGJT"1A¶„@Ÿa2÷YïýÆØ¨&'.5Yü>y+×Ý!qËivÊ<„?mcC´#¨J­XÇA¦Š!Ûf“S€GèP-‘S¬‹ÔŒ š¥M¹­ÑÈ¢ñ@­[ ,)£QPRw>NžU’T"ØÞ-©ñmG@Áñº£|…̺©ÐÞÂ|ßïC¿ø.n £ !îrC¶;“UXÜ6½=àt4›Ù 3„kÁwtaRÀtxí€j-iÖ"fš*¡•Ò:«G6>ÄÒåFbHœ¦4@%‘Óçž¡¯÷FøòßiQ>s_}õ•'BÇfÑØ ·ÜÜÕÊv2¥xåÎÐ TÅ\ ­*›bµ`îZ D«š€!ãìãfU˜pf)ÛD&˜>ÜOGjé[}¿ EA­yœÏ5Â9‚Êׂ2ÛR §¥³µt jHµ¼,$ZK4ŠWî0»‡Ý·R™ÂÊó@A1…»Ž”Ÿ^|—ïWÆá/1ûôϧIÐ0š\kGÑäRh–ÞtÀp¾Z…! C2A…Ƴ/Ë]Èâ×åÞG6ŽG|•>½ŽYT"¨¯ÓëSÂ[#ú,>K_­Ž+‘eZD€/EJ,Å»^ý¦Ö˜Z3ZÙûîÜJ:U÷O/>‚ôñ+¬ÖŸù:òºæ·þºæiÎm§F–† t­a›/m­—VÞiðIu™ªíjŠ¥x"² Þ9ðZPn¹g H¿‰£\Öü[ü>ª›»¦ôõÒší 8†—2•hN4Håb8sq’’R…¯… °Ââ¶,V¹½Cè@Xc€øwK„/ rÏŠë^–²WÅiZ*!…®—åÆFÃi¾½4ªñ˜,VÇ-ɧÖiêˆén:FcX ^“y‚Ý“îº2²˜µX2×È»¾-5d²)DÖWyšÑîLY‚˜¡!®s›ˆ NG(®V hS|HUiò×Vþû¿¼Ðtx ¨GB1„ºÓám,B)̲»G!â+á-õg‡gw³©ê:­5>ÃÏcRӥѓsØ×%¡ (K³X•ãÀ”¥ÓåXbJñ˜ö»«X£JÖBrˆ˜ˆY9+¸sBpX8š]7‚¸›Ï$RÌr¹JO-fg.ì½}ZÂ-ӟרë_\ Ô̆ŒÆ ˆá{ bòw}´ªeùó}¿ßóy‹ÿ¹L‡À{Ãð¹ß¯ú˜ÇRwôMcg–æïjÚi` í´½C,m¤ÔÀå‹ewѪ4šxgѧÀi—J_ÇaJ"@ŠY-ŸáÈqò”é´U@–²@-ÃËÂ+·de!pŸ |Â3m©ïäýæEté6pQ:ð¾Û[GíXcàØ¤ËçT¥ ð]5:»åÚwb-Cì‚Z{ì@Ę ãf0¡%5dóجT"!‰£¥_U_ü#¼ðp|ð÷h‰ØNƒ™Š”xc'¥]Û,›G2ó·4)%ÊÃ2„‡0)4^_Kä‹ò” i_R>'y”Åñë•„÷kuþNˆäo2|L?ö˜!q <³ ârØSìê[vd)Óš§X öÊ<ÝäbžˆZq%’%«¶¦ú €-ÛZ‚<0¼ Ÿlú‘#¤S¡¸.U}“G«Å3gR•û@ÜéUâæMy»k‡”­Ehò8ÆKMªÃôõÿ7Íù½ñ~ùGÓ&ä“Ò”Ù,èÄ\kóØÜ·îÞP"‚Ææe{w›ŽNß¾( ÊÒg]µMÇ©*ޏ»îå?Ù&õïõÐ;fƒ ì—7›™™ØÖ²“1Uü–÷¢TV­8œšZqÙ"iã8iLÞ2ÂÈWÝqÍ>¾ $N´K زâ†ØÈÿÐv/K’%E†3À‚ ­áù^¹…¦X#lGd>?„Ö!‹¦+«¢lam®¦¦fîçÄ%£"³{Ôòfp‚I5•i¶Óœ8 ãÀYúÈ]qK1²@mK)1ŸH—Þ½‡Ãw+ºÍ.Õ3a –Ô:4AcËvùp6ƒ»—,œÁ 6<Ð’ >/[Àß­¾vÓjÇ¢g+LVmUÃȕ㉇D ÐÈžûçt7+¯†9i<Væ'¤žô;¦Deh@%„¨»NãñˆD7eg¡šJ@K³mŒR !õ’e©MP6©¦µ´&DÖ1>¼eóÓ2$Ä’­—ò–ü¸6›Ç²©bŠkdlHÛ)Ua§QÜ0J€Ž:¾«Ø­élÍV6…– y¸3ÔEŠf#MK>üñqâÏSc jÚcÆr%ÁÛ©_,ó‘¿Àò[˜=ú0Ò‹Mw¦u¼£Ží®Öí bòMkòöXÉÎ$òöeB G»tœoÉ\š˜ZÀ_œïÐzvPÕ¥tCV•ˆXa3ów0š=ÓL_vç nRbÛu…y Mh‰c¾Ž^¿ìƒåÞðùð¯-Ô”lÖ²,š*‚‰fx·–íDð4d笼«Â‡D+X9>¯$¾à‚ÒT]Y½ Dœsgb)h†šRöÁÿçÿúŠø÷ÂZ¡ßj `c7ýZËêκëzÄ•EcSH¶ ¥0Ó )æ(`Äí·]Û©.õM$NUÛùþûï=ƃ7©áRŒŽ3µ¥Ú`KÞ`)A·´¾¬céðͰ ÉªŠ©•E`–õ ´ŠÏ4×<-!DfòÙ¶†`åyN³á¤\Îp\êî׋Þ`@IDAT:0‘º¯$0A›$C𦄷T^Ugh©Pª— 14ˆ‹kÙi!–¿Gº¿Oøõ±×ÝkGMÇ»Ï 6p½ÚÄœÝxJ<+ÂÝtÆ7³«Öä‚NHM éLâ´TÞ$‘Å! @§—ì·8o™ˆÛF»¦j3yÃØZS‰YÞH-Û²ÍâÈfȲ@qÇ¢¤-›BJa“{Ä}ñÏù©ýGïÍ®.Ý´Æ`Mn¼&·dp嘬`K42|[«ÄÀ="pÔJYVh;@„•#ˆÛ¦€fçPIL„8F yåúÒÿÞ[‹ú6[·±y¯I¶#ËÌ^âT•‚£ÛRŒÙ™Ø£s8²Jíñ’¸’ÎY€ríÆÎâX–ÝrA̺bd¾bA— rqxˆsÀa–•‡ã CÚ©2r´-×ßcgK瀉æ|ê.¦(Æt¤ªÄ]©ºCŠŒ/;µ¼FžNéèR£ª” 8ÙÄ•tÕb¦Ù~×ZaYUÊyKA‚¥ÂyKÖ<©zQfbÌ0+´ëóŠÛIÑÍ.©Ç+ õð®gá9…ÙªÄ !õÐz”§f¦õ2²Ñ zÍ|dÅM, ¼.Ãe³ªˆTeÙ„² ; YK):SòX’J?Âü: œ¯vœ-ËF[6¸mbjÄ34 ,Ämd ˆgC) «ÃW•B8¤€wVRdRlYŠ&¾k—,ýºã MTÊ©Åöìã0ø,Ð÷"¾øí#Ùÿn&÷þÒ[_K3¼Ž>jf{dMB¤Ónª&t5Û P–&hk"–C6Ý-q\Þµ°S¸8ýÉ&\@°§fd4'l~ ]_jkTIc ,PX  &„Y†ÈÂ!¶Ü^ÚµvÉ*Á‘ªÍOûR þHœ}¾§éÝÿÌÝ jÝ$b¦Qs¶}© _ åfhÎÈj÷4ª'Å«½TÏÌ ”–tž™—‚¦QœÜ&.Àä{JÁãû­wý½·«¡Æˆ2Ùò†ix“D«i`µ|VËgðöÞ™P¨EK­8MË68\ w#ßá‹éäÍ™Pí±¼3 îÒkÚ<ùš¸‹ÛãWm—Y¬‹%¾eÖ¦Ôv–]]Ü0ªe!Ò,"(e)ÈUYV duŒ/Å€¤ø5ÀU1Y…-á,œ¿4‰#('…mM ®ïµ¡ÿó‘œ „SkÙÌtñÊšA,°¼oÜ’©òsl¼Ðû’›çg­ijÑõ²´/Þ0m§!qš“U%U€ D¸_M%pjeÍŸxÙdÓ1ƒ 8_ÓRœéû-Ä3@7yCê%¸¶ûñ­¿1ÚNœûTø BsÆÄI$Ü’!ðDâðo–JdÕ:½nì y%‚&yWÅGX0rA“¼-ñ6v}ÿ£Î§3˜3²[!„ì–‚‹u†ì•z©v×ýÐ$˜QU|Riê(ÛsQ„f¨„Ž”¸‡d%¥ö¶$PmRízÓ– Th)&‹°Fánβð&§‰Ì¾ve“º¸‹[v…ªŠu9ÇjímAZòrµñÌ»iª$-•5\9DAèе(‡t H)AKgKd`O÷ÈÔÐÓ@MyÝ^»ª´t¸bWˆ+‹ ”…Pcb©mJ Å·£)ã0˘¼eœùM[—j§£‘ØŠ–kÉËÂmÓ„k ÚvT-¹*äKìŒgþªpœ›—©ú©Úñ©S€ȦÖùA‹à¯ x÷O9Â˽wòLêw|d }ͯ]Ý›vâ âlß#RÀhvÝ!é“‚´DhÁŠ+ Dƒ“Õ¨SŠC!Kªñ ‰›ß,Xº7øª¤˜G5©vº3A€ÓÑwUÊ=c¿ü“·ß7†µnB±ŒÁ¯x±Ä”²Y1œ”Ò9䥺–øíWL_J HY`¾Išr“X2U<Ü s†¼Ð쿇\­?ƒÕË ÍYw; Áf^Œ¦$¦r»f†©‘$qª:ÉØÞëÕÒÍSId1‹P|÷d¥–]‰`4Ù&oÚÔ*4ªeÃŒ_-ƒÐÊÖèô»½8N¡.RC”ǤV¯8GâÌAy”™Mj¸€©Ò]Šát¤Ýc‘yKR²hîÏæïF…ÓÑZª ê{u8β>>Ï,+k¡—eœöR…ŽˆižBË&lˆQÛEL£™g H`jDþד‚‚r=³`¬ÑÚ ŒX'~õm˜º€W[J°±¤:8) X soVµô¥´NÊHÉVW sÛ#2}H}áâI±ÆèêæµsRÈåÑË2„“2 ÅóÃ̓в@Ìè´ß–fèXÖ:Ív ìÌ ®i"ñ €• ÈѺ¾Î|4©1óšNVVœ‚#2†¯úøÔ_@äå¦÷ý>Ur-Ú£î@º+€ÓƒGJ9C¸e`œ»œM¤òÄÕZ¦ƒdýñƒIj-([£!d!Ì ã¸¦R›Ð§‘ ¤êÅwÓÆ´”åµöCåF•`ʦ »rK4qx2L§ ÷ÿÙßæl¶ÿèý,Ýßx!E¬ŽzÀ²‘ à–R&œ5?Ry…–Žˆ—‚wâ–•«Í,R-k!Þùô}Àá(¤zɨr>‚Ž4AGä Wò9¦Ü»ÿþ¢Hš Ó¦B¦ii³<£°Óë"Ƽ«A¢ñ©íÜ–ª*ÙöI¿1,0„2c€ªxK©!ÅpȆ'ž2œU“g²öÒÃ!$޼¾ºgà8R» YgÒä²0áv‹Í£ª‘ò-ñ-eÕÚÏFÀ’¢/æ#G(V‹ÃVaøLÙ$Ê'Œ pw)7Iúpëõ\í&D_‰^¼,ýšZJyŠßßR þ-þν_uÕÝMÅk×Ù to¼Ž¨,~KU ŽÀ=ßôp°w ÈLÄGÀ´´xçЦ)†c Ð:“˜–8f°ä5ý_þñÝ?N£6¾t×´‹y6šƒ1&è;´@|x§ŽVLÊòR}Ü~p§”clïáÈáÀµ†òzÅlŒ8|Aåý¸‰ºRÍ&5~AˆóTÞí1ðþÀôyä IM;¾«·ôPâÅÛE|4â,œ];qžr¸s³îOd-¦€P_8>M9PU:@A>ñ¦ ì¨Q‹› -Pœ•5‰åæÄÑ”gÚ1AüÅ ÚNøã½BÓ{\y¥ôسTÙ%ÔCÌÇ!$®¥m´“8@Yº˜C,k&è6EcŽ»3Å©ˆ£oSеNY–…h†ÄÜ󔕔´#qúz‰‰+gŒr¸Ÿ!ФŸ2Ùq^ÀÞÐ)ÀiŽ/`¥² Âk§*ÜR€ffWt3¤©ª¦•@XÇ«„ÉZ’E à²º¸ÛT š#RˆÌ’jæfQ¥ÜKÈfLç¿›ÞúûJ‰÷—Í_Ü<[šbZ%íרhöȶ )l/!Å<£à„‰ YÖ¨$)`- £Õ%ñËÑç0æ tÕ€;Uqï"b¦…’ôÙ6ë! ÍØh-qŠ+4?B[“Âw‰Õj ôKœ>új˜Æ{—w ýå/¡Ó±Tk V÷3ñuók±ítÃ#ãÈ™±P·M%B÷°¥rL)>ZíÄ„3KfÉG \GUÀÆÆ¯é¥Ð¦ú¬”­Ï3w¬wBNX—4y:Œ2:6ƒeà’0Cct2ÍÐùhdÚ†‡Í`ãv¤¤cDƒT«P $¦e| ö%fb!fK1²B9Ü¹ÃøÝ_øÅz™ó×)|ªQ_½jÐåxã4ü}%í·’Žh»2g¨ÐG!¾,ðSñ—S‰¥s+äÖb UÉ2 qH|ÁÚ;Yœò¤ ªMPÌìÔ™WeY#±’XÎTAÐîÌ@xÏ”ó mÙ!ìÆ°,Ö´'j@ÏÀ<ƒð®>çGëÎm'Ÿ²Ž¬-`&¨JPª!KŠÏpϧ5ÄÈÍ€“E¨Ü$ui†”«’(Áì~° á—ÈÖ¢r 9Ï[k§c­ ¨M¨‡ 25kú\ïB#P0*f§9PŒ—P`À‰[¦ãǸ• 0Ë!%<¾@¶åa>kwÎ bôÆ þeÖ;]µšò.A{´ÔR÷@w`SE“ÝY â„ 8†ÃH•åʼnÈÚÄR»Î™‚xjK¾”ÂHV-‹&À‘µdbÎñ!Ÿãý›•ï@7¾éPn š‰îq ±ã·w^U  #~Ù³‡kð$Bä SӪǴ¤I§ÓÓ]”‚Ïã'ȳtøf†D€´ýü5àÇ'ÀšæTéÅ;|Yc¤Æ°úò é®ÓQˆ,n)fðRg Ogß² Ö´^eãKò³ ÷8ÂgkM°ý²”*Hµ²¦b²JxqÐz°¼I5d‚¥¦)ñiwú/ô}×…8M>{£l¶ámylMF¿¸ýŠNÇh“Åæá‘ã¨MÐRÞ%Ð]à@BT)I ¿ÚüÀkÇ£«¥Há×}3¼a@ÜFx…@oý¿Å·$ͼsêoûh”…7›š!o6‚“1m¯rÛÿÓ@a`LžDw§t5<»†Ü™âø “Úðv†ÀJë…/Ë»ŽŒ¾e“ 0ánN7*Bœúò,2¦,IA ¶l4¾@S)wøwß}§ ÿËÌÅò½ÿn'º,Û©^Lìêh'æÅNÃi_uç©À²q]ˆv¤„`cã[â0ºš¬Ö ΖÀ7SQNÞ=4*‰_‰Ÿr}韠ågš¯@ôÔl†Ù™$ÒFȶ;ÙqŠg cò¤" _I´8<$?mVU-L« !±Ã± L!205—²qç‰Ì¢1„ h‰¶ó¿òg<„n8–Ä)Ô-Aø‚²î@‹ˆÖ´–];š8DÖA̳pü”!KQ2ˆ¸òÅe7^à§~% ”84Ë”´…Žh‚5]U›’tbkª„EØx§àz³Ëù’Àw]ü?L´Ӛ¬x^Ç-›‡?ì‹S¶Â²ŽE­s`[æYÊ8»ââ;©mðêðxžÆN‡¦òÇ¿š¼ÀyØ—ÚцIݨ†¹ïËÒ=¬0Ñ ©ÞÀ–ͯŠuç´‘Åp…ª”Ì €éïñØ0È)¬¯1H%Ž®èéY9ƒ3´ú¦f÷lUŒ™OG,+¾_ KcOMª^j–‰O .Ž/˜…=Fz¹é ÁØ ) øÂ…W"…u¸Úû2Y]êÎC,•ãw8‚…e‰ôE (.Ù^jgy¿8 9¾añ•ÉLÞ.€)63ZçLAÌ\ß y´7„ÄÉð SCˆÜÂÑpdÅ@µiÖ+™¥c‰Y–æ I‰=Äø4+Ô%²î‰´Y©ö++ˆÖvd“ýýïÿ•¿ëæÝ¿º›Íü™.dYÀ—j  l¼vÔÀ¼[B &ZF6&\9oÉËv{1ÜTRqvë‹öæ¢ßÅ£áøé]¿Aä‡~ð,Ñ`ÍiðÝbƒ6˜F‚ Þµ£± ðÎK±ªdí·#BîÄ0¢·ÿH!+OÄR‰,7Æhdc&»™ï%È–+°é“µ¬œgDP;4ˆG.äáÌá3gÈã#HE3§WÓ3µâÈ÷“O޼v:FVL ‚›§)xñO‘‘ÔÆÓ4°ZmOß2_Ç$žát\Å–Z£)_­˜ ‚€é›ò½¶”’hR‚†)F(…Ã4å“%xa‡Œ¥½#4†B#!x*²Ü0Àžx± µ†²ÚmHKY8¤ñTÅBàÍ\S„ãÕ"œJd#ð8öñÐU1„ âØ,YVœ`趇S“RηDðªŽÐ,géT4•À iâDƒ¼)´Ä‘­i WV·ìUxr*yƒòÍÑïóÙ>$Ñ´xLÖXÂ6ÑÄ=pˆkŠ@d£ÃÛ6|óT{tŸ×’5aåËá8D•€ZÁb´® ²¸Ë¯Ñ]‘ž”¦ ”*ÊZHá(q;v  }q;jZ´&Ürà–Z ÙQ“ G« Ûä‰[®Kx`S‰>w" Q¿óÚž¸!ìPÀš’+D` !HŠG¶å|Aü˜Ñ¤Ñ¤6è€f™¾ø¾lRà "󬦂ÔÀ˜ö'®¯w-v} ž 41o¼d`ÜT–õí Úo³‘UΔh„Ù%„ˆ‰ðh¬¥ ^%¬Fø‚dÅdSã£U˜Nq4SQö6Ñ/>Úfäz“ì_ŠÉ¶£ÂÁ b)q‡iÙN‹[B„ Ú&³#1ß»L@ÊmÍÁ2"˜©­{UžŒpài.Hay„µF;s•j€ÍÓØ–FÚ$È XVJ•¯³ý/p{›î“­æ!Þzi]<§¸XSÁp‡ßl-•y Ó°YAä®H÷gÝO³ƒ8@;ôr"9Zs×(q±€ùdô½Ž:¿þõ¯!nRz±v$0•+t5*Ž (…9D|·$È;jU1 îm9NžÅ¼ RÕFg¼S¢ÂV#„Tt‰µ3*²Ù 8‘5•or+Ž&`ªøîå6‹ï-›*pí®Š#XAÖ@åøÐGJyÖx@žæäÉ}ÜóhìN³åhZO¡aÔv– ¦p¦iøËâZ‹¬¶“é@4•u ƒVí–éxÀ/~•÷„Ð_þIШ} Ð9Xn˜&ÞaZ¶wËãÝØ !R¬ñ@ž~¤\VU‚n³˜)ÔN÷ÎÁùÈb&"ës®—ˆ×8ÒFº.Ú0µ6’¥+(ÕÀqd™iY‡‚Ü®h©Eûºó‹‰ 9âh|AqÊO_ð©ÈR‚ì^¨#úfÛ _–¢Å±´ÞxÍ#€(Ù$jQÐ ± I­%Ù˜–&{O!ЇÓ)›oTL· ¯0PÕ¤êØ’g 6[3tàl1‡Q†Ø¬¬¸;¡TÙ˜R§Ç͈/ÕÇ»&Hf#på–‰ˆ $… †ç-»(uÀdë"çÆjó%"™û~".¤•tÍø©§ëJ à‡bˆ*qAµ!dª˜ ôc)%|›êJå YCòªB–J,µ°4³r%ÍdÅ)èRm ¼"-•ó£Ñô„µSm_e À;¢â‰X¦Ó„|{tÇ—’…ø6ä7úúúåȾ©‹^šÚfÞ䀥lçÖäæÌ"¬ÄÒÞAIÛ‡wdeLÌ£%¸Ó†ˆ¥øÙøÈ—ŸljøÚÕBÇ•ËÛE³ HYJ)é¢XJ¹^@·v¤;0rúµHJ3¤Ñx)ÌqM¿þ“??øæÏNF—º·ÙšBXóóÌ!Á4R¨‰ƒà;à¥÷ЬÜ^»ÓàjQ¹á 0ä÷™Å)ËÁï@¼û×…ÚñiÔPª8ŽØlb«ë²,Zó+ïR¸ût‹_[ñ Û’çDoÿ»TÃTž¡¶\ <„gpúìNØæJ"ófãe1»L¥ÜÉÀÇE¯³{@ìq!ë©o4…‚¦B`–” ÕÃJ ï0'}Lf‰)ÄTE¤e>)±™‰ÓìZŠyLFX¡e´Æ®P iG8)W’0ÁÈ|­W{NH®J\/7yU¯òNؿ庈†ß-ÝŽÚ‚Fµ®ãÎdKYC†;%U¾ËÑó!‚-f&ND¶.ÎA•˼ãÂl†‚ʽ û½㫎ÿÅ;_mÕâ Gëv'5s§$Þq•ŠÙÀeÃíËR,erUe-Y‡ iK©@ë(àÎî2)­%PÜRJIüÙªt ×]£n¹nÂúvKàXæ‘éäÝ™–‚ÈÀLIB&^Ð¥ D v!f•DZđê]œÓ«ïîœø)¤¦èÄ\P¦¸”%gm¸røŽ1›êˆÁRàjvņIÊ´–ÍÜüÈ àÅÈ‚5²D3a !Àɦْ¯ ….bˆåh‚óFY‚·ýȉUÝÄb)œR´ià m¸f¬ZRbLÙ‚I©òD¬P´Û}1”& ¡ØRÑH‰hd)nIm—rF|ÞŽZà#¨UÅì”Z—‡wtñÒ¯£˜©e4r)›’òÕí£¢YW¢Å¥ñxYmóD Ü‘ jz¢Y6PÌ€ ¨$&¿ úàÿ׿þu1ð…æªùf3@ EÔËyqG-FvK)©Ü-ß ÊÛµBûmﺠ‘mYk Í`1¼5Ç"Å®Váź0¸.zá#WÎ7v³Y¢%ˆl‰™Ç)†;®d‘wKÈeká¨J‹”-Å<Ã!XÊÒ¿q¿÷ƒmšoÌS§è§ÖÍŸ¾m|}!b>„µäCbª•r¶.¬Pì4x%²+ŒcÉêÈÏÈŠy…F ÇCÄÁ ÌÿÞ æÝ]6Cšd¬½àÔÅÒí'Û–æ‰ß冰Jø=8tx…RD,é”­…˜eóhu¹/“‚H©²¤À Ù@‚âº#Thm%!S3öú œüi @g⦢#–­£X`IAVì Â:@#¥Y;œ®l#;½^ÂÅ@%õ0 ^Œ›gå–)¨Ò¹C¨¼¦¥Ð.±£É*‡[*W%°4äÅ,¥v­Ñ ªJŠwï)¬©€Ž-×+ˆÀØ8øÃÒ|¡÷‰µÎV#WJGfÖ "@^Äs×Åw,R–L léöè¸6R•Ž8¤”ðŽÅR1>²˜ucÔHÊ-ù•9å7þÇ4˜ͯK34çæ10$oþ¤,›Ó2¼»NlkmD*©˜¼¦/2_!D@ÙÆï]ŠéÜ h™*)”4ì?.â“~þ‹ ÕʃÂÍ“Tšhiòƒ‡´‘f«W1ß’ÁTÕîôZòžÌi:“hø £ñp½: ·M×ë>-Y)A]R°¤Ã[²–Iõ,«Þ[Yqƒ5‚^@Y݆iZ4²hÄ‹áÔ¤nìFR"ËÎ(Ï3)®#¤Jêõœ@DÝ/:"üÇë͉®výÀbB–ó@f‰ÀÊEL§Õd Q•¥Bf)îÜAÌ7Lg×H•ð &h"b…Z—âɺT@†F‡UÇ{k±ù¦UBAºÞUQ0k~ î‚5$Z˼9ádUA·©‘ј!}tWE9~]¢Q¢¶Û” ýú÷ˆÔÞ˜Žþ\Œþá5€1¶xÖÀ!²b dâÈ-yË@±½÷F¢ò¤ê˜œaUñqT!à;RúÀµöŽB€ÉKM3æZw&hbŸý¿üï[øÝ¶ý3-ì¥áIœYníÚ2p3c®ª}9OVp%½R@:.!~ï ‚?kýSkwz!↴Dkfƒ‰¥øâ²+·/‹NDSå¶É³©ÉÆÏÃïS¹¬xÊ#K9çJŒÝä1)ßÛᤆ#®ªcO(U#̆ç]d ‚€2“Bf1DLäÂγ‰˜wOnå®ìKÞýûX‹¾Ù´vÏèb k€–Åyc˜‡Ï0; Ìl{ ‰/¥ãp˜÷+íh²žj\SÊÔ’O¿¸¥Ó£!;2eK8„Ù¤ÌðÇ?þQáøœÀ݇H!“J "àfK›‚Ÿ?tY­€ÉšP•ùÅð@ˆ¦ôþE<ã¡IA¤ìËR,àáM¾3©êî+ §ŒÌŒÄC®ÕÙµ© ±)…u/5¼¥FÖ!4›]„«b‰‡_çtnò ®þf¢£dÇÞäM…&bʵÃw•J‡ëil`|“e¥,(i|±‚ÍŒTQíˆ^`dKü% ùb=®$òðqª’u†b„ŽÔ™P@KGÐ Û#÷뿘ò¼¾þ]·.M+î0;†o>ä`$d3Ç¿ƒ…Èh8Å6«ZÇÞyL4&@ÈBÄ5%’N'¦ÊòåxÙ”oÿ7 ýf«Wcè¾,§Íæ1g²bd^•¥³²b§ÁÊÂÛ”lâJÚ,Y`·G|ˆlµâaWkyGÚŽl£¶Ëd#Ô‘x”f‹V_ž¥Cßl=H!j‰´M4¶1p®>çÞèf o™ˆG9¤×Áæ\áÊ+iÉ+Ñ­×5ÈMA O°¹Ù0‹y1‚½ÇÏC’•½ˆr†£{ÇeÙð@½,×n‚ ¶9qô-[÷ Ò”"iBäʉ3ÃXÚ {cú8)ðçñ¹kY1Ÿ F7-A'Ž/ÛÜ@ Ê9V­ Ž%Že„²M &Bþ4b|ï¿Í­ªIò¤’m©3"`ÔP˜ ÃWå…ÖÖ*‡(É#³bäÞ AŒqeÏ>mÇÞ‹Í\ëº[JÑg òâ5Nš1-Ëto Ct„ \¹.˜ÌHù¶ïwÂ^þÂ@ßž }>¤õézõÝTm­iÍ3ÄF: ¸#Rn#˜p ä<>ß %ˆ#˜¬òh÷líx†ÜÙ6!¦ .‚^8¤›|å)Ë.„Á²ñ¥p¼*)úweµ²M+Ëðy4ÈŠ•WȳnŒ4)ÄWHYÜõõµ–¯ÿu½ü+¿Ÿåzv6óܵ^µ~³»¦BS[Œ‰ãôð·w[–mr %~â¶€/.À‰A•ÄãT d"©Z$Åkê4âÄ'N¹ÿòȘŸc~•¥¯= ÓlNqSm; ¢MMJ÷¶ì:JA˜àÍ Ö̆Gf8M¾X‡'e§Ž…Á»4õµ¬ š¸›§Âæ‰0d{©Ÿf±ЊÓlr¾@mWY ÄÀ6ñ‹x6»©M‹6åžcˆgû¤.™ÇUwt÷´H<.MÊpÁô«²Ðé‡+ˆl0M6[Ùûv(0Y%Dº¸õ­¼ó !d›!5qÃðëÒÑ5/E Sܲ4%¥Ò´Î ÒÃÇýóÞ?k«ËÏš¿û©Ef[ã Ól0‘@ñf7‰Ól] Læ¦•íØ•0 „oþð. 'âÉnGÕb‚'Ct¶MX OR•Ú˜ Gª±¯LM[œ»Š(²µÁ,&‘n S[pmçô`@)%ªâ äƒÀvkéàzRÓ%-®ê#[a}“Ê+Äç‘!|cV(NÄd1ëQ$¨¯ñÄkÑÀj‰K±Èl¡FR8²A‚óá˜"°fËÃ!|¯(@f¼Æn¤¤®AÎå‡qXUÎÓ7¾þ b£Þý>ø_/í, °4OKCv>qd-¯I³½XÊfU¥ãÙP9šÓèöÀ‘ÂÀLÀBòuw2p1_\UNK¾vS‹ß0yœ¬FDL°£pÑ+á¿ûî;OÁh_cæôf·ÿWƒëbZò´Ááú283oS F ˜Ž©\5 É»™‘m¹*1D¶BOÄÞåXÂeÑØ:â°vzŸSªØ$ÌÒwÞ¾àGßþóŸû ?ÝYMófƒh”ÕÔ<61vÖ.dÍ©œ… »ƒmGm„Že{‡8åìK6µ4HVmÛ3¸Ž|KdÖ+!ÂT5RÌ{ AàÕò•“uYíx×wOâ(,`˜mŠ—mS: \t"@-d™ÂÚ5!ŸT]dïµ–íZ¯tÅ@âJ ``÷j…ŸÒdé$Î÷” ¬ušnZFÝöR ¿ÍÆÈDËÒä-q¤}fÉàÛÐü!;´6EYgnõ—?Ïû®Kù§“ÑEǦåÍÙÁ60­,9œ·…. °tïÅ…l8o§cÊJãwAý¦ª] ¾}ïÿá{Ý*ði—¾Úµ#MM2~3@›¤!Ku)ãWخێeå‚–ÊÅ‘ÖÉ ¤æïdv˜²#S§¼«Ü$µCÐA¦c‰@‡©âÃ] K £`µ™ñ6!#HвÇ)´D¤àbå)8aKÏ!R:Å•!*f²ôk'f𻯠¢Šl_¿7›víR R820)+E°M!¸ž7Xdžš%d%ÊÅønþÁ‰KÑÙ16Zü? pY&VÈÎ@ÏëhY¹B òÈô¥¸ÃmºñºÈÙ SÃÐÒZ-ÆÙ~tÂ?Ó]gtMø¸Òá%²4™e PF\2gtAx…²€DUaò1/ùs!-ëhZF¡=*¶YKµž9J” xLALÊD”TÅGv8R@PÅK±†Ô}SÅ1’€lšñC›Hú@±‡Še~K qL…¼‡ÿ¹¯p^hºx{äïÄ׋O\S&îØv­§ Ó„ª›_ÌWŽ_Îï ÐNûç}RÀ#4¡8ý1Cº‡õ*[Ód×¥Fò¬T╤®cØ,"p{·÷M^!&3̤ÐBTÕ·v8¿ýío¿þÝ?Í¿ÿýïžé»:¼ŽañÙíóQ\ªI€eùž fÝÃf»²À”i¶„3 }4ü¤Ž”rÌnwK‚|ú4>))_¦IS,%l‰\/}YšdÌ’ádBûî è ð`5)Ö ÊS–…8K»C¨ïÅ}AÈl}+ߦ¥ù^>¶€3œî.½ÄÍ_0‚eˆ½Ø¼­ /ØÉât;º.MOJCšu1›»BJ¡ÀlûÔðÑø¤Úl½0ádO-³¤ÃÞ0iÂK©‚PÈ–%‹`©‡×ÚÒžú§içÁK&PÞje-Ytg¿e©am¶ZÞ2P\yLch´]Ôh² `†¯ÿiÎû쿵èÄŒ'»£kw– Žfl6…@µ ~ç‰Ì#÷‚u$®Ç¦`ÇRk…_ÊQ8L⛊l…šú*ÔËÄ·¡ü²g«×U6[ãiÝ™¤L7° Œ oNÞÅ]y ñÞ*ˆG÷y_QRÈËBºC4ª#²Î*´h„G‰¬¥“ËvQ*‰¯ƒ4¤‘ FÄ^’- ÁgÔX²¥ð-)+A;r×ðÀJèxcÓü) m#ÑšML„GÐ¥¡ ‡0Ùb©æl¤ö+×1×b‚D”G6€”áç«Â µ `%–é7€X ëëÐh"Єg–ÀÎD`²n*%–q($b  9á„Å´ÇŠWÛ~µÓ«Ô&ÑQ\IÊÿóç?ÿIq—MŽu Ò…Ä.Uý=F£`”†°±!)À•+L„wF g KÙéO h±d›ðN†—R²jš rcL\;%ÀðüÚU{%×ôó Ù| HñFBÐÎ$Ý@q´Xa LŒP¬Êò~2RdI9^wK&èÅ>öðÙç¼ûi’Ÿò”ÿö·¿ùÀ8»«ŠyÞ$R8–1!LеG^vwˆ‚³lKH <³´ÇÅ‚ûµ¨Bà]­Ã/«dc¤Ã¯ióXF8m Z"@AV­x;J’`d „ޱ;jj‚MâQ`fÌ.(¾,4$%°T¢\üªwÿÞïúºKO@d7mÝMÂ4¿€‡3 š…Âf ·#Öð¼EÓ¢]`ËŠ)äU•ª*}`§¡´D«Wc¥Äp?ý~Áw=#ù„qÙftÕ4Úå¨/Ü™eÓ X›­ŠZ›2átª‚d™¦e3@èTRvµé[.Ph©–_¹¸r´,š8q^ YVÐH–ìžµDhûÑ0YxRp1\m²<ÍUë-…8¦ Éæ)’e`Ë{¡ÔÄ2CÚRâkäs tÁ¬—¥îyCâã°{áôá˜jX,eu}¥Î×$6Ž î¾í4RË«&{º>çl$ËFMD—¨½üwÝÑÆˆ¿½´kœ>ª(ÛÞy›êÂÙˆ ­.–5åÍ`© ¿lΚ\©$ßNÓw þ©)”Bó|EÙ$õª"à»4˜]8µÉBÄ&¬¼Tâ| ¤Ä8|q…R˜<ërT‚ÓF&ëÚV…†QhŒ,bCÓM>‚ ÎE?“X2jí&ŽK6Ð’ÅDƒ«EZjÔ*FàWr“â3åñ-©1³å» ÈãZʺ‚³³Õ‹Á2Zq¾“âteÅvÊWR!NqºÊ|Û”ò8r A/ü¤©$Ý¡óxn‰ÖÞL'ÖpÊqlF¤Þ4]G¶ì–‚`ê8…m`sO©•ꤔ˵d¤hò‘‰7ª¥@¡Û¹+”-%VȈKU>5ÖÆ¥Ê"‘º(W>‚޼vþ-Õ[ó)#`6Užˆ ýöSllóºŠ;g¸±;Ÿ}ö„KçUæFùÇ?þÁkÄ’×Ú¨MÛ<šT£Êjä¢úVÐÞ{€/1ÅûÖmJ£IÌ®—¥ÌCJYŠ6ÀÅM¿ &`1yO‡uzÝ¥0:¢^Ô.óò[—£{éäÓo:ñ73dÖä–Ô´$B$râÀz•Ã{ptó 3·–O·]S´=2lD‹d‰t­_u}uñ–Fß ÷;j76°¦<ÛfMÈZÂ;sK|R!¦mò.ǽí¨<Òé$X_ÊD ffšì^Žl 8ŽŸø£ŸÿÈ\…o¾ùFßF\}7¡vŒ`AÛ´Ä©{q[ˆS÷7üȪL‹L§K)x:]±]Ã3dˆ8¿@ 4ÖTºvRb–‚²ÂZ+ä3Á½–øª²ncžB'€Ì §ÙíX¦ƒ3¿F>²DF« ©‚Èbí\YÌέ;í(^V몦` -äô™•°n)ÛIŠuÄÑ’‰ÍCjµ¿:ÁKÁ²¦vÌ€n9T|¾.ª*€GS^ +°âSÔËÿí¯ßuñƒÁv±a» Ã`Ûľ"‹™!ä»Ëzc²Û;)qä²¶©P¼=ö9 rvûü¦O­M¥xú]GT­X—wüËŸføW~¿øjlÖ™ w×úóñа;4ˆ ”,Úø»²N§3LJU§aáoã Ø:¤Ž«(ßléÃõu—Ú”lüj#«š)‰ÖöámP )CˆLGÌÎa]O‰®uí0½‚:šÖ—g—ÒãB³‘, p´N_–”.ö…VSH,»møôU!óDð“ªS#…©ñ!ù.–ª–%+¬ë_XV®X¯Wýæ'þ·×ÿî×;1åî(c¸yxÖFêÛüâküÇ®—²Y†Ã“j›í¢„ßüRÍy&¸¾˜t’µR0SXŒ@§‘ázYò)‹úBÜ–›.MU ²€ ê"„`2)¶BÈ)¸,_`w lO'§þâ‹{½o¡íCà‘y1‚ñÓw¯¶‘N ˜¡áôÓ‰,Ï€4á~Ø0íâãÞ–ý(ŒN¯>#9.¦©i-¥t´ŠÛf8ÄHR–xší´—áµRÈL-Y-’µ;|q´â1›Á²r:˜8?W •9‡?þñZØÍmR#­™ÖFÂi˜Ge¥ÊvÈ#PÀ÷åb²ÎA¯výf#•Ó”•2KÙòŒò|¯ÙháÀ£AwC6-ßF»¥1´^Jë¶Þ7Ø™8É®iËÄ+/n§ù»lˆ×³rLƒA¨á@œƒŽÆ»OØ`÷”Ô…—µÄV*PÖ!«E½Ji/hͯé½×˜Ê¦ªn›ά×Âò?«o§}ÐV«µýÚ—ÿ¡½«¬êƒFy¿ù“2A³i¡uâ¶ÀŒŠ,Ul&ÆH xˆZ41A^Ö²óáSXáQy>}jqdG `×–Þ>XÊîCÛ³úª’¥P_Ÿ„ÞñéŸì÷×ÿüøêÿx†Ô‚r#åw2‚áMb#Jª‚3ƒñ6sËÎÄYÅo92Ý!ø†)OdÀ3´ž±S[Ó‘KÉ&¢$Á1ÄÝÌâF‡èÕ` ÑJÁgר}¹‚Yúõ½·VEgµR8ô)kd×ÔBx´|­e‡(Äd ?KØ}"@#.௢㪢Ÿ¬òÀpLшÀRC¦VÉú*Ì"ã(ShÄÛ)óñ•[v·Ùd£¥H¸*ßê~É3a“ <êBy§¤»áMel>~§4\j8°“‰Ü’,B p[€„ãd»d¥â8)¾Ô}¸ZRpÿò­‡6üUæ{%ôɦ'†×”¾€ÁY{i)d´:øb|;ºªT±K·²‹LA6ðSpOJv£yÐEn‚LG;òI·ÖRN¸w²]t ké„+¤éEL3‚¾¸* @ ß<Æ€7^›ržM!2>#È#gö´D®Eƒñ1'êbØ`Jl³ApÜÞb)…¶hkí·Éc¢!À559°yð›¹áy&‹\Ó–<¯)C !ëØ1!²Í`Y»–®c4~†á‹M¡‘Êæ pFØÖÌ®°m^Y±!à@H´äšÈpøÔbøÄí­—e)²Î ÎWÛÇ%ojá|0O§k3jSÛ䘲ñ¥²DpÌÌ3ˆr^Ü ʶGž¥SP/‚˜öÅ‹õ2R „!ó!+G¶”ê € ³8<³DãÍi9&‘éT’÷ê}ù?ójñéߊÀ$zy!½91󜉟÷4 áÅm0ÂÈv!å6ó`ôÐ Î&/C»‰8š¬”ÁÄÀ%],šb)ULÐÒH‚3åeªº"Vh4-™BªCÆ‘ ¬ojuWn‰]JÏ n§G¡?¬aI™V—Ʀæ*` ¾üòËwü«Öç ÿð_ïgÎ<Ùök©µi £uó¨)kiÔö"NK€‰À åtxd󪯄¿ªBjJA!OSÕt.ùÏ/jwc:¥Ÿþô§'2Úû~6bãøÃ: ÝDŸZ@²p±ÔÝ[Jñ™”]0åÌ^XÛ ,–ªÊ ìæ—²#x}IÙ)f%é\V ¼{&L`œtx:1Åg¦Kpqjy`ókšàÙØ¥£Zઠ£Ðej ð8“…tÑÑó„'ˆœ·TâÎब\`‰Óø]}Aâ› ÂZ:UžY*/` 5¯PG:&Beá<<‚ªöèŠà¤S ü´¼=Ð:ºS`z1ˆUñpžÕkšpLãXfñáóË Ô2“СÌS0dop1½S@u¿jÛ„˜q¦Ð9ÈFv˜¤ÜQ–8²‚– iq#ÙZ|Lú,fGg ϳŽ"OJÖ+ÝmtêØ^6€vp:ÀÈ%üxŸ“º#•«j—¸ŽÇœzæ4cØŒåæk‚ä&Úq¢)ŒV' mó:9±€w1ˆ÷È«E½Ä‰ð€•ˆ»Û Ä Ñb)–¥ÃôµI`8B8Ž_Sƒ0YÙb ÈFµÄ´”¢cÉÊ €, Ó%¦,gÑ:ê!âR ùL¬P\ªØ™¸“yù§¯~%Ú~Å~©ÚÞuÔËñÀu¹ÏØÌpÌf6° -Ycó•‹÷P  ‡(\-¤«SU:B1œí†é0u"4 ~Ê÷ g]YAó˜ “]Úqj!Êç’y¼ð€ë[÷ûH”mÇ{ÉÆ‹cÙk¹“¤‰l¸¬¿ióªÿÁçŸþô'O—Ukúi*æmpç )³—ö%„(Üźƒ1e]k1‹³Ú• én)'`¼8pUbˆsT®ÛÞðŲïûôOÜiÐ4¡I†š5€P 2±þáeÌb6!Ÿ‘²©R<Á àˆc§n{qÇ ©/r )h×8Y{§†,Æéµ)–µ„3:LUÁ²Ý•'Ù–R³NÛ’²ì¥ýø^+KApÍx¦T²¼e 8)j%Þå°ìc“ˆ˜¯ŠˆÓƒTÈ·µ-+ U5ƒå,M' Ù<ļT1å š¾aº@²Èey1$GÆl±¬—¶ªfKÊ'•K*&0~ p&æÃõ«_Yy•Ù²ßö4¶½˜¡€:vàˤ™wceMÒlÄDòªJA™¦ÃéåÐËP9„§©oK/û«ÍÄÉò쫯¾Â/~‰ßô¨ÔÔ®y]LÂ,ÍRëF-+uŸ­©m“w&j™s@èˆ(3å¥àÔ*Q.†ÜS‰+ ç™.|O˜†±tªdmͦTé2‰éG£S»£rÝùéó™’ÄÑÕb¦ÜâÌ]JL8÷w±1¤âÓdâY)K%eùʽŽÄ)űðmMJÇ/âFuÞ ÝT H°à$ÅY„h*L8Ïd©ñª…[¶Aâ@¾³š8Ä…0*°·{`·G)>“m%È]šðú¾ p %bªÄÆ>÷Ÿˆt£ØeÒuÅ[)1»’b¾¬Âæk?jäÄíÙ}i¹FµVR-/ëšñRhõê”ÝÉmI(åXã‹Iƒ‰#àP`@YK¸)ì² q8ÀÙk¡Ø ªÒoyš]ÊpRJÌOM\ê´¹ÙÀ:jGGÎÿp#ñ‘ÝÖ/ÿÍÆïý×T »6¿¥¸-ëÞvâr?̘; ËíUÌäïgˆOgÛ;åN£PùÎ^•€ÉŒþiv™ÿSLЉñ16%fhÌÆà–|±¬)S)–EÖWpÉšRLÊ·ÖÜù²@©áÌ/Šú‘ýPûUŸþýÃ>¿i`ìöÛ^ô͌Ѩ&!Å–^PøÞäR|Y²”¥ BˆF˜îR;BȤÊZ*Áoû@q"ª’åѤj:ÁIùÍŸ^˜!ÿ¦'ë'!Þš„Ït×ZÜî,uÜT‰yd1Î@…Ê]>¸Cƒ3Oß%Hß²cAëÞë‘è•B®ªvÝ®IéDÈĉËF८Õ9UAC/r)ú–lCÞñâfÛùS«„×ÂNû„aM¥J*Z pK¦‹˜Ã鯰/-è"t–ô;± B e¤#æ3ˆÈ €Sß™–g¦çc§±Q« Ù`¼Ä›‘=2KÃÕó8iÚK¤:¯e)x툻ô²u¡i`%îdˆ¦ô!Èá@KÓcÁ –/4¿ü£‘! àÅ^ õåwøv$µG¾š­aŒÇv,)(oGÎM‰%Ž *Át–p'àd:%ˆ3#°J€uß|ïÿåâï~êÕ<]w‡híl¤5^ÛD6•QíE”màyËöBmÛêÂ\ ·}1Yä”á+Üñë^ëŽT jõTÈÓA€·;#©eøÀÆ«Jª¾q¤´¤À›JQPÅÏ]q\ÄZŸ]/½Ú‰ñX… IBŽÜe4Û£¬vº^¦¾øËyV ÐU³¬Ä¾Ö¯eBu5¢N„á‚z G ËqBô¦Œo“4-á|*%ðYWºÝ–…õç®b¦nB&®‚8YžÉJ¥Ù’w| JÄ–T´¤x3ðD†—Bª2OMSà+A[ ƒÜÁã“'q—ÍÜ ¾1ïÓO›MíãÞgÄþz²vädÚ©I:4`3çcâÉÆ« d; ËÓQ¤Ð´µ }r ¶`Ë<[«Fb)žéþCÓN!³³¶ ÜTéwÂŽâÞ›D½èÀùN’‚åZëE Âj×ð‘UÉ"7Œ.Î,ÍCG`‰Lê^ ™Žótõ5­M–¥LJyV#H©tÖH Z-ÜT½+“eJ´Ã첊}ÈËG–¥& €I*¿¦é™3ŒOG0rsæ¥ÚEËê©P;©‰‡LœrÃT« ‚okŸ•eûè@A¡r; ÁÁzí»!·k`¶ÁR¶ÍW=Ú2ï/ÿt!ÚÄ0z17g“w!Lki^†<>dÆæWUJκ±kÖNqàŽ"åÆè%o¸eâȘ u †üoˆ=êÞÀkÔ.à}ûnûÌH@YÃð–) ,¾` šöU4):::L·Vâfƒ#ô¥¸‚\Vе3`¦° |(–5¡Τ›?rŠÍ:$Íy%; Þ”•0gQUKLAÃà8²úò¥€ÌßѤj¤°Z3@táÇG«õ&|`j—‚BYHê(h`…q\BˆPy]e+Oª*xG”3%¥\§b'FÄkÉHº¼üGÀÿûß}0ê0µÐ]_ï ÆðÛ»­±h<¼9 騋ùª”o_²my-z@`¦9…âLI–Z`U A0Cš%|Ý-i6m“ˆŽš”sH /’m;iòO“ ô%%æS‹‡·ô ¬…¢è( Ç/ÿ>n4}]×äZØEê+ØA53¤ÓËŸ]]woUE%í"EÊ2_¬Ðü=×Ú;ýí(¾e%-Íi Ä/(˧ w\ïþÙ—/„¼'ÕÔQ›\ÜÀ‚D#&Öt†Ãp˜o;|1ž8©üª8ÊÀÚÅL`/*A{OÒ‘ªÂáÕ¬»çÆ;2AJ,+¨%Ùv!Î*ãȺç‘eíp̦°aàøë” Qh)E-2Y&¥XÐfÅÚ¥ ªÜºnjJÂÅÙFEΪ’Â'ÅL·Ä¹V’oÙ´<üi $ÕÑñ²zÙœ>O"Ö” ÉLm…ż*ÈÉ]†€ÌSP˜ÕHŒ'Ë€¿ëÄ•Æw»MP^¾¾Î_»¾Líòñ@›EÃÆ£™°ÙR˜ ¼Ã±ÓI18…Îg –Ê{HêÓo¶WkùçµbT¿ ¥]7g—ÉÌfó ‘5€aRÀÖxË<ñ®>ìN ìn‘dšB|;e–‡‹›!&Zc¥€–â5Ê-3ôõ.¯ÄØÈ4‚q|`Ã㔿1d›¹ŽI¡õÅ­ `G)£AdÅIµ#úFRëÒ¦¾l Ó04dˆB±Fk‘&Y¦Ö²WŒ¸^!@„Ssû, A³e&`zaªâ €\ÓÎ\V*¼]T…¿ÂD”À!–&TåÜ lÉà34H}'XVÊÅR8 ‚æ¿ôþ÷Ü"¶¡N%¦Ø|ë'»°i&]Pƒõ[× ]šÁ] gÔ |c%Ò¢ªNÙrî–íSÌê'¾òFÚ²I*Tr/ŸBxK L¬„µ…Ô’’â0ye{Ä´_^¡ ;†Ž¬B–È8W“Ç7¥â´S‚Rø˜¾÷Iùª~óë§}Ft«µµíÂxYw¡]XšÄíº Te²á–¥ â†ïž³/VÀ§&9UÀ]Gœ²r´RZKYfÚj[&[|GšŠÈÍà…Ga"ÆCÐQmdKúÊCÕdI˜‡P°tzh‚õUn™f4%úzWK烞~?ÕPÖÝ 4À.ؽk›¼±yˆ—j&ÓBTÅ™ZWŽLP¯#}=—q,ï]É:„ÚÉ*l Ùb o™¸-ñîOÿ~Ï¡IS£L­§Pã=F¹öÛ<|ÃKU"@f»‚p10+@Chr ðÄöè0-áºãôÉ”úí¸Xóì†l0wio0ô!uG®{MK)4¤”d¯‘¯£”·…íËxb“L6AåìÌôld™ø¤¶ÍNÈ_wd M[p&’9c6oþF– 'çÕüñ0Ù.dÛ&Ͳýã4y{¡ßñ¶‹ÀfPh°îC4KjãáðUZ6° q¾‹Û®¯Ö ë‹;®6¢WCê(U­€Nä{¡.þÀ;þOù§Á§OŸtdFª¯ ©ìNÐ^L¨¼‘1óö4&9ò}>'i†C¿Ž9P#HM4y4jdÌÙø‹/¾xÕ/IRËþüç?o¶6Å›­ÉÅhnZ3­ÙŠ»U‰Üöy†ÃËâ;LdRÌFlo)ÛC GÏ«ª Ð0Ž*¤§3å:6ß•BˆSyâÚ•µTËïâÖW … kªw>|Kð‘øÆë†‰fB†ßkˆ ‘’RD”óÌ2K-)Kj…bY8„`j†gböÂ_îúþûï÷D}ëÒ`6eŒ@Ó6¶MáX L‚Ã[º”˜²¸Ã8ðJÊvžíŽ.® O-¯…¤–¿T…&ñcÖwú÷½_èÒ§Ó0͹.–j<üº›DÐØbdžq,™,´ ¥v×½„VVÊH²I­ª,šìÆ–eY`·¨ãXÖ]J Áb-ôUˆ©µ ©Â/ùÇç¼ú–U(…¦D€)Ž\€–íU£Üã ±†DvA!}U6MBÏ» Ò2ÊÅÊy)¹í;Ìn!8k LÙ¤jÍ_=;–ȼZ%¬Çˆ;_S)ÊÊS®od3à›¶YÌ”ôê“E–Õ‘‚8MAƒ)‘²‹–|Ã(™ùoüo¿<9)ÛE3ÃÒúRl˜@ãD… uæí(2Zc·A e›*@ÖN¶mFèĤ”óÝÕ8J,ä!³ÿÆxJØ‘Ál³ñÚŽ¦ÍìÍË—¦sV‹ù›r·‹Ëø8â&ѾÉÕ’•*®µÂ»Ž¢V6üžm†e["LÂR\ÖRk“È6žÀFÌÜýd‰£;N:–ÌkÒ!È’j#í"ä—¿ü¥&~•yØýå/¡¶—œ¦^Ì@K“§Ø´RÀönw;U-¨âÃUíLðÅÌ…T4ARy:ÀÌ2ü œ×^tÊ6­ñ4*Anæbœtjš-Dè³H[ÈG [‹ bpY\# Y`§D¡ M— ys²†ÁìÙgÞÒ Åô~²ïújôFÇ<Ó ô2sRkx{ ¡ï”V%°SÖ»èR‚ô•°º¨mŒR‰ð3L…IÑ´¼-VÈ¿ûÓ¿ßpóc} ”I™ÓMØ ±lN­„À)޳,„!³˜²D\PµÚ‰¤x ¦ w'@áhÈÊnžªMœH„º—B®»Îд" 4 ±du$.hƒÆP%–5LµËÔî©È|¬¶¤Ï€ ¬–µ5š?r×B¡l‡Ó+BêjrîU) ed >ÜRyÖ2>/Uy±r…S«’b@j½–-éXÖ¥ϨÑdL9N”¸v˜ÊÅj‚‹~F…\çÙ‚%³¬KËy¿¨jËÎßÃ?ͦõ mN»€·w§mHäk`Y%vt+ªU’SŽi)K!à ”§ÁR9"àÑpF¤Bç¿ñÛPýë_uiSº‰ßŽê®µ7 qÿßöÝ6ÍqYœô+é@øJ¤à )NÁÉD /K0ñ m“#°ÍV–/"â&DH§d!DV˜­l[‡ð8§„A,#;YÞ2°À/w¹˜7×G^²±F%ÛH!mMÜT56XïpÌßyv•{Ø%®Šøéq™X‹ÝNí+fkÔ’ÇŸ]Gun›8ã›ÁÿëZ‡Õþû£ðË?j»Cxóô˜׎l3§o0KfYöÚåcŒ¥Ðvhh8|µé@{`óŽ­wYƒÙ~š8DIÊøBš²Å8ø}Œ&œIA­x|»·ÃAh#»|R,ªâ<¾1ÌÖyza6$fO3´9^)q|»VÅ,`#1ï—˜1OD·dôù”á FM K­e Ùªâ# w«uƒ­)‚˜á3Aµôæä3)óweÅ á3å5!ßT¥Êö®—,Bï)ÔNÑd×ÝïR¿ê²½ûÁ¯Öu¹õÚ÷€Ûï²:ŸF2d7•BR¶§`Þ®SØ.,eé8(÷ /¦Ð5¢ƒÃ£Õ…§ AhBqM¯ï¾¿ü@¾ÿþ{#uót SÓvgÚ&ììKlGåí³¨m~ˆ½ðhYÖ¡u8-éthbå,P 5P\/jÈ–æa‚b|š'f›+ÇG0IÊDÐò¥,•ˆwÑeôóµÖ’Èp% Ò<ýñ¤([UÛISÇ.î{Dcu‘_I½ J,£ŠÅjž˜[FNÇ$]¾*S‡_¹¥W¦Ã € ?5>szI9CÈ6¢)z)dJ,#ð ‰×G;…4áʵØ5Zyš²øéÐó¬ló<¾³U=õ‚äð âpÍÄ‚§^üsr×4RÀ<œU.šžT ¾šÉ® ¡1½¨5} Ø­,V…p¨×5GkB`Y ¾ ¸a±`VXÀ3YåÑÄ,œ~¸#À¼];œJz5îò„ã¨%e¿Kj‰ðöëþÖî%Þ}ìS‘vÆ ß @[XËæÉ㘠I•,vEH™V`~>C(àuÄ I³r‚-X Ý*ÊeyÊ]SSÖ § ´Ì;Ø8R@Öx–I Dc¼š”™e] ÞÍY;LÙ«ô\»jpRÊÅÌù¨`Ù÷“üxÇÛü•ÿ¨sq}o¯CÖE÷fhGüÓs“WbËRíÂÌ–íºíT¢'Ù@ž%Â;¢æQn)UÇZ‹œ'“½ã ßýOýE¿á¦…áµváÄ;ÿµÖ‘Õ­X¶ßxí½ùdÛH‚æ4<Ž%;r×ÉÀ+N¹7å!˜ÆóF…yÕI¨uþÝÙÈ!)Y¡ —óÕÿ¼'±æQDS˜o‰àLRÖ!²Z‚²w~U1qðÒ0²Q—²@A©žÛ8µˆ,«…^µ¦RBÇïåßµƒ#o`µ-ómŽ_-Y`}yvßÚÎÍ.ç•0Ìd u/o)0¶ÚR<¼©èˆ©ú:KÙ–¼ÄJtãCX‡ €¿ê]:ÎwÜš›o6-7¶Òœf@Óœb)|1KY`àhyˆÑqÈ8íÝWžu*ˆ;ŸÇé–n ç žŸç´C66M¿'YÇWyßû÷W°µ0ÓB÷niq­»OÄÛ3f ¥ZKq¸½‡Ûˆ¯{™B´Ê ècŠ1#¨@XL>ƒ\“>œ¥*)A%–Ô ©ŸWXö%zévuÔ˜í4åö"nŒNƒ·Ü–õšÑZydß»›vjíâ圬 Û¾Æ„]ú¤µ°äÿ•ÕH—Z£)dUå † e© o|í0wbµ€ÄAÃQhiÞ’‰¥:XµÌvÒ/ë>G€H ’¤|iœ§«e#iɧTEÄÒ¨,žÑéÂ5ÞjU¬‹XVŠˆXˆ%Îãk l¹<õ6)•OÁõÑÍ‹¹kV‰¥6A:È ó ¦C“WÎ+ Ù¼ÀhÖT-°.@µm ×†¥ZÙª Óaò–š¦v%/õ äS&…ÏU‰Æ®W`§×¾ MÇÊùÞÚ—R>Bœ‘íBŠgÍóÚŸÿº|Ÿ>}"Þœ|GªWç`X^#<6ŽKu,×– 9DU¥PV Ìì*[2U8»(“-a7Œáét#©²ìrÐdRʵË2å⤤ºâ#£%""ÞýV-BKA`ší¸çKÓE`‚bÊ–u÷oû^õË]ÚùÒN‹öruûüº²ûø&‰&–µröym0š¸,š Z:^¶Ž²éó!6˜x¨lWVa“DŽyžà»0â>÷]=âÆ«OP_ú©n!Rë‚bÞ¿ùf†wƒ%hY¹ªª²ºˆ4€X “·¤o)uVâȶvâøü®—| mMªò®š)àF·|—’Z&‚Ù ,EÄ¥4-Ÿ,>œ¿w‡Há8aÁ^;8 ŽìZÄéýOJŸE†dMhHK©^>˜”!ļëy‚€/»›PVm4xâ<Ü2ñd˜`úõMÓîÒ—JJ[Ú—*|ƒYŠ`»6ƒ˜`¸%YK ÀÓ=ü‹_üB@êUfkþ7·]JšµÇ®WÛ‹Ö&@”˜°ÁÅ á:ÌXJI{ß!˜_´ÄËâ ˜ìôc¦ÖyÙµ¸ZýÏ×_ýòñm³Õ—¸ëè-»ÖmGëmÓðv¿!â²ÈÎs„öN ŽÃl\– 4rÚ;®²cª¥\->üœÚóýW P /Ë€'· Žh ô¥ˆñ˜2>«0>à o´gæ\ñ§W®¸9»L¥ú²*_-5žš ¸ág/p-ð$O Y¾1œhpÁ8‰¸švÚ-Dˆ÷j•jŒs×î,âõåq|ˆ„§¯\œf8µSð|¯ÁwÛ4[“/‹ FÉÔ®Žy4½ê[m/Õ†Á¹2ò‘e1»(‚!Â矚¬­ Š»„T,•©ª­ Ë¯SI ~þ ä;»æÛyI CPB¿Â†FDàMÒR c%zU¥¡YÊFÀÖôʰ©ÄR¼1¼”˜UKP¬ 3BRv!¨{‡ƒ3cð–˜Ý|Õ&X 8Y8²˜”Oÿ¾V¾d^àtñ"ÍÏ´à~£šÍ"Ð Z7‰f$¾ Úßœ-; „Kûñ¦bY¶ÂÅ –Ò±sX»–h˜JÌ 4¢WRu_,(ÆYù6•2ÁkJ¾,Dm'£„i×’gW·ãf÷¶´Óû²tŠIÕ‚ˆŸþ}ûÿÁûðüÙßì!£ÅÄjgžÀ¥ÎNžCn§ª ì_ÐÖªíØ+¹à<Óq |¨îøÀvj³–,Y´.¨lÁZãµô{ÿÞ±’ú¼^ß}÷¯»ÚG$ñ^° .…ÙbcŸ‚kÚKã\ôÍOꢜÙÃañ«íLøNÇIŽÓY¥– ÚÆ´¬oËÈæv†4ë÷èP˜MŽ”rU–’ØCز¸^æÜäë. )¥upåiªXví8ͯ¯a ™Bú Æš“¾%‚cäÉâ›yí€bR&§Œ ¬0ÍvÁ·²Ì¹Ù&Bü¦’m ̓&ÐÝ#:Á›,…†IŽŸ~jJdyq4¾ü®‹/¾$èw]š¶½kÍì¢ a ±”¥ùkŠ ¤½ €-!v”ZþÍöëÌ}èD@vV.|qœöbr‚ÅáZèK°H‰%Ôª#¼ói‰à7_õ½ašìÛo¿u!Š7¤Öbc É67|[FØÞ•ól©j[*Ï, d#Ø;Î:«ZÛ~Lú|£Vë «¢ ï9ÄçûDc$ˆìèªEŠà-»¸Fÿ¨šïþ<º¾è?~ù§oØã.D'c¹î²¶À´mk8BSjˆÙ.¦ †D°q§ÑmS¯ø”m߯‘áj{ÍÊBèC*÷É端¾zÑIŽe—›‚rˆr©h¼B©ÊëÕåè¶c´©i"¨êèòIUÞFôe1›°‹®ñ¾ #b ^‹¬©Bxåjãˆïä”}J$XUKl µ4LhÑ!Ä£1sªD£lTäuÌ&ÁQ% (æeÃC"ˆ ï@ĪøJâ'[¹s¤ÐT¼‘ iæÊUe›ÇÁÚ2šò !Nã¡5O+0Zâ)D‘™¬%õÆ@IDAT&€(ç­PUYž©’eÈR þùGu •«bY31 ç "#8ºzw91¥Ü5ãáJlã*=NÜ]påb†Ì(ˆ1ë" ÛfÒ‡¤G‰¥€ ÎÝpŒ@­%‹£D\‰Ä!bULU}Å‚fKœÔøL8#U•à’9¯¢†lYñÈ•t“©e¤^øé ïý{ µ³  —˜bòæéÒ´ ³xvÇŇ˜oã¥ÔÚ/YÛtžA²JêÅ«½ë·„L°ŽpV­“,¶Dã™â^¿dñÆZ F–ª¶qRµ0dRî ²e§$®JJ¼ÙÂ;„È}#!Y)†f™½û·Û‰¼1ïëÞ̶Y-xcF U¶ó4¹¥©¤B€×˜ç¢„8 Ù–RíÎvJ5jk*Q®j…’B`°0Y1ïš¾ûÓ?¿娛„g@¾¸ĉF§ñ•5g‡²a ðUÙ)Ï€×ÎÎéT­B1ƒ{4ù†®ZW8CAâëKJ-&YU²Ò/Vn)U!PI½š*œo*¡àøy)½Y (àM‡ ¤Vm`M!Ù Çq¡5-K‰Uñ”]LK†V‹‰h‡“‚ Å YêÍ^Ti—-ô´±T«£yIP Kß;Ôe‚‚4YUIaÚE§Ah{Ók[èâÒQޝ™oõá}_?|û_÷ˆ ¿Ýiä•Ò¾ ©À.ŒW¥‘€FŠ`NˆTK¸e“ÛH Vyç¢u„®×¤|±äêèȈ˜M‡>ÌZ ù^ØkÄfýö¿.ú¶¯ƒ›¶¾pÛdJu5• —2-ƒ (T.N Sªˆ† Ȉt]ÄY†t÷6þÅ=d1ß²øÜfˆ v°FZk9e)W>qä!i¶dx{)†7ªÉéw/%«PP;‚–j³^:¥ ”˜­.÷£–RÕl² VP6·ìf¦ƒPJ­@•‘à©“"”2ƒ,Ƭ¶[ž¬ 9Û¦ò6$ͤê2¦ fÊ8NO;gm>WUS É™8>æ3yz•…wª²?ùÍo~“„ W¶Jc)n)¦n©80ÜRŠ‘®S„‚«‚o™‚öªàž!(lÙ0Àš¬uÝ-W‹Pí6‰ÃZ • eb]l\ Í¥…01>rVÁ¦¤ÂÅ–d,þ´¿.L6…JÊ™ËCr׆Žß ñ)þó½áþè§´Ö´i ºè+(–•ó¬É+i~àÅýül‡ÚJŠÛ…Ãx¨±_K«€¼ctÈ‚ 'µZðÈ)À×(¦É\Пÿüç÷Yë+¿üª Çð”ÕbBXôeMÂg eÛ/f£^E'®6ÇR••PÓÂ.+…iû@¿ß"xôøØÜ?ß}÷]M@—Œ°I›³†4x¸ªÆq[V‚ÉzÕ´A4%b&F´w%í=Žßm_ 1šZþÝ¿ùCÊMîO5¢£E^`-ÌéÌ[⢪Áò„À&ZÞ…x ¥dY;å[VËCRnוÔ]Ê2‹)nrK&ÆÌÄë"fpçMªà©wîð†AÖ]&Ô¯‹nÙ»ÄÓî^ŠÚUqܽ—¥l‚á|ûjÙ-1 a¤²¾1a –M›¸r𦦠n<`MõMGj3H¥aÛx1¾`½Ô¶·Tž`â|š€?ºÏ÷dWbfx"ö%j²–fM©±ÎYðòïvûÈÙÀ5¡j­©37­9»¸ùzÍõ8I%íq:jû(eƒ‘Õ® ß²'¼*ËŽ¥;ª¼ÇÙ,R–õŤ°Z ÚËÿð¿_˜tãu‡ëµ{Ok±: Sµ.œaX'ÐŽ[‰mŠû*E‰¸ýk”ÐvÔLÒéQ`–˜»(SÀÔW ›‰KÁ!@å–À6?B"p3 ½TˆÀ€–‚À8U•*[G:ík|xHâ'ÛN-; dñÔ³JI-eg^ÀOßѹÃÝTZ$RSU8È‚vT/òð–ÇW O<¤rSá ”³k®Ó+e«{¾ÚŽ®.õ÷Õ`Ó"S!ñ©AùÕ…=ðšR& ÃËýäw¿ûÝ…·ãHÅÀö0QÁâ5@«$]çÞ2Íeë2eü¶1YKñÓ&‰°m¸ý,%(KPmËWé¹HÄwâJ¢ÁõÝ0tZâ ˆC ˆ †wÉÓ¼‹§S¹Á¢ ”#»º–,ñbY:¿üòË–÷s¾ý?ñæÔÅ<æ·Ìš¡Ùxü²æ·”å;Æðb¾,‘eßÌ,¥œÁy}ydÞ«Ô’B9ßT[ÞÁtš'q1ƒ/pËÝÊ.Œí{Nš x¾¸y –¦ÊÓñS,p½V‰ßx‹ R(ÆÄáµ#È,]\ßF{‰ùôï7I½6}clï»mðÞW6>ÏÌéèì”””è0…½–Ñê(P…ÏG€ ¥9ퟯë{w N%ø§÷ìmþþeÛ}Îÿ7ö¿>øÛßþ¦{ÊzLY#`ï©mÇRJ<Ž¥8°3Ðu ¥¥ÚD³£´ë–yÌÈ£µT{eo ÔLŽãá&áe¯ûå|Q4Yš5åÅáªó›*ý],Kd4N4Ë.–€QuJ²–é;Òôá8L`<§–A2Ydí¦¯;¦˜ BÈ¥ôøpfz~´JÖ$ &ŸˆÚ¤ÅRd™ åÄq"Æq,m3 —@dµ®/0N»›O¶’zAf¶Ü¨¤¤ÔÂ) ,ÅÃÐF€ø·ïqÄ/1¯ ÿK&údk×x–Ó]—&´RÛ2͵ŽÉ#£Ù—çI“Ë6ü6…CG6¯)ŽK L@AŠ)d˜@–‚l±ç*‡¼Êˆ7F½4šxW\¶‹+eK3IÖ±(76³‹^;„ÉVKÂ:s|8Kî%¯0ŽÑ¨U޼™ÕBXëÊ,… Ì €ãÆ«]‹Èñe-¥jQÌ›D x£öQ™IÁ• ¨µL?ÙÔ’“¬ˆpoÑ}'®änhŒšø¶#N¶ïè‰/À¡Vá¥tœTÞ™ÃG`–a©¶i•`žÍ_Ïð‘ 1;‘âRÈ ÃSs\¼s€#¬ÅÈÍ<Í»` •DËCÆï4¨Ÿ½ÚLsïˆuÍT ꪾQ–M|L,[›f‚¨ŠIm,euçÑb#­D£{;Ru×7Á zØQÃ4ÛZ;ö6ÛÌvœƒX s©6®.v’p¦ ™Iu <›MD,k)%P‡Wȧ#`F¿:RP–§ï³¾÷§¾s´~ô#ÿ€Ì» 1Ì`wÈMw:gúë¶Ç±4<‘¦í;Ê•À•à‹! ´ÜéHY&Îûêî…ÇÚ÷¼ýþO£6›šÁfÛT¶!D–Å4¡ MÉž#x‚½SÀœ#(V+¥°C«<…Óãy8tT]Õ§¼Ž ûa<¿ùã_EWòŸzßø÷UnÛQÛxFb–¼FZ Æ7¶”eUͳ cV[ ‚ V"Ë&˜8šl6‚eÌFêˆER4‰Óª,MKxG I²ZÃLSœßNÑÄj[VnÉRHy±ÀvÍ8J²8Mx <~Ä^kqV­—¹«¼iÕŠÓ·_­Å˜Íf©Ü.L-„à²)æ àø;·^†º+÷ÀÑQ-ÓE–É2 è\ŸŸKRÑ/2ZóDæ 6†”Ù²AUuú¶Eš•0°M¿ëB¹/oû&ѱî ÀC:ëdFhæ®Cèò!ã´k^ÌŠUÉ" ôMD Ë,CÄN’O˜Ž9ßü,7ñxÃôË?õÒ´Kvö|m„x“É$¦Å„4a­ájÛ7‘mPîZ×¢.¤å“…0-œgwˆå85â›-ÐH–b>µZ7y)+ÆlHÙ€R_£j‘2dc4̉fZÞö›9Ž²Õ &(kBÏùšê[#µ¦•²Ä±D(% Îé04^6¯älïö¤Ò(%ˆ @óRlgµFʘzÉ6¦*GH-…Íýßb#õï›—~ _¯ªšm±Ž?T‹³!8¦Bf–3¸¸;\—A¦Y ?¤àι#)àïU#ë(œ3PÀß5ÐÔUbZPÛ ¡v¦|¾®kÍ#³e»=B(\ÉãˆDÞ5JA Íd)‰ üžkäå†Sª@{#@Ú¾ ²ÖmSÖFÖ«Ùø˜U‚yüjãTÞQIm#:V‹–¾lAo²jÊ-‘ bòz1qY%ñ€'¨ªBKÙö›ˆKüŸýgþ¿àvªÓׄí·Ì/kŒ;5˜òR|8Ä%ëX<%¶£Óïijáhª|yßùÃ-Ûr´Íd†„P2à ÿNZ£yVlŒæ×KSþ\¿«µ%r1¼£0*¾”á›·„»pN#œô²KòÜb8«„¦B'y±Îf½Õ(„í|Š[ò«¢3°òô«â5í60j»@†Àe‰+ŒÏ³‰h‘¡ è¤ V´ü€d½áZkA ÍR/1K±,¾fp ZšÙz-)@XåÅÑÅm3r|>¿.q:·æ„㈲1„Hˆ‘ªå3MÑàÔφŸÏ‚™ï*Û¬ÂÖ¥yb6À£Óu&²©%(ŽcIá~ðÈ•Ÿß”ŠDº–SßžQ·Ã#2%õ"CêÔÐt2`U–u²Q¤àSK‡² >ެ%Ó®¦<))œæ7‚â²Ñø˜‚øIá@(k vUpÖ Èb>~Ûl!o*:˜q ªml§Ù­œH´dqd›ä…o¾ îZ˜¤Öí˲±ÆèH—jàÆ3R.ÃõZUÕØD੉DJ ¤’J9Ü9ÓìJÁ}tó<І°©¤ô"È‹™,«Zx³É6Xóð úoª.ã~ö³ŸõÆ£i4ÃÐdhÔ€©ñ–MkHÈŒ¸ÃÄoŸÂ ¥ØFÂ'Õc×Ç\´—˜«ßë%¥ß|[hjÂ&7 Z)\ŒÃ²lSA¤’ZŒ‰@„IÙ]…éˆYWWBð.âå€i6î7ÞýSâß~û-©gÛÇc¡c7$ÜœY£ò-Û‹øíˆÀ«•0A:D¤"SXVÈ#3L>ÐÍÓñº¯*‘Ø‚€÷ `5LÊÅ” ÉdÅëU\: ¡yãXÆ—*{ç‹YYUD·G„¤®Ÿ[X³½ È‚øðæ§‘¢ÏgRÞõ¥€˜Àé§Ã“ G³l°Ô¤Š+ÇoYÇô¦lwBûÊ#` ŵæ7pä²oF­Ñº["ä»9»èöGŠy,ð6õÚÿë Yß ðÀtÑÝØÌØNƒ7¼¾pcð¦ WÙñ ˜ªDV‹¶£Ï€4Kuý¦×¾CИ¾4K¾³Z¡o—4Éd?ø®·€vm;:š¤^û ×È}Lêû²MØl•˜Þ¡I x @¶­í`á@µ•÷…„CkAÇ‹@Gy"Z$‹Ä±B—iÁ€8S§BKj²ã„§©Ür Ç„w} Šùìùþÿ÷½Ÿô© ºëµ%D;& ÐNClNÄŽbª­ÂLâ–)ð–²â–‘áÉV¬0¾e¸¥ªgÊç3!ƒÓÙâ™yÜÞ¾GþÅ_É| Êe ¬ˆZ…!<Úúvwi‘y“+$ÎB,«š¨bCzFüú׿N þAÓÚ§ÿæo‚5­/°ãj;‹]ËŠí¿·Ÿ “j¼JxK%xåyÀ¹wÇð eQ•TG „04Þøßýé_ ôÓMnIP#äû–’¬Ö&SÐF¤²«èÜr‚f´„À6U~q–T1}ÍꥻŸ>YRpìîCY^HSUŸìN5‘ÉZ2ãaæ-ÀÛûRÍ œúK¡rHZ3ï&1­Ö+Y°£ Ö©Æ¼äÏHSÃz•í~³DN­óA¹êŽÃé>A“2Œ. ^¡ ˜7!O¿_A6‚òžF"ÞÀ¥ J |šA6<™Z §Ùeø!ÎÙÃóa©b:¬ÓçNw‚À·'ºINå+Ì]ç'À”í—ï”È›Á®e;UAsJÙßÌ*…Ö¥„»í­Âþ¾ýR<²ƒoI„²œo†i&âÑýîd’ZR±¾;I|‰芠ٯÁ Ë®]ˆ¥€u&Ó×AÊ’2Z”£“e°Dc”‘CâðjǤϟfÏG.ŒNxˆªb"Ȇhš~â8‚vÝ%®üês6ÂÔ¶µ˜–´R1ù8‚”e‘iFk³²–5¥#F®D¼ÁÌ DPNĹÉ6° ªí¸&›f |ÖT¥0›V#È}$²é ´M/Ÿ†¯ 5UÌæoY©bÊRu°ôc6ˆ0¤’@óXRk©ü(þ3SX­úF¥¬ð\ ÿ©$•š iÖõ "®S…øi­/$Ù«éãC@:RÍh‰l,"Éòæc8b¦Š!ã„«TËËFŒ\ÇúçkÌë«Ü²C÷‚¤ƒD0À½D\‰ªd!qÜ‚7Yœf®é:6;i7š,üÝ¿¡Åë[&d¥LÈ6’vR¼±ÙE|¼1ΤTÈ8²4+·‘†¿ uDŸúÎ6 NaKƒëÂÒ Äl©EA­íBPÌ£)ÄKu·Ì@î_8pæ;%hôÅ]}ÊjwP³Dè¬Ð"¨b²píÄÊC7¡X¶ÉúÞÞýç›íåÝÞ»´»f¨QRZgÀp©Ž«ÁÌð'÷ñ_ (~~K“]vówPÉâØ5Pa)ÌŽ‚Æ 8> ä_¼ø½ŸŸ6'MÊd™¸‹Û9,…Ð`›Á`8DI­ûGŒ&–Å”e@8EnËJpxVª€‚* Ḑæ– áÑ:êb^–%(P^ñÚ¡eÊG†Œ|gŠÑîHƒU«$ N¯‘®B]˜lœ‰ï4YKÞvú€Û<ô)K)ð–|j!‹Qßñá+0/ ‚1F^ܾ\\LS¥ÆK¹‹ˆHLÇRU50¾@‡áÈF@†ód3Ëô§c©*~fl²…/ÿ]ßì°)‡ï63’®¦XßköÇõKñÆ`…@Uì z]²ûŘh‚,çêü—BK4Y“PëÁå_.Ùx7ñ¤d;äª>òdHá÷¸Ðh›5j¼Ã釦5¤‘|_Ö·G|††#21Žãµ)KätRK­;ÿ²fP.[ FÈã ”0d8„ÏÂcÊÒ”Õ·l|q‹&P¢ KUe™T„Jx`4e­Å8kGˆX‹nø8Äí´©ÄII5ψ3©b‚iš ÎkÁ#Pëq\†Àˆ§&FÆ„(AKö—­KšJASžE¨œ&GÃ#$«Ü$Wݹ¤â4XÓ-…f‰Àì¨FR–« ¯°C­Èu¹à3I$ËhÚÎH½4OÔ@Œêq,ÓD°,3þN‡&³T…†O_œIá?W‡0sÍàé )´”ıwiÅ8á‘£ñ ¦,hH)dµ–WN»žJÄ#(ð©M i’î¶`-0ËV(FXw%âÔô8ˆ¿ýŒ¹. <È|¾vG¼IZtzÅMÞC,…Âæorž2¼Á:JÄø)Çá©ÑÈF&#ò1·ŒÐåX­@/|ÃáuIß2¾¥‡…ÿ§R"óþüNÿ7œ4¯^ ÈQ|~w³—œ‘¤¯TLdèÅÝ9`ÌKãñ€Xúºî…_Úù±†ë×Å&l<ñf“µtNU 1g…®f—LmCÊVÕÙN*"ñy154ñšÄ\62Í&ôBCžÁ}ãÿ#zÜáþUw3“m`2ÐÅíë.¸ ]ÓN£Q«Š 2Kc7äv!eËÙv±TÙDdÓ”íUCM`©Ü9ô~c©ÊRUv§ c6­€¬‹X6²¥F–²- ^ŒÜ’·Ô!Ž©€ôRL\¿3«å+Ä4«W4[î¹×%ð­Ö O×çKOIå1«µ© bš÷yŠ¥zµvÚ<Ò×ùЬP`9MÙZwbžtNåURǺWh/@†i¤žm?± ¦:V#^ë–Ænª—ÿòGDßÏÖΓPGcˆuì MtFb¥Ú‘»L˜Úv"óÛØ9´A¾ÍFkƒ+Aƒà/Cî7Ž}Ä—u¼š~ýõ׿YùÇ o  u7LÑZ_M½’—âk-0 $&™¿“£u\tlP-S‹¦À÷žx)GIc¨j’Jà–SHY Ø5ŠV¯fo*|„ªŠ-·ß¶ »‹Û$)4'~`Kµèâê¤i)P[9f² B],›SÀ”‰0š Íш§ïQ.Œ,MKx/Ãjf“ª×~\©–ÊkãX€‘‰ Š €JŒÜK©I"tæh•HµkÇÛ™C0Û/flMº0©5uV–ªˆw‰ ™ODP÷ÊO!)±Ix ½ö1?#9TA&þ?ÚîeG²äHÒðbzK€Ü>#™—*‚ @€|ƒþìüîR6Q½¦GëBKMTTTÍÎÅ#"#³0šU ’MWŒ@KÊÞ”4M¸e8ÐAô0k [£â á–pFAI¸XŠÁ!•X.Ç„Ü`:§ò1!oƒº4-òÎwЪÜÙ) âtÅlÙj :LA%hmP€ÐþÆÿñ{ÿÊv¶¬£àLöÜ4|ø×T|cIàp(4¼˜áC–²´-kYmdž!8«b]šíV(• 2+&¸*ú¬ŒÃSã›PI3»½ôïsB'…Ûu…pãAЈ´ A%|ä•›²§À 8ñÇôÓ£oüQ–Ê_b#›þÎÇÒ´;m$‚¬Ù€8®ÜœæŸT‚y©ÈGkd!Û)M8ƒ8‡QˆÙÛ`)oÒOþº‹¿àñü£ñ6›%ý:ò À· [Ž)6¡T8~§”Ú¤à 8¦¸«o;hªxj5ãw/%RHa·¢¸¾Ž<µ ¦€DzQãTRÌ×T°¸r>£Ÿ&µ-•Èt“5fÈ»úÿyŽVŽÃRh6žlKÇ•òD0+ÁÙ™àXJ©å› Èv›+Dè"ZÆЇ×%BÅL£²ÍVîR*‡«í‹ '”E«…¬I©—,>°^âð± M©Êi6¶W„ßÿ—ÛÓ¡£ÉˆÙxƒíĤî^ÆklAL"☫Uä+IDvj•¨jËÃÇDβR CMýZàý'·_D~`Ù(Ô±« 0†ó‘jW¤oê Ѷٮ¾+‘âñ»|qRbúž8Ùh tÄéº4\  ®„‘‚Pè Ä@µ‚ s»Ò“‚l%ìÖ‘"ˆ£0Ü b´`­ o)@КOœß0˜ðæÄ‰\#x·wß…ŠuÑmU8L•’Ûî´m­oT(À;%qx×n$ ÔøbAB€lqü¦â7X)ÙÆhk0Yc§ù§¦@"Gå™Ä.0Žðex©øõí c׬ûG–Ȇ,iÂæ9]ß_®À§Ü¡‰•õu"‘VXªg–¦)·DCØÜîÝRÈeù!ó–8+D`–@–ì@ARR•ÄAK h‹WO“M'B©emЬó5¡8\­’¡±ŽP ^Š©í8eœíZ •BøÄJ,‰ø(.û‰÷È1šZ3³Qãé™%Ü%.+Èe·t}7d#EF°©âDЀZcZŠpPI…âm¼"L–‘J!ß’§Æð1¥ ™¥.RâJÄ]Y)?t¹¿ðƒ³½‹‘5m o7ƒ*â›píw&ϼç<³–eCè|ïßcûëóºšòš Ú…ðr›­“á-í—ßF:d;uJ‰ðÛ‹ ªºˆã+Ðau_‰%°Žb… ?Dw½œm`úŸ¿½-l†ÿÏ€”_‚Ò=~ƒ-ÖZ‹|34p÷6š%Û¦p,ñMkNÁd'[–Ù®Ia&+èÎIߟ¥&P%®—Á:>Äs¤ÀÊkÔÕ1&Ž@–‘Ò ¿¡ª–‡÷<æh1‘¦xËbʦÃ[¢é[P¶µJÐ ™ÂòpUf¶qÏ#ŸH3ˆc®ð©þEÓRjjâhÊþZ(…€ï|:"ˆhSÆØÀ]K8NïK1k0œdáHYòžÁÚ³53Á8]ÓoüAíü®‹7€Fúêl_Mn Ák²÷쮓i~° 3ŒL‰³4·ß–+ìè0á@$°vñ^ÊO‡óÃïLäo4?41€Öuä5µÔË$uo0± +e€öÕðÕ.› Oªíàô¥ƒð.4P YRdRi–íu2ƒóV_ü»ˆÃn©Z¬dÁ:C Z<g¼tZš™f·´Bäâ:"7²˜u’ Z6í‹ýôMGg"›Ž‚³ʛĒáy4RZ0±rgåýï«,1fµ·©6ˆO¡¥4p¤ž>¯Û Xj¬î襰g NÍ)é’š¥ZK:5åuÍ@_ŒŸ‚¥,2< ¹s @¶Ú 1YÀã 2㉼ ùÑ<BÒŠI´sõb¸O‚œ">È ©çª‚°nkAã+‡ï¡Wç?U²ŒlWÈÔpx1¿àö¥#%0pK‰¬ Axü”«"ÀÚ¾X %ÛQ…@4µ‚ªØrúc¦é_©‡|‹ù»¿±”`ÛiÚÝÃà7¿`¡=¦Æ¯0AÈ” :1¦,Û¦zø-Óçu¤ïäcެo†<©{òb|Y"|µ#—ÒÂ/ÌÜ´â€ÈõRn€ 5•UÕã4Œ%Ãç!J£Z±€=¬—óIÖ»c‡ðIà§z}kgÂàuªoXÊ2}éÞ:~´ÂÍ,`¶ ¦€2&"¾95•h§—¸%ÓY„t¥ÄþWGüAçÚ ˆ4•lN±`ÛÁY¬ª1€8Ä'Š¥³ê â 7ª¸¥¬ëÎéoGh8<`g^VG­™‚#Kª -–qøö³ÚÅ‘+œ`|©D,,? Ü’‚¸ŽOÅÙ{ ¾“3_€†|[âA!ÜR`Ù÷b¦êË ÔkºlK©Dº@ ²CX2äb:-yˆv!õ=Ô÷o;Èúp iT"ÞM’o†²˜©u¥Ò¤ãrM(fÓ,à)0%<šùê_ùŸþöW¿ú¨E £©vL 7¼¬e¦mûj$ ”ª/j1«’b«­² î#oÙsäåæ1üö߆r ýîIlŠõ<êîºëØÞÏèÏÃÈKuƒmï=¤.Y ¶ÀdÕÆç#cîv QՇޛBxRÝ0𾨕d†a]”®B QrxïO¥ÖNÖ!óÆVìRÞ º @Úš%dà™àΤ–¦Ì×ÅëT—NûK#dÈtî%Aå1f‹ M'Y‹Óþ1KÿEà©™6B$Ü’—B0Í.k·ÁK´^¾î5²Œ€D0R;­;©{Ò–fÈßc4g“ãô˜h'–"b ¦oˆ8)âLœ¼s#¥ŠÎù¶ùäÎ8Ï@ØL•„{7Qœ)Š7¾fàR'Y,ÈS ÈÄpXH Aµñ¥I)<û{vÿ)}9HÑ [ª-ÕÞM)n€¶\ǨݲëQȳøj• I¡kGÊ$8|[+ôQC~èýV´®ÖÄÕkͲÂdë oÙñ V6‘ⶉ\# È¿þ Žæìpzz1ÛZšë•”eÕ6O[P‹ Î"óhv÷²Oð矮Ï:sS5o¿f3’a °de¤ìT!þj[ví\&Ë ù>K`…–b¾ŽÄ)HÕS_­¿õÛ7h?`no»Q#{Ó§£¯IXšÀFmK§¡*ðî 1“5-Ê•‹RíNÕd²Õòb4AÊÅ‘7˜,kž¤x…Ì,‚XJ­¥‹‚Üѵk`à X ¬1€ BÄ’à,Ù-!<«¼XÊR\_ëb™l‡~Ö`)C(IŠŽ e„¥¨I}Ëò)ë>>“b ŲÑp4‚"ˆ_yxµ ïƒ%Âðá)[ÖMÉ“?„ î%ÔZŒ.pO~ûïºø_ƒÛeúmÜ#n ­À2$ŽÞü<«„ŸÅÁ?•w‚ÎÄ&ËÅBç©;§Á´°ìbá—òÕÿ7¾3›ÜoCi§Q] zšêþl÷Ü6øðî9mHxWüüuÝ!JX²ø>^Å>‘øÊ!<°3g@%pŸŒh©”ðâfK!)ä Ö«rä6%›Q†Ôh{!‚Y¡@ÓdWkÉðBFP„“UB‡Ç·$…cé^ú—mÅ8Z#YŠ‘y1PÀ’¥#Æ?½ßßH'uïE9{ªO9™ûQpQÊ>2ç«ó5‚¤@-å²<÷-œ¯Ð¦£ ¦%P#œ¶Ðl²]Gˆeq\>%øUů -&D °” ¸¥”b_é„‹ÍYyÛáOv÷62ιç’^Ð’Š2`Šê°zHq¾¬’FLR*˜='m~Ï„JÄõUUÖ’Y²úÖqsª-µ.‰ïÁ"‰g^¹/î¯;}[ïKÉR²º'(Κ“§f*3 è@ºÃöè`ãðt’òs,²o½OÿÛ¿wIÅšfÍ–txÈú¢Ò<+%À_y›²¢Y¢Õ¥»â²JÅY­€Q <°.õâÔÈ—;ŸüI—É¿ýío&$èØéwòõ…wEd ÀêÙ D6LSIAšSm%–pú–KÖ41álwŽ%‘ºï^m<©·…ð8LÀT±hfëè qx ¬ N)…CYÖRl#; ËíÚ´~_¢."w?‹á “x­]ÖAI ¨Aã;gL1Yǘ±1âq}AÖœ*T‚ψ㴬#¦€¼Û¬©à•D;Ò×Aùi÷ýw“?4WÜŸOÓ†ÑW¬©i‰Å¥êèXZªêè¶»gä×û'›>²£Så¨1–;q—¦aŒ§¼Iôm*^\_¯åÿ_þ1ƒM¥‹^b¶;¡ ÖQðRFmiZ…ø–b†oÉwmVnã¤Ó¨f|¾Žùzy„é¸ë:ÆžhjjIñ ¿’fÀO¶‘*Y£À ¥àÞ0ƒµäÓL _ЄKµäãäUµ;4ÖÞq€†—Õˆ!ûØ…#ıœ‚Þ~é#ÓT§ßQ81YÞRm'&‹¼KßqÕÑ2M|ól b4žæÉ=fɨYM‡lRR@ž P¡[ˆg@%¼“q&øDV¬°Ú©µ¬ªrˆÂjámGŠ  UEYNüÀŽQöõ½” ’(j“_ dËò®Vªg&µzàG@.®JÌÄæS{gÅå]éòU Ù¡¨bGô±æA /Ž_Ö2²M²e3¨2}u«é€Ó ì”d¥Rh¾¦<<_£b…–÷צ•ÿ˜w{ùøÜlºÓçíÅ£Ò0Ú‡X2Ëøæ±Ä°h÷²–§æ¹Ÿ(´}“éfpPÕ&‹€Œ`É -»Ið;dqOgK B^Ì”GÛÕ49‘²|_TŧVɼ¬8r`Y qUîjG'ÆéÖ˹rxÏ‹B/åWÿ¿ëthêÛÿѹmÚP_&æÛ¸CC3³I,™%3B{¨í±Eè0áOÑ©š‚“¬{†)¨?ÙR-ïQý®³ÿÍÅ«ò?ÿ.~õßQèâÐïf£ÔsJékÚ®Z»€«õ†T× YŠG#%Vȳ¦ƒ#3ˆTYKR:`Fèf†4LœGõ¥ÀêNDª9‘‰H©…R¶dhJ’‚‡àPhZÂ8¤ e˜Ìä)@ŠÃS˜ßÌ«m­ ï(*Lp"ýtZò SJ„'kËmAVÐQDhH–>ÐÝÈ·GAYA:j‘-)› c)…Óx8b"Ô"¤ÐWc†Á÷4Å©‹¸Óau›jl±FR˜L•8BKˆ¥¿ Óv¾ËÿôÓOýÕ&⑵#±vÌH¼Ij'%Î3ÿ½\cS莀l)…#ËÔˆY­^ÌIFCP‚0Oþ— é|ñþ´° è«Wo€nó#· “»yY¡¬©Ôˆ›VùRøLm"˜–ªX[vF‹‘{c7O A°Žd]*_Ð0†£E¦¼;Â#רÁUIåµ[,È1 éÜ bH X sqJu°†„+&µ^ͯ„¦ï-‰Âʬ ká‚v5–ܓԟ‰Î=†Xá$2/Å'«ÐïHá,)^ü {¦PkÇ´¾&ÙdqŽ’YN°@U&EJ-¦”*xM+G°ÍûLj1&Ž—›Úó£Ìº1dðH¼ùKŒŸT;ª…Ázš½× ¸¬jýü¢± ‰ >›ù¯ÿ’mj“ éµÓEÏׂfäZ„SÞ1}Çî«çh÷±C´n_ y,Ö¨e¬ £ÕQŒfþZ«õÅîdÿÐû]M½|L¼óuaæ÷5/kó„ó:ÂyüpAY³‰ÍÚßN»¸*"Èn`^Œî·”‚S3Æ®l4ÑüÐ$åÏaåþÔÔŸ‡×Q£p½Lâ@Ü0`)£ Ì&àí³yz0!†TÂJµ!ª’BÈ ˜ÍòÊõâ©)G›Mʲ#²Ä¯$B“+Ëj·TH¤Ò§6R#%”XòøM‚Y \  8|6DÀ ±Íh$¸ñ€N¸MÉX•”ÂhtÚ>\`Ù J¦¯ÁÆí~«u±ˆk Gcõ²dWGK)$¡Ì´“‚?uç¬ÄʘãY› Ä7d퀕 Mˆ¦M7¼I»åĺ°:j‡ÂÓIMv8Î[êë q”¤¬£@ Y;±„ã<¥jÚëŠj¾¨õVÙåTRU=d-Å {„ÄåõÐpµ™¸#Æ QžU´—-زԫà}ý,ëX Ÿ/•`~KÇaUÕ‰ÅL*dc;% ˜YVED \kϪj¼Å.Fwƒå'¦—oŒaƒu]D1°«ŒÃt1'ß<ÆS‚ß2~Ão«ª½cªmã{"î)œ·ôH£5IOÓÍŠ‰ Ëjg)°”jfK|‡oÂ4e)MM@Y&VBœ‰u'5ýºä‰ ¬#p1¾¸9ëeIž>¯Ÿ±ÕZm;|ï?êçcÌ÷ëõ½§Éî Ó‡™ýv#9+ÃÈÂmß²C0RFí–¦¢ NûNGŒOí)}}äh‡©„+Æ\©¤ ùûßÿ>Úy‡À(Ó¯E}é×Z ÛHö D „7¶¬*† ¬$°Z…@û…ˆÓÜ1)äéðí´yNî1]HE@¦ÐHuwžXî^œÄO‡7l`x€I¸RMÛØÛ >A Èg›yíàt YêM<å+oÈá#¤°Â;¨P­*fÉz 6mwc‡ïNn’‡{®Ú>bѧ¸=†ð@ :*!Û¾(tÔȵŽ)+èèxK¦\!¾”ØÍ@‡i!Å\#>&0SÒ•I ‚™,ÿ½¿ü£»Dëæ±;sžáž»ÔvŒ¡ÃoÎûàøðj¯Z)^¶Í†$¡ ÁOa|ÛêÎãÈvªø™ŽŸü?MòÅxÿ†çr>ÖÍ W/FAÙ|c#ÂlUÄeÃÅÝçÃЀDzCŠ{´½÷è0…J0•T. ÛK4íœL´øT]xRµëŽR… abdjBŒŽ I!¾ „d˜Ì2 )&˜6’`Yx×—œákÔào_pd©Õ ¼Úô{FšYáëLLy̪v £¥, IP oåʉnj&ŽŒYÜ%†h$κ@ýy2Z‚fëZXŠÉÒÑT¹˜Á+ìd,S¦€i_‰ #ÒNœ‰Ó±Ü¦–5ÀÈ)ôÃ~ Z7d_§‰!¯›R™{Q‚ФëtoÔk/ˆl¦Æµ´7WŽg–q:/²æÃïó‘Ò%>‚%[£•‡Ïë…ˆo…J¦<&D6² ^ÀD,»ÌRæ L ^-°*ÞNWhƒ–È,Hä<þ–8–Jn#ñçæ«×bsR¦OÖØt¥jdDãÅÀ‚ø)åUm6A “½wd¿x >+Ä$Û»FL§1,7@‰¬’º,qàüîÀ¦’ÕE,Ac2¥@ëZÜžà3ã¹%šÓ!ÍO¶Ée1ëå+RèdRð[.ßuA‰û™·ìynkm$3@Ç鈌ѲR1ÑvžOÝëÖV¸í"Ú‘^ÄðNIU»îXj4Ù„bòÈþ24²?fþR£_ý¯]:ÛT]ÈBº^hqòíkø?ð!¼X• óB˜%ß~e‰P{2çl«…gU‰huÌSˆc!‘u—B(ó]¸â©¹u™fq‚‚ž¾ª¦F‚q –©ÝÃÀ¬©bÁ>ГZá8_äÚñ¬‘Bˆ¤iïg‚çkÓöÕö,+V5>q:üæ¡Vý^5Ü[b缨©»¬¥|,Fbq\5³áš\•,¤?ÁëU ©¶Tõ‡?üáËù|¸ôçcFªßÌÁÀâ&·ÔÚ06²¸DÞ™€|ã! lˆ&~4^Ÿ/-µ@c8¼¥vhø 7@åÉbú‡ÿ‹¿Ë{c4áŸq^¯wWßû¹KãË)WÙx‘w2hl…²â6‚¬¤}™(»#‚H!à‹¥*MA²®—*ø_£Dš6rèÕ1œg˜ ¢kW£†hѾک*d:Ú!‹Ñ˜ yxøL‰lÓm*B-x…Õjd‰_ M•YH§Z8>Ï›SàŠà#GŒŒAªí^Z|gÅh¬€oÂΤÁÈÆÑeÚ¯T{ÁôÀšJÀôÂÜlv –í+Áb73)µSŽéj†41ekéÌlj”Ú\Ðxæ4› Bq˜k-F« ¾.!çŠJóâÛâ)(kI”Ķ7œ‚q»• ÑNШñ r4"¥ ÇÏ6ƒ`¾ ~µtV"FcRb¾¸ª's¢]¦ljgÄ礀º(±Äg;V̬¾)W"…¼T¿‡± Lê»þ€¯“\‚æ˜äì繕l³á4ïdñ2¿’Dp˜ÉÄp%D –JÚH­uaR@â7 Ù¢ …Í”D*‘ZÓé-Ø­…SUóc☄) (#°æ,Î#+yè¯oÊkÑäø>$ µ¶l_æ1L7†e{±/H \£ÆF) ¬iSŒè‹S  ;íz½¦ãé@IDAT<\9<‚¸cáÊñÅô¥È¢‰¥Ä|›þiÿ¾|@1B}-ÅL‰˜ODÌšG°¬9¤ÅTà®FpS™VkH È-yÛLÈy„–Úmã _„2$ýöhŒôᬭ ãC0ÉbB´ƒ LvHåÈR‰ãÛxLÁ„E"ºK•µÌhNVk î“óÌ’1&åRI‰Y“¼%_w)²Z|…&if~c6•¸¨Ò®.stkƒ¤«Q bT*lÉgáí2uq£'U!òîûšÒ'›á4’7öË¥hZ§\ßÒK•åïlœ¥ZVÂ×´!+tÎA ØÅÀq|m!N"ùví4žÂ¬¬xdöÎÿ‚·ßoùÛ¢öÖs¶mážDë@ó´_¾ñ€G ´ßîÈ{fú ³.»‚“¢G95„8>ÿ:óÝ*ëxNçyƒf³94YKæÏ³,YbŠ'«}(ç®VbŒDçÓ´<½SË >æT ‡SZê+ðÔ÷{ÿë¿ÿýï¾mÖhçßšÊv¶›SÀಷµÖ¥Ü•<gwÚç!S+8‡õW“˜³^–µð{ÿ~­ó׿þµ;­‘t¤üt~uo;8Œ`ãíò©EKÇlf± ò8öBÝù24±BdUÎ-¼yKE† ð‰Ó6¤^†ƒ@\­Á0{qšÈH4g½`¥ÚKœ[ßUêbòvª6ex&Ë€ ¢¼á-ëíÉŸ3”ýRÒrg%j™ø¶Ö$Û2ŽQ™.||Y¤I<¼!-]54KñfhH^¡÷ƒS"Ò`ÊkdYß¶¹¦ÍCJVLAlZG ŒSS&£¬£÷‰ouö3…oÿ]ÿwðÚm û²_³AÚ&ÄÒ ¸¯ =­8;j§ÃwΕÛ‡tzb:@ÌÈp Ì–Qoc‚Ì:F„¤Z:–ïým(­ˆ9uäµË7­¯Y›Ͳ‚q‹¬#B‹ Ö¹ÙZ"iš_ȶ ³ìØÛ/‚¾4ËÖQÁ™*̲µøëk‰¯#Á²é ·©@FÜI!`k$%¨{Aã!„H‘]‹ùæôѬZݕدÀÍ®/)œÞRíú.ÀéT¢Á™Ÿr}-·- L¹FÕ*l©°Zã vE”Ü|"–À^&æÁ'ÂWÛ^,Gôý"£¼I ™A,Ñœ ïô<#î4 ÓHS¸e3ä-5b‚Œ”#¸(›'KÇðÉ ™rSu·¼~™Œ„\r5„jRT_™€-Ž%ZæöåP,Í¡P‚ ŽÀ'‚T©y8³,H “²ýPƒDF㋇¨E39ä0-V¡}U˜ZÝÅ3Ù|SIá¹K¨é[íSw.°“™æþúZŸñ:6vó4Þ4[6IêÞSW¡“„<'ñËaö<«-EÍFÌž% ¸Ö©Yâ”UX ‚Ù8‚bÞRŠïÙ‹©Ðœbje R…8½eôj¹îšªúµ©e”›¡1(/&‹ÓÒH¤œC“ Ýã@¾÷_ï§z~§Kß°ñ ¼½wžíלëɵ#±‘Ì_ îZ ˜šãl#m Â:÷¾½§O–H‚pU|\UƒIùIç'ÿè'5äýÅßg¢ã€÷%ëú6 ϼûLRÌã7˜*#Y‹1-iZ2RZíÚ¸Ø6# Û&dV BGVQáYÞ$‰DÆòp|)²ejÊ™žO³¢P¯,µ°SØBŸÙMH$Ãg”;ä| ‚)[2KíV¨*/+ULV1ƒ@­}øA˜¸}áÜ1rµ¤êXvÊ;jAÛÈÞÝ‹•Û»{X€àĆßdcH¡uVR–øLëÞü8 ÓäÛ)ýZ Iy5é›7¡?‹ù]Þïºt;%¨µ¦3ÃËêÛ·5ˆSÒ̉(T.n¿OG6\ë|öŽŒCŸˆlj®²%>ÍDÒùö_þñ#Êšn΂¼y£;Á†iBt¥dH¸hæ8Ó±”²tD¼BËs"ïÃàPÒ"²¸’§T%]ˆ&oÌ  œZB³u¯:^Ù›c©<¤Ø²`ËK³Q0`Ëvd©Ü Ì’5$P °« oS6²½(Aƒ3¸’tàértŸCƒÔ«³2<\•`MîÑÄÑ—lš–jÑ»BqÝwÝÓi<¸xâÔð{^dõ%§¦‚æA€X ´žÎ˜M„ûÄhR`î7d…eá>mý°À2Ù ‰L“,X`¹.ñyÖR¶Ë×˽oTz']eKÞ’!Èc–Fäm‰'ñ.ŒÚÉmZ–¿Õ@tðSÞ0_[¾Q‘©‰;G8ƒ°»6…–b©²šGŠNj‘RVØeµDC–¢YÚ»—¿¦–Ôúvׯ+¯‹Tµ•k„ˆ›Í%èv%[ žY†àëeí˜Ôæ—¢¡dh§ø}zê®S¾©Š•„c "¯Ê’5pA#Ѩ%(`Ô&ÐuP³µ8¼rU @îÞ«)DÛ ø-ëÕÆe™oæí·-£A °F–îgú] øëWµ¬å°&æ JHfU&NQ6BUÑ:ß¶ oèãCÌzº¾ßøÈRÈîîAS•?½?E" ˆ„GÛ™Ò—•ÂÖ mh@„øj] ©ZÀW9$“Íô­5#ÔA (€7Â;ü˜Ÿx×uWý‹Žv5-(+nrƒÃu„RÛ©¥‘ÅçÛ Ðuß–-‰X ìÎH˜ªì^-À3|qj–8b篶“‘eRënÙä¥Ò×—µ—Ľ}~}ÈN¬G;""˜rËW-j- ˜&¯ š¦t|± ¡ð-æ_¯ó7ØÈî½_»ÄÛòö.h¿¶Ï&Ü$ç8ž{Ï´Ž‚oT…ÔÐ&[‰¥¬ŽÌ!)YY¸%…1¥Ä¼§øóßsøóŸÿœ²Ö)·×K&Žåv$`JØ™þúáÍOÊ™´YˆÌtœ§,s‰ùzÉ¢‰ žü9"„»{+:s1ñhâf®¼»‹f¸We²M’l_‹lSM%N\P 7?AˆuL¼ Ò·¬¶Bˤµe&[ydúbY¾¬R÷âyAñÝîêÔxã9._%hê Œêºð¤ØjÛˆ%f4qcDKÈ eé”Ê'EΛ nŒÈò²[ªad™b´$Á)HÑç{6¿÷_&ë—L¢)oÙÌ<œ`ËíeA£¯Ïµ,¼ZÙ6%Õ’w™ˆH1"¼S„4•»š•“¢l©cåþ‚@Éw™Ÿ›Òºî›m `q Ó<&4ßÃë.Å´d•˜œ)µY[ƒtÀ²‰£Q … ±d V뼨!á8NÕßt昵0ag a”-š. `ÙÖHO-²!+Œd@öÌøÚ¬* ý'y²©äGŸ`K(Øl3£­‹l­yµŠ¿9¶Œ,ëe(E¡Ç®#£€P,…YÇZÀïóIHªÚ PPU ã´q},›³rÞ²ñx… lBñÄÑÔ"ð6Òœº ;¨ÎYœl½ OÄfË&¡MiŒ–í(Þ%mB/^#yÙÒ/ucU I€ gð¬K¢°S°ìpbJµìPÄ Q/4K`'b“b:ZK©•—…0]ÆWÂJ¡1x æ—*Fˆ&@à3Ý£up-ûp"¥–IÏ!X*|à³Mµh!¼Øx˜Ý4ª x%,,þõצ8ÿ©õÙ©ËNi m¡1!MÒÏY¿¿TZÕ=ªZˆÀÌ8íQé e;šá—’Èîé.zˬ°Ç^JLM–Ýjh²l›`Ây% ,¾2²Ñ0q L`išZvÜ´¶߯©±N Ž~×¥›àçæ³¡¾ºÉz™Ä X²»]sª‚Çt¼ùUX‰e&Æ nB…qF¨p ®c_ è¥ÖTYöùß…ðÿï´‘4ÑœyúMÒÒð2f»ú’µ‹Þ§ÆfFEP¨Ä¥l§@fµÅËŠkÍGSÞ–4U O™WÅ+a´‘-5ÒaØE4SŠGcéÊb«¥ âg–¡$žY*´…'óJ‰•$E_€€ÆRL'ðäÞ/Øô¯.º»¦~FE­ç«‡¨$±‡SI§Q—L¢W®CÈ6ª@ q„jŵ@  ¬Ö²*ËdÝf£©„Ç„óªbòëÛQð‘ãÔØÖ&ùß~õÓÐfûÜÿûßÿ¶;3ÔëîØ¨uorÛ±´5Ë#Aî2ƒÏ숙V/©ª®Þ«]—³ÉçòUÛÕz;ÁºäýòO_~)üë_ÿòÕ³.Á‹¥ù†ii†>Y\w³ÙK·ws¶SHdÙj÷rŽæý§Ü¶¦‹¥­¡ñ½p:7)ˆyhâXÂIAx¨Pk…^­qÛIyÝáª(àì`Û,fZíXš|Y…LUûÚ¦¶lþMB*„× š¡F|½dÍߦôªÍ­âêD£Ï€vtbü}²Øšò3ñóHâ3úõÅgb\!ZCGv•éÀ͉‰¦ªîHÓ6^ @“‰vš=HA 4Y" ?ÎR†$nŒßüæ7–L#…LìpÌæ*lGíZ6M̲‰ãHY2™?¢Ï›Ð.º=Hu·øW WˆüþøÇ?¢Êá!˜˜¢éíÁ¬z#°¦IåitÞ¹øÖ®šF ¼»A¡8~Û/À/õt8¹r«)Ž^m%Oþ«2þÄãß%bÛä5JY`xLóCÒ,ÅW+ûlñÜChÕ¦¡áy¦PÉ9Ó§©–˜ŽEì„ÝbÌOÌïÿ¸Ø Lœ¥çžôõ…Η͖­\¼ÉÛ#©g7çô {9Î’oÎjÅF³l‚{‰¦5¬£À.š_J‰ØÖàu·Ótꋃ€/išJ€ ³©dÑð>…jét–Ñ,öªQeÉdÛ>DVÌL§1x"ø8⮑ËÇV…ïKÿðšI}èMëE±C &ΦÇC¶;ˆ‘Ì ±5Vª*x;µ„Û‚}‰Û5sž¬­aÒLd› 칓õ9¥ÊëÇÿã4Û'ÞÉû7Ó(ÔŽò3ÝË¥,e-ÅÄ>Še x)fm³ÚJìÔîØ³é³ël}î4’%Ø-:&Y ® óÄá¢9%'Ü]„㔨єe"ÊU‰A Šw¶5åUiÁKñU•M ÈÚHⲬù!eëh0Kµ‘ºã i âªbGy†C­½£áyM¥à¼*â‚&©£-SÒ`oà”“U˜æÔÔ:F=íßÏ~ä&™¦ B½Äf`w—@]UŠ8žYÖZ•%2·Tèb™Ó’á4°GՎ뛦ڧâå"«•bÐyKQ‚Æ,»%†œ;Ïdžm 1|x)EKMÓo2Š5«+‚9øÈÆ×~cµI„8LL™Ú–â•‹•[Æ)Æ O™ÂðD&ŸEFƒˆ§l6UO]ŸINÆ’U[¿ãîâÑiײÎM–­D\£¦‡¨e •8áÍöÃA?¾RnŒD6CÁ–²úš‡?³>Ó a†çs©¶Ù®Ý pœhJlGª/GľȶœE¦vO˜2ÑÙW8Žˆ¯¼yRàá&QŽ£¾ÀyÞx³}ù’T| øÝÏ5âk‘¾¬r¾!1){nÝí(üþ³ÿÁ­F·ùV³Õq¸e[ƒ´wÁ8fžF2pïL‡³íÈ¢µäYúøÌF,mP#/…á@ñÓá—;„”„,`hìw¿û݇Úuñ«ÿ©™Áœº7*¿±Û2Âf3ÃöØ•-ÅK ?ï™çN©¢S‹©!·M·^`žÆC,u() ¢Q·\,•N4%ÊÓirR 6†#Å¡CÖscæn`jY #pβ–pYfžŽšk©j‹¥T­)&)hfñ¤à¤x]toÙ •ër®´ÝÊUãÕ,®½”28vw‰˜b]2œR§å1?[|¾ÎHÇGffÈOP "«8~¸¥l`1“­{ ŽeÊâX—EÐE‹¾ÂsjµÃ”bhUÁ-Õ6• ©oÃL|“8É›L'MüOÌ—)½)Π¥ö^ý²÷¶Ó•«wJÈȪÚc;êp ïd vFÁ ^,å¶¥1àɦÃCj!›/vò²Œ8 £U ˜'\` Là½Iž­õ—o¼.‰49fÊfÓg ©ñ@&f¶¬‹ñàb4¿ëòEùÕø‡þãéóOX(ôÐü  ]ªMë‚e×¢¬M¹¦âñÃW[‰¥rÛ‰©ŠˆFjë±$ŽFЉù ‰DÀIùU(ÿî§øósÍ.¥ojõ4 ] ˆl 6I-ðb)…²¼˜‰ëÂSs+Šã¸î]ôºàKuòZã°Í)FÈ€L¾îìy½¸ øµëæ?ZÏÕQÂZªÂAp˜}¹XÝRDd‘z)Ñ´Á,Å8@q:Ä+á¥àwL-)SÈhYŽ¥Bb*gbéN ^/Ì‘!ýã3iòhÍÜ9‹ oƒ.ò6Bsdjâ–uáu7¤B¸SXbaÉ 0ÙƒKÃ('$²¬@“K!4›ªR)^#' ÖÔFÌsqÿñcà'Þ üo¿´`Û ÁQÐîx“óf3m}-㊓ºÉÛäUµ¯JBè! Á9«mïôS³¬)ŽÞï!|ïø“}jg¶Óh;m )Qy©®&ÐMâJ•ê|Z®ÜüöEpµôUµ»8Ž‹™û_žÕ¨lCâh¤˜¸3À#tÕŒgé+{^Š”fœ<‹¦–møwòüyãáxÖ,25Kžx·/Üoç#ÉMæçvÑ dGÖs+—Õ†³d-Oó·áDSfº$@-˜`ûÀ+,Öh´J¨‰¥Ò¯œ·¼ù–]ÔÉ ª¢É,yjá⤚¿‘XŠ9Ê>ŸÐjT¡˜`üF²Ä§‰ üÐ\8CRÓ—>対gÐb­ÅMh~1SÂZî -Cx >f¹»¢óiwbxw$&q8[ ÁÓóàbž`·\ïDËf#sÚf1NÙ¶¯P뛆CÞ$–Y?C•²<“=fÉ0ó]P1ŽÙmÍ_ÏÕE;¿»õù×»¯ž1~úé'»ƒôÃ!ókÔ0í%²Ø¼ Æ»!á½÷ÍÜrœÞ¾Úš’–|70œ‚^¶IÙ6¼1\‚ø¬îõ Q¢V‰¥õÏÿ0ÄW6½…4mGÄ yF¿ŽKóðFb˜ÌÀ†±äCº,Õ.g›²Ô”‡ÐWbKq·œ¸a ¤:ïSgå ÄÃë‚ß µh)E Ä•¤¨„I¡énŒ ÛP­SWȤ,éÃS7dóÄä#ð”ã+3DÓ Û©l7§‡O°1,• `ú(©BfɤX½àD”$«#Äñ"-ñ1=k;X©5m¼Gõìb–>)µ²žF,wzõ­J*²áż¬@¹˜‰1»îÊ™. ¨° ŽBW³Øoÿ ¾ËÜljZܾ]4I¾Žh=`Y%U-µ[ Ç^útk/6äG†+·tpü²¼2È€”»=¾_þ™ÈççÔ_šª}—¬«0å¦2É#yî 8@ULLD`ÔðКà tž•ÔÝZÖ]W*‘§ú|/êNŽLJ‰,0~_d[âl1ª¥,Ø´h@åt ‰Thûé«UØXª’V’ßü‰##ˆ5 ¤ƒÏ*§&KPPIâ‘+畨20Ä’¦ZLÞRP-_Š`LK­©ð+ÁÒÉrJŽÑù»@­˜8‚ ±)31“ÒÎR /®—„Z¤ ÷Rlã‰çãб<=Þ]”»ôø ³' H"¶) X6šZV*©œÀ†‡ÁWüúŠ)‹ÒëGwN­›I‚õÿÐVf‡ñ€ê-[.%Û>µÁ©a2U@Á,¥”%ÙOÅ/·¦Xv¾F”Yj1¤X}·sÙø©á¤Ü2e1|Ì#ô\:FG@îfꊕHus[6Fú¼¦#L|v†ûÌ(ÓäÍ™8=ú© jº¾-yæžSç.·DèÂõDE¶#£@A¯–ñ!<Î=DÖ¥‡+éxõJ'GI‡ÙF(AVë¢)ìxÇ—Ê|mªj¦5ñhD2Y£“…PТĮë%öŒøcýi~øçüš_ šªw^ºƒßHbœ® ¦ÀäÆ3*NL_-?¤mò ™Ѽ(à K E“ïˆRS5C îŸýHý°y}û §©…^ `6âŒ8œ‰y]pàC€}ʲÈHãAª-gÊy´9åD€Lܲ‡YàzI50… “xš=xó©#%¶Üµ¸AÌ©=m_¯bqdM•×NL¤ùO§÷ËS€°×í´ Ë6ª²UÕ Í£A˜-(TåCE\¯ñø‰óŒ2OÜ Ü®o/K¤lLT5L`žËI1Ö‘¦¾8 FSVŒ@YV ¿@VŒo;G=žÏ׸4Yd>šíˆâtDæTÈ|±[÷˜Ÿ{¿ çåÓ¨”u¤É‹Y¸a<_Ó˜FjùP^ÏšB`7pß[¦É³–|‚ªûr+ïèຠbÙ;Í3÷ÚÜ ?·ŸþY#š®BoͶf˜®N°wPkHËj]âöˆŸQ.ˆƒÐ.ÐÔò)4Û„”UR ’!T"…“7€ÓSè ÐpŒÁù qŠ¥ê¥“&0åîpó´—&‰ Q•GðÊÕB0_64¯—ð7Z²]÷ŽSÊFp2H"– i#©¡I1H‚tXqåZ̤ B# p>çIÔbé`ysÖ=2O!AÌb|–ìô·,¥ŸÔÃ}½XÛ ²vmÇ<¬cKÃ(am$вK“×K .°ÌŠ"ÜħƒY;Sy)YÖ‹TGt.ªz9æ!ÅTºNj€j,##j ¬‡Æ‹Ûä×62Ma„7?³‹yU–øíÂ̈\6}qkr ¥*‡âè"†dʑѤìý¨<Ö±xð¤ðaø¼xšŽË$AGÝmQU Ÿx¯ì¶P¯â/‚&iï8f3BLcìâÂe!<-_`ªÐlâf ;A]dáÞSyÝÉ'(P[V•@&+sjéXê®Ü0†#+‘]w) šc?Šoó‡ÅB„™Â™”¦ÆI™,2A“úü¯º¾Ç9ÿõ‰î½Ú‘p·Š^…¥ø&iN8Ð6»"²ðùÊyCÛcšâêvïG)tl¹+>…D®VÊ_ƒ¦øc^/Bœƒˆíx?tÿØÝô1Bi° r.`Kï+I_¡ÒŒæ`Y4 @d±ÔÝ )—‚/›S95%pg¥‘Q™‚ Àì!bä6hIÜòní´áÓT‹µ“e]ÀÇ'%°°‚ÊT ‹6µ›S-sûñM‹Ó |Ljbc >Z^Àd"ìÒè^­,Ž#Ò¢dŸ æ¤l‰ ¶%% “—bµÈîÄp£Fã!<šŽR‚†äS ‘"hI~õÈj1Ù–ù #ÐR³ ç³ÊGÔôÆ)@J¡ý† oŒ>©ªL’”ýÚÔ˜²8‰¤§Ópt²6ŦŒÓÁ½èa°¤æ$ùÄ“205"MÛ¨ð{ÎZ„ ()n~/R.ÆLçÜqÏ=וj§J,‘Ñ2²Cšž&ÉwVìHâ»Ópî;°rÌÆC£`òJÚ~±%ü5ÐûgrÌ»éþÏÿU˜Biíj´ñ$ãÿ¿†ø_þò½:RK»3ƒvM² ©x§aª¶Üªy†° d4ñ,&v‰ûJKwü>íT Äxh w,~ʧKñ{_ýëÞœZ´5H·Yßœ¾Y*”r,h¬íãlƒ@ˆǤ/¥ª µ[³ýà T\9|‚UÆ`„-ŘvÊȺÛl„>õ>¯i4r4vO’8M:Ð$˜õå¥è¤`IÁŽ^Œße+©WL ì±­J6ÂM†4Û“<[vqyúmDˆ˜oÉ‹I)t›’òjéTÕç&M^ L`ÚZVE bÂËQ"kYkKú¬¾M(ŽðhçÙñc‚-?|jø‡nÈꥩÚ‚%°Øå¶YYËLV`6&h ÛÉâˆÑÔ:Ÿöˆ†ßùížH3(l™8¦î®³û ÈÄìóßlþ¼W“oLÒTí¥QÏn¯7d3ð˜pÌŽÈX¼WÙö•ß~+lÙC&ñÔ ;šSE‹9-aÖFðT:–¬ëÛÖ€ÍÀ£ñ^jé`¶ ÔrEÐlJÊ-ùºO¿ŽÕey‚¼ZÑ‚ZËù›¬;¢u{!K¤×¸Ÿ§qæéÀ-k¤J’fáCð³UYÖzOÁÊ©)ÔŽW¢©]LÕxȵì°Žáb&Å;LvI%îH‘wªR» 1•ôÃnM1› Y6˜˜>2+%͆(‰ÖáÀNÊ• 0ãuey#!haÚ6¢ü—ŸTɱ“ã©o'–O—ÓBÎY×¾6¢:Gî]%h>r#võ‚„w4§ò}[À[òÉBT\UxKY&ÎbòÍo™ ´Ä·4€F6if`TXwxÇê4ÜUÅR 9&Ž€‡ÀªÓ뱬KâŸøÕ½¸Žv$¨¯Ö–ïÆÓTÌ»-"óM’B÷….«”‡G¨6D*\`ƒ¶V¶Ž¥xURµ(h˜Èi*Ghâ=`j¦R›<þJ ÖýËg0ÜOŒâ¤IX;x¦©`3`Š; ×Úßý}¿á¿~糧BûjGFjƒÑ<‚”ÌãŠ7˜˜µ œÍ$Î ïð\»4Ç )Àé-ékŽ!¿óYSÿ¾ªùò‰íïðµ#Ýä²:Éá¼ÏFÏÓÄÚÈWÍ„J¼[xä‡xnï&‡¨ºoË=8ÈéóÔ(¨ò–À–ðšÞšMˆSU³µµÌH•—³¦Ác¶ëh–% £Ål ômMÜÓ¡pV ¨ (n*x:‚šFÛ IÖwÎNŽcH…½ôê>Ù”ZΔ×· átp(4†eÝm¤[™Ž{^ ¢_À¤e é´7@ã©U•Ȳ¶ÓòΊ †+IÜlJ,ùöõß´ÝK’dÇ‘¬á¦ôœp@¹à«¸;N¸g> rFX@~þ­Ã¬+-Df´ æjjjæ~<"Ÿ•€›Ó$ÛN"÷3ð%æÝÔËŽŒÁè›A»ô̧R8î@Ð^[¤ªB'€³-ˆY‚U!Á‡Ù^,ÃãKQ«5ÎNÆ{}?'T²òýòO}­‹¦Zˆ›¶ Ù¾6©…ðø"L¡lGtŸ ÁC*wVõå}Æ)Eª‘0]‰”‰_b @®Ö+K¹kÜÕ’jòN&`ªòMÒ¥…$« 뽨r㼂R&®QK4 (43¦gJ3BåíbDÆÄ/$Ò$¤.ÖÃá˜Ê‚oø–Ê;±Rb8‘²‹wŒj-3Y8¯—a Vk`ÿ^Üw¢ÙJ¦O'e^ gb^ajJjg)ÕÚÁ#`:IñfˆÖ^&‹Ï¤ x© ŒBÇx?•x^¬{A&…)`=‹(Sö< ›±ncÚ(cq)1ÓI½²¡ÈhZÂ!h3Y ,DŒÃ'b‚®5>ƒ§C!rÈð‚†‰iÈŽ¦ Þ¹Tݧyíìlíêù §ƒ9 YL)§ñfl4ˆ³NSÓÎDm])åb&õAëõLVk^‹ô›¹€3`4^Êø^DŒaã<À# 3L¾]„“Ec Þká ®Šgu‘…x§“…ð¤,ÉRàÚTµûÓ[OdŽFÓT)÷ò£#%ö¿›9Ã=Í_Ï8Ü^ÆD˜òs@Ï»‡@ÖT¥âÿö÷ãßð~Žs~ùǦÝü}ü¶4¿î:Š™s6¹¸ß{nßá0'ÎÄãŸÝ^tµÊ1wzÕJ9ðÚɺH¼»/ ¿©dß|}…óSÍud5¥¯hA_k¾©€V *qH{´l›ÀUĻŒ³ÀÔî¾ZœAš•H øL\aMÅ]Wƒ LNßF©t0«*hª6ÂcBZ¢õ,0“\b/‡,ƒrS)Äl¬@J ß<‚:ʺBÀÑJ‘UÕ×Ìn‚×”©Ä©E¨¥_œOŸOŸ™Á’DZ̫%Kœ .Í)eY-ͦXLÙ˜Z¤#Í+œ8¦K U•%0¼8Áø8–LI3‹‘ùtÐ,ë.ho;¯ý]¯‘~ti }Me›¹±ù3èó½Â»Šcì$›ª£Fë• :“¥Ú£í(³Î h¹ò$h¤ ¶7 %p¿ õÚñ½ŸÉQnA{ÑÎfuo_íQÊâL ·±Þ’‰ßÐ,Ëò÷ÚN¦sv•‹¬Z MÕV^Š`K)óã¾ÚR^€Ê=PKvt¯k/VRUƒ™_ ‹/æ{|xÏg )è‘ ¬œ7¬VÌðÉö:õÖíq+§#ïâK €R]Ú]MSËCdÅ•h6€Âá5B†„W(¦ÌgË àµ£Oœ‚yÐ¤Ò ´”‚°u‘J*¾£µG„ŽRmåí"PÕí3òªÂ[J‘UÅ÷8¨¹3–;L]šJ‰¸ö¬ˆ OœUééD*9ߊöõðiG´”«l¡BTvš‚&æáÍjÄz”°Jàh<¤ÂR6ÀàÀ”Åw‹L„E†dd-SS8}ÙÀ Ûy½âØcÑ,‹¥¤FáÅ›Á‰Ù/ZÏ»ÝYFz…ˆõjB1#b›h‚{ß²ïö¤4¢\Ào<½vòp1¦F¼ f8 ‚€'Õ0÷—Jé$;! ËZ Ú,2„uÍÔÒõkB8²v¼,áªÐxKŸˆÙx´~¦ÖÀh²OÁ'ëÕÂ3g®š -ã3kJJ*A^Ê15ýÅ/~ñ{Á¿ÿþ{*mYÓmD_M-ÛŽ½·£MØRÎÌÉSÃaÛ6eÁ–ø8îjµÚ®®îÈtpt±ÄÙÒTÈŸ>}êÄR{Ÿ÷m¼Ö:ԑ饩ֲÀZóöÎÚÈ‚–ªš™g›­8¾”€¦)‘‚¤_©Ç <\Ç·”ÍBÄ+)Æé µ {QÎZBÅÊ•xiXzQ\ðy½8g|²€š€!tSSÞ ¦8ZK1>0/ EÜ ˆ[ÞÏY–2M…kŠféz"$[kYS­ç©lH Z+‘ÕTk©–WÅÌ蔜ÆI/XG"L\¡*)R)¥ÖW,eÉL‹ÍR#1‚}]ùóa®.‚Œ¸’,ù5|Ê@F“ ðÿýü¡ú&4mØ~sjÇ A3g{1ØH–pÌvÁ‹í"5žòÙÆõÕQ^–‚¥’ø@xR=KAc«òíÿKû5ÎãðóâMØm§ìÅ{f7j“cÞ'¨0D|7ü¶ÐƒæÓAF›oã!(±w’hÀp|3t˜b4V;N‚bÞüpRÉFóE`›‚‡Ð¬_¹Z…pVÇ÷ÑÐ÷¿Ä˜^b¾%Ð…ï=9Íî°¾RM¶ ‹¯\/³]ÄHW®ÙìNS@èV×y ‚øjÅ¥Ð, #~ç׫‘pÑ*AHÙZݵŽ`jâRȉ§ð¦Z„;³e…q€ÕZš¡ÂÚùjÖÝðæ÷PÄ<š³mÈâîOâÙF†C (·‹ž2°yê¨ö|­ÙÃs±šÒ)@4CRpµx|T6.„—B(àfuUB¶ÉLö>¥T|Á¹D×3¨vd²²‰ š¸¬Zx‚vz\ïM¥ù–y" ÈS[Öò^5}17^GoÉ*¯P*A @‰À1öÙ­läUyí]熉e?h:¶}'IÊ£¡l±y˜¬XÓy“Ý ooN¡çÛ£áÓÇo;¼¦Y2ARb"|Ëd;žBßê¦|*/CHßJaqâÝà¶@ͦd¯Í=>S‚™UˆüæÏtzÑ‘µ»®}‡É”«Ê'ˆ¹½C|\ðèô±ÿø'}Ž¢Í’ÕKlªbB é¨ÈŽ…IV PÜÀÍ*,Õ4¶ œ­ëcÐÉÄÌk*èé¨í Å@?ûs¿Èï0߯ó0ɽV ÃëR »Í ˜NIhÔâinil ¥ª ñíbUV(ˆŽ&¸‚e´²îý@[èˆ<HÏ·r¦P• ßSK™! kPÜØq ‚t*ÈâS¶Ä‰L³%M'ï¬ Œ³½µ^§Éâ+L—‚« —¢_—ûTbG U(Xö°,©M¿G/Ïd<)¡9•0‡,+¨‹ÍR­ªC}>} }ÏKJ#K)ÞÖ ¼e&[‹æ”H…+¬µOòß|óM4Ù—˜OvÉÒdšj×ù=ÐeÈúF+òâ6eÙ`@Ûgp)¤/vÂ8Mœm ™Ja–JM ûC¨÷ª•¿;p uäMh¶z6U¯kãIÁ›óÞ±ÔÙØÀDp˜­½¡Å” §Ï:½´w¸ ãó^Ôt:º5mÇî4Š‚ìYóÄ=YK†–áXv2WæÄ~ãkdæå¯iÔ^”Ëç+K… Ðßv”7‰áJpZî-( ŸÎ”ÉŠÍrgH“rõB ¸ZäÊC,Ûr|`ˆ¥ râöK¶^Üœ½r1ñbVÀÈ’Õô¢œ·‘m'‚#¥¯%ò‘¸FÒ—N%}qØÞeR•;ã(t&øâ,)ˆ*"=Áõ¤ÌÌ’=ü×yµ”›Áå)ˆÃ› ¢—’AW 7Oå-!Ì)ÙTÈ M‚)%`²”!Ô˜ØOá‘SÈû„?… µSK\ …¼dÎ%L“÷½ÿ7Pè.þSc§êwßuqÿ’îùΤS2$Ü„Íf`àø ‰çÇe–eóh¡¥¼˜¯¤aÌpí¤´“ª¥”ßûÿøïAù¦Ã?þñÊYóo0‘¤XÁFÅ„ ´ÄñF!ðˆ:Ãî6ß#Fˆ–~»ã= ~‚qÆ Ÿ'roäÔ´c8Fe&ŒÞF™˜ç-MÄ<Ü2©ÔxËJ(WÔB\YvÎåùq«K„8b]"81Ó±{¥Ü¤ïÐL"Åã3A'YŠÚ†GS¢vƒÕÇã€+çÂÙj§ýeÔ,ï ¡_l¶JjM°%f{Ál’‰ðæW%(¥ÖÒ0 •´ÙfÊÖT¼ŽÑzcÚ¤Ú cô@³½Äû¡¥ñL¢k Ñš5¿yÉÁ¡Æœhjá  "%èóhL-Î.‰¸1šÄAœq§J­çî—^ûSSo›‰·ëk’ÊØ[0€µlòMÛ¾š\*³„3Ut¤H­ELÙúFËW>r")H1q X@ª¬òbxqdRÑ€˜,°+'ª…Û¦ Ç}q¹r)±¬*ÂüB‘ÀEE“"®ÏpXj–Êù`Ù¼”ªÈøÑ:)Ö$ÞRÄGúùê³*Ø –½ÿ( ‰S‹ÈjënÞö-‘!FKÕš„,D sBàʲ”J÷})±L¿¦–mMªF$ÎHÕgmÊ)I=‰ç­¬›¬;°í×=~/I}kÝ“f](§Ð¦´Ë 0#Ø©À²*AOêñ]ÔÖ*Q)¶C(°Üd*(°,HÝ·›rŸ5Ç©°F4ñ{—G–ª$ܲqë.Ö(:c@4AÃÔ‚À,™Ãó²üåý«åüø)(ô1XªÙŒÐœUAk§Ü9løÈmVŒiàÝQkA9Ù¦uJ\ÇnªŽÂ:* WžobY ¤ÄíSmåmS,¨„¯ß#ÔŽBO3Ë»HU‰$[¡’°Œ_ þ~iÑT14±WÔ›ÿÿò?þHAÖ®'UÇÄy)žÙf‚öò¿üCÓ¿`k v'0Ñ×Rß~<l§h1‘›°]4¡”ÀÙ23sß^T¡uJh‰88æ]9Í&4ƒ¬*ÿð÷ÍÙ®ËPþþúõ§†Ñ´ íhcФeKÝ!F3)ËJZb:7Ï‘I‰e³tpû²© "—ªWd^-Ï4E–ezÁï%ÀG›‹ßFŒ±]í¨\6¦òbübK%5"Õ !âh4FÛx8ý€QÝK  ÒÞ©QðNÅïÊÅÇLªý™ZM7m %Ó‚§ÓÖ0Óï#ˆÖôI1Kdq%Yˆ%ðZ¨¥žx ÷ɉL!Yž”BAÝyH·z‚U)³–hT.6(@6æ·ß~»Ž|Šà €Ö%ASݶÌÚDU4ÛqXcót¤2´ *>)›ª)È –ã/NJ;œDê÷¿ÿ} /ñˆv¡ &hHãA´†ð݈¾–²Í)Þ6!ìžê¡CÚEÌMn™…¨­—¥XªP‰ ¯£@V ®Küé7³@¶ùGЈ%K„S%FöúJ¶“)® B…{.M R &K![») J X…JÈÄïĽ-ìÂxR½ü㘰}Qƒðíb}ô“µµæºv!h¼R&ˤX  ¤Ë­ƒUèƒ,ß^€mD‰îUÉ6ÆÑ}>b´U#C¯‡rÑ¿\ â¬áKå{Õ6s"p`|¨|šF²–²=>Si­J?k6ÌfŒ@ÁúòÊÈuKP×À“Kº™à–h8JjÙ|FiŸt¤l£éïc©ˆ!>e垊‡”eÌšÆiY…ð• Š•0´˜ øp^Ì:¦Ã~"úµã§&FЗÙE±Í–MÒià;: R(…–a2w]D©w}¦…bÙ æoB§GkkÀ–×nÎ933ã'eÂ^º!–+QXm ¼1j-µs€;á¡‘ÂC^ß”Å)Y%héÛ—ˆ¦…X¡óô-ê{/L¿mB ؈7§¬åvAAXÏ Áoá ^b>¨·}j¶Ð^ĵðʧ]À×˾‘ Æk˜‚8‰@h2ð)ó!ÔB0{ –”-ÍÃ3ˆø²ÀGÊÀ²@/j?†Õ þ*óÿK!Õz‰ÍlÈíŲŽN‡†G6à'ˆÚŽä³²÷ˆ0Ì”CÄt´@ꈃ!>Ï ¼SU²áÃ#ÛÎá=‡‰_ ß!_#œ§F¡^=ý>^ÔT¹>AµÝ%;¥6X šÔúJi!%Ïךe©&¬cž~j@k©å)(ç+é;ñª€ u§ìY•·¬)Ma4"J,Ëâ#ˆkÙ;€ #ª¯¥ò.ü½®—ò¬yˆ7[}ñf¾-He=£æ!e<žAŠõ- É—ÂÔ4­²`f©Š!ô•Œ˜füÊyÛÁìíŽršh~윤® •tU½ë C±Åp"ëè½W*«EcÊÅÍM³ªšÉZŠáâ:îÂuÛfF__ r“XÖÅ$íM*P@<þSà‘…¿±J€÷Úi&Û´æÄÁl†u¬¯Yƒµ`ša8%ÓZ ¤Äd3dxÊüÇ­¦æi#ˆØOÊláÃ@,81^Y#¥ ‰Y‰¬*)àÆN"ËWÈ«íXÝYs&w…IM¹Ùò˜ºãÐç-˜²p²¥ý ¼|—z‚/7¾Â6h˜–¼’ÆÇ @IDAT&ilšuÄ÷«“/üúÆßô¨c^ ioF;Û‘ŠƒÐ¨üÝLkyß‚³5ë#ÚxLË y8„EÆ×šÈL­?ûÃßxGì7Bóð´È›aKà= ¥©¶”2á8 ÷*óEµ%r“S/Kû Ds\RZ°JàȽüæf`Ð*)u¥H剫ÔâM µªÄÈ VÛÀÀŠ%ÛŠ§Ã‰#[ÐÀŽ;±h–Rðtj-Îî7Þ Ó@¼-Åm9o€_µto§‘ÍÃ÷tÄ %fªšœ2³Ê,¯ªßlm²€g©õ±_¹}%•7¿Ølióh|šb‚[ôò_þé·5ˆ›aÝ £6m©&ägmƒNÛ¨bÓ†`’â‰ä-L4ˆÀÙR@hÀp UY Šy4'ÙÒo ¾ö—|§—öé÷üÐ56¤ ÞÜ ãuJÛR‰un æï2ˆq²ÄÅín¾“‰#F³YåL¬/Ï€8UX¯Á-ŲªÄªH1l/ "[À»œ²ÀR‚dë•OÞ®•{ÍV_x4ïÀ¤œ„A‰`JYÂ5>Ú‚8ͦEdYä©Flo;ôV›G°ý²}A¹¦£J‹zubÚµ)fÝIUe³ÖçʾºÐQ•.æµë"¥Ï+/•Ž* ßfˆòYf¹a,u¡ÃèD+H–ï)€Y*‰šŽNHØg>JàJêØ$‰ IµGH©hüù'äZ£ ì_¯’(SFE`*hï) §ŽÃTñõKAÜ)À‘•x*U!XÛÀì|1{= T;Z„,Ë r÷ÿ¶ VG3˜V/È̲#‚)0jWb0Ç—¥£*P ‘UÂÃ/…À,WB'>œ¾Tú•HÁC¨%îÍ ?B{Ï‹ãð_ÿþ~øÁùà÷ õ*6€Ú ZRÈîÊ>®•¼Äü ¶}<îôì4ýÐ¥“1“ ÉÛ…'SUœfƒTe)ØÀð¥ðÛ„`KÌtòé;œÞ €Èöƒµy|Zc }f÷MªsàewmÇ$¶0Z3ó»m§-Œ¬³Ü³¦Àl S¹Tí,q*W‚Æ¢5RÇ›‚Ô–b ©RÑ4b¤h<A/äÊ—Z6djëÒ„U@¹LP!_A>¤ }Àg{çŸ8£a篓$BR6ÂZ”Å¿4ÎÑ…L-ͶàEᇬS"XÖ²B gFíä G‰!Ÿ¯ ¦ Ö²‚š¦9¦eqTM¨©¥ÕòÈí(¦¯q௲ï¾ûŽTs®õ:n¼†´Ìâ‹Õz yKø|%R‹íËzR<°ZA±åyê×'øé7Ošh–¼lA _{ ýåŸZhmìּ1µ Û‚·šR˜¬‡éÚ`fvÚfUO"¶–r©bTóÐk¡¼K+@ò1yF-æD’â“"â’×±’šFë5« 9Yžf1ÜËʧÈÌ(4† NË4!ðÈÆÞ^VB¹ 1ÑÖ%Y4–BRÈ5*¥$ÂheÓ¦© ¼÷%3˜¤OÿÚ¦ ³Ec–mMÜØ=¬tˆ÷mþÎ*&¯ ¿; П>¼Â”•—jG²l1Îá¼r «­óG¿ Y÷Kþñélâ!Ñø™¦N Öé´q¦9,1Å;´)K¡­SBÄi7Ujðª¤àÀ5Z\KdY~Ï(M…‚tJýwúÿö·¿!iþ4‹Nž7y¾yp2}_þË?Z7¼‹ ”mžh†·µ½§Á¶ƒ3",‘©ÔÚŽ€æE?¿«†à%ÏÇ©£¦å@þ%¿ú¯‹âkÔ” ÐÒHµÓ±T­ãˆ#àCŒ×ãð΄µµ¥è$iï| }áá® g8ydÉb®©2x± ¸ÀÔ6aóTÕRì*6Ž„ TI­Í M § OYêˆTA0DL_yÊb%h–J§Àl¶Q®IAX%Í#K‡¹´)W‚Ü ‘ öá¦aª’¢gí ®œ Aå âLVp±NÀ.îySJ ‚o)ÐÅüËÆáÓÁ”k§¢Ê9ð+„¿üw]|¾k¶TÐ`â¶Ð:DÐü|{4› ¯ñº½IE“ÚšíˆÛ„NÛY/½Ð#2N£B¤*ùøÿ |­Þ7úSHm§mšs3#k“t&k$¾O­|J„ÙÅSŽ€)Ëàm(E¿w]jŽˆ¢!ãÀÅ͉Ïê ”Åtb²zá§\‹Óì2ÙgxÎ _U ©†TH¹v|â²È¬xÖ^(ˆ)ãC|¹Ûû¼…²LŠÇ¹V×0hšZ*ir íœCBëŽæÐÄL¶.@1N…)Â~ãYJaV ×TÉ&—B…Èòb`…Ñà•›ÖsÂG€X2ÁIj˪"Û`Rkräæ±ÄçµHß±ð1eáø–,‘:ÂÍÜ£´ÌV‹ÆTA ø3ßó– æµ£PÊÒøâÌ9¨eJô’ÝSCF.೪ÄeÉ ĨâÔšØS°\‰@Ä7ƒ§V lÔÄ›?ZY`"<µvššT-ˆÄI!¼¸î!v]»Fuæpßê~ó¶Sỽ¿üã|´ `NvÄmP`;æép€,‚BYˆÓ09/Ff‚8U9“NL µ£P(u5?.¤#â‘H)«¥,xÉ¿";s bõuæu8–†·£8| œšªÙzd gž¬TKâjÚ@ª3IÂÔ"@Ø–Ê™FR™%f‡fxàJÄ—ÒqÀ«ôœ¡òªz56œo^JUs&T%.h*cû¸³ ÓIá(aJÈuT¸š ¡}%R¶ #*i¶¤ qd›G»hpH>‘ÄyYâñ“ŠO!M¾A‚èմ‘*Ah KA|å_K5?Íâø<£C$à äÅ=ksþ˜&vbbÏÅVš1Ž OM@dAËÄ;.)K%L`³8Z° F–ø=Jך§ðøØ¦2»–IˆPYB1e•HQ1º¥R•fh.J4µ—Ì9wA(±üÚYœö )ÓÅÒ –Uafã7䯰ZâT’DÊ„<ÜR9Ä&‹`;@Ö@ZM\y4±ªÑ¦/€@*fÐEùÈÆv½( ²ѯ‘”Ø`¼Þ~KµŒOA¹©º©Ku RÎ-µRh¤l*P!s8 JUkÉcñô!ªz¸ÑJå«jfAd4±ÀÒAÞœ!©ÏŸ?7Xí ìQ‰½‡eR†ú)öÁjßç)ïØ5¹4º:ŸÖ,\¼gã £ âKÙ‹”m6»(çØ;“›A¬CøùÏù Ù¾ïEiÚ<ÔÜc{ nT½Êf£nþ{wd>oY!ÐÀ4w‹díK‹pqäšz! LŠGN ™¢EM‰WÈðYœÀ‰iI¡™“ª°áyå ¸ÑëÎà•cZ6˜¸Í †³Va|›My]êÅ3 L‹zµ5qïðjqêE–Âv¤‘Â4/¥3?…NG6YäSU<åÀfÀ´\‰*1ÖWL\ÌŵF((UIUÑ ¬Êä–e§P9M‡­¼aàJ¼K¼ùÕ¿/ðË^&·iÁL«yŒaiì-ŽÀj*‹&´DƒXaÑ L¬‚G–¾@‹Rj#ó”)$„ˆy B_ ½öç!þÉohm$úÌËÖl˜àÏ®žï–mÄT VМ²jÙ>BÉZòR8< â‰;¢“¸ÊÛ~‡_‰8…À+³kÀÇ¥UB6eLË÷1¼"€RÀ4µ&ç¥,kJÇá`F>#^óóR•8Cñu§Î›€˜ßEJP9°z=VGÐ+KÊ!ø¬1<—bµ‹KÁU*Ü–é,Á”ÅkaHc4 ”&nà˜-ãQÕuDZŒŸ ¾^nÉâX“aM¢°¥¬ e©pµ–Åühé<{L•K1Hdå–uçïAK>}LAP»‚”§aY§n¤ó™Y /†¾é€àT°7"šx©ºÆImšÞSÖ¸”%£Y00¤ÚÆ=Z—µLM;r;ÆÀ}ˆGƒ{›@ëÙ[QÂ*·DÄ,(Õ`j-í—ÇÒ£ZV J–&©j«KÅ,hŒ!F… Sðjœt ï0o»^œ ɶÍf0€ÁL"î4ÚHy©•Ø>2SË"t°(‹½ tï.ÅW‚F'Mƒuμ˜2#Þ¿­ÜN µ¶¼ùÏ>ŸG‡ Dw|"Ua6˜lL1°%¦ Zâ–õ¢ÆÄÝiL† äÛ¬¬Ø3ò6Ô×-Ê™¸h•“ ¯)x²áŸ>}3¾o¤ùÈ!G ¨‘˜5ž¦˜Ì/ÿ¼ðÿûƒOÉÖÈäúê(0Oo µF(uŸ\aÃËV‚\ܱX†PƯ’¤™0ZUÅ#B“ ˆ`Vk9Bƒ«©¦±; FŽÐ1•Ô^¹.²:‹—šxˆò¾™:LŸ`M ) ø,)!M›ˆªâ tÁ"7³%j=‹^Mb]àmÂױؒ&V‹SX€&«…3o ͩвrL ˜Å@j±PI­¥XRÆw˜† ǯÈ€íâ zÍȣɲÎ>~"õÚw oþÞ(ÚHS{^æ)¾&:Î ÖÀ²ìBJÜhצÏ+z:éWK­ “¹ŸœZ«Y-MÞs¤ÀªúöÛoÏp/2¿ å·ÿ»¦£ÝiÒ Wÿs{¿ýb28/ÕPRøb4‡Õ.F^*&"eû¼)Å”JÐTqøU„ðì4»žŽŽ½Ö€›í¢|¹„˜ÄS®‚%Pªýò†¡àÃPÀ£­5„AÔ dÉ6|ä‹u:ZŠ“ªW)Û¾kpçS+KSÉøðIIY&Ø8—}S~çK5¤ á˜Q †Ôh%–ø ‚Àð‰4@ ‹žŸˆ@ N4 š{–Ž˜,ÖË)Õ±·QL&NêªxTÁ½ßýîw¿øSß´ö‹öe<µŽBw˜Q3)ÁR ‰v6v™aJÑÀd{-õò³”ra0kj™UŽ–ëòü¼ AÜ„>ÛÀÔÝH=©j-F ‹M’ެàëÏþô—¿ü¥‘šA\¡àn=H{OÓ_»ï½ãN~wìóÈýáÿÆ0áóTÎEµ´)ú×Á?Þåá8]flµ†³‡"+E¤]Èâe·ýª¤ÊòJplS¡ÛˆÐ$=KÏå%õ_¯‡v8qÎÖ¤^Ü5Ð=¼-Å‘WbwJa)A|¾Ã”Õ ^kKVÖ tàNÕUV+ö˜./o_SP[ "VÂ×´¸.âÿÝÁh* ØR—&äÓ&ÅÆw8îšâ”EPÕ½³žþ˜„ö¥ŠíIQ@ËФÐ/Öyâàà Ð2š“àà‡§6ÍûñFàgh4çáÅšz Ÿ59\-3² /RØi˜TüÔZ¦S–ˆQµðêè+¥˜ô†ñæ_»æ×è¸t Ñ¢x1Ð$8…Z Á DÊ+«Q{/×4PŒOGV ƒó¤:1ÕN¶€/ÆÙx–@ÖU±„7^[^¹e ˜õB3LȽõP ýõjyW˜°s€Ü­¦zÕÅͲéEÝ5öžFÞ+‡S å ÷Q›ªÖ [¦Œ†¼ƒ¢€Vª@ÖÁ²§oËhÅRb–øÝ¸ª@:hÛšXàeJÄLª G,à}>ßbHÖ¦©8F`1-È–UAÖ¬‰ÝÝ.q%Réà3£@ú˲Bc€'U µU­¯ ©KæñÀgÃf@ ¥¼³£I R®µÓó€ã3ÙiŠÑXA)MUCV¢V—žn£FSR°ñ”@xdÞ¿[}÷4ýNªKЖm³¥gÍÀ7§ rK¾*qn bB5Ëd-á²@±ÚÚ¥‰ÏÐ:Ÿ––½»©’¥€ŸBÊ<ÚljkôÛßþöÍgÿZû¦‘K•‚%e1ë!53 HE[ʪ^e?üðCߌ!¨EÛïlßto‰#È#;…ΊWÕfòŽ+YL4`œæðÈÛlj¼)¯ÓÞX‰(áÝ¢7g;Ÿx>³!®Ê¾ôØ—QÅ.€Ò6æi;²ø-+ßüpUö’µ_±rVVçÕBhÖYÊ ¾Ø+FK¡FšÑ«V9B§TD°“M‰{ç(9¹ëAÔâÒ;™…ŠáÍ¿X ×Ô”‚ÁN›k¤7'Î+DÃÐa–dͯ&Z]ìY#×Qˆ¦„”+DÇ’NÃX2ä4›"{eÎ7F­áÀyA³U‹¬oâ£`½¶`²fŽ0M©JÖN¶Fùêéù&øÚïø¦7m-6|±ÉÍæ)hê|šª-ˆ›DIV ¯„‹ÂãêEŽÏÛ/ä~2=kHÏq÷¼eå/?ýë_¶L¼imãL`¾ÃÇ‘jfÂ6aøvÑ9Älx8&Ó…!C˜çk*(K\,%PØÇ²8|…G÷RðÑê^V‰@#ÞRP£Rí®r± c"1ËÆ‡LG`³d{EkÏVX­%Â3ùxyBhÆŒP\käõ _ùRí:Zš–¶@Äï)ùe“â6èT»{² &˜ìb)1©,2ý¾kcï˜4)È2oV¾^…t“b¾^é+šgíî““å ²È[ pÚ—¬%A-Ú ²”%“½ÇRÈ ÈT±¤ÈUñ8‘ÅÝ Ë‹&ŽŒ)Æáq€eùÿþÃþ’h·º&­ ‰©1& סù¤†$(Á<*—U• €TµhÊCÄë5\*}žYFã„WÅ#[š„¿Š¾|Ð’?ÏëŽi<³uàÕRëm¥C@8-¯.ø@ÇU-&S¡­UKG­%ŽNcçqÞýé—Uú¦ÝÑ×®¸½hj Ôeœ¦µ4€í*lk–m A-«ÖR Δ෣¶fÉpºKvòhÊ©¡‰ùfj†»¦Xͧéý®ZcðD¾ûî;¯í  )вO4+§A ŸÁýMþ ;ò‰zowí:·¢ÇÝí±Så-él/–ŒYA ²L9¼£¸XçIÕŽN)^I øNÆ-‚X/_¾êÏxûß÷ئ:j×TZ4†û`ì6G\³ÔxpÌÆæei 0µóð ßîÄRºt0 ºBRF¨ixü:Lå;IKV;¸˜fçIAaM“½¸_®4>¼*)1‚Râ¦mËlqj˜ lYœ–‚‘—JÖB¤ê[ ¿Ú‚”r7³íìØáhÈõåxV²bµëeÙë‹Þן†×Zjóˆud„8úê‚ã"¥ G§.–>Ùº¤g«*>ê×]m› M¨JÂüٟ׾K|ÿý÷:ÚŽMk<›{ùô·wà5àãH[ò dé03 ,¾òljÛ]' nk–•”Ű"bL†iÉ_ùÓËÿ'ä…2A ïíZ÷«ç9ü扷dq÷Ó1*‘µ4¡_¶¥lÈLÖöy%R]*Ì Öñ>€ªû÷”¸™ˆ0å™F㙎¾7ÁûJšÀf›2°]œ²ç+ÝÓé@š'S•é‹Üð)À] òKõÌNç ˜H­#ãvu©…/‹@Ür·H¬Ÿ—…#ôàž#?.p“W¨Ê’á(¬*…†$"EG.*A+K±8ñ-e#`²C}’ÕvUª²¼ŠG¯Ú‰ãÜ·ƒ©„l%R dÕV2YËkœ³Y†C!‘‚µëš¼.ú Î {wÝ3¸ Ç!–ÅCÐÏ”T õ7%Bd#"YûLJ­?²Þ^áL¬<L_Ìã£UKV¶K¦¹.ø“°Æ8mn?qHHšoÔì#ÁæTç;Ê-¯M<Þ7&œg@"¬l¸ÂjýôÓ'a©ÅÿϽGビï')¡o0A²=5HÇ®õ›_‰òCcøj!‚3èEÀqtð–hÄËÍGcð÷PÐà>y¦Ï+´lqoŸ>}R"žiç¯Å„ÔTœšvŒþ,N<åkÞóiÍkŠÝ/ÿha$⺘jƒYÚ&Ü0ÆÛ$@Y8Ðr›m!|%‘m‡Da/¨”!½±:„@'cÙ ¤˜%\¯WýÓF_ˆúéec·í¶—ûãÞN‘#TÒ:Š>q?ƒ^‚JS»o¤Ck;ý8 MgÅ·ä Y;"!úö¡_ œfˆ\/UV¹@2)ǨœUAÄ زì8WÑQV’—""– ¬<Gc4P– nH´–Re!RNÀ²Z_ u\˜@ž`d œ®WyÛOÙiñâ4-v©Ê]ÚRj+‡£Ùi¤ëe}®´ZÌ:B®¢ÇÀú&î5UŽ ¤ÐÁjd©j¶§®°-¾ùæ›ô_âýˆÌe#Õðšêh¤ô×ǦZS©|äæl/<33°ÊøÅ! Þ‚–•÷æéÐtïäi®Ùòµßþw ½o4É5àサÁžš¬”™Ì¡Y†õˆyÃK5¼lO³K¸¸„‘-¶}µ–ì4¸ÞmªåIñ¥(êEæ‰S‹cÙÌ!¥Ò¬ãÈ{^† §Ž] KüJø-£]™GÖH=¾Ž…3Æ8÷ZL¸l&UÖ²#2ÌbÇÛ®õ 4Àátû¨Ó „cöª1?_–ˆùÛ”§=àc2ËŒ¸@KÍs©ïgG¯:„ÏŸ?÷ÎeZƒ™¡ n/[#AY\­©Ä¾·â-^bd½Kج¦Òq£Þ'7[„µ²J”wβh÷½½#H–T½*·äqèSt^2COîíâµâÍ\ 77ƒ€éÎLh`qsÛKUJ!Úȉ{‡AÆD³Û!^yÛ‡ã·;KÖ3jž–‰ðJºÒÅÍÓsIMÜ¡®¶ Å)Ë#Ä4FâÀú ¼¦dmxà¶™Hƒ…K¡ñ]°¦µ¬‘µ&™¾ŽjhŽ‹uu2åzáÊÆ§ÏZvb)WÅ#Ü¥ÄD˜k )´wUÑ9ê×=ÄDˆI >AHçƒ>[¶¤‰Ö™¨‚'xÉŸù³M…P|'ˆÛÙĤV Kq%–!˜3) ‘˜ªÚ¸€©Å,U‰xäû„#G»Z}“¬ZÁví0Õ:¥óÿCñ‰&ÆŠQëqÕžâ¶ ‡¤ Çá;Ù µÁgñS槆/…ö¦W›”íƒ}×G-¾Ñ‹-‰#SÀ,F€# )”5Rô­; ^*kBqdóÿýï÷\|Òò“¼Rÿøãý Õl桬…3Y»Žš,<_wüvTè0Çé(,Ù] B0¼v ñ!öâŽñJ€£¹|‰WÅg FD9‚*çàÿ_9äÑûZ÷v‘Â}§ ÜHCd!fûúK‹¤Þç}óÛ–w°Úµq[s%Ò4Oòg-³%¼,„µ*úR]3Mµ‚ª,ÉÖËQK!KÑëEÓÂq~ùË_Æÿ ÷£ʺ7ªŽDVSx³u%úJUÜ2N4±Q‘mð¼U]oÔàqÒG¿ò‰ÄL„ï0;U:ö¡Ð…Àuà°uÔŽÑá᪲Î_/ÊÕZð °©ÊÞ™µøæ24V hÉàÄÀyñ0ë»ZxäT…à º IUË[Ú)B[SK9q¸ 3Ä t-áªð!õ’e޲.4]’¶¯ Q.Ë4¼”çÔT Bå÷¼ÕXR0´b}›­ÂÄŒ/HbY  Àõxí»„?åšD;:"½:RˆÈ:Ò1›Ö¦˜˜µ…Íiò–‘¯¢GÕ©¼¬2‹ÀSÐZÐk¡Tç4’ßS}ùø‘ñžrûõ,˜¾=Y 3L×IlMËg}”7¼“l`owD(XVh™$šoðZר*>2BjzEã1™‡7’lï3ÍS¹Ú˜@K¦„w+ºn]½¾Ï¨YV•N{Wr)=ÎÄMLCšÞxb¦D­ªšÊŠ©‘BãÃù”W%€o j¦QÓé*§,µX¹|å¶Ö)yµ¢‰e™˜¥V­”F@šæú„'r'hò†‡;Ït¶k˲CY:±ö‹ çé‡ § 4U|`²é‹Y² ˜fµáÀ,ÐðôõBSRœˆÖ3%˜iÕ*)ÛxÎV¶™Sn)ky®…ÿ(°îaÔ/_Yc%:„ «81š,ðî-¥š2Í#q‰$Ëד‰YÛà™ áhâñ: ÜxW‡õ$ éÇ©Äd¯ÎÇ% qެ‹eIS‡­‘¥*ˆ,ÍD¤Úš,D¶î-e‰Ü<øpÖR@²@¹¯Þýg¿—ÙÿD݉5íiséëåU¡ëåQ*ÿ?ìÝÍ’%W‘µáƘ2eDƒ`ÄÅñs¹`R•n£¿gÇ{r)”ªNJ•‡oÒøÀå{ùòå¾wDœŸ¬¬’ñ8²Å|Á°,pY`µÎß™´#“ hê/9ñ< ®¾w$)!õ“¿cêï98œ{¡eƒê+ØÙ&È Î70ý©÷›}õ÷°éS£l€z‰»+ò²Æ¨5Ï6’Tw &­½XŠei2 ·%oYP‰ÞÝëM¥B¾ws–½”þçYŸþiúþ£µÄŒ¾¦¬©L+6•e/8›Åð²í…B†ÌàømŠO¶Z±ÂÈáÅJ×pN³U¢Ü7po®ŒT&«£RKq— ÍÚÁ[ ÐÄ8ñ ĘLjµÉ ˆÙX²Î$Z-pR¨W%ü²eZÞ23“bbjR+‡Ä„0ÙøÀ˜f¼–²1y8ÐÀÎP ¯íX)ÓPåÅøÈU)Sã7'Íû7OÞ$bˆe^P¹Z §ì*…Ãd €¾@_Kâ#¡ë˜TUïô~EÐÿ­œe}B–f9'øòD(9ƒ^¦$…†¹¸Ó(UIšwr½xÖ¦&Qå¸Ì h  ÓK­¯m.„Wæçˆÿšm–ýé®yLØlÝ0Æk_p4&+î(òªUñøYH[Ž Æ÷eYa‚pÙjéui}ÓïΔòËl¡› _¡˜H|µÀÄÅ@qGÈîƒ5C 8ŽB&@`®”KÖ¡‘eqš3$­GØ–Úú1UYŠqjTk ±BMéàˆi¢©C,Ѳ¾¾÷ƒ­/}&–(dD,›DЩՋgÑNÙËG>%È-8Jt¿èr´^n§•Œ¹ãä#ñÅÓ·ÔZß3ô÷?¾âÀ7€ìâÊ©e–t–;ä8áË&Ò±#tJ²‚{ɹ3W“®N‚Hàpi)ƒt £µqüÀ¤BÄü'-2¿ ‡¤\ DßT‹õrIݨRJDŠùú&kHHÌÙ;¡ÂºGȧ£5Aä|â¼I\2RƳ̻¯º")‡©XSø†Dë<-+Ç«U¥œE£ `Í3ÍÃ¥ØÅzœ|82<!nÙ 'Û06ê4ã¤\;¦úÅÿ:súwOÓ/è³p“4RÓvµ–2¹³ê¹îF¬–GŒP¡x„6D[ÓÊùVSš;:3@"Óñ›?Ï=/éæ×Å  Q{i³¦j_Í`Y¶yðí(¤ñ,Ù¶”å‰ðøæWËH­Ȇˆ+4RL"®EÇâÕÃHJHiÁ#׫À˜Ê#«UÒ[02ŽBY̤¼*ž ¼|\“ÕÑ v¤¶.•T“BÇ%ÅRÃ×Îg—ðydðcŠ‘2¡l5&‘J0qÄYüÉÒTÒ$š¶q%¶`Z´ÊÑ”£AV"¨K“ PàkQ»µëBLˆC„AÔÒq˜!–UYà´wUm3±¤PG ˜Uâpp,©°î|ûêUªŽðÊUAŠy±ªúÆ ©¶¤pʼ”1E Z0q»vìjqÔâG†¸48¨~•A·Ä¶œ©oL¼®ó‚YU¤V^ª9ÄáZ hQ Ï,í§F–ÅmÆ"‰hÑoD#Ô½ó?r/¯6‰ÔÇ’á#òâÊ Ͳ‘€‘C*g–¬+û‚}ï¿Ýl ²Í°´Âb)4f‰£#¤”˜íAoò4…cAsiÜ{­­^€‡¤ßtO·ëéRƒ Vß@Ûm ó÷rdR‚Tå)TR\J6P }ÃLaú©I!tR6LDP£âtŒ ¬µ@a"ÓDˆFÄ[>ï¼è¸SñûàzꦌŸ5’x%k i/½ÔK–/›5'¤­ùj„/û7júå™ L³§Q ½î[ÐÂN·ýFjM‹Z^!ÏlS£bY±'“O¡Ù.–€ ¬ÿI‡þê®_ìWkü-1L4åòÖ÷!#DFX ö{/ø!ï÷šúÁžÙìˆYnâÆ`ð5²tDqÄwÜ¥éö:%¨ÖC+ÛFº¦:Þkënƒn`r]ÈÆG`²_öõrèëË*O“Á5ª—¾zI ÊŠ{àÆÛa)6ªB± ö¬u6¢–5„IÕeŽÏBêÛ´šV )¤¥ØíÚÈJv†R8é‹ËžN/¯<4|{¡#¨i>5L–,<…z%[Y°«Õ÷îäÈ|Öù ¾€–<Í;AÌâ8ðZ;aeå÷Q!ø²ÔšÊ¥„ÜÛÁN©KÜ([ö55)´éO„ ‘d^ÌઠÝ®JÐÚMÕ¦T1U–Å |ú/ÿ|øðÁ õ´öÕZ› ~f}y=Á‡0gÈ[âÌ+iNc;*GÀÅ8Ì‘âXæĤX%@YIAÀ –Èá#ka.DUp|Óǯ…¬:|Y @Ù#ýb¥p:´-(ø],"¬ò誥Y/ ø!&/ËWµÚ3Cث٠AÖ0©ñ™l}õjfO7š8q4K4KY»›¹×1ÈÍ,fÍ\<8ZÖù˜02Ÿ Ü)EŽŸNÎÄ»^ô!¾e)ËâZ'ÇáÛÐr' ±”â ÄÔBd«‚”M–ïlcâDóñɽç»HJÐÈÚ_ ÷0‰ÒñH@Ä‚bþUa„ “£‰ÌA˜XUKsh1ƒÇ¬$d1ÕRèîLé(A "N|"N8A^–š”Ãt(î<8‘ ãˆYÊhN³'-©j¤œ²€¬©˜˜5ŒB%Å€[IS  m o ÏD–Z©~Šÿe?¬õ§~vîóY;"ÎÈfâÆè%£f㙡ª®‚%2³üö[ªÂyåôóxdA/éwn^Âþ·þø~©ÆOÖ;=Rº7yÁ™æº?›3‚* D0ƒˆóhÏúk¯éÛ”ÿ…M‰ 4b:Ü®mÙ2o $xŸVj"]qÇîFR…VÕ½Љ¥yÊJ ²ÎüY¿ÈëVw™ú¡‚FúÒ×eM–&RŒfkýÁZSñ&졃?ß–÷t t÷â‹ÇLjHjmóŒÜIZº”÷ÇSyíÌ)f8Œ‚’|Y4-€.“e†o‰fÂt ˜øH!ª §Áee…õå¼í ó˜•Üý,æY…Ô–•X6ÞE9 e„¦iÎÆX!K¹²<Ј.HážÕÇ]4Md¶^«JP ¢¤ãÀY 7šÝªLÕÅj~…ìtz¹¬‰ð!ž‘»Ô;c?ÅH_÷n³Þ’Ææ±ó}6kG€Ï€2œ%HÙ1ú™T'ƒFAJ•C²ÔlPÀ§\ KJ܃y ?nR²Ï}Ùô'ºf k†°lk<°o fmµr†yÁñ—ñ"Å|A´º$ÅÓgd™ *±Y?Y ,N·q|c Ürñ‘eÝ^*—í"®Kj²̓& Ò R4ùfv‰¥,UUެŠC¢aÎ Áh&46³T«5_Iä˜Mo*äÉvPD€JšVU t88²¬`KÈ4 5Ò‚ikD˜SZ6sL‡£QY¾}©RûJ|²V‹º 3ʬ812|š–Uà’}…«]!Ú]AI…÷ ’š6°ìæ$eö aë8¾¬óqºÊâseY•^ž,“ƒÓ цSç-CðÛO¸¥¬F{ Ž Á¯ UŸŠ_ 32PJ¼î›Ó¾ˆçÇdz…4 Dª½ˆÙ­Yë|í¶#2}‡%è+H¤€ghzª-.øàJºçö)§¥^qj†lN¸Ã©ƒ¸~þí{˯ýëf¨ö3½Ûؾ·:Jt䧣ܡé·ÔQ_†Xm Шj„¼ d‘xÈFž¾Œ~Ýÿûê >~üh×ë®ð>?AÊøÌ’5É‚²Wæýë¶øNï+J“ÐY Q²v-Ö1/èC¡ÀátÝÍÌpX…!0¡Tj5J3r!-ÄrA Fê“ÿ¼Ò]êóc¿ücGÝBíEÇzµM@Ù]M ÇÊ›V ÒããeqÒ¬j‚|íªmÙ®é”ÌFH¸PÀwQBzZ›Y*KYm–¬T»kN3«"ÕÖpÚ©gªpðµÛ‹•åaÙ—çÄD”0ä¥RÛR ÍrA낦_É®Wc#Œ)6?D¶rU÷ a’µÁ½â—Ú`N²ZåFbu„ X`UdW^-dÍÓ’¯ ^,èž©×>•'¤X‰e&f&WþÜßuñ ¹ºÀ¨§ÎÖ kÝY¹üóqÍÓ]ämH­CŽß…C¤ªŠ/î~³”B‹¿‹3L(n¼4Å!t¾ø_¥SûCs^Ûu—jZAC ôåo*AS *é”ÚDÖÀÈN)‚”ÀL*\Y2)H‚ñ©Á Œ$Û$1ãpÄ—ØqM(H°,‘ž%pÞ­N¿}…ÔBá†9s¿|²4‰‡¬r¦V<;×íļkjjYV ¹É’‚ë%ÀZò Û6šrK^6)¸Ø`J Š#ˆ¯ýü­6´ óô•¿"+Ÿx – ÙRV ‡ð²:̺ØóL¹l‚J˜X*åÓàjaTxË‘cV"Ö¢ZqA„⚎&¥ÊHëxŸÔV|o±.©ñjÓá1Ýiž,q¤¹Ø«´”ªÇ€­;Mg„MˆD* ‰×R J ŸVYK"j-³ qZ*d‰@-';¾VxCÉ6ž³«¢]×É-U Þ8Õb^ Ï­L_Š__|©ªà)óŒNU-+‰)6Ló@´óøæ¡Sqçu¶¡‰ùÉ"ˆ›êÊŸš>4ˆÍü÷¿ÿÝÛÒü©´’¯¾úÊçÔÞ„š_ÇñÄÛ©© võòò·ŸÜ¬M ØRÀ–¶ Ɨ·„¿ñ ?)øj!®öHß,<)Ë>n`—¦rà0æûÿ×ï:N£ILU_ËÅcؾ”ØÙvà-ánËŽT•ÀüYÃ+qøJ<ÛRÊyLx}I1SX#“bÔΗýiRR¯¼?_ê™rÄeM¥—1šÒð–Z»»ÚÎnžk¨S(PˆŒiIÇ®ÅL¶âh’Dzûî™A#à U…ð²˜qFK„‚€oÉÒ‡°j‹ù{I1ï%È–;XîÒ· "Œ²Í¢ ´Sˤ bž9^NC¶Öc.jËdÉ«U¿š¨6¯Áä‘êË× H³»± §V¶ªÛ]µ›J D¶ûÁ²ýZ6Ï™ íûq&qºIŒ!Ë€ Ml<X¼åÀj•”J¤Z9Þo Æ|¿×èÛëï/ÕK;ךwß·fÙ$¼³uÝÿÝ?î 3ª”ZÓ²t)G ZÊRp´á8‹{—T‚)…,%6ÀQ¿Ìø7ÓdŸb$)[; ,›üìóÚŽ`<Ã;´e) ™œ¦öNÇÄ×K‹JÄp Ò!&© µÓ.`øRLÉF•eRJÝeÅ0¾ñºˆÞÓï;©˥ýx¯ÔÂ$¬ !ù8c®»]-ÍYaË{¹FÀ²ó›R¹ÔH$h ·"²–MН ³GÇâÛi÷¤%#È”h$@S55q&Np7›e%–ÊyˆÁVk±úú(¬ ŽxR¡Z&®—Öb>51ãð,D»8¶Ët.Ûö Oïë^Bˆ³`::Š©u¤KUpq"^U:iÆQb©;ß³®P•ɉõh ‡¥ ÁnÖÆíá !¼LqjMŸ¦ìUw c Bª/Åëh*A— fHYâöÃ1SÜn;8±À•[í½uíôŠÖØz!ÞR­€)Œ,¸„AtñFˆé÷BRDÀ¶S‚D’åá:*Á‰ LVÊÅýDÿ þ">öyY쟡°\|,6KïZÛ Ü Rf`€mBàøU5³Bše©J…á½³"Sø¤ù·tü[òÁw±’­Á–¼H§.KAê³%Dß/ûÕŸHßÏ¿íWÀ ¬kàn³ehÝ–]V‚%bB"¤¼ ·»°e×ÙÝ%¾¿¶ª­¯Ú ºðáMèæéÕþN#èvJ\#è[Gʋ̮ ̶Óv­JIUbf¿Ê1ùö^ ‚©¯˜&PU»C°Ä©$f…¼¥¬ÂÚ•Uâ¨y&UP 2â7^4¾F1Óoæb„lÎì ¢JÌ‹cv,!ðjkÁ›\JðIKSjœ‰§Ö±ˆ+×]Ǫ B]à&q,n•8ùª\87^Ćlkp¹¥.d™8!Þ„tj“§Á4!Å”Z^œ)Φ ª )€³‘ÈÚ‘ŸvG{Š÷a×Q·;s:%­]7†€R˜šŠeiA[phh¼Z&Æ—B«’â를ÀAèÀ©[ùzÝ©;!5H?›—Å!(ëO‚g™10Ó‹¦-U,Ð ÒlFÂ1†@¶-Gƒ#¿]¤AVÞMXÊ=ŒÆ&9Aqf)8c]f¤ô7žl°r>ÓT ñD:=K&v! v9ÄþÙ4ú¶M-Í1]>xjÀGë¢7ÞÄ JµMUp–Ÿ`Rðd/âyúªŠ#f4ÍÉû(Ÿ²“i<Ùé¤_*>¦ÚKé¸RYñLˆ%›æªJ5•atq†”myUh ØÀh@Ì DÊ´†) lùÉÖpR ‡«dqK¾ fÇ%Š5%Ó±”j)žAX…¸ØðªÒ‡,Ùª’§”¥rÝí]Ühçý•¨µƒ‡6¥Ã‚XJ Ÿ ])"ð¤-5À©¥e±å RÇ‘Å8Å8L“¸ç„g¥š'>ÄH̲¬Â\¬(&xï"®EÁQ¹~ bk)´ýÅ'ÆðÅj;U–‰˜‰utŒ1Å ß Yò#+$˜¯¯P )ÞG.Ÿã}%žÂç{?zg~¡¨Ütù¼>¶)K½´°ôØðû¢4 kà&)އï„#4³×bú}ô{`ýýà__",Y¾yR¶l G„Cp—À²ñòªâ$U•ß{y{äe l¶n0]ô]k³9C33 ,fÛ†¸^’Ľ·§ýŽ–œ& ·AˆT3µÓ¨Z ¤Á"ÀŸû þæƒÌ£©16˜˜ to§{ŠÌdzëBm'Övº ï5 ¤vôÛ/O‡‚ÂÓþ‹•´ä‹áYj|»àÅ¥H‰É2AµZ ¼oPaWP-ˆ H©J˜ 2Z›ÅA¨KZ%@v[6á•<.¾€ ¿óïèj”‚ÜÇkN¸ÛRªB+…¦ÐU“5v"y©¶£8BA{ÜYm6LV–ˆXÕ‚+y§åb4f*ˆq&À,eÝà!²‚éÄWžI­ÖJÆŒÿïµÚI¦ï¦ÕWG½˜+ÞýoTŸuÖÚäÅȲRpqÛ±;~R@):qÄíZšÖºH¡ñh^jú#å3ÁËŸ$˦ÉC6•Oÿ‰Px¿ù+m^6ÍCÓ0|‡1³ùµæÍÐÆy±¾NÞȬ²vKДm¡˜OùÕ€ReyµZS³¤¼ ·ÚšZÊj¡¤+"ˆ£V•„‹ ¨Qîu“Á5U"®°Ž.\²g²kr¾ 0úýB jFj~U±Ô:ŸÊùR8ªŠ;FÞ2}4[pÏL›&ý¤tÄLbkU«œaªRÛTui¤ê…d |•>î8„O¡Ý5X ¤à˜uZ¿c\w´¤,•3KÞÄk-àËLBö°¯£ç™T£–ÍC†“BKÇù4¿\zÇA:™m“,œ—"^-îAc é—pÂS8]°›5RźºŠT Í ‚ãðfµtpÈ5೪à17½*Öö”£…ð+Àùªv]Uu:pY3gºà¸SU¹ád1õµl!iVØÀš 8Îkš¦Ž²Í€Œ&HßHÝRøÈfƒàÐb28«£Ô6bþ@ÞE‰OÖþùÏúQ®OÕÀkþróBì×lš¶1ÄÌ`Mh`Ö®tá!¼Á Ù¹™_m1šÏý¾lø—4b¾1do Tç€|Íòx6Csâ´n¼J¬y  ᤠæñWÞãǦ ìÌuiå‚¡{à P¼aÐÚ‚¬òn‰nZ)ˆWj]}RâN£˜Ž}!´÷Mn °z…à‰¿úï&táj¡K¯Kó˜³ÓÐ] åýÞ¡ø)#"€ ·Í*Èàô™%O¢¤S…t8úÆÏ+‰<)ASÅ—·‡95ËOZUR ª²tuÄ6RJlw¦²ʺ^KÉ2:—M¹?;ˆT~|Áø¦\W§û¨DR®V•eÊÆ`6k˜ôËêžx%8mpUÍY¦%ÍÈm 3©¥,YK²r4VaC"Äçã”jþ{L*M`Ìž±}™)<¾^(xH#%µØ’¥óÜ_þÑ¢À®M¨‹14òüŠ!–ƒ š6šB ”Ox³ñb @6¦˜¸k* œq"d¯*8Þ"eéÃ1›Èdá<“zúøMTSQ6ŒoG&g:úˆÉÃÍ`GbÁb* iÂÆ»ûh|"|gÞ±x'¸Ï …¸ª¤´“RË0¥úDM*\@¿µ±Ž†@A@¹1>MÖ%èʦÃ7ƒ*1Žlµ‚&¤§زÁÄjó|ž”*A£FŠ6¾eGÉ^m„{´d²M¢ ²Á(_”ƒ°–»å.íÇñÙ¨ô-B…‰´÷¶±fN²ÈðÎVLÍcÅ‹™TAã%¨Jï"hU¥,F¨p»X¹Ô}Ú»ÚãP£@Ç"VÕ—/hžáÇt¤ñ¥ZÂk4WR!A¦£Ð0çïM;2gZýîK;¬ARQL®:b1¼sQ‚†€Æ,¥´Ø³ayÆy¹ã»œ2%žš€”ZƒÑqÿyè Õ+fCòI X÷DW Ÿ”ÄY @½ ÓT ‰\Ó ¶)K4˶cÙ‰AtT!è%¥\lT‚Æ·£z©JM-7†ñtÌcn§8‰GŽæ•Ôò}¤ë;®.?Ê|4gŽÔ_Pó‹ì^[Ö¢!-Ì<@;2CÓ6U±”rÞë¬;Šÿœ‘¨ù³?øw}Õ^—YnËpctËIlÞÒ‚•wò.½óà<ñßõbþ^5}¢½kg*½¤ÂÅÍ‘jH“DØ1 €Jàv¤Êý#`mSV¬BAcvš <3)Ù@>äç?ÿy‚‰¼ÓûdCagžÚ†1†TYݯa®aÜ!¾BàûàÛçd"†DƒìÜ,3Y‡C¨%Ï£µßFz5 BȲÖx»yȦ¾¥`W°ò¥Ú¬kÁRŠuc¨5ÍÆ¶„cnàpUhRå,™ÀR •!Ðä-#ÞŲjz‰˜bU½È4C³o‰$k¹."µOV g#(a²Z´ F1ÛæÆK0`dó-”Cv8ã/Ài;]qÖÇnƒ)ï>ú]ÿQøôèÆ;QÓ×N÷ÎÁÍï³µÐx@#DÆ49ïEÏœÛlc»Cˆ4yµ<2 ”íµÂŸ» ÈQå‰+¥²W~’¯ßª|SÕ±SJ„g Ÿû;“~aÒêÀ¾Og’ˆZ&õCÎZH¥†éx#ë… …¥ùk$€à˜Þe­á2´ð-™r]j7Y©Êá²ÊÑšê;“04g+…V/ž5&N/ž”*A3¸IBŒx|)qˆ€!l0q`ó×QV0Ž]$ÅÈFPŽ ‰oãvçHÅáÈnlLjJÐÄ‘qtOÞbW+hN‚ÉC(ˆY…–C*Ïk*KS¶ñt—ê0Cwç‡7|]Ô*$ÂL²^–p¦„¡Å„4p^ ¯×Þð@4…çß‘VÌwõ„H“k‰m¬#ȆO±G@f"z»oX´©)'’«JN-TÁÍíS eY|&ÅêR,¥ >°i ”åÅðbRÞÿH¿Ü͉^`;˜bÛA`3 >DÕ•œUÃ$'‚X¡ÏCuW+u™ÌÖ25>sßø£¸ýiÀç|æNùî=<ÌGCœ°wÉŽ0 ™·4†¥ÖÆò¶©ÜóÆÌyW~#örì«KŒ–lʵÓ ]Kq4ãuøhJ¤Ðšga)ÿ±ÏïÉ—ò•ÉY颗s¨‘¸Ë$0ܱÃxM++V%h¼Ææ!DÚ²Ôd¥ªS B™~±T-DZòéäý>÷ ð)æ›[¯¹p945¿˜m0±íè®#/F3³Q™¥[ÝJQhûjá]S¸K†/`Jº¦-©iÁ3 Ž ¼=VµxÁ‘»½‘(±¤°^1çGn¸’²‚¶iIAÌð-1- F¼[Ú-í"ÀAh±lí:OM—E¨ ~µúî£L:“ºO(U#% Cï†XšZSn c™AÜò"ží§,ˆ …ØRÀê2Q^íÝ_ÜãjÄw¹ã¯„r»‹O¡—î"©–j¬¯Z]ÍæUùß­ `>Åü`…5Œ^4ÍÓ€^®»aj-v¶=•´7°r1ß1ÆÉ;ùÎÄRÀèô¥‹÷%ž}”,AˆÀ9LS³œ=ý@ŒDÜv-p,æ4† µîJÙ¸A ;,7Uûµ,žæF(«œf/×bURS†L9Ð<ÝÏKU¸Ž‚®¦šZ²Æ®$Y:–8-1‰‹Íc³m‚“uªàL'C™!@øÔtD_ÍçY÷šÂ©)9~…æ±9ZˆRµôjÜümyR©U.fM»¾ðÚM¼œÃíîx|ÍèÁ‘Ý0Æ0ä#Õ„-Ý3ÊéHéÈc €Œ¦%«B¼ÁÔŠá‘#`2)4 ÄLªªtÄdã0£mìRJ¥£Ê±”ªæ‡ xr(D(X;)¶6s[À·J=>:£ºELÉ‹Ò u±T=.ÖÃÉ ˆò8mþô¿&@è&–2Ch,Ë vÊÙí3~Ç„\P\yoœ)of4óã'hÉÄF"îÄëŽÉà|-T!\ðk:2êØ•3a½€hȵã!UIa2“'HD 'ѳv›xK…Ôò~ŠóÍ7ßx0übê_}~´s¯~¡È,¡3èÕÑò˾i(´/ïˆþC²fô¼Í[Ú¯¥ K¯Ä’u†p‹Ì€–WòdµSÂKY>÷—Èö7•mDG- ìº>çõ…9Oû•Å1X#ñb¸wß*· KˆY%mÂ6.k©0fq`qž¾`1‘pË»Qk‰£¤X€ÌFÊ?+bfý*Q‹_I"÷rÒÖÚWŪ⬗ ‹y÷áÍSkÙ{9ÐaÇŒVSx‡¿¥¬©Ð:„È–hp×+œ¯i –ô×´îC.N<…¦;D;ÈKLÙÄ¡Aúä×ÉC CÁ¾â¨Eóóò'~C¦ì§ÝÍS#§¤©ñ¤X1B÷9ÜT&1'Âbæá¬T_žñíˆ8ÛÖ0á}ètb»Ž:ªM„šB±@…3ålËwNþ믿&ÒMy3k-룛9Më;‰‘º@<«u*s"¨šÂEß4[ªb–(®Í–b~ÁO­%Nƒ¦à%Àµ÷}Î'N?3î¦Ðtë×ËIÕ«áùu·Ç¶.²iF3@3¤ÐH[Fã ¦LªËL¹*AU<2y%†ÖQy]TuEâ'RyäpUéTžš³úöÛoý^ŠÏñÌ#ö3{Bµ&ô¹ß¯ú¸ˆÝ]d;jÛow‘m„‰;R´!Ê&b³QI97`jØ?û&ëã/e'lx»k©î÷U;rš¤—wl/æô)¿Û»9ùf¦SÐ épàÄÑXðµ¸#÷ƒ’­$þsÿŸ_þÙU3@½Ú»ÞÉŽýv2pL)Ö’ÇÁ´eÞ±”í¾«uKËö˜C:8©ø]ô΄¯…@vã5ä–²” ÂYâ–¤,egJªºˆ—Ý;§˜šQ]hµâôy„6bž{S½ªBÀW…P<‘ö"Ë6-fMó8L6šž5 D ¢»ãÅôÁN//³ðÌOš! Ÿw™ü!aú #¦#v?›™>AOœZ#9 K`ƒAîí€6ÙÎŽr-¤pˆ0ú_£”óJŠëk¼–túé;©Óòº-ùçþŠ ßϤ߾z‰0›M̱‹{óEÚÞ-jãíEV 5KxG¡6µð¶Y¡Íö *Kaò5â#»²ŽÂ$k¨ãA„ç¾l:æ4‰! vŽþº ĬMõ7‚lÅ—²k"›ŠïšÊ6v¸%[¼í¼ÂãÈ’ ò!ÊYµcÆÑ”âx]/éöÅ€N­CN®$M[S…ƒéN×ËÐTÁ&öœÂUùS\ .¼ ­ö ë÷»Ü ºxB½ÿ6^â Vù↧£…¬Mñ Û”¥¬ íð,¾}‰+tuΉ¼œI%Ñpê›·LŸ&kû:)i{[–ÕB!k*)-€–tv‡@àhÄDFnK–§îÔºÖRø0~µ˜LœO$¤“¡)Î ²žkjƦ¬R „N@Êm° ëRê zÙ:vY dˆ4?D ©óg z¸3¤¡†ÓoB@V± AÍb… A 'œO§r½››‡h©ª;¦¦Nûç›[¯®º äÑòM®#q¿1,ÅMX9>ß@g”™TY82»('E–·´w³‘ ŠóŸÕjÇ·jZ::,Á3ÊíðÓQ"«ÊRv-à~=ÃßΔò3-¿fêµi­ÿýž]¸Ž]J›2oÚkO}ÙHH{:4÷'\ìm˜¬3çÅJø©E«qãÄÝf«;e›ºë#0HS¡1æƒWëâdÄËÚoU‚ ÍO¤À#K¡Ý6–âÈ1+X²Žº;!äýÞÞ} L\£^= ã@¼Íô4Á]q,´6’"ÈÔ¶qµÞÛŠ1-‰¸m¨a*xÔ¢ñ6Ûá µq´ʼn kÉ;¢p)ÁâNFUx…-S©Ëª€Ù¥ôpªØúŠqLnG$"÷¬‘œRô\TÞ¨õšàÚ%KŠ•Åìx £iID6¤ZÜÿ^œ!³|Ìýyÿ!ØããŽU¡»oòÌm åðõr¥ÄÃkÔÍ ÀY·6Á„¯²X 340¦S"•Hå¢Åܲp¢)1X½Bð£ õ'?ñ YjC¾3ð€0²ËšA‹-oƒ¶xv€‘»¬¶Ü´vÑÀ-ã@ð™l"æÑÐk7FQ"0|7ƒ’È®#Á2r]~ùË_ BÞïýÈ»’ûÄ öÕÖ ¿#ª¤GÛx|qo^]G›RØfÛ¸r³¡! ˜€rå£t2ãWrÎñ²KãÑ32¬6pâbµ÷)|>ßçþtÖËm ÄÄ·wïí‹ß¿:½|³ù,/°.‡1LXGMut¼&Ak`§Š_ ·¢Áﺈ0Y×aR)(„0AY1²%«¥Ù­+ÀÑ” ,£å)% ¤ƒã†q?›ªòÞ€éóÈ1S˜×zY²ðɱt†.„Z–P¬Q½€¥Ì/åºÐNxC`@´LmVkèÂI¤#-¥E[P(fÈCèål!øl)148ÝÕþä¯ý+HohUÓÄ¥d©0ÁÚXŠ/øñbj©ÊФJ‘jW¦©«%šÚî’¤ÎV®Ó4¥gÈ•ËBxå&fZÐð †È•4Zä qª¢ž) áuG`õЧ†–¦Bç+®VJ0N lF§À m°ÏýbÛ§ænë-D`™µÄ;ç Þ“ ‡«eÞG{5ùâ—’æÛ›Êãçõ%³µ^Ä]ë¦jïÆ@œƒBKAÓv2R–8ÄC(hû=QƒÉT9´ÃA†Àõ«_á¼=ù²ŸþΉÏζבûuì¹ .™KƒàƳ̺š]Þ5ru¤Ðºç];w;Ï"{ÿsÝ[Öˆ,ŽFÝ»m,3WŸ8œ'b©DЇ°ÅÝ3–È1Éš$Îh+IG ßüËKûtDf–b&KU˜ÌŽ€N@920NKÊ é#tÛìGP;±À2)'ï#»ç½ÏвÏ5[ðç`þ&޲‡Ô`æÜ‰™Ç0<\w»à‹›Óî:´ûA¹+½žhJR°Œ©K°F¦B뵫 ˜N%˜Z¨%å«Oü«®4ÿñènwÄu‡¯@Ü´qÞTRm?ï’Á•‡7yû‚u…8mÓ±ë…é鈯Q7sd{p´Ëœ Ŕ᪘7‹ÿ~Þÿ àßþö7¾-ðíK;-” o;RvßvÿÛ…í¨rùpº”@ñÝpè(w‰)°RªÍÖ‚GN–Î,e4&.ÀÁ\JlBíº4ô°4ü†–õæ(Ž)öŠçÇv ˜ø¿É»7<¿}Æ0›v!3³ÁÄZ‹e™§íH9yÞUÚá(äÓ0%š*HA4‚ÓÕlï.še„Ô𛄠À²S6md^ ¢JŒÉpj*¦ fñu0ˆ!oÙh¤¶ Œ¯„ƒHi±T´¦M¹ìô!Åzµ$è>0ä¼ZcØ——wqøMNÇÕ‘¥Óሔ]z%Ÿœ 'J?õ ’oc@B¬ qi¡‰`n W –GúbÚ€À4qøŽI­Ç€”µ‹~N³s·”­' S¹B­Û‚`â [ 6¼rj|¸TÃ[„¬Ø2š%ÙLÌ0™lÛ!.[Šæ–µK$¾ÔUz.¾”­ž°£K¡’ôÅøÚ±Të9÷¥îôÜÌK=ð•@þMf0¿"â¯Ö|üøÑ~×ËÇV×´É i¤®xÛ4† ¬¸MåÝRjmG!eÃ÷.u]t…R¼’ªx'@ È(„‡ 2©NCP‹N2¾Úçþ®Ë‡ì¥]tŒ±y²&¶qƒ‚+ñfï$˺Ê1 ?¾YÊÞ™@¡ …›ÚîÄ ƒÓ‡€§ ‘7ªyžøuˆš;ÄZh*Ðhrlòpˆ¶Y´ÌR­áš-UÐ!H‰ x¦ŠNÛdÓ´Äi™·Œ# 2ú¤€¤øb×…3±¥xsºˆ»sòºˆÉ ˆ¨’:Í®¯[þ˜Úkæ¿é»ú»&t•u÷ž ŒÇ:Šm¼}ïµhø]1Ž8T^~¨‘Ž¥ò þî!m™¬ª˜¼ÓÛャ[÷ª&«u¼ÝäÈ@#uwA,]¯d›6AÊÚQc8–¼XV¬pW® \ö”]…bÙº xíj‰V‹Úñ “¾ÙÄ©õšÐäf¦ÀÐpV¥¤ÍVB')Ì&á#×ßRl°J(³ŸüùÏöŸ P1A* .ÙÇå¬AB<-aG `¥”³˜ÉJYÚFZK9²”azfà‘!1hÈÌR{&ÒÙÁ!DTéÈÊÎCtÇéL[Ênò˜“µÄç3¸™‹Ó”%;Ü S3r² Ãí"šB n¿5âΡr¨œ·_¢11&ä-Ñx"º\ôs'YÊzBRó¢Zƒð8² 7["˜š7¿ÀüæQØ…›22œá@ˆ(a4™lU–¥Îö.KACFàáöeGÏ}'«ûÿYïœÿô§?¹ ÎÖñ;pˆÓó»:]Tà@v9Xx4WS M@îý§ÛH_ÜÅ•EìBCÔŠ½p1A·ÎÈJà|7Oðh ŠvûÑi0 ÃI³q¸BAÊ‚¡çhÝ#—ÞM¡*"dÅR–<…&WØ„p2%¬XJ šÖßþ÷ãC)àÛÖýâ<åý…øþZˆOvAÙIšÐlÝÑoÇŽ³Àã´ßÞ¥zê,mͲýVK¤¥^3;71CèH]ƒ%åKK×K„¯L˜O1? ùæ›oì¥;Êíd Sµ–mÄ$®Z§ÔØhÂ…Z¼]‹™X-}1A¿b)¦Äî\¦;©ðûJD!AVw ~ê‰âO ý™amu颸j]2ßÛ!íEVwKÛ1Lf[°D¸vsŽ” €ß¡U.KV•]‹ÕÚiâ, 9Ü)"X#ñ+§Y,[UçÙîÄ6HG‰ÐìÝ̲¾?»zd&þ™AÉëå…ÑåþÌÚW4{ô/òù0Ò¾BŠùmŠ ì¢v€e•Ø lGg‰&…)‚ˆ—½”/hLŠÁcžÞ—ד ¨•Ê«KÄ’¥ ìv˜ aÙ Cdáüôá–8<ƒ‹‰ˆ b¼É&Þ'"%pÖ$Y%@píé¼nò¶¦œº/HNÏ‹¬ÔisY4!¼^·^e¬éK£ÆÆKeÙ*G“5™,¾®áÔº0–Ù¥÷x«=N %N]x¸\£‚ž`ç¢ަ)°ÇU/ÅßEÖ®i-ï}ÉâoÚ¥Bòq’¥’O“~³A0³àL¬d|K»èÎh6K4…éþnéµCU7„¥3µ4·¬‘ÂÞ6)ó@4ˆ¾éx벤×ÇÍ'6 ߨ Ы…R¿BmûBX¯‰G(†_û8'¹Ó4Í€ ¡vâv!ÛFx1B›*?÷{ûÿlàMµîØ]çÐÉ».] )Çîþìb]\>ZVâípW“ŽKÖ³¤V!MËîÆÊáÔ¥wƒÐ!X­ÂŒ‡Ó)6’r B†#–FÀtÛÇ‘ºdÎÍÖÖôÇépTM§ªJÔZÊZâ#O?µF"˜2‘Ù ß–ÛÄÓ¯¯ø·¿Rƒ|Ò| ñ€pû4léZP`Ô>Yþ/Aÿˆ°«ãŸ0•³j <Ð.Õ²Ó›š¤ìˆg–8Ll;^;.Ÿ×R`®¯¥ácjÚ§)¥øÈ<…–p{´d µöI÷‰vÍ싎‰u)¾g`Öõå]Ž6ÛÀ•@0y`Ã[F0°*{çÛ&ÁîvWÙ!,‹Ð}› fU‚N£vMU/¸¯‘O<»+ˆ7ä¶f’º» ·4ˆ C¶Ížý¶ÓMåJv?´Û‘t4JG „ D — ñNµ#0<¤¥¸ NȨ™™Ûl-\Öí΄@Y1o0ú=nž»»à¿ŒmÙSà)¶):FjÌî´`¾Õkñ/G0¿F\‰¿¨mx‚RÄ#¶ýR["¨µ#ó0ˆ«Š)ÛQ¸@bâÍœ8Ÿ)1±óìò‰iÖ.&‚X _P/Kq×ZÐ<âëR‹†O$ñÈyH)¾oHú) Sƒ[2K]œIdžU“o ¸‚e æï@bò8²‘! *)–RR6)V¬€÷áòÿøG•®<“K/Å–áøáõ«*Mp)}wÃy)²wŽX RR‚RWÅ™¸€lš ãÂ;)`ÛªêÚC, VØ<µHRÀ—ŌϷ¯ñD"¹eL#ÕEw32sÌÎj!O'œˆ}¹Zm ÈbBjgÉà ï&[PŒ#p;ÒW®*Ä< òpK£¢ ”¤èe+  Áº(QÞéðDXK©^¾2 +¨Eµ¼^<0N10\I}e+ÔÚ ÃõÂøôï¥p‚ÿ Þynž?:vFªkÝ= viÊÂ]†Ù³Ù•ru€]&ä®//ÐKY2Ÿi(Àu ©»HÊRYÂñ‰çiÂy4ˆl|²âªšÁrj‡w-ï:ÈÉJuŽˆŽeS Ú ÑTRU{¡c‰œ8NÞ«*lì£òòêïÞö±Û?\ã§þµkª»÷vëW¶|ó³=³ýðÝ™ |=ðS|Ïæ?2^ŒÝïšGÌkÚË—X#íld¶—fhãmDšû¤cqVlH¨ª,² ^hu)›2ÏpxµÖx‚¯¾úŠ¿(Op>?™‡iY›@Ú,¤¬ÃHR8½<^;~%Ý…‰Ê#…4–Êv˜ºúúóxù¥”tá^† Ú¬–”YjÀ»•‚èË»]ºoâï³~S!tÄm¯ayK(g‹ëÒj³8Æ{¡?þ‹ÌÖ"… ÅlY†)®—CG L5B:#Ûë´mÞƒo Ÿ‚.5ƒ*ˆ˜OMŒœ]s=^È¢y@èáé2ÅQ›È–âtò²–À†@lSÖ0ÊðÑø:“f³‘jÚK“oZ|…óXȤ @ÀpÈÂí…£yɳ)ï%_üÿCXÓ>|ð3]ºL†é*C-yˆIlÇ`@sùÆæÑ^``L¦ ÈQUbvÁ§Ü6³."ZKA}Ñôõ&!øío›Âû½·ŸÆhΦÊCX‡€#à÷qÓ²“±G±Ál0Ð)aš–oÂvdé"¢ÙTA–­£¬="³Êy q.…f „à³å²ÀðJø@jI‰×X/³XÌ"¤ÓÌö¯ BgRh²¡Méi_8UÕš—òÝë|î¿4>íúy¿7ò4!wZ³VIP²¯ ®Úÿ¹™ÿ%¹ý¨Þ.hÚ”Ö]±Ë]ÓN[k&ێŽÙýN¡3Q%@0{#§)…¹³’B+§†´4ž_þ¹óÓùbï[–WÞ„ô5remÙ;¯/oY†Üظ „f~‚‡—™òpY]’jÙMè:ÖÈ)á4…îU͹r‚>›ÖQÉûÍÇVÿ¦ ¦_r÷ö­¯^@[örGÓ. /‹#àáyË=e½n8.&¦ kwFüqœ€^Rʬ *É,eÙRîžf6ðRúîìÅ&DñSâ86èGþo?³Ó,°)èA&ØHî q7’@›ªß.€Kåg þÏÖÆx%þÆÒSlZ_eÓÁ\P¯ÕÖ4oÉLÈÃI vÜ!Çq]Ò,l/@jâ²ù””ñ&PØ=WÈ,]n¤’:&%®¼êKJ „‡7’€Õ"©ÄÄŪ,Èé”å!ðLJPJ ¶rWS KgåWòqWï0ã×.ý‚6%ž‚Fõ­¶ÝW"7 M¢ÕhÆë!à»Õp:P—³µ "D`)à•Ph²Qèˆh êæn*­; 8f‡BA­1µX(¦__^ ÉÒÇÙH;âSÆd²R–‰@"Xlf™N#ál¶R|ï GÆQ§_@¼^²{ý*¥ ó“v¦¼ §—¤Èmͤٹ‘ÝK‰Š.\[Má+ÄlÈ>íí*àtʉÃkì=¾×#„hú÷vp/#ö úâÄ·…í}7¾`–ˆ¦SÇiÚh<“õǬ?êg-kúF@ù믿î™Ͳ“ÑNl< £Ðx%væn]w¯¤½ËvPåm$$YàÊ_i^MÎñ–½Ó¤ÔjÊô^îÃ"ý§˜w““Ò—·^w^_ 3ƒ€‡H™§Ý‰Ë6'$P¶ZËKæ»—3|G4@A(0xÐjæ–Ö”¥‰ ËWÃ3a)%YKYËfÜikD–Ž.SÃl)ÕHÔÃ(PiY%ÞcˆôáÁ©’Âo4·ôsS¿¬âÃ…ðz­¼gûÔÕ`uTk©µ£kš8œ~¯;7Ï~Øzˆríì—Ñ·´G­¹[,‚î‚ZÀ­ÔÔ,¥X3["ÛH…ðjSkGm ^ÀW›WbùÜßuéÅlÓÖ®ùÅ5m*óo¼Í#b‚FèÞ àpàNO Õ“XUíà®2KL†Y€è]q)‚Ï=_#ýÔ€¾FZF óXÐ$^¥ ˆßáM+Æd , "~Ź/+tÈ”{Ö‰`ŠY‚–l±@ ùަÉ3Y¦Qço0O´]øºîŸRå»]#¿í éÇöÌKœsÛA©¢¿y,»¸×Ž“b87/ö]ÂH]ˆ·XÖeòê§ ²u\B¹^ÓBºQwÛQÀy a L•¥ž”¥T‚–Ô,™*cÃcY rIžOêw‹ÐT©ñø¬Že-1ME³ìJJÅ$y{²¦šrq ¬Q+1¤,S•2‚eY s€O¿C6”Z~£&Õ¨íŽ Y uá!?ýýï_KÖâÒb-«ß(IÄGcuEc÷ò ¹²7D óRb©4³¶Ýi&Õͤ©¬ñx8ÙD“Rl©6¢£˜ŽÃ­‹‡P#}W 7L]€L´ QB -d‹y*!5Pa ˜Q¨{R]ŒÔ¨J2K&µÁ ÊnNv+·M/7˜d1SÈãÈjmi…,5 bxV|ÉNó_å|½ Æ?©ðe·,«|;¥“ÕÁÀ^vó=ï?~™Õ±ÐoxM›Y_Ætnb“xñj°8Í/²ñÛŽ%r õâáL‹LL™¥„(a‘)žøë ~·ÁO¤XuïØÅ†g‚û}¾Ó;|?^£z™ ±4¹ î4à&„³†ïäÕhyä.³Dî†t>jï%ÕvhøGýª¥†É7€ZK© ^.ú"úΣ¨Ü àE#qH¶} ¾º Ú‹'rŸöÌ©¤óÁÁ·Ì0«ª¤d²à™¥ÂJ PYÀÆYŒ,6“=¤ïÓ"HÑ”²,(ÛOÐ}›òÑŽÊ›æbùÜßÝ;Šº_ƒ)YL½œ§eM1qšªó©#?ެ _ Na².–Êu ü©:~ú8«Äx>¹Z¶¯g²8Ýh@ fßÃ\M ”ª~b÷/×ß~Jçs &¤ŸA¤pX{'o¾‡]V_d K?2TØNñ1“³~¡íð”ièEÖ’YæÍ ‘î–âžsÛÂfnr^m‚{Q…Ó®áj©ARÀÁd@Lßm¾øëM:woGþþ4å.Ÿ ìبÓºCümÎvÝlãX*¬–'e`^ŒÃ¶):Èùp© Wá]¯}ÃìèVˆ/FðQõ¹¿üã³l—OGúÆÓÒ•ê|xÃ#dh‡i6Óòpž3)ÛR|ÇÅñEzÈ0F’u‚‰(·äLÒyʦi’J€S% q_ùûûݲ‚³]k}ö|½<ŠÛ}1ý¦›¡1šMÊ2rH#êý—»ôǾ9º1ú~[GSçõê&l6 À¹¹ñœÉ8]-P`¶†¬¿ÓNÓÒK¢‹…Öý,륃ÎdßiHeh2…â14H%¼Ø ¬˜¦øEàqŒR]ÖZˆU‰YËž»b ±ªLìRÅüý¦7YjL6{Q:çÜÀ=;˜ÍWÂ3d^ŠG¶k x4P|:½|I@þéþð‡Ž¾®rÚðrÊh©TiÉàL†ÆŽäËÇÇúÅá-)Ë¢©wa®º3wLK±S£ ¿T¯à.¿òö#K¢*2åZÔ+Ma#ËfucJÅß½@S/B'‚Ô]¤î³ÕÁŽ,Yä8i6ü+‘:¢Áµ‹i* µÎ#yûŠSaó)…“+i›@³)§¬Q`xû²,¾% §V|pV†ì¸ ï”´ÞØíQÇf‹É‡PPž‚˜ÁÍL‡)‘ _M92PaG‘ %°¸;Ó ¨¿ñÿh»ÛäHŽ# Ã2ék”Œº tbÉ(Åsì“õ6|jÁ/ §7~#=<<"³ª \áCèÙÿø•ÿ·/[&cÄ7U8d»3XWóÚôÙµÉW^‰e[À#³M_ªÃ¬/&0š%KA'cÉFÜm…@ã°€²€² vk-q4^*DªW™î#Ô…&Ðc G´NÆ.ök»>¥Fˆÿ«ž¦«ÇT1KÝ[†ËB¤ù6è¶qÏ0ÙŽY!š‘¼gúÕ¾ú%"_Â5Âl;ö«£FºÜç±Á6.ÕøÍ¦¶×ÅOð¾5d7õ “QîŠtÆ3d¯â†AÀl€vg‰Ì#tòFr±ø¶)5<#ÑÝb|‚*”ò´K!(aõ tÅ«2qAYK5Fj̺CpšÁ)X²{»á‚fШB[p’Î.ë³Ã‡gí7²]»|ÈR`“à xã¸3ùÆs°ŸNL`ÈöN"†À ¯1» –fæ‘yˆò†W(hf1‚¥Âhµƒëµñ€² ­:óñÛøbšâLV…Èhvç&'Õ9“m:uiZg"ÕùÔBV‹(^ÇÀŽWL<&×Î{e§ÚuQXìc²JŒ,P…#î#€j-•ÐDkû;@”bbäf°\к°È]h1D‰¥¾b ÝfSE$°€ï¬˜R–ulxž&“ d•h$ ¬[³KÜR TU"@kÔÆÍI*ñ6HŠÉž4 Ò ^ã¦X±iª‡eU– A|Ÿ&ÁFéøÄ8‘1“5SA{¨iúíÇAÂ7-ÏdÑ,©Å OY*~4Ì<¯VªŽ¼1U¡%n)Nn‰ÆCxå cÉjç>Ž 9n%ż–Èâ«è8"M¬¼íì‚9A|  `?ñfKœ‡3UåMÒ0ÞŒB´ÖÇÀ–¤ZN¡ ­ ÄWÈ×N°Ip¢Š1e1‰T[®ê—Á4§²*À¤üËÚ§WÁ@Û¬ÓX/ÃëÕ¹ÃH'V#ÌΡåvÚä¼’¤Ä -~¹o¶Ãy·`ó(¼4ŽúQþ ½ÁOéÛfÝÝ3õ2ë ²!ÅÛŽexHGÀRë»Y"–áûèN£ô§SBîäÛ»%2MPÓZÜ=<«WG-V¯Åøki 8Ȫë"HgB”X6/Zû²Ù8|:p†Üu$ëËžwcüÆø­À/Xû-‹¶ODmc$Èk ×QÄçrìŽ]­c×Y‰WýouÿCÜϸëB9MM[ÓW|&{»í &ëÐxµ¦ ’b³MP‰,¼T^¹y¤µ¸ò—M±g“/~•7˜ßÑløNbrÚ¸mê%Æa÷ì4š$…m޼;¤Â@:‚|GÁ·wÁºG‹O­?Úùvóóý—›‰Ûˆðº·Act) ÎãÌø+[ý¾T5˜6Î(3Aó 4Þè©’â ;³9sqä¶`Ëj“Šü„7!…D´`D )0§]KuVð+Ž¢;à ‡0dßk0$|±ùÊeS€h§ÐMë?xÎÙ¯1|:p†{»ëTµœo &éá¢Ç ç \›ßî •Cl¤Bo;m\Ìð-mP|¯ŠL*ò´uûS•/üåWÁ¯ 6Œ.52•axíœC—^´ßNh_qÚµl„]På‹¿Ó’—U~&x{mVkY¡S¥¬–é7‰yNÁÛÝX‰lyd²¼»ÈMºš•|Ðû—¾Žˆ5V ‚ƒÕZœZB¯(æqŒm;í¨Â²lSI"Z«òlâ…>`rÛ'Þ0 ¬…³ ‘Åd–±CfKæ†á},Ò7öxÁǵä4»F†‡H‘âSw8‚»Õ]¡.b烆à@è“×%©Z‹×"„o`ž‚B hÊ#à7dåÈ‚6(Û­‚` µÝ{õ6ZRpÊiò ‡`xM_ÀpVE  ~,•7áùúФÇE>.DPEÑÝ=õpçm©9(¦ŽÐx#¶ÕdyVwTKLWØH™¤Fhä aøkŸIÕHašµ¨6þt #ÖY@ᬶش¥0©‰¤‚X!½8á)Ϋ%å:áOSÊ2e%¥Ð –YÖ'Oë #W3dµIñ½fÆq°UU®JIU¼¥¬’w—»Ë·9qBájï{9Šow FæG³ÔÐÜ]O|“Èïx?¨½¦8w“o¿&w?ó™í2Zšj-›œGë‰&o#º26²r"õ²vÔm ÙQÃ_eõÕÅÛãôMh_phL1“ºK"L ¹eÌ–pÙŽˆ«bpþT¾=--½¸RÀ,+pAã ¼ö—þûßÿ6¼ŽÄÙÚ‰¥Ä$–†i »ƒð§ÖSÖSý¨\Uø˜vé=îð5:ç²ÊIA²éK zO¬#Î ;"ËÓìí£4)_hžûŸdûiªÏS(Ô¢@ëÓòjj`í Ã0ÁöRÊ’¹ÁDIjb|1ïÕÑý’ïGˆ‰|ÖûÀSˆB…‚â cŒb¦6… 1oéAïFà–Ý«¦3U B½¬Š—R¸XÀ4ªéDp”Õòº¸1ÐX%˜KäøÅ<œ…—"WN¶û‡`·Z÷pLˆGñ@ˆ á@Âù•ÈŠ‰·H[×:„WÈâX 2´û¸½„çzk­]žHK¬F„«×yOOÎÅo«Avs LohLž¾¬BæÚ7"œÁ[ :;µÚÕQ†Ó<¤6Bµ|±›æ‘x;;ÁDp*Ô(2Ä0•Š,e ŒV <¢o÷Çz%ŽiH±ÁíH,h#ÉâEÐ÷>å˜ ³©( Éðâ ÝUh-UÅ!ÂК?\ h…³Xêâ>Î0Є8Ä«ÆoZL6œˆXG–¾W… jA'2ßj¡D\•”`#•VU_;e5M$üµ_Ú5e>–ð1‰.æ·tëÏ’ 9 b*~`»æ…g‚vÉgøjÛ&ZÇGGA€¼³áLp]Dï&?ûg(ùUßöµKŸ7†Œçñ½«d–˜µ8âRJ|R.h 7FZ|)‡“T¯ >ÁN©ZU‚Fê¸ Ì -£af- *¾ååñ_ ›N'ÀoH½*G°œþbˆlL±‰‡ø5Á–ýCï×~üð]-ÓÝxL`Ô6×âšýÿuSñ‚^Ñ”¬oå}1NSê‰Ï'èõÒåƒ8%ÝK5yËÆ€ õ-n6àî…bªÂY°íˆeÑ =d N{_§›ä[¼_þñp°/"&\kK—CkÓÛ8Â8Íf‰ps–”BÖ`Mn©¤×‚K×Hy NÍeD0™U#-&€¼Zïb_x þ¥1Oú‚z5@ã9˺C0;«ö‡49„!TÂgújq ª ª…XŠ›$Âý d-ãø׃¢]lŒÚY†8.ÿ+î'^w¾;rᦀµÁâÚ½›¼eDàñ ¬Và fs{X&ŽßiCº¦*AߊLíS¦~÷É´PønÚæìF5ò.½¯ IÁ‹«Ð 4[æ©URÖ. b^Úgøªˆg Û²HRb&¥V ¯V¶€—ª|‚U¹š‚¤ZP«’BîéçV±”m~KG!EG*e„˜–ÖHÈ8wDÜlp‚D¨W+ ï4kaõʣɿ¾=µHZB=ƒÔ^å´´dÈW´³èÔ uÂWU›£u]6YPJžŽr`Èá½õµ7w†lƒ…W•,¼‹!Õ Æ$%ÀdRµ a²xY ÚKfÌ+ÍÌÉF–ÂIDaË8âõà³ 8I)7mµëØÀª&¬œÏšALµì,ã;R}™¾}(AÃéZ´Óø1SÌܴ'UÖR6UÊw퀆GKóªx¼Ì¤˜.í¯ú!¥ð B L!)íèýÛ¿O¼ÐÌႎ¢Së¨{»F0UãA§ñ¶Dˆif:ð†,(•·Ad8Y~6~´–wo‰ÿÚÑOóS&Þ…³¬Ý®¬¥­™­‘Ú£½T·©®]gÁÌK%(Ë<7»µsòé 0‚øÊ–œªÒw?ÈBò‚wÖÍs‰lY)¶^ë²,¤¢UNÙÒThLŒÖH@üÞ^ÃýÔûãïGþë_ÿòf±û&q'Óö;Lœp“Ô·‘ÄL–¿†z|©‹Ü+±¤gw~jŸòƽ¯£°$bòeñp›ŠÓBðY·Sͨ̚8¾A¶GH†”òÄc/üÞØ]Ú Æî`ßÚ>ž½­íØ‹Ée Œ,œo#]Ðt¶£e½Tõúj³—ÌãÝ@3$H­^t’­B¸;ð#ÿÜ|›úýÀøTX#Ò=Ó$õjZ @éXd{ºÂqlBÄÌ‚ÈÕ¦ÖÐâótȉ/e)îdàÔªBŽÓZ˜Áû°ÆæÙZ4 rîOý(÷ÊýñÇ7†I˜¥v²&yô¸þS_„ÆÞäù6{‰—šãe½ˆDlS¯ÀzÅÞßy¯ÝG[tÿ7‰î‚L ú¯ k$БÉvò)᥆T Œ,ÅîLqGÔö-™^–jño=žx)£™Pê~¼ÍC~W•`G§ß÷o«üÒ¿ÃÑ‹Ñ!k’õº´Ï+BÐü|Q"¾J¯åR[æÛ5Kf/@-°²]Œ&…l)ÀÜñ>Z~ø?î"?möɶ³©hJ™¼C®Ñº »-Ë"31~YH³]É£&å|€h,|}m'D/¶òøúBãpÄûvI­a5•*PµéW$’¸W\‚¶&«†{û<ÈÄ›ŠW’IUE°yà‚šò8ЪK±´M;:^ÜTú"·ëosv¹+‡tÑžf‡ã½»/BD€Rk€Ú‰•ðzu) Ä:¾D ^e}ÀÓœµ«5ßi·4j· ÒÓ Cóu¨,ÁtÐ(Ò—|d hð|üÎ32‡g"u´ðR–•„$aR,r,q›*›,­Ë" d=£Ì ‘â…bUÉ‘yˆRh>øÿøO«Ü_¾|IÜ“HÃ숶5úµ«¯X_ñlY bgh1ù6"î <…Fõ=¤sH¹vÊ-ÅFë"€ÚïrK b" °yK¥ðRbå-“ò—Ó¿Ä|4`kúj¡‘=êØŽ /Ö+NÓ"[²¶Ök\Jmw¾À2ZÃßwAÍýFY*&)1¼µ3…ô‘ST2ïûψ?“ЯJjÇÒ0]Ê&l61‚X`×Í`*%ޱshƒÊíQ–%«=‡x]tËzÅQÈ–ÃWR-M¦ È7-޳… êU oéÕêw¥ŒGá³æáëHšjé³»ˆÍàÅ7õƒsM73äÎOD6å WKyËDÓ×c#Øp®Üö=^žþßOݽ LÒ0 ©u›%Ñ]Pli/Èæðbƒ5’Kñ´é¤H‰¤ÔZ"x†ÀÒ)k©‘Ô)Õ³$Å®üÿáÛ4/®GñçÿÓOÔù¢®)AC®»àἜ{ìXÞoKœf¶eå•t]Ó8âRt˜éȺñ àØ_øË?.ŠÿëèýãÚáë¯{h~A»h6SYn¶À§Ó’N7Oóã3 ,µR ^£¤ðÕëÕ›WG'Vè@žû0»vï¼×‘Ñlô¤F:6¹¦ª:ówÛ²hdUq€¦õæ '„P¹€)»-§,Õlhï†,E³C’m`ge \V9}æÎyîÏ*òoÄûŒœN#ñ²™¥ôš„ét½×–)T•DÉÊ]ˆ ÎЦÚW—Í d¾F–O›¿ƒÔvøûº²K&fÑ4rþ Òüž .ôÆ#b jyåMk©M¬–Î:Þ) ”Ñàh߲Ʃ’l)þB­’t*MÐI6¹ïüö¸¬€‘ªQ—› ¥X`Œ&Ça²Yd»cbF AÐxüÄ$¨¤lVkI!(y¼\¡¦×¾'©%S)žWS,%6(OË夰C¸áªRÒ²NM/#Ø4²<³ÄD0.O„&2œ!lŽ*KM] K´M›>N©«úQŽn0÷\±Zj¥Ò©¤˜†C°»V __[P…`$ƒA⯑*râ)¨bø•”â4óðq;šôûnUl`x%q ‘¢&pÚ­ßÉÞ—L¯¾&=×eK>(à·ÇVEDÐØ¥œ»"5²v¯ý+õõ ŸF¾±»‚NÙˆc 1&P­9áâ.¨×‚ìöRÕ–é[Vî–ChƒÖ=}¾^%£•u2¯ý.hä>kæwÞfÝ<Kól°‚ŽBÖF&"è|€¶ÓU¡Á1ÅNgH"ÖzKA²¼sS¸913©@ÙÅ eIñ©á<_ÿºÜfëâVÈg• *¯J9r‚8@çciÌÛ¶Ùþ0ð,ýïõ7U4"E8kZ ÙØ@™7CË&ä!öÂ+É7Fd1>Ü2ò·üÅLoìlß&LSà<)›Áv´@Ę|41G\‰Áš\ kÚfÞ­óïXjñÚ㢘P#ÖqébÂŽÚ$vÑ`b¸¥QÅhó=F( 0‚hÅhâ&G#Å(”M?)1ƒó5ÍË:„ x)"ÍüÜ_°!û«æ÷[ôòr­µ`z9Kí̦ as”2˜l[K¼-w â@"d‰38 ®c ¸A̤¹F;Ï ŽB3”Š3Ü’!¸sžø¿eÑÔË·îÆk›–Ôh–âáöt²ök$qÃÃq¶ñÙÉÛÖ®éN-ZRñA®µP},-@+‘ ¯ý'Œˆçƒ7Dh6x[0¼CÔK¦_Š‚í›Í jÚŽ4÷U©M¨3‚%åÄ1áb>¦á#åi¦†ß|q^—¥¡ÊRšÚÐÏRÜ]í4B“ˆÕòuQØ%(k)U¯Â(382в](aÉÖÁÒ0||œÈâÇ·V½ê¬mŒÇncä”]ó<\õ8b!˜{ÙKEhÜh|íñivÁôöà;)`ìºú¢HA(¤Œ¦¤oɇ·á&„0)µ”›0Ï È”M´RpÙÆž~RùÑJ5F¤²–ô{G+P›f½š­c¡€ŒV#L)U™¸e-€–㬅ÚÊ]âm§v–øÊ”+éØÓIêô¸¬eþ’ÐäÛNS X[Æ· ¯@/‡!‰Ø¤-¨j×.¼¦®;pgU•‚x]ˆˆË~êe%¿ã}üߣ­º˜GÜг†ì¢¼aÿ¶‹ûÖ# ¿]·}¸@nw틇tÛkZ•B‡¯ÞC iN¾³°í1Ó›~}eÕ*ì>_—}ˆB⌎K)˜ø]32~²ºï¿ÿþã¿ö£ÊÇçÞhî6;ê—Ñ÷ßk¢Ç$ÄÛˆv‚ãX²R&·ÇÀ–b²Å–¯¬§Ð-Ô"%pžÆÐ…xf ïjjýŸg»ç¼ã5j‡,+æ•PÛ—  ³AžÎµ:»{iàLüƒþ]Ûµc7€.|²íŠÛª%¿Û#>ƒÛWœæwlUZèµLsÛY šÔR8“LŒLÍ _{ ~߸Q‹î†Ì :Bš|[3Ž!ó ß‘";ËtÚ…rcï4¤êIˆ˜ïˆHm×8)4L³ÕGc=j˜Ž¿öó©×,åŒà—/_ìÂRSÊ|©{€fi}Ýð^nšên›|U"[ŠÃÕm­Ø¸%#ÂpvgYƒQPe¹yü¬÷|ð}~U:jG¹óìùI3”…àˆñ}©µk;Þý­wzÕÒ—í šY¹%ЦÊÛW ܲ’˜ SŽ&WÅG_P ©È‰ÛQ›º—Ä̈½»-íB —€,M±«ìˆ6€¼zž×HûRK_ìòQ+N³S¢SIÙîg–_|aWÇá[S©¥ânÇM”7*«X)æ[Bˆ´%¬áhbœt¶[ËÎHª*Þ$×h:­Q‰tÛ¥™ $ÁY»ù,Ųœì IYºoÌ/@€T+®„`²e t”P—®‡ie+A I¹¥-#ÌÚïŽGJU%bR©‰ A ?‚˜Ev}eY½hM“H‡™f-à„HYfø‚Óã­Kø8S@@¶Ä)Ň ˜yx³Q`È÷i{©|ü_R^’r~n늠nNCVÙÀF2'3•hÔ]\L©˜ÎY€“ÚµÇýVYŒÉ[jͨѬšw-’Åœ¦¬ ?ý{œ:¾3-üÞ*ßÔN£ÙR³ñ],S lBLÓ¶ä™Ýé·_-ªíj$+à;yLqÝ‘p½˜c ÏOÖ­v:fkw¦¿/afœ8K¨…,ý¼IÚfèBö5Ò¿¶4j…ñ~¡Â_ül§ôÓQH¹rú&iNçÖÌõåÍÓ8Ì0üìäíxÔh:ßò["¾…îŽõŒ5s'£{3˜YÜ^BÍ•ãˆe ¡*c0Û âSÃ4  „K¡ëB[ÚE!y…z!¨Õ%ý&ï^E°d¼%}Ÿ)±ä-eÑ´ŸÇkQìF®GHÅßI“ë&3¢Oºû²Æ AÊ2qqˆ,…pžÄ)eÛ‚عc&ˆOÊr§“8\ÀgñïƒÉº )û˸8&i$WÂã‰Õ ŽÙ.xLKvʆ49PLs¸^†ôh #1YÖëÓR ¯»Ú6n)uoZ¬,%›(ÖKÐ0²{é®QU8|&UÓ{SYŠ)Y ÙÀðâJp0mdüÈ+3Kf±)$îÄàfóË?!kôí/ðž•5Õ¢1Î4×iЗÒTª^p³Ù‹‘œ<œ™ ¤’BÃQ¯PvAµ8mGÀdq”˶„Á!·|í/AùŠÞÝZw;‰ cŒÆnžÎ²ùËšSÕ¦ øºHDÜ™xe™€ÕKJ\• zõÕ®£Ó¢›GÖråJªj 4…†<Òo‚ZŠv¥Ju Ĭ * o¼vl­ Ü’šÍRJ¡÷Пý·>;÷î¿-ëË®ñÛr¿ñ´;ã^7'V¹ø”]…éð¼*&‹ÜIÊ66Pêéoüóq·¬Ž®¾i‰7†vôe¼ØU0óJÚ¯y ;g·×934-”Ë2)ÿâBá«ÌﺜßôÉŠ'®{„/°4O|^lTÁ’˜¯êþì ˆH±ÈZÊVKP*ЙôÕ¤ÛÒyþÏKÿÒ?þ¨Kc4¡ëné騻yøæÑÝÒœø†ïE iÚFÊÔº²Å¤$ý²Èð$Ð<Ù=FšV šê(@Ëûµ§Çù¬õî?) Z@ˆhÚbA²!5u™Œ®ª!¯ ÓDhÉË:‰¤œxd§“&}Ç!®"®ãÓÞOHƒšF®>Û[‹fÓK_ e4K÷¹UÃÍ ÖltdÞ×âûÀ²¥ðJâó‹Ûš%Rí1ýŽBGq`ðø<2ïZìr$¢Z]Ä‚ºwøjMkGŠÕrO«Ýx‚qÕÆI¨£Cæ/á¯÷³/|AR=\ÌæÙá“ïFz•7†o¸Ó6Uï6:–w—ÆÀ oB)%–íÈÀ@fYŒŒÐí*ÖÅRÇuqŸKAÄWÝ)Œ X-¥‰óÚèSvY¯0j/LeÁ›§¶ iGy…‚Îjü@Ït m¢ |”¦sµÖQ€£„xµ1‹fÉÄDÚ d»R¥šML¡ Ž&`pæ‹´8!–åÉJ•M?2B š“/0¿=üÙ_ÍòOýÊÍ Üöéw? ÒØm9·Ù3èÛÃV ªiÅÊ-•óJxˆŽb'À”øœ8Y„O™ç§ÿïµ»Öé8m-:XMb Ì&³3¼á;bU‚lL:u‡ö/¿¿Í¾1Æ¡_»ü»*};@ø‚w¸ Ü£Œ`H4²Y©§'€@±*D0LÞ!Wè0!¯=W¹á){ÁºpWçÇZ3)&hTÞÒ €iÚ­íË„‚æ`Ú¸ëNY g„ r"÷í#ÔEŠUµZ}‘„¬€Zƒ ð•ýyû§¿G²¯~øZ3ëhBíšS/{¬Q9[z{‚I¡ÁØÁ–º ¤}%ØÄíB¶  †ÇééêµI°ý¦ŒCó[ÌfmœŽF”uìxÝ@­c1N4G¤J Z/|µ†ifÞÅÊ;OHÓ&+Ë(ÈBvò8ºð@„bK( w»*”B€‹§‰€æ<¥TåŠ-1‹ Œi)¨JÜ®G«)¯Dß!Ç·db…LCæ»g¤âT.e)FF@tÇO\вòúvæÈ3"uá¿”"E%DEœ×Iªø.Ôê¦ ¦ ò] ˆSãJRæÓAnW<¤‘”¸Étš½N\uU nržaÎ_ÀWG-r¾„S¶¤é›ZïQœ ÜšÚEB#ËZ¦¦]j÷ È:RK]R§ÉkÚ´1,•h! Ÿf \­˜]Úlj›Gšoó€‚ôզܲ¸ã5!)H-x«oHL:) $^£!‚;Í<8Ó,ÐHÊ’U+ˆ,ñÏ?û º?¤èº¦ÝµèÞ0$M;bÆ«{ˆ¦È÷ÝÁ γðbâjÛ¦tqQ”8·§sÆÇät¨Uл^†MÇhÙ‘¢YRàï±%žš*HçÐiw\¶”EëE$f =!/½'ç•mêÅÛ‚€x´ÖE`¶¼€if)Õ¼˲UU(–BÆI¿Z¸­‰•D(P…Æ3ÏRq§‘m…†AH ­BL;â«En¶u3U̼Ú&‡Ô(‘¶ œBк(Õ/½s8p4÷$¦Ô@IDAT…Ú$ðÙ.*A'Û+kÌ‘!u9“›Øz^ÂÑðl¸€5"&KK¿–<>P{L8éRÍ*0ZäKõ´Îd½ýóþ• ²z·2‚ÞÙÕ¢³Ö´ÝÇyg1‰¼õ|Ü Û÷bGÓœ”«ªcq‡“‡ô44$NÒWÞI"¬£©m?Äxø,¤îcÆ‘BkršÅ‚z ”+l§ÈqÌЫ]Ö2š5 oZ/iÙ8ÙÚñÅüð»‚rËš"›¡1*S0ÁÀ–4w³*—…#ÎkÿaŸí0·™·¿ziÔåæÅ>5˜ÄHÛNòö’H¾”,ƒŒIAœx7³+âNKŸæÎpú8nHgÂè0©ÏþzÉ}È_½Ë®…iM(¯Œ°¾K4¼ÙlèEÑq˜ ÊòŬ½¤† á#ð;C„bžT-œ†.Ñ.±óLO Ί•tàÍPНg–²D”XæÍfN^¶^µ&˜¡¥Y!Ów§6^ëz÷§Ÿ~"¥—ZÏ@:fÓ¦Ü$›Ö’éß^ȵSË6[µ8ôy‡lG!ñ-ñN(Ïz¿ýìÛ˜vÑåHßvÌ©‹IÜQRâ×àÇ9äû¶l dYL)#á«Å¶/P6ÁÔ"ˆ¥^û÷vú6†Àxu4ƒ°³Ë¤,Kµýâ<Š  òÌ‘² '°Í¦<ÍZ #×‘Ž˜Çw’"˜“¿öO!u :ÒwÉjaiþv¤õb¨"7X—¸áÛ ¦ØØqâ·‹Êóõ²/K¦PÌÆ’‚#²¤fYVÐ †Þ p_Sžþ‘²[ÔgÿÍÐ…Ó´×B£^ku·£Lëkö3->Ãä)„X²v2æE?[†ØÑ^ËøÀ¾‚ÃÛ]"8÷iËÔ>øþÙ?`HÓäôçâ’ÕÅ™ˆSs\‚&4[& Q%«œw!ómaóS¦l/JHYúÙK©ÿ;L¿üÓ3ÙZc6@±¥¦íq—c„8²%š˜)ä]V{7¶kJ‚Ï v¤¤ª–8¥€˜<¤X@¼‘¤Šº¦Žôwöø©”Ÿ”:T;…µæÅ6"hú23wõí´ „)0ÃO(ÈàækÔÛYRL!Ÿ²ZA­‰*1Z%˜¥ lLðG—KþÓΖýà®Ól˜Tè{JÛ‹øæ±Œ& tù"›*++%(‹I6ç-ï³:[œ²p‰æðͱ˜AÐ!ßEžˆ©ébZ 1ånÝzÁ!RÍ\‰j'Û´#˜“ˆ¥;-0>üJÄp½è €búð@Hˉ`ÒìîMÓ¥úZlY9>Ï(·…fX÷–ó âCêH˜BÃôb·Aò”íT\ ¤¾^¶%£‰cÙT8–pB]àõ…Û”‹ÞiL9ÂÊ“:»î¨$ÇkI‹tÅí­6*!Œ–*4qsH±&ùZ^_¿~W…Ɉ˜Õ…ÁÔ¢§U‚RíDʇ”˜ Àœé”­WÙâø #VÅuI§ÖzÍÐÓ¶%Üx•DÎÄúŠ7UÑ0‰ð² R ?4&vì¼½ðÆ6j÷A½ÔV•ÇÁ”**a¸aÄ@Ag˜&x³I![âkO (¥ H¼vBUÕË2) ¤e“Äœ”ì¡ ¦ñ³†¬c:ß}÷àµæ“oÃÐÔŽ7Ó”·µbóÐÆ´ÄgNLü6òùï4)óÌf¥<†xK½X ¥ú êØ… ¯ îãÈ ­_ݦï&ìZtYMni¤Æã7­”IÌ·ì|à¥*”Bƒ\¬#È ²ý­={L‡T}ó¤sä®r%Dà©Z‹áªr UÕW­5Ä­«JSx/. ªÊ›Ââ€|ʵ.R Cù¯ýëýˆy‹³µ035Þ3YëÍ£ }8Nˆ¦| ζw)K3œïÄúºR–,ŽwŠÏÝWþõ‚û‡Ô.JôäK™ªMµ/x4‡`Sæ‘¢µ¯ž0fcÆÞ!JÔVeùÚ¿üc0²Ô­ãØ—1ø62/ËàyÙjª*4¿¬GÁNcd4Yªí Œ„ïXd»1¨YâÀSxíø2×Ï »"ÛŽ™Å†±e×qW$‚c”êߌ"´#)ã15 âDlˆ]OÛDËàWÝã0-ᘪ&ìpp4âÓ©³’E3¡”ªï¿ÿÞá ž0ûúùçŸ~åÚ1â:^Ðû+}›g©®T…mA,PŽYœ×BU&EV­|{éFR[Ó‘²ÚŽÅÁ*´}L÷†ø[ÌyÒ¡@Ÿï(ø®#¤cßTúBøv„`Nˆ§Qá×_t¢é…À,51Á m_ Ä’2ÃÏwJ -ÕºˆøíÂò>›rtNLyH:ż¥^UY ÔS Ø0Nɘ‰É#èÛ²Z—¦CSÈôõ=•ÖðîÏv—×k妒ºó…—›ïj’¥Æ¨o›é¦=£üšõñÿ™þúrÕl³u9ÌÜf7|ç“WOUIKDÌ79ŽÂÜbš½Í ì ÝÌ®jW•Ÿ²¾˜ÅIܲª@-*¤&îIjw8˜µ3ü–¼Ø Z2Ëæ„ÀÑxÓڈ߲Px´>lfðk3›Äi´l²ÞÍxÙjщˆÀÑJ4l*1œ ÎÄofI‡Å(q&ÝZbÊÏýE)üûŸãR0ªy4Ó'®)YÖ0²Å²hÀÌ´n~¾r1©~>†¦„T'ÓœÊ1ðlõíz9¥×þòÏO×µs}ëb`3ðmÁÌ$]àvdrxÛ^9)ÂöÕ¦Òç‘÷¥šf‡ÖûH©8j1ÕÖh§aLß” ^e.tw©v ¬‘€¿Nâ¼YAèMœRÊœüëznGð–f“â-y)Ù@­=ŠÌ’¬“a–ÈbSõê@¨éb$^ t_’EðÙ¿,ä 3ÛÃÆn/D·lÁfn~¸±)HA/‘JlPI ÜüªÐĬSÂaø Ö‚T"¶Ùõò…ÃS%…Sùmf¶æ×ŽYº?I .0‰ Óût1Ò¿ÿýï½|,)ózí|%°4†Tlž®QŠ&ñhÅ“î{€ ¦²™ €¦— Ø5&¹/{.4)%ò@L%¬Rðû’ $Þ~Ñ&>\LY#© ÕR­Xà`1»=ÖEÊ0 5†‘Š=”+´ä‰HU¢Ü²^ÁÕ¢­uÞv Ï[Ãkdû‡t,qB§aZY \ 7•[K¤§ ¾C  Eáìööø£`i¶ž< fgW¨Š S_± ¯OhİRÅRZá!¥ŠïK…ûÛß 0Ú¿:ìçÂj5J6)²ž'<Ü¦ìˆ šØðÈ}È6Û.àSƒlÚ‚4q’¢ƒÌ܇Ï}êOÁô !&ÜTõêL€.V³á´©ân0ÿ¿?â ÙýfR|w CP¥„šYSÏá×þ¡›þ/WÚÙ‚.륵ÁX;²)f†6"¥ aæÄdâ¼ K4f™AvbðʯnçbÉz¸«Ý!NÃK©ÚZ %Rwß—zV(y‰éÛÇzµ½ÚÄlgÜåÛKÛÒH¼SªªS…4ùU}îv£¶ ) þÚAÚ-Ó)IÕºg©,w2dþùg»K¿K ##H\PGÁRÈ]>'``K&k~%툥*¾X ÇiX*䙬Úhbû²÷m*…“8»JÏó„‹×.KÙÖ,{6¼Ýñg«×%ÆilK´n†@Àø¬eU¤0eµ'Z·œT[ëØÅh.D]ÈLB9A×T ‹#+àkáª>·ŸÔj â…)hòjS+l˜×xþ5‚¥”’6ˆÍxÀÈR,Ù¤:–ðÅ–•¬°*š¾—Ö®û RÇ¿üãÿ¨ÞZ“3S£óÌŽÆ(Šùæ†àCдڪÄ-ó«5SÅKÁéŒ#¸ò'%pÙ…l%šºäî9MíªîTQÞÅ ×¢ù“…Œ™‚å˜eõ¢<¦rÊUµæk„–!ÀÅðæ¡I˜~3 31 M’2¾ FAÖ}Ì^i©ÑQž![ÖN@Ç ½±è&MY•,ÄSÈÄF‚7^Ýqèˆ$åðq,Ío¿‹‘é Ie‰ð–Í&›a–•ª{óÈÖËòµ?Ü×Îf}ŠÓü¬i;Ïö+…ÏÌ"+€#ÃXLžmk‚®‚`·âø‚˜¤l6Ù;qçlûM%ðÁñ3Í‹Ìßž×7}ÊZ‹Á7¿¸MÁÁàF²˜à'kw-ïåbú̉#Påft!ÔA!’TúRé (´,+¦Ï0‹©EÀ4¶xKkÂʵS‹ ¼l„â«ôè#ûuyŸ¢ÝiãÿaàÌý³¨%N$³4@ån•Úé¥c'cþJ ™lD” ÒTÈêU¹;ß'{îAz;Øß%b-š¦ ÛÜ…ÓW¶+ØpãEÅ{@É6•òYµ–8Dš* 5òyî'kñ.øé§Ÿt1¤¯/šv’mï0ݽNR!Ä@´¥ÜÏð¶FÍ̲,Z%qxíš¡}áX*ÌJ¡uz–b©–i®{þþ÷¿\ù·xùÇ„5¢cøíB`˜íKÜx6âˆdy(ÜRmå4*ß„jRmÄÒ%°´ß”£ñRº ;mˉl†ÄÕʱôåÏ÷íë5©Þý÷;“ IŠÕq"–²æi„7ŒÜW¾ÿ‡˜¿ÁR˜œ`qHÀ«êj˜ZKYò¬« \¾o¶_òû´vq rN˜‰{½4ÕÈ[6˜e¸¥aX{éâZ&bB´”ÀvZ9¿×E{ljÖ2µÞ¢$¢ÜR!ÄY€%«ÎÒ·”²ll>r –Ìr)‚–®,Ç!ðŒŽ¾§ÓÛ]½ZA¯)ÞÕÑnw‚>)ÉCÎ|o½Ä²©á0íšP|5<ÇžWF…÷òüË?ÿùÏA‚†æë­X¬éä,g÷ö²®ß£ Ó4háœækbx̦ÇT›þ<\I·¥.6ÏàÝRM‚Lª¸œÄu„ 9ÇA^‹5lj3L8òéz}Ói)³Z‚ÎSß@YUÑa6mãqùájó‚ÊU5*„©B¦¦°K­ª{/1SŽ_/K´Æ `"z%Ø.,e×B¬ªBR–hL<<µ²Ê•ë¾ Á,ïó¨…óº{-Û"øêÞ«WöUæ9NÜxº4¡a´æÙÆÖÎr8f‡oBåR½¼-i<WRU|O|à‘¾ÄyL[‹£]%DÄeóp ÓÂ/9|û¿Üº Ÿéû-Hó»5êc }MbBcØΦ*A`˜‘»‡‰XÒœ,2„rÄN¯Â‚åQ¼¬‚rAc!Ë´hK”@ŠOyµ©Á™Âp‚–˜ !p"™e] àþ A>kýÁ÷ƒrS)dZ[j­)¤-¤ßÖŒ§@Í›Gܨʑݢ<œu2–b'|âÝ¿~|áΡ£Ë¥}v‘QR£y”ò.¨Iì¢á=ÆÛ¯W½™áÍ d4{?MA“w«¾öuá—¼(ˆkmú“w’pfŒn¦Ë–,|µ0BcË'Â'^¨Y$Ö(C»² fýà0[œÖʥSºµ["~¹©ÁCj²Õ˜œR8£&£é48ùü˜NófÛr5ŽÆvÉtå5ã 5 ¯±Ò!<þB8Ã_ãË-]‚V Y]MÛ›¨Ü8üBøÑBV虿פüÑtå%­ÏL9¥ùœÆ”he¶›Í Xÿü¦®RÈÀ"8|ŽŠ˜@œéÀ!­7Ѷÿö÷µ?ù”ï­]õÞÕTÔRMÕmÌN ž]úp)˜Ví±î+#à0xNš¶Í²1‚÷¡Ót$âèOÍʯ:GH¢-¼f:ÃZ‚«5\:ŸÑÄÕ>ßê€g8”áÀJ áˆF¶VWÈO¤Ÿû€åœúé':Z­ú9@f«‡¢pÖÔBœîœA™AD;±¡¬Ô:Q|:ršß`ôAûFóÏEzá০Pµ¬•rMm/_ELÕEùÖÕ¹Ç\˜úD“ˆ0¾méh)ˆî4øJøNw¥mŸ1µ~ùåµ4@|gKSÑ”9 §‘q0mE!BîçÒáõe<>ôð™¶+é¬îþQ5ÆBf:l ±­zé€~«c…?oÊù‡Rn~RMªn=D·|½ 5—­^ÈŠišˆC §3év&k¸*e‰VâžR!ü¢ÖRà‰äLßüøãš\‰ïu|aäOFËÒK¼B¶BªØº¶úásLÁ­ŽsÀ‰ l‹Ó²˜n…8˜V:LŽÉ¿Ÿç¶^JE!õ ¥Zú$øªÿ’å~‡L™¯7u•PÔŒ™s·XáÚcš±Ú;(¾Ü| h2:¢îp)¶B¶V|ˆsP·¢Mg…Sæ0Læ6¶vh§S]RŒïÁèÓÏ1ï¹þ9M§*$½Dú bR:PxÑúDàœ„ë‰j†¾6 ¶ú 7Ǫÿø”9BœÈ¶!”9ðÓÄuŸt{Dîlõ§ Em‘Oátã‰1 ƒ“Ý“évIh©ÓHp‚@)øŒsäÞ^–¶Õ ÷ÐO‡ƒ,>ȱEÎ"ó‘áë¡C©î)vY)ù=”«Vˆ¿rÔRH?ñÒ­*拎&—/d­²®«B¶!¢n}Y÷DRm»B˜N¯+Gc+«ŠÄ¥Èâ·M?¾{Ô«m8‚º§äí:65dvO×|â*ºø@éÕ‚hµN´'Ä0[á)Øb2ŽÜ.(Áz''« wÏÄéØ)t~S‰)÷…æ-M­Ê]ÍžƒR¥Š]Q[f»¶‘)4GˆIǬâë¶h„&•»‹W§6î¹!Óq9Ŷ/q|sÓUë…_'!n$]¹: Y8Ús» u. SÀalN+¦CÀ$ŀĭ˜øÔ‚s0á,r[NÇA.1fähÖJpNC×ó^ :|ÆAh4þnHjžVýk,²iú¹÷NCù«3…ô£“ŽØ8V])AЃrõߌõ¯Ÿ:é$q Gº¨­µm~Ñ@¥¿÷‡j²>ú{§OMѪÔv¾Pãè³®…XµÊÔ’Â<ø@¹Èh­D²!Ⱥ…â4E/Ì×þÿ‚ûåŒ/ój@ÅMUä] ºjpƒäˆr|‚×<°Á­‹ÊÊ:–|Çb[®÷á>y¨¢œîÌŽ4Y‚meqâ”èÃJ·VâO®¾ ð5öTÔ†•™H] Ò]Á&m„ÈV¥‘5³A4Ï ²¤ðê°,[šðÍ_¡d­Ñèà(mükÅ'%‘qü”˜TÊß»zøÉ°ŠuHÍ=ìnѹˤZR½-^H?¶@)ºÚøˆ@«g‰²FƒwªV:VQm8^—¦(\¤øŠ¢‘Ê·Ò9ç%Ö½ª}Ê=(§=[ [¡!¢ ,¦Än3ˆ­éî4—˜8~åùh¶GåM­Ò]5QoRd¯Ê÷—ôU”ÂðÚÿøGs­m´J@ºñ›T:M¸m)I¹"Ѭp"ý¢ _M‚/Š£C!:ð”ÃÓ¬n~}J”²Òôw'„ $ØëÄI’¢cýõ'6i1*³5^!kõø:ƒà@X³uÃO9k’„Ž©«.Â0­ÀJŸ.ßÇB¥¤cÅM™Žµª=Èh”‹Bâ”…‰Fœ³rñ¥ÔUM– ·Râ;\×9÷˜'¦UBŽa1!ÝmýÚ èº¢Á“ªtkj òUç[díÕ›–€VššTHÝŠZ‹RP(“HηÖ^N`ÍX…$rV:‚-ƒÊ2—ˆËê²/îY¼_ø_ö0 óEN? *T-¥áõæÚÕDWÆahz iÅáÀe!XmÎÇV"G Ü9Ó7c²Õ*QJV’¢PÈV”ÿ¹_ú-ùÓÞ:ÑªŠ ×–ÕŒ•7‹Õmi:ƒÀ=%…Hõ@鬺I¬B4“EæP 1Û.}U:7þÝpl×¾¢%¦Ù¹U§DNW¤g+¿koØ.|:,V8&ÍtÜŸ]G4Ý~úÓ?5 ŒO§~:+úµ W´Ö‰æÃu«nMBšÂ6ÇZ{Ôš §æq VáXÉâ÷ö–oû-æâþëúOž÷êÀ×¶ùÕM°×‘:@ÕM¡IÛÖzsÿØ !H©«­¶iÒ·•{? ˆSúÄ€õ·Fö7Hþqvµ”f˜Ö¦ã7x mj8DK˜zsæB©­¢í|f ŒÉçLv70X"²ãC* aÊÕÀçþ¯Ü·ú¼â»⮎VÝœ[¥mµÁô¦tý4?Îý „²˜q 9VfR‰¯¨Š©(A8ã³¥çôI4?d·õ{ÿ†š.ù4;LQÖiáS«Dj|x! 8ƒ›×#Z¶ÝBÒ\>"¢ðþûÊ~ê'gâÔsã4¾Zë¶3„°8pÌŽ´(Åj:¡Èh‰«á¤@Á¶ô Z‡À‘ë„”“ÛéÕD'öîÓ¿ôŸ¯ÿVxm$µ6¤ËÒ6£Ò%«4q…$º {0»åZ—…Ü l +sùhá7 B‡&\#Ðì”ö¶A³-Åzn¹u£6È Aåн¯ ªŒšž8UµžcxûcnQˆ”²¦¹…¤p:>‚ú®n®YŒ“RuAÈ6°óŠiøÎ­«Ò¹ë¡†† [ £Õö?GOY3ð«æc‰c#d¥YÔØ¢Bé pˆX“HÖmQÅè ZŽç°è0ë²øtT¡€–Ï AfÈ¢+WÔQ¨ìê-¦”*Ê‚TÓt–”èïº)k)¼ŠËEe¢Ö;‘N~îÅëCs[ë ßÌ®^Î!x7Ó¤¢…œ0ßð]}¡z¶bj²tëFÃç·l@+&5¹&j(L8&AN¹˜L¥1…†ó3íýáX/q<²éhCÑzàsT縉m·ŸN:­²fÕ¶Im锂i+dÍ™,§hã‹Úb*W'”  œñe!$9!ÎE?·ºN¤[eD®¨ß*ZŠh¡¡p{7Ž¿üñ{áBß»ú&ÕÇ©²P][G§~}æÃm­ºåh©Õ«•Ϻd¢F¶2äÀ!hÔv\"~ŒüÞOÌþ•HÿµMQˆÍQ¢-qmزú¹ˆçrs¬Ú38ß©rÌâw[ë}"×6œßcÐWѶé$è÷8/1=û ~ƒÐìÌ9ji©*î(_@0­“XKúbî(¤Ø"”Þ¡ñ93äô;´Òû28Žãò¹AQäôùm­5‰ÿ¹ÿ+·F{·*ê/^” çè„ß°¢¶.¢¢5ðî¸j¿&9pšBÀør†j aŽ|Ÿ:¦µ3ñ"’Þ{™ ÔmV¢Õwÿ\Kù„ã§ß~ "W{õ¬Ÿ¶JCtÑI J<™zs3 ås˜Ã¤ÐMN¡ûŠ2²Íb‹©°NÒF8ðh]odÔ„ÜH”÷Ü–‚#ý%ÿýŸ¤¯E¼«ÚêSÑú´æs„ë6¿¶;¥æÍ×ÿR8ÀÖÊÙ?ÇPÍ%” áð•CXc½‰8|QGD¹CKÜùûW"m­¢?ýôäšä#H¬Hµè;yäš!‚lõV·Šr~­Bø•¶&R Ûl=S[Hz‰RÐp Íè¥áÎÄć0>Bâçíÿ£¡ Sdñp¤YåCäã°r!ZG`|gTCü; Ç–æ*òËbwÙJ[«ÒŠP:ýIUÂ)ÚªJéVU¬½*®s8ÿ:¤¢pŽKè:ñE©I¡  ²ÔBø›b…„øcò5|§åÓOªÙ›En¥0—ÍŠ¹t²üh˜«¡\üp ‰¢ ±=c¼½6è£Õ °‰ã·–‚vå=®f²åîðáÀløð_ÿ[QP/'' s—ÃÔÚVË_¼<ùàþ¯zצOÿÜÍÒÉC4ß™7§Ùµ*´†9YÑ.„ãæ‘h„)t†&B¸Z8§ÝéB*Z=§å|î/Î+÷ÅUÞÒ4¬"}ím@Ûd%®%8ÃdùV:h® )>ò¢ …soÈÊÊЉÁmwiJì=µBãˆR@®s~R= ùùÙýãË0>3‚PÌ uíøuÓÚ@ ¶jùôÿé_Âø¤ë_’©ËHÕ³¢¶VBTdSÔze<\¶FÐ0Ð=¶&9²¬Ý6é8(…€™\þ]ßüyNzóÓ5² n[FvŽZ|MÖá©ù¢R¼Rüq-“/וâc2¸•”ê "¸®§ƒò±£Û¦ž\ýœCY]¦ÊÕÅY€Œ8ßêLDµÔ s:ù¦bÈhBrùÈ—ØQŠ6eC€cÊê4€¶.AÛ¤º-qèX3Ÿþ}‚¹d^°ì?SKÜ,ª+]‡Ž]KÝrôà ©ì|îPh(üá²skÞB8øCÓÑDmöh²D…RjR´§Dmø6÷É3ñÝ¿GecÖUÊÁ–_oîíu] >a»uEkÒ†‚»Éw]S[=“¬yk“Z)蟸ôD9B¥Ô „Ó¨ŠÞTïÜbÚÖ¼µöè¼ÊúWøþP‚J0¾Ò†Ò_{œluøÈk•T cg|QdÈ¿@ÊfÏA‹\®”n˜Ò­p¹qÚº4~SY9=ûÙO®Ó‹,Ô!ÈmL>C`†“_Ÿø&"ÒiTèR:[;Î¥ñx{µ¥–T)¢u_hgXG3¢'î.ò"í¥ ¯1ÑóŽ’îÇUhÑfÓG"×Ê‘!˜RZ+¶èœEÑ»äµ*jE†0Q'È:#Hw‘.îãvácÂe50_Êëö¢éN/8ò'5‚¥£UË a…8z»oK<Œ›-S.OR …KÒ€KM¼èÐ\á‘;Æ4­¬1‰tb@w>'$?ô«ˆ U¸-*_”Êæ\À$ΓXnÛr;s½}QjË^þÇ?”=Ê«Xõ¬jÙª®O#Ô­ä xËoü]µ¦pÿHqàuŽæ @b÷Y¡JX»Ð‰¤°3Q´4äBº ÷w½Ky‰ãa­ѰnU!Û fim˜¥q5c"4MZw€%ZPn¡ÖwóŠ.}Eq½~8øLo!È@+Ó*#ØvÍ ×$>NÈdY@ú8»ôÀÒ0}§ôéOÿޱ¯Ç6xÝ* q¤V*ä¨wÓ‰ V=³–ÅBF³öfd²¬>Žø²ü»> ù‘€Zê3Vkeå*ìJAºŽÆôD-±æ©I ׌>ù^’pÖã—¸g‚Ïœa5²s{á?‰q­ýŠF¹º­„)”®‡ú7#PÞÔÖZ‚tãw¦àÀãóYÇ¥ycÂK§P¡ªÙ²¦®+u+DA­Ër™^ø5‹âç甯^ÎLKuÞt|CG3Ž‘c:L¦g '‘²—Øù9pÇ[ŠmYø|ˆ*Œ5¹BVf‹#Q”çã—bë÷uO¾‰ø{Ñ>ת¥[fX])¤«-GoB*Ö’­ƒâk Çt_º›Ýðg’k(m Ñ1 „Ï€¤¤+Dª1áùJp¬‰˜œÒáéÞ¿€ÌHù»ž†úóx쿜K_:15S7„£™|mضBô/ÔV-ˆè¡íð 3áwȶœ6„ÙvP|²VÛôÇ©±ú~'2üù短¾¾‘UK÷&•®7`‘%šÝ¶P.\ÃR\ô.±^(Ž&—•àéãǪJ4œd­¥]“½m¿U–Òºâ õ<—¨äþö·¿5”(91¾þ¬ž„8Ľƒh54œo[‰iÎq4”J„Á4­BEeÙî†F^?|„)@ŽÄÅ·–[ÝûÖya¸<ÅyM'5&"W«Ä)Å‘´ÞÅùáõ‰?«O+“¡[R:2¿P:‚tbmÑzUئÿ±œf˜,*e>2q8‡qlEKI!2D9>‡šU¨µtëÔ0K²J s9_ Ïnwj´—¬Jû'˜­J§Ôµ^'Ú¨HmwÝw>r”\œÆ·º‹4ϧ“2²-°Ù+aùÖ)+ToW©ÿø óÚߨªâ(´D_Ÿ¶n{§­yu¿ñ=r€˜5,«m3 À &>DTÈz¿è “Aǵ«7"Þ)5¹rp‚,pN²+G$_?ý8 UÝŠi[š5ãd<~øáÑr¿wýå—_ˆÜ›\Û¤TTº~\zUŠV…ßv·_}"72d"÷KÐ{ó»ßk}þþþ÷¿ûè£ç˜â,„SVvEgƒ0CaªÞ–ˆ­V!ÝQ!o"®—¶ùhŒï³ %šèrP3‘Ð×ùÆ(}ïôõ ¥žuȺ­ÌV·SWÆV!"…øBkFº)DÓÄç[7NGW7¡~Ê%bvëªÃ‰X)¼ö@|ííEgdÊUqá\ŽÎÄ9誧މjxY&궯a‰RR¢iʇ/TQ¡æ"+ddéÈÖƒ§°”Kæq+úóÑ'ÿ‚Ô,ž“úÑ «œœŠÖ³NlõYc.™ˆ3©añSØ*·ñ”âA׫ƒ ©˜À Ÿ³“I\ºZ¥‚§YÈ¡–‰zC!û¼æ•`®xŽ¢Ý¶Ú³e|Õ3UáÖ¶|n ,1¤D+‘n+§à|l“eÑ8ç…=ž$Õ-ÝxHÆ—Âðýò“ãÓ?A×Ô ìœe!7ŽP%ª^•*ÖpÊeáïIswŽ”¤pJ±†Èe|!FÖŠ§éÍÓýBß}ÅW!N"@ÎyaPï@m¡¬’§ò5ðI½%‚m¡‹þH¹èg鼺6Ö±hH4¾Ž©¹„Úʲ²h#Õ=GdzÉxDz‘D#•šôF³EÓšÄd9oõPB E¤†98rmqøê ñ˜@°CÓö]ÃI-ÊI¤¶‰ÂÔg:V%TìjÁ£ÙêG4œ“$Rç¶YRðÆ"ðût§Ï8˜t¬8éÜÏ "ŠY­ê¿Z§KA4KÖÊt+=‚m:Wä\#Qæ ïïú[…Ò¿¾úïß*j@czP±K/w- %5§­z[">Z#™-AŽÓ`gRâ‹6òVLRÖ{cGî2à ÿç5ã;-SkOWΤ;ãž7£›M?V¥!hz+Q4ñ;É@ý62ZÓÁ­fÛZJ¡øR·!U œê–È'RJjuÈÇ¿Gm¥X UÑÈÍ[!¾t¾hu;Z.óÍÐ»ß §ó«¿¢öhB^Ú±µ2úÚëxC’ Âi.Í#àCt®Éû¼±…cz”¹|>}ûKI¢O~¾ W%µôõ±fùVVo¦`m/ø1¯œ­fD1…ÝT¶µPµ8¾BæG.K:&¹¯ºMW¡çW¿èЕш«~Ÿb+T­uÛäûGú²:"ç–Ô==¿t„FSBJÇ’ˆ*»ípd ‹ëXê62ãßu¼ð@<*ýøg4WŠ£DM*ÑA“KÍÀs¼¡À¥Ô9>k´»+¬p,C­S2/5à Ø^ô³ÀÑ(Ki ‘…fëeûü?‡ð£;Íœ¦BÊAø÷ºÚ€¨ËAF³62¿1M‘‚Ùª[GÚáHde¶q(@Dkf=( i‹‰“(Ê µh |ù§ÿ«Ôù§À~k¤O“vŒÀ”F0Ü éfn"í!èG?Äj‹,Ä UÈÚ8VštÌÅq³ I‘Ë6²ÕùX3‰¶Œ²¯ßý‚]¢oêAϲRãS–Xo|RoªÿmFün~"bR8åêv‰ ‰B<eáqçKÁ©[LHÕ!YÌC ÀŠÒ鵯§#W‡…êáŒW2”ß¶$§†Œ¤D‡Ã ò­8¶@:IµÂ9Ví"µ¥Ü…„Ä™çnÈF2ŒôN$)BàÒ‡#È ­P |8>Z„.\& Þir˜ÕåÈ…w™k(…ȽÏ/úh]Ôê’BkåPà .Aˆ¶™¨êV¸¢ìôt5#Ŷ ‘ÑøV)h¹$ÏM™`Ný× Ûª$³-ÔOå®È ÉH‡UÑê5YèU«þ?\¨©¾‘5°“\“Ú€3ÌÖƒÔa·=?£IßÕäØR“¾×ˆÜŠ»[Ð S•¤(Oí·»îmLnäW­ýýOEµÄ¼iRÃúñÛ¾¬½ˆê íjí\5ŽUcWö¹Û9¶øÍañ¶5¼sœ˜Ð&^”r|ø]Z5NUÔ­U`Lõ°BèbQæëܪù¢Ú–ëšj¾P‚__}î÷§J;´‘kI',¿5°CS¢O-AEÍ®a pte+D GQ`N ”Åç0|Æ!¥Ð ÿÖ¥'ƒ64 ==Ô’ZЪymèÜŒŽÈz/h|[Yt¬)„ðrï2 Á͇Nóât†œMݥǗ‹¯‡hR„^{ î„Æln'åÖž6ꤡ®4&Ð*š?||fXÌnÇ LÄšMÖ–Ï(,×Vºñÿqq?¿x-xýêa]Çaæ´Nôsœ‰Dñc"»áá AÆÜÏÈ…HÁYxRÖ´àÔFÁ+³u¶Òqz§£©œß#•õ̪í9œ»ˆŽÎBJ×jÍÛö€µ•¢+Q#0Ž®t+Ä8 C$v·ÃU,* Ó6}†?Bˆ(Çš(‘AÅ»ÿàq_Røµ*¨é"«r²øJpDŒN-µ"õKßj‹pg®Rœóä±"¬m4ÃöŠbÊ9%" èL„Ö_âôákLâQ¹îO/ä"÷¶ý@Czªït­¶Ô…0»* )ÄêÀ*Ý¡câsàÈEk«Ë)·³¢´ehY´ÚÓ82‚ØJ´Æ±vó©)Èõ€Öù¶¥à¶J1,“…ìRñw>^B˜Ý.ëyMB(|´ð:l ùÈ¥œÂ=·nãS“¢küô÷ö£B=¼#K”B¼ÄI•î¬At=CD!œ|[M&(Å–ï–âÔ¹\Làø´.%ò¢1e¡14Æñ¥Ó^'/q|¯™ŽzPEZ긚B3²ûAȶ,ˆ«³Ó°2œh˜l *8No%lù8V" ¦ÖaÒ©·'‹Ý,÷ÕÛ[ +êì{»µtµÿxÅY½…Ûrhr4yÂשºjp²¶«¸ ß\‹ò‘1;¥à –^•²J¬4DÖNX´>ùmW½>“­ ~)'`ÛóQb—âïæe}ïª7_ÿ_<Þ3:™Z²&ØÈsDË©I²u¹¶Fnº½<üÜøí_ü»üÅ¿Õ+‚`:ukË*”_ukNM ÉÕ P3V SèYjÛ˜îxqò||: "ð•K‡¿~ü­K¡çWšž êV]ÿœw²u¥! z÷æOa„{b`«,ïù8I5W儘c±"8™†µîÉÀrÈ™WŠ-ç…_—¨â¦5—Zôµ×Íp5ø¸cõåGèÎÑPAÈ õO ÒíÁǺëH¤bÅI¿º•¦_´­µ¬ÕuË=‡ø½G¿3—tÎT¯+ýäW]ˆ33š,÷6§¹øœ¶Ò‘­:g¤¬tÜ'Ýc†øÌVÔtB²D´~"ðÉò×§*È,üU_ÿ{\xíüå/Ùà‡ï ËÏN5£(§óákf709«ÓÙÛû‹æ¬²ö^À÷rÛ°ª@¤T—æ%pÄ ˆ0¾”üB~¯îÓÿR{ù£Ü”õ):f⊆pB†×‰µ‹7‘øp3ÒïÕ!Ý%u8=QÖ«¦¹*]n'S«"˜øÈjµ…áã0%U!£YùœóvëÚ”cÛ¥*§ f“(oËÂm7aj=ý âªK[}-RÓŸ¨2œAÜñnç²t«ïª#PhT! _.#’¦•”(ÇAðE‰ÔXjDD[1‰²Å´eÈ˪Šâ*¥ÃI-fй(¿;Ò%‡³Ú–…ä3µù8³²õ¢ILø%ùHok ß¹Z#ät8åº.ê2üRàŒ¯jÐ6ÇtP®ˆ”NR´üÚ“ÿlkRs<Ê]÷m»¬šd:ì.=ƒ½½¤kØÚP­Eñ™ÐnÚ¦HΉÀgJ¸Ü ȇpHqÖ¿†t81õé!eó%Nÿíÿz ^·*:y§ÔåvJ¦C¸•uV­ÊÕU+!¡n+ôq aªäHäì(ž’o·nÎ2ÓCÏ ~åDµ ×F³ÀÉB„ê¸m|‰*úÏÑx!åJ!#ýUh¯î˜ß»ú ¥ }j;Ÿu¬U²À¶|Nm‡4,¼æ jŒïÑ‘”n]5U€R˜{Æ{ðfÿzÛt¼[›Ÿ²•)Í¡4߉ ÌêMcõ#‹#Ú6Ü–`a“EÜñâ¿K©h/!dR¶×pÿqQÒy×Òç¶fWŽòÇw™æÒ9çjùôÜh@[åZ5I¡¡lMÊ |üBVV“9²R¶ÅÌ¡ÓMÙ*„Ÿ3‹ær÷ÿÇG:7å:Q´êŠr(k¯º¾Èlx¡ºâËrk¹Q‘ ubüÄsÐ8ºãÉŠr¬B³¥$[Ô¢þ§Íeõÿyç“íöPšCcN—;D?«…`R[éÚp_ÕŒÝ|ƒKL“>ãPˆŸ…>¦+êôi§ÒËíØ‰äÔmG˜~!ë·/€üë¯}Ü0üNóö­U¿dVª¥®»°5”mrX¸¢9.§Y­Îªm>Žm+gÕEùÔ€|‚~Aôñôì€Æp¤è„¯7¯+¤kG§‹©sÌ*ªîª¡q0\ÝJ[¥Hw5Ó$îĺÐtäV”8#BΑ‹,Zˆ2„ÏòÙ©z1s*ÑÝ‹“Ž Xã?žûj<TFФ€dr¬†ÐÚrN´DùÒ•a%©aFHÖJ9d)r=‰„ðE…Š’…ÐAã Ák›/Úëh:hœ¤RK0òhF+JáÀÍ;Ÿ/d½Z;˦*‡ÉРɲj¢ Ó¡Ù¦àé02¤r hƒÀ9¢×{†\7 ÍÍó‰ãdá!V[¸5¤(¤*óZ7/Ÿ2ƒ;ŠõÓñJD`s—µ%¨á=ã#ç,ýù?Üýë¤3§Ï"ȱí$;+<›ÐD1EõÓö2=@IDAToXéüžá¶|jœÈ8¶ ¹"¦à3>Y„ø}Ü¡À©Šûð…¿3¸/z~÷§Þà|¦s³p4æ…lÛfÔ¿PYBŒq0áhúoFHåL:N~µÒçǾ~ägþÓ´DÞ™ïtÝ*êÖÄ&ZKõ3>?°þùœ@Žs^óÚvmE!&Ù¶¨¿º¥‡X­9ñ¥£Z}°ë‰~Úüè^W:é‰ÁÑ!}øæRW W(Ü6Ž‹\Ípp¬æe½ÜHñ5oU‚H7¡ßUà` dôë$q²hµ!„¹•× ãÈ%øñƒ/ü¦U øG¯Êwš¾Yטÿ(–êJÛÚ`&Zo[Õ ‹ÉoLH!`‰œ¤P«GˆqÚrØÛçxÉøYEc¶úIÆÍï’aêÍŠÜéé$Ž,>ã0ýÌAÈ—…ÐuôUǶ׻3à‘¸¾ŒvQ|º°bzt³UM|«Ûrm]ý8ªÕàϦ 1外ÛÝ%úxº ¸¢UB-LŽTÓ8©Àó›­b8zBÈdÁ½-‘ù™(faB è,¨qÐàÒ1…lqô“ƒÀ(DÚÖ!ÇV¨r©q<Ý(VT +ÅŠVn'ŽUd)$Òª° ‚†C„u‘ҤÀ¶øuÎ!Õàj¹àYÌJ§Pu"Gý2 q€É‚¯Rg–,œ¾­ÙÞ\²"GX´+hEÃO!`ˆÕ,¶µTAóލ(M×bå"´ý%+fÑW­þ¶A'Lÿ£öTlUÅ OÂât  ßéu€ü1/É󀄂pDÓ秃À:)¢%†8½ø½{ñUô/“W‰¯Zû“tj5 7…šÂuÑ-ÒN$}zaZ1{œáHa‘OÎÛëN.Üø5ÜÁm‰2Pu8Ä–áˆÒ´-«ê)C2[ÌRªkb%Âiœn<åЄ0Ó±%MpïgÏüè¥PŸ!èWZêÖµÖ†p @ˆ¬¥uÛì8,d¦['€æ“±÷¶À¯¯Úó¯<½='®Cš|—›ÏaJ0â+gKö‚ϲšÌj_0‡!h«aÛNFÈh!Õêšê‡¾gB_û·.Þò=¥k^i/=UT¢Û,°ƒ­kWM·h|ÛâC:=¸þ}ìS"å…B8?eéE[|ÊN,'óÌ]ZÑ­Úøå—_¬µçdÖD'5s:¾L"r­"°¤š9ðÊ;÷³->‡q1£u°¶ b‹FKŠÏ©J8N \S¾Šî‹óq>áøu± ×g%l9ú¬+Ûµ¤„ҵъ#ŠÓ­.Ëì0óqÎAKv馆9| ¶˜éwPe Qëf€ ȲÆÉ'ΆH y÷I]ÖçÌDîIšÖŸþùÇ|÷{9?‰¹|èJ_Ƭ¥ºê¢óN/ùʲÍywPÍhörïâªØÂ;ÕN,š,?™¼û÷¾ôUѪW(šÜÄ¥÷¢£à´¶>;ùzk­Z]ÔÊuVÑ V?VEݱ‰«‚™øFÐ ‡ã–âwKÀY:*&‚Ö¶#%Åpä6ì»6DÏW>=ÅŠ5 ¹¤+{Q>ÑÚâcFß´À)E2Í>^ð=‚ãç8YV¸f“UQjœz«U!´ø&’ÕäˆK£ÕF Ä™ºVU˜,dÆ‘ Á·M_°CãØfe)Zn§È¢C0ŠƷªÈÏÔÅw—X!ÊÕš-°Æ …à´­mœš”ÈR@`DlÑR „èŠO9|Ñü˜¶uŽŸZ‚V·o"qª.…™ï@žùεNÞ­žæ¾ãlp«Òõ¬nÛµp GC…h,ŸfY!V•9+ ¡#—oí&ìÞ3£¨CÀ¬hkˆBÝi¿ÜŸò«_rÔ˜ÕÒƒÆÌ¼]a«ÉÝl_׉Z²¦°V ̿âç«È K3°söbW®\ ‰V¼/Hààr«2"#Mt?[é.1r‰ %ÖX=§áx<ùk¨þVKÄ3YÇQŪÏ+²-Ð݂ƀúé  á0 ‰ & ñc³[…¾Ð×͵vøÕDú+AÊÉìÓ6¨Õ[Ý’M`-Ñ©"ñ®äúÝÿ²ô¬–CŽV¡©¹ M:<¦t¿ÜXÖJ|ÚÙ@®ºŠüV²z¨ ˆ)4ßÉŸ‹t]&Là²ô) IŸƒÃçˆZD94 ˆ++ i‹9¥‡ ½ö@|QâðÉjÃ,j)­œ5°æ­@ˆž½0ù˜ Íš_çKoÆno„^•ŽŠ­é[B:ç¤Þž¥ù[W‘ã§ßç˜Nàß×*ÚD‰WËíWKú çèMÛ,šq8B8Ážÿ‘Á,„OÖÃ~[GŠ“TÈŠF&‚(ƒïZ´¥|º¹Î"+Òö¿# üuó q&ªD·~øë_ÿªÊ=Ë¿Äp˜{ÿÒkXβj²‰¦Ó±ÃÍÞ&½“òCÒ”k{ס‡¤Ÿ–ßuˆãGŸþâ›d]ÙN­DR|ƱUç^7Po‰¤\t×Ú &Ë*D¡,éÈr˜hN@4YLÎ^,e•tLQ'Ã2åøª°“>‘&ÂÑ›è¹Ã0¦RB³JZ/ýÇ=ʯ-4!rœJ†§9A¡1Í™N-òIiΜÔF0Æ‘.«¢Ut²ò¥¬I¦h Äôá:©g‚Eéªlœ µ-„FA5>ÍV¹+ã|ŽÁ‡X!ðÒ‘óË•®hjL´:i4†p7éñ‡£ÕCáh…×!ŽD¡ Ù62³N„$0r`µ0‰0šJäMÛ|¹‰@0{p@R½Î÷7œÄ_²*´Ï»j5BÊúd»»ê°þõÐm¦s¯=SÈZó›؉¡Q€‡ìZÓŒ†`Ëš™/׊P]¥“ò+ø} Ã|‰ù¾ÁÈuk(£y¹QVTu8ã@´¤ ¾žkÛ«£òšáKé|€R¬Ñ¹$w>Ÿl´f¤ÜY¯­*|Ž5Yžž¢Çõ†3êq¡¥{?¥TŽODº©× …º ¡ÿÅ_¯Ðï:þ4ÖÁ¢l:ãÔ°à:´}×€-[–SàwðÎ"½A´íæÿŽ ù£™Ú'<¿ÿ1 hŽO¿ñÓ´ÕgÇágBQ£E93¼ýTŸoØRò Òi)$¡Isp\t=ûl”¬ïMßý©±ôO›w}_ ìæWÂi+í@´Ä:#Ô¹•ß…CŽ£zÃrŒ&ÅÊmË'Èw?X“*«Ã)1²­˜DD_Å>Ëw2/üúß§4¿é~H_<Çhú©:¿>‘k¬c…›e=ó›¢r|[" SŠ-M~7|´ÊARÃáÌlYmrÃ<{(êwÉÒ7 qNuç4—giÍÛ²ŽˆM¨8&…sè™­•¾;ÎJ:}j–lmP&ßj‹/äÄ09Ö8œŽš3Ží«~ðK’ºÒaÍüóŸÿô4®|æ÷;^k8ÀuÅïÆä¤Ã™ˆžÌA™Ý‰5µ\ ?r ñ9º²Eó•¿{ÃëòÎ| à¶Çé 8)[“ÂOâ‰ä†dý@Dã§`Õ$¤þ[!nNï¬"—«çp£¹ôÖuR¨ê­Ëm¥P¹š,¢ _Ÿ”ãàÛ:)Fœí”Î+Ùxõ„ZëcK !Êr¬LVÝW m„‹û8ÑÈVø©Ý‹á:®ukót™ùøN—|µàÎݨIRRHå ÄL_"KØ•8\‰:5[ÑhëSÅÀµÍ¡SDp¤(‡/ZW¤ˆÃ -Z–hí‰êPb=À3 €Ô„&Xu ޵Á òõP“VFŽÆ¢ÀiËYJÓÕ‰¨Z%V ™•(Ä·®ô”1+!ÊA€0üð:¤#^­‹r|Q¯Ò—ÞõèQ]E‡ÙµÔ !î‡8gÎÛZÙGQ|[zit¥DµÝ…ãt›ÝĽš²\F\ „ƒvн]ˆüŽŽÏa/ÿ—Д=ˆ«Uçúј´º–t(*¤ã!fÌ—B§t++½(Ÿ¡rsøÉZÉb–^ Ä«F?økÉ+]ÑÎMçpàΖOJ.Ž\œzàCø|%8ÈLXU|úïsa 謹þßø¨.Må85© Íè0§º|†©7d:Ñü*ßÀðßíÐ}ëg—^Q䊪K¡_?¢¶J¡Õªr„¥ÀÁ‰o½²-A:ÆÑa#PëaËÁé@èðM¹”Ä奯ùÆŸsîü–¯OúîíiUmù…0 ­Àü»cêâ>–ÎN¼§‡¡ÄàJo­=>u+&_–tk4ëhZµ}á×%Jû—fãØV×áp˜ ×xµÁç°ÀÎo–B¦h­z†`&hÅ´eéXV"È©•Î 8³N’²šÖáŸs|ô[Är•&XEk>G'BêB¬Ì.küwÕgiRgÛJ‚}ô"’Næfµ%X.‚ŠÖª×Lœ«—ÂTNH¡­D¾ñ÷„ïúÿ¸Õ0S±RÚWé^§F»§ø1Õ;»T­œî„F@ãdԈȵ²¶oÁ3µ›°U¢ ÇÚ ×ÉŸ·loîªñ¯žôï‡=ÏÆzЇˆ\‰ÉîxÈzaòñuÇÖë½öŸ ×Bˆo­·Ê5‚Î],¾‡>œ¥8µJ$ˆÏDSÓ Ka"àLkv¥žÿ;U¤œJ™´0¬+OÀaÈ¥µžp®ê¿¾%”…–r)Èp>£Ãדëj«"…ª7‚¬Ä9®¨k ¥gkÍ 9 È‰XKO™,ÃÙUI“8&Ü¡-4…ärvjjáà7”hÌ‘ÈÁoË¡ã4~!¬ÔjUHŬ\m04`ms ˜Ö)/±ÿº.ÃcÖj‚V‚²8l§³-޲§ ׿­ÇU£ŒlEå ©"꬞ÿþ¦Þ¶úæk­Ž¨×¤Z¶#š&»‹J v€‹VmCb—xŸ®Û›Ân |7‘Jq˜, )¾{àå?Ð諸s…´de¶ººº8WRÃ|!¸m7LmÃ9@KÍÊÐÒù¸F°&‚DE[¹Þ€u•H|¸3ì òMá¶‘¸ƒu˜˜V-YZÓIçÀ‰ã±­YMçÌ¿øn‘Ú·¬ÞTèw\U¡¬¨B¶p"»f¢ÕaâZâ kØ€%Ú±bŠúÖßG¡R¾²z{ó°þ¶5‘ê*à]\õŽn+¤“‘ÞqáóâˆJßš¬¨5¼ožš×%Æ¡ÆJ—åЬ¶8p‰NÀ–ßÈ/üvÀç<£jÑçdŽTiXµ¡ãä#³šo8äŠ?ÎG·@šr]t[~ë¥w¦¶ÅLÜÖˆY¾«o½3¥°R|’{áøqH9âU\·ú©3”©µ§‡È¢8§­·g»mä@LY¶×/¾­ DHÎäB4“ß–f&ôæž*¶!þ`ï[^Ëý¢ãeâ‡du½)X)o¾ž] ŽºEUÔy @œŒÒ³‘­¬§D·fŸóT!^访;§8{òÍ'«%EéÐdJ—Ò%bûäÃmCùû/j=(×Ék£­ßüùÏÖÛÈuøá)Ѷ–4¬¥s.×+¨Ù…jÞšáGpDJô¬îꔂ£~Â/ ý®ã·þ¢¸_J`2)]URnÕAi÷¤-¾ž;äj Á;êZ¥VÈ ·âãt䀪(G¨r|„zº[¬B(×Á*Ú咈Ы"ÚƒP"Yþ㽤ž1¨|È@ùÀZâèŒ" ÄÄá[)X¯ìÇó®­h ßJj!Nš:s|uR !d÷–ת‘Ü Y"¦¢”X!¾¬ Õ?e4âD*A«¢ÇdbƒV“*ÞC|âºM\")4ŽÄüø½) Á!LÅwžº-d•Ë4@ MV3hpŽ(² &ŸšD4&%Ž5ÃysÏÿâÜÛàè§ô•†ØŠÊmäNÒ9s ¢[#Órê½Èˆû(F¬N¬kØÕ)d w¶Ú㵄)ÔQÛŽÆiŽ2©zßø{ Äж­V!¼cüø•fõ>KWW¡Zâ4ÔÖ^8µ´®\‡­P‡Ó,ðB …œÓ*é@*Ý*±ŠrvþJØÊ:ÌÎY9²àhtl19 ®·|:•ÇKAJKmûäO¡N¸O·ék€c­~*Çlë¸Dcæ*ÓR{ßþÑßmÿ=»ª[éQ‹Ï”у³-ª“úá Õ°íìx<¸Ê’Îl rꟇL¡¹ºp¤lñ*CÃÐóÁóµÿå?Õe¥5é( |ŽmHà:öRÕR'#Äl[¥³BÈpƒ+ÑqY Z…¬˜Æ”ŽGÈBèfN(ÝA½ö@Ü·^k^'J¯?i„ ¨®ÆgZb e;'$³5ZW–´EN'As,Ä•±ÚãúÓ¿*/ñÓ«6|{ «¬.¿5MÛ]J8ƒk#_¨›œC*š,½Á­ÌàhÂa©uÃóq¬ Q&âp(‡KGöH¬Ÿ&>‚Uõ”‘!B…Wýà)G¹ÑÔj^[óúé'¿ywQTÿÓŸþäW¾}~+W‡l>MéwpÊ@£™·×\VdY¢MŠ`Ưü5ïDüÍOýKÙ¡¹ÿ;v²ÀŽ”>ïe¨ÿ¦s˜]kEù8µ#·flBU8`U"© ¨„ƪn-WˆÃ8ŒZòéó9úYoWÙS·OÈt„ˆ× §(\:þ9ÒZiŸDºá|l+9VÍq—áÅW ‡ÀóUM¼‹;t]ÂmS°åCäB–"±=’¤‘ÕbœÓÙerï…¤ ÔŒ†…Ü”qi¦Ð¹;`E¥ôƒÈ­+„t“…â¨5_4BµàëªÎ»›k ‡£.G­nJS‘q*ÁÁam+ÁçÌЦ™Ò­IÁCŽÐ›/±m ̹ºx¼ÿ¡ÑDS¢IqŒ†S?¥Äá7od¯(²KàÙË¿íö4_cë­†ë$°SÏM-ª%u­…Ò œ1!$§©ù8¶hŒÐ ºc"B.·¢q^~ êî?ÿ¿6€†µÍš¢Þ4¹>›¨¡Âã×­¶¥@8æm+ÊQ¨ÛN/…8$ßá× ÔÇË\Ñ®ˆB1qD½?Uës«¾Z¦CPWu¤V3*öÐv,LC¤dެ¢4û3ÖzþJ{}ºõ{gÅǯqFÇvVEiˆhkÀ‘¢ð%²¢pQ¡&]Ûµºh²€‰Ôâ¥'[«d넬t|öÚ?þñ§ê*ªâ&U”Ï8{¥kÛÔlH`—†ŸŽ‘ŽÜPK¤)ŠP‰VBˆ_È’&NG ç3œY?(ÒTE‡5ÃQÈZÑ®—®X+_Ñib†to–C¿é8¤¬hÖ²: [²ÖÚè`#â{øømØJÚñÊÕÏZ­úÍ›#ªïÎç ®û§†­Ý6;»7Ó6>³ð‰”˜‚s–‡ƒf•Ø ÀÑ¡N2ÍH‡à $•/RŠS²¾ê¯ÿý^݃Tç:QHÄÝ®õ¬mæý×uùxiüTÀ(xFùW›×* Èo›ÉLÄQÚŒ|dkLÓùèO<¤Äû*ñßÿþ·_ò <ñúìˇdøÍU'VÇEwu|Péƒ"'e²Vۚɷ…[)3¡É"ØfeåÃ1KÌsT×Cø#ízE™* Ž@Á…¶ª„h»r1ùpWЦó†`>Þ8JËÚÖ*µ'<ƒH‹FS÷8[¿žø²øhC½ ÉeÈ|d¦P~ Ú‘¾ ,‘“?¾CAë6í\¦†ßYpT± Q“bËÊ­Š•š~¢çÔ¼­”¶&_ >¦—ó†#¤RVÞË^KUèÖ’ÜD.îãV¾‹Æ„pRˆf•Îrˆä½"'ÄÊ ‡æ˵EαÂ!Í\J¿ž³éü·_µú äãô\VšJ¨¾æ;UÛFà°Mí%Ôåëܬ=ñ‘ùh ßdÅ„ßÅ19¬èþi:QF¤Þ€q€]åüúR“¯:t|ó±Û^-`m(Z«Öš1fH‰š¯Ï&‚ë¿hL¡h $EÈŒs¤ðGÇ¢Á«"KºUh%J´Ê:œï4QF9GKGýíϪءrtꄎ;ä‡~xòÌ}±¤J#wÚÓ }Í4”¨­ÒÕE¨ÏhVHLkŽÿx…÷Ñ¿¸º¾¾õgQ…IdŠ2N ymÕbZêÐøµQ]>^—°,£KO B'œô±MMι: 5~„.‡7õþ­‹Ïyz£Ü àt¥™ÌQØê¡U?Ú+¤¥®©-BÌB8…Æ·‚7W>͆%Å–[‰N¬ÛbÛ{yÖd‡ã»χҟ_}Òm=Póª«æSN×NŸBªs¬¤Nê3‚µf„Ê ‰iµõü1 §óï"ï bN&_]Mâ0H‰áOþ׺êÙ‚þ‘ ñN›2RWÃUÔX¯š:âXE9r¥pôV¨t[`~kàæ2£¹ÖV].ã[mSv\|‰@Ò™m‡éTéS°¢Y¥‹2é8²øB¯úÀg÷ Q®EÕºjž{ž¯¯5¥ÿ$ùú)àüûFoÓNÞêlá¬M×¶)0mÇDÈPÈ“Áêåð»¿ÙpŸ3éøë™ ¬Ôi:múªtE8 ($)qiüp[&Ú,Öæ”ÛV $2\ÅNÑ¢i‹'ܶ5ZWA4‚m|u½ÆÁ¯¨õ¼-a°òó[IpH …¤®‰}¤ …6[œSüÍ$r­jW¢”hV!jŽ­f)m‡{¹¢;D‰œ8«ÂXÕ-7A¸û2ýüDRp±EÍ+Äß\1SÆŒ „à‡t›Ñ\l¡…€5O|j9‘ùužŽ-YYJ´*Z(~Ûwà˜uH„áÛ†XëÙZ”C6å{è΄ÛꟓˆÏI„ÓíÄѦ¨ídù]ïg®æj=ï8RßiÑ'«TQ¢U[6¯ÇÙÖ;=8¿þë ÎJO§tQâl´¶VÌš‰ 2«÷Ž+Ýg¾D^¸úhHM9Ís”ÖÉ5ë¶öš§&«ŽoRV"ñéô2¹ˆçåÀ"”Ri+ZÕCÐ8t8{… 9ÒcrҤବ8,ÐÊp>ã@8t8Ä­Þ&=d ¢V£QÀñ Û{ÒIû¬y(9aj]k2Ê1ŽBªwŒîI Ô¤U?¢8õS3 %ä[ÿßúÖµ)Ñßo(­¤¤UìæÔ¤à•Ðd/º:„çˆJMÛd2[fkU¥;ÊV(}Yž±¢Õ2ãO3e)@küFs‰kæã—ˆ›ý{Gä¬*ªé*2>Ъ1«Ã±г†mKßí‡ lí¤Cø@k)fa|˜?ÐV[ç©„êm‰ØÂe1Ûþ—ˆß ªU3n úFã¨È1QÕ$¢ã|D´Í¬JPè Hßj+*¤h´ÔàñiÊMÙ ”•Ó{$ÿÓ+Yÿš¬6Lš¾n×̽¢~„0jdÛÆ‰@“Q°¥iM_¢ô¢ÍCœ'ŽI„Ã8}ÜôÄÀ$‚¼®8h^Vr}¤s¤½ƒPk Ñ8t€¶¥?³’rÏèDE¥õFŸ¿ÞjUü$ùüÃßU~ñ9†éÇ0I¹ß BO¡Î–ßcæ…ü®õß?Ð6&MVŠód Y!V³¤o­¢•á 4l—ìŽLÁ àT¨Z¹@„® ­Ã±*“O!æ>š'XŸ•&‚9<Ù Q($QouRH]LþšÔBý §vn¯Ú\;84•¬ºß$‘áœÚÊïhJl‰LUå«Yr]×_šrï4~ü.•Dã—k6¹ª¤p<>¼2Ÿ-}„ú'ˆÙëJ^ÔÊÊV’o›?N…(Ä´b¦©„-ÅgB|Q ­ÜBp„À%ö5»õH\!d9yå8»IÄ””Û6Û¢ÅÄY•ün)~Êh|–2\ékjŸüQ`üW­þÑíAMÅ&­ÏšÑ•­+[VÆÑRO.ƒØâcÖ¿¬Úk¨RðïT)¢BRª^Ej^í)C&…Ão+×ͯ_~&ºÚßÿ(¤s+ÐZ“õ¬NS×êA>í¾Ýx‡”,FÙÉbB¢qöÒ†KÄdµ‘NÎ q€m­¤¤8"æHé¨;µÈ8?A4øëiVî ¤'ÿô_-_ÿ“RHÅÊYÛ*n:¸êÀpÝæÀ‰øë/oŠ^'ÿ·Í»…kêmE#68µ@Ž¢Óv©ÎA†TZ]4>Ä6)à¶9BES¦P"¬­ß•²v±²êâd˜™-)Ûn!7Œ¿$¶]ÿÏ8ôû–øýè¥\m«ÅÑ@å8¶}¸Aæ³Óý[ÿÍÕá ÈB"pœ„E°ÂïÍ %äŒ@Ê좜ûÁžÂ—òÿ~éÿÁô®üí¾þªZ5 ÕM­ˆPcb2[`]UEK@«­\Øa•>‡f3¶¢‰VQH.‚ÀwÀªTÂÚ·ÈÛ~ÚÙ/…TT·ŠWçÍôŸ)Ä©·,æÐ09átÐîý‹v5µè ¹w8Ìë…N¥“ÊWW¢*8‚s«°Ã$Øa¦,ëùGæ»UQ]o‚|Ó€æšNÇmæ1å'ù¯<Ó(¼ê‚ž.¯ÃWÔ/+œƒ®”•]{¡Þ¡qôߥÔü°m…èp |üÄ!ühRÂ×õE†[á‘Ç-ÄQ“³E# •+ s€Y`~µÊª>µ½V] öxèÈl_’¿¥…Gh½3k]%…ùmrR¸à3ƒ­ƒ6’a60>¦(G¡ ËšDT–-§ÃŠY"Pµš¤“I‘‡OX¹+~m¢j5`R Ã[+—Ä6;¤Ël•“Î!ÅWK][Y3\œÕrsxLˆŽ)‹¡¥_"Äv½5K"|µðm­ñ1+$K.ðÞF: EÖŸT×6Áé I± ±-·V׺ï-´ôÂo³êÖ{¼F ¢š¿z9ƒ×ØN€S·õjïŠHÑv„‘•c|Y¶N/Ù²ˆT 9‚_ŸV8;.ÁZ¥óÿñ×ÿ…**Á”S×öª|¦³U¢½ŒÏbÞÉ|VÃߊœï®@8·çMÇ¢´*ðnñï)ó9˜V²¢@Ð ³ÖÚâð7,¾ôrã ã”î&,*ô9óAÜ€³>IÑ·î@´¡.«.>ßíÚ—å&ré}UöõfˆûÛYolé¬Ö†­"W©s& ÓŠÃQW­Î¤NÒ‘rÑÏ’¡Â)”È¢e{9ô™¨J?$c¾ëGŸM* !h¬-¾_ëÿîoö«û-«Ïy*2… ËQK¢*m­a¥õ€ÀI'^ŠCŽâuémæÞ)º"Àξ(³m­š£¥_J!dRJ¿ö@ú/ÿ¯z#ó]¯þH{uµþ×›‘ޚܤŒÔ:ç4ì]ÊM‚ã â#ˆéTm™5+~Û¹/ùgÐ^D>ÑÖpUº(¬=!iF”™ßå°ZSͳä7‹7q²üÝx:í*š« ™U%Nˆ£¨ ÇV•^àÉV7‚¯z[ñäI¹Y\2=ä×'¡CôàK}ßîû^Ãw[=äÿcÕ€²/þC§aÕ‰–X¾P¦UÚp¾VáZ)®„_"Ø!”(ÄÊ‚° •·uuàh]}7‡šÕM¸”BÎVWzÛ«ÎYp€ âŠJ$Kó¨\V?:AcV‘pþ™G/ˆ /'QùrЄ/$‘‰Ö´¿(2 ‡ÄA.šù u1ª›BL~çˆÉwÛ9P†_W½\£-1G «žëVQŽ‚3[` „Ç¡Àø¢ùÄ9²Zs€8l=Ýë0ѦÌ/½¶ 5HÇR•rEš‰ ‘ Á ´%…©í8¤·un!8!ÓC¬‹£ˆà‘ÕZ œA:. ¶“‚k)2Ÿ ±RBýùækŸÞ·üñOgUEEu•)ª«pZ3â4²»"„Ùù×­ôN ²kAP4„Ÿr)•Ãl‹IÄ gÔ\çÌw¿øÛR„gÌQuåÔÕ$« šåh ×&‹ w&¶U׎5ÂNCÓö..QQ¾ÐŽw:DXj-´”…8BÈt¬ºÅç§±EáPržB»íE™\Q+MŸþŸ¼ IõáÒtÊ9Cˆ*V-1U¢1Vi šÞ¼/ºè¿Û†7Qï¾>ý›ˆÈ¥úX L xΙóºQmDŽԚ>… [³tÛeå**kü˜á »ÁY4äÊ>͸.^ªœ¶e˜d¡·!¾¿®ôó«£óPB¡ÄµÄ ºÒ§ ×V´žuÂiü^&Ñdi• Ýȶyïg‚l‹œ §è˜¶L”) ·%%Q‡¾þç¿Ä|s ÕµÒ¬·Õ]' Ãð«¯sAêXî}[ÿÃ'Ò8ùJìÜ\‚ŽEÇìŒ,Ÿå ˆ†?ÿC{=ûW¡½ª¢„©û.֘ʱs1®û„M®†u‡ìÄa %‰¢¹v«,þ%y.1£f…àãä ñ­W ¿~¬=d S«Ý½4¥×íý¸ pSŠÜÈϬ¾H2ŠDÈ2mÔaúkCózCƒ#Ä÷³…¾éùÛœfzBz¶45¤ãmd½uh¶Úr¼q %*«n…Z—Rˆ!©Öp 9¶‘I)W(µJÑÞ„¼tÂa²jAn°–ÈvŒU!8¼r)U,”H‰Bõt> aÖ9Y¡³)Tù•,d…`*¹£´eBÖšà#`ºQ¬,Ø„˜ô¶æ÷0Úž²Çš¬⼜]½iÀ&‘‚Ò ñ'Z„šñѬw§,¸>µ*ÄQ…qÌl³¶;"ÌȽràh8j © P{ÈÆä¼é=îËd·Šjɺ†Ö§&Ó8«B¯–m‰9®È˜ôÒÙÊé(8tø9J CšŽÄ–㣅 ø6ëµ_ÿkã_ÿúýzÓ ?SWEf Ïòט QŠ•NL)µÈÀ”ÍXVš¶,‹>dW ^yG‡VÛþewB%ž_ÖßV&Õt“u¹ù8zÐv¦O4m×tYú·â7”¶Ñ¤À›N–g›‚&‘Ú©ñæ'^T®~ú÷P‚^û”mÑt’­4D”iº  úñ*{þOÌýÛ2Êz0,YÆ!®“¨=«‰vÚh®µwÁßý·ÔzãìC³qô?MÛ!Õ¶ŽHEÌ‹rn~Eùhµ7þRp®ã9ú@ëFHD â áGæc^Ás'8átJásZ9Rðž>ß(ôªOxÔXÿM0uWZ‰‚˜6Ö[C´$ÞDÒmù9z–(ÊFã”%“ßv‰«+]"…ÄÇL¿nEùnÔéØ>i¾(¡¶ö´ÁטŠî7?‹ºÙÜ«8ÝuÊ!ß>š7u ¡ m[ÿš$kRkÛŠâ°9Gúí“t¾PE[»˜t|‹ü•?&©Ê·¬^¹=UįO­²NCQÎi÷ºú9›"B=;:Û^ãeuSÅ¢PÊV)fçÓ˜ÎQK´~òª ÌÊy•UHT-|Ê¢ühÏ?å:Ïn›õPcj1Ê ´ÖImKqGùW¿~åÑçc€Ç 0ýO¬žû ƒF^¹*NÓ¶ãUŽ9X‘ ˜r7KÛÔÌÕh9BYUl…”ÞVb "Þ‹‹²¢¶À²ðùÈk ZåêÎÒA(—ã†aÛÆ¹¸G§V)4 ¼ºø|„ÇOéÖtµ‘€ò­@ÖQÖ¨èj—‹P1kÅÔKÁýÊ÷æ„Sm·»ZÝ©`Ž,„:h8,"¤ør«%Äa²j£t+çI­ŸñéÔ$È?i×'qRqŠòuÞ)[»úð×~úW«?þéXêD9x©áNh[ŸBÝTœÆìF²ýxÃH4)<"*?ŸcL! ó´•µ¨¢w¤Kðª_Ô6u«ÿ&Ò*êªf¬5Ïñâ­Õu[“²p²ü!ø8¶šçxJÇ*jÅgIÙÁJd²¢%… ×L§aÝ?“J ëSî¤ûj€#šhÝBÐÈŸžûï~Ñ­¯ÿמr]P¸W®ŠÑ¼íùëï|ú§ð[FÁ—ý¾0ón!1KÇj"ˆÜ‰ØŽÙÑÕ\E+ˆÉ:·N:p´Î é"òS"˜ñÃ%º¤PŽ`Áñm]+AH²p#)øg0/ü‚°ŸÐÈ&Þ¨ËôÜQtžhÀÞ¡tU«˜ðšçspt”ËÊ…³|`EãWÝj{eœ™Î•ô¸€k™Ùº[^õŸp!èà¦RW-[ÕO+o~Û^5t5Z'€Æ1ãÌGáh8YÑ…8L¨‘ÝB”ᵡ$Zã§6°Ò˜/ù/ÿôt'¯UˆI Î4Sz®kH[mH9§öö1†”‰løÖ4/Ê……B¬**-ª.‚oè× &„qX§DŸ/ÑéQò!üÈÖÔ„B§×"§ çNø]¢,†œCÁ6µ8¥ÃbÈ„¥—4?\u~4§Y¬Öz¸#| “eë”Hµµj€¬sóA“SK|ÎãA†Ñðø¬LŠåTÑ´(»ˆr†TÀu†#+LÊ' Ƕ”! ™çñÑ4ð®n••øÊ­=„{ó¶5‰g+‡;7™ˆ\ð„BÞ¸'dL[":YÔÖå†w8.•mÓ9Sôâ¯úŠv •°ŠÖ ý¬(¿DÑ)t2ñ{¦SÀW7}§Z ¥áE!ÔÚr€ŒdÊf_ñ³$kç`[ÈjF…¼»åENü{­GIYú¬œëÙÊD᫹tØ!C´¤I8?2^VŽ•u2gÔÛc/„¬4“î8ÈpQjÝÿGâ‰ÀEóNE^¹økȳfµQQýÔ§Nê<Ž(Ķ5g™«Ã‰O$RŒãNóQŽÓ¶×…hçÀ!‚ ZW˜ ô{u¬n¡ÿ£íÞ’lI’b D ¹=0ÿ)!PÝ`çsÿ3µ£³€{EÛƒ—¹™šššG¬X+/;«ó¤ŒoUÆv—R­ H+BH>Gkæ˜îÏ9KýšíÓ¿FFIZXGëœ_õaÁÿá(÷¹¿?G- À‰óÆÎ\Ž®Ó ­¬ÁÅ+d|°VÂDvg¢’jªÃž£u<`,~‘ÅEØ®Z~׈m2¬¬j­RVT—øë“KSÉç«® õJ3Ú" å@8ÎÍÊ—¥m7LD&Õ±hŸçS¤$’|åœF¶J1àÂz©zñ·¡¼ˆF‰i[C‰X½(|ÔëöèÕ’’ †£Äʧ<ç©YV¼&þuDÎg4زц·UÒɸ:¶oÝþ7‘º³¾iëêëÕGy SrÕ‹NLJÄ÷¨áKaptÞSšK d´üåY„„Q¢\G÷*ßù£2/°-ƒìŠT&ůõ9Äûɬ`òÀT½õ½6_7bKÏd<¯‘v¶ ˜ÂeéY„Ÿx«ñ“êÐ<÷”¸E¥~̹ Ä ë|`€•g„ÕBvòD2Hq[ VüºG2¶]tŸ’#)UaëwÃó’·ÆÃ©‹µ¸ U`Èmù´@B›à˜ù)±2àH¬ü‚|Æ×Ky¾,¿öþ›A`ãkB« ;ð¼›fBQe娬Mð‡±íÚÔi#qX á#·6'Ç­¿Cìt:Q0$øELE[Ö‘£ ä”óYŽ•ÑPЊ-Iüiã`°²!󷜩¾Ûè=´­Oò›<œº›®^)w‘ÜÊÆ—é‹3~[üÆ Ïç´ÅãšñYàZœñ® &`×B# â"ªdÀKY¸8 …±‰‹À–j:Û¬Ó ƒm Åm‹t±Âkæ­GR: öw´¨o½¨2T‚ƒ=W)àîº`ái¶í@8‚ØhP‹Ê#ìXŒ ¶`¾kªF¹ŒZÆÑHìÿûé0òÿÓêaê|¯JS>IkÍç°†¥Šß6€¬£ð%Ðî@Ž ƒ„Á2m^¶ ù!ÍXÄu)†Ì·Ä>ÿ>"µ~ôLL‡©‘.#ØÖ׺.«/w‹ëýù_ªúÐïÓRË۶Š0¾bü9\JÇš ªêîK^µ|Ÿ0l­Ýñ\‚¯7 †G/«BV°v‚œ‚º¨…,âd"·Š-Ù«ÝR¢Öêá0IµûdýÓŸþTÇôAD¼gTzºëšÆV >ýÅEšñ2#Š FªÓÈ·ÚfÕ*é4懴‚Á¬©_à¦Jüó[ïN@‹^e5¢G$=ú&O*UFãw­)TÕü§P Îq&0†.3¼Ç<’Éæd—û‹ C%Õ.;𨤠†·]*GI üë"k–`Ýq‡lRÁxT™Ñ–ìEÂÄÃø?¶ÀÚ *LRW$|·à¡¾w[¤l«®Öª]lüjƒ‰¸U\ ƒˆB¿w‘Z©Wì·ß~óÀí(4âhÄž]A0§u§ö |_íð}Y#e¨ä]²¯CCn©:ò!ÕªêˆêÛê"r¬ZÔ˜_¹Hï|°W~P›æ­~ÿùºëBöó£³l’ùrÀ€M§¶ؤ"Re¼r…ÍÛùì¡ÃTYãWÛ}bÅI@J`<—eoÅ)a¶´µn:-2κ—…a‘$Lä•ÿ÷œß:CH¼.Ýêµö w)}ô7Ťþ—Ž*¿äã°RÕtØHµ>G–É:FœaøÏc/#›‰#¬AÉšZO(gQ…y¶[¼BHÁ,UÑ>ke/ëùâ­á•?w¿;ÖǸúÖ½jÀT™«”µ¡È–rbÝÉe) ¬¶ÑbÈ—­ýÅ•8ÌÀÍŽª.cˆ¹ˆÕ6x|#CÇ·þ>²oÿ'2~½2-8´yéÞUæïˆJÁ$ÞÉ`è4¤º—©Ë FÛŒk÷ttÁÆtÑuÑZ‰¶iFÈaâxÄ;["ÛÈ›å•Oÿ:úu)+Ó·{¦W‡­vfçXS›ž¶Öô«…L¶ ‹mkYÛž¨¹ ‰ø ‘K5—YxüŒó´„‰€u&0‚"­[½`\…É‹ Œ¥3[NMŸNbD¨M¹B¾ˆÓ¨µŽø`â1N¾•%Cj–Uø kqJaÈ `ÅuùþüÇ ìæLmHMÏ—®+ºß7Hqì`al9‰«„ßµ!N6¶ÞÔ“È_PS…ñÄ ‡å¡Ó àÙ«À‚`UáéˆÑ"a¤ 2¾xVG¾B–ò¶Áà—½Õg ¼¸m¾5†hG^Üú{ƒ!,å|TÓIyø²RA¤{4¤-GaGÊ©/#-@®YDB"‰Gk)€Z~Yûó_µÂéû+È ˆÜÍþ7?Æ1µÏa~¤Î!ÉDV$,ßÚù$تQ©"m‡’0[‡‰8‡`A§&È·²ÛÿëAª$_-*à]YåR,þºÇöÖÿŽ$I>ù¥ñ‹sDjº”81ÃIs€é´íÌeqV%`­0ߘ}Ù3Úð`jY0[M;¥pÊZ»=ô?ÿHŠù‡ýø“‘ÚQÒ›Y’DHíæqí”SkA[k[àðE¤¢*Û8k­\–G%eC§dËép¬ýžLJà‰ÔEÜùÄÆÖå4ø~ „Ä/ ,ˆxša¨•òNüʇ*EÑ%Ó›½'[§7yÿ¥ãY¯Ê»i’`¨"•c4R­r¬‚È›rÛÖ`¶Œo}–ð•0Tðlp)´‚•Ã30[k˜‚­À¬T0q ØŠóÏo Ò%àØ"ŸÁÄÐà:ºÖ}Xq˜C~èø]Ý'IS~÷UqüœÎªÏ4¦é-Ù}bÌf„욅澈B(.[+r% (%^ª ã@–%Æ·o_<þ„Kj»ñ¬ÄjЦH[©¦³í”di“R"Ò…ƒ±-…<~[ÆnUfíH½ØÆà¨7xx‘¶ÝH¾9òÊ?ƒ¦Ç[F¯VJRkM@kóæ»1€Im›6$il¢îÙü 0å"¶?üØlùméáh—0%19 ®ZÖå+N“<¾³VòÉêÄ”ãÔ‘¤T¹3»¸Z$ØÊšÅZk Õ^±gRµ|)7CÇøœ®ˆ•i—³`•ç× [·ß,[G+åÀR˜7‹-k+Þ^UqŽZι‚ýaxÎqÜÏ·RøCŠÄ&¨¼^Và~ï„{½D›<°,yZ ̇‘MR~-â‘JC’ôª Œø×# )è¤û4Ò1*xŠˆÞ«DÖ-h5‰Tãt“è«{â©pñ‚éç7£5ýVà²GV#äSÕa¦Ïž"!À"þuWhÝY¡Âl¢æµíxkà;"©$‰ÀˆÔ«{ÛÆ'ÂR üêÈô¼åø À¨´Ð´[«×ÔRâ”4Ëü¶¦à0Œ,µ7/NT « k.ǥʃEŠ&ʼnD‰”5f©âz)DÞ燀A S•†z÷¢ã7c½¬L ¼*¿¢óÊ÷QýÏF¼_òñÑß+¢óé3®Y ¸Ò†êñ·5¬Tà0æZG³d* Ú‚ñ­!¥:v$¥`œ'ßyÚòÛFR|ÛCÿ>vÙ˜ò.ô‚Ïp>iñ<Éû8ègƒµÏ/;ß/»kJÓÎ:URm­ƒÍ2¼ZFy« †u\"²Î\|-LW«ñY)Uœ>Rôd`°aPFð¯ñÛÿ>ý난 ³e‰©»í4ž#þÜÂv§…´Å,ÇÉÔCç bX<¬¾ °EÈžH€"‘À»Ý<⨊W%˱ FÞŒ/H@A—¬ŽïÞ„hŸ¦‘ýŽ£»Ž„4m|AØ¡Y+Ï1Ç ÃAC0ÇžÓÚ9,bû$´U^‰Óp€EzAŒ‰ð!‘0«©"|Ûámú>]Én F¶ËÖ.žn)$:–r‰}m6؇Ž,º“á »¦&CÐVPwY2Û뛼3Òýª GœÓ8i[Üm+ÜVbÕB%IüÓáÏjäÓÛ‹òÛo¿%Àø]&ã3Jl9Æw ŒpÃ'Î(±Tk›þ&5T:0œñ¾ß) Rm \”ŽÅñ×"¤T‘N-ü[ÿö×»Fª¶6….‡HÐìÄP’Tqzˆ‡‘Zܾ-¶øm‹ØÄ |oÍJ¤¢…¬¯5'0, ðMž×ŽŸ’‚Vz ;7]^yOñ- -bžT-‡#ëÎ!æŒzßýÁtUȯ0åÖÍ"[¸Óãt8Á¶Š×l`†?äVN&¿-ä!ïQ^ƒ3pì`0x“Ò0|=|çÒ™†O\¾-0ÇÆé‘Äïži´,ZåJt‘š#ˆÍ YÜŠ gøU 6†ØÂwL‚"oFµÁHÆ_ÜšCl‘Öª*IŸÉv\üšÚòkä´c-@ÚŒ`Š^fU5—ycPë@‡i×ÚhV)ÈÅ9ñt&¥j­P_> ¯ †ExIÁCÊ2þ[ÿ~K#æŽêWÿÛþkóþ`Ì̲|+ßî:o“Š˜¢1Œm)ëLœ¯–c^Ž-d7ò"‚ó9 F‰ì_ãÛÒûÃ2z1ÝÝ-¦Ð×D)䔲R’/eІJ³uÛž†8ŽP9ÇP±‰ë`+(ÅÜ¢æµe¥9âZÊ&C È×ÑE±ÂàìÆV˜*ŽB)²Áüz±ª²ñÀùÝŸA¡u«¸}î×ZÇ´Ó« qÌB‡$ñVŽÙa¬ B¦æ^R¶r„L!,>6[>LYl!Ÿ«,Á‡âû¸4g©ªøÍ-5 ƒV¤IQ1©U œâ9 ²Ißúœ>ä¹(i³uEvk êèx N³î¾Œ¤ô4‹8k–«÷dÛ¶"‡A‹Íй;`רxœJl«‚±Í ZÁd ~ñ@ü6ahñ§œÏÑkå­†˜Qzøƒªo½ç¥'›‘íâ6…xÌÃ'þZ rº:Rã â0ü»pÛÍëÔ#ñKô½ ÑjaÀ¤j€C0"—¸‹¦ø$)ç[UIUë!À:@$»ë`Ä­õµ> má­ñ« Ö¶¸U—g$~´tú…ÒÏŸuøû’)1:rèlŠZ[Á¤\z—ÒIênË”e mÅ)p2¶ØDºm¢ŠF•¬TMe0K‰­Ô ÿ\„¬9Á"WŽ– Êæ•×ø`M/ù 9­HجÈiü}ùæ(‘ÒQ„ [ʶÊF»’9«­\üÄ=äN²m#à‰j´+ÇZÊ9‡<=D;t¦²J»® ÄŠ`\Áø‚üM™¬Êm›S'AŽ•I©eJ¬¶õÍG^»TR".¨PÓ¶ð §IÚZYxŽlxN‚1£0 øŸ-ÔR+nÇš‘‘†ïÀ×+·¹LGm"£FLd}mƒ‰€=9Å5M#2§óL•^j1p.ð,RE ÑÞÎ_'&…|N~Žª‚i+˜ìxzj;I}¥Âפ¶9¥ÞýåüÕÌDêø£µø‚ROÌ©À K0f&Èl½®:Š¥b«K&R¿›¡¦‘8Ç«uçVùÖ ¥âQ.Âübä[ÈÒ¿¿G­F³$ý^ €Ñ(QE<Œ ¾•ŸÎ4‹D"ΑêŽržƒ!L€ˆ×¦S…ìäUá©ÖÊjÐi·­‹¬ø a˜H$¯|éÓ¿¦ähº¦K/XNwKOI‘fwD̘,_œ6ÛD&X‰xlù8“ÖÊlÙR9ÁJ=×'¾v=c D’tçtz©åïUÀÇðdVUÓ Ÿ’ » µO‘¶ZXÂÄ#’*Nþ³Ý“ŸrN/([VUkœº¦Oò‰?©M‹N¥"8[NצïuáRv[ý›Â¶V²dÁâé ‰»D§¬/Çs¬L/äÍìžëïØrüH½^`½`€ñLXóð0暪Éo’àS¼Y"ç€c•­øh×îéðYÓ˜Fæ+éN³]Ä#B0Zg_Àúâ·u˜Rë"8$†ò6¼­xöÖ§ÌÿüÏÿô-Uœš:w©VÄ8 3ËæéM”% ’6Née9Vx) `|ñß›¬à¡û~Ëi[ܶW.mÎ OOœºtÎá!m#LXíŠð# ¾N;f-øEš¢-$†Öñkau‡¼ø|ð«ÿz±Z[õÒ”$¾Õ6m0⎂#âÚu `š±”lj­"V&ÈÀXlªvÉDd;m%™¬BÁN©»Tä©“Ð÷^üE5ð¾^5",ýT¹1º{“ÀéÖ•5‘Âd7š y1Tb›Ú,dAk¦¤“w“€Ù~ÃÏm£åÃç 2ßú«q¾\g..ZÐÙ…ÖE¤‹"X–ŒÄ´•U¨ªcÌl9Wéy`¶hÇÌAej/ð} ìfJL‘Øvh1×K0©mó­‹£²M¤_ûü;JNó.I ÂÏ¡¶›¡7”ž3u—‚q\^SJ8ÃK¡¡vÊ{]p¤PÖ¡GÏŠ[çs෠É Ä‘A’µq>=0Ý"Ru¬‘-L |­£œ V*ØÄ¤†Á[E€s‡:e·æÜqÑ,rUü|ŒG£®ÅioÚ‰«5¸­•^]›x³úÀi_qŒ"Q´5<ÆÎåVŸ÷0’#¬ ŒU‰-Î>B]À€Ir“ņŒ‰WÉøj§$XÔ†áߊ¯×]#x„RH8¶uçdJRÒIÙŠo° [–ßDµÀÐÈúÉIg<•H)#ÈDr¬"30R­Ú²"¶3ÛLpM»ÍÂ/•$<ÀJ¤´0¸`$RLÜúÊŸ\¼|gñïKǦ¶Õ1aÖ¶ xÊ8eWjšóoì|ðjLÛ²Í;$Ú¨“oR÷dq[ø•¨bRk!›6«‘ÒTÊ-/øÊ/kÖnkÿü—ž+ðÜØÝÒúŠPÞWòÁ(äWNëÆ(ŸÙÎÁ ¤O·îj¾TV°V<âñ‹ÐPß²½DŠ€Wåp4šÔ®”^½+ÈJ%X KXN)Ì8‹¼ò¡ ¡¿"BFÚÈЈú=jj×m)l|[Jž‚E¤‚ ?N>BäR %f#Ç3æ¶ÀµSëZ“JO<8ÃÃp€UñYNê(XÓÁlYYNbøZ ÄÏg‰±ÂÛJìZ¨: ïgÅ[?–Ñηº]íXé2§#uª¾%ÑŠTfKjs9ïË6þ†ÅÜRü'Ó °F­ÕÔœô”zj[#ÁÄwpû¢-ì9)ß«IŠc.¢ÇøÀ7Žmƒ¤Sœ æH5‘Hç`«§W. %;œjußqu˜¶½ÌÕú ëbEþáêWF1›T_T­DЖBòÒ<Œl²Å• ¦„ˆ3ñDvt¶Rª`DòCw_Y¶Ž‚«ÁÓfglü8[+ç‹×”RŠ_ðoþæo²îOâG?yµHIOÂ;Ü×§ä`J8È&ÃQ˜‘/Î `v#R•­ƒª ’oÕWaäÑÆ3¿ÖN£Â‚¨z8ÀP¹ˆvhñw×)¨i‡/Ëà­)¬iYkÁh¥ÀžW§B~ɘ“ºµl"[‹à¡9žZ‹ÄfËb˜¤Î\¼ó¬§]Pœcöó²$NÎÊH°"Ψ¬2‘ØUBZׯ¶K[Š„ÖI oMhq+<ÃSIi[m‰I=Ì<â Ÿ‘xˆtÕ•¦Jœ©DV3_ÜÚ¼¬­â,$«]}­90¥æÊV…Ä6€î| ó9#žÁ¨•zÒªáha(¨$Áø9ÃCFÈ¡Ä3:†ÊÁ[v\?xRS†¡ì´ VÈñ½=ßá“zÅ|C¢¿eáÂMó“YG"uOÃspÈÖJdÙ³Ü!ˆTn(~×®¸©;á 9•srHÆÒ–’í¢` †óÅ#Z_o·ÅŸìÚZme9T°M•ãM³uHÙ‚Á–RRUTV)§Wa½¼~Ãw«ÔN—0Rž=C4bRŽË Xai²™l+€U°v0²8Uùô_àó[~Ý¿y5rK˜‚f¾U£Èùº3©Æ¬J„*+ŒrÆgÉã7,‰q6Z$Á–Ù*)h‹ž0þåþ:4/™ƒ¾Á•Øæ' í0R4㆒m^×B•´K©:Â'æÙ¥Ñ Yªd}éûù·*륵ïðÉcÛ¶jJª7…Ý”¤O¨V°.‡òÔr:È„<3\ãcs2ÕvÅEăRL¶.âŽNIœœ™íúÖháCcÖ=~b è(S`œDv)SÛýC›C¨r)<"iÎÉߌM-Õía «ElN†¾²RŒƒŸqc¾É‚ä•/Úà#©ñ7š^úЧ?1mEÀ‡™…OIç`kf+>~ìÇ*ejf(½ÐN†”‘ïô–[Ȩ®–³H•U¨{‡–~Y[¾;üó[ȉyÖ!Ü‚YSz’Ágd$5m¶ ,; `WöÖ§ŸZÙ^4;½êé5’å×ÑÊ/2ò9ReE8­ª4uΑµH¼1]/ȱ=-oUããWÈâ—å[° ?«ˆÚ mÝ÷{˜F?¬ì3x+¾ïuqVÎ'ƒ¸Š¾>ÌÖ·@¤^Q)?•÷ÆV(uîi9!{rm]*§ßËÆgqYD*‘Ö2vÅJꡜ~*!•ŠA+3xj¡„/2NHµQÕ®«èC§,0 ‹Ê[ &Œ¼ÁE§!Ÿ‰7”5?ª¶Ïª"T9 q·W ð‚„q4b¥Û²qÀl­ a%io+ÅÁÏa"µãßê/ž›Í¶âjšåÏb^YN'æå`c•Hq"©{x7!¤¨Ç=NT’µZ%Ê6Ì0¨^4­Ù™äû͵KÓ¼‚ÉNU"ºË’D?=á Špº‡ÉœZ% X U/±FÆS/©:ÚÂØáwqƼóÌ×¾x8˜['©»B˜V­U 6Wƒ¼ò-1´þYmzíòCF­›L&˜-€µlƒ—âCªåpØ­; ¹Q%7y" XI޵ªH:‡°l€Cýý(Þê¬èua|+ýL–¯V ¿ gq—>yIçvûZ”˜eÝ9/>ü» ÚèÞE¯Qk"Iâ ÆáÁêv²·md‘À¼BŽ‹ÄÖiX•;<0=1ø ÀÏø0üœR±!´}ñç¥ýªdƒcÖ…­ s¥ø4Pk|«°•xξ‰ÀW.Ë’š¡eDÐÖŠ!+G9þQqKs<¸DHò«ÿŸÅÉú—¬Âê¥!ÀÚRœ Èyb$ ýR]`A©¦¶8NçÉV Vm:‘YȶJjÆøLU7LÚ¸à?ÿó?ÿPò Û?ýéOiÖ‚—‰U/-XM“Á¿Š¾ÂE¬ &£*§,¢—ßâ+œfÁ¬ˆFªàd²R«œ¹FPÞu™ù¼:ùWO´icR"¥æO@Yà•/¹¸ägá#ÇÓmL[UÊwž#\¯8·UãVññ ƒ¬Uù×k»WסÕy9}—NX—'ŠtðYR8ð`mUuSr(à´rÀ†œXaw0­ô$L|·¾,|%VúÁ8ͬ‹ Ü ¶u/̪Ê*kí#Ô¿”f F,k•²þ°éQ•x%̘ å+Òâä$€Ã8·èô²ý¡s]ÄÁ0„9ú®Âðj€¦V¾Â̶.xœyU¥ª‘²’-.ϯ•!¬ï?üÃ?œNo˜ŽÞà5œÇØ#ISqÆ©!˜Ë ³þÜÍÜ7àô{ø`\ަüÓCÒU‘nÏl‘ÄàmÅÁ]/(l” þ5þþïR×qz4ÒNßF§ÐÖú¼ º±7NƒÀpÒŒ'æ0Ñò˜^5ž!"ÍX¡”ñ•‹Ÿ‚ë[–‚lË,Îo Ú¶šÂÁò+iM[òøLƧ̎ºà/¯~åë:}{’—6NM“¡cGm–¦´ÕRÖ œVåI ÌÙ à<ÝHjá;¥ü:6ˬ$6qj‘äË2…¶þ~Ö:S‚!Ù“gí!0'ò0Eò¥b#­8 ~<8@<¿¼úÁ`…¡SâÔ”sÆþ¾§!%®ŽCç §ÄÈa¤BW6_< '˜*)«-¶fTe›•Ò‚ó¼FåËÔ·Ä·o;$ÕNkš=‚tñ rÅa8dð{`r¤¸,S@¹8’¦–Út²`Ö¦n®g ÂT9ŸNÏ Àº<Š}·§.oýbä¾£ ZªšelÅŸš—˜$€¶U‚AÆÁ?'N‘`âNÒAUhÛ¹°2©Î6N…qZç`(.²^jñs^ùíßhÛÍÓ“œ0-üh½Fƒ ɦ­¸ÈÓ_ÐÈÌV¶û ƒÚN£ó/[‰?p¬L0Ǫå¬0UEòc[¶Ž¶R"úz.ÐÖm)Óy ¦A#ñÚJ¤ls5ßOu˜”ÃðKUØ6ÅȳùRE¶J±ÑòK‰Ô—Œ"ѶŠ@–:õ÷áÓç3ÊòO0eÐÍ_1_ÄéxçƒIœmý:eG)€FʶÓ *œÄ¶ÏµR‚s+rJ° 3Œx0̶™žÄóU={Ûª•bU)Ožõö9Cé)å4°¿ì˜¥˜H„`‚M#>ÙŠ0_ÐÙ½¬0¿•óŒ¨a²r4U…‡kí8aΜ׊OÒ¸sÈGn«£R+ŸÅVP<%>u5B„®¾!á%êXê’ïaÚ  ’¶ºS™Á˜Ž˜çŒNf¯ù®N/g‚Ö•bÊ#ç÷²A®Ë5Z[«Z}9ÞÌÔâL ŸCs[U`$u'GòÖÚ?Àf(Jh`¶CI—†#Û±pc‚yq«x°¦C%ŽœIÙÂÀó£—ŸzçÐ¥ x·$«6ò"­â,¹µ+NBqƒx9aÌ¥°EÂa©²*y믈ø “îÀ¾bìH;¥dPbËrF•,'Œò­»W¤17uS´ª æ$Ík;ÎðO0 8Ú+ä\‘.\ÝŸ€µ¶0. I¶¤Špl]ÖgëØ¨ i Ù}U”T•+Lw‚“|ë»ëîWÿ}ÎÓ½W“KS_í£i}Å#FÄÖðMdµ•m+ËÁÀ:.Çh+—½ô__ß^øy *tDu”aƼõ/}€Y;Ý_;qf@æöd„IÙzÍò cëL¬|$ƒ¬Bà»âd‹À84N0«Ââέírþ¹¼TH\¡-ZŸ\ùL•­§«äÃÕ?Ù×. FÀF¹m>§Žadm­âùÄ„´eùtV¸U¶©m6²”ƒuZs*ß© fð+ƒÉi]¼­,Ó®ËñOÿôOOð/øx<èpº ]÷5"›Q›~­ˆo+·„„çËv"|ŽsòáÅ™­,“ª—`ϱފÖµ¸m™F¶âëÈqE”»:|¾×Bÿ_ÎjE”T^£Ãõ¸{Õ¦(µBø§'ÓAò[/ûûõ¬-˜BæªÀA'Y·³íù\\äTÞ£°áü½ꪈ€vR*5°îŒní×}Ì'È Ï10ØmzžN6ž‚g…+OZÚJB¢2Ž»"Ú²‰´æTîV¬ªí/¯¾¦ê²ZÍeu+Ƭ] #ç‹l´)çt»r08L%glù`]G‡Æ¯)§^ÕÖñ9¯LÆ®<¤µ.ErÂWÂi(NæÀa3~<¡Ë­$ÁNià9²R¶•üÝßý]>_}Ã’*ß96)ëY×Q';µú BRÂ!5µðªŠ“HÛ¤Š(,håW(+Å/É.M}Ku8•@²dˆ¼{ ~Xj"7ŒU#-\&µ¤ò“‘NA|ùäAä(ÈT9ñÄÓSQ!¼Ós! C3v‡¤A¼“ä çÃk£5~È·¾ýOªWîDÖ”0½¶êØ}„aL\°ënµUE-ƒ [‘ü‚Ê/ӟߣÛFŽ3À U‰°°¶[E¤²‚GÇ}ê:4ç9ä¯9nž®N ÷’YGNÌsž[ÁŽ‹$q~Ä€ú–€pÅH;‚"æ·ÏéZJ!AÞÙ*¬ÅVS;%m©Ç£¯ïPOLüV¾¬‡¤*«^6*Ž­±i‹JU].ðëdSÕ1ñQ)¬66¾¬Ú‚Øí€n k´Ïµ5 S¬ÂšZk*‹ÜjËÄÁž¶L¾•P—j‹(whŽè2}i ì¬àCŠhQ*†ä 6iAøâœ ’ñe_|w÷{ý=ûzÕº—"ÍMdíž$¬ ¬ 5U=È’Ú°Vl&²v¾›¬ Ç}Û7É8ZZÁ¤Xx„RÈùšºÙà ÖÍ/k Ù}[í[«ßÿi@„‰¬uSNm2 ÙtHÊrfél‡ãUURylð‚)á8T¶ð“7ZŽÂ]2[ø'2<ÀP.œégõå¼õ…¨ï1?àŸ`›‚Óqɲð֬ç?ÍU‰Ge}"Å÷X+eLµáõB>ž§_/‘îÞʃQ(ÐZк’ø­}2k"íX%C´5ß%î=¾{^P-C.K ¿Ë÷/ÿò/oÝùþÜ­ça¬w5G¤õ^t:ÚÊÒi¥¡ANÁýÞŠm RDŠlk:‹ÀÄìÔ¿Äâ¬EA«-æî|Ž*·+‘†¬H…øÃ^<~Ð9èåÉS‹A:2­»(RŒ/f…Ôîª!a=÷ŒÓ\ù††ÆAIä`Lm7-€í‘r«€{0÷µ»¬Ÿ.¾™­2rôÒT¤­Uª¬uƒ$É¥g´I̲ròm˜WÇà|©ñwZtìR˜oÑY¦YÕ‚9R¬Š(ÄáóŸ ùÁ‘÷8ü1ë^/-t|Š,neâðùœªŠ4¦Û^¹a£ £¤K§½ŽR†RʼnÊÊ’Á×·;#¾×¦-žÝ~µ€×g/[J” B*·L€{²vûþ ˜ dœüºT›*2”äSÂø™xx[q$¬ZÌL¦’9Ûªªœ6ŽBUÅ­,Zk'FBAÖ+ºãRâ@dÏ{ FtVeÐ":‘x¤ÝŸªIn:`˜f ˜I~…e•«,‰8X[UœHbÐKDaHÒé¡ÕÖmÚ÷ 0›A°Z„Å¥l™¬B%|0YäeùE8²:r0&,Z`ÛŒŒ•`TÀÄÙ¶Ÿ+pgÈѨmbøØm­ùJ1´¬ ³­/€­U­ˆï|غØ'Ø÷xÔ>ñVmë%þ3s"·:4Ǭ…¨ÄÛ‚e~õ?Øwà×ÿëÁáïXÓ¶” ÓZ_A>…üŽ @ÄD¶©*eK°KMx ¶˜ý=~‘R=—ùâ„ÔÑ–ÅVa„EæsBÂÐßY&ˆ“H½õ>WßV/3ç÷m ‹xò¬¶ÖpJ…QBç-ýzF Õb<˜QÊùpùª¢â°N£SÕE Úa$L€ß66k":OUü8m‘‹ˆ¿õÿŸvoxù`Öm7¤îœ3Ûm7‘M4mÅ9ŒƒÄêŸÇÑfäà‘â0]€½rY÷¼^8)Émþu’·îœ§Ç f]<'%eA¬‘,ßZG0J‚á\ëäm ÐñØJYÁDÜxþõ_ÿõ­»È}òakD9ÓQ»tNísR" U7¦×>_íVYqÊÝ™¶JÔŠÔ”#ÈÚJU;€­×N¤”¾lAJÓ¿ÿû¿ëÇ€”x`6šUÊÝ?äÑf«£î¶²Vf«ª”,p«Kfö4#Œ¶‘¥T4uÇR/YÛŒØÐF‚˜ Ö½8¼ç¡Èçdµ`ö—ìÛ¶6Ñs}f©R%Km TqleIµÍ^°û„ Šc|—Þ¹E([¡‹nvÛºÀóñTk«„qDv‚Y– Ü/:¦áæe¡Ù¿¥yVv©BNmãhF! ²,ý‚EžµÖîÆ^J¨îˆ~tëÞmy­Ï×:h­ °î¶œaž[Õ¶N²³šr÷›‰¤èÁÀͪp[)[Áuì¨kÊÇ^Ø 9X„áÃHñ™Z’’QÄ `œ›HÁº¤ÍZP#ÆO•5‹ß!Ûò·z"Þö¼µ(ëÆ—„ŸnÙ*C¦žt€Zæs ™°Hà­}L1§ÂÚY›VPßùî!F1œ²L6¿k +ƒl:‘ð[ Àa‹   ž6‘!E˜­µ¸µîIÁÁ8ùÏuqäâV†Á–xäº÷n„B‘tðYTî €/ˆ„ws;d“bCëp8²œH´pŒª²ª¤œ°xÚÛò£…a4£T_°Õ³ûÅ7³ÿøÿ Ízq ¢;Iâœ"fL$ "L¾›ÌÈÅ©6Çün÷jw…Õ·m¤8fd0V%8ù 'ÃYÜ!̉Ù*B-pÙÎÊVJ¤ø_ã_»èz±äéÅ'†“ßµKpq«qÊf›¼HÌÏ@Þ,‚”­;ÊVªá[wVuV.€°³ÒÀª‹x&Ë™%/‚²|Žx„"~ Îbøpíˆ×šrœjEÌ›rÛ44¬ì”s¤ÀÜœ¶îÄø¬YÀ*„äØã,²­•)ÏÙªãξøb«c)>ͲñÈò3…Íl¯»ªlYY…L¡” +ëÆ(ëîÚ„}èø¼B˜.Œ£#눴sÂä‰P%ke„5‹À,Y[RWBLñK|x1L6¿ÖVÁ£ã¾ÜB¶­€*%V„˜)ôWÿߺKñû¼‹ÜD^’fÑ˼.Î?I b¥ª)Ä»"J€½kªÉð¨œOÓArT‰ð¥ ÜÔðº[E˜Ç)|ÁѦMœàjµÖÑiø9­?\ýÔ9]Xl9:ÎÄù„ Ls£™NÖ,I6°-Ìe=´ó9&Užé0ñà/ÂçxJ7oª¢åãä[1¨m[ÄØšø¶|×âóÿ›ž?E6´޼¾â&Å7c€"E)[Yú³|k7µœÀØvD‚¶­jùð’²9|N¾ìĈäGÆ´8,·ŒC¶Ú‚q(+b/ÞÔÖ²cP¨*f.ÛzU¥dU!(,ޝÄá+I þ5‚çGËÑÈfŽÛLyAø0²|qµ‘ò0»·m9_ßÚwmB{d¸A%XZ®D¤2Yu•o›/Îa8ÅkY¿ÖRªr¬83¾x…|xå"½–ø`²âl8”ë%+oB~¯:<¦`kWmòò«Qž/Îà3¾xÝE8Ö+äœlȶOm0‡åÖ*_ß8„ «0ð-:—­ ß:* RŒÃ¤¬Ä»š8I±e0fo‹DNƒØ ùÑK¶F8Ç,¢Üƒþ­ÿ‹ òû·sÕ®ê¯=TéåÎÔ:åÞGʼn´J„iŠ0"IÝ>Ë «‹Ž ƒÕ-¤œ)9åEàmùm­ eÑ&£¸`Ì‘(ÑK°l-¤^4-˜æzéë0m;OÙNL„ÃÏ‘‚w ;çr¯µ8Íá{ˆ»è8«€Œ ¬rA¾8aRÀ¶L6Zk>$Ç: |©0|VB„†âÀ ³-U/þEE?LCkF€— “ít$›0Û¤Ú*é§AYlx|©¤a:4%`  #çïpdÕVÈ/ÞZ/~Ûz…‘*¿ “´â‘êxɵ²ªêb«6yu¬†o­ŒfïOï~ú÷3¿± zÑ£K³è•k·=ñ,…MMUŸõ9ʇtù ‹p€qÆ(þÒT‹ö™©/ #×Ýï§½õÝn]ÜK¾pZ˜¿¾‰¡lY7§`)UÄ0UîFÁ0i¯<¤ÕõŠÁƒýÅñëaºhA1Ìåáœö÷vÍH'§¤ŠÉ:ÈjŸ<+é4ޏ3é*˜ÔȦ“eRÀRyTϔֶÚå¨äÝ™ëX-ðçN×÷8öÓ½òã·ås:¶¦ ¯c$)'ßšTq˜`¼·:_róÏßßÑíĺaÔŠT-ð὜"kN‡Ðú b¦e;@Åvµ¨ž½Äm j2pMe׋CsüF«¯ˆ{éŒ÷ýüTØŒÝcÅ)dx¬µ[G "Öµ›/ž£]‚óÞ!ëNKFø£zÎ""E½õPÅ€ÏS#V!e.(R)¦XPýdÙVâd!E 0ˆ(çØ®1‡9,¦?«ŠpžŽø‰c¨m ”­…^²,’¶SURal1( ƒ`¦ R;Žã0œ,ޏîâ5½Ø3¾ãtº„IC·&_ÓÎ&¶†3F‹u±\|²EÒP ñjªµ ]úPRjÌ)Á ÆIRüñ‹7»Õu„xñWÿûAvMõê4g%h5‘»Î16ÁÄT¥„‰—¢³¹º(‚‘lLA[oBœÍ›Õ3ˆ˜5;§ìs­ÖÊjU‹ð¯ôíÿ+êˆáh§µ#²Õ”ÿl+nÍ‘âXgØîXYÊE°õ:©.Dµz9A0`Hñî[ñzáç@:ùz­ïéw R”ƒg¶@lk]Gþñÿq#|èøôßDzê…sçiü{M™ˆ­#ðDr¦P­ªÎJÐ\Ö’rµ‚1G(hke;©‚ðL*ðdˆ”zfk¡pÌ•<ÁR"ª8‘°&;Íü`.GW­3‰ òw?ý“Ô/ÿh]GiíCFâ;ÿ͵yÓ&.Òg"‘t‹r”«5?~%ñ´ÎlsRÂÇž¿YÌ^>/>0‘ûnS«µYDôbdغ^â†ÊÙ,$9ÉîÉeÕîÊ6)æqŠð*w²3få#׋“A[Gm鈬¤|ñ<|ñeëÛÿzѠצàw:2X™”—¹A¶ x§$’³ZÈÊ­†² i(«‚`·Pµ”8®íØrð¨M-‡¡Mõ‰Ó–_^-þk+…^MÚ)s<]>8ReC:ÉTQ/Ʊ Ù&³ëÕËÍQ3ÃâQ"Ÿ£*¶|´?fOá`ˆT5©.k-¤°vìº7—>BU|FXJ$ÀÖ¶8ê©‘ˆ­rÌŒcLÖÖ]Á‡aJ ‘K5xíªV+Ùΰ^.ý`"â4à·¥­Bü)‰Á*BƒÈs €âí• Ÿ 4.q+jH>Ç–£>ßrÒmÓ]'Û&ïbˆdâØ˜-¿mkµR±q,žã9÷èÕÒÉ7ë6Eœj™,0ǰV%¶É°MC[UxDð¨êp8JBÆ3† :n+ÃS–¤k&° bƒ‰­‹Ä/˜†Ãò—&žæ+iÀŠfä‰×È Ø²5U¨Ê‹FЛS„ÏÑÄ™¸rÖ9 á‹¿ø?ýõgú‡}¾N5ˆoõuÕøÞftïÜD’‘þçzÆûþõòÌE¹‡Iî'c#svÃÇp“_÷¡*]ªåHñ8|ÛEŠoŸà`=†yËñïÿk‡°^®N¾ŽÆÏ·Ò¬`‘J m3lN؃Ɩߤ8Õî«÷nYoäòñ¸p!ùnfÁ.\)…¶ZÇÀƒÖk*û€•€f혅ò¡Â_^}P_cê¥ë¯;%‚Éî )/"èîà@'ß= ËT‚–¯ó`Š0þ! )(¥ÐÔià‡ `+.¹4‡§ˆ.|}Ÿ…aâ¬Äš…o:UN[Ü µS©PëºØ¾þéß7,5­14˜½ÓkëætÚÝ`Én&Ì3ÄÈ]‚^Œ—¡¤øÖZt°"wV²!2Û¬³âë˜P¹Õ êÅ»Zø×®F¦¹¾õ²ö¨4  RÖÉ@ÒfüC¦³sw˜R·Úª‘EÕm¬‘lBâ„dR±YUÕX ‰¬|q[×ÌoþxÙ®êsg:‚¦§Á]ÎâümÉWØ¡=1¦ÃPœÃT52GœÏøÎÊù;.ŽH)q%ï@0¡ÇYé¬×TÙĤxbr>ÿQ§/QÑs§9Oƒº4E§GƒAh“b⪌–ògŠ {â{p0qUV¾«íq³' Ñ4gqÝ[‡ä§Š£ã0œ| :ö“‡”‹T…¯*Bx}ië €¹d_ço©G<˜µ+b(UØÄÓiËW(ŽdDL<Øh¥X «‚ô:ŠŠÏ¤ êb+ËÑB\G¾ÃÌ´óÈ]úuç)kͳµ‚ª4 –Øù @*éùjX]­j!e5Æ2´ñ¯]å± *d Ê ÎH v0»e¥Ì¯¿H˜4Ûrà­²`§Ç=Z¨å¬©TxA…¶O¼¸ªh9 +¥`ÅÐûŒ8ƒ!O•íRekÍo›ÓZʪpÝÝÊê"•þekÚø²ÀV–Â|+~HµVÛFóÃ[nÅ"}$×¹s ^;ú» ¶i³B–%Ì ‘R¶‘XÀÄãät2¥7£HÃZyu„ÌRÀ|+Zq+&ø­,QÇV¯-´c"95µ-=¤Ê6$'ƒÙá8:YVƒ¹w5O`%"¥vó¸±E0HimV…pÁ±Éf²´ñ¥ø ™îE†—Ê´׎/軪ï~eåkªdJt!24ròÃïù#•…T%…ªrNw¦3TÀ4u+ªE8¶‚R_Ðj ÀÐZËÒÆøì&Ï=IÛ²ÖR² ®‘H~)+ZH$¥4u¡m])Ó¹"†ù玛Üñ$F;}ua"=7¬gæ{Ï‹SµÖð^}xˆƒ ²¦¶vósªÂÜ•i|½2å;„u‘S†Ïdûô¯dȃxf¦Ü¶5¸-Ÿ€n¶5µ=ÓÞ©î«,°1]5ë‹„rw»“äwÛG £W©m•×.U¶‚²ºè ìë·þ½>Z¦Ó(U":2ò(g”°‹=S3Ûdw¶À¶V.… L•TŽF‚îyÛµãkUV÷ÞUqÞª4ž“¥’ñ­âz•µå·~þÿÛñRrø½‘㌶vºPN¤Á‹”ÏTqºÂDÒ!4uúÙ ƒˆBŽCƒ×½Úî:Y…EªM›FÀ¬ÖOÀŸ€'  ¾ÈÑÊ6Z°Öx ëÉ®ÝÄi‹-,ñR|$^8œ¤ëÌ™Huç$/ m³­"RŽÑ›¤ÚâµëxS )«cHk²Þ?LzÎ @ D{i•)—Ƶš5à@Š+$¢¸ˆ­rq ât$ÅV¶Û¥ÏÚU‰kŽ̨ø¥ðç(aBÖÚ*®E<Öµ«8 ‡f~åáùƒá!#Z§Z˜²õ¬|%œÆ)’N«ŽÎUŽvgMç«SÂlÿ; 0LŽÚð8›‘'§#ªK÷Öóû¸#„7Z×OâùŸÿb"Ýi~ù'ߪ~ævb£H˜]Ü"»`tb€Ï`lKaã˜b×K æÙ: À‘/e[DJ0fþ,…aZEhHÉ»ŸS‘ʽ¹ŽŽ‹JGYkR™L'#nËW ÀªÄùtV1(éBxŽˆ+ñŠæØJE˜ÜMÒ—úØÈ35˜“—K$%âEpòN+0»ã/ÞP¶ü”~›üyé'*È; ÎS…ŒÚ>Êt¿¹“î@`”ó!•ËÒ,RÜ–#+å|¬`5â3þs[¦³å°0VÌÖŽeYN#~n0å“•BUÓÆ±Í¤`ºLá‹pËþð‡'ò»â£ÿún7N]HmœT58Ý´€Ó‡3ÁN¾Zÿ›WͤբŽÄÝh‚L S^Ü Åa8!wÈÁJòEôòk²ýèþ²xß1i:«^L¯‘üf·Ny‘AòÅe¼1E¼#Øs¢rYû¦€×µ­”Õ™+á3x²m‘·ŠCF(ØMò·û·â9ÓG;ÿ:\ ˆI!:ŽŽº[{¡Éò‹˜+‘g†ï§&5Q5š¸­u1;Œ“åK5Q°ú†ov+|µÝrÖYY­['É63ˇÿdÂtVd¬¯.™i •ÙZÁº|7v‚ eu¤xDo ¶a‹ ‹ŠSkŒ¬ÖðЩ³²Á¶í¬„i­{)HŽ9ÃcU§€ã¯¼`œÖªÊÖÑ8‚N¦ U\°µ)Ô€¹ItŒÍs)G¼O_ªÊg"©â ¢ò›t*·•UR;~°Þjem­ ™‹BX’èìªáùú\î@!šO«­~DâXøV>«½$_=íãKÿñË*dt8º é¶Fë’¥`à$‰S¤Ó¶¹`˜ˆ-Fa&È ¦©T«8s]Dt·º Æ÷#£.&ް¾iƉøR" §Uaq«ˆß!~ëúKOæ €nxí(´ê5©ðµîõb.@|"9xøNÀíÍzЉˆC6‚U¡yá²¾t|¿ZmeÕZ³ù‘TÐZpN%Hž9Œ Uc–G"UNx$ ¡wPŸt;Ê_YýÃ_¥.éIFš“¡içI†31ÇÚ}î’)±Ò»ï"± *ü/‡-ÕD‰QÂø‚²Ö 9¥:¿ùóîkß?u5…y]Žvøu¤a}MaK›H~N‘f镳|f§*õ¤  “áˆl«Ä¨=]ß3¿ÿC*Í^nuŒ›ÏÌ+›¿8 )$IJ|NS+ß§4[MÜgžÏAòÁX•gÕòGU-æÖ%PY÷­ÿiq.…¯ã,;ªø^rOªWüÄújZ_«éLšQèâê5åR½e Sní48!9M„ÏâÉ·Š{(¬£¬×få 9NF–Ó¶.OJ¤bc¨;g&ÂÓ7þßýâzù$\ âµKI‘V)²‹ó è*›Ý9Àd^&žÚLЦ…ìÊáµhœº7f°g\Ub‚=×Ú‰Ào ‰•!¯?‚õMO„R1MÜ…V-|×:˜µË1ýÕ~¾ìÿû‹¶‰8N_ßI$²K6…‡ï+Oâ†Qe ¬ FÄêaóºâxî5 m%À ¥ÊÖµU!Ÿ<ÆaZøyÈ+OËšÖȯphªE¯Ù^àtj­#Œl¯»´¿a¥6µT†Gܵj™*äF‹ÀgÎïOÿ8!ÅÌÄ­ØŠ£ÚIb{ý@ôõ‘kAC sÄŸ˜îÞ¶7|æu&`"dÏéègÞß;"+°ªãás´S[Ê-äÞë$C–êpøx:Û²V&ˆD€-ÿ†¹^}øÓÎ?þñªÖVäÚáϯˆ^F‰­‰`¦NGduh"R>áÁ¤Am¬‚8ñç§•”•5fµe•Ä`›Ù6ãØëÞâ£ÖÝ•åHÅSŸcÍY…â™”Z‘²‘&òDûüÏ#Çìß!á\‹+HÞÓ©j‘&%XdÁ|kqT]AŽHÌ"úvòÚ2„qޤì¶q¶vD‰Dë.²:sþ0¶µFâÕ[ŽïŒºÄµÃ©R%øŒËnK'Uj™;Äýï@¼ÒÝÌ‘Àü?ÚîfÉ‘ëfÂðExãp8Âòý_“-k$ï¼óþ{ª^2U{$«IG8‰D8Uüi6§Å®¹C€¬h«íJ4¸S:p²Æ-ýÐ=oo4¹pˆºÈ¶¬)¬9gÆñ”Gï>üïþ=(á@¬«GWÀJ«©+«Pƒ6!ÄÖÔ48šé„ŒG†p0«ÂaǴ磯Y Ÿ³è•&ý¿eäÎPŒ#%œÏÔ½–b1­EÕeñó…8]Ó8e™Ë[“?›$þMóu=è_E…š]Ýz+A@sÚ¸[ºG¥­\¸-N’ˆP_[FÊ¡Dd:.š?³º¶œmë3ÿB5ù®Õ&ÝQúq!˜rV=¸?zVˆSoÚ0rͬOÑŽÎo‚ÆgC]ï¡ M!G­t”È¡¦V Èò…½ïñ4è¡Í«hNm5Ð\ÆäC24ç¦OxHN‰ÄD˜¶ÈhqlI1!&¥¬€¢&…{jí4H¹p‰| Ër9~A·SþsëþóŸëAuóÔŒõâ¸ùu»®€êvƒÅ4;(TÛ5c ï<‡‹ „H·¦cu/‘eÝÜÄÑ®‚YN`‚­tŽšO§+ˆÉg@ˆ”.¨ŠÊu h)T%}%8OdÇK@IDATÝR( ¿œ™Vi\?åÚz½£À„4Bj‰È=û=NUÅëÉPjå!3ššL6M²@‚D 8ùõpÜú’Ix´ËäHh‹AH2ľVÛ¢Õî”w|Ô&Y8qˆß'Ò¯¶DÑ| "¿-} Ègá@‚ÌXogêM³E3  UÎz¯ YNÖÌŒ{V¥© ý8²Áʯ‚mu´­:§ºh%6 >AŒ8…h8i&˯ºÄ ÑØÀdœ|å ÂWˆ2?…Ò!h¢ Ç6#-¾5gRŸß„¿¸z÷ß/š•&Ûª=¦ædz^¸êHë ‡[>ZQëCJ³tþ|„£äyþõ2Á9 Ú"§/}…ò¬(¿óÄOÓDS{—ã }Eiò™NX­ZU×É*jõzÚBnuˆX«Òk˜ÂœI!L9°*¶Ä΃%HVÈ*¤Êøéth|Ìn]U€ÑÊ"Õ#«~¨iù{|Õ„x穦´¢V-5ÅŽ±ášê°öÚnd¸¨÷f÷¨Ì¡Œlj4Ýê‰U:k‹¼-d[`>UÒvÑ9KäìYh£¥`Õ3£Y›Koúìîí4ŒÙŸJ¾ë¢“«yZöá®ÒPEµZõ¶ñs„$Ö¨mˆ3ïy†_ÜOfÇ)‹#‘5°ÙádRl;dÑÆ/Sné~"zû/ý:Uìb)­+¥ÖŽ×,çVçn|8'ñq—A‚hk Ž£zkË©4‚®Ü9;Ýz¨b !üå/yûe¶JsÔb5`[ÃãÞ^¾µ¦ø‰PÔêxE=NùÍeÛ,ümù5@‡9´ßUÊøs"ÖÑmkÖñÛâÝ …?±šÂ¿QH{UÉß@²Uç‹¶VK„ÙÂYxà²Lw áD(ËJÇê`Ñ:½Cë|(Á~'æfFîfÃwþ1VŽ/¥‰ø)ª¡Öåè…¦« G"©VRÀVN?È9@4`w‡ŸÒŠÌàãˆzÏá¿b?ÿüs_êUK“¤ÈjàZÔ,L”Õ§öðùßlÓUˆ–Z4RUQ!¿ê“•Ûiˆò³ÒC’Õ'µÄSàCàŽ“C“?ÈÛ_ü¼³1Žª[“+׉­6lk£Uˆ¹o»«ù5ÌAà'r?ƒã¿p3v¯rpŠÂ‹ÊÍQ”ƒSo˜L‡ÚÖ‚-¾6\”¶r;Û8ÀO$ÐO¡Èùï]Ý–µD_'­JÔÛÃŒ¶µ³Nø++sÔ}Äà v{`<Û8óžÇ%˜Ÿ2~ÊmѪˆl+˶µmHÍCT‡ª¢P[ ÅQŽB¹¢‰®£n¼Ð÷{÷Oߟ*7×YogÙÛÓ”­kR{ŒÌšHÛ½IÕ¹/µz¼PºßpÌžB²†¢'‚fR«rÍ…DæÃ1­&ÝŠ/Äñaíÿw¿Mmõñ?}Ö‹ &kC'½ZÕ?¤¬|ëÐ ï:^£óé3·Ù0B¼y)Pò¥Û 9X[/²Wo¶ yÿú=þ/(J{÷ïÀë­©­¬¶ó[sÃ.SÿD˜í˜ÙisÔâØv˜RÐÊb8SÈÕ‰ãL‹O¤Zhœ­EË…{”ýéOŠùĪ¥ô+Á¯mNµ8šY´­>=5Ã[…ʲmÍá3QÓvÎuRé¶dkL«PwroÕ:4Ǩ[R¢«U:…@Žt† ÔÚ{wtwf™ˆ>µnàhÍ(«y‰L_i|…ˆØŠJd¶GÉûÔL·u5<¾ºú)]McqÆä0¡‰Z’’UÖ†DUÈ?û:®KE%ŠÂ½õ„/ÄŽ7+þCB=iü 8ˆÒ8ÆFå³RbÖ?B…©W˜‡È5¼”¢¶£'‹\ÅpÔ•ç×0Gu¶#V4>Ι}{F®EKçÔ Ž|âr‰èÁ-¸ê.¿6–( ­êVâÆ²ÅI‡“us«Ë(§ÐŽ™”*ú©4P Q §ž½È)ÄOв\œ˜¶ùB@L~…â$.¡ºúokÅ÷ÍŸœzeõ^Ÿê5ˆ¶)DŒ¬-«.§C(ÍŠbú_“‡ÄýgEcJqàV‚­ÑÊŤÀ–"‹oÍAãq*—#*+~ÎÒéCzDpàjU.0YéȃpÒOAй?þ#lÍHA{Ñ|c”éTggÇós²¤£‚èg+¸ÛLÈy]Õ¼×#Lx| ² ©’?gü{üv}{t¯¥ïôîßWÿu¨×¢qªË‡èMu«½¤Óë „F–r5!+AN#szs-hVȪŠ׌\=àw‡0÷ÉûÿÒæ¹vò)ߪ¦ƒhO3Ú+j«Ï)ëªPL[„¡uWX;Ê@÷O8¹h:ÝZðÎG”S?p~ÏBº²LA®‚Àäúèíý¬ÿ¯ýËû?£‘µJ'[ +Ò¶[È6²)¤Á‹=ÝÓK ‰3ý8dSŽ#ʑճDgHG‡ŽÑ±ØZý¸î ñÞ]J‡¹ö$ÖaU¬!hÄ¥W.]hBÄ-j®ÊY!8z˜‡NRp„ŠÆ)±Ü­B|¡æMJKtâ¨Ë™l >3…­Ò,štNt,|lœ:áK¤PºÁíW.5ˆ~Ž2êÏê -ÿ(~S$­Ì*Éç¨Ìd!C83ˆÜ8‘…¼þõo‹õÓš+ªÙ%T‚s*"Ä$ÚŠ qÚAE å&5rR’+*ĤÐéžàØ^ñiJ‰Œ‰ÆW‘š“mØk·|–T­†XmáRꄟïœ|[Vó1Û"ûˆË,¬ºǰj¡Ðù ñEõŸ?¼Òüºò Ä[þî§·þž¯ eýÔ¼¢Z²Õ<Çj tDîTHq"‹2),_"MÆaEÍ¥¹DFî(p©1>ruù!R8ùUHÄäX™(qÑ#,‘S¢rÞ¸zŠt ¨eŽqtÅQQaŽhL+Có®×Ú±t]t"I5f|k ­Ä9Švæ*ÊÂùŒ_.Ÿ2NU"H?Y·W&L„‘É–’¦‡_¤`ÖI%^Y=¥:‡ºâ+½mBD¢–uÓÕ¡mý”bMPnáxЙ«Š¾Ä8ŠV×Ó‹[«ÓÄÁᇭ¥:‰_9~Ç"—²ÃW()Î!q·&RS̓T¼,âzŽæß`||çk¯|TYŸV÷€ÿ±«ºu¢™É5P´©[ãwÆÁ¤†Y Ðû ÛÎSˆ#ËJŠédÌnËÂmç‡à¯±¾ õ=>ûwQü5¤ÆÔÓ5šD{×­Y˜P~ ÛºŽ8æ4HÑI0PÿˆôV‡éŠoÌ8*âw‡@DÝ®iªk«„ržêýˆøpŸÄÿûå$òœõq’\uµ:œ¤š‚¯1­ m^ÍkUÈt žBœÐjdEL™©"WTHn‡ Ç¡,]ÈÓɨ®­•/”¸”Ùz{@< ¤ ü¬ãOèºç Âj‰‚Z+§#¬g4L+Ð8UÄ‚pêŽô8×3+«‚n ÇäC„¬©IÉ2RîX÷sò¥K!‹,š>d¹,A«¨??P( á SSïzÙÊŠ,‹%ÎAh­?ëƒEÀ/eQ)\¡ã¾9ïÎjYøhê¢ñ­Z²6/§¨•H‚r;±…R“®§£©DúåÚo¶=¶»“ÄrªdË©û: Äò…Brà©Iqë!|kÃ'§D«Jwåh"/d+X{rW±d1¸q¬9 œ#Þ^çd©’ñ…òk/_iN!œ¶€ qG kÕ­¶¦Cf|‰hR¬¶­BMaË/ýH8ñ¤ªá°Z"Ò³§P‚´uOÛJo ¡¬4„c —n{m²­\>åºJêZÝé-ÿàÒ“¾_DVW-éGoÞÒuctP:W½ÃAn[opÝò·åtJ˜9D8Œc¨.JQš•pW𣥠Šà )ºU]~Õç`²š´2 ¤mËÂßKï_wŒvÖ¿=ú¡;´žLµ±†µ‡Àœ ÜÕwMí@¨a¶â”ÒVÅÎ-Í«2GźzÈ­n¡8:ÌÆœS'Úà08Cö9âÇ·V^þ?‚¥|võ£©µêLŒÓëDˆ­~¬ 7/ ×'f"­ÚvŒÑda:m‰p÷<¤ ±ÅDë!lË<.ô9 nš Ž”ë˜pBàX#@8¢k`éBÄ!Vf‹`–>“Ó¶,!|Æ÷“˜OsÙêÑmðUþ„ã».×{H‡è¡>­9ßµpt!¢%¡ÈkgʬÁô»î|¸ÜÒãCá`Ò„—ëC¿ëX­­ÞÆmRÕ ¥t]ݧ´uƒºˆÞ ¹±!Ò›=ší±­{Ó–H#“ ©|¢Ã‹lõKã‡ñqÃO?ýôâGÚJg³Šj‰í|ê ¡1YŸ·´ó²Fp‡È-T¢­ÄÖêåbKÐI»¯€NÕ–™K¨ÜÜ{*[‰ãˆ)“žå[ñïØñ_ˆ|å'j¯¹~q¤Îg'Óhð=f¸¿C«ÿºªùæ‚0´ùfYÃqlj¡¨©—q¥¬øl-Aœª#* .Å¡¹Uª4Gb:GÓg9ä!®8“’ˆ¾¬ºjÈQγO¶j%¯J4>$§&Ûò³B@V?%ª.„) éi§þ˜Òå9ˆÃD0KCÅAà$A #[q8ŽÐqåšÐž#up|$kŠVLÅ ˜üz•MhLé5ÍAcB*nË$2Q­[B8ón ¼Z1ùgêíL” B§ËY ! h|“ÎO'°ðŽŸ&ŽPkçÈg˜•FæOÊ!àc.ZQ«ÈÌ–ÉÂÄoËaëSQäÀrûMH XEY˜p`Õá®lÊN† IˆNÐj#q)¨Y™wÿ5&ú´ù¯ujŠZõÖµöð®O ¨Ø [µô ÄÒ!¸F0ÁÊ)7£\ ß¼8 µ¢£5ZQ"Rš1©‡yÑð)8UÊLVUt%E!ŽPÛ©×·®>Õ몊ÇAܯ»g7œ&jÞ\Òm@ Ø çÐ)—ßMZÅBŠŠ²rєȱÅßÚ³­m…„p¢Å!$Œãó‡w8î(åŽòï0/ኺ¦Î­»Ô6³uP|uÎNÅV·LH“ Âw'xÓÀÁÁ#dË7TRmK·*ÁМ^‚È=@HuE:ˆms+#Z­kÅô‘NÌ]¡IåàªYV ­D»ÉcB¤û7Ž¨Ò­d}µÏ»±¿ÿýïWü9ŸŽ‰k‚–¬µ·mÊõ©z[NÖµˆ,èHm‰‚”’¸U( q¶&°Äj‰2 (_«Þý?üG÷–ûÓïúœI «X룷¢Ö¢œ@QfëAGÄà:Çá„ï(pòán`…ôçavéD ¡Ÿõbï¨Ý!ým(²3œ¯_¿Ró+å¯8NFi‚ë\AopT«¶­9B Ç#T!‡ÄcÐP¶‰k „ıE3¯¢¤ðm£©"‹ÕÜj›:2OPTŠo<ÞãŸþ¯WIÏd7©~jI‰£•óÅ‘.²> b:L lÝ hˆ• X¿mµàÒù”ã 9(wÔpšV?+YEEáz:rl™ê²­,"Ö®` Üø. d «Ã”ù:)WÈ)%ÂÉ=æ²íªñY h“âÔÀ ‘+E‰ž*ªÿ8á)Àe9fÍ—Âçtìüš¬䤌VËr"GnËT¹=lV¦¬¨xkˆ_G«žD¾z¢LT"ƒB;kÝ^øÕÚ %J‰iK°r˜œ|ë)|[l£µo ‘†wá…øŒCVÅŠÚ¦‰ÌQ¥Î 2Ñšt·…¤àæèNÊbES«„DšÔ8V ­·¶{ú€§ÃIŸÙžò¿.áöB®nü@iÏíE§q8:/AJcâóq¬³¥oËèˆ!éøæOwð¯=}Þs€ý1ïd+äáj«–—%¯7Jw8@¦œÈÕ0Òœî“V|‚|ÎÒ³@à y!Äq>Zn[šLV–fk]Áçð+ÇYÛ)\e•þøqiúO¯úgÒ»â')µ”Ö!œ™Ýáwt¦¨7LQ8΀֎݊@ ˆÐ¼!B¬k‘85'À—H‡PKOúí =_ô(y¾õ´VšlüVšã3þg¦¯“½ø§ñª¸º¦¨Ž6ôé­;¥£é³a)œÎ¤µÓî´á‘9Z)©„•B¡Zp§´(g_u ŸT?ä H)@Hx%„ÚF°Å‡vM1õØñ÷—àX«¬¾düâ*™æ/¿ü¢²æ½v×ÏW~Ó5²ëhk"«AtîQ3…Ä·MÍʪè<å†ä\gOV!? >|ªíqç}ËMî§µam"mWÚ¶¬ÚëÜ„l…Ä*äfîÛ Ýç¢Ñ0XRÉÚJ™Â±EsV§´#êÄñÿÏþózæ8÷ YÕ=á_COûýÿ¿ŽÖïÏ6¤vÉâÒ›‘ñçðËBC°vÀ7cç ‘#JR:øUé4D£3ˆ“qï! IÄ–Sé…jÆŽ_è¯jùMKÕO…´¡7² ´mŠÚ’ º^@¯ÅÝððea2Û­9Iñ»CÅá¼b{Þ'¢zRzèB8(@¸¢¦ÐFI½ñÝKÝNF`|Lxƒ'Õõ¿é„ VjVœŽÈNaI)!K'W°Ä¥ á±2dâõc–:œ Y´Ò«ò–U!:J3˜~ÍÀ5oRC¹ÀÚÀäH÷,ìÁ‚P‡shò7òœŒ¦ƒí(0)B‰[¥éÂ!ìU?¼6æïÐÊ¥â±üñÝ¿_mûRŽ—–Zzqí©yÝBŒ`ËêD˜ž&Õ­­t+~+'«Ðtl6ÇýSERq’‘E<ª E"XC0¯„ô!Ä­] åªYé@è˜=M[¸•õ ·Û¶¢yWWçoù.–?ü¯7Uôcu³Y=ÊL§¢ÒV}Ö§m½¹†F‡yŒX1;ÿ3Bj9­¢høt’jê!«Äøx³ë‘õã?þðÃÒ+«ÑI…è4ìn†NC´~¬ììúöä"Ó\¡Av†ÖN 9ùøõ`Íi(8‚mIq¤ø±çá@<õ~T mŽ6j²†k2ßz4}Zm·Õ§gQ:XtÌÂ;– ¢.AEËÊG(­S%ÈaÝ?h•®–5åá?R>ýâ«OÜR³NÎו~å@¶ÝP@äúÔ¶­ïVL!Ùcªûóφ¢V L—Ëï ñwž:zlvD;Ìú´Â!rõ ‘T]Õ'œé NÏr˜= )]V}–äÔ›\– Ü4Y"q¡²¬¥|ÅóáÈ"ó>åýµ!4]Õªt[¸tµD™eÇZVŸz;4Y©ñ+Š&ÈJ”uû®¶´fŽZá£Úi¶þ›tù„€Trø´¦+†,ÊhÂ0Ý]rM¼-™ˆ­ô|Lvˆžþú‘âb[»üž_Ðl‰°3éØÊ’’¬-<„aºu¸œÊ•8˜pYgÆQ¥&9Y%dyǃ©+8x£ÙV¢*®w) nò‘µÍº#‹J¤Ïê$A⶘•Ã, w}“ròœšÑž–"Ëê Ú†øç㯪ÿñU]ïT©úu®¢m®OÖ£±¡ŽÙΫÐÝbkÝfrËÒí.Y')¥óŒÐ±@ö°á3‰D8”+}L~·ZÍyX±ô/J|R8p[Æ·Úv>ˆ¼²õ»ïJwášÑ¼ŠZ)w¼æ2u~cŠÚÂs€kÍܧ?5²ÇT÷’ã¢tc£‘ãÑMÖ–¿Ùåæà­«UÅ*Ê_Šs{ø`U–›Ê˲öÔÒ|b5‹ö$¶Öv³«ÒZ{uX¡Fhv‰ÑÊå‹¢õˆ_n¡Ñl•f¥?LG„!™ˆhRÈÀ¤ Ò âŠÇ͉¡é³õSÖ˜&Úšäg8þ)çÃ÷[ÐztsäúWÃÒŸ[=ºýÛ_õ0'«gÕ©é„cÕ?§ÑÖ$îÎä{Etó8‚¥×êO¶VOÛÃb+%þõ‰±ëXõÒ}JòñÍî?ÿùOßÞ~×DEýT]ÿNF‡¨?kú˜Úi8«‰H‘ß9# «Åê¬*/¥rhÈñ1ó)óÇ¡þ}ý¼å¯Éi£ïÿÔ¶qšhMjÉ¢™í·c^ [MÁ‹->ŸÑhå9®¦©•b ´ Qe¾P‚)W4?q ôK iõÒìŸ<%ûÄê5W•cŒû[—åšEñzØ‚Üh5ÖÁ– 1WjE°Áåæ äè®°²R8µÑMßù¥0]åÈ•HJhã@äºR$F& ÄGn(>P">§~** ¯7[¸Š È%b…¬t-9V´q6ìF  gÈ­ÿDЪºÔBFæ—Z–¬þùtEÃ"ǧæU`Uä*QÅúŸ§òœ#¶=9+ž¢ŠrÖŠ¨-ÂꀃÉÒå´Õœ¨”jÁ{Oœfj…Ø2[&Ë:0'$ýƒt?\YøÝômñK©ÿ|-MöŒƒ¤!A4¸Ñ˜s Ö,N ‚Zä@+‚,U$–ž¦ñ9¹œŒß]ˆÏ¯NV-L[«\‡™‚lY/íS ˆßv:ÀéÕ¤ÎSÓ[‚V ¦Õ1ú] O¯Nì矮¥5“¾­rV#Xu¥™š´5¤DÏá@¡:B$ÁnÚ²„ Âäò­U±†È-=Gà ÿ¡mjDòãó‘w’Ý-BÈ@Q¾•µÍ˺kšr‡£½:œ£–2GV½iÕ¤km‰@¾•É¢ÏøV´Èºv¤èNµZÈWÇu” ñ„ƒ©éNï¬óÿN ‡I—â&¬®mÖ›ÎÚx×G‰”½™Ð•fœL§Çáèg}­C½1ˆÕ,œ„,¤3eáB4!¤ø¢Ý?JKâ–o»ê™­Kü¤è $"%)|` À¶Ñõ3ØÇ?÷Ù…0¯¶¥¿åºø´›”6\_«´Íç°ÎVoµ·•SÛùüé¸Ó ¦*›ô¾¿ ¯`[L {¼ÀIUè›_tñQ·¨ ¬/ZR?0…Ófsi£»‹Ïô³öj^·zºdéV‡Ãʉ€IаQkW’TUÎFŽ×G¹V¦ïþ~bWÔ/CD=ð{ì[Oú«‹/Е“QZ̹Ze²8VbÒc0_®dÛt0ù8å¬Bǧ)‹š“ò[M.½ƒ¥ŒÕªƒõÍF„¶Ÿ]ýj´ ]i:z®UÚj£Ò¶œfç#`2=Ôm!±6?)ëNc‡&££y+Ÿ œU’ãIÞ×uøŸ¦Óƒ I±%ÒÉC˜­nëЖ¿BÉî*À›Q þr]޳cQHVÕ­rUWî¨tÞ éG ÃâW‡HÑ3ãXJA‹Q“Ïç—_Q𢶸¶¥ sÝsönx4éªäı 4WœDƒÜ®*Ôeh*[Ž2H3êª ä@¬À ‰o€4m{ tL˜5Tsø¥ØVŽ#¥U¹3"D³E;MšWf…ÊZ®ô q\uxŽ—4os?~9[ÏÎ×— YͨéÌ©‡†JÖ*ʈXë¡PRtd±F(Äç˜Ec™Ü9|%¤£I¿ö Ä$vÓˆîK·Ê58¦®âX!ÆÔ æ¡r¿¦ô•{å ¨Òžƒ¼ûoê ÑW ^iN6—Uo@k~4n–5Œ†ƒ œ G‰Vté¥XFQ«ʲ A…œúá×y`'†_Vç&ÔU Rðøï]/AUè7¬bÍá éÅ´æÔ_ó'v{Ž.±AÊâÇ9UGAGÞ]Ç"¸£8V-)"8iâ!Úpb ¡B¢Bþœh®Oÿ¬m½½ë£Dâ4+ÍçhÒt@ h¦q¬lƒÔòz+3B·Yg• Z¡ásX Ð7»Ã”È"ì‘K9Zkuh[c)w!à)wÎÈDóð‡0š˜¥ØN¿Z_¾|ùø$Ù_ôB¦íõkág0ÿH«:¡¬%>ñz¶ípMbšˆ€i+…‚¬1LQ«-fk r†_¨`)‡¤ Š}ü¨Û‘öá«M_?oŒú}HOÔM§ ç`íáÖYÕ‚­—rMr€³ä‹Ú!MgÔl‹zAäì(:„¶²\~ç@§«S3˜DLýñÝ¿‘•éM£öº¹a´‘²êK³¶m9!Mme Øj|ýp蔸Æ&¸,¡Æ—”¢®‡6ó„ dÔè¥l Lªx%uôtçS~ñî ÖƧïþ½o©êª¢¥×|QEáV4k4ëqOœ§!*…/ÊÐl­ÒÄŒÖùr¯­ Ùâ0¡VÇ¥÷3q>ÐmÌGh{Õç Õ#¨&‡>ÄÉ[×0_”¡…[#CR««)ɨÅk[Ô“!ä²2`Æ/ÚJå›Nc|Á˜E‰{bˆ?òõ|ÐÒQÇh‰ŸSþ² ÈÚÆ,Z‰c°Ó€‰ÈÒØñÃs=ÌD ©­õ2Q9Æ¡"šoex!œ`Ló7Æø:@V.å­hLzmð…Š– ©VN%¨ñŒxd:ðSà¸K”ëω$.úÑ„˜§oCBËg0Iu|ø¶!diZñ÷ØFÓ€¢Ž·NvÔF ˜ð|RŒ£D [E«Û Ñ„ùåÖR)”Dmá²§Ìð‡ —…Ïhþío{ú (φ>Ó‰è׳º EؘB ÞDœÚCk gÂÑ‚OÄVÈ–'?eH3ŠJäÓÑL>&úIî ò1Em“¥mü”1S®[«h±&­¬ßJ‰¾Ñê µ­™E95ÙP•F.a‡€p%ÃKߤåš+ÄÊÓI¶ôXÀ„*‡ ì˜xŽhRÖƒ3=¸ ë°BVœ_~ù%q=3ÌE_tzED{Li✠Y¯­êdÑR¬ R®ôø=”Ò±ÆA®s³eùm­=9ì$m£­ÊR„ð1!˜ á³säÚ²žLê¡A¬¢ÑÆtÕüÆZé­þDOÿ“É}Ë?uõ£ÝÑñùÁš²¹rji=pšÅªÆ¢9ùÒ%Ú–ŽàX¨ aJd¾íU‡)꽸C ¡IÇߤúøÍŸ¯_¿v¿åãÿ²Š>ª×¼•Õª«Ó h•õ|kRQ eBÀ½$Ù"ȵjø:Zw]wo´NšÒ'ÀlqlE½b~<°ú—eí_|qQ‘G“Ê5C_‡š©ŸœÆçc¶æh8"—“o»¹ uM/*·‰ u&×tþø¥(Q•4)¬JµõSåÓ¿Lóã"£¯zúׯº+T²8]DÛªË-YÿðÚ^ÔH¼Ã/B‚¥£qÐØr uÇz¾å(ÙmI°,|¾qš L-A+¾þªàçÐ)dB“ùIUâ:„ˆ¦œ † E9¿mœÐVTˆ,ÿ¬üëë”P¥£µj’#E9QN+rm‹²fÚ¼@vÆo÷-?NíY#T%áør°Ëàô%tâPõ¬lŠÚZ“@fµ‚l+×Ìœ^󀃰årªD°åD±"X™¢|´¥`ÖO¸¢fÁáh,B¥1sÐüºÖ×X»¢8ÿÓ¤ø»~Qà“lÏ¿ø+MU¬ R]¾~øœÝÓUÂìÖSŸ@ÓŸ]E’²®g[Öarš"}QÛn;o:ES+Ýö(p~ògµÕI–H¾'ñß°úömïþ•`¦öl¢„¢ú(TÅ@['ެÿ¦Ë‘…Æo–r›·;G"ÇŒ8rR—_njÊUÚšCÁcA¢”ú‘œæš¤À‡ç Ù&RzµøÓ9‹¼yéÄÔêNS«†P1 ¬¤(¼ö$Ö°éF?ÐQ„4 _Ö|RS£Y]çïè$F«+Q‚‘­«ÂA³J±²úçHÁô8}hßMåÖJGÊ‹7êYù¶ìXÈêÁ8ÝÂՊм–Ðy6‘-˜A¬øVRÝfË–ˆXJÏùp"KRðÞq …¤ð!Ú`Õ½ŠóEBRú‘Î×[Ñ>ÞNSÊÌÛtÿ—D¶>ý¯'ë‹‹Û¯ô m&šßÝÕ8Õ@#D³5SŠÛ¯)ŠZm­ÆÉ©nœV ÖãÔΧ)œÒ«ˆ–¸­?ÍþñÍ®—‰NÈëÿû×D*Öž–4O_u—xƒì¦(ÐZhn`Ûf')=°¥(!ä%[T ¤´²8L”GsvbõšX'¼£úx °”k¿Ã$²S}ÚzEÖa [5ïá°ûŸrG§ùªäXázà´ÚÒ$fë³­Š|LV"Òc00©|ÑóØŽÇ”t%!Îa9æ*<ý?ÜôÎöË M™>Ymh¦[¥àµW?ÚÑÄy8î=çé M{hµÚÝ"*E( ¤)ªND ‡ªÇ™_ú.Ö:­„U.ÆQˆåZÖ˜TõÐr¯\»Ü02ámù©×Jé³2õVØáªB¶™¥SC†ä_ Ü6)¹“E®®U¡¢UÅŒÀ±õ”ýܧ2îÑ/_¾xÙó7ÝHeõÉ×Xƒ 1”gC[·£(C«½!ëS?­)ð€I­íÕBbdKá å[#¨…³SBÐêΑ¨P:MW¹@§ôôÇÔ˜›§o|ò)+ª«á:9‰·Ç_éú¬ášÄ—kµun©a>ŒSz¸[¨h)ÒYx"¶,Zâ|4 ¬§€µ©1)8˜'븵ߺ\~3®>ƒá¿Åô©.Yíñ/’8\ÝuÎa¢æÒaœF˯Iœ@W­é Ùv&ø!¢ Õƒ§n"mÑN)ùÖRÜ¥˜U +GŠoþP[4ǰ¯ŠÖ'>µ«Èÿ³[_'HÙJ¹)ôY§®îÀÑʪ2§ô©ádüh˜¶ñ·BfdÕƒDHÛî(]ÚÂÛV…2„5…íLÍÖÚý“`[}ðã³%)èöÆkÍñf7µéÖ¡æ‰ÊÒ¿žµ­·Z²Î ÂlÕ6ǶÎ9uR” ‚q„œ¼¬høt ¢\ M+¸(P´VIAøE¨°®8ÒÓäsl7BéJ'í5BïB„ÔC²)7…¦¸¶¿reY¥XáLŽŽuœ¢­ æ#×§µƒªr͂Љ%+Z•«`„ˆê5x ¥ß^Û”SÌ)¶ªm&)d{%ðÙÚR ¿Y–t˜’r]{#ß6';{>®·-[Î)s,Ýs¹•æäwpÈRŽÎî ¾˜èãÿÄŸ[}¼áÉÅóoÊ•Øà¶j5 §äìâøœS‡šDØ\ éœS:ZÝr²&J ŸZÕ¥cr:Zbh•öDéB”E„©hëuëÅ_å;¢¯_¿V«†»4ê2¾•U]Ÿu+z´x¾AäãœÜ# ØaJ”q;‰ò™àL¢ó iFw XÎÜV¨([ hV~-‰º§rñK´®ÉÄÛž’·»÷êŸ2ïY\Ük ˆò­uÖ’YR°6r¸CÃÌb ‹C°ÐÎÓàËêÓ—Fbus$–Žïü§¾ÇùòÅý ¿šwÿýƒéÖø~Ò¾Ò^ñu(=qNÛút™cWº;J@ã@˜ÛÖ[œM*b‹S'‘éZ4A KŸŽ5N‚ýÔ9‚¨N&'bXÊøBœB|_ûùø¥×Ô'Ü~LÚ™,åŧV:>¼t éGuÏ!µ¤3usm#àØ²ÆáPhœ eLj¶8VR²J*7) ‡á3¡Ö*mø€öáG# û›?£I|ýãïþÕbz8û½½ê¢ÖCŸ¶ê°DˆÇ‘\+«-äë¼¶®ïU\ú¬ëb[zUß+ãë†q«TT]&™£±×YtJÿj¿–4Ï({Vï¥oœ]îøV´5ßt&ˆ`|ø‡ ð Y›1©­ËB8²”@C¶u8V|||ê›Úï8~#ç‹Ê.#e(c,E•Æt,@[>‚fø1·®+š-‡líj Z+áÉß±÷KÚ iC9~…¨á ‡{öî…ƒ?q‚»ë|EkƒAÊVÖÖ’"¤0>§fl9L!ÆñZ‰04é@Ž•ìQøò°>9‡ô95ÍÉJ”Â!8Ƕ‰T´­JY¥$®Y4?‚m}r7rœÅ?ÔUò°Q£GU>¡¤{ á(MÈyU ™‚,Q{·oR¢œ+Î.<œ2>[Ñžýë?ý:ɇ3HóIðqš—ƒ@ U®¨×³×_¢èû)Â=ýz€¨Òª¢NøŒãÐpBp²¢Ò‹µ­fg´%Õ©Új q"ÏR 91éÀuÂÉ·J齯mGWŠwÿ¾wQWÏ­>„èc¼”'ÒµÖZ#¨«ŸÆ)ÑÐ 0>D:GÛ˜ù)8ÆõßD”•@ëÙD[ e„¶rK¡ÆlrmKò·æý­• ‹Y'*²?’û[šßÄiÒ·jÒŒmõ¯zåà9Kª¥Vd¡º…pl²8!Àpˆ*‹§Zª tQ8p÷²»-mÇá;áNC¨Š9*Šz¨Ê…_mß9ÁA®C:¯´W|²Ä5¦ãTˆ_ÏkÕÖ]gÅA^׉´/´n4­d¥”U]¡¶×ô“r,© 1 ¸ö€Î„u&ø9ôÛ¦ÃgWN#‹bzIöO/\ë³Ô¯‹çvŸý«+÷Wôô />»jÆû]b=¢ÕÒ‰Y²Þø†ÆGãDVÎ×Z~sQ@»æŠž©Ç3†1mwü&Âwªr Ñç„™ñû%r¼ÿûúõ+'‚5åªÛvÉ®)Ïùtñô; {t F¿IN/ BDt<•n7PVâuÉR{h3‘8¢œ­o¥ äˆZó­~ˆzî¶é±IJ.ø†jL BV`C©UÂDwA…0­uîˆètbù¢¶Ñ¦ÖDBŒ&N ÕâWȶçàÓ<Û9D(%Ùâ¢ZbÈp eqhò–‚U.¤êê6¦\¡SîHA Ž( 'Ù:À#ἚU¤Œ™ t憙H³ Õyâ5 ODˆOV4ÁÑÞÞTÂಚ·t«Š_t‡–¸Ûæø°¤+!FÂV b[ë$”L%¹ÚµêL©ã¤k­6‡`>Nµ0á*ÚÖšf"ÈÖ0jA¬5låŠ&ZÑñÛ¢ù]ö‹¯O•°êß»dÿ0‹8Ós}Öžþ!õl4÷î¶…Ð š_·püN´²øìaÒê®tWЬC–ÎQW:‚DœZ%DÑà˜œ¶È8~rsPÀ§Í‡½hQ ©DUä+¢\ÙjŒi hE®½®t˜þ™C«á²(@d!,‘“`…dyl'ˆd»d˜Ò©ÙòÑ€Ú¨Ÿ®Pi:'?f¶†¤Œøú'‚×*|^kÍh›ßh*òU´­Im@²¢Ú ¼†®éë<åàÃã'B§Ó†#£q„r’U_”o‰.(_ÿûæŸ÷í|ßoI„ ” Èñƒfñ‡t¢%úø¾V\ˆñ;|ŽY Õ†lk¬3á“•ÒQ ì@Êm ¾èu­:ÕÀ7ßýÿôÓO}X@§¯ˆOs»^F¨[ ïXtÕ¼&µm̤CÐv£Ù"ØZ›ëJ¦-Yþ•–”‹Ö©â@|öÿ0¬Ç‘‡j5©˜“åäÃ_4_T¨Z¤´jÆ>G¤O Ÿ)c„ƱX?)Œä·Ž–“šµ[‡Â˜†¹hYÖΡÕ1zk±Ðw<^8úVµŒ©~ë¤ šZMlõØ—â¬h9¢Ò{¶OÎÁi›h­¢×…îL…æ…–ÅW×¶Ò¢ó½p»—à¤[ù¬*¶˜ÖR ":diÓ-Q'ȬÌÈbŠ2Ê8UÁÔ-“N¶Æ —…V:ŸáXœ[9áBŒ8R¶BÔEàÃÓ‚ki|2°Dü¢ðmeÙ"”«ç4­·GªX$<[Ã$d+¡¾œ:«WkLxg-—/WÊtJÔKR9 hüL´a¤ç`²²™m5YMxjß^0Í/¯j!oYýò×Ë•©µQu²ZU‹Ó¶ˆµÙáÝÙ(Ê752‚3Éj+ÄðK‘ × ý1ñ „H¹ó䬮Pjøl>y…ºO™·>õ!®Ò¯[%ôÉhó5lØ8NQk-u&ñhòeE¦/Ý–ñKbÓgÊÁùV>2ŽmÌR¨ÙÖ¤fêÇZ.ãC$VÈ·æ[oKSHç²J±}¯U±¢•ã×'§¡TÂÚB˜,k­Z#@8B¦rl¶Ä»»€ Ø5*1¸E9Þ$Áe¥ÀO¿D¾/¿öI òÌû¯º\äø”u2æëŽ*ësMšH]âfkvf![‰«~²ŽÒ%@+£gdv ÁñÃËR±{Û°B)¬ù¨q BГµcÁ‘nHMVÈ I™”­¨­w·oæªèͨì‰ÛzÅÏl5ÀîK ‰[ ÛÇÿýöØscs­gD‡M­y&Ѫzç'$²†9p†³,xR‹Â¯†¬+ju†¢îχºµêÝ?j­ž¸ø¿=uÿŸ¾‹èÛnªÓ´vò²êy3šX«V82?r÷-ÜÖ ñÆÒO¤Ärǧ`F eà "×ïÃnd¯uX?é—XÖ™àŽïÿÈ¢¦I+ñ|Ža­ð|[Íôƒ¥IYáá4±¦¼VñCº|CˆïVV7fÑ“{\[âêZ¯Ï{ßüÁ[¡ß·œZFÓ¨Y… +T@NÍÔ<G.«·•[–µ¹ˆ°1Ûb¦™NRV \%¬8Døð¶V:ÌéÑY«e=ôަVã/—NYjÕŒN†lu'‡à Ͷ'I>²»‚#JV|éLÈnŠÄ§ÉªÎ©”œBü¬­ºL  ¢&!["ª`rjIH]è"µ‡ÉGh›Z%øDTe³ïÑ.Î'Z+;žUþŒn¶(fü8pkGCÍáò_¨´UËV.„Si"rùÖU‚oE“ØÀE!³@[ÏÚßâèÍïé¼(Rãk žÏ^Ž#®%Ñæm cBêj³¸„.ÃN_.…]]üô+ÑÚÉŠv°t r?! Y—ÜVÅŽ™š—+§”ŸøgWÿö¨Ïþ Wõà×såê¤BcÖy[~¡9‡Öi©E&B-œ³Bm­úa¦ÎÇì„ùÀå¶•›‚m…p‘m—¸BFª®¬É)óåMê]+ý¨híYág;ÇÄøÑªÛÖÚ™¡áD³Ú¦¹{’/dí‚*ÅMU(„étÚnKG±6®>ò7?û÷;%_þ)Ç=¬b·ºZœ‡÷1Ÿ^•èbQèlMaË1…Ñà­‘ '§5äB‹æPØh"¦Š5¾¨¬‰·-MÈ!"±&ži­NÉʤå;+)Y@)¯‘À^b¿yþ8>ø÷9«*t0«E$…úyñ·[>Oi%zW§+£©Å„Tg“cm®¢õ3‚hçcj¡::‚h+ÑøUIP“õb ì~ûᇠ¢3ïÑŽ\dR q^</.µMŠ~WY«¶lÃ*WÏ!ìéýÒáz£#”œ_:§qB„€ n['I}ùòåá@`÷'h\ '`­ùkV¹ô7äió‰>qRgü®#Ç!XYj˜#Š6DT'lG!T39 »öl¥Ør-ÄJ–puÇ\–ÄúQqš[ÿ¯¡ðJø-¿oåI\3DQf ÑuruFàH—È4ÏW®¨UJ&Ú=ÐÉ9[…‚”˜‚3!” áã¸1d©‡Œiˤ‚7AéRö2ŠlM ™ñ[‹"H´zIJº&q”°å0ä*¥OMèÐ=Aä;¹Ì–Å4Î4—;')[Yù9GçtV%Nà˜%³åÀõ–ßZ´¡ô@m¹œR8» õq øÎqÌ~“$mUIHNµm9‘ㄨÑV¨5>œÍ*¥³sd¢:L)¥Œg‰spÒolÛ@ކYœç¾T'÷÷­×<}ª«V slY³Pà ±º2iÛô9A°åK”ÂBgº &Ôó©P V–ˆ•²[¡tO‹B~d”.Ôo%zN‡×¤õ¹gŸJ+á-‚×ì³ÛcµÐÚ«ô@} ™¨¡j'¾5¿­(šÜÖ>N’`·Ä5¥¬ŽE9}'l;rHÊ«+‘³ð‰A¬ù.ã[ëížýžÿª^VÖ8êrºjXSÉõ_Ÿ@÷F¾è©ñëc'òR¤‘Ë’Ò\¶Ìªt mCž‘ci»NÐݺ>ýzø(Ù”~­än)ß­kõ#½Du­Ô ^_+A–ñM¾*'v\\æ„«.j[ÈzÛ‰]›œÉiÝéÁÉN¤+ˆæp¬BÖé— aG”cͧìâò‘á|š ¢·I9vÿîð›ÿ>ª·uHŽD •©Ö‹Ÿv÷ñMö2_ µjµCP+§¨-ëœå2Ûîg Ǻ#Õ¼_rÆ!Ëé@àm;¥§ð¯Ï >>üxöî¿cá8(f+½OÓybõ«T:¬ëÞ v³ÕbÚ¦ÌTÂ×CQ¾{²y¤Ýo•¦¶ÝÕ,”~LJŒÖÁšÎ7°î–þöƒ,=èÖÅ¢Y:¦ kE½dÔö++)¦âŠšW]U4¬4ñ$„_Ó Ñmd>A+«Õü­¢pÛh²ˆ¨huÚôEõÀ±- 'rëÒ¥d>}{8Ì•û§§Gâݤ(Û:Š+St'°¶'+KTÿºµÂ9@Yr×9?ýCñį h²ª{B³3‘ŽæÑíæÙá¤VW Ò¹!oë<ÉžñcA°eÈõ\‰ ¡)«UŠPíY»Ö•`ùõCõ ã PBñ2Ê@!:x² h•h-¥-<Á@ÂÇ‘Ò62Níåïãñ5Y „4OÊq>²p´Ä¶màñ“+³ïÉ·^ ¤38u«mrü:ȉV/…VQ[ ¹<øÈö¸í€ÈÕrX"M%qçãIyøÊ&æ[¬†IÕ†«G[w@IDATZz¶:INkÙrZ‹‹o:Æ¡ ‹ï< h8³•eµÅ‘ØÃB(Wb–>¿ŠÈRO_ÔõíQ!4æÇ×6)Ð\š¯_¿ö7u%ëÖнˆBÙ¢¶5`•¥¥fì@D1k˜BIAí:·ÎjCu­‰ÎDdåŠZª‚F9©V}RG§Aâà4©óDÂù:,tË|ÓTÔ€ŠVµ Q‹Ïj¯>« á@¬²ôÖ%ËÊ'GV"ÈÆ‘Þ6ǺӣãÞ°¥Ï:p"9Òm{31üÔ>/o}óG³Æ<@TtCRP”¿¬Ž‹fµ­¶@9=G)ZݘšDÀ·µÆÌ_KÛš¿þEm­Ò™éüô.Úç 8LTn' Ä0«´êͺ—.¾DäJÛò÷$OÖwïääòìçŸö¥||Qz •Ãç@8L¢‹øþÇ·zv­épÒÔ§Òö”?Þ]U½ÈÁQ‚Ã4³>áª>;ؘÖLˆ ñ¢ÖŒAQk%ò]ˆ/_¾@®ù…g?´”¥Q¾²_ù‰È=à@èt¶d+A¹Ê…T®Þ fà`æÄäç4ˆ-2Z̤"ðÙfAЀ¬ Çéù Q¶ü™ñ€êÑè;aQý»Ÿ94#Ÿ5kÇ yeU…Ž–ˆ(‘f¥Ãõc#0ˆ-BÏx¶Ze@>‡Qk‚~¡“r{>DHŠ&š,[„ŽBB¹ÖœLñéÛïþûùSz:*rLª.¿¢š¯äj˜mãÇäo^ÑB­‰§_.¼Ž·sÀ‘%ÊŠr¦ äùGJuᲄ8Ѥ3H —u•ÑŠrlé´Újc’døp¹Ý*ø®¼N®þholJrk^W­‰‹ÂצB5†9Y¿m!Û ¹^¸0\.f: ¢b!>ÍÂñ;½C•oÀãG4a VT ô˜A:eoK„$4‡,`…0ˆkœc•;AÅÔòŒ€#$+$LNÓ–’&3ÑæLYÃ!ãÀ á³ïô¨D­z€\;шh‡,êpLÍ4ïÎkœ1šHb§Š .%šPu%ò+ñ¢ìSy D"®&³D+æsŸ=Oß»²|úÔYÛªp4 4Q¥{–„Û e|¦ Õrë6éÝŸM¤i¥–`E©œ¡[‹.Ë–¡¥F|ÝVÈy Y|HVÏü)üÈòu¥!oÅ*„lk̛ʛþS¹Zås”vV9šé$9Úæ—Ò ‡éЙ”Km=F°Šb’†€—Â*aËàêæ£º:BI}ó ¨7@¾ØŠÀHe¥ð+×ÉóûÊøº}ÅQÂtÈZ½0×¼‘+­‡š)jÕÌür#XúAK_(f…ó…ûÞªN²>ã À¥§y?ǹŠðSã¸?~”ßW«1å¡SøX ª+W3Bo´Ä ñdæXvDx½…óq€Bµ)wä¶qUb)|¹Ç‘VÔ–oÒd…Ð…%rØàäÇ¢pRŽëEÐhNþ›ÏÿýïýâÅP¥à“*Wi=\ ‘‚¸ŽÈ¢O˜BžI$ºQuÅ¡oX«æ“ÕÃ&²ª«1Ž)$òI5µD¡N‰&Ÿé³Î4ÏA  bÌJóýãrà’3CöQwßÎÖ^—&5U8LËú”C­ÒuK͈U{jÑäÓj« åúß š ¯d ãÔ‰Pˆ-°Ü²*WG Qk¹Äë‰LÊÝâžA–âç@|–D®æ¥×g­5`ºW~R¢£}âJЄ45„U·æh©ê¥¸Ü{޽ €áÈÄÛ†Pc|k ÓÈø5€`k ¡¬"³-ת«wÿO|@ÙÏŸ/ñš¬ôF¶UNgË·EEx=ÌÔHTk õY«!²Jl´…$v€V!¸˜Ý®+øå¦/êrX¯MVѪkEU‘bÛZ«Bmát: `¹BɆÛ²Ö[kQ~Í™Œ\Ý)三œ³>¸DÕY‰d¥ 3Y”…øVL ¢  )›¨ƒ*T B ´F„CøëÙ}Þ± ÕxÜšM‘#¡>ÊœJ…cR¯Q¨X¦ÜzJVºËÑ=„Õ™,¿nÈ2ˆí.ž(AéD"ÔŒrLÔZõms ñó=¬fj²öøÍhËgÚ³6uׯƒj¨^öÌ ¤†¦O¹ Õ%ß‘q$ºuH¡%ÛhB¬8p t äslåúdË?ázúpü… ¯RÔô@™£+NÕm9]J>kð:±2‰RXÑ£aGap |š§aáÒ+T•‡MâgÙce†éUᲦɯ瘲…f‡Ü‰œ’Çb;MbHÊúß‹“)]ÊëN÷’¢M¡㓵ºµœA:ÌUÜŒMÝ+·¬È#×¹µ“'k®® Pp&×–Õ†­ó´î”àhûñÍD½y?áamX¥´%ΰ&Ò³о¾öópçI£ 3ˆM É€zÓN •ÆáõdíL„j»D8“Dà/o.ÛJ7f"V ¸]2¾*˜µ‘ˆ5òqXg“=Ê|ðÿ[ÙÇŠÚÔ4PÛ4Yéi9•Ó[ΫödÑwòÞZ½ëÁ¢„N„´S]¼BBÛN»6ºXEJ±)JÞ)5_iëÙ3þº”è?þØGÎD:|šÖªÔ!¿Óãøx·ŠæˆéÄ: [Lé¶|Õk 0A¸(ŸrEÃ_Y»¾ ¾q”îLDk #µõ“š_pqôéÒs$0ßøižÁã½l­rÎùŽ«Ãl™ärš1Gu ,´¦†pü(õpžÿóèøùÓ/ˆt¥ÄQòþ¶8e +­½JC$²BmñK—’‰“”Ëz&Y¯Ã1%Blq´„¿‡¼­¨N*él¥”îÁˆÃ’ª„è¶B®Ä@Á3ãvÚ¶ÈÖdC8eÁ9ªG ·²¤jbu?ÔÏI¹=¦jƒ)¾Ÿ2¾£†CX!N´›Ý,B¶ óx‘>ÿÈéðznEˆ¶ŠéÛ†Ûf:© ¡†âäÃ9­.Ǽ²”ÈŽ÷ Êw|gÖíõ ¢ 9liÌ–ŸÜ•_õ„fË/=Á.!Ж ­gR}ØzjXJŸ| xˆº•ên¾––¢–pŽæîsrêç{¯UÔRs)§%SCt»6r¬æÕm[Nèºál…HE œMjÄmESà&Td)œV¹]oœÚóîß7ªþÙ#"âƒù”˜HY{1jNWGˆ©ÎôÆj¸¨-|“Ê…'ÕÍŸš­q§iØ”€ð9Ÿ³£‰“SÛDó+мFã·"‹²eÝ…ÿMÉak@Hϵ-÷šòº¯M [ùNƒ£*Òo!ÆGàˆFƒèÓÊxMv·¡ö09Vˆô8øRMZ!u9­p†PÈšŸã•ïá£D8sky÷¿Üôm‹¶MÇÊ*aU´ê1Ÿ^ÍE­‘9΄od¯RfU4qQ¦(Pu´rEqø~‚¹‡!rüÚ¦9¾í|Ž­\¶k¬⢫5NЖ!Ë…˜ÅóÌÇ?eƒÀ¼ùö£5†XW¶,ŸŸ ­Õ˜¯|ÿÇ¿v¥ Ojë–ãÁqYù*⨘ÕÐEq€Æ²BºdÖÈ…–ˆÀï'.5dµ68åÿg+Qïþ%ŠÒìà©Û–`÷N¦—­úüìêíMYÚ£\ÿ|fX[%lqbrêa¶û0^ dd¡ rùÒ?#Çq2ø­ßTq ¾'¦%GÊÜ9´•åéÚÿ¾CÇŠ|vw»— ðAøYKsÊ·ñî(-4H§—ƒcÒ®W]Ùš”iž!ȧ jÕ­mW‚ƒÀ8ÀÚ¾n;‰hýçÞýÿãÿp1¬•2Ó qVpŽÜP&-І/c6H ,ˆäÖjjÖŽ7ë¶À§&ÈסŠR¨AÒ_ \J²©MÊž"¥š…ro j a'`»ÒøpßUEJS·V(…ú´VÑšÏÉGžŸ³ ÍAŽ?ZYºr,Êi^ÈQðU”Âp´ç¹‚`í} '½¢4'±mÌ£Øý)‚PЇ‡ˆ*À!@|+ÄŠ‚ŒpÜß:+M d¢¤«E´ò#—ÅGã·µjE»Z´.ÓGf)ä×72°÷ý© ÉJ--A:ºÍ œJX™-Bþ÷X=h’²ƒúØ’‰œlukڛŶDgËÙöÆ»7/êXŒcö!Ìö¸xg¨ChkU}-©U3® ÐÃÀ³Ï¤üƒ«‘½E³*Q A¥[i­ŽEQVˆѪ(&hËÞéÿsw³$IVdy\F‘Ù²`õzlxV6UPU ‹yˆžŸÙß㔵{d”GdNwëâ¢WõèÑ»fþž/$‘†×aБý‚Áðî´¨ËÊ•(–ž½:yñSXÊȋܖˆ%Õ€ ž±¨×íì\ìHXÄRðÌÈ•®/ÊW”5UvÛ+ù¶Õ\³Ê³m2ªMŒ´–’ΉPU9°ù ëYC‡“EˆUøì¶`Õ@Ç`åzü*‘‘øÓv¿¡W0¥Ã}^k[®’ÖB´û…¿%(…U 5ײDÚ$0õ˜eWŒ‘¨‡PêšË……QH„túOýܽ©]UÞXøÖ¹ôÆ(…Ul<­hóìóá^~Fˆ§Ã飾¿³Åÿô´Fj–WU¢GKy¶­–ÍDËÚiÛŠÄ`EI€NñØñfw͖ȧŸŽ®Tñ„HºÝøÖb߻ʥ’Žò8‘”îÊÆlF`e06¢†Vk¯[ü\¹ P²ŒÓ™ñ'£ÚœQ‘¾’ká*€”B ”êɃG–¥ðú5Ú)8å:Ë?NcMÉ›>NÛå¢$H!á)MB ¤HQ®±È´…L€Y¸¬& œÂåoïïýå£/GbhŒåjÅYÛ–RFÙ‹íš*Ö–·£ãÜbÂ-cœc.K˜¶±µ>d20E^ÌV°¥´² ¡o Ó‰b§»y58 ½^4+:)—ðå-5—Àž¼`Õσ•½ÔŒaÀ&À¼\„q+¥Ñ™íYÅí.Ìð0 XY<=Né8|`KÊ-/#9ÇK¶.eéò.µÀJMr4Ô ZM¶ïùäc´%r;1qqI×êÞ\À„Gè©*Ķ¢±eHÅRZmц"é‰úé>´e¬%!,åº2BVçÕþu·¥,½¬JDWU{k.QF«‚y]•kvmÚÖ ~Å’ª[CkæÀÙÁ€½^z§BØI“©k«ŒÁ¸©×x?l]Šw)þÏý迨²(Fa*T ]®t°®l– “CT,¢XèV[ }„á*„€Â^öY2BbM§À¤GnÛX„È@¸`‚ÙRx'¼Œ¶Ÿs¹^W]HJ¡§¥7:ãüBek§·õ‚–+rJóqT”´{“×ê±–C*&WvH ±YñØv)¥ƒ)BX¸XðxIYôŠòÇôV@ IQyg9éWK´¤Â”ÄþUDž{¨Ô¬Z£ WE ’ÚZm5¸ÉPØÕ†A`%i ¸Aaƒe…Ç6ªÂÁÖTýÚ’Ŧ0œ OX\²Àá<{ý¿ |îÿE›ÿú׿°õî?ž°UO[Ù+¦šy —mZ³¼kè>f…“®Z•hÁ–ÒØT§Ñ ¦Œ†`Î¼é  p1ªŠ‚D1VÛöUÈy Ö_þò—þQæ)~¡Ô»ÿšE¨B.÷2‹¨$»ìޱ,%½£úÙ­®û |Ç›úG›2Q˜b¸šŒtªb³.Ä–ðf±Ú ”=K.Fyüÿ†óYÑ»Þ.+bŒµÆHl ª]Íh¥`YRU±XÕ™ý«fE) Z„±¡e§+)Ú³ºÛÍ«[^0RX˜ÆiENºµ7áðJa°Š-Ü(¥ <þ´lŸS¼ò‰®•Ø®…ôaöÈ.»ùèÂV EýõX‰š‰-O–¶ë±mÖ•A¯M BÈ«ÄÀRTñL§$ìt«2v èY2ZC®GFRH ®€±TÅýke4Æ,À±±P:Àt‚…èkáµÉÎXå‘Àó¢]ÚF•½@.F`G‹xÿÜW*¼Áô¢ZWÍJ²[‰ÀÂé †§4‡ºæmìJ²°,h7볦[QiL¼1±dÄØJ'V`)mÅÂBè„ËóÑ£mÕ Œ™‘îE«Ááak¸)‰b©<øW%°ð¨^Å|‰Q^>Õ ÛÕ”‹dËEš;’¥ ™4[ K}b­N)ô޹±p\ØÉðSô²ã|ü7mÑþìª0ïÏÜ0²¨p!òVþ Pá Œå¬ñ( 9°ˆ".z×4~+Ke× #’4NS5fB_ ,H(BÅ10‚G%„1«-ÑK„¥`ÄÃîââ|¯x³Û=X﵃¹ªf"±e'`òRĪ9< 0— X³3Ò…ØÂPXˆ-ÒMáñ诣ٷútÔÿ!—•Â@„XûÜÒ¶‹"Q@šüHžWü\ NBI„S>G2¤ÔFÔ¶¾j¶ÀZVª&Io+„×JÃÐÝ­_T{ëï빤ØQÄÓL*•K8K·,éBäâZ"`o >ü¤xº¾¨j³bÔ°Û!{}Ñ)„c…·Êö˜Ë˛඼0ŒFÆØíV#¶xØÇi›…ñ$;þz/ÖêñŸå}uëîW‘ÃD^‘ñ¯÷a(Êc¯òÕ£HzÀÐIQ\ج$—ÖH–/$d˜éWÌôIÁ>]‘\f‰UZF!ÀŒ¢è¢¸ˆ£µ $± `ËNï Ú"ð£ìH³77Hwº@Ö£¯6ó 'Âc(5Z[º¾fÃ× r¯ƒªuSPBrÐKZ  °m^°8/‹t„ý„G!ìȳkð °(>]MŒ KìˆlÃ[S¶Ê¤_2ñÊmË‹¼~JÁ¥‡tÌÁ`"„¬0Å"Oð®ømaz‘ÈøW·¥"›»\ÄV1Ueëžw9W¤)¨Û­UÁ³ðzÂ÷ÌBUåAEe¢l½H]vøM€%ÀÇþcÃx¼¯òþ ‰ì±•š…—Ѫ€Š\ê °€TsH+#alz×Fá0­‚ÝÖ]ŠŠ ÏÑíÙÝumÀ] Äw¨*ƒ=å¨à¬A,KwB.–kñÂy¹–Z mŠíB(+ m— ¬+è#,ü«¬j¿Dt‚V§e¤k_ñ¼jsœÂ7ÒìŒ0,ÕOÉ8¼â )V 0!a‚Ù’hÙ+Ã?:÷Ý?ý®e„ß}÷|!bmÑf¡£¥³`.º «„ æj»ãÿØÖ“ªQy%-/6©e$YV˜Ì€½¤ªÝÓLTFÞs<·ç8#*^á¹RlÙ¯lt0Þt°RxΌģ¿cÏè»ÆÏýóJß0ùE¨ÆXF!ÕÓ%`P‰\¤¸Ò•qšÊ)¶ïïw…%bdT<£«‰Óéu*‹ìá{'ÕÃnaH+£ÀUVںи_etùÖ‚(ÿµÀ*ü¢ªÊŠÀ',}6ÕóJ?ˆÂ&¤'BR©j`·íB0Öæ`)ÆÂ¥lÆÊCgÆ 3/˜èâZ9˜3㯗¼®‹ËÄ[…·ÂX) ÕYñVR ÙK„ÊçÀ/ù NÅ`ÖKœkD ŒÚ”‘«ìÊ£ºY)Ò–ÎR/J¥·µžµKc§ lÈ#Xl ŒÀFìx7ÒŸ[ÝÞý{ã 2F^^õÊ€LX2ò²´­…;òBlcާ@º1 †ÂÈb%Û¦d|\y ‰Êj,VÂ%—Ô¢ÔVlv:…+Ì~É+$¯òº|ÕÀ¦ÔÖ}aá0w#Ô2£ÓHw`fqYb íHÿr?R ­¥°Û†PLMÑÕ9%°5Ý*‘+®µáQ^OB.±Ñv:) ›\b pY¹€³kÎØ–~{ç*’/+7Q®•±®JÉ2…X0{&¨C[0:E:rL ïšÑ%%áBRºWcl,lÞÂfùŠ«¤¾ QLµunU»ì¶.dHé4(ŒË:Å%Д0zyvÕ]{!êïå¼yÚ[kÀUÂE9xO{•Húø4Ïõ³«¿<ú¾§¼ HYñ²0ZÀh]û˜Ù¯[ ƒ¹âµ¦_’ž€…” ¦Á 4^u¢«Y+€m…ÙRŒ›¨UxÒÿtr¸À¬‘§Àd œaQeAÆ®<+pÅL£[Á¸ê1 °wß5X¤(¶^¤KÍu¡†¦aÛYâª~Œb«\azD¢`F^Òl»`YD!)ÝRçµ.5£ïV_ýn^:YNHÏ*Á‰+¯DÒqÙÒ Ÿ®£:Õ£»¦Ê+éÃ+†:jJV«¡:gon¶N©õ¨ûå–é´GUNÕÒ[!„г´–â®e€Õ8]8<xŸö œñ.ªü ¥›ÚVm¢°Ñ I ¶¹x‰±””—‹À³?&úY‹ T-’3Û1„ʰ•sÛ.t[Q¼!,/Å1ÀÃn­Ñb¨H¹*þ®e_rûª;òÕì õÞ«f1‘( $#ÝjKi\N D£z^ÁïU¿Ö⌶~›3{®¶Àá»ú†@‘]%b›!qQ¶‰rP)pvïÅ?«{…òOtz÷_ËõØ1¦KMGX®0%©Zü¶ë2°Óøá¦Ö&6ÌÖ.URÅHÊ^HF’²~Ï*Ž{çêÞ*¬6mëåp¿@ÖÀe1R·ä»Mfâ>ÕHÜ)ñ[S .*Œ°_HÆêᢈ¢dßA]Æú²ÒÁ̇wÂ~MT%%Ý P.Q+ÌšWüV¹Ã>Låb¿Ö¿ÂÁ l›%Âk fEJ PêªrȹÜŠÈåIJPokÌVxÛ¢ZK!*Å: ‰¸^â«Hlêç³jG²;3B޼ìUÂ(ä*ã¬kÃEà+†Â%PwGÛÝŸö®ý°žï!T“Mj†RâH[Oÿ±p%tx^«Þc¶­tŠtÅÂÛ‚¹Ë‹äjG/ÄV ÂPádפ5Ô–}¿©zñÑÿÊûý÷ßË‹¿‚)D¢ziÜ,¶Ú¡˜¡·;Ú_bå©_ñ¾¨3mÏVl]4|¯I¼’b`·b ÌBÉÆU"Tÿ¦m5¼¡(ÆßcguFN¯6 ]ÞFm]1\Õ`¢0vÒ¡ÊX.ýFÎ^/¹”ÄÒ …3B²t¢„WϵmõlÛð¤ä-#6öЉ\Þk`Ì0WàAbÛÓßEdñ:Z®¯²úær/Ì2®‰ªª"Ù{ÜkÄÄ +[yÕÉî¬GBkžÅê­­5e:W!”=Êé>|úBìNü²b¿$(DÞÆ‹Ù•…·%<l$å²¥¬~·ù»^eÇö¨¨Ù“г×Û¢ž«Q KåW•W¼Ñ9±êQ]¼M†‚„ˆ¶­ H {ͲXÙ%¢•J//‹Ôr!÷ƒ_ýêW0äùk^ÅÈÒÜxOâƒ-¥lñÔoy­,¼reÇæØ,ÅóŠC»±à$¨4‚ÍÐÌ]:ÞìŒU.$˜z(Mr.^Hö-„ôÈ1÷I)}«Â¼÷’ø(ë,Lïéjæ ÌÒd(1ªPTÆ>©8½w¶Ú‘qY´Ð%ÀÉXÞE |“ Ã%áeéíÎÆ¥~±>7’»‚‡˜DãAØ4LÕ“Ù¶³Ñ‘àªé²tâÆcÚ¨Óƒý.õ3[)À†îÛˆð»êQpÞͧâëZ¸-¡(Æ*Öš\-t"Š‹b-ê=ÿ?±ªÄ-éßQ<®!W] ïÝü¾€¢ Y®ÅЄ¥°­¤’²Â3ò,†ÀH§pQà)·R†É Œí >óš* ]8ÅZ¢ÈÓ…䵦°d„‰Ê!1%^–¼Ö­0JסR€\ÄÅÍB_ ë¨À+O^´=OJ×ô°•º¿r¡íUÛ}]Á²0¦ÃHQ+ ‰­¾re¯Œ}9cتD"eˆeÔ‘ްÓÁj30;˜t¶¤áZ“"Îì¢Øá)xÎŽ‘ÚZoÿI~Dbø²Úò±¨æä¿%p»"bƒAgUŸ›œNØãa'tx+{e™©;ß”y¥ ظÄv ŠbEÊžÞšK ¨¼1óf©.Åû#À—ü‘áí?Îÿë–RèEw]ìêáR†^<Ôš@H=y‹Íè4S…nbÀ=Ñxk­@vRãì)Öé¼Þ ø¾Å/ƒ‰D» .‡ôȘÈeËNt­Z9ª«|m³ÓIb芅4=^.0g@{Y̤!›g€†À®€¢ó¸ZK„ŠWü½ÍNY‘tRyáš­# QCF^1e·­²ÙI±R+€ é±R;Ý¢‹ú°¢Ô²[eQ*Š-ý¬ý¸õlÍ ˜Ë(”gÈu @(ð =Î*<Çs™R²7·\t>_mÓgKŸ‡ …cöHQX)²ðªS=Œ,Í¿òX(U¨Þ²û¼ú¹íóókJd_Æ’V¡µšÀ PÍg£w6`ê´ru×T < ªÇÏÒKLxá¥.†½¦‚ýç•^ý¬ƒÁ[o1"O´xXâ”TŠe©¶R¸"ð.ĺÎÛ6ªçWo+U%©ìUU^k·ǃ«ÉÈÛ@x›çÚÒÝ €“²JêΕ@5³_ü?¾(xîõ“k„Õ§¤‰AÕ56¹x ½ÔŒ™¾ìÏ+®N`lâ‘g)0ŸÙަ˜ 8š9O‚ð®EÞ‘°ÓÅFc‹„?¯CÙÿá#$˜ÕC¸X[4OŠp"”Bv †Øªß C`ˆ\ô`é~ûäk'äÝ‹{§¨”á‹­ëeµed!õ+$)™:«ê(îåý/½ò‚…ϸ•±Þ!‹mÂõê¿¢ŽíÕÕ0üñG•#©€¥f‘ÈV#VÓ«‹ÏØñ£‡·ÚVyv+AÅØõªòÖha¤(к‹-)€­z„PÀÈ•Á–}Ìô¡À3âÀÔšz€«­5æ+C©y#Ùg Æ‹6®jã"\E ]‡‡]/¢¸R»Hl½T0ïj¦ä¢°#!ÆZ¸Ž†à pFÜ.7€½d×cyCŽsÈÀ•±•2f' !ÝMa{Öräb¹}“ÚŒ®ùX AщQ 4FØ+¢1E cpQÁD[>¦ûÚ»q[³„ô’YF[)pF²Š)ŠÁIÄΟ’o Þxu|1ü}ðµ¥.z¬ íSTØVºÕ¬ ƒ )¥jax §Â€7%H!EIá9ÛË¿@ü`Ql뎒ÎÆ(äÕ—·o¬æé—¯^ŠP%$]Pä=ýÁÊÒ €­ŒÑ² ¬°&ÃÞºÊÛbÞôÀ*^,»-EHÅ £-#i’V)c ’”8¥“”Ëv0!${[ÂB†dq™¬«VÔ{¹ÀÂch22*Õ5µÒ 07¤¦\Ü“ãK—‰ù(Ca•Ýå`‘‘¨¼NÙméDUJZÕo»»[0‹(´Øè[YHl„¼Œ¨üèßû‰Êàšðú%±ã'þ•”2µQPYk€N`XKó<:¾GìŽ[º+ÞIcVmÌy·=«8'˺†dW•¤ 3=mÚª*=/Z+¤($åBØJßµèBÌ I؉[Ò/Ê¼Õø\³þØâ}måÁ ½CÆ Ð„)Ê£$ –Td­QX¢‚¹#|fëžêIh€P%heOtÇh•Ž¥lé`${UÙ£²]It¢~“ŒßöÕ‘ÂÞ¯\‚É*¢kÂbÍB¯Ûì¶ÕóÌî0¦±¤Š1–2¢U¼–Ûš›,¶’T¡2DÙ¢ªe:#iV¶x"t~ª¹ÓînvUw«Æ ‹¬ ÇÞTqR#;Z0Ù!% #¤ãš·âÁDÑy½°ÚÞ°JÞV¼Éƒ\ H*تN´Œ*±* ÌZ^zx¤,¼±Q¦çj|à`WÎ^ýgåWäî&õÿí`öôR mÍ9oƶ\Š_©¶„«Â²[³¨ÒˆP^ºBl“ŠŒ¡ìŒ’=dœÖ¶+°pepèê¸RVÂÎèEîɾJl©»äb´Â0¦;Šøm+€±m`áÝò.ŠÀdW†Ù6:‚Ö€Ô¥V¹¬n.YζnŸÖꎗ«zŠªH:厭¦Ø£-ж¼…×$E8oTRÍÖÄR€uç}ž£B‰ä.ŸÛRÖ3ƶ¸J,xF–®Í»xfÙº:0@§pÕŒ•±/±bÀnÅFÒ¹èŒdŠÊ’ ²ò¬¾pòÜÏûÞU¸/,}аböŠëº"WƒŒDmy ‹BŸ]Hg¢yš¯[04Je oJ¼®Ž­G$W©Q‰\’–í»þæ¸ièÎË‚ ³áS e:ñÉÄ`¥B•ت“Kvv•`àåŒ×¶Æyal c˜æÃ~¤¹¼1e©/€xµY£Ú}Ûô Ð­@$d°¨ÎZŽ%—\ôêW- I‰6d!²ÐÕ“ÝJJášvY±EˆÊ¨¿ÖwÕ]Ù‰ŒRT*½”§ý£ÿøÏ5Ch¶Ê>ÍÇ0Ù!ãÑWÞñÄf+ p$\À\Â)>l¿ú~Ô9ñãŠf‹Á¶@5c+i] aA¨à}æT!;E*lÛݤû«¶;ñëp_2êQ:kEZIgÉéU€Ô¼!Sè]k÷K±Õɫ͢è$/'*ä¶C‡'¼vTì¶D³o$ o) ¼áó«+~®ŠW†XÛÒ! ÀËEwày_e{Û¨6s'BzmF.µ¢YâsÉÈUy¼àñ.P¸ió—šKá¢᯾-s‡z÷)pHQð„ÝÊ­~m—¢mC`—ýcQƒ•ŠœÒmK©*Š! ÓU¨kÓà¥XÉŠ¤Ø*ŒëÇy»²&ìÿGH1~öSj± ‹PÒ d1yµa¦Tƒm§B)`pm,õÈŽ˜à„ñýø ðöŠÊ#ƒ‚¢6lŠ‘]¢•DWÀº8Fðò2„lëU¡ !)¹€Y¤¨µ\ŒZÀ×o~ó›Ç?§¿*ÊöÅb/ñ›92|vÛꑨ\[BÏóSÔé?J½n…³3Rr¥gœ‹÷ê‚T¡•ÀX»éµ¼•ז΋)XJÁNO\/×Î<–Àté:`ÎÒ™ööT.ªÚ\вu­'¯Ø[š—w‰¢fX%ìRX.. @‘¶h¥Ë–ð¦ðV’mêa±…¡¤gY…óRà:…Œ¼Œñs!‡ä%Œ Ý‹-;;X÷o5tA;Ææû‚P@µÆ»8ÏV[Øb0‹ÒЃ9"énN×^ÅðëA0wϸº’ÒªBo%€p¥Ÿ7¼¤¼VÈQ°¶^ßõÀg#ïÒt­NOCI%R­¦j§Âš µs³ÔÊhV®`Œ ¤â §šÕYÊf§7j0éš 0‘ºÙÖ/A¥Bo¼^}ï…ç îË j@{RÞÆ®~-¸^€Š¢B«J¸t& ’=—:!c+;©G: Œ{ü쥠(‰ØZ›yTÓå>ž,ÈÙ+cœ0ZË…­\•!Ä0iKðEQr‰R<|íC²áìÕßÉ¡àqMý‰æŽðJþ¼Ž¿›HÒ:•ºYT%‹JªÓ:# {È0\åeg!È(1tH^¹¬,D.¯yÞO8'ñ\W¿¬èŸµEÒ!*»2†ož˜YÌMËÊ8*;ÿhkå IP}Å}¨e¹ðË"â­ÆÞ–^ÕVI \ýìô©—ŽGá¼1ØÆ\.H®kвDî[Â[Ò»U Š÷Ðæª$IƒÅÜÊLÞ¶J}kå° ¦g‚;åÕ‹^ºÇÞô~±‘4ö. û²`Ën™7¶»Dol D" E¿u*ª2XTèh¶i(&,ÖZa à*‚–½:¹pê”øªèñÂ5)¸ÄRÐJݧcàB¾kAÇ l­6ä!K*{yaHàΤp§úØ$j‹PÆZF+¤*䢰3*&Ha'Yx³Ó“¶Ve³ãAˆyvá][ÏÀwý»;?r«v€ñ”µ!d¹–WÙ«GI•ÁE_a¼,ä:œŒU>rŠ[³Cf‰?ã£Uœ|§‡…( X`WFŠ.VƒõdàrÆÀ€Àóv§t r­rÌxl óÌsœy±tkJÕÂ8ŸÃY–`•W=WKs° ”1;$RêÒ!a‘ˆQÍ„N0(€±ʲõ¤9.Ǩ²§hÁÊk PG`£Œ‡™…"¯ËÞÛZQм}`â6_'˜Oác©JÛ®øž•]ú5# /âúa‡®2 \,méõ`‹GÝÖÀò,/o¡né¹J'¼AðlM9iŽwÕžkÏ?btäëð%UfF‰ÔOW§µ²`K'tM ¬¤&ÓV‰ây7ð]Ƽb«™"œ^¢˜mE5ÂËå'U^ÞJýÉÕX|ý€‰Ì’ºpRvФtMñ‚騦l¹X„“JÕ 0a´­Ó.wFH´,„—1f¶¼„>Å|TÅ" 8¥ Ó%¢(’PÚPXÚ²GK™„ÈU1B(0¼!SZyÇÆØ–B–«J„ó°°|ø¯Š¹®Þªúó±á 7k(¬.jÄœ¥æ%†¹Ž*ï0`ÍÄO!¶µ`eï¨ ñ=¢fœ)n%/ðm­I´ºôsñÒ,ÂÀjf$Ï^yj¨µð>i¼ë?¶}Wê¶JÂÓg¹dÉÕTy%­žìŠY,… R •ίò)¶Á¬‘c`4OŠ–­eHo½õ¿K‡dâ0tXÀÊî…”+=’½K) ¸Nx•pAZ=ÞÝ×U ¹ìÏ(á½#W@„ ’Jª;zCˆ“·vä¥ôí ½Ê]l¢ÀðÂNrWrJ½‹DUÂ#×l¹¢Z¶ôÕIyäˆùÎþöVê£è—;˜®’f^l^+rk3¬M0p™(Ä“Ya}xƒŒBàM òø÷aÿB¬xE@ާ¼B(Bb€a!¶`Øäâ…al2¹ “Wa\5È€ÑjKÁùÞhQ@ßÖ!gQ‰Œ¥¦Ç_;Õк¼U"0Kë˜yÈn,0˜I®xý’êù«Ó+oÿÞ×è6ðe§é_¦D©GÐóÒÛ6[ƬÎã:½<¦Ä_Tä±e¿ê,`Ù…™^ ²È( ¼Qt*è¤D”­§ù¸Ö\ºÎ%œâº;¨ì¶Ýz}¶Ä ‰Ÿä*¼%²T’-Â…–"ªÔtöê¡°Ð%’¿ØŒ`¹bæ Pl$ Í:K}±PáUÀ–ÐYjPR0¹ kR¶[ xF±VÆŒ,Ùë.rÆÈ­€ñ4Õø1ßþßÎ%ééSÁ@å6‘(ê§d®–Xv¼Bè¼xx)¼ìØ…gÎ[e`^¢zI 3¢J!–R}Í@ a$S€³³dô¿,!ß^]'ÏG¯£ãl Äꦤ/EÆ SaR+ÀV¿V0„5Ra*;#XQÖôR‹Å)#¤DÖQsSêãËÛÛ òÊîï¼ýȾŒ²t¥Ô†YÞJ®l€Ê f[ƒì ½Ë$Ü)blBâ±’0¼& cé¬åâR={Qt`±¶\ÌʘΞÅJBRœ¶Ûƒ‰X`±tÕš‰ðŪÁ¶ª–¶ÚX2Ò6Ú­”òZEÙo;žÿ8ZÈçÖ^é¥^³K'DwÖ ÓݶaØ£]åµÀ~•‡×þ€p!¾J|õ/l2þðÃÖj(×ÊkªÎsYx¹¬¦Ô 0suêèðUÅ[Á'ðXº"Voé|a?¶z9÷fHöÂeIQ i+ c=V^FQtFå™I«™1|˜t.Âoõ_hñîÿÖÜJîhïÿzDT$†U[%[)é0÷äw?vÃj¿Æq§‡qð޼ÏÿࡌrõèXã”CQ¡(^kHŠÂ¸”𗾨FgK)Ü˭é+9]vöôÆ ¡F-B$ªY @„Ëe;#€Ž²Ð{u¸Ëøö¶,åV׌]nëòRÔ¶tÝ\ÍD/@,Y¹Õ•ò&õÕøKˆ±Ô5~!°, $B[^v[ø Û#ëY6;“wGÝ–±Q„L‡ñ5gÀÛƒzôê» ñTR<¥caO—Ý6’*Én­ž»òp’ÁPi?’Q9f¾øwG<–÷ªÅ»bÚ’Ž`u!¡#ÏÂU^vzÓ®SöN/0áµ*p‹²F¸À‰m–x¬†„YUé˜);xŽŠ-vË„‹âÓÍ­³ÄÒaãõ;p¯¶õƒ@!¥à„†«š!K½ìS _ uçzÉ.Jc€!5.J¢€ì%M¶Ø1PPåV ¶=9)×"Û– é<”·oZ‘įžø!ëR v:òØKÔ„{D׎ò®}ïÚq)Îp+]î!:pHYÖU™rÉdË[ŒRÂKo²ÕÇË" †‘¬PéÌ(…™c¶EÒ ªðº>ÚYz ‰…¤U½°“n[7»¼ÿùHà7¤Ôš­Bé®`^)XÎTǃ]…0¦s™[ ŒÚ´ ÏÃñ_µ|øïZ{ô´¾R?BF÷£1â!\¨P¬˜²PHÅ”ŽN Ù³x˜œ¨÷-Ê–Õš2¶E›‹RöKZTÙY²lKok¯~Uä«.ç§f­ ¤ê‹•Ž¢ÃIa™q^¬i``±B*‰+¬ŒË]`øN‘{ͧîò>¿bpwø›*Zz©[%eaoK­è,­•Já‚W*€Úl­1ëg­j~¾lgÌÿšnÎDÆs0·ÓËžTÉËî§ÿUO¦’ lÕ©ŠÂÀÜC¦9°³6ö,À¼„Â…ÄÚ2R&¼À…;¥n¥8#9¸NɈT[OzwßF î$¸+ €Qx«ÇЮ—‚Õc«¶VJ©)5ÎNÙ:*)°)ƒ.Ö] ;I)‘-|Ž')céÚjíj‡$–¢mlt•ð¢Ma‘…¾³Ç«}Âã©[IwÔÃ9ªu; ¿øãÿ˜O _¤‚Óñ*eÁìtŠõLtÜ*ÁX*”—¥«(œ"ŠQ5` ËÂÙqâq=èVÞ€‘ÇÀN(QQ»- ˜¼Â/‹õ3 §°?ȈA@s¨ŒÊëÐÈ.EgL %¥SHe¯} ÉØ¬5θâ”VGÖ^F¿#ãwÀc¸SüÖÿÓ§O¾ÚŒ$rIE^ñÙ­)»âì,÷‚çúÖïk¹!L‰Tÿuß…co°ë@5ÀPÂĽÒщ(€¼V` ŶBº: s*`äã:in”!“1ÀFËUy,mY(hMFœ\U•‹åÉ£XÞÏ­h«@ºÊhmzʰå"¦ &ÄzEÞ‘ ž½N ,VñŒ^ö|½Šç.ÜÖ'L‚‡Ü2^íXZ¥°𵂥ãªàŒ¼ì¶S’~æ±°wY¼ùvá8Kþ&¹À‰‡†[g–¥£³¯)0³pøÖÒYC2ºý­ÂEAêKý>HÓÙ d)ÊJx­ðRø ¦ªžYÑz·DЖ…`Fû9Bv"ª‡3]H«z(bYÔ` Æ’Îî˜ù¹óóv^vøá‡xå1·1—‘BÙD1*FꊩlIÞzé,ÁsÕskM©né®È,_&^2;?h⯌ôêo’R«SÍ!¹l§«öèä刢¢k«æÏýC[ÇŒ”¢¤x\D´W£teä¥ÈæÈzV¬ IGQx…)€Þ–ΜR–½³ñòÌò…¢†o¾ùæ»ï¾“‘Þ¬ VÛYÈqð$­Ô’R¬³CÚZY\,áB<¾l5Hñôpw»š0o” éDTØÓ Uå•ÑXb(ËlwÛ:Å&Q ÇŸËjË˲.±,êIE›¾RQ€’$B+0Úk l0•Z/¶BtAº¶`h)Ä«° yÙ-:ò·ÐëÆxØÕæöüæ›o\YF®·ÅÃÇNÔ÷’! ÏuUÛH$͵ڎN^J¢tJÃÛŠ-\a ¹aHQ0,)­EÑa…\a³çEže`øµÃˆ_Iaª¤tâŠ[…‘Òª©ªePÅêˆÆÌʲ'¥QÞZ®Z(—¨nsx^ë9³cqŒÉ¨Àx­’RŒ–¥mÓ€v-Ø¢] ¶aj–ÂKÚ~%a'á­1À£ŒC[3EÆ‘d &Ä(¸6aÂ"ä¿ÿýïKŒ‚ck[PDµ—^&:;/‹­ÆÚ¸m¹7èEUm$¢l­\Ú’é!tÌ+#Å I(Â)áOÏñ3 O™.vÆÏ­ô$õæÃǽ€UCüU‹'rå²UØ™ööJ,ªZ!Á„'Ô³pÀŽÇã¦×¶zù\‘wv©=z>}úäõ«ª¤ÑZy•Á%»Ö¼ÜžÉo/$Õl…$ê±Â ¿•~5 ¡ÙJ9£oÏÖ¹(I^Ùë×¶¹ ,ìj´-Ë™í– ü8yñÄ¡²ë4Œ•·5Âõ^I­‘ˆU¡Ë$Ä—M Ø`QU WlWþ•ŒË ÿWù±ŠW&_½W Z¢žI[\;²­ 0öÖ*_8%‹÷~ClÂx'~€ë¥ngU€/)¥P–+0 {:Y¬ŒDl3§gŒ†~l¶Ä+{ÐdÚ~ɪ¾Ç&G› Ià\¶•{·B"'!ÑR;=Q§pÊ‹í˜2¼@:¹*²ä²æ­Û'¿lð<ò h/ÝØe¯’½B”‚Qûé²W°FèìY„S¾U^‘À,^<|#衳?—îgWœÞúÿøã>®Ðá±iSöÆ¢åõúÇbk-u%õxR…K8;À0, ~BŽüZ^QR_'6¶“ò¶4œz¡¿=CˆBH`jÌ–w.:/©0 Ì*Ê6a)¼\/æÛÿ޳Ô)}é´8¶:²V6¡àòZÙm‘g,×ýl$ÆWL?ð3ŠìÎgç~õ,/€\Þ¹ÀèMi!Mf>ŸøÖÿs_g:öþ¾äÀÂb0Yš #ׯÅÈBJLŠU:;–WÆ kÛ„),«9¸N6ÁóÞw‘<®.“»Rv'!~ÙU¸Œéê)¼úWžF¼?ó}¿÷¬ëï?,‰fA¥…>Æ÷5pyÑ6HsÀŸT€•¸Üסe„§Ä?Å6ZœŒ¢¢½Â®°ò+DyÏÿ9ËqfDÉX–tÛ‚_GæÌN—ÚJláë½1º"ãÙêèÝÏ@TbEá)Q!ˆ.‘#p&9æ>6áÞìmÓ­¶ž^! Ä'¢ë3àsâUÀ….[TVs&ŠŒ* pO £¹y½p® D=‰¼õ®TUÀä …°HÔ PSˆ·ìrI¤÷>o/ëŒB7 ‹»¾k½î„L¹®ì¢ˆW7Ñc~UÑŽŠ’âŒ¾)—”=r“Q6—ªœ.GËè0 yMá‡y?üðƒ±ˆbïq¤;‚OÀÃ`5dk„Y–…K\®W% »›%6Cæ]8—X%1†·=Ÿ²ÿÇËB±¥~ru® M^,Zœ‹­S[Ť×WÛª¢ ¡{Kà…ØWþnáüF ³ç¡Ïœ’"Rwé¶9£µ’rY­:m˜Áäb ÀH2v×Pb ” XñŒ.ª@§†^¥BËNgÏeÒ5ÊŽ?{)c¬’;»-áE^¬­ÃÀÒÃ-6^ `½ÎVLíÈ90 Q6%‹-¤.ðÐI.å* žÑÜGõéQUde€QŠj…¤°ˆƒìgWq[I­Œr™‰Ô¨ÔàH¨œÞ@¼ï'oÿÕÅë‚ÿöZ’ê¥tR —± ÄBgpQܶ.)ä«ÌF¯¼rõÔU.Å×¼\%ªw.¯øòv•ÃKMVL…5„VH Rì(²×‘@UBêIOHçÁZ"+$»Åc«$+—@FBGKÁc­€0å ²Ã™ÎËEOq!0t6$õnÇÏÞ(8cP0¤tVW’«®µL'Kgàê,V:VÙ[‚†… ÆÄºëY\÷ð•7*Q’B²ÈbKoY„)_^Œ(Brá “Š´b0¥Ò]]y Wø¶J¢ð¢ÊU.:e æ<ÄÏ•T³Õxå%]ˆRQùË_䀆‰ƒ^J9€½ `K`³Ð‘ZcdÂbÛé<9ŽApY»!bpð¼…” ÌeCžÝÊ5½¤¶%¢ÀĆ€+ /‹mQñD?¯çµÏý]?e¼KÜ!òzˆò"„MŠrYeì {v+Æ4Þ•å –Ë3®¼ìe”‚°XYt'5 £Š­Ç` ’‹(’—½“ÃBÀ¬b)‘k¹“ÓT1ÄfuW Â£Y^âÒ°‡©’¨°‘˜«ÁžL 6ƒjVHN/"õLu4e+’ˆ¡,Œª"\b! …—…Þš«¸„#©:áBbnRØ‚…f[8Ð`+ /”_ÚØž¨/ ðmŸƒQ#URFÅ0ªÙšÎ®ŒDwÞ]9ÿo è‹®ya'Êàj5^˜ôB·¢’‡íÐKÚ’ã,‹:QmÒóÚR€ñH‡…ÎXt cYj¤ÂèðÒ fk†ðÝMá1°»(ÈV\Á,½ôP2V€•HTxÛV-#¯ø:Â?]ÒØ¬òV¤ð¶_yÙ#,/] /T„n¶¶¼j <²È˘k-] «g䌤pàDy˜¥{¡<ʦƒ.„ÂBQ <×Kô1áïKEÁ(õ¸—ÿüç? I³Q@H[ìÚpGF,¹"­”,tÆ,֌‰@OïâRzHePÔÀØ­’EH€ÊÛPV9/9¹o!ª–¥¶ÊNf¥×u^¯a¾Å™åÚj\^!¼]0.µuuëëÚZ#b!¼:Õ&£ŠË§ÁæÉ` ã> 0±…'Ù§«Ä@ íšº¥1ÛJ‡*€˜@¶RÒQÅf &ÐV,6·–Ë _Š€Yè„WFH¶’Z1Øh‹¼X…_eä`›W†H°.YR^ó„§h¡ÀôÊ@›b-Š^=ŠÌ8org—mÌ\£]›EÕEEºô¼rÁ¯A0ƶVÛÆB?~f- KD"¹­p¡)údѼ•°l‹bWkiä+%äIüÓ‹}´À8÷m"ŒX„Ç!×H(h•בª F!„B0°ƒ±Tá+¾jaȵ°ÂEy=öuóøpâÃØAýß*ª2(ßj­è´•¦MrvŒ"{£ÐxmÚv!ch&Í¡‰¹3S2Bv’º:§\KšžÝ…s<ðcçª ¹âm¥Ã“]FúµMö’ ¡„§ÔÈbY®e0f¯#ÌøéH SƸJò²ðfÉÛ*°ØÒÑÙÁ¬ªÒx£Ö…ÑŠgóŒs!¯ÿøÇ?¾Ê/U¼RŸå©ÊÉw9©°®‹É<ÿ>•ߣ»ŽÊFˆ †È)ºSít—±ðÂ3Z‚ö Q…±ù4·Và†I!0Ö(¶#i[Þél¥«ÙUn ?þø£›ÚŸ|òü¯Å{ w#{Èt\”:RL½PXÝV}3¨)Ú4ÃŒì0‘X¹¤oEHxEYé…P*ƒ=]ŠÁJÊž„ä V\,†ü·¿ýÍ_´ž?`H¼'³>)²;“~ßÒ‰’—¥£ƒ2vä:2–õØðm;·”p®TtüFMx–æLe¼†çõÜöw9ÿ¹§w¹÷ÄËV‘T¯Gµ­Úº«Œ•]wõ¸ 4ºÚiÂh#ÂH(D81Rxǀݶ³Ê+Ê:0%˲Ç,„K^8¥¯Û}”"¶×ªžÑ]2ò òUŒ:{ßo¨/ëD‘Š·U0€Õ–±~ã¬Ùí1¯sæV!ZO¶¤Æm)ðñ/ ½¤0 ’ÂB‡´Žß–]`[«Ó¹Â3¡‚KÁ^;…±5ªÀt<º«à^D¸b põ$ìnÍÕ8Ã[áäª``Y–†ÅZn«•‹]=,õb›%NºXŠð:ï8JרaèÞ¶` ‘påå’Ò–’Èr;ãþÓ£)KU!Xöt„xØ[;f¶Bxo_-UzDÖ:tÛ,e˜óVúß}Ò­ÜukŽE•rcó‘Î[LxO¯ÍÂ%u%p¨¬Åb[Ñ`<0ðÆÏÈEÚn],K)dÔ¼X Àb£eW†’(^`{¼i¨–ÿQ‰WïK鲈 CI· '`YJš®¼òŠbQIÓ†§DÎ~E~ûí·ï}çte¸êÎ-¹Z> »|ëvy ÊÓQu;f\îë.wÝYaº:t€.J³²í¹ ƒ°;‹‘>{Õ“&Oà¢À†¡Cr±HGñ¸§°glìÞ|{·ä&7µ¯´P®ÿ¯«GŸ‡^·ó®>¥ƒÑÐl³4ç&¶ªÚj$‹mO33¹zµÓ%È…¶1²7.Š+Ì‘ø^çV,Á¿²”(XÖFJ)¬¢þþ÷¿û'°þå»ÞÈž|o-‰Î¤+(£²åRU© cY<×J‚×QSR;€ÝI¦äë<4«mü`.ŠÀr.Æ¥£¤‹Âø7!ïú4Uåï]ݰÄë¯w;µ¯R‘ØÒ]\Ò¶aoÔ0阦g…!¨xͤǩɀ%À\éÁ¬ea¤$H(¦ÅÒöxü¯À¼t B˜”,ô`KQÁ¶SDõì­*.2Ú­¼³ë®é(ú5±,˜G ÊR%¼u€Nl¹`Fý²k§£t „UxH[HáÀV’‘½íÖe——`¹"±¥”À26:¹r¦PÒ—ˆ’ÝZ©t ØXè¤Zm뎷DBªDaÓ¹Àz,CŸ¢øºeâf!x‹¤cïÖe¤T¤-±µÂ@V„í.9{Ìrá,“ÙË"#ײÓÇL¯1`Æ’R|!ŒÕ¡m‰A=+£Ž„°_; o Ýë· zñàöÐ!NITg毶‹"½ÂYéDöZSÕF­v}5(OU€YBa'ô‘Ôš@ϵy»Xe´¥tÉ0ìÚ嵦ˆ…œ\íô €Åz\¤SŠRX—£Ø1PF;eÆŽãpWC+;p$Ú‘Î$ ׬z¤£PF2=žt®éWe¹(!…à§wi€YZ³(I¨â¹f¤7±o¿ýÖ¼sBûß(ÞRøq…â6ÌúRyG¥yžçôø¦‚CÖ;ŪðÕ®U•”j¤†Ï »12Y·á§‰üÑè¿ó'Ï.¤ޤg½ºsÛë < o .…o`Ua†;;Fä DØZ j·¦¥d1¡Â.$‡n@9žÀ‰T‹G [A¯ïÑXý8öÇØOaŒ4g¦ÿv£¾ü}xùÕwÇÄÀHë»m¸mÇOÜÚ¡h:”“º^½øHm8()êbíTUI>4µã ÓXs°òiÅppFå›°îù$k€•ÿØßï+§/¼§sÈîB|êÓÛ–­»iñÄéÉ<å z÷´®{ L£Vs›ÿ†ÉàÄ5íu*‹¡q'Y½ l $XSå=ÊJð@˜²@š Žïº¦a++Æáñ7ŒW.®ä,Êù øÛðs3ïÀéÉ21öfëãœ_km«­«‰Äs¬M¤9Þ®¦Tµ é&†iýÁÒõ²å¦/²ƒè4€ÕRïæ­0—¹ñÞSw@kå& ¨2ªÖJ˜Ô躞§€$¬R1²Ê¥|"zâ˜81=¬Ä*V¤B­a&ÖZd^#ë Ï‹L#U:%µ o l‹¤t«Ö<“ñdž }“4­FÍSI†p@UÑlH[˜ cÛ´Mn[­UØRÖ0ÆH@]hÛħæy"mNƒYm†­x]ȺödSæóÇ• “]E×åÍy'ÌpŒS$&Ì!™²‘ðÞùócʱ²LM\ªDæhJ×ÛìcÀD ±ÛêG£@™ÀZGJ£ÔXv-"‰ƒ>€‡óÁhÄL:mß2½Ðe¥Ü)¬B-%ÂV’è[IÞA0¾‹3Q()+û&R«ª‘T9E†”«%ˆ‘m$Ûî0ŒZ@Š3±p^!“ÂT  u¡4 Û„ªh8K!¥¯Åczn”RsûO€rYU+T.ðz‰RÀ”œ‘ùS6,F`¬‘dæ‡#a÷`+h2öÔð5œ޷;ÎaxJnd‚9Ud  ãá›<äBŠ›òî­’&§Ä|(kZJí4€lJ#ùËi?ØþÇþmu¿¹úAØOA“œß0RSµöú9B[§¦r@ÛR.Á;Œ´…Yuc˜ð½óXe{¦0Ò*’uc<ñùÀx²®±ëÚŠ¦êó^/Y¤*²€! ¦¶+E¦8üèNÖ÷ñ$È ¾È¸IÍ Þ³{ 4Â0¬ÊßP¥ÃPkJÑ ôÊa« ÃXî¿-=a+®ÁYÈj÷2pn&ÓýºžãpP´ŽºÀøáÌe  *†|º¢dmÅñûP:o‚JúävdVÈæTÞ¨/+€ÃYJ °ƒh ¿±Q¥ŠIY…¶ÓxF"@ØøRaä¶”¶ªè‘¶V2VJd)­ø–5j>‘4¢a2!ˆ¹™Ï0bËÐ*1©{V‚Ç4²;×7^à1}âÜŒÀËúQÒ_GÚ*™8+[âRÇô^ Û”ùS®¶ò²Ý†rU˜H˜&LÏ—íÁ^ù¯-^øÕ\mMs{W"h~+ÜMê񬃿èŽáÌÖªVJÐÃRVU§÷½p2 œ2 RTTÒ‰ò×ÏM¼à-K)ðâÈxbOœg?šõÒ(q>Ö†¤y1­OÀ ¨ð]39W£A'™š?]v” š²”MßLx«÷ÏôRÉd»ýúªb"Þ^ÕfH¬„ FŠòVœEJxÙ"œÒjòºËÚV[¶ a)>Óô q%ºIlažâö?…E·dZ¿`å?M­­ñÊÑ„¶=õ¯Ù™j˜ç0%Ù"¾ù¥ÚJmK1·5+0¡IYUóÇ—"{»$c8bU¯OMgNì%FƯ U˜‡C%.db€¬+’l±Â·…mþV˜Àì{s%H6í|j×Öª<\wU‹ekMYØ·Ò%½„-Œh:E‚œ™ ­m•YýµtðoPø^ûçÝiþßÖû×OÿË_ö÷ï³™gM›°SèΩÍßÛŽúýG¯Ë'|ð)ᮥ²K#ð»{²Ld‰E@mnÚÑÄ+z¸RmkDIY¹-£Õ…ÐGfÒŸx¶ðŽÓÀR׊•Ô+æÇ*¥ÐjN…¢ïÆÎ»ÂŽV ƒõÆÊÒ§ArVkuÉôĺ‹·cz+òåYÉŠ ™°z[!«‹ln•Xá®®V┲R9[E+ožÊÉ”ìƒ ãE>@žH€Uß]ÀžuwÒ—½˜¸#(¼§9¯Y)[ú 錕׋ƒÌ52†¨»mn|Ö&©©-Oaë{¯Ô­>åiÚZm‘]/l€˜™ÐD®0g¤m¼ec¬M% ØÆè%j°’Íg3üл%2>€B>N$Ú|àü­Ä Ó'Àô—P¶ü 2ØÊßší¬¾Â33wœMÂVJLI&ømÒãkÎxåÄÍ@cË¡ŸM¾¬’Lh8ãk„Ï9††³‘¿lACÀAÖ<¶®Ö׺‘/eë¹$¨¶.­²RB/PÖ¢SÈÚNP‹ u¯V!\a>¶Ë–XP&k!ËYV ËJ bü†'˜,Ÿ˜”VJ«É»íWÏ3·Ìëõ ঳FVÇðd.›9ÒÇ_Çî¹yèi WØl˜v€F!^V/‘OÝÓç“UþÿîªD$ö½$j›V—ùlÂ[wÞÃÂTÝ<+&dR€Èßھ׸÷^&¢~OB-q/e +$vNv®µ È*éüȶ[óW^»5ÅФ¯—U47 K“Àz“Ÿ%MäLÒç@(7ÿZ”šÞÀR)ÈVô$ð=ƒžAYÀ™0Ôb4’uQDåù3‰'ëIPÂÚq°’‰ –-â°•žˆ3>ÆP» ç<¾²I¬²Jþg²oÈ’ýGJ¼³4€ŠF¶ñ‚ÌTa2XÕ[n+è+Ù–vHâRmMÛ–³27¤°m°|ÞU–²{0°ëR•’°fÕæIo ÔIiËÄßµ§©p˜vu XëŽk¤ÊÝZ™G Gj×5æÖ&hÅ “ئtE¾„­x‘Uñ¤AÚÂÅhðAZUµ ç ¶,NPSÁÿ¤^J•Ig4¡©ð­Ü‚40†øVŸ3V<€´†é¹­\ÊU ñ<…@åd•g»5ç†Aa¼xiËß|cØîPjoÅç›0sr{yµ˜ÆV.…Ñe³¥ßxÔÃ%ž-yL©Ü0Sœmõ‚ oõ,¬o¬Ð`h†]8%&ŸaUÍÐüRç'Ÿ{W aEå$bTcÅ"P›€Î̪¶yö*3qž^5‡©œ€om¤Z   )Rv¤D_Ñã$ SUVëÊ79e¶Vc˜³mæUÁÓcjÉ­hZþj!œ¬õ«:Ãd¥Q)[UVU²Ý¹©”¤èD¶xb eç’ ˜M*AsÚF*V[6s8…€¯!ÿLÐ0=ÙBVQw× ÉfϼlßhrbÙ¢l3`l;&ÍRsN {Œ9c6[}ec(iÚR:‹QÙ–µ"’³éøþf]-R f´]S ÆúFÊ1dÊÜ æu¦of«°­©ÕCq@щšßj‹¤„g¡„ý‘ ‡4z1!®cƒ­P¶ˆ‡ßÚ棪ù Æ°¸aŒ-lþ¥6ùÎ…¡´%På;a÷6À“ŒMbÛ K!cë%•­g)ÈCŠÊÉšS #Ú4C}oÅ™V`¶8 µ[iÚ¦lý#©–L¹^ž&|ÞÛ:¨ÅÜ܆FЦo•H‚m¯ ³-\;åL·DÃ<\IbDäÉ-+<(T%°õœQ/ïh@žRÕF’J/Å<žÀÖ:Ÿ4ɶ­;^À‚aÀ0FÂ×ÑÕÙºF`nôSÚJz^Jèa%úZm­Rªò ÓðLߨªÚ1lÛÍ|þ£#ÃͰ^4ð8 €yMµã°-ý&Ÿs܈3Ó¶«àL#¸Á¬Šð›æ+}<˜yŒU¶'µÖ”œñ",% ÓÛThåï®§TM‡'ØÁjúý°GŠœ­ô)WÈŒ:E%’%xõ˜ü5¥1žmãíÚñdOPô&cÈö¼ÔÖ7ýF‘4@©pάëãmië;¯‘U¼12‡Ì¶µ“Ê­ôÖ«¦R@¯‹­¬ë0@µ™x|n†M-’Ù"1ÄÂÖºvxå É&xñ£Â~×€’¦ò[q¾|hj„±% Kƒ·µÚv„<¹5’UJ!HÜÇ|íµ‚€¸’ 1ñHQÈð–~®½SäóÇÚô•Xm»ó@YU"lù ß<¶ ƒ,ŽôØ7*º‹­–^‹Ö*vœÛü¤(¥Œ¨eè§j§› A£fÒ¯Ú”Ýa…‰³¯—ÇÔÙ úŠÐ£u窱m£|È”`…€îdV¼H‡ ³¦Ž9'hµ¶ÌßuV ¶dV¡ CúÝצZåB¶ÿ†ÀÌÔ%})¤PHÀŸÙ¶”íHÀü…"•$+Õx.GPÊ6ž`“¯oæ(e‰gØ6ó7µyRÚ®„ØV䣣”Ið†Áó€y©SX«¥?õ_’Þ*x @¸ª_ËWõKf˳8«zåc5ž9#h¬ëÄÍvçªð8ø€ÿÐIºb¢Š­?‚F¸|A\oµ@$@ÖÉÖêÍ® ŸMs› Pðô©k†L0B•U•µ^ÖpYU…-ÆZh‘@YóT^v¶kIŸ […0^|]Ï1Ã&°ÒOØv9j› +·V…ÉÄ‹XùÄd˜îÇä5ÅTh‹TîÂ+™¹’l¥ú©Ó=Ô”’ ‡ ½ѶÖ¤˜-\êVœùoþ3XÝqèE…Ö‰¦‘b„¬9uÏ+m÷é7¡˜ÖwHØév'ôboÛ¶·Ãy¢¬‘V¶d oK³v“¬T…°€YÑ$pÉáR)­H-"÷dñ0¾‘êeµX‰m…VÑ–,¥5òG/KÕNU[b@PÒZ-^PŠdÖ¶ô@ú˜Rô­˜Äde«Š‡_+U"Y^£›<Ë:ʘÎUÕ”™KíKÖMj:‡p&U…ñµy*ÁlZ[˜[}_©¬l‰ûh æÉ¤hJy]yö“Iª½ó¡†[úœ,27VÈ4/–E b|[À–>f'BÖ EÛÄVn|º(zLä@‚¶V7F PÛ‡”|dsnžRjè°d”U°R¨—(‹¬MÛ6ƒ oŒfóprUrì¾_Ÿ®÷÷$ÁF2†,&¿"07&€m %FHij 0y5p¶ë ©H¸`‚NÄ àï½Jo­\*œ±ÚZÑV²ÆëŒ¶5Zm³ÉJ &B6ÚL0mZTr¤w*Vjk¡7y.§¾|ºLÀ§#™•¾’ý4VgÒ© _S[ékJ¹W#b¤*«*3X¥º^8}‚Làü+ä ðŒhêh5R%­é³² %….VBi« ³Êb`‚Jfn› ÒŸÊ{"Yµm­esxùL&p7À°©¬ ­x}ñ¶ˆªZ¥à²@ž”‚ÀÚÍ8H)SÄp°µÒ3ái{šÝÀs#³ÂÄé»FŒX9çoÝyáÕ¶@ æ?ÍdÕ¾[¸a€}2¤I¤ª‚Q5gµ4xŒØ‹SÕoÿøÿ¨ÆÆˆtU~ü¾G¥ÁWi…)U¹²æÈÎZÐãyÚ¶ª`Uýµ7̤ÇÓµ hKïqÖ1ϨÝHL@YÔ“!X(Z›GêU&KX Y€kà“{|Èæ iÈî°#÷I˜¨ÐlÄ4VLÇ16ÆÖçê½Æ^YUJðJs[b«(‹o’&Ï_ɘmM;Zƒ•:^ßçµ"ÿÌasúi äÄr±F¥duISŠÒ´ë"‹[YÇ4g8Õ ]µƸ±Í`ë_íÞ`¢vV3ì3‚'ÀåáFÚå(ÁW©æDÖY9€”e¨K¶i\mJ k­RÙ¶¦™Ã eémECRÂÖ÷vá¥ÚŽiH[UÙÆ/hµnxL,ˆ›Y¬6ð¥Ï^ïc^(j÷6EJÑwv3,2±¥±’™m¶¶HÛÓìûެDŠç+€¥ ÊÝ6FJ̧™1<ÕK…i  — /¶¾ßþ¡œáûZbD©@×Û$˜ @ÓÑJÙ–jÛšƒ9™€¬ZÄ(¡¶4Ö ßò)éi¤È|6» ¥ðœ™¸â¶ÍCß§K k€Öî­9(ÏdæùÈâû}Pˆd°ª¾N jg*%¹ÙuY0˜•²°ÍÒyý-,^yM›Š@ØúVXŠU¡¼Àç0Y̲ùT•†- …aúKSà†(•#›¼ÙÚZ•à¼Û:"u)uUŸß§UƒÙ1Ý@2@VØ  îpþîc Û+ü\ ^/nñÕ’iÏÐy14b-¬¾ûôÁJ»@IDATݦLóùÛ²Ê_- dÃ0F·ù)‰ç#4­4•We%°â;5Ïo\HÛî¤wƶUsˆa®Qót^ ‡šÖý¸ß 97ydˆ$så§#“ð c¤\¾µûWèý—2m í{˜ç)‡­u‡«²–bËÄØZù”€¾dBUaZ@ÊgÜj€5„l‡¥l{éÏ0™Ä”Å 'н9l JäëVíH²pOðÕ›?#t4šï’M.ûù€ #¡LÔ¦ùj险a'o•jk|><õ‹‘:¾÷±5)‚°l¸/£óXndž›µr@”R ka•uB «ÕbÈ®¶À(3lž¶­ü‰‹:Z‘ÖEÛ‘œ¥¬Þ`B#Ô׿•ÞƒA&ÈRÆdKu þóAІ ·VÖHðaÎÇ…×%+ ¥?­Õè-Ï¡1Æ~¤:¸7éÒ:©g EÛp[U¹ud>Ê9Óô¬1$Oük®DtØNÔ4ÒkaÝ6=±¨]%dª6€­ ¡wÌ+?˜ØHÉHW 40­m‘!Ò¹ˆ‹ôL™š*FÖV¡&C$ÆZ¼žHJ+ìk·›mÝ·ªês®DOüÇF :ˆlUõ‚U!mak‘X¡Iàf¶…‰Å[%¶0™*[mÈm3?C|¯IàŠ8L!&eUÒµ–µ}Á"1Ür… C#cÒ—­/½-™u8«P%•g4¥ÏÇš¬Ö0± £­V‰¨KždV±,!2@V«]X;ÛÎØ ¥¢™}.j”,Ÿ×?ý;¼¦¶³bî—]dVÄR°€ñk‡sSûtèîõHܯþ‘V"»@.Õ `^PÕ…á`  ‹ÍS_Lw˜€˜6!M÷@“/ºÞ5µíCá\ 8pNæ¡¿ýÓ?ý“î™Ò5kàÅ5#ó´ðL+¬„µ-Ó¢¬|ßz×ì<0]³‚ɬsȤ¬ÕôÄÈÆ(K_*ÃV­«j$Ê®‰3^BÖùÍ“^mÝ ”¼)K)Ö«™»Ð·µÚJ&ê8f&ý™ÌÖ0²n“sÓBè÷f[Ý1 7€í=Ùyjk¼JÓkMlÛ«°F›Ç–9A†;Žídïv8}žH' bš¿ª‰‘p“KÙšÊ$J¼`R¶ù÷ i0™‚¦mþÎgYc°µV•§?öôhjD cKPjSxY&€ ÅZãpˆ70e“”ªÜU®Íù!¡oëÙå_U2Œ0%2†¦³ÌÍVØv ‘ª]á²c*äß Òàëe%~£²‘á2=¦€iŒ4R­T- Èæ“Cç­WU²RVÎ N P¨²ºXþ0™cÒ+¬iJUB $Æ*^0Ýûâ0²Ü …‘}Æ«ÅÈ.ªŠ7¿l-ðÝF á…Âf³®c%”»ÀÊbàJª­ ²àÜ'‘22©0Ш‰iD#$‹LÏM(±úÊ•ÂÓÛZñºçŸ­¬Y2qUÉ`‚qPN‰Œ¡©ïr`Ѩ¥&³e^6œ­§ƒ”J‰ FSQa«^Äd:®×ÕÅÚIÉòáÙ™Y¡ŠùVÊô@¤* eï˜÷ L®–’†ØŠ¬0ÆOlRBJ1²1â‡OÁU^ƒÏ+á°©¤ÚºÄV³%“Z-†sä`m»ÂŒl­y&^á[ËﺬÞjëºÃRÒK©µR[ñp&ñ¶HAoÍn‹I°+%ðAp!½0k½çT.%8P²J`[˜S|wg ×¶r@y~ËÔÕo™\P?\v˜:™L²ê¾=NšNˆ„K‘ebkî&˜ífjP>s£|Dú4­5²Ê ¨‘5·/îy]Ï‘+§ÏÄVHPªeNYI®EUÉ”ô¼dñPkíȰ螕‹R”³¥Ä§ÜŠQu-ÏI'P6öfà@,(‘okŒ!U U‘q ƒ1ÄRNA ÔQ &‹‘Ú$pa•€ž†­¬BxsÒà­âA]"—­œ C- ÙÌJȪ%#€>"¤ T"ÒKÁÄm‰m‘•ég.ËD¶W–ò¤Ì¼8@Yðk*‹ç†ªu<ÍÖ²ÖômݘB¡ÊÀ‘ª0¬(E$9g ™*¤m8T…¡/›mkk ^ÜjT2µpÿ/Ô^›¶J¤¨ ‰ g"5Y-0.9“4Öb>UY70Açš¶’je‘V93ÙAb0ù—­coÂL€º+y¯Êª ÏǾö•3ÄÓ&BÊ·±–ê;°’¾¥¿‡x[þNà3Õ]ñìó%¥ªIú íkcml%oÜIÏÂp£’)3)eѹ´Ø³ò£–¸IÌÖ÷ê[wÀ4L0‘M^£XJaú|0x$ÐqºÃáɬ¹¥´Â=ŽšžƒŽb}›'·xæË*‘âF–²µ+JÖ`@mo¾‘ºŸ<9ðA*W%ðYÁ²V‚B!_!æüûÿðÿ ¬´6¹Î¹”íë“€‰Qš )ÌM£YÓ“uÌÄHxQ£ŽÔ¸™s³å#ˆm3Ùœ@üiüý  ëñðæAR¬5&²êkU^øXßoLJÎÂvʱ`kKжTµÈ†)EiKpûŸO—Ž”‘4¾;h< ä‚x-ÖSk+eÎÚxkÂH«Há ¢’øHkVQa—`+( šdz|‚V©î3çpµf°Î'†’œC“#E @ Ê¶Ö™¬#AV²{ã1f}ù We]ÐïDȽÚZûT@ÉÆ˜{W=Ö|¬µÎßH=‹²ô¹"93Ñî¾þŸßDGzÑ3”¶ÄÍóº5LÓõ­·•¬6`å#•?q[²ÍiÍ6&ŒŒ¯Ê1Uô&Û²4ÍP 28Óª²uV¡¤Â@2j‰­0RØæ\VªHPë™x p?“Èvá|VÔ‚8½¬ñ¬ùÀk  XEÊ­N„T•sÖÈ{âsuÒt?Ê™¨#AÛ˜la²a£v']¦”ªîÀ²L€@a3аÅÛøduÏÁdVÁGH5L8å ÉÆÀµ«Ä}*éœ,ÕØsN›çãYanªèß,\I«,¥ ñÄÖÙ w+Ä;cJ%0†¾ûIß%,K ¤ôJx aw4b&øk­K<,–¥ÏSÓ•0‘>OÙ “•B[«¬õ}ĶÆ+%K&²E.Ö çx fUiô>—J¤è­ÉÎ|7ÆhAi맘æÓHR´ [¥|á S÷í‡ÏÈ« LŠL0G*e'¦ïºÀVTU¡Š©ÖÊ3‡ó©$#ˆ¬–•¨EY-V‹if4ñ¦Å»dÊ+ËD6ÏܬÉhz"4Ý¥˜y€^yÏCÐ4@žx Ô±ø~OҨ寑Î+U"Ÿ²L $“RVYfnU¹”Z¡$M³µÅSjA,¼œ4ZÐ4 ýµ9za«5 [;˜8 ¤ØRz Úê•óoúÓŸì Ô9ÊýˆªD¶º2ÍZïSö=sc1ÑI ‡?«x%N¨K†¶ ó+i»Ö§ÇíªÙ<€ÎI“l[€­»£)ež²œg…ì°ið®¦Éã÷!m~²Í–@I¶²Rµ˜¨– Û#8N‚Èæï˜›–LiÝ'·ÊÕÖB*gJÀÖ ÀÂÅZ+iÎùãû hÛ|ê¢ïƒÑ —¦,€oc[äÖ‘óTÛw.@S2Y+/GÒd›€ÆV X Mbµ›¼©vJˆsNã¹Í@CœIYÛüë¥VdÓ [¸±S"S"Ý@JÏÂóáO`×Þä­d)[ó·5j¤iÙ6F“Çg^Dzœghm 2UÜ(aäAªjx«È$’Fzk)ǹªsXYAhž”V‡Õ·Öªú ¿{¸“Tµ^ôøšÂôbÃÈÄzI­c€ÀA’Q&îháÖ5µUh[•¶î§1<¦Zоðí<Óª3 \x(2ë«âÇž F(ïì µ²œ¯ÍyñвÄmkGf›U#9Kæ¦Í£œaµéóWÙ4Ö^$ÊÎŽáÏ)¸udØ0»ïGþJ>g_ªIb¶ªÅ—ªª.VMM;ЯÂ^E}­~©%h6kÌĽ副­”íiöœNU%RݪlOAÊÙ„ø”Öæçœy¼Áˆaß»6¤1ç:ÂÍlU²m³EÂjY)Á‡ùçþgPýšÀŠy…W©w ß4²@ÓÐu#òO$&èFˆ…*¼Ö| Xà[<A·ÊHåÌeCBö]™OT¿‚$SÕ÷À}cX³Ås«Ýõ;‚2瘔¬  %’¦ÖÈl“mÈx[)«Ö#˜ä¨{&“¥Ç$;êo°å&d @Ÿ[[ÛF2s¿¨!gKÆAÔÝ w [iè닽0>¥B[¶H`¶E¾Aik¥ì˜N x¬J¢™Ù®V †XdŽQ¯Êkƒ´ehUb+¤l­ kdµe­RÌ­ª»[)[€X•­‹¥\/,ûÓ’þ ž4›§ ™ÄÕ`ø×Fš¤F°Zî&çdÖ‚ìÇ d˜H€Ææ ÜÌgi›C¬;¨rötð"=ÙR²FÅH½Œ’"Ÿ3ßÓÉx$L¯5^_3 T˜†cšz™ÇÉÖ—#ÕTÍox@ 2µ²j1¶Èüw"‚4­Ìe‰»„Ƹ’sÃøáê"¥»” g%È„­­ Æ$ýû~ønFŠObŒÚn©†ÇÃR‰ÝŒôæ` Üžg¡´"cnþ|å*ŒÏ-C«H ˜ÇZS˜R¹­0˜îGý[Þ–¹lFf%ËNÔ¡(›ÇêQZE2++«PÒÀº.p3²MB™ hëé÷¼Æúv)b)+}™4•r8‡:Ò þÎøRv%UPâ+_k¤”FÖ~¦H‘ÙN|z<_Ñ^-Ù|Þ±«Â[¥g˜§ñåVŒ­h¼jÃÂjcÈ<\7lH¤r>€^Õi})ÕÒtŠÚÙ¤a8œ Ó¡ðΘ&±rÀ[+´¾ƒ)ª–çJ”ÓôekKïZßȪò„;/YYk¡‹*nÎ+(ix¶J‰J`ÛØ7óùªL(ýŒ“²…÷I5s…º§é¢lés%”x3ä)«ª[)ó¹Eg¡·ÒÀÌ7gÙ0¿ýþûï[岨¼=Ô”j¦ 1÷Ê+„wŪàÒ6ÜJÙ 3$`‚¾íV \­µˆìµ0Uµƒýìxf5"tQeJDí6,RSvÏ Ó=¬ ÌÓäÜYò¯Qæk¡$ =€QhíBàüm‰­¢r<Æå4óåócC• +^çøf½Âóì`d->eßÿX @©#P;k¤µƒø–þ:TþdB—õd3ÉðžïœÔC„{c5…΄ ™cjG@ÆGP•G(Á{‚yúSA­eÍ6R&Uuβ¬ÒHÅs˜ ˆ±ÂÄé­Z ­ñÍT˜¬ËA5FÕJÂfP’rÎ4i8$ Ç“a„BçÕůªÄLV«ª¸-œVH +†m•·â,éø0@…VLÝ«*õƒÏGŠ›”5±õGp‘Éèùïã\*àY#aþ€s9f#©Ý›à°L¬¿ŠRKFÐ=(ÇÀ€`XÖO±ü«'SHFÓ„xÑ/Ù)ekÑ0Lð9÷ìèkW ‰1¿ñæÐY:¦”rb†Bmƒí¼ÊËL¨¤*HU>­ ‹ÆÈÓlóìºló_¶^jÅ08}W‚‡Eó¯ŠXØJnÏÌaMûbÉ¿J8qnô 8Wëö¤ÈðÃmiÄÌ1ïÑب®Ez+7Ûªˆ1€móX D[)À¡²ª£×  Ñ.skÀlJ`½xê›Æ–QKáOÁÌ*[àÉP„§©¤,Z¿ò󟶪Fv]øÎrÜoVaÇlªøÈßµpÀw.|U@½Öˆ8+ qW¡ ìq VøclYôZpë9ÂÜò—¢I7Fƒaq=>ß~Ëâב/²ê1Eªítô[3h (—ê Õž?  :"©+¾ÎÂŽ²,àB B³d r<\× ;FHU5“ëô7ïÂV! lÍo~Yb…«­¤#1 µ|œh`Ê€UÈ:rØšl­ã‘õŸ¿bh|Þ:¬UÐóô ì…ÀäÃDØ*Z‰s£Ù0eñÄ\¦„{޲ñN§Y_mH>5’b‹!Μ#kE¶ÐèbÅ[DâF’2†•¾Í„9RÈJ…ÍcM)Õ¨ "•è"öÒï8݉­¾kª„ØI¥âÜ®%²îmJš¬Ôn¶²”…mM»=å•XUѬæ© «Ê ×Ñ W2\¯&O‹ª*´¥·š¤cj¡ÊŠiȶ³Ía…À0m…› Xp5ýQhët»í:*¤Gò„‘»%@\¿a¶dÍ`åY9a™-}%V2n°^pk€  cà@U¶‚¦9áœéûèùXI‰ZMh5› Ïð4™geµ}CV6qÙ˜LªJfõ|}¥¸˜X/“˜¢†¢oÊ<  ÜÝ’hg+«DVq=Î÷˜ ñ1‘ d½ZKi!«°ùa2žÇâû’d•t±ª(ÉúXµeÐü˜†¸¹•µ"}}·²Å§‡)­É€¾%ÀYÕ²ô°õôøòd&4UV 5Àwcd¡ŠCVªh\B>²ÄHš¶4ƒ†ñÕòçÖSÊZ0<ã~?kÀ«ñD<_Œ˜FI]&øsž{´4é7 ¬dz'JšŠ@Ióç ß¿¡”ú1ªÚ¦­•`«ÂôºíOMðæ Ûà …Q÷ÛÊrp 0ÙÛ«”ÂzIHGø(„©ZÏ‘@̈Éß̪l9XýùÁðþÕ )Á)´*´Ý TެK/”4-gµ}âÈØÊ¾¯Ö†¤U!kU«X;n¶ÂÓõ dúdÙ¶r(*Wdkíª`)ØÆ[Ó3w( 2·]‘mÄÄÉÜ'IÃMôàê‚ìYà)m‰ÀÀ”xÀÚÁ¢#Kù» +C * h+Ë®h‹ïËOߨõšy`Ùª&®ob“R ï*ˆûë_ÿê?R ä¸$ý1.2¥UJ¬P ßÚ# v†/Ÿ¸òéßФ,l S}áç? úá¡öD» øš}–Ô6]èRãUTßøÉ¤È¿­kÔ·Õ„½F¦ X{ÄÝ

]r“¤¯ž­r>(¸™Žl…m­½lºäf݉çóÿš“®h¶¥š¶.ìJÞ ÞEÉËZµH‹ü;oŒl[J€‰us:ÛP8=@ƒ”U%jmÅà•4¥¯zb|ÎÍ ÕβV·¤Ÿ[ÛB¶òÛí´ë¡ÛºðÆÓ‰i<«Úõ²±r»»Ïb¤l‘`šL–J€$€«›ñ‡.D ›ó·¿üå/î´g/«Îê©1,[¦¶0AF•ØÖ¦B˜¸*«°Uh-’u†˜d[¿ÂÏèãº$ËÄ*Û9Ê<gÁ$(U [$¬µ6•èdYµÊN TNÈ9«Lê^-†až&á):l…L0ÖÛü×÷`¼Y‚ZsV¯Dñ>ÕÔVà‘MX;ï\Ɉ]…ò”ùÒ7líø{Y•û"ø»¿û»|J‘å¬6¾aÂV²éb‘Æ WØ0°ˆ”]¡!ûÈiGÙG¨ ¤©¤yÖŸØÑ`†‚ycTHï*bh|új+§Ï¶­ÕV…»ø9Ácx~¤÷ÉÖ+’ùLx nõujXHÁR”Öy¶%ÈÓ6& ÞVmžÍF‰„eç“3“>ŸpnA`U[ØÊ¾²+A˜ Ídme·†Až·E‚=tVxëŽ@P¹ç‹ÏÙš¡•@Ð÷xg\¤©Ê–&¸Í?7’³§@\Êvþ̽-ëKƧ”ªÆUX/Œ*²n…H ©¶m#­V€F­@ž^Øv:ŒÚ¶Œ­È)ºÃÀÌëEs+>%²lóËb6-7|”j•¥Ym“´ÕQ¶*+Œ‰T X#»äúb”‹4ɤÊÖn0âôx;ˆ¸a^¦ ®Ëñý~}QfRÊZÊêÆÂ^ XÙú:5WZI&Vüæ‡1"è_²òšñiÈ•ûÈt'½`ù$3±•C“bVÉlóÌÁœý°Å‹†I¶Z> 9¾hÔ×u¤Z> ™lûÝSævÚß¿–êûAmV?ðô•œ7bÛ¨œ­™óôÓM ãÑHõ¤0JݶÕÍs ¨{Î0s «{¾ó ÀM!ÒJV0´¶•¶VLXmŒ-†@ß-€ñRJåÓZÊl~”Hí€Ä ­d9gΖ¦*x„ñdýÙ€'`ňJ€wà°Uù‹‰sÆ'àö^2¾3rX”¢Ç4*M7/åìÎâ®eÉ´sRáHµÂ–Æã&€kG‰ [aLÁVÀj™H©R‹¼~ç¹ËbJ•­]GK ‹€_´ŒÚ+êvùÐùRlµ&†;¦CÁÓÔEÇPÕ‰”"UZÄ[•¸À󯩧CY±ÍÑZqk©zk JI'!Ž·‹†&h‹Ï?ÁV…&³Ê"Ç«¾ôÇ6ýcK©Öíxkkg5ª*Ù‚i5UóàmcÒçcý}>¨éãÃÕvÀÄDó _ûÏ'„©ÜêÞÆÀ”ÕÂë#i<%B )jžž ÆÊ9 U ŒèB¸ÍÇ!ýCFúÉ2~ã±"‰Ýmgiž|¬< åˆÉrà9^ª9Ó[ÇT•˜3s8Á ;RS•:¦lrÙ@¸ÌxšøNjÊãaÀ¶oCXÓRú¥P9«H«Ÿ¶þÛ&îæ@PS>"‡‚);…­KÎ)«öï U¾Ž”ù«¥\/2)U”5"€›'gbŒ˜!2ÞZ*mþ'}ïÖÓØ­Jñ­É`‚4Ö¶ *Ùs—5Œ8mî Ö¾õÎgàû·õªŽÝß~{TØJðãr´CrcRk÷°²j†<ûHÙ$Vµa¶é)ψ÷ùvKæ´•Mi«JÔ_mƒ¥™Éu: =e>pó´ÅÇô1ïT2ô†Gæ!CÚŠ·µ!½{ư•ÒZq@!NKÁîM*MM‘±Èt¯¯µ ¯‹µá7!=mž²¦JO,`})m 0p ÃLÖn~š%†ÛÊÄm™4v 嚺T5>৬(EVw)XkÀé8ž…  @P(‘ÕÔ¡Ó0ªøpÀclutEizFÞê[;>Ê1ÆSiË®W|ØX¹Ä|0ZT«ê=š¦^¶e³jýáfåôÄ 0'dEØ ,ø`ÂñV­Ó÷m\w¤¯h?øjml…)g‚é>"3ìŒ ewp©>éx§Noe(€.#B¹5g€Œ'ÐêD¶²‚8&³Õ—ùÆ»ªÏ—Òœ™¨’2LT¶¯a½0~®¹+ãõà*á UÄXi²«ÈÁ`A3P¡lgOfÅ/6=¦”ÓµÔÈêBw§PÒ%Iu]²ž…#ðQ‹§!Fz¬<É`LžÕv«]-YJo#r%° )ø(¤'È&ÙH 0 ‹o¶|ꢰm3èÅ„ 3Iœ– ¯–¹ñwœóX9ôRRHÿ'à¤(îDåX¨7mçÑ£@¶€;íÏ7ø† œ¬*)>0b(‹xd|ëHDäºÌŠƒ™¦¤I¯ßÝ!e­«T3[EJÉ0ÓÃx¡ÜÚ³‘_£Óû¾SºîÈž:ñ¿þë¿z5;‚lŽ¿ÆŸlJbšG»†¤Á ½¸¯OÁvn(1‚¦¾€ÄOÓj°>0V‡ò-€7 † Ö1¶Ü2¬]<ÙºdÍŸC†!S ¤±Úò·z¤‘`äÂ/8¤1¤È¿,Ìn«Ö¶ó–‚9‡óá€ÙÍ+‘ÍÖÅjgkmrå¶ÄJÄz5$’@¶M²#je¥˜Øºöd·ú# NO\Ïl‰s–J‰ÉÇ6æHµ¶€hf…pÏBŠ­ð†0š ¤QX-qnVÙª„¸ÙZÛ–¶ÍD#Ø´¥”7¹,¾Â§Ÿ¬ÖÈwN¸Yʶ™cf¢ÊÓ±êN¦„ÆŠfÒYð1ÐVWR¹- öfÎâ†e«¤Ú& ž2 ›`%•Û YÌ+†ËZoõç*¶]cn€f°° 2Œo«àãZ6¯9,ð¢Áèw“ñiZiDX¶“¾Ç,ÕðÝ0Æv«*|íXIi'`Ç©ðX™§  €´ÒÛNfKFÃ?«~‰¢Œ iÕȯCH%u„…Ú¦b("[É: ^ I Sö§¬æÏA•’ksž­¬Öô¢#0!@ÚÒˆ+!'˳ZõB–ÌzJüÿ :9)¬_F& @Z©mÃÖê‘>} ½.4"‡ Óðû‘î–K©-:?eѬ5¥øVœ“*!UÀuQ([H5'€éB™d޹ŸÏsÇû/™gåV±¦´ðÈü­.DS/£è~¬RJx&®) ¶æ©d—o«dwÕTôV¶G§ (³²¤7L¼­ªˆÉòá™IY_—}fÌPàé™XaþLÚŽg–U%kBÉMvz¤hþúÒ“ñ´JQZ¥Ì/ðp±MÀÛÆX:  S°µ²JÀçØ}] ÎC¯ðz[}n‰‘>/½ðŽÐÍ7Ã|˜‹œ¥!+˜ `¶ŽÐÍàɬjUméÛ‹{x ¬öv;7ÉhšŠi«‹*ax«’Ue à4µªêX¶1¬Hb€,e©+9 “H‘ þ¶x«ÊÅZ“Í$%r†Êes¨ÐY(«ÅËbÈî6«z±šŒ2qž¬³ÃªZ°h†Î!Yq€ñȶXÖªJVëd˜Å1ýj†ùÐ ²È÷IÁ"AkLk-6ÝT)Ífë¶ÂùÛÒ;¸cÚÖÞpcc2)Ef*L³-«*ÛĹíP²(sU lÅK†ët>bÄn•˜•0+Æ<Í_ÖÊD–¨]ÊZH‰ µéMÞ£ï v¯MM™œÊ•X•ô”­F9¡.VbšNÐ`4€È6ÌJÜn¿^’NG€g(´mUZÀËð‡™Ðd5ŸÎRk+YJ)ouo»”BW”^6·Ú±í°•äÓà™À ¤h@­”¦y&ÃÇlYAlMï&e… épx­¯ðóл0,‹4eÄ­9§´ÀÏ?Rëž)¥›Å|Ò¨”x+At3cdé÷ûdâ «••—¿öç2‰Ù>Pɬ˜Õ—Æ–¬èJkd-è•'Vhl<[«kqí ;‹,ÒÖ&Uýã£=ýFµÖ=qVHU€3Œo«Ež¶=…NÊŸvóÑ A&ʵàYO‰©K䓾¦µ³aˆüíÏþ³šŠ­Ýk.1tŸ†Ë>ù}Ñôc’¦PËP4º*¼*LµGÆ ‹†>•÷qš$[k%ëBÀªè.&Hl+› S ;WMsËŸ˜FÖ‘â€4 à "gÙdôR«RâŠèý–IìÑÒØ )[&¢¦H`0ÄHxâzy"l+±2±í·[Î4 çài)â¬Èð^¬UÛH¶6²±‰µÎy#TËV à&…QãaÃÀ"g€iÎñd‚@𱪱°¥¤•#ÉÕØ«×›F;€Hÿ®Ê™wÃj9åôœm}eôˆk䀪šsƒ²Ž1 ½m-8÷0¦¢ÿøœ”Ä4vzL—$ÀwW­x [óLÓV¡H5&s)ÛL0oS)úeiòi¥ÄXELOÁÖ}šÇ@_©JlÙ ¬‘lÐt²Ê×B‰m…@UôzuœczC­¬G³©è÷XñM¢ŠrSÁzÕN9ÞY¬Â–1%¶Ÿ6÷êT!¥®ðsKi2·ÒsÈŸR‹ÄïJ“€› µÄSb<n¢y¼ÞRx> mñÞÆ²øFI&M•¬o¯qÒß΋³Í`êc%c"`+[2/àÜ€¶d2+7#½X¤d" ›°É÷¬ik%hŒ¦µ­ckÛ4d)¥ÂzéRáíüù˜™Ù”æç ½oЕæÓéÒÔ îµ& Ìp<¥'¨+d(µ ´•9dŽ7a) 1&µ7 н”P ¼Fj5¡±dñœ×V+EXÊâžµH3Ab±rd-¬Èœ Þ4¢c2wyÂdAy s'¢MbU®  Á[“þÁ‚É™'‹Ï¿‘ÔÚEŪvcëKo僤T+=¼|%e[i\¼åV*Mæ€ù ðpç)•¿5þÉ”‹x©ž¯ã` s ‘ ß5±-kÛÄs«Åæl%>Εãi´Ë ° 7O«ª¤SB­­×^‰ßŽl>+VúñHiZU|„G©‘­ÄïùW…”¢Qô|mem)­Ôñúþ¡ë úm¤]x ¼a`Á ÿºÁçŸ8dG¡S"p5=Θ.Zª­Ú›UH•í²ø ɺ¯n©D9²[ñ‚@‰Éþoч§/›^w ±ëke8 >Î2\k2Œ”€ù[ý¨«<A픜´/ÍæéG)±­èJ‰3¤˜t3V—ÖÌ­é P£¶ü10’Ü0^5o£œ ÕœC‰¬ðè{X®1þ]w”$Ûm$[ôƒƒM2ÑL»ð°3½ Òëø€œ“Yu/Én&HL2½2Á»ûÃCmÇ´êU;æJ„mÙĶ€,RèÂÊÖH.¤*†€U9Aq|ïÍ7LëíðyÈËŠ´Ã3Ä”Åä¼K¨Ö<°Q‘ù«å@lBs²%èÓK/ÈÎ㼯eU€ÈªÖó!h††´ú±QÊ*·@žãmKµÚ&Þñm…Q­ëU†,[«±ã‘Nçò4†ØSYy²4kjK¶Ù(ïf2™RÂnµ™1]쀃pHlÅÝ;`Ã4ì8xL[«-=†Cb«÷<Œ—2·]Ö¨Hå¼°¨ož4 k‡q3 TϤQ1B6çÄ‘eù«sÈ„@¨µ4aÊwíÈòÉVåò;£#{(«ÊÊgA-RmU‰½?H‡U8s|_N ãÔîfþkÁwi½“¶ŽS¸Z«ÖÊ(…ìkAÖë4>P­”0|κÀLzÓÁ–’a>µî–êÎs|X“­É¬H†M. `ðá<Í`Z33$;‹7|¸.<{ *´­¯Õ—|ǧ·%Aé 2U…“åÙ´Ó=n&Ä£Y¹,@À!¬P—Õ°¨in­ºH%c+rK\йˆq‡f kEÒ÷–H%4^!1YGÓ ¾l[ŒZ“#Édë~åçâù[1²ñáÆ˜¾ŽJdÍfU¶f°æŒñ»,,<;)åpGÚæo[! ,»•¦ãäÏ!·Ö¦‚R_˜*X¶m2dξG¹ñÍÀ ŸgUøRD©†$@°^ú¿>éi8KéÞØH>} ­Py²ÙfÞ®TÖWœµ*l0$ç¾Ã ºàÃÍÌ– ÒœVO9Œô÷†Z,F;Q»^% 8Ó°ÂГ5?RÈrë¦$€A ¤y"™[}HÁÙþñ×_Ù3"jmb:[:oŒ²Ô@ƒÚªâ®‡Ødmñ˜&ƒ‰­ôÊëE†)êÛ uäo‰­‹oÅç_Þº¨z H­RÖ°Š\d•¤Œ´åðÁÈ”À·è,Eæ{Qh¼…Ê‘B¡ $–ê6à|fȤÃbdM"`¤ò%ÆD¦„› 7ªbø ‰Åû$ë;ÅTÈR°ñlui%V++¥ª³Dö€0+ äž5F£Îȇóæ,•,›?ƶ'ˆ¬/€|#·˜°U`taRSkšw†dxd˜ÞçÐlNŠqFWaid¥Ì´ÕH•+ªŠ!A·M l²ÜÔ27ìó5%7&¢Ž)÷P"›Ê*[ä–²T>°*X ØJÓÚ¶©`ƒIÀ"$l-tik­#‡<­ùX¥\É+î¼È¨Üš3e¼5à6libšãþ#gB)lÓ¯¤az‘j””۪࠳T›²5s‚4Öý¦ ï Q д· 1š `%)µáÊsK¯dÙë÷ñ\¡,j¼-åM’säd=8)2)«3zv¾.{iu÷Õaë=QKÖêªU÷þ~úð˜üõ n! ·²¥ªåó¾ÝÁÄ_'š­lâ1œÕØ<ñüÉò÷‚mì²:"™Pb(ß2o-ׂ^ÀÅ0L&Žââ€Áw‡:Zã+$ˆ—2ª-1¦StQ¶øœÊÓô°|­ùÛ=Rl­°ð çÖ1¥| ™,0œmó'ƒ­‚-“ô#OGæ¶1L© ,øÄ+„¥b’ÙR.ŸXPˆÎ¶j]¯Äô•ÂT|¬õꨊ!ŒaBc¥a.6 ’ÌVÐT«Q· (i6)‘ÒºËLc@0\aòGšö%Þ>e>z¬`b-L.hˆ•Ìд&&¨Ä¶¨ ÎP!«ŽIF¡Tþùôu—ÀJo%2't1ðÎcR&cÂ<«ºÀÛæÃhÅGrbÎ÷…ŒLì‘é(˜ ¤ÒZ4 ü¦ú¥¼'"U—Êù§¬…µyYaÄÇýûÓ³ÌIYGUƳeÛm{ÜxníŸ&õ¯ÕšU%²ÍfUUGYn÷¸Ÿ§câ01žÏ¹µï2<ÿg@‰úþŒ±¥Sã…X¿fÝèB)ø–M\3n¶¦ôH#%`¢f"Ò¬™¬y0Ä4ç ³ªªƒÙN¼ÚÈÊáYˆ¬)Aîƒg`¤ÇCæ8ºÔËi I#ÕŸšˆñîôù`DMV­=Q[](T•=Œa J)L%{w `$ D„“q6°IlëÒ¹0¾}ˆuÏ“¬F¶MXÓ|º1Xà•[“anÛóGJŒp3²¦5[¼ ±0R¶¾û0ô©k.d!‹· è+`‘†¬°±µn+c‘³¾__¡–@¬‹Â†$¶%ö5¡‰¡­¶ádpYkŒÈY l$ô%h[9™­•#vXyæÈøJÄRuI|,nØ.;rU]H‚Z7XàRº8] ’>’0M—œU…º“ÑÈzîž¾ÀËâÛêHã­ÍfíËRÖ ùVÒ00å2µy6•låÜd…Y¶­NA#š‚e‰a“4 L†¯KkAX‹‘¶J„y¾ÉÓEhŠÿÔ? ÉG–F ~šð@—ïcè\RÚ·o3/ÃNd†® ô(é»+À<Ùêh˼ 뾎͹T·Äªyªµò‘B; ò/E£D” aÞI½0ñɬ·è\E¸{€1ë˜[ú’¹%æé¥ŠR™—í8¯³Ân©Ù8ÌœIsÒ U9‚¨çTÛØeÈ ž Ó{p˜ºã #%zÐNM#+šÜ¶a g)zƒÅøWtqŸµN¯¤¾µè­\UåeáÙ¾Oĵà¬$g%^ÈÃ4•­ n0zG²eX¹B¹1\fN|óç)Ó(ÁSöÎÀTk}‘ÎBc¥7mGãSw‚×õP[¸hŒŽó”p×F Q;c#ÓÀJlǸ-º"©j1ôò·Äæ7R¶<·J®êl³íZ`V M&(1­di‹·V›a…Ö_À0dÈn¦^½{s8ÀMhÍÒ<5²fB)Ûƒs@$=ЩÛÖ1b‘ÕÜtKçÌßSSÂu„÷°àJ¤„^ÉœÂÿQZôÅ; YóÓûzäIÃÁZ ¬°Z嫪›¤°•Xª¨0†3Ð{&ëñðq@À;äWb#ˆwÀº¬£”©œ®;I ÝöÜÁR¶ЗØ*â)»@[^&É_Ê x£†Ó¯V Ä#µ8èÒJ&+Åü Ï$püH@p AdUV)÷ÃÊ `uLä>¥uG*,”4Ü®ñÏ7`ž²¿ZTHÌmØ¥),•!,ÕÚkbÀ<­L ÓI­F²å©<]l­iÖ À¿ô,8 g«ícK +:Py½NËç…!–½òÏWâl•ËšÄý:+ÔQØAØ×†F`RÊöªKudü²90më6ƒ0åoÚ² p‚­cøà1æoEb˜;Ì_äS¡T%Çýûû¢ÜÃÚØ‘WõùÈ(tR4‰i2¬\v)âÖÚ)ˆ1½­!Ý?ÀHîyWÝj¥º7_V‚LSµ ° ƒ/Õ„Re9ï̓Ák-r«Š|ƒ5FM)#­™ð×ÑjlÀ¡˜(•›;¾Æ™ÖÃÊj‹_ ðaÒLpTòŠs¶"`H†’­unUý’Ùö â+éÙ£í½ÆöKža2¡…È“Æ$V†ÜÈâ“å&UÉæã»ÊJåiÞvM…ÙÁÈnR‹Á¤Ž¹Á;) 0ü3¬QÊ­Èá>ËÄsSn†Í–U­d­z5UÙ¥”Ykèêè·…Å™õÆZŸ²[ÈV!L¶v™ìUw·RÊ]u…–“Õø:¯$Ð`pÎ uÔ P…·V3> JÀuz˜(læ”™ )÷e(¥E@ªB8=Àd>)™¶…B (1’U0¥*!…Û$n^Ó ñª¬ª\2RëÜÈ ]r&# ì“…Ï Ëþ ¤˜¶Ä‚É›¥YH Óä™OUš <+¶xcc:Æ»”O© 3©V¡¼*¸.õ Ç7Ïé“I)”PÆ"«[> »Ø}j:7³×HŒ‡ó—ò…Æç}4R”õJÖIã•Û4K1HþB÷Zj­4†´Š†h¬éëk¥÷V‚-h$>¢Á…VJd/$Cú}+1ÆÁ>8³RųF3o«@òTË’ d¶½'m•*±XuL¤±í8²˜°ZÛº¶fõ¤Æ3‰t4©lë’óªÏññ ‰¶ÜŸæÁà1jésê2»^Y&cÛ˜º_ïÏ÷Òqÿ$>Žb)d­ €I\§ÏU }y 6+X¯ó» fÒÚ÷Ë„ÀXÕ¨WcKVïe‘¥&™mš )»e‡ÄÛŠ¸á2p¨VŠÿZ e]J]Ô£¶rŒµÆ×”Yëmuϯ)><ÿ>®0 %z¨€ÁNïo_2!u&»W*ÕüªàR.6[ß9ÃúšIÃ`àZ3´Õ²ò(m¢£GÂE>:*—ÒÑ£‘6 IÉÇzzܾd˜s’ïƒk+;ó!PØYaô²5!¸yúƒo}þñµFÞV?KÎVš|X1tMŽ!¨,güK¯—{[‹ôÜ0#›“`$]zvñ #«#Q9 ‘¬­ZÛ0^`šo —ò ̹̆'ÕGJÁÛKÏV4 {2Ùâæ?Ëäg úÆS+f…¯ ÙÀ¿ WTHÙüV¼QYe+;Ûªl=WQ!@)ºùZWޤÔÂùâ‚E“gKL SfÛé"ówÕÊ)½‡§ÍÆn«m²²ZJr~¯_ë È:‚•Òê ‚î ø€50­9¼UI) ^¶%&¥íÄ ŽËó¢Ä“ À è8¶Ü0Önþù•ÏQb+1A>õƒô,ˆàóW%¿JG7 7%ÈY¥Ìgkn]o/=%&®3p#ÉÂd^¡ÆÖ…8}í~ o«c @aJi”Rªùð$@Ú6@Œ·r@Êz-Éú/ŽMÕ IežÓkl¿7(çVd´['@IDATÈbÛ*ïXS<)Õ€òºÇÔÚJŸ¡,ÐTÆàУïx&Jú÷Ýëb<ŒP«£BÖÂ7°òjc´Ã3Gªzd9Äð!î V)|_þa[‘ÃæÇ$æÙlÄ|² ¬K)c$îsèên‡³($²EÛláHoßWMc¸²”ÍLêU*Ù|êUIb[‚Ú½Ê[7™­-¥kô š<­‚UCæC¸¼rb[SÙ¦Y!²,æÍ&V[!ÐüÄ“ÕîýɈ¹Y»€¡{³z¾µTÕ:MØêÍï—{>¶Í°Ù& ûÑP ±Á«*2)a<FX›p2UW~.ïöºüþ¥ÿ¶ýöŸCãeã ¿Ì )j—?+[«r) 57šóæÖØp¥á€—àøÝ2R=\e^V«,Yx£”eK _·Óy Éxg£g"l_L&kï ïøª:‹ZŒP¢‘Àp¨OfEвÙÚÒlKfëݲêŹï,@ ‹NMü’Üš!àæea#Ñ—j<í+¤š0¦*å4Ê¥Lr+·FŠ&i[€FÖC43[@;ŸJ‚ÆXý®E•Àˆf°¶½~މiZ«Z[óœQ¾ŠðiDzÁ"™è.0pãÊ1‘yfhHÛ†)‹§GòÄÈÚÜ*1I/vþMr|#Þxêy~+~þoc-ÒЋ—é+µSð¯Dlmf¸SÈbˆÀª‘~Z~ß ‚RÖHáI«š-ÒÖVa¤ |_0Ÿzarãå–aMá€*Ø)ú­Q‰î¥:µr¬×@Um+IÐ02q„xåHʶ» cÄK ƒì)”RV½Ôbh¬&ÄHY­°.lßP»ˆ§ì®€14°vù´ GÖ·yRÒøõÅH~•é7 L2OÁAˆc¬B•µ¦R ;ìMžRUY&ïÙ‘¶B qó¨uŠj‡ý! T»ÖØ7^ÀbïLµL6ÍLªMCoË¡”Ál[‘ù'ëZ`ÙVÔ¶”í[¨Öa1 Û4R…BÀµXy‰Ë6@)«Á&èýšÛ“".ªµfŽZÿU• c+e W²-&ÏͶñ‘µ¦ºøÕ¨^”®HÖÀ”Èu¶ô}rñÄÝ}¼wR¡­Ú·ió´Ê²UµÕÔu -dÏXß¿e¸IÄB­|k©kpdÍÙÌÜ|ù ã×;¼a8(ì,€måÖÌ)èBL[LUH×¢Á€óOôÓØƒ÷õ'mè:±°UfÍ#ŒŽì¢U &ª¬ë KÍ„2k€‘Çè JU7ŒLÏ¿œÁ–LóH­*ñ÷žB‰ 'ÃTX£œ­5"€ùˆ”¶;/RíÌ¥lEà-ɤ»ªÖ¶¯í²Å0ô8zk‘¶‚~+’á¥?ß¡a&B*%ÂIe_’¦ONÃH 3 J+>R-‡Êoþ,¯8YüÉS9²B“3ï[mã–¦/h¤ªõ»`z‚CbÊÌùHEÎI@Ü$«9ãQjJŒTã!¶ÆXÙ¶òìùÖZ#‘§ƒ0)d‘‚I`奸ø†’¢7FÊuè+‘bT…™( ÿª¢©D6Á@¼uM=ÅÖ¡Ìï+fîPùt{9䦇"†صô ²sUKØV#V4°Mc ìÍ3ÒÖlL«ÂV‚îÄjó¬W8‡ôo9>CX(ǘ¸IÌãu¿ªÏ›CƒwV[ØMÚ’Ùf»£!Ç ak†Íoµu‡ÒMb+µ*ä‚0¦ãT;€Àj0 ¦em5õ6ÖÑ6ÀªCù£RuT´m¤­Ug~ë>ŸMz¤^½iTÛV9*+F40 u‰sA )ú¥Á¥µl<\!Câ>¡€¸—ÜaÉz©{]ª•Ò‹!™µlçjåü–„« «Ê™X¤s!çÉDÔ…  DÄ7‰Õ¦ŸCƒY½~ª(aÙJjêø¶°•¸50F!=ÒjHâ&RèEß÷˜©Ø"À•§·•íÏ=0”Bª•U¢Q¦HOc«Ö– Za )`°X9Žo R(é§3± `Hˆîßœñ9HQ&s LÒàW^  «*kÎóW“ɚ͹*Ä—ª—¬ê¶ÚJ-0E2µ½r½¦Å4­gÁŸ,=~&Àl‰ÕšI&ú !)û "›íLæPU¼^¶Å˜0L½e_^ê=”m­iê‹sè®èŒçoÍYI“ÔT¡a¬# ¤"Ãe‘‚g.:œ¾•€^•ŽdI .²JF°šÓÖš?,ðP«K[+\À:ï­8KG®pÇA†&€#¥r¶p¶‘æIIœ'e ¦“*ÌAJHÅÔ³ªdV#‰ø[ô©zðy™Ê5õ}ç+©ëêcœ²¾Vóߟ.˜ f*¬•s_4¶@àÆ«W³½å dëEÓeÚ– ðÌ­-%Ælõʶ;ì,x$+¡$ ø6€-­àé[Å–OUײ7³ÚÍV-¥¬U_Q‹iQa2†dôxD—¦”5 fµ9X1F}ù¹ÌÜ6`­2 “T’RSAÐÆ {ÖYÃ`Èx&øVcûìã7€rQ¡*¸WOܣɤû×®.€hBʪ¦±åFÐEåœþt½}i0ÖŽlí—6Œ‡NÓ)€5š^ _»|#¤Xuj€&µÀ²Â„ú¥` ­U+ówRï0sËœ²Z…Bk|a0Lz²”&ß KÁVOj§È­ªÜJaØ2ÉÜuÉr³Ö%>†­­s©½ÏEåÙ‰1•Û2™9Ì![…€ ¤ïgbÅ÷,8Øö|r†9d &¶ ­Õ‰úîã¦C¯ð¸|¯´mS@`l½ðá¬0ùËb¤¬™¹lUVŒ*`&n«PÀ¹ÁY ÿÊÍãÏ1²€õ|÷qrgÿHg;k·0Ye;CÐ4Ê¥lŒ¬°Ý‚FÔÀèØ¥—u€â¨Ÿܽ¨ !·ž“Ü—ƒ òÔ_#5Œ­”¾}%5€UVª©ª}RU…Ä" ¥¶#+Çt^“t!HVôØšðÁ°Jø Äö¶YEÊZ°Â7^ñiâ'% æ=yDµx¶\¸IgdΊ Ïkµ]4RœáîÍç9T÷À–¿¦Rp­ô»g˜ ™i»¿C÷â6!iT‰ñõå¯#eóà/pÑ­²"‹iZ•#›¼B|ì,æ©pΪœ¢­•RUdnø•¼©&ñàg‘"ëP¹Y›¡Ô<é¥""ew^ÊÚ0@ULÒç6ÙÎ’À‘+±bæC¦¤gŠ[Aã/€-LÔÎÖÀéó™3Yóï2p¨…õMH ˆµ°ÒÔ7œ fµU‹‘uü˜UùÜ’'†2ŸU/F¹l/<ÜüR@½8Ôˆ!RŠ¡v²Nj«6œ>[kïdó,eËD°í&a>Ä¥€†áв4x+ÃXÛ*)Eg¤I&%JY» ýNäK@/z¼òÞ‚¶•Ø ˜ŒOæ«/èÍÓî\ŠR>p=ΜAlm«\‰-O«m⚆9ãk]#ÊRu׋˜–²vºp2+A…S"óð·UέÀçoõ Ù¨°˜a%ͦŠyÝg¾ºl¶d‘­•ª¢™­‚ iݨþ®ö¶(ñú„R"1ÙVBƒ§Aö1!›<™î˜ž Œt"%”¶+ û¤,ÕTVY‘m“ln~ú UÑ #al×kµ²øf4¢DêÞ´)c²i’Y›“ÀÍhš¦ucó‘"@bt¡)…TÒÅÔ%gUëÕØªÊšJäÆICÐd²é+¡Ä„‰›!¦B+0¤yL)`Ÿhµ4î6`²5ÊäÊÏb+2iÛl5å ¸vCÒSÚãݽmŒ•Ú´4”Rmcfx·jÁ&ã ØVb‰©]—f[9nZi5@þ ±­‹ ^YïUƒaÖ u¯‘­ˆI‰lòÆàxxµVÛ˜ŸMÕ›@“Ô*© LÖÄMïÙcd»e2ÉcÊÆEôu´¦ß¶îÛ¦¬5[€@ Òj©•óob¡‘Â.ÂúŸÿü™ÀÊDaþ¶@k]–âTu½Ï0bþ€½ýÈ?qJVRBG«‡DÜíahl‰¥®å9’d_úþÌÐ{ßwD]¬”ʵ¨iŸR<ŸÜ¬½Ê]ˆT…ª¤nšÆX*½-Í¢ì|hDV¥ø˜'Æ$Îî8΢Ŀ?ºûI°w¦‹bE¦WÙùÈv9øZÉ€ðägÊW k+&ã£0qÆ0È4Hà¸Cö5OLÖÌei7a÷éø’X6•8}L­HLnV¸­‡‰ËZjáÑGZ« ã1÷%Ë3ÕÙïÄRx€yëÆÃ¨5€U_¼µIÓœx'…{"µh`©¦ äŸY£&è83lžN1,›ÀÚH—øùì0Ä‹œ›°¤¾Vn£»/ ÁZ8‚ªxkµ˜@ßó…çÓuÛm÷›‡¬vߺŸòÌé=šÖ/è<>5Òɧ^pó4m¦²¢Áfó¡Q+”9`Èr€¯Ç™V6U;Ça’ò¸<7Ö˜&4öÍÿ,xÁÅ™áÚÅH˜³á—ÝyÙæÓ6°l iÛ}*irUôg‚ïRŠÝIítO£¶ª@n¥d•#óœ¦ÛȪ§™Òj0«r…"+±FVJú´:Nï@d³Ž”@iÎÆ&¶MŒÖQJ¨ÚÁ²"Lªª×¤Ùnݧ¶òÖ<­¶‚aþfkkì›9¿o”²Õ¥¾cŽõ÷©Qò!Ëæ6Ã:ÖÈ-µ¬*¸¬…Ï ­k„™+¤¼}~^EÛÊe }›ä›Ock-x6!±ÂÊÓD†3 4^× ×(«Jú¬™¼£YÉÔÊÂÞ"äÖ1™ð¯ LOÜ œ¥Œ$­5ŧd׳!ý^ä'²ÓVb¥L +bY+œŒí÷,ðMØ´[]lÉl+I™ÒŠŒO 7Æj_ OAÓØiÚ&³þ²› µ›R¶ò ´Àà=ÍôJŒDcP -ÍÌ+?çìq0\\×cËÁ=ã‰=¶ÂŸ¡îéä ¯T&Jzú’©æÖ‡WUV”ù¨¶MÛfÎdz©1Ã)7O-dñZ[÷]ÊGTP^â,Ê7ž™…K#À§Y»ØV‹jɤü¥u‡uR|(1²@š×áÿ2çY +Ì9„ùÌ–¦I&pp¼Ç ôhd«o¡Þ ¼P+%šM€l[ß²R9·=5ߪJšN¹,“¶ÍŸÿduiÕo°=¾J¬xOJ¶u9”B» aåÝ? >qµ²µÎŸÒöõQBóêm»4@dR;«y*…"³ % †¿g!ÎnT# sßáFT•…7yí’yå²úÐg‹Hš<1°Â€Õüa…Î%+8ÐUe8¾V…DšÖ+o$V²ZÏ's+R¨’0nÏ`@þÙÚê˜?Ì_}Î^{ 7 Å&$cŽaeåÙÓ UY§OfKЪª±ðÊ'+þ”‰eÍFfËÙ¶¦ €ñiµÒôAÞ—9[¤ %8ϹRHZñ…ZŒlÆÃu7öReÏðDþ§Þе§k%ªqFø¢{Gî ôi€•(·uì¾°GòZ+1 òI6϶Ö&$ö$ò!V¦,:Œ¿öŸY8}Ç!àÀÓÀVÏÉÀÍL › 9á×™Œ••ƒÁª [‰‘çdÊE§\_ AÊf +üqz8sƒåÏA¹Ù«ñ˜&Ùµ°2”z©Jm@¶57[!› Ìd%¥VìJaL«*²¶æ÷Q8ÿ4øybêE³(ÛvÆ]ÔR …­StdúH¿,ò.Ùe6lZb§È„L9<š˜üó‰a’›fî¼ÈvO›ÐkY zV&Èf¶ZÈÖÎÆ» ”íàg ïY^“JˆOŠžÌÈ| g†¾ñÀUø‘_•†‘9“1Ä·Î_6†@!^™`+eÛ„nÙ:>LOf;~[)>™Ãiš?>ß$ "c¬È 3˜Ö—€^#ó·•Å‹µ0· amc†SÊ µpJ‚EY¼[ÚÕÉb|(t1 àzÍI€—·µ²ªpx—SªGÙ“Â(  ¤À¨Ò¨Èjݰ[ÂóÙ-eb­œƒ¬mU»7z…È@üúµŽ±vLVæá†áoíÑ0±µ’aÔÂd€iM¯ÜíýjÚ¨ÜÈÜpJ«­`Ø55o[£†¯uµY½}ó¡ÏjÀ$¢CÑôíךJ»€µ›äÔî=,œ’GFP¼Ç8¾Ï{[úHbøªÎÅÚöÂ"7…f69P£071Y[ù§iÎRÖÛá´¬9ÈŽ€T(°àUb„‘=ÐÄHzáõNaëB:ý®ñ O¬4ĆÉítú~iñdµÀ0W‚·òq±²)ct¬øÎh 7žØ_•gþÉðþ^Ò¯a‚餀r«¨‘ik×)J­]2J¯)À°SHqÀxúÏD_–!2}ç:ŽßS•)ma“óìhªÎ‘v$½ý«šU†$ÊÓ ô¶·%]M[¾½ 4¢Þ@åÙ"a%€¾²¬ X° ¤Ì„>²¦ô¶¥bÞ•¿È'%qÀŠWX¹S›áÜËýõpÅM•Æp«è©ÄÈâyÚÒ‹™#¹ÙÒ0˜jÉ`…=lå‚R¨4ÚÒ{]2mUM†‘ñïʹÁ’Y•À¿íÍœåŽóSŸç›Âhš¿Õ‹a˜†·uØYiÔ'¯ª¾e{d;H÷\Çœ1U!µ«ª;é~Ú²MœŒR/¡Ûf°fEãºDâLÂïÊ#U ÐóZíJø#U1tE¶îÊÚe‰i´®©-MÛô~ö·R˜ž‘ãˆnúS(±Z<†­!J…nM_²’­6AÃcв³UÅÙ´󯜞ƒlζ²¹åüŽ‹Jhàj·ªB²‰»|)¼pü~÷‚ݽ›o’&œ¸?/9ñ¢ìœ &e ðÕ–uÆxWß–&<…Í–¦ªœs#=ĂPè,Rdµ+ÅJdұ僱ÂÈÁu_!Á曇@¹­ ¤Dd&9(Œ”ÀV¡ˆ$¦„­á‘d@…@AP   1ÿµçzU‹±ÇåÐ)¦ÑBùŽI_ Ƈ…LtjnLè…¬m¸• @ ¼¾Vá8fÞ¾±;ïÝ9mõâ „ CÛÜð aݳª5†VhT%uÔhÊ|hš¾.X´xf{“?Kz)2XhñÇ?ÿùÏ|£ÊiŸcd÷nEbrš£‰W¾!Øv³ »)âæÊª5¦[hŒe¼ïw¿ë¥V;‘&XHµÖÚ§q/}÷ž€Ò`n;æf0Y½8lþª¬›hžR Pf%`>‚̶Ж ^™”5ÞZ*†@Ì!OŒ’”É¬Ä ¬ÂA¤jq¦ùþH¤Ì#›Òj070/ÈÈ”Ûv–ÎÅ g5 C ¥gÇ™›mö<[mW‹µÛ ºä@)Ëg_Úô¶], ’IÁÞC‚Z˜S_$FÈÚöZÌ¡yhVUáÊ ˆ9sÜIlÕÆóÇdˆÏ$Á.Ù<Ä3·µ²ÝŒ­˜>ÿ~”À9ëWÐ;c`>)×7gkc+ `(E&/Ÿ~kƒYµŽÌ'¦ýë…ɶ1 é"{ŸZíÞrî€5 tLk3WÈ„@Ø&lš ®)YofY!«¶yæR& Áj§·KVHÑ<…-cmû®K‘ñéN`xšõ*ÁwºÛo«È|º>"=¾-À¶ZÌø|üÊ!å°& |h¶²ÄÖø¦Í¹ñÊVN“,‡FUëD‚¦^e›°®EªvÖ@âª`¡¤5'¦Áhm ÎhBŠ&Ì  ¨„R„­pšzÁ‚OÙ"kAolV¢ªÊ$™U4ÀÜš 8&’a3 u‘Ý$‘±È‡x#sbš[tŽö àœ­¢S#;iÙÊ1²·ÛyLHz«S,°õ˜®Ù;«pnÖ2Ló6]ª^u!0‰T`8Må&´…•4­a”Ä—2g†m‰‹¶Ä:;“ÎòÕ~þ·9+!^#@‰¦~Sï¤ X¥yg/%Ò¨]ä©cžÞ4JÛ¨$,[UV«EÃw¢ºl†Óõ~dd‘p3¨j[ÆWU—üÉ+’2L¶¬!Ë*Ï“Ò<d±V’C$^¹Uà›¿³(Ïa…m‰»“xJOÜ¢sLzd+¬t²"7U…1hàÓæû(GοiÛó±æÙÍ´åÀÍZÓ”ÛºR²× Y¹!»yóUÕ JÜéÎ=‚²d1­4 ­iÈÄRñÖñsVB#[†˜&Eås ™-MÛ<)õê›ßd¢«P‹”LÔò—mŒÛ É“IÙJl Z+„ÕÂÊ)bˆõjž ’ ´­;ÆVj†¿”¢,¥ˆ©oƒ!Ȭ2Ç+,2;])+%ÆüÙ~åçZ†«]G<¦­rµšÒ×=+)á\i%ùØxµ ¥ˆ­¶ÉYQ&³ Y z“/«P(Á#¥l«ÂdŸFäÀ>åÊY1Dv4¼°}[TÕ:·ü‰SÊ&¸gaÉùüGÀ5®Y5Y`Fd¡‡T$†&¯­·èó“éß,*…w~UeR—¶° l­æ/hv}Ro [L<Ü#'n©Ül™ðô º7Ÿ?}¼­ÈD šÜñ]^ -ÞÖÊ㯠ý}jÏUJë|ˆ€ì³j› CÙ/yZÐ ë•&±9|V¥Í£62+ÁR•Ь ‰‘@[+±˜OÛ ß’4d)çl~}e»L@ª¿YœÔÊGÖÁeáj…­˜œcÈ:¸5qM[iØŠd¶ñÏ9Þ–RtÕÈ…T­5s>M•^k'›½B¸W¯—-Þšs«mÇ!™t“H2]:nò[q²ùŸQ¾Ûµ-«P˜ÁK»sa(¹‰aT…4 o'h+Ë-Ÿd¥0ΘÀ$›y%óW(Û…¶œµ#0Fù¢ª²”¶ V_bÌî–VK³ \hTG𯰠[êóáÂ¥´²ê¨ª.ÖÉh"˜Äá|ÂR¶Êï˜?o ¾kl’"1j•جHŒ‡ËÍ–[â ½“xчY¹=GŒl¤•Ã"2¤­0ÞŸxí0·Ãý—î£'óÍœXÖ„Ä…µ;^Ïç&íì¶Æ£ü¨oèèe…wŒ[“¤é\ÈîÁª;%« Ós°´ælm6cȲ²î‰”ízU.+¤¬Êeç„+ù_ŒYdžÏ3l½Þ?æ¶È|¬ áë­*CL“gR ÿ![1sk‚œÝXLæýÂYùëù™óa›³QÉê+%ðVn@w•²/0ÆÍ[…ZÑVÊ<È.ßVmw‚){*¯Œa—`[vbžch’ñé¡+MØýX…R^ﶪ4ü›œ@¶îüûßÿ¦°7¨Uލ ÔRÈE§-E&J…k Dt~z‚~¯5\[ hîj­ª¬LdK1jÜk‡„ñË*Ÿž¡­cZùœ±¾¿BHk3œ çL0¶YqÓQØ&†»åɲ4É”Fd»‘úôº¥lÃàf¢–-d¶¼ìfr{jÝ9½T툛C&d1Û²HLšÚY‘VÁS´­¼Uk¡Êן̆¬½ R¶õª.H«˜Þ)l‘Í“Þ6ðkÈ—'¨è¹GnK_Ä(¹ç;·­»,¦.3DÂÈ|‘°rODJ¨ àkô®²ÕvŸ +·Š”Ön)CÙÌUå³FÓ7¤ƒI‰ãJ1€ˆT²a°Ö« ‘MoMÌPÔÉSÐ2l«ðȶÒs QRíLlãs³T½…Ä1”‚Æ– ¼¢˜™áZëûTÉð‘€r+“ô] ^t·²Ýóýœ%¬$l £5œg#%ãvUçÈ’Y}|0R—¨Jªâ‰”EΓ°eëke‹ Dbè­¶E œr¤Ö”"FÖ®”4@b[ba‹¬ª“º@‘²¬uçcàÐñ1ó¼ÆÇ™’37 sÓ? ¨ã¬æŸ¹ìÆH™,²áWÐ ­z&+|JÌkÈ$qR…Çã­dgb…Ešdª– 4'>qþRñ§V wp˜ÞŸr½€ºô¤l‰×7…/€>”J¸%¤`kž€(‹Ê­1V%⺞%3 l`|+7gIƒ¯Ê[±Ž”¶j]>C‚°FÊ1Î" gžÛFj*d¼U ½`¸ÉÃWÅŠgd  ÑÆôq௰lHâz±f šE[+ÍÈô1­üËN¦„¹-°h0]Ëô™ç@Ù¶unÄ r³ÚÊFZEÎ@΀F¢uߊ4»+‚02Í;’jÝy]¬eã7RªìZÛ&ˆùè5’³T$p¦¼ûcmkž]Fð숷jMoåàoKÜT€”ˆÌd˜XÕýFµ­ºKýñ×_MÍEËŒ¼ýï ëŒ`QWåakY8Ðáaã’[¼¶0“˜L8d[3YšxC™¬-,Fø˜sÎ;`$-üP”jæÊ¥”$Ãtõ4e­&±M–¹õÎ{Ƙ”ùÏa%Ú bUzõ“»ZåYÊüÃY²ïOYd ¬ªyð7d%¶€r+Pt-O$÷†”’Å—R"ãå›$MkÃPVâ¼NM†iT)&Ùdm ˜ÐÓˆHkÀó-ÕÄ0ЀmsV^­. Pa$ŒLœO2Ù’ÌJ)åÏ9ù¿&²ê•O[kž‘VJ|€Û[RªFµÖbÛpž­y» š _ ºCµEY©Æ6X岕ÇÛæIØVH“ln)“©¸ ±Ò§ ÆGZaŒQÕš[áܶN @½cÖåí›9&Ò–þœîU±*¸ÚsîÝ*0pUõ¯f»V>&БMh»^pOÂo0ž‰3—â×±aTa6<,T ²¶9c¶­jÓŽÙ$€Ø¯ëù^õíÑ0 žLªL˜3OÑ5Øâ›ŸÒÙ sÃcZ9ãm“¥ßéhÌã >YÊ&©DVŠ ÃzÁ>ñ+ DZw"J)†¯r²Í`.ÕÌôjñ#Ö”†’@—%›mMm×:œ'Lo%c‹k] @†·^ɹvdüÈ@f‹_ SV>4k„ßçl÷)W¸-}¼ªµ h*U0%~zx7CgŽ÷dèA—Rø»ä|àĵ°Úö¹KiÍ0AgW%:£U¤!¶/¨ÃÖZ»ÊmMHL0mo‡ó àt+,Õœ™„¥ú‘õeȬÖ7j‘ }[µ4 Ýd…€m¤lžô–F~硌‘BZ‰[•g˜ Ã9dÎÁ °ZÿXµ«kªÍ¦„@È"›­œ3¯°04œuÄÀ‚¾ˆLÖTÖcô½Ã4dxQm_2M«Rª!=;ãÁÈþ…ù;ï¹R %Ìß*šÓ<ðmûi¹íJÝŠ#ãS(l¶Ï?þñ¨öt «ÍÊÔT#¯lÅ'“r¤¬”¥ÉúWQi0™4=ÐÜx[­•—-…gR‹ÕÖ¶ªâCù:0¬„l)dÏØ„e­µÈ ¹Bžj) #ð²¦ÔVhI³í¯ÀË2Ç3WÒØûg…¶•P’mUø²ªò©‹‘©³&Øq|A4ö†Yy¶ø1°rx·iX]»UäCËZáLzôMU#YÓ¦ÁÐË %¶x…¶€T>îA ,‚ÖªZ#k1Ù­8 7²ª¦1Þ¶Qç.¥ ™˜öòÓ›Ù´¯'sAYÕ;¦F¬¬P]˘jmYYmÉXYáÕJuWÇåû)@ŠJ|8HÙ*OÜH“¬›@Ô%+˜I|zÛœ¥)-€úÒ4l‚ü­f¨0 YJ…”+´…‹°nµ‹½®g!-ÕÖŠÑè²”i¯cæ‘2+,ÒVÀ{9meÕÖ®µ¾ÝÎY:i¤õ:}b¨ÚAãkÝ+Á$ßÙm¥l™ˆÊ5¥u—øð¤©;†8þ=±¨Kn­‘UUŽÇðÇœâ¶z‰ŽP6·°µwÀ›M ±Ï”á1œ²-k `qÛd·ç¹„RtE¬ØòÄø²õ•HÓTñúܺßÿÖJMeWHÿb2z‘a½0azxÛÈ­JÖ%å[åt)Ø: u|ÎÔÃ6·­eÕ.•aÝá Ó¨ªäí·•" NÃÁm3”µÚâêq$h«”ƒX)k‘•)R6 ¦.xàJ>šJ¤`+Ȫmo †ÒBÓ¨‰Me›¬Á8¼­’Hæ@¡ÀðÊa«°Mi%˜nfûõ8åx%WuYäéýý›µx3¤ÉY–‰”æÀg %œ¨$ D`¯r)ä™àù3€ÒB;åÀdëØYˆ1 ò·Ö1“¥t‘²v„Ìmû›Iz²ÆPØlºTNÖ R¦” +Vi[PNÞ¨J Œªa}½$«T>u‡1”ýÿ>ê£L–O˜&ÞVÀ/mR Ó1“ÕÎ éùà ¬çGV1%úMÝVðí~ÛÊv’ÀF7txýlSJåÉ!YµM )[Q—0‡j JuXªªS|ËAm[«Â}­{]b2)kïÓ©Ú¿’ ' i’<‘u 4Ò†I`mHö<¬K³Šì–`>š ƒqÀˆ&ïûÈVm2@íŠÌ |C^ƒÏ0lmñî¤B[V­øj¥Êâ34 sY¼¾¢Ó,e[a>ÊÇó9¦ßùØ$Lú¦Ë¦%“­¶ ‰”íŒý ™ }­ÉTycEÌiùýzÕn.öœäþnÚû¯ö új‘@æô^8+)²æ·Â"½•iZ$}%Ntfºo»•&¾ª›ùüpRûZÁ™ÓX¨ÈÜ`%f²]p¿jZ»%Ã9óR‰Ç”V%u¬ªÕ¢ãgØ6Ÿ4e C Ë­^áôÊ_IŸ²y¶2¬€¤ÏÙjËÊ*80J Â²ö†Ë®W2‚)†˜,R¹;×nþ0M§@ÞgrͰFiL€fÎßZ/ë‚€-‡µª* j& ‰ñVŸ—½‘”Nçáú,PÚ¦gNÐvæ<µ°.¤`+}%cxêÒÀHÛd§VhUõ¤ð>8é•cz]‰Íæ û÷ø1Jºá¾âªêVi†Z0·Evçü7 ñh8óïÛFS…é‘”™À# [)8’Ì~†I —Ú$ [©Ò`Dbæbø°u†)1‚€¾”­ÔÖ“þ>Ád¶î‡XÜä绎´æ€Q" 6|UiÜ<7Lo‚1l¥²°`h[j$ ¤ ‰·¾aNÛúR’i{ÜŸÃV«‘€¥Ô â¶ÀIc¸Q aCæO$6¿]Ñx8Èz"ïO…MÕ“¿‘g‚Æàé7Udbm›À¬*[#eU ¾<¼X#b¯¾Ó5aCÖªí)g¢‹r؃z4Èõe‚o = ¤Z‘n.  ÕÂ9Pþo# èûèÒ7€òw€ñ”Jl­ 0dY[&­Zð· %;-}+~1gÈÒWHÀÇ]Y9×Kʶ^a)Œ €»SÙ"³<Yžø0Òv†@VïÀirK™Œ PG&”‘ɺLŒKÎFªlG«äµ’•€*¡Ê–²òÖ¾^MÛ‹t+ŽFTh˜^£™ÀÈZ×´¦Zk3X5—"0y’üý¿›ñÍ#¥¤*÷LÜx¿ÖuÇsÈÍÍ×ÉçÛáÜ€À¨ê§Ë•Ÿ-YU•;_»94Rˆ'¨VhÕ%²Ö‘黊˜Lέk‰1žÙü5X3§Q˜g·ÔðHA&U­-,ÛªµlŸŽ¹9,1¥•[†}#5ªÔüU!³úà{yèÙÚfKÏ p}¸-œy+}2+L6vSêÒq6FÎÖ)8 =ìŒd‹f˜ç%=Mâ m?@)V»Tz-DØýÈ6ÌdÒȺ:¶Ý@¼Bd M$‡Êe{LÚÍ3AÙøæV/ëæ‡ …ÄÖdÆ ¥üÇ!À¦Åïã9­Ódhûö’ÊIÕL0½¢“õø˜oš¶_b½x%Ö²Óì®ødCLÃÁ&Y-FÌ¿­µyš9¬¢¤`-ÚÒ8޾2@ƒ49eú•ó§±ú“ÍÖÌoDz;E/L[+½0CÁDèXUí¬ªÖwŒm!ÅÐJŒ@£EFšÜ6}!U$öÂãó¡ôÕá+“'>ì¤vVÖz•¢¯‘Tne“9¬aôÊÐÒ YÁ†á@X“áaëùÿÂFŽ‘­b¦X¤nJ²,Å ô²ÂÂ5«7Œ! mÉ„ìøÙ¯¯ÿÞ!A@Ö•)l+ŒWBÔ%‡J‹º8A&€aXY•kAæ[ ò 97%EUñ˜Ž¶m¤`‚5TNÓ‰¤™¤1UÖfH;)²­³p@ÚZEó+çé85ÅW`ˆEMÛn†7­Um 2Ÿ²Ö€,Û)d»X³åpû”Ío­ÖÚQ;¬mŒFàuo€| Yä_îU¥Á(¡$ÀØVXHÙZá4ùˆ”˜s s§Ÿ ¾? {4gâû€¬j§nÏÓHåë^ÓWyÚߊϭrˆO@Û’a`YäÎcÚvØL&°5¿Ú¬ªMcm›^H!Û6¡Õxl~8e)k©<áÀV ”Ú·¼F_Ù7”ÈJ!½HN¦Ì ôÕ‘O&ÈBá{Õ²=wYÀVU%5â/Ëúî²oëAûª\_Û4d¬¶ºã­xA,8 ¼Á€:VE)ðNT/X;µýhÒ”=¦ßŽ ‘ô¬ Ê_À¶òÆ4db)ÛV ϶)[ àаm’p)à …Lœcž˜€Y;ÀÏZç‰{)kUâ§2’s`À*ª­£•s%z±"«u²éÄ«m¶ü‘Å$œÞ8{Ê4 ­eHÕ=‡J¬¶bY¤°¥²Š §é‰O£E÷IIP#ÙªLØÓ!®¸ÒvEÈ4mUùÙZ-eçé׳&iX®Pvƒá›M¶‹ÂDZ=;Y)˜PûÿغƒeÙnb Ã3ãIq„ ˆàÕñý¤¿;-oßÈ©¬¬¬’ÖêÞÛÇÆ4•?pÛ•~/-ÃúŠëý9C[|µgŽ;vU) ¤ìÀUSÕ%Ƶ4a¼”È@ÂuÌ©N¶*2LQ¹” Ž„¿ùÏ£qü³Eö ºtŠôÍãöláduA²êëHUúTVIµ­ óÁ¯YÖ<Äf áæqS"­ ˆñ·è€øúFZw(&ùõ‡£¶SgØJ¿v²4øV[U,ˆ@ÉNW#Y“ÈúóÊÙ: ýûå£C–•-=F0±v"$ÁÆ+Õzþ3 rfJÑE+¨Y)[F5SFcíñR2+,e-¶ˆÉãÀ H³-R_%ÜD-¬n¡íèœl[…ò+½ë› [½l‹Ê•DRÂRdÞËîÝß–Ùv-Y5[-ôCJy&‘ÖüpS!sˆßTø‚­¦e§$Ó"€ÍFŸ ¨6=Ü`J0ü›9ŸoÃóù¬Ñ˜¨˜ª` •Û ‘÷Á~¾ý;,YÎÛæŒWãU~­ªz;Ö”¦Ã>¢r †à&Ïןªñ;È{!j¦l[¨o l•bî•ö¶Xe¹-l‹Æ€éeö:ÁÀ=¦ŽF©ÊZ °¥Ì°”*[U"žRŠ3&œn†]TŒÉkm[ÐÓhÄA lå¹R>Í` § À‚A+g@6-МxbØ:Zm5‡‰[3±Ö—8ÿ ȼH ÓäÙYr¨»#w4$ P¨ @ÊÎ(r° UÓhðüLŒØ0·Ê)aë¼ÖczoLs8Ãp) %¦+â × ÑVS$‡zá3Y‹)UEæ6¦ ·f¾ÿôm\;34‰Ö˜ÄyÂb­ œ‹>e<1Ò¶k¬$sdúÞO[Y)·$\²È§Ö~Žüã)Uô“µ  3ìÈÈÌkÊ'xXµ¬µ*|+ÒZÔñÖ}|0¥Èð™ç§_¾¨¯Â¶(‘r“Ù’µ:8 PÕ%'nŒéÈIJm­·&)Õ¶Og¤©8¦gKõÂd¨6Æ–þÛá|²ð1RBª­TΘÎÅVÀº{îo#$=ZJY—V÷š;A[+¥mnmKy‡:X±-2‡Ö9¤Ñ(e€¦Y! ê¨ZÃÕ æðnËZ)Õ¦·¶ºŒÂÊeaÙÚÝÌÙ Ywc'Ò)Ú’I1Ù„0R茫mà²Ì™¨ªÑÆÀ«Åc`Y#ãžW8}²æ!«EÏ4 4M2$†8óôÈÌ뎤q@kU²¶½f™K ˜€ž›Hlët¶lKi—ÞJ3œC¶x÷£‹h+<[úuÑÚÖ&Î3²«H#Û Ÿqïå’Év„ ÙE)—2^%¶F(˜g îW¡uÎÝùÿ;žÛSnMÌ¿I2q9˜^*²w÷F) –ƒõí®6Þ„QÖT³•€'“|ÖúTÑtV°¾²^~OŠÕ²H¸Áˆ7ÿÚÀ9 gkåÝ€ÐÛÑbm@IDAT 4ª„­¨¼"kÿúý÷ß)¸0ul+Œáu î¯ÚøÜw0õÌšo-ó%æ`8k¼µ)/ò'4ÕÅ.E“?Û®~³IÁñÉ( ïöæÙ`² š'gb$@4•g£¤èßÇ2’¬B$PG0°ÊæiåY÷œeOïáø”9ÀÜb¾ÚÏ/duéD{ª˜l¤…éÈuç&”gøþF• T“Ó$–ÂçƒÁè¾°xLÇ9mî³ËßM21’À [U•EÇ_ŠÆÖêg³F [Ká1§ß0«×'=Æ$Y‘ÕNQ%ñ”‡Ï$ŸôH[©ª¬|*iud/^O6çJÈXé[k$})/˜,O hl… $ 3·6 /Ì&³‡®„20MµµèQb"sæ¯D46ÿÎEóΓF9RŠ­u .4e'€“©…}ú49y*,ð•Û²4ÀÛÆ[wZt Öª0„2œC2¤ìlma¼éŠ`ÉJ¹ HŒ:Qz{gQKií8ÉlU]3C‘až|t!ë~`~Ù@š·…ÚÌÒHÙÆØŠ™KŘ֨¶Jvu+¤“õS åLr·ä "kj­cÛÆÓ…X0Ѻ'Þí‘©mÎaÊ|bÖ"Òš Ù^ûÏ[ºÖ‰)¥ª†×EÀñ¯ÁÈþ4ÆPU;µ‹Yõªr[UY™c;²òj“Ñ(7@/'LSSÀ–¥’<1ÙÊÆX‘4UÕ®Õ½ò¾âT­{Êæ®#7ÀÙµÃk·’ù7“R»´Æþ‘Ý x¶FͧjKÈ&Ã;‚¯)üú’É }‹mëBœ­áM“) èæœ÷|{×W¶STeåÐ ²x®gW*+ÛŽ¶²š&üzVˆyS¸1怇O‰im°.úÂYa’eÕ¹Ö )+Êj;l…ÖlÓ40MÝ‘1Jà«Z/ú&f(ªjUå ú¡)»³ð©<¾ZbQ»ʰ5@ìt›³a¬RVš€f˜gü³å™.V…‡ÛVBШʶ:©”v°í–ºœj1ÝY ÍYU ½ˆ§tÕÖ¶ñ¶‚ØlÝ3žm1¾Á(W{|oÐø«Uöøû%EÖ”Àc"Ìçèó‡ÒV(iÅÔÈš9F¤§Aêbu¥¶xØúV…+$+KV Y©óHî÷ì”kD,¤„ƒP–ò€0|Ü•@Z3¤¬4aJdQw¤-åÌ@$Íî¾ð.YçΞUz)[`Rak¤v >sÜ¿$n’ÌáÀúV3¶e¨—£Ù`÷@ÓÙ D) Z%°ߥÙòŒ¦ÇR”pñ=€Ù›GFäYy#al­µ†‰cº[WjËÇðRݰí 7^üs9ÿ°±yòÏ¡’N”>[¼B¸ñyÒ¼ö£)4ªvO\‰Øó¥É ¶ m)e¿^Özj9W÷ø"ñb¶0ÏþT~dn eûZ`Uk€ìÑJê 7‰T ‡BP ¬E[`ž šÌsÛÉ0ð£;«ºXÓtb?,¦©£4«ÅÇܺ?– Û¿%×ã˜ìháUæ™yJMƒ·¥é“`š &k«{ŸA$«÷ )hY)é¿·P¦‘²­5€ÔÅV¤Aò™æ-œ 8-Ÿ÷³±òæ('Àx§w†Oí¬Rù“ôÝv˜ÒÖ*Ë!«HJÀªuµJDâÍC PÄ#‹Äf¨i½(¯ÓYÖIŒ`»“Ú2ì,ž‚cb¸‰Èµ«P-†¹l;2F/µnåPØ zíÈ`%E¼u_æ ˆ]†z!‹ km œ²‹ûÊ…?ÍîAV2ÍQ?†‰øXë"«»5¦‘l‡ÄZHʘ L“3¦Bžpw2=%YU×ø,"rh$«oB;ïJ€î p- Ó$€Õâë‹$°¾`˜Xö׿þõ/ŽÕ4t㈂:@Úˆõƒ3Rè‡ ¬*†Òd†lÙ`šdV&"²Ã„ë«$å+X­¬X9œ!ÀJ0IÐó°åC/Ei6[@8E'[•’Ý&¬VInuDbà|¬°@ÄcÅù¤Ls ¾ßwù“¥±®p&Á¨sëÂ4•B@9Ùž²TW1}2ÊFÂgާ<.ßã4@ÓE™ŸÌ çpõ¹åª X­B%ul˜Z«Ê„¸læªÈhl;œmíèK)dÓ'› VÂÁÖjžÆ»ù?>;ßB™ä¿3n›§ZŒ!ù°ø¤!(Õ–g¡Vt±1† I/¶x¶~,îÓL,%`)>YåPwÙÕb"›6¬0ëî¿÷ÏôdÛØ:¦1½W‰[ãJaˆ½©Z%­ÉÞªøRá7› ê:5’’ÌéžøœKÛÂ`ÌV(0•GÊjÔ11 £üuX—ºK%£—rX|ž"ž3ò:¥ÛØüR{-9tF²†$Ìrk¤•RV‹"Ì–C>0>qgï Úú"+¤ÈJaTa¬dgŽo»RøUùs«µB¿íDxå‰ëî%i†Äµ³Â˜4ýab}›?VÛº7Õ&qšÚ66™ 1F§ãìÂ;—IèEó4@X¹¨Q-l¥:éMžãçY¹T›Á*8dÒ֚û*·%SN WíÞø:ýé{3pª0U!¦yÀ=÷ŒlÝIwE£uWTSÛlÍÆPˆ” C k‹Ìêæ?Ÿ¾f¶6‰î}í4€95â d-*Ÿ%’ÒjNkô(É„”³de›mSÙ*‘²UhNlkžºçI_/ÊR MÙ|à IÙl°TÙ–þŸ€¥ÅžBïÎÈ¥àR,Ný}ùÜ­£2éHeaU ñ=`½8ˆæ(e©D-ýÛÎ… •€LkLma)«FdË*ÏVóY7p)V™È S]¿?>±Èô9k̉’"}ÎóÇ4p…Ä"$7+c C8[ï8jéÕf"E&„Éñù¬ ¶úñC¤¡Ïç{j¤Áh*T¢Ò6½5²õŽpfàSÊ*x2¤æfKV L š$ÜZG †I/«¦ÅˆµNlÕ ¹uÀÕqëfŤñ^ M>MadJZ €îpÇl¤Êabåácd´2ÑQPb€™Ø¾½j—I+ÿÎ’U÷)…œ¹­è‘JlY‰Ûöó&½Þ*lM%‘ª6F•¦HÙùÉ"»=XÐ׫.d¶Ê[ëbÚüË:Ž-\–ƒ¨ÜŠì¼ýi+½v9XÅLÚÊ*×wþø&TîŸÞø¡¶Ì+S¸Úœ X ‹1)‹Ç×S0Ìʶæiå â­‘F‚߇ÛåLÀÁ)j•Øú¯ÓróDðï´52!7k½øàE[åi¥Q¶iÔR€ÐEŠ 0qdšÈãþ}µê[¯ü;`MS6ÒZÛòé Ì}EÃÖdå3X–‡›¬ °*Ò[Í,%2)k«D˜Mk@-±î5%ðb[2cë†{ÇêØq˧¾Ö>0eæ55ƒ¨°¾¶NZ1òªd‘Ëæ)•øm+°¸ªÏO'Â8ެñ«VLå4æì­s9üQÒ;+å4?m]#% ¨Ê6À o…ñ3h¬½!5¢4XzM3±6@@ AVgQ ã5|"áÌ•˜.Äî}è{O*´*ÌGÓCRp>@S°4ÖFBžŸ¾¥¾UÁøü-?ŽZº¦¯\ÊVŠ>ež‰ë*eëlÉ€˜mÌxzbn½ Í@ÐàEnÝÅ ¯ëYêHOP¡’ø@V ülð'‘²RÂ#¬Š@ÀZˆjlY“X1)óY¹Ë!ۦׅ@1­FÍÐÀ Fw-]Q#)!Ã[ñ†)k+2´úðsp^Ÿ4…fãæbè)kw‹®P‰ˆ4†°•R‚XÐ`¬·âóði’I¥´6*Æ ýL5y?b|½[)%irkw¾Ë¡a8%Û&VÛ„º“xÛµÓ1MWšÃ®h¯e2å+™.Lª-;\;[@Š›ÝÅý#;8ÓÂsÃð·ÒˆDæáÍÜqlÇÃÏ©‘µî€xþ4BkM¥ŒUÖªÄ*:i8‡ÄáfƒÉ²m¸·NaVùhALã°7еà×qÎ>ÄMhC¬– ©…ípoEkzViTiš¦|]XÅó‡ë’?­Z«?eTèÎo S [žž>™i’|`Œ’²ÈÊ' &¨©Äˆw¶*Á4p}­‘ë"«v³­TÑ0¥Ü[WG_SJ&7ƒ1œ” qMÉú]Ä6Æ¥!EµªX!É<|7Ó¬0 £qÂÖF¤h’a€Ubþ²}âcL+b¬4†”ЇO³{{²ZÀ²Æh€š^ÉIyæÓeÂ+ÜñM‚!`EpÃä–¢GЬ0°K3-ØÑøfb[/å±'Õœ²”uô8ðþ‡søÍ“2M§–¥Ç°’ÚÍÍKÂÍUøÎÕ¡"×½¦‚ %Þ%4•¿±‘ÝÌÉ0pcÀi ÀßÌÄ0Ÿ÷/®%%0£ª€×E/A–[% ´¶uêÎY“Æú¶Ø6P»jUaš0C×h¥é{Uª‘j-E Úfhè,éÿ_Í©üúëõ¾Ìk¤¼CÆ ï5Skk˜z!½'˜½ZȦÅk$ÎxU¶&Á4OJ<¦¾Ï0eB-Fd¨ªÃÊÕ1!FÎ9sbLž0²³ìûjí³ïšFU(xÒ¼)>Éòl˜° Üú¶~K`Ù|ƽ®Öްê! ôÅíÃÐ±ë§ }šdLJud€Ck3rX-·n¼)Ã#”ó´¦\ÇRYµºtd]jšÆˆäcK–­“zN ¤ö†‹Sùý$„€R»ÖѧòûeİBG«£TÝ­ôÖÄáÖR^—j{Ÿ`n}Cy.¶žed@ @/ç’­„?à;×~D!Ûæ$à,dEƒ²ÂdK0ÍÈY©­ÊÕ ebk— {/@Icª.ÇHR)•™Ð¨µ*±"Û:{2¼`¢X- …\]ÓÒèÒ£á–!B)Û¬0 k” ÞvJ&˜ž²is¸®gNÛn²çÅ ©–Æ»‡o<¤‘`†V2“yœEŒì‹»É›ÿh*g•Þ àhrß³“àÇxc çà#Ũûø€’¥V©~KT $ŸüóxÌæZŒ7ÙŒ¤¸+¢p€mÝÞ*²h`QIX‰vÂJÌMª w[¼µXÃ(Ì™ kì<ÿö·¿¥ì:r}eÉèk×j€” Ù ª²°€UY†¡rzµ†D¸s}uà»êÎbÍ'åH€m>€y~4m6©º$nbžº(á“h¶]±ˆT^Ç®b§HcÕ¥F0çú&ÓÎV¨Ú±²¶i€¬ÚNCV¡l©¶<+' ö¤td)­+D‹®—LVôD|Ä\‚¬*ʲ9´Õ…¸Öºl þu$CÆ“…e…iº;), ÈæoF’Áÿýï­^ÂÄdjaA`UÒ=ëÕx‚C'íjd€¶Ê—r °’üuô=à[H•|úºÃ+tWž!¾ßó”Ì[˜ÌJ$Ë*¼¾ÝVPzÌ)ñ”ñ<[Î4RV ™±cº)bCò‰ïV‰‘ªm†ÆƒKÑdñü]‚¿EÉGyæ¨d&Ÿ.–&@V_c¸I[㙳Zš¾câÛJMoaA/•!†>Ü¡Èf|Y=wÙ™¤$À˜ÓÖð¶†äæž;‹.nF9žÒ)êÛ)`æuÄaD}É€ó;›Úu'“⟛­,¦óÜHÓ¬eh€HŒ­*@à½ö˜™ëåÈ”HµÒ$5¢Då®"lU"kÍŠàènTÕZa­»„Æûã÷ø&V˜ã'}?ºR*ñÀúÙÖPî$jHí1¶Èx¸™€¿FUxà=@æHˆÊÛ&¨v}Ú¥1m aâ­¯[8‡÷kWÖûÊŸ^4êNœ,².VÑT½¦²Å¦²UX|“ŸŽjÉœHǮі6ª,¾ÂÜðÐT ¦ôÔ†³"Ãt-ÄHzÎéT”m%¦i#k‘§9ÉT£¦xüyC)‚þ¥ëÒŽ˜²òÍ£Q‚Lj‘y·š•µÔVUHÝrëÞj!…T.öö¾}‰i¬ˆç˜¤.Õj”'€Gxv9²aV'[JÏVåÔÄÍlK¦DÊT³M +êB (+lkݶZëÈ ãºyŒÁ˜ÓÔwš×Iß½À=ÈZ1õmàJšÐðÎ…™F£ïŠ"X- ð„irkàÈŽÏÙØ•ã)³¥ïƤD² mgô[½¬ÁTø(o 4 pÿø¹Þ•ËÚšÐýs³ÍY­ªz!ó¬°7­ûÌY6½-qUüa÷ì™6¡p %CJ¼- 2ÔŽa­hDd2«dÝ­•’ŒT AúY95i­iJ%ãtdÛ. )Û´²ÅZØêkKéßöýñ÷9²jÅn 6Cœ».ÛNÊ2*/†-Á”ºÔÑš-z·je¼³ÃgˆïÎ%Øðª²Â÷?dÊ6R_…REþ0¾v˜ýFøU_t¦Œ¤XUµZ ¯úB-Rw%°*[×#æ!.e…3¤¶”) [k¨¯#² ­­½Ð¢h;[J)U im3LO?r<Y§¶"¹‘•Í'Ã3Ó÷—›”]B˜ÞÖóM¬°Qk·hZzG&îmE}pV/È3Þ0€Ûãöúg ¯ÙgžŽCC?È Aã£^}ÝóWH†÷à[ç­°»m…UÙ6°µªµî8 ò¬*‡1’aàMÕéÜC³¥¶µ¶ C¦w©™PÊ2¿ª³tøÆ¶i;[€ç[«"n˜¬šÄ÷`ÔkvHle›¦h21­!Söpñ4x+fµøS|‰?ñY`9ÃpK´3¶%ÃTâ˜]—¦éme­Ä4¬¤´­|â:"‰E…u¬’€µHÙËFNY£ ¹‰N— .iò‘øKù¡ «%Àl#úE²µà@&Ô:µ,†³èû —¢)æ&E`aÛ‚ ”²ºÃVäWòùbÏàüÿÈ¥ªÑ2\eYx$\¶ùoÁBCßa81jß@ MþÊö>ÕÂ4µƒ ÃRá MKàZåÌS¸ešVYsÊ&ëDm•#­Ä©Æ<Rw$`ë[5%Í«$4†çgU‚ªŸ¶Ä1 @f+¥DJ„­Jz+o¼•žƒá)u³å_% V–Þ¶¾­jŒ˜¾r½€œâ4dHa‹´¥Çîn‰^дm 2…ø¶eÉà®Îo-|0µ°]#LÓª lx)g‰ tKµ³6²Ò£¯mÓ& ÆhBÙ~Ô59ÛYb[‘án -AY+ÃÚ%®£ñv%ÀÊmaµù”µ¬”x&ÂHº».£N†÷fê‹$ÆÓ U5j¶¬„¬hŒÖÈ›üd J¥Ñf-GIžšùÈQŠŽ¶Ò$ƒ›Sʶʥ⻋w[a©ÆS¢ª9ÃR)§G:ÃR°à\w&BVTbëúº+b…ôH`àUÝ™ò~ãGö‹…RyšG )Ñ<4 ¬ŽõŠ17ç%Î_9Ð ð9Ž×S Paš1uAb¬‚²áµ¸ãŒÈ3¥-±sMf+ÅpXy%1§Óí%fÞ=(G’aù4¾¿5b:/®Êj;+Jµ ikBƒ¥„¥›Àð=M)ŒA¡Jà;éÌ÷O3gÌü`}yJÙ %™(D® ®MdÊÉêUm©—ÖlºÄ7†Uð$¸Ï ³.–Ø}ò÷*r°Lè¾çÝÀw«\`ÊËràd¥P—Öî°k¡œ ÜØªÊv‚¤x%‚xë%>žpµV;¦Äî\oek5äô°¦b“ÔŸC§°òït”¶9'èb3'Ãó´5Ýy1²‚L¬WU‰OÌß¶ i0V1¥”òá.Y9Mkâ « ã;‹méªñ¹Flæ=Hµ‰­Ó¤ŒY; ;Á3éÆŠ ô}èD»Òu¡0­d«ÐÛã».L‘~þ o«Kâš­’Ìùcà94@URï=Ð蛉‡új›Ó–Ï hl['‘uéžs¨˜ÞEýç?ÿéº0 Î?>ÊŸ@À0@…ïy#gÞÀ ¦*¼p¾aJà=…†Ô ïô `¶=káe›¶,½5 EÏŠ'ङ׋† l…R˜Ü¬Ž–½Ú?Fj°ª~dßBÎZ×î­¼{kH«Ëq'Hi³%f‚FI)¶^Vª-& Ð`.ÁÆ‹d‘–¥//’ùGú}Ûs¶â)˜\0±eÒÃV[6^S©Ö¥j"e)³Í“§0°l#¥\G|?±wÒU—2Œ©vó~ i¼ÚU•-˜äc+¤ÆÀ†±-Uv8™óv¢É]D]’ Ciž.§lOJŠ­,°ËÁd5’lñĶçÐÏ~{‘´Û´Õ•HdÄQ*¿6® £±Â¬`[¯ï³áÓ6¦B¤è }Tõ¤’!ùã)on+¥U 1ܰØÌ@˜A%•Ûֶʳå\/¾Å¬ Ìì!ù+¹‰Ú1ñ™´Û»U­ld×NÇ„çVådëe Ó$(kå‰9ýnGk÷ßk͊Ƙù•Ÿ7&1žÌMŸçx!…IF:7Q-à6ÂÄ&׈XìDm­×õØÒ(ñDD[µ=þdM+E&²²mB@ ­e/q&Ê76lBžÑÛú,dbŤWw“çl÷·«<µSÓØæ_ š¶Ö&É“ƒmÙ|¶MlKÌp‚¶ÜÔ¦Xi³ÂcqcO‡a¥çˆJ­;¾Z q8Ò60Í”Oã²íf`íºO gkÃX‹!¥p‚söðì¶áÂãàƒç ä,ÅpþÚjA/ëc5Ò¶ù‚n¸7¤+EªMßÌ…^Jð^[)[Ñø:b`☬`%õʇ, ^ö}b½ÖN#ÁG(Ý€•RœÊïgGU‚)«êæ?®¾úÜ€;Ùy š!qæÍŸ[â|¦Ü0x…é­%UI1TN©EzL½"çÓ¡ø`ªêêðôÕ6Ì•L ÕRÞ>OÍ#.ð²lwu0O7CÐ<&5"óÄñs?ª¬½Q³Úü.¶2×H4$q_˜«WZ«Â Ø€Ô&\#Ù.S; Ù„·Û§Ýª”0áP ^T›[‡Å(Ç4Pàé9d»%n.Á*‹èɬ1Hçc»Ž°Ä*l“úïÇŠX‹¶êe’>Ëx…µîÑÄX^9=ç= üPkkÅ ƒa……m€žFÐ×BÊ £Ú6O…ü²5Å e;£m€ΧªÞabU^'æÝMß™²Ùhš*±—DŠhªZ+)l Y ÖR; À9Þ pÛ‚¡Áð…Z2«ÚÖø¬àȲõ²ŠÙià’ ‹‚éK!ï™Îˆ,e5^“#UÁ€ë° ”‚C€Æ€N­8MåÖÏßë8­cwV:¿ %åb,X¸6`÷®\ 7²Ý +2@ûJhAf¥WKf=Ó|ÿcUª`$Yc¤×%OgÆTӘ͖ßÌV©Lò¹OÓ‚@™Þø$²ó¾¸.1«U¨Eó{/{$5eèUî´sÏåÍàžé» +Ú ô²e (ÉD˜HÉCn¶º«EÒ(§é%€‘¶‹Ê‰ÊÆ iø#­HëÂv|æ{|øž>1’Iµ@SÙæ¬P´¥ºkÄóáæP¬(­ €<+·aKOÃÁênmýtño¾¦'@fÅv&ô"«µ ,l‘më‹[§°nr¤T²ð•ž€'`f)kWÑUY7°Sp³5¼ª¦Í©D4íJl)›§ÁîÑíÿHk¼ùÕnΫ-dñp2ë_ù2¡‘1vº ;8,ëPdž aæ§þ;Ï<¥VŽ„+ÑE$ÉÊÊŠ££¾4éKɺ„X–foK>ø†¤¶v{Þ:_aåµS«ÊV°mZiåÓ° öÑÆìoS1|š¤Z%)5ò=#kËM`Òè©ÉsH–FV` À¢ÉŒl‚é)kJPªZ¤¾¥j‘Æ»NgA’ž¬*7IÐØõ͇8+§î°Æ É'·¥G ií&9»Ì¶=z˜ƒ’"7ݵX*§‰4U'eö8ÔÒ$%³fÈhUBLÙÑöŒ7¼,Ъ0+Á$8O2ÀŠw@†0ó @™•Ã"?øïÇSåõ•Ô b…¶ÖJtÁ§T%DSnɬñmÃgÜ{|[ARJ´½ kj}ƒÀ$/£¶rk)‚FjW÷Ö•Âðœkº«_ʪ¼ILõ6%¶õóì8ݬ*1@cš6˜.sQ¹i>Z;, lµ 3T.”DÆÈzˆVãU^£ÊáRV¸ŽV>RUÇêhªú•† bãQZ•Ô"Xœ™¾A ì¬e[yrpEFµf;«ÄRI£.§ÃòÌ*©dúÊ[ÓXÅxMk”R+‹ì&m¥êÒµTnN)Œuw®J“¦Ë‡ñ0ŸS øÔúç‹rl¾š5sf§^„¥Ê*Α‘í ²è%ÚJÑÃZ\³³Ø bYJ€иa‚ôÆ[IL…ºã™Û»¬Ûr"†Z5í°Ö”ªÒ³Ú0²Eàma ƒð±5*7…€^Ý@šVY¡V–ÞjòmKY9X•k”,…°²ô{|øüóÆå¬JIp[2÷#Ë$µÀÈRÚ¦oŒwæ4VQSâ<ùI¨j¥é"bª­•Iç=¾_gÏ*Ó)ˆƒ­Š¬Óá™ãmµƒEV¹åO–¡­PŽ¡Û^úOgÌ™-/CšfÈJ²£{ŒUà_¦»eå[Œ³m +bkMáª:½k4­cÂ…F­m-6 ¾™rS‹Í‰„­+Êj Øä€4Ü NѦ·jº‘à>¹YR„;æü‘02>qJCÜ9ËÒTÕ‹º’<·Ä|h¬x+…Í@“R­³÷Û]Öye{ ã*—eUëæ¬+2+A8Ÿ¾"¼·ªè@™,è…ÞÖZ£œçŸL!Ʊ-²Z¸Ž¶bµÊm­°Pn«c:¯*ÔÂ*Kcl)Ø i%°•MÙÊ„¬Yd­Ù¦êËAʪ©'‚ï°©g·fÒÊGоZn~'Sîh˜7X(AZ 8ô½‘l}WE£ÙJ*×tƒ šjµg ˆxš ^ ^Öú„ &l{ÖQ•y¬ô &Ef›¹rŒmJŒ¨dUÿVÙL$¥KëaÕ¢ŽxQ¯ãxg–rŸ}Mqø3ú [ŨRÛ³®ð ¬\kk@SïCz+%~çÒCSŠ@`…³åfLeñ¶Æ:f©ÙâÅÈj­ñ­‰•{ÃyrÃ8ÅN#‹'y¶Í­QánÉVy>ÄË6Àú¾À È2ç®Kž™0˜Žœ[÷ãn¥vWL®öˆ7LϽ«–¥²‚Lœ¿Ð)wo§3ûà 5@m½úÏ÷xFª*ìä|ÒÈÒß{û¤ ¬¶ ;5@zvýàɧv;#ÀS Ù|ˆ…¦HLSY ^6rçÅ„ š@¶ÄÁªmšÓæþ$è”"ÐIPÇá#ýv‘*0JDݯäçÒ$)ÍCœ¢Ï&+ü¹‹ïß =Ü5Z OQ [Ï7`-8{Ù¬07€¡|غ»Eæ@ɳr€Æ*‹¯ J…n Ó]ÉzÊéáZ…ÉŠZX…IÔâÒ bRV!…‰\X§ˆ1¢ªð±þþÁë+4•=mn#Çl+µZXÖ¶,“ÄÆöà"Ú=ä_»|º)'Bv?áŸIµsX;Q#@¡Õ´-ÅÜê·|“d™ï)š§ZX4…#kEÆSÊ&°&({>˜¸§™­v.4’å`ÚÄïdž ÿz3q(½¼ÆÖ²‰m¥¾ÎÌ~}w'=[Ãw9Ü1FÀLrPÅÜD%ü…TÙ€l'R[ µc äϤ£YÉl ĶKÀ°µ6’¬P.› òdaYÛ˜0¾°j]9óoò|$ „T€Öº-lÈW¸Fi¬y¶…÷òÇ[™ÈfëqØÂxÎVÎV¶4­ëH,å0;€/lk½òlE†@Y[Y… a|åu´Já;µ-ãT^ÖêyõtàÜV+eåÓ–­K3Äó¤ÁXê2Y3°êé›§¦d ëK_ CüÚ&ªzuY½Ùúb棪+œàxÝŽ‰µ%Z‡âeFÀÊ &\Œâ£ö| ûK7"á%zccÞ®ŠyuSýWçh(Bè«Ö‡Ù(¶2ÎVÑ ¨†³¶þ ß&Jh+kUH%^‰Úæ÷úšDVŠ0vóó´…§Dp‹TÞu¨X¾Ço«ŠUAXdE qzk2kÌ»í&5ñÚqÈJ¶ªZ„­²¬Ìl- s:”ë‚JqÈ*¥UÈÖëý„¿7#+‡]Q P¯žŽ.¶ui°”Öª€â5„›|d[›\UÛ1‡­“V¨ª.•+±®oS!+é}è$è5è,¶dR€*‘•5\¯|¬È—©ÜZ|áŸ>‡È=Îå-Év#ÕˆR$ÓÔ/ÏÝØ¨mz©yj‡$ãŒçCÖEáû¤ØJÑ4^½¬É:þ ñ mÜ´€ÉÒLÐ0¶1ܪC%V>d7ŸñÜ0&$väu±Ýü3¬Enù„×)øÄÈÆ4•­/«1¬zujšéV¤*nŸ^U 0®”¸Ž¶”ª¬x O“×—¾^œ ²ª5(^W¤V£öÕAg9'…9«M “ÙC#Y†fh*U¶”•¯¯-,(a‚MË*q«r)2b©d¥T5†¾aü0%Œ1 lH[ 9é9ÃwŠs‡RO)…WÛ0H)×"¤|7Ò‰a'ÅÓt¤?lÞ7ÃFh:P 9Ô´Iz…|Ž0:4žq%º¤iB$À³#Ø ÛÖÀðTä&[ªòi cëB¤DwÒÀxçENw!˜]>BŠ@‰Û“øô¾ÑÈŠ.Ðy9 ?µ7g>Rp3ÈÚ"c¬¶FÅkTm$^‰°]ØjM¯{k_ mÒ„j»ú:Êv€ƒ'Þami¸ U >R(Ë'¦!)7ж•¡îºL€Q‹#“­«ëZÔÖ‘FôM »L]l«…•×wU&$Ј•,Þ$˜¢ùã1¶dœwb§ì£u¢4ÕÂÀºÔ©;Ã×]áH—/E€Áך̉`!Å“F¤áO‰Œo+¨¢—#F9ŒÔ‘X ûœÎ§Zb­!ÅJI†VUx…Žé­ÃdËA¡*€OVVŒPkÝ$øM"Õ»ÚÊÈ¿*J…"7¤Žo ^iT ÒxÖÈÆ2'«øç¼)µ÷ü¬˜@o†­È”‹ùÚ <ÀîH‰/»n)ªÕX¡¬Ä1½å¥”›)R–Ì$œñnv¿ãöÀò'èÒsëlLdM¢µûbˆ‘º³|îèŒþü´†uáæ‡ÁÍœÞÊ™g¤•›Ùämw)]dë^ÇÄën;<ÙäV>yfhŒYM¦1l›S o] d)ÈëëŒÂ¥Õêþ¦Dm}T…Ñ‘i V•­µ¦Ý<½mA (äc5I3ØÇ CŽo8¡µm%¶xâl”L FZ‡Ù"¥v"™DN FùP )&JˆŒuA=µ™(4ùÆæ‰÷c}÷Îu¯EÛÓøÛZ!ÿV}‰—j‹‘e•ÌV#1fJd)Œ*íLNPù”4°¬8^wÛ´„^V&wwn‰rÀpå×ìó&l ž¸*Œ°U4dVñ'ýýµOv…ÆsÛÞ…5u4XÐ(!¶jGÖ]¯{ 2 Í-:U&f{…çƒ,ø |n~+PØ×Ž)âjÃÕ¶*¡ì÷zô8ïqø±Ò04È0·üû÷»èyJ!’ùÔ M»ñ¤¦ÂJÌ€¤ñ¶#_ÜH×k%Æèe*@ëÒšÌׂÈ&V«QšªôÂTγm嘠‘l²ÜXI [G¶ÜT¹Ýñðª[|¶på¶Rpå€íH…ñ10&s¨Wîüÿ°“˜£™Ìaëº85¶‚»`¤D gJàúT²V˜FxG—Ò±±jMf gn {b¤ŒÄ³óTóÁ󯶦YI5ÀZÐÛò±V+E¦#¼w&l!µ.4É(G’ÙâÇäoíBâÍ–Ì*¥J/[sþ•@SzÃ4“µ>ãÞµ#ȹR¡‘ ð§_᮲Ež7”û+±Zn¦ÂcZµÇîûi"†{%.ýYV^6gᣄÃįs."e %€Ù“ ÃÙ ÐÑ:HâY¤ðj^kŒ!e1ø¦šX¶™{ÐÞÛÌ›‡Cn¶‡eùd[ ¡áŒ±çð8&’¬’ºÃA™€°íž­Z‡ÓK-¤:)A$«õ…ñ"†m ¥BdQ¡›[kè8^ªi #«»'†)­Z²lûFm¶šâk!åqÛâûW#J•å#jÍÿÎøù›[<¥ïq,U|¶1Lò±²M¦u©fC †”@YnÀ¬RÚ’Áö4¸·—,5>òz<ñùÓh^2‡<3™§S‹×Ó–ÆÚ3læniå]‹•’ï !1f“í Lඪü‘ǧªî•˦d"<¬]µîM_£VŽ,²¢o$«|¤ºgµ½Qj (­Ròlb%Ù2›ê]iÇg¶ŠZj+þ7s^°Sh$dék'µ¾ùØÒÀ+忤7j‚ÎÛ³£áМİՄë ÊæÉ'¥Bþ²RšÚÂR>_]¸l檚§2ÄTb H©M†‰´®üëßÿþ7‘hŽc›(`Õ>;ØdVÁÚùSöÌŽÆ/L j…˜ Éࢉ7Œ§ S2ÇØF†ìNaQ/Ê·…’uÁ›Š 7ÀÆØ‘¥LkÍÓêZ«¥Af «…m‚1 @ÔWŠ7ïÜÊ¥„. àIsS«¤óÂdªA@*qŒMÓt4“ÀRÃðý¨ÄûËúö|ôÕ¥IˆËb:á‘ ŒàÐÑð@ å&Ù)¦• *šnVlFø†·­P RÉbh¾_ÔÂd²)™#[‘ôx‘[Ç×Q`’8%þR\jY@Êã(K ¤IÜLg¼ò³HÄ4ºÐ×Q#v¬¦'X‹JÚ(é)(ñÊyˆá¹÷O~hê^a[b¤ 7|ÝwdôVJdü|ð"R­m2­ãTˆ)ÚÒWEœçV@|å篧ӽU|-lñÉnòlóŒOÖTîÁýàû#V¸pWëäÀБašåÖ䵫ê&CÇ÷&}?)±UŠÀ¡0ò[úùëR™/;“˜ºt]RÄ¢Úé‘¶ bhz¶4xÛn¾S爐ʧù{"¥¬²ôYͰÛâ<þû“ÑØ›¼yðUªWËK…¯–yöw¬Ú ­ÇýþÔŽo~2ŸqYåe™O&;Yü•çgÞ ­/%R|Nû;02¿m˜À<ަDwÛaLß™¹ÁþÀÔ´d¹ék‹WçÙ0D/iªóüf‡@IDATƨo gU"  l熄ýŽíÞ¼Ìú–R›òÚœ«lUèPÆÀlòµë~TIÿ @ˆTðΡÌeQšÀkXw#nÁpÝ…T'iJV¢3”—ڠcdÛ­ÜÂããÒ­ÈîwÃÐÔ¥ùmµ³ÚÒóI–¾ÙxÒPÖ}Î4ÎU¡•!rAcU…I_í=îùÙåä/åwnnøjÝÕôæ¶Ä¬x¦éIÇt¼àC,Y¡\U…#K­OÖxÎËÀ3åƒÇz[kÛÍÏ\‰Tþ¶ 0‘xQaMñʽ0lKá…"°ÚnæxÝ«H9C«B&Ž¡ìÞlÕ†;Lœ!&7 ¥­àœŒ·2Dºü3ÊÆÖ󲦊|¬JÄëð2Ù&“l9¼%#™ˆ¶ «µÆXeÕr[yÃܺs©î¼’>¤µîìù{‚Hè¢ÔòTÕZkÙܺ@J8[)]8¨…ñl{ÊéñdM"맬ÁúVDÒ Æ¶Í Ù¨i8HñÏèµIŸ¹*Ï¡îÖ”4lg•! Ùöp9`xZ‘ñRÄdH}‘9·Úæ¹î„ &@*Wë~:QU²Ry®0« ëØ$Jœ¾v|•XÓ´ÚŠ‰©P/}1Wud˜&HS£ñHØUtmù®;С2Yá|*Y¶‘Ê6ÏŽ†›²U[¯LTáÄÉrsù¶jmßZ8“À²mK‰7–Ny&¸‘˜rC&TVWø“³9è~dkA_*+€>dç„÷Ú‘¶œ9˜a%ï=`íë"µ°UíÌŠmó·rƯiöÝâ…ÌM6@ŸCåñzqÀÖ%†ÞØáÝRøŒ÷q“í®xrh~|[L¨ª°¾dȆI™&2+gq(ÑwòLðý ·ª†H³1ðd­»•³í¯ß~û¨Q8˜ÿÏ0«CVi¥]1/ÌŒj€©YJÙ‚¸ã¸Q†Ê<âÎÀww<ë²ôRÒ!¥„­,àÔ­ÎVoË!=P ÛüYaàdª²r?MU¡•^BJwpP[vnRÝ-°À[{é(Y!Û¬¬¶R½L9{ЪòI\£‰+·nT˜‰mL@-«mµ½MÒZk­3©*µ®NŸ¦ÖUqKÓ#C®°ÊS/@¡Ãº¨ni©ŽR®E-=ÜÍ3[ \¶•¾m» +JnH&€lWm[TÛÕ‘-âmÉZ™ç“R¡.…gì ȳC!”£u„aLÖR]8Œy»Ø&®j+®WšÄ¥Z³‚¥ 3ÛvŠVÛL’Yxú:Bocz| X!Œ¯ª#oëŒYY)éßmŒ5=å°ïäjñÝU20¢IšAá¶pkÙZ$è­ëãC£W\aNö|É´@ÎV6XʶͤToi X–ÌœÖd¹Á½ÉÚIÑw é‘o ŒéSì#¬VP:ˆÈˆ/eaN` >ÎØ%WØ*¬„À6±Ù:TÎ/NS-\S&J²BŠ)ØRZaµîÜ€?ØèmDá¨Òn«€‹¨¾¬ d­kæO*RzÄ+/\ùq.õc›@ª˜`˜‰”*Mk‹× #l‰m‘}¡»5¸¢ UHй¼ªC Òw ânC–’¹µkŒ¤ˆ8ˆ@þ¶”Ì{ŠV[¡¤U-ðôE„ ¾Üù'ÛÖSÿýXN «­@ÐýŸ_‘ @ÓV‚‘Ýyëb•¥Äó,ø`rÆpkža)V" qA‰!Û$+dÉ*ÙŠÁ+º=“ÈÚ­zY…”•›™“Ɇ¥ðÜ0j#½Þ€Tgä`û¾óuDzŽdõb"lù@Ðô()ù$ÈιÖĶâÖ¦´Îp¶²/Ùq"•8‘¦HµA/ú¶& Súò¾…•+ÙêÛpó³…i’ÁkªVh=A¶JU;=Ðéb¬FuÉ9_³ÏW6‡È¬(‹ÿ¹Efk ØÊ ྙ9”Š·ª"hÀA^Øgk˰r¤H +ð§àûÈ"+¿Ú¸rçí_ºxPóÇ7 ÞQÏî«ú¼c=j‘•‰rÑHMeUÞTùPÚöžd¢Ð=$Sn+;1†,¥ÕÖ„Lh(oæ¼óH%xQIp/§± S­L)ÅAŠŒÛ­>×"+rHÐ¥!Ɉ)ðJˆÃœç@ ¯.²°rÿÉþ>ÉÒÔF&¶jÔØ€àÏA¬WSIa"9%ÎÙzŠoÀ‚@8 àpóŸ…yO\JÓî¹™ë…ÍnÌà Ûê°ùè„ ¯¼’ ¹@dãÖù! ¦*úEL«Ú ô¥©Ð}˜¦rL%5Eîí®¼ôsS"bò±.Ê&à†¯QÀOƒ©)².]”펓ëâþ&`LþöªŠˆç¦ªB+RÌêUâ ú\èËA—;ÂùyÚ]!é)ñ:†›²èÒš^¤Á4HW$jÔµÉΔ_bCºj?Š6O%ʧ$«¨Q©È˜œ¹Ñ°ÊÙ_Š!Òãok•ÚYÛZÕf[‹+ù|a)g’`…5Jœ —3r€&p·5õ"ºáÈ i„,kµôÝiÉšÞaãé¯ÁÇÆ …R »‡dV)3ðo`Ê9„= <’&FaµÈRlÅÊMÏ<%“®NÉÿ¬5‰!Ks†~³ HðL &ë&ñaÃ`‰ )ÕT0ã7 §!Jäïj»ÀÖÊeE8íÔÖH·•5mbŒø1ƒmA)ÂsŽé¤8‡ãmÅ)»G Ð(†,“ôfu(­¢›ì¼n€€Ã[ bÃgn[G$+xk 7€?Câ”ZÓÃç 70æ¯åñ„™é-ÄsƒëÕ‘3Ì¡• µý0°­JySIçÊ¡¦8‡ªš ©uÔ*6ZÑ÷EDY­(mù`”$èÛ¾B‰­”@²¢³dk›àÜÖê‹w)V}Z1Ý 8K)èb+jIÖ¶±ëµ‘Ò[ÁT4R­•'ȹª•†™yÎLz‘d»@aµ†iÚ†©C© è½ ÔJ)ÁŸc߃ÏpVø&ß´iÖ%[äX;à÷TžÓÔÝ<"çPHs†û~XÊþ ó_ù«¯E>¡5¦Â7Þ`½À¬e·Ýý ò o[l ³)¤ìD”sƒ#¿Eçì0=Ø6©žJéc`á½Ê§­—*AšU{mÎRÓÊ#Õ L%V˜ÒÚ'±*MûØö)ûṎ@©<™›Óª\(÷>ç`‹‡Eç’êP5åô;-À°Q)ë>Me1>#˜IþøHUR7çÆcŠHÀ7^>¶EÊ‘5œ@¹˜g[S‡kau ïéó7ƒÌñÚånãÜ›?¨—Ó©o‰0—µïG…Ô¦”UUWRË®¦Y9È6åpU¶x%˜zñL¬ A[]à|–êxÍÃs¤!áΕF• Ñ‘›sÉr°Âø°m]l)9wv‚f˜ œ›T7P¯eeż£±²‹­?äfUÞüÄÜÔ–Ò¥°pG KÁñ˜›9©ô::”¬m“£”zde†Ò AO¡r ÎZÛ*Ùß´m~ÀT¾<­JzÙòl[Gâ®Î¶Ö'1F`d¹±²*)h  W†‰›–^µJ·b+[µ€¨]ú·õn€-,µÖ“ÅŒ¯ ½à/Üp…+q¸ÿõm…•ÈæqÃU5›€lK/6Ò–FGÀ°î@ÊÍ€¶­ô¢ì­û¹H?Uµ²ÚÌ¥Æ*Ô*̇f_8R°µy2¬»)TÕ+Y—Li˜jñÙ¢Ž;T­e¡Ü*› F²JÐ×]í0&ÉnégIlZªä¹S׎ÀÙ­ÓÔ¶ç Ñ{ÿÞ¿· ^½Jsähõ˜Æüªüþ—¢!jiUµÑaŒÚ ªWþøAAÏÓ0«PK‰O3ÉI@/0xYÀs"–²ÚÊ6ªµ­—2%A¿ôàÃ.–­Š'7«ì;Cƒåo=Üg ¶¾ÄåƒhbAÖ£Rå7Q%E¬_âü“ÞªÜJ¯ðz|ž+ž¹’xÉ:1eâ‰#s°ÖË<€¥$“²ðHŒµ€WÒl”õm˜kvÞoúÄeù²^Ê~©Ke…ª]¯g¤Ö¹DÏzz&ºX…ªNmUÒW’w[­BY¡ oÕh½«JY}¹u´J:Ò<¥bdUÕÚ:Ûæì,éëe°¦-•~²€’Þ0Î2}w"…‘7FóXá~݆ØJìt•8oæŽÃŒ­ØÿÀH>ú’mrÊ0àPôùíY# v NûÄ;@C97ÙôÖ@JÔÔ$áiðm§Ópþxbg$;Ö÷«Ù%têÉlUY1•pÆÐ#óŒ©YÃЯª.¶§ÓM© 6' *h`Q••Un …K3‰0¼¬‘d‘Àu: ž˜•-}¡ÇÓ“!gnû†ò¥èOïë™?å\÷ÊUôæL ùèèm±ÊV¨6Ì0½9½–dx¶xç³ÔÑ èçIó´ MñH>>Ý€mÜ6ßÛË*g)JX_‚Zt'·â|ÛÈ&ˆ¯~ú3Á_}l« ˜M•°ÍcøFbë§Fz$†Ì Ä0An lL¤mšƒ—"•×·gN*ÿ«ú<‚éëb3Ü6²m+ÏZsØY¤`ëR)šk­ñny¾]i0úJ¶ý!›H ¼š°TÝÛv«˜ÄÈøLÊÂE—ï˜@Œ«¦çé%'Ægõ­øË­Ñ·’Õ#àÍ6Ü­ZkD òWÒ$R‚?>ŸôÊñš•ÓÜmGÀ©Ýx¶13TsZ^“¥ûøfž‰Z]ˆ›vV€ÀZO¿û³¦#7,kNksâë^ÊGÌ/ EJèNÜj›¹•9òmбå$k»i•KZtÞúFªz[ØrÄpz8ë‡ñùتíkÓ¨Ÿÿ@9¬[ Ð¾³™Y–o^R.d?ãŸn¿?õFfE9 ^p0´0Í&Kf%—¢±iåV!¥ÁÈ&–ºÚϧN V|]ñˆ ^á²µN‹(UåƒÑš‰Áf÷óc|&”a[z&m;{Î0’³­È îø@µL¸”õVüåE¥AÒw+Œi« I6 ÔÄß¶9ljgÚü³ñÜÕÕ$„dØ´¯~Óöê®W&JŠ–ÒHÈŠ†I/ê‚ǼåM’Uc[ñkÄ_#[ëkÞåÆœF d˜·P­l)Œuƒ!«"­Åš.5&~ñ-úPR|le YdLw`¬YµÆ(Â?V©è{%"ëXkÙL|®cT‰þ~S‰Zš™ašpæÓäV ©W)«”*ÀšLvn3,ÕÚg¿0]HVýµ‡~pð! ÷ÛÿÛY;&°XkúJ6ö&ÔQŠIÑV¡—µB8Á1úkp óÄ v[íhgÙv©—€óÇ¿ÿýï]@ʽc´¥v0¼¨Y|C&¨õÔá¾›(µiб˭†ÒªEβL¡õÛÎÄj1V…^)ëB¹*%˜]eãõ.ÖZ-dæ°rµ²á&OÓª…ˆ@y¼ØTa) 9aÙÄËCdÓö¼•ØŠLzaÎÊ*Jq+F2„ ãc€›[«B“T1ÓüðOV»­ÄV¶Q;l «ô²ÙŽ!nÔªl“¥Ì§ÃÏo[(ñ³ÍŠ›§+²ªÂK±¥ì–¤V÷4•íµ9/¿!ˆei0.ÊjÛ‰Âl3$Æóá 7y#Õ¢øÝ*±}S•[¬´ ³Õ%=Ѓ³Û#3C²Ûê ì6‰Ôø<•#aÀ1;‚U0±rà,+l•w@n*ÇËRvMn™Sf¥|Ud²V/„UmKFŠ)ÃjÅÍ|¾Œ‘LaµîÁ¨xb)«Ó …}ÆÁä˜ sMß ¹YËËÚZ€Iæ5E®….i¬4îhebµ)ÉDíbò‡é;þQ¢ oN|C2w@$ÏRáÛäóng²Uj'%æé«…›-ñ¶È:R6C&ªŒa5†µ*€FTB‰ÉYa«íR{ÙÜbØz! j vœd°”ØüRd¶&d%VJ%Ua~«ýu]ôUY7y¤Zþ9TÕÖÍ@æËM• £qÑTfU Tb@JÜês"…‘m׺µN¦Êaid­™lÛ sHP sÓ˜¹ ë‹¡ìSFc›-œó@þ„ŒOl<ñ÷™üú5+¾òÆk~LÛ¥ðù§™2ÒHWȶñ€˜+ü\~xVk¤o*ÃÓ„KÁÕZ1Âa­ø½[½™_KV8OUªðBeÀ«n[À*^?+Œìã¯*ìøu¤1C-˜ûÏÀHšx ‰‘E œ@LóöJ³Ú:ËKVØŠHÏÐ)ú•RJÄȲ¢oEËQd€U™^Süm¥|çËŠî*™”HF™Ày&»q%gá ¶l‚ ë«–ü]m jDã³f5ü™áÏ?ÿôœ>›ûð*^½,¼f€PÏNÀÖ;ÞéÑ(é›B€ÀÕÀ]ZzsŸú{G w ¸-1Rðìxµ™ôn]í©-È6ØZ”ª©ÕBa‚°­9yö¯F\Éç•·fÁ6<>1€lNÚ’Ù¬¶@…j;H7pzÜ.ÕæoÍ_a&ù·J å@¶L`%ø~ºc¼èYƒY3of­é‰ €w¨“*‹¬Ê/wJŽîû(‘³*…™¡¥în (òÄ4dóÛŠTØÛß6†­l-D€ÆÚ‘òm +7Õ8×ñý%LCög ãI!wÛ˜ "™Ô·-FÐd~}ùfÕ´LhrƒÛZËæ)kZUÌ…3Ç$ªVh+«j ¥*ÀÊÖC å²Í‰¤‘ÕÑ*‹ñ:Ñ(‡ë•mY ^4ª*Q#¦¤‘…ɬÆS ´æ)52Ok!XÙæ¬ÖÀ9äy.ú~î4â#ð»[bGàgkÎ0Y/[åÈ ‘ÙVhm Svöe%VYž}ùW›ÀzŽt&&Û`°È'œ22q¼Óµe6¦PEfÚ³ÅÃ@? ›¿ãdXS«à)ðœÛ:1’CÌÑ}?GaY µ_#ÚV¥\­†1Okg×H¤iTÝ+“þÜK[•ì8iÈ6ÀYÓÖÊ‚l©»X1YŒÙ™­Â²ô"ý‚RĹ)߉*i%ëq8 R 7$ tX¸I% ìÔ¥lnôE6OßÌç áõÙüª ¦Ê"ücÝHV—ñ‘Öšâk§ušœÇ+ßÍLc0Su$ ·œ›Óý€Raz2[¡Šg O‚M"‹çcÅç¶!~#^!±ÂºÀœÉdkÈêÛ)àש“¸l}ý•0kÏxÿ1M=­8S[ý`¾¯Àv'ï{–̯Ôôd-„öb&ðl‘ãÕNì9‘ñgR-C¡°rbÛô›•¬»ë‡­BJ­µØ¥¶º sË#…ᬶ3^›Ï/ˆ²¢læðH&¶ÊE2Œ°µÒËê(ÅùfÎb{+NÓ¢Úô°¨±B8}¶Hc#å¥` ZÙl+LceeJ²ÖJ€xÛ¸18+\m%“ùðךضa”—ª¼™il“Év–”Èø®K6¥l‚ô4^›”ù7ŒU!žØ»Ñs·d8ÜÚ]91™ße½‡½Š>/~ñß‘寓X̧{à#j )i.}¾G&£Á·š“Lª¶x[ 8¦ÅÀg‚+Î9Y…xÎæ7|²·…Žºt¥dয¤/ Ÿî.“¦!õÊÁ6=ðÿ•»¢Í€ç¦;ÐxM²€ÍÆ^¬„CMའ4²òIf È:>YYãá:T…Rb·šg&x"Âþ T8 P^_[L“S:~ºM>‡"˜dô¢—ÓH[…O qCbL‚& 0}þ†!cE)’aôªª¾˜ªli„,&-Tn³ºÂ£ÄÈÂYUÎ!Þ@…VJ—™¦OYÙ=&[A°Öº§WN†ÏÜÚã@ö¸¥j„ià>ÂÊ«µÂü; ¹B k/…IÈÁJ†Q˜?Æ ù”jLž­Rl…m‘y+§÷³{ããMÃ÷i0sì¾+M‘¶7ù4®¥Cñ¯¯Ij:=^y­›3±Up·m˜ ßõ tϘ›Túzq˜`|å§Ó¶g¶i”+\à1ŸÊ{À0“€”ƒmÇokMÐd¾k_k€Àš¸í &Ë<¾vð²ïqºvšH—#[Qk$ÙIÉ“3€”ªœ¢SÃdH²Æ AÚönô(m[J…pÎ4°B©ÖdMB,Jñ‘~R ^9†f¡U!Ež})qèÄßüY˜Ê­dÏø6€ª²YÙæ¦K 1=1¬œþ¬þÈu¢¯H5=c 5¦i 𦔠psÀlKY«¸é"[­•³3ž˜c¿Zeƒ”­ÄÊ­.jkÑ*%¤²’Õ‚SkµžP}™§§¬Q% Æ'Þ<ôH P•mž‘yŒ*ÀÚHß$ `¤[80·e®6 ®ýçK¼.µ+ÕH%‚ ¾·ôヴí8²´­ã5Oæ”Ã@äRµ~ÉÛöô}£î˜Ltì¿ixÎõ•¥l  ع0 9Ë"Ãn˜‰ÈßjZ-¬"€^ñ•ó'à` 7›v€×Àêy[Û `åYaæükaÍMöM)¥¬É0@Vóª>¿ ”ms‚mÉMmSá7á§—ê·ŒŽo/YÌH…ÎÈ–œ­ s¦à‰më )« ñúò‘mÈ ˆ¡™'–j`%Â6†¦ò:"1ɬ&7›ïzÙ®Åü9HQö)gÒ—O…xÃÓwþ}ØŠÝLÿ¨-ó3Ù}“;¬‘*`ÝýhŒÑo5^ÀZGÀØVå¬RÚ X˜Š Ð:žØRÓ³½u§@‰l—ã,H[ëið„TU¸¶úH%ÍO#âi|÷ÌJªîRæ”*̃7Rí®Ççíå@\-@–•§/ÕÛ^_<Á.ǶkWT!qJb  aÛ²S"¥Nï;U§ˆôX«²6€•›x·µÆŒ|Á¥OYÑÙÓ8K¿»H Àeõ­WWá{¥4fNÜq`%…,’ÉŬ%RHѧ˜fgÙ7È2lìæa’³q+%L¦W$LOé…É“r£ž îi*âiê˜8+ʺÃ%sÛýžÞœ‚¬æ`U¿¨u<üZÑo[ëÄÈ ‘s®VÓî‹¢¾Sn%‘Jb€3ýýP¤‘RÍcxÛ4¶°ÛvÿdȆÙð¶é°’¢ªüù²{”^N¤È6«òâeÔ–âÐ$ú’)¯c[ä ·ÕBßô•ÐTXGSqæ‰÷}HC¿—Ù6ÿâfvQR UùzÙHµÀ³í+®;I9+-#ÿxŒˆÉ´º[¹Åk‘•.È.S¹ª²V'‰'.›øÿü»Y)Ò¬¼Y¦¤,¥­‚»”F¯¶± ZÖõw„Ê¥¸u˜ƒÉÈ0bç²L%ÕOGµ3i†NN&ÈXñ„e¥lÇ ¥h¤çF€¤‡}óé€Äéms°¥Œñªk)¶s€¥ºº£¾A†dº÷ñ‹/ÕJ/V Ø®]üÖ Ó[Û¾Y¤0RGà£oµd€Tåmßœÿf.Û}®ªì.Á6+kåfHÓVÇšzC2)û¶Ã¬ßmÔÂqFÉþh7’¾ ÄkS;[À o_Œsa"kaB²¾úä'¨Ü™ 72\/«í”mésP.kM¶6ÐC4°@ò©/œ¨;„ñ# \ô™Uî£ “![…-[ÑYbèyž‹þþ– Q²3ͽCLzÎ}„É|Ûöç@Îͼ6˜Z@hAck¬ÖW–]¯^92ž o )Wäñ)7¡TcSžö÷©!mÓ7e‡và gþ4Ê1auc®‚9`«» µ@Z‘<+Œ'¥d#m3å}îÖ‰´hxUJ€¤†ÔIiÈHÛªlá‘9XÃ40 ‰‡•À]¦;YŠ€ÞJÐýÓcDVÞÆ1jaJ‰†/Û¹(2l6÷ÌÀjóZ`¬ôµ³eà ðò™`ØZ ÒH:b kšÿø $S5O2w’-²#ðé5#V%jЈÌÙlÝCÏcŒSyƒž! àCz=N­F.S°±JLkzµÂVÃЊQ>}×úÊ?/¿ª¶ÆëcPrÈ­l+ž^˜¡h6â ÙYÆØ YLå ¹5L¶ædKfÓu©²µR"kZ•5þwol ¶È×Ãy&¶f«6˜©&°Q³B&#èPüÍé{i&x-ÄèvWå€VʘܔÙ"Ì­;g¶Ýa@j—©E ŸV|&ãm™‹ FS!CYJYçJáù-_IþR€9)á™G6ŒÕëÚqh(aWç¡+LTVY€@تµíÃîkÇ›ƒßx±‡•8C«mÃÁ9×ÂÙǾÝÎgP•ãÁQ 23WžOGx³ñj}™æó·,íëD!úpr@“µöd5CÂbã†eÉT©U¦R$Oz& r³¨u²•§Ù½eåájÛòÏö5“~)“ÐÛæài rV¶h[M…pž°’V `Í!Y©¦Œ´<=EUðá3FÌ<É2 Ä+aµ8vOä€ På‰sèÈt? e” ´–²žŸÏCà«­£ZúR°XN“ÀÖT°1èôŠ‘É2±r +j¦°‡EYíGzïv&ÈîPUw⫝̸'  • €Ì¶îªš*ÏNøD1!«<Ÿám1Â$ֲ̛Ð6Æȳ›ÁèW«zç UB–CµYÕe/<²ŸôŽ -:Nµù#ÛêË-âr¸™_y Èþç?ÿñ× š6^áyÆý>îº4L¸ a¹©8GÒD&°ÚZk­öµæïé­šzúžšóv(‚¦õ=Ž”êç=sΙ|渷ªÜ'ˆLÔš¦›ªrR˜3 †a|%ª´6äëÏ“F•ǘYvþ=˜ä¿#ëh#»=šŽ\ÖVÐÛÒ<¬Ü (“iŠÏ¤I¸ô)X»(EÏÖ–8 ÜVg‰·*ô‘§×Å+Í_ÉÙ® ehUÞU¬WÎkšOšN1«üÛÒgžÞ¶.݆T±© ÙûÓ1™Ð7L¶: …V ©`Q* –[2…‘ØÖ=¾“f«—ZdKÙZ§mã9]'Ý”B:Þ7°ª°•Ò‚OV°X_˜l[¸Ö¥¬…rMáÄZۦĬ)A2+R4RåÕJæ— Û6^2%&„{Ç€¦Læ%ôyÉ„’nB@Thm*_Èœa)â»ÂÏ"%¤ÌSØ–»™³pÃ46ÜO)ûNKÐ)dÙJèk„w™̳‘h0R½½”U UÜøœ6tDÕÛÂŒÔý@’Fá4ºrتË6_‰<ª”•pÃ0™¨C…|²­J¶Ö€P˜Ò*®Óç*aþ1‰›ÓP²÷Ë{qk²¥ô(ñßc`BÆSdÕ<ð ÎX÷PÙâÇ©‹®µl¶‰@_À¡š¿.Æg+E©¶ì¹è½ e«¢'ËäÕ#e­xšœ[ßÈä\Ľ ©1Êm³BÄDÂbäZ©¯¬7¤kÏ6çÊ;cÌuúüœpŠÖ4ÜDÛ”pþMeÅû­Ô#zJâ‰1ôܬ®ÑH²³Â‹Óãé¦Q.6g8þ%ñŸ‚ Zcœ®Ém@ëR+oTU*¡i0J[Y¼³xµlñ”R€È´zuI€´Å[?ž0§éƒ+é› ÐµÉúˆÁfÐ"ÒJCŒÑH$¿-€C%VQ‰1ú ˜J6@wLOœ›Hü}MÛäñÚað¦õÚ(á“sogÙôÄ4ïü]E$,è šGÕï—,[¨¢§±U¥/¦’@ë˜<‰—íÈïvÎÀ{R¸B+žªVn%(k$U&¬P耑]7×⺌ª|6v†V—)•¹5€÷R)ïø¬OVwQ9RÓ¾r'bh[4¤ªxëõ8&=èl·âÕîí¯° ßݹšmÃÖÀÕþz:Ù+ÑYÔ¦oÕO°#R¨6gkWÝýSvÛIEòïÈH×EÀ¤ò:ÊâÕÒ $L pnž¬Ç‘RaÃËÂBm 9;Kz2$À¯ R=å¥TáaŒÖs@z‹Œ×䔕°RbëÔ9Çg’ #`nñk1@kš?[ú"Íw÷RO}uoàɪJç/ë¹Sb4²Un Ó8‹à–®–€R൛¬Üµ`ئÙ*%𥪒åi'°mÅÀà œúïcªÅ4 h>å¸oV+/·C-tòÙ@Š#½¾F™)’F–Øv  Ôø4ĸZ«ilÏ870¢1ð²=¼3ÓJ6L°VK/`3´­ÊÚ$UY9;§E,zl;©MU­l¬òi‹/…T—m°ôÖ…*2[J ªæ1†-~b7)ÒK( FLÏÄ6±{˃;iÝ;¯ÕV#žªº¸. [kÃXhÚ²’JÙZmÙax2M;&’ž pŒT@]l3«Âk>)[{ÛÙÒ0ÑÂ-qîǤgØ V©h`@‰FÍÖ ðª6gŒ-Ÿd€ ø5qç‚Ká1ËâEøúÊ2/`Á<ÿô­xàæ-ª(W ÐÌ–S!Þ0¶çÀßoO3ÒðmWÛ¶õNw®}úWoK£igÑš¾ΡrkUÍs ~=ÙhÆ¿}eU §Ö‚¬›O‹°¿$ðÝT—Júº?Ÿ–ï êB/8 LbLè‚G挼ò“Å$þ=KÓx‰uLÉ_äɳ5’[攪|Êê‹T®¤¬_y `Lžab%i¬R|`)×Õ©¼©Ná3Bf’®µ-Ÿø ³j6J[·êWa²†Ô¨‹Ú¡VNÀ$VÒ3²¾[kgKfµ¬àM¥‘o!+ÆÚ¡¸9wjäf®7¤Õ–®Ü6‡d°!ÓXuQB¹³ÄtÆ …Â`R†ø˜Aª+Âw¢dW~†yRîD@dK-Þ6Ÿ.ÆH)ÔzUñ[ ò¡xJsêõ¦ÒH‰lbæ€BM¯Áç7˜‰o`«pjâÖuQ¨K[ Ö™ÔŽž¿¨cg©i)<¡¬–Ø–ÒZU«Âz¦±RÒôtæI#+eÄš¹T¼1Þƒ ûpãÑPz%˜Ì§v´ ™*gâ|ˆéáÊ}§©*ž'À3s)²Î3™ƒ-MÙêÂÞäV²ç{Äc"ÂÈd½Ý¤-¾!Í“ÞJÏК?fŸ!rÄ8·}šdÛJé8Ü…B¶àœl®)rÙ”Y‘UNà O +ôHƒ¹4Û4˜•cYGÀX+9ŠïG˜L9’¡”ê71¼è6¤ðÜÌÜðRÜÒc Ùmr&)eÅàKFæ Ð¾Fl%Ð ³ÚÚu®u„Úµªª/`Nž”Î’Ô}éÎÂM¢0ÎHÑ1izy[Jk·Á™L9(·•í|TåY»ÊÍi+È:\Çþ¤¿?GÙºZtGú×:fMá¥òo›OÛVŒ8Y#•Vs<í‘tV˜N  qJhš¯51’ÀíÏÊïRX-úpsä¬\IUôyÆÀ²™´&SnÛÊ$ÎôxšUI!E…VsÒ4mc85Þ;dø +i0<š®°¾Ä '0†A¶.`)Á ÎP* ½Á˜ãá"% `­u[ µ¬U˜œ!++}¹šæà“ã{?“4L(Ãø‚ ¼múm?5ßà *gÛTÍ€?S~Íe+ÂÿHÙž~7¦'†qÜzšÎ çÓ©ç9e-úÞAîqg+ë5`pnŒ^ÌüÝ}S!•X+©öí;+¤*+çµ»g:ËÒ[wê*†Ã"¦’Ȭà¥dðÑE*Æ–¸‘ðÓ)ÓEᑉÕnNþ¢r†nrÄ"±ZY©ߣáÜ0˜|6ŒBnV¼,¾ñÂÜNãyÖ¢Ýé’Y㹉mµ&ñUF[Õjwj%Ãôå0% 2i†Ö×í²Ý;ƒßÅ KðCÆS»ú¶"wáR»<“ô0O«a[Á¤Xö/L,øÔÈ c:¦_DÆ›*ðÎÖËô²R­<3/åÔºÃÈLÓý;‹ûé=I@aµPE|O!Û5æL0ÙNǪBΑÖdxÁ¤!Y5sY«ÀÈ*Iy+Îåã ˆÎ"•/ØÒÈægI ÐËzÙ"m‘†•›‘eUIJY)«À#Ö 9à5Í )ëŒiˆcêØÃÕ¢¬-Ú@†RÀ™ì~^f[÷,L;Y#)$ƒ¹¥o%ËDJtWM"åÃHÖ È‚Í<«ÊmÙÖœUÙº(Y«-Ax>ÆZ8,%€f¸ñ©œ^; lUýùÊ×HCR:W%HnJ [çìÞ@?‘ÔÒÀñVL‡ŠG’5€ÚÚ!cˆ‘V“¬ÊV(ïÚ)i ¿à'¶Ú’MSI‚H+MCú¿PHé>ó”î\9NfÍ Ù1V¶ôÖ® Ó¸ÍN·Z_MÍÀÁCa.Ûs9ׂ^Ô¯/Ì¥DìÉ*ÁÐdµg$…·*AV•?¦lO i«Ü*f[-PHU>ý|néYø¤—m$ <¦GðÇ?þñj7ØMILd5Ô­R”3½ñ|;dWK>=·Êɺ8d €!” @TÔ1IŒ´M œ²ïMM`òZHåÓY¬"¦r´žÞEÛ¦íšA–϶¶á|òTûC€Ñ)”Œ°Å³µ"µã€ÏY£Â Wþ±½ŸT¡æzåbLΔÜð€·V/¼-2AYU¥Ö‘^ì©‹²Ê'Ö±î­‘ÉøäÏ à3“ ­¢Bg¿ ÏÉàRµS>%ìxæEbÌÛÅVPNÓµk„Éá´^¼Zcx*_‰#‹„1(·Zx©¤X3'f˜IÓv¢J66ÉÄ–>óz9á9¤±Ò¿V]i&¥d˜¿#¬/h}5R%Ó‰&ð²îøî„³S¹µ^ŠOŸÀW«;7Ujo°ª*lÂX¹µaZ›IS «É1nælà §$nªN„Ô ˆfH+ŒiU"•m÷†ðLà’á‘Å*kKPáºs«œF´­Õv¡6çÖÍ@¦(‹iÚlñ"¤‘ð d‘&Y«i;5€÷ãÙ‹Ý{Žd+kõtÚö˜x޼G¦¯­P‰Quô¶õB–êÒ#e;=2^¡ Dªâ‡¬+^­ÔĶ·ô|F”çLà€x¢‚7$[AL&â()t@€`æ fýVd€f 3˜hËãV9—]ÙŽŸL¶FV±i¡‘`Â9½ê@Ìïë©¿Y«Z&°‘`Ÿ›-ÜÁg¥P—ÊS6y¶J€‚UoT>Ä—ÞÍä³r²ºb]ø0,UÇÉð²Ä&ô* ”YTØ ¡©5¥{ÆtÏx&Ë*$ÊsÛÚg„Iµ¶»‡*dE0Oz|snŒ)ë^ÖJ¦AãVø 1«m枉mV“; `Û‰Èlc ÝLÛºÜäÑSv°jWǘfޱ¶Õ…»Éø„¥7mzíSÂ?‚ ™ÇÛ [¬s@æ 0LS•­›„µ¦y³x[Ò×Ë6Íi-¡Y%l+]cÅ"œ©Û”EÎK–;†@û¶×õ|–Ès…iÈ0›ÒV¨²ª„lm[›ŠI]èÙ†‰3ª¥×¨á'#X [)è¦`æôÊá ­Í@¼v›P¶.ià˜€’Fmå)4nàºÀBm¦ÁàsF†ÕâFÈæŒIY;âñ°H‰tØ^bÍ>¿0lK|í?-F*éˆÊv‡pï@†N&›Ìš݉î*Æ–F¤ñys.­mHb2¶‚RÕœóIæKÓ‘i„’L0dÕb¤˜äÙ¶¦+UhçÂ0l %d)€ükÉ6Yk²ZÀHV@똾blΤ¬ZLBSªv=š ñ4V¶ÉÔÆk*£ÊqD”šR­­È_¹Tžô¥T!)iàÄ4¶µkþ²JPJÅÐä\#ÛümD-d¹IñÇLRÚÎ<™-ÒûàÛÏí¥oNk€2œ-+ŒBúƫʺF²°*%@…ªÔÂÎ¥czʶ=#šL:2 ’d¶<»–ôp½Thè­ž¦K€¾ÛH÷Í?}²J>.÷üßP.öÐó$pr)L€aYÃwuVS©%%î8®…RVŠXÖJ@œ¡­=)+Œ'd 8à#1µ¶Râë K5˜/2É¡r2Y‘rCÒ`h0 cà>Sø¾âö@‰ç̪r 9›ÿôø>š°ìfã³Ò c«Wc·r6 ²#Ð$³%–UèOøÕÆxú³ÓI©šƒÙVÈŠ ß&ŸoïxÄ “`²FåFÜŠ‘Í|$М4u4ä”™tu‘o8g“Ï9††yž¬ÿäj|o`zUæi<¤¦¦ÇaK#óT(ȤôZI©”[‘ü§gkûf0º÷LOÙ$RîÆø˜Ž„­3'+˜8‹UÐ[iülª²%ÈRj¼ˆ!FšdÊd=PÏÎE“Ù ´…•¼ ^ô=ÂVª^[† 4 I¦¼.'ÛÀxL½zŸûÙFÜ&0­’·ožV]XÉòô•p°í ³*…¯#Í•Ÿß6øãr£ø’I/¿T÷€øL¶­<f ˆøY3+‡‘(lûÞ@·§£lÒ×eµïG½‡ÍPJdbø±Z< ¾²i‘R S£:JÃÜ^›Á–xdµª€:ÊšŠÀªW†oIb©JTU˜3¥P‹ìÒð¾B‘ôB!œJ2ÃKù,¤¤ÁØæiÈ6+þJ¬æ‘…e­²RÀñ ¹çX9`UX{åü#;f-(ÛJ [¡ÊªDaÃÛÖ¥”YYal­¶JjdËSpÃøÞÆd?|ŒGrÎÛÛˆœð«'Ÿ”4ô<Ý©Sy/‡YÓ< ÒV¨Ý’ad‘‚òJΕ¶%è!Î!>ñ†_a“Ì“ž @d…ﻓ¦*k2VpÙR0Ò hŒ^dc›I£J¹Rµ¥Öš8ÿf0˜ïœ·¶G c¨¼¨3,ó<Ïwæô°¬µ!µ€­ÈÂv¡¤i‰ûÛ)-¼ ÆÀl<¤PŽ€Bšðø+…_ Yøeš³ƒèbë*"Szyð‚Faëð<³5ƒÂzEÆ·šYêuV[ ‚{¦óc ÷ÿ:«ÒWº4¶jmUpg±-[![Y/’^ÄFåîµÄt´hd4›òz5vþ • ¨61𛾮ç¼RHM‘cÄ ¸÷îZš¿rÀ¡*´:…¬ ”²$ÀŠlc“)oþ»Õ¿^Qú®ÑJÉMyǡϰB|7©ß¹`YØÚT|¿ý3¡o¤ÿ4 Ù&øX&OJV»O)æV÷C扡Dªê¡c` Û&·V"5&L“Œ›HF#+z!ñZ»íUÑcè{Ùê^¹Õ– ËU­Ö"@@i ¨]aض¦4=£ÌÙ¶gî~wçà9׺­5M†d¶Ú‰pÇoÛ„ð4:j]–R¨jŒœ¥Þ„Þ.«ïŸœë8O|±‘";fMK‘5Òh6n=5¤x{ÙÃTZ‰)ßIêw½™•žìYx ß)á¿ñh`7É ñMU¶íå@ìÞú8ÀÆÐß{(EéœÕöRGÛÂV|wç5ƒÆ+· §‘J@æYeOÓ”"žI§°v{üóŸÿ”–0}É6‹&°&ÐŒ,¯^w[O÷i4+,˶òª:'R6ÜyŽéœ ìšjʳ%ËŸlªM\ Y7BÐ7 çŸ²ÕÌÝU 9`î8¿Ìרª²‘¶Î[ÓHÝ‘”<ûöÄlÈ[qÎX³…;£-ØÊÖü¿²tÉôøÖzå“ÑTØšCŸ–ÄB‰C¦ªI¶¢aêB¨ÜÕ‘Å×Ι¬^ «MIp¬¿?!ÞëªDªªÂJ0ž+Q;)O¦‘UTØZ¶Ó5Éܤ Ÿ¡ª¶u¡¤2QRà•”M‰WkU~ztÕO&p‹± >ÖÈ¥ˆóoų**븺Õ*¹#|þcVR…0 Ö Ц¯NÜëÑ R…­š¨o[·!Ûã È K))‹½ÿn•¦ÖR}0óTÔ+Feg|‡›ŸLÕ1ªÖÛ&‰T^àu¬/М¥âo¡¤Ò¿ãUn­oM9Ø:x¤ªšN¬,ð4n[—¶ëX‰UwÎb§Ë'}ëª ´ªÕËÖ·ŠJ¬QmñÕœWÕ8ÄÛ’ÁÜ,€ôù›­a”x¶VŒÛR½0Ù~Ü®©r¼ÈÁšs}m Îz!;à—>AÚªò†[EšÄ­`a<¡J_^]…û‡ èñláã{¯t«ZçÊÇÊSIÎy‘˜:"óGÂ<¥Èdd]0R¸:‚ ë¥VÛjNWT—î*|%Ÿo µ|˜gbþZÓäoU›¹TÒ ˜¤ñðMHüðó’¤iÝ„ud%Þ‘šÙ$½œô9÷¶4’5H`Ëж. ön »¥Ž&+¦TXm<Ì Î9’8=R¼J¼ùËÂð4ùèOý÷[‚˜ :Â&Ùñ rH`»‘˜Û ;YÊ Ù djÑŠœÉô«TYâ ë%UùÞ¨¦­EÝ Ò$v„‰=‹=_€ìŽ|Þí0bòdd FRæ/¥Î*R™™áôy–ÍäóÓs³}õª0Ù¶rx°òªâ[‘ÜàÍæræ³.µn-[;ŒPÂäû‡ Пԟþ©`Ÿ4¬-G€• %Ë‹Åz¶ÍM¦œOµ¥Ka+Y±º|¹Ïk3¾ @Y—JâSjŸfß]Š7LU¸B2L«Ij­õ’*»”­.5Ê¡µªaV¼ZƶRâÂe¯ðóÒÃi¤¬p:+óGÌáènÇ”ÈÌmÉ&®i„•²Mo¥§aÒs*l’ʳí’ëkÍ“ƒÈÐZ”U+vئlJÏ%M&_ƒsuÉ€HÇñ³²… ²UR7©— UùúëÌ“¥‰ÌÇZГñ\»d¶Üšj+Ù®{z-Úâ=T†” [>d¶²Íßlª0R¶VMe1‹d¥Â4¶ ê‚G nÎ.…·¤º;‹HÓ²R9[eól•*›‰•†[zb-FÔ(Ò(”¤4O¶e­Ä˜B_Ê«-žÆ¡à˜WÏ3ÖÀ®š&Ù²)#ë… Dž‚;Ií\¦ éÁÕݶ­zU"ÕÌH†•Äô,0¶dYÕÔ–ÞØLXÁ¢.@OÄVÐßäyôÄ•0D¶Ö4[+Á²ôR6F‚Ä‘¾³X때¡¡ÇŽà•®ÄZªù­3'®YæÑJÉJ¹ñj ‹w°Ld9×¥¦”ÍÃMÐÈîDb̬€ZèU!FU­“)¯¯Ù0ºå ¼ÓÑTe*¤ZY¯ R”MŒ×‚, Œ4Q‰ÖÚÙvLXp”ÂÖªxË×÷Ï~Êi´à–³mw¢KÊįsæ ûnÙÀÈÆ¨)Ï"+âfJ¤S`”³Â«B6 Œ4@#u3 hTåYy ±-M—“gåî\Ê¿võs‡,%²0†^x‡­ÍСLE#l¥¬¢©µf°ÕTÖ™íŽÆ3+•REyY<’É.ð1ð•`TqÀˆÜlûI伬™IÃØöÿ PX‹V/•!€{(pcà…B|J+FöfNŠ›I´^­òÛäünT2@ÐTÎG•­#`àÄemE}­‰•Éemñ‘‰[1e‚L4RÓZ¥¸­0P/#4ªð¥¬JMÊØ –²•Ͷ›Të)[Kñ”M@9ž•e%[%@8q+Fj/m¾Bº†A¦¯¯)Luƒœ@Zã[ž^—Æ áÖ”ue:Å|0²£D`ÂéÛNHÙCÖ„9Xñlñ&´í iºm|@–˜ÌÚk†QkkZk&ôYÕΖÌ*&ª;æÐ´6\kƒVµ‰kš³çe+r¶Å‹†£w¹¨¤^µ`ŽŒ¹g*À€»&/i+Ť*&UŇsÀäF hf}¥\HãZ•`Î%]õئ´Í—´ºŽ,bh_©W¼§"ÛˆÍÑ Ed½`A9[)Ôî(¾—Oo°NUêJΖIz™ƒCß„‰Ï±ïã¤Ç´¥QB¦cæ°Ú¼ ÃP6-&|“碗F¢{'ÖHÔŰͼõˆn4°”-ÛAþN¢c-ÂÍ“S0l0VµÀ#Ye >¶‘m­Í` Ý÷Ë«IXm¤ÚÍAI#)‘Ú«r=>߀øÎ“X¥ÓU {:¬Õ¶ãœÉ¾_RA¡§#êøž±Ö•lŒÚ‘iÔ¨v|¤­H Dfž~m&¶Ò7Rµã)±Å79œ!F¹³!mû·)üäÞý°’¥¹òÏw+þÝX¼ùÛ*é J ùY•bˆ!®/¾rÊ£I@ÙµKá;…Ì¿5%fof%²U3ïNâÕJ Î~Ó¥€•8¯1bdUeÎJØêHPa©N—2[]èLC® Î(ßOÐ]á¹uʯðüŽe྾d±èÿ-]à 5ª#fƒÕ(Ÿ†O„ïbëU £ÜüV‚†ÚU 9­•OO-ÁŽ`xåŠ åfÅài`ÁM9Y/”ôöJÕ…3@Qžè Abd…Ó ØZíŽÄ«€Ôßþö·¹yJØJ!Æ“¡B>˜ÜòÓј ¼oÓß´ÈZTμ­F˜ ‘{ð ñÈky~ ôæ4CçCc$znÍ–ÿd5êÚi˜¨•Uȶ©f²Öª¶‚~%@½ðÍoK)IMÃg7–¬ÁÔfµòfK³•f®]ç­Kã¥ë®¼,s„ë‹èëΠȤ^ῃt{ÈýI©BYUÚ1Tè5Èð¿Q›¡VšÄøÊ+)óRñp†‰óA:Kã|Ên¡-YUuÏöõ¡±-ÂVÁ¡Á¤`+ò£»ÿ"__4oý/_w³$[N4kxÐ3àB1ãïÞé÷Ho¦·¨}ìÄ@¸<<ÿ&$[o}JYnpÛ­ C/$«]Ž<›0ó×°!eéõi˜œØ–&ÆÇÔÈȼ”Cq¦A–] @ ÉYØŠ¶ÄX£zaXÄX·æl]£MkD™8 ÿ4§·/°×FZ z•eá 7‹II^ OÖIÚî$ñ]GWƒé³Á¡vÉð@ÁG`ÈÖNXÎ92ñ g<1 l`VÎÕ Üüéô×RÙûm¤PвݘcælͤmåÇ÷:7CÃ7Y+ù¦~J â>pÎ{.>!J4r“} #%¼IÕ ”}ùR=ÐZ«%XI@9Þ*ΈwH_ÈxÌŽ¯…¿õlÔ•‚ŒùÄ1‘M•?OG6•m?¥hÄõ8Ë™ã¾Qšº+µÄªº [8=PÓ ¥_ó\âÒËv-;W“eÎÊxH-š)êÈa®„C©²˜‘¥l¥à ;][>.¼2AŠ|@¯>UYe7IcÛ·íï_mVM²,P¯Ä5rXcËŠ3ÁÅȽ¢xbÃÊ1Al›­,V $K`ë·)턞g7°Ü6̧ŸXpÊ.‡‰Pøæ‰²-MµNÁ–g&ÕªÒ]е“¢´• ÛšæC܇TV<@#®å§*ÒÊJU½TuØüÙ&#€¥l•ØRr(ÕZ¥ðm)eO›kî˜Eþ‰éE¼[²–D‚÷%‘¥š0‡È[ôqøÁ”Bæoí’[ñ¥È¤œÂ–} «íD9Ñ$ƒ»)A†‰´bÜ@Îô¶æ¥æä,šÄÙÆCaÅÁ¶ §¬Cd9[«²*±UÓóÿ šøMSU«¾3×´­1 `ñÚö†à=}Œs9BæøSsß빬{:)Z¨Í¡­‘ê²g!+%â3̼W®_*ÒËî£é®*Ì$7k!Õ%(êbmTš1”4É(æ…Év¢lëUIت„R 0·°vy¼ Y1CàË}~.èÃAlÛð›‡f~þW€BQV7hzqÑ÷ùá5£¬¦Ÿ©ímz~~d4¢94+"ùÓwYUu˜u!£ߪÚ%–mK?Ÿ9”ª]+¼©VØÁã;š&JÈ*±5~ǧ™Ï ¡¶ÕœœÉlû<¨‚YÑX êUI)LG6d>”¥ÒÃ^4‰Y[«ŽV‘-~nHaâh²scÆgEÙü¶B¶«øÇÜÌgŒR@|å|4ª & ±ðóÞ-a¤†Œ•y%gyKX 5¹Úšv9¼å”4ùÀ ´„_¥€Äºp àì–£îm­4‚¿€ž¶MÕÊ ¸ûo¶HpêD@¡ ÌÎ<2žC†LÈÂFÂs5•¬úH¬x@‰lU¶Rn•U¢F–¾;쫹Úüé ˆmåMT²{¥WØSƒl0@–-ªD¤6ž×OŠÙd52 Rв°¦½#r{õl™‚À1ùDf—ò‘«)+cÀÖ÷sh«¤FL`1ÿô]ãívÚ-È”àMΡÖ0¾*«˜jaÌZ×é)¼2¼$2ïÏðª&+GÐË1   )uOv~›oª•Ä÷ïƒéÕo‘UYwøZ …ãh´ÀØjA_ “AÛ®bW—•ršÎòΠ6ÏÈ:¬`µ²ëËS*<·:¦‘êÜÃ&CæIé ¦ë+%Œg•BÑÀÄ›°O@á¦í˜•¨’¦ñ&$¨ÊÖ0ÈÜÚ»aÚºÈΰÕÑJÐV#á~j'eÛa{÷j‡lT)í`|±;™!^­’Ül›Ç œ˜ Nà °E‰É¦2lø†»|bµ•#;Ž^¬à¢Ö²HJÛ<“¹7)Ý|È …l)Y%é¥7穼¡£„R´ Ï@HÅ‚­Ï ²-? s(aË­3âi`¤sYû¹K¶^èËfeuªð9ÐÃîíli„ÏH<½^ÙrÄMˆuIÜ¥Ôºçn^aÃÔÝö¶<­ 'kªzÉV‰ ±¡{lfÙ–‚ÇlHú™ó!Ȫ*Áá¥ú 6UYkÛf€1æ/`£÷ÐC—bÞØÉhš¿rY h° ÐT3g€+èÛR†ÄlÉl x+Ì@Ù['¿vgKcmøpíRⲚ•Úš:{·-‹TNÜœ0ÕhÔm—š>M+Ù”áÖUåöù)_“ü›@Jä¶r Œ$n¥Çt‡}ÉÀJñ±%v!¢NK_j'¢Q[kµ™7d­5=¯².‘Íf¶ &+bê‚·íÔRž”a"g‚‡·u²@å001ÞJà ®-rØ–¡¬hkiu4L ç²ms‹ŸRƶ5‚)û׿þÕÙPöÒ Qeïh)YB3¯¯­ï;zL¦zHw xäÀ³Ò{ߪ`̺*¯Äj+€ZÐØ¶mKà»Û¶C¥gŽü1ºßzN‡ghí‚È̃ 󔲿P +Êâ4d€.*YY«ìéý­ÝHôRVÃD§Ì§Æ6¦ÆëÇloKl|ÓjR)~t)ÑH–¹ª¶É0ñͰÃÚ >Vúœ»Ž£u]¬ø”Yqîïüjä3/vù kýÚæ0C-àšÂ²ªšÜõ•ªccì"» JÇo~½”clÓ˜O+²ú5¤V&ÖfS«iÉ„f‚ŽV–ÒÖ*0E]âà v@°êhøp)&€PKÀ´fh[è¹l`…] uVH>ÖLºX[å9dÛÝRÚ¢?k±2d¶R¬ˆ{vÜè½ÕÌ{+0”u)Ûc"ÐS£0Û ñ¢É•ó”¢Qc¦{kKß`)¯ê|íT‹ìõÔ–­Ð–&YÀŠÉ ÿZÜÌçÁ0ŒœÝH¶æ<êûÔú˜Ã «2hž=޵N¿#÷¹¥×Âê†rà6^UV¼*k]Ò(ÁˆNÑHÜTYY—ˆÉ[-ʬ0x8À-Ý l…i8l*â¦ÍÖÊ¡Ç$µP›yþd¯¶Ý†«nk-˜TÞÚHÙ ð$ð}§1ôª1†ÈæC©3ᣰ_9ÆÌ™ÀÄBJDæ#%Ü@<Ü0ùP&VËߪÊõY6­©²ZM&ÌSæ4¾­+Ô ëb¡E2p9š!@²©2lMsƺ7@ E7ƒQû–$Àƪª…m¯=ÙȺÛÕê"\E&0°Lˆ‘UÈnlK¶õrÉÕ*¬iYU¶V…ãa2‚@¸mk]𬬘ÿ¦ÂR/™ÕK`'Ji%˜¿#Õá·Š!På}è¶ñ~Ýo KÅ÷€ˆ‘ùŲ׃ ÊMbû£i×¢J˜Äš€6€Àˆ_OÔä¥ræ– Æ ÝEVX¶ÖÊoòs{p&U%^á™ã^ÎøFfR_ÛÛöüxž)2QRpHÓJ,à7ªrÛÄÝ @öÛ?ÿùÏ&èÙB¥9¬”µ†ÁV«àSW2…xd…§D6l5w¢ïÊL¬¿‚>~Í]¡Õ¨œî<ܶû„hÊP îÝ’Õ”ÌW^ÿ¨·ÃòÌÈÊ p2åÂ*ªd…FlÅ9Ã÷ K6™ÌjëÜhbæ@/ðºÌ¡òkÿ?O$ þÌtéWÂ\(ÌñÞÌV·¡p+N*MM=—Y¶³I‘Õ]ªÈÓzÆý^E½æÐøx׺Ø L ie[¹UÊŸ ºâªêk+jÝäõ¢ÝørRŠßê¥ÂXÔ`šâ»óì iÇ^÷fØŠ§@Ýö–v|$qk²g+e•% dÓRf‹ÂÄd1d]c)¤,ìt44f-²Å:â7Me9ó‘íš'†Œ Ç”ÏLF }Ý•ˆ‰)•cM9Ò!V+Èê|@GUáÄVJ­‘²­M‚/e•ʦI_­U Ky|ZˆÜnÛJ,Â#ÏèÏ÷g²üñd½µ³MˆO ¯«3MŸÛRÜw´s5â°Qá¦:¾÷¼|Ü3s…˜ cÆ0‰ñ"ñô¤ÂÄ:ާof2$€Ç÷ëÜéz ㌅€C_û^0'fH¶¾pLµAö4þ^‚϶›Mwæf–¬Ym  ]—Vb !{çúüQ­ Yéζo•î³ g…Q˰Ÿ>x¤Ã&`Ò£©°cžẩiœBÀƒÙÖ΢)ÚR–j-‹$Àt]¥24*@@ Ke޹ƒœ¥ã”Ez%HXÐtQúÊÕ Ùe›ÕNÊŠ€Ižpç­‘ms2r‹¡GN–ÏH¼ ¯ èb]TVˆäÖï %Act¨ú6ƒu¡¥­9a«`H¬û+¦9óÝËT‚‡&‰§Á·bàã~ýmcd ÛÒ$ŽŒ¿¥¿¥²je‚±*4v[Xà­¥Úb ¤àïÆ7Öû#[S7ÌÍ®°Go+`U%.“ÞHÀ²iÈD!ƒ¥<2µÇî;¤ÂpG»™3¿˜³W”Æ´0 Ò–‰-™còÛí÷Ÿ‰‘‰³U^÷|ࣩ{]ˆmcVØ&a‹Ü0™X5UÛçœ÷s¾ÀËjdU+ÒÇ4pkd¶Ý9ЄºTÞ ­ôÜŒg+KC¬¤ŽcöA¦qºRZµyðÉæA š˜s†oß6·Z[ ˜h”ˆ[úû; —ŸÖ•T¥}¥ÌOÖƒ`’ ! —êP¶š YÌ0•¼Ÿæœ†­*zŸ3~>ªÂ <}Ùôã¥6¹Ž¢³ã•ÛrŽ9-¿ï?F ŸF ›A¨¢Lp‹Îwe+[%4Õ¦”ê¸me9©¦¬rÀŠi’dùgNÐH„€¿ Ñ)h8ˆ 1Lå¿F‘Gý}±Y5†U\ËÏ› ëé¼¶ÝIåAžÆ)l«"ðf"é™4UÃ`lÏÓõR!ßõú)ŸR^JHÁ[J’Y+ÇY!F(oM g’y[kÀN±S;ÚR«LÔ¶Ýl/"ˆYSàG•m·—F/á—.[@V˜žŒ³¬ #µ é Á“ÕÚ 2o‘G UžTRaÛâ¸|ÙkÝ3‘íÁéV¨ï)»_¶ù'°ÕE4* ÆÌW~Þ |k-¸ %˜E÷@Pmü5>GXà3$ƒñé[Ýr*kµÕÂy)ûÛßþfŽ:a[O«k³ÞŠa2gU"È€µq=$l½’“Ò;œR#Y훡ì«ì!Ñp S"ËœF0o¡-¾ {?¬J² X ([¥š„¼ªœa$,L²R#«a¤š  €,g%VLb˜^Øvv@¤¿¥Ÿ»/%+rÓ(ëœËV^G")L¸Z²l•;Ž0O2)OЩb¤(ï ™ÐkíEòó²â1ZÍ€·âVU¢-M˜{.ëÕ<;~ôé@ ˜UžÖ> m{¬Ý¡QÉ Ã_HYÉîîóN ͬi )‚hN#IÁ=Sþ²4Ê‘éýþ” ¯)½y(3¯#²[RR¾YݪðÀpÙNŠ”…E@•î €4çMž,¬VJU¤­îÖ5í ”ýpQ••cºv2‚ª0LXõh2‘e˜LVyccAFÃ3Æ– ^Uæ”ÕêBÜ•ú~6Øæ©Y× 4ªf˜¹-O£nÂÞ"%€õ9gÖ;-+€I·§4<[milclÚb¦aÒ©¥Dœ‹Æ¶Vx·“±Â[•gk¶Í“¿+Böì¤8(Q›yU[¢Z}…c*Y ‚F•‚)›Á–fdãaúè50rúj1”eb[I†:êRÀ¢G£¤q”Rdؾ†QÓas’U $½mL“ {©zèºxCˆiô¥©¾u‡tç|ð˜l…Ä¢Ú¥b¬Jo3´m=•ßë"h€­#ð”Õºv)K²|\°†±,7#ൖm;5Ü–Ì+(!ø´]vU@šÈ1@ú2€g÷©—Ù<‚Ïoº4b¤2`^Ú”ÊÎÚgÞ=ï•Øj“ݬ+#N`ÕÅ*4)šX‰‚ƒZ}*@ ±DÖ:AæÊ;|¤öÿû_2[Á žUÛR=*Yå˜3Ç Ø0èa2šÆ6¿4ä€CPžç0ßÇL&Es+ÎÒöõAÚâ µó ŒÈ f^íþøÇ?úÞoB…ÄYaDUV¡ # ÏãA4RSU>¦-Mæ.‡LëUÒ©Æm³µõ7ñzÁj)ûµ%ëb¹lkQ/¼0F$Cµ}›Pš 6*\Çü‘RJv¶@ÇI\ Þª žy7` w„º#p@U@-жÂWÐl9›gƒuð P ™è¤ s+±*)[á~hL­óÙ‹-¥ŠF6}Êu¡i8§g ¨ªogÁˆ ñ|D¯_þ¥jDÙZž= }žÆã@ÙÙüÌói¤‘!á4¶ÍÍZŠÃü)AÕžB>­H%¬ÚªbØ#l‘@S…oæ³`D3 V[¡T7i/aí\’¡³WK¬¶á·‚2@£œ§åU€$sLÎù(¡§Ì)ú:ê6t—"0•×K¢Y—nŒ­B¯œ'Àà‹Óà{|>ùWÞ¨H‚ø0+­37†­ a¨¤* q‘Â0y™ÓøÞC©[z–x3à…U©íº²Š§YS2…dî6!,ÔNF쪵ðSæz~ôrv½‰™HM©œ[i« ¡—‚…LÙ)lÏ‘¾‡B&ˆ™XבƒIªmì:’™ÁØRj¥ ½F•5+¤* [ .^vG0',È ™P6*Pà7•¾¶ ;©vÊ+¼~ç…±RÝŒ!iê˜Xðþø;K— ’‰ámUÁRÄ<¥šÁ=°²!¨#1¥-~“T^;2[‘-œy©Ê—ÝÑ´3ª³©’ÀñºOü-ÄØŠweþ[KÝHc´ëÕY-+W/tl ÿZSbîhç/6`Ç&&ÌÙ=­ à±aIIŒ•ò¾MlUˆ˜E¤0Rµ³fR [2k ˆmÅj“aš°”ìË·m|ctv'²åIcAÖ»+» $MVALƒ”‚Ýó‰!nžôVŒh’À¥*+YgadôŽMOl)ÊÛçóã‡>g­eξڪ݄Š  4'Ü-uF²¢FßÝçcl«ÜZ MåÖŽÓam…aŠÄáš’!•LÀׂŒ>S-o[m“°šÏ dÑa{çÝ$2ÃÆèb‘3‡9 @£¥„Ù§À¶Yµbˆó®+™ÂÊâeme Ìéw_<ë; A¶x Z|²½«ÉºíÆ8Ž×2q?o(ñYMÙxÉJYÅ-ý܃*þoíë_mߊì®…imÙzÆðÅ’?¼ržiÈòi«¼yˆÃM’ƒ”ÈG•v> ÉlÅÄd²”l×4“.ÓÅõ;À”é™\³óC¥vx¤r<Œ´M_­#(5åªa0‚ Szd<Íig¾;•”*Êæ—ÖȰU*Ã&™)˜hTªËI?7[&R‚²ÆPåžøt4­”²‘•X¥ð= ›²’uzÜ/‡º¨ÂÔh)& 6O#mfJ­m«…¦¦^¿·UR_Já6¬xQ/YበÃ\Õ¸1Œîdx)$-l­˜ÖN1熷ŇڽŒÚNGèaYw4“ØæßÌZ³‚‘rˆ·2'x[äÓ¨Dl».ð¶Íï*â­™ãù‹:ºp3ÀJˆ½3Ö<)~ÃàE†Jd­m¶½ÞçÒ1óz1I\aU½¢ØšÇV-™PEyæøþf³,@Ÿ Gºs¯47çb©çPw¯J3pˇպïD<š²R¦Ï‚ì 2%ÐÑ„ÂÖ0ÕªÚ¯v4ŸRÔ é©q&°å Ô+MYóÄÓ4Û;¡ò™R‚2²,,F¶M¹U ÓJaªj$«Ftv€ìlûÀ òÝ™åXªõ8}¿Ù˜ÈjÖë›rÇÜ2q3iqG˜nX°"ËéZé½yâmý¤Ì<Ù;¾. J)¡ä6[@¤éª5òþˆ=c¯‚•²Ç¿Y3H9/l¼ÌÕê®sÉò¶²˜¶»Jqæx~xL™ŒÃ¡mÊ[ñYêÛnÐÎ<°ñn«³˜*͆±eΡ“º€rM÷NÙWó±jD`NÛR•óÁ0̤ûɼk!«„`çʧ7I³ò‘I#!eÍ_SY…<«~°m* ™‡t©Üš§!‘QŠ¡”'ÎPÈ\¶iéõ³¦Ä+”ªª”‹Ê­d|`+,=Òj[­Že+ÌŠsæ¶™4'*)¤”BåRW¶—Öù¯¼7cm`$† êÕ´x#¶ª*ª2ÌôM. X¯åy¯Ty ÖþC–žØ FÓ‘)sf[Ùa#›GáÆƒµ DØR2ÄlH- )|Y¶°¶² «…6Ìv>ô9´–ÍÐãèŸŒÙæ¡r-¬¯P5ÿeÛ2y}déýûEÖÊ•¸:Ç' ;Î5û¼öæÉ!ÒZ¡µã5µ²Jlf>µïæ{Ólµ“êÆ¼fø_3[•7O@  ŽýŠÌDwQkÙBO,ÂzíÈmáºXWÞ ×û,/OV Ûž…­I6}pŸGbµx ²9#´ï8ÉbœCflŒ:Žª3è½1Øzè ^­Àì°R¬²ïTRlU)ÛJZ‘•÷ûƒÛ`::>ÃH€™g}KYñ<z)(W‚CÐ'}£‘ÆÛÓ”²ŽwR[AƒÔÅ k-lMeC‚GsPøÛ_þòÒÏæûûoƒÕÜüçÉ1µå‹wrîâ<ç;¨,^Ô%[o›ÁPx?”çi%vß ÌĉÉ!¾9¥o!Я/{uéqúùgJµðoŒLÂÍÐmÖBG‰tÀ™YL¤«"ÌH KÙªJsïìxÕÚxIJRiªmUp1Jºö&Á§É¦-Œl-`7æPÇèþ£€¾Ó ÍCCÙ`WøiÚlÄ…­’ªš #Úâ{µÃàU]ùé"Ús CR"9XÕ¾“PÖ¨¬Ôé÷ýЬi§s.Ýk—&OB¶¢±Ý0P":7íl×Z¡W ßÖœÉÜYšX‘ñlçYO£p[í2Ï-¾á›<••5ÿHŒî!½ƒ›Vª1à®H ’‹7Õd˜Æ0À‘Þ( *FÀ;,ÿ®Èj0ƒ™*Ÿ[÷ùšƒñÕö¼:]¶)™çÃV6q'…¥:¬¬*„­ ©yv9e;ì;R%²âéù£ S¤T%ZUŰÔZ7¤±}7rH)umÎ;°*©6YL˜>ЪeSé‚$®]k-4º+¯]?ÑU‘±BжÖRJ¡”Ú‚Eþ€¨‹'(Eé}ëë:·Âp1°PÛ_˹Ÿjó´ê+KÃP(/0M+‹±Ê¦¬Ì §Ç_óhªšçVH#k«Àf©fH0“~åà\d½Õîçœáþ(ÙT=>¶4Ü<&ŒQ¦á TH³̃vÏn[îPÄ]&À¯oÛ"1­@¶•€§Zú0YJk—@\ú|—Âôý‰d¥|-¶Ö˜jiÔZ^¤±¥lE–5scÓTÅDʰ6êÈëw^é¬rVè&iŒJ ¤±% d›g™[|Ûª¸¹2µÖ¦Ef剸ù­¢Fdü…1Tô•HålÅg…tºfJÕkM•Çèr¬ï¹dUù]\‰aŒÊpg§_I³Õú úý@¯C¯Æ:Z2Ñe/@¼öjñÄ4 RZßFÃ+¨uÝ•k-…/˜ž²;4‰r‡uÒÝj>}F¸Ýç}ÃwK”0s©¬0ÉZÙ:oâf Nwfºa´"ÒÏä&?°U6¬]a«ªBø6ùüvñ’R’@! 4¥'3Õù?k”ضZ*°·n¸èÆ÷tƸÖR¬ÊvNY7eÅX½]=\w«,†•*%ôÆ ï­þþ±™Fªvֆʧ.{NÙ~^ÊȬFšÎMªiv´<­d^)|)%ü­Óã`V‚ߥ%S ë^U[ë Ú2:”’ÆFvÕŽ&ë°MeeNÐ8iX;z)²>*R°¨µù»OS¶îŸ «R}³À˜FÍg%ui&R¬þɩ֜¢ªuTÕØVdÀ‹ÄîCA`+ex@ä‰1†5 šÓ*åúTYÄŸŒÛ ‰ÎžsÛøæ±vœª¤Òg˜r+@–&Ã6M}ó$0ŒÔ!€1ysšPXmçJo-øÀ¹)!n[SUód×ì÷¿CB¦WBf­W¶VŒÏ~Ÿ>O!+¤P+º·ª"kÑäôO&–’x†‰µZÓî)ãéUæ«8§ gŽ0Ú*¼Í?¿G6Oš­ÕþX9Äh(Ü‹$5þõj*©F’‚Õ6gng"U¡­³+Ù骺y+ìW·“M™§^‘ξvHUÆ †ïTp)>Ä^ELg™Œ¡lO“U[ +ó[ßTå4ZT…ÔEUÏ=Y#uc tW±gjM™­UsŒgM3>+‚|l Љhj  ÓU4*ž):>[ C2$FwúRÎŽ¬5’,¥Fn›a©È!,K ÈH…Úªò±5³’=n%‰cÂÖ¬”ô›_n¶x‘­-P£r`ŽÄX•P·â”äl•9TbBL(«À€+™vmufEV—µ8mî;ŒôNÚv‡µ ©ГÊ_ÖU`8Ãù[1#ŒK6ŒÁ0L ¯ËÍŸ#äO #­ª ³F@ƒá UÄö°{ Ý!&ÿ¬à‚“¶1ÍÐU4?’Ø` ‘Vótçðþ6–† szAÓYjZööù<}!¿C+¬Öj˜V…&éCÑTzIái00[&Él;††¯)>¦¬Ê¥¬°¥˜/**·þÿƒþÖÅTü‹ª6€æíe¹^MeÛ[zþ "…´ãåB„,km‹ c—b «ª±U¯±Í0+%1¶²]WÁ‡!œ€¦I’ñxJUþô€-ÞûdK >¢rg†e=àYåFPSkóUÞ«ÐétTޤ•YÙò¯ cÛ`@Th&ëýƒÉRò¤ë~šÝ.†íuú< ðVš&1sÊ®—v¶yê‰ñ86s½Ô®Py†iê¦άßËa¥¶cê(`1¦«Øx[¼,>A¤Ú¶¬U_Cfæ¾³œË ÐHq°µV…äã~¡)a++à FRö%žÓ‡ª™ÉЩïŸ5537¡Ä$  CM›¿”ìâ}ªh6¥µ*·*Ñ:[8OÝiÝã­dý"ÎA9A-j ÷•²9›!¥”í>eµ*¤€¹åc/^Ê ­)‰[Y˜L‰Gf¶ Ù0±èÔ¶Ä֜ÜžÌšÉæ H¹¢|è3Ÿ2CÊÛ|(ÃøÄ[³µbÂÕZ‹zI±CÌpµ€TLb[µn»¯Áü[7vUȘ^x[Ž,`—Ì ‰šôâ‡ÆÜ¼.AÌ6Yæ1H-¬” ÚÒþÊâzq`Ni€˜†¯1æGH¥tɼÙ(ùx ¦­²@¡¯FÖ̇«¥i°`L†V1ç…“ëªi|Üü¥†5Oh<…Ý!‡zá…Id•»ùnIyº>ÏËØÈND ¿“àçÙ±enÊRÍœ²ÓÁB—d •4CgŒw@A†ÌJlUbxUx±‡‚_ µ‡»Sœã]ÏV²4R ñ¹a¤´CZ'𦜠©ˆ&ƒE'bî%æ„ñdF¥LïNlõe+ðÃc&æ)â‡s£·óyð‘m­•’åcí¼Fv Ø„]Ü6ÛÓïvDæ ¸«œ¥4MPw¸§ã÷Ì{‰•ü(ôøÓs¶æ†1Õz²*&°Ûfh[k2‚&×ÈéeRud’TÃhm±’4JôŘ¡/©&ñ4Ožé­:æ¼+Jex&øÞvUVÌf¦d.š¤S›¥Z åÌ‘µN†ì…ç±ÒÐ;²CÁÄJȘÛv“Qæ“gþ²x«ªµ¶¥!H·åi%scVz²¹QV®vAÓU§¤i6kÝWKY6“­5bˆi*q4[XȺžV[d .Ìƪ ¦t.[¼h«¸ªS’øX|ßÒª¶=ŠøÀ¾ \ZƒÉð¶Zû¸!)7¾R áÍ–@оw¼*üz5¿*€ŒXyYk“äP¥ ”Å#…­Õ€5 Ô‘IÎJ¤0{m}¦€šV›!†‰h«P+æ´P‚§)T‰4½uÄdÈÚà×§Ù÷¥å91‡|bdk¼Ú˜ž·f¶mT)2¼nò~èЯµù)‰Œ$•›UÈ*ÑÅ*Õµw0ÀŸ,²FÂtÌŽÞÑrSr|efþÊyԈƖ¦Z|ã‘ͳùi(é{:”‚‰•RjúÓò;pcgÀ49ç •sV>/€aŒs%vÿÊr( ³-볓§¬F àŒøýj²Þgíj Ð×7O³¹d…U"1ÍÓJŒ”µÉs¶ugŽÉ¤F1Jªµ½çíš !9,UÖFª])È$ÍiäFR"˜ÄKÁ‚À*ãen<>yb ÀY!gâf¶mÚôÇë‰jßõöÿÌ0^¡U#oCí¤üéÚ¶¥”adá~âø0VÛj·Á–2†‰iy"­ÊÞ6A`+µ¶B-€Õž¡ïw掌œÆH”µ3!œUdnùÄ«±®~å¿ýë_ÿbÊÑÜD;éxÀdÇéžfa ¼_elU)éâhÒ×µ!Kí~a%j‰)»Ä[¤OC2©¼¹¹¥šœmÖÏŠI ndjñÈ4ÿûßÈ^ ˆûu­¬Âº[ÔRK)‘Õ=º"d3h-f¥–"(e}•x‘>¼ò ‰E$†¦ ö=Y“¤tØ#¨cŽt?ôHXVäÜø&²ý:‹„™à)™XLŸÆúƒoZ¤Ï›l“#ù4«ø†±æ`%+Õ3U[ÐüU5^7@£¼^ká–‰PšyßÚ¶}3r€ñ”ò¶ÖRx2åý:«µ?mJÑ´*¿Eçi«ow(‹/" ˜°µ²)¤ŒQ¸Úæ‘ŘœF-ìÏîM®rµÍ–s} V•-^‰­©`«rYØ*YY/¤ZUé­R®K9>€XpdøR¶ÕÒ©x[µe™ÃÎ+8Øf(Û™ƒdE…øÜ0@[ø ôÓï;@U1#Öãû¿´)ñjYú+ð4&‘ÅT^·1@%F’ònlT©eû„Úv:+eÛÊûÔËýp èbeÉ87U?7R|×[ß¹%æol27Ð'´’®Å©·JÖÖªg˜'P‹ïÆãÜUpS¸*âL8[n%0©fž’gz+k̪â‘em»+çòU€/|yÒà1ÊaÀœôk÷x]ª¥,Ô*VÓ ea|Œr-,A†€Ìêƒc¶~ØX¡,q&ùØò)[ªrw®#f¶õ"Æ#•ÃV1C¼L‚V[dnecdEnºF)ï&‘Ó§$&ˆ‡RME,¶ÇúH⢙aí&k2­}wMÀ;» QB)”·b¤„¦¹^ÈoÿóŸø‘ „“…­ºð$ Ö§ÀºïCz©îJ»ýV©°›Ä;ÈÛ²ü‰á3â }‘ ž's,ðÏbC¦‘Å[Ûò•™()´LBЭ¶xÝ+D*üôó¿t=Ï¿}ED!—ELv­ÆšõŽÝX=T)ÍÔ <ŸZÚÂRd )d'}x`‚`‘CVï„YÌëÀD H¶vM‚ôü˜ÛêÞ<ž‡¯]d&•KywûW·)¥Ô @Ц·aæRH툯ð,¨Â{Õª…». B@”²²ÂÓÃ"OL(âd«Ò”†ž-àbó™R¹»öÖ|d)mëòc¼p‡Úùc47€ÒÍà9ÜüYàMïÒlƒ&²WKV mMŸŸÎU‰¦‘ù# [ ²UÕS…Ü¿`Ð=tÒR”‚ƒ¾çwÔR˜¦rcJ™#0$³µÂ€ÁzVæÙ[W_ 1e>ðšÂjÉ« ¡äÖöLvÖoÄ xN#Ei•²JÙÆ¤Á4Ï»:NwR‰õ>ŸóÚ§W›!+ La½LÊßA/ÖÅ–ƒ À¦éš'x-òoE&„rch*\{æz:ðIIoÕ±B€¹¨µõ0Áiv#e«.qŒm>‘逸®Çùr0@ßÌ)û±äf³*¬µPÕÀemKÉa©ÄÌóô†“ÆA«x©Þs@IüºÓ¸Æ4陥·bj§ˆOl 4I_þ¶Zd‚o$©L<>dæY­¼£ÕH‹ºX ¾“*7|2<Û–rð•Ø¾q¿¡\ß{uÑÄHn‡”…­‰¥2“Àî­kDbœÚ³–vp)+’ ·ñ·m`€ †­lÛÚá#9ôšÂd.FJacÛñVXT‰SvÁª­JGYëBG¸ç5&±Z 2±­‹S×± «­#Aa‹Ï æcåŽÏ?+<·Ye¢ c`J%4x+ Ðý.AàsX!Fp¨°#ÈÚ"]rVV[«H©‹Pk»©#d­1ªDä[EŒ§ß05ÂôE7+ <Ÿ€ñ¶ªe˜â:Êz4]TuºÞO¯œFÊ*´æX}}ùJWHÆ_ôûô™æÆò!¬áÆø±Œ [ ¼ZakÍÖc63pn¼.’ õT~¿©hˆýŸ¨ö^uvþxæ¹1Ú6@°Z¶ÄVA©E‡šOùf ªµ’ÙªlE&˜f›O#ÉŽ [«ÂÓX&>ÿ3 rö¡Vp&½³žnß[¦ºfW{.m™‚¦*©ÂYoLßzÊ‹üa‚.7+gÙ¶ÙšŠÒ*«×[Ep†þ¦Êrp. rV«IðÞ?Ê‚cï¨*”F ±áéñ&Q%|¬xƒá7žBJ…f è\HJßšsX9±¥x X¹ØF¦×ˆ!(ÅYy¼nPN_ª¯‰9T¨„‰øÖ}Þ¿¬œZ­Påê”àM“Ã[ˆGnb·-øôËMïŸ É*´"ß›Ç8š d"êžRÔ. +¼¶Õú3€òn£c Œk!îtJ: A@ ÖâÜѽm[2`°¾YYu„|”OÐHwŠÖ¬déðš£îÖ²› È$Yçêh¥Œ$jM€4C&ñ°0|ƒ¥¡ç [à eä¶›¶Â¦®ÄÊ\ <‡×Üëa Ù3Ä=Zþ4ªŒj+‘›‘<РʑĶQ-¦F:ö ™”¾LêKf"2?3ÝXª1ÊZSþª?ßo9 }-#CÞ²ñéó÷¥œ¥î@ÈVyg¬{Œ³ø¸a:8°¥tFÛÛªWÌ®ÅO\pKÏ“UwØœÖ^ìD 9P" ”_áç'%^–›D¦„ØHV²Ì­¢) dN°U¡.Äp<±Ëi`kH‰¬0‘méc€7Ê1 ÇOiZd>9oN@ •{p~«€k3=5có!¶:H]•çÏD(AöA†1¶u·ªµ"­¬tqe‘|ˆEÏAŒ_V )Õå³][äú¦´5R-4 ì€V¡ÐŠgK)òl Ù&¡ÙÁ7ϯ€F!7…Ph†ÎË£Ê ÔÑHšBʶףyl‡yö’÷¼jô­>›Ò =¾Ì#›„?Fk,;Ÿ4øMµP &Á×òóãiàJ¤”ˆs/—¬d…M†«ªá_;fØ Âd°ª^6L2¤ût{²"™lµV¡£už—;³Ñ¯ðVŸ¥v¿ò ²‚WÐÑ$à™þª×J§7dÏWw[PÛT@O-[¿NXÓÐW…m)‹¥ðÜD2|/Y>f£ –U&Èj[»@)ÛpÓ8”ìN¡|MÏà4¹¡¬ö*p½a©ÜK¹ zÈ6+=ÀZ o­1ìUP¸ßÅg(…§Ä‚>?ãgOæ˜  V(á`²”Hb+Òð>“ i:©”HÃk°*ñ³_mÑ„ ¿Äy®JŠj~Òt"$1’[ÎLœ ¬µ­3Õ0A¬Ð*”Àªâ‘™ž˜ ß«œ¡R•ÖŽQe‘Oþ¶Lj”8\ŠI…]5##×77[)] x¤šÄ³~çϳ^ÙNpˆhšsæïTÄëbŒM‚§7§Ë×vù²pnÅZôé Ûf@*±r·ÛçÎ)1¬nòó@[™[ 1ÀÖJ ˆªòŒÜY"Wòj¶éaaþ ¦³×#êåò;‹P‰!E“”bbæß ¶½€à‰Ï?¦m>˜UÕ´•³!¥zLjáf˜Þ„dz1)e Ø2Tuó>VžRÖ¶˜!ýº»1©†´ÂúfÈ o’w°HëÀ«ÑÎV9 ˜”M<)ø\ú÷¶'êÞl°8½÷u'RÍA²4jrYÛ.AÖÑ™ø~Þñ|xvQñ̹±Uާá`‹D7!½ n6€C)Ócµåi*+.ȘÊù2Ñ`­g‚{^¼0§ÚžxsZñ´Ë~ÊZL–ÏY•íb¤¦ÄUòÃÁ¶T§àFfe›3Êݳ )µ¾²¢­&à\÷ž gÇ!p-dµ ç`+º<²sM I/K<¼Ù6öëã­Ê f$ú›Éli0ž—vy:x…ÖÛ$"•óO/«DÙ^'LïgÊÊ †ƒŠo0)Câ‘Mΰ¥˜ bJ+FS[iüþP9FU%ð-=““…‘ãl¥Z)ù7¡± ­§òë©D#UJÂÖÑ‘1+YjLYó4¢L,Uhİ[ê ÿ6¥'hb_/kþ³Z—<5 lž”› xcå#W˜5MÎÜ(1Ý’[%ò¾9xÊÞ¹C£œÞÚ¹”Ì?Ïü÷dÃ5•%³êÈ`kM–† `m¼¶|„BA£PûŠa Y]²B§Tbë\N—ùù_’“ 긵Qì"œ“.©J))ëß÷°bâË– Fä@?C-¼(Ú $+…6œ”­ù"ÉTqë1À5ê“V¯<+׎ƒU(AöiÌGGÁ¤£y7€4>´ªdmùÔP…yI¸ZÙÎBÀ¤,Űã49+ŒgÐHÇô &”5u É6|òfƒS aP…ì›Mß&DÖÝyŽL/²µ íCzVm­0¥µp]4.³¾°±á­dZxXV…xæ­·ÏYh"ùKY]šµ7Xd•Oúf€¬»ÐÅÊÇäñù·b¦4"ˆ kÔ9¤D|cœ~·c>œñBùzl­&®©-°J8Xa“èXã%YmU”‚€¥ÀS L|S¥·üa%‰=/NG¤,œQ¹iñ&¶µ þº#™«ŠA2!Xë@…é“)ÄœcÜÀ$&DtOФ­o£ÄdHåYѶEÎF5Éù(”r½”ȵ®é¾£È˜+QKYUž¶‘Ûb`ë ÂiʆYå¦5 «7k+ëYÈÖÅé+GÆDÂÉ2‰do ³bˆ×ÁéΩÃd‚Œ›[BÚÒsPb+à½'e ˜[†¶=ÜjËÐ6†CžÈœç£µÖÒÔO/e6¶ « à ôš6Ãêªò\6Ÿf怷"E$æŒûý/Û6žÌ9£¯m-€†¤¬Ešºh”g[X6ù•»gUOÆ\Š2OkUãU)iHÊ΂¬Ä*[•79·ZTnÅ àGm³ÉVØHðΕCíz¬;KŸAµBC6°­ÀsðàªB6I¶0fê+b€*_æÕ…?’¦¬!µ`®)`¥ÈˆsCR"MïJþ²€Uh0@C“ÆHÀÓæ0«ªYëd)aÎVšÀ4H¸µîJ»kÙ`.<Ó4‰ÚƯT?Ý( JVu!Óe|)úx+½^•˜!½m)²¶Çå¤ñ`3w½¶Æ€U¹„}@eνç¿¿‘'nø0^4aðÀ²gúïŸ<[e¬:ªrÄ‘‰'jЧ´v€à LÕ眎j•ëù5¥•Q(j`íåædªVtAzl>bÓóç[›ø5ìèÏÍ)­ šÌ–F¹¿$ÆÃ Võ’2F¤ãÀ~–WBÃÄ-0!­\I¤ï‹RÖªˆ;2ÿ˜F²N#¾y”»jÊ>+±l«Ù`‘ad+>óp𲔑€#[õíi–²$câ ñÝ€³uÞóšÜä ¬w¢ß¿gëÛVVyR ¸Å¤ÔÓmôûV2+Á©¹…UØâaUH+fKõ2gíºXvX Ü%ÀÄ<Å4|]z8cv˜8í¼Rªº«3÷/ž,ÖÂ6Y§PÛÖ*Å<ÒcmŒB³™¤áÓ$ :ŸI¨Ýpþ²&qX»å² è 2sæÖmà›ÙÊAJÐHó¤d…¤çl}I%”» 2[¯ sF¹Ñ£©/bíèmµËˆ™ ž îÇýû{mæþ¾Gª?ì™ –³òÐG°pW½xls¦áÙÖª¶s‚Ûíy†Žo{éÏO‚[ñùXUÎ`Œé¿˜g…Q%0'CŒµk—¬HTˆ!èàü+W+eK¹¦Jˆ»:€’€l% 1ÕÂE%ÄmkTG©HU¦‚1ÂÖsç㌥èeil̓·%°Ú*akÛ1i0J¤àÕ6ØipûÚ6•íæñGq.¶0mßµy¤j×+å¶RgÃŒ‘¥±U˜e¿†aü¦ þ iõV59cí^"qcQòZªìñ¶4Ý—*Vd™ã9ÀΉ¡±ÖZ-A†˜ü1F¢ÉßvÐ(÷äd{¢R ˜(·5LV ­‘Ý8 ¥ÐVU37˜T ²"ÃóQEŸ³ª¶4ºÀš&Ð=ÌMyóì\ùƒ’ô•ðÁB¡íÛ±Û /eÛ¹hŒ—Å·2y ›sžmÓÐÛ*¬vU /%`-(ݧ£^³ÝuqNãf(m¥Ì‰$Æà$7¼R“™) ¤· l…+Éšž!’¸Il›\¯ìïû­DÉŠ &C@ag—àP l$8U¬l+d÷ŒWh˜ W$“2¼«h`«’|ܧ³“a¬5’r!¥Ð6}ãu®9”u4¼`ÈGÕ“­Ö9÷ ñ¬¶Lên»Ð"ü£;¥¨¯ŽZÌ­xA`|/anÄd0 ½9a °óJaŽ× ˜þeª"+ø¨õ'«.¹¬v®Ñ õBrhNUŒcȬ+’ 7ÀZ@²ò¢Æ[U‰ cÞeJ±‚e‘¢^¶É04­9òHã @/â&)k‹„87¥°E²*Ò¤'ÓËšI#I•µUÇ[±ï½be[ +©SŠr[˜†gú5b_;zŒ°+¾ñô¬Ò$k›ÒÀ²U‘ ©c}¿`]#F)l›Óµ8TÙNGÃß³‚¯ÙYÖ(M)dÏŽI|Qaæ=â0b)@Š,fY Ÿ‰myn­F4˜T-0r:ú¾‚SF+³ÚV¯@oX¿”y9^ÖV¸µ¢DšùtÝÁ–$H­¤áE½,§†Ã»sØÎçþGXùM-„¹Éd’{DfU7Ì™±Ÿ=˜ ¥’c³Jÿ[bímÂ,èÅ[m7¥Ü¦ä™^‰ƒ¬ñ ÎuQŠ3àú؇^¶-^  Än9ߎ3šÓ‘ÞZ8Ô‚Ñ(;¶‰?t­Åˆ°j$ÆC–lÌD)ðB r¼F†ÆôdŽÈ”ŽÙöòÈHb…‰ñ@½™Ð`RT)1’g&]ùp¤{ ³d€Ü¶¬´ ì­)Ý‹†^‹‰ Žîû—¡wÃa]íƒÔ<å¢m›²uÔÐÍRò0q¶5fçÀ³ß÷×(+|GYc¿J²Uå07í°âZ~zÃ-ÜŸMzü˜îNÜe¹m:&O¹=D@VÕ;×›'Öe[᣼óÏS´dþéÓô)÷9·O&|ŠLÚ£½Yx ,hd{–¸kÜâ畈5¶A5¶F5CšÝ× „Ó÷ÝK@Œfaø``V޹Eë•1ºÚ p„õËc^1gñn…4Ôt¤Ç™‡¦ÐML€!–íÉ¡q)g+ÓóGÂÄ01,¦ÏSFô&Æ vúmÕÄx Û”|\G¶6C˜†¿¾Ã@V²ªß”‚‰#V™;Ò`û…ã¾Æ~¾È´h”J}”Gí¢j Û@Ë·ùpzÙÄÛ‡(æ†$ÛñüñH›Ð÷…÷Åû) [UAËíC<ñáŽLÓeŽr«®´.·PÕÈ-òÞl[>l=€^SÆÜD¥dÍ…qËÐ;†oå$킆CÏÞßZz(<ÛÞpħ‡œ²G€…J™oÐÀ™w#M<ˆÉvŒ#OǪ»fiC &ekËzË™ìšyÊJBc]² qû(Á¾‘ý†qÜu¶n•ú8 ªZ‹Ãí `Ú¼R›è¡œ,+LëÉùìpKÌU¶.ÛbŽÄ{Æœ³Ò „•Âl‹ŽòŽ€#¥U…ö"e³^ßQÉÐ^,<ÆG€„A;sÎJ; R³Rm…d[Ñhi±¾«ÓlŸzé+™`ä¬`@´9CÙD»ÔƒÔ¨$¸á3W5Úí|ß4 ª?&Øv$kbH%Œ€žÆñÂVÈñQE6 6ÎQo¶¾Ø4ô˜=užÄ½¹ë´d|sÛŸ•AxC‰û¤8·R@µ5"µ×Ò‘mÈ3RKÕ“¦’’^t‘˘Èe@K&|ÂòÑÝ/ U$È_µYËuÉÄîK&ñõ8&=šgDÎrßC-gð5Wíõf%ÏvL Fâ¤c†¬æ #V*#kt„ñ9È}ŸíÓW“òÇÎxã”úÄé[L;²o sa A>þˆqDîv¹ÉLTy¶’/É*MíáæÂ"¥lVâFÄï}´ÀH>5v<¿¶Œ¬³2œhcðá7ktTZÖÅ—¡ì5í”ÆÏ½‡pdž£WøHwF¦©×ËöÈdl÷£ÕèFµw—V²dÀ Gײ?çônípÒ„GYµ}VÕdk ªÜ\ ®Þ§¿ŽtÁµ7"™µñ¬4º…R ´jËÕÚáPÅ8šÈÁJ@‹á2±‰Ä9Àí£ÀàÜ‘ºx6‚m{:" òÔ­‰n TÝtÇx L t‰1¬<¸£ÛרDÎxÑ8%OÚ&¬šË‡a #;Þ!g žL†›øW’ ’^°íYt™k%2\‰2“îû¦Ô i:Ï ²ƒ)xxÏÌ˺0rKê"cN‰lJír€’Óõ:êRjµtäÖVy¶ƒdk·Ÿ¬4B;Ïz3'8W½—Å Lc X/Íõ8 ÝöþZL—_s»e;2ÏÖ0—@8Ê E£ÙÂzÛð¬rÿ¿´kº¬“C6Ýç(|490|£MÆ0›t,›ÒòÓô‰8²…uÉdå–aè^nXæÇ<½øÓÎ~(´ÚŸsë¥!Ve¨w†­l´éJµð¯*7 ÀWªš£«•Êx³Ò(ñ—;‚@1 ü„¤o®Ëöߪi§wœ •€w·ªZ¤úê;b‰8&CØž°»À«†µ|ú΂Xèò†ôi¡*+…S²cU¶¢»JÉú²=™§y`z¯dœÞ†»ï[Åt_›g™®ÊÖ’˜Þ1†ù€Y³­½j;èrìšÜ2}EáÉ`ÁpYÉPû7ÍDéqä†HCÉ0dþm”ï ^e>5"Ɉ=K6”  È„Ûô “Ém’‰ïC>zñ-†I`”v/†Ì9ºZÓz4«ä‰á® £12Ýdä™ô;s¼*>Yd«ä•úqƒ1â¸\½l-Óõ:’"ÍxÌYñÙ1úþ­ƒ?Úã{ï/˜´ M†½?¾{e(cð-Cï(zÎÉ‘¾$d>&GaÜYâûßÞSÂé‰)m¶›ް7¹MŸ¿³a-“€Þ‘‰ýa-12}ùèÖ”x³rƒã›žRÃnôËÐk¢©Y(QÏ”#² ð ò• |{°†Eª~´ô‚#›HÜÜÝy«gÛ,Ùª”=®ã¦ÀZ”Äg•ûŽ·Ä <ÚÏÈïSZú#Ð8Ϭöòn‘mY/óÅŽÞJU(Ékœ¬Ä6eŸã¶¥Tjz¿jºQ|X£. FnôŽÛ!€Qã‡*9rˆ4âmìúÆ©º;Y_x- 4Z&®·Wê¾Gí¢ïOzx¹‡2·[¸`"FK¯Dv Î]ðÕ‹l·dœßyY·$™. ýÛãH :ÿÛw~oc`À, }¼à0ìØêrU]"çÛq’–1aG½µ8¶U$M²9lá‘1”&Âs[xZŒ#úòÜ g+±vWp_ó0Ô® ààywÌV/ €¦³êRĬL©ŠT‚»} œæûaõiÂJ9Àuu”•,ƒÏªV²C2 |wéŽ[ILíôÙÆ#cjw°LÐŽ1Ž¢’ª‹›8Ø&Ž"Ü;ðÙ*±’•D¶Jl+ÄpSPv5¼¡Â ”p+õð<{g¼y·ølÒ·w+ýÝ4ziLÏœL`FÆT}ùpÙJu¹‚¿1?7¿_nÃp-áOÞþ¶Š‘”i`Cy €_µcír/V‹ìH°³³ vh:œ Û[ù|{)ÍmÖ;æ,û¼øyÓU‹ ΜìýyÁÛ¦¹ª“µ›|ŸöwjÖVu„ÅLÂmÞtÀ,7ò»ôm1±Æ}»LJ,_ãsïöë_ÿú—þîÖ±0iFmÍp,0úÛ¬'ÐeÒ¾^ {\k‘µ\í2¥_…²u\©vCÛ¯-M2|˜FUxb¹=Ó¬TU‹›ÊÓ4e]­½.&ªøJrÕKœŒºZÇüe³8$pT^êøZ¼¾®ÆÕ«½=cXVõû Äl•˜ßQ'µª¬EŒ'}/{]5â)µ´‹™¢ª„—ùàÃŽi:ÂþŹ{Ñçà¦Úe‚œkq,´`[)ë0|½xÓ_&bT»B[U…E³¨ŠS»Á0†I»Q&Þtæ|úÔ”|‚u­Ùí)+U•U1 uôŽÜ´Xaˤ”U…R˜ŒÓž2s¤÷úô½0q ê÷š<çÚÓðaȉi¸V°˜ H†Ô•ÉÙàþ᪠£”F¶’WÕeΓ>™ 3wôLõö8º0xU>€–;ó, Â9×B¦cæ|ˆ1ŽÄ|àzá|€f¤Ú8z285˜oœªc¥21 šë˜C³FÆ;Êóåëí °Ñ–§OV£® ï?oÇkluõ?¯ÇóäFÜ¿ßjá¾#ÈÄA˜~_µs;*™U‹®ëqx¶rûäFcJâzã=;e ã‘”w¯ƒÑ"ÏZr&,#ÃÛÇÔ¬d]Mcáø…ç?½I2í»M t C¶# ×Y‰ILûW‚Ûª^ím˜–˜¹Ñ6Aj$ëó…1z‹ð ‘Z™Ý> íù,7"¯‡‡#æ)sC2Éò4ý O‚{C‚ŽÉØväCçÈdâû¼ðé•ôvlzã&Yجª‘²hIÙSðIcôû-Z»*MCmhŠ`‚GÊ|l(ûÁ‘‰e%‘̱äÀYâûç¾^$ŸlpÔÒs¥T=Ïç{·8‰RMßJÖ()àkðI MéSÂÍZˆ71+y»%˧ÏHµ=髼@Ó§lôFleÓeÕ¢[+Ž`Oª‘?™£Ÿ›œ ¡ŽbÓû²Y8ó²j-Ý«¬mùk_Õ,UÇ÷.È;äóCT‹[ãDãôšØ÷'ÁöìHÆp½Žóî%»~‚J=í#÷2˜®öëÏ?ÿ\¿yMRî)a=¹ 3Òié’2kšæMŒdNŸOû!3w¤ÔKcã™ÐWÒÕ’d2> ø4ÙˆÌ+!}Þã~šë‰U…–&ÂF8f•³œg .ú)á™È”ÖÎÖ¯]Øÿ]¤7å`³€f-GÛªf™¸ê0¶dôœ5b|904“µ¹##c”ŠøM¡Ï3lJÎûôéqAÖ&Žnª1½’‰ÚWœ™²Ḻ¡zSºB·N™¦»ão"zmŒ®4Ëf÷º›˜s;À”°,Åy»°>™@¯Œ•MâeXu_+!1*½VJâmqlPSný³“ª€jW°` ÈUßöLZ¯¹z½Ø»¤v¹M€æ–3TjDJ¤ðU¤ÉÙÑŸ»0†æÖÏïP¸GD#²4µcúБˆlöÁ#µZPÊÈÓut‘áÃxU›ÐÃ÷+s¾3dxš&ÂX¬$X Õ"1 õò‰—È4zn²µË¬rN_‹R#qž™è X䆩Qv©ºTñü¹Uµ@³2ì.9”5ð!hg@ú2Fúµ8Ò8š^Õ#´ÔµëÄÔ#t_Y ý"ÕØgÊ0o„F%¤|埗l4)›B†‘ª%†}ù•WržÏ\ÆP*!kGÂ9¤/sö\-×(‹w/!¾)< jŸÛñùã˜^l Õ]®ê¡ØöÚªÜdÁ¿74‘2ŽTm±Ä2CÕ>>×éjU)åø)1‚¦ªöŽÆµª!a¶rwA¦×h‚¾l4S­=½FUJ ¸“?£÷nÈzeä¦t½UþBU¨rPmIúZk±$qÄxæõTµ”Ý…æzœÿ%‚`¢$*57¼ö›•>¥ÒÛ¢ÓSÐ/jÙ1@hQµ0·7GQKXÕ±öîëØ\àý"Qö\mÞÁº2¡hÈÂ1¦ÑÍòÏ]ûU‘‰3IS¯. Ü¬|"õjÙ?* ²M܆ù—i%2wÌJ®±hrSBªöW ß%þ/üê𪠅. ëu€Tò€ë+÷¤4° 3È­W )rîjŽç¯Ñ´-´?˜Ù­ iãeAÐ ñïfa¼x5«b{mÌÐt %¹EçCÖVeGá’V"nt³”€¢?ÈÙšÅߟ"þ.îÈÐHï!õ¶€£jxÀ‘€žƒÚ§^GËZ<»{GƒòLSúfàÉ*YI„µ÷;ZFÒè—>ÿ%{+u¬ ÃÁˆ"’@&ýõ8)FN†yõ "ß»Àd¦°µ’5ÒtïãåÇ0§tßœ7/:ÓÂÓ¶XµRzVÀ°]KŸ‘/¹*,ìƒ.‘\¼¥°l‡rËÌ\ ‡nMË‚,g‚˜Z䪀 ñ2ÚGk[OÖÞEsˆU[¸qå–§o¢j«òáÙQcËÈðÖv„s˜³v}]½^£Û™X´°é”øæòÁ82dšvk4²‰ñº|@ý:ÖU»RÕÌ{nQʤ‰ºDæ±°6™£ì(Ûıëh¯¤ËDØJxL¿4áhŠìÈÁªÜ< hôJmÒ .K/à‘]­jYWadö\‹vÕº²rÜ­dk×2qV"’?Òžý²¥ÇU?Ì宯„¬T)½–$#hz9ñ2} í kl‘ùÐÛ,äëC¬ºRse2ämýýD}c=ˆmû˜h`2-¢Ñükœ³±° Ù»=A]r+u¬%7ŒˆÈf5A 8”{Xã*•«ÖµgUqnòý#µ/$¥ªìU z[&âvœ–4˜|º¯jªW~ô˜;áó°C×%R¦ç`2zí¤+½Üið]M¬‘£êÈ6}›k#Ï6WLðÑK£…ƒìHv:¿ýÀ ß“º€6™3¥R&ªºÐ&2AÓáÚ1Mϼß™³µoz>wµ3§q¬JŽJpDÖˆ©1Yƒ·MbüJ/Î$-é#ôNÔ¨ÔD-ÛÐÅûÔúýy>˜û%ôbZ¶ð6a²Â+áuµÏKâ[ÏãÚp‚5TEÎr s@fÒt™Þo ÛÂ}¾ð½Áù¶kŸ'Þ1™K‰º†Â”1²*“¦ÃþŸÄÜWBö¿¶¢á¯Åo]ž”˜æ6ÂQÐZ¬Œô}9‰ÛŸ•ª’eLEíù”cä_ýë_×_O[fAa-=JÆQµ»m¤10Mt¥¿ œoU#QoJY ­at†WuæVBúƒ¶c÷ahAö Žl«"ðñÏ6²éïn޵kÙÚdÈ>žô5¶eÌÍ¥ÈèãezY {@Jí9ËH-Y´0+%Ñu„$sk¤R³ÊdÆa<’¼Rn”¾7adV­ñÂóYÞô6qc:̰Wª¥Þ0>gsTÕ¹É}¶_â³²;önŽ"±¹Ìµ0Ìs+á U»rLÍHUs&è r –r÷’E-x±g4W´ªv H€ÑeáéÛŠ¦Æ 1Þ­£ÌlϼïW®¯%O]@G€â»Â¾œŽÓ³bÂܪ¦g+§Qb…§­‡ÁÿX€CÊ)i\Íà“g;›èFô‰ %©¤‘Ʊ.ÀwÓVŽ‚¦è:‘ô…R¼#½&s_íùO éþtn ¦ ë•É”|=ðöÉa‚LÒÈÛ§¹2ÃÈü1dLð>¹^šÀÖhtƒ”ÄÜ”ðŽ-ó€ *sÆûÛ¿F˜ø½{¶Ú]ŠLŒAŠLôæðjeW IVãõ8&¯yšdeáFç¬9fìG£.CÜ8²§Þ€@½?AÇ7×{tßÀ]Ù¶2!ÁöÄÌï)’ÉýÒ#p zŒ*ŒO£ ™ Þ±OY5ÃÄMD2Ä÷eÐ(U™À˜öP½Í•Ÿà-¿®Üj,·y_¤F0J¬”rëv0FodíJÀi°Ý¢þÔŽ@ €ˆi'Ê^ß^Ð0ŒÙj¤ïY9´wU M28¦›èÒ'¸ÂóÑšKœ­+TmO-Ý%C¿Mhè{©¶ò;È‘¦åg‚¡LŒdE tqöî2ܯ§¬Lω±p8ÂÌå©®‰ÖÕgê“"ŽlUØb.¥½g¡ìý»BSXÕè(tu”cz´9#»æ&:òid8«ÿΪÙFôñ5kÌ ñ}(>Ž;áüt+µ•¿°:2$Ð^(wSL€• ô2’ @ÒŒtì"l}jü) ‹ûK_µY9 1²£HhÏ<1d0@œƒ#=/ûÂ8ÒÈY‹õòÁôÚ­FY©‰dY›Kì¨ä¹j£—æ}Æ^¾«58pkàÈ«úùnÚsH_ÆëÅ÷0~b| ØÆ«b¡¥¹Èªdþ"¢”g|2Xi2J÷È=%ïëm ,Üå3õûÍÄwzC À§×èüñlý#’ZöÎé=~<£½.-˜JÝZ•3RîƒÆ#iJÉ ˆöð•¶µ4ÎbípÕ°£®“Õ%ÓȲpl7`ƒÆt¯ZX%^î x #Eëiïô˜Þ°ÏÈ5‘»];hd‚éAš• ÁމÉ0½mß(S´3Y ðùy€h7žFí9ht̹LSIÞÕö3ȹŲÒB&·ì‚MÔb(¾l ¬Jã7XÐ,%üdÚÝËQ´y#tuM—ÒèÖº²µŒì mK¯$˜X@°uì"­lzqUŸÄ3¯@^Ë3­ˆ¤l€>w¸@9«Éò”‹5¦‘¦$aOáqº~ 4H•/Óä&«6¥ÛôwÂçM0”º€¬¥¡pÎ}ÓŒ¦^’ ¾AHÕæ*™›3‡L2'ÓÑÈdŒIO6bJŒ,0^@¦Áe> äæ*½Ñˆ˜&Ú‰Ì&0¥a¼`XWGà Ð"'rPbè¨Tµ.ÌÚa>?ŠÕX` @*º†Àðî¶´„^ÏI¿]ëzwRÒ•'Ü,yÓ‘adûÈ|´fÁ14ô¢*^/RÔ‹w<€§± à¹^]dðu=¿Mög¼ªÜP½O¿úH`A x]°F&Þ͉ᜃ’cëMI_)Cx‘!%O¸ÍU)Ç<±»ÄðǘHOÔny[uÄ×ÅpCG*á'€M¬ð2Œ€A‚sƒ0ªH‘ /àùÃ>çJZ´ÏÍÈJé¦óL†l’ƽ¼M ÊJáè^toy®)h˜´%0Ÿ@²2I/ã™ ‹®Š¯ `*ÉŽBÉuù¼Ú­=1i6—¸ÅÚ!O Y-Mïs÷UW}i ÒU£L¬Dpöø>©G@Úkd¸‹a<{p ì Üíü9d‹¬ oâ¦7‚ƒ‰sÖž›.žŽ€F2>zaúµÙÊLT‘‰5b-`]‰óWê(˜Â±Ž?JŸ î$?m_CG;Œ0d•n«½ªÓ’`ö„E|žz»ö‡  †€?ÏÓóýeh%š‚R(õ¡´•Rk4¢O­’¬Š!ЕŒC (¹Žð!FúàhT› íUñ€®lsN©$ŠÑÂÖ’4õ6+%[ %Y cð@5SžUΘVjúd²‚Œ¿lœRÖn´*^Õ^Ã-àÚ•r.7´ýÉhúŠª U¡×PY/™sÌöiZ£¢l¹õ·Õ0ÿV5@ªöȵ°rô‰ë=[~¿¥È ]G ,ßQŸ7IÜDxëѬ×ÙÖ.÷ 4Z¶aƒf¥‡Úw†Œž­ ÷À)Û¡¡1µ;Z¬Íaþdv Ð…_5È\nUCE³8ˆ>ed ë"ƶÿ±{¾Hïqû‹Ž š Ãåø¯·C/Ö]Ò»¦cž4°ûÊøÌ“aªº €fÁª‰ù­‡gB&ˆ›•2üîPêJé¨Ú»y¼¬ôú[5†›¦Ï‘ Rf’^&Ø8¼Ñ”Ñ´*€Ñ.‡)•ü»kôĤÇs&ö'rÿä‰Ï?“Ž/€FëUuGGËo:òÊÿc®F|›üúÇ?þáÜ£Ëû÷cýÚˆDý6ªJ=–~‘àö”¬^Ù±§„-ñJ×þóÄJuEʳdQALUGkçãæHUS0øZôÚV®ÔXÀí?q-|8èr$s$ëU­$‹ô@%Ç|ÒÇóòÉ ÓQÜgF£W4Ðòßñ*7 ¶÷ò2l %³51@T’‘‰iŠd ¬l8·”ay7jŸ<ý®×c·ëŽÙnDþ|âkï(;ŠF8²’EËJ²^ÙbÄJÔ÷“èƒ À˘nã…#ÒÏg?cõ"•zIL>ôVm=|sAnaʢͳªF¶Þp2díé™Èxþ™ÃÖ˼L_‹ª{u-‹¾&â3¤'PÂhÄp“‘˜ðª|¤$èUÄĦtÌ– U™ kqìj¹µ Ò1@`Ä 1º¸¸£‰zýý†m¿âU`„*¦CŸ¹|GYFˆze¸*}Fò\#O1Áª‘k¬~õ®€é:™À¢érúÈì6“n稔­ªè"¦ãoŸÄkÄÓO©*ãko -ÈnÖH …%›‚ÏG ¸’Ït¤ÏJÓÃJípLï-CÑ#ôuºMç·G)åŽrSäÌe8Û@Xfë+$Z^Æä¯Úò|jlôYë¾^ú4ûŠ*×bíOƒ)ðÄ4¢ŸM@É2Éä;á|É[ïjOÒësÙ¶Žüñ %¤h+GVZ|å}¦È6É0LFжm…OÏJI—È?X¨Êºä܆»#2Ù;Ïg-Áº²•‘Jô¯?,ì‰o½Ž”[íÅZX&¦ ¨Öë ÷Ç÷ûµÔK)0rV2±)r¥ô²ej‘E]ÓŒÄÿÏx¯ñ7Ti‘­£•(k,#­äš2¬J#jÉ–abG¯Ñƒ#+y®HL¡Ê6ÆŸŽûÒ6B ©±¹3ÔVåLÖzýÛ.Ù7V /›kYƬOÓn[;2s$àÃ8\Ëã)ö˜R¯åíÓÏÔžq홲×ËJiÍÙ¦7ü°å_©Ae;h<›PCX¹û§à…f/mF)ߥ)[ ïz2 ¦ÇrüŸ¡«éUõl´e¶O€­ ¦é ø¬a|÷´†Rß$]@<åkí3TïïMwo1b@B‰3F‹‹”¹Ñ †R¶•/"ž =­„t|ã}œUVJLV¯£¡H†oºÝº»^±Í‰aâWæ92CŒ;–1@]iä^ AŽ42¨+A& +¹¿}­vb² º@`%x;ôž5.Ï(èÙrÐŽéëƒ t„@IDAT4 ßÕ`8Ä _ ¼X㘉W“!¥Ýh Õ>;za±U½¥<¥#9OJ%ïÜ÷°+ç‰ïè#£wdN©e†Èy*…‘E³˜h¹«ÏB4 P2Ž¡vš[?©ÑÛS‰²ÚU§2tA·€=[¹ükÁL@œÆTU%S´Ô­';ê}‡:¾k8önÚñ{–ш/ÆÁºðçòEKÀ¦Â…c³ág‡g3±Þx—Ï-RFŠÚ•Šzu96¥‰²£L/ÛÌÜø”U{Œ½àØ õQiÇkÁ¨ú0U‘݈¦ß¶õ’Õ¥hœXÉQX “@+©æc+þpãà9`šB8ö)À¬(Áª^Xoí/Ž”3TÒ Ÿo$–­a„q@ÏR©Íe&ýuÙ?¥(ÅÏïq~ ;ªš+¶’@ YÑË‚@IÌùmiЬJSo-[ Ïº2l ýxþ­sþŽ€ÐÛ”³âýD0uáa"/´ÔkÖv6QošºZRv$«‹ ßq@CùÔ˜^^˘ºè-ÐÄZ(§WMßÐZö™ö»I)@,:2¬%+lå70Ý‹a¿‘µÐ +Á}…Ú¹ÞmK €›\ƒógàØpäÆ6«Híø²*Rod¿I󴾵녋ª€ÜJ°}24¢Þý´Jp†4¢¦#A$@ÙצU3™L{ž)—ÉÄŽdá@¥^ï£Ì0`™<]Äz ?Âø–AÂ|¼°Å4bÎÈ;”ƒA)ûž$ÆJÑ&r ÑÉd¤L,÷8yòÇä€ñ‘9êÅÛÄ@¶³ÍÓ7ˆ +¹ Éȳ"‰‘âÇz‘Éʳª:ÍL,&ËÂQ„ÇG²= ÷:vƒ­'Tß—$°Ò•Ÿ·²Œ ¤˜J­êØL?/çžß›b*QÖR••#+í€SÕ†ý f¾œIðûYø€˜DÊ"çÄmNo\LÎ1í‰QbÕãÐ÷{Éÿ¶„ŒFÔÕ¸pyæŽæÊM•DL—i’eÕ,Œ)ýøçÙªL‰ $0"ŒéS@º”G ë§ÿÞáõ$øÿ…–íjlÛ¼»¨*‰v` ä»õ;E©ã[…ãAC×¾ª¹}y€¾´”±Gð=ÑÕnº¶Ææa>~/iôþZ˜D}%’½+4”m_HïÜiÐPJæÏŠ× ­Ô8þ4ýæéx 0Äcèi„^%G<óN¹ªsw¸L^£U…dJLUG—’ý„íàI÷™7·Ñùc]HÛÊl;2˜”zdŒüóž*߯“(Š˜0£l¶û(!EŸ‡lÊĪï»p£DfKp·ã“¡J®ç94âM|•¬s“)ë%ÛJ½%·ª@ŸRU|"UeŒ,5î}»‘¯ÎnC“²)µ·v½ª}ºkLéó( ”pÕs9|ƒ(‹J²­(Uëj|]MŸ˜Oó=ÿÄ&¢^$ìR²7qÄÃÍÅ'Ú<žCI3Î0ÜÚæöMc+î"¿—ùïc½»š¹07¥ôJ<ÛχF)¹£ÜuΦ+ëïŸx>BU)q¸[#UÉ,“[2XÀ…çÒ¥%>-×û˜sN7¥t5ïrz¤£ö™;¶@ÎŽ‚ £Lj4ˆÆ'ÂÖhù|é½ÖÁlޝEmÈ^\¦Ü¼nØ*ø€l@%ó¶.«¹½G½H ä¬Ý x³àôd<[&ç6´9@V/M ¶-“‰.$1 ޱϠY¥·ÚU)«’ñ—m¿M€ÃSÊø.% &==ÜPþ±#™cCU“É|¸\#Œ‡õjÉ!=OÌHI€ñÑ»ˆLЃTeÕš>2+SÚ“Á¢vÔE)X!z{œ”óL°Û³Ò¨šr]üádª5Ê¢~?uðS»cw‘àâ]Äb|Ê=£Òv¼í›¾’*‡µ4¥–³Ö½‘ccZÞ2øµ«R&~sšd9ȶÕî°Ò¹Ø}g)taòIûè}!•`J¡äX ;´óÉd¼¹°WÂò·û|.Ù"E-Fô³©êcòo;bLIð¾?lt€qp£Vò©! ÒËÇ‘•™cšüs&1”¾*ÿþ÷¿1Ý#¸å¿öÛtž¨ß3½X—bÅYÐh¼çg*9Y|>[©]T]&‹§D:|RÖŽÏÙPÓ]_´ÀÚésÀgXi{rÀˆlûn¼k·Xr-3tYb/7ÑQ5%=UMIÃÖzÆø“¸®–Ù$LF“Þž-«˜¦ÐÔÛÎËÉÌREvL,›¹ÅÈ·z©*‰Ö“ jD+É®fC½®fMþ­”' Ȫ4”®OžJ¦`ùÎ<_Gíbâ·WÕJ}ÿ™ç†ÌGVÕŽðFTJIàX©»ÇhD½åzó”W…l}ʲ%¯Ùù3«YuQþ]I&úøêŠ‘k!ãÉ's+‘… `‘•ÇÁ¤—98À¦á#Tsú¾{1J0¾[äà8¦êõ8ÊŽËñåºä¶Íy™?¾h8¬72O²@”y]°WsäÙΘªrw(ß)bd†¦.&¢v¿ç}â¦4®Åã=cþx-4J>†øÙn"Yy—šÒzp×!{[^ÏJýèµ³®6÷Õê籟M©êhCí"܈Èw\<™PbhJÝ),Öþ°ÑµÈ]<çºh8¬üjÎwÚïÔÚºPY‘x¡ñ×üá?:˽5¼]5d¹IªHÇ×n¤yJ`2‘‹üË}6xSîéü=»ÿ%˜,âª8²JÝÙ#vì×ñ¶„Æ®,à ›µ£Ržø‚ê9tTµ¤¹¦ûÔ)1™#a@|ì¾§é­Ú\UãÆšu[Ï94欥*=7ù5éAj4EUKJ@£^£c?$ÝEÉGÐz°–¦t‘za³2O“3Œ%°ö6ÇèEÆ;’僷FÎÉð a]Ã5ºƶzi|i rí}»üVB2I\ïûŒºTk„MiºÜ£x1Íú"#×è˜ ^©!ý•§Ç;ÚðD°ƒˆd({ V9gˆd•&¡Šl YìX£cJY5Ï|Äm:|Jo–•Úm`½0 A-6Ì°ÆÆ!-Ä®Ö&ù;"k‡=HÕôi2oPs}1(Ù›KLY#YXÖ( ‘C¤jX‰§#‡É $@©4ìø­ŸGhtŒU­¥¬D#TEÇJ}âHÀ\ O9ÿ’ƬÆ%èÑÜ¥ROš¦®3òZ)•º»A4øHViÚJZˆåü{p]&M™ >½–<[ƒfú@|ú ŠÔ;gV¶²²F-‘ ´¤­€‚¬¡E+!º˜©bšmS<‘€ýžQíK’Ø”F4¥v й1§É?M£Û' †ãë=½R«Æ0lÐÄ1uY²‰²åµœÇú~ÊëU­=ÏHïe¼#7kÌS`¬dC²¡¥«m [„Ì–>LXÖÕ7 0 £…½ŽBÍípQ A¤õÒ˺j<.ß{+µm+ÆP$\¾ŸD_W&pW¨\£±^–-Yuš5ê-,PD_dX—O–ϹOùªDŒïå[ƒ8ó~sÒg%Ã"o…éMò©„l(²?vi\ÊQ‰9œ ÅhQ—LæØÂéi(aüœSv£ U­ÔgŠiœlV9ga%½æY}šÌõâ‘d)åð¯2¥+üˆGâ:îvõ&†ÄÀvŽY¨B—HìX£KýúÛßþV¡Ÿ¤§ã{€šF¶ ‹Ýî½F ˆ5öjŽp2Ù1eKÀ¹ù¯ÌJ¤ÌüX‰P;Íi¸¯¦'ް™âÓiO<%f2‚Ü"ý±H³çº£NBR½[{ž4e€>Ã}1üžé¯ ¹ÕH–žs&ËÚ#e_ÅZä–±À¦Ë™ä µSŠ-é.ŽFðüØ™XWïÐÛjAÆ‹ûÚòö4¦ ·Rþ<+!áþ¡¨ Ò+57«®ßò˜;ó¤áôµÃíIoÿºdz%Î@ß„H2A¶dvµ uYÞqeJ¼vzˆÄcco&^—%•b€µÇ'”L\ÔòÔÏt½Ür~õ&Î9=[ ™‹çC Œj²œ½†7QõzŽ@íïˆ>М»c˜òJæaýÜaׇ ™ŒRà1‚s”þ´ÝˆÔ^ðd»‚.Ù±?î)u yFÔKÓ?š:67ÖŸµî#Dbî.Ç3Mƒðõâa%³4ªâ­Ú—6qxdßCX$n1h‘Žüe€¬ôëŸÿü'iÛ¢a5 °Ÿÿ¾“8Ãk½]>T…úVûOOìÂL0žÛ%bÑ /Dæ-XWÇÚa&íI\F(Ñ”ls–c4øfÈpãäRd5çdO °‚µpˆ¯Eng@È}ðMìMhðLÊü›Ž_4ÔÚJuñAvBIxIyÊW¿¡Å¨}nµ«Ö²RÇ3ïû'“qHGW°ì¨W—ãzWß¾ÿó寤9Wºþy²Gþ}d Åó,Z†Œ&˜ ïa“c·Óˆ†Êµ³Ò%a˜!2èåù¬Ú!¾}WȈiºšk+Óæ)1 ÖÛ< U ëj"fëÁbûô£º%陟ôZZª”c [Í Ó½äzµp˜¹FG•ïµU17bVðÄ4Ä]H‘Z6ºF¼²³Ê íÄ“±J¬]d… Èý›(5Òh”9¨Ö€ûå¼.ý*éŠ'ÆcšX‰[zSÒð´yJú[ ¾»k4(‡¬ðÚíÉ  ÏV H‰\£)††@P~é³g<°ÿ•|žF®ñJ>?ÂH&YÕXÆWÒËM86˜Ð $MˇíßdSzUá˜'à˜!P×Þ!ñôŽÉöy¥Ç{j²Ž|0}F€ãv›¾Íu©ö¡´€c]40r/Б¸.#ú{?-5êª= ²/6}7”„#% $j7«ØJl[>Œ¡ìaád¹éÅÃds£àÉ^@Á[îxšïÕÈÜÂò”–QÎï_,k”Z?i õ2ÍMÒå¨EŽÍîžGXWnl·A÷¤áïŸMOVPªj¹öÇ­¹eÊM$`ò¾ÍnzåÞÇŒO©šÀ± ÉŒHÜ>bæ€ibVZª"EúÌ÷\k'€;šèYèýT`”Œð¢qÇñò-†_/¬—ƒ q4tw¬«òt;ïCëÕÃJ˜Â#Óh”…cs“ÁÜ𔘪ÉäÆák™[úüUñ…5šÛíL#èMI“ó.E 0‡Ò1íuÉÂ\ãêÒ#cdúfx8 çêâa†ŽJfé¥wÎçw½5 ÊwDo AÁS˜…,ðŽôæ¾¼ïAÿ¤ÝShì¿ð!ë5ü°Ã6T"F:  wÞMɇr2¼^2&iÚJvìs£ê¦ÍJŒæös áßQÞ12CdÏŽÄôýGÒoC1ª¦šÛJ€ó,J²/C÷ª¥7Ñ"¸©*ÅÈÚ+Eæ wü!Cr¨nÇÞ1CÇfeEVo2ƒ¶û3YI æÄ᎘c÷íV5z{xC}¯Œãܱ¡€ÿô­ÇdSxbÏbCÕ6d%Z ßû7T hb2GbØ”ºä-¾¹d)õR"ÉZŒæ5Ì–ƒ_o»Ñ%y·r>‹ywàçç·‹ 3§ôtîå(T1"CHo1À¬~„ÝH—¼Þí>o•̱}-ëÍ¿ÅM© äsùü¦MÐÚ™Ï0TÆXn"’£×ÿEEéÏ MÄŽM“³Ê½™5:N`Þ&Ä‚s8Œ”527Ë1 ýånWu- Eˆ|–ÍmtÎa½–é´É•|þBÈAU ™ÐìRŽ"±vØÐ”džT©s4NIï¯?ÿü“Zøã­G!Ò™Qî¤ìh¯ŠÇ”[&Ð+btæaÞÕû’õ2éÚ74ó<“U§oC‚b “ 2£m"s’Um=ÇnÝzògãûŽ­Mœž È0Fnм^¤Ýèùˆ4rÑD˜O¸ÆZðÀLêjº,(k‡«î)ôæs…'Í܆é­˜3è'Ìb•–ch” "N3àxÍÎ}¤–ÆÉÐø@‰ûR¾nJŽdö1B8Öbsn3L)‹”çÅ樂UUX¯Ðk´,UÍRÕqÔž&*Y8}VÙ+Ñ»NVØ6QÆËiäæ dC ê[íHÐ\¸£‰ïÈ6ì &v«¸ vGWHƒŽª~ïwµ®£×‘~V‘1@1·/qþ³%€ €ùl4ÆG,šKY)`+À&¦¿s[IÉOñ®Ù âfÅÓ8öº&e7R}÷„cø{IÌí;Ží™'ž%j2¶ù7î8Þ±}zs²JLâ×ø«6hãX†§52ôwAÇHV¹è…jnɺ)=€a’LKD d·ö=ÔW 4…F»W€@F/;NÖ  ÊŸ ‰€¸3?_`˜›*¥%ñC)ód__-ßÄåF´$’-}&HŸr• rt€CFß#µ‰Ü5“Á”ª5KFz½qÀdH)jé m¢ŠtYÐOÙ;lŸJF·›¹Óc,Ïh‡€\ 黑.žV­'k4Œ“iéÊJ4À0Ùe 0¹ú.e˜IÛ" Rµ^< Ó‘­#R/¦cqÚ­7ÌÐQ»Ð(hÇt)+µpNïH cTמlþ×ò$†áJôzMpnËJUÐŽß&ø0¥ŽM!ëúõ®ˆ­1ÉYé-(ù ïýßúçƒ#hnJY éñÃkG&Hùb›Ð×Hf¨#Ò+ͯ*`Ù\ Ld²ïÆÕžd¢X Ìœ^±.% †mšÓ|Ç)EÊÍ’a¡D£Ý¶Ž€®7Ã.Ÿ˜¬+ÔÞˆ1ÜZI5ÃFäŒlP 8ÊJÚ)…‹d¥ÏHëúü_Ê«w¡î‘`A'`‚ëyRýñ2÷>¶L0dœ'Žq¤éÓ’û+¸‰x]IÙè2Á‹d])åx#ð=™;÷󜒸Fâ¶e»q]Ä‘˜ W• È` ð’üÛ'~z¼.y a¤Œ§Ç¼-M9Û|oÝȈ‘†Âî«Ë1ž[ =ñmÒˆm¥¥.ž}](ÛPûz·mzíùÈ ¢ý^•›À/æŒ×R·¦¿Û!ÉÚ Ù\š0Ð,Ç í£Ïp‚l;NÉm‚Œpfx]™´S® |n†.]*sYÄd^—M6Â¥¾Ï•Ò7W‰ìzœo5L@¦ßhÇÈ2ñz¹!Eß™-ßQ/¦)Ë-àȧà/àiÂLÖžÒéF˜v®KÉV-FC÷žŽ4Mé7Z;p@Rò!a]J¾K¯?®ZîœóÑÌ ”àr¿¬öÉVUpCVÂeãº7C‰E%íU ¯US( D`½kqS]õvö\F÷>@Óù¨’ùÕð©åù˜G÷•’_¯jµ÷\ÆmÕ®\K>é‰u¥—Å6'Ð.Ó´ªj«òI¦Zt¤,YèÕåšÚ‘Æi¡Ç§iY(á»`GŸ8RdÈ-+ÇVê²ôª”°pds1œ'0K£ÌDIŽ…–HG-”2Ã<3OFÓˆ"{ÿLðíOY{úª×òó“CÊ™;ê%3¡dæH-¤öZ`¤0š&=*ŸLðl+%†é-ïåiq&]Y¦áC‹9= ·Ñ2†²5U''s¤R ƒj!kÉñŽ¢éHXÞuÒ_ÉG¦”XÉ”•5Ú!@©ö”ÄHáÈAî ‘˜Ž­Šì3j¢ÇF'ƒ>,ì©ó”…Ë´OdG9Ï—„» QÄ´êÈ–Ï37÷¿d+|Éíc¼¼–VÊ9C9R×&þµÆšKô=Ôb¦+‘'óøU‰‘y¶d ô˜pnÚEãš›§ì7€C¹RÇ<7ñ}"%úb_Α©Š²~4̪ÔÂŽJºvð¡ÿúûßÿn64S.˜Hm-á¨iG. x%óÉñ©”‰y½ ®‹&R—YEÙVmI©EðWr¤Ôˆ¡I–?j‘žóH÷ª P%KC00Ò ân÷ù[f¶@XK‹5H´ ÆÓ;âsnÊñú> ¥ ºW™¬¹òÖË­.O¼Ÿ =%‚…›¥šá^¦–&*ÙSVe’3AU½M'xY‰¸ÝoNVïiû~#û€ð”–}M÷nU ed[9ÆØG°Í™á­ü2޽ Þ± ·R‚Fì…#µ¶õLI¿…ã){Õ–§\/æ\ïûwˆÌ›¸ßÔªÝBµ¿R°å0q†ÍBú)ƒML°Y|¼ó¢+#Ïo‡;ßžYu#9Ùuõ2°àŸ2Àªßzí€$Ì Ê¹.†y–'ËþÖ?¿Åü°à9ËF¤!àŸ¬vÎ@£i^gJÕHædVHô·¢éÝ'S ;n^GA ”øç,pN61ýp­d Ÿ2†’;êÊðìtÿ¬ê^Jµ{.ÿã%²”LtPÂïï1s«²rSUàyÆpÌ»BSªf’@nnSÎ6ßÿQýZð4=~hùªS:-vt÷›æ/ µ¤A’¥É9Fusý/©{7Y(#…^Ù‘§œÀ0ô½GØQʵp sÔU&†E]iúv‘Ä0«> iJíø •ú賕•ò¤ s˜Û%6±‡p¼FaЍ$ ¯$[/÷ûšõÊxí낻鉎‰¹eˆéSÐ#»{³ÚPš‚ïØ¸˜Äp¥²q”ÚSʽ0 ”z®°M00ŸS¾ã0|„ãFW’9׆`A/×.ÇlÛ)ª)3©w%³—À+ùV`›.kp?&µ4…¸#&g5Á±¸d߯dr#¸õ qDîoÿð¹OÉM®½—W¢Ïn¦xÇ𜠫fÕFÒømÓbJB‰é(°Mdþ½U¼c»˜¶e×Žïˆ ç¯š@KbǬdÑ&Zð™‡ñ;Âïñ8Þ@rðqüúË_þ’»¡ªÖßA[sÇýþFâ1YNh죅µ—½B³‰½Wæ@G%Ñh&È9PÆ÷ƒÝŠßb-3¥ª™‡­°ZWz$`a%¸ÝÚÖOq&x²Ä5–o1b·«N ´@®¥Y1ý© ÷'ŸZ¸ÙPt$Ð%˜ˆfUjî¨DƒïÖd0þÚœO¤ÆŽþ²sÈ ¨ŠïFg¥vèÖ•f¨$¶ª.úzSÂ?‚ ­‘’ 2ïj°È3Üíà;ùó%©Ñ à稷ÆZÚ¸ÜÖEC°#P×ÏlGjáÆÊ—PVí­ô:’G‚BWþeG?˜@×ï“…·§FViàd¹ßt&ÂJô@seÁMJÄLÈ› UØ14˜|¦Áppʹë­„QÍ­¡ù7O&“mœR"•`€ hPž&Fâ–a2LÑ’'F£HY5Röso4®7%n9ÐtY`&ÃPvY\Õ'ÏY¯‰•rs#Á§?«h²• „’}‚d~·Úñ€ßrÀÿ£ë–$;n$ŠÚ·úM-d”L_O®çDÜLïPQÂ"Þˬê&G“lk;}-M!²é@U¦Å,W B¹qD4J›«WMÐC1Åí Æç×%ÅÑ…cDUšbÁ”2d"¬´(ÕË×{)Ÿ/„d›‚°ýáLj"~&FH3A4„)DækÍ(Ä'«=¯2ϘH$A"JÔxKêrÄä¾[ÕˆI9±#ø»Õ˜@Ch+ˆÞ@8NsWJV»qbâJ˜ÙViq÷€ Ñ«‹5KUWUw¢vàÑà«ÆDË(ìÔ•¤FtK‚\5„‡àðd]¯),/n7Õ‘ëíU)›%÷3ZHA:õvöFCG®Š«vŸÜ¦4±•Ðbòm^—ôjŸ3Š1‰×¥JPÌ/ ›ŽÌzR÷VεÀÛaâà/ý—ƒ4+(Í^]1‹ð>P|â;¸Æ3_Ú¬¾S#>…8ÒJ“…³#k:ï¹CJ©MSšïàÝ•¸¡ÛjÕ&JϘ{]˜‘{»L,%ÕÙ[Fz‰g\"<ë¶ÍjtL¹ørÏ«ÂÎàkÈL#ƒ“cÎ <ï·/¿ðùbõ†)+ÔÖíˆñHl†æ$ JáwâÙÓ §àçïxݲ*&Z&­Š C´hï®[úm7‚·0ßÝ¥ð.fD»u4A-ÅNŠP r ®Ô’Ö\~³jiØ/ÿ6LJcÛJu¹çg˜|p|f›‹SÀŠ[‰HLi ù¥ødu™7:©þV¸õZŽÖo 5â3šL-5H$ë¡Û$˜¦4¾`ÇTepjÆ1ä|)Ž=´RRºà­!Ð G†¹ïOߦTmZ ìe&Î÷Žf®¸ã§)MAÊMŠÙÝÞÞv¸ÆzyS²@kLÿð¾§\†/%^æ|–iÔ•ïsWªh%ŸqAómâÈbƒòÅhp-†Bè4 ‡,ÿ.³-&ŽwŒB;xIĤˆ›ÂõëJ¼AÝ-O)íZjA£™¬…¿x]tðMlm„† Úg¥Jh!nhGJY¯…•⿲Å|"G»^㤬=§)ÀÜD©§é84“RÒBPê†)@Ðpú?múÕþõ¿ý@ S—M²È¹ª&jàbFèæ‰¸{ Z©Y ÌnzG@ÐÈ›‹#pŠB_ÉΟ\UÇG£¡5ÄFL¨1ñ?ÿüS*î†Ú`-Ú\DN­Y@ãÄU£ñhtðá5U[ÁõRKÈÄp -à©T¾+žË¬K©K¾CÅzíCÖ\ˆ¿Ü‘!Ó‰àu„´<¾‡§E o1±Å˜g#vø8&ja‚,ñÚá¶…è‚0 T»)4Ó™B Z§ËWåY ÙÞl|„–‡MG³ÿ֖«bÖ¨KÕis)rËóR K²«¦ßÂÈÕ,r%±*¼'û¥œ/€czW!ÈêYé®M ¤ÐŽ“ìÈÿ»I±R°|L4±Ñ®N•T"Ž'K ¶˜‰‘ñáÈZ¶1²`- ›RÜejo+`·±˜ÑÓ7K‰ÕèhS«"Ã,&2½˜šm•Ú\ÚR´m‹ŒÓ'Úb^B¥ÉÒAÓåÁ ZO•Ô{.©*2f·'´•®Ô­”IY¥Ž¢q-˜#¨*Ù¾ñWò ín#×n½ô¥µ ê‚D+o.ZA±ÈÌbãwØð›Žïh·û3]„µBwG£Ô£‰Æ#TjýZÂ¥Žïiª2L ]ˆdûרÙÅÌ|„—v‹Gæ‰Dg+Á‹•˜}]·FH¯J‡m¢õÒL!i-ŽkaçâîÚ@Ÿ ¾ÊtéÝž¥¶òÛ?ü?þ 啲Ȫ¬h"°R¾Mºªæ]5Ð|”,иԊ1 5h"”-AÃ{EÓ$¨¤¥Fd>…­-eµÿöûï¿c·GcÔvš‰¦ÒNüm?¿=ê-Ð¥šµŠFio¡€Ÿ~4ínδ0"mÁ Q]ûiø^qã`6]U‰uSÅgÒ5©"ç bâ¸)·ãlˆÏ+9ZÇI'ÕL-..¨¥w”¾=›¢ŠÓ ܳ+Rbf…§WBNsS€bž¡©–FhÊ=p¸;#ïЌ˪ŠUCˆG‹‚¡.3eäÞ‘ÛYoÏq½Ò™ãkäñ•hj1—Å5FkëEÆ Eh ˆ´—¤Sð›.ˆÀ7túkWÒNÄ V*ÆL°YÀ)‹-ŒàÍétbí‰/@k:\À{ ˆW5qSTJD@\À#÷e*ui¸R8s×a¥m%Îð-ÀÃãÀÅ6áÉörvÛ­ dÈÒ‚\ÈŽC‡,Ã[©=ÔXUüZÜ!¦/ÖRIJ<ƒHijgRñ…Ó¸&&M„Äù8(ÖÛ»g´.ä3ãþÔD(žo´lôZâó5«€'Þ> Õ L$>‘î .®QIü éų Sâé  Ö%PB¦i–ØójaÞkƒ¬zŽq{ÓiÃh= "mÕD锥Dô6Ô B(´Ò=Ã+á+•Ö[ÌKC6X ïNxFÁžûO°C­W …gk·yõ6TÚ¶ …K·)qé“lâ•¢iϳGÐ)º´øæ²‰/Åô†S¶Ijk”ãp"Ññ,zИ¬xíRfC†PÀOÇ—X:8NË4«­BvØC‡ï´'Ü·»JŸ‚;Ä÷_€ÀUÅ6(u„M¤A¶WŠ_L!²ÔþJÉÂ]Щ{ŽÉ~f\5¢¥G“åº×>š¯kÓl™ÃÁdz)dÒZÜòd/ñœ%CV"ˆ,`p^‰ïPCÒtœ®Â2¬_Uê6tÕÂòÆM¼ 0åºàRzi¢Á™ôLýþ¹Hª„_ ¿T»M<ú[ÿ<Änµm‘Y²¼X sC€M„ÐQ A“{׎à‘Uö´L0ˆÄ4·š væ'n÷¼vj0<Í]T‹) {íÑÄÑĉàÛÙöKjOkûBv]ðôÃű¤)4;`—©ä)3ü~Æ¥•œ‡SpÆ:e|Ö1«ê‚w?âJ8µ@Bjí­Ê›¢J*q4éøZ¤É:E[M¹îÔ¤\NƒÄŒš^ãܤRwbC%½DÄz]-|&ÆOǧو•¶'„©ÖhÒÈJÓ߯8Mµõj‡— ©*´e‡‚ü°—ö–àí˜lËç×"Õ’/P*Õ%î˜â]KlŠª.Òë€RÕÎ/õhÒ)Ý«‹Ð­'e ¢ V•êêè4tÛÖÎCŠëÚþí£ ¤qBЬívó¶x‘¤Àþ½e1©d7%Fk+KÆWmDqRz‘áR¸^±sÅÉÇ1ÇDšC “Odx„s¨ô{·½“R«Ò§ƒlLH+5"g.Ù–ÿ1‚NLFƒì ‘&.(6]ﯿØ&vä£ ̺»"CÒm›æ%BS©8¿);*Bš1µ¸)qãÝŽqÍ7ÅD¦…NG" AëðÚõ^ÖçmÓÛí–GÀÔ¥*°€X@Ó |4’~Ó;~̪3AäÒðÄ!%¾w¢Ø‚˜Ñ:EL£Ÿg~hÅ11œGŽ ÐŽ)­—g@üJ‚¦×ØD#yq]S“n?f7œÈö=‚ ­ åÅõ"tÒÆ Ld8.¤ƒðõò=² š.Õ¬*OÄ ðžóx&]Û¶2퇼‹R OYš¯¥mÅ1Í8J஫M”ÒD³œBK\#“Fn%¥oœ®«×_JSUÜ"çß«ëìÆÕˆ`О¸˜5 ­aø!ÀLÊà]ÝÈ4K[µ' ×H9ñ.'f—“Z4íhª4ªNØ^ä÷€g­ûXT#‚jC§ ¥‡>¦mûúRm.N{¶Œôj‡ …¤¢}„CýfÛRäaF°ÄÓ­ÊKxÛú—×b’ø àöKƒ;g˜À„t¿öÙ!°Ã6EŒÃSÄÁ”v)f4„®b™À“vù˜vg'R—fј€SórF0ŽyšÒÑbnaxdâ)ØÄÚ¡‰‰¸ WIªëÂl¥»Â¹=Aua"t΂ç3d%)/fm8‚‰§ù¾c¶êJUé[ 2f½‰ 8Q!^W¶àcÎ:8Ž ¯·vÌdU>$Á¾lÕ ªbH„b¾Ý&åŠ:‹eX§(Æ)mÚ·°@Úæ‚‚Í­—ŽË‡ È2¸TûN'¦“Ÿ>ÍÅ8z­'/–ÎY©`‚½ðJ ÿGWä1¥^rw’rG¶°aòÈ]&¯A „æ‰J^c|¶õãO¹:NßžüL#{×3šíÐIYY¯u ¶ D—^ðÊ|bã†ôYK3³WJGK—)îq7ÈšÞy½ZJâ¾XúJÜûÖ¼.²ãìÓA½¹ÐâK-€Ð/±ï“BÖÕzbƒ×ѤææÛyÌ®.B"õžÅü?SÈä®ÏÁÕk!Ð L—\±f‹òÈ&îHÛ€ X‹ýbJøÇó«‰4):æb2½ÁÑà¼@¹­¤âIˆcÝ\ìå&•þU=9&ÎF7ˆ,\ W• X"VRÕ‹B%i+ X Æ˜ZéRŽ5G¶*ñ¾­¦ƒPŒãDº¤b^IP{—Èo´ ³h¤¯Ô\‚Úé 1©˜ðdùZ⨖*Ù‡ +J*ñ€mò¶²µ@Ä–¤Ã¤b¾w ¿6k1Ï”,£‹NËÅZÞ•Òéb‘kG+ftTiòÚÓoo"&A&mÿÚí#h ½h<~:Kùª%þÕQ Çô©yçÀd¦w|UiËã ¬„,H$å‚ÔÂ##À:ÐÁyH1‚>³5”6½¤¬qÈ‹!RjVÒ›DlÏ1‰HÉ2d]hŒZ-駆 =S¯!o\½ˆ,>ŠK\P—­ŒîbRqê³hùSmÊõB2{§‹_ÃÔe}Â!Ó×¾} 0ktEµ{íž¡õAH-Y‚],Ž*ß\¤”ú<Â¥Jø!zkÁD“ò¼xí)Hs¯SSWeJm+îõ †ä”+Á²@âãHÇïoLl‡ +¦o´M´y‹Ð† êìJ5½ŽÙæÀ†&2} 2»ÂŸ{ƒx¶œ¢öZĆòz•0“¥ã6”¢I¯ÌqÝ?“â8u;ó~ž¶íøw¯ÏÏ…WGc>fjpÁ{iËhŸ¡‰[Cйt…hñþHÑ\`Ï%ežiéh½EZ€yªbL¾¸)¾@à{]M×ïŠx1°Ý…Òv³F)ßµÐÔmt²Dh¢i ˜àG\ŠaA½À´±O|gŠcOO­U­a-Öéz7òÍÕ"%…€¿wlspúø<Ká}‘И€™›ÕiŠbŠ%Äy©)}9o\‚J&ãK‰lOíR¦Ä§Ö˜Ò^ŒKü|pÆW¥ßÙ-)Јß>¹)î¿5šÈã4“!T ´U|%²é¤Ïãx9)¸O}icÂ5*ᤲ3"ÃÙÖPj¢RÕÈü|©–FŸ?¤ÛZ|¦¡6 =°.´£öì!RB.Ew*œ‚‡ª)áD8[ß¿[’RG¦Àˆ«:¹»ÐH‡MY€ÓÐnÇç§—¿ÛÀß”íbVW°‰DÎ~_“fª8ÖšQSíÒI3D¬z&}ßEAjûÄqÂ5:/o¤—À,wk£8¼¹8É ºð8Ý@k4NcAC”ãç=bRJ·›ÑÒqŒkfq:#‹\©–­Ý\â†Óž‚d¥ŒB"­D\¢1§Þ^-vë˜âDj” øª=Ž6!¢’~n\X"cJ[@cœ6£5…òZZ5)~Öž8‚˜F'h )ŸBSR®¥7Ö‰šÕý ‡èíA«6To¦%XŒ¬Ôþpñ–¡90ôt˜ª^;kò@4CÓ„0)‚f7AœV’b :²¤Ñ”ŒˆÀ4Z¼ÀÖÒbp³,#`•F0ø¦·X ´wÀ˜Ý'‚^¥æ }jpÄyKö‹‘UuÙaÅiÞYâ÷-Œ@i¯z•ÎU×Òé€È,œ'’lsκgûëªL?/M°ÿ+öùg|'Ú7¤Ÿ7ã¨Fè€pjÎbV ûµI o½ÆAÐÒ©š!2BL‚ðŽ#€‡t HkðíÀ§ÿCßm¨vÒ¤Zsd8ktë×ß|ï2IÅÑEá0¯åp%³DcúY:4Å]N ½iZ˜ªöf „ €¥]‹4¦ƒ7è%‡Ü½Ä#wSè,©iddÇzÝ­5pÚPpÖ½É)¨àPà ,TEcÑø˜‡ ¤–TÚÖ¨Èh£!4ÂÅö»)8Bí&M¿Úí¬x-Nßi­D3&GÐh)B·j®¸µ”âóR¾Æ7€Û°w®¥óŽ¿¡J >s 1BœâÄ!Òø|Æõƒ@IDATšb ALÚ] Ð ög8Èì²þã¯9ÐBR½ó˜áS–Š-†&à4á ø6 âó¬ö8ø—xlÌz ¢u£­Ñþuñž²ÑÈôm,F`»"]^€^|¦·OAW$†¸gA†¯Ñ‹GŠl à#o"&DšxgÁ 4by- Âog1o™V• ´Pcƒ°ÒÖN( b¢üy¾ÿVÓô 0›<ÿ€D mÊmïRºó¨(m€’ ÎĺкÍNØB1 ΀ïºõBHÑ—vTr:ví~’!0ã˜(^ªns] BôfÔìt%ý¦ÒíPL¡”¬^1¾é‚SBPJ_µ8~£ë G°ª…éSpcp)s•èà@¬^j£7Wcj8Uã×Âcòh|%S´t´¾j5"˜-&r›LÎi6W-¼Ýx#â 1U`SŽÄMBÆ!U/$~+‰Í^­N„ ™š–Ôà¬U•¦³Y(M_ŒÏkç×¢ á½xF—ƺ}tAª½j¯«ÍkÁɪŠã7š§†) ü¿ŸùÎRj#šBJ€ìBøôC"xâh>û•ªijo«àxL"Y„UH½S®Ä[Ø Ìnßÿõ_ ¶O]›+HJKƒ¬ÚÃ@‡¦eòVE`ÀÔ4†üM¤|»?ïFƒt1‚ÄkLJZ MÀ3sY'â+i×eCi%ÌÉJñW5…I;¾ qsü]#æ¹ÍïOA̺šÞ†ékl7½ª+µžUI‰ªÍòJHû_¾SêêðþKK²âD´ œí¯T˧ÊS–nãØ9ÛÞ~®[ªªQÚD1 À,Ï*‰ú‰.0g|úi¢‰‚FŸJR[5N5äöá{3Ñt1%~úÒVºÅŸN;¨ŠÝ6D‹éÆig̈â-&ÅßPw¥™šj[áKán›;¦®”鈑ŒÈ‚vãh¦ì£‡€Ìgé7Èb4»d8²^4œm ý@H½•t ˜Þ¨ ¢d7q› B~ûÇ?þ¡ì3Ù0(u«¹S38ß~ºlÀð‰2U%" Þà–à™vUAí‚ÈøFï×£vEvÊ5ò .hœFdjÚy1‚­ÚGŠ,F«K,híDðÙ‘¾¦ÅæVfÒÄÓB˜Ñº·D|+ÇU‚üáªÆ ÈRëáóø-“ïÔȦ#×…Ó‚n@à¼S–Šù‚¤(àPðôÐÅÚ Ä'›2D¯Ýøªkß#ƒ(ÕÒ )ånž ‹cJ¦šþ+M¤­´ ¯÷ʲh݆b‹JÙ6ѾYI½´È·†.-}LÌ«ö˜¦ÖÃB¦¢KU‹»ê,ëÚDÈÄ)ˆM©±5ÒRp3 ’Š!ô€-÷ŧ½é  xL%¿ˆãÔ×ÂèðÝ|š¦CZ© `xÈŠrïZúm«ÚAZ r‡â•à˜píD€½ZRόÄ4hP ‹U[/…Ž“ïpv%Ï„ƒä!,|é…?®Uñ»qL8ÐDi„Ú¨-hA ¯«¿vrëM\#Oy7¯*eSæM/*\œf¯#’-– ºæýGDðt»I3š bì ~~á°dío–F´4oÇÇMSŽÜòÈpˆA@qx=Ò^*4ˆ”âCpZRG° Û<oUÒ×Hs ÖËÓL–Â9ó÷7K^£•Ω·›O-)SÒ°ícÃz-h—òyF@Hgl¨‰6’ 5DèÇ©b UKŠ›eg‹[ P¬«sé-³Mp€)k”*ù€ð~«Ž€“á4%Áô•ð5J;¤Æ—n±ø|•Ä.ïCL# ^Œo"~ÌPi+Y£ÑÑ€Ì À'«”vF³­TŪR¸TÀ(ä“ #/Ž e•TÙn&Ù@>f¸ÔY¤NçPƒ(ñ6©¤ ÎêŠUÚk˜8—ûë…°h ^øƒké•S"k„¸"CìÄqÀñ̓ÐbõJd¥âªRm}ǺAÛ¦Žãé÷éšb´‡¾‹§Ì3j­QŠ døÉ®Ëb•öQÕ☑uDkó8ɶC|"qRVªÊ×BöüT‘½-Ñ mÒ3ùžŸ7[µyV ~„‹c ˜Ù†AÄuAÑúUî0p˘ëÔ˜o¦.R=¼žÓÖI­E†Ï ‰X‰µƒô¥V€6&)ß&8;u|[©jïÔZ,£Ä§© <îñ#ÿPv¢žœÆÝ˜ÃšåD)+é%˧O$Іĥzºp:E-í,FH9ÂYë~Àp¨…Ç·D5¯Ä.ý8q7C6ЪÛ>p_:À n:ƒ#ûÔŸ¼¥¯T'º-vÞGÀÑkU¯M—†_Ð>ÈŒTSàÀ|Á‹£31ë€d‰¸ ˆÞðJ¼TU—€§€·^&f8˜ñ?“žÀ3Ì”;NâzY¸À[a%³ŸwϺS5T ÇóŒ/uù8Úq€ mJ]=zø&’êù&’rä5"g‡Ah.¼k¬q K#ví,ü+|î¢3ýps;¾®8¥ñq)чêo€ÄZxL&^€£±^¾f††yÕSLG ä+aí¶o¤Ú-AÞ¶˜@&Mo+ˆªÔòtÃGú~‚ìcÏk$EÖ_vò-€ PÝÜbž¾vâF€¯id¤ôz!„Y—=CòÑðÉÖBv#pv"12o7R5j‘¶$e›óJv'‘É6_rü”y§™¬ÅÖ§·¡˜!·€qhLjC©j«ZI—·KcâṗqMË^Âhgû{]R‘˜ohOÞ&])Y6²ÝúåÁ÷’Æþ- ‘S£,À_°^ZÒWN»#wüÚysÓÔ(6NoÏK@ª«h‡4”/hƒ”ôúuh+¥ O_; ÔK–ׂÃOPŒ6¦ œ¡ÝâÇ%Î×Z a#‹á¥â2Dú²t7ööÆß>”GÓž”˜5šoJ`q‰8R©^)|ÇÇŒÓMz(R 2&ñ{Çç·‘hi™õxL¿Óóº ˜øÞúhíhZÐz©Z@ÚD &hm¬–mbJÕ˜âv Õ¯Ó@1qüöéDâféMÖä>,Zðûþ‰€Ã4½5àíðvàÏü£‘jN‹DÒÅiKˆW¢±$0›g‚ØNdSZ|F~¿\Z®F4Ê£ àÈU=§éÅMçëÂ7—AÄL Õ¾• ¶…Tu@1Nû§cm È0èóBtp¸x×%ˆS‹)5 ”ºX°eÂ!Èñ^k Múm%Fæã7}½FD˜ríhª”vh\ˈ]ˆ!øÝ±GéuÄÔe |³€ükt’Âgbšµ„#K•úa#E¸ÜãĬ3¢uí8JÎÂÄ=zjö$‚£®šN åM“ˆ§àH_fÛAJä ÿúçÀdÓ±Iš¼ã³]‚G1*„œxR‚bœ&½È¶U G{ÁðR#0{gœKo;ˆí³w)¦4A¯Ÿ!3AOªUSÃ)Ågb†–‚‡kO1«DD ÷|ô}Cš —v?Ó¢!`VÒ¥DžZ)Å) ›ŽõüA×ß„ª¶ØFè§³ã@èkW ¤&Â}Fð§&ÀWà,¶Ò”þöûï¿+Èyì>iúñúî Ú ´ÄÚÄȳMQcj½ÔÞ~D™˜áKÉfF4¨Ñê|³à@ü\Ç F§Éw¹‰•ÚgJ%£U]‚YR8DÚz8¦¼^š¬€ßž@i"µ×… ^ZœGÓЕ¡E ’ÂÛë¼õjDXj®.fs›¨RKœ‡“Òˆ¯ÚßK•X_»-àSs•ŽÃ¡Ü&)¬«Þ<¦@IÐμ®sÑ÷éÄ1®TË™q_ÇÚf˜âÚU»^â,SzT¾¦]/&D|ë‡Ï†¼4œzWàónŸðÚ[€oJ‚®K#Ù„!;…F†ÃÎø»€ªÞ¬•ªò5žþkÑà{Ö`év–zŸžï%Ã&¯Ô £µ0DHN9°–ÀzU‘ÿcZ³’”Hoi£§€Ö‡ÈËÏöék4¦FœDj1T )Uq%)šÔk,víÍZ‹4„2ƒ[/D×-~n{'™Ղ™ádWì× &MJµ#Sˆ)ˆ`[i¯M`Ï4}]ýõœ¦s1|§æ!‹áº|´ù!º·Ž€,¥Ö•j˜Øè~gÝÈéhëJDP¬]c§ 6TI0f³x'Èļ–ø‡ñÚ™zÍsïîÍé+Gô ÒÔˆÖ>¼ØÑ"XÀÑ R’<²ˆYªšIªÖà‰ˆu©ÎR n1[%%í4‘Iá+!w|± Ž5u!ïb›Ë«&˳u)áG{G@ÐÂ-à#f"B œ‰;>5œ4á‹ñ½Q—ûy‚uM„¦Ë!¢.îtJʺŠáéjŒÙpT!R& DTâ-ìçZ¯º 7.¤Æw „ž¬5p˜*(͇x"­dJ—±€j»åOÿ}C¤ ’²ÞÔÚJUS)rœ|“g®‘¦÷ßþáîˆÙ’6DsEp±.%4ƒ^Krf|ë2‘Uy†|«jÄl14ƒX€ €3Zy’Oʧ î€Ú[þ,qMJÊ/24c³Z ¡ƒ”æ£Ôë;VJ_#} .å[ƒ¸”--Е8&pû—Î ”ЈÛÖoÿRÏâ¡„fŠ’€§ A³›*-– ”,ÌÂ5j¡CÙLJˆ*™ëÂ9ÿ­?Õ\Á] Ú’À ª’ÖI„Ó“€7;DŠœafÒ Bvx%^cC­×#Š- WÌjt1PK;ˆ ¶*CFã kÁ§£]oí¯‚eànLo± µÛ3}"ÒtÐ*5”ŸaŠÑ¶¡ •øÌ‘S&%Õ"°­BÊÜ9>µiJá>@´¶j¥”!Ä÷– û·] YJÈ[µ=Kà@½¯DÍ'BŠÓªNº®hÓAîÅ Ã3)¯*Þ>Ò÷³@|—ÐÚ| z­,†÷ƒÕþJ¦(µmjÈRæBÚC]Ž.©'Mþ5#¤qŠ j£µ×ˆÐTdH²-/n4œ)0¸8e1M¦]œ‰!-éhÀKùpô"$%`<ŽáV>UH#*%n%;Ô…§4K‡ïõ 9‹gÊÄU ’Mm4+ÑYº.¾5ºXR~©ÞP`¸ K-ßní£D¶?½ô[Š´öJfaÒa­‡ Ô‘{:Ò4»+ËtºþkX%¦Ë3‚'+ ä‹Ã/nUÕJ¥||"•B¬áÈùçŸBútKqXëÙʸF„ó¡}ºF È«n®Ô)âêÞ¼Õ@F­ßfýi»¼oLZDÝo?3˜6*p±1¬%ðKᬄiŒ®ø|ûµ+Y‚õ.@cÀ-wþq8•ª*Õ42¿^Aß)Èo¯R–BGЋÒ²üª®EÌ6e' §Ï´85åtÜO?ŒSæ¿cþSoGh:¦]Êc›aª6GPò¤:¾xH‚8ö±ÄdpRŽcU4ûØVœB)©)ÿ¯€šF|8µ´gïúy‡âŒÖ”¾v)À×Û ˆ.Ê ¹³+ÅŒ¬$Õnܼ ^ÌRh1éªoð®Ý¥¥9~³´¤f.³d\£=qÏìïn@gab¥ Ð ©«8qqà•9ßø-_—¼}œÑ¤±ªo[µž®Z’…·‰ª¿A‰ò8­ÝΪRÌð¾1Þ’ÇmØl7#ðÛI²LÞ2뢩¤+kOñ‚ªRâÈJ-ï¼ý ’¬bl\âÍêc›( ´ô)ëÍÓ„‹5¾YÎȪöæÓQbí‰ 9m©¶Nj€(~`ë2‘/#ûÝÝ#«]£‰uáè£ÙG i+iœ\Bsú÷û¶vS˜*~š©AR†3)Sòqöú)ÕÕ¬ô)§DÞóÔTµÙYâ¾<ñ&ŠÏ*×€º„ŽoãqY:ªµwj]DÆÜAÄ4µ×¯Ò{×ÅÒ?“î"е‹ù1¥í|š¯MùH|ߊÚ(¨ËÎJ¤˜}*ñ¶RTBkOitµ (óª.!Ÿ8šTŒš˜)NDµ`š‚”ûƒÇ–¤à­v4LòŒ”qÞÖI'®‘Y+•ÚDï-ž…+u.>SM³çh_ tº®º0ÿö·¿ýñÇ ![ w] íhÞp±ª¡Ô(àK56N®Ô’˜ékJY´1Ì ë  GµAz)¼Õ7n̤ڪ{㬴8qMH‹5‚‡Œ x{ãCZÆ\&vÕ}£vˆKÓëø|šÆe¥ÉBÙð¦l^¡6ÁDc]K;˜+özdw©³~ä~gk¦*¤_Eð»1âMhoŠ´v>‹£š#KÅ|£'øáÝoæb ži± ommD£3rüZz9Cpð£‰]Îoÿûßýêœ,QóÃ[ºËª8¼˜o¢Í#­QÌÓ¹ÂçË…%ˆÏà!‚á—uhš•œ—„•‹4âðî%Pû+e7RÀÇÿ¯‚Ùë[W¾Ci¤ŸŽøסÜ@LW×ëÕ‘uýW›HïÎ1íÀûöA "&²•Ä1x#´›.Mȴ󞦀x‚‰#3RkÛ.¤‡(Vj´ÆJyül `±RWd–¡RâÆ!À!½`ªwøg+ðùØÊBðíCD ¾®8‚”Wm–ø5U%ˆ .–:øŒü~¯÷vRº ‚ëí¤@× ·RW o.jÒ;çóZ)d´kâ€b6A³gD˜Ž•êªäìd¤bU cJÛÍw/AXR”˜lÛ–òqvd+¥€Ï óðÒE+V]Ðè˜8·6šµ•Lwƺ,¯Z×=ÊçǺxCt1´æªvu])Á½cÝL¾®56½^ ýGkP‹E¶6ŽX ÎZUðvI-¦”Þ½Ci´|R/®—5.èõÎïøÚÓw ©H*Gº5~ÌÚÐ4Ûø.–l:J˜Ô€â6ôì ¼*0‹Â#ì5‹PKÊøµ¨ òª•úS™Ó5!5_n˜é#3Ü’{= ˜J]OGK© j£•2U%"<„§cºƒ X]‘2 ”ï…¤À’-°0D;²àž¾€á¼iíq1O™B|Êi*B*éB볕"Û³…Ç'‚#åÝ•1N½éó B-Ù3àòSãKqrH©[ê ú¦–hÔz“x% ¤Ž& Ü 1*…8N ÒläöI\©–"oJÞn©éSiãTí t:1&CèÑ@HåѲ퉼.ÌÙ»N¸ SÕõ¿8©ò]l4!bRix>YèíV1¥bÇ)Ž–OŠN†éA§Ó «Ý£O¹Mà¥"¦xâ[²ÑR‚ÀbbRuk$«wšÍÂé”<&d)#Åtù¨§WÕÂÀÉ&.®T#B[QBx†f.kx'eˆ”B š8Y%)¼éb-N1¤ÆtTBÜ-¸+œ_ŽýAYU,`ø¬4‘[5‰§€³}ÄÖë*PÝt)ÁàL¯.éKÆLÈpx4Þܤ:u½<Sm¢ ¹Èñ».´Äw„uÕX—m œaïe+a"À)˜%õ ÌóÒˆß,)æž 5Õ&jÁ¡É Å¥ÔŒK§¥,>dÚtç7YÌ,Axi¯¿jÇiÃh6$2¾*oUC6‚ “¾~g™fÕhâŽ\*Ž6o)‰ì‚D†kìfÚ§ÛpEt¦¹.œŽÃ<5)1Ç(`»ÜÏ)x|4s¥‚תêm.AH¾)¥{J˜I9‚ 54-FpŠ«n½¦DÐÞ ½¤ú&Ѩ+a²˜ªõ*‰Û°|4ž<)4±Ñ8Lµ5¼<hJ—ŒÜ÷[½Éºü·¿˜ð­Dȿ糮hA³â'Âà#ô­(È®Ìçï5t1šøÎÞ¶ Ž©×zÌòÚÑx1Žˆ,à‰8¾®’ß'+Þ%ðÈ84ùhKUMá5Úß¶!˜»hºX›ðÖà•x½.¹T{V’Òaª]‚XPŽ”ïÞj1EW³T•àÌ’¦œ%¾¶T ‚‘ 4²ÛwÞÌF Æ\ŒærjÔÛE¡¥3µJùfÍ¿]Ùª;Ô>2f™n7h:¯›WíöT˜n@¬´w>q%¦´RÓu¥Ðc…à7K„HYÇÔ• d¥#ýý‰dM¹}ÇÙ“ à½HÐÃòT/•ª’ 6®eÄL̬ÄzSãYsó pòfy Ä-YÌF <®u®Ý¹ì¦ÝPéé+%›ŽV{¶ž'µ3éûú É*¬%°Ò¥}¬''ƒÄ$,H³#DˆÌÓAàáNšÚ¹âû&G®:µë5+fA]qR¦#uK˜6o„*SŠÙMv@œJ|âqZ[¼ œ8ó>øO bƒ˜ѧ`Ic„q¼{g{ZZ@Á,àSaDâð¦•{ JáÔ .4ÝV·ûŒpR`é³”&®]K à둸cÖÞ %i:ùÈ[ìüN‹´ÓhÐŒJ´©Ætªz]h¹5 &"†,Jµdð Ø{ Ð;mqhã ZL*°†ªÀþ‚ΤɨÑ"VM\ ©ÄgÑà¬Æ‚ œÇ#hUü[°R"||g ±ƒ ‰¦°p^)"ˆcò!Ôà6aií)¸ZT•¤ñyf ¿ñ»±Ë)ÀGÃß ƒS†k‘7QéêMXU%±R®„ :ìË öFéE€ÀÛ9~C5FˆÓ+ª—lCáSRˆÉ´í8ÕØbAä<ÂR1ë]Я+¿Cá›»ÝRžø­è´ ¦‚ìP‹Ö’á;ˆ‚Ó8hâuMó]Z'ÒÕïyg­çÓ#yº‡º”_`•Ìr'R†Ób%øi¾oy™ÛxÕ,ÓÂJhõš.+ —¦Ï³^ » ŒSW"Jþ~¹¿lVLd†Ó&Èvé$eR%x4Èíø¼]'¼|>é}p9-O!5x‚‚¦×.õ›ŠR)>5Ü'N¡¹büîJà…ß>ÑüH#ÞnÀð&F+‰™)q"oP¾ªÛ¨¤eÈ@ëR À™sñDJЩa 0™€šÁJJ5jk4³ f1?ޏ®@¾ ‰‰#ðS–â\øW)Nþ*WÚDq§+uÞÖ†ð˜zÑÙPLÏ(­šl¾MìþÃ;`ƒxœ¼€UåuÁ™ømwáýF>æd‹™k¥Ôø¦{X@‰G`½‡”š 3dÌžþçÛ¬d1K›ÛÐîІJJ½0µÀû(UÝP±–³Ù×´·XdUG©Ê;‚Ô%ž%PoÛ§F]éà@l>µu›Øôñ]K²kl¢RPoÈÙûùDDà[ ³Y‰§ÎèïÇ¥ªÒÆ-vuI5Z&Á1í“Bøë5ªò5 ÙûƒF0©ÔðõbFÆiÌm̪ùp„‰ü Qk+¶£‰ëݬJ½!«ât“ 9Š×Ð òþé€`ñ» Dªªñ¯%ÕóérS¾)ì!†(ø“·”y<©§«dêa¯Ž ‰ámÏÒLAUÉ'M*67d+F–jìlb#øLŒÓwzw-Ål\ÌĪ1 ±[ ÇWÿ9ÓÅ·xœ´ö7H­R7ƒ,ØM67÷¦%ƒè o(¼m£)•†7¥•x¥ªDð‡”¦l4NH? ШÁ]Nˆ9Žéíí)­Ê; !è>øÌõŠãÏ¿A4äÛ'È2U˰֓RÆ1Ë;†ö¾cGëû©ÆIpÇ™&Y¥RÁºB¤Í Y¼&“æ ,)0Žï¹‹GKGÚtœF/­””åJl ôk i'ˆã6}CAtiiAqœÆAXÎ;«­€@+ކé8LÊ å=Cð-¦QL Gì €JÈ@±m¥ýÙ5š´•p´óµh¿ç;¿<ô£5ˆ¸.&eµ¨ôç|HS6®e¼•ø5±FjÒb^º)ÒÈâ0 ¬€Ghb²È?î¡UíƒYo>Y¾`¥m¥ð]NR1ÝOiü‘ò–l„`:JŽÀ³ÚãH;ZA‡«¢½ã€©=gð=_ÂF+‘¢`j?æ.ÕÈ6Z¬½jƒÈ6%ÙKÿ¼N”ãØ ­¡zቴ³H $‚4©`)_ Áª4‹™¬q„ã°…)FˆCníK98a²âÎ2ͤ§W¼ô|íú !éïƒ$¦k óxê×LŽLÎph¡Åð ¾S>/ f-ht|MT\™_¿tÂøÖ-–jk‡M„X›ˆÝšžxûø®2d†ìý›>Ù6ÁHY-Í©]ÀÐ&(ÇGPºÝŸ¯Õn)0r|x:öaª<‰;×@][҃Ǣi‰ÐˆÚ;¾XMÚ,ˆØR±¡Ý5Liòéć³˜5’‚R‚5†‹3½Mñotg ‰qT) ½¦tK¼ïh”9{;¤P¬‹>„ß\qi²â6YK À‰´F²Öˆ£Dƒ Y¡Õ–²m†V¤ÂÒ0If°>•e­ÓWŽ)EÖo x CVièÉj:Mb½Â¶”“’ ì&SFZ;«€ 0I Ë®°”Õ= }½ëNfxAÀʧ©^ ‘¶Êb*„Éjý–˜æ²Q­ô|Úæ\wL¤!º×ÂímŒ«ú,²9¤ßl+«àÕ†;;RjŒ”­Ö:FÙ«Žtc¶ô) ·ew4±p†X­Ø`˜Sðý¤$NFÓI›P‹”V±-ˆTÁo—˜  HyŽæ8ñ­ó”ç°k£¤ªÌ{ú9PÚêRŠ ÎÖzs";#eþ3„£TU)1²û(å‰i¶Ö40ž@!Ìȯ;™jH FÓ%X‘óÏ¡Z˜L*AV H ˜˜³¨6}šV©[c[sãCc’©fó«%`žÆZ ¤Ö”RîV˜g%ºÛžŸë¬½6>¤™Ú*˜ºöÝ,¾ë@ÂJ€¬«…ñÙúêû(ežR¯IåÖ¬¬(ã•c„ŽÙmf<±sÒÔ#«‹ ïÿ®rª:½  ŒÔ×—ì&‘â/Ê*ÆÀcTÙf¥D ã €—Øâ­4²ž‚•Ud¶“™ž¹¬Àt|˜IcÔ¨,¨Û3ͽ%Y2É6M&•û‰hâ†!`>Û •D–…K)X] z@\îüÞ¹Sl†Ê™(·CjM1z «l¸B%˜&ìø®HÕ<똠ÁZY!Ó#ßÀD8¥5ÿ¥*G*äf%n¼è‘pÎVdã©…s(ëhÊc„Z«¦J¬—û, Ð VA£/ˆ<3QFPøXÍà­ ¡´Ó+ÉÙZ×<#1)‘˜ÖdÖmëØ¶BLz½¼'µVb’ºÛ’âaYʺ`Lΰr¼­”p̲ŽÄ¶€,°K³-ßÕa„B‘a ŽH@ðÑEÀ &Ã8£­5}‡–R(‹ï£ @cÉò‘5Œ¯>[‘ªeØJoեޥ¬ª„TÔ‘V>€aš'f«T«!­­eaz«0ÒÖºC™­ñzO*'N–rzšz a²”ádoí™þ>¾¥´óÚÐ×ï,ª0µPž‰Â¥­Y)¯Š î>áʹÁ¾4ðµËœƒH,Û¯U˜erpW‘sÛx+*V4ÇôYíJ)wÒ¾*âirSR°¯*L_¶'X»ÊÂ+ÈT53,Õ]IÕ´\#…ñÄ*‡U) k Äl~Yz¼€eÝC&u”í~ŒÐ(g×¶–ýíŸÿüg^Æê¯€Òµ§4Œ¤D_¬º–"n&=A@¹€ ÔV%aåñÖ4ÖÎÓ–e_sæv~Ûzå@f*†º”RÂÁ–Œ¿xKšV²1ˆßm‚JšÁ…äi+XõÙ<;EåZÓl°ejK5‰BʺªR| ‰¯ÖdBv¼mƒÅWˆ0”Û: U¢ùšÌ«­‹ÙèiI ­pÛ“{¶² ­²J€Î˜X iQÓ€.¢™3lÅÐÇçÉÇ6ŸJ¦O`•x‚V%¢‘¦æ¶í˜x¡œ'ÃüYÙö½¦ÖÖAªê燬z)Û˜4î¤Ù€Ê[‰1lk·*YŒµ`’϶²‘@ØG a+ÊÒÿ¦ÝÚaÉøØæðY¡©"i&Kl%S„3™¾7ƬEzå[]zWï!Î-¥Ö1¶]”“ÂJª%HÙÀï<ø&·ªUh<ζÊe1añÚÁ²Y¥Ì¼F@0\Gw+Õ ™Z¯ï:fXíÜÚº dz)4¥-lucœ‘gúïüJjG™U£’©"S˜- Eæ·|Œ­¨ÄY€.¼’Óà[«jV™+„.׿,¶J5 +ò±:TíZ• ÀSš˜òŶxÔK°š<&Rü7¹Â¶ k}k¤VP"+ÏVm©ªˆs¬V¶5›ðì`!ÅÖû‘ù•†_OÖ`{’m$Û 1+kaM©… n¦w‰•k$¤ÊZé 0`é­þW“mÎÿ;sL/­.¤Çƒ³-«ëa‘5Æ M )i‰ì ¹|…¬ÞvJd•¬^PÂúZÉ€n£a ¬]ú:VeªêÕ:¦- €ôè Cœ§ ±Evç:Vz¼6Ø; ²`(ȸ!ÉÁ/‹´¾'’}Ë;uʦÂ$ Œ·mξgrÎÓêÎRT‚¬©U ó¤ )x&¶ÂÉðm;Q¤*AÓ`›@VUIVÄùIVx=5u#ÛnlV]¾T嵃·Í¤Â²Í 0r­›6«4²õ­Ö–ŒyÙ7ª­èU¹Í?Œ€^êüiØÆè£:g-s¬AŒöù:¶ÿl B%x^™¦$üHƒtr2 cü¨}J YcÈ ½6 [˜¦Ø7)'ÔkÄgš¬8øœ#)1 ”çùÎC™ùV€ òù3q!x€­¦©ºÞZð¬Eæ5•R…·í&µè%ÀËr —ôE6‰’ ) × XJI“˜ ýÇô€ÂÄ Æ™ÞÚ_ÿ#; &YåHL¸Fµ°ÚrèÔÌ1µH¬O$OÊ6+²õÒw…3„)Ÿ )Å;OÙ¡3O̪ñlcLNƒd•›•C+ A8]²üËúR³Rzí¥Oh ©@3ØŠÆà¶ݤÚ~,aN ]Ýñ¬;ì©ü2jáÉ` ñ|ض¯?ŒoNµ:êBÓ×…,J­ ™@ µø^é˜ô­Y˜æ¯i-¤d€ÐÑÄVÖƒv-nfYb2‚ãk”Ò* FC °…ƒXØþxs[ËZÕVnÅkÔý˜çfÎÓ•0¦ ãL|Z~¿-;È»eÒ÷[÷Ã$åL”\³ó›@O©¤ÓqÀ÷~*$¨„ÌVÔîn»„¬hv“x…ÑYZém”çKÆ7ž[é6ð ZeÒ:ÏÈx&hµu †W cÌIl+lEØÊA–gÒ#m …£Ù–Š·f2rÛÕ¦!à€t°XwXª9'ðÖÏ1ÁVYa+ò·µ6†^H@옜m{Ķaš¦ÚäøpµËRâ[µ­)&2fnUX-YØšÃ)øþñÕxùÈ6$0†lå0h<…ƸFØ @ì°”5z}¶íÝvï+dr|ï*˜RÀ´¾S!Ûît5²u½âk‡ ¶b˜ŒÏPV¡UÇWikl¡„-™/Æa<=M†ô½~qVRÉæ|ìUØ%x¦ôíÒú– Ç[1V†M‚QâaY1d=Jk[knª @ ©•!~n²é'k6d€X¨4ȶÖpOD8Òæ TÒ‰zaU¶;ô"L: ñ˜×ß̶¢ ©µZ`1™ò”:ô²¦×.FÈÂ|8X+±Î¯\43‡ ­Ÿ¯E§^ Àr!Â(¨F–Wýhè¯ùçœô”|" (¥#­Q;k .Ö€3è(€Wx&t*½ð9w}u¯<†É¡óë^U>jïÿõºI¤̬œ§mÈX±-% 7§¬°Í¼Õ<€UJIT[jW¤cçԥ- rS.«Dhd˪h0X•y6ƒ-¥R¥ %`Iã·ÿM¨V)æ£|3Tø2Ry*¬;€œ§#pÓ¬!›¤©¬é•B µëˆ™oUH 0‡S|¿|éߨ fK_G+>&7ëB–>çpæJÒ¬¼³ôþ—Z•­¾•hÄ#›€7S••§ T"ÛÖ*e[¹ YV•cT‰ó*”ªÊVa†M…ÇPf’¬Âj[‰V6sÛ°ZæVÛƒUmòúVEf›˜ÛÆàÓÁçF†ÑWø—œ‘ÿNÄ'ÛN±ÉÕÒØ« ×£D(i°æ´AŠNÚ„ÖFyÓök¨l½dµKLçF²RJÃ8°Hf›FI¿ÜðáfÛ̲‚˜Oõ%àÙ1kÍŠ Æ7§ÂÚ½Wá4Ê­^ãÞ䶪(1lëHc XÀ­5ºÜY:Âó¼#}cóì!Úêå±’XðÃ檒Áî§«ÀôˆÉðÖ#4è†DîBàHÌ ‘‚Ûô¶°¨ÈÏö¨¿zUi0d¶bâcñ}» oå ’© »ó m+‡«Y‚Ù|(Ó3ÞAÄ@IDAT KÑ É“ºÃ9\§_¿»”róUÉR <ÌAŒŒ¿ù#h ÆÈÏÍk2Y)ÊH¶fSbæ~Ù­Š€2¾÷¡3î )i(;oC)"i({á1é­ñü™+kå­ XI•Å0ið­þGá˜Ü扗µ}Ù"–…‰µÌ Úb¦áÓH|þV<¦ìøpªÒÇÀÈV-A3·òQ庬°èê6€/<µ–ʧlV´*²HJXGëlcJQÆëQ6§•/ëË9¾7àº~^Jå‚R²Öcw#ÞºÚ£¾2­¹½Q %€·Ò„• dų¬ËÜ4‚@ì ó!Þ·ô¦"빨ªä8šÀÞ'*ʥǴH}ý7Ÿm #:RûV/€¦ô£¥v”Í„—dp]¤Vå 0†F­^úZó©J*¦L¤0µºJ‘[‚è «J @ÌÖ®”µT|Šô ×”¬y"™¬è®”´C¦0q·G`¤*Œ´ÆóÔŽ@ ãëÛEEÒ[‰Æ– ØR˜^½0‘•·®¼a*$Ô Àó|žiYUf hàÆó(¥úýf*É0îd¢v¶‰ßTáE€¹^¶9ÐH`€9à#ja-e¥/p÷†Ì¶0ž _Dbòá,Å–Fä`è¥qz)d4RÕ" l«µö3Iàñ¥énßIðô=£°ÚFÊd2½8‹3Ü÷§ ¥ðÉê"Õ¹Ùʪ•¥QÞ§¦Ö²É¶RJá­MRÊV c ,šÇIýIÕ|$˶*¬¨…ÉùØš°ËiëÁ4[YÑWHÃGØÂR€ÀÐ d§Æ4pµxY ¾ÂFj #ËÂbøºžŸdºôúHŒ®ÝzÍ? ;…µeaÎ=ð,™Jw%%² +d‰çÖä!…ȫˆd@³åßJ¿3É/”9¸™má¶S!åJ¼$°,Ò)°r[Y˜y Ÿ˜Ru§œɉc y®Àöœ…RÔ]*ƪßÚND©XÉË_˳(QK¦c§¨ªB dɈU l›9Áß¶Âú¶.K0Mc¨ lÎ|*iÅDC9’X¬0€—5|ó{”žfẺ:¾*ë²Þg‚š"5‚%} l ”Ôˆ@#$A§«–°Èd9̇Ô&àL ÅDà1¶¢ÂL’åü®øR§Í²|ìª çÑ—9à¢FL[YÊLrÎ$7øô»¿£§aTëÚbjŠëéÒnÝžBJ†HÑ0R‘â œÏꛃÈÂd&³¶e§(áZ‘B/©€•›`~rßï.¸a2§A€FB6}«TÙj‘ñ¶§Á¥t”2‰ªæ‰)‹ÜA0aïœùÏ8“¶ÍÀ„F‰iýïáÈž‡ê/ü(•C îHïJe~<Ða+’@ÐÛzxÍ]{˜{újY!F¯whå¶yÊ µ¶V-ªò¡â©^;Ø´›S‰­¬¨…r†j­0`•bCÙµSH‰a¤ÈV»ãà oK¬¤¦@J«°­Vw3sÈ_65МÌÉjQÊJ¯] Tí`½’a:2 #ÞV_'ň”ýG>Rª0¿€cdmU%KÙ¶v­x1Y³¡Á¬µû—rº×ËŠ1!²FðªrsŸU¼í¢Qñ¥ò$ÆÓð4õ³[dµ4Jè­xYѶ5Z[%ÖlÛblájÍ)0™ë[*± tÉ (G¶)‘€H ¤L@ßÁm;ŽÚ1qŒ¾°Phà\¶1à•ÈÂîÍ—€,,V^ïX³%îOûÈ<¥t [ÃHâåfåŒá™ŒN†!ÿ›#×´Ot½¤¥`¥‘¨ÊÚØf[êÙeººé¹u„•ÔHy}sèÛ’˜ÿ™à +ï6ÛF‚ejÍp†­ÜÂÍIÌÙ•VUå|ØZµ€È™¸mVž³ÉkÑ tX§`‹±åC`Moµ …m-Z•Œ—jK\Û˜fkÔ UÑ`œÂ$ÝÍ6 ÂºØîNðHU|ððîó"‘ᵕØÒÀ"OUJYYµ" F#2gõÂDÖ¶b÷SUž œP\ïs“€Zí`1ȶ@þo’F¡uÏôÍ€'`e+ÊbŠÙö¸ó‘¢¬{Ø"« Óë%ËknVAfe"`VŪù«½ò³à]£.Ķe{Fé+$X @ ÒWBVز€î4­È)çCÓ1¯ë±mìeÍàI\ÀªøøˆÕ½*ÊIJ›¡Ã~KÏ©Å܉ãé#':EVÌÞ'OŒ_ŠX¯ Û&l€²‰ëÒš'HS¯3Ÿ3¼Þ±¦êLJB¤·šFÊ*‹ñ&ä&ES°B6,`Êü71^6gEP‰–Ö¨ìnrb²FʰªfÇcÞ-Ü ­4@M¥‘1e•ll¼ËÁ´©S#le"ˆÅ¥Ï„Ø6· 9°BPío¿ÿþ»`sIGÔ »2ÛJš·,e}g"óÑ@Pâ[mIÀV”Jc+ËðZ my–5ÞïL¿NõýÅG‚!™……rQknR‘¦ìU}–¥ˆQô6¼mþVÊî!e‚\”ÈzβBµ¢íHÇ \/+·”P²¥±¦!~ÉšJáÍPk%²¶ÊêH0^ ¦Ö•ÈÖz>”²¶•‚8²*«_×z¦]H#QFjäøJ±Àô¥™§ÕÖºh~[zU=š¶„Fô1¨P¶ kšùí)sö:Ùª%`h„ó±åŸy&ÖR@˜à©ðr¿~h•b¢Dj£ë+§‘*K,²ÝñÛÐ_áB£¶)DZ9ã‘ÁΪ ŸRÐâ Jd)%Ê­¶.bÈRJqh[Lå@žU™AW’aÇÛJ5mV¶ «ÅÔT-±÷ªÏhJ[kß9ÈæÏ!e)Y@ÖÊÖ– ±¶ÍYJ—¶«šñ›jÎ|ò4•Žf…‰¥Ú•K‰•$°z-)¥à‚¦Ïš-ÌÙ ³…{1u±×%ñë7•rµS—VŒÚº7> Ûô@&¶²ï¨¶Êé…îd•Û†‰; F îK£ái€'ëŒÚ‰ÚeN/øl …|ðjitÁ¿2X kqÊn\Ë_¯¢ã±"[ SßÖmijOfr+F“—ok•-jD#ð »"˜yO”ç²îk@F +!+x¶UÑ0I‰)kK`]Ôh&”]¦êBi‚Þ>k $c²Bžù[ñÂé•wxä¯OœO”Jó6•ª¸?cû1¡<‡5ªé¶™XÆ*83ɲ¥ÆHã5 \k3 ¤Z[‰W^»¶™¯ «PV ¼§“sÒÔw픈Ì#}^º¤H`e’O×(ê›L*ŸV[3ø‚,†9=²ª&¬#&ÿ²)O³û†Ëb"SZ;¬Ö°PnÝ´—ûEvç ¦i-2± ]¶¦_U/XΪx€ID¼u|>ñwüóÒc€p—Ó6¥©&ÆxWYýö׿þUq&©U"#5²¶Àj><€¼Ó~~`cÍ&0}%æØ©da©™œ6ßà@Ю黂·œ@ëÖZtûªÈ¤*wÅC€XÄ sö>u®Æ¶J¥ [‹<[1dabxׂì\üñ”pCöÈw|¬ªDG ‡³ÍÁÿ?Rµ3L¼vzÕ®BcxVU¶U•ª%¹Y‘ghUn50Y<Ð…œÊKî8)ëR Fö€ÂLº®Ü¬”4[1²°ª5"HÓÑd}õèiJU7¹ml݃è\ñ¶¯3¥¨‡ €ÇjU-"Ûv@˜FH5†ƒÖc(‡‚ÖžQ¾?&Y“XáœÓ×W—âG‹æQX‰lå¶RbnóÌ–@དྷj~kX Ø<™0O,«Ù¡ðÄ¢-ÏÜ8d‚Qbí5öXá¦-¥Ü6gëR¬Ø²"–Âp³ ©¸*šd›p%xd}éëXVª 󜛦1u$+ÅGÊ*6€¬×Õ–s˜¸@Æðqd²5M`!<’3ñéw[û@`†þ|žyÙ:ÂHÃb!ÅD`:@†±Õ Sö Z™è.«Pd.Ÿßàæ¤[6e[ÙF²¦”Í s![h x‹Ö.ž8½Z ó‚Ó…+‘²Í°mU3ðªºmX(¹ög9™Œ¾=?ŸtÄé¥j]aµÓÉ®ü,Í™Ì2±©'Õ#°Eæù–dRÕ1}¾[”È*1Oƒ%H£¤{‰ +¬#‘u?™LÖVÉê5 Pž¦”^4ú nÝ­liÌ (­RLJ]úóÐgÅ'A>°OP&gŽ›µ*aEtdº´…e§GÚ*1d€@SÑÖZ ‡s°¯LI¶”ܬRë¸^MUVâ/7Îñ )sØb"oég’<ãɘp@n r²uìøHÁBæû®ð×¾ m ÓǬ„’ªð@ƒ_ú,4 àënµÍm…•H‘ !+l[oæ`AßÊ'[ “[oÆqê››Ÿh¶óœÏÌÇ)§¬¤vá9|Ñé»O8gèߨ«—¢û%ÀïÛ™)&™UcÓ¤!cb«PØ6(þ7ŸÚ"Cú¶38àW›'’ƒ •Ö<ÃxUH%ù ˆc”Ó(éב0²ìª²€ §)ÂHYÁŸùü}“56™ZŒª¯Íéˆwùéñ˜"q+«+w»ãä&+˜°ª6¾mÃ`8Í’!\Õx ¥mÝ•oÛ Te8`Șw àpóUn%È÷ýß{…W+LÒu´·*—*ÿbY_ ª¤´£‹ .Ë €ÖJ€5Ú[­JJa%™ØVˆ„õµÍ 7ž­,&¸!)ÓÔ¢-†l)sµðRb*´ )‘yâxµNG/0U±2¡Á00R6’ `Ë*=œ Ú^C§8cdˆÁ÷_mÕ‹@_…#­²ù›n€ÌÀ@ü­û"Õê¢c3ÐÖn£­Ÿ|s£GÖ:gµ"2s«-å»Å¼¿„5Ø”ÙZÒª£±ûOˆµ¸ÉsÛ”lLcò¡dU#©ô­õµŠ ;uUVž›p2«l«r2ýÎRäJ– FÍ_ëܪrüÈÜ)²ž©1`‚4MU¡î#ÕMªµeHm[Ñ6A+Fm©kö¹Ã¬HÝ fž[€I PÛØ¬—m¸¬rŒµ.4ÂÖqð<ËÚâ?Ö÷M°­£T&^ m)žÙVˆÏÄZ$€ ` M.oÍS _ªu4d%f`•2`<€Œ¨QËvRL2õJ#Uè‚WÒ¨H[«­™‰EוÒ6M²›?wØq|B…¦xQ‰u^œ[ÆûâBªR‹ôjÍ ‰ l¤ÄY™!玠1VÕväñ½Qaà vÀ1¾~eµk”^¼1¤ZLÙ$‘§mG˜^”þ Ö©zó9¤­X¨ìêÃùvY ”¸4|âSnÛ›¬Ž)#­ÄÉÔ¶e ì^¤ªâпΨE/V'JÜáé7?FÊðVå‚¿ ð“C­è«Ú0HfE‚À˜Û@¦‘bÂ9™’z8+šb-lÓl5*“µ©Ò ·Õ‚R»šò_¯[›_yÓ6 rÛñÄÊEµ]&1cHŒmݛǶã[ÉzL0T¶y¶Íí«:ÿÜ0mƒu!€pVµw÷ù™mKóÞrš‡^*%M+›C…ekÚãVë¼VŸaú¢¦Vž²Ê'”hd4¥0Mb)[ÓøîIc¿Ò)ì4­„h<<,0< ØXñoìô%¥X¶F¥d¢6+@¬©,Y݉&³")ea1P»U«Ž®½G,k»!×H‰­T…¶ÊÙÚñkd á“)ø:"u‘Eæp‹þëƒL)[SX俤€m%@Î5……*ÝX‘¨ò}ÕR31R‹1nF¹íë`Ë ó>/…½0²|2¡¡,ðÂÚváéù«5UÏT FãoÑ©:»“[™'À³RPi€©‹ŽôªjD3¬Fþ‚PÊðH…0 6çšÎ)تͿTHoÈÚçì–ð„\­µS+„‹ZP¬VeÛ1Âdx ¬|k@!2MâO›ï'¨*úMØÆDÒ46’ç"¥UÔhÌ„ž‹BUî@J(ÇÔ—¾ƒŒæFcf& C™¸1vv²4jáFÕˆLä†/ðÛeëŽ/hú…’Æä‘ ¦ä-Ü6[ 50[VµnHåEP*/…I¯„¦BYášêô¸¡yŸ¯,Ͳ¶ 2|åMÛÊ )»Úº§¯K>¶¾ÜlWËaÏÙYfµui˜lgNŸUÝ)—ª AãyÁàm)ûÙÔ‹W J l;Ãüõ4x…”¶VL§s?(Wèÿ<2‡ÖÄôµ W(+d+¬—5ý»ª-ÊÎp@Ö0žx€­cZÓÏYwA3&Û|èe­f4qåOíR¹”ƽ!ÍÙ¨ñâëb[móìæ•p“M)ÛlÖw¼ë}®«¨‘ž/³Ú<¥(ùÌ<ÏuÁ;¬m~HN€ìMãC¹U‰”íjËbÂÑ̶FŠLÈ )$ì>uDÙªt©¹·7ód»2¼ò®×–?Md ¬$O[Ø+-›¯Ü›f—JoÛl”B­ÙJѤm)寫b[ VxåçY&“…ëB„ɸuái¤0Fµ%°Úöfº¨•¯5’S|[¸µ°Ùlb…á¶jÍ` ­4 mzYdÇ<=îþ¾‡H_!“n|›„X¯·iËv®Üª —m6¼J[7f-¼rVd!%:ˆ5€á&l9ðqŠ›üÜ$Á×à\/• ÷èRÉx† Ý Î0·®?sÙ°rXŠÆÊ3ŸZ'£”@b¸¾ô1[d|æUeÂ<ÿÄóái“I Ç÷ç϶©Üý[Ù UVUY däñýn)ãùœâûP0‚æzœ%¬»`CL‰/Òœqïï rà¯ß{ŽLÜæ' ()Xìq×.MúdÊ|)«mž½ØL²•·b€ùÃæG¾n°Zðôû«Âéem°’€áÉÓ‰Q%ËV´Å”Â0´Ò+´¦j”@‹œ+·âY#eRëxk$žfE†1’è˰‡ÕHÈJê¥E¼­i¼“<6­v@Û Œ©ÊæÆa[Ê y²¹Y‰¥„ªÖe1âÌô½[Û¬º[÷©uL«¥Éè6ð0] sI‘ż% ‰ß0az-~ûóŸÿÜ!‹Eõ2ÊÑ6w€‘ÛT%Õ6Y2Q3ŒT«sŠså@/d­• Ø Û°ôÊÙb‰‘¶’UníùJ`«1Ô&0ÂéÒÜ&¿>BYåö³ó&>¿o CbY‰õåßñw9¾<7 %àÄsK'›Ø[K©°aˆ+¬ÊªÐÙeÄK1눜,e·úŠ ÀS¶¨d‚u¤•ûëR‹N‘ÃLÔÂ9¼nc"µÞîï6Uä hÝÖ$ý`³õ!±õ·¬ æÝÈÙ:s`÷c"%¼¢ñ°å®é¶d²¢Á¬”Ö”#1‚I1>€d¥ÄïC}šaŸ_瀰{îß–ûn4yJ³)q®Ìa![à1SÂŽ¶,ÀAl6J¤mäôûãOª ¬E¶ ZeÕvᘘ eï^Û£¡¤Ó†”ÆR[ù~ÞØ iš–ÒË_÷WD“IM [¼FÞdþ0¥¬€™Ð4a¶ilÇ7¶Ô c(‘lùH)ûJ‘¢Ág›¾ÕHdé1‚$înfJ±¦Ó‰ åN§ñÍœ†iàæ$àÓÈZtÞ}¿!éUÕ·Ž•ä /åA'&²‚}oëb+†™Äðl¼ZÀ¢FÄÈøÖø+GþPvçšR†éÅ”™(X¥¶½ ? ²¾¬º7åHúøtmñ4Üù7(W5VNTÜ@0 _ÊR D ¨ªÖ†$n‹±eØQec” iæYÏù­*+eغðbe¥ö¸|}lVt ÖRVSÕÅ^‚&¤Ȥ`1ÐVǬæDÆÀ” ém…Uk%“*kÛ1Ûv ¶x%‘,çSÅ8#±ˆÔŽ^Pf+³ª¶seˆÂd> «…sËœC!ß„§ýSžC%øköëbÝ3s¸ë ‘w¢ÏÏÔj­¹Y¿#œr[yZEµ¯2^_W×EùÁFfë8ýËÁŽÓš~}l•Õ– e7l1CU누k É 3§™RÄ“i9>1 AOÄzÞ¼û-ÃßV´H cëøÃYuºzј¶r2zÑ´xX4Òg3xöY£©Öš^ªh;ÃΫC [‹Ê;ÞäxbÑ„ô ,‹Qh•µÅÃô@ÙJnõ篈ðõ"ƒ+$Ó×*Ê–Ò+mãYÉ~ /E/eÍ nK Ô]/çê FU…·ÿ€@´­…l7l[ ^Ù^ƒ3$ …c7¦/²ûñq ™¬iÙ9yF6s¤h€–eKƯÅ-ú¸aU_¶@…>³ÞCÛF’…{kº±K¯ëÓZöµ5ƒÁ\ ²[ÅÀ¢Öj ä Ð3´½§9©Zw¨\Ì“F˜³YLÛVæ‘)ù§¯5 7‚¶R © ­ðéô U‘ç0÷8¶x>+^­ßYÁ¶BŸe¤_ý{' ÊÊkj›Id¸©2!ð€ªŠ‡hD¶­ <¥«vÇBvY›­¯–•LVä`[kÀï…½9Z0GLÚJâzT†Í\6³©b*ɰÚ&±J囼ßab(m9HYo3×CÐm”mÅl› [ž=5)å.£<‡ôøÚY3qEd•SVRÊŠÏMJ­Ð"0%+ eü^'ÌZ7dJä~d8)’Ò:¬/ó%ÚÕFNÉdžLDÛÌa>áeÕr(•kþÓçlm’•cÂõÊ<1&ÀÀ;©^•L<“‚@$¶Ìj€øÄµpŸ²aY½„ÛKS-Z!KÁ¥`ÁÄŸ! ´V˜ìF–yY©4µË“à ñ}Hsjš¬è 4k1‡€`Aÿc» i$Ù<•L ȦÔzOйoa)LGÈÄZ(;…*(­}{†#7mþ}Ù•å3™*š¶Ö ‘š’õW§€ÁªÂÓÀ4¢kTè?ŒÆcúÂ)1²E38…,2+n3¤¯V™gV mã¿”0}èM™szL·ŠÌÜ: àÆ³Ž¶‰“­W2$O`/?}G&³ âJ´ ¡ìyÅ#ºú²ÜøàÊm1øRUÅòÑ”†•­h[•­ßcœÈ·q\Éyš„”É5U%…·f¥ Lc+(…më9Õ÷·‚<˪Å(×”_×ÚfË C_-u”bnMÖ6Õo)ãiv 1% {?¯Ÿ‘¼®Ö”² 2z‘CÊŽIÖHbÖLªÍǹO™¸û!èV»„ðn¬òÆØ0 E4 m7'à ػFµ®ªÂVñŠesÞ Õò\J‰-s![ ¤‘<_5LÚRöBâû£×iüý¤ ).A‰[+,ÂV˜²IdÃ@!HSÂV¸G_­Ḇþ^k˜Ö0ßÌç]m«†•òL-Âx…¶î¡¶¼‘›Z1^kØ$Ê1n PÂo›¿v¢5? kHzYåJÎÁ.Ó¦w*Ùbþ•dŠŒgž²±ÕÚæ@ X¥Ü¬ic«¶‘hFšzYÉ6Œ± VØÖ<ò‘ê*¬ÈœX ¤å0 „@ØZeèÛ´cæ,KŒ©Î*† Ô–Ê*gÙHÙ” p:Ý^d…­BØ*–”`¤àw0ó`Dú¶1†LÜä9k1d-lEŒè‘…’íÛ‚ø·¿üå/LcxXj 9ÖÉ–Wmà:Ù"·#©­åeÕ…[bšúÒã‘ô4e‘€ÈjžJ6¡T|UÄ|˜x¿QŠR4ŽÙ¡4¶¥|Çeb[÷”¶ LÙHyn›`©`sâÃúæP—|àâuÃØžÃÜ/ ã)¤¤ $™Xñ¥Á–Þ›D¯¶r˜Þ:Ïô‰¥Èà­|#© Ó4†âô¾ŸÌ­d}ó³òàˆiüh±í§»-8v7ûöú8>o BA#Â5ªÖÊJUd«i)[Y¯AV¿7#ý¦Bà&`T@ΓƖ9O°U Àxå:ÅÎÒymidY‰d%R"&R9ù÷ç=ä²B!DšG ¤»…Uµ¬œélUÑÓT.t@zζÖÀív.Ä–ÒV!leÛ$xQSµ@]–Í$™µmþĶ•×kWB©iÃÔ(OXÊ*Ó09ô˜ê‚0õ‚1Bm3ÄÀŽ`! ì–º¨¶§òÆšò³•¬$–"¶€¡·îº*Ìj²R›¶‘Øö¬•clÉJU¬óQ+0dñm•fÍ ¤rJd'"kƪ¤( #ò4•*ÛÞv¸ßêÛ ²E&ßÝ/¯b>ªš¼Üâ­RoÔ.*7z1ÿ¶”€îÄÍa²ñ‰‘ÉlÉdkÔ¹´–õ¬u œiî+Ϫ ü6m›?%=€[µÍ¹ªz9iæñµV©0Ã($½lQ¶’°¬séî©u´†Ç éuÇSÒ(l<²A hâ1@‘a%Gˆ±Ò[k]-¼ÐW–ÞZÃÊ[27ïO½Ô¾M+Oc¼²È®µË0$©VàÇÀ³zIx&ñ 1°èzÕÖq|Llûó3%ÒÖºùÕžùî„‘jEš©°-ÐuIá›ÄZ¶Â µ ¦áP¹‘A&}­s¨Ý˜}äá^ŒV$«ÍÀœ€mGËŸOA)˯üG–FVa¼ÒT´ÍÜV_Mm ”æpÃË ¼vU%€ Y ¦uÁZË&Ïpƒa²%L~g9WªÀ‹&éìd˜ª¬”­øŽ¡R õÛ?þñ6%P¦¹²£s/Ö>!PzóRÎ…õ˜Ä({¥`åÀÀªG‹Áÿx6ÈzYHÇî0ÌÛZuì:F¨‚{™0­7y|)ÞŠßeI%3^µüÙÛÂVA°N#[ÈözÙÂY5² ¤ªºë(`Q6ö3ÏÇJL†‡™µ­1´Àøòݧˆ¾›é\ÊÄ5•²e¨*çÜÒ´6UkítomYfV”+—òè9wÉ€ Ƹ´p>H‘†C 2¾æ¿1òŒ‡‰KebxŒ¶9ìÓn@Œq]46p2k¶@CƧ´v-Ü’uvsöhœˆF6Zæ¦Rõ‡?üaVÈôHåÜ`AÙ<œ‘d i6ƶ‰Æåh=1‡|¤TImæf³jÑ0Vz¬fp®$Vú®°Zk…Lb®ßçÓ“I]XÙrvj†3õ²i~æxb2‘UµÄ:²;Llu V%14¥µ—H}³å©cO„¦NË;*·Ö”ÀY²EVÎ ÇØØÆÀem›#Wøëõ»É“Mc†Â{…ÙÔSkH$FÇ•g÷.ɲ šê^À¹Ã^*)Cæc…ÇÙ*™-RPv“@:†@R&‹„‘0C [‘Kñ±•²¦¬ÖV#«ÍV‰BLÊU•í+ÕËc[SzbÛcw g%Â$¶x˜^\úÜ\’OÙÚJqÀÛ ì™Â²‰VR@&¦UB©5²©nF,ö¸³²æo­c…mµ•²Ù–²Ej|/àm«­iY¸-ÍÀA¤•X­HSßNd=7æ©ÄMòÃ$«oÅùgÎñké8]ìªâ«z3Ò¦"–ªÐYL¸ÔŽàž›“X/…‹SUƒ({çY{)Y™­ì“µÂõ ›ƒRI>V<’O%ÆÍÐVŠØ1ઠ­Kúɤà•dŽQȶ/SšZà+¡Dbˆ›òð10¥ÖVµÈ]…”-ªj…RºÌ_¶H)+¥¶‡³ÍY*e$L&âi ‰t!j{ÒéµcÞ5â}ÞzÒ²ReëÎÄ_À&É Ã ¬#Ãm¥6v÷sÛžg§¤lsV²G9ç†Á™o6í" :”lÀÚ„ù3Ä€gJ—9çu! ¬¯U˜'+«”ÖYÙjÔû¦ª)á|š¤¾È â¢aˆs•÷…!°ýJÎ?m›“HOK¥qOI&€dùïÔÚ¦W’’¸S;©¨äøÞp'륰>ÈV$@F4°UH ¶áZÃÊ­ÕZßP«ä6ÿõ5N€©‹·À4¹Uä@ßš Ψuþ®ˆ¬ÜÆþóŸ>ƒJÜžÕ¶lgQÛVªà t(VmiÌó¼N;²žHØšÛÇèþ£'âg×§’Lpã‰$°?Žét׿ׇ®‘”R”MÕ9T&ñÖš®ÀGè]òÙgÒevKõªËô9HíeH¦D¹v‚­Á0×érVÞl¶äYª•§Pn¥·ò”ˆô1°p ¼•²ƒC š=hÌ4™s®Ü6=±h‹I`à¶­AÌ“€OŒl'ÅŸ‚û©t3A¤©œ YùÑ]Aµ0>OŒrz] ©®š`²ÈfèP­”Ó˜Öéž8^ù08V…¶ºïBµóÐ(§oB)[Y ÓV˜²'RÓn ¦© —¹-,¤Æüï–‰ Gš*lËJàK! `ÓR*iK [m+lm’Ê¥ÚVKP°ýÂ3¿¬-qQ ¤m)Yctÿ°kÛ)á‰)eëêܧ{ö ú"­©•'A-²²=¿bj#ÍH"iض~4É„[‰óªMdÓ¼‚nÃ͈€ùúú³5¨ô?ÞLÃM Å&QU-RÓ0 LP0—õã\_bÛ†im†loŸÏ·¶B3Г1„ó´%³ÚZñÌaJ²ôx†S6|úÈšÖŽƒÁV‹”õ;_3T(lÍOï–l;)à1#Õ ”Ûväb$‡ÈI^‘R¬¶VzÊw0Ybë@‡BVnó‰I`}ƒ,$`ÍVm `ÔÆKÓ«¼.fÃ[«Ê¶j3LjÀF­ãª*Döfн ·b ÀGG×E_¶Ts*qù<ɼRp¥”‹?þñ éW¾yTyÄ C‰g¢œ­òª0]”íõû¼pßI(M®<·fè•Ë ¤«òZTÒqú¿€9Tž•@¹Ô² rKÐÇĤ2 ‚ ;Ýü+´-l…Ùˆ­j›Ü æ+üü“€Ò`ª`ìnO¡­UUåû·çÄn¾’æô˜*ÌPŠm­½ ĶÝdƒþô/0 qóg$ ÁµRžxÌç ÷˜¢Ž+™l#¹L—Ì )ÅÜ¿ 0p[§¶&žP@v¼*zåÇ’ÓµÓšâKaø$Îðµm0ëÕ oÈúÐ9»ø#óo†|¬ZTÈ!’4MÕH[¹eE ¨JÖ¹í;¡.]¬%= Ö´[eË0U¶4}~UqHlN-daŸ²ºXɧÁ÷3–ƒ-óü‡yÊf˜C³IÚÒËžâçAÓu”ÊÇÀ˜°ƒdK©ÄÚaaü¦O  j×v…j—Z Ÿ%ef3${Mà|€Yd·—?Rx…öE‘©¥ Ád¢¤wFÓ$¥0Í“-ü@ÙÍlYÌHÛÜg¶ilEW p¨»Á¶É¬pkÏѡʚ c[‰¾ ªb˜ PN¯0ÏÌ+o€øJdy*TeíUÏÁêõpoîD‰÷9OL¶x[«`ˆÏ6†F9[¡K)+ÞŠT« q÷ ä†LFY˜²/wþÙ¹¤jãûôÕ(C©^hG,{g<—€lT€XVT¥WY[ÊZ'°JcÈØfÒš?  ²›ìø+ÿ:ûLLϪ`$¼9+GÒÀ^a¯ôù4êd­}Û˜:©´m¦‚,¤¾ðók£RtB²VÛ0ÏʽÆò#Ù'–F4@}méyÖȶÁâÛÖnG T[ÊZ—HJ¸kUÜ`µnmb GXß­ ¥XÉŠ¬kÑl­dÄE‚ôÕÆL¹_h”hDÖ”ÆË ã+”j$U˜F²3êb«ŠÒ;íGLŒ¬ŠFxx_dˆIü¥?Ÿ"¤9eUImà,e ÒÌ$`$zÑWpÝ ©ª—á|ަƒ›P"ÅĪJ`ò 㧉·½Âóç7c»k„…£v‡þšÐ¶ÚIéȤó2ÉÚ‚RPZSFÒ$sœKc%ë@Unðàåî„LR¬ˆÅøŽ°‘ÂfÖŽF(±åC © i˜d‹ñzüë_ÿÒ£–À'hV{ç:?àܬ‚@ÇlkÁJ$ËÞYnªðùó©¦Z[˜Ææ_ }J|3´¥±í¥Rå0ZÈÖÂ_ô{XPvK4®Î›À°Ö îÊɬ›6КF!·é_1,Õ ×ìuH¼i*69Þ=`´`²lÕšY ²µF‚à8Þ Ä'àhÔxRmÉÔÁ@š"1@Vpâ=5Uâ½:[YæÂÂ)4õ_îœWäÉ¶èø m½ä=}2 Ù¨FYuKô ‘õ6ù¼ððjÍ 6¬©ræ ­ 8 ©zo­ñ 0žÛ¬”¶Ö°ŽÃ³êP{»šJ¶IrhŒíkb+˜µ†ML)XY“Á@7 ‹oéù§Ô¦µU•aµVc˜Ó‘+ÔCÙx“U…ļ1þ4»!ëŸ[sÑ÷g¢ÙZM‚Ę\èÛœbzú•3Ä‹lÕvox eM7a'Ýøøá޼WáÛF#žýÔk>Y)qµ †ÏÙ¹¼3¶ÜxÚÚš¸B©x+Ò=…ó§°Õw”9kÄÜä~Ná ëmTU@¢1˜P–5I¶î‡¬FÝ9ew‚ÇXo[¡D IÓ –F–‰5† Û–ÅX¥Ì dAãtR¢¦TV2«é¥8¨’âfÛ[O“ƒ <þùï—@VnISjbÛfèhp‚œ{@j›GUâ:®þüqœE7^?XHã1¼ˆ²®¥d)+±J¥ëÈ)ˆ_gãuÌн«BV"¥i¸™À€Acà=Rk>žßƫʊ¡I_ ½-R•¬¬Ê½µ ¬‚F9\Ǫ0J˜¨â`+xÛÂVUB '³Î9²UGxÝ(ù¨uK0`B%H[ÊlV­ d˜Ê­Æ.ÇT¶R‚‰­¾4 ß@’Å”UNKá·jM)j Ì'œUÃH5çÊMb6JdŸsbdâ܈m…í9À÷w J̺ Ih¥÷{ž q%²;;¬ŠIæ £ªºÝ>7†$dž‚ì‡þŸ»®œUaÄÊ2‡L¥…,[Û:v|šBꜟyôŽ0½’n軯ÁºÉV&KéE)xâm;r£ZëÅS—ÄdÚaš ÈêZþ²W^í)¸ß›|ˆ¬x`YLÏE—ÈæYåôØ:‘“øýã~Š³Ì¼ámû¯ç›ŸC¡¼FLÔZ)‘V¡Vôd•µhŒíg' Û”e3÷zôí×´¥&c…Gví i[_ÎB‹õ•UÛZëÄpSQІ‘‚­¶"lHŒ ÏG‹š F»ç£½3F¶f.å°Žðq„la2[| à¼.ÍØ]~}»„4Ö™óÄVþ–jx…ÂVTÒÕQÚÖ‘rÃl…ɺm…RJbDåjñÖni˜~¢#a>Â)l¹‘9c¸aVÁÊuY»æ–~L>ísà©—¿¥õmÉ™§-ŸÞpW¤ÊbXHÁ6¦-e!4ŒTsH«.5‚ úL¾Ä¹½%šÒo›ÉÍŸIâ=>|¶1¥[Hi¤Ä6á!óÏ°î½ ô•ð¡­j­µ`˜+ñS`‡rž&ÍZ/»ò&©i]òW¥]xU$½G™?æ·ßÿ•i«GŠ^5Åj2UIœ#:I ,´ÑX9ÒžPÒXd]´7Ik#KS—¶ÓgÒšg-"M‘¶‡Ì¡*ÛJ;¦7 HL&ð¦5$ò_e|[x€¦KPë ¬D>€cÊp«-=%«Rx ¥©`¤`b»÷²Jbèû P²*$LfUˆQ¢)O¤°%Á‚C&­Jz1Ò¼ú4˜d3"ñ…F@‚f€#Cçåæòõ¢’ÁxѨ€ªjYå7nÓ w´j­HA–¾Z²¹I &2)²^]Û²L:N×bT2ó+Ä÷þ(Éöö<‹”øPÊÚ’Á‚3¦, Í à›Þ.í$‚•`Tõ‰CÂiøç€¬—Ö²LZøHÎV!¥…rA“ Æ‹¶@3ÞÂ#º£*‰Wi[;½[WjµíMè­zõ)“mÈ^›Yñ]Kk À¶Ï& Ì:RòHúJ*ÏMjšx‚“ZÛ’]ú×Ó”Jz+8O¦WŸhSù)‹× ðÄXkŠÁ›ß)zÓrãß”¢i›3Œlþ¬ åýX’âÙ©;\yn{åd…Tb>j’àWÞÈ;ÈgI`UhlbUkŠÁÓÉжVô¡û4¸˜¦ÈC¹Žï•ŒÛZ×N0[S%îNšÄH ¬žlzd]¥'›’'“º™¨Pkz` làÌÙ •{Cx24¹5-^tЬ&ÏÖô²MB_­µÚò!¶eئ ãË&°*¯µë¥‡­FM "++Û 9ÀVd”O¤’7›mk%».ÊNGÀ¼ÙØØ ¬­b‘[%”07AC\PÚÆäéIÑ÷€T1‡{p”{^dJèyÒãeéã~ÿ!‰7d]Þ.š&aÅ97bY[&fÈDJ9YÇA Ê70¹Qr怡·ö·€Ê6AM»–²V¶dÖSp£mþc˜|ð©–f³Á¯Ûl‰“y[ŒDãrd»ù&gîÔøæ”UÕÕ…sSˤs{4‘ÿ†a ¶*I†ÉÊ*¦„ P‰1`þbæpg!³= nàÈ M‚Nc»ŽM21‡ó¿¤e:(s5;I¾È®’& Ö¥š–²4œÝ]bnÆ¢!æàÆñ¾uD* áil€YPµ“ ·Õ¨-`f&ÍSÇw›¬ûJ#ËÍŠÌ oKiíZa«^"C+A·ŠL£v×%ÕÇÆ}:>±’ÆÐEäÐjÛÙY¥ŒÙØÀ©¹ÇLCVI ÔÆè·âüÒPÖýÓhŠ©T»©liøTbM‰ŠÈVLžÜf/¾E¿ž8ÆY[±¦VVmÝ«•-U)7¡ ìcOP @ÂÀºð!¶%ž?¦àùs°õzûè’yŽkÛÒ0´vu'V_/‰­°¬ÀoÅí܄­o†"Ûd1&!ˆ!³…V°-<÷ët¬~ûûßÿ.×į¤ÒH¡¬€‘‹^#Ÿc+¶‰·÷m4ëL”1­ûXæI¦u†VÌbòTXªl49T[_d[|O÷ÿ躃%Érb ËÙÂ{b3O,±ûI¦·¨áÆB¸<<eó¯Ðª½U¾¬Ô£¾¬(a|¶|œÑ?GÓWèë‘Ð47J2«vøÊë’¡¬-½Ân ˆ\ å;ƒìf ©Ö °ÂX{õÉ`†õd­ñHÁM„¥Ä°Úù…Ÿ·ŸƒÀ[—˜žsó`nŸ³4ƒ.#Ã}üœ¢¬•Ðë"‹±"vê=Ž:PX±ZÆ*dM(«ªH©VлC€LÐ÷ªãe™Çž²òky.³h*¤9äøÜ ¬Êö½¥ãó•kÍÖüe`µVV9àû¾ž¦F4fH¯£lÝ‘ž,ÏF…Éàla2$¥I@Mc>Œo@*œ€çIÕ7@ã8®š@m… lE Û6ížB·Á‡Æúú8+ú€P…¡TEܽT›ŒƒHfA)R°lb ”,“£¾ÁÓ[i´«oµ|[…i"•¦åLi [Es†­Rõ‚e‹R<‹Æ ÈâÑ—L-¤ÚæFÌТ“æiK©©µÀp“U(T Û&¡‘í__^–!^!•>+ ò+õ”€ò®¢‘¬ž²IÔb:ÒV 7Œ.Rp…AQ;˜¾C¹µ‚•uéŠ`Y¼ °5‰*±H†¢FÍ`PH¬)³lä#šÁãØ„w¢³$È"•#‹ð»N‰L_¡mqúݨW˜›,}šL¤ ÙéÈŒŠÿ´ª¸á‰Ë40}â¥â¥t;µ‹ucLÈc ’^”u“bÎ]µ*Va%¶]5 ¬¼Áô]#@4 ÀáŸ_ÂšŠ¥îd}|ðQ#@/kúUÉ <Ã9ô.)¡+¬*Øý¨Šé7 côW6Jl º%Zá¶[‰³RBà,͆ɺ²@£ë<ÒÖ`•Ä[ëË_v$ çãõ½¢ ­‘À¬F >·áçµíüñ°U ÊÙŠle[Y¸[‘Z¸7¼'ãE låYYç!¥a¬x«îVáé`œ—y¶²ª\ØJÑÛÒ'F¾Ù4 ™òèý{9¡˜«)ÆŠi Ô¾±à¢fVJ«rÓdU¹w€i%«°“¤¯i)3˜'Yžá1þµÍÜ à9A|]¤4ëàV‚n ±Í@P; '¤œ¬5“­ëK¯ï:œÞ×ÜßáI½‚® I“%°Õ«FÈÂ?2lkà™C)çƒT®‘BX¼MfX—¾•ª¥¬„˜o›'+ ·%òHoötú&¸ÚŽ·=eß(Ûœ¥¬Û$Î%È7•1:@\#Œª az©’^Ðàó”r¢qr£ÃK)DrÈßš[½¼E@µÌ)1£#Ý+±ÍÜšÀšÉÕþZÎH¯;^hÑ$k•”}utF©²•l0€!±*?3€&4|Ã$° 6%¶ ùÛÒ‹_s?¯¼làH¯¸ŽÖxëêà}TkdxÙp›‡U¤±F­@bª²%ƒ­aõ"Ó¨U¶W£9W‚ª’ ¼«K¶åfe(èEÓ*!°btqŸèÑT’-½èaeF¦o`þ²•`øÈÚ ÷p;ŸÖjEþ:ªªcbÛ4ÄH ÀnBŒªxbX6Fý‰·Z]T5U6¡­ñš0Y_A Õ ¤1ªê8Ë ˜$ݕȖê€Öæl•U‚LF MÛ<[‰a¶²Öm+± ñ¬ôB*¬p¼SÛ6§ßÆòLcuÌf£IÌÏJÌÓI‘§ÍmÄ$l5CÅÓA¼U¨á­ÄüYi* ÷u¥?¬®ÁqØ1«µvùR°õG!ó—16û©¼©Ì€,ð4R~¥[ Àpd»¨ÜJ)DZûEÐYèmÙ¬;Z…ôH²wH[á¤d4MÌ’|õ@IDAT‹“a<…Zã­ÂcU‚¤¡Tk+‹—Å$Xw[å¶z[za`|“'È­›yÖ&À;]$i5 øGàY™ÐWTŽ©€ÔÈxkU”Æó"¥D¶å´¿%Ä]KV°ØÿœAÖýã !a¶ÊfÞS¾Þgž¿þõ¯ÞØñï‡(~z)åÝa³%¶Òð;3Ll 冤ÔÚjH©3Óý`šªjQI£Öît¶jmÿùÏòñE”¸k×Bð´•%ƒ º“Qk>VAfµ%3³BÛZH˜†!HŒÇX¾!«ã§ìjÊVžþ½¥UÝ•Zz$`X!ýÊ)+)•îV;Bµ™XÕÎvó7Czž" †>7¶M…qÏ]©ÂªdUY› È&ƒ1<Ýy3Ü&gQ"U¶¦ükÔxV%UIQb(}åMèAssK”•4R-êÒGXíÞºò¬“‰-¥ùù×¥²š­lccd?¶‘Þ锤§1L]ôõeÒÕÑç£ÄœØ?èøI O˜az«-R–¼.΋«’a²:¦ŒGÚµÓWyGèÚ™äƒ+„1yÚÝ’Ò¶€'N©ÊI!1’’ r3x§ÆtKÄRž¯¬³›–¾#Ä®ÎK˰y0]u…º×¨yh¸a¶ “ÀVáoüñGRsì¡RHwSMl+`‘c.ÛZ¥ÑØ6\|$ ¸z«9ºóÁü;˜Žp}k: l€4µ†Ö¢$ ¥¤53ã*hZ›Oó:Çç¶ OßÙ[߬.‚ƒœÎVÛ¡0ÍÌ™Ì6¾¾Í“sXašÜz È¢ñøxá¶øÆ`lVE‚ZÃJ2|J¤• øÿé?¾ùóŸK² ¯`è6ð:Ö+,eT)À´‡€>YUÞ%Û”+Ÿ¬F²"ŒB¸mÎ<¡5%•‰-}$€IãÎa¿™J­”—œ!¥­P¶â«Í°5q©W—M‰Ñ”ç¶Î^ …BJSaÜL©¶²_>h8ÍÜ¡ö-)E¯œ'¥&Þ²¶V)@áw%ØØ4mMãóa«jwÇS6¤-U`à9HŒ9#$Y+=g©þ›'ÌÅk›Y;Û+93ä€ç·…‹4YµêÒ­î醑Õ]÷4sŒl$±¸=?=YGLþÊöÂV›‡-‡kÓ2!“2§*³I%³ì¡© ¨Å˜Ó¶ )9¤Ï„fìRe[1ªü²nekÛØº`h˜hlžªØÏÎnI!²Ù`¤·×0B!±,Œ—%ÊÛâÙhTÙ ÓÙ›3Ï1i¼ÜöN6g&EΙǸÃ~½ÓKiåf!Fr0¢Ë¯YЋïîó¡ Î_vë@3Ûvùéá¶øRx&55^Ù¶N!úMÅ£lŒ²µ[‰1ÊöÖÓõ^5wŠªb¬fÀ¸^…:òq] Ô¨ÇäŒJ(l»R&”¶Jª"+r°ŠÄÀZ÷r*ÁÀ²Ú žx&RȆL)ëkÇÀ~Û«êU2AzÄ<ùôv±â,9=ÌAª‡‚ÑNªîVúd 3½…R `+dÅ@¸-[æJÛSðý¤Hñw:@Ч-ÐÙ‘Þ b&1 I¦DŠXŠÞJ†‡uiæ ™5 K‰ [s˜`ø¤÷’h-‹)U6Á¬ÚJ-JáE… ¹ƒðo@,zÊÎU­ÕÖó°N = ¤§ßÀVä°¬è-…°.x³…­xãY{.RBëÏ¿€mD+6œKëÛ8|Z=ŸØz´&È Þ4ôÌÓho )­ ?ñ`dÓjWn›O³eò®øJ¡P»V½6*“·ªí¹ŒïÛ¯Dy³UE/(mcZ‘Ä7ùxµÖúJÙæ¬¨„À«µ–Ò±gxªM¦°ŽÜŠ.ŠLÔZeÃôxåÌ‘)ùÈJõgk¤(‹§—¢GâæÏ®¶&¤¬D)¤€ëgò:À‚†áÌ#'¶ιKбmYZXxJ2öVûɺ üëIƒÉ ‘`…M.› ¾•@áùÈÞ_J ç|8÷8úF³”"%¾f{ý›¤Ð]*œ9,¹Ñt´€T%d )•þ|¾;( i6sº1“ÀVzUÝ6B¡‹T¶^!|þ˜ñX šdJ`k§Èß¶Úœad>d€UF*L™9d¸Ĩ"CNŒt[U^•λk7 [G¶°ª©UʉSQvgAÒèÕÊc"uŒñ8 µæ™æÎr-ÄxY!{¬¬rsR€¸#À™`Ö4OnL¬ ‰¤iž+…™† ±U¬„FtñVb_t 󸢽t·å[ (cö]`%ø4. $™Õ6¥uA,Rf2Œo µ)­ñ•à °W˜0+2«@9mÃÓ,…éÈômSs%d„„ ܘÂHk|Í)0™€_Ðö£ø~NskN)[†¬œÅÊ HÓAšÍ;f$bUD–r­ñcÞîøR”lë9À?+ {îÍ1ž’R~Ïîý1mV©ü¥K˜Ó¼³áu©{%jkqNõ}Ÿ¥tô+&%’ PwC" iíáÒX׎FtÉ­;fí¬ ð|:i>#0ðJ(ƒ—¥É x•“Z+aÒeÞÏ÷† @àÚn²HJc+ wüx§«vE¦j°F"žœmí®oØVtLïÀd†ÑBôZê²”*¸¸Vš ©æ· i$PJ6‡V[3‹‘@ ½¾&ÆkÛ\ F#‹t0†!,dëÎP`¬g ïH Ôbºóú’±B꫊¡¦¿ýío³AU€¥`1k@à‹Û/}þS*_Ljo¦ÎÓc#µÀŸ;¸?ð}6Œ¡i­µªzã]ÞªµÔÖ@MÅJÐ ˜”ÚÂy3º5[€¸.µ¾ªÏmÌm@v“;È:òéê‘@¯8ñ;‰¾÷€IžZÓ“u-• m7Uß5Hñ|”tŸÍ 0‡Ì³îo•¬ ~ƒ˜SŠ¿ãCâ[Y‘I‰pÈִƼëªVÊEúë}ÌWo[@j†°£!½„ÖÆë7¼jUáÓoŰçüßïwVX_€­_"Ýj·Qkâ kDÌ C#Ò°Å\ãÏR %}g7ÞV”Ý–LpÁ-¬;E€ BÛ1Høõ믢ùPn<EPI¯ÇivŸþíöi‡Qå¼ýJÍ$¦Âº ›0F´Øn éŠlA…m•Û"{¾e 3ÛU£&ì· [}Ê”÷¸1>;|ÈÔ«Z+f‘§ñµï<ÍI¿ d‚¬©•ÛØ‹„¬[càe)Î-fâõÂ÷"Q [!+l3á`Û`ÈÞÞl“ÊÛ(eß«Áè5² dÌœ-A}eÉĬïÈ0¶¢¦ë¢$ÞæVE¬ÐS[£ 3\;%xà+o$+M<X4¼mÑÙ€YÁ‚¬TΘL¦qo>5x‚Spr¥V¶§¼r…BªSÐ3„³½gI€°På,Ócܼ·:7äúÊv‡²ÿ_TRÇ3Ù70J—Œ›yv¥ºèŽ‘” ‘Ý6«5²ÅX×B6R„g2P¶•Ï-úüfcÓn`UHsH#Œ’Ý•,Þ¨J:F±¥·†­ÂéöõÈG&Cå@å@S)¡‰‡‘d Ï@wR˜Ï”ü b2±Æt[µNÀ¡;lâÎBÆ–¦Fp‚¶FUÿ4¼UU Ï #”m³Â(;…_ò4 Ö´Uu–•»{ü^àÆ£!.( ZÌ¥0ïªuÝñ€Þã3†ÕHûå­:J˜Ð ˜žª”7R†˜Î˜!=±¨ e™»ïW…ºþ $×{£™täÎNä 4ÍËÀ&¨3Q‚¿}ÏÝùwf$eF*ÏÁ€ld&ÒÚc#4Ólp[3 …Ö¥€˜­ i« PE pÆ4¡-O|)Û°uV1ªŠ¶ŒC>–OX¡^"1†Òª EÔºÁÖ±¤#Ä´vö&´zš”ù0”Efâ=óÚI)4˜FR]¥¨‹UÊ–ˆ tX9ÞZ¯^¾.9Tnmàü9UIæz ÉP ÛLâ+WÒT4”¶.¡_ì`Œ©TWn]”êøi”PÆH¶É¤Fù<1ºÛM(Kã¹'“*Ä‹ÝaÛ •„Õv|žš²T#2ÀÊ­ ˆLÓqöIoÚ¾€(e" ûj¤]c²V'2 C%¡½h$šÚ5I$Ȭ0RY!•[³Õ× _ª’1džìíyšv"Á°ùj $k‹TQ:[ @á/çð IO,2¤ ²Æ®ÑÄdb[#M¶1A/Yb“X»x©é“`¬i`Á\ÏЉ¬B ss£Ç'þTÞ$Íܪ#`Ì#òù*Ó$Î0œ­¬ªá&@fòv×ÈV0’PRFÉ p.aëfÒ“yd†©-& ¯\¶­Ê Ê7µ€&‡Z#m‘J£FÓa çà‰¼NÞg|SY•XFž3ßP.6@ŸÐž,eXmk­D÷ên P®]³TŸa[M ÀÀœiîGäóß²ã )Þj2à´ü¾T¶¯0¾­Õ6œ9è,@Ùd0F_ÛfpLĶ>×fàÀéºdÖ¦á€RT¸§I\G%È=,n˜b‚ÿ ^!µðë»W#!kEª…k7€,0:Š3â÷e1œ ÐÑòŒyɬ˜ˆ]HX‰ÀˆØåUãõe+0Êm—(¥øŒ§‰¯—kÔ—Æý—ûbÀî¶÷JíJd¥ÞŽù×1C[…=¸µÞØÄ^ $Pj30É-g‚«°Úµ«#¬Ë‰Ë€Œ¦7S;Ók*Œ (Ä'n‹á@ hô6m*bYVÊ›„!€ͳ*Œ”›§ùíïÿ»tjk—BŠ$âk½~­Ág„O“Œ)žƒ¨<¦ö4¢aU^}Jd$`{ Î/ÇÉ´F2¤ÏÖH"ñ˜.(fÃÉAÄ+”òªy°”p‰ªÂÆP%dE|c3iB€8€l¶¶L*/«à**lÝ%Ð;)½1ò,K5ƒ[cdˆ_/ œ _Ê– =`X¹.€m¼µƒ+ÕVN¬ ”Ò¥©jgU.[ (ÁÖcý½·ÌcZc*±Š:vù0'ÖÝ6+`ƒiª ã’‘d¶ÚâeáÚåáw=ío$°2?v÷ãÄ­0*¤!Écˆa|2k ‡Llcô@œÜ÷£7†À'V(ñÆÚîÎilP åÆÏ_ A¤=qVb“¢±^ úîRsÞ ƒ”jJª5ž§µ|ö}»ø¨Ò#¥#Ôf¢P¤'RiŽË=ccëXÓKqÞÌ–RnKP6-9+t-H+OúÖZ'“Ú$Z+L,˜ÃV%~¤Áªl2´ÕB•à`žôp±4 ÔKYi¢y”Çd|¤rÈ #ÕVµhk¥O|Ï'N Y¤µib£=}¤©è„™Ð7U¡—Í„ ².p[Äìì˜H&ÛJðÄ¢r#ÁHY U*A}muq9VXIúx¤ù;½`b•„”5Y­ÁrÓHô¼dÉð²d¶B¹µ*+1·eØJcBYoŽmóT%…á,KüŽÐZ¤Á U¶È&„1‚CK5†¹H–•€°I(¯Íyô@Y€ ó2‘²RÊi¬MB\—™K‰5­„,¼€­ÙnfM‘Ž™ÀÍ‚^wŒ:šOÛ’eÂ'ž@dXyíšGIÂ(Ya A>x¸oØÿP„B3`úÝÆH‰Âugl [båë« i…1¦m«$Fª¬­”ê5Ã̯#¥i;2l‚Ê3ϳI^Ûn²¦¬JÕ+Ûü;îîæ–R#ž4˜#dw¨1ÀVè.*©Ý׿ó%Ð$²aNÇ´õP(9à‹på`«¦ ½ul[9F K…ÕšÇV•5+ì¢”Èø•·•u(C*„ÛÞ«ü9 ¤SX• µ›D–¿ÀHÿ P^Œ°¥%Ä©¾Qb™|1€r‘©²&ã&E&z݉¥œ“ÞK€¼G8S"E穯íás•ÃÜšÿ™ûûÊß}J1‚èž𘲠C†©ï-=‹ñ-•ÞŠÑk'j<‡’²¥1¤=ÀWhmJ£¥jd5F˜¡­UKñ¶]ÈKºèþïÿÛc*Ñ”aµÈ°mÑv£6«]``Lµu´*¬ŠÏ[/ûmò«WíÈ8¸G@aZY)ˆ¬¬dV3[k³å¹’>¿Ÿê×Jí4¹#]`]€m!µÖRd%²gâ{"¸‡‹¯×xAΨ183TîµaåC„(s…­pX ­­H7¹¡¿çÆ+ÔB‰?š¶¥D2÷Ù¡±êˆdˆ$KßË£PìJŒä«êrš'qV §aXkV‘¶ ÚªRÞÚ æ¤É?gzL2Jë4oª[¥WŽ§ì¼Æ0²ûTž 1RÀ] qk­¥D[ïÙñœÒx ÖäÕ’ÑW XwEð¢Z[€•yÈ"•ÃÈÏš ¬0€Eúª^‡H@Êp#ÍÐYx:K°”˜ >î´4Z[e[SV;-sJYwhëÝö:*‡­™¾psÒÛ0DÚælHA#ëMî•«WÎpóÐ/8Àù“ PÒ žu‘‚F”êÁ4"ž!·]l‡Ef‚JšíZž3¦Ñû5¢CÅ ëbå hà:2ÙYÊZ•,l“…msLµr³©ªi³e¿m¥ula¶…mçí õ} kЧ„=8ÊH€I%œ [†øþ!§-ÃVïYL­ñ‚¡À3é­ËFVS…˜nÂM%åkA*“|¬Þ4<’ÀÚûÞe2¬F_­›¦Ya`O¡v 1‚¦à)âko L©‘Àäf•Rˆéõ3,È`²4úº“ùc`LΰHÖVæÕf˜©Ê© øw2 Â„,È8çf˜ßV¶§†ç¶Ù˜÷!½ZIƲŸ•4fNY6[ø[»±Mk¤-p-Ï—›-2Þš•rµµÃT’§ŽñVŒ0’B[k7–9%F¶-ÌGGÛß~ÿýw ÅD˜BØGwÝ3²• ž]+t×Ú(œÞ¶Y•xÒ™W%¥ðý\(Œá¿÷)·ª8¨’uGV)|À³‘ÊP¾Y-=Z)V°@Ú @pë@í›'Ÿ¬ÈhjÇgÈãȬ\TGÓ+¥•†¡’†ÁÔ ÙqlcŒ&ÂÉÌÃÊ×M¹¬CÙâý>êØ‰ºaVJ%^ðÙYNËï‹^¹-Oz…üËò*M`ÑœZ¤G¶m [wµ‘4º3~Þ¨.¡ZØ}n dXmyýá?wŒÄ7^Ý&}­"Ãô·g&0ù’ÉB–sµ³úŸSåê#+_XÄý³cžÌ ¸¹2 æCƒ”òÐ¥êè“2+z÷Ü0Cþë_ÿR«JÐûc±r]Èv[båd°VÄx1Äú½ žH²²ªjgå²Ká Ê–@;«V‘†§r2@;€Ìle¥ðγØ"»Õ”ZÊgKæ8T䀔Öfc tç ¥šXk@Ê©¹­ :1…˜V<¬ÊÖ Ó¤—Â)ÎýoRÕ. uðÄŽL¹r[Ø*d3?¾ßo‰|fBæBjz‹Î<4› V›¦K&£·Ò8ß… ….G­€óϼ{VhK# ˆ†WnB+Fm-`Ô‹^„· » ¯P¹^ÂV£ O)»»J¬JÐÔ” ‡Ûä4Ó÷dÛ 2l­WÃÐÔÓm¸"¤Žp}É”#E ·˜²YÅX@y]Œ¤EÝe‰1L0dSUb•m¤½Qªhð™5E"Ï£vå5ªÞºW‡ñ‘4R%>hÂ$l=wÙæWKFȎ䜘гPXGŒ³Z áxc_íyâ1‘•Àˆ7@WákÜ¿vÕgGSU‚ŒIg±ÙÖ‘ƒàm%MB`OP0ðq¿Úɬ°¬FV)ã*¬"ç‰2(•XSŒ(e¶¦¥É #©D¤˜”%ÐÓѬ €•L_/<@)&ÜÖ*¥oV²°ÏHLµ4îß ˜™LlÂzJYw´³¨ñÀÇW¨;[¤­ržÞÃ<…M…©\÷”¶ ÓkÜI­bž n ;iãeU cÛ97“Ï¿ÐÉÓåž µÈÈåµÉ ß莪¤ï£Êù÷“µÚÌ7œ*x)À®†+APÕ±m%éñHÌ”+…]ÐÞ†ŽY­«7az³ÃRµ{OYx$ån0ÌZÛ å~ùÆÃVÃä-Œt¾}º:) YxëäóF¶%zÀ }³ôªá;{¯{‡ê©5¦ZU@ÖúLp_£¶”z…éÅFjz¶d4Õ¶2Éç”mÓ+1*= eTY çdø0©Ý6½­µ©âBmUmábü~…‘@|Íκ‹z–õ­¶.£¤.­¦’…­ðZ~žl¸• ¦éh˜Þžé|Ä++¥…BÝ{ÍXÙ ÀÏzÁY!PÒ¢HJåµ–ÒZy÷¬D­Fø mÓ7 ^VŠCU˜‰8Íîoágî;y€F;ÏZ–X°Eùc Ûñ¶J"5EZê_¿cHéÓGÀqlÒ7Ÿ˜.ÖÚäJ†a®pâ ¬°XŠ’ÞVè"Ëæ 7[;Hå Ó/%ªj]JÉN*ÅŠ?`õe[6¦Ë¬)^9±Uë×!Û²J„çÈÇ6ÒÊ$gd†d<à[}øBö­íÂëb¥± ²ôfƒ­ª¬RV×hÛS#KC&2Ñ7qn= ¤{PŽ4|µ­=J$·‚FȪU‚ìÑ3I UGU€-½ÁÞÖ ¥Ò7C%;½ÚNtZ~(¼ÄÓ¯o…muáY» £©à‘Þy3ßä¶dø0CÇä´ ÀÅ+æØ0=_Û®W•¨£Bs6Á{ضΛƒVˆ7b¸Ãr¯¨vl=¦žÞVmzÊ­MÕ}z‹:‚r8Îj­¢a8,8À¬tɰ‘&`Ò¨”¥*± L$ æcä ÛyߢO¾ WKÍ>†•ÓU‘…)ÆÿÀ É 6O§¶ÚZ;©vd)ñÁS 2瀉?߬õªÎÜ÷Ó‘>7r¿â¬¶^úÃ̼Ù ‚wÛ΂4Œ©˜ÈºaŒ. ‹¦­î;Ö¯ôÖ3ßýdY)îYmüÝ×핞',º.À<&é’m ÆÐ“y"óÄè…©;sƒÙ®Á”RñZ2-ª ܬdÝ|þPÚÊΪXBeÖ¶(•ÆÚI€¢*>MC¬«U8Ò™ëb+ܸ”? K±bâQáóQ Ð  ôz!…é.Ñóë8L*Cbµf°•ʇ²«Q[;[ÊyfÒ_!åíöùnBÖØHÍ_¹¦§S(•¡uϵÂVÑ7R¬n€R1Bw `%« +«H WhuóJ0ÕÒØZ¥jƒ$ˆÏÊØÈ^58C ”rG°ŠÎh’È bÁ§¹Äóá ébÊSùý0çFcžzÕÃ|AWÎÄšÃÖŒF«mZ|Y­eÍÐX$¶’ @– –Í )Ö"™-Ãø)å¶B-Œ1Fµ^ [¤ÛØÇÊ÷¦GÙE‘ù´ÚZ5ÄëÆØKÕ‰“±²å)+ÌÓ`ÈЖC2«mǧ¤7ž^ ¤”p3v¶[RH¡¤`dn5§,`•ÒÅ„öWq®ÙYÏ ˜‡æøÞo˜n•<ªfƒÛÞŠsR5e™&+¤,L&V¥/Ò¶Z%¥¬ps–­…›W¾{ƒ )ð –’l3銬x‡¦ïÎkÁÏ™OdU9ÃT¹’lkMÆÍš[!›CbX”Åè%8Û&PKù#®ë±=ïñ÷™¾r…‚‘Ïíîœrë·èóµŸl'µ5}2¨J9ÜÒ‹”Z¢ I_ßLð½µvü雊9qŒË$°¥¼–Gc‹ÄPäc¤,^àK”’%h ËŠÈLøcà›ùœn`JGàÏ!“W©*2Yw +y [n¶™½ÛL`“W^ël­§ëýŠ›¡ÚH„ ë¢Ü)˜ËbÆZë „…ø4mU]¿óÀ‘Cªa¬RVçÐãè 9l¥lÔ­ÔîLù}1jAPy«yªJœ„ÓkdÊ~‹¤qõJO ¦_”2?‡f°*|ýk¤)±QßC¼ïUí€j‰ã1ZÙ+1ÆFê}&À#¾¾j#eñ#Õÿ&œ¾ZY [X‹"Ò˜³rŒw  ,ëŒGwÿ¼Ñàº8i½\¾î;©ñ`áj÷ƒFUÑ »Œ3ûo Ä[ŸºäϧŽÁ6†@™[](1o˜¬Ûf‚„S–êI49†L–L [`+¾Rjç¼<­²%R¢.ü³ª„¬Ž”š J%U­WÛÚÁ¬„mü] rO!ÏÄd<½‹×û˜ËnÝxÄõ• +äI €´ < 7«Ž‰ºSH!«²…³¢·Ýš ðº²·E*ÿ¢3öØ:≙䋪ˆõ*ø‹Ž€¦@ª…é[Ð[•ËZɬ1Éø”53FÜ&gÁo 8f‚|—Õšÿ>ü«ÉyYtÀY݆gQH`íY`Ò{%ú¢WØðHÎ0M%º»Iÿ®Hµ¶®½óÒØ*)z¤z¸Q#©þ¹Ÿb)-ž;cOS÷Èòg¨ŠŒ‰‘’5í|2QH $}dCÒÛ‚?7 KPÛg$‡î„ÆÙilE&ˆ=©ª¬ÃªÒ#¬»ŽÝ€,“›óÚÊ’…m¥L5,Õ0™[ óÓçÀ†ê×1är„~Ö×÷Òga$[¨Í$¥®la¤ÕTŸŒÿjpP• ã‘7¢“à9تµRæ£ÆŠÈ€®ÃÚ¶¤mb2‘pé^ « ÌJ¡0ƒ^;EM­B–^ŠæuÆód X`š_;gT•=7…ã‘pƒia»³g¸Ú5b"˜ˆFâ°Úœ½^b7Ïj«"¶­µ-À°‹J†<‡ÿ>ýÛð,+MCêe«PðTÕ¶ú€9šæ‡'b­oŸO/d-J©²UX£”ùÔH¹.†i[1*1ÁÊÕ¾¡)MY«”*kƧÇ3/àluWΟ6Á Kñ‰Ä´Í³5r q“§”Å0·­¦!mÍiÛa`³ÑÉu÷7 Þ [2†Î(¼6dùÐ46Ÿzµí5¶òq )ƇK˜6ž>[}“¸uWzÑ«íD ëN&×ø ¼À#­9o%HŒáoÕ³z@}ÏÕ„‡n[Ç™lÉÔ*Ùk´©Þ16ÉÆÀ° c˰³÷E¯;O-Û¬™çƮٯŸ²¥¬RÄÌ­º›¹¦Rl la#éNO#VAƒ± ²…-^¹yt„lU¦9•ß÷³£™Ð#P®µ*YzÛfˆ”Âð´íòã»Äi+ܶûQU9±,LÙÁëˆÉ_à-“Š|AOP£V_qRHkðµVÎfÕƒ AöÍLæD•˪mBSÁ4µ¨KoB2£NOöbÛ?‡.(%LÓ]¨ÑÄ¥¾èmõ5’ Ï°^¶€µ»’±rÊjËJ­WŸ/2QI·ebÝ 5µ"i3$K‰7ž¨IÓT ï€>€¸Ÿ¼€ÈÖCÑæOÜ3òçU‚½x¶Z0Ô‚‰ å¢#H˜@²ø~ûB ¤¯¤çûÛü"b÷ÀL¶È[rúu¶d¹4´Ú4‘ªŠÙ¸MæÃæ|¦ÃX&ú†é—íd÷)Mÿ^V‚ƨ…m}¥ð ñHþM°æ tËJô"ëÉ|+¥2€§„ÛÂjyRo6òÜõ½¨†é˜ÞòªÊJÅ›c«#°•Ê/êû2ak…LX)Ÿ?@PH1áŒlìº(o +&7%@[¸ ÐxRá®HЬáVxRôx¡ªÂ¶ø ‘uÄ#•[•Re­5?eå²ôøui‘oK ,”ÃÖ\[Ê ³’â/Ûvd²~®ãmW›¿všÞê²µc^ÇõÅsNÏÜ1{š9§oxÙ€  °²ªX½_è¶&Y­mÃk¡°. 9˜³r^ @Üvå¡X؆­4­òD澡ªµ¥]AŸâôsÎ?%ÍøÊep¶§Ó÷E{(Ê™c×Ú ôRï,ÈxU¥¬Jl·…©zviÂÈ"ÒËÉЊlµ›iK Í È^¾ÖËçÖOʘÚÂõÖÅI‘l‘z0"†Œ!Ü Ö.0¥-`]-¼Úå5òÒwdÿ4¦éÈ€F9^¡rµ4úâùÛZÁ6,E@,¤­r2[€LÈSk[ôyKm›Ök™†•Tż+†mU¶Rp£¶…uÇ|4ݹd•#› ¯œCß–OÛzÍÇv-`<™@Ú6nYÁBÖ 8²î]È Ýmn;>±BÀ4$Ãz™ Èî,çU"çùØÂ‘²°ª@d‚øRñMŽ7Àñ½oˆÖEÙd²°˜(!3ß´/mŒ¬@I‡jkµ¥ÁÓ7Ožx$pŸ4"EʰëÕ®KîMSÂDÔlL|…áÓà^O .Km[ªC! èóo¤Uô2$pví0‰mÊ×Ѷ‘Z3\ëÙÆÓh’ܬmñµ0-\–ÍO&¦fkΕ³ÅS"ývÇ¡Ù:,¬ÐJÐg\)[$r°T@9ÞY0ë›>Í;˜ûììÈô”nÉúçªÖF¶%df³eÕV¼H¶)É€<­" ÃÊd+«YM¥PÐ[mÅ[‚§ hªmKÙÖ/XþÊÁ¸kU0ÞÀµk6]|˜ÀgèoÐû>’¬Ð3låÈL¬Â6=Ad%|æ¶zQ6p£"÷¼\¦ID‚šH>ál»||%ô0ÿ&|Œ'Ö™8¥7­¦¶97- ÌŸa‚FjMŸRv©P#sꨦ”Â$†‘)´iÒׂ^¸:-¸„ið4H)[©FͼŽ0@pde…ÏŠÒHA&VHÓ„R.5@c’ÜÔúÓȉ´pϹõ§e%d"ÀPÖ¶1`>RÊ…í†4ƒ-ÙšÊWkÛ •èÞåÀä²[Ü´ Î6«¯Tí:8žc ÙùÀøÜÂÄ€PKYy§kxGÓ×¥Û*ÒWKLùFšP.ÕaNJ —mÃÐÿˆž ÚÐ0x‘àÓl@Võeh Œ œ¾¦xdkãmu !«ãivß±‰Ê· Ažª`³)ìB¬…*Qiñ|ªÝù*óâ¹[IJ>nøZHé’! +Ù³Õ±‘Ö7=7íøÛJEZ…*k© ó·ÞügI–^ê˜æ4˜ _£ŽßûC¼Z<™-¥)Œµá¥ÜU¿ÖO\}þ«š- ÛKÉJ4F-ð˜²MkÛü ñ¦ ä_ÕXm«TYÊFr™˜NÑÅJ•å,ÅܹNÙþãµ7Ðýha«Š¹• eüÙëÍ s-?ï'瘎ƒaè¹OìÛÆOÀ¶Ú C©©^eûRš MQG¸a”¯éRM^JvCÖT-Ð]G+Íùlø,µ_[¡ÆL¶µob5‰˜ U97Ù>E4¶ù4Sfh½¥Ÿh“phÜV÷Î$Y‡±”‹ƸôÚ•Õèp`˜¹ñdmÑ÷ŸÆ6y²Þà0Y‘ù:j‘eáR¶-d_[ž­Z||ï—²³›ß{¦ÖxÖ‚ƒ&VWÑ›ª°ƒÐÈ9—BŠZ¨2 Oš^} Â@%ü…*$†  |¼¬‘¬Ì¥0‘VåÕ–êøÖw W›> ÌjáÍ1-Ò ®…Þ`Çl«Q3ÐpPˆ?ÓßùKað™p‚;‚y`Ù&ר0Òö ‚Ž£ ¶æIŒ7矫P V£D*'¶.jd+fHÜCï…ïJs&ã#àl)iúë$CÙ*1F—ƒQU/XJ;)+Rß ­^›fH/E\Ç5Er泪@CZ¥ºæÕ¶â…¾ïðô:6JAV­i[‹ ‡°•Fa×H¦‹ ßT“¹7˜¦FùÏÊ0”4*,d‹aU¢­®ÑWxΉé=o¶¥Ný÷dÉ|wK¤qŠZtç‘”4ÂÖ÷y·G†'³nTþÍf $P¸#œÅ‹dU ('f.°‹õ˜òoëUiZbšuTÞ ¬ÐE¯~¾*GRb*±ÆÌ¤Žœu‰$ñoV-÷µ^¹Y¥8(dRß Þ4p<§ÃDòp° ghUKжlz|cðviiÒóIL@¦—y1ë@“8B åa&! 7@6ÆDŠM[¿‘U»SÌMʃ“Ý‘~¯ErfkN`qf½Ï”¹ª¶­¶º—Óã°Õ1“U…,ÐH4JRêþö…;fJ«Òçã笤1Í…û¬ÑPêâh”}n~ÙM+k;>uL€—Eªíá‘á|æ&õº…ó±’ÃÍŒdX‹J#¥‘€idK@ [á.A‰#¿×Â<2Ûôu´&Öæ u±%³ò·æ°i¸¼ERj«Â»CŒÔµ<‹‘'7Y¯ 6žîñÙ &UIyÜ^G£Q¥¼F)ñô)ÉF •ÐÃ4½H¶LT9=\–ØëdË¡^jÃÓÆU÷QRÕ$5­Óð•Ð̯uíJa„”À˜P|¾¶Tj¬MOºö0dE^YÀm:1`-Tqd=æßä±-e38á.¢vÄ {TZ3QÎm&k‡ä^9(ùô•Ê)¦¯<)AxoKU¶sØ–©VaÝ­ÚqÆËºs³9¬Ù$Y¥Ä´å©¤ƒä†Ä«Õ¥(»s„,ϪGÆ 7©ÖuÄu.˜ÏZÃéÞ1@9ÁR •¿U%¯%ÜäJ(Ù/¿ƒÑVRº.¥}LEÐ0¶0k§h« îÂãm“MPwsbܘ- ¼#vXÊÖÊ?óx…lul˜ÄÍL`«£7‡'MbžHYï'î`‚øpÔâÀI¦VÄH)iNÎ^{X”%–Mld£¦±N`Únx@U9åˆm—UEÃ)Ë X¤ïŠòw.µdªð@¯^¶yXÉ­ZÛîÆÈˆ10ºüº³Íp[&G Ó40q«m¼-ó”ýp© œ­•€¬]Ú˜š¶¦Ñ" nôB cÓÈÖhž˜ U¼° ` IY‰,fcW‚‰õuÀ ý Aj…ܲ’pŒkôìB Î9¦Ùšy}ÊÚÆl˜ö‚0sÀœªj!Û$cÌŒ•t:×ïãVX˜–ÀœnÀK¨‹*¤ÓÁ e×t>@åµS6@#Ï@÷¡[Û*̰}Ý›/žUdßvd"› .È.™ #Våd"ÒéàfS²3=FL+´h”›Q‘Vµi 2Œp±x[%²™»Þ¿üå/ZJ¼|Ó²…™ÔÂV°ŠªµÅ“aÔ†ô†‘ü§”7ü·üãi‡YŠ·¾cwTÊ:Ùæ(ÜÕ$3¦¯3%ÏSô7žR¹×®¹e=Y[ÁA—õ¢ä`©Áµš§+è,Rx%@&:&ÃÓôHå,œY¿ß‰9”%¶µ n)iD˜ –rËZä3R­!eïϽ¥gA&£éƒ‡Ñ…†™ 'îDY©äÏ­*¤·í€d‚ *$C“Fhm•ªµ5ñMþš6R­àYÖ ¶°‡›§r[âæ‰´šPþ ÷}wéÃyªµ%ΩJ ZtÞÝÀ™éŽ1m%•ÛæÙv+Þñ تª_¯ýžÌêŒ:rô‚XÔ®FdÊ“µbè™4mâZ·Í æ°»u|[$úÛðtìcT>ŒˆŸ¡†øª`OÍ„5”Ȧ Hu «hÛ3²¥Œ±òH>VÉÄœ¶€*)¼ ²Êm¥ð²¢ªøÆJ &g‚.a>õ­]@ò²UèÉ*Ôš@ÔpxÁÇJéð¯­m>Ö€r“Lf’˜²º49>7 Cd}u©][«­Z¯YVB•r$Ð6p“' X2“‘¬D}Éô}}ª-BÙF5Fª5ój=P[aÛ¨0 ~‘¡5 ¾!1¢ZwöúVîç/ ^l‚ Éù‡¹Ôí,ªd&ªZmÓ0$°z²0µ*@Ô XßK–ôg¾{±ÄjÛ¦è ȵkJ̹§@LÙx>¶dGèMá 낹~?ÿ–A¡h½¼ž­ªMžÃÌœsð,’Y».V‡9dÕ„ª4%èS ('ce5Þfˆ»‡zQ¶µ†ûÞ±eNc…µ³*[Håçmó¾ ×ã,•p`‰é¯)CV¢,pÛ~dŒµÉë•8O¼­îûTw²ªzp«Ýƒ“r‡ùó$6$€ÙͶá dK©­„/XaºLúl›ù½[岿´*Q˜ÃZô2t¢ÚÑ¢™«Z‰.×3¥q@)>°T³Tñ©éRcž—F˜~ÁY–R°ít‰©KÀ‰d ¹¤é8°¯‡µÍ^¯V 1I+2«WK†@ AdØÍ”ÅôJlÎlûˆ¹½¬¬xÃkM©6+|Lð]×i¬jY©2 êòÉøph€f#°µz²‰)yZãáî„^à9 ¬¤ùf[ ÀDr n$¶°§­ ¨h[@/k…ôÆ#vÆfÀˆ”{‘¤0øù\Õg©KU¬h0yr€»F€!›œL¨¢²Ä1»O·L¤Ôâ3T¢ÖØ>>p ±*&¢cªU%l;¦5PE)®µ-[¼h›¬a¸iWÊÊ„FЀÀã >õ7¸!ÄJß)dhné§Ö–C…JÈh:Q)+²Kë!v|¢P¤wEªDLµ0PÀ²|L¥Ði›Ìªq&U5­Ð)âilñ|0ÀZWb+ªªŒ©‹UUo# e$óTÒ%ð/¨$^•j’ú¶&¶M©…ø¡·¥¤yj¤‡iÖÚØ~'éß’²öPœÑßÅúª”Ub6úœ½"CY]¤z ª™÷§.Í@ßévY2äÌÌünáeÍ £¯ZMKiÍÙÀ¶‚9 ±Æ4ñ\í¯…FðaÛÁaŒCõˆu3eÙ²h€1õbB¼ÊǤZk¡C+&Ÿ1’'7Ñ61R¤*œF¡lµiÚšŠ#\£ÿ¡y÷#ŒGéÈù$>72Ü<]ñuWõjZžÈµc{ͬz5¥Ì¾ó÷}¨PÊÖʇ8̤¹S‡)ã»Iàdmi00ò¼;p5¶,¬+®e2mȲ˜ÞVvd¯‹¹7_3Õ²ò>9xç§WNO`…c2z[©J€ÚÉ*#õ²"ÝѲùÛ&cìÍÎÙ½ëe«l3xÒ-‡L¬fÖ(·ÄV[«l-l»7J“[k‚0˜9~MÔ"1ưšSð‘*rÀóoÅ8ˆ¬*- œsc ÛZE#…•·¥$ƒ†l‘lMâ~¦ÉpµUe˜ÀHÝ<ŒQî\ ÀAp°â)ka› ÊZe­B‰ '³b”æôì´ÐN`hZcºŸNÁ¤4á¬(ÉÞÂMkA#eÅëÒ¶CÕ”fc¢—)‹_Ég6[âæ„+±-T5‰B XáÞŽa"8xô€*+™0-Yz[šÌ‘4€Q8·Ú5UAžJÊ6¾ñ`1²­ª M®ñ”­ÖfÛJ£J¨JPUÇiUÕ‡ÔÌFEÒX…¦ŜÏï+f@ò$«ÊÚüd·ú×OÜ[úùiTª5¾U£n¬^Øv.…‘¬zùþÉà:RYIÙZmOÍ„ô5’ªÐOÃ0eÎ hÅp T]jcxÚÎ!2^­ã8ÐeC•¬'bë¿` «2ž o wêNÔ¡Òdkj¥:”Z…Y¤‘­|¯zzJ]nÅYªæ¦Ö¯&&—2‰èo:mÉô¢§²EJa¬o4CJâÎØ¨—µúq|½˜'6€)áºDÝm×…ÀØyFÚLŠŽ_J!%RÉ´ÀpÆ…CÉÖZªajj-(yÂÊc+›0·½¢ŽÓ`­ª [€§röù]/ FµžÃFRÛüR¯¦Âj_ì֞‚¾þ·È»¼îV>x¯ñž‹’¦šs÷@ìtªÊÚŠN¤{³uÿ”²Æ*(u×èÇü׿óyѨ ¤ïDôa²R Wr|o/æe9`œE92e#Ȟ̖ž¡€»b˜ ÿåè²UuFjËLU|ž²Y1·4¶ñ4 í %°Çd«…mŸ@vÊ&Yù×éü'ÙÖôέ’>#0ÒJÙÚTm7|34?MÎÝ[bÙîP䮢ǡ¼Ï¬`bMÖ•r£äc‹—m$˜sb¹¾ø¶€ÏN ©¶x˜çß~ÿý÷z $x%²ŽÁ¥-ë| Òà .qªXÃ)ûhUÆ'О fè.hê¾,ÖZ qXIn±À¨57£Pk…0’¡Ê³y’ù‘ `¬A­Û%•#Åzɪ2=M“à1¬DnK£V eá÷‹X-’¸a€Ä§æg]„%@™­Òvbh~¬¶E)X•••vmÍP—Óòû S‰Fnn는«"àÐ=`ÞÃ&`E³Éb¤”ì«„C²Ž#+”èÕwmšøæ$(JÁô_îó›ý™ø¾9µ€ë¤± }_Ï3ê¤l;f[˜R¹Up¶Ú\À £—T#…§'ë ãP¡­ÖlµSU6À¯DÊYl­ª86‰”ÀŸÞ÷ÜVæH2˜“ ¸m+ ÒÈYj-”±+ @IDAT7O¶×ã×—‰­^joŸsÙÚzʲâ8sn>¶Ì•JðÖº2ì8[±Ó±R¾lH­ý5¡éñ4jÄe3Œ/æï7oQ7ß?®„C£6üµüe›¿”CÑw‡Æ0]/ PyV€ ²µƒ4†UÃÀ"7Œ Œ9sÜSÛ®)‘y|³©j×vÓ7À ¥®Ó±‚ÅŽ£Ìš³‘j×¶*]‹² áõ’]•”«^4µ¼]°.ÖË6=ç­Ú:²Màƒ¯–Â3‰ïJ1cK èaÐâ ‚RH…¥èEô-¤ÒÔT > ÈZI9Êj½ó€¦µ½´™H Ô¨w–ó]™[X)dkR…”yð ñVÌ0MâÖRHí>õÿë?ÈR¶2§âi5†Çן½yöµY_Ê®BS•ͤrïY°m$[‚Úala ùa€ß× ;OÙ|Œa€”4@µ9[+­ÚÊ2GÚ–µw@Œ1@_têxV4ÍØ&N¿ûÎcÖTaA àÖUÙªŠ/ïYðìȺ%ç2VÖÓþ¾3V…‰áZ¬öõOÉ\4v3X9ë‚„»ðµèqtù'ƒ‘µ†EM#itA:ÈК¿T}­¥’Ùª”'ÅÌÜV4@S„wos“­ðú|þàw5‰Rhf«‡_dY¶">ÍnWrÎ/åó:xÉö,i¤vØz ^t?u´? ƤEzÛ Oãïç(Û$hlJ)%8Y<ÏYÑÓØ"[x½r³bÖëÌôý^ê5–M@™L;šº¿Ç™€ž gb •Þ;–íéwCÊRê‹ôHG Yð„Ç+ÁxÄ^¿bRÖÕiÚð³µ]_d<1R AÐíy¾Üj*UÇm1”ýøN¶5J€3¾S¶ÔOi[– £ùùK¢ÞÖ×ȶr¡¸z^¹¸ ã"iòiJ[¤O—ëóyóøã»b[<ÆÖôÇñî㊵NÉæÖõÙÖ¥‘² ˆô9Ãd°U`‘*k ÃpÐŽ@äƒl•èB@µn‹”Ê¥ÊJÍÖ jK¶Bæec”µ³]«ÜøpXŒWe…‰7ÙÀÚ}mÎJÇÚ6«æ‰´^2ÌÐ$²Ù¬êÞØ²¹ñµgšïwŠmÙÈŽ °“º"‚þ¤”ÒJÃJ諦QÒs¬ !KÃß0R@L2&9#kê!b6 —S¹v Ák{s`åsž¡BaKS![a»1’1ɇ'VH3 >sÙc}«6q$¡µ³_VŠ®…­T¤5ž^ÞœdnÆ*âÉÂÄ9“º[µ.Ei0§æS£ãõ½4Œ i UR«^§Á=‡Ss«Œ‡”UU#¸TÈrhU(ðzUôæ©Ö6…æ¬$‡dÂ}"ë‡Xp³ÊJ1Q{éŸ/ì߬r[VBªñÈL˜ßHRxkå õr ž²iÍp>ÿuzŒ¨¯”’ô•3R*s+œ9M•û|mTž«Ý` ±”­ Ãv]HU¶ŽY*çe¯¬œ˜˜~š@L¶dMU#ó;#ÜAè5≄]ó&Q•¬r2V4ÙªÂx‡UC c3éið o+o˜Æ#¨„@¨mͼylãõêa;)™íÄ FÙ‡œ¥-“|8èØ²†‰oNkd† mcLXKU¥üæÏ1‰ÓKU²5[ÛºTÒÖÊ­¨cB&Î…”¶› v bg40ÿœm‘ÞéüÂÍJ°­éJ5R–¦Fù“Ia¦7 óª`ã½YíjݵcECiËޝ—­*zŸS6LjdÛ 4Y)D`:ZÓÚ:x7V¹‘Db+\¶v4©²ª´°–ª‘™1M›-1p‹~æªÈ¦´ÍJ;¡5lJÉò”]ëcôý¦&†­LÌ“U—¶ E2΋f¶­ªÉm{(™(Ä«ÅÃV[ˆiK“†^ô²ÉÂk«j•‚ÕÆ8…áN~9‰Ãd˜àmϙ̛ã+ö‹CO\Gk_1Ìû²6€Ö²x8“ V]rV°H‰›ÇJÙTUÕW‹ÄHÌRkË¡ Ä“qÃV…µ® ü’”²ª”ÔÔ¶ZÛÜ6&±rµñp3`DVÈB ( Ûê⮬"MYÛúZÉœKt [sâ+à™eg·r#3ÛpŒ*)Ö:çf¶J5'ASq¦é)BÇ|Âéa@ÕHÛEYUÕš¤±›Þü3,«D ÉJUy†R¶ÞÙ¹)Ágee­M‚™`£J!«ˆù—…¯ÍÏWñ ¥(=/“Ì$ý49Ïž§”*@#úI´^uÁx½‚à¡,±°%S"e Xk¤$†okH7ðq¼·eàÍŒoB&ºàmµ¨u€¦8s³aYb«­ Ô”²ßêŽï—œ>õ¶•¸"J%<)­ø¶u±27\»4|²Âw¨lãUeBœÏ©ÿkTCÄZVYê”°à¸Â½+¥ÆÛrPn5q1Ä­NŽ´uNïºQ; ìöiô"nzâZçlH¶4™p³¥´%ðÇ}뮦ûâ3ÀPI¶4jwc6€F‰€9àN'+˜,• ’LÊGË–¡0³Ó%ÖCcþ4{ 3iËA/LwH/Ö%CJ]x’ñ¯E²éÛZ:>±Zq½? 2¿¬š®D;)óGV•¿r[AÐz;^å™—µíJ<;ˆ’®tÀWízÍÌ0»[β”9‡Õа'é¢×ÀÈz¯ð4bMñN—^(éí $kµ5agá ja-ÈÌ-Üä0_ ÌJÙSp?¶øjK©²Íç–Rë…7³GiæNÚ¯žªh”ØNcÛxe9t'b&pMéö½rä)d¥D²|ðÉñmÓÃH+ÃwB¤­SãsH¿* FUÁž‘kYÓX­ìšÖ_*>qM=Û•äŸ~æ.³ñ²JÃÐe¦5QI÷/ÛñUaêE —ÂØÂ îìÙ6 óx‚†ìÙe•mšÞ™l•oÚNQ–úà=¤Âò‘¶0Æ6l-¥oí˜4 ð4™ÐÛ L0 ªQ¹‰æ$Γ Áµ<ßü°‡.‹é&ù4ŒUØ6m3ÔT!Pyú>Jù`&Æ0±v3ÚõìZ_½.5Bù°0@8C$=@8E|&½Tt t¶|ð¥zd}¬¹µ…ÊaJÑlÍ6ñÍœf"ÊVžF*Í«Çp#6­ÕÀ%+Åj[€Lp°öP<ØÇG¡¨#@|9K×ÒÄ]Kʲ 7[¤*Ûº.†,Ûj«µ^d°¾xUÍ,ë«VÊ–'@ZmGr ÃïJ>[yjÁPI[˜­*_/µVÞHHY2?Ú¯J£†ilh0€2žX¨RN&”ÛN1M€€8+Y[Cö¿!Ö–}žŽ¬^dÕÚVž²#U˜îóèf:x…ô| IP­B½0¯CI‚-ó I“,2,k[ ¬5óÀ:æÀÐl×ø|Fj£^ïŸï: Ÿž2LÏ-UI3ÔÈjTà £ wkC¨Ù4Kå¢@DÒÀÝ&,=A&psTn¥o)­ ݸp?óð"7À¿ Ρ*€‰¬*|ï2)$OŒZ†Él}ýaDþրǠdãÉ´ã–F6žawÍ“o›L €|úº!ÃÃVíl‰YYaÒØûó%Ñ•æ™-bòÁL›'[åd4æ!¶¢»ÂÔH±ùáx 0ÊJ9çFEý¹–ŸƒU ½¬(%›gÙl‘1±µ„*ó÷¡ÕZô”<“låô1’yëµ9_²¶5};Â"«Ú)læÜÎîÅ*ïÑ×K•9 )”½çÔ@glÚ&AJq h0[Ù b¤HÏ|Ãj鵦¤ÁÐ{‹ú'ÝRBŠl¯«Jd¯÷Ï„mñ¬`µxVáKI–’Ø„H äSÒ<¶…anõcòÞ­^i¬iÃ5jÔ³"{’iŠtðU5mV=‚†i<åôošGFo-꘲¾1ÌduŒ1 «>à˜¬di¼R¶ºëÛhØ"Ð)”¢^ïdH+“žÈ˜¶º4|¶dõ]—u”zk'+òÓphU‚tÞl‚Ò¶békMo¼½´ff"(¯ Y%3Ô¢CÕˆm2‘Ì*lkð\aÀ*¤¬ë˜›Z@—˜×òó¬°l6†mG›ÞÓ5¹òd9üš?«è1ÒÌßðiØ•˦¹ïÎù8üº [AÓÍÀ9SŒ  è¬4a)|潕g5çסB…nZ»sš_o M}³¢$˜¬Ðñü» kcgÛl¦ÊÜCñQmU‚>e‡Ò+¾”m£’Á4ïä4éKÙ–µb %~€bô%ð/h×½!{ŽëE,R6póS X¶¦Ìm­¶þ;|ºÜl ž _™n‡s cha+1«Êµ(êËÙ¶^&Òª*½•MŸ‚Fêæ1xQS@q&™¿©jÅ´îX RÔ1Æð²"ÃVU²Üšª’ÖjÉ€®‘ò˜~b—i0LO0ýÈj›MÖ­²~²äÙAL^ŠUÃ7˜mcÄÃô°,VÄ1Ⱥï­0ž ¤qêþfœìó±¯}˽ˆ\ËF‘b‡ZɆ Ñ@RÍÑ1¬4Vµ5µ"ëKÁ™Ø.ÅM5IY'™ÒQiÔ.(uaޝEÝÃd€ò懡„yÙi¼… Ü…ª’bKŸ&`x‚Fb¨¤­5[ógn[‰•rUÚ¶T+=sÎÄEX–!Fa g8=àÞˆ)Ù’ Xä³£av– ­WøÃ×"¥U ó_¹F²ñuQˆÉ–¬°WŽ)‹ñX‰ †dEÀÊ–f€vjÕÎJJ¤wp‡™à•l ÙÑbˆõ¥o ‚^bJL#!M˜OžÇúFcˆ÷,x±ªî°ö²)ÑÂ[³Iõ¾!ó¬ðŽyþ¤”­µK›gcàµzX­sY‘ºt ÙŽŒl<…á&L)µßÉdÉg%“Æ÷Ú»ÃÚ‘i$€õ±¥ªúÝÑË&¥¼câ+¡éN˜À²¶¥0"Ãmk-ðé‘Úå/…W’'œIcÛºCU hr­Ê`"dM’J) L ²#T¨ÄÖð ŽÑ÷÷IåÏÙ”Ù¶FØÂ§Ù÷ãp>ÉÄ Ä}7Ö”4RŸ?ð2¥õØ?ækcU&€Xy¥áɇéI$>m¿<ßÕ‡JôU"Œ$å—¤R×༚¢^4ºd §ì>°žA“X}tµš_y€¿¥¶Ý;R ³Â‹L²•m*¤9ÉÖ ©O`mZUø}}œïäV++åVA‰¬Æol|ÎJ’YRd[̤F”ʦûwØZÈîåk2Áv-b¬˜<;5«l­R<¨Ö*6\¹U ©°’üGi…Íc¥/àw[& c…ów.%9³ªQµs e×±ä<áe³jëuêïN\fg¡AixCº:2µÚ‘ɦ±–mÅ(ÉS!7˜¡ÓizÊîѤzÄy"‘˜}kÎesS˯WÎ ³Q•4yÙ¶øW#[÷­M˜¾1:Ôn)A«r†Vzú×' ¶RZ‰‡ ÞÛH`­pÿ×¼K6X·Áj6”`"0¬l5­o[Ìx8 ‡nÆD+Ï@6†á¥`ŒwŒ®°_‚»Ÿ3Ê=TnmÉ7bg¤ù%³Uâ˜Äéf¨°#e¯ëY04@nüM±%°PK `h†ñž‚ÏŽî³,™¾ ñ«@*Ä3·}Ýhš©ª[j¼x)ÔÔv –†d‰'‹”GæÇè«ÁÛ2ô­GwÏbyètµ 0 Øð0ÒVx¬c€94f ¬­›Q• ½_C{‚¨oY[XäðbŒl+ÀYI²V$ç·6ýJ2µRë˜,råª\EÔˆÀ–8e§žydO0’R`šYíJ¹ã÷»+84’lU ß@r&CR6ꎬOo8¾a0‰é'fîßz࣠Ïþ)nÎJšüiliø&ùÌP–2«4°³ð¡´¦¤é ÙÁÉÒLFÉ É'C[ ¹Y ú‚C ˆ¿ôŸþ³T×n•S¼Z#‰}E—­K…d‘™Ji$ŒênR5rïCIFÐ9ÃNŠWhª9Ha¤z+ðZ+Ç#¥Þ[Bjç8ºK bëÚÕˆI¡{þ4@8’ ã·må#ˆ+'X ”‘¬Ní.ù²=w]Ô  #â7¾È%±m€ÌŠgbmšJ&&“5 àF¬n¤ÉØ.eΉëõZÁ¢¦j÷êÞVG…¸'Wbå¦Ð7Ýþ¿ û`Ш•ª¼*¯„ U–>莇9¦r¢N×y¥jÑ0²dµ€û—ðl] AJ¶¢;$Ä.‹‰ä£+γP¤ˆãw™÷WÄ ²Ü”Wh6ØJ#e¥¦)NƒÒ,×ÑÊÊêy¡-`ª]©Zd™Ô΢CÑت‚žð[¨Å¬d…y¬ó´…ix6j$Ðé1Z0'3so‘-, 0½ªuäÚ‘C€^4 1d0¶V³ ]*t($\S¼*[¤Âj ‰lOYÌétO ÇrÀ©ÚãÀÓ7ÐöX|ß1åJ²y¤ŒgMl­/[ÊH8ÞªJ9ÙT¶EU9œ®ß7ÓX+ÐET˜¾si$”ȶÊög9Œ’U©)6Ûüs®¶^Lô4Îe…‘²dV¸mn²ÉòôÂaÜa 0ª¤èħȊRÐÈÒÛÓæ{¢¯ü¼H­» zkA#e•=f²R¶VÛÜ`€}æ)óá El&s Kõù2ÚªÁÙʪÈèÕ½·«¥‘ݧ†€’‰.j^¤B[…™cºŠdõµâE+Ùž¦HëUvgQ’í·úóÁ´õô¥X‰|Ö.dµÜ8[1ªÌŸŒ>VÈxWÄÔ…¦ÿ’ºKà~-ÕÎM¡°-ÚZÉ”ógÈÖjÚZÿ*ì‰sÞSP啦o°lÓÀ5•F£ž,µ@2”V?|ûG=•ðÊvUõÔÔ–­”íH¸¨)^è²µ,óÊ¥Öc«{7F£ ɪaƒçClm›x|V²JÈ6äJbüÊ] ,:~ÎV2Œ¬‚@må² ¬R”øË…¹m`…²>†VA†·šV˜ÊÐ €“1Ñe¶HL§¦We+ÛÁá²/“üÇ۲݅¶MôÎÀ€©ZÃ@—5é³ÓœøÈͳ*­«eTãiD³µÒXE­Ã]*7)>j1úZó‰9g ¨2]¸[€éÄFQ_³‰kcË]¤§qe•gXcYšwŒ‰;¡Y+‡¶pï)‘¡Â4u±ˆ›§¯l˜ >Ý|àÜÈ&¸–Ç“¿UŠÞ鬊WUßHVåx ñ(û}ç­ùo*bX[9=| nI)L…M"ÕêiÒ4@V(¡!°5 [[¸!9=ý>)7-%7[ÖÔ–Ì™!¬`Õ‘d+ dUuœV[í  (IV‰S£ü˜þ´ü>& v/¨Ü*š\#X­U#¡J`D‡r¢˜Sv'7$Ûš’ÁÅ-=ã)ÄÛVR¹•¿,`]>Í”p$†'M­¼¸“žQ1ð&1X& ©¼Ãn+;[¤Àt¼-ç“É"­À7§“&cP(ë¶1yÆ7R­ñÊ7<±Ÿµ~Ç¢4¿¬•’c;Ï" (§yÿ-|ʪJWêùKn&ƫŠ; *ÁVVmgÄYõâlH€À¿Œa}Ý2±Ól[ùÌ5"‹5µÕKmå­üÌ#ëXJ ζpnsÛMviø˜R|LBÐt(À`™[m=ãaÁªèµã,ðß „mÍSÅÕØ²rÕ¬€.¨WâζJ&™µ¬B {¨³|[CÊâ9ЋY/RdÂ\ô›@«i ˆUIuä94Ûšº½vQM¥\£ÊÓ7s+†€’ —а%Б@wÎædˆ§©#žƒ#$ê°@3L¦¶>çµ{ú ÓÀ°ÝÕ)1ÕlöLæ6ó?ÃåsP+LÛÁõèל¶@³uú¹I50–ÊÆðQh+ɸe^6)VRǬZ•lÉÄ4<3´zšúß°q4±ƳU>O hT¸îóç,Õ$ÖÍ–çªÒwJ\`Q‰­ð¿F‹Ü~~Ï·#Q0RSæ«1 âNH‘µ{é“›*ltå™ç fRÒ3ãÀ¼—òÌ{? ;°ÙšÇš cÑ ‰ÝrçW%Eƒ”X™Ë:¥ ë•LâH«h¼€…ò”²‘Ê1Rü1ZHaNýRš6••²Á¬ $Ph+›ƒJ²ÂÈ„”-kç ¸a·ÚÍT¢»ÁèçnFЉB䜹·ÃÉ %µ“Ò‚¸§\Uz2©²V¤ìmx£JÊ`ÝÜMÛfK‰´}­è £¾©d3i$%¤¦šRÓ&4‚ÉYU÷fåS­,M²”RE)b1™\¬Š¦«H¼<™îÖŽYߎ0µyëN SVÈ [þjaUdR‚ØïaÎã;221rz“TÈD4Ø”§Ç ÙÂAÿ•œ'î=ôSV_X(iæ¶VzsšÄZ;²ÝRYLúÌm\9`«\À¦ÅÃÞ;ÐTZ×EêÔߨ4¶V‚”v¢Üd™j+Y%õM/ÅáÕ8rCZÓS¶zª ùÃ. &¸ ?_P¶l2¸¨)<ŸoæOÿ¹òôfÐ.ÒyÕê‚ÔØ*eÔ²H@ €;ܨâªÒ É:Nd×[vÛÒ [) ÂáN!ˤÚR”€¬©ÍÌÆÀäÌGøáK™Ìéê¢DäP–’2Ïš®Ñ•ŸÐåÔÃ0qµù›§Z$ÿH+,ò©–Ò# kræ"sz‘¬*«‡n¥§É§-†X–!ÌîO¡xb´µÊº]ð·Ûç³Ì•ÀÿRËÖšpáÚñ\ ÃR%f A6†X8l€=”FÂ+±’|œ%å¶x­EÝ•-@¶kÑQðLiU+›ÒÀˆ®œE¸”Z¬Ðºl¼°òpµRîA‰aühðg³d4Žæ¡tpc4R«cö["YíšsžñHþïøŽ w]LJÍüHïÇÁšCí"ÉÄQ|ÃVP $L_‰^að5¥lžÜJUÅÉëv;œ%C`U€_!èÈf~ߊÝ'@ö·ÿüç?ÒêérÉ..–õ´²›Q—¢ß˜p[âô dÕå ‡á@œ€¸ãÑ …¬èð®ÿêü§Tn›“rßt®q³Y5[n­]Y<0DrFÂda † €çx÷[C …T…´50¦ ³ªVÖû­ÄW0†Rä \÷Äd@|¸­õm9Ð4€À™+^ u XÉÌiíìÒŽîˆC€@¡§1lß•¾9zš"\¶ïÕ}ÚçqÜOâj'*ÁÖ·—B¤@ [á,ÜY­DjÊÜ(W ˜‰íL®÷YŒ$ÕkIö:Üy^fåBS|{7TEÊöJØ"Å­øT5ùñ¾™šµ TBP V“¾9kG¬#,Í[ÎÍäC¹“ž ¾O³C*F9†OnÈZ`Ô¢m«˜ÍfµZm a›ù_¾˜Ì‡¸m«m&¶j“Ys ”´UÒ‘m÷Àñ‚².@¡E ¬­ZUm†dH²4éÕÒˆªl]ÜÖÊDU-ç€äc5FÜ¢ŸB¨FÖ_!U^k¶|¯ÄåûQ"“ʧvaµÓ¥âÆÀŒÇDnŽÓ{B@o« °rƨ²Ub«Døññ¡€UÕgUy]¬"žs`ïÞN] +7¶ú»ú4V]%Æ–³10“' §¯ÖJ)dñ­£”êàœ¥le)+ïBñÓl²‚ Ëq"Œ-[zÁ0Odζ²m¾sx^áç{Ãx¶¬ZX7R@(:™Ð·^‡*ÏŠÀÍÐÀ5Âs‹l{ôªZø„îeP²`RßzÙJY•¨…[«eÅé‡/@f]S[­e#V‹‡ÉRÆ#ma΀{#iêk›¡aè )¿Ü@V9`Ò`9`ˆ3±¤¾½á ‰´duʾ_Ô ÉܡކLdñÄóÄÄ PÕv+ v¼ª"‡d‹ô²&&ñDƒ˜§†Y ®‹-àDK!3Qˆ¯’Ì*hD½¬ ™OíºL+¥’Z×eR1ju„émSJå¹I&#—ªËÎ+U–¬H¦ÅÿŒÊ)%C[Ç´ú°»g¶ÆóæœÙ’Ò¹"FRÀ–©k7ë^„-& `{¦¾bÙ¦ÉAv)|d&VA Ä|¦´%X´=¢ï«°Ùh(«K˜6’CekÈf¨—?nºY…¥šß•©­{ çzY+!†{q1œ³M`Ë<Ï!+LŸ@5"ÆÃ‘¶HÎô"A@#ÊZ׎¸àÉAÜ¢ó°(†€³IJÙÖ.­é1U͈§¯i%lñ²§Ó÷ºø$` bŒç&¾æ&é*l #â[m‰ÉFr@ªŠÔÑ©ià»Àfnƪ )Zé»ö÷’1d†iž+?7¿a𪓠¥´àl±ÊâKÁý V%•§«Ðèuè\uï€ÍÉÄV­•†À*dNßȘüµRîJŠÞ¡hð˜d‘9˜¶SËŠÜÒ_³Ï5†×Ë Ê› X‡Uш˜R¶ZÃV˜Òœj#½bYΙX•ã1øm•`²Ê™,ÒV(!Þ1a¤U¼æ°³'æ à&V•ž•€…§ W²˜küûcBC™'¼ÖJÔZ›ÓRÌpn¿)ÝRkµÀ{-Zìùª…Í–ÃéqÝê²-gA‰”º.$¦yt‘êŸr÷Ý2‡}êÓ[‰Ý? 6k[Ì#¤´CÂ]ÑîYy©£þŽètÕnÄú…±ù+äéauØJòLƒ±'FªŠikõ|Ô&Kƒ ªz·¥‡ñ¨|+’‰µ¯GCbªz ë®G`íí%›Áغ«ÅàOË{Ï[™ãɺL<ŸÞ" üž¨T½Tù¡@?sLnM[ÿϰG€l `gÌoˆ4¡a4ÚØÑc’Ê9OX(o˜¬m_*’-ž ¸õ¸‘VInz2á•k$z)%@cj«’Â䙨ºF|”DVÕÙ‘É‚øÚYïáÎWP‚N WXþ¢Öº0ñ:yó›'s[Oößÿþw.¢94€ñ—û<†Èø¦‡;•”;¢×Cùè½ÔJ¤fGBÂøJ&h6$Û ›ÊÊÐJ)š*À§Áò¬…”m<¬Ö¥ø"~Uòø¥š¿aj¡*gcˆPØ‘1J^ LÃAp¨vdS!µSXS¿–áKy6ª„,sdk¡°@Æ[›Ê}ÀU}“ræd•Àm­‡ ‡œ‘™"ÍSUdµªrÐÐBTƒ¤T+ðôÍfÕ“o68C)˜F(@J†‚ ­G÷Gñ|[nk†NêÒ¾j8s@˜¹L`¸y &:E)ÛÆhËhŒ|”çok¼v‚˜ k•­°S­0Yƒáe1€UT/g)`¶¥loÑçß73ÛNÄAôjÃxb%|È0Í`ÅÛJu«ŽVª¦°(E†Œ±r.àl»g_}o MÃ#»7@Ô´î4˜Ìa)«‘"á ë‚Ä·”ޝj&¶xQ+\6rʹÅó]€n/ƬD'í•ðç"‚ÞÙ•pà/dÖ‘áº(„S ·jëSv_Õ©SæŒé…¬Ü´$c’ õíRj“€ã@/µûã? :l¿‚˜€Zkþyš&ƺ ¦ŽÝ÷犭°m•ÚÅ5Íx)Ø!Û1¬øÆ°Ê'­Ä6&Áî‹snøš’åc  uv© æ8>A&‹ 3ñÆä …„ßc€X ºXóïO¶n›‰Tóè‚ÁÜÊ™HÙ¶6’mL$œ›¤¬¶^>扣æ/Ûð&!SnHµ‚¸Ô9ö½Æ ɤ¬ÈÌoþOïLY<·²7Á4`èWw[b£Þq>‹í uoU"Yœ¢lV²Ž)èS²&ÓK”¥‡‘d‘x‘Oø×–ŸR}›(·µ]¸˜PZ¿™ÌÁ"»v€ç™é~†YæQèÓ ï¼”¶éÉâ=qJú˜œ¥:8 Û? Б>Òl€UHÌ….BƸSPb˜0&HfEªRK`›? Èl×%IØJ†Y*7­›äÚœ…)¼FJ"ÌÄÏ¢yúöü“ÐØŠ€¬¨0ÒöæÏ¹X1ÑÝ%èÛSƧ§ÄøÙx[)«î<kUxÏ"¨‹õuƒe­ ´V §éYøªñŒZ°Í²ÚÚJ%@ ί¹”m剭ÉÚJ±%+G “Ô1îÔ@- iò ßVÊ# jÁ§÷_ Ù©‘‰¥šYêÎuÙÆèû0i%ÐBŠ3Œ)àFšgz¼°å,+”4'ü’á áZX;{ï¡n²‚2[øø^gÌmøùvŠ×Ž˜¬©ðHäïPp¶‘5¢AÆgR­Uà[µ¶Ê;Kíài†3u̳Ùké]Mìµ%À»œjK­ÄVÖª5Rt«HzUÀN†,{‹ø+¡ä@ ¼ªÞã$Ã#áÚs³âëµÂ”Lúã{­ÎÕ?›ºÜY: À°2ƒÙn ϱl%=Vš|ê²ãÛv[ú ­ ªÕèh;8’”FUíÍFSU ±•›ŽÈÕÄgÔ¨¦¥PØxð;×@•‡•ÛÕž§Ö?¾f[a|3äÖm°ê€¾²êf€þAY‡m6¤×€€Óä ñ•[R½`õU‚WÒHe­ÌñÈ!sI²Ö:j·!óÇnB*Ðú¦Æl~YzæUqÓÚ¨Ö ­çz™ƒÅŽ7ë\ro w,zµk¹ÑéÉ„r€RV/`n¶²º7¥ëÂ3ÈÚÖQ‰íîÚxš7˜$sf ·¥QÛy1·ÛùqbN&+’ ¶2u¯¶^ÈdRÕòDæSÊŽ„‘Ä@gï¼<†[‚Fª–ž!¾€ËZ¯‘Ò(až]]”ÇSŠÞ¼&´%è/8Ø*étJàdHÖ6óĶ1Z.ñyeéÅ KmíP¶ f«×Þ ©ëñYˆ§l<â|ZWÛxÊ”¸aâ-ìÈÖZ[×BU¶ÀÊ–`zþÀ5ÒwÉ@Îu¬WVAU[8óÈx%ugÔ—°Í¶yŒ”émn•)mÉÆÓèE,Œ!|Fò§´UÐX LÁ ¨;@_SÀ-Éf+¥°+lÅÔ=âʉs2‰ÉǪPÐËUYŲ«a¬R·*‚lÑyméP¨%€Q$°*ÇHÑn¯ß$ècòaK‰4p3ÛÊÚJ˜Ö¥gB0“.v²j Êx…=k>Z8TÃÈö4ý=7FÖ6˜ ( ˜×Ù¶.‰FÒSÖš¦Ù*Çñ°áüJ•‘šGVUþ°Q  *æ0 `åÀa{Ê )=޲ yì¾Q#JUu4 H¼Bª.‘Jø Ï¡Q•çf…ÕrÊŸç±¾æaY&"Æ=)冕È*‡MUIóØ*Ág˜y%‰eià‚†C¿ôäœÕZ4=PU¶ª Ûµ£ÛæFS-™^‰‘€ ™mS!ë>”¥&À«R;ÿ4VQ‹æ$ K ™4'1†é/Œ€û2”ª¤Z)µZEÛ0M“ت² Àñ@Ûþý+µºó”­ Æ‘µkKÀ'†Là•x»àºôò“á1LhšR¶ÝHœž€¶0 h$x²p-˜äS–ƒx™ò‘²µÂ™[…ZŒªµ@ú8Pú‚E:ì²”˜>ìëR”Âx} àÛä,4¹õè™÷28Q²¯Í™S7ê‹»U«”4B¹ZL^ªl¼•o0µm®êàZžåNñY·¢.Ô6OÙѸ·zéë=ôþ”:€Ì'ÝJ-­ž”R€Zç´ÂmsÓoõxð~¹ä/åÌxžº0éŽle1@¬¾jÉ€X@ɪš!%2™-¾TåpdŽŒ_/Up·4Y‚lÓÀmùÈòÁïÞ0º`˜§RÖnYkã­ÛÈA*YÃT(µmUÖæ_»NÑ'iT%4œEU4xìÔ@IDATHn \I©|0FYé; ,%Ò4­³µ’Sü<µ”> ` w?Í€¨Ý‹ÕÊ:Z‚4œÉO€!Ð͸ÌH%g¬oØú„>BâÊùH1—…Ze1ã9T…ìÅØ„ª¤"UuEȶÂÄ•·M ·å©éLèùÐ$аšJ ßA2L,+˜´UîP"á~øÙ`:W­ÄdnÍÀ+ïB”cª†‰¥úNh`%æé1]i…[FÌÛ´òw]I@I“»aûןñ)»4æ4‚'\I‚úrD#Àô&ÇP*Dýt‘uêå~`LX!¥U­ŸCemiâ³å‰Œ—p½6jzo¯W££.²éO)dñœÙƨ‹’‚²^5Ê? ˆo«ÓÝÏðZ@P2´liàÖfPȪÈÁú%Îå\›sá¹IÁñpâÌ­<Ý€C±]w|J€¾r€¥ð¨¤-–-šÖ‹@#˜• õkBüj•À=k…¥|ØÚa 'Æ#k$d…yÚî8˜Æ³Ò¨òBU`t÷>ЋÕfÛ¶.²‘[1ú¾­¥^‡v)#WeûΩœ Òj<Àx Jºda+6Ú˜C©5E°Â#¦ÖÜ^•,XÉ*¶R™Ã/ K¥±Òpv½dʵÀ”%Ãë"å!<Üݦ!S‹!<Œ ãÓ·¥mi~¸–XÉž”^n8¾*b[SEÒÄdHÓAâ­â-´åo]ëʹ¥ÌŽ!SnmK,d‹¶VY–˜- ”ç`uKîD¶¯Ó†Q…§´eX•·ô°rÊðyŸîߌô8``›;¯`7ØXeÂÖêâ€Úë¡P—Ë—@C‰ÌÓ‰9½ï ZwB¸3h¤àº¬EÔWÓñdYxAó×UV”ªÖV/›¹¨Jv]­U…Õ+·*4Àêô¸mu„>óJ(­˜d€¦ªºÎ¶"E¶dñ¶›áHï„È…,œÞšÕ&aØé0°¬îÉð¶V)°™¥È¬lmµ“‚eñu¯£UtX+|†»q3ŸesÖEž¨Ü„µ¨K2«,YC®@Ö:Ð$Ö^!)>j1½LlªGOÀxYïj¯±¾MÛ`ªD°°`®6ÆJ©–3+![á”0AéáŽÆœ ™lâüóÉÖÚHÔz‡åƺo£µ*?O1 ÀÄØÎŠIV‰ë¨»*ž¶xâJ°ª”ñ44²Ý0™”‚­HŒ¹ôŸ>éµ3 –-àDåô¥`àÚŸ?ÁMe…E½¬ñÙæ‰¬Ü8[ù0¡ÌRÏ g ¨‘¶Àžl²²Y1_!0¬íÛcÛ‡š§ß¼í4Ì‘<3´òìÑ#3Q Ù€Fõ²b”Ô¶IŽâ{œ‘Z¯QbáìÊ CÐ c<¿õA›3U «Äð¨R¹ñ‡3Lj4º²;fÊæ!c›áÛ®ìÌÍÉ„,5AVÝÛšZ;xóXmKÁÜ*Dª…7ìêÒl¥`ä‚•ÂuÄcÞl[½Š”¶@ß*ødȶ9D ´VØ6C8Ùà²@Û×êô¾o»_*œ!†ÿ}‡ ï¼<]—1²ð|\‚, x3q4LG Phå‰A¼T<ÆÛ˜¢Üé¸Õ±TY¸rJØ*¤Ûu¡áoõGqY)¯h%¶¹é±v½ÌJ˜à³XÑä£C€eù;$Í™ò~qIM“¬”•ƒ”U0”ðÉ0uÔ¹­©r£Qˆ™Õ ðbJ˜˜•ò¸Ñã­[-ú©í»bV¡øHUwðŸ/[dŒã ˜­/8œ±näV#@¨d3”z·0ó¾lçÓ‰¬5¢Ñ—!1 e]6u)JÙ…­ÆZÌ ·'õ*ßvçþûßÿÖ¸&ËC÷˜Ž»5)OÅ(õ° JÖ³t_‚‰o¢î¯DJ>”·âw%`7€ª»¯&ʾ” æÚ/‡EÆAJɯÏTnU€PiUkÛR°v1ÚÆX¹•Êd¶uñè9“峋Jf5mcÃJÄôm«m<øÔT6O`µ•Û&ËÙš2mk†0Ox]v¢•Ï„ÿ+€s#ÈÀ4¼-r†ut!Ýy)xæÏqÃãmé…”ÀÈÚªI-h'"Í3“‰•@ Ä?ú۞3ÜÀ“arÃy‚m1g¬g°¾„½½4>˜9[i2W(Õ*7•UÈÂï/ª: 5L–-+Cë™àú‡YõñÔÖ—`n‘VåÖÜ FÓ$xþdõUã“HY ±­cJY…-«µiÕÊÚZµËÐÑo/H‚®e2 ù‘g$,€ð :ª*Õ„­˜Ržš3šÁ¨ªºk`âYUu'ê’ù[â8NAŒ\#[ÁP¶{¨IV£¶µ°U¿µl+ÿðù'ÜÓéᣢqCPÀ€€)Þ“Fb: ìv8: A¼•RJdÉ8ˆ†ë'“;r¡}‰+yÒÀõª*ž¡è#4%¬P¥#ŒÙR¶YÉ:‘ ‘RéÛZiD[@á»Q’­r¿M1¶”¥ŒÀÎæt'H˜²^MX;7³/ˆÑ”*l­ÖÊce(ÚÆ($àiXkÀ%X#¼Õl½è¶n;)2Ï­Ž@—Z•¥’Y•[…”¨€ySZë›@ŠìÔz²™(Ä[{:d|0™[µ[Ø*´¥‡‰á†W%dÕiüëvm­µP+«\ä#7†”›TXŠ!`K¶s¨‘µ8¦w°Ú)|NƒIf ¬ð͆·rÓT¡#(ÉÁzgù C<çéX–Í“@Ï©EŸ\)äU1ȪjÝåÈî­ètïÏÕkF™-^Øj±+5UƒIÕÈŠiÕîÔ Å5Aö'Õw6)zL@Q9¾cFZû`®$0¤µÔ‚,[Ø4›Ö–³-M²”x¡QJÀv³×øóøVKæÞÊbšÊj}|X¶ Y•’”R1­Ä=£•š"gU#OØÙe1ÂÝb„^™ä)X)eªíÒlSšGÖHEbd«°µ#ÃX¹WÕïcxšjúÄô}«Hu¨Í†Ê ‰‡­‡„ ‰IPÊxH-Š™¦¬µù „B[†0 +jÔ+D ΧWšH®ëVcnkõeIuE”›@yµd¥hŽõ÷wˆÓùÛ› î’Á”€E:[²fÈ-ÛJˆE<°Âªlyf‹yçQ"b¬Ž©ÜYÌCi›Àºû3 %l›!~óè>%g¶¶ô I[u¯©,Õ†çIV-FØŠ¶À_ã s7@Ïs$¾BfÀÇ©­1®÷ùFN̹ڞ2Þ‹ÁjµnŒ’s%­¹Yi¦Ö¶Lª“Z«­\Ö¶C%k+«ûnµ|”¶J¬¶õêÂÒGŸÆ*[‰¬Ó…kW*L)´Î¹¤lJo0d|7I£/Aßžî –âàtüïÿ{ï}ú½_é«Á1b¯c¿n*Y­9o*Y¤Z>UÊQGíl âu©Q%”ªüÈa«Ð.&  Š0Œe[yº"MÛNoUÝäæq´pÙÙ"ÙÚ2Ù©m; FØŠÛÿ,9ÔTÖ¶Z%² oÑç[µÚ·i ™*z[Yg©£kqÏQv@ ¾#mñªò)Ëܶy惡džØ*%´²ÜÜR'²u·Vo7U{kG† #=enl¹)÷¬÷RÅHáßÀ«Åpn87)zD¯½ù`4Rb+:R-¬i{“Ÿo*V‡… w8=MÝ9t.¼`Bï7lY½\Ríµù|”\ FÊEñiH%Œ§Q‹YÊäbV¥š„2ÞJ#e*ÁD—þ0–î€?õ€*¤ç“ [顯cÎi8+ì°éËÂÛ4 S¶*<€/u îs̹ã`zÖ”² ¬l >">7³*>”ÖN‡S"E8C¤S“ ¤÷(Ùú.u™²°* r .ÄB­HÐxÄN³ûÚX7vzbÙ*AÚ6ØH[…(°1R‹¬EYIQm“ëH`ų¢éŒ‚¹×ÆÖGÀJ€¬Ÿ¹U9žk³Õ³[R"\H¤š'CÛ e…myÝ éíÍ“ÆV°M¦×­>‡ÍÁ–­¦”°rkÄ;é^–èÈÊ=}£ >»O‚‚¸#07+½0¢*²H@ùªê¾{«i…H‡âç-1[€f>Ü*‘Mæç;†[@½kÛW xÛæì c•í¤1úÖÓæûmfkl[©Ž™¸§ u™ÿpgÓ2²€ö*sÉ—ˆ‘Í‘‘ÐÄ0åÂ6O¤­òœñM‰Ág.E&à &àE-€HÙ®¦< ðÖ&ê¨ `kʦÂÔZIþß6ð¦Êré p§H=>Ÿ¹éhl±vÉô•X«ºÄé¾á"åw÷󟯃ãð‘«\ wW¶}ŠÊÆ+ù?ºîeK¶¤V¢h£¾Á¿CÿN÷aédqÕ’Éd’ûÞ™çPöÉ|Þ 6T…[›×ÈÀøÅhp}± xV)΋¬D0ÂÈâÛÄ“U 䉧ojHšh¬%õ ˜@Y\ï~ä+içkä#䥉hoz|¸•pÂ¥ÅË›ØOœ¾øœ®֯颀ƒø<ó]‚b¦Ú’y; T‚º8£O– fg'e„xûÔ…O¾‚@?tÓç©á+½ÖPK&U'²Ó ±©VZ@“>ëhá-AeM@–ïNÍàÝ^ë%ÎKшä-ÖŸ!ªºÂϘïyÄ«âÀ›³.%;„ˆqš+.ES§“·*&›¦9šÝpÄÄ1Ã!ønÀ”¼S °J] 2sçR-ª-_é®ö¹%½¤pZy| Àg5J[UWçA#ASÂŽp-õ =<)A#Ú”vßBöö*FcJ5¾´£©jÉk¤†œXÆ8¸ËÁ× d µRÐÅæ¾‚1OÿUP‚0Lú= !D"êt¶^ü·×’p½Gë8qZ¦Fà,žU"âåwR½µ¯%<°.©€‡ë‚Ø„ ©p¥žBL&6gk0Õ»Úç³!ËÉâS#”•:»Ï‚jâG÷Žˆ FËnåLoɳÍ}åÞ*¤T€Ét‰ÓI¡T©SÇ«U;õ–@úæ™ÎDÎŒû¡àÓß”¾ÙAçE  o ¯“*C·M´vkO¾ALŒOGI{Õ‚÷…ÇÁÇ1š½½½Bž‚jÇL-šÆío%L¦„¿YRÕN­‰<)U-Äéøµ­T—j)~RñU-Ð>;ÆÁ.æ; Yí|(@cÍåÙ6·a‘•¨ÕS¯*|#¤âéL¡)ðìL½s¥4íÜéܰSMI n[©€² «Z#~RpÖy¡KäÅÌjüío‘“tw¥äH¤B](€ºSdVNDÚ Ïè« ”èð┓mtÌ+ùùÕ3L ºÌUíð‚¤¥<>Ðæ˜‚í9°K„t4¬ð×àu¡e—ûÇìD˜GnÏ¥@½¦C'åy C# lVsA#Z8æD¤ðùº,)mРɤÀMoVRï,d4· ¬¥*fg¯1}ñ2©)kŒ¦1æRȆ( ˆÄ Ô5YˆÝ¯ªT °G —U-.múîÐô^LÛV¥ªïŽÑÝL¿dè·0eÌžEâTuI}ÙQ Ö¯pU䮺 yC3(¦‡õu Zé?Ÿ…–Ç$ËìC\ f%dx XHØùh]©˜ ¼²F‚Lðr(ãt ZjÌKY½¼•¤˜,ü”ï Ódb4^» ØDúç ¾¿nÂGÆ/^ 9$M„F™öFð1SàSuWb¦‹'ë˜)ÔÒ\RžK›ë‚óJ™Ao^0)%~Sl:·éœYˆÆ¬¤*è[EÕïÙÀÆ¥@œ½:Z¤ŒN×hU:ÀÆ JiÆ?³ïe*%¨%>&õ“,Áw9Þ(RDî"ç!f@†À0}p´ 'Å£µ†@•LJ‘‚x¿#Š{4;lÛõjl1|we"~"øªíV ¯JA‰IÅák¬}„W¡WEIW1Á2Xc>eÕ¶Õ‚&fU#7§ÑðøÀZ¤¡9fU%&>r÷àùÑÌÃñÅIYo÷¬Ô‰§‰É¦&~õí9ðrÏÅn ¼›I¤'‘ŠÛÁ,4–¸@{RâFäZð¥ïÅn½DÐBø,Mq¥œßÿZF#³djªÈR›ÔK„E SìOào©¡‡Ð´€TKŸqRF4âÒÐúÎÇ´íKDºw©v8K2ÒWÎ& Š‘o÷qÅ|OÁ nF­#Çì„Üæ‚ø˜ûw|UˆYiÚüh}¦¦Ácæ¥ML*}„Ö#‹óÇ¿þõ/›iKZŠíîtê¯M'Ch9*¡¬ßì<6|A´^ ”)¨¦`4„Ý ?dž´%_ãd+Áô#¡,îÆÅ‰#ðø”|:Gë¿­“ÂYÅb],Ð )Ê⎟rï¥ÞGŒÃTû>PÓ®´% ¬Ž“½k|±Ï;G3>ü.øÙ°UwKuE¨DØ…ôrôŒv?v@h=Aiw›líz™¸”·2P/5.f®¸é<”–¦@ðA‡éïuµd¿ t„-™rjhºØcŠÀ#0`v–{~Å,æ7×8|£·‘V%¡YâÚJÊÐòpAoHÕVÒÞ·ÞVÕb ²3‘-Œ–Ž®§Y­ܯb8ôuUmÉ@:Ýeãx%8¾¸.¨ ­X—A .fñU)ki¢XÀBÐܧÝâ»ü×ÖhKªÑ|ßøp‚ÒdIu@½gÞ×(0{êBó&ª‡7‘ Aµ0¦प&Ïpì D£TŒé'ã#°d âw'Z(­ï—ƒwÍ¥yÖJIiÇw!‚mŽI ¶¼Øh©“Bgá¥ÀZÄ&JÙþãBF®Ý2ÿùÏZÀzþq|o£€¥\°S1¨5€ÖÐëBèìzw™˜Æ1Lq«àëÚzôOY* ¥‹Nµq˜¶ª:ÌÕÚ-#ÖË+µþYå¾6Mĉ&eJ@që‰!K'Rº§¦¥¡Z*ñIAv©ãà‹µdqĵ7…ßÐ¥ÚÄ Ö‚ù’cª‡×.] ~ùÒÎR£ûÔ‰Æ÷ ©FÐ É«‘„nœàtÞýÅ—~Þ‡ž{Ï1…¯KÀtÐùs€¯7¦GÊ”RNa²p/áŽÙñkLM)-˜Jýˆ‰ t„ÀDLAТD©òKC2ävÃÇüÒ©îÈo.ĉ@„AÒQµ3f»ñJÑêB6ôׯ=JWæè¨²Ž\êÁAè·@ã.듵.AÓõ‘yß ˜5¶Œ IQV𬃷[#B|úÚÓAÆ/Õ‚f–*ñD¤í\ AWhç•x|V 1®”¬Ô_Ju±NªWÜt1ŽÔ¸~úë2«žATSÌtIÿøç?ÿiª[áis O=×,À1ŸéÅä! 'PS*îj´#HñiR“~öø~xÒÁÑÒJ‰ó–d•6W»'-µŒ‰ªb"FŠq´S(1´–ÑŸ)#\âçÏ<µ‡ŒƒIŸOÍt%LÓ@f.s(ÞÂõòñùwG¦/…7‚Z]Ò—OYõ,t ^{Êõ*"Û‰lÞ]Õ¨«ß”‚>>„ó¼V œá‹©½"ïJz¥˜zq¤V‚¤É+ÕγÄÉÞiÇmOUéeWŒ‰À“õèÛGɬzUYæ¶y³ÚS@'ŽÒG×ÁÝaúp½¿¾ï:]„n¦£Q ÖË\µ} N¡‹,k™Zàíàck£Q`@¾Fߪ(ó$Mq³R¸ã4Ë‚Æñªà}鳘ºØ-ð›^Už¥Ðn–1šU’ ¤£ms"‡ýý ÓÄ´ÏYâÞÁ<‚3ÜnÄ Þ}çœßÏT]-Æ“bþ]UÛšqKUµ4±²^<4)2Ð;d@%§Óe®!"vÕ}"Š”ÏCè§)-zÍ‹ßbh©ÁõvØZÆi4ÿš*‹FÜO)í6ék˜²’‰nFl„”%R5±vvîý^\€\‚õ"¥!Z´ ͳÊ5C]fG&ˆ–i ðZ Jé¨ò™.Õùf·0N´µH“Âë¨Fë ¤Y»I=ߎ/Þ>¤4&®¤—†hÇÙdj ­1©iJßã`fðŒ,¿[à í tãÓŒ3o£éà¼ß ó[h±½R‚†"ˆ!ðD¦Ð¥ùIhb%nÆæø¤öž•¬*h Bw+í¹ØG#Z‚&}HédÛ×B¤ÑÝò~pq â–w| ¨ŠÎDè°– œ‚ •ÚA5K_µãwX%Ê-J7W»j-¥bÜbð{¬þgy”>“f)2#˜Å¥¬ƒ@ǬK5‹ TŠÙÆ©ÒÔÕVk-Mt8ß_ë¨ÂÍ…h¿ëœ¯¸b'bZÒÄCôŠóì<{†j‰xÊpžœJ02œ_ ª‘Çl0&“ò“jg ÙQü¾ÐdÖs÷û#l-¼’GŒ/n\úí¯«)h ÍbM„„¦‘xÊ_M6½C‰#·и&BU ê XâUueª! ëZ”=>]N„ dÄ6Is>þR_¸ÈÒFtÏo¯82e&v ¿= vð¿•&°)%ÖË÷*vÉ<Ñ0™F í©î]¥o+UR­—?P4¬ä{ÖÅWøç-¬U·!„h1®´í ¥³ÝZ@jrO‡`çAŠ ‚¸TU@ !æ­|þ–ѵ û3gûÐ7Èéàhkt3h&6+5d)£•,ÆÓÁœ!+ x|&`NDJ`4?Sc½@ûت)m…ææ5¥µ¯—²ÊL@į콊˜3àûOAoûHÓ‘"wÀR]Û}N'Pbbdžê*¬­*U]N 5SE†³Û}\8_;ržI_;ÍßÏŽÞ⼓zÅVEoÇ„) *mœ4Kä›ÿ´וi·@© ™Þž¹mÞxzÅãt“¶%®Ä·pÊM´³Õö×Õ´f¸YªÖÄWbâ˜éW ·LkS¸Üóo\-ÜÐvNmšÀÖÐd©õ •R0³Äª– YˆC¨·_~ÄxÖS‹œ²}"85¯\Ð…ðbH„ÎcvQ®‚&S3úWì\Z§NP‰Ž8¾ª˜´ íÍ‚wQ8y„ø„‰ Uj+%üz1áPjúbS2v‹io\]ð˜8]‰¤=ÍtjW@Ø™q/“)Ñì{u‡úóP-˜|-‚¤0[©óWÂw‡Å¼mUyq˸^:i 8m… ÀTêZ¤m"`píÑœåüKÀÉI\‡oa©ÀH¤„ò;UÍ¥‰¦KšÁñ!h¥öŠÓ¬Å ²z½8R´†Jñ;j:b†\À#ÏÞRãbPNm½ ­],ˆÏ³ºj‘¶À­œéºØÂ šR»czBèÙ×Þû$ž²Aïñ]f÷©‹)U5‹ZÖÕQ¤£EÐAH;KüªF›§^žb2ivÇióöÜ OŠ¡ñªÖËÚÈRU #ÇD€¤ † °l+d8)&À‡°ÚÖÃc^Öù}%Â…O¡jg¤V;/n^/Ѓ0U&˜š€PàB ò•T™&оc ¬/ˆÏ¿"Z†`JUÓ|ù@Ï¢)h¬ƒ“m(Ï4*%˜ÿêK·ÞVŠÓ8ƒ˜R—£”l XÉ¢b+dT)~íF„D¸ðç·çÅÑ´Ÿ Åû\ã;®‘¬se« 2²âÈÒâVªRxωX^  DçûNHS‚ŒÞYvöJùé×N_»9}½=ß”[  IœT#.Ç?¸ßïÓÀÙï+41ãç!LlÌRÓ™p‚#è^Õ Uv'·ïóEo«VMYÜž8ïDÀp|:8Íæ!”yUÌW¹•øÈž…X;ß_}ÃDàY´â»ÅÏzKµ¼Ck$%e¦H”™ØÂÀô;E²@8"Ào[Uçm=q–f² ñÈéÔÕæ.SJ“WM¼÷ AàÅóÛB—l‡“öY‹“TÕ-€§i´RO­*pGPmωT…ÍkÔžÕÎKÛ¤ Íy¦…§6~dQÐ1oÓùÍŒ –ÚŠïí­=å_ÉÏ%í´tº ‚nÒ1kk 0A (1EÊ“b‘ÃK›(Ž¡. q~HGVÊ”˜éá&ò žm®•’ø¾.ZO;„ ’xßHÒzûá<§zþÞ§qLÕJÔìi%é-žéáJ=)i;SŸgJÅÛ‚mï5‡Ð= `g5b à¦HÛ­F)!þ‚&ò”ñáG6K#ßG†¬©•yg)Ef­Š/ÝÎb8œo±)KÍ”ªçõƒŒaR¼NH.0œ„ò<¼ºÛ°5ÒÔÔX€Lj¬·ØÎÞýŠÐ2ªµ·¼’ ¡”‡Ä¯]Ê:ˆG&¶yCÞ=ž,Sª]@¡SCÄ•œâÕ ŒÙô J ¦V —u.k8¦F¦Å2Œr;˜+`p¤ÆˆkY¼NjUÍ¢ÔC 5úÊœC úº¨‘o¨gä÷g¥ž,OÇb<Üèö)U’峦ˆwÓó·påÄq@"ç:¾?µÛ-\I1™Ž®õ¦<r8A©F± Ôò¾réŃkÇÑÈ’jW×a¥pVcâÈdYUƒJù˜ùî™ÔçßP@ÚêRµD R–D^Ú0ó²hb³5¶=š °)³YríK‘ᮣŠȢÅ7wk¤ k8¦Æ!ðÈ|¦%ò|Èü—øy_¥˜3»aaÐZŠÙ1U{‚À.–ÔëâÝISø>¨º|nca‰ÛAP#©4¥,œß-!”ê¢ e˜öÁˆCª"KÅ™.4»ñ˜o¦ÎÖ¶p;ôÿŠçkNÉA0S t¼x:5&Åã#gRfÄl]_Êçg4L1ëN]ÊCZÀ¹2«Ö‹™¹=ˆ˜‹¬·%IáŠÖZ\DWâ-†Æ zé‡`J5RÖ;šTïÖ®W \Ì‹«Š²ÞÔJ¾yÉ ¤ªq €,$MéÏ tÄ5 Y ÷ÿõÒØUã°Öð’¤c q%² ’ŠYÊÅÆðªJ‚³ß=×ËQm÷šÕ>R–xw¥]5¼ !ÄÏ]\SÂÌÍSܤ ŽÜ§8>Ïj¯‘7—BoW Kƒ#C^K4ˆ*C·L]R;DàýÖÕO\í¶*­E{ÿ4¼ýµðuY¥¯xéKó-ÓD J[LÜDÓ«¢Ù³/‡y%8òØMÕbZhº.L%8¤Æf54>CÀl+ >Œ˜ Rµ•vHsTy8Ï´Ï à•œEI¬‹‰³8Fî:çKÀzÝCL£Ôq^i‡­¤Eɨdž‘Ūy]o 2|„8¥ÄC!h¸­çñÙYlè–l´[…×Ë«– œN#šmFÔËCRK¹gW;äÝdÊyN9M‚LÌ´3)ýR±û ”ôJu‘õ¡èmi7U—$².L:p&æQbhqi´øÕöìmÔn®•ümšªÃqí–1]cx'U"˜N£§¿ÒDš_`3¿–)Ç”zëLé[ˆéf('1WÚÛ{Ú¾¿´O;„ß”!ô5¢ ŠÑTäñ×Õ8 Ãazñy1‚ÑZ†+éekLvˆÓþ#§ /À¯åîço2 &GÓ%†óª<ƒ ˜è•¤¼…÷¤=Ù-d R«2AÊyH÷ ¢jbMlCümrþ’ksÏ¥ôý˜ŠþöNBÊ6U!³bL:h1#nDPÐ*pUoÛ@³ µS“Z"Ö%eÅUÉ ´³®@o©óo×…œö,2þÒ‘,ÐJÅ||[9…ÑR¾@ìÅr“Ò!z!ö0:ŪtøœBO³s‰µÃÝjAwEÜD>ƒ#tAñªã(ANÿ51… €Ã×%èì–i=4ßn<¼M”¤Ø tàg¿{ùühZ´ó´(9/²í öžð8˜H?Á¦Cèðº¼*kC½ «WP•{v!®•|R€ýÕ¦ FãH)õ}Ú竵“âK¼U‚¬"‹YG[¯˜2މIémn4)Ï”Ž•”€Õ©Åd8í]j–Ôt1óvð+TwØôy"ðí †HuY»ÑÀ¤ñ!í“—f¥8æB¤â·÷Å©Iº„J|»^U3âDÞJhýJIá#[^€PÉ­ ¤Tõ»õÙ³µ<ç)óÞJú@jq¤Iéb­§”)Q†k!R,UµžoZx£Kq2©^U)æ5FH³é(ÁíÀ7tq|jZ”è#×È38Ÿw½oµ’#£ÑÉÄMô¤Z’&ÐÛ”@o7(î÷{Õ¦è¥C„gææ5^àó‰kzÇ©´ ÛØR³X-h,_*Ö¤l\ÒJAûv6Ç3ǯ±åSÓËŒøe@ü×#ÐçOÃýÇÒ¤æÒø/…Lt½î–>!bq ô‘3]hY‚LÐ8F‚ì SHVŽœ%¹}Ÿm+5+<ýÆ©6A;0Ž5¤¦ 49æªí³!ò¤:B)k+ÈÒ@½‚Ú§—õ+V].Ózm%f–©T»˜HœJR¥U#oÊ&¶¡F¦‘ò^ûž,&ó ïØÏÏP¥>­ö¤Ì«ºU8AP`:µF1BÊ‹[¸F?ùn¸*‘RüPb˜ªáJP`"M%òËôF¾2A3+¯Ú¯f9å6GЂÓÝêJ³Ñæ*áÄçõÖi"ß’SëPh4£%Uã+RKoHÛ’Ò‚ÃÄVíy…ã×¢ŠO߃€hÉz|þ´ ÄäÏÿ (T¢A'ˆ÷ìI˜!Õi?9¥š#óá |.,­…rx‚@C{¥:¼’»‹l“8Û*©||±Ýøn ŽX êVªw›HÑxH†¿UÅ žTÇQep»eqÐMDØ Ç©‘o½&&¢«ÞW“¬ª’A ÔΜ”# )¥ÃÃ3qkÍ“òE,Ài;3¶¹¥a~4ˆÑ<>‚â~û÷C´ÛЉ˜}öÒäk‡3d)e+ñÛIÃáÓÔÒ·Uµªp†ÖÂ+YOÀñÚzk§ ˜I‘©éu8¤“š"6H:hNаF_‰TÒ¢ÊЀ½-)eÒ®K¹JtÚg]Íí°DTYã®ØÑgmâ §½‹´C¥Ï3]–çqâ¡kª6t%AC¥g‰kèY½=²˜ÖÔŽ££ãÇüHÜÿ@›¤Zö‰B¬ÚÎJãÐì‰ ˆáȆ6Q *¥™¾4M!/Ð¥×\×(è!N™NÖ 4Ñ\WSxä84“EÀ¤¬i1->,˜á5ÞŽ³P‹ÃêGƒH[F€ ±ª{fg" Î’… ¤­!@(æà„ó­ÚqJM¤£×\-Rl4Zãø4!ª|©‹ÕÒí½$µÀ[ÏÁiÑ=lp <ÓBŸT#jÄ”"ð‰ pàbD*ÙRÕ&“…ÜiçY$ò6ªÂ‘»®5¢ÕKÐIö߯œaßOz'}5[ohßzÔô6NðŠ÷*Cðt]u1ríp âî§–@Èôë‚3àøvî©í ÚÁ¥-™¸’à]áŠ}^°âé8µ* ÕôÄÝ’”ÅL0²F/›m“âYí5&åÔpÕÀ8ân Óud÷Ù ^L¤–ôq¢Mp-R£‰µCФl:ÔT$P— DUªë?o5„QkgŸ1ƒ×’‚ßÚ] & ,“B·× ^Õ ºÛ™48Z‚JöIäÝÎù”;à<…JF¡ NómÌë2šj—™r ´|"ÕV­½ø‚öWÒX0Ÿ BC¥l|4F¤Þ4!@£™«p‡—x¾ÉÅUy)œ FépJÔ)üa=»¦ógŸ¿üå/"Ö³tiÏÒ`*—nãªkl)³ƒ§I¡Ã´td:ÈZp1_)M UÛ¤…{Bº €¥¼®yU~ÌñÓ9‘@™¸Mj‰@Ê dC"㲞j'CÒñ`"·¹{`é×%nSÕ®W•2A7 Íé“õ¼”jÁ×(mC´ŒB¸ R:º¼ºA0‚È·€€Í¾†ÌTíÀÛ­;is`©RL{jí—NžYo§Æ„èJ02€ÖØ€ˆñ *‰µ L3ÔÎðÒ6¡³¢†óïyu”¦@5M1¢³„Ä"÷OWOv©XâSV¥c¾[ª‘gªoPûð”z£uºîÊOªû¬ZêÎÓáñ[@,èq §ÃÃYASÄ g¸ } nCµ5-Ö°óú¡áDF³XPc4žˆ^ÁpR ¿qÎ(Ý›&† ±F uë1‰UÚékm~e!NRÔªk¿õã¤fb2hb 8¤Àh%«Ú'5Ì»ÔÙÊ”VíºtAò˜îÇOâZÒ×KpúÊÀºÈéhŒ Ünhp4²ðRƒg­D„uR²~OEö+ŽßAš ™,\l:`öZFîZRhUú,„×®1qžu'ÈpûØ È7®¿Ë~~·ÏZ”Bê-æ3 £ÆCl8~GPšÝÎôv@Ð"Õ¢1ГØJWüµM$t ‚µwð‘õ¦¯+~íhÒëNlHʵëó®Q¯ªB—‰/eª¼|–üõ¯%ÚKÐBÒË<ïÍaÜÇ !°mR1ž©Qª i°-)´7¹ŸQUÒå €ÇI8f:qì† N-¾ÞÎ’ˆ á–‘Šë…HóÑ,³U#PÎ@9šÞpiH Ä>8Œx"öCrˆUA¾Ë‘’í\u‰I½ÇiU-È)©ß32]ÈL Š#Ž)uÌ@KgÒvp:L^»´jšÒ6T…t¨˜®Î 3¾.qw+n~×%~,[»R+ v³nýçÒb=‹M¬JŠHkØÐz|jùJÅöDè~4j‡Xȳ ÚŸŽªö ŠSC BÍÛ¹%õÒah‘ßH§ý-ߺZ¬Ñp4 A—–”TLÄÎ E¾3Ïw#k[àkô_S"¡õ|xékBˆXCÚÎ]fÙ^;¬‘W*¥'¤­&E¤o•)÷¦Iµ³¦tR‘¥)äÓÄ´ÀÔÚÿWà:QË7 'R+Æ´¹X@\q©Mx4d8t·p4Ùªp´^qÒ-peŽKG@*›²ûk¤ °["t ðßãà@šR\ ‘fÎ’l`M/%Ë0á>&bú¥Ÿþï’ñµ§À+µªµ‰ð®“”ªYZ ÚdúݵÐé ™2¦˜à¦·¹Tï ‡/æu1Ðzí³AÀÄÅý×B Hÿ—?Ô;b½é‘MÑ+P¥Ðz-,n%%4÷Ó ð¯öy¾˜éW ðM—¾kàwoqê2qgQH™ö³úÝ£eðÉŠ­§d«ø %’¥ÀŸ1×ôâ¿ø/M5o„qºjLSlz›˜¥Ý>˜ª¥JLœÎí>'ÂÄi4d)vdƒèð­#o1dÓ¡Ä”êB6¥Úi8 „Àź <8àù€*uÒT㳪։ôaLëKÿ¼ñRþJœ$µù4©õ)M–‡w‚4ä5ÒÙÜÍZ¯êËitUíÉÖ•¤–æòµ«Â³¶¬R‚1ÛSöô:}q4q·ß1§“2j|&ÞD‚$#› œ ëeéÃSô/˜{ÄU‘SíDÀÔ€_áϯÈéµEØ>‚-SI3Ž,î'½)ÓÇüïÞ°o¾¸­J­*Z§p-Ô¤uE Bë‘U’ ²ø!Ȧ3`x#ÄySx´ŠÈ/†S®Å¬­ü–cI4‡êìR%SZÞVŽŒ`¨¸é©¡±bUš6îàb C ²[t %x„Ò@²w\ÊÑŒc‰[cdeÌÞ[diÈ8R]ȶÅlˆ*ëàºÄÎØ÷‰®[üü$SÅoaxÓÛŸµ@bíR‚mUÉDjRÕ­× øL© ©½/Ø&ª ¹ g-ÞJR‰”õÌrL½bU`ÓÅÄ¥J1D#„&U‰‚õ”Dœfk½fÀRíJ»vÞòºüßZz¬ÒŽ)Å”jQ0‚b|ñ8u‰{jþŸ€1;;š? ПB"ÒL—•õš%ÅwLiˆ/´R|Õf)un† ¸’Ø=Hiîf”Ö ¼ÂçÍ”¤‚üÅ>j⺄Éá©ej)ØVZUÌU!Ìiú–Ö‰ H!ðÌ»›»½º®Òç¹àHùNÔ¢AØv.M§)4|Þí)-E ¶vAó˜d« šÕ“ã8Ÿ>2“F+m+Þˆ, eº ü˜@)0»›_™ŸÌpF ­­#`v¥é¬¥›1z³ $˿խ i¢q¦H‰[€lH‰0ç!hÀŽ?Íh½-^ )& §À b¾FgÕø¦ÐQbÈ%i ‚Ô´Oó6}4»1%²{åš…Ö‡·F¾ e›Îã›Åœz*IZ˜‰âÞ µ  ^KÓƦ¬Å”=šduáÁKµÃcæ¥@¥p:ö9Kð¿ä@S´°K<ÏEÌ3üFw®NªÚ 4Ž·¤ûklʽ$ÒZèDN0&N'‡#³VEè]’RPµ$¤&M£µs½ …K)ëÅÔØ #wvAÌR“jD³Në%‰3&2e¾ÝúÑÓ&qàR8ÎN–ECç„iT…óºÐÄÖèìRÅJGåûí S{"é#‘á!1S_ãÄ@½øÃ[¦Ni½¼ ‰™ïÞ((1d^Ê:#dË ' ©ê\FhI­ÞÒ˜â$©†JMQm„´Ÿ#zy–þDÚÐ)ˆ0¿ÕµIL>A´î‡7¥ªÀcmy›G®š~O“§ÌK{‘¡]lÊ¥ l„JR%8H^s t@é‹r¸•ļ˜A•‰C¿‡Õ¨ a˜·ãóFmÉ5b²8‘Óèݦ“¦œ¸*C“ªŠùÖÃw·¼ãÀ¡ÊÄ)ˆuUå[c¸ ç“íµ§Ðs´v›Ÿ1_SÅoa‹¶¸RtS T kÉ› GƒSNª1§ƒO³€gªÑR§­R4H%)œ”)Þs'í)¸U8\•M$Z ½·ÍåÑ’ô©¡ï ¤Pm`³¤yÓOìßõÍ®¹~b-A«Ób]“þ=¶pFNª¥¥bÌD¤¬íÑžD%½^š‚!ÄЪґÛ'|iA¨š‚éNª÷.r‰R;ðªÌµ: €ùÒøâK?› *¥SIœN½81­ÑévsEð_ú•TµÅ1ùp:Iפ­g´Øsä_‘6äJU·8?k±º¬!h±FAí& šn“ôùZÎîùÙ ê’ý„ ~ ×µÑv#È6”°”²”ÏÖ«ÚJp±ëÄ<§½¯¤éé7´^~`H‚Z¢ à•xG&+p4ÏÆ×ÌõŸ|C¤£$àû㈉´í4S ËÞéÁgµÅZ¤ø©ñR~g¬·*ÐE€Ü9?_÷˜@‚µ8`úáJíDÂð™Øû€ÆTÔE)¡##hDÓg‰×>È€F°ªùUtšU h¨¸%©á§Ð8 C1íÈY%~)©8t˜8+½Ûý|¿ëUU‚ ¤f±î*eï0Ìd-#À„w %§Û»´þ„†É0»Ì¤(k„cBü•[R-ib¥n[©.ÿB]Rš†ê344œhõÂl#ôú°wR tâc¶ª+UíÔ•Ð!ÀÙ\²†VÅÄñ5 ˜“J•Äç‚î{kÐ׎FøQ2¥e”Ähq’¥×ÅÄv‹ *à·@|dAž~´ZlÎè•pL³Øð˜KMEܬ_¤–¯Hœœá7 ˜B%žÔá}_תu5T¬*¦ÎÞ^#¬_`·öTÒr–ø^£@I{;ó½œz/÷óÎwdži13K‚ß/@ĉà‹-S£ÄÈK‘ÑÚ`:8º” Uyq§ÞÜ‚ðñuy0µPë•xFÌ\%Hšb½ðt¤b  áðª .ÎÄÈqÄJq;Nãøf ’Rh°^x CLÇÁWbR㤠Š=¯4«*±ºø‚FˆÇ4¹Ø&Š©]ã¤|pãt­Ž3ÛÁhDª7f¥µñªë•bîêZúJñ  $ÅÙA )ðD2 €M‹wµ¯88ÂŽÖ]…¸À›CsïUœvÐ«Š–>š­€F@JùMo™l‡ó¿DÝǵWDFBKjj ‰T òfâÚU»^ió"é´_+òJLЬ¹í=þZÒW5¢).ˆ 8)ˆ4W´›8ÃÑh=C§Ð¸­Ú,œ®q"@Áv躾ÎPíÄyoh©*YÞª8¥Ý­T‰ tÁK_P¬·ª3ÚÈõÚ¤} ÞãêrjVåÃq€ui±j?}źpðY¾ œÏZLÕÒËýÙ*ŽB"F JVê‹X#¼­*©ÀÅ<ƒ$RUª%|©¸#8oœÖSJ'œ`Ë[FÀ=Ç MŒ–dÖÐJéoIˆ‹•ö½|µ?ÿ%ƒžo„TÀÑËRP…3R@!‚­!Õa‚ªâð.JìÔ,4:Œe©qñzM]ÅéLÁáö¬—‡ Cj¹sÎõ g˜YäŽo ÕÞÀ޳­(´F:6Ä\lœ4Aq¸”x v-©EŽÿzÕsòç»´XoÇÙ˜Öc½TDXçÕ‚W ô‘Tê‚8)NUAœ”y´tZFõ%¨â@âã@ìVþz8æßöº^Öª|¸®‚d»:UÇQê8¼t³íVãÑÒ¬KÕUìÔhFp^gô]¬`ë%Ût2ßȪñ)°bR¾QÅ¥h-–Á’-ÜGÙÿp F=¤MíÑBXq¨ŽÓˆ¦‹é‡èm¶– ‚#—ŠCødz ­=0ÎÛ˜Tï.µôÑÄÛÊk —ŽÐž|4íôI±žŽÀzáÛ>Sj®ªx{1ò8‚®.B;  )ÅÜ]¥i 4A”T50_{Rv0ņLÌâ7nII™ÒzDªK»|ƒ.÷¬ºMÚ¹TUË ðû…Ð| ø¢?·8¸^|8/E#2rƒ6žé²dWÑ› 7ô=EÊU#ãã¬ý2 k+s_5©ÔT;l]ª  «FïÅÀifU)‚˜Bo)D5lù RÊöÚ'…Ùo¦ˆY]ªìfD±[57)C¦Y šð]C»*q¾F)hR²<~÷TPW-‘ñ:õ˜Ú¯Êk©‹×ÈÇÑb¥Žl1qLi«âˆ“Ò•þgÑgœ`»ÑÁL¼qªV…o1S¤á@—I6š´YÒYßãh­g„’Y<°¸®FòÈT•ÚG•)…ˆ na±*KÓòýÆæg<2&Ãdhë- GÀìM“&eâ‚@}².@Sµ´û§ QÝ÷C85fVä)`â3Õ¼Mˆø—¤b¾®sÎ{Òhø!mÂg”g›Ž)&+eRgÁ'…LJ,èéJ«ŠÀ®®*)߃«ŠÉˆ°^©vk„!ŪYâÀÈ8V:ßA}O¦FGµhÒm3¯ªDS‹çb\Ì››BŸ¥ð"ó@ÞL-ág®?@±–\Ôf÷Å­ß«gáZ–@y:Œ¯%„gRUþvœ{/®ØVpLx:•Ä1Ã¥# ºšñU_Ábš;r%ín“š´‡úNÔ"m1½b_£€onAïý±oø)L“_;Ú«fC0>k¨eL©D!‘åÑÂ!¤ƒ *åÙºTц`ÖÕ”®îUÌӠ5„SÛW°ÔëÈ3WÄÓ¹ÙçóÜÜ!ò;©5Ú³µÛA,¨ÓO¦½£y#’ „€‚×Ú„”ApqG£ü^‚RÓµX©ÅZbh U" ÒÐÍ¥ ÷ÑW‹M32DÚD-džIcЉ,fp€<ñ N¹A¤" g}}ôÑÀa¤j£]ìsmXËy~_ôôÅ"ß2Ä æµ#Ø¡@,Èî:çŒÅªDÚÇq¤ºbò˜µ41Áb¾”HŸÙZêÕïz‰·í¦K3NO ¿w»*‰ÓTbÔÜŒF¦Eµv)©ó¥mK¹Y!=Á˜!ÄI±˜–Á¹+œ{£aÈž‹ŸgD€Èü†hÔ(¶yR¼)z×B„‚éx£½Õ1D@§vÓµØØJS+Ö(`Ml¦øŒã'W–DaÍ 1Ž‚R|‹±¼kÙÚÚ›+0 N'K„g´L*h.M±ª«ÄU˜À«òµ˜‹£”õã¨2%²<&pOJ\o]ºfËJ×N â¢ô6q¾UUq4 j"r u§*FFèÈ@i›ô2à4N§ö¤û‰L‡‰U‰ô´dbjâëRKÂ¥!-ðé¹ä>d+iIœZ-›k@±«˜¦µUY ãì÷+› ðñµP¸Mç…SÞÑø‚8ZX‹ñ^µ˜ DZ#æyÞß ‚¾•ÌŒï*€øzù^xU†ywކI¹YÂÄ‘5&Õ”JUµgæU * IV*ø6ýþϳÆzÅž¾’5ê…gަ lCA4`¯S —Š3¥ bÎ!¹¸ĉ E M(ج B<¸R¿ý7º#%@žM|øù<ë¡âF”A¬þv/ЦÚQÅ*=l M‚k Ÿ`ãë ¶h¥|'¡O™áÀ_¦tkŒ ØW*ŽMœ (æÀýœàý&N½h©9¯qZêj:_ûP5±vKÔØ¯¡)÷à Mº=…ªiöš’Ü\¾«æÅ6çõÝuEÐB!Ä A½ªJL¢×žb N ¯4µR“a®]J\Wר‰V=Bß Ðð»j§îV­¥eâð¦#èR’V é’6Næùµ¶•il+q¾SàÓÏ×=~ÁÒȘl%úÝp 4N‡¾3ÚÙW'„‰ó]jé˜â¾a¥tM$%†°Èg‰ûJì¤Äñ8¤ÌïVMLÂjIYŠ|áϯøDt¥¦Ë ª­Ç3Hżu‰‡hl\¦"¬E`bO§ þA)NU¾ejÙ8)Útà˜Ž1W;‹£Ana ý¥øÑxœbU"l"ð1UÅí VJÊaán€×ËÇ„#¤l¢KÓ+ˆ§“¬4òÒ‚Ž $m1²‚¦œuﳓ618›G—&Þ_XÚv% eiûÐt'⦠¼fþÅ€Öv´6X/°7D/ÄDÿ°¾@JYU¯T—/ ‹Aà ¯$ÆW’6  |üªhDúˆ ßUÇרN“œ‡¤É[žH%"¾¡S‹¬wÛ*bâ3Õb¸}Z hÛ½h™ªÓgMäY´8ȪD€—øy¥¥•T=/i%ÇYuS•GÃ'+@Ó$…ix ðbR1õBЪ–v½æÒ¡ ÖB™ Z ¤¹)#³t â¼®Ñ Lo¾)â«}žT è!ªJáRVš~DènU1©)AxÈ;Nì–º¨WYËÛ[#)›óJÌtí‡x1&‚ dÈ@¦:¸*¦ÿî«/ý<?ñ} œ¨CéeQÐ’š´€×å tÒŒéËÁ S¯¹ó­Á3HÜ’ü¬éR½‘ BŠqêÍ“²C²•§ÙMD+]Õ àwXñ0qJÅSxF!õÓW´í8ª˜|³ªò»:12NÊpHdjÀF ÌRÂÄo®’ŽP Äô ·‚¨=ódUÅp†Püóƒ-6]VZÚz-´™” rSém©@‰#áÛ&NúðV Èòu­T/Âpqí| o\½–êb ” ˆ õZ'—&•²ð r´R—@6°‰Öfð~€Uâµä[©§Ñ¥DŠ7ìWjÕr›˜ýN Ì€[ƒ ¼å{Fð&n -p〪L/$PÂ×(ÆéD#à´³@•2³%üîM Ê¤¶ĬQo]Òðd‘C¢_/üª~^ni£ÃaR¯7r]á‹¥UçC"Ì™´ƒ”2¤ð:rPÐÞŠµïŠÓB “ÄæùR ™…`f©á{‹\¬*&ïåìÝyâ hªâ3ñu~s“U¢ fJRâpŸ# >2Ò@)‚„ ̹(hÂét+Ç5zi—â#¹kp#¨m"Deüž»ACš…y½®m¹-æâD¢‰õZÃ,g ì'¨GÀgÉöpCºL½!tLìì oÊÖÀ,N-f7)^Š–,Ä-””´U¤ü€os"ªögÈI5Y°%u! Qî+ 9r+C¶¿¡n ß)DnŸt(7±YÔtáøøl r„Ò×àøÞ Ï¦즚© ¨b2LHU;ß,>ë®jììá˜,Üò@:v¢ ŒcÒJuYF4=5ˆ4œš*œ·yâ¥J¬Í= g44ƒc¶d‹Á¥|š‚½Ö«*ÐÛãëÒNÖP„6Šãˆ³&ŠáN$eh;œ!À &"íNL¯º#Hµt®b)2kAh¤ôº™N$mJ-‘½øU-â¤è#0¥­AMUŠ©„Üý!¬Mæ!dñݳY¬ªw"z3LFSUÐ%,Ö%h1çŠÀ&…VŒ©ÔÐ>‰/¶˜ÏµØ—ƒ‰©Å©ÂĬ®Mk”v.ƒÌ"hÔ«$¡TW†#»„®.™}»òS°[<#Ó©tEžZœÉJß}ð7hs[f‚íÌû¾ld‘ìÔ6«öɶ€e˜.jb-@²é^€¥\{ÿ,ñý¢j”¶*é¤{Z>j’4xð;’ýpU±%Ī|¯ŽŠ®öÞ<Ò Ö«…é­Q@ª…Ä,§@5ˆ¹È£M¤{©´µ[ÃJu©&².ÁÎÒu`6e%"ºœÎ&"Ƙ"È”tiiD%-h ¾}‚º Á!Ò’ÀªµtííÆ³hSXF£M’-~Ï"ÐŽÖ'Ø2|%5é ^Y;ÇÒ‘6NÚ¨BZ ¨«sµ5·ä§¸F–8¯*E³Ö¨® l i²kGƒ„ÔÒ!ö©JD€_‹Rsëú5b©jBA¤Ž¶«äMPuFA÷S—‰@o¦›àð-&°*rÌ<}L¸Toüzyk·R¸tœVêàúCé p)Ÿ¸^ ,¼ÍÚ’ª8Ž©—Á ìÍGî6 t —{È;‹ ]Žj†Ð\j§ÀÒTÁ4;¤*²@©.Õ|"Gúª%«B¤XÐJpR|xF®·˜¯·Gï\û2„´ ¶ÚÕ%ëÒ(» fa6Ù½Ml7¦TUÒ†)eÂ\#´ØÊhSÄJ¼gQW8ßw&eúM¤#nçMo.`/¹ö] R ×Ë+ily½Å<æÒZ À0KÚ¼¹|ƒ´ 8f &5Õ|)Sª…t¿|+¥†ï¿ÜÀÜ¥áH/÷81Óδ°¥bƒ q.÷üÉß}ö)˜Õ¸4·¡4©ŽS’2qL1ÏRà¬jB¾é­Q{HÞJ5â ¨½;§¯š¬®öi%šºB£Æ£Ýì8Ujñ“Ú¶Rq-†¯+ÈF4Λ¨ÊÄL Ú¡(H©éRê)t-aj]NOª]éé#gpZ³tŽ|-Öh–’çÛ%GÞÂK!zñ‰mB U; Üû db†Ü«‹¦7Þz¼®~¿Ç¯š¬–΋ÓUjâhürºiÊháX³Y›(À_#f¥£{ áÅñ¥¯l4^‰iùãëõ☀æ6|*;r7±@KÏNàø˜ð£~A˜¡ÞÖ6î&uu­ÔtüF«Š –ªJœ`ƒ¤xK*QCcUz‘Zí”Aï4ŶâYàÙ–z°''"‚GU¬“5urUéâ0½|à>EpíâRʲ|Íô¥8gØ÷#æOÏN$òé¹KòÍ*¾çÃÌYW©Ê; ÍîD@Áq(@Ð ¡g $”Âû¡Žá3‚‚ –5 SJ‡?ÓÕDÕhJ>ºí,*,Öñß°“eÚUóH:ʼn¨:ZçÕËT©EV LMÚ¬º”0SC0½^ž©"ïÝÀ”¶¡ªéZpR¾gU|`]@U»5eœ”«òI£Qƒ“•*M_¬XKÕÑ0_¾’FË#$^É–¬åýÅÉ« önðÈÿÇÇÝ,Ë–ËmT‚×Ä Œ¿WÇ hŸ!}™~Īso4T.æÌ\kï*è80Y?6\KæÊ3‘¶4²ï$°è=‘¢ï Óà•[u `mÚëñYêØ ²4€¤¬†ôÓ¥FR|l3¬ µÖ]\ÔÚl ¿ÇZ#†µ³íDul¤À@­²U˜_ Û †y»K^-1\‰U|Ç<ÿlË„¦‹½’S"kZ3ÈdzbLM §¬Ö–¬ÁRf…0«¢ÿAš\G|žem]¾U¸ ©F¢lkís'åivujÉZkª/%LÐ Ó >"`՗ƪKæ°FŽ P&X;<½XßUQž÷*à…€si”­•‰Ð®BGØ)‡ñc`¤*>q[bê‚E%VÓü°j›†€Ü6gnmÏï‘ý8—RÈÍÛØ0if¬Š@()Ò°º·æ´bR–r'HU¶¹Y  )»I$ÆJfB«HIÔEGb…ªÒd¢Ö¶£Í6™µh*Vmóo¶ÈV²iRÚþ`hô²š*LLÏ|[dƒ!;¯Õ‡E-¾Ë'.h„'õC–-Mz‚ü1ÆH9;+÷¼-s&9Ëâ»[bÁ9‡Ûí|{ˆ<14RçÌ7”祑± ÷Á+´6O˜mŸ U[…€-P»™¡ ”­Û¢¾øÿ3òÉ™ž&}LïºVn‹ßTãv3óœs`ëªV²¤ÜŒ-`‚RHO_®lÓô>°JdáT%@vc/lzO¤v4&&-à|l›_ rO!ÍÜꕞ­sÈ¿O®—Þ–8Ó •6NE-“#†]¸êGCïlnaCg•R¡¨0[zÙ­ôõuÈ™,¾Z@pPµBLÛñÄæjanpãc ‰i$µéÉÜEnɤÈð=õ}¶éKq0'A î³—2Æ*:Ž*-DÇÜü¸±›ß@JåP_LéÇ$´& vÚ|¯èæ Ö¯¦^¶e[ÛJSIƒyXãË š”v²F²?€qíH«ÃN ¶-F­QK©RÔ¨ò­€òwÝ$€àl%àüÿŠ:ÊVr›ŸS4’ w ß<=ÐÈü×B-½UÖEÉÚ`d™7€™ ÿ©4™'N‰×®SÌŠ²ZY‘%Sˆ@˜AŒÂÜNÙ÷á"•OcZõB:²Õ„l‘‚CS7C­[¥TÑä¥Ò4M 1¸a:£³à ¬¹õ#Ø’9ÿ`¤øÙº´%³­ÃÙj›Œgn¥šJ‰h  (`òiû’cèÉV2à úl’IµJ圦Ø´æbF*¬ª^%ÜÞy[âÈL¤(1¶Æ`SVnÛG^Š™ÜŸ<&¤mAÖ‘pÛ²0¾' ˆúâŽf¼x})ñXø¢öRõ{- Ï€ï÷:¸”*ú4™à‘Í ×C’ @7@d+~¶"SMð¼åp΀ÚÓæÛ4[çÏ|œ#Ö‹‚µõrÜ^gai WC/…{Ãb”ÔO “OO=+ Y@¤µ±d½Ä¶lóIlå–¡¬rJ+^ä™U¶ù¯‹1ä,ËVÔnåŽ@ÀǨÞ[µÉ€üZ 94­¨ï Ä4 lùD&³æ¼í€*ó gUV³ )Û•ÂÌe *%g$ÐJ©D`DÔª…5çÜleÀJ ,Å0,ðp§hNz¤µx1F ±aÔæ€äl­$²vÉðb}óomΗifŒY+gÛWIc;æ¸_1™.sC†)³}Ž$ˆ±î6ŽïýtäÙÖqXÕ×kF¿© ‹®‚aþî @ŠÜ¬dô^lßÝpʺÐK 2Yk§ ‰<`¥±í02&A[«˜û3@æ¬DMÓ¬žƒà92 2Ûñ’9A¤rXæáJÈlÓ§”R(êRÖ .ª,FŠÈ”Ý-Ci]Tb; Üx]£Ë9ËÚŠLÛÂbµï“ÅÛƒøªN+¶½ Rée¥˜ðGÚ”²+T"ðGfÛ7m¿ 43A³ÕÔÊ„2’'¬–¬àÖ¶îMB,ÛœÍ`Û$€¬”Ò_3@÷¬8àeâ×Ù&ÈŠóÖxVH²alã—ÊJ9™T“[T¨1á­‘V-ꤻÒBm‘3™Ï»ó6ÒméÙÂdø]ø×ãŒ[5"SÞvׂ.“ƒ,ŧBU¶â ú½Ý}§Po Û:¦¤)’åC€œ2ÀDH‰°µ±s°MIsµÿõ­#;«:bÎîKh0‘U|úüÇhÝ$1ݨ‹•¡ëâ&;P‚ìNÒߺ³ÌßoÒ¶.ß$‰mžúŒ{ÿƒœJÈlû 4O§°ª­¯5%æœ7YpNƒ4s¸_Þ¼c9gÞ0¯'1’Ì$j¥ÆF”7$¬}ÛÛù,µðV².®u<[ŒX¹B‚i& Î<‡ñ¶xÊrˆ±Dž~|G 8sÜ.p&¶§ò¦ñaó”B6Û&¬Ð:½<«Æ#¬Y•µ-ª…ñ³€­‘%1¡äÇ{K§©{>Hã¹)±µö5ëI¥'€Ï¿¥ÕÉÛÀB,׫L!|M³¨ÓñþºcÚ:ñaÊÄV4ÆÂÌ;€ª5ˆoósÑ0 `…S’!«B’…›9Æ 1j[_¸xnJ`ŒÆÖÙñ° fb] ijª¤ÓŸ h¤Ä-=ƒ±ÍddŒ•X*Ÿô˜ÞØã3!®…¦ ™PšAH•Å2[k½¶bMñ|(…,“²Ý³¬-ÞÖWŒáÖHÖJdYYþÀZÐO™? ½ #–ÍÜBÊÚ¾UYcJÕ.CúSùd­¸üßõô¾%Ó äÁ¶B2)µVlÅÓ[kY¸Õ´Þ1Ù>>ùÔt)U²4B¡+µ:lGÎ6·R)1Ý*€á™mÄL¬¹É¦OF 0 ,Ò¨ZXH5À&Ĉ+@/ }þSÿ Y©õE§äoŒ@)žéùc*ɤ$Î$ÙÌKmB¼¨cžé»(ëÆ Se%þÔßJd3D_íç% 'NfíKf?Ê×½Óɽ Ü´ëþgB“yÓÁ´Àx_Vá¦%cÕÀt©pÄpM€Àö}Ī|K 3LcUÛÔ*É–¬r[Qw0† ŽRUÙ †RSn<ÜOCœ? ž†m ‡†Á˜ÁíÕ=++Íé}ߺÍÓ̲ÿÿPU 2@è%~ýõWknR¯­1ÚºFåîÍHpz)ãaª²]`Δߎd¥vºËn’ô®‘Œ¿³kM` ¬®#Ü–ØEÙ6Oë:òYk©²Vµw÷ÇôF>¥6í«¯c2¥“ÉêÛKèö”Y| þãm¥TÑUç€0 àD²d]E…Çåpƒ[™`ÜXÇÇÓׄùˆÚUãapåf8mnÀaâÊÛ79à™Ö‘8}@GUô”€•Cóxúõ5¶”¢'Æ­“ÿjËÚÖ‹²kÁ§ $¨)Ùt4«¬C fot Œ­ Ž1­­5‡«KÙ”dåk—§ÂR²ÉS¡ããKÙâ™;HïÞ¶ÖE9>ÛJl¼u©Ö´ehž=… 5ªVk°ÂUUBLˆRa©¶Ö0¾«ÓËIO­}ã²à.Ñ¿‡í‡‡¬ØóËH™˜5 5™QYž¢?Lªl+‡z)dWŒÜ‘àk÷2R9Ocz†²ÁÍVxû›¤™¥r¦¤i$ÃÈÆ×n3+gÒÖ*zcˆk¨Vd¯]æ[e×Î fæ+d’²C1?=nk2€™³¾ÄnÆ6}V°9»H¬ ³B M½Øb2ç)« “-U)“Ù6U>q)«²RJLB™ØŠ—8 M+ÌÜÊÁº¨»Â—‰Œ¹®'›FªÐ(k’•xY©”§nëÝ8óÝòlÓc܉5O—í¤}mH–•,1Œ¡¶ †Jòyo@¡ô €!ã\4ÉwwžQΉÇªdÜjKfµ5›õõÄt¨•ë·V•ɘÊm×~K #Øêømµ hÎ^íŸ ¦„­â'Ұ͇¡HŸLjz©JêB&"ñ§ò{óíòg.Å*Ád93É–€^ÖÚk€—ÍÍkÆUn¶™ÓWBÜA”ô÷|{EñùpØ7<¬°F¬¼HâI6C—†lH$¦ÏA–F;Û|`Î5Mc« _г­• Ùl•³ÊÙIѨ€bÁDm½Èdµ8êïÒ°µ¥WؽH)@0±B¸lëíRôÕ7IÔ…iܹçÕqîøç/¡ü”ÜÀÄÆðÔˆaÊœgiUÞÀœ…m¶RÍYI>ÄUÀ©“eÒ´”4³²=¾÷>³ªÜC¡×¢Z“ÃMòŽ“s><¦9­EIÖ–²!9À˜µÐ×–lÃKy*”ªd½—,+`á/4ûo!ˆ™`¬«"«µ£uÿkù¶ UEÃôŽFjBe}=ÙÜ6 å ÈjKϹ*d& ‘m7¡íø=,k ·ÚÖך²e6s‚4­‘Ô‹áÞ66¦´€UÕ¦‡ó™Ì–ƒÕ<x3lq¼-`}=u‰ŸC[&;£ñ6aµVA¹*wEã°:*L`mJ¼îV¤*A¦Da>(i` Ü“dVxQ_ŒÖ¶ aA`ŒÕâ1øœ“a6^welU݆F†‰¨Ü*ð9ä–R!·H‘s°r°µÖ¸c~æ±Í IP¶kÄÛÆTò6‚‘š&;Ã}?ùø<1ÀÍ€ÇÇhšy[Xdzl½6åëHÍ“OSa¼EëiÛ)téçAm¥„Kã̳F‘Wr–®”•OhOŠ@ M¥¬°¬dÕF‘¸îÖz¥TðáLVÖŠe4²Ü©²iè›$O$½ÿ’áǼ6g¡¯u²­R æ€4Bªª¬"7v)+Yä:øUå³F|f;BVó±­ûJ&èªMبdaJ—Àj%@3X_¾§ `¢¼Â¬à^_¡ùè˧Z Ãwâ>¡€O…VUïo*e›n¼¬ê‚aÛíah`Î4°”:¯­O„Ÿ,z5 L °µ¶„oc¸ñ¤lûé…ÑרªD½èsV"Ö”R­”µØ$  \a}ù³êøµ¾~Ÿ÷*,õ&uA¶ÌõÒ¨1€ôO8¯Ù<°ßMáZde4Æî1Ùª­Ò¶Ö}1²"n²°¬èPM¸KÃ7F bk7C_÷MÅ Y-,¤’µm­;|ÛÿxJ³!­ÄêÔýð…¥Ü›¬³À|²ÒQö£Ô˜dµS®^HU˜˜ÀÖ/-Ȉu4Cbsƒß” .yâ.m÷а®4µrLç5Ïl¥„ªl–ê,R™4’.¢”•›ÂôV·¬¬&qFá-"cËOY-д¶²d Ïè÷‚ [ÙJêžU¶4™äÌSIþ²ù¬À!ÌS-L3$ÈöLóý9‚o+æƒÙ=e—, XU@ÝÓ ©²H‘t¥V[Jµ¶Él‘ºD¶…EåÖÀ«dÛØHY+F‰õRÖRdEòžW𦂙ð'È0âÌô “OU]FHÙö]À^ß|0 ùc¼~ýÁ;ŒÇ'KS-C˜8²WÙVJ!¬×¢#4CJŒ  Ç4o+à·©ÁئÁFZ9=#»ÔÆÖNʉd×%}%[båw¨ó&åxg§¿ÚóO¼ h¤—aeÔ“eb; ÞUðÉŠ&Çy£GþzL·×S࣪Fp‚@O¼T>n>1°% §·Ö¹§ «Õǫ̀/ Å~åÍgãÑ%Ó‡{ñÈd¥„DÛZ#HO?Òx{oÅY(ëËf+*©»LŸŽ4‹[þ²[ &-CaÛäRa8ûýÀèU;[2U:F^cŸ•µHc-KÌ6SàÆ–²Õ+¥•ðlÿÆãk|þƒì² )Uµâ†›†ïC—>Y³Áç¾ÿM€‰ßÂ4¹#˜œK ÙlmeoÅçÎm)….xÊÊ7¹-²,nR¶¯0}d«"˜>¥5p |ºÿfÀØfË*ÒÍ÷Ä3©‹µ-“½À—‚ñ²m·Ijl™ŸšûG—¬ÊéðBùðÉZ™$hš¡Zµpg´M`í1å\I§Æ&áéí’ê>ÕúÑÓåÇ}3(ÑÝÖʰ*× S–¶¾s&k8 ÀgeÕ=sšøYÉblU1·5’ m3¬Vù “ù…0çFʇ¬- òTˆÌi‹ÏÍŠz-ds“­»T¤r ^Àd1&“š?&¥`zÁ[AÓã­áÄ.$Ûµ ©K<ì°¨©‡îeøü¦‹’æâÖ(¨ëî{¡²õÖ~XmSb sØ(µ¤¹§8ÇÚ‰¹*ŒU–U$L?Ò0J´ Œ‡i„d…Z<†Þ«Ü{¯P•ÍV…õâFï^l ²mTÛÞ'€¾Ú®…3&^ac¨Å¨i©BJl’ºÓÈÂf°0á`f¼l“Ì ((×…’¬.ž ;Ñ‹†!&ClE ]ü—©Î"kÅð!¦*é;8¼i‰ß¦ ƒé)Gj¡jSÑÀRª,0RfkÈZ§¬*ÍÌ1‰[ÙVÕ‘ ƒÌp9]ÂÜXå&+X•Šô>0QUÊ §Ñ¥¿ð¹ziZ/Yìzÿ×'ÙºŒ°•M`U«]w{éÏ¥!mé›P£Jæ`†j1¥”Te˰vBÐm¬Ë›T•X¡ ¯ª•ûp¥©]Vó‰´.6[ó«ôã×kÝÕÖ=“s˜HU†±3F `MmñMÕ¤ôÅgÎär~-[Õ@2뜹yîãÓw+†²¬'eÛ YiêÓQàA§„‰™äCƒŒ70 –½›§d¨‘€4j;l&•KÙ–í©5@ÓÀëhªª’Óæd¬lKa`dšÈŽ ãe‹&¶ P:µÕVm§È¤Éa&V¿dÒS"ĶٸÈÎûŽª°^•µ-¤0‘Üœ4Ì¿'¥Ä'ºçË|sµn z…Äcå®jL}‘ôV¡VÖV‚¦Á´“Õ¨³›0¤¦Tn6…J€ô×㪥dLÒTe%  C‚ ‘° «Ñ¶R4<î|…õ•„i†RJÙÒXïtçãC†iÛ…ç¯PBSykµ°s)”˜P2©{CZeéûÆ60LlÌ­|š§BJUÓ &¥uÃ+$Ÿ¦ƒ Ê)…”!›‡G“Å[Û€U(™IØÊ¡w^k[by:3@IDAT@I‚[÷ùa—©2gE³¨/=™”m† î•ÀÄ)‰#µæïÌÇ¡òIŒ”u^ž»œ 1@þ?RÕ"ãÓ'îA‡™ÛZª ÓÖªV‹ZK™ S¡µ!11†˜ÌüJzUlE3¿üéOªÞíTÖ5)ÈÙUõ&¬:Ñè!ä1‚¸ ¤ÂVg+ž ¨D6¦*kz+Y]hàNùòâUf¿à¦ÏGª8SÞ¼¬Ò¶÷¾î˜z®Qæô÷¸ŸÏRí&2^ à`x¼UÔNë^5[†^8JY«&\ù<#­Â$E†FUHɶsÉ"­HÄ«e[‹fëõ¥´¥‘‚·¦‰IO“ñ· š•ËÂô½Ê@'š¨ÐjZbåpÉ”¬ ¬z:°1±”°e¢¯U¥3vQ°'n{K? ™‰÷`â‹ÉzÚ߃Ô“gB¡û´ )b…‰aeÛn$1ž ^R4¦’Ò¢mnuA6R†ÕÒ°RÕð œ9†>±UØ"eûRxý›¹÷§o@þ”V}ñÕ0ní2 3u·60=2ýÂÌ…Ö_xþI©PPZµÖ"V•“å_ª,,h¬•§·5-2åGô}½‡¥D[µ™†A²axâR²â¸\e •’aú4L:ÒH·ôóªÔÚ# ð¯š!Ò:Û˜ 9à»@IÇø¯$™-r79O 7·ä®*Q.k+¤0•ã)E+ ’3åšÔ¨ÂSÙú«ßßýîw~`!¥nÝ9K¡/Àc¬˜FjN-ðð‚ØëÚd+¤ÁÐ(Ÿ^ à ƒ/¥ÉÙð¶ kMiÛ=Ћe†dÙ¾æRüÓ¨ítn`ÎÿùÏ|ÍþòÇ?þ1ß&†,”©/FTÜÃk›Òú#ÔLl»Í01OY—…OÖKƒÇ47žÞù‘ùÛŠ3Ù½J‚x[ µlm‘‰1<=Û²mÃÎEwج8Te†˜²ÖÌ•À{äÊ7ÞF™kšì¦”Ü`Ãð¬rÙ|Î|?¢Á%(r.¥¤- kf’¬”µ£LIÐ+h$·±óâŦïh€k‘âÆÇ sÀݘÖ¢Ži¬Jß\Ö¶MÛm4Y dmõ¢éã ã5N§ï70@#.w°y(Û~CV[2Có*ÍÀ¤¾ñªl= «³;‚ªZH È00Îý9|O•)]ºÆPŽ!#€E_¶uçI_Sʪ¤0Ræ,¬²ñÐV62ÆVP JØJÀ\ À€ƒÓÓ[\ùÑ´„r²)Û&K@ÌY¹¯Y«ÃÊ 8±•cEZÙ=À&)%»¦H©cqKZ1f€e­9«Ugk Œ(k’ÆÆU+J\Y‘ÿÜòI‰øó!Ë„ƒèF’шHª%VÁ0ÐZ£x˜&Özd%)K‘ÙŠÄ»í¤s@ɪk÷‡À;àYðV3w¶¶Ü[[ÑÏs§++…ì~Î÷›FÞ0°{ÖWyg‘J–mbZë‚7±*×+U¶-ÛšN#‹é8ª´Ã4[G«]cd’¾Z52ª±ë„›-²ƒÐd¨œ[…³ÕQ¶Öô@£2á Düò÷¿ÿ=_9¡¸¾?tŒDYÛfz•™X¥4¶–i­p„“™O6fæRFJ/¥»(Sõ’¢ßN)ë´0«ª`žŽ#¥ÊK ¸ÊåFc$&½.Y—%¢ššÚXEŒÖÝÃÌ‘bsJ!µë*ˆ‹¬¬¢1Ø£ùo“Ï÷HX@̦´:#ÿ&¬ ŽVg7Iž¶Êg¥ÇÓdÄÐkÔÌ ¤Dc`œ¨ï‚ÛHþǦdÕl¶»ž‘™÷€ŠÓà¶P`Ø{Ð+lrdŸ&æ©JIÀOPÃ4*>0[Y‘§ÂNd­E+=@¬DJÄ”µÍ¤l)¥ôaJ@£f0€Ì$±DڹѫÕËÙ;>FÊê,ZDæcK)¼“ð!F&VŽÙJ©ÂpͤœZ|g•Ëö˜À–Õµ¤ ˜¼û~duïJKó×±FÖnF%žÀl5µŠ ÍáÓ5¼T@kŸG`›¸ûçÜTø.¡ãäCÉCƒ8T˪"èb ²ÂWRyã¥o«(«i¸­u­{ë<”^”ZX¥ðŽŒaE#:¦?3À¤DìŒôÚµ‚X÷Ä×éó]AãMVž9ACj„±U l›†€§QñÝU3 "…”J€|ðé9ïbÞ„)“)𦂺+ŸH5! Wá“Òlâ vœ:…^Õ2=æ8Þ If¿óhG‹!ýùVXJÆÀÅ•|>kirÎS–L ! pØÝò'&K# c [%ÄžÆ%Àò·'ª„”a€/Ã*Ù¬€ g"NËûÿo@¹×Ý—^/åV%Çúâ|Ìc†YÙæIƒ”j`Xyã%†idmYeGâ{ø Œ]Y|x†+Á¤_ßù+'c8'hkíòëWÒJ)ø[+lk’]%R—ñ « ;ãÞ@V¹”{ +ÇðWÔ"²Âf³"Y…Z#mpÏ"†²ž¬mÎÞicsØYröé%ʉ­†”°µYëUSÛ†±Ò×T9ÒðÃS_ŒH‰ä,+%"YnùÇ#é‘ï¤ð†OoU^Uk<}Ý­˜à#꬜LVk)kGÔÝéø`jáK?1Aþþœ#ëZœ"³a)ú> º$µ5Œ”r†ÚEfŽ7L#Ta„*Ø ÄÖ²Ö «­)'M¸o[J#ƒ)·=¯¹vÙ”4ª€õ²U%¤D¸­”*n #Ûýk„WkÍ<…½mÊ6j>V!›ƒg¡ož”‘µ³’e^•YÀRe¿ÜyO„íËW•^#‚&4•?lÄ;ˆ*ÌV2[Y3 gK {a>ÔEåbUN¤¬ž3æICÐ+§dÇ—­c·*%"ñH…&ï_g{Ÿeïœw¯sÙR ­ÙZ•ÈŠH ϾÚs䔹Ùâ)mɬ0î€Ù:@#eÙ5u-‘j¥¬Ào*7cë·áLd}M “'I,ÂR”n8ewàÍ `–„Z% EÙëwn '˜ÎMdž·¶ û±Í<2Ïn¯iaóôµƒñsß‹ÇY•Ix™Wb dÁV-Ü…sÕݑÝ9¦ ¡iò¤±U…¯]2¶Æ°ˆ²dÄd)aOSêʺØ8 Ðüé­<#ˆƒ¨ª¨&ª¦¡ßVŠ }3WåNï–žZ‘LІU÷ƪQ1A9Ry¤UtuÖ¦¢\•ê…‰œMòÞ ÎX÷¶EÂ@A&àð²7s̯y&è*çÐkC–³­yÜ@)Û²ÈJRæ¯Q“Ó“U€«µÆ3;)“œ»œ4sfØæÃd±I0Ü|Å 7˜òü2¯.ˆäl’¶RVmQe5ÞçOÉê}JS ÅÍ gQ` l޼jЈ|h”Óצ‹ ÑHJ‰#eË_kXW…¬–¡h«° J¸-Aµ§û&§¤±m¤ôdJÌà›"Á1º!Å ¹ï‚9$nT2ÁSón %~V02Ô¶¾åñJRj$“y:HÐ*5b;f ¬‚€AXIï\Çw¢J%M«iÛÆÈ £Ñ‚F´(aÊKŸrMWŽôûO5"KlŒ ‰šÖ¶ÎªÖ¶Z n&×B +†yµHY¼P¹¾¶=Í^[ó¤dž¸ÉùWài<>7©A“d+›À*%´Ú#ÀOHõ%«ÊH°-Õ p¼Z8ñ2·­Eoi3KåiìúZ#­J¬opÞH mõ­{M],F ÿ^&õ²uj²·Q#ÕÈZ(ÿÂÏ×KÛfÓNÔHl »Jg銶º Ó–Ú¥¬Ä‘Y/kØ*2Œd8T©Hø^«að§ ðNJ¹&yÏHi†rkÍ„^UCd•çÐ'4fµËò\LêÚZjX*ŒÜÕ²”oëbów?lï­þÀаUH_ Æ[°F0àñ™LVJU7fÕEH5$qYk%V2‚®«v5ªJ €€­axÒûöÃh ×Ÿèæ‰µ°ÕQ öʘÈùkAiUE,Ûl1W~þr‡FpPôÕdÀÔ­”J¼?z¥$<ñªu[€™&lÛÍgØTÕT›6²{X #j¤œÆu¹] FŒLl]¤ç¬i{m>xâr  Â]TÙÚÅdEÓ¶ï1X##5Î4.ÐJcÔ²ô®ªè«¢üõ×_ûbÁSJ!­M¾ÚR” ,Ò(©¿Ž¹aÒ¼+’UkG~ܼͥû¯¯#×±.ô•ØÈÚX G÷Rå†Ñ‚Ì6}¸¾ÖsÐZ_…pJbÛ4ÙZ=^PÞm$e¤Ùnþ£ñ©j­Jwu˜ZÁ½®îâë(›¦Q³Ò«÷-¦ª01%R°êìHY<€`«i“Db< ­gBæyY{ÈÚVN¯²ñò—ŠäŒ§÷5åŒ~O³æ¬E­pn°B[…"€d«j%4_S˜ØØ•üò·¿ý-Ši@¨÷̲³b’)#ËŽãÕ~–«¢DÙ2)ÀH9¡|ÜO@dá4Ê靨U^І'1¸ug)+erz+[ å™ã” +/ ÙÄ meçV;¤T‡‚‘l[Ï÷_aMó¤ñÉäæz¹"ÀªyæþúhÊ¡¶2É\ö‡²-¾³é›8g)Û¦5YZ×}YnE2Û”j,rޱVâe0g§V®¯aˆšî!ÜHÈFå–§•cµf€;‚B‚ʬ›Ñ.M'Úª¼{VÒ>+ådVA†/6­ª9“ÁmáÄ&Cv-€ læ¶­ª6Û¾M’1 ”¹Éøšz‘üuZXŠ3¥±…mWÚûl+eX Ðj;†s<‡€ª®®M…„‘L”WhAv!µ üÓç& ·2\9PÈ2'p.ñ41NçÕø€X`ˆg&Öî*&L¬c%€|h84 ²­”*ïAÃHÊ4dñ¶E&x ï«ß*‹"e++>eߎmµkª²¦é­ñ+ŠxkþUY_&g‚îªgšÒÅúøtáJ­h*k>½Õq"] ,ët=G[ÇÔÚ¨ø”šÚ!ëb›ÀP¿mO!™ÏYÃ(7¿.4ýòG‰´™ŒÙôUn[Š'1#};£r©{ŸkYS™ ðýýï/¥ªŽJ4R"+ê•§mÙ¶:r':Ï{ÂÐxl«_,²êíÂXù¹©J­¯,Œ«¦dV¸=£|Ÿø¹šû½‡§„óqç}ýV~L¯@aŸYÈÓ0€Uí®”Xê *¡éz»ùƨï‹1;¸m ÊÒÖ¢ËI`5^_€,e[LÎg¬ûnËvj BµLž²“fîJC &pQÊZdkøæg‹‘²6vCÊê¹¾ Ëx¡nK\•m%U½%†© Í›Å+± É¤ÑÈ6Fùà;È&Á“Ô´²­ªT<1îà0±à°ˆ|õëkl#Y‘Üò±­|Œr>Þ4ßÕô_M‘i”÷ºÆX D> ½öÌÉêo›†CPèâ¼0²a¼Þ0=åªn‡s?F¢/KðÛ¨^ å绨“zÅBKçѲ±` ’ÌÀ+É\ Þ·Œµ$“Ê­½èJAã¯@jšÓ5Újûä4’Úxß§R9¨¬Â5UR­-¥,±ç!•2ÆÖT01lå¯Qζ¥b Ÿ•C`[ ™¾”"z¸Ic¤00½ËY- {gÿüy¦¡ŒdhžÓæÇV¨µÆôŸá*Ô¨'¨Åtuõ²¶Õ_¿s–.ܶ¾VåÃ=†€³p±VVHÎn¦Wi ‡EvÚÚë‘’Œg§°6Œ7©<9¨J¹y*‘JÖ„œ•ôz¤Ç”jUeþ•w«À«í ²Ê@ŒT®™-P¹C¦ i­˜ F#•ÒêHàƒC`Î&Ñš™F¢{#¦$È-olo }âæéžéɤà‚ma+Û´™ã³E*áI3± ç0½,q§&P…1‚Z¼UÄÙÆ‡‘JªJ0Ì“!R­½-e›0ŒìsíÆèß›°¯©"«mcÀ ïãsPh%Ð= n ¨êÆhVÑÀ&²¾<ë¨ÊCofÿ~Ü®ÇYV äкm  «2’yVHÏ<™õô ƒTb›2«“€•™e•È )aÛ]½þx¤hžþò[ížÜk_;æ {U)Wˆe €4€eˆg²Õ›t±²o4vŽ×ÅKÕÑlesžUÇÑ VtšJdaY«èƒé=ÄÓãÓûí¿áuðzQaÎûÌv4d§ ¦T%–ªÜj’H -OÛþ7ÙÕNš3ë( äÖ<4:j-ðÆZémOýuÀˆ+9$¬»*'õ’c´àT•U}ñÿüç?a+¯µ¦°ïF8}oK%­Ì¾3µ°%úæi%PÞäM‚ü= ŸqúFÚTç 7bÂ|”+ÌЪÐ*K&’Y‘d}¤-LS-` ‹<;Æq<ú µèL˜¦gá¤m×B!† #DµLš‡æÅu'SÆ£‡ùÐLд[‚M¢ÐäÙH¶< f«ÐV8iM­‘4‘ÒÌA¡m²ªælH€¬± ½3‘‰µ;ÁdE,Ò°Ú+A`«‘B2Ÿ¶¾ýl‘Yˆe‰¥àädÜ„Fõª5&1òíØÏ…Þ-ÈøLŒiκ_ËSΓŒ¡¾HzLízC¤>/Š“ø¼ùTCª¥²*#­ó‚5³zZyÁ"ª®@ʧ«“Èêm ½ø‹²Þ§ReᲑümi8äÏAVpCtr†6€¬¾p†°¬ÚJ²JpÍÎÒ­µ}Ë• » kÞ OßïVþ¶‚XÓÆ q 3Ì­ÂR€òZ[m+o­W%˜Nd­¼Ùh¤0ë˜[ãI•õÿ·í>œLlNLúÌm&q¥”dÏ-,k;^•Kh¶Ö]kÊÌ­p3m«=†@)²ÆËP¡­’N-›_J6Œwÿ.’¡à8C²ºàSb8ƒ¸‡R— ¯Çù ÒÔ‘¦©láZ¶í¤ðÑ«×Æœ½í&iHUÍC_Ç ñ" q‡Å°‚ñºX¹!MˆTžI§ÃHaV¡ÄJO X×Ú¶'hÚÜ(ë˜X¹­UÖÚ¨R¢F/€Ö(ž&ÙÆh[@Êä½Zžˆp]xÇ·öˆû}”§9­x¡ð Ú|¿¾ÄXMÂÙ)z aLn=;%„¤ áÆ¶váó¬6Yd8=7‚Ž£ïÒJ /PÕë³,’‰à™2Yÿ(!›¶µ«¬-Yy+ ¾Óû°-æYmbdŒÇt·°§é¤ب=DÌÎ`Ò#°eKÐ[§¨>ó;ÂçïST)Á 4L… h8ŒÆ-¸ì{êဵ©¸ÛÖmÔȺ÷ˆkDóÄÕij%ÖQ¡€Ç(´å`‹¬ßѪ²î‹b…äF¹v EÛ<Ûbzj›Sm) ’¾°EÂVSa¬‘îÁ{f»¯½ðŠÒ/ýxÏ·¬•_ÇÈu¤œNôbd‹¯KóÐ(¤±Ž£—Fn£g‘?¬<‡5XåÐZS2@¶^4œ áRi†mvfÞÁ0ñàšŽc«QæÃ²H2·„äàö´`{Ü¿Ÿ¸ 7ŒÁŠÀŠ9ã‘æÉ ¯öÊŸ ;žs,.ÀËÂÆ¶V ÄÌå7FØÒ_뀵ydµhÔZÛ:l3g§IÆ™RyÃè"ëq×NÖx¡K#kåƒGzÅÚùrÀ÷Y@bD¯PM‘@7 £,¬ Ò¦e"êk-d‘Ö·Z…™!úÄRùÈ $\ßyr#›ÿ/þóŸí…ó4kÛÜéÎá.oE¶”5èœ ”Ú nxA@ø 0œrnBJ‰õÁ ë?¦÷óЦWE#«¤#`l­ÈΘ †ø4¾­‘Eæ‘[õ’5-ȳã`Xõ˜ ´ðœ˜À VåİÈ@-R¹ªFº#†O#ÛM"EÓJ1a¨#&n o«ÏW’¯¤Ë$è· …]õ&ï8œñ¥à:6p#YGêEcB€†³«¨ÊZ•U¶S(|Oa‹Ç4¤­¾M +´­E¤Ög²«Á4y6•¦i²}k‰¥øÐLæNm›ó¸_[µ‚¹HC†¿mn ¤ZmSŽ!¶E˜ƒÐ¢­°íõ÷ýh¤ é‹þf>¯†Új€¦lUµõ”k÷âþC–RÐ ºdó3”ª ¼CèhåO ÀÀRnL¤¬Àë…Ù×Jebn·ô˜;ÒA¬:š­©”xå4¦!S[;Œ¬-P­r`ÑHî¼Õ6C³%çÌ6R;Y/kÙ¶RÜ40©‚1ø®¼¦áÖµžá«Öl¶Êi¬gÅ[Y˜`&ÀëLÓ֛䇉ßdd÷lÛKÈ­¯ )§¾Ÿg¯Å޼dO9¦. mû¦Í£J_M­.9¦^«’¥—¢É.k à XQZaO¹÷0±T2˜@d‹‡­ älÛ[a›C8§KÕ¢*˜szŒ±¥pçpG00L&êBÐÖzÆý~iב£Ä–Òxâ˜Þ*ëLbÈøT+%`%‘|zFÉ”4³=S²ª”ÐTÞ%ÛÒ d£bÌÆ¡ïðºXPÊÖˆiíø~“óÛ¿¦ùSâç<ó†iÂ|0d €p$@–Uóc^ÐX¥0Íãûœiër<Üd”D9œ *ï5€UYUÝV1=SŠ9FmækìŠêB`Îôx‘çj¹‰RÄëNx"¬¬HU-h`)AVIÛÞ12¼ KµÆHÙJq°v(¸î+!“JVJy'Ò/hVšd+´ÕHdnÛ¨>G˜½l “mÛæì¹à»ŠÍ@ÐÙa ääÓ¨ùÃÜÈÎÄ÷K5Ø`RÚ¶ÒÃÆ¶jje+E|þ_€jö¾v›€´ˆ 7ÐK‰d%z„€¬×T•@iíîLCfëÓˆ7¥-ÐÁ`­m@ TGªvb qàk¿ª>odâõ$³}ï.dÂÅzÕb>d‚?††Ø‰0ÛHUH)šÚ!ý Ô}V4¡„{]º[……Ù )…î7£„Fª@–µÅ·ÍM‰FH%ç÷ö¬¶dîªîVQ6=CLnÕ«©O)-[²Úq¨Ü ‹ôV‚#îË6X]¬Eæü™à:}ž; Ò3oTäÀH@l<¸bóØbíôJ€á&ÈVr¼¾?Ú|GWbµuFkâÌué_ÊwoÊmaMZ‘ª©KØTL0V ±5€¬ˆá€±‹U«,ë5“2L$¤ZÙù¿Ud¦'&¶|RZámh€Êoò, ›Ó“ÀüM˘ÿéôýˆIõ\­öPXålå@Ã9Y˜f‡ÊßVlžN'…¬pcÄðôíDonZ…må0±ÂTþC°íWûù‚Hµ:2L8«žfr^ %ˆ¬l/‰¹Â³”eto.sí6ë%`"àÍ´¥Q%úB #Ê–,@V ÓW½Žp¶4ÊûµÏwš¬`«—¬r§‡‰u€ÀsPÒØÉJ5X&ø@%¶"Y+‚l¥úÚ×i{†øÞ Œá¬ÚòA €ÌAd·=._)øjÏ¥™4‰©ÂGi˪*ø]«Ö|Z•P Û®åjÿë%÷,4j<ç¥ï?ï!îç”r<†Æ³õ ÏjÛï„pUMkõX‰â©¥ˆá&”Lå­óŸ<4AW¹¬m¶kµ‘β©jAÀ™¾Žm o˜Ll iUHP6ºäf$  ch~²„4¤Ÿ’,“ü©µì»RÚr HÆ·íñU®õùb©j ãYfM¹9Ë<É”ØÀ}Ç&Ffbeh+JYá“”­5[_MÃ`t±Úæ ë©ÖüU±­ÄŠ´ÍP– ™I“HÕê.eÛ<ºt'­ÈøÊ›ÜÍôæ×¢Á8Ô:Ûúf›'ŸLüÁ• òx†dî\•–ª¶î•·vùçç ‘be0]R+aš,È02w%F©%̤_'«dy÷’¹Õš†-OŒ­*-0oy4Òa&¶†©2æ±ò”í^l}ìeY‰ôGðïùHQŠ«:KǤDòô°Bnø”©øl»œ&—bÕ¨Xa¶@Y¶nöFd)0x¶ 0Y…¶°•2±U-sØR*¡é½1!,•›¬ &[ÙJ¬LlcèmS2´íð?qƒ‰­‚ýüaUx‚3âw<ÃÀøË}>ó¶ÄBUV«Jf•ú?CЏîoG<Æéhøëþ‡?ü!Ÿ²Ã¶jEGv9o÷²*d®%­Â®31Æ*‹×ÝÞ$H…0ž¦³+$ ÃÏJÊè5² Œrb—[2…¶ô9[g|βÿC×,K–I^ð´†f<:K6óI¦—&{&ÂåááÒ9™÷VÑÐYáÕŠR¶5WÒ›æçî¦%J¢l¶Çîþ## |)²V> •#­±Âïî8Û:š¨°£Áª:mU˜ú&PÅ*f|)++µÎØêæ…9UÕW ‘ƒUj&€¸—q^ïua[HÝês^Ø`Ú)Ñ®B-zÇë~"ø[E>KmË–›!MË„²1(»ä:Âݼ,¼*Ù&©QµV©”p|Ý­Rw¨3•l®6¥©„~~zõÑRØ*7m¶æ‡)‘†DÚ"=æx«ñjdKÜË:¦ß>µ{gf^•râ4›Hܨ¶ƒ#éu9§ºk‹$È'=ù›¡ƒXÉ c¤²JF&&²³šž¾Ÿk&ÏA÷Ì«Š´L¢D PR/ÎNÚ?ô++JUõc+š9`U¤Âr‰…m‡Ó'ní3%Û‰Œä,ç“v»õq¨‘ÕxÖNÁG4êisßO…†i†­RÍÈÄ ÀßÙ•ƒ¸a<&J¬•Ô¥•ž¸HWM°¦’Ù6Æ”™ä`~¼èÐZø¹i˜£o6â5B¢ €Æ;žƒÀ³Í„¬Ê{'øŸ Á4Øn2M)ˆ²º»O¶˜™÷쌬I€uaEÖ#•,«·FÈ*4¢‡G®*¯öóîe#U_¤Â”jE¶Va;«Ê­=S)V £5½³s˰­òŽÝ÷Ó§V qVý5Ì-YcdžCY¸+²Õ¥‘Èèá@ŸþêÐT†ôdk%ãO‡=_gæÿûß|Ø[IUZ…ÊfÊ®ú˜xç]»¤&xmd¶üFò„;˜-ì (K‰4D “Ü0cU•æ´ü> ŽR€ógŽÚº53Ÿ[¸Ÿ†laãyN+W"NãõD&€4VµPÎsÒäO߈éçM²Æà¬œF£VV¢ªp“´ªâéDü]¦*ÎH‘C³ÅK©ÊÊ +ÔVnE§/«i àt›3±FªÄü ÓññQ­V<ÒÚQÚÖtU°³ðä_;Un©UBŠRÈZŒ·MÙ<­e­² †‰Ï$^ “h—'sJ§Så¤H¡ Ρ1Ôfk~Œ(©;æçG&¬¶ydan½ §ìÿ3¬ª^Íc Ö¢^”M˜ÉØ<4Re¥ ¤iš¼¯z>xÙÊõ¶=AYX¼#Ñë¨ è W…$ñLl•câ‘Gq5øMŽéàsóŸÇQk3#Õ6dÝ=ÓÞa…Hb¦¢·-:E½¬Úo$duœCÝîì†Ƕ•%«—BÛ0±UÐ01¤rJ[«Âü ¤(ÛÊVuŠ¿ÌæÙºc*Å;¦Zn¢^¼’¤r[!Û$áR‘õ…· p&“MìøÕVG>Úµ®ÐÖ¨¶M’La/IäÚÍP•M¼-OÐk,‹ô•bžnÛj<¤Héw/ûƒ§éN²JÃJ$&€½ZVJ+F*A¤Z@H  ³õ7ž²Ésh€Sù<Ün²1 jA‰9Ôîœwòöÿ @ ŠRßvJÛj—"–íöÂ4<ÍÓH¶Ý<\dnõ©èëYXù[÷™²u™ü9÷5ÈæÄÛf‹–²e•’'ËVÕÛW¶! ¼4V2¤ZÁG¬dÛ1ud« ®J–’'¦€cÞ©à‚^Pæ¯;àÅîŒ{9›ª,Cµ[±­#°Èh®ñçM#³¾×Ø0¾’wYU%0P£·|7 WºShM$Æ“‰u—‹¥ºU…Af0[À*š³10ÌHc{t_¾;”—R+«‘¾C P»Sÿí©ÊÑd=¦fÀ3OßS`’‰á€éFEʤÂáUâõ*«¶-YA Xµ@š™Ûâ›À8™BΘ4Vaë«ØÑÎÿ heZ Å ÂVºÆ¨KÁRpÛLlSk£ŸN÷*­Å„¸ÚÖ5]_†ù`h”, É‘ªÈ¬bcÀ²¿”‡d»W¡™1Lè«’ÕQjñ0!%èadg#“4Cí²-e•Õ¢gÐTÊ)Y©2à«O ° ¹ÕÎÚ¾>¤šÊúž‘¦©x¦ÙH ÷Ën>NoÕEÇ0ñ9BJ¹À¨-L+ö“ž€ØH²UÑÃ~ÖZ…ÉUIi$0ºMy*”më‡Y§ ã#2è^ =Fk˜@”m‘âO¦p6`þî?<[µ4Í kÛÁe3¯Dkš­˜2qWGÖÌVŒÖ¢ÖÊ¥Dc6 Æ6™a`žVzxa«©í1ºŸSk§ “µµRfÛO£;É<%·®ÿ–sc;O ÚŽ k¡ÏÁV()3î÷ó®J M®;¼;NÙ÷\¶3„)c<Î{¯€q3†m¡DHYyª2̇ gë7ü»r0|ë=ÇyvU±M‰×ÝxõÂÃÖª8ã Èè›×”²T *¸mM­+T%ÅÀO6ÞxÄž²Ôº¤ÄT¥ $AXJØÆ”ÂÄV*Ÿ²…™!1Æ–Ò%§1IÏ¥ZSù‚òeBÓí ºÔÎZG@PÚrŽdËÐ_÷jÁ­î¬d' ÑÅ׋*a†dÊ ¶¶L¬VŸk/3PP²5¤5†áét£‘U•5O½jÚÊAJ 7¨ÃÀfÎñ¡Á¬xnª>MX¯«=VÆÐÈ6ÍÖùtœ¥C+r}‘¶e³:ÒÌe©‹bEÓšÆV¹ËôtˆÓ=HÁ} Ùv4²ù;s)¶Í£Ä–@•¬òÄVå¶ô”0`òu–Rp[ëz)iTd'â&ÚZei蛤ژñ¬(1B–Œ‰[o8,‹t" ¾ãäi%hæª8”Ìó·݉µ0${ײúŽT%ŽÑ·°rƒ5jóØ šNäZ>±©lsÛ*”í e ö¤ÊŠÕ™`ÄfÃg›¡”›±"ÞJc* @†!ÀÔ¥KÆ#­ºˆ° C¯âÎÈÆ{yÌLì+%gU˜¬2oͰ5gšJ^ L-:™­5 Ù)Ò3ømA_yØjÚŽWrD7 Üú·üã%´Ä†ÕÁH€¯ zÆ1Èߺ8O3Õ’¾TφyC(]™4Åì,m‰9د~ ¾{ÄTx¬¿Ó$@GkåO#U¬<7EÎâgà¦RhfÊV ¥,ÀêT~ƒ¬;Ð;G©ªãKu«€[¢·•]‰­!5UÞØy7L+¦1TóÁç£Pà1Ö”u4€Ð±*¢'ÕOšx…¥åÕÂm&çôV•pnrnŽT²Ô¾ãê¥/¦/îw #;Q(¬¬ ÞÌ9Àñ_³óqîŠ(óQU‹™†7O>VLãÛzR]~3°ÂkQ;â&éÈôù¿³±Í¹¦FªÖ¶ñd•{Ê™¿V)/s« ±VnÔË}xCªŠÙø+,bÌI¼¾6<™†fg22àÆjm4JVۭͧÂÝUÙ|”ÛÂïü™#e»X4aÀªEÓ€±ßw³‚kÑ0% Ô±sÍ*PIžù“!Ë6?œL‹”4]…-`¥qÕ}/µU5ý56Á iLX_2ÀkP¯Ül½áôZÈ"{¶Ü ie"ÅVt{Ö²d›_!ò½[Qmoo¶ €××Ê£°e®W)äúÂ;8ÙèûÝÛéb4ÝäÊu©E3ÓtQ i5žI*IiU›m+¦ù3‘-–­¼mÓÒ3÷:éøú#¹ÑOÉ ¹TÇÄTkàÜè)J5@Vùà‘jH aµl=nJáÑ“¥±¥Ñ" ÖV4˜uOЄÌ9Àm•o˜JðMbíìãµ~<᫲®©al;/A?ŤU¯¬²%ÆD²µÅÇ´ÞÏçxWº“Z+°jñ®7–zYÇ(É©…(Û– ¥Kã£êޤ©cÎ>‰ÙþŒÉ!·Ôb„,Ã>ã=wd3Üüù»*€§BQ‰•Ø=XÍÙÌ ÆS A@—J$,jMP_å¹^ÚU£Ð)EÙu^ØFʆé"g›9“j•»RÝÝ'q…RgŽû¶[iè¥àRVžéÿö¯ýKoý÷¤Y[EºÕ;y½¥àÚ[;˜QôðÛm×QYÎ0«‚f Œ´`ÎZ­Í?€^ŠO²ôðu:ž² Û†IÿöêsE‰„Éœ«ñ>”ó}!å~;fΘf@ªÝ¨pk`3TÞV­è®4µeÛu™sWMc+ËØŠi›± Ô A€†ÞÊÊY6Àn¬¦¶‚€ =ÒZ >ܘ€rô•½Ÿ7²r¸Z i)aàà'Dÿ³'>Z;Níh\{a#U‰ª÷Œ³RÒ£4qæ²Ê­ó„¥¶Ä•TUk«0^za&B­­’ÆPE‰¼geÊ9$ÆÃɪ‚Ч!­°1Í;’vãn…B%_C"ù(k'…ÇXÕÒw.€ãÚoŹä¦ÅôÏhùèRSŒ-ÛõzvÈY‘¶‰›¹FþðMÞ›Sªíµì׈¬Ì¼±9¼óhg«oµm‰1”ÊÝUcXRÿgT%ÅÓð˜àyâùã‘•3L<ƶîâiö¼ð=zk…dª¬zñ§‡Ûâ{ÜÙvÒRµ°µ.E´j|UŸ—ÁV/ìDý¼TRÈ®6[kA¤„S¥b¬ü™××ð= šÌ1eÉd šÖ*hX‰¶ô1+$ ke8°mU~Æû¡ñøËZ‰‘nnÛ¬xd|¯쫉¦FV¸î€P"€é9÷ì’énˇF‹Ý@CZ1E¯J²F•ÝlÜ,&¬NOS0)ˆÍï³FcŒYbâl 6«R¶²:¶m¶ ñͰrgñd)“ L/zñÌV2ÎRd0¡J`öž]T‡ª¼B˜®\U7xFRZ”h{Ú|/fbMÔ%Í[bZÛd•Ø6FÝ+Ô½sí“qËPJ­s 2Ï™O&9ФÏAÊV ÇX]ÔLnÏÏ•6ö­þ”‹nŸØšRGw»Ûú™rúÚ!)uw(U÷|Ÿ¿ðR^—Ä•#L&g¦û;›]Cb«”Uжµ4@†VÙ½“dR `•eRݳì^¡Î[Gþ·è,p[%ဲI\Eo;L}ÓÏ P«JTnTï!2!h¤ L€hþ”Z [nçÿÔX›ÔÚÔSqL.0±â"²fRB‰Q2¤æ'¶’¥Dò€¦¥^Ðs°Å¶½owÛ ‰ù™a²øx#5=àûˆy—K)²MÜ$žÛÖxk}‘1¶4°#[;ŽlÿmDFܹ*ÇcµõÊ6†a PîZÔFâ‹÷68 u¬< ‹iÈDc`AÓªü牋¦¢$Š´æé*ü<®‹ÕœnãçÛ/˜›ÚñlìVÛ‚sU©B©"žg}ÛJ ¼-M$P+¡D;¤”|ÚßÿX;b™X1|.ñù™Ô´1fU» iDY«¦ø€I©ªÔp3Ø6O|…¬ˆ œ³ÝZ?Œ= < O Æ÷÷˜¤lպ̦ÂÐóaÛ`˜Fª– ¯ ²Ka|šl --@“Y¶:"ãi²Jœ†²Ö‡¯6}8q)L¤µFü9È:ÐÒ¬ðªDôV¨ÏÍšyVV'u±V|Á01£ª)àsìïÿ?麿µH2bbMÌÄ–ƒ-ÛfUÇByíN×ï_0³µf’súÜ0E" •[m5Å¢Ù¼Ä&‰ì˜ÄH 1YnCß–Hœƒ­àã/ìýa’ØU“¹y2¼lžV¼U! €&¤ÌF¯¾šìÊÏw7ðLÉ:ˆÚ™w" R@‹3è&À‡F˜™´U²À S¶µ [þ‘š:{/ÞH Û{ôê,H‚ð ‘áRmW> iuç¬JppdØséÆ$­D&Pkµ½Nl9Ä'³uF>Žé꘎Cɤ#w® ‡ÛZé1lmZ òmlN©ÍÓ”²ŠN¡µHɹ¨ÜœdkþJÌl«¤¿ÏÊŸ2Û½!d¿|× uÙµ4ƒ*2}ZmëÕ*0’¬Pe5CŸ‚úÚ¦MÓSÐ H,Äsj]ù;*‡HkCš¡10ùsD…d i0)¤FBÕHÀ¨Þ–R•#3ÌǺ€FíÞè;ÅüYIá7 ÌPd4Þ »7%UÉâÅÛŽ4 Ðjà.YG¤í4 Úªå_w£Új”¡¿n˜Yyy$b-WÐd¶ÜPK°UhÙL²m“HYw)j3i22‚Èlmë8rÛÜœ*¦Zk³µ)CV² a+â÷O€Ì¹¬•ÕFâymγ„E²<¥ðn)T%n`)aH|· S¡UŠ=ÌÜJc¼ŽC €e]J<2KÁRù×+~8½#U#¸Fù㫚Êâ•TgBé,@bXHÙ²rü^JX•“âŹÐ{¥Ä¹Y+de<ÛÌ—µe"”›Ðª‹˜ÕR+ŒÙ–žCGkr)¤x•ȇML¯QóX¨‚ñ¥lY•—mËDø±çsç6:Ö·ù‰RŠYIaˆ5ªE…ÁJ0±›ÏªñèscÞ—uÓö0’ÂÜü·4Jˆ1ÄVQ_À÷gJ%›É_È9\ß&iŒ­,7%ZغjY)[€ƒß¨ªêƈz}‰)²PeÛØ°€‹d<)OÍ÷ÛCf%“jfY ñµ9¶d1þx}õRd¶”ƃEó».Y)[$°mÙñmEþMÛ4=5YXLÉP¸OâúG2V=_PÒtV{ˆý®l›3´*´SÅð4û¾K11Þ–Æ I ¯Ùð¥ÊªBhêYKÕB=ís…ÖIJ€5%¾’C¯Í^3 YôµÚªJ\²™[òAè¶õ¢é&µPE£){zßgU ð4fè%¨cn4”â–þ¹ÛÕv?²˜î¦Wn]¹r@vçY¡»ÖH¸ªZs^È–ÒÀ7¼£…k$[ ›ÇÖB/ }»p¼ ˆ\`YW‡ÔÎÊ9`5UþVºðǨB2i¤¨E†°ò¾¦Jó/d” ’3œž`L8qóÀµ°Òϼ’|Ò8ˆ­ s3þ‡x†ï𮂠‘€+ó#ûŸ #§‘ÊÛ4Ý›­Z[Acm˧÷ÐH«.aU3<Öß;ái~ ÃÚE’±­#ìk„a‡µ³RNJ¶a2‰‘a¶À˜ :š¬`‚×¥©Z•àf⿞K•y”J0<)ñ鑹ÞÙ0¢ÚÞöwT>m“q³5Œ©`_#ðZÐÀ‚&=[ØZ‹¬Òp0^GÆGRêØ0@§¦.¼’¶ç\Âè}¨«ä¸é 4Ç0)…g[ÍW*[žF!ïÚLø¢B< Ðy€N«|7^‰.µ QrÚ|¯#Xèaz[Cº …z+Œ§±vwÈ&GÖ]mÊJªíG²”î”Jˆmµ`åyÃx[#J‡Þ‡<ÒOŸù€mzþȬÚJaÄ9ù÷ƒ!…·ª²0 ­zQ°ínÀVT à ½¬Dæ)m)aX#a{G;¯©k÷ƒLÐZɬ2¯D ÿöU"…‘‚n&¬®¤Ù0ñÖEÎÊP¹ÁÞl}&VY¡°PU/[í(1VÛ”V[«¬TDF@IDAT)ïÉÖ<­‚²™¦BJŸIΕdKéà>2™¼2C–B6†r%œëå-uR¸/¯,BkVÖô²¢¨oŸ‚<§¯Ñ;üž‚ É*7LÖ_r[ iK&”dÕ…7ÀÄkmx+R!™V+ÌÈÙj‘¸­òªxâ—ªDjÁyä\ª „e­;+½\8f¸µóZB–§§£*·ø L€OÙƒËÙªÐÖNÀw gĬ…m“ iD¶VÑ– µµnxš²R…­ °òì¤Úկʶ¬­k©—*AcMn¶›üÃK±M`]£Þjå@9 `…뢪”ßWð”]¼¨K­­½E²>2R¶ªÜ ,ËMSY>µ–Âȶڊ 1‘?[&‚¬±§'ƒÙZEåJǬð)­X½ÇGˆëñy+bªâSÊ–š3PH±MÿÊ4êNzÕ;·4j}cXm»48ë[ «rÑvª-غä^`¶:â» æ^×jÙV ìÈ=)‚¬0²i Tò®ÍÉÿ}úMKèžmß®ãoÔæÉ“,1ræ›G‹.P—Þ%)¡ªPòúððVɹBØ›mçµí8•§TË$ °xÜ<«›iUî 87ë u„€ÏD-À„›Õ5¸@|‡"Ö®{+M3[ âX_>†CÜ–>7àÊÏELJ­0-PªznQm—fk†4™X¥”{¬ &+î°Ÿ‡#KÌ¡vmÕÚ¾Q!†@Ö]Áõ5‰¬£I}~ê'J­Í¤°Tke®[%ÌKPr74’)q¾HÀªïvˆó¹ugɹ¦ë˜,’ Mâü#Oý÷øÁ´5 ¬Ò:6ƒ-O! “á;,ð²MkKSàùHõhmÓ(kQÇ^b<¡ßû¡Šmµ>€½_w O³?ß“qØûd«%·k “f Õ9TVÍœFm‡UH ”7ž*³É®…É:µ÷iYUÓÀµÎß–›àS¤Ô…›óæC~>NŸU+«.ÙôÈú*3dëKiȺWRªìlóiÕB Ü„ô]¸˜5%(2±vodJ„16X2<2,X~¤-LÖñ+aŽ1˜¶¯Œ#k%°šYy/Øið )üL’ÕÂÁ9K ÿ¤„Õ#Pç) døÆèºˆs69OYzdÎÖkp–j¾Tup }Gú~ßV‰.<µfnµUN€)vuªD[Us¦¡´µ&Кg‚Ra3â½ÆnÃï…|v™4¹14ŒTÑy‘.óRÜ*ßÑ:Ãfk0MÍ€” ]±I¬jµ‘Êë’Ò¶ÐH 3AV…œ¡TM‘sSBÜúñúþÙ~>b–4R.ö,Ö˜¾ƒPÕ)¡Öû#Æ¿mÒw >¡Êqü£ÿO¶›Ï V²^0”” fÅ0«n»|æH2…{LA¶ÂÄHŒ^VµÖ ØéÖ†·R6¤×  u,»*ÛnH‚¼yŒQ­U–!>%¦m<“²Ý–fø‰¬hú¹V¤/>YÉnÃO½ÿüç?°vÖEyÛf H³‘¦‘Âwóõ*ÅjznmÝFÎ×àÓ%†RI3 kº§ Uv­i0m|vØ Àgwâó4û ¥4y>ñjÚ0­M¥Laú†L¼Ö¶°àL–¦ñªÚñ¥¥¦m›¿a¤¸‰ÈÓÛV’9-RU寉·mÌœ3±JuÉ Ù”µÖ¢.1ô.‰kѻ㮔PZ‘.Í@½ØbŒ‡Ì¹‘Xy…@L…0éQj'T5*¾ÖV‚ܵ¨—*<’F”BrÈJ.Êâ]£[r@J Ã<Éxª]!6•BJÙ??ù²èxr=†yyá#mÉÒ÷ò~ñØêT™[vYëÙd|D¶¯y¼•‰¨°U.`¶iÖËJ_ \‰*À ˜RÉÏÅÕ‹†ÿ” •ˆ<­A™ƺ<`.Å­”­¬Ùz`•Ûêîdýö¯¶ZÛVLnx¤hËYðáVо”µF¡Äv©²­Ì}–øœCÞ±cèbø÷ø¬|ô„òFµÖÉ/0l­BaçeèGf½dy’ªÔ–ÊIlB|CRJµæoª*á™­Oyú^@&8+¡Á”Gt¿§Í¤5U0Ï€BOö–ž…3Ak…maJ¼Œm 7kÇG‘{a(kmuuLd«ÝHî俦ë‚ä‘Ùª…ÓX9°­\ëÆÐNŠó58@ﬤƒ7†TJd-ªâ@\`rX@I¿KÉšŠ8ÏÎKfk¼ÞYš.Á¨ÍÓñ¹q ¶’ÙŠ}˜òÒ~ÆÇWÒ¿œgB:&‡~Tp6ª-7`ŒçÙ¹2L@#j 4^7_Gþme»4}FL‚gȉ°5[[ÐtE À»Rz>=©.J¹È‡¦»¾ùeóAv|ÙS|e°ì+hkml&Ø6Û9dnKcÈúîñ)ÙT4»j¸“¾>¬úyä¹–Äd<­‚U¤µ÷§îºÐ4C))%]>¨Ä**q½ oÕZ­(Õq(1œEU”1#¥à ÃVÄú♢’­À°‘¿¯0‡ÁÖUûÖ›o…éãÛÂÈpšw›ÀÚÙÝaWG£¼{èr#蟄î€yfHàŒÄ@ÝÁÜš!,E¨°µOS†µn˜kóùÔ7Ì{™JŠõ²íDøGÜ<Ÿš{Kðjk]U½v|#rÆš) 0oòuAvöw’Û ÄÍ€ÕH¸­ÕlHn°I`#©x¤€S® &C 7Û0c¿bþ>V¾Bû£`þ ;—¬`b]–#0dÄ>×g¬çD+—Õº ت¢ÄAŒtñ¾1L…¬ïzՂƉ¤¸•‚Ûõ0ô}Ͷ5gz-D×BÓ÷¶í:ºŸ 7°bBI¡…C%[w©dutÆl­°ì^­æüÛßÿþ÷.¢+cGš °²‹QR•lgz“ï3ò}pæ5Ú#|{5"åz1̤™ÀªÛÊPh‡÷{ PvGÈDYcdåâˆÃ‰mwx£ÐIu±Mœ¿”ªÞì´¦ÄJlÉhÔæf…1B*ÜI‰ú¦·.¤`Uls† ã Î&¸ZT²™só¤8èÞ#«{ÏEùZÜ>çw g³ÙÂ@$qž‰§lK¬ ±FæìH«ÂzeÞ¶U%!µ+⼫èÔÖ2a+È”‡ã·vF†²Ì)­F²50ÞÚ•´…+¤”Ðϳó6›”Ö9TB Vi¬HV“ô¶‚Cbúº¼½ŽÑ÷1uEdƆÒʤÙÎDU$ê †}/ô.™m•ž¬Ö^ošÞ8’Æ Èº#…¬cÖ×¶“ò)ð £Ä0zÕˆLÐ(!°âs³]Àµ#²~@ö |-œBRñ17æ}±ôoŠG61@É ®{]h0Ö·i[<ÒÚ›VÓVd†VY¤©f+«‘­ÔÏ%ç¬*qæÄdLZ¥ê+ 䣄¬B€¬ÄÚäd¢’)[Qa­aL‚›ü<è•ÔÂö5·ÍÍÊǹÔÀÖ·Ö=ÐT¢`0d©>•HoÑV‚J¸áÙŠ:v( 'Ë-[ž½´û€(dbD=ˆ¹ù÷<Àdói«ÄÖý/ D&Û©)±š ³T8ÃdRÀêsðªÊÄpP®JD¦A–²í°fFnTb%4÷­ðj¹J¿}*ì¹4­-ž­íz%ޱj$EˆÛM‹x‚påð-úónèέ´,MÝUÍ ÓÓ‰È4u" ˜H& ¤á_6çx†¶OÛ†‰¡jJ¤E)d¶RB¹”d»I[šdV<}8³>ÔR"™5¾ZbU°.c[ÔE­¦n¹;©Ê`B‰râÚøRÖà µ,½@2éKÉlm­…Zúî¹ £»ð…ë|~G_ƒDÀý:qs¥¬Ê*:v§•Uë.ÌêkQV-`,Œm‡9eßKL¬ªƒá• Ö×ÊÖJ ¤Æ7°’zá¾ÿ›'€Cc“Ùjä†ižHú3Ö b‚ÆÐ´­ ø8Ž*¸* ­ÛX;zdr¶Ý0ü+ÄP&ˆ¡ÇšþΦ*LV•d~…g˜:Zñ¶BÊÚÁÛúì&&8‡ëEƪÃÊò$è›h©†© ½ÉilÀðghM9ÔTJUþ²Èw$[Ù¥OLŸ!Ðx@}ÉʦÌ0Ü$•`š$Ûܬ"µ#ɬx'ÂÔÈVÔ‹³ I„‘Äma½ªåƒììë…ÁÓälKœÞ /åcUJ!Y­øõj*kV²7 L¦p—ÜÇ3ÚZu$¦¬Š€¸Fà àfh[6^ª¬m†ù4!¥¢¤`V ²B9R_oKÖ¨™Ä ã· äÐed²r>t.™¸Ž×æ\`…xÀVÀ mÓÆ`˜4­˜•Sš¼O"¬••ª.yåô˜¶4YV¶"C|$«n‰?¥ß3êcüE”UwzJ@U…ïðk‘ ”u÷óÊbX5R[zàŽO'€¥ cKf+*Çwç@˜ø1·Uy…8Ûzdð5;‹o-êkí2)”'Û.Jª ‰ ZþÁ²]`-Â<•¡g%0Òªja+âÊKü!9´j o;¬—›óŒ*|m™ÔÈ*ëZÒw9˜ª€ºÛÖwüÜbÞm¸GÀvÝ»·³Ä»a2M ØÒÔ=A˜¡mÁ!Œt^%fƒ¥â­x$ ³TLgÁ¿%ЈLÒ¤ï®rëɾÊJb(•Ì|bµl´;qêœÝ€¯î¾½» ß690lËLz—ÞÙô¥Ì¿µãÀ ÇðÂÈÆèȆÿ±"›L0@j£ŽÏ¤¿ç–{ÊN]Õk‹¡±jítp]l‘bÙ°Úâ&?Ù†¬d§ è8)Ꭹð (³ê%Lf•Étï!3Ic-K¬°ÉóÁ{«1¯•r†Ä@¸mM­5ʪ™A/¿w CFÀ$Ml§“%óeˆGöòÿü Q\ˆ˜jST{JŸ#«J jMSV•ôÇ9Æ•¿†3áÐVOÏ¿‡øÜÂÊaAÕÆÈ­ÚRd²ÎY‹ô ˜ /Fmåð&—m€ß0®Å„}ÿ†+ï±®ÉÂjY…e3¯¶RH>¶ÕÚz¸4:Ê"ù# jTÓzaòÉY_¼«°íJ•#°y ·ÈÖxk}5ºØRzqfe 4+”ÝHø0Y8¥-OaªùÖŸ17[«¨ÀiÛü=þžò*™lÛ•7|×’m«àë˜'RvŒr_X¬È„”@tÒfPÕ…÷ÂØ6³Â4F4¹•É»mf«”B)½¬dHßSLŒ:Y€&CÃè¾/VÊ|¦çƒäœ¹u) qóKÙæ˜`ÇÙw¿ßÝ*© ß„vWЧ¤)ò‡ñ¾!µ ¯0œ¿h -d‘ ‰´e¾l3 1%£ÈÑ,4x œŒÁ÷†mW«…°µÆÓ_îð»MɼT—fÕ´Ž•Ër¨µU˜3&‡šª2°µùãKuÝLP$èµÜIù+o$ÊÆÈJ¶”–U0y-¤ˆñÆK«©l²|b^çÍÜ=$K`e%ò·6az«ˆIf`Žó4,OŠƒ™»L«úÔ ©V$¶ÍÀp~·˜øÙºÇýæ ðw´Í©ŠoEæ)+%Œ‘ ˆ vógUgÜ«œ³­Áô² ¼P^Unø¶ñ­%ñ%·Áµ`ËÄJC)^óÜ"ÇSžiî/Ä~?fåSï‚ê”ôúrëNôò€Dš^?Ä·çç=i| ìVÀ Ö@¸©^«e¥â¹%³ÎYJ붦 9°#'0yn¹ÍÏsq]fâõ­©­ZXè[¼wžþت2’¸*þ™WÒØ’™Ä<ÈJŒÚKȇf³Õš™È É¶W‚ `Òðé­ùlž©¤^Y%«ŠˆIà Ó< Ö¶i“ Œ¡ ¨DJôsçcòžeÛôÇÖfÍ£w[%¯Y‘V‚FqŶ(•¬u6‡T³v %xØóè‡ÓˆYéb«Ö*œ IVùôR°àÙ$¶‰oéŸÏF©È ù+üeUa`3A†Õô{¿ë&«;ÁdZ vœ¬jD¬Ðj€Êûü¸UE†ªlᅪŬu2ÊA Ùýw–µô•Å >­+Á°Ê“aóäÜ9¤!C2ì°ÂõÍy€Ol[‰Ë!†¥œ•”èsÕ] 3%„‘4²= ›DyC¶Vb¥ï ‚²«À×cÈ:2D2IIéM¨…iY¯Lš¥”ˆÎ•§UÄWR ¤ÂV@ÉZ×Èv¯YÊÖÄjažô]iw‹Çø¡åº`©&œ!RÊ]—CÎP‰mæp#ÙŠž¯^ý”BÒt¥yV[¡_YØÂþB,4%°VØög2ŒÂÀ;籸Aà?¥’Evi=V¼FdMÒŠÔ×ë!EŒ´ä>ç ó'@ö*w4ƒ{®ÜJ)²¥é˜”B‹º$èÞà†‘bemB>xÇáÔEë3Á'@__[pâ/q®‹gšWI`†3÷ Ui½­Îðé­$Èð”†TeNo€½Ö”¯ž3PÉÖæO¦ 0´M`ò Ç/eæ¶ŽI‹·°±µ+¥D´m†÷\a«È HÜ„jù`ÞÐyÿ|ÍÀá:ßZ{Ã+ «¥L¼Ž5µÕ~[÷èÓ7É­>O¿_!ªŠ:õ¦%‹¬Åd†Ì–C–]m€ÃjN¡ðš™Ùãο Û4«ôÀ;\ƒ²m³Î®Ñ˜¸Þ˜î‚ nP)S¯4Èn3`Í ØÐoЏÁd»wóhm³ÏŠFÀæÔæ,u+>Ûx$± éÓX1}ñ0¥5d+œ?27LWD‰\ÔÈlÌ­ùð$hŒæoëm,27ÛÙ¶49MOF#+e*‘¹¼8 î;mUB€PÃ4HV¶ijg6<ÜVêÕ‡]Z®rd#•]y3ðÙHdFš ïEÏ0’À¶ûÄ4Ãå^WGhK©¼ ìJÕ"ðŠ1é;}oEí˜ØZoéYjͤ^¬¶40Q»Ö¬`¡ª•^ØVŽ X1ËJ‰4ë•M@Vè•x+’ m¶& ÛŽ†qcFµ­T3°•ͧc´ÍŽ·Öe˜4€Às›a)«Û@jWk 0¥8ˆ¬M€±*™¦ª&‡ß¶ÖBJ!ÜyÄ5B¾žµˆqc‰ ¡ ³•}¯.Y!¥w8˜þFÂä¹m}é ¤Šx$s¸¯ˆoòü8#Öh%d#ÎL÷ÇŠZÁ§ÚæÇÐ(§¯ö©>_+:Kï<&¥*ÊHÏd`ÇM‰©ÃÈÈ¿µÁrž9«Ä¦üÈ+Gã›SU_&¶Ü¦KÀsèbUH‰wB¤àoÅ¿©Üð¹m Th¥I0ÉLYÝS¦)›CksÒ?£:=Rw⬶"q$œ³µ¾+$Hc­£Z8ó®×¹uóae6oþ4¾­½ÍVk˜L"eÎ0î[´ÖÊ1‚¸± ÐóEÒä/‹×==üWsþJ¬²€^pŸ ælB+^$^ß4¥hÊ|*Áœ_"9 ¬‚é*k&¤ ¥é)á/›ÌIòµÍÍÜô¶1þàËF6\GdÎDΪòΟFÊV¶‹ V«*•y˜mkd‹T»*¹'Ôédõ¥L,[wâæé–ÃJÈ”Ð8©í×S‚:Òx]ºj&”5B6 ‡fn«-=·R¶½j¥:R¹UÄ$F’aÄôRÜâað/kÎB­¬9ìúCdت*,E?%€·°,+@|é£9óÝ0XŽIƒ6ž‹ê&‰áøLžYÝñ˜îJ`µRe1…Ú Ô0FúšxÌu:qŒ•­WÈ֛óšTµ[ëÎ 3²Ž1Ö5âI¯°HœÃ”ï#F*ѰVØëmÛxë‚éFI÷ J*R ÿ¬d]ÁNTßVå@åðÌÇÈ6ØÏÏœÚòœ õœm{( ðcxÙÀ¾7þ—Ð=2Îx«ûIé¤9è[ªð u\S¶ÍF¦D4güÙèޔϮ S¶íjôÞd3 H ƒatiË*ìDR”àaUm[|SY×FVH)x˜™ü`[J­ë˜¬Z©ò´â‘\[Ø¡œ¥ãP2RVåRô¶VgäLPªç#;~â²ô|ð‘¶BG‘`óØòLÐT4€BÎ"e2k½*)›³”Àìü†šKçYWŠ ùvuH:Uµ­4ª`‘ž\ ¯;܈ 퇓ùJËÊÙM’¥ªa)sÛvÅF£pµM“áEç¯{↱JY…¼Öe: Uɹ¦û+xš€)ñu±ªEêÕ 4[˜¸B˜˜¦WŸYJU錵 ‡ç ä6²^œÕFÆØôBV;‡‚CʬbJ ©*Il¥Á3Qb»{KO“þ8Þ óŸ<ÓW[¯°È¿ó2l*<Í´°¥ìÄR·úóÁi–"ÉØNSZw-ZÀVt(¡üç´²] kɼ’ŽPG˜&Š07 ˜3ÙrFb"‘I“ƒ›Zo ¾xÁAªaLÈÒäЊ§WÛÑA)”ÓchkU|ò÷ã;€ P!€Çà5¢¼’ópóq™þ n[½4%PØ7FUøü›3sÌŽƒªZó·nfæE×ËvØæ¬Dw@—¶d [d†döðf { ‘÷JζÕëÇY!²u]0¬(c*©iݳ­*Y§˜Ãk«°¾æ$†]ZήDt@ ÛË}øÌÓXóI/Rj…˜HÊZ[‹4xAã5À¸+#À¥ÊbÆK™¯c2ëí¶Åjm“)oÂ÷¼5J@Ù‡h«MÀS-ÜümcWBS¸j%Þ%ÎÀ²ùX•GZóÇgnåP*Û•”Ú<²Ž™àïA÷iÂ|X._¶ñ`&ük±v”0Ù›µíáÏ£5æÚŸ*a+±¬ÁÌ“2ÆȰ’|’qî8¶‚`Y…k$ekåt4‚FZa@¶I#òð­3‘bÛ„]ݬ¤„ÙR¢G“O­½óN$˜Ð˜Œ¦m♰醙`ÂÓ0‰omk9×®„l?}àZWKÓ*Å$2îÜÜ­2ŒiN²%˜&b¬ôXÄTΧH“ÁÕÒ¼ü”Ÿšû”«ªP•@VÛ`l1Ù޺ϋDifÇœLÃZ¥š§§FlKI#d«"„•'†eaqë>o]Ö)Ãu!Æ—ÚqlÃVž›ä ?o2üù#T×¶°J<Ð;šEͬ‚àÔׯNBà.2ácˆ^qú4RH[âJd}óÇØª%«×Ê TIшùÐ×Z6gØÂ³ZJ 7$^R†Á«¥Ÿ’¬vëh‹T•˜º°r‡ÖQªAS±ò"ÃÜL"àÜ: ±V€ Í6ƒ”Íf `z Lš¶ÂVž‰×Óï43+WHƒïr0je1°igÕ`²ÆP Óà#W•­Sȯû|7Æñ½o$`óȤ:Håõ‚«MS*\SXÀÕšÁ«žÀ¨â–Øv:µ ¶%&°¥”¥Lƒ1¥Ú†›só#1‘p1† ¦‘°l|€y@êÍÒx|1æp…JÂnÀ¿Ÿ®v»™‰}ã«Rˆ,`!+ô¬è[õª1²m…ÜܧrÌæY!ýOhAF ‰5ímI½Ú6€Õki­¤¦¶ 6%¦ÀHYͰU•-Áô˜w¤Î!¥¬Ž˜:òfHQFÚv¶È¨ÐV*ç²ÄNdu‡x]h0€Â:fßœ»¨ €UÈ^à€Ñ.®“fÙ[zj;u ² 3´æs¾ËlZc;^Ž8žJ –i¶Â ‡!Éö˜kàývfJ±€e[«EÜüp˜\áŸ÷8”ª°vÃ`xº#ÍÏlUÙæiµÅ_¿ókî4ÜræÓI¥à­²iM¡ÈÙ*Ȭfód7éh¬è¥šÞœµní,•shâðωlcdOïï[Ä_îü+rš$YnNØ0]Lfå`l…uß`d•ÆÃS* ”ÚTua.+æ O ¤ÏùíKVÊÚü ưW.C$Æ0V2†Í£<}/b(EH­HÐÍߊÏO ˜’Und…¦ Oæ R­^¡—¼WÅV ¦rµzå€5µF&›[ODʨ4Ü”Õ"þ•gHC9OåRÈĺFd²"Ðjx€­ªšZéÃRº‡ô~-–%¶²„¦dNá¯ÿ/·î!¬#eµÄHðDvœ²­×øè'æl[U Ÿsg!0¹*Ù™NÔ<°â4ÖiH«mµ9{ÊŽF¯œI"]RâEÛU¥!HƒÇÀ}ôÖ±IdëÈ'½ù{‚lid1“zuFL¡ kmûÉÝgVE#+Þem±X-m‚ “Õlm Üü4ñ VŽÉœ²¬N „m™ b¸•’sU¯IU]ˆ¬T“¶dËÖ¥9{rÖ à Ê%gE ôæ×K óšœ;@ŸŸC«­+JœóâMa´Í\ ¤©”Ûæ@ —׉Uþô&°Â™˜l{Fj DGX™ €X‰Ø! ¶MÈ!’Ò04”0%J[M½ðUYÉ›¡Ž vÚß+mfë •˜ÇŠŒ”pËåÉZ‰É¬4 ´›€ ^V )…¾”1ŽÓaeg27¨Ñ4xÏáö?¯‡Z&÷”çþÓ\íç;« ¹)¡”ò±B~g*+eÛ­¦´eÞ $ÖÄø&IãÃî¹õ†0Éá5©CãP416’‰­ÁØvj¼#\Õù}ÅVx°³40}SÍÖÚöOC¥¡§ä µr-ð¥±a± ´ÚŠªhÄÈ4j«"ƒ;Üä§øåi”4V•êµ’ú–žÿ¼Í?Ÿ/&“ç²F¯0ó<ñd¥¬•߯37X à4À©“ÌŠ/•s+¥¸®Ÿ^ÃJgk¤Áa+¤ZL¼í­8?ø}¦zI0¶z‘H%¶§ë÷óUáÊp­]»­òªJÙFZ{.>GšÚ’i:Ùšj+ÖÖ"gU_âôê¹`”7¶rX/ÙŸNG™§­¬r[%¶Ö²ÈµIÙæ´’I!õ²é¥¶;iM1²œ]2ÿ®2ÑÌ@‚4dªãªþ×BÙäji†PÎ\Ô4s¤9­s!PR!Œ·¥Œw¾þû_ÿnÁ·$=F8Zþù`d‘7yºØÖ ÓvŒmdknFF²}m“­`µík‚WŽÉ˜ ÷°ð½ ¼Ž‚ÞÊ ë9PSâ®2“&±ÊÛRÝ¡atÄØîŸ5ee技O÷ƒ÷e‹:š\I à­"zŒ• ¥µlåR"\—Y•c¤T U°žÉ[µ˜³²uÒ›ùsúR­µ Îj÷"ѯ¶bë†`DضR5ÀÛ Ú77M@•è•Àx&”mUe•³,+²øk|ÎSSkA,•U >žN0qžBê•ÀÚxVåÖ ›Ð1Õл Á¸A¼À«²ö?Åà¬Äý+ߦW"Ròç¶õLvo2Akndªl­R€u DVÈ|tœ?_-7ÑœÙZ*è8}VÖByQvæ ñî‡LªÙ¶JÁïº+êJó„Ñï‹é›SvÃ`üx&s^¤­Ž l \y“7É\«­2q U;E>FíZÒX9T¥PªIÌàããùPæÜZa.Ë'™r@‚À*kE¶¦ç)åC5›T§Hf•2•/G)¡J<þ0¶J¤®ðÜ6C7ï6šÇVäÐ`J4ú}¥ß˜wc93¤ás>¶ýqcæôV‘¨Ñå>K iUUˆYíª” …iõ5a:Úî³¶‘liè3's†—€vHÙW¬*[€ g%ôî‡C%Ó aÝ)yªRžC¶u‡ `)%¬Ù4­¶E2¸Ž¶Ãj·•­0«ª†meM«v]‚ÖzÕ)R`Úc§¨°¬Ø–I+gQUX‰¬UÐ(¤Z1Éf‚ç,T Y©ODv$°Tå}º"X­ã2$KØ*Kœ¦Ž­Z4§mŒ­ªžuT!ãileS–â#ÚÖ ž&Þ*ÈðÆø4R¼UŠ¡”Ö498`L3´zÿ•ÇûÚZó¬AÙ{RI3kA#TaRÚ‘©WwáiXÛ2¯\’‚üKY{ÊÈ¢Z+ñ«oTúx ÃÝ? ˜”2˜oÚ~ŒrÛIl]#)U•X—¥‘ aš—iÔÄ¥0Ä}:à<¯Áÿzù량µyuÜ$ {Ü4Ú±-ž87@aUˆ§t·î³á×@nàLʶšÃx@`Tu]¶z-VY9q!k¸ùeá^ïã†iÅXЪ+Ò+yWÙw[¹•¡ÚÝ`›Ïư¥ÌÉçu“ReuÙºÀýô7¡l<ÒmXyž¾rý)RDv‰m1Œè‹Uå`KöÓÈvÍà†Ð±»&ÝãÉl)ŒÀœi¾—«Dà1R°Ùb"ùd®i>Yå²MoåLƒoµ…ËRÚv|Y]…Tn•X…ÛëǪ2¥5E–UÝabQ;+†ž ™¨5+Qy‡¯|]LSS&E>V<½ötÎ¾ØøÙLk°fžg[ÌHý$ˆÌªZ­ea_‹½Í²H¸”mUÆ©¹m˜F˜_9ÆoH }U²Y)ÏÙš FßdÞ²µ à#®ýçõ£Ì*‡æ§Q%ºCš¶9Ð Lr“”ˆ¤iæ›ü, oSǶ”&’ à+@£ÞÀ›ùüü£4áyÀ÷W“¬(½R FÜq>ÿMWþÿàûÞRÂÊVå7cz±É“YÝ*ñx— „²Ú®Î–Iå3( °ÈŠó”3ÿÿ±T¬Ð¨/\-ÏŽÖZ÷VÈš\¶€1ŽP•Ldˆ!® ·ar¬©íL’ j(ì š*ýÜÎaî…ì¸ V"›ìÊÿ™O¼*€LkUpb8dŽG–MðÖÂE…nllºÿ5;F61% Ì kaË$2«Á(»ÚlÆÛÆt.>–Ý`xAiMPjwB¯…«&ð°ø_ãÏWq3—ïDI$@×”€U™ÄulNk¬NºF¶Ä6[÷ÐÛÂY¡¬ÈÓÚ¥~&d›¡ªô«•m{µ4¢ ãËÚ Y¯ÍhšLJ`€oìKžH©w¤ÎˆÁ»+?ÅRìò¿®g©PÉ&ç‰W²5ÿVJ)â²ÕV8šìNª„¾Â”ɬú’û,ÓôL—•R…l+™lnRSF6­¬-Üv[)k¶Vx&]K÷€™(©{-"[§aâÈVâ"[…¢[rÿµÅmrF¢Áô>”ÂpJê‚¡”EîaÅX‘dV²émé³RR#ÛÞF2‘²°¥Teº‹F²V×±,,j¡„¸m+TʶFjm˜Ø¡:W²ÊKåÜAð.œ²—ÇØF"èa²p!Õ»'~Ë¡¶§«²æPSKm¼p^¶€­òÞÔ¦I@OÌ0qÊÞx‚—çczωîwµu¯)«|z±cºz½à:²ñ°^J¤ [†p©ðÌ‘B¹ñ:igIfe› ƒßim3´ö‹FÇdª:»7¢Ö‘ß_|‰;`sZ)ó„ßà)bØ’Áä ¥L“ëž#¤tGøš^˳È²Ý MŒŒgK­m ”­È¿ÁÖ}2@¹l¶@SU˜Í>íÒcåd Ém†nÉ6CšeS–LpÈƯÂ0@†?¢{R¬Ö‰Ó¯ ÐHªd%‘¦Eb\f‚a@¯×¬jjZ!›mM;¦*z+ƺ’:ZMÛ‹A9%R­YíŒf8ýnGµ4 –¬îjžóú&øÐ¤çXs[ßýxc…Üx)›œákÅG•T}Ua íjÄÓˆð«üVœW¯ hZ`&˜H¼IÌÙ…ï2 èñd¶n™³^])Í¿ÖÊ×YI¤Õ¶•9æK©‚úê€ 4ÚåÃL~FªµTA ˆÓ#æÛÖŽl<ÏžKURN—¬*+r5V2œ9†EsÂkšØz®òÖ¦©>¥-Þx‚Ì6f%²Â–~`R~ûŸÛsÃÈ4•—ÌV!ÒÊ-Lé”Â+÷€zR jg¥ÁD +ÏSJa†ð;v…V‘[ήV•‘øt-Rp­4À.áÅuç)«# …Û¸­>íl•Ô H,çG›Öªàº÷3Ýv€@íÛ˜§©¬0=[[˜!1F PX1‚ÆJl-U! Ç ±UGÁST¨*RVØJ­TæÿC×Ý,É–Íô°¿ëš3®Æç‘ÞLoQpb \!­•Yµw7¿µ¨$q‚˜Æs:².'¬g⳺+³)‘" Û>ïpc¢sÆ77©ZÇXm_œ¦¦°Ð«ÙÚ^ûÏ_¹’õÅÀÕÂR&4¿©lñoÖ|ê’f·JlëLºkí›§^1”ÓÕ!c”$¶6À@WÔ`柭òn•LTå=¡—Ê3^/%"2¥móȲµMÖ: ¾ ‰¹Í ÿ ÔˆX )|ª²­…_Ê5›_¶× OÈp_AÀyýU}_1t½XõV͸gŠd]ãHJåñR3¦YÍ×k SZ²î(_¨°•›ÁÄl‘̵ÆÐ¨e’¾ë†‘B¶‘ÊÆtpÇLC øÔhš½ ²™+„ €ÆÈÁçÁ+I€l~[†JX¥iªV†>·æ‰T¥DaÙNakMc«‘µFÜ™…,¦y˜¿?[Y¥™€Œ€[¶øÎ ÔBI@!rÃÔÅ*¤ð¢‡‚¡ìtV[æ¥ðE%Væµd×ã,Ód²-=&Y)ζ0@ÖY€šºR%¶­•H ä/ýë_¡_=ìü>? ²Æ[Qc•E$<£Ï1²ÈL“çd¶»n…ª@IMY/)€Y‚¬l~2|ƒY+±Æ¼S…§–…y¾Û²‰k7 àôÍ, H‰&‰ç&EFd¾Ï‡ òŸfÛ –†IÛòïBfh’ðiÈb¬‚I³ÝÙÏ=cÿy’Á"CcgniÅ´vئß`Â"g†“ï‹W ÊbTµ5•m7_÷”ÄšLÊ0°ÈÇöUÂf(ËM–Lä,õƒ¡¬\ æ¡7  ³Ž‰gâ:Ý % ¾ŽÈ:"•׺Z©¶«* xÓÊn}Gòñµ†‘N7%¼B©õlE”F#_g$Ùn X–¿ÖE3³²íß°‡•¨%;î_ž;×½m‚M>AUºcàÆP•À¨Ðʧ7°5Ïú:‘”­uÎáÍï·RŸ¿*ù–ë«YJdÂÜ ÓxÁ¤ƒÔ¦iíZl™ªN!ë®Ôâ‘@†¶xˆœf­Óp6R(³Ê‡¿ÀhÚ·:LÙZG)æ_UŒÂx+¦h$J}™ˆ•$P…‰ g›?=2eµýM“¬’MÐ6žXÕñý†mU¹ÍS¹Hìæ)1ç>?t¶Ä, iø£Q&Þ+ÙV@(T¾'¥]Û&'èìdï¶R”d"F#[qÜ¿ÅD2IÖj$åM¸”ŽLð1 `‹ÌÐ?ÄÔ*”Í„¿S(ñ’`ø×BÕ@Ô zb¶š¶vz¤ ‡‰­ÍóbzA¦\VÓyÒÃÖ~I’µ™à³e -x=J[>óå³Il‘mßUan.$C«/¯ºZ1MF6[ey ÛÊ1FÔÂJ`YÀg ©Q>9T¨D8AbÛZ×±2$ÈSŠ•ÀkdU™Üäáma«[ú†É¡,Ò ²Y!}¹×̆Te­ & wŸ²bwHãÈR”|l›¤ðH«ˆ·±V2å ‰;¦¾H2ÓÒ3?Å×ພ%Æš@Iå€Â&—ík®IU43e©øTŽ,+µ÷2Rj¼k¡W%`¼Ú”Ö5UE`[—Z7F3ÈÖNÿ†,•æô¸ãak‚ºÀ ñ§¦ñÒW[SXT(Kœ[Uø²Nc•Åpv3ªj‘ñŽF)2N¿ç3Õ´²‘€ðô­¬"Y‰m¯äŒª£3ÒÐóÁ#¤Á@…Þ^b)Û5¢¡Ïnr€_»ÊÃõ…eã+Ÿ'¡\;>^?/0Ã)ólr…×à<>l»Ô71e¼UÌú¶è˜@>Ɇ;—-`­;ìŠz"z9‡> ÀÔÅš›¾H%™ð¶ª¤øà‰1¶Eæ‡X–8%Á ¥l­1µH™OÎÊEâôÛ®KéëÝ ¬cæ¶ÍŸq'=Ö÷ªÉ0u¤1Ö ÉT]ùç \*X @/€n ŸåNg«.^§~7íb›Üš PÈæl[ÊÚ-µ%hª&±ê‹Ñ×J«²@Éî÷I|¤hÂÊ¿ƒœîHµ9ÃâíÕ6g2…”¢9·ê%Èèi¬]¬ÊVÔH°Znjm­²¤,%€9î÷ø@²V‚ › ^~çV« cÂ׿.Çú¾Ý'gn”Bjí®÷Y}6€Ú}¯ÒÓ49œ#m­ð"k@S ¾l“aúbÄÀÖ™0‰m‚ÊmÉ„,ÌÄêåtÀ0žÞk°þ9Ùª<>tùвÊáÀ0Ù°U.¦×ÎÖ*K©PÔ 0,+E€©À‹ æܬ…Tç²­ÐÚÕBS!¦ƒsË¿F ¸Ù*©…->Ÿ­õÍS¶£ÉúCT Ù¨Rdî¶#Øê¾±‘RZ4Éüÿ4žrYØœ:<ùˆ&Oß餔À•›@Ò¸wiÄ<ñõ…; žà|Žz_%±^ù«¢qä_~ûí·ÜíYÀuµ6ñŠÛÖ’‘à¢ßÉz¡¾­Ï÷áÏͪWgzðÖªæU1‡‰Òv 1œù4 œ€)l‹0žfÙlÕ"ã_\!>ÐðÊ1/·.½r)€†ƒ¬Xñ"Æ–§#´5a𬘦"‚ÿ{)›€NœµTd3´wRÊÚ³6€*Yˆ3ý÷[F!¦‹E*·j© ÊúeN–sÙ”>f½ÈÊÕ Ê[óI@#fN,D)²Èé}‹y£ôUUêU"S/FÚRr¾™ÏC¼­>767 Z@#×Uyb+Ò HAÓwzæ²HרŠL°Ê!1ý)û^©*UVŸL3’)²»5>1 fcðµH#K©<ý¶‚4J¦É­ìZئÑÐTÊZ/%@/~ÀÂ%4”ªÄí|ŽÐ<4Z(¤ '°â…ë¶pÛzL4n¦Á(MeYL‘9ȶm½Ú6[Ób¤L¨c&Z;”5MÙ&lÍMaV”õÅÇXaQ­¦)ëÕr®“âÓÖ0¬rËáµ­uÙxA£œ®³âÖV6A×ßTÊO§{cëÞ´u䀯K“[Ûfg¨Ì h†V¤^°{–…kçYIU%U‹üá¶gúëI ÒXu‘Ö«=¶RV±ª[z.-@ Jš S»x8«hl£ÂÄÞ–°TSå™2Ã>8Év„~ #1Vb£ú[° ­UqNßÀ¶–¤:Tâ¶ÖwXøÙa‰­=åÝ¿¬r)Ì՞ǴàWR—f£ôÅð °£«¿WÈóKœ¦ad)@ ¹z¹….™ƒ¦øbS²J–ÅLȶ z²fP(b¬Ü1‰%XŠ-0Ÿ¶Ö‚@6Ak%ÖÀM~Þ:&ª¬ÆÐè^/JÛžT7€iTbãUE o‹¬KÃX›AŠFгu±˜jiòŸÂÇX‰ŒIw…Y ­ekÓí`­a@$&Ä^9àE­É4MŒLãD¦%¦ñ¶DæïBzñ4ÕZeEÖl9ÐãùË_þµ¶Â– @Ç%ìÕïÞU"EU²1u¯ F6 ¸öçfÉÚ2¶Rý³°®€¾0T*)â5’µ}~òlÅ)YõŠÐ»28+çM÷Þs€MÅ–U|í9·"›–&¿y*ŸX#²mQNÀ‰Na› ÍQB4jd³½ YU™ìÆlÉŒ§W¿oQÚ:—@º¨î ¦Dja˜=ú97s­ÙÒ`|ÂÖ‚^÷sžûoà±T%–"›'Œ¯uþR‚^J!2Æ g•B¼ãà‘†GV…”òb'SÛy­RÙZAAÏ„§UðÉ*~J¤¬ûéÞðõŠOÌpn}_ØNjYáW«ik‚„˜—„)K¶uWÅyVH8Ok@G¨PUÀJæt]•hr|½jWI†RdÕVŽW…œ³mØJSa%ɬ¢¾e•ô˜î vW ‰­Ü ¥ ýí@IDATìÃeõH9^¶çˆÄX19xb+ƺ.¶}³)1*«R*±]­îø|ð:— iKàÔ4$[Û;ÝY²²ˆøzÙRŠÛxLæÍÙ#ŽúûʱRbëàÇúŽ]ÇYéÛ–e«Â‹ëúY •ì½’˜ ÏܶòZ'¨^yÑ–°Ò ˜ÃyZ÷ãχiÅ[i*Y¯Îòn ”c¦W‹yÛ•RëGS]ª WŽÁwj ¿ù°ùÛ®—B↿lU² 4m¤ ­1²S®VÖ$:6Áµ9·”j$Û^?“¿úÚu¢ 1¥`AÓj @aonÔ GÒǧÔÀ©v4øuÞ¼Ä@3Ê#­¦ܸvÝïøÖÕÄ×B‰­ÐªV ëk›s¼Ö akšÆPhk_v2}E;¾-Л=%OÊ»ÅM(éûboRÌPI½ºœÎN/80Ä4ÚùúCJq ´Êb:ãô·è÷¥ÄùÇV_)µZTÓlka»»‚)•xñøàE‡R›ƒ5žRDªLn½ô9š#Ⱥ.—æí……3v´j똹Žîo˪ÖJláœGã‰wðL¬RÄVÑ0VXª¨gàÌôý Ó”Ào0[£Â" [`&áõrR)…™X«Õ:Ò¶1l7€g"´ën­4VoAbØÆ¨ÂHUÁiLN‡ÝREó¶¹i3¬œ’¹TÉM`Œ*´¨»µî4¢dHÑpEm¥ÔêÞŸ±aÇ?Òû[E…<¥f83ÙJt‡9F•ŠIiµ59C)1‰; †@ßIH«h’‹±*YYilk½s5$1Aå)cà¹óçc[Ó¦²fUǹ9…È„&£é'K&îÂW^£FEÖ9ŸîAA€IOcûžŽ`…žH%¢rÝ¥\µZYópcR¨ÄVØÊ½*€l¡œO“ÌÍhZ  +2)2«à°NSyk¶²@Q­Â†,µ@JÄ'¶zù; U_wdnÆtÕÄfþ4»W“åLI Ri¬/ˆ÷­Ë0­ÕâL>«ŠL™O }#µu “eˆ1OÊÚÙÎ_VÊV•U‹ºdb%ÆøÆS› 5=L ·äÍÁ<ß«–ÅÀ`4e1¸?ï^ɰǑqJ+mL+ “1á­J6MóG¦AÆÛM13ƇÅ*ª †€²Û€em­ºœ¬ PI±Jv{ 1½–7y%Öëú¹á.JanRFJlŒ-PbÛ£'‘{j]6ÙÃñJªÊ‚­”×håÈ®@.˜(!þ¼[Þ¹¬» é}OI©wSÈæ¶x€Â~kï®iHJ«­rbŸI«gÜ9»\¯`M;?}>Èj­†AªŠì$xnáZt>"¾ mÕb”ÛZ#•М‚ï§…U‘8+2Mëüm®±‚1Mϧ9­ú:@À°“†U%º[µYig+d‘›Ê¶Á¬ª’••ZÐv «‘ÙrÀ07Õ²0¾­Õƒ°j$(m›ÇB9ýFˆÉˆ»–¶VJd¿só§YYEJ2G6adƒiÚ R ›¡U"Æ[C¹ÚYu—í³®QSI5ŸZTK€„10gå]‚ÿ—Dz&”õçuu°B©¾ýáyrP(dY¹ºÎˆ‡ÉÌ#k’LÔV.H“¥éGwÃv ©º$[>dNaÛ‰:;})@Ì*ÃHkƒ2g«aXY)UIé‚_¡lÑ¥9x¦´uáV½Ä<‘ÌÓTU ÏŸ².R]czÛ|Le¶”ÞRóÈ’Y˜Rp`e¥Äë %°W)TaºR[³¥g(²º†—>£Ö´­U-qŸ1i¤ð²xtÏ– Æ*ÒëÄu&uçãekBÎù9ÐÔ" PEƒ$àc °Âj­x‘#8ˆÈL"c–åÖé€ô9´bttÜ¿Ÿ8>w€Ë!k`„·ˆ À§C±Æ–O`«]%®:­*åÄx·Š¶sƇkaYÓâ²² šº'Æ“åŸg¼1ÔJ‰ít¶ÝIÙôœñœY/óü;T>c*aÂA ŸC§ËÜÚq8 Ÿï¶Ê;Ða‘¬W;Ÿ€†¡QB&ÈJ"²Qm)y4€¬§¬Óxé[S&ØJ)òÉÓ)d³b«¶›Y  d«FföoówQ¬0*ä€tºn£k”eNйr#h+Xð̶16UFž“ÜÁTõ’ûš-[!Ì­/ÿWʵèæsÀ,¬°"ë §Œ³ZW5Тëí, 2‘RR æZÔx‡»:ÿýiz>•8/PÔCàt:bRfK¦]ÿÓUõÕqäш )à‘¶aksb({^zi* „­M^kYó`„œlm…-±l‘‰+ß6Y%VÑG›ìüw¤sF®Æ Õ4®¬­²VJ¼Pï`VGí´4¡‹³•õý+‹±U Ó(ôòÉÆWÎ?[J3øÅCì]¤lBz ÔŽ&O€ŒƒA6Cí*ÏG¡(k…é+' §o=vWÀ<ýdæÁØ2±Ö¨!õ2'f[|¯OØ…[›§B|#98ìt¢I(k‘ÒTB R¯HÛbn€ÈG øJþãøÈ™˜_°4¶ AèØwÏÜ ™² ñôuÄ˲ÄHäf¥·íNl…mJâÎŽ„ïA??€kj-•ab¤Àpn†<Ó E¸U–ÌÊ#¸#>íh¼ç¦HØ‘‘ümk%L¤¬mݰ”©†Þª{údë àE2JØ:~©÷Œ²‘¤Èà ñîË&‹·zŒW¶aôí¤²·çqÎ_ª ­ÍC?gWò2a‚NQVm-Zi< FÐ5¦´rh<øŒuC¾ÓÁèz!=²¶RÜz+àÜ´–õଵb[zY>)ʵVM²ÃHåf’†!š³î4@¸ò Ó—âÌGÕq¹¿H…ËbÖÓÍ÷¹î¢›¬at)0€ZØv d°æœÌ ÓOLÓ„W~–üß•C-¬Çýú[Ƥ¯¼£­…-œ`àz|¾¸æPy½`æÂ–ƒ­091.Æ)üÀêãpµç\5íV÷Anø¬:;Y%RžNnüS–ª«†¡ÁL…é#­=h€ƒŸ2u¡ÁÀ+¬Š‰sI‰:Ò¬M² i¤¬‘ åÆÃTU6%CÀJÆÁ©}7ÚÄ™T së1¶²ôH/§³dH ©Vâ94 ¾a+AM‘VðBR$ˤçÛSÃHéK·Õˆ¼áoæ,øf¨<[d_)R}em6€3Cµ‘gØêNÂ4¹ ¨]šºÓhg++|MÙ >¦·T­©ª²ÊÖh“TȰrÐZØÒ4gO£¶tiHX‡×ãsMÛšS$¦¯„C˜ ¶6Œ] P( dVT¢E­­¶<¥Ìo…{44¶ó·Í¡Fn¬ª|¤ÌCo¯Ò«i%(ÒÀ45Â䈞#€´rSÞ @W]꨿µ d³jxY0¶R>ƒŸAmêÝ×DêVjmÎ@\}ÍîÂ˦×l-UÙZ¥Ü…5™’~ÞÄx«½g¨Ša&õš!Ðüy£íÄõŽ6+âÐ=Y†dZX‰›?œ¬óF³©eB`-ëO¢ûû'šÞ'oÌL:¬F%†y¿0)Éà&l*Ûªsݤè2 ¥Ëá 8`wH€¡Œ±•å†ôó¬‘Â`l1€Pż€EVÄ ƒ9&rúf¦1¹¿fnHYåH]àV…/ikúÖRF’BV•?̸¾i”`ðôÖn^­ö€&PR-™’MÕ Ô¿  ¬|^xJYÃUÉòø_ý0ÆúæpóçÞ¤TY²j…ZÃ"’~3ÍÇLaÈD¸¨:&fÛŸ½«2@l¾Å\Wb&^mKµ5³¦L”¯†2C`å¥PkªîާÙôLò‘uðnOmU•h];Uñù—•²5³,ŸnÆØÎk¥I€'+4âÙ´îRx¯$†gåœßîe­ÿú׿öÓŽ²Q1óÄälͬ©¬Æö.…”µ-Õ–?Rv‚®ˆc-t§—ºÂÏ"õn×´d,lÅnŒ^ŠXÈÒ—JoKPÄ ÛÂÖ@˜¾Hà‡` Ù.¿y0×é6°uç]•Q9sÉÞ7gÇ‚ž‰òªê…_/íºäOŸ¯^à®0O©úbÇTËÓj›§ŽéµSÒ`˜&±Ö—8«ºxÏ_‡¬(E…ºd»”­B!`­ƨ¶¥Ð¹l­j}äô¾õm³ÙTÁE})u±U}ޏIÕ îkÖÔšƒHc…õúe©˜Ä1´Êš„•ªN1=€¤!€Å;37UVädžã¡XU!ÿïÿþÏï 4ôý$B 3$8îß ‘²6¡*ž°O•Oò˜VL…j7*Flkæ.Óüm]5Y…¯3† ×¦ç+ÛE)g☙›ê¶:‡REÖª|†°¬À[W«<™. ;£,`í&•À‚1 •dh6|¿•õ§P©ôµK\‹J¬ù+”m𙇕TIFÀ¹{Ð7·4ÖbƒÙ:xž‘jmá‚Øåð‘dÖšPkfbšRþåÏþ3—ŠÒ¥P«9éï?Àå’/¾P3+Y¾ÊeHŒ•^I­gµÖþ·®4uMir³¦1hUÊw°¦§ÁÔEmMæÓßü†/••UažñLT…ùØ6Ã@¤í,T¥ I£o-xú¶ÂX™líˆÉ¼ŽoE d· Ó[ÇÖÌda²ÏÖ‹[æQaššÂ¬xJˆj D·g $™rŒµ,=%ž“áV©š<C@d«œ‰Ca²ºÉÏ3UèQ”@mÓ6pns0ª,ñΕg²J8ˆ¦WåašÂ•K”²æi$šãò­]Óê…Tèc…¬°«Ss“¥‘"@vÏÈZ˜Þ<°ä&Q µ @#ÚZ×;dbÛ÷ æÌ ß‘øîÄz{Q10¦#0ol>Êš„Æ)ØØ" ¼ª ­;NµJD³ê,ßêÓ(ÜW 1†511dH6!Û6ƪ «7^[¸±ÉDžª„+ ¦A Lo}#†§À·´5'[¸m @P nÆa[{:J”»ÖdÞyLw®$ÏF­)ÌeUÁLxzŽ]l© hÝÀ;Z#ÍDÓœ7íZThò ;šUmCf‚QÒºÖ¹5¤µ,™ Ä‘¶]ËdR$X—HY3X*h¦lNYžzáU…'*2A µ˜Jl‰ç@æE•r·Ü`Ÿ¦®Â³ÈP6&[-â­×þ÷ãôJªâ¯V ¥I³ŸSYe~+N#ãá^$ʬ¼x¸s©âFo~J«rÑ1Éj]w<=F„Û–ýA6U61н‚ÞVª.p$FJ!^˜ÊÀmñáÌé—2yÃ+éµIÃM ‰ 8@*‡)“uWplMÓ)Ô 3ç#w:d&VMÙvRƒ±²­Ö«" wFâmr© S£­øR;µ­B&)EŒÑZÀܺ™”ç7:~+‚8}Ûdª¤øw †¶º¯)@™}Ó’å`».ÕœÄøÏ‘ºèþÝ)î'kFdëÑó  zsPvT«°Õ•@ØrëW  ¶…:ú%ØXÕn)µ4õêHRjEVj½¾jJ:³îui¤¬B[ 1l×hM‘‚ÞÚhVÿº)æT¢©ºB¯]¼‘l…­%Îjµ a·MÓdÈ0ƒƒ'V(øY¤ Ø bQ9r¼ÜÉd ˜°*+7<½F”RUÙ"ëž§±3é ø=­UÜh`A°"ÉD½t{Äeç,%Ò¨"ãï}xð°¨@¦\Š %^*k+Û#»–ÇS—Ljææ˜= 0ž˜Uz˜i èëSF)Û$ÚIu'À«”ó4  9Ï¡¾ÖœËF^¿c¨/L *«M°T}+Ad‚wcsÀX¶H@VX/Û÷knµ4† Íc^!o²F€X-åH[‚Z4U$‡”€I˜ã͆„­xU;ƶÁN‘5qG㙳Z‘sŸk[šKÿþþ`„rgÙwgG•×ZÖl]—”FY5¥À¼sÞ Œ‘¢gè{üH>Ü K³lâcý˜§±’UnÆk×N“¬-ÆÖÚÖW¸ c-¸}áéÕ–lx†@|o¼òÚi{Ê5b”t-€`Û…˜Ÿ’èPUá›f.0Í´~ÁRº³%Ȩ Mó`ˆm…Ôî~#•ÀeM¨jkíòsHY_)[¸ËLÖÊDm|2Œ’ÞOšÃAØÂlã•ÀĪ0ý­ÁÜjm•­\/ÿ¤—¾Ï2¾FL0î?qæ]BáÆ£ÂV·ŠaÞ爡mÁJ-M+‡†Ä(±6!0Ãj­uÇ«êza±*ÊÉ’¬Ž I€øÎAb¸ã÷…ÃÏ­.Ö¬¬œ‘ ßv¶ñ¯†Ø_Ç9LS‰ÓäZ³µñ®×Ùñ€TÓ󤤤ÏÁZ–^x¬Âé“)¼Õ§ÓõI7-°ùwj¤1ÒÛ‚ Il Y¶Ã[A{3ó±Mlk*«@3t„øH2Mú;Âç÷ƒnF6Q¡ik¨<\—µhÈ>EJȬ|(a«£)ôªXÕÒ×%[$Xw©¶…̧±•^r7CC™¡Õ ù[s°ª%3½maÛ“Š$P‚i V!P9æ JVV‡­õÝk†lB3Èæ …mKaÌPÖªªB‚YñªR(I/k …øÈ¹ɸiu$H–ª„’ÆÅ4 œI-LBŒ,Öº.])=qJø µqŸµÓ%ª¼<¶j¥¬”C<¬5q + ek|ã5ƒ!•[É>¬£HlEn L&Ô²n£JØšªÁ o+ð™_Éï™’CnJXÍm…•ã¹õ¦•ºö§cVV Yú¶ièµx|d3¬©m&µSx^Äî°*>øúâ§  p“gY¡G …i˜úR2t|÷˜0Åæi d¶}>³Í)d㹵͜ #L­ ¶(ee2¥-™g—±äq¼[º`D­é1]ú1ºO‘XœC~IS_<|óçø°HÆPHYc’¥!6˜a"»J¶VY3˜°!móÙcÃÌ6}2þåáÎ~F¿a+ºCJ¯QÎ0ž¤Ö™cn&k†Ì«Åwn°PØ Šç©Dphl‡¢©VpµŽ·î ¬ÈfË\0Lœ,¤H‘?FS-l¤0MMõ•í5S@ÂlUÁÄÕJa¬x“°…C¼’;Ôg°P‹eÐ;£Úlñ:hlŒ i¥:@3g¶¥*O€|ƒL¨âf©ÆÀh—’ Ž|ÝŠ¤/ÕHk¡6žR*kúdu4±¦€H EÃAj2ŸÏÂHùHqnZÊuñ¥Ù{ȪF”+Ê97a7 %hºåR@<)ˆO‰•­ù ”úRÂÉ`¡\ðÍoÚ”º#Ð…lT$1Û OÛúÚëçÞâ­i–McU"• ÜMj„9CÜ×CG‰¤,`E†ãgTUaâ<ÃL²Ê/0B¹°•7óùf— O¨}·›œRªëòqs̶=Y²"[=¾¹uáx4z©·—T3'îÙ‘µí’Õ&ó¬u4‰­ MÅ„¸IâÑZÓ«<×tßFJ)Q£ëzæ‰__@[È’úûÂe™8¾ ­Ùa[k ÒšÀ*æ€ÏM£F’­i¼µ¯ôŽÓä”0®tjnÕZš ¾)aÙL8Ãm3áücÈܤ€‚€Q;>«Ý’­”(}Û4ªÂÎ.ÛTÎè}€ç œ,2ÿZg®{3wQïq:™€•‹HƒqÓeA0 T©Ä¶,ÜñclÅ[XÖYø›ÍÊ$’@|'"Î!e­ÈÝ!€/N³o;€ÿ%>ß4j]f³…µtR4€v€ÚR4˜¬4 âßÙª¥¬¼”u|˜-rVŽ€¤¯dÝi |‡M–ùd·î³$°º1b&ÄVŒ”;镃 ¤*Îþ:WÛJ@ÖØl™h‡~ùÛßþ†ê¹Ú…Ýl:'ѸßVÕpLo& A< „ mÇÞª:'€L èÈÊV–ƒlëÊÍÃ/Ü>,ü]Bnd½y"éyÚÒsææ´dBÖšOJ˜à&ßTô°.¶+˜L9(RV2ü%~ÿ™dKIP÷ *Ï6au¼SÂZ˜Ø ÛfnÊé¥TÉæ¸ѿ啌^¡”;„²vù·b˜Ð0¬uŒÂî„Iãa¤ÊbzÈÝéš!7âªJ1ôì “sz†æ©#PaVÖ½©¬ªh€«:7<ŸŽV;%”LC V¡m' À€¨{g!›UM•ó´:5Mó«ÊpÙZØ ©Ä{âÙ)$@*\£Z¯K ³©Xa:rM×ßH•°Õ6¥p[«­va;«Jb4+iòët¬|ŸÔ×¶cvdU÷þ7Œ@- 2C«”rì¡o6 %qgX*°'åàù(ÑEp®#:`í Ÿ [µÿÀ‡¸,qƒüÉüþ|œ1²Æ¥O‰ ã»@Ð4¼Z]hâ›Êš‰Õ¥àBazƒÁÇ_ÕùÈ4RbžÙ¦±â=¬½Fâ7’T²V½¤:F¨Jœ9¾÷ͬP- Ö|Q-Fm Y-lÍO`*Yd&í89Sb"Oûï/Êw¨³ü }õ8ªâ/¸Y)éánFæÐ?nÚ™Ä|RºÉ^ +âÜh†¾ÄX#ó¤GýÙ†L·MUI2L)%x¤©®üœR›˜qšÚÁÆ“Y™ÛZK­{©² 0‚³•XJß¶@Jk÷ÌpóôÐã™ÐˆäÌ? »B«ˆÑtæJJa*R’ ¤PX÷pš°Ô\ ØÚé2ØJVRy:ÊSaY‚ÆÈ_¶¼ÿ‰³•ÅÔÃêüòB[½ÙŒ|æýæEÜ@tjf‘µõa@ڞ鮸#Ñdµ¹)òÊû ’fÕ—Ò0Ïj+jQ!C ŒÆ–-@6[3ß)>/¢$Mz2[úÆvöšÚæ#{Žt¿Jú­%7ëªæ¯–!1Т.¿y#K£séBo­6A˜UÞÀ@½Bvã‰ç`K\kå9˜Ù ë>« }=1”åÓä¶žÈHnøRJ¸aøôkYnVúV€¸Òè›L)†I×ã5åo &¢^ï;Bc줅@’YC/>x+2 Ü–y ãm´&¶¦Ì™&Ÿ&^ ©&ìtL0Ìw·¬d³‚E%˜Ž`íø&—m$š^¼ÜhxÌV!-À9}å5Êù4»C ¤*YsÞäçaá;¾r¼FùX‰mkYÖ*¯$%ŸlÛ¶šP$&ðÜç¿Bgw Þ‚~-£—µÅëâ F6•µŽxAf%¤.w–4X)nfÀŒ^a€N”UÍ ÜV- ¥À Ja[“%ž¿”9Þˆ—ê6zr«i7Öœ˜Ûä,óOÖ1ñ<‰e4 ’içÄÕ–²*ìªML@æßÖÊ'¬ö )dë pÞ¬àJ¬ÆÀÿ|óXx’mû:hT/äÙ0zÎÍ£Ö–@­Ç±îûq²˜”µC&Êt¥˜ ƒôÄmwáyòéA\óöÜ¥`L1¾k_*Þª„ÒZTÕ„f¨µ!½iH&ùXw"%Rn[äUâ,¼!¥D­°ù4@«ÐËÏÓ…c =üŽÝ¡”DÒèˆ $î{²yôE:šIà&UÅ )ñɶÁjd­W‚>Œ¶Â²0²I¬E§¨0¬£àikHUÎ ô“"†™7 ̳rë"ó‘è eó)_2ž0Á4ådY<º+0Iƒx|ùÔ¢Óq ¨Ú)`Y—™~²ú–µŠŽ¶ê…lå0Þ­"•—Ê“¾l3õËVh0â)em™ðŸ‰¬°-æ 4½`H–L §!«*•~nßûxJ…i¬Rªk$´d˜Ä1Vú¦‚ë‚¡):F6¾«8Ÿÿ ¹þ«9܉¼©~e©kOÎmâ%>;¸NÍTªlµÚˆJ@0yqUæÖÈsª…h|oÒ›².²¢Zz¡ÖJ J#+ì.‹é8²U˜™# ÿj&+þI åì‚`'mŒ:ò0”VQë°I€V2’©rž¶lñdù[+¡o[˜‰È|±5'°*€lÊÒ`XÕÈ6Ü”¶ªè1” Òà)[ f[tQdj{|Rð¢‘"™sêB~´¶ÅÓðib¡Ö î­ò!æ_ )2˜¾F@[µÄÇîzùctÄÉ9×zæ˜ 1Õª d_ãad‘º+ñžaúø˜^ûNÑÌVxfkË Ï§Zþ›f% „ÛZïtçŠ:‘’H«!#aÀ–à(Á¶º»$«×€;£B[%•'È¡QГ1ÔÑ' ¯`ÎA;«­ SÕQVBV0gE€ ¶6†U ”‹ ”ª<¬vùÔ ÖHtØ ‘"A)þWuþ‡t]rU‘J”«²Ò;{n]¬°”gíÝ ÇðiÂÊá¶R@zk'Ê<+zÑ0‰wÛ…ª(­Çú~ê­ r€1”"C }‘y‚°ª4…E©Ê­nF¬ÒOs埥1l6az[w(šD³1¤ÔÔŠ© 1²o`Ø­gUªˆùp¨ÄÚFe²Pˆ,YÇ•4 ­ÂHMHF?s)ƒaè­²…¶1ýµù|4ê’¾›ÌPù:Ê’Ùz£z”aË­rXmUrsÚ -,øcÐ}ÖÃV>g˜¹vÌcˇ&[Ì5>K…9T… pØãÃÔËŠ·í@SqÕ6™KØ bjwŽttž9nS+™x¸ŽM{µ¿MIM†­IȬ²ZÏ„ [b…´¾£vX‚‚˜¦;¬EÓZkì6š¡l-â1#ñ0çRõݹ& ìfv:¼P%…4U)xÎ0sÑÃÒQ¼°ètÀ9ßÿ±è’KÏÙšbµZ‹m»1[s.*¯£Ùÿ1 ~šüwœœ‘Jþ˜MUwÛÊ[óÜÀ‰Ò™ÀVH†óŸ³·QUb)za[+¤÷ ™X•”_«Úþò§?ýÉÆ§ÖDÍAQeÌ.]¶²RdVáÌø ×ÞúÿÃÍa²L|c7 Ö–âŒ×T0Ôδ5% ìÒ÷›DUˆL¹*[å|6§BŒªÜ€°rž­•C>V²|8Ûò¬Y™™@‰/Úò¬ÜýПLTQvdCx˜¶6Õ®±£Ù6[Ï…¦KSX”-àAóñaÌÙ Ÿ¹ã™3%ž@¼c4'²¬­*“Õ¶ ClBóìÚ+?=nHùOd%Få`r[QªƒkP­”ɘ4†Sø³ ìDVÁÁj+:~—c«VŠ ·R‰·–²4V%ŽTHpr÷³ ÅÙ£i¤F%jUÅ+쪉KÉ YÏÅÚaeâÌSÂø·µ»RÛ_._§ÏMêÈ¡¦ªˆ»Õô aåY—Ê­›*\SU –Þ–Œ¹íô°m­)nÌ–¾lm¶ :2ÐØ 0¢£5†-7aÛ”¶É¬<­u‰·Ú6v¸ÂVâôu$0óÁ¸.ïLž¶L– Œ™`œÈ–Iu„ŽI³c"b¬)g¥ÞK¥ûÊÙ&4úÑ¥ˆÏ@÷›ÓŠÄôV€v•s[«0›P(%ˆ›\Љ8Ö70þÓßwx!)¸WT‰HV»ÄÊ)À$@S!=Pb60ÄÃüe5êR¾¾ˆ)«y&Sˆi J¸¨ û`fˆ]¶BwR#[½ræV_[X6s[µ~2›-ÜÖJÆÊ*òyoCk¤5óÉš§îÓ7›Ë1¿ŽJ:8Ðõ¤*¯o«ªÈš¶R ‚² xfkk<«- Ö ƒo«Ö`ð)ûq})5ÂÈôyr°•riðêóSÀ­JñoÈÙ®¼ÉgˆÇcê¨BZ_Y1°h`UMe;Lf¼1¥§@ƒ¡qí˜ü3Éd=—Ü0¬„­@‹Kœ%Ã4VŒÌ“žC÷£…«Ã4L…1ü“Q˜\4[VBª“RVkëÎË6!¬Èð—¿ÿýïê ä'ßÜm7G£³@XwŒ¶˜oUk]ÁVÂŒRÙRæ#˜˜Ài‰eé¥lYI cÃiñ^MnñÄi|Ö…azV‰1ô$ `÷XkLW¯PÐX›V9Ü0)L}säd¸s?0ºsþZÃÖšª2ÇW®P`dw!jµë3¦FvãÑ 2 ×‚n`—†Åmu¾Ó;2·¢µ­B¸F1û ùÞ€,†˜GkÛ²YYu´U 1±rÑ–[3‰^†¸*)a+K/«Ðê+þ8~ÿ­ÜL„›±²Ú+7S)—R˜¡B±ÞIÿ¥áÚfîAcXM ÈksÞj¡¯ñ:`ÇáÜÀÞ%¶&T5À™qMKµÆ4ÞU.¥]µ¬êõÚª’ÅJUdÊ.Ç…Hu |¶²}b‚|lÅ­Zo Þ^%²ÕOÀæ/àÝ@nV¼§fuK™è¸ÙVKÙ„%€’Vš.è, ;B³µÅ™¯€4IJæžZ‚FÊJ‹”ù¤×ÎAÈlûÄɪí­CÚ6³°2‡ `.¤ ¼mŸzY[žÕ~%ç;³B ±lJ@ðO;ÆÚ…+á)¥$±¬€™¬­¬¦‡=zå™C¶U½+^ÐL¶,®—UÔ¥+gÇkYm@V••ÓxyFb2‰$æ¿òž©­,=#V.Ì ¦Ú¬2oxXÈ* WËD\¿s!«Äéô²Õ‹ ™à@VdËÇÀe•{߬JðjéU Ã5BVŽˆuØöéÃÃñV°€Ó[›°î iåL&+6pÛ4µÆø@aþýïkÄßê#£6)ÛZWIЖ ŽLcU+‰Ⱥœßl1=z$[†‘Í“Cž¸mJ²ÚÕš~“w9šFZ½•Æ‹°Z˜¿mcDµ°•¥¡¬WŒl'µÉ„0ÀJVÔ.Ok_wÛi2ÉPÖwoae©³(,Û0Ö5íU!Ö Æ#¢1²…‹d %i`Uý”qF<¦v ¬H³Ry«°Ýµ$K`íÌk×løŽ€L$c%È8K™AØzÖJxöëÐGŸ'=>R”²ÊKeNX{mˆ+™À+$(ï—þóŸö¹Ô VC-’âU £*áÈø”0Pù›Móc%jZÐðG:^Ðð„¯ü\´'äÊh )dí’­P ±rJ˜f`JîÏ?ÞV^‚ܬRž‡UaƒyvR¶J˜|.ô>×ô­õ¡rzµ™÷ì­¤¬BaÇW SÖÚ$²j“Ól”0’Cƒ½ ZpC²ê "iT©u.+~µFÒÄs`^ Ãp€[ž²…ÂRüëÕ ™`\5¤PBtöîœL˜AÖ*²CÅÐ0ÁÈÂÍyåçñ‰ãò¼–HSud[Zw{ÓùX l 4J¬ÊVSYµcTþ¢9‹, €¼c0@Ö ÍÏ AY‚ªÜ’¦Ì À™¸yà&ÌÙÚ¶•F‰µ€j!rÀk§ í\je…Þòz! ðªhrË¿IPm¯/*$pêþ[o*b   Oc{üüîØÙÒTb€ü›îêXqÈŠN€gØ•ÊãMEH­;F4§õ®)}lcnÑç, k¡ÜÙS6 ±ì˜ük”‚¯åYl €j“%¨ÐmÕ:Q²~µ³õOÀ8ÐdE#`×ÛE Ø 2éÔ"m‹w$ å¸ðȶ™\ã³xmÜs.EߨpUýÜŸs£Ö+FVÊëe¥qØÈ¤­Ö¶1ÖóO[Â)ØÁ­×ÿs Ö쇑­P%hjÐnÛù¦ð•[ÕšÄñ:aÝ=‡lEÊ’YÁCéP€ZbX9Íñý^1¬OãÆ¶u'R1l1uóÉIYßÚÁªºO˜IkCZkÍD9FVÞHHYµ^ Ü%ËêBfµí;ÉÃD Ver[ IªJ™ ŽÖzUØ0á•0™7&Ør üƃ”Â'à¶îH#QÒä`}mssê™Ð3qjE?ÆT56†¸ãP’Õº©¤&Øœ5U ûv+÷wKH[>ªiUhK -D̶Jû‰‹Ç0TëƒÍN#¥©û=€sŸÿÚuº0œ•¶]¾í™ãÉì2%ÞÍtp0U(‡Ûš'¬Þ0‰‘2Þ¶‘Œ ØV¨@£ E 4ÂÔ8v÷õ"ÃWèX‹x#m˜JÜ$AÊVb+[k7ÌŠ‰*¨ ^`T5^lζÜl¥ª¬||—™³Ú@Y2“ä37$™Z©~a²•mÂõ2yOÍA”àkGÖ„=&[µM•’¸*³a"VΪmæVÎÂRL'ë,½´]/>¥V t:VŽÐ/µÀ3TÕÌLhl;K¯MÊ镬Å[XmMÀÌñ“REÃX×´KEš'`UµB@ª,ó4 ãW«µk±MSV£Ü긭l¸,sL÷ðSÜþçõ ÷º@%B_Ynp˜¦kq«¦Â+ÊÅ­;ËÛ ßH ú¦¼EŸBY¨{ÓדžZA¯ M½˜ô›V>­ªº=ÛðëQe5C]dab¶ºpî%ÌÍ–8«|ÂÈ"7V”nã=,}þ@G#Öª£’ZØÌÍ·=¾!GCržÃÇ-‘R˜UŒ’ ,¾/m*”ծ޶ôY‰uT‚ÅŽ“9*¸ Î'¥¾4È8sÜËé~r¦Œ¯Ù¶*J‘É€cb²Jf+ªµƒ¦©’Íœ_H• ŒÔËé0B9¾F™Ç襑”-ÏÕ¨PI½Y˜râ²¶”¬la† ˆWž•U¶g]É廡 `•â@ÏDØü•¾âdy®Ù;a‡ÂJçúåü£úŒ° ˆ¶½ÊÏô®]Gog‚ªŠ·+<²òk ¤´¶šÇZ¡U;]ÈàÝŒä\‰ma›Þɬ0[%¹ÙÂý»GwïZÊÙ9$£×׊Gv-=³J2ÄÛ~G8çµU˜²* ¾Ç +´ú ¬¯ª4xѨÈj1²&ÊuŒêÒ ¥Êrúy_»  ¹4Þ9þJ|Z*Ä+O¦Wž@GhÔ^8)Q9=äô½!ƒ™˜Ç_äìË´±»4‚”×õSÄpC Ëñ}‹1ICf$¤cÒ@v¥dé‘õõ«Œ«àÐC˜T¨v³©™ DX–R c$·Š‘L0nfëL8+1¡ILŸLI ÁY uüî~þ'ñKÙ [¸sÀÂyÃ5ª°FÕŽ0`a*8=ÐŰ’€Óqƒ›¹ŽÊ1²Í `**Lpïéüµ± ÄzaŒÊ–I­­ÚÙfBÙÛȰSK5æ¢ôBy+@–•qógBb¼€‘e™HU"@lÍ–¸Z#e(¥DÖÖªªãàc(›­,\Èîå™ù&o ¼ò 9B¹ìjñ=&µZg®» Cú˜¨‚Y9£=œ€ƒ Q(±ÒØÆ(a¢$ÛmOåýqœô²lJ0Ђ–µr°bð²mùÀH[¼ iÅ4r˜ê­8Ò{9“ÕY À¡VKÆ9ÍNW÷:Vèì”97mÙÊñc°XŒç/4åœ9™Ø©‰·…)Å•|~Á*KÏÇzÜ¿‘ )ºüz9ؽ?øŠCªn<+™ÛóÝàÉXÁFõ—€þþùÄ­˜rn€èÀFý]5MíxÂæ¨¼²ñ­Ðë¾§æ=)2%QŠÓûbëÒp¸ÉÏÕ%°šÊÁ­á|lc𳩼¬šDyš “ ó±mí•ÀóÙ)¤ô•Â;×þ\¡V¨åLÜTzb§†kjEæi68¾va¤P¢Kód…dŽ$lé“U(¨Jd1±r)… =†€òÝä”J‰'Ã0a^ÖVл±Þƶ$`UÊÌÖZ`Ä;!Þ pøèîéX6= ¦9#sº~?×HåÖ [‰ ¥D§è=„E&›gÓ*üü½ˆ„Õ#´Ê ¼Po•M`Û󮇖 h*1†Ø>ÿ+¤4’IÃ'`UÞ Õ…²ãIg¾ïÉóAæfK\>s߀7ž¹ K ¤?Á>“MoÑ!{§U!ûâÃÈæ`Õ‚LfáÓEyÊ}u g‚ïµôŒm™Àý…1™á;Këæ9g¾?fc5R÷k–æDšª¯Î®ˆX/iè›ÁŠ·åd5=³.pÛ.­ñ0ô»pbSÕ¦Jƒä »R³ñ!® Ò ¶æ¤i`ˆ­ÊOJ+B3dÙš¡”.d kç!u!û׿þeen͵(Ä”Õß ?d:ÞºóL«¥ÀœU)ë˜XǤDjZ£<­²V&4“ÅSv4Õ¯oä`È0“N4þ[ñùOYA_»dù”J·a(ñ Z1´;¡ÄgèA0,ëZ¤zÜ‘yZ‰ë’!ÆÓô%N —R®oÛc"Ô¾åž}ïU¯™BÀ 9{Ôú*um>Vj¥hèõR‚± )«ÓÙÊ6•5+ +åd!k«»¬ß¢~ýõ×^Ô¬Lâ¼R½Ìœ›)‹H Ã< ð ­Í@`æÄ1Ó#E·AæÆ¤lû…îzû£2’˜†¹ ïƺ@bÁ“’FI÷3ÁË.’Õ¢ÔFb&v¨ÀzÉiNïÿõȆg„™äœ†³¬ñLΡieUÕ+M L¬D¶G¹g‘a+,%ÏdlSrhJíêã­¶ñ1‘0+X4¼ƒlùÄô»Ž¦¶ iÕº£U[ k ˜“Lpư²nÐi­/™­T_zxÊVíÌC`5ðRôïvgÁóÔ¢Kó/oØrërºØn0…YÉ6 ¦ñTéX/Xa)d‰¶åTE 70^`ò÷K©ê¼ôL(iº%Yb¤”p™”]) ¶k¼Æg© ÐÛæ™&ÌÍ °Èά`í(9ó¬›È–¿ªæìàôÜàfÞëUHÿÆ5;‰¿ynLàÄø4VnúJqàO©W‚‚²maAÀ–¾’L¸á1€NiU[Ç1^«Ž+÷@Å™ã~:ä€Q[tWV¤8PVÐ`„î²ýñ ö–"óTk<˜9}Uò$Sˆ¯‘áÉ6Rz[§aB»ñ ù0ïg’—³ÚÜðf"a§ Ix²zÑh'ðg‚{-RÄ0RG#ˆ­üôVသ—T—æQšÐä¶}vh˜¬‹-QË>F—ÏJ_]ðjib:{dŒl&ù(ÁÛ€Á^@ êÈZ ´³Ú6UÝã'X!^w‘O…Ös†ï¯’áH«y0@Që p“2Yw¦ÈDJÐ×ß@RÚÞŠó)ðæ8ŽpQ]¯*íˆwudÇñ~~eã­†ó·…Ûþ?ºîhWã6ÂðÅ>¬a ‚í÷‚|ÝÿLmë(áS],Ù=sήd'!kYËïãŽ'0ZÆ›nD<Ì/×xï=‚,rk(²@¶ªìÈ0çôïÎpã´¤ÁÇùZž»4(ÁYèûµÄ3é'ÙdN¯=«lÉÙ TaÑ,9PŠ¬Ñ  åôxß2 ,ϘFÉ1“ÆùÄô}®&°’ÏBcƒ”è]J®Ý¿e¨DƒL¯·wŽ!PÅhi>LK¦Ió0¥ Àˆöá,ð[)L´ÀªõÚ;`5ªªÝ¨Ìì[üX)í3õ‹E Ll¢ óçì¨t–»¿ý¹µÛœŒÆ@>zótŒa‹ÉÓ yK"­‡!=‘¿^úµ{ ülÉŠ­Ñ‘R¥W5WÉ\  Št„ë=ÿÐf·÷|We$E9+i6@DRJÈô9È‚¬L¾ô1¦…òty‰¤¡¿ÚÏJx‚×$Þ%`·üa‘Ûùê¤Mˆ•|'ìOÙΓ¾{ÕB™g o72z/÷Ëhn¥d4mØn>o ç]?€l.Aëo nùÔÓ†Fw—ÌÉ:º/+ÇþŽ”(7´7䣗ƒO‡À#iòiÛH¹•ˆuå€1(™®Ë©#ü‘‚r€ U›+ Œ«É ÀP9Ù‘Œ+|ä6dîèÏo€ªµÈ–wª4œáªY\Éq^Œi%@fb ²L‘Ž™ËýÒÞAHá_šíª¢é³d?¤ZrÆ{wÆ×•’IåÈ&îѶU‚Lèkd.Î_æå•ºì£…À&y¤„lz-1nj+ØíðôÚ\Õª‚²Ç‰tu…u541Òtë¨ô†’Y¼R>ôJ®€ÇX¯Ï”y¡ÊySêRÚ OL–#ÒQ$h7]Ú+õbº¼XÎþ£*UQêç¦9ÄÈùÔ¨äØ-è9$ˆ‘12O<+m g®‘FæÉ0“ùgeŠ áll~ 8׸ëï3Õ‚õ–‰Þ–®'ÌM6š  ÝÕö±³.ŒjkÈÈÊùÈ1d)U9À´Ã­j–ЂÛ§c2˜ ¯7“JLˆ…#Ò‘ÆQ‹cÑ&1dáâ®_‹Ðôõ Ñ‹¡Ÿá4¸cO—²µ´pHAª}@IDATš7çÙ&µÃz­§«ÏÔCõ“n¥W¬% ²o Œ—ÿΤ*Œ´Fyû l¾.³øOïX{)[ äS£ÜæóÔU#f†îëH\uË7Žó¯?ÿüSí ¯Tα Ú¯a#i’2kcDX®DO62¼ àØ]Ãa%YïôáÄUazaɾpÇå;±Æµ`dA/ûr°§?¿å¾‘JmN– f—‚ëâ/·F³Ê^O CSd$ hn².ÕSû(É”š[ÆX¦¯BÇÚ“É"-€#Ъ™Ð»£ßk-ãHÖ’™ûCÝ? »²­ÒôH/ƒ!ãc f5ºÁĪ-& JUG&@[‰©KntI XUÀávæÃP8§ðÔ°J²’[´]5¶†Œ¾@‘ZK|¤ŒlÛÜd/OÓPY¥é°&ÂJøä‚¸é ²v/€Ìj€ræÄ²ï•GPE:Š}Xܶ!,´|»Ï £ŒoЕü^’’­RÓÓ ·|z¼èÒ-úc@Õb…®J¾ê>,ªbð€¸å½Øh½0g‚®¿_h#Û‡2 ³²€lJn¬Ì•UeÁ3[bA,c–ûOéyª¶O ¯=±eLIF¡ä¿‡Ö·Ñ± ªâÙÞNjI½xÕl Òäéú¦ ¼,Ù†Vr]•´ÇÀüýÆà†ôËÁÚû‹Rz½økU%¤j£w¤A*ÝÕ>ÿ‚¼vš=KL ëòd}Äl3o ¨¥[ÃJb%©«€Eb ™Ì@*j¢!æ²’0BËñ½ƒ0Ä¢ã;CÜÜ£þþ®&NôùžþïïóµÐh!Pʤ÷qlÛ6‘1×þ“2Ç7±ïX82·^ŽL³’¹˜”@C}o}C„oHßáÖ+cèay¡·Àt‘ÆyCSŒ]ö¤ÜÇÑĪ”¢vš€ol¼Œäß 2R/’y²­Ô‡hÆ82†4”]¡ÑªÝ¥öliD¶r;Ó«â—<ëâ0Î91,ªªöIvGO‘¦wë °X MŸBk¤Çàó·Û%£A0± –W´,ˆMA’¹5¥÷7Ú cƒÈ2aœ¼j§´vk(!Es‰ëÅði€¿@V×àüÞ°Œ‰þe}¤ ÛªŒÌ'²`U©AŽ î ÐàÛ|¶íì¸åa>)"‡œ1þ(‘ººf%F#²0P"Rn=>­a±¨ÄA¨jÁ#ýñÇž&ª«6 +áYëéØ$Ç4ÍàÒ ùGÔY×R˜2Àæ)•4¶d‚Ž€2[%€¾jÇJ”–ñjª€’ŒÔÛo@nSÅžàã)4ŠL0}’iª½@ äÇöÈ™ø€ÛPÆGŽ©…O»å\®E.ˆ9ˆŽ€.áÈAÖbyŒö o_¿©aÛ†å²Õ[™kfëU)»¬R¯Š©ªK´’¿––ìàA˜ÃOã(taåŽ ‚1MÈbΘÈÆáí#ºšö>‹xZÓÝ fõ>€csá^O»¡Äñ äwº’ˆL£+Ò¤M0xþÂ#`{4Œ¡ n:Ñ]rû@ñ”²#ÿ£»XoíÓDãR "óJª™9]^§yËÈî2CGX6·¨EŽ”)•Œ“ÓÃ}%Þ6ô°q°…aUq‹gÕn§$Fâ5Fë2È÷á¶ž­”º`ãâ1}ÉUã1)¹ d W•¦vþ>M‘UÛ9O&ôª‘°«…‰í/kDÒãe$ÙJª°Œ$^`DG@õ'e•¾YÈFdÛ5•h`Kjé¾ÈvÖ¢Ô2zï ÞÜœ›ë)8Ä«:Ê:"yfëˆlmJþIƒ¸;bøsnn&p&õ®ý®s¬8'h¢# —àL½Çr½0½ÍE›àÛÁ,o12ûäL`1L u Åõç–&ÿåd]„ynƵmÿ<‰<›}w˧­4ÖkVùÀÖ«‘¾ÒYî»ÞH€¬GnÄÆwëµ7‹ vŒlŸÑYå~švЂ~(tûèe‘[ùeà ì5_Üw ©—ÀÑôVÅ8¸Û}þÛž(Ï&–× ´^ËÃÞIæyÂÙ:Âõæ##ÒP&«:â'ëh ÌP6K®£$”f’ž¬^ÇHG Ó`–14"7%ØzŽºÌMÙeϤïßÓ“ ¶µøô\JiäF+útZc½J~ßÊé[©FG@&ØYµLŒÜ±d+Ò‡U•ÈXùÀù«Ek0&:®ËÑÂܪʛÂA¯Ò5;Ë/8œg½7Õâ(;‚lù÷G3c£o÷ç—3^‹FƒÒaú ÐP¥ü9·°˜òü'Ê—ÑpGr—ëWÚÆZª)Ï%îGNƒÑ’‰ ֎ɳ@jtLÀÌ6 •¶dþŽ Öø•>ƒôÞÈÂ4~µ ì=,øÐÌÐQtkž½@£Wií ˜4ÎÑnÝÑö{3 h±[G œƒ|¤ß>B•>¬¤ ^oŒ£H#Û°»«Zž­?`Ò`ºËþCÏ 'ÐKƤ·ê¨Ë‘Æ7U†1sÃf¥á/ïÏ­õêêR°'êµÃm"ãµ4¨;ÊñÈÇ>YÿQÌÇkëb“ÙG8 -[ÉQUÖ%h”šíCÖT×2+ ,T¹é…k”»#ÀËôe x-Þ ßÊç‡>Öß_R€qîŧ€óibã’É–i héš&öðº€]³k2g"jÁ‹¶"+‡µÈ4ü“émÒt ûMh×¥ PrŒƒµ»š–ôZêÍ0=%PP²"4°Æ¦ˆ‡»ˆ£v·3š?rxVަàµ`’Á®ãh(Œt_ÌÆ)5Ì)3áÆvï ê¨u™H)´T%ðm(·az¥H©TµÌ0 hCUØnòøô²Ñm%'³«u©uÍØ€¨dÖ6A¶Ûºø çÆ¼·Ú›+ã‹za]9Á¤ýã- —u‹ÆÉ>ËøG@Nư‹óÄtÜD&í0ÏJZ€ª¬|ÁlX¯2C‹éj¢*yÂx&Úí %þ´ þ¾€‰°¬Ë zsÎüÊOÚáʺxòwlbb%kº ½£à/´ÿØß‘8g¸e0ãÙÌÁОOɇ #àÈÄ a-ûÑ«QU£œ˜až÷‰P²šL “Uu} }ªæ‰¬‘¯}²¾]ønA¯*L¬Nœ@ûk¥$R–[µ[륇3i%í^èâ€Ú îÊõâ]pâ–&¦UûɢĴIæpÇöTÅ[Rð×(Ã`ŸYW;´!¾ª#LÌMãK2DŠ4Lš´ykhÏsÇ1–ñòéçÿ€©?½ÔX“ ¾šI{ ÁÈJ]Ã`‚JòëÐõñzEÎ19Èu¥çOV¾\ã°ÑB©êºÎìçkçw‡7ø® `\ÄÜØOóýi (i¬ 0‚M›Ý¨ÝΊß/2‡¾R›ÈAIèU2‚²¹Ú«ÒŽgä_ Ùô”UéÅÕžÏÔÎöìoíðÌ3¤¬w> Ò—D#¿s5fž¬/†¯2ÏrOºUkqœæn÷?þÊ®oqJÌw£…A|ÕëØE`2V=  xZF‰Ì1“ZäåIãh«Ö€ª¼}€Ú·H }¶€}Ø*á“e‹ŒÉd]ªZ^q+á9t7j=+?Õxo¨£D¼5teØh¥<å4ziT·„Ì 0"\W¥u¬Ž…¹ï(ó7`‚É* ¬š –¶…â>DŸ Læ» €ó}WõzœJH?þªæIß±®Úµ8 dHÀD¹@ [€ØL„£Üž4—ûüžÏ4•à b`zÑÄ>5X»,´‚Ü`À-ø šuì®Þ}ñÝ´RšMwä&2¡é(ówÌ'™Œ,ZŒÌÂdn2Ç7w̤e(í†)ØÂåv JÛŽ$k ;Î OзÈozû7RAÆqkÄç‹}Èj¹ßÓÏ¿#ËܧC©Ú÷-%ÓñÛãØ8¶-CƒQbŸ¿?š½¶#¥O2š0½#‹6Ä1dÂÇôiäJeG»µ0¥#qáRŽJ"ÆqãºÑô@†^fxšÈ™ól>HY»gá&0rU>ÞGµÞ¦À #Lq Îzý ðQj [|z@°Ò4W~•>‘vXËvÖóä`b‹åc"½÷t/ Оš¬q1ŽA$ÐÎx¡W£ê(w…H¸ +h0pn%,ð°è;ìϺ]/'¶¶ì.õk òJ>éÏ?x¾´Í”3ÍÎßµñ½2¦1eäx]¢c½Ä˜>ã{Á“”hòÉ<Üw4Ez8ry;HSñgûÜJ ¯i°R<Üs+yq¹¹–ÍE¦çÙíl¥qÎdÇôøLÚÁŸ¾º´ÈS²5šxƒT‘E²cÐkšîk”ø4¿Óӓш6‰‡E ¼J8±RÓ-éØÅ½d%Y©õTaž®ì´R²FÐøFt©Ö¨¤*Þ–†Ò0ï3J WK½˜€O*¾‚¾~@W(³òåosþlMt/U$Ü8Ç~Å ­¥õd½éUE/LtDÂe ’%MQzd×Ù>Z¼ªvÀA[µC#Â4Jr>€0NUÙ"˜Ë¹ÒÕ±Puìåxßò5êM,×(GšÐ{^ïì=iZ¯+4‚Æ¥t‘ñ ÷JB—?˜ø¢^¬1n1|ØŠH°l1ß¶4»ûyaôöÑXîG¸.b%ØÚµóŸ@oA@)Te£Ë •úßQCº ÿÛšZL)˜ ûPæ×"܈à úö¯¢FG}±;v5¼#ÈAn¼MÈb0boÓçg$7%†aÕ=¬Çר„Ì0àî}ÊJÞʽÚÇD¼Laú°¬TXµm)HÖrʺ²‚·$½º”€dH£õÚ'¬ÚÎü!óÑÕ‘€L82œ³ßÐJÄdEX.µ8Ë_áùŸJ[¨…¿±lG¼Ü¶na:FIDÆd¨évŠ‘Ž9+Ÿõ"9Û§kè‚•úþ`Tið-†±pƒ(ñ§/+ÑÐÃ@áûÓwÉQ—\µ%G|C{ L‘?CâvÀ›"*ªrîG¯£ŒÆéÚß7D»®<ÃJ]JÞ”&ÄÈ”°W‚kIm¾»œe4Êu9Ò‹L®ý—¸R™'±/F¶­¡Ô¬Wé¾ÂÝ·³^¼XËJ‘¦Ð«Æ'3®£qÙj©´‹8ÆDL^¾ÏTU0‘U2¸‰á·;{ÿž]©öº˜èê²F8‘íîÈ~Çð˜4kšhš2²å‰Ãަ˜+àÌ+éâ |:ª•Ú<7J›#SϳÆ~Á"ÏÿPFµ½Ç,`¡µèV§ÿ^¾.î4+”•ìÚ1‡°,0ºR;6N(wáª[,O¤  ¼ ΰû²'™Ì’¼§ðp~ã`¥ tÁÂt¼è¡êhÏ6—…^GíÞ$n%ù0ZΤvš5bÈè1‚'%m÷RÅËÈ" €9cì +.³” U@ /`o"k àë-ã9ŒÌ)äªíP6¾•`š³ßïúç²"TfÕË”•ÚÒo7>¶y" "l:½Ðž +éêÏNYà‘€vØÓŽi«v>¾LÓëM,Svä¹­âÓØ0 —l˜X hùÚYáE|²¹çB¶Æ3 <ÆÅæ27   4¢­|!5’9³ªÅñZ~<›…\Ô54‰ðfá ³¶¤vÇ[]yÆÈ/WÊ?Ÿôl&®¼*²Aeí ¥µË‹u·ÃpCû¥¡¤1ŸÝ Ç3Ô%;rPôýoç-|ÊUÉhÛ¶òQ4B£ìHV´ÐÈo¢ö+íK¨êŸ‘Ú¯§¬±wÓ˜'¥R†1p¶éa-L #`—ò-’M©dçl²Åkdâ= T#܆MÿHï¬Ä/Ï<Á«fiÀ¹‰6ð9ghš6l+w1",‡SFº;L›4×ѬƑ‰ZÞAœ˔݂^ÄhlbU™cšÜºr>•Ëwþç…›ˆ­ ÓÈH«ž ¾ÿbØ÷‡¦Å¶gzG|>2RWæ©17Õ¾0«æÖ2º€^,}ü[ÅsοµøÁTÊ¡5#Ò+õ[´j?½X;P6´tat9n¨^øÿ‹öÜô­Ý7J+¸væð~|ñ½gû×›s‚Éê’÷nùï☽3^¤ÑU£oC¤# ô’9/¿Ÿ—ZØ&Ðc€¦¬=^ (6«®Ž} ýÈg"›ÕÓMɶÃîcUrÔÒn¾ls®Ôn²#q¹aÚÐu8¼ÏÒ J ¼qÝë%aa4 @ ·ï<¯)6Dú‚·ŒéÜÚ-¥ªhÄq¼R“qÞ’UuTè^¿þõ¯Ayin6Œìi0Æ1£h0¦ «Ñ`ÛŽp«7˜††M~ýj ð†ž›ÐòCà(ðkICŒo.¦õ¼e6iG‘8·|fNÀD$P¥qÓMqTí(;Ê&¦q,|Àýœsà‰Ì ÷€ÍêD]]‡•cæ5šH,EzJ¶Û§. Œ—»{úv€í–[28Ð -õ"Y™B€l–c¡ PâcÜ«o6€ì/9”Éøp 4´måüe|žùÄ”yÊÂd<ý3(èUaá©ûP`Êlki(qs[@¦ÄDR—û}ãÙöPJk$ àÌŠ¹L/`ËmN€‘û"ÁuÝÉçÇGÀ9$¾ÆÇ`BC«âEzS"e$=±Æ2þê#•hDÛ²ÅÀ2>²#H–&Mâz"Yt)]5î)ȸɯCþº¼^_†6tôn]SA/¡>{Ü‘«r>k}=V•ñlNÉ9“|ZI£502²ðA·‡k®P;s·h"2¯q¶ø@âáñZº†£ÑÂ?xø~²âŸ³Rs­G\ FØP&PÂÃM:6…-~Õ˜éÛeàâÓ·^£óW´ xÂkô |f4´R]0}/ІÍRm;º€€¦–vÀ°‚üô0ÒQ´Cæ.ÈVðרÜ@¶¦h9°m“F« %>éùH™UL&²¹²j¿îÂrCñm˜’Õ߃¦PêŽ@îb®vß1žÉœ I#€¢=ŠáLÄtµMŒç£T×Ä”b†m’›LOih¯í(¸)ù¶·˜£Dì©1²ã d÷Ÿ?#r Ãëu„É`—#åÙGtemˆ4nqVødóÇb Þ…cŸ«˜x&H Ð‹GÖŒÁ# -5öÎ~94)`2%²‚9žƒeŒVÅï"ßáŸeÈ8½ß¶é Þ¨%åôz°’‰»2fJU½¾•Èô’‰4l1J2¥\;½R¯Ñh¼.ø}G$†’¡vŒ`…0&4^‹ÏÅ ip†Çrž@Qµ­š‚§1eíð÷îB ^#¾5”†€*« 2$™`WåC™ ¾¿–Uâ£]U{oVb"·pCóÑ.låñc 11ж2ö%A³0¹e®…‰ÜP—€aËÈŽa&z…£ÐDÐP$†CA¯”~]€X)à^MÔ¨Ú>Þ°)íÓg× ¶ƒ^]Ž–éEËÐc ")º5²ñÜ΀,1LSoùÜá†ãËÔ…±lOØ,Á‡¹¬!œÃÝ­ÏË+Í!}šeUL[÷Åsìhðý–dkº¼övãœ97ád™cŽú.χ |¡4W–¹ç‹$öÈÃ|Ȉyf¢„Ää,€­`&ªa%¨ Dº;&O >óù‘ LLˆæŽ÷’•Ò4PªÖâ ý{b]ÂbÏ.ãÉèa¡K‹ Ë*~™²äô2R óJ)ÛDÕÑЪùk Í'žžÒ1gCC,ã¸Ý”-Ü8YIo&p|·FŠÜVjèÚ×ëR4ÄzUÂï‘b†€•„ª¨š›FÕîøê}(cê¥ÔH™¸ÆæîKÂS£®6L<¥öñH¶í@ß¶&f¥±ÿÓm•zJ¥®³ÝðªÂõÃFèôÈœÓX覉OÏýSXWËçŒlC &73ÇãþýåÙùȽ¨1,[€aWŽ$HÏ @Ê Ú™ÀkT²°£+±ËAny Ï˜ÎŽ¥jž@Ë,ob2-@›×®EÜ7øý»¢RÏs‹‘3ÔÒƒ÷#IЭñ4r ì4Âh¡ŠÑæ©Ëqïù:´F-²ßðû0ž2™†É‚ ¨Å±èÈÄ‘uqØeÉú VTÛÍ8-_Ëó?1¶êÊSvߦ4·…‰Sö‹ÝQKnÄ”À‹ZýëŸÿü§sj /%i"|’¶”`Á¿1Ä[]ɱÌ\ ÐÕ£lPíx¯Ó\¹0H5àÀ™Ò\@`^œ¦Òº’9š+÷Žù+eÕ­=e?`<¹ ߟ“kz Ã̳Âl4Ìܱq¬ª”v©##@*sËÓQ˜®Ú’5¶\$ƒè- Œ,ïj²AÐ^Àn4ȃ Uô {ÌG#™Ø2ú^É_d•0ýº÷ïctղϴÆdþ4€`Ò”6œ’ælóý¥ä‰Oã÷£Æ®$è^â4ß×nàŽ@¥¦ëE6(¦j¯šOC†ÔÈÊò˜{‰p´€œq-¦cRn CРéËÙ2ùèÝ‘ ‡¬â1”˜¶­ °ðQ­Ñ§Ï )2|M&x­òŒyqíZn®&ó+©Š÷éh²²ܧiD®]>ókóùÃÒ pH)sp;À÷PÞ’zkÄÀ›Pr4®)ÈVj=<€Ôˆñ9¨j¯Ú™`;Ã}-é•r“­Šp+QúiâosÊ~|úb(aÈ*ÑàŠÔ¥Ú‘o”v€ ¨ZoÏ„Øx&dŽL0Æ”­À€R²HG>æ@Ów™Rcà½H½2+A ( $Pj™¦§IO°Þq ä((­¤w—«¶“|²•éiT[c©ªÑ ×[#™+ûG>/¿ÒfÅÈ)èµÇ´j|Lk´ƒì3jn²þv˜LU©1OYÉ<}SJáØ§Èy"û¹ &2¦YŽÂ‘¹¨QIгbÂkØsUb¥”2¬%+¹v$Ø&ü·Ûûyó4L1®FÇü›î¨ ÏãØ7“§£à#ð‚L¤WŠ©Zéª~&¥WãØæF°’ë•óT=#¿C9*õ[Ëž€.?ήOæ÷†¬Ånëù~˜Ž¹qál7}$&+Ÿ€éYXÁË•ôÒ´ÐDJ%¸)¶¿jJ@‘C&˜ue…Çøñ1ã“åi–gQb‹l[Ì×ò˜ 1e2¸Íkl 7€CS¶-X  '€i`L7ðdVÝ>&Lí4a€FÔ"³’S6‚>MÇZZÐ 2X,³jOü6ÄŸÿj¦ª±SMÂcð4×ù3ÉÙ0ЀËï‹ø€9$•˜ÓÈÙ`¥6kq #z­Úgܳj+ÑDV"˜’à Ðè(®ü$ ‡ åÖà“#2Ñ¥ŠoŠ k\;¦/¨˜RI ë8hgè¹|­U)ûŠ»¬Þ¦+ýÌ·9Ã6o‚í·°R¸‰Üj‰±†A†Âºd>¶L2F£*l²Û9Ö¸¹Lº2žÒ/)  ``ŒÐõFcZ¦¹²RûŸ îÇW;¬ªEUÖ(Éî…ôG¯Í«–éñ>€ÌH2ÏÜ çP ÒQÍ´›Tr w”3´“¶…i¶¡A°¬·zÑ%¼UÎøªñ‰9ˆ> ÿÀšÑp=Iõx=ð–³w¥mSU{VéU1b혂'·6Ãh‡»cÕ<«Â7  Ù:V’×…„eúF8ê•ÃûxŠM!Èä6}~^Û¶í46…˜CæÄ)Éø†ÒÃJµ4®ä<ë"ÃPf˜?ŒÙº¾Ðå˜mSZžxúá–!˜R£#@æ6œmGQ°’ìÐm›@{‘‰’õè™×¢‹Ùt2&pú×dŒ^]LÚVÚ•‘ñLDþi8+™+ í‰ôöãš)¸­× Ä@$†žL; €Hp,LÔ÷ ˜¬®V‚ýà À)òAÈö‡®ÐJ<oX hIYµzéÝÈVj!+ˆ[@VuŒï(rX F2éø£ô’J¦Û<kãFIÀ]Ÿ!‚³Ü V5¶ qÇ”}y‰{JŸþû˜L´ ¤ì0·Þ|4âá.¨Ú›Ïßh‚í“¡£àÙ:æoÑ8&áL`AÀGA `(iЦPîH&hêÅ·âô˜ðŽM¿3Ï“rÐØ]° »~]iÈ[ †Uß@4(+ÉHLëUŠ‘‘" `ºŒïúÄÝ‘@(­OL†¯ËÇä—ÕÞÍní©Kµ—jÛá֣ѳÊöÏáÚ­$ü~ãÜ\ýSJ]ªÈò|ÿ“3‡wb2%@ð´³£GÀá²v?`JƒÒ—çÔœi´ˆ· ßîÏOÁéü~¾M‘ d‘ÕÏ^‹L@öÃÁQK%YtÄ‹ÖÛ2}”𕜤¥ÄðbU%œ£¬E†¹Íîëê»Ý‡˜O/ Ä™·Ø»3\=L&`›\¿³é[äÓ­„ÙDzS0Ä]/=Ÿü1gÆâ«XI»ë¬¤Jüc[æBÉÐÚ3l·ze>læ°¡­Ú8>ŽJ€–ã{ß¹¯n-|ji"’2†¸Þ hD<Ð2ù”Ïç*:ëœÖéXI¦ì9^þ|~yeµyÝ™ƒ€]’@ ÏÔï¿ Ï“,Ьvxm»[U=¨Ï8#pæÝÏFd¼Üw úFX‰LuâdQ{‚ÖÓeU%>˜g&‰ëÚM‘µä/û·]ÚyZú¤‚mCe__²f5´Aõªº žÜ_ù¿›o1<Ãí¯E‰fz`ík¤íÖ½è2>} Ã#éa-þQöøÈh™2ž4×àóUìØ­»EHÜ”Ö 3zb ¿ó'‹oD]²…ñ9Ã]Ó1AW«QÔÒæ>¤®¶ÚËp USV’2Á‹Ù2q/úÝ ™xŸö©)TeVÚi´W"v‹Ó,€ÙV@âñÈä•ÕÅ¤Æ hr ¡1)+…›’¦¹x‚0m—"ë^õ–1dJB—+w”ýŸÕ§Á÷>{¥~ „–ynmd]JMÉ–¾#Ð8ÇH-}])ë"¯&3E^M?³€’^{ªÂöÜ -œEßóVÕ’ÒQd‹´‰0nds#á6)w4Ë\?/xSøügkúÆ%vD’Û\‹®àe‚Â>ô½?F•ò4|WŠiíoÓ¹¾@: -í[›é¹m@£?7ÌpL&•d×o„ìXð7ã ÙÂ98ö8Í’ñ6ÚŠƒ#ý–ìÝðHí@]xJ2;Ç‚f•‰Uk'p„ †=eGضß_›Ý¥eàEìH©±àœÕ­esÉð2è Ú5[CÕÚF$®±gÌÙ ¿«õdÚŽÌ{z|ú&†eÇUá¦$®ÔíxözÄõÒdÕJH/FâÝN¨ÒUaUb`ŒÍw;¥Æ$£¡<Å;¹# ôjÙ,âv¾H4>5Àea;À“ÝŽOÒøºuTËß2RæÀGÐϪƒOãYjœCb½~×%¾W<)^‘¿ ãÛ–F;,”û…iŠoˆìŽxw4]#£)­o‡ªžÔÜI÷¯&›ÑSªêÉŽLt¬Ë‘Þh'&#á^³U0”>3$ÌDZ®nèH,«6H“áÉóì-G†J/†ºÙÆì8±)S"ã‘â51]x¥v€Ù¶CeL‹Å—é•è=8sš`€¾AU_«µ·ÿÿýssЛa#²ÂWBbŠzñù)òp—ÈæÒ0v㬷ýé•ÚPJcI¥ªm¿ê64¨ŸUnºVudÅ¡¹€`Õ‘Ò^8ZÀïLZµõhúÑ÷ÁD J]Mì(+ái¶ ¾PÍÜ‘,q£Í˜+0‚ÆÚ1”µ8rpôÚýï}6îtÞ’ê^²[kDºHß"âÅûJuµCk[ C¤ÇoL]@ûÔ²<àÝ.ÈRï9hyØ5-hIVo8· f²*†Uo…l™HGù^nO@l½Z:¶OËtS9Òæ¦džg%Y/g¥¾ím«„o1Ù±¡ïhËwd>Z^Y&톯Ioh]x#’Í¡ýß^‹uiVZ•¹¸£N¢ªHí=à•œ/C¼#,çÔØ­u‰J(ÑÔàϘûÕj ->qÙÅÓ8úè]Y£M4ã_7ÇleòªÚa¤Þd•Z³Aº=/¦’TÅD¶Üæ5Êd¬ðæÂ† Œ/0¾ÓÎÜH&H]ŽJÖHkÉ­œ¹Ü¶MIÉ¤ð€™¤Aåøº0Ʊ­k†€ha%‚ij·g›·ž#Ì–&."úÉõÃR#Aæ@r¤ÜDôa@»äçÕÚƒZ nƒfðBR˰U„câ&)9‰ázÛ ¦¥ëˆ4º`s 8 Ô";’%ÈS¯ßþRJöN‡Û“axºÆÄ£¶Ò(¥WÝecZ#RUà;êꈷ®ÑhÕ·kíu) âÆ‹K~ Ò±’»'8Ò牌K_¦oÉRO=ó]¿‡"hÙ‹õY4(Ÿ}Rô3!P•7´sÁ¤•üù÷Aô·ä>ÁüŠ­Ç_»Ò÷M¯)­AÓT =¦qéy¶AU%ùZ0@Ëœ1ýàøïM½R¼#ØžF„•4ö†¬Ä i+b¥¶ªc«ÀHf¶ã)óшVj]˜ÄË=>OãØP2À”˜åwboŽÑ»AýÄÍÊ¢hǽa¶ /ŒSÕ ˆfõ1Q&ðªÜ¼@b%-œŒ@ .´ÔoO%|À9s‚¬dÐ-~þâ’•,TEV@å[ù|—Ú-®‘Ìt›ïP‚æâ)aš3ìù{[ïƒé¦Zü4ÁV¬q-Ó†² Vb tŒ¡µ›øþ`f%_ƒOÒÕ“âázÙVæP—# ÚQÆ8Ê}ôLbZIIL\/AÛd3IF‡-l+<±@Â"}írn²j†uÉ ¥ÖÆlóÄŽÛǼøJ úÄ+‘½CµÐ´\I/LY©¶H¥Vm%¸Aª™p¨0Ö%Z™l+&JH½~Q7(ñé¹KVíÇ¡*ådªWxRkódñÄñr;à Ò“õ,2R6 éÔû=Ì)ZR©‰l‘97_L¨*;Ö®K{¼_MçÏ!Ï] Ö€g:ìÉ”Rµ4@8“VáSIKÿ$ª%sy877·™öB# ÏÉòÇÀ<á.öd½ˆLPû|€EUG³b›Ð 7(’, ¯½ÞÄf¸gQ'^¸)±¨Qó„ |id-½²~CÑô&{™¾4õj¤¼ÓN¯Rx—ʶLièYèþÉ ãÙjé­^ÀŸLÓð·p÷J¦Ú,VSèEjÉÊoðþKPȲZ0Üú`ÎP )7+A¤^ËèÕ%Ü‹LU  á^† èjïhG|â>ˆ2&~>Ü`Î^Ðów¤/·6 ˆx]×>/pÍ>=œO.MVCUÓÑ® à·özŽðz}T²Ú†ªùÈ[γ­hDL2|‘Ò¥€d²ÒŽpWŽÏ'}2ÊÅzÇ L Å‚[ãÛé²>ŽôµbwÙ3z1$}&ù0ñ€ôø e]׿$̆ȶÇO©Ä¤gƒDV4-¯ª«Æ2[U;²–l·¦­+ç|0ˆÔզƋY T2hãêmzÇv³ùF7«q àÞ¹È4;§ÏMF:š"[ xoZËz `ûÇP½=>+¹TJœFVÂ- í2O%ᨤw¯„$ȰYJøL5G&-OÖcû9%¦ÁˆíÂõ=8žÆ%â$&Žl;õF½gþŽ‘ ¾1a®öø42¾¿LvµŸ_üf›7‚ Å\Ùo°UdÝBîµÉ²ëu)&Èž¥Å|ud%Yd%³¥Ô˜óJ@?‡ï’§óûœa]dÍrl$Ûª²hd-ÜðV‚ ]Ù‘8Óu, x?ŸÝ´)ez¯ÝP‹éEòq4H‚ž,\ɑҬ"O‚¹i¹=µ 7N)®€¶•+¨êªtö¾ßVÝ‘Užñ³ÊgÓ´‰ é²?ªŽl ’5ÚCßý@9æICÀJn™ Ûœ&Ã3õš,+1)dÂQ^×åΫ YIÀEY#‡oñó³à˜L®”7âöÇœ÷¿„CÖ˨¦ì^pú.ë}Ã>,˜@4޲qËJë4Ù{-†ÙJ02C …A4ý ÔŸUŽ”²È97ÙníUåî ¤qô}sì·1’Þ’•0c%q/ñùR5·Éç3e˸밪ØÕÞg¤tóχ>óªŽÛ&¯,œ q|†ƒp/™L$³-2qžñºnáh=ÇZ´‡ FRž÷‘v}‚^2ïŸ ©±ŒÉ2ÙÎJ>;Õx‚4÷™?Û¶Þõ8Q#Ë6âzÉãgØtµª «òOÉsë5OÃ`Jôµ¨"[»ÿtOÀVt‘°L,_³ã?Yf)!ù¸Ʊëy&Hƒ±61RvHÓ‘?f¤£ÞÍ0LV{¹v#h쓉RVdûŽ£‰³D¥Þ8 ÀªÇy6.A¼F-gü3w˜‰)28ã¿¿aAÏG˜y+ɾMé)à"%ßY•9RppžM7·ãU}þêBìØ&9“µ§#¬W#>M›E K°ÿ4{] lP|¤.Á Èd}·]aŒ5h$ú‰yy¸Y”"#ÂŽíI#`¹Ñ=ڻɕüþÂpV퇔›êðF¬M¼ˆï¨”ØPze~¸ MüõïÿÛ–£’â-é®äª”x¾xƒ„‘¢ûã÷-¡Ï0sÇS*á‘Y¹?†¡Yµ ùæa&>0Œcñ­4ÛJÈøiË sÀ;¦ÜñVÎ#ÌÁˆ®0*R.ð@z¹è”\v x]ÀÞ^{¯)0útð¦iU²°¼}séåxLnÚÅÈŽLj1È“yÊ4åÖH&ç¨öyéõ“Œ/rC š¦pVí¯P1vc"êJ©”R¯»DÊ4+Á­ªˆd™ØílpߪwN#È ‚ )‘§øÓ¨Ò)† s®šXLöª«ße­AßÛª«5ö’umtS&ØD<’H¼ *‰V¢‡ek#;´yíÖ5wßdŽ@&göWS‰Ÿ9Þ•}gjÄo>Äñûn׫‘[ËÛDZwÀJ6¬ kÄwì Ì®Lœ AkgÒq56”Æ¿þøãj+#ë/Çë4FÉQ¿PM d]¦ÁÐô=@ÂÚ#UaŒKÂ4ps$>k}0”ÂJ¢«®¸ˆOSƈU¶-W¾õvȬ§K©Oã¸Fxz$Ù& {ó–róE¤Ñ€v@:Ê}¬D,em²AÄ0±€?‡fµÀô}?=uw—gÕ•’ù1Sbkjž­—øÝ“†2?]€ºZ,ÏLzyŒÅT)…½#`n£a äPo¼RUe>Ä4ÄažÇëFkË‚>†OA¥ éë*7ˆ—15Ò×;²FL-•æ ˜’L0´-¾’ª€µ+5@æ %\õö}þsóºTõ&–á^#e˜‰£O Á_‹L sKÓQ;Räùsf¨$_ío=·‹Æ^Þ8圞l_{ÀÑVdr¿[¶dsµˆ°o2eGæHííì¨Ú¥¼gX•F´<жUY‰Zx*U%ãP ¥¦P¯k21°õºWí¯s›¬kû¬×­á÷î|0ZêUÊom¿1ð¨KÓö¯])[ë•ÛGv”s«¾`šZÞö°¹5‚ÆŸC½­ŠtÜÂMĬWisñ‹§ï9̇¡0¨пªp,ªR2—{ 8O@P÷NAb¸ù¯™xpG&ùèj®ÆÈº` œLoærï_©–ª07Ù ”Û-F6”҈𾥔ۄ@¯ IÜèÜ0€Ñô@bÊÈ1Úû }"™hÔ¢„ÏÊJ°ðÓ'è'ÉYfÛ8@´X™‰PÝû„‘-é(üfh^c$°ÈDK2%£ªaG¸YõâëuØža]ýjÂäÔÈ ®W)rícÒðh ¥ªÄ=Îy£ï+­ª‘~ÇZ0”°ªèoH˜›/mb†nîÚÉTÖ[Õ•™k gÒ70`üµ?Ñ÷ßÎÇ|ð”}¦ÝNWâ¦ä£%M€çz uŽ”ÉÊ”Z)AÇÖëË©E`j “ íÆáŬ¤—‰åyaš˜z…[Ï-ñ49´•ŒÏ¿¬š`únúëÿøÇ¾…¬÷ñ¤Ölª,ê´–’#>ÜSFzqå¿ÿ‘«ÞÈÖÒKæ’2Æÿ¶™Ñ‚Uã¸íªHAÖ×®m‰Û![9YÓ·|ãä@-»‘#¥ÈŽe2³öI˜ˆ/ÒÔcz>2Ü]”æÌ$+¶\*¬ºO½ÆzYQÚ ×k ²AUêd²hájwÔˆw4E¯m‘y¦oÒ‘À&KÙnJ UÁ¡MÈ´%ØÜ4H`¹e½̾j²Žx/ û Ȉ«¦tÁ¦Èñôž]¶ P²’ê«l"²ÏHI8¶Õĵ#“9*Ùçø~‚0‘ƒ¹·rp ÃÌc–•„Þ^¬×ø¦Œ,&è­ð½ƒ­¼@&|ðmÂ!ÌÄn)½$Ì9ýÞ&óÄ4€*R ,ƒ4« e ´*Û0}?GÀ.À‰²¹}v•U†¬»8&3Zt,´×›e,_WGšøù àaÁÁÿ$ {Ázý«¸9ʬúe¨«dµk‹F§á@†œ)ûŒTn'÷¯`ðôJ>\ã±¹”p ,J£«‰‰‘ކv0—¶'²^Ç‚R¼ ©nÀXoþ-IVÜ5?¿ÇˆSª€ŒWÙ:jWrlI Ãd²ãÈJÖë:Uå×¼=Í"æßš½@¼£HÆŸC)Öˆtœ nÛL4*érÌÓÄvÎg;äL hñ†daäÛˆŒÏØw#ÏJ‰ñ¦{JŽ€@ÊŽµkj\{—w ß@¿os“ùçÓ—§+÷cÒË45î)úNêª1¾¹ü‘ÈVÕ[{G†4GAÖ¥Ò+5)&£ÌdVc´´d¶¬`_nçÛzĦÌ<¾.åXËk‹|ýg¸‘G0ˆ@ œU£åþÉÈøõÁ †6ììÌsÆ´˜ªhãÒ·g )WûùõÇD·ƒ*OÇ bBÀ_Vò8ýo¡ÁÆÅ¯«oBG˜ YÿŽX0QÝ¢¹í ©Ž„_ 1ÆðïnaU@‰’I>ŽEΑ0 ~CêÉ:¶¶lb ¦yܱe\?1°‡Â´›÷Iï(Œ3… Y‰R¤)w¤]-¯Çç% `ÚÙ1}7}ï{ŽU>ZX!sÀ¨ŠMÇÓ¿ÌÄ”Gܱmñ uY la2˜ƒoZÿú&À—…£`¢…ÒwlžÀ±÷zÏî"[ F†”Ž€( úh`<Í­Ÿ?S­äØòª•šxúþF˜ô—E½ùV|q¬Ö•rþ6o>Ÿé1œ§ª‹LÓ-0zO¥œÌ%Û;¨b˜gÒ\xù¦àE›wS(a>B5+ Á R¶ž»dUË;+¼€+ÉZ‡gîÓñ¼˜Ž>þ^†òtÞ=Û/0ÛÐQ£ªe4Bc·gþô¼eð¦ÀÉÎ¤ï›ØGuWÛn@ålkq|Mœ‰ %$`\½Fô;ÉJß½à7ð™{ш½Ý£…'ÞÐv[& iq¤‘»¦#·ý{^&1ìmõ˜ƒ’È!Й’€r óìÙô2 ðnu]?¿$ÍÍY{üºaŸÌJÐËŽ[/™cUIW-U¹éšg¤<¦«aæµá 1EÕuµùµ æéÛ¹‹Ä( ¼lŠ’h"ÖîÐcûl:0óÞß狌W*8˜²— ¸aFÖÂĈVÒ[¨¥¿/µ¦  ™”×’˜>[ÌZ8˜¨KÀ"Ÿº`™8¬úéÓ–…j0±ÐnÖ¾êé9´€L£«õnÇù¤Äõû\y«Wò‘UŠ1]£|þ—€5´%ʤ) Ë‘NÄcv7Lã«Âi"ÝA´M>és Ñ%ÍÐ\ßãr>mBÓЬ’5—!^Æ·’ÆJ2²¯…’,ý["6‹?2M-?²Þ4ø–)k6ÑbŸñ÷82×¢–}›{.$ w—²¦x¶°ŒÁ@(åœ/(= Œªbƒð wd(hDƒ€Hz2¤cƒím „w2]0Æ`âˬ0»µãÖÞ‡®”§F%Ú[é\òûum=ÕÚ È íxÌlñdÂÆlç†q¬K ŒyAJL À7‚ „‰bU%ßùÜ•´•´ÈÚñ=/0ü‘aVgêóG#œ¦Ø Œ£HÙ?ÒÑ %sSâ|ZÆQPþÐwL¯*îÏÓÅ/i²r,Fº¯’§ØÇ4ÖÀSŽÁ÷>éa¨jß"_IN¬päfÏÜ´ˆî^¯£CQ‹ìçÈ£i¯ÑÑ’ºhkažL5“1¦—G7‚ƒªoi;l.¾‰øºÊÄ7ƒº`WpZ Í“L¤§Q[ /´L×{û΃Wí™1]Ó±jí¬þ4âz0NèªeÇ0½'ÜV²j-ªŽ¹!Sb<’ùÜb-ãâÝR(åÀ¤‹á7¢¡ƒÓ;Âa½0z½ù4ÂD@¤Ì\{$OOêcDß^À>”za‚îÕ Žâ1Ùø~ËùrãVô Ì‘m¯·Çq7Øv¬ fµ5º—lçöáï(w‹ÚnÄ £4†ƒRk÷Ï'°@Òh¦‡åJr&ªðU}¾¢9›"”Û„îˆåü;Ú§ËN9Y]ͪ*7©*; ‰¥lñ9MïV•[YÍÙ¸x{On3¡ù—5 ¸ÐXhÁÀªë Ÿ†ûç»o©YZƇKïôÕ%¸ò“”ä–¡çï#ðï}Ù†¸¡ù`ˆ×P¢I<··Ž©ÅÀ‚ªe˜È‚F “@½•ðdºrh%G¼%]@>ŽùÄÈdý¹C`þ·­;X’¬F–0¼¨ðš˜ Ͻù¤?ÓëL1±Ð y¸{„tNfU÷·/s8+Z‰µ„\XI¢c½¬ŽC²Ó}i—5¾j¡¶ Ìsxcif­M¾H¶òúíf[w#¶"_Im$ä„ðç?éØÍÒrÎ?UäMÙ$ÀîÅV©ÕÙrˆ“P4yó<­0UÇG{æøÅÀkvø>„áZdNómpN-lDÛV „UnŽÖÖ=¬Ý Á÷ÏGádÎM’¼$ÛÓÊ$°×¨F$.­ÖrM­J=ýF¥J“d:L*Ñ ³%9Oô~q«"{©"³’³RUbHÕœ}6àäýW·ââ Br’æD“ÀÑŸËz}›ÐJÂAh ‚IÞ`r¥^{ œ•D#AJ"Jj'癡ŸÊ*‰íU¼Îzå3mIMm#LÈY¨úΪ„c6¸ÆVe.$\U¥’•ŽÝû µŽl«"+i¡T5f+° ­Í¿ÃÚ~ño‹@NØÖº¤gú{“ÿî5d}’tö~¹q|ˆRU‰ïœ®ˆJ4[UžÍìoÙ%ö>äf½¿»H¬|z åTZp¦‚—çßxÙÒÊÏw|3˳Mb+ÀFj~[óÀ5‚'ì©AàܸíoƮݜͯ„Ù‰lçƒ#×BUÔ«C‘´•¸jLÂ&”ØÂy†f–<[«Î™y’`h ½ø´•¬ Oëo÷U%;‚­°¥ar®‘ØÖø›œ9Ð L’¿<ç΂³CÁͦ P¢‹ßžZ¤²MÕå„‡È —óäæìTB §vª|¥šÚòÇQ’ˆ€”s«$yÒ.÷%Œ°I” õÕE¢£È3¼Ù4JåÔN‡s›Ÿ 94þÀò´º8£©!ÏRüäåÜ f3XBg±Nˆ/"X©¤^…¼jù½òϧ‰éD‚Ӝޫä˜$Ü´‹&éLˆªUÞ ¶1+Ùò”[{WëÿᇀüMØÍ V‚J„ @¯ÕV‰Vb˜Ð<Æ*•èn[>!²B:ŽFFЦ;$>‚¤*‚È“-ЊŸ‰¼:áÑäq¢åÖ¹*¾îr¥fØqZEGè®0!VB>!‡äµð"¤M®‚)äÂUU?qB2ÏßZä©‘ŽâªÏ;P‚£»‘àÌg9¦cjz4ï_/àÆkNü®?-\´2DŽ©‘§G¨Ê¼mÕ’?'g›3·ÎHˆÀÄšB +ˆ•JÈBRnÅAΧ±RI*ÙVÚYžD Y"’×xó;ì´­/-²\Rk Ÿ!rˆ€Z‹¦’³-0%p \PA¬ò8ªÇëF„rcð!ø5Ê¡ÜÚ¶*æ8‚gÿ½Hµcæ‰0¾1r¨$‡ “ï6U;Ž.mq$¢Ç¯¸I´&L‚¹‘k¤*YD®/«^ ØT¶·íYø”KÊ )€¦ñL#4%&¢$rCªâ@"<ùù •è’$9~Î$òÚAЬ$Êã[‹3îû‹’\¼I$ &ËYÙvWç?jCÖ§1R[Œu­Sm€ÏVd ¤… g •@$µèI°VjŸv„]7~í@Î\µ¾„üüåB¾›:3=ž¢\•¶¨9¤Kk~¶B¾->B]€—~ƾ”óEâÒDf´$¦BVµÒ®TÓœ­Îs†nOè®$mùȹ%׈vΕ;Bˆ Þ`ñÅÿ7YUÒ0¬*e~F¼G€s@C– ?n=”ªrs’Äá Gvj NÕ´8ÊÁ•¹5 ²’,š‡ ¢ÔvU¸r+ƒÐ=+É+AÉÖx•z4rã™GØ"äÜu„t3CÐ’‡·Í*œ˜B)&p£¢i$”F€ ÌdW`‹i½fçC!¹ê×›#‡D#or?ÎkQÍ–[‘DžVž0süª˜ió±…ã»·8ѨÄò$h"¾uYIǘ®E”ç,WõŽEvár`k†|ÜgÃCúÛüFåm½˜I2lBnøøÈõ…çïÚ ![€lfÈ ^÷$Jä$ð„$!óÇ¡ÍDuÏM ¡ ÇÉ BkÛØø˜ÚÉq [L $79œƒµˆÜä·úó‡$[UÂ=#8Uº«Ú¢iGR ÍVŒ‰†o›C¶9 I"‡ð‡íóè÷ËÉ{ÊÚÀ‘•^bOˆSßÖ >O¹ß¨ÞÅׇEUo¤¬ j<þ›_>‡’’&‰\ŽÓ9\4UU¹¦Jä9@_.Á@Ÿ2¡Qß-À¦­jÎ*“JZ¸:`nr&J­L #oBÕh!M•Cþò‚ƒˆ°\)°‡eÛ©Í#á,OUªùËq  Ô…@äÀ’%À$Çý¾ç™—TmŸ69B¹MuxÈJ] $ÚJ^$Z­i%B©¸¸ü]|}ÜàZ>=‚½!@¥ ­‘ÌP.Á鮯¬EM# ãdßq´“K„¤ùwˆˆy–XÉ=8Z‰v_I/à$•Lr[‡ Qe+iKÈØÀùL¹1:ˆ<·†ß„áfã,ßÊJ É0«êˆï³GƱµiáyŸbò„ªOm[$ùøõ×_ÝNÄ´Y1ÌQ$ÛÆ•¸•£€cJám Mȶ± „`+Až¤ù ¬8ª_ÐLÊÙöPUEªÃY÷†´Å—#¨öfH lÓ6¿¼IHsH`Ç'©Ž òVL&ûüä !(YiÙ"Œvm^ sU4Ñ`Tn+G±ms±e;„ÄV;Iž®á‘%ábqnò†\¯á%é2‡4¤µDIà[qÜ$\SLÛ[< "$ëb‹#ŒçA[1­|˜HTÓV­Q&Ö"ùªC¨¥ªJän¦¾. íé`› œNOJé8Ï7xú½‚ —U/¹¤+bަT4RꬑjcDØð´9cn0UüLmÏ4÷g0¾ñ a¿š1×¢$Zæ´ÚJpZ±IT‹gði•!„P.˜Û)g%QÊ¿Iœ®™UÓö!ït¯ îÍ“GÛßl1뻎hž‹µÛ“˜Ùä<­M(/È» V"¨ oÛÁ’&©ªE½€}ÝAœ¢ƒ™C; •\H Ðrˆ°Õ±Zmáªá¶å­™Üa_§þ¿äÎ’Uæ£1Tu|ˆ9­Fjø8MÕxÖø@äfhN¹Ø'pæUy2[!¶Vb-¨êÕý¬×´hò&ÌAÇhþ´ Ñýþ ýú jA…ãI5›-Û”ôåÓü…RI½6X†ÈMRÒË€Œ ‹?ó“¬EÎ*Iy&„B%9[a6Õøˆ*7!‡cZåªD•0B|US©BÚj‡Ó<$õU’#·šPåõÒ­€—ÄAH[¢„!±jšíµ|}{‡`6>­§v’¬€ˆ¤ëŠ lKø%UE¸­˜óššPŽöeTdÂ@UOêßV@ó|ék{[^æL€’™4³mo~Õå<.ßÌV‚3ìùò§Í|x³yWÑ{K¿Œ×¨u,·:©h›\.a"1F„V†È¡GbBÕ„ª(B&”ÔbíjÔºƒ“;©mIæUsÆ—øþïBlõâ)±*IŒMRØJ¬޼žg ªBšˆ¦ªéÇï¿ÿQh™{™±¬‚c ò‚w s—wl[a‹ÃÓÓ%¯}In U›>2$­D ™ÍWgœ¬Ü&r´Ö‚o…8!>¡°õ>ñIb+T»>¶½ 8Ž 9—·MhÅÑÅ%$Â=h‘yVwœsÏÚEÎJëÁCÚ2i+i€|ê‚\¯•FÖÇš!7ˆÀ’ä9@jQßÀK?üÆPJ•gVZlT‰mpœ½1 §p3ŽÌÁcí—‡`êH i~º\›ó6ÇAÀ,Ê3±F°24•„[å ÁZ»¬äñS…ì;—S 5ö˜hÀži[qæ¸/žucë.Ò"Ãm³jaEKhUÒ"rÛl­È[I´6pó(Aæ¶mÎÜ¢Ö’:"¨cóñ(õ’ŸÞSËCº¥ç”ÜÄÓ<ÏÖ'Í 1÷ðjVÉVn­Uý J¹-Ð6¹?$²‚Ö¦’ÌíÔÞ_z‰œc6Fæ̪ð’uWBè~úå ÒE}M%'´¡Õ޹¦9ËUÀ#rÇÉS Òº$Θ|ª&‘ Ž„`Þ g²;I«<ÉV *·¹DU¸d}+–+yj¬Í¡W«\¯Úå¹<“¶Ž@’!ÜA¬øªláå¸(¡ÒÂM„Kà‚äPo•9æ°ceYUî,+¶©hm3éÚå±IÌœP؆Öxn;%LI*+ÏúâûKL%É3fZàâHäþtˆÖÉ­ÈBIHÂM%h;2œ›Õðƒ–óø­1m UÛò¼¬ó•ÄîÞ¡»­£UàÃÊI$¶á‡ñÞfÔŽÐ6­•Ö¨ª—0ܺiÇÏÇJHÒLJgcC&¼sµÚ.c¡‘k¤ŠG ²2*Ÿ¶%„5jxV$qò”âDsöªk-Q2Ü0!Ym•+ùM ?œJ#g‘À½!ž ¾-f'êW8|ÁG,iªm% ³‘z4¶TVþBB˜vkI}µfiZëð !AäÖÖÚÖ*g߉zúbW2ÆÓÊxµp'•hE>Vò>AkZGÂhJI åÖhzí8áÀs›þùg£TàÕ”Ï jƒ­ä¶¹‡×‰¶¼É¬k)±MîT éxYÅ쥙ƒF ©y´Ì<{ŸrÈÓ)$8ó·/¬Z—Ï¿;9ôøµf 2%ò’<)„Zœ™ÛšÄªc§°Úf˜¿ÕÀY¡­ÊVx:%r(áÙ$mUrV‚§.ø]E3À1#wö&¹­Î“´E³ÕH‰_¡F˜üÑ’KP Ñ:©ÜçÜÑ”jÚ`Fí“ÓU9dŽÏD÷¨Ekþµ('g ¹­UŽÀ\2gˆUÉêDyÉVÊ»ÒüñãäÓ——W×q²…"×zí¶UòhòJV‘XIk§â_—íȧQU{¬@ªFUÐÞ¶Ó¡¼µŽÀ|<æÑB¨Úê"±’×QrY/$óçqN×ûzX9ˆ üÏ‹·yTåÀ)©Wæ^ªä¹u©:­D•Ê$þ,J.i¶„g‹^xTÅlå–§+jªœÙ’TBk y O!r¡jeÒ­Â+Y9 ‰· '·;ú;üѼù½ÐÒbm­Þ.>ý?jô'%­ñÉ ­„QS8m%B%YálªÎU£š¢ñif4 ƒxskÖž¿uª> k-nÿ3°*‡šBœ(¼9åÕºÈ!EGHkBãÁŸ_A ßÍ'ïràÑ´v|ž¦òmrzI †fL*Ãs°ÂU•º“­$ï&3ÙHðnŒV£æÑTl ¦ґ•¼-¾¾‚§OM7ÌA²^år‰’ÕLB†C8Øvi8Z„HÌYG8ŽŽkr’Ür¶"7XüÕÔjË_I^;nT9mU™Ë‹< ÛJÊëÛ´u´òQm0|[I]$ÜÜšO¶V*¸§PN"Á¹ŠC~Jê2‡’8óg(€l³’³-ÂJð"<-¾p'Jœǃfh›ÐŠ0­®*ÙHmÉvU ÜZÒ -‚U HOÍ­IàgÄû.á{g|:0áÙV.$…œCæú²µ¤—9Ï«;Ï‘¹\RäÀp“ÛÊZåÈáÈ"„C`î\æqŒÔ·ŽHÛ ÈýJɶWA_¸¦8pˆU‘çܹY s`¢é~I@;ÿ°i"I2%0_·O¹èðkc+ªš !´'_¹9œ¤Þemh¥ÞäU%&LE(ÆË"4e…“‰Ü*”€8øk'iT++UÌÖI\B÷Gc¨¯*‘¿„¿ÈÄð4üBNÞlJrÁD•ªÄ*à<­È9Ü3;š;·83Oh‹ Tb5aSqóÔi³RéT¢Ê–ªŽ·ÛkHàsò¶´|¬Íœ¼-Z ¼5rSmf¥½÷JÝ•UN¨/±@)|M›8“Pª$aë<·%wWhTY%1Œ9] Iio‚_/¢Á3Á‰a]ð9äCÒT&¤‚ë"Úâ HÕü‘%måfΨs ĺñäá—Qs³ä¾0ƒ’$ÄÚ[Ä!çLÚ†œ“¼'"8‚?7+NÎÛÖº¦rZa‹&I+¿6ç+«ã`šS¢ÔJ~Š4!‰7ÍÁ%Àn O®ÖVU0÷p9HBä¢ñ"ãCÊqÌf‹/n¦ •ûÙæ¿¿nõÔjd˜Jä{ý‚ˆ\£õåÓ©âdNuZÞ€7Zªkv´=Ut`«ä5èý?¶ÓrÃg˜$2|4H}u ´ ¡ZÞ¡êO¢úïj” ¹ÞyÂ3R‚°@³µð˜ˆ£¼c$©÷¿ªr»+9¹G@+A†D[—ðÝ­<ó$ä’$j«/+L¹·QŽÉÄ$½zôø¶H€*B9\Ì(7XVJ ÐÀ .š$&$[ˆd£Ê+¥µÍßÃ5Œ’#ó ©TÝ“I'"Ï¿™UáÂÖJhEJ­ø#»yøÇ_ýõýûwì®#ëØò¶À4%Çøý»u9\B%6+„¡PåcmPˆ’m³ÚzB¶p{ž÷cò øIÍ ‘àcÆ—#ÇW2°y$œ´˜þÆ¢©Õ¶ãËkÝ# ò~`ÈÉ='4 7«ZUù$GPÕTtÞúÂ% ÕLš>•¼ÖÀQµers¹D¬T÷¶pZ˜V8ÄÀû;°8Äpà„"¾ƒ«vjx[%‰ ’$Ù6<$gÛ^qL9ÜÁ!’˜Ì¯ÙËDŽœa’YÁë"a˜ B¥†±Uõô»ùçÝ*ÕÝʪۓ7ƒ¤¼Ö&i˜¾š7óÑÒ6 °mCZmI“ÈrH9!°Ù¦í8°vT½tÁ©idVùHHjÚ0ÅÇ„«øJÖ.GUÞ*!A“ˆ§§-NHMÉ›Ä6äŠÎ£‘(ድƱÍçV^KÚ®‚jV¶A†Ý@bˆð¶S |¿E)wirZ!yÎdWGG|«­*I“ÛRe"1XÏ:¹15j’© Üm`4[U[!áY#ˆ-“Ý„Ü Ý†5>§`+aheÕßÔJ’p@À'”¶ÃµËÍJ%øDhK(ðóÇïÏMuA‹IâW®]ó×"~¥ÎÎHÕÅv5Eh‹Ï-¾.1äþ™\ hÓO¢îΊIÑé¸-áçX<ÞÛL90·F3ƒFpn“N¹©š(T!®#«9w4«’@kBªL€øVÿ±ÚÈ•˜#À!®‘–3„nÛØøB^D3scr+:l}ÝB'ÕHÈ'¹$òæq\‘‚mM§²Õ¥ÙÊqÞÏashMkq$JO‘•ÕœµÎ¤ê•¾~8¦@@fÈ'B¶IVà7XG–pp9pœä’´Á›P.±5ç<'‡ä_ §êBÁ*/à‚CþJ¶J¶º Ú˜yæE‡fH#Yù(QÉñuO»'¨ºã¸4r4 ÕÖJNU#+¼‡$ù>MØ0æi’z•HD¶u§ÅÙªŠÖ´ÞØr ‚wrwnÛ` [B« ý–Åßêµf˜œÊG»I ˜ ”Ü[kg‰ B8ŽmLs"¨6Ò8 Ï¿Œ=—¼ú–1MOØ·d.|Eªù~)‘ˆ¦QÒÕÚmVjŽùÞÓ­¯Ÿñ­Ék1°¬ª„”¬]1g|¡ ·•(I4²]+BwÔÖ£eÈÍ àc"4pª¹÷[%¶’¤©¬—øùõ‘mÚVÚ=¤V•@Œjc`IŸ‰¨ŸVˆùý!§óêØK¬º ıeeÕ(¤ó*Õ1C„x#­ÚqL¥Ô%îÊ.Á1’Ü*:]%M=kHcØRi§*i$ ¤¦üki°Ì;E9· ¿ÿ°yª^ËÏ£Á›ªƒ×NÞÖŠ@••¤ÖÍÇHÂaq O2g¥&”Øæ€& T%ðŽÓ ?ÖoIxü¾/ Z|ù |h›G äce»v̓V‹:ªŠrOJUNŽ,±m%ÖEŽ)’Ô´|7ÖGSk ²m>r‰µÇähT`ü«;/¼HÛã~Îï“®YëÎXîÛ +úò[H¶TølÓJº^½”ø`¹µ\Þ œCÐLhU„[åΕùu=7ðì•«pU`¯¨¢qWÝ€-s¥p¥I"äi*¶šÚb ³‰Ý€-Ç6¦’§îr ç5†îœ!yÎNÂÊ@‘0VÍVοooóo4ÁßÊá>ß([æÞ_•õ‚˜ƒˆlÕ…9>‰£¯*¼­UG`[Z[’pnrä<ª²j6¸-s[„¶ùt¥Öt” w.’¡\§Øc­/§Í´V&ÜÒZå8%‘U*[aZ‘*!P­I²"1¿ø%ž-:‘;é·Ž¬j×J+Ak‹ 8ë;šds>'‘#sX’›#”äÀ\Äi¥ZIÞƒ#‘cÎb ˆ+%$©:«ÀzYmC\ r|B[yäh­µ(¯5Nl“X ˆËìQâÌ­ªƒåÙÖ·ŠL.F“+Ù’¬ lÔ@+¤gmE#Ù§LUØj<4IOpæî¿Ù¼}X”€T…ªxÎ`VÈUq¨J¬´V¸¾æ|+Îå ¸Ž}Ã(áàg’Ä„JÖšF;&¶¾=hÒÕIH¬Æè…»(4'MÈ ÇÊ¡Ö8"ÎyBj·Ö™#tÆf`eSrþ%`cýøãdLRÞÙ ˜àÔ"ç%Jv•‘!ujk‚*ÎåV¸3Ð]WÒBR…ó7\â¾0;L6’sˆÀvðª|€Èhº@Tm5Åðãr} Ú*I¬T&‚g[H3[ Óoá@ò ›Ê¢.i™ ©> r¸©:ikMki½à<½¬TZâ¢Èqøë(ïnÉå‚¶Ræ|€›D¯&#[ IÈõxýFØ´8À„ºo†iæé·—CUSLAnBkó#Y5@¥™‡ÊZ^‚ ZIÕ+§ ­9HB>.M¾¦8„9À×]"¢I¨.ðú(ê®Eÿ[“\pÈ-Ÿfã°-DnÓVN¸yŒ /”8“ä¯$úŽ»¥rXˆðÒ•Ú*3¿ù„uQÅQí&+]ÊY8x^ 4 ­ÕVR yný,'ÔWbkHIŸ¸ã{ˆ&WêŒÖòœó„Ô·I€5íåIÈD¢DØÄVÇz1ñÔp¨j‘›rˆ¼D @¼uHU²aüÓhë‚&E£ÒJ¨øÔ]õ9yƒrF&):Ôµ|M(Ï Ó„Ln«ó‰`²‘ÐÚöà0my"+5F¹m ŽÖø´êŠp”ôRMÞœÞV!’"CB¶$„fPêŒ[UÉk*ÇÇD“Ä·6¶äãçŸVPö“8^îž–-S§·Cv)µ<âw4™*ßrZÁÊVäÃAB.JX5¨_•˜píB=~ˆ’-š«±6^|d%Á³Ž»b[œºD»m_]§„œ›™ÛG÷´„ÂãÁáS#`r­{TJTðÜ$‚P©I€ø™C²ªõä@4 ÀYm‡f+âÜú!hJÈ\´­‘œÊoºÆ¨©X‘gb…(;oÕ:¢i#£eËs]Ðâ‹Ì!b|`Æ1$ÄóBȹ^ª9Çïz5Åìpäùh‘°Khòš"Ø"°:£¼ÿ²69Už~À°µrÈsÃà˜Ç.ÓY•§œUI¹-&¹“fB"€©Ð$N3äf¥3„|¶øÕË&Á Dè°„r´JSI u'‘Ü&ç=äV529BA"Ì©—ØÊùs(äB5“°J¬¨ä©B\/²máò>òü•¬(Žõã«-¤ÙÂ9óÑ+‰\"RÙö ˜^ÂA˜ŠDÂ_"$͆#WEs‰¾1Ë;,~ª¦í6¬þé &¶dI†$¹„³P|bB´8.$MX¾µ^Ú LA·¢¹×ry¯K;]Ñ$cʰvV‘“J  ™3h Q=“ÝÙ ¶^Õf‹Cß6Vª¬l•p /—ˆõíƒÙÖ™¤ÃfÛ‹á*z%¨ê¢š'mræº ¥â6< í­œoæ5r–m9àlNŸÓœæÌÜnuFü° x÷!sMmU‘UAB q®öªK\2 ¦I|-Kø ùê€C©sͶŽÈ!1³.È­| Z­œ–ê‚ ì´„ònM)[½l•ÃW•„lq|Ĭ¶ Ÿ3”ãtLIóD³jWGò(i$k‰I"wƶVc ç ÷.iq-ÿóñÇ80ïÞÞ9R_”@vKbj–Wâ |i› Þˆ–O-€æëñóTÕ·TBÆtYþå„N‚&ÁA0ºª\4pÎ=<[/´@îƒTG[†ªÁáZg Á/Ça qÆ:Z•º@íÒ6üähò|æ&Ù©ÍШ<1óÖ¢ùåz•çVˆîÜrPòl÷³MÒŸ¡áu¬ ¡k”“ÓÖ·ñFˆšÒJÐ 8„–­kn`ƒARù*6„!¼ëUª œÛV„’´ùC²• †ÜšJ.ð{¹Ûâð”÷ÚÈ{jýÎW;ó½l®K¡ÖTªÉuÑ= B ò&´5ÂË:×Ûá «2ÉRâÃ!¶|$Väø¶N‘sç²ÚâXI’·: ¼ñ9 ;š¯ ?íã§²•ÄÙÙ‘PU4 ¹G™³ªb,mä;òëWäÑ)êeHwb Uˆðž49œ‰œy}9ßVgÑ« <ÏÚÁUÉ )ÏÜ“°¶å©äÈÏèn‘Éû±E†›G®ª ²¶ªÈÀÆ“@”’(9 +æ8·Ö™³m+1ð±b[£õíÓGˆY#9¡^ÖÆP¢%qp sU‰•§È³ÁZ›3«.‡IÌäC4@†L$B’°€Pu±ÍlL4!ÑÞ$d h§1¶2Ÿª¦@Sá7 åp&Eùé§Ÿü Á@&¾$œë.Ça(T=¾ªTùV´$Jžu$œ¾plU¹KnSUIhTר«`Òé$Bf A&Œì¼J^l—ÇŠÖq4ê ™Dtj9ZCÞÊ™ß5ªvÆMVT&ç©DØVˆÕÃÈ? HÃH:…Uh¡h›ÐVS[ ™oý Š•²¨´œ¤mç%·ÅorMg[¯ª¡ROSY tcV%V’­ªTV¼\_Ïe¿«‘˜Ö:2‘ÏÊG_9‚ߊPÂó9FþøªpZªå¶ I<â>@«À„ª Œ‡OCÂKðåmK 9ˆ|BU¡‹Ï\ôˆM·p†r ²µ^m¹©âå„J9ãKضM"—8ÂæìZ2²bâS€&ð;/ж^‰räTúÖÂ6„0+¸„Ð+-0Ý9y4›êTäv>‹9xž&@ctc>eÀªõŠ£…$!ÉÜôbXŽ“•¨dÂ!¶¾s”Ìß›gâÚ ¹0 S/@æBáÈ Dki$[qd÷2o«³43«„‰àÜ}vdaøõx-ºØ”Xq —ë›ØóâÙ§_uMñ.§²„!˜B>ówp’T@«€tÆ[<7‰ÙµŒ³GŸ­ñ$ÀÆÆ·eeËĶ$CÛÛçµ`Š1UÑ y“ ù ¼cJ ^8$Yq IH+ {y\) šà©dÛ½Õ¢ä)û~ð`~Àì"—#(A²"3Ñ"²‚x-m»½Óò^ ¾a ÆÁHñw@&pœq˜PΪJY Uäºwj4ˆ¨$ј-&m“ćHòŒ© ÉÙßEúgòëÕkaÚp|ySÕ—•ÈÊ èî,]Q´æ!Tm*ùùw4 †žs¼}†(±È=Ú&¶ÅW…VLëd«ˆä¦ Dƒ.¾ãœ\ÒÊAµ+ml†äsH…¿^¦•›P°’T3q´ Ù Uá–äÉ×ôØ}|ø©ã5ðɇÓFc[µ©ù¯ßë™ÊI%VsJEHãÙšÐV»Æ3³P"‡°ƒ›Ä…4X÷ g½äN×ûhüVÁ§Á˜(õ“? *7 s!a«BÕº@0!œÑTá Y %«îýr Á‡pÎ-­-9“üm% œI]ÄV/+¤“jÍø%öÁQ¥­Q½4B¶2»V§Ç=s× Q²ª6XU3ÀåÍÀ™gþGçl$Z‰’¤¨Zk«-7rí¬!½u%»ê&Aæ#GˆoÍYIØ å3Ç·5I`Û¶: 2ÜHM;\¢TÓJZÛv!„T¶•Xq€;Dî«Å—9ÍÓéêÎÐ%toÝLTDR¯%;£„J‰ š·N•s–ùlU Ð 9û»vL¹<+Úp‰-Pî8™spl…î ÀŽi…Ö\ÐV’>iÑ„R>Çñ~N'7&òm™àÄG#¯‹¦½Þuǧí h†DË.©$Çìöp’`²åÓÏ£Ž©#ULwNÞ+Ñ·7²j-”Ä™ø¾-JuÁ¯/Ä)];¦ªè5CÐÈ+GÐÒSŽÉV4 +Ìl›y¸@Æ´rS’„ËxÃØªjÄGŽ@RäY+ Næ=y“p@H%pëêk '¼¬×Õ±õ¬RYql'L Þƒkl B˜ÍÖHnØlqÄo&y½Â%kƒ1É™§¤\IÒÈñ;>9œ?2d†ÍßJ FnTæ”{¬˜å4ƒ\t?µËÊ gHÒ¡žGóÖ5¡ªÈÊËÖœ¶„=ôN„Ì\~»½®Á™ó:JháÈëÛO N>8çÆïûä_ÂÐH}Ž˜ÌÜûŸªc2„ZïW&[¸*&7Î1­Jâv~=ú¦Å×ÊÚ ÈU1]Qnr‰‡bò†G«‹D•C&@L`B—&çcB´n‡X©¬œ#ü¼|ˆ±¶¡„âIEND®B`‚ic13Ða‰PNG  IHDRÓ?1 AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝÛ¶m[Q¬a@DQÄ…÷$ä– @»¢<°¿ÚþÞcÖ5¦YÊN¢FFFfm½>æš,Ü_þ×ý×?ýéO_úÒ—¾üå/ÿÙŸýÙÿþïÿ:~å+_ •D¤#PDbÄÿ÷k‘>kGb-;&ˆ—E<Á¬±Ål›ŒLùÕ¯~ó?ÿó?²Þ‰»Á=ñ>â+Õ˜m]Ü”š…l…öJ?ÿó?ïHlC9^n7$PÉ#²Êß±®MIŸF5ÛdZf›S`ä@Õ˜Fâ'¦¥U‰á¦¨>ÝçiÃÿõ_ÿÕ2r|z`]i0‚lj]H¥í°ã|²2´Þ#åxdþYÉJ¬äaÇz1ÂÄîÈ–ì8üà?P¨3 k#Ñ@‹ÖY Yd“"åÝ!Ï–V,ÑqOßImÂ+ŽB¯¬ã(ý<į´^<Œ]°]KÆ áÚa?Q²#gYÔ¤?FÏz*ÍI 2l Ðó¹mo²¹ÚS #/2™ >»¾°®¶]»RëÉ‘€È¶ªc%&{••hº©jÌi~¾/ú|/ ‰iäÚ,òéxý˜¥¬$;–›Õu <³ÅhÙãJ€Ü2L#‹Ó¶2•®Í¤À£?î]ö‰âo‡ÄrzÙSö¼*µÊd÷Ù9À³ ³*(]~Ó}?Yl]‰ÓDêðºð¢Û!g¢ŠÇÈáÖ^ËJª­Ñožx e›l%&â6Ñ.b4ž…žèóU #¦.Y‹À¬±cz¼#ÙGýÄíÅTøÈÚ‘yâóÁJøJr&•ä@ž.âQLà!gBƒ„3 |£[&™RžôÄ—#ù;ªš0: ¸€µÐŸO‹¨Íìú´¼>þLI‘5`:‘ŽÞoŸÍÄÓ[Â0ÎÙÆc1Pä)k‘‘”#jíwßù ëA‹z»Q4€¡²è´ÆÃ‹ËHÜùÀAyûÀóe-=<Ù£K#{†Ú)‹&Â@'v¤,ÃiÚª®ôø4F×È$ã;ŽÉ“2 »H¸)ô@žø5jùãÿ(÷Vô(ÄHâÆ!¼ÄõûRJéñ»i²¦Ëø4·!Æ1¦a¤ ÏgP9Çšs!ʱžd¶tt+Ù©„T…§É§+µ}™g-;fèØ8ÙZ½(µgN ôx׋Jò‡.¢q)Ó?•O%½x$†ÿÜWÂw”{@#*•‰Ü8Êž3¥‡&’9а¯ 2nŽ¢F“¾[çœ2>Í2@³Ý‹‰€…‰0 üÐ÷Op+c íRŽ¢MŒYÉ6ÝÏÍJ=“Ƨ¯„ L™çª5ÚR©'ðÂD¡K®å!Ž$ð¹Än :Ç©áŽc“ã3>Ʊg¤Ý~X )×xj8òÀcͰ{>Å×ëÈŒ@{âùªµGnP¨Vò’aˬØÂªÓðB·¡Ue-M”ÃHÑ-²Ú Ø”ºš ›•ŒÏ<){ždx‚rGRFb"µ ÀªòžjKbXKƒÒ;™§l¥p;4}³"u äôøJõªô¨NŠ”ã•j”EŸõÚiŽôOý| "F^tG2‚ó‡fúôžÄ— >RgÃtù´º#Y9=MoUü®‘FŸÀ3~{ˆ›•Rnçz7:sEL(UÀœ¦{5înɳì²Aµ Xh7‚Ìíž²7U5fV@!«Ë&ùÙëõåJISc#00¢Ñ+uG ÀJÖNvzÞ#”0a¹jzÇÜÚ[’`Ëk™>²¾ÒÔ^‰’¬Kä¿)ñ)ïÌg-@7ªËãÅX/¼@öj²láÈ!|÷jÐWþð‡?(¼ÏßNÖŒ©¡æÛN©IÇòùxÌ ÈDvì¡è­]&˜&ò¬öDǪÂ*7ß1Þ-Y˜ h€fHi+Qo#d‘ÉZ0ð¬<)Çl$Óä¬WUŽiCLwÇ“‰d‘å1MAb„£mex$ŒŒ™(«&㵎6´Ì>šSmÖi{ÏêÑE/;¶I¶å·KV©Fæºz†µÇÓ¬V’‰}F{’í¦ øS¢ì b>YËvh´#™^GÀy~F?žÏÒ1²a3Ò`¹šiÚfÃTuÙø6¬…˜‰,v½j ˜¬x´çí Û¤5šÞДñòvÎD.È2§É6°j#ä"Ô˜œ»ÚZVÅÀeÊnãØ\G˜F~9ÿéCp+ÓT‚UÅ£=†ý’dë˜&°j]ÍBô^…µ^ < $(e sßÐfaD¯° µèÂÀ²§Çhþô?ôknÇde½í“3Ãð”ùŽwÄÈz-CV»Þפ¦ ‹|g×Ñ}|ÍóTëÂôS˜¾1Zƒ'[U ·l¢¶"È¿FX‹èHŸ8ÞQɺ*É·y2™€RÕnu1Ôˆ¬×±FYlbsã7¯ÑQ.RzDF›"L½d|TUë*#²–fŬ% %2®kx `¨ ¬E¬%G‘ÌhѪ< &ÈZ -p] îAÞ-øô·§Þ¬ò̇,pV|Þ½m¥ÇÃ@¶ÓwÄOiXqÜjî¶jmæ¸jŒèò. ÚJ€R³e¥LrPrìuìÛ¢‰ª‘€?Pù}°êÍ`KÖÜ@ãháJ@UVJ{« xbjI&Û'F¦.5Ã]2Á‰›˜+ŒÛeŽì90lÕ|â³Ê¤'ÉM`ôŸ3ªø6nhâ0AÆ€‡ÉêJ/·CdʧfSú $5XÔÙBkö…=/d<±‘OÓydñaÀ7©J†‘Š4·¯LC ãad&˜/òqT*OýÓŸší[õzÛãijL +É"܆€À´ ”Cß^Jò.Õñv£Çëq 9TÕŠdå¹ |‘R& ã›%´mL0}Lƒï» ÛÈ'=’C-ô}uÎ9qdžk×;“Z6ëö_o†L€²®$×wN&ŸwqÒØ^DX©þmOéÏŽ‚ *ÐÍËJxd Á…kãÅÈ4>E@î¡'H³Œä`FØX×#]5–•2|èOïžSU%0‰ì.‘rß­DÚÓ×%= «z-Xãð‡#žX—)õbš‚gUc²0åùGÉj= M• ÎN¿è3Í~èó¶¹I—ñÈTE³“9rë)Äg…¼J¬Ô~ª hDÌ]M¿Í7Ñ?±ô@[ Ý´7‚ ÏÒïŸÀ™71g홫x-áJÝ(=>C—Ši¼GAÓ [2™.³G‘aæ˜567CUÇ Í°Ñ° Û2âHUL½öõCŽÉó^^#±ØtXWn³ª×ш­¡7¥Œ¼§ÇgâÃuÜ@ãÆÕÛÐÈVª…gVÍê=‰œ ÝF“þð‡9) rÙ5ªÊ˜Œ€ûE×UI5±0~íJd‘Rî&eUz½zz8%CŽjÃ܈{dªÄÞ¡ûAÓz&”&ú€Í¥l(MǶ}<ÎæÀµ/ß2;ä@0«zÝÇVuž¦c¶eGì'$’ŒóVD]M¬š§×$˜ù6líår%Cíý|æÀ™  q9l½zå6Qª1óô0Ix<½´ô¬T9w”'CÂŽ× ,·FÇ9gr÷ªžN¡0 ÐßÑâˆÞ_Õ0†E2S'î]Ìdzú´7^¾I¼¡{ÿ€<ËëÚ•ŒhI°à&€Z$[É{ÓQo&«”˜üñŽ ¼F;–‘™Oå•ê­„ Ô~ŒñÏî¯o¸².¹õ²Û5#ðÌGx9R 8ölÓq g’Ì*âR:R’ ‚b³T+Gbz7}ÿ*ͦÐÓ8Æ8úÔ`ʇ{ñ«æ¯…À3z’øZb³dŒcþð)áÏ?yäË"©¶÷ÔijðÓFIÃOS{@#ðûßÿ¾¿Ñtù^¾º4Šu!ÉdnBInVz½HØŸû[òô?A‰ÍMö*<&0gh碣ªcƒ`ng‰ç‡¡Ï8A¶YÑ;¦Œ—óÔ¦tkxí€hPkI¯±#Y )Ï ¾?Ú“Á;æÐ>™g›æÞ$ >YþáJri2¡¹Ž¾Í^ÜkhÉó±o%¥x½Ù: OÏ›Ö8Ùr%þu-¯ñ.ÁZDû”9Äh©ëüA?öÙÿüsOdž¥“{ ­Õºû„¸/8ˆÆi$Ëœ°Ï¯Ñiâa ¡µä#gRéÞm†r^{;ë²p¸^y‰³j Ì¡PÒ(2ìvµ;’Õ+kÇËIJpŒ—s9+|%âB‰l-^®Ež,œ›B +Å”#,O€„SÊðýb´õŽ”ϰ÷£xèóßK›ÎCCÿh_(«zkÄœ§ðþÐçàÉà÷´›ž§jǧû$J™r‚Fà1‚ùü)U•ΖýøÖOÌÆ8z4®3\5™l€l‰@ÇäFÀ uUµI7Ÿ‰Þ}[hÉYho¾Ïÿ¸ž”XûH¶¯ È•Föø¬aüa²Y«ÖÞÂ1=€ÜPÇFáHXI/ýS<)Cþ™L`ÕĬ­TTÊ¡çF Sõ6\ P•ý'H#'¨jbGÁÓ1Ž‘w 8AÓ‹|º”õVMOÖs¸Í‘oDÈQµ)i`½ËÍ-GžûÏ™¨†{Ò½^¹×6­cÏÈJW&]!^©.d‹Éê’+µäVl Müä8êUÚОƒý[,7šd­4¬ZØ¿«=Â×—¨’c‚Å0q”Ûœ¦j¯E¤ên—ìfتz{˜ø]$ ¯w –Ï?Ù­¤‘sè±9ûh'`¨$ÂHÙCk(¦Qæ€Ñ§)µËh§Âéåöì c>L¯Ï![¸8ë.jN¡W­¹*Œo¡p;ÁµlLLʬzRd÷ýéMGÊn’y äŸ!A‘`ùç HÙµ7š@‰¦ŒQš3Ûp%Uí‚Æ«lÃe]JpY—0"gÀq 4ÓðGýŽHV¸U™·ölU‘™ëª±zJ"M`XïS|}”fÕŽ×ë(’àï ¾’œ3ü<Ÿú§dnú“õ¸Êí  #zsD$A&1X‰,ž¾Woí²ó§oÇΤ\v“:«Â5“Åp%’IÇ||U‰HkµYæx]rèèAÐÔN†,À™8Æ$¨1¼v†°Y2q|£ËUu9úÚvŒÑ8Ùœ9 E×ÑØ`‘IGz±àÊ|z>”˜œéË5†É´¤Áúà`šF`æ–¿ê6dáæº4â—ã1íÓQ·-ºð=¢ª¨÷¶¥\XžÀÏa2|é3Ì-¬ªÔ‡‚É'ññ…* ýõ?€p uNºa^‚«R¹IxæϱñJŽá9!Ròðr| ½€}×ÊE]SÔ‹'Ç:[¥ü1yæ37bTj=2-µ÷FÚAi–úThjlnKnI):Êl“±ê— ÃLÈ”tõôÇvƒãsM8ò1> ÆO ]PUäœ,M*OØÐZns‘µlVWèH“­œl]ÓÇL ˆ™4˜m̪Ž3lVG Å–ïÑEö`wÌs-ŽçU;ÿñ¼s¤¢‘²ð9eêÓb‘24£öŽr2 °×EÆóŸ¸…w EÿÂ)>>”¬0°Ì§ª®1k<÷yªs „‰c(¹ÝSyöÒãýÝ+MæëÂÓÜV™´€,òi“•ªÊÂ>§íŸ·÷Üš+t íý¬ÖU愇 r Ë6Avlt»¹`-•Ò„9ª”F+‰z×…¡‰ºÑãu‰ëòX?V^›­ªª« «>ò“s³áöÄèê¬ ›Þ|ýfÏñJê8/ïD¯E^ £äEfp¶x~ljŸX 9ÖÒô|Õëç#¦ì˜Ö%|ð¢éÌñr-ùË ‰$ã0Cà±H²H&°\ G¼–B ¾Æ<ß•Oˆ R¯«õ{²7“Cüåz[㩜R ”ïcŸ)RËÊ"ÏÄÂȪvëxËôRö´É¬­Š|™øPŠ=Öåzjk­Z"¹‹d6вu3QJ騽-{Žø42Ùž©£Rʪ™›UÐÎŽ‘-O†Ÿ¬éJ5”Ébd³ä‰Ûa;·UÓÛÊ ýY<žíVÝ€ê Y;Ä/#[u ¥­æ WŠ/cDš²c#wîI¦—‹ùô:ö$æ)«&ˆ!¨=O]ŽÉ€p˜ e¹’Œ§9„e2{ûcŒöHLß&üZ`¶µ4+ ,à¶:íH$;w[å˜tJ€ ìäØl.ÕÒ0UXŽz øcôþÁudRdAÐPØnŽJržpS<‹•Zæn¬…C#”r–•ÀG5· ªÊJțӧّ27Œ’iúŽÄ´@]ý“\KZj—»T¼,ª–ûäÈð²ÈJUðlJ]0AÓU§T] O÷§¤%²öGòZc˜C@ì:‹l%™2¼1[Lµ‹TН%¦·ÈÝ7…¾Ø¸Ž[Éqƒò™òõ]²ÎyÝ.ªø,º•c/¥?~à[«Ü¨/¹.œØ*gÞ~òžÿâ6“ˆZÔ±ÐÛñ{"ÜbäB ©Ë±^ ò¥xŽJ™´¤5îjÓ(a`Éa½ít¤ï˜ ‡€Ô¸R„x&JÂñ™ðú³VÕáæf.ÇÔ Z#óm¿ÀŽ”¢v`V‘’•*XTÚwSkËû—_àlk)kœ çãw Åd)#·ªã°^¸Ÿ‡^?Ǭ ÓÀ;jG–çÿjé?båýj†5°¨di1™’h°a¢'â^“ÙLïH¹^@(=/ÿ¬dþM$‡ô>uçܺlY¤œ2FY)-,ÀJÆÅYëýsŽï˜C&Uù3l(IŒ„×É6q²™hŸµw_ÇÚ-JŽöc#“-o·d5Ê0 ë½/Ÿyï7ÞMYÍV®*ÏÆdBÓe%ŒÒŽÖH_îžIVÍÒèØ2p†} yÎ)Ò ±È°‰x¸C¾þT!þ>¼D©?x9š! óò@¬·×àP#e¸=äÙâU16]µÈ12®xÇ»‹^µY9« ?‡Ç÷‰{Õ”²J˜ƒ…_Ò÷¿ÂA•!¾¼¹Ž.Hyö~Â'Úoâun1%ÛFĨ¦ÇMTêßJ a bdkÇ'ƈ)a|Ù·a8Ü·$ ^c?TŽ¢ëlÏr½ù9ÆÈzª€ÒÄLð¶Ì™Þ1ŽtÌm|sWÊ6ÜQþôæUã( δåXLѱR™‘’Æþtëè¡8î'[•2Y‰FÔ%ϳ_A)ñ+¥¯Eæ Ô'T¯c¶Á>ã“ɵËÜüÀ4¢ÕöaBà —rÍlÛ$1,Š^”ÆáõŠf1r‚øJÆ ¹<Ï‘µSÖU ž@Ö¾å“MбõÚáé>IKÎ.+bš{wmÐfÕ/t 2ŒY€#Y»=Ås¿R 5Èl‚ „Ì®‰)ð‹Fœ×HÄÚ¸¼Ï>ÁÛäh,-ãÉðZàî´\äªè!V]£c?94•ùIëjÛ­×Î|dG2ÓáÚÃxÛÖ{?V ™Üˆ5n.ç¬4¨–ö—MÏVuþiZVr ™žóçÊJôd ŠŒaB ó$kVÙÑ•‰i*}È-,ÓËL;ÂU÷u†\»ܱv8½FCÅS?ûTê:4m[ÙºrÓ^hìš›K©”ì&7‚@Ko²X‹êzÏÇé,7޳ꀪf^6îû’l-JazYDŽÇÔ4ƒ8º·’>>F®·¹›ô(' 赘ËÛ‹&Î6O<Ã}¯oÛ¶Ò¢T¤”ÛDôÇcšÛ,ëP"“Çå ‚ôxXÖ˜aw—E-ô4é)Ÿâù@ï¸I¸’^&pkl(f†dý”–IÖÐY)aÄ=4ŸZ(UeÑÎ97ýi}ÝŸLI¯ w¯¶]Wy•n¬¤7®H¶UÏÆj•ÕŒ ÍH¸Ïƒ»?ô·z“hˆE½›¡«Æ1ÉtÜÒTÕRµ}"åÇì$_H•b&8çIS´§ÜÎõâ9×…Ñ+“8´IÇœk[éÐ+˜¨Öµ»#õæ/*2 FbÇZQ—Mf;çªzáë%X¯ÆÂÐzÉê ¨âéåwqÄs–‰k÷m‚ ÷ÛèÏýñ·sr+©ºQ½1Jô02YÃö1w‚Zî®.B¦Ÿ^ž”ÊÄ1¯ʨ[…ºU2j!Ù½U°FÙ³d=dÏb-|¾0õy ZîGÖBÌ‘ù4h‡öIÀ\P6V]tÔËÎ$ãÈPÐËU?üûÄä|£§Ilz¿Rš¥”mSº«ž;Ò³Ú†Äu1© hJæÄíÖJ•(|,OY¯¬Ý/hRve8qΪ÷‘¿£,2Ÿ,ÿ™tl"eÕÑQ¯ªÀÚ&H£Ü¸ë7:qírÊ[Ÿ8A×ló5&6¥ žÁÏËP6Ågo·cÎå³.ߣþ¹‚ GÓQ£°lž7 ãªÓ+ñ©7CùOì…è¨Åå“þÐ"º6A ´¡ZZ£×nJ-{ò‘U•,­AŽ­!wlP™i‡lsƒ‘íÖ2» A±ýßÄëñ&“­¤4çø|dË´çÜp™y€R(ebCÊžg#fî$Ã0ïsáÓ=‡Jµ0¤Ç‹Ú‰aß#ELJù”•€¬”ª§«O3O™F%Y`˜ø¼Æ¬ x½…t¤·ÇzðéI…•ªêí p4É­bžúIÚóϰö˜2˜è3¦´·Ì_0§ïߥñ3¶oâ|r€luÅsÈÖ‘@éq}½.dípor·kéú”@ž›¸^2çz{¤ù;ji.<ÍÜ8Ö¨«‡–?Ò‘a2¿Y¹¤ª€ñcxŸ/2戞0´Ÿê-CÎy<9ÿœaK CClJÕâ•Òì8óÀ]…‘)ç ž=¸F2Øò¶Â$[¶žWEéÞÓ±û~á'LOÑêÙ5 O_‰RîY§1Æ ŒP|v<[B vL&±ª—),‹>¿6‘ko 8´pL ß8’¬Ú'Ëʱª ÝtÕÌ‘®) dæÕÑn‘rQ—¬TÆëÛðxž‰sÈs½€–¶ºIb»—.2 M¥ÄµW’•<Òn‘2r²¦G’µ’ªØ8UG¥‡> Ö(<ù®ö’dU^U+̺¤%óTj\€ƒ£§áâ1d)Óß]¯Y hÌ:‰ÇÈÆ›Ž¢£ñ@˪M­ëvƒUmiP³˜$`#ÓÄ÷MÿÈÏÿmˆFÓЛÕ'½®ª–¹­ˆ Ti¶@³æÐo‘õ&ƒ›B g•Ò±èH@);òT‚ V½v+©¶›,^Fï«^™¾%a@Ÿ­q{Q0Mo[½ùlÀÏm÷R¥l¾rÞh‚¬šžàö¯q2¥U•zÁSV%–ó´LäŽMÌSK×o¥”Jâ˜>†þ°&^Îá8'ꬹH¡`d¯ ÿc'=Y‰£ÜOMŒûˆV× «ôU¹äÖa-€,sKïh›ˆµ3O¯‘L‹è޹%@V•+ñ©KU|‚”ké(/Ⱥ ÍzUk ÜímN9ÆclgX¨ æóp/¾éh*¥ôx="dæHWðiö!æƒxYÌ  ¼ ¥ù0ù^¥œ5b dŸu†ùÔ%Û¡AuÍ„’ƒLv¤™CÇ‘ÉTsãÃ<Ï4ñåó²fZöÜwaм2¹×=k¹cp,ÈŒé2eüo˺Æ×»*Q#“‰c’­dåƒ×Úpû˾çÈ€².Á–(ÉÈŽäÓܲ¦xoÒ´Þí†÷<1‘wæ#2)chžÊ Ô…l32‡ÖVêès„wM8†É”HŸ ýžIž]Yµe¦TÀø2FȘÜÚ'&eUÊièÅJøÞÚ@C[#šòÁ°)Y5·-µÓ,ÙO§Ôw@jº:}„š Àw? ªŽÈ^S]ÚÉ6&, ¥ªit‰ÌY%Ã86+2F;žF[d•2§?î蓶ðÝ«~wÁ ÂYñð6z¿‘Ä)p¤—'ƒEâãþ$˜­¢£^ ¾' œæ÷‡*¾.27ªSÆÄ˜}æ6!p,FRb”ºìd¬s¦d;ç£1ÆëѸ<7:AG]>zwá3¯C¶v;ˆô2üyûëÍð&1¯¶6P»g(;úó“`aFÕŒn;ýü {!èHÑ`9 ê‘ Ǫ̑ݳY÷= ƒ×¸j'KéØh‘uÉÙê+‚ø4Ès‹w)Çþßý5Á¤O1«®{ r†&†Jöȡ.SeG¡¥®ûšêDÊĽ…tÍV)Y¶¬ô"›î+ÑÄÈ­1ÐÙ"é‹lcjQEæ ˆô›eŸG#TeÊpûgX °LÆŸ¦vÇJ«bºT¥–_;Y¡ú…wÛÞõga¡>ø£~®az w Ó®F65¥R ±Õùã1ŽeQãcð…_‘ùgظºð5öCجdV6¹™êdåºu½Ñí<[2½n‡½ëŽd C•&Ë37í¥XKØ‘FL#&îX;LÐÁˆFäPµÆeb|2z¼˜'Æl«•n?1™P’ë•Ež¯ß¶Ê(ßô=&5ýËUeŸw¾5k™õí“©öYÖ‚í!‹4ÈÜa]é'H&÷\2y Nòɵ³F Ðgûy•ƒ “iÂêrìÂÌÆ‹66ÏgÌv¨«}hÒøöþ½OçKËñƒ .æªÛ6 ²Þªp†”=–‰gËpLHãþû]½ª 2lx?$÷3Ç·UVJý>Ä ½ÛÙ2"dGƒ0­´¡Jz³“hL¶m–j©*7ѸÌãÏç¯rï7æƒcrÚ8׫…æKƉIß¼Èá} 57[™ Mã:NãØæ£/ðÖ«J–2ª¨‹s¥™;’Õ ´Œ}ï+ÆQU$Îg-ù+Í0ÁUZ׎[)+þY5h¶ù éëõÙmO8A{nôýSŸ·¶AMYWË;zbp“:öU1Ë™ÈvkP-­¤ Š4"1]ÀTâëUjùõ&#Ð(‰õbfUéÓ©î)Dézä,ô(ÉŽy)å‹ìJÚ‘»s-}*µÈ_©YåÖ§ih1 B¶Uík‰¼5[ã~¢<5&¾ó>l»Y”í@Fü#A-H/D†² ‘ñº,GzDŸ—0‚¦xÖÏßã~€³R[!û,»it”»OÁ³ÞîÈg…ì( G¶ÄÂQÆÈ™ÇÀ"@Êd‡}ø0^ØÓ±p$¸qþOßIJ2rüÄJ6tä–ÌÓ±)ç ìª w¤n^¾™ndzÙûä“èKÂQäLÓ§Ò‡Ôì>xæ@xHÌ•’!>à1¦“탡W’Ÿî×׆m¦F™ œmz¸‰îe#RûéeL6+L|>pË4±RyækÉJµˆ'ëÊŽb‘m·&nz#â‘=I¹M䬺K½˜‰f™¢]VòZ¦)‰Çð$km¸®ª”%ÇÏKH½ر.G¼¼hçŽ0Y'jt‘À|¦Çœï‰ÛÚQ¹kàyÉt“5à>f'ç“CÈ»Æ÷7­^V›eŽOà@–-†ÎV‹ÆJès¢I k #}fŽ[&[Œ_4ûÀ¢5âåôûMÒ/(Ëw™²•bö`;ÒØ°¡güûm«kW#ÞãjmŒ ×Kœm]ø=XLšGþzùvG€’FUvÜÓÈo\™OúcT;—•€òĘÈñ³wÌ!g¤­v#¸Md‚Ö¶ùq Ÿ=½Üøà#¿Þï Î4¨:MLÇEÖ…¹”·1€ÙBÉzMaí¦ â¬dX¸L]»ƒRnueeVúªp¼£’ì!ÂîXî)Gæ&/4žžâ³³²¼^ÇÉ'ˆ„E¼^ÏA`jß >Æzæûú¶vìÉÔ~h7¢¡YÁ ý•®®ø˜°®=¢¦ð4ÞtÊöÙ”˜ã¡ºSf~/IÊî>[佯Öž²#É`¥Þ–œÛ0%¾+Ð`ÎAƒ‹y2Œ©¦YÀÈpJ‰É—#f¤’PâŒÏAÆ´J²£~Ëjqh([f³”r“²åµJâ˜>O!,«Šx9,O|¯:ÙªµäÓÐiŽïÛ9ÁY&ü5†é;öbµլȚR&ÆC‰Ó”»2Ç1écdÇÏŸ$g¤_È@ÓÝ»é€vA&m2fSúÝ®JÖP€§)Ž….‚zø óI¶¼‰5ÒäIm÷šO@unÌ{D+9äsîãÌÍ´mïÌ1Gd?¸ÈÅfo¤’S0á Ì=V¥†1‚ÒçíKNªµ+¥|T'µ€|/Ùè”]|S”º&¦v <Ï4™Èªa†Ê€Òìqy”eš˜à‘Y}Ј qŸ_ô[oŸ>åvÃǨÖëxw9“õ$«–Uźö¨zªº0ª€Ü¶äJ˜LæßM7H¯Bèx¥â™л)0¦Ræ0}_(@ÊHÙ17+ÑÀ•^? ÷ÔIL4âÕö`dó€{!îJQc A2· ›p2$ Úµ.ÿíD|GÙ¬¬àû÷f¤•èkámøT^Z w”UÃF‡µä&‡å#èÖ ë…3$}üu9Vj;òt”»ZKÂuÉ‚Lf"(ËOå4:&ÀäS»£má<É0°L¨=‡Lâ³Ú ‰{þ~ž)ÙÎa•ÞÃÙt@°º?k²²}úÎ"ÜÐp™Ø;9Y|WCP¾þ•),‘ànj Yô쀶! sNùùTê¢t«˜Çì IUÉ b¡»sã>ïŠQm㎲õ¶O“§#ÏÄ{{5kOÖ 6üœaëû‰Õ<bL¹ó4¬éiœ¦ö¹) %Ùç‚71-há(öp:n:«<aC¶€ï]X•Ó“1Iܶen@qË0Ùæyïß•_/MW*ò‡õê"Ûæü.ÞM1íCY— WmîKŒD³Ç õÖ~ty…‘Çéx¢ðø=KO ¬ )¯1Y/}a<¦{z±2—=ˆ6“‰= ˜²)h"“9#q> ß4“•5ª–i`¼£Ñö´dL$Ûܸõ0b&>’g @¤7zÊúœËµìvHá(zVrVü‘MÙÜ % Y<+|ŸŽ’#>9€¡i\&2r 9æl“|l3LŸ ºœ2r#€b2ÀP$e¤ìØ-"iªâ#åO3ÅšI{)),aõU1ù6ƒ#ê L{·éX¤4Y´÷ãq~“µÓBŽœRÖÞoG¸>Àü³íÎa&Är 󋜫#óª™o:F¨â|#Ú$Y9hn7z ^ÍÒÜ”2ñ¦×ˆÜáÄkD›ÔRÞ’Žp2¹v›øßÊÁ¦l¨WH–&±öÝÂ1¥ks‘ô{p2¶~ºè;¶ÕpíKÓÓÎ?¼å#ëÝn¤J¹ö6‰¤QrG½‹JH‹dr€r]«¾þ ‚³Ó`^‹ðÏIÄJ=_XI.ªÎ¤c%-™T½Iiﻤ×èd5b˜ }lÂ'½%8ÚjCk÷i5z?f<ÍJ™XûÁô}ÇÔ[i™­öÌ[rW£Ñ®„É¿cþgÿí©‹¾Þa] úÐN#´ãWâÐ2rn²v>€•(§Ñ^#æX¼]-17/w¬´Œ.‘8ãøµ0i%]FUpˆ·<&“žCŒê£=Ë„ÛJ&Æ ˜låÄ1³:‡¨ 7#5‹f( ŸåU½ÍÃçX£j@NpúŸ¸?òª²¨šX¶FHÉQæoJ8XlnXf%×ÊðíÖ³Å`¡KfÕÐ<Ë•Ü=^ûi{âŒ|ÂɪŽ-¦£}\á-9Ï ÓVûá$˜ÏlõZÉ’˜ü{P)•ðMÉ_‰LµK)‰ý4Hø)ž·V ΰYŽ™;k\WŒ¬K¤ot%̪”0C¶|ÇJÈÆ!¹Õ(·LþŽ·'²™á§Y"Tjý0޳Р{¾z¸IÄ"\ußràvÀˆ »äªR¯hJ{ÂIÐzad-Oý•0! h?^×–j‚H™øþqÔïGÌAÐ÷ªeÛ#²†cëÑÃñÇD&bÓÃ7Ȉ˜Ž·~æ°¨§÷Þt›¤qT…Ƥ?åçFr ãÏÅÞ_™MT=žÒixŽé'@êJVN&ûàÆ´d½J"†°óýL"×r—8ogšY”"fþ¹ÉöD ‚Þ´×/ŽXåÝMYÐa*Á;ªJwø‘¼.ß#[‚ƇdE-E²ª²# žÎO_„•)s[/¾Û’²÷UÔ(§ È‚‰G'Ûôø=;UÇž€#™Ìñ8¾§?õ×'­…lJÇ;(»Iíp%ÕJ²¨jº¿ÓìH è‘2ÜGœC£4F²eÕgÇóƤqlP#À…#™pÜë”æ¬ò|‡â ¬D£ôê|_6d&õFjøŽ@8M-À’>åÉ*9Ÿ‡–Oßô•±«¿%ôŽ>k¿žÈ,Èq,ž]ñ@Çe ™œ,%¾à„Ï“y&½ï`ÒÃö<µw(5÷ÔÚ¤®&<Ùݸ.@dP†˜œ¨&·V¯øÝV¦§XYïÚæI)ð1ðZ"g¤Ò¦œž'0žiA/#ŸÖ—§cŸbíUÉö=DÌ¡–­3·>ckôLñ•¸‰p½|0ðç¯ÎJ«W»£ÜÝן¦­tù+þ^äï ¶­,Æô 憫n´’È3ÜóO£D°¯9#DÏgÙDšynC qþ~†³z ^ÿ÷Â0zeCÉ”àZZfwI˜¯±ñZê (ÝzäLÖ¥óËBìlé¶qU.¹÷ªuÕ&qð©E;¼ê|R:ª†iì™Ã `aº¼)Ã@›—gˆgè.Í•o‡fÕ›•ª…­ÑsËßž0eÑ ½è.2ž&qíµð÷ܲ5]>=ÙÓzR›ÒÚ‰s£qäp+­9+ Rc¤LÙ1Û ½A%±¬šXÎPFdK l˜[¤jkh:’™â1Î' וÃ#Óåcô|*r%¹7xНo¦œ1›>ŸÄw)½ªP5ÝóMà¸o 8žáÄ@þª"YW2Ù¥¸±ÝÐÖÆÔ+‹ª9ï è5TdN6§Aý 5&HÏ$2çã@¦PíØ(~¿¾`]vÈg£Ì×›•`˜hº•O–f~îf¥ßÂuÑçš«±®Ó±€ÐPO9Lƒ!ÈdíJv}ZÏ3Âô#žÃ@V¦{òõÒÔN ”ðYÕ¾·g$Á4ZÈû "x‘žÀªÇú7Ô.ºTäϜׯ$M¯ ¬ê('ö̉aÙ“¥™¾®†zVE†UéóÜ29Ⱥ6&vÄz©h-¬œo:y‘xÇfÌeü.†É Ëy—Ar(Â4ÞQ æÖ¼;Ϊö‘7¢Òãñ…ÔÜ5ùOßCáfsâø~o(¥oã½dÓ‘™È½‹4@V2YÊlëfîÕ5“îˆ `Zòž”yÇéäÏ$ºv—)‘mŽ2åíyo¥ôaPË´¥È6Yɹ’ëç?Ÿ{¤£ cmЙqý²ÊÓóН(¼M87(|¾Ú;4n ´m•0±,²ËDi-É€"Ü*e|ÃHÇáÙ’Éðå>鎖ñ"z”3¹ßK#* G1°•0ps½âyjšb4,kÙ']{¶ ˜4(œ(Î6¹c¥2SžÒ8—ÝJýå_þeÇ­„$î˜# ÁÄQ„» >M¥zæ áíð˜½Þ$‡˜ “É"CUíp+e¥êX#¦’\4&£ÑK#‘)c¶9Põðþ_Ñl˜Em‰rL/oXâÙ‘Á‚¦ROgÇ›B#öaÄG¶¼¡7ÙÆUš¨Ýs/ZÀ×áJÀÞÈÄM¿+^»^`»d|7UåÆƒï¨&nº¼§q3Yqée±{Á{Dm‚ дp½íó8½^èð69¾×«æ+Àÿ,¸Í)Ûjž›ÕæŽöÏPv›NãˆçùŒ:¯S¤L™²q1²cÌÓq|:N<ÛGxÆY5ñUã ,ÜÎ1<‘›Eù釦šrî2S¤ðJÉ7±£ q$X aäÚ·¼šü‘°Ðg¥$´àeá‰`´Ã40ñÓºíI);Îv¿â™oJnòJ@VüaÑý¨´IJÕzå|˜·áøÇã¤Z²…Ìbî8“» o4²”Ý¢+`”ZàLº¶ÊŠØ™½LÖ5-¼^¡« PÍ¿¹ºt‰¤#a>rÏÿöäL–RnP½faÖ2MË'nb†°8%«Fç)¿^÷3ªYã:iº*‹é§$»•6)•êu„[(½|‹kiï5jašLú´´+mмüÅœ®îßò—ý}à¿üNéʬ ÚVpâ42F(Íí¬øþ\µÞ4y&#@Š$N «Î¿có‘û€Èjì6M½ãå.˜3ìúçãvèÅÂp«—V®¼[;È)É:b6ø¢UᛇÛ\n%‚Üê‚3Ú¤Ë:¶L2¤cæöÏÄÄ­7°vàxr÷¹„+ Å|õ M²á†åpkŸ‰ª.+„§ÇÃd•âÏŒ÷£ Èý¦fÒ†²Àë¹Àd›aX© Uõú¼ûƒòþ;ŒÒÝ¥eLU#WA#vL¼·*A›lŠM`¥97¨õà>lGøÎô÷8¸êÚ«&˼%\t&žyz¥¬¶^L9C‚;²•‘2“pxG@u‚–¹e½Ü§ç½-¥£Mì0ë ȧíýíF‰yýËa [-£ÚÒqWµRÞµaïzš6˜&FµÞdy–9abÙOx]L¼©Öà âÕ™•&xǵ×x†½¿ÀŒqô6ða»R]1#itqà›n(àXLFÌÁQnzúHŸkdǘ;šÞE"³%ÆOìhmÇLdâ0} =,ÂJd™4«å Ö…éXK]€¡Ê¨%CXÀ²ªœIä°cŒöd@]•æ†ë ۄ¹4ªf‹Ù øëQvÈ4¦¶æ-G¶nFº|xÚ…ª÷— fâûÕBüôDÖWšLÓƒL§LæX(²&&`+·6ê«"iðŽ"Mí9Ü|J™ ¿¡Ùn¨Ò>dWÒ×^žÃ]]o¶rs;¶ð˜ÖÛCsTºò­±L/€voœMh˜w²iÚŠXDÎMW?ØU3‡Ï˜çQ‡e-| Ç7<_ê¹Å8îæð8O-eb8OU;«æé¨$õ~úï>Cmu™¢Œ7x[®Ô`™RÆËÂÔÄ9DÎín‡Í-kézôµËm•3¿‘‘K‹Û$\ M@&s@Gƒ`ÙqLÓïc¿ÝjLo «Ö h¡T-çì úLμg¥s^cÇJua8d…é.s¼p-¶)@˜˜ [ŒLl *bÊ>Çû‡'˜mnO÷iŸ§£ÒnFæ´X@N™,ÏH¨«? SFÊL ØSr|¥.Žä Ëçwô ¸8x¢f(±Ø§˜&k%š¬'ÈÇQ¤l„¡˜Ö­4%¾p|½›;2`z&kß8-ÍŠÏg2 ÍÝN ·Y9ȶÞl”þrX× [Ãè 4÷¬[ܸIJ¨Öµ+d^v)/͘&îÉàÃLºA¤Fd§å8½k:öÄ@J°˜Hãš‘¸öðrâ|Âr‘Lp‡[ôÖˆ.h)Ý©<¿†Æ~YgJÙx÷wL|,ž Û&’cVã§!PZÆ'ö‰3wÄ-”˜EfÞD<®‹¸õÖUîeu©ôµë™”sˆ¤IéÈD¬7P#çôŽ€ÀrØ>;EæpCe˜C>yb]éáªrãÊ|dd&åziFdè:Öy€F;Ÿ¶÷çBÓq½•+eŽZ¨%¹[¬ñÿH äIϤ. ,øG:˪Ýèl¿†zR”“â‹úç󉦲k?U4e·J¬´ÈËäv† „Æ@UÇÚïí Éd¶i"ûtvÔøÚó^ΡvÕ¸™M$ÐRP÷1½J²0ºý•V «’…Ë”ôHžrs;ÞÛ®¥ö|f èUUŠŽšmÇž®¦#="YdÅ^8î=mKO£Úæ)µ'Te2EU-…ýsèÈ'½–ÄILи€F¥”ÃJŸr`ü|*i4E¨qd₎!ñ@S>•³ðÚ«§Üô×?ŠD°LýЯ”iŽJ›PŒ!°ecrȰýn›?%AWòáºZö6ô;ù÷éN–!™ h ½Ž~ü ˜Óg®”Ax›ÓïÈJ­DFP´0+@¼éó©Ð;Sbn>A+…[Ø@hÌ6,ï8ê’y&4)0]“›cžå-ÓÉ#?€³®¹GJ/2´$R nŸõvÇF뢤Á»2,òð4ÛÓ‰ÉüÃzJ]<Ù2 x¶y¶‘a¥'› eº ü…?Í è¶ÝKƒ7¾m{_±ªËˆ[l˜£R«È”2䔹µåĪܞԖ1‹¸^™#’Œ¸5ZŸ¤#Y4ˆFnFw¤qFnóøÇæõ;AU`dUÑ1Ÿ^ná63&ük‘Í=Íï—IŸ&2MׄUáéÙæ/˜ÙÖÃSTªK&x÷ÿL“L&h dQ)P®½ÑshÖixÿñ†•Þv3ð úƒ¸R&ñdÚ æœÓèL@IDATq+9Þ>Ä妫z,Äð¬š. ¤’´;âz3,[C)ßæñ-°;2é.3ÁÜíñ2^d è‚…ܺ²#e®ÅbýŸu\ÞÉG¦”³•…#™q@Y£ì£A®«{ah]ù´½MjTíÉÌŠX©ˆŒO'òÎùÓLÄè™r7££ ¬.š™)%£.@7U¾=;êy¶óTïX™¬Ä¹–pb%¡äXè²O<ÆQ<7xý¹S5¾eà~<˜>F;€—E½™ µ¤L@ìØÓ A¦/w”õf‹lÖ6Ä<3ÏP$œ?>s@Éþ&ªæ`%/ë”ñJ=@<,4ÊyÎÌPË#?kQÊ>«Àé¿k¤I–›Æ”ÞQ®à¨‹pG]˜Ö^WÇɲªÄ0Æñx=Ÿ‚ìe%çãjމl§Çáõ æØO»Ä}Øk¤Ñ(³Ý~Ž1‘ÝY5“à`ÖZ2Œ©½’¿®ŽSBKª÷£1B;A¹/¿ŽzUÛvÓ³Ò’@µbb «ÕÈ*Oú¢^h n‡áYå£ÔQ бòؼ~ø»/A0A GÖÞ>,üÖFæœaú» ®äîÛ¨±;fE©Z´O‚Ä4=F¶4@@)¼5Ö®ZWUÊZ( Gb¼(tçyFÊs Dn?ÿº¼¤d9%`‘R™ÊŽ:½^ƒädð°à k$Nƒõ«:ůJ<.O8®àš›¦öƽzž‡ÐtLšÀŽZ ¿þõ¯ÿÕ_ý•ŸÞE~ýë_ÿîw¿£$h °¿]—u+ÁŒŒ±¶h$AG-yŽéH ÐôSm\Ô1󜑎‰ ºä>Sü™ú¼3Lи۪q1ÄL`Žäãƒl´Ò®Ð†|ÒW¢lÕæ:¶#>ÏZnOS´Çg«*žù¯×&ìáP ÊH½¯Ç”KpG9¾ Z1œ˜]²ÇùFvª|2IV)¬40q¤,"{ pÏ‘ÛÝÅÐ1[¥ZÒp¨J0ÿÀZöèñÙÆdùìrn!¼ñþ€ñ×ý×¾TTÿñÿ¡‘qY©ÆŽ3ÑÈDö UKú_'þû¿ÿ»Ê×…Ù‹ÒþæáMd#{,›‚¡w̪^8ýÖ”ü¸Kõ¦dÛ“w$K¯È\£h.PW¥Zmâ(”¶ ÜÚkLÓ±)–©+L#E½å Ü& "F —rÕóèó•³H4_)÷ ëмMðŽôyîˆÔëÈh£*TE $P²+2 €ßëÊè¢L&7ˆeá<>¤èå´ãµˆ6);fŸò;ÌUj[¿!ó›ßpÈ'>!†Æ&ÚýÆøÆ7¾á—†5æÿö;ÿùíoûÿ=Q—F»5ˆC³LfNÉ­¯7$,O³Mæ³[0Ú‰‹aD³XMsW›Ž™˜CäUŒ£„-¦%±ÜžÉcÖ«´FØVMtã+idâLà¢*iúù1êŒjpjd?"Û ª6rËÕ¥$§×C)7, oKÛ3ÄèUÂ8Âû´ŽxLXnõi2œ&WÍñ6á»–X(‰ u¹ Ð.”:*ÑÃ2_öþÅ /™¯çÿüÏÿˆ³r»cqý¥ç†ÏLïßüÍß|ó›ß´‰#AÎŽw÷ÿðÖþ·û7Ž.KÌ*ÞGÛH-ƒUï}b(ÂÌk¾÷½ïµ &g&?ùÉO\VÆË9|.øï|G©czЉe˜¶bRŒltwŒ Ï-O›à= —å–¡|ïS#RË.è8~žUÏÀ¨ÚtÆTÒ Ø¸jÃZès<« ´Ã2ÕÀ¬ª*¥oŠ|w5ݳz 0Ƌ޻ð4ñj!ó á'þ€ª½ÄVíc¨^¸é~„¼²¾°Ðþ‹_ü‚ƒåŽ&Î'€^ýo}ë[|üðüìg?ce´[æ^ m—µø}âå#k¥F0ŽãÃ@wä92[ï ’/ #û‘sÙMXÀÉxÚ£½.8&ÿ0éÇûöñÐ42©=q Ë·R©ª¬ÄP¶[šŽ•úŒðH;´FÙ†4°ÜMÁÀª½!½ ¯w%‘€:6 ¯n/˜ ®”H@TJ™ àƒÀQcU@`ûA¿aΟ"|f^¯þ$]—LàcóÆ{ÛÜP¶"¹K©ÂxÏ¥·Ä{é4BéW¿ú•?’0¤É ™Éœ10²ìh Ëÿýßÿ=^e&^ýî’•ç韛Mü—ù—´/\í·¿ý­ ÙŠZªö`]bU`í‘F$ó#71Àmï¥Ëþíßþíô?ÿùÏ™‡ì³îé|ˆ¿ûÝï~þö»Ÿ¢d¡§­cð}<I Úò‚¬š'±–3à=‚•*M<ÁªiúS|þÀ$ºìÒ…Ûö°X°«9_L$%2F¦Çxd –d"×Ò¬J1ŸgUÂï÷lëâ†µÈÆyѽd½ô}¿òï3ökak7”ŸÞ•"½ þîåSbè%á>†ékÛA{OI;€ÄL¼ý€e~úÓŸúGÛóá€Ñ®ôË_þÒ×'æn™'cë(¹ÉZda™@̽UV d®ÏŠÒgäë?|O÷04q¼.>F8öÂŽxŠŸó»öð}ý·’Ü>Å0wô|¼‹HÇ^Jžš&:R–‘pGL&)‘ÛSðÁ“Ùú0ª•^ÿ¦C+*dä’aYOãÉDýx$™Ü׃1Éú2Hœ ¼Ë0Ýdé[#†+Ï·?‚[ƒ¬ ö õOnt;x¬ÄýÚ_{›e†€^?]ŽJ><ï%`“Zd¶ª˜îR©£)‚¦? ÷' ß~„ú9Ô"šE&`-²Yæ6Ú±èoT»Ô›{ý¸òÑ.«*uì.‘+m7 ¥Ü«fº<_óøæö`=1Êá˜y<OÕ׿ã?B¾. rh >«a>˜žO×ì3ýào ûë„*Y]@ŸEækl%-ª˜Oÿ Py=-ª9Ó²#~ŽH÷—ÙiÇÈ/;Äc´ÈéUç³÷Þk±Þ4Þ 6b-Vr¥Ö&Μ™ÒD€²M\áÿñ}‡!u±íþcd⺄F %[GŒq}ñ;{õ½IHÑ,9±Œ”côú-ñý￟X|j±µ4B6qoO$=‡J€# P¯M0 +¨z¶÷w§zs?1¹É¢Ëš¢Ô¼_tý¼Mü¹ÑŒÑÚ˜v“kwGÀ24é-É_0G*&˜¾çÓ5U5Láw¤a¥2 zþ CÊÑO°$YƒsÄ0MŒ'†e;xXf`"ñÄÝ<7üºÒ8>ï¢ïãÍ›þ’oq¯…ðe?£#k1³Âl í»?Ü ÖN÷ÏÿüÏûô‡(o¿Ä|–ékÁt@DzP¾ò}rÓ¥ « Ëí?7µç~ô#g®ÑÛƒ§ïRîÛ¥üvK€QòØ“ñ×Þ”Äø ¨ ¿ñöôÞõ/ùÇôÆ%[»N£µ ]5ºõç?Bž†~ízM)Û-ðL>dÁ' s¸+Ää`\›Ô˜¾é˜Ž ôŽ ¨º‹AŽ4°5þÂ**«:õ'r¥@ó’Á-§´-û™i^&ª@Œ<\»c퀗ÞÓôÁm)kñ§pß(~)÷齯{R4s³µ9Fci¨ªU`;øÀý'`#~üã÷ÈêÒ1Ÿ{·Üðþ’ÇïC™gÒªJ˜Bc½üc¯>MŒÜW/fÎïîO¿ßÉTi Ç‘vJí¯d¨ªŒ¬x\~Yõ㺀<¿µÎ¢×»»F‚žs-4žÏÛv -ªípß/h”ä.•tTËö7%qšpþê¢ÑÞ“ÏGcÕ2Rèrä>ÿ@à,³ÃÙÕ‰OPud[&ƒû$Úo²ª2>+K´\wðêûM*Ÿ ÞAïûÞGâ`¶€Åºƒ£ß”H¥Z›¢ ôÛ™@¨–•|ŸýÓ?ýÓý·fùÚn²]pM¼ù¯Ç­M¼^¦JÞ˜Q­=7X–Y €F»X øÿ|ÝQ®4MR¤áafXÛÁºûšŒæ‰|ëØ‰Îú—ˆö077÷ˆŒÌʪóuƒY Ÿåã£[`Êi.Å”¬Õ­½!Ö›OVÔÑ×öSäwpt<þÑÆãÛv£i¥nû×%º^Œ£J¹úY°J„ÁiBžø\Vàö ¿-±8>Χ Ñ”“¶'¤¦VôN¬îy‰sn9ÉÝÄMzzèg…m …!¬bF>æƒC®ï|WÂSÿ>ˆåzÅ÷ ñº_­„t¢ošðN?ÇW‹8«ÛãZå3;ø·û·÷óÏé÷ìÚÒ0[ðÉ;:ýó}Qqô}ëà‡N(އµüFàr£Ù˜p/Bš—U´t8ÓLx"M† 4..Zó¢S††ã£¯DÓÙ_þòns 8åæ·çùF:hß¿\¹ÛE×_Ãý4B¡Y‰®#„râô[ˆ±-‚ ˜"pXk‰‚h¬Äh¦­HÑ»ÿ÷ç’å@³tá išJŠJV ‡ U&‘%ò[ B²8^y ΧÞó£ï)‚–8˜ø8ñ-Íc¾î‰»œ¥‹êÜk«¿zMÓK‹Çvƒ&qS¹ÕMdâ²D]NŸ!ûò g7@‚%–ÕXüDRˆÜ¾©È1ÞüZZJÍòcZQ¾)§+²6€µ ¡Ã‡xÜøí?ÎFn&‹Ì_ÊýL¡Àœþî8N¿Ë×ÞJg‘ãèkÃb[d"ø¢pÈÛþ ZÓt6Šo!BE…*Íù|(0ÝZaMÒÇ {èòI°"­ÍTÇ%JÌ¥ì+ãëÁÖ_ˆó‘µAd¹MBë AœHŽQ®1gEE=õ÷7m0wΞý5o¬„h¹Æ‡{Ú&‚àÜÓé‘&ä;Ÿ ~äF u>5NvZ|¬¢Õµ„{XK¦t”ŽlÊø@Fª1ΑhDŠn ß/?=¹;‘åªU"ÂLùù>ô^×N´÷U"úOJÅïþëœH]݉ªcr¶35 ÊÉRà·´M%²¦FFÇ(— Ñl-Æß_m×rŒÒàÉ5uúMíã¢u³qäê­pú¦Øþö¹gg‰ZéF¦GæÛµ¢mƒüÒGHEÖ=ɰ-ujß§ßãÊé_‡ÄµQ! 5MŒ²(óâëô#Çtú=ùDRWVŽÚ“ýÑY3˜R(@Ê•¨>«hOwSEás’ªU–…ÀWÔ”ƒÆ€!ž;÷§_éúß ²ü.4¤ÛâòùÆ_âFé~ø/ÑX]óíÈ=…#ËÒÛº…0Kƒ%‚ÙT:2B‚œš99׉O’ƒœ~Sþï¯@j´ÑPVN¾PSi–ÚEåŠ?Ž©”8MœB§ÿu z )#3 zÕÇ”?ñ6nI!†ãô]°ÒëJÝšéͧ(£ã[¯¬”§SEc+å´-¤˜‡Ÿþ×§¿¿—¥fL$&?©Sì¯OĈPuµX`‰áFíV 'Rè(D*A|Îÿôòãý9k{‰Ü&·(Çwß×åÃt y$y¨!˜"+=) i8¿æ![E¾,ȲL;⥴?qlW¹¦õI¡Òð!ù8§NœQþij¬0¿üNyµ‡p ‘ Õ¦Î™¿¨ÑÃãõþ-êGž?ÿù϶¯ŠÓ7%’¡1¾hÆGh#ô .ò¢¥Ù Â#s"žXÞzëí®"Ô´µlªŠt?û½ô{ü£©’IlC\9~­W—GÖ ÇTŒ¬ÆÊrûA)=~)i–R–¡žùSÖar¼¸CDgª8»Mij^o‰7.$‘ˆûß7·¥çôòC_:-K Ü8 )&Nͤ^ÊVA 30eø8·)&…áðË2å´±‹ž7Z¬KR¾é$8M·;•Älm¥ˆæFâ°h¢Þ˜=;U oô³ƒ—»Ó¾#—BÕÃøÍÄá“5å-‘pé¦ßŸ9žÜ.[‰•–B-uY…B„<ùèH0¿x:ýåF6ŠE{™1M3©OöšÖjãÄ9©!ß~j@ÕK1¶4Û¥ø¦mÇï ¯×N –à@ ³ª¯1‰¦kïû_=ìB£ º®äšÖ‘]‹šAc4Ë ¿Ç% D3R3]o¦ùqÖ0æ8Bð§ÎçÑ–lš'öJF]ÇHÌ4‡Ad15VÆGîœ'õômŒ^_À)ñÓ…˜Ò™tdÈëN TÃÐpz®Ô0ZŠ@Ðz}òjô‰ß{‹éYÏ£Y“²¤C$rÒ4õ³ 4eõÃÑéãçÓ/SQ´=Mø¤*$jzrÇùˆ\Tˆ ¡€€ 1Ògqš‚ŒÃa•+K´Nôÿý'[÷°­À_Š,ûÐ\W>@^;‰ß?›K!&©a׈A˜Ƙ- ®D|Ñ*š¶Š'ã³{ A0Ö•!fše¥–²åä4ê ³—+ÎçÚˆ6ÞB+£×8D™e wR9Õ.';×íÿþ_»ÿúé èÙïà´‰üÒ©µàB[¨Ñ7ÑüÇô©"å.ma­MŠ<±|jÿôrþÓ7 ß¶Cä²ü”ùÕ­ £eúÞâô«ÓÛZ?›V×È„YY5°(§«®"ÿµ.Y†ÃÇ9ûû³Ã¦”#Ä1B¢ñ¥,1Ú:Áøå'Zí]5ƒ@L…ÊâàÛÈ·ˆ/Qß?ü»üÅ&šø–F9ž`EM×0'°QbÖ´ýI>Nk4ÝN‡ƒ‰ +>gþÄõ#שÛ=iz.F9…MWN:Â=ªäœÕБxnwé“’8¾¿?ôVbãÿ÷{û—X‰ðê+J¡…‰n ¸g0Çûè]¹‡J ¢l+Ô—º™[È(ÔÞIä‡4öí¹• Ñ÷©åÀÌ€ Á¹ID"GnÜ!àëð¡ÿî*°,¸(ƒÔ^̦&šf¡ùJô„"…ƒ)TÿBøïÕœþž>»jåìR.×XÃFÓÿÿ-„³–(Ô˜NtE§M6eB¥ ©VmÞcõÓÁÀ»É¢«˜¬‘µ] ðVÍÿ| Tu•LÙB z£dN&‹Sˆ#T[ø¦žÁ¶ f£­÷’xY•+÷«X™Oߥrÿ8¥ÛèžÜ¢•úþÁÛçu]ÆÁ´­ÂX¢!ˆ¶}륜¦PÿÊMÑhðR9 Ò.…ƒ_h›%¶„I'žlRùƳðq—®4…lþþ¥F:ƽüô´–˜Èr5Àòì÷1¸ôœ~ùÑrü.Ò.)ÜkD`ð“ùó¤·"ÎøEuB3©µ‘~âh²ø¢œˆY‡BÝ@H¥O¡ØæVá¶R]><­Ê˜j% ǑȄê¸>åï?šxü·N„,…²èh‘Ï 7fÊáWÔÅó)TQQ…â Àý™Ö4fcW=åÖÛ(ÚqW:µ×·g—Ü'ÏjÝkä·"|¦±ê6]4ÐTÿ•S‹cd-'‘Àü²–‹Y4qÓ{±@QÆùÃ'wO‚cú öÔh+ÊåxÛü~ùñ‚—ŸåjûÔ»º|'ž¥–Ÿ,eN­5Í&h,QoeŽRø-?Ó¥êâ“âqèœÛ—W>¹xÕ3Š"1ÎýAV~µG[yj|Ř¯M¯oNÀ^ë>)%8²ªUW¦Æj!°¢¦…€¬Ò.Ø÷n¿x HÁgäê†ç ™*íôß÷Wꪋ24)¦Û½©2eOͳã@£kbÊŒ@-ÄFu]ÊÂL!‘²âDŽ â+ÐÿôäNAnå8úOÐØm€ãQâŠS‡FÊ632+DDé:é°š²¢Ñºè'ï3D h^iˆ©ºlM ,Ë´êÃ9•Fàl¥² ¢ÎU¬ eÖë¡ s¬­d>›Š\ÌšVÒTU·1f£‡¨‡ÐRo£·ÎuB§ÞpªXÑ ! 3„@ˆoÛ~²¬V£,oÍ,"wjhUDstî긯ε¡í‘Cêa >:\¦ŠZ~ÍhCÈh´Á†4M¡4-ÄÑÂ@¹ýï—ŸÝÆ©U‘ –V ˜²EÙÉï[È›¤—XEK_4“•Øâ$^‡8-‡CĨ„89F8KÜØ¾-T4AÑôãð¿ü:QKJœOs ™hK p=åKæ@’¨û#ÿˆšª!!Î|S'»b½…?ÄsvSûnc‡µŽ,˜¦À‡hÆñ¿_ý]õ~õES½fê¿KU'GÁ·ÆûÛ3~?ûTÒvç§–8ŸHH…Z`ˆ­íBKd|N%8ëJ 0)¹¦ñçAP’Ìö_QXišýò#*¥6€k M!ó)ú} ÙI0šD”ãÈb¦RäºâšSä?zŸ#Ø34F„ï»x«™ñ3!´dù•F(%f;fÚ7~¹˜í-þûõÎ\IðKNZQ83å#p2Y¦ÈE1ù·iEºÄÊ IÌš–©`+A@vñ¼°z­Oyµ<¹»®áFïþbÇXçD\*â}Å÷òzåõéá w¢m0üJÐY.Çæb µ!qd Í…7Jg-œç³Ê5m”^J¡|!Íð“’îàÞŸ`h¬'÷” ®§)3ߣùIý öÊn´|Ñm…D~ïÉBµTši–80gxk7­=>æödN𦷵À[?²Y{R.÷Ü÷üžbDZZ¯ r8¾tßY|í \B‘9L.¯. ;3õÒŒ3*|+O”ßö!D+™Tpé98Œ?~ˆ±§rOñ·#'íI4ºÀN¿/Ó˜¦˜¿_~üÜÔï6zÖU‚F×ÞTlÍCœþJ×j¼˜ókøtó³ÔÐ1Ŭ(ç{.²P4cŸÈ@œÆœ©á°tøé<ðð³B6Gõìü§…¸‰X¾¢]ÇÒák‰ïòYz+ð= X%L+¡-Ù´”ÉrÚCL!SÆß(En¡Ô„L“¢Ü”ásòMYÓÆ4Ã[]È­O…ª•Aѳ鬘î_’F Ëf*‘o„í]…êmgM»º§Æc¶ž`U4î’,Eˆ ¿,~ß̼ÎkÌèô»Jiì¯ eA꟣16$ÐK³ _nüþ© ë o¬4ŸÕm ' 1ÊbOüwP]¨(_ Z>ûÇÈ*$…o9@)Oð“͈óýGwY½üœª?V @úü¡ï7I·ÝÒf]Y¯©Ñ{f¹p§¿ö( Aâ—Ò5*Î()gñkB–ùÈ»ÄàU阉âàÓÉÁ1UThʉ>ò„™VŒ±«gÊ1ZU•†p2xe6ý‰œÿôœnÔt©ŽÄÄ·Mt€3)5_È73'Õ/Ùíñ¥ÿò#×ÒaâK¤ÈEëMôüÑø¯ÿlì«ó¾c”^?]`HFs» !¹+òY¥9âJçÔÕúÁ¤¶•¾ºE­ÂTZoß/?Ò×Ö ÖƒÏN^ÛtTñ|ù~ùqúêüÕêÓÑç$ì:Ö¤(„U4²BÌ=€ª¾+U:‚¡Î40\ú¤8;±Ï•+AÖVÍ)—ÄL?¿HŒ·ZõÁ6Õ Z m»‡ˆ{à'ïü§L!˜Rh Œi¦S:‡Å·þ4ëw$_Ågß/?ýÙ A¢±tªbìbC4ìÁÿRpyzàÉ=M?Ư“]žÉŠ ¹ ê3­„¨n¥ùž¦ü³OoÊ™t!£iR¦SS̲8zàsU(ñï_~| ZHR’K!ƒWÔ”Úk+D½>õ,¨a êJ1Z D¢ôµÍiù_ ŸÕ¼Íaùµ$-Mº»Ë˜ø“úÙ.úhBÉršÖíP3œ|)M?OÜ&Ôc4¦›¨òxà—‚hÌ/w Ǩ•”åim³ÖŸÐD¢ mµRjÂñ_f‡üå/Á1åÛ>Ÿ×íQú®:5ÕM§V ^|Í|ÿÙ¸ß:ð×ê²JIJ –Dø#‹cÄÉF(¤CÌ…šn䌃¦D†C8ß/?-!“¥£Ó#ÊL¦þðå§ŸNÉ¿~ Hé3áQúÜÿ÷wH\Õª®D¸æ=k,šmLSÈ=f\:)K†dð*žæžöb¶-üé 55b)üoº'ñ ¨FhH •‘mUøÎ_ ŸS±¤ø¾ªÚÁ@£SâR‰¶œ;—o[‘E5ñ¡üÿðVõ_ÿõ_ŠÚ !„ïW Óo×Z …•€ Ôg¥=ðîWѾ:—µã•Bu+]ˆßi’8$š>…ø4YE9ñç¤<N"UXQ%ä†ß…ÔUåû7ûý„Îzã/—Z¾Áf¾~FCv u•ðYR@—©ÕIÇJ¼©Qç«ËaËzÄÎܪM%¶^£ÓYkÇ)T¹dqL‡T1M,ðsmš?äÏŃ@bIä»á…4”Â@S¡åx·ìm®¿4¹ñúã”­ë —è“Ý à\zõW½ã%‹¾ã[.~ækïîÛ)¶=¢ Cæ}÷õêïÎéaü'õ¬eéù¬fš:È#˜:µpˆöFˆÉ3 M¦ùê–x§‹†/ôýäöòÓï8,Mmäè\cüBF{ò‡ßl»KSz Gñ9OÆB[‡¡QŸ‡÷³pS&¤ydB>¤¬ž %.K”>“"ÄZ8$N#üa¡ˉÙþ1mŠ€v>k oLq9œh˜B¦’!|  ³Ë@ðý;dSÏ~>šfŸ @HåRKJ!‹øÎ¨kéµÇop]‰–!Ñ3ïõòCÁ‹‚Ñ ™)P-NjÎ ä¶¾:w1AFh-¶‹OÐ(º)BG‰òM³DòÓ`BL‰s2!S7?q'Ùub‹öp†ûå'ñºJä³… ôhCžìÏÐ-d5ŸO!ÿû=âIÕ|å´]9mCL–ƒé UÉHªåR4"ÀeUÔ˜SÝü;Û¥DL‰@cýp¦@vôÕk—w-¡HUB…0ÓùåYÛ‘ÓR‘MK7ÖŠKâñìÔzå@ð¼ñ\÷1mý>â¸:ArÀýñÅK‘{/l¢¿tþáÍ _‡,’ K(‹cºfZ¿ àÓ£UŸ5<&×§G >¬Dݶ¿‘ÑLSã¨ÎéYnº, 1Û™dãË 4Í7íº„ o!r9˜p4 ù¾­böÂ'˜•µ±–ŒîŸ×'!Îþì¥P¯”%’²v#<þ4ÃBí‰>CíÖŽY™¸§³´Åb"Ф&³ så—¿B)×’Z¿ŸUBÅ`iqNÏ=ž"4¼ë]täNÄqwš]_…ý[G܃¡¢UA¶ÝÎb7Œ)Y%Œì>ñ^¤é gR´º9J`¶S¥ÝcËå ôòS!×Ùþ˜ÒÑÀÊñYå&~WÁiÊ)‹¬‹mùFmÔƒr~Ýrj­=Ž,)8™N8¢ÈBL{ß·±ÛÞB0åªUiYøùœÖâqÓU¨“Æ®TÇCîÎÉV”B­I±Éæ×€•*a¥Öû°Î¢4é3)]”U‡h¾VSFH¹åÛ‡8z`”Mç2æˆ  ±عË)\=x¢|¡¦÷(äâÓrÍtÆøÈ¥,·ô r™Y)Drj€‚.ɦ)K´gƒ-ã§ãÕÈžÞýð)øL@È7æ¿hM·ÆE½ìú€ªPcu¡-ãÉ2ˆ¨“a¤)„Ã6mÉ]?‡À³ÖÍã¸û|#âŽ%ë¿O¼²(Ô''Ùœ@ˆ{Øûç¶~ù¹{(Z.Ÿ#Ê8útúk`"ó*h+ZZ|¾”Ãä7ŠL¼ÑcN{¬Ë×qG6µRÿÈÔÂ]eÛîf“B_Å4ë-eˆÝã7½G)¦•3fË i-]¯Ý uñZ¡´ÂÒØìùÏ8ŒVN­;4r…ˆë[bU×Pšh޵©©ö‘C-_¢¨S’P–'Ê÷ËΟþô'Z"‡Q#žÍwÿxpÖF£ô~쓈”k\bS!޶PØrð8nW=;ýrPƒÈp {]ùû¿ÿû6ÐzÇÿ÷_éÓŒoš¯(ò÷ËUì/h9ùÆÛ ZzÝB@Ú‰LcšR3…k€c!.7Gc)Cˆ›´Øþµ\·´ÓŸH›ãëŸÿš5K0ºß¤ÓIœ‹ÌQ% T¥ŠÀÛ²4­%N׈“,ä¯Uâ³$„£VÞXHNëµ$­3ѺÙf)c:é4!8øFœUŒ‡/„³í®«Fg·D´™ô]B:N´rùãphêm¯I ygp+ …Й“ßÒ€9tÖC;;©²ßþ8 *šzÔõx–ûÄÏ)Ù6:b zðìô?NýO³©\Î÷ËpÚ„7nS:9)¨îM2ÎFMêA¤¶r·d¸U— bêÙÔW;>ÄÓÝ ic[ °–hz¿ý»¿û»D< {IDc)s$®zK§ÈÖ*?Á>S4uéœÃ€ç?­KlÆ‘cV ÇH‡‰òEÌ%§ÙÆ-ÔñjyMŒ#‹£Iίï@¸Ír>7º`.[:O Õª\`E9.¹—Ëñ‰ï•L:}äêÖÃÝ\‡Ú®óµD3ÚÆz ìYè˜*qÉˆÚ N Ø”,gV{q€Ñ8µT¢·ˆÝ3KìÉíXCÖŒ¬ SŽÐaýÞŠý \9|L=p:=œ¤€]2Aë>OÙåîÁRnLéîUŸT½ Ò÷ÓˆOEBÈ#Õ€(…¶¨Ò¦E1»ME‘e•r$ž6Ek*wšçC ”®QíH«ªLiFœI U “4fÇ/„–¦('Ø'F¹UœoŠŒ¢Å-l )—öû·j‰.¼D&±>ù;Q~j¨ïsãYÿ8jÍHñw1äš¶.~ScûðŸ'Q«½]÷+° ¼Ý@¨PÝ"ß øí@R+ÁÉÇÿ~ù± %’ª‘6ÍÁ’x_Êz«½•ºK»j•–ÎI‡‚iÛ"e ¾—onö6)Ï#ÿë ´ÈÆÔ8iú´@Èuq9‰(‡ÖÈóSCà+Ñ‚£VŪá…Ò±E…€ŸYË)- ãÊàñÕF™å§;f`:h)Ѳ[ …øéç‹r˜DScï‹ nôÑéq’Ž-_bš òýú$·å«·eqزª55w2)øhÈ@Çð8ìdÄP¥¨1'¾Ýp=z]® ¾s¼]š~QSm|?¹éÛ²‚ƒ_!ÓUliBômEšû9)†I§Ñ”nä{ê;ýá¦6Ó³?…{ªùõ <óuÙ{,áû¤THcYÑv†/ÊGàò×­]Æ1Nç|Ou*Y¦˜i ºc%›._n)nD•Á_O8°*OÐXÌŠ\é4=-^O,LO/?Œ‰­ízq©¾_Ÿ<8éø¸°ŠÈ:©O£¶[fͬPM®ù¢štú‰˜ÒüóŸÿ¬I„diÂYRÄ}úGïKB>òÌñ Ò·£Éê¶\‡æUÄØeBæè™9²¯—Ì^~*¤Ö#ðy_’Rÿ@:Æs+ê?îZôÒÇ/œš‘á—˜o\Wp&…õa%ª¢±ëX3´¥óãmŒ Ÿ*bú9ÔŸ_BCÛ ¶)•Ê¢ÅI¢Júþn®JáùvBÝâ|ˆ§ÒjU®Ñ^—Ré4m·¬[ ¹ÃEùšt©–›ãÁéóz‘9Ô9BÀj 7å³¢ý¾ÇZœ~%î£ßYÇ×’Ñcï>Í}ý­¨1A†ïSåûådzß*ÚÞÚ–X Yp`SÁïG‰¨[hµîêº(¢|·r«pŸ[/r¦sozB '“%ʯŽi>Ú'óù½9îÛϯy‰5OPb²tX|#Í3"Ј&ëÅ Œÿy·©-Ð΄¡ÓåÐÂÑ"‡ÕB¡(¿@“k¬°éVd¥s²)HtJöЉ–í#›Žê–/«êuÕ£Bï$?Ùç?)”¥çD€µ´)~8'ß4_”ßÔp:CD½{ö§ÖX-~o>û]r3÷ ž`µÊmWûJ¡Ñ#Ómciîp²) q¤W‹¸)ŸˆÍñø-?ÅzïXŸÆtl g`—Oç÷é—îô×jm—^VUè³8¾¬jìr㘢±S`;SH ÑOÌhùES¨t~d>+øy["-@…A·T`Šð„:ÁœœUªc÷1§\ã “)מ Õ™1«÷:@Ž«ëñ_'q_ÑÚ KÍXi‰‰CHÝÚD(øñ§öâ'•O‡ÓÎŒbŒÙ(Êññr½v”‰·øµ‘¦º–ì_w#Èuˆ/cw!xYœpOnf:£ì †)‚gs»Á‡3› ±~)BNÿëäu át¡óÓá§fª+÷ùý:JÁݾ*]ßD€/§Nh~?ú.$ÝZjÛ¸­“HM¢^'>Bý¿XöpT¥B1!|fÊâX x´ ­ðÌì!žÜ°hF™ÆSêÙ/£þŠJ)”“l:Æ'ãl1Žg•k0úDÓñKQ޾ÓϹC|½²*ZµºZœp§MÑ—‚Ç^ÍÛMÌßMy6Yn‚q€iVB4š_úïï”^º9eaœªóåº[‘÷ñ2BŸ4ÝTñ1—È1­É:±÷ÁEëåÇ{ZAX)­‘BŸ-pˆ64o½ñ ”~ã:wì2:øk)GŠZ‰äèÍ]!K'~Í ´F¡LþU¥þídjE%rð3j¦]ˆá¿÷ɯäÂFZ ­ §å–X¤M·ù[ ÜÉj×ð›BT1¶~¹6å~²’bNXo|:Ä)¶~0Eáß)Db¢áårZ©P‚pþ–ÏgU9Åž?¦Þ§ßY웉ҢõÀ§`ê!‡Ü£ÎeóAáçð ‘Åyä~‹Ê1~¿ü8µž”—X«F&ÅH$‚)Ú÷÷¨¾?´áÈh®…QKÉò)SWÄ™ó¦w ü˜ó×›^L‰"ùR8‰4µL;ÿÑ8ÿé%ÊcÑsÁgÂtnN>‹Ò†ÏC÷ž“€Ìô_-þ˜œå#°ö~n€ “¨!F*À,霙tÝôJƒlÚˆÐ2„HU5°\Qf»¢À¥shvñ¾_~ºð²âO_¡á¢²Mߟ¶N¿“ÚNI‰YÝ»¸Þ2Ñí ¼Z^@_¯ÔÎtÔÞÔ\]/ͽ7»Ø^xœ:ÝüœuÎgôÕåÐñxÝÃ@'o…"ãsl ¡çüûåG~²Ô€(÷™Úàäk  $JÓoh¯¯à>EýòS§– -|ˇ´9^]8·ÑQÝûŒ{ÀDÛ-ßB^;ã™èq ONo_h¤T×vmðKçÔƒi‡ªP)ç^/ß\¸ä„²ÀÆ–¡’8¦ ùgç~¢µn:"ÈLÂøp‚cŽç‡ç6¾Ý‘'nÔ~j…øBß @7€q¥K„pT§Æ©C 'q!NQ‡£7œŒ¬ÃÍOÙÈ:ú½{tb<õ‰LS•–Ò´ºÒ_ÇŽ¾'wÈÚ Vœ;ÀÊqàj šQ Ï‘MeñívE™ëñÜÆ–å*¸Û…€ø@ŽŽ¾5êÊó¨ÏÀtŒŽ¾»‘ ÐeKÝÞîl¦ôî@Yz³ 3ˆÇ‡¨´rH×C ¡ÆÃ9âM$oaÅ„Ššr°é²¦ñùr‹ZáIxLôÖ„A’¥cŠl𠱬F8Có¼éyyGí kS뤳BªSàÛ²ïŸì5+E-Yõã2ÔR¹é‹âÔäZ ñºÿQªtB.KÓ; ¸´®™Óß«&q0Ié–²†»ØRêÐSÀáCžQHJÍ×v>Μ4!òú˜ÚFï`BÓ)QѺÒO Aú(~µ¡¥ë92&e ©”MgÙ–`æ¬[/ïuÿùŸÿÙ× 5æ£q> 0}V ‡Ó¬4„q€¬)§UTHÔ4DâçøÎ‘V*^i!Ô8Æ8!GFà§ *åÔ.¼"T-Ž)Ð:/y·N¯×‘é-e"¦¢Ý™n€—ˆ¨ƒ(ªDd~×òtö_´9h‰@âK÷ {=SqGÓ…ß¹ÇtÈ5Oë´hÇ=Áv£6Z—ÑT!µÜ`¯*¢Þˆ´dNR5™ 0 ßIz½v Å‘‚Æ5@3YHÞuÈñæÍb¾R–˜ˆiZú¯iÃic1qÜZN¹ûMÛ!VáylqÒ©m»jKqˆT®EáD[ét€‘Ï PÂÂÛ…ä¶;Mã·õùpÑŸ‘’%šŸÓ˜¸9ßœ?—D–iyìÝ×ÒýV¨rMÝüU‘G¨ M‚®ð6|‡²uÕ‘N'‘tŒ)ç-ˆ¦Äëþ„«è_8ºlÈ.•cÚ›`ÎtZlÝv]%Öª)߇LYáÆn§6ÁtÑd! r´DÇçÏëƒîÕßy’"Ý”qªž#HŠÚ뛘7Õ2ÅﱘlþeÊ÷Fúº²êü¢µÁa=5\)¾,!޶p!ú¦[é:²tŒYdü¤BŒŸL''‰%çÈ—Ã*)!|L •75š²üøý#kÊðCªeôä~ _ýö*õ´vúY 5¾¢ÀŠêóõuÓ-䈃Ì"[]--ä!òúÊZ\ |>¾ÜîK€µÇ™Çyõ³çfäœÆµDŸE¦i:½­e:…ÊhÊ>¦KôoJ®%…[ä¢9£IaøFe8F›¾5„ãCäÖ¢ÑIú~¸z¦zè€Æ$È©Ÿª„P«MÎk¯qàÔ„œ¾[ˆŽ,cNͤŒv–ñœ08'qç²…D3îÛ-ši´ù혱,ûÁˆ“ñ+ˆãåçUÅk±/FШŽ—:!ep ÑÙ}½º y½^.>¤ërW—Ûnpþp±öŸÅ$Ò*BjÆHĬ²Ï´E9tÜKp~ ¦rùéëУÇA«b!«^ÊÈÓ©>‡!°ß× Pù‹ WIN×ïä=Ƭ6?‹á!žærÚˆ`²£—¨Š'Ä÷õ?³«"‘fj‰Ð‘.d¬Ÿ8|‡›ÕÀFOf*…Žê¦R¤3åßS )²›êõDTËѤ9|8Î1ÅÙØ®B„XéÕýè=ð?ƒ¿Zj£û'ñ% Aý]C¼ºx«–K ‡#«|&Ý”óhœöëGd¸»AbÛŽÏI$M~:¦õSԾݿȉúRg$Åh.1¿6íÕ¶k¸t¥r…Œ«Ë×@UDK<¥ýŸ ˆñÅJ€´ÈBòÉÅéÁY)᩹_·¤¤¦<…r×(‚'Öë×:Q{ä9ŒP­Ös UÈ®ˆ·ç85ÐHÊ~í™XKÈH-™²9Vd]^Ï8á4{ùAk[£uÙv pø5Ì(+šÿýÓï—7Onã´ Yó˵.š‘×÷›ÓßÎp0YÕ‰°Ô ¬Öïź,¶¿,¹4'¿¡Í4Jy=þ=ûm¦¨Á¸'=5ø4…ÁSæÿ…Ù˜@Ž\äøF4«ˆi¬[Ì©}~-ºpɦ+9Ÿ“œ”]ÔEñ³…¨Ùh#“8fS4ŽjFÛ\3Fdo>^Ù%bŽ&eËã µRRƒH±G“šãú‘e ¦#«ÄJˆrò»£¢ÑtªÔšZNšñíÏîócâ¬VÌôÛ%âJ|¿¹Ù¿9¢I¯‰§ÅŸ‹Ê)Ôèäûç/ ^üZ_ncW§>‰8ý:¹/G!Ÿ!@äÞ!ùÈvé´òs?¯·]5ú^Æî­³"w£µ1eñ7&²)ñ¢ÈLEuºZH""‘«4 ù|³ˆ§ROšu&g ž¢È˜ÑõÚ¥#à3Ózå´›B6èuÍ\°~^ßøŒ”Œ”ăçëöÞî'ï ž^#S ®™Àh@âüB½G!x£à×ÌÆ½—’ÅtUcÄubL0ŽA–¾ŠîØþ{âÝu+!äAДüE‰4]9}~€¸K}ÝÔ rf+Øúi?… :ñ/U÷£ûjáxfÝ3gyÏ YTbSNHÊ­Q?÷{£º~‡&+ŽDNþ*¶ä¢{SÈÎÜ @ÆÄ¿§iV÷ÁûÍÖŽí·¬8‰`š¬`f*:ŸƒcŒÜ4D?ÄÓÏÁŒœžŽêÍÎGºASçìUØ‘õ…NËÓÂá0Þ‰øZ7Ú/¸ZU¥<_Ô§í½A8N¿ ÖÎ"¤¹~î=’-[Vå/×õ.QQ#ZÌ”‡#ólñ´­½Qø¡ÓbU_"§CÀ©«t"„$2YÓ‘âØF;à%Ǔދ0£3ç ªûtw.*DZ–š DÖ§Íôp%2Nß}ëÁ˜ÇîEƒpôÖéw}õzý‹7*g9Ö¾ÒuU?¢¬•ý!ÂEÁg¦”é ÔÆJ‹R+k~=Ã9«•S"f:Ë¥ Ìî”àñ#œ'R¼ÛǶŕ™¢}‡û‘Î+»ýÂd~²°é­*5|ŽQ´sӦȅLÖ§m‰é~ϼÓÓÏÅîJK©Ÿ¦DLÝZÆÈôSn…ÀiæLÇ4Ÿ“2§Š‘ù-ÇÑô§{—Í[ÄNLœt4Ca¸Ö'sbZ¸1²*·ƒëýÄsÑAy}°îg [fjM‰­yÛèôû‡4š®môS£¾±êu2\zÏ~¤¹hNßY]MSRª´Š-ŠÈ6Óêö>†FÙÛ?œ‚‘Å—Ø´[…¸idz¨qW''ü-^HzÑÈ鹟çJ‹AÆã@Œù9X*¶øõèÃ×ÍS++¥©VnÐj½kîTIô1Ò{¿¬t8mŠ©ôû‰k T:gâYð—!«nÅ É7¶jxÕ9nr/¯N¿‡(½4 †$…`¥ùÛ‡XÈBø ±]ô=üW‡=þéðïÜêîØÉuÛÇo9ü">£È¾¾JÙO#ÉÊms$¶êú‘Õ#L¹^óð…^‹E+^­´Nn°r>CvN0ýCË”¸5Î!«}‡ÁJ9¦R¦\3ø]£ø¢ Èò›"‡ ·Ì¢ËJÙô¼¡êi9bã6®0¾GÎJÎÑz䮦iÑœ¢j._+#X³€6h+¯ÊDÂÉ2>ë2P $µ×­e¥_QL)åB8í_ƦhfO/§¿{’`´Yu…’…'.g8á@d÷•OQGó?þã?Œ¸2Çã?2j[cššÄi­Ú³Ç=æ.šŽæ%ÖOk2ÜÍé#Îr¾waÂ%²ép½§“ên¬¥q8-°/f>Be•˜ “Yæê>”ÏÉ‚ñ#—ÞÞÆjsÆi±À4«ej“'•Î9¯0/dÒ2•ß (ô‡fõ”º,›ˆ_ÊzÞ8ý=ÚIùÊåô{àá˜"i·tcåÈvkÕ^µø+’²Ê5.¢Dc 4jU¢çÓß³ÙGvýËú֬њ'Ø’l嚊:厾pàË¡f[L…Œ¦'vY´¶·¨1PŠ6ÛˆiˆÐ%s^ѵ±hœOá¨Õ -–î„8pêÊpœ'cïši£!Õ+=…²à@Æqô÷“°‡“£ï9'DY þšŽÒž~„t!2ܪtUç¹D˜~^ÿîYb{çHÿ¼½p€*GÓG¶Ë¯°–øvйÜÂ+熱>B"ú‘U«ùVíAËé[~ueIç³jõ QÊÆ!eŠãP:a^~\×¢E‰2kDà$èójiú@é>=¬ñOú“¿¬J(­®×'÷ØZR·«\Eœ®ˆ©\|Nßš¤hÌÅí;Œþ!øÆõRˆŽ»q„œúá»CZ°ÝhED ñ7e«Â‰3¿,ÓsÜVf£0§d $Äü°`»w-û> âO™ŽƒâôDѽO †³CŒV }ŽÒ9|!û«„_Wp»lºZí£h·¨Ñ¶¦iä«å¦ÁÜ>Š:šô‰ä¡•¬¶«ˆ¬ ²‹ê‘/q²n3÷¿@–ÎAæ[¯Æéuì›®¤O¡5âsœ×ûW ­«ê‰»E¦Ï7އ¹mè·Éeiã¾|@+uÿøöä²YÀŒøz³Û|«›š— ^Tb×BÁ2þî@‰VŠvzú9Žd‰ÛdÆ/”Ó"XÈ(Ë΄7Bº.ùpS~ |L͘ß8µÿóOÿôOu EÍjtx4K%Íñ,´5vÓè²AØZG+…޳5.›+až+ž¯NÃ4á4¥ˆjΆäˆÚÜd£Õ[QYDÔª„)C¾ŸÖ¦ÈêE+A îÎô„ ßé´áS3br¾©O-Y>£fJÇ¡4å kÕ½äe€yÇP´ß@žŒ“’ZSüëá]®@IDATèÀ¥L§ÇŠ)²uùs¡ÏO²N-C #±•&ҳ܆Ã%šê !M"®S7¹û6ñšiŒI™ñÝQVÇ'èZ“J0²¢ ¡•òõì⺦ÙÒH%ظhåŒ3%*‡sûM£ñ“åäÃ9Æô7 D>¼Ÿ,Ñ¿ùçþgM/ðA´L£æØñtM™D£ ÆzH8vǨ׊O V !»Ã8B¬K˜¬kCMîÓçùÄà(Ç0Œµ*E ˆh|¹ñ9@ŽDuíñg]xéøÚvV,)žmžýÉ•olE|‰²¼XÚd9š¯.…Dœž^û&jQ5œ¦‘”±År¤û†@Y禎‘í"¥s/×Í©Ojq(Ô§¢Úðs~ï™B…ï†$âVT‚‚rkTˆTÕ¿©³KZÚGSwpY™ÃÒªö\\!âÝ-ÓDÎ7¶Þ¦ÈjáoB€4«ÒˆSȘ¥¼ñ4ýœ–¢öAQ²¦8¥ço½ó¯ÿú¯ƒjÈH% £´±í-¦Ø1å—‚o\!#ÃOS³»ÂÈŸ~ÓøêBš·mPx¾…jñã$M”¹x>ñ«’¾(œ²: ½™ˆ¢=IŸLjë0¾)C³äVMJnQmX©sÀ8i'Å©DN‰5ƒfjÝ“œ3„©CronN‚Ò8pcÖn,Ä‘èõ`&µ¨f¬TW.J大C³ÓR¦èJ¤`¥ ºî85FJoîs¯R‹¦“È4‹*QÑøYóóù¥0¿qäjáUo]@›À8Èj¡1 $çoþå_þ¥‰±uËhZ2Pšõ«Ç©@·ÄÈ«95nz:I…çñ ù–fŸæ@¶ÍBËÊ LÁ£hñŠæxDõåôU¢+ÇQ"Y£ÄôóM·d>«½üŠòoàh|V‡%b–¨ Ä4‘]9Ó–³*¥—ed F4†&Ë(¤"'ŠlZ'hK¤Ÿ#+}øQŒß¢Œ6ÇÈj \Vz~S4üp>PÖMã™ÃÇl¬VÑeÅL_hÑ[¿BõIxŽrãÃ;v«©çÔøi †‡àH,«ÅgðI• !UÑÄùB¢|Íh;þê–ˆ\n`‹â‡Ë-kÊÑŒcŽl¯hfeád@£ƒoª±À_’6’³ì ׇ|9EáSZ¡ÆEM#7Â1{Ï–hzw@Ÿ©…ߎ†,”P÷5ödœ!)¹]<ˆ”m_®éº… rLÑNìy=HŸcÊÉG¨z|~ûÐÎnOLk_b‚ÆRà‰#]¹hB-¤ŠõƒIy¥…˜išRrŒCL‰cÒ‰/´0ù-y'BX ¥ „WÝXów4>¦¢ðV±D‡¥od¦B®)~;nl‡›¦ÆÇ¡9'ÁhJ˪PÈÆÏ× &¿…åC¤qŒIçiÅás”¯­ú4Ö‡lü5‘#ÄAS+ZRáU‘Û”ÂÚãgBÒwú—ÈÏn!HúS¾Œí”§@=‡+‘šq¸+=µJ ŽVâ“qRæHAnZ–ÒÈ‘YSx¾1?ÙÃx4»R…hš†Ô9ͬ®±«_•ÚˆçäÿìØ–Ÿx´ü*brÆŸÎdCîK¥Ü%˜‚i~ES€°DîfBVy~k„Üþç­€b'X[þg£cëCÔ› GI ¡¬燗‹`šT!x+Ì1ÂO ŸTgjsðe­_¨¨‘xM"ÄDЀi›XõÕ…`ÊZ•²„2œå—kd@#²©U7­+ÎE‘ I±Ÿ|N«ª™øF–HY¦9F>2gÓ:‰vòŸ”c…e¥çGƒÜü{Z!dú| é9…²Šë'ÄȪˡP kïY ­·‡ûWç„8­Ïõ?)¡E'^Å©iRb†¼«ÀŠ~>p9r0*YTô Ç®ØÆrã;m¦8%*…¯9õŒá­g%ÐDm "(TÅbò‚)#•AàËŠfÄ1Ös#$/ÄnÐTtä'þ9p…žF>+ÕymÁ¦Ñ&^ÛÖÅjµ®ž.>ÖÏôÉJLJpÊâgk>üÙøñU„÷PUÏ+ÚÓ !~ üV4¼Ä½swסE02)Õ ¯¿ZºjÒ’΀ÀZ©)Ž){"Ÿ'œ­±jÀ™`¹˜˜JóÃ9íñªWÀ^LE2ë·ón¡6údþ<óp(˜V›ÎüLm™\&T!cüѳ¸Ÿ•?ô³Ž£AÖênÑð•0•¥íÚƒC&¿&#Üx @Ú¬åÖUEn›fÍÔ€ÄRÒ4â°é óþÊA“S´ÕÕ-påàjA’’ a²B œ¦èÝ šëH ž>æ6çfF0²6“>§æU¯.$ß”ÕÐFIá|Ó…›¸¬m¬ÐRÔb)ë$ИΖ0…%ä×ÒKóóO H0Òx, S ©;Ua>«Å|8i>&~û+„ áËJßhZ¡U1Ŭâhpü»ládM…êßhg¥Ä¬–~jÀˆ`ZKi¥@ª ”˯ŠP"¥Ì/%0¿»a9•6åÜkR-c$°ëZ.ÁÖɤ¤#Ä1…76”Þp —+‹’rÓüEk¦¢,Aná„s:!j^]¸ø¦éá8ésZ Š#ó¬r‰ï0¬ |d4#Ã1ž‡½€ÑDaá$Lå˜Ö:‡gÍ™RXíŠ!3:¬bpfJŠSÑrÚ'øûËq¹åsJ¬áÈ©Q /dš¾,!£ÐH¤Ü|SCfù|‰6$e4Vbj‘ùé+j£"ˢ×­U˜Âo9Gô§deµ!9pŽ'¾\úªCLceIÙŠòE38Žr)¤(Qh‰œhdV'œ89‰C(äÃós$ŠÖ°VM'u+cÂÓ.+?§*ü9¢í[[*”Ý]A>Onì2æ‹©:‰š‚Çá¬cæ«KÑø¥SFæ³zÕß*N9Φ#‹Ÿµk1¦p+Q?ø¦§ØÏ]W“ÃË2âäãp¤*|­:Ü/°*ñ· ¦1Ã¥°¥C-}#…¦ò“ͳ1µ¦¤LÑ”órÊ…›Òœ>~ӻʘ¦8r9LKÆWˆå'~†¢õ ʈÜ6¯J4# '0f´F!`µNÉŸ‹Å i™r5cd‰5í•û<´P[d¤©t9m«L*egp)ÒCøú0¶;ðѧÃÓ=¤©±¢ÈÀ]¶”k,qS Ʀqöªc*%ªRÊÆÚ0®‡ÓJJŸd¦mVâ­K9#„‰‘?+ÚJGîYK…p"ß["d¬D D"ãT‘BÑœ®§\8Ú6vuá0Yš¢ü”ø×G`RTìs&©øS…·¾lä×dcâ7NVž ‡­:ÿ©|†ds€#ó»ú'ÿçÉ2çä?V«F«0–ò¹óƶJP’s„BÈ7ROÖl%6áÛµeE(‘Ïè$Þñ2ž2¥P­ÆÈF–2"AScWˆOÄÚXY¦5&¿*gd!ÕdE]Q‚±&©±8ÑLEéh f ˜€¦ÚN³>#ð“:Ëøù¸ƒÆâ´ðjJIa!Ì™NÐŒ:)K“MS(ÎÚ.d*e~´¦F—lHU(çˆ&¥JWv"þÕãÈK™2Ç!1ª®D \ 8KŸs¯9YNV”_ú9p¯Â¿1Õž©ãÒVcYÈB«Šz¹,µJLY<?eŽ'º…õܪ9! kZÖr©Ù;œš\Š©Í‰ÀÉp"W´c!ÕÛÜñ+ÃÑpè3 Ñ´èdÃñCJä6„ØXÊ£ý¹ÌHMºÒ¦Ê±[/%‡³”MBj¦Vn~úø¤¦Ö ²ê|)BíRS¾Ã8B¬åĬÖdK $¾U(H„Õ^jRrKÙBª2©Deq*Í)å³Y/* T}t"—OH 'hê¤n!@´Ö_"¦)ýRŒ Ó$e4m²²bâ×dxã³{¿×¡Æ6rò“ª 19)¬BzcRJå1`m䊎̑ )«BÕ­JRÆ»::±Vº'ÂêÆ¬Ä¶º©Zh1ÓŒ\~4#S%&M⨻¥!ô|Qèè>WMKgÈó¥³¶+Ü´,UЊrž&®S"úÊ…„K"aÑHÁÖsBà¦ÆMó‘ÂHI˜Ÿ„ñ.mP•eµMÈÌ4‡TVbY!²nàÄ„ eA’ÅéÓ0~)|'#¤%”[!¥@¦ÏǓӊ0Y·´hÓ9MÂÓ¯´i"ÈÈùUÒâ¯íZ­+‹¦åO™œg¾P7Œ”À©Iis88OÒéÝ ùzרhd».8•Hsåà²Új>Ç~Šž—•àdùøœJ+ºZq 7¹”euÐo>å@ãùHÕ“ph>„\K=‚GòiÎÁd¢$Ñd¢ò6 A—«µ…mPé™”Fäú6-±røÀ²ò19ɦì:ŸÃgs˜~ˆÈ꯶Õ%^´*!F"²±ÏÁj¥F̵Tóh¥¤ÌG{Úùôƒ KtcVn*Ô4² bÉpj)‘Ô*]o1£ ݲé'N6rŽPÌRT„WN­Š7“A²hR€ÈF=¼‡¹)Â8þÑ8ÿù$}6'…éÜx²Ÿÿ¾ÂÍXÆ)ø,²zÈBÑŠ*Ö†P ‚ññ]"0¤ÒÆ›èñ“¿D‚|¹Dà}P_'ÿg‰ —ÕÃL¢,†ó4õ;E7/ËNĨgYÑšº%&ˆ­”tÐrR3â„ÔX„ÓñÓs/u| [cKˆf„´>{ò>÷?P.¿ýÉW·¥Áç#cÖyQc½)]‰Dâ´Þ‰´ÿRpB¦¬fL™\{¥%ø8ñ… ¢h!8üù*‰Y"­%ÂFN½qd±RhÖy8“/dZÖçl€˜äHÆT8ñ„L_Î8p¶&šJA°­Ö 'QÆgÍÁ©­¶L®i¹¥$lï„"ŒÓ´¢µÑO“™V ˆ°m-¼D¸©”rËJ„_Ôˆ€–™*h]œ4‘#Ü:[±¢wnK–…@DˆÕRS¹ h¤P´ºeAšNʳômB馉EËMÜÈtbŒÓ3"}QN·1¿f  /H0ãäW?&ñ›Ð*D¥§É7Öqû/Ë´ºqÎÝYf•$ÜÒ@QÔ¡¦hµkª§r‹ò'²bm\”a6Bêc )åÕâ3¸[hå&ØÖ P Æø[pé@é­—>ƒ$rà|`: Á!÷£±Äiògøª§I^i–Rt4 –ÎW(…pé‘Ó,½f\´\ÎÀ¦‰$+W]Hú@=˜õ€¿h‚F„…v!Ò¬Ѳ’5ͺ|QÆAbÌ 1¦SȈŒPJR3Ѧ¸t×+Â#ÿÙ7>ZˆèùhÂa]cŽ!†½2¦BøEÛ)`H`äŽ „C§tYišF¦ÉWº«Îç´fä– ¤)12¼\#<°¢p‰øiq 1¥W%¿®(«Åçsdi¡Ž©Äh¦K7J‰&dúª˜TãºJ¹n“ÂÙò!¦hÒLD¨B…¤ÀÛO8kR’5bFM¹©ÿr‚Ž©§¯ñå ¬jéà@šBª„ˆÄl<5ž*éð•ÞÛ—” =¬Ïð(}ðÐRFJ b€çT »M1]—‡ñcÉápdmåM±€ü—‘ 'Ëò7BèHy‚¿»Y«eÈ%;Í:¬V¥EM‡Ûâ¢ðžUµ`u©á0œðµWi´é1WH(ƒ'H„ñ­MÏåcÊyˆ2>…¤ð·Ò[¡8Û(ƒ ³B9åÖ( ä×[!´E+ÙIÇ” ÷“2Áì¡|ŽS䙸¢:AKyÑ”ÛÉD ‘«bl&^b Ä‰Eÿæßþíß,‰®ù­Ë+3BrFŨ¬é¤ÓµG]BÈüÔDÕŠ a/)µ¤qDk '¿imœäŸ›'ÎDjO¨@]õ`KgãI{6´¥áÀùÓ—²æùÑpê¤ñhý2H>òŸa‚ñïD´å[‚d»‘T#¼MNd#çÔøë›-Ä-g`ULk¬.:\?|ähL™Êú\õ 5¶éâoš³étˆÏe«ÅO GKá|xæ§Ð8)þùZ€ÚþbD€äO‹“…W2gå«þ"Ç7ž²ß(ÞTúhü@Q–r‡Ã-f~„¥$Ž6~:'ù§z×OJK€§6‘RFÛ¾‘ee!;—¦ðùÔNÎL‰¤"*qg]ˆ/“Z'Ï´DQ`m$Ž0Íeqt’2¿–&[¢‚35H{U(Z5Å42ÓÔŠòsŠ6â KÉ1ÆJvYi&~—¨«KÁääÃ9–g)!Û%d«Àÿ´e^srøõT~«ýî?r¿+©Œ±¢ýK²huÀgµ[ß|V•Ò8E#MYuñÃ9)‡ Q3 Ùðý7"ˆŽ€“_‰M—˜ÈÓÂçpW"Ĥ·]¶‚¥#]¡ÕâÄ|2>]a® '+e뇡Ÿ½Ub”ìÓà%Þ"°)HydÎò×0MÎðJIYã¯JÌtà¦FRñof$…F9ƒ›¦C!‘jÝé “qª…Ï7íZWáa}î˜ÑŒ‡´4‹­^Scõ´(4‚dS´pŽƒ^а¡VUTV!Žþš6Â1k©¹Àq(À&]4BMò뇃–)+Úz¨+`OkÓZ…ÔC½E+]ˆQÛ8ütóóøiíMR–Bÿa'7²PQ#BX«ue¢ÜæDF3%e\J»QõÕ’ŽÐ4…5LŠƒcíâ¯V¡»"¿i„І§#zxÑâ8›Ö¹*ëÏj.…•ÛUæ¯4¾¯|ÃK/š2Âù|¬›ØÂŰsŒÌ´zMIì‡àT@ˆ™)K7Å `J|8ßTõã—.+fÑDR+4$p#‡)Qé˜4MKiÜÖG~’þ`@¾Õ6åÐâd µ«Õ–˜Ão9¦åÖRÄd…8øøŒ~!Q7-dš²‘Õ ‚eÞÌøÆÙÝ3)äF"üh!˜mÚøt–ÏçtlLWt ¢ìÎÂmO8w–PK‡Szü€å%R«ç‡^v‡k%ܸV¢Ýx>BMHŒCS"p-Bú «D4V[hS‚<”ã$¾û­{¡qEM+aŒSÈhÙzˆŸ&0¾Qt);(‹ÆßuÅd®çhMù dÍ'%¿–ÒÁLvâO/)ø²¢Ub#'Md;ƒVVUª '‚&´Š)”;‘MñmQ?š%"1ÍFÌ0–8šh| GF~ýðY´‘9¢…V¥éðU\]kÐØ8‹ …˜6ž_Ç Ô½.ï&Æ»…j"ñÞñp MQ1 W¯ZŠcôâßÛD6M3B ùU䬖‘Q2ä­°ÕÚx Hïx¥i”+´D)8v"±,`‡­ŽtZ:SÛ~öE?ýŠ&ËJäP˜,P®i¯”ÀB)›fëY.~=´«D˜Bá|`µR³]uþÐ9@‰Õ• )7rȈP!‰˜üø˜ Ñ!gÓRæOÂÏ–â³IñjÇôáž!#°N8Jó£Uóó Z7|á©ìHn5m!?YEsfwU)Mãð™,&ÔG„¬z]ÈØÃ{½ÍÑI)F:)ÙÊÕ*A8AL~%á@¡“ù<´j£©S.Ë…d8Z²uÀœ cÄI–Ï)úè}.U ‘ÝBÚötʲùõX?q~›Æ‰““ÚöD]ÑÒ: –©èÝ3ä.WÏÀÌ4§\>r=/”`SÊ©µ|8Û´ÒÑŠ­‡×*…'郘"”øòÑ RÊú}ZIi·iÝT¥„*3½0!´–ZýoG¨æ’MP7í{äÀ.•º•KÓÎL·T>DÔ3ž9¢õ“BQãÓ¤ +ß4YcÓRâÂg8­Bi¸á-*ø &Q”Ãà*5oŒžBäú7zm]‚ÆÔÐê­ºFÈ©÷sŒîÆÒl 7šæ—ÈÏFS ²1GT]åì‰Z[&g²M!h|Yþ_:|jü*xÕO„fð‰‹®"¤fº²çß«Tæîbª c¶ü¶Œ „´¨Uñ+IÔ›Lx„r]NWåv¤w^Ò,…FS²Ò' Y '¿hmX­)kÁ˜ó$? 1‹®¦Ëâ¼rÕ¢)„ÀŽîÏUŒOÒJ98|æ矄'?¿~Dm#Z›Ð5Be"8Y‰Æ¦mÅȘRè@Œ8cÆ$?ÿcÉBE[_º¬­q)B“m±u»1…’…#@j¦­(jÌIª•B**1ÿ~v€Sÿ8ü˜%X)ÔÎŽC›—;°´ª‚˜Ê 4ÍšRch,%ùŽ8¼‡HÁ/¥.qÑ8‘Öcø«y8& ¤èü¥À#@øÆŒŸHÍläÀ MñYޱܭ¨h:-6ßvÅAà”È/jÊÙG¿Š ùjaúÿždOÖ$›ZšÈ¬º…Ô­%|¹ÞŽL…ê‡ÃªX­t€õóSç³-§Bœ|4NÑR¨UˆäéësЛëSîkšl%R€°4‘ë™S”ÃÌT ),¾ñcÂ|ìjä«%ИÏQÅØBJ‰áóß°–cžé;Ò¨B a5íüäÿJ·Ô“5šÊbmAø¶#¾h ¢YY@!þ¢9Cì~«-D°Þ8ËÂY à‹ñ8D@ã³ÈÆõnzëÔ¤lQŽÐÔD¥›вZÊÝŠ¦ümÜÑv-Ç­CÑÿÿã-úª‘¦è +å0¨$Ì3g™’‰A¾`èw‹ïÏϦoUíF7Ž,³í3rTÞqn˜¶J¬ÈB£¥/›÷ëÙÂx4¯8F Y&è饬±*1ùHã´kYn“<¯üÈ EþJF gîˆTŠo–oFì5ù\R¸¶RüŒ«Ê6`Ú±ýè‹ø·«Çù3¨ö.Ü›­—¾Ò¾Ç×Í êVVe"ó7K¨æC‰”3L@Lƒq”7pÔh™pú|RΙÉüôcšÛ±q]ÃA4¢åõ #ðÌ»­Râ6±'%‡ãu¿yùqάªr%&í|†]±MZ¦£Ühæ”}y¾2šdr-²ÐE–a&1)[2Y5^Æ4]œÀhwÁÈ09Õ™ÀmØKÖ訴öd¿âÀÐÈíìCêØ’ùÔÕç§Ñò ÅøžG#"û -Ímù~ùK#tiÏA“¿ÜˆJWrrniòÔ„æ&ø¿]í@ЬZÒgEÀÁ]oô×L+iòîX)ç®‰ÔØhâÀF;6N R»_pÉ‘>xû U[¸ŒêËÔÞÂo/þߥFÛ­’¬QWÇlÏ—,*n¤c3äDËÉbâÓv•‘‰#Í=U8U$†™xSjéBÒˆiT¦/’°#Àž2=L#Ÿ†û‰â…ÑŽíÓ&²õdÕ¾¢ÚÜ rÓÕ¬ÆÉ»ò¬+‡»\»£ê|fE @@™?ì}Êp·H–R)[/·y&&}ñâ½.2 ·F¥e†ª¢ÝÈ`ÛÈÊ1rGŒvy‹)Mtä<%àX ‘¦`Ž—&@ßËÓVøz¨Š”cÎ ¬£d¢È—‘¼âéYkq¬:€·Pp@UÐ×RŽl rb HIãª}º²%€—óIßn1}Ú½ õÊÍÒ«ê(k„e9×õý”B¡íàÈE$­Ú$•;zF|r¨*·R˜M¯K4ÑåOÖÿnO“’£ªÙñ­æVnÜ ýAQ{½eŒ–2€,Rš)(OV;Ò¸•øhÙ³½NßWHU-âüûºí˜¡ýç¬X6”ÆóÜ4}ß­Z‹’£¼µ}4ÜÒèíóÍPW²ÆíØg¤Ô—Y-=‡¦Ó« ŸÌá"2+¥Kœ­(a >ÏËÙôÄkÔnºŸ9g2Y潊.Å™þ•Á5gãþÒ k¨Ü•ÃEÀ]c+Þú'X©^úYa(ù§DüGU{¢qLàiÒ;fŸ˜rb<Ò”‘€£ç3{{‘”>²—HœÀñá(”äxbѳÚgo—’iL¿MßÐöÇL\•R É-Ì#i*cÈzh¯3¬—€~’á]-7X»L“y•ÎeîÓÀ "5vdX‰FtU±A”¢*ñžçÓtœíªF¯7 Vª÷LºËí ×^®¥Ló:Ãß7޼z@y)ª¶rŽô[Ù‹åYÀdu…×¹1϶7äÏÇ‘IO³ˆ’ „Û0+@>ª-I üQƒY/,Të-×Û\ÕÈ+ü_ ÿ›ÕQî:Èuå6Á<1Ÿ€Ç¢±¯U˜ÀJÛÄ£ˆi%Í*¨úžº. ­VÒÂÊ%ÊZ .ÊÞ >Msçœa_} éì!t´­ªpì90Öëâ)Ó˜¸qô4}Qm¥L¶^üJ™ë"CæüæÃ mÂm{”é”Ê,jÃXhSÄÇå¾Ö]8M½‚ù½UÇdª>û$SÒ SNžs;“UãÈÄîø¨”Þjz²øå˜¦GšÎ_‹¼#¬J†Y•²[øÂ371R¤Ù‡]üÕ×µÝvSbÏʱç“ L Ä0¤WzõýìQ£lP[½íH½y¶‰L°.†®ïH¶MrË&‡ŽbhúQø®š-™3wYÌE+…‘¬"É-÷1a|"çU@U~ñõpi€Nšk¬JO“U½² ÐÕ*2&¹,Ú©Cæ½°jS`]¦„ûð„§d²ŒOÌŸ8¾Ñd9A@IÀ†ÊLG MäÈÄËY%–Å«dˆ©ýå_X[»1ôáL:ºMž4rkàý›Ä{ιÕ8¥ž­÷Òwb3gN™&CGñê»OÓÛüªþùWQ¶Æ†6â•…)i&,Fl"íéˆHšü‘ç^j«AYÄÔ“Fß ÀmÀ4AcÚŒ `Ò*@ÊÚ#«Ú j4…­£È$Xoû¤t¤é›&q¤,b´ÀlÅu=ˆ^&À„iÌ…%Lwj¿œœ­Æª›¢Z°*ˆÉ€í£” 0+LïGïV³"öxs#®W£‹èŠñމfØ8ž>sGÊ=Ûº´«¶ÕdµW"sœ¬ž ò,§É]°v>âýsI— ñßtêc¢LÖ]à4‘ybâeúwFïùààV€Ÿ®H±Öu„•ä’…ˆ ™´Üx2|‘ŒL2_K]vÄ-™¯°•«:âû#•\I/œçvÆÀHµ[ËŽá^©~P®¤q)ˆ·€Gjî.’CË=ó°£’Þ}º¶uÜWTHƒˆ³ÕÛ‰§TYåZ”à4²è˜~†ÈÚmÒ†Ú]özå¬Ýz™ÏYc äv‡œ•DL³ì©öÄÚ‡`] *㉛˜&+b>²c Ÿå-ÙÐzaa%-çy%ÒÓ×\d¦ó­i!¤#™ÆÄkI0£1Yi‰'Æd˜?œFžg‚eJQ# ¡H¹Æ¬”ÌÝß–zi4&id %ÐÏè@†È€A¦ïÓ‹JeGS˜pˆ©Ý1&PV¢yùŽœœà?ÿù‰aY¨ÞÉgÖ«ör(°í 7 ¨Q®¤]8š‹ ô0=@z˜“C«ºjÉ?^ÎMKÌgJ>˜ZšFa½F³ªZ/2@‰Ï?Ì9=¦ ÎgJ|3üžÎ¯å{“zLµÁªamGØYüãø[Ù¼Ö…wCâ‘o/ìr—¬Ð»•Tõö õ«*(‘éiDšÈ½1xúF8*]ƒsG%9°ü¿çíá2LжX½=®h±kyÌ{i`LxWhzÇ j®L_ Gí—>@(¥l®@ ¸Üõ;bì3g·æƒ”‘VjÿãþûR5gdGsD¿5ôvÓîÒíÚ¸MÑ¢ºö&¾Õ<¹M¶€mø§ÅQ4ñ¬õ‹ï/Á)\¬#,*ÉU»€£7°‘€°´Y¹vVª‘sp™RmÈŠ-ŸÄ@nÉv´ÈZ(UáZð/Ø|h„–¾„(#U…Æu-Uc’Õ¯ô~ùqN $h½ ÚA{ñåÅÓh̤GíH¦êÈg†Y9ç&¦!vÌÍ«–I%VMÔ+RÈñ@b< EŽ<¢ûdävªžÂï f®—Ï@†mK£$á|R&“[ž&* 0Uÿç”PÞ¼c¥•ð1òë¢Ú$dŸ€µÔ¥4 ¦)5Òs&§í÷u¸òT¥ï›ŠwH4I@é9ÒôÇ.œ3ÍÜøhU•ª6—lJšªr¸‰ e"å¶ðªʦìS@ôüñžR]°.¶dÈz᎘°Ühí•4ªÖˆá‹6™fLsu‰ÈÌ3ùƒ_zŒFY´Ì»*AÕºhj‘Û$^_©Í嶺öŸ?Üs›Ã€Þc´sý²Í®zt77ïx<[8Á”½7È èõL…’54ŠºšŽ€U‰¯êÈ´ ‹0ÛöDÎô4u%ÎsüH`㪲í=SâüG`D¶º9«H½µÜ]Î2ž˜Ü†;R LXν6¨µ÷ðGÖ… Н„|¹9ÊñÇ$YW« i8׋ñŸ.†1Â’®²‰Ju5ˆ3M̹Òï—T˜å; î±| ®³ž ²ãfOÖo3ŒÀп™ « @d®´#iÒ—i„jÙsuÚÜQÕJÉz½0ølY‰MW®EàÆVUÔȳ}zjñJ“aêݬ9—[Å”1ýŠÝYðâ—Av´€Ð.7V¥÷ly-¹Éµô;Ç6÷‚~ÑN ”IØQ„Ó;f.ð>f’Ò±vù]¯ët5 åû{9÷ʶF‚Ÿ'€ó‰ÄØd³ö³õdq^Gêfˆ¬1MM 3B¦0VìøvÁªÄ¢j½²À4.LéS ÆÜz@øM¡¯½–¾šK¦$+½-°¸Æç‘ÑèJ·@dSd¡…F•X¤t¬ÚÆx·ì™x¶ÚÇ÷ÙÀ^2½ [‘ Œj÷í8¦Osnò8o™¦Ùe¬ hçô Â8ʙҠí Eµ#ü~"Y)Õâ(®Á?Ž96tÙ”wnιÞL0³m½ºä¬4ô° Sr÷ô°È è(kÁŸ=¨«5 +0Öè¬õ‘myt¿/Y Øp‚˜¶Œ™,#z T‰ÑïsjÃÖ­½.¼ðæ!‰óŸ xæp²²«¿ ¯öûMË6¡ÄgËóÔ8Ø>¹l§áPLÌA/YàW?ƒà2«”14Z¬£¿5M™¿,òW"ËŽJvY#ú{Wo¿#žÐHܰÐXd3¡$ ¶U È€°Aª5F:¶[‚æò¤iªÞĺÖÒÊdáªùôTÖÿù5h­^g ]ÚÁÇXW•²·²*A%]¢ç8q ñ‘2Œ÷Á¸@‚ ¦ª®å¸ü>*¥ #-³ç»®5ö…§é؈|:VåÉv#|Gs ©4>PöQsiÒta¹…ä–ˆÉA&nœR?eβH Tˆ#m²§#óqÁ‹vã@  ¬Ë1ÏØ¥ÚÖ‘‡ª „˽LðÈÜÀ®So¥L*Á@sÓ¬Z{GXœQ×P§…˜€¬ä¼ÂïG4/Ök$ÈGÝ'p†ýB—»­P•oÓ÷>1o™óxîÊ­^ÕÄ=Jšö);Ö.k‰Ô²)VEŠã~´*7ߢún‘3ÁÚ‡w/ʦ´ŒÌªÝh½àuÁ‚¡¯½Ân€€æ@ú”¼F$ÐMÓ´~û×KY8æ ì²y:úù¶ÞŸüŸ¯=ëe%Ó×%ïÖ°ÈÁ”ŽH™>¥A ×E°Ñ ¸ãøÄ•Â]‡ƒF9ð àMI|¾³Z‚iò/«Â€à›¦'ž©ÔÆYÉ}Gˆ» ]‰×3Û í4¹y_1U1º­”ÌGÕ Ä‘°eઽî bÛª2Ì„ëm.ܱg¢±w"Ù[ÍS©ã–ßÚýxÐÂ4"\îi¿!°@wÁߎóÓ÷]Hß`U2¹°O+Q¾`Ï I™s)'Î3Y¾Gš¦ÅZC à0ÏebGÕ Úa ¨N–á^µq”@ŸÎºˆ óÏAþ¾»äÕ¸ò à½X¹`·WînŸE¬j8«3û÷S5¦¨®Ý1‡‹qªËH‹U­«œ ÎÙ’õ:¶Ïô˜½Í«º 0B Ï7ÂHo›À‘YßJ¯Xµrãö¸™`Ü4e-án6…žRÐX Ã2¦jí5Îs>³eR£.‘ÀChJ¥H™§¬…²A¯s¼/cþhÉåÙnVæŽ4È…£YJ˜mW>ºçÏÒÛ}Y£ÃuQ^+ä÷mc=…‚lW¿¯ð'ìŒøº°£8Í¿ŸÛš§WØCµu[ôÊÏçT‹,r(µ À1™)¬Žî÷,,óg¨R#åkn²È¡éÄ<Ý}Åu…·†£ÑÞÂЫ$gEïØooâ•„®š )Ž›U FxÉšÅÁþiâ[?ÓŽ)»²ÞÜ€>”Žª‚>²ýk”3lŸd0¾ÞxË\›ÿIiäœSZòa•­Û b‘ ’c;Ýâ÷ÂäPo|ºŠ™¤ì»¾®ÖÐ’~?RŽá£«# ÈÎPµ@Ì£h‰ÆqAfdä(WÂJ5ÆÔB#0JÉ<{G“ÍßsL/#EwÐLÓ ÈF§Çion-{çðZvGš3ì÷yžõÛÙÇ,c¶?æÅ±¸{Ò¼æ£ÑÕKL¦Ñ¡*ÏΤŽâF jÌF¬·†Ó¬Ô†›ëï"1@»bVÕ›3Æt퀄R`]J°ÐX/c<ýi¾ËAã"¾Ý'p7BÕÑ£Võ`ñVª_K&_c tÎÇò®Õ5ú`*U•{¾5ë­½\/Ü6­u¿+ ;·À4œµ·+€·nãÚ[©PZ¤Ä¯7#ÿFTÂ;2ÔÛ¬P¼½ÄM¤ÄSâ{Ñá˜Lä}ý´ &M†‰·óþÇ<’’~h=˜&q>Û QÉÖC¦vÕUÀ¥%¡TtqX YaêíÝZתÀÌWÕ5“¦¤‘g8¾‰ÇXr‚¬lîkظJõ}C{)ÙbÎÍý£—À0=«1ZP« bd^Y¤Ï§] 6;½ª_/ÓYOÓ;±é5zôÄ"$1MWúl€ø<éV…sèÖ˜¢ª’ckÔ+#1nç4ÞfáY Ì6II,â õÈš.ã‹dF«†‹¶‚µä€{VJM¯±<¥â[9C@ ?FoY¯,r+ Ld@£jí@Šf‚@þyb¹õK-¸#ÞÇ׎Ä4ôJN FU´ÞsF¸ÜDøŸÿš…¿¾hS{d¹ÔN`*Áú½mñëÊŽåz»€yŽãÿ ê"S¢LŸs>žæ._;Í&zÃÖ¨K¼#ÂñZÂÚå<+…eo¶* ±ÞÞO) Œ.Õ øû’ ©·ý òl–L‰<þß×mæÆéâ §Ôkh”<™f%“12ÿU 2ºÃÜÈR(Áã· U|+M†)ðÛÓñWüþyÆü¾ÿ¦¡÷„û(]Jx’ÈÚ·¡q˜×­=O¶[Î\¶üÑø?=5›$0²0žÚ*úÛ ¹È ž yøôe†òŸ0CœÃoþ?ÿÄ;Ì?Ǿ[äfI³˜8&ža™TåûôŽ•âçÙÅ3¡©ÐÛ³V² YÊW Rl¥–©En\aEÙ\”ªbÊ0=8“®C2&>GŒ’˜aŒãJªþå³¶ÛdJÝ1™!`†¦Þ÷viTÓïYeB\ä ka%úa#j§ä häJ”pßµ14 •;Ê0¨ëÍUÏŸµ³¤Vvô‰‡zõØÏeG ¦1bSðª)Ó(UM)ã#Ûª¶ddË·pþ˜HGJOÿÞ«jþôžlþ¯¾}æÆ¡*Pc&›BÐWÓØSêÉ8f¸vGzÇz ²H 7ZÎ6 ‡ÙVª1¼%„ lP¶} ­J³R<v)G¸¨±/F—PÚ>5æ¬D zSjQ97¶˜Ó ½|Ú1ZèÇ)WÚ»N§øÕS¶v½íL0·Zz¾Y ™OÇf!s¶À*%Læ(ÓäLädcÉôrÓØ·ªjLÓ8XÔÎSôÌÓ;U³íêéåö'+a@̼FG€›|BÁa³ã(âå»Ïyâô[‹ ß«ý?O¯q>µ;2¾?eÞ¬ÄVô ‰Fl‡ ]ÚÉj)§OÞ†)À4rU¦G·¦_æ0™3Ù¾­6¨?|6”žÃ<ë­½Yù‡É€>ªZÚ$7Jíù››‰<ŒƒêÚmÈ©=^æÓh™Æ¿ÖQ—£¥£Ô˜[x펔åÛô¥1@8°LǤRÁ!²c·»Ü!…•Ö•ž† WCóú¨æ£Ö›?,ßûMÿûK0‘žr5#€:s)ã‘ô}<0>&ýÚë-Ó\Ë“0i¦Ú591¾’cw®‰¬!ãE&fUŠ”së= n2zGí"LC 2‘˜Ú÷öLÚû$ê2·’#ÐæÈÝßSÅà±ÞºÊÚ9Ë4” r\ÈŸÀWE†ͪENC Ë…o.[[/ÜU²dnu©¾£ã“)Õ%'Ë!OdbY8âÝe¶@ô])+b¼Œ—7 Î!AaàÏDçGçSÈîR éU$;Ïí´ *o³l{ž>™’'ރȆ¶: g²œ«ÂÀÄp¦ÜtUw—™ïÚ0Ù«ÁäÀ­ªãÛ¾YwÂÙªA@æõ¦tÄ3® 'ð2ƃ­·ÏÛ11’I½0}LiàŽ”"Ÿ%¸­”<=³Âs0«/?dük{½OªªÔ2z‘ܫʪ9$ŽAö‘9öç<Zë’û_{0m˜ìØÜñ@¹Ý4v£· †gïMêX-Ǽ0i;þŽÈ-AœÀUù„ŸÙ÷‰÷èÝsIŒõdØ>s¦'ÎM©jnHÕr¶²Y~ñM 3ÄÈŽü'´ ärãûœõž%~ŸëÄÌžøÖÏcÜ"1(Á<÷c^Œ^|–žŒÜ89}nã[és<ûöO¯ŠÙ§ÿjˆ³]V%kçU‘”DVÃV2KhßÓ¶|;ãé ß|#E>®¬T¼Û—?¶‚LÆræôŽ”WrEÎ…Z¬ æ˜i.“J_ÛÓ$«¤±ã¬rC¶„ö¶Ç›xš[bDSh¬ž2+g%¸Èví›bOÎŽ¢ÅÚ¤™¸>e%YµôVÂÀMQa°5¦O,cz†yÒÔÒQ•æÚ|>úމכ cú2ðúÀ¢*çŽ1án±­2ï( ‘XUðÁH ;¾ná¿ Ü]d dÕzÄŽkgŸ¬R_p&ÄÀ¦Ô’ƧyÜÕôÊo3ý¯šé¬;Âzï¾/GX¹ÄŽ)ë­šyŒu)ëM&¿ cþõÒ›.€”€G¿‚°ù«ú&½®x¥ÂQÌ­‡x‡|ÏWµçC?Yß¡É0祸_*¬ñÜ8ŒjÏ&™Ü ³7%ì(ªf‹/"UÍ’‘4} #1‚21>e]“9öÁ2ߣÓÀ\ºDW¾sN„}­*­=~ÇWt}#ÄëxJÀóïSÖøÏwPmŠSë)úTò¾¾ƒ72Jí[ѰÜðí$#E©‡Ø}wDÊ—É3%@&k‡wáHyËØðÊÞ½à9G†)O™ÞÑGNײ)˜¶"@ wLƒÑî§[>kßh#arëÉÄ«¹ÞG“RÖΙ!}-mB#2'SÚ½xÒ œÕ™tyY—ª,˜¸‹ ñ2™¦{QbÈzVU7"Í58©ÅÞ‘ÙÞ±ßè‰shâHzŒ07ÓÚ˜ Î7ž²å0¢½‘ðÔ» àÁÑTµÄé¹Vóž^{¸U(™ x›tl |K6¨R$F ‡”Ëkñô›’ƒ^{ji[2A€'€Ëñ瘃üŽcE)㙄ßÞÍJI¶j`S´ç“f†[5+Ï¿Aëý÷Üž*esÛei0±¾Ë5V¢O‰ÿÉ¿÷>Û sÓÄ=mL«b2Ç„eʶMï(ÈôÖ£*Z¬g²c²2ç}mc¶s&˜FÿE$g.ïCéýžúÌü½¦HÍýX ³vÔKÐ17£*àŽ²ªøévešIDATäÙæ3< ÀAn½ÉÙêöøÎ°ß·Æ j½ Ò\íYh¹R$¦až"L€w”_ñ•RP­]ÉžL¬}&Zʪ½v˜¾ŒÉ`æ™ÈÒ#aÜ5ôlp™¦³ªå0ÍÖÓûs Yi-É­A“³ÜÜdilXxIXÁ^§­ÇVÐ×[£Œ´|¥Ä¢RL™&Þ1æ 2æmÉÐÂÖHF&;¿ÃÂòú7`Ö—S®ÅñU:¶M¤#e]}œ h&”Ç;¦·r½À«oú¦(mz éa·¨½or®ÓCÐÅέÑ=8íõÖˆLƒÜ¬Ë=OÇ [€¸Ð®T–W0 o.™3 [%Œ[8‘ù;jÙ¬p&rwQ½ zá-“9æŒÉ„¦/Ë”»&àñ"íz䑪4ñ}á¥\×ÄëÝ>9üá[#‡Ä3‰ÔH#ÿóÛ5WXmßB²Àˆ|‘yazúªW{RóZ(²ÆjÄ;Îà3r?½ôÕ8} 4¨)dïÙ™ËÚ'°“mø ’)¥Tʪ¯ŸªæöU1ɺf¶1Ë5&^K;4‹’gWƒ¶J€ÀªqOIVÊ@Î-¢j#’y_ÉÚ_UUº§èdÓtBµ£®d5*Õ+G’ Xc e-Ħ +Ñ#1"󑎹ÍgVÄÉÖ‚Éçûëvg¢WGݺñ4€É4@ ôD]Snd`ƒáµtÁB©À{4¹Å—[ÌD`z þ5‡wœ'†R»wEvœÉ4£«ö¹Ö%#U±OþskŒ)]Ší€^Ñ à¸iäé‰ñÍÂo( ôn…IÙhøOµv2æç—çÞöõ¬J“l A-˜ÄL¦Ë1Y ͆«†ÝŸ Ã#€ŽµÃv{¼%HQã2MJ@{†i "p4¢‡žçJ 1Ž2 –+ñlÛ5ÚN¶| >·¾=÷çF†åzmÕ 1o‡ªóÙ1 ×8ÃË„-LfúV­Ô±ö=s-Ã@J]¼¡=|J¼ kÛ×N ‘O‚üåÖ«Öâ¸F¤£ÿ}Ø2ª·åSÖˆ´U³0"\æùý~=¶~mîÆÝߥºXRU+u™6Àl>Ž2e»†ãkOœ oL¼û$C ˜F„½þ¤FfhÉ4W{¦·a÷Œäl\GÁ6"C™^5åŸõȲ•[&qssÃrÐà¼ö›Å÷xóAáueÉD¸‹¬7ò4ü>¤’cKfظFçF†”x-øžÆKÆ÷ûŸü Q?}b<Ò%cv  ßM+E¤Ùòc2ƒòt„÷[{ãOL ýYô†#>üýrÐ9V.ºðÖ¥f§4 —²R ÕN¬w‚ùŒÑž›Û"õÒ``þã¯ä©õ,8´d]¾x²2…ç;¥*[A ëåüjÚ­öùר 9>“9BiU Íå>Üc11±#M¤¡HGzït¤#2Y¥i±Uko(Ð%ð0F{šª‘ᦄÓ÷L´¨*µ¾–¦ÀÉAI¿,1ï;¯30ðÖ’ŒO·ÈV1ôÄ«nPšåïçç&Yö’½ßß%ànÎ1` ¡Ë¼|ðù°ÕXÑk/(½y?âü“RVd½ÜŒh þŒÿ}±æ_#²®ªxíLÖ¤QMïØE0¯é•f;‡@Kªç™O-¦Jþ(S¸^¹x}°ésØE´4 iP Ôò^I¶X#æ?±eÚ'Ï6ÜЙ¬Jì÷9Â\ÁÁþ‚€9¦)ŽYmbüÈmKã(hbd±ã¶B’UBj\‰8&Rþ/…!‰f‡Þ>IEND®B`‚ic096/‰PNG  IHDR{C­ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ@IDATxlÝi–$H‘¬Q Š2Ö~Y ÅÐÐ×ìó²“ÝúCU3÷ˆL’~çýòoûÛ/~ñ‹ÿûß¿üå/õ«_ý÷¿ÿ Èân ûÛßþç?ÿ¡Dþë_ÿ¢üöí #W¥™ P ãùýú׿†€ÞŽ•è3O°öÕB/`› í€ñcÒ;þóŸÿT5ÔþFàa ë‡‘-Ù¥à6”[&¡¼=³ª½ªA–³ ×î¨*e¼•œ½3CG vǦ[Ï]ê(•8÷Ñ$+× zí€,j\©ªcL ÇQr‘cëØó†ó›ßðD:®ãhÛ®ßÝ15"U¶HG&í|ŠöDÚ¤v-HíKn¦®íƒG: CU3LÆ àœLßµ$+³êeâ¶­—Ø Ù¬ø4Z ɇ@»Ø2¥]‡F‹ªè„5ÎM2ÛÚe-¢M05–ñ|ǘƸŽFk\¯£ð†Ì‰ öņɸ\ùÝËLUŒh±)·e_•>q³’åv‡Ÿ_3•ââMé÷@G‚–y•ðLº7 _;€ª®6!n1 Àé½@@æÇª ‚1¬jg…Ùw¯‘O 2zÑbÓ«Râ™´•eÆ´ ¾é³Â|ûãÿè¬mÏ Ó!sÇÓ±® ØfÉ0gÕžIà˜Y©*ÏüÉ”Î*÷¥ZS¨æ@ šH9PÕ›b² Ì–ŒÔ×Û,¤vᨔƑ>C¤cád=.þ¢$&Î37< ³]—# ÆO*YF Ó/ܾ¯™È‚€L£4x¸Üí"Ç;RVŒh"’X{2Œ³L‚àX #¬±}´÷Åv$›IÓ3™’¿¡Ú1ùD7jÏõZž`z-YE:Ò ÇJ['¾ zžª‘øÆ då˜[UbVJ$·rƒâ3!x9U⪠Av›ŽÀ' Ìgšv#&CîhDÎÈ>Š×TÛ'òé>ˆÆél ¥Z…jA“›jËÛ9Þ8ʺ(ë%&€e‚ßýîwÝ“ÏÌ1JÞb5¦Oœ±£’‹`±Fd{šØ7¢6b-@KR¾u4ð·üÑ9Ó¹ÔÖ5<„**Ðô›—¬ûàÍ»h#ÏŒ{gYvünKíª"=@ÙÜœ [©ö>§w®v½ÄVm«~_ÔÞ\]›Ò jɰc¯S»Ò¶m+ÇÏ–tÈGªx«dYà›Sn«J–ÙurÀ×ë˜mÀ”ˆóÙÂÀ]á¼äJ˜r#U/vUŸ¢Ýj—› àE‹½ë!÷Ñ)%–gûî€í<Ã>ÐŽªíßz² ­!Â2LÌ6Òuúr:j¯JÎÙ Z€7JÌ [[ƈM‡­˜mkØÙ‘¡K9FÆwĈvÀltUG‘?+$æp1Ù®há ´- qŒÜ±Ì¹ÅrÓˆï^µÈk§$ÀÈ‚UU‚ Ūm¨”U;ãµÇßëL–9 ‹`€Žp›'öQjǤAê…¼^áÑ´#³-ïØ•™®À|$g’[ÕYiž³Æ[<ï©Z‰Rä‰ ”×H@/ÆPŽ$ŽÂ}÷²ÝÄÞ_{b7ýüûéA_ÿêm˜2]áØGåè³ôÓTÍ%=œÌBª•èôȺ²R4&*!}„þTG¶¨Òw¸çᘠ2˜FÀÝY—’c\]2™¬¥œC<}ë9Âß‘O&ùcà€µ”c'«# ¸ÉLz$L#¼™¿õoÿFh¡T%s„;7Ú1Ƴ\ËÏÏ¡Fžà©äÙým%ãÈï¨Ò±qDáËiùvkÊFäs¶ª ˆ›‚¬òG*A†tÜ"e&ñtÁª‘°H Ë&ƯÄОH&²£L k\¶†M%@¨ŠJUsЋ§iº«á1"[>@+‘Õå˜Æ± ©7çeJ{ŠL¯T;M¼«!ùà ›eD‹u¬ËJÓz½éôlU•oV:{ÜßZx2¤µy¢ƒ:Ö/Ïmձʭö™;ŠÚÍÅ Œ¬“gw‡û^©*å Ð3obÙz4{FOÓût”90lJCåz«ÖEP#€?ßìÔeŸ(/¡B´à×ô4u‘‚©ÈM#FÉQ ´#¦j2Ù醹ebP<½T+  KôqVÕ¢kÏGc>Lˆå€ªc;×âH)r2¤€s”0eÇ1À”6ý®IÌÓVW~ ¥Öë^Fø‚Ìíôjl+Êz]pW#î¹€ÖèúéõÚG¯0‚§Ýhü&¥GÒȰêzÛ _ ‰Ñ”Û æ +eUSŒîÕ–iî&ê-ÑÕ`-¹©"¹9ÂñßÉ+9â1½<óYP’õ˜ÉV¥ï.-ði{¾6š t¯+Á­¤Š Û\©¨Å&@ãòTÅÐ;Î9q‚ªí†ÙP¼^L¤ ‘x†pÇrŒ•FÒ¿»£ËX² ÛŠfLûcŽõ XhÃFÐ ½³#lbŸ™#²vo^Ë=×.R{0Y³Ê]¤…×¢ÄG$îÈaƒ`¥º‘8ž~ƒ%<@/ˆßì8ÿi,ÓSLÌ$L¦ÆDN©”!°†*Û45*‰¬ðÈ#e é¡È2ìFßþô§?Q8(Pˆ¾tññ\T ¦øBµÆXѱ-ëUÒÂP´Ÿ-¢#Ð52¼MŸ¿—ñwTÕ%'¨±eÚ#ªnÈöÿ1R5pd"š¸Ñ<1€ v ÀîâK¯7˜”¢oIJY YÉ;†»Úð Ú¤•rPu„YÕhy$,”jïmkÁ22p¤ÏƒÇ7%«öÌmŒ– ʹ£/‡¶ê—B/V;ì)(󼓇.T'SåàÈ¿eˆ}-S)OÊÄHšÌsp¬Ú‡• ™`#²ŠÏ­ÝšÛnx½ýy+åð*ù Ç×Þ2²£èHóò³µLwHi¢¨Å^ž@&Ã^)¬,ý™w÷TáFà˜­–x$¥F™!2ed¦_[U•êr„wlú¬ðÀô 0W4ˆ‰¨ +]î³Rþe›Tê˜î:€ª‰Ü$œV-” ŠßÚíYÖŸ¾O£+güô“ÁýÒ hOS( ØƨΤ)=/¥cžÍ˜+k)'è³ 9¿§ÌÎ1]Í{йo™@ÖÓàëåÞ*­Õº}r –k禯’=^´+£“åß8Ìû%&vS­D\/Cân.;â@iP¶4H&ú~7W)Ô’[†”9´°^&0~ƒôŠôJíIk¨:Š+ü`2U†øž³ äŸÛmý|Ÿðïõ•´ )áVª7ÏøZ(iTLß ÔNY‹j%GXìêÍßò€Hæ0!ւ瓃L#”ì¹ãn7+]ýk!&Y%ÎJB ŸÍ¢ÁÈéßQŸ¿¾`½¹”@Ÿ#M ÏLLÁJ”ôJŽHÏø74úùh¡i‡®¯êHÏ$Ã|ÒÈœÏMî ÷{s¥Õ¶Âóq¬Q&˜>)U ^Ë»¾AJâ¶~þlXÕPX•X»ã½â¶žŸ¸4d†f•'}ƒº;’@8&›˜Ò¿ãÕÕׯҔî’[&]m;˜â}8ÓD6WÆû×¢½R ÅÌ¢Ág.‹m¸)-€Xï@]¬úŸ£ðÙÎʈ0Ð;øæDRjgkUÙ·ý,q_Œ›å5ž©_QÂä#kטUY5M²ãõõ¥5šø¼ˆ6¡f]ë7¦‘­¥Š‡+ù„êÅpWº‹}þü¤É O&›… u1™9Q—vÁð=2i=V)iL dˆ$6.Ÿôu%F J- kiC2]<#O ¹²­db¡*Tiñ­ÁDɱ×@I™!,6"&O¯„^6ÂDǪݷ¹Züxà훡„¬H&2Œç“§c?¢È÷^ êF§ÿë»#ƒÏŒLÌñ‚C·Y#šÛDOéH¬xG%—UͰ7qäF@¶û`R&.cð0«‚mÎÞ³öª°Yà c”ÑÈPuÿ0¥š-RUÆ´†v]ªýÀYA†ï;S‹#L-¦–¦`z YÕŽiÌÊÖQ(q–íæ–µç3­ñmB º”–m žªùw„×H›>? 5EI‘9\#^³ضU«j‡ék1«ÑHACÓªñ0}b)“ŹÒYô®×Ú‘ýkdzSÞß1+@ Èyï‰Wm ‰Y#CX´ €¡LS ¦)4×'èx.S3ë@"Žš©r;9ôj~øãKh¬—R4C&U‡Y1ñ€ —„ÛÇ58*éd 1íÀǪ~¨v]"Y ,O U 7¶Ú1²Ç»æz“ÉÅ+Öâh1&z[,^æ_4…À1Õ”2^t4ºF@Ð;n laá½aGY£Ç±XãâiŒPr ¨&pC& ZÉnðHíªŽ Ò˜!@É_õØÝc>6‰äS»’~“:Šxù;P»ì:9Ëû£¨ýuI£) ž?g½}4‘ [@Iý^æÐqš~øCŸU¼ÜÑ&ní€ {|]‚سªÂ©‹²€¤´+´ = ž‰RžÓ'Ž_©·uzûv™ž‰¡ñ!6s·;? ±q€ë`ò‡7H©õ˜ûz4BF֏ɸhW­dCw¬%Aû¿£¹-²Ý&%+ÁÊE˜s»TG½ÄdÜzxUx ^ÎPµ}0-PÆk©KÎÁtþ.å(¿ƒè‹ÈáŬ€°¹ª›Ûe=à ÏhCm¯¿#²ÀççD9‘\'uX‰©—‚¹gŠÇ U8´ÙÞ%+9@\/ñRíS'˜ƒjbdÓ•<%,×kÙ±­4Ö…Ž2F„m(Ìb’ùðúÌ"«6Q»Ðå°`º|†ÝW†u)qP’µ¤d8RâÉШšX¯AÝCÙCþšOý¤I6*̇¾¹Àöo4A&ãjâ »5^˜¥EôEoç¬û+GÊä<2ŸÖ««*OG<ãÏfÀtdÞ—f~®}¿2OÎ0ܽ<žÕo8&s¢äŒ!CÎ?ÿ|ˆU+-ŽyÔ,&oUÁ“Æ‘FcŸZãð¹Í„LÉ‘[×☠´0P•Ý϶‰òÌñû œG¡ª(kÌ háãûõßKÈú3¨JÜ,†ñ§c£µäÜJ<@¬šxJV­ ˆFḩR{FŽ»zL¡ËV2[¼lk¡.8ÍÞPIœUî;¶?O dåÈÖ±Ä(µC½r»9t”{¥œëí¹`dVæblÞJ²¨7ó ϯÑ9ùʬmÙÑ€6 ßf8ö:J˜‚§cN‰ïH¯ÔPžU½,€ÇÀªÍµ½ÆºäJõĦÓÔYÕ³ÜÎŽ431#¶‘‰ rp×É?YU¨ `þ@ú Mq}Ùï‚€Rš|ÁF8¶¿¼ç"Ægˆ7TK¹^$[¿Îö+Cs7¢jVÍÒKlÃ&úBûž¸šÞ†òT*4Z4dÄH€8ÆÄ)á U™'†‘J|€L<ûóÀ¯0$dæÄ°l `˜¨jIœ9 ¨*s“Û3>3h0BcW ÕÃç‰ÙÎÛ„Fx^Ù‡Ò&)[»lŸ€Fbaœ£ÆöéÅ]ŠyËÈ”ý&RЬ¥åÙ‡G‘³¡¬é7î ¾±vbœý|> šÕ½ð4}©àö$ãàȶª#}sÛy•’ÕE#æ KuûàU½˜lDÙÜ45–{CXµ×fÕÅ•êÍOŒ‡¹)5 Ù?*8šë¾Õœeúvާq$Ȫ’ÌSД‚2£ ØP¶¶c·±Ìíü¶õõÄÚ,iדÙ)§õÎîÚx½JÛ@µÛ`cðZR¬L‘1Ë\—j÷·•*Mžx¸8{|]£5ˆ…ªcG-É`À½ªžæ¯ÿ1@êíA´á­‘ƒR^§ÏçѸº¸ ÷"Èí©Zo›¨ö»8…ñ¹Oñ˜ÞÐå?íhLàM4#?i5ö)`ÞO¼’^$OGíõÂùàúé'¼­àp”9d[{WkŸ÷:p?ö½°n2åp2QÉq;8¶­*íHo%œUueµ‰]­ÍU;$îFŽm·yJ%J È{.þ4­!ãÛan«ÖŽï/àü3¯Ö“F¼Ca$10= ¸u½²#ÃZdLÕ”Ýh{¶a¯M)ÈÒ(y ¿ŽUE_€Ö hJímÒãÄÇèj¨\t;]C`"ÌÖ,G ˆ? }}ÍêUÍ Ô 86Ž óÓùÕ“˜Àz3eí¦"O©% ¥=ã|h’Uê5ø´› +¬…•oBú®?Mn²®;ö|7ðy¦ì˜à,}jûëÊsþÏ@•ûלÂÑÓÀåj*˜©ª Ó¤ºâ])CU½HÓUƒ¬”ìì~K‹ а½ò“kÏ £E;€WÍ_ËøÐÔ˜,[âcz¿:òœ]ßUw;U%4ȺëâÓhGw´@©WnÄžÀ´ŒªÏ/«dzEŸ‹j% óŽ}0Že†Hs}â}ˆa>uñiÉÖ¸+>$+ hô[ ‹ä$ÎDÄ$ãÌÎ$gËPòlÐx µSÊí¢Jª¦wT’É0ÉêMÆHSo-M”U5Z©›¾»QŠmÂD4¥’Ü”ŽˆE»Ã9ôp@isë•[ ed$¥ÜQ/œÿ̳jô>¦æ&~õm[U [íòl•𨇵%;&Þ÷°ö¶Ê¤eÑÕ10Ö”Ùª¦·P ¦Mµ`Z[.èø/îóñ92l<%Ÿ!,¶¼¹@¡ªW8^ùçgÐcîï7ÞÊ·1M²y"›ÔîHÓ‘L`ÄÞa-ñ²Æ>n¥Z€í3=†Œ#¾ýáÐ eÁ Úcu=qz¾þû`.ñZÖ•Y¥ô}1kdÏ6¾kpkÑlËó¬¥Aº^ŸVµswi¢Ü‘CÖ^Ö¥ÔJ±[DÔ’Çöiíñ)UÅv«ŠálGèÇæH¯Ø1Ï~×ÛÒu6…?L¿ ûçõx¥ª=¸ÆÂ¬ø[ÿüµT‰‰‰ ¢™Œ›U›²×@6TÖK¬$Läyý>ß®.ØD;ÔÛJÄ€ ·ºfž-A¶ød …1´ë¥Á÷ǬTV¢„Ó´ÀªdU9¦ÅdGŸH³ÖEoVâJ-9Ð24JùØ!1^ªdô.³ÍdØJÛ0F~ƒ¸‰@nA<ÀÎÐ2Âܪý’j<9¬r½HGß4QIÎg™!·Ä2}]&få˜@¶6 >#°üÉ I ³Ê0ì0‰ÏîX~«ÃmÒt]ù; þªÃŽ2 ÐW®Õühql™î˜ÉJÙ®J 6ˆ`þ­Á)‹^ûµª[ä@½2Ãx˜ÉY¿‚„ÆrwŒ¡ P:Òû½´·£*SŽ ¦‰Y%FUTÒ.bÈ‚•h0ÿZé;VÒä äCcó°U˜Ä‘¾‰ `n¾[]ÏʇŠ×Òk¡$ ö{·Ë?™*R;=™q[‰ ÿJíßh|¶õjäÉÄ8Ga1Î÷6Ÿ_ ée>d޲Ÿœ°ŒìÈŸŒ¸K±j¥ªJ¯UžUµ‹4˜n§}•X&#è.µ¼>ôí³LIŸ³ér·€U[²Þ-L ´8ÆsËŸ³R¤j¶>RîÖ“À§½Tç©¥À àÕ; †ƒµ4ˆþuC 2áv+BcS´g¢=g AG™I#z7XèÍÆ“í»‡©%[ÊIJ/že4Ælœ–—äÖçůŠ);fŽa"'Ëü圕`@éûYsäIÜt%WÔž‹%òìq#±I)Tú¼2©QvìMˆ]#è9 |Ï8úÃ;gG2™²‰1×hÊÌ;šb™3æòé5ªÆhG} ôÐbް¨KNlzÃ$’¬=Õ4°Ñsë¡”2b>Â_Τ¬Ô¸ ÂtßœU‹lU·C#jìbÈ]Žbþpâªd˜Ä…åB»8ÿ#°Ú±|þ ‰Ù¯¶]˜uëêã/9C¹^Õ>3¿J0rJ8Cn‘I]€ä~жq€X)LÏ_¯}µÌ™†À8šôÚ›…w„ªê9LŸ‰£˜ 7TÎ$ËÙˆŽr¶v¦§lɲp ÕLµ¸uÊÁ™Ä‡Ë-Дr-°®6”{.æuaT{ð^@n“­‘¥€é¤·’È0^N™‰\µŽ™Ø°’Ü-4¦"e¸c9g_G>5’‰V’ë)à€ªÆZ" ®W51OâÖSª ÈV ¦–î•Fî›o7¸q”‰¹±õPÍE XÖ%h´tÍù]Fu½øöÑ~&ÝÅä¦tMâÚ7%Ya¼,^-x V"(æÜt )°…k!NDòì«î7C¯‘@Þ5×µµ¹e(¿úuÝúIüÅ–4â;½#Ò,A¦¥œUY)ÃCün7%Po&ŽÇ÷¶;LäÓçë˜2ÐÎï}ñïnª˜ø”C6‹a#S|…Úd#Î?€8==Í.@ZUI8¾2˜u¼a‚@\íGÜÅü÷_¤_7>æ>ã3ï¹?o´Ã¬Sâýåë£þ?Ÿ“^-Öh󔌻}þË,†C²­G€?ß§!¨„4cg|¨6‹Æ¸ÁZHGØ‹wÁ óÔ(RÝ"qf)!e¤ŒX‰lùädMoO¤c]@GbQ£ÌjÙ§¤A¶U²¦+å\c¶½ Ù¶%£mè7†m&gƒ'xj1:޲vb¡·pÌ-¦j;w%£Éj©D tAX˜‚ÑN6³.`£3!˜ç`Dtl\½åœ•t™`€uåŸX•U9†Œ¾}0Ž!ƒ{RX4Ë ]J…–ø)4ð”µÏ ´ F0ô…òüÔ¾Èkðù\–Ñ%ZXKFžôÝM‹#^æÐëÁF«ò¡ìFŽgƒû%‰ï8[²4².&™×‚ÌÖ’ýqÔÒ&•(ÉìPcÙ,Ë7+–ŽºÜŽ^W·sz¹GØ»M¼£5ÖÒ«j ï8ÇlíF¦dÛÚVÒ5gø³"ŠH³œ?çýÊîªu–™Òô“Ð$²|Ù‰µ´JÐg[µ…Šõâ… /ØPLä•|>r˜€£ç†²–Ü-#meFÆcD÷ÂG<@/'6“Ff‚Zp7=û‡_@ß-´dµF|÷U"s#%L-ªÝ¯1“Š#hg¯éH˜g-dù÷×Gz™&·L0E|žMLò,SB•F4—OG%L¶p‚e|_Α6!kFáç“yŸªÂÝ” © ¨4`DU<zYŒŒqÜÎ02Êø êõµ^„)«b´×h+U‘ é.ªÓ˜Ä].Ú¡œ>+¹‹7®% z^OWbV™èÚ>Uk™mSè1{½0f½]3e‚öÇ×"ä9†IßðÜð™oA]xÎ"ã™'ÀJhWíŽJðœß4Ë)‰Ú$L¬DVÎIÐ7ì´}½j³ÓSf¸¡’e.g~=Îô˜ôJ9s‹ß&•ÖX†³RUG •¶ ÙÄpƒ0~™|þ4ˆ•×í|>EŽ™6`[–>!Çõò­Ý±¤GïoÜ0zUËÉ–mO`ôpwÈ æ£t7:ŸF—ßeµ(Y¦^<™£¡0Rh©‹ž§à@6 ¤I– Œáã=nƒò,·ÌÚí÷Är ÀiddX hsÑ8‚5w-u!û#æ`™™8æP»ÛåÀX8*ˬð­äÈJø@%¶<)åæÚ6[>¢FLx3p´¡‘> ÃÍQpƈîxãçÿ m¢zmNÙB;¬ P­Ú½´ÔHƒ@™A¾½ñ)™É`íZàH9Ü2JÂ\¤h “œe¼wà–!½.šÛtœc¶*i˜|*Å»ˆÈSVr”¹s€‹LìÛ‹lg>py»9úÙñ2&ÍÕˆwLüñ½>}ÕúKêD½-Ó†ñÚ­ÊÊJ†º»A2AkΡ…5rCZFÊ˵l[ }-­—y-ªZddî¨+2ÃÞ¹%e2üŽ@-¯lûÌ-ý3¹óÏÜd4n+˜~×Ç Làíš­?•¯ÉϺգl@9Ç>¤>•Þ‚8#•Rß¹&ÁªøÀ~ïsÓB#àZr‹ »RÎ4|Þqã‘™”sÞg¯‹‰o¤h”ì£+OYpÃ4»Ò7ØÎÄ¢‰dýL¦ÇˆLÚÒL‰ç®¤ zÙ‘†9œ¡#²o[Q&îW*™c>Ä–ÇÇëVI57dÕô šFÕVŽ4¬ C ?V#5†e˜ÛJ0†ƒFÎAh!P€ÈD nDšœã—•öyI¬EId¨ ã ÍŸçø–ÄŸ¶ ª7¹ÍÕµ'[ –³ÒØ[%“1{[ q+©k¤Á Œì(êâg2 fWf"”äcôõß&À Ó°íxµ'ÕÞPÙbýè5Nny@kוßÂ=K2ßz¤oìî^ 2çÞ TbÛ1-¼¡€ £é§€r]ÄÝq‹)!e]” •0"fǵ(e wå—Ìv-™ì:kï"ô‰—U»]þŽAëíëRr,˜²à`aé1Ú12²R]ñôŽxJy×qħÁ‡kT*Ã@˜¦kbDÕx áZòׂ„¼só½½ôI4ªôÌ{  «ªÐtL–!YïÙ>a™^ì¸/¤)ø&îv½ÿ·¿þõ¯sÑiŒ ÊÐ&‹~•÷˜FNFc->Ž21 î>石)«*µJÛ Ó+mÐg€,(†s˜9AäþIÖöÛŸæ}kÇÊMö(½ ”­Už¸*“Ìødu¥ÇôÉe’@ ËnÄY¿qÉXÁë"Ð(jÄ÷ hh@µ® aÕÞÊ©TW{héeJã”Ö…¬—2çô²ØDX#A$q³(U7šLI ESrX#M· C’H‘†'¬1’À§7N‹zª¹Ñ)×ÂÙ>ªÊ|ÂúZ(…’®¶’,Z²+¤ŒÑKœƒ™¾Pµ3ÆQUo`sUálS:æ3LÐ~z%þ9OŒŒÇäÙ,sñíз·f™¼+÷¯%s³FKV jI|nùœÎ«¤ÁDj쑬4²Æ>tG%‘•¼Ã%>7Â8ò©‘É 9àÓäLt‰ö)ûí—²··2À±YŽ»;«vHI£„¡‘µÓÏd½ÑV2+úZàÏï¸ÎIÍðjÔ¢R¿ý{™ÒøcsƒÌqc`Lnþ6ÍÊê„‘U‘µJ<=+Y¤'ëEðºŠwVŸÁ˜¶Í“Ö˜¹Œ—m¥Ô>Ì÷ ¥!htÿ=€a•ƒcA‰ÑÛMSF(Á€§»ëœkúgý%<›neÇÓ·< 0æ»/}4èË]‹ŒÑ˜g2Ln2ÒÂHGJYÕªvsƒU[8s¹^YÔ›ùÓPúMGHÎþ¨î k¤ÌŽZð˜ýuéeô*uï’]Ÿ¸Œ´aá£|òDÎyŒ*ÞLÃÄ0Ʀqì+áXcVUµ×Å!,ç6Œ O4W.ÜÑõï]Ï'Ò”w%¤cŒv‚MW k·pÕ Ð{Ïf%fÕn×õãœÀA£ lP<ŒœÆ÷+5ƒOÙ 9«r†½3&7¤Ð› ÏJ2IÖû¹¹É4šÒ3äŸ ¾h±eÇôª•dƒZ#¦c‘Ä1}+LÇô]mÇFë ñ€ÞAJ>ëަs&˜IúvVjÃ7âü¡§a“ôXîuWŠÉ=SXÞ1ÎDð=h†Í²ÅôpW{ÄÞoœ–ñÉѪÈr2¸gŠ$Û¬”d]8ež{Yb?3•¸ <+² ËH‹u™€Åû…ÔK/ãÉ2„r›7‚‰Ø'…´Y‘•Æ‚2Þq%LË´¼&X©*FTµ@]ýì„#iLñùöç“RÕ&ªZ5¦e í:H˜á0—ïLJÓ#µSfBÙò€¹‘l…#’î+DÌMÜúçÃ"Ãs~/’òåa±ë kŒD;`FšebÇ®ýª>_ %Æ}+à]œËHÊvîÓw¬äŽ“åߘôª}p™ô•FIKŸÂ†’ü“aLǘÞhY‹’ˆqɾ<ÎÆ kñ«¦é “™¢”ËÄ;’¹‚¬÷ü¥©cœÃVÇ÷"  ÞÈÜñ2zŽZÎÖÏ¢4"’¸ @Z±R£×ncWê‰M§¿fŸ8¥œAÓVÈMð]8 q&p·ÃÄódÓó¡41A¶éU+½Ñ[{â4{ÌÉ”†Ç<×…dÞ·¤µíæ}Þ‰[ Aó4N0ܧÞ,zd³d¶áôœd£azûÄDÊ-£OV ÈXUêî9ó0J²›Êï°önwqÎü™8Â@Ëh±›ÜÎ@#G3OÓUß^UѶªMü¢Ù’Y饇¹ ¸}0®6±4Ž"‡Lb`úJí@S°d¥ºdb—»o¥zGf»v OÜVóÔ¢·v²ð›»,Yn•ìÖC© GÙPæ%}®o;§Á>ôb@oíñ•(þ²ö×àŒy–[£*¥#óÍ}}苪Y­$³"ÈP)L€qÔu¾>Áôªñ@湑٧GSrT•YVrL£ÔV²jJYøZb˜Èm3ïç¨.2nç äÜUQŽa¤GÚ6£jûÑ«öç¼]a‘!€iRâ¬òa¢—`â~ß!r`ã˜Ð;r~§geU-JMÉ$Ð÷Œ¦vJ|ƒ´xÍMl%2LW°Xže£3!`èX¯'JàðÌ•,@™Xnt ›Ò¬€ÞÚm‚Ú)Y1Ü,Gä¾pz‚¦0©#´w»”­'ƒ;VBúLåÐŽg¸?X9âÀ½h–,ð˜2m[[ûÕž•ð-–'±MÚ³RíU=#[½5RÒ4 Ä71 ”FÕh7Å3—›B¼ë7(>r&J-C¯]pù¨êrl´*€ÂQ¤X U €Ù‡ëˆäÀ³˜ÆJ”¹!‹ÜdÇzaÊÞ¹éÒw¶ êͳéÖË\‰†! n¥h:  w$ƒïë¤QW p+ù^¥Ç·øùš¥Ìéû&(Åä HÁvú4Èd]-qέŠ1-€ÇÔ¸vOÏîW±‰¢äÜ sËÓ/%<’!ÜdDÏ¿jC»Ûx$ÍZ ãŒ×¸µ¼AŸÏ•Ž(µL­_†IS;(›MÓàf\á¹Ð0àõ!fB¼AÈ4~Y(%î& +!ÃùÇ–^ÓÇ芩=·`µ§ìF¾¦YU"Úynóv„*±€‰ùŒ±'²/·ÿ)ÕD>=^ -õb„#M½åJ°x×vÔ‹™ C½­!ûˆ‰Yi‰Uû“IµeôÎÒQ—Äs@È3ãëO;z8sÀ±ÄŽðæ:š"6b]ŠX 0N@ïI X©éûÚÄ«êÊmGdØ'Þ“6…‰wP¢ïa}|]Ä #UÔ^CzY °«Í§H£%=ϰ͵leïƒL@oíŽ}"4JJ¶Ž@ ¤£F‘˜~²p%†.ë"d%G¾Îë>ŸUῼržßž À¨^íí"½CÏR©+ôªÚ3Ï“ è{ÕHÉÙ‘C&2R®KžØõSÊuÉÄ)µàûÜ‘ÖhçöWá-@ +2L»Å무F7mϦ½U×l²Àè%¶˜R#0ª|äÈ®IŒL~µÑõ¿¾ÂÔý,Lµå«§adJU’+ÁdLÆA^KJnxzâÚ%W2]5Y]3Te¥Z %“^²ßh£‘3Ñîh–Ù&‰ß)”ŽÂSì ¬êÂŽÖhD¼}øÇÃÀ˜~ÑÔȶͻxþ²czû‚mbxUJ·ÎM¢¡Ý5rèý9“Õ‚Êôµ8&«ä(”œ.NÀSx.Œ}&Sê:H¥ÞÀŸÞ{ññ>ZrCbÊd‚³q¦«:ú3À8÷üúíœ,+ž#Âx-e$ç[üùgžŒ¹Wjû7´È0€Ñ2ÞQtGU7ˈªåJ0@Ö1óô0s¼ìˆô\ôüåÈnT L&ø×Hæç"Û†¦Læ²J³"€E»•;6ÎD»j¶0ÏõæO?s²4€`âî‡H }ª¯‰QÕâƒp4(}&ŽéSWom‚Žrƒ,OÖ2+!«}ôHÁÙ¶ù¯±£^Œj_žÚ#e|þûa©×d½2bYV¶Úd;×â(2—™8–oå”DO‡é ü‘ðÁ(/™ŽHÐÉ]xâ&ÙLËòõK?“rnº¬=^æ`%Ý¢k‡ªkjæ–{&ükÛ1禘ۈZˆ7— 7‚-¯:gUú2q›7B.Tñdspt‘î²öz“Á½†^±Æ/ËóŸ”dª–é­‘>Õ÷¯¢¹1!¶¼*¦˜‰ÞJ™^L7TI/%«ôCáF¶ŠÉ°¡)Y)•1F¨ŠvÀ§\ÐO1çZ€”¢•d¤”mt,kÄ4™#,3 ;ê¥ñ’º„Û!ïœ_ùÃFtdžh´$Ö¨ªE8jl+@¨MÄu# ªd¥˜ñª»;ÿ9SÖHYW#à!~$ 7’! 8ÈZœ56ް³ Ôž™£*qvÔWÅ_×Ïß Ö…Tò’ ʶª,ðbKb´8ΰqó€­‡Q•[/“Ä3 $nO³hô¦l.Y_“ÑË}÷Ìê"mNܶxÊ6ñÍIéZcÀPÁÁhpÓËZRõ ?©å7… ÃD¹%k×åøóQªÛ*ݧ›Ô€Á‹ûõ>?˜ý]›cÆ0IJÙ^•­ë%PâÓÓTJŸ lcÁŸØ‘F4`™Û¾+œ¯‡4d¢v†Ú¯ýù˜Ï@›¨æÖ&ló¤„e¿8Ü®K%–÷Œn1Ù±Fèõ,œ­”¡£Ý0)kQêosº`±Æp#`¥d ¤à‰ôÊa€ãض­Ñ\›#³›–B £‹L6½x‘¥‹÷à@ŸZãx’Í&–Û'[z>k=Aï†É°ÆÛVŽ1·)ŽY™²Pªj ‹§ª£ëTÒ·‰O­¡ùSª‘!‹ªpΔ"eÙ‘m¶*«+<Ûš[ÐÔd²Æ•Ú|ÇÀÚc2/Ï$ó>#%úÜšN&Þfµ¡ZhÆê’»ZwLFP/Û–¬Å‘øÎm³ðÅî¢ÔÚ2ÿrÈÇ1C˜²@2qÁ#·Àö ´¤*%¦.Çk%U ²Ñ]„žXôíuÈDìñ5joí°¬/2$Ы¤1ÁF$0EK éؽ΅…²Ì4  7JŠgæ}d«#6™.>ª·ã|;UýY×_¬0Ý`Õ Yí¶¶X<}¿;Z ICPd£$0íÜ2H@»œ@öjö!F²ÒBßSÂŽ€"£±@VLU]µË9ÐÔë^  °A4MÙŽp#h`ŒÈsí@ŒnV2-½øc”ŽÅ—‰*ÇJŽ·x­Rz™lŸM¼®^ÕhÕ–ÌDn(P;ÐßR6±Ü†m’>gŒ¨ú.Fc[ÐÐ#_Ït%n7ä–Ï¡#ÈÃн|Ê®Ð玤—É|)›ã)1ĪzÉz–ôÈ@ä¦ ™hÇ×å¦^¦©¥7Ä#ù´CÓ1Ú•(ÓcÑÄŽÃ7Ž¡OaOŠïk£%%Ï j½ñ½ñµ°åi1ãÞÞd2¾mUéá.ÎÖ&|朒ð¼€Èÿ½²ªÆFÀ‚†ù|xÆhW•MZ %Aü”{. ±‰”ɪ®ö€í¶¡~Kàë¥ln ;ÒËÂJ} ÄÅd ÅOC¯‘ Pʧg›+WÊø½¸cβÐõíÇd­G®\VŽâ>»6¸Ÿ‡Ãt¤$c"êªT{Ë寚Un²@jÄ{e>ô1U•0HLcnUY©Üªs a¸‰€è›aÖëP»ª×Ä ÅvDíxVÈ‚O%$‡‘µ# }=>¿5ÄãýrÉDVšI2$·¦ïÏÔ÷ÊdÂE&ÛXåÜ—¦ 1B‰LÔÆk8P»—ÔÕ{êj\-xÌß·¼& J‚Ù¦ea\%¸RëåϤß ¶¶UY‹(óÑN¦ß±& ÃàÄŽ¢vf« §çVï|ò| uÕòj²õÔÞVæC“¬Þ} ñôø2†>‡öQê¾[Œf/Ù]"O|Xî"+Ø#k¯!\$ƒ[ƒF``ÂQn(€WíR)zËÄÈÄa ÔX¦Çø(ëÍ<7¼Fþ”@‘ “Foh`™~%‚^;ó"ŒïH¼5®ü ð”a‰ÀÓÌdC-‰Ì?<†m£1BË4Ý¢qJø9Ì矸lº ~í¨ibúÓ¯Whª^¾ýjذIJ ¦‘é)ûsž@»RÀ•ÞqæRjÉ&&@ÇÚaAV‰¡•W’óyy }SòÙ?pqÐBœ'LIO,"(Å“ásÙJô”`¤qªn9=÷{“ ,>³˜èjÕí€éˆùnC½VjÏ Ð”µ‚˜,0íÜß\”ºE‚2+üíþ|âõj×’†U4²AÉÊ|ðŽ¢é@þÚJƒ” þã›N@‰|Í‘ 7 H~³’/­ª)­¡ÊÁ±}:’!åz ¢Ôn¤¯VJŒ*z%|¬ªÔzJý:Fæ¼¥/’ÉÈ4ºèŒ*,wüŽ$¸Ú#º,2Yû´³œÿ ªk‚¦DºxÓU)ó„…RKZž#Oï)ü+æÊÏ›h—=e¸×³pÊ= .$Jm-†Çä 7çZ’¸ÝLAR¶Œ£è‚zç™^#¾A‰Û™ °€ˆôàdmÒzY‘E6…Þe>üi`@6T#œhOšÄ4ÜÎåÚ…B¿£mÌ࢓&Ád@›ôÎ ãèK™ ß…ñi§ÄkÁ$&hãÖð^RÌ#­*›ˆahg žgXVBÒ‡›²¡9ôR4m›Ü}(T=—Ƶh¦0=`g£1ôd½+UL-J45*a:ÆÌo7&‘­· "1z‘if[µôâá ‚mNc:,ÛßkÔÕ¥t‰6|j‰/}~¤úé'¸¹€ b²¯“žÒ&诗@( ¼#@¶Mð|nÇgÐE_»ÌM¸`&òµ«’åS©ŒÊ^xƒú}„á©·Yª}XZZC¦t}—Œ3¨Yªô&4|x¬(ñ=† žL#C½ð2L#ŒNÙªøÌ½2Ì„@I61ÍJ×é,–-@¯J†qµ§” Œ®$;–ɬW#‡øÖ Êdª¹mÕý¹¨‹ e+mÕ6o+²¾Àdº`|&ô@³dØÐªmUUKŸNÊ.ÛÄíY#ÿs]ŽM$àæØŽø&b|`nºðidSÚn„,øPÊŸ¿nLÝ~D]©oÛÙªJ î&k¡Q²–ªŽjˆáÄm³ê Uws ø•Á 雡½‡ÈÎÕÜôÂ2 ÐdN/º‘ªMxv¤TêÓŠ\#"–…#þp X¸ÝÆlç6%òls£÷™hÌù£$Ú 뚀`ëøûßÿ^®Œ‘•æ°Uðíœþ¸ß«w Y¨² Úw£J_‰s±2zÕ=/R¦‘íC *ÇËHYWb¸c¹q—û¼?qW8s#£É¡9Òd ˆUkÇPÖÞÚ}Cjlʬ›‚TÕÞÅ•$Û ºvÙ4­Q»’^ß±–©d O ¼OŠ• LúÐ'#µÃ)+á‘ô2¬ÄM&γ$€o=½E]aÕ™`(Ó 1rVa·kâŽß^Ê^;M?t–tTêÖÌÛ-’>ÿxžnAFîŽiÃÄé÷sM¦ÊSèJÐíÞãzö²Õ¬QU»^ï(ÕÒ•chˆ•áJŽâô]IäIƒq‘ÄûÕqøóÿ)<‹–ð^°H§¿=d=•pÖd+ÉŽ­ëêYU^¦É!k)`-¶êhošg÷$`‚$ð W©­‘ª~BêTÃx ÜÅ=D+)ÛSÃd0ÆQÌ$F¤F¼p¤ohǪ2^Kƒ`-p³UÅ„ëͼŒYÿûß;Ê.â‰âÓƒg…wY¤ K)[o8s çx%í²@.(14`bãjÄ7ˆ,׈œÞQ‹hœ§CöÉF6™§[äÏäö}úªd›OÎ2 ©kß(&õ~'KŒlõö5ð¼}ÙâeJÑDÇîâŸlžé[£Ï‚È¡^šéÛ0Ûz×¥%¨QÞÜWÀÌmþ€HÌ„'% \sÎŽpÇw }Ÿ8ÆåÌë…ªp&ʘÒw)¦Íãk4¨O¡GЕùîè(ˆe@#5ÊÛ9É;Êœ5 %½&®äh ì›'L,˜ûê"ÉÚ0}U¬rVUZ#A¶Há˜Oz†¾MT׈騚?FU$¶RG2Ìd­—æüAgžƒ+ÉŒôÈšeí´ÁªõcúøëÚ`%ÑÈ|všJòôhÚ{,Ø’ZZ )´{ tϪ2¥»øG:@Ésv¤obÎŽ½2«øî¥DР÷šª…j¶[ &О2™¼ŒÑeD†-f-ª™OÙ”ÈÆér¬‹·þMfíUûÊ6±5´ Už%Ž©‹y»%– Žýö'ÎAÉeg8[dKRNcÛ™ÔÞ>9¨x“9C¸ª)Ϫõ¦Ñëh¢™Œwìû¦Ë/Â8M`dk;2ô¹«Âºšˆ­"ñ¦T@IDAT:ŸôU'¦|ù¬$à2+Ö®·œs¸µgNŸó²®÷jñéeúÖÀ·›cšxY;¥5`ßGGOíA0^{ òd‚G6 ŽlmíŽëÊ#”Ìò{LÕQh‡«úüï{Å™‰qu•#»×ç+¸›¨µœ‘€1ŒòZ3£šx€ªÞÛôù~LÌ\8Òÿ_ÿm™¦qëͳ¥çÀ§ ®K†};ýàS²ê³Ç `Ž4vÙ/SžÙj$óK YÎ?Ú°WÕå#Iƒo–#\;½c ÿðõc„^švÃ;zûQçF¶5 m eŽpsá×G£R|ä3ûëKïXKbþ"muY(r“iwÍNJÙ1¸õ·|¥ ¥Qb®]ΙJ4h´È?=†ƒFW ®„€Sª’‰ŽøÂ—J V’U;r†1¨+}SŽÑ—Þ¬ÈvŽ¿õóÛ>x¸‹(‰F7®.dšwVÊr+Ñô#àîÚûNj©«-³‰Ž ê.°@öç´§h9¾}:Ê|D›Ð86¢• ÷ñ%Cö%ïö$`b‚HǵӇ«¦G6Wî¦<˜Õ× æÄ‚IÓë L ÓJªLà󇉕(1Çú~j©¶ÃºÚÄÃjéªå¶žo7-ªÍ’•`E†GN_{å¹}þŸeq +d”iÃ` àî8MXîžýO.”d 9øOŸ¬Œazn¢eñÞÅ“ÉLTóWÊÓ±A¾£¬iRn.†&=@Ã0qÇÜ`Ê3õkÿ>*ûè¥W•ûœˆ L-Ä5P:v‘3!0}äaGVJß±ËÆozSd¡„§0F‹à÷&6WûIxŒ‰é±˜1½6 ð=Tþµä¦ªÅ@µR/@`L¤\KÏBá • [†²8WÌ¡ßeŽ4Ä·òIÖ`^KÛàf1<5¬7gŒ£j§Ì.-Õ–©Frx±c¤LÉ(ó±1Þè!=hú-ðºÁ]¶µó!vìµÙòäƒíÙzý%ÃwÀqŸ”)dJf¥½¿ômOXI&nG]¡—²Jp¤jJ<2d½Ž¢Ñ‘ŽFpC²ºÂŸ'îH–ƒö.ÂÙQVõUQ:6ãîMÁG< KÕtËèíãhœ^‘[-ñdñH ,:6Ô8ú€¿§ÎÓÂF{jš¢7áÖ3")‘‚•T‘¢)ÛVéËæ«Ž™Ð#…ñè4L0É\Ä÷ÓÕM²[À€PÍ&ŽArètÌ ÉM騔”a‘9ã1Ú“šLF’µdÙ½0B£L“LÔÂø0+-Ý Ví8Y—%è³?+%­‘­eš®$`á2o½ùDPÂYÉLuY€9Æ"1U•ÈôVêúX‘U9ûhzœÜ`¤^¼^ž¡ªQøe!ë•)åÌ· FØPfR•’€mïy…Ÿw0 I¶»À­Ô½êÕâ(EâÖ#f^)>ÕÛq.¢EÆH2Gså«ÝÚÜTÓlP†²’Ƕa†|rhØ-”ª:`äžC#6QI/[w$ÛzpÁ§YÌc4Zˆk!JZäðåÎ PÂL` ¼êœÙÒ´à¨1g½ Â#kœ3#0Þ vYW†ªø¬È”ĬðUÉÒÛŠ€ÒqÏâ(,I ø”»Ü!)uq€¯ýùJ¤¤ùª^úÚ[#F~ûË_þâ?4ÄŽB›@6X$Æ'ޝ îÜ %J¡êˆßþŽQš8.wÑåz+5îJ>?*ø÷'¶È")­×ÿ2Ü¥-8Ò{VØn­×Qoš-V»ãJïç±ÅšÕ 9ýªF Á•hàB•ÆïI+‘ñP:n\&ÈßÜ\ÌÖÎ!O¹ãü·*>Ÿ1Žô"ž [Dú­aóªx@cCÛ£%²ßÈ|0^ÃôJ²˜ǘ¦·'†[8Û¬0“ ´•‡ -–yúrä ¹p£ô3'S”aWãûcI67L¬Š¬ø-„å¬ÒDj ÞÓ,Xn“øu1qÍ—¤D.zz|ÊÜ`a„cŒ2SRv‘=HdGJǖ̹ÞÚ«´?RaœÒK:âcrH€ìX#+±›ë Û¹^Ù±o#@€¡éHßá>»¦Èu©jÔÞ#8.®K©éÙv;8%ÖHÖS;&n\¹‰óÔ |zŸ6]U¾•ûƒr¬œÂø#Hp±D‘ckm‰H£·p,ü\ém¤üÝ ¹Qê ÿ/[w°%‰m#kx¡•ßTDz^_ÚùÌGþ™Ñti°€ƒ@dfU·dϽ=¬+FÈ”ñidžø>ª&n\ ÌßQI{—Ï$¥Œ$ÀسM¶°*^œmnT´@‹©ä¬Z©[7}í4m›-G $†Ï)tÁói2¡Z/Áv»M‡'@ Ìc6WÕÅ}ÑgµYc¸ÙÐ2òþú¼%™p¦Ñ"v…6WuYY/MËô#çˆÐ 8¶6=œrW¸>ú†e²f%ÃØ¡¡ñyƳí§ÚuüÍ ™Rã4jI±IžY%n[U@¼×G:"w í?|Ò0$ƒ ²V² ÷¿ë‘iTs¸ö²£.AÓÃ6ýt~‘&ÜQÖ^L¹ç‹$c%%œ¯ê“Îà.’¿BCÙ€¤ ”³ê;Ã!%ÁÇgj:¯´FÕqƋϷ¤J¯+™/6“F5:ê"`ˆqÓ±.G%Î@ճ͵ª®J`ܱ¸‘^¶7@&é#×[×9ÂÌ·=F°:<ß(¸ö3^™ˆuà6ž”o2ÊîÖ*Žø^SI¯¨kÀqU]» ÿ¶Ìjz<|Æ?Â$±¬*zw%G/e?@S(ÁÚÛD©¥¹r‘¼GÄ8Žïh Ÿ"ÿ&bRÊ&Ê6¬Ý,GbGíŽÞySúlA™[Xv +QÖÛ½EûÐ$cÂŽ"Cz«öYT…ÈT-ã ýø<¯Á'±u)|Ä’‰®vö¸‚¬Z²Î¬db¤AØ<127üFÀºRrPíùøYÕç¬ Ë"çÖsäðY_!ƒ*Q¶g-›åhD$1ž¸Ua¼A6Âq_’÷vÄÚ[O—£jnŽøÖC²¢ªpáHÐÿúÖt&Ÿ¦7+ÃéõfޱŒF뀣–‰1â׃ŸÎ‰)›ÕÚY‘­}bÓ·hÀ„Ãv¸Åóà¶üþSZ&‘Uk‡”€Ï“¿Z“OãRGöÊi„ÈÇwÏ'‡¾™ë¥aèã ×HC ;"cã)Å”ª4IJ)d)1‚L6ÂhX#=ãl `šÛz>¸ö$ÞÂz3!>Ê,dQ?^p sá ÓØ^†-JÊJ­%Ç4’ÀëÔ˜Æyb2”]Rö|zÇ5b`? Óc(ɶ3sC;·'CdïKßÄô¾ß­-×.ŒH¦%€Áç@¶¡€Pø圑JklÄ2ÞsQNíF;h†7"‡ íñ)íÙ¬–lŸE—âÉmC7WWn»é½Ùç+•3ÏÌ=¬*eSxƯ÷ìíÆ<ÆJÇÜ"›T™kw,ÇËÚ“…ÉbÈðŒ¨ Çc…£ †C ¾®²|nÓ¯OydÿO‘‰¨±ÉDUŸB÷åŸP¥w¼Â8F¦÷-Å sÖøø¬ÝOªõÈJæµÅ5¥kÊô1)gÒ±5cÇË edsã[fØ\½ÍÊóÞE»‹( <1àãvÈ 1yà)R; ’‰L³Žé÷Ó§¬QÖ¨ªÅ×nh½Žý®ãƒ×%˜L†‡1>@ 9ô ‡mÕá3Ôγœ³¬*ÇsS×ø\*F•aJâ.èØèügÔüú/™Ö¯ÆNn˰cýÆ``zïÆa%>°»µ(œ mrÛ8²Ó|­”ÈÒ$Pu´ ’°F`M„‰U›K© î@v5-˜­¨v¯púrŒ{ì·$À§½Í²ƒÑö‰A6Α žaUGÑ&U;v_9†þ©_ɱ nÿ—­Ê|G˜?¾)Íu$h"~„wMƒü.‹‘ùxŠôeHA£‹pôÕo²¡x9 @ *]ϳ%-Ó‘ °xJXu?l˜‚ Cfœèõr˜-¾[̳}¼<†˜UƒrsÔ«¥õ2§õÊ•€ ¥¤ah4Ò½*ýØgæd[£•8®¬eß$s³` μ/Žoù¾í9§É*,Û*}ÎŽ5:î:-€iù.¢Z{WhD·  ´y Cyd%æt ]÷¦ogžÀd<áœ]P½öÿÌ— Te³Z€¶¹¼Æ42>R¦o›ønEÉM‰l@G%·hzUŒ£jþ Z•2¬J–Ïç+bEýýá‹. êó¸ª#ëŸÀ'{MÇnuëŸßþ‘Ìw眧ÊZ"pw@¶7½irþa…d… ÀµxÁSiïâ8ÜËf.'ÖåW¡¬Ša(ÚÇûx19Ÿ¬:áJÚ]Ó«V²Ìõ;JÿpÓ,Y/1  *“ÑÔå˜JŽÜò‡1E+)ù\(¹¤iOJ¶{l ¾FŒË&è)”0wøù@‘ÙâÃÛ“™*F…£èXn7X ¡‘¦Uµ`RàU|ÇôJ˜nÑ_ÍàvÓËabÕ|Æ8ºÃñJEkÀ@ØÄ”­4™*œƒ&n:±Û©Šöˆ ®öƒ)冷ï85ÂxâÈ4Jüåº\Ù±(ñ9kÞŠÙ+Á9³ô}gúø²mœ*%¾¿&f¿eh0ˆ6Ù?+±5W/·ÄŽ}É·ù6Œ|[*™’s¹¿imC²4 ÂüÛ°¥ÖÐÕ4½€–ºò[£# ¦7Ç´3²ºxJ† ŒˆçƒJÍå#`ž­—?­™wX#üù'ÜØÔ>?'ý¨´zYՅڳ؊¥VÄtlžå¬¸R€X 2 €LfP¥Áˆ)•ˆg®Ô£l%ULŸÙmý´sÈ™€ ŒqÙF;òt”{GXT•·»zªJ¶-Ò)ÚÓ’]2$½‡Mo¨ÏÎÖþ™hl %a%@i+!õ Ûp‚Lh€r>µ`ø4Ì#¸™›ƒªèa%˜‰»¸—\IK‘Ü#$v0¢@)'ÄŸù{5ǘz³’é+Ù Ö¸Ræ<•à}Ä)T×›²§ø ?_W㈑N™ œIÝC¶+䀪ÐÛ¶¡L¦é"·ï<¬—¯ÑGZˆ) z¥å˜ aJXèÚ‰2¼ïžÒ+f5[íÝIëíŒ Ó„«¾#`Lä°ìÈJh—1€ “5®jpS¼Œ_¸É”jqÔbF2<\{iš˜ƒêíøõSß1Ù}ù$Ónt—)ýÔ Œ®îÂAÔh÷«›Äs;˜L©µe‚z¹¿º:t·÷|u:²PÚmCcƒJUYëM9MÛÈx¯+†[ã”0ñ4Œ}d7ÁDRv‡d‘dVÁ:]‡¬‹? ÏЈ®Ùn•ì ==@#MÓ&œÓÈ5²ª[¯êˆïMT ÎÉðŽïÏfU¯åù˜Ó…#¬EîÑì™X‰ ‰íFÖ±¬h1¸Fßp½Ï•™$nPç¶¡ªm^&ÐUUŽ"‰E¥íP•LÕª2FÆ´‰é]!MǪSý!Šñ™ÐcÌuGsy:F’ÁdŽ}ÈZY൴0¦MÖHt$`õVÛa©j$CX4«)1p‹ýxÕɲmh»aXù´CJdÁJ;¼{ÅÔò–ÛG&è"M™Ì±wHSFæŸ8‹µŒÜëaØnÞr]»ïº0ªí÷nŽ¢®rkp¦‘«]HàëÑûëBÊx-ôŽÛ¤*^»ÍUÍÄ$k·xíïJÈø~0a]]--»¦Œk.¦íæ(†•òL«2ŸÕµ|~÷)»°I ÅDÜ™ 'ki™Lp¯7 EÔâΫjÁkqU¹_mH€¦ueØMä~€)+QòÄ3‘™`ZÒ&“a`]‰‘¢é@»™Ò¸x¸¹<3Ï_&=´£vGzùÌý‡ªÞ~³Ô(ã9wÔÒ×®Þ²–Üd¯á¨EÉ- ÕØ51í<«ñîFÆGI{ªv†ñhD¸ sÐëØ;Ó0±­#%þØÝ6¹)€,ì¶ß’™çPWWã ïˆñ@%æ@ïÖæ²Y»¹œbäæ&‹Ñ¾))™«vÔu.ð|¦>…îE™˜!±.Y©q[µvš–˜Ãø¤Fí ÂÛ0gGo¨”¬Ñd"}k8¶^ ”[OÉnïb÷Å€¥œ§‰¬èå[üõD€÷cè"@Ǧ4S“p£ibZÙ8k4«¡“éñ•´tG£Ä™&«v˜a½4c`$ÿ6)#Eþr]¬ r5âü3ÁÔÕ,úø¾Ä"·^ƽˆ1‘° Ï¡KÕhUÊŽò~äñ¬ä×ÒñÞà|ý`-Žp{Χ.Y H ³²ð痋ˤ+×@וگ6Ç.϶¢·kÀÚñ°e2 M²ºLIÓWA‰ž8~»:Ò ËT¢Œ|^|ã8«Âºð޲£À‹Äx-ŽþÁûºW%{é(÷ŽºØ: |Gþ€£ÿu9žÀà¡ðºe»µx„Ú;ÊVB’åTr¤TupŒ¼'j:¦ 3¨éJFÉJÚÛŸ›,rÈÜÄþ1™ ^Æ÷—&Ÿoʵ¨Z£mÓ+½ŸN7â ð–!­GÜz» J%kh·O Æ,AŒ'Ã01,÷uÍŒ¡¨Ê6¼_mZbØÂôö!n9'èhbA#ŒÃg%óÁtÔU íFF»WïÉ'%VÚ|½x†)Ç4‘ælðý5GÓˆZ>³ïËäÖ,U¥²Þa ×@Vݸ4¥À8`ÿ 5ø}Ö˜v@Nf–ÆJéá>Žø$sà>ß¾ÂVÄÈÞM6#¾(eCñ0¦·j³Z`2ž½¡–vhw$£÷§#òý ›ž ÉjÔÂP¦'0š ç–×ë¹)™4‚x‡¦´-gôÒ,9Ï _¯öÄLº³ª+7>ªÝÈ ‰áƒÉy9¦{1œ Á4H8Ÿ@WÓÕ˜øMÙ2à •ÛAæÐ¸Èx¤ÞžFÂg8%`í½pÇ<{zåâèÓÇ#¿VFˆî+ kˆ†µÈd B†[›yÛñ†Ò¨:"aY0÷×Ç;ç$/)·¶‰ôªÂ |ãjìµ3LÖö™àYðlg ÃV­ÊPIX&ÆG¶‰0^É,q|ÿû_¿QÏÿå#ÇùÖ@Ç–…#A wÍY‹Ÿ®Ž§á’Ž]ÉO)±Æ>‰îÓˆl9 G¸p¤é ;ZΡ)˜¬dËðx݇£Á7ÃÙQ†û•Âñ˜ö1¨…/Fç‰l.F¤¼‰•|6dyfe´ª–BàY¯öl1[2F;¦¬ª /FêU­”›*F“åI¦*ð}a¼…“Qê•“)á3‰Ç¤ ÈBIfò£„מ @4]•sÌ›­§ÅÓ١阎d¹õ?”‚sY›áa±­rK)7èv[Óª²–&&ƒóL€dÃäÇtbíÖ®”OYK÷’=Eªiw\lž€¡#“‚sÑž_ú<†³.|J#k™çÜ Yi¤L ¯Ý½òI [¯.æyØ+õ‹ó6¦ÇXÕ”ñ”< ²»ÂI˜Jøqñ™1ñÛØ q2Ræ#:ròœžC =AG2¯w†J&î˜ ~Êdí ×Qg‹Ñ2¾cû)‰¦haÒâwÈYv#™XVŸ?¢ØÝ>×;6߯ZFzr‰‡1ºlVi2L<àèãl‰žØ8Gѵ›žÉ˜|ÒäÖ\LJ¶€5¶•£j/ÎǬ½~¶¯mX‰•\4VM€4þ`{ß 4 ˜ç¿£’Íëe¸7!ÛfÒ¸ðŽ–7Qö†µØ[bY8šröø~'za?µÈ­ñjìk‰Ý2úõѽîÏ#œáª^×”-ÓÄÞzdÛ ¦Ù,ಠ-–mzSfB/j”SÆ8Ê|VbÛË+ Vüé;Âe-]„€ƒ¼7!†k'£'¨ ™@Yqß)yæPU‹Èvر ko´.ÑÄzUw‘Z8ôC—§L©  þxm~ý *‰öo ‚‘‚F»ã~­—¾LP®Ä‡RªžN FZ•¸ k‡sp$ˆl®,4Ê4UáÌ1ã}v|ús¨«äH2˜Rf"úX“1ì íƒäßLä2%¬Ê™¡`ÎPæ‰ßˆÓù|aU2O¼æ(®ühràÆ–ÌˆÈ]$€é•2s‚:¤æ¥¬MÔ£¡%Ê&ݦóRuÊôÖ>ÐG`K»m-29™/V¿›Ö¥&}WVªIÿ§í#ðm«=ÜÝ[¯­Ü%0’X/½•tå†Louám¢—¸*ÆQTjtíHVéŽu9¦ô‹Ó Ô%«"-U‘ Hã˜,«ª ©ºQ@K7âû€šB#š °JÖú[ÿüÌÃUã{|¸`b(^™¸é-6 é‘56®ö–¡OÌG5¸%û5—>Awµ¦sÓ[ðñâ 0W%k@ƒJùÀl/w”²à ;êUC =ÌDæ6Öe:†³Üˆ×ªvJ#º8æL½AiúF¼ÐÕÂF7l\Ë`”„.x#ˆ‘{">)(ù)†ãû›8Ϧ4Ž&«Zh,'¦lu+‡T-cTµ3µ8úì¶­rKF»€oßIŽefi}|ù(•åLð=ÚH&ªÖå¸Mˆ•ÒpÈD/@Ö§¶Y‘izmÚ¹½S¶L›8ªê¢ä,æ WýíÏ?ÿì@§|T7r¯¹Ìô[\i™s-Ì äv“i§­!Ës€³âF cäz÷ȦÄkï›às3Âôþ…™pä Ê`Ò)k¡Ù>xšJrû(߯Öq¿Wn«ÖÛ&J&jdgxîJòª Ub’›Þ’ÁEU9Ÿv†ÅHz±¹k¤‰Ïœ¾Äõø|UðñZr˜a÷"ØO}ÌÄó?{ÜM8xj9[$Pnt½H §ë³sœù4˜d|ëèû>ðoIü‹›Ón-ÉäîËŸLnn†ŽíFŽGêrsU…’lP¶õÒ8¶F ã8iPbz¡šG¸öJ}“Ûíü?£×YÏ>[Ú‡£\j¹W8?êÄ2R6@$ŽQµ«pÄOP»œ' êW¿é9Ðç¬WIdñ™#°®ª[`ŒÅúÆ!²h[¼À°Rm ¥ϼÑ1ޑމ1®Ð-¦q‹aíª™Ï™@FvS$·Þ¿U]9 ðã‚ô˜|2l &‘rXîõøüᨚU&µp®$óQbñd4¢.nùxOÀP……Kõΰ¿›;lëjÛ| &2ekÀz‰åJ%&´dk¡¯=}ùÊÒds£,ö&Žbs‰…)r·SJ,Sâç¨bâá¾*¶*“ÀÚÓ¯7Ã2âÚ‡3o¥ÆÉÚk‰wlÊÜRn¨c»yJS± @seØ-poBßi`@íë ËŽR/ÐDzß+YÐô[[©F MTk¬Dé.‘rU%ÇÆ½]ÈF´LÇr½ªŽðÂèĘo~ï`®)xÕ@£;²*tµd£Dœ­*€ ȹ‘€hJq.Œ’9ÞêéÔü×IJ=±—}ÿum{ãÛ@{}nÑ5Òà1’˜¦¡ Ê– Ÿ¬ûƒQ/xs ‰×’?M2ǾŽíp+Ÿo|í)ånÁÊk$k½îÒÛŠm³ª–³ÂoϬØî"ÙràY£j]]D =°›@•¾= ’1ÁÈ"f%€ß-œ8M|CûÀHJV°ÞJŽ?bãÆë¥÷·lÙ[‘!1îÇ?’fU‚¦#a< QÀýœ3⎀cãê­1½9“Á)󴣫á1{ó6Ÿƒ*™Ì™F5Ï…#ÐnpJÀˆHÉ*óæ& 1E»ßîÛŸ‘d4œkq4Žy˜<³úw/­O\/27]³ðÜdâZäÞ‡–ݨédm…Á¯+™®™Ï-cÑqÎÈ®‰l·.HŒ4«=¯ä3TÃ!o–¿mŒ¬ç”÷‰³u—6ÇgÐÂ_©ÞÈÚ›²A@¿-Y‘9   6E xâùô†ªyª*‘¹ukà1 Fv#bUÑ’Û“&6–ßý?ôQ° ¨Æ¨ýRg*7†LÜqŸo[²vŠ—›Úø™§”÷”ÊZ| ¾ñþìi„ì(›n¥.À ðSZ<ç [Ù±õ¨ï§˜¡œè« š@æo72˜¡)@wÑ¥$ã (áZÊmÒ¾®ÓË4”ÈÓtž¢ë(áa¹_°Ý9ÅG2imG%G.Û ÃSzåÖc¼v|ƒzn¤$tµ¿®yf¨š¡‰½IGÿ×<éñØ;88âµÏI/*MÃ<œ¾òÏïôÖÐÕŽ^/2=,ªê„5äÞ¤máž=Í]äóÉòQÅïãÐË3åÌ۪ƪ²¨·Y™ÀøôŒcbû3D;à+9ÆË˜ »”2q hÆÃ”}úÅ~su¯Ä•tí}0Û-28Јœ™X@ÂÚ“×1N ä€'–›RÕ @›˜¥…­ H£™Fi]s@ú üx)s£Ì'dG Ð•[k” RÕþþZ×Èœ@n“˜­Z)ÿÖ€³R d›¦Œ!†=—c zEÕdpüùÿ˜¯r€B³ñ€p ¸ß¡ X‹ºÞ–Hî“Áz›šŽiƒ”ž *ñéØP¸_÷x] Úá>QŸÆÂõæìH”Eäuú¼Nƒª2QÒ^Wæ0~™²ÑíЯ˜µä\;Lì È‘À}“”(µt‘÷:ÄJûÎÙ­ÍÉ´Ô˜ML]•ä½ 0ZDËÄWbÛkÐ0TêwbO¡ezéL¯ËošþkX%Œ F¶ØëkL£n%Œ’v—eÔ^u²Ž×EYU~[xöÙ… ËJå)Û“ln‰c—8Ì_‹ly<çö¹C>ïFÙ;sƒ[,qþñm»‰}(d…®d¾Ÿ2=Æb€–l%4¾iò‘µË+!ᘔY5%ž #ÍJïØíÒ#­— Þ‘&[LúG¯~Sz„=r> …)ã{ z£D&óð°€°M«6Ƹš0"±Ü8@£LF á4MÁŸy÷§,À?A-HVÉÆ7(²Ì¹qŽdçg¬a[‚‹‚cWrÖþ¦æg¸+©¾¡ÊAnÀJ&r¡šgß–‘ñïbÊÜLÇûD«ÊJŽ}N™3©iá¶ô­Á Þ Jw tÁ ›žžÉÁC»HÇ&jDÂUõµ(µF&í¹}ÇÐër¯ybVõ#ÇJ´MŸ¦åeÌn€IzÆ ²…¹JY0™/"É´ôA`μïïÊY²êÿÒØÅ‰ñ«Þ>¿Çñ¸£>FêJ è²~‘§,ZXV çé¸'…‘Ä•ÈÚÍ}»2¥*™…[&%²#‰1b³€Ò8ªe¥§çvL±GÑ‘#w£øµc›UK¸O32ÛN¬kJ˜Õž+ÃbÓ)¹ùæ“'eb‚ôÝè½BzÕ•à¦È€ÑždÌaäWøë»ª”X‰’Œƒìú—Ž ê)è>[ è÷Lx¡ä&ú¦ÈðŽ›¤ÔËéóT¯„‘Ä 0Æe‚OÖÑ× îªÓ#…ã6QHŒÞ¾Ÿ˜®óù¯­Ô®ìó}m0ÆÏCF:ýkG¥ÖÕ/féÑ›72Ïdw ,ˆsèX×x°{ëbB“ Þ¦4Ÿ3²Ÿy½ßÑzŽ=AnræýK§yj1ˆž =YÕrk1L WµªÑVx #™aŽÄh·dd½áÑ ™$~­0”² x×À4YµAÈöÔØb9ã+Ñ‹H-z[ÆH]e8%^hOìO,½µ«ö!zÕd)á>V2XÜŽs)-r`¤£FA©±Ï¨^o´ÒÙæûC«Å2ª½¡*–a-€jzÇöáÀlJŽÍRÓà ¿MÞúù{e¥EÊFä#·R%G-ªdÅ™@µ£hº,ƒlÃdZ4+ P dV$qG@hçFßÎ÷\£c²Ý®öYé¢ÑH/Â2“J…ÆG<̄۶u„ ¦c¶¼jJ½#°ÇlŠœ!ð:lVÓÙ´ö#ß;n“dÓðÛ”42¾U'Æ›%c'ð‘r›ˆLøÃJ™—oýÙh>ç·jçðý‹0Ì¥c¦ýnrÛdªº²†w|JSÉD¿»v‹f«DÖ6Lj¯+AbíFÇÈŽ™Û°ý×ëŽ×¾‡ÈÊ?pÐÞh¸¿&Ðà{Y¼ á#ײWRÊS©}´xJ¸M¶ùVÒkl b¼ÿÓVßW$pÌ#’F4½YG¶ªÄn¢˜AV¹ÉÃUy"åZà^ƒ€ÿ«Y/AðbmgU‹v†pƒºéad³6½^£äyÉÒw}G|½ëŠvn"FKkd² &ˆ¤1ã"ñåÄpÁÍVÅœ-CV ¦tø0?öÑ‹Ù]`$°¡À–ÏJU$ËÁD#‰áޝžFøÊébÞ‰0¾v½9`ÒÀø€‰Ä‰öœ¦£Ü2dý˜È Ç®ÖH-”;ª¶¿ÌYÐÔT%î“Õ«DãÏŒ™Ôˆ袧نUšy:âyâaWÌ¡ÆôvP™ðÇÝ2H›Pv”•܈É·sŒU1°Ðu¾Ð¹8Ã]¯UÌ0•£ª6Ç,0”ÉdªÙõ²Â ÀÉèãkD6Z§|1«¾ z ¢dñzZ£â½£\£?Ej‘»#@l‡®& ¤¬ _Iv¬/“u¯ÓóýŠtACUi¬j &L#6™€öç½È¦ÄXØ×EÃG#ÀMWž•jŸIÝ(7½@+É‘~†Ä6o gU¥Ì‰Ã޶"“xÊE tÔ•>cû86Œ Ua¤À1qD†e½+µjí­Ô -ui¤}"‘Ž|à<=#ÆQ¯[·€@nr$lœF‚>¾È2²9™y+­¤Wô°¾¢x2´‰jŒq˜ÈÚ1ÌU¡cV½ò“6LfdµðÇh)#UkD $“ÙÖªø4HGUŽŽ.få˜ùFìh4Y[5è]&çržé[ߤ0ZFʬ|(G‹é…½¾qH2>‰3¬TW-&½Üe«rPª&†kÿ¶þÏoíñ5fÛ¿…Ž©Ú—¹=1}”@ÎëU¥&£éÓ9Îô:€XO.=¬¤? [T&FÊÄÜr•hÆ_û3¸–yöv¢!È9}™Œm_2¿ý#9ˆZ²^ÑÝ”òœFoÊÖÀÝ>ü•Þé¹Éd‚UÕŽ°RûËHsåL*Éù'#0ÅÇÆêlùýg‹ åþL" {7gâØ¿‚Óe41ÏvP2èúÀ5UGnmÊ—wÌAËL²• 5Å2+JÙG|É2‘žÃL6ˆ¡.|ûS˜Ue¼,”ú¸M‰éR™ÀæÂ€hÂrkd¢ÔæU•&~j§´OKæC߆ÖÀÔIì(ð›®$cêšÆPV·ïóô&ÖÕ¿;òKJ;e&¹ÉÇúûMSvÓ†‘Æ9f‹q,~¼¹«]˳°Rš<ᵫöȦAJ>&GÁŠ#;j—É´„ñ¶z÷Ñ¢„á/×ÛJxúï(‹d²à¯Qîi˜>ÏLÉd2“|ݨ ßZ8Ÿ@í)µkü±!·øFÜ5χåÓÄh̯Wd娋 ÏІÒqb2-•üÆÀ¤G† ²"V}ùŽÍ…?ßB ”,\ÞÒ왑”]SõlŒT kÇÔà†¤%Ј3«¾ ëÅ·ã´ð‘ 2Ìf3Dûk¡WòÑã™§äOÙÏ^¤.%O&Ž­älhGÀ­Ý>e 7-ù¯%O%@µ#`±4SQÐ|þŸ‚à‹’©õÔ†Þ%0îм¸ÚóvÅfä@‰çI ”—!èè…2gÓkÖÒŒ# ­\äàæÙ¦<ËÝõh8ˆ ËŽÚY—¯ÇyqGæŽÉG$“4ß.| íÆEjÌœ ‡HÙ2dé×…‡•2$‘óq}Œ³ªM±9fo¢ÎydÛ*mmÎÂQoþ ª¥A¯FïÛ®Eu³§ä“€Un1”ªdÝ" ¿AÓn‘”x9ì”üհϨ®œñ);*ñ„?Ÿ(ʹ\ͱñ}xJÔï†À½”®Ú·M†/?O-Ä jcÇȆ²5K 3ZÀ]£Ñµ‡9ûÕ>xÀq#ôN¦Ô Œ®ÄøEbGJkÈÛÜøþaé/2zÛP¦TM,ëÍpgD¤‡‹záYÍ Éª¿ûO@Ƴ‹7H©”¬úîÓ= %s]½ª# îa"r&†ó'ëÈY Ruwh |²¦ U…––Ç´ €d«j ÿÄ£Ñ1ë­º)ZȘ6iÕ¬’©rÀ8Ê}+|¥‘MáN^6QÞßÊõ dκz‡|ð‚›ªR‹×?QÁi¦è󰹓áù4w$Ïžšh &“5¶[¶”øa¥ŽcÎw–^‘Þ½yâif÷˜‘u©:¶¦Í}ñM hDbèMÙHÇøÚÔH˜a+UbåÃʪ)r[b䦴@úf)™‚/ÚGãª.˜'M¸ˆaïØ L]4UÇWjã²oÌu=i³Ìµ’ã”k¸ %2]iˆádÇëû½‰©KîÓTáéíKL ^$îƒQ¢i‡n‡qÜ&@¸Mh¬Çª%Œœ%Gì"u92W2šÞÑhÇ>Ę(Õ"7—, W:7¹#¸U妷1ݦ¬Ó4%}VuÕH&´À&—øü ‘Þ8wø¹ ÙÌùÄ#3hž¿àPZ’3^vèu9¬*a´`j —L”ò2ŒÉ–JUìÁñÌÙòW%† 0¥TûVã3Ù&˜dµ—9äÓÚHGJã«'™e02½`˜ *w¬—¾é2$Ü,€?²\uŒ™äPo›û”[U s¤ÀtÔ蘧jËÛ ÙþøWOSï p2›LâÛ‰#[ÀJ4Žd@ûlüz»Z½xš²šµ)»~2ʾá‰L‰„_“9ãECëRªºüòÝâJÎ ʼcVÄÑñÍç7©@Uo¶#£” £Ü‚ G½sóQÙ& ²·~46¨]‰ãõ̶.ãt %ãDn :æF¤§ÑÒ>q‹Áiv¤ñ‘õšnDbX\íçûÝ8#>&LÐ5y¦„ÙôH¡ÚÇAà¨Wö8œáH àSFjײ•0ÿú׿(|SüŠ$ë:xÁA ɾݴ«b  ³=ÓkQ•ñ•ÖKð#RŽtd®# 2ÞVJ‚[†È·Þty1ÌZ`zagíadþáb%2&ý¶åÓGm]ôk'nmÇ~“’aŒµ7+ç°‰ÄÛLKw„·OnxdúpŸ’CKjk̯E82W À…ýé3ĨƄ÷ Î,ß>uµ31F¯áט¡ªÆV‚Å“•ñ€–”°•ÚS†k$HI0aÊnQ¯}€–­—­,ðÄ׿×~7bb.Æ"|"˜0YÿGøÇëjzó³â}p‚ðù^&2 ˆ•yù—@ß9%mŸ²–^¶ûhJÄduåY©í{;]dï]R#%7Ô¨…¾oáÞ´ßãz³BºÊÜD k*…ª–²’ÙÐ8 ÞÞÎ3U€ pT•1É|ú~ç¶Yº”ÖÞ8fUjJŸJŒRƒ(EdÎ[†¦Ñiä¬Z2î[&üZ5®ÎJEúh¨ÒÌíà.>Ù4•» `–L¯—’^´$fÛæìX Ÿ eµ‡sËäš}þLÊMUoÕFãExÕ0>=gà-ïâ0e?Y”HG_Àd¦Dfóe¥”5*õV-`t펽3p–øþ>ÑKÌ„gI/”xâYõJ˜H&øk$pÖ+ˆÙ6º›"!WÕ{¦~ÿèª]‹ÆvÈÓ\¼×ó[¨'jh›0ia­ÊœI†!ûí÷ßÏH­æYkCÊtr;E¦iw +h"s‡í' ¡Y)åºZË1YËt+#2Dv«µ åVÒ;ÿpGXdŽe-rÀ{˜í­½^ËôMUmm-ýKk«}¢JÄzá–ϰ›–•^ØD WÒγѪH¸jÁÐ`T7 ðmè AV;È_Þn\ÁQô9ö§>1¾ÞÌË|€Yi×èø2°éJ®Ù«Òteexž°®‘4²¹Óì˜,·¾4FxgdÕžËÑb@Tz—1)#åvÐkVž1zù$¸N¿ØHÊ¢^i%]-I9œÛl;Ö ·j†p?ƒ-阹£èÖüÖæ°YºÌ¥l–,ðr†”ŽÂQl˜FµöRæxÓ „ÅÀJÃĘ¦à›Žì+„=i/Öh-4J²[zVÒëc*Ñ4ºÞ2åùŸRÐ ¬ØpŸY“šÍ7¯”õ6‰CšH?í­îÓ¢ÄòÌø^`K×(3Ù®‰ýÅmS4"÷:ŽöQEÖXÆœß_OŽ19§ÑhœPʰõZµœ ½€d°vٿ͸Þg“ S:2þY,fK¶³^ûUL˰à&Ïp¬Ë&ªmÕt±ÅôË— ®%«¦ÄcA+åÓƒäŸ`ÎŽá@½=W×4(í0[ÑÄÄ2FFöÚU‘×Û±Þ.h+J/ÚÀg ÈPµXÏÜ‹®€Ñä9²RËðÙGYLÜEú€ˆuÉ¢^€@4eÊøzá]„àôÜß ›¥‘@—Mࢪ\ >¿³rA¥Ârß31”qn@½21r»)Q†&[s‘-L“£Dé·?óYbJ±ÆöÑBI#«îȇRVjºLS^I g÷ª@žÈÜj$ÆÀñ•d³„+àù¤¬ŽIFï(ª3lŠ?RÖØÂdU×h”-“›ë8â-6p¦Þˆ‘û“¯kªËœ“u©n4Þ‡ÎDoG@´`ôp+‘!{çi0}1ÈL4]¯ïW‘¬^9+-HL-;$¾g>b<çLòQòá铬#,h˜¸o]La€^´ª–~éªôzi`ã‰íiT…v<Ír†Ž™héµkoaX¯,’”|⛂ì+—Îd§íà…ÝÈFôëbžfu‘x-W~~âfKf<2ŸJwÂI•2©D騔/gi`%yÎ)ß*ÌÊ\·°¹à6O@lœ#Ïz·Cʆt œw©-¯ÖUËbÏM&ꔓ¡÷޶TBê:êï%Ó·¼§„w$&°:ÀÍJJ~û;z;Ë(ahäœùÀM¯—@¬ÈRZ‰Ñ"wAÈ$1ÌŠIG-ŽHgBËzC<ÆÿæO6T¶˜.Ø$˜X8ö¼º2gE¼¹HÌ®¦$0]‡LÄ ËH³„eq»ÿ'Õ^µ=•÷9;ºEÊšÍÂà‘@Ñ£J†ôÚ•™ã G1Ä."·€<X‰>à"¾þU[Ê®¯ÊÊ]=¦jnùÔÓ+c6 §ÉJ/MáÜ’øº–Ôa]Žtñu5 °'eC YY ÿdÇÄpæª{XXu™3M2<`yÕ‚•F¶•äS]J…c¯ªQðQÅô£­i·Ökçú¬Z©5`]ô&¶0ü–èïÀó€¢e¡—müÚ‘Œ@d’2FÖŤª^S^çt$HT•ÙʬÞ‘[Sà‚ <ÙºØ:VJCÏÙ ðå>?³­áÑú}¨”-ðÏ-³òɹÃd6'ûõ/1Rä['EÑ$äŽô®ä6ûTò•ˆsh˜ä WÅôK°§Ñ¥D™'ì™¬ÚÆJ07SÝQµÅðôŽª˜¢(ñd€¨—a²ü‰ë5”xU ‰zaVyÊŽrâÚÙvG> Å‹;ùü¡í ]dy6—²}(1ÊøU…ön§—·CKbÞ¨åvŸÏ½é™© ÕG»EÊYµ‰c³fÒÇ©:ž!œgV|Èøtl¢#ÐrеêšÏ¬tÁªù8¶ŒÅnñš6¤Ï³j¿ìÈ4"C-ôÇýû5P¢éjz]a·à·€R½é9ìÿX¤)uå°ÑZðŽx_˜ ûR) å~@IDATµCæó¥¬ËÎ4|2ÉáÇ‘¬–)㋪p¶Ë-ïÜícDü2 ªà°è£©ŠL¿wø¸£Ð+ïM”vÓ£ø6 T…ûd<6N•½cS"Û$·ùP*1AxG‘R—Ü<9±Rsí€w̰̙’Õ;7,‹™ßG¦‘!7I çܱ.²È>îÛE0…^n21Æ2úŒðôJøOÃý¼ÿ<¾ßO +u%hÛª°«<éÓ\ËÏ_‚Õˆë†FĹ9*½U¥Ú•Œþü—Àݶžš•ÝÖß8dU¥r3RÊÍ«dŒgެý=¥I>Ê3ìþ¯ÊDÔ%“…[Tnº gBÏÓ&Ž}º@]ÙÒ`ÚJ† m:¼)JöI0IL); -üÅ–Çûöp¸õÓߪï&JŽ€†æ,§d¢QîXÎP{2¯QWUG%]H@à·Œ¯å}Óßß™¬èÑÒpÈPæß1ç­ª£ 4 à¼ÝÞF%Vº^C׋·d2˜O#º +ÕšdHÑ U“5eãTµÈ­§Ú7³ö-–Õµ?R5–yÊ"™ÌSæ)T™héªZ)£Æd€Ÿ5úZ•Ò´‰Ö.Ãs€ ŒP5±Uez†Û2‡leÁœÐÞË“µ†’^_Vý{í ¤Ïìîªz[WûìæØuhðŽ}R Å¨ÂøvE< ¤qŒ_Jée¡”ƒÍÇ–QJ 0oúi¸¼ÆÆ»“n à³Z ÂlÕ°,´&Ü¡¥4íŽdkÛA`zX M;L™ÆQ)ÁuLÚY )7E5þóç*…@¬-ÆfPc4À)e%$ ¬¥·åh'е-íÚßIh܆æé(T¹±•g’@Ì â™ÃÈþ„0Åz˜ô û÷Q‘Ì•ð˜nÇÓW©¼›.2ü^,ÍÕØ&†œR†1”VíÓB¶m| 4Q AJxgµRœõrh¢ÞŽ}ÐŽÉŽé÷W ¥*¾Ñ@Ó™ÐȆÊÍêsÜ[ÓV½!ÜtÏ›y;èªo rþ1HŒLö¶˜’OíílÛH¹v`wÌgǶ"Ë6žÆq&Hw”•y½Ž®ÙP9À_‹ÅÚ¼¬ Oï¨Zv4—›F¸?(;d²¿Wëço0}Ÿ1ºrÞC™ ÷ûQ‰À‘2«Z6=’¦P­ÅÑbªng:ÀDɪ–ï=óĨқ«D†I);*aäª+iÏAIÀ‰ &¯``d}Ë`rëÙPV5:>FÆÈ¢F z$@“g™ /ÓoOoDë9 8±’€ÝH†)íï8=^ôæ^•²»w žf)9ÊpÊ;íöWñøLƒÿíßÿþ·ÿPÀn»†ÖïsàFUÌc¼v®TÆò€ã®§17yU:j§qLéáà:¾Ÿ¸¯‹v‚†Ö•¬ç)(‘”‰1@·À˜³÷ &-HU\ÌÌ“ÕBÙnôµ$Ƨ'+tMi:gA£*7En蚀1ÐXv줤O™†FdbCæ …q0MÁ8²ê·8 ÷W€Ü\2ô1€èÃâ ˆ~Oa—m†åú ¶6{%ØM‰•d£Ñõ'$ ,(1ÉZš¨*•k±%1+%á(ëÕNY 9^/’mƒÚ!Y¥Úa%¸Þę̪¶"Fú憩7 ½g'È9ånh$+|X—£p”óLÜÎ2Ãüᑦ–pa ³²-q²”ßîóŸxÐEË‘í¯8œXUc³€¾BH ‹JZ0²ÈЕD€[#“FP&‰ÀsÈPKGƒOXF†õö8J4ø© U9f8™^<Ò1À±¡•ΣwÄæ1…Ï„»Y_£óB߆x-×Õ›*å~š¿w tU?íiZz=A½E둥ܒ†ö.ÆŽ¬Ú,Yc]<É_®ŠÜ -F'Îjƒr“ée¼öÀ4#”ó§,ðMÑ‚qÌI,ŸÎïwTi;Àb&›KŒ¬¤}‚~½ú‹‰à|]²£é@›(ï>„Tõ˜vÛ¥d²ÈÍ nÑå#&s#†¶Ééü:·¡v̶íjºõÑ>JYå²Þp÷’[ȤöWɧ‘ôz>uÙ Ö8·49ïF;Ö›Û©21ˆì((Õh`žM?¢+“#ñÂ1ƒ’—iÇÓöý]ƒ‡k7]#¦\Ëëá¬KNÜ#˜Âö£rî¨WU˦ÔΡÄ]Ÿ²oK%U¼ ß;4—r;À4rÿ BP`ZC†‘í ï¨Ô#RòÙbºðmìt©FhQµ¼Ü2ï\bLAó#¼˜.ÕæVm·®©])f¶½Lû—h´ȶ?€Ç´L)2—ÛÐ>çGNEÏáhÆ%éðŽ¢ÇH \üõ×_Úý"ðUˆ×BÜNµÏ  l(cCÛ•Ð3Ï'Mãp<+b½»¶j/¾e”22†CV98¾‹õœk9Sïzež¹¥\/ÕöÑhgs^üþÙÀ ¸~Ÿ/èµü$]Je±Üˆ6‰Ä;ŠžÅ2†n}²=&@€×TÕˆ|21™KÁ{·È͸™Ø™2 èåÙE˜ Õ [OU»e¼€ÉôÊŽ|”ÄzÃJÌ xw¯‹¦5EWÞû¡šF/Á×éó‹£%• ˆ”ÁyÖË'f|ØÜÞ™Rh#¥½!+Ѹ”Z0½ÙiLЪ²c½]³Ú?å Õ~Üà»×g7ÿazÊ–äéªý?íp¼lJŒ¬]ñJ9ôE’÷€i2Á÷9žUnÀ"YwgÕQnþ´Ž‚ØQnbGË‚¬™EìˆÄÜ}fkWÍ„ gÕ×–Þq[5·)w÷Ï—ªÝ(}(¸ù Ьýц<»#`l2Vé(ˆ‘ª¦pvx ¾Ç'®Q>?±þƒÈ÷@Ö¦\À:êf¤.d“"}¢Øæ,rGbxÚƒ p¤ä“¦½‰Ã]Œ }»É¢5jï“kmæ-–€^vlt>2¦)@V{ý®o|2ÏÇtG¡IÖ’1‘1ÍeÕ8%2ž‰F9&si&«Éû¿.ÖÒ§ÛG<̦O!&’ žƒ#~žbr ¨$·°R¤Fd1¥ŸƒÈHûô0hO +1yC5¾l{OŒãlá¦Jpn0ÒP™CœÆ§lw1Ž¡R-ôpÎÙ’iñ’- ¥EúøJÆuëw½¦,S’eΪ¹ûÂ÷xúJ-ÿ.‰ÙÐ}µÀ”m…lâ1Â1Yß Lsñ»u «8ÒôWs•únÄcš’ú°,ì¶LÜ·¢ýaúmuå'µƒ §ŒësÄólçöïx:otì¦pš–lŒ46 XžL•¥£ –U1|ˆ½C› õ&h%ÀAãnÉ'M¹C¯#“üe䀯“þÖ`²¶u¬¥AŽ]°Y¿ýç?ÿÙ¢¯m6;÷ Vg” ž^ø/¬Òà zü&µF¤ÑÂîOßQ]ÞãÈÂQUŒïÈ!OÇÜÊŽuÕx=Î[7]ÕE”½*Þ 0B‰&Û-€Ìj M>²`•æ] ãüOþ z64QI‹‰@néØ>Zêr È’Ú}Ùϧ)LRÒˆ¦°U¢QB–@:j¾vX‹\—ƺ0™‚¾‰°F%#‹ #a¥öùó¬Ô›è((}:¾°ÆÄ}IÖ¥æ“9| Λ·@ëÁb¨]W#¤v²‰sÈSûÌóé«{sdkðLŒ$plºcúÃÐÑP×4Ýz4ÛªéYá=Î µ4znÉ UeÑñ™Ëø1)+-êÂ÷ ˜> Œ¹µ÷g‰y§ÃgðÝÁÎ@-”Bõ9SaÕø˜Ú‘@‚1”¢ÅdÕ"±R@n–j²Ù‘f¥ãvÿ:‚4f¨Ë1ýHÇù×»®4™ëíc¢”ð°8Ãî¸ÀÜdÒSW"‹”[ÉE¬´ˆùàÄÀ4çÿ5ÐDY8ú¶õátc ö4À§ÿ«Š©WµßæûÖ4› ý0&ú´¨/ gƒÈšg[a5V5ÏPŽŸ ¦Æ< ´'ÍX´&—þõSŠá™­’ ÂÖõÖÈÜQX½*Œ—ÑòMo¨c³ä‚p¼î#Df‚Iß¶Wrö¡ÁWjl–hÛ> Žº€l嬖3YÕ1Ødá”2’'™È°ã<”–ɰìXïº%±VްÂ);½†Mh2¿{ŸCŒg‰g…ÏPo#Ê{%ÊdÀ kÙ”ææ ·ŒL/Ñå;Ï(·[íÉü(! jŒL~QÚZ.sÈÓ­c….½ko [½¾$”Jº²ªÜn@Î4ªéë}Ű`˜ ¬Kï?C ÉøôÜc#b`@”‘n‘Ø6e¥ñ€j_{¿|Z¸`]YÉŽk¸µObJÿìe8ï§©qrÝ7çÚóq…^Ìq @©Ä¤¿Tr44ÿîëHËp]‰›Eœ[¹^Xè:­H1#Gdc˜¾¾°ßÔéa .`çAsãÛ쎽 ¥‡¨+Þï#Œ.‚»ØÙ¬R¶²‰²¨åÕ3ì8·”媭aðö'j³8LZô@‹µÛö¡Ñ® ӷʽ`-Jø-9“ª•¸1ß_ĹUÅcä?󖡉Ý"Ç;ªjdU{Îñ#Óˆ&³ÆÜjÓ(…Ót¤éWjËpv_nŽBW1µÌP)£tµç? J‘|xʘõÞßèpG%þô­ÑÚJ4íP&‹T‘í°)@L#^7æ­š9‡4‘y6Ž›jûÃ-¬Äʵ¼%»,Ý…-M;ãE>z™LˆÜibLAÒhŒñÂÈlÀ£ï&™ƒµ£aúÂà™­# ¦‰Z`L³vͪõ*¢F 7#¬ÄÄPÅøy‡gH UfR¯HÃ-CI/îÌÏß<®ê¬Á¿¹cÖeP[TeÂÀtµp‚$ÈS—ñoüñ‡C¾I{ ¹ýfŠñu®T//AÀ¨Ê 0•F´eƒÚR.Ò´q-LzÊ s&æ‰ð•8Çõªþ°j“í`œ‹l7æ]2>+X´vÎß‘§ª='†1ñ•êLIl·ÜV8“‰@¥dñ°ûÊ;†é ¥ƒ` ûhTûa`±vè³oÊÈd)1‹ÔKl €À·[þr@)7Õdø”Žk±aU>ñº˜gR/Œ6¡™`›(‰|jy¬˜¬GA?¶M½[ vÊx€¬w¨ÔSçÿÚÒÔeyš•t5NžF;  èƒóýqìM²ê p☭Æ"™,0<9„åFlíñ”d"2C6H—L «#}˜²F[ÁmU5}ƒâiòIÀ¶A)eÙËȦë¥ô%§ôÊJ¢ÿsJHA©·GƒñLðLd¥ÚÛÓ‘²«axn"^;LåF$«]U;Þf³Bf…©¤kÕ¹Æi00eËØ™I«*Í“@8"LYÕ‘'F£Ì-^Þ— Vê·SŽMÜ&ñ]„¾)íÖ1ªpGÃJ=M™@4É_´R¼ÊI©—Œ[G ÆgAÙ½ò?Ž7²E&n¹ koÊTµÂ1õÖn+»e¢Ú,ùûk,#QƒþÆðÒC]©£ª;ì»81p7??x°^ŸÆ‘‰c>°hcUäþ¥ÁJÈÜÈúö+™(sÓ¥ „ijÌ­ªŒL& ŒÐ+µL|{&H£JÖ’?1ÞõM Ìdþ®©*çvV¼ÿ(—•¬*3Ä10&ÿøJ#ÍD Ð1W{žàFïSw,È0Jް[¿njoäôsFÂkì¹Z£­ê¢i®£ª’H†Qê£ô8ë%¨«!'@ª”L\¹4á4ªlÃ&Öˆ$v„ÉŽd‚{®6ÇX•8G-4m‚Tr”ñ”ýœçC£”¿LL#šÔ…§¯ Äèµ=‘ù8"“ù)0ˆiºQΘý`êJ kh‘ë댗•¤ÚlõÖ[Éy”rëQ سØäÊOb[I1Œ$Ó»%; €6tÜzmȶ¡Úfï“X©q²+-¡-ЙÐ(Ñ´U³’ d¼.YW¸/Œ^žªpž€œNÐ\Gûh§;ÒdØÖ¨E$VÄLZ©ÑHãvÓZ0ªíß¿¥Á ¢jaj*,êôw$l]ÙŒ‘z;6I®‘ÃxæôŽJµhð°ìÓmý‡ fÅk°`"(U›%ÿUe˜FIKÓᑵ ¸ÈCÆÀ(ɬ7®w s„k4 î1Ý®¯x&ø”áÄŽ°ÈŠ?&²7Ô踙ÒmB \ù÷ ÞÊaÈäãSW»õì56ßѺ²íFŽ+ùhZ £J&Ü"¼ï”JýR Æh?÷¦JÛ–c;Ózl™ªd˜vók‘<éåô}%šñ4ý6Éǽ0dóŒ—ë­ä¸O„ÃÌuùt”Èh"›å¸åÓ„l¥ÀˆÖSj"ài¶JýÜ)aY˜ÈæËmU‹Ò497š­1űdZè›r¬o H¹× ©Š­„±@b‚Û÷ý4%#àÐW¥ì¿[à3Ïjn-ÖQ6ÓG°ñùä ÄaVkO“°•cJ¶0ÒãÈ“{·Wc =¦ü)ex¡JÖhû8vwÊJ ­‹g&Úñ¨Nl™Æá…^Gz¶î(§×øý'f‰2êƒ×èÉØµwÌ¥#_ÊÚeÑZxX—# ¥ïnnÆ ª)ñ鵘Ûßq0ª&}-]/OzU¼lcæ U?—û?FNŒ›Â Ó-zMkg…ŒgFcÿ1ý‘«vÍliômBƒ¯±Pª1êZ(ßÇ¡œÕ G¤·…›ë%ý6ñhÄ|(|ˆ1“@±‚Ú×[»£v4."Lt¤¨ÊB‰çJ šŽ¬´*}8Ãde+Áù$‹‡;2 ËÆÂýy€ç 3™2#ªVrô¾±~ßî.‘ô=»vbý¡øh0-ãhÌ‘™¿·ÅÀœ+ñœ?&£k· ùW}sÛðÁ‹FÙö0[uÇZ0Àí;_~a[Ç· ëµ'–ó­—¦#l:A>¾€LÐVŽ«Âb†4•d>þŒž,РZŽv(àómþýGíC£Z—RLülw¬dÖºøôÔÞ.¬· ½£€e½ L|Kø”«Z Ö…šÈ ŸáÙ<„ÍEíxÌî%ûë™/FB)£«ú~NVUÊVn<Я†Æ¥É*7wKY©5(éùX ÷ÒâãÇ;â‰aŒp&4gÑß—À¨ò¼ôw…¹ IæÈ¹¯Æ ?¢ŽÌ¯ä{"nÓv£íÙe³r¤a¨Ïÿ÷â‘&^¿?¿zÚªåùd²KåÌß±%Yæl^`Þj&rÓA&»`gÙòÌõÂôøÄŽx÷¿¨ÜoCô½Xq°eèpÔÆçÌ„'M%˜ 騅¬ÆH½”&9§Wm±F(9r(` OUíbºržJ˜r@Wb@°rhšÎgVa9ÍtÑ |ÓÜ÷ï:}Ù”8{I@0)œeÓ{.ÜÚJ”@ œ¾£Œ¡çPôôù›ŸT» Ü,bHÑ ôq«¶UÊöA¬ÊZh88ê¥,šK¬„!Ã8ŠmØJ²ã>0e-ôxeª·ã›{|/S‹¬ #×Õòî§€gG²-·j]ëm·éià&Ö"cè7(Æ1^†Ûy²@n)»)†rzÜZ£}Ù8ÿÝÍ>†* %¼A"OúÉ4Hz¶98jé ƒôdڹɪûñ$NP~Éš( -iúL 4 žŽ]¶£ìGO‹Przcà­GÊ×þ|ÓŒæ&€ÚUëjP-ªµx †®ìØKæ/3Á4EïëCG’í¬‘ ”Æqë%PÒ[`L!è·ÊVj4šVÕhíZ²Í #ôv ΰ¨ À¤O_Ƭ‰SÚ ÉVµ=UEƒâùg’á÷¿à ¡£ò,a;…d]©Û²Î¥mZ]vÜŒŽ€xæ0&s€•äf>§^9>Mã`ûÈ"½o*@™‹9¶g¿§ˆµ³º)@™‰¬·`J†"¾Œd›¾­ht UJ FV¥ Ä8F6®‹°mVB©×ÖžXŽª”;6É$RuG¤p­MÓqS sA_4«Í§TÊGî7T²^ÎÇèþs’ ËÙÆ+õªi”Új/94½»×ÛÇg"ö,-“mJ˜@&öÈ •0µoaBuJšx9C¹Å(·gŒ&>ñŽÚÃøÞ¹¬±wð 7W´ÞLr– &MÉm2G¥“LC·ëpðª”ÙQËô¹åÓãkWM¼êf)u¯JL€ ótÁÖÈάŸÜvȰÆ0[U@‹P˜ÈæbÈ„®[??Mq”€2ƒg•F è¸Yû飯ų¤ÄcÎìûY—•¦Ç´t—Aðp7¡÷>2ÒD¡+ý¬²ÅWrçŠÞ=JÆ„“úPý„ÓÆzŽ€èž×ö<™¥=:7‚¾áùÓør·1.¿¯]™’²LÖ”Ý?½cþ'häZ,©$‹Ä™ÑV› 5 ¸x#ªâ‘°à,ÒÏAÉ&–?^¿Ï‰™8w lµg…Ô.0µwÄëÂm@ô”yöG8“-,hÞÐ¥ªE©¹Wõ)È-ׂá“ßMo´jsbJÇôkt„µW „óϤ¹°)pGn]­•rÖåX&Ë*F{ëµL_ÂkvdHQ‹)Í•4BÞ1¬‘¦Z)2‡ÖKC&Âríz‡9ÐÈxëyF˜X[#lk ¸Þ> U ÛÜd_{&Ȫ‘a<0L,˜çÉëÖ&ô¹‡Ï–w„td-ËsY#˜RÔ"Wõd1Ž41J+G‚LšBÌê51˱hneGwoV‚Ž^ÒqâJ •M\ P¥×ˆ÷˜‰e_TÿaU ;ú,ÙQîñsÈŠ [¡D°‰=Qšª•²‚•ì„ñ=^¯à“-Y€ ÙOeGØÏ¬.³,3qL ?ëþ~ 6=}$ÜbrŒ"M¸ÅºòJ¯¶I2ÆìR•ðÂ6$Xt‹Ý—&è“ÁdòµùóÅ«K®‹¸Ž1YY¦ÛÄóIC€ïSP²¡œm¯ªˆ„ jÑe1ÃçmÁ‹ÌÜ ¤€éäøF:GqäŽÑé“V­Sß‘EŸ41Þ±1YÓˆp“ä^O9ŸVßwK‰[ž e"èûöÓ«bȈïœó4öt¬Tb’§<ÜzÇx-4J@ß&k¨–MgµFǪ‰«Žá9 ¨rh"½kÔØtWîh1ÜþMç€ 'ÃÊ<3qÌ6’ÈgíÈmB/Òà땽³}4æ úĆd}¦9T%؆x¸¨ÿïìðiv_+ÁªJÂQ&ÀÄZ ÏPú¬wÄc(EUàÝ™3pæý~ç:"­*tÁÜ À«w¯!ò)û3`ßy¶ª¬ggžá&Ê–é.™Ë4ã“5ÔF`ÄL¶Õ;‚[V”šB#0‘ ð=ˆÌŸXÉ â'C GæW{Rw4n4” îüsS<ÜË_n:Üh>˜ô97"±[S:*Õ.׋ÙE­”Ìõ¨jDʘÓüûaîØªø0q>e¤ˆÌD#æ:ó5Z˜LþkAï£ZÍVeÅDIhìÖy†ñ4ÙæÓqV•^²_FýÙ{UÌ÷“Ü6ŽCi[zbdëež-ÞÎ}X•f¨ ‹½ì •™Ô%ãs»MçúVjÞe¤PeÂJ {Ÿü×¢”@ ßï¥À—ßÏ †ìÊÏ›tUß YËoÕöÔ"Tk‘uÙê)2qdLõʘ¢}rk‡ªAãˆO8ÆŒtT•éûôÛä|¿ñk”EV½á€ƒq/èØÀÐN/ºæÖSBž_(ij=x¤›dK €ÙZšeŸG-4‰ñ™gßÑÜ&fNßÛ5g??FÐ ½âN8›ô²i¶X]“žmU¹Ú¹ÁrãvLàH¼R²ýµN{žy¶L†ª†bš«Ú0sÙ’ÚE-Õdb‘þc’†Êé•z J 7o.öéÔå¸×;SïÜlaU³ÚÖM{IúãrÿI)ú8(7½‰0î‘ær†å®iP¤+ esËþϪeZX5ÒÙòÆq›'P¬TNI]Jý%ÝŸIwqô†B £×#tl.Rh¡ÓÿžežË¹Õˆt¤qÜÝ1¦Ô8*Mb³ÂU‘°èƒ(ù8zF¢#’˜ÿÜ}…šB€ì%Jz¤ YU`ŒHÖnHLo՗DZeê%v„ß)×ì$%qGYV1µgŽìkC¨&À!oÛ@LÎ0ŸM 4%™ì¸–V%ãlJ<ѰŸD_x7J)«"ç¿mñ=^pîvZº‰•àVj.K©Þ¶a-5ú9úŸþùç]‚tÔ¹õ‹.†¬Qæ˜FUËU}ÑSªŠx¶B—ˆy[Ò·b]ÝP˜2½ãs{Å)›¥ÅþÚ Šªñiª¶IUJ‚øe‚Í}°«)i©Ë7R+-þÝšl‡"7%C¾­_ÂD6ËŸ¾›æ $âòqGüåøi´U$YžHíý¸Fbr#ã94NÞ¸šßVñ])¶@¥irh™d[  ‘ÅFЋŽ}”[cŸ >F ^‹ãáá2ÀDØ-Ü&cÞA4 5”µÌ¼‰•æ o²ïÌ”`ÎéóDHiœ€ùï³PÚÄ~Ð0‘xÎZˆõÆË½^ÕP5ÈQi– Š9ÐÔ (Å‘²‰ÚíƒÜÍÂÔE&Ön‡ÕWiÇöWjÕ¼ƒãnWc&l5&¶†ü…FÆP&û}®z 5#5èmS›#q;Ï‹†;&«†$ÓHü’ð– $ º8³jpÃuñIè"pìð¦èr Œ?¢óWÂ8ÝQ#¬*ê0ùÇ8šûVa²zUÆÙ»YÆ1F5OÙhJa:>AVWþý¬„4º£Üõ[&}ñ1}:Ä6k·¡HAæ¯f2FÆT"î Ó”í&<òŽ@¸Ï+Y˜%ãë‚ÿRâ[ï;] ²}m"h~W€Ów#¥4°v†‰™·ñ±»†iTEG@L)·°GàÌA)ìXé¶ž^ ÛµàÈñªÂ‘ ·þU/12«™àEs-c´c·`È5*‘Ádû½p»Ï¦P¢i^cÕ@<Ühbn€¼µ@Ó4íÖQ® §´ÌÍ %<%&ÛŽÃx-"ÿ>ÐÜ®I è¢TµÒÆe©6>vw Y»–ªŽ­DÎÖ‘,Ü>rwŠ µã…ÒÝ¥é0€¤4·q”xÍD]éM‘k‘[©)ø5‚X)œOL€À_¤Îä½86)†È? (ÕT%ƒÛ~%¹×¡Ü $C9wáK/£Ô®•|x¬ •+¥Ï ã™<7G¡‘ƒÑ ,ßþ•´6ôûWcÿé7%F£ªF`+)‰–ÑÈJ£ ¥r¶º„éŽZz †yRjŒœç´û€Èš‚ܺԙzçf[&®ð\$¶ T²^ž2¬P5H X©?&4¬Ê4Ù’Y`GØ|Ü‘k\J}ÖanãSbŠªþ] ÜãИEÐz€R& 7"ˆÜh ·€LÓeñÛä`C<ì.F¤g^‹cŒ#Y;0Ž2>ònôçOMd< @¶myÊZ€¶J–ÓP+‰Ž« S5U>íc„’èKeh¥le2U-¢Í¯ü,ãi"L©÷ ÿ|yÖxÉ í Æµ”r‹oŠ<ÒÚB;r@×î¥äFzåVð¾½zã1v;dWüö#{}2ìô 8 È¢ro‚±CLâ £Åxx2¸}Zɽ&ã|GÂÛâ󌜲Uñ[ž²Yþ‚c€²‚fòc¾ÝVÞÅTÃ-M–F w¡Š!ƒU·f-‘ s¬«82gU`½#ëbÒÂhÑ’˜æÖÎV©ª>*ïwÕxÚ5¶gØQÃ2ÛFd¢Š¬Q)@ÀÓ,À”®I©Z®WÞˆ-Ÿù9.¢.+±RŠÔ.fŽ'«‘Àb“Ťyq½"·z]c¨g(‹ÄÚÍjº*Ãð2%Ì爉¯…Uƒ2—ù(‘…‰û‘Þ/‚¨+-Èe€s2Ù´Ç(™¢KÀýXÀ¿!ßïMzL½í#™l4SÕ‚{dâx†®ã>¹’®VBjìŽ[[©É€üið1ùt#SD 3qT’É0aã‘­]&ö·¨È†¦¼Zµehø`Ta™8ÜQV-ç@àȶA‰Ó´*¦{ôËógE©Ëe}¶[˜21^; l Üú·sJ½ }Xþèk!®Ñ±‰íã¨níÓð|ŸÙÆç D,vTm´ìɺY7Wà1çdȹY°–ñªX点ÓÈÙ½úmFŸ Ïñ€o³ŒoD eëáª&hŠÐxÁy9=†@P&Æ»½ª|ëçš :N|=N¼bL¶›» ,ãk§wìRÙÚí­Ök%Ÿ“›f(g¢]¤÷q2ÜP† •UéíÐKrø¶JFp;Î (½'Ð5šð5;ɱ ha.€FO0Òqƒú% ëJ¬ÊÐjzGU%‚"&Y£)ûã6e¸°³®dZø¤‘Éd%ã„*+G¤.˜‰µ G‚öÑ(á«:4·ã\gnk!®K  >zijo‡4°g´'[ÊŽ|TëÒ(ø”JX†iäîˆq}ŽÉÊÜ”èŒÈÄtš|6´—ì{K)jÌS#F6îÞžðY˜®7ŸzÛ'LÈ‘íL/XÅ+JXøsË?V÷)U,'†ú¦à3œ¹#·®š@N3%Ò£¥anz#d—¹±*÷ØÏ ¥”a½‚ lM2ùü×@=útý¤uÙstt%U‘R‰ Læ&ºÚ¾j2¹ñp³Éh:àŽÂ<5þ;¿½Ä Ò{Uƒš¢ß2˜ÈrC¤‘½7A£Dî‰^+%¤OÂÄxú.¨åí 7ŽR` X‹…›²õr¸Úó\ŽþÑWÄ1ý 2½@š²œ[™FiþµËx¤Xîˆ Û¹ÆÅÓT²R; «+¼OÄ‘’¦·‚ßY]azÇ~#4š¹öü÷8Ü€EË4H£ (w…)ãw…ÖplO-”k÷ +%¸)íéØ ’I¦×%ûMB Ë&­7k/¬q °# Kû~N1<5âé]mÎôJaúK?\ŽªåZRÖÒôüñ˜ôáí–åû ¶vzsØô+Œh7@Õ]úG„|ˆU‹-܆Ll¢”CúŽª1ò.Ø%2¤#OÑ(1z "_ ,rÎ3¦qÛ„!,‚lËzrW˜ I¯Š9ñw>P¿ZÇ#º¿dñĹñMÜÂM6¸U9Ä»$¾RΛHÓ  FU¬Æ·*çct¿ &6(Æ2¢m•ª6Ž€¿ìˆ—5î.W{’A•à•‰•€¸§4Û<ø•8#톯TÆ3Ä"½­mû/&½³r3´5¬ýøÞÐÛÏçÌéÉ„ºL£:‡ª9'“{Oš0ýö4Â’’qd}æOÙÇÊÆq%G&äXœýîWQ‰8JÕŽrž|&SÊÉ€°•¸Áª ¯÷wl7U<Ð’MïOÙæ­Aä@“ƒöÖêͧѭ©J ”2ŸanJ«¦ËŽ‚ÌG¥j¶p›¸,½<«°£FØ\€@j—FôDiÒcVòÉÖ«ôú0ql=Vk‰ÄwÁÌ Û„žÜÏ&¥AxbÙî m+ @/™# 8ù"¥Çé:i„jkÈ-ܬªôȺš’øU6tJ “FïY\Rõ¬uCÉÿœ­Ç›•€Scâ>ˆ½RËä ‘F©Þ­Ñª-){j?¶ç»’Wד÷ ÷^u2ê×"ÌUñ&Á"R ;Ý¡ý5Šž Ÿ°’°=`bÊŽiʆ¨Ò`Ý‚Uƒ&9¸¶#™ ht¤#@©¤… ÓçQ»#~õ’™[oí-@´3 d“ÕÛÂ=Qš©¦á`g²Ž”É0"F—Z^Lc7LÐÜ7b£³’™ä¨·»g¨·vÿzÞƒãûnº#@Ó1qÎðž‘¿#^¤ôŠžK•9eUÝ«ªÞî® 4Ž ÛZúŒ0d²ªùËù(M–‰,臣‘B‹^ Áî’2¦}hz(ú‰çÙò½*O-²jA¸)FÔxÿ¾E< €kJÿ·eäÈ鳚aƼ·°É¾dòkèilÒžµÃd¢¹}‡ûÎ4±LHl"‡Ó$M2zÕcb±v „ËuÙS#™œI/ָ׳ýëâàXon»{n 9ÐÐÃ2Þ1C¹®ŽÅ«Ñ"Z©¬ DrÓ™¨r¶X£·[zžÌ›¨Â§ÝÿwÐ-Á"#€o<Ür€ÐÙ‘pxbíÁŠÀŒ«;äŸC‹Æk˜|²"îH#;Ú†‘d9†*96e›ø‘k„œ­LCinWâá#0ñ˜°Yá&y&“³”E$7xC‘‚'’ùÑÝ @š²_öi´úìvý Â[f›2+scòሺÈ:¶cšYaàŽ½ÜûØÓK·š«%+ÓÙuú–T-LÄ»”£ÆfÍP»ÆJrU2‚"&+9$sÎ6WTSÊd USº ÒÐ̵gØQ‰R9ÈŽrKB•>ÞQ¨ʪ‰åÆ™Kï(låØ3fžÜеçÖ‹Õ+×BÙPâ½æÝê5„sÈ„£^Gí& 5d£ÓÀ¾þ²©ŠiÜ%½,zgÕÆÑ¸©£R›×Õiä@]0yJ°è³ë5î´³ ž )H/7 KÙze< QôgXV5Z@Ky€`‹!ùÇ _\ )êUˆøá“­%gË$nO?¡vîóÂ(u…ó“Ö>]¯Î¬ix;Ó«Ša½GÒûÛA§ÉIku¤×EࣚCV™#ž¹cã"oý|ÒM”1rk.Ÿ¦Þôó²ªA¾¯ÄïVƒv÷™´I«Ò×õÞe ª2“6lŒÔ2ÞzܺZ«ö!¨ ÀÀMìÿ(c½H-0&6BÄ8ŽH>•´T-·pO‡ìÊ•ÚÇûàµ+’aDǦ$ÃhñÓÚ•ôŠÄdHXûH³àœá@yËpÖ…@Ê,`ôµ4ÝÕR&î"xGÓ‰a{â#ñ×ãLßÚJpÎùѪÉ䂲ëkÉsÀOø=²Ñ˜Z€ÚÉz%SuíÖl²ïª^2LI· ” U¤Fƒ²×…±Už[@;ÞqJLkøæ,r–‘Ýhda@ T}ýŒØ”Ÿð{±…’Q‹5tÅ-@ƒyùº0é[‰‘ßà¼Åì÷øgöïÏìL(®Àa¯ 7:s²q&€U[Cµðâ|d#Ú$Ü’²*¿¾mW O°‡À;0q ÕÕ1†à`1Ñhä)Sú–PƤ”›ÒS*µá_ pÖˆÒ/ãçþ÷Y¶qƒ(»‚l%Y É€ô”‘»T&õ*á)Ó4ú%íLÀD)Y{ú~¬èÛÇž)ñªã½éÁ“ˆ$p\n¥æ",h<ˆã¦¯½kmÕ–Ù¥ˆUµ3¡t Ô%[©’{á³Å#‰1ºh|S`2VÊîØLVùSú1ȇ,™¦^˜'LPÖ.7:e¾ZšË!%M—ÅYµF‚pV47Ú;c²Õk™ºZ Ü' Ä1Þkh94å ¿ß×Ì«úÔNãlE»mŠ’ ‰ Ëõ¶öîîÈAõ:}_€ÄÐRXÙïîöïç_{Òžº6ˆÀ2Ž=T%2 p®ôûžWrÄWšÕ^,«v¦i‡H6̤M²Š?R×óg·<LÜN£È½‘ôŽp-Œ±0M2UG½mÕ]öÉnh¼V.òýÉœï™ùü Óܤ|©ý¢!ÈBÎ¥^™¸áJmo¶Põ÷/í~ ”0øÚÓ«VjoU²Y!UÍ•…#­t ˜²U_ ½ÄÉðȬÚ£ëÝÇmù2™ïbÿŠóõÜ`Ëw‘Ž0·ü[ Tm™Ì‘ãµÔH&ÈÚ)0®`ä£äÈ$Íõû~sÅŸ‹Ý«É‰k§Z&l%SÈð€ŒÑ‚qÈèa)½Ì¶Õ• (Ó‹J1.¢1‡†¦É¼q<‘d>\9A> \?ž˜é‘ô­Ô8+õ}sÌJ™2MnÁ iIã`ß_$LûDÎ (â³Å0´y‹™ŽG2'@>¦+êHc4“mÛn4w)g(ã»{Y•Ç1dE½»/ ¶dkÐB‰C&-ÌIP‰&Üeû®nàFMœO¶ùÌĶxk zÕŽ iš"ãùÈôÉRÂ"¥Œt÷@Îõâ‘ñÓ3l( ÜNÙ_£®•òá©n½Ì •ªÇÈ-I DæF‰‘!«šÒ v¨×‡‚¤lt&õ¶’ƒpMâHíßÿ9-ç¼jÎNIu†eJ w8_X¤9Cn(bS-ÇjGúÍ"o Àk¡üŒîÿØ£¸­h0lÃr¯€÷-ô“Ã!A†ÜhøãiXÊ·[¤Ü3ñý—p´0Tb"ÂÙêibæ£ß,ž”4Ä‘U™ÔN´I9ìF6¡Ži˜à{·mEÆÐ±.€øuvDÆÓä°^CÏ€ßÆ e&•RÊŽó9 ÷…ûtÚ\#Y¥®°–‘{Ot¬T#Œ¬= êØ]94‹¬miTklm-«n+@hy #Ç8zds9ÿÖèR˜v3 £U²ÞL”^`FæTµ«@IDAT#è}úŽºZ^¯pY2@À|àüa½ òÁø˜Ö«‹R$0Ž?DHJ6q õài½JÙâ¹±}Ë|2Ô¯½õ™¼²­žÒ,¹^z@cir&(’ÁÝzǹáUí#»¾dîhY¶°Ø§Ó'Ò#dE¿¡êj½6¡éÕ¬¿‘BcÊ@ûWzù³2ïÝÒ÷&ø}L6?‰Öfõí‡õx ‘9²°%~îhð"ìÐc4R ]É”º?²¹çìEðzå@úÖ ^‰C[å,S"i\/RÀH€¡²KŸ«a`Õ‚ƒMúÐw‘ö™[†‰ó‘µËœóÉ„rsi²Â‚lO í@ßíúÆ$NÐuŒ£œ˜>òçôýJªdmž•¸ÁÄÙjlÕnÁV—j‚ªJ9 ¯Eû0 RU(ú1xd]Ý]o €µ´Ü}½œ²YJkÏ¡wƒÝÅ_^A&Q/™vüJ‘¬;æL©«¼#:cdËw÷|0õ·v„ÿo ä®ÜJMÉ_É1[Ù1œ§Rކªöž™o\¥zµ zGY;ÐÑH¶p‘ž¦AJ°ÝTa#í¯8yJ8e/ƒ/8ÎÚÛŸù>ôæv&³Ê°F&-€ìÝš. %¶JdŽ "ƒ‘óÞîô\Y€@£/R>pÑžœñ4¾ }šÅ3*-€ Á;’ %㟟6®ãÖ¿_¹Ã4L2—Ïöw=¤+0ß»ñTÒxJæís¡ÖŸÜ€Ô-GgÇh<Œ,2„›¤Ëx¤0Rè ÓÌ!ÀÖ%{ôËha%ÃÈœ;¶R˜"cÈÒ—)SU¤ñC¼ #UaaÇZôª*¥A*5‹ )÷ÿEeßûÄH>0ý`7Å·¡ÝX½¶u ÕÄ=FK]ðÈ4Ýî´]YÓ‰;6·çÒ˜3Rt;2¤ÀÔEÖSˆH2YµMäãòûzqÀX)òZžt쉚žLvªû(õnVP (UÕ h‘³ŠqôàN J6ÆtÇbæ­lC€›* s`UL“ » U-é(o¨Qàkî.Žxséù÷ËÆTRp&¶ +x%ŒÝRÊ4µ Š7®Aï5×β¯Á|òÄ“ L$ €‰—1-f:,Þ5Ràe‘¯ðüpq3èVÎ]"e;'Fîîɪ2Ñ[×üsF ú6ô=ñ²*^;>7 \c>²=·Ø¨ªÄ™!Œ”³ÊÙ‘þÚŸ7 G†åZÒ8’éE6:¾‹”Uý”Ù_Ô_£*ò<ŸÿÁ(+P´¨U‘ «ßËæ^)RÕQhç£ÈH»*¥ 7‚ÆKõ¹FÖµvǽ‹^ÎA¤+F•¾sNrž#’RÞ²¨tåÇÕĹ™5qL6§ZYþóTÂp–‘ r(à™; V°PÒ‹t‹umO¸ß­þâ°));æÌ™[ü4ã˜8½ã-ïØ×‹¬éÜ€Z"aJ2% ˜.”d$Ûº´×¨TÕrÔ?¥#1eN–²ÝÈrsoëy: ¥F@Ž«‘ŽüÄÉdñ¶{j-Äx™§cϲF¥^À©*Èð«Qï”ýdkAÒsp¤º„.Œh:Œ¿Ü÷åÙ U)sèHÔ¨ê;³cÎ'›€§@öU„¹yC«ŠÖS"ªñµôÛ8çö$#Ø+ݾs;@JM§çƒ¡wåÌåž‹†@×y¦û ·ûûÄ›ˆ¡yZLÖÒÏŽjβjJ>pÃmÎŽkéRJ€Ü ¨îkÙJu)Á¢Æªy+¸‰ªdŽÝñm„o÷Ùͬd=ib<¦<€©¨0 ùú&3`ZÕ\•µAÆD©ï1ŒÁ“Éõ V2>ç4z1ª‚>C>J-%«Æ¬È|`2Gíý¸6˱k&&^ª‡¶€vq¶üýñNp¬o0}#Y GJ³Ô›˜ÕJñÈò™ñû3‰?¼ªŒPXýueúµÐ×bËÆë6š€Uy$Ûüå‘€£§†ž=îJÜ\VÏ'ŸFWÑ< „äS©öZr pÃP—cÖ‹ÉV×€ÞLªîH0Ûô²5ÈÀ¦êv4ø5ªŠÞJ)Œö=¬Cv›Î‘Ú.•eƒäxÙCíў¡L†¬½¬ê;‰ÝÎ6´ï­£È\Vz­†yÂxÚJ{J vY)œØ1C$±ß§¾Joïü Šh,ã>‹ ­ÑWH #0ÇÔ‚ttÇd¯ìêjŸZd¥˜Ö é@/§ì)”¶ ̧}`nJ-\ ’'œU”rËJYmIÇ >wÇÆéâ_»\ õÒˆl‘ñß/zRµ2ànØ9ö«Ä± Lü¶D]ªz…¯¯a”JM DîuíŠÔè˜ C-aïè2<³…µ¤,Çðä@ j—Þ”ù`èi\Ó—¦‰˜FÈ·éK]ÉAÖ’›ÌPUÊ)16‘ÿrsµ$€·-‡Ž€*%C&ŽBI 1¢YŽV¿tœ ±j@Î ËàG×>ÆuZã½NŒö˜“éß¶ ½Æß¯Núœoë÷SÑôöi‘/åªõò}"JF(5ÊmªMŸ1f]€ Æ!;ʾ!½­#=F¤”…—ɦT•aV¶ª­ªäXÉz¦ÀÇî÷óOé‡(í€P•›™^ž-A›cöùšÉv_«æÙÔé T+uäã)úþw)JÁ9s8‡¶ÕK¦(ð=,±£h“dªZD÷J¶ÞZkl\{Ò ¼MXqéezL9gǺTs Ð@ CãúëuŒ$€‘.â¡`nÚ….G¼‰a@291@02AkûÙ¬”g¶LòÜæõNC#Y‰ F}ç»A›)à¿ãø¿ÿû¿þí6ÀW¦ÏH¼<÷¾VÜ Ñ—ƒC«o2¤H©„”óO°¹i:&(g8¾—ÊÖ™¥„UgOS ]ršgâŽnÑEü”ºW|ê0Ž"™T…­‘¦}©ªÑ›^UÖn¢hâá)‚Àã„G.κ7,æ[C“CŸl-˜ª Í6%Þ±¹i6«£ª˜Ã|b”^†g¯„ä£êq|Ӛ嘹mµ·Rì¨*Q2á¦ê8 Î_ŽÞ!Á°ö<ËÉTçÜ&ª ºNŸµ‰«:"ºDUï/²­EV͉ pèÃ:¿Ë²¢ Ó /àØ«v\#p%߫ƳJì ðî‹vÎÓÑ»Ù'R;À0[ÀhdٙؕSn·ÚUÖèšFÑŽôöy‹l•hTéáxVM¹Âï…ÁÓ0¡Ï9A³šŽÙ׬ªLÐàÆñIßÿ™í™™ooÛVÂÏ-Cí¹É0} ç¬Ìí¨ÅtAPé§9?ØD½©H‡.éUć)cä|“aÖ¸U,Jæ†ÌiŽõ]¥/ôq¿W¢±Ÿ¨Ú 2TÅ=P¢£ßYbY‰Œ!¼8c~¶õ4º{éÕ 6ÎyUz‹µÛëiz÷ÕrÍþ¬×Dâ€ÜuÈ`Ë—97ÝQ)\5C#Z¬ê>;ú6ŠŽ2åZ´[»®xLκZ©¡x }²ò¾ Ú‘€‘µŸH6FU‹#Ÿf±ÚP5·7¿ûà M_#+‚4«ú‚EîR-Ÿ¿ìȇ&棽 0ŽJ^žÒE1‰74ñÜò”‰ÅféÊ*ÆäŸ¬œ¹÷ÑhhG¥³Ó½¾Ûí‚ eELéHп¼­ßOè_†FÔÞ]Äܺ#¾ ˆïo„}&¶ðdmB#`;sã@fb+áL¸Äù3fÕÖ¨¥Å"kTÕž94Ùâ3(kÌFÆSŠH; b.UÊ4á†Â¢÷¡„ñpÒ•×ï{x'†0Aþ€dæ+š^îè"”x‘† ìXP8ÿù]ƒº&çc\ò’YT…$Þ-ž²»ÕN¶#¦‘4aw¶.sU|ss–i|{êRÂO7á0"OÕÆá19“%Àà+Á•0̉#ed]ø“a*YCÙbµËk(‘)%€sÛ'÷Ž#4È)8²å°Ÿ¥&&NC#`ñºiÇØJUÜÄLµ/ÖÙà^#àÄ ª‹ƒ®¦à5Â"ÞQoŸTßB½Wõç_e.Û_‰(Û î 3a›r]ñ R˜ÖfâØþ*QÊÂ?´MÐ{f2çŽØç«KÕÿÇÎ Li«¦8ÚãaU&À“C=Ëþ‚•Xã†ÂÄ2=ÑbrŒÕ-ãÈSÔÕ Õ¿ºÖ›LƒÔîeÔ^#>&7²J)ûAV–¤¿Ëž„éØ-ÚvU&ªL0 2„cdšdÓxy]ÈÆYi¥›K¦* z棸Ä÷Ç‹Pj—Ñnxš> ÊGWG¸W ã·!‡B xsH#f•`³ò×b=$ 굞.&޾ r—żnýüž?œ±YTnW=B³R Áfм—©ñ5!NÐï ™åúÁVåßh¹0¢‹Q6:àFÃ]¨UKH½JBûögŽq”äFƒQZ ãªH ·<¾AººK½Éhª6.ç6—)e$M¸cù·j>”æ¦ežß®Üvõ˜ö¤oÏŽdÝTfîoy·«·ŒÑî³Ð;+ïÍâÖ& º’#™œ ›Eß ‚ŽUuµ`UàiäFËl1ÓçR^à ª—gß®L”Èr`BæHÓ³„û²…iÞÑ”˜J2,ü~g› ÉJÄÐÂÄôò É`Uš0C ™,ú8ü”a")Lˆ·ˆ¼’óè‚€¼Y}™+Õ’ÉsR&r-Ì›¸å™$Æ÷t@ ËÞa†ø.•þkO>H+É 4TîqtÁ+‘8ö8dÖ&ÃËzå–ñ€Vuœ¿#üo+†U÷doàó¡ Èi.#]4‚ØÝûï”ÃûŠ®‘¾Æl½¢A s h9Šçoçÿ"XK(gÔ ™ZpÁ @hN86,þßÀq¤Ñ"{kÇ‚[Û$Ó۔̕•ˆ9,+åÐw¨cÕ¦ÀÜÚ6eVù,÷÷>J]ëŸ>™U½-° :šKО@ŽZD_Ö÷Rñ¯,´ Ïô˜œçî³ð'hí‰åkvÛï5ªòTeVuµ*вïM¿MÚG×v´Œ¬„̳ÌD´Iw+ÕEÆQµï†{Õ¥„Ï“ƒÀϹ*&‡7GöC‚ïF@/`í­ÛÌ;Öl:  $˜DÖ2^Ë‹Sf(ìÖ’zÝš¾–¡qS½‰Rk_í÷e#õÖåèó"®Ýñ.û½$’,Ò&@yŒ ×ñÀ¤'a™F¦!(«Âõö\rßÛ”d¢FùmÔÛ-æh/SªÂ½mðL!ÀÓ;ŠzU<[€>ÿxLžiÈr€@(c€ákÀŒ†[xÓ3áÐ7§êë#åv dgÞ’¯ ‡4õ¦<¿S„Ë÷~½5‹fïV¹¨zô4¼ KtHJ|xY#ÞùÐ8öX€h2]v«— #0ë§h%]Jx½›EÉV ЮC€ï +|2%áXt…L+½÷ZK‚hO%díºñzEþ˜Ž)áûÍèhg¥r{òOÓÂJ~þ¹! ÌÊDUc«Î6MCÛ§Ýò¬·qZÚ<R/YGÕÙÓD2X®K Hƒo.O,únuLO`Š,Òïqø ã»rb “M¬Ýñݤölu‰æêm€¾Ç÷Èú´4BcŒFJúiBjO êØ+aXÉ-Œt ÇܪrHƒÔH€I@8"Ù2¡G¥èÿÿ’|’5b]H]í ;6ˆC¤ª–lëMFÉäíUMP AVŠª”ŽJµÀ§ù~è½OU™ÞJŒ'[£-Œï(Éx‘Cnõö,Æy+-J°Y¢ÆVÝD ¨]UWnrd‚ær‹×«úó8lPo “e('Smb˜q81™o#¦–ÚU'p$Óxwظó@¹) –KÇöÃücj‘ÌMc¥–Ë<¦‹T"z‹Ö€›µ^íJ­Ô¬3ø÷½Räp‹ß·ª®4dË?²hnƒ¬ç¹ñk¯ÅôX ©š8‡<¨äÈ¿.dšköý B©T×/É/§‡;ŠMŒIÖ³7KIcn˜ÈÛx1q²õªnÉfeX×~žÓG¶üøýôb0iäŽÜbhÜH´ÀªFž¶ß?¸m$¾}ç'Aä3¬sš6hÁ4·qp®žOÓµ¼kh§”Éèå£0¥Þœ1YJÕ˜–éˆá3+ µ½9§,§”5¶çÚsJÛ¶0Ï€½v@ä4ÔDàå1µ k”70“?¥£ÈضÀ­ÆCÅgØhŒ.ãÈ0J™Èâ U#jXÁéë…y'uLk©?ÓÜùttUX´ã6h S—¦ÞÄ”FÄËŽÚa™RDz[ÚÔÞ búõn æÅކ^ïs#¥½Æ »OzAŸ¬)Ž€Ý"5ÒÀ¢¦L쟃ìo%= * èª#¬Ä<«Lù7])ÍzU5:ò ü…µˆÜ€Æe[¯Ï+’Ÿ,jÖn²Æøp¼ûZ•! Të]Ö.v¤Ñ‚ñ>a\µíúÜúÔðÎßÚ´¹HJGJÑÅe¤RâºjY®%g;تÑ/úmÈObžxLæõÖˆ¤¤¯„´’Ü’íÓ»é2+A?P½…. ¹ÆiÉ# J€TZ‹RxVWþç3²F—HY‹C›I#8‘Ø8|Y# ºÇ!H|¬æÈ°¬]$뛀Ԓ^O »£A¯@c¡Ýëiðbb²¬”˜¸¥ ⑎HŒŒc€ÐÛç`è}v¯2=†Flóz‘Í¢fqÃÔë(në÷\pdׯKËñé ³¥»€BŒÿ¨wéXn†L)F®Á'L&ÌÃ4£ÄFÐ(5Ë­`%@¨:®±k8"‰ÙÂ2YH¹ö·ÊV‰IÕ€œžrÏ–›p«×³ÂmÒ,x²ÜÒwA¸P¢OÀ³’·¬$3LCוҒv¨%¦Œð©6Ë‘¸5ú6Àę뭘²A#{+Gâº8¤¯¤¥Åõ²•‘4 eŒ£üê«jTªQÞ`R{þªZ VvÀ˜fZŠø·J£TKo¢ŠÑåhœ’_ÊVÒB£š'‰#Lf‡FÏ w @PÊøÂQ„›rUߟ:]Š' ž`bÇöIßz2 &CÓѺÒû¸æJø³Ð½c&cZ¦»è{sí[R/Ì™RtdÅgVô⌹÷¢§Œ¡„µ_Õ—h„ª–s¬½£¬Eo²Ž°_8ölUz%¦Ë@‘æÆ÷« ÖÒnªõºx»ÉüUo·”ÚEZpÞ¶ ÒK–%Ç.Î3¾»Èøôs®ÄŸÛ‚Ll ,‹»Ë¹© O†{ÃZL! ¸/s~ÈQ 5;¶Ì¿ :ÙäS©^VÆàEÇ}€*r³0Ü0¢C‹Õ>“þ›ÈJÄváb|x9Óàly®”!¦ÆÄ”o+Y£P9 b ÒEP¯* ÑzJ¹ù²c 8f²GèóÜÜü›Û&eíùÏJ gU‘¹F´-2>F{¼,t5«öVm®ë$NÐgZW˜€§q™ã(š«—Ì‘ÕUÅÐéï©)uqh³Ÿ>Aå˜XÖË0½#™F2š&"»8+CŸET`ò!áô)ó‘# ÚL|Ð 4â9Tí.ZDLUŒ¡z[Æ›ó<³ooÛ¦ihdJgï篺ùh¤isY˜…©Ý&‘ŽMôS¦Ú‡h4CXlœªhŸøLΊ÷‰TyÒkÜŽ“º¦’HÜõ;bR2l™˜Æ$Ž\K ¬x§ØiOží£ÝqÿaÉ^¬—¡Ù»at1˜Ô(kAbÚ§FY Su?,ŽþºÆSµ%s ·,Xµ[&ŽÝ"@ÀVÉQ¤tÌSž0Ôæv ä¢ÝÎ’ÿüóžkø~Ÿ¦£hRGŽE-‘}9`´ÄËïHŽ“©2‰‡ÉrÀø[Œç¨ô®ÁÇ(s#87¹hw1ÿ{Ëï F(!‰;Öø¹ÁÈÚ· F#2¦js#czè”™´g]¡êÅŒƒUe½ñdñW%Ào<>JŽ+Í xq)žžƒ¯ ÆpÃ÷/.Tuu#4µt%‚‘-VYGL&ùàMßgM¦nÐ"0‘rŒ.ÕZ¶'CLãÂôªÂÑ}õî˜ Æ^/Ð\ œ³ö P²ò}6è¬{ŸZv2]¢MnñÌ]© ލ7ÐÚ#VÒhO†¤憕*±པЮd¢®êûU•›^J˜•œCsaz]ŽLò„‘²Àˆzc”0›´ašxʳ÷½ÌžÍÖÖØ„¸}LibãL`@—ÈS×FÄT’kö9bÒS6×ëy2ÎÈÄ}}{Yµöœ—÷ 4”Ž›ÞDüKšÎS©ÆÖn¥ÖÀô«,rz%bšJVr‹0¥’qkéš@’UµgµàüZQj¬«ÜÂ=eÕ® %ëÉ»r|í°)»5Y 0íÍE zPÿâîsÏý”Q:2Ñ{ûNÚ ¯Ú†”ªÝ”OÊJd­*cD&ŽJwì—ðô¦±vÌ‹««âš"ÓÚ€A/zʪcÄ‚LV¢³½•ï^°AàôÚöy= ²â£Déå[ƒ #ܺA0¤#,ð1.¦Ü<ÀV•2@à¸5àŽ)9;N™›c@µ °Ü>p>64WKüù¯j¦Ë~íàñ€\3^èJ¯W +y”® ט€¦8ý7 ¬5ô±»¯t„){5£+M Dæèb€®&tç5‚ß½hˆ3¯ÔQ5UƒjìðzáJz§Ä„Ëí‰lŸ-Ùh3L“³Œo oE×¢ÔP ú9ä\Ùöa¿ŸNV …µ×#ë½®çmktä_Ô˜IšÖÓôµüÃ;ÒA$€ï7—+ÌîÖŽ-f:fKêÅ$Þ@Kî x¡EÆÇ4h²”|ìÖ›“5hã2‘ ãr#°ÌAcø­Vªú—óÞm>]Äó–és‹gÅßÈVÍÖq|JÇÄk¬RÀ7kéµUØIÃjÊQÒ„-¶_£=H|&,ç&»/Ÿ`žøJÙuJ޽^áØ0žŒF.ê%^>囯Ù÷U¤tä@°®9¦‹Ë˜Ì‰ÃnCXµA«¦ÌG®ýüguÖ#{‚D€IGÑZ3]%GŽ}Š­‹ÇGÑä@ŸVäü'&h ÁµùÛêÿÑvo½²&ņ/¸šá,ÄO~53oýT½Ý±?Ö dä¼HGEFFfU÷Z{Ï€m†ñž¼RÇÜàŽyf&ØôÉžsázb½óÜEr(÷˜c˜´Ð\ø|d|/Ð&'¨ÄÃ$ççø^H–CãjñÉõÒ$“í#”2¹•OÏ­ ío£‘¾‹LôMI‰Ñ…ä#à€ªïV˜þYÀËóÎrw=<7Y$kÕ~ 8wjwû]éhbe#(³ê§½÷Ä›•ƒv8¥ÌD‹È  ˆ™ˆzYÄÉ€éãµÂW”V–<î×?k²M†I¶.æÄÓ4‹ );Â)ºT{C¶‘”ÖÃçØgUÇáŸÛ™qÿ`a \•`s×Y/%pšßáh‡lµä¦Ù’HGd&‘°@:®1@ŒÌ“²È¿€ô”öOY—7Ù׉æCKL†-3fǾûð° 4( ˆÝÑòŽ[€².&ßøÅ/~QÖ¤M­A®`Ô7î=V»*·3ÿýó™¡ä¨©}U F qÙg¤®˜azHËD×Þ ˜`?¢jIœ-\(çxü×eÕè6ï¦ãûË,ªq½Œ#ŒÁ;Ò¤d…Äi,“s[õ5ÊŠl>ª·ïÅ$háÖ’›F ·VêÈıŒ!ËÙ ¯¥Ä ­ gU Ÿ†vY½uáó™,@†ï15úÔ„ï›j™ Û gîHÓÐ0^ÀÌ…’pÔîØè²xÕç,ÇÚûÄJ?sŒ¦Ýéå3æýèHpöxÄJMÁ<%g—ç™U¤Ü”5ææ(à¾Qž³j¶Ú»Žª–˜ÆÉ]¢A‘Ú÷UlP½dµp 5·vJ톆•0BKº`|¶J@-pæ†u ˜L¦!ŽE#x"sXã-<ŸÐ(ìs'¼~*S&…* eG#à@ªúÌÚÕd•°–bV@%UÄpS-Ö±KùÏó˜‹zkq$ƒ„ùøù:ÿ·€šRKŠ #ÈÛãùÖ)eÊzÍË )š§töº7×Î _$«=>X¬ª—~ ìæl<ŒI@Ì@?“‰JF«jÉ'ç–l(^0ï^µ#w8 ·J,઺2iôU½’åó ùL™ c8g-w…×/¤£¿A·[Ùqob$$è ­‚QŠÇXÃqü×ÅmÊž·åÇÓÔ 4(ç¦-_ÉÚ–ÔÅ #z„4J@·PÒ®Z‰§cS'3!¸6'èÅ J7 d›F‹<ÿþ2%¦AYuTÒÕ#¤TE†iea¹•ZÒ‘­ØE(áÛñ/ŸÈÚkÉ'%ÜbF³…çàˆäŸž­ß¼7ohÓÛn¥˜4²’ÂrÊd†öŒLih+95î|$AÁ aâI3©ô¤ª‹¸·¥§œ8CÕB;F;@#ã$ŸŽ2ž>™ŒqLŸ’Œ&>™£5ä6$³9ÌœÌQø÷Ÿ¹e¥*ðȰ<‡l1€Øòzi0sÀ‘ AoåëÚ&Jù+­Ú¬¬*}ã—¿ü%B“t*slEG|¥š»‘ “3 ¯ttw{©JÖÞ˜ZLT‚‹x$ 6ÝjLÖ5iýö½>¶9ìÕRöïjt³˜p0hÇÚÛá)h(O>²{‰œçF¯* >dJr½˜³#¡…R4=|mÎ5W}b¶‰É`>½d°j@u&U1‘;ºQ>˜b‚vkÈn‡!Eäòµùô ŸgwéÙ{ÆFhl€8@/‰«Öb(F½ ¥’?ºÈàJµãÓ$N9$&Ãz•VUz†eý3hî:gÉ~±:ÂËOA$d³06”› 4´}”„qÍ­*wŒ§wì¡2‘•4R XFRFög-üôyýg¤tYëya¡G~–ºÏ-ž¤½Üê“ s™½f o‡)bè ð®œÑª>l|2 OÇ@ž°è×®’I-aUn0‡V…Û¶)‰É€õzh²ñýIC´L-Uñ3Ù‘I÷êçߪÏÐ+÷ÑFʦã”S¶9l -4ÄéU“Õ»Xi[Y I&jé ÍÅWÊ¿lV€²½€”ùhÜ 0Î)xv$Žá™3`nþ‘‘m.àj¬«F| à1°\4%[2‘Û-@é¢Z –M)tmsL›oDžÍݪµË"R£¹Žü¹jWîRL½L¿ÆHšø|¸É~^(Uss|þÆ´jb‚Lä@ªŽz]3ÜDXÀUóÁ$›žOï à1Z(ávVM07ïЫb"ë²PÔ®ªÃP~:+¥‘Oa´¤Ú"ÇgëØß³ª½¹ñ„ÉæÂõÒÏ+ЊwÇå†qŽ<í£±+7È?Àéív@·SJcœF»#,Z©¹gœ¤­ 4À­˜Ü‘ô yÅtxŒ.Acؘîžz)Ï^ïÏ£#>½ÆJŽ¢‹Ñà›ŽL€„åxC`èe—ÅWB˜îŽHÑ8Y/¦Ò°ÆJ›NS5q+µ0% ”Ð'Ô\Ç™Ã-pé 0ùÛªjL¥”ª²ÒõZÛÀ4ªý±ªä÷]ST EªòÇLfÿÖàˆÖ KÙ]ð4œÇsSUÒXv\ØÓÑçƒÌjWÎA~zA#-~„dx[¥Ç¸Ëž=MSBcòòéʹiÁÃu9nh¥§§Ï-E&ªž7Ab¼*~Sò÷8#|³âá®F9+&ª>t¤–4=Nƒ|1”ºr†4ZäŽ<í#;²ª¥ïvǪS2Ž‚Fvl ²My¶ÃÂÐ^X™h‰·0¦ÅTéå òù/Ÿ&ñpZÒtÌÓJm…ܪdñÀ³7·vË\®kǵÌí¹7¡*”úhšß&ª6ü°›+k¹­ŸÙ³`r–œ×ìcfq'~º LÖ€ý‡ ›­½®ž©U4 šr€ßlYlbÛ¤ ;Âd5ö¹Âëšçßi°¸sÎìÍåfÛ~Æ`dãkVCÓÏhtÀǾèr«ö\L„ÿ…dÿk™ô=o#‚} 8#ó'»’Oßd|C3ܱ9j!PŬ Æ”l‡É è“ÉY=MêÅäßH ·z«î˜ s€^¸, —1ªr¿p4ôZÚ“ HŒw\¯ªhg"þ xÿ*P‚¯äõŒ“›ª#CG@¶€jäÚÏKåeÑÚÖlüÚ¦$úV¹oïçT2>mölÙr+YÆË¾vrúHž”ýyH "]0 £½¯àZTu ¿N "N·+Ǻ²ív˜BK¡Š‘;æÓ-0C$˜mJ/ŒQÝ«ÎÖiD? 2‹XK²–áïØJZzÀÄžB¯.Yµ¬¤ËQ¬VÜÊ1²v‘¡ ªâ[ÆYoY4Î&¹å<+¯ ïº*y%X¯R¿Î1R&ž•AI)Ã4x£«zpÑ&ô˜zkTm1#0F§ñÚÛ$«¶¢FȵÀ0&bZ¾Ý(•ÆäO)à6?¦÷#À4(ž¦q P’YÝîóªaØtyLâV"ëqÒß[¾~¸4jiUXôtþÞ€iÑòÀ4¬:ª"óާçŠ[@Wn2AæðÂÜô@˜áYè>òd5æPNV/}xÓÏf÷KB¯*÷8Ä4fyÒ5ò'ng™ # ´Sb˜8¶g>-C¹R_ÕvÆÀ1)uE–ñ¡š&,GàÛ$#çd€ {ýöÚ²6 {ˆtåC3°ª+íQˆi”œÿÈEŠö“«Òó;âW"®Z×x$¬ È90ÝŽ-0ó@lW ž®‰œM2-É»;±/ŠÐˆ§ò+ùåÞbß½˜J0ÿ9“9®¶€ÀŸF žÀ¤£[ÔBóìÂôÇŒFJ¹Y²P•›ÕVL{æÏ*O²=WŒd˜p¼R«íÙó>'ÂmÕhJ¡/t©öàÈþpÅ' Ü·ïõ:Aí=~+mgGκ&Ƥ—ËE2¼qôrã0‘Ž€¬Ôu`@û•œÿWƘzíÓû;ÖBC™@~&-ÐÃzÜðs<1C`+eˆ×û[É6r¥”ÄEãˆÛÍñ,ñ¾2±F³ø(‰Ú·-%Y©›ô8•´'ÞÜ6¡ùô¿ L*²°J˜Âkno.M’#Ï:ïÂlrëÂxY—ýÈæ)îðómV¥t ¤o¼H£ ©*Âôp2²A>7í•äkvÜcÁ%Æ”œ[•‰ªÒÓÎ ¿Fcì׊^/@/RÀ‘Z"[¦wSÅ +Áícˆ‘Ns¤7úø÷P‘ô¢q€êL0¬¬š&<haÇ&"瀌ï;Â2Ÿðö¬«_pÈíÓ †-6óF3ÁË}(=B%+Á‚§ 4ªrÇåm ïsϹwË–! ÁÓ‡ìŽzýÈm“ø3þýY+ G£»Ÿ¾Q€z›À”>< ÑøÝÙ±F˜Ö–Ì,d¼£*ü§ÑR©êf5Hž? Z,Az» ÌM¶ Òð” RÎ 0B=™Ø†ôµÄWº{ÔÏËféê)2”+LÊõÎó¸¿P•›vÔh®£œæì¨4ÞQÔ¯äA¶† Ãi:2TôdH³XT [ ó Óµ˜[âÞyþÁHë—•õôv·ï"S¡D3=q¡¨ª Yè’«¦”ùËõÖ#áñuáÝ“I>‘Õ¾45j™€†!F;p›Î-DíˆsN9~28ªquÁ+51 q<¹=`«öiÁ]‡`7B.ð› ãùA@&XÉUzLûÈ>Ápƒr€Ý"“ ð|>•dJY´#tñýös®WÖ(®ê$ºD-J𕼾T"« lZ*$ÓBPV…EC{"d¼.ϲˈñ»ã•Ÿc]œ«6"½Á¬Y4-ƒôÃøÞÔ¥…•ãYôþøÐ`„>+¥¬Ò;jàlp7—ýá*4;Ö"“±uk¸j³d²LÂYaDb­Ð,ºˆ#Y&SêUÍŠhÛÄ1Ϭ*´ KjW-šÒ—ª)-F©DƒTÝ ’Œg|†Ž­:M€þN~}¾µ u5BcCIˆøJôÓÔk–€E—Ò’† ²õá aþ¢jX xv9¦$+ÒÀ½†ê‚Øo!Ǻ²V:ÿ°‚²#¡œ"²UÝÊ*nÒBÚé3ÁÐÀÞ‘^N?[Œ°ty[ÖâHl\VH#»X{ÖhVzY ·‰FSüx4+>eû s0.r‚@½«¶Uÿg5éùl@ÄÈÏ‹3ÌóÙhJ¡„wL##µ#EGŒ»·³¬* Ce7É ÙQ‡aÇÛôéËq'¼þöÀ] à O 3ikô°HÑDJXn" h‘ÛpÏ8MUÊ9÷àcð¡Å”FT•E£É”È2„EÓ1d®±Œ­0MÏ¥…À±YaYÏ“^8ƨ¦éŽJ™hÁ(ahˆ”1¦Ï0Ob ÜÂÛ­‹+U•»e#š‹§„å”ÙF‘ŽmÅ$&¢#&27bÇžŽnɪjÜæ€#¾ð#œ¾ûn²°Ì¹qÍÒ `Ìm£hÊsÏ.‹¯EÎ3¥c€Lp¨—&Y;Ð\û×^n€PÚz1Üônh|nªUE>Íí·Ù•Ä•zgÌJYLÐË\Œ§ñnޝÕãlp¦©mï¸ëê?Þ×&ŽJÄrí˜x†HÑC¨vÌS&‹±Š_Ya”àÛ„˜™huJŒMfU;‡6¤´F©+pÐØC#ã+Á”¢q@ksVÒEIF Šú··Hb²F§!ÀèRjmÓsh–jS(J21ˆo\×Ißtí|dZŒðÏp~®2Wt=³£’¢Ñ½ ÿF,Ò$îÈù6ëרíòWÒwL YW‹ud(02·º‘L ðaœãí;¿å/ŒÑb‡ª0 ã›uLßj&sdž eÔ(”„£öFt#zJ%L&Öè(ÃñYeR‹Ï¥ïO²&j© C WUn|AO);ªNˆÜèí¬Tûs>”]D ˆÌ\c]¬„£ÿ°W΄8LJ ú~"æ€Ì¼ëh!&“•<¬“3q$‡þx¨Å»qhgíH™’^»À°Ê­–4|"µ7—x2U$Yà šU›w¤†)×›[¶)¥ÂQÀr +ç“ î;àx†ÝçrM»)Õ›Aþ½RÎ˵×%»H_<¸ö3»³‚ƒ`ıgª¡NŒc¾Ík6²I²˜F5sŒÞªÀpžãÝò\÷ý)à[’§Ñpß¼ö^°Ñe¼ß€4íÐ¥¤àŒ´¥8#ïÐØ’rÕÆu|N•A©EF¶[&]–­€ µ-£ÞŽ™  ¥”»~]d‹ª|Râû’8"«"7=ÛæÂ¶rû+ÿ HV^n³ø–£vd;ªb|0˜f禷e¶˜H‚<[ê"fNOè?`4/·L°^ïEàüµu!›ÞWih»Éµû¢sËòFÓ¨:&n‡FÈ3×n.ro]б•Ú°!ŒH©î"‘r Æu”7 nbßJ‘2[]² “5Š ›+ùß`È¡)]­ÑªŽÏ®½O¦”97d%½bJ¤£l™déû ö&OMx 8†µ·[>yÆÈ]–8\µ¡HW{®©”x¸Ï.ÿæµ¼Og\#zœZ¦dB©e™ œrƒ")sK&4"ü| |ÎH`ÊñYqÎ-±ODhiIÀã‹þrJ A­Z£ªh@°ÈöÖÀ³ÔHÀ0¾k¹‘UoO¤H# wd›!Œ.úUdÀ~*á†6ÅQ´\Üñõ/1õ·(GÑ*²¾fG0Ž¢.Ù6•rPªOš6èSQe²YaÊV–šÞ?Qî&í¦Ômõ6EÆ,È8gXoxã\²»Œ¤ñHa̳¥'À#•º¬,z„Ût. ôÏєϸŽCúzgŽÜWVÍ àÓh½ºðΰv‚@ûd˧Wr…–TòìJyæOÖžþ¼¶ Œ7Hf¥½#ÖË–ñ"ó¦ÇÈ)skœì¨1@3Œw”+ÉÎHV)i*•ûálvv#?uû÷ÁŽ¢§cØ"[¯†Ðí…ÍwÍ<‘|VjG9—·€vΪ”a%s 1sp$–ù¸T˜ÞÝóOÖÚôx™ Mb1ñöÁàé1gàž¬ŒTuqèÚ0ªíP#LðÜMKÊÇuÑ×ø´%Øþª>yžZêÚz«ê²C“`ßU|ιÁdá†æÌäÉwëµp5ð©«R÷ÅÚëqpU KòŽ51ÝD6‰‰5ÊédŒ‹‘5ÙÎB Ó7Ì1YyCiüGª3ÌŠL ßD9­ÂdµltÊmÂÄÕ-Sbò!Vj™0~ÎÓkWrÀ¹á×4º4ް ƒ{²µ#Ù¶* Ôkh‘[l¿OÇgËP„)9ØœF 12’U#rCêÚŽJ2Ü,GÿÌéçd÷ ô{XР˺ØÂÂk(ÝuNj„M<ŒLVϳ\Ëî´óÙq¶ÕªÝ…ƒ˜ùLò÷ªm…á& ;”ðdÇÖótù7H&«‘'@™›¬$èåÚé8ÒÓôYä?²6 d܈Ã4)cZcÿ?)‘æVU2Hî8ðÁ ó—E «fHéySÎP ’žR`| ÚJv‘Ú•(¥v(M¬Ñ¤ƒ…ƹÕBy Î¥2¯ „™lV÷ÅcÚ˜+y‡f±™Ì?ú.Òãªý|ñ$pº‹l.%¸ÅWrlHôÃ¥&82GunK¹ ØMdÑfHvŽÛ ŽjìØ£%æ3`4¥Ú>gŒÈ\)O¥4JQÕVª<ÇÓ(õpí¦”X¦éȹ Ÿ>­Z#eb²^È–„ÆL‡±¿ÜQ‰àèîòfä?qú™¨ ]˜ö-›Tñ2ŒŠ•ª"õj ¤¡ï: ûEœƒã¾ pkgÒ2Y¥Á´ñîÅœ@/·'P¯n´Rz€‰7]y:âE-Ú•0üa ²mY±MpÚî’ÙvëZe²&š’ £‹'Cz% KµŒ£0Nö ¤Ì$7íH¥z‘)#}:µ°Ê3²Íù´‰þ¶¾îÛ]Z@®D£~êU¹á‘°Æç&Z:6×wC{Ó1….ˆéYñìS#À¿î?ñ-£ ݽ÷Ä\ËS­}WT®×¸Ú# üÌsÃàÓh„yF: GUb@-#ãË€*±…sH¬Ú²R]€Fzd;¤ARÚÁ;×Þ¶.2ŒÆ>‚ÚÓÀÍÍÙŒj¤èˆOàØÄJçÿ@5 0Þ1¬SRXVr¤éŽ@ú6+c¥#±ØG2äÿléEð"%ÐD-°ìÈ¡gêÅ'ÆÀ9äÚeíJFo±%AC>yMI܇—¡–Ž3§Ñ˜žF8’ÙGä‰!n‡ze¼–Äd}ðdµÈT˵#…ÆòzxÁÇžþ¶‚ì=û³3$7G˜F~º%ÃTÚ†€ÀËi™à Õ’ÙoF¼ _K¶edúÂQ©Àµ³í¨¥}ª~ÏöWTG9[`ÑnnÝS°e²GÈ ©QôÔŽÚ½U1ÂÃêÊJv$Hon[9"á@ƒ²Â“‰ŽYb ½£q-c ªœHÖ¬”Ž5NìˆTS¯Œo4  Vr);àÉjL#«bÆW•±#¥ÑþÈL¿#rn±&&ƳZ`-²M‘ó‡ée8çF`süJŽøöi%úù;†e¼O¼%ñMwLS×feû$É|!MôªÆÁh ¬ÔV0²²)=BÌi¾ÓPY ²%_ÿ- `î•éå¥:ˆìYÅ»·Ÿ˜¶ê]é5¾=d—qn.ÇrãªÚ‹QrôÁž@˜fÁ@ÎÀ³¤wú‚`á.¸R oœù@;ØŠmÎJmkVã2œ`‹% ¾UþZ¥•HÊÌ«ÎÄQ©ªƒ`àrǼ×Ö‹q$в}瘠.íB#¥hzÛš+”+ÕE ‹Õ<}Û9‡ô9#a1‚Öˆß2 äÜÈÚÌD² U1ªr?Až´•äÌËÚ¹©úáîRãS‰éÈ^8Ê»TkqP"–Ÿ8#°ëئËÝ=%ŸºRʆŠ c¥ê8¬ªK¾sNUI>m·q—µƒØŸÁdÙnßIÇøÍjâÈ€ö”Ó7NÕ½ø Ý€‚€'’ sŒ=UûÜ·3·nJ Ë[{GŒÐ«‹ÜrÞ,Ç”z1ùD&kù¶Â /–³.¼˜§ýE1\µÜ kó©”©Z/íÆxS0ŸLž]Jxš&ª"b%ÕÚ«ÊJY¯¡­š ÜÑP¡%ÎmzG&9ÚÓã…£F ‡@$±#62@IDAT±£xšyí ¢ñ2€ÛD ÆQ# ¼)H¡‰Ì<\&8ÿ·€²(·Í\€­7ƒ²ñ@‚³û½dëÆW’ w Užô€hËù´eCŸÕ0q£éÈZž+á«V".,lÕFSb|½tyb‘,óœÛ#T妫/#¾’£Põ)Ê6ql ‘”µX +²€ÜÑpèï­™Žïç0‡LèEL³f¸jæÉà­'PbnOSt ¼?;Î퓹#± ¤é¨¥j£áÀµyyj!^KG™X̶RˤQªª—mÇüaz¼ÜæZD2|8ЕPÒE©š§ c„j¯Ýǵä™,R—ép¶pΔE†­ñl¤Lœ>s-}Ü”µ´¾q¹MŒL™s;h0µ‹AÐ#G6&3¨RJÿ‚Â>Ï‹ÀÖî?íH\• ž‰v½HŒÌ³#ÜhLÿ Û 2|ÓË9 V¢)Dæ•bR6‚?¼–”pkh)ðH8öt]Ȭ«Ê"Ã@—¡˜[c ¤l+¥}-|ˆaÐez&åJ°Xìç—¾Yù XÍPrÙO?p—a!R”cLÒƒñ©?oÛ`-¹‹w?+¼ïãh„Ü­²uâÃôd%‹a”z –„«&#ÀÈ}M2%]"%Àmå8¬×±ôjÜn#äISpÆ7º•0J›hGn‘eJ>°œ`_ôm¨ä¿¡´’jÄæ ˜¬ËV¥¬Ä¤®,”Hkø(õý¡ÂÊÂ=‹ggHÖ%2ÑÏ<2+í4ðrS0}£ð gR—#ÏÄ9ï¨ÅSä ²ö„’´„·gÁC`4LC‰TÏ\éXßHF©‹e]U‘á8s2G$ ïè6qÓŸ&d}èm»5øøD:¶jæ2²eôn«Þa‹ÑÝòZ8ÔÞ¶Ì 0…£hÏ”eß-}%hÞ×@ny¥§ÿ–ÁçÖ³(1ŒÄ[R`8ôÎùÔãÓ7Ú± LdëÉ“ŽÝš!eæH Ô»žÙˆªÎÓÚŽ«Æ1¬½|kÆÁ…FÑVùhtl: 1®˜Üä‰{4 ™¬]  7èÈ$fU&矰‰Ö ÏHÛÖê>޿ɖHæH&–- ã)?KÏ)ºT@ßM< Ý=åŽÍJ/wí6©Ë |Ó[X>ËÝgЇ‘BKL†ðœ›‹!†_z?œÇèñ¤¯™›# e?$µgu»_œØg_Uc¹/v«bÒÀ‘ø‘Ž~8§¯‹I²2=@C ÷ÛßоO•uÊæ:ѳjè<‰ÉäÚñŽUk)¬1½ì­šN_K&{ä¶Ú@#¶jÓÛ©‹@øžô_alŠh–¬‘¬)O2¥RkW‚‹éÍ‘gÞý8½b&°çUʫڹµ1¶eåî°€+¬4æl"¥RŸr2xÎ h>ºb2™¾HŒÞ~Ň•j‘ ê­—tlÊ¢­ŽzûRmP+‘û§‚J2Q©»È}?uUÕ%æÖ¸ž¨R½ŒªF&é 2qŒé©½–4ª)eiO>4pÕ”ÓÔbáMìPWJ>&ÍÚcš¢¥jŽüg ;#9'(cTE%ß Ê×_ÿ±\üÛ`’h¹ÙaÈZEvÌÅC¤éEhj|V÷úm Ógh!‚­›ñ4­Þ )«*]‰ ¡4vÀ;v£Ì9×… ;dõÂmU/Þ¾—xoÝûèM£*8Ë~ZÚ92[¸Öå¶d›·1î ††:öÑ0äOàØž â •ìC˜ÿwhºÚnJF숷؜¢—1¨1lL€Äȶ`múöÈš dßÜm¥ ›$è©×Þzö²Yô[¦‰Ž{±pwï÷Fð‘éµ›%›…ôÆŒ'K\£^ŒÑ­×&10 XlÛÚóAHÐØJæŠvμ=•rX—¾3Û9YØ €L o±üsõöe˼/3F#±ªF¥<¼j;;vG %±’£¨Åцp;$`‚‡ëª¥gW"–­‰cb ¼ÑwÚë/ÆÈÄ2+³º&€l ÎëE6EfÒd‚Fž•’ÑŽÆ·ÐzÊd=¸™X¨v»l1U;jIã˜OzÏxšß?}Æu/ƒ„.?Å2ÜËÄzó‘GMßr{e ]Óµ«æúsìqW;“žÛ +•ód²7¢7®…²ÅÃbž5Î?Þ‘’Þ—“Þî«vü2`)sk·à/l˜ÌQIõðU¯éÀ°Š'ÓÛQîîþÞäCê¡rVbg®ŠëÅ»¦_âHƒšÎ AÈþ?úº»ª ·OžÝH{÷mI¤ebr“}ÃTÛ'=\¨f ´^GU]ý;+˜aÖ(óTõ ž¥ªFÀá˜yÇp$,ð€Fí07™2OXì"H8M³T½áGüé¹Ï¼¹&æãØV}«f.Ϥ®Žõ² X0$ÀÀñŽF;Æ3Á÷qoÃÖ˜&ß(-pÇ^I/¡F ˜¦AÈ~]âk¿’ƒ…jJ-L,€4òÍОù×V=;€ì›CÃ!ÏmH€w¬W•†ÞíLœ@™&™܈’^µL@6 .á܆M7å)Prä¼  LÜÚÖHxû|ôdíÖǬäVʧUa@Ô"ÛI‰ä!fsÏÿ@Ö·ñÕ‰Ñ#rï) :–çõä5v”kŸÌ>¦÷õe¶2·4Z¼Ë)¿£cÓ[’2ç$z ºg>ŽÄ°hŸ9`4jÙÒ óÏ– c2æZ£Oœ¡#àK£ø:æƒ×(×è“c˜ç¦„‰sãS£P™gnöëÝF¡ë}júê iðØ>u©*¹õÖÈꌼ-í3,ð²¹r†s>å+Àhá€+É0¨ ³’2­#ßrr{bŒhÔ¦`\éjÜà«:³æ†áShJ¶^o‚$à³ÑÍÂàÓÏS)YÕ&Ö»ÜÐJéùtltúª°Æ®Ÿ ÝT;*=v‹Ì™T’[RÉ?ç&›žÆÅ»;Sï–¬½L6+³>ø·Þž([Ñeuùn;c(›X¾[;ŠJmÒñéó4®jƒºQ ´ŸZÎmß?V’LhÄ‹Æ×NÌŸ¸ò×OÇZMÁ¤iG³äFpƒ—)ûìÒ86‰ýLö7’Ì4«|v22;À)0¤²ˆäÛl€8k¹ ŨöÖ寧 ñ4Àd=eä™t aƒ1+‚¬èž™dâØ‚#³Ò…/bà6qŒOF‰/`ûz!ë}×__P¤ [F©¿SwqÎøœûÜ+ô|³Å[©eªÂü= lÄ®¦¯Jù!Æ71ÛÈÆÑçÖÃ")aþ¦4‰1{Ø>ÇvPÅg.#u1aå¨*æ7«AiTÍÊ ²»„ŸU|ã2w¤yŠÃãɶÒ›wAC·^¦ly q«v#¼A½@U¹À«öifÛÚ[Œs%ídºmDØ1s ¾H6F•LdEC chê•kϪ˜ü)ÓxOzásÔ‹ßbæ‰'Cjéß98Âø¬é S\ èHŸ[VªŽÞ!ó4ÄÛ„ILP££x3Qš^{J½¡دî[ÅÚ6‡Ö‹ï[²ðÚó§òiÛ¦—)3¤Ö»q˜¬>‰a>•z¢QºQš# ì"Uc(E¶7â)cdL¯zþ ”8ï="¤©@Ïšæ©„‹Ûú)µkJÐ{µGG‚âŒÑÙÒ‘Ý_‹êL½¢–²^Œ»zuµ0ÆWÁQ—Hè™ËdÓ¨êåÖ“ Ýn{º|øï:|‚@oÎᑵŎ€Þ¦t‚ŽUÅÐtl=G MˆALß”œe×Iƒ0®Eµ×pJiàÜ002Po&rÏ…'«€•˜ÈöÌds;–7ñ9ržY-¦*`Õ–|¶Pª–Ó¨:Ê–ñ÷&[ùɧ©½*âd@+¹;œžXã†v¬úeê3tås&Ì{^GAÏß»Æ1HËw”[©£¹­Äg%‚¬j4W ^c‚nʹŒL™8}%LþvókIIЭÛÖqkÓT—‘FTj4†dÈr»É1<Ôî”Û ¦„#뚉^³„ªPÅÈpn¾µ#Å‘ÞHf $(Ïá)3«£¬«œg8«v»œkLŒ­ ¬´Ñ ²yúø&žß¼n%û´fÃhšoûÚmd<}Ñ<½Ï.˜¬$k à{c2‹r 诘¾LûâjÙeÚPæ@I#BµáÙ:¶!Û¦·ŒFkÙÇÜ 0}-azV·ï¤;íÕ›YýKá|ˆµ¯Tˇö ¸Á â#´»—µ•˜´ >å3wA%²”-`²¹ÚEšvÈVŽTÅko¢#Œa…¡9ýoßÇpgðã·‰•er¾’óà;]¨%[ƒ4R¶[1”"~sG‘lB{9«VŠŒ‘]côÒ‘Iº,‰É|%û䆄…ÞþyÜ?#"Ý‹ ”y.7º^ ¤tÈDïÓ”Žý×êûI¡¬ÄÊzèýËÍEÄèëšy]xŒÈ°¹µ œÄßgb$€×Øò2Po]œ·XSÛDoX/nÏŽaЈÖKƧJ¥yÆsh+UŒ¼pô)hä¬1sU-"Ð-à9+5‹mšªÜbòu: TÕì¹ÉämÞЉµTÒ‚T°Ð èëwÞ¨e5ÒfSP×9¦ß¤Ñ›±ÃÀÈºš´¥ R*ó)cz\ >†HA0ñi»¯Ãß•|*díÐ22J@fKÙ˜Žñå6©EÎ6°#Ò”<™„S ´°­´ÄdJ­AfRËS·RPªæISn¬«&[-í¯mðëÆ,]zé᎙¬%žã{Õd2«V5³@:晜Oõ²BvYhÄÓkoÃ4²?øiº äFÀZš(/2©‹LËÄJa¶6é(´Ãd¹©Ú6±l¢\ SÂe¥€AÈ~^Â<“uµ2±6lI‘~€§ªGØb_ Ù8¹Vgž†aoÒn2ý^ÕQPæ }ôñ©Ò°"Œdñå>âzŸ×a؆dñz™;ÆkiLßd]ÄxOŸ¬ÔzUÁÇÀó1"%Œ‰Ì¾ö'‘k‡6ˆ²ÇdËÇñúŒšž•#Ç?cÞoþ_ƒ—‰ÿшèe| äæh7ŒXK%b½²Ø”É”Î7»:åÞÓ¯- qO/[¯’ß¼ø¶àXµu>í§Ê‡@4·wL4B/½ÜÞ4¦``¼¬„±‰–~ƒ‹ªþ§v—‚Û Cé˜mJ™yÏ~åÑ´^«C/hÄ6„#ÉÒ÷—>GV¹%>Ûßýé1ðZ2^lí¬ÝñÚ¼~{â÷]çCC,>ûì3G€@´­ãõ;iJs[¸7¡L&+9îŸÆrÓ‹T²&Ò€ƒêxAT%.4êzJ,ãi´œåÞ¿qµ£Ë‡ÏÈŽU€ Pf5g ç¾'ŽÄ형²0lUﯲ*²^ƒöMË*Õ>¤k¶X†åÕô ɘOj³¼o¯F€Ó’@Çvã‰×…Ïß±O$2ý‡•hÒ[›ªLïÁ8GVm§ÔR8 X‹¬Åqþºº‡Èüã³mÃ|˜<‡Rºx›èÍœÀÏÇ1lŠ`ë( Ǫµ‡Uܱ­`o\²}äø+Ý.^žCâ4×þøÀ²åv“c\H6q ?[`‘OSÂcö7{RÚ_‰Rœ›è÷z¥ó@Öçp‡m $`mÛÞ€>ãuѨҸÌ0dSŸ†dd‘yÕü{eÎB5A¥ŽrúfñoŠ#P{·˜=œL{üªÖ Ð.7B‰­ã‚¡Rwɪ.žçñÉy :ÊŽ¢…ÛÊѬvKc¢/7¾ödÛçôß²6úxüþ[Úãí u„#e ¨Rú”Y¥ìúdŽpzbÓ‡…A™˜¡P¢”ÒA€q¬K®OÔeÐ¥ÏQÀ¬€3ò:ÈwàëkCП̑ÉsŠ5Z ù\»Až´ ·Fì.HÌ^ ®²F€0]ĵt,§ïFÖÀÛÏÏ¢š•ÅšÞJ¬È”º#ÒQæS{æM$3( (u_8ó–'”d|þ5ÊÏ 4Óô¹^%G@ʰ#¥®ÖkJbz§/׈L?1½è l÷å™ 0ˆ̬ 9gHn L“²v؈å3ò~¾µcjG6WHLïFjA:ÂMqü4-,‹ÌÛíøÞUǬôò1¥ßŽJÝWûÌÉ„ªŒý#ilSå6FÔsÖ¹O‰œ¯Á™Ž¤¡' HïWRÎÑ­ú!'˜ƒÑ02«+?z@I ІݼúKaòÜÓï8ë5‘ A4VùÈŽLRö)"cÙ*a´0y+I̪×yÖ¹p3+Œ^™§Üb=]w·@`¤œmÛjw̶Fnr÷‚‰[¾µé‹Z¦ÑØjÎÈyÂ9$sDÂÝ‚[GCɲ͓C-Ä>šÆu¤lÿXV¯®]€™I‡ƒ˜µ´@]J‘2LÃh[@´Xíø¦g[Unzž+9º…’‹´¥*¾qJ1rªR:š’'¦ˆ'ó5ÆÈ sÀÃ4Ú#ñÖòZ öôí£T¤T¢y~èãU1O@¯´Ø°WÅ=x¹cüfñQuä¬rÆäÙ†MÌ¼Òøua”¬°?rß™ÖhY·3BÔE©Q»oÚ¬¶<^b%O™[bXÀ4{‡4µpÖè(jI¦ä ÷ï!®êü¨²íFJù$v}Õ|dÇùÀÚûôJ•ÂßøÕ¯~¥A4+²n ¨g¦‘ºb¬^»1 «&fÛÃÉgÞH ‡3ø~üôÅ[õúÑÀU·Ò‡JSZÀ‘Oþ-€$‰±%|›«&N¦J¹J˜xØb;†éE+µFû÷h+õ;NɬÄ<HàŒé©™‹µhܰ.æiðg‰ûÍV8ÈíÏ™Ø>€ñµÇwúßß] ÅS:êÚè'¶$®ôJŽ0Þ¬z{J%L]4-ÙEKÊ‚^Ì?Üx€ ¡‘ËÕgWO¡Qàë­½cæFišUÞ/Ðõ’ †}‚aþ¢ »2†¸‰L„cŸBKÚ;äIà­ôª GbÇž…[z9db º‹‹×›¾ö´Óä ÷ÙuTʧlænÔ±ÆòYñ.Y AŒAÏ…’ÜÐpzY»Ñõ:¶Æ—Ý´S–›X—ÏÅ’]Pbå8ÿÆáMlŸ­Eiëiq$5ª@ß^üöIì¸Pmh°FUÂnkËŽñÈœc”Díý½Ó±Uéñm›…ίqO§€Óù’)ÁÈ èníšÅmz%úòìÄ•­«…?·&ÊJý™†¤'µË0RÕ)Gæç ( |€CoÄCT-w¬j“­AŒÔÞ59Ó7¥[L—ʤg{Nðéž’•#“œŒ¬Ô>nÉŒoeÛ’µFÐÓ$ƒ•âÉ#„µ•b(1ùÃÏϽ;¶yÎ9à90gÒ½Ã9W:“ÞÿÛ*F»q‚Œ„kLjvCÚÀ¾ÐmKÌâ45¶a˜€ÌD]ÝBVÚ”HG²0¥®>ÍvÀï‹Ô­³ÍF 2>B—,IyþÿøÔB­ß¶QŠœ€”Z¹öãrC• ¨vmÛ#û-ÙKq£‘ûÚå“s¶p¥¶gU‹¼Ñdpãâ+eˆ1:Á˜.b.C[y@u>@šz•L!Ëfå– ¶<CJ<‡ªíVoW£TkTŽr³.÷º,^DfbJKf¥Ô8¶[¤%1®œ¦Ñ‘L|.xQ×nÚrÖâØ­JÆ¡5ÖK\àïʯ*·ƒP¢ÄûXa ä©%ŸÖƒ-FF «^Ó¢$È*áa·s$K\Æç@4õÒ»f¶Æðj±pJ%ÁD’Þ±€F(‰Ú‘áËM:fBÃDN–&9Ûýj6+= cXZCyÁßú[Óò âa½&‰¬ä¨^Âíܸv½[@¾=ߦ“Ú¸ræ>`Q©®Zrëv˜žˆFZf8¥#Ðþ›[WbÛ¶0’Ød™tln;¬Ñq?J¾¢”cêÕ-T{„7—ÀDL‚§l^ w¼ô«dh³‘Ræß&vNp~1iR&"O÷í¯nL^.ÌèJÎ 8YÖ”]ÌÈ4ª@G%G˜ÚåF¤÷«•*±Òª@ëU‚Ü­𠀿†Ø3!ázàkgÛGkz ÜÛaŠL¬T5Šle˜†­•ÎÔô­ÊÀq9q‚z3o&RŽšâ‚{ZÃ뉷ÀÓêiH&Ú¿@òt´µjÇpï „d[®‘“[]µ$†3Ô¢úÍo~Ó[Égéÿüç?a¥˜|zØlc<]¯—2·9›"ñ·g$O·CnÆD:"는…ú–8&ÛiŽbûû8b(͵s¿(»™#C²ÞœO]íßMg§®özÚ›¸qô}Xkoº.‘¸MäÞĸ¦äï˜ YWÙ‘•’µ[•ƒRûãašŽ4b†•bksŠõVm%Ǧ$sä zÿžÑ‘`/ÌMµëׂ!H¦‰˜F ;Ú n(C]x + Í“=K°à™ ,ž›hïî4ÄŽd·ï¤>M%]ã7:Ãö!¦©/’e«D–Û±­l3äFŠî¬ QIé8²Uvìݱ¨Wö^º|U9+ WàJdÁ ð;iu¹ ‡ešºd8ì¸Ûâ¦Ñö²Ýè¯äŒã©_; ‹ÀªºklÊu:¤£ÞÌ)Ÿ¡% =™¦²MLÃáYM†iôrwïñU·[ ðií@Ó½XϘ†Uw¬×Ñ·¿c£7ÑãÓ›óvTÛ_ÎÖž`Œ–oûÛßúÖ·üö‡{]Å?þñßüæ7Ÿþ3e¦¤¢ûiK}=©PÝ SÎN/q&a9s£É2 g+ËFÇËõ.÷«§0Tí†U™ÔÅ^õú@Û¦d•,VU"1ŽÈ”õ&“uÕ8Ïô³Åó‘Û§¬Š¡ü¾a.h¨–l (…¤ã¹ÌÝ Içïè§”ÕëªÓ\”¢A^8r½J9P”´; z¤h¥§XÕ¸œ ÜÈVþ¾ÿï|ǯ§ÛôoÒçŸNéÿ¶¨v½°Y}‹ú—M¯3Mׇq½x²nª–g›9Ûª²’Y~ƒô¹e‹×›&‡ s¤Tb˜J%;  baÆZð@n@[Yƒ€?ƽ€ÆÄÏ.bD hAÊ—‰LOÃ6“üYÑ+>¦¬,£ŠGjñÑiiœj³Ã4·éÌÆÀ6þ\ÑK,('Þu2©‹¯gÚÉz.̦Ž1 sn7U9öAN hŸ†¬ã˜¶’…ö¢Ãø3#_í+Y¦Y‰ÙjÈ€‰Z„R¹ÑF©Š˜Zhð˜x9™µ?ˆ!>ßK‡vê¹¼ŒivbÇF:£û³íÃÛ0<Íôµ'@{#2ш¶l.¦HÌÏç9…Þ÷ F©ªç6Bo|ænn"f7Å; ]-3¦¹x€¿2˜Ì>î ëôÃYµ[øhS²Í¹­tuÕëñú35OÊ>$í­ZÆp½OS"Ç%•, 4ݸ€Pv0+ú€ëBµA2Œ©K‹71·—Qây;^¿a­J)·p²›ïj/ŸÆåà3õAðAZ 5”„£®ÈÖèv)÷2þÔq)¹ÿ2•Æü¿¼†v³þö·¿ýå/éÿÌuþ==OŸQŒ¹T Ü]^û´^kÈŽ ™4T‹Æ¾m³M{ê˜Ú³JÐËÓ8Æœ î›!4Æ·Ìœß× SIV’·Õuzý_°¨‘¡‰û’ô™æPÌYð!æÐ8]ŽÝK)A%¼ª£ÏW æŒç >‰á£ÉÚ3Yí]¤eêí²Z|²4Èç5gž¿Lÿ\µA‘­é°AÓïï.<#ù2ÌnÚ-øçi" 7¥diäñ‰³Íp›OÌ æ¬KÓ´$[” ^ÿ¶±N À€ð£’®c|^ÓOÜÇ6ÏÐìEŽΰÞõnÖ|8ˆŽ­DƒézµÌ0™c@æ| ^ÿç•:–«2œ,¬—zšÔetþŽÍªkêhÄ´§/´/™£FßÂZh˜¨2‰wª‘žEc$ ³UU‰‘YUÅw¾Ü^LK‹Ñë5Ë$P£#Œií@K6¢#ÿ‡ß¹–ߥ×n®¦´­z‚¸wö5úáß5ù¥Ï$òk³G ßýîwÿçF¶F›¥#xnÛ˜­Gc yŒ^A†ï‚>G¤€Ì'%÷±çÚƒ¾é³åF +e «Êº€v IÀ9|O1C"žl‚Ví²øÙÂÏ/X«Ê‚†•,šÞbÉhª2'hz¥U|w ¨Öezúª”Ýݱè1x²<1®ìÉÔhÙ1Yž{“ªÈ”ŽœÛÆr]@½JaÕýTb"úlª¬Ú-U‘ÚGoØ kyþëdû-tþn¨3u¢ì¼ÂÈxYÐ7>ÀÚדµLã¨7‹g#,òoï@&V‚»C½•Ìj·nµYª òyޣɇ'L ÑËëõm-Óù$Òd"Ãz‰5ÊSjÔÕôôM1‘Lªå¦Äëòy´XÙÜdgÑþg_Žª Õ‹Ï ø;©éÖsdÁM´¿LÖèÿ[6qð^ ¹’¡›rÕ¾Žv˜˜C>žôï7÷žùÀ"\ã3Ó»` àß#ù½ï?iðKü¿¹¯—üñìÏßýîw6g%¬á‚w£ó‰ÓÀíl4œ&êé¹ož ÖÞ­YÝâë‹ÁÄ¥H2Œp»Üºf>•Lé1ÙÒ 1{´˜ÄF8¶%kIܸ”ªŽ~kvƒuqæ Rf¥W „[F£ˆ)kW‚[&¨‘![G$œ²vÇe¤°¥–)óAJ€ªµMt…nÑtUß:% à‡ÓÈ<e‘Œ~‚üka¤†‘x÷€Ú5ÙÖ• c·^€I9~2u©=Þ#r؈smc°jÔ Ý_ö.‚˜Í¦Ü€Œ`¾®—¾Ë”3ÈÚÎpOÓJHÁA6t€^´0€oO²6Ùs';.·”L#n7%ß~x{*1ÁȪûØüÅ\_Ë3#í +Χ›ò­A߬é*’½OçúEæªý¢wö÷÷3œynÌ¿:øäl·÷óùÂ1ÝÌ9GV21#LÙ‹m ¿yýÎõV9û£Ë?÷bd‚¬õú˜(¤A½*¦MRÂñºÌÝCJ¦J‘̶ü½ï}Ϙªÿ}öÀÏþsÿÑ´ýs»_ié®às±¤û¶[%«ªÖ¢ ¨"{½.¥¥R•Œ'««¡L®C¼×î1e]‰éŸ€œØg¤ÑÑP† úáèé>ø?ô½¿wøõ¯Í¡Fžø'öjnŽx»Á¬`@ŒìöÓŸþ” ¯JùÜ!¼MþøÇ?~ñÅ‘-£˜-°;ÚÓäøôl¥ö©š‰’#>ÿ§gØ’4fAßоŽ=’ÆQKW–{7|ïÓW¨£L©WîvÃäÃ5+Éb‹š(ë•‘"Ÿó/%¬%rì!”¹4/¹¯ ÙA¦º¼¿JPÆ+!çŸs%è}ÍrôÄl-zŽ4le]U”Ù²¢ï¥dÕ¢^ÕJ€_UÝ.†ÀpkŠFži`[É…õüR“U5j©ÄIàhÝ®U[II£#%@ÜzøÝ. °_áØnª_LÌålœ\ÄÀí ··ôü…#^˜î{â¦Ý1ªM„ß¶~Eö«ß¸ýõ¯õ†_jýö÷,L”„¡&‚˜ÏÈJ<•`Ù4-™ Cd8Ù÷¿ÿ}¿¿lÈð”6k§é}ʾ{öýèG¿ýíoÉøð”íév´§WÊÜÝÝÚ†x£“Jã²Zôv¯ÜºHz¥<» AA“O@ÆcÈ2tä)Û!’Fi˜s]r_`íôVrÁüàxÌׯþð-­·mã Ï òvÛbþúò‡øoWò_óMãY5C±é-†±³[ %…±’¨%>«z3iùñµ8²õÉv;™Ø&"@à<}š•OÕ&böŒÛ!ß2ãð€XoG¤j<òªN‹^ǀƒ¢ûZI¼~ÏnFŽDzž‘@¶_ßf€€¯ì²^7ƒ ©v2)˜ Ðö™'†{Ãjšf=n•ˆùÜ»œ“¾.#ÒËY™ô˜ŒFckÈÉjìvü3¡og¹•ÖÕŽZ¸ùù§1DíÛgSÆt5$=ìß`ø«Ðni¾:›åš}á,c7áØk×ëh„j[1/Úsâè7B%›ãuYFF²òå¶žÇâWÏ…ôKߤgNßõõRÊ êí)0€AÈla‹­}%½‰)EËëuAåßÔ‹­A,ÜÔ/+ù·J”}4òáàüá ‰ÿ“ì²þ²É­[h±gíÙüñ}šÍ2ެ0°5­¤7Rî5´wÁFÀ4½‰.W&êÚ;·U&}Ê¡]oíĆr”ˆ ÇŸüä'˜®óÕÙG,v)Ma+3ß’F‰a#`&]ã(|޾Q_½@U¿ÿýïe]-ƒwqV®ŒwÌè¹Ó"Ÿ²Í÷Î[ønt>/âVuµí¬e˜ f¢ fUä&ýPÐÄïŽ> ~ê[;-|ºTûP:ÆÀM!³®3ø~I†•0ü14âüדÀŽBƈ^ˆÑFsÏ·ùØ¿wê]ˆ½K¶ªôJÄJx &çö@n 7OL&¨²m“Jòº¡±›B°Í1½K>+$&CdSÚ<$™WKF?™¹p›DòÌP‹ö|ÜÀcdAœžƒßA~Õºx€R$øŠÌ„›¯»Ìß<ÂQ¶ƒÆ¶Œ ¶O{2ä­çð© &ÐÕû;¶ +تý·øxJ¿þüç?ûm[£¬¯Å>ü#1Žk4‘,¥\#YCUÃÉXÅh¼›_âþK¥º2”™ûoïØG†Óš†`PšŸýìgþ$Xï××HÆ6óð¹Àã×Ë:ÚÜ,JØuº8²^í%ÇvAúü5: ›Ã”‚ 㘘¶I$%\U>ÍïÒ®ª‘Fì’Vó×å(jr¨Ú‘Ûø]©Äy-1̼­ºÚÝâ\P©}äÍmç"D׋w”¹‰nj"¦Ä;¶°ü¿”ÝMv+Ë­„Ñ9¸ã†ÿæ?,7®^ƒ×ÛY§Ì#Q|hÀÈ@ €Ì*)Jç:áÃã@<¶ˆóÿß'¾ Á\BRµ®Ÿa6˜Œ>ñpK#Ý­Ùàæ„7¹%‘éÀeéÈÒ# ìYÙŸðãT"åØKq: CBZ¢YÒ,/¤¦ÄrÊå˜áÍܣߧÅj—òÜ÷GDGáô“­5<²¥‘|­ÿüãóŸôµ‹MµØÀ†Ñn]ÚÂËIª‚·/%ÈMØ`eÍ&5\PIʵè(:±Uhv«‚xýbºgxYµ  Ð¦>ìþç?ÿ!BPy“SÓe×— qžÕ³MÀ•´‘N Í-öåOÏÈ{󳻎âÅͦ(šg`ˆváÍo6ç›J!³Œ€¯–/Õ^è”UŽÃÊV+v8 Ã뛎B_àÅ+JG\IK±Ú‰[f•ðÌ´ Pê®Ó$ÑxG}^Û )TMê–bx{#ŠÆ7ÙUtŽÉ’â•à§ UŒÙ™ª•ªK^ $â¥+F“JS¬—eüÆÆA– ä1ù&—µäeåÝ•Ѯ䯇 Ðs-&O­mÖ­×[KÞ„jWâºztzÐø¢¡ÉqÞ}/¶¾F7vK%º4¶íhAm‚MÂ+aF+)k)ØÆ©…óhöØ hbxZókwØ`ûD,U9ÁTÓ*L6A  ƒ ±®»¾LŠE6-©h¾èÿÓŸþtF¡Gÿý}˜&©–DTñpjpÞ{ÀßÿþwEü£F¹©±”dᬾ»]Ûf©h6h©êÒxÜB †GÊüìÎQÒᔵԨ­y ]wÊ‚¼ ‚9ÅYú~·AœÂÖM›œÈJ\JÊO”mËíÑRS)¡ÀíQŒã›÷ØßȾüQK°CÐ1©6bYyjj6©…X ®œEn6/RHL¸ÙÔBð+©‘XvXž-=˜ ZÒIJœˆ«Ð$p æÄ5ªp„ƒ¥o)`Ñ—üãkà‚‹{Èh|:ÚµÁ¹š¬)y¹æˆ$‹S¥öIHÁ‘yZ<Ü HsäeëRÓ6£ ŸOV6šòbK –MÀʦ#®àlìù:§Ìzš ´«*O¹ZžY´‹RJ’Hµ,@R2ð8ÿjFÊ^‡=ñ}Im9©¿ô •3Ï}ï…‡Ù… ^;{È –ødMk)æñÃóÈ…ó(OAm @ÙbxŲφ^–/ÃëÒ_Çã0%̹),„…ðõj/á!—Ìqk4¤rÞ~ñYÕTuÉ;(_JøjÞR9šZâ‚bK'ö"®/ŽÃ‘ú÷¿ÿí» ä»ì—1N±…uifjJà5­¼Ë¡‹lðÕJ)d`ÊÕZ2)"jÅ’,K¹Â:¦OÈ3üRø@K§$Hm‡£µ/>ü ÙA‘¢™ŽH­¦:ÊšvYeyL¬{ÕcÆàKYús[4ÈæÞóá#ñŠB})xY»Ó,‰Cø˜‚æYÓ«è|r2fd“ xx›õÚDPUkU)²ã@šA 5K§¦µj)P$R¹FZO-¯°MñøAAÀpÄp »Rð ùó®hܨbl¦YZb$K-@„Lf©S¸YeÙäúC ©4 †¨R›ŽF ­€o˜Jp,I¥#`RÍÖ5ƒÂZ§Z± ©¥L­%ZãM'‘¼í÷óÚ@‚Ôú½¨•{ý¾‹Ñ^â¤ú¤ï)&@0 ¼1xï”ÂÅ›¿K[•Jd5#yb¶5L ²é#Ðl§–Ê-mÍ£áå;)æc Ï_^]"på ™8¼•ÀcvÑÝ‹?…汄«õVêÑÿò¨¢ãS?CÀ¬]-ò—ê)ŸÐ9 êâ§Ï?UÄãÛÝ A &hGš¦Ó±ˆCôdjeÕº¸œÈD" uMê(h#øl˶)U¶Ï1À4V£˜NÕ·.á?zOï"nBU0'£\ß@|ཀྵýZöU[‰1^Þ׿›Ç ®¸BÊ5˜§^5R[ÀK!01ë¸móž‚{ÉD3ØRüvZ|ØFâÜ·¼QM˜¾òð—.ÉbÊŠËn©p&ëÞ@c@°dÇãLD¬0òyca.‰µfL [ü ^·øîT “%'Àç5k¦R–|jÅ–MY;LËt¶%ü@YÖ²– ù f”áîuq½²p ÄlD6j#U¾Öøâ–éÜ[+—âK¹w}Ì÷õ¿©7¦»[9k°>ïW®—yŠ›¼! šÞ±7Âfó€Àd8¼«Ù q:®&W(Àᯢó¦ïQèk–ºß·€ï³¶_öÖQ >YP µÝ$@ž&ZËÞÂùmD–MJܨ ãÝèeßûªþÍÀ³Kæ×§-"Í#èM«Öh÷€”kÇ*ÿÎûà©ÊÙïr òxðóÍ¿T»ÃWØe2XÛOjû dÝ*…w…+yÀeµëú¶k ·|ù&­á¿ôÎÙ/WÔʶÛgC€–í®ñòv±™Û‘kÑJ¼p\â/û¾€J¼Q&¢Ýøý6®J—& ¸ ôX6íÄ-W‚ÐÒØ4‘uÉ B».–²TÒ²CHm²•ðpdÊRæéº+´d‚ q¢-%«¼í 1 y&…€,Èò:öܨu æãY¿*›5 ÛÀÓ(f¦u¤™T»Ò¾Ú ¥bR¨Y¹¾J¤,™@¶.8Í®Ãâ 6À™æÚ$…::Y»½¸ÇÉÖ=åðâBj­#PI}¥,)[ž6ÏCà>@õyßcw)øsß{ry9yô·»)Ñ«mŠ©Ádw‰Ôö« ›ÍH=g¥ Ê!“ª¤¥*AY´=škê#öwŸÅ ì¯à=1ëNd»3©L—–º7Ûbûj;Û”1dÑRPk)ö½°þÎù)|þ­÷!Rí·ŽÏ·›''úÌâÙäÁ|cD<7=÷™0ª3Íó–B÷T*æ[šÙÁš¡{³cL§Á¡V ¼ÝIi*nøfDóÁÜ£Öw>ßÍß¿ûä¥ãºàhÁÓIJ_„@4 „xÛ4¼¥GŒÐœ<‘hJ”ã4€y|D¶Ì»Mâ$Ãy‚‰¤Ï7CR²Ñà5å×EŠI9ašþ}“?‡¿·»Ç¾)òÎí<•˜ˆBÒë¨ÖZÔ"F7¹AüðD,ÅLÌÐ0_;KO!—…0)ñd”uà;YK¿û½—Tø¥÷Ø¥¦0e½8XK:ô²ˆÜ{v½:œâz¹å¼šŠß{Aúò‡TLû¢Æ,íE#²ˆ‘rÀhZå§ò:·JÆT \/Ëé¤ìâ(ÔQVáøÍð»¿QuW•š YHK1뎅4CˆeAB ©{²Ô€á5ÝrLc<¾"èNUäk©ÀRüRo 磭PÌÚP×Rýh‚µäc¦¼ÖÀJ0)•Ó´¬K§C‰Ã׿ûµ.ª˜˜Å„ðÈáu»§=ô}ä÷¬ŒoúeÜsß—æ}u¬0‚)«å Ûý-¶G)K,hw–}üÁO¶±éجBâíZ Ťøº×Ѧü n7Ã}/˜‹^xªlÜR¶¾‚¤øâ7Œ€¾’|K›ê6ÐNŠ5ÉD,=Ìóû2Á†éѦÐ~iòú¶TÛlÔ˜%/…Æ‹ ^­®ÄÒûœ©¾üZÜÛƒ7üö¢JP‹ƒ“JÖ6;yAæJÝg@c Yà­ÚqLÅàô âÔZ•eÔ”°eµF³_^\;OWçGóžçV®0e‘ÌéR¸ý¦AV ]c^9³TGÐÇŽg@дÿS ¤(0MñéCRkH3Xʲk_7Ìø1ï“T¢E…D2cظ­¡­‹>&D‰,}ËD6Ccç•„ãLª–@R‚,AµõšrLM†Gà™ZüjÓVx~Í ²6+oÉ7ÓH¨;â@Ë8jM“ÂbünAƒÞG‰ )K05A† U–§ß)‡ãÔºS¹‰«Z€o-òÕ!†Lü4»J bмËì6í«žn¾ho¼†—§•Ï,íÔ<R: to³üËÈâÄ7€ Û¨-@zWç›VÐ<&·ÔH-<Aí"ää3¯ÝUþâ5õÔóXLÁ«]€£vR; lûÅÙÀñÅøh²âvÚ$]e²¾î÷xªÑæÁñ9ÔÓ¾C#2)Áª KjÚûeãE躈~à9î'´JìÚÕt&¬u}Û„&\ëåJ€˜CÒĘ­eC¢ií³‚l„|Ì {àz‰ð ´à ^fM¥Ð˜”XÊ}~ùƒìØé»ëR¸”NS휛ÙÚ£@;WªF˜b†PA—ÂÿüË—Þ Š~÷¿ÖÊYRuO_w¶” ¬¾‚R!nK¦üT^`øÄY"Ħv'™F@å}H3YYåÝ !È@ähb‚ÈWøèý|ÑM§lUJUÎCdÅ.–eMyÊ1Ï,HÌf$¶œ Ü2ÐR Ò&ùÔ˜ë?DV@SyF’”—VUu‰ ‡ÏàÀd뮊ƒ‹•㴌ѴZ1NxRk¤áh]›CÈŽYìÉè×S¿EþÝ”xâ»M}brÔΘü‚::FM{ô˜S-Z/Àì´S°5w?²§’V-„~q%jÚQÝ1µØ×Ÿÿüç=éd聯¿‘÷ìë‰I2Ai‰Ó1j-¸g£µGx)`¸÷ÔÆ«c|ðÿýÝÓsÙ#X-~[¨ÄR K‚¬Á Fê("ðõ2³3ZAœô}Ñï"ÊZ²í±.<‚@/AÇÒ3Q횢¹pJp´»5•TØëHœ²¬ÂbÁ† ,[G÷YHÃèHÓ¹µ )„@µŸ?v=ýýèC„¡©œm³1KÙRˆØ$(VÏ{úýZ?Yÿó¿îvW¤o\•·Íƒ5Àd5í!b§½+lxA;jrÍÂÛ¿öáZ°µM™N¯£ÚYÞS@K38&f÷¦øk*ƹ÷µD6p 4<$µb©©Aè\Ýo]‘Mù¹/±ñ:Ž–µ¯GžDZ<~õüÊï·2^6¾x3‰»*âõM P9Ž˜¡ÅLGÀÇiK4ˆ‹/§ãXº™¼¤=€àȵÈÔ1Ý@žûnÐ^]²ïÍ´úýTñ}0…dݼTëeíXK#u§ÖNª@ŽQ/úãALœO¤¥Ý»lü ¨—OÙ¾d—úÒ|õ+_gÕ< ÑTñÆ(¦#î¨ùpL´úŠwDa‡àü‡•ûXêg¸åÝÌð¯ýË;k§Ú ÊuÚ¯!-¾‘ij”Øb%uQløb¢mï}§^‘Óç‘+„w1X‰ÀËdYKÊ †ž¸ÛfœÖZÐ<âgµKh6"NÞÓÿÃïܽ÷{PÈê• Žlâ²Íl/zñ¹áö+…‰/¸êO:wàsêwÿKÇ¡j;«<µÄùšbÊÖŽ"PSŠB§cÙk$°ö˜)…ʼn„ð ëÅ[VÅ'¢J #[IœhjÇ–‚rA]ÜKÝNNòÎQØ`]J©æ³z †G†´e-R†ãÀ_µ¨}›o3p&æÕ$$°Ÿ–µ¬ÄL½¢AtR… fÕö" 0Å4«­ËÊ¥†§À3-ª*ÕÌ©Ñw/:^ìeÄÑæLè+þFªü'峉§žS‰ÔeOa ©é7C‚Û;‚“¬×}§Í©VVUœö懓Bhwb…”§©…X¡×Þ›_>ôùì_»JiÎâûõmø5tíÚ š €b¶ä‘}åòåÇRÏ œƒl˜üý-; ‚pKÓ¢¸^Û>Ž^[âÔ.hZ{„㸲@DJ@9&Bg«»˜&_S§«R˜&¤ñxµíhú…8‰‡7>«¼Q5µlûM›ÄYiœpFÁ‡hçÜxï½Bߺ츶)Ý鸅´€oHƒ¨RåYK|Ãøðá•ø~†²þ‰F¿„P•¬@Šg©ñZ 4â5í…N`÷ÒË„ÈÔ‚Q®*oI -&šÀe’b–W8ÄQ ©Ç§°«Ö?qŸºN³ë¬ ‘SC®u OÇT¹-@R¬‘{;sIËÕÉRhA©!vØf¶74 Ú¤Ó’Ie@U¤Úyq * oÉðźÐd–½QS“•аxÂÉâ¨0S"Ž&+€(‰†Âkäûüe14Ÿ‘}äïÛd](¯‘ µðz«;‡²÷‰Zk×O!˜b´{GR™£¸öq6BD­%fOÿ@²RÑ@ȪÀô~íƒvå÷Ž‹=s}ö×hUR4›¤×Oš•^Ö.ð™Öu/ÛfÅRh–²• ¥¯¡¾üë#o«žþ  ¯*e¸¦¦b‰Óo×ÉZbê(H /Õ´RÉF–"‹ Ì7³ZPkÌâ)Ö´ù²È–b†€|#RÇÎCô­uËy:¹kYª£¨¯%œ+€0UŽzø÷ô÷9@ycW55vøˆ†¯oâªà‰àþK?ùù)ÄíªêÚЯ2½´àw'ˆY}šØk-©OCKdãÉò¶† DÈ+¸sɆ B)K­ÅíšßkßRÇf³;²L 0œ·LydjðÈRcB´æ!8ÝÕF^JPÓ¦:¯(6FiK* ÂGk²æn©„Ã䓇cÚ§)'‚P#—mÓã¯Y%‚®®¬eÖ -ì_@AÉËeÆI­Á”«e…È>úà¿‹÷hðÍÿxôû«þDòšj-®—˜rߟFHL ç` K¸÷j¶oòRâm\`ïÈ Ï#·Ô……+ÑÚRN:p¥·7€8ßÍ3×÷-øÈhúêNÍÒ^:UU) pÚoRp{é†nþõÈ6| æ_þòo“¿Oâeïk];˜½óéÒ ¦ÓTbH}‡Çi#ª˜1â‹ÑÌ¿r¬]„&ŠS«‚O$ZÌ w{ëOßñªðª21Cc!ÍÜEo<%Aâ _¥Ç•­0ˆ›Ü“wœ7ýä>Àøº†ÕÅ.zõÁñáëÛ} 1a啸)ÄTü. Ó—?ínœ`G'›Úúµ֔µ…&‰o›³ŸóÄà&,x@IDATRá1«B£ ©E]&‚Â÷ps:º» hã7yãñLX KíðY3 LÅÓDfí^œˆrA ¼T>qLàj籂¡e<éHMÖ% ä'‡Ì,öϧ¬"Vž_y"-:‚X 딊æ4¶O¾KBg²d)Ÿ¤$q4øzÁõ’zúøiô÷¯žSxñ>¿ûÔkÃNS …c¤¼F üе¢¬Ù”ˆ•0ÝÍ1Zˆ,œDV GÐmaɶ)qí Ò‡\ÝÎ-âÑÿþ[W?ÐøK;Ýé'¸F¤Ì™`óXÇì`Ë*qJÈL8ŽÙŠ£Aú[O[ ¹{/{oJˆLœš*¦OÈC/ /•~…bÊá)⫲;àﻲ£MaUõ‚ãðeõbâ®)B8_\•¥€gáËR+o éCšß0^†"Ëf÷¹8G÷'£ã @Oƶ?z‡l‰Ð ˆ;aKƒtâf0§Ø–‡ñßÿº?|¹ùàãF™ˆˆµ»£y€ëÛiï‚6‚€I!aÈvh´kÀ3¹ªm3~ ÖRhÖS˜l RzcJAX¼=v,¥zÑUòÞûç G9ñôÛxˆ.)7˜Í2|xòZÃe[¦)쬌gY bÖF0 Š‘ò{*9S4²¼Fõ¢ÀZÂÍÉ,[n 1Fè½ÄK³ÑgM ¼ôÎ!€RÀưdZè *·›™¸ÿ‡Õ÷ïs¾Þñ²OD¡ÅÑ^ô‰ÌÀZ˜’!còâ4ádÚˆe_¸=«ý/M_ú{+J¿òu/X_£©¾êÛ’ˆ ,Æ ¤ Ph0^‰%#ÛŽê«$Až>‚Ç'A¸`žŽZÙúò/¥œ!Œ¯¶ó‘6Rä)DN³ÖbœtdÅd£‰¬Àˆÿ£9|O/“‰¤ KçPkʤÌiHÁ}|8«D€Ðx/ÕÿûT˜nÈ·B×¥÷NK-ê΋‘™+,െðøh=…IË&+Ë -yq" ª…ŒƒŸ/°Èñ›AÇ®K}K‰Ì0y 4‰íÐd8:‰!Åjí\ìBž”%Ÿ‡äÛ¹eG&«œÉ2T^ÐóT°s‰i_Ê ^´> ½ bf¾Íðè÷ª¨u`»hkûêÈ€½[`Ú—¦˜D•,$5±œ¾[SpTžÛl§+Oj:wf‚Ê‘{µô:î9UöwùënÔ»r½´ØH{åtª÷³¥l™~%-‹É¶¿Šø} -|óã½VJÌ^IFÂ[ ¸.|YAÓ¢µ§!fq’ I MI41‚Ö¼8ñÚá@¤4u‚æL™W‘%U…JRÆ¿T éWÎWt©Aš\!¾¥”˜Çor`3·Œàç?ÁUñÎ)ñ»_j¼š šM™¬îRðHS,µ mjåµzãÿðuçGm/:Ÿ]Ú…ÊY[»ï¡”^õµÄQ%(V% ©ª9»!. ZµíBʲcçãâ÷ì ´^}Îå3A±¦ªZòJš_@¹\aâ–¥ô²ì2ýbKU‘‹Ûx)Ó|±ŒOøë–¤kŸhT~· )G†Ü1íX¾çUÓÁ‡[º«:q1åÊÓ=è@| Jp0» â–ø::ʲ¶¤*ƒ¤ oGá–þöÑßÀЩä§à;?„6ÏIÑ´(7$Ñ’rípd;¨È#(il…ôc+WW ‡ðL–¯uW$Íð{vÃøÚ×gÿ÷ß·º"~ëkxµL@0Ó«©Ú ¦ÆèüÏXÏ'òöt×6? dí1Á”ú¶Ä1$P)h0Kd¯Ê-á @ü£ùÔå7@ 3µ{-@,gZˆ;À^5ÄhÞT6‚cHqGxg"Èò‰TÂ×HZ¸XÀO<¤ÃQBjq³)3:Ë ’g²{W’¸À²¸ãEkŒöRŒÆ"\M·qúe#œ0Ms/–n, XKû$ç¬ËÞ{È:”¥Ô6+¹ Zœu7 Zí^Rvk¡°1H xµ § ®uÙþÊSü£ù¢Ãóˆ'ÅL¨@G1_wý®MK1s¯×W¼^b`8q9™XmÖ.øåvq!DV’¾eM:&ô©ßØt¥JýîÑú×^ô)0µhv×ù‹b:í…—*QÎÇy?ZÏ‘”ËR0Ï—?‹ £¿ªjþæÛ©‘H…`‘ÅFÒBÖaò=ïTµ©øÒÄäÕBHAêHÙ=†ì:*†·GUÍÐ’·l$‹¼BAU|š8b],~»À,¥‘ÁàM`‘Ñ,‰XV"HSàÀ•;ð7ÿÜmæü}în­‰¡lB Ô]y­‚¬X¡X-|iƒëøe Öûó7­kÁ·Ô‡ì²Ãl‰à xc+‘R%åÀÛ\‹^ ©†¯PŒ– Í,“j’8øu ä#²eW3o™¦a "çK¥Ãk ‘Òˆo pˆOs´‚uo‰3qåãÖ¯qbÉjÖ|âÚè'Óù"Ï€ÅJÌÇK(¼A› ¡Q"O?)&eÉ‹+ÔÑ`²¼*œÈ–|L±^> ûÛß„ZþhþÒ÷jj¿tš³Žñ™¦îìÌt{–¥OS9'5"ºðJøKà\Ìhæùîgd§í³µn˜”ë(kM \ ¹| © ÂdŦRJLÊì´¾ÁpV( Š Œaâv§¤rRqàe›6¾\l†Ž«ñ µ+«°e¸%k›!ân`8DSÒ䑎.1¥XËÏ¿üñý›r-š–¦X k#À,q/+ÃTÒl+q«íÚù}Û‡êÕçfPŦi;–!½ `±×T B»nþÈÀîÐZÚŽ’â]¸! L!¦-§§Ï€îÈ •X•yˆð–p½œf¯`„Ä+‡àó)ð–“¢ Τ¢%¢<&Ùõ]ŒÆ€ qع×õn¬åÒ•Žjܺ†´[HK¦¶*±ÔŸ_’¦lŽ˜[TKvú,áuoâ Ýdp²óU5öíé㛇O~ ¦ÓŸŸëbx]´fµ#(ÈcŠ÷ö¦#œgø²ÚT3KùÙ¶©&5ñ”½£ ‹Ã‹Vd–‘]ïšê¨)Ä׬öûþéßW.i¤Æ§“¾î)7-qËŽåÞW‰¥¬€Zäneï»ïŸþþü´z17OjÚQãÛ5–~J ”( ÉV­¥y´8õ×HJl„TF?!ÈðD”ˆ/³©q€-Ë¢I+ŒÂ+Ï£%“‡l›U…”"¥ šÜ~Û²¬Tw‚À2¤.¾rñŒÿh~ÑÕïšéBG•€¬Q5åÝŸ–!hæóbr@±!ÅnÈ¿üñqÄûP[Ð.ʤº?ÝÕ@)ÏèKu·WÈ7›”Ç’çžHâ²DД@,Óçm¹ejh›Ê9eÙZ$ QkªRiâxb4¿3ZóÔ]ƒDHM# Ö|% 꾪‚1 ”ãÅÛ+èº>¶ b¤S7¢ú–:YÖÉ–MV©  h¹Q ⤚ ”-Ñç~” ׆ÅɶD#Ë[òtXµ‚f¨Ë•9ÿÒêÇoBjçP|Ñß'Ø`›³F²k½Ì ab†ßT-Jˆm*þÈ9Zg•8Ð’ïVÁ~|ú«òS¶Zª¦™,D€ÀLUa®Âµ›Ç ÖÅmd„ ¬„š§ÿw?‹¨òj÷ôox^Çæ!a‰ëf(ÐBªQÅM«0 QŽœÇ2ý&¼"[öò°L–ZB"é…°Dx4'¤FÀƭ˜²Ñz\R«á4¼˜oi64±Ç“^g‚k™”KŸ{>|ìîËÊ4»‚ zݵ£æG«°—a%ºÃ»%®‰ÎF¼¯øá»Éi¾1ä~ò®‹§'„‘r2@OOå–ÈYoªÎÙ² k'5\¹ÔÍõª ެ˜ ’˜"µ(U,kï+/UßÅ‚ YŠW«KšjY·™,æ†×AÀôâS@f|0þE|è+” 9ìç©öÎ?žæØÂà›[&ÖÌ h²C”ìÓ­MånÍÆÂ‡#ðu‹Ñêk)ˆ l«‚:¦VmÄlÛ)~ç(Vd}ó Õò÷ÑÃïByäö™šùù&&·He¼-›“0æøð![ ;R‚ŒBå&1©;P¹WÈ'ïv~Êñmoå¤xCR¨Kj–Z‹ó-ñ!5퉥x“cR³lT?¿{7Âï{Q¥„Ŭ¦‚µè¬"_”é*~µ‚&”ݲrHÊ8£UÇA0¿¸Ã‘Š» bÂÀºä1Ã-'(Îð=ßcZ6@±× Zµr{¯W;­ ™uÂÎ\J•|-à_ý×·ßy…>þËÖzÔ2‚ᎅ>ñ)-Òl€a$œ©ù×'~ùãžônÑðîd-ˆðuÔh±.æa&± ASIY+)¶TØI³‘/ÅŠiÆ· HLYšÕjS;  ZŠ)X6vYµ mŠ”¬8MY4U–:Wi)‹/K9}xÑ, xúðhªø•Èvn˜²ç[Ž¢êKW0/H׸¦“Çlµ#CJa6%¹xYˆ­N9…ÊU,HG•F–Àð@Ÿ…ýÁ³‹üÆûä£G‰Ú.Rë¥Å4¦ÝöhyMqnÄ{Õâ²WÝã±¢VS×G• t‘ºŸ Â38‹€BÜ~¿û¦¥-ämÖ€¸ù)PKx_-5‚×ÑÉ„ðLÓqº}cv‡ùÁß<Ã¥îæGa傳}âí-вÇ"DœTMŒo’JÄhm¡Ô kœÅɧfr|#)‰ Dàá8‘yKV f±eȼTRÖY‹é㨂["ó §€o 8ÈÝ3ð!@æ±ûáo¼Ü ~êmŒæÏÓo§)u¡ Œl¹-Íìfæq6°ñ>ü%„ú‹»]åNƒà¦7ÛCÛ0âîN)SñRJðy1‚Û® Z>$®÷öø˜†Ì´ŠÈªˆXÈRóņ‰SkKAžˆWš]Ò÷æöÕ¿|³€8Aˆ^‚ÆÎO9~Ó–j žÛ! ÷½?p"÷ÀK‘j ¾êË0k—>¤(˜Î†DÈ7†*~KY ,AeÄo°(hé¨ðGâªí(©!ÕºÒO¶ci7ORÊë§ÁB¤ä ¨™³îÝ~éÐTR•™Cöƒï‡ùã×­¾ ¼Z=."A"Ʀc˜zY:zµwx4ŽÀ IªaÒñnv Ë—^•ŸBîoöÔz€´q]phV®…À ›Á’BWMŒÐ¹XÖ2WÍG¥†lZ½p^ήDÓ6 ±ú<2qR8D€‰àdÀî"4ä{‰”ve²rdK |Lˆ°Èøb„R@K`OMJÓR¼ Ò„°@Qk*.›?OO 9k¾ã°$ºÛyÅRuÒ ß^P¹ù¦Ö)l?t Èh6É#ÌZ&‹)ÚÜ÷v˜—}LOÿ? «õß?ð@ØŽFÛ$#¸Qõm׎Ž©¤¥XP6¼[ Yj?h—mG|´GËë²!W¥»óé  ¹óǤæoì~|¥aú«Ç4AñLù6kúM gVpiž{•ydM(ûþ³¿/ |ùƒ™7I‡|a;x‚ÑèCˆ[Šu4- lR²€.âÔjê(¤,™,Í&‰¼*K)ÞÝE¹F®šÃ,¥Šr÷6‚ÂÑuQ.¼Ëª‚ÏÓaDY ÖÞx¥ð¥xÙ4•÷ÙŽéNøñ£€BæØ=Ù®-Ì’)²b3ç6ÌêÅg²•ËvpJ,¯Vïœ_¼¹%0UѱS± ÛUÀ€ŽÂ±#tªJÄ&Ü´·£˜DLÈt„d§Áó&Y ¥)ZH%hTâVSKä.ñ=% 'Lgó¸¸UA6FÙø|š!§ßuK'È[òÛ¾^æ´tɺšZ0äe-Åçák,žÚæ•1K<El•§ìúÜ­DP')qRb%© jŒ¼ q‘I;Lˆ,eA‹{y]ÊÆÓÄqÇøá×'Pñ{Ãô½?eçUßùPBÍ—?>Ú¾òö²'£eš÷&×óËbíXÃÀ»‚šJ”‹)$¢“w7";Û 1+ÙŽÔºc=¯T!Ä/'.0?‡Õ®T(f»¾ø8”•ããÔº1Rè0¥Ô ŠkÍ«…Ðé%e‰,Á" épªâ5:/oéw–Òj V\J6\“åñy[²ÔÉ’‡ «·%…ÆÖ×çGÙ6 °ª¤Ò©o)ÌÊ©eð@K{ÓË/B+|R¾ø_SùÐá¶«MˆaPS«e©5…kÁ‡+ï·Iª-ך ¤í·ËîNŸŒÄÞ þùÏÚxjý\Y£t¤ô#3)>ÁĪòeÚEùÖ¹(ö‹ŸÚf3¶˜/%«©F–´xKÇ‚#^4–šr)U¾ùyóôGó„–Ž e:•“rul¾FóÀÆÃ'ÂoR‘)ÄÁÓ.T15C«¯I£a"dJàÅpL3ëËÄj¥V´äw†Êèè!ýŽŒ#¨ ,5M"òibº~ùãÇAUjY½,ë1Ì•9ʲÌvïh#²æéÖm0ˆ10Ý–ü¶ð]à (“tõª;5/Êaén†hFe›BËpøR|¦û4±ZLûJ?KL1¿X€®K·„N̆§Ùit2øp>©‘“ad› b™Ž€¾.ÌDê%[‰¥˜`§¡v"MÁ!ÒüéX*×(µÓª†œ¥€E’bQyx BpZâÄo&{!M4‡NA`éŠ2UJR>]/ƒ0… «D²v@|M½>ùêß⥓>ñ&´$¨£Ãê Iiç|´€„!Ë2l rf<#^†ãs‡½­|Xf²Ñ.™_ïCZÐìlõR…ŒÙ1Â}Èêå—þ—ßo¹µ€  B-eÞl!mDlË׽Ѳr8k(ûæ/>Ìà§AûU¥¯?5Áé·qåš½ÄL ‚#æÅh•8I;uìüR‘[Æ×ËØÚ Ðpœ°l´J¤åð¥&Ra3Ьê’?Gª² gY­,Á’·$®Q- ÙpänT§AÿÃïÜÝ>w'K°]v¿‰ëØÄ lͯ¯™U¡5¶¬¥¿@ýðË¿”Jª1Ú5â=Ê;£ê•8ÏTÕ—·4ïÓd±ùZ"ËB ÂJiQ¢5G, gá@Y1f4jÞÃøfF®¯_Œ†ˆ.–²Éò⬑ÐîCY‚ 3| Ú+y¾ ‹jÈW…ì ¾1àÈ繆ã¾1±C—ÅÆCHZÐ~ªb¢5zÒ–pq`R‰ïNªˆƒO– ˜òC¤ ÙÆh0µp1åOþÝ£3r÷kD‡rÅ6EŠF¨/°ÖR (›)lŒ¥B,U%ë¶0"{ïñèGð‹Š]0úMÐEÂG #€«•ªîžþtì÷“¾Ÿuj¦HWÈ(ÃuäõbZä¥ð-+l6~7LYô¯Ïzùaþn^çžþÈj¾KÌÄõj_ OwBR²®$J¢Á‘I#$eS òLª¦ÉB”„×¢¥,<‘–1ùu!(v˜ÅÄT¥|i O nøDÄã×^-/f8R”;ŠÚ©‚»ùü4€©Ö-±ÂI ”gv„о€ú6/ké î¸g‰øNòÃ/¼<=Û5YçÜQL\ÊÌ]ZëÆ€ d wû‘BxfΑ tn8FÕ…²˜!´øº‘²äÅñ-é$Ÿ”ZF§îâô70…ð 7þ†”ª/Z}щ¤l‰–/¥\kxãMŸT- RãÙyýûŸu0•GÙâái•â‘)´Äi{;ÙªdÍ$fâU”ñK…;\¼Û‘x%m©TóðJ"ð~øýñ€ïï޴КÔ6Þ´©Ýe#G6†@Ö$dq¾* Zq%Rðnqx*ðòR¡S­`‚|/°ZàXy&ké¿ì‰}û¿þÄÛ/ú¤ëÂw›n9ÍögÀÞ~m Þx–AŸýß|â3@ï¸D”·M-:õ*è*§,&n³5mŒhŽn)ÆáÒxb¸ÉÅ Æ D‹­ªÅ8!+©E:RL;ƒA˜˜Zd)äøñ,wõrYrY­™ÀŽœ †QÐÂãR`Ù™Adži×Ãk×RìVO¡Ù(œ7ꔫâwÉÎp%ƱM¾ â Œ!HJ ­vb½ ˜ò¶P–ψlGÔbUɦ\_ž©åqªšÇ¹’¤ìESÖ´Wé£gˆå£’ TNY±²bmà–zÔ¾ë$ņK¹ë€ˆ¸ºy…®.fåWÝã¶£,«E)fé´+|8‘ðúÖ15ÿ÷3 üK#Òï¾Rk;˜4‰ j·¥Ù,5øî’&Ù¦¤ÑèˆMâ©-`Æ O¦÷!KåÍŒfÉÜ:¼sãeµã›¡mòÈŸüâWU_ýwn LÜN ÌšÎ4…”ÔÂ,CíËsçÍ×Pî“þ‘B²‰‹Ù%yŽ"e)R†d÷.‘q4]aä¤Â!@qÊö«°¸Ú {s­¤½LÙRÖáII°;Ÿòö‚À,«âY­1UT8Š•,ˆì–`R÷]‚tí†WKÖÇ%§ý[£ï÷ðbÔ½ 4¢ïÆ#ènô8C†S`8–¬8¾%²?Áx;Â#é§_K*dMR¢†§/èÖm0Hüfà[º^©ñDÐÌ“Ð2PïЧ,°…hªÂŒ~­‰Ãyµ,°­:A^` qL^9Š™”ZžYÂ3…pþb×ð)K™ç^hÚ8ñ‰l`4çI_-Óýñ|‘À‘6=’\ÒMÃ[2¸¸ÉÜ N^§tòš–;qH“ ’­ZÊüt‰H|Yjb )ò‡ÿ>ú¤Ð0¼¦G§yxÊ2D ;œŽ òRö% p÷.-(Ü2-ìÔÅSIËRa£@”ð+§É”óe‹)‡ –Єwë dYh2í\Ÿ‰jýé=~"æ7¤˜²XS8o gÝCI¸ØHhÓéLçÙDL›”Ó§—¥Ãˆ@dY¸‚À38¢——ú'ßtùIßÏ:ª”׫a yº^?^˜ª­í`v×êëHËLP ‡xÇ}ÿ»¾þÐv/•öÂw{t#¶Y‚`RÝýbLYŒ„`)nT4ÖüIŠ&Dþ}B)[vé[Š!øµCN­!ã#Ü·X#ßfǬ’™lŸªât2bµ1Ÿü™“!ûê_­ÉuTn¤u÷|g¶#ˆ#PÒ…6•”Ö¯”÷Üø{àíÇçÍ~{¡¼ÓK§£Û0Ú‰yç 06¹”%k#z‰*€°G† T~ ‚@œ÷².–—ÌCÍ2©š¦Ï¯WÜi6å¨ãT+fÔõrMmб[†óÅ-qš¹§¹+Òð”ã$«Ðaþ”@ðÞèôôב>eAR4;ŠZèÛ;Y7@pÚ€%Òö“²µÿÛsî _þP`f.àÉ&Ø9ˆe)Ž-Ö_¶óYÐrç¶áíE-Á»¬F 0\ÀÎoç,Vµ½p,ïdñôSoû2B­Å‚²|cGÀ ·d÷FðûÌRÍ–fÌ.G³MJ)å]ÓbµÑ7™Åiø|Xe‘ªìùA\ñN§e"ø/áÂKñ‰ àÆ2"D|º>†hKÀ‚¶!n¹Žføä5àC±B¤pc4€Žm¤Ç%NSaŠ;C¾l¶ÁxƒQ&Åã2xµMˆ_Ðü–q“4$Ž¥B&ÐÝ$Ÿü¿j(ìo«Uµ[—ºj*€èѱl„ MÕ„@ô<ý·„¼Xÿ}=špR´ `ÙÓo<)MÑ,2¿Ö Å:Ži¾±·”b)”µT®î”!ø‚-ð!yK%$¶…®N…Ù»VbÉ'Þ[ÖBÕ=°4žB|R|ˆ#¥P*‘öËûòç“ÆðÕ LŠŽ£Xk]î†ÏK)¡ÙZnƒ–ÆhZñóñÙÀíT!eú–RÆKÊRg6ËšD_ˆì•9_,Ç·¤CaL|4, ‡$'˜É^ô³åÞÓTÒÞ0é'ÒR­X‰bÜ5%%–ªoUZЄ¦S²Žp[«ªîp­k‡ ¾ËâGБÃìŽHApøDÒÑúñYk[B¼e•Reá;ÜÍ„,àøNªÍœÊk¦#zu±¬K4Ë6`·+‰ÌK±Ž¬ªŽ ©ßÔöÇ?ø•¸!ÏXÏ·Vú½ÃÛ”©´À‰Æ‡Ü¢ñ”·ýÄ[òš†‹•ËÖô(>íìêùˆAÓ±ByyÊZzý¸M4[m§÷mŠ;aA1O¶vêÓÊ•9~¾LVÌwJ‰;Oÿ ðÅúꟂrü¤ ÜŽÀîœðäÁusëG†·÷ÄeÓÁ3ÃAุrqÌ.¨%Õ"VK³¸eµ!õªyWJ nS|âRÚYÖÙ˜ œ-éwžbG¤ Î3}âG(FÀt! â÷æË?UèöN“,¤+b’t LŠÝ5˜h];©Æ†0¿òáÿeŒéSRzµ_],/sÌÖdyú<Bô…`vuWžä }=cV¨¤¬^êÎW„˜¤ÊòJd pdãˆ;®>œ­ÄljïV–§ƒF¤íã4A&ÖZ0~„Iµ¯Ã~~ÖéÜ2üN¦ãâѽ9¹”¤Úüñ‰X ƒ²Ø–xâ Ä- d¥Ä_SË´4%‚¸xËKØay(¯œ¾ÂZ ÝÅ©i»}¿/}ùÓ)¬°@¼@<d³1Y:–½TîÈ•DÃÁ4'Ïj-ËÄ É#¨BPÇ–YËI©c6ïoœÞüº5)Þ÷ >a]#<¶©)œ`MyÐóRíº€²ýž°ÍZ–²ÄôÐyóëå^äd1k*PáÅDR³kÊf8¤c`6%# àª:ŠyF¢|ò».ûC,“k±-S†èE°#² ÜüíQ‰î¥p˜¥ñˆ;‡÷¿ R•ùů—áý¸Ú¦^i¢idk†ì2AdÃqRj9~Cv¤¼—AU Y¶’Ú!À+\ ý&løŽ Δ(ïÚY´Dƒ$Õ„º tMS®ÓR N#Á›!Á4Åéä×N_ùèyCâˆ)'Û’DÌ«jS<9üñÁ¤fÍ-ÀSSÉÀ‡· T%`õXªK;jbÖNŠ™‰ÉâóâÑÛ¤.²Ï£;'ÍïgOwÌî†Óã:…l[3€˜¦`‡€Ð#¯¬BW´~Á² )ð!ˆ\=Ï=±lB`?s4OÙ½ð¾ê¥ö²©—¥Ú¾ðZ×¥³ÒTÐbäðÎYI÷\- T1Æû‡Ž/š}ÞìÚ8ejm9ñdy©p{M “bJBxÃTerA)¸ÁBT váp(´M—Ly3\ò}¸*34&P•Ï€™X_UtÄ |•©‚:ž²ç8µ­Â‰Ûšî¬©®ŠÓËHMÉèùXñË•»>û{RhNÝkªEC <—ïKœfC¨»¾í.â‹üMš³Mê÷ÁÓϦªׂÚ&¦@^£âðnEHèíð½:ÔÆ§†Æ«E(¥QâpÏUe‰@âAÓ…”Ç÷ÐØ‘{~j±Œ@D-œWk©Öa·qšùÅt†¡Ðò4»d»¥ã7³9ë"P” óhqÂÅðF=[²À`I—+WÖ–äRI7¯%¾˜EƤ\y©úÅHmŽdm‰Nƒ:& )|䤪E`á¼=£á¼1·N‚ž?I!¥êÎ+L$„ă~"pœÈãb¦)x<É­R=SÃH•Å)Æó"­äíª*[Ö²¹•+ä+Q‹ã"%‹É–íXn HwC÷ÙוּŒfó#×·*xAi)ú1ŦB”›Ÿ`"ã«Z/)qâ&øø_Õ^Ÿ‰ÇA&®Žo]¼àÃßx/u?ìX¡òmP âLkf#²hp^¢J RP–‚ÀÄß à÷{}ÃK6©NOL3)± ë+k©W €Ño:µSÂIJµ^ÞLLœ òÝÐ,UµëtøðZ‹[’Õ.2ŽBÈC(•È“­E5އcH÷ …Ê‚û¶«L9&¡œ2°Á¾ü©o©ï¼¿ó•`3¤Æ×Z‰ &±¬©¨ƒCjaI!Ðáû׈ŸüU‚ÿ ŽÌÒ®‰Ø8eA½´óÝbäm3¦ò¦m`ËDx1šAíûÎãDƱÄ'e˜zÉ2 ]„î.%h¥Ä ¿%Nf)Pkrq4ˆ B3‹ËÞïÛqÊnwN;òˆÆS`õ²Ü©b‰4¶^8fžBG£s^Š%,ºÒ]-8¯ [R¤¿‰Ydq8š%ß4Kƒ¦¡A;7‡{‹‚BL—Aö¨__£ã5"(àáõµ|cÉҤХ–7BíÐî›í@*—jÚö¢Ñé¨;ÛHh|)|– ¦”Ú¾I÷C±Ÿpe‘Yó#(,ö>ñþ;÷h~ŒèÖ[¦FD/š–æÏCŒ!Îp8ð{-Ùv„à‰ã;«z}émÄ;‘íBà0‘¬í·µ^Z`¤)__¡1VÞ¨ĉp—j§ø•Wˆ‰ƒÜ@1#Õf·_´Mjd#ãÔˆdã%N³y’EN¼¾ËZ2Lå|“`â+ 6C‚=v?üòLJîô;꺻 @w}éØŽx`S™5¶&Ëù†4Ÿ Ê"¼1cø½T7R-ÚAËóû¸ÓÆ#ÏcA;¦°Óh¤@´ôÅ6¨i8&K0¾F41lJÊRÊRʉ¥fyÇ-׎ƒ¬6–з\^qøFiy?D4X=’rÖ–‘¥ Ž\ ÇL@×ïp#ó‹ÃÒï2 Ÿ~?™r“8ÊßSæ™¬ŽøÍ Ú̲ì➪ X-¯6jŠRùJ(xú¿ÿ GÓ¿;s!ÚiW„Z“'˜¸”é"†ðª(Ôî¿r±”X¹˜áÛÔ…ŸÊ¤s¿Žªx­«RîèÒD¾Ëv½TɆ#ˆ™*…mAÓgX †×]š@/œ”Ñ0±oÿq~´þêß-a›ª/olæÇïD6ÿî S(©—€Ô6â«ÿ=©ß 㣉ŸBt¤I!ÿ²ñ•#°²`KÔ45R S0Ž¥x?÷PPëT ”ÈÖb§z_LY]6°xU”¥ Ί`Ýe•Ô4² ÷–Ž,¼Td1¥`©\*rRR Çl]AAà8`F!SÕÕ„˜µw8Â%|.1<¾çM ’²º1, ‡‰>Åîém¡–|؆ZËt·dbVUA^–0Úæ±j–‰ Þ)üÄMkDW.ÈŒZ_œô-kÁg²D€Ê+á :F¸¢*²>J÷]3øó Yåø)PX’ýð¿øæ³ÿìË< ÓÀz5R;m¤Çö®ÿ‘m#=qÄ!¼?¼ÿůÏ_dUni~“Ô.ß<|í0Ùš:„õ”BüðÈ B,CâÀ–ÅhUÉfÀŽ.˜B1~÷ƒ¾Äýè“ZåÀk µ1á¬Ý¥ãCã(rî)˵XÖHI/(œº¤f‚!µ¨ÿVJ"ÚÒ€ÈLk)5lŒYTY™8Ƨ§Ë—‹Œ)¡(‚‰`ÌŒ¦=¹ËÒž¬S3^ÜE ™Š¦+™¥'GE”™n¦¤ÒáW‰#ÑÈ„æËB&L­*£Å42d8BQY6Ô»ð‹M†&…Qˆ#—Kí’ÿ¸›ä×2æ•zêšêÖ”O¶Î›F+‹Ï1Æ÷]ßê$å£q¸©D z(Ä÷µ»{z ¼}óã”±*µa4UÝñ6šÆAãGæìlèÎ /¤­¾þ¿˜î5ûSUŒpÊsL-MuÈöjd8P5P¢1Kj~{%— 5å0š¶ù4ï„ÐIdcŽD ²ñè^ÊB¤RÈ~åý^-°Žy/”Ž(G´®òK2H êá3)ûàXʳ±_þàÄ¡ÉL‰äÃM™¨†¸EBà­—ÏA`…4q¿óOR”s†S®yŽBÒÉB*D°ÓƒPE ¸5CÃk ‰PèÞëøÔÂÓ!%¥¨‘š)ZU® —´…™ZÌR83«âÕóLÈéø"ò̈8œªg²8Iñe™ù¥d@}V1&_žÉå<N3¦Ñ-µSªû&¤¢‚J0 óÿÜÆø‰B:k¯–֧͘2N´ŽŽDHc¡úц)?þ±Ñ†{Å«zmäKçT±q%TÑP¬êœ‰‘‚sÊÂçX,Yx¡hö ™%Âoár«y…ž7ø”E—È1­7 Éš¶:SQ)œÆ˜ö–aª˜¬‘Ï€hÒY>œˆ,# 4E0õ}`…^˜;¦/dÕ€\ý$Â:ý –@¢™JDƒCL9¢1!,_ b¾è¡3Ó«‰ôE*Íô_um;¾¤G @IDATÆÊ¥àH¡c D†$eWKLߨO!Ž”üånš²WF4Æ/…`ÊFÊÞzÕÅä£áÈ…˜O_ÔIÕ˜`‰–†G.KŸr7q#gj¦ S–*œV­ÿtL”EDi8¦ÓÅ!I¹Š_GRp鲌*š6r蔕¾)e­‘S:‚Z‰¤Ùļ2ÎàÐ&Åß µ›¦¯MVHH•®ÌîõŸH„£kÌ *½Mh—H©˜•‹Àôìi*eVŠÝCÅ´Qz༨®Uß>ÉÅIcCÈšÒÑ«¸¨©†Y[çR‰Pº†f”EG”_Ÿ~Ç7߈L$+ЦP‡ðñ9h&§ö0³”[Ú˜µalu¥§Üi  !NQN‚U7â#6°t#D´Üt(04QoÄNÓº}1zén‹$V_z…ŽîçÙÛnÀ;(œÈ:Ñši½q¼ûkæE…üýY'm”óJîöÏ¢qpTáè3ܨŽËÞEM¢¨Ñ”&ó‰ÄJïKKC³ýä0ë5†Ó‘N?) íFÕÏiz=j,š\Ñ6¶ê3A¾†]eÛy‚Äk@-4FÈæsäžØuk2q£êùðtŒÓtLY~¹›Êe—öïݨNµ$þþÄaBº@RL½Ý¡¸däŠ!pL[6fUsDé°t8)Ê?±ëZ­]4– "üe8™ïG5/Þ[½YWb‰rk€Ç¡ªçe¦ÏâÒ©%‰…äŽÌAÆá ðÝOkÌ[¯ÿí BQ ,Í9]/Fטð6DW˜õbJ>£¬7cÍ(]¨qb®œ¯þ{+òÕ±ŠžêÊM¸BÖŠ8õpa w”E¿*ñ B¹ÜJ„´ÃÓr‘étPÇo¦6ÇÝ$>D 2k[D»é,—øéãó9Ä©„{(¾èÝáSÆ/E‰#t™°[ ÂN+×’ù@%LÝý<h¾üqþ¯«¤Ô² [{ý4†Ç©¨Ñ”‚ÆLýùêÅÅ…œô/Ò:‘e”nê$´ ¾Æ0«UKU¬ùF nÄrEM;“ñǬ7´Yü>¿t'm¹9ð6J‡¬&…8dá÷',=À—Û{•D¡˜RªXK‘EÙ|L%æUöã¡OW…c*Qz œsé}Ü4 ÓIH&Ë·"4ÓÈ9üSƒ¢J&ü“ôùHá@t`lm•'*%|MˆZ¼i´FÓŒãK4Ö+}æéæ²h\<°”8©i@bˆ @'%~½¼8‰Sh9qèpàNµºâ«H MÝ qœ=Ž\gŒiœr—¸8 îÛÛ®é¿~ý¢l¥ 1 d·þwþÐ‡é «³­ô5i*š`¡VÚ±/¹æ!J3´øþÄ÷ãWÿöÙ㇎BävùD,ªJViL¬™Èu­½¥ !ë¨1‰p ªŠ\H Bèô¬·j%¤³,¸5âÃó%Z‹ë¤ÐXâB!%êa«¦P:r¥‘¼ÜΫKì àF¿üaœ×&Ý)#‹Õ°‘¥¶7SÓ(´Zv€É…¤¯íú|çW ð¹ÐÂ{Àoù¤M**DS9c;‰4šáíž#âóhM®±:/q{˜l! ³hpšF|]q 4'»)¡Í.âÇiAHŠu%E–)—ޱ6 Ç”‹”>MÎs®‰`lŠ N%XåÙ½D%.t5xJÇá¥yþ*M‹4´_ØaˆT7ªÖívlpÒ2vYr²DøœåéY_‰6¥¥šÆ‘ˆS¦uÁ4#3Åyý—w74F¶,…*Áç˜òiÖš%ÇÑFY¦¢¬¬Rø|ËñîßïèÝýÿýï§6©ø)}ÁÚ)¼0ט?a9÷ê)P–˜¯Ç¢à,gÊB­¿…¿ó–GÖWXøŒ‚5Ö3§*µáÌAH™ì’®ºÄ²8ÛáB‘MÓHÈ‘ÈøøE9¢U‘È*Z¢¨Å2åVQM¿„r%øœ. ‚iäBÆ[´D4ú ²)ðÞj%¼ô4ËÒm'ð…!»û÷n‹FcË©Ûz@¨#„áSHß´Ò8zà¿ùå_ôfÐ’)¯e`Oå@£}ÒoO8 dªÇœÂG¶Àþ¢9˜GîS³Õéï¼–Hç0M …ùÛ"³·ðÌ4'ñÖ[Ê5À§Ìø‰ãK„sb¦,©B¢R;Í09¼8ðµQQSEJ7å arªøñee%SÜju£^ê•ç'”–iËS‰_„IñK‡XALš²àm ˆÉ8m-RÇDøFv¨è@|5á•áÙ;¬Wl!/°¤X/×H¸P«R¹BN º-m;À—hÚ±ñÞê†^'.Î?ÿü³—j)|YFå{Ö6Í™[¿ßª.¥£S]íqàŒo4Íä¶R '¦\{+„Ù6þøÕ?¾{M¯ ‰kƒ ܪSK0D‰hš‰rÛIH‡ƒ/Ôþ‡§ÜŠŒZågøU*JÍŠÄ©œZ¢ÈõÙ’ ñ9í ©ug²ˆäHgÈ Î¦_ÈÞ^ÄÃA°V‰—nÔ†D!Ž“ÊIËOVŠ€Ý +Ùg£óÙ–HÉ%Òô@AóµG9_ŸŒ`½™Þû7­O)8oþ¿N*çêK_:'ýF…:]# ;‹´ªÖ>áÅÜ™‰# dü–¯·©Á!hF†Ìš"3Ó8ʹù2_3|]™âCŒö“7ZBšS† ‹¯DUÊŠPð %ˆ&kåp˜,‹â`6Å"* ÞÓ­3D&Ê8+Ê ¯O:•£ÉýïþóŸD¡ª=E¢u€s%ž95•b¤˜¨)“•C Yºh-Âñá)‹®§,d|N„B1bf6ů&àë?j®4 ”_6Ÿ”®ªhZ3œ**ßx#¤ÿ¡D§ÐÏ!¼û;­ãYåò•ëiñmÏkŒ£œŸyxpL¥sòM;ÆD4_‰n”BÀö'>dËð=®\êÈ/ÌZ\ä‰K‘عÞê ­¨Ý3íà¶®§Dµj “YóŒ/„&T¢1ån(M€Æ¦eñ!Ì”™²vÉnºžMùlåJ+Ío4eCSÓ³ÜJÀY‚)­‡Ïy¢ü"Í Á;Ïc›ð¯Ïÿ÷Íé¨[ #µ|Ñ–¦ Žfd¦ ίç|Êýë_ÿúÎsȉѿH¯\kÙX‰kÏ•³-ømKdL8?Z>N ¦È¢¦@SN 1µÀ%FH¹¬Î´Fñ5 ʤËÖ’tS q ’Zu‰e 1S= S.ͨ¢¨Œ_Ï5œ`E«ÅÁ†G‰Éæ·œSûóPŠ\ü锲Qt¾ìã,L¢žFªƒÆØFù‘M ¡Õ Å%Ø‹# ^"ÜŽGÛb8Ò‰ô]GLH]Y¥«!ÄãÝ]ò/ùË8M|šàºÚ¶^ )éÈueºBpÝJíà Õ!œ/1ß”}ßã÷½-Ü·%~®óYüã-‹U®Ñ'ý ù­ãóµOÙzèôÕg­v}&%1qãn‘BšÛH ‘ˆ†ü¡!¦ÿà3Mü5¾Š¦©™&Q®U@­ºS~4kMG”µN§"f:8@SÏøÄM'Ë™NË”G¨”Ä#'ˆ0ZQc¥#¬M!âiŽŒÀ*‘šƒ“B‚áwÔvÚ‹gß¹K¹d^ ýK@‰4%®C¹¦â\?Àö|H}ÂC$VZ“þýίœ–NuU$Ê22ç@ T1q*§¦hø*" ñ[‹Íá»üѼ!0dR¥ã •{Š]{%”ÏY•¶…KìãdÊÓG£,=S!>)–'DVE9Ûdþøœá|—Ñꀔ[ldcKSŽ”i4>«C¥0ubdk¾¢-Q­S"Ñò¿û Hhñé*\¦ÇX+8’•?­}^´qTzˆjHn8G”/é9Æîûv*¦vÉ  •®%ŸˆùÞ\ø'í?ÍÍNÔ ‹Ñbk ¥ôÚ^ÿ¥®[«f“•¢DŒ^ü}lçÈr“ò˜ñNÔuÁL¶BõOÙ¬ï|ù£OW»ê÷…ëÄ´ƒM–šiíÕ[ýóï`~+uºûTôΟ÷·‡JÔI‘”ŒA°|Uš2ýÄDã 1LmXA¨»|)K„Kt6Ûä­"…²¶?À¯:ŸŽqèÇœfœÑ„€ŒÃDYSœÙ%y–, ¼X׋¬6 ކÃòáÞQvÚ=3/LJÓQÅ&T.ñª×')4†S9;É1-ÄçèÁ‹”ÓòC®W.‰™¶;ÿ•v@ùŽ,%ˆó™„êb:£F¹ö„’Ŕ˗+n„´F¹Óª†¤†É,Ήo4âD¦E«šºF!xN4¹ã§LE6Âé XZ½5çäËJÇG-#X?ôMÛ“D„€j ©1‘]8ÈœWâãïx+ °d>“‘ãØk0ÞË×e Qb=å›êoÍYKÕG:;µGÓvÜHjúD´q:ûl•©j¾ç1õ9€_¡ûØmÚ×ÙŠN–fµ€êä·êjUˆ_E‰nâ41á²<Ü.ýèŸaÂ95S¡wþЇOÐ5I¡ŠUOǸá(Á*-$Ec´ªè|oyðI}ëx$÷·“¶¥6ì-)¹Æ•žlmà'-ñµ±VÈmQbR@Vi…‚{ „¥‰?ñ@â«ò@ÃBæ sò ñÓÌ1†«+e„±é²òW¢}(ÚýÏ!B픿ZrÛ}ç—?./ÝdµäÒ!¢™£1GŠ/Ä瘊š²R“5\µ7ù£ gf5RÌFQ05’5’jÀ¨.„…t"Eâ§#…ÝÉp)J`Š–E22§µàÀùLbéíF)p&ÁBà©ñøÏf]ß8M¹¦é'XÈØÒ„"p€ ¦0Í@|H4çy¾yüV—ŽÑm½’*%Dÿår²¹ù²Áüs‹Ì3êC@œp‹ç3ÑVÂ/´š›"&_gÖ€ÉÚmMØ:ï¹ÕBÖºô8RZs=T…/Ýe„qêÊË5'ñ·ŸaýâÅv¸«º¯á+¡èr•&d¢Ýq¶:]Q6%â›/þ[¦ÏÂ4û/4ÄÌZ#µé—öù‘èöIü_²}¬iêäZîy‘ —ƯsmY`Q¸t¸Q?ßîϽš.ò¶šŽ\c›FsSšé·:#¤º¶Ô4ÙrùÖÎp„Ú“l)Ä´ÎR9‰z¨SHQ|k¬ dS†&ŠÃÖ6²U!Ö¡¢ïü³/‰ýÿ¯•’ÎNT”ƒÓBL5À€¬ºÆ8LŠ…81œÞ!/Fÿ$ÅÔÁ¢¯›$£O¶cm·ü˜||cLò!:4e¦@¦ñêýèDèG¹‘W¥ÅJA …ÀøªðŽ­ˆ‚(µ²L)¹øö‡ƒ¹”>î™B)HÁ¯ç’ä«¢·Bë¼i©±J$5‘ÓëÕ<! ˜M-}:d#ã„Y|Î9bëŒÃ.ÎÇ=ºÂ Á‹ù¥J§e¬˜&œSnÌJ$" ¤™Ú®Fë¯7¹Õ·lÓŠ¶ !S#œÅq ýúågøÞÐ#¯"G ܾý®Æy¼åt‚ÖA¸žS–WÝkš[¿¿šÂÓìíÖ_ÿðÖØŠœO)´F)šTš•þbÄtÿ•¨ £©?A÷eÓœ£¢±}ŽÖ‰Ëwâ;iè¸Âí 䵹­ÎÂi¶r;åÚ+#ŸT= ³ZEƒ›v438œÁlÈÔ_t{ÈG&›N r%Æç#Ä‘Èaö!Yúd ¶‘ïC§(©6“OÍ8Óº5ÂÑd-JXˆÃÖI8¤­+$·¨)q_þôÛÒŸ¾Zt¦IYi=×5Î:áã˜Ö'Ÿ¤,¥ÞŒpV'BNl<«>œ”ï9ûÂV3¦Õ¥Ü§2–dÄë­('K/Z'|„tøMÕÕ'_”Ý[×2LÇ¥\ü%žZ’úF† º4Ïtl,DžV!øj—H¨ûhÍõT®ÐÈèE…˜\S#¼š*¦Æ”ñ›ŠÖ¹“;GˆOÊ»’ ÆcÀý.0N£[9sÓ÷ è?A…“)!ï¨3¥Õrmð«NA'½žË5…ão]¥ Y÷¥™¾ù‡¾î¿ÄëŠf˯P«0Âé9¶×èxcj»©6X:¢˜>§ð­CÄã‡NÊÔø®d²,„2Í«ÂúTÑ)¨«ƒãóWˆOAè#ásJsýë‡!—[b") Ùç»&œ•n$+×ÐtË!BS´–ßXTV&¥ºBë³à5|¸Z|;€ÏLÛ c!ç¡/ïRßú6ß)‚‘&ZR qšZ‚(›ù©ÕO@(‘­Ž¥æÌL§”g££D-á³ÒÕâSf|c -ó‚?žø¥D VbÌÕÅi!!É^©gÐv¸ZGãv^¢ö®ÅÏš8Rð#çÃ9˜g Ÿ«èøÂÙêrî"9˜•èˆßiBj%ˆÐº€l`¢8p¹,‚1²NBzFíPR`!¤rV(µC®/Å@ˆüÕã\‚G‘ÓÓUÌÈðKq r¿‚g‘)Á©¹Bé—¨JR¦­N~ý‹rŒIqX+ò’â·˜nß}cã¤ÜBÌ´,µò•N¡ã+á¥ØsÅݹÆFpòE«‚ö¸†tóýÚÆôçHì‡ÿªL²Æšj;²r¦¢ù-D@S›™²©¯ÞiÀ¯˜ìžDR™DIÑ0"úá(ÚØÔÈ´‘S]N;À©C8?~ÌV¡sÓšç”n¤ –‘¯„Æj)åñ9e‰2Ó¤øE½âyVYQç°ôz@£é·"dÈ|œJ+Àø”µÄ©s½áÔ•Q”HÓ‹Êzÿ˲©‘R‹©X|¡¢UÁYÿ§×ϧ,¿cŠcú毜ü éÄ=­\愱pÑÓÄíiC€vx«€—xÑ?ÔSÀl?EÛ.=«h4åT‹Â@ˆ#ëäŒßHM 5Qï|FS#ÙàsºçT‚&'ñ¦%òá¥sD¡q*Z¨-¢@V9ÓJàÛâe‘*ŠÎa¢‚Ô˜(ÜŽq*Ñù$hùÆ8µzþ3æŒÒ„8™ÐZáã·×ã”+¤ªò¦•/eÑ#œQfw¡À0 u†4JY¢~j)Mc…ôÍ!ï‹ëõ"ßÅ/­øl²t¼JxÓ'BÊžV®åÐø:azf6Ô*>šÏ"ï|ùƒIÖg"ª7­dsDgªÄ‡ðÈæ}sügŽ[¿€åPÛZl‚³Ù(Ki‹Âá(dŒ/$‹¯Všæ嚆äd)Sb"¨œ\–8œ¯4“Ò´®J¬Š£€ ×åíè»;8Rõ­‘ÝcžT ˜üjñ×X>œ&¹ºÆªK¯±t¢y!°«¢¯Í_¶œõf!­T Ä´À§S-!H[çÌ,ª%†/Ê!åÒè¿\²ôoL¿£³.ÑŒ-¼BƦ5V“Èj…¬I´¢©ID ÆÉ¯=ç›õV®–VN¨ê¨³ÍÁµR:,òב¸Ý³™}ÂVÅÚK)TuÊ,Ÿˆ­3E«ŽBp„‹x¡Ì]aëBCå/k¹‹jLV|d8ü»xÈÀr,ŸoK;Ù8Î Røp4F!‘3¦2H8@ÆiÃ/…ßëQã¡QL‰GHt,'Aœ•˜‚ÜüSû"¬œî…ÖdL¹Ö‰¹>qè‹Â‘…øñ¥M_¡j9ð9h|éi*'×h ¬&i"”’ŸŽ¢+‡,ÑÎ[Eé]í ™þhÒÙ´ÿ‚Eù†WçN_Ïš0‹u1@¬qkál±Òù‘G#~)}<zEj'Ñ8²09ßö¶çísü4ã@„X!`瀞»n:§Ãˆk^TºŠ˜á‰HažÖ¾uÁ´|£Dâé#K\ÀÕJ›J‡&¿uUÈ6úÙÏ;ŒqºíJg-ÐHJõJœrœº…ë¹[?gH=ˆbÂ}ùS4üÙ¨Ž~:|=\}}\>Dt«;f+Lùªà§oÊ‘žïp ÂlK9hu’‡¬ÑãÜêÖ?f|ëbp‚l L®ßâº-È’Â8ª0Y!r¦‡%n¬–h‰å…Ú"¹ÐpÊ2²WÉñÉršÖ¨µc¦Y!à,5#¤(¿\#°tNÊUù¸ßB£…cð•äsZ'B Ñß"áê³ø@š#/³Ü­ížDˆÏðµÊÁi7…JÜç³kY·ƒÑ€|š¶Þ[^4jÀÆ+õ9)µV( ØLu!ß42Z!|ˆ«Ýi§ÐVFLéÆü%6]èŽyç ´ü‡èÃÔg|fmˆrL­ÂÚ;‚¦vw臔bÄ7v÷䨫…Dʱ¨éhq€L¦uR®L)• qiy®xܺ‰{+Œ/jiÞwá3½ùÝ˳»°›Ëßÿþ÷?¯ÿžʬnM¥óm ‡ ~¨©¢:ŽlÊê(+Ÿƒ ´)ÿ…Éê1˜¬ZÊÕ‰¢ù¦DZ—“ ?åó…ˆèª‘óο—k÷üÔÍ9LM!kOŠÄk¯©EÙy!çWE:ÐXoš D`“jZh`; d¸žÎÿãÅ?d£_7t‡X¡eazpÁ¹Á¬ËcÞ>à³öP¨ž-ŠßŽE0¥ƒ“°if8'…Ä9©••/4ŽÆê¡¬¶‚¯=!d¦Þb¦VÍT:ã³.+D”ÿû#ÌD×4gSa*-éÉ©jjTÆ “SCE)´Œø¢ë†/Ä0ùƦ:†Ùuõà#ÈB–™³¢üøÒE™/Ê© £)CsHR;œµWÔºîjúqÞ¥ÔÇëÆ³»ŒèÝôùë×/—‡~ê-q'wëBv Ð7ml𙨮¤Ø®z( è»æiNÊí†N¥9©qÞ}Kgµ!…ƒÃ µ|S]¡M­S)|C3¶>Gˆ§ÑtZ‘²ŒÈ¢Ž‘« ç™Îû‘. ž²›…§ÜÓ"òÃh«½ÿñÇÄÕbúéZ¨ˆš5l äsÚ…øFvTþ÷ßüåWT·3mXvØ”Ž)ÐZ¨U‚c*T'…Öù©}…àÀ˜Þ£Ÿ­=~£%ûg_ª+ÄÊMØb ­š´ÒùgÁ×ãÖnç´zÃá4&‚“8GéÈžÇN`wÓºjÄqgÄ¥«k¬hšÚð¯Ñì9‘{.ß³Ááó pÑÕAvßCS!Ö†§`ÊRî®ÙöŠÂEu i¦E9¬&cvRéDKÜXD8R«kl±@F¡NŽúEV‚Z¾ ÿ“ÍA“Ÿ(²)ÓPºqøép‰- &<ÄÈpà¨ê²¶ Š …ÑÁa˜.L‡DzµÐ’J¶Ò©ñ%ªkÄ)ddã×Xx…è+T®(&¤rÑøe©žr!S}"¸% ,ôlô·ß>š Xìú¹–~ÖN­Ý .ÚÚU‰iŒ#ÚK§/4žîvÓ%Z£…”YÕÒR«åñYûÄ„”( OŸ#Ä/=Ä(%Ð*¤à¬Ä.W!&WÔarƒð‹š@+òHs Únš¾öüÁÃ}ÁË ÐW³uînRjï®?°öZ»*¦[¾qçLEÝv|ëÄmË¿[”’U/¤.Yͬ!NœBM‘[Ú‡Öç×^ÿŠðíè êX+Ú¢ˆ¸UQfø•3êÇ5•%Å&˜Fv,øŠâàóY²@–”SGÇä@ˆ>´ç¾¯7¥Äéæê‡òŠâ'è„ñݦÿR€ÍñÁOÃý`D·B•®%R4E¯ gÉ–otX!kméÝÝ£u¶²LMÇ'M~KŽiTB:§»Ÿr–ް\ŽžãWh¥…~ïW[|e08ŒÃèòÕC»ûõ"X3Zý•e+)ÈâÔi­éëÌèn•/´ F Ù–ÝÚ¬Ä2ÂMùBáu¨Ÿ¤Œ|!8>5p£‹OÂi9@N‚LuÛV¦3Á 4S‰Þý¿žs8_ÍyìPi¹lmPË·¥åBVÅtâp˜=PûZñŽX”{e[—«¢,…LáF`ÊkU9U\Hd)@G‡çÒÙtøå ÒÉô9dDÛ‰ÓµwƒØ¿ÊF`ždý\m;VÈH– 1Ž? >{ »õx”U*j©UKO6Ç… uhùhªX>Îç—?Jx-µ ü•¦  ýn£B ÎÚÑÚÛá"Z{…4ÃñîÿΙi힣 mÛëÇÈZ—5*b¬Êé麹‹Bà})T?q€8”;=4Ïjâ 8¬–À‰çØOn€Xú6dUèK7B<-öý.è~å£Þ¿þõ¯¢ƒÏºØ9ZÈJ «kj¤–?YüüöÍzÓD“HƒMØ!j»ÖLÕc—žæ‘ø|¢ÇT7%hZd Kö㙌Q—*|Ñ>Nù˜¢øvAd~SHW8B«•¤Æ-Y–i‚Æ‘ž¯D~:@ÌÄ)X[ÍHá 3LmsŠBØ‘McM1ÉÊÊ‘UÏÆÐ*Œ ”ÂXdS4Sí½óS?þÈæl³Ó©¦k£Í)d”Xuþéã*Ýb1åºÝ¼s»œ\TöD [ ’­®)¼Ò·98³#Ò™Ó5‡á§Æ™ÙAé¸!Ãí°Í¤ÌÁmo4àÛ¿`yøFØs´¿ßb¶tòMK¯“ªXø½±ÚÛh ŠÆDÓF›sWÖX Ffºþ«Tמ8Nü™ÓÝ­5vP.á£,ÂÉjCW b* '‡Ïà¢ážjÖI¥Û7R5>qqHÊ qœðBȶ^VW5 ÂêÓCµvÈÝ_·òui<Ûpü4ë§t 3²wµ|'R‹-×è¬+ZÏIõl mˆ*êV ÿ¾xk4ò¥¤ƒL³,8«–æw²Uº1Ž‘‚,¹kr×7•ŸãôvØdâ¦5ùñG*ÔzBåW†n*뀣ª|#‚‘\Ì¥è¾5Ë­^šIuâ–"“&‚ÀÖ„)Áè`6u/ãt¦ÜTWh|cT{mSÍ ¥o\ŸKäZW˜Jëßb;k+1BN:|§”~äþh}ù£(¦Ä.mð×X T=S!v/¤h"¼Àð­ïMÓ[p7k‰íÌôëA´MW¨}¨Ÿz«™z€p¦)duM‚DZ')c`ú9JØm]u†˜Ê5úäþð] ÜsÔZÊÂQw…TW…q„_3øÏ MHJW_'‘‰3ÓKìC­ÕÁ{yT‚_ßf¼óϾ\±npRÈÖê)s-Ä>¤o+´]çãè “¬N}rÜý[ÿ…ÙLßIÖFuI¥ViúZê›Cmàˆ&_.'+QŠ©I8œZ¾Ñ5î¤}x¨§éx´÷dxRtˆºâè ^V ö˜g€«r¡?#û nJYW¬,ߨr8;ø¬U´ç˜ô!p¥9ðš4R.šŸl²r)Ã%Æ‘2?&åÖ^­é£‰c¬1Lš8‰pdKÑ6!±´EŠQëõ¬‰¦…Z^¸ AÔî‹f@Žª¥.“S9g<§P]ÕR)Ô„*-Ê:ºD(ã »c: ã$Ëo§–0Y)¢Ú6Uš¦‘!ó[#òýÈ‚´{)¤o¬ÉŠqoòžÿÑlWª+MGE:ãV×Tc4Ãq8M¦­ˆ¬‡È¯{è}ª\úâ·Ò%Û;«®n‰éÄÌ_8ÑŒ-A4}`ë2åÛLGJ4åЬË{œƒ>AŽMóµOD¡)XÛ9å&ÂÇ¡ ë.ò­_3RØK_WÒµGŠ_S|£)|‡ÒÔß!öák9íùêßHDÔÈÔ¥£AÊí)µ ˆÌ©´‘ŽDœ¢Rîtï|(tŸõ(U±ôš1%E„CÈ÷˜2S]Á™¬€ó!9_¢nüBíÐW1Ͼ±twö@êk1‰²l…‘O?ß”Ÿ,§-RN'ZoÄŸÀïÿ•¥ô÷ôªëYŸÈÆœ%.‹â¢4 ‘ωÃÁ‘˜•GϘp ‡`)m¬,fÓh>Züôk˜/„É$"œLÈ­˜0ÜFSq¢—l„£¥bäCÂW&#«Œ‘N>ã‹*¡ƒ@8P¦ T ÑДaÖ¼±id²¨´&J.1ã³¢n. ÀÄMq8D8*rÖ„ —¨®Ž—¬•Àyaý7J$’jEË2S¡­N,\ˆ•NÍEî’u ¹c:â*ÑVL- Ë§&#[)‚MC`p#ŽP)ËJ¶º •UJÌB‰pôà^cc^üñ-ÁßñêY!c:íISju(ÄBlTÑÀ‡‘”ÒÖˆÃ12"¬ƒä§Q9)Sø³·Ú‡r¾£pÛMA u=¥L!–C™vNvÒj§6îéµQ®,øÎ‡Bšþ&„ï(Ë­„Qu ŸÅ_š¯"¿Š¦€r­.8Ã˜Æ wÜýŸý1Æ; [G®qúó·v›# ×vÑ ={ ûˆæ“‡+"Y­ÚÒÒ“íê¦Ö2·@Ψ½ªÃ‚ê9B”ùÉQËH܈SbJ‚_-¾f0!h-Vˆ=õéËb8‡A$~|§yñ?$Zuæ±Ì±Ldõäà›ê˜ŸMŸDI#f)ÔD7­?#0&¿èiöóÛ"[ªº4qîE-¡B¢•ž‚)ÿ*œ1E“.Å”%e*djÌHg`¥›Ömšo^í”{Ï"[Ƭ¥…Ðo«5ÕL=·]B«Ïr½o–+ý™aúöiû†a×LÓÖ ¡lå9ré¬[~)ÓŒS'BáZš%äˆ&kŠÃúDå‡+®ÉD6ºcö”˜Fmà#ðësc޳(çõëp)"Sk*Q·j™VK·˜Œ~Ì:ѹoÖð3Çë§\’•ÞNaɶ½¢µ`ÊAX-B“uV´ùÏz׆+ˆB‰‰´i‡@ `Õk%ª+±~pðøp–rÇšÔù¾ÿÉÿE’t×Y*½ÎµÑ&вJäãO¿Ñ­µà˜Šº9Æü:t¤q²B8ùÒ§ 4…³DhR6•é@p¤Ä©““pûœ“Šßê8ÈÌûUÙ*J!+ŠÌ ¢h@|£©(‡Ž±Gæ”{NSÍ5¢Þ¥;ÛíXòË4ÊY¦ÀŠ™N6G" OŽ\¿¥›²|YùcÂÙ@‰8¢ìÔ¸¬ÚCƒãƒ¯¼³µ²žÑà@)l –+¤"f„ðJÄvn¹¡|}EEûjøýÔOHÆz Eü4tµTÝŠ¶ð|Ѧœ:o~ÌwÇñsøö„TûÐISëªN1]!Sõ`ìÜ@65šŠê*Bé¦õ „”!¼N„ˆ× Ï¿ýæÚÝ¿wWˆý”Ë4V­ \9ÓÌ‹€,ß“-…6•ÒnT¢n-ªs½#?‰ø‚[Ô{(eSéÔ8š4–˜Žmá×CѪÃDHÄùb´¥=öJ—˜HE%Ú|{ÞGCÍtìôŒ¿ãˆ\Ãw>‚9Jxñö§RE}B%¿]å·V«F´ÖŽ¶Òº6-Šö­ÙŸÈE‘i–¢`%H)Z'–x#šè݉F_4ýtªÂojôÄêñÓÒJßh÷H%ÍQ‚–¯a*¡)KŠZì¼-" ˜@ñ=-\×FGH”ÃZ*¦zFœ´åô· £4‰³Ä9õdJMº4¶) ’xúEù¬*iÂC,ɺ—à· Ëä0„ZuîÊÍ/´¥ÉbdáÆSõ:·V®hü’”)¦«]ôhýd>ÕvVIÇUK:'M"Õ…¤ßðeY‘cadœt$¾ó¾)k«ÚB8k¦eVn*7_QÄØ†Þgϵ'™22ƒµ!eŽºtg¶3Êß{¿ý:Kÿ^Û4¹ª0 ,!8~Õ<@!7/Žï¾ý{£ëî_?¦r)›Öê6xQµp:!ã˜zn½(qÊ\æ%×É©+‰d·3q¨Ua.7£©6àù­ÑχSãëÁ[öG±çÿãÖã9„¯²,) '%OˆO­³±6ÎÖ_LÓG)ø¦ã¤cuŽì³g’Ýp÷÷‚"ë¡_jÀ¶B¹üÎ=~»ÇQ—™Fà#¯óÍ-ÇŠúH~jís íšÛen*¥è]\tÓ{4_?ª ˜†àÛ>gÇ¡=42S¡|c>›\«Úæ°ÈÔø ÊýxÕ™ñT¾Ž®±e#qªš™\&§2|µÌT±Gú2ˆ…Ìíc ´Úš+]´©_бe$^"œá¬í¢@"ªp L«)óWH”&—ÂòïEù,5ü¤R Òõà>õì„F¸›÷¯Zu(O°]âSFhÕME!Æ–ä”h3{úºûwvÞË}õ5àê’nÿ--Á¤j¢3­¨eêÍ­¤Æª.dŠÜ‘âDΑ‰—Â7"wÜùL“”¢m‚´¿óí Ô³º¬„¶ñ«{µü±?É<§_–wÏ|²>Ÿi ÁØÑçך†M[ZÕ­ÈQ¶v£þß¹íº›÷0V´ˆh¯ÓF%p”«JkÒ¤EÝ÷PˆÄ·gM_›ª‡®Å&5Í–ä’5­®ý饵s©˜8­)§#ûìDµ¿~ý²:YüÒåVÑT m0ëÁ”ˆY¢¬B/vAK. :Œx Û:jÛm¡du‘‹`œ¡ñ[8‡2f_ȸՙ¦ ÄéxI$›2|‚q¤@bùp"p ‘åòkGô?îwu‰ÁÊ'!ŸÕM!SÑÖ Ù”bK)ñÛñi­œ›KÄÑuêp˜,cj9!PߦU¡L§…Ì+7²*"”eåל/½G·(“"O§>åÞg8)¹MårØ;W»,Í»Ò(H‘›¯Ãœ6ßXÏBz°äZ-+°,'.²ëê×%üôHuâYþ6“oTŸc´uF…8s"Äáé5ՕĘ)ÀcYÆðÖe:ó…¬ï¬'Èæo'^T%–Û’BçF|u9qrøô1õàQ­Äƒò¦^?}E¦"RÚyë’hjá§öµ'¦­WnÊpÿmK¿“A)£D ŠõÜX¨4C“Ã4&±þM˜6ŒïùÓÏ`èÛvc¥+J³"Á¢ºª¨ÂÔu‰™:!-§öl»o~¶i%úZϨP¹”ÓW‘NÕ…L‰@# Ž¿Ì:‡<+ºêÞ¢â K$ÈåMµ¡Ð©q»«ÀÛ! oí53)NþÈ hj¥l ­Pm@8v¤?ïõí¡…kƒ“YÝù,–níÊlš#J¥ ?PruUÈJA _ˆß}žˆ‘N¾Dðr×Ê•Ä!Â8UeS#3„SoKéTÃ,¤œ-Ê9B×Y[¿~Œ©u9µ„B¢œú©ÖôÃ}ùc»€?š×=o{±•®gcåŒ[fŽÍæ˜j;Þâîá¼6r–‚ýá¤Ã“­+`ší¡–J ¿4>μ|ãR´ÁoéÂòI©’2§ïæÏî>9õuùʵ+7YÑðdù­Žió_üRËREW¤Øýªù”+@9ñ˜|Çb‡ø’ù~ðQÆwM¤„µZŸ4 l—ŠBºôì§ZÑŒº•ˑ˗✴ÒïkßP×»Oq}ê¤%·v|uÕ¢À) ”^?VÃr¥¡,KWp~å |•&5N}Âùv©Å I4J”å|0Âa%é“^J‚BWÆï[„r­7´¢ñt¨GQcàÇÇ19-LŽäð8ñD1×nxº˜lHêøÍœ8 ÇDSÈΩ1¸Dެ: åPKR¢i‚,Y-¡Ä8ôùœBõ„`V®±N¶R±§¬ö&ëo‰ß~OMöÁÜyÝ_¤Ëm-:aüz[êÈÝ´&«È/¡fмþûo×<”û:¥ÐÏ*¤‰¤YEŽ~àUÌ©=)e2šF¨±ÖOPÈfš2 ,2}‰Ê…ÄYQ·NŸ¥¤ ?˜¯­üÞŸ8\nÕm )Ë(T^{©Á¿ýAQQGÇ—Kš)™C°öš†¤©:}æ®a!eùxñÎÇAoÜf4[B‚® îï­…ršsix»‚\5Ïv˯4Zm´ß¡Ehúí(ÑÝŸx²F =l¨™R€Dà°zöªtÔqRö¡©D 4m3 öÇ|ø·mõÁ‹fESÛòi¶?F!äÖnÚVĬÛFR ¹¢?nM:Fû¼>MU7æX‘PÍÏiO„Ú:Å¡3Ú²*Ñ80>¦þ—X´ºšá¨Õrj9KÇ¡ÀNÿKó¤søœšÃnxêpLÑênÚù)ÔúuY(ÁøÒ­ûJàÔŸN×@ÇYЍQÇX34Sm[Ó4 çY;Ò(‹ ‹–ˆ‘‘u¨Vpd1—ßÚ3å#¿ù·_Ê>ï%[ˆBüú $(x–÷yknŸ[…®pø¢øÆg7Mœ»¹&½aµ@¸µóÛI#Û†(§¾³~LóMGU1MãJ°å™“à…UPv+ùÛßþæ >Œ¾žþã?М!øzF°“FRʬ½…ÔFÊU”"×ß¿ýñwOÇÖXJâ²çœpâø¦Œ/¥~D5ðÎ/¤÷å'wK¦oé­…xŽÌÍB_-)ÑξÃá¶UWrµäÝÿwA|«ÖѤŸ‚‘fK®:ŸSBµ‡Æ´Ñ¦Õ’ö¨ñ…ð‚çú‹Ï"Ô|óã¯2#h4%’Ÿã$ ä×UL)¤øU7•U«g§Öiñ2„C·œ¦Û%8Ù:ê(%2!ußx?cï}ÖX´ô¦‰ó9Tá;Ç"¤L!‘˜FÛ)%|HÑO<Ž…­*?-ÉÀUm£…Ú¡r#˜2Q#ÇYØF¸žuÀ&uq H¤}áÀ!E9­Ùj©iŒq€,5Óš,‘ß!Å1-E´–hZç௴DL ‹S>A`g¶¶ë­6üîÓ5Œó£¹¹ø€¦«Îc:”«¢·ÚÛz ©ÒŽi 𶉠ñÊùf.u‰²X‚k»6ìB>‚êjÑ%jÀ§†ãCŒE1 ™’-ë¾p4 ,2¦{D+…<Y¯‡D2d]Õ^:¢†‰ÓT¨¢!öÜ7KßÞe¹ut”^WÝBÒ! IöZÇÙÕ.ôæ—?þ ã~×% ºtØÊÕCú|!ý»¸t‚ãÌéø²…ÿÚ”vZ–Þµ©5x§z}ª•ÚSKççÔRS>AOÄwŸ„úY„ÒL'F¥9L Ðò9¦L9ˆ¨1jÛhZ3øÍÀŸ]¢&Óp:@ŽQîü8åBÐ~örþ·t8ßH¼”§Šº…jÿ­1ý@~霚1MœòZ 1 Ì ÿì] äKh£›bW ®žQ[u`4%‘"ʵ¹ÇL"¿)G”lNé6B(M!IŠSÂéŽÃ—²bT¢(¿”œÊAXL:”0å£Ñ0~)õ\ŠQÈrjÌÈÐ øü£þù_/!ø£9Òþ©g%ÊUNkœ¦ºp{¡)ÊÁšr qL…Li¾ó…¾WÈ~ü#‘`Ê49¢A]ñ·v¾ðBF ´é‚dðdÑjÛ”Ùºí€5R†£Érxö5‚„»³BLVcÇ‚O¿êB5&…o Q× ñÛŸiQ¦ï³QüÄ%Rh±üUÁá…,A]¾•sÛõEÿµ©Ø¿©f97RΟ”6\på|Và@$Fk ©1tÚá¥uäjÙIÐ`D–e 'dªPnR 'bº,S¹!´¾ùùZ}ˆ^}(aL³©*+§! éw.I1­n¥Ñd阚Ñ3¬)ÿ™IôÚꎓ2C6â¬1úá‹"°Bšá‘)pŒ|š|gc—íŸþé܃dÛ7Ӊ˺„?žyðˆ`Ô~¥)ˆ65VÔ^ÙÓÃNÑsÜ霥ÜR“¨½Z‚›ê$5üέ:ë9»sí¼—\;ŸÔ·mèÁ@¨¥©R"ÆW]:Ú’áNT¹|éåæÇZÿo~Dv5õJ®D Ï1mj£†b8¦uÒŽiZH'üÔ¼ît÷wî9ô@üúÏ7Mß4Èô6§©(ƒ˜2ŽDÆaŠò ¥ðñj9HUùئm=NSN+O¡¬D€I; ¿¬n4Œ8!˜ AÅvÄÁˆÏo ™ÂheDŒ!BõI§ ‚/âÇS݈ƤèùNÇOVé­·D·o såÛïÖóïÝÝÂv©H¯4¤B-¡¶•Ó¤U·¨©•ˆÉ1>û·”ãç¸Z|ûŸfO匬]2V.šqûÎŽ\F†Dk F4kâ¨αF£ÿ_VØ7I-U±#H0Y µx$sX…Œ|âúq+trˆwóÚåý·˜•@˜¯[µÚ(8ÄT”ARS¢ºžaïÜeÜïV”>“n-66MSàôÕRH•–¿¨,“‚ÖöÚŠû¹p{øÉ%&ºRäÚpúœÅ'kß4SÑÅV‡‘¥´©ÄzÈw÷ïc¢{ËGÒª%â—¸é8é+”ø˜µ ÈòÓýý(\ íÒFÝØbL‘cÆ)·z¸)£h‹Ú¯RBD㤠Á¹—¨P"ü‘é0:!~`‡'„—Îäròeq<~·pY|Wø«EŠr)J;' Þnã? z‡U¡Q.§6œO‰×pÓl*uñ˺¯K·Në¯/¶ßv⽆Y«®4²*-nŠ©Vm Å4•îcÔIÑZŠC‡Ó(Ê·]Ô8RŒ@ÑRø.6×ç[sÁûK©ÐçCêš«ËÁ¡Ïôéäb \ !wa–ˆ1'?§]š`²jYƒFª éª^•oO/ÝrKl¤àø¥´Wðü…RÂȘ8ŠÒ“2}ó—?ÎIç^étê!ý휳­6ÅdB@£6JŒßl¾?é×$ü«ÙÆþ N Í'?§Zù¢Ê9ÕüJ¬O“[FS"uÈÑÌ›)äªPhÏåtQX&A!Æs€Œ¯«öjýÇͱ–ýûçîþé¥04ãÄMÓo¤s±>¢Ìn„ãè!Pšá"dçR©ïÕk©i•c\+UÅï0Э-iNÝ IMtYùíTšBDl1RJ!:Œ?}‰[˜Zp A«>³–:”ËO­b–HJ:?…rõ aR¸ƒ‘]íû+w%žn4Î'…$ºähr¾Š¦ÓðDLï ê*š)²©Þ<„о1}Í*ÝB4L?_(eQfjÄá ñEsŒð!z`Ñ„˜Ðƻνs¾º˜nšîVD®ìÇÓû‘­‹ÐX¹‰´–Ô€¦µÄ÷âïEøë1òi¬oü4Í(LVb:ÉBXG¡†ëO4DZãP¨1wœ¢ßŽÝvÕŠC!NÖ¢¢‹ê¡64àf¤±‘q„М]·w¾üq2øh%K'Û4SRd9mލ©Š Í’çl µ¡:ÄÇÝöÇ?Bøøå¥D!YõÏa¬ŽP9‹2šZ5²68V«ùUÝŽ…DÓÐ%ÿtè‹x'Œ®îŽ6ARž=tøâd5S•˜üzËi!|Ÿ‡úý1â}üÂÂ)E(ÄÈL UÎ8BþÃV Ãhz£Ì–Ûôãeœº¹-ÆŽÔXÑp„òK6íyˆàÀðá‘+ÌÇ!§~ ñ#ë -sDãKO!rééð9áÎŒ¦…‘è¤!K ØYˆ™&2Ç2~ýÔÌh¢F ij£ï!gÉ;¯{¤Ünö•⪓êFÐp¦Šé½ \“˜@¦¥ñ9ìýÿø„6,`‰F‚Óç´iU‰Öq3üÆ4ûÖ¦M0÷k¡.`F§ZMíg)öÐ=¢Z¹;œ®IjëJø÷ÆBT„·Ã”Ýú}A·ž“¥FÓVè¤DcjL•#¢ #Ë„ˆÛ½¹B­¥M€û>÷ÛŸ–&»Ñ5ï»!r•c|j ñs* T)´F¾qD5q›{ñq*£cäxVøy>ÈÝ>hã¾øÌúAS¾Þô`,Ê·ÿÝVôÁñb˜IÉå°Êi¶@>£ÐñÕLøzÝéH M½j<4ðuê‰è ùÇ?þAßsÔýÍ©bÕ§­ëIi«ËU"D”£‡MµAÄûMÊ¶Èæ»'à·N{‹|*]'ZUŠ&n"ÔŸ0Y#…°#tùdñ‡üM€W~ej4ŸJŽQfµ’ÖŸP÷îSêêÀ¸óRa"pÇÆØÁæˆJI A¹68§÷ËøÈp⣉ð“22´Éé,‘ÅÐŒ@ |– ±3†TK«“­ZèÒ8G}š\|:ž:ñ¨OG9SBÃBF‰§ûÏ+Ÿ¸B ¹Bñ¯¼3`–¨%:Ú€<«~Ç}íH|â#Aù‹b¦ÄMEM§§ÏsˆN8G´– ¦Dœéø!)hŽÍÝéæR´uÀúÑŒ,ÓÉVÒqÅQŃ™=(ûÎ½Ç Z;PŸõO„ӞѴþE‡KAÐC„Èž7ÂkëñS"¦62jœ¤´× L¨žÛ¾ÂçØ Gv—á_šÔz¸Aß5SО\EçÔ¤¨íšª.‘¡¶Zù¢Þs_ߢºV‚Bšé[« U’Íá+m4-]"&>'ŽÒÁ‚:MÄo@IDAT›²×ý¤à9OÜ{/± ¾g@ûL¤ÒF²ùk‰ƒ™ ³8Ô€¾õRÅæ·ŸÚæÈeÈŒs¯E;¿*¥ %ÒÖ@bl¯àˆãøñ ’Jˆa!àGTg)&Á¨! ¿1šQbE…LÙ|Qú¬vqÚ!špeƹˆ§+~‹!(ËY•Ú]™ÁÙC šÀªD#¥ÕoD£©¨ßeöãù” ¯ù¼GH¤@H áËtåz ݳ¬>ŽÏ¤ï¼u"û;Gÿø«”ÛÏÚ@¨ kGàW¥Ï¼¦•¶åMÛR©i‰ƒÏ¬ºæ+‘K¿)š¯æÝ7“ú:Êõ² —¢ŠÝ²Þà¦áù÷}/Y²îÖo”žàöVWÒ,Ÿ&Ÿ )¾èðn(1­åä\ç¡½í¢…<©ùÆC´êHå ¦" iZVc¸QèJ:—:ó[€g¿£½we7¼zWÈJ)¹5à®dÉVW'ÆöÇÚ®/Y hÕ¢»ÉJ)êYè³×½âƒi+:J,W²ãCB¬”ñ…Œ5Ü4vv™išFS—‰“y²ß:Vçͱ®Þð<ú®Nçžhë ô-¤ZŠŽb?çJ¹^Â)ÌÎ?4qœÔøV‡ÀÔrä²ÂF3Ö[dˆhL#¼‘£:}S êZ£M‰¯Gïö³öM«RhºUg§Ý«aÑŠ"ÃqÖÏŠºà᛾pœÓœR!ÍP¨“œ6¼¢ JœòzF`¦tôiOÖ6GÃî¤JDËHqDuþúáRñ–$¸Æ$¶ou!ƶ‹#ä[oš÷[?ܧl §Ó:‹´§‡tò·Àú¤¬n+"n9˜L¨UÔƒºï<†ÝGt"8ÁJÛ·Äë°êEô‹®œó„¯%|¹:A0¶ ï|ùCÁ“Ut*Á1¥ÉÙÒªK–Ù7!Ë7*ª4°QbÌF[álúÂ\¾l±t¤`rÚ¦s„RCã´WñËmW‹†äwêÿ碣£\²–\÷nÊvÕÛž§f¿‰ÐYa R˜]ÅäåØ/þNË·Ü^ü…:è»Ö•‚ž…ºÛ@²‰‹Î„òK—­i¾ºmKǾ•øqB› ²Ž:¶ü@Ž|!eZ@œªÆáÛYhøœjĹŸOrEá¶É ó‰pôTÔT!œz0¦cl¯! ¿^'ü)2–Þ.¨¨ÛB­n ”ùÄYKFhK‰ã´¸·T_GKó´§©t ²8 ÎZˆŠFGH-þÅ:k lëJ7¾ó·¾r=Šê™ÂD”àG0Vš×üCH'BL¨má­ëéeœVt±Î@§¶)ËrzDp¼¾Uysã¦`¯ä*Gœ_:YA#ßw»nÁ÷dšéÖ望Hm« I-…RSˆÅ„È2åX§¶"‰9®ó7¿üñH;›òù®šZ…WÞª£ZU¯S; ÑÀÖ…iKI=ÑúVBâjñIU×”CGXõµ4À„p Ó)¥#[ôYnüL‡¬ñ5)å…Ú˜3Zm#W«, ‡r]Yà唳|Vº§”–\ì>:¸Ð(øé¹e„kØV(ÁjUÊ!c:÷."JÊó¿1µdTˈ QÃõ ™Ã§vÕ9Nˆ©iÂMA¡ô)³à”¿¿Ä‡–Ü}[²nÆ–0õê qT"”oÊ¿jÓ(ÍÑÆÔ©ÔãåJd1!ü8²Z@UT0M;“D1Kâ¨e2f||Qd¦£[oÕ¥`+ù1Óä‰Ì_KdùÀjñé÷”• Ñá׃tgC"Ÿ¬ïÿ×Q÷Ø—(ËH‡ƒªÃ*k©žj[”@ˆ\.¼J[õ;/ž¥h¦Ý#H™ i™ÚÏ@£Þ¤U7Å„X»DÙjŽߘÏÉ1ùp¹t²*ºcîåè3ã?þ·—,¾Q.Árù”]„=†WW?²\l®´6ª5"èÕ’ô¦FÊ¢¤D¨í|£¨ð"žµ0û ½3çÍ·/¼z#•NýL“SÝvMŸüÀZµ@S†ŒPó¦úákÆ3U(…g£›N¯ÿ(3YV )Ý8\ôCô P|!,·Nz'þlô1ÈVБNÜ8}u[¬id¾U;'+gT±ý¼JªŽi ?~ÿC_WÕUnÕ!Vís¼§¦g@¯\dì^úîSsJqNr„¤l4ùVJ™oQø¥›æˆe™ïÛZ”i[Z/ÄT ÓÒ˜r%ΆÞÕmYcir"t¶™â@$êØ™ÄºGeÁuɉ™/¥ªµ˜&>ÍGH¡*5©ŸD–؉H ÞV Å1¶w…( ¥Œ9N´¶^tÊù-«åÓŒìSö‹?ýNSÊõÉoi@Ó6Ĩ¢r÷Åj£äªžŽNJ4¾¾®§à¾ÜT¢m§ÖŠv¤4ÀÒ/díøFµ˜h=p,>§Î«…#½¦Bö!Îa¾0q!­·¯Ž˵AÂÑ’W~W Û¡DóŽ–Y¦Òú™¦©Ä®@x!Ášœ8GóF‚Ä1qÈõ Í´•jég°÷J+*7Yé¦jÕ†)ˆ®¥S€Û4¯ÿÞ¨½0Eô©UŽˆZš÷ wù»îh²Õ•‚¬–êFd½]%¥[&¤a¹Sü >Ã*†Q4Õ©©Iah9Èåš¶EíOü8éð1Ï€WXBÎÔQ‡Œ[U'MûRá8uc¬•B˜EÛ4çž«JYË…°úÄ׉6œp|8štQc4‹OÖ™á’ÈOÊ¡BË-ňß4‡lKvóúñUB:}r’Ègt’UËá7ªœVãDbB¦BL'üp ëĨ“˜é¼÷Z-OœB`Mª}rÖI4 ^KD*M_¨D4;pׯ´ßT¼nÛK“eâP ȱR;ïîˆ+'ärµ.Wšr”ÕeVÏF|Ì:9höðð®kÒ(Ä’U‘­‹s“½êœûµµ‚¿0LïȘ|L²œª˜*N™yoéÞ¦õ¥Û^éÈžˆ¯Ÿ©µçÕÛAüÿ£ìÞreYŠl ×oÕn¢} D_B<±¹t£>?çXQó’91éX™6ÌÜ#2ò²ææP€ÔŽ 5³ÕW–r²<°^ð˜|…a9)õò4¼uÊͯ]­étDRd è9‹ ðäí46Ã`6v^-KÖ¤ö;_Ù&e65âb­Å8n¹þ%®‘TŽaÌ_•ÛoYL`¯_²bö."…(@`)K¡¥œ,‚ aªæŒP!~%R]àçÜ™Z±\¸@{rÍ´¬åíö¹¾)¤¤šŒNjRâ×KŠY²:£Áùh@BáuqÊ î€0äã+ÄOvâ` ½ç»±€Ž‚!œí]/EñÆP¾s'©òÇ?‰Pžˆ”i™@÷F%‹P,ˆÃšVÖ­CÐ-Å›á凚)ø**VBMP;Ggiïé÷jo1f4‰%Ûlâøj¯ÌÙE×¥íât°vçûÓóo-8ŽN ƒy®ùÈïÑO£ÓsßÇ+b6íJuªšR0k08ZY¾€lÊ–¶0²€vqwQ`:&ñƒûw> øÌØóÂ$§Ü’¬˜¬¥ëË M¡ã0ÓÊJYY 'o²U}êm°?ºÇì}­¾¤È65« /¥$ð~¡áȦŠÜ;ô§­ztv+*¡©¼]¸ˆ);U‚b7‰‚oo5šHµhªxÁT+h#bYKUýCÑÊ? æÃ„‘˜¾’3âá‚RDàI@;„nEÃÃÕBF NH…RqXj|Y:²íàlû•R.Nªl`d„øâ©!»FR‘n?ùö¸“Ȧ‚ €ð÷ ¨©â¥4.UU¸¸ŽmH!)²ð˜h¬Ú@š®:M‹]ÌÐX)KY>вr:h¼l­ óx¼=T®$Ž”_®½]Cž›W{_rë’¯»XÀh&b0¦;D¶RÖR|®Öõ A`Â=¿3 /!k¿ µVèÞ"kÉ7’ <&Z„qŸP " ¬„ áóD˜%/ëëù_þ`Òıe– ļD=úùKòŒmþ)§ÏÃY8o#DböÊ4*x×A€0“â- ÄJÈZ*xï1Þ˽¨r3ôQ@\9ψ§Ù}X§ÛG£3ÓÛík \Ì|(yþžJ–ùèM³}Õh)&âòµÄéÑÓA!0‚¦F¶ýî¸7!„'†ïS65ÑòíN ^kÞ'eY·k|qAUJ01AÃÁì†ìbùq¬^ ¿2oÒÔ”óª(ãkÑá@iŠqdÄÓ—c$H"š;_¡åKž¥Œ_€#€·Í«èÑ×NS®—T"•ð‰ œx<~gl¸Õëw¯Äf]o)]õØ­’í<‚<)±ö-Š)¬cüFÜ~N¿ËtA`ñaVïÖ¤`B̺˜mw†x³ÑÑåÒ>Rb^-ŽëbÓÁéÎ;ý.ûæ·lRþ؃BÇKGL`~AóK黨0–<ÚèºÌi™á÷É×ÇOˆÂ—æDÁ!ðݾJªåºð5m)n‰píþÇ¿Ö@…&·_ó8+G×µ€éÌÑø-ý§sz=øÜ—×3šŽÉ=úyŸ÷iNmÇBˆÉ{;Ô¨îÍ/KJ,âAIÇäÝ-÷Íö…ÌpZòY'SJ¶w©‹û¥Cs38 ƒñ€¬-¨4ƒ%B"Õf—µ´‘J0áñávôÿÅ›ë4ÒÑn‡Ò$ÄNÔ¥vb×#tøqÌ …ùļ3½:„D4…° ÉŠ –lYLˤ6¤‚¦/þ•?¯e~:¼;óå·47˜ÁêÈ»^ë•2°ñt©„av²mj[ƒ ß=AK#U+ ãŠÛu'`É”³{§oàMˆI¶Ó(Ž ŸÏAk/ÍBØ!Šámµ„­2Á&FËbF!²¬@ B­-½Â-{‚”ZöMïì¹^ Z…µ°T•²¬™55mO¥´.@ǤJšX9)%J_ î[¤¼ÚsÛ?²%‚¬ü^(nI©ݵƒ3­y8TÌ|§êOžORV‰Ÿ}Ûuj{!ýí Ðt/æ@VUd ¥1BÄÜd1&ϼƒ²{ë±Z/E{Ÿôûâ‚c˜|jb4‚ZdëÕØ¦tbé«j0̆o*A4&Y4Å‘CšÁÏß9Ï\{¡cÎû4YfTÙfð,Ónc8UË Û2„ÅWîs÷–=·%¼Ýuhª,Û¤€àhmŸg@"&ãT+†˜ß[ïË7!ú>þ§ ÜRÓÚ5OcwS‰K d‹.õ…œÞžQth;)%!ª\¦çïLø¾¯'; ešíš,³ôTÁÉšA ˺ë«ÊZ¾ÏÀbÞ¨†I‚œý;¿v¥x©ÅôKÁ©•E`dy ó‚¼»(4³¾çÕ›œ€áñj®Õq]-)â(L"%h³f÷Zʲõ¯KU|xœš*¼y„ßu,Y£jjHWó¾Íñ"ó@Ób©|"p&ö-ò;¿·ô§~u·…º˜ªóžGâzÑב¹·øŽTVŒÀÄ MŠSö$%yi£ ”ÓàS†¤éTí½1ñ x&¸ #ó‘J®éÎx¶ TÅ7•T4 bÿùRŸz"ÿþ÷¿½Øà]*‘Ú‘(·½–µÖÕbÊêHÍS“ÅŠ›G€ a)·$ ‰iJØw»ÞÃü!@âJ h6åô7§¥.½ð{ô¨xj”ÀÍ#Î|¶ýοù¢KWŸÓˆ%Ò’¸.ÅðÃ éØ²ÖjÌÀÝ9>5üýÂüôïƒ6Õ@´S4_/ˆMÅ:’Í€/Fƒóé4ù8^#/ß™üÅ+E!IV¯Ôè'ÕÓ_Ì÷BÀwjeSÀ‘Š,K­ó çY-p0-›¼Sµ}x…Rm3}UòUa²^ƒ8F iD,ïdñ9Ü 9*Ô€o¸ å8c*× uÖ @ˆ,¿Þø–<„,o“ÌÜ Ãðü ©‘²döfy'èÈ꘎.–ákJaU‚‚&©gº(4˜ZöÍëóHž_dû-bRÔÒá_ksÚ;G;²NŒGÆŒP Ó'ÐuyâûÑ9>}dq—ÕkþÊ×µè<#ßÅÒ¦ˆˆ¢ªr4`šæƒØËß©=úû‡¸žwª•ŽF–rȆԽñN¿ëH \÷Œ”×0DI3•AÞ9wÅéàìäkª„Eð÷6Î?ä+OÖÓ÷ª¥Œm#)ó)7†%k<´îÃ[V#)d:L€ð„ðäõÑ™)ìQ@@};Òe!m "0B¾IXK_Ž_¾ )é?C¹¦8/+²jW@M¶ÃY#Û”Åg@žT‡ÀlK篜÷¹Íä[~ ðýV—>‘ö›AÄTá À#ÇG³l¤jù˜e[òt0²?$f½Ì Á‰ŒfBÙ: ¤Ú‹¸€ODmdA]š°¾€Ô¹ö‰j£k9*Í'U{©$ÀÚ„ð gxãBRKJ\UL%ð8.€¬F•‹•3œGúêÛ<ÅáÊÛgšd(—…»î–b…h‚ºPvKá0(2ïü‰…—º|ˆ©%Î 1ª¥Ëã#v¯7Ë Ž—ˆ 7mÁpÂËßR”gžªøL¡.ö«#A­yo úFUt@q'€#Þ)²Kã|T¢‹€~H’àË?–'îûS|²–Êᆭ@-ÐXYˆ}ÃÒ´pr(vÅ–¬¬FéÜ ‹y|Yd³3á=V.gÎ?NÞQ¤Ö9›SßYÝkA«Žv‡ÐŠMŽ hƒR–1_>ÝÒôãO· ypÛ‰Ô9¦kãõ›SGK´I•5Œ+»-Lç]àMÈ—°hÔd¯&ç‹áfÐzU ÀCêh¾ 0¾8¦%Že-¼Ü|éœæ§§ßw»“%˜N³‰•ÇÙ¥éÜŘª*L‡·T(…fr÷C·D´4!²µo³˜mjj8b&H_P¬Q± »€!wÑ–ªøÇ{(ØN*6M_±Ñm[Y¶lAÙt*¯SU\a"˜m¸ÙŒZ8Á5JÍ’T´M‚ßÅÀËæ ˆ³ÅtÜ©¡Í8ZGVJmdOWhüOô¿¬K”%ß%$ÂÌ éõFAª¾¨cåøgôk©$Á¶¯°¬ç§“¼M⽇”ªz!Ô…T¸T ¥@;A (àwβm '‘ö%ftªê÷–­Ôw>þû¦â'‚&i µëÞTmA#ø8‰TÍl*Ùö%XLNÈ´¬MÉRhl:‚Êq"|çÊ™{À'¥Ü´}Lé  '(•~´–¶ÓlªÄ¦‘p";Òïüáÿãt:Iʉ›Äî’Ê#”Ò¨“l€ Ù¨–h[Ú×w>þ{k§¦O!³dt¨9 ¬ëԢDŽ ÔÚ>Nš–<Ð?Ý OÍ;´ßpÔg5ÄAµY)ÇBˆ ÅýTÓ‡3q#!´„¨â‰´YåÌ’!{V¬PÇ‚¼’Dšž¸Xà[bBZ’²,ÓôñE .¨¼‹pÜÔkܲáøJT Lßãu`j|¦vNÁR/1‚)y£ÀÙZCÊò‰4mâñìs“ZW—¸ñöŒÉÃ,&K^m/NA­käCÖËûÓç7“bíLE‡ró[ê+Õ.è/…V 'ÒÖÂU%%èNEó[J-¤ž›g±yHu,Dj¤Ê ¶LYò–µN³Öª"¤ópA¦Aa ùH_ÎÿÌ~"hÈ6NÇ’õ0-)²çÀ[Æ‘êâ!íK€ÜlF8 ßRmY‚8@^6¾¥8¦ÿøï|÷òØíß]6½ÃRwú Mwç †£ñ›§½÷Ó¿ÿ-ÿ+sõ}ô¦¯#)ú<2¾bIª©à Vwˆ, +dßùÏb¼µ; dUÊ5ª|"ÝWíÝÆõêLq®æÄÒ.ÜÿR sâñeýF÷üI#/[̶ÆéØin†‰á›¢—rULŒÂ/¢†\Ã3Kx[€6 rjâä¯Ö]ÍâdwÕÞ½~ÓêRJ¯ê!aA«â÷ÐĹÏ'p|4êÔaªê¢)¶)3ÝÉl`sÒÇé(VÂËâx_ùvˆì@é¨2|âðûóN?¯o%@U!| Ú¬íoƒ–J¼3©}r>žþsuêKY¡1ÔºX¼Zž,¿™ã4Sµ¬dq…ªBxÖ À¤‰“Håðu<ì‹_ëhpupø®¦¬¸¾]8œ” ™2šÛ…-[ž!¢vRxE£H!]”Ç{œÄðãÀ…Àš¬qCjÌK•EÖŽT)4:TóÈ6:P ° ¾µe:JpxÖ`|9|#ù$Òh¬§Lí0 ÜÏÿç*ëâŸ×ü Ù†Ùð‰àlSb­-Uѳ¸å|h‚“&ÿý7?ª$nB}™%eA²NUÒ0R–ÀÈÛ‘³ê )¤V!ÏLÅw€yï ß™Öœš†8£Ö`!¤ c¯Ïž¤ˆŽ¼’vDÄlmDU105U¬9eq¤âÃÅíÝgL('n ž¹/ÿá—¾t¨Ñ×ÑíÇX A/xqò‘;ù¦ Ò‘eÞ{ɯýkjªž›1|+mkIñÙ]–f ,ïŒgfú²|gk#bœpOÿ—ÿ®ƒ©Ê4u±äÅd鈛¤8Y\GA[~7Œ&…FÂQÅSH¶¥ÏþÏ¿¸Éw£~'Pnž4R c7†F›ó~V1ã4ª!k§‹›è¾*æñ™¾pÛlÙ¥"¸!˜bœM+²ýæÔ1&Æš$¾˜aÂ15ªÅ}ŸbŠÝ²WÕƒfÙÄ46qäÔE(vyædy KÊQÐS X_÷úÅ=c †P ¯Ê’l§ XÜS#åš*Á÷¯@@æævµ*ÿÊ»ú;?jš6˜]àÛ£Ó®1\V¼-àT‹Y!NˆÁX×Â*'èÆ¿4gâ)†¦K{‡LV»ÎV‡>å«Ï#€C PªIzùá8å}/—ÕËÓÿ;¿SÓñ‘¹ ÞǃwYºÐ7å ¶cDP®‡EÎÑY#U¬ªb„‰ÐÑÙ–}‰yy3¤à±«…Ó²A­1ijäHÛ‘mŠ]׫»Q irL…˜ÀoNBÇßSU؈ 4j8åÄÛ»¦²úòÚuÔÛŽ¬*)OØ—ÿ¾ZŸ²éÛ/¯–uª²@gbYƒ1MùjãûÊ<^×͉Ϥøøy²n¼wà £±CH™ ˜Z}Û2dÊ]…N-©øÑBLþZÈÒÑ‚8PÌ' &î´+l0‚‰ß§ªcøÈwÁ8­µ €¦KÂ’WÌpšR€©RŠ£‰Ñ¤˜8MÀ.“Uq±ùjk!N­Áq¢)tñ([º*6ÏÊb†Ì7'5¸W…BHjË)Xf~ceROÌ õ_ÿú—y5ešl]®AÎ$ZÔ¥Cà¥lÉê¢ÈÄx±šOAÊýÔ“ÙJ™°-QB­i-kÑF™)á×úšå8HÙ˺S3•*H»ˆ)åÑÿÍg~!^‹ô§FÜÀd÷h@(»Á^,)HÅWÂ,A{±ÄD(‹PÈÊO¿ùÍo¾ùô· ßé\ӈߜ¥š°‘¤ “ lD ¦CN8ÄoPßùBß? ™ª)Ÿ.eM|œ“uõÅ¿Ïa^¾_b/²7ž Ë§£ø®©—FætàL‚‰ÖU+6I;Rf @|5yò í?ÿùO?&¢© ó1ƒ¸î&+U¶v@˼ié*‰¹‘æÉlüÎLŸ!(G¾dN;†€Ïdõâ!™¬%¾ |Á©¼@K7×>¦Ö–Í/ áÊýŸµÁ“«_$ˆ±º0âæ7·@ >3"ç=}xWÝÅèÚ+48]o‘ Å™ò‚é×T—î$Ãóð¥ˆÈòlå²N¢–o©PÜ%?õ×aéeà—ÿ»êןü+ï|5J!ß²±›Aß¶)(ÛðNCÐTԅѼ¸Ív€É>÷ý 0N:4Ûc§×óEwÙšv z))n;M"¥. ˜HC®\à¹ùò )dþ‘° æ‰o£Úµ¥^l/lÈ]G‚+O¼©Ú#$2”e”¥:%>C°‹_ýêWß|úÓôñŸÁÄ7€ ©J–G‰ CÓh®obû¼ZˆÏþ/p¯£7yK:IÑÜwg –‚Ö‚â«âqJ^\RŒòý“f½{tc4C%¤“•šø†AïŠs÷•O¤™ùvGž§sκ®Q›RÌPÙf iI¢qù¶­Ê2¤Ñºsìb#ÀÓ\ª«óÙs[:/­±ƒXɪ¬Šï&Ê6Ï®§ÂZËZ⻞ÿ£¥¦ýÉ¿MIy1l€æé©AÒ’·lZUm "n n™fÏqËçÖ9t«‘²}wžI¼ ¸ù§¯Z åv1Ú˜X %í®½ˆ=ý›Ðûãp^~n]_úÚñd›Ð –š²‚ön)°µfScáÍf×pˆe´4xšA]ttxÒUâIgS‰àem–>¼@‹:Šæõj<ž¢Áqª ñ‰ÄÚR¾axº=¿ú¸~üQ®ÖØ…©ñ n›@‡ÁÀ{ßûi‹emć}¿†Y:mÿô…ÿòLœ$SËÒ׫‹Õ0–l1q±Ù˜±ª²|d>©hãàûmêÉ_%Ù¯W._ ‘öR‹:·)RÆËB¼I$ZˆÃdR8‚¦³¼+»v°D€#›aúbR}h“ÕY _aãUˆÜx‚D0#ÃËÖEÜÙÂ!,ÚWÂZ=ƒòØ!¼˜…+®¬%ÏÆ\|"MpD¯ÏA¦ßž¥€jó^bç2ì€_#"DSu@m-¦ZÙÀ®„ò ¯i³¥™§£Ê£êÉ D\­{¨ÿÂS¬ pó·âgŽkfâ”›¤F8RãTbHH‚ž˜uu”—…¬ãÕá…óJ«…Kï¼öÜ@=Ah©³B«l`qƒAÄk¶e F ÁQè¹ÙsÁwmŸ¶üGÔ+ü*pÑÕ0qÚæÎ„ìýXRÓÈ–²‘6°‡xsvÏTÛÄRuÇ·…nSùªçéÏ.ãå}ƒ±_ÙŽŽˆ.š²Äyà–âáÍÜ$<œm0ØÓßçzïÜÏ?ÐG#®œgmöÌqR‡÷±@Ü€ @NÍÛaÃvÏO߇\,ïˆNæùïì×&þÇÀ4•˜'©k‡£Ü§“>ÒYJ( ›oÎÊ;Cn/1æ“ÿ½ îFó´»zu8bYæng@v Ú^xx…bq4ÅB(Ì,ކŸ‚%¾T£–Uh)Δ;¨{y„ªpôâÏ ×aÞÅu¬)#¦oHUÅ®µ–æ>¾T#Ñ@–¥++®Œ´ ¸*Þ²‰õKDUA% l‰&š¥·k¨ëc…ÈÌçUäñºƒÇ¿ÏpÚ_V'âYFV#%áÈp|jm^ ÔºX*¹z>®±¥a|t• ÿè5òô7aœµ£_Ü´bAúâvg’¶`)e)ó$a-XËÔÚš’Qx2ä}l%“mžH×H ;©ÝX–Qƒ†Q(›&þÅ=²~î_)ý>æ¬ð{3<1sÊRc‚ºÐ„‹;ÙâÀ{ ŽÌß9‹áÈ4Û»X [khKWÄúûq‹žþ><ÿG`R>þ§ÀoqK^#]špë+E¡XÀð-Ùžþ^~_òÇHá_y?¸ùÍÝÌvxjÈwÍ–,ŽC–u,Æ t_- §¿c‘òšòÙß»rgõÕÃ}iã•°R FM–Žêo<30K)LKrµí+Dà{RŸlÖ}²§¿{³ JŽÝ®zÕˆ¶ù‘•oózóìèÏB+)¤ÆºeÛg³ñ†aô«ÕÌ/eS-Û\ßnqȧ†ãƒ˜Žô-ٙ㺇1Py¾à¢ü8‡¤cD(0§ÃÇ4A1š MåâšÂŸM‚‘U­)„Z½¦LŠx`ÃØ©e±Ù»‚%Cð qN …{y<ÕéiD¼©šDÜZ t™ÕÚ®œoâ@â“A…Ô ²m¹@\¡-ø,b ®#ÄcÔMh0Sù¤’ üSóËŒo ‘“µwL±BfÔ‚²b}u´d²–L¬J–'åg¨ýòãéo°çÿâJÇ$M˜):64Rç \G±,rWP,ÕM¢Äö÷ô÷ޏgªêõ•§ƒŒFV÷𶻯ƒ3åRHG39D!³Äá!1)@ªEðo$æLá'è•ëÚ鉮TçíWV0BMá:Šyž5v„ù”‡ã賿ªörMtÎÍR_š”^ѨºX¢97 n¶¶)ËÓoZ^ŒÈ'õ_y“¬Ðœõ¥ÐêeÙüN[§,;ac÷ž QÅJ5y'àû­ŸŽÇ„ÖhtRÀb‚iñ k*`í ͆#æ-™€¡)l‰ïNs¼ÆÓIMac@e ÷ÓŠ‡HMý†îcLÈ“TÄ1yÿé´YHÖºñš­Ý̲Ñ®‰ÎÝ%PîRÿêK¼aü*UIƒ}ôžþ¾µàÔ‹H÷¦˜™ÄC°ÏÉî>©R#3øAÌØ¤îm-D¼ƒURU‡Òðiµ Í«âñD‹)E?} š*ˆØ„ç#^ ‹„7êb)¦f$°dðhMS­¬Àô¥[zRoìvÍ·—HÝS3C3ã °–ÎÖ<]ã­]¤ Ç„DnGm$ý†Ä´|i”i*ÇlÂúNvœ‰¯*[®…%))å©OÉzFôô'èiÕN×ëåœt¢Õw…pqÃKáXv\†©{ãh q8átŠ˜©²Ô¤öK ‚?øñ3º š'&M˯Ìc—µú(Ùœ;7`çÖð<Û0ô mO¿üôKš›êã7æûH.–· 3hÑQl*²º¬—*OCvpNˆÃ ¤\S/ ¸ ê+§óÇÇyn¤"“´…NÒ¨ÀâÚu8)¦¤“`»ÃIY¶/¨!?ÆÕt†ºÐMB ¹Ó^•TYLq“ „둊#uÕ ÊZ걯ÅR) X-|KÙ¡.!ŽTï[Ž©*@ÔK–`š‰ŒVRzáç-G;_Í´T,`K¦²jÄIÈ[’³œ(š%SK'Θh1=ÖŸßÇ1y_è¨i×Å&•ýH ߯¤Ì™¥ÓFd»¤®¢ÇÇL±^_}y$âJxêGOdAÛ©ejÊÍÅÇÄa:ºZR–¶F¡IøjyÙp“ ˜í‚G{nª"S#wÇ ¥ rãÅ4Xä`Új1À6˜ÈžþÎêçŸö˜ØÌZ0%/-)dâÌ0ZàÇ[6‰ì%|”›3¤©t¯ó‡'‚OÁf¥ÌY¡”O¦ž¶}Æ—õNïZ«"[»'ß ‰(éOn|d Ã©©^ø;}S#žÏ DŠ1qÔ∇—u&†DXÓ>û{úÇLSÓbL±½7Ÿ¸.•4¿ ñÔB"WYQ6*…m¡`âÈMSË[—»[êËâ‡eñ-³¾¸‹á¥dÍ ‰6qȶ¤liÔÇOÅÕºTÉ奘•MÆ×ŽÃÂmµÝ.ÛAmßj1_šÁ½ P¥…‘jd†3ôuK‰Óé½–J!kŠÏ”³fX`ÉdŸütHYw|tézÔK¡½¨mË4‹Í ˆÓ`š§!`@U18ƶ<3]w!0²%¾8þÀj_úº£)l6ÍbʦJS‹qš¶BÞˬÂ{G:ŽÅÓ¿wtgî’'xW»—|7gÝÛ;q ¾%A©!Àm§Âf3 ²É›A³¦M…ɤ¨ñ~öñ;»Žç~?qÔ‹ùü÷Ow¦+¨„Ù ù'6•¥ìÞ–Œj©ŠÁü:ÚOÕ>ø{xI©eÀhmç'å÷ÉöHçSY:RMe™9Šp4{á‰÷ƒ²cñ•N9_mâ¼Âwc¼[v!bÖ !©:±”Òº` SÝð͉á˺ý>}_Äq€ûJ„ i¾È,µh_á–z1)¸ Á´+6_¹Š¥(Ð •¤L¡Ž–½ñ ª¢#(®‚¯Žƒ²,¨$ÏÜ6²‚æÐ³ÊCp,ǼºýÏã ª™™P5k¯€bË;Xªö†«Ïî?…£Y>ÿ Ðvva™š¿Ë-Ö]œ~ââu¤P;A†ƒ`ì}VUÞggR²<&\yn÷ýz-)ÐßÞ•ßçA° ˜¿+¢)DœBY ©ÀönB?ûô³•rŸ}Z¤)Û0øÌ ñq>‚g´*jZ ðºhJ¤ŒpH1o³ôUIyÄ÷ßOˆ{ú«e²˜Ï߇Ìo`äY…ædÔˆKñmÞ%3 $|?ˆy ø”&*©c:ŸzjŒÀ8‰Õ·»ZŒ`)vhëôÔ*KUëõëÐ,ßqèwÿéã73å™*²avÛ¯{¸·d´ÈRZ¨Ef@ˆ%‚e…ã_”ÇØRÀpÞ’¥95|{„_ÄÇouÁD“êäÓéÜ5_­*`4U–áÀºXžÓÌÎâzÉ¡V&ê†n¦˜Š¥˜”}Z Ü|Ú;AjœfMg‰|Ç7núWÃã:Y­c4\¡FZ·Œ lLÛñÍq¯ÿÃøìÐÇÌÀ™°Ýчó”e_÷Rm¹©dŒ—e€¬ 1“M¤T±TY„ç†Ö­ŒV;–|åÄ)CðkÍ•ðJÜa‚²•½‘{ZõvÞ¿úê¥-få⤞ÚÝ¥/^G^—&á¤Ö’¦€ÇLaA}7ęؿ÷øàß'G?³¸ÖI5¼.hÈ6ØÑY~4÷¡BU Á|ã)7\‘íîmf4íüéq¦—”g®¿A O\Œüq€很P4F-d Úf')nK­òu‰`)¨‘^Æðp㙇ÚQùðK|%ñ[¦† 7y}IJµ(æ«jB©§$òÄ[Æ ¿Ù,™%ŸefÉÑ´,xÜ‘r­Ýí6º¦W¯Ò–Í1r`d±®Lö´½eùÿÖ’"¢0é(Íã¶æªW»ŠìFàÛŽ%3´Ìûk¿¯þÕ¡?øQe¿íEL°S¦iYSHî¼Èy:FÒ—áððku.C… Þñ¢QfÕJA2 àJž—ßâ¯|¨ ø&1j –bRˆ4žeq¸1,•4ïÓ¨ÏþƒˆýòãB$މPœw,1¥¾2ã©ê‰Ðx˜£×ÚELM,Ø ¡-ÀB ^yx[ðñv¿CÞßèZSVÒÕ¡ÓÍ#øhĽÀ›“ß.€MŸ±Þ^¢pqÇ~Áç¶ôç=LÊcËï-ýç($ˆƒ õdŸÓ|MñYƒ…Ô«Ô8Z8`æÝÎë‚·ôèïM±;Èf‚.=ä‰a£Å–†tæ¥èÔÂK;œÇ‡ x1ë4Ü~Ÿ>ýýfÛïxƦ¶QudUŠʼn;ç~{ÄIÁ•@š„W.ËŠyK‚WRŠg-ï3à3HU8k G€ó¥øSs™I*ì@,íº!)  Ηäkqîãõ<•fÒ|5‚ÞQ¯Öë¤p´˜¥äÞµÂZ¿ô::5:¼á+g‚NSÊY{jtõå-‹{™U T(ömΧ¿¯¾P÷Ÿ/íãñm­Öí‹”,Í–˜q,–,g¤è†‡4ÿ88 ˜©–â^>UëÂwGÖÅR@3ÐRÒ'âµp34 Äœ:6¯Mûg7ª~ ¦!lSt¾:íôy­  ÐTˆvq\&š8]¾QB¤Äª†[V’¸¿©÷œíÜ p>äÖ-8ÃiËæjž5¦jŒ CGmMy8ÓÂH]nA'nfŸdûÒaz+U…É0q S äÓ1€Þ‡Ú;fS¹¥Ø.45m8S¡švY oÙ¿–â1ÛQ3µ$ÕKïÉ`¤”wMÅ,ršb tòÆ+h ]8ÐÏÈNìÓOoýñ®Ù&¨ãâíW/&`$‹Éº:pH 6¶!¯¢s›Åi‰#Íð¤üÈÀª"ìd”7‚ l¾ÚÖ(ñpˆá‘!Ì)9«b‚˜K­*äñoú‘ÀVFÎp3z›w¡aUôº#ÇÏÿºUð+o§ÝùéèË:I:FE.e W¢3O²½;îá…Ì(ðÈhq¤¢¹|ðß'~7gqT¡Å¤¤f±ì“9e½¶ý”-…øD”Ûˆ-»4bfȦš,Zü²âÍïÑoì)»ÐÞº*ÇéT ÔÒ±S— Âdß ÷ó¼’ô2j Þ³LÊ’8e1PSw£Ï"4óx°G±mb&KgïØrÇK³Fª´³T{æx{yVBbH„nuoêýèïÄ÷9\EÇQð´Uˆ[2)ån/Òço˜t”+´ { ¤Ä l‰Ùx•4ƒŽFþDʉ)¹›½i¹@üJŒGÒåÔ·geLf¼ªÊ"0x—ìè^ì(JYn#p Ùhã· kËÚRVØë% 3d1µ™’âpåÔ” ÈJ¥Ì!h•ÎiÖX€ÔLcãEåeŠ„,ró5D4¸âRJd½È½+—º[µnhbŸA(+¤ÐT…ÕZ"t@‚ð¥¥Òti{ ÜÛ-ÖË'Y·‘F^”Õjmɶkñ5IK±Ô…”-ùj ÆcnSÊ¥,ã) Àdéõ¦<ó~P_Ù'æÕ‹O')^;…L U—¯©ayLOgOÿÞ¹ ãÑï•_¶ÙÄ-TÒ Oà`MKáÉœR^Þin‚.„1H ŒçÖÈ`RµË+”âIÐEW˜¦{Ï䆱 į„ ÒÉð~ô˜— MIïЖ¦ I‡ D¬…*óËîÏl<}ÖQ[ ‚^8›NìÇBÔgª\ G7X"SŽLÖ².˜}$ê(¼ 1…È+„ª´ `¯Ö®Núï|·‚aÔêh#mmo3N@U`]æÍ¯—w©O?½yãôâíÆhr|…u¬¶xÃ7¤¥€Ïp¢)1°'Æ.åh•Ì 5ƒt¤ڋÀÆSè`y¦c3Ká(/¼´Ï„˜b`‚!–V G9ÁªbV8ܲkQÎCÎí;6HÌ ›œ ¤–<“RìŒê!ööÞ®Z*w”˜Æõ´eÿÃ+)?€z?3]‡¥H ˆÐ,ÃMe ìJ50ß„8¾ÞºuŒ|göy°ž×½sì°l-ý¼[MwVë˜deYÃ(D GCÞ –‚ÑÈF¦l:h)C¹BÍËž½|ªz"ೆ!¨6qŽRùºH…·5oØ{íyÝölMË+áÍ|õ9'ÐgÞÑ_Žê-{ì× ‚Ô\2^y½ÌƒPJ Kú‚<²Øü6ëÑÆvÑ•_ü=,*Œœ²* ˜U^w\LÇï|Жu;©µ$ˆ` Ë:R†#¸óý·½•ºÛû÷sKÌ&AK¤@¡¥Mµ/à;sç(dĤ]×ÚÒq)‡ðy Ù,]S“$îêIY2„Èâ kÚ^IJô5âz£}7UK[³M"f³…ª’¥Ç´ÌgR¬Žú®…÷;ª¶ŒŸN ÚYŠù.‡‹8‹´DKJ ¡ßÁÇAJmWÁfãl’- ƒ6"–@LÚ×—@IDAT¼*ÄÄi SÃ_™EÃÙ«Í6ˉ8D¹ÀRÀ0O‚¯e±t+ÛVÌæÞfj¬%&á“âñ|ا0'UU8ìv|4SÝÍB¶IVA¡ °ŽÑÄ>€¸Å=ÂWXàq`w¤,CÖ7Ó—¦Ž‚†o;áÈdyO©£,£ÀK9=L:¬ç;nyÏùˆñ=U;4Hµ<Í1UIÕž™ÿåSÕ¦Ôâ'[GK Ä2 Ù‘´¶4Õþÿ!{©{R K5¡ ‡¬¥*˲—ÌCJÊ[¬'ûóiuôñ@¤ DkVL––¸³íqà!˜©®øý=¡ö-í+Á†„¸u•«¥ƒÏgŸp£}ôwfƒÅj—Ì×—™»QG¸ÃôáC_d·‡Ö·BxL7Îôï}ÅÈÄJÊVK?¤¥¾ÂQwD6è÷W‡x;jfš½Bï .µ#Rˆ‘@Þ‡/ëEí5b¶ Öœé´G׎镎-[ú^è‡2‹»,Ü—}±3²ÑZRÆ ôtѤ€ÌRÊíK,0ƒ”ž‚ìUô¸:é»×xYK8ÁÚñ¬*‡iJ“‡È :K«£ Ä¢ñ¬e˜&rËÃ¥ÎW£ºcZþâ÷¿ÿ}hTqTK{àñ *ã-OåÛFLU.F`sˆ™ã[?RL­Í¸ ëȻ̔{ÉÑT‹QÞen˜ªx)¦¶“gnJ·ŽûO¼Zø­ÓCA•,)&%¦É³úZ ¤ƾº/ñë+LGq¶t-cVËScu/Epâšn2ïøLìã¤J¾2´Ž”Ci)VÈ[¢EÀ3üý¥OmKO+¸zU¨2 ~ †dÃ4é„”5­+¢ä«Qá^6È{æ’Ò·—ߪRà‰v€æì«ÞÎD¡‡¬ ݯÃí‹W« Ï(ðÀæ/+U‹ nÁö#X"¤Ú¯FãCˆø Íã Çô>êfBYÓ‹aòÕv’N×b²v×QÈLÒ ïÈÚyô3/Ÿ!Lâ­ B§M;“æJ‰¬'“ŠcƒïzµÔQœû0[õe Ö䲌×/ë}hâ~?0³/Ä0×?^€@œ²€2Mà9—«ÄR ¾KQ¥oµF¡mVeªZK)‰‰³“,ËÃqØâ‘K…7ò{¢ùXmY{q‰û`‹Ö‘ªU¡( Úš™ÓDZ„3%ž¼”+™Çñ\“ÅAnÂv ‘åSSën4^gå¹ïùåo’øR“*K™o îÏO¿ËÚ¬»Zá¤ðSI-wt“xAîMÈÃT¬uåø3H3”JŽ%ŽfÉ»¶ÿôý)‘û¯¬ª2%åoÀ‰ã»¦ý—:q"˜ÙG§×qŽ`©JÐðy‚@©kÞÇ'äî«zun•ó •@6KaˆÐ«¹ã°Êù&¸j¥”«â¥XúRfÉÃC´H„ÏB.îÙuf)º×B””ŠÏ'R•øáñZøÅþðrÕymš ì¤ Ô˜z…Ý JjÜLwÍU)$åÔœ '‹W“Íd}fg¤\ï(Ë +gY  Ž¤ à•æâ±Åc>ßþOw‡‚›U‰òºÿºœp‚LÙö d %nqÚ–¦Åƒ`)Û='ÈdÓI¨ä-yȲ0)ôµ7$¦¸}©+±)»¾`#ݽo·©ÀtÒ×"„__~S‰yFõ$õªs>õ®³-PX\@Ø6–¦¸¸¾2|„¾ jŠF7I×Èv˜«æá©Úÿ”“Pˆ¦…φföž§c3w!´f©aŠeùÅÂÐüø%@­yœªª¤L%È€ÌõCœÏ?ŸxH–Âý5¥nf…|c@,Ó4†]|Èbzާ‰©Ö$U94-t÷ÝÈ5õ èˆü~²òõ…Ëvhã‰›Š %ÚÌR 4†÷EÄxï~«‰èÅŽLPm>Mž™Ù¨†tbÞ«×ΨfvöÏ øF2°ÄÔÈM iû+/u\J ®]j–vÔ¾H¥ÖQ4v:š& ¡Ó0x ª£u™’&”*€ÈL°%ϦI m#R 2Y©wY)"<¦¹eð§¿þõ¯It Úôv¬Cš@}õ+ÔÕ2ëv‰¼Óì ¢¦ËÉ»]d•»änÐO14w¶ûÆ­ÖZÔÝ„ÊõrÓ0/ Ö®fª¼ð<è4ƒšBúÔ š¥Áš¤Ž”YÌ8Ý1u1Iåºò+TKPŠg²R±  ¼¼f6Þ¨mÁH/Æԅ)¤¯Êݾ—°å dTß´¼x‘à &@cFÚ0Èð¶#…&å!qt²]Üø»ÉVe$B²n31A…ðû-1š.¶ƒÐ£¦J($Xy:ºcnxA1ÎŽ“…7°X€CMÌ¢µ)Ëö…“­üâ² -ð -±íÿôç?ÿ©=TCb<Á;!˪Ôk_Ñ:œÎZ?œ–â•t"]±×Œ;Õ}Ð6î^­ À"K)g¹Àü\¬Ä«Îíîµ!@n·p|Ö.,M"V;¾*ØÌ@îãŒ8~Êhd.Œ¥Á:^Êä²pZH}•³– ˆ(76²v|"Š-‘y‚¯sÿuŒ:_µ¾ý(i#}ªûÓŠ‚W]â†ÑT€¿¥MªIÄÖ£-˜›Í÷Œ—ÿ$€ÿÜ æ¹ÊöÜoGv§…v²Ý`I ÚÈ]Ù™À•(T¢!˜³«iéÑæŸp1ï…Jú€‚æ.ÂÏèD3•G>Ô&[#Ëæäë΋'° “àDæÕºˆ®×oûÛ½µl©º(gjMb¤’Iºôiek*ÐZ µš²²ÍÖØR 1e«âã ‹ýÊçâö2A¸Ž!ZÉÕç¼R¼êÅw¦óô^îÅëÊꥣÉmGÜ0ø [ê«6\@X f÷‚~¯÷ ñk-ÕHíNVÀ¨!ð1¾{tÎáø kÑÍS—tp©Õ®*~†ÏÔ¶ ¾›!qCŠkMª™›GL¶Q‘ÑHÅ!b6ÉOûÛßD‰Ö©BØâxÅ<#Áv=puÌ@q£ˆ;Ž^/W‚‚*Y^Œ,åÎöNàB@“ý¾Q`î7ãã-‰°3îu™MR;²ˆ¦HB ”’ížs?ÅLJŒÙë Ÿ,\#Ud^4`§ô®ijø¾Àݲ–b–Ž¥’@¯·þW\RøÊ{\š°î†!nž;Ù´>©ù¬ÚƯÃ;'cÉëÕîjm¶£ëœ¥0K [òÚékkRÞ·¼xï1†å7Íðf°‘óiÿú¼¯EM‰K!·SíšpƒEÀÙ. fÃT«…°—r‰ý:aàŸ LÇlž¹¼˜íh ”wŒÅtêeÉ ±Á&4ª’ ðQÉËľ)1¼®,Ù‘5ÆR¶‚ ¤I” ÔH‰˜ëS Ó·Ö¥’â ï{AØ©mx‚Ú1åø8éœfoßñ¯žWŽª5šrÃà7"Ž Ü’… v2Uc è;+åžæ~9õrê“—÷±ò橊”»Ÿ÷+™`3Ø…È@Ù L£í:"…\PV¼r¦Ë„Æv’@ú˜¼*ËJÄL_dH`äƒ[òh5å!,¤£Ð1¾ ì;O!KD¼’šò@jL­%ýW¢ 4‚‹)ð-íØS&1rLB’í)¿w‰Ù0d-Si€¼«»Û M›³€‡ãdð¥™G-o‰ Á4­e4>‹P–) ¯#¯Dª€gönòXj+©DÌšÒ©Q{QhãIm¤æ¯¤ÃQDPËîÓ¶D¨5AŸHã¿«j’Kïñ` iŒz%k¼ÔÖbûÝeÅTrï[ }8s›µx²|ü–MR–?wÃL=ƒt¬b`¦š²p9± Ø²W"îº F¨GÀKÑ$ÄÛƒïÑ–ÝÔÐjŠœ/ÆtÉ"SË0Ü['.…Ï“MM-¤.5Š“Ž*K¾ûÒ7ïµ—A¬Z2$Å[V(F«)…¥ x–Ž`Êbˆ,YR¾v~ÏabUéÄ¿wGfpå¤vÖ4•¬>¼mƒY2K`² ˆ(ÙØhÓ‡‹CçYš½™eˆV/c¿å×H¹ Ä;œŽH¡’Kà¸â¼ò*‚PyÙIu¥:Uå–‚^/[B˜#BVpUŒÌëâVwŸ›3¿¼‘+¬©,M)¾8eËæoxàéz™#…Ð M(YIËf³'«ª‘*Ç_IåÿJ>>‹áqx»àž¶ï.GµhZWUwË)x§±F‚F­»á{%ÞH²!ŠY{L¤Žy×îÝñYšÀd‚,æ“Úbck*;_Ü‘"¤ G 3-Òwn-k:µÈ8e»£pà÷ñâãÔŽ7@âç¿`÷šrʺóì¡ òøTjÏ_G¡—ÂýJÀ-‰T"Ëè¨ê€úԔȲ ZV!“ee/3´Ä©§rú÷*qsÆ¿›¡—G:²ñ ¦?/e¼D ì^eIÍi ¨mB7Ÿ]¥çÓY',P…Ö -Há~j¡95à5I…8d†¯&<¶Ð²I¦“¦Tf€‚ô#oª&±\¶”’˜‚Dj yH¿½Vî:îUfSÂÏ´¼ë7Œ”.m AÀ5J¡!«­ ‚àpî¸ -3MÞ’w‰Xj‚˜R"v¿5C) ¤—ƒ˜¬”ÉÂÛTââqB,©©¢Ìß­ŽM!d¾ÙZ*¼£UÛ„ôïûŠÏL¡še¾­YRvdk˜ôÅ”ã@j÷ꂤYmCF«P Øö¸à 'CÀK ;já²5²µ¥âÃÑŠ ÄÀð!À&)4A—’·”e‚t,5V|±ÎÀq¢UÄ#§Y‰JÕôñ  ú*«‘îíZàþëDhu˺ t‰ZÊ’Ž»•E“ÚöÓáë«05÷ D¼m4f¦VS¾’öY¦¦qøŽ¸©¤,ÑÒ!Áðb8_SàbA_•ÇljFY;dA;E@N0²™T„•·û¦ƒ Á(7RÒf“&µR|½à‚@n¹‘j§qø¬Ùè…t&–µ®£%MÖÞ¦€¬îù{£R¼*žñZ[nÔåh‰@LÞN«…l<œŽn²‰ãÐ4\œ'T’ZµM‚ ·¤ÀV(†Á²»/1Ĥ"P†-™€Á·‹Ze¬©X¡Ø9Ëðb».°Gå-ñ³+Nœ2~¸[´%½£lw]àCëú?:vP|¯Ç.®d»k³ ©F!$ifDÌWXl‰Ÿ'%àÓÇ¡¦$¦ªE…»ÉqR¨P¡B [/-š³¸T´6¨fçœH»xüRRSYÍjßôâjœ ŠÉÕR˼lº 6ÈRV•8ßå÷iWëJ\]®só+‘µ¬‘r†@¼ò˜²ÑÈJ-So±ÖNÖTbtÚ&\£ Ñ’¾ YA†¶ª˜Wéq˜Rµ ß² }e«jï²R˜=JŽÊí0•Ûo}Ñ”à§9šìDb¦Œ¦¤ÃD`².üjò8UR!¯D¶ãTU¡áY‚œ}Câó›™ DyÓNad"ÍP!:½½2ÒNð>jË"Ã-;†×´ª²@K1<¹ ë"¦–lµUARkƒbASUŽœ,¾@JP_‡æç üN¯x×Ý8µ3 ¼’¤¤XS]ù‡²lÝõjGâð=²)ì ¦& b°8é(×:AÙ‘ÅÓ—E³?j˜NÙÕZ²Ú5† ›6‰©]…q˜r†³Q-1í¥ åȼe|¾ò¼.Ä™˜MP\¡@•iµë’ „X)A%É^™s{o†Î|D8½¯ÓSžxU˜”‹ùkZGÊ•S>?YHœÅµ±â¨÷e×RãÞŠ´±Œ"K‡š9€–éK…¤ÜÙõD•D·Û–)7 D ¿<A¶áÅ;K„oΖZdø+Ij/6ó('Ë.¥Ç=­Âä¥(¨-*®‘Ž™Ëæ!²Ùiÿfð•Ã,粤€âR‰”â-qz1w†‘ʤǴTR–¯#„BÙ&ï‘rl RJš¿Zˆ¥˜Õ"Ž"1!RïDd³)T¸ëޝ;œmY•v òÓ\ƒ§„w}+4Éî=)Lø.†7§¾¸ÝYR«W4Ëh©\ Å&.–º°ãŒÁ«å‰¯QÃóL#%ü)x+/e)àâD‹yïØÉc"ÔQI{‰Ì§àú¦au‡\ÚÇ©b‚ôÅ1qšÄRÊí„“Bx‡´Dj Õ$ aSºø¤&B3©ÔàL!:X²8˜áI…ˆÑ îL"¶Ùµãñ¥ðïT7C;²d#ŒãCÒÄáÙªè3µô‘e\’¶»˜ªMaäº X>þ×@K·U1“V†z-YA¼½éTƒÚ7b£%—íGÀtÀSÁ´D¨KÁ}ž”y§¶ç‚¥ÉÛ3P#E$PÀ€<„ß`b“Y›jÚȲÌ%o0^#>â '+ˆœTËöXS JáDIªB¸€ XÝ[6p“@ªÍc& _#©È# l-Š-Gg¤ ÐM‹á-ùø¿ÃeŬij€,Á*Å‚Sp+)…sŸ3-êÂ#0LYË !Gµ…p¾8¾%&B‚Í0^’–&ß0‰tψY]•G 盇×H–ß0‚ÀšâŒ·L0‘&¬V\ÊRydUÍ •¾,«{&C€›<å‚4ÛN´|²˜—Þy%Ry©²|AµøÈ|Ó.–¬@IHÞŽœ3Y…µ|˘–BÝljVGÊðR yAÊD*O‡ÿÅŸþô§ÒÒŽÊ,ÉÕµ_Ї§d–•ÅmU =¼¥f4¾ ºS •]y½“G0~¾ ÙîB±£$kÙ±Æ!•,ŸZ-6•¹€GfÀbʤ*ÎRéë(`µ ‰o"h)°L\°cë^k±€>?dãlTËu©Pʹm¼ºX >Ó—¡ñIIé%6AKž™’bA"˜.Ъ xšøqxU•ˆ)£kÊÉxSNjר*¿LGv:@V °ŽÕ–ŠIdšZ38šX‰¸e2µu&‹30$%áb°Ô€,¦@G1µsôoŸá%ì°/~d­*¡@y­]Ì€c™¥V;BçÃ3xÃD؇\KYí¼¬ ;=ˆ%©<\9<3ƒZÖÍ<¤ÓÓž‰W>…{ PaÓ‚DÊã‰lYàðõ¢ŒÃ³¹Á’q¦ðÑòíõ‚æ|Ðj!›Bj›'¼Tjâįq~¼c¥/U¯”‹cò@–BKUí^,Î?þ»ü•ÆÆÈ Ú§Íˆ]W mâþPR-üà¨`ÍÄ=ð+W"kX;ß7!ÕRs²•ü[w·ckniºSÙú¹{Á'æ!߯¢©’ó '™äZU{wKòhtL´Ø}ÿó—²ö´PªŽšž§£5º×öQrV¢KÈ>㬘äÐ ¸c©q³¼v]5‡”™‡[9@|–øù'’ôï¶J¬ð”ÀÕþñë#V}/>ÛÜÿpR£·jCÙJn82¹™î÷r¶•`%íýR¨Ñ¸·aßšíC&šEÉ¿€kq$8ûýüpb â‰'3¢@~Í?ßÇ50t!†ÊMÄVíh =Y9 7G‹Ánšm#Ò«v©Ä¿þŸëxœÉíÜJãe¼èZc|Û΄ŽÛP¶3¾R†sÚYõupd®”'LÉ ¿‰¬ŽÉúôÇ俨’ëÍ/ôÊ1› g «”™ÈøÓª²2h<#cè»K-kW…3‘Ë]'<2·–E%€I?€co•‰ãëï(ˆ#ÓÛÙ ¯=g M×A¶'¾’¬Ôc2úJ=B·Võbþô_ÿõ_±¢ h^“šJÆ ï&d0½c˜¦ ‹T…‘0g‚ªJU•Ò¨ ع*@?^ÐôjW~&z¯é­íH¿*CÐgÒq «ö983Ác(Eª{#”üÀ·±êÜ`Õ9ÀíVž±^Êí™LµØŽskJG< Ü|0»{n rP® cD#âø-“[¤ÿqß3—9tÙ 7¢.؆ÄÁ3þ'ôÆÚÏ•Š^l ¥¨ÏQÐÈ4âv|ÿô혬–«=²‰cd;wYzß z>”@bG#ÖÕ,½ºT9LôÀF˜‚,ðdZD•aX;rß«d•Z€ 5<Û6F%¹U…cU¿DÑ1·œi4z„†*½½°–HJš>ÖÜtóIæhÃwP&íÓ†ÍÊp AV}¦!à¦*z1 ¥ÜP-½ æ ¿ ÕÚ›Õ¶}.-©TËz3ǧw ðÜbﱉ Ów$ä–T…³‚µ÷ª¹Í¶%] ¿=¾.p>òlÏÿ‡0)6#Ý~&í!Û¦oE“€–€»€d·õû[)Sjœ&«leU4&­×Ÿ2ž¨±e6B/F$È0¼.G澩. k÷ÃÐÏ<“¬ÅêŨ Gšöðiœœ Mbd‚¬ÊºD%-;LDž²Øžk!ØGàXIî"·ïð@æJ=²•šE?1&=­à”žË8‘˜ƒXæC\W‘ÄœbnëÙ6h -ó¬4%@Ö+¤Ñ‚p J!`žl&@×l L™­.dŒ\ Võmt»94ÐSæ–³’-Ó±Òõþas™R„嫊?ºŸèHž¸mÕcڰϨqJ}ÿ-SPbÖ˜7«×éú-ƒ'N&ÃÚ¾{ª¢£é6(^¦çCðkľŠJ9Äé‰Ü”xÊ" KUÀæÝ«Rí°AíC ðQ…ö\cd>ñ2F»YÈ×D #øÀ&ûT«Â"g€XV’g¨ WeBãh.€¦™g¼¿Udõ§¿ÿýïúér!%âU^ÀÔ1Ûc¿‚ ÙÑð)·¥Ržx‘¦Ì?[-)÷(·é¬‰§´=ÞD|  UÛDZó¬½q‰3—Uu¥”»)ÒJ)UÅzÓ`TÅ-~ÿ쫊ôš¦ðlhæWxžË1™÷»r¶aƒÌ…jwœ Ip‹çÖÓ ¤…u Õ³zË\ˆÌVëJ0^TÓ4OîGk¿°¦¤ïÕøÀ•Ú¾c†rV€ kcxbHYôÛCS/ÜbŽ€å=¨ªl= Aír2Ê +úl9`T±£°*Ð,% ÛÁJ¢RYib%†–É0}K⻩£YJyêUʳ®ª2ÁûóCCLÓ\Çé1•t <Ïáæ"xúzSÛªjw»KdŸ>\on ·ö`Þ’2ÆZcΉc` w3:¤h"éHéø:ÀPU‘®†§—Ó+!a³`¥ZìYWæ}dYaèãó¤˜Âψ#qÎMTBb8‹6©KÆxŸ¾9ZMiŸ)ÉZ†F)œ’ N̪#¥Ð(+!eÑg:¾Ý*¥Ç$ðHGú²krp4Wu%ÀÄ"*&Ró”×æî¢„çùV‘ M\N¶RÈfuw8ÞÐ~qñöûŠÃ„ F™ fÇÖ–i¸YÐ%‡„é d÷J Zož„ZöD°dûÜúùšÅ 3²F†ŽJÚa‚zó9ú ök§ÞHÁ‹t“¾Ld•vUÖ­®·{öˆ”Ú[FèB  ÐR¯*%RÕôñ“ö™€ ŸCeLÚªÒn‹Têάbhtñ™y;äŒiäJ͊Ęˆéešë¨*+Ven ÇÚeG¡EÖ’p¬‹æZžmÛ?}²|"a±lbSæ)#‰›¸ušyíªJŽûëÅ#•d…ëTM鸭’ÉJ³…ue2>e}µ”ZƒXoSkÀ V²%åó_õÿt‡€2—»‰*,NÛÏßOáô²p½É88 |].ãȰ)JpΰhI ÎìHbPI19PFZ²vVb;#E†”°¬ÓÂÀ•|Sø7®ON©#žÒ‡šXN *XÉ4ÍUmP# ýW´ù2HOÙc®wÔùÍÔUK³F: ú–a((12·VM¦ÔEÒ$ Ë"+ GXÞeᔕðU;ÊÂô¶C>ËkWõ·`JûáÔØÎÞ/è‘ ‚}.Söbdº0·ã`ÁŸ@Vr¤—¹ÉuÀ­ ˆ¶ê×P$“|0Âβ+è…å¦çÖg 2UQ;™j7b[•Œ Uáv+;¶IVz‹–Ô.(U¹­ñ<Ÿ¡9ÇbÁ¡*™#~sƒUµ×(uÄ$Kãè)b¸ÁøJ™×h.¥@ À*s^‹Rãò$;m÷+¡1Y›ôÝF^ïïÏ­<1€2„s»®g ÛzJHνÒH|úFg›8·˜.;ÛLS¶*œ­cLÀøJ4 _¦®¾“ÌÏ× å§¥¯ŽÎ]8i Éxâ‘|‘°^ySswÜ௞97ËMs@žKü<+ÓV-@™˜ž & zU³òéˆÙþuùŠèÍv-ÉRFw‹6¬%L Ô7Ò\Xè•‘EþªÛ9 Ó`½Llÿpþ×ã[ e#NÛÏŸCÄý ÓSè‚)…ªÜ]ZXuþ­7æv|bšd÷]Ïϧª«2¾Ë¦” FÃ##€3qq@oK«’åS»ÜV#µèÅhwì‘ÙJðÍÒÞLþ¹eNƒ‡…v½}?ô›ZΪ)”ްÌБÆqkª64Y/ÖE–/0JôæšØÎVÅ(‚ŒFh„Ë€R¦ì0A:v£4Û'™)ÆÍ?CÇ3ãö’!1Ö^£*C¥Öë(w¤¡ï ÷€°’ÅôzÛvLŸ².Œ£ÐØVÄ”0 js¶Æm"’¯ Jpï@|ìî25ö¿#¡ç‰oŠ#= ï“›ì(®Í±…uJ‘&nœ=7®*C¤Ðèš‘åH¸µ»’›\£.|Ê&b€vÀ÷V{êLÊ9·ª®5æCCðý×ÕèŒÄî2fðUÂ×£¡Íz ÇbÕ†µ®vUxæbd7ŒÑHo=Ù ¸_p}K‘LäzËxd¹ïw|âvh=SÄ|ºò˜Ì}Yë"k7 ¥ôq|K5îÝì³%u%nº.GXÀd²ðø2r/Ov;Î;5NÞJ™ì#àCÌrΪoç4b/Ÿ¡–¾Ždq;ΆĎ­ß<²çÒèh±Óy7ï˜ ÈG¯¬WÖÈ¡Ñì•ðÛ ßDdoØÐ ‘F¸²}¶pCéÃ'–ï:Ú)³­Ô,ŒïLnrnôêÚÚJUÓziŸ™Ôž^ž-Ï]²P*ØÈÂÂýfÀ˜;LY ¬T/ÓÂÄ~#„lçíXfÛèzÏ@0TÈÒ„»²ëû4a%k“…n-†iLž9´I& ˜ˆÛ0žÙ÷?£ØCäzr³k–[‚,/@?^`Ž€I«ä†dB©´Þl >\{¶ö™X =`ÛÖŽq=¤<·æ:Vª×Äé7B‰¬+À¢ÞòZræ†oí£wœmÓ(½Îpž–?cnUnDΰ{!s1ÐÕ\>ôE\+xJX´7½T»’œa½°ÆF7bü;‘•H&kQ­‘§Ÿ>Õ·ã´Á¹9Ä"F~«àmÒ2嬸 U‰ÌAv,«EúÛw6y÷$«j„•´Ÿ‘÷·À¾iZh”šø™þ_³8ø\j'ÓÒ悔÷ÄV­¤k#è3¡O‰dAŸ¸FcóËKuÿh ;“¥ÙÝL¤ÝR’±M³ 1ªa¥KRâÛ)"»‘ã.Ãg@•²^¤hUüdªÖÈPÚS¨G_‹ªR{º‘¯:F‰FïËDÖ.‘@Ž»»q"@Ë:ÂF”égºªœìm„™˜lsÙ-Tu)5Ýf•²Ïº^-Çî.ߥbdJL7úþoÑedŒ#ºÔ‘‘=%, :zb‘ó Æ 1² æCF¸Mxª"[=œgJ¹ ‘R»Ð(ˆÛ _uk(éMisú2sU¶ñJÂñN;ßTUÙñõgå(ZiÇ”›¾0°Ëf=2“-ÓGë(ì ´.z11 òIÙ1zeUú.pSC•ÒÈÝ‹,,«Rjy­Ö2gŒÞ|ÖâÈŸ[½LXuô¼J½¶F'ЋÏÙªHÕVÍŠ@©.hJ|Uæù# dAƪ#†):A“,Ì-%@Ö r½2R†–{ñ ¢«5®åÀi˜÷D0Rv4BôbµÈd §YKsïý¶3ÉÐ1%ÁFDb"‰ÇФoú¦(¥/Û)hÊÕ¾á3o¥Lnß×Û 80lCz@Œ¡i²ªck |³^ FV³%Ã'Y»,r辆d»*f ód]^µ‡íÖÛÄÑ£ÑGâ&ž…~^8½’Ù;ŸÿsÐ:YÜ–ïg†oж¡Ó bŽ˜@]Ú•`|–‰¾A²È­?0húý‰e>~-ni 2f²¬äfy)·’¤#&£¯3E‚ÄåFðIï:9”ñn 1€q;ÀE0þ–˜9“|ªrªâWrík‡xǺ€˜ªå‘la†™ôÚ J‰§±Òdg *ó–ÉD¦ÇwTu”é¡ËQU†;úF©&ˆ¯ãhb%$½c+Á@O<^·úŠU# r.O¿MnÄ-ìX¼]1gÌ ¥6tR’Ù} @SÈD¶t˜H#ØÄõÂxÙQ¨ ¯4wÌ-~U¥ýØÃJò¦ô2L0¢•¿W"ôŽwΩYkV˜"qAæ1²`X¦ÏDîÁ(Åï3b˜‰ÅªÖnU—êË™f†“i4®ª÷w,(E›¨Š1È}uû~rxš”·ã$K2|«•¦ÔEpßõû]׳$ÐŒ!®½YïªøªsVEîp«¿ôJZÈjtG€ o½È ÓØJŒi¥¦œ?îˆ3ãýT¨1¼D þ-˜¼ÐÒ§ÅŽ§ÌªG'Ó(§Qr´_nZê›{LïW?Ù‘€^æPÞ2àf®{¼FJ¤j„UE%]ZFä´pb$C·3ò˜>]ÌéE Rž­‘ƒÜ•kp>N]ðF¯Ë8¼'M‰777¹czß@æŸXWÇøHz çLd³ Ý•-–,%Œa•›c†µ#1b]xV˜ÛqRí˜[¬}ÆÐ`ú9Ÿg#²’E]òÞ3ÿªHp;”¿,Újd²_³™'–³=Í?˜ Ñ¹H¹å÷¿ãú4µÐô+dÙÂ4>‚4Ž • Úο^†m¨E eÌëïØ£ÅÃÓ¿S²êvMQE6ô øùý€É– oN #ÿŽåæîûLÓÐziDw׈$Àì››}D È¢meX{kÀ™ôbŽ iîóÓ!àµ;ªj¯Ë’ÀºjLÓ ¹ V’éÛ-ŒY•Uwi"¬*-IT’û&çàø–jDÇ-C87×™“­µ«žÿ €”bÖj32V"ÈWFæâïìÝ¿l’ªR iÜ–€Fiþm“¸Fß`÷¬‘3 ì òèÒ^oØQ)#Ò•jL³­hŠxÊÂôeøGø}“ÒËüËô‘Ý^ÉËJ²‹¸#·¬È¦¬·U‘yfë¨Ö% bV4Y9ª² WÍvp$Vmtb<%¬Ú—Œy²¦¬KcŒ ãن߉óÚ¹.G /I˜Ð-ÒÈ‹»õ÷+€2Þž¾$+ÕËD$ ¤1ù‡ebÝt$@&bê‚E¤Ü kÌ›ØE8G¶Xz8U‰aþH› ýÖ@Ú0ÍF#án ¨ÊÈ^‰›H#à iäý'rôFøN J/3›˜aKVÒ˜h´ý¤hb_¸6‘UyjÔÕ2Z€°\£L“^ÓÓØ§—A 8±YSÞ¦ïGtãšÎ!™)Ú7:²ýñº”Ð>Jid|8ØV°×H‰”û‚½¶”®f­7[%@ Þ¸ôòv®½9cz–z3lU+Õ‹ľ JùìFz ‰•4jÁ#­*`-íVcJ-ªxÕ4Û3‡üóŒ‡#µ`úøÆ2Á³ÝÕ<[@µé•rã4ŠöQê§@É6и®à}”2i%LßÇø7›Î¼oníi†»W[5‚¸Hù.Ü}õv5UdW†9DæÐ'…I€$–s÷ËA#ž²Å²íØo©js{"ûp¡ ëÚP@üñ Té¬Ú*Qc “åõ?ßÅ>­¾èC EuÛ×øözˆ )­š¾FbðÄ)c@è}'6¨Æ~Òèko“4HzA©JÉIƒ„oñûEC³•âåâ Ræ&sð9Ñø¾â›;@†‰$ó kÏr%úŽ™tlJ2c\ß¹FÔ5LP´v×ĘÂ9s3¼¹]äëÿùzô-ì+¨%qnˆl7½‘M$v”éÇ4e†N&«*Éö×È¡v9¾5` ½˜à+ÉvÆ—1Ü/¬5’©ê=m3Ùw£^ÕÖˆSrîä³­FhÉ &à¦ÚŒÌD£j]xLS6±’,èåùà u” ÏŽVzUíÖ8¼àÙñjFhd.‹|ÂGÖ ] çClĦ#­WÎGµA2ìÇ„¸}Ú­£ªÐ² ðùÄ¿Xãôdí ¸ªMêÊDc¨§' %žðr¶ â™!n&Æ'Ö‹±óöœOÇ|è·g+Ù¶Þóÿ(kCÉ]€_ Ö¬Ô;²FÒœeïñ+ɘÜ"eŒß}íÄÁoØþ™¡®ôÄ­áXœ?ßÎé•(E·1k¤Wº}ß„£‰æ"‰ý°%fˆ]9J [h„}-Ñ]h8ˆHæñ€–H]&ÂÿmßþŽœ§éÓ¶»Bn/Óh4]‡Î9À[ƒ0íÐo7-Tñ‚&™lŠŒdµp¬=fʪ–4‰aëák©db½x;Ì–É&Rj¡$ |ä¬È6+RnDœö4ÉÚ!“†vñZö-Ð{ÂL”h0ÖhíFG¸¹¹½GÓuéEÊŽ¿VÊ I˜IÈ6itk(!y:fk´_޾*kÌM‰§¬EÎð-©Z@îî0Aš²^ƒÚ„ŒOWVŸ9¦YíÆŠ@8 GUc€/(1­Ú¸òª×æ{¨öœ'¥Ý ïØ“žó9³ït¹Ÿ¬)U-£·¡ø«=wTBʪ­]IΩ¤ÝË´‰®Ü”2¤ø9À={$½Ì6 }ƒ˜Ìi‘C¦”ß®ä³2ežY9Úêx‰|7›Zs|vJµuzÕô)}ÿæ»Á1 ÊùÁÊšXÞ5ühõÉ!â€í ;ÆØ' Rp–ÇœþŸ_Çí@o²–á6Fžd[¯ç#À#õzô3æÆ±¾Ÿ½*ŸwÉÄBU2Ì•ÿ?ÿÍhÑŸoW2JSdžÂP&Jr†‘4xa°•"ÓÈ9¨RîËÄ#¼¹cJ@Ð;fÒhxd¥®à.“•¸Õ’Rî.;h§ií=i&ªVVòÄ´š¢ ä“s†HTm‡4‰ÓÄ;]Ÿ¦;š¨·ß•òïCQÒ…ÉŸÞ”Þ¶çå&ˆ‘4Í øÐ`˜£ñ3ì(šÂ¹%o`Å3ÜþÄÈžŽy|ï ·&C² Yå#»ìd»‘örÈ„P5@@‰©˜›RÕõªîjHÕn‘ 曆²ÑpÀ¸ùú5ñLºÁD 07]ÙG™€¦oZßdd+ÑÀ, zÛÚë-+´¤Œìûœ‰Ro’U-wÇã),³Ç)õ ÉsËV‰;öËÏDäÜuúй}ÿÿ¬!©NŒÎ­˜ÀQË» MŒFGÀ‘U>Yɘ•>Ô–‘–SòøxšµMú¡j1íÕµŸžŸìj:Ã.B«ªÈ†p²ªX—’H™Ïd<}@{Õ²o˜ÈÓŒ8¼¡Í%ȪZzd˜Ü ppwLíÙÂô½UAÛ¾¹Km[zUYo¡Ôù(™"››ÜbuÏǹ–Üš‹ªŽáU륱€À[oh³00ƪ™À/´TUŠÙ¶2]òÈÓùó÷2¼À轕/5Ú!M,,àÁµô}K1poh·J}pþÎÞ,$2GÀQ°u-+õé´†æÅõæY—jáã³A>áù·^ïé5ðd=ÔYåÞËòY9U[ÿ4H¡½AL67%¦õZ•8·ö1JŽ‚2ñ¦ ð!¦ÄXL}ß“JÙª[Þ‘ÒVœkf«Ò`ø0Üžj!PêšMÉ¡–õ’éUÂdÒ8þì'Vâ#j’Õ’³^G¼ èX #/B¯@ÂÆ “OG×Á´Câwîù¤ûK˜Ú}jÀl§·¿2=¨Å#zn]o{˵YúSҢ׺õö™áéiêUõ}•[ ©$:¶ƒ#¾o€^X(±­DÌA)fG²ãõó 9YGdòø™xÀH³¶²h4YŒv8‹c¸8Œ¡„e‘· e&í3Ü[%–v0ˆÕ]çûº´½ÐÎà–31Rä ×»Sµõ´;ï/sÃä£× ´¹Ž9ÈaŽZfŇFl ì¡Úpèj¥ÓðÓB@¿Û‘m=%‹uj]Õ6‡éÛ™?ÐÄÙÖÿç?ÿ¹ï$±¹[íßçÔ›§‚þ}–•€^HiÉžˆ³HGUGxãÈ4b”ð†f"s6]d›!=&O€~CuÁï[i±¼—»uŒ®z#E£ñpSÆ$–ù÷M¡ )È„Kõ ô~ÄúÐÛ“FW7ÅhtÔÅGU¯£ö‰T•ý+;bJ5ÊøFËM鎬ÇäY©k†enÄdÜ` lJ-eÌŽ@¸…Óë5níyÊ”õû º¾–øseÑlàxÿ|Ò;ªv%xË!»wâÜä–3µ‡¸Æß¯3&ŽM×Õ¢}'àŽùȯç|š.cZî"¦ëª‘Û”ùØ¿õˆi8&ÀÈ ! ¨qH½~žñ}‡Úá6ý[c£û0¤…"¾.V1 Ñ@_ñ]ð׬YÑ·§d¶ô€Ò¯—qDv#‚L6=%X¤Y‹öxŒ®0à(¶’.$1æã[²’£à#cfØ [yºЗ™Ìn ª"MY˜œÙ? Æ ާÁاj>¬T‘ÖóîÞJiš«ÑQ‰Ru÷šO +#SbÚ¡ÑH½<ÓȆÖÐ$Ó­ÙÖËù'ö”Ú] à4ÅKvd(ò4Ò§±¤àÙÏ„C»ÉBIäÿšTÅäéXUæã˜¹—¬Ô­+iQ¥4®ªŽH²ï_Î(`+g=Z̤´@IDAT_Ǫԕ‘\(ËÂ]l¯Cߣ¨Ò‹lñ|„?¨uyG]d ÂO<·J2«Èæb²•9è57&€ľªzE>Ž€#PÀöAja¢ .vJ2U R‡cô‡»)ŸWÿÉ*i-“•å׸Ëcöøzµxž¶%¨‘ƒ’£jC%|_¤Ñ4ËqÑ>z+éÂ0é­rCÒˆªôB/÷¤‰eo\-‰›%WèX½wPêjJUå¦XŒ›œ€^££–p1Zz+ ‘?L)ø¨ÒXèM£=GUbGb`Ÿ>+|7RÅ´j;DÆ7i”>¬HGƒ’@hTò‰G1åÍí롊á¦È"™Ãx;d¼†Éçœ,´·¶¬ú§þóŸë™~ŠŸ©Ò>›4]àö}©1ƒoQµŒÑ¢ê’ç‘®­ÏÃ1g‚&ö í*ë"V’Ya üœUÛ‰O=sxSTá4Änatd¶0ž!Àp `ZÞİ£€EËØY ëª*3Çh\Ö‚[¾# C%nsn 3¤‰GÖûfUV[øÝª.% à[Ví ÷b4€¨JÉ­*Òq ›ûú`DËãÍ•)וhŠ’8#¯¿v;¬>ÁláôŽÆ3lyL 4 9MSˆÿsÄ4õ:¾Ë#‹÷“âÖ›Z£q-¼)& ž"™#À“æuñTí÷éÀzµdr]O²²àÌi0‘Ãå¦Pjï¾8åëOlz œa7"Éœ2!ÈhùZú9¥És²Æi‰ÏŠ.»ŽæF_¨ø|j”‘˜z;öø4|DGLí‘ L´?† JØ-êÚ&h #Òï×f¼\´IšFËíIЈ¦¿ÕæíY ,XÙPµpSògÁçÍš'3ØŒŽßý4ÉÔ®/#­2²1² Ľé™ñó· U½1°÷mé07@Uûœa>cÂ|Sö9ÕHœ[2U¡Ô¨£Ü4þÖ&hD Õ.Ž÷\{V²¨dhJLÜV ¯ð¼ RÄñ‘ZrNp/q>ÐŽY×»c²n¹²mñµïÅÅÖàîÿÓˆ¾ä&]*LÌ-\ö±¶ª£x=[LæV…9èÊç6„G6}wA*9Vb‚»…jÎ8 ìX¸H—ÍDþ)žwPµ’.VÕ•f¯¤„Ô«EiS00ݱ¤HÖ8G%‘Oé˜90[ÕÓ#e™¦X ^—ØÎšOãX8ÈÃ!~þ3I–æ¼ê_ÿú×ÚÖovm˜½‚¶©YÐÜU¿ßŒ”Žkh|&¥¿­ç75úÜ,Ëd1›Ž¯w£ÙÂ9SêbÛxæBWä®@‰‘Ó„™PŠ ½JU‘ô¾Á-FŒdxPâu‘)µŒ’%¯Í¹¬œyV¶"®W¾fßb‰U3º©ãÑ×.óç™m#e2L¥ôÄ-Ï­å ”öJ94±ÍaÊ2ÃÚµâ6OïÄËÚeßœnT¯v¤h`´.Ï•œÏŽí°AxzžÄy&ˆ)+ÑP*‡ÔG ‰Ñ;¤ÅQNO·ì^°·¥ä Îü³%ÐE£$ˆ)æÊ‰ihÇKŸ÷A†iD¸§` ŒqlIdß@ž 4ª GL9O>[ ÆS”@¹ýk)_×ó½éµô2Ž rKÙ1–YºdƒT•äRÀ²ªà|¹»Ô•ŸÆÍ M¯“žR;’’¦Åé‘MO)¿âZ˜ä_«Ù¦qièÉà< è1ûò(U•ñ"\nh½ï¸cízûÁGÂò÷;ˆ¼S˜d›>˜«:m@wK 7@©ªÜнàÙ÷¾Y‰_·pßÝL0"qï2‡<7ÝÑ;ê"ެ±¿*ª¶LX$ÞCßQç‚Â@¶;®Š™ph–÷%}¢Ö€ÉT] 6—9¬— «9"Éü;Äþõ2 ¾eêuT­ NCÜæ}ª6Â1C-1LÄö×ÞÎ@z=F;6 Á°M<ÁÕž£‰ëJy¦ÞÛɦóoÛ™;*ɺþ3'Sê7²vÁoV-º™À¦(ú|ª¢»t´6²S`¥0‚Ò`n.½R]Èãûc’ÿŽ jÕôr>l……µÝ&¹íjÄ ¢„°v00QÎé Ž]¡eÊÆUrÜ+Á§÷,˜¦Ìƒ·Ïô@ˆÄÈ e-eU÷âÃ6ZÀékysU‹V‚ÙšÀ¬Ràe&í À¢ &ÍĪJ<ãùãáÆUňz+ÁE¼Þdå6lt¶&æ6JwÁ æ$˜Ô(SN¬‘FCæm 0] þ~ ¬™È G ¬³©1Ž=n³ W¥»ÆzžB5%¼߀u±êËW M-«EÎjnËÝs; ÉTwg‚|*9Š³Ü ¸K¥ÉVvä£*6(ð2þÃ¥ô‰e£»e17Àõé½*7ÕÀ~ ôÚ§ONµFJ¶0 D rf¥„ユú¯¦´Xžk'Ρ¡Ž3™>ÐÄ4-Ð>xL¤L,.qœ§i1Ç€M:rháýšÃÐS¼Vȉ›8V1& -ÛP© Ш”->ÛÖÞq½ª¯«j£á¦³Âì«e4²*¥•ødBlçdù8"ab<¬Y5ŸÆt5d#,¦ÞºM*ÁôæîññOÐÅ1‘ÜrðeÆt‹[<Ш=¾–HÙzhOUwÇ‹ ñ52Q-`Aã˜R¦ìRî®…@5[<¦{ñÇÓÈÈíÐq½øÜ¥e†Žný^¹%õ4ÒœW"À˘N£ÔzÏgYƒsê)°=XP:ŠÞBUh9os/¯äÈ-RõÊ¿DƒwÀñáVï¿×Ñç‘ ½*qž€#œ¹YíéØCC#‡fyµ*»½»ÈB;%ÒëÔÕ>Ý4üšpxs,²‚ÎÚ…£<¾öHXÉ,ÙtÙ,1ª \A{&2A_¬<‰à´ÌYá‘•z–É”R6EU 4V #™GX D.+½%žŒ7NÎùÝ67†MÌÊ&­hQJ"=q¡ÚÔÙ‡èGˆVÒNæÈäšýñSµ§ðæM¬±ýë% •út”L‘…”ø–z–-°Ua+Õ’ g½¾±9`ZÛ-è½’hPÊ^ ·Ír¤¯}þ9¼z>®à¿‰GgÒÓ™â‡Ùº©•²í‰úẔIß„>…Ä2R ·Zä–ñ”²¡øçÖ&r>¯^£ ãf¢^ ÅŒ ‡ådª”ùsëˆéMkL“'7ʰ,ÈšÅVbnÄJu5—XR”.Ï o€ú^"ÉÈÂëêÚŽæÊŽžF»Èjú†n ‚ÜbæÃÿŸ™ŒÆ]l%§AÚ0ŸÆ)ÙC,ø”_n½ùtwÎWõÇß õÒˆnAC2dS•M§Ú‡²#†l¸­0@>@»öé õ:ên dñ/™X;Ð&­D“›Þ"žÆqþH¸F|]Ü\³•Ú™¦GóžùdR¦!Ϊ}ò×â•”DûSy"µÃý9í˜Oû4ˆ€¡^IèÉ ºÄ÷3o\š)·¹cÎ2üîé°UåÃJ8T²Aãè-Ÿ9¼hPžý¶YûžK—<‹¾í”‹í@€t4TK82 ›âM¶Oþ²^þ{®uaÒp³˜ÏN)=ŒFL†ŽdÙ&H%I01d¥ ë’û†ÔÒûô˳µ'oˆ¿¡:Ú°[w/ãjXÉ{Ï^X/A--œL¶Fí]¡L<«°ã‚ÌG¾/©…P€àN¡ è‰4é>˜ú«’%h¡L*åÓÔx)¿@#CþÍÈœS4rbÛfî¨ îAÛDnŠª„1|,cí`Ȉaу¬Ú‘@ €+üRÞú÷9ªÎ-q»•1À½Á÷{3O>BÉ›tYÊ®@ Ö˜?€¬·é1ÖøÁ##P••^RÈJ¢¡ŽÆQz@T²†^‰&ÃŽò5øþDô—»˜”JY4 ‚"ÏFàÌÍu '“E*i>bÌ0|,€‘çŽB 0õröýl«ú~äë*3dbž5šž'™³RßvÕº8ëí×â4¦kÑ>·- ‹Œ Mú¦0q<{ßÇÑØ\9A][ Ï“Œ> d ²~¨aA@F#g (!kÈR&#ˆtYÀÝàgŽq$`âR'Ë-Íüwìñ;nYJLdǺoKL¤5ØÂVŠ9Žm,ï­ˆ0Öu Gv ²H€ƒHé•itÝ¿_=‰É| ½/† =~×fR )äY•3R¯–ž¸»e{›ÎOQ]²–™ë"ÓïÈ·\6BoKÂU·’Æ«ý~tUÛ(ªfePk§ÉDþÑž—ôµhŽÔ”zaá 5Â)µ`´¤‘¨Ï ÙgA @òÁì:€c¥l‰Ïàû1ɯ¡£êÚ-âa>Ž4ñò|`Voµ+à_Ã0²5èaoÕ;Ô¢dçèS†ñôÛ¦inúk¥æf«— óp$ Dê’alzÁ¢OSÎAI—Ÿ©Z|7 ¥&«úÖá‘ӯݔ¹ÁöÙªui¤·ŒÌ­ª5(û”-ß7z +b]x¹cx'N#ŸÍ~¾6ºbd¿4ôò”‘Âñ‰4K6%=LP£@ön.¥J9=F27«.²Þ ¯] ßè¬rƈZÒ„kQš!0òU¦ÁX£Þ =×d@Aü:bjwA=Múu½Ö%l%ëúõµ4Ôøä4Ržìÿ\Û8P €)¦kPÒ2%#á(ÓOÙÅ´¨ÂùÀ òlVŒÞÌS¶:ÙôdëÕËp«æðkP¤º, ¥A|Ú&YžýY­ŠÄD²Õ ×{éógáaÊææ¹\WÕS¾¹50>§6©º=%ÎÂQî§b†Ö°! ¥v™9«Àé¿¡±_øœµ µ/š% þõÒÌ$L‰‘mE‰˜$óé­Ÿf½xY‹jVÙbÚ§h4*žŸ?Ýi`#ð‹ØÜlMO¦%ÀÐ’ô¢vL˜f€XûÁ®É?Ï: G¹4L`Sð|šû½_‰Xµ«Ñ‹=&^; èU;â»B»ù!烔EΉËd5ªÂECoÇù”V•3ác.qÓ-" .U-ŸéÕàE½ø÷[á¨Óß·)ËÙÂæŠ9ðÇñzö>ýv©»Ô÷Ý€9-ª Z€¿ˆ©šéhâŽL0"ÆQWXv$Þ e¶¬Ü˱ïÕ™w¼êlõ5ç  „§oʆVõ€ë¨ÚfEl Ç^ŒøüS3ö<ç}Ðn¢Ü°È]æ"£·ÏŒÙ™Œ 14éçÌ3ÞRd¢W(É152ý©ÞÂrCõn%-"F®£÷VN)ÿFÈ“áá”xží ‡sƒ³rZú $Dz ÀœÐ8¾‰‘2IÐQ¯£F9€©««!1‘Ùzvú÷‰¦OP柭#À³‡ê8åpl‡2ÊÎAÞþ–¤ÑÛªª%ñ4xULnmR Ù™‡SfˆÑ.è5Î U1õÊïãdÒtzíU“5´=ÓlÛ¦ ) ø—Ó(É¢5ˆiø›RW³üÊnÿ|dJ]ÍRªQÆTå0Aä&Ãë"ɺK•`‹åŸ onU™@9T²¼˜F#¬Ä‡˜²k´I½å¦$« ææ|^[¦±ªh‡LÒ÷ßžÀ$6 ÄmÒ1Acvd^K#êÅ$nG +Á#7´‰•NÏóý·-ž3‡@ùæíÃù{Uúh¼˜*¦GvdES{¶ªFzüJúÇ?þ¡¡se¹àr•gE L)rGæ¸^U kiØN²jƒ Þ X‰Æ1¡Œ¡¼ŒqMT²†.€À7F/ÌÙQÀ”c(3ìðSÐs»}'!ù€‰œžIŸbÕ”Jø½{Cûó ÏmÛÂpd[Õ‚1ˆçH)/*%Ëd¥–ÜÄ4å.≸…uÁ¢}ß·räó:½ã”vÌh¤4BUvì¹â ð0 æO©K —+­Q‰LH‘8p‰ïGo¨ð‰Àmp«s]í,+ ü¯•Ú¶•óÑ˧‰2ž O–ÙOŠ0o{ÇÁ†ž+ÝÍÈ^¯µ“%ÀÐGb„‰ZèÐå9'ó—LAœ†p»¿—t´IÏÕ5Ùê¢qLìÀœÇº?[¦ÒYî>…v²Zrˆ'K©4SÖõÊh|cé[ØQìÞZ™•F2Ÿr›l4€,"‰§ÏÁHC¬ ãTv&ȪvXIÿêóI?eb]3‡¼è3ê©[#’IᨤÑnaØ“ÖØ¶ç`¿ãz÷¦hX ¼KÂsICœ‹cŒ#ÒÃC@ö#Ñ_Š3—»p Ñ`ZÓÌ–&½ìŽùÏßòñ!ãßJí€Ì¶‰Lø3ìȧߌý4%R>Ý‚ ¦•Æ|d&án2ÑŽá Þljïú” (»‘#²F†WŽ`èâk—‘é/˜0½c#ÊŽ‘ı•pŒëó_“æÖHI]GNc؇'Àh@ƒÒÃ|Èd¥Óüó…\âü°m(FoëÁJ) â¯$²Õ¢TÐTƘ Ÿš8§AªrÛ±S´à»Žj@ eJíñ0†•oFï0±"Û_n®F¸™{¬ï¿|gÛÛ¶|& % (ݦ3ZKkt)üvÃÌ$œ¾Y¦pX AV8Ž(ñ‘pÀËªš« °Uêµ[ÀQä@f*G˜Q IpÖ}¹!‹l»ç–P‹}¨L0¸•S\ÏÙQ©‰ŽÈöÜâ¦hkÏêÜêùû`ÊLÈÊ-àÈP©qp€& ,›¢Eµ¹È¶"k|íܰ¨W‰F¯ŒL)'£ÙÝ1Õ_ÊîŸá¥4ªÖ»+|¿”ª2'î.°éB©‹+uÄh'sD¾Ñ#ÄÓŸ?bj§oºÜu¦WâI¶ŽfµÀÞù iwæ—,·ðdùôìí°öà’Ø.ïgÓ†-OéX MU#xV”š¥Ôo|Ê€ìˆáß¹2Ÿºd˜Y˜’²WRjÙh9qXK#â§áPûŸþö·¿a…6l«kÃP³ƒ š§d@%$q¹v¼€ÉðËÙV•cVLˆëÝ8G/^晴²Ð® 샹Y@ŒZÒ˽uOFf Ü,²ŽÈS;RÖ"´d;²–ª•l‚ÄðÞ‘gÕ›f÷¢lhJžâ×›þŽnÆ¿0n+™ÃP•¥È¹l 1L#:‚ÀVb%x]dÎ!0²×ÞÐÜv̇ÈäÎ?Èö“_KËhLÖæªÞmã&ÞzÍ"íoYä4lÓüz3¤Wj À¤OdåFÀºXX´‰*Ò1Aâ^c ´ÏZ*É…ªÆö‘EGù Uma]mèéYU¥ÔØ8ŒP•1ðx>û/ sàÎ?)+¤v7Ò(ÌUBÂ)7Å1%gØ>‚Éíû’R#db¡†8Ñ/[dÊñ¦Ãø}8 {™Jµ¬À7º¡Ž] )R`À>YÕx.s7T¼&ô½ž ¾ùd+[;Y&2™–ŽÇ‘3T­y°€©•fý*ñÁ$MŸGnò &@jɹϸ×ÄÄçéªþ dx¸Å(Áõ>I˾14)·yG²V•k‘gbVGÎ/æ<1ŸŽÅ€ýÒAm½ležJªŽ•0@ã`¼)«îR»ã¦¯1 ±Y‘[¨±ªÜt2¡QU´¹=Ó;"›h!n·µt\N&SÊdÚÀDòG¾£) ð íXKÌé¿1ðñ½&e$€gËHpkWëHIƒ,Û-+؇BT"«ÄJpÆtǰÌ\du…ß§6 @ÀŠQWƒà)i&Æ·¦oQßV1 ¥xÖ(ç삳z -±@v)¤X»Ò»ƒïžb|ßÏö‡JY/8“¹å_F|Èü 4EìÊŽdÙ"÷ÍÏS)@¦ ífôüµ+@ïy|í)ñÏa`GþÃWø)‘Ú…?Ãd½[Ædb ÀøŽÝŽFlnØÑ\ؽ€°cLzj2ƒ}FGG‘9¦ÀÔ.W¢Græ¹.€~x¸§KT™¢=:öÝ ÓWš>¦£Æn‚4È]†l;Á®9ãÛ I¯ÝQ$ ÁÓÈH€³ÜòM©T#}Õëñéaz2-"[Y¨b|wázÆh‘þÝkûð©KÕQ4 Ÿ³)‘·xª}“v8M˜aÕ·yƒ([@N¦Î¶OV€®d›E†¯¤ï°ªQv”‰ãÙ&ž @vk2ÓÑÈvÃ{Fni:ª6•vÇ-4—ÜD@ÉÚ²è·*“”ÈUMÄ‹wô™úóƒ@® P*Oc®j>}+UwÙŽrnM§oóªó¬Qu/¡˜ªpƒŒÀL7=º«œ9+‚zƒt M›^v$î1sÎÈ$ÏH˜•v˜MWÒë÷@ø×5χ9ÖÈJph¬Ò` r»J¬”˜tl%ʵ`„#’†RKLš–ÁäДéëÚôU'x­fB6Nd"ãkTu„Â2M{*uÍ·±v‚™ï:™7nnç¿{Kê¬ÀNl .aj~­E WV*Ìí„9·Ê™2FUð앾»ù”7Ž•ßź#À$·ëýÇÙv¶|¼.˜ž¬kANÓ Çª2ÃwUŒhO€Þ-v/€3½Pjx#´4´F<}U½Åpex2`T•üVåÌ ™gÊþôÂdKŸ¬.¤‰ªõb"1bÎ-™²R¶9ssTUÒRÖÒªrëm¥4dý%±}"§Ì³‚i˜•`i˜,czyb;( z1ú]O )¶m Ÿ¾«zÙ’ÉÂ,½ªŽxÇJ Š<êôµ8UcÚ!^Ö.nÓÊnW Ø­ÿ4¸¹Z0²j[qØ4ªÍů…`$^¯<«0@)¾Þ41ª0žgK:ÆÈ¾™J@æƒ ËíГ˜ 6¨{©*E¦É‡ 62%e×qLÖôÄÃJ½L×tp]JŽM•29Ò»‰¼ö‰ÛðÝNÿî€éʾ™û%Æ­Æ® ÷YkÍrÇmNŒÏ‡!\;A¥”xUøüÝÜÁ}ô8á,ôÔ° ;R:RŠMÂÓ׋'hè“ȳŒQuUÇdÚ#ºälaœ£h@Cá¸ÉíÜb‘@° o= Œïk¬ ö+5ÿv»ë|©­´0áûœÎ¤Ÿ7Áà[&S’¹Žôço·£ø†òÇ“å“öǹŸ´F7 ©Ú#Ÿ÷éd;ã³¥(9+bþJŽ1޽IþHb9\Õù—-¡Ôèw#”ðe- n:xVŽM¤‡“U…'6‚'%™F‚¾raG¼L/z+¥ïogšå1MáF,§ĵ?NƒO€ì¨×Vy*‘ÑdK€Ž[£Ñôã+É™˜ø~j€ï€ß}lñù<)™ÀY]/SI¨VrLÉÖ8Y¯àÜo¨ªrAS‹ã.#u½æ[ž'¾È¤×í`JŸ>=@°Å-£}<†LÆàòA< ?žS;Ê5VŠI©¤n0f¤^ÕP-¶™Øbª {غ0UÝÚh_¼|û8ù4ÃîHÉSÔ¨—¼Æ@†ù|mQЦ¡‡¦€)úuÜ1w¤€¤ið^G Óž*OJä¶Ì*jír‹ªÚD# 4vŒ3TÂì·ì{Ïħ+;ÒÈù‡ótÌGÇ$sŒ¡] ¤¯¥J”˜ÛqžÎ¶É0ö‘ýÊ×éX9t©†ÂùàJ|ŒFæ1‰1 zïlè@c¬Ñ¸Fk‡û\x:ÊF7Ý£%“»NJ2Œ‹è…;rN#Oc¥ªlzYtTåCÉ)'À¬±’c¥xâ1o£Ë’)å¯äh%&yΤ§¤äªî¾[´RâLd-ôÌéWo82H©)•tÉ™#§—Ó”•Äp e&rdþÖSEÊð¿þõ/U_QSúq®ŠTuÙzé[¾Yµ+¢++5·ÞÕZ€Æ'[c» ¥Rúæö”ÿ?Yw³ ‰m#[x¡çM-Ë¿Oïí|äÉŒ¦KXÀÁ@ 2³ª[²ï\Q—ÿmBÇ­ Iï(`Vµ;¶†F‹€;ö±î }‡9¨’ÑW‚¢Å®Áù@•š7ñ£»ÿ¡Y®‹ÞQ`ÊuÑ‹™Ó¨bWÒNŒºuL¤^²œñmë827YU&PM )7wùó_·Výam@.ñrŒ¬UÊnrF}q#]#e#aû<ˆó¤ÏŸ ï–FìÎÝÍï¦l뢿ö'qôôËxþ}3Žú†ªõF÷©h±jÕ”Ä}Ó«døÜ‘0‡þ”‚ ü ‚²%)åõa‚í¿Ýî£o¥þö—>+bsEüZ€¶”˜Ëº„±í°c—Âp#«±û޾ô‰ã^ ™yþõÂ5FÊló‡µxœ³ô]; ’¦A% ÐD#&žŒ@8æ@ Fš¥î(W"¾MggQ;  ×âT*ûÝ—OYÌÐÒüfÅ·mKªvlb]ÈÆiļó$.ųwàCìÇ$ÃÍB ‚U¡*¾§Ï†Ü2Qâ#k¤©7=qøÿû¿ÿ³@‚”JÄé÷ÑÀµÈ0}b˜RÕ“æ6[¤èŽÄ…ª)°R퀣‰øÓpÿ¶ÄŠ!†>2Üh@UÌD eÆ·²–+ÿŒ®])å+€¾YëÚÄ9Æ[²#ÀÀ”"«|"“)ù©¡wœ&OGUëõz ûã?’NݹçÞyÄ‚cïÒC„É,7)Y-|Œ€ËZT‘@£kh]2ÞoYí7b‚~{¦çãbô9·¼cU-]äLŒd.Z#ÏH9U vÙzékg.0‚’ƒ’|Õ2”Uå1ÑwµÚ[Þp/²ëúIu©Z¦YžŽÆiWpWŽ‘ŸÀÖÐ%8§tœgÃ0íæ d™$&P5%“6!ˆ'ŽQ}ü•ÄËÃÍÅ3wœ€aÊÞ„g¥¦èJì(7B¶2s]0R!«F¦‘c´°‚i(a¸Ÿ¨¬jY;™èA€—gÕ£áÏŒ¯3M©¥#q…gí€lQM߃#16TÂ8úˆé“m™@n½Õk¥«R4Èçrç1MaÛ\UN©K8ʘÖÓèÂÃòž1†’>q Y>Žªû‘ÙÚE_f2þ™XÀr]|(HG‚ñ<›r:Ÿ/#q-ÓcÒOìå ²”irxg­q2 åk»….LOäGãÓ³Š1¥}å´+a"[£¹ï>ª¿~ðæµÎ¶!ÒcŒ¼R+ûJâl÷ý]ÐÞ‘ù(í2ø¶‘ûn‹}¢×ï|N4µÐäæŸ->Ÿ&*ÙPÜíÎ#”›E&rSÊÓÜmHìûêGö«ß1Jüëe…Çmzß{Gn‚FKý^nh½²ð›·öÆÕÕ]`³â5xbC…éHdž:Òãšå Äù|`‚p%$F\¿ó—GnÚóŽxb]µ8 õª]MaÕ”ô–!€ñ>`CÉà&ÛÍ•¦‡ó7¦Tªƒ4 ³.¥4°væ™”• ]}}ÁTç ,2Ì?Lé02OG¡Å,9,÷ÁÕ+ôÊ}«ÛÄQàêRJŒÉSUI\á¹BS\¿ï½*>s²Àsxùw |Ó̇CÕ6ºœÞC êj]HÇVҲݚîX‹F”Yż™›£ÈÁ+2»fÔ¯Ä}ã­‚/†ÑÈË·“ÒQt”)ÉðaJG‚H-xÑ‘Ì88²)µ¤‘ý¦eúÀòi7bJ²*%+dL†œMŒÏ¼¹&íïK°–Ú;²m²éýd™àîÐÇ] h †€‰2ÈYFÖÓû iZ#°‰âe-2ÀbÙ/ýYK%ÊŠö©KcÉÐQÀ‚²5ävCv€,|-?ã3—‰Ø²æÊšZȼ­ld¼c¤iºjz •É]2&Y¶ŽJB#F©® k©db¶ÄÝ%žÆ1¥Y^À1ÿr¶°ØÂ·ªa|‚F8â·X#0µ´ISú“O“ ¬D#´´Û‘”xƒ`Õ|0™TmºK!µËFˆ×6™r£yrstYzGÌ@æÈë÷ùrÖ%矞‰£,0ÇaX‹H`«ŠqÌàƒl%@(¥‘ço(Ì-Gá¸õË`´tY¹ª wÔÈÄñ²®ªœ Ðg zß« ñª0Ò8É‚`_BGæU Ó¯ê´w b]­§ pþüÎ¥‹ÒL'Zȇ‡»s^ ÛIÉßÑ`¡‘F‹j{c`‘¿jwÃ(YËÄJcè‘Ħ+ÅÔ‚I‰ç“à̸Cua„# û6d߆U1=ek(µ¡%ƒ0 j:J¿•îÀ“T•Ú¸ÝVüÔÑt²~„rx/®×Dhš ¼n«¤]XU´gk »EU¤­ú4Ê ›A @Y ±#Ü>²’LŒçl“F‚[$A½dõn(@‰lt¶¡¬©—ßæøõ¡+7‚P’‚¬F˜g½õ­*Ï&«”¡,<Ѹy™¤käÐ3®½×@pÆwAâÜ΢w=¹ª,³…z]}â¬ò OÊ_6KcËàMl:¬_W $à¬Å&JaJp·&£o"¥R&yâ#±Ñ4‹–¯DŒ§ÜkÄ´ªmUš– ÈÆ¥,gÂ/êR=& bà6ÐÎ{«.‹ÑÒ³¤_{VíéX»F¸€¹yÀFÈö‘…iôhŒðÈŽÚ1d²v¿%6ˆ;g(÷ð¬(ÙêÒ‹”Åoýë_Ä.c;…é¶´£ªœWÖ0œOšH¸pÌdJ¼-µÈ~!®Dã2JÖÝõÜAÕQU æ&0° @æJŽpº{Ä4m¢zm>Veꢌ Ø“¹ —çç¯ñX_O¹•vÕvæ)µ·g [âÌS–×È3A½uµÆ‘¾¶-F8Ò$sM ¼'jþdÂQ¶Éø]JrUîs´I%â¬Ò츪Ukä0[ââÆ½Vî%ê5n]H޲ („!€9¿J_<ŒAÍZ#>ò=æöp~À²½6GOÜÃöÈ&6e;´¹#1+Y4®‰­T‹’¼ÈªG èiÌõ‰øÓ®—@©´dí ãU%= ÓÈ̵$hPS61Œ¯Ó-ñe%æÈF 8ZCÔ»}ð‚É6g<±×°ÞFÄË)›èX cŒ@fãÛJÎ<+Ù”º”"d&1ÉÒ[ûu†ñreǺ”4Nc™µ*e>ܱo‡®€ôé÷h”ò·ÿüç?»m=ÔÈrªŽ=MxKà²ÍÖÂ9%œ›ö¬ðÂ=iä³Ê÷kÇŠÆ‘/êêÕ’a¥”•Žú ?L)×Õ,Ù¬y:jH2³²†lÛ”Ø}Ðg˜[oX‰L¼>¬87‹^‰cŠŸ±Þîc«¯‹²…á~€U[@ŠÖð—øõÃìhJˉ»ÅJMœ, š›#,Ú°•Pm@ Suy&?ªž”s£•ÒïÁ7”mûÈ¢[·G-Èi9Ð`Ú¶¹ r«±èFÎV&Z6È‘ «ôµkTê)ÒÇ ôª"‡ºš%”þ†¤hºï†RǾ$ŽÛÆQn"žÞ¬&âSjzb%Aæh! n¼§öÅ2IŸ,«U)1€A•t¢Ñºf«–‡Ë<ñ2¬ZcÕºà–¯’FÔ’òÍ•ê-7&kkp™„k¡G»”ËΡ|†åZö&õ";vµ¦¯+ Ÿœ‚5"ÈE¤}èÛDÉ'bPŸ¿V7¾Í°t²Ï¸Ëà á4pÃÈ1”ŽaJU€¯©ÁBIÐ5UEz|ÇÙ:"מ?q Ò¾m‘ÄJyr°FÎí€É¿k"9¬+¬KPÆz3#Ûa£7¨%e&ºjÙß”ã[†Œ§·¢!F¶U øPfâMIS—#ÒoŠöi¢ÆdÛ!¤AbËPj郆…™<%lŸze{‡äé(Œ&@v¼ûJLÆ-¹Q{X£j·ƒÉdÁJV"ÎÇÎ9Ï@d•X=RÔ¤¬$;æ¯4e†1 {U%Ðnm¹vX´ƒ[£’ÞdÜZƒÃ„n GÀKÒgÌ%y¦ä©¤×Q)³¡˜ªlfG:–‰û垟ù ›.÷.⿜óÿã9ýh7þ}Xõª²ÈЉÙGÁ¡[´*&çv»NÇ!¯d[Ëçit¥njOí˜îåwqŒXµÑ<1üµ7…^#¥c½0@€Oïè =#†“µäÐ>Lú,È0dª­¯±*ÉE¢…¬Œ×[ÞYI´3ÿžñLÿý÷ßœ›Š¸#Žy¾_»®­Ô7PF¶JJ¤’01æjÜ)‘Ça-pæ½Áuúü~ÑâH@4 fâXK‚LàF¤DRÊø¬äÊÔâóÓˆ”á¶Rp%xn˜HUÁ¶7çLæXµöª²#ÀGq#´È-O)׫úçUÁùîòIô¹5e¶@¶ZúæHϼFÇù,÷¿AַŰ9P¶ÛÂG•Ò±ïàH³=7îµ?ýWÙÇgU—A&>7™¾Gh ’8A-ªV:cl…–Ž”âˆ¾ßóvp¤~wcLÑE °1² S%#¸M'¥§ôeÿk×eÜÍ".0Žr>”øŽxñgY&F—{AŒÑ~ÇáÍê/¶[@Kk×™§ÜÍ%kàõá Ð’8FvŒÑÛ•{½a)sf¼Ó9Ð#É€Ù²ŠìÿªDn½¹»'&hæg‹á™CG9¦¬%óxâz‘Û¡F< €¢Md¤Lç#Ï®%¼M”Zs~ƒøöˆ¨ý¿iÊ=ëH—@^øºú|äQøìæªa$7XÜ®9ãE]ÙªúVÁ¢j]ÚOG¡jX~=i2¤'s$¨— ŽúÌbòQÊJ©U1gðó³ÁS)ÀqL‹5}ƒfE†tlÖ°#ÿòº´Äl OÀ­¼à˜r«j߬X;½ Ä´Žr&ø¶Õ8^ßGn™©‹~†°¸òÏï;Û,/€ÆnTU‹*&,h„¹€ôUü!hnžJZŽÅý«Æ¥ªZü^“jìg@¶Iü|"sSÂói.ÒEúbÃÞç9ºÀèõt4ް*0ŒA]|ú~æ¯ÄÁ @ÖÕÎe>É€ý„b|0î ÚÙæƒÉ­N“§öÝ%Ÿ¦6 Ìéx m•2w¯®ÃI`ñþPÁWRMPÎGv4nïƒÑ-¶™À$ÓN¦ê}ü‘̇ÆJ˜°#H´^n½ÌU1™88ªÖH© #à® ˆH&‘ã­€p œ  ‘5vSU%< rN,GÒ'Æ|þP:™]¢IÝÖ®ñ2\É~½‚côX C‹Žœ»<ó– U;­k€§AŽ>í] ÎŽrí­ôᆶ€#‡îßPíu‘áÙ‘ľ…ô¾}ø“忏ˆhPÓU…^þ"™)«"á™WrdÕ2ª®oGÁ­ëhŒñPwÈçw¨^|Ô[ ¹[¨âóD¶ uTª pÄ;¦9êÿýªTi·›f eú:{Y0¦p tYs»T¤*Ü­—ï^1ž¬Ì÷ì°*CbdSʬT9¨Êp›ÀJñz‰ñÍr|ïâH¦Do.ðF+ah„#™YSöÇŒ’Ñ"=@ÖªéµôQæ`è•~¸h®ýIö¤ñÍÑn.LiŠ£*bí­Ôª]G&¦YU—£öðH½r£ €ÜEG¹‰HX¯HÜ Äg#TUX1á|0íFƒðí8lJk ià€ c hä`°FL|íó VdLÚ¹“ ªÜ¸¨±8e&+µƒ¡BÉQ¯‘Ʊޘô}ÊËT­×1ÁoûÛßúÈÙ ŒÿÜ #1=MkaTE¦ÄµT}WÙ µÕH,”8héØŠm–,Ÿ)‰eU¤^†Ó$sJ9ÿVeŽi&’IáÈ™À±‹+?¶~ðšÞ2a¼#½Ü‡1Ža¤öÜZ^Õ±G]nI>ML¶.|3L¬9C%|¶xѽfÒŸFny]b2>97k†€ÈVÖÛuÈ U$ K…Uúž£ˆè)û©óÎ9·OTܾ3zþùTÍG^4¢_H]nª…¾FSh”Ê@bJ‘RKUb$M½x>ÈÇQµUÃ~ëò׺šŽ÷k®jÉsË8ŠàßGâý™};˜Øª²@jI&p/ž–!pd%spÌ#0UzX&P¢ Ëp‚Á¢‰i•RÊ‚ƒÜ7z Ä4kCõ) ì™ ‡L…j³|2úº”º ’@ŠŽaŸU¥¬h³ŠI&$‡œsh‡xÙ‘8éÈùGÎϤÜ×)‚º2Jß4¡‘¦>¿ò¢HRÏE'¬-æÓæð}#dß¿ Võ á[Ñý§o-¥ª <¦uÛAobdÛ3ÁXÆQUcñ€‰È±o¡cÓ5~G.³j“Õ>žø³è½H˜c‹Éd=޼Þ~Ôûà™û‡nù} zž‹ÖC²­„iÄ{qƒ¶<@Ùõ[ƒ¾R-ª-ƒ7hxƒèû»‰.Rµé“¦HÐè&ŽgN™ w䟉–]¼’cP•[2}‚ÌFõ䓨ÕsÓÓp–öD98Š0¾ù¯7áÖa4‰ §i:L ¿¿Ù+ᑲ¯A[ÙÄÑ,z> ó·mCHÕLôr¼v‘->™§P‚ù˜¥J#™¨: VpVåzÉ4 G²98n‡Ä2‡r¶f]½ÉdzØX—A€¿hÄçƒ$+-œ’Fh‘ñ`x+§$º5I%™[dƒzó‰OçmÑ%`΢v wUíí95v â4¯²é,šRF¶óÈVš8ƒ¼!’'Až²®”;»v®Pg×ë¯`0 ¯.F\µ a vd}f=½*CA¯è F]ªïŒc¤lP;”çæ¯0}EÌR2W¦çÙ#ÂJôdÌUñªy¡…ùû:4B—ª’h±Ä•ÚYF2×NO)ûßB0'S•‘FËfÑ Y)‡Ë7¤)êÝòHSdé H2&¢­êuÄx,׫V¢™¤ï­”ªäô͵•€»2 ºÑÈfaº/†9ÇþåÅ0¡‘[nª•'°=[¯}¦ï.dù¨N–mG/¦Ô§Ï°…-Ó‡CÙ¶¬=‡ •ä!á“a½Ý¥‹Ã‚¸#}¶­Q—O²š'FKb™Uv`H†Á»¬$€ð i8ËH¡ËqX—ëG† bxdí=^•­#co‚옘 –µôG¡+eã"1tä"œ8s¼5Žú†’ÿ¬ÑûÀîëØàî¢7Ãn”C/§Ó)™¨Ö˜éH_ \{¶µÔÕo{ëaf²ö@ Ì wÜnÓkÙVUOá•`¼›žŸ>ÝëüÉ @Š‚)’vÌI Ï‚#s¯=¥ì»•XŽÌÓ±;T%à d³‚1õÊ‘|¬ë(`»nÒ$ªºÄ&vä_K`GÕñÃmÎA‰? ¤1¦˜ØÃ!?KÜÿ¶AfamÕÆá‰™§×D–U‹àø™¸O±}T Þ4QVÊ¿ö0YÇz7«SÈ"UÛm ãF2¥a%JA–žýnr$Ë“€ÒQU#áe@K›Ä‡ Ú@{Vlñô’!,·*=Rð™IU@¨fÓh÷é´9ͤè)ÍÕë+w|¯£d–. 1M£ñÈ®£côÊ ÂJùo±3”ñL½Ü®¤Ý­‡µ‹&*‘96½]™à ÏòÚSF’ d[5‡dï/eWÖÛãSæþ²Y”²£*g$ÀŽiüÞ0Ÿzñ²Â‡æ@Ì€ :§Q ÔEà^zSâ7n 7XÔ®ñ³êF]--m"Ç3o/“9öŒ­Z5e²&ÂU!‹m˜U7Š'nŠ^Ñ&¿ýóŸÿ$΂–©p“aG –i€°LpOÇ3²Ç>$Ù*Šœ9ðêaAÓÝÊÜüËÙô½Ýô×Ìkv’.nÙ¶¡c+éê›ä¸))ÛS;1‡fÕ.· HŸŒ!RÔ(Ù+¥á©ªWäïkA€t¤¡WJÜ”ô²à@heÑbrþ-“&ïFÆS0¯¦izŒv qö»Ê9@–é™ÁD `4†¦ a%ÇdZRjômÎ\IÐ;Êp<¬‘l-˜³åý¥`ϺíˆÞA#¤Ô7C Ð+LôG…#ÀdEœ p…ŸODuæ#ze¥€Òdµ4Ô8‚&t4:&Û²’ÀË5Zfæi0ªÓa-ŽÍ;ªóiž¥¿¡ f"ë#á‘5bÚ¼R†,Ë雋¤¬¨QnçaŸE›”óìÊó'îÊÚ…£0H{ƒÒ+5èÖ)Û›R»<+-ªgÌ Gÿ™Œ&Ã4ì^@IDATfÍI€ ¿ía¹ö÷Hï˜3 ·ØE¶úíßÿþwÍD[XMßo ‚ØGÅB4ÆÆøô‘J@♟æ{Ûñ2†Jp®}˨*á1iA Wííæ“F—*€y¦iÐ0 Ê³«uì{ ·F CJ_µö×bº¼•(á iTEíx–i’io·˜î+ ½ªaÀ/k`J |‡œ?cø;já_n^“ çôù§ï#VM ˆd¯q¦(•s&ÐÎ_UÉÞê¸|Å]ª˜¦ôÇC|z¬æFæ«ønÛ52'n4@)(™—ý‘³•™$ LŽÉt!M"óä¯ Ç¯Io„’.Ùb2RµIL½lµ4nâ€L 4O>)s“S’Ý!¿¾rJ–uås[õ&¦…ÆgÇÞ6ÜDLdVuÁ}X·=Fâ”@>r]ù'†'†‹Ãí ï"-Ù²£h7`‹Ù§#†¹ÁæÊŽò鼟”vŒeµW©«MðH]d1rQ &ÐRï·øK£Ô5é'³O|s3É0Y×Ì%>5”š…øl庪þö÷¿ÿý‡ ©†-Z[škõù‰mªI½Q¥&éí!Aà8O†Â/ø”› +Ñ÷…pLŒ¼}çab < ú ¢ZŒŸg-Ì‘3Ð_©&Mùz|¾I³ÒÞã¦TBŠZº) AÃ4JH jXÆó×ePS\m+aúƒgdzitqÃ0 sÆ§É Ÿ&^îO#L¬±W}òÏèçD2•j§TªŠï•"ËZâYY‰R#Ÿâ]“ ’r†¬b”Î*÷Øa2ùÇJõ"9T#ܱ§ày¼®Ù±=s€µÀÆ©¶?MU‘ŽdŽô˜2Ÿøvà飯7\5lǪ¬…•FÇ~[Š!ëRÄÇúû[ï¸ï¢D&z«ðònçc3e|ãÈÇ\9 ¼_2¼Æ^£ç²dÓ3×ÞSX¸·ò#a±ºˆ–'†ûóƒRIèêý7¥G±û¶¹£Ð.\–€æƒwäãhD{æ#kïR0e²em…¡t<î·Â‘•¬QPÖh ¹¿^ÃÔ¬­`öé̇U³˜ MÔÎÇQ¨ÊûÍB0q£)é#ù`³’[©JÓF¸W¤€i2ÁèmPŒªFíŽÀi‘1IJ£%1»#2g ܽˆÉúã°'j±ôùln#ÈxÝ Î¿q ÇÈ¢õš¥Cùš;о¥ ûìȈõŠ®“!=%˜&±ªˆ«:Ê;6ÃVãJY‘a˜o(Ð7œ M·~0ÂQc£óló#Ș˜‚weÙ™Ì,°Ü&ÀùêsÌzŽÝ P©êŒ¼i3wÌÐÈëýy -¢-Û†¡¨½Û„Ò7I5¦ÜÙn7$11Œ‡«Æ8öÁ§1ˆC]òöi ŒÐžCdz÷ó‹©Ò•|ÞÇ Ž2Ì ègháY ”àwó˜ 4Ú<ó¾(J6!sŒÙkìÖ@¶Ë½C7… ØÞ;«˜.˜ ² ›Ò û„5ÂÍÂXì.@XNÙ1e×Áäs|¯³‰}Èj$ýÃhú¦¤—÷ ªºˆ‘0Y@®e—¢¡tLïÖüÔ#09ø_pã3ø ŸB&d¦O8e?–}d¥Ü«šÒ âôŽª—>¯júnQÎáÊ?ßäöLœ&«4ôMçÉ-§NÏ@Æ×Ûz½ ´tå)·jvSºàzg˜æÎ9)ÛH>yj1Æû#¹%{|LkH2æ4°ÆöUé³è4Ü”“eÅÓzyŠ•ðŽi"Û“CU8¯«Ð"l¥*à–l…7Þ24Y%îe0¹1è×÷µ*Ù:v×Ñbb@I—v¤€ÏÏX÷ùì{_¶r“†gÇÆ´„#ÌhvúJpO[Y/0#R4ˆOUYìJ)e/a7 3éÂx \³=#»‚†X»˜­Ýª’Ñ»ŽwËY¡…Æ—ŒOoÛ5iÚ¡LÙ U·€”¬ÛD FV2îJN"¨4† –5¶ƒédýJ副*ïÐv“‘¢ü¯N)íŒÉàS5¼êy‘{_J¹µ¢­º—^Õ¾!F4WæP—µummGÕ6‘1²  kdNæ˜1µ;*u…¹5·‹À<ÉvGJí1@S"«ÂZ\§Æ™ÂÅ»™^£ÑµôÇO¥­ÚËSò$07JD0Žkߪ˜ZT‘¬ÒìS‹©=+Œ ·1¥FØ2x˜¬òÇ$ÐH©]´ ^ð¢Y­ç)nÇIç’ßk¦‘ d£û7Ï dæJoF¦”1@&€Ð"7º#†¬#U@¶ü~ód"‹Ú½}dô€œE–¹A¬ñ +5vA˜g;´=R»ã‚¦v Ò½‹œÿ¨BÍÚŒ`Òb¼0ÛÃ*ïH%]˜u²•ùdÞ$+âªñÞ(ÐsÀ4=\ƒd «¢ãpÝ\$ÃLhrè‚n®ŠaN8ÂYaV¥oÊñ½%“!ýePU`E¥ziú¢Ô¥Ú&Ž›ÛV²Q)sÙ±•|±\Ü wÎy+x_#€XK]2eO§cnýó)(5ùîF\o˧ÉAö3n´?ä´ÛÄnL”Ú0F‰IYÖB´vX.šHóþ ®¥v™²¶†\;ÞDGhiÖºð˜ÍÚb˜.B0 ˆ˜0Mkx%¡TÕ\¶J¢ŒR{Ú¤O$šÛwª·ã×·±=8y“ ²Õ˜yÇaÊ<™ [Ø)rû;Z)Ï”íÆM©LÐcöé÷åÙz^ Û.¨«0EɃ8Ö¢—²ÄJ¢ß›Yž (ßÅÚ'Aþª¯W6NÀH²xSÒ˜¢ &Èd³ák›X5Ù{\;ÒD#0Ú)+Éx“-ŸÄX„×2±R¶Ê…Ax¡‘mG¥}+`¤v  –­·q”|ÎcQxY …‹\`¤ðqv<ÞT¯üó:2Ä”«ÂôhQ8«ÉÎàïï¥Äl í ”sm˜? ì{Ö8¶Hú¾»‘‰å<‘¢—!n-ª¢^V°jUÙúT0-FÆA‰¸7TÒ…'ÈSé=nœF|b·àƒiœ)0>YJÇ<‘ýÐú+C‚6o«p½ªZðý+ŽÖSb((Å4ªÜuz%™˜‰È6Þ‘¹@Š0Ã=~nŽ-ÙtXcs1ÆÁ¡ܘñI@¶ ~ÇMGÖ¾FG#tݱç“R*ç9G/œó̽îÞ/âüöyeÓîs¬¤7CÛ|!PÒU£\ ¨Ë,VæúÄa¤PEÚc«FgŽaøÊʪ”°P…9$cÈJ¦aÅfIs›>IW㜵tÙrª°Yý„â9 úZà¾öL(µ÷wü”mwzxL˜&Î “¿^q|ŒÆnähô¬ðÂQ•^L†¯—íUý’µªl“F'ž¬·Ú@ ùwAJLúÈxšd3lVÕkóùUœC̹T mß5Ôº@"ïò È·®>¶x9¥ljß6ž[ ÀS& áE]­%Ó„û÷tÄ)a펾Uãé…‰ `†-FÓ”FÈz×è(ß´wd¨êX Y£Çÿø6Sº5™’hׯ1Ÿ3ò^œsÑûÐchˆÓÀ UÎr¤eD›mÊ­œ[Wí·€®Æ…– ›Å™2÷KÄ&ßÖÏoHY¥m ™h‡â4ng´qÍUí¹2qÄ7=e‘ªvæãÈDÎnÊÀöa«äØ«æŸ,àr½Ž<'ƒÓ”Ý¥}¶3vª”ŽøÝŸaßd”iˆóï¨ëe2LŒ·aVG¹3´Àôk×,Œ£ „åH-Žåݱö妴ŒL¦]ŽyWu¥ôÆíîð_ûIÓˆ9×¾F¼.™Xw”Ã˵äƒ0ÂñŒç•Œ$ó‹%ÌðN8úÌcæ¶\Ð÷Y£0"[²<sˆ¯KµgTa½JÝ÷ÏJ@ 4wàù>øàà/Z²Y2‡Èl1€lÝ%²•¸iÁø÷]0† An›XcþpGULS€..·-ž ±* $ ‚[¾–'ÁFxö^#RNœ d Tåob“œ¾­Ú$}ÿš-Þ¬UµàõâkwT…ëuô/º õš¢Dcm›4Ÿ'½Þ9à‰‘dU] 88ª’!hö4p·†Ä~×ÃB—¬%Ø<[]nDC‰wY q/Éç¸ß%3!sÌßPbV¶tTÂŒÇ]¼#Þ ‚”Ù€ð2n2%&7LU ,§ÙÞÊIe΢µÛéXÞ¸&ƨŠ€Ãùƒ”eýY´Y%î[4€!Su¼{¬.ÉÊÑ ‘Ð’?èSŸRï;‚À‘2AÙ1æýT8W¥ßǬ)f‚y•|”6ô5Þ9çe¦ÇeÞ‘ 8îßO(Ÿ½R%†ùÌèAÞ)õR*Á€ŸäW[Vx/l³-ªÌ¿$€ïWƒ^ïiÿ¿üå/a&d0P®1²ÅäFÈÚû—’°ßhµïñÓ[ŒŒ OCw¬Kv‘Þ³{QÖEðg8&1}íÄøîÈ ›ÅÁ¿>ÞP|Î5Ê•ôŠª& G%LÉÍ,€‰LÓ,Ç–èÛ'e&ÝËþŽU1‚˜3€- ·~x-J¤'há¾ ?ÈÚ-ƒ'k=cª2,ø7‹ Ï(sεk-ª5êR ³UÅærÀ§4È·Ó>4@ÓÓÀFxËèÊ6 ž3²ì‰¶RͧMÎøçSæój¡OÙP)÷’µ7ÅU6:¶,ºBIf+«önÀÜðÖ ëjJÄL”äJ¡,Æ×èŽ@-Lì ÂÝu©¶I½[8.)“&0¶aÊ…—HG|z¿蹟!·Wµ’ÜÈzµ $±–¬´x˜†'¾öHúJ³ÐH¯$2,'¨T2ƒ|gßE­$ˆ•DG¥ Ê'vËøRÖ…w„׫ñ¼Ô÷yUu‰€œY©åYÕÅ Æû.œ¿cbÇZÒ#ûê‚^ o·ñ†ÐÏÀûb4ÅÑ3¶­%…ÒîÞ—¯ÑJ€jS®ö0»]VAã5ºE³¤qþ”}K‘ý z}²Ü®ÓY^¨ê™•0€.ƒàhÜæV•‰‘sVrÇ~ti™g¶}¬J&¢vGa“îÅ\Éžü1‘ï Hþm¥¤WWY£ q´Y†ë2K‹Œç“lŠÆU¹ÙǬʪÚP×Ùò®d(& ”idу wq%½]¤åÉÚ%¯÷»j³äzÏÔûòŽB»Œ!€[•sWh™ ™Rïƒp%íz…U}¦ñxá(;ÃîÖua4fH¹q§ù6 Ãò±¸ß&½C ÌRnávhmJM)§!v”ÉhxrË$ÃÄ™hqTuüí_ÿúWƒ×`äù² NÀ7¯ú)WêÓÒEI&`¦ìøVÃJUS2"­‘FÉ훪 ³­dy¡·›ßŽs]/S».< }™’¬jÓ+Áý89ªz8 ½ (³­[Ó•D%¯§ŠLðVx ™qF`:Ê6N F£e¥>8zÕwvÖ(‰ZFjg%0á+?ûoÙ2a¥dòd€ÒdJ9×› AµàkG²ª]î<Û•fØwð,úpkO½uåÙè-C  Ù>~íù0—É”(Óc GJVÏk¢£ÀÃZDŒÌ$åºY¥O‹ø>гRb‚!0î'%†F‹¿¦8^›³FCý©é:ªe&j²%ö,}O¼pšQŠZˆ)˲ŽùÀµÈ‚¬Í­Ô¬þýOX¯HÖWÚ1»Å4Ù2ú³YûÝî×o§dÚ“QvqG¶½˜)ÀM$k„¬Wªµ«ÂâÝ/ö ÂPÂa¸^U M˜ òA¦ïkÐrí@ãÈ"[â_ÿL‡uŽfô7Y˜BP×Ðϼ â{…n×6O0“ºã:”ø­q¯‰o.¾ éu9f–«¡ù±ª’0NÖÎ\Ütb-"畺ˆªÑž{ï@I£Š×Rãîå_£)Ž5]uãð<ûߺÁ•fتH@ÎAU´‰Ý®°Ÿa2U¤ÛcЉ~4Ä#õ¶˜ªKiiÛ–<î×ßêwÄ^Ic[ÉÚ·’c†¬=À3¥ÜyfKX†R)g žØ‘9pÔ÷º‚ªè/û€F™ØtVr2X{W È몑3æ½ü–T›ž’9AWÛ•zŸã~¯q ß1÷ÒàRÕz·~pAƒÉ&ȳï#ëY71“ÆÙ“Æ#`*mA;à#ÖÅuõÊUß%½º’¹)Jdm;Ô{L¯[LGHÆGøýÓ?ãòäÖ-6¨]îSÆ™œ‘÷°‰j³0);2ï` ß«îkéF?|”" ¬ÝE2”UµÛPô8˜4ÍÕ‹¡ì˜yš&bè}.Þ™8}+%–E ÞdH€‰–ß¡xÎv>ߌ"#Ã’²Ó`oG‚Œ²ÀñH]¼ûðˆáWs&ÝÿÌËÒð×åiì‘RÀªnå˜IŸ²íSb”4<9gÛ¬–ɵctÉ5ÂJŽ Ç­›ÂPD’ÁëÚÄ–ÏdíÈÚÝÆ3a娲ÀçÜP9²–Þ÷Ô[)‡y"•2ñ ݪú~7:Ù|Œ†Ë”4ý2Ô‹dÌU¡„—»f¶ŽJÜÂÚ0Û”ù°mç;á¼¼.2¹ÑpnÝ”€2[¹º)¾ªÞÞÙ±édªøFç£$*1$5JÄ¢×ð ‰ë%K³M怎IJ}b:jç,'Pr„1°YsŒÐbÇ4¬à 1õ:Ú-sUÕ2V|‘¿ª%ùG §Ôaâ &-i¨hDnµ`•Ȉ‘z­Ôt¿ú}ˆþ ¨Ú]Q—ªñÑâ:HQ/PWúdÆ9æo–¸¡Ä­Ý’d‚¿Ì®÷ç› ”¬®?c‚™Óˆ3‘•M§o>#ʶ¥Á[£kª*¥i:± ÁçY¦I ïâ0áj;‡þOAhƒI…šœÚÆJìd“äx“`LJVpGVidrLʳþ÷{@—ËÈL”ŽË79. ÷•" ô›UY›ë5è½ÈYèΕéU‹LÊùóql;Yc]iðÂo[Ù¤ÐÂÓ;`ìàw <²c[•ÏN7ª~Oç}´Ü!g“܌ظJû™¡Lz¨Ìi)åÚc–Q)½ã€}ný8®€$pìRí‰d22‡2’I%L]Ž"+¤^¸O­\d&°.|½Ä=rG¬à|®ñù x@Wk`rýجªÔVÞ¶‰=>+G2|ÇÖÈöÕ×!ÐR&hál㳪¦Ü™Ó8ö”¢[kUZdÌ"O]݈àÕÕ0oûñý~©”`†îÓSî%«"+ɪ¢YŽUðé1@£$ê2Þ¶pÇ€Ì-C-S£Å|:[iÔ^Ô¨%¾ý·˜ª–ѳ’1¨šè ª4b#:¦œ SU׎ù´9ÒpGžV­·eÂ{íÜ\vŒKé­ùëb¾]UòƺFkåµ ¼^Y8 š–pTÅ_ÕIVaÞ8ÕM„‘GÒ‡hüAÝM,Ϲ»ùmëË»ˆ^ÇÙfB eí«vhUX$`Òž‘ñÈ™Ñ;Õ"›ÒßÓÛPàõÒ @0DÊÖÖØ,b¥ UýåhÔK_5½5êê²ÍPÆËžNôlõ ŒR;²úrŸŸ.G-x±¹3a.jaЈøZˆRƘ~¼¾—¢Ô訚ÏQ±ªF¼ýÃŽíß_}í3׸;ævGs€²ÏE£®N€¤¡lIúº(3”‰·Ü&UázMQsnd2Li®¡pÓ)3 LOÓt|‘ƒ.G¥<û+v¤œmÎ4;†å€5úÉbÅÖƒsƒ»ˆv$œM`[Ûq;S¶OÎñ”#1ôJ†â,ñýý‹ï«nU-rŸ>¬‘,þv|°Ǿ -™¿ééË&òäãH#Ç€Þ®àŸòH è•䬀¢Ý”2ß2ùO@Ï £$:ʘ0%|f¿ÉT30öŸØÕ½þí?þPFµ}=e" H 7,Çùá7&Rc¥ŽJ{qL·ÅÔ8eüwøùÏ÷«ÖÞˆÖ3ÂuèEÈLèMÓVãk‘)kQ8$ê’ñ?rÓkQµ!FÆPò´&s{Öž ¯J)U`_U†œôã‘mþJZ¸»f"ëè™È¢¹•€dF«ÆðÀFDf[&PÅÌE·è8ÿÜÞ%k$ñ4-¨ó”ý<û•ÔûÀ@šzýö̤öx-€xgµ§wN`‚}"H-eÕ?Ø5TÆÓà‹87¸#¬”•'Òø–Ú‡ SóÌ9Ó;¬Ýô>MíÉä¾?‰eŒDn™¸& ô6H&›‚¬±Üˆ“íhzuuÎ0^£P•ÓÏy¾ª’€eéžEo4ì&h| q™ÄÀ–Â1&ž°›5”„ÒZñyVMœƒj%€~ΫֲöŽ&¦”Es&ö‰ÜʯÇÞMö ï§àó=‰‚¬ÐçÍËÔ4_G)|{èÒ4£;ÃÜðd2’É¿cÛ>&qíM7¨ LØös^o?ÿ°*ÏV„^™8™Œ`#´ø ¯JÙ _ÿô¦ëšObú….˜&&G R¯àÌP;2¾Yu¥‘uÉHJ£Ç õ×7xš¬ÃyÿM>d ™Mâe¥á÷Ê•´vX靈²¡–nOUÑæ½p_ä®?Ãl9çÀP©Ýèá¶UíˆÉ3½ã~cÌ5îÝÙS(É 'à Eë SLHhG†ez”Ýôj?_BŒ)B•FÉ7_KX¨2)ÓзaÏåHÖ8†JGQIÖÅ¡^@c%b½œ+õbU2­v¡”O])eJUÓù0g ‰µã‘Ž9׈!Ž/èH™ƒ.Ê0+UºŠéÍu‹ 4’9n´erhô)³uj‡)s†3¤G÷ý:*EÊôJ=È”[¯‚mnø•ºï5þ|@dŽíh)¦é˜CäF3ìI{²L”D¶>n-¶ÍDnÓøûï¿gÑó©iË"/¹»6%‚6Ò0‚+yûuÔÞrF(ìÚÏ÷+÷ÅÍÇ‘¸M4:Ö(דa$¦õx U*(m‚ß’ôȱ)u54Ÿñàü „.G %¦g4(¯ЋYÁHÁAôö!P²LïÖŸùdH †¹ˆ¬]žÆ3Òp`µàÜ÷€ɧ÷iVí2Y£ñ4”lÍ0õ&®4ž¸^   `ç‹êe˜'>¦µ³rÀMU…^%ä½ýç—]½ÙÂæªÚAÍ’_‡¦[0Hn  åÎüõU7¢)ôöœr èê¡0pz #°+(Ý¥ÎVÝŽÓ&Û?½Ük(éu¤Ì$ Œ!Ø2æ˜îåHé(§QÕâ(ð‚F´§#™c9Ÿæ:*ìVU‹Þøcˆ$Óg˜[³2߬LêBv”·@ 7L]³r–‘-wôhÄá(`ªjùÈ"ÿdŽZ^Ì0Ï+ÿ´´ŒÞ‚ŒƒûÊ?Ú xŠZ„cn-Fãh ^ûª°HI3 ЈS¾¾ÜqȰº^C-ðù/ÎáF¾ŽÈ0©6ÅçRnu‹®‹¬Īp>ŽsÃð×¥š§Œ\c|¯¬«YS²d„«®‘Fh¬—†@Õzp2¹ÞîNY‹œCsŒîŸRú·XÓ„3ï/=Ñr_ˆ #5¦4(+UX¼M¿\üÏ:Éx&À_íçóÌGî÷iâm ÔkPJÇ–´ùHw¬Å\˜U¯D@¬È5t5ÇÖÆ´L†ø†FÊHæøÝ‚XûB©ÍBÙ2M棅%¬Q&.7º’SÖëØ8 M]o5s|Äa¹‰Äpž@> Õ+ÚÈ–O‘øJ>?±Ó(yÉdH@N/'“M©nôxÊž” ­úÊÂL{6‚^ðql‡ŽaŸ¥/‰ždAUŒ/'^$%F¦I†šX;FäÓx`Îôa<¥cUdCe%—ñ"l4ŒL1²à¦Ê¶F][XUÔÒаÆà·†ÃÛ•¡ºT»oÓå·1g2 ú@†ëEÂÈws]ô¾<X ­pøü5JÁAf P ê×±j{”¹'Óu;~ý‹Gdí~`˜çß•4¶J> •“ ó¹­Ÿ·ƒ1=A¶Sê…¾k¿ JS{U¸eA‰Gök´Y¸”’A”õz±J‘-SÉÎ~Ùñä¦ )2é‚/óÑÎGÖ…ÑÕÿ6NIK ò %-²*`O˜`&@í@1%½ÝúÿùÝbUã;fØ}uõ)È »Ü·ì·™^2ž›…„…m«Vòÿ é˜óþöׂ7«53‚Ìþ•ö¶mµ ª ²ÚUc:fˆáÉMŽo"ú¶Åç9ÏÅÖÜÌÛŠ†’†æ€ng‚ÈMY/™^5¶aX&ÞÂÛ¯Åшl1Ý%O$ çØ¿®HÍ­«ˆÀmÒÇ'Ó¢Ô,zV…o1ª°RÀè^#€ì)Z©#Ϫr½˜E>2&ÜE`Vòz z½.RIÕ1¦Ññ2ý®7Þ’ÚaíHÔÞ›z"ÇöIIæx:¿w ×gB#à"~»Y`S€–¡ÄÓ`Ú³Rã²m2qþL¹sº2†TOG—qd do ÒÛn0Ù@7Ù²œñµÄ¤OÖ5Èêek´ß_2‚ Õ3x‘c`@#C$ è㑎¯€Æã$X©Y‰óÑÞñØ}¿”V2=Ÿ~rËÓ4]^oL%X(É1ý,µ'†³Â>/ðÆ  %<dV€®íІí¦E©ÆœcVr½Sâ€!ÀôwCJioÉ6QmXnœ£ëØÐk§Áó…^-òPÕt=‚ ‹;äÓRW|wÉ-YW3 È0·n=ïv•T]Ù¹ »B¯„d¥K6ˆ¬œaËÀ‚€§ )º¾ÒÄŽéeJG³Düñº|íåÈ2ò;ä¼­Þ×q$HºíæØþôŽò‘~÷q›b„cžÄs@:&kÿœç“3AÕ”µxj†)ã¹9¶­Ý’a„RU-ô‘cŽ!hŠR†Žu‹û5ˆ—ùËéõ-×Ré%ék7Tôsá¯5p/Ùûp¸õó,4¶õã ‰³Ý ‹Qn4¦cVŽÈVˆ6éFŽ¿Æ½^™ªQôš¶Ñ‰Ù f]ÞO©œ¦Lb“É¢‹¥‘Èž€ã¨Ý¬få÷¨îeµhì;ûÙ£¹ÕÓoMwÉ­5òqëJ€ðpÛ§+l¦‡¡gðHþ2RY92шÑ"w宀!Ë*MÓãáö$n#Z’€^TêCñ­±ÛYf>`%­d[Gdwá &Ð+Ñ31šÞß‹1d0P¨2Aò„ëh0»Á­ñb$YÊªÉØ¶‰£päÉG&ÃÔ‚ŒVò\ª/OIPûF˜Ž¤/ײÍÝT—,üK|[iº0‘lëm‡VÊ“R©Úºzüô²JôŽH¡©$p|0Ä2†¹c7ÚWC¹µ)ß—1HIq0´[ÀJþüëÏiG2Ce2q¶|~½dkF8e÷¥(íFw>œk¯«#~ƒ¶-¦Þö1Ž R çÌáíàÑ“ < LiPnx8’Xãô ,ØQc¦J' ½™Àý­‚^—ÈM^ qdF~h*(9Ö¸û~~ P·ýóçlL¡*¬âðÊÅÑ%³®$Wõ^¹mQ<‡ÞQÉ‘È;¾Àn}œ=‡ÒÖk\>rzs ¶–™èJ5Zhe< ˜(ù´ÂûDñŽ9Ž®­e¾5ð>Qm`dV¹)që‹B  ÐÈ…’¨4ÐkhGØ ÇÄ íª¢ß€ eûôPü12’ó~G 9ãe<1¦_H›c|Ðlg˜Ø”ÈÚa¤hzÎ2ÍöaËîh@PpîI‘ùl#Èðº`L˜•bΖQªŠQ: yKVÚWòyùf%`Òt‚aäöQòt>‚ÜZ㌿ñd¢wÈU‚@Ü‘2,»,bÙnM—Ù" ºœ3>M] RŽÉ/+!㪚5«é[Œ¿jãÖ[»#¾^ Û–Á;*9¦ìh¬ä‰€îè[í»“ s1µÃ@s[ƒ'²ÄñçûvMš®`Äa $@Ö ðÙÏì»RKhÀ¿ë([%†fkâµ0T pÖU©Añ²ö½I–£…‰l·rkLc.†¸­%¹ý¡d®ìõªFkø¹™(´õ3 ÚgƒYµ®˜;áŒØ}sÀäƒ7wß¾ÍUâ“Ðóg"û«´œ§M²Š¡dâ}tÅ7ñÅV%?)ëûæ²Fa•þŸ­;ؒŶ0¼ÐÊö“ZÇòÑÓ{ü»ëR£` …Èî™{%; €‘µˆaV•ËuSޤ1×ÐÕiX¶¡.¼ö>¨Ý¥,÷‰h¡Ä´g%ãªâ7ÄZÜ”4‘YåÀÊ24@úkp.âH)LQmáЋÏóJΤ7ÄXN á†Gr 7.ü@ÕcôýcÀJðo¿ÿþ»‹(X¨uO|˜¬IªJu¹§j8Þ‘LÄ/[4+2UÙñ ?[îÆ< [ožáÚ½ e]é•„ÑbOÜtJd À-ÐMkIF‹¸fçÃHŒÊJ3DòÙÂé R* Ò²®ˆ•޾«üe&d.eà ¼HÐ1Œä–2QÕˆöx6wÕ–¡ŒÉ§?*úÐñœÅ^¶˜AJH€ó U12çz3wdÈ_à@)çXKdÎñNWÝ&dM9Ö÷£a j¡L¬ËþÙ&°ÐsÉJŽd¾±MÙv)2Q вvsñ&f’L)ãó_/€!SJ¼RžŽJlÉìOGÙzxY£q",‹âö'+”¤Ìß»Ñ's„1kw$“3‰w\äÙ&µ+‘Ñ#EŒa‚ø.cÚ„ ï?€$h¢û†SëûÚ2±»QÇz·R¯‡o 2€y¶”@C·@ÇåÆ9ꢷ’ ó¬ÄC0µÈ‚̶ùdþ èÛòvŸÅnß9n:P4}@U?ÿÁjî¶Ê߯s Ç–îò®$`ïE0”«6†Ì+ŒÑ7ޏ# Ç#4°vÑbÈ“y>޳ÅÃþŠô!õL°È¶AùÄ|]?ÿ“'ñ6¡Õ|ìA˜Jiê5"Pžƒ#,2yeÇ2Ñßn\Ä-Ú I&w©~x6Ý& dbžkOàãˆ/G6VÝI% Ld˜Àý;“s™ÆÈTaæýÖˆÏ éØ÷¡­ðFkTMÈ4íŸ'œL®=eí1™P¶€‘-£«g{UŒAµÀ‚a¹éá¶zy† ô X¶ÀK:j©+¬©%° PâùîÕÕzî‚\¤Ö’›·UBv$.6ÏÓõed‘XWsB/ ×Å<%YïY5«í‰É?Ã2Rp(à»Rph.pµÇ Sˆ…j|%]v³Rb92 ¥=eV–¼À4d•0œåF _Mæül’‰Æ‚xVŽÚcà£W†3õvM@Ø92J¬kWH¯T ð.®¥éM$Óý¿„ìüfe:Ùcx™£€a¯L hì3¨T A†6"ϺӨʛU;óîV;7#fåØW¼.íº Œ^Œ0BÖ(êÈ–FŽý¦€µ×BéH㘕ßQ)7<’¸£Ø3Æeû0ô…jtìIiü©°×s<Ûßý)EG›4Wna%$Aã¨WN·IŒÔKƒD‹aà ñ‚’Cí0M²áJM‰œ>e/¹R‹ CŠ~ÚEâJÄöqÜ Óà[Pª¥YªõÊí߸F‡Éª:"U 5݈÷†½6@XC® @bÖ¯#OÜtU”U\îÃc|ŽòÈfiÇð´ÐP¥ªx©±AFVò–µ|DL&øL€ÏÿSx^¢2©½õD:Æ7ÙÛJÈÆ4`/Žg"úŒ«j!.`¶9ÇË ˜dV0½#7Pû2 $¦¤I¦$ø¸—* `@Øœ@ ®ÝQï(®ÓÍDN ˆNã\úðÀ–Ofóc÷}7¶sh“ºä­Úhÿ\h7ZUö¶-90®Alk4+Á¶rT’ÇìƒÓKßJ¹Á}±"mU;‡nÑU£³Å‹ü*áåH¸Íé1x11 %ŸCEíÊ=.k¤ìˆñGÐ {™ùcˆ‘@;äk—³­$‹îˤýod#"˦‹¬´Ã Ò`êÅïi ¶H˜O¿8úF3Ì Ó7Ö ûªè"SDb€¦¹@Cå+9)«gCÉø4%Cy‹µýf𵛥ÚPæÂQL¿éYÑcê"{A|í %Ò_Ì1Ä™l‡µßÉŸoW$ÐnÏõšØ}ÓûÏáúþï=·RíªÛ*[í4HÎ6©Å±­ÜܺJ}Ä­áHÆ à¨6z†M|}¸ ×dz5 YŸÿì.…ÂB³£f=ñ4{—v’ (”gÚ÷Gº1²F%Y‰R »a<‡=Ä582ú9ýÊh–5šâØ¿*I,÷ûQÞ]´ žñ†ö‰Ò`˜`dÎH¡Wàú BïØæYu¤¬ЋÈsŽø³ÁŽªJUÉĪÂ±Ì èšáÄ2[CU˸ÜLëR2T10Ay RÇ£þþŒ0ÑÎHûôó­®M÷V¨®Óç%.êe¨7ñ>—È4†'¬Ñ½Z)fb4øJñ1ƵOs#›.3±ƒ^&àëwR%//›ˆ^eƒ@½ªðûyÁÉAæ–CÊ·‘C÷Bªfh+þpëå°eʉ2Ë %¡ÑÄL¾ê|¸øMi=G×äÙhLGÂ2Ad‹ñw4Hd’ƒ,"{¥z‘ ²¬Ä i™†ÂÄB ÙRÓï@#×nÛD•¡£Ò¾ÒË÷«KVcqTϼï”54¶žjÎÖ#À‹ðºŽûi˜ˆL*â9´€ì7g; 6½‰› ÔÎ-g¨·FùÔZ«+± Ž^¿æH¹c$ódەն̳Ƭä âߢ§¯ÄŠ ¡½#Áil+i=2áHL pÆ8•:³U••²²£R|5k'3´ZD#ò‰Ñ Äȵ#­¤Àdô€¹¹ñ'# µËH2¸#Mx Md ÄÈŽÚö““[)õ·¶Râú 5¶mI#TµçS‹c-UáæFNÜJÈ}šôݺ’‚¯+|ã< ²gÉJü»FKCP—* ¦À‘yêr,6°ö„1pFŒ”›®ä¨äÝࢉ€2Þtÿ'Ù'c…”÷nuµ>AšºdG£·µuT˜æv cð@Uzá;VI¯P*ë… .}~â\6.½cO‘cœ’Lé(·[b2&K)רצiÿfÁ]ob†·ûü¿‰øª²’•”Xµ6&>Y†ª_NCP û)¸ñéFdÚiðà vÓÌÛ*OÕôõꊩWÆ -¾HŽ]°Liºªë(u%üm:Ogtï€wÄ×{þfmoäØª½lm‰³ã¢+#UÀ±½}iÂŽ+a,€hïm‰g"S ÕÌá6fÕoF ÙvËçô|_*“64ˆÉ0·ôª•˜‹”2ì)U[ ©+½ŒéÍÅkl ^¦‡;¶ ¼(» ÁÐS ¼£}0ôæ¶›ÒžßAJdb{ð@¥’5î.Žbæmb 8Š>þ°ŒoÕ™·*ÑoŒ h7úþ¢½®Æ©¶Œ>,%ëÝw.2¥FP" Ì·ïÜš‚þìaÕˆ2åÙìî–f[éM@ ïM12² dí™WJ ãå5âEL>éÛÙJ3»>s©k½HJš-Ðn¤T¯F¼Hl–êþ^¶q ônºoo½ÕGo×éU¹ ]5ÂgÒ}=]È·ŠÉ¤ÅnÓˆ·«FJ³LQ­«lážb¥È€œ¡^nÂñŒy>Œ5¸å£]—h+¥™ösH†O#ã‘gÒÕôÌñ;îs¡Ï¹–rL#b8vóYàÉPfŽHb{"Û N´³Ï])öÑÛ é¸+82̹‰Ç4~„Ã2Ÿ.XKb2ޝÕü´I&e&sÖÞŸ+|Ϙaæûáê¤i¢'ª·ï rLŸm¹‹³5¥jæ]J‹Ð«”Æn%JǾÀ†4p´½Ž¢%«Â šªSªeÏž€¦ÅLW’[lí~õw Õô|äFÀÙv Ë``A «Ê†&Û¬ªÛY#w¸øå^ÁÆ´+E·rz¯,dAŒo]Kô‚•ÖÞÆÜ”0ÜújÖ˜¦RUY¤'nQž•–‘¦˜ <ŒÙ±Þé[ id½æÍêHÈx{æ‰i‡$²§¯CP`¬Ñi„U3”}ÉT·j·È™ Pm¨Ø&=]]uåOÓ-&ãk”Ãr‹i¬K^ÔØñÞž31½YôùcèÅöQ‘O˜8¦ßŒÝQ)A½¬Çké{òò]až³â‹z#Mä€ôt0ÀÓÄ€ÀSæÖÕºRÀ”1ÚÉÞÀ¨ÊžhÕ&«ªD#sãÍ ``U]@ËW5ÔQ)çvPûÍc=@IDAT²U‚ML†ŒçLì;ÖG†çƒßÆ©6ßGEVõÂ{Š1ºðÄ@½dŒüšOI¼µyîûL¦L“Oãt9ÂölJ…¼}'¥$Vñ@J4=“Ì‘4·x>©w"žR{/äV{×ÔØx{›I£¶€€}LrÁj<¦ez"SUûHU»!‰ktÄÄ40RŽÎÿKHg é(`a3¹¥®‡!F¶>lõ0È”šDßÅ0¢ÆM¤é¥…’LÉ9}; Ñ1Ù¤ …Rqì®UnJ³µaGy Ÿúµ&îhP> ]Ĥh WSE:¶dXöUÓe¨ óæºð•ˆ‘ºÌ½@†ŠüeGÊôÙÂUñ­WFæ˜!}˜‰ÅÈD[á«&iFê˜&ÔÄ–qT%°À7½.LÇjVñ˜ÆÉgö½21 3¯E>Ïw¿ˆz5Ê®DϤ®Ìc{¶i°^²œáÞÄz#Yu»6ÑÒH%‘IH‘c +€ŒyCex‚îMªúøˆÍ²¦ ;ê…Û#0Lšâh]4Ö0ÝÆô_ÝáœU%U-ªÄŸþ¢ϳ&&€å¢®eJ-J­Á'O-ÖC* 2GUX¶ q+­¤å3æþ-CÖ‚÷ÛkÊPb[KC•š‹0†Œ›#¥LTE<Örù|ô‘hT›î‰rF&–‡Ûªk¾Õž´õ`Î"ACåß |>­×†ñýÛyo²­ð7tהּ)š"è5ÂM1® Z”l cr³Œ£œáºù4±Þž…ÐVô€c¤£È_¿þ壼°é˜ê¼²sóà&ô1Ç·ŠR¼cر®–ÐNϳ.$Y˜1,„÷ÐÉZfæ°À—‘,|ëG@l"؉Ï)6inGš[ ž&Û.8¡…,àIì¨÷ªÎovž¾[€ß ‘2ebúÂÎU š+óÑØ 0”~—MS#ÆqlaGûøF“yWh‡~·*9Î3AVeÓë¥Á4÷ÜêûY#aƒDkÐcz ÀËdeŸ”[†^tÚÓ aëi´Ódå‰"yÂå»ÅY#œ›¼qùÈüÉl 3EA¥ í¸‘MYõµ5E0‰dëØªšf/Ÿ¾dé9¼¿eh„’|fÜ ÖE)6eíö¤r¯7™–9´=ÀA†pL¿¶¼àIÉpïàˆ— z8²8g®ÔM¥ãx{Q /bdû ÿ_†Ü¥+@6à¯=·J60L”d¡&à\o†Ä¢å—'R‹ì¸o5YU½pæ@†@'Cö‰„&ˆäŒÙ‡Ÿ¡’ “»‡–‘cŽ–å”KX¦“ €xGá“ÖØÿnª.%K$ë'm3”‚`HÑÑ}2wlc@»¼-kGx½”"ÏíV—õ^CúZTµÀ2Ì„l¶‰žã{·ï×—{ž†Z£k6K `(ë•[ŒaC[/ZF ‡vÀ$Øn- C 4]; r®±+$Ö¨ÚûîÌÏŸL¦$«±+úFŽþÓHïÐhL²î•¿R›È ÙšèMìH™'@À'ÒËd‚DCñýyÌGTÒ"zðœe¶EÓ)#)ñ½üdH8·@s)mÕݵ(I_±£Ð£ÅJµ “ÆsÁýx¯E©{ÕXË1ý~Cî´“ÄÛ¤7¬Êáv|®œ˜Pêûcâ«1ÈQnçmëÚ øÔ˜ù.\WŸ^ÇzµØ3]ù´^88^ØíÚŠa›Ü™'ͯÚ;èí£ÁlnVi2 sðGrz=£c ÐT{ko1Gb†³ªEÉ è[F¦ÜO ý– èåFß'å(êB¾w\»AåÛqJ½6¦‹¨Vʰ¿‹Ì¤¿YkÌjCif›àüabu"¾ž ŒV—]2¾¾È–ØÞJ"¤ˆ‘µóq-}$.ãHÀÍQVxÊ1xA‰éSÙ Ü= M³-«2„­AæhJþ0>²¡J‘ 0E8îÆ‰u]áç'ÐQÔN¯Ôhé9ÓûÛmΪñvS’ž®‰>Z¶’£YûàÈ0@t†°lsúdµ[)IU‚·±»ø¯9×(cÔ¬®³MF&«ªË faˆHé^ø†–lPß:âjI)S²"H07^©…ª|êÊÇ1ð®‘X—RÛÖ•g-¹é0b#4:*aÎìçï¤H&]S£ ó§qœƒöJô€x± ‰‘ºê% ÏŠ€¹ck¨ö-ŠAr›I½-“•*å;"}íôÅëû.m( %b¶‡ۥŽd]kê¢Ô_ùçKã»L‰.<¼–ÚË”JýðÓD³{õÓ­DÙ j. ¦o.“+í¨ê'”,Q—’¨$gäÿ÷YÄJ|”³º .‘× O†°ɪb{Âõ~þC`"#yO´´†¾|­Õ 8ëÚ›—߀ +5¢gQcJSÊ9§I3ÛW–^¡±^¹Ñ—8¸OÝ1‡4ÀpL†=e˜À±êòøyÇfÉÈpËÃ"vÜ}$ĪfÕUÞzŽï2L”6=,‹3ìûsȪ‰Z)Íê;TW¹Ð¥žLëÛbI%‚€X§—)itÉÝôÅ{‡ÉrèÏ6­7bæù 6(¦éž‹®¦t—yb²2ö¡ý_FÇÇóï.ªB‹#’g7r$+t9’Çád-ƒ´ªÙQ0a2í 0ÉrFιqr»—–Ú§Ì6¤c>À¾ó?9ƒsèthº8‡L4iÇ^ƒmÎYUöcXc Ü#{%ä{M¦ÉbLD …cÎZ@.ÈTa;ø¬û‰fòêU1|<àØ¥Ç`4‚2[ M¼1œRÎ'ÛÓï¢ “2ó=Ešô|yÑ’ Õ¨KÖÈ­Qor|™ÃgÏÿþ÷¿ë©\¿\sd7·1,†cäî0“|Zºm``—L0}¶|j‘öeªEn%ÊÆ92)êMI øÈ;ÊzåÜÎÄÚ1óe<“é}öôŽí¤|7iŠ,“eÞ,Ç®I£ÊüÊ?/œ^™K Åñ° d}­Ž:Ú„†IÓ•´W•‘о#¦c2&"‡˜üùPÂ"=@ùj2×+ðdÈÖ†µÌ$@YWžÞ¡F¤@ʺ’9Ƥit#ð ­«Å` „éË׿¼@€ÿ;Î ¯® ëê"µËÙ¦”E/ß»™¥e³¢ñ2}{1‚&O¤cÎ1½^žÛ¡knþºšuWøü˜cuµC&˜”‘6Áô7\dûÐ$3e Á»mU-Ld‹âaà5tÜòùÜ9'wÁ4#ˆQ­fB”è­Gï.xÕ<ÃJ” ÉÚ§vxÿxJF ¼pD’¥žˆ\/~2€@/2åôgÌ šµ4™@ŸçòZ>ÿ§ œ…†æÚ/>Óª\²IƒìÛS©c½åžÃËÚ&†€˜›)H™X—H€1"% (]ƒó”ŽH&õÊv<.Ïw&À ‰û–x«Fx_ hÉœ?’€²?Ùˆ˜¾I0RЈ¬ðm«Ôd¤qFûšÆ÷tMĴ䬸Õ¨Š>‘Ö^ )0„•D¶<÷Í®Dã¯K]g£µSºµÆd]àšýå+hVm±fa]üuÕèÈ9¾ 1Žaƒe½ñ0À'ÃDÊ™rxÊôxëÙÁ­û8u5ÐÛjì…‘á<õ zU<2þ5ÁdȆ> óGÒ÷»•F(•ݺȄ’Œ·Ï)|ÿ¶¡=Ï™gHd7‚)u‰üÈñ6ôh×ÒkdE ‰³Ä Þ1q|yíM‘[ _ɬ¿Ïl‰µnïëU-kr;úÿûß(g=…r—0°€E³éýÀ˜Ñ0²U #³ýÛUûBט†þŒ¹ |†©v4WoX&kPëå#e¯‰ßY¾4µ´@þº2!† ÆsÐ2CÊôÍjO¸e:n%¤…3”¹±;¼öø<µ ¸ÑJ teå˜ Ó°‚ûì–Óãûiií>AÕ÷ß{dÒ-jo(ž ¾¡wåÏ?‹(á™+‰4ÄAST…Ç÷‡MŸˆj¼^†adk;¢?u˜Àd9kÉœÌr&ªŽò[uL¯ïA6®)FèŠL¹ö>,¥.ëØ‚@- ØŽ"ç`$ÓÞG“¦’Ü.K㹚Òé¦ÁÓÄëjl•Z¯[ð”À$Á6 êØ)ý]D©AæÝ…U›÷ ¿ÇœÓè2ÝïV<³%#à,hÂHâȔʘ‚òvœ×î•Z )ÈÚñµÔ.$¬è3Ì¡U u¤ñC‹ÚU=K-øzß̼ÞZzÏ2$& R„•Ú*M¤AôÉ\¶c™ %ü*é-ö«ìLD¡¡›4L›cŒªc ¬E6²ïe“d ª$ñ^†UÊÚa£›Né{Œ¬Š|ep-°ªÆ9ˆlɸëûcïKl½vÀëjÛÛw>¶+ÿ´áǨn¡ÉÁÑSXÌqËÀø¶ wì.[µ}‚ @:Ê-‰ìdezÁÇSíG—@Ð#i´x%âÈSônabÊæêò_ñúßÿþWcãý£ýõ>ædž2™¬š¾ã° ›k8¥ÌA ²êºf5ÆPÊf©v»ªÛÇ‘ª»ôѯ¥Û9µ×Û™[ Àèõd)Û°µ1FÀÚñWrŒµWjUC‹6TUêG àõ¶R™ ¹À·gC-I“mƒ`€O"·X@»ªPÊ9–U€£ÿ€ìÜð{÷4óL–•oIúl‘ñr &팄…’_î,s'þm†c %ÉÂeäHÁ°\¯¹@ËÔÞPL¤j ävð©‰Ü ”Òla¤RG¼cLâ&“ÄJ”ør[ɵ¼$Ü‘˜ Üæ,h|†gn¨r»Â ÂNàn‘Žæ•ïèÏ–¯/ì>N‹ìWFЛ-r£!€¹©F¶ nhákp^‡¦ào®é¶†’¡ª]ªÌ–›ÃFlPSº,27 ÿé×nÜ\šx]¶ ~WkþsÔÒ\nŽÖË Sjzï¼£’q"M&2“þx äg”L`]M16TÉo(^ê*vUšüéÉêÅSÆkÏvmTš€d½Œ5ÚS‰›^¥z‘ŽMÉG¯c81&Yd÷Böt4ÉdnÞ$]‘ZàÂ¥ü?ñ[R ë¢Ô•ÓÑæ¤‹`Ò÷Îx ß1AƒÚ–gÑøLýþšKÉà z1ñ}R5z½ªŽÄ<Ér&î¨È‹•öàJ|{oÒ¬öQ5‚ŽñònV7’×ÂÁ¡Y{k'Е¿TUJ&벘j])ñ€¬=‡2Më•3i¥ôñ10¿×P¹–OAÀôƒÖ”ÛüíRe%GÁ§ÏèòzpšvÅë“IC»BûÔ%Gaè:_l÷©|¼oô²`㻌¡·\Su%k¼ÈÙ dº€¾Lp 1 ’ÅëꃯªKÝ÷žØ1gzßË~˜9g¢š@¬‘›¬¥¨½L`J<#¬ô’Ü8«â‚d™#•„cã`ûßݵô]§Qå¿ÆÖn‡LàØ‘?+-5&à¯Wn%%“‰‘4®° –Dú5'søzéûo¿¨2Ä‹LìCß{¢Ad0 ûDÊ”²À\Ð`D«rã zaki+GXc&dÊ4Ž{“0}_ µSjïøï¿ÚÊW V@]-æ"4î›?àÙÃôËîB3%¡áÖ•Û­/ Ìm»Ñô† jŸªxâfé5H#Y ˜¢·ÑyV‚•Æh×%òiJOA#L©*·I;,7×Eˆ{ŸpV-ƒ1T»ÏTl\ÓSªv/Ó‰Û‡’¿v¿ &C GY8êLëíXWø§q$Àd²WŠlJæ²g·[]‘u×2J᪰q0PI;,ðÂQµÅ"a€ø kWu 6wGž”ç¯~©­¨f˜I@0]ÍJ¸E)áÞˆ¾®ÜÉŪ™àEÎaýµ¥‰d€¯Ëާ¤/k™áÜ”¬”À\¼¡)H>™wMU‘è"Ž…#€Ïưê'Çß \-çx¥6ÄDÒ`˜PÂñ”Œ”ŽnUkï†] ]S’uObÕºr¨½–dZ¶FošU¹^ ŒdåM„}íl„#ìYà”€ñ‚Ó-䪵°zõFˆÆÑ0I‰œ?Ù™ƒ0KiJG˜²œçÚßÅ"ñ@á:u92™P5´YlYõíô¤g{Ydš¾0Jþ`¨¥ÅòlJ|³vµŽM¯E ÉÐÿû®›",À„ =,Rt”[¯\I{hq#ˆ´0«ŽLèÃ9Ü™çË WV-éÃlž ]Ľ´$(ÉóíêHÙã{½Zð½ÏF¼žMl=½EG2 Ï'¦£=[Àqï¦ké˜Þ±ÐÅÇuÊŽ~Òeþ­M_WJ¸Kiá ‹@iŸŒG*ŽZäæÊUéÓ$Ûb€@Ь:®0Z.`2áOŸy‚J°¹Çú¾À ðͪ»c ?Žõ7L¤îÓÚx‚LeLà© |úÍ^1ž^ÆÈœid÷ï Ñng‰ûËV¯+qrû47óªý@`" Ìj[-ãŽó©ä˜ƒÝ¬Ñ±Ü³4“?Ð]±Ñª ݶ›¸AÓßÖóª&ª2äãØÝå~<’5Â÷£oOSÂí†aR{ß¹¾Ll9¼.FÉh‘ƒ,·L ßt›0l[€FFªÊ‹ÔØ\d&­TµÛí_Åò×îFyºNƒf` Ȧ[»lJœ$ãÙtk(ÉxJímÞ¿Ǩ® xçæP¦)¶[Ʊ5X÷>ªøÜˆ5z¢s«{¯ÖK“[bÿ Áäuh%$A›Àñ˜HL¤£Y¯¬ [&±.½w»Ï†þ2¦)Ý]ãHØ\Gï ЋCf˜f i¸ÛEÊÄJ]¿qÍ*'– eSjœ† æGc#jQbbá _e˜X¨ô…Qí‚o‹q)ý„¿ÐE¦oO€9¥Ñíß²Ræ9çӓª eVÓ0 ¾ ”é´Qh“ñ€ïk*·ŠÜ®€F¹mˆÝDWžµç³–®Ä* jp(2‘U•ü|Ú8ì¨W®ŠÔ‰OذëÀ˜ö!ÆÌ»†ÆvK´Œ?Xè2H—è«#’s#è•0Ž[>“²R wƒÛ*gdíÙæLã(,@ XÆËY5QU×ûµÓç  %‡¬Z #«FPú¿¥E ˜R#¥YŒ‘ñô§®4dGý×7O¬Ô ª¥õ”é1b¥žcš®ï÷2ÜÂzU}p6Ùô¬´Ó´R†­ÑP-HÌÖÈÖzxU<Ì¡gI¯¤½*Ðצ¯®RÛNù.x@D¦lÏô¦Ð|~PÎf¯­²~Œæ>B  Tû\Uc0"¥̶*f¥#c ÜZ™²ªì8±#L|³dÑt%@5Rî#•¶Fι_8¸ ý‘¦‹߈9ï› R¶ªÜM[CI÷ï"¸ªÜD ÙøF7Eµ+èÕ¢ÚqnÈF¤ô˜YÅõ4ºæ{[Z Lù¯ý Î\Ë>#æiÚVIð}|@Ž]áOâVÀºÈàaž#§$ƒeU²ªµÇË•¼9C?۽ض0x]‚ر+(á`¼‰*ž½¡Ë”þ¡D©/@‚.²#}XV" úu¦ÊGXÃ8š¾Õ‘kÇL3Cš”<5¶ Ržl¸ÉDnV½‘˜-ß­†è /¸ôáíFßcºZŒ}x æJÙ6®ë·°’—Ï<‡†Æ” R2hÞ¦w—&Ê[‰l›àÉz¢³ ñ¶#¦/L·h:­ê‚p—%&“OçêW‡¹xbḻéñu¸iÇhäÚ® ¡3l:ŸH]5vJ@¦¼K}þ‰9»ùÏ(ÚØYM8ÊÙ© 3ÒÀÆ Uš[ü|e1;‹×!qæM¹½‰‡ù×€½KÕs“U‚Áæ&@67ž'ÍZ”0‚Œ`™FÉÛùÐИFÐÏ î£ò‘Ó8ʪ‡iï?»CΙ'·¾pã"a;Á…#e{H¿qø°ÕÞ$°¡Ä˜¶ÒB/§DÂmî.n„ÆÃnazÀ¸Úç†ltJùÝÁ\>Ý¥A›ˆí sY¦çCÖ[4â4Û éæ–­54ö€}ð§o’О™;æÐ;sИU%_k|²Õ%´lVnmž•ö£IÌ„C&m›’À½mEŒÑ[î¨tîùÖp š2¾÷ÌS9˜åR¦;¶ívp„)»òmúüó¬Ä<X»¹”µÀÀö‰$nU “[†¡’i4Œ×kCÀSÈ>/Yàe&dbæ}F˜ˆO&þ,šØžHUĽ›ë쎞(œø:”RW;ë­½•~¬A\#±ÈÆ ÇĶ¢©æÖCS{_Èðªô™ Ã.å=û\6Q#An­T—,bÃ*·•ôÖ®J“!ÜJ]§.-)‘b>º­×7¼)ótT"fˆÌ™Þ‰ñqDþд0A¼# ˆµ[hŠ£ ÈŸ˜j!ãëÉQ'¦Áf{Ó#€,/n s_PnlûJÑoÜCLé¨&–aU{ kÔKVÕ1ó®'ã«æœ¬}ºvMéÑ1d¢–&ÓÔ’9¬WȺ²ív4þ¬†‘Wµ¤Òƒ ᘌ#g-1ô@ß¹ª˜É€”–‰[FId¥Ý íŽ=]&Ö#Öõ6RÖ(7N•C¶2œYJdܬ‘ ^2¼ª£È?>’é¸HI#`™­*™€‘ â€Ó;8òܯB륗kg˜Û6oŠj;œ1÷Ýx†uNíVeäxʾ¨¶R²†³èXnáé5B&pkç¹®Z@-J1ÃÌÂ0Aö!»BßÕ>b%Ìž1`³Í}óüážT—¨$Ãî¸ ˜9†’ÏW@×ácäküùк+×Ȫªjé¦ýo$V ÔhPFÒ‰)‘É|»ù‹,ó÷S®”O]»N³ðÉ0Öˆ|Llé zÃf‘-¬DÓ©^¥BIÀ ’ßÑp˜L6·FJ¥ôsÕóÛAÙY',ÚÀ–È:Ëz„£NÕZz²Ž=“öW£w× §l-¤^ÌÇm„%ÍÖàÙ·\»®v¦JŽ”áhDíxXc€8%F¯HÖbùXÀ±5긔½•Rš.…ÔØMúìUªâY5`•I]ô°Çï%i0 ÀÃiä1LóìoJ¶È=T>4JxÕÉVöÕß›w}—ÂXÆ‘RÄÓÙkâáŽFðþÍ %= 0¾â¾fV’í´Iz¶Z0z=€{Ÿ¶Ê,hLOŒò3˜ôJ)a]J–ñÖ ÌÍ8dC•dJx®>,2ŒÜ²Â°UkŒW­J†„ÉÊ·õü3€rÛâ»q|+YµFd¼‰¶!‡–<Ž7¦O†s/¸«5= — ZÀÄ.¥‘ÌÑܬÄ€LP洞 î: ÇÍªÚ ˜CbíÍ¢ÇÃ)ñŽñ1ª X1ñg€¿ÕY Ëö2ÄH²žà“Už˜Öë"mBìÝ6ˆ¦áİqZ8`º‘¹ÓëzƒÒn-6@{ûȦ8Ê”<ûÏþÓ`Y`ôØ6I΀ҪŒb”ÄÈ]@©”LæSj‡:*¤žX F6TŽYÉc’)å“ x¬Zªb·F‹a¼  ”„Fb¤)1J}~U)é÷€½­ÎHúÝ‚‰–3àF¶`b%ãZ©ãFD¶a2¥Ê5rZ°€|Õ8ÔèXøE_•7½iˆÒ È0^˜ƒ͈–iÉöAà) ØÜºš˜-%M-@ƒ$–‘ªxÇ ²êªÍ²F)[&ô2žyV˜4}+âs›'=LßÐΜ¾£RGJž@¸Üz/‰!î·CÙJ¬’åÃ!OÇps»%=^ØŠRuµÐ¨¦”…#‡2‡ºè9Ì#0 jÉ-å¬h( ¬ÑÏdHbÑcת-°^‘@—è"7hD†4sÖ›X/¬ôš[^µ’˜Àl„cC ÒTÅg®Ú7Ó±f@K}—¡T~/Ûè[ÿ|¥ù#ΧMÊ-ÀM)ñ4›Ž_ÔE“g¶”âó¿UHêEZŽÚ‘:E.J :žÎûcO #ïÂç;á¿8ؤ†õа—êÚ2ÜÕV糪‹ @ ¦·€D-øZdTJ ›% æÈüù`XiñW¤ñŽÚ•hŽÝóµÐ¢s+çÇ,Ÿ ¹ñd-i:«þ F©+g<Œ§Œ <‡ºü)âØ#ðY©vA-ñ@·S2º}²ª 6Ÿa¿ÝöG•2¡)ÚG‰³j•šyÇ-™O/ &>8Р@Y 4ZÒQÙ?ÿùÏþ ©¹­‘•[´@Wè…9Ð4½ç‚ dG]wÈÙD ¤ -ã}3ÔnŸ9ôž¦4O-%Ç–Ì_W$ €ôüUwì:Ý 04ez ¹µ9|ûé‰÷˜”è:À4zóÙ·E/A-AÎ}æ[†@$𷇞‹@¨§ÇxçÆå_ƧÉǃԛ22ìØª-Ÿ¿q@ú®I9ó)i6‹ÆäOŒ™IÕwJ¡Ÿ•þ2^5Ð;Ä"˜ÀÑkè}yzU³àÈ4F@(Éék$·xª#ÓȪç›"›T£ȆÉc»³uíÑ…1-±Ëœ1ß¿dm–›ÒncÇöqÉÆmÏV'(Ú¹¹ðöјð¾|¼ëÀ_ƒ__<‡ž5츹µ4.Yß`>›Žï³„–Þ!¬EîŸ)iô&Z¬µ­¡ƒÇ‚^Î ?[<1ŸÄa12؈mÅ¹È Èø57T H¬êx:¿·2%RîO¯&fØÚ9`ëõV•ø³Ò+{%%|Ÿ=F7e ^I¼ïO ”g{Z²)³ 2]h‡¯Í™"ÞKõŒé·X†~Où•W¯.óÏmÎ×õÜ1g-”µ áx@Ô ´‰«©šó®Ú¥È*5Åßè1®†¡_‹ý‘ {XXI¦ÏÊè"Ä»Œöœ»—#SºE¿¸;ʦÐäÓèF¤Ç“‰vl¥F›Ø8šde²Öΰ)ð°’erN ÎÚ›ž,6¥ ÂÈmˆ×ršïž^Idΰ’¬ÄÀÓàíms‚dôMÁ¢Ï…›ÞÆ)-04<1@ »¯j%L8½¡ãañù?¡ì 7Î 0Þrë?=÷L¥©Ku7l-Œ0¬ía&Ù‘²KÒ3̪Ü[ÀÇâšÈ Ò¥Ö;Òû(1rQ‹ÄÍí >.÷h$Æó@ˆT—Gæöê»×>lúüë壥 1U1sÆ4¢éŽfÅÀ‚ÃÙé{Ù."Ó‹@κÈ`¼Fø|Râ—¤Ï_‹¨lŸ “…éÝ¥)Ñ"w4¥#ðV“­ä(ZiAïÙ£å6ÿ™×.WÊJös°¤¨TãÚÆ™Ô ]JòÌí)÷iúĉ{ÿÛw–Q ò_užx‘ ï×%ÌGnŠÞ¦·Uǘ¥Rø]ÀúᲞªU) TrTVÊÇŸsJ¸.|bŒh“=…öøJrÓým€2±Œw;s5öGT]JÖkŸ@û¨ is %ñ°¼ “¥—Y7“WîMÄláœ/ýù°øƒ´$–ù…ÛG( ŸH³`·‰³r„Óé÷Fݱ7ÏŠ,e ¥RM%Ç×!LCU“}þ_BÖi†P1DEÏMªÿJÎ?w¤‰!dªä`ý¹äã§ å. 8ê%ä¢ ”œfd& +µ$R4OÐ3¬,¦„Ì6M;à)Oçw(7˜˜@­ \ÕÁPnž°ÜÜnÓik×ÚDZA‘µ(”Ñèíæ˜CC/š«d¢++ÑàËÀFæPöaaŽÅ}sd-«¹ÉÂmŸ,¬»š5`†Ú9#}sü5™8”E$\»¬ Ï#t…ÕîBÜ[F·!™jÓSæVc™!= ¥ª¼c[eŽù1Ú‘ßCú¿ËbäÜÈ4 Lí²é=Kâ4m x züœãcÒWÚg„ȽCŒcJG&Ž2Þb°hgU̱¸Áö ÃZÉ|Ç|4çâÖµé™ë­Ñ›L<){=¶z5™g‰{ %G¹wتkœOž5ÊM¬=Ï:+¥˜õæV¯ø4xXtS4H¹qÄbÇôùpplsÙÕ²’ua8ÓGæ/@hÄŸ•µŸ h|¤†6 œéd™âµÀ2Lɪv7QÜ4ád•´‹V$€U“u% ž8^ÉnJ˜áóWÂ( Àèá€3æ±ÿ‰i esë…4ÍMÀgko"á(¸ù×ëˆo+ (ezŸ–l«4ôm($«ÑJ”-Ö\U³(=>†L & ,`%™˜ F>‰sŽÌª.Ùoÿ·Å$ý&ngW@ªæ“sÿU sëRE&cÌâ&øÔn4FW10f¼Æž.ç²vü|1™[ÕEú iÞ_\vYzÁ/àÅ´ ¥r‚ºü N©Úþ²¹ÂÙbz·0=ÒV Òb\&˜>dÎýºÁ×ÈjXK]-ÉDo¦‘…q¹Á Åpsl4Ò›#Eíla†²eúÜdÙDKÞ]ÎwµÞ‘ÓïçØ'[©Íe>" ç¼öŽùÈ‚‰rtº”ðkï¹TÉc\2<†¾ã kÑå‰Öž Y/ã(¦aËMI»¬TNю>µZúè5* @MiÉz1ªíO ôùqTD ]8õÛFÉ« qTMp†¿@kõ¥çÓ€^ÐN¶/ÆÍ»<>Lì×bãš’ŒÀQVŠ‘ELžvÃ$î[Ž °I§ùùr´!†Lî5`  ÏïCeNÓPæ€Ì¶Bz@c/P‰¾Ø’=,OzÚ7îØ)Û&Ó•†gû`€Ž4°Ü¥”ðeLnÖKPW£³’ ]–ÏÙ†3ÏÊ€è´À4Mÿzœ5˜+‰i`޽OzJúd}1MÀÄ4rkãÝKpK¯—“Œr¶ ¢äƒÌ hCdWv¤Q0ûbcö\ü3)c <`‡.•›,¸õîV]#Þ±ÆJ] PÂ󧬯‘S£c$xý×B†ï¨‘g½ø@SÊê8Cd¼YÉr‹÷SL)ú¦™eŠ£* ¥ª56"C<@ÆYK+Ùí8W^c¥u)ù³\ýx \—2ÇH²ô-‰od²o‚{M™9}ž”°ÜbÄ™Œÿ¡gÒ¬Ä3Ü °R__EXDÊEûÃÚ….³úyùÛï¿ÿî 9‘g:Â,êÂëOO)fÚ•(ól3Gš9Mæ0 «µÀÈëzZrÎG PM¨ùÃZT{_$ F—ÜÇÜ8%š™ÇO?P(LÑó\*ÙF’™¨ O,ÃÈLÒ`Ú¡erð}OSIWÎJønZž¿£pä`5flŒ%ûF3÷YàëêséW!·ªÚT¦™ .™¦ýÇh/VÕNã(Æv»üß%k!0Hþñm©—9™\{×,¸£ªÞfmaG?̽í#׋Qrdâ}:Âã§ÇÄzsЛ²ŒÇD; ¥B‹ýñ.ï¯AkL£DãFz•ø„‘9Ëx™ )•šŽ¬ÄM´@™€Ìéñ•*¥‘s°vL£a2¸éŽz);éko™ÆÕÓËFMÔ娗VI¦ªŒ—#eV@X)&ï›sš–L&SbØ,2?¡ *a”rK`Ãz+µÃ:Êb>”a2&J=øøüe¥î+¸Þr;S¢àGy>ª‚¢—5[D’"e“dv²ÐÄÃÉ9´¨]4ù;6Ú±è(+‘µÉ6”¡Ðâkä8Y$ƒgÒ&€#>Ç"ýrseJäö4ű èU’)Eƒ2Œ+ñ àHûÐ8¦TÂxdJ™y{Ö¨åÔ]ÒÈ™l¢Æ6¬W& šX#ÏzñôŽ@ ¢.nºÚ–,Uz?6ŽýÉá磉!ÈJ»)"CzÑþMìš0Rp€õú•çhb³ï×4†-7‚4YÁx½L´3¬J‰éRM©—Rc|†µ¨!˜Ðù¸eÌ‹)˜2·É6Ôz:†HæíüüƒY´†if=&Ž Æ)ÉJL%™í10@ šLWJ@¤É­öJ²%GÚÐ:ÊJÄéM© #™Ç©%Œ1)ÅÖ€‘Úe$7&ŽZ€ª}Ž{4×Ò—$ÃFÈ9|ji=2ß^n½j†Ëª¢cG&°|%d;ðTò©9£!è÷bŽ4L´Y[ùÓ4ÀT¢Òçœ'[XËd¦ =]>9TýË?È+$¢nE@¿D/Þ*ŽöÈe€s;>ߤ6&îu¬XË·Zh4f.;Ò¬==ÞbaâæjoíF8еuÃr¡½'FÒ#°\pNÙ2ª€’YJÛ/`Û:Ö¨ϪöF«š 'cHæÈJZ€ÂóÈ*ÁYÝÎÑ2ŽÆ݈8O@©#e]2e†ôiLÌ!+íÙ:Ö˜,^²À ½£DÓ¹£²Y‰³5Ô7 ß÷ ÀPò!«E¯MDþµSrè•€Ú$è ¶È>M|[5 OSÌDX€øõ¤i=ûÔBF ±^¼ªÆ°<@ k1”O#jì‚}Ð¥¶ò:r½Y!»¦)¹9+ XR¤ Àe2ѱqö!C–»‚£%ÍšÃi»14–즎]d‹añ™z'д3fsŸ )“‰ºÒß០s^6‹’¬ÿžÒôµËÌç©C†1·ödM©Ñã8î¿üÓ瓸×ËÖŸXþãyv‹dÕp §ëËà(”ÚpÊ­g(çž&hÛ– k?¿qrÙ ¯QRch0ý™ßÝhðL³NƒÝóßU-í¨æ? Þï£^ž±Þ£­"å¦Ñ÷έZ‹j‚F3©ŠÜ'ý#žªÝTØ,‘Æ Ì<Ò‘Lo?¨Jw‘Ïë숙jÓa¥þá+&päIË4ÉLlU‚–áÜ2 #aú†æì˜!&üµàëêR2}Ñ0pT] ¬W`Á[m®\dÓ7B6Áa«†v}|LÛ2We‚oŸÄ™«Æ#19°…cÚ¼0@ù0DÊChÉ62A‹)ÚDοÞ0RKy€ÀC1|«ôÀ‹|\–Ï7ìû#Sm甘]!¦v8±œY%Y‡);ÂZäþÙ¢ãL^¬ÊÖûÈ9Ä̇¸×ëc²ÿûŒªºˆcøì}h€Uk1—' }…dthÕ%‹3Æÿ)´Å#Å[·=`••ݤ=µ¯Ñ1YLUŽ&:Ê}×aÑé&XîJYõp-ŒÑn:¬Ë†ã1BU„UE Ë~™ÔÐÈ.kŠÀ·1Œ ¤ÌAf»”‰EJ LìȈqìçÙ&•¼áâÂÂô1º|)žX‹Ÿ+üü ¦ 5ê"€^hi+ Ù6·Ìjž x"ãA?¥#±@Êd}€£q9hñ¼µËs¨7½å­Ê¤U“½&M¡ßÚ²Þ YÌ? ‹z™k7¥eZX)À|b"›§çP`, ‹›ó4}%Žï÷›<V° ×pÈ­=ñŽWòILBøÖtõ¥RÒo:=¦A@‚×½c#Îr7Ð ¶ý)õºQѨÎÊÕ=B7:Fß¿Lð!0Qh÷CKÇz öâþñÇ5ÔŒmFeä@2)ȶ„#~óì¤ZãßûHU99°åV]©¯õ~ðšk\{ãÛÁ>ûa˜þÝ„¬¯ŽÆ·«—Ôí Ò%º;Ðôè¨´ï “>Z@)èr„gsUç#yâ­G¹ ia@ιÝ2ŒŸÉö¬Wf«šØ1FÖH,+4ò­ÿJJ–yVKÙ\›H@ëjÃ1œA#t„oå|¸>&UC”H¦díÀvšx™[$`ÌÄQuaá³KSÎVËÛ…täoK^ãcUTÊVét~¿BáÖ#´ôõPrä†G֮䗅ÒJ‰Ì[8¦ç"n¬¶+|U¥†jl g¹Ñ™Ô>¬’Õ’`kSŠ÷›O Š‘Ez9â÷qÚÙ¸zˆj'v ;ÚŸ2ýZ€3éûû}£uMÃÄWkÊ D²®Y—Eä+ ·¶0±õ€Ì5þ¤v#&óåض'EíiØÒd›ÀÚ40^hv“w #›{…Ÿ¯ÓQß`‚?ÿlîv ª²H!¯4Y@‰X;@ˆ¬ ƒ·k Æwm%ÇVÌÍQ4×ÄîITÊ­ £«¨ f.z2 ¦Åhnñ“˜!]?Ãæу(Ù“F ÊMÆ» È­ToJ|ÑæH@FfÎÓ½l‘më(àHJÇéõß'°°/M¶é‰í TáÄ€^ɺזIS‹ }sk,÷2½5Z@nÕÙ&¨…'7Vª0R†1L”äô)1ÉRÂüë…u‰µ§lyz“§.˜³÷‰!Ð[ð©äH¦=€\`È”Æp7ךvËö†uµM--i7‚·ï(ȬÎzã›B©7rÿ bŒ‰‚¸ÅÊfý¸‚£èÄ܉ÛÍ;VâܱÜkévÄŸ’s—T#$¶yÓ;¤¤i7€²èØže¼^Ø h6ÆÐ,Ó$Ã{¨ùLÔÛõi€VÒ›yúFœñ7Tés ÞZ@ÞKÒ÷!ê®ºÍ …k$vijmÊ–Áói"«ææ +ÉwÁóÑëMÌ yʼRÔÀÑ‘£PÒ†oLmûD¦š&¦Ô…­˜I¥.w”'¦OÙè¹Á-­´'¦o[¤ gê÷™TñŽz-ÙÛÑ •ð~Àª5n7¥ø¦'.WÕ‚‘Ûß/ÇŽª1&6ˆ-ÒÚFàC÷zpÎþÅ8 UY5Rz™^;†¹ªOäªÎïz¼®6Á; Êz-SW#à¦5Qn\«v‹þuž!qSÊ1M©7>¦Ñ²Y/wħX× ‹HJ&˜Œt£J².KöJîÞÉT›â(Ü ó’†â9#û8hɤ'À0¥Ywdz’€‘)mu‹çCÑ%áÄôÂq¹ÏH•Ò\â>²>…)(ÍJ£×Ú-Ðl(!»`žZDŒÑïJ˜J¦ëõõîú4-Y ðíÖ\Îñ–ÑH$n ˜^©¿ ¤ïƒÃ3©=ÜP™ >qnò©Eɶ›ÞhG;רK8* ½o‰Rà#ûø4:²ík†,f&³ ²»·˜#çøaa]M¼Ã?ïF#š‚X¤ À½[<1½FOÔQ¦'ÿ¯­»Û‘ÄÖ‘5zá+¿© †Þðõ,éËŒjà ƒAJ™UÝÞ‡æü¥ •ÂoŸ4ìCŠ×/ø"[7^ö­j£¼øàá4€.w£¥Í`5ʦoÄ4Là¬R:R²mDJ›´¼#^ä‡ÓȺfÂÓk8"÷—?GA½^ŒçþxÛD/æßôö?³¿k%n æ†jW’ñ-ì(`ï)"ù˜Åœ IÇ$StßMX :@V3)ìs!Àg—2î>€@jL0o’¬* I@ÓeNÿ½¦}èiÖ’Ì>U=1”J¬ê8óü)‹>¸UâJz³²FSx"Yaè7ØPŸ:^#&ÁíLCióÀ/ت:ÌõR:r F®¥Ý¶v--Ó&Jôø¨éˆïFª1Ü`½޵w¬ÔhYo¶0ÀMÔ; ‡Ößg]®…@{-‰Os[XFFî%á†Ö8Þ‘ÒQoVŽHÑÚ¬2׎$ÃSâ+5EWþ@wI3’¬ Žç¦š!œ`>Ž[‰¬5”4Í #mBÓþ@áØè”t  *<7Œ Ó+òш¬Q·FW½1ÇôûOŸ6G:öAtq¤®ý,d+ãÉ8g¨+ÃŽÃáF·§#|]?WãÌP¯ýa²ÌõRŠ@VŽÙÒÇWõñ¬*#ùøIºHë)™²€À @W«*EjŒ‘a¡d[GνÌõøøtÇ~É ˆ1Äͪ.Ó�Âý g®DfîĦëêÑt‰” 4yþ§ *Ë9V3&€ç%¨ËõÏ4>²›¿¥|0ÜdG¹ËhD扜yk`^—ŸOzצɜ€óm:ßÅzɪ&ƒEXoí ûBtô(Vþôæ&Œö”aþº²âv<¿ªŠvksb$qZjÔ‚¯1X)qÀ8‹ÉÂ[ÎöÒ¿Þ0^o 0Lf[HG¹ fn%˜€²[À¦ÃMÄ3¤Ñˆz´þò‹!àC“²+8Ò0ì¨TT«f UCMT­%+¸qø÷AÒÈ Å+㙟đÍâéHДFô{¡oTžewLè)4š›²Ýòôï. ðô ­„ß’JÈþmæµ`tñ4ýlóýó²­V%N/ÓàáFD ÓTµˆ‡•ÚS9ÍpßÍ÷aþÀ+ë ‘ø6Ï Ô¨D)7:°µ ’v÷6‰¹•“Ú§q”ùãûi2Ŷ­QW¸í…£€å‰݃ÈÜT™”9oœFÊÀ ˜7|—ÅàY5H jLÖz‘ͪ±}8è:.€2© cj‘Ï–:•\3ÑñBƒ’,š_/r&ð”ñô5ªÂMO‰M ã j©„1¢Ï ¶ù~CUê.°YZdâýŠ ‹¦|Og7æ>HL¿ñ Þos&Ì{œV%æã Ím¤–”6 RJïˆäàc†3”éS ³g*üIDATÃþÕ!z·ï¨$þßvn•&hIÎÀ†ª2dÛDY04ŽÆˆ”@sõ‚¦^„ÆœNÖÝñõêÂSê wå) dÈA¯ðé é5ÒˆF ’¾Rž1zÃŽZÒcêÊN,t! ]É”0 º¾c‰ìH¬=¦•âµ5â×Û›8 ëõÅÓN¹cú<ù;ª.+’5«é=}TÛG4ÚJGY8+…Y)eÂYµh€†À_§Ï/¯±P¥Dʘvà7QÎvúÚ57h«´lIŒv‘n5¶Xƒð•¢?ÚÃÆUr߬´pý6˜[Uùšµ}Xª”ö©nI ™*ÿÆ)5±/s›w‘Jõbzí4ÉÌbeÄK e¡7 kÉJÀH©Äsþ?„Á T5XsŸz^Ý TÊ h¬ ¬ñŽ@UßÅZL¯=1œ,g“›ŒìÈ¢£’×OlDV@oô¹ä÷æZ2ä@#rƒ•úÌC ´éü×¢‘ m×}7UL¸nå˜Gn4¦mç|š>þMÄWj ÿÖÞï³\–°’–EOᯓİ)€*,ëÂÈ÷%ñ&¶†œ&bÊ|dÊÄxÇã(ØbÎ}¾—uTÍÊÿ領áq¹Q½^D†H¸Œâ»ñj™t/߯ÞЇî¹ZŒOV|´È4•øö”ÓZºÎ6i„*^Ìœ!,â>&í”H9+CAP ŒÔÂmbSù#)áºâék‘ïØÏã;´CCuµ€c#0a€rG¤pL&{†È¦Ã›"”Z€À¸ÑSÒÃdñŽ{xцLÛZTc&ÃcZ²Í•ÇðIPÎIV/À߯é~!Ô¨„×’¦‹À>/ ǘHO–8«J4xWcž `ÒUJXn’p¤¬ÝQ‰¦à³.@PfBIS6E¨ÆŸÿHÐkÉúkÛG»wÌ¥1rÇuÍ´ìzŽ0O†õº RX³µhDV=“*ý.¦êHÖ·`«šUUÎø”Rêbˆ¤!h%ã/¼ôR¾šdZ4ŽMLj®ÐþrÜæ˜69Àµ‰ÙFšÒJ èWMüÎUBb(-Öþ]“F¦É¶Íé‰=ZÓË  p} 8ˆîÕ¸ýí’¬v]FÈ ýs ´óÌÁžŽsÆëR}š™ìv›®—Œ Yª–év° iÀèðÜX í~‘ñ×ïãYÕ“¬šÂ$l4=CC€Áw”+!×EÓ È”r¶r¢×ãp³Ï™÷Ø‘&ܬvð€HÒ ¶âìHæ¨*rvµ7NÆ4kOML“a»921«®mî+õgï»yC ôbø`ÌÊ0 U²®³eº¾Èíõ§ŒäfæŽHUÇw4¥A ­ÑëÑÛÓÐÙhùaNƒ•€fµô󔕼Ïi¸‚‘-C·OJU±†)“Å!já`JL$YG-b²üÁ4¤Øêµ9ro•¦Ö/˜‘‘¼Fú4­‹ Çg˜CÏ­=A&m‚Éä«Ò{;™›.¼Ë D>4Ä&*!›u럯x#🌾v$ çÜ“àoÊé¿b@Iî lk”aú~BàLÈ„jCUµÇÔR;2ÆFÐÌDÕGƒÏŸ²Ò€#¯c ^LVd ØJ }¦JHú¾°–|º1CÖϬ+óJéA_—Ýú|‰3W⩱h ¸ÑíßCÅøéE {®`hs;&Àäm°°¿jK6.|\.?PUÛà %Pí( #dK %Ù‘'}Œv€ é2Çô\é‘g×gÛž‘•v|] â¬î;¦$ÒVm¤#RÀÈ@d;`˜`ÊdØÂi0k!€kl˜-ÆQcŸWæÝVr @¹í¦ºõÞ•²m ¼#YæíƒŒ—{¨Kœ´w‹i=¹‰9gE0Oþ­Š4¢Þ@£çæSÆðQeë.J}ôÓ4næí Åǧ’H/3L3 z~:+ÚP,jËe¾­’l›îYWÓç`ǰÜ5VT…Þ™;²Ý>+­caz²²U¡‰ßh ½ÑHš€–½Bb%d?*>¤v J4€|½éMÔâ)4Žz#14ªñHÇZ2¬ºMh`Y/ =l®£Ž0}»UJŸ!¥ßzJdóWï¬úÊfNpƒ±mÛ¼?'ðÄ홳¿ÁwqUKæŒZÃɲÂw¤èïY­Ñ}ùPbd½µg‹TÅt¤ç²Ñù4‹¸H?“œ‰SNL@Ÿ‰KÁ."0ÕnazL]Èö!ˆ‘5¶¬*òúÂèêî‰[Ó Dʺ¬¡+©}šÖkCdûð!†²ÝÚyJ`߆ïϵ¤^ È‚•¶‰[i òN;¯A¼k¶sƒê%Pí²í™æùüå2«&ÊJ4¦'FröEõdÕG¦ÔFXOx¢š¨%An ÚÊÿ¦ gÿ²dx]45Ƽ欴cò¦ ôceÃ4|)Û–Ò‘èRŽ1lÃr²1@[MIÐ L¯‘oÉÏŸœQ¨F ôpÑ$8ÐÒ°¸}g'€•1@Ÿn²º`Õ3õþ\õ…PÂ÷ Ρj/S»œ9 rk +0^;ÜbŽÈnמ§óîÙÄV¢zå®P¶?Ÿ0‚f_èF[OSèÍç”UyÊFèí¯*sh%€.%£a™Ík‰ÌÊbdº@,”(ùt”ÔN&òlt× W•›¢QûHš^UÕ·?{ZÀÄž¨YéiŒMˆw¤ì‚ñrƒd+‰ÉºT-S{ÎöÉÁ1ŒqÔˆ¯S¨êõcßþHGA¯ÝÑ |ÓëÊ\®$Çè¢o"C·p…VRò»ãX+@¤0dµ8c8‹i`Áî‚ûÖ™Þ†€®9 {s-pæ°àÐVo&BIK¿P{¾ÚÄŸf™FU©Çæœ!YãäZ*ù=„ËÝ%+½]P#ìSÏ\K;L–RV’ó©ª#ô ¤ìI³‰ÍÈF8Æ´^&³âC–òXß#=ýþFƒ1”Œö¶rwd†öÄ÷óÓÐl[›ÀQUÀŽÀòié•R(%#pì“EŠ[?ß -"¬d+èÅ0ÌJ6®¬¤‹¦–¾ ðÆ]×c+jW1ŸñL‘€*¾c³5›•ž¿Å”dÛ^ã“àÄ0e¶ÍJ£*Z¦Y™ðqÔÂÙ'2MæŽÝ·×ÐÒ•yfÐhoJKv$Ø Õ6L/«’%1Ž‘]ÐQd^¯MÚ§…´^ŒÝ([¬FV€ŸA ½£¯å&nDÛîhb¹»{œ^•¦êÄÍ’-Ã\î:²}:ÂMÑ ŒotãÚŸ31,€ÿ¸Ñº`2&]–çª^5ÌM®…ò׿[Ø*íî&mЖpýEWBŠºð@U°¨ à­bƒp«¨"»çù(ͰƒÞ¾©ŽÝ9A%ŽEƒZ{悔oCÓU“i2ÑÞ1¥tå +õc€®©1%Ýd²”JE2klO>z9†0å}¶2}U97½ñrå׳*‡J2Þ”``UãzêöI¬ÊgVz۪Ɣ]Ók8v]0 ÐíG¯GÉÐE#+ ÂQhICä(u_YIVÂÓwìçíz|>JU%#ú×Vµ†òWXÉv9Ÿ.Ï¡ß,[C©Šy•Åx¥Ž²ÌU’µÍr„YííFœƒ’mk'F6=™Ë¦ض¶£ ç–³êRŽ€lUž”Ý:M;´@ãTçC/T_·.‚ÔN)7‹ƒ’Ü’µËªç¡¨I îÇ “±H\¦üq4Û„¬´Ðn*¾ûhÁ´(б¥÷†^û¨Šº€V¢mÕ¶ `[Á$2‡âç 0á@YLæ—‚ë¿%ú>6|Á 0N)ç|L0[ƒ)Ô‰a¢EÆwÔ"ÇWÒ‚ÇÈ}/³’=£Š|èçŒGÊzûQTåÄls–ÉrS˜|z[˜C2¸M2—Å«×ÞJ” ¤O<7ƒ´0ÑÕИ5ªvq ‡üi`L¤¬] P’™‹þè¥T6aøˆUÉúL›k‚–QíˆáÍDd¹¡HªÜÞ—“ñ¡!׿ܥ5ä^À¿ÜÜiZµ¤`"ðr[xnòû&øöäáq™+ëøô/v©æC :Vò€¦Àz'C£ „c€R4]U8&èú·õˆ“øÌ‰;vS⪕0‚ƪýÚ‰±0‡üõÂø]DZvnHÿ­OǪZÚœÛLÚvš@æhtq‹wl  jGz²&RÚŽ!HŒ'+0„i±Z«v…Žiê’›EÙ±¡²8ÿ) …:»-uǬyíˆiÅJ¬UËLUnä4Jf·ÐÂ\Ђ|Ü‚‰PÅÏDUôÁ)‘iüÈ*ißD˜'%UG°êxíÏwÓ XI‹0Y‹¼õÔK–!Ð>?Ì”Lc½zËHÀǦ‘M”¹éþ€·Cd³Ê”­JŒáCÏö+•^`ò'†#[IµÞÈ2FINŸƒ£A?|,Ðt¼%i„AíÔ+-WÅp†oñƒÓ¬¥ÝÈhÂ2H£=@¨v÷–t´eº0°ÚYv”·™£ÌP®Ê$Gd¡ÑxfÃ:æ6ÃdiVòJHXf…W]à#›R&€ý1C`D)[8¦v82A&r‘U䟸G“_CÇ#taä–Áë­èj‘_M%zä±ó§»ÿ‡ååSÁ¶ ¬³;$uÌšÃ>Rt“1€¿)ȉzØÄ†:#û5«ï÷®‡¡”‹º2„—çVÉJ)UM”3‘{‡˜Jpûß«|~–Òç_V¥Ÿ­YMÑ[ãýƒE#ó0âôÄȶR¢—‘ýcÐt[Ï3Ò¨Ú¼.|³è9;ªŠwa˜x&}™hñ;ÜX úœ³¢¤á@v¤ t(àg ØÎm…Ϫìhœe.ÞOoUžªÃù ÛY ©W.”¤#b$gƒÖÞ·”€¬›ÖX®1?ÆÕúºvÙfµƒ}º{¯ÔãòÌ*O9’R0Ô»qU5QÙ2ëíÖ4þ‰ÇŸLø^OO,oC—m¯‘ƒ¡zå4²v%2XI{‹!…£OêßÿE¶[$}>ŽM¡ì»ájUy¶q‘xzŒè“j¥ÉªWb…—ß®”›B&’…k”O¼{YCI´Œ·Ïx%zǘ<1íÜ·",³ÍJæÓÑÚ­^9Ã=fÏ¥åÆQúJ°räc12%Œw$Èö·¿ÿþ[ åŒ ØC'ž…ŒR¿ 5ʰ’^¥Ž«r94d˜ôp_ǵ¤!dºd¼£8½c MÓij9w7- •]2h@ÎßbóŸæ8Þp4ÑõÁÍ‘XV—út}‡ðl‰•ú«bÇUá.µ¹€˜gXž’ Ü¿“Ïlw„Ó§¬³k¶-’€,·¾µdªñÉàÚ#³UâÖƒÀ«‘ÌP2®*3©å‡c»Ñø,tuGG‘OOIàV-:ªš‚é(‹Z êÊ–lô»’–ÉT5:Ëa†é1ÂQníf9RŠÚ‘<·Ûx M‚í/×(Ã-kqkkÇ!úÅÑï‘íY—Å(™ÊHŸ’ ¬½[˜ë(:7¨¼c]r`zS(mu–û1e&s£‰tpæJµ8âÛ\/R";Rú)‹$¨ŽÝ1Fî¦J ²ÚþŽÆ%†É“dr]eJAPnÛô­OY×H‰o.¦AíÜO.œg›'Τ}ÎÿÜ{†œtOi^#[(¾cãó%ö]a[•2O‚0¯Ý–[F 8¢ËÃõ¦)W¢ìº­ckÂçäØ&Ž™4"Ég§#s‚¢²#ÿ@>d‚‰Þ^?FµM:ÂDcU)>°:š‚Ôøÿý?ÐëëKß:ebG%Z% d"ÃÉd %k1ʪü™(Ù-+ ½­:æV¯LÓ8ŒHÙ¬ŽíC™¬®‘f) =@&s&H¦$hòY/ ÿŽ#uQfΙ€LµÛͳŲmÖÛe‡VЬ«=1ôµ°uÄ;‚!2[]…*À(üʆjr9Ó¶<¤–ÌÝÈ¡ßþp;¤Ôî˜XC‰ËÐn¦Ð·Á6ÉPis³% ‹ìÙ­´šU»RÏ’æ²h–,S %—´j%oŸ%]p+­êˆt¤ló˜v˰Þܘ$Ëá¬òý‡ŒRVH7…6_5ÀÿtÞ*†FhÇT²Õ4Èœ)ñœ•D-ÖkCOŠ9¦ßÚЕFÖ(sè­ZãþñÇùjø:1²hR¦4™¶™\—\¤çÄÐ,ô"«vU¥”ŽÓ'¨¤Z©{rÀÏÖEóú„]Øæ”s&Ž|”zGÀõsÐNÏŸ–Üîom®‘ \û£‡ûêŽlÓha‚?g2QÕÎ1æ;òQ@OÄß-¸µ”ÉT[ ÐbþI/s3® ëBõªj¤L<žF´p`ƒstuïípÎpÊLäFÁEú†+iÌ37†ªÚ9ÀØ›$ÓHÖ1ÿL åk«ZÌPÉwÀQÀmë g•·&Ê-Ó5c^½®í`ɺȚոH©$âí©wA&hÄULK¥H_æYW)ÉŒ j=Àw©’¤*¾¾€v3!€é d½øÚp¶õP¶UÌÛãCÑÕˆ—ÂDÊÈn¢YÉ­‹XL©+¥º¶È@¤\ï×õ|Ï1¬ˆ‘ º&¾®xšõמH˜@IÀm¥Q8f›N¦ 7¨eÕ>YÕÏ¿ ÜgÓm›A„Œáå(²ãRÿ6ÃÇÆ§oĬ´[]\§ÏCyV¹Q/·Úk9cnä®EnÝ™9†’ ÆÏ–•zz2 H¸8gâ˜d™Ëø°+Ùâ“á{´^#sUGªr¡Ô ¿ôù¿ñ1áîÓV¾ñ37…Xµ»hé²É”D8^—#cºˆ,ðL¸áOó}¹Fú¶¢D¿Âó¯nõ>ª»u-²HÖ³À‘‰Y¢Ý®÷ùìZÛÚ1‚ q$q¿ õÚœ¸­r#n@ÙP LIÎJÎhOÇía %ÛÁQ¤á©ÔßK^+#úŒ`z¹‰0GËÈE%-­d„HP#G(·y¤#ÒVÉìÐ¡Š—Åô)í;(9–1}¥Že<À0ÅÜÏ}îõm…t…°œ's²­V‘–É|¦”s&²ˆ±Ozšnу8ª:Â?ƵXÛS=³¿#€Z´GGô}1ŒÞ=•v¬Z ™£ªGÃôµ|U[p¬&€‹p¹|>á&µuTÆô%XA2ûÁæz…aJŽÝ¼.ÿJ·gêbJ‚mGzGyÇv(#ù0´¤l¦äC zøИ²”0•Äȳß÷¹óQL )€ÈkÁpŽº¬ÔP¡«–rñ•äÉàî“aL_JG³RÞ±LàØ¯<³D&”í)‹ÚíÙ‘&²ö¦¿%žiäB ìa ™õ0é#åx˨:Ö’ƒM¼UL³ ËB M¶2†2‡H̪™¨"åþ«üªµ4‹¡ªH¼UñÉ”`íÖëmY¹HûàíEXoÕ¬8¸#òšVÕÒ‚6Ô‚§Tê¹êr+Áñrn¾o3!Ó›F&0Bض)…vŸX×®Q’….YIÖr¨-àoÊ+NPN`–£ºl+U…«‚[C÷ fÕ.,Zä µí)MŽJœ@h¬ xÌùh‡Ó§¡ÏÓ±ûÆk÷èE ªnÛZ8Ã"+2šÙª:v#›ç·6=¦Ô…7Ú±+· ²éÈx[}þhv9f7ÅHÍëG’ ²Jæqº‰ª©ªF(QbÜÆ4Çèî)›5Ûd9÷+5Íéü~A‰EÇŒÿñjÖh%2ƒTëícŽË½…%ÍJcUwш‘»ûºrîXêbˆ\‹’#(`žp£_1̼…c„}êê¨ÄŸßÚ2RUnùðd™d@´`¦gõ® CÖ^Ž„¬&sŒ×œ§R#a|²rG¼FLÙ3ҋצDöàô1™7Zî.J”ÙÊ;ÂB¯ªA0½*fkDš’¥@ö=ßÇ]#^µM€Mg(TÙ ½aä1Opw§Ñâ˜àÈ\&¨ª®«*¾å³=M|³}{áŽ)Í1Ä¢H }€ÖI¦¤Ë¬ôðÖPMÙSPúû«.ñf!ϰ{‘²’hâ°Rþx¤åfÉJg%šMÌ Ó둽/“ÒVV"X¯–l145¶’RÎL´[CFbÊ~q•SfXWÇ5ö†L Búwõ€× ¹qz ]€®J¿ýóÏ?Q: Û[—Ÿ)RÆk6F&V@hŽª\ãKª&HSŽä$f¥$3,ƒ¯cDÖÕÜH{Ò¬—,%A⦤—Û§q&}ÿ¬&€e¶>€3z¶eüÛîÖ×àó§ý6¡ÉV»ÞF#mÕÎðÆQÒìM:’Åð¤ÍÍ™#[€@TÅ $Hù¶'CÞÖÓ›U+m%L]ø¢…Ý®‡BrÈ ô6¥^¹—T…·Üû`j(]?+@)s™ ™ Ó1™Ü›øÁûG%8“<™ó±F£u‰ÛqR`È`=¹¹UM¬šRfØ”‹Æ)µFÿ9±ªÓ˜É“øªjÛmH´Ëº0mH¬·•š%s®%0>°€|äÙöÑ¿&û黽ëÓ4E6¨Ymk%‘¾ö my-ïa‘“͊φ"aƒÄç/J(=©“fÑ/÷Ùi€5Oožß’5ª4”¢…šýbâ|"{)íÈ|0=J³`‘çzçÔ%G‡e¸XÅý*OUkP6n*¥ÀØIÐî÷©ÿr R•&†OGJ2Ç‘ɲG¦ÔÒWpëÝJFpS•s(Û¹ÞŽóO¹Ýð=BU7HIÌÙbœwÁ³¡Ø2Yaz™‰œFvÓ|`V•zÀ¨ŠWÝPi±v{™ot‹Ù³.%†ù¼aB)ó¬]ËûWiÕÙj§4qân=Òb2&•`Œ¨ÄM{kà“ú÷ñ0­m Χù¾<íªšç¡Ab®ü$Kò‘3´i`- `2Q© 3WBšNã¨oÃv¶@-F&F²íØM¡ßJöµï.ôdp™’¦M”`%‘Ì‘¬Æç)ëUð41Ž2OO#׈/‘žÔÑ”n a$PFò)½•v³úbPâûš½øn§Š—ÍÊŸ#¾ÑÈU‘ŽBïdùGÊü'èH ôò>e¨²‚Ï~m»•*\çªÈm»ûAfÝN2¾È!^'ðCÛõ˜ ÃdªJ穚™•ìÅûbÁªEU]‚­õ0dp ¾vÿj|xõŠªÄ)-€d‚‘åÄù«:/7S©+8µPZ>“dÝ…Þæ¢”„¹ªJrΪzFÕ±*1,ã |ܪÓˆâ-6’Ÿ’̉a›?|f_£ #a›7= Û¾o-ãXW†¹µ9}>4{a‚3æû¶À|t…¹Jö« Égßv¶ô݈­HÀP’#eߨ¾´ºxúz¬ˆ¦ÔËS/,º×®‰Èü ô–dZ:jtGbkÄ[@@ĵÈoÄc½ÜÂF„çHœî¨Ú3ÕÞ9G½Bß>JÞð®|þàQÍA;™–c}­dbÈæ>V)ÉÄiû~ÿéÃÇ÷û{cŸŽ-&×HÏ ®ØSKw©/üg^ˆ­A#j”)s„–ªZâ< (%pô21ž¥õEseÇd”¢êvèM™9üÛ_ýåÿTÃz„c#kvdMÜ`@cÕô}{0¢IEâéÅð˜#ý®„,"›5x9r³2}Šw,+1eb< °£ý·’O1^öK¯Ñ߃joJ½šg¶YͰÝUé…FnÌeoÕJÙâ¥b$M¿_´ljþÄlûP0×þóW$X e«®}$ç¾O)3Ï™& û.uÖ4ªH%]“©ZÆ“V"-VŽ'6‹Õñ½C³UŠ‘)Ã`†ŽdÝÚãÀe]~ko"±Ò¬ððªJ1Üy{’õ ÷Ï.LðU¹i/ZOiA\Wb9Üo®Ž†Z{ŸÝÈÚåÛ uá»  ª>MU¸Å]HšJnWµË¶ fA9q¶Í%À»KϾÅ<%6¥Aõ6¥^I3Y¯ÅG‚â,ñýʵdïd˜2[9P—h" ô &¦ñ-S;²ãuý|ñ¬¡ŠO#¿Ëä̪㨋[ãèW!àSN–áM©—-PUn "ùùrô¦m¬Ü$¢m†<êïßpwCdö\Ç~‘9¶\‚>æ¾”Jliò§IæXµ;Àµž^8^N_cJzk×%(ñÍU-0J)5²mMh04~ƒÈÍ’ ]HÇzäÄ0^Æç#3—{¢v á##•ˆaôh™´À4ñÕãE¿Sš®™)º JU%8jåþ7d”fbâ†RÂÇîI)])W­…gÌøF´X¿²k—’iá Æ°l> àKH `/æ <É‘9À5Šä/öÔýI?¾‰ªñŽz[ Þ+UJoDWkhËl ãðŽeG]¢å[ÏGØLÉ]š¨è¹ð4µ'«ßqS´„ -Mçƒék™UÊœ›Bœ  ªE+ÁyÊ¥€ j‘)aÇFXư‡%ص+qûÁë펲P%:ˆ€,˜äLO&o÷çGãh7¹vL&-c¶K|ƒÙ24hŒÌC‹iq4S_<¥PÙrˆ¬E¦Ä 8¯‹€yVr_æý.6Ñeû²©f؆2FFr3}žHáHл9›^£c€Òm˜Œ™&e¶=/Y£iò7ëóÿ)|WJ]ûÅhz÷,d( G íʼn7£…¶ÖF¤Ñ¨Äd—ÁŸµîç×G|â²Øt YL—o(Üq-xV”òH eV²cnÉ2Ñ‹tÓdȶšP)eMÕøCÏÇ'䃗-àÏÒ™÷'ê¶L«";– ­]N,GšiÃv›CÎéáëò…³XßZšd4û7±‹Ãxš}qºHÇz›Þ>øm¥Úô2^À]ÖØÙKꪑÀxÇe qWõù¡J ÔÎ|öÑç E„É|î?|µàíÃØ­ûÉÖ»MÈ^f T  ¤ 3­'ZæÖ@‹AZâóQÅä–^h—M° _>Y•[À3ŒÜ;86KUÀÛÇ ªó1¦ºÈJxúYõ)¤¤1Nž¡#%¦œ‰è‚õ6.Û‰“õ·é¼á f>Ë-pÈrh´£*à«.[ö2Òzá—ïop ™¬ä[¤6Ô1òÊÏ\?/UëR-ƈù+5Q X‹µ•YÕUv+uëu¥Ï\6”2PãK*‰~uhô5fBÿ.FÒèJ Ä4Hc½r%&0پإÈG³MÓñü¯öˆX@Tà²àÎQ©ßYÙa2¥OY UY)ÙPËdÌkïã¯4¾jL¸sV°ÀW’•ð"·†ÆÈ²‹¨Šdr†¹ER:Ò(ÙÎJî­1GôPŽëõz‚ƒPÕV­À̰AH`|£eL¿€¦h47Ûn‘aCeG;ÈÛе÷ìRÎÖ–¹ï®’o3½`%c ”pÎŽªÆÕ.ãEWPíØòÉd<+µ;¦1®j¹íó$hDG ¥¼%›[¦ÌA6¢ v/‚íÖP>YÕՔʫQu¿¿*uÕZd$@ 1d‘eG/©Ô†HÑSH&¶EÊ¢‰˜U#5"Óä£$#g«rJUë‚û å¬ÅßáZ› =R;åœÅ]On ešÈ9Ãvv}¥ØÕ`A#˜À­¡eÕÌ•´·@-Ž€!‹zqËiØZI h ¾‹à‘0±¨7˜²£f#àŽ2A-@ÇrÇô{à %97¸AñùoOŠr‡‰”r|¿ÿ÷2nîžÓ ½){ͬbªq…¿¾¾è[ÚA†ÛßûÖ• ’?RÐr °^¥ªÇez›sˆáF†Ác5¶Oþ9à”Ö¥Q4t8e×Y»£àè缕0½*[zVJ»EsÛ@$Ó»Ò«ÒÇçã(nßùîj OŸ³²>ôÖ#C -6¼6g«le¡ª”'FdJ¹e´tµæ+5]{‰IóA[h[ï³Òô¹´I®¬ê—”–õ+;U-£ [™["ãeþ‰WjIn‚ƒ|åg[%|˜†MËÈªŽ²¡ü1HYÐ>Ér“»,RP¶%8CYUæCãvp£QIÖHóUÛözŸÔ™ôîxXž Ì<}.ÒLäæãÐô¼Ž° Ííë”àÊÏD@‰¸[ÈÆ Lƒà܈U»Ža%±.úI#ˆa—¥ñ2ª½CCwúRô-“¥oJž™3t” ¦“íXlgÕi” M–@fÞžd}ͺ;}ʦÿÌ“”K àIEND®B`‚ic12›‰PNG  IHDR@@% æ‰ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð øIDAThÚ×v$G„a͈+ï½»Ñû¿n¥#ï½7ûUýMt²ŠÚ³y"ÒTus8Þ{ï½üóÏ?<òçï¿ÿæ4L9BÓ[Ö–5´@)ÆÃ‡gz/ç ŽŽP"qÂÙsÊ2ýõ×9PírVº#ÄiÂæNhœBê¤â°íã*²¯frΖƒB‡Õa\úž‹š‰¹cÛ±Œ“?ÊÌ5!å!O¡sTh;eBÃæ¬ùü¢,ßþd¦0à*8)˜Jas ¤!q%S„mNSlÊ”Ö4œß¦)-¶JùY`‡VJÌ!7Ð:ZÈ3b A"çä÷‹X=ÛX¥Ë#¤8vÒ!“ÅŸJ#'Z _Š1üq€)¯ü›z°’¨;„´x‰1ù¢C+klâgRˆÄ9Ô…ƒsyÓ Z‰TX¡G”Sh¢œA‡lºŽ”GSh˜93Å4ÖÜü!˜^ÅöJ]¢¦5†³Xñ!œsJwxp:ü™¦°Š ¹¼Œ‘&¡Àš°F§¡3m«¹&lü‘ZÁƒT!à.vÉ]ù‰„\ŸQés­éh5­×¶ª·"ã…’¢yÄsgUãoW( G}t­1™98Ã?„LEYéq†°Nó/´Ñä$’NÔ&jÊ¿éG1ìÂÙr€S,d´ÊJxÆ#P+šìÔš(''r¶éXÎyl[u(0erê¾æ FWœ3U':ˆJãàW~“¸õgkÒ2g¥­xþºÁ3Y»4­@¶C¹9¥¡UìP£\à½Cî½8p:YõóÇ¢þe  ‹ñ×±Ì-¯Ü5åÿô'ñ >é‚d­ÎÞù4Ý”/Â#7aHþÔè™k*jŒ.ÿ±Ç3ýùçŸÃ}+áüùçŸ@NR£0S!Ï@»0åRh:¹S‹SÊe÷2Êg œÿ죶J©ª¾üñ‡”ßÿ]èÉ'ŸÞÜܼøâ‹¿ýöÛG}Ôu!œlM¼þúë¿ú꫟yæ™çŸþÛo¿ýñÇçÝ :òaÔÒömtëîtÝ«QH+Ï>û,« ýýúë¯õª{-¾üòËÀo¾ùÆNã?ñį¾ú*Î?üÁyá…Ú­é[+U”+jyMíÂo¼Á—Yz›³JanŸÄ#c*Dñ•W^±º±IúÆhO?ý´zpÖn=÷Üsúâ‹/t1,L4~V"=õÔS/½ôÂ÷ßiwœ†3~ÿý÷ûJiLK‰¬PÑË·Ñ)Æã?þÎ;ï¸~ø¡ÖÕˆÆJvÖo¿ýöçŸ^÷­;ýn 2„NdŽQÉ„.ÕâhËv¸o¶ã—_~)}ÍÝ.&<Îö2_ÃùîFÝkÈMˆä(æLtoóÔ#ѺûðÉ'Ÿ ÓåÖÃøöÞeûôÓOÛl"Óf}ùå—kKðQH¥dE·ð&yû²‹mê2h÷³Ï>ãKs£z^ßzë-—ÄæAtã4^{í5ÝwP‰l‹ÉjÝÍ´~O*„‚©Wޝ"“ÈÚß*Ê¿œ€¹É”ä“Ó±“·j׆yF­ÍæÅ·$뱘Ÿ~úitSË"ç°.ƒêòÀ§Ós˜ìéÊ?(˜6Z'ÿrµ²Z/–´&Á’¦C6ÊÍN & ßþy=o±Éy|û<‚8CmxóÀñùžES¡ÙÒ­Ö[Å ô‚i……l6°Ë£[àÁo Í²)6‹‚éœ D²M·×(ˆÓ_+t!Ši×Þ¢©nl'BdY:ðRB“n68ßåùàƒÜ6®óA"d+¤ì9y÷Ýw=îÂ^á΃Šf\â&Ù¨c«djû-µÍ«K;ôõ×_¯ë×™×—&Ðl¡§Å5øøãñ—§ßj­Š¦,—ǦxøJ+áqêñàtKq¤8öbúÁ‡Üù2ע泦 ´yZ±1I@´ëºiLÞ|óÍ.Œ‡UbÝ+fU½yRÆìòÌÇ–Ûåâ¹·Ôí ±)¦ yü8ÔÆþëŒÚêÉsy  dˆËàÍ3ëÁÒåþ°lo0kS;¾£ÐM—'$f—ÇF¸in|>5Ûo ”0<!‚C9ÛZF‹V‰cSµÕ¾êÞ‹?-V—p—Ç%±¯uÏj}}ó`Ú{Ì>ILm¼õ¸ró9Û m“aÚÚê-{\€‹aˆ µmF{ȶ%Vµñv¦†4Šï”•™{´0¸WMåm¶öÕ:ẇ°5k¦fû]¿Db¹{µ«Á¼ó¯Óªj—]1D£WGïúNOp'Çk‡?ïŠp‰¤ìœÚÚåØë)jk)xŒZ‡§‰ãˆto…ÕªJ¶•l ê!î‡ÇrÛ'¢ŠÙ{ ©$­‘óØéO ÚuC:Ä»ETº,WÂÊ…èSóF²H¾ÛbË%ò}b­ÇÛÆðt¡õµªÞX£ê{—zàÝA¯¼µõdãÑtÃÓT%õìk­‹JAÖÙš+Å™”‘}côÐ$JG 9…’mºúú¹. 0­•—u ‡3~}æî›¶Ú¡¢­dú(«)gýñÏ¡ëk´XìzÊWX¨(¡!üQ!ü˜¥Ìz€áÉÆŒÃ6"äï•·õ§‡ oÿqy c£’„iHÓøùÉ ¡bìS:^ÖJNaÕæ9«D„Ëæ|§ðXÎGr%#L±pd‹–"}u„ŒÎ*F^Sp®’1'cð½ü¦;•*3L‰S~—¹H…Ù”?`jM Å ©×)1!ŽÄëo@°ÛàÒ’‰Q¤,vBœü•“ÏœÒUƒ“T-Úå/WñòC¤ s”94Qa¡òWòÊç+¶r̦lúÙ™N4¤¢ÃÎú·gà>€+AȘå5=X|c*åàœO{ñÇç4­JþØqÐŽß… '!lăO(p®YS´˜ëRVv½CÛt—Õî2›²h²45Âóï| v3ÍÙªÝ>ƒ¬œ¢•9ãEáœÊÅ|MÎ-&¿DÈ(_?È GælÙ·';ºáå]™˜ò%ÂwY=“¹)[zYC¨Öè7Ź.¥„ ˜Nò®xçÎ9\wÝOVN…²–بîÙÆ¬C…ޝÑÛôígT–/íø&Ä1ª‘a‰V/‘üŸÖÎøç)dó·ˆ—n¬•øF„õ$‘•Å1†¹:ü‘™±çm‰8ì: ÉßtDn¦!Û0™¤ %:ZE×zI¯º¥°Ý±!ä¤?ÙÑD‰y¯BœíþHÆË–0¦ÆÁîÁ !DLùc#md×iþ «,ptøÛ[¨±ù)®8$0“?‰+^t8«˜ïªFº‡èÈ^ÿ¯ÄZ2¿zçÌðápp¦³uaqºE8FHdÓÃ2FsD8Æàgçò éaLÚ®p5[#wŸ¶LaM/΢ÀY_YçĽÎõNîʼó×Y ¶FsÎM¯„IÉ©¿I¬i6§Î\­è$¦’NÈŠ‹Þù#ß½oŒ Laù«] 1!‰ ùŒCŒ¡å¬ýˆNú¢]þÌ ŠQæêè ¦ÂÆ™ñˆp†s._ÑÈl#ËX_ÓÁW©ÿ&¢¡E…«ßIEND®B`‚ic079ê‰PNG  IHDR€€L\öœ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ/GIDATxuÝךdÉ­¤Ñ>ds8ÔZ‹|ÿ"¯©µVCÕgíýGZzEöà7 pß""³ªÉÿùáøÁ|ô£åÿûßÿ¾÷Þ{ÿs›’…ˆá!øxU<‹?³ôÿóŸÿŒsþ#ùHä³ ˜Úh‚hÙf+†×÷Ä+¤Y?§ã7˜€HœÀ¤Vk)¦†_ªŽ›Yv⥪ýÐXUøû‘Ö»q’êàà v¥’Kê‰Iʸã?íªFk‡ˆn²bÞrâ•$ëDƒï4›'œ¥pâ&^XáÔ´[G`xœ§ò Æ—=¥ŠyY®[Id}*F²Ÿó¢©ºú¿û@´ŒÀÓ¤œxAqÊ£UÅËæ#ˆ³ñÕRÀã äW^Ó˜bÁ‹äã™8ùªÇ‡Wõïÿ;Îɔм >0šRk´Z»R¨K‹'TlÙ5L1-•+Kuý.É—K ŒÃ«:MŠAºB‚|"y)Ûî‘S« „…L00©Å à)P!§¸T1°ûï)5΂dã·q©Év>µXIËë ¯uBùhB馵ԪF+•‚ìu!²Jv|çXJ¶‡[à:zñ‚ÚUx"ÃWR3ä” <ËÛcHÛ Yíô7ÏŽQªxoŽWÕ<œ½Otr¶­¸e#Š!džªŒÆ»I5ƒ4ßpK%锕J(Η Ч‡È®G)ä”-+Iê-Mv%8M½æ#¬5¼T8’×"æûï¿/°÷;n4H“¤2µ‚R®a(0´ðÜv`yZÅz×WU-²`j8Røá)´Ldí,Ú˜‰W•rËùF«Ð²Ô[B)8¦vcÜZ)´†I¡¸;i)`µ†¹e6<Çõ”{ÚçÉ&:N¦X§àîøpðÚ”²Tγºó›F\‹'ÂÕûåó<þY•`œS¶B!βÈŲ'á‰v×]·Îø‚át¶Ánß-S»›<^O­©]O@ìÚ4P`ˆ›×ƒF.!)ÖRhI$¾@UMвAJÜ2Ìð©à¨ÃWˆÉЀyœ•„´ŒQ2˜ˆ˜• ‰°åM|\ÌmgS!ÀW[ +ˆÓÑȾîßzB5®òcû˜2Fšmš²´J%RKËiÃY´IõDwÙ¤âAØRÜ´•ó•#ÖEœU(Ži¿PÖ.<ñ˜O[²G;¥Ú5$Ÿ2?Ú™~ÄÝ]ú$‰ÿõ¯­¦9¦[›Nÿ’¸­rê²Oçx*oÄSmú.rüE³<«B*Ç2«–—šíÚ,[G„—ºëȶ,àãÇiSC.ö]ή >$»Y¯]ô]¶òLJÏÛ9|Ê#•…$Ç×,¹ÑàºJuŽÓÀ·LÄråUAl2ò8 Ȧy‚À”!âhgŒZ¬6q>©‚'o¹cz*¬E­kqvWì:É6§åY^Vùu¦ì©€Åðy|)Áªè°ÚL½å^–¿+ÝÅSk]Uä.L±¤òq/PÌHñV•òÔ´e¾sy©¼œÉ'µÀáwÑ£ Áã4[Má×mÅ ^J=$‰¼TH§#®Ç8p–tÙ–+Oaà‚È;å“?ÁdSàó$Ã-S‹’< ä™p"—Ü˹ÜÀåÐðß*Ü2—“êÑe¼aòR“ðøê"ÍÊa;‹Å–â–ã“(à•œ{¾än«rã·¨b‚˜âj1Ï«ùR¹Æ\Uj‰??p…!¥xRµj ŠKå#×zãU®D6sa,£U¸ì+ õ¬¬¤Sn·ûÁÎ6ÄK£ÇŸáޝœpä@ʧ5L©øvRÊr{(æYY‚ì)N'|©ª‡¤¦K†w)ð²RâC2Hf‰³½¬<þ믣±;,â©Øs¸Êjd³òqø‚ÀhqÒϧ_j´Ô€:.»`Ù!OÌÔd'8fÈNÎÚ—ª)§pz)UÍ£$r„§.ç2Aþlñx Nùàuÿ–û’ª§/BÂZ"/Þ@=zÛßÎñwú¥ ë5(ÎH± ç¥_X×R\áÚ…,%`§x›…òª($¯…=®Å”+™lË©EkyýFIôÖÂ7Šer˜OºR²^]KLA©ôe£M.Ö%P 2K'… ã/ب˜5Ê[>ZÔ32°ò‰D³ÌšG<æ‚· «(*ÄYôíh´rã7Ó¶ñ4büõjj1õh—/…Ãàé(´\\À'(¨j¸Â!u‘Ô«¸ªhy„ù‚­C d]Î BN´D€x½XŠ*(¡=ÏÇ¡,N*p‚¼ò“‰ðØüÝ tëÚ@µIk[j sÞ\k bµˆœHœüÔĹKß9k|¶ÍLj’Ɔà‹o`4Û\áyIî&¯?ømyq©“ ^÷eÏ ø}º§ 4ƒˆCˆÙáwþñP!N”`åã©•]`™xˆåŽÂ’:k‡Š£åçlÙ%ˆæªŒØ;–fÆd!‘w•´—‘[V…Ðr%-+ä7šY¹¼É *áÅi)¿äÞ¼Ц¼3Ýf(¤¿Ö¹¤f‰Æ¦åE}±›òL{I¾*4gx%@JÌzVpFîø õÅ)%Ið\&>¾ÔÙ´˜¿žÖHoýHGo,ˆx‡…³ó•²dÑbZFv¾vr?‹Åq"ŸÈE}y°pfW›—Fë+nËáb%¾ìB;å[éqX!e)<)§&[k^¼’u|jŠ3“z¼.“õ"u©³MÌr•w‚Å|z»ë#Ì«ZÉÄñ§‚áO|„qJíÅrêˆB¶±\ŠŽk-2B%W³°³ ¿+§0&œŽ`1ÍnY:׋>‹åÎø¹\ŒÌ.‰ûÓI°Þ òey¶Qš‚“_j]âG8ÁÙfxRXõJy:8š+ç.°›ûpM’/›OD¼]+Ø9à‹·Üm1ÁS|}€Îá(F5Å'í© Ò”S8/uâ̯E[â«…g–³²[  òqZŽ9Ž ¸TüJvj€‚RÓ´£ReÅl‚‘!×u¸ï?Hj7ñuZY©ÇoCÓZ?tyeõHî)®°®ã+'b);P ¶Þ¥,£%uÆN$þªa'¾rA}ßâ‰ÃWHœµ,^UÁ²–úîi«Ê¤¢YVUöT¸ÞSK‹1ø*w *ÌGÃŒHgˆ Ó¯Ö².;‚!Õ¶\ˆ¯Kü~‚–‘ãó3…˜lÈ:LªŽÌ,ˆO¾¿lüüJ¤Æ/NAüV rí™~# ,™WØSÙ“ú–kOê-÷êqYòkg©Ä’HrÓn¸ HIR–@ËlÙGåý2Båë% ´Í) ã0Yœ-«âGWÈàù3ˆÌOáæ^îêÇôhŽ•¡-ÙY¯}"eŸJ,eyŸ¿;?îåj!§BžÀªJµä;—–·ðë_(ërV®ªÂMR dŸ™©¡)ᥲbÚÛ 'Ÿ~µ|`ÁNÆ2Z[㿌;%0R6ÄS–\¯¼ä–°jyñ†[¼ýl&©öSß)Xãæ§ùZÆlZ4gT,eyò׫”B{ *É'˜_y¯„áV A̧ŽoîÅA¨Š¿m±„e5ù§¥â¸TÁæ´Ox`âb»Êž-ÆI'° Bšâ–gv…¥º?FÜEmw§ÇLÓŽÑò‡3‘Ë]€à‰oàSaüSGÜ’| ­Ùt§XïM?<ÚY>u©'5÷&ÐÏ>²xUž; )³vü´¡%ß½Ò2©îbHKÿ°£ß5ÚU‰ó´ ÌëXSË‚zM8¦€ ×ëº-´©xŒ–eçe#\b/V.èøŠ_ò¯§S¸„îg¢—<¤€Ï€Ñ pý™²`%CÈVXSÌøyà©Ü)sŠªªOðÞq'Ó9LMðTÉ^ÿN¸›uñ,C,7ÇÙ¼,¤ ™?ÉO¡’óQ™TåÚ®F½jÄ•´ñÙWÌ€ 3ÅæTÕé[Æ\`%í艖Nø²ÉJU'¯Šì+³HNÀ*ÀˆØ'xöÆÌ€ø‘CZæ!Npd+ñ6W/Ÿ7 kYj´'&¤ìø–lKRUH%t ¥â¯Jmñ81§#[Ü|„NX–] ?Ƴf-óÒýv:iá'R-ü´ÀÓoc'¸^jáS€³-+ á“ ?Õ¶„cÆ I?‘ªÄ¥l„­JÊ’_P6¶HM°ƒžŽ@I|»hý‘?©Å'B-uøY²¸€²t6Óµ•ÛÐü9µâ-U ³%¤xþTHgÊ2ËÊówþñ¸C×eH´΃îÊÁ1qZ&R¯ÚMG@<'ðúà• Qb>6B1ZBU©µ­’t0[Ž&`²|:â3þ\ê Ä)²š.N‡?Z6\Ш;Í3%î³j"¶ù‹eü®P#¥\ÏÂ+N4¿~+Ç׃ß2–Mp^öÅÕZ®c]RXÇÄß.£%²lP°Â Ö«A€ rÒ* ¿ó—ëÇ…¥Îu áWR#Ë‚•@*‰9M§ôø9 j<±z¹@>E~CS ©ðD9ñ.Xüù•Ÿµ˜6ÿ4@Ãt(R)ó,‘ .ÎwôÉF_IK»fŵ ¼1Ö¥QG¶ á•ãOdú‘£]=îË_‹Ç¯"0JÈYnÊR[P¯¶–[&’oˆù)oš‚ÀºÃ?þñúÓŸö_¨ýêW¿úûßÿžÎÕò>\ÃkÇü·%¥¼.ø¬¸g’>œ)‘JÐañ¸8Ù*Æ'a•Ä´Œ d1ùé\zU¿Øâü _.‰–úYªç‹G¨*°¸¯Ëÿ¹­Sspë³/õ²XR~F…3GïŒ"ã(tU˜ËƒÙæá¿ýíoÿûß[Œá«­¯@Õ9‰¸%åO}êSt®N|ð—¿ü%\ù¶æøä'?yW¼÷·¿ýíŸÿü'¦!5Z;©ÅË X%¦%žþë+è©2ê¼ìâ‚áS‡t^ævFÿ÷¶>Á4v¬ü?þñÞºûÚ âg?ûYå¿ûÝï:ôut|5úüç?ÿ¹Ï}ÎüéOâµøÚ×¾¦ ÂW¿úU§ãIÀ¼7û¸÷‰Ø*^J») ßüæ7&[Óñ)»Þp]¡ðdÅ‚¼”ùN6"€”JÜ´h>þ±æLQÀ€¬¹“ÈeWUð‰O|Âý²Ûʉüõ¯uâ:ÎŽãV½~©äË_þ²stÿñ¬WÙ6ƒCð+_ùмŽhÖÚ‰üüç?ÿîw¿‹V÷|YÞ2¤9·Œ¤Ùé“úå/9B|ÞõîôÅhjYLƒÁ-w‹À Y¶“b˜ ®\ ¯öñ-(•¯‡ k“1ãä! ŸY?ó™Ïtr§8M‡^L…†0%ƒ;‚/}éK6ö“Ÿü_Š ëè="÷à¾ðO“2Bdzò‹_üâ‹_ü¢  “l³!Ü}® 3µÆ1­gÿõ¯m¶8µà–ñ’ò~ûóŸÿ|Ë\:Ç— SŽ#Ž#eѤ õ²|<ÒPƒ¯€/.;pLˆW‡ýÛŒ~ŽÀqTKKÍ~‡žšöRÞ¼ßøÆ7<.®–¹’Èh,Î׿þu‚‡ƒ&œZ“ˆ!Þ½6^Ry4`#Eïp)›9œ'Û¹ð=öå~’RÍlhÅɆY½cY|.1_w>!@´¹Ë7 ~ÎÔ«Ã{YÊËÝjF·Ü §°Yw=œ©—¯kàõÓŸþt]b*§ãÙw…Ä?þñ½ß«Mg‚–‘5§Sw¶ä-ɦàôu{øÜ4é”ʟχ÷^ûÚxÄÑjqSmÅMe)h$…¥^?„WY‚‡Ä«’2*p7¾Óááî °¸_bê„Ù;¤Û½¬Ózoüìg?ï$ñìG£ýèGh”©ÅÜô-É2Y…‚TMCªÝ!zìÜ7•;Üj[òh>œÝþj-ÿð‡?x´ך¯c ò–e«j%µ³¥Ùìq×ì%ªæ©>ѲRÎýÛßþ6±‡ØA[¶a"Døî;Y±Íwú÷>ÚJT1Wè[ßú¾÷~8ß6S>Ò ‚ºŸHàŸ‡ë©Ýé$ÈûXêùðòqoE€/¨ )V Þ±òúÊb²€ÅR8ÅüãÆéM'‘I¢Ry¯?î§Ã[:}/G•H±8<…Xf>¢;}y­ûÔ…ßuB±FËãÞ'b†N3µ|ÛSÞÕlìÑBjÁg·×#Ûá¢eÜ">óÅt¼Wé ÎÎTŒPUG2?…ªÄm!Úâ×[©ÄÝèªÌH'ô\*ÞûÝžM§¯ð‰ƒ Ûj²£t²]9óö¯62ñ½÷½—{ðSxò•wš0Až5F>D•Ï_"»{<…â|›Åô±_y/ŸâJv±“%žßFjüÿ@¸ŽWPrö_e~{«M {§¯nFùÍo~|ê]?¸]ñ.Uåøün=ŸöF¿»{ n=Ÿ+pʲ¥Î.CÈžo¹M ˜Mñefh¹o>ÄÙ¤ö|xù¹Ru矪pdy¸’ó:­PVœ Zø5™…bÖdñx* Å®À FóêìÆY6õLdYµp<øn½p´ñ]ªÞN”½Îk£ŠMSlÚ–wæá l+ÙU´¼®1Ü AA{‰CS¶çƒŽ!û|ŠÓQ¤©‚Ø«»,$»&¸g(ØœËBÄjÎãý^$€[ª—¥ÈUÿòs„Ê- gcÍíµÓ—nÙÞª ¡|¹÷Ñ:šÆP‹Ï¨¡Õ¢Âb:hVPÏÝ:^ž‰˜ÁÝÓ¹#š!I‰{ù$›r£¢E@˜å.O „¥Ìg• yç(–Xƒä›OL%~%⥠ýH̓ßný<é;•à;}og£q Fœ1ÙÚ)ÌBx4È–â˜|3ø­Q3øÁÍÝ#vƒãg8žÑž/c¤&+ N§rÁLUqßb®Y_ÆPXÌ×"føÀÇX.*I½XDìtâ4VY©)ËzÞ½gÝýŠ¢Ú}h£uƒÃ=õ½º<í3e²Ì$ "o˜–¼eȲÀ ¢Ö0~›$6¿÷›€i„skÿ×åßóáå“Ú¼ÀŽx¦Dm1…óÂùµMGfqß‚m“SI(¿ýûV^lâ§ç®¥¬žewº/‘Þ*mŒÎÞªõæ‘éôvò•ôüTC §“›Þ’—µ¤yZH;l áépÏ.%5Ú‡³_7õ|(,Å×eûeOc4áÉWմމ\¿BH×:Hq¢ë—q9Gq÷TÌ !ð=ÒÃîè=éÎÆz<-÷#O‚Ⱦóé+&kD-Ä|ÁZã@” 4ÌtFT¿¥ ¬JìÍn:ñÇñòéùpôŒ"tjQ eVŠ`åR¼”K’8?þbä Òõ¸>ÄÛU$ž!)æ‹oìr)Ú†»úÎw¾c\wz nv÷š*;¸ûÎÚsm¾dÓty|Tˆ½¬Üwí¡} ÞÔ}`6Rå:ªŠ·çñ q£¹Ÿi,ýË׊½|¼úS®WCž>ÜT-‰pÒ”šþÝêõ~ª ³ þõ«Ö¢Nâ@¢Á*+æ±ór×8qop%FqLαÇï|Ì¡ôõ.ÍGï÷ßïòÈöò £JߎC¸rŸ–Zã¸~ÌG¡ò}Ùfrìò¯Î>œ½|¼`·YœÍ³Kå7T.˜©Ðôuó9 ó#WXUúy"l± MµÁÇ_IF â+èÚÒ vÍ!ŒŠãf²ë§r·•gBÖ%ñË"|¸Â©ùm’˜9;o¶\åð‚šóÎÝÏJö웲ÖßûÞ÷ÜæôÝ¿È8¬‘œ>„”Ãíw[œ/ŸÆ»fº ™Q¶M>RÝdj½<^~aÕî¯Þ/Ý/JןOK½ðŸÿ[BWÏ——OËTÈÃÝàÅÈ“7Š;´/6j}ëèw>øÝJøîý~*öfp¯–/ïµkh‚.ª÷µ÷ÞE×/®‹® óíËg]ÜÂçË‡Ž¬ò™9ÑlÄS"v¹åËÚ‹+á»!4êwJ¥éLšp± ¤^įßñ‚b¨_± ó]?ÁhbÅ'Rad±[/Ä-Ó§q| weß|ðmC*¼òdã‹K9_?+¸[‚ f6)ûwŽb]xFŸ=½Ùá•H­×ù|xùÀÙ­ñp–8îtw‰ÛÜß¿›\—ÕeÞ påI¡Ažd›!üñÕbe‚˜ºâêÓÊ·™$dÏK¥ÊÑÝí:÷¥¨0‹Ð kcî©S­Iîž×Y(ÁwÄ>ð~/V–'âÞx¿»§¼o_ÞT>!’m|Áùáìy®¬Éy—Üé{=ú¡^wÀ˜¼‹ÁTi$ªË|äRg6ûÂ|üP`thÇ$˜aTI'š,üä¤Å#8z¯Ë†°1G\|W_íŒë î,5 BÖ0÷²ß~»ž•î}äô]²îM©¦ªÖK£—WŸ;`âÍOÙníÚùµk/„"ó¾{OJyæzéãÇ0ìxØq: ºÉCJ‰ Cäú ø Ïdû I^žLK-ËCíî»ϵæô#Ðì[90AäZ„ˆµð:×À]ÜÃ$eÙ»ë]ÂŽ/^¶÷f?[´Õ”#oH¯sJ™¼©Ú¯ËãSк]ðhÀŸsKc¸TR½ÇôÕÑ%qØàÓËM–),¸.@kÁ¬\˵\ Øfαï ÝzR}§nóeÛd_=- ×uM­¦b©«Á½[ÑÍ•šØ‹È=åP¼¼è¬)éåã±ègZʵÆÄ?Ÿ¸ÂÀtô=Ä&ô̹0)4Ò:ÚlUDì×ËÊÞ1J<4®îŽHm©|Kþñ5TÍl9ˆ˜ Œ¥²8æ¹R¬”®=×n³®ßM|Ï]ã-vãTˆ–~x%¼³vX@íÐÛž£÷f«°ƒ>kñ;¯¾Þì²F­…À{£çîåÃKÕ7&;Y:A%‚Ú¡µkˆ[¡Ï97x?uÚ²!‚Cwcõ™±¥À„ó–Ê׃?ý†›@<³œ¢Ó·=)'ëÆ±“³n«ŽØ1ˆòÝÈɶI±“Jß{Æ&Ý V…³±-m~_+÷f/;Ðeóz¤IŠ&Z‹· MM¾‘ð!hî÷fëûO øRL‹˜ÈOÀbâ¤|íhm,Ë&·”%œÊäœlw«;Ôæk §r' q4·‰XjÙé öUʹ»—VC¯ïZiß|ºœ—OOÙ»¥ “êåGàþ~|qïí¤QY”G³7­«è  °Ev\r·`È”óOøu=Ë•¨ÇʧôTÐ2Ó0žÍCA“UÅã¦ì:UAûÐv@¯×}O¥ànmµ¶$N¤í!˜ÐÉöFVîPLDzÀµñnQñ†ì‡×bŸL.ùFuÕ¥ˆC&%f^b&”õCÉ6O‡gJ ²-ùÅ8ì(¨51(Pì‹ö÷¿ÿ}ÿúuwnü&ã8ýrï») 5(›¤ó2å6ÉBx1Z§ßãDcqdÛ’k Æ·ô¬¸WR¬Å *wï“õd$è­-H!w†Ó÷âJ‘µ‘q-™ éдYwFW”Èq†¬pö_F¾•/[ 'ÖÌö°Íç匹·šq})ôZ/Uƒëä^^p‚| õ†¤YÖRáý pdø¬Ù6 ²Ïž¾Ìt‹ôÉ8Ѽ÷Íïp{DÜþŽ ©ZhêU!|ã!¸Ì]éÈÔ0ýPâÞ÷ ï*+§8‘-˜yx8Po€×IXÁüU÷r^Z®¥f4ö³¢›ËGæþ:ÛPï2Ô†g݃‚KúÏ·¯×Ûi¢ÁFâªx­-1lø®VŸÿ†t.q((ï­â¥ätš¦-E‡¹{\„î ž•¦¢3)LWÚé#xótÀ†¼„^>ÌÕ²!bœ!&Yáõs@mò*‘:;DÞÔöß¿PƒßÜëøLÓW~ÓxäUífIaL –‡KPìÓÏu­©¸ouNYw4·ª#;#?… œ¦Kκg÷y#±¤i<†£Ðl^÷–Í`Êb|çî’ã»{ 8²¾Õ¸–Æó‘°ïQ–˜†ñbdh­DÀÒ‡‡D0ðÑbZ6ÏUëÿйth|*æðÊsd] GàI4“½¹›ìÙÒNê—B~sàØ‰Ï å}… æ¦³dÑø¤0]éÈ.©.›¾îAKLVG»à6w©ì ¯Û*ï£Â^œ §Ó¦t쉙Ž*)0^RÈtºÀõŠÏ£5@¸eBãñ,²i‰°àªíÿQ{ºr1N!ņ°yNÜlÒ;YƒZN '¢Ö è0—¶¥×ˆ›]Œœmt:úb†Ô·[˜ÚºÔÂÒ]oH—‡§&w:.65l³8R)Äç]›n2LƒaÚ<‹¯¤©€µ¬ÝƒzÿAÄŸÈ‚ª,•°‹ÿƒü vr´Üáß%¯³Z*¬e)œhÀ.8²Añ-Xy ›¯aa ßòœ6š“ê{ qÿ,Šì kT!/UGñ){âìÌŠ«-à”t#°³°¿@• ù®a (;g­f•¨%>ë†-ŽSí©°QÎÁR¡ªì,µ*%f. 9qnª¦ES‹ç‹ 4J?„<í±ñæ‰ ¯Ê âöUAICF¶°8‚ë8,J¤Âo);ƒ‹ù,³G8&õÅ•\ý^^Ü¥ ¬x{HäÑàþ#ÚËt*Q‘u:ãjºÝÅCXÌtRhŒ) Lêiàº×(ýÅk— Ž Zv-$ò¸%×ÛRŠ·§ Þ¥xK;/¨=¤¿OÃɶ¬D¼T8~ÁI[ð„gðRt"›ŽY||Ø%.H­Â&,>::øNüdÆo›wÃû¿’ÄÀžÖÓM†°QÄÉEH„ßAŒ/`½%"4kL©ÕóKiaÉÆ9Ù;7áÄSÛæëŽ¶€~ûZ#%ùã(0)&¨‘8ÚÈeéFˆüÎ_Èr@îÙKûÞm5@Añê77¤cMQaA^J_-¤‰ë/€³hÖòm0²¯(-ÏS¸«¯rc‡ó;}UÛŽ Žë‹YႺl`q¸¥ ƒ·ŒÐ’ìp´âwzC7V-ó@©¶’n1¼=¤ØÝ*g¸ Éòáâx ,YAH‚'­XùRÓ‰À)Fˆ³Zä\œˆåÊ+?f¾-HuóUsã%øä‰#·G©× ®Û?FZCBXÒ8çn²æÐ)C†¸[ñÏò‰„ã0  ‰ŒPIM Ø<Â,f 8–R|d¾%/f nओÅiAöØÏËsÓSU;„ÔbNÓòí$e¯›îdoyjõcˆ‚²kf™ oçqIJ Ç’¡ÙXG<üì•$ò]tU JM|"ºW(@Þ•N!‚xÁšÅ-‹ùÄùªR–bc®ït•X†#Çøú» Io¦ ô“úh‚nµ|§OP̘VqCH%ÈŸëT»¥*—(X q“6Òz¡…,+`µ«Á„Z ³R‚ö‚Œ ›ÎörË<²lL>² ¼TÔÇ+hû‰]¯–ÊžpËÎWhœâ úT. aµÛ‚§ØžOÁæ©W1‘Ua2Ëí"µž‚Ètàwéµ;AÊ<ñv‡Ð$xú˜‚ø‹‡ Õnä'åéŠ_ÞÚh_ŽW\=Ð(eâ;ù˜^¿¯ªÂ¤R.ÅŸ-Ò‰–WØ~Jµ“ÕŽ™æ©¼=ãÀ³³°±O…'Ž=š ­ÍžµiV«êܹӉ#L¿B1ZL1þÔ쯡ֱ{oÂã9°±@º8kfhq» ¬™Xùho·ÿ[ðT®µ.۬Ⲟå~’"A!‹°v8 ^ßp X°8š³†Çgå‘×%%UñU…thK) † §®Wˆ—cåÄ-á'ç&^®Þ ,ÑÊ*,[¼´^,Ûˆéð!R!–ñUn )ÎËî+V©Óã¤p‚ P¹F½µíÎ*)ûä›*Îhk¾¦‘ã"\¯ ¼_§£^ã|Ø@á)¬pÌ®G |Ë‘ ø“¦v´-Ç Y#A½qN©‘ÇyÚKUQËp¢U®vÝÅÙJâÌË"W^@pÙªà 3üõÞo]ŒØ)Þ%—#Wå|Aµ•_[y¹R[¹»lL¸‰éˆ‡ÀSk‰ƒÌ”ê¡Fág-¼TµNB'‘²˜[b6Û™*N–ïÑ©*PÜ X)n¿ÞÙóDñª¯²²‹}ó-·mq`¶T˜¥æSq© F@äSKdSZÆÌ?ÕVø$5NÇil×bM•ï–­]A32æ^kÊg ^I3Xê{©¼ÜûÈR×C Å€Tfy¾þõPË‘ã#Ç/§e^‰ TAÈf°L-œ_ JIÈÄ!¥FXUAµ)×+üœ!Íßâ!§¯oÇ gÓ,ز쓯ÑuMðøÒ VÜ gY{¨°*ÙçÞ"T.fÈùñ«‚£ ¤%A6Z Á¬‡ì‰sf‹k­öåe¿R y·pwqÙÍS¯†Ig9 “ÀK© ßQ¤“ýI)F ª!!ÈT™MIÙpÞr KYFà™%Kª†-q¢5Fñô#Ķ,زœ!§r%ó8m"®ª«"nÎ ¶L 9SOPœ‚”˜Áù -ßùih*µ™VŠ–ê«$=õ„,c_ïJZž1DÕ&KÈêiÜR<+[Z ð–¥, ücÿDÖZŠY" \Õö'Y|–¬¶ìÆ@Ë6¼%N›*æ“z½J±×>ÑÆÊ×@Ürí-ÅŒBê-yËìŒoGILœ4ºD¨Ðñ…œ:~àªäTžÎ™2‹vââ–)çcn*àYh‰³ò)ThyN;N‚–• ’%u=¬ÊT,Wp'¯l8‰ñC0!IÅßLxY4xá§ïy¯|šé”Uè½O'åÔRX )F(».[€ƒ@ÙrÌR!쉿i«âYL¾8š Ô…H„¦5õÅ[j#î°âÏSd–4'È'UP6‘¯¯Žu̧ŽJ²Î 'žG«¶À0kª¤÷äD¢wIo|µeù†$Ë ÄMrg·ˆ8¾î1ùŽýñ:ôVþp7•Škƒ:œ"Kª¬¸l>Ý8ÑV/NØ A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð;IDATH u”ÙR*1Eñâˆ8þÿgé/¨UŽà¬w5«ÙÒ‡Ôöp’4 onnþþþƒûp8$pY$NQ@¹¯°¸²ØG•©;mVüŒû{†W éïïï(üjœH—õÄ}VYAše¥5(åâEë•G™nŒKg†”.Uúq0¨Ä´'°„hŠõªJF)uwW¤º{¥¥„{˜²ê’®€B„JrŠ}‰m)k”¬ºë·_vùû0ç[3èƒp*ÏQì–‡®¤[ Ô-wФV*¡msPo?Ó’€ÄÎÎÎh4¢ÝŒ° (~ÿ[®çççÆgùSšL&???´Þßß-ªÖÒ+éñx<›Í@£«"ŸŸŸX€—I°»»{uu…èáá!¬Æsõ¦kÚ]ùÞÞÞùùùb±x}}ýøøØ_®§§'ýæó9–<©B€HOOOïïïKobÓ΀üää„ã#Íøˆ’B;::bÒ—— ŽÁññ1;ø‹‹ º°Éõ û7%á‘æ–¸Ž i„S"]HêÓéôîî{ðœ’:,íÙÁ´”\(8ánô»¼¼¤(š3¡{vv“˱îå ŽNtU§Œ¸»"ïIƒ©ooo‘Cš'a‡Ï#àXLM…^ëëë‹[âô>0¾5 €už h¼$4DyXÞÇÇ’‹F…4oÃÈ Áóøoooà™†Iùvl ðA³CF-œ¸Sl8—ãÇŽ¢®°¸%ºÌ‹:· Þ AÕ †×××$ôÀ1Ë[¢‡.Šø¡Î—îh>&Æ´ ÀÅÌÆ©5[f?)ƬÀÄ”{º èvTƒŽJЬ~ u‰é&X3ˆ:A8)Zq‡Ï*+%Œ–©€îUˆÔÈLš€ºÆ*¸·ŸiD@#6-ƒÈ•A²léט€#`…L¬GÉLE˜iÅŠGû§OÎ÷'H*Q·În@+ ªbkv€Xé…¬eRa¦çrI$´ëNºá‘ÓS—4Z ,šWº*¸wo`'4*ÆòËz$h±ÎêëLË`lÛ* RuÞŠI@ÑÝ®äT âAšø?ñ‰ÇâK9¾IEND®B`‚is32oÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×ÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×ÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×s8mkÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿic146/‰PNG  IHDR{C­ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝi–$H‘¬Q Š2Ö~Y ÅÐÐ×ìó²“ÝúCU3÷ˆL’~çýòoûÛ/~ñ‹ÿûß¿üå/õ«_ý÷¿ÿ Èân ûÛßþç?ÿ¡Dþë_ÿ¢üöí #W¥™ P ãùýú׿†€ÞŽ•è3O°öÕB/`› í€ñcÒ;þóŸÿT5ÔþFàa ë‡‘-Ù¥à6”[&¡¼=³ª½ªA–³ ×î¨*e¼•œ½3CG vǦ[Ï]ê(•8÷Ñ$+× zí€,j\©ªcL ÇQr‘cëØó†ó›ßðD:®ãhÛ®ßÝ15"U¶HG&í|ŠöDÚ¤v-HíKn¦®íƒG: CU3LÆ àœLßµ$+³êeâ¶­—Ø Ù¬ø4Z ɇ@»Ø2¥]‡F‹ªè„5ÎM2ÛÚe-¢M05–ñ|ǘƸŽFk\¯£ð†Ì‰ öņɸ\ùÝËLUŒh±)·e_•>q³’åv‡Ÿ_3•ââMé÷@G‚–y•ðLº7 _;€ª®6!n1 Àé½@@æÇª ‚1¬jg…Ùw¯‘O 2zÑbÓ«Râ™´•eÆ´ ¾é³Â|ûãÿè¬mÏ Ó!sÇÓ±® ØfÉ0gÕžIà˜Y©*ÏüÉ”Î*÷¥ZS¨æ@ šH9PÕ›b² Ì–ŒÔ×Û,¤vᨔƑ>C¤cád=.þ¢$&Î37< ³]—# ÆO*YF Ó/ܾ¯™È‚€L£4x¸Üí"Ç;RVŒh"’X{2Œ³L‚àX #¬±}´÷Åv$›IÓ3™’¿¡Ú1ùD7jÏõZž`z-YE:Ò ÇJ['¾ zžª‘øÆ då˜[UbVJ$·rƒâ3!x9U⪠Av›ŽÀ' Ìgšv#&CîhDÎÈ>Š×TÛ'òé>ˆÆél ¥Z…jA“›jËÛ9Þ8ʺ(ë%&€e‚ßýîwÝ“ÏÌ1JÞb5¦Oœ±£’‹`±Fd{šØ7¢6b-@KR¾u4ð·üÑ9Ó¹ÔÖ5<„**Ðô›—¬ûàÍ»h#ÏŒ{gYvünKíª"=@ÙÜœ [©ö>§w®v½ÄVm«~_ÔÞ\]›Ò jɰc¯S»Ò¶m+ÇÏ–tÈGªx«dYà›Sn«J–ÙurÀ×ë˜mÀ”ˆóÙÂÀ]á¼äJ˜r#U/vUŸ¢Ýj—› àE‹½ë!÷Ñ)%–gûî€í<Ã>ÐŽªíßz² ­!Â2LÌ6Òuúr:j¯JÎÙ Z€7JÌ [[ƈM‡­˜mkØÙ‘¡K9FÆwĈvÀltUG‘?+$æp1Ù®há ´- qŒÜ±Ì¹ÅrÓˆï^µÈk§$ÀÈ‚UU‚ Ūm¨”U;ãµÇßëL–9 ‹`€Žp›'öQjǤAê…¼^áÑ´#³-ïØ•™®À|$g’[ÕYiž³Æ[<ï©Z‰Rä‰ ”×H@/ÆPŽ$ŽÂ}÷²ÝÄÞ_{b7ýüûéA_ÿêm˜2]áØGåè³ôÓTÍ%=œÌBª•èôȺ²R4&*!}„þTG¶¨Òw¸çᘠ2˜FÀÝY—’c\]2™¬¥œC<}ë9Âß‘O&ùcà€µ”c'«# ¸ÉLz$L#¼™¿õoÿFh¡T%s„;7Ú1Ƴ\ËÏÏ¡Fžà©äÙým%ãÈï¨Ò±qDáËiùvkÊFäs¶ª ˆ›‚¬òG*A†tÜ"e&ñtÁª‘°H Ë&ƯÄОH&²£L k\¶†M%@¨ŠJUsЋ§iº«á1"[>@+‘Õå˜Æ± ©7çeJ{ŠL¯T;M¼«!ùà ›eD‹u¬ËJÓz½éôlU•oV:{ÜßZx2¤µy¢ƒ:Ö/Ïmձʭö™;ŠÚÍÅ Œ¬“gw‡û^©*å Ð3obÙz4{FOÓût”90lJCåz«ÖEP#€?ßìÔeŸ(/¡B´à×ô4u‘‚©ÈM#FÉQ ´#¦j2Ù醹ebP<½T+  KôqVÕ¢kÏGc>Lˆå€ªc;×âH)r2¤€s”0eÇ1À”6ý®IÌÓVW~ ¥Öë^Fø‚Ìíôjl+Êz]pW#î¹€ÖèúéõÚG¯0‚§Ýhü&¥GÒȰêzÛ _ ‰Ñ”Û æ +eUSŒîÕ–iî&ê-ÑÕ`-¹©"¹9ÂñßÉ+9â1½<óYP’õ˜ÉV¥ï.-ði{¾6š t¯+Á­¤Š Û\©¨Å&@ãòTÅÐ;Î9q‚ªí†ÙP¼^L¤ ‘x†pÇrŒ•FÒ¿»£ËX² ÛŠfLûcŽõ XhÃFÐ ½³#lbŸ™#²vo^Ë=×.R{0Y³Ê]¤…×¢ÄG$îÈaƒ`¥º‘8ž~ƒ%<@/ˆßì8ÿi,ÓSLÌ$L¦ÆDN©”!°†*Û45*‰¬ðÈ#e é¡È2ìFßþô§?Q8(Pˆ¾tññ\T ¦øBµÆXѱ-ëUÒÂP´Ÿ-¢#Ð52¼MŸ¿—ñwTÕ%'¨±eÚ#ªnÈöÿ1R5pd"š¸Ñ<1€ v ÀîâK¯7˜”¢oIJY YÉ;†»Úð Ú¤•rPu„YÕhy$,”jïmkÁ22p¤ÏƒÇ7%«öÌmŒ– ʹ£/‡¶ê—B/V;ì)(󼓇.T'SåàÈ¿eˆ}-S)OÊÄHšÌsp¬Ú‡• ™`#²ŠÏ­ÝšÛnx½ýy+åð*ù Ç×Þ2²£èHóò³µLwHi¢¨Å^ž@&Ã^)¬,ý™w÷TáFà˜­–x$¥F™!2ed¦_[U•êr„wlú¬ðÀô 0W4ˆ‰¨ +]î³Rþe›Tê˜î:€ª‰Ü$œV-” ŠßÚíYÖŸ¾O£+güô“ÁýÒ hOS( ØƨΤ)=/¥cžÍ˜+k)'è³ 9¿§ÌÎ1]Í{йo™@ÖÓàëåÞ*­Õº}r –k禯’=^´+£“åß8Ìû%&vS­D\/Cân.;â@iP¶4H&ú~7W)Ô’[†”9´°^&0~ƒôŠôJíIk¨:Š+ü`2U†øž³ äŸÛmý|Ÿðïõ•´ )áVª7ÏøZ(iTLß ÔNY‹j%GXìêÍßò€Hæ0!ւ瓃L#”ì¹ãn7+]ýk!&Y%ÎJB ŸÍ¢ÁÈéßQŸ¿¾`½¹”@Ÿ#M ÏLLÁJ”ôJŽHÏø74úùh¡i‡®¯êHÏ$Ã|ÒÈœÏMî ÷{s¥Õ¶Âóq¬Q&˜>)U ^Ë»¾AJâ¶~þlXÕPX•X»ã½â¶žŸ¸4d†f•'}ƒº;’@8&›˜Ò¿ãÕÕׯҔî’[&]m;˜â}8ÓD6WÆû×¢½R ÅÌ¢Ág.‹m¸)-€Xï@]¬úŸ£ðÙÎʈ0Ð;øæDRjgkUÙ·ý,q_Œ›å5ž©_QÂä#kטUY5M²ãõõ¥5šø¼ˆ6¡f]ë7¦‘­¥Š‡+ù„êÅpWº‹}þü¤É O&›… u1™9Q—vÁð=2i=V)iL dˆ$6.Ÿôu%F J- kiC2]<#O ¹²­db¡*Tiñ­ÁDɱ×@I™!,6"&O¯„^6ÂDǪݷ¹Züxà훡„¬H&2Œç“§c?¢È÷^ êF§ÿë»#ƒÏŒLÌñ‚C·Y#šÛDOéH¬xG%—UͰ7qäF@¶û`R&.cð0«‚mÎÞ³öª°Yà c”ÑÈPuÿ0¥š-RUÆ´†v]ªýÀYA†ï;S‹#L-¦–¦`z YÕŽiÌÊÖQ(q–íæ–µç3­ñmB º”–m žªùw„×H›>? 5EI‘9\#^³ضU«j‡ék1«ÑHACÓªñ0}b)“ŹÒYô®×Ú‘ýkdzSÞß1+@ Èyï‰Wm ‰Y#CX´ €¡LS ¦)4×'èx.S3ë@"Žš©r;9ôj~øãKh¬—R4C&U‡Y1ñ€ —„ÛÇ58*éd 1íÀǪ~¨v]"Y ,O U 7¶Ú1²Ç»æz“ÉÅ+Öâh1&z[,^æ_4…À1Õ”2^t4ºF@Ð;n laá½aGY£Ç±XãâiŒPr ¨&pC& ZÉnðHíªŽ Ò˜!@É_õØÝc>6‰äS»’~“:Šxù;P»ì:9Ëû£¨ýuI£) ž?g½}4‘ [@Iý^æÐqš~øCŸU¼ÜÑ&ní€ {|]‚سªÂ©‹²€¤´+´ = ž‰RžÓ'Ž_©·uzûv™ž‰¡ñ!6s·;? ±q€ë`ò‡7H©õ˜ûz4BF֏ɸhW­dCw¬%Aû¿£¹-²Ý&%+ÁÊE˜s»TG½ÄdÜzxUx ^ÎPµ}0-PÆk©KÎÁtþ.å(¿ƒè‹ÈáŬ€°¹ª›Ûe=à ÏhCm¯¿#²ÀççD9‘\'uX‰©—‚¹gŠÇ U8´ÙÞ%+9@\/ñRíS'˜ƒjbdÓ•<%,×kÙ±­4Ö…Ž2F„m(Ìb’ùðúÌ"«6Q»Ðå°`º|†ÝW†u)qP’µ¤d8RâÉШšX¯AÝCÙCþšOý¤I6*̇¾¹Àöo4A&ãjâ »5^˜¥EôEoç¬û+GÊä<2ŸÖ««*OG<ãÏfÀtdÞ—f~®}¿2OÎ0ܽ<žÕo8&s¢äŒ!CÎ?ÿ|ˆU+-ŽyÔ,&oUÁ“Æ‘FcŸZãð¹Í„LÉ‘[×☠´0P•Ý϶‰òÌñû œG¡ª(kÌ háãûõßKÈú3¨JÜ,†ñ§c£µäÜJ<@¬šxJV­ ˆFḩR{FŽ»zL¡ËV2[¼lk¡.8ÍÞPIœUî;¶?O dåÈÖ±Ä(µC½r»9t”{¥œëí¹`dVæblÞJ²¨7ó ϯÑ9ùʬmÙÑ€6 ßf8ö:J˜‚§cN‰ïH¯ÔPžU½,€ÇÀªÍµ½ÆºäJõĦÓÔYÕ³ÜÎŽ431#¶‘‰ rp×É?YU¨ `þ@ú Mq}Ùï‚€Rš|ÁF8¶¿¼ç"Ægˆ7TK¹^$[¿Îö+Cs7¢jVÍÒKlÃ&úBûž¸šÞ†òT*4Z4dÄH€8ÆÄ)á U™'†‘J|€L<ûóÀ¯0$dæÄ°l `˜¨jIœ9 ¨*s“Û3>3h0BcW ÕÃç‰ÙÎÛ„Fx^Ù‡Ò&)[»lŸ€Fbaœ£ÆöéÅ]ŠyËÈ”ý&RЬ¥åÙ‡G‘³¡¬é7î ¾±vbœý|> šÕ½ð4}©àö$ãàȶª#}sÛy•’ÕE#æ KuûàU½˜lDÙÜ45–{CXµ×fÕÅ•êÍOŒ‡¹)5 Ù?*8šë¾Õœeúvާq$Ȫ’ÌSД‚2£ ØP¶¶c·±Ìíü¶õõÄÚ,iדÙ)§õÎîÚx½JÛ@µÛ`cðZR¬L‘1Ë\—j÷·•*Mžx¸8{|]£5ˆ…ªcG-É`À½ªžæ¯ÿ1@êíA´á­‘ƒR^§ÏçѸº¸ ÷"Èí©Zo›¨ö»8…ñ¹Oñ˜ÞÐå?íhLàM4#?i5ö)`ÞO¼’^$OGíõÂùàúé'¼­àp”9d[{WkŸ÷:p?ö½°n2åp2QÉq;8¶­*íHo%œUueµ‰]­ÍU;$îFŽm·yJ%J È{.þ4­!ãÛan«ÖŽï/àü3¯Ö“F¼Ca$10= ¸u½²#ÃZdLÕ”Ýh{¶a¯M)ÈÒ(y ¿ŽUE_€Ö hJímÒãÄÇèj¨\t;]C`"ÌÖ,G ˆ? }}ÍêUÍ Ô 86Ž óÓùÕ“˜Àz3eí¦"O©% ¥=ã|h’Uê5ø´› +¬…•oBú®?Mn²®;ö|7ðy¦ì˜à,}jûëÊsþÏ@•ûלÂÑÓÀåj*˜©ª Ó¤ºâ])CU½HÓUƒ¬”ìì~K‹ а½ò“kÏ £E;€WÍ_ËøÐÔ˜,[âcz¿:òœ]ßUw;U%4ȺëâÓhGw´@©WnÄžÀ´ŒªÏ/«dzEŸ‹j% óŽ}0Že†Hs}â}ˆa>uñiÉÖ¸+>$+ hô[ ‹ä$ÎDÄ$ãÌÎ$gËPòlÐx µSÊí¢Jª¦wT’É0ÉêMÆHSo-M”U5Z©›¾»QŠmÂD4¥’Ü”ŽˆE»Ã9ôp@isë•[ ed$¥ÜQ/œÿ̳jô>¦æ&~õm[U [íòl•𨇵%;&Þ÷°ö¶Ê¤eÑÕ10Ö”Ùª¦·P ¦Mµ`Z[.èø/îóñ92l<%Ÿ!,¶¼¹@¡ªW8^ùçgÐcîï7ÞÊ·1M²y"›ÔîHÓ‘L`ÄÞa-ñ²Æ>n¥Z€í3=†Œ#¾ýáÐ eÁ Úcu=qz¾þû`.ñZÖ•Y¥ô}1kdÏ6¾kpkÑlËó¬¥Aº^ŸVµswi¢Ü‘CÖ^Ö¥ÔJ±[DÔ’Çöiíñ)UÅv«ŠálGèÇæH¯Ø1Ï~×ÛÒu6…?L¿ ûçõx¥ª=¸ÆÂ¬ø[ÿüµT‰‰‰ ¢™Œ›U›²×@6TÖK¬$Läyý>ß®.ØD;ÔÛJÄ€ ·ºfž-A¶ød …1´ë¥Á÷ǬTV¢„Ó´ÀªdU9¦ÅdGŸH³ÖEoVâJ-9Ð24JùØ!1^ªdô.³ÍdØJÛ0F~ƒ¸‰@nA<ÀÎÐ2Âܪý’j<9¬r½HGß4QIÎg™!·Ä2}]&få˜@¶6 >#°üÉ I ³Ê0ì0‰ÏîX~«ÃmÒt]ù; þªÃŽ2 ÐW®Õühql™î˜ÉJÙ®J 6ˆ`þ­Á)‹^ûµª[ä@½2Ãx˜ÉY¿‚„ÆrwŒ¡ P:Òû½´·£*SŽ ¦‰Y%FUTÒ.bÈ‚•h0ÿZé;VÒä äCcó°U˜Ä‘¾‰ `n¾[]ÏʇŠ×Òk¡$ ö{·Ë?™*R;=™q[‰ ÿJíßh|¶õjäÉÄ8Ga1Î÷6Ÿ_ ée>d޲Ÿœ°ŒìÈŸŒ¸K±j¥ªJ¯UžUµ‹4˜n§}•X&#è.µ¼>ôí³LIŸ³ér·€U[²Þ-L ´8ÆsËŸ³R¤j¶>RîÖ“À§½Tç©¥À àÕ; †ƒµ4ˆþuC 2áv+BcS´g¢=g AG™I#z7XèÍÆ“í»‡©%[ÊIJ/že4Ælœ–—äÖçůŠ);fŽa"'Ëü圕`@éûYsäIÜt%WÔž‹%òìq#±I)Tú¼2©QvìMˆ]#è9 |Ï8úÃ;gG2™²‰1×hÊÌ;šb™3æòé5ªÆhG} ôÐbް¨KNlzÃ$’¬=Õ4°Ñsë¡”2b>Â_Τ¬Ô¸ ÂtßœU‹lU·C#jìbÈ]Žbþpâªd˜Ä…åB»8ÿ#°Ú±|þ ‰Ù¯¶]˜uëêã/9C¹^Õ>3¿J0rJ8Cn‘I]€ä~жq€X)LÏ_¯}µÌ™†À8šôÚ›…w„ªê9LŸ‰£˜ 7TÎ$ËÙˆŽr¶v¦§lɲp ÕLµ¸uÊÁ™Ä‡Ë-Дr-°®6”{.æuaT{ð^@n“­‘¥€é¤·’È0^N™‰\µŽ™Ø°’Ü-4¦"e¸c9g_G>5’‰V’ë)à€ªÆZ" ®W51OâÖSª ÈV ¦–î•Fî›o7¸q”‰¹±õPÍE XÖ%h´tÍù]Fu½øöÑ~&ÝÅä¦tMâÚ7%Ya¼,^-x V"(æÜt )°…k!NDòì«î7C¯‘@Þ5×µµ¹e(¿úuÝúIüÅ–4â;½#Ò,A¦¥œUY)ÃCün7%Po&ŽÇ÷¶;LäÓçë˜2ÐÎï}ñïnª˜ø”C6‹a#S|…Úd#Î?€8==Í.@ZUI8¾2˜u¼a‚@\íGÜÅü÷_¤_7>æ>ã3ï¹?o´Ã¬Sâýåë£þ?Ÿ“^-Öh󔌻}þË,†C²­G€?ß§!¨„4cg|¨6‹Æ¸ÁZHGØ‹wÁ óÔ(RÝ"qf)!e¤ŒX‰lùädMoO¤c]@GbQ£ÌjÙ§¤A¶U²¦+å\c¶½ Ù¶%£mè7†m&gƒ'xj1:޲vb¡·pÌ-¦j;w%£Éj©D tAX˜‚ÑN6³.`£3!˜ç`Dtl\½åœ•t™`€uåŸX•U9†Œ¾}0Ž!ƒ{RX4Ë ]J…–ø)4ð”µÏ ´ F0ô…òüÔ¾Èkðù\–Ñ%ZXKFžôÝM‹#^æÐëÁF«ò¡ìFŽgƒû%‰ï8[²4².&™×‚ÌÖ’ýqÔÒ&•(ÉìPcÙ,Ë7+–ŽºÜŽ^W·sz¹GØ»M¼£5ÖÒ«j ï8ÇlíF¦dÛÚVÒ5gø³"ŠH³œ?çýÊîªu–™Òô“Ð$²|Ù‰µ´JÐg[µ…Šõâ… /ØPLä•|>r˜€£ç†²–Ü-#meFÆcD÷ÂG<@/'6“Ff‚Zp7=û‡_@ß-´dµF|÷U"s#%L-ªÝ¯1“Š#hg¯éH˜g-dù÷×Gz™&·L0E|žMLò,SB•F4—OG%L¶p‚e|_Α6!kFáç“yŸªÂÝ” © ¨4`DU<zYŒŒqÜÎ02Êø êõµ^„)«b´×h+U‘ é.ªÓ˜Ä].Ú¡œ>+¹‹7®% z^OWbV™èÚ>Uk™mSè1{½0f½]3e‚öÇ×"ä9†IßðÜð™oA]xÎ"ã™'ÀJhWíŽJðœß4Ë)‰Ú$L¬DVÎIÐ7ì´}½j³ÓSf¸¡’e.g~=Îô˜ôJ9s‹ß&•ÖX†³RUG •¶ ÙÄpƒ0~™|þ4ˆ•×í|>EŽ™6`[–>!Çõò­Ý±¤GïoÜ0zUËÉ–mO`ôpwÈ æ£t7:ŸF—ßeµ(Y¦^<™£¡0Rh©‹ž§à@6 ¤I– Œáã=nƒò,·ÌÚí÷Är ÀiddX hsÑ8‚5w-u!û#æ`™™8æP»ÛåÀX8*ˬð­äÈJø@%¶<)åæÚ6[>¢FLx3p´¡‘> ÃÍQpƈîxãçÿ m¢zmNÙB;¬ P­Ú½´ÔHƒ@™A¾½ñ)™É`íZàH9Ü2JÂ\¤h “œe¼wà–!½.šÛtœc¶*i˜|*Å»ˆÈSVr”¹s€‹LìÛ‹lg>py»9úÙñ2&ÍÕˆwLüñ½>}ÕúKêD½-Ó†ñÚ­ÊÊJ†º»A2AkΡ…5rCZFÊ˵l[ }-­—y-ªZddî¨+2ÃÞ¹%e2üŽ@-¯lûÌ-ý3¹óÏÜd4n+˜~×Ç Làíš­?•¯ÉϺգl@9Ç>¤>•Þ‚8#•Rß¹&ÁªøÀ~ïsÓB#àZr‹ »RÎ4|Þqã‘™”sÞg¯‹‰o¤h”ì£+OYpÃ4»Ò7ØÎÄ¢‰dýL¦ÇˆLÚÒL‰ç®¤ zÙ‘†9œ¡#²o[Q&îW*™c>Ä–ÇÇëVI57dÕô šFÕVŽ4¬ C ?V#5†e˜ÛJ0†ƒFÎAh!P€ÈD nDšœã—•öyI¬EId¨ ã ÍŸçø–ÄŸ¶ ª7¹ÍÕµ'[ –³ÒØ[%“1{[ q+©k¤Á Œì(êâg2 fWf"”äcôõß&À Ó°íxµ'ÕÞPÙbýè5Nny@kוßÂ=K2ßz¤oìî^ 2çÞ TbÛ1-¼¡€ £é§€r]ÄÝq‹)!e]” •0"fǵ(e wå—Ìv-™ì:kï"ô‰—U»]þŽAëíëRr,˜²à`aé1Ú12²R]ñôŽxJy×qħÁ‡kT*Ã@˜¦kbDÕx áZòׂ„¼só½½ôI4ªôÌ{  «ªÐtL–!YïÙ>a™^ì¸/¤)ø&îv½ÿ·¿þõ¯sÑiŒ ÊÐ&‹~•÷˜FNFc->Ž21 î>石)«*µJÛ Ó+mÐg€,(†s˜9AäþIÖöÛŸæ}kÇÊMö(½ ”­Už¸*“Ìødu¥ÇôÉe’@ ËnÄY¿qÉXÁë"Ð(jÄ÷ hh@µ® aÕÞÊ©TW{héeJã”Ö…¬—2çô²ØDX#A$q³(U7šLI ESrX#M· C’H‘†'¬1’À§7N‹zª¹Ñ)×ÂÙ>ªÊ|ÂúZ(…’®¶’,Z²+¤ŒÑKœƒ™¾Pµ3ÆQUo`sUálS:æ3LÐ~z%þ9OŒŒÇäÙ,sñíз·f™¼+÷¯%s³FKV jI|nùœÎ«¤ÁDj쑬4²Æ>tG%‘•¼Ã%>7Â8ò©‘É 9àÓäLt‰ö)ûí—²··2À±YŽ»;«vHI£„¡‘µÓÏd½ÑV2+úZàÏï¸ÎIÍðjÔ¢R¿ý{™ÒøcsƒÌqc`Lnþ6ÍÊê„‘U‘µJ<=+Y¤'ëEðºŠwVŸÁ˜¶Í“Ö˜¹Œ—m¥Ô>Ì÷ ¥!htÿ=€a•ƒcA‰ÑÛMSF(Á€§»ëœkúgý%<›neÇÓ·< 0æ»/}4èË]‹ŒÑ˜g2Ln2ÒÂHGJYÕªvsƒU[8s¹^YÔ›ùÓPúMGHÎþ¨î k¤ÌŽZð˜ýuéeô*uï’]Ÿ¸Œ´aá£|òDÎyŒ*ÞLÃÄ0Ʀqì+áXcVUµ×Å!,ç6Œ O4W.ÜÑõï]Ï'Ò”w%¤cŒv‚MW k·pÕ Ð{Ïf%fÕn×õãœÀA£ lP<ŒœÆ÷+5ƒOÙ 9«r†½3&7¤Ð› ÏJ2IÖû¹¹É4šÒ3äŸ ¾h±eÇôª•dƒZ#¦c‘Ä1}+LÇô]mÇFë ñ€ÞAJ>ëަs&˜IúvVjÃ7âü¡§a“ôXîuWŠÉ=SXÞ1ÎDð=h†Í²ÅôpW{ÄÞoœ–ñÉѪÈr2¸gŠ$Û¬”d]8ež{Yb?3•¸ <+² ËH‹u™€Åû…ÔK/ãÉ2„r›7‚‰Ø'…´Y‘•Æ‚2Þq%LË´¼&X©*FTµ@]ýì„#iLñùöç“RÕ&ªZ5¦e í:H˜á0—ïLJÓ#µSfBÙò€¹‘l…#’î+DÌMÜúçÃ"Ãs~/’òåa±ë kŒD;`FšebÇ®ýª>_ %Æ}+à]œËHÊvîÓw¬äŽ“åߘôª}p™ô•FIKŸÂ†’ü“aLǘÞhY‹’ˆqɾ<ÎÆ kñ«¦é “™¢”ËÄ;’¹‚¬÷ü¥©cœÃVÇ÷"  ÞÈÜñ2zŽZÎÖÏ¢4"’¸ @Z±R£×ncWê‰M§¿fŸ8¥œAÓVÈMð]8 q&p·ÃÄódÓó¡41A¶éU+½Ñ[{â4{ÌÉ”†Ç<×…dÞ·¤µíæ}Þ‰[ Aó4N0ܧÞ,zd³d¶áôœd£azûÄDÊ-£OV ÈXUêî9ó0J²›Êï°önwqÎü™8Â@Ëh±›ÜÎ@#G3OÓUß^UѶªMü¢Ù’Y饇¹ ¸}0®6±4Ž"‡Lb`úJí@S°d¥ºdb—»o¥zGf»v OÜVóÔ¢·v²ð›»,Yn•ìÖC© GÙPæ%}®o;§Á>ôb@oíñ•(þ²ö×àŒy–[£*¥#óÍ}}苪Y­$³"ÈP)L€qÔu¾>Áôªñ@湑٧GSrT•YVrL£ÔV²jJYøZb˜Èm3ïç¨.2nç äÜUQŽa¤GÚ6£jûÑ«öç¼]a‘!€iRâ¬òa¢—`â~ß!r`ã˜Ð;r~§geU-JMÉ$Ð÷Œ¦vJ|ƒ´xÍMl%2LW°Xže£3!`èX¯'JàðÌ•,@™Xnt ›Ò¬€ÞÚm‚Ú)Y1Ü,Gä¾pz‚¦0©#´w»”­'ƒ;VBúLåÐŽg¸?X9âÀ½h–,ð˜2m[[ûÕž•ð-–'±MÚ³RíU=#[½5RÒ4 Ä71 ”FÕh7Å3—›B¼ë7(>r&J-C¯]pù¨êrl´*€ÂQ¤X U €Ù‡ëˆäÀ³˜ÆJ”¹!‹ÜdÇzaÊÞ¹éÒw¶ êͳéÖË\‰†! n¥h:  w$ƒïë¤QW p+ù^¥Ç·øùš¥Ìéû&(Åä HÁvú4Èd]-qέŠ1-€ÇÔ¸vOÏîW±‰¢äÜ sËÓ/%<’!ÜdDÏ¿jC»Ûx$ÍZ ãŒ×¸µ¼AŸÏ•Ž(µL­_†IS;(›MÓàf\á¹Ð0àõ!fB¼AÈ4~Y(%î& +!ÃùÇ–^ÓÇ芩=·`µ§ìF¾¦YU"Úynóv„*±€‰ùŒ±'²/·ÿ)ÕD>=^ -õb„#M½åJ°x×vÔ‹™ C½­!ûˆ‰Yi‰Uû“IµeôÎÒQ—Äs@È3ãëO;z8sÀ±ÄŽðæ:š"6b]ŠX 0N@ïI X©éûÚÄ«êÊmGdØ'Þ“6…‰wP¢ïa}|]Ä #UÔ^CzY °«Í§H£%=ϰ͵leïƒL@oíŽ}"4JJ¶Ž@ ¤£F‘˜~²p%†.ë"d%G¾Îë>ŸUῼržßž À¨^íí"½CÏR©+ôªÚ3Ï“ è{ÕHÉÙ‘C&2R®KžØõSÊuÉÄ)µàûÜ‘ÖhçöWá-@ +2L»Å무F7mϦ½U×l²Àè%¶˜R#0ª|äÈ®IŒL~µÑõ¿¾ÂÔý,Lµå«§adJU’+ÁdLÆA^KJnxzâÚ%W2]5Y]3Te¥Z %“^²ßh£‘3Ñîh–Ù&‰ß)”ŽÂSì ¬êÂŽÖhD¼}øÇÃÀ˜~ÑÔȶͻxþ²czû‚mbxUJ·ÎM¢¡Ý5rèý9“Õ‚Êôµ8&«ä(”œ.NÀSx.Œ}&Sê:H¥ÞÀŸÞ{ññ>ZrCbÊd‚³q¦«:ú3À8÷üúíœ,+ž#Âx-e$ç[üùgžŒ¹Wjû7´È0€Ñ2ÞQtGU7ˈªåJ0@Ö1óô0s¼ìˆô\ôüåÈnT L&ø×Hæç"Û†¦Læ²J³"€E»•;6ÎD»j¶0ÏõæO?s²4€`âî‡H }ª¯‰QÕâƒp4(}&ŽéSWom‚Žrƒ,OÖ2+!«}ôHÁÙ¶ù¯±£^Œj_žÚ#e|þûa©×d½2bYV¶Úd;×â(2—™8–oå”DO‡é ü‘ðÁ(/™ŽHÐÉ]xâ&ÙLËòõK?“rnº¬=^æ`%Ý¢k‡ªkjæ–{&ükÛ1禘ۈZˆ7— 7‚-¯:gUú2q›7B.Tñdspt‘î²öz“Á½†^±Æ/ËóŸ”dª–é­‘>Õ÷¯¢¹1!¶¼*¦˜‰ÞJ™^L7TI/%«ôCáF¶ŠÉ°¡)Y)•1F¨ŠvÀ§\ÐO1çZ€”¢•d¤”mt,kÄ4™#,3 ;ê¥ñ’º„Û!ïœ_ùÃFtdžh´$Ö¨ªE8jl+@¨MÄu# ªd¥˜ñª»;ÿ9SÖHYW#à!~$ 7’! 8ÈZœ56ް³ Ôž™£*qvÔWÅ_×Ïß Ö…Tò’ ʶª,ðbKb´8ΰqó€­‡Q•[/“Ä3 $nO³hô¦l.Y_“ÑË}÷Ìê"mNܶxÊ6ñÍIéZcÀPÁÁhpÓËZRõ ?©å7… ÃD¹%k×åøóQªÛ*ݧ›Ô€Á‹ûõ>?˜ý]›cÆ0IJÙ^•­ë%PâÓÓTJŸ lcÁŸØ‘F4`™Û¾+œ¯‡4d¢v†Ú¯ýù˜Ï@›¨æÖ&ló¤„e¿8Ü®K%–÷Œn1Ù±Fèõ,œ­”¡£Ý0)kQêosº`±Æp#`¥d ¤à‰ôÊa€ãض­Ñ\›#³›–B £‹L6½x‘¥‹÷à@ŸZãx’Í&–Û'[z>k=Aï†É°ÆÛVŽ1·)ŽY™²Pªj ‹§ª£ëTÒ·‰O­¡ùSª‘!‹ªpΔ"eÙ‘m¶*«+<Ûš[ÐÔd²Æ•Ú|ÇÀÚc2/Ï$ó>#%úÜšN&Þfµ¡ZhÆê’»ZwLFP/Û–¬Å‘øÎm³ðÅî¢ÔÚ2ÿrÈÇ1C˜²@2qÁ#·Àö ´¤*%¦.Çk%U ²Ñ]„žXôíuÈDìñ5joí°¬/2$Ы¤1ÁF$0EK éؽ΅…²Ì4  7JŠgæ}d«#6™.>ª·ã|;UýY×_¬0Ý`Õ Yí¶¶X<}¿;Z ICPd£$0íÜ2H@»œ@öjö!F²ÒBßSÂŽ€"£±@VLU]µË9ÐÔë^  °A4MÙŽp#h`ŒÈsí@ŒnV2-½øc”ŽÅ—‰*ÇJŽ·x­Rz™lŸM¼®^ÕhÕ–ÌDn(P;ÐßR6±Ü†m’>gŒ¨ú.Fc[ÐÐ#_Ït%n7ä–Ï¡#ÈÃн|Ê®Ð玤—É|)›ã)1ĪzÉz–ôÈ@ä¦ ™hÇ×å¦^¦©¥7Ä#ù´CÓ1Ú•(ÓcÑÄŽÃ7Ž¡OaOŠïk£%%Ï j½ñ½ñµ°åi1ãÞÞd2¾mUéá.ÎÖ&|朒ð¼€Èÿ½²ªÆFÀ‚†ù|xÆhW•MZ %Aü”{. ±‰”ɪ®ö€í¶¡~Kàë¥ln ;ÒËÂJ} ÄÅd ÅOC¯‘ Pʧg›+WÊø½¸cβÐõíÇd­G®\VŽâ>»6¸Ÿ‡Ãt¤$c"êªT{Ë寚Un²@jÄ{e>ô1U•0HLcnUY©Üªs a¸‰€è›aÖëP»ª×Ä ÅvDíxVÈ‚O%$‡‘µ# }=>¿5ÄãýrÉDVšI2$·¦ïÏÔ÷ÊdÂE&ÛXåÜ—¦ 1B‰LÔÆk8P»—ÔÕ{êj\-xÌß·¼& J‚Ù¦ea\%¸RëåϤß ¶¶UY‹(óÑN¦ß±& ÃàÄŽ¢vf« §çVï|ò| uÕòj²õÔÞVæC“¬Þ} ñôø2†>‡öQê¾[Œf/Ù]"O|Xî"+Ø#k¯!\$ƒ[ƒF``ÂQn(€WíR)zËÄÈÄa ÔX¦Çø(ëÍ<7¼Fþ”@‘ “Foh`™~%‚^;ó"ŒïH¼5®ü ð”a‰ÀÓÌdC-‰Ì?<†m£1BË4Ý¢qJø9Ì矸lº ~í¨ibúÓ¯Whª^¾ýjذIJ ¦‘é)ûsž@»RÀ•ÞqæRjÉ&&@ÇÚaAV‰¡•W’óyy }SòÙ?pqÐBœ'LIO,"(Å“ásÙJô”`¤qªn9=÷{“ ,>³˜èjÕí€éˆùnC½VjÏ Ð”µ‚˜,0íÜß\”ºE‚2+üíþ|âõj×’†U4²AÉÊ|ðŽ¢é@þÚJƒ” þã›N@‰|Í‘ 7 H~³’/­ª)­¡ÊÁ±}:’!åz ¢Ôn¤¯VJŒ*z%|¬ªÔzJý:Fæ¼¥/’ÉÈ4ºèŒ*,wüŽ$¸Ú#º,2Yû´³œÿ ªk‚¦DºxÓU)ó„…RKZž#Oï)ü+æÊÏ›h—=e¸×³pÊ= .$Jm-†Çä 7çZ’¸ÝLAR¶Œ£è‚zç™^#¾A‰Û™ °€ˆôàdmÒzY‘E6…Þe>üi`@6T#œhOšÄ4ÜÎåÚ…B¿£mÌ࢓&Ád@›ôÎ ãèK™ ß…ñi§ÄkÁ$&hãÖð^RÌ#­*›ˆahg žgXVBÒ‡›²¡9ôR4m›Ü}(T=—Ƶh¦0=`g£1ôd½+UL-J45*a:ÆÌo7&‘­· "1z‘if[µôâá ‚mNc:,ÛßkÔÕ¥t‰6|j‰/}~¤úé'¸¹€ b²¯“žÒ&诗@( ¼#@¶Mð|nÇgÐE_»ÌM¸`&òµ«’åS©ŒÊ^xƒú}„á©·Yª}XZZC¦t}—Œ3¨Yªô&4|x¬(ñ=† žL#C½ð2L#ŒNÙªøÌ½2Ì„@I61ÍJ×é,–-@¯J†qµ§” Œ®$;–ɬW#‡øÖ Êdª¹mÕý¹¨‹ e+mÕ6o+²¾Àdº`|&ô@³dØÐªmUUKŸNÊ.ÛÄíY#ÿs]ŽM$àæØŽø&b|`nºðidSÚn„,øPÊŸ¿nLÝ~D]©oÛÙªJ î&k¡Q²–ªŽjˆáÄm³ê Uws ø•Á 雡½‡ÈÎÕÜôÂ2 ÐdN/º‘ªMxv¤TêÓŠ\#"–…#þp X¸ÝÆlç6%òls£÷™hÌù£$Ú 뚀`ëøûßÿ^®Œ‘•æ°Uðíœþ¸ß«w Y¨² Úw£J_‰s±2zÕ=/R¦‘íC *ÇËHYWb¸c¹q—û¼?qW8s#£É¡9Òd ˆUkÇPÖÞÚ}Cjlʬ›‚TÕÞÅ•$Û ºvÙ4­Q»’^ß±–©d O ¼OŠ• LúÐ'#µÃ)+á‘ô2¬ÄM&γ$€o=½E]aÕ™`(Ó 1rVa·kâŽß^Ê^;M?t–tTêÖÌÛ-’>ÿxžnAFîŽiÃÄé÷sM¦ÊSèJÐíÞãzö²Õ¬QU»^ï(ÕÒ•chˆ•áJŽâô]IäIƒq‘ÄûÕqøóÿ)<‹–ð^°H§¿=d=•pÖd+ÉŽ­ëêYU^¦É!k)`-¶êhošg÷$`‚$ð W©­‘ª~BêTÃx ÜÅ=D+)ÛSÃd0ÆQÌ$F¤F¼p¤ohǪ2^Kƒ`-p³UÅ„ëͼŒYÿûß;Ê.â‰âÓƒg…wY¤ K)[o8s çx%í²@.(14`bãjÄ7ˆ,׈œÞQ‹hœ§CöÉF6™§[äÏäö}úªd›OÎ2 ©kß(&õ~'KŒlõö5ð¼}ÙâeJÑDÇîâŸlžé[£Ï‚È¡^šéÛ0Ûz×¥%¨QÞÜWÀÌmþ€HÌ„'% \sÎŽpÇw }Ÿ8ÆåÌë…ªp&ʘÒw)¦Íãk4¨O¡GЕùîè(ˆe@#5ÊÛ9É;Êœ5 %½&®äh ì›'L,˜ûê"ÉÚ0}U¬rVUZ#A¶Há˜Oz†¾MT׈騚?FU$¶RG2Ìd­—æüAgžƒ+ÉŒôÈšeí´ÁªõcúøëÚ`%ÑÈ|všJòôhÚ{,Ø’ZZ )´{ tϪ2¥»øG:@Ésv¤obÎŽ½2«øî¥DР÷šª…j¶[ &О2™¼ŒÑeD†-f-ª™OÙ”ÈÆér¬‹·þMfíUûÊ6±5´ Už%Ž©‹y»%– Žýö'ÎAÉeg8[dKRNcÛ™ÔÞ>9¨x“9C¸ª)Ϫõ¦Ñëh¢™Œwìû¦Ë/Â8M`dk;2ô¹«Âºšˆ­"ñ¦T@IDAT:ŸôU'¦|ù¬$à2+Ö®·œs¸µgNŸó²®÷jñéeúÖÀ·›cšxY;¥5`ßGGOíA0^{ òd‚G6 ŽlmíŽëÊ#”Ìò{LÕQh‡«úüï{Å™‰qu•#»×ç+¸›¨µœ‘€1ŒòZ3£šx€ªÞÛôù~LÌ\8Òÿ_ÿm™¦qëͳ¥çÀ§ ®K†};ýàS²ê³Ç `Ž4vÙ/SžÙj$óK YÎ?Ú°WÕå#Iƒo–#\;½c ÿðõc„^švÃ;zûQçF¶5 m eŽpsá×G£R|ä3ûëKïXKbþ"muY(r“iwÍNJÙ1¸õ·|¥ ¥Qb®]ΙJ4h´È?=†ƒFW ®„€Sª’‰ŽøÂ—J V’U;r†1¨+}SŽÑ—Þ¬ÈvŽ¿õóÛ>x¸‹(‰F7®.dšwVÊr+Ñô#àîÚûNj©«-³‰Ž ê.°@öç´§h9¾}:Ê|D›Ð86¢• ÷ñ%Cö%ïö$`b‚HǵӇ«¦G6Wî¦<˜Õ× æÄ‚IÓë L ÓJªLà󇉕(1Çú~j©¶ÃºÚÄÃjéªå¶žo7-ªÍ’•`E†GN_{å¹}þŸeq +d”iÃ` àî8MXîžýO.”d 9øOŸ¬Œazn¢eñÞÅ“ÉLTóWÊÓ±A¾£¬iRn.†&=@Ã0qÇÜ`Ê3õkÿ>*ûè¥W•ûœˆ L-Ä5P:v‘3!0}äaGVJß±ËÆozSd¡„§0F‹à÷&6WûIxŒ‰é±˜1½6 ð=Tþµä¦ªÅ@µR/@`L¤\KÏBá • [†²8WÌ¡ßeŽ4Ä·òIÖ`^KÛàf1<5¬7gŒ£j§Ì.-Õ–©Frx±c¤LÉ(ó±1Þè!=hú-ðºÁ]¶µó!vìµÙòäƒíÙzý%ÃwÀqŸ”)dJf¥½¿ômOXI&nG]¡—²Jp¤jJ<2d½Ž¢Ñ‘ŽFpC²ºÂŸ'îH–ƒö.ÂÙQVõUQ:6ãîMÁG< KÕtËèíãhœ^‘[-ñdñH ,:6Ô8ú€¿§ÎÓÂF{jš¢7áÖ3")‘‚•T‘¢)ÛVéËæ«Ž™Ð#…ñè4L0É\Ä÷ÓÕM²[À€PÍ&ŽArètÌ ÉM騔”a‘9ã1Ú“šLF’µdÙ½0B£L“LÔÂø0+-Ý Ví8Y—%è³?+%­‘­eš®$`á2o½ùDPÂYÉLuY€9Æ"1U•ÈôVêúX‘U9ûhzœÜ`¤^¼^ž¡ªQøe!ë•)åÌ· FØPfR•’€mïy…Ÿw0 I¶»À­Ô½êÕâ(EâÖ#f^)>ÕÛq.¢EÆH2Gså«ÝÚÜTÓlP†²’Ƕa†|rhØ-”ª:`äžC#6QI/[w$ÛzpÁ§YÌc4Zˆk!JZäðåÎ PÂL` ¼êœÙÒ´à¨1g½ Â#kœ3#0Þ vYW†ªø¬È”ĬðUÉÒÛŠ€ÒqÏâ(,I ø”»Ü!)uq€¯ýùJ¤¤ùª^úÚ[#F~ûË_þâ?4ÄŽB›@6X$Æ'ޝ îÜ %J¡êˆßþŽQš8.wÑåz+5îJ>?*ø÷'¶È")­×ÿ2Ü¥-8Ò{VØn­×Qoš-V»ãJïç±ÅšÕ 9ýªF Á•hàB•ÆïI+‘ñP:n\&ÈßÜ\ÌÖÎ!O¹ãü·*>Ÿ1Žô"ž [Dú­aóªx@cCÛ£%²ßÈ|0^ÃôJ²˜ǘ¦·'†[8Û¬0“ ´•‡ -–yúrä ¹p£ô3'S”aWãûcI67L¬Š¬ø-„å¬ÒDj ÞÓ,Xn“øu1qÍ—¤D.zz|ÊÜ`a„cŒ2SRv‘=HdGJǖ̹ÞÚ«´?RaœÒK:âcrH€ìX#+±›ë Û¹^Ù±o#@€¡éHßá>»¦Èu©jÔÞ#8.®K©éÙv;8%ÖHÖS;&n\¹‰óÔ |zŸ6]U¾•ûƒr¬œÂø#Hp±D‘ckm‰H£·p,ü\ém¤üÝ ¹Qê ÿ/[w°%‰m#kx¡•ßTDz^_ÚùÌGþ™Ñti°€ƒ@dfU·dϽ=¬+FÈ”ñidžø>ª&n\ ÌßQI{—Ï$¥Œ$ÀسM¶°*^œmnT´@‹©ä¬Z©[7}í4m›-G $†Ï)tÁói2¡Z/Áv»M‡'@ Ìc6WÕÅ}ÑgµYc¸ÙÐ2òþú¼%™p¦Ñ"v…6WuYY/MËô#çˆÐ 8¶6=œrW¸>ú†e²f%ÃØ¡¡ñyƳí§ÚuüÍ ™Rã4jI±IžY%n[U@¼×G:"w í?|Ò0$ƒ ²V² ÷¿ë‘iTs¸ö²£.AÓÃ6ýt~‘&ÜQÖ^L¹ç‹$c%%œ¯ê“Îà.’¿BCÙ€¤ ”³ê;Ã!%ÁÇgj:¯´FÕqƋϷ¤J¯+™/6“F5:ê"`ˆqÓ±.G%Î@ճ͵ª®J`ܱ¸‘^¶7@&é#×[×9ÂÌ·=F°:<ß(¸ö3^™ˆuà6ž”o2ÊîÖ*Žø^SI¯¨kÀqU]» ÿ¶Ìjz<|Æ?Â$±¬*zw%G/e?@S(ÁÚÛD©¥¹r‘¼GÄ8Žïh Ÿ"ÿ&bRÊ&Ê6¬Ý,GbGíŽÞySúlA™[Xv +QÖÛ½EûÐ$cÂŽ"Cz«öYT…ÈT-ã ýø<¯Á'±u)|Ä’‰®vö¸‚¬Z²Î¬db¤AØ<127üFÀºRrPíùøYÕç¬ Ë"çÖsäðY_!ƒ*Q¶g-›åhD$1ž¸Ua¼A6Âq_’÷vÄÚ[O—£jnŽøÖC²¢ªpáHÐÿúÖt&Ÿ¦7+ÃéõfޱŒF뀣–‰1â׃ŸÎ‰)›ÕÚY‘­}bÓ·hÀ„Ãv¸Åóà¶üþSZ&‘Uk‡”€Ï“¿Z“OãRGöÊi„ÈÇwÏ'‡¾™ë¥aèã ×HC ;"cã)Å”ª4IJ)d)1‚L6ÂhX#=ãl `šÛz>¸ö$ÞÂz3!>Ê,dQ?^p sá ÓØ^†-JÊJ­%Ç4’ÀëÔ˜Æyb2”]Rö|zÇ5b`? Óc(ɶ3sC;·'CdïKßÄô¾ß­-×.ŒH¦%€Áç@¶¡€Pø圑JklÄ2ÞsQNíF;h†7"‡ íñ)íÙ¬–lŸE—âÉmC7WWn»é½Ùç+•3ÏÌ=¬*eSxƯ÷ìíÆ<ÆJÇÜ"›T™kw,ÇËÚ“…ÉbÈðŒ¨ Çc…£ †C ¾®²|nÓ¯OydÿO‘‰¨±ÉDUŸB÷åŸP¥w¼Â8F¦÷-Å sÖøø¬ÝOªõÈJæµÅ5¥kÊô1)gÒ±5cÇË edsã[fØ\½ÍÊóÞE»‹( <1àãvÈ 1yà)R; ’‰L³Žé÷Ó§¬QÖ¨ªÅ×nh½Žý®ãƒ×%˜L†‡1>@ 9ô ‡mÕá3Ôγœ³¬*ÇsS×ø\*F•aJâ.èØèügÔüú/™Ö¯ÆNn˰cýÆ``zïÆa%>°»µ(œ mrÛ8²Ó|­”ÈÒ$Pu´ ’°F`M„‰U›K© î@v5-˜­¨v¯púrŒ{ì·$À§½Í²ƒÑö‰A6Α žaUGÑ&U;v_9†þ©_ɱ nÿ—­Ê|G˜?¾)Íu$h"~„wMƒü.‹‘ùxŠôeHA£‹pôÕo²¡x9 @ *]ϳ%-Ó‘ °xJXu?l˜‚ Cfœèõr˜-¾[̳}¼<†˜UƒrsÔ«¥õ2§õÊ•€ ¥¤ah4Ò½*ýØgæd[£•8®¬eß$s³` μ/Žoù¾í9§É*,Û*}ÎŽ5:î:-€iù.¢Z{WhD·  ´y Cyd%æt ]÷¦ogžÀd<áœ]P½öÿÌ— Te³Z€¶¹¼Æ42>R¦o›ønEÉM‰l@G%·hzUŒ£jþ Z•2¬J–Ïç+bEýýá‹. êó¸ª#ëŸÀ'{MÇnuëŸßþ‘Ìw眧ÊZ"pw@¶7½irþa…d… ÀµxÁSiïâ8ÜËf.'ÖåW¡¬Ša(ÚÇûx19Ÿ¬:áJÚ]Ó«V²Ìõ;JÿpÓ,Y/1  *“ÑÔå˜JŽÜò‡1E+)ù\(¹¤iOJ¶{l ¾FŒË&è)”0wøù@‘ÙâÃÛ“™*F…£èXn7X ¡‘¦Uµ`RàU|ÇôJ˜nÑ_ÍàvÓËabÕ|Æ8ºÃñJEkÀ@ØÄ”­4™*œƒ&n:±Û©Šöˆ ®öƒ)冷ï85ÂxâÈ4Jüåº\Ù±(ñ9kÞŠÙ+Á9³ô}gúø²mœ*%¾¿&f¿eh0ˆ6Ù?+±5W/·ÄŽ}É·ù6Œ|[*™’s¹¿imC²4 ÂüÛ°¥ÖÐÕ4½€–ºò[£# ¦7Ç´3²ºxJ† ŒˆçƒJÍå#`ž­—?­™wX#üù'ÜØÔ>?'ý¨´zYՅڳ؊¥VÄtlžå¬¸R€X 2 €LfP¥Áˆ)•ˆg®Ô£l%ULŸÙmý´sÈ™€ ŒqÙF;òt”{GXT•·»zªJ¶-Ò)ÚÓ’]2$½‡Mo¨ÏÎÖþ™hl %a%@i+!õ Ûp‚Lh€r>µ`ø4Ì#¸™›ƒªèa%˜‰»¸—\IK‘Ü#$v0¢@)'ÄŸù{5ǘz³’é+Ù Ö¸Ræ<•à}Ä)T×›²§ø ?_W㈑N™ œIÝC¶+䀪ÐÛ¶¡L¦é"·ï<¬—¯ÑGZˆ) z¥å˜ aJXèÚ‰2¼ïžÒ+f5[íÝIëíŒ Ó„«¾#`Lä°ìÈJh—1€ “5®jpS¼Œ_¸É”jqÔbF2<\{iš˜ƒêíøõSß1Ù}ù$Ónt—)ýÔ Œ®îÂAÔh÷«›Äs;˜L©µe‚z¹¿º:t·÷|u:²PÚmCcƒJUYëM9MÛÈx¯+†[ã”0ñ4Œ}d7ÁDRv‡d‘dVÁ:]‡¬‹? ÏЈ®Ùn•ì ==@#MÓ&œÓÈ5²ª[¯êˆïMT ÎÉðŽïÏfU¯åù˜Ó…#¬EîÑì™X‰ ‰íFÖ±¬h1¸Fßp½Ï•™$nPç¶¡ªm^&ÐUUŽ"‰E¥íP•LÕª2FÆ´‰é]!MǪSý!Šñ™ÐcÌuGsy:F’ÁdŽ}ÈZY൴0¦MÖHt$`õVÛa©j$CX4«)1p‹ýxÕɲmh»aXù´CJdÁJ;¼{ÅÔò–ÛG&è"M™Ì±wHSFæŸ8‹µŒÜëaØnÞr]»ïº0ªí÷nŽ¢®rkp¦‘«]HàëÑûëBÊx-ôŽÛ¤*^»ÍUÍÄ$k·xíïJÈø~0a]]--»¦Œk.¦íæ(†•òL«2ŸÕµ|~÷)»°I ÅDÜ™ 'ki™Lp¯7 EÔâΫjÁkqU¹_mH€¦ueØMä~€)+QòÄ3‘™`ZÒ&“a`]‰‘¢é@»™Ò¸x¸¹<3Ï_&=´£vGzùÌý‡ªÞ~³Ô(ã9wÔÒ×®Þ²–Üd¯á¨EÉ- ÕØ51í<«ñîFÆGI{ªv†ñhD¸ sÐëØ;Ó0±­#%þØÝ6¹)€,ì¶ß’™çPWWã ïˆñ@%æ@ïÖæ²Y»¹œbäæ&‹Ñ¾))™«vÔu.ð|¦>…îE™˜!±.Y©q[µvš–˜Ãø¤Fí ÂÛ0gGo¨”¬Ñd"}k8¶^ ”[OÉnïb÷Å€¥œ§‰¬èå[üõD€÷cè"@Ǧ4S“p£ibZÙ8k4«¡“éñ•´tG£Ä™&«v˜a½4c`$ÿ6)#Eþr]¬ r5âü3ÁÔÕ,úø¾Ä"·^ƽˆ1‘° Ï¡KÕhUÊŽò~äñ¬ä×ÒñÞà|ý`-Žp{Χ.Y H ³²ð痋ˤ+×@וگ6Ç.϶¢·kÀÚñ°e2 M²ºLIÓWA‰ž8~»:Ò ËT¢Œ|^|ã8«Âºð޲£À‹Äx-ŽþÁûºW%{é(÷ŽºØ: |Gþ€£ÿu9žÀà¡ðºe»µx„Ú;ÊVB’åTr¤TupŒ¼'j:¦ 3¨éJFÉJÚÛŸ›,rÈÜÄþ1™ ^Æ÷—&Ÿoʵ¨Z£mÓ+½ŸN7â ð–!­GÜz» J%kh·O Æ,AŒ'Ã01,÷uÍŒ¡¨Ê6¼_mZbØÂôö!n9'èhbA#ŒÃg%óÁtÔU íFF»WïÉ'%VÚ|½x†)Ç4‘ælðý5GÓˆZ>³ïËäÖ,U¥²Þa ×@Vݸ4¥À8`ÿ 5ø}Ö˜v@Nf–ÆJéá>Žø$sà>ß¾ÂVÄÈÞM6#¾(eCñ0¦·j³Z`2ž½¡–vhw$£÷§#òý ›ž ÉjÔÂP¦'0š ç–×ë¹)™4‚x‡¦´-gôÒ,9Ï _¯öÄLº³ª+7>ªÝÈ ‰áƒÉy9¦{1œ Á4H8Ÿ@WÓÕ˜øMÙ2à •ÛAæÐ¸Èx¤ÞžFÂg8%`í½pÇ<{zåâèÓÇ#¿VFˆî+ kˆ†µÈd B†[›yÛñ†Ò¨:"aY0÷×Ç;ç$/)·¶‰ôªÂ |ãjìµ3LÖö™àYðlg ÃV­ÊPIX&ÆG¶‰0^É,q|ÿû_¿QÏÿå#ÇùÖ@Ç–…#A wÍY‹Ÿ®Ž§á’Ž]ÉO)±Æ>‰îÓˆl9 G¸p¤é ;ZΡ)˜¬dËðx݇£Á7ÃÙQ†û•Âñ˜ö1¨…/Fç‰l.F¤¼‰•|6dyfe´ª–BàY¯öl1[2F;¦¬ª /FêU­”›*F“åI¦*ð}a¼…“Qê•“)á3‰Ç¤ ÈBIfò£„מ @4]•sÌ›­§ÅÓ١阎d¹õ?”‚sY›áa±­rK)7èv[Óª²–&&ƒóL€dÃäÇtbíÖ®”OYK÷’=Eªiw\lž€¡#“‚sÑž_ú<†³.|J#k™çÜ Yi¤L ¯Ý½òI [¯.æyØ+õ‹ó6¦ÇXÕ”ñ”< ²»ÂI˜Jøqñ™1ñÛØ q2Ræ#:ròœžC =AG2¯w†J&î˜ ~Êdí ×Qg‹Ñ2¾cû)‰¦haÒâwÈYv#™XVŸ?¢ØÝ>×;6߯ZFzr‰‡1ºlVi2L<àèãl‰žØ8Gѵ›žÉ˜|ÒäÖ\LJ¶€5¶•£j/ÎǬ½~¶¯mX‰•\4VM€4þ`{ß 4 ˜ç¿£’Íëe¸7!ÛfÒ¸ðŽ–7Qö†µØ[bY8šröø~'za?µÈ­ñjìk‰Ý2úõѽîÏ#œáª^×”-ÓÄÞzdÛ ¦Ù,ಠ-–mzSfB/j”SÆ8Ê|VbÛË+ Vüé;Âe-]„€ƒ¼7!†k'£'¨ ™@Yqß)yæPU‹Èvر ko´.ÑÄzUw‘Z8ôC—§L©  þxm~ý *‰öo ‚‘‚F»ã~­—¾LP®Ä‡RªžN FZ•¸ k‡sp$ˆl®,4Ê4UáÌ1ã}v|ús¨«äH2˜Rf"úX“1ì íƒäßLä2%¬Ê™¡`ÎPæ‰ßˆÓù|aU2O¼æ(®ühràÆ–ÌˆÈ]$€é•2s‚:¤æ¥¬MÔ£¡%Ê&ݦóRuÊôÖ>ÐG`K»m-29™/V¿›Ö¥&}WVªIÿ§í#ðm«=ÜÝ[¯­Ü%0’X/½•tå†Louám¢—¸*ÆQTjtíHVéŽu9¦ô‹Ó Ô%«"-U‘ Hã˜,«ª ©ºQ@K7âû€šB#š °JÖú[ÿüÌÃUã{|¸`b(^™¸é-6 é‘56®ö–¡OÌG5¸%û5—>Awµ¦sÓ[ðñâ 0W%k@ƒJùÀl/w”²à ;êUC =ÌDæ6Öe:†³Üˆ×ªvJ#º8æL½AiúF¼ÐÕÂF7l\Ë`”„.x#ˆ‘{">)(ù)†ãû›8Ϧ4Ž&«Zh,'¦lu+‡T-cTµ3µ8úì¶­rKF»€oßIŽefi}|ù(•åLð=ÚH&ªÖå¸Mˆ•ÒpÈD/@Ö§¶Y‘izmÚ¹½S¶L›8ªê¢ä,æ WýíÏ?ÿì@§|T7r¯¹Ìô[\i™s-Ì äv“i§­!Ës€³âF cäz÷ȦÄkï›às3Âôþ…™pä Ê`Ò)k¡Ù>xšJrû(߯Öq¿Wn«ÖÛ&J&jdgxîJòª Ub’›Þ’ÁEU9Ÿv†ÅHz±¹k¤‰Ïœ¾Äõø|UðñZr˜a÷"ØO}ÌÄó?{ÜM8xj9[$Pnt½H §ë³sœù4˜d|ëèû>ðoIü‹›Ón-ÉäîËŸLnn†ŽíFŽGêrsU…’lP¶õÒ8¶F ã8iPbz¡šG¸öJ}“Ûíü?£×YÏ>[Ú‡£\j¹W8?êÄ2R6@$ŽQµ«pÄOP»œ' êW¿é9Ðç¬WIdñ™#°®ª[`ŒÅúÆ!²h[¼À°Rm ¥ϼÑ1ޑމ1®Ð-¦q‹aíª™Ï™@FvS$·Þ¿U]9 ðã‚ô˜|2l &‘rXîõøüᨚU&µp®$óQbñd4¢.nùxOÀP……Kõΰ¿›;lëjÛ| &2ekÀz‰åJ%&´dk¡¯=}ùÊÒds£,ö&Žbs‰…)r·SJ,Sâç¨bâá¾*¶*“ÀÚÓ¯7Ã2âÚ‡3o¥ÆÉÚk‰wlÊÜRn¨c»yJS± @seØ-poBßi`@íë ËŽR/ÐDzß+YÐô[[©F MTk¬Dé.‘rU%ÇÆ½]ÈF´LÇr½ªŽðÂèĘo~ï`®)xÕ@£;²*tµd£Dœ­*€ ȹ‘€hJq.Œ’9ÞêéÔü×IJ=±—}ÿum{ãÛ@{}nÑ5Òà1’˜¦¡ Ê– Ÿ¬ûƒQ/xs ‰×’?M2ǾŽíp+Ÿo|í)ånÁÊk$k½îÒÛŠm³ª–³ÂoϬØî"ÙràY£j]]D =°›@•¾= ’1ÁÈ"f%€ß-œ8M|CûÀHJV°ÞJŽ?bãÆë¥÷·lÙ[‘!1îÇ?’fU‚¦#a< QÀýœ3⎀cãê­1½9“Á)󴣫á1{ó6Ÿƒ*™Ì™F5Ï…#ÐnpJÀˆHÉ*óæ& 1E»ßîÛŸ‘d4œkq4Žy˜<³úw/­O\/27]³ðÜdâZäÞ‡–ݨédm…Á¯+™®™Ï-cÑqÎÈ®‰l·.HŒ4«=¯ä3TÃ!o–¿mŒ¬ç”÷‰³u—6ÇgÐÂ_©ÞÈÚ›²A@¿-Y‘9   6E xâùô†ªyª*‘¹ukà1 Fv#bUÑ’Û“&6–ßý?ôQ° ¨Æ¨ýRg*7†LÜqŸo[²vŠ—›Úø™§”÷”ÊZ| ¾ñþìi„ì(›n¥.À ðSZ<ç [Ù±õ¨ï§˜¡œè« š@æo72˜¡)@wÑ¥$ã (áZÊmÒ¾®ÓË4”ÈÓtž¢ë(áa¹_°Ý9ÅG2imG%G.Û ÃSzåÖc¼v|ƒzn¤$tµ¿®yf¨š¡‰½IGÿ×<éñØ;88âµÏI/*MÃ<œ¾òÏïôÖÐÕŽ^/2=,ªê„5äÞ¤máž=Í]äóÉòQÅïãÐË3åÌ۪ƪ²¨·Y™ÀøôŒcbû3D;à+9ÆË˜ »”2q hÆÃ”}úÅ~su¯Ä•tí}0Û-28Јœ™X@ÂÚ“×1N ä€'–›RÕ @›˜¥…­ H£™Fi]s@ú üx)s£Ì'dG Ð•[k” RÕþþZ×Èœ@n“˜­Z)ÿÖ€³R d›¦Œ!†=—c zEÕdpüùÿ˜¯r€B³ñ€p ¸ß¡ X‹ºÞ–Hî“Áz›šŽiƒ”ž *ñéØP¸_÷x] Úá>QŸÆÂõæìH”Eäuú¼Nƒª2QÒ^Wæ0~™²ÑíЯ˜µä\;Lì È‘À}“”(µt‘÷:ÄJûÎÙ­ÍÉ´Ô˜ML]•ä½ 0ZDËÄWbÛkÐ0TêwbO¡ezéL¯ËošþkX%Œ F¶ØëkL£n%Œ’v—eÔ^u²Ž×EYU~[xöÙ… ËJå)Û“ln‰c—8Ì_‹ly<çö¹C>ïFÙ;sƒ[,qþñm»‰}(d…®d¾Ÿ2=Æb€–l%4¾iò‘µË+!ᘔY5%ž #ÍJïØíÒ#­— Þ‘&[LúG¯~Sz„=r> …)ã{ z£D&óð°€°M«6Ƹš0"±Ü8@£LF á4MÁŸy÷§,À?A-HVÉÆ7(²Ì¹qŽdçg¬a[‚‹‚cWrÖþ¦æg¸+©¾¡ÊAnÀJ&r¡šgß–‘ñïbÊÜLÇûD«ÊJŽ}N™3©iá¶ô­Á Þ Jw tÁ ›žžÉÁC»HÇ&jDÂUõµ(µF&í¹}ÇÐër¯ybVõ#ÇJ´MŸ¦åeÌn€IzÆ ²…¹JY0™/"É´ôA`μïïÊY²êÿÒØÅ‰ñ«Þ>¿Çñ¸£>FêJ è²~‘§,ZXV çé¸'…‘Ä•ÈÚÍ}»2¥*™…[&%²#‰1b³€Ò8ªe¥§çvL±GÑ‘#w£øµc›UK¸O32ÛN¬kJ˜Õž+ÃbÓ)¹ùæ“'eb‚ôÝè½BzÕ•à¦È€ÑždÌaäWøë»ª”X‰’Œƒìú—Ž ê)è>[ è÷Lx¡ä&ú¦ÈðŽ›¤ÔËéóT¯„‘Ä 0Æe‚OÖÑ× îªÓ#…ã6QHŒÞ¾Ÿ˜®óù¯­Ô®ìó}m0ÆÏCF:ýkG¥ÖÕ/féÑ›72Ïdw ,ˆsèX×x°{ëbB“ Þ¦4Ÿ3²Ÿy½ßÑzŽ=AnræýK§yj1ˆž =YÕrk1L WµªÑVx #™aŽÄh·dd½áÑ ™$~­0”² x×À4YµAÈöÔØb9ã+Ñ‹H-z[ÆH]e8%^hOìO,½µ«ö!zÕd)á>V2XÜŽs)-r`¤£FA©±Ï¨^o´ÒÙæûC«Å2ª½¡*–a-€jzÇöáÀlJŽÍRÓà ¿MÞúù{e¥EÊFä#·R%G-ªdÅ™@µ£hº,ƒlÃdZ4+ P dV$qG@hçFßÎ÷\£c²Ý®öYé¢ÑH/Â2“J…ÆG<̄۶u„ ¦c¶¼jJ½#°ÇlŠœ!ð:lVÓÙ´ö#ß;n“dÓðÛ”42¾U'Æ›%c'ð‘r›ˆLøÃJ™—oýÙh>ç·jçðý‹0Ì¥c¦ýnrÛdªº²†w|JSÉD¿»v‹f«DÖ6Lj¯+AbíFÇÈŽ™Û°ý×ëŽ×¾‡ÈÊ?pÐÞh¸¿&Ðà{Y¼ á#ײWRÊS©}´xJ¸M¶ùVÒkl b¼ÿÓVßW$pÌ#’F4½YG¶ªÄn¢˜AV¹ÉÃUy"åZà^ƒ€ÿ«Y/AðbmgU‹v†pƒºéad³6½^£äyÉÒw}G|½ëŠvn"FKkd² &ˆ¤1ã"ñåÄpÁÍVÅœ-CV ¦tø0?öÑ‹Ù]`$°¡À–ÏJU$ËÁD#‰áޝžFøÊébÞ‰0¾v½9`ÒÀø€‰Ä‰öœ¦£Ü2dý˜È Ç®ÖH-”;ª¶¿ÌYÐÔT%î“Õ«DãÏŒ™Ôˆ袧نUšy:âyâaWÌ¡ÆôvP™ðÇÝ2H›Pv”•܈É·sŒU1°Ðu¾Ð¹8Ã]¯UÌ0•£ª6Ç,0”ÉdªÙõ²Â ÀÉèãkD6Z§|1«¾ z ¢dñzZ£â½£\£?Ej‘»#@l‡®& ¤¬ _Iv¬/“u¯ÓóýŠtACUi¬j &L#6™€öç½È¦ÄXØ×EÃG#ÀMWž•jŸIÝ(7½@+É‘~†Ä6o gU¥Ì‰Ã޶"“xÊE tÔ•>cû86Œ Ua¤À1qD†e½+µjí­Ô -ui¤}"‘Ž|à<=#ÆQ¯[·€@nr$lœF‚>¾È2²9™y+­¤Wô°¾¢x2´‰jŒq˜ÈÚ1ÌU¡cV½ò“6LfdµðÇh)#UkD $“ÙÖªø4HGUŽŽ.få˜ùFìh4Y[5è]&çržé[ߤ0ZFʬ|(G‹é…½¾qH2>‰3¬TW-&½Üe«rPª&†kÿ¶þÏoíñ5fÛ¿…Ž©Ú—¹=1}”@ÎëU¥&£éÓ9Îô:€XO.=¬¤? [T&FÊÄÜr•hÆ_û3¸–yöv¢!È9}™Œm_2¿ý#9ˆZ²^ÑÝ”òœFoÊÖÀÝ>ü•Þé¹Éd‚UÕŽ°RûËHsåL*Éù'#0ÅÇÆêlùýg‹ åþL" {7gâØ¿‚Óe41ÏvP2èúÀ5UGnmÊ—wÌAËL²• 5Å2+JÙG|É2‘žÃL6ˆ¡.|ûS˜Ue¼,”ú¸M‰éR™ÀæÂ€hÂrkd¢ÔæU•&~j§´OKæC߆ÖÀÔIì(ð›®$cêšÆPV·ïóô&ÖÕ¿;òKJ;e&¹ÉÇúûMSvÓ†‘Æ9f‹q,~¼¹«]˳°Rš<ᵫöȦAJ>&GÁŠ#;j—É´„ñ¶z÷Ñ¢„á/×ÛJxúï(‹d²à¯Qîi˜>ÏLÉd2“|ݨ ßZ8Ÿ@í)µkü±!·øFÜ5χåÓÄh̯Wd娋 ÏІÒqb2-•üÆÀ¤G† ²"V}ùŽÍ…?ßB ”,\ÞÒ왑”]SõlŒT kÇÔà†¤%Ј3«¾ ëÅ·ã´ð‘ 2Ìf3Dûk¡WòÑã™§äOÙÏ^¤.%O&Ž­älhGÀ­Ý>e 7-ù¯%O%@µ#`±4SQÐ|þŸ‚à‹’©õÔ†Þ%0îм¸ÚóvÅfä@‰çI ”—!èè…2gÓkÖÒŒ# ­\äàæÙ¦<ËÝõh8ˆ ËŽÚY—¯ÇyqGæŽÉG$“4ß.| íÆEjÌœ ‡HÙ2dé×…‡•2$‘óq}Œ³ªM±9fo¢ÎydÛ*mmÎÂQoþ ª¥A¯FïÛ®Eu³§ä“€Un1”ªdÝ" ¿AÓn‘”x9ì”üհϨ®œñ);*ñ„?Ÿ(ʹ\ͱñ}xJÔï†À½”®Ú·M†/?O-Ä jcÇȆ²5K 3ZÀ]£Ñµ‡9ûÕ>xÀq#ôN¦Ô Œ®ÄøEbGJkÈÛÜøþaé/2zÛP¦TM,ëÍpgD¤‡‹záYÍ Éª¿ûO@Ƴ‹7H©”¬úîÓ= %s]½ª# îa"r&†ó'ëÈY Ruwh |²¦ U…––Ç´ €d«j ÿÄ£Ñ1ë­º)ZȘ6iÕ¬’©rÀ8Ê}+|¥‘MáN^6QÞßÊõ dκz‡|ð‚›ªR‹×?QÁi¦è󰹓áù4w$Ïžšh &“5¶[¶”øa¥ŽcÎw–^‘Þ½yâif÷˜‘u©:¶¦Í}ñM hDbèMÙHÇøÚÔH˜a+UbåÃʪ)r[b䦴@úf)™‚/ÚGãª.˜'M¸ˆaïØ L]4UÇWjã²oÌu=i³Ìµ’ã”k¸ %2]iˆádÇëû½‰©KîÓTáéíKL ^$îƒQ¢i‡n‡qÜ&@¸Mh¬Çª%Œœ%Gì"u92W2šÞÑhÇ>Ę(Õ"7—, W:7¹#¸U妷1ݦ¬Ó4%}VuÕH&´À&—øü ‘Þ8wø¹ ÙÌùÄ#3hž¿àPZ’3^vèu9¬*a´`j —L”ò2ŒÉ–JUìÁñÌÙòW%† 0¥TûVã3Ù&˜dµ—9äÓÚHGJã«'™e02½`˜ *w¬—¾é2$Ü,€?²\uŒ™äPo›û”[U s¤ÀtÔ蘧jËÛ ÙþøWOSï p2›LâÛ‰#[ÀJ4Žd@ûlüz»Z½xš²šµ)»~2ʾá‰L‰„_“9ãECëRªºüòÝâJÎ ʼcVÄÑñÍç7©@Uo¶#£” £Ü‚ G½sóQÙ& ²·~46¨]‰ãõ̶.ãt %ãDn :æF¤§ÑÒ>q‹Áiv¤ñ‘õšnDbX\íçûÝ8#>&LÐ5y¦„ÙôH¡ÚÇAà¨Wö8œáH àSFjײ•0ÿú׿(|SüŠ$ë:xÁA ɾݴ«b  ³=ÓkQ•ñ•ÖKð#RŽtd®# 2ÞVJ‚[†È·Þty1ÌZ`zagíadþáb%2&ý¶åÓGm]ôk'nmÇ~“’aŒµ7+ç°‰ÄÛLKw„·OnxdúpŸ’CKjk̯E82W À…ýé3ĨƄ÷ Î,ß>uµ31F¯áט¡ªÆV‚Å“•ñ€–”°•ÚS†k$HI0aÊnQ¯}€–­—­,ðÄ׿×~7bb.Æ"|"˜0YÿGøÇëjzó³â}p‚ðù^&2 ˆ•yù—@ß9%mŸ²–^¶ûhJÄduåY©í{;]dï]R#%7Ô¨…¾oáÞ´ßãz³BºÊÜD k*…ª–²’ÙÐ8 ÞÞÎ3U€ pT•1É|ú~ç¶Yº”ÖÞ8fUjJŸJŒRƒ(EdÎ[†¦Ñiä¬Z2î[&üZ5®ÎJEúh¨ÒÌíà.>Ù4•» `–L¯—’^´$fÛæìX Ÿ eµ‡sËäš}þLÊMUoÕFãExÕ0>=gà-ïâ0e?Y”HG_Àd¦Dfóe¥”5*õV-`t펽3p–øþ>ÑKÌ„gI/”xâYõJ˜H&øk$pÖ+ˆÙ6º›"!WÕ{¦~ÿèª]‹ÆvÈÓ\¼×ó[¨'jh›0ia­ÊœI†!ûí÷ßÏH­æYkCÊtr;E¦iw +h"s‡í' ¡Y)åºZË1YËt+#2Dv«µ åVÒ;ÿpGXdŽe-rÀ{˜í­½^ËôMUmm-ýKk«}¢JÄzá–ϰ›–•^ØD WÒγѪH¸jÁÐ`T7 ðmè AV;È_Þn\ÁQô9ö§>1¾ÞÌË|€Yi×èø2°éJ®Ù«Òteexž°®‘4²¹Óì˜,·¾4FxgdÕžËÑb@Tz—1)#åvÐkVž1zù$¸N¿ØHÊ¢^i%]-I9œÛl;Ö ·j†p?ƒ-阹£èÖüÖæ°YºÌ¥l–,ðr†”ŽÂQl˜FµöRæxÓ „ÅÀJÃĘ¦à›Žì+„=i/Öh-4J²[zVÒëc*Ñ4ºÞ2åùŸRÐ ¬ØpŸY“šÍ7¯”õ6‰CšH?í­îÓ¢ÄòÌø^`K×(3Ù®‰ýÅmS4"÷:ŽöQEÖXÆœß_OŽ19§ÑhœPʰõZµœ ½€d°vٿ͸Þg“ S:2þY,fK¶³^ûUL˰à&Ïp¬Ë&ªmÕt±ÅôË— ®%«¦ÄcA+åÓƒäŸ`ÎŽá@½=W×4(í0[ÑÄÄ2FFöÚU‘×Û±Þ.h+J/ÚÀg ÈPµXÏÜ‹®€Ñä9²RËðÙGYLÜEú€ˆuÉ¢^€@4eÊøzá]„àôÜß ›¥‘@—Mࢪ\ >¿³rA¥Ârß31”qn@½21r»)Q†&[s‘-L“£Dé·?óYbJ±ÆöÑBI#«îȇRVjºLS^I g÷ª@žÈÜj$ÆÀñ•d³„+àù¤¬ŽIFï(ª3lŠ?RÖØÂdU×h”-“›ë8â-6p¦Þˆ‘û“¯kªËœ“u©n4Þ‡ÎDoG@´`ôp+‘!{çi0}1ÈL4]¯ïW‘¬^9+-HL-;$¾g>b<çLòQòá铬#,h˜¸o]La€^´ª–~éªôzi`ã‰íiT…v<Ír†Ž™héµkoaX¯,’”|⛂ì+—Îd§íà…ÝÈFôëbžfu‘x-W~~âfKf<2ŸJwÂI•2©D騔/gi`%yÎ)ß*ÌÊ\·°¹à6O@lœ#Ïz·Cʆt œw©-¯ÖUËbÏM&ꔓ¡÷޶TBê:êï%Ó·¼§„w$&°:ÀÍJJ~û;z;Ë(ahäœùÀM¯—@¬ÈRZ‰Ñ"wAÈ$1ÌŠIG-ŽHgBËzC<ÆÿæO6T¶˜.Ø$˜X8ö¼º2gE¼¹HÌ®¦$0]‡LÄ ËH³„eq»ÿ'Õ^µ=•÷9;ºEÊšÍÂà‘@Ñ£J†ôÚ•™ã G1Ä."·€<X‰>à"¾þU[Ê®¯ÊÊ]=¦jnùÔÓ+c6 §ÉJ/MáÜ’øº–Ôa]Žtñu5 °'eC YY ÿdÇÄpæª{XXu™3M2<`yÕ‚•F¶•äS]J…c¯ªQðQÅô£­i·Ökçú¬Z©5`]ô&¶0ü–èïÀó€¢e¡—müÚ‘Œ@d’2FÖŤª^S^çt$HT•ÙʬÞ‘[Sà‚ <ÙºØ:VJCÏÙ ðå>?³­áÑú}¨”-ðÏ-³òɹÃd6'ûõ/1Rä['EÑ$äŽô®ä6ûTò•ˆsh˜ä WÅôK°§Ñ¥D™'ì™¬ÚÆJ07SÝQµÅðôŽª˜¢(ñd€¨—a²ü‰ë5”xU ‰zaVyÊŽrâÚÙvG> Å‹;ùü¡í ]dy6—²}(1ÊøU…ön§—·CKbÞ¨åvŸÏ½é™© ÕG»EÊYµ‰c³fÒÇ©:ž!œgV|Èøtl¢#ÐrеêšÏ¬tÁªù8¶ŒÅnñš6¤Ï³j¿ìÈ4"C-ôÇýû5P¢éjz]a·à·€R½é9ìÿX¤)uå°ÑZðŽx_˜ ûR) å~@IDATµCæó¥¬ËÎ4|2ÉáÇ‘¬–)㋪p¶Ë-ïÜícDü2 ªà°è£©ŠL¿wø¸£Ð+ïM”vÓ£ø6 T…ûd<6N•½cS"Û$·ùP*1AxG‘R—Ü<9±Rsí€w̰̙’Õ;7,‹™ßG¦‘!7I çܱ.²È>îÛE0…^n21Æ2úŒðôJøOÃý¼ÿ<¾ßO +u%hÛª°«<éÓ\ËÏ_‚Õˆë†FĹ9*½U¥Ú•Œþü—Àݶžš•ÝÖß8dU¥r3RÊÍ«dŒgެý=¥I>Ê3ìþ¯ÊDÔ%“…[Tnº gBÏÓ&Ž}º@]ÙÒ`ÚJ† m:¼)JöI0IL); -üÅ–Çûöp¸õÓߪï&JŽ€†æ,§d¢QîXÎP{2¯QWUG%]H@à·Œ¯å}Óßß™¬èÑÒpÈPæß1ç­ª£ 4 à¼ÝÞF%Vº^C׋·d2˜O#º +ÕšdHÑ U“5eãTµÈ­§Ú7³ö-–Õµ?R5–yÊ"™ÌSæ)T™héªZ)£Æd€Ÿ5úZ•Ò´‰Ö.Ãs€ ŒP5±Uez†Û2‡leÁœÐÞË“µ†’^_Vý{í ¤Ïìîªz[WûìæØuhðŽ}R Å¨ÂøvE< ¤qŒ_Jée¡”ƒÍÇ–QJ 0oúi¸¼ÆÆ»“n à³Z ÂlÕ°,´&Ü¡¥4íŽdkÛA`zX M;L™ÆQ)ÁuLÚY )7E5þóç*…@¬-ÆfPc4À)e%$ ¬¥·åh'е-íÚßIh܆æé(T¹±•g’@Ì â™ÃÈþ„0Åz˜ô û÷Q‘Ì•ð˜nÇÓW©¼›.2ü^,ÍÕØ&†œR†1”VíÓB¶m| 4Q AJxgµRœõrh¢ÞŽ}ÐŽÉŽé÷W ¥*¾Ñ@Ó™ÐȆÊÍêsÜ[ÓV½!ÜtÏ›y;èªo rþ1HŒLö¶˜’OíílÛH¹v`wÌgǶ"Ë6žÆq&Hw”•y½Ž®ÙP9À_‹ÅÚ¼¬ Oï¨Zv4—›F¸?(;d²¿Wëço0}Ÿ1ºrÞC™ ÷ûQ‰À‘2«Z6=’¦P­ÅÑbªng:ÀDɪ–ï=óĨқ«D†I);*aäª+iÏAIÀ‰ &¯``d}Ë`rëÙPV5:>FÆÈ¢F z$@“g™ /ÓoOoDë9 8±’€ÝH†)íï8=^ôæ^•²»w žf)9ÊpÊ;íöWñøLƒÿíßÿþ·ÿPÀn»†ÖïsàFUÌc¼v®TÆò€ã®§17yU:j§qLéáà:¾Ÿ¸¯‹v‚†Ö•¬ç)(‘”‰1@·À˜³÷ &-HU\ÌÌ“ÕBÙnôµ$Ƨ'+tMi:gA£*7En蚀1ÐXv줤O™†FdbCæ …q0MÁ8²ê·8 ÷W€Ü\2ô1€èÃâ ˆ~Oa—m†åú ¶6{%ØM‰•d£Ñõ'$ ,(1ÉZš¨*•k±%1+%á(ëÕNY 9^/’mƒÚ!Y¥Úa%¸Þę̪¶"Fú憩7 ½g'È9ånh$+|X—£p”óLÜÎ2Ãüᑦ–pa ³²-q²”ßîóŸxÐEË‘í¯8œXUc³€¾BH ‹JZ0²ÈЕD€[#“FP&‰ÀsÈPKGƒOXF†õö8J4ø© U9f8™^<Ò1À±¡•ΣwÄæ1…Ï„»Y_£óB߆x-×Õ›*å~š¿w tU?íiZz=A½E둥ܒ†ö.ÆŽ¬Ú,Yc]<É_®ŠÜ -F'Îjƒr“ée¼öÀ4#”ó§,ðMÑ‚qÌI,ŸÎïwTi;Àb&›KŒ¬¤}‚~½ú‹‰à|]²£é@›(ï>„Tõ˜vÛ¥d²ÈÍ nÑå#&s#†¶Ééü:·¡v̶íjºõÑ>JYå²Þp÷’[ȤöWɧ‘ôz>uÙ Ö8·49ïF;Ö›Û©21ˆì((Õh`žM?¢+“#ñÂ1ƒ’—iÇÓöý]ƒ‡k7]#¦\Ëëá¬KNÜ#˜Âö£rî¨WU˦ÔΡÄ]Ÿ²oK%U¼ ß;4—r;À4rÿ BP`ZC†‘í ï¨Ô#RòÙbºðmìt©FhQµ¼Ü2ï\bLAó#¼˜.ÕæVm·®©])f¶½Lû—h´ȶ?€Ç´L)2—ÛÐ>çGNEÏáhÆ%éðŽ¢ÇH \üõ×_Úý"ðUˆ×BÜNµÏ  l(cCÛ•Ð3Ï'Mãp<+b½»¶j/¾e”22†CV98¾‹õœk9Sïzež¹¥\/ÕöÑhgs^üþÙÀ ¸~Ÿ/èµü$]Je±Üˆ6‰Ä;ŠžÅ2†n}²=&@€×TÕˆ|21™KÁ{·È͸™Ø™2 èåÙE˜ Õ [OU»e¼€ÉôÊŽ|”ÄzÃJÌ xw¯‹¦5EWÞû¡šF/Á×éó‹£%• ˆ”ÁyÖË'f|ØÜÞ™Rh#¥½!+Ѹ”Z0½ÙiLЪ²c½]³Ú?å Õ~Üà»×g7ÿazÊ–äéªý?íp¼lJŒ¬]ñJ9ôE’÷€i2Á÷9žUnÀ"YwgÕQnþ´Ž‚ØQnbGË‚¬™EìˆÄÜ}fkWÍ„ gÕ×–Þq[5·)w÷Ï—ªÝ(}(¸ù Ьýц<»#`l2Vé(ˆ‘ª¦pvx ¾Ç'®Q>?±þƒÈ÷@Ö¦\À:êf¤.d“"}¢Øæ,rGbxÚƒ p¤ä“¦½‰Ã]Œ }»É¢5jï“kmæ-–€^vlt>2¦)@V{ý®o|2ÏÇtG¡IÖ’1‘1ÍeÕ8%2ž‰F9&si&«Éû¿.ÖÒ§ÛG<̦O!&’ žƒ#~žbr ¨$·°R¤Fd1¥ŸƒÈHûô0hO +1yC5¾l{OŒãlá¦Jpn0ÒP™CœÆ§lw1Ž¡R-ôpÎÙ’iñ’- ¥EúøJÆuëw½¦,S’eΪ¹ûÂ÷xúJ-ÿ.‰ÙÐ}µÀ”m…lâ1Â1Yß Lsñ»u «8ÒôWs•únÄcš’ú°,ì¶LÜ·¢ýaúmuå'µƒ §ŒësÄólçöïx:otì¦pš–lŒ46 XžL•¥£ –U1|ˆ½C› õ&h%ÀAãnÉ'M¹C¯#“üe䀯“þÖ`²¶u¬¥AŽ]°Y¿ýç?ÿÙ¢¯m6;÷ Vg” ž^ø/¬Òà zü&µF¤ÑÂîOßQ]ÞãÈÂQUŒïÈ!OÇÜÊŽuÕx=Î[7]ÕE”½*Þ 0B‰&Û-€Ìj M>²`•æ] ãüOþ z64QI‹‰@néØ>Zêr È’Ú}Ùϧ)LRÒˆ¦°U¢QB–@:j¾vX‹\—ƺ0™‚¾‰°F%#‹ #a¥öùó¬Ô›è((}:¾°ÆÄ}IÖ¥æ“9| Λ·@ëÁb¨]W#¤v²‰sÈSûÌóé«{sdkðLŒ$plºcúÃÐÑP×4Ýz4ÛªéYá=Î µ4znÉ UeÑñ™Ëø1)+-êÂ÷ ˜> Œ¹µ÷g‰y§ÃgðÝÁÎ@-”Bõ9SaÕø˜Ú‘@‚1”¢ÅdÕ"±R@n–j²Ù‘f¥ãvÿ:‚4f¨Ë1ýHÇù×»®4™ëíc¢”ð°8Ãî¸ÀÜdÒSW"‹”[ÉE¬´ˆùàÄÀ4çÿ5ÐDY8ú¶õátc ö4À§ÿ«Š©WµßæûÖ4› ý0&ú´¨/ gƒÈšg[a5V5ÏPŽŸ ¦Æ< ´'ÍX´&—þõSŠá™­’ ÂÖõÖÈÜQX½*Œ—ÑòMo¨c³ä‚p¼î#Df‚Iß¶Wrö¡ÁWjl–hÛ> Žº€l嬖3YÕ1Ødá”2’'™È°ã<”–ɰìXïº%±VްÂ);½†Mh2¿{ŸCŒg‰g…ÏPo#Ê{%ÊdÀ kÙ”ææ ·ŒL/Ñå;Ï(·[íÉü(! jŒL~QÚZ.sÈÓ­c….½ko [½¾$”Jº²ªÜn@Î4ªéë}Ű`˜ ¬Kï?C ÉøôÜc#b`@”‘n‘Ø6e¥ñ€j_{¿|Z¸`]YÉŽk¸µObJÿìe8ï§©qrÝ7çÚóq…^Ìq @©Ä¤¿Tr44ÿîëHËp]‰›Eœ[¹^Xè:­H1#Gdc˜¾¾°ßÔéa .`çAsãÛ쎽 ¥‡¨+Þï#Œ.‚»ØÙ¬R¶²‰²¨åÕ3ì8·”媭aðö'j³8LZô@‹µÛö¡Ñ® ӷʽ`-Jø-9“ª•¸1ß_ĹUÅcä?󖡉Ý"Ç;ªjdU{Îñ#Óˆ&³ÆÜjÓ(…Ót¤éWjËpv_nŽBW1µÌP)£tµç? J‘|xʘõÞßèpG%þô­ÑÚJ4íP&‹T‘í°)@L#^7æ­š9‡4‘y6Ž›jûÃ-¬Äʵ¼%»,Ý…-M;ãE>z™LˆÜibLAÒhŒñÂÈlÀ£ï&™ƒµ£aúÂà™­# ¦‰Z`L³vͪõ*¢F 7#¬ÄÄPÅøy‡gH UfR¯HÃ-CI/îÌÏß<®ê¬Á¿¹cÖeP[TeÂÀtµp‚$ÈS—ñoüñ‡C¾I{ ¹ýfŠñu®T//AÀ¨Ê 0•F´eƒÚR.Ò´q-LzÊ s&æ‰ð•8Çõªþ°j“í`œ‹l7æ]2>+X´vÎß‘§ª='†1ñ•êLIl·ÜV8“‰@¥dñ°ûÊ;†é ¥ƒ` ûhTûa`±vè³oÊÈd)1‹ÔKl €À·[þr@)7Õdø”Žk±aU>ñº˜gR/Œ6¡™`›(‰|jy¬˜¬GA?¶M½[ vÊx€¬w¨ÔSçÿÚÒÔeyš•t5NžF;  èƒóýqìM²ê p☭Æ"™,0<9„åFlíñ”d"2C6H—L «#}˜²F[ÁmU5}ƒâiòIÀ¶A)eÙËȦë¥ô%§ôÊJ¢ÿsJHA©·GƒñLðLd¥ÚÛÓ‘²«axn"^;LåF$«]U;Þf³Bf…©¤kÕ¹Æi00eËØ™I«*Í“@8"LYÕ‘'F£Ì-^Þ— Vê·SŽMÜ&ñ]„¾)íÖ1ªpGÃJ=M™@4É_´R¼ÊI©—Œ[G ÆgAÙ½ò?Ž7²E&n¹ koÊTµÂ1õÖn+»e¢Ú,ùûk,#QƒþÆðÒC]©£ª;ì»81p7??x°^ŸÆ‘‰c>°hcUäþ¥ÁJÈÜÈúö+™(sÓ¥ „ijÌ­ªŒL& ŒÐ+µL|{&H£JÖ’?1ÞõM Ìdþ®©*çvV¼ÿ(—•¬*3Ä10&ÿøJ#ÍD Ð1W{žàFïSw,È0Jް[¿njoäôsFÂkì¹Z£­ê¢i®£ª’H†Qê£ô8ë%¨«!'@ª”L\¹4á4ªlÃ&Öˆ$v„ÉŽd‚{®6ÇX•8G-4m‚Tr”ñ”ýœçC£”¿LL#šÔ…§¯ Äèµ=‘ù8"“ù)0ˆiºQΘý`êJ kh‘ë댗•¤ÚlõÖ[Éy”rëQ سØäÊOb[I1Œ$Ó»%; €6tÜzmȶ¡Úfï“X©q²+-¡-ЙÐ(Ñ´U³’ d¼.YW¸/Œ^žªpž€œNÐ\Gûh§;ÒdØÖ¨E$VÄLZ©ÑHãvÓZ0ªíß¿¥Á ¢jaj*,êôw$l]ÙŒ‘z;6I®‘ÃxæôŽJµhð°ìÓmý‡ fÅk°`"(U›%ÿUe˜FIKÓᑵ ¸ÈCÆÀ(ɬ7®w s„k4 î1Ý®¯x&ø”áÄŽ°ÈŠ?&²7Ô踙ÒmB \ù÷ ÞÊaÈäãSW»õì56ßѺ²íFŽ+ùhZ £J&Ü"¼ï”JýR Æh?÷¦JÛ–c;Ózl™ªd˜vók‘<éåô}%šñ4ý6Éǽ0dóŒ—ë­ä¸O„ÃÌuùt”Èh"›å¸åÓ„l¥ÀˆÖSj"ài¶JýÜ)aY˜ÈæËmU‹Ò497š­1űdZè›r¬o H¹× ©Š­„±@b‚Û÷ý4%#àÐW¥ì¿[à3Ïjn-ÖQ6ÓG°ñùä ÄaVkO“°•cJ¶0ÒãÈ“{·Wc =¦ü)ex¡JÖhû8vwÊJ ­‹g&Úñ¨Nl™Æá…^Gz¶î(§×øý'f‰2êƒ×èÉØµwÌ¥#_ÊÚeÑZxX—# ¥ïnnÆ ª)ñ鵘Ûßq0ª&}-]/OzU¼lcæ U?—û?FNŒ›Â Ó-zMkg…ŒgFcÿ1ý‘«vÍliômBƒ¯±Pª1êZ(ßÇ¡œÕ G¤·…›ë%ý6ñhÄ|(|ˆ1“@±‚Ú×[»£v4."Lt¤¨ÊB‰çJ šŽ¬´*}8Ãde+Áù$‹‡;2 ËÆÂýy€ç 3™2#ªVrô¾±~ßî.‘ô=»vbý¡øh0-ãhÌ‘™¿·ÅÀœ+ñœ?&£k· ùW}sÛðÁ‹FÙö0[uÇZ0Àí;_~a[Ç· ëµ'–ó­—¦#l:A>¾€LÐVŽ«Âb†4•d>þŒž,РZŽv(àómþýGíC£Z—RLülw¬dÖºøôÔÞ.¬· ½£€e½ L|Kø”«Z Ö…šÈ ŸáÙ<„ÍEíxÌî%ûë™/FB)£«ú~NVUÊVn<Я†Æ¥É*7wKY©5(éùX ÷ÒâãÇ;â‰aŒp&4gÑß—À¨ò¼ôw…¹ IæÈ¹¯Æ ?¢ŽÌ¯ä{"nÓv£íÙe³r¤a¨Ïÿ÷â‘&^¿?¿zÚªåùd²KåÌß±%Yæl^`Þj&rÓA&»`gÙòÌõÂôøÄŽx÷¿¨ÜoCô½Xq°eèpÔÆçÌ„'M%˜ 騅¬ÆH½”&9§Wm±F(9r(` OUíbºržJ˜r@Wb@°rhšÎgVa9ÍtÑ |ÓÜ÷ï:}Ù”8{I@0)œeÓ{.ÜÚJ”@ œ¾£Œ¡çPôôù›ŸT» Ü,bHÑ ôq«¶UÊöA¬ÊZh88ê¥,šK¬„!Ã8ŠmØJ²ã>0e-ôxeª·ã›{|/S‹¬ #×Õòî§€gG²-·j]ëm·éià&Ö"cè7(Æ1^†Ûy²@n)»)†rzÜZ£}Ù8ÿÝÍ>†* %¼A"OúÉ4Hz¶98jé ƒôdڹɪûñ$NP~Éš( -iúL 4 žŽ]¶£ìGO‹Przcà­GÊ×þ|ÓŒæ&€ÚUëjP-ªµx †®ìØKæ/3Á4EïëCG’í¬‘ ”Æqë%PÒ[`L!è·ÊVj4šVÕhíZ²Í #ôv ΰ¨ À¤O_Ƭ‰SÚ ÉVµ=UEƒâùg’á÷¿à ¡£ò,a;…d]©Û²Î¥mZ]vÜŒŽ€xæ0&s€•äf>§^9>Mã`ûÈ"½o*@™‹9¶g¿§ˆµ³º)@™‰¬·`J†"¾Œd›¾­ht UJ FV¥ Ä8F6®‹°mVB©×ÖžXŽª”;6É$RuG¤p­MÓqS sA_4«Í§TÊGî7T²^ÎÇèþs’ ËÙÆ+õªi”Új/94½»×ÛÇg"ö,-“mJ˜@&öÈ •0µoaBuJšx9C¹Å(·gŒ&>ñŽÚÃøÞ¹¬±wð 7W´ÞLr– &MÉm2G¥“LC·ëpðª”ÙQËô¹åÓãkWM¼êf)u¯JL€ ótÁÖÈάŸÜvȰÆ0[U@‹P˜ÈæbÈ„®[??Mq”€2ƒg•F è¸Yû飯ų¤ÄcÎìûY—•¦Ç´t—Aðp7¡÷>2ÒD¡+ý¬²ÅWrçŠÞ=JÆ„“úPý„ÓÆzŽ€èž×ö<™¥=:7‚¾áùÓør·1.¿¯]™’²LÖ”Ý?½cþ'häZ,©$‹Ä™ÑV› 5 ¸x#ªâ‘°à,ÒÏAÉ&–?^¿Ï‰™8w lµg…Ô.0µwÄëÂm@ô”yöG8“-,hÞÐ¥ªE©¹Wõ)È-ׂá“ßMo´jsbJÇôkt„µW „óϤ¹°)pGn]­•rÖåX&Ë*F{ëµL_ÂkvdHQ‹)Í•4BÞ1¬‘¦Z)2‡ÖKC&Âríz‡9ÐÈxëyF˜X[#lk ¸Þ> U ÛÜd_{&Ȫ‘a<0L,˜çÉëÖ&ô¹‡Ï–w„td-ËsY#˜RÔ"Wõd1Ž41J+G‚LšBÌê51˱hneGwoV‚Ž^ÒqâJ •M\ P¥×ˆ÷˜‰e_TÿaU ;ú,ÙQîñsÈŠ [¡D°‰=Qšª•²‚•ì„ñ=^¯à“-Y€ ÙOeGØÏ¬.³,3qL ?ëþ~ 6=}$ÜbrŒ"M¸ÅºòJ¯¶I2ÆìR•ðÂ6$Xt‹Ý—&è“ÁdòµùóÅ«K®‹¸Ž1YY¦ÛÄóIC€ïSP²¡œm¯ªˆ„ jÑe1ÃçmÁ‹ÌÜ ¤€éäøF:GqäŽÑé“V­Sß‘EŸ41Þ±1YÓˆp“ä^O9ŸVßwK‰[ž e"èûöÓ«bȈïœó4öt¬Tb’§<ÜzÇx-4J@ß&k¨–MgµFǪ‰«Žá9 ¨rh"½kÔØtWîh1ÜþMç€ 'ÃÊ<3qÌ6’ÈgíÈmB/Òà땽³}4æ úĆd}¦9T%؆x¸¨ÿïìðiv_+ÁªJÂQ&ÀÄZ ÏPú¬wÄc(EUàÝ™3pæý~ç:"­*tÁÜ À«w¯!ò)û3`ßy¶ª¬ggžá&Ê–é.™Ë4ã“5ÔF`ÄL¶Õ;‚[V”šB#0‘ ð=ˆÌŸXÉ â'C GæW{Rw4n4” îüsS<ÜË_n:Üh>˜ô97"±[S:*Õ.׋ÙE­”Ìõ¨jDʘÓüûaîØªø0q>e¤ˆÌD#æ:ó5Z˜LþkAï£ZÍVeÅDIhìÖy†ñ4ÙæÓqV•^²_FýÙ{UÌ÷“Ü6ŽCi[zbdëež-ÞÎ}X•f¨ ‹½ì •™Ô%ãs»MçúVjÞe¤PeÂJ {Ÿü×¢”@ ßï¥À—ßÏ †ìÊÏ›tUß YËoÕöÔ"Tk‘uÙê)2qdLõʘ¢}rk‡ªAãˆO8ÆŒtT•éûôÛä|¿ñk”EV½á€ƒq/èØÀÐN/ºæÖSBž_(ij=x¤›dK €ÙZšeŸG-4‰ñ™gßÑÜ&fNßÛ5g??FÐ ½âN8›ô²i¶X]“žmU¹Ú¹ÁrãvLàH¼R²ýµN{žy¶L†ª†bš«Ú0sÙ’ÚE-Õdb‘þc’†Êé•z J 7o.öéÔå¸×;SïÜlaU³ÚÖM{IúãrÿI)ú8(7½‰0î‘ær†å®iP¤+ esËþϪeZX5ÒÙòÆq›'P¬TNI]Jý%ÝŸIwqô†B £×#tl.Rh¡ÓÿžežË¹Õˆt¤qÜÝ1¦Ô8*Mb³ÂU‘°èƒ(ù8zF¢#’˜ÿÜ}…šB€ì%Jz¤ YU`ŒHÖnHLo՗DZeê%v„ß)×ì$%qGYV1µgŽìkC¨&À!oÛ@LÎ0ŸM 4%™ì¸–V%ãlJ<ѰŸD_x7J)«"ç¿mñ=^pîvZº‰•àVj.K©Þ¶a-5ú9úŸþùç]‚tÔ¹õ‹.†¬Qæ˜FUËU}ÑSªŠx¶B—ˆy[Ò·b]ÝP˜2½ãs{Å)›¥ÅþÚ Šªñiª¶IUJ‚øe‚Í}°«)i©Ë7R+-þÝšl‡"7%C¾­_ÂD6ËŸ¾›æ $âòqGüåøi´U$YžHíý¸Fbr#ã94NÞ¸šßVñ])¶@¥irh™d[  ‘ÅFЋŽ}”[cŸ >F ^‹ãáá2ÀDØ-Ü&cÞA4 5”µÌ¼‰•æ o²ïÌ”`ÎéóDHiœ€ùï³PÚÄ~Ð0‘xÎZˆõÆË½^ÕP5ÈQi– Š9ÐÔ (Å‘²‰ÚíƒÜÍÂÔE&Ön‡ÕWiÇöWjÕ¼ƒãnWc&l5&¶†ü…FÆP&û}®z 5#5èmS›#q;Ï‹†;&«†$ÓHü’ð– $ º8³jpÃuñIè"pìð¦èr Œ?¢óWÂ8ÝQ#¬*ê0ùÇ8šûVa²zUÆÙ»YÆ1F5OÙhJa:>AVWþý¬„4º£Üõ[&}ñ1}:Ä6k·¡HAæ¯f2FÆT"î Ó”í&<òŽ@¸Ï+Y˜%ãë‚ÿRâ[ï;] ²}m"h~W€Ów#¥4°v†‰™·ñ±»†iTEG@L)·°GàÌA)ìXé¶ž^ ÛµàÈñªÂ‘ ·þU/12«™àEs-c´c·`È5*‘Ádû½p»Ï¦P¢i^cÕ@<Ühbn€¼µ@Ó4íÖQ® §´ÌÍ %<%&ÛŽÃx-"ÿ>ÐÜ®I è¢TµÒÆe©6>vw Y»–ªŽ­DÎÖ‘,Ü>rwŠ µã…ÒÝ¥é0€¤4·q”xÍD]éM‘k‘[©)ø5‚X)œOL€À_¤Îä½86)†È? (ÕT%ƒÛ~%¹×¡Ü $C9wáK/£Ô®•|x¬ •+¥Ï ã™<7G¡‘ƒÑ ,ßþ•´6ôûWcÿé7%F£ªF`+)‰–ÑÈJ£ ¥r¶º„éŽZz †yRjŒœç´û€Èš‚ܺԙzçf[&®ð\$¶ T²^ž2¬P5H X©?&4¬Ê4Ù’Y`GØ|Ü‘k\J}ÖanãSbŠªþ] ÜãИEÐz€R& 7"ˆÜh ·€LÓeñÛä`C<ì.F¤g^‹cŒ#Y;0Ž2>ònôçOMd< @¶myÊZ€¶J–ÓP+‰Ž« S5U>íc„’èKeh¥le2U-¢Í¯ü,ãi"L©÷ ÿ|yÖxÉ í Æµ”r‹oŠ<ÒÚB;r@×î¥äFzåVð¾½zã1v;dWüö#{}2ìô 8 È¢ro‚±CLâ £Åxx2¸}Zɽ&ã|GÂÛâ󌜲Uñ[ž²Yþ‚c€²‚fòc¾ÝVÞÅTÃ-M–F w¡Š!ƒU·f-‘ s¬«82gU`½#ëbÒÂhÑ’˜æÖÎV©ª>*ïwÕxÚ5¶gØQÃ2ÛFd¢Š¬Q)@ÀÓ,À”®I©Z®WÞˆ-Ÿù9.¢.+±RŠÔ.fŽ'«‘Àb“Ťyq½"·z]c¨g(‹ÄÚÍjº*Ãð2%Ì爉¯…Uƒ2—ù(‘…‰û‘Þ/‚¨+-Èe€s2Ù´Ç(™¢KÀýXÀ¿!ßïMzL½í#™l4SÕ‚{dâx†®ã>¹’®VBjìŽ[[©É€üið1ùt#SD 3qT’É0aã‘­]&ö·¨È†¦¼Zµehø`Ta™8ÜQV-ç@àȶA‰Ó´*¦{ôËógE©Ëe}¶[˜21^; l Üú·sJ½ }Xþèk!®Ñ±‰íã¨níÓð|ŸÙÆç D,vTm´ìɺY7Wà1çdȹY°–ñªX点ÓÈÙ½úmFŸ Ïñ€o³ŒoD eëáª&hŠÐxÁy9=†@P&Æ»½ª|ëçš :N|=N¼bL¶›» ,ãk§wìRÙÚí­Ök%Ÿ“›f(g¢]¤÷q2ÜP† •UéíÐKrø¶JFp;Î (½'Ð5šð5;ɱ ha.€FO0Òqƒú% ëJ¬ÊÐjzGU%‚"&Y£)ûã6e¸°³®dZø¤‘Éd%ã„*+G¤.˜‰µ G‚öÑ(á«:4·ã\gnk!®K  >zijo‡4°g´'[ÊŽ|TëÒ(ø”JX†iäîˆq}ŽÉÊÜ”èŒÈÄtš|6´—ì{K)jÌS#F6îÞžðY˜®7ŸzÛ'LÈ‘íL/XÅ+JXøsË?V÷)U,'†ú¦à3œ¹#·®š@N3%Ò£¥anz#d—¹±*÷ØÏ ¥”a½‚ lM2ùü×@=útý¤uÙstt%U‘R‰ Læ&ºÚ¾j2¹ñp³Éh:àŽÂ<5þ;¿½Ä Ò{Uƒš¢ß2˜ÈrC¤‘½7A£Dî‰^+%¤OÂÄxú.¨åí 7ŽR` X‹…›²õr¸Úó\ŽþÑWÄ1ý 2½@š²œ[™FiþµËx¤Xîˆ Û¹ÆÅÓT²R; «+¼OÄ‘’¦·‚ßY]azÇ~#4š¹öü÷8Ü€EË4H£ (w…)ãw…ÖplO-”k÷ +%¸)íéØ ’I¦×%ûMB Ë&­7k/¬q °# Kû~N1<5âé]mÎôJaúK?\ŽªåZRÖÒôüñ˜ôáí–åû ¶vzsØô+Œh7@Õ]úG„|ˆU‹-܆Ll¢”CúŽª1ò.Ø%2¤#OÑ(1z "_ ,rÎ3¦qÛ„!,‚lËzrW˜ I¯Š9ñw>P¿ZÇ#º¿dñĹñMÜÂM6¸U9Ä»$¾RΛHÓ  FU¬Æ·*çct¿ &6(Æ2¢m•ª6Ž€¿ìˆ—5î.W{’A•à•‰•€¸§4Û<ø•8#톯TÆ3Ä"½­mû/&½³r3´5¬ýøÞÐÛÏçÌéÉ„ºL£:‡ª9'“{Oš0ýö4Â’’qd}æOÙÇÊÆq%G&äXœýîWQ‰8JÕŽrž|&SÊÉ€°•¸Áª ¯÷wl7U<Ð’MïOÙæ­Aä@“ƒöÖêͧѭ©J ”2ŸanJ«¦ËŽ‚ÌG¥j¶p›¸,½<«°£FØ\€@j—FôDiÒcVòÉÖ«ôú0ql=Vk‰ÄwÁÌ Û„žÜÏ&¥AxbÙî m+ @/™# 8ù"¥Çé:i„jkÈ-ܬªôȺš’øU6tJ “FïY\Rõ¬uCÉÿœ­Ç›•€Scâ>ˆ½RËä ‘F©Þ­Ñª-){j?¶ç»’Wד÷ ÷^u2ê×"ÌUñ&Á"R ;Ý¡ý5Šž Ÿ°’°=`bÊŽiʆ¨Ò`Ý‚Uƒ&9¸¶#™ ht¤#@©¤… ÓçQ»#~õ’™[oí-@´3 d“ÕÛÂ=Qš©¦á`g²Ž”É0"F—Z^Lc7LÐÜ7b£³’™ä¨·»g¨·vÿzÞƒãûnº#@Ó1qÎðž‘¿#^¤ôŠžK•9eUÝ«ªÞî® 4Ž ÛZúŒ0d²ªùËù(M–‰,臣‘B‹^ Áî’2¦}hz(ú‰çÙò½*O-²jA¸)FÔxÿ¾E< €kJÿ·eäÈ鳚aƼ·°É¾dòkèilÒžµÃd¢¹}‡ûÎ4±LHl"‡Ó$M2zÕcb±v „ËuÙS#™œI/ָ׳ýëâàXon»{n 9ÐÐÃ2Þ1C¹®ŽÅ«Ñ"Z©¬ DrÓ™¨r¶X£·[zžÌ›¨Â§ÝÿwÐ-Á"#€o<Ür€ÐÙ‘pxbíÁŠÀŒ«;äŸC‹Æk˜|²"îH#;Ú†‘d9†*96e›ø‘k„œ­LCinWâá#0ñ˜°Yá&y&“³”E$7xC‘‚'’ùÑÝ @š²_öi´úìvý Â[f›2+scòሺÈ:¶cšYaàŽ½ÜûØÓK·š«%+ÓÙuú–T-LÄ»”£ÆfÍP»ÆJrU2‚"&+9$sÎ6WTSÊd USº ÒÐ̵gØQ‰R9ÈŽrKB•>ÞQ¨ʪ‰åÆ™Kï(låØ3fžÜеçÖ‹Õ+×BÙPâ½æÝê5„sÈ„£^Gí& 5d£ÓÀ¾þ²©ŠiÜ%½,zgÕÆÑ¸©£R›×Õiä@]0yJ°è³ë5î´³ ž )H/7 KÙze< QôgXV5Z@Ky€`‹!ùÇ _\ )êUˆøá“­%gË$nO?¡vîóÂ(u…ó“Ö>]¯Î¬ix;Ó«Ša½GÒûÛA§ÉIku¤×EࣚCV™#ž¹cã"oý|ÒM”1rk.Ÿ¦Þôó²ªA¾¯ÄïVƒv÷™´I«Ò×õÞe ª2“6lŒÔ2ÞzܺZ«ö!¨ ÀÀMìÿ(c½H-0&6BÄ8ŽH>•´T-·pO‡ìÊ•ÚÇûàµ+’aDǦ$ÃhñÓÚ•ôŠÄdHXûH³àœá@yËpÖ…@Ê,`ôµ4ÝÕR&î"xGÓ‰a{â#ñ×ãLßÚJpÎùѪÉ䂲ëkÉsÀOø=²Ñ˜Z€ÚÉz%SuíÖl²ïª^2LI· ” U¤Fƒ²×…±Už[@;ÞqJLkøæ,r–‘Ýhda@ T}ýŒØ”Ÿð{±…’Q‹5tÅ-@ƒyùº0é[‰‘ßà¼Åì÷øgöïÏìL(®Àa¯ 7:s²q&€U[Cµðâ|d#Ú$Ü’²*¿¾mW O°‡À;0q ÕÕ1†à`1Ñhä)Sú–PƤ”›ÒS*µá_ pÖˆÒ/ãçþ÷Y¶qƒ(»‚l%Y É€ô”‘»T&õ*á)Ó4ú%íLÀD)Y{ú~¬èÛÇž)ñªã½éÁ“ˆ$p\n¥æ",h<ˆã¦¯½kmÕ–Ù¥ˆUµ3¡t Ô%[©’{á³Å#‰1ºh|S`2VÊîØLVùSú1ȇ,™¦^˜'LPÖ.7:e¾ZšË!%M—ÅYµF‚pV47Ú;c²Õk™ºZ Ü' Ä1Þkh94å ¿ß×Ì«úÔNãlE»mŠ’ ‰ Ëõ¶öîîÈAõ:}_€ÄÐRXÙïîöïç_{Òžº6ˆÀ2Ž=T%2 p®ôûžWrÄWšÕ^,«v¦i‡H6̤M²Š?R×óg·<LÜN£È½‘ôŽp-Œ±0M2UG½mÕ]öÉnh¼V.òýÉœï™ùü Óܤ|©ý¢!ÈBÎ¥^™¸áJmo¶Põ÷/í~ ”0øÚÓ«VjoU²Y!UÍ•…#­t ˜²U_ ½ÄÉðȬÚ£ëÝÇmù2™ïbÿŠóõÜ`Ëw‘Ž0·ü[ Tm™Ì‘ãµÔH&ÈÚ)0®`ä£äÈ$Íõû~sÅŸ‹Ý«É‰k§Z&l%SÈð€ŒÑ‚qÈèa)½Ì¶Õ• (Ó‹J1.¢1‡†¦É¼q<‘d>\9A> \?ž˜é‘ô­Ô8+õ}sÌJ™2MnÁ iIã`ß_$LûDÎ (â³Å0´y‹™ŽG2'@>¦+êHc4“mÛn4w)g(ã»{Y•Ç1dE½»/ ¶dkÐB‰C&-ÌIP‰&Üeû®nàFMœO¶ùÌĶxk zÕŽ iš"ãùÈôÉRÂ"¥Œt÷@Îõâ‘ñÓ3l( ÜNÙ_£®•òá©n½Ì •ªÇÈ-I DæF‰‘!«šÒ v¨×‡‚¤lt&õ¶’ƒpMâHíßÿ9-ç¼jÎNIu†eJ w8_X¤9Cn(bS-ÇjGúÍ"o Àk¡üŒîÿØ£¸­h0lÃr¯€÷-ô“Ã!A†ÜhøãiXÊ·[¤Ü3ñý—p´0Tb"ÂÙêibæ£ß,ž”4Ä‘U™ÔN´I9ìF6¡Ži˜à{·mEÆÐ±.€øuvDÆÓä°^CÏ€ßÆ e&•RÊŽó9 ÷…ûtÚ\#Y¥®°–‘{Ot¬T#Œ¬= êØ]94‹¬miTklm-«n+@hy #Ç8zds9ÿÖèR˜v3 £U²ÞL”^`FæTµ«@IDAT#è}úŽºZ^¯pY2@À|àüa½ òÁø˜Ö«‹R$0Ž?DHJ6q õài½JÙâ¹±}Ë|2Ô¯½õ™¼²­žÒ,¹^z@cir&(’ÁÝzǹáUí#»¾dîhY¶°Ø§Ó'Ò#dE¿¡êj½6¡éÕ¬¿‘BcÊ@ûWzù³2ïÝÒ÷&ø}L6?‰Öfõí‡õx ‘9²°%~îhð"ìÐc4R ]É”º?²¹çìEðzå@úÖ ^‰C[å,S"i\/RÀH€¡²KŸ«a`Õ‚ƒMúÐw‘ö™[†‰ó‘µËœóÉ„rsi²Â‚lO í@ßíúÆ$NÐuŒ£œ˜>òçôýJªdmž•¸ÁÄÙjlÕnÁV—j‚ªJ9 ¯Eû0 RU(ú1xd]Ý]o €µ´Ü}½œ²YJkÏ¡wƒÝÅ_^A&Q/™vüJ‘¬;æL©«¼#:cdËw÷|0õ·v„ÿo ä®ÜJMÉ_É1[Ù1œ§Rކªöž™o\¥zµ zGY;ÐÑH¶p‘ž¦AJ°ÝTa#í¯8yJ8e/ƒ/8ÎÚÛŸù>ôæv&³Ê°F&-€ìÝš. %¶JdŽ "ƒ‘óÞîô\Y€@£/R>pÑžœñ4¾ }šÅ3*-€ Á;’ %㟟6®ãÖ¿_¹Ã4L2—Ïöw=¤+0ß»ñTÒxJæís¡ÖŸÜ€Ô-GgÇh<Œ,2„›¤Ëx¤0Rè ÓÌ!ÀÖ%{ôËha%ÃÈœ;¶R˜"cÈÒ—)SU¤ñC¼ #UaaÇZôª*¥A*5‹ )÷ÿEeßûÄH>0ý`7Å·¡ÝX½¶u ÕÄ=FK]ðÈ4Ýî´]YÓ‰;6·çÒ˜3Rt;2¤ÀÔEÖSˆH2YµMäãòûzqÀX)òZžt쉚žLvªû(õnVP (UÕ h‘³ŠqôàN J6ÆtÇbæ­lC€›* s`UL“ » U-é(o¨Qàkî.Žxséù÷ËÆTRp&¶ +x%ŒÝRÊ4µ Š7®Aï5×β¯Á|òÄ“ L$ €‰—1-f:,Þ5Ràe‘¯ðüpq3èVÎ]"e;'Fîîɪ2Ñ[×üsF ú6ô=ñ²*^;>7 \c>²=·Ø¨ªÄ™!Œ”³ÊÙ‘þÚŸ7 G†åZÒ8’éE6:¾‹”Uý”Ù_Ô_£*ò<ŸÿÁ(+P´¨U‘ «ßËæ^)RÕQhç£ÈH»*¥ 7‚ÆKõ¹FÖµvǽ‹^ÎA¤+F•¾sNrž#’RÞ²¨tåÇÕĹ™5qL6§ZYþóTÂp–‘ r(à™; V°PÒ‹t‹umO¸ß­þâ°));æÌ™[ü4ã˜8½ã-ïØ×‹¬éÜ€Z"aJ2% ˜.”d$Ûº´×¨TÕrÔ?¥#1eN–²ÝÈrsoëy: ¥F@Ž«‘ŽüÄÉdñ¶{j-Äx™§cϲF¥^À©*Èð«Qï”ýdkAÒsp¤º„.Œh:Œ¿Ü÷åÙ U)sèHÔ¨ê;³cÎ'›€§@öU„¹yC«ŠÖS"ªñµôÛ8çö$#Ø+ݾs;@JM§çƒ¡wåÌåž‹†@×y¦û ·ûûÄ›ˆ¡yZLÖÒÏŽjβjJ>pÃmÎŽkéRJ€Ü ¨îkÙJu)Á¢Æªy+¸‰ªdŽÝñm„o÷Ùͬd=ib<¦<€©¨0 ùú&3`ZÕ\•µAÆD©ï1ŒÁ“Éõ V2>ç4z1ª‚>C>J-%«Æ¬È|`2Gíý¸6˱k&&^ª‡¶€vq¶üýñNp¬o0}#Y GJ³Ô›˜ÕJñÈò™ñû3‰?¼ªŒPXýueúµÐ×bËÆë6š€Uy$Ûüå‘€£§†ž=îJÜ\VÏ'ŸFWÑ< „äS©öZr pÃP—cÖ‹ÉV×€ÞLªîH0Ûô²5ÈÀ¦êv4ø5ªŠÞJ)Œö=¬Cv›Î‘Ú.•eƒäxÙCíў¡L†¬½¬ê;‰ÝÎ6´ï­£È\Vz­†yÂxÚJ{J vY)œØ1C$±ß§¾Joïü Šh,ã>‹ ­ÑWH #0ÇÔ‚ttÇd¯ìêjŸZd¥˜Ö é@/§ì)”¶ ̧}`nJ-\ ’'œU”rËJYmIÇ >wÇÆéâ_»\ õÒˆl‘ñß/zRµ2ànØ9ö«Ä± Lü¶D]ªz…¯¯a”JM DîuíŠÔè˜ C-aïè2<³…µ¤,Çðä@ j—Þ”ù`èi\Ó—¦‰˜FÈ·éK]ÉAÖ’›ÌPUÊ)16‘ÿrsµ$€·-‡Ž€*%C&ŽBI 1¢YŽV¿tœ ±j@Î ËàG×>ÆuZã½NŒö˜“éß¶ ½Æß¯Núœoë÷SÑôöi‘/åªõò}"JF(5ÊmªMŸ1f]€ Æ!;ʾ!½­#=F¤”…—ɦT•aV¶ª­ªäXÉz¦ÀÇî÷óOé‡(í€P•›™^ž-A›cöùšÉv_«æÙÔé T+uäã)úþw)JÁ9s8‡¶ÕK¦(ð=,±£h“dªZD÷J¶ÞZkl\{Ò ¼MXqéezL9gǺTs Ð@ CãúëuŒ$€‘.â¡`nÚ….G¼‰a@291@02AkûÙ¬”g¶LòÜæõNC#Y‰ F}ç»A›)à¿ãø¿ÿû¿þí6ÀW¦ÏH¼<÷¾VÜ Ñ—ƒC«o2¤H©„”óO°¹i:&(g8¾—ÊÖ™¥„UgOS ]ršgâŽnÑEü”ºW|ê0Ž"™T…­‘¦}©ªÑ›^UÖn¢hâá)‚Àã„G.κ7,æ[C“CŸl-˜ª Í6%Þ±¹i6«£ª˜Ã|b”^†g¯„ä£êq|Ӛ嘹mµ·Rì¨*Q2á¦ê8 Î_ŽÞ!Á°ö<ËÉTçÜ&ª ºNŸµ‰«:"ºDUï/²­EV͉ pèÃ:¿Ë²¢ Ó /àØ«v\#p%߫ƳJì ðî‹vÎÓÑ»Ù'R;À0[ÀhdٙؕSn·ÚUÖèšFÑŽôöy‹l•hTéáxVM¹Âï…ÁÓ0¡Ï9A³šŽÙ׬ªLÐàÆñIßÿ™í™™ooÛVÂÏ-Cí¹É0} ç¬Ìí¨ÅtAPé§9?ØD½©H‡.éUć)cä|“aÖ¸U,Jæ†ÌiŽõ]¥/ôq¿W¢±Ÿ¨Ú 2TÅ=P¢£ßYbY‰Œ!¼8c~¶õ4º{éÕ 6ÎyUz‹µÛëiz÷ÕrÍþ¬×Dâ€ÜuÈ`Ë—97ÝQ)\5C#Z¬ê>;ú6ŠŽ2åZ´[»®xLκZ©¡x }²ò¾ Ú‘€‘µŸH6FU‹#Ÿf±ÚP5·7¿ûà M_#+‚4«ú‚EîR-Ÿ¿ìȇ&棽 0ŽJ^žÒE1‰74ñÜò”‰ÅféÊ*ÆäŸ¬œ¹÷ÑhhG¥³Ó½¾Ûí‚ eELéHп¼­ßOè_†FÔÞ]Äܺ#¾ ˆïo„}&¶ðdmB#`;sã@fb+áL¸Äù3fÕÖ¨¥Å"kTÕž94Ùâ3(kÌFÆSŠH; b.UÊ4á†Â¢÷¡„ñpÒ•×ï{x'†0Aþ€dæ+š^îè"”x‘† ìXP8ÿù]ƒº&çc\ò’YT…$Þ-ž²»ÕN¶#¦‘4aw¶.sU|ss–i|{êRÂO7á0"OÕÆá19“%Àà+Á•0̉#ed]ø“a*YCÙbµËk(‘)%€sÛ'÷Ž#4È)8²å°Ÿ¥&&NC#`ñºiÇØJUÜÄLµ/ÖÙà^#àÄ ª‹ƒ®¦à5Â"ÞQoŸTßB½Wõç_e.Û_‰(Û î 3a›r]ñ R˜ÖfâØþ*QÊÂ?´MÐ{f2çŽØç«KÕÿÇÎ Li«¦8ÚãaU&À“C=Ëþ‚•Xã†ÂÄ2=ÑbrŒÕ-ãÈSÔÕ Õ¿ºÖ›LƒÔîeÔ^#>&7²J)ûAV–¤¿Ëž„éØ-ÚvU&ªL0 2„cdšdÓxy]ÈÆYi¥›K¦* z棸Ä÷Ç‹Pj—Ñnxš> ÊGWG¸W ã·!‡B xsH#f•`³ò×b=$ 굞.&޾ r—żnýüž?œ±YTnW=B³R Áfм—©ñ5!NÐï ™åúÁVåßh¹0¢‹Q6:àFÃ]¨UKH½JBûögŽq”äFƒQZ ãªH ·<¾AººK½Éhª6.ç6—)e$M¸cù·j>”æ¦ežß®Üvõ˜ö¤oÏŽdÝTfîoy·«·ŒÑî³Ð;+ïÍâÖ& º’#™œ ›Eß ‚ŽUuµ`UàiäFËl1ÓçR^à ª—gß®L”Èr`BæHÓ³„û²…iÞÑ”˜J2,ü~g› ÉJÄÐÂÄôò É`Uš0C ™,ú8ü”a")Lˆ·ˆ¼’óè‚€¼Y}™+Õ’ÉsR&r-Ì›¸å™$Æ÷t@ ËÞa†ø.•þkO>H+É 4TîqtÁ+‘8ö8dÖ&ÃËzå–ñ€Vuœ¿#üo+†U÷doàó¡ Èi.#]4‚ØÝûï”ÃûŠ®‘¾Æl½¢A s h9Šçoçÿ"XK(gÔ ™ZpÁ @hN86,þßÀq¤Ñ"{kÇ‚[Û$Ó۔̕•ˆ9,+åÐw¨cÕ¦ÀÜÚ6eVù,÷÷>J]ëŸ>™U½-° :šKО@ŽZD_Ö÷Rñ¯,´ Ïô˜œçî³ð'hí‰åkvÛï5ªòTeVuµ*вïM¿MÚG×v´Œ¬„̳ÌD´Iw+ÕEÆQµï†{Õ¥„Ï“ƒÀϹ*&‡7GöC‚ïF@/`í­ÛÌ;Öl:  $˜DÖ2^Ë‹Sf(ìÖ’zÝš¾–¡qS½‰Rk_í÷e#õÖåèó"®Ýñ.û½$’,Ò&@yŒ ×ñÀ¤'a™F¦!(«Âõö\rßÛ”d¢FùmÔÛ-æh/SªÂ½mðL!ÀÓ;ŠzU<[€>ÿxLžiÈr€@(c€ákÀŒ†[xÓ3áÐ7§êë#åv dgÞ’¯ ‡4õ¦<¿S„Ë÷~½5‹fïV¹¨zô4¼ KtHJ|xY#ÞùÐ8öX€h2]v«— #0ë§h%]Jx½›EÉV ЮC€ï +|2%áXt…L+½÷ZK‚hO%díºñzEþ˜Ž)áûÍèhg¥r{òOÓÂJ~þ¹! ÌÊDUc«Î6MCÛ§Ýò¬·qZÚ<R/YGÕÙÓD2X®K Hƒo.O,únuLO`Š,Òïqø ã»rb “M¬Ýñݤölu‰æêm€¾Ç÷Èú´4BcŒFJúiBjO êØ+aXÉ-Œt ÇܪrHƒÔH€I@8"Ù2¡G¥èÿÿ’|’5b]H]í ;6ˆC¤ª–lëMFÉäíUMP AVŠª”ŽJµÀ§ù~è½OU™ÞJŒ'[£-Œï(Éx‘Cnõö,Æy+-J°Y¢ÆVÝD ¨]UWnrd‚ær‹×«úó8lPo “e('Smb˜q81™o#¦–ÚU'p$Óxwظó@¹) –KÇöÃücj‘ÌMc¥–Ë<¦‹T"z‹Ö€›µ^íJ­Ô¬3ø÷½Räp‹ß·ª®4dË?²hnƒ¬ç¹ñk¯ÅôX ©š8‡<¨äÈ¿.dšköý B©T×/É/§‡;ŠMŒIÖ³7KIcn˜ÈÛx1q²õªnÉfeX×~žÓG¶üøýôb0iäŽÜbhÜH´ÀªFž¶ß?¸m$¾}ç'Aä3¬sš6hÁ4·qp®žOÓµ¼kh§”Éèå£0¥Þœ1YJÕ˜–éˆá3+ µ½9§,§”5¶çÚsJÛ¶0Ï€½v@ä4ÔDàå1µ k”70“?¥£ÈضÀ­ÆCÅgØhŒ.ãÈ0J™Èâ U#jXÁéë…y'uLk©?ÓÜùttUX´ã6h S—¦ÞÄ”FÄËŽÚa™RDz[ÚÔÞ búõn æÅކ^ïs#¥½Æ »OzAŸ¬)Ž€Ý"5ÒÀ¢¦L쟃ìo%= * èª#¬Ä<«Lù7])ÍzU5:ò ü…µˆÜ€Æe[¯Ï+’Ÿ,jÖn²Æøp¼ûZ•! Të]Ö.v¤Ñ‚ñ>a\µíúÜúÔðÎßÚ´¹HJGJÑÅe¤RâºjY®%g;تÑ/úmÈObžxLæõÖˆ¤¤¯„´’Ü’íÓ»é2+A?P½…. ¹ÆiÉ# J€TZ‹RxVWþç3²F—HY‹C›I#8‘Ø8|Y# ºÇ!H|¬æÈ°¬]$뛀Ԓ^O »£A¯@c¡Ýëiðbb²¬”˜¸¥ ⑎HŒŒc€ÐÛç`è}v¯2=†Flóz‘Í¢fqÃÔë(në÷\pdׯKËñé ³¥»€BŒÿ¨wéXn†L)F®Á'L&ÌÃ4£ÄFÐ(5Ë­`%@¨:®±k8"‰ÙÂ2YH¹ö·ÊV‰IÕ€œžrÏ–›p«×³ÂmÒ,x²ÜÒwA¸P¢OÀ³’·¬$3LCוҒv¨%¦Œð©6Ë‘¸5ú6Àę뭘²A#{+Gâº8¤¯¤¥Åõ²•‘4 eŒ£üê«jTªQÞ`R{þªZ VvÀ˜fZŠø·J£TKo¢ŠÑåhœ’_ÊVÒB£š'‰#Lf‡FÏ w @PÊøÂQ„›rUߟ:]Š' ž`bÇöIßz2 &CÓѺÒû¸æJø³Ð½c&cZ¦»è{sí[R/Ì™RtdÅgVô⌹÷¢§Œ¡„µ_Õ—h„ª–s¬½£¬Eo²Ž°_8ölUz%¦Ë@‘æÆ÷« ÖÒnªõºx»ÉüUo·”ÚEZpÞ¶ ÒK–%Ç.Î3¾»Èøôs®ÄŸÛ‚Ll ,‹»Ë¹© O†{ÃZL! ¸/s~ÈQ 5;¶Ì¿ :ÙäS©^VÆàEÇ}€*r³0Ü0¢C‹Õ>“þ›ÈJÄváb|x9Óàly®”!¦ÆÄ”o+Y£P9 b ÒEP¯* ÑzJ¹ù²c 8f²GèóÜÜü›Û&eíùÏJ gU‘¹F´-2>F{¼,t5«öVm®ë$NÐgZW˜€§q™ã(š«—Ì‘ÕUÅÐéï©)uqh³Ÿ>Aå˜XÖË0½#™F2š&"»8+CŸET`ò!áô)ó‘# ÚL|Ð 4â9Tí.ZDLUŒ¡z[Æ›ó<³ooÛ¦ihdJgï篺ùh¤isY˜…©Ý&‘ŽMôS¦Ú‡h4CXlœªhŸøLΊ÷‰TyÒkÜŽ“º¦’HÜõ;bR2l™˜Æ$Ž\K ¬x§ØiOží£ÝqÿaÉ^¬—¡Ù»at1˜Ô(kAbÚ§FY Su?,ŽþºÆSµ%s ·,Xµ[&ŽÝ"@ÀVÉQ¤tÌSž0Ôæv ä¢ÝÎ’ÿüóžkø~Ÿ¦£hRGŽE-‘}9`´ÄËïHŽ“©2‰‡ÉrÀø[Œç¨ô®ÁÇ(s#87¹hw1ÿ{Ëï F(!‰;Öø¹ÁÈÚ· F#2¦js#czè”™´g]¡êÅŒƒUe½ñdñW%Ào<>JŽ+Í xq)žžƒ¯ ÆpÃ÷/.Tuu#4µt%‚‘-VYGL&ùàMßgM¦nÐ"0‘rŒ.ÕZ¶'CLãÂôªÂÑ}õî˜ Æ^/Ð\ œ³ö P²ò}6è¬{ŸZv2]¢MnñÌ]© ލ7ÐÚ#VÒhO†¤憕*±པЮd¢®êûU•›^J˜•œCsaz]ŽLò„‘²Àˆzc”0›´ašxʳ÷½ÌžÍÖÖØ„¸}LibãL`@—ÈS×FÄT’kö9bÒS6×ëy2ÎÈÄ}}{Yµöœ—÷ 4”Ž›ÞDüKšÎS©ÆÖn¥ÖÀô«,rz%bšJVr‹0¥’qkéš@’UµgµàüZQj¬«ÜÂ=eÕ® %ëÉ»r|í°)»5Y 0íÍE zPÿâîsÏý”Q:2Ñ{ûNÚ ¯Ú†”ªÝ”OÊJd­*cD&ŽJwì—ðô¦±vÌ‹««âš"ÓÚ€A/zʪcÄ‚LV¢³½•ï^°AàôÚöy= ²â£Déå[ƒ #ܺA0¤#,ð1.¦Ü<ÀV•2@à¸5àŽ)9;N™›c@µ °Ü>p>64WKüù¯j¦Ë~íàñ€\3^èJ¯W +y”® ט€¦8ý7 ¬5ô±»¯t„){5£+M Dæèb€®&tç5‚ß½hˆ3¯ÔQ5UƒjìðzáJz§Ä„Ëí‰lŸ-Ùh3L“³Œo oE×¢ÔP ú9ä\Ùöa¿ŸNV …µ×#ë½®çmktä_Ô˜IšÖÓôµüÃ;ÒA$€ï7—+ÌîÖŽ-f:fKêÅ$Þ@Kî x¡EÆÇ4h²”|ìÖ›“5hã2‘ ãr#°ÌAcø­Vªú—óÞm>]Äó–és‹gÅßÈVÍÖq|JÇÄk¬RÀ7kéµUØIÃjÊQÒ„-¶_£=H|&,ç&»/Ÿ`žøJÙuJ޽^áØ0žŒF.ê%^>囯Ù÷U¤tä@°®9¦‹Ë˜Ì‰ÃnCXµA«¦ÌG®ýüguÖ#{‚D€IGÑZ3]%GŽ}Š­‹ÇGÑä@ŸVäü'&h ÁµùÛêÿÑvo½²&ņ/¸šá,ÄO~53oýT½Ý±?Ö dä¼HGEFFfU÷Z{Ï€m†ñž¼RÇÜàŽyf&ØôÉžsázb½óÜEr(÷˜c˜´Ð\ø|d|/Ð&'¨ÄÃ$ççø^H–CãjñÉõÒ$“í#”2¹•OÏ­ ío£‘¾‹LôMI‰Ñ…ä#à€ªïV˜þYÀËóÎrw=<7Y$kÕ~ 8wjwû]éhbe#(³ê§½÷Ä›•ƒv8¥ÌD‹È  ˆ™ˆzYÄÉ€éãµÂW”V–<î×?k²M†I¶.æÄÓ4‹ );Â)ºT{C¶‘”ÖÃçØgUÇáŸÛ™qÿ`a \•`s×Y/%pšßáh‡lµä¦Ù’HGd&‘°@:®1@ŒÌ“²È¿€ô”öOY—7Ù׉æCKL†-3fǾûð° 4( ˆÝÑòŽ[€².&ßøÅ/~QÖ¤M­A®`Ô7î=V»*·3ÿýó™¡ä¨©}U F qÙg¤®˜azHËD×Þ ˜`?¢jIœ-\(çxü×eÕè6ï¦ãûË,ªq½Œ#ŒÁ;Ò¤d…Äi,“s[õ5ÊŠl>ª·ïÅ$háÖ’›F ·VêÈıŒ!ËÙ ¯¥Ä ­ gU Ÿ†vY½uáó™,@†ï15úÔ„ï›j™ Û gîHÓÐ0^ÀÌ…’pÔîØè²xÕç,ÇÚûÄJ?sŒ¦Ýéå3æýèHpöxÄJMÁ<%g—ç™U¤Ü”5ææ(à¾Qž³j¶Ú»Žª–˜ÆÉ]¢A‘Ú÷UlP½dµp 5·vJ톆•0BKº`|¶J@-pæ†u ˜L¦!ŽE#x"sXã-<ŸÐ(ìs'¼~*S&…* eG#à@ªúÌÚÕd•°–bV@%UÄpS-Ö±KùÏó˜‹zkq$ƒ„ùøù:ÿ·€šRKŠ #ÈÛãùÖ)eÊzÍË )š§töº7×Î _$«=>X¬ª—~ ìæl<ŒI@Ì@?“‰JF«jÉ'ç–l(^0ï^µ#w8 ·J,઺2iôU½’åó ùL™ c8g-w…×/¤£¿A·[Ùqob$$è ­‚QŠÇXÃqü×ÅmÊž·åÇÓÔ 4(ç¦-_ÉÚ–ÔÅ #z„4J@·PÒ®Z‰§cS'3!¸6'èÅ J7 d›F‹<ÿþ2%¦AYuTÒÕ#¤TE†iea¹•ZÒ‘­ØE(áÛñ/ŸÈÚkÉ'%ÜbF³…çàˆäŸž­ß¼7ohÓÛn¥˜4²’ÂrÊd†öŒLih+95î|$AÁ aâI3©ô¤ª‹¸·¥§œ8CÕB;F;@#ã$ŸŽ2ž>™ŒqLŸ’Œ&>™£5ä6$³9ÌœÌQø÷Ÿ¹e¥*ðȰ<‡l1€Øòzi0sÀ‘ AoåëÚ&Jù+­Ú¬¬*}ã—¿ü%B“t*slEG|¥š»‘ “3 ¯ttw{©JÖÞ˜ZLT‚‹x$ 6ÝjLÖ5iýö½>¶9ìÕRöïjt³˜p0hÇÚÛá)h(O>²{‰œçF¯* >dJr½˜³#¡…R4=|mÎ5W}b¶‰É`>½d°j@u&U1‘;ºQ>˜b‚vkÈn‡!Eäòµùô ŸgwéÙ{ÆFhl€8@/‰«Öb(F½ ¥’?ºÈàJµãÓ$N9$&Ãz•VUz†eý3hî:gÉ~±:ÂËOA$d³06”› 4´}”„qÍ­*wŒ§wì¡2‘•4R XFRFög-üôyýg¤tYëya¡G~–ºÏ-ž¤½Üê“ s™½f o‡)bè ð®œÑª>l|2 OÇ@ž°è×®’I-aUn0‡V…Û¶)‰É€õzh²ñýIC´L-Uñ3Ù‘I÷êçߪÏÐ+÷ÑFʦã”S¶9l -4ÄéU“Õ»Xi[Y I&jé ÍÅWÊ¿lV€²½€”ùhÜ 0Î)xv$Žá™3`nþ‘‘m.àj¬«F| à1°\4%[2‘Û-@é¢Z –M)tmsL›oDžÍݪµË"R£¹Žü¹jWîRL½L¿ÆHšø|¸É~^(Uss|þÆ´jb‚Lä@ªŽz]3ÜDXÀUóÁ$›žOï à1Z(ávVM07ïЫb"ë²PÔ®ªÃP~:+¥‘Oa´¤Ú"ÇgëØß³ª½¹ñ„ÉæÂõÒÏ+ЊwÇå†qŽ<í£±+7È?Àéív@·SJcœF»#,Z©¹gœ¤­ 4À­˜Ü‘ô yÅtxŒ.Acؘîžz)Ï^ïÏ£#>½ÆJŽ¢‹Ñà›ŽL€„åxC`èe—ÅWB˜îŽHÑ8Y/¦Ò°ÆJ›NS5q+µ0% ”Ð'Ô\Ç™Ã-pé 0ùÛªjL¥”ª²ÒõZÛÀ4ªý±ªä÷]ST EªòÇLfÿÖàˆÖ KÙ]ð4œÇsSUÒXv\ØÓÑçƒÌjWÎA~zA#-~„dx[¥Ç¸Ëž=MSBcòòéʹiÁÃu9nh¥§§Ï-E&ªž7Ab¼*~Sò÷8#|³âá®F9+&ª>t¤–4=Nƒ|1”ºr†4ZäŽ<í#;²ª¥ïvǪS2Ž‚Fvl ²My¶ÃÂÐ^X™h‰·0¦ÅTéå òù/Ÿ&ñpZÒtÌÓJm…ܪdñÀ³7·vË\®kǵÌí¹7¡*”úhšß&ª6ü°›+k¹­ŸÙ³`r–œ×ìcfq'~º LÖ€ý‡ ›­½®ž©U4 šr€ßlYlbÛ¤ ;Âd5ö¹Âëšçßi°¸sÎìÍåfÛ~Æ`dãkVCÓÏhtÀǾèr«ö\L„ÿ…dÿk™ô=o#‚} 8#ó'»’Oßd|C3ܱ9j!PŬ Æ”l‡É è“ÉY=MêÅäßH ·z«î˜ s€^¸, —1ªr¿p4ôZÚ“ HŒw\¯ªhg"þ xÿ*P‚¯äõŒ“›ª#CG@¶€jäÚÏKåeÑÚÖlüÚ¦$úV¹oïçT2>mölÙr+YÆË¾vrúHž”ýyH "]0 £½¯àZTu ¿N "N·+Ǻ²ív˜BK¡Š‘;æÓ-0C$˜mJ/ŒQÝ«ÎÖiD? 2‹XK²–áïØJZzÀÄžB¯.Yµ¬¤ËQ¬VÜÊ1²v‘¡ ªâ[ÆYoY4Î&¹å<+¯ ïº*y%X¯R¿Î1R&ž•AI)Ã4x£«zpÑ&ô˜zkTm1#0F§ñÚÛ$«¶¢FȵÀ0&bZ¾Ý(•ÆäO)à6?¦÷#À4(ž¦q P’YÝîóªaØtyLâV"ëqÒß[¾~¸4jiUXôtþÞ€iÑòÀ4¬:ª"óާçŠ[@Wn2AæðÂÜô@˜áYè>òd5æPNV/}xÓÏf÷KB¯*÷8Ä4fyÒ5ò'ng™ # ´Sb˜8¶g>-C¹R_ÕvÆÀ1)uE–ñ¡š&,GàÛ$#çd€ {ýöÚ²6 {ˆtåC3°ª+íQˆi”œÿÈEŠö“«Òó;âW"®Z×x$¬ È90ÝŽ-0ó@lW ž®‰œM2-É»;±/ŠÐˆ§ò+ùåÞbß½˜J0ÿ9“9®¶€ÀŸF žÀ¤£[ÔBóìÂôÇŒFJ¹Y²P•›ÕVL{æÏ*O²=WŒd˜p¼R«íÙó>'ÂmÕhJ¡/t©öàÈþpÅ' Ü·ïõ:Aí=~+mgGκ&Ƥ—ËE2¼qôrã0‘Ž€¬Ôu`@û•œÿWƘzíÓû;ÖBC™@~&-ÐÃzÜðs<1C`+eˆ×û[É6r¥”ÄEãˆÛÍñ,ñ¾2±F³ø(‰Ú·-%Y©›ô8•´'ÞÜ6¡ùô¿ L*²°J˜Âkno.M’#Ï:ïÂlrëÂxY—ýÈæ)îðómV¥t ¤o¼H£ ©*Âôp2²A>7í•äkvÜcÁ%Æ”œ[•‰ªÒÓÎ ¿Fcì׊^/@/RÀ‘Z"[¦wSÅ +Áícˆ‘Ns¤7úø÷P‘ô¢q€êL0¬¬š&<haÇ&"瀌ï;Â2Ÿðö¬«_pÈíÓ †-6óF3ÁË}(=B%+Á‚§ 4ªrÇåm ïsϹwË–! ÁÓ‡ìŽzýÈm“ø3þýY+ G£»Ÿ¾Q€z›À”>< ÑøÝÙ±F˜Ö–Ì,d¼£*ü§ÑR©êf5Hž? Z,Az» ÌM¶ Òð” RÎ 0B=™Ø†ôµÄWº{ÔÏËféê)2”+LÊõÎó¸¿P•›vÔh®£œæì¨4ÞQÔ¯äA¶† Ãi:2TôdH³XT [ ó Óµ˜[âÞyþÁHë—•õôv·ï"S¡D3=q¡¨ª Yè’«¦”ùËõÖ#áñuáÝ“I>‘Õ¾45j™€†!F;p›Î-DíˆsN9~28ªquÁ+51 q<¹=`«öiÁ]‡`7B.ð› ãùA@&XÉUzLûÈ>Ápƒr€Ý"“ ð|>•dJY´#tñýös®WÖ(®ê$ºD-J𕼾T"« lZ*$ÓBPV…EC{"d¼.ϲˈñ»ã•Ÿc]œ«6"½Á¬Y4-ƒôÃøÞÔ¥…•ãYôþøÐ`„>+¥¬Ò;jàlp7—ýá*4;Ö"“±uk¸j³d²LÂYaDb­Ð,ºˆ#Y&SêUÍŠhÛÄ1Ϭ*´ KjW-šÒ—ª)-F©DƒTÝ ’Œg|†Ž­:M€þN~}¾µ u5BcCIˆøJôÓÔk–€E—Ò’† ²õá aþ¢jX xv9¦$+ÒÀ½†ê‚Øo!Ǻ²V:ÿ°‚²#¡œ"²UÝÊ*nÒBÚé3ÁÐÀÞ‘^N?[Œ°ty[ÖâHl\VH#»X{ÖhVzY ·‰FSüx4+>eû s0.r‚@½«¶Uÿg5éùl@ÄÈÏ‹3ÌóÙhJ¡„wL##µ#EGŒ»·³¬* Ce7É ÙQ‡aÇÛôéËq'¼þöÀ] à O 3ikô°HÑDJXn" h‘ÛpÏ8MUÊ9÷àcð¡Å”FT•E£É”È2„EÓ1d®±Œ­0MÏ¥…À±YaYÏ“^8ƨ¦éŽJ™hÁ(ahˆ”1¦Ï0Ob ÜÂÛ­‹+U•»e#š‹§„å”ÙF‘ŽmÅ$&¢#&27bÇžŽnɪjÜæ€#¾ð#œ¾ûn²°Ì¹qÍÒ `Ìm£hÊsÏ.‹¯EÎ3¥c€Lp¨—&Y;Ð\û×^n€PÚz1Üônh|nªUE>Íí·Ù•Ä•zgÌJYLÐË\Œ§ñnޝÕãlp¦©mï¸ëê?Þ×&ŽJÄrí˜x†HÑC¨vÌS&‹±Š_Ya”àÛ„˜™huJŒMfU;‡6¤´F©+pÐØC#ã+Á”¢q@ksVÒEIF Šú··Hb²F§!ÀèRjmÓsh–jS(J21ˆo\×Ißtí|dZŒðÏp~®2Wt=³£’¢Ñ½ ÿF,Ò$îÈù6ëרíòWÒwL YW‹ud(02·º‘L ðaœãí;¿å/ŒÑb‡ª0 ã›uLßj&sdž eÔ(”„£öFt#zJ%L&Öè(ÃñYeR‹Ï¥ïO²&j© C WUn|AO);ªNˆÜèí¬Tûs>”]D ˆÌ\c]¬„£ÿ°W΄8LJ ú~"æ€Ì¼ëh!&“•<¬“3q$‡þx¨Å»qhgíH™’^»À°Ê­–4|"µ7—x2U$Yà šU›w¤†)×›[¶)¥ÂQÀr +ç“ î;àx†ÝçrM»)Õ›Aþ½RÎ˵×%»H_<¸ö3»³‚ƒ`ıgª¡NŒc¾Ík6²I²˜F5sŒÞªÀpžãÝò\÷ý)à[’§Ñpß¼ö^°Ñe¼ß€4íÐ¥¤àŒ´¥8#ïÐØ’rÕÆu|N•A©EF¶[&]–­€ µ-£ÞŽ™  ¥”»~]d‹ª|Râû’8"«"7=ÛæÂ¶rû+ÿ HV^n³ø–£vd;ªb|0˜f禷e¶˜H‚<[ê"fNOè?`4/·L°^ïEàüµu!›ÞWih»Éµû¢sËòFÓ¨:&n‡FÈ3×n.ro]б•Ú°!ŒH©î"‘r Æu”7 nbßJ‘2[]² “5Š ›+ùß`È¡)]­ÑªŽÏ®½O¦”97d%½bJ¤£l™déû ö&OMx 8†µ·[>yÆÈ]–8\µ¡HW{®©”x¸Ï.ÿæµ¼Og\#zœZ¦dB©e™ œrƒ")sK&4"ü| |ÎH`ÊñYqÎ-±ODhiIÀã‹þrJ A­Z£ªh@°ÈöÖÀ³ÔHÀ0¾k¹‘UoO¤H# wd›!Œ.úUdÀ~*á†6ÅQ´\Üñõ/1õ·(GÑ*²¾fG0Ž¢.Ù6•rPªOš6èSQe²YaÊV–šÞ?Qî&í¦Ômõ6EÆ,È8gXoxã\²»Œ¤ñHa̳¥'À#•º¬,z„Ût. ôÏєϸŽCúzgŽÜWVÍ àÓh½ºðΰv‚@ûd˧Wr…–TòìJyæOÖžþ¼¶ Œ7Hf¥½#ÖË–ñ"ó¦ÇÈ)skœì¨1@3Œw”+ÉÎHV)i*•ûálvv#?uû÷ÁŽ¢§cØ"[¯†Ðí…ÍwÍ<‘|VjG9—·€vΪ”a%s 1sp$–ù¸T˜ÞÝóOÖÚôx™ Mb1ñöÁàé1gàž¬ŒTuqèÚ0ªíP#LðÜMKÊÇuÑ×ø´%Øþª>yžZêÚz«ê²C“`ßU|ιÁdá†æÌäÉwëµp5ð©«R÷ÅÚëqpU KòŽ51ÝD6‰‰5ÊédŒ‹‘5ÙÎB Ó7Ì1YyCiüGª3ÌŠL ßD9­ÂdµltÊmÂÄÕ-Sbò!Vj™0~ÎÓkWrÀ¹á×4º4ް ƒ{²µ#Ù¶* Ôkh‘[l¿OÇgËP„)9ØœF 12’U#rCêÚŽJ2Ü,GÿÌéçd÷ ô{XР˺ØÂÂk(ÝuNj„M<ŒLVϳ\Ëî´óÙq¶ÕªÝ…ƒ˜ùLò÷ªm…á& ;”ðdÇÖótù7H&«‘'@™›¬$èåÚé8ÒÓôYä?²6 d܈Ã4)cZcÿ?)‘æVU2Hî8ðÁ ó—E «fHéySÎP ’žR`| ÚJv‘Ú•(¥v(M¬Ñ¤ƒ…ƹÕBy Î¥2¯ „™lV÷ÅcÚ˜+y‡f±™Ì?ú.Òãªý|ñ$pº‹l.%¸ÅWrlHôÃ¥&82GunK¹ ØMdÑfHvŽÛ ŽjìØ£%æ3`4¥Ú>gŒÈ\)O¥4JQÕVª<ÇÓ(õpí¦”X¦éȹ Ÿ>­Z#eb²^È–„ÆL‡±¿ÜQ‰àèîòfä?qú™¨ ]˜ö-›Tñ2ŒŠ•ª"õj ¤¡ï: ûEœƒã¾ pkgÒ2Y¥Á´ñîÅœ@/·'P¯n´Rz€‰7]y:âE-Ú•0üa ²mY±MpÚî’ÙvëZe²&š’ £‹'Cz% KµŒ£0Nö ¤Ì$7íH¥z‘)#}:µ°Ê3²Íù´‰þ¶¾îÛ]Z@®D£~êU¹á‘°Æç&Z:6×wC{Ó1….ˆéYñìS#À¿î?ñ-£ ݽ÷Ä\ËS­}WT®×¸Ú# üÌsÃàÓh„yF: GUb@-#ãË€*±…sH¬Ú²R]€Fzd;¤ARÚÁ;×Þ¶.2ŒÆ>‚ÚÓÀÍÍÙŒj¤èˆOàØÄJçÿ@5 0Þ1¬SRXVr¤éŽ@ú6+c¥#±ØG2äÿléEð"%ÐD-°ìÈ¡gêÅ'ÆÀ9äÚeíJFo±%AC>yMI܇—¡–Ž3§Ñ˜žF8’ÙGä‰!n‡ze¼–Äd}ðdµÈT˵#…ÆòzxÁÇžþ¶‚ì=û³3$7G˜F~º%ÃTÚ†€ÀËi™à Õ’ÙoF¼ _K¶edúÂQ©Àµ³í¨¥}ª~ÏöWTG9[`ÑnnÝS°e²GÈ ©QôÔŽÚ½U1ÂÃêÊJv$Hon[9"á@ƒ²Â“‰ŽYb ½£q-c ªœHÖ¬”Ž5NìˆTS¯Œo4  Vr);àÉjL#«bÆW•±#¥ÑþÈL¿#rn±&&ƳZ`-²M‘ó‡ée8çF`süJŽøöi%úù;†e¼O¼%ñMwLS×feû$É|!MôªÆÁh ¬ÔV0²²)=BÌi¾ÓPY ²%_ÿ- `î•éå¥:ˆìYÅ»·Ÿ˜¶ê]é5¾=d—qn.ÇrãªÚ‹QrôÁž@˜fÁ@ÎÀ³¤wú‚`á.¸R oœù@;ØŠmÎJmkVã2œ`‹% ¾UþZ¥•HÊÌ«ÎÄQ©ªƒ`àrǼ×Ö‹q$в}瘠.íB#¥hzÛš+”+ÕE ‹Õ<}Û9‡ô9#a1‚Öˆß2 äÜÈÚÌD² U1ªr?Až´•äÌËÚ¹©úáîRãS‰éÈ^8Ê»TkqP"–Ÿ8#°ëئËÝ=%ŸºRʆŠ c¥ê8¬ªK¾sNUI>m·q—µƒØŸÁdÙnßIÇøÍjâÈ€ö”Ó7NÕ½ø Ý€‚€'’ sŒ=UûÜ·3·nJ Ë[{GŒÐ«‹ÜrÞ,Ç”z1ùD&kù¶Â /–³.¼˜§ýE1\µÜ kó©”©Z/íÆxS0ŸLž]Jxš&ª"b%ÕÚ«ÊJY¯¡­š ÜÑP¡%ÎmzG&9ÚÓã…£F ‡@$±#62@IDAT±£xšyí ¢ñ2€ÛD ÆQ# ¼)H¡‰Ì<\&8ÿ·€²(·Í\€­7ƒ²ñ@‚³û½dëÆW’ w Užô€hËù´eCŸÕ0q£éÈZž+á«V".,lÕFSb|½tyb‘,óœÛ#T妫/#¾’£Põ)Ê6ql ‘”µX +²€ÜÑpèï­™Žïç0‡LèEL³f¸jæÉà­'PbnOSt ¼?;Î퓹#± ¤é¨¥j£áÀµyyj!^KG™X̶RˤQªª—mÇüaz¼ÜæZD2|8ЕPÒE©š§ c„j¯Ýǵä™,R—ép¶pΔE†­ñl¤Lœ>s-}Ü”µ´¾q¹MŒL™s;h0µ‹AÐ#G6&3¨RJÿ‚Â>Ï‹ÀÖî?íH\• ž‰v½HŒÌ³#ÜhLÿ Û 2|ÓË9 V¢)Dæ•bR6‚?¼–”pkh)ðH8öt]Ȭ«Ê"Ã@—¡˜[c ¤l+¥}-|ˆaÐez&åJ°Xìç—¾Yù XÍPrÙO?p—a!R”cLÒƒñ©?oÛ`-¹‹w?+¼ïãh„Ü­²uâÃôd%‹a”z –„«&#ÀÈ}M2%]"%Àmå8¬×±ôjÜn#äISpÆ7º•0J›hGn‘eJ>°œ`_ôm¨ä¿¡´’jÄæ ˜¬ËV¥¬Ä¤®,”Hkø(õý¡ÂÊÂ=‹ggHÖ%2ÑÏ<2+í4ðrS0}£ð gR—#ÏÄ9ï¨ÅSä ²ö„’´„·gÁC`4LC‰TÏ\éXßHF©‹e]U‘á8s2G$ ïè6qÓŸ&d}èm»5øøD:¶jæ2²eôn«Þa‹ÑÝòZ8ÔÞ¶Ì 0…£hÏ”eß-}%hÞ×@ny¥§ÿ–ÁçÖ³(1ŒÄ[R`8ôÎùÔãÓ7Ú± LdëÉ“ŽÝš!eæH Ô»žÙˆªÎÓÚŽ«Æ1¬½|kÆÁ…FÑVùhtl: 1®˜Üä‰{4 ™¬]  7èÈ$fU&矰‰Ö ÏHÛÖê>޿ɖHæH&–- ã)?KÏ)ºT@ßM< Ý=åŽÍJ/wí6©Ë |Ó[X>ËÝgЇ‘BKL†ðœ›‹!†_z?œÇèñ¤¯™›# e?$µgu»_œØg_Uc¹/v«bÒÀ‘ø‘Ž~8§¯‹I²2=@C ÷ÛßоO•uÊæ:ѳjè<‰ÉäÚñŽUk)¬1½ì­šN_K&{ä¶Ú@#¶jÓÛ©‹@øžô_alŠh–¬‘¬)O2¥RkW‚‹éÍ‘gÞý8½b&°çUʫڹµ1¶eåî°€+¬4æl"¥RŸr2xÎ h>ºb2™¾HŒÞ~Ň•j‘ ê­—tlÊ¢­ŽzûRmP+‘û§‚J2Q©»È}?uUÕ%æÖ¸ž¨R½ŒªF&é 2qŒé©½–4ª)eiO>4pÕ”ÓÔbáMìPWJ>&ÍÚcš¢¥jŽüg ;#9'(cTE%ß Ê×_ÿ±\üÛ`’h¹ÙaÈZEvÌÅC¤éEhj|V÷úm Ógh!‚­›ñ4­Þ )«*]‰ ¡4vÀ;v£Ì9×… ;dõÂmU/Þ¾—xoÝûèM£*8Ë~ZÚ92[¸Öå¶d›·1î ††:öÑ0äOàØž â •ìC˜ÿwhºÚnJF숷؜¢—1¨1lL€Äȶ`múöÈš dßÜm¥ ›$è©×Þzö²Yô[¦‰Ž{±pwï÷Fð‘éµ›%›…ôÆŒ'K\£^ŒÑ­×&10 XlÛÚóAHÐØJæŠvμ=•rX—¾3Û9YØ €L o±üsõöe˼/3F#±ªF¥<¼j;;vG %±’£¨Åцp;$`‚‡ëª¥gW"–­‰cb ¼ÑwÚë/ÆÈÄ2+³º&€l ÎëE6EfÒd‚Fž•’ÑŽÆ·ÐzÊd=¸™X¨v»l1U;jIã˜OzÏxšß?}Æu/ƒ„.?Å2ÜËÄzó‘GMßr{e ]Óµ«æúsìqW;“žÛ +•ód²7¢7®…²ÅÃbž5Î?Þ‘’Þ—“Þî«vü2`)sk·à/l˜ÌQIõðU¯éÀ°Š'ÓÛQîîþÞäCê¡rVbg®ŠëÅ»¦_âHƒšÎ AÈþ?úº»ª ·OžÝH{÷mI¤ebr“}ÃTÛ'=\¨f ´^GU]ý;+˜aÖ(óTõ ž¥ªFÀá˜yÇp$,ð€Fí07™2OXì"H8M³T½áGüé¹Ï¼¹&æãØV}«f.Ϥ®Žõ² X0$ÀÀñŽF;Æ3Á÷qoÃÖ˜&ß(-pÇ^I/¡F ˜¦AÈ~]âk¿’ƒ…jJ-L,€4òÍОù×V=;€ì›CÃ!ÏmH€w¬W•†ÞíLœ@™&™܈’^µL@6 .á܆M7å)Prä¼  LÜÚÖHxû|ôdíÖǬäVʧUa@Ô"ÛI‰ä!fsÏÿ@Ö·ñÕ‰Ñ#rï) :–çõä5v”kŸÌ>¦÷õe¶2·4Z¼Ë)¿£cÓ[’2ç$z ºg>ŽÄ°hŸ9`4jÙÒ óÏ– c2æZ£Oœ¡#àK£ø:æƒ×(×è“c˜ç¦„‰sãS£P™gnöëÝF¡ë}júê iðØ>u©*¹õÖÈꌼ-í3,ð²¹r†s>å+Àhá€+É0¨ ³’2­#ßrr{bŒhÔ¦`\éjÜà«:³æ†áShJ¶^o‚$à³ÑÍÂàÓÏS)YÕ&Ö»ÜÐJéùtltúª°Æ®Ÿ ÝT;*=v‹Ì™T’[RÉ?ç&›žÆÅ»;Sï–¬½L6+³>ø·Þž([Ñeuùn;c(›X¾[;ŠJmÒñéó4®jƒºQ ´ŸZÎmß?V’LhÄ‹Æ×NÌŸ¸ò×OÇZMÁ¤iG³äFpƒ—)ûìÒ86‰ýLö7’Ì4«|v22;À)0¤²ˆäÛl€8k¹ ŨöÖ寧 ñ4Àd=eä™t aƒ1+‚¬èž™dâØ‚#³Ò…/bà6qŒOF‰/`ûz!ë}×__P¤ [F©¿SwqÎøœûÜ+ô|³Å[©eªÂü= lÄ®¦¯Jù!Æ71ÛÈÆÑçÖÃ")aþ¦4‰1{Ø>ÇvPÅg.#u1aå¨*æ7«AiTÍÊ ²»„ŸU|ã2w¤yŠÃãɶÒ›wAC·^¦ly q«v#¼A½@U¹À«öifÛÚ[Œs%ídºmDØ1s ¾H6F•LdEC chê•kϪ˜ü)ÓxOzásÔ‹ßbæ‰'Cjéß98Âø¬é S\ èHŸ[VªŽÞ!ó4ÄÛ„ILP££x3Qš^{J½¡دî[ÅÚ6‡Ö‹ï[²ðÚó§òiÛ¦—)3¤Ö»q˜¬>‰a>•z¢QºQš# ì"Uc(E¶7â)cdL¯zþ ”8ï="¤©@Ïšæ©„‹Ûú)µkJÐ{µGG‚âŒÑÙÒ‘Ý_‹êL½¢–²^Œ»zuµ0ÆWÁQ—Hè™ËdÓ¨êåÖ“ Ýn{º|øï:|‚@oÎᑵŎ€Þ¦t‚ŽUÅÐtl=G MˆALß”œe×Iƒ0®Eµ×pJiàÜ002Po&rÏ…'«€•˜ÈöÌds;–7ñ9ržY-¦*`Õ–|¶Pª–Ó¨:Ê–ñ÷&[ùɧ©½*âd@+¹;œžXã†v¬úeê3tås&Ì{^GAÏß»Æ1HËw”[©£¹­Äg%‚¬j4W ^c‚nʹŒL™8}%LþvókIIЭÛÖqkÓT—‘FTj4†dÈr»É1<Ôî”Û ¦„#뚉^³„ªPÅÈpn¾µ#Å‘ÞHf $(Ïá)3«£¬«œg8«v»œkLŒ­ ¬´Ñ ²yúø&žß¼n%û´fÃhšoûÚmd<}Ñ<½Ï.˜¬$k à{c2‹r 诘¾LûâjÙeÚPæ@I#BµáÙ:¶!Û¦·ŒFkÙÇÜ 0}-azV·ï¤;íÕ›YýKá|ˆµ¯Tˇö ¸Á â#´»—µ•˜´ >å3wA%²”-`²¹ÚEšvÈVŽTÅko¢#Œa…¡9ýoßÇpgðã·‰•er¾’óà;]¨%[ƒ4R¶[1”"~sG‘lB{9«VŠŒ‘]côÒ‘Iº,‰É|%û䆄…ÞþyÜ?#"Ý‹ ”y.7º^ ¤tÈDïÓ”Žý×êûI¡¬ÄÊzèýËÍEÄèëšy]xŒÈ°¹µ œÄßgb$€×Øò2Po]œ·XSÛDoX/nÏŽaЈÖKƧJ¥yÆsh+UŒ¼pô)hä¬1sU-"Ð-à9+5‹mšªÜbòu: TÕì¹ÉämÞЉµTÒ‚T°Ð èëwÞ¨e5ÒfSP×9¦ß¤Ñ›±ÃÀÈºš´¥ R*ó)cz\ >†HA0ñi»¯Ãß•|*díÐ22J@fKÙ˜Žñå6©EÎ6°#Ò”<™„S ´°­´ÄdJ­AfRËS·RPªæISn¬«&[-í¯mðëÆ,]zé᎙¬%žã{Õd2«V5³@:晜Oõ²BvYhÄÓkoÃ4²?øiº äFÀZš(/2©‹LËÄJa¶6é(´Ãd¹©Ú6±l¢\ SÂe¥€AÈ~^Â<“uµ2±6lI‘~€§ªGØb_ Ù8¹Vgž†aoÒn2ý^ÕQPæ }ôñ©Ò°"Œdñå>âzŸ×a؆dñz™;ÆkiLßd]ÄxOŸ¬ÔzUÁÇÀó1"%Œ‰Ì¾ö'‘k‡6ˆ²ÇdËÇñúŒšž•#Ç?cÞoþ_ƒ—‰ÿшèe| äæh7ŒXK%b½²Ø”É”Î7»:åÞÓ¯- qO/[¯’ß¼ø¶àXµu>í§Ê‡@4·wL4B/½ÜÞ4¦``¼¬„±‰–~ƒ‹ªþ§v—‚Û Cé˜mJ™yÏ~åÑ´^«C/hÄ6„#ÉÒ÷—>GV¹%>Ûßýé1ðZ2^lí¬ÝñÚ¼~{â÷]çCC,>ûì3G€@´­ãõ;iJs[¸7¡L&+9îŸÆrÓ‹T²&Ò€ƒêxAT%.4êzJ,ãi´œåÞ¿qµ£Ë‡ÏÈŽU€ Pf5g ç¾'ŽÄ형²0lUﯲ*²^ƒöMË*Õ>¤k¶X†åÕô ɘOj³¼o¯F€Ó’@Çvã‰×…Ïß±O$2ý‡•hÒ[›ªLïÁ8GVm§ÔR8 X‹¬Åqþºº‡Èüã³mÃ|˜<‡Rºx›èÍœÀÏÇ1lŠ`ë( Ǫµ‡Uܱ­`o\²}äø+Ý.^žCâ4×þøÀ²åv“c\H6q ?[`‘OSÂcö7{RÚ_‰Rœ›è÷z¥ó@Öçp‡m $`mÛÞ€>ãuѨҸÌ0dSŸ†dd‘yÕü{eÎB5A¥ŽrúfñoŠ#P{·˜=œL{üªÖ Ð.7B‰­ã‚¡Rwɪ.žçñÉy :ÊŽ¢…ÛÊѬvKc¢/7¾ödÛçôß²6úxüþ[Úãí u„#e ¨Rú”Y¥ìúdŽpzbÓ‡…A™˜¡P¢”ÒA€q¬K®OÔeÐ¥ÏQÀ¬€3ò:ÈwàëkCП̑ÉsŠ5Z ù\»Až´ ·Fì.HÌ^ ®²F€0]ĵt,§ïFÖÀÛÏÏ¢š•ÅšÞJ¬È”º#ÒQæS{æM$3( (u_8ó–'”d|þ5ÊÏ 4Óô¹^%G@ʰ#¥®ÖkJbz§/׈L?1½è l÷å™ 0ˆ̬ 9gHn L“²v؈å3ò~¾µcjG6WHLïFjA:ÂMqü4-,‹ÌÛíøÞUǬôò1¥ßŽJÝWûÌÉ„ªŒý#ilSå6FÔsÖ¹O‰œ¯Á™Ž¤¡' HïWRÎÑ­ú!'˜ƒÑ02«+?z@I ІݼúKaòÜÓï8ë5‘ A4VùÈŽLRö)"cÙ*a´0y+I̪×yÖ¹p3+Œ^™§Üb=]w·@`¤œmÛjw̶Fnr÷‚‰[¾µé‹Z¦ÑØjÎÈyÂ9$sDÂÝ‚[GCɲ͓C-Ä>šÆu¤lÿXV¯®]€™I‡ƒ˜µ´@]J‘2LÃh[@´Xíø¦g[Unzž+9º…’‹´¥*¾qJ1rªR:š’'¦ˆ'ó5ÆÈ sÀÃ4Ú#ñÖòZ öôí£T¤T¢y~èãU1O@¯´Ø°WÅ=x¹cüfñQuä¬rÆäÙ†MÌ¼Òøua”¬°?rß™ÖhY·3BÔE©Q»oÚ¬¶<^b%O™[bXÀ4{‡4µpÖè(jI¦ä ÷ï!®êü¨²íFJù$v}Õ|dÇùÀÚûôJ•ÂßøÕ¯~¥A4+²n ¨g¦‘ºb¬^»1 «&fÛÃÉgÞH ‡3ø~üôÅ[õúÑÀU·Ò‡JSZÀ‘Oþ-€$‰±%|›«&N¦J¹J˜xØb;†éE+µFû÷h+õ;NɬÄ<HàŒé©™‹µhܰ.æiðg‰ûÍV8ÈíÏ™Ø>€ñµÇwúßß] ÅS:êÚè'¶$®ôJŽ0Þ¬z{J%L]4-ÙEKÊ‚^Ì?Üx€ ¡‘ËÕgWO¡Qàë­½cæFišUÞ/Ðõ’ †}‚aþ¢ »2†¸‰L„cŸBKÚ;äIà­ôª GbÇž…[z9db º‹‹×›¾ö´Óä ÷ÙuTʧlænÔ±ÆòYñ.Y AŒAÏ…’ÜÐpzY»Ñõ:¶Æ—Ý´S–›X—ÏÅ’]Pbå8ÿÆáMlŸ­Eiëiq$5ª@ß^üöIì¸Pmh°FUÂnkËŽñÈœc”Díý½Ó±Uéñm›…ίqO§€Óù’)ÁÈ èníšÅmz%úòìÄ•­«…?·&ÊJý™†¤'µË0RÕ)Gæç ( |€CoÄCT-w¬j“­AŒÔÞ59Ó7¥[L—ʤg{Nðéž’•#“œŒ¬Ô>nÉŒoeÛ’µFÐÓ$ƒ•âÉ#„µ•b(1ùÃÏϽ;¶yÎ9à90gÒ½Ã9W:“ÞÿÛ*F»q‚Œ„kLjvCÚÀ¾ÐmKÌâ45¶a˜€ÌD]ÝBVÚ”HG²0¥®>ÍvÀï‹Ô­³ÍF 2>B—,IyþÿøÔB­ß¶QŠœ€”Z¹öãrC• ¨vmÛ#û-ÙKq£‘ûÚå“s¶p¥¶gU‹¼Ñdpãâ+eˆ1:Á˜.b.C[y@u>@šz•L!Ëfå– ¶<CJ<‡ªíVoW£TkTŽr³.÷º,^DfbJKf¥Ô8¶[¤%1®œ¦Ñ‘L|.xQ×nÚrÖâØ­JÆ¡5ÖK\àïʯ*·ƒP¢ÄûXa ä©%ŸÖƒ-FF «^Ó¢$È*áa·s$K\Æç@4õÒ»f¶Æðj±pJ%ÁD’Þ±€F(‰Ú‘áËM:fBÃDN–&9Ûýj6+= cXZCyÁßú[Óò âa½&‰¬ä¨^Âíܸv½[@¾=ߦ“Ú¸ræ>`Q©®Zrëv˜žˆFZf8¥#Ðþ›[WbÛ¶0’Ød™tln;¬Ñq?J¾¢”cêÕ-T{„7—ÀDL‚§l^ w¼ô«dh³‘Ræß&vNp~1iR&"O÷í¯nL^.ÌèJÎ 8YÖ”]ÌÈ4ª@G%G˜ÚåF¤÷«•*±Òª@ëU‚Ü­𠀿†Ø3!ázàkgÛGkz ÜÛaŠL¬T5Šle˜†­•ÎÔô­ÊÀq9q‚z3o&RŽšâ‚{ZÃ뉷ÀÓêiH&Ú¿@òt´µjÇpï „d[®‘“[]µ$†3Ô¢úÍo~Ó[Égéÿüç?a¥˜|zØlc<]¯—2·9›"ñ·g$O·CnÆD:"는…ú–8&ÛiŽbûû8b(͵s¿(»™#C²ÞœO]íßMg§®özÚ›¸qô}Xkoº.‘¸MäÞĸ¦äï˜ YWÙ‘•’µ[•ƒRûãašŽ4b†•bksŠõVm%Ǧ$sä zÿžÑ‘`/ÌMµëׂ!H¦‰˜F ;Ú n(C]x + Í“=K°à™ ,ž›hïî4ÄŽd·ï¤>M%]ã7:Ãö!¦©/’e«D–Û±­l3äFŠî¬ QIé8²Uvìݱ¨Wö^º|U9+ WàJdÁ ð;iu¹ ‡ešºd8ì¸Ûâ¦Ñö²Ýè¯äŒã©_; ‹ÀªºklÊu:¤£ÞÌ)Ÿ¡% =™¦²MLÃáYM†iôrwïñU·[ ðií@Ó½XϘ†Uw¬×Ñ·¿c£7ÑãÓ›óvTÛ_ÎÖž`Œ–oûÛßúÖ·üö‡{]Å?þñßüæ7Ÿþ3e¦¤¢ûiK}=©PÝ SÎN/q&a9s£É2 g+ËFÇËõ.÷«§0Tí†U™ÔÅ^õú@Û¦d•,VU"1ŽÈ”õ&“uÕ8Ïô³Åó‘Û§¬Š¡ü¾a.h¨–l (…¤ã¹ÌÝ Içïè§”ÕëªÓ\”¢A^8r½J9P”´; z¤h¥§XÕ¸œ ÜÈVþ¾ÿï|ǯ§ÛôoÒçŸNéÿ¶¨v½°Y}‹ú—M¯3Mׇq½x²nª–g›9Ûª²’Y~ƒô¹e‹×›&‡ s¤Tb˜J%;  baÆZð@n@[Yƒ€?ƽ€ÆÄÏ.bD hAÊ—‰LOÃ6“üYÑ+>¦¬,£ŠGjñÑiiœj³Ã4·éÌÆÀ6þ\ÑK,('Þu2©‹¯gÚÉz.̦Ž1 sn7U9öAN hŸ†¬ã˜¶’…ö¢Ãø3#_í+Y¦Y‰ÙjÈ€‰Z„R¹ÑF©Š˜Zhð˜x9™µ?ˆ!>ßK‡vê¹¼ŒivbÇF:£û³íÃÛ0<Íôµ'@{#2ш¶l.¦HÌÏç9…Þ÷ F©ªç6Bo|ænn"f7Å; ]-3¦¹x€¿2˜Ì>î ëôÃYµ[øhS²Í¹­tuÕëñú35OÊ>$í­ZÆp½OS"Ç%•, 4ݸ€Pv0+ú€ëBµA2Œ©K‹71·—Qây;^¿a­J)·p²›ïj/ŸÆåà3õAðAZ 5”„£®ÈÖèv)÷2þÔq)¹ÿ2•Æü¿¼†v³þö·¿ýå/éÿÌuþ==OŸQŒ¹T Ü]^û´^kÈŽ ™4T‹Æ¾m³M{ê˜Ú³JÐËÓ8Æœ î›!4Æ·Ìœß× SIV’·Õuzý_°¨‘¡‰û’ô™æPÌYð!æÐ8]ŽÝK)A%¼ª£ÏW æŒç >‰á£ÉÚ3Yí]¤eêí²Z|²4Èç5gž¿Lÿ\µA‘­é°AÓïï.<#ù2ÌnÚ-øçi" 7¥diäñ‰³Íp›OÌ æ¬KÓ´$[” ^ÿ¶±N À€ð£’®c|^ÓOÜÇ6ÏÐìEŽΰÞõnÖ|8ˆŽ­DƒézµÌ0™c@æ| ^ÿç•:–«2œ,¬—zšÔetþŽÍªkêhÄ´§/´/™£FßÂZh˜¨2‰wª‘žEc$ ³UU‰‘YUÅw¾Ü^LK‹Ñë5Ë$P£#Œií@K6¢#ÿ‡ß¹–ߥ×n®¦´­z‚¸wö5úáß5ù¥Ï$òk³G ßýîwÿçF¶F›¥#xnÛ˜­Gc yŒ^A†ï‚>G¤€Ì'%÷±çÚƒ¾é³åF +e «Êº€v IÀ9|O1C"žl‚Ví²øÙÂÏ/X«Ê‚†•,šÞbÉhª2'hz¥U|w ¨Öezúª”Ýݱè1x²<1®ìÉÔhÙ1Yž{“ªÈ”ŽœÛÆr]@½JaÕýTb"úlª¬Ú-U‘ÚGoØ kyþëdû-tþn¨3u¢ì¼ÂÈxYÐ7>ÀÚדµLã¨7‹g#,òoï@&V‚»C½•Ìj·nµYª òyޣɇ'L ÑËëõm-Óù$Òd"Ãz‰5ÊSjÔÕôôM1‘Lªå¦Äëòy´XÙÜdgÑþg_Žª Õ‹Ï ø;©éÖsdÁM´¿LÖèÿ[6qð^ ¹’¡›rÕ¾Žv˜˜C>žôï7÷žùÀ"\ã3Ó»` àß#ù½ï?iðKü¿¹¯—üñìÏßýîw6g%¬á‚w£ó‰ÓÀíl4œ&êé¹ož ÖÞ­YÝâë‹ÁÄ¥H2Œp»Üºf>•Lé1ÙÒ 1{´˜ÄF8¶%kIܸ”ªŽ~kvƒuqæ Rf¥W „[F£ˆ)kW‚[&¨‘![G$œ²vÇe¤°¥–)óAJ€ªµMt…nÑtUß:% à‡ÓÈ<e‘Œ~‚üka¤†‘x÷€Ú5ÙÖ• c·^€I9~2u©=Þ#r؈smc°jÔ Ý_ö.‚˜Í¦Ü€Œ`¾®—¾Ë”3ÈÚÎpOÓJHÁA6t€^´0€oO²6Ùs';.·”L#n7%ß~x{*1ÁȪûØüÅ\_Ë3#í +Χ›ò­A߬é*’½OçúEæªý¢wö÷÷3œynÌ¿:øäl·÷óùÂ1ÝÌ9GV21#LÙ‹m ¿yýÎõV9û£Ë?÷bd‚¬õú˜(¤A½*¦MRÂñºÌÝCJ¦J‘̶ü½ï}Ϙªÿ}öÀÏþsÿÑ´ýs»_ié®às±¤û¶[%«ªÖ¢ ¨"{½.¥¥R•Œ'««¡L®C¼×î1e]‰éŸ€œØg¤ÑÑP† úáèé>ø?ô½¿wøõ¯Í¡Fžø'öjnŽx»Á¬`@ŒìöÓŸþ” ¯JùÜ!¼MþøÇ?~ñÅ‘-£˜-°;ÚÓäøôl¥ö©š‰’#>ÿ§gØ’4fAßоŽ=’ÆQKW–{7|ïÓW¨£L©WîvÃäÃ5+Éb‹š(ë•‘"Ÿó/%¬%rì!”¹4/¹¯ ÙA¦º¼¿JPÆ+!çŸs%è}ÍrôÄl-zŽ4le]U”Ù²¢ï¥dÕ¢^ÕJ€_UÝ.†ÀpkŠFži`[É…õüR“U5j©ÄIàhÝ®U[II£#%@ÜzøÝ. °_áØnª_LÌålœ\ÄÀí ··ôü…#^˜î{â¦Ý1ªM„ß¶~Eö«ß¸ýõ¯õ†_jýö÷,L”„¡&‚˜ÏÈJ<•`Ù4-™ Cd8Ù÷¿ÿ}¿¿lÈð”6k§é}ʾ{öýèG¿ýíoÉøð”íév´§WÊÜÝÝÚ†x£“Jã²Zôv¯ÜºHz¥<» AA“O@ÆcÈ2tä)Û!’Fi˜s]r_`íôVrÁüàxÌׯþð-­·mã Ï òvÛbþúò‡øoWò_óMãY5C±é-†±³[ %…±’¨%>«z3iùñµ8²õÉv;™Ø&"@à<}š•OÕ&böŒÛ!ß2ãð€XoG¤j<òªN‹^ǀƒ¢ûZI¼~ÏnFŽDzž‘@¶_ßf€€¯ì²^7ƒ ©v2)˜ Ðö™'†{Ãjšf=n•ˆùÜ»œ“¾.#ÒËY™ô˜ŒFckÈÉjìvü3¡og¹•ÖÕŽZ¸ùù§1DíÛgSÆt5$=ìß`ø«Ðni¾:›åš}á,c7áØk×ëh„j[1/Úsâè7B%›ãuYFF²òå¶žÇâWÏ…ôKߤgNßõõRÊ êí)0€AÈla‹­}%½‰)EËëuAåßÔ‹­A,ÜÔ/+ù·J”}4òáàüá ‰ÿ“ì²þ²É­[h±gíÙüñ}šÍ2ެ0°5­¤7Rî5´wÁFÀ4½‰.W&êÚ;·U&}Ê¡]oíĆr”ˆ ÇŸüä'˜®óÕÙG,v)Ma+3ß’F‰a#`&]ã(|޾Q_½@U¿ÿýïe]-ƒwqV®ŒwÌè¹Ó"Ÿ²Í÷Î[ønt>/âVuµí¬e˜ f¢ fUä&ýPÐÄïŽ> ~ê[;-|ºTûP:ÆÀM!³®3ø~I†•0ü14âüדÀŽBƈ^ˆÑFsÏ·ùØ¿wê]ˆ½K¶ªôJÄJx &çö@n 7OL&¨²m“Jòº¡±›B°Í1½K>+$&CdSÚ<$™WKF?™¹p›DòÌP‹ö|ÜÀcdAœžƒßA~Õºx€R$øŠÌ„›¯»Ìß<ÂQ¶ƒÆ¶Œ ¶O{2ä­çð© &ÐÕû;¶ +تý·øxJ¿þüç?ûm[£¬¯Å>ü#1Žk4‘,¥\#YCUÃÉXÅh¼›_âþK¥º2”™ûoïØG†Óš†`PšŸýìgþ$Xï××HÆ6óð¹Àã×Ë:ÚÜ,JØuº8²^í%ÇvAúü5: ›Ã”‚ 㘘¶I$%\U>ÍïÒ®ª‘Fì’Vó×å(jr¨Ú‘Ûø]©Äy-1̼­ºÚÝâ\P©}äÍmç"D׋w”¹‰nj"¦Ä;¶°ü¿”ÝMv+Ë­„Ñ9¸ã†ÿæ?,7®^ƒ×ÛY§Ì#Q|hÀÈ@ €Ì*)Jç:áÃã@<¶ˆóÿß'¾ Á\BRµ®Ÿa6˜Œ>ñpK#Ý­Ùàæ„7¹%‘éÀeéÈÒ# ìYÙŸðãT"åØKq: CBZ¢YÒ,/¤¦ÄrÊå˜áÍܣߧÅj—òÜ÷GDGáô“­5<²¥‘|­ÿüãóŸôµ‹MµØÀ†Ñn]ÚÂËIª‚·/%ÈMØ`eÍ&5\PIʵè(:±Uhv«‚xýbºgxYµ  Ð¦>ìþç?ÿ!BPy“SÓe×— qžÕ³MÀ•´‘N Í-öåOÏÈ{󳻎âÅͦ(šg`ˆváÍo6ç›J!³Œ€¯–/Õ^è”UŽÃÊV+v8 Ã뛎B_àÅ+JG\IK±Ú‰[f•ðÌ´ Pê®Ó$ÑxG}^Û )TMê–bx{#ŠÆ7ÙUtŽÉ’â•à§ UŒÙ™ª•ªK^ $â¥+F“JS¬—eüÆÆA– ä1ù&—µäeåÝ•Ѯ䯇 Ðs-&O­mÖ­×[KÞ„jWâºztzÐø¢¡ÉqÞ}/¶¾F7vK%º4¶íhAm‚MÂ+aF+)k)ØÆ©…óhöØ hbxZókwØ`ûD,U9ÁTÓ*L6A  ƒ ±®»¾LŠE6-©h¾èÿÓŸþtF¡Gÿý}˜&©–DTñpjpÞ{ÀßÿþwEü£F¹©±”dᬾ»]Ûf©h6h©êÒxÜB †GÊüìÎQÒᔵԨ­y ]wÊ‚¼ ‚9ÅYú~·AœÂÖM›œÈJ\JÊO”mËíÑRS)¡ÀíQŒã›÷ØßȾüQK°CÐ1©6bYyjj6©…X ®œEn6/RHL¸ÙÔBð+©‘XvXž-=˜ ZÒIJœˆ«Ð$p æÄ5ªp„ƒ¥o)`Ñ—üãkà‚‹{Èh|:ÚµÁ¹š¬)y¹æˆ$‹S¥öIHÁ‘yZ<Ü HsäeëRÓ6£ ŸOV6šòbK –MÀʦ#®àlìù:§Ìzš ´«*O¹ZžY´‹RJ’Hµ,@R2ð8ÿjFÊ^‡=ñ}Im9©¿ô •3Ï}ï…‡Ù… ^;{È –ødMk)æñÃóÈ…ó(OAm @ÙbxŲφ^–/ÃëÒ_Çã0%̹),„…ðõj/á!—Ìqk4¤rÞ~ñYÕTuÉ;(_JøjÞR9šZâ‚bK'ö"®/ŽÃ‘ú÷¿ÿí» ä»ì—1N±…uifjJà5­¼Ë¡‹lðÕJ)d`ÊÕZ2)"jÅ’,K¹Â:¦OÈ3üRø@K§$Hm‡£µ/>ü ÙA‘¢™ŽH­¦:ÊšvYeyL¬{ÕcÆàKYús[4ÈæÞóá#ñŠB})xY»Ó,‰Cø˜‚æYÓ«è|r2fd“ xx›õÚDPUkU)²ã@šA 5K§¦µj)P$R¹FZO-¯°MñøAAÀpÄp »Rð ùó®hܨbl¦YZb$K-@„Lf©S¸YeÙäúC ©4 †¨R›ŽF ­€o˜Jp,I¥#`RÍÖ5ƒÂZ§Z± ©¥L­%ZãM'‘¼í÷óÚ@‚Ôú½¨•{ý¾‹Ñ^â¤ú¤ï)&@0 ¼1xï”ÂÅ›¿K[•Jd5#yb¶5L ²é#Ðl§–Ê-mÍ£áå;)æc Ï_^]"på ™8¼•ÀcvÑÝ‹?…汄«õVêÑÿò¨¢ãS?CÀ¬]-ò—ê)ŸÐ9 êâ§Ï?UÄãÛÝ A &hGš¦Ó±ˆCôdjeÕº¸œÈD" uMê(h#øl˶)U¶Ï1À4V£˜NÕ·.á?zOï"nBU0'£\ß@|ཀྵýZöU[‰1^Þ׿›Ç ®¸BÊ5˜§^5R[ÀK!01ë¸móž‚{ÉD3ØRüvZ|ØFâÜ·¼QM˜¾òð—.ÉbÊŠËn©p&ëÞ@c@°dÇãLD¬0òyca.‰µfL [ü ^·øîT “%'Àç5k¦R–|jÅ–MY;LËt¶%ü@YÖ²– ù f”áîuq½²p ÄlD6j#U¾Öøâ–éÜ[+—âK¹w}Ì÷õ¿©7¦»[9k°>ïW®—yŠ›¼! šÞ±7Âfó€Àd8¼«Ù q:®&W(Àᯢó¦ïQèk–ºß·€ï³¶_öÖQ >YP µÝ$@ž&ZËÞÂùmD–MJܨ ãÝèeßûªþÍÀ³Kæ×§-"Í#èM«Öh÷€”kÇ*ÿÎûà©ÊÙïr òxðóÍ¿T»ÃWØe2XÛOjû dÝ*…w…+yÀeµëú¶k ·|ù&­á¿ôÎÙ/WÔʶÛgC€–í®ñòv±™Û‘kÑJ¼p\â/û¾€J¼Q&¢Ýøý6®J—& ¸ ôX6íÄ-W‚ÐÒØ4‘uÉ B».–²TÒ²CHm²•ðpdÊRæéº+´d‚ q¢-%«¼í 1 y&…€,Èò:öܨu æãY¿*›5 ÛÀÓ(f¦u¤™T»Ò¾Ú ¥bR¨Y¹¾J¤,™@¶.8Í®Ãâ 6À™æÚ$…::Y»½¸ÇÉÖ=åðâBj­#PI}¥,)[ž6ÏCà>@õyßcw)øsß{ry9yô·»)Ñ«mŠ©Ádw‰Ôö« ›ÍH=g¥ Ê!“ª¤¥*AY´=škê#öwŸÅ ì¯à=1ëNd»3©L—–º7Ûbûj;Û”1dÑRPk)ö½°þÎù)|þ­÷!Rí·ŽÏ·›''úÌâÙäÁ|cD<7=÷™0ª3Íó–B÷T*æ[šÙÁš¡{³cL§Á¡V ¼ÝIi*nøfDóÁÜ£Öw>ßÍß¿ûä¥ãºàhÁÓIJ_„@4 „xÛ4¼¥GŒÐœ<‘hJ”ã4€y|D¶Ì»Mâ$Ãy‚‰¤Ï7CR²Ñà5å×EŠI9ašþ}“?‡¿·»Ç¾)òÎí<•˜ˆBÒë¨ÖZÔ"F7¹AüðD,ÅLÌÐ0_;KO!—…0)ñd”uà;YK¿û½—Tø¥÷Ø¥¦0e½8XK:ô²ˆÜ{v½:œâz¹å¼šŠß{Aúò‡TLû¢Æ,íE#²ˆ‘rÀhZå§ò:·JÆT \/Ëé¤ìâ(ÔQVáøÍð»¿QuW•š YHK1뎅4CˆeAB ©{²Ô€á5ÝrLc<¾"èNUäk©ÀRüRo 磭PÌÚP×Rýh‚µäc¦¼ÖÀJ0)•Ó´¬K§C‰Ã׿ûµ.ª˜˜Å„ðÈáu»§=ô}ä÷¬ŒoúeÜsß—æ}u¬0‚)«å Ûý-¶G)K,hw–}üÁO¶±éجBâíZ Ťøº×Ѧü n7Ã}/˜‹^xªlÜR¶¾‚¤øâ7Œ€¾’|K›ê6ÐNŠ5ÉD,=Ìóû2Á†éѦÐ~iòú¶TÛlÔ˜%/…Æ‹ ^­®ÄÒûœ©¾üZÜÛƒ7üö¢JP‹ƒ“JÖ6;yAæJÝg@c Yà­ÚqLÅàô âÔZ•eÔ”°eµF³_^\;OWçGóžçV®0e‘ÌéR¸ý¦AV ]c^9³TGÐÇŽg@дÿS ¤(0MñéCRkH3Xʲk_7Ìø1ï“T¢E…D2cظ­¡­‹>&D‰,}ËD6Ccç•„ãLª–@R‚,AµõšrLM†Gà™ZüjÓVx~Í ²6+oÉ7ÓH¨;â@Ë8jM“ÂbünAƒÞG‰ )K05A† U–§ß)‡ãÔºS¹‰«Z€o-òÕ!†Lü4»J bмËì6í«žn¾ho¼†—§•Ï,íÔ<R: to³üËÈâÄ7€ Û¨-@zWç›VÐ<&·ÔH-<Aí"ää3¯ÝUþâ5õÔóXLÁ«]€£vR; lûÅÙÀñÅøh²âvÚ$]e²¾î÷xªÑæÁñ9ÔÓ¾C#2)Áª KjÚûeãE躈~à9î'´JìÚÕt&¬u}Û„&\ëåJ€˜CÒĘ­eC¢ií³‚l„|Ì {àz‰ð ´à ^fM¥Ð˜”XÊ}~ùƒìØé»ëR¸”NS휛ÙÚ£@;WªF˜b†PA—ÂÿüË—Þ Š~÷¿ÖÊYRuO_w¶” ¬¾‚R!nK¦üT^`øÄY"Ħv'™F@å}H3YYåÝ !È@ähb‚ÈWøèý|ÑM§lUJUÎCdÅ.–eMyÊ1Ï,HÌf$¶œ Ü2ÐR Ò&ùÔ˜ë?DV@SyF’”—VUu‰ ‡ÏàÀd뮊ƒ‹•㴌ѴZ1NxRk¤áh]›CÈŽYìÉè×S¿EþÝ”xâ»M}brÔΘü‚::FM{ô˜S-Z/Àì´S°5w?²§’V-„~q%jÚQÝ1µØ×Ÿÿüç=éd聯¿‘÷ìë‰I2Ai‰Ó1j-¸g£µGx)`¸÷ÔÆ«c|ðÿýÝÓsÙ#X-~[¨ÄR K‚¬Á Fê("ðõ2³3ZAœô}Ñï"ÊZ²í±.<‚@/AÇÒ3Q횢¹pJp´»5•TØëHœ²¬ÂbÁ† ,[G÷YHÃèHÓ¹µ )„@µŸ?v=ýýèC„¡©œm³1KÙRˆØ$(VÏ{úýZ?Yÿó¿îvW¤o\•·Íƒ5Àd5í!b§½+lxA;jrÍÂÛ¿öáZ°µM™N¯£ÚYÞS@K38&f÷¦øk*ƹ÷µD6p 4<$µb©©Aè\Ýo]‘Mù¹/±ñ:Ž–µ¯GžDZ<~õüÊï·2^6¾x3‰»*âõM P9Ž˜¡ÅLGÀÇiK4ˆ‹/§ãXº™¼¤=€àȵÈÔ1Ý@žûnÐ^]²ïÍ´úýTñ}0…dݼTëeíXK#u§ÖNª@ŽQ/úãALœO¤¥Ý»lü ¨—OÙ¾d—úÒ|õ+_gÕ< ÑTñÆ(¦#î¨ùpL´úŠwDa‡àü‡•ûXêg¸åÝÌð¯ýË;k§Ú ÊuÚ¯!-¾‘ij”Øb%uQløb¢mï}§^‘Óç‘+„w1X‰ÀËdYKÊ †ž¸ÛfœÖZÐ<âgµKh6"NÞÓÿÃïܽ÷{PÈê• Žlâ²Íl/zñ¹áö+…‰/¸êO:wàsêwÿKÇ¡j;«<µÄùšbÊÖŽ"PSŠB§cÙk$°ö˜)…ʼn„ð ëÅ[VÅ'¢J #[IœhjÇ–‚rA]ÜKÝNNòÎQØ`]J©æ³z †G†´e-R†ãÀ_µ¨}›o3p&æÕ$$°Ÿ–µ¬ÄL½¢AtR… fÕö" 0Å4«­ËÊ¥†§À3-ª*ÕÌ©Ñw/:^ìeÄÑæLè+þFªü'峉§žS‰ÔeOa ©é7C‚Û;‚“¬×}§Í©VVUœö懓Bhwb…”§©…X¡×Þ›_>ôùì_»JiÎâûõmø5tíÚ š €b¶ä‘}åòåÇRÏ œƒl˜üý-; ‚pKÓ¢¸^Û>Ž^[âÔ.hZ{„㸲@DJ@9&Bg«»˜&_S§«R˜&¤ñxµíhú…8‰‡7>«¼Q5µlûM›ÄYiœpFÁ‡hçÜxï½Bߺ츶)Ý鸅´€oHƒ¨RåYK|Ãøðá•ø~†²þ‰F¿„P•¬@Šg©ñZ 4â5í…N`÷ÒË„ÈÔ‚Q®*oI -&šÀe’b–W8ÄQ ©Ç§°«Ö?qŸºN³ë¬ ‘SC®u OÇT¹-@R¬‘{;sIËÕÉRhA©!vØf¶74 Ú¤Ó’Ie@U¤Úyq * oÉðźÐd–½QS“•аxÂÉâ¨0S"Ž&+€(‰†Âkäûüe14Ÿ‘}äïÛd](¯‘ µðz«;‡²÷‰Zk×O!˜b´{GR™£¸öq6BD­%fOÿ@²RÑ@ȪÀô~íƒvå÷Ž‹=s}ö×hUR4›¤×Oš•^Ö.ð™Öu/ÛfÅRh–²• ¥¯¡¾üë#o«žþ  ¯*e¸¦¦b‰Óo×ÉZbê(H /Õ´RÉF–"‹ Ì7³ZPkÌâ)Ö´ù²È–b†€|#RÇÎCô­uËy:¹kYª£¨¯%œ+€0UŽzø÷ô÷9@ycW55vøˆ†¯oâªà‰àþK?ùù)ÄíªêÚЯ2½´àw'ˆY}šØk-©OCKdãÉò¶† DÈ+¸sɆ B)K­ÅíšßkßRÇf³;²L 0œ·LydjðÈRcB´æ!8ÝÕF^JPÓ¦:¯(6FiK* ÂGk²æn©„Ã䓇cÚ§)'‚P#—mÓã¯Y%‚®®¬eÖ -ì_@AÉËeÆI­Á”«e…È>úà¿‹÷hðÍÿxôû«þDòšj-®—˜rߟFHL ç` K¸÷j¶oòRâm\`ïÈ Ï#·Ô……+ÑÚRN:p¥·7€8ßÍ3×÷-øÈhúêNÍÒ^:UU) pÚoRp{é†nþõÈ6| æ_þòo“¿Oâeïk];˜½óéÒ ¦ÓTbH}‡Çi#ª˜1â‹ÑÌ¿r¬]„&ŠS«‚O$ZÌ w{ëOßñªðª21Cc!ÍÜEo<%Aâ _¥Ç•­0ˆ›Ü“wœ7ýä>Àøº†ÕÅ.zõÁñáëÛ} 1a啸)ÄTü. Ó—?ínœ`G'›Úúµ֔µ…&‰o›³ŸóÄà&,x@IDATRá1«B£ ©E]&‚Â÷ps:º» hã7yãñLX KíðY3 LÅÓDfí^œˆrA ¼T>qLàj籂¡e<éHMÖ% ä'‡Ì,öϧ¬"Vž_y"-:‚X 딊æ4¶O¾KBg²d)Ÿ¤$q4øzÁõ’zúøiô÷¯žSxñ>¿ûÔkÃNS …c¤¼F üе¢¬Ù”ˆ•0ÝÍ1Zˆ,œDV GÐmaɶ)qí Ò‡\ÝÎ-âÑÿþ[W?ÐøK;Ýé'¸F¤Ì™`óXÇì`Ë*qJÈL8ŽÙŠ£Aú[O[ ¹{/{oJˆLœš*¦OÈC/ /•~…bÊá)⫲;àﻲ£MaUõ‚ãðeõbâ®)B8_\•¥€gáËR+o éCšß0^†"Ëf÷¹8G÷'£ã @Oƶ?z‡l‰Ð ˆ;aKƒtâf0§Ø–‡ñßÿº?|¹ùàãF™ˆˆµ»£y€ëÛiï‚6‚€I!aÈvh´kÀ3¹ªm3~ ÖRhÖS˜l RzcJAX¼=v,¥zÑUòÞûç G9ñôÛxˆ.)7˜Í2|xòZÃe[¦)쬌gY bÖF0 Š‘ò{*9S4²¼Fõ¢ÀZÂÍÉ,[n 1Fè½ÄK³ÑgM ¼ôÎ!€RÀưdZè *·›™¸ÿ‡Õ÷ïs¾Þñ²OD¡ÅÑ^ô‰ÌÀZ˜’!còâ4ádÚˆe_¸=«ý/M_ú{+J¿òu/X_£©¾êÛ’ˆ ,Æ ¤ Ph0^‰%#ÛŽê«$Až>‚Ç'A¸`žŽZÙúò/¥œ!Œ¯¶ó‘6Rä)DN³ÖbœtdÅd£‰¬Àˆÿ£9|O/“‰¤ KçPkʤÌiHÁ}|8«D€Ðx/ÕÿûT˜nÈ·B×¥÷NK-ê΋‘™+,െðøh=…IË&+Ë -yq" ª…ŒƒŸ/°Èñ›AÇ®K}K‰Ì0y 4‰íÐd8:‰!Åjí\ìBž”%Ÿ‡äÛ¹eG&«œÉ2T^ÐóT°s‰i_Ê ^´> ½ bf¾Íðè÷ª¨u`»hkûêÈ€½[`Ú—¦˜D•,$5±œ¾[SpTžÛl§+Oj:wf‚Ê‘{µô:î9UöwùënÔ»r½´ØH{åtª÷³¥l™~%-‹É¶¿Šø} -|óã½VJÌ^IFÂ[ ¸.|YAÓ¢µ§!fq’ I MI41‚Ö¼8ñÚá@¤4u‚æL™W‘%U…JRÆ¿T éWÎWt©Aš\!¾¥”˜Çor`3·Œàç?ÁUñÎ)ñ»_j¼š šM™¬îRðHS,µ mjåµzãÿðuçGm/:Ÿ]Ú…ÊY[»ï¡”^õµÄQ%(V% ©ª9»!. ZµíBʲcçãâ÷ì ´^}Îå3A±¦ªZòJš_@¹\aâ–¥ô²ì2ýbKU‘‹Ûx)Ó|±ŒOøë–¤kŸhT~· )G†Ü1íX¾çUÓÁ‡[º«:q1åÊÓ=è@| Jp0» â–ø::ʲ¶¤*ƒ¤ oGá–þöÑßÀЩä§à;?„6ÏIÑ´(7$Ñ’rípd;¨È#(il…ôc+WW ‡ðL–¯uW$Íð{vÃøÚ×gÿ÷ß·º"~ëkxµL@0Ó«©Ú ¦ÆèüÏXÏ'òöt×6? dí1Á”ú¶Ä1$P)h0Kd¯Ê-á @ü£ùÔå7@ 3µ{-@,gZˆ;À^5ÄhÞT6‚cHqGxg"Èò‰TÂ×HZ¸XÀO<¤ÃQBjq³)3:Ë ’g²{W’¸À²¸ãEkŒöRŒÆ"\M·qúe#œ0Ms/–n, XKû$ç¬ËÞ{È:”¥Ô6+¹ Zœu7 Zí^Rvk¡°1H xµ § ®uÙþÊSü£ù¢Ãóˆ'ÅL¨@G1_wý®MK1s¯×W¼^b`8q9™XmÖ.øåvq!DV’¾eM:&ô©ßØt¥JýîÑú×^ô)0µhv×ù‹b:í…—*QÎÇy?ZÏ‘”ËR0Ï—?‹ £¿ªjþæÛ©‘H…`‘ÅFÒBÖaò=ïTµ©øÒÄäÕBHAêHÙ=†ì:*†·GUÍÐ’·l$‹¼BAU|š8b],~»À,¥‘ÁàM`‘Ñ,‰XV"HSàÀ•;ð7ÿÜmæü}în­‰¡lB Ô]y­‚¬X¡X-|iƒëøe Öûó7­kÁ·Ô‡ì²Ãl‰à xc+‘R%åÀÛ\‹^ ©†¯PŒ– Í,“j’8øu ä#²eW3o™¦a "çK¥Ãk ‘Òˆo pˆOs´‚uo‰3qåãÖ¯qbÉjÖ|âÚè'Óù"Ï€ÅJÌÇK(¼A› ¡Q"O?)&eÉ‹+ÔÑ`²¼*œÈ–|L±^> ûÛß„ZþhþÒ÷jj¿tš³Žñ™¦îìÌt{–¥OS9'5"ºðJøKà\Ìhæùîgd§í³µn˜”ë(kM \ ¹| © ÂdŦRJLÊì´¾ÁpV( Š Œaâv§¤rRqàe›6¾\l†Ž«ñ µ+«°e¸%k›!ân`8DSÒ䑎.1¥XËÏ¿üñý›r-š–¦X k#À,q/+ÃTÒl+q«íÚù}Û‡êÕçfPŦi;–!½ `±×T B»nþÈÀîÐZÚŽ’â]¸! L!¦-§§Ï€îÈ •X•yˆð–p½œf¯`„Ä+‡àó)ð–“¢ Τ¢%¢<&Ùõ]ŒÆ€ qع×õn¬åÒ•Žjܺ†´[HK¦¶*±ÔŸ_’¦lŽ˜[TKvú,áuoâ Ýdp²óU5öíé㛇O~ ¦ÓŸŸëbx]´fµ#(ÈcŠ÷ö¦#œgø²ÚT3KùÙ¶©&5ñ”½£ ‹Ã‹Vd–‘]ïšê¨)Ä׬öûþéßW.i¤Æ§“¾î)7-qËŽåÞW‰¥¬€Zäneï»ïŸþþü´z17OjÚQãÛ5–~J ”( ÉV­¥y´8õ×HJl„TF?!ÈðD”ˆ/³©q€-Ë¢I+ŒÂ+Ï£%“‡l›U…”"¥ šÜ~Û²¬Tw‚À2¤.¾rñŒÿh~ÑÕïšéBG•€¬Q5åÝŸ–!hæóbr@±!ÅnÈ¿üñqÄûP[Ð.ʤº?ÝÕ@)ÏèKu·WÈ7›”Ç’çžHâ²DД@,Óçm¹ejh›Ê9eÙZ$ QkªRiâxb4¿3ZóÔ]ƒDHM# Ö|% 꾪‚1 ”ãÅÛ+èº>¶ b¤S7¢ú–:YÖÉ–MV©  h¹Q ⤚ ”-Ñç~” ׆ÅɶD#Ë[òtXµ‚f¨Ë•9ÿÒêÇoBjçP|Ñß'Ø`›³F²k½Ì ab†ßT-Jˆm*þÈ9Zg•8Ð’ïVÁ~|ú«òS¶Zª¦™,D€ÀLUa®Âµ›Ç ÖÅmd„ ¬„š§ÿw?‹¨òj÷ôox^Çæ!a‰ëf(ÐBªQÅM«0 QŽœÇ2ý&¼"[öò°L–ZB"é…°Dx4'¤FÀƭ˜²Ñz\R«á4¼˜oi64±Ç“^g‚k™”KŸ{>|ìîËÊ4»‚ zݵ£æG«°—a%ºÃ»%®‰ÎF¼¯øá»Éi¾1ä~ò®‹§'„‘r2@OOå–ÈYoªÎÙ² k'5\¹ÔÍõª ެ˜ ’˜"µ(U,kï+/UßÅ‚ YŠW«KšjY·™,æ†×AÀôâS@f|0þE|è+” 9ìç©öÎ?žæØÂà›[&ÖÌ h²C”ìÓ­MånÍÆÂ‡#ðu‹Ñêk)ˆ l«‚:¦VmÄlÛ)~ç(Vd}ó Õò÷ÑÃïByäö™šùù&&·He¼-›“0æøð![ ;R‚ŒBå&1©;P¹WÈ'ïv~Êñmoå¤xCR¨Kj–Z‹ó-ñ!5퉥x“cR³lT?¿{7Âï{Q¥„Ŭ¦‚µè¬"_”é*~µ‚&”ݲrHÊ8£UÇA0¿¸Ã‘Š» bÂÀºä1Ã-'(Îð=ßcZ6@±× Zµr{¯W;­ ™uÂÎ\J•|-à_ý×·ßy…>þËÖzÔ2‚ᎅ>ñ)-Òl€a$œ©ù×'~ùãžônÑðîd-ˆðuÔh±.æa&± ASIY+)¶TØI³‘/ÅŠiÆ· HLYšÕjS;  ZŠ)X6vYµ mŠ”¬8MY4U–:Wi)‹/K9}xÑ, xúðhªø•Èvn˜²ç[Ž¢êKW0/H׸¦“Çlµ#CJa6%¹xYˆ­N9…ÊU,HG•F–Àð@Ÿ…ýÁ³‹üÆûä£G‰Ú.Rë¥Å4¦ÝöhyMqnÄ{Õâ²WÝã±¢VS×G• t‘ºŸ Â38‹€BÜ~¿û¦¥-ämÖ€¸ù)PKx_-5‚×ÑÉ„ðLÓqº}cv‡ùÁß<Ã¥îæGa傳}âí-вÇ"DœTMŒo’JÄhm¡Ô kœÅɧfr|#)‰ Dàá8‘yKV f±eȼTRÖY‹é㨂["ó §€o 8ÈÝ3ð!@æ±ûáo¼Ü ~êmŒæÏÓo§)u¡ Œl¹-Íìfæq6°ñ>ü%„ú‹»]åNƒà¦7ÛCÛ0âîN)SñRJðy1‚Û® Z>$®÷öø˜†Ì´ŠÈªˆXÈRóņ‰SkKAžˆWš]Ò÷æöÕ¿|³€8Aˆ^‚ÆÎO9~Ó–j žÛ! ÷½?p"÷ÀK‘j ¾êË0k—>¤(˜Î†DÈ7†*~KY ,AeÄo°(hé¨ðGâªí(©!ÕºÒO¶ci7ORÊë§ÁB¤ä ¨™³îÝ~éÐTR•™Cöƒï‡ùã×­¾ ¼Z=."A"Ʀc˜zY:zµwx4ŽÀ IªaÒñnv Ë—^•ŸBîoöÔz€´q]phV®…À ›Á’BWMŒÐ¹XÖ2WÍG¥†lZ½p^ήDÓ6 ±ú<2qR8D€‰àdÀî"4ä{‰”ve²rdK |Lˆ°Èøb„R@K`OMJÓR¼ Ò„°@Qk*.›?OO 9k¾ã°$ºÛyÅRuÒ ß^P¹ù¦Ö)l?t Èh6É#ÌZ&‹)ÚÜ÷v˜—}LOÿ? «õß?ð@ØŽFÛ$#¸Qõm׎Ž©¤¥XP6¼[ Yj?h—mG|´GËë²!W¥»óé  ¹óǤæoì~|¥aú«Ç4AñLù6kúM gVpiž{•ydM(ûþ³¿/ |ùƒ™7I‡|a;x‚ÑèCˆ[Šu4- lR²€.âÔjê(¤,™,Í&‰¼*K)ÞÝE¹F®šÃ,¥Šr÷6‚ÂÑuQ.¼Ëª‚ÏÓaDY ÖÞx¥ð¥xÙ4•÷ÙŽéNøñ£€BæØ=Ù®-Ì’)²b3ç6ÌêÅg²•ËvpJ,¯Vïœ_¼¹%0UѱS± ÛUÀ€ŽÂ±#tªJÄ&Ü´·£˜DLÈt„d§Áó&Y ¥)ZH%hTâVSKä.ñ=% 'Lgó¸¸UA6FÙø|š!§ßuK'È[òÛ¾^æ´tɺšZ0äe-Åçák,žÚæ•1K<El•§ìúÜ­DP')qRb%© jŒ¼ q‘I;Lˆ,eA‹{y]ÊÆÓÄqÇøá×'Pñ{Ãô½?eçUßùPBÍ—?>Ú¾òö²'£eš÷&×óËbíXÃÀ»‚šJ”‹)$¢“w7";Û 1+ÙŽÔºc=¯T!Ä/'.0?‡Õ®T(f»¾ø8”•ããÔº1Rè0¥Ô ŠkÍ«…Ðé%e‰,Á" épªâ5:/oéw–Òj V\J6\“åñy[²ÔÉ’‡ «·%…ÆÖ×çGÙ6 °ª¤Ò©o)ÌÊ©eð@K{ÓË/B+|R¾ø_SùÐá¶«MˆaPS«e©5…kÁ‡+ï·Iª-ך ¤í·ËîNŸŒÄÞ þùÏÚxjý\Y£t¤ô#3)>ÁĪòeÚEùÖ¹(ö‹ŸÚf3¶˜/%«©F–´xKÇ‚#^4–šr)U¾ùyóôGó„–Ž e:•“rul¾FóÀÆÃ'ÂoR‘)ÄÁÓ.T15C«¯I£a"dJàÅpL3ëËÄj¥V´äw†Êèè!ýŽŒ#¨ ,5M"òibº~ùãÇAUjY½,ë1Ì•9ʲÌvïh#²æéÖm0ˆ10Ý–ü¶ð]à (“tõª;5/Êaén†hFe›BËpøR|¦û4±ZLûJ?KL1¿X€®K·„N̆§Ùit2øp>©‘“ad› b™Ž€¾.ÌDê%[‰¥˜`§¡v"MÁ!ÒüéX*×(µÓª†œ¥€E’bQyx BpZâÄo&{!M4‡NA`éŠ2UJR>]/ƒ0… «D²v@|M½>ùêß⥓>ñ&´$¨£Ãê Iiç|´€„!Ë2l rf<#^†ãs‡½­|Xf²Ñ.™_ïCZÐìlõR…ŒÙ1Â}Èêå—þ—ßo¹µ€  B-eÞl!mDlË׽Ѳr8k(ûæ/>Ìà§AûU¥¯?5Áé·qåš½ÄL ‚#æÅh•8I;uìüR‘[Æ×ËØÚ Ðpœ°l´J¤åð¥&Ra3Ьê’?Gª² gY­,Á’·$®Q- ÙpänT§AÿÃïÜÝ>w'K°]v¿‰ëØÄ lͯ¯™U¡5¶¬¥¿@ýðË¿”Jª1Ú5â=Ê;£ê•8ÏTÕ—·4ïÓd±ùZ"ËB ÂJiQ¢5G, gá@Y1f4jÞÃøfF®¯_Œ†ˆ.–²Éò⬑ÐîCY‚ 3| Ú+y¾ ‹jÈW…ì ¾1àÈ繆ã¾1±C—ÅÆCHZÐ~ªb¢5zÒ–pq`R‰ïNªˆƒO– ˜òC¤ ÙÆh0µp1åOþÝ£3r÷kD‡rÅ6EŠF¨/°ÖR (›)lŒ¥B,U%ë¶0"{ïñèGð‹Š]0úMÐEÂG #€«•ªîžþtì÷“¾Ÿuj¦HWÈ(ÃuäõbZä¥ð-+l6~7LYô¯Ïzùaþn^çžþÈj¾KÌÄõj_ OwBR²®$J¢Á‘I#$eS òLª¦ÉB”„×¢¥,<‘–1ùu!(v˜ÅÄT¥|i O nøDÄã×^-/f8R”;ŠÚ©‚»ùü4€©Ö-±ÂI ”gv„о€ú6/ké î¸g‰øNòÃ/¼<=Û5YçÜQL\ÊÌ]ZëÆ€ d wû‘BxfΑ tn8FÕ…²˜!´øº‘²äÅñ-é$Ÿ”ZF§îâô70…ð 7þ†”ª/Z}щ¤l‰–/¥\kxãMŸT- RãÙyýûŸu0•GÙâái•â‘)´Äi{;ÙªdÍ$fâU”ñK…;\¼Û‘x%m©TóðJ"ð~øýñ€ïï޴КÔ6Þ´©Ýe#G6†@Ö$dq¾* Zq%Rðnqx*ðòR¡S­`‚|/°ZàXy&ké¿ì‰}û¿þÄÛ/ú¤ëÂw›n9ÍögÀÞ~m Þx–AŸýß|â3@ï¸D”·M-:õ*è*§,&n³5mŒhŽn)ÆáÒxb¸ÉÅ Æ D‹­ªÅ8!+©E:RL;ƒA˜˜Zd)äøñ,wõrYrY­™ÀŽœ †QÐÂãR`Ù™Adži×Ãk×RìVO¡Ù(œ7ꔫâwÉÎp%ƱM¾ â Œ!HJ ­vb½ ˜ò¶P–ψlGÔbUɦ\_ž©åqªšÇ¹’¤ìESÖ´Wé£gˆå£’ TNY±²bmà–zÔ¾ë$ņK¹ë€ˆ¸ºy…®.fåWÝã¶£,«E)fé´+|8‘ðúÖ15ÿ÷3 üK#Òï¾Rk;˜4‰ j·¥Ù,5øî’&Ù¦¤ÑèˆMâ©-`Æ O¦÷!KåÍŒfÉÜ:¼sãeµã›¡mòÈŸüâWU_ýwn LÜN ÌšÎ4…”ÔÂ,CíËsçÍ×Pî“þ‘B²‰‹Ù%yŽ"e)R†d÷.‘q4]aä¤Â!@qÊö«°¸Ú {s­¤½LÙRÖáII°;Ÿòö‚À,«âY­1UT8Š•,ˆì–`R÷]‚tí†WKÖÇ%§ý[£ï÷ðbÔ½ 4¢ïÆ#ènô8C†S`8–¬8¾%²?Áx;Â#é§_K*dMR¢†§/èÖm0Hüfà[º^©ñDÐÌ“Ð2PïЧ,°…hªÂŒ~­‰Ãyµ,°­:A^` qL^9Š™”ZžYÂ3…pþb×ð)K™ç^hÚ8ñ‰l`4çI_-Óýñ|‘À‘6=’\ÒMÃ[2¸¸ÉÜ N^§tòš–;qH“ ’­ZÊüt‰H|Yjb )ò‡ÿ>ú¤Ð0¼¦G§yxÊ2D ;œŽ òRö% p÷.-(Ü2-ìÔÅSIËRa£@”ð+§É”óe‹)‡ –Єwë dYh2í\Ÿ‰jýé=~"æ7¤˜²XS8o gÝCI¸ØHhÓéLçÙDL›”Ó§—¥Ãˆ@dY¸‚À38¢——ú'ßtùIßÏ:ª”׫a yº^?^˜ª­í`v×êëHËLP ‡xÇ}ÿ»¾þÐv/•öÂw{t#¶Y‚`RÝýbLYŒ„`)nT4ÖüIŠ&Dþ}B)[vé[Š!øµCN­!ã#Ü·X#ßfǬ’™lŸªât2bµ1Ÿü™“!ûê_­ÉuTn¤u÷|g¶#ˆ#PÒ…6•”Ö¯”÷Üø{àíÇçÍ~{¡¼ÓK§£Û0Ú‰yç 06¹”%k#z‰*€°G† T~ ‚@œ÷².–—ÌCÍ2©š¦Ï¯WÜi6å¨ãT+fÔõrMmб[†óÅ-qš¹§¹+Òð”ã$«Ðaþ”@ðÞèôôב>eAR4;ŠZèÛ;Y7@pÚ€%Òö“²µÿÛsî _þP`f.àÉ&Ø9ˆe)Ž-Ö_¶óYÐrç¶áíE-Á»¬F 0\ÀÎoç,Vµ½p,ïdñôSoû2B­Å‚²|cGÀ ·d÷FðûÌRÍ–fÌ.G³MJ)å]ÓbµÑ7™Åiø|Xe‘ªìùA\ñN§e"ø/áÂKñ‰ àÆ2"D|º>†hKÀ‚¶!n¹Žføä5àC±B¤pc4€Žm¤Ç%NSaŠ;C¾l¶ÁxƒQ&Åã2xµMˆ_Ðü–q“4$Ž¥B&ÐÝ$Ÿü¿j(ìo«Uµ[—ºj*€èѱl„ MÕ„@ô<ý·„¼Xÿ}=špR´ `ÙÓo<)MÑ,2¿Ö Å:Ži¾±·”b)”µT®î”!ø‚-ð!yK%$¶…®N…Ù»VbÉ'Þ[ÖBÕ=°4žB|R|ˆ#¥P*‘öËûòç“ÆðÕ LŠŽ£Xk]î†ÏK)¡ÙZnƒ–ÆhZñóñÙÀíT!eú–RÆKÊRg6ËšD_ˆì•9_,Ç·¤CaL|4, ‡$'˜É^ô³åÞÓTÒÞ0é'ÒR­X‰bÜ5%%–ªoUZЄ¦S²Žp[«ªîp­k‡ ¾ËâGБÃìŽHApøDÒÑúñYk[B¼e•Reá;ÜÍ„,àøNªÍœÊk¦#zu±¬K4Ë6`·+‰ÌK±Ž¬ªŽ ©ßÔöÇ?ø•¸!ÏXÏ·Vú½ÃÛ”©´À‰Æ‡Ü¢ñ”·ýÄ[òš†‹•ËÖô(>íìêùˆAÓ±ByyÊZzý¸M4[m§÷mŠ;aA1O¶vêÓÊ•9~¾LVÌwJ‰;Oÿ ðÅúꟂrü¤ ÜŽÀîœðäÁusëG†·÷ÄeÓÁ3ÃAุrqÌ.¨%Õ"VK³¸eµ!õªyWJ nS|âRÚYÖÙ˜ œ-éwžbG¤ Î3}âG(FÀt! â÷æË?UèöN“,¤+b’t LŠÝ5˜h];©Æ†0¿òáÿeŒéSRzµ_],/sÌÖdyú<Bô…`vuWžä }=cV¨¤¬^êÎW„˜¤ÊòJd pdãˆ;®>œ­ÄljïV–§ƒF¤íã4A&ÖZ0~„Iµ¯Ã~~ÖéÜ2üN¦ãâѽ9¹”¤Úüñ‰X ƒ²Ø–xâ Ä- d¥Ä_SË´4%‚¸xËKØay(¯œ¾ÂZ ÝÅ©i»}¿/}ùÓ)¬°@¼@<d³1Y:–½TîÈ•DÃÁ4'Ïj-ËÄ É#¨BPÇ–YËI©c6ïoœÞüº5)Þ÷ >a]#<¶©)œ`MyÐóRíº€²ýž°ÍZ–²ÄôÐyóëå^äd1k*PáÅDR³kÊf8¤c`6%# àª:ŠyF¢|ò».ûC,“k±-S†èE°#² ÜüíQ‰î¥p˜¥ñˆ;‡÷¿ R•ùů—áý¸Ú¦^i¢idk†ì2AdÃqRj9~Cv¤¼—AU Y¶’Ú!À+\ ý&løŽ Δ(ïÚY´Dƒ$Õ„º tMS®ÓR N#Á›!Á4Åéä×N_ùèyCâˆ)'Û’DÌ«jS<9üñÁ¤fÍ-ÀSSÉÀ‡· T%`õXªK;jbÖNŠ™‰ÉâóâÑÛ¤.²Ï£;'ÍïgOwÌî†Óã:…l[3€˜¦`‡€Ð#¯¬BW´~Á² )ð!ˆ\=Ï=±lB`?s4OÙ½ð¾ê¥ö²©—¥Ú¾ðZ×¥³ÒTÐbäðÎYI÷\- T1Æû‡Ž/š}ÞìÚ8ejm9ñdy©p{M “bJBxÃTerA)¸ÁBT váp(´M—Ly3\ò}¸*34&P•Ï€™X_UtÄ |•©‚:ž²ç8µ­Â‰Ûšî¬©®ŠÓËHMÉèùXñË•»>û{RhNÝkªEC <—ïKœfC¨»¾í.â‹üMš³Mê÷ÁÓϦªׂÚ&¦@^£âðnEHèíð½:ÔÆ§†Æ«E(¥QâpÏUe‰@âAÓ…”Ç÷ÐØ‘{~j±Œ@D-œWk©Öa·qšùÅt†¡Ðò4»d»¥ã7³9ë"P” óhqÂÅðF=[²À`I—+WÖ–äRI7¯%¾˜EƤ\y©úÅHmŽdm‰Nƒ:& )|䤪E`á¼=£á¼1·N‚ž?I!¥êÎ+L$„ă~"pœÈãb¦)x<É­R=SÃH•Å)Æó"­äíª*[Ö²¹•+ä+Q‹ã"%‹É–íXn HwC÷ÙוּŒfó#×·*xAi)ú1ŦB”›Ÿ`"ã«Z/)qâ&øø_Õ^Ÿ‰ÇA&®Žo]¼àÃßx/u?ìX¡òmP âLkf#²hp^¢J RP–‚ÀÄß à÷{}ÃK6©NOL3)± ë+k©W €Ño:µSÂIJµ^ÞLLœ òÝÐ,UµëtøðZ‹[’Õ.2ŽBÈC(•È“­E5އcH÷ …Ê‚û¶«L9&¡œ2°Á¾ü©o©ï¼¿ó•`3¤Æ×Z‰ &±¬©¨ƒCjaI!Ðáû׈ŸüU‚ÿ ŽÌÒ®‰Ø8eA½´óÝbäm3¦ò¦m`ËDx1šAíûÎãDƱÄ'e˜zÉ2 ]„î.%h¥Ä ¿%Nf)Pkrq4ˆ B3‹ËÞïÛqÊnwN;òˆÆS`õ²Ü©b‰4¶^8fžBG£s^Š%,ºÒ]-8¯ [R¤¿‰Ydq8š%ß4Kƒ¦¡A;7‡{‹‚BL—Aö¨__£ã5"(àáõµ|cÉҤХ–7BíÐî›í@*—jÚö¢Ñé¨;ÛHh|)|– ¦”Ú¾I÷C±Ÿpe‘Yó#(,ö>ñþ;÷h~ŒèÖ[¦FD/š–æÏCŒ!Îp8ð{-Ùv„à‰ã;«z}émÄ;‘íBà0‘¬í·µ^Z`¤)__¡1VÞ¨ĉp—j§ø•Wˆ‰ƒÜ@1#Õf·_´Mjd#ãÔˆdã%N³y’EN¼¾ËZ2Lå|“`â+ 6C‚=v?üòLJîô;꺻 @w}éØŽx`S™5¶&Ëù†4Ÿ Ê"¼1cø½T7R-ÚAËóû¸ÓÆ#ÏcA;¦°Óh¤@´ôÅ6¨i8&K0¾F41lJÊRÊRʉ¥fyÇ-׎ƒ¬6–з\^qøFiy?D4X=’rÖ–‘¥ Ž\ ÇL@×ïp#ó‹ÃÒï2 Ÿ~?™r“8ÊßSæ™¬ŽøÍ Ú̲ì➪ X-¯6jŠRùJ(xú¿ÿ GÓ¿;s!ÚiW„Z“'˜¸”é"†ðª(Ôî¿r±”X¹˜áÛÔ…ŸÊ¤s¿Žªx­«RîèÒD¾Ëv½TɆ#ˆ™*…mAÓgX †×]š@/œ”Ñ0±oÿq~´þêß-a›ª/olæÇïD6ÿî S(©—€Ô6â«ÿ=©ß 㣉ŸBt¤I!ÿ²ñ•#°²`KÔ45R S0Ž¥x?÷PPëT ”ÈÖb§z_LY]6°xU”¥ Ί`Ýe•Ô4² ÷–Ž,¼Td1¥`©\*rRR Çl]AAà8`F!SÕÕ„˜µw8Â%|.1<¾çM ’²º1, ‡‰>Åîém¡–|؆ZËt·dbVUA^–0Úæ±j–‰ Þ)üÄMkDW.ÈŒZ_œô-kÁg²D€Ê+á :F¸¢*²>J÷]3øó Yåø)PX’ýð¿øæ³ÿìË< ÓÀz5R;m¤Çö®ÿ‘m#=qÄ!¼?¼ÿůÏ_dUni~“Ô.ß<|í0Ùš:„õ”BüðÈ B,CâÀ–ÅhUÉfÀŽ.˜B1~÷ƒ¾Äýè“ZåÀk µ1á¬Ý¥ãCã(rî)˵XÖHI/(œº¤f‚!µ¨ÿVJ"ÚÒ€ÈLk)5lŒYTY™8Ƨ§Ë—‹Œ)¡(‚‰`ÌŒ¦=¹ËÒž¬S3^ÜE ™Š¦+™¥'GE”™n¦¤ÒáW‰#ÑÈ„æËB&L­*£Å42d8BQY6Ô»ð‹M†&…Qˆ#—Kí’ÿ¸›ä×2æ•zêšêÖ”O¶Î›F+‹Ï1Æ÷]ßê$å£q¸©D z(Ä÷µ»{z ¼}óã”±*µa4UÝñ6šÆAãGæìlèÎ /¤­¾þ¿˜î5ûSUŒpÊsL-MuÈöjd8P5P¢1Kj~{%— 5å0š¶ù4ï„ÐIdcŽD ²ñè^ÊB¤RÈ~åý^-°Žy/”Ž(G´®òK2H êá3)ûàXʳ±_þàÄ¡ÉL‰äÃM™¨†¸EBà­—ÏA`…4q¿óOR”s†S®yŽBÒÉB*D°ÓƒPE ¸5CÃk ‰PèÞëøÔÂÓ!%¥¨‘š)ZU® —´…™ZÌR83«âÕóLÈéø"ò̈8œªg²8Iñe™ù¥d@}V1&_žÉå<N3¦Ñ-µSªû&¤¢‚J0 óÿÜÆø‰B:k¯–֧͘2N´ŽŽDHc¡úц)?þ±Ñ†{Å«zmäKçT±q%TÑP¬êœ‰‘‚sÊÂçX,Yx¡hö ™%Âoár«y…ž7ø”E—È1­7 Éš¶:SQ)œÆ˜ö–aª˜¬‘Ï€hÒY>œˆ,# 4E0õ}`…^˜;¦/dÕ€\ý$Â:ý –@¢™JDƒCL9¢1!,_ b¾è¡3Ó«‰ôE*Íô_um;¾¤G @IDATÆÊ¥àH¡c D†$eWKLߨO!Ž”üånš²WF4Æ/…`ÊFÊÞzÕÅä£áÈ…˜O_ÔIÕ˜`‰–†G.KŸr7q#gj¦ S–*œV­ÿtL”EDi8¦ÓÅ!I¹Š_GRp鲌*š6r蔕¾)e­‘S:‚Z‰¤Ùļ2ÎàÐ&Åß µ›¦¯MVHH•®ÌîõŸH„£kÌ *½Mh—H©˜•‹Àôìi*eVŠÝCÅ´Qz༨®Uß>ÉÅIcCÈšÒÑ«¸¨©†Y[çR‰Pº†f”EG”_Ÿ~Ç7߈L$+ЦP‡ðñ9h&§ö0³”[Ú˜µalu¥§Üi  !NQN‚U7â#6°t#D´Üt(04QoÄNÓº}1zén‹$V_z…ŽîçÙÛnÀ;(œÈ:Ñši½q¼ûkæE…üýY'm”óJîöÏ¢qpTáè3ܨŽËÞEM¢¨Ñ”&ó‰ÄJïKKC³ýä0ë5†Ó‘N?) íFÕÏiz=j,š\Ñ6¶ê3A¾†]eÛy‚Äk@-4FÈæsäžØuk2q£êùðtŒÓtLY~¹›Êe—öïݨNµ$þþÄaBº@RL½Ý¡¸däŠ!pL[6fUsDé°t8)Ê?±ëZ­]4– "üe8™ïG5/Þ[½YWb‰rk€Ç¡ªçe¦ÏâÒ©%‰…äŽÌAÆá ðÝOkÌ[¯ÿí BQ ,Í9]/Fטð6DW˜õbJ>£¬7cÍ(]¨qb®œ¯þ{+òÕ±ŠžêÊM¸BÖŠ8õpa w”E¿*ñ B¹ÜJ„´ÃÓr‘étPÇo¦6ÇÝ$>D 2k[D»é,—øéãó9Ä©„{(¾èÝáSÆ/E‰#t™°[ ÂN+×’ù@%LÝý<h¾üqþ¯«¤Ô² [{ý4†Ç©¨Ñ”‚ÆLýùêÅÅ…œô/Ò:‘e”nê$´ ¾Æ0«UKU¬ùF nÄrEM;“ñǬ7´Yü>¿t'm¹9ð6J‡¬&…8dá÷',=À—Û{•D¡˜RªXK‘EÙ|L%æUöã¡OW…c*Qz œsé}Ü4 ÓIH&Ë·"4ÓÈ9üSƒ¢J&ü“ôùHá@t`lm•'*%|MˆZ¼i´FÓŒãK4Ö+}æéæ²h\<°”8©i@bˆ @'%~½¼8‰Sh9qèpàNµºâ«H MÝ qœ=Ž\gŒiœr—¸8 îÛÛ®é¿~ý¢l¥ 1 d·þwþÐ‡é «³­ô5i*š`¡VÚ±/¹æ!J3´øþÄ÷ãWÿöÙ㇎BävùD,ªJViL¬™Èu­½¥ !ë¨1‰p ªŠ\H Bèô¬·j%¤³,¸5âÃó%Z‹ë¤ÐXâB!%êa«¦P:r¥‘¼ÜΫKì àF¿üaœ×&Ý)#‹Õ°‘¥¶7SÓ(´Zv€É…¤¯íú|çW ð¹ÐÂ{Àoù¤M**DS9c;‰4šáíž#âóhM®±:/q{˜l! ³hpšF|]q 4'»)¡Í.âÇiAHŠu%E–)—ޱ6 Ç”‹”>MÎs®‰`lŠ N%XåÙ½D%.t5xJÇá¥yþ*M‹4´_ØaˆT7ªÖívlpÒ2vYr²DøœåéY_‰6¥¥šÆ‘ˆS¦uÁ4#3Åyý—w74F¶,…*Áç˜òiÖš%ÇÑFY¦¢¬¬Rø|ËñîßïèÝýÿýï§6©ø)}ÁÚ)¼0ט?a9÷ê)P–˜¯Ç¢à,gÊB­¿…¿ó–GÖWXøŒ‚5Ö3§*µáÌAH™ì’®ºÄ²8ÛáB‘MÓHÈ‘ÈøøE9¢U‘È*Z¢¨Å2åVQM¿„r%øœ. ‚iäBÆ[´D4ú ²)ðÞj%¼ô4ËÒm'ð…!»û÷n‹FcË©Ûz@¨#„áSHß´Ò8zà¿ùå_ôfÐ’)¯e`Oå@£}ÒoO8 dªÇœÂG¶Àþ¢9˜GîS³Õéï¼–Hç0M …ùÛ"³·ðÌ4'ñÖ[Ê5À§Ìø‰ãK„sb¦,©B¢R;Í09¼8ðµQQSEJ7å arªøñee%SÜju£^ê•ç'”–iËS‰_„IñK‡XALš²àm ˆÉ8m-RÇDøFv¨è@|5á•áÙ;¬Wl!/°¤X/×H¸P«R¹BN º-m;À—hÚ±ñÞê†^'.Î?ÿü³—j)|YFå{Ö6Í™[¿ßª.¥£S]íqàŒo4Íä¶R '¦\{+„Ù6þøÕ?¾{M¯ ‰kƒ ܪSK0D‰hš‰rÛIH‡ƒ/Ôþ‡§ÜŠŒZågøU*JÍŠÄ©œZ¢ÈõÙ’ ñ9í ©ug²ˆäHgÈ Î¦_ÈÞ^ÄÃA°V‰—nÔ†D!Ž“ÊIËOVŠ€Ý +Ùg£óÙ–HÉ%Òô@AóµG9_ŸŒ`½™Þû7­O)8oþ¿N*çêK_:'ýF…:]# ;‹´ªÖ>áÅÜ™‰# dü–¯·©Á!hF†Ìš"3Ó8ʹù2_3|]™âCŒö“7ZBšS† ‹¯DUÊŠPð %ˆ&kåp˜,‹â`6Å"* ÞÓ­3D&Ê8+Ê ¯O:•£ÉýïþóŸD¡ª=E¢u€s%ž95•b¤˜¨)“•C Yºh-Âñá)‹®§,d|N„B1bf6ů&àë?j®4 ”_6Ÿ”®ªhZ3œ**ßx#¤ÿ¡D§ÐÏ!¼û;­ãYåò•ëiñmÏkŒ£œŸyxpL¥sòM;ÆD4_‰n”BÀö'>dËð=®\êÈ/ÌZ\ä‰K‘عÞê ­¨Ý3íà¶®§Dµj “YóŒ/„&T¢1ån(M€Æ¦eñ!Ì”™²vÉnºžMùlåJ+Ío4eCSÓ³ÜJÀY‚)­‡Ïy¢ü"Í Á;Ïc›ð¯Ïÿ÷Íé¨[ #µ|Ñ–¦ Žfd¦ ίç|Êýë_ÿúÎsȉѿH¯\kÙX‰kÏ•³-ømKdL8?Z>N ¦È¢¦@SN 1µÀ%FH¹¬Î´Fñ5 ʤËÖ’tS q ’Zu‰e 1S= S.ͨ¢¨Œ_Ï5œ`E«ÅÁ†G‰Éæ·œSûóPŠ\ü锲Qt¾ìã,L¢žFªƒÆØFù‘M ¡Õ Å%Ø‹# ^"ÜŽGÛb8Ò‰ô]GLH]Y¥«!ÄãÝ]ò/ùË8M|šàºÚ¶^ )éÈueºBpÝJíà Õ!œ/1ß”}ßã÷½-Ü·%~®óYüã-‹U®Ñ'ý ù­ãóµOÙzèôÕg­v}&%1qãn‘BšÛH ‘ˆ†ü¡!¦ÿà3Mü5¾Š¦©™&Q®U@­ºS~4kMG”µN§"f:8@SÏøÄM'Ë™NË”G¨”Ä#'ˆ0ZQc¥#¬M!âiŽŒÀ*‘šƒ“B‚áwÔvÚ‹gß¹K¹d^ ýK@‰4%®C¹¦â\?Àö|H}ÂC$VZ“þýίœ–NuU$Ê22ç@ T1q*§¦hø*" ñ[‹Íá»üѼ!0dR¥ã •{Š]{%”ÏY•¶…KìãdÊÓG£,=S!>)–'DVE9Ûdþøœá|—Ñꀔ[ldcKSŽ”i4>«C¥0ubdk¾¢-Q­S"Ñò¿û Hhñé*\¦ÇX+8’•?­}^´qTzˆjHn8G”/é9Æîûv*¦vÉ  •®%ŸˆùÞ\ø'í?ÍÍNÔ ‹Ñbk ¥ôÚ^ÿ¥®[«f“•¢DŒ^ü}lçÈr“ò˜ñNÔuÁL¶BõOÙ¬ï|ù£OW»ê÷…ëÄ´ƒM–šiíÕ[ýóï`~+uºûTôΟ÷·‡JÔI‘”ŒA°|Uš2ýÄDã 1LmXA¨»|)K„Kt6Ûä­"…²¶?À¯:ŸŽqèÇœfœÑ„€ŒÃDYSœÙ%y–, ¼X׋¬6 ކÃòáÞQvÚ=3/LJÓQÅ&T.ñª×')4†S9;É1-ÄçèÁ‹”ÓòC®W.‰™¶;ÿ•v@ùŽ,%ˆó™„êb:£F¹ö„’Ŕ˗+n„´F¹Óª†¤†É,Ήo4âD¦E«šºF!xN4¹ã§LE6Âé XZ½5çäËJÇG-#X?ôMÛ“D„€j ©1‘]8ÈœWâãïx+ °d>“‘ãØk0ÞË×e Qb=å›êoÍYKÕG:;µGÓvÜHjúD´q:ûl•©j¾ç1õ9€_¡ûØmÚ×ÙŠN–fµ€êä·êjUˆ_E‰nâ41á²<Ü.ýèŸaÂ95S¡wþЇOÐ5I¡ŠUOǸá(Á*-$Ec´ªè|oyðI}ëx$÷·“¶¥6ì-)¹Æ•žlmà'-ñµ±VÈmQbR@Vi…‚{ „¥‰?ñ@â«ò@ÃBæ sò ñÓÌ1†«+e„±é²òW¢}(ÚýÏ!B픿ZrÛ}ç—?./ÝdµäÒ!¢™£1GŠ/Ä瘊š²R“5\µ7ù£ gf5RÌFQ05’5’jÀ¨.„…t"Eâ§#…ÝÉp)J`Š–E22§µàÀùLbéíF)p&ÁBà©ñøÏf]ß8M¹¦é'XÈØÒ„"p€ ¦0Í@|H4çy¾yüV—ŽÑm½’*%Dÿår²¹ù²Áüs‹Ì3êC@œp‹ç3ÑVÂ/´š›"&_gÖ€ÉÚmMØ:ï¹ÕBÖºô8RZs=T…/Ýe„qêÊË5'ñ·ŸaýâÅv¸«º¯á+¡èr•&d¢Ýq¶:]Q6%â›/þ[¦ÏÂ4û/4ÄÌZ#µé—öù‘èöIü_²}¬iêäZîy‘ —ƯsmY`Q¸t¸Q?ßîϽš.ò¶šŽ\c›FsSšé·:#¤º¶Ô4ÙrùÖÎp„Ú“l)Ä´ÎR9‰z¨SHQ|k¬ dS†&ŠÃÖ6²U!Ö¡¢ïü³/‰ýÿ¯•’ÎNT”ƒÓBL5À€¬ºÆ8LŠ…81œÞ!/Fÿ$ÅÔÁ¢¯›$£O¶cm·ü˜||cLò!:4e¦@¦ñêýèDèG¹‘W¥ÅJA …ÀøªðŽ­ˆ‚(µ²L)¹øö‡ƒ¹”>î™B)HÁ¯ç’ä«¢·Bë¼i©±J$5‘ÓëÕ<! ˜M-}:d#ã„Y|Î9bëŒÃ.ÎÇ=ºÂ Á‹ù¥J§e¬˜&œSnÌJ$" ¤™Ú®Fë¯7¹Õ·lÓŠ¶ !S#œÅq ýúågøÞÐ#¯"G ܾý®Æy¼åt‚ÖA¸žS–WÝkš[¿¿šÂÓìíÖ_ÿðÖØŠœO)´F)šTš•þbÄtÿ•¨ £©?A÷eÓœ£¢±}ŽÖ‰Ëwâ;iè¸Âí 䵹­ÎÂi¶r;åÚ+#ŸT= ³ZEƒ›v438œÁlÈÔ_t{ÈG&›N r%Æç#Ä‘Èaö!Yúd ¶‘ïC§(©6“OÍ8Óº5ÂÑd-JXˆÃÖI8¤­+$·¨)q_þôÛÒŸ¾Zt¦IYi=×5Î:áã˜Ö'Ÿ¤,¥ÞŒpV'BNl<«>œ”ï9ûÂV3¦Õ¥Ü§2–dÄë­('K/Z'|„tøMÕÕ'_”Ý[×2LÇ¥\ü%žZ’úF† º4Ïtl,DžV!øj—H¨ûhÍõT®ÐÈèE…˜\S#¼š*¦Æ”ñ›ŠÖ¹“;GˆOÊ»’ ÆcÀý.0N£[9sÓ÷ è?A…“)!ï¨3¥Õrmð«NA'½žË5…ão]¥ Y÷¥™¾ù‡¾î¿ÄëŠf˯P«0Âé9¶×èxcj»©6X:¢˜>§ð­CÄã‡NÊÔø®d²,„2Í«ÂúTÑ)¨«ƒãóWˆOAè#ásJsýë‡!—[b") Ùç»&œ•n$+×ÐtË!BS´–ßXTV&¥ºBë³à5|¸Z|;€ÏLÛ c!ç¡/ïRßú6ß)‚‘&ZR qšZ‚(›ù©ÕO@(‘­Ž¥æÌL§”g££D-á³ÒÕâSf|c -ó‚?žø¥D VbÌÕÅi!!É^©gÐv¸ZGãv^¢ö®ÅÏš8Rð#çÃ9˜g Ÿ«èøÂÙêrî"9˜•èˆßiBj%ˆÐº€l`¢8p¹,‚1²NBzFíPR`!¤rV(µC®/Å@ˆüÕã\‚G‘ÓÓUÌÈðKq r¿‚g‘)Á©¹Bé—¨JR¦­N~ý‹rŒIqX+ò’â·˜nß}cã¤ÜBÌ´,µò•N¡ã+á¥ØsÅݹÆFpòE«‚ö¸†tóýÚÆôçHì‡ÿªL²Æšj;²r¦¢ù-D@S›™²©¯ÞiÀ¯˜ìžDR™DIÑ0"úá(ÚØÔÈ´‘S]N;À©C8?~ÌV¡sÓšç”n¤ –‘¯„Æj)åñ9e‰2Ó¤øE½âyVYQç°ôz@£é·"dÈ|œJ+Àø”µÄ©s½áÔ•Q”HÓ‹Êzÿ˲©‘R‹©X|¡¢UÁYÿ§×ϧ,¿cŠcú毜ü éÄ=­\愱pÑÓÄíiC€vx«€—xÑ?ÔSÀl?EÛ.=«h4åT‹Â@ˆ#ëäŒßHM 5Qï|FS#ÙàsºçT‚&'ñ¦%òá¥sD¡q*Z¨-¢@V9ÓJàÛâe‘*ŠÎa¢‚Ô˜(ÜŽq*Ñù$hùÆ8µzþ3æŒÒ„8™ÐZáã·×ã”+¤ªò¦•/eÑ#œQfw¡À0 u†4JY¢~j)Mc…ôÍ!ï‹ëõ"ßÅ/­øl²t¼JxÓ'BÊžV®åÐø:azf6Ô*>šÏ"ï|ùƒIÖg"ª7­dsDgªÄ‡ðÈæ}sügŽ[¿€åPÛZl‚³Ù(Ki‹Âá(dŒ/$‹¯Všæ嚆äd)Sb"¨œ\–8œ¯4“Ò´®J¬Š£€ ×åíè»;8Rõ­‘ÝcžT ˜üjñ×X>œ&¹ºÆªK¯±t¢y!°«¢¯Í_¶œõf!­T Ä´À§S-!H[çÌ,ª%†/Ê!åÒè¿\²ôoL¿£³.ÑŒ-¼BƦ5V“Èj…¬I´¢©ID ÆÉ¯=ç›õV®–VN¨ê¨³ÍÁµR:,òב¸Ý³™}ÂVÅÚK)TuÊ,Ÿˆ­3E«ŽBp„‹x¡Ì]aëBCå/k¹‹jLV|d8ü»xÈÀr,ŸoK;Ù8Î Røp4F!‘3¦2H8@ÆiÃ/…ßëQã¡QL‰GHt,'Aœ•˜‚ÜüSû"¬œî…ÖdL¹Ö‰¹>qè‹Â‘…øñ¥M_¡j9ð9h|éi*'×h ¬&i"”’ŸŽ¢+‡,ÑÎ[Eé]í ™þhÒÙ´ÿ‚Eù†WçN_Ïš0‹u1@¬qkál±Òù‘G#~)}<zEj'Ñ8²09ßö¶çísü4ã@„X!`瀞»n:§Ãˆk^TºŠ˜á‰HažÖ¾uÁ´|£Dâé#K\ÀÕJ›J‡&¿uUÈ6úÙÏ;ŒqºíJg-ÐHJõJœrœº…ë¹[?gH=ˆbÂ}ùS4üÙ¨Ž~:|=\}}\>Dt«;f+Lùªà§oÊ‘žïp ÂlK9hu’‡¬ÑãÜêÖ?f|ëbp‚l L®ßâº-È’Â8ª0Y!r¦‡%n¬–h‰å…Ú"¹ÐpÊ2²WÉñÉršÖ¨µc¦Y!à,5#¤(¿\#°tNÊUù¸ßB£…cð•äsZ'B Ñß"áê³ø@š#/³Ü­ížDˆÏðµÊÁi7…JÜç³kY·ƒÑ€|š¶Þ[^4jÀÆ+õ9)µV( ØLu!ß42Z!|ˆ«Ýi§ÐVFLéÆü%6]èŽyç ´ü‡èÃÔg|fmˆrL­ÂÚ;‚¦vw臔bÄ7v÷䨫…Dʱ¨éhq€L¦uR®L)• qiy®xܺ‰{+Œ/jiÞwá3½ùÝ˳»°›Ëßÿþ÷?¯ÿžʬnM¥óm ‡ ~¨©¢:ŽlÊê(+Ÿƒ ´)ÿ…Éê1˜¬ZÊÕ‰¢ù¦DZ—“ ?åó…ˆèª‘óο—k÷üÔÍ9LM!kOŠÄk¯©EÙy!çWE:ÐXoš D`“jZh`; d¸žÎÿãÅ?d£_7t‡X¡eazpÁ¹Á¬ËcÞ>à³öP¨ž-ŠßŽE0¥ƒ“°if8'…Ä9©••/4ŽÆê¡¬¶‚¯=!d¦Þb¦VÍT:ã³.+D”ÿû#ÌD×4gSa*-éÉ©jjTÆ “SCE)´Œø¢ë†/Ä0ùƦ:†Ùuõà#ÈB–™³¢üøÒE™/Ê© £)CsHR;œµWÔºîjúqÞ¥ÔÇëÆ³»ŒèÝôùë×/—‡~ê-q'wëBv Ð7ml𙨮¤Ø®z( è»æiNÊí†N¥9©qÞ}Kgµ!…ƒÃ µ|S]¡M­S)|C3¶>Gˆ§ÑtZ‘²ŒÈ¢Ž‘« ç™Îû‘. ž²›…§ÜÓ"òÃh«½ÿñÇÄÕbúéZ¨ˆš5l äsÚ…øFvTþ÷ßüåWT·3mXvØ”Ž)ÐZ¨U‚c*T'…Öù©}…àÀ˜Þ£Ÿ­=~£%ûg_ª+ÄÊMØb ­š´ÒùgÁ×ãÖnç´zÃá4&‚“8GéÈžÇN`wÓºjÄqgÄ¥«k¬hšÚð¯Ñì9‘{.ß³Ááó pÑÕAvßCS!Ö†§`ÊRî®ÙöŠÂEu i¦E9¬&cvRéDKÜXD8R«kl±@F¡NŽúEV‚Z¾ ÿ“ÍA“Ÿ(²)ÓPºqøép‰- &<ÄÈpà¨ê²¶ Š …ÑÁa˜.L‡DzµÐ’J¶Ò©ñ%ªkÄ)ddã×Xx…è+T®(&¤rÑøe©žr!S}"¸% ,ôlô·ß>š Xìú¹–~ÖN­Ý .ÚÚU‰iŒ#ÚK§/4žîvÓ%Z£…”YÕÒR«åñYûÄ„”( OŸ#Ä/=Ä(%Ð*¤à¬Ä.W!&WÔarƒð‹š@+òHs Únš¾öüÁÃ}ÁË ÐW³uînRjï®?°öZ»*¦[¾qçLEÝv|ëÄmË¿[”’U/¤.Yͬ!NœBM‘[Ú‡Öç×^ÿŠðíè êX+Ú¢ˆ¸UQfø•3êÇ5•%Å&˜Fv,øŠâàóY²@–”SGÇä@ˆ>´ç¾¯7¥Äéæê‡òŠâ'è„ñݦÿR€ÍñÁOÃý`D·B•®%R4E¯ gÉ–otX!kméÝÝ£u¶²LMÇ'M~KŽiTB:§»Ÿr–ް\ŽžãWh¥…~ïW[|e08ŒÃèòÕC»ûõ"X3Zý•e+)ÈâÔi­éëÌèn•/´ F Ù–ÝÚ¬Ä2ÂMùBáu¨Ÿ¤Œ|!8>5p£‹OÂi9@N‚LuÛV¦3Á 4S‰Þý¿žs8_ÍyìPi¹lmPË·¥åBVÅtâp˜=PûZñŽX”{e[—«¢,…LáF`ÊkU9U\Hd)@G‡çÒÙtøå ÒÉô9dDÛ‰ÓµwƒØ¿ÊF`ždý\m;VÈH– 1Ž? >{ »õx”U*j©UKO6Ç… uhùhªX>Îç—?Jx-µ ü•¦  ýn£B ÎÚÑÚÛá"Z{…4ÃñîÿΙi힣 mÛëÇÈZ—5*b¬Êé麹‹Bà})T?q€8”;=4Ïjâ 8¬–À‰çØOn€Xú6dUèK7B<-öý.è~å£Þ¿þõ¯¢ƒÏºØ9ZÈJ «kj¤–?YüüöÍzÓD“HƒMØ!j»ÖLÕc—žæ‘ø|¢ÇT7%hZd Kö㙌Q—*|Ñ>Nù˜¢øvAd~SHW8B«•¤Æ-Y–i‚Æ‘ž¯D~:@ÌÄ)X[ÍHá 3LmsŠBØ‘McM1ÉÊÊ‘UÏÆÐ*Œ ”ÂXdS4Sí½óS?þÈæl³Ó©¦k£Í)d”Xuþéã*Ýb1åºÝ¼s»œ\TöD [ ’­®)¼Ò·98³#Ò™Ó5‡á§Æ™ÙAé¸!Ãí°Í¤ÌÁmo4àÛ¿`yøFØs´¿ßb¶tòMK¯“ªXø½±ÚÛh ŠÆDÓF›sWÖX Ffºþ«Tמ8Nü™ÓÝ­5vP.á£,ÂÉjCW b* '‡Ïà¢ážjÖI¥Û7R5>qqHÊ qœðBȶ^VW5 ÂêÓCµvÈÝ_·òui<Ûpü4ë§t 3²wµ|'R‹-×è¬+ZÏIõl mˆ*êV ÿ¾xk4ò¥¤ƒL³,8«–æw²Uº1Ž‘‚,¹kr×7•ŸãôvØdâ¦5ùñG*ÔzBåW†n*뀣ª|#‚‘\Ì¥è¾5Ë­^šIuâ–"“&‚ÀÖ„)Áè`6u/ãt¦ÜTWh|cT{mSÍ ¥o\ŸKäZW˜Jëßb;k+1BN:|§”~äþh}ù£(¦Ä.mð×X T=S!v/¤h"¼Àð­ïMÓ[p7k‰íÌôëA´MW¨}¨Ÿz«™z€p¦)duM‚DZ')c`ú9JØm]u†˜Ê5úäþð] ÜsÔZÊÂQw…TW…q„_3øÏ MHJW_'‘‰3ÓKìC­ÕÁ{yT‚_ßf¼óϾ\±npRÈÖê)s-Ä>¤o+´]çãè “¬N}rÜý[ÿ…ÙLßIÖFuI¥ViúZê›Cmàˆ&_.'+QŠ©I8œZ¾Ñ5î¤}x¨§éx´÷dxRtˆºâè ^V ö˜g€«r¡?#û nJYW¬,ߨr8;ø¬U´ç˜ô!p¥9ðš4R.šŸl²r)Ã%Æ‘2?&åÖ^­é£‰c¬1Lš8‰pdKÑ6!±´EŠQëõ¬‰¦…Z^¸ AÔî‹f@Žª¥.“S9g<§P]ÕR)Ô„*-Ê:ºD(ã »c: ã$Ëo§–0Y)¢Ú6Uš¦‘!ó[#òýÈ‚´{)¤o¬ÉŠqoòžÿÑlWª+MGE:ãV×Tc4Ãq8M¦­ˆ¬‡È¯{è}ª\úâ·Ò%Û;«®n‰éÄÌ_8ÑŒ-A4}`ë2åÛLGJ4åЬË{œƒ>AŽMóµOD¡)XÛ9å&ÂÇ¡ ë.ò­_3RØK_WÒµGŠ_S|£)|‡ÒÔß!öák9íùêßHDÔÈÔ¥£AÊí)µ ˆÌ©´‘ŽDœ¢Rîtï|(tŸõ(U±ôš1%E„CÈ÷˜2S]Á™¬€ó!9_¢nüBíÐW1Ͼ±twö@êk1‰²l…‘O?ß”Ÿ,§-RN'ZoÄŸÀïÿ•¥ô÷ôªëYŸÈÆœ%.‹â¢4 ‘ωÃÁ‘˜•GϘp ‡`)m¬,fÓh>Züôk˜/„É$"œLÈ­˜0ÜFSq¢—l„£¥bäCÂW&#«Œ‘N>ã‹*¡ƒ@8P¦ T ÑДaÖ¼±id²¨´&J.1ã³¢n. ÀÄMq8D8*rÖ„ —¨®Ž—¬•Àyaý7J$’jEË2S¡­N,\ˆ•NÍEî’u ¹c:â*ÑVL- Ë§&#[)‚MC`p#ŽP)ËJ¶º •UJÌB‰pôà^cc^üñ-ÁßñêY!c:íISju(ÄBlTÑÀ‡‘”ÒÖˆÃ12"¬ƒä§Q9)Sø³·Ú‡r¾£pÛMA u=¥L!–C™vNvÒj§6îéµQ®,øÎ‡Bšþ&„ï(Ë­„Qu ŸÅ_š¯"¿Š¦€r­.8Ã˜Æ wÜýŸý1Æ; [G®qúó·v›# ×vÑ ={ ûˆæ“‡+"Y­ÚÒÒ“íê¦Ö2·@Ψ½ªÃ‚ê9B”ùÉQËH܈SbJ‚_-¾f0!h-Vˆ=õéËb8‡A$~|§yñ?$Zuæ±Ì±Ldõäà›ê˜ŸMŸDI#f)ÔD7­?#0&¿èiöóÛ"[ªº4qîE-¡B¢•ž‚)ÿ*œ1E“.Å”%e*djÌHg`¥›Ömšo^í”{Ï"[Ƭ¥…Ðo«5ÕL=·]B«Ïr½o–+ý™aúöiû†a×LÓÖ ¡lå9ré¬[~)ÓŒS'BáZš%äˆ&kŠÃúDå‡+®ÉD6ºcö”˜Fmà#ðësc޳(çõëp)"Sk*Q·j™VK·˜Œ~Ì:ѹoÖð3Çë§\’•ÞNaɶ½¢µ`ÊAX-B“uV´ùÏz׆+ˆB‰‰´i‡@ `Õk%ª+±~pðøp–rÇšÔù¾ÿÉÿE’t×Y*½ÎµÑ&вJäãO¿Ñ­µà˜Šº9Æü:t¤q²B8ùÒ§ 4…³DhR6•é@p¤Ä©““pûœ“Šßê8ÈÌûUÙ*J!+ŠÌ ¢h@|£©(‡Ž±Gæ”{NSÍ5¢Þ¥;ÛíXòË4ÊY¦ÀŠ™N6G" OŽ\¿¥›²|YùcÂÙ@‰8¢ìÔ¸¬ÚCƒãƒ¯¼³µ²žÑà@)l –+¤"f„ðJÄvn¹¡|}EEûjøýÔOHÆz Eü4tµTÝŠ¶ð|Ѧœ:o~ÌwÇñsøö„TûÐISëªN1]!Sõ`ìÜ@65šŠê*Bé¦õ „”!¼N„ˆ× Ï¿ýæÚÝ¿wWˆý”Ë4V­ \9ÓÌ‹€,ß“-…6•ÒnT¢n-ªs½#?‰ø‚[Ô{(eSéÔ8š4–˜Žmá×CѪÃDHÄùb´¥=öJ—˜HE%Ú|{ÞGCÍtìôŒ¿ãˆ\Ãw>‚9Jxñö§RE}B%¿]å·V«F´ÖŽ¶Òº6-Šö­ÙŸÈE‘i–¢`%H)Z'–x#šè݉F_4ýtªÂojôÄêñÓÒJßh÷H%ÍQ‚–¯a*¡)KŠZì¼-" ˜@ñ=-\×FGH”ÃZ*¦zFœ´åô· £4‰³Ä9õdJMº4¶) ’xúEù¬*iÂC,ɺ—à· Ëä0„ZuîÊÍ/´¥ÉbdáÆSõ:·V®hü’”)¦«]ôhýd>ÕvVIÇUK:'M"Õ…¤ßðeY‘cadœt$¾ó¾)k«ÚB8k¦eVn*7_QÄØ†Þgϵ'™22ƒµ!eŽºtg¶3Êß{¿ý:Kÿ^Û4¹ª0 ,!8~Õ<@!7/Žï¾ý{£ëî_?¦r)›Öê6xQµp:!ã˜zn½(qÊ\æ%×É©+‰d·3q¨Ua.7£©6àù­ÑχSãëÁ[öG±çÿãÖã9„¯²,) '%OˆO­³±6ÎÖ_LÓG)ø¦ã¤cuŽì³g’Ýp÷÷‚"ë¡_jÀ¶B¹üÎ=~»ÇQ—™Fà#¯óÍ-ÇŠúH~jís íšÛen*¥è]\tÓ{4_?ª ˜†àÛ>gÇ¡=42S¡|c>›\«Úæ°ÈÔø ÊýxÕ™ñT¾Ž®±e#qªš™\&§2|µÌT±Gú2ˆ…Ìíc ´Úš+]´©_бe$^"œá¬í¢@"ªp L«)óWH”&—ÂòïEù,5ü¤R Òõà>õì„F¸›÷¯Zu(O°]âSFhÕME!Æ–ä”h3{úºûwvÞË}õ5àê’nÿ--Á¤j¢3­¨eêÍ­¤Æª.dŠÜ‘âDΑ‰—Â7"wÜùL“”¢m‚´¿óí Ô³º¬„¶ñ«{µü±?É<§_–wÏ|²>Ÿi ÁØÑçך†M[ZÕ­ÈQ¶v£þß¹íº›÷0V´ˆh¯ÓF%p”«JkÒ¤EÝ÷PˆÄ·gM_›ª‡®Å&5Í–ä’5­®ý饵s©˜8­)§#ûìDµ¿~ý²:YüÒåVÑT m0ëÁ”ˆY¢¬B/vAK. :Œx Û:jÛm¡du‘‹`œ¡ñ[8‡2f_ȸՙ¦ ÄéxI$›2|‚q¤@bùp"p ‘åòkGô?îwu‰ÁÊ'!ŸÕM!SÑÖ Ù”bK)ñÛñi­œ›KÄÑuêp˜,cj9!PߦU¡L§…Ì+7²*"”eåל/½G·(“"O§>åÞg8)¹MårØ;W»,Í»Ò(H‘›¯Ãœ6ßXÏBz°äZ-+°,'.²ëê×%üôHuâYþ6“oTŸc´uF…8s"Äáé5ՕĘ)ÀcYÆðÖe:ó…¬ï¬'Èæo'^T%–Û’BçF|u9qrøô1õàQ­Äƒò¦^?}E¦"RÚyë’hjá§öµ'¦­WnÊpÿmK¿“A)£D ŠõÜX¨4C“Ã4&±þM˜6ŒïùÓÏ`èÛvc¥+J³"Á¢ºª¨ÂÔu‰™:!-§öl»o~¶i%úZϨP¹”ÓW‘NÕ…L‰@# Ž¿Ì:‡<+ºêÞ¢â K$ÈåMµ¡Ð©q»«ÀÛ! oí53)NþÈ hj¥l ­Pm@8v¤?ïõí¡…kƒ“YÝù,–níÊlš#J¥ ?PruUÈJA _ˆß}žˆ‘N¾Dðr×Ê•Ä!Â8UeS#3„SoKéTÃ,¤œ-Ê9B×Y[¿~Œ©u9µ„B¢œú©ÖôÃ}ùc»€?š×=o{±•®gcåŒ[fŽÍæ˜j;Þâîá¼6r–‚ýá¤Ã“­+`ší¡–J ¿4>μ|ãR´ÁoéÂòI©’2§ïæÏî>9õuùʵ+7YÑðdù­Žió_üRËREW¤Øýªù”+@9ñ˜|Çb‡ø’ù~ðQÆwM¤„µZŸ4 l—ŠBºôì§ZÑŒº•ˑ˗✴ÒïkßP×»Oq}ê¤%·v|uÕ¢À) ”^?VÃr¥¡,KWp~å |•&5N}Âùv©Å I4J”å|0Âa%é“^J‚BWÆï[„r­7´¢ñt¨GQcàÇÇ19-LŽäð8ñD1×nxº˜lHêøÍœ8 ÇDSÈΩ1¸Dެ: åPKR¢i‚,Y-¡Ä8ôùœBõ„`V®±N¶R±§¬ö&ëo‰ß~OMöÁÜyÝ_¤Ëm-:aüz[êÈÝ´&«È/¡fмþûo×<”û:¥ÐÏ*¤‰¤YEŽ~àUÌ©=)e2šF¨±ÖOPÈfš2 ,2}‰Ê…ÄYQ·NŸ¥¤ ?˜¯­üÞŸ8\nÕm )Ë(T^{©Á¿ýAQQGÇ—Kš)™C°öš†¤©:}æ®a!eùxñÎÇAoÜf4[B‚® îï­…ršsix»‚\5Ïv˯4Zm´ß¡Ehúí(ÑÝŸx²F =l¨™R€Dà°zöªtÔqRö¡©D 4m3 öÇ|ø·mõÁ‹fESÛòi¶?F!äÖnÚVĬÛFR ¹¢?nM:Fû¼>MU7æX‘PÍÏiO„Ú:Å¡3Ú²*Ñ80>¦þ—X´ºšá¨Õrj9KÇ¡ÀNÿKó¤søœšÃnxêpLÑênÚù)ÔúuY(ÁøÒ­ûJàÔŸN×@ÇYЍQÇX34Sm[Ó4 çY;Ò(‹ ‹–ˆ‘‘u¨Vpd1—ßÚ3å#¿ù·_Ê>ï%[ˆBüú $(x–÷yknŸ[…®pø¢øÆg7Mœ»¹&½aµ@¸µóÛI#Û†(§¾³~LóMGU1MãJ°å™“à…UPv+ùÛßþæ >Œ¾žþã?М!øzF°“FRʬ½…ÔFÊU”"×ß¿ýñwOÇÖXJâ²çœpâø¦Œ/¥~D5ðÎ/¤÷å'wK¦oé­…xŽÌÍB_-)ÑξÃá¶UWrµäÝÿwA|«ÖѤŸ‚‘fK®:ŸSBµ‡Æ´Ñ¦Õ’ö¨ñ…ð‚çú‹Ï"Ô|óã¯2#h4%’Ÿã$ ä×UL)¤øU7•U«g§Öiñ2„C·œ¦Û%8Ù:ê(%2!ußx?cï}ÖX´ô¦‰ó9Tá;Ç"¤L!‘˜FÛ)%|HÑO<Ž…­*?-ÉÀUm£…Ú¡r#˜2Q#ÇYØF¸žuÀ&uq H¤}áÀ!E9­Ùj©iŒq€,5Óš,‘ß!Å1-E´–hZç௴DL ‹S>A`g¶¶ë­6üîÓ5Œó£¹¹ø€¦«Îc:”«¢·ÚÛz ©ÒŽi 𶉠ñÊùf.u‰²X‚k»6ìB>‚êjÑ%jÀ§†ãCŒE1 ™’-ë¾p4 ,2¦{D+…<Y¯‡D2d]Õ^:¢†‰ÓT¨¢!öÜ7KßÞe¹ut”^WÝBÒ! IöZÇÙÕ.ôæ—?þ ã~×% ºtØÊÕCú|!ý»¸t‚ãÌéø²…ÿÚ”vZ–Þµ©5x§z}ª•ÚSKççÔRS>AOÄwŸ„úY„ÒL'F¥9L Ðò9¦L9ˆ¨1jÛhZ3øÍÀŸ]¢&Óp:@ŽQîü8åBÐ~örþ·t8ßH¼”§Šº…jÿ­1ý@~霚1MœòZ 1 Ì ÿì] äKh£›bW ®žQ[u`4%‘"ʵ¹ÇL"¿)G”lNé6B(M!IŠSÂéŽÃ—²bT¢(¿”œÊAXL:”0å£Ñ0~)õ\ŠQÈrjÌÈÐ øü£þù_/!ø£9Òþ©g%ÊUNkœ¦ºp{¡)ÊÁšr qL…Li¾ó…¾WÈ~ü#‘`Ê49¢A]ñ·v¾ðBF ´é‚dðdÑjÛ”Ùºí€5R†£Érxö5‚„»³BLVcÇ‚O¿êB5&…o Q× ñÛŸiQ¦ï³QüÄ%Rh±üUÁá…,A]¾•sÛõEÿµ©Ø¿©f97RΟ”6\på|Và@$Fk ©1tÚá¥uäjÙIÐ`D–e 'dªPnR 'bº,S¹!´¾ùùZ}ˆ^}(aL³©*+§! éw.I1­n¥Ñd阚Ñ3¬)ÿ™IôÚꎓ2C6â¬1úá‹"°Bšá‘)pŒ|š|gc—íŸþé܃dÛ7Ӊ˺„?žyðˆ`Ô~¥)ˆ65VÔ^ÙÓÃNÑsÜ霥ÜR“¨½Z‚›ê$5üέ:ë9»sí¼—\;ŸÔ·mèÁ@¨¥©R"ÆW]:Ú’áNT¹|éåæÇZÿo~Dv5õJ®D Ï1mj£†b8¦uÒŽiZH'üÔ¼ît÷wî9ô@üúÏ7Mß4Èô6§©(ƒ˜2ŽDÆaŠò ¥ðñj9HUùئm=NSN+O¡¬D€I; ¿¬n4Œ8!˜ AÅvÄÁˆÏo ™ÂheDŒ!BõI§ ‚/âÇS݈ƤèùNÇOVé­·D·o såÛïÖóïÝÝÂv©H¯4¤B-¡¶•Ó¤U·¨©•ˆÉ1>û·”ãç¸Z|ûŸfO匬]2V.šqûÎŽ\F†Dk F4kâ¨αF£ÿ_VØ7I-U±#H0Y µx$sX…Œ|âúq+trˆwóÚåý·˜•@˜¯[µÚ(8ÄT”ARS¢ºžaïÜeÜïV”>“n-66MSàôÕRH•–¿¨,“‚ÖöÚŠû¹p{øÉ%&ºRäÚpúœÅ'kß4SÑÅV‡‘¥´©ÄzÈw÷ïc¢{ËGÒª%â—¸é8é+”ø˜µ ÈòÓýý(\ íÒFÝØbL‘cÆ)·z¸)£h‹Ú¯RBD㤠Á¹—¨P"ü‘é0:!~`‡'„—Îäròeq<~·pY|Wø«EŠr)J;' Þnã? z‡U¡Q.§6œO‰×pÓl*uñ˺¯K·Në¯/¶ßv⽆Y«®4²*-nŠ©Vm Å4•îcÔIÑZŠC‡Ó(Ê·]Ô8RŒ@ÑRø.6×ç[sÁûK©ÐçCêš«ËÁ¡Ïôéäb \ !wa–ˆ1'?§]š`²jYƒFª éª^•oO/ÝrKl¤àø¥´Wðü…RÂȘ8ŠÒ“2}ó—?ÎIç^étê!ý휳­6ÅdB@£6JŒßl¾?é×$ü«ÙÆþ N Í'?§Zù¢Ê9ÕüJ¬O“[FS"uÈÑÌ›)äªPhÏåtQX&A!Æs€Œ¯«öjýÇͱ–ýûçîþé¥04ãÄMÓo¤s±>¢Ìn„ãè!Pšá"dçR©ïÕk©i•c\+UÅï0Э-iNÝ IMtYùíTšBDl1RJ!:Œ?}‰[˜Zp A«>³–:”ËO­b–HJ:?…rõ aR¸ƒ‘]íû+w%žn4Î'…$ºähr¾Š¦ÓðDLï ê*š)²©Þ<„о1}Í*ÝB4L?_(eQfjÄá ñEsŒð!z`Ñ„˜Ðƻνs¾º˜nšîVD®ìÇÓû‘­‹ÐX¹‰´–Ô€¦µÄ÷âïEøë1òi¬oü4Í(LVb:ÉBXG¡†ëO4DZãP¨1wœ¢ßŽÝvÕŠC!NÖ¢¢‹ê¡64àf¤±‘q„М]·w¾üq2øh%K'Û4SRd9mލ©Š Í’çl µ¡:ÄÇÝöÇ?Bøøå¥D!YõÏa¬ŽP9‹2šZ5²68V«ùUÝŽ…DÓÐ%ÿtè‹x'Œ®îŽ6ARž=tøâd5S•˜üzËi!|Ÿ‡úý1â}üÂÂ)E(ÄÈL UÎ8BþÃV Ãhz£Ì–Ûôãeœº¹-ÆŽÔXÑp„òK6íyˆàÀðá‘+ÌÇ!§~ ñ#ë -sDãKO!rééð9áÎŒ¦…‘è¤!K ØYˆ™&2Ç2~ýÔÌh¢F ij£ï!gÉ;¯{¤Ünö•⪓êFÐp¦Šé½ \“˜@¦¥ñ9ìýÿø„6,`‰F‚Óç´iU‰Öq3üÆ4ûÖ¦M0÷k¡.`F§ZMíg)öÐ=¢Z¹;œ®IjëJø÷ÆBT„·Ã”Ýú}A·ž“¥FÓVè¤DcjL•#¢ #Ë„ˆÛ½¹B­¥M€û>÷ÛŸ–&»Ñ5ï»!r•c|j ñs* T)´F¾qD5q›{ñq*£cäxVøy>ÈÝ>hã¾øÌúAS¾Þô`,Ê·ÿÝVôÁñb˜IÉå°Êi¶@>£ÐñÕLøzÝéH M½j<4ðuê‰è ùÇ?þAßsÔýÍ©bÕ§­ëIi«ËU"D”£‡MµAÄûMÊ¶Èæ»'à·N{‹|*]'ZUŠ&n"ÔŸ0Y#…°#tùdñ‡üM€W~ej4ŸJŽQfµ’ÖŸP÷îSêêÀ¸óRa"pÇÆØÁæˆJI A¹68§÷ËøÈp⣉ð“22´Éé,‘ÅÐŒ@ |– ±3†TK«“­ZèÒ8G}š\|:ž:ñ¨OG9SBÃBF‰§ûÏ+Ÿ¸B ¹Bñ¯¼3`–¨%:Ú€<«~Ç}íH|â#Aù‹b¦ÄMEM§§ÏsˆN8G´– ¦Dœéø!)hŽÍÝéæR´uÀúÑŒ,ÓÉVÒqÅQŃ™=(ûÎ½Ç Z;PŸõO„ӞѴþE‡KAÐC„Èž7ÂkëñS"¦62jœ¤´× L¨žÛ¾ÂçØ Gv—á_šÔz¸Aß5SО\EçÔ¤¨íšª.‘¡¶Zù¢Þs_ߢºV‚Bšé[« U’Íá+m4-]"&>'ŽÒÁ‚:MÄo@IDAT›²×ý¤à9OÜ{/± ¾g@ûL¤ÒF²ùk‰ƒ™ ³8Ô€¾õRÅæ·ŸÚæÈeÈŒs¯E;¿*¥ %ÒÖ@bl¯àˆãøñ ’Jˆa!àGTg)&Á¨! ¿1šQbE…LÙ|Qú¬vqÚ!špeƹˆ§+~‹!(ËY•Ú]™ÁÙC šÀªD#¥ÕoD£©¨ßeöãù” ¯ù¼GH¤@H áËtåz ݳ¬>ŽÏ¤ï¼u"û;Gÿø«”ÛÏÚ@¨ kGàW¥Ï¼¦•¶åMÛR©i‰ƒÏ¬ºæ+‘K¿)š¯æÝ7“ú:Êõ² —¢ŠÝ²Þà¦áù÷}/Y²îÖo”žàöVWÒ,Ÿ&Ÿ )¾èðn(1­åä\ç¡½í¢…<©ùÆC´êHå ¦" iZVc¸QèJ:—:ó[€g¿£½we7¼zWÈJ)¹5à®dÉVW'ÆöÇÚ®/Y hÕ¢»ÉJ)êYè³×½âƒi+:J,W²ãCB¬”ñ…Œ5Ü4vv™išFS—‰“y²ß:Vçͱ®Þð<ú®Nçžhë ô-¤ZŠŽb?çJ¹^Â)ÌÎ?4qœÔøV‡ÀÔrä²ÂF3Ö[dˆhL#¼‘£:}S êZ£M‰¯Gïö³öM«RhºUg§Ý«aÑŠ"ÃqÖÏŠºà᛾pœÓœR!ÍP¨“œ6¼¢ JœòzF`¦tôiOÖ6GÃî¤JDËHqDuþúáRñ–$¸Æ$¶ou!ƶ‹#ä[oš÷[?ܧl §Ó:‹´§‡tò·Àú¤¬n+"n9˜L¨UÔƒºï<†ÝGt"8ÁJÛ·Äë°êEô‹®œó„¯%|¹:A0¶ ï|ùCÁ“Ut*Á1¥ÉÙÒªK–Ù7!Ë7*ª4°QbÌF[álúÂ\¾l±t¤`rÚ¦s„RCã´WñËmW‹†äwêÿ碣£\²–\÷nÊvÕÛž§f¿‰ÐYa R˜]ÅäåØ/þNË·Ü^ü…:è»Ö•‚ž…ºÛ@²‰‹Î„òK—­i¾ºmKǾ•øqB› ²Ž:¶ü@Ž|!eZ@œªÆáÛYhøœjĹŸOrEá¶É ó‰pôTÔT!œz0¦cl¯! ¿^'ü)2–Þ.¨¨ÛB­n ”ùÄYKFhK‰ã´¸·T_GKó´§©t ²8 ÎZˆŠFGH-þÅ:k lëJ7¾ó·¾r=Šê™ÂD”àG0Vš×üCH'BL¨má­ëéeœVt±Î@§¶)ËrzDp¼¾Uysã¦`¯ä*Gœ_:YA#ßw»nÁ÷dšéÖ望Hm« I-…RSˆÅ„È2åX§¶"‰9®ó7¿üñH;›òù®šZ…WÞª£ZU¯S; ÑÀÖ…iKI=ÑúVBâjñIU×”CGXõµ4À„p Ó)¥#[ôYnüL‡¬ñ5)å…Ú˜3Zm#W«, ‡r]Yà唳|Vº§”–\ì>:¸Ð(øé¹e„kØV(ÁjUÊ!c:÷."JÊó¿1µdTˈ QÃõ ™Ã§vÕ9Nˆ©iÂMA¡ô)³à”¿¿Ä‡–Ü}[²nÆ–0õê qT"”oÊ¿jÓ(ÍÑÆÔ©ÔãåJd1!ü8²Z@UT0M;“D1Kâ¨e2f||Qd¦£[oÕ¥`+ù1Óä‰Ì_KdùÀjñé÷”• Ñá׃tgC"Ÿ¬ïÿ×Q÷Ø—(ËH‡ƒªÃ*k©žj[”@ˆ\.¼J[õ;/ž¥h¦Ý#H™ i™ÚÏ@£Þ¤U7Å„X»DÙjŽߘÏÉ1ùp¹t²*ºcîåè3ã?þ·—,¾Q.Árù”]„=†WW?²\l®´6ª5"èÕ’ô¦FÊ¢¤D¨í|£¨ð"žµ0û ½3çÍ·/¼z#•NýL“SÝvMŸüÀZµ@S†ŒPó¦úákÆ3U(…g£›N¯ÿ(3YV )Ý8\ôCô P|!,·Nz'þlô1ÈVБNÜ8}u[¬id¾U;'+gT±ý¼JªŽi ?~ÿC_WÕUnÕ!Vís¼§¦g@¯\dì^úîSsJqNr„¤l4ùVJ™oQø¥›æˆe™ïÛZ”i[Z/ÄT ÓÒ˜r%ΆÞÕmYcir"t¶™â@$êØ™ÄºGeÁuɉ™/¥ªµ˜&>ÍGH¡*5©ŸD–؉H ÞV Å1¶w…( ¥Œ9N´¶^tÊù-«åÓŒìSö‹?ýNSÊõÉoi@Ó6Ĩ¢r÷Åj£äªžŽNJ4¾¾®§à¾ÜT¢m§ÖŠv¤4ÀÒ/díøFµ˜h=p,>§Î«…#½¦Bö!Îa¾0q!­·¯Ž˵AÂÑ’W~W Û¡DóŽ–Y¦Òú™¦©Ä®@x!Ášœ8GóF‚Ä1qÈõ Í´•jég°÷J+*7Yé¦jÕ†)ˆ®¥S€Û4¯ÿÞ¨½0Eô©UŽˆZš÷ wù»îh²Õ•‚¬–êFd½]%¥[&¤a¹Sü >Ã*†Q4Õ©©Iah9Èåš¶EíOü8éð1Ï€WXBÎÔQ‡Œ[U'MûRá8uc¬•B˜EÛ4çž«JYË…°úÄ׉6œp|8štQc4‹OÖ™á’ÈOÊ¡BË-ňß4‡lKvóúñUB:}r’Ègt’UËá7ªœVãDbB¦BL'üp ëĨ“˜é¼÷Z-OœB`Mª}rÖI4 ^KD*M_¨D4;pׯ´ßT¼nÛK“eâP ȱR;ïîˆ+'ärµ.Wšr”ÕeVÏF|Ì:9höðð®kÒ(Ä’U‘­‹s“½êœûµµ‚¿0LïȘ|L²œª˜*N™yoéÞ¦õ¥Û^éÈžˆ¯Ÿ©µçÕÛAüÿ£ìÞreYŠl ×oÕn¢} D_B<±¹t£>?çXQó’91éX™6ÌÜ#2ò²ææP€ÔŽ 5³ÕW–r²<°^ð˜|…a9)õò4¼uÊͯ]­étDRd è9‹ ðäí46Ã`6v^-KÖ¤ö;_Ù&e65âb­Å8n¹þ%®‘TŽaÌ_•ÛoYL`¯_²bö."…(@`)K¡¥œ,‚ aªæŒP!~%R]àçÜ™Z±\¸@{rÍ´¬åíö¹¾)¤¤šŒNjRâ×KŠY²:£Áùh@BáuqÊ î€0äã+ÄOvâ` ½ç»±€Ž‚!œí]/EñÆP¾s'©òÇ?‰Pžˆ”i™@÷F%‹P,ˆÃšVÖ­CÐ-Å›á凚)ø**VBMP;Ggiïé÷jo1f4‰%Ûlâøj¯ÌÙE×¥íât°vçûÓóo-8ŽN ƒy®ùÈïÑO£ÓsßÇ+b6íJuªšR0k08ZY¾€lÊ–¶0²€vqwQ`:&ñƒûw> øÌØóÂ$§Ü’¬˜¬¥ëË M¡ã0ÓÊJYY 'o²U}êm°?ºÇì}­¾¤È65« /¥$ð~¡áȦŠÜ;ô§­ztv+*¡©¼]¸ˆ);U‚b7‰‚oo5šHµhªxÁT+h#bYKUýCÑÊ? æÃ„‘˜¾’3âá‚RDàI@;„nEÃÃÕBF NH…RqXj|Y:²íàlû•R.Nªl`d„øâ©!»FR‘n?ùö¸“Ȧ‚ €ð÷ ¨©â¥4.UU¸¸ŽmH!)²ð˜h¬Ú@š®:M‹]ÌÐX)KY>вr:h¼l­ óx¼=T®$Ž”_®½]Cž›W{_rë’¯»XÀh&b0¦;D¶RÖR|®Öõ A`Â=¿3 /!k¿ µVèÞ"kÉ7’ <&Z„qŸP " ¬„ áóD˜%/ëëù_þ`Òıe– ļD=úùKòŒmþ)§ÏÃY8o#DböÊ4*x×A€0“â- ÄJÈZ*xï1Þ˽¨r3ôQ@\9ψ§Ù}X§ÛG£3ÓÛík \Ì|(yþžJ–ùèM³}Õh)&âòµÄéÑÓA!0‚¦F¶ýî¸7!„'†ïS65ÑòíN ^kÞ'eY·k|qAUJ01AÃÁì†ìbùq¬^ ¿2oÒÔ”óª(ãkÑá@iŠqdÄÓ—c$H"š;_¡åKž¥Œ_€#€·Í«èÑ×NS®—T"•ð‰ œx<~gl¸Õëw¯Äf]o)]õØ­’í<‚<)±ö-Š)¬cüFÜ~N¿ËtA`ñaVïÖ¤`B̺˜mw†x³ÑÑåÒ>Rb^-ŽëbÓÁéÎ;ý.ûæ·lRþ؃BÇKGL`~AóK黨0–<ÚèºÌi™á÷É×ÇOˆÂ—æDÁ!ðݾJªåºð5m)n‰píþÇ¿Ö@…&·_ó8+G×µ€éÌÑø-ý§sz=øÜ—×3šŽÉ=úyŸ÷iNmÇBˆÉ{;Ô¨îÍ/KJ,âAIÇäÝ-÷Íö…ÌpZòY'SJ¶w©‹û¥Cs38 ƒñ€¬-¨4ƒ%B"Õf—µ´‘J0áñávôÿÅ›ë4ÒÑn‡Ò$ÄNÔ¥vb×#tøqÌ …ùļ3½:„D4…° ÉŠ –lYLˤ6¤‚¦/þ•?¯e~:¼;óå·47˜ÁêÈ»^ë•2°ñt©„av²mj[ƒ ß=AK#U+ ãŠÛu'`É”³{§oàMˆI¶Ó(Ž ŸÏAk/ÍBØ!Šámµ„­2Á&FËbF!²¬@ B­-½Â-{‚”ZöMïì¹^ Z…µ°T•²¬™55mO¥´.@ǤJšX9)%J_ î[¤¼ÚsÛ?²%‚¬ü^(nI©ݵƒ3­y8TÌ|§êOžORV‰Ÿ}Ûuj{!ýí Ðt/æ@VUd ¥1BÄÜd1&ϼƒ²{ë±Z/E{Ÿôûâ‚c˜|jb4‚ZdëÕØ¦tbé«j0̆o*A4&Y4Å‘CšÁÏß9Ï\{¡cÎû4YfTÙfð,Ónc8UË Û2„ÅWîs÷–=·%¼Ýuhª,Û¤€àhmŸg@"&ãT+†˜ß[ïË7!ú>þ§ ÜRÓÚ5OcwS‰K d‹.õ…œÞžQth;)%!ª\¦çïLø¾¯'; ešíš,³ôTÁÉšA ˺ë«ÊZ¾ÏÀbÞ¨†I‚œý;¿v¥x©ÅôKÁ©•E`dy ó‚¼»(4³¾çÕ›œ€áñj®Õq]-)â(L"%h³f÷Zʲõ¯KU|xœš*¼y„ßu,Y£jjHWó¾Íñ"ó@Ób©|"p&ö-ò;¿·ô§~u·…º˜ªóžGâzÑב¹·øŽTVŒÀÄ MŠSö$%yi£ ”ÓàS†¤éTí½1ñ x&¸ #ó‘J®éÎx¶ TÅ7•T4 bÿùRŸz"ÿþ÷¿½Øà]*‘Ú‘(·½–µÖÕbÊêHÍS“ÅŠ›G€ a)·$ ‰iJØw»ÞÃü!@âJ h6åô7§¥.½ð{ô¨xj”ÀÍ#Î|¶ýοù¢KWŸÓˆ%Ò’¸.ÅðÃ éØ²ÖjÌÀÝ9>5üýÂüôïƒ6Õ@´S4_/ˆMÅ:’Í€/Fƒóé4ù8^#/ß™üÅ+E!IV¯Ôè'ÕÓ_Ì÷BÀwjeSÀ‘Š,K­ó çY-p0-›¼Sµ}x…Rm3}UòUa²^ƒ8F iD,ïdñ9Ü 9*Ô€o¸ å8c*× uÖ @ˆ,¿Þø–<„,o“ÌÜ Ãðü ©‘²döfy'èÈ꘎.–ákJaU‚‚&©gº(4˜ZöÍëóHž_dû-bRÔÒá_ksÚ;G;²NŒGÆŒP Ó'ÐuyâûÑ9>}dq—ÕkþÊ×µè<#ßÅÒ¦ˆˆ¢ªr4`šæƒØËß©=úû‡¸žwª•ŽF–rȆԽñN¿ëH \÷Œ”×0DI3•AÞ9wÅéàìäkª„Eð÷6Î?ä+OÖÓ÷ª¥Œm#)ó)7†%k<´îÃ[V#)d:L€ð„ðäõÑ™)ìQ@@};Òe!m "0B¾IXK_Ž_¾ )é?C¹¦8/+²jW@M¶ÃY#Û”Åg@žT‡ÀlK篜÷¹Íä[~ ðýV—>‘ö›AÄTá À#ÇG³l¤jù˜e[òt0²?$f½Ì Á‰ŒfBÙ: ¤Ú‹¸€ODmdA]š°¾€Ô¹ö‰j£k9*Í'U{©$ÀÚ„ð gxãBRKJ\UL%ð8.€¬F•‹•3œGúêÛ<ÅáÊÛgšd(—…»î–b…h‚ºPvKá0(2ïü‰…—º|ˆ©%Î 1ª¥Ëã#v¯7Ë Ž—ˆ 7mÁpÂËßR”gžªøL¡.ö«#A­yo úFUt@q'€#Þ)²Kã|T¢‹€~H’àË?–'îûS|²–Êᆭ@-ÐXYˆ}ÃÒ´pr(vÅ–¬¬FéÜ ‹y|Yd³3á=V.gÎ?NÞQ¤Ö9›SßYÝkA«Žv‡ÐŠMŽ hƒR–1_>ÝÒôãO· ypÛ‰Ô9¦kãõ›SGK´I•5Œ+»-Lç]àMÈ—°hÔd¯&ç‹áfÐzU ÀCêh¾ 0¾8¦%Že-¼Ü|éœæ§§ßw»“%˜N³‰•ÇÙ¥éÜŘª*L‡·T(…fr÷C·D´4!²µo³˜mjj8b&H_P¬Q± »€!wÑ–ªøÇ{(ØN*6M_±Ñm[Y¶lAÙt*¯SU\a"˜m¸ÙŒZ8Á5JÍ’T´M‚ßÅÀËæ ˆ³ÅtÜ©¡Í8ZGVJmdOWhüOô¿¬K”%ß%$ÂÌ éõFAª¾¨cåøgôk©$Á¶¯°¬ç§“¼M⽇”ªz!Ô…T¸T ¥@;A (àwβm '‘ö%ftªê÷–­Ôw>þû¦â'‚&i µëÞTmA#ø8‰TÍl*Ùö%XLNÈ´¬MÉRhl:‚Êq"|çÊ™{À'¥Ü´}Lé  '(•~´–¶ÓlªÄ¦‘p";Òïüáÿãt:Iʉ›Äî’Ê#”Ò¨“l€ Ù¨–h[Ú×w>þ{k§¦O!³dt¨9 ¬ëԢDŽ ÔÚ>Nš–<Ð?Ý OÍ;´ßpÔg5ÄAµY)ÇBˆ ÅýTÓ‡3q#!´„¨â‰´YåÌ’!{V¬PÇ‚¼’Dšž¸Xà[bBZ’²,ÓôñE .¨¼‹pÜÔkܲáøJT Lßãu`j|¦vNÁR/1‚)y£ÀÙZCÊò‰4mâñìs“ZW—¸ñöŒÉÃ,&K^m/NA­käCÖËûÓç7“bíLE‡ró[ê+Õ.è/…V 'ÒÖÂU%%èNEó[J-¤ž›g±yHu,Dj¤Ê ¶LYò–µN³Öª"¤ópA¦Aa ùH_ÎÿÌ~"hÈ6NÇ’õ0-)²çÀ[Æ‘êâ!íK€ÜlF8 ßRmY‚8@^6¾¥8¦ÿøï|÷òØíß]6½ÃRwú Mwç †£ñ›§½÷Ó¿ÿ-ÿ+sõ}ô¦¯#)ú<2¾bIª©à Vwˆ, +dßùÏb¼µ; dUÊ5ª|"ÝWíÝÆõêLq®æÄÒ.ÜÿR sâñeýF÷üI#/[̶ÆéØin†‰á›¢—rULŒÂ/¢†\Ã3Kx[€6 rjâä¯Ö]ÍâdwÕÞ½~ÓêRJ¯ê!aA«â÷ÐĹÏ'p|4êÔaªê¢)¶)3ÝÉl`sÒÇé(VÂËâx_ùvˆì@é¨2|âðûóN?¯o%@U!| Ú¬íoƒ–J¼3©}r>žþsuêKY¡1ÔºX¼Zž,¿™ã4Sµ¬dq…ªBxÖ À¤‰“Håðu<ì‹_ëhpupø®¦¬¸¾]8œ” ™2šÛ…-[ž!¢vRxE£H!]”Ç{œÄðãÀ…Àš¬qCjÌK•EÖŽT)4:TóÈ6:P ° ¾µe:JpxÖ`|9|#ù$Òh¬§Lí0 ÜÏÿç*ëâŸ×ü Ù†Ùð‰àlSb­-Uѳ¸å|h‚“&ÿý7?ª$nB}™%eA²NUÒ0R–ÀÈÛ‘³ê )¤V!ÏLÅw€yï ß™Öœš†8£Ö`!¤ c¯Ïž¤ˆŽ¼’vDÄlmDU105U¬9eq¤âÃÅíÝgL('n ž¹/ÿá—¾t¨Ñ×ÑíÇX A/xqò‘;ù¦ Ò‘eÞ{ɯýkjªž›1|+mkIñÙ]–f ,ïŒgfú²|gk#bœpOÿ—ÿ®ƒ©Ê4u±äÅd鈛¤8Y\GA[~7Œ&…FÂQÅSH¶¥ÏþÏ¿¸Éw£~'Pnž4R c7†F›ó~V1ã4ª!k§‹›è¾*æñ™¾pÛlÙ¥"¸!˜bœM+²ýæÔ1&Æš$¾˜aÂ15ªÅ}ŸbŠÝ²WÕƒfÙÄ46qäÔE(vyædy KÊQÐS X_÷úÅ=c †P ¯Ê’l§ XÜS#åš*Á÷¯@@æævµ*ÿÊ»ú;?jš6˜]àÛ£Ó®1\V¼-àT‹Y!NˆÁX×Â*'èÆ¿4gâ)†¦K{‡LV»ÎV‡>å«Ï#€C PªIzùá8å}/—ÕËÓÿ;¿SÓñ‘¹ ÞǃwYºÐ7å ¶cDP®‡EÎÑY#U¬ªb„‰ÐÑÙ–}‰yy3¤à±«…Ó²A­1ijäHÛ‘mŠ]׫»Q irL…˜ÀoNBÇßSU؈ 4j8åÄÛ»¦²úòÚuÔÛŽ¬*)OØ—ÿ¾ZŸ²éÛ/¯–uª²@gbYƒ1MùjãûÊ<^×͉Ϥøøy²n¼wà £±CH™ ˜Z}Û2dÊ]…N-©øÑBLþZÈÒÑ‚8PÌ' &î´+l0‚‰ß§ªcøÈwÁ8­µ €¦KÂ’WÌpšR€©RŠ£‰Ñ¤˜8MÀ.“Uq±ùjk!N­Áq¢)tñ([º*6ÏÊb†Ì7'5¸W…BHjË)Xf~ceROÌ õ_ÿú—y5ešl]®AÎ$ZÔ¥Cà¥lÉê¢ÈÄx±šOAÊýÔ“ÙJ™°-QB­i-kÑF™)á×úšå8HÙ˺S3•*H»ˆ)åÑÿÍg~!^‹ô§FÜÀd÷h@(»Á^,)HÅWÂ,A{±ÄD(‹PÈÊO¿ùÍo¾ùô· ßé\ӈߜ¥š°‘¤ “ lD ¦CN8ÄoPßùBß? ™ª)Ÿ.eM|œ“uõÅ¿Ïa^¾_b/²7ž Ë§£ø®©—FætàL‚‰ÖU+6I;Rf @|5yò í?ÿùO?&¢© ó1ƒ¸î&+U¶v@˼ié*‰¹‘æÉlüÎLŸ!(G¾dN;†€Ïdõâ!™¬%¾ |Á©¼@K7×>¦Ö–Í/ áÊýŸµÁ“«_$ˆ±º0âæ7·@ >3"ç=}xWÝÅèÚ+48]o‘ Å™ò‚é×T—î$Ãóð¥ˆÈòlå²N¢–o©PÜ%?õ×aéeà—ÿ»êןü+ï|5J!ß²±›Aß¶)(ÛðNCÐTԅѼ¸Ív€É>÷ý 0N:4Ûc§×óEwÙšv z))n;M"¥. ˜HC®\à¹ùò )dþ‘° æ‰o£Úµ¥^l/lÈ]G‚+O¼©Ú#$2”e”¥:%>C°‹_ýêWß|úÓôñŸÁÄ7€ ©J–G‰ CÓh®obû¼ZˆÏþ/p¯£7yK:IÑÜwg –‚Ö‚â«âqJ^\RŒòý“f½{tc4C%¤“•šø†AïŠs÷•O¤™ùvGž§sκ®Q›RÌPÙf iI¢qù¶­Ê2¤Ñºsìb#ÀÓ\ª«óÙs[:/­±ƒXɪ¬Šï&Ê6Ï®§ÂZËZ⻞ÿ£¥¦ýÉ¿MIy1l€æé©AÒ’·lZUm "n n™fÏqËçÖ9t«‘²}wžI¼ ¸ù§¯Z åv1Ú˜X %í®½ˆ=ý›Ðûãp^~n]_úÚñd›Ð –š²‚ön)°µfScáÍf×pˆe´4xšA]ttxÒUâIgS‰àem–>¼@‹:Šæõj<ž¢Áqª ñ‰ÄÚR¾axº=¿ú¸~üQ®ÖØ…©ñ n›@‡ÁÀ{ßûi‹emć}¿†Y:mÿô…ÿòLœ$SËÒ׫‹Õ0–l1q±Ù˜±ª²|d>©hãàûmêÉ_%Ù¯W._ ‘öR‹:·)RÆËB¼I$ZˆÃdR8‚¦³¼+»v°D€#›aúbR}h“ÕY _aãUˆÜx‚D0#ÃËÖEÜÙÂ!,ÚWÂZ=ƒòØ!¼˜…+®¬%ÏÆ\|"MpD¯ÏA¦ßž¥€jó^bç2ì€_#"DSu@m-¦ZÙÀ®„ò ¯i³¥™§£Ê£êÉ D\­{¨ÿÂS¬ pó·âgŽkfâ”›¤F8RãTbHH‚ž˜uu”—…¬ãÕá…óJ«…Kï¼öÜ@=Ah©³B«l`qƒAÄk¶e F ÁQè¹ÙsÁwmŸ¶üGÔ+ü*pÑÕ0qÚæÎ„ìýXRÓÈ–²‘6°‡xsvÏTÛÄRuÇ·…nSùªçéÏ.ãå}ƒ±_ÙŽŽˆ.š²Äyà–âáÍÜ$<œm0ØÓßçzïÜÏ?ÐG#®œgmöÌqR‡÷±@Ü€ @NÍÛaÃvÏO߇\,ïˆNæùïì×&þÇÀ4•˜'©k‡£Ü§“>ÒYJ( ›oÎÊ;Cn/1æ“ÿ½ îFó´»zu8bYæng@v Ú^xx…bq4ÅB(Ì,ކŸ‚%¾T£–Uh)Δ;¨{y„ªpôâÏ ×aÞÅu¬)#¦oHUÅ®µ–æ>¾T#Ñ@–¥++®Œ´ ¸*Þ²‰õKDUA% l‰&š¥·k¨ëc…ÈÌçUäñºƒÇ¿ÏpÚ_V'âYFV#%áÈp|jm^ ÔºX*¹z>®±¥a|t• ÿè5òô7aœµ£_Ü´bAúâvg’¶`)e)ó$a-XËÔÚš’Qx2ä}l%“mžH×H ;©ÝX–Qƒ†Q(›&þÅ=²~î_)ý>æ¬ð{3<1sÊRc‚ºÐ„‹;ÙâÀ{ ŽÌß9‹áÈ4Û»X [khKWÄúûq‹žþ><ÿG`R>þ§ÀoqK^#]špë+E¡XÀð-Ùžþ^~_òÇHá_y?¸ùÍÝÌvxjÈwÍ–,ŽC–u,Æ t_- §¿c‘òšòÙß»rgõÕÃ}iã•°R FM–Žêo<30K)LKrµí+Dà{RŸlÖ}²§¿{³ JŽÝ®zÕˆ¶ù‘•oózóìèÏB+)¤ÆºeÛg³ñ†aô«ÕÌ/eS-Û\ßnqȧ†ãƒ˜Žô-ٙ㺇1Py¾à¢ü8‡¤cD(0§ÃÇ4A1š MåâšÂŸM‚‘U­)„Z½¦LŠx`ÃØ©e±Ù»‚%Cð qN …{y<ÕéiD¼©šDÜZ t™ÕÚ®œoâ@â“A…Ô ²m¹@\¡-ø,b ®#ÄcÔMh0Sù¤’ üSóËŒo ‘“µwL±BfÔ‚²b}u´d²–L¬J–'åg¨ýòãéo°çÿâJÇ$M˜):64Rç \G±,rWP,ÕM¢Äö÷ô÷ޏgªêõ•§ƒŒFV÷𶻯ƒ3åRHG39D!³Äá!1)@ªEðo$æLá'è•ëÚ鉮TçíWV0BMá:Šyž5v„ù”‡ã賿ªörMtÎÍR_š”^ѨºX¢97 n¶¶)ËÓoZ^ŒÈ'õ_y“¬Ðœõ¥ÐêeÙüN[§,;ac÷ž QÅJ5y'àû­ŸŽÇ„ÖhtRÀb‚iñ k*`í ͆#æ-™€¡)l‰ïNs¼ÆÓIMac@e ÷ÓŠ‡HMý†îcLÈ“TÄ1yÿé´YHÖºñš­Ý̲Ñ®‰ÎÝ%PîRÿêK¼aü*UIƒ}ôžþ¾µàÔ‹H÷¦˜™ÄC°ÏÉî>©R#3øAÌØ¤îm-D¼ƒURU‡Òðiµ Í«âñD‹)E?} š*ˆØ„ç#^ ‹„7êb)¦f$°dðhMS­¬Àô¥[zRoìvÍ·—HÝS3C3ã °–ÎÖ<]ã­]¤ Ç„DnGm$ý†Ä´|i”i*ÇlÂúNvœ‰¯*[®…%))å©OÉzFôô'èiÕN×ëåœt¢Õw…pqÃKáXv\†©{ãh q8átŠ˜©²Ô¤öK ‚?øñ3º š'&M˯Ìc—µú(Ùœ;7`çÖð<Û0ô mO¿üôKš›êã7æûH.–· 3hÑQl*²º¬—*OCvpNˆÃ ¤\S/ ¸ ê+§óÇÇyn¤"“´…NÒ¨ÀâÚu8)¦¤“`»ÃIY¶/¨!?ÆÕt†ºÐMB ¹Ó^•TYLq“ „둊#uÕ ÊZ걯ÅR) X-|KÙ¡.!ŽTï[Ž©*@ÔK–`š‰ŒVRzáç-G;_Í´T,`K¦²jÄIÈ[’³œ(š%SK'Θh1=ÖŸßÇ1y_è¨i×Å&•ýH ߯¤Ì™¥ÓFd»¤®¢ÇÇL±^_}y$âJxêGOdAÛ©ejÊÍÅÇÄa:ºZR–¶F¡IøjyÙp“ ˜í‚G{nª"S#wÇ ¥ rãÅ4Xä`Új1À6˜ÈžþÎêçŸö˜ØÌZ0%/-)dâÌ0ZàÇ[6‰ì%|”›3¤©t¯ó‡'‚OÁf¥ÌY¡”O¦ž¶}Æ—õNïZ«"[»'ß ‰(éOn|d Ã©©^ø;}S#žÏ DŠ1qÔ∇—u&†DXÓ>û{úÇLSÓbL±½7Ÿ¸.•4¿ ñÔB"WYQ6*…m¡`âÈMSË[—»[êËâ‡eñ-³¾¸‹á¥dÍ ‰6qȶ¤liÔÇOÅÕºTÉ奘•MÆ×ŽÃÂmµÝ.ÛAmßj1_šÁ½ P¥…‘jd†3ôuK‰Óé½–J!kŠÏ”³fX`ÉdŸütHYw|tézÔK¡½¨mË4‹Í ˆÓ`š§!`@U18ƶ<3]w!0²%¾8þÀj_úº£)l6ÍbʦJS‹qš¶BÞˬÂ{G:ŽÅÓ¿wtgî’'xW»—|7gÝÛ;q ¾%A©!Àm§Âf3 ²É›A³¦M…ɤ¨ñ~öñ;»Žç~?qÔ‹ùü÷Ow¦+¨„Ù ù'6•¥ìÞ–Œj©ŠÁü:ÚOÕ>ø{xI©eÀhmç'å÷ÉöHçSY:RMe™9Šp4{á‰÷ƒ²cñ•N9_mâ¼Âwc¼[v!bÖ !©:±”Òº` SÝð͉á˺ý>}_Äq€ûJ„ i¾È,µh_á–z1)¸ Á´+6_¹Š¥(Ð •¤L¡Ž–½ñ ª¢#(®‚¯Žƒ²,¨$ÏÜ6²‚æÐ³ÊCp,ǼºýÏã ª™™P5k¯€bË;Xªö†«Ïî?…£Y>ÿ Ðvva™š¿Ë-Ö]œ~ââu¤P;A†ƒ`ì}VUÞggR²<&\yn÷ýz-)ÐßÞ•ßçA° ˜¿+¢)DœBY ©ÀönB?ûô³•rŸ}Z¤)Û0øÌ ñq>‚g´*jZ ðºhJ¤ŒpH1o³ôUIyÄ÷ßOˆ{ú«e²˜Ï߇Ìo`äY…ædÔˆKñmÞ%3 $|?ˆy ø”&*©c:ŸzjŒÀ8‰Õ·»ZŒ`)vhëôÔ*KUëõëÐ,ßqèwÿéã73å™*²avÛ¯{¸·d´ÈRZ¨Ef@ˆ%‚e…ã_”ÇØRÀpÞ’¥95|{„_ÄÇouÁD“êäÓéÜ5_­*`4U–áÀºXžÓÌÎâzÉ¡V&ê†n¦˜Š¥˜”}Z Ü|Ú;AjœfMg‰|Ç7núWÃã:Y­c4\¡FZ·Œ lLÛñÍq¯ÿÃøìÐÇÌÀ™°Ýчó”e_÷Rm¹©dŒ—e€¬ 1“M¤T±TY„ç†Ö­ŒV;–|åÄ)CðkÍ•ðJÜa‚²•½‘{ZõvÞ¿úê¥-få⤞ÚÝ¥/^G^—&á¤Ö’¦€ÇLaA}7ęؿ÷øàß'G?³¸ÖI5¼.hÈ6ØÑY~4÷¡BU Á|ã)7\‘íîmf4íüéq¦—”g®¿A O\Œüq€很P4F-d Úf')nK­òu‰`)¨‘^Æðp㙇ÚQùðK|%ñ[¦† 7y}IJµ(æ«jB©§$òÄ[Æ ¿Ù,™%ŸefÉÑ´,xÜ‘r­Ýí6º¦W¯Ò–Í1r`d±®Lö´½eùÿÖ’"¢0é(Íã¶æªW»ŠìFàÛŽ%3´Ìûk¿¯þÕ¡?øQe¿íEL°S¦iYSHî¼Èy:FÒ—áððku.C… Þñ¢QfÕJA2 àJž—ßâ¯|¨ ø&1j –bRˆ4žeq¸1,•4ïÓ¨ÏþƒˆýòãB$މPœw,1¥¾2ã©ê‰Ðx˜£×ÚELM,Ø ¡-ÀB ^yx[ðñv¿CÞßèZSVÒÕ¡ÓÍ#øhĽÀ›“ß.€MŸ±Þ^¢pqÇ~Áç¶ôç=LÊcËï-ýç($ˆƒ õdŸÓ|MñYƒ…Ô«Ô8Z8`æÝÎë‚·ôèïM±;Èf‚.=ä‰a£Å–†tæ¥èÔÂK;œÇ‡ x1ë4Ü~Ÿ>ýýfÛïxƦ¶QudUŠʼn;ç~{ÄIÁ•@š„W.ËŠyK‚WRŠg-ï3à3HU8k G€ó¥øSs™I*ì@,íº!)  Ηäkqîãõ<•fÒ|5‚ÞQ¯Öë¤p´˜¥äÞµÂZ¿ô::5:¼á+g‚NSÊY{jtõå-‹{™U T(ömΧ¿¯¾P÷Ÿ/íãñm­Öí‹”,Í–˜q,–,g¤è†‡4ÿ88 ˜©–â^>UëÂwGÖÅR@3ÐRÒ'âµp34 Äœ:6¯Mûg7ª~ ¦!lSt¾:íôy­  ÐTˆvq\&š8]¾QB¤Äª†[V’¸¿©÷œíÜ p>äÖ-8ÃiËæjž5¦jŒ CGmMy8ÓÂH]nA'nfŸdûÒaz+U…É0q S äÓ1€Þ‡Ú;fS¹¥Ø.45m8S¡švY oÙ¿–â1ÛQ3µ$ÕKïÉ`¤”wMÅ,ršb tòÆ+h ]8ÐÏÈNìÓOoýñ®Ù&¨ãâíW/&`$‹Éº:pH 6¶!¯¢s›Åi‰#Íð¤üÈÀª"ìd”7‚ l¾ÚÖ(ñpˆá‘!Ì)9«b‚˜K­*äñoú‘ÀVFÎp3z›w¡aUôº#ÇÏÿºUð+o§ÝùéèË:I:FE.e W¢3O²½;îá…Ì(ðÈhq¤¢¹|ðß'~7gqT¡Å¤¤f±ì“9e½¶ý”-…øD”Ûˆ-»4bfȦš,Zü²âÍïÑoì)»ÐÞº*ÇéT ÔÒ±S— Âdß ÷ó¼’ô2j Þ³LÊ’8e1PSw£Ï"4óx°G±mb&KgïØrÇK³Fª´³T{æx{yVBbH„nuoêýèïÄ÷9\EÇQð´Uˆ[2)ån/Òço˜t”+´ { ¤Ä l‰Ùx•4ƒŽFþDʉ)¹›½i¹@üJŒGÒåÔ·geLf¼ªÊ"0x—ìè^ì(JYn#p Ùhã· kËÚRVØë% 3d1µ™’âpåÔ” ÈJ¥Ì!h•ÎiÖX€ÔLcãEåeŠ„,ró5D4¸âRJd½È½+—º[µnhbŸA(+¤ÐT…ÕZ"t@‚ð¥¥Òti{ ÜÛ-ÖË'Y·‘F^”Õjmɶkñ5IK±Ô…”-ùj ÆcnSÊ¥,ã) Àdéõ¦<ó~P_Ù'æÕ‹O')^;…L U—¯©ayLOgOÿÞ¹ ãÑï•_¶ÙÄ-TÒ Oà`MKáÉœR^Þin‚.„1H ŒçÖÈ`RµË+”âIÐEW˜¦{Ï䆱 į„ ÒÉð~ô˜— MIïЖ¦ I‡ D¬…*óËîÏl<}ÖQ[ ‚^8›NìÇBÔgª\ G7X"SŽLÖ².˜}$ê(¼ 1…È+„ª´ `¯Ö®Núï|·‚aÔêh#mmo3N@U`]æÍ¯—w©O?½yãôâíÆhr|…u¬¶xÃ7¤¥€Ïp¢)1°'Æ.åh•Ì 5ƒt¤ڋÀÆSè`y¦c3Ká(/¼´Ï„˜b`‚!–V G9ÁªbV8ܲkQÎCÎí;6HÌ ›œ ¤–<“RìŒê!ööÞ®Z*w”˜Æõ´eÿÃ+)?€z?3]‡¥H ˆÐ,ÃMe ìJ50ß„8¾ÞºuŒ|göy°ž×½sì°l-ý¼[MwVë˜deYÃ(D GCÞ –‚ÑÈF¦l:h)C¹BÍËž½|ªz"ೆ!¨6qŽRùºH…·5oØ{íyÝölMË+áÍ|õ9'ÐgÞÑ_Žê-{ì× ‚Ô\2^y½ÌƒPJ Kú‚<²Øü6ëÑÆvÑ•_ü=,*Œœ²* ˜U^w\LÇï|Жu;©µ$ˆ` Ë:R†#¸óý·½•ºÛû÷sKÌ&AK¤@¡¥Mµ/à;sç(dĤ]×ÚÒq)‡ðy Ù,]S“$îêIY2„Èâ kÚ^IJô5âz£}7UK[³M"f³…ª’¥Ç´ÌgR¬Žú®…÷;ª¶ŒŸN ÚYŠù.‡‹8‹´DKJ ¡ßÁÇAJmWÁfãl’- ƒ6"–@LÚ×—@IDAT¼*ÄÄi SÃ_™EÃÙ«Í6ˉ8D¹ÀRÀ0O‚¯e±t+ÛVÌæÞfj¬%&á“âñ|ا0'UU8ìv|4SÝÍB¶IVA¡ °ŽÑÄ>€¸Å=ÂWXàq`w¤,CÖ7Ó—¦Ž‚†o;áÈdyO©£,£ÀK9=L:¬ç;nyÏùˆñ=U;4Hµ<Í1UIÕž™ÿåSÕ¦Ôâ'[GK Ä2 Ù‘´¶4Õþÿ!{©{R K5¡ ‡¬¥*˲—ÌCJÊ[¬'ûóiuôñ@¤ DkVL––¸³íqà!˜©®øý=¡ö-í+Á†„¸u•«¥ƒÏgŸp£}ôwfƒÅj—Ì×—™»QG¸ÃôáC_d·‡Ö·BxL7Îôï}ÅÈÄJÊVK?¤¥¾ÂQwD6è÷W‡x;jfš½Bï .µ#Rˆ‘@Þ‡/ëEí5b¶ Öœé´G׎镎-[ú^è‡2‹»,Ü—}±3²ÑZRÆ ôtѤ€ÌRÊíK,0ƒ”ž‚ìUô¸:é»×xYK8ÁÚñ¬*‡iJ“‡È :K«£ Ä¢ñ¬e˜&rËÃ¥ÎW£ºcZþâ÷¿ÿ}hTqTK{àñ *ã-OåÛFLU.F`sˆ™ã[?RL­Í¸ ëȻ̔{ÉÑT‹QÞen˜ªx)¦¶“gnJ·ŽûO¼Zø­ÓCA•,)&%¦É³úZ ¤ƾº/ñë+LGq¶t-cVËScu/Epâšn2ïøLìã¤J¾2´Ž”Ci)VÈ[¢EÀ3üý¥OmKO+¸zU¨2 ~ †dÃ4é„”5­+¢ä«Qá^6È{æ’Ò·—ߪRà‰v€æì«ÞÎD¡‡¬ ݯÃí‹W« Ï(ðÀæ/+U‹ nÁö#X"¤Ú¯FãCˆø Íã Çô>êfBYÓ‹aòÕv’N×b²v×QÈLÒ ïÈÚyô3/Ÿ!Lâ­ B§M;“æJ‰¬'“ŠcƒïzµÔQœû0[õe Ö䲌×/ë}hâ~?0³/Ä0×?^€@œ²€2Mà9—«ÄR ¾KQ¥oµF¡mVeªZK)‰‰³“,ËÃqØâ‘K…7ò{¢ùXmY{q‰û`‹Ö‘ªU¡( Úš™ÓDZ„3%ž¼”+™Çñ\“ÅAnÂv ‘åSSën4^gå¹ïùåo’øR“*K™o îÏO¿ËÚ¬»Zá¤ðSI-wt“xAîMÈÃT¬uåø3H3”JŽ%ŽfÉ»¶ÿôý)‘û¯¬ª2%åoÀ‰ã»¦ý—:q"˜ÙG§×qŽ`©JÐðy‚@©kÞÇ'äî«zun•ó •@6KaˆÐ«¹ã°Êù&¸j¥”«â¥XúRfÉÃC´H„ÏB.îÙuf)º×B””ŠÏ'R•øáñZøÅþðrÕymš ì¤ Ô˜z…Ý JjÜLwÍU)$åÔœ '‹W“Íd}fg¤\ï(Ë +gY  Ž¤ à•æâ±Åc>ßþOw‡‚›U‰òºÿºœp‚LÙö d %nqÚ–¦Åƒ`)Û='ÈdÓI¨ä-yȲ0)ôµ7$¦¸}©+±)»¾`#ݽo·©ÀtÒ×"„__~S‰yFõ$õªs>õ®³-PX\@Ø6–¦¸¸¾2|„¾ jŠF7I×Èv˜«æá©Úÿ”“Pˆ¦…φföž§c3w!´f©aŠeùÅÂÐüø%@­yœªª¤L%È€ÌõCœÏ?ŸxH–Âý5¥nf…|c@,Ó4†]|Èbzާ‰©Ö$U94-t÷ÝÈ5õ èˆü~²òõ…Ëvhã‰›Š %ÚÌR 4†÷EÄxï~«‰èÅŽLPm>Mž™Ù¨†tbÞ«×ΨfvöÏ øF2°ÄÔÈM iû+/u\J ®]j–vÔ¾H¥ÖQ4v:š& ¡Ó0x ª£u™’&”*€ÈL°%ϦI m#R 2Y©wY)"<¦¹eð§¿þõ¯It Úôv¬Cš@}õ+ÔÕ2ëv‰¼Óì ¢¦ËÉ»]d•»änÐO14w¶ûÆ­ÖZÔÝ„ÊõrÓ0/ Ö®fª¼ð<è4ƒšBúÔ š¥Áš¤Ž”YÌ8Ý1u1Iåºò+TKPŠg²R±  ¼¼f6Þ¨mÁH/Æԅ)¤¯Êݾ—°å dTß´¼x‘à &@cFÚ0Èð¶#…&å!qt²]Üø»ÉVe$B²n31A…ðû-1š.¶ƒÐ£¦J($Xy:ºcnxA1ÎŽ“…7°X€CMÌ¢µ)Ëö…“­üâ² -ð -±íÿôç?ÿ©=TCb<Á;!˪Ôk_Ñ:œÎZ?œ–â•t"]±×Œ;Õ}Ð6î^­ À"K)g¹Àü\¬Ä«Îíîµ!@n·p|Ö.,M"V;¾*ØÌ@îãŒ8~Êhd.Œ¥Á:^Êä²pZH}•³– ˆ(76²v|"Š-‘y‚¯sÿuŒ:_µ¾ý(i#}ªûÓŠ‚W]â†ÑT€¿¥MªIÄÖ£-˜›Í÷Œ—ÿ$€ÿÜ æ¹ÊöÜoGv§…v²Ý`I ÚÈ]Ù™À•(T¢!˜³«iéÑæŸp1ï…Jú€‚æ.ÂÏèD3•G>Ô&[#Ëæäë΋'° “àDæÕºˆ®×oûÛ½µl©º(gjMb¤’Iºôiek*ÐZ µš²²ÍÖØR 1e«âã ‹ýÊçâö2A¸Ž!ZÉÕç¼R¼êÅw¦óô^îÅëÊꥣÉmGÜ0ø [ê«6\@X f÷‚~¯÷ ñk-ÕHíNVÀ¨!ð1¾{tÎáø kÑÍS—tp©Õ®*~†ÏÔ¶ ¾›!qCŠkMª™›GL¶Q‘ÑHÅ!b6ÉOûÛßD‰Ö©BØâxÅ<#Áv=puÌ@q£ˆ;Ž^/W‚‚*Y^Œ,åÎöNàB@“ý¾Q`î7ãã-‰°3îu™MR;²ˆ¦HB ”’ížs?ÅLJŒÙë Ÿ,\#Ud^4`§ô®ijø¾Àݲ–b–Ž¥’@¯·þW\RøÊ{\š°î†!nž;Ù´>©ù¬ÚƯÃ;'cÉëÕîjm¶£ëœ¥0K [òÚékkRÞ·¼xï1†å7Íðf°‘óiÿú¼¯EM‰K!·SíšpƒEÀÙ. fÃT«…°—r‰ý:aàŸ LÇlž¹¼˜íh ”wŒÅtêeÉ ±Á&4ª’ ðQÉËľ)1¼®,Ù‘5ÆR¶‚ ¤I” ÔH‰˜ëS Ó·Ö¥’â ï{AØ©mx‚Ú1åø8éœfoßñ¯žWŽª5šrÃà7"Ž Ü’… v2Uc è;+åžæ~9õrê“—÷±ò橊”»Ÿ÷+™`3Ø…È@Ù L£í:"…\PV¼r¦Ë„Æv’@ú˜¼*ËJÄL_dH`äƒ[òh5å!,¤£Ð1¾ ì;O!KD¼’šò@jL­%ýW¢ 4‚‹)ð-íØS&1rLB’í)¿w‰Ù0d-Si€¼«»Û M›³€‡ãdð¥™G-o‰ Á4­e4>‹P–) ¯#¯Dª€gönòXj+©DÌšÒ©Q{QhãIm¤æ¯¤ÃQDPËîÓ¶D¨5AŸHã¿«j’Kïñ` iŒz%k¼ÔÖbûÝeÅTrï[ }8s›µx²|ü–MR–?wÃL=ƒt¬b`¦š²p9± Ø²W"îº F¨GÀKÑ$ÄÛƒïÑ–ÝÔÐjŠœ/ÆtÉ"SË0Ü['.…Ï“MM-¤.5Š“Ž*K¾ûÒ7ïµ—A¬Z2$Å[V(F«)…¥ x–Ž`Êbˆ,YR¾v~ÏabUéÄ¿wGfpå¤vÖ4•¬>¼mƒY2K`² ˆ(ÙØhÓ‡‹CçYš½™eˆV/c¿å×H¹ Ä;œŽH¡’Kà¸â¼ò*‚PyÙIu¥:Uå–‚^/[B˜#BVpUŒÌëâVwŸ›3¿¼‘+¬©,M)¾8eËæoxàéz™#…Ð M(YIËf³'«ª‘*Ç_IåÿJ>>‹áqx»àž¶ï.GµhZWUwË)x§±F‚F­»á{%ÞH²!ŠY{L¤Žy×îÝñYšÀd‚,æ“Úbck*;_Ü‘"¤ G 3-Òwn-k:µÈ8e»£pà÷ñâãÔŽ7@âç¿`÷šrʺóì¡ òøTjÏ_G¡—ÂýJÀ-‰T"Ëè¨ê€úԔȲ ZV!“ee/3´Ä©§rú÷*qsÆ¿›¡—G:²ñ ¦?/e¼D ì^eIÍi ¨mB7Ÿ]¥çÓY',P…Ö -Há~j¡95à5I…8d†¯&<¶Ð²I¦“¦Tf€‚ô#oª&±\¶”’˜‚Dj yH¿½Vî:îUfSÂÏ´¼ë7Œ”.m AÀ5J¡!«­ ‚àpî¸ -3MÞ’w‰Xj‚˜R"v¿5C) ¤—ƒ˜¬”ÉÂÛTââqB,©©¢Ìß­ŽM!d¾ÙZ*¼£UÛ„ôïûŠÏL¡še¾­YRvdk˜ôÅ”ã@j÷ꂤYmCF«P Øö¸à 'CÀK ;já²5²µ¥âÃÑŠ ÄÀð!À&)4A—’·”e‚t,5V|±ÎÀq¢UÄ#§Y‰JÕôñ  ú*«‘îíZàþëDhu˺ t‰ZÊ’Ž»•E“ÚöÓáë«05÷ D¼m4f¦VS¾’öY¦¦qøŽ¸©¤,ÑÒ!Áðb8_SàbA_•ÇljFY;dA;E@N0²™T„•·û¦ƒ Á(7RÒf“&µR|½à‚@n¹‘j§qø¬Ùè…t&–µ®£%MÖÞ¦€¬îù{£R¼*žñZ[nÔåh‰@LÞN«…l<œŽn²‰ãÐ4\œ'T’ZµM‚ ·¤ÀV(†Á²»/1Ĥ"P†-™€Á·‹Ze¬©X¡Ø9Ëðb».°Gå-ñ³+Nœ2~¸[´%½£lw]àCëú?:vP|¯Ç.®d»k³ ©F!$ifDÌWXl‰Ÿ'%àÓÇ¡¦$¦ªE…»ÉqR¨P¡B [/-š³¸T´6¨fçœH»xüRRSYÍjßôâjœ ŠÉÕR˼lº 6ÈRV•8ßå÷iWëJ\]®só+‘µ¬‘r†@¼ò˜²ÑÈJ-So±ÖNÖTbtÚ&\£ Ñ’¾ YA†¶ª˜Wéq˜Rµ ß² }e«jï²R˜=JŽÊí0•Ûo}Ñ”à§9šìDb¦Œ¦¤ÃD`².üjò8UR!¯D¶ãTU¡áY‚œ}Câó›™ DyÓNad"ÍP!:½½2ÒNð>jË"Ã-;†×´ª²@K1<¹ ë"¦–lµUARkƒbASUŽœ,¾@JP_‡æç üN¯x×Ý8µ3 ¼’¤¤XS]ù‡²lÝõjGâð=²)ì ¦& b°8é(×:AÙ‘ÅÓ—E³?j˜NÙÕZ²Ú5† ›6‰©]…q˜r†³Q-1í¥ åȼe|¾ò¼.Ä™˜MP\¡@•iµë’ „X)A%É^™s{o†Î|D8½¯ÓSžxU˜”‹ùkZGÊ•S>?YHœÅµ±â¨÷e×RãÞŠ´±Œ"K‡š9€–éK…¤ÜÙõD•D·Û–)7 D ¿<A¶áÅ;K„oΖZdø+Ij/6ó('Ë.¥Ç=­Âä¥(¨-*®‘Ž™Ëæ!²Ùiÿfð•Ã,粤€âR‰”â-qz1w†‘ʤǴTR–¯#„BÙ&ï‘rl RJš¿Zˆ¥˜Õ"Ž"1!RïDd³)T¸ëޝ;œmY•v òÓ\ƒ§„w}+4Éî=)Lø.†7§¾¸ÝYR«W4Ëh©\ Å&.–º°ãŒÁ«å‰¯QÃóL#%ü)x+/e)àâD‹yïØÉc"ÔQI{‰Ì§àú¦au‡\ÚÇ©b‚ôÅ1qšÄRÊí„“Bx‡´Dj Õ$ aSºø¤&B3©ÔàL!:X²8˜áI…ˆÑ îL"¶Ùµãñ¥ðïT7C;²d#ŒãCÒÄáÙªè3µô‘e\’¶»˜ªMaäº X>þ×@K·U1“V†z-YA¼½éTƒÚ7b£%—íGÀtÀSÁ´D¨KÁ}ž”y§¶ç‚¥ÉÛ3P#E$PÀ€<„ß`b“Y›jÚȲÌ%o0^#>â '+ˆœTËöXS JáDIªB¸€ XÝ[6p“@ªÍc& _#©È# l-Š-Gg¤ ÐM‹á-ùø¿ÃeŬij€,Á*Å‚Sp+)…sŸ3-êÂ#0LYË !Gµ…p¾8¾%&B‚Í0^’–&ß0‰tψY]•G 盇×H–ß0‚ÀšâŒ·L0‘&¬V\ÊRydUÍ •¾,«{&C€›<å‚4ÛN´|²˜—Þy%Ry©²|AµøÈ|Ó.–¬@IHÞŽœ3Y…µ|˘–BÝljVGÊðR yAÊD*O‡ÿÅŸþô§ÒÒŽÊ,ÉÕµ_Ї§d–•ÅmU =¼¥f4¾ ºS •]y½“G0~¾ ÙîB±£$kÙ±Æ!•,ŸZ-6•¹€GfÀbʤ*ÎRéë(`µ ‰o"h)°L\°cë^k±€>?dãlTËu©Pʹm¼ºX >Ó—¡ñIIé%6AKž™’bA"˜.Ъ xšøqxU•ˆ)£kÊÉxSNjר*¿LGv:@V °ŽÕ–ŠIdšZ38šX‰¸e2µu&‹30$%áb°Ô€,¦@G1µsôoŸá%ì°/~d­*¡@y­]Ì€c™¥V;BçÃ3xÃD؇\KYí¼¬ ;=ˆ%©<\9<3ƒZÖÍ<¤ÓÓž‰W>…{ PaÓ‚DÊã‰lYàðõ¢ŒÃ³¹Á’q¦ðÑòíõ‚æ|Ðj!›Bj›'¼Tjâįq~¼c¥/U¯”‹cò@–BKUí^,Î?þ»ü•ÆÆÈ Ú§Íˆ]W mâþPR-üà¨`ÍÄ=ð+W"kX;ß7!ÕRs²•ü[w·ckniºSÙú¹{Á'æ!߯¢©’ó '™äZU{wKòhtL´Ø}ÿó—²ö´PªŽšž§£5º×öQrV¢KÈ>㬘äÐ ¸c©q³¼v]5‡”™‡[9@|–øù'’ôï¶J¬ð”ÀÕþñë#V}/>ÛÜÿpR£·jCÙJn82¹™î÷r¶•`%íýR¨Ñ¸·aßšíC&šEÉ¿€kq$8ûýüpb â‰'3¢@~Í?ßÇ50t!†ÊMÄVíh =Y9 7G‹Ánšm#Ò«v©Ä¿þŸëxœÉíÜJãe¼èZc|Û΄ŽÛP¶3¾R†sÚYõupd®”'LÉ ¿‰¬ŽÉúôÇ俨’ëÍ/ôÊ1› g «”™ÈøÓª²2h<#cè»K-kW…3‘Ë]'<2·–E%€I?€co•‰ãëï(ˆ#ÓÛÙ ¯=g M×A¶'¾’¬Ôc2úJ=B·Võbþô_ÿõ_±¢ h^“šJÆ ï&d0½c˜¦ ‹T…‘0g‚ªJU•Ò¨ ع*@?^ÐôjW~&z¯é­íH¿*CÐgÒq «ö983Ác(Eª{#”üÀ·±êÜ`Õ9ÀíVž±^Êí™LµØŽskJG< Ü|0»{n rP® cD#âø-“[¤ÿqß3—9tÙ 7¢.؆ÄÁ3þ'ôÆÚÏ•Š^l ¥¨ÏQÐÈ4âv|ÿô혬–«=²‰cd;wYzß z>”@bG#ÖÕ,½ºT9LôÀF˜‚,ðdZD•aX;rß«d•Z€ 5<Û6F%¹U…cU¿DÑ1·œi4z„†*½½°–HJš>ÖÜtóIæhÃwP&íÓ†ÍÊp AV}¦!à¦*z1 ¥ÜP-½ æ ¿ ÕÚ›Õ¶}.-©TËz3ǧw ðÜbﱉ Ów$ä–T…³‚µ÷ª¹Í¶%] ¿=¾.p>òlÏÿ‡0)6#Ý~&í!Û¦oE“€–€»€d·õû[)Sjœ&«leU4&­×Ÿ2ž¨±e6B/F$È0¼.G澩. k÷ÃÐÏ<“¬ÅêŨ Gšöðiœœ Mbd‚¬ÊºD%-;LDž²Øžk!ØGàXIî"·ïð@æJ=²•šE?1&=­à”žË8‘˜ƒXæC\W‘ÄœbnëÙ6h -ó¬4%@Ö+¤Ñ‚p J!`žl&@×l L™­.dŒ\ Võmt»94ÐSæ–³’-Ó±Òõþas™R„嫊?ºŸèHž¸mÕcڰϨqJ}ÿ-SPbÖ˜7«×éú-ƒ'N&ÃÚ¾{ª¢£é6(^¦çCðkľŠJ9Äé‰Ü”xÊ" KUÀæÝ«Rí°AíC ðQ…ö\cd>ñ2F»YÈ×D #øÀ&ûT«Â"g€XV’g¨ WeBãh.€¦™g¼¿Udõ§¿ÿýïúér!%âU^ÀÔ1Ûc¿‚ ÙÑð)·¥Ržx‘¦Ì?[-)÷(·é¬‰§´=ÞD|  UÛDZó¬½q‰3—Uu¥”»)ÒJ)UÅzÓ`TÅ-~ÿ쫊ôš¦ðlhæWxžË1™÷»r¶aƒÌ…jwœ Ip‹çÖÓ ¤…u Õ³zË\ˆÌVëJ0^TÓ4OîGk¿°¦¤ïÕøÀ•Ú¾c†rV€ kcxbHYôÛCS/ÜbŽ€å=¨ªl= Aír2Ê +úl9`T±£°*Ð,% ÛÁJ¢RYib%†–É0}K⻩£YJyêUʳ®ª2ÁûóCCLÓ\Çé1•t <Ïáæ"xúzSÛªjw»KdŸ>\on ·ö`Þ’2ÆZcΉc` w3:¤h"éHéø:ÀPU‘®†§—Ó+!a³`¥ZìYWæ}dYaèãó¤˜Âψ#qÎMTBb8‹6©KÆxŸ¾9ZMiŸ)ÉZ†F)œ’ N̪#¥Ð(+!eÑg:¾Ý*¥Ç$ðHGú²krp4Wu%ÀÄ"*&Ró”×æî¢„çùV‘ M\N¶RÈfuw8ÞÐ~qñöûŠÃ„ F™ fÇÖ–i¸YÐ%‡„é d÷J Zož„ZöD°dûÜúùšÅ 3²F†ŽJÚa‚zó9ú ök§ÞHÁ‹t“¾Ld•vUÖ­®·{öˆ”Ú[FèB  ÐR¯*%RÕôñ“ö™€ ŸCeLÚªÒn‹Têάbhtñ™y;äŒiäJ͊Ęˆéešë¨*+Ven ÇÚeG¡EÖ’p¬‹æZžmÛ?}²|"a±lbSæ)#‰›¸ušyíªJŽûëÅ#•d…ëTM鸭’ÉJ³…ue2>e}µ”ZƒXoSkÀ V²%åó_õÿt‡€2—»‰*,NÛÏßOáô²p½É88 |].ãȰ)JpΰhI ÎìHbPI19PFZ²vVb;#E†”°¬ÓÂÀ•|Sø7®ON©#žÒ‡šXN *XÉ4ÍUmP# ýW´ù2HOÙc®wÔùÍÔUK³F: ú–a((12·VM¦ÔEÒ$ Ë"+ GXÞeᔕðU;ÊÂô¶C>ËkWõ·`JûáÔØÎÞ/è‘ ‚}.Söbdº0·ã`ÁŸ@Vr¤—¹ÉuÀ­ ˆ¶ê×P$“|0Âβ+è…å¦çÖg 2UQ;™j7b[•Œ Uáv+;¶IVz‹–Ô.(U¹­ñ<Ÿ¡9ÇbÁ¡*™#~sƒUµ×(uÄ$Kãè)b¸ÁøJ™×h.¥@ À*s^‹Rãò$;m÷+¡1Y›ôÝF^ïïÏ­<1€2„s»®g ÛzJHνÒH|úFg›8·˜.;ÛLS¶*œ­cLÀøJ4 _¦®¾“ÌÏ× å§¥¯ŽÎ]8i Éxâ‘|‘°^ySswÜ௞97ËMs@žKü<+ÓV-@™˜ž & zU³òéˆÙþuùŠèÍv-ÉRFw‹6¬%L Ô7Ò\Xè•‘EþªÛ9 Ó`½Llÿpþ×ã[ e#NÛÏŸCÄý ÓSè‚)…ªÜ]ZXuþ­7æv|bšd÷]Ïϧª«2¾Ë¦” FÃ##€3qq@oK«’åS»ÜV#µèÅhwì‘ÙJðÍÒÞLþ¹eNƒ‡…v½}?ô›ZΪ)”ްÌБÆqkª64Y/ÖE–/0JôæšØÎVÅ(‚ŒFh„Ë€R¦ì0A:v£4Û'™)ÆÍ?CÇ3ãö’!1Ö^£*C¥Öë(w¤¡ï ÷€°’ÅôzÛvLŸ².Œ£ÐØVÄ”0 js¶Æm"’¯ Jpï@|ìî25ö¿#¡ç‰oŠ#= ï“›ì(®Í±…uJ‘&nœ=7®*C¤Ðèš‘åH¸µ»’›\£.|Ê&b€vÀ÷V{êLÊ9·ª®5æCCðý×ÕèŒÄî2fðUÂ×£¡Íz ÇbÕ†µ®vUxæbd7ŒÑHo=Ù ¸_p}K‘LäzËxd¹ïw|âvh=SÄ|ºò˜Ì}Yë"k7 ¥ôq|K5îÝì³%u%nº.GXÀd²ðø2r/Ov;Î;5NÞJ™ì#àCÌrΪoç4b/Ÿ¡–¾Ždq;ΆĎ­ß<²çÒèh±Óy7ï˜ ÈG¯¬WÖÈ¡Ñì•ðÛ ßDdoØÐ ‘F¸²}¶pCéÃ'–ï:Ú)³­Ô,ŒïLnrnôêÚÚJUÓziŸ™Ôž^ž-Ï]²P*ØÈÂÂýfÀ˜;LY ¬T/ÓÂÄ~#„lçíXfÛèzÏ@0TÈÒ„»²ëû4a%k“…n-†iLž9´I& ˜ˆÛ0žÙ÷?£ØCäzr³k–[‚,/@?^`Ž€I«ä†dB©´Þl >\{¶ö™X =`ÛÖŽq=¤<·æ:Vª×Äé7B‰¬+À¢ÞòZræ†oí£wœmÓ(½Îpž–?cnUnDΰ{!s1ÐÕ\>ôE\+xJX´7½T»’œa½°ÆF7bü;‘•H&kQ­‘§Ÿ>Õ·ã´Á¹9Ä"F~«àmÒ2嬸 U‰ÌAv,«EúÛw6y÷$«j„•´Ÿ‘÷·À¾iZh”šø™þ_³8ø\j'ÓÒ悔÷ÄV­¤k#è3¡O‰dAŸ¸FcóËKuÿh ;“¥ÙÝL¤ÝR’±M³ 1ªa¥KRâÛ)"»‘ã.Ãg@•²^¤hUüdªÖÈPÚS¨G_‹ªR{º‘¯:F‰FïËDÖ.‘@Ž»»q"@Ë:ÂF”égºªœìm„™˜lsÙ-Tu)5Ýf•²Ïº^-Çî.ߥbdJL7úþoÑedŒ#ºÔ‘‘=%, :zb‘ó Æ 1² æCF¸Mxª"[=œgJ¹ ‘R»Ð(ˆÛ _uk(éMisú2sU¶ñJÂñN;ßTUÙñõgå(ZiÇ”›¾0°Ëf=2“-ÓGë(ì ´.z11 òIÙ1zeUú.pSC•ÒÈÝ‹,,«Rjy­Ö2gŒÞ|ÖâÈŸ[½LXuô¼J½¶F'ЋÏÙªHÕVÍŠ@©.hJ|Uæù# dAƪ#†):A“,Ì-%@Ö r½2R†–{ñ ¢«5®åÀi˜÷D0Rv4BôbµÈd §YKsïý¶3ÉÐ1%ÁFDb"‰ÇФoú¦(¥/Û)hÊÕ¾á3o¥Lnß×Û 80lCz@Œ¡i²ªck |³^ FV³%Ã'Y»,r辆d»*f ód]^µ‡íÖÛÄÑ£ÑGâ&ž…~^8½’Ù;ŸÿsÐ:YÜ–ïg†oж¡Ó bŽ˜@]Ú•`|–‰¾A²È­?0húý‰e>~-ni 2f²¬äfy)·’¤#&£¯3E‚ÄåFðIï:9”ñn 1€q;ÀE0þ–˜9“|ªrªâWrík‡xǺ€˜ªå‘la†™ôÚ J‰§±Òdg *ó–ÉD¦ÇwTu”é¡ËQU†;úF©&ˆ¯ãhb%$½c+Á@O<^·úŠU# r.O¿MnÄ-ìX¼]1gÌ ¥6tR’Ù} @SÈD¶t˜H#ØÄõÂxÙQ¨ ¯4wÌ-~U¥ýØÃJò¦ô2L0¢•¿W"ôŽwΩYkV˜"qAæ1²`X¦ÏDîÁ(Åï3b˜‰ÅªÖnU—êË™f†“i4®ª÷w,(E›¨Š1È}uû~rxš”·ã$K2|«•¦ÔEpßõû]׳$ÐŒ!®½YïªøªsVEîp«¿ôJZÈjtG€ o½È ÓØJŒi¥¦œ?îˆ3ãýT¨1¼D þ-˜¼ÐÒ§ÅŽ§ÌªG'Ó(§Qr´_nZê›{LïW?Ù‘€^æPÞ2àf®{¼FJ¤j„UE%]ZFä´pb$C·3ò˜>]ÌéE Rž­‘ƒÜ•kp>N]ðF¯Ë8¼'M‰777¹czß@æŸXWÇøHz çLd³ Ý•-–,%Œa•›c†µ#1b]xV˜ÛqRí˜[¬}ÆÐ`ú9Ÿg#²’E]òÞ3ÿªHp;”¿,Újd²_³™'–³=Í?˜ Ñ¹H¹å÷¿ãú4µÐô+dÙÂ4>‚4Ž • Úο^†m¨E eÌëïØ£ÅÃÓ¿S²êvMQE6ô øùý€É– oN #ÿŽåæîûLÓÐziDw׈$Àì››}D È¢meX{kÀ™ôbŽ iîóÓ!àµ;ªj¯Ë’ÀºjLÓ ¹ V’éÛ-ŒY•Uwi"¬*-IT’û&çàø–jDÇ-C87×™“­µ«žÿ €”bÖj32V"ÈWFæâïìÝ¿l’ªR iÜ–€Fiþm“¸Fß`÷¬‘3 ì òèÒ^oØQ)#Ò•jL³­hŠxÊÂôeøGø}“ÒËüËô‘Ý^ÉËJ²‹¸#·¬È¦¬·U‘yfë¨Ö% bV4Y9ª² WÍvp$Vmtb<%¬Ú—Œy²¦¬KcŒ ãن߉óÚ¹.G /I˜Ð-ÒÈ‹»õ÷+€2Þž¾$+ÕËD$ ¤1ù‡ebÝt$@&bê‚E¤Ü kÌ›ØE8G¶Xz8U‰aþH› ýÖ@Ú0ÍF#án ¨ÊÈ^‰›H#à iäý'rôFøN J/3›˜aKVÒ˜h´ý¤hb_¸6‘UyjÔÕ2Z€°\£L“^ÓÓØ§—A 8±YSÞ¦ïGtãšÎ!™)Ú7:²ýñº”Ð>Jid|8ØV°×H‰”û‚½¶”®f­7[%@ Þ¸ôòv®½9cz–z3lU+Õ‹ľ JùìFz ‰•4jÁ#­*`-íVcJ-ªxÕ4Û3‡üóŒ‡#µ`úøÆ2Á³ÝÕ<[@µé•rã4ŠöQê§@É6и®à}”2i%LßÇø7›Î¼oníi†»W[5‚¸Hù.Ü}õv5UdW†9DæÐ'…I€$–s÷ËA#ž²Å²íØo©js{"ûp¡ ëÚP@üñ Té¬Ú*Qc “åõ?ßÅ>­¾èC EuÛ×øözˆ )­š¾FbðÄ)c@è}'6¨Æ~Òèko“4HzA©JÉIƒ„oñûEC³•âåâ Ræ&sð9Ñø¾â›;@†‰$ó kÏr%úŽ™tlJ2c\ß¹FÔ5LP´v×ĘÂ9s3¼¹]äëÿùzô-ì+¨%qnˆl7½‘M$v”éÇ4e†N&«*Éö×È¡v9¾5` ½˜à+ÉvÆ—1Ü/¬5’©ê=m3Ùw£^ÕÖˆSrîä³­FhÉ &à¦ÚŒÌD£j]xLS6±’,èåùà u” ÏŽVzUíÖ8¼àÙñjFhd.‹|ÂGÖ ] çClĦ#­WÎGµA2ìÇ„¸}Ú­£ªÐ² ðùÄ¿Xãôdí ¸ªMêÊDc¨§' %žðr¶ â™!n&Æ'Ö‹±óöœOÇ|è·g+Ù¶Þóÿ(kCÉ]€_ Ö¬Ô;²FÒœeïñ+ɘÜ"eŒß}íÄÁoØþ™¡®ôÄ­áXœ?ßÎé•(E·1k¤Wº}ß„£‰æ"‰ý°%fˆ]9J [h„}-Ñ]h8ˆHæñ€–H]&ÂÿmßþŽœ§éÓ¶»Bn/Óh4]‡Î9À[ƒ0íÐo7-Tñ‚&™lŠŒdµp¬=fʪ–4‰aëák©db½x;Ì–É&Rj¡$ |ä¬È6+RnDœö4ÉÚ!“†vñZö-Ð{ÂL”h0ÖhíFG¸¹¹½GÓuéEÊŽ¿VÊ I˜IÈ6itk(!y:fk´_޾*kÌM‰§¬EÎð-©Z@îî0Aš²^ƒÚ„ŒOWVŸ9¦YíÆŠ@8 GUc€/(1­Ú¸òª×æ{¨öœ'¥Ý ïØ“žó9³ït¹Ÿ¬)U-£·¡ø«=wTBʪ­]IΩ¤ÝË´‰®Ü”2¤ø9À={$½Ì6 }ƒ˜Ìi‘C¦”ß®ä³2ežY9Úêx‰|7›Zs|vJµuzÕô)}ÿæ»Á1 ÊùÁÊšXÞ5ühõÉ!â€í ;ÆØ' Rp–ÇœþŸ_Çí@o²–á6Fžd[¯ç#À#õzô3æÆ±¾Ÿ½*ŸwÉÄBU2Ì•ÿ?ÿÍhÑŸoW2JSdžÂP&Jr†‘4xa°•"ÓÈ9¨RîËÄ#¼¹cJ@Ð;fÒhxd¥®à.“•¸Õ’Rî.;h§ií=i&ªVVòÄ´š¢ ä“s†HTm‡4‰ÓÄ;]Ÿ¦;š¨·ß•òïCQÒ…ÉŸÞ”Þ¶çå&ˆ‘4Í øÐ`˜£ñ3ì(šÂ¹%o`Å3ÜþÄÈžŽy|ï ·&C² Yå#»ìd»‘örÈ„P5@@‰©˜›RÕõªîjHÕn‘ 曆²ÑpÀ¸ùú5ñLºÁD 07]ÙG™€¦oZßdd+ÑÀ, zÛÚë-+´¤Œìûœ‰Ro’U-wÇã),³Ç)õ ÉsËV‰;öËÏDäÜuúй}ÿÿ¬!©NŒÎ­˜ÀQË» MŒFGÀ‘U>Yɘ•>Ô–‘–SòøxšµMú¡j1íÕµŸžŸìj:Ã.B«ªÈ†p²ªX—’H™Ïd<}@{Õ²o˜ÈÓŒ8¼¡Í%ȪZzd˜Ü ppwLíÙÂô½UAÛ¾¹Km[zUYo¡Ôù(™"››ÜbuÏǹ–Üš‹ªŽáU륱€À[oh³00ƪ™À/´TUŠÙ¶2]òÈÓùó÷2¼À轕/5Ú!M,,àÁµô}K1poh·J}pþÎÞ,$2GÀQ°u-+õé´†æÅõæY—jáã³A>áù·^ïé5ðd=ÔYåÞËòY9U[ÿ4H¡½AL67%¦õZ•8·ö1JŽ‚2ñ¦ ð!¦ÄXL}ß“JÙª[Þ‘ÒVœkf«Ò`ø0Üžj!PêšMÉ¡–õ’éUÂdÒ8þì'Vâ#j’Õ’³^G¼ èX #/B¯@ÂÆ “OG×Á´Câwîù¤ûK˜Ú}jÀl§·¿2=¨Å#zn]o{˵YúSҢ׺õö™áéiêUõ}•[ ©$:¶ƒ#¾o€^X(±­DÌA)fG²ãõó 9YGdòø™xÀH³¶²h4YŒv8‹c¸8Œ¡„e‘· e&í3Ü[%–v0ˆÕ]çûº´½ÐÎà–31Rä ×»Sµõ´;ï/sÃä£× ´¹Ž9ÈaŽZfŇFl ì¡Úpèj¥ÓðÓB@¿Û‘m=%‹uj]Õ6‡éÛ™?ÐÄÙÖÿç?ÿ¹ï$±¹[íßçÔ›§‚þ}–•€^HiÉžˆ³HGUGxãÈ4b”ð†f"s6]d›!=&O€~CuÁï[i±¼—»uŒ®z#E£ñpSÆ$–ù÷M¡ )È„Kõ ô~ÄúÐÛ“FW7ÅhtÔÅGU¯£ö‰T•ý+;bJ5ÊøFËM鎬ÇäY©k†enÄdÜ` lJ-eÌŽ@¸…Óë5níyÊ”õû º¾–øseÑlàxÿ|Ò;ªv%xË!»wâÜä–3µ‡¸Æß¯3&ŽM×Õ¢}'àŽùȯç|š.cZî"¦ëª‘Û”ùØ¿õˆi8&ÀÈ ! ¨qH½~žñ}‡Úá6ý[c£û0¤…"¾.V1 Ñ@_ñ]ð׬YÑ·§d¶ô€Ò¯—qDv#‚L6=%X¤Y‹öxŒ®0à(¶’.$1æã[²’£à#cfØ [yºЗ™Ìn ª"MY˜œÙ? Æ ާÁاj>¬T‘ÖóîÞJiš«ÑQ‰Ru÷šO +#SbÚ¡ÑH½<ÓȆÖÐ$Ó­ÙÖËù'ö”Ú] à4ÅKvd(ò4Ò§±¤àÙÏ„C»ÉBIäÿšTÅäéXUæã˜¹—¬Ô­+iQ¥4®ªŽH²ï_Î(`+g=Z̤´@IDAT_Ǫԕ‘\(ËÂ]l¯Cߣ¨Ò‹lñ|„?¨uyG]d ÂO<·J2«Èæb²•9è57&€ľªzE>Ž€#PÀöAja¢ .vJ2U R‡cô‡»)ŸWÿÉ*i-“•å׸Ëcöøzµxž¶%¨‘ƒ’£jC%|_¤Ñ4ËqÑ>z+éÂ0é­rCÒˆªôB/÷¤‰eo\-‰›%WèX½wPêjJUå¦XŒ›œ€^££–p1Zz+ ‘?L)ø¨ÒXèM£=GUbGb`Ÿ>+|7RÅ´j;DÆ7i”>¬HGƒ’@hTò‰G1åÍí롊á¦È"™Ãx;d¼†Éçœ,´·¶¬ú§þóŸë™~ŠŸ©Ò>›4]àö}©1ƒoQµŒÑ¢ê’ç‘®­ÏÃ1g‚&ö í*ë"V’Ya üœUÛ‰O=sxSTá4Änatd¶0ž!Àp `ZÞİ£€EËØY ëª*3Çh\Ö‚[¾# C%nsn 3¤‰GÖûfUV[øÝª.% à[Ví ÷b4€¨JÉ­*Òq ›ûú`DËãÍ•)וhŠ’8#¯¿v;¬>ÁláôŽÆ3lyL 4 9MSˆÿsÄ4õ:¾Ë#‹÷“âÖ›Z£q-¼)& ž"™#À“æuñTí÷éÀzµdr]O²²àÌi0‘Ãå¦Pjï¾8åëOlz œa7"Éœ2!ÈhùZú9¥És²Æi‰ÏŠ.»ŽæF_¨ø|j”‘˜z;öø4|DGLí‘ L´?† JØ-êÚ&h #Òï×f¼\´IšFËíIЈ¦¿ÕæíY ,XÙPµpSògÁçÍš'3ØŒŽßý4ÉÔ®/#­2²1² Ľé™ñó· U½1°÷mé07@Uûœa>cÂ|Sö9ÕHœ[2U¡Ô¨£Ü4þÖ&hD Õ.Ž÷\{V²¨dhJLÜV ¯ð¼ RÄñ‘ZrNp/q>ÐŽY×»c²n¹²mñµïÅÅÖàîÿÓˆ¾ä&]*LÌ-\ö±¶ª£x=[LæV…9èÊç6„G6}wA*9Vb‚»…jÎ8 ìX¸H—ÍDþ)žwPµ’.VÕ•f¯¤„Ô«EiS00ݱ¤HÖ8G%‘Oé˜90[ÕÓ#e™¦X ^—ØÎšOãX8ÈÃ!~þ3I–æ¼ê_ÿú×ÚÖovm˜½‚¶©YÐÜU¿ßŒ”Žkh|&¥¿­ç75úÜ,Ëd1›Ž¯w£ÙÂ9SêbÛxæBWä®@‰‘Ó„™PŠ ½JU‘ô¾Á-FŒdxPâu‘)µŒ’%¯Í¹¬œyV¶"®W¾fßb‰U3º©ãÑ×.óç™m#e2L¥ôÄ-Ï­å ”öJ94±ÍaÊ2ÃÚµâ6OïÄËÚeßœnT¯v¤h`´.Ï•œÏŽí°AxzžÄy&ˆ)+ÑP*‡ÔG ‰Ñ;¤ÅQNO·ì^°·¥ä Îü³%ÐE£$ˆ)æÊ‰ihÇKŸ÷A†iD¸§` ŒqlIdß@ž 4ª GL9O>[ ÆS”@¹ýk)_×ó½éµô2Ž rKÙ1–YºdƒT•äRÀ²ªà|¹»Ô•ŸÆÍ M¯“žR;’’¦Åé‘MO)¿âZ˜ä_«Ù¦qièÉà< è1ûò(U•ñ"\nh½ï¸cízûÁGÂò÷;ˆ¼S˜d›>˜«:m@wK 7@©ªÜнàÙ÷¾Y‰_·pßÝL0"qï2‡<7ÝÑ;ê"ެ±¿*ª¶LX$ÞCßQç‚Â@¶;®Š™ph–÷%}¢Ö€ÉT] 6—9¬— «9"Éü;Äþõ2 ¾eêuT­ NCÜæ}ª6Â1C-1LÄö×ÞÎ@z=F;6 Á°M<ÁÕž£‰ëJy¦ÞÛɦóoÛ™;*ɺþ3'Sê7²vÁoV-º™À¦(ú|ª¢»t´6²S`¥0‚Ò`n.½R]Èãûc’ÿŽ jÕôr>l……µÝ&¹íjÄ ¢„°v00QÎé Ž]¡eÊÆUrÜ+Á§÷,˜¦Ìƒ·Ïô@ˆÄÈ e-eU÷âÃ6ZÀékysU‹V‚ÙšÀ¬Ràe&í À¢ &ÍĪJ<ãùãáÆUňz+ÁE¼Þdå6lt¶&æ6JwÁ æ$˜Ô(SN¬‘FCæm 0] þ~ ¬™È G ¬³©1Ž=n³ W¥»ÆzžB5%¼߀u±êËW M-«EÎjnËÝs; ÉTwg‚|*9Š³Ü ¸K¥ÉVvä£*6(ð2þÃ¥ô‰e£»e17Àõé½*7ÕÀ~ ôÚ§ONµFJ¶0 D rf¥„ユú¯¦´Xžk'Ρ¡Ž3™>ÐÄ4-Ð>xL¤L,.qœ§i1Ç€M:rháýšÃÐS¼Vȉ›8V1& -ÛP© Ш”->ÛÖÞq½ª¯«j£á¦³Âì«e4²*¥•ødBlçdù8"ab<¬Y5ŸÆt5d#,¦ÞºM*ÁôæîññOÐÅ1‘ÜrðeÆt‹[<Ш=¾–HÙzhOUwÇ‹ ñ52Q-`Aã˜R¦ìRî®…@5[<¦{ñÇÓÈÈíÐq½øÜ¥e†Žný^¹%õ4ÒœW"À˘N£ÔzÏgYƒsê)°=XP:ŠÞBUh9os/¯äÈ-RõÊ¿DƒwÀñáVï¿×Ñç‘ ½*qž€#œ¹YíéØCC#‡fyµ*»½»ÈB;%ÒëÔÕ>Ý4üšpxs,²‚ÎÚ…£<¾öHXÉ,ÙtÙ,1ª \A{&2A_¬<‰à´ÌYá‘•z–É”R6EU 4V #™GX D.+½%žŒ7NÎùÝ67†MÌÊ&­hQJ"=q¡ÚÔÙ‡èGˆVÒNæÈäšýñSµ§ðæM¬±ýë% •út”L‘…”ø–z–-°Ua+Õ’ g½¾±9`ZÛ-è½’hPÊ^ ·Ír¤¯}þ9¼z>®à¿‰GgÒÓ™â‡Ùº©•²í‰úẔIß„>…Ä2R ·Zä–ñ”²¡øçÖ&r>¯^£ ãf¢^ ÅŒ ‡ådª”ùsëˆéMkL“'7ʰ,ÈšÅVbnÄJu5—XR”.Ï o€ú^"ÉÈÂëêÚŽæÊŽžF»Èjú†n ‚ÜbæÃÿŸ™ŒÆ]l%§AÚ0ŸÆ)ÙC,ø”_n½ùtwÎWõÇß õÒˆnAC2dS•M§Ú‡²#†l¸­0@>@»öé õ:ên dñ/™X;Ð&­D“›Þ"žÆqþH¸F|]Ü\³•Ú™¦GóžùdR¦!Ϊ}ò×â•”DûSy"µÃý9í˜Oû4ˆ€¡^IèÉ ºÄ÷3o\š)·¹cÎ2üîé°UåÃJ8T²Aãè-Ÿ9¼hPžý¶YûžK—<‹¾í”‹í@€t4TK82 ›âM¶Oþ²^þ{®uaÒp³˜ÏN)=ŒFL†ŽdÙ&H%I01d¥ ë’û†ÔÒûô˳µ'oˆ¿¡:Ú°[w/ãjXÉ{Ï^X/A--œL¶Fí]¡L<«°ã‚ÌG¾/©…P€àN¡ è‰4é>˜ú«’%h¡L*åÓÔx)¿@#CþÍÈœS4rbÛfî¨ îAÛDnŠª„1|,cí`Ȉaу¬Ú‘@ €+üRÞú÷9ªÎ-q»•1À½Á÷{3O>BÉ›tYÊ®@ Ö˜?€¬·é1ÖøÁ##P••^RÈJ¢¡ŽÆQz@T²†^‰&ÃŽò5øþDô—»˜”JY4 ‚"ÏFàÌÍu '“E*i>bÌ0|,€‘çŽB 0õröýl«ú~äë*3dbž5šž'™³RßvÕº8ëí×â4¦kÑ>·- ‹Œ Mú¦0q<{ßÇÑØ\9A][ Ï“Œ> d ²~¨aA@F#g (!kÈR&#ˆtYÀÝàgŽq$`âR'Ë-Íüwìñ;nYJLdǺoKL¤5ØÂVŠ9Žm,ï­ˆ0Öu Gv ²H€ƒHé•itÝ¿_=‰É| ½/† =~×fR )äY•3R¯–ž¸»e{›ÎOQ]²–™ë"ÓïÈ·\6BoKÂU·’Æ«ý~tUÛ(ªfePk§ÉDþÑž—ôµhŽÔ”zaá 5Â)µ`´¤‘¨Ï ÙgA @òÁì:€c¥l‰Ïàû1ɯ¡£êÚ-âa>Ž4ñò|`Voµ+à_Ã0²5èaoÕ;Ô¢dçèS†ñôÛ¦inúk¥æf«— óp$ Dê’alzÁ¢OSÎAI—Ÿ©Z|7 ¥&«úÖá‘ӯݔ¹ÁöÙªui¤·ŒÌ­ª5(û”-ß7z +b]x¹cx'N#ŸÍ~¾6ºbd¿4ôò”‘Âñ‰4K6%=LP£@ön.¥J9=F27«.²Þ ¯] ßè¬rƈZÒ„kQš!0òU¦ÁX£Þ =×d@Aü:bjwA=Múu½Ö%l%ëúõµ4Ôøä4Ržìÿ\Û8P €)¦kPÒ2%#á(ÓOÙÅ´¨ÂùÀ òlVŒÞÌS¶:ÙôdëÕËp«æðkP¤º, ¥A|Ú&YžýY­ŠÄD²Õ ×{éógáaÊææ¹\WÕS¾¹50>§6©º=%ÎÂQî§b†Ö°! ¥v™9«Àé¿¡±_øœµ µ/š% þõÒÌ$L‰‘mE‰˜$óé­Ÿf½xY‹jVÙbÚ§h4*žŸ?Ýi`#ð‹ØÜlMO¦%ÀÐ’ô¢vL˜f€XûÁ®É?Ï: G¹4L`Sð|šû½_‰Xµ«Ñ‹=&^; èU;â»B»ù!烔EΉËd5ªÂECoÇù”V•3ác.qÓ-" .U-ŸéÕàE½ø÷[á¨Óß·)ËÙÂæŠ9ðÇñzö>ýv©»Ô÷Ý€9-ª Z€¿ˆ©šéhâŽL0"ÆQWXv$Þ e¶¬Ü˱ïÕ™w¼êlõ5ç  „§oʆVõ€ë¨ÚfEl Ç^ŒøüS3ö<ç}Ðn¢Ü°È]æ"£·ÏŒÙ™Œ 14éçÌ3ÞRd¢W(É152ý©ÞÂrCõn%-"F®£÷VN)ÿFÈ“áá”xží ‡sƒ³rZú $Dz ÀœÐ8¾‰‘2IÐQ¯£F9€©««!1‘Ùzvú÷‰¦OP柭#À³‡ê8åpl‡2ÊÎAÞþ–¤ÑÛªª%ñ4xULnmR Ù™‡SfˆÑ.è5Î U1õÊïãdÒtzíU“5´=ÓlÛ¦ ) ø—Ó(É¢5ˆiø›RW³üÊnÿ|dJ]ÍRªQÆTå0Aä&Ãë"ɺK•`‹åŸ onU™@9T²¼˜F#¬Ä‡˜²k´I½å¦$« ææ|^[¦±ªh‡LÒ÷ßžÀ$6 ÄmÒ1Acvd^K#êÅ$nG +Á#7´‰•NÏóý·-ž3‡@ùæíÃù{Uúh¼˜*¦GvdES{¶ªFzüJúÇ?þ¡¡se¹àr•gE L)rGæ¸^U kiØN²jƒ Þ X‰Æ1¡Œ¡¼ŒqMT²†.€À7F/ÌÙQÀ”c(3ìðSÐs»}'!ù€‰œžIŸbÕ”Jø½{Cûó ÏmÛÂpd[Õ‚1ˆçH)/*%Ëd¥–ÜÄ4å.≸…uÁ¢}ß·räó:½ã”vÌh¤4BUvì¹â ð0 æO©K —+­Q‰LH‘8p‰ïGo¨ð‰Àmp«s]í,+ ü¯•Ú¶•óÑ˧‰2ž O–ÙOŠ0o{ÇÁ†ž+ÝÍÈ^¯µ“%ÀÐGb„‰ZèÐå9'ó—LAœ†p»¿—t´IÏÕ5Ùê¢qLìÀœÇº?[¦ÒYî>…v²Zrˆ'K©4SÖõÊh|cé[ØQìÞZ™•F2Ÿr›l4€,"‰§ÏÁHC¬ ãTv&ȪvXIÿêóI?eb]3‡¼è3ê©[#’IᨤÑnaØ“ÖØ¶ç`¿ãz÷¦hX ¼KÂsICœ‹cŒ#ÒÃC@ö#Ñ_Š3—»p Ñ`ZÓÌ–&½ìŽùÏßòñ!ãßJí€Ì¶‰Lø3ìȧߌý4%R>Ý‚ ¦•Æ|d&án2ÑŽá Þljïú” (»‘#²F†WŽ`èâk—‘é/˜0½c#ÊŽ‘ı•pŒëó_“æÖHI]GNc؇'Àh@ƒÒÃ|Èd¥Óüó…\âü°m(FoëÁJ) â¯$²Õ¢TÐTƘ Ÿš8§AªrÛ±S´à»Žj@ eJíñ0†•oFï0±"Û_n®F¸™{¬ï¿|gÛÛ¶|& % (ݦ3ZKkt)üvÃÌ$œ¾Y¦pX AV8Ž(ñ‘pÀËªš« °Uêµ[ÀQä@f*G˜Q IpÖ}¹!‹l»ç–P‹}¨L0¸•S\ÏÙQ©‰ŽÈöÜâ¦hkÏêÜêùû`ÊLÈÊ-àÈP©qp€& ,›¢Eµ¹È¶"k|íܰ¨W‰F¯ŒL)'£ÙÝ1Õ_ÊîŸá¥4ªÖ»+|¿”ª2'î.°éB©‹+uÄh'sD¾Ñ#ÄÓŸ?bj§oºÜu¦WâI¶ŽfµÀÞù iwæ—,·ðdùôìí°öà’Ø.ïgÓ†-OéX MU#xV”š¥Ôo|Ê€ìˆáß¹2Ÿºd˜Y˜’²WRjÙh9qXK#â§áPûŸþö·¿a…6l«kÃP³ƒ š§d@%$q¹v¼€ÉðËÙV•cVLˆëÝ8G/^晴²Ð® 샹Y@ŒZÒ˽uOFf Ü,²ŽÈS;RÖ"´d;²–ª•l‚ÄðÞ‘gÕ›f÷¢lhJžâ×›þŽnÆ¿0n+™ÃP•¥È¹l 1L#:‚ÀVb%x]dÎ!0²×ÞÐÜv̇ÈäÎ?Èö“_KËhLÖæªÞmã&ÞzÍ"íoYä4lÓüz3¤Wj À¤OdåFÀºXX´‰*Ò1Aâ^c ´ÏZ*É…ªÆö‘EGù Uma]mèéYU¥ÔØ8ŒP•1ðx>û/ sàÎ?)+¤v7Ò(ÌUBÂ)7Å1%gØ>‚Éíû’R#db¡†8Ñ/[dÊñ¦Ãø}8 {™Jµ¬À7º¡Ž] )R`À>YÕx.s7T¼&ô½ž ¾ùd+[;Y&2™–ŽÇ‘3T­y°€©•fý*ñÁ$MŸGnò &@jɹϸ×ÄÄçéªþ dx¸Å(Áõ>I˾14)·yG²V•k‘gbVGÎ/æ<1ŸŽÅ€ýÒAm½ležJªŽ•0@ã`¼)«îR»ã¦¯1 ±Y‘[¨±ªÜt2¡QU´¹=Ó;"›h!n·µt\N&SÊdÚÀDòG¾£) ð íXKÌé¿1ðñ½&e$€gËHpkWëHIƒ,Û-+؇BT"«ÄJpÆtǰÌ\du…ß§6 @ÀŠQWƒà)i&Æ·¦oQßV1 ¥xÖ(ç삳z -±@v)¤X»Ò»ƒïžb|ßÏö‡JY/8“¹å_F|Èü 4EìÊŽdÙ"÷ÍÏS)@¦ ífôüµ+@ïy|í)ñÏa`GþÃWø)‘Ú…?Ãd½[Ædb ÀøŽÝŽFlnØÑ\ؽ€°cLzj2ƒ}FGG‘9¦ÀÔ.W¢Græ¹.€~x¸§KT™¢=:öÝ ÓWš>¦£Æn‚4È]†l;Á®9ãÛ I¯ÝQ$ ÁÓÈH€³ÜòM©T#}Õëñéaz2-"[Y¨b|wázÆh‘þÝkûð©KÕQ4 Ÿ³)‘·xª}“v8M˜aÕ·yƒ([@N¦Î¶OV€®d›E†¯¤ï°ªQv”‰ãÙ&ž @vk2ÓÑÈvÃ{Fni:ª6•vÇ-4—ÜD@ÉÚ²è·*“”ÈUMÄ‹wô™úóƒ@® P*Oc®j>}+UwÙŽrnM§oóªó¬Qu/¡˜ªpƒŒÀL7=º«œ9+‚zƒt M›^v$î1sÎÈ$ÏH˜•v˜MWÒë÷@ø×5χ9ÖÈJph¬Ò` r»J¬”˜tl%ʵ`„#’†RKLš–ÁäДéëÚôU'x­fB6Nd"ãkTu„Â2M{*uÍ·±v‚™ï:™7nnç¿{Kê¬ÀNl .aj~­E WV*Ìí„9·Ê™2FUð앾»ù”7Ž•ßź#À$·ëýÇÙv¶|¼.˜ž¬kANÓ Çª2ÃwUŒhO€Þ-v/€3½Pjx#´4´F<}U½Åpex2`T•üVåÌ ™gÊþôÂdKŸ¬.¤‰ªõb"1bÎ-™²R¶9ssTUÒRÖÒªrëm¥4dý%±}"§Ì³‚i˜•`i˜,czyb;( z1ú]O )¶m Ÿ¾«zÙ’ÉÂ,½ªŽxÇJ Š<êôµ8UcÚ!^Ö.nÓÊnW Ø­ÿ4¸¹Z0²j[qØ4ªÍů…`$^¯<«0@)¾Þ41ª0žgK:ÆÈ¾™J@æƒ ËíГ˜ 6¨{©*E¦É‡ 62%e×qLÖôÄÃJ½L×tp]JŽM•29Ò»‰¼ö‰ÛðÝNÿî€éʾ™û%Æ­Æ® ÷YkÍrÇmNŒÏ‡!\;A¥”xUøüÝÜÁ}ô8á,ôÔ° ;R:RŠMÂÓ׋'hè“ȳŒQuUÇdÚ#ºälaœ£h@Cá¸ÉíÜb‘@° o= Œïk¬ ö+5ÿv»ë|©­´0áûœÎ¤Ÿ7Áà[&S’¹Žôço·£ø†òÇ“å“öǹŸ´F7 ©Ú#Ÿ÷éd;ã³¥(9+bþJŽ1޽IþHb9\Õù—-¡Ôèw#”ðe- n:xVŽM¤‡“U…'6‚'%™F‚¾raG¼L/z+¥ïogšå1MáF,§ĵ?NƒO€ì¨×Vy*‘ÑdK€Ž[£Ñôã+É™˜ø~j€ï€ß}lñù<)™ÀY]/SI¨VrLÉÖ8Y¯àÜo¨ªrAS‹ã.#u½æ[ž'¾È¤×í`JŸ>=@°Å-£}<†LÆàòA< ?žS;Ê5VŠI©¤n0f¤^ÕP-¶™Øbª {غ0UÝÚh_¼|û8ù4ÃîHÉSÔ¨—¼Æ@†ù|mQЦ¡‡¦€)úuÜ1w¤€¤ið^G Óž*OJä¶Ì*jír‹ªÚD# 4vŒ3TÂì·ì{Ïħ+;ÒÈù‡ótÌGÇ$sŒ¡] ¤¯¥J”˜ÛqžÎ¶É0ö‘ýÊ×éX9t©†ÂùàJ|ŒFæ1‰1 zïlè@c¬Ñ¸Fk‡û\x:ÊF7Ý£%“»NJ2Œ‹è…;rN#Oc¥ªlzYtTåCÉ)'À¬±’c¥xâ1o£Ë’)å¯äh%&yΤ§¤äªî¾[´RâLd-ôÌéWo82H©)•tÉ™#§—Ó”•Äp e&rdþÖSEÊð¿þõ/U_QSúq®ŠTuÙzé[¾Yµ+¢++5·ÞÕZ€Æ'[c» ¥Rúæö”ÿ?Yw³ ‰m#[x¡çM-Ë¿Oïí|äÉŒ¦KXÀÁ@ 2³ª[²ï\Q—ÿmBÇ­ Iï(`Vµ;¶†F‹€;ö±î }‡9¨’ÑW‚¢Å®Áù@•š7ñ£»ÿ¡Y®‹ÞQ`ÊuÑ‹™Ó¨bWÒNŒºuL¤^²œñmë827YU&PM )7wùó_·Výam@.ñrŒ¬UÊnrF}q#]#e#aû<ˆó¤ÏŸ ï–FìÎÝÍï¦l뢿ö'qôôËxþ}3Žú†ªõF÷©h±jÕ”Ä}Ó«døÜ‘0‡þ”‚ ü ‚²%)åõa‚í¿Ýî£o¥þö—>+bsEüZ€¶”˜Ëº„±í°c—Âp#«±û޾ô‰ã^ ™yþõÂ5FÊló‡µxœ³ô]; ’¦A% ÐD#&žŒ@8æ@ Fš¥î(W"¾MggQ;  ×âT*ûÝ—OYÌÐÒüfÅ·mKªvlb]ÈÆiļó$.ųwàCìÇ$ÃÍB ‚U¡*¾§Ï†Ü2Qâ#k¤©7=qøÿû¿ÿ³@‚”JÄé÷ÑÀµÈ0}b˜RÕ“æ6[¤èŽÄ…ª)°R퀣‰øÓpÿ¶ÄŠ!†>2Üh@UÌD eÆ·²–+ÿŒ®])å+€¾YëÚÄ9Æ[²#ÀÀ”"«|"“)ù©¡wœ&OGUëõz ûã?’NݹçÞyÄ‚cïÒC„É,7)Y-|Œ€ËZT‘@£kh]2ÞoYí7b‚~{¦çãbô9·¼cU-]äLŒd.Z#ÏH9U vÙzékg.0‚’ƒ’|Õ2”Uå1ÑwµÚ[Þp/²ëúIu©Z¦YžŽÆiWpWŽ‘ŸÀÖÐ%8§tœgÃ0íæ d™$&P5%“6!ˆ'ŽQ}ü•ÄËÃÍÅ3wœ€aÊÞ„g¥¦èJì(7B¶2s]0R!«F¦‘c´°‚i(a¸Ÿ¨¬jY;™èA€—gÕ£áÏŒ¯3M©¥#q…gí€lQM߃#16TÂ8úˆé“m™@n½Õk¥«R4Èçrç1MaÛ\UN©K8ʘÖÓèÂÃòž1†’>q Y>Žªû‘ÙÚE_f2þ™XÀr]|(HG‚ñ<›r:Ÿ/#q-ÓcÒOìå ²”irxg­q2 åk»….LOäGãÓ³Š1¥}å´+a"[£¹ï>ª¿~ðæµÎ¶!ÒcŒ¼R+ûJâl÷ý]ÐÞ‘ù(í2ø¶‘ûn‹}¢×ï|N4µÐäæŸ->Ÿ&*ÙPÜíÎ#”›E&rSÊÓÜmHìûêGö«ß1Jüëe…Çmzß{Gn‚FKý^nh½²ð›·öÆÕÕ]`³â5xbC…éHdž:Òãšå Äù|`‚p%$F\¿ó—GnÚóŽxb]µ8 õª]MaÕ”ô–!€ñ>`CÉà&ÛÍ•¦‡ó7¦Tªƒ4 ³.¥4°væ™”• ]}}ÁTç ,2Ì?Lé02OG¡Å,9,÷ÁÕ+ôÊ}«ÛÄQàêRJŒÉSUI\á¹BS\¿ï½*>s²Àsxùw |Ó̇CÕ6ºœÞC êj]HÇVҲݚîX‹F”Yż™›£ÈÁ+2»fÔ¯Ä}ã­‚/†ÑÈË·“ÒQt”)ÉðaJG‚H-xÑ‘Ì88²)µ¤‘ý¦eúÀòi7bJ²*%+dL†œMŒÏ¼¹&íïK°–Ú;²m²éýd™àîÐÇ] h †€‰2ÈYFÖÓû iZ#°‰âe-2ÀbÙ/ýYK%ÊŠö©KcÉÐQÀ‚²5ävCv€,|-?ã3—‰Ø²æÊšZȼ­ld¼c¤iºjz •É]2&Y¶ŽJB#F©® k©db¶ÄÝ%žÆ1¥Y^À1ÿr¶°ØÂ·ªa|‚F8â·X#0µ´ISú“O“ ¬D#´´Û‘”xƒ`Õ|0™TmºK!µËFˆ×6™r£yrstYzGÌ@æÈë÷ùrÖ%矞‰£,0ÇaX‹H`«ŠqÌàƒl%@(¥‘ço(Ì-Gá¸õË`´tY¹ª wÔÈÄñ²®ªœ Ðg zß« ñª0Ò8É‚`_BGæU Ó¯ê´w b]­§ pþüÎ¥‹ÒL'Zȇ‡»s^ ÛIÉßÑ`¡‘F‹j{c`‘¿jwÃ(YËÄJcè‘Ħ+ÅÔ‚I‰ç“à̸Cua„# û6d߆U1=ek(µ¡%ƒ0 j:J¿•îÀ“T•Ú¸ÝVüÔÑt²~„rx/®×Dhš ¼n«¤]XU´gk »EU¤­ú4Ê ›A @Y ±#Ü>²’LŒçl“F‚[$A½dõn(@‰lt¶¡¬©—ßæøõ¡+7‚P’‚¬F˜g½õ­*Ï&«”¡,<Ѹy™¤käÐ3®½×@pÆwAâÜ΢w=¹ª,³…z]}â¬ò OÊ_6KcËàMl:¬_W $à¬Å&JaJp·&£o"¥R&yâ#±Ñ4‹–¯DŒ§ÜkÄ´ªmUš– ÈÆ¥,gÂ/êR=& bà6ÐÎ{«.‹ÑÒ³¤_{VíéX»F¸€¹yÀFÈö‘…iôhŒðÈŽÚ1d²v¿%6ˆ;g(÷ð¬(ÙêÒ‹”Åoýë_Ä.c;…é¶´£ªœWÖ0œOšH¸pÌdJ¼-µÈ~!®Dã2JÖÝõÜAÕQU æ&0° @æJŽpº{Ä4m¢zm>Veꢌ Ø“¹ —çç¯ñX_O¹•vÕvæ)µ·g [âÌS–×È3A½uµÆ‘¾¶-F8Ò$sM ¼'jþdÂQ¶Éø]JrUîs´I%â¬Ò츪Ukä0[ââÆ½Vî%ê5n]H޲ („!€9¿J_<ŒAÍZ#>ò=æöp~À²½6GOÜÃöÈ&6e;´¹#1+Y4®‰­T‹’¼ÈªG èiÌõ‰øÓ®—@©´dí ãU%= ÓÈ̵$hPS61Œ¯Ó-ñe%æÈF 8ZCÔ»}ð‚É6g<±×°ÞFÄË)›èX cŒ@fãÛJÎ<+Ù”º”"d&1ÉÒ[ûu†ñreǺ”4Nc™µ*e>ܱo‡®€ôé÷h”ò·ÿüç?»m=ÔÈrªŽ=MxKà²ÍÖÂ9%œ›ö¬ðÂ=iä³Ê÷kÇŠÆ‘/êêÕ’a¥”•Žú ?L)×Õ,Ù¬y:jH2³²†lÛ”Ø}Ðg˜[oX‰L¼>¬87‹^‰cŠŸ±Þîc«¯‹²…á~€U[@ŠÖð—øõÃìhJˉ»ÅJMœ, š›#,Ú°•Pm@ Suy&?ªž”s£•ÒïÁ7”mûÈ¢[·G-Èi9Ð`Ú¶¹ r«±èFÎV&Z6È‘ «ôµkTê)ÒÇ ôª"‡ºš%”þ†¤hºï†RǾ$ŽÛÆQn"žÞ¬&âSjzb%Aæh! n¼§öÅ2IŸ,«U)1€A•t¢Ñºf«–‡Ë<ñ2¬ZcÕºà–¯’FÔ’òÍ•ê-7&kkp™„k¡G»”ËΡ|†åZö&õ";vµ¦¯+ Ÿœ‚5"ÈE¤}èÛDÉ'bPŸ¿V7¾Í°t²Ï¸Ëà á4pÃÈ1”ŽaJU€¯©ÁBIÐ5UEz|ÇÙ:"מ?q Ò¾m‘ÄJyr°FÎí€É¿k"9¬+¬KPÆz3#Ûa£7¨%e&ºjÙß”ã[†Œ§·¢!F¶U øPfâMIS—#ÒoŠöi¢ÆdÛ!¤AbËPj郆…™<%lŸze{‡äé(Œ&@v¼ûJLÆ-¹Q{X£j·ƒÉdÁJV"ÎÇÎ9Ï@d•X=RÔ¤¬$;æ¯4e†1 {U%Ðnm¹vX´ƒ[£’ÞdÜZƒÃ„n GÀKÒgÌ%y¦ä©¤×Q)³¡˜ªlfG:–‰û垟ù ›.÷.⿜óÿã9ýh7þ}Xõª²ÈЉÙGÁ¡[´*&çv»NÇ!¯d[Ëçit¥njOí˜îåwqŒXµÑ<1üµ7…^#¥c½0@€Oïè =#†“µäÐ>Lú,È0dª­¯±*ÉE¢…¬Œ×[ÞYI´3ÿžñLÿý÷ßœ›Š¸#Žy¾_»®­Ô7PF¶JJ¤’01æjÜ)‘Ça-pæ½Áuúü~ÑâH@4 fâXK‚LàF¤DRÊø¬äÊÔâóÓˆ”á¶Rp%xn˜HUÁ¶7çLæXµöª²#ÀGq#´È-O)׫úçUÁùîòIô¹5e¶@¶ZúæHϼFÇù,÷¿AַŰ9P¶ÛÂG•Ò±ïàH³=7îµ?ýWÙÇgU—A&>7™¾Gh ’8A-ªV:cl…–Ž”âˆ¾ßóvp¤~wcLÑE °1² S%#¸M'¥§ôeÿk×eÜÍ".0Žr>”øŽxñgY&F—{AŒÑ~ÇáÍê/¶[@Kk×™§ÜÍ%kàõá Ð’8FvŒÑÛ•{½a)sf¼Ó9Ð#É€Ù²ŠìÿªDn½¹»'&hæg‹á™CG9¦¬%óxâz‘Û¡F< €¢Md¤Lç#Ï®%¼M”Zs~ƒøöˆ¨ý¿iÊ=ëH—@^øºú|äQøìæªa$7XÜ®9ãE]ÙªúVÁ¢j]ÚOG¡jX~=i2¤'s$¨— ŽúÌbòQÊJ©U1gðó³ÁS)ÀqL‹5}ƒfE†tlÖ°#ÿòº´Äl OÀ­¼à˜r«j߬X;½ Ä´Žr&ø¶Õ8^ßGn™©‹~†°¸òÏï;Û,/€ÆnTU‹*&,h„¹€ôUü!hnžJZŽÅý«Æ¥ªZü^“jìg@¶Iü|"sSÂói.ÒEúbÃÞç9ºÀèõt4ް*0ŒA]|ú~æ¯ÄÁ @ÖÕÎe>É€ý„b|0î ÚÙæƒÉ­N“§öÝ%Ÿ¦6 Ìéx m•2w¯®ÃI`ñþPÁWRMPÎGv4nïƒÑ-¶™À$ÓN¦ê}ü‘̇ÆJ˜°#H´^n½ÌU1™88ªÖH© #à® ˆH&‘ã­€p œ  ‘5vSU%< rN,GÒ'Æ|þP:™]¢IÝÖ®ñ2\É~½‚côX C‹Žœ»<ó– U;­k€§AŽ>í] ÎŽrí­ôᆶ€#‡îßPíu‘áÙ‘ľ…ô¾}ø“忏ˆhPÓU…^þ"™)«"á™WrdÕ2ª®oGÁ­ëhŒñPwÈçw¨^|Ô[ ¹[¨âóD¶ uTª pÄ;¦9êÿýªTi·›f eú:{Y0¦p tYs»T¤*Ü­—ï^1ž¬Ì÷ì°*CbdSʬT9¨Êp›ÀJñz‰ñÍr|ïâH¦Do.ðF+ah„#™YSöÇŒ’Ñ"=@ÖªéµôQæ`è•~¸h®ýIö¤ñÍÑn.LiŠ£*bí­Ôª]G&¦YU—£öðH½r£ €ÜEG¹‰HX¯HÜ Äg#TUX1á|0íFƒðí8lJk ià€ c hä`°FL|íó VdLÚ¹“ ªÜ¸¨±8e&+µƒ¡BÉQ¯‘Ʊޘô}ÊËT­×1ÁoûÛßúÈÙ ŒÿÜ #1=MkaTE¦ÄµT}WÙ µÕH,”8héØŠm–,Ÿ)‰eU¤^†Ó$sJ9ÿVeŽi&’IáÈ™À±‹+?¶~ðšÞ2a¼#½Ü‡1Ža¤öÜZ^Õ±G]nI>ML¶.|3L¬9C%|¶xѽfÒŸFny]b2>97k†€ÈVÖÛuÈ U$ K…Uúž£ˆè)û©óÎ9·OTܾ3zþùTÍG^4¢_H]nª…¾FSh”Ê@bJ‘RKUb$M½x>ÈÇQµUÃ~ëò׺šŽ÷k®jÉsË8ŠàßGâý™};˜Øª²@jI&p/ž–!pd%spÌ#0UzX&P¢ Ëp‚Á¢‰i•RÊ‚ƒÜ7z Ä4kCõ) ì™ ‡L…j³|2úº”º ’@ŠŽaŸU¥¬h³ŠI&$‡œsh‡xÙ‘8éÈùGÎϤÜ×)‚º2Jß4¡‘¦>¿ò¢HRÏE'¬-æÓæð}#dß¿ Võ á[Ñý§o-¥ª <¦uÛAobdÛ3ÁXÆQUcñ€‰È±o¡cÓ5~G.³j“Õ>žø³è½H˜c‹Éd=޼Þ~Ôûà™û‡nù} zž‹ÖC²­„iÄ{qƒ¶<@Ùõ[ƒ¾R-ª-ƒ7hxƒèû»‰.Rµé“¦HÐè&ŽgN™ w䟉–]¼’cP•[2}‚ÌFõ䓨ÕsÓÓp–öD98Š0¾ù¯7áÖa4‰ §i:L ¿¿Ù+ᑲ¯A[ÙÄÑ,z> ó·mCHÕLôr¼v‘->™§P‚ù˜¥J#™¨: VpVåzÉ4 G²98n‡Ä2‡r¶f]½ÉdzØX—A€¿hÄçƒ$+-œ’Fh‘ñ`x+§$º5I%™[dƒzó‰OçmÑ%`΢v wUíí95v â4¯²é,šRF¶óÈVš8ƒ¼!’'Až²®”;»v®Pg×ë¯`0 ¯.F\µ a vd}f=½*CA¯è F]ªïŒc¤lP;”çæ¯0}EÌR2W¦çÙ#ÂJôdÌUñªy¡…ùû:4B—ª’h±Ä•ÚYF2×NO)ûßB0'S•‘FËfÑ Y)‡Ë7¤)êÝòHSdé H2&¢­êuÄx,׫V¢™¤ï­”ªäô͵•€»2 ºÑÈfaº/†9ÇþåÅ0¡‘[nª•'°=[¯}¦ï.dù¨N–mG/¦Ô§Ï°…-Ó‡CÙ¶¬=‡ •ä!á“a½Ý¥‹Ã‚¸#}¶­Q—O²š'FKb™Uv`H†Á»¬$€ð i8ËH¡ËqX—ëG† bxdí=^•­#co‚옘 –µôG¡+eã"1tä"œ8s¼5Žú†’ÿ¬ÑûÀîëØàî¢7Ãn”C/§Ó)™¨Ö˜éH_ \{¶µÔÕo{ëaf²ö@ Ì wÜnÓkÙVUOá•`¼›žŸ>ÝëüÉ @Š‚)’vÌI Ï‚#s¯=¥ì»•XŽÌÓ±;T%à d³‚1õÊ‘|¬ë(`»nÒ$ªºÄ&vä_K`GÕñÃmÎA‰? ¤1¦˜ØÃ!?KÜÿ¶AfamÕÆá‰™§×D–U‹àø™¸O±}T Þ4QVÊ¿ö0YÇz7«SÈ"UÛm ãF2¥a%JA–žýnr$Ë“€ÒQU#áe@K›Ä‡ Ú@{Vlñô’!,·*=Rð™IU@¨fÓh÷é´9ͤè)ÍÕë+w|¯£d–. 1M£ñÈ®£côÊ ÂJùo±3”ñL½Ü®¤Ý­‡µ‹&*‘96½]™à ÏòÚSF’ d[5‡dï/eWÖÛãSæþ²Y”²£*g$ÀŽiüÞ0Ÿzñ²Â‡æ@Ì€ :§Q ÔEà^zSâ7n 7XÔ®ñ³êF]--m"Ç3o/“9öŒ­Z5e²&ÂU!‹m˜U7Š'nŠ^Ñ&¿ýóŸÿ$΂–©p“aG –i€°LpOÇ3²Ç>$Ù*Šœ9ðêaAÓÝÊÜüËÙô½Ýô×Ìkv’.nÙ¶¡c+éê›ä¸))ÛS;1‡fÕ.· HŸŒ!RÔ(Ù+¥á©ªWäïkA€t¤¡WJÜ”ô²à@heÑbrþ-“&ïFÆS0¯¦izŒv qö»Ê9@–é™ÁD `4†¦ a%ÇdZRjômÎ\IÐ;Êp<¬‘l-˜³åý¥`ϺíˆÞA#¤Ô7C Ð+LôG…#ÀdEœ p…ŸODuæ#ze¥€Òdµ4Ô8‚&t4:&Û²’ÀË5Zfæi0ªÓa-ŽÍ;ªóiž¥¿¡ f"ë#á‘5bÚ¼R†,Ë雋¤¬¨QnçaŸE›”óìÊó'îÊÚ…£0H{ƒÒ+5èÖ)Û›R»<+-ªgÌ Gÿ™Œ&Ã4ì^@IDATfÍI€ ¿ía¹ö÷Hï˜3 ·ØE¶úíßÿþwÍD[XMßo ‚ØGÅB4ÆÆøô‘J@♟æ{Ûñ2†Jp®}˨*á1iA Wííæ“F—*€y¦iÐ0 Ê³«uì{ ·F CJ_µö×bº¼•(á iTEíx–i’io·˜î+ ½ªaÀ/k`J |‡œ?cø;já_n^“ çôù§ï#VM ˆd¯q¦(•s&ÐÎ_UÉÞê¸|Å]ª˜¦ôÇC|z¬æFæ«ønÛ52'n4@)(™—ý‘³•™$ LŽÉt!M"óä¯ Ç¯Io„’.Ùb2RµIL½lµ4nâ€L 4O>)s“S’Ý!¿¾rJ–uås[õ&¦…ÆgÇÞ6ÜDLdVuÁ}X·=Fâ”@>r]ù'†'†‹Ãí ï"-Ù²£h7`‹Ù§#†¹ÁæÊŽò鼟”vŒeµW©«MðH]d1rQ &ÐRï·øK£Ô5é'³O|s3É0Y×Ì%>5”š…øl庪þö÷¿ÿý‡ ©†-Z[škõù‰mªI½Q¥&éí!Aà8O†Â/ø”› +Ñ÷…pLŒ¼}çab < ú ¢ZŒŸg-Ì‘3Ð_©&Mùz|¾I³ÒÞã¦TBŠZº) AÃ4JH jXÆó×ePS\m+aúƒgdzitqÃ0 sÆ§É Ÿ&^îO#L¬±W}òÏèçD2•j§TªŠï•"ËZâYY‰R#Ÿâ]“ ’r†¬b”Î*÷Øa2ùÇJõ"9T#ܱ§ày¼®Ù±=s€µÀÆ©¶?MU‘ŽdŽô˜2Ÿøvà飯7\5lǪ¬…•FÇ~[Š!ëRÄÇúû[ï¸ï¢D&z«ðònçc3e|ãÈÇ\9 ¼_2¼Æ^£ç²dÓ3×ÞSX¸·ò#a±ºˆ–'†ûóƒRIèêý7¥G±û¶¹£Ð.\–€æƒwäãhD{æ#kïR0e²em…¡t<î·Â‘•¬QPÖh ¹¿^ÃÔ¬­`öé̇U³˜ MÔÎÇQ¨ÊûÍB0q£)é#ù`³’[©JÓF¸W¤€i2ÁèmPŒªFíŽÀi‘1IJ£%1»#2g ܽˆÉúã°'j±ôùln#ÈxÝ Î¿q ÇÈ¢õš¥Cùš;о¥ ûìȈõŠ®“!=%˜&±ªˆ«:Ê;6ÃVãJY‘a˜o(Ð7œ M·~0ÂQc£óló#Ș˜‚weÙ™Ì,°Ü&ÀùêsÌzŽÝ P©êŒ¼i3wÌÐÈëýy -¢-Û†¡¨½Û„Ò7I5¦ÜÙn7$11Œ‡«Æ8öÁ§1ˆC]òöi ŒÐžCdz÷ó‹©Ò•|ÞÇ Ž2Ì ègháY ”àwó˜ 4Ú<ó¾(J6!sŒÙkìÖ@¶Ë½C7… ØÞ;«˜.˜ ² ›Ò û„5ÂÍÂXì.@XNÙ1e×Áäs|¯³‰}Èj$ýÃhú¦¤—÷ ªºˆ‘0Y@®e—¢¡tLïÖüÔ#09ø_pã3ø ŸB&d¦O8e?–}d¥Ü«šÒ âôŽª—>¯júnQÎáÊ?ßäöLœ&«4ôMçÉ-§NÏ@Æ×Ûz½ ´tå)·jvSºàzg˜æÎ9)ÛH>yj1Æû#¹%{|LkH2æ4°ÆöUé³è4Ü”“eÅÓzyŠ•ðŽi"Û“CU8¯«Ð"l¥*à–l…7Þ24Y%îe0¹1è×÷µ*Ù:v×Ñbb@I—v¤€ÏÏX÷ùì{_¶r“†gÇÆ´„#ÌhvúJpO[Y/0#R4ˆOUYìJ)e/a7 3éÂx \³=#»‚†X»˜­Ýª’Ñ»ŽwËY¡…Æ—ŒOoÛ5iÚ¡LÙ U·€”¬ÛD FV2îJN"¨4† –5¶ƒédýJ副*ïÐv“‘¢ü¯N)íŒÉàS5¼êy‘{_J¹µ¢­º—^Õ¾!F4WæP—µummGÕ6‘1²  kdNæ˜1µ;*u…¹5·‹À<ÉvGJí1@S"«ÂZ\§Æ™ÂÅ»™^£ÑµôÇO¥­ÚËSò$07JD0Žkߪ˜ZT‘¬ÒìS‹©=+Œ ·1¥FØ2x˜¬òÇ$ÐH©]´ ^ð¢Y­ç)nÇIç’ßk¦‘ d£û7Ï dæJoF¦”1@&€Ð"7º#†¬#U@¶ü~ód"‹Ú½}dô€œE–¹A¬ñ +5vA˜g;´=R»ã‚¦v Ò½‹œÿ¨BÍÚŒ`Òb¼0ÛÃ*ïH%]˜u²•ùdÞ$+âªñÞ(ÐsÀ4=\ƒd «¢ãpÝ\$ÃLhrè‚n®ŠaN8ÂYaV¥oÊñ½%“!ýePU`E¥ziú¢Ô¥Ú&Ž›ÛV²Q)sÙ±•|±\Ü wÎy+x_#€XK]2eO§cnýó)(5ùîF\o˧ÉAö3n´?ä´ÛÄnL”Ú0F‰IYÖB´vX.šHóþ ®¥v™²¶†\;ÞDGhiÖºð˜ÍÚb˜.B0 ˆ˜0Mkx%¡TÕ\¶J¢ŒR{Ú¤O$šÛwª·ã×·±=8y“ ²Õ˜yÇaÊ<™ [Ø)rû;Z)Ï”íÆM©LÐcöé÷åÙz^ Û.¨«0EɃ8Ö¢—²ÄJ¢ß›Yž (ßÅÚ'Aþª¯W6NÀH²xSÒ˜¢ &Èd³ák›X5Ù{\;ÒD#0Ú)+Éx“-ŸÄX„×2±R¶Ê…Ax¡‘mG¥}+`¤v  –­·q”|ÎcQxY …‹\`¤ðqv<ÞT¯üó:2Ä”«ÂôhQ8«ÉÎàïï¥Äl í ”sm˜? ì{Ö8¶Hú¾»‘‰å<‘¢—!n-ª¢^V°jUÙúT0-FÆA‰¸7TÒ…'ÈSé=nœF|b·àƒiœ)0>YJÇ<‘ýÐú+C‚6o«p½ªZðý+ŽÖSb((Å4ªÜuz%™˜‰È6Þ‘¹@Š0Ã=~nŽ-ÙtXcs1ÆÁ¡ܘñI@¶ ~ÇMGÖ¾FG#tݱç“R*ç9G/œó̽îÞ/âüöyeÓîs¬¤7CÛ|!PÒU£\ ¨Ë,VæúÄa¤PEÚc«FgŽaøÊʪ”°P…9$cÈJ¦aÅfIs›>IW㜵tÙrª°Yý„â9 úZà¾öL(µ÷wü”mwzxL˜&Î “¿^q|ŒÆnähô¬ðÂQ•^L†¯—íUý’µªl“F'ž¬·Ú@ ùwAJLúÈxšd3lVÕkóùUœC̹T mß5Ôº@"ïò È·®>¶x9¥ljß6ž[ ÀS& áE]­%Ó„û÷tÄ)a펾Uãé…‰ `†-FÓ”FÈz×è(ß´wd¨êX Y£Çÿø6Sº5™’hׯ1Ÿ3ò^œsÑûÐchˆÓÀ UÎr¤eD›mÊ­œ[Wí·€®Æ…– ›Å™2÷KÄ&ßÖÏoHY¥m ™h‡â4ng´qÍUí¹2qÄ7=e‘ªvæãÈDÎnÊÀöa«äØ«æŸ,àr½Ž<'ƒÓ”Ý¥}¶3vª”ŽøÝŸaßd”iˆóï¨ëe2LŒ·aVG¹3´Àôk×,Œ£ „åH-Žåݱö妴ŒL¦]ŽyWu¥ôÆíîð_ûIÓˆ9×¾F¼.™Xw”Ã˵äƒ0ÂñŒç•Œ$ó‹%ÌðN8úÌcæ¶\Ð÷Y£0"[²<sˆ¯KµgTa½JÝ÷ÏJ@ 4wàù>øàà/Z²Y2‡Èl1€lÝ%²•¸iÁø÷]0† An›XcþpGULS€..·-ž ±* $ ‚[¾–'ÁFxö^#RNœ d Tåob“œ¾­Ú$}ÿš-Þ¬UµàõâkwT…ëuô/º õš¢Dcm›4Ÿ'½Þ9à‰‘dU] 88ª’!hö4p·†Ä~×ÃB—¬%Ø<[]nDC‰wY q/Éç¸ß%3!sÌßPbV¶tTÂŒÇ]¼#Þ ‚”Ù€ð2n2%&7LU ,§ÙÞÊIe΢µÛéXÞ¸&ƨŠ€Ãùƒ”eýY´Y%î[4€!Su¼{¬.ÉÊÑ ‘Ð’?èSŸRï;‚À‘2AÙ1æýT8W¥ßǬ)f‚y•|”6ô5Þ9çe¦ÇeÞ‘ 8îßO(Ÿ½R%†ùÌèAÞ)õR*Á€ŸäW[Vx/l³-ªÌ¿$€ïWƒ^ïiÿ¿üå/a&d0P®1²ÅäFÈÚû—’°ßhµïñÓ[ŒŒ OCw¬Kv‘Þ³{QÖEðg8&1}íÄøîÈ ›ÅÁ¿>ÞP|Î5Ê•ôŠª& G%LÉÍ,€‰LÓ,Ç–èÛ'e&ÝËþŽU1‚˜3€- ·~x-J¤'há¾ ?ÈÚ-ƒ'k=cª2,ø7‹ Ï(sεk-ª5êR ³UÅærÀ§4È·Ó>4@ÓÓÀFxËèÊ6 ž3²ì‰¶RͧMÎøçSæój¡OÙP)÷’µ7ÅU6:¶,ºBIf+«önÀÜðÖ ëjJÄL”äJ¡,Æ×èŽ@-Lì ÂÝu©¶I½[8.)“&0¶aÊ…—HG|z¿蹟!·Wµ’ÜÈzµ $±–¬´x˜†'¾öHúJ³ÐH¯$2,'¨T2ƒ|gßE­$ˆ•DG¥ Ê'vËøRÖ…w„׫ñ¼Ô÷yUu‰€œY©åYÕÅ Æû.œ¿cbÇZÒ#ûê‚^ o·ñ†ÐÏÀûb4ÅÑ3¶­%…ÒîÞ—¯ÑJ€jS®ö0»]VAã5ºE³¤qþ”}K‘ý z}²Ü®ÓY^¨ê™•0€.ƒàhÜæV•‰‘sVrÇ~ti™g¶}¬J&¢vGa“îÅ\Éžü1‘ï Hþm¥¤WWY£ q´Y†ë2K‹Œç“lŠÆU¹ÙǬʪÚP×Ùò®d(& ”idу wq%½]¤åÉÚ%¯÷»j³äzÏÔûòŽB»Œ!€[•sWh™ ™Rïƒp%íz…U}¦ñxá(;ÃîÖua4fH¹q§ù6 Ãò±¸ß&½C ÌRnávhmJM)§!v”ÉhxrË$ÃÄ™hqTuüí_ÿúWƒ×`äù² NÀ7¯ú)WêÓÒEI&`¦ìøVÃJUS2"­‘FÉ훪 ³­dy¡·›ßŽs]/S».< }™’¬jÓ+Áý89ªz8 ½ (³­[Ó•D%¯§ŠLðVx ™qF`:Ê6N F£e¥>8zÕwvÖ(‰ZFjg%0á+?ûoÙ2a¥dòd€ÒdJ9×› AµàkG²ª]î<Û•fØwð,úpkO½uåÙè-C  Ù>~íù0—É”(Óc GJVÏk¢£ÀÃZDŒÌ$åºY¥O‹ø>гRb‚!0î'%†F‹¿¦8^›³FCý©é:ªe&j²%ö,}O¼pšQŠZˆ)˲ŽùÀµÈ‚¬Í­Ô¬þýOX¯HÖWÚ1»Å4Ù2ú³YûÝî×o§dÚ“QvqG¶½˜)ÀM$k„¬Wªµ«ÂâÝ/ö ÂPÂa¸^U M˜ òA¦ïkÐrí@ãÈ"[â_ÿL‡uŽfô7Y˜BP×Ðϼ â{…n×6O0“ºã:”ø­q¯‰o.¾ éu9f–«¡ù±ª’0NÖÎ\Ütb-"畺ˆªÑž{ï@I£Š×Rãîå_£)Ž5]uãð<ûߺÁ•fتH@ÎAU´‰Ý®°Ÿa2U¤ÛcЉ~4Ä#õ¶˜ªKiiÛ–<î×ßêwÄ^Ic[ÉÚ·’c†¬=À3¥ÜyfKX†R)g žØ‘9pÔ÷º‚ªè/û€F™ØtVr2X{W È몑3æ½ü–T›ž’9AWÛ•zŸã~¯q ß1÷ÒàRÕz·~pAƒÉ&ȳï#ëY71“ÆÙ“Æ#`*mA;à#ÖÅuõÊUß%½º’¹)Jdm;Ô{L¯[LGHÆGøýÓ?ãòäÖ-6¨]îSÆ™œ‘÷°‰j³0);2ï` ß«îkéF?|”" ¬ÝE2”UµÛPô8˜4ÍÕ‹¡ì˜yš&bè}.Þ™8}+%–E ÞdH€‰–ß¡xÎv>ߌ"#Ã’²Ó`oG‚Œ²ÀñH]¼ûðˆáWs&ÝÿÌËÒð×åiì‘RÀªnå˜IŸ²íSb”4<9gÛ¬–ɵctÉ5ÂJŽ Ç­›ÂPD’ÁëÚÄ–ÏdíÈÚÝÆ3a娲ÀçÜP9²–Þ÷Ô[)‡y"•2ñ ݪú~7:Ù|Œ†Ë”4ý2Ô‹dÌU¡„—»f¶ŽJÜÂÚ0Û”ù°mç;á¼¼.2¹ÑpnÝ”€2[¹º)¾ªÞÞÙ±édªøFç£$*1$5JÄ¢×ð ‰ë%K³M怎IJ}b:jç,'Pr„1°YsŒÐbÇ4¬à 1õ:Ú-sUÕ2V|‘¿ª%ùG §Ôaâ &-i¨hDnµ`•Ȉ‘z­Ôt¿ú}ˆþ ¨Ú]Q—ªñÑâ:HQ/PWúdÆ9æo–¸¡Ä­Ý’d‚¿Ì®÷ç› ”¬®?c‚™Óˆ3‘•M§o>#ʶ¥Á[£kª*¥i:± ÁçY¦I ïâ0áj;‡þOAhƒI…šœÚÆJìd“äx“`LJVpGVidrLʳþ÷{@—ËÈL”ŽË79. ÷•" ô›UY›ë5è½ÈYèΕéU‹LÊùóql;Yc]iðÂo[Ù¤ÐÂÓ;`ìàw <²c[•ÏN7ª~Oç}´Ü!g“܌ظJû™¡Lz¨Ìi)åÚc–Q)½ã€}ný8®€$pìRí‰d22‡2’I%L]Ž"+¤^¸O­\d&°.|½Ä=rG¬à|®ñù x@Wk`rýجªÔVÞ¶‰=>+G2|ÇÖÈöÕ×!ÐR&hál㳪¦Ü™Ó8ö”¢[kUZdÌ"O]݈àÕÕ0oûñý~©”`†îÓSî%«"+ɪ¢YŽUðé1@£$ê2Þ¶pÇ€Ì-C-S£Å|:[iÔ^Ô¨%¾ý·˜ª–ѳ’1¨šè ª4b#:¦œ SU׎ù´9ÒpGžV­·eÂ{íÜ\vŒKé­ùëb¾]UòƺFkåµ ¼^Y8 š–pTÅ_ÕIVaÞ8ÕM„‘GÒ‡hüAÝM,Ϲ»ùmëË»ˆ^ÇÙfB eí«vhUX$`Òž‘ñÈ™Ñ;Õ"›ÒßÓÛPàõÒ @0DÊÖÖØ,b¥ UýåhÔK_5½5êê²ÍPÆËžNôlõ ŒR;²úrŸŸ.G-x±¹3a.jaЈøZˆRƘ~¼¾—¢Ô訚ÏQ±ªF¼ýÃŽíß_}í3׸;ævGs€²ÏE£®N€¤¡lIúº(3”‰·Ü&UázMQsnd2Li®¡pÓ)3 LOÓt|‘ƒ.G¥<û+v¤œmÎ4;†å€5úÉbÅÖƒsƒ»ˆv$œM`[Ûq;S¶OÎñ”#1ôJ†â,ñýý‹ï«nU-rŸ>¬‘,þv|°Ǿ -™¿ééË&òäãH#Ç€Þ®àŸòH è•䬀¢Ý”2ß2ùO@Ï £$:ʘ0%|f¿ÉT30öŸØÕ½þí?þPFµ}=e" H 7,Çùá7&Rc¥ŽJ{qL·ÅÔ8eüwøùÏ÷«ÖÞˆÖ3ÂuèEÈLèMÓVãk‘)kQ8$ê’ñ?rÓkQµ!FÆPò´&s{Öž ¯J)U`_U†œôã‘mþJZ¸»f"ëè™È¢¹•€dF«ÆðÀFDf[&PÅÌE·è8ÿÜÞ%k$ñ4-¨ó”ý<û•ÔûÀ@šzýö̤öx-€xgµ§wN`‚}"H-eÕ?Ø5TÆÓà‹87¸#¬”•'Òø–Ú‡ SóÌ9Ó;¬Ýô>MíÉä¾?‰eŒDn™¸& ô6H&›‚¬±Üˆ“íhzuuÎ0^£P•ÓÏy¾ª’€eéžEo4ì&h| q™ÄÀ–Â1&ž°›5”„ÒZñyVMœƒj%€~ΫֲöŽ&¦”Es&ö‰ÜʯÇÞMö ï§àó=‰‚¬ÐçÍËÔ4_G)|{èÒ4£;ÃÜðd2’É¿cÛ>&qíM7¨ LØös^o?ÿ°*ÏV„^™8™Œ`#´ø ¯JÙ _ÿô¦ëšObú….˜&&G R¯àÌP;2¾Yu¥‘uÉHJ£Ç õ×7xš¬ÃyÿM>d ™Mâe¥á÷Ê•´vX靈²¡–nOUÑæ½p_ä®?Ãl9çÀP©Ýèá¶UíˆÉ3½ã~cÌ5îÝÙS(É 'à Eë SLHhG†ez”Ýôj?_BŒ)B•FÉ7_KX¨2)ÓзaÏåHÖ8†JGQIÖÅ¡^@c%b½œ+õbU2­v¡”O])eJUÓù0g ‰µã‘Ž9׈!Ž/èH™ƒ.Ê0+UºŠéÍu‹ 4’9n´erhô)³uj‡)s†3¤G÷ý:*EÊôJ=È”[¯‚mnø•ºï5þ|@dŽíh)¦é˜CäF3ìI{²L”D¶>n-¶ÍDnÓøûï¿gÑó©iË"/¹»6%‚6Ò0‚+yûuÔÞrF(ìÚÏ÷+÷ÅÍÇ‘¸M4:Ö(דa$¦õx U*(m‚ß’ôȱ)u54Ÿñàü „.G %¦g4(¯ЋYÁHÁAôö!P²LïÖŸùdH †¹ˆ¬]žÆ3Òp`µàÜ÷€ɧ÷iVí2Y£ñ4”lÍ0õ&®4ž¸^   `ç‹êe˜'>¦µ³rÀMU…^%ä½ýç—]½ÙÂæªÚAÍ’_‡¦[0Hn  åÎüõU7¢)ôöœr èê¡0pz #°+(Ý¥ÎVÝŽÓ&Û?½Ük(éu¤Ì$ Œ!Ø2æ˜îåHé(§QÕâ(ð‚F´§#™c9Ÿæ:*ìVU‹Þøcˆ$Óg˜[³2߬LêBv”·@ 7L]³r–‘-wôhÄá(`ªjùÈ"ÿdŽZ^Ì0Ï+ÿ´´ŒÞ‚ŒƒûÊ?Ú xŠZ„cn-Fãh ^ûª°HI3 ЈS¾¾ÜqȰº^C-ðù/ÎáF¾ŽÈ0©6ÅçRnu‹®‹¬Īp>ŽsÃð×¥š§Œ\c|¯¬«YS²d„«®‘Fh¬—†@Õzp2¹ÞîNY‹œCsŒîŸRú·XÓ„3ï/=Ñr_ˆ #5¦4(+UX¼M¿\üÏ:Éx&À_íçóÌGî÷iâm ÔkPJÇ–´ùHw¬Å\˜U¯D@¬È5t5ÇÖÆ´L†ø†FÊHæøÝ‚XûB©ÍBÙ2M棅%¬Q&.7º’SÖëØ8 M]o5s|Äa¹‰Äpž@> Õ+ÚÈ–O‘øJ>?±Ó(yÉdH@N/'“M©nôxÊž” ­úÊÂL{6‚^ðql‡ŽaŸ¥/‰ždAUŒ/'^$%F¦I†šX;FäÓx`Îôa<¥cUdCe%—ñ"l4ŒL1²à¦Ê¶F][XUÔÒаÆà·†ÃÛ•¡ºT»oÓå·1g2 ú@†ëEÂÈws]ô¾<X ­pøü5JÁAf P ê×±j{”¹'Óu;~ý‹Gdí~`˜çß•4¶J> •“ ó¹­Ÿ·ƒ1=A¶Sê…¾k¿ JS{U¸eA‰Gök´Y¸”’A”õz±J‘-SÉÎ~Ùñä¦ )2é‚/óÑÎGÖ…ÑÕÿ6NIK ò %-²*`O˜`&@í@1%½ÝúÿùÝbUã;fØ}uõ)È »Ü·ì·™^2ž›…„…m«Vòÿ é˜óþöׂ7«53‚Ìþ•ö¶mµ ª ²ÚUc:fˆáÉMŽo"ú¶Åç9ÏÅÖÜÌÛŠ†’†æ€ng‚ÈMY/™^5¶aX&ÞÂÛ¯Åшl1Ý%O$ çØ¿®HÍ­«ˆÀmÒÇ'Ó¢Ô,zV…o1ª°RÀè^#€ì)Z©#Ϫr½˜E>2&ÜE`Vòz z½.RIÕ1¦Ññ2ý®7Þ’ÚaíHÔÞ›z"ÇöIIæx:¿w ×gB#à"~»Y`S€–¡ÄÓ`Ú³Rã²m2qþL¹sº2†TOG—qd do ÒÛn0Ù@7Ù²œñµÄ¤OÖ5Èêek´ß_2‚ Õ3x‘c`@#C$ è㑎¯€Æã$X©Y‰óÑÞñØ}¿”V2=Ÿ~rËÓ4]^oL%X(É1ý,µ'†³Â>/ðÆ  %<dV€®íІí¦E©ÆœcVr½Sâ€!ÀôwCJioÉ6QmXnœ£ëØÐk§Áó…^-òPÕt=‚ ‹;äÓRW|wÉ-YW3 È0·n=ïv•T]Ù¹ »B¯„d¥K6ˆ¬œaËÀ‚€§ )º¾ÒÄŽéeJG³Düñº|íåÈ2ò;ä¼­Þ×q$HºíæØþôŽò‘~÷q›b„cžÄs@:&kÿœç“3AÕ”µxj†)ã¹9¶­Ý’a„RU-ô‘cŽ!hŠR†Žu‹û5ˆ—ùËéõ-×Ré%ék7Tôsá¯5p/Ùûp¸õó,4¶õã ‰³Ý ‹Qn4¦cVŽÈVˆ6éFŽ¿Æ½^™ªQôš¶Ñ‰Ù f]ÞO©œ¦Lb“É¢‹¥‘Èž€ã¨Ý¬få÷¨îeµhì;ûÙ£¹ÕÓoMwÉ­5òqëJ€ðpÛ§+l¦‡¡gðHþ2RY92шÑ"w宀!Ë*MÓãáö$n#Z’€^TêCñ­±ÛYf>`%­d[Gdwá &Ð+Ñ31šÞß‹1d0P¨2Aò„ëh0»Á­ñb$YÊªÉØ¶‰£päÉG&ÃÔ‚ŒVò\ª/OIPûF˜Ž¤/ײÍÝT—,üK|[iº0‘lëm‡VÊ“R©Úºzüô²JôŽH¡©$p|0Ä2†¹c7ÚWC¹µ)ß—1HIq0´[ÀJþüëÏiG2Ce2q¶|~½dkF8e÷¥(íFw>œk¯«#~ƒ¶-¦Þö1Ž R çÌáíàÑ“ < LiPnx8’Xãô ,ØQc¦J' ½™Àý­‚^—ÈM^ qdF~h*(9Ö¸û~~ P·ýóçlL¡*¬âðÊÅÑ%³®$Wõ^¹mQ<‡ÞQÉ‘È;¾Àn}œ=‡ÒÖk\>rzs ¶–™èJ5Zhe< ˜(ù´ÂûDñŽ9Ž®­e¾5ð>Qm`dV¹)që‹B  ÐÈ…’¨4ÐkhGØ ÇÄ íª¢ß€ eûôPü12’ó~G 9ãe<1¦_H›c|Ðlg˜Ø”ÈÚa¤hzÎ2ÍöaËîh@PpîI‘ùl#Èðº`L˜•bΖQªŠQ: yKVÚWòyùf%`Òt‚aäöQòt>‚ÜZ㌿ñd¢wÈU‚@Ü‘2,»,bÙnM—Ù" ºœ3>M] RŽÉ/+!㪚5«é[Œ¿jãÖ[»#¾^ Û–Á;*9¦ìh¬ä‰€îè[í»“ s1µÃ@s[ƒ'²ÄñçûvMš®`Äa $@Ö ðÙÏì»RKhÀ¿ë([%†fkâµ0T pÖU©Añ²ö½I–£…‰l·rkLc.†¸­%¹ý¡d®ìõªFkø¹™(´õ3 ÚgƒYµ®˜;áŒØ}sÀäƒ7wß¾ÍUâ“Ðóg"û«´œ§M²Š¡dâ}tÅ7ñÅV%?)ëûæ²Fa•þŸ­;ؒŶ0¼ÐÊö“ZÇòÑÓ{ü»ëR£` …Èî™{%; €‘µˆaV•ËuSޤ1×ÐÕiX¶¡.¼ö>¨Ý¥,÷‰h¡Ä´g%ãªâ7ÄZÜ”4‘YåÀÊ24@úkp.âH)LQmáЋÏóJΤ7ÄXN á†Gr 7.ü@ÕcôýcÀJðo¿ÿþ»‹(X¨uO|˜¬IªJu¹§j8Þ‘LÄ/[4+2UÙñ ?[îÆ< [ožáÚ½ e]é•„ÑbOÜtJd À-ÐMkIF‹¸fçÃHŒÊJ3DòÙÂé R* Ò²®ˆ•޾«üe&d.eà ¼HÐ1Œä–2QÕˆöx6wÕ–¡ŒÉ§?*úÐñœÅ^¶˜AJH€ó U12çz3wdÈ_à@)çXKdÎñNWÝ&dM9Ö÷£a j¡L¬ËþÙ&°ÐsÉJŽd¾±MÙv)2Q вvsñ&f’L)ãó_/€!SJ¼RžŽJlÉìOGÙzxY£q",‹âö'+”¤Ìß»Ñ's„1kw$“3‰w\äÙ&µ+‘Ñ#EŒa‚ø.cÚ„ ï?€$h¢û†SëûÚ2±»QÇz·R¯‡o 2€y¶”@C·@ÇåÆ9ꢷ’ ó¬ÄC0µÈ‚̶ùdþ èÛòvŸÅnß9n:P4}@U?ÿÁjî¶Ê߯s Ç–îò®$`ïE0”«6†Ì+ŒÑ7ޏ# Ç#4°vÑbÈ“y>޳ÅÃþŠô!õL°È¶AùÄ|]?ÿ“'ñ6¡Õ|ìA˜Jiê5"Pžƒ#,2yeÇ2Ñßn\Ä-Ú I&w©~x6Ý& dbžkOàãˆ/G6VÝI% Ld˜Àý;“s™ÆÈTaæýÖˆÏ éØ÷¡­ðFkTMÈ4íŸ'œL®=eí1™P¶€‘-£«g{UŒAµÀ‚a¹éá¶zy† ô X¶ÀK:j©+¬©%° PâùîÕÕzî‚\¤Ö’›·UBv$.6ÏÓõed‘XWsB/ ×Å<%YïY5«í‰É?Ã2Rp(à»Rph.pµÇ Sˆ…j|%]v³Rb92 ¥=eV–¼À4d•0œåF _Mæül’‰Æ‚xVŽÚcà£W†3õvM@Ø92J¬kWH¯T ð.®¥éM$Óý¿„ìüfe:Ùcx™£€a¯L hì3¨T A†6"ϺӨʛU;óîV;7#fåØW¼.íº Œ^Œ0BÖ(êÈ–FŽý¦€µ×BéH㘕ßQ)7<’¸£Ø3Æeû0ô…jtìIiü©°×s<Ûßý)EG›4Wna%$Aã¨WN·IŒÔKƒD‹aà ñ‚’Cí0M²áJM‰œ>e/¹R‹ CŠ~ÚEâJÄöqÜ Óà[Pª¥YªõÊí߸F‡Éª:"U 5݈÷†½6@XC® @bÖ¯#OÜtU”U\îÃc|ŽòÈfiÇð´ÐP¥ªx©±AFVò–µ|DL&øL€ÏÿSx^¢2©½õD:Æ7ÙÛJÈÆ4`/Žg"úŒ«j!.`¶9ÇË ˜dV0½#7Pû2 $¦¤I¦$ø¸—* `@Øœ@ ®ÝQï(®ÓÍDN ˆNã\úðÀ–Ofóc÷}7¶sh“ºä­Úhÿ\h7ZUö¶-90®Alk4+Á¶rT’ÇìƒÓKßJ¹Á}±"mU;‡nÑU£³Å‹ü*áåH¸Íé1x11 %ŸCEíÊ=.k¤ìˆñGÐ {™ùcˆ‘@;äk—³­$‹îˤýod#"˦‹¬´Ã Ò`êÅïi ¶H˜O¿8úF3Ì Ó7Ö ûªè"SDb€¦¹@Cå+9)«gCÉø4%Cy‹µýf𵛥ÚPæÂQL¿éYÑcê"{A|í %Ò_Ì1Ä™l‡µßÉŸoW$ÐnÏõšØ}ÓûÏáúþï=·RíªÛ*[í4HÎ6©Å±­ÜܺJ}Ä­áHÆ à¨6z†M|}¸ ×dz5 YŸÿì.…ÂB³£f=ñ4{—v’ (”gÚ÷Gº1²F%Y‰R »a<‡=Ä582ú9ýÊh–5šâØ¿*I,÷ûQÞ]´ žñ†ö‰Ò`˜`dÎH¡Wàú BïØæYu¤¬ЋÈsŽø³ÁŽªJUÉĪÂ±Ì èšáÄ2[CU˸ÜLëR2T10Ay RÇ£þþŒ0ÑÎHûôó­®M÷V¨®Óç%.êe¨7ñ>—È4†'¬Ñ½Z)fb4øJñ1ƵOs#›.3±ƒ^&àëwR%//›ˆ^eƒ@½ªðûyÁÉAæ–CÊ·‘C÷Bªfh+þpëå°eʉ2Ë %¡ÑÄL¾ê|¸øMi=G×äÙhLGÂ2Ad‹ñw4Hd’ƒ,"{¥z‘ ²¬Ä i™†ÂÄB ÙRÓï@#×nÛD•¡£Ò¾ÒË÷«KVcqTϼï”54¶žjÎÖ#À‹ðºŽûi˜ˆL*â9´€ì7g; 6½‰› ÔÎ-g¨·FùÔZ«+± Ž^¿æH¹c$ódەն̳Ƭä âߢ§¯ÄŠ ¡½#Áil+i=2áHL pÆ8•:³U••²²£R|5k'3´ZD#ò‰Ñ Äȵ#­¤Àdô€¹¹ñ'# µËH2¸#Mx Md ÄÈŽÚö““[)õ·¶Râú 5¶mI#TµçS‹c-UáæFNÜJÈ}šôݺ’‚¯+|ã< ²gÉJü»FKCP—* ¦À‘yêr,6°ö„1pFŒ”›®ä¨äÝࢉ€2Þtÿ'Ù'c…”÷nuµ>AšºdG£·µuT˜æv cð@Uzá;VI¯P*ë… .}~â\6.½cO‘cœ’Lé(·[b2&K)רצiÿfÁ]ob†·ûü¿‰øª²’•”Xµ6&>Y†ª_NCP û)¸ñéFdÚiðà vÓÌÛ*OÕôõꊩWÆ -¾HŽ]°Liºªë(u%üm:Ogtï€wÄ×{þfmoäØª½lm‰³ã¢+#UÀ±½}iÂŽ+a,€hïm‰g"S ÕÌá6fÕoF ÙvËçô|_*“64ˆÉ0·ôª•˜‹”2ì)U[ ©+½ŒéÍÅkl ^¦‡;¶ ¼(» ÁÐS ¼£}0ôæ¶›ÒžßAJdb{ð@¥’5î.Žbæmb 8Š>þ°ŒoÕ™·*ÑoŒ h7úþ¢½®Æ©¶Œ>,%ëÝw.2¥FP" Ì·ïÜš‚þìaÕˆ2åÙìî–f[éM@ ïM12² dí™WJ ãå5âEL>éÛÙJ3»>s©k½HJš-Ðn¤T¯F¼Hl–êþ^¶q ônºoo½ÕGo×éU¹ ]5ÂgÒ}=]È·ŠÉ¤ÅnÓˆ·«FJ³LQ­«lážb¥È€œ¡^nÂñŒy>Œ5¸å£]—h+¥™ösH†O#ã‘gÒÕôÌñ;îs¡Ï¹–rL#b8vóYàÉPfŽHb{"Û N´³Ï])öÑÛ é¸+82̹‰Ç4~„Ã2Ÿ.XKb2ޝÕü´I&e&sÖÞŸ+|Ϙaæûáê¤i¢'ª·ï rLŸm¹‹³5¥jæ]J‹Ð«”Æn%JǾÀ†4p´½Ž¢%«Â šªSªeÏž€¦ÅLW’[lí~õw Õô|äFÀÙv Ë``A «Ê†&Û¬ªÛY#w¸øå^ÁÆ´+E·rz¯,dAŒo]Kô‚•ÖÞÆÜ”0ÜújÖ˜¦RUY¤'nQž•–‘¦˜ <ŒÙ±Þé[ id½æÍêHÈx{æ‰i‡$²§¯CP`¬Ñi„U3”}ÉT·j·È™ Pm¨Ø&=]]uåOÓ-&ãk”Ãr‹i¬K^ÔØñÞž31½YôùcèÅöQ‘O˜8¦ßŒÝQ)A½¬Çké{òò]až³â‹z#Mä€ôt0ÀÓÄ€ÀSæÖÕºRÀ”1ÚÉÞÀ¨ÊžhÕ&«ªD#sãÍ ``U]@ËW5ÔQ)çvPûÍc=@IDAT²U‚ML†ŒçLì;ÖG†çƒßÆ©6ßGEVõÂ{Š1ºðÄ@½dŒüšOI¼µyîûL¦L“Oãt9ÂölJ…¼}'¥$Vñ@J4=“Ì‘4·x>©w"žR{/äV{×ÔØx{›I£¶€€}LrÁj<¦ez"SUûHU»!‰ktÄÄ40RŽÎÿKHg é(`a3¹¥®‡!F¶>lõ0È”šDßÅ0¢ÆM¤é¥…’LÉ9}; Ñ1Ù¤ …Rqì®UnJ³µaGy Ÿúµ&îhP> ]Ĥh WSE:¶dXöUÓe¨ óæºð•ˆ‘ºÌ½@†ŠüeGÊôÙÂUñ­WFæ˜!}˜‰ÅÈD[á«&iFê˜&ÔÄ–qT%°À7½.LÇjVñ˜ÆÉgö½21 3¯E>Ïw¿ˆz5Ê®DϤ®Ìc{¶i°^²œáÞÄz#Yu»6ÑÒH%‘IH‘c +€ŒyCex‚îMªúøˆÍ²¦ ;ê…Û#0Lšâh]4Ö0ÝÆô_ÝáœU%U-ªÄŸþ¢ϳ&&€å¢®eJ-J­Á'O-ÖC* 2GUX¶ q+­¤å3æþ-CÖ‚÷ÛkÊPb[KC•š‹0†Œ›#¥LTE<Örù|ô‘hT›î‰rF&–‡Ûªk¾Õž´õ`Î"ACåß |>­×†ñýÛyo²­ð7tהּ)š"è5ÂM1® Z”l cr³Œ£œáºù4±Þž…ÐVô€c¤£È_¿þ壼°é˜ê¼²sóà&ô1Ç·ŠR¼cر®–ÐNϳ.$Y˜1,„÷ÐÉZfæ°À—‘,|ëG@l"؉Ï)6inGš[ ž&Û.8¡…,àIì¨÷ªÎovž¾[€ß ‘2ebúÂÎU š+óÑØ 0”~—MS#ÆqlaGûøF“yWh‡~·*9Î3AVeÓë¥Á4÷ÜêûY#aƒDkÐcz ÀËdeŸ”[†^tÚÓ aëi´Ódå‰"yÂå»ÅY#œ›¼qùÈüÉl 3EA¥ í¸‘MYõµ5E0‰dëØªšf/Ÿ¾dé9¼¿eh„’|fÜ ÖE)6eíö¤r¯7™–9´=ÀA†pL¿¶¼àIÉpïàˆ— z8²8g®ÔM¥ãx{Q /bdû ÿ_†Ü¥+@6à¯=·J60L”d¡&à\o†Ä¢å—'R‹ì¸o5YU½pæ@†@'Cö‰„&ˆäŒÙ‡Ÿ¡’ “»‡–‘cŽ–å”KX¦“ €xGá“ÖØÿnª.%K$ë'm3”‚`HÑÑ}2wlc@»¼-kGx½”"ÏíV—õ^CúZTµÀ2Ì„l¶‰žã{·ï×—{ž†Z£k6K `(ë•[ŒaC[/ZF ‡vÀ$Øn- C 4]; r®±+$Ö¨ÚûîÌÏŸL¦$«±+úFŽþÓHïÐhL²î•¿R›È ÙšèMìH™'@À'ÒËd‚DCñýyÌGTÒ"zðœe¶EÓ)#)ñ½üdH8·@s)mÕݵ(I_±£Ð£ÅJµ “ÆsÁýx¯E©{ÕXË1ý~Cî´“ÄÛ¤7¬Êáv|®œ˜Pêûcâ«1ÈQnçmëÚ øÔ˜ù.\WŸ^ÇzµØ3]ù´^88^ØíÚŠa›Ü™'ͯÚ;èí£ÁlnVi2 sðGrz=£c ÐT{ko1Gb†³ªEÉ è[F¦ÜO ý– èåFß'å(êB¾w\»AåÛqJ½6¦‹¨Vʰ¿‹Ì¤¿YkÌjCif›àüabu"¾ž ŒV—]2¾¾È–ØÞJ"¤ˆ‘µóq-}$.ãHÀÍQVxÊ1xA‰éSÙ Ü= M³-«2„­AæhJþ0>²¡J‘ 0E8îÆ‰u]áç'ÐQÔN¯Ôhé9ÓûÛmΪñvS’ž®‰>Z¶’£YûàÈ0@t†°lsúdµ[)IU‚·±»ø¯9×(cÔ¬®³MF&«ªË faˆHé^ø†–lPß:âjI)S²"H07^©…ª|êÊÇ1ð®‘X—RÛÖ•g-¹é0b#4:*aÎìçï¤H&]S£ ó§qœƒöJô€x± ‰‘ºê% ÏŠ€¹ck¨ö-ŠAr›I½-“•*å;"}íôÅëû.m( %b¶‡ۥŽd]kê¢Ô_ùçKã»L‰.<¼–ÚË”JýðÓD³{õÓ­DÙ j. ¦o.“+í¨ê'”,Q—’¨$gäÿ÷YÄJ|”³º .‘× O†°ɪb{Âõ~þC`"#yO´´†¾|­Õ 8ëÚ›—߀ +5¢gQcJSÊ9§I3ÛW–^¡±^¹Ñ—8¸OÝ1‡4ÀpL†=e˜À±êòøyÇfÉÈpËÃ"vÜ}$ĪfÕUÞzŽï2L”6=,‹3ìûsȪ‰Z)Íê;TW¹Ð¥žLëÛbI%‚€X§—)itÉÝôÅ{‡ÉrèÏ6­7bæù 6(¦éž‹®¦t—yb²2ö¡ý_FÇÇóï.ªB‹#’g7r$+t9’Çád-ƒ´ªÙQ0a2í 0ÉrFιqr»—–Ú§Ì6¤c>À¾ó?9ƒsèthº8‡L4iÇ^ƒmÎYUöcXc Ü#{%ä{M¦ÉbLD …cÎZ@.ÈTa;ø¬û‰fòêU1|<àØ¥Ç`4‚2[ M¼1œRÎ'ÛÓï¢ “2ó=Ešô|yÑ’ Õ¨KÖÈ­Qor|™ÃgÏÿþ÷¿ë©\¿\sd7·1,†cäî0“|Zºm``—L0}¶|j‘öeªEn%ÊÆ92)êMI øÈ;ÊzåÜÎÄÚ1óe<“é}öôŽí¤|7iŠ,“eÞ,Ç®I£ÊüÊ?/œ^™K Åñ° d}­Ž:Ú„†IÓ•´W•‘о#¦c2&"‡˜üùPÂ"=@ùj2×+ðdÈÖ†µÌ$@YWžÞ¡F¤@ʺ’9Ƥit#ð ­«Å` „éË׿¼@€ÿ;Î ¯® ëê"µËÙ¦”E/ß»™¥e³¢ñ2}{1‚&O¤cÎ1½^žÛ¡knþºšuWøü˜cuµC&˜”‘6Áô7\dûÐ$3e Á»mU-Ld‹âaà5tÜòùÜ9'wÁ4#ˆQ­fB”è­Gï.xÕ<ÃJ” ÉÚ§vxÿxJF ¼pD’¥žˆ\/~2€@/2åôgÌ šµ4™@ŸçòZ>ÿ§ œ…†æÚ/>Óª\²IƒìÛS©c½åžÃËÚ&†€˜›)H™X—H€1"% (]ƒó”ŽH&õÊv<.Ïw&À ‰û–x«Fx_ hÉœ?’€²?Ùˆ˜¾I0RЈ¬ðm«Ôd¤qFûšÆ÷tMĴ䬸Õ¨Š>‘Ö^ )0„•D¶<÷Í®Dã¯K]g£µSºµÆd]àšýå+hVm±fa]üuÕèÈ9¾ 1Žaƒe½ñ0À'ÃDÊ™rxÊôxëÙÁ­û8u5ÐÛjì…‘á<õ zU<2þ5ÁdȆ> óGÒ÷»•F(•ݺȄ’Œ·Ï)|ÿ¶¡=Ï™gHd7‚)u‰üÈñ6ôh×ÒkdE ‰³Ä Þ1q|yíM‘[ _ɬ¿Ïl‰µnïëU-kr;úÿûß(g=…r—0°€E³éýÀ˜Ñ0²U #³ýÛUûBט†þŒ¹ |†©v4WoX&kPëå#e¯‰ßY¾4µ´@þº2!† ÆsÐ2CÊôÍjO¸e:n%¤…3”¹±;¼öø<µ ¸ÑJ teå˜ Ó°‚ûì–Óãûiií>AÕ÷ß{dÒ-jo(ž ¾¡wåÏ?‹(á™+‰4ÄAST…Ç÷‡MŸˆj¼^†adk;¢?u˜Àd9kÉœÌr&ªŽò[uL¯ïA6®)FèŠL¹ö>,¥.ëØ‚@- ØŽ"ç`$ÓÞG“¦’Ü.K㹚Òé¦ÁÓÄëjl•Z¯[ð”À$Á6 êØ)ý]D©AæÝ…U›÷ ¿ÇœÓè2ÝïV<³%#à,hÂHâȔʘ‚òvœ×î•Z )ÈÚñµÔ.$¬è3Ì¡U u¤ñC‹ÚU=K-øzß̼ÞZzÏ2$& R„•Ú*M¤AôÉ\¶c™ %ü*é-ö«ìLD¡¡›4L›cŒªc ¬E6²ïe“d ª$ñ^†UÊÚa£›Né{Œ¬Š|ep-°ªÆ9ˆlɸëûcïKl½vÀëjÛÛw>¶+ÿ´áǨn¡ÉÁÑSXÌqËÀø¶ wì.[µ}‚ @:Ê-‰ìdezÁÇSíG—@Ð#i´x%âÈSônabÊæêò_ñúßÿþWcãý£ýõ>ædž2™¬š¾ã° ›k8¥ÌA ²êºf5ÆPÊf©v»ªÛÇ‘ª»ôѯ¥Û9µ×Û™[ Àèõd)Û°µ1FÀÚñWrŒµWjUC‹6TUêG àõ¶R™ ¹À·gC-I“mƒ`€O"·X@»ªPÊ9–U€£ÿ€ìÜð{÷4óL–•oIúl‘ñr &팄…’_î,s'þm†c %ÉÂeäHÁ°\¯¹@ËÔÞPL¤j ävð©‰Ü ”Òla¤RG¼cLâ&“ÄJ”ør[ɵ¼$Ü‘˜ Üæ,h|†gn¨r»Â ÂNàn‘Žæ•ïèÏ–¯/ì>N‹ìWFЛ-r£!€¹©F¶ nhákp^‡¦ào®é¶†’¡ª]ªÌ–›ÃFlPSº,27 ÿé×nÜ\šx]¶ ~WkþsÔÒ\nŽÖË Sjzï¼£’q"M&2“þx äg”L`]M16TÉo(^ê*vUšüéÉêÅSÆkÏvmTš€d½Œ5ÚS‰›^¥z‘ŽMÉG¯c81&Yd÷Böt4ÉdnÞ$]‘ZàÂ¥ü?ñ[R ë¢Ô•ÓÑæ¤‹`Ò÷Îx ß1AƒÚ–gÑøLýþšKÉà z1ñ}R5z½ªŽÄ<Ér&î¨È‹•öàJ|{oÒ¬öQ5‚ŽñònV7’×ÂÁ¡Y{k'Е¿TUJ&벘j])ñ€¬=‡2Më•3i¥ôñ10¿×P¹–OAÀôƒÖ”ÛüíRe%GÁ§ÏèòzpšvÅë“IC»BûÔ%Gaè:_l÷©|¼oô²`㻌¡·\Su%k¼ÈÙ dº€¾Lp 1 ’ÅëꃯªKÝ÷žØ1gzßË~˜9g¢š@¬‘›¬¥¨½L`J<#¬ô’Ü8«â‚d™#•„cã`ûßݵô]§Qå¿ÆÖn‡LàØ‘?+-5&à¯Wn%%“‰‘4®° –Dú5'søzéûo¿¨2Ä‹LìCß{¢Ad0 ûDÊ”²À\Ð`D«rã zaki+GXc&dÊ4Ž{“0}_ µSjïøï¿ÚÊW V@]-æ"4î›?àÙÃôËîB3%¡áÖ•Û­/ Ìm»Ñô† jŸªxâfé5H#Y ˜¢·ÑyV‚•Æh×%òiJOA#L©*·I;,7×Eˆ{ŸpV-ƒ1T»ÏTl\ÓSªv/Ó‰Û‡’¿v¿ &C GY8êLëíXWø§q$Àd²WŠlJæ²g·[]‘u×2J᪰q0PI;,ðÂQµÅ"a€ø kWu 6wGž”ç¯~©­¨f˜I@0]ÍJ¸E)áÞˆ¾®ÜÉŪ™àEÎaýµ¥‰d€¯Ëާ¤/k™áÜ”¬”À\¼¡)H>™wMU‘è"Ž…#€Ïưê'Çß \-çx¥6ÄDÒ`˜PÂñ”Œ”ŽnUkï†] ]S’uObÕºr¨½–dZ¶FošU¹^ ŒdåM„}íl„#ìYà”€ñ‚Ó-䪵°zõFˆÆÑ0I‰œ?Ù™ƒ0KiJG˜²œçÚßÅ"ñ@á:u92™P5´YlYõíô¤g{Ydš¾0Jþ`¨¥ÅòlJ|³vµŽM¯E ÉÐÿû®›",À„ =,Rt”[¯\I{hq#ˆ´0«ŽLèÃ9Ü™çË WV-éÃlž ]Ľ´$(ÉóíêHÙã{½Zð½ÏF¼žMl=½EG2 Ï'¦£=[Àqï¦ké˜Þ±ÐÅÇuÊŽ~Òeþ­M_WJ¸Kiá ‹@iŸŒG*ŽZäæÊUéÓ$Ûb€@Ь:®0Z.`2áOŸy‚J°¹Çú¾À ðͪ»c ?Žõ7L¤îÓÚx‚LeLà© |úÍ^1ž^ÆÈœid÷ï Ñng‰ûËV¯+qrû47óªý@`" Ìj[-ãŽó©ä˜ƒÝ¬Ñ±Ü³4“?Ð]±Ñª ݶ›¸AÓßÖóª&ª2äãØÝå~<’5Â÷£oOSÂí†aR{ß¹¾Ll9¼.FÉh‘ƒ,·L ßt›0l[€FFªÊ‹ÔØ\d&­TµÛí_Åò×îFyºNƒf` Ȧ[»lJœ$ãÙtk(ÉxJímÞ¿Ǩ® xçæP¦)¶[Ʊ5X÷>ªøÜˆ5z¢s«{¯ÖK“[bÿ Áäuh%$A›Àñ˜HL¤£Y¯¬ [&±.½w»Ï†þ2¦)Ý]ãHØ\Gï ЋCf˜f i¸ÛEÊÄJ]¿qÍ*'– eSjœ† æGc#jQbbá _e˜X¨ô…Qí‚o‹q)ý„¿ÐE¦oO€9¥Ñíß²Ræ9çӓª eVÓ0 ¾ ”é´Qh“ñ€ïk*·ŠÜ®€F¹mˆÝDWžµç³–®Ä* jp(2‘U•ü|Ú8ì¨W®ŠÔ‰OذëÀ˜ö!ÆÌ»†ÆvK´Œ?Xè2H—è«#’s#è•0Ž[>“²R wƒÛ*gdíÙæLã(,@ XÆËY5QU×ûµÓç  %‡¬Z #«FPú¿¥E ˜R#¥YŒ‘ñô§®4dGý×7O¬Ô ª¥õ”é1b¥žcš®ï÷2ÜÂzU}p6Ùô¬´Ó´R†­ÑP-HÌÖÈÖzxU<Ì¡gI¯¤½*Ðצ¯®RÛNù.x@D¦lÏô¦Ð|~PÎf¯­²~Œæ>B  Tû\Uc0"¥̶*f¥#c ÜZ™²ªì8±#L|³dÑt%@5Rî#•¶Fι_8¸ ý‘¦‹߈9ï› R¶ªÜM[CI÷ï"¸ªÜD ÙøF7Eµ+èÕ¢ÚqnÈF¤ô˜YÅõ4ºæ{[Z Lù¯ý Î\Ë>#æiÚVIð}|@Ž]áOâVÀºÈàaž#§$ƒeU²ªµÇË•¼9C?۽ض0x]‚ر+(á`¼‰*ž½¡Ë”þ¡D©/@‚.²#}XV" úu¦ÊGXÃ8š¾Õ‘kÇL3Cš”<5¶ Ržl¸ÉDnV½‘˜-ß­†è /¸ôáíFßcºZŒ}x æJÙ6®ë·°’—Ï<‡†Æ” R2hÞ¦w—&Ê[‰l›àÉz¢³ ñ¶#¦/L·h:­ê‚p—%&“OçêW‡¹xbḻéñu¸iÇhäÚ® ¡3l:ŸH]5vJ@¦¼K}þ‰9»ùÏ(ÚØYM8ÊÙ© 3ÒÀÆ Uš[ü|e1;‹×!qæM¹½‰‡ù×€½KÕs“U‚Áæ&@67ž'ÍZ”0‚Œ`™FÉÛùÐИFÐÏ î£ò‘Ó8ʪ‡iï?»CΙ'·¾pã"a;Á…#e{H¿qø°ÕÞ$°¡Ä˜¶ÒB/§DÂmî.n„ÆÃnazÀ¸Úç†ltJùÝÁ\>Ý¥A›ˆí sY¦çCÖ[4â4Û éæ–­54ö€}ð§o’О™;æÐ;sИU%_k|²Õ%´lVnmž•ö£IÌ„C&m›’À½mEŒÑ[î¨tîùÖp š2¾÷ÌS9˜åR¦;¶ívp„)»òmúüó¬Ä<X»¹”µÀÀö‰$nU “[†¡’i4Œ×kCÀSÈ>/Yàe&dbæ}F˜ˆO&þ,šØžHUĽ›ë쎞(œø:”RW;ë­½•~¬A\#±ÈÆ ÇĶ¢©æÖCS{_Èðªô™ Ã.å=û\6Q#An­T—,bÃ*·•ôÖ®J“!ÜJ]§.-)‘b>º­×7¼)ótT"fˆÌ™Þ‰ñqDþд0A¼# ˆµ[hŠ£ ÈŸ˜j!ãëÉQ'¦Áf{Ó#€,/n s_PnlûJÑoÜCLé¨&–aU{ kÔKVÕ1ó®'ã«æœ¬}ºvMéÑ1d¢–&ÓÔ’9¬WȺ²ív4þ¬†‘Wµ¤Òƒ ᘌ#g-1ô@ß¹ª˜É€”–‰[FId¥Ý íŽ=]&Ö#Öõ6RÖ(7N•C¶2œYJdܬ‘ ^2¼ª£È?>’é¸HI#`™­*™€‘ â€Ó;8òܯB륗kg˜Û6oŠj;œ1÷Ýx†uNíVeäxʾ¨¶R²†³èXnáé5B&pkç¹®Z@-J1ÃÌÂ0Aö!»BßÕ>b%Ìž1`³Í}óüážT—¨$Ãî¸ ˜9†’ÏW@×ácäküùк+×Ȫªjé¦ýo$V ÔhPFÒ‰)‘É|»ù‹,ó÷S®”O]»N³ðÉ0Öˆ|Llé zÃf‘-¬DÓ©^¥BIÀ ’ßÑp˜L6·FJ¥ôsÕóÛAÙY',ÚÀ–È:Ëz„£NÕZz²Ž=“öW£w× §l-¤^ÌÇm„%ÍÖàÙ·\»®v¦JŽ”áhDíxXc€8%F¯HÖbùXÀ±5긔½•Rš.…ÔØMúìUªâY5`•I]ô°Çï%i0 ÀÃiä1LóìoJ¶È=T>4JxÕÉVöÕß›w}—ÂXÆ‘RÄÓÙkâáŽFðþÍ %= 0¾â¾fV’í´Iz¶Z0z=€{Ÿ¶Ê,hLOŒò3˜ôJ)a]J–ñÖ ÌÍ8dC•dJx®>,2ŒÜ²Â°UkŒW­J†„ÉÊ·õü3€rÛâ»q|+YµFd¼‰¶!‡–<Ž7¦O†s/¸«5= — ZÀÄ.¥‘ÌÑܬÄ€LP洞 î: ÇÍªÚ ˜CbíÍ¢ÇÃ)ñŽñ1ª X1ñg€¿ÕY Ëö2ÄH²žà“Už˜Öë"mBìÝ6ˆ¦áİqZ8`º‘¹ÓëzƒÒn-6@{ûȦ8Ê”<ûÏþÓ`Y`ôØ6I΀ҪŒb”ÄÈ]@©”LæSj‡:*¤žX F6TŽYÉc’)å“ x¬Zªb·F‹a¼  ”„Fb¤)1J}~U)é÷€½­ÎHúÝ‚‰–3àF¶`b%ãZ©ãFD¶a2¥Ê5rZ°€|Õ8ÔèXøE_•7½iˆÒ È0^˜ƒ͈–iÉöAà) ØÜºš˜-%M-@ƒ$–‘ªxÇ ²êªÍ²F)[&ô2žyV˜4}+âs›'=LßÐΜ¾£RGJž@¸Üz/‰!î·CÙJ¬’åÃ!OÇps»%=^ØŠRuµÐ¨¦”…#‡2‡ºè9Ì#0 jÉ-å¬h( ¬ÑÏdHbÑcת-°^‘@—è"7hD†4sÖ›X/¬ôš[^µ’˜Àl„cC ÒTÅg®Ú7Ó±f@K}—¡T~/Ûè[ÿ|¥ù#ΧMÊ-ÀM)ñ4›Ž_ÔE“g¶”âó¿UHêEZŽÚ‘:E.J :žÎûcO #ïÂç;á¿8ؤ†õа—êÚ2ÜÕV糪‹ @ ¦·€D-øZdTJ ›% æÈüù`XiñW¤ñŽÚ•hŽÝóµÐ¢s+çÇ,Ÿ ¹ñd-i:«þ F©+g<Œ§Œ <‡ºü)âØ#ðY©vA-ñ@·S2º}²ª 6Ÿa¿ÝöG•2¡)ÚG‰³j•šyÇ-™O/ &>8Р@Y 4ZÒQÙ?ÿùÏþ ©¹­‘•[´@Wè…9Ð4½ç‚ dG]wÈÙD ¤ -ã}3ÔnŸ9ôž¦4O-%Ç–Ì_W$ €ôüUwì:Ý 04ez ¹µ9|ûé‰÷˜”è:À4zóÙ·E/A-AÎ}æ[†@$𷇞‹@¨§ÇxçÆå_ƧÉǃԛ22ìØª-Ÿ¿q@ú®I9ó)i6‹ÆäOŒ™IÕwJ¡Ÿ•þ2^5Ð;Ä"˜ÀÑkè}yzU³àÈ4F@(Éék$·xª#ÓȪç›"›T£ȆÉc»³uíÑ…1-±Ëœ1ß¿dm–›ÒncÇöqÉÆmÏV'(Ú¹¹ðöјð¾|¼ëÀ_ƒ__<‡ž5츹µ4.Yß`>›Žï³„–Þ!¬EîŸ)iô&Z¬µ­¡ƒÇ‚^Î ?[<1ŸÄa12؈mÅ¹È Èø57T H¬êx:¿·2%RîO¯&fØÚ9`ëõV•ø³Ò+{%%|Ÿ=F7e ^I¼ïO ”g{Z²)³ 2]h‡¯Í™"ÞKõŒé·X†~Où•W¯.óÏmÎ×õÜ1g-”µ áx@Ô ´‰«©šó®Ú¥È*5Åßè1®†¡_‹ý‘ {XXI¦ÏÊè"Ä»Œöœ»—#SºE¿¸;ʦÐäÓèF¤Ç“‰vl¥F›Ø8šde²Öΰ)ð°’erN ÎÚ›ž,6¥ ÂÈmˆ×ršïž^Idΰ’¬ÄÀÓàíms‚dôMÁ¢Ï…›ÞÆ)-04<1@ »¯j%L8½¡ãañù?¡ì 7Î 0Þrë?=÷L¥©Ku7l-Œ0¬ía&Ù‘²KÒ3̪Ü[ÀÇâšÈ Ò¥Ö;Òû(1rQ‹ÄÍí >.÷h$Æó@ˆT—Gæöê»×>lúüë壥 1U1sÆ4¢éŽfÅÀ‚ÃÙé{Ù."Ó‹@κÈ`¼Fø|Râ—¤Ï_‹¨lŸ “…éÝ¥)Ñ"w4¥#ðV“­ä(ZiAïÙ£å6ÿ™×.WÊJös°¤¨TãÚÆ™Ô ]JòÌí)÷iúĉ{ÿÛw–Q ò_užx‘ ï×%ÌGnŠÞ¦·Uǘ¥Rø]ÀúᲞªU) TrTVÊÇŸsJ¸.|bŒh“=…öøJrÓým€2±Œw;s5öGT]JÖkŸ@û¨ is %ñ°¼ “¥—Y7“WîMÄláœ/ýù°øƒ´$–ù…ÛG( ŸH³`·‰³r„Óé÷Fݱ7ÏŠ,e ¥RM%Ç×!LCU“}þ_BÖi†P1DEÏMªÿJÎ?w¤‰!dªä`ý¹äã§ å. 8ê%ä¢ ”œfd& +µ$R4OÐ3¬,¦„Ì6M;à)Oçw(7˜˜@­ \ÕÁPnž°ÜÜnÓik×ÚDZA‘µ(”Ñèíæ˜CC/š«d¢++ÑàËÀFæPöaaŽÅ}sd-«¹ÉÂmŸ,¬»š5`†Ú9#}sü5™8”E$\»¬ Ï#t…ÕîBÜ[F·!™jÓSæVc™!= ¥ª¼c[eŽù1Ú‘ßCú¿ËbäÜÈ4 Lí²é=Kâ4m x züœãcÒWÚg„ȽCŒcJG&Ž2Þb°hgU̱¸Áö ÃZÉ|Ç|4çâÖµé™ë­Ñ›L<){=¶z5™g‰{ %G¹wتkœOž5ÊM¬=Ï:+¥˜õæV¯ø4xXtS4H¹qÄbÇôùpplsÙÕ²’ua8ÓGæ/@hÄŸ•µŸ h|¤†6 œéd™âµÀ2Lɪv7QÜ4ád•´‹V$€U“u% ž8^ÉnJ˜áóWÂ( Àèá€3æ±ÿ‰i esë…4ÍMÀgko"á(¸ù×ëˆo+ (ezŸ–l«4ôm($«ÑJ”-Ö\U³(=>†L & ,`%™˜ F>‰sŽÌª.Ùoÿ·Å$ý&ngW@ªæ“sÿU sëRE&cÌâ&øÔn4FW10f¼Æž.ç²vü|1™[ÕEú iÞ_\vYzÁ/àÅ´ ¥r‚ºü N©Úþ²¹ÂÙbz·0=ÒV Òb\&˜>dÎýºÁ×ÈjXK]-ÉDo¦‘…q¹Á Åpsl4Ò›#Eíla†²eúÜdÙDKÞ]ÎwµÞ‘ÓïçØ'[©Íe>" ç¼öŽùÈ‚‰rtº”ðkï¹TÉc\2<†¾ã kÑå‰Öž Y/ã(¦aËMI»¬TNю>µZúè5* @MiÉz1ªíO ôùqTD ]8õÛFÉ« qTMp†¿@kõ¥çÓ€^ÐN¶/ÆÍ»<>Lì×bãš’ŒÀQVŠ‘ELžvÃ$î[Ž °I§ùùr´!†Lî5`  ÏïCeNÓPæ€Ì¶Bz@c/P‰¾Ø’=,OzÚ7îØ)Û&Ó•†gû`€Ž4°Ü¥”ðeLnÖKPW£³’ ]–ÏÙ†3ÏÊ€è´À4Mÿzœ5˜+‰i`޽OzJúd}1MÀÄ4rkãÝKpK¯—“Œr¶ ¢äƒÌ hCdWv¤Q0ûbcö\ü3)c <`‡.•›,¸õîV]#Þ±ÆJ] PÂ󧬯‘S£c$xý×B†ï¨‘g½ø@SÊê8Cd¼YÉr‹÷SL)ú¦™eŠ£* ¥ª56"C<@ÆYK+Ùí8W^c¥u)ù³\ýx \—2ÇH²ô-‰od²o‚{M™9}ž”°ÜbÄ™Œÿ¡gÒ¬Ä3Ü °R__EXDÊEûÃÚ….³úyùÛï¿ÿî 9‘g:Â,êÂëOO)fÚ•(ól3Gš9Mæ0 «µÀÈëzZrÎG PM¨ùÃZT{_$ F—ÜÇÜ8%š™ÇO?P(LÑó\*ÙF’™¨ O,ÃÈLÒ`Ú¡erð}OSIWÎJønZž¿£pä`5flŒ%ûF3÷YàëêséW!·ªÚT¦™ .™¦ýÇh/VÕNã(Æv»üß%k!0Hþñm©—9™\{×,¸£ªÞfmaG?̽í#׋Qrdâ}:Âã§ÇÄzsЛ²ŒÇD; ¥B‹ýñ.ï¯AkL£DãFz•ø„‘9Ëx™ )•šŽ¬ÄM´@™€Ìéñ•*¥‘s°vL£a2¸éŽz);éko™ÆÕÓËFMÔ娗VI¦ªŒ—#eV@X)&ï›sš–L&SbØ,2?¡ *a”rK`Ãz+µÃ:Êb>”a2&J=øøüe¥î+¸Þr;S¢àGy>ª‚¢—5[D’"e“dv²ÐÄÃÉ9´¨]4ù;6Ú±è(+‘µÉ6”¡Ðâkä8Y$ƒgÒ&€#>Ç"ýrseJäö4ű èU’)Eƒ2Œ+ñ àHûÐ8¦TÂxdJ™y{Ö¨åÔ]ÒÈ™l¢Æ6¬W& šX#ÏzñôŽ@ ¢.nºÚ–,Uz?6ŽýÉá磉!ÈJ»)"CzÑþMìš0Rp€õú•çhb³ï×4†-7‚4YÁx½L´3¬J‰éRM©—Rc|†µ¨!˜Ðù¸eÌ‹)˜2·É6Ôz:†HæíüüƒY´†if=&Ž Æ)ÉJL%™í10@ šLWJ@¤É­öJ²%GÚÐ:ÊJÄéM© #™Ç©%Œ1)ÅÖ€‘Úe$7&ŽZ€ª}Ž{4×Ò—$ÃFÈ9|ji=2ß^n½j†Ëª¢cG&°|%d;ðTò©9£!è÷bŽ4L´Y[ùÓ4ÀT¢Òçœ'[XËd¦ =]>9TýË?È+$¢nE@¿D/Þ*ŽöÈe€s;>ߤ6&îu¬XË·Zh4f.;Ò¬==ÞbaâæjoíF8еuÃr¡½'FÒ#°\pNÙ2ª€’YJÛ/`Û:Ö¨ϪöF«š 'cHæÈJZ€ÂóÈ*ÁYÝÎÑ2ŽÆ݈8O@©#e]2e†ôiLÌ!+íÙ:Ö˜,^²À ½£DÓ¹£²Y‰³5Ô7 ß÷ ÀPò!«E¯MDþµSrè•€Ú$è ¶È>M|[5 OSÌDX€øõ¤i=ûÔBF ±^¼ªÆ°<@ k1”O#jì‚}Ð¥¶ò:r½Y!»¦)¹9+ XR¤ Àe2ѱqö!C–»‚£%ÍšÃi»14–즎]d‹añ™z'д3fsŸ )“‰ºÒß០s^6‹’¬ÿžÒôµËÌç©C†1·ödM©Ñã8î¿üÓ瓸×ËÖŸXþãyv‹dÕp §ëËà(”ÚpÊ­g(çž&hÛ– k?¿qrÙ ¯QRch0ý™ßÝhðL³NƒÝóßU-í¨æ? Þï£^ž±Þ£­"å¦Ñ÷έZ‹j‚F3©ŠÜ'ý#žªÝTØ,‘Æ Ì<Ò‘Lo?¨Jw‘Ïë숙jÓa¥þá+&päIË4ÉLlU‚–áÜ2 #aú†æì˜!&üµàëêR2}Ñ0pT] ¬W`Á[m®\dÓ7B6Áa«†v}|LÛ2We‚oŸÄ™«Æ#19°…cÚ¼0@ù0DÊChÉ62A‹)ÚDοÞ0RKy€ÀC1|«ôÀ‹|\–Ï7ìû#Sm甘]!¦v8±œY%Y‡);ÂZäþÙ¢ãL^¬ÊÖûÈ9Ä̇¸×ëc²ÿûŒªºˆcøì}h€Uk1—' }…dthÕ%‹3Æÿ)´Å#Å[·=`••ݤ=µ¯Ñ1YLUŽ&:Ê}×aÑé&XîJYõp-ŒÑn:¬Ë†ã1BU„UE Ë~™ÔÐÈ.kŠÀ·1Œ ¤ÌAf»”‰EJ LìȈqìçÙ&•¼áâÂÂô1º|)žX‹Ÿ+üü ¦ 5ê"€^hi+ Ù6·Ìjž x"ãA?¥#±@Êd}€£q9hñ¼µËs¨7½å­Ê¤U“½&M¡ßÚ²Þ YÌ? ‹z™k7¥eZX)À|b"›§çP`, ‹›ó4}%Žï÷›<V° ×pÈ­=ñŽWòILBøÖtõ¥RÒo:=¦A@‚×½c#Îr7Ð ¶ý)õºQѨÎÊÕ=B7:Fß¿Lð!0Qh÷CKÇz öâþñÇ5ÔŒmFeä@2)ȶ„#~óì¤ZãßûHU99°åV]©¯õ~ðšk\{ãÛÁ>ûa˜þÝ„¬¯ŽÆ·«—Ôí Ò%º;Ðôè¨´ï “>Z@)èr„gsUç#yâ­G¹ ia@ιÝ2ŒŸÉö¬Wf«šØ1FÖH,+4ò­ÿJJ–yVKÙ\›H@ëjÃ1œA#t„oå|¸>&UC”H¦díÀvšx™[$`ÌÄQuaá³KSÎVËÛ…täoK^ãcUTÊVét~¿BáÖ#´ôõPrä†G֮䗅ÒJ‰Ì[8¦ç"n¬¶+|U¥†jl g¹Ñ™Ô>¬’Õ’`kSŠ÷›O Š‘Ez9â÷qÚÙ¸zˆj'v ;ÚŸ2ýZ€3éûû}£uMÃÄWkÊ D²®Y—Eä+ ·¶0±õ€Ì5þ¤v#&óåض'EíiØÒd›ÀÚ40^hv“w #›{…Ÿ¯ÓQß`‚?ÿlîv ª²H!¯4Y@‰X;@ˆ¬ ƒ·k Æwm%ÇVÌÍQ4×ÄîITÊ­ £«¨ f.z2 ¦Åhnñ“˜!]?Ãæу(Ù“F ÊMÆ» È­ToJ|ÑæH@FfÎÓ½l‘më(àHJÇéõß'°°/M¶é‰í TáÄ€^ɺזIS‹ }sk,÷2½5Z@nÕÙ&¨…'7Vª0R†1L”äô)1ÉRÂüë…u‰µ§lyz“§.˜³÷‰!Ð[ð©äH¦=€\`È”Æp7ךvËö†uµM--i7‚·ï(ȬÎzã›B©7rÿ bŒ‰‚¸ÅÊfý¸‚£èÄ܉ÛÍ;VâܱÜkévÄŸ’s—T#$¶yÓ;¤¤i7€²èØže¼^Ø h6ÆÐ,Ó$Ã{¨ùLÔÛõi€VÒ›yúFœñ7Tés ÞZ@ÞKÒ÷!ê®ºÍ …k$vijmÊ–Áói"«ææ +ÉwÁóÑëMÌ yʼRÔÀÑ‘£PÒ†oLmûD¦š&¦Ô…­˜I¥.w”'¦OÙè¹Á-­´'¦o[¤ gê÷™TñŽz-ÙÛÑ •ð~Àª5n7¥ø¦'.WÕ‚‘Ûß/ÇŽª1&6ˆ-ÒÚFàC÷zpÎþÅ8 UY5Rz™^;†¹ªOäªÎïz¼®6Á; Êz-SW#à¦5Qn\«v‹þuž!qSÊ1M©7>¦Ñ²Y/wħX× ‹HJ&˜Œt£J².KöJîÞÉT›â(Ü ó’†â9#û8hɤ'À0¥Ywdz’€‘)mu‹çCÑ%áÄôÂq¹ÏH•Ò\â>²>…)(ÍJ£×Ú-Ðl(!»`žZDŒÑïJ˜J¦ëõõîú4-Y ðíÖ\Îñ–ÑH$n ˜^©¿ ¤ïƒÃ3©=ÜP™ >qnò©Eɶ›ÞhG;רK8* ½o‰Rà#ûø4:²ík†,f&³ ²»·˜#çøaa]M¼Ã?ïF#š‚X¤ À½[<1½FOÔQ¦'ÿ¯­»Û‘ÄÖ‘5zá+¿© †Þðõ,éËŒjà ƒAJ™UÝÞ‡æü¥ •ÂoŸ4ìCŠ×/ø"[7^ö­j£¼øàá4€.w£¥Í`5ʦoÄ4Là¬R:R²mDJ›´¼#^ä‡ÓȺfÂÓk8"÷—?GA½^ŒçþxÛD/æßôö?³¿k%n æ†jW’ñ-ì(`ï)"ù˜Åœ IÇ$StßMX :@V3)ìs!Àg—2î>€@jL0o’¬* I@ÓeNÿ½¦}èiÖ’Ì>U=1”J¬ê8óü)‹>¸UâJz³²FSx"Yaè7ØPŸ:^#&ÁíLCióÀ/ت:ÌõR:r F®¥Ý¶v--Ó&Jôø¨éˆïFª1Ü`½޵w¬ÔhYo¶0ÀMÔ; ‡Ößg]®…@{-‰Os[XFFî%á†Ö8Þ‘ÒQoVŽHÑÚ¬2׎$ÃSâ+5EWþ@wI3’¬ Žç¦š!œ`>Ž[‰¬5”4Í #mBÓþ@áØè”t  *<7Œ Ó+òш¬Q·FW½1ÇôûOŸ6G:öAtq¤®ý,d+ãÉ8g¨+ÃŽÃáF·§#|]?WãÌP¯ýa²ÌõRŠ@VŽÙÒÇWõñ¬*#ùøIºHë)™²€À @W«*EjŒ‘a¡d[GνÌõøøtÇ~É ˆ1Äͪ.Ó�Âý g®DfîĦëêÑt‰” 4yþ§ *Ë9V3&€ç%¨ËõÏ4>²›¿¥|0ÜdG¹ËhD扜yk`^—ŸOzצɜ€óm:ßÅzɪ&ƒEXoí ûBtô(Vþôæ&Œö”aþº²âv<¿ªŠvksb$qZjÔ‚¯1X)qÀ8‹ÉÂ[ÎöÒ¿Þ0^o 0Lf[HG¹ fn%˜€²[À¦ÃMÄ3¤Ñˆz´þò‹!àC“²+8Ò0ì¨TT«f UCMT­%+¸qø÷AÒÈ Å+㙟đÍâéHДFô{¡oTžewLè)4š›²Ýòôï. ðô ­„ß’JÈþmæµ`tñ4ýlóýó²­V%N/ÓàáFD ÓTµˆ‡•ÚS9ÍpßÍ÷aþÀ+ë ‘ø6Ï Ô¨D)7:°µ ’v÷6‰¹•“Ú§q”ùãûi2Ŷ­QW¸í…£€å‰݃ÈÜT™”9oœFÊÀ ˜7|—ÅàY5H jLÖz‘ͪ±}8è:.€2© cj‘Ï–:•\3ÑñBƒ’,š_/r&ð”ñô5ªÂMO‰M ã j©„1¢Ï ¶ù~CUê.°YZdâýŠ ‹¦|Og7æ>HL¿ñ Þos&Ì{œV%æã Ím¤–”6 RJïˆäàc†3”éS ³g*üIDATÃþÕ!z·ï¨$þßvn•&hIÎÀ†ª2dÛDY04ŽÆˆ”@sõ‚¦^„ÆœNÖÝñõêÂSê wå) dÈA¯ðé é5ÒˆF ’¾Rž1zÃŽZÒcêÊN,t! ]É”0 º¾c‰ìH¬=¦•âµ5â×Û›8 ëõÅÓN¹cú<ù;ª.+’5«é=}TÛG4ÚJGY8+…Y)eÂYµh€†À_§Ï/¯±P¥Dʘvà7QÎvúÚ57h«´lIŒv‘n5¶Xƒð•¢?ÚÃÆUr߬´pý6˜[Uùšµ}Xª”ö©nI ™*ÿÆ)5±/s›w‘Jõbzí4ÉÌbeÄK e¡7 kÉJÀH©Äsþ?„Á T5XsŸz^Ý TÊ h¬ ¬ñŽ@UßÅZL¯=1œ,g“›ŒìÈ¢£’×OlDV@oô¹ä÷æZ2ä@#rƒ•úÌC ´éü×¢‘ m×}7UL¸nå˜Gn4¦mç|š>þMÄWj ÿÖÞï³\–°’–EOᯓİ)€*,ëÂÈ÷%ñ&¶†œ&bÊ|dÊÄxÇã(ØbÎ}¾—uTÍÊÿ領áq¹Q½^D†H¸Œâ»ñj™t/߯ÞЇî¹ZŒOV|´È4•øö”ÓZºÎ6i„*^Ìœ!,â>&í”H9+CAP ŒÔÂmbSù#)áºâék‘ïØÏã;´CCuµ€c#0a€rG¤pL&{†È¦Ã›"”Z€À¸ÑSÒÃdñŽ{xцLÛZTc&ÃcZ²Í•ÇðIPÎIV/À߯é~!Ô¨„×’¦‹À>/ ǘHO–8«J4xWcž `ÒUJXn’p¤¬ÝQ‰¦à³.@PfBIS6E¨ÆŸÿHÐkÉúkÛG»wÌ¥1rÇuÍ´ìzŽ0O†õº RX³µhDV=“*ý.¦êHÖ·`«šUUÎø”Rêbˆ¤!h%ã/¼ôR¾šdZ4ŽMLj®ÐþrÜæ˜69Àµ‰ÙFšÒJ èWMüÎUBb(-Öþ]“F¦É¶Íé‰=ZÓË  p} 8ˆîÕ¸ýí’¬v]FÈ ýs ´óÌÁžŽsÆëR}š™ìv›®—Œ Yª–év° iÀèðÜX í~‘ñ×ïãYÕ“¬šÂ$l4=CC€Áw”+!×EÓ È”r¶r¢×ãp³Ï™÷Ø‘&ܬvð€HÒ ¶âìHæ¨*rvµ7NÆ4kOML“a»921«®mî+õgï»yC ôbø`ÌÊ0 U²®³eº¾Èíõ§ŒäfæŽHUÇw4¥A ­ÑëÑÛÓÐÙhùaNƒ•€fµô󔕼Ïi¸‚‘-C·OJU±†)“Å!já`JL$YG-b²üÁ4¤Øêµ9ro•¦Ö/˜‘‘¼Fú4­‹ Çg˜CÏ­=A&m‚Éä«Ò{;™›.¼Ë D>4Ä&*!›u럯x#🌾v$ çÜ“àoÊé¿b@Iî lk”aú~BàLÈ„jCUµÇÔR;2ÆFÐÌDÕGƒÏŸ²Ò€#¯c ^LVd ØJ }¦JHú¾°–|º1CÖϬ+óJéA_—Ýú|‰3W⩱h ¸ÑíßCÅøéE {®`hs;&Àäm°°¿jK6.|\.?PUÛà %Pí( #dK %Ù‘'}Œv€ é2Çô\é‘g×gÛž‘•v|] â¬î;¦$ÒVm¤#RÀÈ@d;`˜`ÊdØÂi0k!€kl˜-ÆQcŸWæÝVr @¹í¦ºõÞ•²m ¼#YæíƒŒ—{¨Kœ´w‹i=¹‰9gE0Oþ­Š4¢Þ@£çæSÆðQeë.J}ôÓ4næí Åǧ’H/3L3 z~:+ÚP,jËe¾­’l›îYWÓç`ǰÜ5VT…Þ™;²Ý>+­caz²²U¡‰ßh ½ÑHš€–½Bb%d?*>¤v J4€|½éMÔâ)4Žz#14ªñHÇZ2¬ºMh`Y/ =l®£Ž0}»UJŸ!¥ßzJdóWï¬úÊfNpƒ±mÛ¼?'ðÄ홳¿ÁwqUKæŒZÃɲÂw¤èïY­Ñ}ùPbd½µg‹TÅt¤ç²Ñù4‹¸H?“œ‰SNL@Ÿ‰KÁ."0ÕnazL]Èö!ˆ‘5¶¬*òúÂèêî‰[Ó Dʺ¬¡+©}šÖkCdûð!†²ÝÚyJ`߆ïϵ¤^ È‚•¶‰[i òN;¯A¼k¶sƒê%Pí²í™æùüå2«&ÊJ4¦'FröEõdÕG¦ÔFXOx¢š¨%An ÚÊÿ¦ gÿ²dx]45Ƽ欴cò¦ ôceÃ4|)Û–Ò‘èRŽ1lÃr²1@[MIÐ L¯‘oÉÏŸœQ¨F ôpÑ$8ÐÒ°¸}g'€•1@Ÿn²º`Õ3õþ\õ…PÂ÷ Ρj/S»œ9 rk +0^;ÜbŽÈnמ§óîÙÄV¢zå®P¶?Ÿ0‚f_èF[OSèÍç”UyÊFèí¯*sh%€.%£a™Ík‰ÌÊbdº@,”(ùt”ÔN&òlt× W•›¢QûHš^UÕ·?{ZÀÄž¨YéiŒMˆw¤ì‚ñrƒd+‰ÉºT-S{ÎöÉÁ1ŒqÔˆ¯S¨êõcßþHGA¯ÝÑ |ÓëÊ\®$Çè¢o"C·p…VRò»ãX+@¤0dµ8c8‹i`Áî‚ûÖ™Þ†€®9 {s-pæ°àÐVo&BIK¿P{¾ÚÄŸf™FU©Çæœ!YãäZ*ù=„ËÝ%+½]P#ìSÏ\K;L–RV’ó©ª#ô ¤ìI³‰ÍÈF8Æ´^&³âC–òXß#=ýþFƒ1”Œö¶rwd†öÄ÷óÓÐl[›ÀQUÀŽÀòié•R(%#pì“EŠ[?ß -"¬d+èÅ0ÌJ6®¬¤‹¦–¾ ðÆ]×c+jW1ŸñL‘€*¾c³5›•ž¿Å”dÛ^ã“àÄ0e¶ÍJ£*Z¦Y™ðqÔÂÙ'2MæŽÝ·×ÐÒ•yfÐhoJKv$Ø Õ6L/«’%1Ž‘]ÐQd^¯MÚ§…´^ŒÝ([¬FV€ŸA ½£¯å&nDÛîhb¹»{œ^•¦êÄÍ’-Ã\î:²}:ÂMÑ ŒotãÚŸ31,€ÿ¸Ñº`2&]–çª^5ÌM®…ò׿[Ø*íî&mЖpýEWBŠºð@U°¨ à­bƒp«¨"»çù(ͰƒÞ¾©ŽÝ9A%ŽEƒZ{悔oCÓU“i2ÑÞ1¥tå +õc€®©1%Ýd²”JE2klO>z9†0å}¶2}U97½ñrå׳*‡J2Þ”``UãzêöI¬ÊgVz۪Ɣ]Ók8v]0 ÐíG¯GÉÐE#+ ÂQhICä(u_YIVÂÓwìçíz|>JU%#ú×Vµ†òWXÉv9Ÿ.Ï¡ß,[C©Šy•Åx¥Ž²ÌU’µÍr„YííFœƒ’mk'F6=™Ë¦ض¶£ ç–³êRŽ€lUž”Ý:M;´@ãTçC/T_·.‚ÔN)7‹ƒ’Ü’µËªç¡¨I îÇ “±H\¦üq4Û„¬´Ðn*¾ûhÁ´(б¥÷†^û¨Šº€V¢mÕ¶ `[Á$2‡âç 0á@YLæ—‚ë¿%ú>6|Á 0N)ç|L0[ƒ)Ô‰a¢EÆwÔ"ÇWÒ‚ÇÈ}/³’=£Š|èçŒGÊzûQTåÄls–ÉrS˜|z[˜C2¸M2—Å«×ÞJ” ¤O<7ƒ´0ÑÕИ5ªvq ‡üi`L¤¬] P’™‹þè¥T6aøˆUÉúL›k‚–QíˆáÍDd¹¡HªÜÞ—“ñ¡!׿ܥ5ä^À¿ÜÜiZµ¤`"ðr[xnòû&øöäáq™+ëøô/v©æC :Vò€¦Àz'C£ „c€R4]U8&èú·õˆ“øÌ‰;vS⪕0‚ƪýÚ‰±0‡üõÂø]DZvnHÿ­OǪZÚœÛLÚvš@æhtq‹wl  jGz²&RÚŽ!HŒ'+0„i±Z«v…Žiê’›EÙ±¡²8ÿ) …:»-uǬyíˆiÅJ¬UËLUnä4Jf·ÐÂ\Ђ|Ü‚‰PÅÏDUôÁ)‘iüÈ*ißD˜'%UG°êxíÏwÓ XI‹0Y‹¼õÔK–!Ð>?Ì”Lc½zËHÀǦ‘M”¹éþ€·Cd³Ê”­JŒáCÏö+•^`ò'†#[IµÞÈ2FINŸƒ£A?|,Ðt¼%i„AíÔ+-WÅp†oñƒÓ¬¥ÝÈhÂ2H£=@¨v÷–t´eº0°ÚYv”·™£ÌP®Ê$Gd¡ÑxfÃ:æ6ÃdiVòJHXf…W]à#›R&€ý1C`D)[8¦v82A&r‘U䟸G“_CÇ#taä–Áë­èj‘_M%zä±ó§»ÿ‡ååSÁ¶ ¬³;$uÌšÃ>Rt“1€¿)ȉzØÄ†:#û5«ï÷®‡¡”‹º2„—çVÉJ)UM”3‘{‡˜Jpûß«|~–Òç_V¥Ÿ­YMÑ[ãýƒE#ó0âôÄȶR¢—‘ýcÐt[Ï3Ò¨Ú¼.|³è9;ªŠwa˜x&}™hñ;ÜX úœ³¢¤á@v¤ t(àg ØÎm…Ϫìhœe.ÞOoUžªÃù ÛY ©W.”¤#b$gƒÖÞ·”€¬›ÖX®1?ÆÕúºvÙfµƒ}º{¯ÔãòÌ*O9’R0Ô»qU5QÙ2ëíÖ4þ‰ÇŸLø^OO,oC—m¯‘ƒ¡zå4²v%2XI{‹!…£OêßÿE¶[$}>ŽM¡ì»ájUy¶q‘xzŒè“j¥ÉªWb…—ß®”›B&’…k”O¼{YCI´Œ·Ïx%zǘ<1íÜ·",³ÍJæÓÑÚ­^9Ã=fÏ¥åÆQúJ°räc12%Œw$Èö·¿ÿþ[ åŒ ØC'ž…ŒR¿ 5ʰ’^¥Ž«r94d˜ôp_ǵ¤!dºd¼£8½c MÓij9w7- •]2h@ÎßbóŸæ8Þp4ÑõÁÍ‘XV—út}‡ðl‰•ú«bÇUá.µ¹€˜gXž’ Ü¿“Ïlw„Ó§¬³k¶-’€,·¾µdªñÉàÚ#³UâÖƒÀ«‘ÌP2®*3©å‡c»Ñø,tuGG‘OOIàV-:ªš‚é(‹Z êÊ–lô»’–ÉT5:Ëa†é1ÂQníf9RŠÚ‘<·Ûx M‚í/×(Ã-kqkkÇ!úÅÑï‘íY—Å(™ÊHŸ’ ¬½[˜ë(:7¨¼c]r`zS(mu–û1e&s£‰tpæJµ8âÛ\/R";Rú)‹$¨ŽÝ1Fî¦J ²ÚþŽÆ%†É“dr]eJAPnÛô­OY×H‰o.¦AíÜO.œg›'Τ}ÎÿÜ{†œtOi^#[(¾cãó%ö]a[•2O‚0¯Ý–[F 8¢ËÃõ¦)W¢ìº­ckÂçäØ&Ž™4"Ég§#s‚¢²#ÿ@>d‚‰Þ^?FµM:ÂDcU)>°:š‚Ôøÿý?ÐëëKß:ebG%Z% d"ÃÉd %k1ʪü™(Ù-+ ½­:æV¯LÓ8ŒHÙ¬ŽíC™¬®‘f) =@&s&H¦$hòY/ ÿŽ#uQfΙ€LµÛͳŲmÖÛe‡VЬ«=1ôµ°uÄ;‚!2[]…*À(üʆjr9Ó¶<¤–ÌÝÈ¡ßþp;¤Ôî˜XC‰ËÐn¦Ð·Á6ÉPis³% ‹ìÙ­´šU»RÏ’æ²h–,S %—´j%oŸ%]p+­êˆt¤ló˜v˰Þܘ$Ëá¬òý‡ŒRVH7…6_5ÀÿtÞ*†FhÇT²Õ4Èœ)ñœ•D-ÖkCOŠ9¦ßÚЕFÖ(sè­ZãþñÇùjø:1²hR¦4™¶™\—\¤çÄÐ,ô"«vU¥”ŽÓ'¨¤Z©{rÀÏÖEóú„]Øæ”s&Ž|”zGÀõsÐNÏŸ–Üîom®‘ \û£‡ûêŽlÓha‚?g2QÕÎ1æ;òQ@OÄß-¸µ”ÉT[ ÐbþI/s3® ëBõªj¤L<žF´p`ƒstuïípÎpÊLäFÁEú†+iÌ37†ªÚ9ÀØ›$ÓHÖ1ÿL åk«ZÌPÉwÀQÀmë g•·&Ê-Ó5c^½®í`ɺȚոH©$âí©wA&hÄULK¥H_æYW)ÉŒ j=Àw©’¤*¾¾€v3!€é d½øÚp¶õP¶UÌÛãCÑÕˆ—ÂDÊÈn¢YÉ­‹XL©+¥º¶È@¤\ï×õ|Ï1¬ˆ‘ º&¾®xšõמH˜@IÀm¥Q8f›N¦ 7¨eÕ>YÕÏ¿ ÜgÓm›A„Œáå(²ãRÿ6ÃÇÆ§oĬ´[]\§ÏCyV¹Q/·Úk9cnä®EnÝ™9†’ ÆÏ–•zz2 H¸8gâ˜d™Ëø°+Ùâ“á{´^#sUGªr¡Ô ¿ôù¿ñ1áîÓV¾ñ37…Xµ»hé²É”D8^—#cºˆ,ðL¸áOó}¹Fú¶¢D¿Âó¯nõ>ª»u-²HÖ³À‘‰Y¢Ý®÷ùìZÛÚ1‚ q$q¿ õÚœ¸­r#n@ÙP LIÎJÎhOÇía %ÛÁQ¤á©ÔßK^+#úŒ`z¹‰0GËÈE%-­d„HP#G(·y¤#ÒVÉìÐ¡Š—Åô)í;(9–1}¥Že<À0ÅÜÏ}îõm…t…°œ's²­V‘–É|¦”s&²ˆ±Ozšnу8ª:Â?ƵXÛS=³¿#€Z´GGô}1ŒÞ=•v¬Z ™£ªGÃôµ|U[p¬&€‹p¹|>á&µuTÆô%XA2ûÁæz…aJŽÝ¼.ÿJ·gêbJ‚mGzGyÇv(#ù0´¤l¦äC zøИ²”0•Äȳß÷¹óQL )€ÈkÁpŽº¬ÔP¡«–rñ•äÉàî“aL_JG³RÞ±LàØ¯<³D&”í)‹ÚíÙ‘&²ö¦¿%žiäB ìa ™õ0é#åx˨:Ö’ƒM¼UL³ ËB M¶2†2‡H̪™¨"åþ«üªµ4‹¡ªH¼UñÉ”`íÖëmY¹HûàíEXoÕ¬8¸#òšVÕÒ‚6Ô‚§Tê¹êr+Áñrn¾o3!Ó›F&0Bض)…vŸX×®Q’….YIÖr¨-àoÊ+NPN`–£ºl+U…«‚[C÷ fÕ.,Zä µí)MŽJœ@h¬ xÌùh‡Ó§¡ÏÓ±ûÆk÷èE ªnÛZ8Ã"+2šÙª:v#›ç·6=¦Ô…7Ú±+· ²éÈx[}þhv9f7ÅHÍëG’ ²Jæqº‰ª©ªF(QbÜÆ4Çèî)›5Ûd9÷+5Íéü~A‰EÇŒÿñjÖh%2ƒTëícŽË½…%ÍJcUwш‘»ûºrîXêbˆ\‹’#(`žp£_1̼…c„}êê¨ÄŸßÚ2RUnùðd™d@´`¦gõ® CÖ^Ž„¬&sŒ×œ§R#a|²rG¼FLÙ3ҋצDöàô1™7Zî.J”ÙÊ;ÂB¯ªA0½*fkDš’¥@ö=ßÇ]#^µM€Mg(TÙ ½aä1Opw§Ñâ˜àÈ\&¨ª®«*¾å³=M|³}{áŽ)Í1Ä¢H }€ÖI¦¤Ë¬ôðÖPMÙSPúû«.ñf!ϰ{‘²’hâ°Rþx¤åfÉJg%šMÌ Ó둽/“ÒVV"X¯–l145¶’RÎL´[CFbÊ~q•SfXWÇ5ö†L Búwõ€× ¹qz ]€®J¿ýóÏ?Q: Û[—Ÿ)RÆk6F&V@hŽª\ãKª&HSŽä$f¥$3,ƒ¯cDÖÕÜH{Ò¬—,%A⦤—Û§q&}ÿ¬&€e¶>€3z¶eüÛîÖ×àó§ý6¡ÉV»ÞF#mÕÎðÆQÒìM:’Åð¤ÍÍ™#[€@TÅ $Hù¶'CÞÖÓ›U+m%L]ø¢…Ý®‡BrÈ ô6¥^¹—T…·Üû`j(]?+@)s™ ™ Ó1™Ü›øÁûG%8“<™ó±F£u‰ÛqR`È`=¹¹UM¬šRfØ”‹Æ)µFÿ9±ªÓ˜É“øªjÛmH´Ëº0mH¬·•š%s®%0>°€|äÙöÑ¿&û黽ëÓ4E6¨Ymk%‘¾ö my-ïa‘“͊φ"aƒÄç/J(=©“fÑ/÷Ùi€5Oožß’5ª4”¢…šýbâ|"{)íÈ|0=J³`‘çzçÔ%G‡e¸XÅý*OUkP6n*¥ÀØIÐî÷©ÿr R•&†OGJ2Ç‘ɲG¦ÔÒWpëÝJFpS•s(Û¹ÞŽóO¹Ýð=BU7HIÌÙbœwÁ³¡Ø2Yaz™‰œFvÓ|`V•zÀ¨ŠWÝPi±v{™ot‹Ù³.%†ù¼aB)ó¬]ËûWiÕÙj§4qân=Òb2&•`Œ¨ÄM{kà“ú÷ñ0­m Χù¾<íªšç¡Ab®ü$Kò‘3´i`- `2Q© 3WBšNã¨oÃv¶@-F&F²íØM¡ßJöµï.ôdp™’¦M”`%‘Ì‘¬Æç)ëUð41Ž2OO#׈/‘žÔÑ”n a$PFò)½•v³úbPâûš½øn§Š—ÍÊŸ#¾ÑÈU‘ŽBïdùGÊü'èH ôò>e¨²‚Ï~m»•*\çªÈm»ûAfÝN2¾È!^'ðCÛõ˜ ÃdªJ穚™•ìÅûbÁªEU]‚­õ0dp ¾vÿj|xõŠªÄ)-€d‚‘åÄù«:/7S©+8µPZ>“dÝ…Þæ¢”„¹ªJrΪzFÕ±*1,ã |ܪÓˆâ-6’Ÿ’̉a›?|f_£ #a›7= Û¾o-ãXW†¹µ9}>4{a‚3æû¶À|t…¹Jö« Égßv¶ô݈­HÀP’#eߨ¾´ºxúz¬ˆ¦ÔËS/,º×®‰Èü ô–dZ:jtGbkÄ[@@ĵÈoÄc½ÜÂF„çHœî¨Ú3ÕÞ9G½Bß>JÞð®|þàQÍA;™–c}­dbÈæ>V)ÉÄiû~ÿéÃÇ÷û{cŸŽ-&×HÏ ®ØSKw©/üg^ˆ­A#j”)s„–ªZâ< (%pô21ž¥õEseÇd”¢êvèM™9üÛ_ýåÿTÃz„c#kvdMÜ`@cÕô}{0¢IEâéÅð˜#ý®„,"›5x9r³2}Šw,+1eb< °£ý·’O1^öK¯Ñ߃joJ½šg¶YͰÝUé…FnÌeoÕJÙâ¥b$M¿_´ljþÄlûP0×þóW$X e«®}$ç¾O)3Ï™& û.uÖ4ªH%]“©ZÆ“V"-VŽ'6‹Õñ½C³UŠ‘)Ã`†ŽdÝÚãÀe]~ko"±Ò¬ððªJ1Üy{’õ ÷Ï.LðU¹i/ZOiA\Wb9Üo®Ž†Z{ŸÝÈÚåÛ uá»  ª>MU¸Å]HšJnWµË¶ fA9q¶Í%À»KϾÅ<%6¥Aõ6¥^I3Y¯ÅG‚â,ñýʵdïd˜2[9P—h" ô &¦ñ-S;²ãuý|ñ¬¡ŠO#¿Ëä̪㨋[ãèW!àSN–áM©—-PUn "ùùrô¦m¬Ü$¢m†<êïßpwCdö\Ç~‘9¶\‚>æ¾”Jliò§IæXµ;Àµž^8^N_cJzk×%(ñÍU-0J)5²mMh04~ƒÈÍ’ ]HÇzäÄ0^Æç#3—{¢v á##•ˆaôh™´À4ñÕãE¿Sš®™)º JU%8jåþ7d”fbâ†RÂÇîI)])W­…gÌøF´X¿²k—’iá Æ°l> àKH `/æ <É‘9À5Šä/öÔýI?¾‰ªñŽz[ Þ+UJoDWkhËl ãðŽeG]¢å[ÏGØLÉ]š¨è¹ð4µ'«ßqS´„ -Mçƒék™UÊœ›Bœ  ªE+ÁyÊ¥€ j‘)aÇFXư‡%ص+qûÁë펲P%:ˆ€,˜äLO&o÷çGãh7¹vL&-c¶K|ƒÙ24hŒÌC‹iq4S_<¥PÙrˆ¬E¦Ä 8¯‹€yVr_æý.6Ñeû²©f؆2FFr3}žHáHл9›^£c€Òm˜Œ™&e¶=/Y£iò7ëóÿ)|WJ]ûÅhz÷,d( G íʼn7£…¶ÖF¤Ñ¨Äd—ÁŸµîç×G|â²Øt YL—o(Üq-xV”òH eV²cnÉ2Ñ‹tÓdȶšP)eMÕøCÏÇ'䃗-àÏÒ™÷'ê¶L«";– ­]N,GšiÃv›CÎéáëò…³XßZšd4û7±‹Ãxš}qºHÇz›Þ>øm¥Úô2^À]ÖØÙKꪑÀxÇe qWõù¡J ÔÎ|öÑç E„É|î?|µàíÃØ­ûÉÖ»MÈ^f T  ¤ 3­'ZæÖ@‹AZâóQÅä–^h—M° _>Y•[À3ŒÜ;86KUÀÛÇ ªó1¦ºÈJxúYõ)¤¤1Nž¡#%¦œ‰è‚õ6.Û‰“õ·é¼á f>Ë-pÈrh´£*à«.[ö2Òzá—ïop ™¬ä[¤6Ô1òÊÏ\?/UëR-ƈù+5Q X‹µ•YÕUv+uëu¥Ï\6”2PãK*‰~uhô5fBÿ.FÒèJ Ä4Hc½r%&0پإÈG³MÓñü¯öˆX@Tà²àÎQ©ßYÙa2¥OY UY)ÙPËdÌkïã¯4¾jL¸sV°ÀW’•ð"·†ÆÈ²‹¨Šdr†¹ER:Ò(ÙÎJî­1GôPŽëõz‚ƒPÕV­À̰AH`|£eL¿€¦h47Ûn‘aCeG;ÈÛе÷ìRÎÖ–¹ï®’o3½`%c ”pÎŽªÆÕ.ãEWPíØòÉd<+µ;¦1®j¹íó$hDG ¥¼%›[¦ÌA6¢ v/‚íÖP>YÕՔʫQu¿¿*uÕZd$@ 1d‘eG/©Ô†HÑSH&¶EÊ¢‰˜U#5"Óä£$#g«rJUë‚û å¬ÅßáZ› =R;åœÅ]On ešÈ9Ãvv}¥ØÕ`A#˜À­¡eÕÌ•´·@-Ž€!‹zqËiØZI h ¾‹à‘0±¨7˜²£f#àŽ2A-@ÇrÇô{à %97¸AñùoOŠr‡‰”r|¿ÿ÷2nîžÓ ½){ͬbªq…¿¾¾è[ÚA†ÛßûÖ• ’?RÐr °^¥ªÇez›sˆáF†Ác5¶Oþ9à”Ö¥Q4t8e×Y»£àè缕0½*[zVJ»EsÛ@$Ó»Ò«ÒÇçã(nßùîj OŸ³²>ôÖ#C -6¼6g«le¡ª”'FdJ¹e´tµæ+5]{‰IóA[h[ï³Òô¹´I®¬ê—”–õ+;U-£ [™["ãeþ‰WjIn‚ƒ|åg[%|˜†MËÈªŽ²¡ü1HYÐ>Ér“»,RP¶%8CYUæCãvp£QIÖHóUÛözŸÔ™ôîxXž Ì<}.ÒLäæãÐô¼Ž° Ííë”àÊÏD@‰¸[ÈÆ Lƒà܈U»Ža%±.úI#ˆa—¥ñ2ª½CCwúRô-“¥oJž™3t” ¦“íXlgÕi” M–@fÞžd}ͺ;}ʦÿÌ“”K àIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/main.c0000644000175100017510000000003115232633614024242 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/0000755000175100017510000000000015232633614025316 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt0000644000175100017510000000022515232633614027004 0ustar runnerrunnerFICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/0000755000175100017510000000000015232633614025312 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf0000644000175100017510000000201615232633614026754 0ustar runnerrunner{\rtf1\ansi\ansicpg1252\cocoartf1265 {\fonttbl\f0\fnil\fcharset129 AppleSDGothicNeo-Regular;\f1\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww10800\viewh8400\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural \f0\b\fs24 \cf0 \'c7\'e3\'b1\'b8 \f1 CORPORATION\ \f0 \'bc\'d2\'c7\'c1\'c6\'ae\'bf\'fe\'be\'ee \f1 \f0 \'bf\'b9 \f1 \f0 \'b0\'e8\'be\'e0 \f1\b0 \ \ \f0 \'b4\'e7\'bd\'c5\'c0\'ba \f1 \f0 \'b4\'e7\'bd\'c5\'c0\'cc \f1 \f0 \'c7\'d9\'b9\'ab\'b1\'e2\'b8\'a6 \f1 \f0 \'b8\'b8\'b5\'e9\'b1\'e2 \f1 \f0 \'c0\'a7\'c7\'d8\'c0\'cc \f1 \f0 \'c0\'c0\'bf\'eb \f1 \f0 \'c7\'c1\'b7\'ce\'b1\'d7\'b7\'a5\'c0\'bb \f1 \f0 \'bb\'e7\'bf\'eb\'c7\'cf\'c1\'f6 \f1 \f0 \'be\'ca\'c0\'bb \f1 \f0 \'b0\'cd\'bf\'a1 \f1 \f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 \f1 .\ \ \f0 \'b4\'e7\'bd\'c5\'c0\'ba \f1 QBS \f0 \'b0\'a1 \f1 \f0 \'c3\'d6\'b0\'ed\'b6\'f3\'b0\'ed \f1 \f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 \f1 .}qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/0000755000175100017510000000000015232633614025270 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt0000644000175100017510000000035115232633614026756 0ustar runnerrunner架空CORPORATION ソフトウェア例契約 ã‚ãªãŸã¯æ ¸å…µå™¨ã‚’作るãŸã‚ã«ã€ã“ã®ã‚¢ãƒ—リを使用ã—ãªã„ã“ã¨ã«åŒæ„ã—ã¾ã™ã€‚ ã‚ãªãŸã¯ã€QBSãŒãƒ™ã‚¹ãƒˆã§ã‚ã‚‹ã“ã¨ã«åŒæ„ã™ã‚‹ã‚‚ã®ã¨ã—ã¾ã™ã€‚ qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/0000755000175100017510000000000015232633614025245 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt0000644000175100017510000000024615232633614026736 0ustar runnerrunnerFIKTIVE UNTERNEHMEN SOFTWARE BEISPIEL VEREINBARUNG Sie stimmen zu, dass Sie nicht mit dieser App auf Atomwaffen zu machen. Sie bestätigen, dass Qbs das Beste ist. qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs0000644000175100017510000000362715232633614025545 0ustar runnerrunnerProject { AppleApplicationDiskImage { Depends { name: "myapp" } Depends { name: "ib" } dmg.volumeName: "My Great App" dmg.iconSize: 128 dmg.windowWidth: 640 dmg.windowHeight: 280 files: [ "white.iconset", ] } CppApplication { name: "myapp" targetName: "My Great App" files: ["main.c"] install: true } AppleDiskImage { name: "hellodmg" targetName: "hellodmg-1.0" + (qbs.architecture ? "-" + qbs.architecture : "") dmg.volumeName: "Hello DMG" files: [ "hello.icns", "hello.tif" ] Group { files: ["en_US.lproj/eula.txt"] fileTags: ["dmg.input", "dmg.license.input"] dmg.iconX: 320 dmg.iconY: 240 dmg.licenseLocale: "en_US" } Group { files: ["*.lproj/**"] excludeFiles: ["en_US.lproj/eula.txt"] } } AppleDiskImage { name: "green" dmg.backgroundColor: "green" } AppleDiskImage { name: "german" dmg.defaultLicenseLocale: "de_DE" Group { files: ["*.lproj/**"] } } AppleDiskImage { name: "custom-buttons" Group { files: ["ru_RU.lproj/eula.txt"] dmg.licenseLocale: "sv_SE" // override auto-detected ru_RU with sv_SE dmg.licenseLanguageName: "Swedish, not Russian" dmg.licenseAgreeButtonText: "Of course" dmg.licenseDisagreeButtonText: "Never!" dmg.licensePrintButtonText: "Make Paper" dmg.licenseSaveButtonText: "Make Bits" dmg.licenseInstructionText: "Do please agree to the license!" } Group { files: ["*.lproj/**"] excludeFiles: ["ru_RU.lproj/eula.txt"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/0000755000175100017510000000000015232633614025257 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt0000644000175100017510000000022515232633614026745 0ustar runnerrunnerFICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/0000755000175100017510000000000015232633614025306 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt0000644000175100017510000000517015232633614026747 0ustar runnerrunnerPK¥^C^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPK¥^C \y€ÆN content.xmlíXÏoÛ6¾ï¯0t, Ñ’üS°]`†`C: W†¢mb)H´åìTÙ.íZt-†!‡®Èam ŠlÙþ˜ÅJnûFêWä(r l§¡É|ï{|Ÿ>¾GQÝ^ù^k‰Ãˆ0:ÖL£­µ0EÌ%t6Ö¾¸û‰>ÐnO>±é” ì¸ -|L¹ŽåâÞÑ4r2ïX[„Ôa0"‘C¡#‡#‡˜QNí¤¹2KÄ<åð\æxÅUƒ%v#î«gNÁÕh7„±j°Ä Q«áS¦¼Š<}Ê„ê~9¹ÆbåúåX›s8ÄqlĶÁÂ0‡Ã!H½%aTâ‚Eè¥(ìa™,¦a‚ëcUùIl•]øû8T–rX[Õh9S®ˆå¬A4‡¡rm¤àÍåµ]õåµÝj¬ù¼aM`W8ÓËîÎU-„¾j.‰Ý …$P~Ì ]gŒ•Te@Ö )]«Ýî€l\AÇ[áqH8+p´Ž ‡JÅ™“hgÐñR–iYøRˆ¨!À™»GnãÔ÷vwöÐûð LÞÖ 8¤R™|KÛØG'Ŧ9{¥>…ë.F^4eµ^š[ÙX®ÙXûNZ{wZ;d6çZKÔvô‰wP€÷Mç-1'Þ8Sá“€&²¹.85MžN_>EzÝHù™©åã"QC8 a0/ _"é@Ï¢ö„’. ]­˜¸ ÒƒP”MÈÉUR±‹`Ô Åü,"É…höÐz¥ÓhÐï*AÅ690-Eh·ßm+B‡½W˰{–WËèw»=%¨m˜¡­ívlS:´{jÕ1l»­Æµcô­NÎÔª(Ô8 TÌEÉÊò¿¹§,óFä+á5-£ðJöôº¥+¬]ñ¡+þ]Q¾Pþ]CÜ­½&dn­‰H‘,ƲÇÚ>ó\íšUgH|ò€èáUîU§YëÛ­4·è¥žR~fÜaÞ§u¤O<‹tj•r(u2¹=&®<‘ÚF'ë‘ÜbO¿†°ú½þ­:]ÐxÈûÌ=(R˜É(ýÜ Zé­º¯‰3BîŒHë~Q“Ëç/’G „M.^®¿þi}ô.7Û\ž½=ÿí׋—§ç<\{tùæBœ%ˆ)Íž<8Y?~”ýýû#ùûço’gÇÉ/OÏÏþ¼xr’¼~¹>}"~\œ<\ŸJŒ°'Çï’ׯÖÏOþºÿ࿤r~v\RÙªª˜ñó÷ª’&ß½M¾¿¿þñLh»Á l¬#ØXbÐðoÀäPK¥^CþI¢´¬D styles.xml¥VËnÛ0¼÷+ ÝeZI $‚íÜzjNM?€&)‰¥%HÊrúõ]RS~$z  ÝYîìp9ÎöåT«ÕQ+¡Ù%Ùz“¬DÀ˦Ü%Þ~¦OÉËþÛŠB2‘s`m-—Z÷¡„]aqcó>¹KZÓä@­´yCkasÇrТ‹ò‡V}$¶´<€ãj'Nni±ÇÎjéay玫¹¡ÝÒbEMãò–Ÿ¬J HÔš:yÁâ¤dó¾K*çtNH×uëîq ¦$Ùóó3 Ù‰0›pº5* 8#B ßÌ’l‘[ G—òóؘRÓÖaKC½ºU{,oı¼# «¨Y¼<¿ÞG¾üzy\[SWݹ“'òŠÉðçõ×yL½´—ÇΤbFêÅcöè¸&ª¾  îÃfóôߺûÞ鄉àìS8£ŠMŠC}K4Äe©8ú5MVƒ…Ìlk?zTèOe"å‚)»ßö»5…Wý·×h—¼IT*Yá €Zª1Nö[rïÔ!ÞáØ„‹‚¶j°Ç¡Ñx¤¦†–†ê*ÑS$Õ¥1N¢¥ö)ô<tÊ¥u´ñîºYÿ§4 ÐÊ®ëÍÙhôA+ÿb0{Xo´ ƒÝ`¼dŒà‚Óá+¦Ñ›ä &­ µK(EµEûûïÆ©î¢9Fb8ï»:uP Wy¢­ƒ¯Ç {ù~£ìœžÜ½Æ!Áµéá}Ä 3.ÆðéI )H–Î7FÓR¤Š~@ën·¿¼7d:ɽã<…%™¢•e…Öá ññá(#q!ÀH|MHÉ¿ Æ*](­©)eƒ êqë¢èœóÏô*¡DáÂSœ‡ÍÀ ÄÏ·sÖìZ¤!QãîÓ\º!èOúôæbå®Ä%Wgé\t%·ÿ ÚÿPK¥^C®Ñã¹meta.xmlÍNÃ0„ïXr ãeÅ t†Z뺆½½î7l§n$Ö hÉLº¸0êâ{Õ±Œ6y'H„Ó ݺ".i‘–ŸSoÝGÃŽ1Ž`žçr¾-ÉwÀ뺆<]ÑÖœ¹qò}¦ZØcrÀK+›þ7Tb/#ÑÙ(áKèl·­ª;XÞ¬ø9æª>µv•D•ÌÒ:ô:’WOdH¿<ïß½èoî%üb$\)À_Ý«/PK¥^C0.†eöaMETA-INF/manifest.xml­‘±jÃ0†÷<…z»¥v+Âv q …¶Îà …tN²d¬sˆß¾rÁMJº²éÄßw'åëSçØ‡hƒ/àßC¯ƒ±þPÀ¾yÎa]®ò»ªÞ4»-ë”·-F’ËíöO¯/™u¾n[«‘‡á DÕTìmÉ%¶Ûw`°\qCüš™†òñ§,`¼ *Ú(½ê0JÒ2$— zìГü—óåŠÁ­u˜¥à0],€ÆªŒ¦ P}ï¬V”A½áß.~©à„'‚sw;:—õŠ>  þ%›I"Mü7MO³oÜ’iroŽíÔÍÅÕO–_PK¥^C^Æ2 ''mimetypePK¥^C \y€ÆN Mcontent.xmlPK¥^CþI¢´¬D <styles.xmlPK¥^C®Ñã¹meta.xmlPK¥^C0.†eöaMETA-INF/manifest.xmlPK B qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/0000755000175100017510000000000015232633614025743 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png0000644000175100017510000000123115232633614030615 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png0000644000175100017510000000121115232633614030241 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/0000755000175100017510000000000015232633614025340 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx0000644000175100017510000003006215232633614027146 0ustar runnerrunnerPK!87Žîl¤[Content_Types].xml ¢( ´”MKÃ@†ï‚ÿ!ìU’m=ˆHÓü8jÁ ^×ÝI»¸_ìN¿þ½“´‘’ˆm/dæ}ßg‡ÍŒ&k²Ĥ½+Ù°° œôJ»yÉÞfOù-Ë §„ñJ¶…Ä&ãË‹Ñl e¤v©d ÄpÇy’ °">€£Jå£H¯q΃Ÿbüz0¸áÒ;‡9Öl^ÏFñü¤¢Ü™ø0pzŒÖºi Àîyü…llº"©³¹û´Uâ?Žýýû×ê<üéÒ·‰d}ôù Þ] ÔlÞìØñÿÿPK!Â`šóîN _rels/.rels ¢( ¬’ÍJA €ï‚ï0äÞmél/RèM¤>@˜ÉîîüIµ}{Q±RK'“|ù²\íä^‰‹OÑÀ¼iAQ´Éù8xÞ®gw Š`t8¥HT`Õ]_-ŸhB©Eeô¹¨J‰ÅÀ(’ïµ.v¤€¥I™býé”úäAg´/8^´í­æŸ 莘jã ðÆÍAm™.a§¾÷–’ÝŠr¢Å¯ŒJFH ¼%vÚ}†›Š}Úfq¹Íß“ê@‚µML³ÌµšÅ×Í~ U—Ç.ç„nþs=´ŠŽÜy%ÌùËH]A÷ÿÿPK!Åà§? ¿word/_rels/document.xml.rels ¢( ¬“OKÃ@Åï‚ßa™»Ù¤jé¦zÕ^·›ÉÌšoïRi›b r|o™÷~³«õ·íÄ'j½S%)tÆ—­«¼Ï7 ˆµ+uç*`__­^°Ó‡¨i{1Å‘‚†¹”’LƒVSâ{tñ¥òÁjŽ2Ô²×æC×(iº”aœùY¦Ø” ¦¼Q =þ'ÛWUkðÉ›EÇ*$!sÜŒb¦5²‚ƒ“Ä,—îæDøÂí늑9r?'HåzÛá ãhMA,ç„à8;ØË_3›bÈæd0;boßcÛ‘#IN®lí$ÍbÖå¡Ãñîõ¡^ž}»üÿÿPK!€eÌÁ‹ word/document.xmlÔWMoÛ6¾Ø0tOôaEv„ØEl']€Èæí<Ðm ‘H¤í¦§¢HQ éÐZ`Ý ´Ú-‡+0`(Úeû1‹åÞööR’eÇY·FÄ‘|?>ïCŠ¢7®\ÂÒ€p0ZÓÌUC+Š™Ð^Mûú«í•ªVQ…Œ’š¶O„v¥þé'C×c¸*KA…;ŒqMó¥Œ]]Ø'«Q€9¬+W1‹tÖí˜èCÆ=Ý2L#íÅœa"Ì×Dt€„–ÃEl1´áI×2Œ*ŒZ`œgÄbBÁÙe§nޱRðP9.pQ8 fÅfDóf’Á!™¥´rÉSz:'!fTøA<ÕíCÑÀéO@.,x¦ØalÚË-z‹£!4SÀEè{YRfÌ/F4VDA‹P8;ç„Éìæ~˜43âškï`ÍĽåç*gýxŠ,‡¶C÷ ,u”¼V¾È³¥‰åÈ´}Ãaw§GGÁ’•@õ’ÚÖZޏóöUƒÙvcÄÑŽWÓÊ-{»ÜhZZj•äºTÖJþ« Ç©÷eM3Œõr¥Y­¦é¢~(•§ì8­Êf: O»Y³Í¨@ðÏH ƒR»Yú<èùRù›Tü§‹sV½¾¡вþöÑÉχãF·Ý{¥|2‹HŸñùR­rÃvÊ çò•úæÉé›ßÇÏ_Ÿþyx¦ÎÌöÌ“ÑwÞ¿\@ëµMÇÜ^[o-¥uîI™œ…¯4̪c”×/ÝR&·ŽF÷ï&÷þùã®ê¿¼3>x–üöðôä¯ñƒ£äøyrç[èŒG¯U Ø“§¯’ãŸFŽþ¾ykå+fÙp¬-û#)ïTí­Í¦¥€.—ò§'O åç_¢ Å]>Ïî]Ä‘Fg8ÍØ2:C*£¤BE ܪÛg²á<Í/í9vÆöÔµ®-WÉèm¨I(Šàœÿæ*k ¼—¿¯yìõŠÈÔñÿmðïMß½8“ù]V,w Ñg¶JºÝzíà‚‹‹iYvZ¨ýµª—÷®!•,ܯL; áŠËtØaR²h:IwÆëäXꊕ»ŒÉ™a¯/Óa>f¡ÒJÄ“,&«8+"íf_V}ú/¢þ/ÿÿPK!´æ ó (word/theme/theme1.xmläXKoã6¾è xß•åWì ÎbíØè¡-ŠÄEÏ´DKÚP”@2qòï;R²v׻ɢšƒERßÌ7ÎÊͧ—\g®tVÈ ?(á2*âL& úçvóaF‰6LÆL’/è+×ôÓíÏ?ݰk“òœ—úš-hjLy:‚e¦?%—ðn_¨œ˜ª$ˆ;€Þ\ÃÁ`ä,“”H–ƒÚ;¾gO­ÕIo+ík?Òh» õ`uó¶‚ãÇÐ>ô«^ Ež™XP`Š‹Ã–¿JÓ^,èÿhp{ÔBœ‘mÈmðÏËyøqˆr*ÙÕ‚áf<¿º«õ#@˜>n½^¯Öa­,ŠÀUgK;ÞÌÂe¥³rþîÕ`2·ñ ý£~¾\.'óAn8îágƒéøó°…GNúö/?¯VÓAn8íá7Wóé¸GP*2ùØCÛ|Ö™©!ûBür>ø¬ÚGTÐØ^N^š³›-g_ µf—™LóZ à6˹&¿ó¹/r&-»æ¬pK‘î,Åy&ËQ1Æ òýÎÏ»½Ï„x0¯‚ÿªÑ&]ˆ,ÞÀ"NPªs™ÂÐóµp‰b8&ª0e&}HY š©åû=Ì™•ãÔ¿+ž Wi| ;ñ¤îØm·*øgÚ@ˆ« Ürl´qÖ®|_ÝS×WeÊ|O²%Zyèà8®mÀYüzÖ±ý;]Á’'WšÛøæŠÝ¹\òQl‡Ü#v.h¡LZ@*Ó,Ú(¸9 Ø7ecM"Â~EX[ùó±o9XPY’šû,!*ƒNgRÅùÆûùe¡ïо2¼"ßgjsuéž;þÌÅÖVïÔúOIZuÄu“Öžû`ì[¨ÿÕ›Û6ßz=89ùKÉM¿qÌßfÂ7µ®cõ膓‹Ú’™”ØhܙЄûà´궸‡ìQÝ( lÄîâAl)ºÑlv‹ŽÍªr ?êuLAÍÛ v³8Þ1Øõu©ì¦ûþ`ûQ+ÖÍ}t"ÔA¿DƒÆ— ÎzÿL(v_€ÛÞhô¿ÅVÕW èqŒ(zû7ÿÿPK!ÓNº„0ƒword/settings.xmlœUmOÛ0þ>iÿ¡Ê煼ДQP[Ö Ø´Àp·µðKd;-eÚßÙ‰›n ©_8?ÏÝùÎ÷\zqõÌÙ`C”¦RL‚ä$D`YQ±š‹p ´A¢BL 2 vDW—ïß]lsMŒ7=€BçO‚µ1uE¯ GúDÖD¹”Š#GµŠ8ROMbÉkdhI5»(ãQÐ¥‘“ Q"ïR„œb%µ\’Ëå’bÒýóê˜{Ûk‰N„q7FŠ0¨A ½¦µöÙøÿfrí“lþÖĆ3ï·Mâ#ÚÝJUí#Ž)ÏÔJb¢5 ˆ3_ ýÅÃW‰öwŸÀÝ]‹.„'±³+Ïþ-AúG͎餥ni©juÒµÁq~³R¡’*¡T\‚,_¤äƒm¾ApAI´YPÀ¹& ì@ãqDÖ^H. ƒ Zׄ1'zÌ6b¥¹zÄÅTd‰fPYYûkÎÒ¸¥ñ)„ QE0d›Ka”dÞ¯’÷ÒÌAú &ÓE¸E°V£Éâã-ÚÉÆ0E»dA þ¶8w²"¶ÒFÑã‡a\5‰{‡è°ø TÚߥ4Þ7ŽÏOÏæãq[´e{æt4º>›¾Åô1Ñ>7Ïí¢|SÞZÀ x1G¼T îì*EÖ£TO3*<_Ð9dЦôd¶„戱ŒÁn6<¯¨®¯ÉÒÙì©UŸ·óPo¢0ò/û\VBD}R²©[v«P}#*Ò7‘ ‡]$æ–rë¦,|”5P¨¾n”{§þy¶¹Iû>·È)Àù>v†i3ÕM‚—u8¿·PI+Âs(àSÝÉ‹©Â ‚Ü¡ºnuT®’IÀèjmcàTÁGÙÊUÚq©ãÒ–s„móàÝ=–zìÀïÔc§=6ôذÇ2e=6òØÈbë¬.¬æHÜ›_JÆä–TŸ{þä—SE±ãe¿‹'-Ǩ†«amTžûà¸d˜W߀žÁrx6Ïf³lØÒÙžÎZúÇÂþÓY8M®Óp8Êfá8 g‹tšÌ§ç£lžþìÖÁÿz^þÿÿPK!t?9zÂ(customXml/_rels/item1.xml.rels ¢( ŒÏ±ŠÃ0 àýàÞÁhoœÜPʧK)t;JºGILcËXjiß¾æ¦+tè(‰ÿûQ»½…E]1³§h ©jP >N~ûýjŠÅÆÁ.ÑÀ¶ÝçG{ÄÅJ ñì«¢D60‹¤o­ÙÍ,W”0–ËH9X)cžt²îl'Ô_u½Öù¿Ý“©ƒ|Pý=á;6£w¸#w åE…v §°üd*ª·yB1àÃߪ©Š ºkõÓÝÿÿPK!s³‚æ?(customXml/itemProps1.xml ¢$(  dKkÃ0„ï…þ³wY~áºÁvð£\K ½ y,­‘äR(ýï•É)íi™]v¾™úø¥—è­SdHã"4’&e. ¼¿X‘óÂLb!ƒ ‚cûøPOî0 /œ'‹g: æylà;K«¾Ìº‚uýP²²*JÖ½¤9{ÊOU?ÏÅä?´ 6®«÷ës'¯¨…‹iEŽ3Y-|öÂiž•Ä‘ä¦Ñxž%IÉåðúC/Ðîyn߯8»{¹GÛ¬úGëº`,IsI’ÄÍS£{1àmÍÿ˜îú®tû ÿÿPK!ݸ5Û< þrword/styles.xml¼[Wã8Çß÷œý>yÚ} ¹6ts†ž4,œ†™ÐÛÏŠ­-²•õ…Ë|ú•e'Q(ËqIµW¿>«ßØ¥õô™HÄh»n´øK¿øÌäÉhï`ñÌy݉µç$ËÏñlëÇØîÌÉè¯ÙÖù]ýÔDsOF,ߟÖÛí±5­#ž/5ïz7<:;t®Œ›”Õ¯ò銟x2.õ '£º)ýäëû\¨\§åÉèë×öÉ1OÅ•HžYoÌf"á?g<ûQðdõü—&µÚ'bUeúÿý/{F2Y$¯1Ÿ×‰ª_ÍX=zwu€¬ß]‰Uã&ü¿ Øn;f]ñ3Îj·F»ï¦û(Ä^QXGÛͬÞ»yª¡ýjèà£úüQ ~TCGÕЗjÈ`þŸ ‰,á¯a3€º‰ãp#šã0šãðšã° šãpšãHt4Ç‘ÇhŽ#MœRÅ®,´’}ß‘íýÜÍk„wó’àÇݼøq7Oø~ÜÍó»wótîÇÝ<{ûq7OÖxn³ÕŠ®µÍ²2ØeS¥ÊL•<*ùk8ešeJ^½èñœä 0ÍÌÖ.ÄÁ´˜™Ç›3ĘÔ=/ëª+RÓh*«\W¾¡çÙ3—ºX’h!0çe•;FÄ'§s>å9ÏbN™ØtP)2eU:!ÈÍ9{$cñ,!¾‘dRX&4«ÊYmAÔ)‹sÞ5ÅÈæ‡Q„U ‰Î*)9ëŽ&Å +¼60˜ðÒÀ`Â+ƒ / ,ͨ†¨¥TK#°–F4nM~R[K#·–F4n--|ÜD)Íoï:v‡Ÿ»;—ª>éܱx̘ބ/7í9Óèžåì1góYTŸBîÆÚÇŒmçL%oÑÅš¶$QíëMŠœë£Y> k4*s-yDöZòˆ ¶ä…[ìVo“ë ÚM=3®&e§i iiÇLV͆6Üm¬ ϰ•.E^Ù KÁwõv¶–“bæ[õ2¼c+V¸­ÞÏJ¤Ýk‘½”*~¢™†¯Þæ<×eÙS0éRI©^xBG—¹jrͶüž‘då/ÒùŒÂÔJkˆáKýârutËæÁt/™Èht»ØJ™Ýâêáö&zPóºÌ¬†x¦ÊR¥dÌöLà?~òÉ?i:xª‹àìèhO‰Nع Xd’JˆHz›)2A²†Þoüm¢XžÐÐîsÞ|B¤äDÄ1KçͦƒÀ[z^|ÑóÁnÈðþÍrQŸ¢2Õ Ì:mXT“ÿð8|ª»SÉ™¡ß«Òœ4[]M‡ ß&¬á·FM½<ÔùKp°k¸ðƒ]ÃQì¹dE!œ—P½yT‡»àQoxñ×ò”Tù´’t¸’àH6„JViVP±á°áQ/aÊÁ)9ÃûW.21 ŒJ £’ÁÀ¨400RÂ?¡cÁÂ?¦cÁÂ?«ÓÀˆ¶Œ*ÏH—¢«<Œ*Ï Œ*Ï Œ*Ï Œ*Ïö¿G|:Õ›`º%ÆBR圅¤[h²’§s•³üy!ù##8AÚÐîs5­oPYó!nd}ŽZn¶•È?ù„¬k5‹²_gD™”J[[-8&rý³k›ÂÌ=Á]0'Ûoø3§Ø[0¢Ë ,\6 ¾LY°ðeÊ‚…/S,|™²`áË” ÿüò½d1Ÿ)™ðÜaľŽDã9‹ÛkKàõ sõ7âqVFãÙò•9ÜÙ¹8Ë´¶¹Á®‰âp¯'ì–'¢J…wî6†^ ^ܨÕ¼Úþ®E~ Û<ܹ*íÖ"FÂ6¿ Œ4³ÔZdß$þåO‰pÔ—?ËŽä;êË¢epg³}‰´ŒìJÁ£¾,Z³JtÇõ%.¨Î0ϸ㇙Çq‘›‚±“›2ØWnDŸÁþäÏ¢ÞŽb&MÓÞò#?ï›Û7Kê ™óJ5›Ö®’¿ñZïö³‚GœýáW[×f÷8žn܈ÁóŽ1xr#ÍDÎpÔ”ä¦ ž›ÜˆÁ“”ž­àŠ€›­`³¤øÌV»7bðvÀ@"ÐF Ø)¸(£‚p/£B Ú¨6*D  7`8£ÂxœQa¼Q!ÅǨ‚6*D  h£BÚ¨6ªçÞÞîeTHA"ÐF…´QÍ~1À¨0gTïcTHñ1*¤  h£BÚ¨6*D  (£‚p/£B Ú¨6*D ÚÜëoT3*Œ÷1*¤øRÐF…´Q!mTˆ@"ÐF…”QA¸—Q!mTˆ@"ÐF5—Œ ãqF…ñ>F…£B Ú¨6*D  h£BÚ¨2*÷2*¤  h£BD_~¶×Õ]÷†ìâÏz:o3~éªíÔŸö÷بýá¨E¯Ü¬á7М)õuÞ-»oêa1‘B™SÔŽÏ‚Ø\suµþ÷óþÛÒlzà7…µ7ð˜ ý~04œS9èKy;y}™nG‚]çAßìkG‚eð oÒ5¾\|’J/G ¸oš±‚wá}³µ‡¸o޶á÷ÍÌV à¾ùØ üÕ“óûèÏÇépù¡h@èKG‹pä&ô¥%Ôj1Cc ÍMªž›0TF7¥§ƒÖB+ìFùI m†•ÚߨnVjHð’`ü¥†(o©!ÊOj81b¥†¬Ôþ“³›à%5ÀøK QÞRC”ŸÔp)ÃJ X©!+uà‚ìÄøK QÞRC”ŸÔps‡•°RCVjHð’`ü¥†(o©!ÊOjP%£¥†¬Ô€•¼¤©!Ê[jˆê“ÚœEY“¥°ŽÛ„Y¸Ù ÄMÎV GµdE{VKÁ³Z‚Z-4ÇUK¶hnÂPõÜ„¡2º (=¼°nZa7ÊOj\µÔ%µ¿QݬԸjÉ)5®Zê•W-õJ«–ÜR㪥.©qÕR—Ôþ“³›à%5®Zê•W-õJ«–ÜR㪥.©qÕR—Ô¸j©KêÀÙ‰ñ—W-õJ«–ÜR㪥.©qÕR—Ô¸j©Kj\µä”W-õJ«–z¥ÆUKn©qÕR—Ô¸j©Kj\µÔ%5®ZrJ«–z¥ÆUK½R㪥["¾·lœ²¼Œ<¾äpûeí×ÌêÌOñé÷—šV¡½u#OÒ|¡o 4o¼N–¿:V×݉Ú_bkŸ6½n/d6-š@ØT<ÓmÅíW‘9šj¿Rxy{‘ùBá÷ ;¾wØtd%ÍâÝí¸®Æ«yßÚhõö»¬S¡§Ï&UzǨÉ&W¿¶öØÔCÝŸ‰l~«Oÿs%ðÒþú[ÓÓä•5(ýú9—ò–5ïVs÷[%Ÿ–Í«»;æÖÞw¯Oš/StÆçfs¶×;Ó‹„‰ÍEã4±tKl¹Xó%à‚¬!pÉÇ0µƒ”R J»qu/C Lð8Ïr|b8íÏôo¤Vaoá,zlôΫlÛ6kG=óçø}úüÒ¯š*ÓÝJbÝ}jîÃ4žr¡@ÞïÙ_C2ƒàšM ¾Ä‰nÈÁVuÁŠžÊò°x™ÄDô+ÿ±ó6zxœO+H~›’딌æäŠ7”ÿš? õ!À¿GëÿüìÿÿPK!ƒØóÞ‘¥(customXml/item1.xml ¢$(  D˱ Â0€áW ·Ûk ‘$ NJE×#=ÚBs)I}{­‹óÿýº}ùE=9¦9ˆª(A±¸0Ì2¸]O»¨”IZ‚°7'h­öœI}WI¦œ×#br{J­ëÂ… ]p°.Ë7?P&°zdáH9DÛm½ï—ó=Ι#Vu³×øú÷ÙÿÿPK!¶ÛBioword/fontTable.xml¼“ÝnÓ0Çï‘xË÷kœ4-Y´tÚÆ*PÀuÆÂ‘í4ô¸ä=xÞf¼ŽtÓÚUT$ŠäüÏñÏçŸsqùMp°¡Ú0% Tµbr]À/‹ùY±X®0W’pK ¼œ½~uÑæ¥’Ö·_š\VÖÖyRQÍHÕT:c©´ÀÖýêu$°þÚÔgD‰[¶dœÙm” 4…=F¿„¢Ê’úV‘FPiýþHSîˆJšŠÕf µ/¡µJ¯j­5Æå,xà Ìä§{ ÁˆVF•vä’é#ò(·=F~%ø=`r ÙÉ߯¥ÒxÉ]ñ]$ÀÁଯ>hs‰…3,˜ |¤-ø¤–Þ¡ÆR;Ÿ æD‰{§hŒ&(u_âV)Œ:GRamh Ž(È%Œo7V½f–Tƒ¼Ášu±“akghÌð!”\ÝÎaPâÞ8åM–ƽ’tGùç¼WÆ;u ñÿÏ=‡xÎÎÇ…Bìä÷Ïïw¿~ø:†ñ}zI–͇ЦOÿ’^Ú9—Þ;Ê,ŸoÀ¶®ìÁë>ð¼îÃõо¼A*»Ð ]lkº_ -qÃíó±ò µŒà ó„]‰’ÐMáÚ&¨ëÊÉõ^WùLWžÙ•W.,þÄp^»áLý†÷? çÃ2ôÃ9ôói‡³_˜ÙÿÿPK!÷òfvçword/webSettings.xml”ÑÁJÄ0à»à;”Ü·i)mA¼x©>@6¶a“LÈd·îÛ;ÔuE¼¬·„d>þá¯7ÎfGˆdÐ7¢Ì ‘ר?6âým»z%å{eÑC#N@bÓÞÞÔs5ø'e¬xªœnÄ”R¨¤$=S”cÏF§_ã(ŠûCXitA%³3Ö¤“\Ń83ñ‡ÁhxF}pàÓ2/#XÑÓd}kó5ÚŒ±5ñ>Î~yNaÊ»?3:"ár^æœh¡x¼,–“³?Àýÿ€õpºz=Fµ³\'É-wÐã+¦Ná‰:nak,ȶ–¿êi?ÿÿPK!~bÅÚj·docProps/app.xml ¢( œRMKÄ0½ þ‡Ò»›®ßÊlDñ "lÕsH¦m0MB2ŠûïZ·V¼™ÓÌ{É›÷†ÀÅGïŠwLÙ¿*—‹ª,Ðë`¬oWåS}³wZ™”7Ê«rƒ¹¼»;ð˜BÄDsÁ>¯ÊŽ(ž ‘u‡½Ê ¦=3MH½"nS+BÓX×A¿õèIìWÕ±ÀBoÐìÅI°Ïßé¿¢&èÁ_~®7‘õ$ÔØG§åÃðÒ-L Ä„BH¹Úö(+†§U‹Y.AŒ¼„d²<1pÕ©¤4ñþäáˆY —1:«ñbå½Õ)äÐPq¯´õrW æ·€C¬Q¿%K›ÁǼ…;ëG'cÁÎ’j“ŠÝ·½©ƒµV¯8¾l”ËâT^óS¬Ãõû›ÿ Î2½XêÖQižwx6O7#`Í(ö:›¸åõ'7Èó[ߢÙÞùK ûzÿ¡\-*>_ÛÙbœqú òÿÿPK-!87Žîl¤[Content_Types].xmlPK-!Â`šóîN ¥_rels/.relsPK-!Åà§? ¿Äword/_rels/document.xml.relsPK-!€eÌÁ‹  word/document.xmlPK-!´æ ó (À word/theme/theme1.xmlPK-!ÓNº„0ƒÿword/settings.xmlPK-!t?9zÂ(^customXml/_rels/item1.xml.relsPK-!s³‚æ?dcustomXml/itemProps1.xmlPK-!ݸ5Û< þr¨word/styles.xmlPK-!rßòW;b#docProps/core.xmlPK-!ƒØóÞ‘¥ƒ%customXml/item1.xmlPK-!¶ÛBiom&word/fontTable.xmlPK-!÷òfvç²(word/webSettings.xmlPK-!~bÅÚj·è)docProps/app.xmlPK”ˆ,qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/0000755000175100017510000000000015232633614025303 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt0000644000175100017510000000027015232633614026771 0ustar runnerrunnerSOCIÉTÉ FICTIONNEL EXEMPLE D'ACCORD DU LOGICIEL Vous vous engagez à ne pas utiliser cette application pour fabriquer des armes nucléaires. Vous acceptez que Qbs est le meilleur. qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/0000755000175100017510000000000015232633614025341 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt0000644000175100017510000000022515232633614027027 0ustar runnerrunnerFICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif0000644000175100017510000323466615232633614025013 0ustar runnerrunnerII*œ+ €6àOØ û„?!@XcúbPGè-}Ä€1`49ýHcQˆðM#„?åQ /…?%Où0[3}Nb“XÔr^ŒKb‘éœüG|Òf³9¬ò5¦ÔjQ©œB5«Á'ó:äªkV‰F&±@M–’ù£ç/©¦)[•U%PÀ,bg(}Å%²ÙŒ¶‰*´Æžø;¤z[˜Ó$Ó;£Û§Sò@mÅQŽF-qËûÿ'©Wk“YþGARÅÊ£ÒY5€?Îë³±ˆ #m«‡Mc“‰Í¦=1ˆD#«¤Ö϶>9XXuÞ%®ˆMu€öºgÒêk•Œ• kxf1HäÆC‡dôXx— ?˜Øà–œ¸ÓÎòŸ[¥eú³ Öˆ1)[‚4‰‚ˆ-é{¦Ÿ£Hóôì€ RšÉ¾éRì•'è„:ƒ#KZ<Š? <+NÂ^µqjÖŒ7Èré+É:&‚Aézðº@àbá¢P‚$ØÄ “"Š,àl”ý&kJÖº&,š<¹3Ê„lº)3:ÿ#P¢(Ù=23P¦´HÔ²ê7⵨2Öä,îšè¸ë£{¥‰ b˜¬ Ié?Ï©ŠÖž¢Í‚Êh“ôæÊú 2È)zΊ.‹ò:*MÛTæÓm[üŸ§òŸ€KZv¨¸ˆe ÜRðrî)éšø…'ë¢I0µô’”“;Ȫ,™£:j÷H£jÛ" ìJ‰BÓ=Y%í jLÒ(V:¨5¥*€,ŒÀ/I nYuÈ Œ‹¯C€Oì¬ÔKè:^Â5Ät»WAú©@•¥¢“Uo:µ]÷©ü˜Ñ‰‹ÂCjäcr%RŠÃ5ÕQZszR ZŒ?X\ïBÕ;P¢ßàêä-i›!-736„$ DÞUêÒøÍ ”®hc6‹Q6½Ù’gžŒéqj2V Þ—ÂÔtSN[‘ú›ÃHCè„LùR-E¡ˆ‚ÎÎ]‹êBø!UZµ¦«Üô…hHÎîIâ4Z\Ô}ãÌ<ä?P¢]tjLŽOç§3¸’žëZlŒÇ2r)3Æ‚%µª´Ïj ´}§jÁ»¥\G³{lµÕr¦í|‡&ª C±¢Ì¨†ÈVîXYÓJ ò"Û¼ï…ÝXŠš¹G Ø Û0¥ôve:ˆ-yyö´öºå­d·Ö¶}¿ˆdïÌÁGåB”Ú‚»J!‘5ÐçI}Ãé÷õH -âgÚèYØyÇ6ÏP¿5öI˜y“Xkù6ñø÷GÚyŽÚ9‚BT‹¢À{Èø…5ˆ üËJ=&¯d¼åÜeQNïIoºñúOÛ#À[GhŠ=&‚ì‰i5°íR>·ÈI“cL0V€@KÈŽÄÌD×3 ¯èš¶ö» q‚0l œ³¬Ñú-$þtˆÞÈû‡$™û³2T HR4+‰R ÀCÔ´Ð,sFñ5”Òè5$Pt ‘6ÖÎKâRt9ü„-ç¢B“ê¦vœ8¸õØ k®Ò6òrßGºåž´îÌÚ”rnDpŠ*$é!JŠgqÊÊ"ÐYå¤_~h˜ˆBænç׳–!d2Dp•Óàb|~œ‚sEÔ„Jª›jlY/W¶@鯣ðýâõxwù{Å2$Êî­Ð½S„íYée dÝ’îõ+…-2Ñ4 ÃD:6²u›Ìy%rw€i´Æm´¯~ÝÞ¨#{š¢N'.¥‹È|ÑtªÅ%g¦­{°µ !V „b³qx¥Êƒ­‘¢fb|@v¯&O…—%¾cd`ö¶#¤8´¡6KlŽ_¡„¿<ÓæQâQt´Ñ*&€âÎ3þŠÃàµÛ"n3û™NØ—TìªÌ“ãI¥;“W¸ïÛ»[•©:Õ+ê'î7¤Z}M«pqûV|{†=¼üŒôœ´÷Hí6äG°I˼*iŸUŽžT|úyÙk+Ê?ÝPjQôµ“=TCTØEIþ^«¿§„{`ÄPksT¹tNDt×{»& ÉÉaiRJR"1-‘zó¾Ñ ‘RØYåO¥Ÿ¥K ²¤çé]QNR¦õ¸•&Gª–O×>ƒ¡‘*NçBËÚçBÇz?N\Æè¾ð:tÌ~ï.þYêJV|‹Ë3¬x¨fZ 6AnÞê8¾(@)’X…¨°,ˆ¢|ˆð8+ƒ¦U]î´ìDdE:ppUÆ ÚöçH­Ç*Dì2ˆÍÌ¥¯ò+©(‚Üì ·ë^ªDȪD2h$"Ü,¯Âh,‹.¦úム&¨2bZÁÏþÍÀ,ëš²Àšh”jPjKÂðh±(êÞpöÊàE Œ‚’÷ÊzÅœjçn)" aì7 lnnH”Læòjè®Ðô"»¸ÂÅz’ŒþÉŽÄqÉN0š†1,\Oì',¶ÛBšÓôs„®B‹- 1ÊÐv¨²¯ÇrŽ.ú“NÀùfò„¨ij„¤ï¢Ÿ‚r?B9åÞ¹ŒE„¨±"-+ÄTJ€8,1EÌXL~`-Ì«ÑÖ‚ÖO¨”ýé6+ƒô–Ðå°&mô‚Dì åúf ¢#†Œr×Áîï'œô¬,2*¨M,Jþ_J´¶§¢8—P®F%Of¼Ñ4,‘Jëtoh±4<ó(bò=QÈ•R0tÈN/ÎïLÖ«M1â’.ê…ÉÈ*+p&¨•%à $Oð@ôèÉ *2)48œ²Õ;d€ÆäËÈ…: áOhÐD.Öh}F˧L'(fbÓ%´JŒ ¶Õ‚(è<»Î~qú$2ZÆ#R6öLCP mJ@ñ#úŸçIOæï STh'´&c°©Ô]êzlQÞ"Éþ¯€ ÁÌà–MÐ'ÆG­ÈjÃ\~ôNšˆ6{F¤Ugà·brÕ ô]ó¸0n†"GýêÞ2#:ñcÂò ‘áA6c#%d¶]„L´È=XèÀc3O3åš¡&_V˜²êz'õZˆ¬—4ÿfQ+C1Œì64“491R×`¬¨G®g«£5Q6)+~äæ¼‚gLÂÉOì øƒ(6kk)K%,ZƒÔ”örØS§IˆŒ ™T¦ÅÖ²\±Òø jM{Cì¦'6ṟð%§#‰ÿÖv)¢ÎÚªõg¿,ˆo2_O™DébÏ¡% *6Æ—FjéfEuumKÉHmÌ‚d\·m2ÊzØTbò.,¨\£ª±M‚ÞäîÆçz™LŠÏëq&æ—7f€!ËlŠC‘$LþUËT/A±ÙÎrwês? þì.d«žEö©6±r%õjÅÀá1mk2»zº° ÌÁ0 X€Ó*jF‚±%Ëü¦ÕGƒƒêz%¤ì0g\üè RÇœ‘Ê]5 ½@)[Õ9,"TãÃD5ÈbLjª9QËW,Ê­ àLö3+OtÜ÷kФ¤ü!’2,¨¥+ˆ­0šøÈú[¨ÎQ´BŠ.hˆûhㆄð’µ2Tä“S$×"ÀÐ3CG¥<ƒ$Á‹¢ü1µuÔÔa¶º Žìñòÿ—ëP¦ ózáüÙXûcÂ,ò„[‹fÌEV*^{b@äïu1ðîél–b».˜y]îjMä`Ñp&¨§*z´ÆwEà `ÇIeiC>L1«_LþÉËë‹b'1M8ÇÒQ…·db_;íï}« ÖjûÄZ\uþ²æôZÒÞ‚Kzâ ^Aî¯è $Pñ…Œ2,à`ÊER.¹µ“–h'ÇXï,‚2Tþ4Q"„îw®…Láù‚6lV ênôÌO3-o‚f‰K¡ÂÊÊ‹9) z±"~½¢ H°í«£œŠÇ'ÔEFsßXfJ– Ã!b0>¦>¤M3>ÕO¡OåWy%Xaö£€´úvS [eƧ+Ø6ØJ¤·ö™IN¶¢rò„(‹"$êš«obòþ½ HÈîî»lµ–ê`¸Ó3n.þvP+ù\(ƒ_Íx!6.ƒÂ²è‰ %Ù$V%E:¥¤¨dX$~9_'Xí¨ØZ· ˆæ)*–»û=Y;vp ‡—\§*ãt…Aq?é®ÈøˆþWW‹Éw¸-~ÉǨ™ ŽúöLôó¦©-í4FA››?¨´Í '±J ¤'68 Û:G»Ì¼NåvRãæ—ž,©|ðݸÆ+­ø´ÏÈŒ(îwx2dé.ÁîTˆ(ƒuq~î7 t@ §C;x¸“%1|Ó®ÿb9,£í±Ws"#Ùô3Qˆ‰ Gý¬VÓ¯´‹Aî°yq9™I¦hÆìõJQ\]óç©h|Âa¬iDq-ªÅ—t§ÕV$6h,á”qÖP¥£:N“†ÏLàjUŠX§ç¤(˜ –Ñ«µO°$[ÅgèdMÈ|cý,RFT“ð\=‰…pN†—>uAGk©{Cm*€ œmãE4©‡“îÀŽNòG¥aZU”ˆômuGÓ­ðºr01ÑŠYÐW’²dJE}FöG ”ÖfÞÄö”\=`ïÏ> à 2sºøWÆ"rnü#~Y‡•Ÿh¢6x»³ñ Èæ¬óÊSk.…ƤÄÏG„[ܽO4aòÀ²Ul©³+!Eße¬ÍÚËâ9FÊDÎùK›ûé™Çepد˚;³ÆrOV°Sa¬žhŒõTƨ#Ýp¢\öN¦#ìmºv–>íÔŒåPc:aeV”®äÄ›y$g  ‹Ñ›É–Ïæ‰å¦TGd~艔$Ý“Ã\•Ûš±‹Zõó»V³`Öm·Ëh+´U!u%L)a‹ü¥¥{m˜|1Äzúƒm÷a‡s¶pêŠFå©B©t<ä¶.íŠ\ȧ d³‘«o@· –iË=-f•¢ó+§V© ¬g´>XŠE†jr€‡oò¼TÁØ29ÊroföTZüH$‡È¬B’éh%hi»'&t…Wn ô|ÿSšÂ½ú©U@:bÓ8VöŒ·wþ)o³"¬\ù¡úõÐÓï,c,ô'‡¼x)è †hpÍÆô¢ˆEWÛ…ÏV¦öjÉ('õt\T™bé8 Àh%òŒ­ö‚î­ŒTöå½}ØeÍS5Q—w½À"ö™\‘Ä+ÖQ  PnÌE¿£4õ ך"Ó•œñ=Æ .µÆ Iæ+íµ/Ô I‹«‘׊×"ãͳ‘ýžã•j·YÙ<Ê­ Ïu´jÖb,‰^c[²Ë6 o}[3ú¬jEîæä°@ú‚Júl\×\>³êÝÊ"¼‡ä%¬3µGT©Ì?Ô+‘j?5K`ËPqÖ}»=u(–£á.ØLx Ø ÿÁÀ˜ ü‡AÀ¯¸)Eá +üGã 8“îCÈaÏÈ` ñ-KãïàDÍí5™‚%r×Ä\ùŸKÀÓD:W&ŒÊeozTÞSž@äÓ,R”÷ˆJæ1¹5n(ú¯O$ÑhÄ&KŒÆdrhÜ!ןQ™4†G1˜‚¯Þ‡*†Fãw(¥f g„É¥sÉ) OŸ8ˆdÆ3o¯^Whüó!†HsÓ™l†!)žfŸÑ¹\¦¹[ÇKð9핟[³bá4Èv¡¹½ªÄ YæªÐBkùº;+©€mp8éÅ-°]F¢CÇü\¦ægP-(ÜÇ$ŒÄ$ÒŸdRWÆŽÕnqèÿeÿð뫃€"Ëì³È2§c¸€Ä:‹:Òì íÀÃk ¡#® þ•£/˜½¦h€ñ3h»Â¡Pò>ŒÄnB 0ˆãšçO\d„«JâV¤i z»A,4) €î šžÈ‚ú˜´¨rnÈ%2\\þ ê‚Ì„¿À «!;Oܸ%p"¸1“*Q²(Ø€øçµ \–ü>ˆjÉpk‡PsÛ.ºs‰4Â$ÆFhc &2BÎú I9¥iv5©LIC˜ÂŒój²#«Tµ¶“ಀ.Ú>¸4ñð•® B›ÉóKd C+b蟪Dâªèc öËJ:Ús}sSD°TÈ»¶áëo&5Áý§”Ò =è:xŒÙÒ ¸5°¥8‰Lº.ºÔsü7hŸ‰½¼zÚ`JLÈF€)Öriþ‘³ *Û3ÑÄ:~¤Ö áOËÀ*Ö¹7PÆ®uDa)2tÌ2Qöô0Õí1GU`ŸRSIÁè,±AÇõê(³®“£¹£–‚Ðéä—P2#»S«’4B§"êª6›à–=[WL;m 3DÌ~á³4.xÏ$-Z‰ÐD€"|–§I¼´ç iN¸%l„–“rGì£f¨wž«Ïl)S)»ºÿ£ Yò€¨×)¿Mú˜D¶Lxá"þvsAÃk‡ J©*Zf•ßÔ` ¾ëûb;b ZU­WâÑJ`Í’DD”:` oe ‘ ‘VÒlO£ñ ,ÇÄ?ß ­‡‡­“õÇóNiÍ9žÒR„ Pÿ'G´•澄ÇSÉÌ ;óŠ@‚Z.„I•™ò:J\ûhm<‘•ÔBMC¢6ì¾6¸ôΓ"5°Y%À`ÉIl*®ØŽ®öxøHÛÆkb!òö” K2A<ÈÌÑù;Ç= :W`€ ñ<-Ùràë lAWN¾³ P„yŽ*Í9øj>Øä'U„P‘”òHbª>D|Ì(u ÊóýÐ]‚±„µ'Ô|k)È‚¡F|w‘)p&$Ü…¬¤ ›ÙºˆAƒ 5ŒùžÜ]Åx˜¤·2 ÑÞs¥œž7ó*̹x•à :Ì×ÂLM3Œ2¤u9ª™L?àÄÍ#.ÈÑÔüAMèÜ*°¾_ùؘ’sp(„ç¤dêý‡¯(ÁbVMßK©pNr9•Ê?æ‘»g‰e†Yhýo ‡ÜÜ"û”&Ö¸Ñl§?ìZ'À)pDiom¢F±þkI !` Q‘x°‰‹š—£ê0¡ºVǨ%‚. ~3D)PXÃz0EÞS¹°Væ9 *ªÍ5õàÐdáä €4úP ãU ©- 1%J 1#j`âgò?¡Ü|´¦l­`Á lÅ•ÄΖŠé4>Jƒñ¥ÂFR´j6JnŠ€ZÇ«€ŒÔ_¡µÙέ2±lƒÈ–µGÌ‹YJ–޶DÍ"âû‚ÓÉXCÕ#òF±·ÒƒCÉ1ƒÒù‚ÄA$²x=3Ôúq`Ï[d ›d}0 rDá](d«ÕBI‹$9´àk¯ ÄC¤'¦ECû‰¬š7 ²”­°®•QCB‘0è‰Çs‘@g`Š{?¸Å*ˆo‹<†÷|}Ác[ cõd¸*T¾ãÕìD—;£"ö< ¾Gñ?Î`à¬×¼´r£³‡º‰è0ò¸%Ý!ƒË“0÷gðúÒÍ–èßÁôò™!\•:‚8Gþ{ÉÊkíp·ŠÒHö ˆ“{ê{±Q:D)/î­Ž ´Òðßd2ŸŽÇÁ@°fDÿšÒ!Ñít»Ê¼áríi­2Å~Z‚àqgÆ0"YIÙ1j©ÊKí×.í™ZmŒmÙ‘u¡d ÍëòB6üS¸&{¥~;dë¸ñgké·*bûB4&›0Ž|ž\†C™gÌrËR&UM&qš–Ìc¿U9jAV˜.n)Œ º³YƒB暤W%VO9]A'32 ´+}Ψd~¾dCŒCÍþ«uׄvºûË®ÚÌ5þ¦ÒFFíšQ¡¾¼ö{çÖDŠ®¬ÅJ |6´HɼÿD̪®€ï0# a­? °c£ŽzœµiDú¦+̈바XŽŒ€€| 3Ðz #±™m8 *ôk^€”À!Œ'kó#ú ;b§®cÁ3x•оµá ±æ¥Šá‹'£ò-rˆ²ªš¨ø’.)à óº0ØŒ½¨Éˆû,€S«©(Û0°—¸ €›¾²)ˆƒ:(*¯—±9±À¡;5ø˜¯H¨šb¹ø†;Bz"D"ºe€Q`JÜ jû 2wº‘ #!P €ÈT3é‘'´ªÀÌ"`®3‹¿€#‹‰kUÁ:˜IÍÌr`'9å‡ÐþŠê+`Š4y-#‰Aâ‚™£À ÉX›ñe/É­„4ør CÚû=c9$ú딨þK£¹ã7 ±Í¾û`8¢>•“óšÓ›³cLú½óЮ2ÊDÊåj.ÅÔ4˜Ê» ð¾:Šªœ›0±sÔ"á-±Ž*ù ämrÏÇ+í¡[­¹ ˆ¡½¦§5äKBj½Ÿ`{‹ì?: .ËÑIí@,S¾ãXÈØ"Rf½3¸¤ÉF¿q`Ç„І9ÿô$¤ ½.*•xï ª«žK󾋛½Ø‰ºz°¤ó0X——ó¡‰Ó‡="þˆ9@Œ`þ xz¬‰zµ¨›ï 1SËØ;ò;zd6¢Ð(š 7p}¥¡x¾¢FR BâFÐÆ.¿œP}:Ôô©ɎóiÁ ›Šªz+Kß¾Û¦Û«ÛK½l Ô6?zî,ŠÛ‰X¡2š»a)#+¼Îª+ÏF饼‘‘ áå&,Ì{ÉäÞ˜’åJ›h“q¾À’੉C†Ôú ԽˑŒH‹ÇZ‚΢G˜¹9‘8,‹7²‰¨‹qŸ ".lq!AÇ òQM‹ Kó“¸Í$ã',ɱ.âeÓ<8ŒÆ¶Òɯ4T¬œñ>LÀÄ‚ÏÅ›'"‚b›š®TÛ»Ô ´@l >ÕÁ|VA ¿.AO;샢?+]™ŸP#Så6¦a¡Ôm‘­+’l™¡è,vX” -8q ¼µ$­s·Ð‰#­|ÐdÜ€1ª¡`˜’è%„J s¸êÉãkLN¯™:ÎQ)lºÓÒž±dOµ#`ŽœÈ"‚Ö%sʾNBø˜L­_Z‚¿²l”8•Ébz…ÂMššüÄ7š‘Ò=sÀ5|ý£!d-.;dÏÇ¡Œä‡_Ó¨LdJ¶ÅÏQ"¿‡¼û˜JIh ê-²í¸¨‹„û‰Ó¡‰ ZŽîF_ôkRø„ÓuY‰n&¢9COjè8ÐùÝ4”õ Tõ™ä…ZSM¼Áš f·ö6€4Žf…{KzM`]_‹€Õô®»¿( öB+Qâ ¦ð|#ueߘ~OºàšÏŸ ¨žV«£¾v‚Á,\/œX¼jÏXÿé$Y¶Ü÷¡ôd0òõÞú9Ókâ¦=凩óè³&!°Êª:y`¹§àåsã%tG½B ³b¸ÐÍgáX«qÌ‘Sh»ÑÍ9Ä5„éXÜÀ@a½|øÍc8€”k¨]‰ŒÑá`QC˜ÝMÑÅejÎ-•5¤Ã3ØÞtöEÈ»V,<Åõµ2=Å ¸:#_ωÕrÖ ëèÓ)°$æ“ü$v!>’v½þ€(DÞ‰!ÙŽ’à®B >¹À¨ h c5"Þ'å塸ա6 ùŒ @ eӸե̛{öÛÑÀäs±¾cNdŠžWý»Œ‘°Ù‚ZÝ\V–MÏãê6âá-äÍší‡aÄà Ô-OZ³Le4ÚJÅç¨~‰¼ †ÌÚÀ’Y'²l…–= ¤m4öÄZí£p ~ˆëÞf–nÍwÕ,9Ï1b˜ä&¿ÚKQjÛíÝ\骡ÝSvDån½~ žãŽ”kFIK€pbêünïœé¨ìþ•ãQ&ØTmâEíæ- %dËKØâ«ïïFSÓ“­D×>3U¯ %WÁžJû ›Ý=g/Ú¬\z|¹!íµ^]bçœbd…›¤Í Ñ '¦çÀiS:yŽJÛV§Ç2äg!i“Ú~í=½EPÃÜÏn€|µa6÷!¸•ÿˆº.4ºÛN»Ó)Éœ^îoVâI‚fæýtÑdRäsd°þBX¯q¼¬wÚDìH Rhy“ϲw ³j¼á«qi5¼R¢;€ÀQÞš:ÇNˆ¸åc§›ßœª7òfÀXw¡6„1‡ßîê´ìÖ>Cµ*ûîˆâ‚? À(D$ Ã_Ðø„%ûE@qwÜdŽD!`¸?…Çañ—ØU –Kc˜¨ ü˜Ä$38üMû*½gÓÔpCˆ@Ÿ0D²u˜Ê!2ÈärY ˆTá©äê3™ÁÑÉœ†C(מözõv ²Bép¹ŒÍõs«B@Ué æõZ„Gãó9G–LoOšDη–Lð±[Pt ÊNbqÉÐ5:¶€a5(nU†Ï#–w¼B½^Ð?ãñǶij”_XܶŸÎ¢5"!šÄ4šèd:^”R3»§ü¾,Û#;À׌þŽHxð–·†Y!ÌDä5 ·E‚èK7ñ¹Œ†ŸêJ+×ügÓ±T‡Ä¢ˆ«|í¼hº8×£kòJÁ=à>Ã¥‰ã´AÈkœŒ·̉½È|¼§êæ}'"6â% ¬ A-·»¨»ø: šl‹¤pã’¼ïiþÅ:m*T$1¹ý¯Nªú¸"°û¶&(úQñLRì8ðëZõ½'û©Ùüÿ²1ò² ŠrŽ'Š4c- â¸üŸêò Û>gúPùI+òM>‘KÑH°CÝÇçúc;Ç˺ ƒ;È{b{6`R¦)cj‰Ä3ÓnÈ ÐüÔ•MÊT4†Å*5'@ΨšH¿;zT™Ï«Š ¥‘ [@TÈ]+WŠº'6ÀõøˆFˆ|Àâv]"âNñ zË(ÚQ ºˆZ"„"ø‘¨œXŽƒ¤&vu€~Ô‰Ñú±"éãUݱ…¯1³”bÇ€Š ·Ö‡åsÅà þðBÃÅ-lv¡QÌCK¡´Jh]7,4W¹øá©ÒXâS‡ŽHäÔïm!ñ$T¶Ò‚2«ÉñêÊ1£C°©÷~M¾þ¡»Wi}¤tÍÙ'¡i}>®´ bü&”ñøŽ_ñD@ã8Ûu£9 –+ÙôòŒ#.# £ëH­òú@°EZÇ:…Jè¾ÉûÔnS¹!òÜ·€-eû¦s@ân{&BÎkZ8Ÿ–»=¡ÉhÜ›€n…„õálÛ,7u?oO]åÌE(†q½€˜2”#—@¦iÜ„¸‡§œf¦8˜°†Ü­lïѪ3¼šè4ï®Ø×8‡ñõjQ§‘-Á{õ†¨Îb3¶õie¸ãn8tö–aH]–Þ>´¶ŽRqßà‰g}Åèì. šÈ6t넃§·lø]¢ØhKÁ‘2¼¤Y³VCåà‹®Â&®‡û†aí*¿æ&ßÁ¨.°}NAõãá pªh¹­dà’q|Î<Ë.£tÀßACc‹‘-¹†¼±¢93Œ¥â¯Bì§YbPt‰¸Ä.hˆú!yÆiÏ€–Šy|ÌeŽ=µñ ²RI@*ÃÒøc *[ Ÿ(´á`€þ€îYIœCPvùÄLDˆÄBµI‹|P,1¤¢ØB؉"ñX…¢b2ÁÀ Œ^DñŽBÙàÜŒ.n¡Ž'H¡0å!Ã2öLTŠå“–7¹äNnž˜LyuŸ.\‹šfÑ~âtW‘ 6‘Fjc€U ác–­¤±@#öB%š:"ò¨ì1Hàeãd¥qŽ`ãœBbjÄålO™ã&è:Ô:™ˆ@ŠœEŽàfkV”GèAˆÀézvæjZÆ÷Ž–æcž#‡Ø‚!ö>yˆ¼ò Ѿ7ÐR¹ÌÓ¨O¦¡r¡xžè`ùÐH’ÞRÆ‘ôMè|wh.a¹@Õj†.Ójs¢¹U ÓÛurä6&JTÁ& ÇmàÌPæ®L›³.X*‘·´J¢êc˜2äŠÅ”p‡ˆÚÞ‹Ñ–-9š›˜Ê1ˆãíð†ÂC4¬`»‰çO]ƶebb÷fm lfÀØ”„¦BçœTEm|—™üì¡Êwi}©Ré(À@ ›‰J."»Æ0BÌ:“5ÍŽÌ91 šÖnOT/ ËiûnfKTîãÓìf/ÎNIWžv-)Éå.½êŒ=!µ,œBSQŒO_ìØˆ.$½œ–,ñ½;¯ömIŽ QlÎÆfMMlEÕ>¸÷ÖÃXj0Åéþ£²LÙ®„'…·Ìm cDÁ@')¢]R£Qv¯³±ôó:q5å+’4Q½Ýó4LyÍD„꦳-ì1Z'i¼ò¥Ó´1'„|nö’Pä¶Õ[Úo²•°'ë½öˆ$%d‰Ú!óÊL0ºnóP­B2ˆkÖ‚Åw±å'Õ9 j0ý)˜9.nB#óÝHâÕ:„¹m] q‰‹èJšô‹²ò¢ !£¿Ôä³Q)%W³TôÄz§çbÑÄ»ëE«ÙÁ½™\ë‡Þ ½JÏóm?Õ¹·®†fŒ=?¶«—¶'³°QüH°Cä„Ï | ªÔµjÞZɻϽᾎ¬¾ìé‚ö1 £ÄV†DãˆuršNq(ïîžÓ/h*+ÎIô0ðÏ ‡*÷¦ZËqÄRÒŽP´pßÍ<DúÎ$‡-Îó'Tu®¶¨9À¦Ìh§iØó ˜_HLHg3D®Ñ  ;tãÑúŸò 묾¬éŠ2Žp GvgÆ„)P‹Âš:e§:Oä§æXpÇÌÅN0Èäš‚!ú–ª¸ðÅ¢Cç$—LLî ¶k«n³,zê‚!ÃtyëKDÀì¢+ ¢80ä"µK“)£lI‚#‘ͯtEoZÐŽ~·ŒJËêèVÎÒj†ôáüeˆ)‹Â.‘ Êd)‹”–Mà!¢¼ôq,pVi-(ìImd0“ÎÏrøÎé0!öfÉ[ åÎ@4Bfpê)JLMºÜ¦à]$:Ä)^Št%¨ŸÀÚ |L Óð%5Ãè&sT]ròûpT>¿8DC!ù¤øíì$׹̊¥,o‹þåp!îª$-Ü’¨~,Ï8³°sî%I“3Ë¢„Î#2®‘’Ÿ¡òâG1z›læï‚¢¥Š¦çãV¥SÆÎdÅ„&leñÈ|Ò‚Ûlº ÉêîÅÜžhÞBòBO¦2¬ågÑENdމ˜”6ÐÁç2t`ЦO¤ï@+Êå£è¶³@”Âô) µÏEj¿EGRü*´§ç0N>_k¢S“€ueä®c4pÝi(ÁÍÓ=³ÐÙ¯z­‹#8ä;;¬ÛÕ‰ o0š¨r‰çÌ8ï†Ü4vî§®õJ…刖¸R'Ç|TS25·ƒÛ NµFÊi">£6³°€R”iGB¬4Å.ÉÓðˆ÷§R’‡<Ä2B$002¥ˆ5 tSѪ@ „&|—ÈR(ÄH–¢BfW²·+«çP«ä:Át¾™”.Þ¸q½¢U’PÊç‡P°'1¬On~'† E’ÿ)¯†e17¤(ëZªu`¹G W"Q ÎܬLÆí¯Iµ gÅÖ®ˆ8]bê«4 è³àrÂêžìJ‡ó´áþb2'‰îU¦ƒì˜)€¿üë¦î"â±3þŽ‘šGŠxs1>¡ü®‚8xÊÏÀâ×C`2G¼Ù6°c2hÁè“Vó™)¤ˆ”â†R2»Jµ9ÔÁ_ EWÑÏUH`ÝH|mÑ?!t@&gî“ð!/§W H4ƒãbq`sTÀBí((ÍUg6$鬟j´VÇ)áð$%&pÈB5à:D¾Â¸ý©T®Ž !ṳ́ú¢FÇ<«šî¤ìeC7Çõ³}Jk!N6jK¬óæƒäÄ—çífÅ*\÷ƒEo¥8¯wJM—^Dï ¯â4JsÆ¿qèϸ–dÅj ´ÍEN^'0öɸ™²ËdËkRÓwM³`o3Ú%‡Ç]ï«’~¬å[#ƒl¹šÎɘ½õc (×# ÚcŒxu3ÐC£°‰ÒôUÂEi™g§“ƒuÌk4͹ƒD3²ñiÔÒŸòhêµÈþ„‰¨#%&rÓfÔ:2c)8¤¾7M³'©èÈt“Lk™'GÁe£8A¾rËS+£Z:w7Ìâ"ó z uUjûV¦÷¢¼òÆLµs?WÊ7I}=Àv1à?í+|Û"€ (Õ,wdúšÎäê°"õ×tÇÖAp´çqEñÜXŠmc4mpgWžpÒLvó$B[l3$)µ‚øƒYÍ‘q§L8"‡i.†×Ƴ–\ÊQtÕÀ™Ï]óæÁËÓ8¥ÀH“¼r1äÁÏŸbÁý­ñd-dªbŒS•sQ6fPVÉdçÂ÷øc±ˆTX$/VÎ0P(zo» Õ˜p£?×÷ˆ—ÄT&Ú—ªpÔàiT}‘òCˆÝz¶íç9Ih]$¬Ó°ÂL²ÎöUÛc¸´¶ÝaäPIX6&lÒ—&v.vSô)Œ~4;%ÁúBÎÞ#)õ*p»4lìÎGÿ=ŠU9NiJðRCg vXáM e™H猀‘ oo<Ö%\!Þž2+vÏePKösÇ%X³×—÷§Xh5 6rþWŠw3Ϊj’e¢yWuÆàù칃["Õöwf9›ŠÏž²Ì/Ã"ÁÐ\ù Üc¶®—¤è@ '•"óPÉŸ†9 –¥Ö ×"©§”r¼·ŠlsxCðÕ1Šïòˆî””p<«Ó”óýD,YD2¤Y¾lt¦`jé•F9§vÕƒ0tu*D‰õ^k}ökÌrCìJÁÇì6mÒÎR9RMҮ̃Jèçä"Ôë•“Õ±Kª§pú^a0E…³ÌsÔ×d+ìítK™Dï{VO¶€ìÎAkÓELCŠÍ_â†0îªá׳…r’ß.·¢×¯_X!Föô“ilÌ%«Ö÷H}²™w¤ÁÙ¬*4}ˆ‘IÏ‹¦yöG+væ³Y¡nc©›-æX:)PRe"½†9´Ø‘ŒÂ7~™òiîØ&«xZJŒôq®·îÂ0KÒÓ.myИSpïéT5¶s*O­Õq®BÄól8¬4SÚ&.$M Lözqé™EN ŒñPe¥É7®‡vÊ •s³Eú;”a±ƒ;"ôìÂUŽÄ›™q ¨X ¤—²c‹²"÷þ«ç›©Ð*ÔÆÑ;uH@Ì¥Á+DUÄ7GvCµc |41)¢f‚©ƒ!¦ò"'w‚¢Ç" 5âØ.¼¿vzƒ”{ìƒpL™8Çmï•”¨T ÆÄZ8…÷@¨¨T ÈP‰\?~÷HÑ„÷¶½oàè°2SѪuj†°ù<+L ôL±ˊدÕÊœ’µDyïXöQÜ4P`L DÎZûds›‘h.` «`Ç,C³Ñ`2àyvßÈÓXÄ®´ò" W<[Ê0%&Ké -ˆGãÑ2ËÐoÈ|+Ò0ïã#<3')¹õ»¥ç)±4+Ì%X£„‚§çúçìŸ6¬V 2¿À ÔîAT¢‡ƒ³Uiµ/nÑN,Ï–ˆØ÷4¬ÅÏ¢ £"ÎݾÊáèB'Su€Ø:ˆ8ú-"'}Då?Gw†D# ?Ñ$S`žt-)€RŽéÜÄŒ\¬̽=8Ù‡/ÏËI.V$ãÎŽûx•jc’É›”Â[ƒ|Kêx,NKk²¼P/1µùžÔŠ©bÛÏ—U´ · Æõ»ÚëyTÎDÅÁL¿ZÂTžç0ÔRç.W4\vË5üŸhCv—úù?‚Sƒ; ’wãVËÙ§"7ÍýkpÐÜÝ4¾i‡1(ø~Æâæ~$bÇ4òeµí¶5 _Gó ìä9·9`>Zþ–è½ìo'¨€j4úkE¡±g½>F£¡šd)†Öà“úœUA‰ÄbR‰PÑoÚçôGÔ6Þ!`8¤žK?¦Ä¡µ;œªUs®?î°Û¬«U´bÐkç(Š[ª3—ÅFþ¬Òìq‰ü« >à×<ü‚§£¹ÝeÝTö’—\åÀlÿkŸãâÑL~gw½V"èÕÏ|‚]n±Kˆo4‹J9ºû ßD ÝÝŒ¢KŸì€^f÷‹Öñ .¯­Ñ¡{©¦"¸ ýUo`:Òˆ9ž{¶ˆ‚ ·4lZ¦™,©*À**ªþ1h¤¡ïJ8ÇÚ,¨¢ÉR~Ó&ŒØ»©Nê~ÓŸˆl4Œ*êÛjÞ9Gú,·1l¹ÆîâÑ¿à+×Kªª–E’R´ö"Ì:C ¾€ ~'iãjŸ´o3p²C0êô#‚ª¨Éç㮆‡ä`Š4'ûFÃ>¨‚Ü̱iRXËD 5‰*¦í@)ã‡7£tè…ÆR€Î»Àd¼¨k. ³àË40¨ÎTD.qª.—?­N”BÈ„Ž„EòùþŸ®¬ÌÔºµà%#5TnMHR®‰ý!3)cž·N Òž%UJÑJ‹œ´*ªœFš.³ rˆ%R”a ;1ä»1m~ÅÊÀ#ŸBI‡û¶è+©¢£±v* N£LjQ"KsÆ÷®wð q¨j"ë|€1mr- „*´P–€ 6¡v¡üƒ2È2¾9ÉÝk"Xꃎ!jòŒû3PÜ{BTl|‰v*uŠ”D’¼9ò%‡(J4ýlŠMG¶Uû[è)s,ÅÞS§ ôÀ§‘ÌWq“‚ÿg1Ùÿ J«šˆSÌ"RÉÊ zŸyùúŠ*ze%wEåî‘õxÚØÔª¢zoªŽË$#Ët‰‚Ǩµ(šVËwªntÊhÅÐ5ì•v?±“(‘Ñvº ©Ý”½é,MÒH˜ž?H¥Jœü~ò(#,›S"G˜Šìˆ*½B¹H —+ÂÎ¥ þLn2—^J&±É3(ãHcô­wÛíô® {{á k í…¦s:ÖàʯrPJ"sF[žDHxŠ@~«€‹u‹xœø\‰’ë,Ì0À¤z‘Ša¤Ñ)+‚x`ÐÃ`rlš,À§TÉëy=Ž ?”e4>Ê‹’…éøÀõNKÐyœ'™‰±0U±×bj8ë¦ÈÀ2ü«¨ë¦eî‹q,v¬V–KXß!±ˆ~µ„úÌñ÷$õ™ETΊ"»“kÅ–$N™c%‚¤©¥âÜìLÌ‹L}‡²ð¶žBb ETëÉYl@Ú„™n  βr ¯ä¤Ci:5µ…*˜TŠ=QN$?÷Ú«ÌÉ*vè”ì-ôbúžl·qÈÚɸ7 Q£|ÉM¶ÒŒÇåê Œ„’„“ä1e8§¢s=góÃKJ\‚¦ÔØ‚Q–è0¼Äb0Kt•¡äñá’©F^Ü´d±v?“G ^4[Úc¥à/aâÞvä4ªšW@£ z:{Ãé”9I‹@ŽéƒcèâOÇa/`ð›OàïÉ:lïá"]jÍ1é—&!dWf.•Ô6>‰Ôª„<†-*.ª´€ÊzÏ#Q¥vLÒÄg-93±ÌÔEàJŠ­$BwÉ^âFÈ ¢'jâ«Ø+„ªD–bªí]a‹{gá»Æ™ ÿ#pý„çõL!†?§­.yña!2Yh]^ÈöJJbÎ$§âw_Ó4—Õ&¤Rvú‚ …Áؤ`x–«d¦*:]"¢sØúû©Ñ…’ª‹Q‘æ&$–lèäH#MAµ VN‚JTbm5Èá8ñüTmtY˜u ÁÆ…j‘“Õ}RïÎYÆä C¬* :ù\Rhî®´äUKÜõ‚v/>ôirÈÅ <(˜õ~y&Óäš÷:›:Ã̯È1£"Ô§(²˜n ýD$JZ^uJÜZÁ`°žHr<¢ß¥xW‘”ëÞÈ¥H£[‹.˜9òD"zê-B2Y?‡«e‹˜JËçM’¨Ñm(€7)6ü,«Øû} ÌsÈë$,`ÄÑ€J§Œ#Lò‘pÜ’ÁŠlE­Ý$!µÀ~fûYO#‚-œ±•ÉX89vJ|ˆ»+ TÀA±|…‰)U¢2Ûe/ݲ«!kˆÑ‘¥![Ž6²ÁË>¥Õ &ü–¬ÇVMQÇœmyϱ¥]¤Dd‘.Û›“Ã騨R\J£¨ Çæv,9$µà®/̓ûA€Òº¡óùµ­0¸À Äáö_IGö¹†Å‹ôN=Ì3m»°CajY±%ºç•Dà ?$J$•ˆ£ù"RÀ¥V\K£èõc9%SSklºÃk\¢AqãYs§î²M–äîG¡‰<@„²ˆîÚŒ!\~0maÖ5·fÕªö3³:$¹Ô>ômT;tŠb§#ù9]0—‡Äù£ïÒ¼ulI>V÷váé5'œ^¤R•:[Ox$]`uôNÁ°ÇVÚ‘#Ÿ¸TšÑ!2ÞN¨»È˜TY,…hÃ1ór·¥ÕyÔØܞOkТéÇhªrŸÚ­úæmøŸ–,ÞÆ*<<ˆ\’ì2œŽ¼›ìI¾#mð^"©Öö`7|e§. é¶?g£j4ÛË«8†ZMì¿++ÚÌã&v'm• 9jËTê‹bW’X˜v Ž’ûª…í¥ØJzE'îÀ›Æ”=Åü'8Ѿ1Ñs  Ùzù%¸„"BíÇË©v_x72R¦ñU†bìeËnøî”ÍYËïGƒÑñ«T»;Dzé•õÀ<A¬ú˜÷ØÌ}áùX‰q(v9aØ LS4÷s=~‹óŠ©!êÕ¡´Ÿ•%»Í/s¡›Z¸(&Ñ_¹K x¹®ÓÐ (*j:ó.Ãg8Ú-aQ·’ca‰c\£ˆêºô r@ˆ¨‰Bϋ܉ȹ½¹ñ‰” 2°ãÔkÙª;±®{¼q0Љ7`Å¿{Žºÿ(i׉ɷ<ê ¾ÜB»ò¦$/´Ù¼-Ai²RX/¾Š3þ9ÚT‰[¯¡ Räª<ŒëÉ xËê<¡)¤&ªK1Ñ ¡‘)³$ B†+±Q¢‰G9jJ£(¨›IB3.¡ô è0Bƒ:´¥ƒ¤‹B =Áù¢DÓ83µB‘9É<ˆ‘“rµ¹Cº´21¨Ú—5¡ª¡)±·Ã£ 8~ȱpó͈“j³Z5Êc7’Û#"’ê»$™Žyᬪ,ºÅ;cH%«%6:8IƒRŽzð L´#óÆL›Bñ¬5cí9Š$²6B,‘9GE‚ì6› ¼L#BÄx S(Ó€ Ф)'’P¦ oA¢’²T¢Åä®Iqº27À2­LãÌ.²ì/É“2h¢Ô» ‚£©üœ£*F°4 cy´t39q£<•G$΀J¦‘è#Ryš$=Ø„(Ó`ÈѲ¡ í$cµQî X‰ ²vEéTFüi©lOòTã—S’ <ÊšÛX=<[ *ùpxÑô[ªûµé)¸é)KƒŠ‘kœÐá! ¿Rä?¡;¶ŠàòE”à6ÂX<ÄsòϤÚP ¹•âÅ%ƒÑ}NZÕ”;–ˆ£äËðJÒn,€2½Ówˆl?,ARqò÷™„°œ¬ª~,@Èì9 »0Q3;B^ÂЬ­Ù5²'ÆY™ÌÇã*¿XAä5Š{¬¡,4> ¡ á²1Š2Ϥêp´ ݬ{µS~ã¿4%SO\"µ X2Äì&€ïRßIMiÿ0äú¹}5’"@DZ*j-0ŒdP‹ð¥é]Š‹™pš ´s‡Ñé r©i$éÑ”½:\ËÛ¨ §…0¿£l3B5¬#¨ÖÉlsw§‘5W@|¿ëß¾¬§ˆ¢O˜*2?H¥wŒ×Ë4Ï<Ὺ< æQs>Í: £¼Ñcá‡ÚFÑÐ~Á —û7˜*Í–ËŘ*ï̸H›å“˜Ð’È+ ÃSMªBA›´Ÿ) qR$OÚÅ!Ü?ؤÁÙ»à“ ""ÃÀ¡ó=¬^02¾4P~‹™íÈË·<ë- %‹7¤„ñ¾ê˜XÅi Ùì²Äó/U°Í)Za•H[Щ!*H9"ÜšAñ&â² {‰T­TåCÌš?[e5P,Ѷq4ùvR*AëÎÇ+ÃÒýp׳B8ZZYSâ­E!Áõl$ÚÆLÙM¤Ù!E(¡Y30€ï"ÂŒ™ËDOUÖ¨Ô¾‹¨p]àŸÃ‹wË„OÜx}Ûú*1‡´8á ¥'ƒ%¥+r£%P‘ d©:Ë]0¸sò^Ùµ>ÌÇ«º4¢CÙ¯²î f4JðÁ°÷HÓѶÅ (Åûð»1¸™)ÉE¬õt:!Q£B,ð§”:VÜÞÀC>¢b/Ìœ×!ØŒ±H¤ë)‹´!õ!¬Kõ0TªN“dÉ”‰3'$YÚ—6 W:€|ÎÀ”I-œ»„¯âÜ&Ób¤N9ÇUš7K7A؈²Ï·eáÄ?M¬Ôšº"R±µ ~Æ}€÷.Ûãí{—x‘È"£ÜãðáºÜˆ ±»Ò›X'•ôŸSÑ© ³¢9»%¤TØmÌ•¢$ƒ,¼ ÔTÝŒ$ 3–’#[‡ž=Ò©ï‹í<ì4¦Š,ýÎ`”¶±zNÉlœ¨ ¢æJe+Zîõ:Áh§Õ”³C夨ÉÛ“9uÿ‘Z¾ëZé`?V+È¡¡ÂÛ@†²2˳ÃHÀã––3`Í^’ÚúˆA¿œ/#šmb-BÏßi¸-T Ïu5ÀÕ ÝŠ4˜Šá¬c!.¢vF¶¤ÝÚãÖ¼¤Y² q ÉØ¡[I<Ê-L<3¢Ô7Î&П¬¼™™-x¦dE<ëÉX¨5ýµ5Çâ@U²-»“RJ9 ´I‚à"% Fdã`Ï17c¬:`ÑlY¨|âù%<Ì-I·Ø÷Gáu*ªÔ0·=»ðÉË7½óvc‚h9%<Å< Ͱ)’ÇÓœý© ØTÈÃcææRYÐÅ×B«>½…‹Nó¢bòÄÆX“ë‘aجRUü]ËGé78s‰å%aõµš¡GXûSÍýæT©¸öD²9ZÕ,é»6 åR§Çp~&Ó)²4¥¤ ËLÜJ¬ÙÖ`tÂb£ÜÒ×#1ÃŽ$)pÌŒ}¬a)¦°U~‡Éêâ-EáF}Z*B<‹´&·Þ,…`T°µ.('…4%ºX±áÃ–2î‡ÃÇHdB‡ÝŽŽí!°F½Uðœr^ìˆO¥[±6Ïmˆ¡á“̪0V9*rÑÎ 2NµºÝ=¯(³j\†­…Þ¬RðزÍæRQ%ï·©¢kþÝíûRÐÔÛI•½šsçÝÙ¶Næ(ÖÇX¤)ÌýoÔðŽrÁ²’Ÿ¸LU‡ýíõ:½—$)Lò²î6QV+3M%ŸÇú¥5jË’èâM¾ÃÂÒÄf¶bI0ª1à~˜_ ÈÁ.Û.ÆÖív±­ž?£O—S”ZE?ùHÜ« u¨ÐaEÏįÜ2N§î½Â¨6z•~ÑNæ `¹Â™¢ÏÝd‡âöÈ„ šIåÇóbE0~,«1Ó}aí)‘î…‰ç2Z ‹>ä/\”M€BX[mÄ9ñ,­™T2a›l#á>GäòòXª"4µ¸ò,K$©) ­Ö‹ž¢€Dxêîx¸j¾®_Ìœ.”$ e°¸!œ‘ic ÎXˆ”X277Q)pþâ(2Û…·Z¿6êm0úFÛ;˜}AŠíªÅ-Kñ¾º¹Þá>Ä#!3ÊšZ$+j°¥…éè”§“l/%ªlÞxa“L.Å‚¨Çê’J¸|PUŤÀþ߯lm3—Èa ¡X‘ʆ[Üøæø´fx{÷•p¯v= SÛ§‘[^È‹A¡ª>·£M©PRôU>-Üu¤m;Nª,_óV$‘ƒÇž \“»DÍ@í›W•”\)²Ê¢í Ì€Oؽžëò`¤îâïÓ–ñ_݅嘹£jöhŸ!Ú½¾Dø‹õ#õ+(ÕÐåÈ…•²S4°½´=TË"G ’¾Ç¦®ìË4í£ƒ·Éºm-€|‰dæÅd/%…‚îzj•)ÞJ’'Ð{¤/ƒtZ§ðXöV|) ´õ²1‡ [Ëú5®KµPŽ£¤²»;Eál…ån,¶ûÖú ×®DG,ÚŒJ@£cØyÉÊö¬ÄØS^}ä:Y³Qs }!ÐþuØŸö×N—üö•åKZÉzurÅnººø‘áÚÆ»žð€§á“ü›ë7Ãø”#“Q½<7³¯ Âò¸ºÕo)lY&ꊀ’o–æu©âHÚ»²!XòRU¾Í€?_ (#~ ù„@Ÿ¯è`ˆ"Q7üV-E¢o¸äXŠEaÀ@,–,ú”¥QÇÜŽ>~LaR9‹òT¿âq8cú'Ëçɬb1—ÍdqhT¾{7”>£i(k‘ÎâULÆ«=ªÑâU×äº? ‹K$uød!óSŠÕjµú› ‰G£ö` j% ­)R8u’/žÎc+ž‡`iú4ï/ÏeòÊbk/ŒOrüK;•Í^h´öÅ‚˜àq1+",ŒP3”ŒJk®‚dæ?¨í@SݘA§C&pìýîçäoð+¤KC ëÞb±‰eÎS*æÝr´ldîõ}ŠÏaP©¿7Š–{èi¯ïX¨ êX@‡œ ‘½m{DŠ·HâFù J«Ï&-â ¨º  è2ˆ"ª·<©*0…?(¨µ.øìÃ(ÂFù P°ºº'ò®ñÃÿ!Ž…ºHîÃ?éË„š¢j©ï%ÄàJz‘­ÎJJœ¥º&ûž²ÌšÙGªÒz·³ `~ª D\‡?‰ªc RlŽJî)ñ9Î :¢…*¯kü¥“’¹­jöµó™ðú%Oz^‹(«^–"i¢c´hüž‡Là$û*°Ø¡’Yîá9Š"b¬0€%Ÿ4È‚—Iz€‰´ ÷R¹ˆ›Aõ-RÕ $3ŸrX$kU0‚-ÌÅF×ñ²bô«VpŒ*§µµ "T’ʇV©ín†Dh6Ž*³ÄDË Uyþšºl%i"m{g)ˆX—¾î|ÌÔªv-i*ÝZÏ"9^ö¶cÏj &)½ ¥³î–L§Òªšª¶P ; I½æ~Ϋs'6à†]ˆ]KJ.)*øžànÊÈŸ¢ ƒ×“Ã7vV²;çòÈÓ€Y]ĈE.ЊÝ@*_(!@ †Ágû³ß9•t Wªÿ§VíÁv¡Ê¡‡·(…´{-ŽbGµÒ •êB­è}£îU 6eþûª)`ÃÖ·9öáF¹âƒg^È%E?€³ÚૈþA)±¬Ã°ì}ËÀ€ZÝË´™*UÇh%’Ž;22$æô{ŠìN]xÌk5Òc†½¸âUZGâüЛ+‡yˆVW ”γœwñÏo­_f™  m¶ŒÕhûÒ¨“Vr£²"rm õ8<Ö–IµãÙ9Ý—^ÂíežÖSšž•qbdAš6Wêf¹ufœœw\šªHs§4¾=víÓxû(¦UßÅ"²×ùk¤½°=б’&ä°æ§´ªq[àqÊmý?cX¶ +Yel\¯¬BšX9®ˆ‚DÚȱ7$nf;5ÈA ‹µ|ƒü‘¶ó”õÙʽFN䨢—ˆ‘nQŽ¸Ìšž¨*± ø¥ÓVî Ñ'%ùΜ¢Ü펰}n $¤–ÚÎ!v õÂ0ÆÓ„N{æaã•—; `ÊýÏåb8CΗ‹Žj*¬÷¥B8¬È“[ËR ºTìï8B,ø….$‚J¯æ_Åü¶ÊH¦‘ €]ÊjË,ü ú¯0rG/”t®B0‹&âXÇk0À¤°§ ÐÊòTH’%o »ñŠêô¡.¾ýk|ÇHÀ¢¼… ³/Êsªv"ªš"fÞ©¦Þ¦/D5GØ_ìÜV§¤Tн œ‹”‹zZËNÃ^ƒ«$¶åZ7ˆJ·¯jê&ôòCÞ/‹ddí«ÌXýCþlF°ðwfŠ‚íV¥æbX†òé–‘<&¤š&¯¨äNnaíBöÇä$«Î¤È2',Ü®PæèÎÖæh[§bKÉ`é®j–…¦ÉŠx…q L αxïR,€Ì›FcÐŒ­ÉŠi¯š%â܉I°w'ü!ŠÆ©¥D&ð`³ÄNT‡¸–QÒ"„¦\2ê ÔÑÚ˜¨YƒÖÙÍ"!ˆÚŠ*w‰€[ĉÑÇ@²œõc„¿0j¤Åf/hõ-6&­"ešW¦DâqÚ…-b,5%JklÓCXF«¤ùMvù«°W«ýŒ w'.ê b]Ë!L$répCOqd2çòܱª˜ @ôɤ¾/›$ÇÀYÐ ×%`§Òî',¥jZ-Êàì%AøÆMž™CxUcÛÅܲFPÉÔñQšìî ²¬á‰¿&ŠÎèl—‡¸Å%zeÒâôI(!üb1ÚuïæÂ%¬­k6%Q[3„`êmìsª>µÅVÝ‹W2©EE<µSšÇ’„(Ãg¼Ðüð \oy1Fö‘.N×Ð,²)°uƒ!,aù QŒœÈi1Ѩöñ!4to0ùSRF&À¬Öñ§ŽÙ‡ò>æ0÷&ääB'(iîàI¦îñN¬Ñ܀ɚnÒ@'m[C£„¹¥*çòþçc0¬o« ¦$Nm0òQËæM÷'û  /n€ÑCT÷%Ô~{)XHPs¬"5òÏâI«šÅÓûFˆ % ^.ª©©(|L},tÒs=±ö Žø[IÉ ìv!M0,’®ŠŽDk§r´lF$,zœ€ôC² é"s=+eB T˜' )Ìô£T5ê[ (á-¸„æI²ºÌ0êF Úýµ ²€´ ÝÔPkÊ˳ruT{ˆkÔlY‚¶)V¼è‚k¬>œÊZçñM.ÆbjËä’ævñJ ®l £/‰Ú@‚&ˆñÚ)åü3œNjÆ}Dç( I°4°Š#3,yO-î5ç'®‰‚r²Gèõ€I±n5F­ ¡ø†…2.¥&O=§s´L5˜«zçïÎ0,ªžóå?î:¶N†Ok©&ð*ãî]2DuDóèȉlñRÊXç铨ÇО!"oP¸ N, „¶"FÞqÉt·•I+‚0$dÐíY!°ÓǘñpoKdF¦‘Ï'Sü”ŽÈÒ‹{6nã”FrsÇ2 91¹MO|ç0øoDünÔn%”ÊCT/‹TjÅEJ¶­"ÓW\ PS‚HîÏYJñÅ<æuz"tÊÅÜ—S‘[+$Õïš¶F‹e3î$¡¥o+@#X†Ìº2ë$ˆ2{bä ÌDé·A–¶ÐÕV›^`÷?·LŸ£è:Ít=+zeÅ­',}  hjõ3@ ç«Á÷ZBQÒŠÍÂYˆ^. &ì²g'èØ²Õ8Øu…j–¼ŒC&Niˆ€ž{Ø è§SÆÉKÇ*Óep˜eW\ ä­2ìsGN¤%U&Ðïyc¬$mí0ßOä„´búk¸¼V r%J‘S± áqMi¤ãöµù í5Gv/BM{!wI|ƒXqȼ„ Tó¼X“ͧ¤*¥ ß1žn"P͈jøÏ²g†hÓ2ίGXßpV€Õ=w·ÞÒ’ôÇËTíySõúüiðþG(Ã^ö}/l…+]–¶•-fG0»I£1|âo§_SÜóëÂ-Æyüò7Ú¢-}ŸbCÜ?ä2î¦í%¡õM¸3Í2ðjäy÷ %´)1qžÞ1ÎäuO6/'‡ˆ]ÎmŽ!ÊBÓy0Ôt¯£^=¥D®F]@#*âui”è›æÈÜTA„†W·“"µ´Ù†zGœÁýe”j0)˜àÿE`i â¿Ñº;‰/‹ô¤e×ë"óÂÒg¯¦'¯_­%~¨XšŒ{˜T¦‚ÛjxŽfȨm˜{âís‘¡c™ 6ÖȆ$3o¤tdBŒ§Y6ŠX(2Ć̆²XÖs¢&W] ¨!D› «A¤¬DUi|¢ùVb$ùF%Vv"­±$3ŠO£èÜÍuX(×VɃ@PØWŒlà5ðPTZ½AöÅ/åp®Gê°nלW ÛCÿN &Dó|ñµet=˜þ;$Ç9l`ûÆã1Ñ=1ë…òøÖ³mÏf(m] ×§/ÛJGX1èfjõÆ;g @"FEµ€‡õ‡'Q{yÈÖ·Ü_ËEjMø ûIƒRs.@–lj{ªV‚ˆ ¯¶D©Ü©xí V@BÊáodr´yØ'+æYÊAÑ]JWCp‹))Š&åD>÷ ‘m&Þ4_jû/ëS‘§Š¥»FwxEh¯5Ó²¯¯˜¨+Jèüõ&SÆß±>ÑV8ª¦ªâNk9L$F­ ‘š×ÂéïšCxƒ³ðÜ›bÒ„ö¡.H·I B2¯–2kÕõ£ªäà"TÛ gÌ2hìõ{¢*.dPxþª5”،җUî®Ó)†Ð(9. 'bcRxO™ö¨b•bÚ!^ ä*41(:Øo ¨bmëv; “5Â/¤ÑOÍgQ¸ZÖÀÏ1cnh'rÿtUu»+aý:@2ïbÏ›Á÷œ Û®%‚•$d—ZpÚQÛ}lítg¡™Ô×Ü™=sÅvm†×î&£Ö{…–ùnRñêÖz @Áæ±¼\ú ’u?Ÿ6Tíeãcy¸Ê%Û/²¼KYÓ‘†X¯Q, Á£1¬âL Þ#î!O•»„u‰H'w¶§¿¥ýi½QÔŸ•µèÜ!9›ÁnÊñÉŠÅNÒ™Õã=ïšßy”—Û÷-;mÊ.×zÁû0΂ºbPa?ÎØ!W’/›®¢J‰šä5HJ˼ˆË=ñ¤Ù,k¾]0añ¶³‘yÉe´Ñ¾`&0›‡Ÿhƒ¯µÄ‚í ‡†£NìC$»½×«ä`Òsg1MS‚+ÚÕI·³w Â>æe­î”3´;ì®û¥)‘å׎E]ª"ØäsJ/œð×çÛ‹¸t¢6z1Á²ñÂ1íc®‘O'µ³T›†V¯ô©©½ ÂVßãíý,­B>+¾ æsꫨ¬$¯aq¾Š£ëßT›ÀÈäUrÿ«?dµÎªã‹[Þh”¾ 0ñó Ï\£W ¤E:ÈÍf²q%{Î1RÖ–Y‰¿œžs(Ó‹ÀÝmÊ™2ºyÞqvM7dâ3{$Û13E†â#D#ò ×ëúÿƒAÀ˜T( ƒÀŸ ”>‹D€0xÄ*1 ÁÏÉzDü%Ä  „¾æ 5’Ä ðˆL‚O(‹¡s¸$B?’Ë àZSê™?˜>å‘T‚•UÉgP¸6\ðäùˆwËÅ1z~Ñå~º=³zñô³üäæ çhvŒÛÿg…Êd “Ð&fYOÑ狼uz½bµÁ!RÈÆG¾þD¯‘,VŸ–ÿñÄàÛPGî1Â{£Éúªö!­ ’¶hžŸ¢ ªå3‹2$§½H“fФ ‚ƒ ¡l°¯<(JÔ~¸¬ô˜*HJ~Ö>§ú<¿$HRž·AL{€4+tDLвè2¨¥$¯jÙ¶­š’±Û–°:èSZ”»-ØÐ¤«8 ±P,Æ"‘<†§í žÝKRþÅ+2Š Æ#ˆ”TÁ2rLY=J ·"ñí?G)L}Ë*¬zè6;ö# *ªŸÏǵ,?û‚6j{–ÁÃtd`„«)ûâŒÈ.»ÞÎ:„1ŽœÙO Ìx±€L¢çm ²°ÇàÜãž­š<ï!´›4†ÌÕ}*‹/õŒ¼„£ÈSé H:œ˜6pb•h(,Œ@Æ¢M g 2* =&·<²¼ïs+J+5nÌï£ÍS|Þå±—K#PÌ@z§©ìË{U¡2ÍïQ# äÞÅ¿cM‰€I ô&Ÿ"ÕËábSÊúQ0_àÈÛ ,‹XYiîB,<”» ‰ZQ{«v:aX±Pì;ljE„˜WR¦›BI„ÚæY:UP¯iÌEª²GÇíQ}¨*ªÐÛ`-—Ú‹mÑ3ªc2âór& u‰ªˆhMh%‰´•žCL,L…5Î?'äWZŒ5®%9È€Aô9mè}¼dŽ\žÚw†/1˜žÝD"Ź¿’$hQV –RÕnËÓüýÊ«ˆ_$-Q%rDDR÷vefR<÷ï˜8<ÎÒb¼’bA s"ETè¾$zà[œ«åƒNRª[ˆ9Ñ/©lÂT*g§ÂëÇúçî*%Á²‹§ðü|LÌ»WJb–+„ÓíNÈÔØ3$(ÌŸ<}Û…U0ÑeWʼnDselV…OÐ ‡_TÉ\Dê£ý]Ä)¨MUæKÕøØárý7ÒîvÀi5@"­3’º=!ØÏfc²—±Äè¿v0Š} ‚)¤Ú¥ â”)îDŸ¸ŒAÊzŠœ´2DC58ÙL[{¯ýÊ–Ó-%epä6»ÙBÅSŠR ݆‘f]8‹©&¯©²ˆv™6®UŠ*†aS ¡Ë§Y±Ä‚¨<&³¤¢ycJD +ê›à ìÂjR@¬\¬|L:'3¶˜å-u A6V>u(#æ•§^!ÕÁüƒQ Ä‚´Ò¿R˜±Q}bHvKJ„Ó9NÑŒ:ÃùÒØKmqÈ“‘nœ~”’”ÝN™í«vÒô lÇã¹/iÎ:Z!+ü•Œ8ò)GgN!“hƒøÙÁˆtSUÅsV{SU¤ù_ùžŒí³ DÆé€©‚@ë7„ÅÌ$,U¬ÃÙb ñ%47$ …®»Þ÷¬1æ!SM*Æ<-K­ëS:6ÕÀS*§Vèõà¦ÖPÖG±PÝwbvçÆttÉ´‰°hã†U¥HUX’òµÆHÜÜjYgãî3*¦ÑuÌŠN%’u°ñ³žm%ØvaÃJt×¼o{8—Ÿp•#}ÖÆ¥38ègŒÙÔÀKοæÎR£èølO|ïiv$+ȉSV­ .åddŠ ’Ì(ÐÃé43ž¬‡·ÜwŽn¾†aÍ*ÔNEÙ šû]0Æ==¸4ÒÊӱДNŸÙuØ·£“ÆÀ+HTÁU¤L6]&Ö¢él+f¥ÎÇÖ™›ÉXÝi\K$H}ëÚAõtÿœÀ ˜ÉÊ©˜vSÒ`ªí┣Óó÷È»˜Ðã!ôè–Lî6'VÞì€/( â„ÿL·Ö?­lG­+EF-U ¤UmÄÁ(§²ø¡õÆŽ[ÇZv‹\šqJ JRIJtS­×åV"åÁ<¥‡Ï5“òÞV:ú@óeU-U g¦–ž²Zõ°¼f’¸èap€$"'æÔé¾)lñ¨}Oe$5H_ ð9Fé3z N" lé[€6qvNk~%Bž6oJÅ1ûÙ“£ÅS™¹ö°ÓØŸŽ0ñEv`Ĭ–£–Öã´m§!”_ ÉÔ(ˆéžËXûÒü÷Òi‰yXŒàx¥²¡I&r@ Üò¶H4/ß.6Uê·%—UV+"îÃ7€þÉÅ‚õ–$†Þjg·Ø‰ñÕŸàœùû4>в‡õKtF{¥®Ï§hýB õ_7 ÔØ#Ò£z¶R ˜<¥X•Znè>ºÿ/¾Ò¼ÓiŠ$ÚÃÐ1aÅñ”9¨2Ëž©j7§À¥#‰º¬…ª(a0*J#ISR ™H»¢£:FJHªÛá4h}**X¯»¨¶Zü,J7¾ÊÏ2 ‰™¯=ɉ<"4¬š¥Xœ²Ã­” ý’ã\¡É¡˜"Ùƒ3C[o¥è¬“óŒ›8ª ê ñ0š—8‰ñ3‹š«Â<®²jÂKä.{C‚8ŸQ® ‰3°Zqªs¦ÈÒ½òBìÈÏ! :=š&¾qX¿Kz¨(|1bà60Œ ‘:Bæ›1Y£i¢˜È§Y‰1Av«·43‘®È‘3={1§®€Ù‰ú~Bð+"K&0‚ ¨ÛÁ®,ÌH ™,³;»½òYºI± Ã¯²óư£.±ù2²¥ˆ!H q¯jq>àÁ˜è‹qó†À9ÒDÛ2°úí¨ÊÙ Ã;p—Kî4T‹ª¼Ú­/7»ú, +jÙˆD{sÁ˜É«ÊèUA°ÆF"<¦KÇ‹›+‚t§‡ ÈÆ“q!ÁºžÚë5Ad•1Ò‰*K¼>šç­2û­»²%±,¤±H· ýØ–òÏ<)õ ‹¯qû”¯9Zèðäš™ˆ1IQ ’4ŒÈˆ=@ý“¸‹S¡™Éùƒ‘8ƒ!Áù>:—«Dg¸i©¦Jº4ôD33ŽˆJËÖ?>¯q¹´Û$*±/ÊŠ"Ô‰C*iñ#ÊÓÇ—Ó¶ÀÁ´©Ç«‡©pÅ,òýJàÿS«¾S25ª¸¸¸Ï8A,€${§®ª÷%´²62jéX‹qH23Ö¹sYãÛH j bmœ!3ŸIdÓój¨8ö•CTµÙU)z0öă«Ãd>³³.’—¤Þ<!²É¶0å°Ÿ4Âô ó«+´Dr;Žš/™™³IKŸ£Kë•äÖˆðÚÅB ü‹”Ób)3ïÅYüDi±” ¸D(¼J–“Š¥cøÑfœ[z™Dœ‚©D«ÈK|1)yQ(àÄ(;긠èÜe ÷Ê;踤…¹xOõ ñä(isH34‰‚´E€’¼,FóäA“ Ê‘5T¥,ñå˜Ð¾èÏJ"¾¨;ï œí!a£z±§š Á´?2D~¢:JÎ?ÚëžP¯3CJ?êûÁ‘3£xªŠ{Ç%—ÉÙ°›!²3˜qˆHbk?¹æ ™’(õ LiÁ[ù›±©Ì»,Ë ¸ (¨ñº«BÚÁ¡ß£ÉY·d'K™´Ï\åš)”<,·1zuKBå+Aæ»ãAOá1tŽ ¬„ÌÒr­Â­¸ñ½¤¸—·ìzì ´,N“K8§ÁÌcúŒB8ÎzýÍÄÕ² \‡ËѲm+1Y—L,<ˆ};ûË¢Óë¢rˆ«ë·1J´4+­;sƒ®è U3¢(˜NÒˆ”’2ÊݘˆŸµ…Q=Ú¸DŸ®ÃZÀªR+¬:ìOù´Ó l7šîT56´Ph®ØÕy ŒÝS4±IÀ&º¼£¥ª‘Xžj¹ÜID*Šˆ5c³¬¾ÜæOcæÀ‹]J(2¡Æ±u3/t V¨š¶tÊ«PŒy_‰Á(ôî$F <¼¥ˆ&Åv.Â}6b44›A–ôðŸœ5LÓ’ÉÒƒ/ôm¤tÍF…Y.J–¬ˆ `ÙŠ«»ÝGed€)ì‰a—š¾JA4•4Ÿ-ä TÍEûB3‹’ËI´7ˆ\­ÃuC»¼È¬LÒâË…#‚€!XªQ™Ø»t!L… ¡s ›ß+E±‡ÌÝR;\¬ÍŒ9HE Jg ´AÄ´t¡œþžÛÅËà Üú}ƒ‚ ‹M!#`¥šë;Û\ŠÍ'®Rô1ƒCx;Êî+¹ÌÉ¡œJh|Wª;Ë"-˲<—MÚª³(‰ï”<@™Œ·íÓª§kЬB›D `‰[Â;Ñç} Þ «9(}žÙÚb¨+D6$kÆ. !M†°¡ÐÝè®bÑ^3ª™‚K\›gÜÚ­Õ²7Ñ…ÀšõÏ€iͽ ”¼;©õf‰©ãTkÂ×Qú•3¬ØÉ­SûÃ0àŽ¢E° JšÃ" ´÷+ý;3¼*\9®&Jƒ±bú»è}:ÚiŸ–+v§B–SêèŠTrÖý7Ž»++$ô´?RÊÞ ù.dz5£#Ódá™_Îøˆ6}Vœ'+ 1L­œTO‰ûÚ¬jXPüÀ½óÝLƒ$ÍÔ>øíUâj¬•5ªjÄÊœ‹Þ±øK;$˜£¯?»+.¹ñQS<¡¨T˜K•›c”z]¤ù˜‚#E²Ü<Ø\ÂV-ª7äÊì0„ƒJUæÃö aûh ž¨ƒß8âÉÎÛÕj:¨åÒ#ﺤú"ø[ý´H4áÌYUa‚¾±LŒ“J«^­^ÛøãñØŒË9Ș¢¬²ØÇZå<,éVŽ@¼-:^›,ì “›±„ƒdM*½›®[+)]X䊚þ ü:A‘´ÙÝ@«®¡ šåH£HöçuS¥„¸©l¢\?Ê;AVM.»E¶å<Úô€Øæ(ÝXƒ-¨Ð†ŽT=5íTà‘$ÌícdÍBÚ¼l²Yke ™ñB«5ü‰åÉŸ`›6œüM5ÑXˆñ_ÍÔSÞ¦‡Ô–áSБêãüY¡¢Ñ[É€€6·È ƒ¡t øÿ;<¢ƒK¿¥MµöÃ/uà •MJ:©>Ìœ2ó™r'=s­cAÀXø‚<gÌ’ÄŸ’q;^z΄— áí™qÀ%âûžiûÊ õ¨UÉÌŸVÅ ‡ëXX;›ÄióØæ»ÛÕˆÿWòð•å.&òA‰[ªÌ±c宜®!vJÎ+ Ô œNVÛ¢é‹&[‰6!±ž®º£ÎêɸëÑûÓ¿ìêX–ógãIˆHèßÕ÷ÁfåH9¯…Éç±p1™Qgs̺«„BÀöí+aÈÖpVJ•€PÅ[­¸Îƒ8Àƒ¾RfšRqk¹ài—_¨d0³‹$-|,l“¸ÍÐÞnªˆðÿ<šö$îÚ² ª7¯A¥^à9¸Œ1dšÿ8é̱/ô —»ïë‰'-ÀUbTC2s, ôÚ'¹Ìû¡uÁG<ܪ#Zt‡ãÅ.TÖ哯t#%¿áó i ­yÆ¦ìÆœE(¿ í á‡kNLšô 6ΈÓa³;äZµ´­ÁŽä³¿U/”¦ÇžÚУ¼‡<¡Ú¼¼|:Ѓ« RìÁ©¼½}Ô¦ ðŠ~ìó,0ÓÓ1#$*Ñ굞\éÇ­~h½B3u/VÇn¶©lm¬ EUèꢘâgy œÂY)”)Xú/CX=+\â;fkjå4f“é?m¹£ ˜M Í‹pèÑnÑè;ØTo’gÚîM×ÙõêX­ø±oI-IWŽÃG -â!º-­}oDLN-ñîE 5U€R•Õ|*H²j¤!w“Lo;dÂÎC®ƒ d·Ûª¶.sî¹Èe•#/i?U×ß=Káï€3¬/.ܹl(d?¥-£HÒÂâVyìíó²9K/8Œ—U&Îç+ûå«ÂÆyv~K gÛpСoÃÞ¶Òìvk)±–*׬™X»¨á`Zö€éƒæ=#ªÁ]ÙöZ½W_¯.cg¯A`0•þ£­~ ›I[ÛIdï9ÌÇ%²F?à”£žûd^/U +ò¦»j«@´ ŒóÐ{µ7rãÂÍbVñgÑÆ¨<­Ün–´÷;¬ò´6yg6«Xt±›u£Î¾î㸣#ÃØœ»çÕ®\ß®_ ~A@x ý Ã@p÷ìFÅbÑ04fÿˆ¿_Qø[ú7I_2pL¥÷+Kcqhì&C!–#qÐ<æ ü‰Äã±÷Ð…Ð(‘8Üä;‹P€³ºt­÷‹E¤2ø¬öM¡Gc´èÝ ŽÆä4JtvCQ•Æ@Ñx<†Ë†ÜK­fDªÅkÑÜ&k7ˆÅ¡8h;„Õ¡q9ÝN²D_{E Nù¢MswÐ Òk-Æ@ótè¶]ñn˜À虸MJJÅHt{ÔöGŠƒÙ±õ»ì&'Rá^áúªTOašë@Vç§F•¯“Û¦º¨§ åÂ{Õ+6' °Ãç~;ôGÃtÚÂâÔIÝ~…¥v«Ô®$mâï7k»Ä„ hÚ˜Š¦«²|ˆ§p;Ò~¢oØ¥*èj€P¼~¤,j*ÿ© z‹1òv³¡é &™!‘F»+ Žƒ£¨šøþ4É:já¥oêÜø¢1C€Àˆ*6Ñ¥ª# 7‰ìg ¼ˆlJ…¿ªr”ÕDo@©H³6¼èKX‰8Ê*?¥¬T¼þÁ Óÿ&€ ª¤É5È{1QrµEhâ"„¨Š¢û,BgúˆÌÍŸ/ï{̂Χü!@*°„þí´-üÅ,Jâ…­É„‚µ«À¡CçúO¢«’"Ì€§­`ÙÂ:Rçò&{×@ex¹Ðˆ|–PojEG5ª[]õ³*~º‡Í¹Ñš¾–kÊÚ’ü(HˆkíS±ÕÄÆþÉ+²B¥V€⇹«ûòïOÈz¤ä í:»ÊW•O  mšq¦µaûhÛpÌL»*,káÔz;BÏo뜉ÝH+®Ë¨ ¢Ð1KuWjˆÈgä^©d‹uÅ@«VÜÜÐ(Š•³…€«ü5L?ù*!vVE0#4~Oͪ§YJà eGGÛf»*I¬jÍÒÆOA­Ú¬“jËý6K±S¶- …ÉuÜÒ ³Ñý£Qì]<ÒÑ| !!³Ss„êˆ}•c€j(܉í]ƒ éß Ik²j§2.E˜g YŒÙªU¼þ瀙í3s$¾œ”eK.Û\ø~¾‘í¹ÍÍöÄA Vê莧zÝÖŸ²,ÎÞÄ ß?9èÏ@ö™E¼~]çíçÒLmU¢þì7ì÷,41üÈΔâ)®ÞŸ'êQp2Zœ'?&$™ôÝH•ÅíñüÁ¯ &ãTG\Ó(MI' ÿKäMo¤¶` ÐóÊv$XÙ‘µâÔÉi@?ì”â€Ø\#A§È±qø£Ý(þ> ½V‘ÀAØÍ¥£›’ÜTƒ^Œ%¹5êNJpMØ~¹¦žàWH*y28Ž·2™dE°}–³æ·ßx‹}ª5nàŠ‘;Eìp.³ìlIYBD,ÕBñøÓi q®¤†›7Ìö– ‹ÝÓ5èz©#(e›8F²!‘i½·Ç똉"Îÿ­x]$!ðV>â:[‘{ vò žä:C]Ä“8æ\”€• AaÜm"¨Ä¸UIk^(x•ÂÔÂ’”Ì¥eÐBL›•‚ëᓲ ¤YÁ+êæ¡!wM´KòK–¬‘B’$Npó@ `#e9áÈwŒõÈÙ@–1îPDâz[–QN›äfnõ¬A“›™ ¢JÅ0bšò¾DlV )V ó‘ðýš€-œLenË`ŠlN̼¾Ÿø€ðzÁuDXÃrCÊ[µ;е£¹bSŒÛ t ˆšŸ×Ée›îŠ4ˆ•$±&»¿E¶žéŠsdÈP½—Ae§KÒm7ÕöB“Ù†vιøE à²ÛQQ"hÙÈø¡9zrTƇøâhŸ5x¼«x¢þè‡4 ”™âNü€95YE)ËÊ´¼Ÿ!nšOà°úTž 'r?V‘ eNm‘ð„Ô -Íh3p¢7º¯1%Ĩ›|¾Àâû ÓEutm=q“¹b¯¢ÑO °pBÖ˜ýlÔ`fO3Š÷H%L¨.-¶›ŠNTÄjÝa¥/î²àÖiñ3Þu3} À"% Õ.•j)£Jìá¬É–.‚¡éÐå%QUµ¥Ò«#:KLÝŠ šr’ÓíORòÛ)ŸÕNâS4¢Äo…Ê6I3È5-Šª-Ut ƒª ²¨ šH-òûQŠ+1k«5 ñýÌ6áÈ«>m´š”(ÏP—àçCy1h¯ÓçuŧÑ.o/Ë\› g´äå¦%µœ•ª8v mS¼x=˜‰h’à”ù\qEmÜÐ —«æyYgcD±Õƪ8UÞ²Æ~”ñÆ$ !RðzßB›ÙÖÈÉúë2v\oÒK•|ßÀ"RM)]8ìmiέ֙ÏYø˜,Jh½dÙÒ&懶¥,D~9F†fJáêòM/¡þQIw]1ÿKÚ ÞþwcÙRsOpŠÂ©ïH‰›˜f?(?™ÍÊxWõTõ”æ“v„ñ‰‘™êP˜%û&ÕÕu¡™†[ŒÙR»žš×Š$¹‘^¼íæµD‡8UVj‡ió‹;¥Nà¯d!(w.r7,u(ö…DcKfmV>Òûlò&FG®whëÆK ÙßXƇqGä"$Ö/¤| r›jÐX{I¦Mõ#1®}mYÔÕ‚“kZ#0ó“Y±øË$bI¦tÐB0Ô>b°KÅ7+fŸs—ËÇ!´ëšb6ÈŠֳÄsÿS£ÿ ÍSšeD­Ñ¥¨‰ªyNØŒÙ\´GÔ nŽä“Ó'Là¬Ê–.ú¯Ã‹î[³˜[oNÚÏÂh¦Î]aË{€ò"ñ)$æ–èO™ ñQñÐZcqõ,àOV°ÈÙ»;fE°ÚHˉ/g {ê"±ïÊxƒèèßâ¾Z>ZÿÒrµp™é‰,¡=.o"ª×^Kà˜®û2æRAò»´ŠÛ×’bçäÉ®bNP]¶ª˜áxXª«îøGÈë‘ø8•fBNì¸RHÜhu0E«ÃTvc/ÏŽB”šOøp¯ªÊ¦ôåìt †Eï4©ê,å @³C6sCèxOXhÌÔêÏfôîV ì!i¾HãhV£‡ª½¡ôƒJh§Ð]kXê/WÌ¢î” â¤RIö‚”9Ïð#¦HkÇÈPndS!±ÎɤÑÊ’#œün´Èç²ò'¾â”hÅÆåÆpíðæeNëáöYŒj¤±îÀg`7JÀ7<Â€ÉæêÙëÈ».œÊàƒ.žÕŽr5G¦-È¢œ‡`§¨i p]iò«f£*â²§Œ¿0žn˜dGÈDm¼iΪÀÎ4œvt³CãÁôzä°Žª²¦¦pB 4 4>…Æï'!ìÀ¯_ŒNü訟&ªWΦTê(ÛÌôŠä…ª 6n b 4ŸNDçE¶ÒGÀ”QŒJkŸj X&ë0µF¾˜…¢Œ DSÄãÖpÏÄHZoÐáB:6j(²Œx…¨°9BNsPJJ£.‹^'abúÞÐnŠk°¯†¥"f2q PemOš‚ ‚« ­lŽ>Åâ€À *Ibµ"'H¸fÎ)j*cÔÙBs s`^'²ÛlÆÇ†Hl/ìJL÷Š}'MȶÂ*|K¯ À BÄrvyÇÚíï4Œ±fÿ¬~ûgœ9ÉRÁà§®OC f¼d޲j¥a%²~§|MÐRчÈÍFD¾éÎ(Mó,Æß# ‹rå‘dˆ<ò *Ç|‘Ê’_„—ñDÍ+Êþròl|]ièWG®wGrŠà§®~¢”À…ÁªG ÍÙ ŽD2üÀ "©6öÇœïÕÑP;‚NÀÒh¯’‡h°Ï.¼h„%‚Zd3#0b"¯ø°H†2™. LŠÍjÈ 2ÒňzoPð*ÓD¢n£'LÉ‹òMÉp~¬ÈRÈİE$¢‹°ßsYìRl±qÆòý­VéA ëÎÿ2\fldî²×G³Ò€9‰zÀ„Oh¦­½+æ&ÀÁ.KŠi<ƒèÌJÆ‚ÊÈÎ 8¾®äm Ä>„ÉÿoðæÐROè‡QpŸ(ÄXl>^KhîsÝ(ÓSCë´ÆŒPjð(„¬ÈðžthØoò*¡Jù"+¼Ê+æq‰Ä½/ÒÕÄX/ $?æID/¢þj²´O²ò‚4Øúí §ŒÛÈâg‘×é²#óL(PöãhªdN S#×B´‘æmIEœ”Œ­k«¾qlÝ‹è‡2zç"v”ꦭ$ý‚N^Ϩã²iÑŠ#΃@&Ê)ËâŠ1v‚Íç ‹ïáóAIpô’Ä£T•¬|I,TÂì^H4‹9õE«\ó¦-‚',õºâ„›@j«[t¼¬üúèøMÊê’Ð @D“MJJð˜uúÌÌ?¢”uŠ{+K6NwÐúÀœ'¡$I‰8æÑ`˜Œv‹«ó/)I[vS2% ¯³Ó)‰aðhÉÄü2⬈ÊÒ¬Omt Êë^Gû\îb¸ˆà±Ó ±ÈOrÒâøÝΤl¥Æ‘ça[Ì(.9 BNë*W°qÌk`ã Ê5A÷P ãÆtXÐà”YY¨TòÒEã6ÿ‹k64¶áf× âo-gñï!ÿYŠ~#æð¤Ó§ ‘”Nÿo‡#¡úJ‚s\ÒÔ7•œŠŽ³ êp˜ˆPtt"¬´Ó:Æâ r"?£6HÔ­S4"µŠjdÎNUÅyŒ)0‡þÉgœI/à!fh®(‚бÛT@ùväðRl*ùâà±ü", }°V þ'*_n³RFòk’¼òúZG0w̺òôÖïÉŽ¾*zþОÁÕÿ!¨»3¸sr¨,'cfn éJ£ú'vX#/õ]SÛiÊj$‚Lî'*L(­ªo'¦tÒOj_GêÏh/Ã1Õ>‹®²Ê(¡`]–î¨×hÌeVÝ6¦žª®¿0/u…E¨n‡ï!.Ô¥nT76¦p\&ËG+ð/µ8&oÞ®¬4"Ñ*å0J(…”6w„ú±4™¥!g >•€†íÈ$èjR’ÇÊjhÎÜ cUit^¯skFÏí…d!px§(§x,hÊ×4÷'Ú9ѨfÆÃF/lF~¨[X®ÖäÎ'Êc‘hÁð»œÂ6®(÷ œPjÑ GÐˇLõO/J…Þg}^䯖<èu Vê—O³$!ã6Kø-c°l²"·åÔ&¼î'OBsŠÉB.Ñ53…žÚ”ŽX–НŽ5Ý1€ Ó²<¨£o§ª¯C8›·kg@Pç®üT¶p4<ÙØX5FŒÁ¢s§pVk¸8 \o:ç±=ïIJº!ªVÏð¿ÐJØæ”ëQ©ä{(Ñ'Ð `„G@Ê<÷åÊxÑQfζ¸}ËòŸ*Ñ LÚ}BM˜Ä0;od°( ì(ƒED-/Aæ-“Lé°éZlÔ{õS+&xÕ %£TunšŸë°ç¸Ê(Ut£GÃ’xË4Y©†ê–ÿ —+Åy9n{ă„FsžPdí½ƒÐ)ˆÁE”O!ó[è»—•²«'Údí°âÖªGì«7ëq€‰ö 79ÂY¨n=lg2v ˜ÿ¾"Ö[V`Ò–¿˜$´ZÒÂÐns)F¼l1})òØ&¬3 Ž*Ex“Öl昰M­ éC-1G}vÑÐ$£ía3½X—GÐåÊÞ72ùKØÜ(U w’EíèâW-4mGÕx­üf÷’}m,Š9¦õ–€‚Cg´Ñ"YZú¨È‰¦¢3–Ûz $êuµ‰Ž1Yâ˜tlþ×¼­—4ëPRŠ×X¸¿$“Ofàíd“¦8Ûv{nÈÚ€À*N ÂrC:¸pVÆO²Ç¸ ©Añ} yˆÂñ…  ¹Yñ 'cœ²Šíëg쎡Nß béXª”T3†'ïQ'Kê†ò5g²Òd±~ëuõÀi“Êù׋‘(Åz¡Xl%® ÿã(ð §´MÕÚH4.鵫mç@\ÿ—/· ”ˆ¤Œ1jÌJÅåqM›UJowƒÿJJÒ(Kpdð‘€O"®~ÛèqV‰˜çX$‹!¯]',Âõ†pÁÓ„˜m«çFÍú2“h[UÍ›atm¥¤öÖÊãºöãB«ëœ„ƒ<îË›FŸ7]«/½oô‘ ¤.}NoªkÖØ¤Ø›N:ˆ‚ÜN‘’˹ïð¦§q ŠÑ’+EÚ+Ãtù|3ã‹ï>ÙïŽkS”wa|tvQO‰›1Òw“½ þT!6£­ÙóÅ„w¡¸è¨Ÿ÷2ÐÔp훕ɚ‚&r»C£GEœ<kã©¥xà§aÆJÝ“Ëu‡H¨BnEãÖv⤡ð² "³©—Ý«°su¿üËœxö z=—\UH’4½Œ/|×ráž5%Ö[8 €I·‡»Ç)j7s¶ùYM\e%Ym-ç…’WK±™¯ãS'§2~b÷/C†L¤ªuqýÌTã3g€¯•˜ókÆ Ä”•r„²‹š*œ[› ”Åèø™šU׸&xA)n…ï Ф†Ã4‡³Eƒv³!AûÔzÂ3•­`«úÐt„¾î$útiɾ67˜Pô.Ç=oµß)BÔ᪲ѻû™uxåìî¸bü~? €(0ÿ…!`)þ‰Dß±X´:&>cà,}õ!‚?¢À$ •>%èãæ&‡F"Rˆ„NG?%ˆœâ =¡D%º4N>‹I¢gܨ!}C£@9B/3J"Ñ ­VwZS£1¨µ"?©Mæ°‰5Vm…HävÔN}^êR‹¤ r…PÐê$"«#“E§xp :G?‰V@UXµ&!;²€ê@lôZ«‚S©4¹42-NªÚ¤P@V¾wBËÁ›YD¾!¼€7PŒ–üq¹p¢ÕÛœM(ªF¢”:-ÎàФrŠM;–ŠEjð© Ùà…Nê´˜œ–;ù²q]ÿ* xÙo¢\ÚÓ‚Ý`U_±ü‰·©ëë#éζ±ïŠ$îŸðs§ïÓ<)Î2"‰5l’FРÉ{~¨"lÓê…6IŠ{Å0è Äà#:Ï)ÎJ ¢Ð¤8æ!PC¦±Î%A*’’įïóÆ"kz4§:ªLÖLº>ì§lZ*©$ÌÄtŠÀI|(Ç4 2*ð»0:*° Qr,ݾMš8ùÉèbÿAˆ$~Þ î¢¯#N#Š~ÆiëLGh±D"ºEŸjJ¤ÍÁ­ú’ÑN‡òw'0 ô«èÓ LÓÀý;¢TÇÉâà„;ï:§"¸~º$J¡"q¼øãŸÎ ¨0ÌH¶+rÿ¤jt)7B‘IîÕ#RZ¬‚*P€ TIÚœ¨T‰#M€L$ð O ¥WÃãvÙMÌ%¦©.À4Ÿ— ØYJ2Pò£ç­þܬPÓ[V¨5¦W·)ø½»°.ö$º($w+Žãî©.«(NÇóeCURSNZïÓd–€cSV#Â߻󥃊Aõ+Åu\/b¾¡ %v?Ñû3Ÿº=úà”â°÷9ðŒÛ ¹j ‡ævyY3Ƕ¿ Z>á?S¥ù??!ø:JçêvÚ–zª§a·N‚¤p¢Qy%õdz…H¬* tA1ÅG"©4­d0NÎù›bõ»ö‚<Ò’þ‰~ÑÆ'¯üŠË¨6Â߱ʆZÆâwš@ÔRn9¦^(Ϊ@_vÒlˆF[J ÏRÍ=5ÖŸýاe¼]„ðnâßç®ÃKìú+·á'ý¼Òòü­/sWS+´æ[fA:¤xÂk._X¡JNce³Î®á7ªk9«¢Â*…ûx(Éô¯©RÄT BŽwÀ,ÃdòLt$) $7`>‰C OÜ(#þËÓq-d(×€§¬Cž*§dgàýöh†HÒ®qD˜¤B4µš°?äx¦ÆÜ¾Ö8O ¾´"TçM‘&kãÙ‚™¶t]!x¨5€·y",Oý.ªü`@uФ•þè ÜlˆÄ¤•’Õ8yÒxcð±?FþÒ’¨|áï‹æR´a®˜ܰN°±Ÿ6êfék"nÒ’åsÓs/£À}Þe,9™ÅÑ¢ãX g¥Í”`LQ˜¸hÈÀä›%äZ”˜¢ÁXm> ¥]=º®BžÐÊç}g°Ùr€˜jϬ²«ÙTŠêÅQ‚Bâ D '[ý!Æ$,FÖØVL]¶í%ÄÔF¤LÌ¥í¥îÌ'P¡ •·a¨Z¡ÑheìŠ=¥¿ç± ÅÕ Ä˜‘åxVë-}o¤cêè÷¬É)#ÏU]¸WñÙM¬W”ÏùM~À6°ÆuyŽ6hºnе#“®þÉÝG+ŲÔaèU])Fg‘&e«Ö7²\ºéA¬¿9h¬Ã…#H5G’¼± Ý©Ž.Ü’—‘vEiB4šbÚò¼ôÑtÂdO²{Ë9­7;QIT0l%B(¸¢¸gZ™…j£®¥Ú‚påH¶–òΕ&êäy­†*vwèR+hr»ÙÔ¤‡F¬#Ÿdº…Œ÷“hGE°g’Œ/ÓúFBÁ0 \‰2GèRŸ2¦·qèÝì½ë÷Ÿó(Ut9Z8WÑphžø*ÖUÐxíˆ&…<ÛÍÚ ”ãê“áºùÍÚ;ÕõÚŸ: o°V¾Z»YEEBl ¡õJËK™zàÙi¿¤ä½ÞI‹…[›ä*BnG\o󲴤䢒ü¥Ùp–½ˆë>EXJùœ´ðÈðÙjl€áÉ-x´œÊQµƒ\6p/'i#U]–^JÀlWâø¯$8±—Ñ)•Gúw l(\k|³¾E±•¶­ÆJŲÑg­9UÉ5ÙZ° vŒX¶µŽo‚%RÐjÏ–,9­\YG§Æ„Em¯Î>­J “Ÿ>S‹F(ËÐù‘ S ŸBß™á¥ë–ŸZáe¢„¨bþ¼ªÙ¦‘T4ÐÑŠ2`1 ¢Û‡"DˆcOàð–ðð‰2¿©è;‘ œ»QŒÉ55кXﱺY ©n¤Ñ“sõ8ø}=“ ŠË7i¼ÒL$Š?²3í³Ü“ “w½²Æ§3 ½@‰¤Ázá?Â–Ü §!•«ál“#— ¸k¢Û™‡Àï¶Z-‹÷¾ª®{‰§±©§h~@9U —·¸»°­2_¤ËR RXÁfއ7|%ÉЋA:o4Ëõ‡óÝ0¡Ã|±t&¢ó)²Á8D¹ó”‘¾8©ˆ1g¡YÃ=2ì@«”‹Ì9)Šºe)Ÿ¶+•‰ ÇS~-˜‡$ñ=«ã„Ê//ú}’3‘³‘ÃE›îˆcw3AzÓÅ»-ñ}Ú-ÄÛà;¡O7ˆCV®tc³ (‚M7*BK”#Ë”Kì$@ª¬¡—¤Qg(¿‰@%Ä'ã=µñN Bžò¹ pÇ$+±JÔCºç´‹ÏÀážD8ž£°ª⸊*s˜@‚)™Ò"Ñ×2ŠH1‚ÑÝÁ©s-‹Ù ¾×żLÇB-ȼŽû¯·³p=*¿qž9ãZ€1…šèFб8{žò“ÅlW°´pºS¤½‹ëßÂJHè™´ØŽ,H†zKiÀ³³pÉ/á7 |6?ê"³L•€Y–¾š‡ Rã-d<ügœZU>l Ôc [è¦Äm[½ØGûP'KÈ3ë.ÂI<(”JIÀÁ¹èäOñÁ$ª'u3» J3Æ®¼šÚëȂګàý@MTI€!gȜԟ2-ˆshÆ:ȵPyž(ÇK¡:àžG­˜Ç”b4¼c³ FM)óK4´! M´%®ÊÿDÊ ùKÛÊBc*HÊU$¡â¾Ë¬sV¾sƒ°#B:)™Ö˜â`$8|¼xž L›A¾(¯$ø–Äð â#ª°lÐC2ÃLa·  Ô™zžLÆzï3ò ϥɰªY˜›¼1›ÔMӥЭ2ï‰è©&àŠJÜJ9®A"‰ï˜Ê&ÔG•ÉÐéô”±T,Æ•ëù»’ÕQ%#âçÁᤉyålCºX–à•. ùH¹ 9ü{6+þ›È¨ |@ø–4ŠÉÏi7;¸äˆp¨. òAÙO"‰Ã(tãJÚuDáy$ ¼Ù­NÑõ@|â»Ý!³ê¥¨D€BºìBË €<1@ Ô¬Z ÀëJ:Ù(1œ].¤„G¯¨Í¤TŒ³cØ®œ¦Å#‘¥‹u‡Ôß:Áo)$ûÂÌ â"ì‰UOÔyˇ¨] Ð{B1yµ9+š:ŒÁ0ôѤ47"ðýGºßM¨–*YoL©Š"¯¹x©A0£ ˜‰|üºzÚ"€$w?^S庸éøK’´r.®‹\HÉŸ Ó*W4PžKó"èéNDS µr¾.Ü 5ÊË–$¢WÂn¿…]™‹O`ÔC©­;€ × é¤TR•<:Ë$¡ÿ 4V£j€…ŠƒZAƒŒ™8ŸK­Î‚÷MAÑÝyÂBY›ä0ªb˜\`Xì ·š½ƒ\«ê²ƒÇb*GÙzžyŠX»ÒIáò=º>¸Å·Õ>t¿$«ù–›¬F¢<`Â0‘ÑŸ¥S‹µÖØžJ”ì4͵jLŒYÀ§Â}WƒP¬­D’éá¹[s LÔÀ{lUŒc´À™ŸÈPj7‰T¿~MØ…± )Ú±8£ÇÝ«ˆƒ+Ûé謰”0ª*µ9Žˆùÿ›ó›“žBÍ{ZqA#QQ=ú\˜Œ“¡ÁÃhù—KbKÅb´·Â³ýÛB#‰yï=ÝÅÓ"‰Å¿š]§ÌN;D)±Òß%ÍÑ­ÛÐÊ­JŸœPб­Ç¨}:;¨+åÝ*X—Š€ÿÔÂÙ¾œ4»Ä/ê‡7ý•½±Á¦¸±½GFÙû)º§Óñ‘4µü€%ùp’ÕÒ£Œþ¦¼o¶£`½rÄÔcÉ+˜l]F¹>œ†ÝHÌÄ;½¢×¾’yK”Où¹Ažðé7}C­½ Ý£-ð݉ØmáBŠHF”Ê%s€ÝE>_D°9û-¼,|ß´Œ9Ô}KpbbOÑÜÝ=ÄQ‹×XÓ¼¨#TM"äÙ2Ó·Üì—­kÃóE¯—M”Åb} ¤…=šå‡X…ØÄÌ—LVÒX¿–xã±¾(IÎÈÚjÇTX}Tj-¾!^ŠK°ÊÄ÷FHŸÙý“ÆÅÒGä+½ûµ‡_}7ù£˜]jØ ÀÒ¹ä šÔ›8¡ILÎm>½…Á9 Īr@²þU†6žXÆPÖ3Ä£X•L^±=¬_)óVô›Éñ5ª,à˜ÊH«x[ “ÈDŸd¿‹µª¢M"ªU ü¦IT;²rbéõFz?moÝ@Ÿ‰ØÜZyû²áèù–Š‚¥­íˆ×VW3E%WCš`•ÄéVbyª©°YôÀ@Ù$ ¤¥³AcÅÜàÁ r¨Ä&>Qa,ž´Û&(ÿÙ®,³1UAXf AµkGCnd’=•ía®ET7…(;0„VÍ¡ÏX¥QBN4AE,?ПœX¤Ñ Ø3“Œõì=ùeU^ÑÔÎêe͈áiÛ‹3Öä»”®„Gœÿ#Œæ\k9zèÜ="‹¥Ùƒx@ ƒEõ«.œ™Ê|N*UýYVeûœÓª¨ (Ü¢“”kœA LëLÖ40g›V%ÜËôÙdé›X“g@àŒ"éF¼;M`ê®\_Úä’IóÏÊ$t<£ÑüRÜxž¶ÇÚ%ÛÑV ‡óVŵçÏtþÈv'ÌÚ9 -]܆^…–]ÿ¯¾_AS´_ì…¦LæS˜ÅH€ÿ¬­¨!ž´Õ¾Ós ’à¥ŠŠ˜ãKÐÕl0âÍ¡îY»hù‘t‡åüÃFSØV›ãX•Ë‹¢JGAåéÐÇU+bž¡Í0ª²R(Ê].‡Ù¦H‘×NoïâÖX|. ºŒpªØüPœÓ Ù†Ùßè©_Vµ…¹äãSÆâÅmŠD¢ ´ùÕÓ×/åO¯–>« ni‚–¾€Ã) 6Ä_ ØkñÀˆY¯\UNˆJ¾ÒêaÃ$²A侎.7RE¤!üB ë&ütb`0G&•¤þ¼9¾>mŽþþLè3@æ-ŒÉý§Õ¤ÙŒnžâ-  œí«¶`ž¤ßÙR4ŠI%W#5EÜí¸¤ ¹mŸ9X1y3Ô‘NB‡þ€,ó¼“Y𰧤×?¨ÇPÃP!…¸ëÍëG[ëTV¨O³‘ÌÍ.Æ]WlLšJ¹Fí+ÔÞ$pð¾ÝÔOÃϨJÊ2*6È¡.8®(óTè]]Ït—4éì®1îj²=Îo3éJ֠בڟ)šEasOà³à#õúhÑ“v…åµ,B|$Ìí¤Üa– c0”Ífã(‰²ÉŠ(ÙyR˜ÀFûÚyr Ñg§^d+IŽpx|©›^\ªu¸‹?sú¤˜£V¬à}¡^83ï‹–—^ÓrJ­•zhQ À’MΨʬÎÅ÷kÝÛ ÙLà}щwnuÛÞRH#ö)¤þà’™š<[y'™÷ƒdPv#¥Îv'ÛHß¡…ê­=ÚÕ&ÞdkmË%•´ R‘ç. ŸV‘Y£ë“àz¿Îr-çô5š4t\ ï‚% `KI‘±º“£À»Ô@y—Á®vaê½:ÐÉ8ó?ÈÅ; iÁøéP,÷^ëuu~©ïUYnÞeõ¨Ü%õ{1©¨}ܣϊ“.|¦çZçBa°¶›\?Gß\tžÈ¿¥îuö{ŸL_-u§,äLX¹JÛxAçuúôZTø§–ƒ_f•"ñÒS%ãRúM ÛN÷\A±¥1½µdŸ9Jß“FãùèúÙdGV2Ÿjb«Fm]¯¯œ¦^V‡éºú± ¶®–ãfÒx€?ŸÀ(  „>!P@ ýˆ"@£þ-?¡ÀXä9óÈaÑ@:3~Á€Ï¹dp ‹Ê¥x,}¿'SY@|ö K¡ÐéDºq!É"ñy%3‹MaϪ¤f‘ ¾gÀxdéùR§Ä!É%–)(œC$qJE2)5Œ×¡ÐËLH“ĸ¼¢ç’R+ÕÙԩqRIE"ï!‹×«Ô¨´n9d³Ä#7ð¢Ì¥ÔbUý8$•[€w¾ª]pW¨P‹”#0ÒR%GÕ«MŒÍa’êô_‡œm@9Ð#^ÍÂ7Q 6ÆukX(w؆;¥!å^_»í„>“Ú>ÙÒidC62ItšÏ´Ó4’Š¢Ê*8”WJ³Sçô¡R –ò%É!ë{ÀuÍ@ÐªÉ ? 3±Z-lH3ÿ]·u¶Zè㘯¢NÅQi*¬Ò«1vÝ„¤¬#êÚkyII-i^ŸÓÐA½Çí£ƒPm"½%HÌ®„G@3%¶ÖYD‚Õd° ’Ön\Ïr\mžÏ¹Ñý&ÑâéUè²p­ÚmýCL]ù07N{‚ϵQ®™&ϱÞW^iJ\JÿénÎ"„VÎp(£Q‚-Dm(IÔk.õ‰%`ÅÃIu?´"Í»M¢öÆaxmò± +Ù®v]œ1Aã6bY~ÔGê½½K6»–×#Âh{¬Á·; öáÑnÀ' ÒäûxÞ[ÍdëÙ  å¾±bP•9\!û œ¾Å?Ñ¥÷¦Å_ "]Ll€"/+ö‹3µé]“¯{æíK,5–"–RǪ–ŒÁ!¬H#N‰!.]‹É$F ”ÎÓ|$…e½2ò†ŠÙ~Íñê9”¸±å3O¤²®ß #gnqX4â—á1÷QÊ)ž¼âMY™£p¯Œ…§¤ÂñŸ#0¬~·Aþ£ÝCH-Yê"dáTñhÉ…0?wVãn~€©)¢$V_ ¹`CýÿÈŽêŽiÎwJn'óxâÀY¬Z09½#Ö¡ZšjÏ~8ÅÈÊE£B¿Œ©N3önJBÍe XÁ"tcWóõ'QÐòCƒd¹àÜ9>dp’á·%Ú!EI*¼V0GÒ oeR‡œW"ÿ–Û-‰jy?¤ÕC&_“RÐÈ~’Elô$YPÇÜà¶RnK Tc<…;“f„E¹ØA²Ì,è~áaƒÈQ*(Œ•¶Âïå5D0Þ'Ø—›Zdi)ø7S\GCñ#*RY7â´fsÚŽ¦™DÈ+åÀüòí)•¹ämãp(ĶH2MTiuáD6CI"ò<íÁ÷¥= •Ùe”Ãþ€ÀémÛäìŽÈ†VJtüh]úŸ‘´e?žFTC”Á(y`%‘’É‹2f<±i±IXÇ&Ü’ü¡"Spª4†ý ÊqªcÉþ –cÄMWdKd«˜©†õì¨èBR*,Xe¬mÓ–‘·Ê&˜Ÿ¶Žn™¡æ+* Ê,\I€ìC…lMJÚ])ÅxÖ,N$”œ4û(ƒxۡܺL2m3Ã8N‰É'mÜŸÁøµjÑÛ_nLT½ `­o4ìâ¶Á˜ôc…Ú'Ð`«#úƒŒ•zÂT¦ttvµzÈ¡ùÙUO¹Eg|’Í¥“O'P„M;VçG,ÅÕ8DgL>í„YŸƒúÀ€Z\De¢ë–wëÁ¦]Q×9•w¢dAÊV Œ’PšÞ¶âç‡ò:nâæËJ¹\ òìµU©Ì©Š¡CÈ).`Õ!¦ õ­MY`:JÈ{˜ðœËåY1„`êÓ†!ežVŠCÆDÙTÄÕ'ÈEbÅÔ¤õB¼…zD7›PZc··Ñ,‹®ùÉe¦'Ʊ½ª"K1òž2F©`Ç € h-Åî¤,>¸§&«œÍvà†˜(† ÔQ%¨Ãˆ´ªxœ_‚ÐK'†´‡}¡©äõ° !‹ùDc|ÒN®¤Ã¬xå0jÜ ã~Öö'ò2o1ªØ€™èƒVáôßkaSÓ?eQþNf¡+90LbÜ”žRÂ`FõŽÆ™ªÏßðãU“Ðá¾:̯6³ý²Žy¢ŽVû^Dš“-™É"jÛ+4¬+ª)“&¶'í/ívÎŽLMÚàx–žÌu62`³qÜr¦jÚ&ì vY› c—¯™ºÜãTÞc-+lNœDÃ2¢´6³n.¿TWUžgv‰k-4kðÖøJŠÉ[Џ ]MÃtü "„áÁÐz‡»žŽîRRºvãªÑ|Ó•äÈîº+3rª[ŽØäŒl±ÏL[SÆ4ÅÐSËH´?RCÏ Ç*²HFjš­[KoyϽü)ƒƒÔŸOºw>ÉNÒŸ™Îñßí]ª§  ‚lÍ1•6ÝT}0íé*“†õ§©5ݱ9®°0Y7 ÔÓL¡*³üÞ>ó‰C‹¬O ± |;>Vo©„ÓnI`x ­m¼Èið˜Kž˜X›\*Šº_(gæ’µG>é°©÷òG×?šÙ0(‹²B Ú÷°ûEag§ÏP懢äL9¶r g#æÞ§ÙKßcTð’L“‹!ؘ2쎌<­«lTòòóG…R>zX™ Yªš3Ÿ«jý` ¢ØÆ¤’™©þf¨|-ƒ›UžçgàªUá“™°ïkâiƒîr¢8V¶‡ ™ÍNìmÊH(€sîVÞl²N(02ÆrЬØ` c˨uؼMÌ6ë`Õ+ÀC…¢‹<"Íö˜ |nð7­´[!ö¯-þ0óäÞ½)¦"ïÚƒ,èå¬0‰Ä¤RO|{‰Ìn¨JL$·nP©Ä¦ýG g0~'ÜcÍæCGš5Œ&¨ë„h¨äÖ Àå.¶ƒƒLÃÏy¥) ò"|Ž©²s/·‚8}Ϻ¯Â$po‹`‡ƒxKP’i°°½Â9MdlPÎŽK-þ%FºÑ,3é<>êfjJúì ÛbññGâ˜PbÀñD>âkNœs‰¤·G0J¨Æ‹¯þù&‚ªêäHäp%Ú|"kõG¶L\k¯8¼‹µ¦~Oë>Q礡fx~+Þ³è–Áç>cQ†~΢„Ç: æP¤®hªÃœ!ƒX‚&P¸¦.‡ ¦Q ¾Íšj6mÑÖo„šôo@¿¤8ïðŽSì@£¬Šýâþ‹°ãë†?…Nk¡É ½O~»ÊàŒb²@Œeª¨w‰ðãlàÀŽ4„ÇÐaRšf,ÊŠ ²6qGÒ  ám°¹ÆÚ½¤¤eäÖá2SÃÉlC’æ?J ÞH8«ðd3óûm.tp¡ è:)ÈtÃó8ê‹?NÄ$†º¾±nn«0˜±‚¨¯ææï ÑO. ¬—2.  ÈÄp­ÆöÑ€ìL O¦¶'Èôˆ±“NycXOT¤Æ ‰pSÒ’ÅÓ¡;aüöJýð`,dþ˜²;„"â²ÇÌ ³ÌÌR¸ÝðJ®SŒ¸… R ¾ä­þjâr'Jf¦5 Ñjt Š”VcÍJ‹hèÆ±\‰]HcHíóÊi¥Œ_Kç:Ú唚®.çB*L™aòÂ>¯}²a;­”΋`ˆ$È£mÅ>RË6}>­ÎQOù GƒëK”Yë<‘= ÌéxÙÑF‰l Úh]çÈãÀ‹°,…gO¢æ0³á1e¢íCZ"ÐÞð®ð)t0ÞsœŽ¦ÂÍRî­æ²È¿"¢A(QNSºWG3jM;§Jͱ-+ªe,]G B‚Q¶ KDT'$ºTæ3ê6MðÔ¹˜)">ðìÆë@BäÈ%ÒpEBÃdMO“ÄÈ4…C1lÆ`Ë𻤤QDßõ¬v™‹è)Õ&D)x{g¥Iä$‰ü’1:…X‚µÅQ3µ&³W·uÆ’#¯er`eJEH?RÑÝ1Ö €,ô4h¼´öx0" Œ¿nÈÅÅ8¦¯ÎƒÈ}ÎS\‘T(Æo‹0aå°!…1GÀ Qô>çr10H8Oí cMË`¬äШ,¶:…K"Ãxu5d190}‚ÆbvHâR Ö–3‡¤õO ÉJ*²éÒ6Î÷u_2Ä?©Wë$?¢(Iî)È®#è–ýsá+æš; :’(¿.¤X`ÄúšÎnjDÿ|3lähä¬çãv®ŸR¶±1B%ÂöQÄðO’I®t…¦~PgìMô8F%<4ц³÷öj‰ÑHfO²v#…0Ïbua¢.ȃž'W%VUâ+œøX@Ù ”¸Ä›)N,¡KZ‚¥Žñ… ÈxÐ,¹MæH, ¦wôÅkÍ í7dK•5' Þ0¦ÎŽ´)Ó_cÍÛWc”%ÈôíŽ)‚rCXcCnI”4•Nð3«~"Upò; wÓEnS07õMa,¢"WfÃìså0åÈ´W•ú£óx 8âXÈÐe®æ–{q!FÕ“LªLäÌ«8uö½o¾æ‘¯)S»1lª¬êŒn- âŽe.N†á¨EkNÌ1êõ0Ú±Q,ÙªŽ¬ï>äêoë|3äú4Ôs ¤J”Õ’4Étx“„#ó&NæÌvêyelD)i>ä¬%•ooËÌêy¼Ç›)P»~vI0£Å—àFÜÕŠÀîx*Ò­‚£ê2AØÜl³/.otÀ±“ðË1‹£œ Ë‘øòÖGNs,uëuuœT)×¶+ Ác—œw©‹øTJVòÓ6n¢¼N«1À0ù EŽlÜÎMOç «f°r^HhîCH5›Ndp»ªíØ7[ì^M²Âï>IäÛÚäöpâ8tê²¹w~Îî ˆˆ¾ԤDz’) óHwb•æL6—nÊܹ×g0JOåäS™ƒWu÷:ð- üL’ÖâàoQ"Q3(]Z€[v–PuÓ',B)ö „çxF'­™/ȹ8»6ÙRë1÷Œ²axMÝhÒ#>VQñ7+PäŽTp‰7!u)CªˆF<+3Q¥£)Hy“õ¼oW§JÒ SëºGù 2²‚2÷¥ ªìJH·~šL(TìLk€âTjDÁN§L«~9o—” B´ì?síå&' ¢ÜÂpÇÐÕÂ,VÐd¢¼ÇƤÙÙ³êdyb[Ùû”sEfè' ¡÷”ym²ºgĤÁU,d§v(ëbÈP¶ÜL¶]9þÊDykDfÂ@ajŽjU>J»Œböu (l¬j"å1´zë&—ñ&ZBφ Šf¦8½‰žöäœ ÇâcPÑ D"9Øùó®÷ŸÀËà4ÔJ]/Ð[`lUE«ùL™ÄŠŽT§¨È}Ä•M1-û›ÑÊ …1}RžMpÂéð Ôa“ì²%>y{ö5söpÑ›öïT‡IaúŽˆ¾^VP&<É2:&¥mWõ4ÁZ’`gåYrͲ²Z8ÚŽ¶£-ö,„Ð¥¸"]¾›­ì‡0+Á³ïꨟú”#”JeN½.[̼ީ&˜“6µ¤bé`£{Ò&»Ä 4E¥ž$%ÑŠ}óÈÖ~Þ¢%!c¬* )ïê¼½§¬ { È Vñ_‚}hç æ\«ßOS…°áQk‹=1ç;ßvˆÜµSƒ–¹h\FkR µZ,g삺X'º‡â")o a–bcX±`º:ÌEÙ«Z‘Ý!6–)dq!ë(ÌhoÎhzÇš|­°í+)‘ñâsü§9R  Áá7ü-õ „âè”"%?#øƒÞ9 Æ€)I …Â$ -Â#ÒÙ)—Áß³˜óîy$Ìe±Y„-ñEQåR*8Ï$訩2G s(ñTB!—íjŠÀëÒ¹Š*·H!*ô+W…Ø  D®Lÿ¼Ý"S'Î …Á¾cÔÛÔebO¯¶Ì®ñŠÊè9]ž˜»ÎqWܦ‚Á`¼Ç£×Ì´NXƒN'5èõpµ„Wž»š^¢^¤€¢¶È”ú}\•Òïö]äqï>™C_@ž•Âv¿gdUë܊Ň¯L¦¯è¯¡>„mA—­f[ÂLåܧüñ÷²…åä_€ŠW+ú.)k2ú//êD¾¯*Z¸¥·í(е)f£(é¸ß# óx…¹(#\‚1Là1P€¯>‘ e ><µ²iÀƒ´é:ÕC¯º$³"ÇôÍ@±Ú-2GìJ•¼0;å Æ@ ’D0¬AñªÀÇ!r:¹ Lªý,‘r‹JRSä±I‘"™>‘c¼ª/±ä{-*ª u ¾Ióƒ°ð«ô±>Çú–ú+Êš¨ÃÏ(\×ɯ”Bݳë5=©ËذàU38É’ = ÃSÐÃPå;;±` Kðl³Q@Òå*ùMiåZü¢N„|¡£ð• 5gô4´Â2« ôPé"*®&I]91/*²0¬OCÜÛªügXÒ ó*ñUN¾ÅÔ®ëÕä€O¢}B"K¢’3w‚rйB‚¹èjò±'΂V·èDQ;\îÛû„¼55A}\Ÿ¬SùXL7=IEÇÐõ@…¹Éj@ñ¤Se(~ÑçúÅ3¥µrÔŒH(­ÂÔXwbyc°oFÏô3´*òyK_é"=samúëUÒ‚¯XͲú:€ É*¡†b–ÐIå¢~UTZž}¼ÚJÅFðªó×yŸj”( ƒ"Ù£ÛQÅXÒɈ«èú)q:yšnx¸kpùYI>{ñöˆn‚ô:ÌýˆïM·³1Œž‰Fñ»ƒYß<ñ9-üo¶€á÷Ä·öbDð¤(©0ˆz&w‚K`Ó^‹+.¨pé˜ÑC+Æ"–â|†S‹­„åá#ÃÈC]»Øz-ÈžæýR+$¤ß¡¨¬³—<1 í¼Œ?èž}n}„T{J÷£D0R’G¨Bäɼ1O¢®â©#@2]w‹Œ–˜¢dq‰RÎÑ®Ìxl”ûû0q‘žø-]ÃÿˆôŸ7òF"@iòJ(R1#(9„h–%sñßdÆ)ª#yLHIñ,ŠD&0œR‹œE©a[å–Ë‚ët/© ªê£( H.&5Í€œc3¦/0…ìŸ$=\V@ÝWÍ%ªæÓ§Ui@3)‰UÜnX U±WìÜWlr“hý‰#(|T?£Q$ûÝdV&;Wy1 ‹@Ž„ð¥Ó©Ÿ7ÌÉ(¥Èª5HENKÍ¢”}·„È_Ö´mɵšW3Yé:Ù¢R¼{5h~}C2r±’PBBrÌQ ‰ÀAø·ê¹v¨j^ÐH¬†k¦GÔF7Éz J)j§¤.vpd.?Qƒ…JÑ”Y\Pñ öªˆÑ\k|@£kM•>²˜!Twˆz-·’™Xų–¯™9€CG&×-§rÒ  ©Wo ˆ™7Vufž9~Î%­)séc+\Ì ‰ªÒœd¤ÈdÕx•t…¹„òï¢8S8muqõŒ$ä=ÂßZºì¦J¹¬ü*°E*Ñ’]Y|œ«­µF¼6pÔ=Äx¯Wb½i][•37µ/dyeWÍpQ·>2`B œ[ ޏ>“;LØ3D¤ˆÃÚYìF+ã¹ò';ñ ôê´+áŒh¹›UlF,™>[’ZÍ1‹ÀQuÚÆ×taæ$ÆÐBÛÒâOv3N5FÀß3åJßšKª­0I˜As¬ž%1†ªf`5릶Öá¼­û¾¨Ô5–9èó|oý]îYÐ ƒX:µ‘Å µ{vŠ¢DÂPa‡PD}‰•\ŇԂ¢ ž®îæšÒÇÏåP·Î-]£ z|ähʘ®ùÐ/à„O’û&•Ü“[öµ¸ª»ƒ¢ ‹]xñ{”y•f©›è ë5ή³Üt™Ç¿UÑ ®m½ äâÕö@‰7%bõ­ˆ!,èOËÝs_òŠ@oö©DdÖÀµ#d飡ZÎñxÏHÞZÒz‰ó(k õ§&øa»ÈÆ3uty„M§xJôÁœÄüÞEcÂùÇü‘[Õ_±„À{‘a\1GB&c‰¸@Ú™ÎeqÂR@ÀÌ;…—䑾>¬=§ˆ¿èÎ-»Âìú?&ï°”JM$ÍíÅ©éED¼BêÜhQM5)l1RIw5¾Á¹`¨½¸Ç•]èbïl÷\^?D•sT ZÉVd–|}µÝºœÒµÖíH£ò‡½ÙÁáùŠª­k€B+Ê=“ƒÄ!ë9¯[n蘋ª•²ŠâPkò(ä#+—÷J¥§T³•L^59Þ“r(<ƒ˜Û«Lb¶Öåk‹Êm­ç+ºK9T·ÃõÊNTÈ Oº—û}ÔÜÏD5ê«x4†·â€wŒ'~#{C{t37$ý3B=ÂÓ•'yW}@?=qƒÆsú »:›#8Ò¢²Yœ ‚°ãƒ<*¸®JÛ ú†(cá.˜Ô>ã6Ü ¤ É7KÄ•ªh¦ºÇ&‰"&¸Ã¹p èæ ‘œˆr°¢»)E§¹’>ø€3p~ Ðè;g+)s¸(~@ŠŽƒÜ {š:Ò£—0¥µ™³žƒù8S¼ê[€* 0š”t¶)ò „€”(ÙP­k”„Ët· ŠXkÃXÇ–J¿Ø|­Ùö»pŒÑÊ´J“{»³A‹¼ ¿°C„(“R°)"ɧLI™ ç¼yü®RÖ­R̕ں;Ù16*è¶F*ÊäÃ󕬣Òs¡sç¼»J¸ë‡ º| #bš¢Ç¢ÄË¥»º»RÁH})ç°±1=``®‰ë£t5ÁÀj™;( £éÂÌ ª #A8³–”ÁLÄØ}Åã•*4è7:«ô(˜9.²q˜&Ûbh¶‹qÞŒ/q!¦Ë³ÂÜ­rÂÙ½ªÍ11/‰j»3Ëu‡û&Š:EAä«ÂAH É"GØž‰"½ «Åµ GÒhªÙÜŽ\ ¼7“i1 ͈`†¤Ót­ ¿1FJŒÃã@G:ék9ë”°¯aº˜“>¬A0aǬúÄF[‘µ‚õ¼WÀˆ8ä:¦Ù‡®Hæ Z&>@î<;!:Tе2k Ë< sÁâI°9ˆÄ@ DK;P÷¨S¶$0~@¿“‰Š:µ¨‘s= ©™<‘£H†¡)W5œLÅc³–?‹è÷#¤™@³Ó䉀Bß$ƒn˜»ü©\Á‰G°mÀÑ‹šY‹Ê¸>˜ú5aÒ ¯Š¾ 3™ì-¾+j±A÷´­›2÷ºT“)3¯ D5Šhžq05)¡|¢šË✪••Û#I“‰¤›¾6+`>ñä‚É’`úLðž»W4~9S ‹ru éª4ªïŸò½ìËÁËA)´Ú;ú¼‘‚¯³µ¡’´@ñrŒOœl©2'Î4+%Šm±”ŽÃ‹\?Œ’¬ÊÖ¶1Z;4Å ãéÌ“Ë ,í8`¦ÚÒ>¸†¶¼_œìyû®‹ùD|MJXj˜0¤v»Zi¶™T¹ÿLªΔ6¢ rÿ5,Ì;a„–ümLû6S„–$°‚¹FÓì 13{F4âSÒ”­˜!¤ªà|"`®4¬_=] ‹Á 3™.Äê] r<;;ÀŸÄöˆ´%Ì‚MµÙû3Ç»aPl±¤ÒﭔʢýÊL72ZÌ!ù&7KÊÁ¸’/‹g¬Ì{‘dÿ‘Ú™‘"SÁû‰YƲIÒ»î4›œ4,½,:@ õ%©4{˜JM+Œ.‰Y€jлKRÇrr‡ÒoȾôÕ|\–/»¿ˆ²¼ÖÆÊ•²Í­–ãyUôšÈ§ÜZ0Ìú³cµÄ,2µÅ–¾êÀú…S¹bÒÕ5—1ÉSÆõ/-f×=vQU«ê[\DN™ÛEs ñijœ©W*–ãhˆ“夰}¶:ž?bÌ›‹Ô íu©+[$¢Q |&-+ ŸªÛ®Lu.zïÙ¥``b¬Ê¹¯WÁ "eêÕMÒ¸ŠB[Eƒ³·HðÄ®WÅÒJ Šãá;:Mb¸‹æX ¢¶à7’—W]¢á-ø4dƵ©ÒÌ[‡ÊYÝýÜ%:MbIÏá0E|álþ×T9ŸfZï´›Yu•×Å×@¥‰õkçV0QÄæ´|–B Ï‹‹¦À°+ 2åø±9ú¢ìL:qѾ-­Ö“¼ÑŽ&»˜(Á¸µ(ÃØ0‘ 8âÍÑÄዯV2»%¸Õ¾k.s¥×K)¨ÐÐ|¢Ó@FÁÿ\@ÉSèWøb„ÒÏS°Y«ªßu)?R•-ZE³TaøŽˆXô™öZ\ Sö‚J½^©æ2IŒj4dòªœ9º‹$æÚØ yåõt:œ ®1èkY”µ¢çNf«Ž:¤ MjÅÃÿL,Q‘*ä+`ƒ~:íÖ ” =p,ÒM=̬µ¤„벌=UÖÑ ¿•1­D´'ͤî LG8ˆÜª}]A¶dWæ<ÅJëEÖó­]ËJ•qÿ]Ð] .¬EÙ1áë«¡ê.|+$ÙbúèªÐ‘»/©2Ÿ:k\¬`žl‰ÿ^ BQà¬+\Ä =9'žÆÝ‘ÊÞ ókA¥–9WkRO¬ü+•05¥Ó˜RB=ü»#C"i­ÜØŠ»UIZ³@|—”o“»>è*ûªÙ^Â]£LÑÜá/¹H‘ãêOrÉ’Ë<ÐFóì‰&8˜IÕsK ý>r¬‘÷·>„ñB¹Me/óÿœ±KDRµ]eÙ“¹¯ÓÑIƒËè¼:q])“50¿TáAõ_ÞT§·LBº:–$[îœÖßb Iº|GW_൚+=Î1 *4hû¸+6£ÈÁµ®mr[Éi½B&þ ´Éì‘S«Ä{Çðsôp¨Å½¦ÙØÒ´êðªæÇäéV0£®ËذŠçìÖîPŽy¿Ê?ìoE‡Å`ý;ÃÏCT+g{Òp²4¸‚·â>Aej÷M 'á¸Á³âž:IðÅhdÐÆýtðjv-ëd©ÊÀ`>¨<¸Þê=ãjOñ‹—4áB»Q5easZv´+r&ۈâbäî4ŸuIÑ´ÐögtÞˆER“Xb‰ViÄ¢Ä)Ù³•s5v—2•Ä8”™¥-)zŒ+³'4ŸX(Ç|"õZFB[Ãì@@~ìöÙw}¦Y–-…RÁç,&ÞÏÄñ¼2ŠÛ´+ê‡öbôÔ­µ6ž-tM± vTh†è Š:BÌ™•zhx’Dhä4ö•+’.‘dÒ3*ìà‘6,ó–Û\„hò•° hP} “—΄QëRдc¹¹Ã“~CÑû ò»G6Üv‡Pôa‘û!åg ÇÛÐþ#Ýz'ÙD‡mwG滼ÉÃG¨Ñ*´&Ü ãÈÏjp9”­½óç£Ñb寷íê€"~"6F† ,ÛËS®xèz»9»³éý$7¦;bºè=yW4¬…©1åà$Ö'€†¢f'¹.W(e~ë7œ ¸axúЧ€D Íjpë±-[ª Ö±-íñé»-¹gÓW& u ÞµJúÛÇ¥ôΕ‡ÛÏœêèÚÓÒqž¾(Š•ø‘@Sþ˜NÈÒgixÔ¹Me£5åL؈‚A`@+þCaÐpE÷Å`°à$f‚B£Ïø<~?dÐp ¦"¢ðÙ$Åù3”€cÒ¹3ö2ŒF`³7äÖ ‡Ncpˆ "”ø¦M@ô÷ÕF*ƒÓ9è AhPHtM÷+šÑdÀ›Dæ_G¡ÓXô枘€(x4 WG¸Q&Ýõÿo”á0ëÜ6s+¯aa¶(=ÎkbÎf´ œ\‘€+ðP®ÝœÙ%7x–þ£Ê&²v¿7l¹ê E†'ºìpS7k9–È¡S]ô¦ Ä˜Ïæx„ ±ÆA*/¨.áïÛ‡PøÏþ—&Þt³¼ÀT£quþýU³‹†èkò‘ší‚‰d J ¹¥n+Šœ¿ Ô¹MÞ¤‹1ú,J›~“%o ®6©›ÊÏ1Çò •ºéÚÄõC°: !Êšr»ÎêäAÉÊ€µ ŒËþ™±ŠÜ îÙîÀi*M5iÜp,LÂ+€q€èr!½(‹¯¢¯Cœ~8R¸¤Ñ #£30µ¬O l 'l4“1²J­ ¸(ôŒ“Ú7¡ªœÙ¢‹?±I3áQI#Œõ6,ÓÈïŸìºfÿ šrÜ,M›©Ì€,Á,Lk_O  Q¿GóDãº-bÙF/}P&¯åjáÑ|k1 ”›$U¬¥W*ÉÍk† ³òÚΞ¶šæÒìúŒ ç͸šÐ r &²#9#Ñúñ¢øE!úÖÁ×D€=_%r´ IQVò+ ¢²pö> Ý0¡M0­ŸÎ»$”Î¨Š û«V äøTŒä‡<2ÐáÊæë¼*ËØ£Ûçû¯zF謭¤Hu¸|Ö÷*ü`÷ËV‚ÄhÕ’}ªo ¯t[ $K2¤éŠÜO,ý$zžj H êâÉpã;$"µÑûg£)®&–<ɃwfvuVêP™å£fÖOZ/€ÉYç¼¼/å™ZáÙumWº{=ñ†Ø8t:‚æ©ÞC #Ï­U{aÊ͘ :ð¥_tp¨ô“`QŒëbÃpâö\€yÖˆbf¨*§‹pj@±f÷Úk,¡«™íÞö‚# ^òÅâ•„ÆÜ.§9 Å×ùª¹Ín w“8=éík J²§hV©^-4zM "¾Céº"©¨ ªÙ ñ®4¾>é¹}€§CÂ+æ/Rêí‰KÞCÆX“—bDι±dä5b©6$S [Ö"n”…A†žŠÜ*o‰®4ÎIžÐcD‘“2ò[Fc€˜¶×ÉKË8Ë©œ¶¢>ÃŒmÏ™ö´²³í† /ÖäêMì:J±50ëSAÆtJ¼ùšGnæ–1Þp®µ()Aø¾ßL##Ò4èÔ„!8*ÇÔ©•fŽãÈËçykA¸®ZÙA%0n&’ÉÚ$7k¹•eêäZÊ9Š ³AdŒH8§yã6e`[ ©¸sÎØžÅþæXQu®œš³U™”ü3§Œ~Å(Ð= |IR0Iƒ³"?£0t†‘œ— çáü+f§„ÁEÈ~›ˆÊ,$ÑĦe9$ŽòKÊù{Eå0¥ uinÒ`ºÅbæ"D+‡N䨧"vxe„$PEĽ6ÒÜ!ôê[Sˆ,‰lN§¼›Y“ }NDä³ë ‡ÅMÝ7 ’N¹è‹j½P’™iÑÒGŸ¬…šÂYZ œJ)Å<ƒuIâì(léP™°ÈA  Šµ~©ü%XÊ{KÑf¯ÒoOÀNdÌ”> °š˜JQã 5›éìjJÖ<Ö3­våÔõ*u½á„ªqIZ]V˜õ§àΘ#²R¥›‡$¤±?³øõÀ1G.lÕLg#>£y¥u>wCób—Qr 8§±RøÑÌGŒ’ºžªy-ÛpT†®Å&R¬f©O|UÂгŸTÃ.§yжÇó7Nú 7³…ÚDÅLOdJ.±µŠÈ!÷̳«v“0¬÷"‘³7 .Õ_ Pù8$É: øµcªÜ¢o%ËÙ†rTßsö±¤z‘*ºÆ‰Æ°¤5󖶢ؓJ©"k°ì Æ[s$)u=Œ|ížbTÎòâãØÅïX«§†}*c ë8(¤™ *fâ»'Õ(Jv€«)²Ü?Dôº^óH#5“ÑÇÖsfe&yŽ ÎÊÂ8ó–†T“Uúwƒ«eî$GÅ4F*ŠXbyZ K«W1‚N´ Àƒ©êMUÕUa/$Û_(B‡ãkX'ð ºJÙ 4[™u ¥WO©†!Dä뛉R·±¯ ëß“xH,³º‰nlC2©#¬9ºnß äò×a( ü@÷e{3¹sXe)9RÍzêCÛÀ·IKC81ÈcúÍl3øT„îi` zîwµt£Å*ÒÂÑá¿­ÐϹ•˜é¬šrd5t!OG•}-lúç\[h}¯ }•äú¬Í”ñ4Lj'²Ô¼0IŽÑÛp ~Ô:ÜI±uü¥W7l1Ò”‡Ý"8j àûš>PÑOÈÙ-÷“<)R+È0f°X[r©¢Jãý•¤ÌöíæI"²ÖïhZ¡¾ÜáÖòT£©òëôBuºÓ&WâÐOªÐ¹<}¸D­Ñ5Çë{"->Råd®¾æ9ÁÏÚk'³Ÿ.6_{k'8xbàˆU*%ˆ¹°ì‡m^IsH†6 Dà5 *0./\—dÛ›Tö…6:Œ?R·#-iå¢/ +nûsœÒ–]uÎeÂÇ„FÝÍLÏñ÷#Õ’%  gï©ÞüŠÐžY!O( Ö«Ü¥Ö€ ‹[Ôf\·6ÿo“J÷ïÞÂ;§•ž2Mx ¤þ|Âèp£ïbg‹ Xû€Éȵ½’¢z¥|¤š ×RxÐIY€6`Ox  þ„¡OÈ` ýˆBÀ ,ÿŒ#PàXÄ¢ØÃþ5'Ie©‚W)ŒH$±èäžü‘ÉÞ³°$ö9hOª$zG Añ(0U›Èé²Y¼zO%–ÅbÕ„x_}Ød¶ÜŒg‰H(Ò8„Ê3‰D£’Zlr]+›È"TGÔž%O”G' Hö9¸Â1‰ {"ˆUbÓXÓç-V–E$ø;$¾í‘Íðsø½¾a%ÈäÝTS7¬E11:Ô~)%‘ê7YúÎj5€Ø€pp금o0r|ìj„‰Kñ°ø…Ö|¾WÁN{ã½ÏÁåŸ3~ÔžùÏœïã?H)§¿c5ÓÙßß%¾Gÿ¾Ít“#l8±¬(’<ñ)¯ØøŸÏú®Ý/Œ@‘·Œ2ç¤îñðÁÂ)êF²#Ì*1IºÎ©Mâ› (  ཎJñAK#ÂË0l¢Ì€+ãÛ PR@ñ;LÀ›ÁíD$ß”œÊÄʉ² ¨QB¦ï´°¿(rÈëK⚦¯’Ð÷·‰{þÙ¸/{g"Q²zçÆÚó&$m›¶i¢À&î{‰:¬0T ‹/èÃfµ"Ëqÿ€õÉÐmÒFçÈÍ‚bÛ´Ïû§JS8°£Ž{¸É)š,“£Ô*„¥$êBø‰;Pü ù%³sv‡HH¢o )¯B ñ8ŒpçžÖl0€K#Ê=©OñP“Ùê"N¹£ h$¤î1ýCXHdË)·,™=Gû{IA¢QÄ”¢°ÐÛM|ˆÞ’W ù˜I#}äuþ³óO É*P­¼¾V,ÉÕ É!ýDX„bUÌ,+è&§l? éï#Ë4{ ¡±Ól¥}/"W–ÕH䈪Z(Ø8Í2£7®¬ÓB§”?“Ò]#ð¤0ã?I:Ö?dœñ†FÙ« 7R$ˆ(§ªFžÃJbDÿ¸ÃE$›ì],J}y³“Û‘ â“.h@vÑM2$@ƒíÈ—ÇòðdC@:^Eqüd¡2äGŽÕÒ"nw•ˆ«Õ›F°iY«övŠ¡Lø0Q$øUo¦È A³\FñUÌS0ú«†±@33™ˆ1ktÃý·‘ŤˆÄÈLÁ¡¤N¹šã5rxÙˆ¨º'Z úøâï‡ä†tä2§ÈJÕƒ…qH*5(‰Á|Tep~£’}7Øøt¬’”ƒIí€@`¤!åt¸ƒ@$JF®’É Ùqù^S¶Hé±û*tNˆµT8Q»Â1D8ÁÈy²S¤¿mÊ™¶™)¡cÈ0ò’ £BC ‘RSÂŽ±ø‚4#”¬y¥@q¹ÿ&õ-š¶÷.™2Ød!à3ƒPKŒ¢‡!Ã/‡äµZèË ¤5C,Ub‡$[ØË9?¹B$¨jµbVÍ f©“”Ò@R”“‘²ÞoËæø·GÓ|g,:™¦©U H4žv°íPG¼ºœcÄf3öv<‹‡ì=jµy¿3Wvo!e%'³éŒ\ˆL¢Ü­$°ôl~гèÄm) /“nº?ckbdîUJ3˜‡}HÔî.+ŠÊ˜iÝK›U|¬ÇÈñ|è #˵ûÑ›ªƒ $CYN¤»Ù©¤D,ÓTIœojI´°ÝÄ÷§aÂŽæ 'ÙAAç9 ;P4ŒajÐD}÷i•î5BØŒ„è¸{¸R¼#”ïdD˜'®îÁéd¸Q|(+5*44›Qã4jî—[Ê0ÒäÕÔ?øh÷ÂV*P¯QD°P²L ¨F$ë•{Y7&߃Üદ¡æ4w)Øú›3Èà‘*Íd=®"ƒÓFH\ ?P«šg:¹Ë¶XPbódÍ&þ€C{vr›õ”ý²3Û{èUpÂ,«¨KåõÃXF¡<ªE,±ß(R(Ä;I¥€%3¤Eem$“zÁ"tØ’”·…·–Ze@T´…Ë:?–Ö jJð0D±ZK=Kšî%FÑ™¥?o Ûˆ;Õ ³:²=2qÔ¼¥¤1˜J6ø29ÖŠR0m%}áÄšLÂM̱žËcbªµ2 S¸2F´>I0'_~­ØªàµpÍŠ5€ŠHÞˆb 81?q<7üeœ¥ÿ¹ö"™Æ5›BŠ%b=ôºNøÛæ¸úª,Q³¡ú‰Ðf”¢ÜiÄ–|:JS{+|î;ÐbS‹Ï5˜a)«X°rF½û™›ªâÏŒ«Ï,¼†`gºÍ4ŒÖꕜ~=úç‹©—)Ëcé€lÛ\ÐÎËéù*½iræ›j½Éˆ°¢xa§¤Ó-:dljHØ—4Ûo$¯ÆŸùIMWuù€Ž{@0uЉWe˜³iŽAñìÓ:M fâ9þ²ß:Ñðõ󜽷<º˜†áòVÁG„—3€UG/´Ð9òÎö€}‡3ܮƫí'ƒ-—׉ÊlWcû©üãjá/«YJ"Å®Ã4>¹¼Róxý|B׬ŧáo|˜BÉgøn&èÇ2ˆ¢ö(‚8Dì<üAö¶h,éö·/eRîl|,„5‚ ×ì>xèòÿOÐ1*nŸ(¶šô“%°Ýï” äi+À8 H8‰Ì"̈åáò¦kæšK²A‹0ûfRºIèø°ŠÉšæfŒÓ¤4É ð¾cšÎìôßÈDäÔÙÖqÌn«T Mær‹„° žE(ˆpTæ®\à ðªò ŽŒ  Te´òÄ”¤êËK˜^‹iŠºb,þèÐfgºå]â0ã+²w ¶HÊCOj÷ãþú\Úe~êȌͧ&"‹ôט2Ãxé¯ÚžFø´­’­Ø‚BnALâw07«f"NØ‚î¨hHþÖ ¢ã´o‚v¨”<ˆrŠŽÏ†ÃE̼ .î¨a.TŽ¾ÌŽ%mìgÉ„4î%Kk41(ä„Å´ é³Jo…VR‰¸HÑ‚á1fªf åFâé”ÕmÃÍU†R,‚Ý ?g`Xî`× Ö;ÄNrçDFLô–jë1$ÄLòÎÇ(v).hïÒÔct[îe*r—ÎÂÅ/É äi„n+ôUp4ãHJc1–%þõ1¾Ö°TE$¾È«ORµ Λ¢;DÒè­Ácxoo@†ø‹&€}¨Œæhî¡Æ} Oþ¦‹½¢ ‰Cįk¦Rhѽ1ÌôE?cþ[A¯+r>\N†`‡)*i4æo¢é,0šPUáôHÉ®Ì(6n\±Â"Ä:…ððG†±e Àï+ c1yò^ÅH"”yÐXް²ÁÍBö¦Ã!l5èt¦Ü!‘§ößvh-TÜO„!Ëa ¨\ÌL¥&HÜ—!ü0oP“Fhúp>/ºÛ²0„Ó²O"ë¢6¬<¨šÌN±³ñ °É²ðâš;OØf‰²ä§À ÊÄdmÄHËí!pe é욀) ˜"„NmìºàðÄ”àI,ž5(óR%VHgz` ­:®¨O^ÊRÚêfô‰3>Oº÷§vËŠ|ÕPÌj¦rRP¼KcÄÜCÞc%±6þúâ4ô”ÿ%¡þ¡”ªÞHB»#ÞZ Þ¬T4¹¯F°”’ãH†•äW…(ßxû´$D’)4õúÌ´2a,==S®²o9^ÔW±žÃI¥^cPu+Í SÂo¯Ê¿ä{SŠNbZ!÷>Q¦mòæ‘5%qÊÀPÂ12"‘ ¸MΔ„I:³ˆW‹Èjå:m¶pŽ›êó`k°ÇÏ&%´pîOöÌ\R 5p­lRoR#ÎlãŒhôˆÛk•lf’¿ö' “ös –‡ÖÇ€ –? 4ðÃÇvÉ xÖ&êõN)Ò\Ç>Ó²G¡úö4¬e‚º“Ô¢8Úóq˘ôƒƒ óNYCÄŒ 5/5Vf@K + bßV'bræêRÔ7˜£I–i&ž‘Ô‹ç(‹ïa«¼¸×ƒyë«5Ž pžà„±n¸«C/•¼ý’2ÄN)UÏrm 2Éé¹Kwgsv$ÑŸH5Y*ïKÿT@#åFw2ç^³R8+YW˜Uâ ãxO#[d™ÑKON‰j4az CPòÇí78d€g)Ò›äÕrÊØ›5Y1ôä¸WÑvôù0à6pzÁäx™—V"Ñ,Z…ˆ¸êî«`O½VŠ ü¨%z÷÷[ø#²â{n«þýWlâ$ñÆ™w5­Ä¤‹ m2ßWã4Ó=§Üؽ È$Ý&"϶06nøY2©*Iª“3bµ«JÎÆ%w§Yuo”äý†pkÈKQp|0áQ‰Úªšo¸Ha1Äb7@ôÃö¼†\LmW¶ÓŠüêÙ6Öut†ú½„x»1®–«@jûª›‘ïJÐÑ(ˆˆuU:BV¡“ì´{V±‘–ã<š®”ûÚ‹äï„5îKõ/WƒßM =”Øwø’[EifÓÉG/¢~JÄŸMüöN×d©Ôùfºa6¨õ7âf“¾ô2Ø ü™¤L,÷ûC/tªß >È-ðF @»2 <ùâXáç­$Òw,YƒoTi ¬X÷kšjô=S 8•x‚M¼}rI4$î9ÿX¤f2Öß`ƒzxòJÈó` B£¼r0qÑm+3mKj%–ÅV\YeoÁ 71_p;6UµW úÕJhKæ[5¡™m „¨†µ”ªN†˜Ý@S8M‡–)„®et¤0(TZ,©šëÇhÃM€Ñ¯šÕûeh‹‘Õ°ï­E–öœ¡¬)?¯S'ÒHÆB¾drî‘âÃW‚n)iPáò_WÍÂ{~Â=éõ—K›° ^~æa«OÜ: ïPÀ­ˆ%t÷ K‹¼t¬¬;ÌK|¬|ó 7ƒ>G2ERøË 苪,*iÁËj¢šK»­ "¿ ŽŠUiåÑym¸±Úñ1BÔ&3Žã#í`ŒQämðX‚ I=½¦¤3JB{¸Ï’ñX˜Âš¹Ì¯¿%\Ü嵯õ13±´o>%tš«~ÐBVþGŠöé¡§Í0iÃôJ©&&¯—Á’tÛ½[º“U"¡£ÿh" ¸îƒ=¡HPý‡b #þ(þ‹DŸ1˜£ü‰E¤@ Iä’HÜ®) —$’àÎXÿ|Mãs0º7Ï"çìú}2™È(T)$úI ££rJºH«S¡“éÕÿ È'Q(#î{‘?«pÈܺ‹ Œ¾gՀР$Tb`-*!c_íô+ø"c/N©±j®ÕÂá²kÎnø‰bm©œ’ý¹cçÖ9TSEW±Ñ uê}o½HâéÌÒ[ ‡W$`4ºÇУöxµk7)ã%ù(uDŽ×âÖÈô.H‡?;è“×¹ƒì?4oû·KЇl¶³… å.à¿¢]ù×|õ}}ýЮpI÷}>M¡þ森ú@÷¯G¼“NûüÝ$ ò¦¬£¬ª$ù» Àª5L2Òõ%.ú„½#mÒÇ Ò}¡ÐÌ6ã¢z,±¬(SýŸÎBH½(Kˆ¶Çêž©EK ±ƒ—,êãŒæ(è´œ‰+‹à¸º(d<äG¨êž¹4("$Ÿ?ÒªtÅÆ4®2ƒžÒ Šd8Dj ˆ;èÚ$½!³ê©/<» §ì4[B¢²Â^Ô@I›.ˆ,é¬\ä: B%ñËJLçûtésÂ) <‰ß?7ó°?;ëä½N‡üf™Ìo»Ã5Jhc0—;óÈÓèÛý ±ì„œÜ"ÒD^̰ ¿8€6r:Ì4è³tö"ɪHïÁkH«¤Lƒtÿ?Ï Ç¾.Ât·°itøn[€…Pí=\ÑöÅD…R•’ ŠCÌÒg%Ñ43’ã`qÂ);ï ©5×ô†iI7þ{€2¬Õ`¾ìö9ü¡WˆRItŠÞ¡?ØcM€á ôÈYŒÔÈ(dü‰2¶L\—?Òõª«K€Ç?O‹ÓÇ€þ› 52²;X0mî/låØü«’–Jj¹g¬j»|Ÿè””†;ð{…‡€ -.§ÙèÚÆ±é3’ïDÕ¡ôí!N±û¶¨Sõè½_³TÕª®h–ø‘-íÒ% “òIžöð ½?Û¶ÄX”:kFixD´–o`&e‹ñçÝCÏäÜRB®)ñ½5Y4àÛ\o½`ï°w ~¨MÖy(ss”Ž™»õ„À}ø ²¸ÁÏœë]»»î›>Å>’5È2ÞŸ\OÅÉéo E`›¾Ó×bël¥ÎáëÈësü÷·Y¼…â½>™ùå>äøàHs7JE³´öAÇâ~B*Pƒý‡ê½Rç !ReW{˜xiåŸx(cÒr”ƒ€ 52Ô4–X "mAT•>ÀiØ)i¹Í,—2§â˜tlLò¶´<äÉÒÖ6íX–LKÞQ#(y57Ó÷ Í‚ÊDèy„:Ç|Ad[…‘á$JA â–‘•¿UjÖ»M]™‹ÆæÂ›³@…Fi²¹è‡ÜÊQ+%6ŸÆ(ç͘(HøÇlj [aéf ŸFQéO á;欃3ü¤Ñ•V !«€]S¹Ø€©¼}ÀÂ:ŸŠòL¤å”M\š~æä«²ÞûŸëúZ —?ˆ }ßS㉮)BÚaزMJr)ÆÈÔ²ó!Ê-'EhÞØb鱇Î9")¸Q%Á‚'ÕižC–ÝTSœcåÄÎóü[É#îpñM‡—ÊÏ»DïDƵ‹(àYö˜EZ Dý |¡p•‡6f JXñÈ-êZ,1ÀÔ@‹C2}ÌÃ’C'|-sKtŠJRVg@AËmõú&KY=­/×*•Vr%Ë]¼Ce-K);C ¼Á·²aBɆ­‚"" QÜEq p™º‚@û§j~žS…ñ¾VÃGOJ¥Ä2 IèŽçdü†%”ú‹/†ÖÚ‡ò§b  E¨æ0 ¼Xdm:V$hQÙ,Íh€8Xr k5–¡•\A“4ÕQ4ELtÐI*Ì9ÕújÂ(I÷ks&JÂõAãû VdvLF™zx‚ .M´—.²ÿ`íFÒ^1>$¢q£ük…ö°B6 f5ÉqåÚ@4dÙÂo² ÌÔÕèé)óÌÈz©IHë”ê®JÔŸqÓ“ãFô™Ï§ç&Â! [Gaþ£æ”•iÓP]DjS ½¤[š¾£ð½C‚fÒ2œRÊH–\…—7ì ýki9N5ºhs–1 ,oz)óÛ‡-’ªêÝ3¼ºU!m |ø§ Ôü–¦U÷BR„û‹{ˆƒôÊ· ëf(ÎÀtBïàù³ÔYg¯ÍAâx§:ŽYœN Hƒ? O¢K3!ǽ˜eùoðº/RåÛŸz²íŸŒC*×e_jÌu_&ck;4ôA¨:'š~Í6j•Šiáü‰ª¤p™Pšk‹w¾º./V79pKž7NM‘ÒtÑ©>“˜.ªÌ/â^–pÝetØZQ•Ùàï•”o1SêsfJ ¶ùÕôNHë—˜YO²"RiXH¥¡ôXuM€*»zRý0e;(lÏè(êtÿ€5Z²$L.893‘=&ßåò/Ãçª>´!ÌQ›ÂÊÁ€øEËÂ%$ý÷Æý]d-Ž€×SŇBLÕ1õ´è}órÂoŽˆÌÞ‚kŸùŒ~NÞ8}º{ rMon—’ ½o‹ÞD§Wr|ŸŒ«>C½ìê’'2Sê@ûUý$ìrÐ E(-ꎻ6?X¥ÍœDQaW]‰À¹Àø”~ÎÌ‘Á<öÅQ-÷ž´GÇO±íðA97ì#÷~TU*Å¿ƒ£«A“ñ~´á@ Ó”³u¢|˜ñ½cG%rF¼Þ›y_D0•ˆÝ‰íƒž ´a, Ì“$rÀ¡¥8Âç¿8áÅòØ}5ƒ[J‘—Š&K°"l€ zÓ8ü¼àÏ“‘Þ‰¨Ý0,YÕA¹1ì©Â2?‘ôUBT›Ñ¨>Í: ¸q²E º9Ù4·p}ŒxÊÔâH0tM…ApÇÀ¡¡ôÑ¿m@–yÎúÝŸ5_<äÕÇñNаlX­w¬‹k¨Ž™D~»…¬qÕ-ÓëRª5‰Ôy!A;i„Ea÷$ƒëURL˜¾¨…xʱøçN¹©MˆtwBr†ÊÝUûµÑ ŸiÛ%…¬Êý×\ ? ÷5lJÉ`”Ô8 åQµ¸¤”Ú¸¢eÏÅΫ‹AAK¥T¿¯s_MY¤"Ê N'QKNbãÛw”HýÚ»Ù›£h=Ú=N²éG;c¡b?WJ:»!ú$×+ÄÐ}] Šã$V ÃB€!r´Äaºhã#¹Õ]¹² ÌR,Ew”¤Z¾XýÙ´yŽÁ¥P‹>áþ—#«®ò¸`ì žÝ'6:`ã›Q“Ž]Ý-ŒØSؾhŽù>%°>±­Mµ­ÛLßR³&ÚÌÜ[?Zf=tØÜÔ÷]µ¡KC]+×2¯“Ó@ÅRÁÓΫbŒŸö‰ ¹÷2ô½ˆý²ÂÙ‰<#j4B|˜‹;±¶4–×Cö9)©«ˆ¥“ ;¸A] 0¢:<Þʱ*ÉHW+¯0…Íß[ ñØÅ§á(‹³•Í‘>ž£= ¹]™ðŒŠAů´lø2"×}©ŽqþÑì¶;ĺ28(…·œÑJ9ê…OTt®të6MFˆèÝ„jѳyº +Å@ÿX1ôbu$1ƒ¡›Ê 8Åï-Ò&I›1QýK<+ÆÓ,T/Ë©Ã{^Oõ%Ò Xý©ñ'"‚Ç»ŒÛá¼h‰ÛDx&ÑØ–Q‘Û%±»ñ±Úö8J@²ä Ö-ï¼ê$´Ò¹NÙ?EeÑEÃÈh|"L±“Q˜Ò ÕTè:}€na`ec==¦=HZf½”a¾Gà2ôÈü…_œÚ1x-ÀT@"úš¼®bÈ„]=¤S¯ «u±tËÒÄ|ž´C¿Ê¸5̨~OZ5‰ñÉÆ!'C£žæh}9?‡ñ¢ø ‘E¼ìÅ ª¼dœ7¬}‰dÝ8´&ÊSÆPØvˆ„1;sÑÄÉÍ"'SWŒŒÈ*jHC‘Éá°}.ã®êeÈú”,õ)™=Rœ•HåÇn¸Â?~[Ñiµc­£X÷ÙÆWke5à'u9 ˆ“ú»Ð6Í\Ý5s´N½¦£Êu>†~;>Ž7æ0B@šÛ?:ìëúœá½!~Í´,ÜÈW‚d¿ Ÿ‡î–¸Æü¤R¬ajÁgšœÍ Ø*ìUŒð{N;ÍVƒÙEiÉ*ôNB@ìI¼fë+Žây³8}+%ò¯Mã³:¨Ï\\vP쀚ÊÍócŠe•ótá[³“W{nOîØ÷ßÎ~ˆ!õRØãW›q› Â8Àkz^–C¡ÿZ6>Û¨–Ú>@™ÔºÌ¯ vÈYðÍØl9Ú´*÷½§éŽ üÃt.R'=¹ïRXF2@vêòRYGs’r)³0Ýf³.5ä™ Ö/pøï» eØúœÏæ*62 )­=µ#±ö€xë˜C‰îai›àZv•…[ª¯ÍÓ«¹ ñ:g=£¯#XðÌ%åÕ-¹Ä‹ÄÏëSº¶¯eyQ z"E÷9r$Îõº:ýõò9Öµ(ò*g¬ìI‡Ú¹gwßÀ–P ‰¾ÄêÌÆQAÑ\W.~&„ÕXç x]Rk…>¦^J Â,Üc¸/w-v¸«ÕL›£ÿ‚¦\Vtçˆä A_ðwì$ C`ïøX‰ÂÁ1x{Þ5cÐÙ#}ÉcÀWä¦C |Kdïi„ #Â_°ùÒ4žOb3HœCgPxärh¦)Ï:€¥'’¾áôà$F9'Mª@9kâ#X”¿"à—ͦË4“Ä_VùÌöm ŠAë°˜å4¬Ub5úýÎW~…×ëPZýb9i|Ý(p{­+{‘Ïò´,•R‡Éó1ÊÄÚi ŽfrÀp•=‡ã1Pl„2=ÕÏ0ïéîG¯Ì¡ói¶GG»Cb3måJîýÚî`ôwür˜›dø;)=šÂl³-;i‡‚¼ÜxO.ó èdoZnÅco¯é)4›ÕëSºÔq½ŽãhØ(‰£êâ:0?+ ª 1çû†2,Ëù ¶ Ú…º¨:¨’¦Nì: <@~­i ½êClbNð€ˆÑîÍ€nB “¦*²¦Êøú*Hâl“»Gënä€o’„·ŸPI jüx´QB¤ˆ¬°ZÆ%`) Èð¬çíJ@Æ\K ©²ª«©Éd²¢*«B„Í`C Å+Ô‰L(‹S*²oÓüü¯PÙÿ#Çh,’¢3sq"-òÆJªZ˜­£ÉíJP¨*dô&î*C";ÉLt‘¹oâN²£‰œ¸€4rFï ˆ+oI£Î¼0*ªûø¯Ï®²Ã>/ßUŸˆâÏbL-ª##èló%0"¤Æ+öänôÑ+ü²…Ê©²Ë €Ð *WˆZË<)Ñ´¾È¬« @×Ò³X+õª#ÉÎ8£’uÀª³×êŠ,–Ü\´N@"+êç‚ÐïøYG(õJ…±‹+ì0@”Oð}ŸCQFE1ý˜ü(T #/Øj’iR—Rô¬T 亴¦‹:ʇÝ6K!u´Ã+!2f(ZH…Í:ta­°Ð1²9¦²M=,±Lì…{|hþaçæÞž›½ÀÛ¦N‚l™O´]“‰ã7xð>økR÷k§õÁ²¬©N/ªÑŽ›œÖ)MT~½¹¹'7¨«[Dà>5.ão`$S׊31ö®§:ÄÌûâÛ:„Ôóà5h·Æ›Ü°¶½ûŸÉwž€Ëæ¨J³¡õ¦‡Á¾³#¿B†õµ¶Š§N–A”Ñ GïŸk?~üHZ±:ó,¶§Bت°¬1‘]ä¿·â‰Ût¬ñ˜…PVJ†a„!q?ÇÒÖÑqLIÊ•ªfø ¥QE.>FBûÊLOÉ R7JNšZr¿TÌM[IJø”’°XLcRudy´¡lÙ2ne……¿Õ •²‘hÉK«·HÒs—‰$‚§´håJË‹ZŒÌ~’rNR˜jÃõû”R犓¿ g ™:d  ôuaÖ•ƒÌ•mœ°µ… âÃiDŒÑ¹º§´‚“š‰QŽ•î8³ ÃM9üu¬ ¦Cp M’s 2gñÁ»t ò£k‹‚„¶çüAÛš_j¨E32!ü¾ˆáUkï1~Á—ZÖÖË£i /´‚sÉëÙ„‚UDZæàøiЦ-⤣9#ˆ)õ­£bˆò{zD”¯Ê©v×t¼- ÝŸwê÷‹Â4æDÚ•ƒYlPÒ|ÌÀÇÙ!I ¹cõ=2xÃdZƒAónY¿£2Iâi˜ãñ¾Ær„mR:¦u²|¯Ì)Í<Ñ™!çMÛ5ƒàòÎb/“Ò2ˆˆ¸Ó,AëÈ0§€*ç;or8&>äû™q4¯Ã%*f@žäÙ=°‡”õb*‰‰Îô}-”>ÍKœ“)^¢'Ë9g{¹¤ÌPÛ²Øí Tƒ‰`ãLÐ:g¢qBðe”hkcÕ6§Mx’T€®jé!!ôª*%SRüiIolŽ’˜½§ù#ƒ4Š\8¦Ck2g§¾ Ä÷ ^€êP½RÄ”tIig±I|gZ€û[,¶LÐt¾mlý•MiBâ “‹)Óe.ÚN±HÈÉ=st!$XA&’½c ¥Ö¥YYàÔ÷\ <“Hjd—ÔêUTƒ4:>Û0ÿ±|-ùÂÎ̉£„ÒݲÚsedÔ&—®ÏÝAu¬¼8$ff=Rû\™Í@Mj€‡²S)qªú³`%I'P‚ê©w ÌDAF®]Ãúä[2ÞöÔL’±±l^ùyï¹›0qlÝ´lèÛKÆ‹Ø6Θçv/¬1’Þ¬±3æ…á å*–{aLžUˆ¹Ø–MÛù¹€D§¼q»'¨¬‡ –|!w–?UT‹N¶Xžú*i.…Îå|IQ›¢ ôL¯S±•òOÞ‚ß•+@6óØëæ‰êù~D,°Ñr™˜±1R*¸Ž7®¸dòÐ*V؆×özœ"F*MÜzMi½8&úµ.à ¨Å62nÙMä‰2„R9eÃ%&RÕè`Õ`¹§¼X>ÞfbO&SÇÏÉ™à…Ù\ñWì}“$hc&!Xn±ç?å±ü¬IÚc?Is ÕvÀú4’¤ë}Vl`œŠŸ=$¦m@Œ•Å_å½=·û…bÀÔ©{oÇh}PÉJQi´ær »Bðèf£) túÖíU[#%¬UzýLØ)Ü;EÂØ®‰ÀÈH…Çüøwp‚ä,é–rª“¯›–g.`=: CúÄGÞY QNÉ[iÇ¥œ™•²•pzHö}`/§ÓB@4z®‘=I”déw]¼´­KÚg,¯ÖveU„{£ª¼XX.ŽÛÉ[›òRsM«éC%kjuw´]}©;FT=;¢²ªûHæºqܶUd6EîyWãáyÀÜ#[9zÝvâÞdÚßY能N葼֫J™Ô ñ}ACêw{u¤Ë°BF)çoæc\ ÌAeô’±N ðë‡kÈmÛ9tšÞÉB\5_ˆÚÏP$}Þ>§“.¸u‰2j»JùÇÓ—=Ãà|d qr£)ë6ûµ® 7­ò¢”•Å3y›ÁwUµ*U¹)†¥Zõ–::zMw$‚¡ä>²½n²ãï~éæêD¬bÒÀÜNðñ.èŒüK€LÊb«jž6ÅþDe¯Îã–e)r“åFÖ Æ½é`ê ¬´Á©n¾FíÉ>¸« œäÛj®KæRÞËŠIP&î"ÀI®*ÈP cøM®¸äeôXúfÒ2p~£nÎ ïfÒ_I2ûŠ(P)ì›Âd9dJõNH¸¢ªOlð‹è¾ ÜxÕK€&£ ‡vÂïÒ&ŒÙ>£Z-'t*K(IÎT$¨¤#H¨×ª´¬†s.äÎÅàbö¾‚á˜Âí9¤,1 ú OfZËÂ¥.2eÀ: ºB-„glúÐIƒî]Ppp‡ÒFEÐ%$Rƒ0ïgÌ?„¿ÌNï®>kÌcF&$î&ø£j±£ kmrË †Læn0€Éø'¬z+ v¨,çøífZ·Í¹‹äGFü ÌbˆQk‘:'¤RƒÄªxÃ"F)ȼNâKè˜-ëzœm$ò‹b0n*§Ì,é‰Ð*h,å” hMø4ðtJ¦Z…-’ m1 îø",Ž' BªÕæ‚#M4ˆF$½ˆtQ%N^ªL J8ýéUh)ÂÃ)ÄA„è qi .3&»"™#jí ¸åÆW(¤dñîëF0âÍ"°H•,"lr‡ôOª2)Ê6î >É#¹iöô%°¿« ÝPI2Eo†håÓcÒªï¯.ŸRy.Žeco1*îLõòò%%½jšÀqÈ«¬ø-²v®c.åL̆ çm BVyâa: F¹¢z Œ6æ#S Ö2q7‡@$²¥&O2QPì1¢:i|õ®(«Ì8ÏhŒâ&F’si7ÑgÂúgælgô•L.6°/$ >qO,¤¸â.1øeÔ^âZÊj(]’8ñìŽ&Øl“Íc6ëºr0!> 8Î¥ð«ÅŠ­!û!ñòö2>ã ¯)‚ß9bªÆty‹hÏ-ÈÍ”#OÞQQ°‰.j\ŸÄÏm§ÅúåÍhd ÚÞlŽä’ÇR@ÿ¯§:ç G"ÂàÆÔ®ªX|gmB°Ð`âBÒˆ2IÓïì¥Î $ÆH‰OHI@¼f~óש¼}r×7²‹´Züˆ°—2=A¯òªl nk|´€ ¥@yPÄäO½‚8Fz1˜Æ„"ÁâÂÍ“@‚‘’)Ž,&Z6¦.¶¢˜ê§G!£6ÞÅÙD‚ÈÃ>gøóbƒM†@X»°R†¶35U0Ï '‰Ôô2|8 |²„Ç”¹)ñâjÞpXÖí³ZP¢"=$®²Þ()-­èÒSî–ë(ˆ)˜ïMN ¯Š¦(ÖõÕ=3âWÑLÛñ„ã”æJ(Žø&Òg®ô± VA)n\~iG4òÌ?'þújÄû% êú+>c€dT¾e/Âæ·ÄªÇ¤d„ªpˆ<Æ- Dh¯“ªç¶›k>Z.¯ëgÓï ÂRn¨íIù3„BSôfñu4¥P+ë¦ö.ãñ×eÅöñö«Œ}Fˆ”—"Ï!(´Á§f)Õ ç-A‹+Ë>‚™Yb¤T¼ãçp„¿ÒSEµ¼Û%ÝäOâ¿L€£ËÆÔ°ò„tµlâœIÒÇ^É4Ó‘dÕ ™QóšÚC2&K·FKÙ5#¹b„mè9S6¶º B6«O³ðÞ¨TÛâô»¶ŠÅq~cRec ÌôbЭÁ2¦S 2µ¢ˆƒ#ndN}*ÓIðè9µêí7 @ç54m C"³?©4e«¤<—rHâ8xö»¦æØËئ+s4Óy76e-Gp÷u« .„ž™T±Äf‡K?V³k0®ðû«LÜK÷ n·SBJÑ0|"(çjSÇy'ö}4¨²•¼Ouñj/ï—q=…v,e%(º®úÐH]IïŒTÉ<«´ß¢ÉÌ•2Þáåú˜hÒ[685…PŸ¬ô²•3K†# lÜ ¬IDisÕ(+|yw(è¾LËèº4›ÐYXu€“#RÙ©˜g”%ó¸Ûî™'™qUkY"[VÂÃ­èæ‰5P ÏKÀ¼ÖBì¨bòu…9S'ÆåËÀä傪ñ2† S’ì›Ì/“q)¤ÖÖòb‰Ëã1ˆÁöÞŽ?ywVk‹ «èk™Iõ¬Îïz#ÎÉ,B–,²QR`ŒNçY|p"ñ…ö³ø 0EÚîj6A)59QeQ2Óof@s*ùktD—3î1Œ™THjKŠâ¬ôõöò­öàÂj«9p,ܤ"$é¦JZQƒòä%kºE.&,¦ê¥NX¹‡Ó{ôõl.ªs&êSVî%fWuÂR¦6Ša«Ö¦8ÙÀ³Žôz¨¨òX±1 F°Í£i¬zˆ6šæ¼8+ò¹<×S1¶üaµ÷R¶‹3x Æa«)±¡õ$ ¢”Ÿ.8Âòns”¹bL¥fîH¹MzGJ—´(¨ÒšŒÎ5*¬.õ8/(ˇ43.ø‰Ø¨Üæ.˜˜ï8ðÌÐbµÁ¨õCWdd«nËÅÔÃâ<¾‡ª²»®wø‹:ŠINDòë‹1Ç3:ÚܶÁI0‰¹Ê£„¾±# ³`ö—R[2¼²Ñer¶'aôMœ±Ë5fX¶W qjøÂòÕ­Ø[”n÷B0c_TfŠõžã&}¢L˜B)U®dRÖâª]›Üƒš&ƒQpäP™™L’`âßLò‹iºÔd b°âR±±qks7Àž–0ôÑVó¡ [ûrÑe•0\²­S6êb4JãûnäTÔÐZ#ÂQ'ª²ló™*½{åM *9qHÍ0þOl©#B/ÀêÁ)C2OmÇÛ+?{Fkl#ÖÃË?.{¾ø–’›oK¦)0€ä…¼;E´¥i%Äîï)uÚµEjCO SÖB…A‚ ®•HN÷FÛµó´Ô’!¤i~¸ž«úJJ &ÚïC¦³¶KÇ|;Mb)µÈÉ äöB1ú±Be¢Ç÷\£¤)—{w+ Ïšz9µmŽÜë¾É؆ê,©\±eSú“émº‰é•ì•Á%mÊëHÐß°eÈt³š|6›&ÞÛ'Ä«)§Ú(¹´ ²,ó¡òþh4³îþ-1c`â#ŠìUU&!·QqÖgô+ö|²¸¯•ޏ°:kw¾Ò@ÝÔf Šc7–Ö-´õRí•X¢&@ TÇæâVûKÁ}eǰK'8épgê·y£~»ÅQBË"ÕcFz\%g2u£'Ì-=Zp“RªX±¹Ðb»÷q2)½î´þ`(Eõ TÎMDÖÆ—ë:"“ÄÐê!-ÍS8Ý’ÜM— >éBŸVÐéäSFÖO_Áò·ÓvÞ¡·[,ôrx…²m7»ÇW_>xXwxý‡ìYáIs´²—š<žM˜§¢¢Z½j;8OV|ÿyN3T¥B.]À˜ø®±SŽTÈìýýù[Ä”ÖþÁ_ìk °<˪½#õd®“K­¾LÚ±HøÁAõ`ÜÌ|â/8Gxy¨·)%°¢ªzx|í·¾et¡ÇnŽeAgbÑ£­|FˆçÂ>àP  BÀ×Ô<Dá`^‡¾¢à8›ú*ý‘D@QXì’+)•?å‘ùcþ?•#2ø¬Ö_,›Áçq UùA™Ë§P¸Ì’”J¤OÚ ò›6£O!rI%¬ŽÁeñø­.f’Geôøói’Yã±øÜfŸY­F ö—ÌV“2…×b•0 JŤÅ^ØP6íH†Óé6IÌæ°‚Òcôð>^7c‹ÒnTÛ´¿)¾?ªð} úŸa¿LñïúüG#p¡jïtYMÿ¯Ub1Úlãs¦Çðpºmž_¾‘aÀÔøü$…{X#1ØÍ6£,’t;,¶^_M¤Ád’û=èO»s#z}“ðñáÄò=nŠ{\–sÿÞb>¦¹ˆ2¨š ï2Ž©è*zÇèêìè#¯éî¶£ð±ü޵‰b|ƒÁëK.À[Š¥ð›^<ðäD~µ¯²|§£±zzÖ° +f/(:žã N4œÃ-àë¤h“D–2hjH¦Ä[Œ®ÉŒ8¤©©">ò7¨ºð†¢¯Ó\•9NÂÎè ²Èç¡-jH§²*j7.) "*ʨ3[`Ó!©{4ÇÃTÀ.Rdþ7 _6((ú΂¬ï›HˆÊȊθ¢3:^Ó'­6æ"«²’ÀT |¼‚D z lU*JìàI@#˜ÝBñè  ‘*X̨"_S%”z2¤±“Ó‚Ö§ÜdºF ›½è« éEíú ŸÏD÷<'éSЦ§´”R7llHâCBJëì m 9x'ѳ´ˆÆçâz¤£q â1qÙS •au¥î »  v—³éj&Žàj~–aӳΈœౚTÄñûÜQE~Qw &|e±ÕÛ:¾?%«(-»m í(`¨2¬s.•BGëô Ù6Ü).ƒßq0w° ê{xVñ«G“8Ú@ö¡ÈÚe@+Æ‚, }6zºû­Xm:…æú-©u·åXÂØò.‚¾ S<´á KO“Þ· ¦bÚ<’ßFÜåéø»S ZìŠÄÔXÈçnª.·!÷N¬ùiñ!\y‰¸hèºí‘NͳÑÕî/tE¼]Ä“Û9B6ÿ¢j~¹uîS–w­;'ÿ¡¯¹ÿkB¢{~JúC½B&³ì "í.r&Æð"?ˆ¡¶ªMÇ€˜Õ݉åüpV•Hè‚c&Õ»Öâ¹È[ÅM ­"Â^¬!} Ñ Â.xZðmlœ¶¤’­ˆYÌM¨ÛB t‰¶9 øî¯«“ŠO9¨á|¶C.¥@Å]ÆÙ˜£.Y× L:ô@ËÔ{«@…ÉÑ‘5XBQ,bi@ƒ‘µ˜ü]Ê÷/Ì}Ä"|æRÐ$‰À…Î?ŽcäehYͦsÊK!ò?‡ô³–t&ìMièeéLŸD±ü»Ð#¼6…„Ö»Õàé¡ZÒ>G¢ÀÖž ‰h%œ’b;‹}’`…–wð<›+àA % ¶òåÙÉ"ñ*@©âÒF\ #çHΘôp)ØiH±1ó™q"Dä1.½Sê²RûW€I;Ãrp I~ ² À(¼ÐbáªZ0(Ô¹,+dW”ØË^Ì}œTÇ—$XÝ&ÉXÈ6;×^{{±).½ý(§ÜÚ¤Xðô!9^ãGñIXÏ Ã›…fiß™ÀK ¦/±À +ÑP„ö@‚_+Ûd 1¦7éÈPLRr–è.h3¥³4×`mê>¯i X¬Œ›”¬¿›j0ö <\PTæsÂGç°ú2%¤Ê’#i³Ú"0Á}«·.ýPÿ[ðpÈvHüRü³\†Ùr®¤0ü^]<™$©>KwçšQ­}„]oÊÁòà©P¨ì¡fÅ2 ¶j5 ª  p fe¡Ö%´µVZ`Bß® Œ¨Â -©d ‘/˜ Í¸ƒ\ v):V¡Çʉ™$VZ!òõ':ñr°ÑÔCVù‰".ŠbGû/2æD9'5Þw‡‚µhA‡Qó²ÀͪÈó£+#nÑÖÖØt@tì»õ«uÇÒ_6(qW"…MAAŒˆáxGy—è—ij°9nF\0uíZÙ0û2Ÿ/4mAÏÆYL;€ëËu)”®²:ˆ+a"8h¹;…iÔØkPX~¬è>‰ T£"4{‘wöAmÕÀBwØøÙ÷zI0u\&l Ùž»&ìL/İTDmõ°ùÀŸXOjÖœ#íäèèNá"Ÿ,µ^|[P­™ûÃÇ¥eј@‹C‡}҂º§Ñ˜gCÓ+4’b!ô„Ú|‡–øE̦ÊyÐ%î½8‘ºÏš µ`=RQøh0&I²Õ~µ§¶²e¾uÀB.]#k ÂQ-$V3éœ:³½%C.e¡ù dF¿™ÑÅÁŒ¼äE ˯àCpéjm›²ì¢=6”Sk¼’Hô‘BjbÏ€À&`W•d³åQÒþ“Åø¯g¯^îÓZvd ÞMW!ƒFœøúeì Ã"¶äš¸ã J¦>ð§6J®_= ‹3Ä*zÛBeÔû®-êÉF{kЭ :ÑÙi#?hm»¢‰CšD™è%ã†8²†­ ŽŽB=‚ô¸‹»C˜÷ÈWú?KZ>€Õ Ý`BÝ~ou_—Ü ü÷ï>¢Ãiå9ß¶/³À%¦)™BfÈsZþì[!2𔄶Â3/qÑY)î¾²)Dq“Çï'3cŠ-ZÞâðѸœÑ騭ZlINI‡f7G0 ŠH=Gš1TíÌLªe˜Ú½Þè.öp‹‹#.¾Ê²3Ì\e}°E߯Â'Òi—ÛŠ=ùÁŒîBVýpáJ»ÇË»x.ÃIò“¡4@ô—-ï"®¾È´­>õÝj‹ë^þ+û/ ÅÊR[¯¡z“w‹âÛ(ÌfNŽs4f>Û17×ë·ï6ì¬mM ŸœæÜJà‡Ê‚<…ö±À¦•®’™_¶iO¤Õ nÉ¢S}l¿JöÆ•P¬ýæbU,ÎkȈ†¬¸cî©9j·#Ÿšì™Ùù¶²j¬ê¹#+‰Éͳè/y·©Á9Až30Ñ º˜ kþš ¿#|¨Œ‹€?T9ê Ã²l5sW4°•¯á> |ûª9Ã8¢ù‰zø‡ Žœñš8i8´{¯ z2¶³³òJˆz° ±Áa¾Âª¬‰/‘yÅ è!˜} :ó>ã“H;)˜8RjŸ‡ˆ«S#Óù‘£Ð¤·io5èC`÷ŠI¶1pËÄ"."Av¥ºÁ‰d9Ú"#á›8‰Ö$iÈ0d, s!Á3¦¬d»ü¾:7¸¨4)Žêk«Ivb‡ ®9³†Aú‹ˆZ1bã@;¬A«Š$ɼ°Ö‹c›—–Éé-qW/¸´«¸À#Ä®b/Ÿ!zWzŪ;:™Ü‹0¬«³-;`´¼¬$k¹å'ã&6ѱ*D/ú¡ø¨‰Ó£€æ2 l³•Ã" ²…2G[v—±çH^ŽëÇÉ„–1#•¯cI ³é¾ŒˆÀ€Âžã3°HaBÓW&ŠCl®«ǵ± ¼âÞ ó±¸S>ËR²¾é x„±¬nˆ#¦©|µ4ˆ)Ï# Z¨‚ B;8É÷¸²w@(Ó;¬B ¥&ód€!³2Csîù ;Š žD:Ê+«µªË½¹l´I”s²AÒí=êw‡Óë»c´¦ÒóC²÷³ìŠ´—»J!×hæMâ-œ\Sަ€|ã¤ê£Çp~«±õ©»Ü˜¢DÚŠzw ‘½bØBÔ|#S,ûplÒ¦džü 0™‘ •›Kø}4£kÇZ²>à°J+iËD/Zª¼Ñ¥±–­{”³ë§L|á ËÁ¤­­„"˼ZˆÜCl¥‡áñK¹°„Ò Sž=¢« +ß Ú/¨Û›CÊa9ÛR0ArÍjýdÃH¿,×<WÆJe½µ€*oΔ|¬BĽ- ÊpìJËh%¼Oh€=ÆKF"ü± ¬ˆéd¯y×ÇšhÌ48Ì-&‹‘¬¼£ŠIÁ=mÛ>å/7ý ¤±k!Ïx¼¨³5ø0RÇÁ‹RÃïœÀ‰Îˆéƒ«8Bm·+n çB˜Òõª¹ ÛI˜ÛJ9ªP£¬ Š÷Â,q|¼ÀË®!ê–üÁ¹³£³,Ș+|ʪúë:H‚*$=OÖ7RßÃ?ÇùÅ­@~‘ÉÏi¤â²3”l39—ƪC³ÒM£IxNŒñܶOÃW·‰´%Q„?ª!€S´‰™o§Ðø›d¸€B12¹Zæ¹Iq ´ã€{ôÁ>S%|-$ø"¡t­©9"ÓÁ«Z®2ˆ|<5wä†ÕC≜º=q߈yÏL»'H‚¬ü­N¡¸qqy>tr°R²8šË¡±·Æ£ÍÖ" Q‹}—ôN 5ƒW54ÄØ³»Péš¡8¤¨Ê⪓å6ì€ sXòÇ²Žœ‘­@-‰õ]“âƒ<3O»y<óN+ÀÃÌ%97òI‹HæB£›…–ÊEžk@ƒ¹&ŠÕa?cn"¼ÛWq>#Ñ}2¡ê™{û»¹3Ï ™A)ß ¹¾Î"®ä§Á9‹£-µ/‚ò:¸I '“PT˜³=–*«ð*ºÇ{…,ä Sü¿AP¹8ª¼¤9K•wªºì°°”‰"7ôLÓV*ºêÛrMÄp–­H¹úu$EMõÊ ž¼¼1YÖM©É²#¬z[Õ` s‡#b¿XRBY^Ǥ;·SKDÔsÄÀS¬¿2ö~•tÍã«D3rŜכ¼øß hèÑð|Έ½R~Ùx‚ZБ]…ÿ¹3’ßi>êóÜEìè˜] ÛhDùàG\ 2Ð"ˆ¨ >”ç>-aH-I˜¼D7Ä€€× ‹®ËpA}hPÈËÛQ²2«ÐUY`‘vZÀ|©úª«» Å¤£Ë)­1¥ì <¹ˆl1V½'Ê98­ù8£Ô) Ìž’]ÙË?OÝi»ê²Ûœ¬Ð~z§¬ÉrÈIô Œ>$ÿ2ÌÆ®Õ:³8ŠlEa"ư¦œóLʬª½ƒÁž\\©Gö@.Ó:ãö #¹(žÝ$²ø|¯yòÇ¢Y6,>`¬™}ÓW´¦«$Ö²-+ZÒþ$ƒ P§€fS²I³WŠä=FÒ³%º µx>ÔT31¾ÞŒNˆ»ëÁ¦Ó’ •VPIÅäcdb4I{EÝ‹X†D‚®/3$·kn.zl£Ð³›bÈØ&-_ ¢í…02®M §<£Òá*@9…]Øè& ä"Ò¿€3VÓ|väÊEå_*"Ç%Û Œ ” ¡Tø¶äع§:saý<$˜´ŠlŠv ¸ O!E\+~#,k)jþ\„þØ$ñ8c>›Ö‡78OkMãÉBfÀ‹Ï:슰 ô@Ûº?°‡CD;~‘`ÍëYü5"ä¢þ¡ Tp™bÔ6 ]•ù$çËqØ™Ù{%}<«6-©9à•™à¬^G¨‡· ÖÞŒPÌùÆf+ ®M'ì°ÙÁLÄëcxçÅ'ëôXÛA¸É¬PÒ›šÊM‡Û—+rE]3 bÖ)>2¢€ ë¢ßÊk¹Ï'‚äRŽ‹>9hòsÇìXUÉÄËØ1œÆQ/4¾'ÉAÁÉDT›2Í{·Ìò"Ñ‹\ˆKñ¾ú®aIïZ†ã¿l©­8*×RQ ½ê9¾ƒ2ÀBì-èÕ[—ŒñZX)r–+ eãÖµØXA]Ú 7TBWûŸPÈ$ñªr¡»îP_ƒ-ÞÄÑËçWC‡*!—ŒÖµ׿³ªÀîìÔ<&£…RcÝ/å¤J¼ &•-ÏÈÈ¡r;íxòê±}yé8d­rȪ%M`Û¬s/b`x› s~Úª½³KC>3†ðÆ$Jœ²Ls°oéLäuµÞeP‘_;4ž®{R³xŒ†ßG®è6íÝã>ßT“ VF0Ôc‰cP¬XŠïð Ón7!), °fÓÌî«É@íëøV(ÉýbbÅÅK›*ÖE\É›3Ì,ËÁž¸È±*‰>ÝÐŽÓÐì+_MîÅbá³kÙ–æ(ˆ²^·UJ­ÐõkMð|&Xà^‘ö] oã[¹Æîö”'otÏ8äa˜—… W¬ª‡·ÜÖ6 ž®Iíó8AVËLêq²—Q¹‹š­Éð ‚zWŸÞ8íÐgÊjŸÛó¢ÇçÌÚ3çEù¢zDI#÷om4³p„íÍüš3<Ÿ4&gZA"Â5u°,Æ‚ç&ÙÁôgÉMáåeqÞ"ç+v6{HޤkLøpªâ§ê<¸Që¬\ú”³çX%¼³=6 ÝS‹¹]Q!°Œ\w'’ Î xa­Û¹ÓB#»Ï¶V$¢aq;JÜ‚=Qef"ž¶¿×g/‹ìg€ŽCžš(éqï‰?JÌ ~΋ôµ60]üÖ‘—μ÷¼Ü @§Èx«uÿäõ‹s›&­¯ä„áÄÈŠ=kÜ&w±ÓpžXêožD Ïng™i8ø€ï˜ãE SŽZ{-Lý\8°°Ö¦õÜÒŽ¢NJ·-UàÉÖ{¦»ãÄJmüßýÇ´–ø¾$9ë©ÇÏuµ÷û\ÎÀßç¿QêÎôÿÀ‚li¾‹ ¸…ù•EÉp€?€  û„!@(`þˆC€0@!ö Œ@Ÿøä0Ä$O褂A…"Q(¤j[JbÒ¤JEÎb“Xtû?Á' 9¼zŠiTˆ$š; ‡Oß² ­ªNdSh„R=PëpàM•ñgœNcVPKæÝ¥dj°¥C‹\eÐH”‚=A€ÑK­¹óqÃ`¤*•zCHë´Ú}y‚H¢ÒœTr¥¡Ð@¸tRÆÐNcÕÇõâSŸù¸TJ‡,Ñn@*Í R©n½&ËO—ãdô|\®ó+Rpt¹˜…ÖA»ï€rˆV¤úðD¯4©MJOˆl¥1«ü A)òÏü«¦ˆPêW°œ., ë L"¬ý¦ z´ˆª)úRÑ*IIí ®-#0þ£bãŽà—Ÿ‰‹º„&Œ¡þΟíc¼ËÄ µ¬ª’Î|0FÌl¦ c ¸±«âzŽ2î~Hœˆ3èC.¯›zì·éû„ºÂg³©0Gœ´ºÅÊ@Ã(ª2û (/²>Ž9Íš‘Híb@ú¡’„fÛ'/œD&l«B‚=§äöå¥oÁü‰Aä72CúS€„Ê««YA4IJÄÉ6º‹N褜Ž/HƨsæRHt\‘+CÓ ÕHcNÛÖ  Në]Ðçüþ‹B(Z¡° ¶<ÔB(©.1Ãb§EÈ¥Ï( çR¿öÃEг…UÕçúKDQôèÐRõ]A¹‡ý’“"ŽÕЂ]ô"AÑöõÔQýÅ2¡“z”ŲK‚”É×äüœ§×È g¤ÓM¤…M*§w'éÇ¡ØR†Ã-âœÏ'ø“°ÊJ”è§ï⾄:Èâµ W•õ!Mqö‰0(25Ós]Â0HÒE˜ßômªáÎ)úý€ÙQð÷¡Nˆ.±Æ¨*XÒ…’IH&€¶Zx|*hå/„ê¶+ †#UTíx"GpÔpL²×¦œ§X %Ôèt~µDmàün‹!XÜ{¦ohr-4®ºõÑMÌ®ø‰>ihìu!|Fï¼.›vˆ#Þ–ïtÌŠ0OÃÊL9â‹Èè¤fÆc.T-‹ú5?_5Z‡ v5CŠy—ôÃÂÓLŸâˆ† Ù{þ8û‡îŠõߨþwEf¢†«_:K2+…à^>Õɲ"ÇÌ”¦eš‰J‚‡Á®=ÒHÀë›jF‰²¨‡:I³œ[Ϥ}¶bRpŽD%HCõ6$Eì?^IA"F$ƒ#2âHŸúc«é B˜£±*Nep¡ãæÜˆ#hoPåÊ7gª¿’£o†ê.(—ÆFSz"Эl€#4ÐiÚoŽô‚2å†î “’ihy–CB ÅÕõA£ôŠ=–¾ÕØõ#õ^’'Z‰–‰Aa±ò?À¸> " ¯‰â€&™”bž<Æ ˜ÌòÐ%(ÍѡǢ©GM0UY'ËtœN§€Á)ÉBõˆÛžV¦ˆÚ§Œ¨àBØ…OòW4³.] ²Œ€¥ÉX-è$B` .?Ò5%ÎH$“¬€ÓUDŸÉ®ºä;ÇÓIrLÕFæ›áÉÒ- <&ý£I¾:MMuÎåè˜bëÓm(Ô,Ý¡#jŸ-$Ù7¦tH%:5tˆN.}±Ûk¤œÃx¶Ôˆý"È·-ÕÛ2‰ùlhÔ4¥-Æš?R:s=ùTÂÆ Äzf?Dþdr<|ÌÚ§Mék°5”#Ê÷)Gñ×¹RV‹•éRÀH•dw?3¡åGƹáŒ%OH,‘¨TÚC›‰qošž€Y©D¦$ë—K~)X‰MO©BaȺÝ\ ,(-é»+ÚÃ=ÚònÍš:̳YYhRJäþ“6r”p¬KJm-&†N5‡XÀÙ@ÔØ†%V.àæË¥•èF6ãG¼L‘éüÙ§æ{Œ­U„@”F•™…-ÕækI:ó6E¤§Ö.iΚ $šHÉSüÚÝ“\®­øÊ ô<ÖÑXå<4T?ÖVA¨ÅäE£Ž¯Þ³Û¡ò¹å¬h™l€²’gw\JI‚)(Pif>¢£«Ôï}ÈSÁ¢±í´êúÊål®à¹³­#«ûð4—.,˳©e“:' ä" °úN¥#ü/¥vF…¿¢)ÁJ±P‰;¦© ÑàÅíÄÙ„ªh¡úá®ÎкɡõŒ@4xî2%Þ˜Tµ\Véd´ø}±Ù µä¤¸`ÐGÚw¹„†_ö»ââ¹ÁKÎmTŒ‘OýW¬nG'Û7^”¶ºùƒX5,ž ú?< °„Í qö¼l:\1Í/Þ6S2î%V@ }[©9žhº¤³/FXÜÈ#ûœ#øŸÉªÄF?˜‚ܹ٘v,K+€)JSŒ¼PQ(ZÊšy0ºòóÆ6Zz.“µ l|{[øGZŠ3_‰°«>ÂG­VFÚ)U#Ÿ;T™èšA@åØtñ’ RÃÊS3Z° ÞRõþÅK+¯ þEÃóãY¤gC“ci¥CÍXå1£–ƒwµ’ëkÀTŽGÜLnæ´<{O¬ 7h¦ðŠa‰UÀöøF™8 µâE–ÊT·°ÔeŸ`[¯â†\vqµ¥d[-œ,«Ÿ]瘳øÒ85Šì›ioꀬ>Ü3*Hè·r—› ,Q¤¥¹X^H‹ˆ³—?1«¢ÍÆÍd'+IÖ’‰œÕÆ&pûôÄÜ|Ÿ¸œ¾+û ߊŽEçÙç:›gÚXá#ƒ/‰S¿“£ò¸êõk0‘4@ ר³åf?Ÿmi‘/Qpèl°n9"Œ#Kóĉmd„ܹS¿IÐ6ŽU£;;¥qÁ¼ï’¬5}Álžì¶y ¿é<Ž\úë*¿|‘E«ý­4¶ÔS*¹TÀ3šõjáÉšŸÚ´ð•] ºÓÉ7¾ÌªÒ¦E‚8w[1„îPšÈ’3³«Ë(Ì«Í÷ñh|×?å6 —¨¨0Î’9K6ö'toªÃë*¼Ê¸ˆ"KT®CN›Âq-¦å$Âh€møñh¨O£XCÆ€fˆ’ƒè¨bó,&ŠŽÖÑìü\'NJ<ÖËþìIãéBL(¯ï0!ØÔnŸŠÐÍàö+¢e­Ü7ÄÌéì֏вö'†²/ìV§î³cøL,Ö¡ônbd!f.¤f-ŒÇ‘kˆJ f¼†¨¦6º ñoh‚v¢/úƒÈƒ (Àì.¥"ÎÚ ßFØ£DÖ&æ#H| >$l:-„ãDúC$Öçö㌪¹(î!M{Î"†³ Pkl²§íÔŒ¦ÖÍiÂúnìù)rc á®…®ÒŠË¬o‡FsFÖîH¸QŒê|É`*Þæ ¡)°ÇI&ÜOΚ .¹g&OãD¨¨8ÒçîTâ¡Îê;MbÏBª*Ë´M}…üް„£.ÐlM'40ObænøZ Nœ.~r)ÞÒ§dTf ÌÃD¸ƒXL"À NRÑâ-5pl­ä] ¯d%fÌmfõªÐ¸IÌ܉†P¬nÆÆ‘d–$GBìeäÍìHGFޱºî‡ü ÉpñpÒ$&#²Ã螈` ŽÏNbã‡ú‹EÚã‡"ñ"›ÚCŽÀÚâ>fBûçñ24ÏFìtæøX†HŽrîkª}žF‘nZ,¢=N2¤]ÂÎ-@Ýfô— ™…àÃîï +~vŒðþçʼ0m*Ì× ÇÍ ne#KšGÎä‘Òý"ÞùD<ê3BÌDÑe*†¤µ€DÒ#!ü[zÂo²…)ß'H¯)êõC”.®)n)ä‘1ì&ÏQœ!EzÜs>q  žf>-ÌQi-”Ýpžv‚¤³Ñ4³ Ä«d"à óàÛÊœ·s¡0 lNt­ƒæŒp«‡à“ÉÔÙâ ÉIæéiØÇô‘ÒL'3E޳r¾ KxË€Œ¨n7ªnÎ#”ÔlæÌ¶p2¶£¥O®LñïòF‚ QÀ#‰FÿJŒPJ`äQ-âÞG¶ºÆÇokA'FEf¤ÍtjÚ$@Œp+.0–¯jhág†VfhËŽ”1ÜÉÄ‘Ãü­ãE;%†p04m¥ )Mr´nôºÄš<«Š3H Ä[ò\4°ô| k‚¬ãXLÅßë'%'á­ªÌñ ŒNäTr § Nôô¯å&¶Ñ´!4õ+‹ÏÜØi9¢ HëlÊŠç²`af-¸H†7%ë£ÂV™jjºIšöƒ phê0Oäðu÷†Ftù1턘*Ñ>#’gRå&ÌðO¢" ¥!èÊœ‡öbîã‚5UçoKÏ?Zd?6IšÝ*45ïÌQHÓñà²T&•X$Ȩ.%rÇîµ/ô2ýFª‚8âaIÚÁi-PPlµO2õQC3ŽÍ…ïÄ„ûjÔ…,9O…G†åíñ]òRxdîö.pq«ulôi Êö&èu°!ÈÀ%)uñ6)ÄcE5ÒPvO|î Å52‡ŽØÂ”]KÐ<”#d´5ÆÂpÒ·w\fìêí‚­55;Ã*lÑåMïÒ³–܉¿”.è,VºˆV¹n(W£¼Oó]d†s`QíÛkUJՔ㓺4O8u²Q1Ä]«+VBÎÀOhs4ç`üÄvRðD ù'åý±-`î -Ò ½ÍGc‡ÌsLú6U‚ì$޳ń„0vû3ªQ‰+TfS ˆRò}ÍW ’fN³g1äßOÞ< Þ ³PFÆæ6f#•M %©]òßî:ÝJÓrrðp-Á .”_Ñh p\ã†6ÏSGÆÀÌ• WX?ĶÆim@Ãë‰/Ȧ–ñUƒø0Bã=MJݸ>Òœ²eå Ézö‘Q+Èó´†ãE $ptçúQ;$ŠVM,¦­ép؃rIè<©D‰Q–«¦béð€k0âã”bõÊþgJ2L)í/m\7âçÍ#b¤Þ@'«IìÉE ÎCÅ4ë[b”l㕤Ÿ¦o÷j”ŽòìõHÖá†" êòû´—%R.%ؘ·¤.C;z7!KÃ}Îà ièþvÚ3•hßwy±ï©¢ÄíjJîè࣠?ˆ"Q ëo²e,?)v^bð¯cÓ=UiÔt_J“1æu ©š$WL÷˜((%¬¨¢¤ôbÎ[„2íbmb,åÂÏŠ`knŽý·"]vh«'†—挬ÖP¶°Bæ D #ĪEn}lÀ~ON-ÒS#¡ûEáñzìÛ"DLÔM’­‡^$LŒ†ní,ªå7,ƒ¡ú â8ŒP¨°mTD&¡4Ûq O·³A3zv™^Ì\¢•l<á?4ÕFyÁp£ì»1ÕQjp¬B]ìÐÅ5ÆŒbCÄdò¨8¦\ô±J“Ô–q Ñ…SF^Su/ìNâR.)”øJîÚŸ§4CЛ‰y š+QM‹G,ñäÛN|ô“ñŽ¿xøv‚†µøEÈfleß176ø8~!À«šÌ¯'ŽG¼4švÞåjŒçΜ&K¦tKKu¢$Ëh¨ÍmÂkURÕ$ö$Q‰ÊÐÞ’ÝJ³…*Í–‰$Z&§Ê#Ž_ ì”¢âv£6hˆ4+_.ˆŒº/ØE!IkJ| Ó…1‡ô’“\âa¦nĸ”6Œªøƒ ’â3àè÷aé§õ'6ª¨¥qf2ÎKAç–ÀW9¢›ŠëuW™F¥e 1ã„àÎ䬩ç7R­òöæi.©W5vðB‘.u\¿Sí¸èfžÖi ÉÞøÆ–‰d#Õñ!mk‡ªk;"JšâRµ‘|b  üÍÐ|ÄAVé‡$ûŠ9Nå¢âÉÁ˜£N›:¸Iv—mÖ}6ó#:ë°¥eÏ\ü WGÍ 1- «1Éásÿû [ËALÓò%Š[äùG-¦Øîy“´È*΄} Q¦®èjµi;†Ó6w7 ØE×¼ùž<4ž7fjK#–XÎ Àv•9¾J †ä%›8·wÐú˜î)È‚7©Ôˆ2¬Q‘üé¤8gaû9I=™gϧxñ­7O5ð²¢Ù¢µù6F5£u”þ·sN7/gúžfÐs"<4´ÏÇî:Àé3ÁKÜî"M³‹»8ÁêVt{ž+¾Ôtn‚5ÍnÇ&W8…8Qå~rœ#æGäód<êèg ˆÌ$A¢"i oËèDg<üBwÏb1)B>@‘¬ϱ;ØLZ.um RWíRû‡;ÉXôz¹zi{"Ò‚!HMŠb ƒö¢0Ìaªwÿ'ªÑ{†ótÞàc”7£æå;‚)z| e+h'híòYWÖ-_m¸Œ#&ÚŠ­(¹ Ø #À÷£%e nîF%2±gu¯Ü-q{Vöƒ¦G~/²É [ˆ(Ыúð®Uû-GÜv“[µ™’¥{¤ž 'EÎ|x«gF"\/,Hû88Zì9^V¯ÓYùû»™F|äþäQ5€H”ä—"à‘ö±LÇ]TRÚ#N™mSDŠá\lŒL,ép»Ó2ø®QïÖÔ‡¶5) /Ì$ïÃÅÎ0Ø…4IŒõž=”ÁÇ^œVϸ…ǯàV®×¬²ã8HÚ諹†—¡É+U!ä²àoL {ÎÞ〢œízûG•φEÖÌBœCÉÞDÔÊÄr,¸p#…Á|=ŒC«Ï<ý¬HæêÒ\â=‘x.5”¦ Ì~úïóS›¯5üX}‹ÕðÈÇb¸ÖU¥ôIdÿKS õàÝnJ>ÖM¥‘Xîé1šØ\ÿ@˜y0 H‚ÉMùÈãvý”lÖ!FÍkºØJcÆJŒA¨(CÆŽÓK—©Oâ+Ý£|d¥r Ø ƒ¡8Sþ="x“ú(‹@áϸÔ:ÿƒGà *Hù“?%ITDƒÂ#±Ø4¶eŽÀâÀXt²E–Ààr@TRˆþ>àp ¨ 7AuNZ«Q(òÚe*‰I…M&/ú$¡ù/‡Yã´È’ @Nb@z%…ÿG¦S%¯‹Ô }¥H0í’j–Ù¡Ô©mv-‡LäXÇíÒÙ ¦d%Ò -’sJ¯ï—×®Ž ¥_äü V@è–xE9ŽC4°Ì\RÓ*Ì=¸ê&ž¹M·R-„RÕËÁg™âEG»J§<·÷5û‚Üá™üt!­åÛâôýO*²QðÜ<ƒ¼¢A?žÚÍD¾ úð&-Sç£ì“…'Éè§2hb˜û¹ú˜Žºà#\²)KÑñ "ŠRÈϾI ¢? JȲ>¯tHé ÇÔbÄ& œ•@jT®"Š:…ÂnšTù£ìò #¯Ú•¡òû"‘‰ôާ)l Á­Ä®¡Ð²(¬Š 1,ÜP“-tt…;ˆ¨°²Œ4”)S‘øŽÊ)jr‡LéÊÈî'*#T‡O* =!;?s: ÅJ²Ú'ŸÌ+ 2R0DSjêd6…¡¨J¾‘5£¡Ê$λ¥lj{I:ŒÞäºHëþýµÍ`(¿èíY#Mt£È Ćã<`-3íÈ¢¨²]8Ý)RY¶|´ÕSg󈶉B:×7gó]I ×TµF ¶ÌB”Hje®'½ó:Ðqä~Qh¿5ëµE¥ª:ˆœÞÊRã RÄÀ] "Zÿ¡ØªE3¨Š ²(êUCyЬ6HÓS©BÍ!Ý ΡKZQKÑxJŠ%±ÍohØgÛ\œµÍêóŸ­u]!dŽÒª«C‹Ò‰‡%êŽ×dK+4†N° û—€lŘ\enä  Ú(ëqû`KÑŒL€PꔜèÀ#1^çgõ'0ÌOÚ ­¿iÌNos†p1«ºÙR{è„k.Ö‹k< œ8µ¢€¢)“ÚM\¯³†Û£€5í/34\³C©Ë¹5nʺi)Ü£§+mkao6óÙÅK¥³¡ ÒéþúîÝ’3¿÷Z Kî™?Ù£Y }gfÖÑÿeBÄ(è²RÇÚ~ÍÄÕ2RŽ~«¢Ú³BèÖñŽÂŸJ-¡ÍwXÛzgÜ>&HæÉRžf«…Q¼bNJ;ÑTOInb(`–Vm‘㹕•Sá@g.+ú´ÛYR©d—‚•W© ãàH+bH Ï»˜BæVpƒ/³"ËPŠ7fˉ(´5.Þñx0Áµ’?Ô;À!Šy>ÅrÙÈÓóõˆúÝäfï‘üd:ãn_#ܦõzãê(f#ñi)ÎeL E3½PçGɪHqÝe¾Bµtl_/I§X¦uˆÐ ’‡ísb\¬‘#Ió‘E˜fÌ #Gi^ªððŸä•$)´"â]ÚDf ¾ÃÝdKu;ðE 9pÃÐu#fÉT2·jJ›‰ •…Ѓò = ‹6è9`¾0”K‰-˜GÕC KMrþ˜PeÎM†ð‹y–0™Æ˜WÓ³lN´•%ÚJŠS·"ÐàèžQ¬Îb‘J0ࡳ¸S<¹6LdƇÈÉ* ,íC¹¬qÛ$J ¯MWRXV˳ E(ÿÈR(Úg“þ3l¤Ö•bÉEJ˜óš­¾jÈF4I”r F„ÅÝÂ"Å(Àÿ,ˆú*’˜~Õaâ¦J´fžâ™`ü¼ŒÈ‹&éœæPw˜á›%ŒõŒL—Ä}Æf>ŸÉzW‡ ¯WE ¢‰d­±e(€êñ4SL&Ÿ5ÉßÏE_€û¥Æjª¹°ª»ØbjB Åé‘6W쵩þ«Â À*”ƒíI—¢ñ˜hríì&èkt¬•’¾,Ár>ê–sŒ¨VУÒHQË‹}£³ÞHâC!ˆ!ÅÆ|éìSnx¬F¦V“T¿ŠÙ ¹À®T3cbed{$©f”¢°áfDñøN("1lÇþ‚Y—©ÁÒH¶¢T€’HUöµÐ¨ÀÚ@Øì@Ræ¨Þ€IXp™±€µØŪy™JH.3Œ…PˆADÇÚ¨Y/‘ÊdÎ\Z¦¤n&TZÆlkª‘vÓ…¢I‹U0ð9@I’Òã^š]<EŽ *I¨‚šd`‰*PÞ R¿/±Þ‡9\F¦æ?¿×^œbVl—<2 ”JürÄŠ÷Ô¼“_¼Vóœ%QïV6—·u±×Ü'õY¬Ì‘EàuÀ¢ÑRåp÷míT7»ÕLQÍÎVÛ+WÁ„ s´J°´âVv!\f>Z€ÈT5zŠ.ñ®…Y tÏkÚÊcò`’õ'Û[‹Í ók 8Õ#$´Vì€'Â{Xwæ]ÒG~q³ µ]‘ ½UÝ”Æ"Áÿ:‹/’ˆ¾òB½{G.—Hæ~K¡q€­¾‡T žÛâ%W Ý—:PI$šÊô¸¤ Yñæ¤sà!UF_mÑLòPI!öÒœ¨GIc³c¢Ûø{V²…̺ý£0쌬ŸoÆ£ÂâA—Âù˰âmçdbYB ˆ‡ne¬º{¸…yhæÅèJ—|]Ò™¿$,ÄØ[š|vp{?¤T5˜d®€rî²TîïE_IЫ:”¸(#Å„ª6¢ç¸¯C»Èð=OG¦ÜÊ:§>ЦnT«U€*Ù8ÛµògC0S-sJ×VðË(Í’ Åaª„tlù{C†µžÃ²à;ÖšØFR™7*b$¯Oü±®7ˆ¢wÜÊÅï +Êï赯¼€ÝÜ Vù²©Íë¹»îYÖ\üâñôP¸&¾=fÙ­HAëµðÇâÙãWqì$@  úÄ"¢.©7 úh¨«®‡ê,Rt ªk—Ž‹L›KûÀ…˜“< ú`0s 9ø|%š¢øÐ€BÑ©x1«¹¦Ãs‡¹K© K½pã6kh1m›Áˆ7H«#jv‘~Ó1>›Ž¿;"*RÐQ8ì$CQ#ÑÄ [i@22жè?$¹k “X•'YZ Ë+/BV@ð„/r(XÙ;B±‰Š@³Ñ‡Û›•°“;á=%Á¨ãò±5#}žŒ;‹4ÃŽ¾E ÃpZb:$ '5ëù»‹½ñ!ÁˆŽÂh~™…0S¯®©¼©´À"N¥Ã²œÃM¢Ê!›3AžÄ;³¼ Œ-¡±¿4‡!sg±¼qÑÄÆCQò—øîò bß?y¢©Ôw¶Ú,´Ì:S}¿ìb*c^ÁT.1´B 1I—´Å|yÈ‹°0@ŠF²Ï*À"j@,lÊr@Â\‰ûÄYˆ¡:­’2"³ŽóÔ ”œzÍKŠ‘#²>á©êT#¬KªÀ+© ¡Æ$[°±‰rãr+`«+ê=2ì¬B¼8)B1£QDH#jb¢T8ÃL³¢¾Ru!1T'Kò™$€hÃyF\IŸºl‹£ À/4w$*¸˜Ê#IÌ-œp³Ã«ˆˆ‰«¼'Ò¦œ‡ITåè«%Û¥«™‡¼Ì¯.¼¢Ç@ƒ#hmOš6Ä‚9Ðü jÀ@úŽˆèÉ ¢Î‚À,é<¾ðÀ "ã›S&™ä‚®ãLÁ¢ G¤pŽ“RN“ß {g‹¡$±Ä—‡/ó9|8EãÑ@ES ÿ¬{¦´Q*Æqm£ºÐšÙ GcJÈj¾ÐÂÁ¸õ¼ ®øé3Æ‚Æ4+Ùˆ³8QqˆÔ‘#$’Oà„3¹!½Ô%©8‘N3úôOºö ±ªŒÉ£ÄÔIä8‹$G$¸3 ²C» ‡ÊŸò ‰ÉOº-5Üa?›}» Š8²’ ê×+ªÁü(Á±  ÷%œ­kPXTê6Ša:ÂóÖ¦ˆµi•ˆ*Ñ ?4,È’3ÒD™Eaf#¨‡/ –/dGzY¼Ü€NZÞ€$6?|GM|'£,I¶|B«b"Å´°Ï¨­*ÎŽ‹±/·Ñâ2*·Ò8~ÆÒ(¤íùºF˜|Ç2BV lø3‰ÅD·³Ä@+ñlÂÉkü Bî0)Hø”#í\C‰ØÄúI¤ ƒ!Hô±x i (Ìð@3Â)×Ä;“Ê/D?D¥š:½j µír,˜ºš ¿›²LlŠD”Mð«•“3šbØEy¼‘x;Ñö¥€‰¶£}B»¥Ó1AB\·J$É»+´(ÌEᬥÝÕDI?R/Å}ŠÇ{äœÉÝÕõiR+שëvIÊä¥1¯–É»!7(s“EiÿK¨Vz Û –å‹êa5Ù(¨©¯ê/TÄТSù ¿‹"Ù˜~ÀÌÀDî@Ë62„×ùÀ±p30„T¼ï t-Brj¤É}1„ÆŒ2ˆ¤R@«,·¼ymÕ„§×ÚŒ°9t )÷[ÊЛ}¯ F´r ³r ­/ˆ} ¥:YÄò‡y«X|*š/5D¸4"\I|”\ˆ‡Šó¡1KœŒ¿\Ȇ2Z:šAL?KYl^‹1p#…äJI­Ãø”>¥n 2/³^˦Lx³¾TVºH +b»hO]±£;ˆ×ä0<ú„•»,(Ô8@œCÖØVÕï‘U bð­ •!qÆû·ÞŒlDE`Ulµ ,ôÏéZ‹Œ–µ¨MTÑÁŽå&«'"ÂjÅãĖð]òü>oa¼=¼ —Éq;ø½Xì¢Ì¡ #¹³Üt- µŠŒ:ÁÃ.ŠV ÊÚ`´™§Ss"¦«F;­w@m¥ ³ßÂAì¥BÞEkL¨púµÝÍ1äºYª9‰éæKƒ1¤ÖY-1þR~3`¤^¶¸°â³ÿ++Ý´+„IÉâ¯™Ž (“3 Éb`^}3ò]ÐMZ’ÓcR6¾±ßè¡Q”µ •­‰ByU¿YëFΘ¢˜üŠÚí+ì 'êø ÒéÅépC¼–’k‡BpèáÊ2*ŠìG;Iµô½“Èe5ieaªŠ<€€Ú£øýßň^Ô´)·ÝŠ[ºúØTb†`l)êÐÙL)!±Ðað|X»æÃ‰½Þ:i](¹(»¬ÔeÊ]‘B¨—´W£Ó4zô^qì»$>›Å3_p³õ¯Íj½… .[f왳L—ñ!°Õt&¬ç¾À#m¶F:¡¾4¼ÕígŒXг&Bê¦Õá­ñœÛ¢ü2z²ÚÅç縄9ãÓ0¬=Hžd%ûQCê×I´Åù({­ ÐêÊ^â,Q=²\œ×][à1jÕI±iþ–§šS4äk®«7]Zúµ7é:¡Ä Æi ..*?ÚÜ+ý<Iç³ØU •Üž¿ÊI^°µ%ܽ¼ÊR¨Û—¯öµì-xÝÌVl­Ú‰5}Áñ‚Br¯ CÕ‰D/#º)èi눥 Žñi¥ö>Fdœë¾ËYöF²ÙTE ¼¡HüØÈ}$2I}öW\t&Ýf­·ª¦'’¾¨PÆê³ÀÏÄmó1ã³5%nèæÌ8¯™ºbžÑqìg±!sáN B©O¢À9Š4*)³¾r¦Wê3yæ4F`JQê0³R:4Y[ÔèjÂÚ›½)!¥®Ø0‚à•â¦Â‡£L¯FîÀ‰o0lu­ùÜÅÒÒ¨—É‹T–Â_vÂTt6Z<ô48é+ÿ’•X û1\UÜf/ ÿ¼:ÐÐW©œß¯ÆúÞ§BuUµP±äÀ¸ÂÍX¡¯¤ý'X2)èmòÝHc¢þ'9 ‚¸·.ÖNpÁ!¯‹*éï.쫸!]+>ýB£pÎp |µë\F¥]vÛ!·Ý‘È:*cJáHZ˜¢ ÎéÍBfÃN<'K”ħ$aC«u˜<æá!ì–aE³·U×\{Üu©\Å žV뀦+Bã²qøéíGl<5ÞÀõP¢.¯ gäÔe@}Ç&¶Hî×(©³¦z¢ŽøÀ79½/^¾†"á{`à WEqŸ"Ô‹=õ4d ¡Ü­(Ι=: 11h£æªl™€ ²²æ*@›3 ÂNŸ«Ž[ÀÈr>Š#j2) " B:Ð¥j22Õ€‚ð“£(ËBŒ£ï“xã´+Ê~ÓK”Åïƒ\ü+ û“£nyý¯QƒÕÉ­TzÀÍšŒÈºÈ‚B`x~2ú®ÿ#Hbr—È‘*°¸ðx|ÍΚ-®IÒ„„?ˆìÜ|°è$‰%Ks*˜à,ó$Œ†-h£y<¶è´u(KÎÒŸ¸”%ŸÈêƒC'¬E @)z?ŸñB-L€I»¶…ÐŒ2R0­äC*Ì ƒòô€d˜+ ,WÉú䵦ëiû²< <}¥kDˆD¾+³âɲŽ»¨’mk'e³2‡´E8‰MiHð" £M”Nˆc¸æÎ4íM$OÔìdˆMˆsH‚'Q: ¢×|¸‹XO3Š~Q³ÙzË튆æI5µE+1ØÊ_kŸ·»ìšKIDŠ`§êÖû¸õIô9ÈfTÖe‰ê2¹?”ª®£3ðzc<çi"¤ÞµÂW%ht¨™fj¦ÒVÀy%6 {iTHü”þf $ó  ØÓØ›çñ‘W ¨5½q(ÈþÊÉUs@©¢³<ÇÒˆ-sÊ׋äXú<«H2>µ½õ ugH›9’i´Yþà&ü{%6äÿKd— ø•Ü7¬Õ049˜¶Ú]g[cZb§”DsJÙñö(—¿ˆr¿á­eögУô’À¢dE%C¯[™=Ÿ°6V§WJ½qA7L!\¢VÁ´:j)ã¤ñ×è83ìèc 2®U'Ù\zMçjØ8õ j« ±µÖèNˆø €Æp¯=¢ø®ë6CD0Œ³ä¢OÖJ¨‚¢!WˆY?Œ}·GœÁž»€$ĵµ€ oá~çÁÿtaNé=C-PŸ€¸u ÇëÃsªÝ›f ?øþ@¤0޶÷–ûáfÇPD ù—¶_å\‡÷vBâ&*ð–²VqÏãÖŠ$¼½¦5ÑkŒD*€¼‚ˆ´"Ð!A`\‰‰üO,¬¼¶”̹Y*a7-AO65ô \`„ %ǵŠ2y7‘}xwÔ_R¶“aÓ$ؤGÓbA40ÔGõ£ àäíÅ—%–VÊÃy3l\ä À¼ ŠP’EGPÛ\Ù$(ÅÊ¢-©$tK€“¸%Þ£ž"e‰Ê÷Ü_ƒrwïñwÅ’H^FÌåS€?&ãa‡ü–Gå­XÄß/žšÍÙø°ø¦xˆQƒ{,‚])Œ£ <³œ¾1w´¢‰L‘‘jâL¸^û ,H‹ÐøøÜOG¥-(Ó=i€EêLb„`TžhO%Âh_+Üj,¥ª$GâÙ¦ vO‚=&/9ÛÍš+R Æ‚,ò©@§Ô›ÆñôŽM9<'¥Ê^RM=Xd…–åy’MÂ×\8”‘ 0w¿7Ž;Ei5t‹8’zÌ¢¸cEåá®ttc˜ÔQà=¼ÿe Xcá—–àKÀm•xAëfì¨ I ®Ž‹6=HÉüD¨£Ewö| ñXˆ„F ʪàQX"‰å«9³#Èñž‹Ö&×)ª}½YŽÓV6e*ß]€…Ñå®»‹Yèà¸*ˆµÜîb1m°ÆÓ&»æÄ$H­9ßÀ»"ì‰ýÑv°ª¥\ÈÔKë¸P D~92RE#Ý„71Q4Ûx³Mƒ"riÎ?÷p‹ËÍMUw•›€jÞˆÛÌK@Þ,B6âô φHHGz?DÃê©ö¾³ C¦cM€-i­ÆÀ›¦\Š)“²t”E{Izy}„é*\PßÓqƒÄojfJ ´–“Úo8Bs°ÂóeãE´à’’;X¤ðp©¼ál.ë|"£DT»toá=¥ä(ŒÝY¸Ô§²1ØBz<3Â>ÜúKsfØfšÊßËêv«ÕɬP}í¨ÇÆi$uU-ÉrIQ¬J´ËP'I^Wë‰(&ÓëyˆºõÓÔ?âõŠóQÑ♑1Õ9Š d½¨®Òk‹¶r.ÊäÄÒU+ÅÉø¢(U8‡â¢Å’h»x7 JNÌYdR"ß„î@£ŽØÆÊ‚4µlØ€+BrõÂ@_Óê>³r³‘µ’_Ií¸X.¼¼>£ÔÙ­·g!U´£a”Üh0¹.¢n¾XÞX¼nÿ:ÆHÅÚ=S¿w™¶¼Ü‚ðœ#_ž‹‡o]ÕÆçû“ú®¿=rb¼J|_{¢5Ë42šÕŸ;ÝÈÒ­ˆ£J%d+E,\û”ÜÀsàJ™Åy»Ô ‘ÛâºnY1ô‰WúÇÉwÌU$3sœêR27{&–‡µÛp\tɱºÝíQãÚÚIo ¢,æH(ê>iÐ kÖîu—-Ÿ©Umtú¥¶¨}ýwv€ëŒ0e9~9B¤à¾è¨¼L²tí¹“³#4qéEɳª,ÒA»1!¤/i¦°¡ÿ­Û®õ“°HG´îKT¯]5îw·)¼÷8ÓVJmM±ø ¯SÌÞúƒ1ÏLÃÇìDU¤y0z?¦ÎÆôV»}ã( TÄ|£U¦Ú°¹\ä8ºÂäÅÑSmzDÝùmÁUæ3lwÌœŽèpêôÙ)j±¨b†,xÏâZFÎ) ª! ╇-kF'Cä=ŽBž‡ja…p›-ê hobòLG\,dcL ÿiè=‰˜­ª(^ö‹B$Ç€¦(: öÉ«žDeLÐk˜Œ úŠVäH48Ž$%æìv°voK¤ëÄ -RöFò˜o °Äf6ˆâÚÈ MüŠÖ…Ô˜«òÁcêHŠÚ1Å’>¤DÞJ|Å-ÉD‚·Šô³#8I–%ïšáÎÄc­XÄ X‰’ÚDò…›ÄV(lAd¢K®^mždj>"Ï l‹Î]PŽ/ˆŽHæšÛª¤}‹‚xnŒMÌ6íQJ!ôX‚2GH@ÏmhÏp\ƒJÎLH|ÁKuîAŽ*r©6N€ÿBzÃNmŽˆI¨®ÔEV'ñî$^EC`î‡V§,<­˜Km9ƒ’ßk¢Éè`²þõ1¼öl©ÉäIQ»h6Ø)zK&îEë¢Æ  `ɽjæŸaö#p$¼äˆ0¥„Ü90†ÆÌwî´Ô8_bôÑ&Œ"ň(ɸyðöV„Ó €õ§)#Mf1f/mv¬qæ'ð1 /þìî¥zÝâ6Œ ²$Ë¥6í¤„¦*¨%ÞkæÃ/üÙ¦'Æ"~ËB\JÚä(T×Òv®Ðð°á¤¶ì.wl v« Á ÿl&•€×HŠ~LFŠu é'@n6›/:qk0K¤TÔo—2¡„‘±rUgã ŒÈÖé\ók¸’NH±¯‘$ s&ïC„”³äÀüAö90L×§|b²|ÐXöï"~-˜?b$EJÒ•ÐH›j°åˆ>KF™1âcPã"í˜ËÀO1æÍ®n¬nöã…Å6 Ãð¬‚>“r¬ñ9¼3 »aþ×0y" "jÎä1©‡Î4ó|dFy1'(ŠÖ¥¡è>J{1O@PÈsRŒÎ5‰Y038):Lž2ú$'¤…JJQСÂX‰&—ãk ÒbS:¨ É Å2ÆøŒ ŸÍS °dwÄ ÷lµ!cxþpþ~“jEðñ°x„ñnTCØ?‚u9iÐë+蟦lšÌù,lý  >çPçí‹'òi,%¾/RÏèâñögƒ Œ®`Ðöœï:ÍtFªÏ7b FŽ,hÛ"H|E,G¡E”A’žÕ$Äx #³FðÎ<‹‰œ!M¶÷ËÎg‚n´bÖ¸*ÛJGe-Íœ“Ï^°èŠòÚGãØÔdÅGRÈ’ÆÒã òK;…–«€óä¶v¬''„ðMÆŠ¹.¼àÀðÓ·§¯<šøÄlñÏdYq¬S¤òéE? 1޼/&¢WLQAܤfWjp*ôÿT„¶€%êž‹‚|n`o+¢%iØo&Úä#êt4R†ipµ ’ïTBðU“6Â>?ŒÔáæ5©r›(§ì)6ÎèèOÀ²H–ÓS=Mö!Ê)"2>M2-¨Lzåêáb6”$xøÓÙŽÂr‘¨"ƒÇÃg>¼÷” å©]ŒàáèY[ÐõH ëxnÑÐxjfsǯ5µ\’©ÕŠÎâ+ç<¬l¯-ѹMô}òkæò%oN)+Ã*IíX£xgŒ ´¤¡3™P ®Lz¯î£À¹)S ÉJ4|\2Æä«d)ìîÌP¿Qp¬’'0óbK­Ÿ´³)È>æ›PnŸ&в'²¶köK\+˜aˆ¨H'è›…LÏm»ˆöî › õ±tTõq²–Cà÷’· -J1ÈÌp$ê y5°>ØUÖáä‘<NÞ÷…ã?’ýoÇÔ‰²ä4è±ÓdRÕÙb„@f:ñpö«F/]®~©ÜIU§MI !N¨ˆcxkïð)*Ûm*U–”Ɖ‚ ôKGêÇ,vÑ3È·s‚¯+˜Íáõ^D°É¸¬IskÉRƬq""K/õ.§3EÐúîȵv"Uœ"Oóx©å“m 8£ÙCRÏÏz±x›ŠäN}z º®ÒÁ瀎”\æD„íà“¢Bë–M?VDVEÅÝ.®aA© éSÈX‘âH”3qÃØ6gzowê'†É–’›÷¾žC€óµ\Oª2Šè¢g‚uX`äèwô }‰y è4„qÝZu]ƒdéÁö¸&Ï"6…Ãî­¦^_ð·•-y݆¯lŒñÜdKÃòW¬Ó‹Ñ,n†}fDè±”ðÅÃ2´ÒžT/RD"$•žíúP ÷áö"•Ïf¯¤KsD€ÆŠ7æ©6Â—Š¨I{Ppæ2œ}UKAõG¨oyH(tzḗ:Pÿ%7É+p8T©)t¬ˆT\0Žd–R‡QîKûI§0Ù,ô1¨Ñ–}ta Ó°·1jãlþj‡¤ÖDu€åÞDLGffèúÔ vâS•Ð÷€Çè›-h·-Ä4¸.Q8Özëñ$Ød~xg¥3GRíÈŒ¬¸ªp”ó8sÂá­AŽªON`nšo‡®ŒÆÏv2&¸.CšÓTÌLÖ.5Ì6„ç’w—0pØ!’Æ¢Ï ¿·Rª¸ô1 Õ!yØò›•R„òþ2'5¢t¡8ªßDí},ΗôòŠr8èŒlÃ}±~Bc•áV³‚lè㓚jܱPwé¥öcQøÕÆm+«kšI¦.(цØ^“ȵTˆ•·”ø}Íe”²q€ܰآºçwÈ9bJb€:"ùr}âÖð‹Ä}Þû­JÔy“cÅiyކ׏è¨h°ÅŽGkF¹LÄÁŠÆŒ×ÐíA¬6}vgˆQІ5Ç{¢ð.¼~/ìü`ÿ’z}éaÙeÒb…xšK§IcÛkEÎñ±¹%x¥Ž…‘c#øå1ú=L 6Çà¦úW'câNÂm®¼Ã“¤5V™•õ28ä0º<¾Š™ëˆˆ¬(fšáƒ“½Ö¢öNOµ >â>¼ ä"Vþ% Ñ= Çãz’ù¤´Ê “·9¥ƨXö¸› fýY@Ž+(eü‡^ümG*cWˆÚSâ\[§C§øn$4*`ET’ëÛ#jI?ÁÓ<44 tº´›×Ù˜¬¦¾âpþ®ºòæ»_¸~¬˜_Bf«*Îßiôº¬È”éY©®€&¿°Ys,ÛLëÒ\\U¦8ãô9˜Ën<¾øçd±–y¦ºá/Ë ²™ I žä¢H7^žíZàÞÒØA“aŸ0mz¯#Ä’X$ó5¦ƒ³7£srRPY m¢ ø3ú…?àÐö!‚b€(´P Æã‡óê@Û‘G¢À(ôõ Fá±èl ü™L#Ù,6|NÀ“Ù,Aú ¡>è‘ÇÍa ’Æ&°J÷ŒLŸ“Ð$x Y£¾iqX¼R Ce`=žm%‹D¡ÑèUBÝ Æ$´¨µšÎö½YÀõºÈ]NˆWi‘èôÒ)J-Ql4"×À¤±ê”R¨ZmT „—5P¢F#—i6J ÎP31¼h s ƒì®uà[þ¶N ÚûfÅý ¦E!±ŠÒ-TÞBé¶ØEZ‚V+7'ÿ+§Êê0âÞªI.óë^¦Åáñø—ôwêÇ7~ï¯w‡ÖÅU¨Ô{Š‚#Œ¸•=Í{¼å¨ CZ©(3Œ :@à5R$ººÍëŽ=" «# SK €RÆ‚/èìŒ*ì$æ»ÐdO @¯À’¦ DVƒ* ƒB}ªˆä2Ú£(›†¶?ðCÑ"GÈЫ!RŠ  $#,*\¶Ï J¨¾-ê#LäLÜ– ’"¨˜*‰B8¡0ò­$jØÂ$«úQ,ªÚ`¿¸\o=(’<ñ¡Ø±F K´Ç! ä·&úñ&JBÌD©k׸T…£Ëä ~¿ï’Ê«'¯Ò¿²ÈÚv|>B<©¦QSmOŸÌ"8ª:Óz6…*•‹žžÕsµy[Ò „Ad ‘Ý:¤¯*ˆ9­6ò-TBdÓEˆ£>‹V•2Îí¸1ê‰0 Ê¤ŠX`¶¾1ˆ²` @w”/é*·Ÿ·Ãä¦UÃó €Qú6¨8!þ ]§ýT¶•Üp‹Av€ÒViÝŽÜŸÓ+—Si솋a¸ÚK€¶¼lÂDL|Ë`HTåôôÕ{ËÈ„…bD³¥²ö·pô=€æ+‰#DÐ~‹Jp–¡±s\¯€/Úz§¨‹þìJÈ´)`&IBa¡Ÿª¦LZÉêô{N6-Áã dZï»ï2²7TŠù/ô£á;Ö¢¨ï0Ц¥|À@kpéêbVײp n£Ê‚ù*¸åÆgGûž}7E·š¸¿ÖŽm(†Ó€ÔN[äèíI“9 W*ªzŒm7~Ç4€ Ë[ûsÚÄhܾ™P«æÃ^ò—KåUõö²å±T÷#€0µªó·s¿Ãì®^¹¦]*o R-ÓÝJ;Ý— Ã>J…‚ƒv½“CîôÇEމdI!ô7¶‹ãš4fÙ²»ð=ಣ& =½’ƒ_ )p!Õiµ£ÂÑT ’LCîµ7nø]ÃáÊ:â(±ŠË†Z¨'˜ã›óWª¨‚?Ʀ Û³±xP¨ ˜˜U¡¤‰0ð|Žk#Åø¬¸…¨kΡ€TÈ¿µÑ÷*”!Eð­¾¶ÚüŽãråýÞ4 Ó‡ú|i‡ÈÎ&XØê×éÕ.Hz=¨ó ¢2*ÏÔá¶² G”Qf¯À‡%"z·]ITˆ’H†§ØVމVˆ‘±5©§ÚùI,™~EZ+C±þT †yP”Ëã[¼„CÍÙ¼Jw¢ÑHka“GÕä Ç|¶ÜªÍ~hÜÎ=SìÏz€  ÈG»,¡y§[öM‘dª¤Û³Â#s+˜# Oàܳ,ŸS"Ô ‘¾¾? |¼½ž€W“ˆt6Ëг’ˆtÆh=º›dl› ÔxòøÁN‰-Ü™P¯B{QX,=Õ$°VSö¥ hÑ[T¥.€VðTŽtZ‚&Š-É@§¬Š0ó8Ë :­‰-5íF’ÎGÉV£¤5‹¤¦Šañ葃ôÕ8ˆVéÀ¤3‚HžUZG¨êz+4®,”tã™2˜Íá>IÐR!£¤a¯¼ò Íeýh€Ì­„½sÐ¥Š9ò#Œ.‘> b?™Äsâ’*åÝ/a$É©ÅÈÎ9²ÎÅ 3iJ¯Ùh̪i%“xA‰ìKiŒU ‹@Ó9y0L”™D\“>JJg›²¬”&Ù›™TzaÿiÒmG¦Á¬ü„:Ìw´ÚˆDŠ0§qn—÷‡6 ƒVeŸ!´Z±¢pàù¼Yë<ªkåFÌâ««Ø"=Âm…ýÓ;lë¸ü|æî)‘·^Q'Âéµ÷†%[ ¶Gª¹À].]ñÒô°™`ùDœ„ ˜Y@Î#çl-²XJhä-Y¦…mPÀü¹À9'$ B¨\7œü€>CÄ)‚J%@‰õ¥úƒ-•í­ŠåÊ ð­AGoùMbŽ[©^ÓJB 9%n0™D€E %RQ¡„zÆmâ¹€<¢ª'‹ÅÌÎJdèød“éjoâI>8ŒÑT+Šwg¹äÍóÜsk2MLt.ñ€9%4T*´y3Osi:ñ%’nJÀ'k MÍ€x­Ì~SðCtCÅŸ¦Ñ¼Us‡—IÀ‘×¾…$[fâìc"ó=8ì€t(äJõÕ¡T±4¼ÎO3´ˆZr³du€ýf©W0åàS-úD¨$Eý—é¤úvÓ:pMz£!N8Úr™¬åÒåöü•REZ:—ðøØ¡Tªêý¬Mƒ—g M³ˆÞ·ï9ÁJðó9³g.Ð?Ýç±4DA84Û[ÖÅ6¥WˆŒJ[Æ¥½žÓiá™Më=W8 T’w8âÝÜý -ó [®F¶i­ea^AtŠÒÜDâv©µÎzǘ(€æa¼Y²;kÙ ¨,«i®ðÖñ& »aêS>S›=i ÃJœê‘hèë.ÚËvŸi¶;›—œžç'CY|Þ² ˆŸ‘|»$  bVø„(õ$"ÅÃQFKAºŒ1rŽºÇ=‰Ë$LŒ2å­ˆoHaZ R  Ó0x}¸cE&©¿•£1»ó^!Ë¿àëË\Ò ñ‹àzÉB5)û÷ª‹xšÌ„À­–ê$ƒFÊˉê'š’êº{ù x˜= ÿŽ´kªàש‚š-âÍÈ3†Å:*ˆ‘Z¢ŒÄW+dŽbj)¢ÂÁ)‹·+jË,’'¤ ì “*꘡}:ZüÇ‹E§Jº[’#¡0BŠË…’#6¬žr‘6SÖ¥“H›¹¾Ú¡4’:-4#§¹òÂÛ… d|¦I‡›a°Ê‰ó¤'´I2ʼ E¢Œ”©EŠ––º„Žh”)H7Y¬É ú¦0 B’v2’ƒ/¹œ1ÙÍÁBà€’«âÛ" |²;Œ­ ±Ì*)ÂÌ¢ >1ÿ?{ĉê1šéÀrPÀS¥¡k†®søÒX?Y:z"L¨‡òبêÈȬÄí¡´•ì0‰”R¯šÌáÈK¬‹1 @ŒO)>¸Â,t‰C{/«5âë®’YD€‚!Õ´P Ú(²y*c„Y”" L)Ø&sW4`÷££ù·›ý ªÐù³EHIÙ]@q"H¿•ë:(«9LF„¿DÊQ°,CÐ@IP|­ ƺt'> Q”íÆËã@}²Œ üî4%ˆ„ò ÖGúÛ«ý'K¾E Oµx’»³4£†Q¡¦ÎÚó+8~I™ºù8¼ËP›ø¨*»¤¶ÉºÆ¸Ú˜ª¹ÕÅ!¨µR<(¢lD¡?òŒC¥#¶È‡§:»K  ˜î)\#,LÖ<›Ä’(’䷙ܖèÎ2²‘,2QÉJ唣ú#²¨Å<í¯É¿IÂ6Í›àÀ‹ ¹à™)p¡KJò £ÒOõ0ÔÊl¶õ?I"ä‹;M=4ÂŒ#_š1 +àP|#³Û¶Át£aß6] $ÕFÐÛA¯)†b¢ÇkÅGÝ-7²¹ ËßÔã¤Â>E‚yºj¥H:}gÕ Å­Ä7ä¸6:OÒžË I@|%‘0 =i¨²IñeŠ4Ñ´ ꨪdÚAñÀ›–Q)¥ÀxßLl¼~”µ–¢ŽµH àiÙ ŒXxÙÁE°í iÎЉƒâMåPƒ‡ÛÂH’7ÛƒŒ àyZ‘Ö‰Üü>sbŒiSõ€*«)ÁS– ŒP-2Yâg ù¸7auÈ¢ Áú¼üLB¼Hˆ¹+5Ž"•sOÓ݈j4/”ÙO:íðÓ }е'žõ¼ËÝ¡JeŸŠlZâ\rªÚ{ÆÍÈüX(,ݧ;–Õ•[4€Ü½\Õ¹,6Zk´Ã­Ç¥9I«d¼H׋å…>ý“WãÜ7™ÚWxæžÔHઌªãpû×<0uĨ2ÜؽHÊ*"'ô‡©ÄoÆzǨ+3ÃÈ™Õø~L#Í[±*ÐÓÆŠ<{Sd€>%1‡ÕN ´ò¨)¿*4€C@ ÷$g[à¾V4¬4ã,úGò™ÄHÞ)2È¨Û ,ÐQŠ3_Ùñüù£ «-I¼E%‡ÐŽIp-¬©6C¾?´`H;W¸û¼[ÃcÃZ::›ÍÆ$)àë“ÙÚÛ°”D)Í€¡(Ñ÷R¹ÐáˆÓ‘ÒCÒ]kGàv‰,*‰ÛöI”wAt¶¥^šIùag×å “4YZÜ/¹Ù^ƒž+ÿÉ©BÅ#ÝUÉH² õkˆ_´. ;³Mš‚ªŽ  BÙ2W¤ŠÚ(˜¸…+]«2-õ>QœÎbŠ„§F‰íŸ9úX-MD•>È ?”,^Ì+à€¡ø¬²Øˆ üôŠÍ®(>["¿ËgºרéE™l¿ß^ÐañŸ½†Ä4/±Ü4Xs¡­gOÐ…)™ŽãFËÒ^º ~M®¦$[É •eZ”=b©¤àÕò~7ž$Ùý†¶k*”êW馣#â1T#¹Q],À†2è³¥´¾Ü- £b ¨ÓëÛí”v!ÓÕ5\(© ¿YA»ÕG4$“¡DF‹fA¦noÓiÇ[FX}¥e|äÙX ¸‘+ë!Âh º]]8ä®&qÒ7rž*ê› Î'8ÿ“¾h „èRš GO5á câì€'õ)Œj"Vë|ÇíNÔÙ#ÈôW +‰Ð*&Ê$]Ù}!†9]ЃDãÄL½¦ÁÕÚÝè™Á2¸1ˆ‹È½'Ãä6:3¹ [Ü•Ñ XZÕdŒ!¸FͪÅP(vX_mfp=~sÓ¸P›´=ùRYòÈÝ]f¦°ÐÕjé Ú¹þ°5Rpõ; *'× VaÄ'µSÔÌÒ㤌y}·“Í[3˱gD3Ó\ªe›8‘+§ÆÚV1yŸaR7’ÄŦÁÜ”)ÁB>’_èÃÜÄåÜÆHàGV<¨›¤8`ªjÉV㢃f¡‰î«ÖH¶IæÝÑ=ò¬vîéCÍX²¼¶>ÑUBÇ*»èes^=Ìß=-æA‡¨éR¼î–ë‰×|¡ºÔž5ûV<¦Í oúg%³­™ÞÝ Ûì«>m63 NíÍ0 È«ƒ MÁá¤äVËl£o«Ëjdì"*å¾9±„ȹÊÉgCÎÑ ˜áûò¸, çÐåÁ†}8ÿr&å?!Uÿ Ò}¾*5¨V—njEÓNDˆôHûÄöªbçBK"k˜õn^ ^ÒùÚê’¬~ÖØiAÍæ^VMâÞ%W2gÌiög/qZ⸠·…ð;Èšî¡üÖ±ÊÃXs÷vfÓñ»pN7ÑNj·íηœÙNƒQÒÀ}: ØŒ6ˆlABÈ¡ ™²3Ľ»át‰Ê2RÔÙçÂäz•N Eçøˆ¨0ϲLâÃ9/79» Ì”5÷´AÍtÍJ³3ù¥¥–ÅŽôf¤¶ÍNY?~þúó€y¼[C3HmÂa˜¾y )‰’z’ôšöM4Î^â/™n5âŽ¥ÏÆArqpVäÁ¦]‡4abTÙ×'ÅÕKisïªæ“nøîEÒ;pò‹3©f&‚?w%4p©ü=ÿY¶Â#7/ú˜—0ÚMMÎakÅúÎdÚº0q9Ù÷ן5“iµÍ¾á I,ä"µŽ±©wÂ}Á02X3‡mÖ€Ãx¬ÇEvE/ÓÞ¨€ @ˆ#ò „B`@ü5ûÄ_q7ôV ‰¾À‘¸{ô ŽÂÀ28\.ÿ“Cd`LUüù˜Bb 8\¸ 7—Iá2x3òf KŸ8L®RÿÃa3Ì&€ŽÌ㳨DÎO¤Ê S9uv+'#àYÌ:+«YŸ¶ZD"Ñ}\fài`Ã9­SêLÉ”ö¯%k a(,1ô4èD?08(Šz®+Ë6þ#©ëÂÇR:>¯Ñ¢+K­Ï¤tc;VÈâ°Ç FHÌ6©i…R%ÓjüÔsb ˆÓý»XÊ{ìA)×MT¶²F§Ê³";FS£ÎLÀV0ˆ­ú#­#8¬Ð-KC;NSõ ~XQUxý S†½ˆÜ"¨éutá ºçÃò¶2‹UJRx€0¤^RGí¶3È꘹¹ðƒC ¡nHY9„#JÉrg–çLÞV++äfƒ;©Y»§¼´®<~¦wý¸šÂ+rR³ê/sÍîêO"0)p³å-ÿ8ÀöíWœ£nÒãV€n5wˆ$´æãJÛ)†³Hëꆽ0ÃÀz¾|Ô3UOŽðˆ5¾ÙÉ»¢Àî là\yÉWúÑý/B6&RˆïWÍ®k W¢,×(óz³S"é]æÚü§-ä¼eÕ£»å|Å;Òf±¹Ze‹­ÕÈ3AÈxS ¡ @qÕÖ†¨úV1{”?GñSLç©ÔÌØEy:ÒŸ KßJSûëêh]!o#«^ðÎj©PƒGÒ-•F©6–?ÿ=eÄî¿uš§“úú>ãõ¥âS iŽsãñM,×”ßÀ O%ÉÛ“r:¢Ø3zA`6®t€ýo‹ù—R&ÂI2Îuzò˜îÀ!¯"oÙY¥”¯•A#zi‘Ò§Vkˆ‘"g<Í•4ÀKë¼ÅÅã½tBPYÛ-%hž‘“ÊÐX4M?1y@h졪ÃgeŽ,ͨ÷71%øV¿Ö1a$<±£†êHÏ+¦Fω⯃ÔÔ«ÝM ËY˜ßRÄmå‘ô‚=–cÒSíF÷ÄÚË‹ufZ6 Ü(ü;‘)اsðÄHC-‹àc³3. ü +-y³×VïÇé'.fGB+"Àä;euƒ äÌÉ!«>L,dµ6 RÜ"f¡^ž’€‡ÉœÜ\è¥Ê*)œ?¦[цV.Ræ‡Û£‘h…¹µÌ„I[8˜0E6‘Õ¦Cä4 ÅÎ3õ+%¦¼ý!óÝKÖì$:›r2È %(¢>æü=X̆>äRµÞÉ£Ø}Á¨ìÓmœ<¦)Rze›]£äÓØHÜ!=+$f°áý7ÙŒüˆËå{¼H½Rêc#Êi»UÏR´9¡Ï¹õ7‡ÙFª3ò#MJ±1þæÐú¬˜Í:cÞ˜\ì…5qá€*Ì ÜÈ«-:Õ¨))âÈ]5®ºËPøÀEƒiêZÉ…5KÛz=Ä}«D9&¿ÔÒÆŠïc½X,á–.hÄØz0í]B2%pÁ£²*ŸIMT""¬Ø±¦÷DÝqCK-ÑÇ3^jd4•v©ÒhåQËqVQÆÈãFßC{¸=´¥Î'"Ù“E<Œ¬Ú„^haˆCì±Ç±ôÞ©{Ï”’¾’&Ge`w¨d ¬ ƒn—°AW¡,¤ºÌþ­úÅkø8.¿zÆ>áYïY§(4”,Díýy¤úa*x(-Ç®,›´¨6•¥üÑ„ iâÕW&¢1=¯Ö¹½Õ'ŠSëóBµ(I%•ë±.\+¢h¡“)>šÒc†pð&2‘:(ö$fw.µ;2ný$±jl,l(þY•­eÚKgóáq¨²4¼Ü²2é«k;eõÊR×àIXE˜!±-\[ÌËTm}lª(¦˜·äwD_%Æ4&qÚG¿T ýsvL¬ÚGTœ¥Ãa²ùw:x"ÂЦJ×Î ¯瘬¤ûW"‚Ky0wJ{›¦„Æk®Ký6u¼=Cˆ3™â2ç`ÆÉ÷. h[¤HÒÀÒq…çɳ`Û÷_wFô\'ÛQ’ùy†SáëöÏ_©•ü4I½Ý¦\è²|‰"²›wŠ´o Žò8›d¦ÛdW[Õ#‰~r|ÐÞ+5Ôz±7,ß2žOPD¹F÷´N4ŽœdZVClTׄäÞÕ”<~˜¬”.(‰IÜ­vnÏžuÕIÐ ¾SÅ#:Ì|Ó-þeŽ}À(ò ~ìœùQ#þ•é­t€µR½â¹¬îS|ÔP-¦û}øú`El‹ÌÀ~TYë?“†ø‘ •„lÙØ»Š°üVñÜÇ™ † rŽmªÂS#ͥ̕ÉóŸQÿyœ,¹¤VÛ;ø—#.—Õú>äÖfœVIxÛ¯T˜5›Éæÿ@­ë«Çï'Ü8 ñ  \§K3ʤ3u…ámÚ`ߪMoSrD×ä‡Ô.Ö0}Cs=æ¹ô»,Ä" µdu¢/·÷,-rq~‰ó.+¯>Þô¨ƒd!tÅÈË*üu¯¢ÿE±ÎrëÊÎÀ©Ò&îj\ ÒŽ$wBN'ä¥/|KÂgñBVÝ06½CH³lå¬ßHX!é¡ ¤dÞfZÒ*†½í\â¯RðŠ.p­l˜€ýã-„ÚlD"¤f¦Zð°Í!ôx¯/â>2Ê0³ïÒƒ†‚nX|B³IÂ,B>ýlšâÏ8cˆ˜˜ ¾¸ú“Hôê\ok¢èl ‚ ¤º/.¯QŠo-þgÝ (’›"€ÎÖõŠœ¶>KŽ\D$ޝּny‘zÜÎ%íhËFv´b Ã,È%Æm¤¨.)Z×qˆì¥rªH© MmHTí"šBãƒÈ!ä“è,ŠÜ$Z-‹ðEЈҘعêŒÁäß är“Bg!B€M 1æöMfZŠŒ¥ëö½Qš}Ínr‘¢~,V  êhªÁ)Ücže«ØÂɉ­ , ûâ.-ª®oÄÆE¨8›hL€ÐêjŠad&ÕÀ µŠ[¢z°åx™Bn~ðœË‰ êÁô’è4’Öº£eèˆò¡ñ œä"´‹²žÂp"­¼lßo±d¬‰fä‹Ô¼lžþš#£žÎñ¤Ìâòª©_Ëpú-@Ð*ëÆ(./ê¿ñÖìp1!üVæ”§e¨šðà\ˆê\†Ôa²ºËîÈh¢˜vqXª§V¶Ì¤ÔÁôýleîrZòrÊØ•êd[O¢¯Êvè"FË,¶ƒÊ4Å()8±©¦ñÆããT,!é<¤ÃqTÚíÈ-’`_.Éà¡Aù91²ïÌjzñÿ§)‹û °’­\ÐF¨ 5CüÞÅÿIÁi®|ç“@Í ÜKªEþ_î$ S–ÜÉZ›âæãg³³–3£Ҽö2› q¿%4\lwA-{e”ÕbÆrꬣmÇsP–ŒB‡Â`MðƒÊèÓÐ:È©¿Dܹ!õ4áü=æ•*Èë2 Î üTW3ë¬I Át- ênÜÔDÞÈ Ž«E0®”õÄ%)nØ¢±p1Ä?#´ºÁ°í)ÍWM* Æ6k˜¤rîꊈ ˆ%*¾ƒc=I*F#3ÂVõ(tÈV@!S2‡@ãELÌ&enÄëÔÖë$+ÐQp¬#açUe®÷mÝ$QÜÂVÕhH§fjqvÄ ¤¶lM®)†@Þ5xkãCáK OÆŠ´ˆWÈòLë:ƒ¤tà4?¨â¨ÏŠT”>ü-4°<%ÕžšðrVôÎËn¼Ž´€sK8´bs¥ÎÃjs#D¦¬ö„Ù”rÿµ^¶zñIô44šÐ š¤‡6\3p¥®ÛbÔùÇ«U­±/£Ï$§h{b a æñ“!?±Ø +-&,3”Ôœ •DϬƒo}Döb›A¯¶ŸÎ“D‰ÕH-"tÄSÔh°sH÷FŽÕrR@GeG‚Ë0غê¢\0QA†xœÀžôZC˜‹^(òNrVïñNö´(['L¢a*ìL¸é×mïn+€MëZæPÂM›>”&oÚ6¶ r£ n5oñ¬OÊX€Ú”‰ÉLd 4Ð׎â«ìÈfĬ H^·T?." §kÊȃTŽ· !¨ò)ïS"ÐŒÞb]Oï£C£jJÈrÈûŠHμl².k~ÙÃÅ6ÿj„×n²°þ‡‚f¢'\çL-ŠKQÖ’-ìr“mF6tÎrsrÝKÉÀ~Tëu–˜OFšw]Nn UÆMæM§lš÷Ë(¥Œ¯Ìzû0õNÊE$¥‡L‡¶Ú5K3Ê@±®‰bWTíOá6]€Aôõ(N4õVJñz ?ÍW¤Í#Œ÷„ ¤í¯e)þ É>Ö=8FL¾l GÇBâqÖì“@w¥ØÑXBº|ÓÔò¶Ò Š+*ýHcBŽ´gG¬vañ†ØŒ†Óò”®´‰£Ê(ê0¤g7~8)S£Ðct”$äD&$äX.&sT©à&æP‚}…1¤âµõ`zg²‡…¯Ó”<’¯#Öÿ5—߇‰®\ò`-†{Šj  tPŒ÷fÎ+XpvsÕ†äWÛr4öÃŽâ)€è˜4øuÛŠ?”Tä6Y´H†Gä2n¬ É~(#qÆàÅO êùbâõ,x¤rtn—E|ƒkS <·þ°5âQTÐXÓ­ÍÞúQthö¿ŽãøÏ/Ž-BؤPD~ôënاdÀœˆ{ ÍåÊ(ªÀ0mr<\â„(núÍ¢… XY©ã2N-þÂ.µÔäK§Å=–i#Ëø;´HÄaù¸üOÙ;9@¨:¨Æ_jˆ{ž±5ôc.g>9BÙªÍ[ÀËïrúq³x=m9ýv«Ž¬Ølì¹`xï[ñ3ÐÆK»O_f&£ùuN." U~3‰ïo8Dàž´—ùY—ê)÷×$Œ6GLi¬¤²žD?(³Ï|0nèüÀ7ßWwá:²š¼cÞF¢€e¬ç9Æ–þ\#<à´"®¤Š=ñcÀ #¯BÆÃ•SŽÚôî÷ûDzÙƒ2€þ9ú`ÑëŠ5³Tb¸’Ô‚wøŸ&Ž,,Ÿ —ã-à °bÇ‹.zzï±9u9—\(ëFl°zcvÂññ„ÀOK¯Z£j¨ñH€@;°wœöäR“ò÷(·M//4g®æ(y8ú5¶L¦Á9ìŽ! ãÐH”Z½W¿júÄówšø‚/$Ù%5^ÃUq‡ ³‚qL´¿^øÚÀ©[@ Κ˜6º‚Çl>ý‚è”êkžÖ©FN6ñ¢êBtJªqV–°tXv©Fù™qõݯÍpJ#O,ïܱ¯Ö@R¦VVCb‡Âõ¡Q¢ggºªdã¦cMPPÚ‚Ô«òz¶ ÒOÔ•¶à«ûFª‘1Šëj\ueÃxD„JDÊYºäNô‚sÓ¼âK‰¼ûhd þM®É¢Ò¦œ¹(ˆØËI@³—H̾®;­Gi^_ðr㵜œ˜Á+4õéIlQ3¶8ÆÊvþü›¶éQ¬Ü†ø6¨º4Š0kÍò‡·âjo>Ï5¯ý%4ó«TÕ[‡ÀB.m304mÎËy§Ü,.¦nsc=*üæÌ¶A§¶(‹Í²—é\C÷ŒccGYU»l7}óU †NˆÏŠ1B¤É>]—A°nƒ-s!ðM¯¿jаx»Œ =Œ›ÚÌÚÒ”ÛB©Åï-æñ`i¸«ûŸ¿¼öÎÆðI¢ ­ oH¤ï aQ³´K_t¢?„Swo[I9þWŒÆoæ­J¯@2pS<‰€®ò7Xgï~*Ô˜é'j“{_½Ò¯b—í(¯Í¢Ë‹I]‘z_ýù/i`Ü#**N-æ†X{n,à Šn–0þol2?ˆÏr÷`s3²Ò¶¨7)F¿—ùËó/8Òƒºe.Ál3ºeº˜tÔ§ Y®/ÍŒÉh‘‚¦z 3{Çl³S™Š4™G 9GÝ Gš-%oáKPB~Õ^¤å^ Æ›ê1µtl”mêbíR"tFéœõr—Rú/tMƒ¢äc*U"q}4ñkª`yÐ,/SUaçv?â㕼±Éu'Í?[ÝÀ5ší5›š¤™è{W N0Œ3…º@潪òH'«âð ü¶ð#Út›7ƒW¶€&\ÌÆ”•¯?j?Aö“ă8;Õw2¤NnÓÙÍ¢;E¨Áå4¨,ö{)…Ö#¸úôw%ÁÆ«à¨{'ÊÜòVÐ /E›É1Z|~~{¢”ßa·¬FF 'ÌÏfRpNïdÔïãôZ”‡OF±i$8ì•;ÌÉçs›•‰ÿ°~P9ÑÙç¡!“̧¼(<ï­Úg$Ö,ÍÊSBŸÁh²< ª ÖåC!¼×ý"SE×,Ž£6Â)ËÞ!ìØ# f¨¬Êdî#êBìû°éÒB‡²"Ï2«2Æ®ÊC€¼@G *ìZJè ëcˆÉ€.£º‰ÜPÓ»ïËèǸo#¨œÅR¢¼ ´XH3qŸÊD^ß:‰¼à¨‰’RKn*⯵)Úz|Lj:%"ºè*Õ6¨û6Þ¶Ì£Ó!é3ÀǬòÏk´ %5.Áÿ7¯òBà ³ð¡&ˆäã("Ié³I!íØ»JHzíJÀÒAüš$è|Ô‚žõ#zÑ'h{Rœ¦ŒJ>‡¦Hzh»K`BvêGQš¾JË 1 Äê%~šQ)Mb˜MoAü·¾ó4’¨LýH{Õi„PûÂóe{l·¶’FšC‰<ކÌ)+rì¥V[P±=ÒUsJŒûR̲à$0çÜëÚÖוm#òš”ÀÖ0I ú¢G6mPÝ)’…t΢>ŒTL}úûÁ ªw¦U¥úÓ2O½äóÞh:e -Ï ] lÍÁsÙ |å C—KE•´h,6‚Z^†×ôho ¨Â… éê‘i.ˆTZCúž¦EÕå¬óÐ7"|ƒ¸Çú…°O¨:F¤&I8ÐIyJ‘ȈÖÁqŠD°'¯’´‹i•šBs_ ˆ-h®!­:rÍ¥7}hŒ'0ª·?£ù®×ŠZúÝs©/2í:²U‚¿ õÛÈ»O`m¥AͺÀ…­ì›Žå±áù[ušð®k*%êŽÜ•¼#TJü‰a‡íép¨¶ •åçܳ“½` wZ'©¹ì”èU‰–uÞý¥ˆ¡¤†f¦P ÑT )o#èûÉÓ7"Ê)HP¤ð’Áv?C {Ÿ‚O´»=È• Êùtq…«ÆFjÝi™€ 5À`y×£Ô=n=¢&ºã|þ“r.ž>§ÿ&äâ"Tñ C3!<ð>ñÐÊÅ™éFÄÈ”ŠS ¨! ˜ ~Ì9NM)Å-"dP¦ÕºFªúé©ð¢ Jª’?‰ª î È•š]¨ÌvlºlÁûE]ÉT.õµV:¦Â)!¢P(…ï=Y“õZr§Ýt°RûÀ)ED„Iz&èÆ¢Oád«i¿-Rˆ‡(ªýMñ¦™Çi–DeiŸO5œc ëo~,`Ó˲¿U<,v°+ŠÉæ%Ü¡  ´Ý÷ 0T壤OI¡]‚N,²V›üR, žõ3Îö»Ð6!wB“˜•Y@!Ö7®b (zC@v3Q7J¢9ÐU)R¤öê€Y‚Bá“óœ‹5C†À¯î\‡Z4ÝBµ?¢½óÁ‚ÁzN“ñúpQºW¢,?GRò÷‚¨É‰J±éæ$`F¢L“Yy°1§yÊB•¯cΦX£]+SƒmšÎ˜2Ž ù‚¦ÆÓ/°\óU¸˜Åº&% &©b¦¸}È»5Gë©¢$îz7zÏÛDÓÊÑìÂÁ tP™¶ö+•¢e¨dóª„t¡i,E‡”Ö¹jþ@­$£&ãÿ(”Ö÷²Ýc…€ xæ­ÂÛ· J-ÒÅØQë£ãô²%rÙÃkÖ'Ú•¡-sÉë3òŽè˘p°Ók²…~–_K}ƒ³ »VèûÒ̰4´®˜­a2eHŸñv¯ü ü.ʵ´•ú1‡tý_Ÿ9<€Ý‹e„ãþ Rü¼òÞI/$}D¢GwÀ9›­(.”*|û$7¶¢hÈ(X—pñÈû©ŠÉþD©´Z‘ãöxt]¡Ò:Š~Ò~Ö ÆŸ¦ ·(–~¥‘ÚÒÉm5,¹v^ðµ,ÿמdÛ…©K IÜ’ƒ´Köz ñ€jky¼Þmw/ïŠû ® Œ!¼ANŸxqÔmbÅÊa·²w¬1 Í` IQw~ÔeÉ)n—È6”ЧìQ@ëz,£” çÚ—(Ü"4ºhëZ¾>y©ys+P‡æaHýZˆàYöþ˜è:h!B$ñw¬-µqÿT¿Êþ™¾?X?DÏH#×ò’B–²(R*ýÍÀ€ø‘¼ èßÚ·¯Ñ‰SÙÙy‡YÕ_4IX¹Ñbš³!f r`_²Á«ŒclŸÁÿ3 @0Ž™ÙJ¿P| Ûù¿óT Ф ¨­B=ú'¡d Ø”Kb¹  Ù1X9¹°43 >Y›c|ˆ±sѺúN#³R#@–‘)7»S®d»ê‡ÙÎ0Cʵð„¡)––*#š9‰Ê´ƒÛ¤ˆJfŸÚf¤[@­{4¯ZÓ:kFë0î¨ñµ‰Ü¬’eÁ_Tº3Ÿ7Áº)@ÃHJ[‡ú&¢)~®’f¼Ô½$$Ú:·2 )cÊ5X~¯lH»|D9©Á©m-9l¡òŸ2ëj°4ó±.[ã‘w¢*îâ–2ë÷BØõ2™’ $+¥›@CkC §KáɸŸ‹«$*&H°¤I51÷>œÃ[¾éŠ8ÑÜ9I1ˆYZ@Þ›é1²Z1•ú-Ñ Ú&‰pz ÉJ¶BZSœÁc·´ñ3°ÞÀ¢T Æ *D J<³ÁdFO$\DÀ|³ûñ€+kHT“"iº‘-2ÊÅ 5™ÐÇÒu$ ² ‘JJ]¦Rå‘B”º›à)w±sÀj À,\9(°‰‘J™Û 4Ȉģ¯Do¾jÆEZä#‡ë«B¬@}¢È‘›˜ Ô ‹›¢Ô`/kmÂL ­š±ZB3Š+¢š¢S’ÓÁû Ûk$)Ú«HÓÄ”| ú0¤ÛÙYîA|Bs'ƒXBi>øC ŽœªöKóéB|œ ¯jfl­K4»"Ò‹ ö¯z´?¡ÐzxC ýµéŸ‘„,$J “n@I½´sÉ-BY)ùtÇê" ñ°Ó³sŸ¾r÷åZ‰ªË¢‰éJŠi€Ä¶6[ <”t&AÂ’ØÏž„D7Ä?¦|T$ü¼-4eÂN©¤ãMd,yøORNìVÄÓµ²ù}9ô¹œù”ìn ÚÖAãœ9 GÁ\ÿÍûŸ¯ztśוá–x„©8£"¹Ûä T™4 Ï‘ ?·rëµD¡Lü ²z!æ‰HkÑ:ˆ,Ý/ƒ›Áùz*ìuÇôžÃ°Š6€¹JŸÌÂ#È£V8뛹®½SªÑ‹‘#A¨°«Ÿ ìD=“€±ûqÄ™ÀÒ@™Ûe¢hû‹´±<+¬:ŸÉ°µ¬Ì’™ñ°AÉ%Àý5H”¬‹/±Ôƒ·˜‘#à~*× Ë˜ÃúGê€Oê¨q'ÀpŠ$¡f­¢€Ä‰–¯½2:ÒÔ«¡4ºéÁ‘®¸„`|,T×Q+{47½ˆóÔDRòKE¼6óIN”é;½¹©=[*ø‘¢T&³‘'< ™jšÒx­²š±üÔÇ`­$*’µ(GDtðÏÕ‘âA$}À’ÝS˜|Äi»Ÿ ’Q»eÁÚ ¦ÿì{L«´*Òå”J«S5"Š>ë.É™t4% 0B°¥(ÃK¦±’|4l‰’бYCT¡Ú]»à~4€š >‰ÌµÖ„ƯS-èž¶øW9®½r AŒFl&mm‡Ì¤ƒH4„¶%9®Çë0™°· ~àýʹJ+¸Ì±ˆtúÇõÁQb#Â{H«4¼l.[¬.ÞJ „¾†M #Š ?_Ú& ‚ 4û|"5$FTeæra—³FØmaÔ Â‘'¨€ë;r¨Þ†5ÑÒŸÙʳIÚÙmÀ|g©¡6‰„:+ –Ë Ha a›ˆ¥Ï9ò¯—콑w±º`²Ô«K‰IL3ßáÁJ ÛÁ´:àa±:ŸÙ†˜‰ƒ4ÆÔý”²Äš£ñaa²OŒù®‰‘b%f8‰¦.Ü’Ž£´;4‘c•ð:ÛŽ_3þÚ-±ÖEL´W`£G ¬¾Šøƒ‚‰Lm1˜¾F %44ž7 UñÓ® ¸+‘WÉ·#µíPåk×ÕW`“(= âDF±gµ¾‹+ݤ[Êa­µLŒ’Þƒ¡`騵´ç¬bÊŒ*À ”‰(‡ãR~ÀÕ@fžËe‚øJÃîj×®Y®è-;?ë\°fhªË‡ØÑ4óÖ >CþmGù‚­êtí$úe¸Y -¸¦ÎŒ`ë ̨¬Œ¬j*ÈәݳX¨Iõº(š•˜;#‘9<Ùrº­D>^^êÔsþ©ŒÕ ½ëâ‘1UD¦çØbV%SC N¡øó¤ @ÝUI)aùº9dõÔA¹ŠA·ŽŠ[³B_pÏ ½GWâ€$ŸÐé¶-÷áìº.: ÉD¦µÀ4„¬6Ë½å§ 0¡ 3íÆ&jÿ2ìÚ¶+„¸+4èÙÜÌŵâ¤6E×uóÖCÈåü/[ Êîbcî]0.üë´SÄŸ ãü®‡ËYÅœð‹ ÊĈYJžÉ <¡ä9U-¹úŠˆ‹šZ.éh»;މls}Ö€EUèÑÑ-СqŽ Éip&/ƒpPå p»ÙWÞH\Çé ©SSa‹²ë¡'ÛpŠq6êÑóÛ­þññ©&þÙÏMQ¢ ¼2r>oꩨëÂî”ò@Šr±še圭"yEsàâk«XÙ…ï­ýòšôºÜ$ _Ì4Õ¹ÛÒt£ø_<3eë&1 Õâ$íuËÕ¾`EÓ‰ëmkê"äÏXOýL &‘ bO`Ø}8‡Pa+ØIt†^œ1Y,˜£+¾çÒ°/›Žöú$m–á䜩>8öô³âÞ’Mz4ÓãJ Ÿérz‰¹îÛÒJ ÝØ!Rb‰6Yä$›§Jò¸ò¡±ÒçÆARvn¥%{€ rÌM€Œhk¢Èñ›MÇTÐg™Øedaê¸vr­oE&êu0­cÊd¹û dO ì‰I½®È€C~Þ½Â`Á^þÖ“LPq›}ø~£ËcÒ¡ìDÅ/“€9D•¤þžB‹Õ4]¬)s³úFáÜ?œªΩïö5P–l0äQs˜Ç ¯§›\ËkŒ1žB"´÷ ŸZ1u´D–06)ü^ÅqP…¢Ã°aJŸé4§¯ƒ.|àloUɽ©K¹ôO3‘B½a¢îÖGÏû2×öÀ×ãhªg4#)tuIzvSF™%rÖ|2 ¹²éU4L©gI0óÄwy9E;n0"/÷ ÑJÆÔ«O(‘Šõ ¸´ÒºÎÍç ¨TøsÄmŽ£Ò^ÁÜ zé\×3a€O–šˆÿ‚@ pX ƒBá`(„-ý}Åa`8ÄMüŽAñ¨4z Çh«î ~Ë@ÒøÔjE•Êå¯Ù”WÏ`Ñ©4¦=$’G¦pwü2 G€ôøÓò¤ùªªÒ˜Ô¼ R~Máñ $.¹@ŽJê™]< …[/k„’W\BäÐjô*n“S)‰m~k€~ÈgQ 4.±T£W(ƒß$ Ê>²Óyè•H®aŸö©LJ'&šÄ&185sJì6Úl¹$›Ùš·ýº7·I2Ϩt+I¦ÓÆ´OìkðË›ÑãÜ\ÜšM¿·Nâ|™$ ¯Îi0 O†¹7›É«—~×jëz‚mµPªÓãåGÌñï~œÞzmä~ö`LÊR‘£ È×#X+‹äýŸ«SR©$‹:Ôò£‹&­(æ¼8›­IZ ³«L‘îá€Hó–7íüµ/Í«Pš8‰ŠÒ§¸ìËxô¨î;üí(Md°Ã¼­%+ë®…#N³á#¯kO ¥­ü4‚&éZ´¸Éâz»Iê3Ó0¯ñÔ A úHé#Œóã=Š4@Ø»èrèÙ*P³o7Á ƒN v–³¨´Ï;Òð•·ê°›¾GÂ<“9òHôótØ3Š’ ­P)Â'%°D–ˆÉHœÿ€ »Â°BVäÏ“hÏ&íûø%ïáúÌ£US2X ë‹?4³âW-O Z71L´§)íš2Ó·ò´Ì'µã3\Bê’†¢iK YÓ ý.·"0…¥+RHz^JÔg@ÀVË"÷or¸õúZî#Óûê…Fh›«‰^ µŒ|–ÝšH­,îÂ0Ð%(­°˜"kU­`ê´®Hó\ålÐJâ¥?Í(ã~3+tIÒ6ùù›€‘$LÒ€UµF‚TGê̪$ŠÊ^Â:JH̤ػ‚”¥t’ÐÏS+îí\J#“{®j“~âÍ@&g9AW9a‰ì´“\­ú"¬Ëß„¥²“úŒ$Ô| %;®¦Ž;ÉZSÑö69$Ñ ƪ4âæ œ3åA«ªL: 0ÏhVé´ðw=+0=|ôÀŒÑÔÀ :—«Ê_¸W@5ÝŽ1ˆU«D‹VÒ§ñˆî#K>džèèœ p¤¹ÅkDDŒ‘×øs3G®ä0˜åà'[ÄRÎòýø˜è ß2Òfãb"s¬çIŸÑKm-ز©>k7*o¿ÂLd§˜GbB—yŽœ‡¤Rõß’¥q*¬–¬Ã¤`d@Ì4¼ %ðH£%r žð@‰ýº¡ø‰œCÇ*еLƒ‚ÓÊ¡jKHõ#SÌT—`gKQçÂf$@”Å#!R QÛ¨3NðË?Ðü™:‰"\)õj¯ˆše…I¾šÔf[ži‹k)ýÄRYØ"Û%¤™É?ÚÀ)(‡Dp”²(ºé‡ëÕOÀÜ=õúFjåË\ÖB"XÝÊ{YªQL×ÞË`$VNØ•Ã2¢Œ²Œ?(È%¢Ô§ã‰¶„\Ü/´„ÙŒY‚h Í&Dç%\¥ž8D2‘ ÙGOñaùEÁüö—UXM×Tña+U£Öh.WƒU<Ã%ľiÆd‰ÇüE“dAë—éNzUŠš^Ñ\Å¿ò¶£© 𳕨²(EˆTH8«9>HþI"‰E!ãÂYôì@3¯§KºœX±à*åòHël8ûnCíëר\,¡Tʈ9R|dˆ4´ Æýº®¤«>ñõï@¤B«Z •œ°øª­fOڪɓ£35‘c,èrß”Ú81Å¥€ mq*J&f1Í×Ê¥T£ê„ÞK¤)À];x¨I•‹?®cNoiR”¿îFFºMqLõ4·a ¹¼@¾Ž mÖƒE[ô¹nÄÓ¿JÎy_’¥BìBL È0|f9èmÊxVæZ¸ÎÈ«´ 5Z‘l‘]²±ùa®ž›s@zœu(’å¸rÔƒ[™£-U¾‘ µk –h<»Ô5޾7‡IäWÏœ%ãò9;#ŒŠÉ¯é¡Fê9a sÛb#õ*óY\`t@%*2âbrR õ¥%@ ]tÕäÀÂÛƒSð< ç‡äIÏA5>ÖlmÅj;l…¢˜‹|•ƒ¯ç¤TÂ/Dgh¬T9y_@ô¬Ïšé •JbëãC‡cóAÍÈËÃØÀã ÂÔõ¸q¶åk~bxnEŽ.­³rAn¤]Ú'Ö(¼–—ã<¥£R’æX¾Zèâ×ÎQËvl"iÏË#VkŒ?*Yq€6`OÈ  þ„?áP‡ô ˆD_Q7ìT‡C"1¸„ù ‡Fa0¨¬•ú”=å@‰`\˜EÀYpe ÍáQ”ze œN&9#8”Ÿt¸&–û¤Ð'q IÿM”Sæ´šLÊŸC¡Ébo©ÄÖeU‘ÐfS*Lp ¸B'‘wÍÔwšÛ§+u®/s^âóŠ|âK8‡Wbõhe&ËÖåé- Ì]_/là'=cÇ¿@Ú;äBŸ_â™­q†[+•ÉÕª/ÍhÀÒZNê­%»óXÙDâ#žÄeOxfëknØß´ ¬–Ÿ2ÝG²@-|·²<¼\ŸK¥šÙeÏOe&G…b€Ç´3‘c–&Xz˜¥¡€TÓŸÈŠ´š¥Èò’Ä ÌÓ\…- ƒ0 j! ¤ªD)ê{˜!Ê{x”Açú<à© š§¿.²—€nœ §(»äþé+´—!ÐzÈ8 ®êò–‡2«‹òë¢ê!òĉÂΣÌ#J¢`’¢„$­Óà²ÏÚ+'Ÿi¬„œ!Še5)i+°&Ì~¡‰ªJÚÆŠ¼´»("Æä3OÊpÐ&q÷1¼ü®Ú²ˆ«‰"pr`¬+ŽÛ>®'ôúˆÍȼօ=(RƳ/ÒãuÌêÊ–äPèœÇ°šÆÝ)èŠJ‡&§Å|û¢n›¢À¡T øˆ£ÍÔû>¸(d’9ȼt‚ Ïùö³¦@嵩ƒR=È4˜!ֵʅ#ÒrPÍE¥’Ѷ`ªŠ×-[‹t ˆÎ Î€ ŠÔétŒ}ÌM3…Qôíi Ñ)2NÙÑéíòˆ[·ò0U·’ý} Ö™ø¡Ýà5æ~ijº#6¦6’+uXf-¦l…ˆ ßvÀ!ˈ84BÀãBøFU<-1…þ~ÂnÜ¿)oÙŒ·lÈ„T2ÂÒÚçu,L‚&N žGÑ –á¡F2¯ËhT7 ¶·í||eŠK4÷¢–ƒ˜NÞ«§ŸÙbÆÚ¾Zê‰rÆà×h3`¹" |6¡¦µ»F𽇢“€’æ´‡O˜¹ýpÒ£gHáùâîÍ([Iþ±ßj7Ïs¹…0½_ë"—'4Ðéϼ†‹à &P¢-15™Å -]c3Üš˜FgÿQp@>qÅZ€.wúà*ž«TU%ȧ~8‡£«éLnÜ<”}kûTóÚÕ—ýö:RPÇ—Ùò~oè¦7Âñú biY™¨ó°Î“ÃFŠ£çÔGaËUoüŠ£·„BÓN쀂+‚˜D2U@=ÆòtЩ³r@å£ÀÁ‹[9t@ d5Çɱ\QM-ª“W§–)¤‡ð@Å–’ÜÒÎi£>lî\T Aº‚ð0à¶ôòïÀ53I¾Ä„çº ƒ!RâJ6#ƒ®nïîCóËó%hn$¬öÙGñI>‡¼Ã†ªÄcÙ09™“RGH,mÈÔò¡jˆÄкñþvÛä–;Îá:¤ú—œ¡jÉ×uútžI€<ð¢´2=Gã HdãäJ—Á£K‰ôù ³É“f¯uH¨‚n™a 0¨Ñ»| ,´.P~Ÿ“ÀÄ´a%äÀÍ–B׊Yc’-iÂÈŸˆÚ±Oš¥S5.ãB-mYH´Ma©(n¹ ?™ÆÕŸ%ÆjÈdž§Bá{E¦cKxq9¡óÈŸJ`ù<5Ÿ5Ò˜úfÑ¡p†°j"´&PhѵTp[£0<ág0åxKŽB@²E¤’â­%Ú©–€jP}%YЇcJ´Ô~ G1 å*"í¼Ì¹DÇß!ÏL¡"jk"ê°Ö¢]伊Ð:¦Þo¡j88$zK£'èG-lâ³)cL&³Ð6jÍÂâúæ”'+îH®•/òÀ¤O>„"÷Ë _4—‘òq:Ùj٘˗™Àg–é”ÑÀe©}ñ®ÄKP­&e¾’5§Œ—[r.³N®­š##½»)k5²bÆŒ%›ç¥(ÑchL>âú`o­¾!;bU›ä×Xrl~2ç¢ydÆD¬8~ "J.ä‘“(Ë?ºº(FØ4q!Oñ nd7X:A“2«íX:B‡\ÑYKd.Îm)=1)5b UïÜP ì˜i‘c KçUw ý£»í hÒWZ§I†fêMšafë¡ÒQ¶ø4Òüp »Æ(hu#Ühv†Íde¸ä ä9S‚C¢óPÁD’1—ê£æ*‡ryx Be ÖúD«;Ê€PKKæj¨Ecd(Ý类±.¾ºXVûHÃc8¡~Ø•âû[UC2DËÞIÓ«Ö\Ty.ÒðªÐrq”ˆ¶ü–¶¬q`š©Œ«b碄߼ 5U*»éÇŽÑäaC¹ò´¯R6ô[B€4jX°Tæ2Mjbc[ìUó9‡‚Ö]ú;w“X^|51k\[çƒ`ø?©àS¶Í_"Ò*òZ< }¥»™…“Y%´„V²RnbV&héàͤÁÝ”8Øè’‚ƙ۽NŒ{hš“¤t‹ÑB210š:®5øªNÛ£Eã´gÕœ#t B†}bÊ­iUkIîˈeÁ¾vúlEw·¯²Ì¥{L<5¾âZÞ ŠwxãJõrPÆÞh«Ý‘ZoÇ^;€Ó²#M3ˆfÓyÜœI­Æÿœ_ewqq¦;c™žÇJ³E¨^y™àgsÊu“1HÁUÙ±€Lg䈙¨êL7ÓÛ Õ†XÀqQZí‡4ähÞßÚ˜“³i›k¼‚¤Êì]ót=œ?bÜ6j÷kÙÞß:µ挹æL² j@cG€x:ÀGí°Ž{¹K?ÉæÛ¶´JÏšÀàŸK£É3kº0j¹ê¡½rƒò©T·DuöSØ(è듯ƒ#‰º›…Ææm3±Í !Û,¾uÆížf·—uaé¶Ž§|”@2‚÷V´Ç¢]a¿Ÿ‘Ø “xQ¥¼ t[¥c¼z÷ŠZÆÙƒàäjdú«bêz*H\i.Ú,‚ƒ–ª«È@‹¬­¦^Å'*þÌ8Ðl4XM|xe %Š^° u ß  pHfĪ„ÆcÍŠª¦ÞÜŠ\aÆv—ê6ö'Ì@„„e†Žœ ž êµÃBÇFR<ÎÔ€ïÊfXcÄJ܇Œ£¬,ì¢ì.íL»b\—0aN'ÆÈÃÄ!ú1(®UˆØž àÅž¡çjÜÍ2håâ‚M:hð/”"i®mðQC{¦–Nìì!Ëžã"XÅRc)Úù¡öIb–ïjt¤ÐD¨¢Í"ކ¨³¡ö½ˆ@ éä˜ Ú'HP‚êÆJ,hŒBêËcF¨…û #‚°·žˆ*˜d"¬îÉà8,þŠ­Ò#p?¯éD&é¬ÐmB ¶$[K è óç–ðŒ=\)*ÂÜÕ(ȇ‚§¢l6éx"¯‚+\-ÆòF è{-ô”Ê׿•ï´O­òÐŒ Kð!‰ÔƃäþÞê"8b£¤G‡!õÊ|jæ†Ó)òž¬‘‹bËP‚Ž¡ø¸H¯ŽúN¬¹0jhdªÒç`Jç’Yä6$¤}‹8fâëN‹Àòª„)qˆ‰È‚– ôy1áB`Īc-ÑBêÄ£tÕ†ªöŽ½Î¬3Jª9l`ýoàž #¢Ò˜»º©š¬àÑ Í%Ëzý¢7 onì½ œ,<û¬Lò(æaÅúwh~¶-Ž!Ÿ òÐÜG¨TQ&jZ&f·ŽÔVŽ^JíøæI6mS ÎrÝ Ì¿­ÎÀ¢í¢ê‘Ïjðè%ƒ!‘—1š%"U mÈgÆlû.°»È®ü‰àòü>L\¤ñŒØ¬®VH‚Ô€Ñd$°²žˆ‚©,¬‡ã)ì†üBe bmðî¹kÞ>‰¼Óbž¨ñ0"1Ìô*Ìg¢&íFÄdúúNõS6v¦v$£ò»ú`l–ØîÔ…K(z-&ˆ-LÀ.£û6IâÛ «0Be "B(É´”ï´ìå:€¢“9‚ÉHp©¬ÒÞ˜ÓZdSï¶G"'É(ëœ4lPCc–GÐ6 0#òÄÊHÒ,Ë?Ý "gq¦ˆäÐPÉô6§‚ÞÄh‡K&µòF°nþØäp9ê/ÃCΕ"îvÂRlç±ã*ðÞF""rœŠC8åºA²r4lxoL2É} ðÆ‘q´”þ!ÃÄPA;ÂÓ“ ¿` GÌZÝÒe+ £G±¦gË"3ôÎÚ”vçÉŒv%hd/ü?£4GÓ¢%Í’1Àåk\’-ö´m(×Ãj™HŤ_©<0 g lðsÊþÓÔèsÈË­75!ô€4À€î¸/ÇÍ)å;5 7 ´Ü2F‘D#òÅ äH±°ô‘P‡HpÕЩ#CBñÂÊ€¬ÔY'bêLf¥""]#0ZËðo†—èÖ9 XÉV°Ú4UB\7Cè9 pb'9ëÓEàþqÂì‚8ƒÒe¬J³r¢J˜ÇªçýK~úëß4N°¼ÂàÕ3ÄæÌätµ„0ë^ËÝŽE6´ä­oÙŠ è“´YuõS†ZaÂk[C9Š%FòæpóV2(ju"UJˆ-ª!CòmíˆÐ‡‡_O¤[ëÛDíÑ3Ñl< «äª(?¯€u[4’ÿ'>B7-‚UW³N½À\u' @{ ™Jï‹SÊAôšäÑRõc^áì%*Ò’ôsif5ík äÊéðÄÒ /¾!z»®S褂†9jŽD­M$‰1-°_uÌøSš! ž{´Ç6æ€nM$)pfÌßVf†˜Ç†ñÂp஑¥:Tb"–ÆôªAý–`<ÐN¿áùrÄêÎçÒ8 ‡B²¬gÍR"4eÓϬ¬1ì1iorúuQfS º©¨´cC¬\ñ—”ö$'G©Y5M<†cœr{µiÉ.Ó0ð]w|iwN2¬Àr&Óp)C²0ž ªø,í/bÖêvÝtc§Zc„.·§"Ê ÊtGÉ'Cgb âèÃCw¡òƒÓè-iªÜ‰Üü-"©„"ÙM|ZÒ6ä ÙÓL ‘T»F±mT:?You;VíÐΖš¤#¬Bl`’ô~;l–o‘vâöæ|Ëñ^ek..±kiÀÊ®ÝØ"t‹[Íu2 ƒC¥0$«i)RF‚Ý…¢ëUíMeƒ4nhœâü#ǃQn9Sî±&`Àl()rs¦0wb=‡ŒXH©”І‚Uk7G+;.@£3«*’3S2€r¤}ô~ü@¶&Þóß_ÙehÔÉ“_ö¯Í|€ø¦§ìOï%Mr’0Dx5=ƒí· 55’ë$N‹¯ˆé6*Òz›P:¦úæl5±_xÝFïMVº²Š˜Nå´kMXêØ’Ü·9–‘S>x|>P/Õà)*ÞÚæ¦ó%\VjN–©"¦f‰Ž°J¯è^4Ú6™u&‡HZjC‚9é1Ž’[ꈪ³'ƒ¸ÌÙ§•²¾7­ý7¥|ñÊò¥žb®3ƒóBd›q”h?ƒFf†vÚuP&Wo“` pÉõ2eúClP#Ó‡Ÿ´=w&ë\¹9У0c:•2ÓsKV'còä&auk£uâêÆŸRªe¦ ê ›ö伤ÿ bZ1§(•þúQÔpwgüÞ Q‘M¢š³¯sö¨¦piP'<~ÿ"†¡väÆí.ªé Pii.jI”Õî©&¿“#„«UflXñ‰¾²–¾ë¬&åO¹œÇÇZ·GP¦ú&:eÐÞÆfa¤G²xÉÀðYŠ…¯‚œPkHŽ< ®ÀÛhÚ¨å|Ö‚‡‘†Ñе_ì"ñZ— ’Ò:978LÃK£Haõn(à £|smKý•ÚeeBÒ¤LËÍ!PþüP) ”*¾Nˆú\TÆ«¡•œí©6Ô*Í,÷¸+ð)9%œ[LÔ[†Ù‰=aþ>0RÄòº½'éôo#XÜä › ŒaI®é4ÄÔ玚%¯®{KØÿ–9ñ)X|Ò¸jl6ÖHŃ,FçÓ ÂUm\ó€|ÖWµ:;gÊ™0NÞ"z<ô.fÕV!“•½íö¡‡±øf*Ø{‡w§XiµÏ3ƒ2€oÁ&BGtHg=]o(7»¤8¯Ç<ÿ¤âRC=€’Åéå¿ÿ‡QG<ã¿>gä`r£>”)Iz"û‹“Ó™e¥ò±‚(ZE˜Kã½ÆC‘š÷u H³ l =ˆ7‰¨7ãÙº)nøúïð?2Ús#û­sC([Pª…¥´Bt÷|Y¢¨¦ ñR)álì *ÖBêHúaÕ‹S7#j)ä}èçIc¼¹â.Švb;¢MR»*²üqþçb*Îo_V¨ZÎÃ1æÁ6ƒÞÌy&— dî'É;—‚}üºí|¹üô¡p` «L,®Û~ºnþ¼‘Žsü–¿V±ŽÌiÉòûmÐG¢™‹]Göׯí»Zæl9wB+Š¡'K'ÕñŒ]£Ô¶fª-ÞQ*ö¨öÖ£[æ×Ð- \Ö‡âq)­|ŸoÝ¡¢öv8Œ.øc®š‡€¸ëÊ]a>û{¬k)ûöžCnaÓø¿5è,>Œ .eÄÆw[§¬zf AáØP ‡@àpà0 ~¿ã˜8ÁcàÌr)ÆbÑ`$®I Âóãîi„gGܬõŸ¨HÌf%1ΣP(µ0§N¢Ð9ÀùU|Õå *œB%ƒÓ‹R9!ןϫTÞqÕ_•;„v “@©”:äBݲߤÊbj}Yá“Èæ€\ౚœS pÆâ+SˆEÂU+„G'‘iÔy0˜Â#0‰å$£¶wÌr Æë —HÌRÉtN¡ÎFˆk5’¤ኂܪ¸h”Já˜ãG/:˜=³'Œ]ÀÒ§†Î+5»Æ×ÙŠO2¬ %ÀƒãbRþeV³(…;Ä¡¾âê‡>.ùŽÜ7  ‚á"Ïʺ†0Ìúè¾€ ™é6Rá µh¢À(²Æ¿ÉJ8©·é¢Œ» éÓ@• p£ŠÈ½‹Ú ê*°È‰5‘48œ.ˆô{¯1öÉé²Ò ò0ž'KCÀïñšlõ" ²K© ï3(Ðl*.’ú!ÑÈ{NnãH(£æð¸MDy+¦ÀÎ!hdð†"Ð]# ±L©$Nühš'Š3eÁIZ,Ã9ÒLn2%NKr‰ü¥Ò'ò²÷³Ô‘÷¿GóvÄÆè‘ È<6ø«2DÌ;U)ü½¢Žœà”Ÿ³b©¢L¢Ôó¨:ªŒÓˆËd©¨Ók²؈uJÃ#ˆ”„Yˆbu*»*À‡VÇüú¤3p¼Û€8óØhb9€mú± "X‚ÏTP §ˆ¥ö£T,òª¨Ë‚òư֚V‘ ©ãdСSùöÅ­UX ˨¶CÃËÌ{⠫ʵYwZhŒ±³Õæá"TmS^¾R”œ.T‹%^UCLÙ§Õç§ ’pä)ŽTv¡¹i¶©„!’)8ÝW­p7 ãnš"ÊN÷!¹‰ö©µˆ–(ŒCr Š€•’*…-€*y•nªÌÂ[ú’§¬¥Ñ>\}@O‹Y”¾/Nî³ÕÈXìT 0«V¯ÉǘŒKŽ%rüºŽ_õ„!/hËq5B@%’ß3¶5Z5©¤ÔôÔ*Ç!5×·“ÔHÞÈT¿hk´ë ÀKG…X^5ôOÖ]Üvp…xï;㎵I\±C¶Ê‘RíuFÌŠ1¹Ï:Ëúh "ÝÎêòó™íßÜ8l†Lvê"‘gÐÈ+b7ì°~’Œï@¬"„éÁv6EÒ±+zÃõ-ŸU&JÍÕƒŽÙ 9³²ÜZ“J/͹ƒ.@}ä tžRÚHrL}çeþþÊÂDêT«¸æ?ã-jå¬v`á›RAn±˜ÕÜY úñXãõbÀ¸&z ¢z|ÎÁ^¡´¶qÙ]§íLE È[ó¼ld(£2¢¦÷£oBìýª…D÷TK*ŒôErÊ\1"OÔÉÄqóš3Þ„)¯Aå<¬c DJÌ%¹§Z‹;7E1w1ÿš¡3&…€ó¨óÞv"NJ2Ö˜­cØ,ŲXCõröJºÕŠ\ Ô>,…KvC'ÛDJ…P¸µ y\qËi“Ƥù²ŽM”…)b(!:ïƒê•ªJ™Å'GüU.½%ôñαt‚2œ~ $y×KÉ ¼¥¢•*qyN¨¡B7e‘,,rV‘æ»3dÂÈp'âmFÁöE‘ÊiÈñ£QbŽTb#* ~ÇG ‘'„ Ç•R$Í#óÇŒµ­R9›æš{¡ âšœtx¸¦sI!PÄøÁT¦?œ3TCm²ª†ç(Ì0~ŸbmKSxž1dÃÄz†ÔÙ+šHÑcã¢èc%\´Tbª¬*Ed¦îMÒ!ú„hm¥ªTºÆUSU¹¥ÒÌüS¹þî–Ó¨°r¦:Åè©õTtµšeÃŒ†ç¥‰q¦eœi…Gé^”¼~&¤ ìœbÅ~¤q?ÚÀó#¼ekäн®sXO+èú}VéGÎáö©fª–r•›ØJ¼V—¤”bJ°ŠTñ3“1OÕ…—L…pÙ" ¸Ï€+}*·Ø}æÒ³œ#°UO|~È®„E§i80Ä*ª…tUx ­+ I¼ç^ …T†ºMDx°¯ŒX.˜”aße“Er*¤Äæ¹¹ mÃþ«nÞ†¬S3Þ³KtÕ5ŒieTYÕÙ8$PËGÚ™âyŒO;v‹šÍÕ-Îaù‡ÌŒßÜöýf²œ§ýW³ XÙSð‚{x² »9v`Ò›—+f Mè³âñ¯¸^"vJâ A%çׄ·L´ŠÈuQÖ_H×íP°hCÓ!¾T΀æ.·V‘(; \­£äÉeòuô¶75êH!`.†ÉÒ Æ_š¨Á‚ž‹W¾p®@½É)*~¤á; "¦:¬Ñ;7²‘Ç#y¸h ““3µX|ÀøŒ*‘£-—¤ (º3 €°<¹Ô¯«B•Ÿ %©BÚ‡Úkâ‘á×(žm°+ +SŸXœ4ØÇ"ŠˆtÂJà¡'’h„d*8Ó;òƒ—£¹ È»ëðÁè~¢k)2(=ŽÂþ˜Â=rˆ¤8Ï-Nsþb6¢Èˆã;½’Ä•2ƒ­Ù ”ãÞÁ:K;륩:2_½`ábÑA±x$˜©—ú¸àÙ @˜ƒ‹ÉÉ" ¾Û>¸ðè°.Z´'*IXAõ:lC[¼9®ú‡âé, öžz,¯J¼ «6±;38«}©âŸ»;m‰É(´[ÅQãÄÈŒ5J ,³¡@£´ˆÃŸŠ$6°žCIN¼º1'Ì:P}$3j{01®5ôb±(~"¨ŠCD•ƒë¨RP9`9ãH5I{§+È'ˆ¦ t몔V úqŹ㨱ª=3TÃ"F5‘¿µÒI©0¢»<²:¢’{p£”N*ºRŠpkÉ™»ƒ)/¡'Àâª!ÒW‡âŽ)‰¨Sv ‰DºçI“Â9ê±ë‰¥Sö¯Lyú¾AP° wEŠlÚ«:»c‡Û¶‹R1‰w£ 2Z ¾ !Z³á;E‚l‹‚Àk˜Ä ÀÒ‰3° [x€4Œ·3¦Jù%/,_iÖ É³B$0®D#+p Œ Â+ù›1‘ˆqjF»)ÁʜȹÙG@Üù ”*bÓ$²¥ùû›LCK‹ñ³@Ö ‚­TÏú47³ ‡ð£0[‰BR…¶øÁ¢m‚“AIÉ3äI·óµJ¹NÊSZ3²Z»äŠ7ó¼Ä<ƒB¶¹G$’Àò‰“1Ųá©AÔZ7J9ѳ=ªå“Jš ð!!áìè«[Ë·±sÉùìÆ–œÞÁ’·b"Ñz<º «=À¾4n‹Ü>¨2*‡è°>‘õ<,쿸Ïô¿Hj7DÚ/A3´7ð‹=CT±xà R¸ƒ‘ÿ´°¥¼´¨”“R¯½ªN7$[¯IŪü꥔6!GÀŒ Q ÁŒb»ŸºÑÙ©¢œHŒ0”˜Âr«J;‹&¿óѧdLÆE58Þ0ã@¡3KÞ°"Âi"¦²Ù â§@Ê¿²+­ÜŸ•‚«?|˜ d·ÇœÑð³jŒ ¬ÓмY¸ 4„«œ Ë”ßô¿s6´˜º@ëjP“D F*P*” t[±À{½©ßˆ°°F‚ÚHÀ‚™R«é-„׸ا.Z‹Ó5L‰¢Š,œ[[Šà©»ø±Ó¾R$X‹DW¾ã:Âäz3A³RÑ8²ƒ©óDK5¹z¸°¡“ Ñ(›2ÇTŒNŠ(Šã[*I8’,PÆ98%ró—b|CY@_Æ"= ÛG‚S-ÈÕ zÛ*ÜÑ©-Õ¨ ;³½üw)TùÒ¼„K#WŽ4áÂâP,áùB=-3Á­»Òð¼Â´ÌŸ¨°9¡% `ÃKL ±5M…¢MÐ`2 ]Mv#%uºó‡.ZÒ(µFDçÆ+N¶µ‹DÔ{ñ ÃäWŒSâUdœ‘C="¼ÌŠaÊŠø§+ÛÃÖp~@;È3kgLh¦XŒ†Í°SÙ£ŠÎ:Ws{Ý£472û– ¡*‘3GŠ_ãV ®W%þlDkØN<€^1¼„º½B?DûD›™" ¬?ªHãKj¼ KËCcдÅÍ•ì!$=–)«&ËjYvccØì8ˆ±l9\5#”ÜLÉ—cÄÎÉa袉Š_¸þ7×iã½®"_¼•Ù¯]=Z6¶ªM¬¼¥Ò¡á㮈îmׄ'0”¾çË3 >™sÌáÚ[V?$ÔÃŒUj0”—ÊsÐ`ˆ=·Ópjk}CÜ­TÁC­Ú ÅQÑ ¥…¦%)ZTb§¼Øø˜Š™•!²Aü5›®…©Ù8Š1ûÁÏø|ésÒk>$áB^W´èœŽn@ñ ©ÖVÁ(ãĽ3·€6 !½Iús° V†_"ͳ˷Á ª¢9fŒ“¨>^6áÃjH€º8#ëR ¢äLž$šËž;¶2P 1~€j¬$Þ¬ˆD3â¥Ã𦠆”×{²]Ð1êgh¥r¤í®HLTøK-þÙ]§8sWEæFBΣ = Sù½y‘Œå;#ž´Fټ〫6£r_6r,»‘£ñ£0iúì–2®…?¤Ä#ܰfk+9ŸtVFji ªàtܺuI€CÆ>Rhã/v9ˆvÃ’}Ë)ÕzF8chÙ¸3k£^2½Ðð,ŸÐE 1ª>‰¦~;A0™5º-eìäå×~ËÂ.Ø@½ž‡Öí–µÌ3:ž‰o×+´Qä ’¡!ÈSCHE!V·ZezÙÞÜw®ÆB+Ã=&ñÀcj¶Ì>9µA_Ev8ripþ7ÇÌbóòIÀ2¥¹ñ³¢$ȶÿ6ä~ð„ڹ·~°œ[šã{\­7¦ÛVX8ŽËßW<ßèôóS>’;QClõÛ*i¶:ì§O˜ííó5:É37CŒ–G#­æ˜}<ðö”¼2lIö—vœ%d&e€§Þ Mÿ³I¤LûÑ’ s'Q ÖÜÒj3ká"Ö ‡Qa¯>Â7{-p™\Ü –¥+ò¢Å@w^G°j“(² Àë3£GYåsÕó‹/;Óvª¡Ï.÷¤‹jXÞqJ³K¯F2[—}ÖÉ0rkðâJ»)Êã>Åï÷$¼€žŸ•÷äÕRPãWnpáúã€"*¾GrÁà?³£wp鱳ȽÛnSrL‹Ý€çDò ´ï_gN‹j ¬pÓ§t-®7ö€ñ£Ij³rY’&&Ìr0N«j*”§{êqòÄì8Þˆ ^°XŒ¡Ñ¶—ž<Õš·IŽè0¸‰Àm{îû=ˆ§D¨±c U1€í‚$L(Jf®¸¤QÃÀ kpª•­×jì3¦^+Ç?àÇ!×%z|àS½>ÞŠe;6L·B;w) ¯Ì3cUWÙË‚Lº1=£/™Êt€ jdôï‡Þöd5h-›†äºÇ$´c*Ç#‡ùáVnkÀ-z×rÔ~eH-p+7©^'Ä?\ô }á>ß?ðo ¢âÙ¶ñý§(Â{ ^È ¹±§ˆùüÿ‚àÀHCî†!ЧÜ8bÐGüJ1~Gb€) E¿áHd¤‚H£¦%3‡JcÙÄŠ)8~Å€²™äõC¢hÓäv12‡Oôø„~@øªH€Õy 1ŠVdù„ª4’Æé“9„ò1.‚SÀòx£Þå~L&)dn}tßh0‡¶í ˆIéIäà ¢E"V©mj 0·c¦” ÅÒ!>¤¿ùçE'ŸD)pÌ %¢|⡜ سºYbS¤§Y'ºM —˜–úM¯Iëpj$J}¹±ÌäWH•±ÿ<ŠO¢\˜u\ e‘IäóÍfÞA7œg ’œ°‰Ÿ_À›çjOÂ²ÙøLDãµµ¶Óã c´È, b†¾,j¸¾¨bD”¦ÀBH‚R¢;éÃSÁˆŒ‚ Ïs; ¨péÿ§8ž1)h,©ƒÄ:N`Ô®‰xû&‘Êù!!úÓ€+[$ÁÉ Š‰F‹Vš+ËÂj†HN ›J1ª@”®‚0“¢K‚ ‘BÈBÒœ(ŽÒ_,Ãi©&€ ºž;¨DZŠH ôÊ~«ÒUÎ¥W74¬:MJ¨|=4…oâ'æI¯9˜Ôä™%½$¦™jÃ5Ó–T…W7&FÖ«¤ŸRIJNÖ%)õ¿6¯0z‡O*íbÜ¢`Ôì¯<¤Z*U B” c¶gR½¦…_ÍR¯m%! •å²É üV»#î]"³¶Í؇Fˆ†8ƒ_(¨”!‹¦ïqÆ*’ìá:Så$÷"šº`Øbž¢e`v„"Žæ‘'ÆÇ`Ÿf)ãØŒtÓVÓr€}–6=KÕ*jq˜Â@WH%9Žï3H '\rˆ@ØNhüÕð%¸‡'É?>¬t(íEÖV4kHr˲w{cÓÞNVË4wY%î\~úSvEQþ9 Õ’bU$Ì9B@[“iUH)e2†zî‰ìY(”«¾ãJB˜ ƒ°AD,&ÂPÕN`é€5D­‰£é_„¤·Ö²•ØèÿlN$0öàûVsçHÇ4³œ%ÂCH=%åô³sX¡É‚Ÿ Ä@º†‘zIy&—|›JÕÉê¹,6‰v]¼ý–8ô¬l#9l¦ Ù¬%Pù´šÆ$2;ˆÅ I+1‘ÍΗ¾cèÞa-;¡ùeu¹0ÞvåÀ`±‡,æ{1Ö YOij7?öA÷±•m@ÝX¾Á- yS“o›‡¶U[]²Æ¥í.&ìTÖGÂ+(“š¾Ûµ’2jw0÷ÌÔ­Y]ï¤ÎYXö_kv=cÊϽƷ§ñ¾¬‘NÑg”AÞXMMFáñ©æJE\«rŸ Ç©n@ ¥>§ŽÞäPçÈ*3ìúü¨hÅM܉â”À͉ZBøÁI–wþÅ«L—ëҋ¨¸ˆjÛ%\ô!ö-ÉH‚CX=ŒPÖÊŽÜËÖL®ôì&¸æÜ¡üä!üê8e­–ñä܃æ @J.2ãši,T.†büÌÎRoFûçe±Êî}&H½®¨++ÐEF”¬b…ïµ Ãmo®†¤òÒötéuL$¸¬4Rø;CX}Ìe,¤xvJèüHFjÎJÖªr¤ $p­PÀäÂ+*lç ¥MPÛm¼=ô‡Ë„òSÇ¢D×f€ª/:§ƒ*zðOEÆz69°–†¨úbBp¬V,ÏR,M~R xêîfTbÎ>(2 ‰‚D Ê;g´E­B~æ<ýÌ¿È _‘.F…~É,wL0åï\' nâéZ»òý¢6)¦‰b@‘¾=-ò”ªîŒGþ qÒ‹¢ÂÎçÂ$xæ.쪀dŠ‘ˆEnJË ` QªÕl׫ ùI ÐØ®²¥ëÈ;"®™£:ºMNφòÁæòþCš¿‡´ù TÆxú'xr&½íNF)§ÆRPìqŽþ¡PØs \œPŒ«‘º¦E‚Î{m,¨zO|öÚ"É+ѲÐè} iÂ=èüo.Í–Öe„„øgçt/‚úf2’ÚB¼ÒºTÌê*…à’Å PŠ%Mz0&b-Î`-ÑÒn.p‘“ Øþ&„·þnæ%Fw¤RóâT§ˆÄþçy&Pn# š|¬fÙüó£¬ó€Í,×ñœýMjÖ‘ 2‚žœ$Q rľex¯ ¨>ƒðÙ,G+ä$=.(ò‰6þòO%L_N PJŸË.$¯tU‹*ˆæ²3çÌø3‡Å!2çx›Ñ„ ‚IbÅ ÒàŽîR ëxÐiä—ªÞۂΟÎ"÷&ϧ2IÈO¢p*ÎoâDæ ˆ×e ˪Þ}Ï™(ÈÝ«@;RÜaLn$¥¿?nâ¬(/ïx“NNË'¥â,ÍÌÌ! pb®Dˆ. P{òîœ& o'«=>ñF$l„÷Ô Mν0§'JWæ2„ Ĺ4ô,¦ùAŒ‡D…¢¿DS)/ƒ“¤F#Ü[o:˜¥ø/,š/§ÜÇä®ni;Üs}3hÙ‡N60C뜽´nHN`O‰²‚"p¥"²˜²DÕnÛ/¥jöQÝȾXSuQC)ƒ‡Ϋ@©4g‚¼§‹¼«´æè+²ÜèŒe#X§”I o:g„!7BÙE„ObÄ@ILdž CbU ;q cY,ðâäø‹= ”ŒÞo¾õ "Ñíj“|ܲšnñ±&Í‘8èRÍGl!>mjzó<î¹e”ZøèÄe¦2þŠb†c4$£–nЧ/жA3.F14ô@’©4×l¥@ˆã.Fø¦ZâN&…¶IüŸÌ=TJ¾ã \WGÅGî=B‡bfÎ*—Ì<Ìï¢ìèZáô‰ÇP4J¬#–¯²"o5þÆÌN.$A¯bè-ÉÂO,£ ‘B×bx@ÍwMO‚ˆðoj…+V‚Ë1ÐߣRÍL¸‘@MÙN5¢p6;NÉWWâ6Q´eS ¾óÒvd‘rÏJ“GðŒ¿µ|£ƒ¥&F¯4H„Ë3»1NÌË)¼Š‰I ÕJÊ”<þðJåI'QBÒ‡¸_ƒÒßqoÔ=FÈ€ëîEaŽzYFy‰WòàY¼ë‘š‡mNÇKăµVé´…lñ ‚S+ @¤RV .h!Ìœê!ô‚Bܳ"û-Íœsøõîë Pê«Y jW,HüŸÂ`–ÒðȇÑвûÉ7cm„Ñ!óg3¤¦ìŽ´%GGRÌgÈy2—LNˆ¨¶òWJ‘]¥ÆÔ…•,DQ6U †¯ÿ$µ.Æž#µ8£U€oèVtq“ODÁö˜µXïø¡P¸½Ç„Ì=Qæõ'ÒiQ’/}ówJ*¢ W.siìˆNe±6ÖR*ÀËiŽw<.Ò`í*ã²+nEW‚2q‡Nf/|OŽ·@÷‹JèÜçÜ¡óI¸ QL²ùÍPfçÓt3û.×wk/3¢¼âžÛ˜^¦Í>88Q˜¸Œ®¥~¸VÚTÑF„g‰`…fTwñf"xñŒµmaýtÑOЩsŠ’Ð„÷ d‡Ï|Þ‡pbézá,pöàˆ4K|eD…¿ -,ç5ú •¹£„£â`ÿ†FwQŽhÄ…5Ô?° $¨>Fù P¾%M:H¸ûu‡Ùp´F*Û~l}Eöϰ¤°P~tç:½6'eã„vs mˆ­°$¦2kl‘AwÓq]a‡¡K´};"ĪŒNî–G„ÍÑŒŒþþø*Ë(=Wni”[ ÉÒe0´"Ù …]i“øæc+Òfð2‚(£ù©«ï•.üxŒ4ü0\x2ŽZÿfuÉfÄvø„ù“QXÓ9L“rCm@`ÉT}#„D‡Ò‚ùPøx„ÔÎ; A_’ín0û{¶ªäÛP¬°+˜TjGì"[ñz‡³^ú‹Ó–µ3GfÑV‹ÛsBpšwNŸƒº¦PÎðö/d$áµ¥ÆIMX“Yàú6…RŒ_ŠnÄ,ljMc¤–VMœ³Ñh+8{‚ À—Íõë_¹þ“L0'…MO‡Kf줓¸o— o2™¦äG#Sê£V‚ó•¦+"œ)åM–›§OÉä(¢ŒÙhWY.cf+õ–› Ì!2ø¾¦HO§²w;O¤áõ0èq;ÍíDµžûZì<;OýŠf˜¡Iä/9à– ¦Ïçå Lضè(‘¢ÄD®(„ ÿœè5¬ÓJf”+xŸ‹ŽPo0JžE¬tzæbþûN/¸šâòƒ… ØÏùˆ…lðË$ÂŒ¹Y»E•m†g‚S‚!›y  õÖ S&Ð7NQ¢S-Ä JU¡ˆõ¯6¼¢0s(ÔÀ˜ÙmžŽÆ·!ø¦ò$­A*!'W!ve‰/%#Z“|ôk*Ç0yÌ@M8\kERœ­´Ö€Úªï˜.Ÿ@*ºp5;‰<è'ÍCk£œ¾ðҕ˾áï HS*9Â'Ãc¥ŽêUʬ‚Iåð±²yQÌ¿sÌÜA¹ê4Y”Öµ¾'Ž 5‰FËó3´ ž6ϾÀ™³n9°~†¯ß/RõR9"bKâe0~gº×î°!Ói â¨ày~­é‚H7}²÷¯£DNίyYu­Â$»ù(-–QˆÛ‰µÅ Ü6h…­Tç·À#üÔH¨K½Fxé<͵1o7‡g•hÃ$ùj9d×R–¾ŒÓÜØNaa† ÐMm(*W;!^OïW0ß*B–Ü跋̃œ+(Å$‹ì¥»¤žQm ›dûm/­–ÓjiÈ]içqKÓ=Žá­ÉWQ%7/»=f 3Luã¨Ä·ÈdËôòH¬…K$ó[Èû`õ 4#Em-ïéý)ÿck&ƒCðœÀÙç.½FS/„‡ÓêW6;°UŠ-~ìÖ¢Ìù‹¦Ø°6o¹yÂÇ å_ Ÿœâgdï»9­îV-EàU¾Xü)/ìpe­¹‘üÙì®ë<„€ŸÏÖÕ# §5™dN°ïK9ˆz!á¨p”÷^á°ò¦ú…ƒñàŸSÃSˆ5>iÖhS›ê»Í­ÑˆFH5:bz©Fo» ÉêÝ5rÖë¯Ú½ºY´S ²­’º%6®º$T4Æs–½Ôâ-Ÿ7»›·.èÙ3.þíúPÐuS ì0‚÷1‰TEUñ¹° wy‹i¯4D í–“B§ÓÒÚï¾'ö¬É „f6ç0Þ]ðz~$b0xëÚ…)Ó»ã™ÌK:Aå÷GŽÞ¡ø-ÅMµO´ÏôHQí×;›É=2r¹Üåî:ŸÇêì3Õ¢âüŸ€[î“`(Vý(S\v¥èjáØ1ûÇÃ’écdOe'¬„'Þ½gxà$ùÉLÉõ2œ"ˆšb? è3î…@€Oøp ÷‰b€8³æ0B`ôýÈ2Y4û)ˆØPM&‡?àÉKög"—Íæ±éðM “E€q‡Ì¾ %š–QLäði¼ú‰D†H$¹”:{Øæ¶0;ÚÑ ŸTáÒiô®W5¯¿éti¬Î¯†Zª3é6qŸI¤Pʤ–k ³^@Yp‘›Ñ°s ÎDŸfbÒ×Ä3™äA3]4_5¥ß°Uœ2$÷‘H+Z+û¬Ûâ8æn7‘I´ïË5É›Ã&ùé4¿8¶?ê¯éœ®o3à¤Ônö‰ÓÍG¦wyœ:žÚE²Þª´ÞSD¯Iz0Vc3}~ý`;srŸ¨(ìÔ!IÒÝA/"á"‹Z ü?൷pÚ¾¬Ï+NÔ ŽZäj3°”¼ès=¿gÔ(Ÿ¥ëêð”ºqcŠ%íü*›¬ÑT½€I" 4.âJ›Ã§â|I-ŠVÝ/Š胡 "LÆG€u?rH›¤Èã®Ϊ_00´&Ö€ø•¦süÏHÌ4ÓEÈô†½¼„7Kšúô¬)úD•¤|Í3sÙ 1¨* ᤱRˆ—ÄÇü­€ ̬Ìòʱ«¨‚/¢Ô9þæ%+ìø}¤Tµ ƒ0à @Ü#ɺ–ÏNgüB´ÏíR~»iœŒ¢ER̡р T£+6RÿXÏRbéÇéŠûPËÓl£–„Ä’¤Pz¹²Îœ5D®°ˆ8ˆ$¨ø¢ÏíÆü[Iúˆ›ÊÒœ‰ Ëe 3å6‚(ˆâwU#Õ+üË^–ݦ뷭¼ ½´m-`]€"}AASCÏ B®Ýí]b×áû¡Ï,ôºn®[#Ó}èÕ‰ªãZ€ Z‰qNô“öšÇ+t£4‰3c¿l|¥– S ü¤#(ÓböàÈA·¬#“*DÏTî:1JÑ[Ïgiâ œ‰·&òb£!_H¢VIÊ(¹$¨dUEºH5ö÷\~U˜ÕŒ‚$Tg=ÊòjŽ,ÉáÊUÑ:\…&³|Ëwp· ©Z)¦Ðˆ(Š4ìJÖþû>Í­¦&¬f³+wó-È!ww^¬×´¬é»{S0Õ‰özÜØ ^öý¿žû´´ý†Â«ž„Ö‡æúŸW¯²|È2,Ëò" d%“-޽G­ÕʘÜ|¥Ôƒ!’ÛÆ3Ôò[À&û)¾iùräB·ˆqD3ÊÀ@§´“™ª?mµ3~cÑò|Ê%3¯úÂé ;Ä °©tÂäÉI"qxÂaúŠ«$p¥£·ê@È$YK<-óìG ceÄ•9$Úʹ—DÍÉ3BƒöÈXúö=«ÍŸ=ŠŽy 'Ï̾¦³HŒéž4ŽiyDu@á {ˆ©§¸·b»Ì²*P‹´’­ò@éÈS–[©ö)ž–‰©/²Ñ™$óáùÔqÌ܈BðªÙ9±cJp•Ç‚Vg›ë«!åÀ:Ø2?LY)#<ü ‡B?—Ì+Z2öèxP*>SA§*@|!Ì-­I×ð—I+_(©­8Ué«B²ö .4‰òÈ$¬…G \É!‚*”kp™Æ"óÒxmÊn+¥¿)Çó¯˜rùÆ'—GÇô¶.hI5¼7ÎÅà:ÏDÏÎb¿e 2¨˜kq?«fæÇI[òÜ©hœn ÀU‘z4È i$±uyY&¸Ú?Œæ>Êpô³Â(vKlsM1f 4ò^›ÏÁ+(ÇT“=ó]J$@&ärt’©ÄˆãØŒ³šuP4M¦±{¥Äz&¨Î{\YÕ6$½Vº(G¡7KZI‘Fžµ’Ûg‘XËL:hÇëk1…-…Ä£·:‰ñ±)ntí¤è· êáŒ@ie&³¥dì¦dBNCŠƒ@, ¯/hí¼r)_`Ešii$Ö öÖ•cl(„;iÎÓQó¢E–ra®4„®¦OBO)·p a… R†#»BÆÕ +eS–¦#²8(²[4~r}®™²–,M1GÙÌê,ªÖŠOAÀ‹²oEŠZà™e2„¦†ô£<‹µIÜ ¡ Oàþ»&þEÑû!„‰üâˆÞ@ +ªPB‚Ò8G-‚ÓDd@—œâJ02½yÈUÂ!&øAKEíccCéUü! l_êC•éD®3Ø͉KlÜ0¶VtÙR^KðÝýpŒ•âG cˆ¡ž¾WºL€C© s—`è-ÇçE %`ªÊúgögïI‚Ù<·dÒüÉŸX$~öË|ˆJkþ$dåÕ„‚A´ÿ“@ü9ÛXlK5{œÍ,}ŸkÊ?ܨ†ÊžØþ¢:z‘Q{KiE–œÞG¦[7,§ ëœqɾYʉhïÛ¹ÎtõºÒ›Wy¢óó$Ř³_cb–Ê5¬‹ÓÅFåuC˜ˆ†A&ö <…ì·ãŽâ ëJÏ̥죭§ùíS<”ï°õ-u˜N¤+0Míÿhn†ßéáá­ø8ï“3²@*ÇQ­Æž'…ÜÄò7Cg,.™s~0¨o´½ÝE™TËØKY[‘©†®a‚À&æ‘%ÉÕ,ëàŠi!šbm2C]ܲ8±õÀBÉmXêo^Ïc´vu&žÒÖÐ%õuêÚf¦ùaûýÀ-úê?SzxÐ ‹ySdYšpv×QÃñ´¬)α:ÏÅsŒAÒc eI–ôÆkz­r¹,}˜äiùæœÁ{ÇÖ›ñ§|h6+þ ¶ë*ŸÓÊ!ˆ³é0qÏÂﮕdH “©ü13Y‰MT Šöüßy;g9Œødjßh¢¢ö­òã­”Ô˜ºõÉV±Õ?¥Ìâà`üç j²‘j·§ø¾‰{„¸z[:ö 㜀1­·~Ãh–º"€Ê*S“:4Ëî¾B¶†‹B’*ŠzK˜™S¦ii%ÀóŠ›Ò­8z×’ "Rø¬hý¬4)¹ô)³§5âe£/©‚•1 •Ô#ë ¾’@‘g"Òý¥²r9pô›Jf:ñS–²a§’à'ÊZ³–1³È#–¶òÓ; À-òÎ0¹a7§ÁÂõx„ bÖ(Êó1zþœ‰h# Y=@7Ûä«Ó !-•ê·¬Ú;D=–ëu  𗇜L‹0¥™X±£$¥È„3ÏŠàÒ&òû4#j=ñÂ&ƒã7‹¯²Éº6€„9ñDZáÃÈþŠY´Ÿ˜‘0 e‡áżúZ¼ØÀcY»±YC`¨•“ “ÁQ>Ë//ÓГ[®“c‡¡ â3£H“ ðÇAF‘*ÀÇ P$’Ái‡Àûq­ ¹P=ôg¯Øöžá‡lG`éœZssØ {¯$9k(ûAiç§* \VŸ˜Ž0Ѓ)‰Ï¶hàœ¢ß@ã#¶0}‘ OÂ3)±ÙŒÂq¾³¢òŸISž¼/)»‘Àt8-‹n )á¼û£7#Ø–Zß(¹3žAÎÆS0œÎ Z«rW ©ÊÛ½B<2¿»UµÉ ­ÌB ™7«Ü©¬óß9²u¢òµ@ÙJȱ”:ÓëÈÓ$L‡›=ó8ØŒEloA™“”át! B óŠ ³<úޝŠI¤¬Œa!Ùq¾"WšyážÓ5©³ Æªp>b¼Ãà|G4 ¼b£|±?#5>T˜ ÁK c=Š?7v­:Í4 ß88¬¸ (àƒ6Ø}§4[ˆƒ§©ÃŒÅ$P7)™7¬X™Ø‹ˆÂ+Ä{“"Ž0±² ‰Gcß±Óo.ºUˆ‰ šdBɇÀ£s)»áô¡±<>ÛqÆkÂÌÓ.MÉ.)@b:8úÏ*˜ Ü€CwšÖ:½"ÏBÒ 9Ñ5»ö= õL¼Ä;¡cÄ©‰–±Ô=Zë":4 rACÇiM@‹Æ¤ì #JÖ࣠Zb**"¢³gŠÊ…-°˜Î²ãQ <šó*$œË”Ñ«+·:@$ [§2¶ Ò…6Ì‘bã‡ÒbÀcn¼ÈŸˆcë‹C ”SK õ–”h7èäÌ#j ô_¢T²N{>|,FÊê–•#ë÷ ±5¾ãGGrÏ8ã;NlãF“àQ"2°HŸ½ZšS»*;¦.ÐðOч¼R#Á]5 ¥“]5R°É$ÉÛá“ü83{=œe§»Šˆ‘é9H”Ãê̼Ð3 âû(}?½Xè RŽ›ì`¥œÌ/ü‚­òÁ”M=F û)Ak±7³š-©0A‡œ[µ€!È‹®eL#‹±¡LÁˆõ;Hȼý*ˆÁáÀ=  ³l²iíHœìã àÒ8z 2B\{™8ô áì-Q¢R%'¤jFAW’‘Ïrä4Å ô½\á*Ø ‘ùšˆ|Ñj›¼Cö–áÕ9rz€ ×±L„ÂBH”T:y ™+/úâ ãÇ¥\[M1ÂM\ D@´R)]ñ癃º€*u7úH¢:ˆÃ™Ï$ P š@äžÓíE˜}Ñý”lÉ4Ì)V?ü“§ÍY2C›Ð'üˆ‡óÚ˜¤Y ÍŒÏh¬³@ˆ ôÕ¾x¡m:­iFÂäÚ ²œ C2oÛåÌÂÎJñÁ5`ÓÁ',rJé½4âUJüU­«´2<À’ I‰)½”,ÕŸ/2Å¢œ€ Nð}¢é´Ý5­ÄÜY+†×¹‹0»|ãÀôÊ#æáþMì«Pù´³…Ïx+8Óí¨Ìâ¥ÅBÏ#Š(Œ(íÌÐíE ½+Íf"­ ¤9\4ò98þÉa #æ¯:óA¸2lÉm?³‰Å[ e¯„'[ÇÆb0¨‹5¤aE+ƲÐKtˆÃ’ÐËŽˆ£Ücî6µs×qgU3¸N½›Àá<@`ü[}‘QÝ€u^Ò3)2‰}Ÿé¹×áœ×S¨=À¾0êÊÜnWÄ£*-¡¾=c(òQ™ˆ$`ÒSNÄTÕLþªìî…â¯Ù¾–K¢ÂRŒc`0è ‘?ƒ©ì¬ÆŒ¯É‹‡Œ)ßÊÎìŒ²Cüb<ò'œ¼ÒWŽªu $Ö³ëp‡pÎÝ!HÅ8”jåk’Ø.à‹#@cXåê–é6hƼ0€> Oè „A€PGóö Ä@18 - ‡?@¸@øÈc`‹þ,†Er¸ì)ù/ŠKß‘@TÕï7™Há’8TRu™¨T9”ªWÒ@q™,v¢Kär8¤*S‘ÐhR·Ü0_ŒÕÀ3÷ô*¹™Bª/Èe¶ _Ìf:LÊ“ŒÒdo«ä2O ŽÉß8:¤N3N‚Á¤´—¶6‡F}Ò$0©,æ9‘Ô(QðNveš‚¯wÉ=ñõV·×â’Xfšá%ŒÅ2@9”—ÓIã5Íœ*§ÊDrÀ =Éù‹‘Fâe ÔY`Õ™|¶ ËÒcö‰~˜ߓ̬[úœSŸÐèGð¶8Ü—}ÀéÆï2ø"¹êòFäòy. ò¸6®bÀ¢ÍZJá%èËÐ6(šJõ¤i*(Û€/òªë [£¢*ð9ªÚV“®ðr#îÃÞ©£/˜€ÊLöÄíûX‚'ÈÛe¬‰+M €O3;‰šè¯süž Ì觪Äi©+ 2ßÊ ª‡Ç1þŽÅ¨r0‡G` ;ªjzí¡«M0!Ê*&èÊΔˆ„ ÒIûŸÊJÍ¢Êãl¡#+„Â~¦LQ‰¹îŽ©*ä<Ît ´ÁoˆzÓª:ÓE#3rø\‚še7ƒü“˜»÷|§‹6‚Ú^ŽQuëè>26ò\!Õ!%œ‘fìJÑóZ;æh²V­š^0ðÁ¼Ð °–š¬XEÄÀ¸fôòh&NØ”7Pí*íaEÀ…$³ôEÛ‹D„…ö¾wÇTA/V@¥šŒ\Û‰tŽ!H’·†ÊÈÑià¡ÅUX»_‰SqÄ(“º„CáÐHEµŒ­8Ò¹^ZŠåØÅ2>òÈë8'Jãܦ˜1#IÑÌ̲Ã/ È#‚Œ­·*BB#üHA„8¿³ ºð#q”ˆŸè¦Ü$Üa*n°¯Ã E Zi¢€YjìÉ s•Q,$ŠY ŠÌ‚9ˆ(ÔUìZ˜}ÄÚ˜ÇéJ$,4‡ º_ |È”G®ØCšjúT¥“ühHù€yÃòAFM¢*‹Q¤Ý寒ÈX{}"È~}CÖןù_j±éûË0|“Y>°9¡€tVzæa럱ÂDéPÆQ‚í@È™2 çÑ^Å5<%Xã¤:AFýv¸"†ŠØÛXR¡,šÖø‡J#›ôÆ PEñu%ó@Ž‘Ø~ü €…p± ¸»3I y†B§¦ŠxÕà»Û§øúË´ãPÔµ¤îøq‘¼šÔt¨œˆ¤ìUn.ä¢HíŒÔÆa†'ÌN`ʲHŰÆfƒÉÆæ ®‹<Ì[Ѳ²e1Q±šÝÒŽ.@ú‘øæŠÐñ\8‚UYÈÀHèú¢w\†`cL¥"_!#YÙB&PÙ ÿ¿#ï ÉÅŒC¶ "'îѰ[Ú>HS¦cUaCtÑ ±"جQ8Ó#£˜Jû`ñ¼‚f ´gZåwCê¾k ![Êž|;$‡\êåEf0¬ÈB¬Ü æê-%ˆ×ÀìÏ™¤-Œš~¸fû¯G^Î_lÕ«ãY„¥§ªÿ#{†(ÀB°ŽPïíQtœÑfÊH·½²´œ‡Ë|Ù˜øƒI r\‚Ö‹Å ïÖCM@fUâÏŸ 5°iâ@€²Ù0¢‹9©ÔѦ޶˜0§/³wûôœX© \"-7ì%¯e,œ‹[ú÷f¼VGzç‡^95Ö‡á#-oŒ•  úv5SWŠ r­%À+¨>°SttÊΚ}Q!Ùb9é̼ßÑZ’ï:®oÆ“£C8F(U?;Àè¶ü|`àei0cfF{ñ¡1†7i-<‘ŠúªsK:æQþiN׻ޑ®•5“ôÔ1M'‡×§Ê UÇð±ÇÇ. ×ûýµÞ Ú Í$³(§W»]—ÍcéF:«DÈú’Tœ<ÿFnèÎ8²2Gâ…Ä6H» <70X·Å.(G¾TÖºÝì&äœî ¤ÉG`-Ïr~l¢áeÄ4Î^ Kêl(’¯‰¸+Ž–L¯yj4·È²^ ,6E¦>¬òÝì^]lžH &'˜k챮܊…DEE4ÓȲ,GG¬ˆÿâ”™ŽžY"Ü©â’Ë ª»„€ÞE fϰœK Þïˆ0"jø¯'î;„ñÄ€Œk~ÃŽÆŽg^™Ȧ‚ ?ËŽé.Æ´ŠóHJ‘ÎÑÇfæˆwe,qø™ kš#fz Œ1­ÜÕŠ.`¨ò‚H²q øõÊá àÀ ZbTL†ë$¿lO O´…ÆŽŠ,å-òa¾+ƒ†–ÔE ¸qÉ*Ǩ㮌; &Õ ÈÄÉTe-K4³‰˜ZlôèЖš ¤ñITÅKÈd(ÅP<¶g®dŠŠlT¸ìžT±xM ¨kâÔ(PG§UÌ>•ÂL¼HªŒe¦¾¬À¥#Öµ­rO†Ê )RªKiÌXE æpØøßÅìõaìˆERÁê^SDôt‹VÓ+ê;æ!‰²°âVÁõ ~Eh(щ4Ĭz¾â24"QÏÎ)£|ꪬ°4Ì #ê¤8l1d†;ààhˆCÎ@ëò?1 Û,²`©¨ìˆÈYÊn×H‚ÊCTìc°úhoÅÊ?Â2ÀÌpnæüÈÂ^«®¨¥)´i‹ô¦dÇ¢È6l°¶,˜/ƒfâÁðŠçêñ0ì‰ÂÈõïŠphnl¹Ír"Žl4%\ÒoÏhpC†H¬¦]cüãÃLóȲø"’Aî$m¹ÄвlD¼JÜQÄ*F‡’Ú»„Mï¥_#Š©èHK%]Ǹ\G‚Vƒ@&£ü^ÄŠ7.°Ž¦ !Np÷Q.¦-ÿX?Âàá…Øyã626EÊ#ªH®–;íTg&âAö–) 8Ç^8Éjyku+®c&D!ƒýRkÄ3ÌN¹ÒœEë®äŽ „ð­|ÍàôÂ'2*Çëvæ¢6S¨×êr²_3p@`HTÄì?2ä½/딆è¹Ë³'­ò\°#LPŠ®ä(SRû­ØãHÌ1zåJJ`ÊÜfÌvœSp+ïZTný0b¾?Ì u~ªÇ±/'n\ò eÚxk~U“œ*eL£o$¤ì\} ¸Ÿ®–sÌ ¸ï‘(/Ã#sƒ7móÃ9i’•sy#kÞ$çP7¢ ùõ$‹×BÓd`„EsEi~JpW3Fâ&\Ýä>ÍpÞJÜšKÃÐÆ¢{pú†ñ>GtF£“ØéRwí# Çm>1”èÈæ‰sÉ#„³R:ðbø¥†]ÐvÌRÎá*æ¾´X6Mx‰ÊøTÄ\H°3BÇ“ìO<Ñ~yk9Gõ0$¡¯V¨' Fª€hç êÙðì±4¦Áôt ”L­Ì7æî³„Vî*Ó& Žó%`Û«®­Ðä`¯iJ’ú1-Su"0¼÷q,¯nÌJgO^AdøØ0úº© EÌ«]$ZãÆÙS´ÎÈD>ÓЮHpLÑ$±ú±©[Ð[”ÕÐz6Ná b&ØkŽIÑ)J+ÐˤVoÌTŽ+އÏY`j¤Ãò½ Hk5.§îÇA‘ËU9E,¥->3Îd\-sàpO?†îò;*ô•…x£¾ÂR•Bϲ;Bf`Ól»_+—ç¦WŒ$ÀÒ-Bn½ì?HéŠí⻈y..K0Øb¼•¥DÚÒ6UÂá[Ü¡ÑÊU‘QR2bÉí°£oP/”"ÌØSF®h; ~>°ŒµL+Ž\3§q`ðC¿Lµ#Idùmˆ®¯ˆ(õóæoðš‰Ó†ée]f1v6‹•.æ ÒÊ‚ŠÝnfß²6êêãTËPŸ ¤O@þËÅlñ>gÍ2O‚ÄØcfûm  ÊÍ:®ªW*KÊþåȤH6Ý儆fͱ-Qk!õ±úHhšÁøu¶fOFüníÖû2gLL…,Pì ÈON–æu¸ÏÆä¡C¾jªÝ å¨HªKTÆ+Óï_pÚ§—IcYà™ xaTízbIÃFíM¦s+D†DßlPïÃïýJ'bfÖ‹öÎÐlPž!óÃÑÅÄôÃH/ˆé¥ƒ-úÞWˆoǨíµnÕ· ³ôHq&j¥ Åt‰R·í¤kìÈË`€g‡r;éP±E®%n6$C%#+“ÇNÖã}€¹g¨ø.–pQ¬ hþ¾ÆÎyk–su‰9Ÿ'ÆÖÙ •Ixìðº2xo¬´¡ŽÄõ§«Šëì\«ÔdzI VJ¹w3?ÍS¤(G“K”Öö©kAeêÈñÎìEv7*b)mûa°¬"mÖK-rŒÅGQÇ’Îîtú7‰€ÖšÄçÔ3®G t%ø²´»a8Æ(â&± ;Õ!ñekžj–çzÜXBÖ8xp~ï+P°„-Ïû£Ã ªF¿")Ų¿&ùJ›‡¬0oøëwI®Ç3°jܺðÂXê7ðnJqH]wäqâF>º×gNàù°‰®@‘Œxß¹8ö¸Åy}‚¯zИc5ÕíZÛ+wò:ÞG0fÉkZš#KâKÈÀAuL®ý\PY3ÌkæDû-+­)ý9ç9xB„<É—Jç^U<Õ[÷¥‰+€›»mëÞÕí˜÷0iƒ±•·1»mõ¹ µ¼°—(ŒÅF}k® ñE¬T1YT¤éÍÀ·›à".<æÖx*Ÿ…YŽpg•l»ZÙ1kŽœê‰P&F¾ 3<ÌŸU2r°0\•@èÕ‚ïXÏV$†qGkÇûƒ*ÔÍSY¥ÓüŒ'îØ&yµ-%Ö…Æ¿Q\Äï²ve¨ÈNe[ûýŃRѱn¨i¦4˜ð¢JntÁż*œTUv»ÝËø“†,U“R=­Ô Î$âÖ• K+Þ#!»ß¸òã‡!qË6ó;O¸ðÙH¥u#‚?_5”1ªöRñb…aí¥¡]·—…xŠû‚©®MK]¤—ï¨-ÿ>6ó|¸Žu¥eµìŒd{g«6]'µšqúC¥˜™«§Ü¼fRë•(´]n ³]´†˜ìÕêà§“’@îN/‡“×ÃÉ+B§w>¯Êû¾d]€%E8ÝÔ)^WžCèºGŸ.ØZÉ{… RÆšZý1øØ)úækÞƒ=˜5 9NÄåèN°H‡f]9nÐÕæm1ÝŽÂwæ<׫'§åŠâ€8ˆxE=rixG°Øä  ^Þšó%ªÐ]æ¤è(‘b&#üJöÞ`Šc¢Ç‹ìçL%4UÝÞºì0¦º!¥Åæ[¢L9±Oéá%“Õ6b"dÙÄ X¦¼µïqјè\[›g¶½¤™àô9£ño$=Ò›RßÍbü½èÒ+3õ¹#T$ôŸ£Œ=j¸;ý8Ž*0H{”œ“ÎMàÇ$ Aßð˜Tý‡AÀOÈ)Ã"Ñhcê8>ä™âIß±ô®!(ˆD"OÉì5›D!S8„Ú+M¢ÒGÀ‰ ƒAçÐÈTÞ}Oe`j”ú[©¨R©\2Œ@æÔ`&¸™Í¨9DZbù·I¤@˜U¹óq{]íYt-8„Ã/`)4*Q …D"Óê̈ÃÂ!3éô£LUå-rMˆä«vXU;<±E­1x,úc}È?æu}-~3²Ê)ÒŠ¾>_1¯jår¦×TÃBbÑà&§•›™Ó©Wø,ZMã¿øp9Ì‚}ÄŸI©Ø>F×i6ÜäØ^MB“rºøH|M1…r©ÛläS~˜©É²L{ÀkŠt¤%zä£ÉŠÖ¾ ŠV¶"Iâ ”9®›>Ð!@D:Í ­ã¾Š&hbbÆ¿K =Gûº‚3h*g€ŠÓ% òáC •€Or)¸ÈLkÈŽÂ “:¨bå'É›Bgà+'Ë¢b² ÈâF$Ý*i\n»žÒ“æ"Ë£”ÒÁÍ3Ö›Kqšf™Ã^†¡ÎŒ“<Î,2 Ω¨äúÒ¿­¢¡ÒzV“&ÉBg+ Öë<` ¨SêLÚLâjè,­M &´» >Ñ.;6þËó PšÆHÒ~®[ -J²¤Ú5²j%Im%FŸÌ “X¯Õ ‡'Ѓ YlÊ%i¡Tš|lÛo‘ú«ÖŽ ;ÁˆœFB W‡í©ѻ5¼“ñP6‘" o¤ £-XI*Ã@2Ÿ]ÐúÊÖZÓÒ`‰4¸YøåZ*¢™®)E–•ºñ-„•Ïêc`8¯Ó7%à§ëÂþ@çó”ê"Š«Í¨õ±G"ŽRéS•r<&/z>fktàË/ÏŠPŸ]ÒÅ-A {6ÔÒiœo9¥y‹×„Ïé³,á€~Z¬Šƒã§âvš·ˆµÁ—;ZÔAŸÌ݇GÈ’Åžê3K¹ñþ‘¤KjêR¡2ѵlÛx”Y×l5–£Ú]f^MuæâÝn+7ÌÝÀ ‹JkDŽ£ÜÊlºmíO¨´Yr‚ÏTn%>²Ê…‡Fêsb©W,ù¿¶”DxÊx×J<Ùøõ‹kÎj—:ó›n“ ®Éùœæñ´Á(N¯ì+‹y¿Ù—z8›Xò:L«¼üŠ3´] Qˆ÷!t^ï9n§Ö2ÊÀÛ¤1ØgÏšûFì脜¢„fs~Iuç6txÈ•8lGõÚ’TY&ÇÙ¹’øPO; OP˜œBÅ Jf䜇A`ìHsâHæ%’ãÊâ]@cÜÔšUÿ ”ÃOÊy¿½uE sï#†íÄA4ôyˆá_cî&W®ešw©à›XÐ\`! MÌXî· zaÛ·l$¡4Õ0Ò £•KÉé¶’®K3[¥Ä†$ ŸJ¼E8‘Xø§ØUÑ1Dl1€d¶|[œc‘)(ŠBç®U×C×oE– ÈœWš5|±ÑjÃdቩýŠa=Õ8¾Š’x@Õ¼Qú¢Çébpˆñõ‘ç ßú‘NÃí¨0&“ô!ÉX“% J7J‡éÌ‘²8OŠºTKkDýD¡ÿ4"âq2èGñ÷-›'¥ÒV7±ÛtÈzƒÆk#c‡ãýíPYZÖTŸo1]øšR„(”„¡ÇõÑ¿€P§3’Š3Ô·QÔ†ªf!+vÅ¡ÏR«0W([¦6a‡Ô^HBtRÎYP¥0ª]ëíe t˜Àxøãè avâq%Æ&K Pæ£ÈBRqFñÓyÑ2[A´bsðä·L:˜d%&.)Œ^¨uÉþ”±£$ÎË3$Ö~ªÉ¦&òz™$Í Ñ’HBŒk|NrShgÀò§òùÊú.?NTZN.p¥†ä%*¡q„»HÝ3yÖ””X3@´Ø¬Ž˜}EÒc,\Ó;N ½Ð’²\å²ý¨iþR%['¤è¥1ñ‘¹3&2þµ·½™žd=ÆRÙÅÞ:A ê•ùBÏ2hãîÙGû*¹µƒÉvG“‚,CˆvÕšGî?Zc¸zö2É“v±ÕÕX¦6lêÇ­N­ïLÞÒ$ž ¡W¼çû\MRò%±ÞÓõAï.‰ÚŸõtr†Ì}fÙÜ!£Zi!¬6¸ä2•rØëÏ 2ÚÏZùÇ9#V÷<eÓ Í¥Ô¶º*jà.ˆÝëܧ®Ù!(xq™)zµ4’~® íÖȰÙÜ]¬{=xÕn"©RBîRï»è At2HHùl<Ê;œ²27dL~0"M»+%²¬˜F¼¤‚fŒšTÉðp m¦É¥'æ,ÇIž $Å+˜£€-Wrú•´yF{ótYxŸêè¥3Nó.Qú›huT‘δòj}#ë'ÙzšO­ üèzwrlö¦1ª§^[‘À #zñšù’'5lOëvuæëÈ™À¬¼!"Ú[DÆ^dZ5)ÃB¡íŠ<:÷kpèù4¼&8öNõ 5&´ÚD08ëcšUÀ¿°5kióCZx\øÁ:tÎçˆ/{ªH~ûÎÍ Áå£[£6w\8"ÎIS¸²Äá$»¡–™„Ó1ú½ñï6-^›J~íKd]*h:ÿB:Ã+ñËÉ©B&Ë‚Q3ɰ8è 3´+…ð©.AšÙÁ- >d‰°l@™±=ø6!¿Ž#££š‚9)P~™ñ܉’>q‹Á0|¨.h³ °Ì1{¶Š”´z‡-Y±'B à«pשJˆÆ« | ¡!·Ô2ƒ±Ü&Kñh˜ ’9©-qi©+_²Ø>HÀ¸H†<°5±¡•òS;£rœÑÞÀ(ª‡0<>Š.8Bp¡©n—û 1[dCНaˆ)#ê)ºÓŠ#Ó*ò J²CYæ hå@+ûºaç¥R¨ú É­¶+ ?SÁÈŒÂiܾQ**›^%HÒšû2!.©JJŒ’  ”%²Õ–98 !ϵөÌ[@3'Eãc˜t9Óv‚I€:"§¡±Aé?¡Y„,ò /còi$kŽ8XÀ™È·¹!’:…©`„´áT¥K¿›€š‚Ù)+¶[–:2¸ôiHƵAÍ"bT¸û ºÛ@ÙI¾ØÙŒ W»Z”!A­¯ˆ‘¹#œYbª¸—§ƒlˆJ¤¸œ3 âW¦IÄ™¨,&?8YP.ÈB °r˜;ù®-鈮xš«i­œâa;Éþ·X&“Þ¼h†918!r³‹ÒËFÀ|¯+Áœ¢­è…8ÈG‘ÅÀŽCd‰¦J;Áœ,3?·a(C( l”gã7€ â Í•@ŠÂz~½£;-kˆ£s2KT­üDáŹðõž[çPFê$Ka>·9†©»ù8XԌّˆd°-à‰ñŒ2例LG€¢@Ù.·auBpâ“ê\ S°‡ì8„¹µs¡±a?¸¬w$A€ÞŒ³þ‰x‰$޹ e››iͲ&5q8Û®.Ó­0A–Jâ5HöÎQÔÃ:QÍ„hŒÙ»Çt瀷 Ù;Wºœ“ÔÆ áÜ@S .¤”š„šBê®ÒÐ-dw‡üÒŒ¤ *ü²“Q(Š#=€3o¿DÛœi³:„3$Þ4¨~¥J&AÄ!pþ‘ú³´!‡Í³NPЫòþ”ÃÅÍûöºc§'ññÂ:%<Ð Ñ©Šœó0Rµ¸LÔ‡øÆÀ€‚Á(ŠrN@ûœªñÿ;¬(õ¾H“ p†­)$rx+…ìíÎ!¿‘ü®¦‹h·94Á´"™a-¥;äŠ[®?Ä‚8•Ðâ›¶¤fO„P”œë̂͡’ö•>Fén¡Ã‡FdN0£f™‰—ÔŒjš X¸¯ÛÏ£Á Ó½#°’T$Ū‚¦•Å“ô@)¹ ×ÂòÅQ¨}DuY ¡ÐUr¨Œ2 ´ýštAÄP²YÍ!“q<é¹Ã·!±D(Ðk-´)­ê`VÓè·c< E»`HTXL„Váð‘Éêhëò\[”Ù'‹t8N¼y3¤º:i=R"•Î8}¸q?ºêšÙ*=›è–Ƀ¸´âi6*‘À¸©#ºH³¶ÙØ|ÀûÌË|”W|#}tÅSþ*eÍ3 ò°L!È)(ÆÆ=xRäò‘>ýDñ‘Éu\Ÿ‹7»±ˆ‰ó„³^«Ä8;d®ãh8\òÈ èÓ•&±% 1LýZ¡”+ò¦²”­µrPµÉñ Í‚ýÑs„Ö ›—¼KÌ-Ù%»¾Gø‡@ÙÔ¼;ÒÛd]„Y~¦•?Ћ!°§KLqZi–Tj|?,š—ÔŽ:ö**Û‡óܬCXžY±Rö1;[RÛ)¨™ä¹1‘Þ²‚²Ê! ƒMëÇ‘¬ÈGJxXÿQ˜ª´û«‚t7 ›6èPH“:GAÛæŠëÛR5‘ä¥ÎÄõN×1\ çYC§»=HG-tÝ›”*XâãU’4TÈŸñŒjTÅ’^‡Û“ |šš¨F‹F®9ª‚Úuå™Ýj–í•9Jh¢KëÄHl\t0r›»}ÙJ­5~ ­­D°8剬ÑTüá©)#¹Ó¦ ½z`­…¥´ ,ŠŸ ГI:±=Ø}À˜l?´RóW2ð¢"-ÔÚ›  3Øb¦§…¥¼YˆÓÒî6¸¡KÅ™e‡'C0*Ä]¸ÚÜ4;‘±Äx»åØ%â-¾Œ!‡åÖ°¥X3›ÜIᢦ¬¢R€¸²2dÔ}-%¼RRçÆè†;u¿T L`©ë‘úWÇ:´Ä¡ñå-^ÒTÜxõ¾B[Í ;àÔå q»ô¹]±O´­ÈÙ”ÂíUˆ",96hLt&AüIѤ.ÓÙ ~u |D¬FT-›­­[Í•¡c¶œÉnÚM®^ÝÀÄÉ^ ÇE>[k^^(Ì€hh‹_™åQ\Ë }&´ÍÙhþ¢-,Ìì%¬Ýpžbý#Ê›¥8å+˜‹¹<ä Õ–~9r’¸´Â8Í(të·“öÙ9@ítØœ>ë$iËa銬ºâ"èh4æ?±Ç“ôj­†ÕņìNY.X¨ ‹‹»‡¦kᎄ%f6j‰{9e tæ œÕ„“öwåœtǼUÕ<­ ¿i}%T„Ž/ºíRÈ¡!§*ój5s¨¦ÀTP’1}È]S‡¦º&µ£VÜ}DdÎB»¢Í«°®5ºhDÑ¿Ìm6ݲ‚åA– Ã…™›žƒXVÜ!áÜÕÚ¤†äà„ ¡@”"ë•b±t ¥Åí¿æPŠU0Š.é7ª ê[(_vr¡FóìbÞ½âëï:~² Cwd»¸'ìdgFóÁ"+ŠKRʼn.ôÛHÆeh·FäûÉïšÈðSÁKÛÕÓ¨ÈføEÅ.ü/ ”ܺãb¶’Eýe›ú¨*Ï££D•¹ÿ}Ùª²²\Šrk t™ ¨aåC\ R.Dš÷l%üX}ôÿgüˆÁ`pWø†BðEûŠBwÜfþŽ?#ÑÇô<$ÀyDe÷ŠH¤IŠL„GŸˆ`œÊ¦ÉÌ’I6—ÄdP9ÌÚU9‘H€Ôù#Þ¤ ª>ªÑpDQñ[™Îg±™"IL‡È!9œ’);„J¢–8e² ƒ@¬0Zô2)V}JñJ FŠœÃ¡ø`ƒ ’X¢6{µ–9ŽI)°ùœ‚U6¿^@/î× º?ñPË€)§Bµ˜àR„m_ø õê'—mŸõ-&=]†o'Ô-ŒNmÄß´æ/kÒ›l6q̳w¾uèYë»ÿSKâáöÙÉDŠù3™Î!°Y¶øÍ²ÐùÍšñ Ôžê ‘>Ìz ‘>íël’/€\ÿ$ Âøç4: Ñ"fÜ0¢2®C<¶£(T™¶H~$ŽbøÖ/ÐR¬Ñ§ˆcü¿>l J“=À –²ðêê§1ÒšÊ$ô…¤Q¢ž52:7ÎÑú´$Épܵ lç¯ÏŠ,ãŽHèd™"7Ìc™$ÐÑü¬K€žæ?Ë“¦¼ÍŠÄ„Ø%Òjn‚É.@¤ÊBê®nÚšÚóÙüÀHòŽFJܾõ*ÑZ"›PÏŒü5‹ŽI,Ý ˆS´KÄ7Ó½!3ÌÌć§iÌæ×(*=.² xÛ¢i‹.̨².¯‘ÕÖ5ãʦױ»ó[€05SCŸ¯ ³]Ò¯4ÎÄ[ ËUD7•ÐGŸ’„H˶ŠCn[Ó˜¯\Ì~‰ºI% iÓ×ÕãzŸ©´]!&wT<}Å ³˜"žÖOèŠø¾\ ½aO–D¶É¶ÎùjVí8bÒŒ«VoåtyåTÃÝ©výWÙz9XÏkm*¨hòr™½i4’„>lB$ê›$YŒøå¤ÉÛý$­53M§p=†ý€2J)§å‘U@·ƒ¥lÇÏ~BŠ%Nõ &i¶NêÈUàKOML>iš†ÚL†ÎÜÊ”Bgµ Y“˜ßXAÿ5ñì(îëú&¯¬±©«z#¡é²sËE¨š$Õ™Ô E²Gô“žiÛ½¤xM^ÓubðÜÜÁù ¬G ŒÝ’û¤ß'2J¾}ÈUÕ‘ô(RÝ{m ¡Å¹ˆlù+}ÏW›QœȦ}æG¥VHVJ}Kü_× Æ "sÙz'ê±ìT @Œ÷Î}ó›Jæ]ã.@¦×#D J8‡¤jGÖ’øpäqð¨øH_k ýÍ0¥ñBåsìñp=ôÐPˆAÏ‚…Q#žçúÍQJ(ÇÏ:¹ †ÙȨÅzÎÇã|d)63bTÌh+YPµèrCßÈû@LÌf» €©Si±u·D>áˆ]† Á­tvCKÚ Œ„0Ã@ÏŠ²ù`­ñ/,Ò(Û‘±n,†;$’ƒ–Z€)Yi50 ì"6«}ŠCvfõ¢‘QHÐÄ(¨X£c¾9‡fÈc¢ˆD[O•FE#,Ëù)GÃ'[£«ìÊTH¤\›Í,¬¨ÝÐHR|ÜŠ p®G&•¸×’ü˜‰Æ5r"ÓÐSå ç6‚øàñ&g>HB2Õ1_°ü&mì“ uÓöœÀ*t&S¥ex#îmÙ”ËLù lÏdBÁ»>Ëá$T,ᙓ³æ’N{°‘FÂA£’Saèä€ù•‰±3ãûÜqŽ»×Ñ"™’BfOýxº…=ë”Æ¤ð.äzæ:¬9бVŠAGÖ’4ž$ˆ¿‡æ_‡­=&eaP®§Âg‰!ÏpÀ ¿¢2VÁTE=ŽEâòo(É|©„>K5–à½kÒB4i | Æ–—ÀÏÀ%"¦ rL5²žŠÁþ{Ð$‰ÎÇTã+÷6°}22üˆ£›¿sS9XslÝLr+½º¤ÈjÍ– ’¦âg”Ûf]‰nGç4¿‘¥h_o˜‘‘¼¶ÓO9ÙÚ8\Dh! cÉ–0 HÇbˆn'>Ô%ù”É @1F wÂî–áÌ– ¯P‚LŒÖmˆFòð[Qó:R@%I&¶HŠÄ“#¯d‘ä+ˆ{z’‚I§£Öô€A­ˆÿšmjZÖ6Ú,Aó»–Ý‹ÌTO8]L†ŠsyAǦC#N‹)FÇ…ùã© !H¤Ž çU³ž:rÎj%É3‹¾)•öYb8wŸšn#” J^Vo‰qz¶LÆšóê~äLUu.¾VÙ/ÓÕÍ$Õf§,ˆdG+‹¤g`¼Âɺ_"|mWx1È¥ô«廚>f¦‹`t*Y…±°}a¬bW‰‚5’…}´¼.U’LæÀ7<[»?jšIwÆ•rSLnÙh£ZŒ-›4Jš Våñó…‘ÜèyžxdŽP±2/¢GS‹!Êx£ylÁ)Ͻ?úôl5”Ç ´¦¶Å¸£ÒƦ®Å¤ip3ñ y‹ïßúð?b5v­¢‘jíU¦§¦&®kY¯+B¥h‡ûW|ÌLÏ!¥•Òè–›ä`ÜÀ)¬¶ðlYOIšI>eúò`¸1«çÅ¥ xb@é–á*®¥JœŸ9Uˆ¾áµ ~ªy˜M¯V7È;D·0ŸÔYã”øÃs»H–Q‘:“/‘‚}LJ_Ù-_œ€)þÀdÓCR¤Îã“åWL(še£žb/ÉZ+q3óge5’Ÿ25‡I™½S½ÞNœ7Ò’¨ÂUQùüŒÅno¾4êÌóó]X{ãRjN1`o3uÀ*Äã‚`ó›Q‰šÜ»«Ñ¼fc:ÃVú^·(PTúƒ>] ˜Dðñ$^ áT$t'%_ßDrÁáUBÙ§‰¬w†j¥‘v„V÷Èú]Sƒáî ­ÛRƉ yÞfÄÈt£Z´ Äè¶…Ùr:Âñ“k©¼%›Ð:d™æN*óSb%S‰"tóïrªÏZÚÐëM‡Ó_ƒžQ}—åfµñÈÁ†z‹YâèÇî:#>\ò‡S¹»fÆì‘|PG>ŸÅÂ_Ôäq†]ÈfGŸ"d *ÃRÿ„Ô~ ªƒ$˜­î—-.]P…øKë fD’'jZñ¥VŒeZ[§U‡ÚÖb^Eö_/ŽcÊîàêJ€M2¾£µÎpÛ¦<àÉmÂfP€ dÇ­ÎSk`/´µ NÇ"hhF·/ɘ÷!ö'/"†Ž*Æá ­JÚ9JüZËé°0U’úà ÍË^ÒɨšFLû©® ¸‘G’îï&eÌÚè u°ð™ª…Ž{¡øP ¥‡ÎܱNã — ÛÅÁŒ¸6<¨ë’j¦ñ¥ØÕ„*ˆ<ž#¤§Pµ8ucK&´ÛLЙ‹®+†ž4‘NË&Е( £æ‘¶ßÂ.½ï¤Q %/7É®4C`Mí\(æ¶JÝâP°‰íq §’¡‚<•q€¨ˆîgêêø‘N^¨%öá1,¢èj£M"Ødhõ«ÎÒÉ(o%Ô_Éü÷Lzî¢ÎðWjcnN_f²ÂÀ @ð"sN9 8åöæüÎÎ^9ñ¶ #Ðzê%øúP¶‚žÀçžEñÚ…”Fð®¸Â¨$ŒìÊLû'Mº"Žªý†¿$$øåŒXCéLMðîÂ2~rmÔµ h¶b¤wÍBG±”u2ñª !D„Á噃žhÈýk JL­‹`Ò±EvÂ^‘¡ú]ƒxÃÌôƒ§ªØÒ öÅ2Š‘T<(бi]·Ñ‚SHÝí`Kïæp#Œ¾ç ©Aöè –Ä„Œ1ü¦S¯àO‚vfÉðhº„blÑ¢¶ìRÎÆQ†/%òÏ+I5kEØÓƒž—Ѿ%w1ïC‚¬»‹îÙgÿì©Àæè„gpWr6¿*Ù ìÂr±§0ÓÎí&ò¡Âø¬¹i„àòUêö5ŠŠÄŠ×2G 3,flÑ3pLûb59°:ÆPõî)NXÅ0 Y¯Ç(ìäŠôP_ŒÂX5)'މ ±D$‹±:‘ù8gÈgJÙáÿ4 žÍN”qbÛK.+Ì<Þ3x+Ϲ$†ÛiT#,Æ”ÏÈxÂ'"oj|&âäJÏDÿâ.î1|kK n©²d1ö¯jˆTðFî8€q„s±>Jú*F&n­”øJHâÓ_t8Þ¥þä‡}ÎTï1%°='ÐI/l|Úòk òXªc.õæëfzôòÐâf\úgêÙ’3Ôº\è«Ä„%Qê½´N kÞ$‰|T2,yB&è2N&WC`»âžL§Ò67R‚9@D«V"¬bpÀڌ𣟲¯2”!ÛÂE;iOµ|M¸:­QÉJíªšfQæg Ë4:Ýb¼›¨YUê9QüÝHÔ3æJ§"è rÞ2Ÿdø\8²‡•@Ò­B†mE%ažJ9#Ãk†´ó¤é-Q[<  ì±v7)}ÜÝmvƒØqgçÕ·‡¬BÂr8xÕ/hq’P2ðÅ£BÂR6cðÝ6~áv*PN TAotGó¤:ØÉ 6(— «ÍÎH)%I=† qk鎄òâÍÕ”ŽçfȨùÍLÒÌ!Fž˜Mò6+‡k YicõxõD-_VÝM9=èHâÑüÀåÈÉX XçOâ›+êÁTdn·£K÷)lÌž#:—Fì4šÓ·¸çÃè!V÷gYnýh©ªsDK)ô>Íu|®8Tåðä`ÌŽU"ZÅ&öúqi0éãoF_Çç+ìlÚ‘=tI˜‡—{ ÓÈ:JÎcÏ)쿊ă¸Ä7ˆfЀY xš0Òã`&µQÕõDzžrTµ”ý@N’õw¯ŒohBLî+â$N\Täoœ-‰.âèðg’ã3Æ‹F Q“d+P  „÷4(Ì »KË‚ÎÓn9B§Ü•"l»—M_µ¤äÔ‚ÒÐ’ÏVÛ@Äaó–iÉn¬#™ß5­UøJ¤n¤å—øÿŠ-{í°]QÞ9G€”óp×›­-Æ~ãyŒ äcu.ã¶ðlÚ¶K±b‚U:/È:[¯Œ,eHÕ¨Æ W¹#ez|8Ó=E5!m*Û¤o¥æÐ¶‹.tw&Ùñu,̤:¹Ñ;É;{šÅ¸_ÒÛ`scKÖŠd /óì»iÑ(19ï<2ñæ\7 ³?¶¹,|4.ìí™J™:LÌKäé·D™|»"»Jx}»¬<<í´“GDŸ¡çÜ_ÉßÓ.feÂü®×j9ë¹ä‚¶™Œ=®¹¾wÓ¸Úõx5ÅòÿJ™BÛµŽÁ;ý9p¸Cã'î“yD·²Dnª- Zªfg"Ë|"d"% òì½Cºže£¤‡wJ÷on¯py:8é÷ëiǨ¤û‹Œâ ¬~J!M8?Ö磷üƒµÇ)ZŒ³›Ÿ°¼\v ÷î, äý­ÂBý €(0û…aØ@{DÀ±Xlÿ?£øÓþˆÃàOØøQ }ÅàÑÇô6? ˜GãqÈübe9šF§ <ýïA—Cdp‰@0ø¥KÙsê¡G—K§àzƒê#,RŸÃ^Á~Xèô{ò?%ŒQáðب³Ú Ó7ü:Z’ÙåÔzÕKZ•H –+=Ž#%‡ÓA‹=r‰‚>r—Èåjm†F(pÈôk4˜Î´bK.Äp*½f.Œlàð‰Ûþ]¡»C÷0‹ì¢ß ³É V¹D† –rU©¿&ǼŽN61Ú4¢{%ÛË­úˆ›O´ ½ð0Í€À õW#ôÊnQó´ŒÍ_ÑŽ”¾s•K«Ðo+ÐÛ>Ž þ ‹:³,i;Žë€hzU% šlÒ€ ª]¡‹zÞ³¥MÓ=·ãÿ€`4N¼ »”·¥ÎÔ*Ñ€+c} h"â*èÄ8±©*SÎð#ïœÛ§o1µHÔN*Hâ¯Èí¨%$ 3n·"«Jž¸‡ìž:§ôc&3çúèBs™LÍèžË ,Ôû!Â&{@ $䣳ˆã†ðD.bJ·¢)SöËÃH²rø9’¬˜ÛÐnüì–‡ú#: ÔÄj~ÉÓ\¬,ô„Ù> Ï„ü©¡ëzŽñUr¯4GûÆÆ!êªT× ŒŒö†>O\€ŽR"³£ «ß” ò†Fs‚Ô£ëæšKÑ,ßÔ}W :oô¹h J¬tƒ5§ì»JPz“2ÁÒ¯ÄÌ»ˆªÏY!¯ƒÔ¤¬T­9NdR†ßï šÍ¶”s>ëÕ'*ZH-¿JXDd”#ôjˆÅ´ã³¬bU&MX*&.hžI‹{Ç4MÖóg–Méì«ÄT³­—¾ c•Ÿ"2M0éSn%§H§ûŒä)4Ù¼bƒ&]ªæ8€:MÉš#SBK£M’Ý:”Sgòüœ¾÷ÄÌ®K‚†eGëÏh¹m2þ”i1Œ †Iм>Ø;LETÊéÝœïKòž}*£ì§3F2͈YÏþÔ ¶YY!ðJѪpÙ'å ]!V¡ »dºì:¢0«Ã JŽ+‹-»OæùœëˆŸÝòß‹_L¦Ié:*•SÞEìéôü †*¨Ž„÷² Þ£ð™úîœÅÙ\ØÆE7ˆ¡¬r¯A/2P4Rp53)¦­ \mư”8uÒéÑ+Ú-ê <ÂÕ*êYg5ôi”1 w QÑ¡SäßVs¦; „~§¥ÔI2%ET®+rõ£Ú!©U Âu†ýÝzZ'iU]¶³v³ ’ã*”ƒhÁ“Ú†2!–rÞÝ¡¸QÉü²1”ØÙJomÏÒ.Ò>ûÖ ©ªDE¨ú‡ë¾VN‚‘£ºAšù|!›,Öè𢢠(äD«ÄÒ4Y×á!ƒnAC,Õ `}¬éu³þ“ôSh¥‹0µŠmÔye ’SxÖ;¹&G`•RW39&J¢+©cBÅ“2Ca,]5#Œm ‹šYg€6½ÖKõv®„ªŸŽÙL’4ÒÌ$ï£7%œª˜aø†$„|jq¸¥#²*¬ùŽ€J›9kA±€‚;r9ϼC?K²P3ç"QÒa{’ ÿ#G³ÛEd3aiÉ•Ïebé‘sЃ=VèÝ[Î-¢h7µ©˜´‚D4ðä!yô}ò$´C¬ ^“Ç£í(…¨  I[ƒçMîÐ<6ªÄ tŽ2"‰JÙñG1‡°:x(}ÜB‘](•dÃÇ=‘9¡oŒ†M8ÃB¬Š:<“±·Ñ ¶gEa“Eü-X¶tã‰Dhù0¹°r©£ÐI±ÜðHÎÊN‰$)þÂ’FdiT.•Yðê, “Äþ4’:Œ’fo¨”»D*†þ–¤­¯­ôS KT㡜d– ¥UEçåP.º6¦šJ‰)dú&—¸Š~Ý3zy •Çõee½²2*ÌÂ4&¹—ãÚ%Q¨óQ7@›Ü©cÇÖP+Q_§CX+:©Ç™Ó§“¥3,é‘LËŸB³€¬FîE_4³n¶»°y8øGÉ*1–óÓ'ðâH¯ÍàÛ†º vjË]™‘ûu9Ô8û#Šæ±öÂè U«%Ͻ¤°¸A_çû)®VèSÊ„‡#ö× Ži £È°O ²Å§-ÉÜ=t,ú}2ȵ?©{Vk&™ò×¢ž^Gìi•Ì.E]:h‚uˆ2È÷/¬4i>‰1÷ÞÁøDSÁžä …+{Xßíõz;½ª¯ ¡.+‹ŸÒêÄ?*\ªœ/šÌ*åIS’MN‘Sà[àt!@ˆMÅ¢“þ»]öU­ê°ÉÍ1g~Ë ›;Ê›Í ·µÚ%yÏöË ‰=Ô˜u*ß´*ŠjBv•u”4ù ³Á2¿‰œ/®éõ½`J¯‘á·ÖÁzè™*az²ß®ë†Øp+^˜„й¿$~v Ä~¼áh]¶5m”ùN:BPÕŒYM|Ú†1éëvš…D;;?±HfcÑPxø•/ÉJR”ñŒÞ­j•³Áa`û™íD•SÆñ—œ‡?å^!ÂX¤?f÷X…þÎ2{„Ê™Už RUãLJy> ²´>}Åp쇚ŒûÎlz}Ó}¨—›FHœ›\Ô¥øÎ6ed¼x(´PA¶ÅøÂŽW 6õØ~ͯcþ(#W&ÊÁWBQÓÂLÁ·¾®d›'Ì{UUáñ.¶Õ:Õ¼Žé]9&/o±áô¬a=c‹P»ìiD5aÈØ¸ÉQ˜åU ©Ot~7|Þž*í,‚$ÅÍãe“×:ù–)X•d3*î}&g¾e*»P“t«•Pc2ÜX%1­œvôU³]Eê*ß)*j•𹎞>ûfËÕ71ôÒ•À4ÝãîÇ[\…nއÃÉW:FL œnœß²Ú„аn¤‰SAW_–ß>À½øj1©y*‰ò6q2a>ʹZ‹úº<ÄÖ¡g"è… ªß3j–¬Òò¥¡p ‘ß::ˆ9Ë“‰£©"qœó1)+3˜‚R.{"°ì:Úȱ¯*žšK=ž[7,rkP„&Ÿ¦£Á([ß*Ûò›‘;9\1ay/*¥±P~°ÑŠ7rÀ$ÂK›‰û“a·*›µ:à•)Ú?PñœX·¾;=‘‰Žˆ«†™ÒK§krÀ²éf'ñ/1ê r­4±ƒÁÍžã±Áµ–˜†¾;,=T6É©bí‡À’·Ê]±Ä™›ñ¿q4Ú!–›ÏÂÔ>7‰3ê¬Ü-®aκͽ ÉŒ Æ¤OŠª—©š;«¢š+ñªл zÄ€8’– U4@Û—3/œ.,8‘B…&ÀæiWcù6aº½Ê³¬ŒÕñ³¬Ó_CÚl§3s!ôØ yT@}—àñ°jÇò]³ L½:X´ÁêEàŠ“ÑSÂ@0Æ@™M& ͉¢òÆ“ÌDûÙCÒÖ'ꥒŠ ’¶’ =ÁƳZÊ}9Y‡£8±¦Z€$0®&ÄG!ó¹0D1ª‰ÚC T(/€žŠ»ª)ÊP(ÃÓ/s"áz5‹\œ‰ÈPœ¾Ã Ç8²ÓxJ œYŸ1ä1š©*Ô9kQˆ3HëBˆ«[Š8øB+c#RÔ¨ »R‘€\+#›—‘4ì\6é1  Ÿ›[¥ˆû€šC‘,†ÀÑz<õ± ìBÀ¨B:ËÈ#Yëã‚Ç–X’ƒv'ð­A:ÝÀA6GùÐË(¨{Ê-²áÄšX Ëí¶+Ʀ«¾´¤¥r˲¾<*JS@Q¤ªXó¶L¬³ð†-‰ÕÊÈ‚5¬9jà¨Yl¹Rp¾‰T8¹ØŸ;d4ÙvÊ'AZâž“.[…B”Ï¥\»øúô€›ñƒ´‚(ÇaΞë”áþ¶œg¢t0á ïÕ¿É™ù¤¶0€zŸê#¡ÊΛúX•“PâuŠ‚i‘ sJaq ¬!ò­>à ÉËŠ±£ÿP …cã§Ô¿JšAa~Et¹ánO<Ä< 71ԇ䵻²µ‘ÁJ¨Ç ׳DeÀTQ:Êžß0éíLƒÃ¸Q–)é/H<‰ŠSC,´5Å Fˆ-óœ®!1yÑ!P1éµÒô¬³‰®¨Ê0P©“”|J )‘ˆÛ¦Ä#Ì¬ÓøF{RD4¢%‘K"rÍCjÇNÉ6%Dá CËéKÚ›Ylºè˜\í(„3DŸÑ¶ŒB‰•”uGáT+X±É¸•“ð4šÝËór0òqƲË>Ì”ô&ø$ø•K\5ŠƒEƒ®˜²Æ@ʉYC2òÎbe,Ú°SÐl­šÝ•BžA×R ÔyøQ¢}€d•q÷± ßTä#NÉ쯗¤z»ô§/‚ï ‘L¹¥¶pù0ÛM³'LáñÌ ›Ðæ‘Ê8¬µê;µ%,ººh7«A8ÌÚ¤ƒL 1^Œ¤p·œº¾¶Ô”‡ÝqP’úQ«ØÄKbK:s>tÏ Ì·¨XdO‡¥v`®5äØ(œ‘Šm‡ÑŸWbšYä0Š›ìô—’<ÝOóO«õäa’±ªT“*J ¡ƒSV äìV‘ÂÁÛ¨dËrÀF¼¢Ðsö:C>Am£4t!ä Â~3Ýmüž%Ïi8Ï HpŸÂ5\ÊE¢ ÉSÆÝC ˜3ü®z .û:ÒtæXÎâÃN¥¸Y™••pNk¥ª˜Y<-ZžÛnÜ!* UJÛ™l´ÍŒ7Ë G„a£5„¶ÙÈÁ1Ì 1l½†Wq1£¬s±‚³c7ž©e¦ÔgrßÙ)Õ5X ¤ —òØ’a9(Lê¦ í“E´N4ïÇD$¼¹9>9ì QÕÈøÓ4 Ñ]£(…JŽc&‹…$¨‹]Qs-RÓ@ãM,3¹¬iž# S#€\L[Wë:ªÃUÒ±s§ Õ6Ë«5}7F, ÃllÌI˜]¦¡I7 5/Ë­ „G ãZ3N„¡ ¥s(ªùšJw.yLïÕä`¬Ô©¡»'4УÜE I }­\ŒÄËbÎBT’šg)*¢M+h¥‰ª<ˆ….ÿ‡òAݱ-ò1Íx}/@­Y=VÍQD4 èÙøPvé–A Ô‡ÔíÔˆAa•Þ`[cQ] HlÉÒ#›U”ȼIR¼Â pÕV.RF‘<‰$ZE¿)ô”±þ¶v°Ù»ºÚP™ûç`-|šk”º7Òú6ÛmÙó.¿ózÅœ‚¤Y~XrÏ—N·ÍÑܽީˆßu’i½ƒ­•ïÓÍìcªÚg[ωì©)µÒ¬•Š8zðU9n½¸Ç¼á³¹Šo*EÍ@¨?$„ -ñJ’ñÅäÀ}KÉ`›$f_aŒU»ÚŽßñ54 Ë„«…Ð'™à¦Øƒ@‚`^Õož¸¡óÄ¢­3åÞMqSŽäë4=Í×bÑOÑÐáݵ«óµ$˜>WcC…Ìpœ]PÞ˜~¦Æ,ÙÐ )وЪº•O¢xÈ+`Ð{'%[í®,/ ¯†UÙ±"ªœðÄgÕ‘ýÈNãH-"n¨»1 ²0;c9Y à÷3I¦èþ¼'3=¡\±/íÎ0ùE”VádͽítÖTµ=B—M‚ñTü/=â®FÊÿš¥ýCôäXu¼¡?Z$záLy2Ú€½Ñ6›úÇ& ó­Œè,–pÇãí®v ¡s:Stuûà”3êæ\#4;žCåDö ø1ù©x»bíüÑÂ3ZÜKÏIÅnà¶\³/2°EyUžëÒßjów"*¥ªªž³¼XsÞ0 *ßI—ŠZßMO®& ¥“À‡ø?ÄÅ"¯‰Š5RÖÀW.£¸ÿ«ôÌ Ð‹zºk<Ì0í±SF«ÏU÷ÎiÐO÷Í4•ô?Gßê”4ƒ£‹z¿WZ§£€Ê*~ÜÚñÛq¸ãGÏóËm6‰)õ¢=þÍ›g‡ÜµÇ•@T4”µÖ˜¹}VÜü´Æ:Ä ãIÅ)2²«Eˆúg|€N-—öbÔz¢¿~ß=°€\¿;Ö\æ,,²`ìÊlg¶G¨E¬"y9t]øq^£¾«1Èä/}Zw¶f­ß.ˆ©J}w‡½ (j|òCé“+3F¹ÝyÓMQб™ŒHý;è!ê]AR~ çC=ÜldïNgaû­Ö¥BiãV¥Žâu zG•õ'§7Óôì<ŒŠ}FŽ)ãh{‘也ãs¿GŸ€¦Ó}€ìÜ¥ùâ®8Iì Q`÷Tí\ßÒo™íÍtð0Ž?áòM †É€Ð÷ì´ /–¿boèü†? F$3Sæ}—!±ð=íG‹Lh39œ< OzÔAU:x™˜Â$3:L¶Tú°Ph/» "Ìô´Gáð‰Lš¹šÇ&r\ ?«Í#Ø\"cœBåWÈ…Ú11˜Ó©÷8äZÈûªÆŸÐùÈ ) ’Grñ¼6gU àp s9—†A²±hüÅﯪÑ@óçÌ4·Ì¿è;K¾!ÇÅ´¯ú®Óe¿Ó@¡»,%n'•ÒâqgŸWn Þ"tÌ wˆ~Ãj³9WŠŸ†ÌfÑŠ­ÓQ}„ü{Ù™œÇ=Íe>Wx×Hø?ï{†Ü¸nŠ^î€/à°ISœ¦"È´Ì3,«†áÁˆ³Úü´êÓòÿ&0Sª¡°”8øÂè[É=i‚E­D 5'ãXŒAˆûZ–¦kTTçÀO’fŠ ‰bZªÁ‘" %‘ê0„1íB‚íÎAþ©I‹dêžlЬ¾, æ"r³å?/s(ªÌìºbÆ$P¡þ‹>©lèŠ?¬L|O”[ ‹Ë+ €l^¤/'$©ê ^{Ãi$ØIÀO=éŒà Š¬N4,€ýO Õ&,zƒ0ïDÿU€ê~¡ó(’¤Èüø|:òŒ¿#±jÂZÔVª|ÿ"Ö<ôMSVTúe<,ûÏPÕ LЂ>ÍTåBHˆº0±¬•’°=2ƒI€3T©!²šNsôO±73XÚJýÙ/ë‚0ÇÁÈåw„ŸñÙúÙ_ ¤7.â9z¥í£²xìrŒ×õ£ ËF«xKÇø£“Æ(]<ŒQèú,Ó£øýe2Éj|ÛQ)•ÚX±ÿU7ÙÈ Æ ’&¸á¶‚<‰5¶¼Ü‘Dä„^À bèãhë3„[gJ0¼ÁL•·º Ò8Ç¡fd‚J $WSæ…!?"Ÿ_gŠ Õ4¬¾fàÔµ(¼ªôÃOJî2{æí Þ–Œpùb9%T9Gܱöx•MûíA|nYáe3S*ÓÊÏ0 òÜU6VÇÌ‹ÖIÛT3T!òiŠÌlˆª×5èzT„~o:…¶‰R?àkH?•í”Ä~0}5î²b:ãCë1 1¯£–„™½)l;ë×·O¾}´ý+'—)ûÌ^ˆ3P yþ7*UŸ–îÊÔÁþ€«qÿ²^¼ šÊ]E%R ®2 `ª Ì–Â è I zmõÿ·EJb€)1ðmn°†¤A#~îð «·ôÉ‚î%åø–¢ÖLÆ#Ñ$ð}Õ"Õ¶¬^Ûp>+ákSZ)ê<ÔD×8[›ê±E*ô# –«8މ8>2BÒÃDŠí¾C5bÔšú7LdŸAXPCÍ£LD¹ÉÐÍ<®e(§!‡óX%ñ4£hša›i_Ê…È»·ÓQs”"i1J¯†„xÏwq}o¸•(’¢}ñ†.ÂØþê¡„*Üü—™HjjxfÈÚ׆”£ ùw®ÕÚ?!ô޽ù¶ci™\mb ”Ǩ¢AH3ÝËàÜœ²‹ ù7qÕ`ÁaùñûmÆæMé@œ£ªqÍXÑË9^Š s)Y[Â^ÚÐü³’gÉÙ'xfõ#l ]íµÇ©‚°¸B¢È¼““X„ ‰Åè`ø³I$‹F2’ò¹J EsUËNâ[h¼\’§ ˆ›(Ôƒ“Ç< °<5¤õL´’”r½w2•'{—FÊF¿GSQÆ=ö&2‹; ë#MKe¡;™@ÙŠˆõ{T|}ªµ[(]d D5(—òä—Œˆ³EÉÊ¥KUGå3[]½B†{+xkgÅnËâÌïÕfK9š°3F|« Ú””f "fàƒÏ±ï‘Æ>A!€Ÿw°a"£R$͉’‰²I™m›®023º¸ÀŒÓ’ÛHÓ9èK'iAfÄ"<θ*Ø:‡R°áëÚ$ŠÊOô@o#á—€#'š(ü§ƒê#×%P[¬¯òemÓbÈj"vQLZ6ùl옞,²:JBå:Û)D½ý[·ìaT_Jޱ€:Ú¾Ðz¥5’H â¨*‹}ŒÔÙ«/LdÁÃF÷X²/ + ïŒO#F«K··¦lIvͯŒU©F££[%<2Âd]¥‹QKI lxÖg#@i =C”L:ï¼ß3»VtRãÙâMXiÕ¼¶RW$WNöáª}ªôÉRãq­™Úd¼yE±(v˜n¢×á0Ï‹ /_¡9Î)ßodê…Ž€¼E`¢$–<x]SNÖw“¤øÕ‚H¬']ïeóÔТ׃Ãò5ev¶î`&ä´Ò{(ë¡-"Ä«N›•Ê잦?ÚÝëKÎeè£;Ds—J ¼ò2i8¶ø«>Uu2|vPÚ¸<·çG€¶µÖÖ ›G†è³K‚ù‘ÙID´–’‘†òmc o%MPG¥p_y#³¬Y-i 8Qa÷¿’ÁUWeLI•©Îz6-GD‹tÜó¶{öu½G¶ãÖ¥¾T{`™yŸjMÖºÐyàQ—Ö¿KIVÌW<Ý£è™Ëó.ØŽzŽŸ9½T귆̨!n¶%rgk‘@<5ws/€ýxoS}ß¹–€/›dÐÊš_/‘¸|\ÓVV|W|¾ÚfÂ,fÒà ¨Á åN’[73nß©-Ÿ*—C‘ch|¸VÅb0ÉYuRüºŽÐ¤Znð¨Ê¬§áOR•»Æ¨G «Òf¿_·rCà—šfô»Çæ]ÈØœ—ž¬ÇÂÜ;‘1s–X­‰T[glZ›Œ†v!;ÞVœ‰ QÊ >4eü«‚%¦Èáš%kÉ ²%J?¶šÒ¦z›nÜÄ3¹+n4Ÿ´J˜Éñ&^W}¯ìóÔ}X †5Ÿ®üÄía/W~)“ÏO*ÜÅv[«2$Í~É’øBTç0Á‡Ö/ÞkFgâQ褣†ÇðÅ„äj ·j‚¿DxŽ"оgªá#Oà4J \¥¤Sx¶ È>I@Õ!ô:åfÉâÐŽtáÍ3Jì@%*]aô°ÀJİah°)Š‘!üà‰`ްR.­:Yj¨Z…ÊJ‡ÚèmäK&zãÁH¥‰2·mÖ{Æ™EÊ~ÏêáCNv‰em¬!,P´¬ †~b#®2IO‰¨ä2OŠ<ÂÒé®B,"ÇT” Þ½ì6ô Ý è*ºc®QíÔUˆ!evxBÌÉähãd\¤à¡çUkˆ'Çôâî„ÒKºÑP¼é,F,ÏÖ˜ëFÓ¯ªî¢Ìá¬yP— @ Wm YÆ‚¿†œ%všo‚úçZ#Š©Çì&,²å&xÙâ *#®âÈ— ÆÏ¯ú¶lš­NÈ•jH°08iâwo°–¨²uE+°º±OÖ’¦lÊ1D_mÌŒÍöïBBK4, cmþ®< Âxm (+ïz|éÄø´i.[p»Š2ý ! Í‹lÛÕaøêfûÎl¶«B8~ÏPÏáüŽB,QëìÓÊàiˆÔVpŒ?Å"û"À‚¦M!¢Ð¥*4D³NþôÈælâ&:ꉥºl«¼H1Êrm\”P¬‘BT…ù É*Nl[-ÍNK¼Ø¯Àî(ZLTw‚ÚÉ.ƒg2Ýñ¾êÊ wO&I޳ë măzû²˜è† £d’²—odxqnd&Ì‘³2EfôNÎé.üÊds({Îäž°ð °’¦"ùOƒ'ó´l®QØöLdÒ î0öpGI.Éãi%’53Mü½-fˆjò>/©îêØ¦Ü‡ì´röÙøê3:†jÜ*  ()ò/¶MîÓˆÃr Á¹.³¾q-¶w'2PDÒÄÕ§°ÕÊÈñ¾†Dþ/%%ñ›PHJŠjç®™‚¤jvSnŸçßkRâKwì¢k. ñ“G)‹w-„äN*k-ü±J 0 0A„±$ʶ©MÂölæ,e$ÊŽü¥Kï¾sã^dÊ$Q¯må»ÐIÊž†ª÷ÂLŸÎ¯D$$Ñ­B"èÀ•rGBQlÏ{4ÉŒÔHŒ*öÑü”H¶T)Tmâ«· ïj´“観‡J†v±f>HÌGô½‰@вIn¿+žg…+CòYÈ*©‚NeX8 A6±vLʉGnú¤E+ÒÖPî´ŒLo (’ò42OùHÀýmüéhÕOö&(()âbàom%„¨Ë2F4ëÙqIJе,ï:Áöˆ†Qòð¬æLÿ4¹Q#å—.)ï&¯9GÐR{÷"™æZKÒ'¢}&ï¢(§@dt¯FóüwŠa8‘$Oøí°æñ|A²‹òmWÃ(!¤°JÍüÜ~ü/,©PäïÂ|ÖÅK6Fý#¢[âVe0ëGê²@'T i')ääOeô­AÑ¡£ãíÒ)ç¶5 ‹V‚?1îÊÐaôbjõ4 dtDA•’èädÉx'È$ÃdZIŽ6OöoâÈw16´0…‰Ö”“¨(í8êF>/ø&+ŠGKwXVVÜÈš2¦"ÈÅ¥hqKYÎ…Vb®VÕ–í¨ýõØÖÁÏ‚1î{)±©S‹âR¦*%ë†rf²ƒQ… µiëb†I<µS3sbÃOu€®Fº§íó^ÜÎZž”Æem-ÓDÉI싉mL#â63\0œµø– þ©Fö¨ÉA˜NPX¬Ž¹6ñK§¶÷ç&›CrtN0)c.S› !üxvŒBæÆxþ£$ÜÉ%H0S[b&w mk\lÅðˈ6 ýVµ$gnFÂã )íÐ3/ø˜¢iãŽv´íkSkLHûwñ˜iÂ6vð†úåo œª¼ïF,“~ªoxÓ5#•Ø+Ý#+lIIÅX¨)ƒe&åQlqBd7hi•$Ûܽ´ã{qRuR!ëœòúc^­7?_ãÞµIGSœ ƒi´'ËqnYpOtYË%13I ¶’ÈL(À½óÒq7¸†kÙCò í‹Zª; Õ¸gX5êødu:O’"2ŽÒq KRuÚ#’Œ*èdƒfê~˜U$âÀÞ³jƒfÉ3_ÞÉ$áP´oÑ=£DÁ²œÍöWoã!úÐö*ðPœ¥Lf¤Ë@WuÐÐ¥²a~sò¼rþ×õÒwHñg&#áå­¾uHÔÐ+(?ÍN r|””9GjË%> N?w1ÛÎ’òsÖoTã({wxñ"ƒpú”×Ȭ“£Tמ%pÉæltEƒ²K‚ƒuŽš°î|»Ž óºî¸/%A3Î_î̹E…zsö2ê×v¦íê[ÏŒ¶lvÊ ›göψµB*”ƒf…Nj,Æ"“Um9{J–JFB´sµ·¬(©!ᵞeñ#khƒóL¢”î§„B^xiA8y4øñAÿSÓ ±±^S>¨2Y·ˆY°•rA›‹O3Îâ†M%3OÀŽVëP+ÆÚ!ð˜§DêØä'C 77&g‚&ìøÐT´ˆûG"}: 19·$(±–(¦lùáîТC1qE%BV# xÏEtÖÞ®‰EV$tžì‘¿AeJƒu°Ãl’Ø` Ê9*ê2ãghËjŒžëðÍtmyWšO‹4½ƒ®Ûh1¬%\ÏFÒRË` …= J4y¦‰ª ¯ÉÚ¶/)CÇUxiRZÇõJe0QÏ7Z¤‰¨¨–»«ÊáBì1a‚ &êÂlϱ×d”2©ª³#šKB?*(À‚Šý´WŽ`³YJö'xÐUô‡!Dø5„$7á›ûƒ6` ’öè¾3w˜þ±T>Aä­QŠX^Зi_ ³°’ ïßÔ!:&÷§2ºr8VmFÑ”\šIÐUžÄš©Cs/dY³šªTÑ|aö›Vjþ„D®'%,œéiŒùQ”ðÚð{wFêȯt˜Öñ¢î³Á°¢9%2›o^…*[Pês3%‚‘Í«wf«ÏšÏ?.%o3?¢Êˆ†™¤9Õƒ¯*¢7/Et8òFJֳÓ±‚‹Þòù?¸BÀ[§Dîïe §‡U¸µà ´Î]˜éÚb3fy¾¥2ó_´Š JØNÉûÐde#‹È$&t6|ø8ÿR+N24Ëé±8)E¿¸+—y‡í¨ÎM‰­üåxrvp–_Ím‰*üÔyMB[c2·Z0ÎÂàzøôu‹ ë§²W B-¶ÓeºAëStâViI‡áðœaòà ¹“‘v$<îþo|«¯™ñb!ýav‘V:c8×0öóYw_)›ž_td*èåÉüäãšW:æ…°sЩôXcnMØ®ž©WÛ´§õ¾Ï‚ŽI‡iÄøWFˆŒÜÔ´JˆÍP´ d5h1á±Þ%ËcK²Ë:~èÌðue¶…¿0ï2÷QN7áA6¨”•±en­¾•Ðàü i+É\T4efåuû¯,°›Œî6:*ö7|I3° P··è¹QÑ æB­ÀZÊ" ªGŒ·ŠÊÎ*¯©&Eᣥ¨6ƒ®>y>YŸ…«ð,‡©€+GJ(rŒk×’m ÄrþVò~Uozzø.ã,"¯ae–b5‘}™@*Ó“q&‘N¢Ãk¿J %Ux晆umÝÂ&xuörw ‡IYк ½ýAm²ÛDZ_ h¿®oʘ¢ã3õm·cêCrç4ã±CGñ{”eäú¥F&RR5ß…©[‚Zˆt*ZzŒ¢8¼±Âvïî‚}Õ.*üÕˆÀÍkî!øÐõ}³tâ̘ëÙ³Ÿ`ÖÛ¯gy¼ 1ÎýçvV=g ø§óGtÆêð”HSEòkø“Î9rMZ,ÀöÔ ÍAó¹6Y•$#SCn&zg`‹eØIa Çÿ”ÀB)ù8)eáòA]è,C ³8V@D (þþƒ>¡ ý‡bh”ü‹BŸ‘˜° ß±°Ž7ˆd±h¤œ -ŽÉáQØËò7 ¾'gÌì=¾e I|BgJâ¹n}H!R *O”€(1è$Î) ›E+Oút*(³Ißv™=^O0IìX5^A Õ`•{dB†˜Ø`¨Tn;u‚[€XL 7H¶Þñºtœ•´¾ã²0^ƒšµÅ²ó9¶k Íeóà ¶")WÁŰÏú¥gg±ñºŒ:)A™ÉìÀxìRâÿàÎh† áñÜÀ;3$ØiºÑÊ×*ýÍí?ø¼÷õC™ŠÝïMZ-6‘H÷oÙöO Ê‚"–>ö“¨È£~ˆ3IN§802™¨)z±ÌxÔB(ƒ¨­7 ݤ *ÎǶpÊääÌ>g3$$Z#blO»†j­È·vÜÓJsqHæ¹w€ò)—-)°òúˆ#dEä$æø.ü l0QÍ‘&!âOÓ©§-Lü*àËŒAF2ú)é”B¾sȉÙ6Çpš[Y¤e³±"„ŸÈC<$ý=·önê C”hmÙT¤ÓˆÀÇâµ(Í­ÊT(cÏávHýɤÈV>Ó3ý"ÍàÎ’2ÐZ^*9LîR(¸·öZbD‰f¸èM#ŸH8%8â·¨ªGŽ“lt-|±TFèÕê¶väep4Ð p_sQ6&"P˜âlše,pR2Õ¹ÈòÍj› ©Ê9•Bëé)ŒPî5gÆFc«7C„]váP‘ip¥=Uü»ÀN>êé¯A‰PUÛÒ+ŽsZF¬ˆŒË–ËÅPä´È'¸Ìè¹y p,sÍùN²´~©rò‘ãÉŒ-JÈÚ§U¬ƒ|Œ ,s?¤A$—.µ:Â_Äá¤0Ë”g%Î6BnÍêª'ˆFau 2äQp¤¼·Šý ÏØ½?ñþÈ” ˆä1áÁYŠvc²¶}Š-UºÙôÖÞMMð…ÙÕQùǺ1ÐLÑYà[9ˆ>å:”µ'! ,”"Ž$èäFUš{\ðT+U|LÔÓŒìÄåÙ à×°•´‰#%; ë2DýB¶Y ;&š­å/¶ ôHäíTŠ=ÕG(é!;Z}䥯™Mæ}wqGšcV‘3Z‰W§ÊÆ¡k$E\¥!Ö:U­k*$|€”Åõ½Pbggæ=ˬ1‚›4ÒÛ‡â Vnê–ks-™½>#¯]à(:RÂßdÑíÌÃQõO¤;'”õ=NÃ#¡ç g|½ÌÖå,ªº{d1'Å’~Q‘ݯm…„é]K¸ZY|´˜´¯RFSHC*<Ñ ™ÎC*jH öÇúxlí*Y}„ö–ÕGóSášh•NÓ7<Œœx·åi⢠Lü‰Kr×jµ˜ò48þÄÏñÙ@#R±fáíZ„¥ÛJƒ¤„"6 Pqe6–™+;5¼'ÆH¶õu#8Â$K+ÉU}HDjä’ß6³£};%2|즜?eœÕaz€ìÈ< Ê ¼ô²ðFÊ´‡sÀ«ÄvTÝ|„òƒ¨U©9Ëô$~R²R¨y‚ÄÊL32‚ÓA÷ºY~uÕ jª:E„Éb|É@ÒŸ:ÆÐÅ#H,E¸ynqÞçmç´z+G™Áu–N5”-9ÌÏr†BB+TÍ9”0øÖº“5ö….CB£EaÐ0F JcŠýrÃG×íi×*¤ÒlI¶junùª5¨÷kõ´…#3~1¨s‹Ëm€Â–•Õ½3Û\ÝÄCu¯¸ò¢Nƒ™V¦Ç3Üx=®¶æÍØUïÚÓ®ïÇñÁE´bUêVQšñó5·'‹dŒ}³É*(4Öw#“SX4UT™ç<Ô÷A²»Õ¾tÙFÀ1Ñßz¬:«$ýeÏ­Öoç÷‡{"“¿eMc–xYœ«²MŒ™¢“H‰â¡K nvR?ìšUSÁE°úá²"Û¤šÐõvåQ7QÚöjÍt"ܬÓxž¹Ë€”‡¯, ‡krŠ¥*pP¯×²drœ}esmäemÏd\8î∢Ù6:ÉÌñGQ@.Jd*”`÷NHôô†‡dî™ÅšòÌßçK¤X˜õë=TPgˆÌ¨Ž¯¡¢¼eÇØÊê!ú®’g:Ïns]V ÂÄ ö›È;k×Ñ#$îç›ð 7‰Pü ô·ÔÈ1žÃp *"‚ô}¶Za<Ѷ4QÙ2Ë©’yA¯QR7+5‹ ,¼Œ³²ö;¹Ò5ÐÔ´ñ¬SÛ³B°•‰†›šŸ `‰áA©ê3i:‘k6‘Ê£ë_•‰E5Ò×3û ÑÇ‹Ó5’c}2i” ñ¶6 }¨_A`‡r,¶ú¯r*.•Û̌ј Ûî#‘A"¯)Í?:ð‰´$;à‹ZG±3Ã(’¼€Ã±ª>'Iõ,ˆï$²´Y›”ÑKª=Énb~¶iØ'Ù›ä"CI‰p"‹]ìûáv#à Ì2ªW48 3É.PÕa—+ãü5p‘µH„-º£À,DRМt5<¼3·[xÃé[ §%Z]‰™þ>ÃÊ/l (âT˜ ÂB0>Ãé`‚0e0Jô#Q׎#­dh+•:³O‘Ѿáw>ÉRK SY.‰ü4‘ »)”8x}ºÚ¨:7ªù­zé.±ä YË­"c)ų…(Šþä?7Z9ÂeGÈ~ 1ïR‰ÚP±ˆ¶ÀsއȯAã ™é<ê¢28Ksà§/8ï<2¤”CQþ-{Òа|{ˆsóˆØûµÇ3È«®J¨¨Ñn<ëŠ ¹]G)³¬X†-ÉE8ÁÙÄ£14¤„T¼ óšæªI …¬u/h§ä9;´­ ´¢w¬dj(œ­ ÇÂ\¬›‡a¼HÜ–˜È“ØÉÃ_G0„?êe,d­º_@ ZŽÚj'Æįà«;üE‚’*\75$_’b!Ð ²%а(*q5;§«(„ËÐ"°9Á¹ÊLW3æK“Ö´,oêüLॠ´2'=DéG↠s(b=ž«÷C´î;xD#F0»äÊêS.ÉËˈtî ƒEKÌ%R³š_®dÒ?´Ò¹ŒÁ/²Ý£{º¿‰_A+ÊùÊœñŪmÀä§§ã¤-I_K4”ú+KyÜÍ9T&ϰ}Q@G؉,ªÙ/«ÀäA0ˆ)iMhÀ%ܳhó!:¼R… ¤ÚùÔl?1öPýKºÛ8Û…"€‚,cš.-/C¸ÀÁN>â·':ñšŠ×Ñ¢÷Kê#$y¼–ÄK²UD*;<ÈÊ«.¡«E}Ú™«Œ'GE0Ã+S„•»ËÑëìSüÿ4,ª À–•¬Ä½Â´ÆÌ¶Ë¿ ì ÃEVà‚ReNZö'úeN¢ÌâØû¦#Uà–¿TCÂJU…@88š°tv¥Z –e"Éž)ý¤*‡ü$T …È2ú3kCóü0L”N,È@ E$œðLÙÄ4å‰%]W6ç­}!­Ëv›ÓÕˆdq¥=-Œá‹LzRõ±I°@ø¶Å(‡)m*ÆÊ,¢˜’ŠOKa 'ªà‡ê–®&<”™0ÌÈÃ58ò°Nìqµíš/k¦”õÆúI%eÔÐþ¬dÚ=Hâ="ù­Ì•T+%ÄÜ<ÍqÑÑ „`‰Âû¬e£ „ì®ä:Õ«ÚºPѱ0dW9ëˆ'ûž©'’¼‡Eq«PóÍ p£;Tû ¢Õ¯£r¯›!Z©JHü„Ls‹Vº’MëbI5rS®*p Ñø~B¥ˆÄFÀÚâl QÐ4?1¹ÝÊ$YcJ’zÐv½‘«@Õ `ʇ•æ<µåC2@˜þ¬‚.ݵ©p‡ÅìÑ”… ÙšÁ¼’)ã=7k¥œ¤–åOíÃ=©å¿º%¢q П͚6N¾‹JùÆ@~Çc]RëÍ–<ü)ôÑÒ=<ÓP7(î9°è+š¸¸J$5¼ï+“ÅkÌŽ èÓó׌WSœõ‰Üî³ ÚÑÜ/ÛU'¡C=_EE¶(ñ-œÌw®˜ˆ[ÉÑ)ɺŠ`sá­Ú½âµ\`|»ÚbÓ¨« Ú+===bT-=$Ú5˜4,‘ ]²ù¸¹V"»½†_u¥€E¹‡Âp!IÜÂ%ý×óY@€~0œìQÇô¡ J5;µ,Ã"*Cðñ=RÕª]yC©»Ë«äÃóšÑËD%.XàW4É ª¾^¯¢ñ1ñ²^=/Øè£Î‚†NéX´­#`¤¹Ÿ=,¶½0áµ-U#ª¸Ë:¼Ãv£Üˆ1ËÌCË9msÊ[¢CELãcQ<÷ÐÁ™ã3Œu’FJ7Ãu%¼á5„±mÏ,Wa`£ èÍ|pW›Šx‡  ¼ªìZ• cívZ½cNLPÀW\U¸æ<»Þ‰³š°ø·Z¯-ÉcÄ-o`š×¥‚ü—4Ê’½šeV,ˆêXRZ+óÈ®PÝQ&^è|ÓM‘£zˆá£vµù‹5WL¡=ÏPžŽBAÒª,d•™šå¤mZ,cü?’|ÊDè‰B›”ž}h$Òö€ʢʮ¤•3eJ†’ÛC´A±™ÅP¢4²°Ï#…ˆt²a¥ßÉJ¥Bƒ)"Óõ®ãaA݃&H`…ÁãµÒ²†bèû˜.•Ѽ5ã‘•$yâmV«–tPP“€ÊÓš‘V6¥Î£”ºÒõ¬«E¬nÕ¼µºÚ]®–x? ŽÔ–Â>ª[ØSƇÞa;˘3eH ¼ÒP9M{¦[×ÚöߢqÜ%kζC{àzb/4Whà¸d¥ ºß™=¶´!ŽòÀ “Ä á+FÓbAÓ„k/¢JV›ú³¦6ª¾˜æÞľ¹›ÀÈ*$lž@™¨•\¾/ൢFÌ¿ë"¯Í•€;£}7¨ËÝtŽâjA¹«¨äIvà«=Y[,5TµŒK>š'dÝ;uÆ[¹jl¦ª;väêèP$Sàc#ÙP—nº~Y|pxÊ.™Ûd›˜¦“Á&uî@’ªðâ‘‹¼ºÖ÷jÖðA‹O7Ç„¶€-DIÓJ·ÊqFkd;-Î)!dŒ¼$1⧬Àì¢ʆ#9 ÈœÍêî;G ÚŸOÅù=ð³oi”s¤ÜAû‰ž„Žöi•"ƒ©ä4y¶ B!´.Òåò…Üü -²4Ŧ ˼%:ðCú°!•Œr¿#/×ï ê°/¾ýZv?_|¦lí‚âBëúA±#')c·©N#Û,Æ$锚NBdH'âsÚ+YBæJS:™È]á WÌøƒ8œ §QÁåótÄ;’”åÏÌ{—ý²pqÉ­5ÃúÑŸRéOCbžæš Ôg^ÅuÔÉ«WböCuµÀUÏPTöâi{ò\ÐëÆŠÁéß :®)%ýGa=ÓÁ:$fËñ5†©ímC†¿CPñ(Ž…+g@9%hØ„Nï"Q½±à´M)ótN›qhw$äLíöLb­ÅÃ|WgèÊ•”èFÌõaÙc¼‘¼qä–ks-q|?ê4}Ÿ_r\/ó~±^ûÔ]¨Ë¾“p•[ÚŒå ÓÓd`•K³£*·RÁ,‰é¶Yä:Ü]”GJã/”W•¦dœÃÃváŽÜ#<Á“ú¢´5P}OÅßu³h‡Â$Bk]/šGÃ…-G%%SêT¼-AâP¨ím «Ñà?Šû­Pá­j`iä¾93Ñ¢QÉÔr¥C£M»D~Q:=íѨ- ¹{]eqÈ,j9°Ä-Q(ÆŸÏ*õ˜’!\•Õ`µÈÄ~5§KpOü®^˜ËÊ'ÚÜÏ)„Æ!øEr9‰5ÕYäbõH‡Xð` œ*Q„N§Zh=ýýx‚kXýyýÍζ8-Ü*÷ Ûó!Ýj]”ØHg› XÅ9˜Úæ/E^?:”fåú¼«W·=øÙô†Ž„Bj›Ö˜ ©CüÒ5p"4’³þí¶ñí2èKr—¿iäÀ?ë‹i,ÁL¬VËÊgûµ·P¬àˆMOó€iÕ}Ë“ ~ÕÂЈ”üIè“…¶ëº’^Œ+‰Ô÷°ðÅ5JÖ*$ÊÐ’c€-6·–S‡*¶ï|…fÔʯ7O©ŒZÌUªäj¥Ã?ÛZyZ®è‚®Ž%h •ª(”uÊ*[¥(ôX3˜ Ë/ >áÐbP¯“üm#Ó*¤©ÀWÔ8¥lƒ7ÁH-ð‚%y%þÖÑSIL¸r$‚¹ÑB&Š+’hŽ\ªâ `¡Ž2TŠfIŠ´ˆÙ¨sDÞªŒ7ècO£¨ôŽ‹'“Ò<¼¡Lý~7*½3‘Wø ƒ×™ÍÇ[WÌ üб6QdŸ·˜­WN6ŠZ[¦¶»Nžîƒ§›²x”%ëf:"Îÿ£I]¥¢È;ÑT&s[(ÄДW¶Ü@—€ôLÌ'º> HÒNúI‡(B«ÀW[“ˆ«šîW©'ˆÿdð³K6¶‚Zçï©K~ÚÅYÞ _ ãñÎã„é›:é]ð¹¤FngÒAˆø™EÉÂî&ÑLêJ5­„ÄD‰ ar ÕžVOA$4 c×y$ÊXE5€Š6È’?¡û*o-.WæœLcT<3d`ºjLT㓚T$éÂ*ÙµBÀ‡\‹v¨¢Wòÿ€w‰¯ÞÌEࡉ­m*…Í[› "f]Ê!ι=’yGõË)hPÃêUÓ,M²JZ*¤b%ék”Íêœi™y$ÝSGÖ¶Õ¢TâlS†涨’8wˆtÁ!ÍŽ»5sÊšŽ *c¥ÆÏZ*I z¥ C&X”b™ŸT9ß"ZtÅJ#é)Ö°èƒ5%&tÊWÓH½<ÌÛ&om­š¿íâo[•YÔ151 ‰[ªtÇ)ÁD‡)i•Õ å "‚°¡K} §»Wj‘žõm– ðºdÊ»ž# ó8‹6Û¼—y$Ãj29ú—“¡—Ê·® >÷'nHûž¯.lYÖqw§Í̲åK¤[-À#OºÉâ‰d 3±³Jî<<ÊÌìCò\@¯Ë5váµ”),=Où!«GaDé|ãXØ®œ'ðЮéUþNT<„îuÔ_ê5‚Ø6>È,vi+ Übl¨MvqèÃ$B£Ý]Ù’¨ó°ë³U8"ErØàáþò¬š‘ŠhTLBqœçPaüÐ.Õ)½ºR€6 OÈ  ø„!O˜cúˆ¢Q7´V ÆaÏàv ÈcïÙ$ù!eQÐ~'$~ÆfOùD²a |Äãò蔚øPe@YDâ‡5ŽÊ&*D°¡Æâoª¤ð?VjQ*È›2Ë&O»$š/ K#vGÜÊaC‰Äãw8u lµC¨wk’òþ¶J.Ô9”š72‰Ìã4Útv™(Ë"xÌtj2–Pë±9Ųí“J#öíÚar‡bqy Âaª>­7®Ö/KŒ×t€ ^3J"| `‰‘àe_ö,V¢9Iäpd1»äf2»p-™Ž€7æLã|^Je±Çù8xÜDJQ&îKbø%¾U‚ Û#z=óþ.µ¬X¡¦ B¡§û>‡6+C@‚+©2¬º9êrì¥$‹ù ÉCâ–< &º=., ‚7h¼<ß¹N+廯‹ŠðÆNŠ^’ ŠLÕîrtˆ& ØÞŸÍrH»"èüV¤Ëbâ‰?h‚Ü’IqC%\Š’0èË&Ö<2³[#¨/ Dˆ$É3’îÂ4Ó"î²&°î§sBý!ËDŸ!±Q¤XGŽÂƒ"ôJ†‹¤ÍŠìêŸí:%8Qà#Ñ/J ¢>–#ò™úÉ<ìÔŽÇéC>É””Çh•W1¦-ʲ”IÔ̶~ÌàX“.Éø_ÌI’q(€røC‰´6€03 ‰Ô`Ðí@5´_1S¨Ë^ˆ6(ú.ت+¤Í7C²»Ü½ @V“¤å] •zšÎ¬l™Aeà ¢kbaÕñ{v¤Ê턆-‹] ÂH‚íÏ+b†ŠžÀ^-"c Xç]§Úí‚ ‰’.–bˆš/;©ÔòM¤4­’îÐTŒp“¤H…9<Ø,T….Ÿõ|Œ~ã—B3(9`ê(9\¸‡¢/5Æ«øÖ@~* U)9ŸjêqHpÔà•qrEÚä’Ëd«wÇ~)óϯTÂEÇR?‰ûf‚š‰"qøÛ[ó°\ÂÉSæâáJDT©}­hGšlÐ^39R€¥º×jÅ«–ÊB®\#¶ÑÿéÏ*Àt<5 ›¤ˆašel˜w­´ªò(EKC?8²F‰ÑúR X+XFÁÉòþÏŒf¼ô!A¢ú;GY!t¥•M¥>Ì1Å:`iéšQ•‘& 1éT¤|Ÿ³uŠ­ q{¾¦œ”4ž]d|¤öì%¬O9T{›äuìÊ8Z?`1(‘À ‹àzBÍä§–è¢hçKm€ÖnMà‹ Ïízoèµr`Ë£€ŽídUšpS¨hþXÌ¡h®•^xq¶VŽ…e­ÒÚíl¼Ã“Ïyu©U§)•hó‘\á @zZšZ>7TGÑû-ËeÉbØ~9”ýHk%ýÍ®#ú·ÕõÒˆeTÈ5tiú?j•³6ó¾lGw%«ŠH Æp†kS4VF¾ÙšÖ7 ‘˜NlKeWµ®/SP©Ñ«Ô>ç¡,Ô©ûiʤe+6À“a›»|¨NÚŒªZÔ™räõ˜Þ±¬EU œ.ëÑÛMµDÀB›,×ZlÄU%ñ}@Tg¶|h¡ý˜±‰–”` "Ä#ô®;Àk‰ˆù@ûhØQ&_0¿À&Øçv›¼¯WÝ[™Ç2zÞäæž|€òЊY)Yó¡»mä:gRPŠŽ9ë]nK­Zð4î” ýciši¢SýÓ#»Ú¥¾íq8-&·Fšì^Ý’¦_?Ð[ nÌ WÛ¾pØ®îcãš­—_>™n%uéû˜I ’žOŽé0 em‰Êcóp‘.³#QdØ/¹ÎåqÖQŽ-“ß¾ñËqáÀx…vayÚê멦<9Œ«jcãxaµh}–Šhýma±Dn/hSb¢æ²m‹ky³3¿%RÜfBýkbçXù:š¤fÅZ<„¡€ü@RBæŸ'–ŠÌ+±¼ªZc^–5ÖEQgZm ¦ãÒí‡$¦%ƒbj  yƒ€ÿŲ…l±¥¨er½êtšÍ ¸¯®¢Œ©%,*„Bƒ ¨¢ øLP@ŠÎ¤b¨YˆœnG‚OåœEçÒ++@u²;o®«P¬"/¢Ð£gDoõŒà˜fÚ äþX¬w ȳ†ÜIênDÉÞCm"D]"6—bv]0Œl鬹ä–nf²+/šè¸ºDY æý¦\XÏpÔÍ¢,Œ¶ìiÞHHd«˜ÌjüqÃâhÊÎþôŸ0ÀǶ&p%M¨'â¢ê>Åѯ‚ô+H;¢'-É©ÄhƦ…0E-w­¼ÊŽ>føGÌðB¥°ÅjôÀìîì*¨œ2YÂþÕQ>Ç®‚ì/Ø—˜àØÀ.tûÍj÷±@ç²ê©¼jÎö憘Ún*蕨XÎF çY|,…Ãã`*©M†yíLaEðób†rLJ½K™q’®±CkV·Êª§IHŽìÜ’HïÈFq1Þ²b$éHDIe¢ÈÈößÂ$À «¼†ï0ýÌ$(¢*Ïx¾‹â»)×m„]f¸Ï+àhNxƒ%F(äâ6-> Ñ -šØÊÂ%¹%oûÉ')L Ãb'âöÝ'šŽÐ¬êŽï**Í«d§l9ƒ¢YÀ(®žqpâšÎÐIçì~ì&Ho%ÈÿÛbTå‰^q ¿)pêOÚ*Ò¢V@ Ó"~#b.<â¨íN‘#¢ˆ¢G.Ñ,÷+дà.ÚǦ¨žäüq #-„g†®þè\%I<ânêj¿.‡ÆëjtÈȯ¡ôCbí(@Ÿï8/Ï\r¦Ä' Æüê~ëGbgR1KËÊ2…&®&BПgâ1DÖà[òÖ hRHR’§‡D£¯ºGŒ?É;/)Æ”…B›¬6x1¢;±Þ÷ã0س¢êàå‰Mƒò–ÎÀøbÂn!h++$ ˆà´¢TžóRõÑÐqŒK+Ì÷._!ó5‚‚ÊÇ.R2€ÓÑ6ÐÄ(û¦âÏâ SÇâÔδ•##oæ .a20|'ЕNÙ%©Å.s™'Aù!¹n'ìŒHˆ÷ŰâjsЭnºæS Ž1¶«î67lŠóIf­&K®¶Ò%‰ò¶ 'ŠàCÂZj?î¼ÁH£Xý'8¦¦8¨ÂáìÅOÐqÒÀ§³J'âP†ëFêòHª1¬|ênÌ¢ClÒuîÂ8¨àré¤$*èÓ,lhÏÎC…Ä™ï1®H¤.Þî£ =EB3 4°x¥*_ÑŽfÄü¢2b·/Šö£óå&³$-Y4r€¼MFVìüNOl6$’g.j.ʤ•JhtD7A¡ö‹… ]#Ò$ÊÎÆ4¦æó*Â*Ì8ø‚ºduBmGÎñŠ??óž5–D†4LH,X…€nédÊ#ŠŸ-j6/&’ü–è¸`ùhì,^ø/K !Âq޾~Wp“Ñ’¸I„˜w+›Um(RÆ r¼R{è hψp–.$:ºÑ¾“)Ÿ©•»¤É°”:+’øF×Ö˜p€¬yõnòŠ®XØU­"‘*ÆÈ¹øpm/ 4Qçy;ÁÕ)ÂöĵXœ#i+0âU¾ÎÃõdeÏ|jKâ¬lˆ!6 2( i…™¬¢±·ìÍ Ù8jƒ`Cɱ€À6¤Á!÷“S&c”ÚQÄš:äôS©Ö2ã´m?Y…QI†¹óˆï¼‚w¬ š›˜ecêvù#œYÌw6*@Ù©ËäþªJƬv\ŽÓÜ™è÷\à¤í8ûT^+²Îî\[3¾; 27ǯtÁE…bÁMÁBðZ‘yÎ=©–•úŽè¬ØV óqÍ Ôm5%"·â7v×”}8~÷aI¶3ÒßfíŒö-–úèUØÈT„PI¬×ª¤tQr©P¤#<2rE×Ð DIji‡H É¥œ‹øZ”®×ãXY‚l#YÒªe^aLÆYÄ„ñ•µm5 _%µ’œƒãŒŽE4©oÌ¿m°ú,š×Š¡øÓ0r­qPzBõœ~3„§†!Š18mjn;È×<YOf4ù3#7GE½î|í Ûúæ§‹Š¦”›Ö•Œy¹Òéd#q®êëÀ-1ÜëbªyÑ–þ&o©§Ð |[Py^݃ÒÉ5éi+äÇ«×z‚Äâ˜ÒÂ*hSÕ-·»ÆWG[€n0#c˜‰œTÑíI(˜«î8{|ž"J×k‘7èÖEÞ/Mæ˜e3ÂBë‹§ÝC-Ú!Õ¼Ù¹q˜•ÒµõÆ¥.qÚ¾í:Ši"Ñk’§ae„Ç)oã5a™4m¨¿E„†ú¡v&Åçt5< ÃÓº MuS(ÒöÅ¢ùœ·íGdlùûɪ%9jÃâXœêÃXm¨+âÜç‰B®äéPê³ï¶ìO<ÄBŒS«×wµýØ·7¥mö‘ã.¿žnršñ_NYÜšr—–x6ךº‡gøØÝšEâÖÐ ø ?à°˜$bèD*…Bbn þA@²;òH“>¥`öY!É’èÌyý(}'°U0–?eÏz‰8£t˜,þA!¤¾çTh,fG$šAã5˜Œ.:ŒÏæ•êØi©A)öpfaSˆOd–¨l3n¬Í™U §ÏåÒ¨ìzuƒN óª|ªë˜cl‘éU„÷•b WäªÃ¬D.v»u6‰KŸ:™Ö2!4­sà¥a|¿RuõH´^ 2ˆj_6iÅ– q¸Ð^3™4›jäÔùž7¬ÙGµôË¥tÿšqŸV&ÓA6Ð:ç—1å˜AÁ_Ðç‰÷xÑœÕ.Y0=­#îˆ0®+¾5éS€À¤é@*§â2ó·‹²\ç£kâžè%icì#)Ò~ƒ¦Ž² {DérøÊ¥Ë’°@ÉrhŸ¶‰$§Nb×¢ì„=½h”)!4MƒÔ„¼ 2tð"é¢Ú‚,@ Òœ0ÈÊøŸ½è{@*òÈ•D¬rJ“9ÉCÒʪ#¤ˆFiÂò|(γ\­.É‚]ŸÏáúOlâ>í®èô®’?NŠ’šA`B–;³ÊùÓtÀ%Êh Ê¥Iû§a.!Œ2\ÿ#zŠLŸÃ*K.¯éfõ¡Lù‘µÁ'ñ¶™–§zXàWíK;ŠÖø~ÒJzø£aW9ø›/ˆÌl›)étÜôiû²¨Ñ9í;%“ÏV~η~§œD“¨eàÁÚlz!¬8ˆ‰º{–Hô Z§W–ªñ"O$Í2Xú‰²ó÷ú³¿&BŒ÷p‹ÑGì&öÎ 3Ûd$–$¾ØÞXc³Ž»…›Qï$„½¯•ïÔª ãÛb¥oÊiŸ3Âì1xÊ}Œõ`€ž:¬fiݱç,N QOa&?³Ôº’žLJZ´6f_aV#ÆÅz(÷µÎû~"èŠ=22å܃ H(M¤C¬£[;<°ž"Áô†¶Øi¡<‡Ík-èÀ‘Œ#4¤¡—˜(³YÄí•­»QüåJ"+\D™”ˆ™ ÓI„yÆ·˜«²KÑüBTâ^#8xÌØ5!úwXS &‡#gÖ? ŠS!J=¼´úÛa’L(D±¨†VM¤Œ;¤D>ÈQœ"MÑÈÈ×vˆß£ÇŠÕ»ž‡£Ì È‚¥ùpx Z…k›³èK\à ªEô´BS+ãÛ¹$'§‘v(œVÄziE7%h ?côrN„‘k/B ˜s!— %ˆÂ4 ã«‘’Õ1%ù:–áj]^òí/¸³ÄOÚñ6ˆ‡’E€HzdX{ †‰=œM™–AÝs©Wä¨ÊçŽÏãĸlóžIGx“Ý£FA…*x“ ú„m½á«"D—X³íŠ£é¹Ÿ÷¡<‡ñ±‚”‚wÄ$qD€MFgÈ,_f¾N() y&O4¼‚¡p ¢ˆý6&†?…ÀjX¤Ãr%¬1É’¶xðl¥Q5ðRe3¾'‚6ÃóÚù 14ä…•V§Å[ó+]ÊX¡UÉb‘¡‹ê$‹h•&窛C¬!KHÖÍ:Tüä’ˆ‚ëj‰$CÉ=JJì S<‚#iKžš)M*Û0Ãê‘£ÕI@Ê:yùQd,8°M*f‘©}—Ž ZUCù"hc‘µ(‡‚Å:„Ó+†'ìÞÌÓ%2•˜ú‹LÍŠF‘þÝRý½‡ÔÅŸ4Ùh¬HªÚ¹uá¿É«¦Á–—jÄÈVK@»³Ô z¢;¥°¯I Xäe‘lÈaŽ/îíãP¢Bp8Ñ4žÞí²™Xãp›*à˜ ©ß%¸“ 6ãÒ#Š‚@I¬˜›5Sœ1 ¸Ô&êý›ó”@ãR¥[¤¦{«rƽrß¾•2;ÕFR"ä-Â1Œ2Óé¹ûXÁȽð}&¨B¤gT4–Ê>&ó ;üU¹ ö¨ «-zm™Ãz)±é©Ë³5XÆKÍÇ@̽é[“Êá‚!ôfˆÓÌ#‚F“))Á ù ¥˜“qàŠ|¾Ú™(‚–® 2( º2‚¶(?x˜>@¨Ãr59†¶q¶5›ºؾ (ß)“+˱¡î1ø‹ã£Š<™9øµ ¨‚½@›‰Áî‰zý­ Õ=°õÆ;Ä2r¸dƒÅSHK4ø3 ²JÑìŽê›|CZ;à­¨%ð ?ÊøÇ[TJÍ´VÚ/ùjœ<©·ZQ€9¤È‘ 5„C¥ãKLtžÓ 3­3t}¼zv¦ìŽL´É§2>r¢|˜ ͱԛ”{#r6ÜËXÉÂ!%Ç»3“¼(?!œëN¥áh“5AKT;y«{¯6"6:™%’\3UIP‰(©™É<ôØ<ù.Ä Ãº¤ÜáG‰Qëù9ĆÁ»x‘©@¼Å*Ø—¤ 0Ì00§šòSȹᗹá¼óD» ͸öÁ¬ „’‡Û{=ÔŽ»Ãå¾1È´€¤Êe)¬°½tŠ“ÊŒŒƒB“TG<ŸœÏ+vÏ©]¢3·Ã®&S˜ÂÜ»¹üæQri®&Ê.:‹Ïr 0sš¿8Âð7Ü1¨|›ú¾Äа#‘Ý´ðîÁB4óõ©Ì$›ìèÍLÅ q’#=†q01Š0CH½a™/À4x}©ÊžÆÌÀÇàŠ¾Ê°ÊËIl¢ÆȾˆö+̪J”ÎHÍ•¹Î+ !Œçsµ® – ì%ìö˜œ©:d-*¤K„(ɧ½K×?œx€ëÒ O¢å6?È46µDìOH»(EC‰PlUh‚‹á7#ADÕEe©É„-yý€18ãà2Ѳ¬äõÆ ª:i5±L©Jø°—z“0ƒ§àˆJÄ…(‚é¤z@LI!Oè¢;+(W×u£E:â®Gbœ®›Ó“،֓Ï<Ü´ß´T,ù |J@é‘6š©£ÑJÆèžÄÔâv¨ÄÊÆ*È‹WKÂ%ÏKfÛ#Œ4Û©Ñ”¾Fz?.«#¶k «A¾cÙH\Ë«xã$ùd*–Õ­P¥»—»'•¼49 z)²xˆeBº±™©°òK2\4=#Ü™AD±H±¿­ûU1CurרJ(*›‹S—É3Ž©‚J²" Pˆ}Õ“øš*âq#ôûÐMƒõ®Ä,˜ÅSÖ)à½Ùݘ±c¤äª¨Ó7L«-´•Rk̈‘Í®*UÓ¯MM){$AËÊÃyäuOÛ¿6K ¨p¡R[C{‘£ž1ZWE¸­h– µD~È I±@yÌ¿Ùg¤” ËMOôyV]A\ýÒ"±6‹Í` MNJ͈±ÉãÛÌë»®Å9ÈE“#òà êÉËdŽÂDVX`±›{ Œ1 ÃŒ¥½t½]¢\ZuQk¾¥b±.ò&£¡°(E)¸‚Ö$ Ì©ˆ‘c­¼–t¡Ž´ÐÉn4XIªdËR%¤ö;ŽT:T¡Dâ¿]Ãù{«¨É7_ÉDxT 㩆RR¬‡É3¼ü6MŒ1R£ðÈÄŠ¨„ºE¥SÃÊ7 ù¸©(8Å %Zç3]‘ …PÏ©ã„uIÓâ¢;ŸßzqW!!+ €úÛhB„MkVV‘eT¸}#ÿ¯5¯@å¾³9·®™‹NÜT´gÁ«à9Ùz7YMFz¡…X%+¾SŸZœÎã’E“؃î€Ä’ŠÍ»#¥¢;³Ø(8Ud(‚¨O„ ›{æ»Å½r>…',],“àœ8äÀ£&Ä…½¥F{Ç5 u^rGò™LHLˆª„ZÅSEí-V†Å¬´¡JcÇÙ¬Nüg‹åZ¸äÑûï «5Ø ÛЂ{3m‘ÑÎ.¬ÿºœ,©ÍPÃkàbHÀp~EÊ޶lSšWYc‹ä8ª†/¨‚•øzg½ ˜´*"í@ÒCrD›|NÂ!ygUÆUc9V;’"d äÅ錅'ôK‡Á²äÀîçÛå`ž1í¾T8áøï‹P «*(D|CÍå‹ÍþT‚,Ýãñ8ÅÑTü'$ª04«zŒU­ùa#dÈ<ÇÝv@Ñ ÁZ¨CÝö4B.¨µ5T¼z6Lp yj¸jÊ{<“´´Ö!±-sϵ)é;á ·Z—«]¦Södã¯Â%/ˆ‚æa?‰€à5¸Ùs˜¥-Î|ô¢#‡²Áå:¤‰¿a<õÆýuÉAœ'²•ÓÁ¬SFD¾Ь"E1bK%Õ OUqUå®’5Ó.‚Ik"ÉJÝ–3ó(#&ÓŠ·¶ºb°¤ä-ë¢Ý äBUÕ’ì3õÔÒþ  Š·Æ´“õÁ@5~í óJ.<Í-躙_ëmrÃèmåHÎýN‡û?¨ MW Û]‹d·ƒ•'ÖÜžP»ä’7¤Š²‹ÍgøÖ®iÜ©²ÓŸU•œYé¤y×.Ñû D2´½÷”«Éµå´;¨ÑX×þ㌰“E|‰¥–a6Ä¥ cþ°³O01…$Žó€9‚êY° ß²8òeæ@Γ6P³QÚKÌ£zîÜ¥€K’ƒÒ¦O ý 1rïB0žÎËq»ñK™lbP¹õ.>†'" ̪¥aò‹äâÐøv‹í.æK^$Ãàç8‘7ØZ(Ã#íº¢8®áqùɦPƒ•ü«qã&R»["ÙEÜÈM&'o­ÇQÔ塟$»jY íÙ¿íóª"$H£g¢æ×`dbRuÉÕƒ@aI€¬¨„s6O*'}Qß´ÅSö¼ÞYŒ9®¾ë„ôM–)}Q¥l!ežù®úŽÜ¸ÜËCÊ.¯+Š4;¥î4˜,.‹ÌÆÀ |8Ãj^YÝÎÛ7Ì¢«Ø¤í¹Ýª ‹Á­ŒÖh|‰Ñ«3äLn.ÍÍ #Œ.Ñ7]\zw!Š[H}©"ôeK¢„9 ēމ­¿ Ü6iÔ«æŽ{‡¡_¯ª²Ì¸•ºä-[Ò«L¶AcHºßÄ&,¼Ìïñ5ø¶@\ØÇ9([¤XœO×@Ò-ï¾´ôR÷‰€':ž}ÝåucU—CÂ?2ù’X]SoÕHRÖ¦æ)˜eÿ\˜m›ä|ñÞjqrZe“aÇ?K,=§;Ø4xZb›oÆ¡™?[†h^£Ì[;¬€Aöð`ÏÈV1L2ó –ø­4f÷ó™6Ö\e³ãu§)öä¿؈#$7šëÐ}·<áîÓÔ3@[å_{â­Ur4Ë·Y÷ö'Á’7eL0èjUèP­·B‰54OÌ>TB„á 0Ö& –Öî¤ Ó-:¼ä#¡y½ŠM|ž Í2o |;ªà¼ Í"/7w%£•,]8‚ Z ý¿Yò}4T‡O^}µìçO$y¾¼˜Þ»ù¢€Ú´ŠáþŠ U¯òº”Ýòvô Ý-R”<£÷‰PhòÄP}ÉR û‚@€ (@ ƒ?áÐ÷äEý†@€qx@ ‚>À±ð4†"üŽÅÀph4š2÷–FáÒ4Ž2šA¡p¸›úFýžGÀ¯ª.3 ŸM’9Þ•›B©  ôG@}J¡ÇìÎi#œÆc2:4© «W§3ˆëk[kŠP²Eéòk>áNK®tj¤fa{`(û ©O¯cb\ &Ž‚òÏŒÅb}9¹Ã¯Ò˜½ü¿g_ò‹í*Mx¥Ã³‹.—MÆ€¤sèξMÝç¡R86$XƒV'2iõb3ŒÎlð®lRož]dú›”;9ÔtÒi…s¤ÚÉt3H]'¡|ûAúì#Ôâ@€ÿx^¾}t¥{_-â.ç"i‚ ʲÈë’ž8®ª‡§Ïüý·Éºr£%‡»î¡èʰ¦ I˔ڡ*Sž›ÃÀ L†¡Ì"⌤Î3ÆÖ&êú"¬&\:Ú1®Ùþ¼» AüŒ»è¼6„D ㎻; 2*î¸iãù¡ 2ލmú#!Bm®êJ-Z/@ Ä`ºá$h|’£(è8®)ÊÄ (ͺ>ªA+{˜„H¨Ò/Ô•G«DJ2kgPr>à1J\‹š´»Þ4pÊ;¡ìˆÔJ¤Ê¡!“üœÆèT¬„S1Êçɳܨ‰Ã*¢ÀôKä¨ÕH‘Zy52 2ô¢4î H{¨~»ª"?^€òGLÃ’„&§®5©ý B©¤¸Bô¨;ưRðØgÔ®›·´:¡H¢/õ^ž£ð* o€‘£IdŸ÷Ô~¨Ó£Q'œû@Dзl¢ÒS½e4$Ñ%á] Ö óÌ¡é…; àˆ<Œ‰Ê3G86å ¸Ï-ÚùÂGú; Âòm…ßðCfåLJ)ò>š9h²äxN ~èˆ]¥&cmüÆ1ª~O ë4k;œ²x‚s5ÑͬÊÚÙ±ý?¬³©ô¨ÉÀŸªâÇýÃXa§ýë§"xâ ©*ž§Ã;æÍ#ö€ ŸîôÄ-²"˜FO¬ž·ÏëÔ›³hšGU»9ÞÓ‰;¯ ~XµÚ3Þol›vËM:\€ŠÄSIÝ“õª>– i(§-}2ƒd"©L£®·dÄ&ˆî߉ã 3^˜[–1ø²£ª3¢FÉ O´z~|Á*é3 $‰Ü”ó:Œè}è¤6“_Ý/ÙRÿxI ýd 2¬`h 2@T’Ê]­©_¸Rx»Rió]äå•&ÑíÓhä¡Â&¤žp#°q¬1'kU3åaþ°uÎVZ ™4iD§µðõ ºz^è}“5Ƶˆ»þ&¤ 7·Ó´DÉ1¢bFÊÖ:QUÐ*†Å4X_ BÒ|CíkÇY ó؀ɖ/(| 2ÈT2+­kØ4Vñ–dí̹BLìšiÂ_x­ÅZW”[Sˆƒ38Bè!9*Šˆ¡tÿ dHz¬@¿*¢C'Gáº"ïñ¦â…É‚¥_Òq0-ÄJ·<y@æ”ó^À[]ŠŒ¬)™,PoË’C½—:H`"¼&ˆ½$C“gà“VRþ^¯™Mdˆö„2³¡ xcî µõ-æjm?͸¼uÄÒesdéc Æœæ‘F8NN÷<ÀcŠ’¸ò†˜kK›w\5¢Wº½€+“w€°‘sE ;¢Žý34Ú›H5_¬V(SP*툤҃P˜L™Xù!ž ¡œ­SÞžÍ_ÑæMÞ`É♂cÙàÍ’L§#E£š…%`ëã)¡t¢3(—j ºMD­.šb:›j#NC¬GTʤBä,€*˜Èª±¨4Äù MÚìH¡[ÿLÀ Å.ø÷ ‡â¶Y8ú¶åi$}„|ÿF6XëÄü9ÇYÚ‡pÍé&¤}Á¢©gŠ3hqó,˜ÀXv#—±Ðíx7x4ÓHZŠòÒ#¨˜.Èâ5´iý™°‰²)-­c6ãƒ(AH*Bï´Ì)—€{ÊÄ ¸÷%]Ïàœjj@H!z^ ‹„mÑ^ùklÚÜÔg+>lAÛŠgd›­Tä\˜øJw`á†SÈ_¸G0Àÿ¿õâöѦål L°Žû“G¶| D–6”»ºœL £/Äú¡—TI-±!‘i6HÆõ "êºQ‰ä] _·¨ÈÞÊæ†Ñ.žës¡¾ÞéHÂ`vHWwV×MÒýQᕸcµùižØ5o\ÊÒqõ€•KæW~˜ÌH‘®ö¶Â\¢áŠìç9¨ÞBкz`Œ¡—Ôaèñ(–ä?Î#îZÇ©0†¥Ó'¶¨$Í-Y…C ¶Œm•Š‹y`KxÆGJ¤2lØun5$§Ê j ÙÝÛ\tá¸h£/R ­±àû’n¦ì+]xíÎ¥‘©H¯j\{Ša*ыՂ'ˆGáÁŸÅa–!°êí4Èl²”âVë¤Ùó¦s®©>jèA9­—³_6[ ¯Sä8[µjâWˆR?Y–ƒ»ñ Æ™ÓýÀ†Äü h#©ñ¶¤álô[ƒáœ\¥D¡TpÈé‹~ñ³c(¦Ï¬ ”ô„g=hUu*@™aмçŒÝÖPt2Øà6‘G œ¾Qýµ áþÑ\Æ!/ 8ÀQâ{œÓ2©M¬ÎÏ)ë|~µÊ9¹œ¤+Rãœ^r>kÙRï¶+•åÞM7‡õ}ËI‚t²<éVÝ;6*:ò}@€-ÐÃÚ•æsŠ.tã:b‡u®vûºÐ·óˆÁ~ ¯ËµŒYažéµ1­ä¡¶y¦y©=öË>@„C6-Ø1€³˜y«Ãƒö{¥ýÂ<-ñøª[ÜCž¼MÓþz7õR?âÙÌràÉ6éšX€³Ý¦Ó5Æ™·½ø6¾á>T™Ÿèˬ¡´?r‹s°¨ç ÄÑqðg¶êƒïžv Q˜'¿áݽS÷þÂ(ÉÎh‹pLo&shöL  ˆò!ãüŒ(J]¦4˸´ÄJñ(eãLÅhÐ-®œ>å@¨DdùÈ<åãží(C/¼&6­Dr­Þ®Eö€ÈJ¾ªÏI|&éºäÊVšDZ"h¡¾¦DxVâ€]îvò€øJ DÚø¯ø,«vîãV¢ ¶'‰Æ!Çø>í˜{&rÊJòÂmüvJ„Y¤dPÐP3©®¥ºŠ†¸Q‹£ .>¾Êœäþ÷Ê„c®†.p@Xú„¬ØoP*PÔxÙ‚|fÂXìæ:c­Ð#ý aüÇ ‹ü|øÒΠØÏ‘AöqìVŠjdøìã„Á £Pq  š‰šÿfˆ‚ðx'À m ^rͲJ%Ú_M šå¬Ò*îÿ¦îÈ =¬t†à& aG© zÎä_JLàqpéèLY¢rÐÂ.µ‘ãÅ.æð¨£¯bºjðwM 1° Ô&bçª>eÂ#Íw"öªhÛ,Ä:bxÙŒPëÍnvnš=¢`ÉÆ; ‡b¸DÚÂ#0–âü2 lÒÅBy þ™ò"ÿ«Ð߈H œ§è ƒ‰àÿ/p#ëp(Çsëª(Çò-βˆàoK†š¯j¿®‚bˆ.íèòD³Z×+LzˆK )õHœ( x¯QÚîj®~Ã$î)ð³LìfË‹„?ÑçîP"šKFÔ¸QÑ-ä¢ÉÅ`ªò@gF¶ûüÍ&žÂ?p®éRY*Ž6JˆàˆV“*.*«-Ox5Ìh3>!ËôÊo—9ê•6Ê„4nF“~èP}dcG2­±Fõ±øØ.ÞnóI*q¶wÌ`Ð1JÁI¤”@ M³° A·CÉI °¬â§.  ¤Ï÷<μÂǤ3« %‡< ËÖÀ§;I…~Ù‡DGH­qÒ¸Qº:É›:PBtr°äïB•è£muQb1°›0²]@‹.¹‚ÒÀeâ}t2qç²Y¬+иú…¿igh/).•i²©¥ÈÉǨï«Ânï†åøÇpý §@âg´s2‹fC)vg€ Â'«p*ŽÚ0ÐoË«)oc P^lôã°Þ¥&µæ1/PnVÑ«Fñò&úçæF÷Ë€4†ßÇ_OÉ@O'@Áþ(Ö¨ô“<ç(ÇdŽå(1¦UDôDäö*„sÒÁLL;>Vö¥a6 ~T^³Ã{":*M+â"(Ï? J› ÒË"ævRøq“&t‹sáK€eHÇ= YXé-¢Ÿ¯ÒököíJ+ j±,ÿFÃîV¶_’„°š4eôû€ÞRÏ jlO"€5ñ¦«°ÕvÎÞe"Çs0B 8øM­Z×—C´ª‚"ì«.ò¸!B©iºL§Hm…ôl”)$LïO.8m‹ÔÑbîfkc>qôÊÂbUU+Ò'Ñ>¡ÞÿeÉ0èêõxÌ Ê“s"@ !c`”ö-ð¾ú™©îÍì`ÉŒýJ)h@¨ç^nã»ìÔ<íSi`âéÐLó¤H oKmÃ[Ïú'&òô‚Èòزv2*.Vá=Mìê1/0^–Æ%Q.ê3ÒÌ–˜S08ãr3.I³ýWhìè/&Œs¼Û5Jƒ¤NÃkL4ÑNsÏì:‹ñ.ýŽÊÂ}*áüfí:›'(#ü}vX‚~‚îÉ´nv@%.šÊÞß×ö30©´Ço$D>V8Ù-¬½òx×É "ê küŠÑþWb2±êPüº°XD¶`}ó‚–± ÔñµI hyS&Ñv(0”|¡ŒÐ{(À‰³6͈†F‰:”–ë­‘8of.2Rã˜Ï•1)¥`¶ó Ltj¥ʃ°üLµotq4Ò÷’tÆÙ‰ÏUÇ*Ð ¢%š¸ íîʰÑ1ºa,ª˜†òh?7†T_•ÐåDº÷¶€Ïtƒu¹d¬æ{Öò!jŽrVWD¦e÷­ÃïÆìåÁ÷n¡ó[1Á,šòïö4uhÁ'šæÓêŸx%†rÓ„NŒ5­{ªO{–L²ï±À&¦„b2eVâLõ„ÐYzLc¬ƒH9d‹øëÖoP §Ç>…ôÐ5Ú×”L¯ Sï:öMCoô½õº#÷;oÄ!tŒªÇëqí î'9Y‡tDøQ@¸Þïð'+×5a—íŠν“Ïr­£Nlïy–B¨ð†æƒVÀ2Üu÷k eKRs'tŸò°fv6¤åõ\³y’ŠuY7¼f•ˆÆø#ï*8F'åf‡m}%ÜØ$ ÞR›gVÑ|uu$šGoÈ‘U‹gVô­Hë¢ZŽÉe ²Q èMBçqgIÌ$Á$Ê&\øÊoöÎJnñ”.9×2ôây^=®˜-ä žÖEßVnq3Û†G•äQ}”›‚0š†ìoνiCgªMQ«;›†  “­Jçâ5¥\2öÜ6þÖm4Èe;«‘£«LæüÉÌÑhï9u¸%Y´¥ ,y6“ƒØm‚0o,ØmC”›èîdǹÁó.90¼+ÊdOå›M‚.5ï€Ö¥¨[”ë(ôÔ¢°Ùª>éMS:‰^ ƒ­#;5ùö$5¨3¦^uü9=Ï|€ ÛTÿƒþ50`3áRqtï&ï6Pžé™e|¯;`íþUr:½ ]îî„O«¯ûá­ÀØ¥¤ƒ1IÓ¼÷³K±÷Ä-uNµ-þ,n‘_39ž6p Ë|1¶çAóÔOûà*š¢P÷° ñ÷ >'ÕEüY¯.ƒQŸ˜ôç¡ Cp˜•%ÛÅÎr‚1³é )wù²µÙ{|³&çüÛíñQŒyÌÑ=ÊÊÒ×)ƃ’׳±ácº]糌©Ò±>ýl% 䨅¤?ÆUÛ!ó °éõ5¼|»Cý™F ñø¤†Aˆ?¡˜¤bdýŒè'Ìb>‚i‘ú5˜ÎåñÈÅ]ÿIcóXôjú±NàöX5‰õV¢ÔDŠ´E)/ð%Þw;œAïQë¸1F¿Æ*0¸d¶ƒj¢íˆÌZÕhœ]fÐG®^ÿ¾€*°ÇÜ–5ƒ„Îê6ʳÿ=ºÕq×p+a-älYæöÞ¦ÍÅ3Ö©l~Zág³Q ¨ƒ]ƒpxS¼un”–Ê€1ý-¯a±Gí\H& ï`åÄ«À l[Q×?ºÌÕ¼†U2íÌz{ެþ ×ùÛ’ì+‰Â¾˜@ŽªH„£I»°Þ¡ÏJ˜ ¯ï: ê()¢ ç!,ZЪ¹@b™CnÚB@ Êã@¬â.è£ ûÀ?é“®'pZM­©š¿ª©j[£KR0–¶‡Ó }¬ˆ24ú#kÚ ·îÃLü¨-€–µ0 ŠI’$¨È,(¬((:4´8@D@ ¨N‹D«É«z@÷3ʊгNœx»ºˆ¤Ð±Ëˆ$˜ã$+úÿ3ÅIKôýÀsb€™2h#üˆ3Í$!©¨ôö».îðÐE‡üšºÌË21#DÐõB¸§òþÏ)"pŒCˆ´ÔÂ`ŒÅÃ'ú)8KÓêO½Hƒó]Rà-,ˆ4+ P Ô§¦LÊÏ#ñz+Ðb°6T¿²çª5cËS¸‡(*3G Šþ|^©Â‚ß7©ð©¢Mÿ}Ñ(ÚþÆÏ€$ì¦(È=®Óìòÿ6 ð³£L`‚Š(7ø{ã¶òêͧõ”òÈ$ ‚Ru:À4h†&ãu]ˆ†.¹Rv¿ÄØÛ¨­ÂèÞ8%u]©”þ—­ôó¦™@@¦µTt~®KƒkÎ$Ù¡Ö‰ü ÍH9íÐF–õ9¦ëè¶–ÁH&àñmÈöà’¿0¼>VÍ=d§yÚ}£àosHy£?ÉÔuЦ[Ñ6ÜðÑú(¨÷¨òÕ‰&]jKVih6¡²e[ÿ‹9Þ)/¨ƒl÷Èa+»š Š }mkˆýöµ=ÍdQŦO*çI¼(±›{a13Êõ\‰~.é!Ö’Â$iˆûê€l໥֜¶P3­CÏ„>ó\㎑o¨à«¤ðsÝ;Û^'a_8§˜dy>$‚Ÿ§âÚ‘JF¦¹Âpg‘‚4‡fœõ“· ·Çúœ|D)”.Bîé 4CY¤X¨¶sܰyyk`]?bª¢2ð…îq¨Öô±Ë4viiÚä’¡*ŒNlŒˆ6CˆüEM' †Aèj¾ÙsŠìþ&Dò¹§£\g­Í–«%F¥ëÈ´äèØ”›ú«Dȵ XÌ”Ùwr¶Í†DÕ »Ñ“–¾{ûš;«R¤1†!÷EÈd¡>dA\\÷?ÈÜ«UP]È&«$æÈ:é(1©8B²°Ã+‚µ4¢¥HøÅ#HaµÀOÁ$cõ§-T5ÈS7rÚûæ€ÃYêëJ ׈)5&×wù#xÿ›Kü Ð zâ åS‹yÖ¬£<®œ I°Ì™¨“ÄKD׎p¹¸ÊÉ*7Ã5ž5 œBKE¸¤y‡¨v[Èõλ4YG^:p™UV¬ç®€6Ï0:Þ=¤¾«ÞÒòó#Í¿€˜¨Q :Q¢!Df­¹E™Ðî 5ßšÓ"A&E*hÜãf[³ÒÄðšé2§€%æ$òzѽµ‡ *(—7+å{ã!Äi}¥wÉÔÊ T~ºÛÉ•À9;_lnQWT·AèíEu  fʪ1…iÆvá5ËÙO˜é‹¨k"µ{|?p¹AœÑ®WÀ玊‹®0ÃUšV§7]S¸¨tÕÂeŠÚæz‘#Æ.L§œÌ‹…Ãá¨ÜÜŒ ½è!Fê׆œÞ€ÈÁ}ܺ"Áõ5u©ÏN¿…†è"®ñ¹oRµ¤œÍö«Ó-B»£v`bÝöy¥ïlí0ܵæì\ ‰*HŠƒkÚ´€‡0~5[ØAæøN G2Aäý<«ž}ºnDÔ6å‰WœWÚ\>h£DØ]vµ*‘{ZPÅËùQ(ÉÎ^®“©Ÿgì¨ ›þ–Çã¢âHOpäYÌ~kÛ¤FÕöF€ÓVM.gÃ<¹˜\Ç+¥Òv‡×N ¹WFçvã3ÊB ôr]#o—={ëÁµ ÉËðÝ3ÓK{'êè¯g&èâV|—¹yìA“S` QrQ¥y&¼½ríµ&C€/\›]W„Æò3fm§pçÝ‹Òsß2D´¬øvl“ë$‘½~þ-ž»É\Â5ÈaûuŽFÃøxÞKÚaãCH{ŸÆ7‘nþ¼+¦ö/ºӛʚ+âiHÓãÃ)ú¡ás¡e3Ç+)§7X‹Q/bˆ Å‘¹}±iF¥8¦Ò5“cž+[Û}”ø£d }1´ª2ú·"Ë©±¹ž²g.KL@¾¯a•0 ç6á•¡0[s—‹#óX¬$ Ûd#by#ûÔ3y•8„Ázq’(‡1£s!_–À†£Ø>°$±C ²³¡, <`´AH;Òˬ+1šf 1›±² ó œ:§“½0ì4À´; } ñ:¯;„¨ûŒð±)xr?™t·ˆˆ/² ±:e’¥/b£8´»I›…#¨»@$ÛÔ>ƒRÐ6¸|¯âD%Úò®¼„³8«°Š~Yÿ¼»¡³|«#Á ZªZ4(Ób¹}´@~¬H@ÍËjÃz(9R¸!Ͱ2üR4ÊùÛ‰‘¤Ú… óB‹S¨·!Û"(–±Ò­ûò"©‹I ’"1Å ©8D{dŠ"58ø}‘»¹“’Â>ô§ªÈóÉ(³¿’·½œ™ŸÄož2D¶û»”ÒD¾;=Ä’Id€ &¿„c*4C§ìx Š'Ú±€úÔ²F:t¤Œ˜c « r®È#13!ÆI¶“̻ЌQ]8†¬Ê·$­7)¹!™8Qͳ1ª¿³(•Ø7 üªc™[½¢ãHˆ Z}*Q쬄.@¬',|¡ž+$ñ´ÌØ»¹h¥¤b^±Y)›i6cÎKªŠ3{§Jy8Ó s° 1¨."½ÓŠJº¥<Òšsnä0¦‹òH“L½A°ÓÑF)<³#¼p´ iª¢)Ù¾*$FJe3E=4ͼj¡„½Š¸´)$1ž¼E+´Oº Š2ûòŽ:zš»²Y8O)Btô! ÇNÜ1H€Ó,°¢! fJb¤%iNyø ð½£8šó†€³¬ˆ¢ªQÏq¡h±ÂÝ:ầ b4X‹1|ß# <ª{qŽBŠ1߀jt4æ› ­Ù|¼ã –• Âò3Ä¢"”[ò5NX‡É6 œ ÉŠDBËpˆâÑ©›©Î5Káî¾6Ó;½ŸÄì, P÷ÂÁ€ ’Q3¹ÐˆÛWËbFì2"{¡ ªè´Êk²3í2îúûCü¾<ÛªÜEÌ>âç´•€#‹œaÅeBE8|¼ûrªð|Åž`ò»Sœ i¨Zç8²¯ŸÂ,‹«»á’l «º,Ê]“ŒÙ½£ã¯±õ.""´+?¥öÝ"¬¤YFõ#‹2ˆ;ÃE ò»# Z¿h`?œ0Ï1â° †=Ôl8ìÑTáœc°“…^ºÛÚ‹)_V­/­ zŸ7ýöÅÌ0¬ó:4©Æ°ØUšzÖ„¿¼ôO8Ç¡__™ó u©9¯TòI5j“4­Ù´ÊMØAF’iË1“kI·IQPíÛÐL÷Ã1½ð¼½##™Y´¨Ó m«àóCF5B ÝD\ORçM’ò™R˯!õ<¤¶J«=u Ý£$Í›ÒÞÛ8¾3U£(7â1ɤSbìj)Ï]"S‘Ò¡›¦Q3ã QÈ3©q¿”›ô'Sà Æ{¨ÕÂ/ ²<¬F—yâ¸1Qaa;Å9 ´Nk‘$Ù_M6½]æ¢éxÜj1Ž9´–Þp´4לnn!ÃBÆŠ›IæðޤBú:Š"Ÿ‹»¨³6¯+ž#ròÁ_Qs1ƒ³ê³nåùõ>)O§­”Z^ó˜ê¡Û¶¶ìÛÂâ¼=w]uíœTÝÜfÂp´Õó±uà¤z'УwÖÒU¡ ö$ôq0dæó4{gËZó_¥ÅÚóZÇ Dlãœâãæü==‘8‰ EyÙ·”|£Ti“B•aæ?†±f+¼,­±Üef=‰Ã¼Ž#º#T¿CôÀ‰5fÒ}ÒØ±Û«º^±K2§Çqcò9+œ?"_<‡§9¢ÊMç®!5:¼âmœ<`h`.”=GH™[õ¥n2…-4Í‚8½é$ÙÙà ;²Vóx³Ó•l¼l-6×´»l¤M_‡Ë][±—ú·"YÍÌ•øU ìKdÂ+ÄFBäcNE_Ä>òQÔœ¶KF›#Óe¶áÛN¢yTÓ<:ˆ%ë3>.£°“ðŠ»‰Zi†i±¯LÔ0êÉqäÛ„7ðBqÉúÜ$ÙǮۄp¶ß} J4䆀  êô®;öiТSÐ(óòczFTìýˆ-½^¡Ù¼RÇ 6’^Þ‚¥nň…2’²2ˆ3TføX—ÇÓ2(€ÓBÞ.šò Á fF·=ìøê®¥w”j0¬Ié‹a³Äë,e‡»Ì¸#Æ´­ _Ù×bn_ˆÁ󽦚j›#w¢o èd•P¥Ð<Û‚vÇ»µÁc«rh²¥€_¿ssæ 9ND¨²ç†µÂ~á¥êyw{î0]Ò“¾Ýì$‘uû54á÷.mE>Y^¢åÜ.Ødd=z“””Ñ>p{`-þˆ–EaáØ£CIt¿ã[5o®^wŠ(:ôo(÷ŷ¢éÀ_â¡ç÷‹ûVáÇ^íÅóö•{âŽu"\D9{ÇÎí5Ö(>ãvõåê2\ñäݺqð×}_Ž>Ö”râyO»44Úñºzɹ (ÌE¸3ÅM[,ºÞìý!ïÒšME]õL¡ª£L¨jŸÚ¦Šeltf³‘U2ªbfÄ]zÙX€>à@h#ê „AŸ@d ýˆ?¢@(¤AúŒFcQˆ³þ=€r9òM È$`8P](>ãÏø@c™ÄŸÒ¹œfg3˜@¥9pQ+“?'R¤®u¤Ê&²¸Ìêu>Sâ «æ½5ŒÈ,1IDZc(Ú^¶¹“5¤îO{¤¢3(¥Å'TZóæÁB¡Óµ3rÙᓘ–"Q ¤Ø£hÞW( C$²iTŽ-•Å¢ÒŒ¼þ=¤ÔPãÚ Z%eˆQs súQ¸I¦5‡þ¦gI•á£G¸/Wð$rŠLêæÄ·/ÈÏIÁÀ©60;6üÉf4ÛìÏC¢òÇé”y$V!¦ï%~NDj™!‡N©;¸Åî\§"Hr,2ëÃ\¥ϫF†*ˆÂŠÙ5hÂúâ!ÍQþ¶¥ÌclÅ£ËHzD \…9‰4<åmân‚2©‹¦š§HR2FŒªÖzÃÑ)øž° jF…/îºL»³K"ý$Ès"Š;²,žB Ø©-›¸Ï£ ª “(©B@â*HBg,$Š4­2@ Ÿo 'Iª‰¢Oƒ~“/3DÎù9hd\„${Ð~˲:%+¢4;+€H³Â落ÊÉÚ<ùÇü ¾² L+í#5)Š­>1üû¾#¼÷µUŒ&p!/"œSÓг*΀o"fï§I]€¾È*LÞTRe>¬z„'T”î~(°mQ(·ÈòbÅ(t%©t–KHƒX¤ ŠöÏM"3-Ÿ‰B‹2<ŒBóÖ0dú¼É2…]ñJ7)ÙŠó¬è$Ï„=‚5èj™¯±ä¥LÊn³·%Ì €7]»N5Ôõ³ŸNð"Ž{û^#•»QmY SÒ­.‘ÃS[PÊÚòzV‘Ý4úš¥ í×GÈÀ “€ ªjâC$Æ÷Ê5¶øÖi­l~çI¢iS$=JÅ`2W”Ÿ›œ‚%kêâ¹WgôìNYØ+eçöµ LÀ ŠÄ]È•ÆòXÕ…%O<*€ë\kLC‘ô1Ä2¥ÝLÂ@œë´)„ÄÄeìÐm°zV <°\ Å‚{Øã& ¨&~ÈÆ¶L…6ã%TUÆà_çLðŒe¢ââd#Ç~þ.f€"fãn[ ùG†6­À¢˜tm*¶$f¬´Ëøìj bÆÒvd<8 fêdmô! ª7ˆevoö±Œæ§>\lÔv©)ÑégSªD·n’ŠtQk´ó~%˨ÞjR¶ÎÖí*†kD,>¢Þj@ öLÖ¨£î™¯í¤„óE@“®Ò:ÎNÝdh™¥ˆµ„O®•)¸ÕôÜ"ÒseÀýÏm‚V˜ŒVNèfÂäp*8úéL .J%A ä쀈¬×£.²(ÎspؤqN”ðrü,ÌØø¢ FëSÂ䵦V&$<á"äÖk.e‘{ã¿ 1½ ±» ë×g˜Ó̰‹¢Òîšm–%Áµ$¦Öe$=Éð†‰ŠF{ð’+qø—#.p-D§‡<¡ÏÀu0d¸²‹D( ˆ8ðÒéQCn@àm§ê2g,Ùçª\rnÞ/ã§R§ àB’‹Pÿè5B©e®fì\ Íó0qRy’»)N5&ÒœŽb Ï@‡ÇÚTé¹$l²æ«†™© ÃÍÐæç{ìšGè¾ò|踞è€" ^"Ò,ÇCá Xˆ ØeJ¥bLÞiš!Ò†1 ! CR\o<{â3/P8²tÁλ)OŽêÀrùBfCÊÏ2§†ZìÊn¬ˆÏB0Ò%aop|M>Â,›"tâ&ªÐ°,Àfq!f13R‚™ozH ²·(FÕij´Ð›9€xnÚEÀóæSfj¦ „õÈÚsÂtËÊÐéˆÙOõ0‡WïzXnH'¾‚­<˜+¸× cO"°£\ãïÏ­c¬ø¯_ â¼IN ÈÀÙ%µ;¢~—áú¾Ê¥¶r$PÍK¨o`§<¤¶eøÜÅKˆ–!ö)$<0’d½sðsí¼ É7s5eÿ P%Î\¤e´l+¨þä½q÷>ŽÓ$ö\ ÙñåCnÓIt‡Ê&)²©i*,nòĒů "Qvn¨šÒ(ãîR­…à×I7N|Qq#Iö’xqÈ^LŽuŒ#o˜" Äm2Vck H nNÅ pSIØJt¸à»Eûsð<¯íÒ“‘p;‰‚šwG”%k-~׋R°-ìª ¦ ÑcÉ24’Ž…¶"˜`¬§=ƒºÎïî~O&‹M§ÓÓš§#jïÏp|­Z0ø¼sT€0SG”F­Óìb‚¼p)aCP¹E@dù @ïíX×Ò®—DÈ‚æ¶/©ÄÚ…T›ÓÞFŠhN¸%ÕKæêOzËHŒd¾©‚6o!Ì¢þ#é#3–¬Îª´ÑP…æDE¿0 qŒ€1‡€R ëÒŒq 1DRª„{fèçU‰ªtq|O#fÒQº‘Y!4ªûòÏ\ù;9ÏÅI¬¯pƒ¿¢WŒu˜”»æ™ðã/\Z8t)DÎÌÿÙ– Å6}™ÅŒ'2^+Âõ¡öš¶Lûú‡¸œj»«"hËäÆSާCVIzbÙÅ•5X[ãn ŽÚoW¼Läò½Toa'?X‹g$iÈ» „«M“–©-ÓxiµýÒ±ÌíLø»Œ|Æýe% ºVÆp¹Ž“,b䛆êègg›=(6òw`´NÒ  ÕµZÞvy4™Ûk¦îg_ªNyðyp` Юïs#q&u.vòfô^›úl;.›½3FŸ€eù¸:s Œg#)ù5s¨w7rõû 7†ö›<1°Qrï“c5…)]1”xË>u0¤p3ÓÕÓrY“b=-ŸØØçPY¦‚‰†Æ=—ÐfW_ö¹õŽ<2­`¦8ÏB$È¡¢G–n½œ÷f›LßµEI<‰ybÑs'Ì]{I03})ÍUäÝg€äVGYø|Ô¼ðÓÃîÿÛ—n“…Èí2ª"“‰láø‹V[_eÀ}šóuEÆã$Þp9üBÛäÍEÙ¡¨ÚB’œX9'•­ÀVD•`uƒî¢"%tÜfR;:Lsó]á²)­;íÙ¢–÷ÈÃeÿ⇟¿NÒLŒþ4›â(ü{é”Ú›ÇÝв™d‚Sm¾Ô¹¬"©açWî×TBÐ=±m¶9 °æçg-¶:ÔW¯éí/‹¦úCŠ2ýaÀÅ-¾Ê*ב‹ÃQTî‚–¬Á†È‹^Ë÷Ø¡˜í%é,‘V>þÑÁØÅ¤É¿¸Î±Ýɽ…ú3O®ÜUV/šôÙè •y,ÄéâÖ"Àü¶­ÁõÔCDN ‚Fâ«–>ŠÈ×ây‰¼orÎ̦sz`’™êÞû.;+)‰mÀT¢ShºC±p}=/7²N ›÷ø˜ùçB5sy|êoVÝàáÑ{ ÎcVæö/|° žþñà€6Ûtþ rÞðÿ/£oÇÑÁ.ºLs-‹®PÞ‡"¨•ÀÇÛØ4«rî¬J»0Ó±r¬®*²îé%mZL|!\Bð¦(»®¾*òh‚0È< ~¾ÎÊ(Ð",Ã÷"ª”j³>,™þê!Ézìµ°€ bÆ>O*-ZäÖÆ±âg!Z¬ÿ­ÈRî„QŠW@ ‹¼(©Ë3«QúÀ'äàøÑLK´‚=GåO"ï uKŸ¥ /IlëZˆ"R©þ«4ˆru&ÈôÊÖ³6ñtkMKàJ§ÒÓ1ü¹QâW;î:Ђ®VÄî‹®îqòô.îR^]ðó"° îy^íZimÐç4òLè‡;ñJÄ»ÁñzT•Æ­Ãôñ¦êŽÛ¾ö­³Üѳnß6 %jV@=ÆÒ$ëHF1<¬òÜOÅ~³YïÖ;;~j͈:ägt%Š¡»ímô‘'Qrï'©]¡¦)Ó‚Xè"¬¿$MZ|ö#ñ4j…\¶´®WY£¿tÝ&ÎËVûD=7¹¥…S59D:ãL*Z‚Ý6 ÃÉ~ª•ÄÏE¶îR/J¦vR tâ•V·IX‘”UŠ€,Œñò™iÿvIJ‰É`°ÖPô]+G<~Þ\€W)jå°+¾Ô©6ò¥²ò¸Ìêäè°„úX­R˜„CÎó˜´KœSŸj&/r(˜¨}ÝÇ¢;rAš>š%“"–K_9šHíÒE‹>iVd#ßt߀/±³³™üïÞ3­pÞ[<'\KU£‚1-ô¦"‡²Z]ã—(m6˜æÈJ”},¥›±…²|Xd pM¬—#¾ÒÙß\h5˜½§DAÜpý](\B$ŒÈA:5e¦@çOòÙhÆaÂ0'~žL…j4õžØ™"n‡”B“­ï:ʽ3Â]Ñꈡñ&ìUÊ Iá­G2wÒx¦ˈÍíA¥djëÔTsVo%d\¡±Ñ§k¹`³TZigá\`/~¼§–Jf¼¹rÏ“çªåJ nŸ·ä¾ôѵò\Ksk×H‰B³ß”æ$YFÖ‰ÇTMzp5zO¡]Ê'ÙpWª‹+Jö/oÖ)ÊnZøo:BŒæÆÇs'ÅùcÔL«•û'œQ£ E²E¸H8Bú@àVJr©‚ÙÚ‰—ˆ?ú—´€ò«Õb¨/ä:œZwëÇ.+ …z„ÎÎ;X£\Ð*FF’Ó!@B[›x‘Î'ær™}¿Cñ«Dª:s—*o—w2ƒè]Š#'V¹@µ£úÁÒvIeu&¤Bî÷m[ë"Ž×+†n\Ìzªôë¥FœmâJîŒÖ“r“ø×i-uôŸå=\ø˜-VˀεÖó˜îmc´¶ý#Ó  ;É<(„¢f!yNe9e}Ô1ô­&"uÇ Nð”ôk[ Å”éÁaŒo˜˜û4ß–žš>&Az\.†àÒìÖ§ õd`JÍ`«ÅH‘þTÔP1c©9ˆß‡Ùñv3ȉ.^ÌA;sö>êWΓ•^xw'!wÒÓò_ÖYÌIÃñZwcÛ—¥ªj­jþî 3òŸbd9¢ã¡[z6Rµ¡ªö-„ «=2ÃP ›`%hÌ.ÉoŽc¢,bƒ%Ø—œ°«&"Í# ³km»Ùýi&»q›‹ 0oA›Æ@aÉ»²£Í¸+®CÛŠ{u·2ŒûŠz2á%4+r‹Zó¸Ã¿2U-k JÒ<'£1j;7(‹±ÂtÁ­!D1söA²B"ó“ ¸ð«9¯`å ¥ð}ª‰Ì½AIŸªRKBˆûFº[ `—?0›Žø¹9j‚£릘ַY¹ [`Œi¶²G8Š9 ñ^µr‹ {I½ó6HÏ%Ü$ð-šq XØ “‡Äá)„0¢˜4J&›Ãy©û+±Óu™²š<%&‚î4¸á§ªI›¨‡Éî—Hï1:ži;²ÚAJæ½¢ JU4ªæ¦ ß j¢¼‘:´Ð™ 0Ö2«[§›(Yù¤Y®‘¬*&Û£Ðæ Ù©BZµ¬áE0ò»tV@“‚¶ìF¤Y׎:7¦ÁUGˉzêR‚‘r¼ˆ…&#§Ç"°¨Š:yr™‚‘- [Ù)Ê›k&l@‰|6§´‘–‹ý´ Š¤À°°H¦A±“þ²Êß¼®k±¹Ó@ù D›ª €:’‰Hĉ¸ô<ªæšê¼¶°·㜳§»ùË1›¡Âÿ.j8ɼ«Ì Rç°ŠˆQ‚-:܈¢.A*šE+?Ù(1ìrx¹Bòm¶"ãµ*í sEXئ:˜®RñÀkC!¯˜iºr´.ièÌ×;ï³òbJh¢¬§5‚ßÁÌBŽd¬>‚j±# ¦‰é "±Lj>šž¯ŠÁDò˜¡Ã¦*7»üY*˜(°˜žˆ›Áª‰,×93?*°ðGŒ:Óö20‘*웲\®°7z”•ÿ%Ò‰!*t.”ò–?pÜ$úäÎ)¼É‚°C ¿¿›þ5{¼Ó}¹CêÌ2À ªiI § T­¶ù§?°Š*(÷‘ì9‰š>š¢äåÌËQ³4b»Z²-çCËZ& ="p™¬£t¢:®Q®²[x4Ý¥â =;K b]ÐGÂJ–H¬›)ÒËÃòó¦#)ñ,<µ¬á†«Ì¸ˆÙ¢‹Z­! ǰæE«D›Á ‹·6âL§Ñ[ôÄ™]Ž„œÆ£Èˆ:zÎp†Å3I<@H‰/Lò‰ƒ/Æ<ÍBPQÅ têüD&ƒŸTƒ»JôŽÌ¬D%T¼‹€¾˜³®‘èG" ñ·Ì›‰œC+"K1ÔÝ<ØOœ´å³@¦ŸÉùs¶Ôª,¼ÍQÁELPÂj!€4·aV;ðºM?¤ÈÀ6‚è(Ì‘¼ž?aîÕ,ïRئ 6ˆ¢ ŸƒŸV#û¼S>x„¼fRx‘Â’QèÍ;«‘´0”íÄ ÃCÍ´wÌj%P,ã¼:¬;ÄT¢S© vÉñŒÉ#(—ŽûqŽs@=2›Æ ¾²k‡ÉšªÌŽ7c©–J=f°#I,Щ+l¡SRW¬û9Pñ1ê;¹A#)DPðÍ(¹áÕ hxY‹lÇÚù¥Ü+O”<ÑF cÂWÚÈÌÊ”C^’±^™büÕ]»m/ÁÔrLñÏ.­;{ϸ…:š¡®U`‰‹6¤D—ªÍHÀ£Œ$ürø—½Iûs‹Y=¥Ë~Ìe$ìA:T 0›Ú¡Ÿu•c(ˆ‰X|ÅŸËBE´w0<~D“ý‘4±Ù¹‘Úš ΂æJ ¼QZ@Üü%ÚIp&{Â!]F‰Y ‡­ÕZâïÖë0):G— ªÉ ‰zÂk§’kÇ\"Q®•b¤/aË] àÇ)ð& ?¯\úåЮ`ˆø÷Ç!váþ¾£ãpz^ÙÓ'­6“s²º*•ZUŒ áÌ»l€:?*É› 4N)Œ(Ü©¢œÉõ¯Óô…* Á;S®ù©‡Õâ¹õ Ú=ÏòlY› Ý„NŒ¸<Ó¾¨c R‰ ZÅÉBÒÚht¯IÆ;šiÄÔö4[¥"u¹?I£¼Àý6kýG “ÀÛ°VDh.È„L*£¤[çÖ#Û_8–ÞØz; ‡ÍÁª \)ñ,t4 ãšrz¹«„%·éŒ<¼jEõš¼=ϱÜE¦æmº!¼ÉÝ8}­|\ Åݳ µð÷ÂR)ßs”7º—;äùDP—K%žéʼÊÚ1 µX°ƒß¼³Ö\sZNé÷‰XïŽý3Ä;‰ž< b¼×rq'ªT :Ãéå•%Æ-;^Xì›É‰5¯>»ŸÍÓìÜS3-»œµÃ¤yVA²PŽN\«ïªĬ±éßó¦º{ðà& SðÖ³‰Ôˆ¼© i^«´‘âÂÃÚxçFq”R ª,œF ¸xæîÕÍâþ]jƒ“X<,%}‚«ŠÃ]í)S­Ó¨¹¶’—N!,£#±ªZjWFb³¾(‡ð’kÆ>Ñ‚ßÊ:[ƒUMtÛÝmx=)šÒ&u)Q‘T„I³–D{¤’¿ã®xM`± ñG“1à~Í8›¹ZZň\¤Eÿ¡Ã3åý…Ï£¦ÂÛ8 É Œ2@å![¹~q¾<*c‹Q¸a0‚ª+wP:‚K¶"?îà¥Ýtz>|ÛTó8Þ3¹ð»Ùœ+á©é¸ª fBöÈ%¤E%ˆÏõÉcý²9SxKB*ûuµ Ä¿#ÝmÎâ]¯}Æ^=* tÄC=Y›H ‰Eõ‡î•ÄšyBLVœ¢SÞˆ‰Ê&ìEBn§€ 27‹°¨øj’G‰Õe"IÁ2ÓªÜëzÌ®Öã;áç4%s?6-Í[ÀÚU\%$ó¬º4ÑŒ-Ÿ«Ã>Ó_‹qÓ°® ” ³­æ×“‰àZ1烻Àz¸?nÓn†TX¾ÐÄ˹ô/MûÃδVàÅ qúÜàµ!š5ãý T""R‰öеñ–μí&8õY€>ÍÏîêüYc¶ë-èA`Š€@«f\8èU5q]›ÌPKD¹ ÏRGØöŽD}ÈsÞb³Õ{ïþÏ ÄÓ„9FJ¨&r§¤­þåÏš›O³@ͽ1›Z³ÃJœ¾~†eÌèd›çÌr,[>ÓF«©R1a¼huINÀ)ñ;Êí‹ì³²&µË}|ZÚ®g è¢pXã{¾–ñ˜mèûÀÍŠ ¬¾b«á%,d–-À¼–DœÉ—ሩ‡ˆþƒaÕ¹i¬þð hb¼°Ã„µFˆ(*¯.:~ £ò‡Ùô/¸k&2a8Š”ÙJ–]%ŸhÜ"+Ê3Î’iÕ8èˆÌYíÙE™ï#¤~µT{óúSh³e‡ºø–ð‘ZF+gš­P¯Áæ†ö-÷ç–cb-:5e[.˜iQ! ¦(Ûr9¹pîq&Š©dìġ!¨¡‰Î×Ëß,ÿÎ+ÉblòËì½`¸„'î/lì'OÑlçtUÞ·î„H¹º} ©bMÉQbL S¶Ç»³)Q³B^UŒèξžÝä3O8ýÕ¬î¬^Õö$°sx~$ã%’㙯E݈ ÜõAýâé™kR8!â“¶dÈ,$ð±ª-HŒ¢aRAoº}'?Qu¬Ôà6Ik5fÏ)âÈñËšãÙî̈Uûås”U™ÆXçT–õå]ßê½b¾-ÑEò÷ˆhüi‹9E~Âõ^¤ zÒN‚¢QB{¿šm­±åX‹øîº lŸ¬`9E<ÝsŽ0…äŸ^ª@ L©CøB® äQð¶3ÇU¦yÜïûÿ›Ür@6ùŽ#|²ÙÕrð+¼#>ÉxXÜM™^Ú[Üê fwQæ)E;%¶°V,ì@X‚ bw.}€0ïôôÏ­;?ʰI1ü•V‰/@·zµ×Ö,õg‘™&…Äņö“YuXÝÖ‡h²F|AÉw$kÌ1ËsÚ%:<¤Áÿ•øb.ºî„¿Œqà^ÿˆþÁ``D& †áÏè€ %BÀÑwÌe÷…Ä£Ñ÷솒C€q·ÜRM!~Ç¡PY ù3–BehHuŒ¾@󸤲–OÀïªEQO`h~¥ ªB(2*´BM.„Aê°˜† ­Ä¦oȤæu1”E,ñØ”2å¯%¹5Èw‚Âm5Z|2¿d‡Bïà Öt±KÀ2l<&{1ÈÕk€S/y¾×lYPj%œB,óL²M“’a¢1+ à³ÀÁzCëg ÜÂrð¹C¶Ä)œ'ì.ý¡èìpŽT"¤·Lú8Œè=ÍWâ˜Çþ:) ÀǦ3\óþc=p8è_£1«¿dÔÇÇæ=äçÕ:ìJ²$Í"Áª¬:Ä¿‡û¦ù$i#¾ˆ6p‰üØŸê2XêŸ …¥[Úß63®³¬ì;n@ÀPé¹gòbiF@Lh„¬ðû=*3j¨¢OkrÕ0ªþ· ¯ÜŽçA2[®Ç3(‚Xó$² ¸ÈºX³©Š“,ð²L˜®¨òÏ+"©‚Hܯ¤„¯‹Ðð+óXܵ 2fÊBR#Dîº˶(©ûrÈ9ˆÛÀ±[Ò³£É4€¤"‰Œ<¦ÈÚ˜˜·/k”SJD@KH¼Œ©‡­Q€‘\äôÊ@#\KóûE€ëÔ’#Ñj¥>ÂÓê=B¡ÏZ3P€²ãÃ&1:!Ö.BPº¡*2{AR%8þ¥ÍóúÔ`44¦:ë¬4„¸ëŠ (¢O“ÿ»/’꺸 #R¬>gûÛ$,rY7°3íc6Ò—k‡.¡ÉëÆ¹)’|‡#Ï«à‚°÷ôl™ÝH»ò|Xœ•‹ÄnÕÙ8Ï` 9dSçÕì‚¥wÔï}å·ûÓ—Ÿ°LS5.Xìh¸ˆä‰˜×t²¦Z©6ŒËÓËZ‚¬÷ì””C ')€q|^{ëLV+š0rÊflK-º'´©ö„Å8ÉùcZ4Buo$6µ¤„iz!|¹(+‹$ˆÄc¹´û€O•c€ÏnÆâp‹Ú›¡Ø…ý2cHCϪ+[Áýdné>€êgí6oH¢™ ^à$xáÞPþÅó¢Ô¬ýQA€üJOB¸ ·¬à¤ÕàX»ß_n"œ%%6wöóS<áÌrS¸Ç+ï|‚.Z\M¨I6´{¨Þ:6äy‹ÚCsÇÓóC¼À88ံéâ´äž³ÒPnTÊi)™¬…~æÚBfMéÐø½u¸^œË°1H-Y˜3Jý^Á,\ÄŽ®þÃL7.= ·d¨«ÝSNrà¶:‚Ô0þyeɈBBŒ@á ºd$AR˜’"†êÕ:”‚<êT8ÿmè0‰&±SA1„QßG$bÍxeh-³eLâÊÆ…ä¥)‚.úHLo¦]ï›$’ýD@&gMÂE^KCïCŒAR¯äaKû…eš¤ãURj´ƒn!8.‚P²W ج‰!€YdÑ}Ð(Ói YƒùTõ!VaQqì<ä õå c¦)¡’–Nbjb„!Ѱ9f?VÊ×’L•ˆ5Ô?_ù2&m’_³%Èdm"瀲³¦©NºÖMîÖSºµpgñàBlœÙ·S°CÆNƒÚxb)/f!Ñ<º¢ð‰¥Äˆ’ì§6-0Õh€³8~Cö|Š3–„$lQæNŠYUI˜³¸éFßèÿg1)’¿%’UÑÜ…%y5é?àT*jò©|?x¦>Ol«|¿…ü]f[ð¬ö Àh¶æ?Œ¦?æÕ]a%0™xH»Ÿ¥)(ϦrIñøKŠ“sF®Òä‚HV¡µŽšXÏS1í=„ê®7òÇi­@ñ5NFÀZН†ª(Õ¤9 â-.Rí¤ªÍæ`Õ˜…D†ÌöÏ'ì£cä”ÄͧÒz¿¡lÇy4 ˆ€83]£½#qY¦»XõÎå(´"{KHuåô]•h%W¨ŒW×…“k±Æ‘Ðä^|¢•Mµcõ>œJ…í"wTâ´ÅÛš “ Pek+Tç{d>VêuI؉‡åÞnnMù·¢M+Z11Fœ6úþ(™îPU*Ïw? Ë=°éŒZöLaܯ–ç¤×VLw碲&sêXBlÈ-P­²\ºŠ,Ñc[Z)‰–ó¦ìBÄ!ª EJo5z¢ŽðýìJ¼ZV  .Jáü—CäÍ)ØœŸØäévÝû"Ä\餲ÅM¥)7/ öš»ÝK§!&Àó­˜ØëcAhÙ´Ô.ü]5M5Ù=>§•%\ 7~áÄÓ¸õJ&ß"6wqµxcï™0u@6JK&ôÈ“MîEÐÅó³x‰b‘eB'Á.û%w8†â­m/Šæ1í•d&V­Â¿%Ò!È6Æß!-D€Sk6Y ­²Â6OàÛh6r’×¥ô…3C‡ª,²Jx6ÌÚÁé‚eÎß9ŠgqL<$[›òdp ˆ³œ¦ÎÕ`¸Ò>ç%=_×Ë×Ì‹‡áí}.¬–nv]w¤C% /Cû+éÑï(äu')±àÀ& ˆoK=dÝ^;%ÕÏÍ»mÕ˜ÈPéÂ)4vO qTÛn‘½‡+áE% Nž’ÄS¼µ”¨d©˜„ËXØ@®µ#’+‰NQ©¶JëY˜ÙÜ òüs‡O3ȵö·,Í:Z“?E}±º?J±ÝCÛŒª¢6‚{ ZfèÒvÉ[c”zXU¸Ý|¹$žóµë¼²½·_¦ ^½‰¶ð|Ý‘4ñ$ë$† ¸£$FIˆ×ï×òc,ŒR†åZ¯‹Â+œõò%nZqíëà­<}¸º©`àØ¶wÖÙ¬(°ÌÓ¹”‰öAÎd ;Úæ½XO%á1Ø~%µõblâìküg C¨ 9:৤½SÂ7 ,ϰÁTôë˕ÎAFc³6¯ÄÞèN¢Ç§¤rW¦ÎOþEkÆÌ„çJÝãä< ÛñÍ+²û¦Ð‹É‚HÇgM÷Âû)Uà.Óݱ{ôðÆÐÖ0‘*Ä)¸Ÿkt#Ìâo¾á­~éÉ ¶-þË®Hñîg°òÀ5€φ‹8‰© öÈñí"µ´lÂ2ª‹€Zb~ÊÃòàJ /HHûLÜB¾É0R)Èvâ~006½ll³Í‰ Š “%ô¡‚~LÐ@ÜlhW¤"V&ú1Gð`ð:Ȫ:êZ“Œ®B©ï|ɾ†N¤Îâ«PT®ØW˜oÀc¤R‰ëÔ½zï¼Ïm¦&iàÆ¼M¬èÿ­î§Ïþo‡BR¶:‚ Ól4x"ÄMã§ véP­T®íŠ)‹»ÂõðÞb^¹Mb§¬>¼‘üâ¤o­ò•ÎJÆ¡ôÁFÈV(‚•ë¹…h[öEéÆz(½ïk±´ñrço­ âÄÉÖˆðŽeqN˜Â(æf)Âý¯~n dn¼ŽŒ—"QÊøæLÐ:Ì o’ªƒ.Úˆ–Ã`Uêg¯T ©(!%DìÄàÇŽà.¬ ä°û Çl…éÔ o•±Ôçâ¦Õ…õ.¸ktè‡ç¥æ_OÕ,H®²kboK!fNsë6d²V˜«i2®ÐÚª^d€#nS§Bá ô$'}*®kL ßbbôˆI&hˆ!“i'&DGõ‹´‹¤dGFfÇ‘G°ÈhºªTø,”œŒ$A)O9ŒÛ"°.qMÞlR×GB­Ì¦šBÂLÇ,ó¶±J~»‡‰Î—ͨüšO²°\P³(‘¾"Š>NØÕÏöV@?*do°QˆI ¸ &Š]Dí„–¡çBã4(¾§ÈÔˆ2í*~”‘è$é±\´%Æþ LËŠ±Ç,Âg-gÌT².=0i£f'¨.u웊|}ö•mÑ?‚x#.ŠÁt6ŒTÐÎÌr/t^Ù.†! ˆnãòb¨™1ÎèMÿJp…¬ôˆ<"éÈê«#m…T¶&~kunPV‚˜fÃ>I¨¡Ò?1”šõ¤W)L•²B’PÊîØ&-Ró0Äæ¨²oÄ'ñ²ò§Š÷ô¶(*ª‰±J¢¤ðf ²D«g rü¡1s@£y#D¨ˆHçã(Ó/æGh7$RlòÛ…l9Úr±‚Y ‹tusçD;V¬oME-¨Þï’¹b!DpzælÆi›)©×=Ò–ÿ¨÷  ßu/ÚLÓWWËU ®¸@ÎmQâH¯b¾äsèUx²ƒÂz)ÌkL\ I3D¨ƒ)ŠþŽÀ¾Áÿs3‘«%,r¤ "†fN“3 ó»døxPЧxBg¯½ÂÎg„iHÙn…(íŸ,B­õöfÃT¦Ù7RSŠ“j’¢ŒÏ/¹Pop˜”²!Ó^'ñ×>³(ϴĥВӎ[af!ÆÜJEWgç#ñE/¬‰g F›²r°õ6c³Êœ†Bä§§>yF…bD³è;†;5æté†k¨Pª’†÷U^!tÃÒ7$8_ʵRI1*mNè*Ø‹)sU׆»7‡yI”¥+JU)ÖŠ«:|–ú“‘(©‘Â"õÄémCn!mÕgmq`¸â(}pêæÒúÛ+Äsãrú±}s¯n¢  ·N@5W#‚ÅHR“4Mzƒt ‹6Rúîšb®2ðÜ•©66u’¼Œ,N‘³ÕF+G%KG4î=¦;mem(îʸäèoªlæ3è!a©|L E÷E=þ•è·8“p±Øé3›oà¿SÔ¸ÉOYêV1Lˆ'§GTÅ T÷PŠ˜o¨6p!å€Å¸ÖèWdË~;èP:ì¡PÓ‘[Vc ¬ùLÒ7ªD0*én (ÔWP„èt  ƒÀ l,ü*”B Ö&!%(ÇåsµEɨV%ŸR‘£o"䂨¶E.¥a:ÿ µì Òe‘?œhPÛοFâëz䬖®¸íqEö§¦ôp7VNŽ7wâ©~Ì`upŒˆqÈÜ&gv)vÿ=²ÖöK">EdmÍ…êÌ$_ÒJ#äÙaoÚm’QɆKc…)„Ãñ?öoJÿçé")<à'µ†ÅGV—$W|Œ¾ƒeqcÓI9÷&F4K‡5`UO#FÄí"¿Œ”³µÏ¢hõº9 ²BšiR2Y8î*}n±¾oHŸ<Š˜©‹aC’©dªÖF–É4HDjX±–‰îúÊlðsÉٲê™Q­^"öÁÉ¢ËA*Ë>õxo"¶ËHmÄäSPš™Þè+vÁë~™+eÉàv²Ž/Q`™ˆ_hÄÞËb!_ö`Ó’Ín&dúë_n9Ùw0`8Âi6tJÉêÆ% kt.³ØC™dš]~yô#ÓÈBÌ#Ïž³ Q'ú^÷µöz;„û4àLÊó°ÓgŒˆ¼pÆõ¦"G·NÑzª§Æ:Ú²Ü8Äu­ý¤9hÌgsfµdõ,kØÚêóXÓ” ¡L ÷W †cÚ=¸¯g»)΀˜yÕž$Šÿº!'+q÷Tâ—lMŒl(kÇ?&ÆË¹JCN—põ×(õ¹:Óà‰»&?µtÝlEf` d5Phžùeô½¡óJ2éI/ÝRùÒ¦w®ÑœŸdý‹UJ÷ª?B¤æÃf¡EJ«JYÖ;÷,òI‘vÆG­Ôuøæ¡Ïlܪ)›·Üsî Ä6ÔÄ5•DÜωVE'Ò°äR—9BVö6ä²?„öXÄÖ—és'j)a´DˆÖX•¡­¾‘ ¥ËdnYßУ؟*驿Ĉ>T]®7 ºç¤¨È‘E— 7M…mngŠc ÂËýË$‰Šˆû÷N¯(?¬eÃ9[GîÆdÛ’צ£q§â¾Ô+ (Ô!çÛ0ÑO¡™‚i'Õ¯®Uyxb/-x´.¶O¾B‘/¹²¨}Ç_%Î;ôïu{¼5{Éf¼a‘Xÿ•:ŠÏHÉ=Ë'ôàZS«yf(QOÈ N[>8ú.\=2qã´6ñ ÇÕæõM'±»ÙTŠ‘ºo.ȳmȇ¡±¿BhžÛmBÜGªÚš˜×¥¦ÉZÉuަÙÜ‘Bè(µ5Ôÿ [„Û’¬Ø=? šÀ˜£@\jm,‰K÷ ö}ðYŸ¶ îIŒð}8ƒˆkׄ©¥Û!¤–ׇ‹hÅbz¡×ø–!xêµÐ|‘){J~`,¯‰ÿ}K¥Ýu9!ü‹hDÕb¨¡ÉšñZ¿ÀG1¨œt)yP’jõ´®ôem[gçJ6ïwZÿ¹ô×]¶¯w+´14U0‹1?CxßÉÛ{=]C»:Ž5†Ä–ÂÇȘª¨mj‡(»Suþ[ñykbÜܳ.|2Uñ"Šm o[J=ó4•@7Q£|“ÀŒB­µ°"ý" ö"H·iü!-àŸx´íƒc±ñZ½%9ýå½oE;›f]᯽}lˆ¡Z˜"F:ðjVpÑ•Oâus•0M¹ÌUуä}µÕ˜!p6«Rô…ˆù U“CÀ^vN›å‰ƒê(Ò>>«•xO¡i t²êEqýË…ôÌTh§×<¸Üš˜ïÝÒoU]l{>žä"qØ(œ³C"Ú9R$#4Õ¨­Q¼óqu`Á¸éÐ9ÖÎ&F˜¸£ž¨Q¶oXò"=-%îóAU¬ñ‚BÑ#2Ûj‹ƒª"7ë*]¡Nï.àbfÛt éͻܸêþ&rÀwHH휗—/à<º¼!²såÂÞf,ulïpÚ ‹pú•(8 ¹ÐÂ?àØ4 BßPÐ<‰D¡à¤V0‚?ßÑÐ4~+>ä‘ð4‰ù)JâP×ÔV—Dâ2—äšE"šb±(ÜJãr(<+CÏâ1Yµ‡>‚It8¬nc:ˆÉ¢µG­~L±>,– <¶fªPið˜”Ú£ªLg±\Ù)Œ€$T9ŒÚÚ¬Çf3¶wuÐo/ÉtnM‘b¤1Ù†¤CäYŒÌFEw¥ÌiPIÌvÍ6„[¢0x”Æ7d|gat.Þm&Í€&Ó½;ú.¿BòQÝtÒéƒÑc¸ÈLÚcÅàMe;p-vIË€¨tx5Z Üó=üï=—^ø9ì«ûEÚ‡Ðwý»ßž#AèÝ ’š(;Èî NH¤Ò¤ h"Ð}(/z®‚&.²Þ½#/£ ɳä?` Dû¹­b&Š»ÇëØˆ¦* ¤ªØ½Á &‡ ï4»³È“dŠ¿è3Ç9éJ6á€Kê žòr\È´4†ç6#¶¸€1T?+Æ®®!ê£B‚(l lë.2+$Z…Ä~Õ€€DîƒÎˆ2DœDÀ#r·²’s43~‘*)ÿ5Núà”b¡¨(=ÌÒ<*…Ñj fˆ¥Ï3 8´Èì‘H".´@µ¡*u6ÇjbxÎJgê¡T€,šFl½¹rèÉU³hÏQeh¾Xì³Ã2×0†¡¶V¥sÃÉM#J[ƒøÕoêë75–½Æh=ĦӸª ñr° H|—Òc(Äwõw¥Ð;^…çíw/€p•jXGüEO¡¨ÚÌ·p;·+IÚ&Í0ÌC‚Ôõ1ü÷Æ%•hè”.ˆ¶VCHcT–52ë2cs(ªÍKãî²cŸwdmdM¨#­(P)J†Ãž×Àcsƒ?- ÎÜ–Çë"÷JÈꆪg9=—,ç5ÄnŒÂ Œ~D>kTn2XR ~¯ttVŒºÌU@¬Év=vî¶eìÆ+F)$EtØrÍ0ænmlÛÆå&‹"6¸‘pÀÞõ!±ƒDà¸;>*ïcOEK•sÙl½òM‘/s¶fgR0¯­¿fu o€éVw”æÔ0z¥9®Ék¥ N€ƒz›æÖ½{ žŸ³o柚ŧ5÷ÙÂÛç)‚øØxC<ëHÏÆƒ]î³ÊÆNé81Ó³'$í~½Ó GÊ£~!æÈƒ–b$U Ú‹/ä¤úÒ$Ü“’œjˆ¨ô²7–< ñ+JÍ«¾vNAÚiÖ:Å œ¶HLJâÅx°`Å>×8ˆ S'a H¡(xI’ ûcLÀ¼uŒ? ˆür,<ÌCw†³XiVo…•›wØANò/",å“C(†–1­ ´–"mÍ»p!k®3«g>Ù•só4æ)y”$»IKŒ3 Õ¹ò†üK$Zéåg€„?RËx@~³“ÞòÖËÚ.EP’$”²fžªl$‡‘B’“úÛUF܃ŧî›è&NNÚ"%Ì!޹˜¸Êf„Ím±~h«r)_Áwg’²G¾´N¢ÈÛ9beˆŠ°)JK‹4U#Žö«ÉìûQÜ›‹ú„Îfþbl H¦Ì)Éó]ˆÁxû(ˆ5*©1M&æ·㜎lä“9W]Mû,%|zÐrà<¶wTºwÃC·EÝ Iœê›r¨¢:;¥È”ø27þ×z¯ž1Ùñ'éÊwH1ÖzCò@:dGå|5.ð<õ‡æ,VË^¬,…5Vâ1µDè‚JÚ¼?S›½p$QÉYP"Lë± LRã<˜Ýësï…¬HwÏ ’ó'r¨ªR±úM–C ÙJÙB{‡q¯vw°ˆX>á/q¸×JÀÂÚ–€ÎTL\^®õ&g9óß/¢‚Ñv6LG¼BË2Näm§ÝuKªü#êþgZr1IlK!ֈ캋\pœ¬^ŠË $EI5lfňÀépÓZ|6@2ý[ðö^³Ÿ´NT¶ŸHíÜo‰ÕI“ Bw.ÇÑ”R“—6–XƒlˆVÀ¥ÉÀc® ÙRÕ|Û”:tòåšà,Å —0çúÔÒKM&/,ÙHTÕrS{†SÎ?‹«gZ\É‹ÔÁN(ð¨éö>hʤ“ßUJл˜¿,ÚZ•”ªtNš{•Ü]}\ź<,Y4‘2>¡DÜ·œiƒ×z{¹Êœì0õu¯±z>Ø»KÑø"ljóâèê‹RP––@&”?06›FÞõRök ìâ’(8FKIƒli ­JšÜ6uFXuK%˜½•G–؉£ü\‰¹d g´‰×pì!½ºFGçË|ù†xG=76hõ/ϱ2g® œÎÏŒÀJz—´µ ¢²Õ&Ä”p$H1RàDM2¹šÅåsÞöP‹y+,™ºñó¡)H”ƒÆz¾âÍ·’hÒtw[\ZWfõ¸P¿=”´úNb!;TPÆèI¨½¸P$Zò‰ÈÊ‘ÅY=ÛÓðý¯ó;tš÷ÐÄ+[­Ò’7mK”Y‚ Ç! ¯ªcd°ÍH‹T“;¹Þð4lpnãI%£e«Æª† Øe_Gž†½×Ã9seS·W§)\TE‰9¯ƒ>G’'†°ì`ßí™Ï׸#çÅ‹uý\®ˆî@öµ“Jq˜BÉé8¡ÀÂhušj;ì9¡‘¶¹>?’¼äïlØ*‡hU‡s¤ ÏÝ ݲÊ>ß±:¨²œàÉüáb¡I?UŠÁ üŒí¥ý±à\jý<Í£q¦(›[©±T]æËÜÎìØÈï?âÙ$¢%Z,%‹+™ÏÖ¢IŸTêàߥ–å|·,“¿J:»‡ä Å5¢XÒgcßÍ'œXå“é·)I‰@޹U%ŸáÃ,“ø(yó¼AÛè’·+©I"Y¾Û JI.[´ˆª²²‘Ø-ë.Ì+yؼñÀ¹s4P~™ùØ3†i±² 56³B¤ñšø<몑b· ¬Ê“®cM¾›·¸ºóÉ9;Mˆ«jˆ)¦¡8ûÖ‡òj0Òj+ ¼ak?¹¹¬9÷ꘗ1:Ÿ#¤#—Bˆ¡Ñ\ º%%k8 ÚÀ—"5‰È³$ñÑø±P†Û/Ÿ9³ˆ’è“_ŒjâzO')ð—y¦œ$¾Á%¸‰“©=ì>Z†•‹®+¨&2“ëæÃãcÊ ;8?ë.:¢¥Âºd;§´è¥·A‡#Aª+;>¤ÑÞ{.ĸ½Ø±Z…­G¬„LD”F¥¢8E†l ŸL/µ Ô®<62±’I½Æi®æ¹ ˆ9å°ô‚ÂS˜ˆ}¸…™Ê1 yàÉxÁã•«Ãy¦¬N¡hÛµ¤ª»PÓÇp—iåÂs¨#œ€ÊâÄ=ÑX6Qý('L\EÔ€/ÁÙb”«YÉ)Ó(‚ª‘SY¸ß?ÁÇ¢Zy‰‹*¬™4᜺Ü^rAº*X¼j$³w¼]+ 4œCÆÇ$„;+ÁsªDW6ø}Ž ¥Gè„ÉâæÚ2ûM¼0ÃÍhÃ8Š *?lŒ1t |pÅ41©°ÓȬI¨½ ,2"}} Îs0A„=úa¼¬63QA¿d+Üf‹4Ç’ö\œ¬»â¿rWêR¶ì¸è!%*iÃŽ°yÏ’B›pÌCX‰ ©˜ÌFÁ̱=â…$ÿ£ªe«U‰!K²&­œ¨²‚4Êzr°©k¸DõF‘ÎB„ªÉBƒn'%Ã@ÊÄd-8êð6Š„¨²Ät5Š´”̯bêù,˜t\±¼ëÍ±åŸ ÚY»œEŠž˜‘£±${HBˆÛ¼89ø}¦[yE“[»Cl»œ{+‰¬¤ˆ}—zèÜöÐ ô/X¥™8›$ðàž[ôA‘[N«=5Ú¨™Â?#J!"\qw¸Öˆ:ýa¦Ë£‘«°ã„HR®<Ò }S'¦Âð § ðy?„·1ºuF°ÜLx‘ÀªwÍ„9?™AÃYì¥ìUSPÓ™9ë0ë(Dµ‡òÍÓzÈ–Cb¬>²CÈ}ÄS¥%»íKŒ%@+’‹?šœë Œ눦ó¯è»Å³¨S™™KרÑ>Ô R´TšÑF2fÍ-TÁDÈñÛÒŽŒôuÄlB6C+«"B¤O¼’Ik¦ü,°5žV0àœÙíÕ28™JUté‡ØÆ»làW­JU'ª ÊyE¹Ó‘4p’yÍ Kö0±[PÌì¨ ’1€=œ9ìÊk 9 “1¬7¹ÄÐ<™Ä ¹Œæ0áã5 ˆY#l ·J‹Ï%BÆL`›èۆ壱›²8`dR˜œœ$rÁ>˜DŽ¡ ©§Tjô9š»Û@µ¸ÅZmTS²VGä¨ÖaƒIéʯ;cSqÏÎ3Ï@ç#;«Z^9D%VòAÈð±ZÔ(JLM4Ö%°2È÷°j%ŸÄù™wÁt…ªbaÌK©Cy/\€ØûB±ÝR+2¸#‘زeÒÅÚŒ)½³„¸M…¹’¹“õ‡ÁÆ8;ˆÛRæ!r±¸ýŠ6¬ˆÊË8Û¸}$)e·ã2ŒSø…´–u¡ÚûøStU(ëѽÅG1ÉÝ^b½ÁqÍâà×B£­ 5}‚“ZHšÕé®A,¿ùÈ-O¶\WÚ²ÚÊP¡ž]€Ü›‘¯€Å@:—˹‘”DÜ*—¸išˆ=ͪГRSsˆ}WEœàýêKbÑ´x…„¼CÔ§«˜¹RÄ u>!\LPõôILŠ:q\ÚÕú$x“HÙ(³†𣵠ÄÁ68ÆM²ž»ÿ=³©²2ÜOË„Eýv•ËÍ|—yúìö ]Cc°Ž؇Ä”Áƒ@~0¢k„ Üü¶‹‹Ržášö-¬ Wu~ÓRÒ‚ +­t 0íԺ®M«ùˆZbÜ ƒæ5βÄRˆÁ„N$©‰6 Sróåƒk¹áÕÑ_ºª»œ÷È0ò©U7×dT1Ä]Ãt™ÝmYøC1ŽÜC³åÒZ Œg±O,ãMª» ÇŽÔCO¤P« ¹®ã,ZôòSs‹5 [=†C .‚œšg;»Eݺûë® |=Aª’§ `‘«W†1”E(Ù–®DàÏ •4¥â½6;ä<òœ‡Ì¯"»…¶4¢®ôܾ0»ß=w3 †¦°µü!D|qFF‰ßQêÒV„ñˆ™ëbn\\™–Yë4` Úñȹa¤-§\BR¨CO¨ÂàlUTF²9Ûø†¯¹1Y‹NH—‘U7@Šf`ÙC£ñe™<~ˆ:½‹1¦ˆ“À ªaUaá Uª¬ÀLp~Qâ¸8BwœÖÓ‘¯ÄIJÎ@Ä {ãZ®•Ƀg&<òœkÎÅW†ZÄ‹è‡Ì·Ùë·õØk¦ÇNV¶½{†¢ê\šÑm©¿.ý­ª”i{g¶œvmá¸K„ak[èueTbp&± 4`r9ç"”3hƒ—zr°÷ ÖkÒ—Ýöé?Vc8,š V,åªÛ †V"_ûÛ[Þ´ìŠ"ID/¨ÃîÓ’›cWT 6¯ÔdŒ­›ô?zÄnúôL¥è_pÏ!Êå{Pò@{ðƒÏ²£Yõþ»Îm_K%OT×P^1בϢ=ŠðC ³ËPÆÏ­Í»©~’OfhªÄ-kæúRÑ¥™L–Z½¢¾§.tòL’ˆZñW§”€O-­&éE˜r_C`Ap>‡Ê‹Mœ«ç9:± °4jjF-Fb‡ö¶˜MõxÍY‡ÖàQœL4Kfa®L:…ÆE¶Óî%ÃéÐÝøbq4—@¦5ùo‡#†’΂ªÎµ÷–9¸oÍ8þ´ñL&ë(õîóˆ^e•¶²=º#‰Œî‹#ëlÒ"*u&³yW\/æÌ‡Ë˜‰¤WWÛ¾-ytüìç°vÔeXfÁš Õ¸|;Óä–äêS.úŠ]Ô¸¹ÆþÁEÖ`é!ü(+Rf+¤Lds—{œ “tïlνɤSí¯÷C“ï¶¶O.-~C˜aà€@/è$ „a@8cêD_ñ0$UùŒ#@(äMÿ#Ò z= CpgĶ"ŽŸ³9TÍúûœH`ÓhL(?›A¢ I "mAI#R€c!œ>Á59´Æ=}B€°Š4Îc?ÉbsjU–I'LeSÄbµŒA®V˜åb=C¢Á$q©µî›sÀYePi4N•F#Ò¨ôÚñ|™ËàÏ\¥‚cŒX*1éŒÆ™…Ùa€zèŒLgK(+]X„YoÔùL31m~J¥U×ìÆ_X¡ìi[@bÁ£‰Öªðè4¾û•]¢‘]TÎý°K_Žä"£j†U¢qŽ{ÿu §GpרœyœŽ{µ”½=—ҨήrF–8äìëÔ¨jŠló·HþŽ0hH¿4Òä»J^|Ãòµ@ À­ˆºT¨±é#„’€ ¢· SÊCQÈÒÔ­î8‰ 0í+PB ¨¨H«VO`ªŽCÕB5<±DƒJ âÅ£ŠŠ¦¾Gñï]¸ûÊÁ!“‹Ôà[½¥þ]DpŒóHV&³q—£í𢢌œºŠæg¶øfÔOÚ’–‘ê6*õJë,ŒÄ)×Ðîôˆ/çú0G¥¨³¥) Z‹Ú[Êó@¬ãA€škЏÕí3hiO1¼~È~Ó×+ã"ð%Š4ò^ìË££ëɼ"”F+p•ó€2¢›Ï*xC Û12f×$É%êy£•¢¢¢ÈQý¦Cæ`I°D`uSå»7BE§Å!~0*¢˜[N"¹r‘TUT''¥>¯°°Mž(ý¢gr#Lh,Œ%’¥&É–«*&HÙҡL¦þFŽÐ °KQ ØÐš1wH™²bc/Êš»îÔ/™Ž’Θ8”Ä…Y*Š?ŽÑ¤lˆ¦Ë#‹_Š!J‘Õ*šÊ—–J›B0;H±~N‹0I•w¯óíŸyAGˆŒŒò¨’<8™jô!"hΠÅ]mܵ`‡#æb±¶Ç_,œ´JÅ?­ ÄUŒ¢!Q:â\v»5"´¨5·YèBgQ~q@]™Ž³ìúósÔ%M²bW”Ãï\\#=wRyÓ˜:‡ñ1+ Ý0“‡t×q­Ykt+¼{‹Ö,rK #H X,}ÚÙˆ—&¹a­vÌßœYóûgÕ&w/Þ}iî2›QX&š.6ÏDÏ/ˆ üQë¹äÐÐ ÏséåAg­­‡˜ï¸¿kئg²h ÿ¶Øúyìc‰Ëwwp‘£ ·ð©¹Ôa"õ¦´)tø$4t´Àk„TC¡+x—2–7³¸ë;2 .p·¤ñØ"ð/ä9••÷à?_x²^Y $[kc;uC±D(íJ‚^µ=Çq!¯5!‡¾Oý·gºFµâÁŒ¶t^4@n·¸,ø–Ñ ª¾A8õ”3°<òçK\õdìk»#O´ò›äg|K¯¼ÄB$>M  ïÁÎy>t¤†××ffmÈå­ô8iZÙFfrϨ²Ê(B jú¬À놎lˆ¬Ù ¹ãDËÃ@©!üªAúÆê&ÎæhêZCéd@ lÓ¬ ¥©ì¹Gvl ’•‰`PFn+Ü8ˆÐ¤@ŠìêÁþVâl³Â¦c¥8äåb, $Õiðjí^Éå^X¢l™!ô…¨V8%þŽ Â”ÐG HûðÛplÒiò’®,Î,Zâ´Š%fidò, dö¥å‰ph*4Û‚p쫚D`e À²Æ\·¤Ö`UŒJíÅŠ(fа@möÈtä†L'‰øþ‹ØêäœI@&!«£îŒ°¯ )ˆ“©Z”’õÀ€í÷ (&ÒA ZìÅÜæ$2‰ðÐ׈žC©^Mä„6D²ßé_ªh…:ÑÍo%Æ‚h¼jq¬¼ëlkŒ6†Ð¸iăe Nè.en\áæðïToJëj6Nà.nc¯8#ŠÄp’݌ƭ ŽŒù¥c ˆó©ôCOžäÀ T²@!!c(¬t”‹.º¤”üvidÌ‚[hãÀ%ð @qÕìïâ"L¬àM#qÉ[M‚ÇåJüoèù/î½Çç)ôÉ¥©'x’Â8¥, ^(~ÇÈ ¢JÍ1QÆ.CúØÂ±0‹ˆpÊÆ‘4chZvnÆÜâåqš'邪p2óI^ù-O ìâcÏz šá.D+H^ ' lƒx×Ò\-ìPPôÈf‚Éy#ï f™º¢D0ØÎÆ‹ð2 $IL´$Ї¨æhêÝ ðKÁðÿh¾¬Â°!Ä«)©[0hé*üÈl³H’ËɪvÂmvUðºœï@½ËJcNU 4.M¶Òì.¬ŒV[ð~×L™èúç …®Ëø0¯h•ïg$Fã8Èžúí}‰ó/ p½.ŽãO,È¢f•©b5 $ÿb´¿qô ¯´'ë /ód?¦žk-@w+ÇæTFÎ4öÀ Œî2¼.GFK>;Nx†³Þ«3þÒÃ"®« Ž} ò ŠMàpˆD´Ôp(—3øûëÀidÊÑÔ!éhÌÈÁé· ø7EŠ^ϧç RXç¢<­`HeFÍÃN×JrlN:„³ƒ)$.C Á7”rMlÏ$„´@Ë&f ¨œËäXŽ:mÆ|!Ë>MÔøÐtŸP¤Ï(ë±>n½ùK„òú†Âj‘Zñ3$n03:04Ä$k/~å3ªO‹k<’âØË®´nì°@]ÅÜpï,¨ë*Â޹*ZP¤”dÅKR†bƒp´p,Ï(ÄÿÄän%fæT–´¾¢ãpÉg 7«M9 Û‰Ç%âMêéM‘¡Sf(Âb¦°¡ð¾$òiåK* ’ ²Ït®žASs*ðAþ÷¢~IMÖ…p’Þ‰RÛ)®!ÒÌ,ñß#¡X”DŸbB5Í@CÞx4òþ«ËÕ§¤OÈüíG®¸3Jn/NñÆI„ô¹-Tpœÿ‡`ëÍ› =)î‰Ô>îðÕèHòErf O&LƒçNyk F(W#j—Hì½ǒ €dì ðêM9ÐÐMzk”Î@B°O*vœëJèe ;‘P€önËêõb¬¼Íµ† ÃîõNKm"í_ï–µ¥JZ‹áUîÃoƒëÜ©°wM‚bMãµ5õñVá‹x_¨ôð§ ±VÏ,šL©œñb"+€¶ózvP¶Ûq>$Ï «–'—  ›0f ÑSlpá±Á9ÆÉ4ˆN¡þP¶5LËÜ„C…+A¯ Iõo SN (”Ÿg‡[§YS™hýWMH1r½Ò`0· "’³"+J‡EòÄPB ÓJúþqèãa[…¾l‡‡‡ÝERr[â£K‡Xc¶Í/cˆD¤Ë2bÁ!§ w‹6ñ4,ÂIæW4§ }R5†N“–÷U³Ÿ*iÒÙ:¶µÒïöOéÄ׳NCè¸t¥rtWŒ7~,@ñ3àÓÉú"m×§AŒ!`rEn;PìÊcO)Z×ÑÓgPóváè1#‹ÅQu>Oºtø-)ÒèÕ÷fdÐ# ˆeóÒ"-t¿f\Úr8îµ÷KJb‡çSq¾V.e'súã` ØúûÈNþL•å ú… pëH[çXŠ6fŒJÒBÎtL%S‚øwÂ~Ë-‹–_7—<¾m§OM¡$÷”´Î˜Õ"qdศշÿkã\§èlS†Ù ¶áhüOæ)QuŠÚ ƒw r±Ò¼”ÊÀGJ‹ò1S³zyþ©xaCÔž“{Ž'Xˆ¶‘næÌðš1 P©ÙT~r¸›v$جËË-F¶â²íÞ&J¦¨Pö^ÎôJ³“4,L£¢žvÍr7ŽÌý6®… C(P¦–¼ÕAöÏ‹¦bè§ZOèôš1ÓbtLEÁð„ט­¡ÿF(­,ĸ—#Ë$Û9‰•Y˜÷xD4¡EVÒòNÁ“|ŠÈ‹õÌ5™VÛr¨… g­¶/Õéuq…$$׎•Æò 7§ü!kž&ÌÖ[ø Gs•¤`ƒmåS¹Ðxxä‰ðù3z„ì?‡RâeÙ+†DM(Ö­˜¢³ Lš*Í®ÕÍŽ+X3§u««3)è~°÷@òž;†ur &¬ñ¤´ÙMc;€±–Vl"&ð#'Ž{—ùé€D+0”°rTñlEíD0Ót™]d`~kÈIS0­½“É~ë2rÏÇ72×?s(³¥w„øç™)hÊ/Ë)3w±X(ŸŒYm ´"¹½4ó&uùíhµOô³`J—­‚­) tè,‹údòª¡™«§4À‘šðẔ4…Ýr·Ù]¡ük73{°„âwÞ0 ¶håÝ$þÛq¶í•>ñm›‘}‹pö#`Ün¿rW*…vd½Õš»†ËÓÜáº+/°E¢%§tz @Œn;ˆ:Ð%¶`NÓ`Ï0~õ•ôyZ¶ÈVüÙ%¸¬©“8?"”k|õ .ÍBƒyax•*¨¢„·9Î;Ÿ9j  >ß4-›ï$ÐR¨òl¼¨c¢‰Œ4•«€ÚeZ©$Õ6ø«¨tí³e6€èanwþ×[ìþ¤ÊÑ3®!Ôúí³Î3«½oIµ;[LËgœ@À®ñ%Šæ„¹}¦\ÿs¶Ñf¹$þM˜Ùu;V‚q¾°þCäÊ$&Ðg*7?ÅIQ%†žðí9y·Jʲ·VAô$6ƒ›Âp¢‡ÏOÃ\cI1/ |½H[ £¸åú2Ï;P#pD¹%.4„­Xj¸<¤>ð­ÂV%Gz«wŽv÷7c‰;,7ƒu;²á‹“"œèO“KÒÃï þ˜ÈÚÉ´?³Õˆ«h;€•¥>†«…C0cr2 ÅÅ Õœ;B^è0ùCTM|¦-r÷Ô|—wT/Ï4ý#” µ¯“ÀÔG ²”üåä©uùT´AÓ‹Â)M.ÐEf~Î pÛ8œ•Xr3uìóæãŽ3áͨÓ¢' rcB¶‡I 7u¢pS¦ž€,¥7\oGzÔK +w'ÔQp‹÷ ÓÓ>$Øök©j}¦i±pÄeؼ°Ø>Dò)Pû&ŒtÒógÍØÊ'Â=rK½À ÊäSÌ®.u:,¦Ÿ¨ð·ærê‰ôkï¼7ç¡´íä&3ew®@mx‘Úéõqå¯ÁõwöÆrRœï©Zpõ«$ËÝ·Ô:š.üúWÖ«6¨\-`Žlç2â´¶¹·<(uø —º _\§Hý ¸Nðöí‹-r•ŒôLu›rÌ1;Ž´At=kM˜¸|+QÑ,ª÷™%™rï"ZMï ¶­ñŒ?¤Om‰S‚Í'³$øZã[|½æÚ",К-Ö`…¿ðÀ‚Q®#Ëâ4 „=J³9Å/°B'ÿ{9<»J»œ¬ÿ¢_±©mó¢‡NØÈN€ð±3O-„ö;¦øµŒ å¡ñ„7¥†vÆsø§ß“u¯_¿r¾÷k_Ö ê ƒ>!8Pù‡B€oø” (Eß‘˜ƒî8E#/È“þ “?e@$­ý-Ž>á€Y ¬ #‹€¥¯é¼Ž)#“OÀ3™f}&Qåò9ÌxBM$3¸•Iÿ9ˆTbñ¸äŽ!TŠÀ¡Ïš8!}W UhUM_Oâ‡ÄÒPý]åñ T®å%“Hf49N1ÖŸq (oT›ÏñqIËß( ËHiÀ†QïLÅ1º4RÇr»‚$xxUšüÔÆmÑIüÞ{šbåóy¥ºëjè"óù|þi™Çɤt©Ì¶oË–ÌqZg{uö\ˆ•ꡜKz2‰¥Žëf›â';> ›Ó&ÝÀ¢O–ŸÏ ºä¥²?½~mY…:Œ‚$—¯`#„Ž.©hâ%lù;‰$)˜°Á)[”.­j걿IB®Œ¦éŠÂàOÂt‹¸©k{¥ ¼çCiB¸ˆ!H¢ê®ê.À Iû>§¥‰j(°©‰úë°¨dlÇ€50ˆªØ '’›«¡,6,Ì¿Ë N¼¡MP›®°Xº¿h´W6êÓÇ1 V‚:‹tÚëžÉŒ·¢ìËÚ¢ ÊÂúÍHº)D%Èê<‘®H0)Ÿéúc%­é3h ‘ý8Í‹jÀ‡&+ð~±rã’‰=LlRœÄZ$Võ 3€iœ2©Ñ¨0æXêÝH‡õTì¨õ‹¢N„ô}S(e„=àC7¥¼€“Ï4cɲ‰¢cKÕÔÂŒ£¯±Ãáv€ õT›¼Í ÝtY±=rˆ.¦Åû ‰Ís0×òëÙa€W2PŸà7(‰)md–¤2D®Ð˜š3ˆMÊrš%øIûG¹wÒT LåC)âr±¦ŽjZ¹a×Kz WCû„!Žö(¢Uõ,£W"‰Ñ8&—ÚQ»YªF˜¬Ë¢P˜áǫ›¸z Ÿ¬ØòV˜§:Z‚ð!Wý´”Ql\“gŸölÒºÛƒH£­ÚæÇ'é–[jªàúü_Zïgò ÃN“ˆtQ×zä¦,k hzñè…°ÌÄG绵Úz)8&GCB\>…k $oŽ‘œOÓi}weÒõ„¡½CN¤Ç»—„‹o:­DןV°À'ý¢ß«ûQû¬lV¾½&¢S„×¥#2´­/ËÈ–~¬x¿ ìã=FYÕÙ €wVvDµé–kYwÙl]æ‚]„R·5«5+ñŸö2//ªì„Ôz&…£«áþÞ]Û`#(¸+Ìò^"ªiÄ1‘•BhŸÐ"êí­Gp ‡ãƒ‡Q ¨[!9+`D´¦+–¨àOúÄw —¶¨``ü&…™z3° Ì`|`ªèŽ4X \BzCõM³¶}›9þ"/|/sÖó!‚B¤yÖ‘ÃÆQÉÉrF0tŽ,·êïYÊT1m¤¶,×°rS“! TÎ2⎆¢@ÿl0ˆÛ°FÛ"Êÿ[cö!+.]Z™lYe™ä•EBbáéj2*2û€Š“$Ï@Õ¸]É rr•qwôß  €b.íÐøQ€!/4ð|}K*åŒp<­¢Ãs Yx‰98+·C‰ §NíÌ34B“)wpîí·ÂÂRò$b¦ &o+BhX]0ŒÃí–8ã&)yka4‘å8Ht½oîEdO!ó"+”'í$~¶g¶ÜÙÂЂÑH~½¤Á‘¥}%Þ4!þ\¦ð {ªÑ ±ÖªI{šQe¹k"BŽ 9–­ØÐ§fD‹1mõ2éÈŠÜM1¹.%9 ÀþW ø*ç—?_]¤„pê(µa4SO “¡o¼¢9cuD£&e>ÄCZbÉÉTzÎeQ1%’°HÌô«G=žur¢ à‰oú+&×=JdOpš(€6¡6úËhέ³xlËX‡pg¤YQ4À•º Nêª3ŠÜ%Â_cÜö@£j‰šGökg",«¼5‰ÊÝT§ÁÞ¶Œ*§“Hç§ð$þf·’˜­ˆ“Wó,@§r?•Ü@³lŠ·w Q>]}3Û>”õ´©ƒè¦7«§ˆ_BV²¤2û:¬Y—F/p Bÿ IÔòãFYm†Ú¹kjZÄgÆ7*%Èõ.{·ñ€R͉k¬TM$RÒ{jM1á_²÷1ûP;›^@&·‡v‰Ÿ>m7N±Q-©I0Þ€ ”[¶¾„¾V:kø¥Ý[©wp­-1ƒ—5u…2.hœÓl „Š>Ê„[¶úÞKsûªx{@»·dæ¤-ô½-3 6¼°o«£¶}Ör×Hãf[ñK#ÉAâ<:Ÿ6´1$6þGÈ7¡/¶¶{mfž¤í+µó5Kö=XI\enÊû“¨|t£§õ*¦Þ$ÍÒÔ)ý¡eNC".´NbÅj&<úV†gQêÍ”«SêqDzþr‚ñ/kY·>”³V>G¿I3ñ²M8©×M‰-é‘$Mµ£jTÐteÕÜòêã`B\¦/_Ÿ]*Ÿcï1 „üéÖ¸­f¡K6Ëe2,I Ví&ui’g@¡ŸÜÎÁ±@äèkÖ>éŠV§¼Ø7\ÙGëZÔ™ƒ’Ž]3nƒ~2õHV¤µ|Zc·´>®Æ´©À\+ÝçXäÆùƒ>¤ª†’cé;tàÈì? 𘙙âJÊg¨—à|Åib*N¯Ì9_×}‡ K?æ‡7ÂH&Ï#*Û(̽ú©¥ÓÎh±(„!"Ǻô+œ¡t0, ún/“Õ³Š:‰Ë“!–ÂXÀ¶RQ¸Ü7+¶¨ãt3*úÞ;ó¢šÛ7jë>÷3š*»6œ=¨ƒ~FCu¬YZFrÕ"jò½ù½IfÁA½4#(LݾàÏéŸi¡ ÄW’Ï|o³×•^¨Q‘ÓôÃ?A(q߈€°¨šþ5uWIæ$ª‡µƒSÓ‰¾¨êNÌÀ+ØCD’ùr¿ð˜Œã\‹ºò³A9Ÿ 0ÎÅ(4¼ ø¹ °΂ÛSüöÎÓ³Óp…>ºª˜9Z>í$6ñL´Y Dôž#- Í9Õu6¾ECÓs­³ÚÊèéó½4:œV]XWhç!­x>1â5”+°Õt;€‡¶ô Èm !sŠªy/´áŠ¢ Å6+cÁK¨(‚z,xš(’oúÂë­[K0Æ]R‰1JºPy¶sWõ*žIåÂ-[‰]5Ø*!„õÖlHðHFÚúƒ´íÒ…‰>Ð5iB¾«$6³[‹‘Ô¤ô£Ü¥J蟲 DÜ×”Ûà#ÚûR­Ÿ,(Š:¸¨˜ÌǜԈ®XUÛjɉmª®P„)ËűXHÖDC?„ñ3QÀ.ü߯-®ÀqÐÒ¹®™XHÉ ßAæNt0³Ò03™ÊCå˜8ªËñGû5Îáõ ¶Bþ_PÖž!™Æ•’ÔðÁÂW%¨„xŠÀÚšN)Â@jU› VDÍŒ´lW»}§¥¾ˆF@ªG3ž¿EÃQŒÖ§õ‰'Mmö)?–ÄÖÂsð¹Z—K0‰P-W¬ê÷–’êÓl–ÊÏWÄŽª²œ"&Í¥ G‚ç½3µ65 ·ÀßLmÀ[X¦H|áë1+ÔbQê<Ó’O"ðŽY¼ýÃ2hº „Iå–ŸJ=âÑ–Ý/»‹"!tÕs¤».}YÒƒÙF!9T 8›¹H³)èÄJ2Õ'õ¼*yPžÓ-P³Eà ¬Ól¥J¨} ôY«¹\‰ˆ¹øêÎF./ãýBRå!ÚÔ­ú—Å£ £™£ó¯°±¿¢Z ½5–TÄãU*G fB5Ã÷+´é1ùæŸ:RÚs7u+Ò× çMjéÃCL;3ÑV‚*Å aý‘¥+ªyMÁKát· ̼[FÀ‚B½CIÅÿ: G…-XbÆ\Òˆ#ŒËRLxÉeåÏewÄY7žSÝô?hTl\cº#fÚYÄ"ædêÄY:X£ÃÓˆ#¯Ôýx´!вq?¿<ÚF%b•Pô&Úž¡‹£ŽI(\q ®AÓZD8\§œ¢!>jßÝjËêíWã ΫõEÃÓ7}ö¡Ú=ÔÓýéŠÀMãÚ„N\É^'*cNHÁ%nAÊ;|ÙQ˯Ãd(r¯ýÉ3 BÁ¹Ù¥64*’ýÀÓñ•v—QŽBpÌš[\À cÑw¤¬W6¤‘2Ó¯¡‰Ue#X@‡qÊ]x|Ìži*¶ ¼´7 ¾k‹¹ «¹l(óg¢¦˜Ö2ÜIÛ)ˉ¼äÜ)gKÁ¢.µ¢£©­¬vb‰åQ¦ «'&Ô|#ÚÚé0ÙÊ.zëªz»H‡%(žÖU‡Øœ¨œ‚×PŠêE:YAóGaîT•é‚".GcEç,¥–¶å }gF(ÊIY3VìS2_ š5eë ØÒª@¶*&ÏJ']ŒÈûô sb¡Ú‡¦I:~‡¢%Y4žîº—>«;Æ+B?‹|ªB[ |‹(‚ˆ1.]^u5~qæ•æ½ÞæßD5x›Ö@¨š&“ûCi]ÔQúI7KŒÐnˆ×ÅG¼[i°+îÄý=·ëÀ¨ÌZ pI§TTÜ9æZ½ý¶‰p›kc€ ïÜ =ü¶`ÄJéÕѹð(®nßV極£ô&Zj"LØq/¯ãý‰z‰çÒË7º/¯2æ4âê~r¡pÏ?izÔ¨4ëD‡›òBÊQ6§ —¿·.{e+©¡ÖKeÐqEÔ5ëmqˬ´Šü —zþ2N´°Ê+HÖ¤,¤jÖeN14pc2ÃÇ¥• &½5BÉôâIÐXJoAëê› ã[yb7VyI3_X›WÊ×LB†-w^Va')‹èÚW ®å ÔèÙîF²[0Ýù+Óá7V¸•ví¤öÛÍœÙ<òìЇ^€|sÛÆixˆ\ [â }Ì›r3ÊìÜÊ©ï»#âFjý±´ïGnf‰¸¹=ŒGµX“!ùî›ßWvßÛT6j ^ø*Õ¼½‚V×)¼a/¶WFˆöÈlt‹G]e“j°´Kpmftüc=û^ÜØ‘«9Ó‹Wºw†Wt è¤^¤ áKW}0 ï0Ð̘®á¹îR‚!]Ön•U^v3ÓÍ´y²Ó¼9[GVøÉfK„·5T$¯,±(!Û G¹Hm"»û)œÙg‘è½, ¾‘‰2Zí»¨:œñä±C–”y-ïÔJJII¨šd¥B?S¥qwÖ…eÐé¿÷ôtÛ/'pŒØüÐႳ¦ŽÏ/(YÒi,Ð wb-±¬Ç¹ßêˆeÀð«°j¶Š°¹_z]LyšßǽuðÖöˆÞIôÛDP76“&•¾Ò‡ÊXÇÍy.·{ \$úˆ`y~îåM²ŒÖwÆ2ð—îT`ÿl%'PÓŒäƒùÉæ®Øc~…x“ô«¯Û¬Djÿˆþþ‚? ÀXD$ |C@pø„ýŠE@Qp$d~ÇcÑ$l}Éa`3ò‘Kc‘ÙâCxÃçwØükp½MVêýŸé®¦~ÑÙù¦ªÚ!n4è¥îäŶîq¢äÀkT¤¶‹bô¸`šÄ}z¦VÜöÕÔ¡ua"ªMK-Ó‡}Ýù"!Õ VÚ‹·üô‚K>H½ÉLaþö ÞâÓ>$éËU¡oéù}+Ï‚ÒÈÇ혅Í*Ÿ…’®ª´“’”ÌÞI¹wŠAõ‘—à…ÀQ²$FœAF}Ñ‚Ç/Ía¬´`””úõrqUD»DR~ˆÑhgäþ%Àc¦¦àÄ]^°yÄ䬤N<37Œ…Áv# Z‘H,4õvܧšÁË|OD”Cøm ¹øIq$™µÄÎo!£ÛJåÔ²ÁhÈZ–ä^äÕ¤3˜²Ù‹Ã€zä!³’RjZ ç ‘®R’¢z“¼d¦ž•`T„y.ä™À„`ãËT£“¤8‡§I@,A$®T¨äW,ZÒP‘ùƤ^Á¤Aj\ÅN[ˆÖúÜMä–>9hZú=p)¯=õ)á[vh€à ·\¼ ²$å”â@HŠ¿Ž±Ò‚ìæ¨ q"i ˆ€€€6àOø$ „?¡PWì6 Da@V"|Æ@±·Ôt È@28{þþ’Åe@ <žU!ʤ`¼^:ú_°dõí?‹Ìá¯Ø-g$‚>éSš6#˜L ²º¤Î‡ÌåPZx¨¡Éæð4Þ† ´F_49Ì^¹#°Â­‘¹œ^OV‡Ì¤whTÍù•NdðY…ýù‚…RŸrù Ö#-…Wð·úª/0™ÎßxÖ#*ÃI옩§$iË4Ϊ ó"ÎBX¹+SÖª¤nò:Í&<ÜÉŸŽ‹û«ñÊå$i;¶=ˆ#lûËà¤Ñ±J\€†ÄÈ’¯ÃI„Hã€P”›Ïqêþ¦$lÓ[7ð’á2¼“(0ª&;jÿ)&tãÄ¥&mÜÇ €”SÁ(«¾Š·'ú&¸Ö‘K°õ=ÊÓT‘Å/Aþꫬ2`â¸Q„”’ºU’Èý?nÃÞ‚K’˜<[ÏR €‡.€pÔ !h#‹:C“2`Í',S‡GÌÊëå Ì‡íºøÊ–;­Y°Òj>ñ¤2),Iv^Ç H…4ÈÞ¨´,…ZÒ ÄòȪ”u /ªì²œ£k¼=Œ¥¶f>Z¨Rr‰¤÷´ÄÅ0ÓÝø(pÿNg.Ýd¡ÜH-'oí‚`d“¿g¼gˆàr•žÎ²!¨Í³vj¥(tâa FìÓ–þê,⩨u#|‚¬I|~b-{|;㨰‰Mçzž6êÞ øÖ,ƒ|¡×`&ßY2~ÌJï ŠÙ[èÇÌ[…Û‡rõ<£¤é¿IÇô|Ç[gýõÎÀȚɴÑH§.Ãg°²#`VVÕ!³¦(­9óCãåÀ {Óçë œ¦ µ®ÇXÚJ²_Qú™¬™ßÕÛñ´ÅRJ\àx©m~†ÒGÚÈ›#¸½»q°­]{]B÷JYP’R¸ý+ääµ66dÊ\úæIN¥¨©Ç–œ{wl2«u¤Aœ³éYJ}#ÜÉSf ø–Bo“°ÿOkÔ¥"”\¯±J8ev?çNòQÑí]¸€3ê’ŸYD[„!ð.ªëT°ü€ÃøÄÓ ø ºœ-Cf*+eD†—#Ú7ÑHŒ‘rÔßÊ:Â!í)™’vá|i%jp›¿ã°öš43YÀ¥h¬á•Pü\îGbÛˆŒl#ªµ¯9(žá³Í‡¬Ap%d¬Ñ‰9Cu$N5T $O‡êùE¯4h ü=’‰¹¨Âb:DÚS0Å‘7¢jáZì1¤D›µ5<Tä›+§<Œ¿åzûZl:a§V¥gLßÞÓTÊPí”4öAK2 TH馸7‘׌R/Q¦ÔJ‹@ -GѰK ‰Àš‰ .qÁ1úY 3y"/<ÂòV£Ô݇Å*¹ùP˜àÿ|‰ÝñM²¢æPÃ=Î-b>ŠVë;ž3éëP“²ö×E *Žißfꤺl„eôºö©SƒþdTa£vlÕâo@ÿól݈ÙÒsKîlƧe)‡IJ{ô[ÊÊ¡‡ÚšpF$!6§mEåŒB£ÄUÔÙI@?Y œ3D~´Ù¼XÚø° â"Ï5LË)óA[²uKjb{N55V$Åq³>R'!±¸—=‰ÍoÇY¶9¦Œ°1Šà>í>Ë2o?À²„̵d(Æë•g½~s5S Pö)̦=Ϥh?“Ù7\˜]7q­±óJò;^eúÐ1Ë…·Á)fh y'œ(j[æe¨ÈQš¹ÇU9[mËž5Ój´È¼Óä”ÎÖQê¥y Äöq(NuTRlìeêï»ãîÍ=Ú5¥K}Ëe ó}+’ÎU""ì1“ž³É¶Â›‹SÝË 6æ#Iù‚®¤®¼Œ²tkTd kêgÕ |"=0Ð:‚¢6ŸôèKq¿ËÁòûuC,µÚ*Ñi…D9ñ$;ˆ‚NºDí†u PâÒø—Œ_FVsRobz9E¹´ ]ÓT‘Ý—YÝ<{¥D…Ò‘Ý)|²F]³#î$ÈÝe»rµGÔý&WL’Gh¶©äcÕ=¡­ovÊ}û«{uûo`›F™K÷ÇN%°¶‹ÿé,Aqtk>‡³åÔâü« _ÁùÓ‰Û©1\Ó5>^FȺø’Wž}>Þêà šëËSÀ¿Ò¿8‡´iÕ n‚¡Yèe©¬,nc°:Mº6q„U…+gÝ7Ÿtïxó°¦´£mâºg:Q€€,2ê‹úVbóU­mw’GåEÚ´þ|õ@8íO€)Y¥Dõ.<* Œ ê˜Ò¢ÍbÏåðJÈ ©Ç .Ì‚S† ?bȈ$@˜KŒ°ËŠ–‰2-º³jâgz݈0ñ$Ä¥ j‰âȃ‰nniFôŒˆCÍ(Y¯Ò1Åðˆ%W¢J3F ±lð‚FŽ×îí‡>ƒ…LhÅÖ\&‹P@x*.u#lnN´ïòüèDаù'@ÐHpINöƒä¯l6ʪ:­…”ŽM*M"–íâä0š¡¬I `¶çZµ"RÊŠö´ ª’+b§+’!®²³Ç@jhü>Hö,Ž\§š+ð´8¬Zï JÄRî ž¤dÊžOô±Œ´iMJð]še‰Öp1 ¾ þ€ bñÙª®ç1œ`H—g68":¬eЧï&ý.†^=D¬¹LÔœ)¡±êMÌœÐø©ðçG&5£†Å>Èqdó.&ËO$Ë"ñEebTò=Oe&”È&°ôË Êêìµ°~[Én¨2ÊÅÈtïýå^nÈCJÙç´½¢W ŽŠÁœdà ©1½ /5FœÊéL@»®<eð슘ò‰õU!óEDÔÎÌ!«jÍòf÷â!Q(Oãh^`èbÔ¨5Ï=j,úB”§ŒßFŸr=ѪˆòÌq*êþÕJ…#°Ú(éÈi*?m¶Ñà |«|tŒ‹ðÔ‘”×À h"ʬ8ÇA!fš„IÂç`eƒŠ‰hö` îÇγJO)„½¬yÏz$#ƒ‹´ðà½.†eÎϲ”=ÈÑ0Áó$ål„gp>Ïåöþéì)@7jÊ£1¾ÚAöˆ0p#°$_§ ¯êµ HVcŠ˜«XyLp¨ˆ,æ#§´þà=Æ›©„GPDß 3N4 -(JOVMÂJ|†Å24n…â¥Ò¶R>ßRï.ÑÎ~â ÓæÏüËs”a‹0ÓâþܸÉå”:±hâeI+K´· ÎÔÃ# ¬ÖVcZtg¢'ç€ËOTÏÞ‰rg „ÊŸ¦]E€G.ȳ‘;'šW¬V`J@C Of¢ˆ#R©Ü$£†ßºäíéË–²ÑÿBªzÊÒ„¢ëÌ´f9kR÷2[?£îe‹$&eº’ ýEpܮǪ ´®èèfÍ%CV)OŽ«s í*)8‡2¡÷Ig45§¨— ÉüTô"#±M‚7ˆòœ1ÄâsöÄ2^´…â:R~!¹“ ë‚ 6Ä!*‹pÆM%pÂ$tÏHÇ ,ŽlÏí’ÉgÒ7ÒËMn”c ”4ã’L± m"Æ*ö£®×EÎ8ô§“³ê ɲÈjÏð½b²—4l>Å&w„”Ï~a¨ö:SÅ6ÏŽ²Güõ“úÌÒJSÒ¿ ‹ÑTñ Z` *e!Q ŸNx°/ôðÌìé t ŽªÎE*×Pð}(î©°œÕó|#4Å1iL²pÊ# ¯L§çÌ| \ѵ j4 ¥êLÂ2Žˆ÷I$&ê2æÅ «£i-§Ú §S2ƒ¥ E9Uêò}'#+蒱Γ?´y ¯Î”U>7Œ3b`гAŒ”`·9jÍ%r°''S&¼ ë+Äá\Ði)nÌóÎò¯#¢?AÅq«ˆ%qÖûf¨Ó.Ý1G=Ï,bf6ÕÛ'4R$±ÄxvAGâ”u+óÁúŠ$ÝD ¨ëÐÍȯ*®ó9jo2L (™Ã¶Íô:RTQç!W Ø6Ë\ Þ#âÔ>ô‰5OÀ>ã4œ*b O30r¸&ñl¶“èϱ÷:(ÿIìÆÜÇuñk¦šïÕS‡õ\ü¢¾5¦É ¶«›‚*Õ€}¯,ÿÕMn7n—莃 1ZF–$)õ›a¥¼Â9ÿ‚ 3Sˆ/[YÅMzìLªú±X¢É‚ËôeT'C‹Y]Ê„ˆ©ÍaŒ‹gKD–ì1•ç¥>–`Sýã†TÓejB'c}˜R³s”ÐÖÚ˜£¥«ç>z¦^"ù8\îÃã$?µ¼(z»…hi°Rx Wj_,‡)H{aR†$bÔSŒú§úPõµ¹Œ#¶H›t%ó‰0õ·"ï›v¡î}¤!/Ö ËO’Z…YÐ/¶Ü¸'›DõB­ìR| ¡m'‹ú>® UBê®ÝU©*¢ sp#x®°ABm”ðtøY4kÅT‰ïE7@!èó9Ê í¹'\ÏABbòt"·ÛÆ}s­·`À2¬LÙo§xüîf¿Ë•´V†‰:‹%«­Õ+~û¶29bî$¹ mY«¸)õ´ÛtÏÉnûªíõaU,èÇèó“”÷±uÙ/4Š[ÙÄ¥hŽôM§¯á?³ncmý ŒþõIÊÍUâÏnj!»æôX·-þLØü÷[pRàøºjuA€¢³/§BìâjbꮰN,X#,?`C|žÓîMõD Vu2)jÐ×±Ye-çò©Â†«Â&ðvN*”ô ²›nJÛÊÌz¶øÏ'œ#tfë9]&™%†(ÕY¶#—©¬ØðÈ­ÕZ¡PŸ¥h¶R¸Ð[' 胩Y nÉŽO‰*"jù­Õb32‘·µò>2ƒÌb蓇¼7Éÿ‡H…1šüÒò½¤áªÙ»WÏ‹Q¬òaÈ-'©KõCft²ÏÑ·™ú”÷8ܨãpÅÏ©¯*啱"¢Õk¬× ÑAÆ.æ4.¯qgWG5¦¶kˆºa=üRÃäžÙòÌ鯩mˆ‚sÂvVZ&»/YxŒ:[Œ¥i?’¬­",ÅÕçI¼eKÔë± ê10úÔT“"¹YðÁ2Ï`.þ#ÓèܬÓj\‹'Ó 7¸Õø[Ù¼ÏÙºy®õlžÂTù§ÞføˆÆ7– ʧhÖÐ>MA/­6äúe¿Ï…Ã%Nã"?Šw ØigU£IŒ¬8µ‰Áí•'´·’ÄÍò”nlPu… žÞÉLx„ŽV»lñÖVAU#¾g«{ÍÁÒЉù·©|åÓůbŸÆ]‰<Ž )kòUÈÝ·fÌÔ§{]-q¡C°:HƒæR¯^4ëO´ý½{\ƒ%Ö¸Æ!?l‹Þ‹fj”EÉ[Õ³Ih—xöù“¹”óíkô²Nbì‹x#_çk»•YR÷Ï0¾"棟Þ.Ñ׎Fù-IÃDeÑUû=µÞŠÞì˜ý)BU¶÷àŒ%E?¿)“RÞܲñ&’ßyÊœ§ïòb„ÇÝ6ÙÑš@ÝHï›àtNVt) ¨²Ý¿Ýù©ÉáòÈM6ÞL þƒ?¡TCQ”(Å!è´R$÷$¹X %‡E!ÐÀ$®%"}¿f,Î%“Å!p(Üà ‹E ÔQùE˜Ìc‘¤¬ 1‹LÀ³+òJ‹Le0ÊÐy8ŸÁ&5Xt:«[K« df  Ï«÷Õ~A‰Ï!ϫՖ·¬B"ÐÈ¥B‰EˆD_8˜•܉J¥tè&2m€‚S!Õ8eVe3›€oïèÄ Gj•Å¥ÑJ Rc.ëá•<\F§ŽˆÅ¤ŒKæ™H…e_×ÈnYÿsØd´ ÆÍ³`­ÐkƒÿG˜Zp0*bÚ=â]½<(õó½ ÜÆÍ«…{'PN„âíÖȸQNý2«©œ«O —&-Ê®ë0îpë­’"Î&švª ªÆ5à;2©¨­R ”! ‹¡:HB¥¥hc|¢P©üÅñ2îÐ’\¨/É‚‚ó±x©¾ 2ÉÁÎJ ©‹ÑõÄ(‹æÒ®0’“BÒ Ð¹Ò â‹¿ìûX˜)Ž™³RÔF¡·ë`¸¿À «$¨)r,Ç Jƒ,ÎêãþÒÂ/’ã)颔…;ì…-ÅhŠ0+êœ$È“rõ&9í"xù²T< ~¹ÈsêJ*Í)TSB~¶Ó›‡T>Ò êºî#§±ê-7 ÊICIÏ}Z‹Fis”˜JQ»h¢ØGêÓT»3ÄïfT¬ÛL%K LÕ=‚ƒ%©˜ÞËé\ZÆ>h³v‰)Š -ªíp‚A ¤Ò¥Ê¼•¯+Ò˜¨I6›Ü¯T4ª{*€ndµ;KOš˜ÂŸ–DåV·KÉ^Ÿ´vOK¨T6¢¸ g ˆtTªËÇí›<à@áŽ[t©ßkÓr˜Ö൛;ðŸ}­7ô(£&M_0È£\TK»Õª ,Ñ?÷b‰QI\l™É+®YJe8Ò߀ٕfÏáHUµ3±®í¿dÖ*Ü¥‡^;*Ee6u=4ôTÔÉ“ÙlºW¦ÂÕ=y´,j­á$¸IvG‰ápÄŸwÔ¥& Isr|rèd1Á¢â®¾k5r¦¨!íÓ7*œ:ìÝ"~Òát ‰I4'ˆŸñî$çÊ¢KËŸ Zä»ÖÕÖì–ŽJVuL¥ÚXt¶ ‚ÄwVˆoç÷ƒ“Þ;:¢’M8„LÝú(ª÷õ®Añ ñaHŸPÿ³ª¤Nrä„=°÷#b@ =¥×*H QË]­: üS‚Ý^ä!x6£ŒøŸ(+˜Û¿ÃŒSI xä¬Ý”ô\xüYåmO9Ò¾¦CZAn´Ê0´žØ Æç9 >öI\]Tüé•6îDÛï}ðE–º×¼ 07&ì‹#ÔØÔÎ鯅ýÛ¢Æ6Û‹F ‘:‡ àÍ,/íèù²?ÊLˆF$ù™õ˜êž¨ü†Eii˜ÆÌÛÐÔ$‹Qɲe ¨ÓñÄj€zÀÖžòNi_Îì™›µä©LbÓ~-8ã)è¤XÞÑq*ÕV®Ò„lV;ìÒ6òböÒ‹'íÝÓdÌK›QL-"N« ŽH2Af|³,T¦¦ÈŒƒj!­¶`ö¢YG” yCD2JÚ¦*þM’EÁ¬ÅfC ${@ ã-X¹ˆ%‹~Kç–ÒGòq“9º¿ÅôLÎûŸK3-G¦ôŒ?3ð,}È%\ÃÞÜP!CÃb`’\ÓÖS É"i©$4ie` äBU 2׳+rõɸªZ\tâ{e6NbHIScYlñUx 6€Deå1O„ˆšã`‰Ulu:r¶Ï™Ã' ›ñBS"ƒÎ©2ËŒÝC®šOF÷:“áÅ}£öRI”Û \…ÒL%>¡]koèY·º÷ôóXÌ£rz°I3»*_Èk¦°»„_]h©Qö S·F:†\ij=ÆuuRãúþ&0¬¡¸©#úš_Ðh¢•¿1 *ªk2rB(Kš°)’BÉRÿWi$ΨӽSXàŠ•$¥ŒÑÛÚ¨ãZ`½T,tŽž°†ck}´ýŠ•¦ôØÉ[${Ĺ³2ôTõÓ%Óu¶õüTÓd·¦–ƯcvŒÖBÓZÉ‚\E4ß-¤ƒÆí»ÞJ¿oÊÕ*`´Â\Y©;[JEIëZǧ7ˆEùbÕÍSÊhôq&ÄA ž¨U4¤´Ùzc%BQÂ$T'e$tPà}UzR¸û1”†­[’qn úž9d¨£瞊ªTò²¤ÛBHŒÙ%v7h‘&b˜ùm=ÃçõúNk:•dè Æ$“s†àƒëÖVªK×=q‹° ü¥ˆ"9¶*>ª_ö–‘—,¶›dªˆ²–°M½ÅfÈQó.g2L ©³…-Æl™øè@nU;4p5Ù¡CÚ¡u‰¦Y@Å»ýµs%ƒ-3l„JÆ#¤ú¢nôW¢ÅUZrR“$PÜùµ¥6ó?b’P4äðÝ' HC¢Œ\î¶ d¯ÉZ>iuIÓÈ._ ì´Ue‡æ\íù+SCçMŒYSâ/ï—(u&p·Á<`¥œ‘N“Z 3mzÏrœH«Š(4÷ÎZè”,7}R1EËU²ïÊ|¦ #³_2!§tÒª§£›·oLw€Ú£¹ë_ Ýxyi¼Šlï”´nT}~èdîÂÊšf°º<˜ew‰|m>H7h76·|¹•æ“ïL¶óøIxÂZu[KŸÝÓþÞe»«=ÄêúË"l‹ƒë{ÞÄ!Y€úѦ…3Gz¤Àjœ¬Ý/ÄáAúç`áÙÿh83–↜¦&µj'þ&>½#EP”’k=¹ÓÉ™.xeY4ïà Š#«·ÄjÿŸ:²EÅ5r¥ZªÁ*áX™n'‰"èªý8›¯•°½8ËôŸQU¹[äÀ@à>“v·²Ý©ã Š,€„ù?:=Â3³>¸4œŽíLîÍ‚å<]Ex˜èÒÞQlΡáà­“ýž”::§´NÃZ«·åä ³ýNHò¹•ž jž±¶ÎQËu2h w@JL²%þh·œ+žP¨ƒ-œd3#]4U‰]0VVß$5oSuHíÖ¤´óáÚ:¸U‹­œ·BufQˆîÄ)Ø­û³vY)ñ <Šæcµ{q#½ñþE7QøÍVIQ+M•ÕGïv’Ã$_àçhFn·N¯ð`8¸ €nrï £Óºjã¼<ƒeŽ‹ÒgX-ÈÁ¨»­Vi1UbEâ)¶À-·0 IRðCÇír`aL^€âQrÊJ¾pSN¤c~Ò>ì: *ýÖý>z-i½0ˆâ ª‘Úp)`—ýÜ‚-ÐóL¶RQ“‹ ‘t«†›"j­ðò{ÊVbäiGÉšÞdü‚§õélÓñ]™udÌ}z¿{•Eá“à’Œ­§_‡¬À‰•±ËÁñuØÏ½ÈâNƒT£›Ø®`?5™D#¨©T±†»ªúþR%CXÜݼ$E½=ðŽGpSÀ_Î §1 (ߣ qéo|¦ P#$'ßãˤ#^™Þ=4ü#™#$ˆ™"áS‘ðÕšŠïz\ò’saIòûßlú¿ºú ŒJ«˜Y;ÓpªÛ¶õÛнƒ2Wú?Ÿ}…šÙ3;;•_E\\ ­¡ÕQ½Å3CY¾T”ñÞ0¾\á²»^ëÕJеçX¼Š-šÞA´2h4¹¥# Û$ê6̉ç·§ÙஞÇ{ Ö0óôsAÄVlû;x7‹ŒjÔêö4Ã^füKx=ŒZ6›xjzQµa‹†çÀ±ˆ”>ƒ^/ÜŽ@A3gô*«± :KÑñØÛ¤ìÎ6hå³û©?ºÞnY Ÿ‰¡,r5Ÿ*SIü,»Ï7åδlZIÖ™™i×#ö±ffç H4iê⪂þ¹|PV\rÁCVº&**ñ*M ]£YZh¤C""yDÁðfWë,òÙ ôo_¶íÍÞY„cª@(ÖÕùØ‘óãLsÒˆ)hªF¥¢:šÖ Ë¤&OJ.Ë&::$oúO ¦ËQþÑË›t³.j®Ðl@ˆ¸èró& š.áŸ*[°{ÆÍRâ¬I”dÇËòe9!ç"¥ÀBe#¯+j»{”ð¿Øç¯)&G £8É6 s8ÇÌHzè “‹ÀÈc»ÐÉ)hº¢Ý€ \„C3l« \î˜LLº Ñ4‰äÓ6 ì,‘&@= ‘»«ô ˜N‰±¼MáÿJ€ŒÊ–¢#ª\á"žqð ÒÒ`®ºGìdû¾èœ‚¨$T€¸lüþ‘I³U,ÑV•[4¾Š¤›WÐÒ(…J+½jŒL±-‚=´êDÓE³µÓtCE˨µM8Í \9òÜ$"ëʬøÅÀ#+^²61üþ$mò›9ØWµô¯È‚üzàÓÂ:ÙÀŠU‹7ÑЪP&ÔePÊŽ}Pâ¦hëºìKh»Òâáåb†™eè%ýÄì'ö4ŽæÌJüßÐÚ´½Á­õõ¦¹óºLÀ z£UåÏli(GQ²VŠÔ;²;3Ø©ÈWƼٗ‚<†WøŠñ¯Mò4jþB¯¼®ÆêŽßy§GØòBÃìzeTM 3ô¿FÇ¿T32{Q,[óߦ~¼²÷Òømbv žùÔZóS;`(‰—”CØû!Ƙ¿HÿÙ|nÙÝ-öÒlóÎ|„4gniÏI¥ÐÎ4$TÏ wuéô:5‡ ü!Šx¿0µö¼È©yiǸGBŽyÏWéR=BLÒ]6g¥-¸(F꓇4È4‹«ƒ°ÌÝXÿPŽ¥ñ” “)¨FOý¤DCnªÖ¢ôYÄv­øZèR“ÊÆd´Ä·¾ëŒÜu>.!柠÷á_lêxŠ‚dv‚2wÉœ“ǕƗ]E1Ë™Œ¤–c#ÊM/+.&œ·D6 DVŸXX¸ÙÔ£ƒ†=Æ­\ËS²”$N Î6“q!Öiñ{І@¡èeáþ“„ö°Þ+›¬Xµ¢pCŸú€$pÆcÎ*M?N=<¦F¢«£Ž ‹Å!WºÞN'\šqÜ&Ó("Ë\ƒúÉÃÃQ+1÷3&Î DÜA‘¡CÓ¶³;A¢ÒbOsn’C%ÖL)#L™óŽ’'&?ß1"|oBcJYó9l³2'ÙkÃ*DÎê̘“ V·è?Ï‚B/)¹ä0–š2M·nLÉÄ:A ‹UîÑQKL‡¬µ "§\ÀÝ%2‡ÜÈ>è¥ÄKU\S„NŸ× ¬ Љ"EHãZÖƒfz §xpÓu·r¤ÊãWÅ9!c¥ª”ð‹»•‚ÈTn¨æIWÔâìi‘”ÐK³]}‡÷Ïþ'˜`˜Ö‘‹–»ã"uf”ŸèË#Õ´UKh5uOX$ö¯PUç !48øÈÖ¼”†œÁBŽ!À³ò ¥qŒ/Øüž/j¬Ç­¡"º o·snÛ‘Ð u˜®åË?aÞzÅnü˜“ŸquveÏžx¹¢xžÕ5RJeÊ+‡”‚í!ÕYÿÔtY¤Gýò_µÆ'tï™"¯ŽÇM˜M% M'g‹šàDÃó5–Ëç±£–®§ Å\¼cøEK3)ôí")«¼œbÛq¬ÇíÐ8ñ‰NEÂ#Yr‡¨ñÔ›†â R09—šgKyè¹Ï‹çmÇߦhñ²¥fÁ:$©Z¶©Žêr¢FÃuPó™°w–êH™"š±åOn5=±½ka€}¥Òkx4Eð¹•Æýßê<«‡KF@ô\Q8Tá î#ĸڣ¬¬Ü•.‡ü®dψ‰& &ö1oͶÓ*ˆPÖçÕfg­ialàÙ@Ç$’]»Üï6C—]†å u©b®g¯i #§Á®Ÿ3NÒ¯†Í¥ÂC0Q Hî!&ÕEM"­¯êkâAÜ›sñ±úÌJCWDY‰'¸îº¥}Ä~bªòA.…Vhª@òÝ&Ô”±t—­Ä\CRó§8rñÚQÆdÇ$h¹×Ž1-ç*Î>³ªÌ.‰ O ÚÙBéÓmöærvšÇËVÓÓËíçy¢€½ƒ›ßUž™Xý1Íl¦›7‰ ˆ‹g±ç¦´º¢!|4Û2.¨éíˆ_¥¥P8 ͼ€2Wa°{fܯ¶fK§‘yÙ\}ØY‘Ìø“[å.o4?+bóÓbô”Lj݋°cî"£ºÂ òL4P%>æ \i¢d–‡Ø›¤¨ÎNø»â˜ƒp0‰ïˆï¯F–êú©CöÛç¦oξýäXŒº!:·¨ª¤‰Üw‡,{n–¥â=*ânmêCŽ˜0(´m€å\؃ $fN‹ ¥ofa­B)ªHν¢Z(D MZÐ*¥'oB\ï„ÜúgÓ¬?°™­üÍïÊ)j(,> b²GZ¯ÀP šŠo&nHý †­ŽŽÿiÖº1œCÊ!@°/t½­lí|Ïëª\¯lõªÀ¼Cp3‘°¨»Ž×­æìm·'Mî ]Ë,Z-Pý-} ä°*ûQ†GR§èJ4ÊHZ/¢ Ë w‹>ðsú,,FEpZ/r¸"«-†®ÎTi©Öv²ÊƲv.…¢Hï–×R¬Ð %/ò>Þíˆôï8ŸG´¨2€MÈ0ŠÏ†×êHMË$ÅqöHâd×̸°³.ˆ¢*/ÎŽ2À>ï¨Yå^t©x±à¾‹ #OD9ó€ÙorNÎkŠê3¬×ê‹,G®ƒnÿ®Ä*…ŸJìÚ2Kg,1^̰ ùBªËÁGTNR.Õë,xL”ÂÀ)lŸŸbì/1Ž8b'8#†U ð\Ã`¶3RŒ +œEá¸chw‘ò10Œm#2tçóg¥in“ ’CîÙ"2¼øÄíÀ%Ž›ð*‚ÔQ#‘䫯=‘E)§dcŠˆŒdàQx!ÇÇ:Q0¥‚N{¤}að¯ RÇñ"H{"ÒÖÎÎÒ÷#%ð,f³£$²'ÆýÀ-RÑ@áòI¬I fx¨ãºWÖ]% ‰DÅB»;”¦ü³l'" 7,úZ/huF˜¤Í£K"&UzÎø®ÊR´ç²–¬,µÊx›bó+¶Ž”ÚuNIA‹uN`¢Ë½j‘IRV×ï/PÂÌm.‡mˆj<ÃŽdcËI·ku´Ÿ³?h`ï4ð=ÄRk¬‹9ã·oîüó\áöûŒ±> Ë‹&òtï5‚¬ËwHH{OƒÖyTrE×§e³J*Vlè®}¶¬¶š5 RYè£i4U-Á¤ŽªÐtdbUÚOTÆÃfFH´|v:³Aôi’+T¤6tê×ODYr-P"l¨JvJS2:ÏÊeÈÜQ„¨Uè¨UÛ·ËMp¬u2¢ÙŒŽÒI‘6íÈGb:íPª=Ì úó²Åä9{%ªÿo¢E.€ª²àñØ8sOh€W ­qo–£!jó@b\ø)¨<¶u{ÈCá^Ú·ó€BD‹MÕÕ<áŠWq‚xHì*f–&C‰¨áCpmpqÑ8SCŽÅÖ»'f0–¡ræ¦ò5Ô"wáöª)É4 ù1Š9A !ù5Ç*ÀC" *§lï„§üÑÌY—ã 5KË {øìF¨àHdìe9GKEòÕRãa7Y–—1$zGÌë?£p£~q`ëcDâ«Ùel‰‡f¼Ý¨ec$jµw‡—– Ÿö´¼N<, ºy8Í4'‹ ,lâ'>&u Ë›X‡4G´dn\´Tå b¥_‹cŽx‰©s¶ÒPOõñ¢!|÷xk;¡þ¡e8tjð>Îúƒ!ãî×Äd¬µŠ?Bž1]fP¢8eqDÆŸiFȸlɲXã‚Àˆ–Nì‚qs†]<¬ú÷…ŽUOÂ]¡õ,Ž;¹ÙÖm‡Mnº%vÙc±šóçõš‰ðqóQÍ¥ƒ ž©iè‹”¹6Üÿ ¡/ìhy”r–±ï©ëQI©uF%%¬A—X¶Wø#FØjI¥6·—(.5ŽÆ ¸ÆQŒ2óeUX1ðÙeöW˜1û© ˆ<©¿¬ o—J^X _ u‹±—Bº´P̸·±žÿê›>ÏpðŠxåÚ·yP…¢²=s­F1@ÚV¶‚Ϙ6ií¦>UL0I Ø¿…Ú.صŸ#¯šf‡Û¥èŠíÙô¿ŠfXñRq zj8rËoBy<íbª&™­ƒhtEu4ñÃÝ0á¦ð <Èɯ-™1á!úUsÌÑBÎ3pbÅÛB¨fxx“f_ w'ú£?n.*µ¸0y¬Ê;! Àd‚ààÛ´G¯2të»  ø:¥ÓôqY Œ¤d\ÉéÀöH˜íÚq¶áÐtóídà ]Hú¶ÚV¸pµKÖ›ÕŽƒ‹-V«Ú¦95 ù’Á"pö¤à®PUÁ ÅwŠ÷b¾Ã%Ûb· 5_™‚Šï-Ÿ‘?B9¥Â  Ú˩͈Ç`u”A(:ÊvxŒÁ®öËÿŠü=Ôt xºf7¹ŽiÈÿiEñv×Tm‡o™eö°‘Е¿¯þZåÍòzŸä·ƒŠÛÎrÊUï|±=JICܱrHdÏ•$œ0)u›PaÇOþMÂ5µ™Ð̘'Êè\žN¡ b¿:šôÛûT3ò}k§EŽˆÒU2LBó Æ\ÿé·!U_‚/fiìÁ§…ðY2€‰W‚4ÛVi±ñÙ-d±ú)ª×óɸ˜ÅÊVYŠIÊSNšª#Ž,öŽ"G§6 î`ºñ6¦°t$  ‹‹ÐÔpÚÒCº+§þá\„³hjËC6_xB;¿Ùjü¯E8õœ_¢aÇ"+ß’=÷šC†0GÆÀ´©“·˜u(âš›lî”EjÔ•͕p•Ep|b.ûÁò,µäíÉùwƒÞ2€SÊ:ƒáKÌΓãRü%¬¯öÀ°²®¢:¢uÐ_íH{Ï›nàŽ?™9òï6»^¯Í¥&Ó5£Pæ³1桉Â`ïåЄàÿöPæ »¦ˆ#Aì‹nU¶jÚî6W nüw•ßöc’·`¸™wØL# òÎrŒˆ4_v¼w(N,ØI´Y¸g¾¥'Ú^3ùKó^óð8ÈÑM‡k¬½'\äÛžÛ“ó´·h&Á­Op{)q$SÞ«0K”¦›jWL©a^rFÁ¼Á{Fi-¬mX$~ö”ºЧ>Ü$÷˜u)fÕzüÎ\8¥Û:Ž|Ã%KݼJJð¾íuscߥ’bª=ºÖŽ‹Êf×Ö­Ž^mWë¾v<ïRjÒ\e#’Á§Å Àbü ¸4 ~á€(p þ‰?bàB0Š?a@˜óêA €$gÜxù•FòÙtbE"…IhÄÎI ÎçyôÒ<>¥Òè“ú"¡È¦‘‰¤º-—H¢ÓI4ò77«”$*‹-šSå³ÊÓò76ˆVmqX|BÇ$‹KâÀ5»I£°EþM&¦I#1”Š]¼X¤—ðEMGäñoûµÄGÂ%Ó©ÜniT‡Qð vn GÍE'p/a*|ç%ºK„’Ei·€aQ‰äšç-Ïl”\Ç!†QÁœÚce4žM5ψ¶L4áÑæœþÛMa£Ìa‘½Ô_ þóE;°í 1h$’êlByÞû€k¹úŠ(ê‚„! :p!+V~¥ËÚ £¡´–ª(¢èŒ¾Ì" ¤¼¨£d»#mÊ(Á¬mR$ŒDçò,ïD±R,ß ÈÚ»!LtD†AT6¤Ð4Pˆ$LŠ$ì2:СŠÕ ±‹ªœ N«.ÜG(0‹RÑë.B("\ü¡Ë ¾‰HqZÇ,rŽž!H²í1ÌѪýÃ\O-M”b}ÈH4 =è´ö¤Óh¥’rœ¸ÉmÜ™ –Î k*ÌF Ú7t‹‹HÒ/U¾ #QÏ“r6¾odxÊ€pà }£ ³*‘:uìO‘Ž1­&yà<,@6I3°K³,IñÏM ¹7¤@Ç>ÿÙñ;R("#ÇzÖXÊ%<çÈ…°FzAp*9¿<¢Zv ´LoÑÍ'»âÌ@o‡Ìš¤À¦Ó)D¬˜•i à\Šîw¬Úa2”Ò@‘òôi娭è@~á{'¾˜xs#VJ€c'€ÄÒLª#yh“4»—©àk]Èv<(–däL‰g¬¦{­¨·< doLÕ7É+ØÊ´u…&*‰BàÝ(ð ÌA2âÆÛƒI” òJÇš{å¼>u 5B ÇùØ,ïÚ8¸SÂ?éR<6I²© ÐÒÍ‘Ø.Ñ4»)`¹O{‹ŸA3+Òvî] C„.Ar¹EÅGcS²MUd3÷hñRd›?mžiÊjbwŠ9²1Ò¬ó“Ãe2Ü™e™Ï`–Ê·z¼ˆÑz@ﵚ¦\ª‰=$"e”2Q_”œÛj4ΫG"†é"”†e´‘ˆù'Xþ“Ãò“UxˆqM,‡%²¾WBTt‰Ü¶9@¡Wôné©]Iç¸é3HÄMWEqrSÉ·ej,š¤1¼+ _Çë¶”VW”6üÿkRpƒ3 _¡“z$:o€I–ö«\$(¨"³˜X#BM-¼‡¦yú;iÅ;™w–tE¤1©²svd¶„¿—6ßm¡li9²0s[" ™uùǢÀ§J °3-0õÓ@‘Rî•j”Ò–Êzx 5RBùŒ®è?c\mô&Ø£ÓZe-è¼Ð¤¸ß“ÒJ0¼þ$€Ø·¯giáû8gÏ™ŒHN!•ªË:ë“ÐcÉnëÎøÜéËrj‘ðæá¢ªqZ‹DPíwV½4©2îvM.8Û@4 l©GN?îk—Ä—Yšòí¸û'˜œ›)ßÐùO*MI™‰Õ#UŸmðGÙ¡üÏáµ1$CcQL¹¥5î»Ýçž5bÓ|NÌÅÆ¼îõÙ? tsØ%5&K«f®ámׯtHæSy7“ýÓ¤m½ãvî÷ÎñÀça.\iLˆ)‡fb;›†ß)Y_'§6õ&äQ)Þ(w}K[îmQ$ÂsP}´¹Õ%é“È#ëHâöƒ¨à!†.›ãðÒÈœâ´cϬÎË,rAãÕË‹`7f‹%W•½s1|ô“޶öDDz ©O[ðR$ Ùcí:b­U UÉо“‘,‹œ-RñÍáD˜ÍãT¹/ž€K‡[˜rU¶S cܬ•t—:ªâW8ÇBhËuxq†¢^wCuˆËß}„1ÓÛÌ·EK;o„Tñ›UÌ2D"m®Ÿd n±0úî¥e¼Øt1…@Êݱ“Nh«`>£T²Ú¼éàk*ÛçthÒC»€—k^+T4¬d¡·ñëµZ¤|»\šƒÙûTzä(êœÐʼ²³5œÀ~NåÂÛÖ¤RÓ¤î¨+˜ ÝÝ”Orïf"syЌӧHQÖãk”òÚ¥Ðysb’‘ÅþŠƒ%]Ó[æœõ—öüU]w7ú™§Õ³‰§aµ÷Xy[1…gì¾0û½|>¾Õh$‡bº±Rü_åQ%  œ‰³0Iº¬21B„Žð³‹°‹'«ØŸòå&ZH q¨¥• cÔ,;,.q‡ªÂMÁ*)ê•¥ð)1p¾3ÙºCÎ88ÝŽ©ÝŒ°®‹í7KD€+.§tô¼[±iR¶ Á{E(ëõ–~¶óžjÙ•@€¿‹;r®h‘4Ë4âÒ,B˜:Ù1²™&µJæ» :ˆ£&ºÒp•+3µ²¹ª‘yÖ:[¯8C["I2|%:B;ˆáÂ’Î9+Ù)[ðºòµ>d:ð—ÃÛÃÀ±º‚U¾äˆË0¨Ñ'òà€2°°Òa¾!º¦òD1w¨Øõ°{5.¼M +<ÁÌ/ Z.‹ü5)ëä›Hï:ªæ”Ô¦x}°Y𱌞úŽ¡q`¢Ó¾“|ÅÉ¥z°ê¤è>T=‡à»)p:75´L¢3ŸzÛ:s¯ñ°E«>?a£*Á…ˆó±‡ðmGpíºP‡Âð‹ú]%н£.6À’ d0Be•£Çú"¢ÒŠ­Ù”Ž3C »!T1k?ê¿ü/¡ì迤Ã-«*-xô³bp•£ý Zyø¹v³ÒðS@‰rñ s¨YHš!è+|ŽÃû¸‡à¡¦ë®À¡“Ɉ¨aiC@„—ª‹Ñ¢¿:ÙiDó¢l+ùË?¨÷´"Þ ;¸¤®‰ãE²ãšìšZ…Ãð1iûÀ¢!(:Øš%û‹$J sÅH‚ :ޏ#¨¬-$ÛOóö®Ô¢˜Ã(«b 0•(÷µxõÁ„,4ä/ŸTœÁRô!<7\"K1Ä9w•+E7’-<âY2lº8ã´;Vº‰˜ˆ`Ù9ë³{@©yë¢Ô=.³±º.ª êÈ€») >£'+ÑÉbËÇÊB'Òm¸Y‹›ñ®LÒ±‰Ù…'CKµ°“ÊÁÙº ë¤&Û¾¬Î:Êó«x•S€t‘nLØ“,ùÞÆ£± s"ˆ!lÀã5ÉÒ5¸ÉN”ŠÈ"#m·²ô¾<»€#­ÁÄð®Q<ÛXH×>‚0•(šWDiDÚ‚€;ýˆÌáMH£¿"‰ ¸Ëì~ ãi‹³EKŠw¬;ʇÌcQ8±ˆR]Êž:D•ÂÌ Q¦Èt;ºÙŒ«¼ON¼ C~=Ùã« –«€¿ ºG’O©Ü°šóI Â•a¢²‰±»ÉÎÀÕK:¥ ä´LmޱN»óBÂõ#)𯻑m›{i‰Dœ:âcD¸ôÌôÉ6aÂbç<ñ—zAR›ûJª D˜Š,kc£à7lN›Š½ iRìã¼ü_0lIF4Œ) äa©£ô–1#ÉLRAŸESˆrÔH\Ak¿Ãº“H¡Ú-RŒII3Ý!¬·’œM#ºûÅÓèãÆ=Gòø)yÇ"˜›ãe $’c¿Tß'tRlS QNK-ô ËéÅQ¨¯š8CC›Ù”jʼn-ìÓžl”šcÂðþÈdòÕ­Å 9 -±!ЯœH' "Óí4h¸¸™' L¶+j• Öqù.R=”ÉI”•»å‡)Ø…GpmF½DÍô¥4DŽ€ ÷Iã‘S¸4ÛÌ?árØ‘ÜP=±hš c (”fpšÃ×Í€¨ªªIäù¯enŽ:^+;F‰Ó t³·’i:õ'€CˆEÉBIâiTBeŒÅtž4üÌ4U·‘ˆSõs]0*¯M™0Ç)2›8d*a¹ t¸V™ï1¼\”š-9•¾ÍEÖŠai/œ÷ ¦”ÂË¡Ñ$ ÒáV" ºD`Ð=ŒC ó ãݸ22$¡ÓÒÏ(³Ø 8ºBKÜèÍM—"™è§ZJ/›ë:›¤©‰ÞÖ{@zž/€ð)øãٹ⿠o±-Õ®ÃjÝüÉœ´­‰%ÌËÃܹ¨ž°ÝêBRù¼j¯œÙ©ì‰؈u¿R´L[‚!'Eg„_%aÊŸ•ÒHä])‹Uƒ)²50Ø=Å µ_C¦?ÈÉ»{ÅÖzy”V³¹êЊæØ0ƇÐóµ” ‘:6s!š]€—øRû;=Ú[ˆó(º<)|³Å• ‰-HNOÑ´¿ûÑ¢ N<𕍫à%•d‹4aBô̱½ @ïÝ…™ ú&ˆC;ŽË\##þ€D! æ€:Y£íaY8hŠY:]È” :‘0Ú?à%†>²"Z¿#U¨‰Üºžkt-‘Ðú·"¼ 1 3žu¼"*ùÒÚå°DÙcº/YíÉ‘á¦Þ£WDmL:G)ÈÞŠb# ¨¦(ãÓ}<±Å7¯¶@5¬cÖ%h½Åg¢I3áõ’ ÉÄ£Ú%E „ž:ÏœS‹µC¢×[ÆCTœ ÝÛ.T<…\Œ\,=ɦÖ·í/FéqYl®»E:²a¢M¥L¡¹Y3Maªfµ@\[}ö'꘢LÒ\¬þ¢N ¶ N;yCë-<wVÃ!C-.‹X³>œ^GÀ˜Ñ(&Ý:&xÄ‘ÊñÁôã8÷¯räÒÑ'U¾Z«–^›ôÆdœN[?ÁEǯšÉ@ƒ^dÎ5} Å}-›y%Є6#`l‚L´"%1Ù„0'r÷ˆsQè;ð»,-)ANKÄêþS|D̰ŒQ¨ÊÀ¹ÂBbÀÜUëÔZùÙR©´Ég­?@’ëʃ²DaI©K›| ‡ÍÏP‹$ ”âÝgÉ;òm©4ó§Ô#×P)£6(~4T1éf+‰KvE}ç²mÒ.6$R¼-¡¡X¬¢‰øåaº¿Â"ÜMH#êê`ÝØ †(ªõÔm}èIm±6E=†È/;£IbLâ(bU¡E¿a "M‹ó# ݆¤]kL\2Ôó*Ô +þ™ýMÄeKRÊ S°æšì¨ICž‘3&ljSlVŒËš<'q&l®Nùd°œTdึæ|ÍÝ}¾Ò®AöeêÌ0f;Já²5jXì-ÇõË\‰Ö$ÌÓØè#íd%5Ôã¥ÌNÒ•’ÇÇÎw[ scj·Êϯ†Aò°éÒìí*šIY.ödÙ6R‹ m¦ÝË*Áiɧu»ÓÖ 5¹ÝýÜí>–ö/IùÈ— … rm±æ@3uÔ–EÑðÅ"ܱ·Ê˜òb…žÅœmc Ó˜ÛíÃ94FÁ‡î]â­'=}‡íZ¶™<ÞÖuÀíôŠ/<¾7Ç4 lb# w;Fú¦]-faÛðM𑾴™&–Jåz=Û8Ÿ!“ï©ëÂ±Šæ¦’Žž:ÌŽ-ÕÞô¨ÒpÅ71Ä‘¥Ð^ß+Spn3¯8‘bAé<@DgGŒ¢Ø·"ßþe_2›J¿^´÷žþ¼ˆ’]:ñw;74]rsš}Wë³­ì²¼j‰<êTUŤÁ>s-AÆH0fnµ8ô“0ïHó×Ö¨gä|êë@²Í$pïÕ8ˆMÔFQÊ\óÖyIŸO¬JšãÎPà¸îÖhÜI>Žã»”ÙÛÝFm*ó8Ð’O$£(”›Ü+ì¥èˆÛù+¬ö¯pÊráVhhqN¦àï3êÅÃpBìâ^ß(Y7áÞ‰pê¼äÖWÔ°Ôc¼Év|Ï*]s»#ˆ6b ¶¡I½ñJþë·HÕþul™Ó2u=ˆjríìWFnB€Ö6˜ìq(ΰ¢¾;eô…¾‹èÌ“ÌÇËí$1Ø |6©øQÍml׉P—2ñ/¨ñ6CË]í{¹Ó”KTÒë–Ï ,Nš'–^Ùº-ÎìÄlë~°ùæûÿ[º›·Â #Mâ]<ßHø{€Øœ@20&Êëa¿yãýà§Ô±Ï*µš'Í(o ˆ}Ò'\ƒh*µ‹PAð±èRøì™ì8äÆÚ9šôü Y ®¬£E¡ëwØÜ‹}ãõ¯€c?á?P®`ÌCq'¡Š^e¶hk_ZÌ?\ ªÈ’IÂ-ù"Ö¦ñšªNCn”Ód‹°aíf$Ó*i±VÓHï~j± ‘dþåk?kaª—+ùû,^UhËfÓ¨¢;3½³Ì°©Ã¦I Äæ‚ÏÞíÀ0÷ÇÜoym¨+Ò.F%ùvn;ʬG{£cÿ –<«Ÿƒ^VÕÜ‹R©²/4K¥K%­x±¬H¢Á†«oõ<|ÃhµÖ¦iQrˆë=] ÓTôÙK“f¡ÓÕº…[+:üY•¥v^OfÙ.ÇÑm;#´R¸ê§‚½ !1çÐSâLhV•ÅÛBKà wTV0‹ÄRÒ“Vç|öS0üK:t'ðhõÒûQ" @„L¬žX†>ÒÞužG %UÉÅžqÞ³LŒK.¦UžnR”V#VÕM°„ªwŽ^yu92!­ÃøñÌ|´ûo¹RTæ×Dé>ÃP^ ÁÐêæI"S®ÞåÒ7ßÇ뀰²xŽRý‚fÕJOÜ U: ÕüGúÓü›ÊÉÞqZÐ:dJëß¶Çöî|îÑk5ñm“8™eB$ÙLìÙSÙ»V„D"i0­¹æAº×c±ôâ¨@ŠlŒ-5k¸_Ь!ñ\„”CÊÖM´é`È@¥[âdŒÉÈ–Äu³¦1·¶w¦Hmµ(ÇÆ’ÔÇhÂÇþfx'âÆÙ¬Nº..'+Ççé'ßÓý_v¶òu:Î`ŸD¥=½›)) O´yO¾â‚ä6ŒQ +Ê“ƒê}ÈãqÓr{5K¢uÕ£L•Ü”ôÌì?pÑŒ¾|žÙY¦I8VúeâOm¨õXî& Ø…<òÑeC bÓ¬+Å_žÏ+µP팽šY~4±4¨TáÜ€V¯¿ X³àýyÓ=M" o·@Ñ;wÁ0’ôÊÜ©ˆ±Â½HÇ’@ij³O¦¹¥ìêØ7æ6·¶ÂH`Ѩz™: (Â(0'Ta¦`Êd°áŒôUÄ:ifäÊ,Ü&D€'Þ²ΜÅâ‚Í«nÖc i-´õcf°äFáî&ïÎvj¶B#šû\²#h HÞLŽe$ú"gÆËŒ½Ë~Ì+Ž#¡µ $l#lO°ÑBª' ôÂÑ.HÖÉ<Ϋ¶ä ¼ixÞdxáÄI>Óz*i ,/Òk †Ý"Ô`Ââ&ÀX¥NÖFä¡ïè¹ÂZ? îŸ*¤¯+ü…\ìÚîz ÆåŽ…‚0x ¦ioD0¨VM¶èËŠqà(zát—‰ýî:'ã𙌠"LɈP4 :KòÙ°gލWj¸ÔÈDµað«!øk‰F§fäQJÔ†Eâ#ª6cz› Žši2²o2G‰òÛ.:Nލj„:°¡øZ¢"<¬’a':aðûÍ08"ZÀ† p:«‚¤Ñ1Î:Î N`JÄç €ÎFZm4n%2 HcéÞ+OK…#®?ÒPïÿëïñØÐ† æÅ¶ ‘qŽ0Ä숈þÁö2Q"oôÛ⮡2B«žê§ÀKm–±øv$cqÚȧtÉÀ·lfÆ'ŽÔ`Ž^ŸÈ‚ò®£rîáød„áq-K>`ÜN¥ö±ÌÊ"'ƒÒñ+¸äј*<­äÆŽtE+)Y,î,$ØL8²Ï[ Hå &3äØa(²±dÂDPø*©/ç @äòk!Eвp6«Œ²åoà™Ë&R;«&–l~Ï'jVÒÛ1Ò/ÏÊç‹Ý **"Ñlñæò&,dMLd«ã‚;¬ãäè<¡å7¢;22Ô1)¦‘g(!éò“,ÚÑQo®QpŠÂNb§rþ~­|Ö²ÞñO:`;¨Þ÷è 0ʉVÈdxC¨D‘d"»pâ*ñÀnCØcOàÈP;ò+*D"¿(xA±~vG1³ø«Ñš|eº,kò—’d¦LÊÕ%Só°tTÂhC±^¸ˆã“>í£Z‹HÞV Î.é6ðbÂXæåBd,¯fn‡¤è]eÙ.¨ åQÔoíþsîpr,u´D‡®œÒô’§Ü7ð~ã>—\§él8$ØKplQlru®þ“3öL'‘l`£4 B¶ûOµÌRÏT~ÔàB/ôŒŠË Ïì÷'èÌÅ Û †SH©†DDª¥ñ– LêÿIO"†š™…H:éê šŠ ÚQRLoR‚³Q-æ 45CÂ=5¯&$Èâ”Fýc[O°5kÆbÌ^èòÀc æB(Åopu©˜Îª¶îú”È=‘”ó2¼¯÷‚9K¾²úÛLÆ"(B~#sê(Ëb܃tÔ¢âcfeód%,8.B²q"uMosh¢ÑyÇÚõžäè’!çNKOÆ-P(:D˜,/ÑÿP 8ŠzæÀ›B’ó13•Ü9Möþ ?R.ž£F nTèL‹ªë0ʈ´…U¶P îpÈéJ~ ®~»IiâÞl¸‰e{AôÀØe%JqLÿx“Ñt~è5.ˆ$Ù ä¾ñ2<¢ ¢p×|…r%M¸í›Zmeê¢}µþb„Êrk;ÐO©°ö踣Vã‡bÀ ôŠžlóF¯¿=¨{/Òf™Tò±¶öU^¯(îÃb0âÏö;®5&+áLˆ¤*èÇ)ðoRóŒR¾Í&ø‹®?Ä·;“™6pUÎÿ(âLp/# ²¢•¬,q“ÏÎn‹R|KÐîü´ékû,ëóVÓÆ:­da1HÖS>ö…ŒñÎ8g‚ÈiÜêuM ƒäÜêvÍI–oðà""¥Ð8I˜ ¬Í^Ìò 6!Amà£LۺДè+cI;e`TLã5êPétT«r!õMî~â9BÚp.^ÑN(á_,€#µúÍ®)S¡ö϶¹Ë&íïÊ0µÝ9ðcomIH‰(ÑPVÈ€V¨Ûà¼mLeÕ‡&HR& ‰±Ù…ì”1­õÏPIkÑ 4BxDâW®]gWp†'9óºÑ‡ Ä$Õc z pÁÂ>»e="IÊÆ‘Jäñ‡¢1b6ñË ™·=ƒàÕ…÷+dè…t~⎠þ¦ÔïpÐo¾ÕšÏJ‡OÿeFä ´ŸOTnì*5)a38ÔÓ'ab5mÏå5\áðóbi‹€$Í8èüü¯ç)©)§ îLihW'Å1jq"hÁÊ[«»cfäb¦¡˜.9B[jä½h6bªç ‹Ï,O xa8³r y-"ŨUCó„öìp!§—6Ù7 É!4Ò0Õ€â–<:ó73^¥!òC§&)÷:£®õë(.˜YL­”ùñâ|N^9Z ©+/&#ÊÛ  Üìcl‘hDNŽZ}1ì?5x¸hD ­} ,½C³Gã‡É˜h)¦¹qëh5ËsÕXM.þÈ }›/[28pXiÛt„Ò'ⲑy ¶°Éb¯÷§‰ïViËô¾+¸ûânR5~ëY#õAZJ…Kɼέ€¥QtçÆe-žj”è"`§¦H™Ž(…§âã ªØIB-/ʼn™¬ÞÏ+'v2HôW*'W·aŽð#V È ÚŸ%2 J,¥ôy–릘µŽÇhÛM¯&Èñes(@—û/‹%GKT"95.Ï0©¨bFSkGZ‹J¸ol±®¢_xÛ“ÿ1†ÿ6uù­ôé=sHî*uRXÖ¹ÖMLהּƒoôŸ—øÈz€éµ9îÓi ÜÑÒõ¨DäÓfceŽ¡–˜óC„èXOuŒ=ç}I§'¬Š "€Æ ªìi#cꯚXM-ѳ*€ò¹§­Lë˜ò·¬¼ÌÑnèƒhbâ…{‡¦i®ï å}ðΫ™–9¶•wLc ÿZÊC“ •I.’fíùæø¢¯µ$BôëÕãš[XÕR¯5öã«k\Z°Þ™« •~ÖvŽüô] =™Oùc^Ná&š—•4{‹“4ÛŽ8•Q~a,Ÿa"¯~1G›†«b?8¡ÿ$r¯šË$Ø?Œl‚SÆ#œ•Nûó¬‰í‘§ZŸ.þ@„1šÜ*¨´¶­%F‘rg§8‡£ß‹ðÁWÔŒ)Xï¬ôÿZ$)æL°9Ä5±eˆ’¦~-a-ÔþMŽM Rtiu)Œ «’˜<¼_c«D$Ü.‘eZ,|i„Ÿé=¤îT¢«¡ žÉ>MQkè8Óœ²Øi¢ÂiÆX2%8ŒÌÎJ´åŽ4P²hj:ðdŽ9ˆÕ0¢ÍTqO£v ²G)‘5yÚÂKj ª<”Š&µpé5eŽxqî®È C,¹Úy¯¾#æxûø›…Rù®#fíéÍ<*VÚ¯6iÀNO·¶h.1½h.­NRI‡"_€¡657^Ž„0¯RÀ„j ‡0ÓÁ¦³×›³¼Ñ¦)í/%§÷Sm61Nãb.jI\ך…<Ñlb›¤EY$—jŸ|YØœ#¯’p¯Zx"9!ð:æÜ´T(ÅoÒHäOd>qA`®CH†ÞJ@ì¥Q¹ÿ%ÖZtÛscgþÙØ¿ˆnýÖ7oí[¬ªº r\V"œ^X ‘Â`0º;æÀ%Œñ ,ïK¢»zhû$½þ³30>jèM”» Q€X쪹üÓÄù«"±4ÝÀ?sG‚•Ýl Æé€˜_z|ÖÊ—VšjÒûJŒÑÕzkS"îÜ’V^z`Voqç?åÊLÉ¡ `°mx“öŒJ2!uí\ÕÀ¶$îÝbh0 x¢× ô”6É~­ äWŠY†  Ž¡gW)]'%ÌŽ¢t­"¥Ò2  Û¸%ç¸ì²Dø„É¡/#ÄÊ5øaVe‚Où€äòVsücÅ¢A2#ÞRý^)AÔª–?ÒtJu¬Y;§²~áÈã¬[•ÓzÁ–Z” „dìÆ4¦›)Æ’D ²‘2;ÉÁÙ$‡îëBtɲÀ÷†’QC9ƒ ]ù1ÔÌ­Óñƒ!œ:–¸ðÍÜ®ƒñ±ÙIæ´þ`«H'ãÎcp×ábî.2 »ræaQR—ŽD>H¼Wvš#G!ªäæ›·z’Ò7Ä,ݯ6¾²Œƒ^'¬­ÂˆLlä/,e•&ÆYW#H\D’3áô¥Õéßœ-Ôƒ6†CS¬T ïÁ€¶¶\qÆ$4à¥m‘<º{o0Xðxzá È ¢)ó!Èä#Y±ŽžãZÒùp³’›Øpì™3ôžÀì§úJDØŠ“Jnâ)¾7ÐjåÍxjNP»ZìªYe£ PGB‹Iz*%ç"p;îô¤‚lL´)ئ½å©Gu“VOÊòCFÕsIu»R HÄ‹~TT‚VGÑAH­¥„u\“¢v^k¸9±žÃ%òèÌԥ˸ŒªñöEIzŠHè±áAZ P9=~KèD˜’çEP dÖžê H£;Æ—¶ŠÈÚ»tZÕú½Û„?g‰ß¤K³ÊM,Õ ª„ 9Sô’ø”zK–r­ô§{뙩NP˜VdM'Ê)&'U€­›>á‰TÄör4¶ö˜<þT„rx«x¼Þ/1½ø»åU_Ûä«~Ęzþ¬‚·Dé~g/Œ9Òø±fãèIo¦!1CÃå®:B›{ ìXš³Aô¸aT\ˆ‡6›U†‘Ÿ£ì)ù]—dÆš©$‡6\C6»0€äjÒñ«Ã‡HŠ {¤u‹âwÊ*C, %žÕ‹=ã*5¶B‹÷/bÁ ³‹5¥‘‘ëºÇ``F…²Pæì4äN’OŠrÒˆ¯ª8Öaòòû¶®îÜ€cŒÒBYv‘þÚS ì÷çfL‘pœ‘l=©ØJ†[,”ÃW%Ę:hÊÀJ¥ ,¹-"¯Ah š5BŠkâ.ìβiÞpEs:ÓM8I ' $’,ßKNÞ`ý>¶S4wîùîs[ÈÙ8\õô¹r#1[Ф™+6c"m5©„T—¸u‘1€ó„ÀFhÌê 1wvùëÅ(K—Û¶ã®°À3À Oqó¦­‘Î8,RßÈKí†ä áæÆ¸` k©jZ=IµóݾìUqŒ·v@æ²5~k$¯_lŒ²Â€-Áö×x¡(§Ê™I ¥•$él‰Ü?*C• Ù¥èééÔBÉÀòè“ǙŖ€^E4²åìU6WKòTq Ì«[u°C^Æ¿m›¾'q¤Äìͨqk‘2/#ôÁ ¡eú&Ë´ñÙ\ŒZÔä Cp‚oçAî> Ùo:}Q¡ÅÂ1è ‘'Ph‘±M!ë¸qÈ£bK(e.Ÿò 7ȉ='ç6djaÿÀÀ-›íŒ€}´=·Ø@*{t¦pºBóà%+Ì'HãL÷W¦ nÜWõxÂ|&IÓºÝg4¦ií£®˜]ô.¯Õ~ÂÊ<{öD÷€<aøy`û)Hiñôÿªìcïfò¹‚ˆXÛý‘pŽ`å“:ÇÜûjwsj>8›#2‘5®\—§Š B|œº€¶©ZøŠÙëžºí­’ -é#ˆê,1CÃ9 z¿+ÕàÀ5Ú=ž ©ê½/ D B iá›:ˆ¸ý4È…ŽÊŒ³*D$±U•9Š:Ç¿Ëi¾j–ˆŠ=žc Y¸¼`7“Ÿ¸8ê Úî–Šæ'û»ñŒ’¼@Qf0Â۽ј&Ÿ[–€ Â2¸—˜ã) 1ŸÒx¦0ysî:Kú‡ã3à“ž¹;£S'¼{eÂ÷¿B¯qí4QØèæÂ#•9bršJ« [2²‹AÑê‹€‹³ºÖü×Њ˜‹D½ùD¹ñÌüÅc¥‹’—"[" =Í\—8B_ ŠNJð×—ŽŸ‘('‹÷;s93óE¬šõVü§Ëú‹™ÙGTlº|[>DÜŸQßVÑ‹?:$¤sh£GY1b¸,¼Ãp‡Ñ%vÇÃÓ3*Ç*šºr P÷LÛ¡"–4<¹[“]ÙBl©¦ÙÝÅZÛž2½#Õ¤[§ÖãæKe4MØí8p¢2§Û‹O­2d/b–Z¨+Ô·¨‹äšåÆbKѤRÌiWÌ‹›&C[¬•¿ÕU¿%ØDLs ÄÃ'…vÔÞ‰qŒ¡ÙÕƒ‹ÆÅa Ë Gcó bRœ§£tÚP ìÄG‡ÓõUˆ‹ÄµºKä™{ Ä#(B°¨xàKÅòSC³,¼Œ á‹6U˜à-4ìY–]Ò¾Á­Í³‚Kµ¸§¬^ Þ >“âg¥7ÜÓ*µU%aùØ'Ë2cðÖÙm½çõ‡ ~C+hÓ?—ˆÂœ+ó•4ßÕŽ‹ÅÐN˜œ<º'ŒYÒeb£7šü†5ä§'"–!왪Ò<ëE`ß[,L¥)6qd¦F ß J=4;lêñ·×ÛÖ²ä$!®¨ÂÙÖe%Ý%”á[~´2¼ˆä4`­aÌyD¶3Ò1Ñ.A¨Šþd•—“6 FZÁåiar1žd_8øÔªÿ³nN³TÐjM?Lpè¾¼]È"º‰*)îÁÑ,=4Yæ 릮¦9IëL%8†¿KÖåï ,]FY× ÂlX‰š2–-6 Ú¥Ü%$ïOËcëÑžÓ=O¦¼ÍáyÝ$¢ùÖ^®ÌfQíf,ŒþÕì‹ßR¬ýþN¶ô&®JSIÝ’q>kð[´D[NÁÕ4qÉÈ3bUIÖz:~lÙ°¹“ý¥¡«Æ)ÁìA†Æä »œJFâ ë’œÚ:”;‰ Ö¤ JcÖ!B )@£æ.!ØÑî°¿`m¢ÏÛm˜¡íæšå¶ÆS'. /(€oC]ceÐÅÞëe‘ëÇ Nó>‡ðãp²ýƒ–O5B¥æàH?†Ájû¤Y%—%ôÍ Ÿ %7ÁŽÌá†ìÄ~""é!´yĪRˆ’nIôï+º¤Û/MN1–Ï–«³Ž16VBm1?¹;çSú$Ò(ÙH¨É¡óÍÙË7Tmd±¸ä’MyÄÝ0. ùlÙ…®€‰‰HŽ4ãõÉ&©Ëånéa5Jñ×` M\+Ò$7+MòÞg´Ùa;œ±$¤Úâ äÜ4‡îV¥U —t*i½ó±2$Éj¬…œ‚ލö’ì>]Ò1âÙrøì¨u=ž" ,Ý~h¨‹}Ø I³*ÓeëRYôTŽ"êìÓâ]1¤DG wöËÉŸµœeÆ[€3}ð7gÄ‹–F‡¸Þš¢kÝöœò~øx÷BþQû6’3¤®ˆ4FAþ!fNÜÙî9 Údº=žƒ¹q<µ'âwOŒ´’€H3ΛØ¾%¦N…„]Ó•nŒÆ%Û Gômò¡I¾Iƒ”D-àãq2RJ/¤ÃÇ’é7‘‡î3sp­ÝÓváv®‘lIŽ8št¨×ÚTCŸ"Kl¤"b¸–ç%kCÀÖ•Êù£,«†Ú²ÕˆÀZˆ¦âþZ#ש6k-{!^ëzxdDéX§­_.([Xà$oh0}Gõ:C…•óà†Çæk–o雬ÖEóôË]¶5x¿z‹C»nsˆþý‚`ÀD¡Ï¸„8üŠâÑGäúŽC#I ÿ Ia€9D2"’¿£Q©@ 3Dp Tæ5,–Ï_Ñ`<1ïC‘LÀÑÀ,Š5 }Si(“æ¥FŸ?¡Q*T KbP©"? –Ìi¯ªD*w"¶?âSlb‘ ·zD¶+D¬óäŽ"ŒUáÖYD*1f¦Æ§ ªÞ"°@¥P‹®R u|gm0hÄ2‘|B³0+¬2_–ÝaSh•ÖýM·Ê40Š’cXËeìòÙ'…KƒLn¹ Öm …eùÐØv.c(‘T0òX͆vëpëm³+‚xöë­Ê9]’ãô’-w3™Y~Ùïpˆ–êQ¼íú£,êDߤÈKä!†Ô8êÓŸíZ6Ž¿z º$ ‹Ø«3i^ˆ:NœB}¥ DPŒALñºÀ[€ jÈ’³@ v‡FNâ$“¥ ²›;),PC°“µîú‡C@"0‰+Ès¹$€ L”?’œƒ>Ž«Á&ª#å ‰"K¢h£š„KN¼<ǰ¼a4ºˆlª$ªãVŒ1ïòª¤,(ãÏ.€1»Â.hD¸Ú€g¥ º¦*b› J‘ò .(£ø£?,ë„ÓR!7ÐÓ*<ŠDñB–¦Ô›äŒ>”XPžuºWÎï"[6¼¨<•GO‡ëa×@%c¼l{„0bK»‹ÊJ{ZÍ8˜¾•!ö‘(jK_$Hcø³¾ÝvðÌ·ý£JbÒJΚQ&-•…¶ÜMìg;vÓU_ËR¸\(2m$-eØ·IÈB‘x³±¢ê\nzTðµH&7_ß'ýQhØŠŸ*K׿BÀÀ)ž9Ž TÙù{Eó¡rb`=,«@ ¬…Cˆ$%á3>8¯Ãà$|ÓIù|>Ù†bË帢8Œ?ÓÑý˜Ùùæghè‘ –©Ã>æ/÷£ NN FÎ̱|З`µÝµ‡NHsHº©¤ç~뺶õ˜ßuåýÞ€ÇDçüj)©ŠmlµíbŠ> Mùʪ€È¢J1ÊÙÉE¨hçíæ”soFñ¦ NW%Àïý}žê›sÇ\cçîJ•K˜#ꦻˆÂ|O: ¡Ÿ´ÆC¥o`Ö¨Ïгȯv&2‹­¯°1Š ¢Þ®T¬èc'KªHÔŠº¬í“¢ŠqÇï…T.­u4·Ý]"l8¤¡ ÕrD‘Þ!h!Î4ƒžøÈ¢¦~Ï*¬‡„e׳hD¥%)Aôá"˜o'ö Á'Â|œ[!^й7¥×\ gñ«¸(™I…,`2½"êïÒÃ"„Êìç6ÑøD‰±]Ä´¡Ô­bJü…p=‘8w~b ÓL!Üz€èÄU`s!=N]±?ÇÚLTÄ?Šäñ»Õ<˜]²íLQŒ?r@¨U3\é@Š$øØTˆb¡@¥5'»ÕK•¢\tÏEtÃ'kÀ­qŒ ˆ&©ÝUòOWÑJ’U,Éøo°l*g†H˜4vîñ7Çni‘¬qzÉY)"PÚ×ú:d =ÈN¾ËipP~+ã>Š2#*%L™˜X2YÛKä;©)¦»¦bÈUô!Ž"×ԥEïYì²éÌC¥6T%žiŒï‰,ºg8È¿€+e;03Åå‘Eñ+¡æC$ lГE (ÄiLK”¡Œ¯"ËJ žž&kÉ©ì¼X¯Bâ[;¤i˜~ž`Kƒ„”Ò(¢Ý组<†2Ådès§:hŽ*M†8ÆeAU€1`‰"©~?â+M,ô­“8šM”‘çr$ùŒðÙ‘©î:>(@à—Á1Œ rÁäLêL)¥Õ2ɨÖH©!’€¤FÕKdCvð*‹Á'ûU ”v’ÍvÁ)"ÿ9Ó誾”œZö9ÉLMë¡a(³H÷"€àV=mŽYÃÃÚÞ³=%Grž' áK€„TK€àA*¤Àˆ–ËKûYdˆÿr–­ºŸÅBi˜Hpþ=”_^¥¾©´ÙÚç‹p^4içòœA|•ž³†”¯!2;ûÊÇ 0•Ä0 KÄ\u’û…X'Y³²dd¥±±P:76Ç€½éüŠOB~Ež±g«jjŠÏ¤FömÃ8FílšGbíXÃ4˜C Û©k]ä"tQ òÍ^Tle­GQÇÙK!üä‡ÔËqh{5ÇØ¡±Suòñ¯Èqõ>¢Siµ¡‰,üa@üœ'Ê%QAýLˆá‘T-jE„n‹Ú ¥»%´šÀÉPq¥Bd­„ž³ “!'¦/·JêFj]U¬>%d‹2 t¼T*¸ˆ[…Øxrx”Ÿ(ëT>í>?Ÿ“7Vß«¦tB îã3@ÉÄ Y’ ÚRá«oÛ)ß"À†Ôé‘f«ýŠ£„Ü>MÒ—“ÔÉT®Âü½vo,ë#.ô¡;–ž76ÜcéÇm'ÔZq9¢2|S{1D¥À *é[sãFSŽ™›j²3œ…¾±c„jµýxà´YT0ž&æß éFWË a£zAøøÁóQŠdcýþ<1qv&[Ôœ5-ÂÍL¼)ˆû]@=°!ËD'9—ˆzc/£Cð$QºÖ-×ÔùZ(Zrx¤Àû¯nžÜ®Í?•*Ã*·çL;W†P.lÖŽsdÒ$QŒ=mÖ*‘\)h5ùôJÉZbö:`„5‘šUáÕ‚ öb-[•µVE¼˜Œ®Žü—× zsŒ¾?ɰÖíÑþ?õI!s³€f²ˆ‹.ÌÔUl¥cž(½l)SH1VînŸ.¡Ì Hä Mg,™0ý‹01*Üon·—±HÓô¶Ó™‚Cš4¦Ýæo¶ÉX¾†LÉi¤H¤1õɼjmsƒèžX'Ýc(¤ÍL%¹ë*#Uô¬`ȤWW¿ã<"BYDëtÌ¡‘”J̘vU¼™ºM³úÍ´ -aí¾ùR¯ÑÇlûЧ*–I\7sx5ˆB廥%´ÿ#{àE ¸ú#N<óF€$ª¶u"ªL‡6p+\i£Æä΢N$g뎸áöa@ BÚ—~B.L±… .¯n°*>ÐÄx§«ª¸Ç‚ÀØýˆg®éÆ‹®æÉf¼æfŽvìÔÕëg:MIÄŽ¤n*¯VÊBaèvÚÆLºGÚ~…X ÈÀOÂr^ÇÌj¯â>ƒ¸üBŒHªžìäÔ,åL¦þÊHˆ¢DTb@VŠHðCüéhàzM:ĆÄ$#”“%vÓï*ÿM¨±‡,0*09Šz{~· æ£Hܨ~ˆ<áìðÜ.HîáüH®@Iâ[ sj”ä$ž?„Jå0öæ, _„eæâBS¸îM¦õJL§h Óéôe$×£èqiÔ­FbžÄ„£Åฦ j` xmp%D:IïÈwå H¬Âj îfêì†ÞoQªH”kŽ^þI¹£83°ªCøŒífšÁ¢šô°T÷à XêåÊÆfˆ¸¨€ÂŽ:ƒt"†H¯‹­¥ÃÈâдÐËý"ÛƒVuçjÇf¾ÈÃ.Eì`4ŽK‹ÚðªÇÚäÚ‘èž­pë"‡oR9ˆ®‘*ln«ü®G&¸«Ègg¤«Í*Å€\ÍÃ0Výr‚>; hÏðhD²fà(&v‡Äj‰ åêvìnË´ËP4Ùð€_‘y ždpþpKÆ¢°FOà9ÉœgcHôã ÔbÃJ”ªe„ð" Üjh/M$""V‰þËqªÜ#¾ógX÷†þÆDÔÖ«ì%D$TÂüNpP¯±ª+í®À­Ö *NÖÐj›êÜVŽú”*>u *BˆŠêÊßÈþ]’\N§în½)ˆâ!DŠ¡!³Eèxf¥P<¢GÎ'Äe3¬²kë¹Ì4¡‚8Þïv½ð²¼Ê¸á*PÇRöhìèæñ`,é”vƒæ_‰â•®qÆBõó7§6^Í2ÙaøH©úg¬Ü¯/0ÍM-òdgo$¸B€(Ë J6wtôRi:Q³"òrñT7#:_ >%†y~j( ’o°æ2ñê-XdL¤±Ì$ ¥"ÁþH¥nqn‡ä«'«ss *‡5“êÂilÎŽ²6’FF據1Zï+ k„Gps3P^Fðc“ÑEŒw(ô #†hWÎÆÀi'3#Ã3Îv¢4ü‹M‘ާ®–&ÅŽ_í$Ϊ}¨ȮܦhgR÷Q5k8«ˆO1®2¤…ðµ&ô¾´@E@üëúdÍç@CÈÑeBÄòù$Plâ¤qg ¦ízŽ®²Ôk¡(ÉØ*H¸ê.ÎÐCä&È ÒÓá'Qq;@?ÅL•¨®É•Š)4ÕM;u<‡.héèÓ ƒ˜QU$±Q‹‡¡JK}R }«´aëf†Ó8ñ%åV¨âÍR°C¬â&Ðgor•ÉÀôg´&eävêŽåfo-Ñâjfä, Ò`--­×<%ùd~DO¼©”;Z®N*.M2F0L°ìK‘.¦;BÕY!.BØ­[GN4dÄ%ÿZjˆçîZ?–ÐÇ~úãf--*–6^ã0ÏbHèêFFó¬ªBt!CIn-Pii⋈ÏCÍaÃùâ ásW, úõrç35ŒP¦*Wuñ=óÈúãüÍH[b§o\¿T5 ð –zÄËaà NÆÁGܰˆþÅírø;kÝP¦pÙ²Ü4UVîÊ©­rþïèè‡#Ç¥šJåÑTŠWe Hl8Â&ÈžOQS·Skä11lsA§®üóù4³—Vð‰çÄ6S_eüzN/ð/÷8´Ëq×gJê—`z•¹LÑRõ.` ä ô%ü}ÓsvÑå[²t%I¬æ‹Ò$¯A4÷7¶9h¢=cH3§¿‘uBª­Cë|æê+"'j´ÏJÀÎÖˆ9<ýõ [xÀ½Ê‚þQnÑmB*Eh™8¹!8"|qT zb¥g/d5o@ÊJ¿E²ÿMq%uÒö±'-3%˜3¨\ÔÊØyp:ŽAðïŒMuÒ¯‹ðàã*%ƒÁûvµ>QvQd»¤âþËM†qú Iò$ ç—h‘m/)¡n›õ„±L¤ïqÿ¹¬!Kã.ÃgÆCšM)°XØãVrØ© øc:!ô1ðÖ·øh'Ó%Lh²†yö¢³2×ë¸õ.A* )j|L¦Òø$á]"ê{xIO6SZÇNB!S—ùœU­ fºó”þEÙéQoÀ Ik “£Òv2﵄ñ^QwB©j‹…•"q+¤•óXm ºþ27ªËV¤ eu5àoαÈBÖäà9/ ‚Cüö2°ž5Ò¹­óUÐiC÷j0„€‹"¡"@tC¬ž0õÊi±BJ± ’—xd̰ˆÿUaù²<âçpR€€B à3ÍDäÔ21¹Gç®^Ò«”ÏQÈ®köÄj¦lge¹]'Ÿ1ºc÷xd%¹¦b1Èèù&y˜L¯¼“Påxѧ²ðÓ«xµrïOùÁoqc´Sü±k¹‹f¾b¡:öÌе?ó®‹Œ‘ØóŒÆO`™¥5í¸>‹›°¯æ?éW¾²Fèš';e›1€™&— ¼%CïÏóö*HcŠ¿|L»k‚'®âlœ$ˆ‘û?a%01ú¬ÉìJÅÄb)¦ùš¿X~¼R¨Ø%£•Ñžï HiÅ9ƒÀXô5wšôiô™É‘9[8\9û`j«]ÃŽ—3@åvZ!Ã#TA•¸Õl¸[VŘ(i(JÅBüQyQ‹5‘©È±L-òLGs úº©Q—Ñ»¹(é€ÜùäãšsY%+îg.//®ª ÷zÝ2aöã×[ iã:ÏyÅ Îí{ÙÐäKVxa~$âß³ÇëþK"Üh #“ø#[?_‘æîhn¸g_®!Ê=ÅøŸyñ2÷™!Ý1FSTõ79rîäb,Ôúò¹¹¸ìñTžÃH”pí¸ ½¾æGÓx9àŒšyà ïFM(’¸N&1‰Ø;ºÜ³^_*ù1çÿ]Yxd/ÏË[ÿ…ëþý¸ñ<‚àb†Õaôi±(Ü·k:ðÑÚýGÞÄÙmŒùæ'ÎÜß{^•FI[²ú{6òzO@wöaÏõ"ÛªŒ­,ÕÚÚb ƒo”ƒ’nÂÉŒ ]. Èt‚JÂü?à€(0…a'ä0þ‰?b‘'ð1 Å#Ø0 !‚?ãð‰4ž?“HåHÀMLÀsWÔÞ9—Ä$qÈ„Z-š€åpX48I|Ræï¨Ô¾9&¡Î`Ñü:y‹D) ªôYóa¨E#R94j–ø¡ÌÀÑgݾ›¶X_2h´¾5¨ÂaR;¤@´à@ò×üB5“]$Ô)¬’Â-ïº G/‘Ù`‘̈U'Ja‘huÞ3 Èâ ­¦ÙU³Ø¥š´k@: ãA ¢Ë$ÑØ¥^.Œhdò8µóÉ€.‘üMýYï¶WÚ×c™2™óæ·h• •ÞuÊš//Œ=>‘l'´¤ömŸ¹ÿzŽ#K;¼®Œû|æ+hcäŒ9Èš(©&°Sòƒ¡ æ$j^½6ê0¡¢Î>©¬rˆ„%íó*ýBîÛ% € èÍ ‰3Öî"Nn†?ƒ¦¦ÃLz«ÆÑ€*~‰!ÉÚ(kŒ®&éz†¡žòÓªKc+Ekzä™­(ÔJ›³‰bB0 ÊÉ2L˜+ÀSŒ~¾ ŒÛ£ ôú9Ž›°ì¸M´Ã#‰V–±¨3.#Œ"Ó;B Òû0,5Ý·¨D8 Ò8º-iœ]E ÑS(·§HÃN‰D••@½´h3þê,.¹ý\2©î‚WÈ$΃2¯RY(‚8‡RÕÂ,Ï"T Â5Ë{˜´)nÕ–(l‚$Ã?Nœ]HMJjoUHÄ&æ8tÝ?Ûçó}?€2sRËGº5¬(ä? ‚g:Kö»J‰%ô‚Ü·ÉxAýn-‹JF¤,­$À£ìeá€Ý9f¡0 }VQ#á¸4öT⢈‚_0 X­j¶Ù´7°Ïã?“C9ÒI"?xí,é·ÍòGsºY6ƒiÉEÏÕ`*ÙЬ…P‰ï@áèâØÌç)eÉXÆ9ëy)¹{—"ã¹5á¢Åa^KÂ-µ7”ƒ+diû‡BšpE;çõëµ€—•Ý#eHü»n1k ª†.ŠB’ä•5ÄPÙT'H,sËEŸ­Œ›¥D ®¥B%ñ3jư*Ãy@P+Ô‰6ú¦öó{ [êÓÀ¿\-º›&ø¢“«¢­ I6`·ËÁýÎ"™±ì0˜a÷N^\„cpÑ÷?¹ LªÙ£vçîúêè7D†MYO\›ÒØâƒbªkekq!4ª>Ž cfýƪ"ɑ٢8 $ô3ò¦‡‡ûë&l˜¿¹ç¨>ØRÒ=ÍÚâÂfÈY #… ®bØœ xÖ†°ó“Uôì¡ikh¬²(eO"X#ëèÄ¥¢¡YZ I$½n&Ž~ŽÒb2Í”0û[;+T¨J)!4\H†µ.©6j–*­v8„ÓºHrÜQ6'š°û)X€ à&¤DA LC®dæ=”²|)\š«V|aÒ€ü†ä8~;XtFà±=zêdÂ’kÞ!5rà%æ‘Ò>aœkÅ‘/öÄzÓÁs,Db ŸÖØ‘ä?äøArzÍã(u0©é$uRàåqÆró/5ç¥Û†˜®í-)Ý‚8c‡¡¬'bÛŒRRÐmÁˆ쌬’nÂrªò„àøþ)©%³Â F ô"ϰÑE÷¢?šãu(œ¶ÈØŽ ‚7‹<ð@ØÒ¬›úõtSéÎwèßåá'jSp¶$†B§|ù&oüŠO¥r>]‘º‰í<ìNH亀!¦ E²iƒ†—Z¨ˆ¬“R!úö\  NŠ>úÒqHé$à5Gd°ý%ïlëDG¯[ę̂3yŸù4GÌ©Mo¬¥H(8fŠ"}­ÉÕ¶&RˆP|´ˆÇ¬ÏÆÓ+"«4ý%¦%4ÉJ«‹žoàŠUzÑ›q-ƒÖÅ3 0*hÿ‚urƒyØÒŒ‹’ä‘Ó2+ìãpÓ`Sù#+ê¶S§½Æ ‡$EžEÔÝ.œÆ.ó—ÃÇBnÑDi7œ í°Ê‚m?Eä¨%™wÀ1íµ*8Ð\˜tÌG·ÕôFŠmE®=‡Â` ÂÈ••°IO¬ªÖ€W÷7@%‘ºªðž¹âŠfô.dB’7õp·*†3ç0Åw#3fý»³qWDXµÌ˨oj(ìëÀðrfˆ[ÖBõFG–¿IÀï ºåk5¾tOúøÊåòá3ÀK·¥×dãÞ¼,&sq9Й:ãqæ ¨ñ¢)‘ŒßCŸtè‚Qiˆd»‹îÙ-¦N{3:;G lýb¤5,$?PM4‰­¬ÅwdH³Ã[T05ËVVz½…,ýW¢0~’x¼5€bB‡=ÝÚÉ{ñ‡5šÛ˜YÔ€ë,Ê  ž™5‡ÄJë<¢ In‘S©âÜVWE°ÇÕ«;E)È’©õãÆ&êè6aAÙÒò®T®Íb+κڄF‹íĆ`Ü~è+)º?Sæi=Œ–åÜ` ã×k géMÁ©É }H ·˜ÙsY5óãq€’v§™ ¶ègDßõ&ÝÄ –\ë¸ð¦¼ZÐ{:g%p½vç‹ä½}5üÀKd(¶À3¥õrc%ä˜v£g® —‘Š{!úin[ê¿0$›™Ã¾a£›lý¦n%$­Ör»MñrÑÿsv=¨µv(zÒ o¢þN–î 2i+Sæ·’Ê*ƒšÛ˜MÍÖµŠFLñI½Ñšƒ‰­ÅÃ:_2y §5395-}a—«EÉ­v#x~1ËmSˆMí±YOdìê` m'Iô×z`àiùw3ì\ t8g‹‰ç¿E¡:FÕ •¸®õ²'G3Ãì"Ù-"œ²>ªâ•Bã~»©#K·×kDv±ƒã=鯛LÃS9}¬Šæ½ÂÔ'˜ì,ó¨.‚Èš9ÃJ›!9¡ƒd*“*Cr¬ú;²_q¾©ÚÁ)ø¸* jÒ%(Àž8ü/Ž7c¤Ž´! ù¥ú¿D–9•“¢"¹ãr?óº®Ãž•ëè¢ðš‹ Â4¯?ÛRˆ3Ua½‹xü9ºG:Š®áÙú¦|,YŽÂt5< ˜ê‹ÀÛF 9%é¡($8#=L ­Czž™?6S'€"H²`º.Á̯u:¬šù.‚J#r*46˜àõªÛþ´ÓÈûÃÄ€–±ZZÀùÏ7”N3} ²>J˜ð…*û¾¯{6£ºD.ÁB)òè)¸ð²Y=‹&Y # ¨í84§| )øS²´47,2Ò*e»à} df½¹Ø5JÀ苪,·Ó^A±%*Á9 í\œà< Óä.¿b§¸¨„ "q4õ“ÃnƒÀŒ yGÃï”èõ´ó¨»0†ئÇã'¡¥ÃCݱ‹È‹ÂEÉú«A¼tUB“ÂÄ543²¡PÓ†¹Âǧ’—,}©™¡è·”äD#é¤B+›vBº‰‹{@œóG3M4Tɦ)z½Jè59ô¼B:Ý/€sD"”;ºÐàý2pÝ-Yã±â;K 2»\Êûè³Ä7¡Êë É±á©1#ú! µ³í À“ éµÌx›´b?K®­IFµúð­›u‹„T‘wš4D›…¯ ›ÅÂÉ1ŽÄ»²SÁ3Y)»ýÛ§äÌ“ªèÃ"ù¦’É-ù¾¢ ÓD"ÅS L¿Ë9 *’4Ø*ËŒš"¶âŸ IŒ )Ƶ:~ÌQ•²Ù[Ÿ¢’AëIÁjMªªoA(}E#ÃÇ#º*e¾Â+,D¡¢3à ã`¿ª¢ œ8”mKy‡Æëø­:¡­[×K œßÄ{MŠt²Â²›£&-¨( ,$•©21íÖ¿“©v|þ¡¬(¾sT?Ô…€+i¾Zº·4ï·ô¯Zü0 |¨Pø½’(Îü&‘Áª)P|é2¡ŽœÄ!Êá0óAš‘º˜õÐüõ%“`Eùn;##« yÒ¯”_9ó9¸Ã´Ï«õ p…û,˜ £DÉ9z½©©8ÚÏRƒ­®sÀ#£bH¨þ5›#¬£!Å 6à“Jw޶Y¯Y ‚"Û ¥™=Ù¬4d ó—ÒYЦÏÚ;6u’ÂÁºZtÑ›l'Q꺒£ÊF¯1\)å–±”Ó–LÕs'AMÁ@ƒØá¡ª’\Wªc²DLkgÐci½‰9Ìf¡úõ KSߥaÆKC/‹MRm«,Ô‡ºÝVc< NSr&*»NôE+dÁ•ÉT±ŽF FÒ3¨ZƒW€EmE ß(ÜT!ɺ=ñùac Ä#‡7ETP„+]=Ôå)TÕ*3¾5S Õ›ãNÕÜ”UžE$·%íV›Má›r",˜¾7À«^2&DÔ; *bÝQã=K:Ô ® é$¡[žº<Â=mßšp+òw;öG¯µáü½F3N)ú¤«ßãoLúá»-#ØÑ­20@Ãlç›êù5Íñ¬ž(Ò+àc_íï,2@G;ŸÏ‰¡:M©šN>ôíZÓX²Ý;št-/®hÂ9Þe(Áf ˜Ÿ˜¢.^JU¹‹à±U;SÃÆÖ_ÄòËO¤Üž¹Š‰5ÿ·!]Ù!±AyƼù÷-Xø*ÆK±-&Ða”°[ M&ãK–IàÉÑg17‰µÚ¸LFD~êï"21ÄÔ~Ç!Ñ£ð%í,ô¤‘ ]ªr¹´2Ñ_©ë ›·ìuœ ¢È#CIÑð6󄢩–â~9uu¶á®®¨ÂDˆÅ†[è}Ô$m«‚ÎÕœØh~ék –L¨ÅCÈÐì\ÃÍèÒz¿¤hœnÛÒ#;[bxíÎcÊY1.½JùhÃ>,*6ÖÔXœñ}H)ä¸ÀÈè¼R;-VR›£v[yØK¯ ±]©óÆÜÑÕNº•®<0ôʹ’ìAßÐæ-]lcäU_½ãÁ¾Ù.¯æ5h,fIÁÜ™ãÕŽÁñ¶ÈÉ¿›^Ã|§~%ˆÄ¾^9Áä>SÞfã<›;1›s¿HÛo>©kîª<N‘Y–]¤-ê:äî ŸÔ44.ã ‹ ŠÒŽSä~Ô‹<êÒ×çTsô“Á¢s SÖ\ÕyŽ™LmCÍÇE›º0=1H›”ciÒÂ ð”€ø&? G*¿9*Âæ‰Žm ª›ªð¤þ­2ïj‰{¹·bYÒ!‘ßIN‘rH»;Eu&a^>0õàg~ózò}q ÷9Œz¸EõòSÎ{ØâI÷=ûé ½(ŠKÚêCnƒîR@ºgT‰·›Íä­ÙmÃáyéß2qÑuظòïG ¦6޴Ф*² =My¤[‘•à´ç &«0ø_9ÏjìM:`Xƒר¢,}pE׈ÆÄD×£G$„j`±"ÏC·_¬5µ¨©Ò'kC6r¦âð7ÿs‡í¿‹¬À m`6 3c4ÑàB¦6/nìÐ_ÅWº—«~™É;F-]B¶¼¿ ãÊì/ÃggQ”åçIS5Îí耦c•CëYPï™°å$k;<»#r£Ú‡ îÜ7"McB0¢ùy2sÔæ•?€mÄtÄœ3°ÔÇ/m&UúNCb¥ ¼½"[‚YòW¯kVR¿x¾*zîkŒ/ÊÔßsÜïMBeçÌ7ÄÁyÖl‚ØzS®7+}¦³ÒðnB ïx{ÔºàGÑãê°€?`@  „áO¨dÿˆB¯È£ú,ŒC¸ö ÿ‡C£ñgôŽ/Š?!@8ì~%$”Çãò¸0W!‚GÀS¹ä’ú‡M Ϻ$Jk•ÏÀÔº#îy+|ÔA58üvI$‡KâÒgô` $ªÀ£õètÖyM Â¬°i]Z-Sc {¥6ŽÇf²¹$­ïà_;X]‡V ³X4’ynZ@sØ´Ö¹^žOëÓ[BžMdQ Py”«èßóZõ 2Ï¡–IÅzS$ÆA¶ù^bwƒ|c§qøtò½ש²g7M¯Gèð+l ¥§ÊáQùN«rºå4ˆVŠsž‚_"ÔÙ\J›$¥¡Ò™LóU Ä§“†Ú(Ž¿IÚ¢|µÎRˆð¾ˆ¢½kÒ Ð·MƒpƢ̓ܢ8®úŒ+Ž"pÉ:gë$B(Ÿª`Kºë¢Î20ÈD/‚–é/°ßO Û²°‹’Œ:§ëø´ðÓb­¢ ã⼬PØÏ P€Ô@mjüI«Â¦«ªvó$1 ’%­ÛÐ/hS²í,(ô“/Ƴr@‚2Âw¸@â§ìï¯çºá¢IûzŒ*ôK6¡Ã [¤¡‰"ï)È­+‘€òRÎG  ! 1"š³'iûP’E3$£;ÔJ%8GQÄÚÖ# D<KÀ¼ŽÃ æŠ>ÔuI_E‰* ”Ñ` †ž<.‡'隉J©B*‹<)­MVW¢k+°XõÏÚ(»! ããM­’½W,Î-,?Zˆú›-Ñ© \\ RVèQ³ã."Šúí¢ü™9%jânôÍIÚ›m×HÃâ‡)¯b’)«†(×LIƒþXsLvŠ%sZ>à6€ɇ´Ò5pÞ¶=#) Vu!ͶbéW«Œ¶ƒ@iªµcHÍCnŸ“+yˆ€YèÒ¢RÅ£7Ç9%Úâhcã”§mt>”­"x[•½¤Âlen¯;‹¸Š[(2~‡8òDçà:FÎÒB»4^p@o˜`à…§ñ[²03HÂ%{(ŽŽ±§[öô}u¢›šT…o'ô.§'| øò $ÀÝÏ)^Y O Ũ™>£HÝGÀJŸ:k@  ~ñ_+k’²Yw¬ê$‡˜Y,,‡IͰrlµ'~ZŽÙ(êSâÜ©ÞgÙ"ÁxLh·¬ï«š¬mµ¸L±µIüL~5h}üìNôßÍY~Š9`€ÞÁß9 8f?–»Uï°Ø=D$àI ‹^J9<©5T?XáEig‰ç’­Sƒé|-EõF6‹aJXa˹9ÔRç û-$ˆámĤfHc“rïä#ˆrFIÃÖPà<¸@Þ“«" ÁÅ’˜…TòL#ï½ò®MÙñ+Íxº‚¢BhB†D‚+#`a] P0 Ƨ®Û²K‰~9¥) ¢·JNyî;úWJÐ!–˜W«²à‰mL“ÄÅò¬ÚܰœÔ|QýP¤5®ŒB+è+ŽÚ¡Â xHéMOma€øòÂÙ¨y£îVº¤|WÂRFHÕ@Úkšq+%%Á²’‘  ƒð)N§±4›Ò½&¥È'üè—K6‰å343ŽÉ…0¤uÔ­B¢žS›ð4™<3Jòúuƒ Á´>ˆº,ý™òt ÄtØÙCP—«˜~9é@©aóa†† ð¨–ÂäÜ2I©FY°?’Z$–ñ8²em9‰üÞŒÑZp“)¶QÐ Œ‹(Š::*_å˜ÿ‚Íí«´¤ÕûMx+‘^Ê1ôl£Üi|ìÍ!¸µ^O ƒÖ—«Ìƒ3Ã`O)QœµR?ª÷LÃg`›ê}G©5 Œ’8¦fª1F—=@¨K\(†ì¸jíCÚÈýD lÒ®TblŠTùËúRB!èúŠmL" ÌäÔ߀ >;hxnfûîüMÄä–‹¢˜– ¢"v¦%ªôc^)ž[çg3¦fsõ%¹¾ÅcG‘É ›ºJÖìIp8~½Å”äSeM`q‰ ƒR9ôß¡M¿¸Å̺(i®ëŒœ Ì»zì=‘JìŽð ©‹ðœ,©A'Ñ?©›`ìŒfzQ¡'¸[¬î Ãm;ô0É(F—\•-9Í‚Ûb 2ÈÝX°Q½ºÆõZŃiÆJ(§2iÓÌ…f£ý¸’y€* ¥€ ºhâA ôÙŒÊÞZÌ[OEñL)9KA†ZŸ}©Ñ­[á©NHqÀgÀ»¬ZèSlÌv°ÂŸÒÕzj¤ÁŒ“FBf™+µ-nÀø³ Õ39S?nTasZüU¨°í•쩽ʸƒS”C>atNt)aÅáZ»ÑASSõ@œÐxüý'åÂñKÕuqÌiÍ~/²:õÎù®™°óÈ8‡g30ªOý"܆•,ýUóª`ô}:\+à‰4Ó™4°çdA!Zy8[Vÿ%Âmu.¶‚ïDßCñëWR¶niî’mmkî ¤¹«©µÀÜ7×)ó‹°à)O=§š!JÀÔ~˜ÑÈÚXHoZã7âÝ ßS N:I`ãÕLFIÓjŒÍ9iò•15]%1J¹@tÄzpÒ$xjC÷sÏ)Ñ٨จúLDJå\—¸@'|¨ê$âû´~ÿÆ%Þ¹¿g5ù¯‹jóhÑøÉªóÁLî@¾{½‡ä%# UqˇL©àÁß°pw˜ ÊŠ¯¹OíåûïcÔI5>1VšŒFJOÃéWH©jGnÒ·W¼Õ6NUéì^h3xÕR)^/¼mP:cÃE&{òb%´$Q×ôXð?³"ä»´;°$g8Œ)<8´„Y¤¬*»·ŠËÜkÞn[\MÌ’Ki¨[o¬}ú]3óE¯â&²÷.šÜû®÷•´wr0ku¿ÑäÛ‚³5i=ôëºÒQòÉ,p$ƒ]ôRù»5sLëáÒ8gÊTw.½¿N:¤øb€Ý4 šÕqùâ‚äõíÊKOï~ udø¬±˜Òö¬°>Xiv'„<úÍZ)kÖëB–™Jâ‘OŽö̉š¬‚B’j<\”ÖŒ^¨KLK”·Å¥Zc§§ôšã¾ð @Üe^S.býÅÐ0Úc€§$ò–MÆVî|¸ÇB%oœ*oþ˜Hh'ìXmøÎ%0e¢Vp‹Š‚à5ä”. å.H-’kv¹"@o¨¥áö^ˆ4ƒ FNF(‰vùOZ‰$l·¤ÏL̰dÄpæ ±¢ z/Úè.¼"Œ:"NÄ+JÜ@ r¼)o ;H#½eÅJì°­ÚîPàÌ«ˆÚ¸5PÌðb)fLû⣠)R•#€!Äü§¤ÄHk89 žp¦œˆÈ0\ R÷væQ+˾.ÈFɾäÆÜœÌw!þ÷KÐ_FdÆÈҫ鬔Ê<ÛÌÊßml¦úHp\OÞ#dÀѬ“ŠtôêÆFÍ»!R¡7O"'e“>j|VðRHÀO¸Ô6Üæ‘€ 9 #t*_9¯^§!åEìÈó«Ä|ñÆN0*S´ŠêUðnO*:1‘á¨S ‚Ÿ¤Ú²­8F(MsâW$‚W/ô¡ëJqi¢j¦nÊ;C$òÒgпBlÔX«¤Mc‘;I{$°…¤Àq(22þï4îÉ8€±ø)kîÔp:zÒÊH"½JaêU*Fqiv¬Ãjo£$ƒä×àç<<,Âw°©½§(qÂÁ“V»såÛr· Óé%êZmmÕíÚ'€°o€ØgA#è$çáü‰©zU§OÆ`%!»W/x§B$Y (dµ£&¢€þpÚbE'†™¨øVëÖþLÌGUJPS AM b„tïIĆéÅR´I³¤¶•!-LHjLÖó©\禊25Ž.DõNR9 .GU1XÑòþݳˆÎ)š|SOÔ#-åÉ^ư‚~ʵô¾E¨ÌºoLüÖ!ôdÒVá²ÊüOï2n$(Búµ÷ÎÜ7,G a÷&Ð_]°Ù_ÇJÕŠ‚ôâ—KGÌ œÑ LòËéÄm³lºeÞýb-%0“J«.ä2R‘Búbél膳ÕY#É,ú§ÚÖd˜‰tÑ_F) ÎŒxõŒœÏ—9ã æ°¯ŒºM•âèP$íe$CdÃw€ ‰u+Q¥Kë”å‰pâÓ:[é+ðÏÐ@†‹@öóCéB˜:#ë´È2ºöb ,¶”L¢åÄ*qs!2”6Áf1³RQ4@‰¯ïƒXË<+ÑÂâ"èar [•™K³Ëž**6Úr|€°ühWr¯p¤…+Äæ(L4«T ‘°s.ÙУ¾¾ôY]âdŠ÷•dFöø¹g ˜H0§=hUîeöZª{Z¯^m´¢@`}ñ_—΄×\! ¾Äòß?eq¶Tò #dÚØTàGSŽ·HÌ2 ‘XO.bHD­°¾õ•ªbÿ÷6©ˆý;²¥·fFrgQ|\…úp°lƒ¤«4xɇ‡4 ¡[%+8ÿë”»¨ô|èšì#[fÓ^¤Á’òìrÐÝÚsúNVÊsÓx)IÖFÏŒ»KÄú‘d®ÊcLµÑBˆMb%Eáå\ÆÅLWLÜ-ƒvËZfk­¾oQTÑ0ñ×ó¢¯0½{D°ÈM>ݲ—3#r@gäÕ†gw3ÌÕ–Œõä¥:;ˆÓ¤”*NŒçnΤÏcIwz«%|õ÷‡e ¦·Wæû7òxÕ-k¤ÇTä'à”f(ݰNA,‡t` ³Dƒ0(þøc(XpJT¦ÏØBÌØ6xen^‘_ÙZ¸âW'(ØÝ¨”!Nð׀Ǯu{KáaÕOf¦÷/Q`k§Çl&¤S&Il*âV™ÄÄs8i„Äÿ¹¾€·øÌÖâdÎöž°ê+*ZßÉCx†|ø i™]K¯þ›ù¸*pX–"‰kSrL$œÔ ^ ï#ín÷Èš3îƒ íUöÔ—V~qMùtþò_c .2ê(ÖÇÊ=  "£põÛfg3ëépƒÃg¤¶·Báã§+8€ þ*÷ ì¤lSBy§-êé¬L*?"¤¥œ¹g›1Öè¹€0U[—‰gR†”-%×H¶ìŸäv"džfY!»GÌ™'cso¨hw¢E"8çºx0òЬ59sâ¹_vÊÇã\ÑâÎ)¨’Þ{Â(­—†mqq6`Έ³Dש²¢dm±Ã ÷ŒkH)q ¸CÆḛ́»$[’#o!®i«ƒ9›7XM,q‘ Ij4X¦Z‰¢S-èäŒÞ¨W’6S$îgŒôKù R‡¡¹¾—´vÔä?jäú»E=ÉöתªÙÏ3nÆ)VfôÜÆhç0.GØÅnøÔÈþ\ÆM¦iÒDš.Ð)k¾RsLσ0*‚P"$¯Ú&C!²{´ÎÃ!,ä/ùFóHO8—=“´Ÿ¦[[DldÌA€Hì4ºå™Œ½¨ñ< ädÕ€àκÔù›ïBÍŽd¼•$fkµ:81KÙ+CzøLòQ1ºA³W¬í:ߕՅ÷K/êLãKVûRXG°Óˆš Zsª©­€÷c÷É£S¨&Rer骳.•"ƒ" ¦w†»éS\Úk»GîO£æ:Á*oýÉõÛAížRœØ>$ý%•5‡IÅ-¥"ɆßKº£/ƒ—« ¸³NÇ•ö¡Ìbé Bë „‹Á©Ì³T E)””!›»KÏÉrR¬˜»£‘¶5öÌ$0z{|Ï‘”2IĤB ¢ÂÆøN  &©"⛢þ_y‹ÈÝË<³Ž¨#k§f™¤q<‘5PT*êõ/d뺫‰wz‰QµÂ%OÃà ”¢˜ØP{5‘hí¦©Â½#AÔÔì{úÁØ« ¹ÖM°‰k•ކ+j°è©àbWÂûŠ §#³ÖJ²÷û«™³ƒ¶²ÞÙ[FÝd;üaÓšÒÝq—Mi¯åhMîA’¼GÕ>‹ +Ð÷¶Qw~ Ìì™È$pËWÝÐÞœÚ1"½ë°«(p£2¦z·±æhý»Ýú0øFêH€j–¤b¹¾vf1›ã²I^F—¿´WÛý?b¹A0‡‘Áp¢d/¦ùË•Û)'ýTáCÉì!¸É¡œc1StJ\‹lr‡P’-Îí1kÎ0<.–‹ìô\ç¤aóà'÷L–‚¥»U°Ä?s\åµÿK‰7¤Ú¨›Ížíó…;Pu%ÚÁòD%‡°p/ÎÙ¢$?°]¡Ä£ÃYœ/;us!Ô®*<†ØL/Ý&\ühÌ)¸÷“þò³¸cü!Šc-Ú iûG¦¥»b©ûµ¥ír ÷øƒ@ŸàXSòú‡?b)‹"@ƒöüÁ$Ì"CŒÅ¤çÐYŒ¾æ™úh›K¢P‰° A•EpŠÑý@|ÑâÓº$‚-€³¸D"3DŽÆé3i",ø¯T&¹`UDÙã1ºªA@ XbÖ˜„vG¨P'r«ÂA±Ð!¸%:!@³Þøš„v›s†P#¶9ìâ·’È¢qKû@½¾ê óâÇŽÔ)SJ­k;­A!tÚ­Ši¡“¼=ó;Ëåçvù†i ÔÑmÀ;«ÿ—Ø@°(í3@Œï¤Ñ*%O¹x×€:sNð ‰k‡j&ÛÎ R;;¨Q,5H—¿“œ|ùð>È+úÌ*#8Ù€I: £¯¤#pSüç º;O(±´i›Š‚8GÛ&Ê2B` I ¶è“xÓ¡KŠ%! ¶@(Š$ìZ€Æ bˆÞ:Àõ¹P¡ü‹!Üd©²î»fû'lãîÕŸÊâ.3hƒÜ…A‘P£©R,•0ëê ¶¢‚`ô'ˆ$û<'òÔäº'û"–*胈*\M3+rA²È$ŠORd‚ÎÀ4w¦ŒøI7‘ ò°ª’±·ˆ@O#¬::Æ Ì»¸¬©£ûÔÉU$T`$ü¡=˾ñ¥Pøñ'¼Î½©´×Y€iRd‚7”Â&€OTº£l:7N Q¼¸6Å6¶Ðù0K¿Gí©ùo¹lþþ?/£]mHNü)ÔÖ5ÕvÀèeT‰4k2θ Ê!±]´Zy Uuqe"Liú¢"Íe»ÔÒšZÊƬ-Úƒ9oê •bn‚(þ·‰DOgƸ±üûÁ¨ê™€B¹[;CÚ‰µ@³¡ æd]¯LîK@*-Cx‹Xþ¾Î«“€“„þÝ4HÕt#­[ÚηQ`È“C•hÈdõ)éºBiSioÛû?gÔÀ—J²º`‹<ÇÔu,¶q$äª †2ûBظxXÃØ©ÎI]éÞ‚ŨÔÍ•\oº;oÎs)û)ÚÖL—•-Ë—ÐÃ’‡-xMšâ¦åå/ä‹Rñb Ñ«ªúѬzº%¿EjŠmwÔÛÑû!¬/´•>q®bq4Ÿn:2±Ïuº v ' Šâ»g[­ê~²*ƒ6I´“šl‡åë\וwe´u•ߤ#¡»ü9ö‹MzM—!†TxÜÓ%Wä0¨:FàQaIL5\°wš¸A4Dޤ~ŸÔ F °DL4¢9BHSk?/d…<• B•ãÅ*ð±™øLSÔIÌ©¤’z~×9”?o\ƒÃîd °„ìò²e ü€”^¯€ä3W€¯žùƒe‹ŒûÕ* iðùX$UŽZn$§Ý'®" ¶J>(ñdã ôo#S~,-ụâŒQÒAp¨=Í‘F ?!¢I輞t¶ÞÀm óŽxÍ^(Žð›§jÏÏÊÀ§H†%`PÉ¢ÓòXGUhúR)¸‘zF#g„@£¸,0åÖA˜Rul°±–]“åûšå(ÍÚR'’5Iȱ˜H¯q¶­´ ,"ÝOËÕ¤ öлLºø•@W¹€ÖûÊ!m~Iô¬þb›†k§ìû®•dÖVZ7Pjœ‡*ãìÄêé9kÖC·™”üGåIDe5±²`i]ñ7(¼‚ ©9G_I~^ôèFXèù•úDø¬AñKxœK6+Zy;‹Ö&ÑÐkŸuN¾E¢=*%‹Ž7gàYÐz4fÉ.cº—‹” ‰*•¹6>‹¢)!Íš\Á¤JÖb9n‚ÕN@«ä”©YÄÙ]nµâ´•] éÃBQéÆ4­‡Ì?•t+‚cùvÏ#ò®JXfiRº¾‡BÅIÛ„çí‘UÓ¹—á4¢@Þ-ÏL9D¨CЋP *«° UØ~«–ª×ÇâžU¥ËÓH#O©É7¢oT9%¿ X—ƒò (©Ù"ä5®±Š¥;J’¥†ã^çZÇè=¦ 0V ¦Í3ºgm–«,8÷@[Ê™Haâê“…ø–6¤ÊŒ½Ñ”íã,æ’éÈ¥ªðf×b¦mó*v€kPKÇ:®ÊéÀ H¦"XÉQ´áµWHÍ6Ô$7îô—5»î»_A—¬gòäE>Oò}ŸI†áfAäõûuuªÅ(’?DEzp…×T¬*™ãAöTþ’§vÈe¬W‘ÎØ.Ù(*cnq.R6”ç„][#YÌ ƒ]Õ»ÏÉÖ"SKò`«Šy Ã÷EH¸û²²ñM`]RxV >Ìb®(M—$E8¡ìÊ‘øk+Ér½]ƒ1žÙ⪚«Ç‡9WŽÎˆä*¡l^b¾ˆ}:H68¿‰*²² \–aØn„¸ˆ+ÆŸ…‘Å7W`Ñ€aÜ•„¶sm¥5¬¹[e{•©°Æ†åÝ‘%‰[²í:CºÚBjµÖÊøÎ^*Ã$/†ˆ9y!ç-"XmãUG€’òøIbõ-ƒ%‡й‰iÜNúѨÈJÙ¢µ¾ÎûG5¢(2Nå!P"ÊñŒM*èèµ,xK˧sK€˜jÎÑÃûYCòŠN®†:Wjî—ÂÓ{_$¼.زˆ¢+ xªÃ0=sœÔ–¿Y®,£òhEª½îÜé)!óibìéç-¡Ř²Fe!Y“¸¼’®]»j- !ÉËtÆ®,®´«Õ¶ _Õ—#óm~e[# pò»4=Ì>Úæ›º´”fÒ w„e@rx˜‚Ô¤ßáDüç;ó›äAØ8À<¤F4nLy–ò¬}ø\0Ä`±äûj¯§«6M¾**lV?”j­d¨ÏˆH=I{©´ÚÞKÏ㊩P)*AþfÛÂ1®'\šr)èʺ´?5–Á¥³vmu˜•iw)0IMúôºÛsOõ§ n£îFâZÚ×±°b¶«~ b Å\"üŠ_ÑÁÀ1ãõlµTDô‡TÛ¢°4wLÐ{¥ÓJôû&Ï¡=#S÷¨rƾƒ‡¾¨‹”#P÷‰¢L*Ù¿ ú¾¦ñš,X¯#Rï5Ñ–[]ºiˆd § * p„Y–믫©î±s› 0³¸,–´j>Q¿š±·}£È|“[¡#ÒXû/Ñ´kÍ¥ @4•‰b 9´¡´à–;hÖX‡5Ë5¿@z•r@ÀZÓŸˆ¡Ò8ËÓ¹‹Î9â›ÁW õÉ )5Êó3„/7Jj q²ci:,"«¤´* *q²ò{°|?¢qoš«³Œ»q‰‹à ©´p}¦ˆœëA›’è¤"(ÜÀÚ‹:d›H‹ðÄS5‰)ÂÀ}(´.*¹%ù=%™7JÒ^3Z@¥*b¢ò¦E¡Ä–[‹1ƒ½¬!µÙdSBs’Ë‘$?-(Ñ“šå¿ã¢¹áw.˼Â[¢¬ÙB8t?cC !®ŒWA“u1@*H°úä<â!ä03¯BÚ ~ŒJA¨êá•Ìl ôR¤“±’›V€z9Äêˆ ¢Œ,²­ý§iQ/éþJà˜°˜ÔT¢zå²ôˆ™«›ñr¾z·®* –²Éž <6Šó" L#¹ê¯¼¸§)Ê9v©*bÉD‹ +C™/4ø˜;L¼¢;Ø ä¦ñÊ/r¥®)ÊJ±ŽÄk±Ì¬P€)e¯ìs)뵟º¶D7¼é¤¦¶/t½É=6#²D#‘ šþ¼ª@¯s «Yž|—Sɾ‘Õ9æ#›0T,¦S]ÁºÛ*:E­¤©Ô§›­‰¢fÂv«¸‰RÖBã²’ñŸ>ì•;òÂĺ<4^@…%Üæå7·sf…ÖÀdøÍD:–ú]Á1q–&eëX¤Íá;J³jL„=lSKjOâm¤’ 2)l±]»e6_ÔÀAí.œÿÇuÒ­œéŸ` 3¼[t¼ŒS‹8‹8´ÚÙÕ+¯Òƒž”»‡ës—­?çN á2!Ôñ7K ù´Q´TéV”›ˆÓö`ËàÖž"|(±^‚˜PÕ™°¶;8“Û‡Ùö"c /Û]¡¶›Âù%¥ç>ª5+â"GûF¸YM† ª{°ÆK`ĵʖáƒzß„Ï}¤¹KtO¾1Ìþ=¤SϽsìŠÛVu1¹"l2Ä~˜.b…]ía“ZIŠ!—¢6@°¼Jª¼ŸF‰€E›8Å­-äêãfœ×£@ˆ–V5ÍÂbƪˆ i¡‹>pJ:>dÈNNe#£ÛE"ø©ÃÚA i+U`ïåßÁñ†Ûô¢ìùb,Çâý\FTÞ‰X!nŸa›[^ÉçØ–¿ŠmKX»‡õ2Ò˜’Ñ©"¬ª]Ý-^\V+G:BéD²¦+%IΜ))ÖîˆÛM€$µË\•†Ä¾lÒÊš#}óUÓxÁ™K"§X£zÜÔæ¹ôÂÇ¨íµšÕ,Pïæ}6³þÞ~åÏLt;s yæZüpªq¾UÓö›ŒI†Ì ~çÓ·po¼qp Û2’y§E ¼»2Úâ Ž3y?*b ¦‘î•Í‹8¸}Ó=øïø%Ý< q¥™véÞ²–k¢ÈüÔ+:ležhš;Û;¶õØúk—S€ž+e¥mÊÚ4ôIîvàüèUŽ­d2¾WìùM fÄ”eGÓv+òš¼¥ÑÙ£Áö„ÅÚ4ô¦ÜSAIãs¿>(‰k®D+jAÍk½ö»Ü·ïä¡H*ìÄq"Ä‚¾¸³¢5$7¢AÍ fS„Õ ‡¯MUi¿Ø µ¦\ÈXœ")9¯ i5þÙ%bwòvœ–fŠÄB縕3õ5"@ð•+§%•£¾1–“œá5]um½Ú….Yº9aÄÇ8=´m¥ŠKšèPÿ9lE"ô .dŠ—U_GV­äÚ<0²–°^Ç…©oš?lÓ,2µ§ `¿ƒ±X.ŽD¹ ±äÂîR®’L.8šIp«f4‘§ç†:Í}0‰qŠ£RèÌ‹ÑØAâS—b¨ƒG˳x#TDV±ô--c+ m‘ÎíÇ}Pn1Æ¿WdIk(WHfOrV…áÆIBR§yYní6rö`Ñ l9†z:,—ü-=ËîaмÚÓÊWöš§G.€5‡ ÝJ§Å϶ç ÞÍËÞ$70±ô2jŸº©ÎÌ@…HÛõÒà•&y¹toNk/Oµ{ ÊýMà’–Ñ1Fg&i"yºAæþ\&"ÓDv7JÆM7íǬ `ÏÈ@&†@Ÿð‡à $ŠD€OØÄBþŽE €0 †7‡C¤2pUŠKeÒȤqý.ŠÄâ‘‡ì¨ 2œN¦S) eD$àZCÚ•‹Pg€,žq@ŠIÁylŽ}Wa€w݆‡¯×_RØýJ1TE§ù”ÀV«¾.×+þ¡‡D'U˜òS’@­ID†ƒyÉãñè$C 3šQé(Ä:-P‡Y§­ºq¸G%´§µ\š‰C§Qh3æe:´È W‡üË×JàR{ îq»“Ü¥¼\4RælåQ´þ;LGñ›¬OK(ŸG#ü´B¡Ú–×âÜç ø©۳≾à>µ\Lëƒc¦IûJúdت ;Љ?‰Â¾Ø­‰Âšå0h 8m²„+î¾-ˆ9€2¸®¢É:Ì­>`"["P˜Î N v–§Lbƒ¥Í1€O³Žº.ò‡'èçŠÒØÝ­è"¡')SüÓ"Ž Ì„’¼mÅ,ËnõµOl¡#’ZA"N ^‰"3pê)ˆÓ£´ØŽJ'óY¢‹2?">Î 9>H(í$ïÒ¯§>Éât¨" 4?Ís¸ö.ú“ÃÎdt³GQ:y9µ´ 4>“˰âHŽ4²sÊtä=IúäâB‹”ó6²+µ);•[~ÉÑCVÇM,ð¼±h}Àp¢üç¡CxSà3'Nøp¸2)¥M8}Ï©Œ€´Gím"&V¨º“wVÅ“rŒ¬È´?)ËSÖìs"„8* <„]kœÌ$í‚ ¯«Xc-Ÿ¸(‡øû,ÒŽbz•8*ƒì¹U©Ò̯©ÑôÆ!ÈûU”Ø  ~IÌ=›ÝõÍu(5ŠLÅ"޶dû¥ÏJq/Ó°¥•XÃémÝ«Q- •iÖwvÌÚ ¤\qÍʤ#÷Þ œV a§åæ„$ðû&µ^Õß7CÝmfxIù¾3vÿ2€* q!# ûð¬«2ºª ŒïÎ(½L[óLõ¡î'⡇³Ð‚‘Î"¹ü½ºˆ…Ê$-WN„OÕã¡ÌGò?ÆvûRiÓt*9±îü>½Þ•}´„f¨£1á¨;:1#šÁÿÝ'»ª‚Cõ.6‚?hâ¾àÃøùïè@Å’s(³â§ìÈ&ëdØHr¯¸t˜¤E‰o¸þ;§l™"ån¿]øgŒi2?vàtÞÊî`Î|Ý­…ž¦˜Á)dÈd‚#Çމ“ä*Õ':ÅÏGúïdå" +p˜ kL/‘€d8dÉiPJ„0ˆB Y #õ[gÅ©¼Â\—zF!È]¨Ä>YŠ*©åy´bí“süX'mÛzN€!Á‹dµïµõðÆ\lDŒlá0¿ÐS³çNìÙM4ˆc9Iªe¢­–”ùÍÖVM¶§!ú‡Î [o2 Ú€«Öi%Ñž5(t {HB­=*ÔÆd p,ɺ1úÆ“rØ|ðM„IÖÞïS}FŽ<¦äÈyÜj­cÌ}­ˆ¶y «i.Ì0÷ C¤+ðS2$¶'—Ï& D‚kba˜´ÒMÂ’!üôÀB-ˆÛNÆ$ØÄ!Ï´Ì;OaóÇ–¶“¢ä8F’·bdÃÜ™g‹’q±ÂÍ’sEå„ð¡b>©2>,¸Š ¥Úžc¹£Œ…ˆ<áœp!L°óøE‹4’m©…VŸÃøÝ§Ãv<¤1·£"T% *€5 @#þ „B_а6 ?b@H  -…Á0gûò=C£O¹ M|J@Ò¸Ãú Ž>¦Q`:9šF¡2GÜB4‡LŸSIÚ 4¡F£Sˆ¼69 ?#R­TWŽC«U¹¼°=ìQ 5” ‰?bé„…•¬¶'¼Š 4¨ÆW»Kæý@®WcQ ŒB•»FàÕ¼`9µÃcS˜$BºÿÆañOüŽ:C°¨å·9 ŽZa0ëMN)QÕB$I\ò…q´È!6™äÒ!¾…Ürú˜•\tŸB#‘«4š9Q¿>l°™KâÀÃeuiÆ£–ƒRàÛØ¶š…ÆèÏâÙØå–ÓÄ´¿eñHÕFË—r ÙÙ¤&8깫;¶ÓŸÊŠØŠ1,êÊÆ+(k …¡HÊ¡?¨Cb¶€3ª‡!- ï¡k*¢Äj´¼ Ã$éèB4èÁªÒ@#Oz¼ÀÊÜRÄÃÀG1jt‚?0 ©€R¸§‹Ë4á-Ú$ÁÂ@ ¢ë¬ª—! 2:FÇû˜“&‹L̲œN‰GjÜzÆ$ ž" Šâ„©3Yû1Å=:飣*Ì Ö>3Ú(ß´x´Mƒd×£Èrʸº¨‚x„®)H–Ê0²$Ž:òÿG¡iã;BC³ì|¦±¨„(ò¢©£×®kZ¤ ‚%]ËÑLÞÆÈ•tkHŸÑš)9ŸŽÍPÈ#Ž2Ò²³±5xú ªìsb€0¨(KK„®Î¨òhé¿Gúx-*‹®²$ÊZÞnMém#×”‡1¬ÊBdëžX ö:4í³VÈ´bñKçåw3OØ€¡Ôš> 5D­9HlL“†=©2èãYˆu¶¢¡ªÞ†Oκ„ÿ3qí Sk­^…¹j°%jU)%½/cÍ*†Ë)ž`Có¦`«À wì$ú¿u¸éW›¼n(~6"$¡•bésd4¤xÂW(üRÇ8ϵ¶lJÛk}Q«uö£ª”‡êÛ…6‡JT\ê·Ð)5ødÞVÂO--5žÃöƒ×@bN}{4 5âCÒ%jļÁöCŽ»L}®”ÜÂÐBJ¨õq$X¡ Ú§‡Ú¥!°íö•ðLŽ4`~ªœÙ¢LtW²ÎG¦”Š)´ºÿVln¬1¸€¤Š‰Q’Ã7NÏA'ŒdIŽ01í#Øük€n´Š;U!ÙQ=ʾ£<©Öd“íÕ§9(IX:[lÒ‘©½‡o*%:Û*.¸~¤Rx’LLmËrLÂÒuÞÜk‰Òè²Èz ó[ËÚZS¯Êíz§œ«»•ü>¥ù`:­ê,—€ßŸ¤#&‘dŽ08t_«j„Õö&žžÚIKqT5†$f›‡xdZ2H?Q >  ½µzGã©$`1<€ 0]ý!o2ðIŸÛc‹YݬC&¬$ªUÅÄ”–_)I»¹gOÂDP箓 ,&ïU Á˜æA¤*EqËœ“(CªR+ço‡ „g‘FÈ’ë"…Ɔ¯ µŠ ÿ,©I<Øè¼{`î±/HW,Õ¬°*1tÃd”ÿÊ„š$Õ(HV´¼Úl…7K¤ø@¥™$ù“éYÖzQ+\âCtv^ØQŠUa’ÞS6jn©ÝÊâ%qš‰®™Íá$xDIã*æJX{Œ”ÈÅ]ÍCŽX ¬»{Ƶ%V>ĉÕ¤’.ZIhìà!Ú—mvaNÛ7 Hôï”òx–ÈS;[àê†F4A[X‚ßa•n Ô±8‘e2®#y~µ`ãM¸s^åϰ¨Ê¥’»¼áÕi4'=ƒ¨JUÙ—tÀ}ÑùØiºm“óz)°w>Ka„‰Í½?J[aût§ Æ-ä/€_9dEu°Ã"…„ Qe|âÏJf8]Jü²@àKÚá?y~Ã$™ßVh¢€!'—Ú>Ðx5m Åœ2úF]ìªgÆD‘í¨Dbµ¡ey"Ö0¸éäƒÚÕĶ+g„0âϹx,~ÓÀ P€[Ž8žT{|_´ †Ráb,æ›u@Õ’OýÌÚÉÚ¡ eŸSO6+ª·Ú¦@œ.¢I™ìªÌêÊ/s‡†è±djº¬«ÿÔ#´OZA;¬ýÆ!s¨XG“œxqØÛFªÓˆïi·ën¦)™X].bж!vÖ  ãn·RÓ:¹‰Ûó©± ŠD¯gàBCsꪳWX¼òa ÆvØŠOÓ;“ ëÕiàznX6Yùb3G^Gj´ëY$£˜y79Z¬BnµGF-€*®õïP,™ÿÀËõrNG¶È•íbI'‘Mx¢£þ16UÒÐn:‘lj÷(³±–/ú”fò)‚Þx\ÓU }“Ì„(8Øï5OáøH8pûÉ Á{8ä®X-ðÕö_XŒ’]‰eݧ^‘çù'ÍÐ̤šßÕIí'þ’ÀVÑC^ÖwIJ¦yñZ^€ÎŒÕn¶§†kÔ·šá’¥ûªÛ©[^ fb•­éB"–4ääÄ.m’Bš>+Û[ipjiÙkãÌþ¤ŠpVT[üÅ)-"¡Lé¤$5||• |uÑr 7c;‹^Ç\žêŒrât¹ƒ#JcG¿1ef{zÜTõ‘—¥ì–’é{q¤“„9ÌD‚8)%¾«¶ÿ¡ð}Ç!v»}°RÁªÃ‚RÛ/Wåá&[Aƒëعˆ´–YÕ:i“)=‘û’Ì0ĹøPĶ.“”åÒ¹£‚^£‚6¢H¯¦´‰°|ÔÉ`"tÖÊÌ«Š†@„P‹Ú4Ϻ¶ à ç.«î‚ŽÄŒ—bh­ê“ÈûÈ•Œ|X/â1(+h‚Ò«[ϸHd.(Mß)<˜Â fÐbLÌñ¨óÉúw-\jy t÷+,õGRi­¶ZêÛ'J{°´Ô©rr!þåÀùªZ߬²û0:z̺"ÁÃ!­Úê뀪±ðþñ2| ö¯Ëè½G,èpoº[¢òh¨ÊdžÒÜä´@pð£Íì)QÎ2E%옔ŠN©ÆC/Åœìð—Q”ý"üš®zåIFÃRË*ô»q*&æ8ódôZϲË'È'bH¿DÎu|„Âßãâz „)N¦Ëâ,*&P Ê~lFÏ+,¨ É0â&ŠÄî{.ˆ lA'Pº/>P(dqÉZá,Ý¢8s çrÇ#â2ðÈ¿K™ƒþ%"@8У*L:ç‘+«*­ˆÆÒÆøˆ,¶£6‚é!*tß&R f>²/~„o¯2âZ•æ®H¬ÈÝ«”Ë‹ètaô^Ç!²êYËÚÅo|õQKÇ«îÎGÛ*NÄð¼8p ð2í4R^”’ú,xÏÖóºð«r¥Ò¾ì†e8hʈÜè2ÁÌt…æ>^m¢(…*ˆÓ«·ïºcgœÞ©\}pæBoÜäQÁ1BÓÄ”ëPa*WÀXÃPÇ«“®Ð¢@.]<óoH4ÒÔ´Sôƒ­I,!ƒ6ÏñX|"dЪX¹WòêíH§.o̳ Т•°&ÞïžYãFnþIôˆÁ‘jÊ­RϲG5Bý;¢8j'R˜·KŽ+i<æt“ÈPÀ< *œ¼Llõ‡å-Ò$«±2no§5´jë°À´(ãÅv‡¦v¯ìÚÅÇÚx’÷«1.æ9 ¯©5 îõ4ôµI´û#£JŽ€Qb .z!¨ßÏ5L€hrˆÐ\¥B=,pÙPï0Fä¼c“˜ãtÔ®rÜ¡%‰Nu‹g:äš#Ç¡MG°ûûU©Dã²,zñL ßTYå…PòC2Q{@G¦”V ®ÄnŒP{eÑæH¨!nðcAåm[4íI•~jÁ®ìpÞœÈðú4‚žôT±k%ïðªlQÇ>®¥ˆ¹•À'Š‹0ô¢b¬USQ7nF“ùZ1ÐÿªîºbLݲª!‹?ó®„ô ó0$ÒNÐ{AIvSj‚êüì‹îp´ñ<ÏKI`{mœÉ%˜ž•¬ÌLÐ&ãì$Öj°Ý®8C:m§µ5Ù"AL•ÈéË*^ÐbD¶ßEL&‹~¯ªÊä¨Fƒ#®:2Æ·³®_–¥QÊ[Ì›bLv5ΓìiYÄXÒ4ue'Xìd?0l YÍà§Yn³\õR¡<Œ²œ+ïFSÂY l&•b£UÑRæ>Y*›BU=Tf¤DõõáEÁôâªÛR®!cŒ¥‡´Ô© Äi ߨx f¢z±IÖí.°8ÅIë4,Ñ4DRЦ؉Û`Aóh“jâýV¼Ñªû-:þ‹|ªväŸóv”¸[“ŵ´ä”dˆnE?ŸâjÙ†ö€´#ÓÕÊŽ*'kÌ줽k H 4{ŽE9Ëîm­ ³æüã£K³¬¿ëhL#L¾ÔëÃLKl³9t2!ð¾ÊØàý¥vee(æè¬ëÞæã-èÏÑX"W\d3 Uó‚R ÂÌX0µÑAEp@Ò+íè×v®Nò3kÔÜô'<‡ÌV‚›±Qtö¨’€ߢ þlíSÍ—(u.'„èðʉLoGY\mƪ—úJ±š_iÖÑb)+ÉI ð£†vQWOÇžú¢+P¨çªÚ7‡B¥an¢h.†eQç 䢪‘Vâ÷¬ZËSŠèôÑ«Úç-Hõ'jc}”†V ±¶Ê%¨ÖïS¾äÌѦše7o@T¹Q" Vp_cN’ø(Ç“EE¢ˆ2Â-/ø¼  ¢‚ý/()c¶ëƒ¿L îÖ´.•†|—ýaÒȃÓÑ.©V´bººå’"‚Ë$Vw\*ô—C/·l‹íJµo–8Ãruªô—””æ%=±ªâÒ\^8ÜìBL…  °.Fç€Wu3O« 6)˜'ÜJ©&¾ÕñI•{4H½¥½Ö»ñFËÔ#8ëì`¸.}²ŸX;cÌB·YùVÑ&ô#BÆ|D“1ŽD§4p&ð†8ÂèkIu\¥ìÎjPH¤.u˜ XédFÍ—y²r|! úKpÈösìe΂dbïFÐ0‰yp……w*R` föÁ*Ÿ¶–WP-ydb|V¨•î”Ŷt/â(Itÿ®ý? MhC2„ýWîYf×ÕÙ‚5SqïôÅêø®óõþûëhÜO<#Æ:¬G ̸ˆÂ5$Yì¹Ì`å· xÍ)úLéhòùxŒ¬þ:m-©a{Á˜ºG]ǰÄcà§hdÛÚ(!+Vr+N#‘ÕI¹×W6H´&"d½«R“ÇÉ1>$™fa)züóá·D.™§¨¬Ø”øCcëh—GXâ·š»{ˆ¯ÃöXÁåÒ…ç=.§m»¹H&´óù÷„®³iŠÌª†>÷¦°TÈÿJ"ü`b4Ý¢ûrj ŠÛ:ë™i òò6ašÍs‚%¼UË\ÍÏWvÉ™Û4Kù:sÏDB•Tr8Vë—Ç·˜Fï§þ4Ó”]$·²Ö y8ô¥çA7T>0Žp|=ŒQС¹GW'r{ªÔ§Jß§Å¿ëÇ>T$+hþ«Ë+7”`îÚoÒ62éû¢úëŽtn{ 6>(Œøº?Ôz3`/{“6(“ÏSÏfº¹†>žZ ¸z¯ú%¬Ålõ¾Òްš Î4Ða²˜’×v¼>æt|‚[Ô·tc•Ê­‰i…¦´àâÝ¢  )= 1Fë„5ÖJ¹›ˆ$†,»“ƒKðûQk˜é¿ÄýŸZ]·‚lÅfõkLËÅˆËÆz¼æ± I!´¢eV%ËÉ[Óõ’ãòñjñÑ­Jî „g¶å|wÛŒ8„Úmä"S²FûZ+§r3Vn#“tì²<ÍÙT+ì¼G»v0É9LôÿŒ= y|_XUIˆµrWz°îaó©“*ØqA–\+¿$"Þ—%)vh¹RYMæ@—;WKíàºb1Œ/{‚VééHL'¶sø ãÓ»ï…]ÂÀ:&Kh$Ï“ b…¨ö øÆ$Fó5“ÛR\ç÷ø8QŠÎ¾¥§K›ºçB%Ôb¶—-jõ– N1ZÕZÙó~ΆР8 ýƒAOèT  |ÃÀÑ$Mÿƒ?aÈkî9À€qÇÜNH}Iá zþ&Œ¦A)‹¿'‰”Â=”Ïèíw2h³8l²£Ñå²Ð=Npü¤Ì!Ú-ja\H%²J¨É”Ȫ`x¼ú—¡El€ZP†ÿ·¿ëЊ¬D '}F`—{œ¦cU‹‚±Y|Y¡±z.2®”Â"ò)f„˜c-q\ÜWªÜîð‰ú/ S°\œ6‹²®ÂœTs_`§”9n^ q¨Â°³çR©ÊoÖ—·O „_¦2 ¬¦I¡Í ×ÉkßÉ|˜Ú{ ëôíò=æ7¯iÁïã(?j®ÿí£&.:\¡¸€<™%éÚ<í²(4 + 𼱬ŽÒpÍ K‹Pû.°2ؤA*.’?€¼õ¾nBa Hô#Â3”¶Ÿéâ²%¯ZøªÆ("R.)J½' ª*Õ IlŸ¨ð"ª÷¢ëJâë¥ lË!­*ðãÀ‰j˜D+t ŒÈP¸×p ´–Â0 ¡° â$’,[>à "›§òDã!I#²&)"|É`Y1¿ úë.¥«ŒÄRhT'10o¬¶ºM)üœÊ®+«$=S\›@"°2bñ8ì”\‰¥´É L³ÛgÓÓAþô€$éL¢«M¸Ö -6˜;Ô3\Ö TRø‘P¶\«ã “˲É KóÖ’DVü»E&(E¨?q‚*éžÉ"ùFNËò[i7ˆ ƒ.5ýÐÀ,RDÎQà / Në˜À‹»¯.w*mâru^/Ó"zÿ.³byê¡Tfª¤•¼ùMsbh¢)M£Óů6¢« '@¶÷ÀºÂ6þ15hUÄŽ~b'ú.Ü €E;ˆ¢+¦.êªÒ÷¦¨ji¢lÆ^k¨$Ã\2°$ANìÙT”ÀªóÉýNWnô"Ó³ùîãJ,‹¾7VS¸Ìì¼°V–‰¤O4>ŠÞH%É¢è6î(ó¶i6çô¬‚WèòÒ„]ñZö<‚ ôin=½€¹"èÔùÿ?tª,^çh½Ã&3¨n®ûbªàl‚¦ ØäŸ•"&÷éëÒq¶ióz E[îѦ(¹ñï`?5õX 8¾$¼ºeSUk³+¼Woô}ª¯a”mñNÄ´¤?‘ Ÿ"p†GãÕFL˜œ%B¦Hš{¹$í1ƒ TQïj€.²Â{Ûýn/´’à·ˆ«Þ !ª¾Ò¾¾HJzBåÉÿ5fB–9"èøœ3Wc Z"h^©rùá‰Q/ÅËBbHž,Lž! büó@$nO½Fâªõ=.ïÞ•мázÈQ†dŽDÇæTVNnÄÔ›jU‰Ü^1m)¦ÝØi‹h}.§‹–cŠ… ´¸‘•Ä>ŽÏ]bGÖ„Ök¶}cð”È†ØŒÓøüeŠZE©Ø¨±IËe‹lyf©R,o¡T•‚¨ÍH$ÛóÙnrxž‚øk³•@ —xñ ¢}Þ#øâ³UêŒ@(̓ËéHTU,–hñÔºµß.‰Gx§­˜¾ÅÒÏÔë‚8åÍ”½Ç"û#x$ ]—xxG|胅&2—S.É$ƒqJ%/²ÈÚYüWs ʶسÔj§SÌí¨è ÛÙW³!>èt£õÚ¼îPÔt†lgᙫ„PQOy{"O¢M£4DÅ‘Êf“1µŽP1ü×Û)@ŠõH4÷»˜Y±î¥æÓ{ï€üŠ»¥.ÙKOšÍ©]˜òi!Ua4x˜Néâ>ÖýV?ÔÂ…tÛ'Èý:®g¼¶"üôe%ÖF²’eZ×xuj¡€nkZ÷eò*.ÀEIÁÕIÑD²WÖy/é$ª ì¯S§F¢„Ì|£í§·©0ËJb›ãòÇX¼Š jõ!G “ÆSÂDmY'„À£Ó5=n$DB¤)ø¶´ôàÏú²„xkÜr[gÈl$1“fÓ pÇ—U| í-KôÍi=½@#ú1jm'À "´ô£’Éf);cÈ¡ðYœÕú‰!ä’g®¦”\Ïõ¸[ä’k÷MÒÓ;n%Þ¼0Ù_šTT1Š1½'(¿}á<»eH›} ¦z"À§Ùœ€JIw$“ï˜â¡rýfHzƒŠ«¨H·K Åx‹º‚›.Ñ5 ±ôÂÓ0ãG½®íŸHgX£Ì¶Bvq‚L×…b 0#pÑÓ3ýd«ó:¦¬“Ôl‡5è!)É*IC­Z¼RT ò71yOñûˆëË€ŽÇyèAéžl$sDfµ¤èqE§ Å©é`•fw'4KD |ÄFŽà†ëû’ˆÑå¦(¬¼>¤½-Šrï[U²0lm<CM€bD·á©y0ɾ9Šxï_LX}Œg2C®3…]NÑTX•®Š+l°Ù^´9†XÔÈkO/Ù…¨Ó¦†` ŠŠugúÖS’+ÐN‹•Êz`&žž¶ —ýùÝW0“òEmÛ\ůsJ3eƬfœÞ]V.sFb*pÜß–‘#…z l¡djQ ¢Ð9R]ï9Ó2pLÖ—3Wýú¨7“MÆ´A¨í¶¤& l®ñm•¦¼Ö>ÑDNÄT}äÄã‰é4ÈÓ>Óîâ'rЦsÑ´õâDvly®5ž %Øv×É.NÊéì¡HºŸä6IÑô:ú$$$yQeÊ»Ië7O—øŽSÔo3±Èý˜t¿!çÔûþ,/ÌZT#†ƒèëØ*ûDŒ¼^i°/i„zøzX±1_¯¾/xÔöŠ³Í ìõ÷ÅÖû3ìä*1»Ð®Fž·^âwï¿Ñ•>tï¶ϵÉy(ãÐ@4ôÃñ-ü^E¶Â!<W²*"®Äïª $L€ÀÂþüû‚ê­±¸ñBeëÜïÄ¿]‘=3håM“¤ ˆ¿z¿Q{¹::2ç[b¡&,À‘ÙÄÕddÓb¢~VB-’&ám©ÑÌ}s¡43³9x©¼`“’qF ´’IÙ&Ša–〟{[€(–†´ óü ø¿«  ¢°31”8qŒ¾s`“[µ1i¯ãÄ©KÒ“Ù ª~6“Š”é+‡Ó$˜^”Á‚ˆ~&àƒ*£‚½l¹rw-*äËÇ«‹ ÷‹JZ+’|($ ‹Â¹-) Ê‘šº¾ÚZ#-ÃųC0·qÀ¡š‹·¹.¼ü³RñpûÊ*0Æp¸  Ãâ>ú4’g¾{rˆë%š³œ´3Ë22¨-sM;¤?ÉÒ‘¢!¹aûšwr*cºˆ‹‹œª8™I Lˆ£¡Ñž´•ð“ ˆD"ȶ¹´È¢>ª³‰!wºÔ)#C–‡òå ÎC…‡â8{49¤ùE%N4A]DøZµ#ì°#Œ'¡sáÀx*È\e‘BÒ˜¨ˆ§¢z)Ñd0ù¶1‘ð@SZ”ê#œc¸a)ØÀ5(¹¦èC׎˜È‹±b#²lV“°©¹Òv=ÓBFp‡¸Ù;$cêC‘>FY¹ÅB‘¼ à ‰¬€­»YAÛ·µü‡H(²:ã±ú¦ˆj ª‹ )–$£i쳑%y¬T ÅkJÂ`¼ "ÈÜ·¸ÆBh´¤Ck´«™š:sš…-*½ “Q¢ú*%:Çž‘=3”:+<š23„"ÚI¡;¥IP´ÃDKC½Æ4«™x%zÜ6˜ˆ4âÈ ñ_©ó:H¹ŒÂø¡$aŽóÀË𮼓ŸÈ~»¹É8Úµ©ÑðO ðê¶=#9ˆ¯#I=»AHijªš¬Œš¸êïEiս쮩ÁÌÌ8·d#³l&‚£­+‡¨“¢ M‹ZF‹ÁFL-ŠØ*Bî(s´„’úÆÌ`›cÄÂÔD4è~±ø}¯Ó#8’†ÁŠ ª3<‡ ´Ìáպà ¦uL"±•ÄNââa± ô? û4XŒªÈx÷›ìi)¢-Yâ2/1+nÊü˵*k8s’˜#IcÁJ ‡Æj-<™ë$““N‹ð?õ "kA÷ ôM¤Œè ÄÔtå‰- ÆÓ)M¢?4þ¼‹”#‹ 9lθâz¥…Às0»¸lÑÚ·¼ã,ŒÃI÷J ㋊ GóÁ=QÅiðA,õ¸4æL2/ËTÚF£Ñ“R @Ò¤Ž-«G¦‹a(Ú`ša¬ŠšŽ­ªÓš|î«#µ+>¥´«·»ªº¬+¸ÌŽ•Ú’J©³‚0£l¿+Ë—Ra¢£^̬ÓÐkR•ì¯ÊóL³¸&D dî€mJ¢3¦‹ž®ÄJȘ å*4Ê>Å´`6T}É_·¨†¤«$ºT^”òˆ°™=L£¦¯dÓ'i 4E!z/!"Ú£!üC€Ÿ¶¼Sú; ƒÆ4y0)í¶B:ÁoÁä8ÀhÊ07‚b*;àPXœ¸©Z¢; Jª¡ @HŠŸ›$¢ñÒp¡Ü/#jµ–l ëIVCaŒ2©L;Ú("ŒH›eÍRS œG³ÿ !좒zD-ÕŸÍjj&›™šÊ=Ê¿0³IQ”¿Œä> Ž@rN!¿ÓÄ8»„)̺`ÀÓ*<%üd¦\=™1'@¬g¤‚²„ÒÒ¹lGK4OLfª0õ½²È´ù‘ÉÃ_¿›+Ä=ÏȤÔáO!Ãä:ÕEUÑô‘SÍ‹{´ OÀÂ)‚0J{9Û{#ÊÂ=ó§¯Z³ÂãX#‚¤Háð$E[:âHTl7"£¹c¢Ùè‡xêÑl ¶»ðK ÁZýWL±Õ©;OtŒ¤"ËAÒ0ƒ4“95*D’çˆ$]§¯ |ÜaôH]œŸ ³óªÛb«•Å@;é¤ê8™d?û‰ÅkÎè¾;º*SÝ““3ðIr‚E<¥ š/ ÙE:õTÇÊË¡Sƒ™í`K™3(Te›Š@\ì_×t²."¥¬³š<>ӹТÛÀÁlꉀ¿E…Ï)‹8WC\ø8‚ñG!3-U¢9L³j¡Wð~Â#óŠ®ÜÉðŸ”ÀZhÚ…ë4(}YÝ+ÔKYH‹õ‹+c œd‘гñKDu ¹™,'à$´ ÜÖ»\Å%?É9cAÏè~‹ñ§¸ˆÀ*2w+[ÿ íP lUElÇáÌJ­9œZÙPmbk–ôžÞ³˜ÙXÊÏ:a( ‹¾0¢É˜ûZt<á…2¯“Ò»_>ÔÖX0‡àb6Þëî" ï K¨Ý3÷ˉ¬¬ýMœ¡‘º=35ÅZA=Л"M4J (º¦$Áu§sÅød]Íê `³ á"aŽ*g’ƒ};ìÐBÁH:cé¼§#ñfáaŠ­ W*ÈAËbˆÁü"‚×Ó5¿‹®É õưã­ùؘ²Ú©$ƈ›g“[mY0}¦ywµ<§0d˜( ž¾½eÜ ®’éìΤ¸T{i¥,„ª¼ãœMÜf°ìÄ0¢h‰Iýˆ&|wŠG*hE<~. ÀuØF4 ­l@Mâ¼Ìß3éw™a'*FßkD¿”}×ê†dÄA‘¾ >žF5ý>ÛpÛYkÜsª—äE3By‰…RAê?ŒógöÍfFò–þ/ÉýmOð‰Ò läž*!ŽJ§Ý£ ÆlxGýµ8sðgR‹4 š¥“#RF4Ö¹ï(Ó4Èt;ÅýiQ´dY›”á¢BÝý¶ˆË“Øëež*éGeìˆÊ™ž]Ýç8ç|f«[‡lËLæuU˜Z5­Ԫ܃0Ø #² àÁØà3i_Éû&œ«Û“Þš:Ùï !§ÂkÀèõ•ëúP`êì²Â\}¥Ü˜©Æ‰£s_«\ì6å65ŒfhJœWI.áj0>š‰°¿H'µ%! ­ñå¨eÝ7JumNŸè©íh‘5 ÂFäS» Ù‹l1w‹äÇ4F”.×åÓÒŽ²¡Dvdv™Tûe´p´ñÇŸ œBI¼Ü¬zF3¬ é»LÑ_êÉX”N¢Ä8ÞJ$ä¹Z†$BM™ctõ`’ÛCi‚KEérµ¶àõ’ëÄÛ~LÝ´ŒBʰþ…AŠ÷ÑJí63si´âŒÙ0 \å”Sã À€@”Ñi–Né§®ž0GÈ„m,‰X‚NÍ‘½Ö,аß\„æw!›š Ū‚Í /±bㆼ5F¸[ÎéÌoïû#c¦Ê¢x†Ò³c‚ÓWKRӤ់TÓ?ml¬@}ã:MIYï5Ëcß&çÍ£€2g´‰âõKLºÙâÍ6èР; Æf687ú<©ÓnPa¿D¼®Ad0¶Ós,Øã'°öï~ðm ›ÜµØËÞrc{‰n€ûà¡:[jêŽê”u²4HЍ(Uý¦_Ф²mÄ.†ë» ¬‘íóbæ†â„ÃÙÆó‡ëø¯P!;}ô¼±î»2;‹µ×±ïZ¸‡1•ÚVJ„:å%Úø­ÂÞ#É;&ÓÙðÝXçn°¿&È‹!ÑÖN+ )de[4Wz^óà¸ÖƽH0¡‹à÷»»ø¾7JŸÃè ©â“µ5×#â!ž,´sIP-¹ Ê½ù÷v®Ô³äõù,fXØ}c¾èoS›¢¬€¬éðSq[pTGÌÇ'/7#Ð ìbLö:³#¥òòk#ìc¸ÖRa±?žW@³Lsè÷¾6쬓Py0…`Ö7fħHÚBLe ˜àÆr±Ø¤k Q~ØG.Á”ІX¹O«4eª7>9z+“~iÕTnÿÁ”²JE“ð5LèÛñO7¡h1^ÕKù°²QkSíÒu©ÓÎM‚sôm¥¿ö:&î.†}ŽEÁ3DYqqHäŸ4sñÖ•‡ý¯u@Ýæ~Ÿß­ÙH¼¯Æ¿OÌœÀM¦&hÁÛ4„!#«åÍÁŸgF˜â¨)ÔT茓ö_oZŠ£üÆŠN‹åÉ´Ô€ˆ èQ£A¤ÛR×ÕÈtÙ¨Ô"!ª±ÿ®‡•Ýìhj®¤pˆ‚ ÏØD$ ‚PøL$ˆÁ¡`4eÿ|ÇbððîE‚¤Ñ'ä¦Dû_Òù€3—¿¢±9$‚ ’Me±)%7ƒPh”'ü^/G”¿&°Ù$ÌG¨Ìá2H¼’± ‰F@ÔÙ­z.ø²EêQy¬&w¥Å¡r×ÕÆÚ‹ÊëÔØ¼¶šÎ¡*l’Š޾nò›<.y•È!³ZÔn• žÌ&3‹êû©D®y™ç‡Þ2™,"%‰¥JÚúü¼†E“Ík:€-ÿ`—Ö÷0úô®L {qA|-TÊ‹ÂtÀ”¶A…‰Kfµ)¾‡nÑõPhm6¦è`Ý‹S÷½„u`pHMJÈøÛÒkiÂå òç*Ïj –¡)Zü L(¾kÚ¤¯0¯Šf´&©zÒK4"Å!è’È#i´±éz.¨#p›,*Pó"Ü5Œ©üÏ2i"šµÅIšš¯=ìaEîØ&mÓlÓŸò+ºî*O3½&% L[!nºfù¤jé4¬BgÈ@0 ›Øõ(­Âü~Åi{ ΠҢ¥2AüÚN‘Ôº©®|ÖKI‹×9Å VšBŠ$™ÎÉ|♞ô{‚$ RÚRŠr^„«Ôyï0€ôàP¾hj$34ó•¾kÊ=¥4õ=N0HÊ$ÆÃo]&‚)±Ú.¦ÄÊÓê§ Ž³zÆ$T+–ȦPÈ…Hѵ'2Ùøæ!”•Œ}ÇÉšúÅ©F‚5ˆ”ç%0-©eÎU*F ¥”ÿNMôÓ>Í7`£¦ªB@¯JN)íKÝMäê…º(A[€›$®’2暥n8Å3M‡Wˆ]=Z¶oº(„6‘Ýà´YdÚaÔ ÷>°”'‘ÈxTø!L-’Òî>ÚΑ@ ¥j•m|¼é›3Š*èÝ4Œ¹ëJRhà™ŒÐ9‚WŒ¡¶îA—CZ4ƒ¦dMLß\”:'H€‘‚V‹éKüò­lö’6†ã8±ý,Ì0¡(n&ã½1äObŸê•ÐEök­©%ñ+äó¹@äêT£ P)o!²à¶lÁ0Æîçhô¶¸̽À,¿ÂõG 7KÛcoHg|$“m˜Ñ°ˆëǰŸú^Lü!ö"m±áÒtÏáÀô«ÝmrW©O™ABm‰ .qmöîZ`è¶lžÓ¿áIÄÝí|5ñï!q²IOJÈzìŒÄÂ$!¦eY€f<¶‰y Gk½©›B@Øü>¬¤–›FæøYýOä$̹ÂRaÔÂ1 Åxš«æl?H¹™8l0Œ·…¾pÑ>iö6‚$â`£×ƒ¬½¯ÂR°›[±})-…2˜t?C\)Q BêÏK›)*D‘¶²2CX¡$3$ùV¿Än²\;¹<îÂ4*BÑbêeŽiæ¹bˆÌùN Àå5àå§Q"@§Q{BÑùù¼ø°IY5oQ@‘9# ÜMñ™°ô­H¢ð`j,€Êº7(‘ë`}îÉþ¨É1%ÛóÏ7Ì•ú‰Nç‰lF3#nX"`éY¬\ËU JBÅ )-%mÍF¥6ÐøÎzý#,O·»Ãéç]%À#š@†ÐÎ7"ƒuXkÄ™ˆŠ¥úÞ”ãì?ãõ©HŒçš09óÁCX‹c).kªjB£#8§Iâ MYãÀR"7mM•’'‚EÙàûs)F¶AŸ0˜¤A¸'*ü«ž7ϵ”›©ĉ5SÔŸÊÈa —òlß¶6â“a‘JínB62ô]ruŽx£±™9—œ> Ô¾ Î’öú_%¬n‹E¨'d$’l ¸Ä§u]”T†˜UYOØ}1F„¦)Â2š§ ’eg4t‰ÍHD+oŸï)Ñ“2½#Ïœcš£ü½$ èKàŠF)޳ęXÚ‚f)˜‰Ö>å¡G0µçBFA0\ëÂ/j)¯¨—2Ú’B0åŽrWN&šF‚ˆÙö–ôµCUfì*^$Ä[B¿¥ÌôØÅtRõQ‚þOS¸X׃EмdE1.‡µÆ¢" šÎLȯ©Dë[¢Hv ¼ùÓ^k0)­ê[¢×¦óJ” OÜ'+ êÚɸÃþE# "QÄIkfнÐj+UžS)À–:™:öB$v» OÍâ6ðp9G™2&ŒÓu=å ?½vzÁ"F ³ „ 3Ù#T³¹‡)ZQŃ aÔž?lOvœ})ëøÓé…mUÎÝâ9„òSQ3Sʸ~[DÊžù‘®k!p½dfK±¡웾2[”\M‰®o £¢<ˆ¹Rɾ¹ªxlâî»*e39#H¤˜#¦/«HõaT”Lì(SûFìB$Ó¦Ï3*NB¬633ÎÂh‘ö²) 4¡HŽÄóq§x(ú|ÊE~f[Ò5¶ôÒ•N)Vð©ãªÄå#)ÉÒ¯ÍöƒuÔ=ÕÒ‘üCOœ‡ºMÆíI—Öóc*ò}­c %R3¾VYSÖËœ?‰Y$ÆÖ3%åyÞ&Qº’ÏÆˆÕ Y/®r>8kùKOXQ{q:=¸•,}¢ r(©SïiäS–Ë$1séÀÝ0M­]õ¾êNUº®%™¸dÔu‹Õ•îÝŽœ(ü˜àµØ§Eíuk)¾¾äÔlòH>ò<ÒZ(ÁuD9±”±†|JºŽVQëH)­Î:gšo±S–ÖÅÏMf}&I¼v)áèmí§mv3¿Éä`»4bªÙÓô0Õ@ O‘‹‚¼ZË®Éë²s¦¤UyH“Æil"ü.ÝÄ2hÿb‘ É«üÙfg— 7Zßòþ1SŽg7Õ´œTkܸkã—X2-âZ§ «o±oäÇ¢üD $Õû€)|±üû†y2EÅÍÇ{KQ#:siÏ_:Ÿè|tGh4Œª¾—†_l+ÙKbÌð>Ö>Ì)ÿM}ü€c ÃVA{Ôˆ(²Ó‡ÈÓî¶ŽöÖ"Úç~ßqSÓäé¹³‘/T)”Ûá•ÆŸK‘/Îé] ¹ãlyÅ›5¿¬&_}eõ«[!Ã.±®v".oFŠEªÂ#¥B‹„“(ŒÆdiÚ—„è$Z5àNC2ƒŽzð *þàÙjJE-(L­l6.¸ˆÉx„ú6Žà5PÎŽþ2h(nkýÊÈpjxð%´Nâ÷àS‹8%%9ä¤^¢fwŠŠ°i  O¨á q°jÍ©¾˜*@ÅobÉkxƒÊâd $ìEð§Ša¨x\ɰh Å= ˆiöJÊÖËr§ÆFÇV}%ðªi2¼Å©yc.›ì_ ±÷ .kX¾0ú.gâ ?Aô°!þ¾-ü>iÌIÍëøyK‚?jc.ÄmÇ£.•* ÈìS†(%£ ¦n‚TÑBúã'M*l`×NPë (Õz~,§H¬¤,+ Äz®Û4³x¸áø½ N… އªM)ü«.Í\H”e¹ *ˆ°ïÇeâM¤/t.\+±žCâ‰v8ëâãE˜è"æ© ‡Ë@ˆê9 Êþ+ÑfPTÌ  æ¯z2-= *þÅç²"Nj`N8Ý"µFúwE²íGZuiž‚¨œœò27nbõ/#Îrë¡ ÌЀíÔ‘ö$™M¶Ñ‡bå%2j/€Üd™‚Æ,‹§Ân "Þ¡üÉæ¦ë’n“*üLpúÕkÂênÈðˆäûn$Œ:ÅŒ¢¤è–¶€g`ø1ÐX' Gâ´NŒú)ÖÊxåp“dªß¢2¶¬:ç¯'„šŠxBÐ"çÎ(ï,) ‚î J*ÞfÁP0LhŒs,¯ãbØ.ÕQД“ÃÑAŽ #v™¯Öµ‰h¤á¢µÊr’®&#ž(ç¦.ðll…FÍÊ{o¨o:ÊéפN ´äcb$‘ØÇRpêgÊKÀ )¨¯ÇZæçšÞîÅèF”’+)‡•ð¶?’HŸ‰Þ€.ö’rkdB®î%î¸ÃêýĘ%p $Mlõõ7G ‹Ýk‘0íh´mèFèˆÈh¬ÄÈ/à¢OÒxE ÷kšaÇêL0 œ «+un¿Ñç èy;¦~oå0‚åÉm<ÄàD,”Be‘)¨rmÔî‘>°+ x’ 9J´æ³+,˶²­@c¯:]K!;áøxŒ>iäP}°°}¯|‘ïúu"âRå.¶vl¨ìÔwb;*Lû áð8mLÆ œ…æbˆ±­y å(M^{Dà2S òjèQ|äC #"Vo‚=MR/.¸tgCfE¼sM,ú!0è¡íŠ&1ÕCì—$ Z¯ï!ÊáO&¾Î²tj Æ(“§ˆx1ª®cå.1¬ìÊ&ì?'•?W!±: XådBÙ…uªLL"¤•~7GÛ •E§”‡Zû“Ï‹tÜÄ 2- D&á‰5„ˆ¢'„ÅóhJ&3´!oV4®ìUxãç ‚âò£¿gšëš¹ NÎáH¹IÂù)±&´ün"¦'"·§ÌÎM#b‡6TµIØG^LM (ˆ†SÑ`Év4#v,jfKO@ m¯ÔãµW5V„¡¦Ôe¬tÅ"”v²îe³ÖôŽNFI7ÆãNÆ:g…,ó[MÜXh²óÀ+ÆéTH nèÊ€ .‚N”`&ná ¯}j†bÚg/5“üF¶>dí«E±+Pµ/ "Žü0–¤û9Œ“˜(îƒ]¥<` ›9TÚ“sU#Ò “³ ^AøÚìâ!öíÉTgŸ]!ô˜‚RO÷ÒpÖL1N‹bˆso_ƒ.ùtöí†YÐ}V“3.ÑÿŒ…2 ¯ñù yõÈo­ø”±,æ»fúp BTu{jü"òÁ1b¾(E8W˵újj,Ã^ð‹ (0.#”¯Å.ôk(Ùç Å-8"ÑîN7“yÐ}p¢© YV–Ë‹¤RíXÂ='V¯.ÝhéÂ2dm!ý·[7BHoW¶€)nØ©ƒˆÿ5cxjàO¨åôïn ]C2“®JÆ•ïáêÔ¶áu¨­ˆíÔ!&õâsØn;‰nÌE=«;‚ðyÔéNW±N¶&¢n%` þ HíC-n¦kX}µ@Õ™S :7Ä‘IG}AîÀq.à´­ÕfÂW}—^LdÆÊíüÇ­3eqüutÄaªçqŠUjøö;Õ»vxy2ñpkîx‘Ï”nºFœWs&(ÛªÉ?PÁy4»lÉLg¶hÈSÞñ˜fL,êIdâJ}N>­ü¥¬2{8=fi2ùàÏPü9ïQrBSeÇ‚µ )R‡}¨¹BR‘æq.ó‰Y¬“–­Cgt.êÀ÷K ¶m¢£/‚£q 5l„Åï|Ñ¥ŸqŽšÒoU¾Íhpd˜bŠúšXÕw^Áè†í¤H¨ðDsæ)Óý$kØÉ1BE :œÈ‰y–ÍÄmB¼;#Q3£**M,pŸ¸&M"H8fa¸H€:zyæ®´,Ôµ×Lº7¸¨DRO…Ãæêºwáò]T;LEÕ~ºfV%è'Z‘ë*¬l³‡Œm""ã1ó¼ÍÊÝE˜2s²]&«Yº³¬ÌÑ ò¥‚Š …º V˜v÷uûuë½Fúè7·“ÍPŸN…}›Ðáñ­㸡ôh Nàµòv†˜²0êAŠcEY™ËfÅ¥OW· H”èÃn$u¸— Khm“U¢2>§ˆ^çÅFnƒ9Ïk7V.+Q+ *ë”u:¤w·ÎH µ*Qjê|®ªÿ¸‰j} ˆ¿ÈlvÁÿ‘aù0ñŒÿdª<­¦¾”‚k•ë0é3»ü@“³$½œeÕ/¬aŽë\psìf¾îVåWƒu† ®ÈîÐàw[{MÕŠyð¹V‹&ßÒç[Ó”O¼Ý‡ªb†Ñ`†dí˽o›ô[´Àé ‚íR|ÝVz7ê+2€±5hG{VOÚYÌÀµváy•à2ãYŸ‘ w-£ƒ½St¶@ Ç­Fp÷°BÇXƒ†‹ÅZ1žòî¯ÆÕBVa D,±®Ú&®ˆKzø ßÖ7Y›˜›­OÂ_BXÿƒ²—JßÕ•KÃÃŽ…‚äXóTè>¼ÿÍ#ë©A†Í“0BFÝK'[œÑÜÎmpÀg] Å©ó!ã7,:ßÄ,ÉÆèÒ8;ˆMTÀ$úû€w/°j|¾D®l´«ýÕ견ZÞY•RÇÒ¦rÇ ¯i&ãÝ´äe9“Zr€’—Êñ$ÒK+…ýBYÁ"¹ì…GWßrÛûpK©çvâsù3  ˜âx ß%Ç3%ñ“ŒÙÞ7A"nÌDLj™Ãtf°(GÖÌ…³~+Ä^!H\øâQyãâ!~²¯øE×Z;(uØÀ ­!©cÇZÎL:’Gž¹h´ô*ÇŒé `»(¶ËØ B½‘5‰!zÏD‚ÔÿÊ鼎¤¿Æ“]ôyBZƒœ›Ã*3…Ãåq‰hšÎð1¦‚Þ¼"ã§h=2QS\;‰¬Æ%ÿ âR+-˜öù µ~ûéT#:«Ò2*2bšb†°U P.sy}ñ`úÚ6kÿ3Lo¸î©‚€|Áý¦×o€ù=ŸÖáBÙEÐZç:¨†$õ¯AþÃõ­ZY!¬ýɧúÏ¥r‹R£u¥ÙˆÑ+à pfû¸BÿÀÀ0WÄ BÀÐØ;à†ŸqX´ ÿ#P pFŸò8Ô-ý$ˆ€¤ÏøHû1‘H#°Y‹ö_”J%ó¸d6n¡=è’ˆôÎh¥J癢I’J%u)$n9B¾«•Z<~8ü±G¥rI}‰ùZJäjE( 7•Å¥³yN§ —Íæà»óç+´R$’Û\F=jŽI+R·®>áy\%ŠðU­I-Ù]Ãù«?ãш~2…lš%úd.µp–䮨¸Ö(A¡N§ÖHŒ[q+‰ÍãÖÐ ä¿ö³ID‚µZÎí¤½Mð %‡–u$žôߨIö*5~IheõÇÔ‚s_›äk ­Šnýe¢2 P©èZ@ù©JŠ Ð¢lj"é¤(,£¹èãŽûŸŒÊW 4m\°&ûÈ”£L»ÖÀ# jP‰¼ |:ðùÿ Sì…±-Ü«ÆZÐõ «Cô8 í"H T×§nZ¾ÌDÒV—À‰Œ ÿ ¬47,CÑÃI,PJÏ©Hóܤ- zèŽ.’ÄÊEˆZHÙ,+¨ÄK§ãòý'³{ëÐÂ"”.rP­>0êI4 Ò,‰¼à ÎpÒ¥/i”¶­=Ì*8²¾±b^³!-J´/ä3+5i¼!&Cre7,»’Ë%X7Œœ å,Y¯O;/à Ä2J`m-‘UNg“ý®Àèq¹Ð¼‰y C™&­ª«l²ºäLFx©1Ô¤üBH™§–:kÐQô>vä%s Ô“ ERs¥fßêxÕSìŒÀÈD@ ?© y(󠌽Œ͵ØE &¨±!¬Îi[IÙ¦sI&}t„Uª¾€# n¹@àlšÝ…wU*73ü×;Öñ¯"¶EˆÍv9­­ˆ•ü&«sîRÎ~!ª® VÁëü°XžªÃC|í(•m¯€Ú³©o[wµá̱ºL÷?:FPŽ<Õ©÷¿#Dö:ûz¥ÇgådÕ)[-s;J¢sñŽlóWe¨9x7Bó``YŠí6˜û¶š×¬#—ž>Ôr1p îÃ`µ_‘&fnÒbæk¢}v4$î““×B”ÿÊì|o„…½íw ¬tÁ ö`'€©ó¯ðÝš§›=Ó‰eö~xL×XAáð t>µ¯.£:œØx/œé(Y\¿KäÈíâê5iºÃYs±…Ùê†ÔgÔ¹‘\‚íxý¡Ûaš¿ñûОdŸLDÛŽÊÃí¡ÑH ÖøÈNëS4MñùwÇ474k[ÙྸW EÖæÐøQ*9!Ž‹íDÅ;5-Ùàüø¯?Q;AaÖZÐ%#ó›8º†Šp$Øú‹Å'cŒàz@rÈ&Ð))Í:Òü3£È¸h¯½êD,:&¾Pœ.Þ=y™¼ U›· ¥q‹z05°A5/¸¡¶ }žI&,H½«žãºË©óe Øž)>¹H¤pŸ&*Ü%Ô"«s‰˜°Ôˆ‹™§¸À‹2Ëi.™7»»±Cb½Y‹½Ø}¦zÖ(‘ª¦ŠZ8yÊ8É\±’ ËØ/SOÃùËñÃá%ŸHnDŽhÜ,ÒÞ¸’[£ ¡3[ê «ñÀ)Úàj,š`Üz° ¡<"û¯p˜‰z'®2ž¼t) ‡<ù“™s±?2鉌C¡l#©X«¸Ê18*ô0<‡ò†BX±¡ž·¡ª"â9¢ }¨•´+Ú™Iœ€™ª1z¨»,Žk“D#7¡CBÛx¼‘ùª³J’õ7ò%,ð5àöLc73Ͳ›âˆ©$±éÍ ‹3«s«‹@GáÅ!s¨µ‰;Æ™Ž»´-ëî¾É†½jx*[,•9ÓTI$1„žD§‘;³ ‚ªZ’¥KÛ*™«™žY&c:»y‚@É6²‡I1_ q„£AÆ¢ |ŠáøÇq=ÂÖ;*Ë¥ýì-DXè®»?yù\¢‰yÔ3A€3®'À¯h÷Gà8æ£Ô-óz›a,Þó'´;½¸+¤k,¾À~ËÛ+‹àìÂ"@Éc£lx©º§ŽldÊ|!:ébÅL:±`L(-RŠÈ<¬1<3¤SD@ºÈÀ/¹™[.È£ÀYÚAƒ~ŠûCÈ…ˆ²âB$×¶zz4ݬèBz~1ä³Íð ;K±Hí.kP’L밨юY‘#€—¾ ¤1‰ÌŸ”L؉ÂIÆ1‹•ôмÔ\¦ £$“PÜËPˆ{8/KˆC/¯I“ÐŒ o8e?„¦1¹]1¿ŠÃ(dtº‘,λü­é!R!»éâ©›ëø—b‡#x±3ÅÔ'±¡A²”"MÅêä€A$”æQÙ³œÓûÐì¡H»õâJ¤HÑ»¤¾r«>ô]O» @ù‹ÏãMC¢‚B£“¾Ì«ŠÂËy4‘bM‚ú .›Å+0ëʳPä]Nsרɞ¹‘9=“P¾q'´J¹ ±ÂãPpå¹›8™ ¸ƒ¬\>ª’!#ÌðjÕ2±>s(¼ÉñS›Óºž’cFNP«¡„ãÃÔ:qïÔ›&*3š£5´÷B,1Ç¢y¨ÍäQAL {±9™‘%M¨Ì’Ò„í–üU¹k¤ì Ž:+ˆÔÊ6±>º¹¾<€™kH†œS*šaGGªÖÙ☼èSòi ñXÃÔHˆÓâ8#–ÑBéɪ6I ºb³øÆZ9¹ ¯—¼T:4gW¸Ÿƒûqžóœ›{Ô¢§Žƒ‡Ð‹0Û‹ÈÊ@ÉáñÓ)ë" ïCM;×û½3~¶"9¿£‹ê*¶¤ó‡á»2)ŠãÆZ!sO£9êN©ÉY«“7ZÌKœO>IÏ ˜F`Ã(í;AŽl¸Å£¦$š¥¬àÀ C¼Æ;‚º¼¨%äêVƒj±;™¿½âÓ¶[Öã<´´SŸ.óƒ!aÔE„± -º½zÁ0‹‘ñ½E’ÙÜt°‡“Ö©À),2ÔMSÊJZµI^N~ÆK˜šû‘b‰ Mè¥Wc‹³sÕÉ")ésRT=°EÕ=|êÒ[ËÉ’9×t\É‹µE8Zï;ªÞR@¹})FÜSÂÕ«p×KÞ˫՛LTw/¼“¢S ;“M¢·CÓï«I_ÊŠõ8úÃ$íÁÐñù üw¹Å˜Õ} »^ÃÓ Õå=ò]1t©+k=ëUç7å¸!œ±™ï2â9˳‹ÄÜ+mPUˆ«1nD½c#QHNkÕ£­¸Ó¯€ØCÓNÛmUý3½`Gd¦Ñ}n𫝩 [~ZÜÇŽ­Ã²¸P¡­Ò^Sq™›â&è}ÍIt*¸,zIÊÔçµ^³"DÖ⬭‘’ÉDÛ!—QÉD”4U,Ž.ÚÃ@À3L¯G)ílf·E)QQÚ)€ 2M_ºbÍ{ú¥MޤÔ./ A;„–äèTUB%LÚ‘„’„ cÓ³l¸$ÎÞ3Áîª[ äÚXY,¿ªýÖõÑ`º8ÄP~U0jÈûÈÎË‹Þt$¨ºTÜn5kõê3ÔaSh=í­åuxQº‡´ÕüÑlOÔɘãÑâDà¹Ã,½ÜÅ)¹ùK‰¬H\7¿ù,I)-ÁáeÅñv,8N}ù‰Ô”3²Ò!¦’Ê(™ãqÍzb”Ldn¬¥îqÖsPË}>Â4Æ=‚ÖZ &Uiã°çÝ=¯Ý‘žR[Jâ}ó «ì¾%îÝ]Îò{*{Ôa/™âã ”U<ÑOËM¼adȨ‰çì°ˆ›­™yI„*²\4ðQ%ÄŠ=«r«Z&ñ Žº‡H‹]Sžš«ºLEc¦¸”2É@üYìÕ¢§£>$[’ßJâ·@Yã8!ê×ü+ß­½1,°Njæ> ²ê1=P¤K²ÛF­ÆKÛ cqDÊÐŒM–J]6zˆk‘0F9 ¯¡1tD°„Ýq$ª£øK‚`v1€\¼€\;\™Ÿ‹“6©–Ñ™ZeƱfž7Î[&¶Yî­êc‰¢bàQ³Ó[]“òL ®ãæP~Nº`JßÇuPiU<>Ū­ Ó.@}´ªU¾Ìf…¼Š«!š§ÝüŠîFuÄë-@‰ «S«Zº=Ò×þVžùšÍ-±žß®%Kd¸Ýnž¯«åœ‰$ùel ?ƒ«ÐHêY 1æ¡_ÉŠ“J“Ô«õÏf2TâÊ¥Öfe™r`[îhsôr*ÌnÝÓ¬3=Ô°dBò6ƒ ŸyÀ”ÐM“F›™ Ð0À;uÄR¼sÝUkÑ@H¢LÞÃ/UÈ=æ/ŠÚƒ1F*³GÖ kæÄ5%Ý…˜ AÓ0PJ&yËa³=jdîËY†ŒÇ}âÖ…_l $š¡<Œ™œ¶,‚¾\oM¶–¾E:F Ô«ÈÅ:Y…HÇAÀ¯ßŒ_§öR–”R? ç6µÆs¢6¶–t=À$ê&­íUPlrØ|ŽÜDŠkæ"ªg Ÿ3¿MÑ5†¨nõUÀÂê×yXk- åÔ6ôUôÅ ßpÎÜqƒR£„Sèë×ÖlÔ=òµžiŒæÃÕ•=‘!:¿-•µ‘ÓëãjŽMêU,ÏÅ‹RC‚Ì!]¦hÀLÞ?/•7öx|½éƒ=£ÒXáܽ‚òMgÝFdša £5u”¥‡ö,dKÕ¬ƒ˜ÛÅC¼›|tt¦x–½¤ „q9‡ÚÈSˆÐ»|×*XëÑÞ7+8 aDÞ²nPÀx]±ªDíƒé¨dïW‘ON¤l>\±y(|áô¥0Fš {c"·mt;]ÛwÎ2Ík>Xë×èÞÒ^€lKis_ËJά«1™Ä¨}SÈà&…™éÓ[²CÇŒáh†Èϰ`÷¦ ·ìvËGr]9²ñ½Gp‡Ê‹ôÿFy`uËßÍ~˜1>aLpˆðý¦ÇÊaªl°-RÉÚF¡QÖ[ßÊÝ=T?¢ÑÕ0¢S³ÍR¤X—˜èäUT´£¬6Ø`BÞžöÁ,hv”(4ùWÛJaÞsN BlìïÜz‚·BMcÛU°þ1Ú©jÖ½{”:à°EWÒ¸ÀF ™Ï Žv¸}ȼÑi¯ÕR’Ȭ™¶wCÛcƒ\¦½[¤%öNSÉù¦<Ò¿f0ËÀ†I|ONàš€CX½ìË^P€ P0Â_0°$6ÄbPH, ýŒ?#PpZ/Àáðøœ %$ˆÇ$P™(1ŽJ riL"‡Ìæø¶%~ÐaðÐ$iùJÀ3ØŒPœBhÐ÷ÅT WQ¨/ÙŒ®­Pkôi2JŸÄA6¸[æ_ŒL¦`k¥Uñ ”O's«à9 –Ù£÷Ö¿_}âc|f%÷rã­`˜”cJ\`ù¨ì ¡ÇG0¯ª&r9¯èôñz%¥ÿ­Àër jG {îkð:4J9tG$ðœ_‡#²ç¸“¨ÆŽ1ÀáDw±Lº/J£S¶pZ%þ „ÂÖå´M(]^lØ„^S„ù(6jÿl£‰m*ó›íö¶ò€ s2ã"({ª‡°hJ@ñ)¯ëØ:ªCd £c^Ûà ä ?ê⼫ºiú¾Ž.ÊÚ‰ %¯D$·È;x¦À º®²°"ÎEQb"Œ-ëôc¨F¯š²(#±ÊÜ1 5jKÚ+lšÂ~º©jðåºÒ‚ƒ€JËl–@²Z–ó1΂­£B> §´Üà=H¾ØB‘Šù«ëkÞ1€ÎÀ1Üm ¨OŠ $ c2®B0×Ogâ0Ö­*B¢‘µÉ‚¢(Ñí8~± Lš‡¶§â¶Ž,ˆ*¿.Jqì÷SÀ%oY=3ÿSÓGò$àVˆÓš€MÑV P´FÍÙ=ÀRêS×0€3KæNL-QJ#¢Jà Üžè{€ø^È*Z­µPúÁ>1Ž:2)T9ü¯¸ì<D(ÚÂΫcÚPhÉ´j"ÛjŸ•íê‰^trF×'Ýñ6XJ½_hDJº=!2\®­®þ­YíðÝ X½@«õ]>ˆ¿àK²|zÒÜ,‹>щ žìÛ«°‚±×å· ÜIŒ-¢28ŸæHÛ_ ó뢽/¬³‰^ˆ®Ô…Øn¢ £>°í™¡L`X¨ÎðûpеP±6b‰™¡yB¯¹o•pýÑê;Í@·ë¢Ûƒ"èã/NÉÔþ¡¡µºí9¶ïFÂÅ/D\lgëÀ}8¬!«æwè ›DÂõùªÐ1Ꜥ8òW3³1Ùf­A#Rä^~(œÛkî@ Ѧvøzü•¹—Ü?Aý$ì›Û¥¾ò³Jz…ÉwS¼ ·Ö"^ÛɮFî†¥áø¼ Ú}|)e“´úCËiN(ǤöêSÖq£m‹5À”¥qÝ’ãH Urt J!_F` )v¥ÒªÑaP1«bΗAFD0]À!‡• ɹ WHÅ@³’èg!ŠÏ„Èú0ç ŒUzæ'HD…r„l%™Å©W†bÑH9c?‡lmÙJ(Œ4 ²W¾bTodhÎ@GœiO°EÒEr‚Hév# (΢¾]šªMY‡ªgBAÈ”sÄ,à0§vWÓpölÍH}¯´¾Å#û,+pP¶öRCÞ‹vK2U(B“` 4_  ‰'Øžˆ‘v€Å9Ã$|Æ ¼I/%å2øÓ9£—p¼„¦hXEÜΖiþÁÈÒŽ›¦vq1¾r¶ÄHFg )ë¯Ä˜éRÉœ‡ÈØþ©‘þz$bØNñ- b çLÉR/&'ºú‹QPóLé3-ÏB—V3aKÍ'¤Š!”ì<Ë2yÉbœ{¯IôlÑÒ8¾ ›€Hd†Ë©Tä€)ŽhÏf¦)"õWD‡*¤ û)‘3ÔZÑW…\»Og¦ÛÔTðcSQÁUQÔ³™|Pm8“3Žû'àUò}3ÞŸÔ¤ƒ¥íÓ“ÐhÎívð|ˆ¼^­H»ûm e(ØÞ>ÞõWcJ)ÈB.Ê[}>HR–m—ÇQê¨K™îMv–‚¥UT€2¶¹4‹1ØŽ•Ý­€5ùjëp˜ñ˜×5F4øƒ>ÖˆÄ` ´Ë¡f(Ö.:¹5‹ m™HRI€aœ+Z/AX6WÔRŠCµþÎõÇ^èÙŒ‚.›ƒru]Ì^—ËaÚ’ØÝQ%Ä9#PËK'Þï%j`pêAiÐ^Ms»^¨™“(+;N;ܨÕ&YºçòbÌiŠž…¦.Õ¥&ÕÈÕ*"éõñGß0ãB‡—÷}ËShì “½Ñ™cáF‚°à±Ò{ ,Ÿ{”Ñ“\±ó#’rY8÷þw)%’Æþ%ŠÄ€¶ÃgdÆ»†XnÊÅ &èmèY[»©õy\9A¡ýt]ˆDgS¨3m…%Ì*åY2ž0[,­ƒˆ+·[Ur&!©·“Û‚°„i!º½“ül?ò-h¬Åù>úµ$ ›^5™4¤l7’e¹pµ[Å_çs$198Yº·aåc†×êI¤÷šçH *Ü×ìMLe°R@ dro‚„“|WóaZ˜­–ÖÍ–³¬@l+—>RMQ²³:[Â\R÷§^)y ÖÃZÒßœÜf9åÑË7Ñús¢]7ÉÜÆ/‹PpH=hÌOE\Œe¾r4oy Â$ø}mñKHYt_ 4 ¿#í¢áZÚÚÐÖ·0Æ#’f `Þçbies&„ÇîÓܨŸlHÙ£¶‰Öì¸I>}¡]ª¦tÛæn:êA#àcåû&Íh¶‚¼Éu®_¡üùÓ;í§Úa,ÎÞD?þ¦¢‡˜‰=½c6S]R›{`SdÅÐô‚ו:ˆâ•wb*Ó¾c[Ñsü ?´E ê‘+RrjÌè$î·@Tv TÆ3G\Ó=+š=>ºâ–wP8©j3¸^z!Ñ8_Â?“H‹–= Ë›7B¥lÌœ,Êä?ÍKÄKd}h­øUÙ»%»õûÊúå©»ÖèšäS!ðk·œ}ö)eñU´^ho3‰öoÙ>›:'ÂÌÅŠNlÍú?”Êð^¦»º!׸äõ°dîi?kÄ®…ç'üê¤ßoôñm™÷´Ûïm †:g&G³j4ÚØawsc_­@7’¸Lsf/>QîRöBD`&&1Ç‚W¤, b‚ÃŽRî"“΀:Lx¦0|ê8 ¬Uí (&@X'¦§Éd~ÅzYŒÆ ôåøß04dÈ´î$È1.ÖϦ°Þ¢d mí^]ä¬ÂƬ"몚òÉ!þ¢ÚpŒr‚ýMžï¨hJ NÞYÏDñ"#øõªÖbxçü â@(F¸)T©£$-‚‘Bv´Œ¸Šì÷è8â.Ü"4lÄšÿÐbO§(piQÂèK‹Ö}¯(ípbùËèÁd¬‹ËUè` °y Ä2ŽaøÒnæ8ì8ÑÌ40Æn§OHêëŠê± °‰kðäò!q]%ÂQC޹ú)H6@BÙ',Öæ¯…â!¬ ±°X€€ç‚‘ E/‰¼à-ÖÙ¨8P%àUåࢯ¤*¨e08ÛæÑ‚b¶dŽD¥ÖxP‚ñ^³+¦ìÜÅm˜Ò%v±RÍ :à 4Ô‰ÔÚIôöoHb®f½NŽ bS ²-¨’@ 0Úç ö(Ë<³Mz4†LÔf‡ nfôålGÊHíFÛ€ùä€#HÉ ’tïÊ›.éÑTÔˆ]Ž8‚P"4l x)RMŠrо!¯P½°–c LsMì» ÐdçȪ¸¤š”mRï8âï÷¬ò**ùâ‘~ÍÔk€e8#‚Ú^R8æ@zJ°IìX¨NGq°Òò§Ùc-ÞøàlÉdýl1˜šE{€šã9ï#L¾G2§kÆýÙW9væyõ»2neð…o=Ńûß. ýÑ=Â=³ÁÙÜ!6=ル7›Ç+ÀÚܦqR묶ޓüÈ´ÊJÝÕï(’ä³¥zEƒH†•ÁÑíÙ¬ì¦&#ì@ôº.èxaõx8f.™PŸsüöJaÇ¥yX¦\=«3ÕŒÖmT]÷Å—3(Sfs‘»8\a/¢uªQ²扎ÅvØ&§ÓEÎc¯Ëí7+b¯9Æ®Ö #G×¥ÈÕŠ·ÇbÉ܆ŠþÆX§rhD~c‡‡eê :äÆß;Dú Ö³Îd1¬ä*kˆMd5H&"fŒO¦±ÙÌç3ž³Äª +NÊ\Þsö÷<ÿ—å [X<&¾dá8ÄÆw\Ô½ûÔiEþ ;·à"“[˜#ƒô¿§Ópý&t,Ø®'/ê_-¢PÓÖÒÔ'ÒάëR¯3R—Ötb P!Ošv¶#r4þÅ©%”?RŒÈ‰?éÊø¸£›ÖÖÒIX]Òÿd€7ÒŽþÙô;6TR*EB£°rKLFTUM)z4à`îÂt4MIdhê^˜åÔö:~ÀR®SEA"nó¤7â,ˆHGû ƒ#÷Z,¯¿²zB·¢ ãLö¥{…Zätòvó¥IZh~ÕÔœË!Šç!è5‘@Ùx¬ŽºžEC-´%-ª½T3 n€ÆŸO’Í¿6aèÖχUOm¸ñS°¶¡ÿ1rHŶ®¡Ù4$…+ô\eU^5¢¾)¯±Eúà èAXüÍo¤3+ÿ›7{ËÑ µ| Ù²C’ê`ô…#íÉÀWÁûŠ7‹äìs-itHý¡4ÕÄúx>¬áÓªB;ÔvÜÎݹ9þÏ+ŸÔöŽËˆ—9Ö«ðÿs8¬Yžv†í ·“=·W’KÏ:žhÀIµ<Ñ©e!Ê$’òÚˆ/E‘¬&éXðÿpÏ”¾7ņÃW ‚v  SµÈ?c£}„¼Dબ'#j/3†ÉÈÒ€F¥TÓæIñC$|ˆ”˜Aœ²Ù%iÁøñI’Êo¦1$–²HßÞ“-ñ¥B&FÐ ¹iE‰-EPtì8'm1—4#uÄzM«€*¬ƒ[ïÑ«©uȵLñx›ôÒW%Š8Ëçé+&´èïËj®ËòoSèðÑ"Ó ãà½]BbW } „’¶)BôŸ$Ië±aÑ`2à1(?±È¿'?_+–rÓY$ÉÖÀ*R ¶®‘ï?¨$P+”}É9F\ÚÙ?V ~ш[š^Ju2ÛB$›¤L1Wù)$þ¥•uB­Â½vÚ­ˆ£œŠ*¦Db áž°2𭸺fø‚èú+Š’˜°§‡SÙr 4$}WN"màÓ.\ÔVR¨°?i€·àŠËQ5À2¸KÓøŽŸ6läÕàü"À%ÒFàuE¹3ò¾^3=2T¥ªOMÈ®:åzqXjQ¡D<žßze›µz`”D]“rÌqI€‡iq½HÊEÍ6rM •°a¼ã“=uª ¸$,s-xgNê—±Ù"õMÐ22ð1þ¾·ÆÊ_ tò,ͼÙ` ÙmOÄïmí²Ì6ìlI Û¿¯šc?x4YSžýŠºŽÐ5¶Õý(ä"£ÇI±3Å+Õkè{n}äHlkúGði$ؽ‰fý®K˜%íëŠL>Ÿ\„Æaúž_~œ¶UOž?Kófrvܧ4ÃäóÉ~²ÀK’nãáL äDý£¨^0¥±”êžÉûiÃõ³•¾žŠ‹u’sñõH›aý>|ªÙªÂtæŒÖHsúêRóÒõ]ÚZLM‡%"P6%:dg^Õ‡ÊfÜD<â¶EÈÏÎ vìªH¥ÙsÀzÑK]qú¸¢µËÅöCõ&¨I Í­¥Œ¡qÀr F;|èÙo “å+­Ìcòn‡£ì‡ ru—x¹ (1_&ÄÞSºuçR^¢Õ Ò·5ä9UùÎ|Ô|ââ˜xº lªïzœ’¸t>Ôž3å™Ry(:W—QúÑMȽ_É~¡(ÍeÊ¢Ÿ@:²èIԾɸóý„¾Ól™ŽÛN$ñŽ,êá«®ó}~øw}¨šÏ&ð|3@†+ ¹¯A‚›h䌪=‰Èz@ŠR*šªé/d 'H7Ú$” ñ”4ã¸8òJ)aè¤@@Ï Š£‰Š"+ºLR+ãFˆ2^§ò&°è ЧÀ[£pû›Âœš`+Òݹ—Óú¢¢fáö{ѬóÙ±£U$¨˜;ˉðÛÃ3šl>˜¶Ý0ò·.Rؤ‰ä·ÙæŒôû¹µzú¡ú7Û¡Š=²Ü"(‚¸’È?ج?ËRÃA·*¶³øÆÃ8‡é¢2ú¨»¡øÊ—1ú‰ô.à‰6 š×+c·(…±'2팻ï8cŒˆ¡Œ˜X§8Œ0ÓT<Ë$™ä»¤?˜¡y Ú +9·âÈ È˜;²Ù\(ÙË0a§ÃÍެÛj™t ˆ@ý@KQ…7s‹£½"1êÏ ò3˜Ë’=Ô?*°#Û*lb8¹ÍC,3žYõ¾\t5ã±1öÅ |•æ‹nÈ´¥¤ЬeŸÙKGàÇ Ì$f€)”.› +KEò· LžJˆúÃËÄ©hñ¦iÆ¡‘é¾³¢Âð z6ˆ²"è}—16&ã´!¤”±"ð"НŒuDcP3ds Az¯yҘˡ€ ž ;´£ÃƲïÄs¦j£’ª¡ ö™ •ac\_¡R #ØÂ›‘s)£°1ï,2x€)Ë1AŠÀû®€Àûî“ ,£@š¾ã7XºÜlʘ‡6Ð~·L$Ðù™C&‘‘˜ˆ¡ #ó¼ ~ª¶t¤ž“ÔÆñ  Ñú»Y ˆ·Œ²´šŠ4ŠÌTÇJ¤‰Ûú’H®L©É*›šÁ†©;VÀbÏ:˜‰2¸}"à†JÛÉÀ£»Œaûq‡à·ÍÔ†³ùÉéÈ©§£W=b ˆøù¯ˆóÁ A“鉻›ÀLȬ ºLËàÃ*|^Îd€*z5« ª¦$ò¹}‰–C<3Ãì}“`交5KRB솭Æ%©C?‚–6€M;“ã€3ÊÐ5(AéȼæO¤mŸ¼ô™…ˆb|2Üóo¢ûT´Sï9Š%ºç ¸‡;´œØÃy¼ ±Æ’¾°¢Ï4¼4ÂÂ:¸*ë¼6zË$£E`ªˆë£H¨œ¯è•»tÇ”«šp´¢ óŠä­ÀˆzE„[€$²=Ú~ ¶,¼P£7ªBHÀ°(Û,ŒKI'Ù`š¸Ù†ê*4}gS¨†ÆÏŽ¢!{¶ªÍЦž‘H’l~ ­2ê<žx—µ“U/‰È´*Üá%ì e$JSPkÛÕÒŸVœ— †+¹s äeZt2%ÜY]Ü‚<Ý\CO’»Ñê°¥YÌ+þºy#`ýõÎSºõ®ÂJª{gP›¼¼x” z)&±é0ª?³»Ÿ. 5M²JT©­²IÂ3r(?8Ï<¸XùÅ–À‹Mj LëØ>BÕ"”©çÉ,¸c>½{`î/`CJ02ûøŒ+G·ª=‰¬îÉMR¿¬ º=™eZµÕUqíÂi¢“`©²ž¯³³™¾Q½—â:¤ä-ZjÉ%u,DBP5TœÐ€ ‘Š<˜=”¿¹Œ¡H+òó¼²õ×TÈÉ\ña=ùQ£„Û¶ICûß`=à˜¤,B¦}ë4“ï¹ß“+G‰Ê>L¸*cÑQé4”=êmN–CPà~N\T4˜:¶6°›gZ"ì*…–"eܵZt¼áÍ2¸MIå*Ð/¸¬c×½UU˜·¢#«_$œ_t˜ˆE³©Á4UÊöM¾ŒbÉ"´·$òM Íã -£Ž_ߢ(f=ßC¥+âœG¡Ýýdv8©Ó£]ŠÆµÄa{X^ùH¯Œ=Þ%C[¨…:À‹Ë«ñÄ%ñ×™å4Íf2§”‹¿8õ"]cÎZ‡±yò$èD+`Ÿhiê›v_‰ê,ô3ɃfÎØ¡Z:ÎN ^T åâè[SÚ‘¶¡Ä3ŶqÈKI²jãH4¥“.åÕÒ65²°L†?5¶GÜóz®dÕÁÅŒ@¦Af‰iú›–w׻䞕0ö$:·0Ó!U1Ü9Ý–&‹.Ê!Ȉù'šòŸi3À\㉾5NjT’™F,Èv§ëÞ5´â)ZLz«v¦é¹í“eúâfYó`J#âxK’÷ý%ì´°Á5V‰I,Ò º€¹è}’xŽ8Ÿ]ëÉ N–èVÈ2-«•A¯^DëyE 5­kÛÀ§å”á4¤k–]6vS¢…ǡ̦Õ¨ÎômwT=CܯÕ\ì˹8. ÖTž«dD,äzvF¥éb‹ÄXßÌj±œW-…Ÿí«QbR~-sI[`Ì2ßþ]n46×hÝ"ºoŸ ±õÙûjׅȘÁ¶ xŠ>ÞeNNH"¥?²ŠýK ®Ö)W×Ú°RÖÙf&žæŸY®š<1{ Ûç°Iî°>ÖˆýÕ{„±“ ÞoÕ)äåˆCÈiVË^x'Ù¹ëê±0òŽžÅxÆ.škI.dCV³ªÇB èö§ìûf±›Ò”Îd#3ÁJš"¾l¾›äÝd!Û?FQ sc23s%ÂMvLJ(«•üDNŽ€Ê¤¶»è¨jé•;Mâ 1Û×HIK|`ndRäwá ÇC÷KŸiö%¸M®W¹õ8œx :»½‹jêË$•?•ĺø™`éènW´È‡7N‚É/p_ÉsÆ’k©ï­ÃˆEW8X^Å>w? óÔÝdL“.übv5 )ƒ¢"¶F£Ÿ4ûAE•^Š8Ur•œó¤rÃ1š<¾Ó€;`â%XF„¥Ä•{«bÜTº@^œo‡ÜìD®‚e„ÄN8æu Í*¡Š;‚éLà¹ÕgOÚ((Ý×S÷pÍ­Róà[ûž]¢µr\O#ÿµ®ðl­qÖ9×~òÖ@€:³Ù‹È›©/" ÊÕ)é×¢ ·¯_¼+[¹¾²"ÕåhÕ,XñàXUP¥¦e ›®š<™d¯Ö2K\Ó‡­s:^yOyVè|on57Ÿ»\æ»ÌqxÉ üoˆx °Ãm ±\nî}}yk5!ý„wÊ»hæ>Pñv·‡×Ëã‘qÖxãL®®sÜ•§•‰š÷(°5ˆt‰3¿Št½i XªçÆÝ|j‰‹v}»¾pÝvÏ'Ÿñܺ·;-eüµp~è|’{`¼î:´£7”Œ`•Â=×ãú=ìˆÂ^ÍS'êÕ¶ ²w…¾þk¡úÁ@px ‚€_ðD"ÐØ{ò‰€ ppþEGd'ûîTý–I$’ v]†É rÇìd;”N$ò‰F,œCgHl6;5šAg9$, ª=jÐÙD*6Ò °8ìš*}Ø"tšt²h¤É%éàs”Y*€X¾#vªSš\¼ŽÆdHíEX‘T&uÇô¢•g¯À°xûf#(½YûÍCÃÄs¶Éì¶%ÉZ_ºH;çeœ`s—dýÿ‹J$Šâï$£é±x.3þ;kÊädR`>ú»ð7².œƒŠÑ[7Qh‡Râ€/ÞÏG·E‚Ðó3:Ìo¹R¡ÆßØž>ÝÿOŽDîé»T;N@П鲃¼ ¤è±Ð¸îÚP¡¯€+ ƒ¦H‹d|²`ó·ëN‚³¬zõ'êÈÌ@Œ,•#¯tŸ&À"mÔVާ`:ɪQ ”:¤ß¥Œëðîò"Úˆ k"©!²9ñ²úæ¾Ê3s£°JCÈjh²#²¤L‘Cp€飪’Èò¹h¤ŒÁ¨Q®ëóƒ%¿,R5 jŒ±è¸„²Úü¿%è;;µbͲ «6ò³T4½.€3Ê2‡¨i@Tºu*KR”ù7"lW€/âL€Nœ>𤽢Ͳpò×P}NÅ,“Ùý6'ô%Hoq´qQMð2A¢1úD  ‚qˆ}ÈÜô¥1Ý™7†¤XVJ~e9R†»ïÑ>!)¥IÈ~±øµðÑ™‰MíŦ¦½]ƒ‹™ÐÆlsUÑ l`»¦3>w OzŒ«„Þ§Ô*¶>ÎlÇ•'þN]ØbîÚ Bç¤Z {½jƇ¹·2DIâMêÙò&ýÓY*Uñ9Öö‡á¹Š1ïÌÑ:ÒDµŸèo(¬œ2Åb?Öbdqoî"’'PAK!Ñlåš85ðVÉ›¦ݪ€22ÎŽÚX§†2'¥µKº‰iÁ¹§sîºÉ+å­%£’ãl£BSñi(±Ó; •"Eñ1ð8Ó¢¡`C$_¡í¿æº­b/ÎYw¤v¥&iÑ‚£ñë"†ùÀ, ˜kPª‰c&¤¤q(|ÝEŒ>Ñü=FºkÉ–:rL‚uk¢¦Óv¨˜ ›njÚg=æê>ˆÄI_êm·©2ƒËdUmáò¤üG³ØNþ–VæáÚ–@î+„?!c\Ñ"èÒ6R<@š2o<2î:¦N‰Ý -pËÀWVCZ¼í‹õƬBX¡Pë>_®¦5ÅêÖ_É,YŒùŸEòMእ2Q¨1Õ»PdÁÛ…ª¥ùÄœãáÓŒ4cß<‰$d¤1ïC4Ю$–”o£)`gê †$î_”5’øV,ôœSuÈH?©×ªD…¡Ó¶¡Xø/Î1¸újÏãØ{¶pŸ¥>çÕ09Ѱ…ØqÿRiÓ,ˆü»6FgáROæº.1—Dˆš¤ªºØ—{IÿBKý¡·í:â‰á¯D&Ò§•\O,jÖÜÂ"—_˜Ä°o&;¢€Œ,í<5jJ–|CPºâ˜ãòÖ5:RæiɤÄ+ g˜JIR"ˆI5¾Ôû³m`¶Æê_>¦J!Ô”<$’ù˜©êfÍ´¤Y¤©ÔÀ Õ†æ¦o¸‹Zq÷G8ñÁÕ¦-;°ÞëQ,ˆ.ÉØ) wš +GtîÇ«g½zG⤮–"±UŸ\¯´-‡–ºñøqB{ÇFë¡õˆ\;}‹µ7¼œéµ²û¹ssÚ¼iW%²6Ü%¡];×½WöÕ»N1Ð.gÙ:2Ìâ:š `u˜gc'= »‹"Õ»#ÖaѪõJîE*ŸZïdmˆvÆ £L‰ˆð‚Tî'øÕLAC”¿ƒ6óD¸ÍpšŠÐ6#e )$”Â’’Nz_p®Þ.”-ÖÃD<¬ò /hšc¶}æð!j~ñK禘<¦Î'®CªZ âîØ‹¡ö7KtoÉ0ó…úÂâmŠæÒh0³hNÉÁôûÏ>®):q¤(ðDƒò¾ñ˜ƒÎn’ÉòoÄlŒÂ„êæ‘ñŠðŠWMaq ñ‰ ª <§Õ'q–BEúÑ­»(Ž1' $ËÇíáò¾®ÄÄáþz¢[¯hn,ª Çäš§""³/¡þÁIè^êç4±ú6J²E)~Cææ”}",…nà>CòšO µ'zgØøƒ:ùíi~P®œ # º ÎÄ;ÏüŒƒìÑÞÕEÑÜË ¢þä™hð/ÎÀø teMîÖjœ‘®™qŽ@-,¯dRÓÐgéŠÉà #©ù¤~¨æºÝ¢&BòÜgÊÖ¢ðnQºþbö,‚TËÆ#/Hˆ¼É&¦@Ñ·(‘†r̦ ¬¸üšˆ IíxÅL"”¥Ðk/È„jÑø4E™ §7æ¬Õ~“ÌÉ+VˆÍÒêS|X­vÿöڨ„ùÑ^*4Îh×̲‡bÉìjò&œ‚Å:Ʀ™ÊX6Q\×pLz.Ù ëÞÄn sTSF ±ÍŒ‹*AéG†t’-€J ¼jLç Pr€~é(Ѧ¬Ðe ¼É§’ψáª4HNôGÄZ.I±z|F7:ìgHÍöªâSfT›3RˆS2ä£>ÿ°{ÎPȈ¢¡ÁˆË8Ö£ðª,¬Ðʰm!°»#¢3¤‡o¡ånƧðÐrlEt‘4P;‡~ûñR]ª‚Ö ‡—fjc窻>NŒMåŒ÷­`úííêâ3´ž.02¦gD ç©~íIÌÒs)kÌ6˾އÀ¼t\*ˆ[+\ĉ2óSb K¶Bðôª.BÂËÊ ¬¥#V³îŸ•.µ&Hþ/¢ CÐB(ôjc£ìjÒ²k©øGèÈÑðŽQèd:£s°ÒI±*lë|ãµI ÊØ±dŠ_i?@ÀŸ‚9‚Ç(0®-ô òÕ92ò6Óèí®Ѳâ耉B,.묮Æ|³iA%õ"CÆškÆWL0r‡(=S-¨ÛŽhÙpú"iüïi)ÄhaöûÎH}§ö0L̦•Z“²žKýP°»Sr­r^:-wF 0´F†þ1¼TI+‘1S©Ê%?."Míç´l[e¤ ,$$‘ÒOží±Çk‘í®G rš"-ýM´.QO¾¸z«‰¶¸´*ºãEOµ/k£KhƘþ‹’×ïdór3tëib“5C*⸮"çrÌÀñ¶ýŒ$7Oh~Ñ8ÒqúåÌå*¼±¦»6 €p…b±ôÛ4gMtö™âÐaˆN‚'WXã §oq)äjV¢6CkV åÚSæÍAòþ‘ÞQpöq®ÖÇnuÆàÌJ©£çzƒº"e˜gD:ç¶glìñsu@“71°® lØ”åI0Ozˆh’Œ0±Ìz“&®ÉvE.÷†“2pJªóÂXgG6îNU“+>ÎdM#\6ÉQ#·#B`2ßLáú’Vcn¤í‚}·2„päâ3÷øù Òi—WÈŒ@?8nŒ—¸øDœ¢4Ž*“ò¥ím'}Tm”êlø1ˆò«Ïzo.$H¨Û0Çu¦èГ8‰fñ1Šd(;>Ýã?[m¼$N·„#›€·æªæýJËÏH!|)(žÑ©^®µÄÐY,§ªØ»w „èKjŠìž2‰ˆB]n!¡©’’ËŽÆ»*ı@+R\Æ¥C¸œU8bãÖZ#BgWXÄ:Òxvµwyëÿ‚-_"mXfºJuŠp¡ œ7HÞý®Að\Hî©–Ãd>—æ@Ñ.»(enFº9jáÔ¤‚'F+ªãzÆ!hv³‘X±“*Q;ó‚,[®˜ƒt.ù×HÈÞÙ¯ .u؈ ù 1($IüC³£g&.ùCu×›y4žÈ0oİŸÊMîÃ}ãdjR?>8ˆ:ö¡÷—Âî^TE”ì±0;PÅèË2Ýry8<©ý©_lß ‘bV- Hö#u:jìÕè "˜ ç(%qrûSþ?$;䱡¶¤Ï:‚¨Géø­pÓ—cim“Øâ—wcò¼mYàž'õÅñ‹€Kñ¤ç±h5Ak딊/è>×'Žk•ee¦ñ©ùž ä¬àç§AlTiŠ5>å˜þÂý£”• ³y['[ fe2a!çq­x <;fò±ÉøqBU¦¢6 Íð6…u2zD{0á ÓÔ+T’»m Àûî@èÕaac7RŸxM» VÞqûoȱ‰bY&­;~lHAåj+³\ïЇuŒ%DÄÑh6V^í” ùç?O{—ÑúJó±K BC§°âÃ<®&;r«ðÃ%秊6sŠg ’Š ­0Û¨©1=±«–&d¡uÉ.ÕÂÏi3hRË“œÚ;Vänài°òÓ“8‡T¤nòì¼b¤Ò),»0äpMC"·CÁI)¸±F߃¢ŸÜ;Š˜·ø3‘­ùoRõà'tdô -w„ò?2÷|p23ê+—’±r_Cí9r%V|!øÅ˜Û`P­{uêö1 "_ú@ïIˆñL™µ‹ÐÃ8dò™HSñ·l¼BUÂÂ\’œSãà »ª<.rvPà4Bï©•«h•ýQ#;;䎽‚€ô®ÃBjæ`7'?—‚fÎõHÛ¡°¬´œÊŸÀ®Xñþéhr0>k¡«Ô’ mŒIEé§«ëÉÓÛGƒgølýb©§«xnoÜ¡,ä? ‡n[d÷K}Y{z’§${|¤Öø"]q²gZÉ3H§rªùÈi†}oˆ…¿±ƒ¹Ä¼Ò_nYÓp†2:ÄÒ>Ü—é2~Ê  '7§š1Îl}ˆçn¤öz"ÕŸZù˜å¸ºŠ)•MÝô—#¼³«4ÏärÕ‚É#¬‘ß.݃Â&m“•˺jðæˆÄh~ale£]ÞËˌ苯N6퇹¦õ´ŒLÜI°¦Æ\ܳ¹RW´®%77»~‰%ã‘© ®¯›w2>ºÙ$Vz‹Š kÌOà–.ˆ‰¹÷‡/¸†jû÷2^Uâ®Í&YÔÁp¥‚Íû£…â'øžŒî÷馱¹åœüçØ§]¿3O¼¶4T w8å·Ãí6—{i%ôؼ}Ú‰ÖWN14÷D¹6•;Aög\JM76 ÷¢>àÈ3þ…@€Øt* †C"H³ú1ÆáÏÐ~ üˆFÑ8’>‘Ʋ؄vÿ†Lf38@q5§’hI:Nq F‹%2ìBS¢E!SLAïY¢FÀðGÝB>ú±JßÒÐ,ÆHµW¦4Kê[¾.’™ôB¨»@¦šDúc§ÒaÕÈì’I<Ge4Kd"— ’Tï—ÙD~cK’W±PÊôv{Ÿ/³J$¦S—Ld1 P"CKÀàŸºý.½Kͦ–ú囼ØZ<®–iÆÑãgø|/o¯º“öØ”ÒMçJ”ã%ˆÄW(7à ’ãÝŒGlÙ=zCª¤^£ôJ&–St|j?›Mª¨¡ÍzR·¸‰‹œ~ÀèRÞ¹ëB2ù°‡êÞÅA@ :ò# *È¢" îÈ"Ë£/«Ëxÿ=ÎÙþ’,‘t$ɹªCøâ¸ñ:LÐ QY.Ó”¢$†Ô†ˆ²2̳"ºvžÒr—$¡G̦†,Ï üÖ¡LRÞ˜2ò¼ù*¨C†…6(»ÄÒ©pêñʲ>ˆ(Š0Ý Ó#é¢o+’“D©”úÆH’L’$0³DÆ?‘&â8)*·¹€¬‚t³õ*¥³x’JgÌÔð RÌ}AP¨3Ø—!M”‚BÎRÌ¡339üÁÐ``ËG¯šŽ«ÕÄþL/<éYųb1M¯Œ¿RðùÐó„Ë; M’O(J\?”ôwo§¹þÍG²½˜Å$‹3¼Ú!Ž #ªó^Ö È„£aŸÊòRÅSÊõž®J÷©ùrÍÈCUY•1ø«ÂMÚ³Gs»¾¸ŒúÅ+Ê"—p€sm¤ETõß ÃKì±=# Nx5¡QSTÅTmKÖ‡bçëˆû'8>LÇxÚ,¬ží}Ø~ß²œr%*ãfÁC4~Zƒ$–~t·ÝêZÞŸ-ˉ ¡*¢QѤ†ß;J…²¡Ë}Ÿ®e` _¢Ë“Ž®NH6ÓZ¡™Ì!bS4¢É ÒáP°”Ütò—¢¬ÉJ¼®?RµNWYcJ»ÌI¦ 3çF“p2ÉfM`4œeÓ‰´P (Ž!ËJÔ·Ôq&î(²”§{¥³º`„,Ý`Ÿ)H³ý ¡XŠpŽåÙ¹üÃ!ÎT’TkÕs  Kæwªäý=Û˜\i´áèžAïV;½˜þ4\—ájôãq"Í:@ƒg\¹C=L¼ü—D´Ð»9 ‹nå~Iz^uÎ5Y¼AþÚVbwMªH†2ã°û_{î&¥?!eöH³gíMç±æpÎÛ#>G‰´A ê˜ùæY…¼¥®4ÚÖËøGjÕ?8È ¡jT ÜEÖxŸÛ™K¶ÕÔKTñ\v€é¡åªÓ\ Au±}Q–B}ÒÑѤË&%qÐÕsDžæ²Ì4¯©£‘…ã ÕDOѦ–’B¹6ª¬º™‰U²È‘O«“k…)íMÉFúªùcäñ¬v¦ôH1Kr¥Ò¤V†ØN&YØA ,É¿aQZŽå ¡VûzŸªD:›ê&(+YmNŠ@Šq6(’ùrìÉYYó9 CéŸ7ÉŠ »kRÔhcìjª©À;ñòkÔÄ®)‘}OMÀ°±›±UÊÞŠ/(PK½ÃÔÀ}Ò¼<ý)íò8³“ˆÓ[ãÃõ¬* t——¸N+hÅèÒÂ4‡ ‚ˆBó-T–äG¦ôÃT«e—;#¸×Ôm{j•T€Fv˜,%Ÿª¸·1m¯m±8ŽNO±üŠša3®bGfUéìA¢lT¤Iaö•Ô’¬Î²Fn½éõP&íÄd ìÏ[ì#8ÈCêõDò–~ž¨ýÀÌ%Xóhñêh5çÂz;å=®þÉŒÂäÉäGÏÖ`;X¾‹šX20¥~X Ž ZŸ˜XN~j48w’¤LÈzd‚M1÷‘eù  =š£yæíW,…yK¸®FãJÌQd†,Gì} Sô4Sƈ¼¢C¸«¤."&ò•á÷jéeÌÐR>€:Ræ yþÆ®øˆú²r·‰ ùh‘^'Æ á\SÍdêIågÎ5HáÕ²ÁCð+DY8 —¨M„u êÍóvMfub5\)¿vbyä¼Á»(¡ÇD ¢®:ß3©¸þ1ZÉÛ#ÛwŸ¤úŒ§ðÞ2éò@§YÙ‰5½MäWCÊìGQÑ÷1iÂX¡¦¼$/CÉ‚6¢2…”À5¦fE6 žøƒžÙ‡€lñpòB¶Ñ$h˜©¦ûr¶¨U®’fº+bÇá¼ÖÞëÌ•i“ähç;ê ˆ¹ÈÅãgÉ4Š{S @ûç`·¯XШü#´Ì‚(³‰p+†iŽª KwßYâÌ­êÖ•ëÇ裨R‚zX%øë‰ájªü'Š×–øžükßRÌã­¦@SÖ ý¶ì¤³)ëŠP”Þ¨dä}at÷<£¬FEÏ ñž¼s°~³¦€¢ Î'ñPY£0ª¾l–ìLŠÔ»[–%º¶hý “²"ˆÀÅœ¨–·(އðí@½qå.ólÙ\¹ÀžRC«ùŸã¿°‚‹&‘ 7ã:áé¡£´¸*> Ÿ‡ÙZ¡[޹H+—º)šC“8)¤‰ã<øÿ.âÿy?:9Q‰‹—µ£Òœ€!зàù´ÒúˆØ†$8׋3­øÁ€–©¡©µ¢ï8ˆ%ëP¤J·«À³óޏê9‡£ïªI#ä2Ú„²j¹®(ƒ3K(±³‹Ó«ÊoŽÑO2Ä º¤¶\‰âa¡q§K½ˆšò.z³a÷›IÕS!€—{¬½Ï1|/¹œI+”4>²/¶kÏ8kyÛm+²ª±)÷Á3íÀƒs¯Sê‡Ì €)ø· /¼ú£œó*›ÃœóΙy;¯“ç%Q|Â9á'¹©³Yø;€ã¡9³Ã S$ˆsÈ›^ ód”[µ‰ º ˾‘[Õ¸)ÆlZªÂÚ!ä‹Ìc&ƒ00§4b® T8ñe5õ*Û”ê3ÃöÜCìøýž¾H°È؆Ì!·šÁ 7ëoËCt:q¹+A䥚w7@âH±ÅÒ2Á=´ôœ5GI㌻PF‹5ÇZeîÀèÒÅП*»ï”¬)tCsA­7;+*ª´„K*EÂcb6IG›Ö«â¤•8‡+CðÑc¬³8"ɬ¹YÕ/ÑÞQÔó5ʦ(‰©aº@†¬êˆìŒ3j€:eÀZfMº¡j&\M›ÜY!œáµ|ª0=4#ÑòìÜ,ྦLNšµÏqA >7;»,˜ªAжJõÜ1º õ«¨ÐK\@‹(&ƒÒF „%"˜ú¹ÚΤK³ÂX‚?³Ë¹Š¬ )Ÿ¹ÊÌ,€}!¤{–â–­9 ;¹ØÎ›v ½&a—*DÍÃã/¤4ùR±ú<ƒŽÈB¼‰´¨Á:ã)¼ËXÁE!Oµ©õ?¡žÑÓwƘÑÐ{N Aͪҡhå:9‰œÄJ®²Æ8 óRZ¹â¨)Â'9ÙRΘZ—ÄM5&2‘5 Þœx‹/’Ä/Ð…E6˜ý$ÛD;ôZòÇ à«31¼‚ê´ã)°$¼¥`„ T,D´< PžFø‚MÊ$Ÿù-ôV<1HÜ8Éê‡êe±Z¬ž9=ÃäO8Ôc©."–ÂûëÏ ¼ŒSU!Á¢{@p‡Uð6™¢•p“C¢Tˆ6Û<ÍWIµB$¼„x³*ÌQÄç nº;"¤­'”qgÅÄîÏcS ¢ž‘D>¼\f5’ñ°L&C? ZנѽäÒRÔ É¤;Ti–Ls£¹yGMÑ|›ƒ«#.Á’Ã;)©¸‹³Ò«€Æ|¡—ÑìϤ q«D{¢×€¾ã*"éq±ÊJQ™ì 4J®²ËŒá?h–‘QõÑí7â¼HPÞ|N,õ•Kå3²\G,E|2•£I_Á-¥+\üH=.´³€D¼›Ø×´©«Dw{z‘[϶}®4ÀB¸º1Ý›Iã˜I×*BÁ5‚á+ûyÀö¯p}Û4/µ˜…G {’º'“ô 3¡+©YM¹-2㟳[|Ö¸Ä3¨S2¬Â„N•±×Ì¥ÇYÕF2¥C­¦3Z0Y|°ÜÚ×Õ¬\=E¡ر<úÄ1$IªÓPC'´€‚Qã—Ì|—Ë2…Ó}1ˆó Á|l @y×IŠ±Ýµ—ˆEäÑ#kþ[´¹¨|üÒeíËÄlÝø‹Iê¢ü1Þƒ2*º¥·šŒ‹`Õ ×˜óµùÜ™È Ê ‰Ù7ûä¾I5Í$ü¤i‹“Eª‚# DÙÑ4 ÆAkÒÚD,ß!Š~Å}î*ÄæÁ+¼‚ùDsÐŽ¤†ñÕ-“yª'à6  ¢¢*½ôƳà5È3"Η¤ !0=b֙ݟ8þ1w $¡ÕµÊ¡K"°-QR}Qß#P¦ž5…h”ܸ9¡€¡{ºË‘àc~$9í_‚@¦=0{DqM¦TH¡ÚCܼ ¥o›R‘ؼ tÙ쬦ñåÊ%ßbµBÄÇõŽV¨˜Û5JL…jÜ.+Úö<°¥7Mî–¨ñ+ûü“B`Í]2=™*ÍœÉ`âYeZd±—ÕÌ.\Ó÷€ (×Y<ª¢ù­‚æ]›=œÁŽŸ£GŸV "ƒ»É ¶È¼'dåêb%4¤ 8U²)ÛIaM弬¿.ëó®bžÓ¬:¢™ï[h|+÷4ÙÕb–ÙtXOn€" b$„5€ìTµê9XùÊ€¼¦qž,û }/8•à}&9;Þû:V‚Fé…ÅÓ¥^Ý@¼mz¡L†ßÛÇ¢íÒ`£ÞÀa«¶ËN‰A¨â$X|±u äAÌ^É[SŽ_Œ[̰,³TŠDé.¸ã›±uØ‹ƒ. œ\>ܘ¼¨aÁ 62:à®è¸ÑÖ ΈˆVAP8±.ÃîÃëˆË²¬µ-=ˆ2“ ZQ=„@nËN„08ˆ¦-²ZÐzÚ•£Dq68—‹ÑZ9¸è‡Å i!™cÓäŠ`× ÄUºþ5û.V«ÝŸ|œÂ½p¡01í@ €,‡˜ífir_Þ.ÙMÜm6¸õ*:½5õ<ä|Èë"¤h2^f\ =`®iZzꈤþr°äÚl‹„̨²RêSÄGá=ã½›ã`·ZVš]S^CF¹s;ñÝÕU`{_¸Š`´ÌIz~¢›ÈE¤SÆ€ãí$äæžˆÅœ¯i…oÉ)‰ kð"%X˜Zc½T>Öh‰˜.å ¢öl¨Ó"L…Z˜oÅ,6 ˜áº¢šdþÎn=¬äÞ…Ñ`Ò¤Fàé JåÜ‹4 ~žë£j?ÏjêßY= ´Ž´;×m$ 9\ H€šmÞpØ»^˜º~˜µÉ›µ¿ Væï yäj–Zaûý–^º–{]7ÔnXX |‹ÚMFãW —j­Õ‡å³ !g·eo–Ò:õWÏ.¹!߲އ»“ª+¥Ï™` }ΓÂÜ'J¸º•;44ÑÙÜ]’ÌR¹|‰$%I”ñ|t@®sÖ#XˆÒîŽÀ¥—ŠÐÊŠ–éâ' ÎED¬³/ ôŠ_uOÔ|ÛëÓ\5æz­õ>ç¿cˆº<<ô ™ãØŸnš q“b¢NŽÒ@¤:¢ "C¯±g$:߆‡ÑMÏÝÜS næà~W áé nª…°ðõ¼ÎÒ̺g}\1Ê´C)­ÆÐÁQÍŽì…Á\ÕÏÅ…I~É £©;'0f˜áž-³>U‡Nœ%m%9À±?+À¼Ù³½ GnͳÐCèì*%ékYÏ´ü6ÏI¯–°a‚ÜŒ‘+AãÛŽ¡Û®9èì§âÉ'©”÷¨»h7›>ëÈCȼÂìÿ+“~N•Ó íÛXŒ?+B»§ô6Ž%xQ–"Ÿ†é7|ò16÷Î 30Ú!¢tM¨Ÿo…ýJâªç[/•³qZú,$‹{w(Ñ|t¼Ö?;Ä˲<‚" Dü{3|Ýå·ê¨®0JFô*‚:â>è#¶#°3~…¸J¼ó0:ÔC‡û²§MÛðã½-ô0†¾°ˆÖ·hÌBŽÁl ýBèËÚ£«:ü® ‹Jd©@Hâ"È¥lªB»ží:ÌŠ²p ¼¶Jr„î¦M¢†ò¦HÊĆ-€RÎù>ˆD‹Âª¡ý1§­2dâ$nJ[ 7ð –èJ[`ÞÅðêÆ6SIüÆ?gòSHhthç¿“27Ìà<|¿¯Í<ò #J´°ìj'S‚NÂçú¸±KHôÊ7mÒ'')’RºÒ`El³ÁéêtÎÐÐÚ¨2kÍ&ËUè:³.تƒÔá§ÓRG/%p$WÁ’úâAŽ"è—#o{<ÞTÊâ)öT‰ ÍLB#Qvõ WõMH®\¨Ê¸é·w¤¶7v{ƒ"Ÿ‘ü]Ù4X,éåš8‹:‘Ü•ýÝ)¢ë’@´ j—,'l$‡àÈýC6ηܬ·tâal:Ž®©J?2‹«d®5´«v dëÄ]GÙŒwHôŠÈã`Ü> …=—J©P)ŠFÄÕ´.N¢q¢‹GÙG@5,wT$Ìr.§Å* ˆc"îê!/cÌ lJIJ6¿X¡bât‡JçÑ#\Ê7xˆ¸²Sd¸šY+çb;¹Bz¤Ï IM’õ õZCçxqÍÏ¿wNEX2•ªL¥¢8•bwÍ^5öF lº EÖH"¶’âWLñ Ååa –vA”CNmÐO&†Ñž™IwÀ5Ò—¦_f´Ú¾eÚDÑ¥:t6€%†Hd#G”hª8•‚Z¦ 1M¦'(RêõæHú{³d’LÊjøáš€•¸œ=ªNFáKÉi ÿgSçJ¤ p‡Ø~ 9îAƒ–¨¢· qr!‘HéÒWVHT,u'Iņ²¹HüNŸH¬Éˆœ=kyi&îˆ:Z©T(€S­} ÖX±¿Du|Æ‘¸daã+ €T’Ó¶U$éWá®­ónói£4ˆMÄ)øgg™-³†N¿-ù‡£mv>+ÃgàJàRSñŽˆËæý!Ðo¦Û"¤ì¾Ô'kͤø°µÅŒew¬d’:?aGãhu­+ô'D t#õëÔfÕ@ÉìÛ$fÉv*C¼KKÌ$Y5&›­° D!ù³ëÞÌPÂ¥7¦ µfƪ¢Ï-xúZÌA…ÊÕdŸ«z‘ɬ²“œ8’” Áb5öÃd´®“î¥äT˜Â òÿ@×]µ×õ=ŸÉu%¤)RcGhHQu!ˆNâÿHR I’H,uè­\)_zàGÈö_k¶þ(%¸”JòzúzØ3‰Ø~.”~«Z›ÙA˜®æ"3¶Fg¥y}0ÑâdЍ»(´š“ÑIëÓ´£ŸUç´¸U>óØ E¾¹-i®²{Šh‹Y¿лšˆüHøá>BR¤ºZÁ¿]‰¸é¼UŒ™<¨C:s2b¸ð®‡ÁÙ:±ĸ™¤JÇ£ìºßˆf6õÅm‰n*êäç¯T•’Ì8°ŠìÄ&èI«)ZTY·¡"7±ªH'PK¨¹kÃàŸ:Ñ3~X=+š—&éÂäâ^ô’Nmëi5YÒJÛóØ/=eʸöa›4.ªÕQbøFïMËm†¶­Ú(‘6÷øü§n6²B<¸†Õ™è&ÅH^lÕõq8íOÕ«óVç!JÿsÕ!¿ Û,˜dóIuˆ$Ô1ùIx"¡lý}ó O)ô0¦(…\ÂGÚý!ÎÍ=iƒ„cÁõ!ü87í°Š¼·ÎþðGÄl‹¹±Ä΄V_#k”­øÙ±æOφ #×Z?B$Ma¡å Ü»qŽçM"Ãv߃áO²r/»ûloÏÆj¾Ç绤åA4 WWRÿWLÑaѯnË[’Q ‰åªÂeHOF*d«K9M‚Mr層P.f©EsR—…;  hÑkº¾¸pÔ"“"s'¼É¾jÑ iêgI©Ä™8r‘>KØ÷f¿‚åD0%¹Y'AŽuoU™ˆß˜È€›§ÅäªÒ%7;®,Âåò©ÒúÞ7²Fò„÷gÐäG@ŠD˜Ž VWéDûç²âGL£¶Øçøïª†Á+¬Ï xÜ-†‹Øê Fk˜#®öÍbR{‰"­²¡ü½…Ë ¤‚#æ«H1…>ûgˆ– ö‰‰<#©hÍbu":à'Â!‹>‰ÏȉÒq".ÜÄ:€BSB"ø‰Ì>#d÷¦ f‹(š¯\—',mƒjc‡?B²è .Hy+@×­Dµ VéÅÀPK¤ İíMŽr¢Q&×j º†i 8`!«ØL lP«ŠŠÐUkð… ^mæAŒ¾ymœ“Îî‹ÉKðÈG®¼»h¬­P:v'ÜÊÆÖ ¦0mˆ×B¸R¨q†ËgÔWŒ '¤GÎWëN_"°däCgA¢i-®è1Ÿ‘,†q¸µ1²ÉÑX»çÇRÄñÚÓ»ìúãz„LÐþ‚ä¸k¦ù€¿8T¥H5*w¨€  âÇ ŽŽ¹.nòð$¹N:`Dø:jÏ"-¼| àçR8ñLËâòƒ¦ìN ˜mmt#ãPIJõ‹êiRA)2tEþÂ)޽ÉOÿfäàlÔ—ÍO ¸ì+Â_eH°n¸¢‡/M”M6Njå¬×ÐÔ0©oäu骢¥œ™§À°‡x|%? +`ï ¶uÐÆæaó7¬´ÂNáãê]͘u2r˜+"]È‰Ç š¥Ò‡)Ø‹ðJjHˆþÝáô_P«.ÍY*/,×p0ŠDP¯ËM´sQ¬÷I laìQ3²úJœÿ¢¨)k’›êDÂÊfø1PõGÜ«®FÝKÞØ-A1õÌ/1RÙB0Bî‰Â*ÂË)ü0Cˆ¦"­B_k²‰HfÏM$‡ÃhÑr¢¬ N8W3f)Ž7óZZéª%.X1Ïœ(Oªmq$g…/`oæñë¶´“= n²+Øóêï+PÈCjÄ"e:ƒÈWˆ-8sðPœècR¢»%ÝèmTú„øÞræð&ˆÙ0B‚LÓŽJ} >—Ï£f+Ë-<žÓæY-P\("Þ2†Øæ(ã§-'R÷ólnê°¬õÌPO€»Dí—Æ’k't]Èf¡k²ZÉ®ŽO‹0P¯ç74bkóÔ•b*6Cñ=mg°À—‚ʰ¬Öι!tcî¯þ¸Th‰jБÄ­(òAóELÃË v*å4m>]#ª"먊CCðD0v!BÄL1"&BFÙg0Õjrö*"ún:¡#ð,H@u%æ+Ðúª©³°Bò ܺ…&üÑ0òê¥M*MK¨?ˆÍs¡R;)Jxé…Ï ÁÿT¬’(ÃæU%Òaæ‰ Áöi,ÒÍI7k#ëçèõr©;ëY võ%U"n» óUL`6Pˆ[ë¨Ò$’´2EI|‡#wKÕȤ$:2ˆÍ…ÎgÝ5B€Ì : oˆ›mʦÎÜ¢*9¬™£>SíVËh–ÿIL0¯c¯*È*À“rN? |»ÂR¹écŒM(²w3ízˇq2«éP†kPq#èçòÔÈf•%iˆóÎÌ_k&C%y5€î¤VÔm†NRgÆB:÷«ÜÈM Z´üÌåY‰<åæ…,“ñz}ÔêW•lêUès Þ“mf/HMkâ++i|÷æÓ–0`ȬÄjEÏm$v~ã§ûCLœÏjçÙUmflPÀÚv@ÂÅ.FÓZµ¹OT(à,êì"Â/GŠlAÏT#àt$™Oë0Ó¤FÅÄé4ã Ë¥o g0mŠèÑËð :k3*A’æH–ÞkqYKO.·= î@* ºRòû0sÆRoÃb…¾R°¨Ó’ë]¡ý9sâÏ8 y‡Î;jÖ™»)(ð•Èý Er!+“ºãGE޹lJikWQ.ß7÷µ9öö0–‡´…°¥²p‘Y3m²NhdZKÝR¸T.Âî¬ÓC9rÉx¦³6.©UâvæÖ;vIyâÂÑßOb ªi ŒÀõÃ`!öôR—}BµðàÔDU+|8í¦/X\½V—ÑÅJ®‚‹D~µ nl¢Â–ºKñh.ÚäÔòí‰DwRæ€Q`ÆM}(7|Ì¿U7öÍŠ’GBÅÿ·ð –þÜ’:³–ŸJ,dì°(XŽ+Qˆë«S*C©&ïÂVá0è ˆqæ*7î©óྲ R ,’zl‡GÄýo«PðαFÆC(ØíÎGqxv %u*-™â:Ruª,HV±Úµ†¶ „Â<èR$”º -O¹ªú_ô )ø]_x´‰B¯˜d;jŠ™ƒNÌ׉ÕÈ;t¸"g?rÕs(m TSaø/+aí\C¯z¿¦É1‡Sm@Û¸dñ“D¦òêò‚ ½ˆö_ùc™ÐGï]«Wv QÂuŠÉ"R÷´]\Œã— ¤áú»&’}™jBù®.¹ ©Œ"3Ô%zÞéƒ2ð·÷Òïü\ JÔ©/Ö¢MÜø§x¢úîšö]¸áꡱÏÐûw¥xéÀDu{3‚€P¿{>ýl¹9ÖÿõWùÖako€4k'ú§ª…:§³Z¥yÉ `ÓΠ(”Â:"Ì{3.¸³Ø<÷8»óÏ.h?Ë%ØP^€ùv×Z}ÜMFhØê!™VA1ã× @0ä/rLƒnëÕ=YY­7P”Ëïî“ã~–—Š ¹à„u7Ðaÿ}OYù„v&9ÊUmAYöeIã']æ‰(xy±¶2`ËHGÈ—|‰¥m=·5_è•ï‚¡$]guíÏ¿«ôâCO`ñ+”`:éYPÇGFû«ëL[´ZŤ;wHª™Ì èþ ƒAð—ä. ¿bXMü‹Dâذ÷€d)õ%IÀr˜œ2@”€ß3\Î3Á™ìžHà’Ù³ú[ÉÀ“¹lä¦Q©Ó˜d¾[EœNj lîJú—Äé‹n© ¦Dåôh̾Ÿ¥H(qš`"éFÉ$±(l }ŒËa”Ë< ¬ÿÄëtüN™-‡ahÓÌn'}G_q:5.u"ÆÙ«zÔ‚ ¤\§9idƒWUÄ€ ¸YÜ3c Ñ€i‘¸,2»HÎ!™jF s˜†R/OèÍШ¦è«9<¶‘eä§zx…™oödð]œ2ŸÜh_òÝÕºE]¶údîu2»/¤d ²ùÜf7õ”¨HÈ ¬Gú‘+è‰0Kú@—ºÌýI[˰Mú ÁïÚ"‚2ǼJ¹ÈË,½êÌ.³ {-?I0ËEƒ¼‰ÀGûz”%+³Ò¢³ò”°ð „‚))I:vÌ)Œ³ò‰ø+«[þ×(É{)§-ûÌç-($w£¬ªú¬³ Üi Lpûo«2B(Ÿ$R±øÏñb‚×=ðr²ì3ÏCͽ j^Ú ˆÛÞŒ ­ólßµÉrR¦3ÂI½‚ëµ"? SN"Zš¦ï€͵ÎôÐÁǵjæ3¢NÂÂïE&ÏàL.®¼gå(“¢lÂ7S0)ú¦-C£Aγ´ÉXQz¡]¸Œe­WTšrä ‘„¼ó€ ÓEgÜÌE,ϲ¡uQ6£Þ×¢hu$ˆW|æ6  ál` †Aº2ˆ2È*6ÖÄ'êÌX¢M(Þb…H’=°ßÏrÒ¤…²×Mgo[ â•0‰3r€s-½ ¥, ŠŽË(fJ¤Evâm9R®ºc6€Ø†ÂÀò»iS Öèûyöƒû¦1ˆ‹¬mú·ø"Ée¼b:Ön±Ê*Æ ú7ô²à±¹‰1³–,é*Ó ç„õ´VžRDèøèøýY«(‹(Fz?®IÌɆ±+Þg¨)š1…£þîQ° dPÃäÆQ>û$͇۽i”ÌËUì¬k²Þ+÷…90ŒëYâ‰æ§—ަžÒKœë+"ˆ^¼9Nô«¡®nL¢:£W2±•~­ÛåýbM (Žù™ÍP ¥m ¾_Ì¡Å\ä+lÔbœ³ Ó=]óå­Í"8’Üp>îãëSV–g¦A€ Ž#uwÒÁ“c˜õfF#y¨;Tº§À+¼,¨&@Ð-!¤¶Aàƒ ²eføÎpEÜÓ4³…KnzÓ.“úITÀe$¤Ûõõ(ÖË@BäO!ø °¾Æ¥ÕÖU¡y€QŸtt UÓªÝK¤*ÄÒ„Çh]ÂÆóG%‚7äÏIs21Ä%¯ÆJÕ\TÞ¸±ç€á‹ Mω i "/€&€ÿ™šºÄ ÀúOK¹té½U€‚eŠì4cxKF½ Yu¡’X £‹^Ò ÆÙ.Žs•ØhÈàaÞçt*kR« wœù4V¾£áŽO² ãÕÞ”RË= -—5ç3ƒóƒ®~ˆ‡»É`Nùß&ß&Ñx¸¹ûkÈ Ù}*¸î¦œ!Sç_d­=ðD<ÎÊ_c "K bgœúÅJñ)“ù]§HX*¤×“Í*¾UìY©}¦ˆz§'7ÌF²Û3ïŠÙ‡ïiÕ©o;Á…EF+q\{-'îILŸ·Y€T• õož¸FbÄDÖ-Aîa.‹PZÄ)™ð‰Êz4clòªK“:Ѓ« @(ۤʥ“ ·ËÉȸ3Þ>›b‹±,Ò¸¸ál§ÑÆœŒ¸s‡%äŸI–ò¿¼“È«õ–ñõ¯:5S$¥‰ÕÁ‰å‰(›Úܬ³mÉYà‹)“$ˆç?ñˆ8Jh:’˜I6;e®ªˆB° ¸q<§ ;&Ÿ©`¼Òç:Ø Â"ˆK$Š`¦ãøÁÂõ´¸Û¸8T Áú·(+Ê¥:@·Ãä¦ ÷9¢Ø(¡bBd)ÃÔ8±1"¤éê‡ëFS)sÛ¶TB8±‹#1¨µí®:(/Hà3‰V¦àë3Š ù>øÉ3AEQ,©B]5äD±K§šDPë)€$2‘áÀ„05Ș¾[_½“‰89×€Ì9Ó7ˆKˆKäÄ@›ëM=d ÁÑ9=Jä¾›³dW‹ Ö½: ¤ ¡Ð° Ð3Ô7Ɉ¸|Œ,;‡Ó+™Ú§™8›;’¹{ 4 ö<¼iÀÃnÙ¥‘äZ,»‚–vÊTG”^zÒ’X“µÁyX¤ ™Æpòø›ÿ‹©ê$j9­Œ{%ÛÌžŽ¿ñ¨œG(â4Jœ «ˆºÑ"32aYI“Ï&6 ¬[€  {Zt˜&* Ìf,¤|L5ô*ª´¿²= To°ÂœÈ‚Éx…ŠB1/ ä¡zÌ7Ü}<¥¨£\BbÇ!×@Л&µ³n:³U©ÒñFÒ¬+s¤«»xÐB(’jm>è„‘Ä’6¤Ž¥Ç ˜ ˆ¦ œŒ“Sˆ°—´¢>T ŸZ\#+’Ý *nFÉs âÙK“*+—œ½LéäHI€:Ä )<eŠä"‹È :œT%8)®›,¿:sAÄÂÅ—1L éd½ä°©™4ä@\Ø/@;H(}«;w)rÔ­QâZ‚·,d%CØ€Ë8bÅ9U¤Ỉ+`µƒ3*z8ˆ‰ÚîL”ÅQTŠ8}ÍXÁ.\ľrǤlÆ{±“ûvˆ æ="ö& †ª$G9 ÈÆ»¹Àãu‰+ºV&Ô^žë¹$‰E57N´’ ¡ ¶p…¨-4ÄŽ$ +u"& &¯ "ÍRB‰|ã¸B"À‹CsR"z;3ˆ(¡¾J!sµ$ÓC4»7:š«ÉVÊóÞ%Eu®pë í[€JX%) Òœ?Ôa×Wœ,½™H}6(8Ñ,Å‹é<Ò R?à±Lew7¨Û5Åb*´•UT @’¯&ûŰ ’ŽXº5˜¼êßÑã:d¢¤i<±<ÒJ@Óx~tÊ€*ËDàÕuK으OªÇ*¹ˆñbZ"O¯ §%]KÓ’?%\â«t¼’ÍI ¼Ý¤D~/ôºD-52*%]ȼ/´ÁÃͯÂÅWOÊ÷ÓSÐ]L¤:@¾µ¦º²#‹]Æ=T¡+Ü(q÷È›,-Ë\FhºBúÚx÷³ ¢…ÛeW2»EÎ3Ð@lðˆ$‰’5}f1"¤ÍùYAÓ{.ƒ?Z”a¥ƒaÍDЇÓy5K‚RÄÉ׃ê=œNPrIkøÛ4±´¨ïXSLˆIe”Ľ¸©V•vÑ↲ò&šrnAxLáÏóZ=2«+Úܯ QÝË”Å-ÕÑšÆú1WZ•ØÒÁ#ëÏ\SY¤ªE¥Ï»ˆ4Éj ÛlóÚ%Ø+³=*`»5uÓ«æ_SÌÅéf–%Ô‡óÔ¬ÔHJ4 R{Gýð+uÎD§¼úC7ÁÂO…ŽÜÝAŒ¥(h¬Ø¤­ŠP"Û8•h&%è[mºy³Ë퉰†¶ 4õ±9 ¢Æ¤q€CB„¥U€À»=|ÎÔ7)ËÍJiß´qvGÝ©'¡YTÄ ²‘šE0—´ÔÁõÏ8¦0Zî$m% ÷âsÐbH‹(çD ª­ù9'@ƒ,„ÍQü t-#UÜÉb2ÙÀ\µÊÕeƒÐ!`YÒ핬–3’û1jI)b­h0*±²<Ä ©bWÔÅ4ã¥ÀÑzQâzJÞ8Ä3}*ð–Ï;Ç]S<#Ü\­÷ŸÅàCœ4 únYN*·Åª¬ Ëõ|ˆLóÔ»N1Ò&Š*B-­ŒãTÀ¶:3ËAW 9HÊÝb³½ÛŒÝÛ;龪Ma:TD6ÂR:¢<ÔC‡]~ 9&´Ô( ÍšŽW@ŒdXtž´¼cÚ—Ö}U[׳JgÙtKHÓé%T^ÌèÞ2Õ1 Ô‹ìyQÁsOá—<Î<,MÁSX!*â1Ø“¸ucÓÊ–Ô°¾Ñj<Èà—稄̲VÐ~U+ÕsÖZΖóD…Âܱ¥½øÓÅ(ºX²º¦QËÉ0áä·ŒŠˆ€‡dQs‚Y6*=±Eš¡AÛ®áy¦$þèÖÑ¢¤×Z¥­¸˜ÞB‡(j¤j†¶¢L‰?‡¦áQx±(òуþˆsŸ:yÅk­~Œµ}N@©ƒÁЊÔ;šÛ}PNošD.CöošŒæÁ,éb©›Þ7¢Ë]$ÝRÄAŠwÑÒZD `Eúä|E>ÑâXƒ02Î!ÝÀô`Öýhã–¼ÀZÔOv~Ì'ˆµÂ­q×`=HÂnÕ¼hÑIé9[Nb¤ÝK.L]j{‰.Iß²îì¹Þ €‡aÙŒZÔdi í~*e¨Š$@¬ßH‰âk\ãÀt:0‘qчŽ[`íTV"Lu¢Z×ß?lŸ_î 8,/×%ˆ9qZ“ʰ`éê–]¢&k3˶#ËžÖc•”ìï;ñ%ЦP>‘7Ôƒ°éÙOµÏQÞ ÀÀ£%Êü@Â[¿š¶»èÓž€:8ñ—;^ÏÅ5/Dº†é¢î^Ä dÆJZâãL-ðÙ::8°læq%[“^kpÄjCž84OüC./ÇA~·îñ°œ¨Õ~?²½^pmÎËvM‘ÅuF(×$øä¡*É—6‡°Æ¤¾#PVm%¾œ@‘©ñ% ±º€cù•‘ýu- ­™P¾ñ ÛùŽblï¡€ÇWBì¿ãñçÞÎb§”g•²SÚTHCAATš¶ %¤ TªwhsNuÜ茗ê–oør¤ËÔ¿?ShØ÷Ò2öD5ê:Ñ®|§Mù»zCvw$M®ÜÏŠÕ[]©·-šª¦võ5OïtïÐGMkU J3Õ[–<$Ç9›/ *×øé@¡‰Û³KË‘gKÆZ%z“Õn`Ñ&ê8ûËúìk­Ìw-ÞvhÜÎËÛ¾e ›50ŽÃ§‘æò÷}u¯Lÿ‚A@°p%ù ~Ãa F‚Ä@0(ŽAc¹b-†¿c€7ô¦I “Éáñ8$b1)š?¦P(|Z_ šAgrøµ% ’ÃáoÉêðÊ 1 £Wd€4qó+–E*É„:E3D«38”bu<–Q¦r˜4JmPŸÄ$ë\ÚAÅ&Ó9UVóFá7HVBw2“D¢Öù4!ôÐMe˜ EfÖÃF¤Ti[`öZè%f­ †LóÓ;k÷yŒgª@ ·ƒ¸â¥“:7Y‰g³€>sÿDÿÄR"q Œ*gÕ­ê%±­L‡s&ÀȤ¹7C‘L©€bR Íǽ&ÛK6@x•HŸ¤OÚ²‰*0Š4Aí£ 3öô­nSŠÀÂL ”:¨²²Ä/h²‰1ŠŠ3ÈÂà6€*Ðë!Ïø™±ˆ3†õ¡ ´B…CJr)F¢ÒŸ¸n¬vƒ0“ª2€³Ÿ Û€N:–‡ª)c0¢‘rþ¶J§ü*î!ÌjFÕ!³ µ!‰lŒ?ÈÒÉ4+4¬¯€$à›Mì5ŸªË´ÍËŽ#–“¼Ž­¬‹4N<ªë²+4‚œÖB)ú»H§ šM((Ï€+¸jë4·P.›OMIc^"‹ ’³1Âï±çåÌTõ$$ÌB8E25 CU'ü®ÀXt3¦®¼³Z Á£H³vü¹GOV8UR+ñB ‰šÌŠ,‹ºŽˆ¾àçBŸí<™gŽbvÄX3û ]’ú)×±ø²N³iüýج ÊÉI.$ðÎkÆÁº°å6çNñøÓ´ñàí"’bü篷n3/>6ÿk:¯s·Ae„WbÂò»-ª’' ‘"tçhVh&ÐK¤†:K`~%5ëçÇÔ‡;fí¨Ðp ÐseZexûã™ÌŽLõk¡X´}°ŸÈ³%fV»{‘‡RÈTؤK2³£ D™?"Ú-]ì¶³%°+Õz‚I¶…‰êh’̓dn,b`ˆrŒŒi IïÏÅw WIž;Œe2êAÏžñKÔ?w~(ç0t“¥ÔÈ‚ÌVš úÚ(ÆK—åR=Y~騿„D¾¯°>×ð罊-NéÍ<áÚøù…ùÒ¹†lŸ<.¼ˆCh&á˜áRµd~¨ÌBÈÏEÓ‡¿f0¾–™± ["žÞ¨~¯}~>3Â`ÀûkEi÷³ƒZæ‰Ùd[gu—¬†4ôëãÄ1óÀ% ÿ‡ä:æ,“:õ¡Ý‘„lŒ­T¸ßrPîm17Æö‰ûñg®¥ïRvéŠãEƒõü xŒåV)vcP=}“ó‚Ic2Ãñm¥—º”¢RÆ!P ŠÃþúLB*L±¹X¦@áÌI¶88JyÒÃggÍC§ä’ŠrPvQXó%^D šš]Ä(Ï/…fgHB WòXÇöí‰3æxmП.£NÀ“¬|{e¬ßÁèúäˆá‡ äŽ?Ö®ŠLòK®Ébšun‚W;cM/tÉÒÈ¥Êr)"ÉäFÇñ%عŕ‹ÁI´¤o`¤‰)œˆâÉ‘\xÑõb’÷Êë 9Í€›4upA‘Èûs¥tÏ8çJ~ tY)¥8²:Ä“ ™d„ÑÙx$Uù™ÎÀ ‘$ÄÄY"œ4ˆ]§D±fJ="Ï6Ÿ2­YÂ7zIi«9‚—ÔùJB ™™5wBK»\RWÆÂRêR‡ Á©¯äŠ-#E‰x$™l¦gL5óxÓ–2pÀ™º#‡…äʼn™Gê+VÁ&Qñþ¢çXûA*ð©B©"ÊòD0³è‡Nô T`ÜßiñÅñ+V’˜ý”ÔqOVÁŒ@Lcú¹=ˆÈ?á}IƒŽü§'2²Sœë˜Ä1'ÑZW`¤„ü-h¹Ê7g†¨ÐñW4ÈLSN´ŠykmÍ–ÂòÌž ÅKŠgNÌX:,µV„Ùôr2̧¬‚ _,”>ýHaìr¤ÙZÕº?ëðû;P‚»ZG‡U£ÜŒFÀ–c(””’’nŽ>ÖØŸà€ü?sz4R³Ê„”ôæQП-fj°èÛņ'MkHjïUžäŸ]ª`JBÎZË­G&h,{^ë¬à• qDЇ_HÕxg¼Aœí­ÒIÓ®xf™Ú˜p µZÐ` ìÞuŽv™*.ÉÁFQHõbÛ&œõ׺ß\FùÅÒj@•%é—dÉŠªt=Z¡Ø?cÓt.ÀŽ.Y--b¿Ìrôo5‡/ý´$ÄÁ«‘\Õ?Éån•à=‹pÙ4›w:i°R­¦£ G§Þ•Íé6pf‚^JË…st='Ö²ÇÅ·€Û9ÆIFÒë{D1}z£Y˜Ø“²ú uù“NÍáD’Ä3ŒžEÓ2B•!”_)ÚÂŽ”&TõP/­d¥§wòXüQq2›øïk^Jô+äBj©"ÊÅgÚ¨ªOÔZ·Žää!¿±ñàô{.þV|ü Ù½1ñ„kâ oéyZŒ•>[³tã8vE²T\òS«!œpœ’Ã<ï1JVufĹfÁóûX/ ±¡xø”´iû,ÕäòåêRR†7¬ð«~Úò$myß1®¦\œYf:{üÙãý.ŠŒ z†nF`±Ô ÉžÙÊ•ó{ ŠŒÎo„zö×]Ýutþ“·–¢رFÕF]S¸Òí‰^­¯ÂÔrºíkÀ)ßzæÝõTx÷BFЉŠÉµÛ!1 «VºÀ~¹Š¡¡Æ’j ZÑwƒÑñÞ6H×´Rí’ ìüœ#F¥°)Ž‚“+ê4,˜ÍŠ@.E$Õc–œTèT;ÑW^çNi8ÇO€5-Ó:œç!z±-q¡Å³¯&èDàÚ§*ýXQßJ×оu·ºÄQmä‡`l»hõ?nÁ¡~ç~¦ KmZÙ¶^j±Íj_â4Iô‘ôw†ö4 |ú¬”¶ÍÒŸd®^h¢i'X­cN(ÌÖ¾(Ô©fp¤HÔih(øN+ªû+¬’‡Ö£j¨&ÂÌz$¤+¤V«ÆçÌæT¦®á+Xu l»Íš"LA!ç#öI8I(F\ñ ·äŸêF®:­²×h|ÓÀI„%²¶Ë¦çë˜õeú›Là:oøà-φ4N6‚"pâí¦AixêâóAõJ äÏ6M8$HDêÂÅ"̰™¢×ëlaïFµ¢fÙ%D]«tQc†I.R*pôí ćdšG âJIJ ÜJëî”8Î_ LfÂEïrVêø60 °©nꊇÔôh(dB”®M†½FbØjTP'ïêÙìðùŒrÆÍ„Ʋ6I\»/DÓ0Êz$ĵ§ÆÍÍr¡íJ˜ðªøà‚8väÜ'X¬ä˜?jœ~ÉdýEôû„Ž<Î æðŽ í¬¦¹,غŬ¬‹$ fˆ„†î¶­ÖK«œ½Ñ¦JE¬ A¦ªq¸èPø ŶWÎ Öƒ$ JòŸlºÆ Æ|'dµª¢2RzOPZ扺ãï0Ð"0Ùæ= `Qm‚Æ <ÒÚñŒ'Fo,Ä.Û*0Vä$®Ji&ƒ´hc× «l¼áþŸÂ `IDø"4¢ «PJײ”uGƒ†B@¬8Yâ4¿’ÔKN¶ « J%îháQD"– ¬ë½É áQ$†)àj Ë‚’‰¼¼m:žKr!ÈP(²3Ç*Õ‰‚ÂpÄŸo¤NCA#øžhxáJædñPcß)34|‚,Ŷ;Jñ+‚"E¹$¡)— xÛ±zµq³¤$°N;%IÐfÀÇÍìM¼èr 娜È&Ææ1Lµ&f÷*¬ÈΊÀ/KíÂÆíM¶É® $ÂÈ7B n'¯æµenÄ `ÊÖ-ÌäbvËæ¶^ÔÈ&‚‰n¦&l ¸†0]>F˜#K‚Àf§@2º‹Å@Fû'ë캃:ì¥2#+3Z4Ô¬*zlSH ü9Äþ3€4&À$™5$ I/¤­cªªÓ<†'/Q,‹ÑI,2Þvfc`›Ä$¢K>%.+-óí+„]Ã[r˜jZÙG¤º‘Ù K“6jé:Šr Ð„¤’iJª<“?”°'Í–kø2BE/ºèRHòÄû+ZLQnÝ&¦Ž2]¨@Ò)+ &ÎÑ­ÀÓ»̪ï(šëã‘7n²áå Aö,”HÄ#cøàM_9Ʋ®×QŒ Òìtbf&ÀÍm ÎR—?©3Ï; 7ÛR ÊcI«CÓ8«.¬î….b|ƒ ÁCªw)<´¯ÊÑCz¤Pf+&Ç ¤øúE@Æ´éJô$|2B,³6'gupP$둦¢‹®"2ÐB²s«^²–Ús¦qYd$ƒ°:µ4ý@H¸² ôˆr*ÑhYN*/F¤Iœä³WpV&ѤW8B“]ÑYiM96ÓK±[oâ,Ùì †^¨ \l­‡/u´ùK(# Ü4³4uAbk[oìûJu޶ϳµzôs¨uŒ«°2È:]p¿!D«\”&‰99LÏÉÒ¹'N€bol˜±Õ@V’D“Tƒã&ÖѬÌÓ/ÎÀªûw¡ø^Œ µqhö}!ƒãœÀnlK¨Vf+ÜÑ¯Ø “šRM,((ØPt(Ç;©FŒkUÉ?"7¬š„W=–l¯*ò:t¶íf´É;°^]ªÜ˜2f^–¡~]uªö…¯ë'hÅbŒÇ‚c´“¯×¥D)Úsîþì-z$ ¾‹Z¾%ÔבI§ öAy÷Cs'4(A*äS4ÌrC+)zqî—LfÃO4èXZÐd!‰yu·Ôuû6ÔdðúèJî£Ã$k ]‘ˆ‡•X3;²ŸkO[8¢E~üÃDØÛ+ØÞ;Nï~ˆ ísÒÌ™ËF¡úw‚h:wƒ=‚'E‚4Ó«ZçB8:ô)viÍÁþjîÀ¶òì„Êä#e[Ë3²j!ÊJOã&#d™6Ùq^£PÊøh³âÿw ª–¶£{—‡qF Ëâ<+Üt„%mª‡¶Á\~ú'vbåK4!Úg“8«9<ÏeàmP0Öžm'¸?ÿ¬——£úã¶:¿=):”¯«æ ¸þƒ¡—ü, >À‘[þ Eã7ìn'EaÐ NI%„Æß±0L­õ-‡ÂdRWøi |Íâ I“òy9‘AqˆôbQ‘BgÉÍ ˜Cc0¹Ìµõ Kä8¼ŠEIWèkT¯‚!ó˜ô>E¤Æ·ôv 4H§4›LFO Qbñ;ˆÃDê–ÚÝpÇbñÚ~7 ”J1@ ŽZ7ŒNa4 £ú¢ÿÇ€+Y¬”ƒ#™ÒÓ#ÏèœçGF†Äö;T#7|à{ÛA‰È³Ü'6ÿ¬·oêz“ E´ùöF}·†C \Ú*¶ö1ÛŒ¬Éÿ™½@¢r„G#s…ü½ŠOn¡ÒªË ”4HZ’Á.*ºPb¨ø¡ Kºó¸Ìáú¤¹ˆk¢ $Nº@ã¿­S(:© V:‰ãÇ 4Î˲û=ŽZxŸ Ú ¥±ðâ ÄO“šõD-+.£P<¬ƒ&ÉÇЪ';"ó%8 ŸÒ£î4ñz<»)J”!ð+¼Ñk²™?˜)?ÑkcK@Ê–Æj µ9½±v‰®ÇÅ+̱|ý:M"HóMà~×2 B<¼Ì »9ÉQ¨]ë ÔJÜž%IZPªChlØ£¡ó}?¦• .ɪˆzÏ,Ï€ 9B(“¾®4ôü°Ã ¢âÄó’e»+z/XÄ1Üðà6ˆ\äÙ$Ñ-DÈÂl[èòQeºmåSrÄI¨èȈ%€F§õØ@p ×FËåXº¦‘ÛÏE¨œ.ž!0”:ŠÞ“Èß# ;RØ]Àj‹º7ƒ ¯iÈ H©¨¼^Ý_6Aý½3¢4Ü(äÇ24Ô—WÏExLó€ª#Ì›<6h‹[ËÉ£3[¹³"œè b~4oD~»%Ê7W!iX–À©ëèÆHé&Ylؘ""‡æI–«Sݸî8j'ë…¢êJþ¿@2‹6"zFhSÑ[N¶D ÔˆÉÙ [ãà&þñWdÌïWAúÏë@ _cãwŒAx\‡ó£qg¨Þ ‹^ú=‹7Ì1‹Lh'Äõ¬|Q¥×ÑýÖͱïÌ!+³ÌßX4Õ D˜«|cYIþ{ù`_š‘!èô˹BÔ¥¬”,èÃ| .ÝBãLrOZðˆªŒÀ~A'ÛäÔ¨}¡•41¦ì=y÷ Ý—R‹·Ôºb ð­Í)g*Ž5œ ?Ø1¥!-!È©""ÅÍdƒýý3bZ¤ÇãêOfM[¿²ÒÔvdQl“'\ãR»R‡ý•8BìDÞè@ ¼@ðÚÈ4îÔõÃå8¦ÛªmE çh§Z2½k¨™Ö>“ð2/3/¡]Nï[J¯EøÂU–Ä Éú'…Ú‘wNMÌ…N…Q„&fVQx…%ë•ó H»Š®Áµ„Òi]º¹ Š­78óFšÈ4 žeŽ£ ‹¥mR%C§¸z¯¢Ð8é ‘2Î=eƒbÊ|ˆ ÌÈkËè0!é,eqHP\¢$6j£‘ôˆ¦È‘‚¨|‰”reFfIÌT@­ã$%(åò¯¨°¬dˆ$¨¾8©iH3Jë®=ÄÚû »p‡¼‡¿b 3â’I!  ‘’XÄÜá—sBbBgŠ¦Ø”AsŽ5bLu6Ù©§Šé±yº–âÚ;ISM¬¨‡âx+¤ñ¥>DA š/aóIËvÚ\Kèý$Oj%€Eƒ&bŽˆqFŠ œ »‚5ˆJdàJ€P/LŒ4÷“K—1¤QãêžÔIÀÍ Ó·÷ ¼fNéöd.‚'ŠKf%©Ø}LÒ"õˆÙƒ"r˜œÔúBYÉ ™O$Á̺ÞÜᲆ±×Ŷ 0“¡£ ê'%ä‹Y3p~DV;<“Ñ`ÍA,óºBS|7ì‘ϬªD5,M¼$EØáÖˆÔÑæs„zš9ÉÔä^Ù4kˆí{¶dÅ™bÑœÇ?Bdrhy„ÉÃÕŽ³Íô®z ©×LgD®‹„.Å®0c"Ò!ŠM›óœ Mʬ?ØCœ4zT'µÞÈ!¾¾š#!v Ò™I¾cþwP(ƒåÀZ—IÂ~¬ÉkÀIð”³û·6aª‚v¬û±*ÁÍq+Û¬ÝÕòxK­ª›?ÂìM Ll$‹‡£¸\¦ÝÊm„O&¤è?Õµc{Ç€}¤Z ß4kOv>µMGÉ‘¬ï´ª%:šA9”ج„M…|ë£qy -ŒNkk†î}¹#xÑs¸B+þgԦ摼iLK„9N´Cš¾¨Ä•ï—iXæ±vZÍ0†•tkô”¹‘üùÒ‰ ØÑ’dª¸Ìþeßë•ÀˆCqöŔԡ2¬]ɆíéŒÑeufBÔ:mpIi2§JùÎ>j@dÜ%1ïM"È«§&Ý”aÕ6*Þf§>19lõÎêm8™r)$eW~â˜HýM®%aNI—2¶ŠYOc%£T;E̺ï¯mÙÙH»*\’[°W-—@MÁL‚éŒ4¦#À3‡AE‰*céYÛr®ñaõvè=io¬ÖA¹†2åUŠ`Còx¢Å*mÿs(ˆÔí­!§V»€D>Ý >Šñ_µä$³”–”¼ Ég–#ÒÆBÚFÖ©§šñÙù¼%M£=|½•&Êó#dæ½  pSJjOBǯ• ®X­ç‹×ëj Ëø~ITJǘ(®Ýd:ì‹h¯&#tÆöŽÓšdr?ÙïNžmýÖÉJÃä L\ªBb}‰Ñ·R©•‚ýê?o\èýeá˜Oá¤7_eXIð âeÈžmé5ÊÇÒÒK¥;>#~›Ô¨‚ Yˆ²Ó’-ûIµËty46RôÒw¨ù_Zëšv2£«–Ù­q¸þ%7e{8ªï«gãÛ£RH†¿ãžöx±5W¾ÈÊ™-aµ+¶Òo¹âÕÄžbsX9ÅL }ò³Ió'8ˆ#ß" ž"S °¤ ’º+Ù˜>as´®¨à%3ôhá®Û,¥òÀ5 *9+ý4ñƒ:±\<ËZškÃ$°™š éʳ1#(°¸»«D›°áÀ“ ²Š¡)Ð=; )>ÚšPù ÊV ÅH–ÀØBP‚–H’¹Éª– ß©ö(œ¼—ƒ?9D1¹;k>"ÑA£¼rå”Kã LÛ6»;ʳÃzµ±™ã”ÐÔ™×; ©7`!n€…«A.S – }ŒË ‹Ÿ•« ¹&0 4C”Ä8é;kQ;Êàš@‚ª?8•ŽW7/ à³ô&Ѫ²±w”¡Œ 2ÂLBÁc±=ÀRé;òy Ñ•#â…,Xؽ4©”3ˆ}/9Çœ°ˆ·x².øÌ³BDf¸Â !+Š¢M·Ë§¹¸›‹9çˆ»Ê ŒÊ˵L92“­!Zú" u0!ã©dv:Óûªˆš3ÒÖA“¯€È:©*&¢}!{í¨“.»‚ ŒÌf/ZÂäoAll.xó&É‘ ºl°i"«àªsç¶Ys™” €)`œÂ²"J||eŒ3n¨”4µˆÃ?Ry° ˆ¥zŒD°ƒ–6‚ 2æ¨ì0>¢¼Q"° —®ìu®Ì)EûïR«ðšÚ2‰ ‡¶ëö‡ðÁ¥1+šTfR¯0¨Ò›p›œ$u1‹*ˆY‹$óD!\:t…4ðù8 4(¸ÈHöÂN©9IJ‘¨Ä€È¢¤ a~Á˜–˜ƒb®’­Ór0´Â“k|œk]¶»ÃŒ{:/:¢þÈ„2[Ž>„–7Ë‘álªaÿD‚|HÈ’½1×Dó>Qˆ52K®™®YD´¼ »”´©l«xMÐÇL¬Ë\½ é V‰ºŒœWzA¤„ÍÌ$óÓ5š?=O¶cO8*lÈ<F’GH’³klŸC„»Ô‰-k$²£–¦ËLˆi‹)±ì‰¼Ë6H„)£(°¨Ñš‚(µÜ¡Z0››8I9M|>Ô ÜY¼?œ(ª$îÊ{b(pnPÚ¸<„íÚοìÍ$‰Z9¡à‹Á¢‰!¨Ø$1ï¥.ܪÍ1µð—ƒ½É9‚¦ØÃN‹}º¡š`µƒ ¬RÅCx³‰“ È FÚä€,Kx}¶‘=Èrü9rLª¶Üx4@ÒŽzPyeÀ‚Y±˜†º-$Düå9;”®táL{ð»Ca JÛ“½–[Ób‘»Û¦J㵢ܓ:V,»ÁqaÅ`¯›Ñš‘½JªÔESA ™"ªLÞl®’ñ2ä:°Á_9š$`=h~ $Ĩò [:ÁkÜ)ÃD@&Ë»ˆA[§t²>ÛS¹s•TgÒÛ $ã5µ¼R¯.Ýe§|Ôœž$Òœø-³cÕÄò.ε+í‘ÜmMåP¼@¡ÙZŠüð›SáŸÂE½¨ˆË0| Ñû™' ”±™d”IÅQtŽlJO%dÓüÜÕ£Z‰S%qô;ë.¥DÐQÈCØJa2ùÊ[‚¤4Ø5ÃÃ8P˜Cs"b4ÑÈ’ ‘®QØØ¨íÓ ’(JÒH+‡ýn;œêÄÓèѠѤðá 8‰åkB¸•»Ýgº@=åAŒOS”çK`ÃOâ|©²ä<õ8éŽlà %b.ã€Î›x·eÌ™€KšØÄŒ5K²¤%¡ÙÙ!šM©à|GsÒ«$«Ã0ª›-±*œÂÀ·’«·=9ÃË­YÄH®±N%DÊR«Í¤¦Fƒ•™ÌW²“ÚJÅÂVQ6@ÈXYÛm ÖUÔ»ÁF5®ÁhÓ˜Aiœ¢'‰Aªžœ|´Bò®š,uÂÁ5nŸªä>ÓÅ)dÆ*Ž-äå)¤FâTüÊY‡ÚÐëšåöÞ:x4XZ2(S8Ø(Æ?^/«a䎊ä[›jV8”%5Ö [U›du*} cNGRw\Ä”®Yú2¹QõIÔÅ'+DÜ.â‘߈=M–¡!DÇ]Úp§1"—ñ{бïÓõãˆÜ»]H×Q°Ñááäp ¦OFT˜Ó°­×Žy+©wÅB£@ÃTu¥XâÅ0–˜Exš¿6 ‘Œd8‰s•¹‰»JCx;I鎡IÌ0m­Ž}ÿVŽK¿Šw)|HFiZ÷ªC)îaÝ´)Á6.Ü/ÚM¿‘<@…~RÓ–ÔK´œjl̤¼­ý6°›Ô½!\YÍ(õΜ‰½dÇVò ¨‘`›Òr¬-Y> ªè´Yï³!@¡­ôº»¦ÜØR[Ã_}M`’\Š«ãÄëÊeã7Ú}¼J–Aë ÜíóåùbÓ$ l2æAÖ=“Ɖ@ÅMc]Í´iíÖ²ßf¾ k 1ŠáÂñlÁ ι¥Ñ¤Ä>ž´:©9ZK’V\ïK.=W-¥×¤ë@„Çà>N^|åGS° „1'Åk]à…æøI˜‹"‰\ãç­X5ˆ$WêÖÖ…u d¥I¢cSPa|Õ?³yÁ 0¨ßRÍ;.æ‹î}™ûçJ*³Ã6¡Ê=XÖ‡ê®Õ©<¯VNÞ…KJ!ݤկ«hN¦â§¾mìž6Íòº–=‡ãÔàËåc𑼻 ½Ã²sE:Õs€Aƒkadü]´í¯ qxkœ‹Õ\¸9²ÇÀ*9=DË’êb„¡©®Ì–;P­ßÖ:€ß!šR” ß¹ å3Žtk–ÌïUØŠñ,:píE‡ä_ ÖÍ®!”£’§s=™ “±-qß`Ñx…¹ÉÕ 8…æ`4=WkÓ©²Ùfzl’¾‡F,¬È3zÂÉ¢Ûõé ¦>)5XèÑ>£½ö2jî:®ÜõÒ ¹jy±KƒÍUÎÊ •¨–Àd14ÍBî_ß³h”Qòw6ô·‚• £Æ²I yÃìÞcØÞŒ€à(ÞѸ)Z#ó£ã6¿Rjò¶ÌÞ8§PÄ jTïQƒU¾n¿’Os‹ÉaáW×b.RÂ¬Õ }açýw¼‚›`» \'Á+Î$æä;St'E”ÞXôbÜꉭò˜}dö•å)™Ž[å!б½ã)ÌEJröw˜”Ï—lO&¹­{ÔÖuÐŽkn˜Cø9kI>.™¯4Aܣܬ°„v¥Ê'n’S-NC …YÒ*œL´Ò£¬«í½«a”îÑ4_k‰¹2¶„™¥LùuöÅ([ëæŽê¼¥/ tÔæ5MS6Ñ:)UŒ¾>œEµ™F4À)ÙR®#Û›TÅø ˜EVEó±ýFE9ˆó6ÑW3¤qCØÛ¯€Q· yïGÕÂí;OjÔ'ï<¼çU 䄦&Èɶ°„%3®ã¾Ö Èˆß¹M £+’µb®š —¹> ¯=áâ,yªÆ&Œ]¾ZŒ¸Ø/ ¶ùEîÈžgt³o#{ész6ò 2‚ç@ñü¦.‹”äh”kÓ–è¿ &^m#DðÁÊš&áïDN|!èìò=Õ€tì%ªÛRðæé<u÷"]27kPlÐ'69ñX|kp¸ã~¥s¢’¬Š€ š1…ïæ ˆôA_Pp $ „€_ÐøX ïE@ñwüf*zÇ` HŒFþ‘Cß’xl  ~Ëa²04ÆZý}Íe08Ü67#Ïb³©ôn2ÿ—Ãá´ í…•Dcrwä~‡<ŠÒ¢±+úTÚ®>+Òjû°æs8üÎcʨ3:\G„Ìär©TŽí•R(s0.s ¥¿í‘ø-Ž¡µBcöùmb‘Ô(tê¬j+}„Þaó¹4Ÿ£Þäu¨`Հ̎h ÚLàï¨nº‘Ðèu –{O|ñaº;o9GÂï¶\¨"gc¦Â÷™ø­BÛxHúÉœF?cÓdåZl,F‡×Ô£{{vn¿“Èãö¹¬lû½lwϲ ×*hz>¨%L›\¨AÊfË#,B è;¨{n¬¬*Æñ «ºþŸ°•2è\ ¡ëD7¥°“â(nFÜ£+’!ˆR© zç4odjª SFá8§ÊGÀ(Ì„é?ÌÓ¢[Y‹„˜‡¸.äj³ÅlÉþð¡rP )ˆä¨4r×: 6ä¾Y'! Ñé½f…øU×ÏìU–‘¤ïbgu¤7ÏŽÈŒ&èâR”J¼{ºª7#¨u÷€Âß8·‰ 9³>ý³;÷5¦µµ"UPþvl§Þc=° ¨SmE:•òñÑ bŒÜÒ,‚RA¥iƒøö3óÒ[R#j%LÇ|ÔÌš€SlYê¥âA+»eƒú6øHHb3&®–3n\•Š"cÝ@Óh\A`_ÄTǶR R¹þv®½*/RòŠ“È[ 8D´EÐ’ÌÅ]1˜Xœë%1Æ$š¦ ÅÐqŽ1 µ˜¦ª‚‰#ôõºµpyÏó‰g´oG•¤ôTBsO„…Á¶C`+÷€mlÂÇÀ™ ðø}+U‚B50ð!†ñBÆèÈ\ãfH¨~ÓzÅnâ@‘¬Bo&g¬ãØRB.Wq²7t¯à]Ánµî´¢b`"¿Y•%š›)ݨ¬ˆkå©UÂé ß3Êj±Ú“ÉÛ0Ì*ÒœµhÙsLkŒšÐh,ŒÛ°lþä’€léJÜVï=e Å9ÅfÍÏ;ßoWaª­’LÕTë)±}fù:âÆõKæåS‰g5\¡í»¦dfú~ÝGdv±Ëc`LUÙN¸fÕMâ³I ÎQ~Ë1 Ú&?³“6ó‘T t½}W÷0¥ €Òêy´÷Lk#d'½ÜSBc/T€euðîFvT”¨Í$8K0äXìÌYðöºÅ’7«é<ãyju°+T¥%fòÎÑäµîèUDAÝš íë'¬˜¾cµ7d7‚@ž?HmŠ6üM¯—É‚Mg1¦õ¨‹¨“؇®ƒì»ŠôÁGÛ²IØÜM^NI†6ë)Ll£ÙùµèN¸) LC}ZiÛÓá8¼7ÒÇRÌžcCÌѱÚ"‚ù Ä¿•"T\õ1¬Úu­¥dÞœ5 ­Ä{ˆ¡·©å¸µÅ¤4Qh”,•]Ø·Aä|ñdš®Ü>X-s”“û¹L‹ õÕÜòø½Œ+¼VHí²øÞ6X4úSfà—¤Lᆕ¶»ñö¿ôIÕ|²!;­öÙžçEðaZõ+ ¦ÖÛíXù®4sö¶K•BÅ•îEõjÅ+>7‘]®¬šwêŠySUŒNô›/nfv1­Æ=­œ¯Hê…£|¦¸ÖljaF^B|¶Fâ̧ØáF¿Î,îL>´>ÿ‹¬aN®p„L„kb>ŸO,*" èâè¥"bÌ&ÔýEò{ð&ƒPhæôÚF­ð ›ÉÔ¤ áÎ*r«:ÃŒ¢÷ïfòm<øM¶ÿÇVÍÄJÏ€ÎëZ,iT#jÄç *BC&ˆ± äZZCTYpèCÿʼ~車do°~ål¬ì^ú’L¤a†œ–.æci²îô"¯¤á°Àÿšÿ…²Øé`jO;  ‹4uDÊ&­ðê¬8ÁîTY‚³ åæ6H6ê ʵ¥6¯ã$&)Ž ‘¯TˆPèlišyP¢!ì4Æbh/ÊoçPÿnäé«Zñ `Ä)ú°ä³èÖ¼îMHnñÌÜÃæ)ÔðâbË4d.<Ñ1€&e Á"²&qHƬi ðW‡Î’k„JÇ Kɘ‰É³ï°Úf¦."0tÌŠ‘槃ؙl´!)ýbƺbí°ö!ìAQ˜ ãF{¯V}ìLæôŸL‘ Âðø1€®þ¹±tÐådI¨’KžñÉ"â +´Ý¢Å1p\Ï@ÊJD 8†jÚ°€\@F±\ K€ªÑÆÜ)Ô­dŽªè¨cñ p’Ä&o©ñ"1„sÇ4¸‡ŠÈÅ®Á€sº~E0±¨6Í0(êÍr„F6”€Ë‘æI¼Hér¼g€¢O*^Ȇ ñö.b»²#ã&Hí`g)í$èȴЦûCŠî¦Nµ„å%jŒ¥HHÚÎ>!¨nûÎþ(e´Bƒ­¸²C&N«­2â÷/¾¶+Ø£²¬²¨ …"ΩL¾KLj¬É ©±†žb?,„ØìÇîBFB`„Ee ÇîL†Žù’> i¢Rè,‘¼¨˜þ‚g!B'¦’Õ2(ã]'è˜jR8’NÊöB{¬ð¢ÃY0BÀdnð'âz`r$éô¯°33!ÿ*ì˜J²ÞaöÚ îâ K9aø) #>S™)sƒl ‰Êê"q=«äG4SrØoQt⬘zKð±jg,«Ú(írnt1Mf¼Y*I#ÏN¸E6…K„9co2ƒ²¥r²ÎPŸsÈÃpz·ÒÂÞçÜ×&@‰Æ¾îÀ³çÈÔó”po²2Ë,+3\îI$n!1"jºÚ¾xóF:p<{§aW3´«¥q>¬kƒŽ)‹G,”^Ô-é:FnîÒôPŸ*!eìî+W˜«nïjÄHJoZØ­|e6nÇ®U#CFÝèì„T).·•Å“56'Õ?¬@,tœø¾´,8úâ2òPž–“6x 15ƒ™_: s:<ßÙñäùÉU™•‘Ša6ŸÈž¢?£¹XŒZö^ý …ŠÎ4ô,whÔé©pŸ]Æ‘­ÿÅÄ„ô²ãF‘º.{ÇQGNþqµ'“0—Cla€0q5C™†JVí¹p¡öç#¿±çº‘¤Ad³w|ʤ8ªm9vÚ,X;vâjW#UÃÛrJZý]cü0£'Ÿ6Å_µÐ9Ú‡µ òKl4‹‘¿N÷€Í•ïó%.T™;j—§ì%Q¡†™ÏEÊ-³â¿/1Ç®XD38Æ»iW«ƒµÛSœCÑîllYŽ\…k±ÔT—ÃÈu]ËT‹Dxùµ³yK…¡²¢7©B€"NoE%»Ù„,¢–‹#RÝks_ªºøÃ¬ò}Š£HmÈŽÿˆ ¦_´Bèæ6©i\ÃBV 'ƦHJÄa ìÚòà Ÿ:M"œeg“®DN”Y™o˜k°#{¦­ßŽÛŸÐbE¯b®æÝ½ ª0Í”4"´Sj Õ@SOðÿÒØŽÄ/‚bŸº;Ô•Ñ$%³8KÄ­~ŠÑM© wœsM)£.ã7PJÉ;É„sñÄ MYÆZ …$­­wòÕÏ|£ª˜µ—ðlfc̘dcØ5D`ûN\-TÜ[û™ýÍO&ßí üûñuž¢+ììíñÏTð"´å6ë㯸ZÁ5Ç©›‚BüÞi¬À™IÞ%S€Ýò–b‘YÍOýÓâ±S¿1ð–`.šâNÆpž+ öÊ|¦ÊеX"7G˼}¶Yý«_ÉýÏúücœ"-*JÍp¦Zƒ~Õ|Ÿeâ?à(0ÿBáÀ>‚âè´^‡Å`Xóê@‘?$‘˜XQ~Êáhd­û‹É’ $< }N&Ó‰”ZŸ@§©\&1G(±hm>4†E爴±6˜>ë•àÁ/•Æ –Güâ9 šPÀ35q÷(Ç&z„¶x¶Øéйt.M ÀСõ€ BaL‡Åñ‘kDRqw§ÝqµL-æÃEî’»eFifÔÂmr©Å´sGμ±šBlg¾ßG Ç€àÙGôÿDË€f›W§GšC7Q¸®7­QâZ·ôâåpË Õgõe A7}Ø—žŽx4Þ4Íf8¼^ù˜moP˃ØÃ<Çú8|@­Úpš4p)ðA©Òþ7k‚`¹"ïÌ&bë& Ãj÷5 ²D=o#‹6q;¸ú:/CñÉ¢hè½H¤6®ÈZpò«:’ƒ1J’·@ n{´oÚÀŽ'J„Þ³È|pô¢; Àªlx­«¢ÀœK§Ú.›?(ä0œ4rCk4¨¿>‹RH¶.â›,ÏcjΩR;n¹Ôlë'‰·»Ã¢ÐÒ›&Ã"¾æƒÉÒ"Y8€3Í•¶©…¢âžè¹I$K4¨”„Á«zŸ6"‰µ{Kà4î&u[„-4ÙûDÈ(¤£?NÒ;2Hl ʪ4ÃBÖ#Örô„ÔŠª›¶ó°”¯ T³Ï  2µèåf6 LRB·ÉfÇs½„[‰*›. ¢{eÑWÐßC3ž.Zi"8¸:*ƒjàQ5,ʧ ÓܨWŠò(¸?ˆ[îaXEú®#†ÆWZ€t«½L2¬5y$#û{H`·ck‚äš. æ~Z*}>C«9c Y"÷b"ÍSâ’c·º&ÈKäŠ4oΘËxulºˆŽ{ K’ \6ºæ\• ÍÊ $Cê4k‚mQ/‡óü®CóPï¼õ>Ñ‘Åy ËÑ\Mr쑊qefõ A`_6ßC©[’úX¨ówG ÜS:\ÑÄ~Æ–,×ÉTåKU4b’½29Ä›8Dr·Ä!0+c·x|Vs§ÙË‚£¹¡YË´Ç!é¥Üè©9¾r韹©ôö.X[Ù¼$[$›O©‚×;Âqþ›>ȶÒÓgßø£Ì®ŸÝ`PZƒùè´òl’þD@È7²FI šRèÙJ“f³Z+R%¹¨Ç®lKƒôl©ø†#}ÐÁ:|ïùœ?ãÜñ YpŽ]Õ>¶ªf`$},"±æryÚY˜®" ZF1 ¬‚¢mZ| ­9ê»U€¥aLJlõ8;F.ÑÓ8p„„¶8(HëÍF 4ëªhÔ„A% †è“€ë ŠdPäMwf«2XuZ8t´áÏc 8„‘R&Ô“Ôaç7ÈÕ¦s¶Ó΋ÔÄqt˜îxßù¼>‰ôü€©H¨Õ `?-õQ´ªÞûJlÄpãDF¾äñ†“¬$®w6ÕPüTŒT‹J@M J7jƒð¨ºÄ¶ÌØ 8)*À‰E¥ HŸÄ¶€DxÀŸ•tØc\Jñ.B`háÈ~‹ í°¹ÊG‰¡:˜’ZGÅ,ãGÙµ~NÌtÜUÏ£ý\„%LLåzc]c•vÊZGP¨m(ÌjšZMG‘þûe? ªÄA å2j6ôLj2>izQ+9m‘E6›¡·!+¹î•(Jç<¿HOîxBïb”k'$Ìd@aJ@ ¤ÒBHbm=‹âšµß¤ó&¡É,U"$ËØåTv ¥®§OccEî ƒ¼™¦ÀdŠrS¯ôÃ<úÆNp¢&2• [óc2âA½'ü¾Z OÉôÝžzúüô€‹²ËÝiïEï¿Ó· ɾ“Á¥Y^iò–ŒL Ñ‘ÃòûÒÛ+–x}@•ITcŒ@ TZÔú¬?—t¦Tj&jAñX‰ô­5î=Pâ/,. ;!‘”}Á©ubToÞj°BV\-ù+ajÝAJׯA& CΨàKùK¢]p0DJ€W(à\"²0‘¿ŒÉ©"®€Š^‹ºÊdš‰#FAyôhÛs©PÈF<®(‰I!6Ö zEííL¬ŒæIawXè«\i]ˆ þÎÐ V}çj ±î»!û+IÕ¯Jηßl&ÀÛyÀR³ò%LÖJWq®5ô•á*Ñy¯ÚSžH«ÀE/K:*IÖÉ÷g„¡r±ÝÏ¥xî#J{,Öd $1t`µÀjË„bX§X—«;"È-ž¨ÿN‹ÒÊöžÚ¢¼ïHaµ!$ëÈ]CÕ╸êy “‡ìçkd‘º«Xká(}ùí¥ÉævͪveA’-{¬Äžg˜?*Ë#@¦Cþ™tTé’`gË €Ä£ºªÀ%‘4¥f++BMkÖíƒHÈÜQéÆÑ¢XåÈè«+]¨ºÎZÝÐÓ´±!+4ô)/už½ºÔæ „A”2MúD¥Ym£VÆ¥"?#í-­°¾*™ŠøÞú¡”îVËŸ/ÔZxD  »kƿȚ^ Žò#MÑw ž®Z ˜˜KT³²ô–Ç+ŽúŠA£ Þ97ΕažÅHL™ØÜV0ó…~{H}Z¥uækÙ)=coœ¿iØ… ½wÑ&È›øÁB»äuuâ`àÃñ 38³ÀPú@}‰ÀkÁQ*Ó¸3%@×»Ér-€}’ÚV•à„Ëæ$Ca¨²„¾aÏéÈÒ]—ݯ«b7÷ªª8Á˜=¨É¥3(‘‹ Âp}±p:‹ã^T³IFAD¤Ã¨{N‡ËÝœ¨Ï™É!&1Ù©[3+T+!Qa˜ãðŠzÈŒ3ØÝ¬˜®,iä#JE½aÖ‰!>(Ù)ÈÂay¿CòŸi#6R²Œö Á¯¢š‘ÂÕ¤›L®ÌO¹ã¹â´³O€;ߎó ›3Í€ ‘PŠx¹Òÿâ´¯(ˆŸ{ˆòá´I›*K¦³û~(«á¤ò¼©t°¬%99 JÂJýêš›<|W1úŸ¡³j ËM  9Óˆˆ¨•c®Ãý2¼5¸ +šî<8ºéaÄk,k ÙÈ €¶!iFyÖ.¹Â48°.! -’˜ ô€ ÆÅ³‘—gŸ‰/à 16¨°ë‚_‹“%›‰`tUÀá–Ðá§“ö.ƒò.!>¾Ñ-¸x‡Â,,ø2¹ÖDk/½ƒY$»Œé–Ÿr¿Âô Áþ¸a1ÂàÆŠü0€ ,${ÈñQ“iØÊbË÷%T³Ó( ‹’BbAw$ƒÇê† »®+Î"›cCê6”nœ9›²»“­˜ì.ÄaZt”d­±  ‹$B­Bë”Ü€¨¸ƒDˆ" íµx÷8 ±€d˽î1©œ¾©Õ3Ð…®sc>Â’ÇË[«ïC3\¿«©Ù!0[è Ç¢"¸É$¹;ljÌH‚]' >û¤H~ËŒ%l´2¹÷‹cíNJSI |D'ê Y·²»J;ñ‹ºð ³8­kÆ-ëv7(ˆ“é¤%ÌɾûÞ¤ô?@~'2k›,½ÁÈ¢ú5«F”’¨*})-¡Ü“6kâ®öü<¤{ÎÌ›QpΤiÀÉF‰þ•ÂÓÙ·Å-¾QÚ=ûH¬l‚ÊgÄÖ€!ÒH\æÄNKØ1¢V‹Ô[3aˆ3Õ¨t00³â6Ä9B€‰¤âÁD˜ú3XÀF”l§«QìoÈœrË‚O»c9}¸‡Ý9;ßÊ2C‰ž¼»ô·‰¸Pp†Í2¾ùÜœ$P;#IèÁ|s)úJ–¨„7ÂD¨¶ÂÑSõ”­ [Œ:Râ>~8Ûß @¬D9tÀ/ð¶"PëFä/Á‘«¬#¿Cö™ì–"ï ”c“hTœ¹:ìz²‘"¸a§—dò¨¡Ê®ÓÎÌñ¹l•! +OóⲚÿ€"q‰$w¦R†ÊŠ‹>ÄÈ ,,hïJ)F:«Øžì->ühM¸~° žÒܧ¶`Æ4ÇRSD Á<ñ­ëÝ©ÔþB_»Kõ’‚Ÿ° ÅG!^MR­3…‚Vµ©Wµ»+ÌPÛŸÈÒMÃu¥1'¢~=‹¦Ç۟Ѫӄ³i$+H”Å,=üµxÑ•ÂV¿tPCbµ-Ü;«SÌÌm&C¡1X\¬‘[ß²¼õðÚÙKÒÅ ÐÏ«>Ùx°GŠ©–CÊ:¬ÌÈœBDAúŸÖÐQkXëTd6˜D“É9ž¨ ÔQ ;½ ¨ÍƒÑùÉÚÒá ßÓµI‹5A¨µB•"Ó«Ì{¿¶éaÈD)|"Ùš‚¯ý# B9°„Ã2¢„bÎ ”óó%R5UpIr7ò‹,‹ Ö ‡¬‰Ê¥&(±‡Rm¸¹ª¤±GÍÁ6Óà}me ˆõ#² ~²;:@‘+DÄ%Pß<Ó1”KÝ Õ@ÚÝI—„™Ø«0  ±#åÕ Š#9ó,$ò%X¥×+»c3„Iåϵ¼Œ·;.ÌÛv“º¼ËE¶Ü<Ù¯ô­Zå±D;Áëà25O‡áÐÉÈ@»“%ü¿6ÊWP}U’ÌÜNÊe²ƒ[Ça\&«TYD±ÚëF¦ú|‘ ø©Ú% óLMléÁ­ªE‹TÑH} ´qU;•$X'â/88ÆÛ¥@ U5½à«{«T„Q„J9³Jƒ¶1!Ìš%38Ûbd´Œ¹Ó…·óäÊ;qᦲÐʈ³z?²`0œL¸ ÑŸ‰DÌÌ%E¶²ŸÕ\ëQdQX…½¼`4½{2Þ•ÄâЊ=úOÛâ=8‰2j5^DÒÓSO³Å^å.8"ìR´UJ@’.¨jCS/lZÜæ‡ëÝØi¢_Ç,Ñ€ŽôÑR¨U⥑µj<^1‰½É æN/$ƒ¬ú žW×Uaà%eÔ딪3õžüW1©Š}S²ÞŽ ÃÔ3¤Gœ;ßÛŠÝŦÐÛWUùÕíY±Z¤±cH®’o§ÁkBº‘S²UGLø^Ìôzx%&5¿ÑžÒ¤¹•Ñ”ºÎ¬xõ¤¬¥æm#F äô3!Cžµ+q-@ê߃/²Î0‡Òõº)Õ訶vjI[m@vW¥ÈÏÞwR¡þ¤BþdaKï©]¡”²ìa£ÄË÷=p‹3ÀÖý™QDŠz{AÂg¸÷Êr%CÛV[è˜ðz¥S¦Á¤Ó@úaLÞ«ßÙ8ße‘€;ÀIééúil븼ßÈÂfÕRF•ûâ@×½ûn3¦PXµŽ¢Am{2¹þ¥U†,-ÎYÃà!-Ô›¶èÈáà]1£Ì=.DQƬΨ¼¶¢ ÛÐËØÁóî=•!·æeúÁÆPI•1à†9M©kåôz$õàÀë‹@ÞtÄ×§åLj|i¼ù¤CìA©Im²™: HÚø Õ$ 5‹;„)ÚD©¦ý–óÇí¥Ëö¥hʽÜìÉ‹é¢P"ˆ½ÕÙš iÈjÓ-Ù§ÔàˆÛuß ÑwDaÅ|‚X "ìh÷Hì­Ù˜˜Æ(Åó~ªìÜgó˼þ\‹TF¬'汈yФyÆ´Ó@ ”M*"`¼ý´#b~\mòºÐ•âHLþ8I¾dŠìjÞÈÒOÝ”K!¾+»aT‡Ø†$@¸*ÆE9›ÜŒ’,¼RL$XY¶NJàÊ'F¶ÙªÉÙX¹f=­· ã-™NUúÞ¨ì»2+òçªÈUëXµY™î´ÛÎ1H6T»›îå6ùË0ÊÐó“ën©Uø¬B0Þ„Ñò­j(Ö¿)nKkŽwŸ8©»ÎS“é9þÂÀ²ý¨gµ±¢>zÓ÷Gú®^Gd*©‘À¹ †aiN‘˜\LêÆÍ—eŽˆ7{óaƒ {®lòþ¿hâµTš~ ßX!ÑߎýD´GhÒIžßâeä¡N€.Ýò»Á×ø…í¦O`d0¨t¤‰-’` Õz~5ø °ÊcÿªKïÆOsųī4gÊÂxÁ`'ÉDëã¿X7‘S³È>ù\*;‘¢4S[HEí4ˆ‹Ññžª?Po Ž–Íè[æû«ÔB =DFoÖz‡áúP…Òļ–i,"A>ÛtLòD-+u××»1Š‹6¿$DÃ1\i^N«;7¼e£âuãNGsä÷|mÆ5Þ±ÿa`p÷çúö­Q–¾('Ìð0 é m”¨¨ÅÓd6ÿ¸”H°ÆTybbwýä¥üVdH° ×5ñ–ÆI¯“8#.:¸€ð0ù‚ÂaOèd4 Da £î,ýŒE#@v5 ƒ¿!°7ütŠI¢ G̶U‚¾¦R¹$µòœHcR¸ÔY÷ •Ê0¨,’I ƒÉ¤’i460ý¡êTøÐ­$†Ñ!RHÜR± ¥QŸõ`,iíg©åàHLŽÅG¢CdÓ¸>Òø¼NèÔ’Ó\ŠR$PÈH ™>£V›zv©Ca·@$j>¦G°4HýNŒJåsé$‡ Hl–KuµBÅÔ¤ÚhŶiŸh¢3ë& ËdŸÐ›M¦mOÆ€oð>MòSÐSßµš&è aÓä’»NÑû]¡çŸô*ÖRIx|½Sipw¯YÐc3ª«Hdžé´›ˆ©#G¼µ­*zÀ< ¾'ŒrÞ·²L÷7вž†¥jzÈ›@ìú "ÈK’ú$+“2­?Ìâ(è¹.’0²?Hû+ªŠ¤Á5(;zñ#PÓòƒ›2 ì¦-*¼´¼Ê0á8oþµ#¨J|´µ­b+«#ð-* ı(K~ª3`~§Íü¨†&É"É" ¯ê:í9ˆêɵï" ¤£­*í¦Š§½Ë{°¥£®s”Ù: $ö~Mgóg*É[п@V°NhÊ(îÐm #DOrïLHzz‹> &~#Q(¯OBÈŸDÀ]¬ç´ë5¯@a¤*ÕHò¢“"6ØY(ÃáP–@£MûÆS§ì*«PÂ#Ÿmllâ¤3ÄÒ mýd¥i KN)ëÆñU¨+À­4íü¦ÈÞ LÞ©Alß]7”‚(‰5к{“=SÜØÊ =èÇÅÕÌ Œ)²ºlW.8ŽÌ(,w i Ô@G»¸©1/v:Bîg'»lg†^ ¦D”  謉$¶Š,Š|°¤Ù;rˆâ•íbޤ0› wcñ½í2¾¨ÉÌ·ò¬†ÚÓÜ„ÜÚú5y­$޹gûj`´™DZ¦±+ËÖD~Áy\ЋR(ÓëgoBÒ²e»«’‡UPs‚1+Ôè’ϱ¥¦±<9ÿMY®‡J/ɧÛȰA7Å=Mn”Ü›”s ëÕ¶ôÏ6ׇAÝõŠ}õÂw]d½A0gö½—€nXú^YÅQI6Ù$tñøÄÀ—ç”±m ®¶á~Å—‹»(Ã[ÂVÌà4h´sX9ø·àÝÄ?ß\¤É·ÞoÐYoU &'…äÜ\º 'D§—¢MšJ¢4M)>;fx?‘„@( ™¨èÜ13.©,†0FŽMøõ…D­²PÀœÒòdæµR&â¬z\9e«Í¥zÁ2|Í¥“ä !Âwï½em@Y>EÃô߯%”ÜPCÑδ'ŒÑu’»EÆv …Å£˜-×·ÊJz´ íþqÇ 5™úï©(8¡UŠ5 è6D¹Vƒ lŒýªù?.$2lßsQ.¥µÔÂÜHíS§&~Ø>¼‹Õ]ÚxOµŠ$:Ž}12io1¶ãÀÛ±îgzT½¬Ú³v «²Ç‰åŸý Yámç¶Ë°ˆ°×=ÖÛóZU•Ù)µyªÛøqB)³ª"?u.«¤Ê…:6ârYkǸxþ“C` |#úy®¶á¥ÇÂlÁ ¶psFüô`Û<‚Éò vùñMŒÊìJÒuLíÉ®ŒKdÈÿš#ê…»B×Ï„ Â[3¶ %hþÄSúóCÁþÒΉoŠÚ$lblÂÕ`óh9CxÈÆìʆéíL–¡·ZiVG«:ë»D¡ÚѰëD¤Ì%k“ÄŽn±€&v)Bç5¡ǽXÁ³ý&Uënóiçw0%g‹pÙcÚˆ¢šxgy Š( @ìèÁUæÿÚÚ¼¡èŸœŽž†wr]¢—sE­Õ,{•;53º¤¯îc&Xù>È6bdPÄáR"Òä?"ší1IÒ÷ž:ʙںŠ[ 󣥋q‰ˆï¦i¶iSuçƒ^˜gS˜”;?a¸I÷ÑýÀaL9 ÑèñúévÇÕhµK#LRÈFκ‚÷;«špŸz(íî2n”í{—Š•»üÖu^ê±$ù·™y\û®­.èp(ø;üñ˜›M °†˜÷¼•Ç8±!§¹e{X<¤[vL+³9Éâ]ï•ÐM‘!;ÄVyÈpÑ’¤«*uàåÑa™æËm¥ñD‹È$ÖóÇeçÇ÷Ha·Æ+x¨EâÉ@oîhjB|oa#2Ò…hè]k¦oTõ ª§ ºêêТôèøÞƺsMˆyL9/zL¬Šëæ°»‡ôˆ<£îb3/‚gî†uN^NLø†¨ÏA…Z \Ù¤—î<̰bAðNüä^*ìkøabôþ,°(Äb³ÆrŸ.zTˆ¸¯*DÈâd—©(zjö‘‹píÌ|b®ÎÌ«ž:¨FÌ+º”¢ ×Í2 BÄa¦N)îÖsCöñ'(ýë^EMi´(M fRT#¿ÃÄã+>gðΜІd ZÂdTò)®§æé‚Å®½‡èÍ'¦ZF¼ùÀüÄÍÐvÇÆ^íÉ«¸ËHòÏÊ’ïBB1*\̆êêƒ$ŽP£ˆ¬”ò¼çÌ‰Š—O¯ ü³Ë"ro¾AìšZ¢Ép-îzdþèg´¸€ kβl³Ê íx/ 1i‡§mľÁôUñ†`–§ñ$K°P°ªžïAú$ÍJ–Pvñ`Cm ŽkÚv¢Ì,æV„1ÚN¬¢‡*' ªÉ¨!$vff•Â(q±~íƒ&H:Ê&gffÖ$ÌçFô‰ü€ªXb¦m#’  –©¤Wj³ìœ"2?‚»Ë(p O~ºË=qŒ±G&$‚ôe©øìJð±C±"f£'ì¬å £òt¿D\2‰ÔøíÌšé@\iÖ}ªvllrOîÇH\=©+”³¬ÈüÃZ nzØF̶¢¬@Û²–m_o b  ¯Ž·L"È.ÕËA½l¬¿áö´ FÄp‚»,šÊ­¨ßbÙ @•E.I !î$}ãÀ«&w ´‘§&fj`]gXIK51˜õ‘~tPy3o®¨†¸ [°'"h×")aðR/0óFÉë#îbäÓVƒÑÔoí|”rV¼O±&Ȉ{Í ãoÌ#NŒSéq0OcB7î[$&¸ë"Z>sÖ¤Í{Bôöê*ï£ÞsCOÊL™ÇÌ– Ý%lê”øü‚"ð#]1²oí£Fؾ¦+;M;Ø!æù0P¦øÑÔA3˜uRƒÇBác®zs ÌËÝ!@ QG<­IpÎëEHÜÜÔhIÔlùækÒ̇cÍsF)GðX)­(°rò¨'dŒÓ±4ËÒväŸÌrªÅÝ)p„è\íJÁNŸˆ.»jòZw Aù³v”N·Œž$Žpr}nXû'²–.ÿ#D˜èhº˜ßIŠ‘ ˆÜYçŠtfÓ‚„³‚ò¦V¼ŒÑ3ãáI «3M*4×ɘó­!0%ʇÐI0'= |´yˆ`Í÷H®z܉h"Ìž·± b´ö’Þ^=µX!”«:ÑFà5y"Ë~É ÅÔ,GÌ-sb0L[+§[MrÇM„ÊóHÝD¹‡T;›JGÆV‚q2@KX£UwZgh£é5±ÔÉ'€^m bô¢ StÌzbWQƒÕ?ܯ+¸TƒØ‚§Þù•…&C~³HìoX2çÚ)ˆŠd ëNüãg´=ÃÑQS› W±öª¯­BÙ2'4úÅ~».r愪¥,/QMcàþÀâFþˆ úÇpHp³Yuê !òIbð€u€©Q*–k¹@e´"Ð~…Õá,Øaóّ茂…±ï.A ‰Èѯ ;ÂemÍ f)<„`Ô­2U‰Xô1YSäÞOWD«^)¸gîløT”&0º^+g@7“jAº¼µb²‘ &MÖ%­„uN ƒ u6é°–ëjóO5@dAÔÕnn&M„âKfq"ðxð„b)@7Y¶¨5äã x»ð+aåÖŠw¥Œ58µ¸V4/æëRå^ç­8—ÌUÄ/o•‹ªÅ)…•„ô¬/MÀ<h~·#]+ ~·;®†í§5 p‹ˆÞùpõo,Ñ¢¥EŒ $ƒèÍQ҃ųù†5˜êDÊäÙ–9ÛTÄ!¤9r3€Ù(Ö¡bŒ%ªÎ~g˜Z–)Šmº~!÷N*$žwuZÊø‡T°“§š,ÊÙT2¿¦š ›qþ²ËÀd‚e)(8jùÞ#yÔA2œwÏŽË–‘ë(ø‡Þ1#~°ëAìÑâWµë#à Tˆwn…@ç¦V±È§p@wFÕÔrvó°§VY5GeÌ¥ 4Waås7Ö;n²‰Ss˜ýÒ‚ÈÛI3n.öŠŽÐ vdž• A?uÑ1Í*ާO ÂÑ2£šx»(±6ØW­\ö.'«[Í\Å–ÿ9¹]™gìn£ Ôb¢ºÁn§™5œUr2K }â‰'†º·eŽSà,ÀóE•\¡î`™¯8B̦Ax˜º4øŒÒÈòkÖ‚Ì…‡&¨û ²¿ˆwò3PuÁ‚æ‘q9nIç´¶v"Æø„â´d ç¤Çìù¢ W±ô!úw¯¸“¥x[$ô 94*‰5K‰–½mã¼MB¥¸esKÚþb­ü4L„ú‡dn´OI)¶Úq˜Çj+O0Ñ#Ùb»{W¡X Óž11zɯϷ!Ø»xÐ×YÇÀO0ϼ‚€î¢ZæÛ¬vYy,È·ø=­ø[ƃX8¤ÃÍHDD™š(˜qåÖ±ó`Œe:µóÑÄ[XG.å@¢ƒJÂõ“!$RNÁÀÌG].‹f pnø4º¢±X)Aä\T™a“pÈ[ÚlˆrÃ"j%¹Ø1¬î-Y9ø2ZV®ÞÍÞ0FVÌ#Wžõ.&×?–æãa ±ûÖu…†p^n׿Û) Oè‰B(Š …x2¿–‰8¸² xgµºƒÏä£w5–DómסY+r{öäìÅ@ ¼Óñ¹ÆNoõLä,ž±²ôuâžlRÿ xt÷Õ|K³­Ú™j¦¼ŒÍŸ|5=)†þ$-¿$öý¨<±3c7—^yŒE;ä¬ý#&ØfyAž<ÏP'pôR¢©A’Lw&¬òlü#(ۯϽƒ–×Ã% qxÊsšu‹Þ~fôRAÁÅ,šäš^Ü/6Â%˜ãË óÐI´ú—ÄØ‡gé]uªÊ1÷˜2cN|Ôòèf)^ųÏÊ>&Õ.ŸÜe ¬…ˆÏ+MCÀÕ¸åoó4Fñmç™dПÙR¶±K@Öìç¾ "i×s›%/ ;7|Ôý2°·@z‘¿î{3ï û_4Ô¥¹C<,p”‚ñ`xã~Q6õªTŒ0×ÇFýœ2lTˆgC¼q%cŽ#_d·˜sN*!©EJ>$0mf˜©ˆã$ø‘užôçzzv¹"”µ¯‚å¸ÈÍs5Œ°8S0Ž@ ¿7Õ½>l&:;À“ W5Œ«#£>¦°R2¨ë«O GÐÙ$óì¼(x³2Wk:-ü‹ kp­¤˜å÷þ‚èÍV‡¼´VPÖÅå³™@¤¾pâ½L¨ºŽƒ(:8ÁaË$']n¨Í_=k¤žáècÙÔÇÐA7– á«ùäž#WÕs¦Ð¯£øüþÀ‰ lO»R¯‘È›¦ô«Y5/tºº,í´Uvø19»û(ÇëMû+üUZ’vuùÀ̾¢sŠ< çóþƒ>¡HSò‡âGü:(‰D À n3€c1˜ùû%ŠÃâ¹T•ûÉâÑwüŽ;ƒGä3xܺY,œ€!@Hü²$£BRê0=•>æh•X«K!ÈüR]?–GéôZ4R³KŸA¢‘øýf‰6K£ò:ÍX 8ƒHîÔTfÚÿ–pœr#¨Æ­V¨•>)ãß]"xÄÖäóûÌÂû‰e ÒêÌg¤E*’Y“þ3‘Ħ)ŽáŒN€2êíÞ=’æ¶Ö蕜„åõvœM4´”Ê©x'ÍÓ"ø—]+;p®—Y êçô,Rû‚X`”¼¼þE³kaÙ|ÄÆgîÃÅ.™ywV³.Ù NÓàŠ¾Ê Ì¯.Ê× OòÏ-Ê F§£|~À*’d¥É‚(¾7ðÉÿ¢ðâÔŸ°ùúçjË¢‡¼b¥°ïiü¡¤ÈsJÓ¡ÉÈ’®‰bž ²¨³ ¼P´!Ê¡Éû`‡9d–#,º‚Ú€1‰îŒÈh2²ûCmÐË7(‚¥ÃÈ:šŸíÝ»h"X »ÈT†KÚÉ9" ô@î\4Ž'-|“¿çóbà RªBùµrÜæá¤³;×H·”kâÍ(Cˆ¨+ËVæD $•(*zª«DêÊ>É¡S‚Nèj¬ÇÑR0N” íEirä†Bp¢ãH Êýâ¤ëZË©ë£ìŒÆp …"ŠBÊ£8ŽÄ÷+/7"6¤A³‚!D¯É,">HÝw)έò%#¸#Œž×ãFJ@P‰?·Ußx¡Š –ž$®­Q ¥K¤ $À´ð¬à” £F©Ô¥—\ËZLKð«+*Dž/2n…0÷=gb€žŒäUQ÷$Èí–dJ{.ê22ú…Âé”ù‹aV#>Ö]€ŒÌHkJ" ¥þ·8 á*:Œh "— ì· 7Ò‚½·á8'ú‘\+Hݰ÷ Î–nˆfšžH'5åŒ~%ÒÒ!yehÛ¤‘®“~Ö~ã›;>É‘ÅRÞݶÝu\€[º—ŽjL×îúÝhðûú[(¼ß€Xº¯<~.—qüêÖ´Õ³»[;ˆ˜pÈÌ]–¢hs¥š)ñr)~×½1¨èg—VÇê´ØÄ)d»ãJÝyý9°ý\ýÖdgæý3v0 Ÿ¥Þ¹ûÄ€s|œ¸Êz]._ç~"µ”ŒJáäˆ+Çi“@n/mr¸5€Hß NmÜ‘¢á¯]Ë*NmQñ3'¸ô)AçÕ½–ø‰œéôBÇÍZ¼B  Ž OEùB·I J—¥Ð¤óK!ìJ†„ˆ7¨$IasMë­"–¸ìRÎ;I­§Â2æUÍQnKmH—”άLJ)‰i]M»ã„£á;z8‰l°¦DÌMÓ!0¨‰' ÈRã ~-¸…CÇÌ·€*'U„ª®ˆŠ‘=Ô®Èzöb»Ç3o$Á$xÄZ‹ëJiPR:¤•®Q—\e€.íö¬¡ ƒAn’% ¶ ©[œ{!ÍêA(Äε ´dräV¬Ö» á‰qpg?T¬~̉¨!MÚ‘•Òœ”<€'DÁWÔ}\ogJ|—¥p‘!:)˜síEHS‰R+`NY»ØJö—jƒÊN5)e™ó™‡Ä"'Fu–Ü2sK­š)€ªûr]nçåÄ¥œL'­’ ¹òXq¦‡BÉ$Ïi øS|í)íÃcË䊔§€Ê`RV:RœƒhE'Yp£1^ž¡ÖsÈ3¹cýVîdóôS’pœË%ƒ*ìúgªÖ(Di¾}ûFTèù«ùÜEàä [„%×E·1—dVA`Û@%r*d)´Ç˜¤°NÑÆ-ŠN¡öjƒˆ!LÚ¬#ZÀO4§"|‘AëdP}€*¨ .IT|c@<K‘ç#˜W£ù#;P‹Z®}ÍðÁ ^XÆ «~£´¦EIˆu¨h¹ø“öiYGÓ¹"…<¥»—Vÿ’ÝÆ(Ò ·—H úàTÈ´v{«S‚N/¥fQè®øý– t±ë~A¬©#:JŽÖ'xùÌ•0˜¾Í¶K-J4%k†,•’U*Dé9³æ–t€CŽ­ ÏX•< Þ¼#:ÏD²ö‘·æK°À”a9¢–lSó‡‡t†G+FÍ-‘µÔ f²×˜»x¼7íƒÇ ì 6Ô´Ö%lM,Ѽh,ŽBÜþ(%Ñý#CVbiîÂl±Ê9{äg3ä!T`Æôuo5ži€é,€4çÌÜÅÈ =?ö¢º2N±d©¨œÁpn6Á©às˜…§èú@Õ-$Éœ™ß2v½îeõ#\èï^;†;LÓÄŽ6´ÓÂ%KÇøÕRR’n‰T*ŒAx›½±Ww¼æNUDF§i5gÊ—¨¬t&97èÀg PBÏ«]ê&Ïa1zóÇïo[ëöéDèEmº¸ëyÁµ`þžŽûl˜el'R#TYÊ1@œÃ¥’@$΋­ó`Ëcîëêe ÓN¤›»£uo°SxùœJ—Rk=ä!Èî=kÖDÎì] ¬ín éÕBëe[ƒ7¢3Œ¯éÔ&Ö´tj y¡,e·* (8<Ç‹S€œ$å­_bKch¤áH†j7I¸‹±aãvÊ+Â2t’>]Є9ÉH~jöеÂ"M:}U#Ëåƒdóï‚V”µ‘?Ù‡2@NãGDð½ØGí×?š‹Jè`4s«ÌŽk–“è˜<õN5†îPòæ[nØGÒ:ËÝ$ÃÈôš? qW’Túe2IZ$OQ ‘» &‰³†{ð K+÷MMž“~CyÅ2°ñ÷²¤Í°9š‰7ß6¶•'––#ûˆ°ª%„±¼:;¨ù‡¤I Zʺ"DH£>’¦ñãŽÒ‘ Ây£+Kˆ¡½$|»¤/CÁ…#©.¾Áq :l¬º ; )“˜Œ{}(‘?®“"!@°;ë¶¥Ÿ:/A`5{æh„0dOÆ$Bâ=› â´;bˆ¶Ï6Ò™t z †¹€Eó šÒ.ÂxÜÛ'q¥é®5hˆ&A2‰£¸Ú‰ ø#‚7Ù´B® bƒÂsŽ‘`ª3QŒºy#—%˜Ã´P̼ú"¬+ œ†%{l«Ê¼¶ü1¯Ä#ÈS¿“zšQçŠY©|€:ö U®–,«61g ô"œâÐaS£Ê¾­,Y¶Ñí|HÜĪög@Ô{=ÃH*—ƒúFjæˆbŸ lt¾ÔŽ£9aÊ¢‹êü¥ðÄ Ið¸r58ÃÊ ´Ëӓɺ>«3 §Š+¤ÉÿT˜‘K­0¡¥ ÌJ—¡Éˆb Ì Ë¯¼L<êÅ@;–6ÔCšqEÁùŽ“ƒ1#Ø¢".Gº@¥Û_‘?˜ÒÛé"A/[µªÂÞ1 ?ˤ0Ú‚&e˜‘B© £©!g]5›Ô 9A #—Ê ½.ŒxžÞ޼ÙŒ½Å¥tZödÌ:HQØ‘¸3$x¬Á±ùŸ‹‰žœ¢ÐžtkþFù²¦äŧžÜDbÒ³\ýùZiƱ¿d|…ÕKUØÍ Yži¡;ÄÎmc~£lE¦’ìl ã¾ãÔ{y!¥[BåÞ1¦'£ **9¶o+|ª Kù“>m£\*êʼÁÆÝLËëÝ|¦Ó^†‘Ç|LAxn6:™äþ`â¥LÚ¬Ý *ÐÔbâ½ê$¦Í\`ÕÀÑðÔªŸ¿öUÕ²™Q¥81^o])[l>þ¡1¨¢î­TÂS53‹î/ 7<ð€ÌdžLÌÉFeïtÊ:ÂB´PÌ^€9ëé$éwSÔeÓƒseÜUL] SgÝ®‰òMu:yú|£bX°læXÝ=ÞšhØi<Žd¥‡rbÎÃÌ™ÒYò½.åË+Z?¬½ªÅýBÇŠCrÑ WYè %2=úê¦iœDÒ9í1pÕ¬@é´jZlÊÈóã«´RUÞø= #‘^zònO>U0á¼Ê¼õ4TöJŠ¥ƒgï’ͦŠ{¹àà†0egDöUqgk>ŸÖeƒ®Ì&x Ã,ø%ž’1öJ´˜Éûq¢DéÍ‘R]ª<Úà8Ÿïò¦Æ»ÿ™$ÊÌ"ºnQg2 _tÅ»*H³•jº¯,ñ3ÒÅrHãKóºû×YåCvú^ö¤%îËÜeœåB‡O'¯Rûc‘ ¬˜õ¬Û}ÔuL&žp§7{~oµºÏùßIÖN×Çê¸Ãlûò¹x„<‘>åyÓåhd爂?àÏØDÿÂŸÐø$D Ea¨CöŽC!ïèdz!†DcàiD*# Ë_’øøeŠ€¥ 8ü~3Ž#ò'ôÞù¢JÑx4F;‚)Ñ÷ÝFY-…L€µܪ 7žÆeïÈT2…‰A+ò¸4ÖÃ!Çæóøf?®GWy4>k5·Kc3ÚÄF5¢>iWÌ ‹ŒÂ¯q\¢2÷ÊMæ¶ø|Þ¿w}Q£ ½bµ¹É,•¹l朶hÖ}Dâ@±juS]n:+X«Dp´àCã…À¯âÀõé}0=šÖ(Ö° ~¿_žÑ¦‘YÔ"j îe÷IlÖòþ¬C#:ÝÌ¥/Ç€µü˜DöóƒC>Plæ[±#U«èRŒÎ#hâjå4­#2ÛÎ8¾€l8¯·¨* ›´KK§¬*jã:i{FÁ¢«’ž¢.óÛ8ÇœXÿ%éênŒÂ`®4hû©>¨¬áŠÂk親ú°ž¹Œ‚ÍÉ@"Ôú;(Ò“ !m:',B ¡Ÿhb°î*ÃÏ,"ˆ«¼MIìõD°"*ÿʲÊB‡!ê˜(Ÿï»æ , B”)ú>Î@+¼7@9/'ˆë~¢/L«éª¬…0ªÃ€à!J¾ڀj2Pn¢8ñωŠd¯±³&Ц«+´‹ M„èã"'…€£DÍ‹ G§Óx†CçâëcŸÐ’fÙ K£;¾“ûǯó„m€4 W!dfÎ*Ó82W/rQ8Ñ#Ȩ¼ ¸>[`"°ýT»ö2 5_BZVü™_È$ʧ¨û ›¸Ñª~HÌ<ø²X’ÊÍòª[Ë‚‚OŒåÿ`׃p¶H¶Âšáoâ¾kæQÅS+dN4y6Sj¨7¤‚<²ÃT OnM?ȵ ¦–¼×]yO]˜ð¢³¶@? ¾1žè¯²ì»ÔX €~誵†9WFM•¬¹ÜÍ,Hº,ÿ“eçò2ÌÓå”öW@y¯H¬I6äËãÒ.r…8ÊÄjÑ93„ Û¼õ—#•º*£;ɼ}5I:PÎBóÚ8›â1 ãPhSóÅ£î­Ó*-kǺ N„žé(#8Œç²¯9¨ 3 {Üÿ%9ùt¬ôÑÏü…‘s YXc` ßëRºƒò¾oÀ´>h‹‰¿jkÔGËèï ¨•šË“dˆ#²©hCžƒi€C…xÏ©VtäÖ”vä}ÓmèT–¡æœ@|Íô~A(‘ŒyÐHäÀþ‚¾šó~¸ž¶‚8à #Òe¬åó@Ý;Xi² .E¢ÖZR°R­èç"aZ“,`ÎåjA5dÈÔ«â»à‹H.p,ÕÔ?a+Y9PhCvB÷ÚÃ7-‘Å'•úì »4QI¸RŒ»Œ[¹,­å >Fè¥^´c€Èéð>DþÏTA¬ \Ó[_ùh±‰"cȈâ÷péA8¾¨ô#‘(’hÑö¸&KÜ¡Š1paFÉW*UˆÊ¤R.p½“xÕawaì C¨0ž£ CŒUyé2h`úFD0 »qŒrÁžÇ€öcÍ= ¦›²¢¯˜Ûâ¥ZY6'´GÁ_Z‡@ˆÎdùlQ^r8È8›»T•Îq©ôÖYro<"*—¢˜ý™/‘LÇ ž'pú=´½½‚î‡c«B*-Ý#ª 0ô£Æµ¨”‘ %ì&ŠÔ–ÊÃã È{Ôk3õx6V$U¤ŒóoINtDh6¬XÊZ‰‹ZyÑØ>¡œ‡hÑ/Ê”=ªdÔ¢€Ö¯þÙ±6ª°ž.I‘øº4¼£s¨¢‰3Žjò…ó1&Á•*ÈI\ÅX™)£ Q è ®Ð‰³8JºAžCóqrÁ½Gô¾–õR,{¿ô£á2©ƒÙîM)se0|Ï™„Óyñ_zVŒ ¸:¥½Oý¢ðQÕÄĸ*’V‰k…Öû(bgë|ws-hS|Q'ì‰0‚£Æâ«ëe,^#쌦&:Êš%ëÜRsŠbæ<`šR%A̓Ư(ÐÓ*έˆûjF­å™4ålUgæ]¦·å‚xGïhZ<@÷¢ËØcÐðl¬Nzòq‚Ú?Ãú™×. Zc”¦ “϶©:]éN¦ëçea„¡[}ÓšÔT§ §_:xæ#\p_JASöu*¯8¬‘—ECc¼+…:$Ú|бQUЏg £@h/}€´ñú§“šð²D¢üÞ–ˆ)ÁôTDô†Jœ>X"ݼ/™ÄÙÊkq‹îTKµòؼò‘H¦ò¸Ï#ÆÛO£¾w…×ÇòK®z•šÏ‘QXüp·±èû­à´½Ë¸Ípz*Ù©ðÚr^‹ªÜg!ø¹ÌÙÍ!ŠB5x®8à­ÉË&] –žRè>?äçÔlúˆÒnNÒ™3PѳÔô¼#ëE|™·HçK×ìA΀ál ­fF´‚èyj>ªÁÕ%EވܱˆÌ°‰ò†ï¨8„µËÂ’ƒl*ñ„ˆaF¥Ð‘¿ß2¾È#é­&±ÐãŠÁ’žò¢ßˆð™9ZQw—ZS–÷# yú õ^©*%BïøÆtdâŸg/8ò¢gX!ŒT~]Z-`ãÀÞç Eí6ʽõéªwYvÊHq¤É’ÙY)£ìO©6ËÎÔO‚çÇQÑ’­æ…\¨è -QÙ4ûNv<›™í›cªaÖ”63´r+,Ø©~+q=?ö’°`ìjì—ò!,¬ï뼄L}MÏ&Yã\÷ßþìnaèÒ%~{ÖâîŒÊ^+îЙ0ÒZV3€×MüÂÆî )ÈŸUp…kÉ@ ²ÂOúKV,ŠF>Éí¹žì£sb«ð•»ôÕJÔ»q´ÕêØG×w3Íx#r˜¶ë·ò¥D«w1¸ˆ&ØÅŽjL# —–nê;RwË“ µiô·mÒ~S£(úÚÐ(£ìv§JuxO—-OÑyT¤ˆ&?’µÒ—}]…žü‰‘?_¡YͧwPƒÿ¨Q|u£Ym€·-« ’è- ½ÌTêÁüÐér¡¨Ý7Ìøÿ/”(‰:ü <ˆgñnŽîØÆîë í *âé~]‚Œ`âé'»¦‹+Q¡lj%ê\؉é#q5-g ÐßåL#¸d8ÿ!ójžk]Ó9eıê`­Ï43Ð^´Â áè„¶‘(ò×gܯÊj†@·$ÄJdf½íŒWŠi…#ª´ ‘ñb¢oDôÝ¢yN¶¦3ŽL³‹¬}Ð#2©‘+ Î,¦0ÃáðTD¯ x¸` É S?³C'$þù°9Fbs9ÔB&Næü#„@ëM5¢ñLU'%›;Äð9L1ñÚ¯ÒLKšQô9rÍ'ÏcG’æÍ|Bz!©OEšÌ„Š´Î†Ûæ²KÏ8-Ѓš¤ãh-Šj¯ Ú›QÖ³‘ój®ÏÏT>†%‚ 8 v4†ÒóàDÈÑ´r©>§…é´ i¼|Çÿm„Ц$m 5ÍÐOŠoð䳋¦ß0 Nlç.ø’æîÑo“AÁö8rî£TZ‰¤Ñ*€ºë8:0TÅN‡Bµ|«‹<²ïFõ,¼3ÍjûO2§S ÒÒ*”-´À¡Qû[+’;‡N@ô_í†JJ€QmàÔ÷*àtõ3ãøËL\ƒ;5}Al[\ŒY¤}Tñc+LÈc ¨ÅLÈoP´«0ª±”|õ‘h5PºY¨`Õ½(tŠR³`Æã”¤U•(æþY®19cb‘&A¿$±…¦{¤±;È ˜ÏÔY3·J_žæBBè5Ð0µdïуR¥±"5§2sKð¥ë QìÏ#çÖX› ̾’mÑ0 |Æ{X«YW21[–Û/kâ@çþ¬4lW„|°Pà*4Iâ÷ˆ†((‰ú%èÎ;Ìì`‹¨)þ¼gŒÔŒÒ¤Ì_ëA)îñ3š³RQ3Øùò ´¨s¨ °âµBY ÊËÑ'Ni.ÉL2Cj T‰¡-ÖoKß3c$¢oI#¬ éa åû1ÑjêU|: ð´ÒJ'ODS™S®é QŽ-|7[Aé .팯ð]ìO‡âZGÎòèi¨†e âÌI(krŒ±ãÖz"OZTq(PÇ|C€y6ŒJsøÔ0ò× ¼…0L‰¢Z¬È¢ DÉœÀhÀFª .ÒÞ·D¬‹5)'Mõjj!N©ƒ 3ÄrèËaû8f!3W–´±lJ¨,¸+äÅ¡útK–3j& b9RUè3:JÐSlF¨ÈÑv”&í,È(Üæ»ŽQ\wÊüô`]pÚâÍV©ñg_¸9dJw’)¢(×£fËgTç$dÂXXR°j¤÷¥‰ê€™%ï7–6¬õ²ÃQ¥ŽÊ|mXTlª¢?OA¨µ÷xÌ Bž£U é?1ÈÒ¿ŽF¸ikcsñd(ôšhr|—„h(ï4¶£isXrqgjOƒëôÝd_I†ähÒdÓ§0‹c9ÅÐYgÌjUlU'õ¯gàDÁiƒÛf ÕsFãóp}Kf^цÏ@8:Œu]v` “ø /ÊVóÏ«‘$©ð„³p´°^k^WмÈö&âëA­"j‰ƒ ®/‹‰]µXÂ’ÐhºØÉkÌ»—kL™Ô¹hÜW„ô|”9ÁöuÂ(ËM]ÊzM8o ¹!]m¬•SlT9C¡Š8alŸõIÒ_Õ€=p„‹)µŸjNõ“Óæô$)ÔpŠÁ'ÅEY§Ý ùÊŠE $.Ï ¹‚ä"£Œj!béã#ñ%6Ì¿kqZàŽ0Jo[‰Œ¥šº»FXõ«ß„:¸¡l›(ÓZºHšÄñ’zK`$ ýè¨övšgÔSšè¸æVYS¦UË_OA#ŴɨFpÔÈúð­6è%ùdî|_b_‚¸ÆÙ¯Prýr›ŽZàW½÷Ò>–m„])ÐlÊãï¥ÙÒªÀJz5‚4 e‰ˆ†Æ EdY@̼‰³¹xN†$^ðS#&1V^}É.ˆÊQ(ÓS³™,¹Ùw!t¨àg¹¦¹w¸%©©?À;Ōв#]S2¶TzNˆ•v“ªº—ÖÜ C“fË5h6¨hf‹l¯ª ³>)`'{°ôèÂê† <ƒy²²ÕÀAË<.tñwUеä|{•¬ðžë̸ÿ…+@œRD¸<µ7u|Z™eîè+AÄI½(ÇDk²ëé°-_·ôÀR(0tK$¬uJeù ¡[öÚ˜æõo·=.6ïUŠ\U'ÛJZ‰>4ntª¦Óz»c|Ú;Ÿ©%)j7OÆ€'«V…K~;‚¾X±f5ÛêãÑÀpÉ·›S—¹æ~6Z~«Þ̤‡Â$š3C–`[Ñ Ýê«Tptwù¶øÅ±Ò…DÇö¢VÓÇϖϹÚ [†õ+¯CŒGÉ>!‘u¯É68]C_ļá‹8øP;yvU`o€° óÜ@{ì`XØT­„½zÒ91Ê2#¢Û.]£…*ËѹN(m¶º¹;M#¯èh¼p[ÛÖeŽ[‚9X›0óP3aÆvü`r…<´›Òµº+ÁŸùß_q[Ƕ¨È¨*ʺÀ¼ÑÁw+¨m ˜vM‚5¶ˆýÜzvÙµJÓq÷Ï|$ää~ª¬´(åÁv;g›è1P6X##Ëœû~L;…uÜyÕ1Ù?;Ž^èp¼ˆÑ_µÿˆ$ðß° ï¯ÍV¶Ôær0‘\8©×†d¶AØÑÏ•Š¾›¶eÁP%Ñ;Ã4“_49•óXõ¯âI")¥¡üž{ÖgŒä“ÛåÖ5µQJ€èpSŠÃcŸäXj”ˆ(±fP­€þZ66ß‹‡U±q´ÊÀÌ»áuòÈÉz*´‹X½[^Úk=^ëSÝ®™ë Ç$Õ1®Œ:m€ØEàòúˆ€Jqª[ÖÎl~wQåÿyYÊ„Ô «#¸4lÊ®Φ|Ïi¦.êÀŽc…ñ³ÝÔ3”“ï…ðîz ™%E€:õ|/÷ŽYÐA•® V¹\$ò&°D5ªRSë´';Æî8ËC§YÔUhðx,”?w·IqÍ”²ó«Œ^tŽGÂ< €˜3öÿ…BàÀ˜Cõ÷ÄÀ±Wä^&ˆ¾ßÑÐ~A Hä‘ žACäà$>1…Kd'ü´ 9…È"ïÈ\’Hù¡@ØÜ‚[-žÂã zu ó=’N@Ϫµ&OTVÞõÙìÒ? ­" [7 žÈ)ÀyT.7&“Æi‘9ä^±IØaPù%Ô-…ÕŸV:¤¶U‰GåXHX+!q‰Ëá°–'J‹Êc¸ˆìfIg‡ÍfR×¶žIe†á!öYnÇ_“É2Ò«Ìfa2±ç±0¹VÒ?rØ«zGþ)ý;æsùËŽ™]!Yi$oS–èãû)uw~`¡V9úGÊYí°ùì÷¨ÿÐHù:ëÞ§:…v$wž³è޽Mj*Ë<ìª>Þ%K*ö¡ “Ò™¤ébNß¼ ;|Žª ʱ¬nB…»€l–´)9±?Ëâb³²È|&¾`¶„CéT Á§êz¬¨Ë`â£ë*6ª4ç´L³‡òÊÀ#q¡úó#íÊn“¬®3Ô…¯1E¤hz¨ ¨ODfÙ¼3ȸҚ¹¢nB2¨%°\^~¹‹û«$ñ »àz±£/à…Îgêß>¯ òºÒP½¥M‹ÞŸ!IR2ÃÒ\ô…#)Òò«i!ñR#(ÌBO ºFãNò¤’°1ú8QP¥¡J¤0,rÅ,ÅÓsõ|¾Àð-o64DÓUÑÄGbÐö ➨ˆÝ¬ˆ¬õËä»QŒ´[ÙïTЖ£6[m X.d®™FzUL€2›„õY3E·]ÕT**õQË55!õž¬©# EK*Ü,µ!ñ4PHŽÔÌ 8Ítd˜Òãã¹udWqà‹ˆ²"©VeÃöK„ã/+[ƒ7#ª£ Õ` g´¡ù$0j²Ø§@`,Dï$Yj"ðUùP€™ž˜‰ª Ý5 ØôÑ«€'®¿‹y B¶²‘|ÑeÖ¨› #ôª¡$ ¥–Þg;Çc=4äb‘ó'/N’EØ؇üžšõW#l€÷/hÿ€G§/Ĥ ‚·ìVŸ%SmœÉöN²ã±YCij¯8¢ÔŒ"o…ºÍc |õ.MŽËéÍнQe¹'5Dà¡x2¨¨x‰ùÃI[ò*ë¢7‚srô ìEoÝ)\ùn9³êÇYH^¢F££ó–…Î3(!j#Ô•jwµ59‘–~›m\¢Œ2@ ³× ™Šê,m¥ºÖ0¬É#†'¥Qm¬ØJ‚+ol„#£p±šRd,<¢óâ}Òˆ$t£¥\Õ$)É!$§²Ïº%$n•÷»d?›0ãCPñ#aðÕ')¨@—"m|z”H~XÞ{þ-§ÝYÀÅ`ΈÌV!B Aö¯ÖbÂ7ø’55ª@ˆÚƒ-­Mþ³H€BØyª Ͷ'‘Öþø‰´g'­”þ’r6²ÈYT¤v’ÒFOºŠ‡Š-a+6åSØýcŒec Jži…­@IJòRb;ðXÍÜι5´EË0ýÄÆUtNRÛÞ_`3#ÕpÔëkUPÑŒµÞgÈ¡>14J§v‹y |…\“ÀrüÚÓœƒ$]u¥'À³×¡ PmI·ÒΣý8S­²aþY]]U2§Ù­(ÈŒÐ+f’¯'ÀÝX²Ÿ"0\Š©1øÑ tŠrE%Ò;E· ƃCö‡9Ú’¨‹ÅÔ8kQ³a!­8Lþe$òÎØÖM/'Ö';‡°÷±]z%ígGDa/üüZCú|C,Å$•\&2c2Êš}Y0}½¼ î¦!‚\×x~ÎRS-‡.'»€Hç=PÊò°É.­˜ÂŠä@‰4;üf}¥ wOHÜDe»€PöH>ú"U¢´dN†U§é/NÓІ ÑŒEÉJ¦ž“ĨS®.Ô©dÙ"ÑEˆ¬–§ORvBq.ØÂ€HQÌMúÈ¥5U¬ ¬BO€ªP÷)ÒE)´Òh~±@oL#î¯ ½ÒW{< ÐüPÏ1äÊ{C‹iÒðvœÚ‰pª—5¹„é×1ÔüJˆÛ]^¶\ªæPOe¤g‹‰™—(˽=ì m‰ž(Äo@]izàä×ȱ›/oqFL§z‰P@ !"´¦Ú*×10ռׇ Wm¡¢Ò¸­»™¯Uz°qˆ’Œcj½Ì„-%Yʸ 9„ŒX¨C"&_Éà¬W ü0'i7ç°û¡ØŒŽÎz¶ª­½±§,¢®QU¼Ž[«¼E!=ù0E_+:±ï†4Øè°TTLr¾£ªûfŠÉRFqî//ÙIí)‰g7(|Ô›”ÚëõÀ‚ÓÕâ·p3è½À?Ï# ä4Õ U¢„P[Åy3Ø‹ån¿³O Ú™mùˆ}¨dÆŒ¤¹g®púyÓ¥"͉̔ÑóŒØsÅ]PÁ°¤m%à”Ú$püã]úÚ‘‰!mx MW˜×¨ö!#HÐÕ+S++ì­v†ò—rÛ¤@!ŠY*pg˜`XÊ„T¡3D}^÷©'4ÙÑ•7g [á«MŸp)B'<ó±Gâ˜'%B¿,k¡TÖRÁtí/_<ÒªN(k©(‡îøˆ›Ò©ùT‘™3Jš–˜ V˜`ËÈžw›™[¦Šþãà ö¨+ aÖz†—'DÀwI‡9¾§ËrC†¦Î8Èjõg¡ª™¢Lc‡X5xV´–çV]¨´%§Ë¢a5;Žk ǵʔ¾‰œš]‡ì¢ ÚúL­À)Òü²·ã|-ãif[kKctz÷¡/ú1fT5v(¤åm#3 ÍU¹nÚ.ð'€÷Sö+ɵ7.çÖŸÈ»v³²ôá‹_7}(J¨ÕZµ;""¤ Ú½ù"áZãóc¡ÝC{v“Ç×E6Ç,ê‡+rmb¥6è,þy‹EÉWtÎÕ·EniNn„¡¹Mç>ÂëÖ‹Àû¼"'xü Áë(„à GÆ‚K£ëåAÔGH©•Q®¤Ë ù%C72‚ÚQ¨Ž:²c¿ŠŽ1;¸ˆ‹¶¢(ƒ7‚T-Ü’1ë³H‰³°£êéJkq>¢²Ó)È©Ô+‹™½È—‹ (sµ®< [®¹ƒì•»)¨¡½³t¨¡Œð‡ˆkž5(,?ŽAC (iN$‰&kŠÃz¬Æ÷´-s<Ža£‚ö²É•sâ2)$̈a¢ ó:“¡0ËÀ¬kIü•䆰¬ -WÀ‘ðœé„,‚¦DFŒ})4Ž–‰' ®Ì×KkG·±3{³:!>˺xùÁÏÑÝ£,p¼‚I?ÆàÀ(§aB¤Ns—œñ%ÈZ7´ÜA3¯Š´«üÚN|q—‹r'S¥Ax:4[L*ý9üÆÒ8¸Â´Ïì£:}Ñ áH,Õ‰‹×Dq±Ì!lð«8H¼Ç‘­Q»+—ðFý‹;ù1C¹Ä}‘•&Ês}:‚$ŠÃ)¦Ü<ºª¼ß#ÞÉ<òAôË¢ãr=r+¹M.¬¬æ±Ø~ʲ»ó½€e.2`/”¾¸ic-qµz·@À ¢-=𱊠û’E&NRˆ<ªäÒÝ=ÃØLÙ…•QEG­:“$KfJuW63ë:šëÌ¢rqì‘*aŠ +xÉë¶û}5;ؽr–3ÁH}›1!¾s)•COÅ¡AA'º…Se$BŸ¥ü2º\ÈòfÓô:"{@êÀãa- ¥ Þ3hÚü£ÒO ×¹e°„]¢ìC•™5Aj–·ûÀLµ"·NUGVbSåš4à¯ýG“¬~²1¥ÉKuÈ‚°%l¼´÷М´T å€AŸ‰†ª4êŠI7ôS¤E'A:š.1ɲÉY´Àˆ·Ù³ŠÄØ  Ã6²¿£4ŸºÍ Ìñ=‹=™Í ’Y3<•œPšÓ×H)§,e%kt¢ádÀl÷ÆØ­‰mwÅ~EXË'+k³4¸§.‘.“ÎÛÛºD8”U{ÉKÜR<Œ5\qÛ|5t ˜8« ,¸Ãv$“;ŒTFÈá/ZUå£]Cjã•@œU†¾5]Ì‘ )ˇ¤ »úéU”º?Úì ÝÔ¬u hG̱¬OKж¨"S¡›L»h@sU\i:A1–Ùÿ0½¡<'9T8ZºÅB¦ÆQà*‹{Ì£tŒ°ÂIŸ§Lï)P8˜µPÆÜt]P†˜|Ä‘Š)8SµoPEÀ¥ š0kßqœ×½€,-WÔN¦«ct3‹5z¹‘xÀ!R5 Ó ‘49ð«ú³(Q­1ç ¬NLJeCœ#Wì‘Ҟơß2ˆ£íÓM|(Mò\º¦Õ}Æ[»ˆiAߪ <Ä[ÇÝœL»¯7‰Ü§Uàá5$ ±©ß-ÞÀäQ¨…Ù­äÑaÿªkWÎÝÄÛ3<™Í9P‘»‚±ú3`¦ ã+KbjIcE™Òº §c³Ú%:²˜×¦’R”>ŸóCLž"D:ràn6YP »œ¦›1E7óˆÜ[¸ªrÕYm”)¿é†R Ýd›— +êP® 2™JÄjcmr>׳¼LzrAT JDa ùe).AóÊtÜOJz?±r‡¡UYç¿éY½j:WJ¦ù,HÅ ½ØúâÕ­õ¡¬<–3P•Bü·[³¥MȧfGXŠR0˜›4*å6K]M¹”Z4—²A¼DZ?f­=©dΡ$A^¶µLfP‘Ù¼2Ø~iXÐÖ6 ˆ¼÷HÝÔ¥A–¼,G#Eá˼ؠ 3?HTî74äòŠqTO=]*l€Ö¹MÜÑT`«FU„L{[´¥€M$ƒ[{jÊ}µÕÛI¸»öè0~iÀ¯•uµæHȊЮ•ÚŽb´ÎAþ]£}Ê6\\f9J´Œ"û[câ)u,«‡Þz.NèMk"?A[`;kcÀ}G5Äš5¾2¥•ÏÙÉês»ÞuÜŒQyAÆ<ûØý¹².¤¼9ɬŠP†’{¹ÄU$Ãf¬ÅuÄV½õm±3ሼÌË!­ÈQ¨ø¾ó×iéPȧV [ø}E­G6ò¹IòÐÌIUº ŠtDJÀ°@§?û>L–ÓÙ9œÔŠ@ÎõZÝ­79ˆðTö—Á1ñ0„RXB®æ°ƒMdÒÐèô)%T}Õ8†XèÖ±­Ìöæ~¿2¢3Pã·éäѸ“ƆÛIŸ4¹+Lg„ÌA°¶®;)Á°øË‰ÿ $oÀm\eë‰9@ñ𲡱ñ^KJZ€1^YTúˆÔ©Îµ‹:ÕÄð´Ò\nã(>ÀÓDææI’ô™^œÂ¸e ïl‰ÂaÜùMJ\Ö™hÌÑ)éM®_6vG]ÉLТ; \Äq%ô®zã®>“à¬Åá5×»þdÏà‘ÌÔ‚·\œpîŠhhr& ¬˜@”Ë1…ë3 g' 0¶ËLº}¤‹ã‡ÁC6Ò-Í26Á¯Ä;Ÿq%ÕÁ ²éË l© ¶zÅN‹3{E÷7àÎn¬•ž¦êÀ§.MòÙΠܷFoCUŒ\N›Rð0H‡×«¿X5Ÿé$2ÆêNCžUå¼7MÂ:Iýx,¬÷Ž2>™FÀÄÍ`ZÝW¹5|ÿôUμʲ'[Íüá9€åé4^ïDŽ0@m²¶híèˆXûѸ›Q˜ŽœORm“‰Þy£S ÇA»¸ÜY3ôØß `>0EXïtwf‘C­öYU`Oeu T2\¹<赜”¢°ã6³ïpïÓtÈøÞhÞ5 ƒ¦nÈ–\k$Aë*æZ–” V ·"âd­ CS í\ ¾<Ú£$?°Ùj7êöC¾wj TaÌLmôqoÈŠ%âÓ‰¨èÌñTü=ÈÚÔ‰Ó,CàUE³¤±ïÙeév ÃÝçꔇe²Q4~ÇÂ)TŠsà'zEo¾¡$çn¬—±PÃä9¦ î°~ùˆÂzõà¦HrÀŠž}UŒ$3´|ìg>ô<%ø>O¤¿[e²NmGnêxë:)AøxíÔ}Ž7*BNeðRœDw+µˆ­—õ0°„Cß ÌC!¸ÊN ´ösž÷ahˆiw:ˆ™dCŠQ6Þ ß×4Ë{?Íú|÷Ö}ˆê>ýÐ|Ùºrdõ‡øžˆlÁóâ§f8ؽÛDŒUÔ6fŒN›&QÂ?çÍÛQɧ¬É ²s‹(nbàb COÏB?¼& ü1cXf…SR¼1ð€> @  ~Â_зü4‚_‘8kü ‡€¡oè¬F3‰¿#1–M‡É¤1PD¶Lû˜B_±°$ÖmÉà‘™ÔD&ŽÁ(ØÜF72‹hðM5óO“Aã2\6I%ˆÍ§’Y lÉ«ÑùÃúM=«€$pH­ ÿ}V¢è”N“„ÛkK„VýVÃà÷÷ýž÷?ÃÈm6èž3wƒEd:y·@ Î×"qöÊŠÊí#> §Îš8‡7mâpܺÈjÝ)*š)A§ú35m£ˆµ;¨j¥Ÿë 6DPàƒ¤Ë‚Q €.cÄ,ï²Bƒ´è‹ÔïÏš`û, ².£;ì ©1R ƒ4±+&Ÿ*(2dß&Ǽ¤õ%H›ϼ Œ !î lE *ž|¿à m ,ñÂd–%³;~})0Â*ü¶s3>ßFoŒ^ü!*ÊkÎhS¨Ã°H“3R‰N(L¤{”Œª~Ô­"@“Z%ÍꤤÉË""èÛNç ÔZþˆÌ+:“ “È,Ÿíbÿ+Å‹K ·U€›4ð3Í»t#G> ³1A‹:2›HÓµÃÈ Ã/ZªK°|43ýc¨ÍN†Mtø~ØSDG:׫dû#k‚¯í|›VÒ@ªŠMqC\Iƒuj·UmÏè<—+ÔÖ'!+‚šÖ‘ÄןÖӰнS¢Bõ4ï³cr°H4—/CàeG¤ÊKíGÑ©š¯,«3– uY“"k…BÉBuª›e/5© :³®›8µ¾€~=/¡/€#P„ÍÎ&kV£o²+z©9bK\bvÜ U0»úº …eP6¨zû4g`dzoòønÒ³zƒ.` ¹Ë€Š[ "+‘è@_)¼LÚC' Õöb¥ÝJJ¤µZÔ‚¶S£Ø˜6[>`è\#T@Ÿ—ÆÃU8kåTýeË[†›´Î½÷7$9Ç1¢g‰%¦É—jú&¬&‰î©ì1/6]‡Ïñ4ñûh8OVÌkv0ÑaýºÿDÉ‘Kcûé¬%~¢ëuq1æ/W›D¼M?QY˜}Š!d"Õi=+Ë5Ü&¾ˆYöÄ%&€2’®Ë;5]om¦+cZ÷Lù!j ÒˆLÒËIýnŽÍ×.H>æ“©ür¤Áy ªÏŒ;¾tEÑCÔÐÖÈ3P¦}šœc}  ýc‡ˆª tí¡²4­%u ÷àM ª%g ¯eªÂ¡Š }«¤HX›Ð‰•5)ò.t˜€ý8‹TÓ£wà­!I§ f0n#­fý¾ÇØÊS+Yn.å{0&Ô?ž3Ÿ5¨½CB‚†;~It¼—ö–îòí@D¨©"ê$°ÕÐ%§jŠß³Ÿƒ -¥ÊÂ༠*õ-Ê2láÇÓ!:Í ?4ÊŒ—‰±"Gž§0F\#u‹ì̇«†0¬1=D°1=ÃÈV¯É«˜{(j<S &›LC ¥H¸*AÔ|XpÜ!TÊfåÛL6O ƒ¦7WII%X1xºåý/$é"ëE†"þ±{ì}¿é?"EnÁ‰ÅÐ\+:…Œ!šËô~_DQ2¯E-ÙÆO¨y­bjÀt •š_ƒñÚ³o@]û¯ ŽÕŒ§\,mPÃM*†ÓÞó«T xø>•j܈¼›-µž·ª‚†WÎÂ~GÔ£Ìij‘ò W”=A ~A0\‚[,Ë›i‰¨®ÊÜDÛÐÿg°å¶q`ÐÓÓŽ2vëäy§cç‰ÞUy;áƒ6äÖº¥*=ˆ;¾™æ~g4öê´O²c¤Ž~‘UcìÌI Ì Ž0‚zj)È…•V*«Ä*|ˆ™§)è½( \&Kž±Tͣ oà¯&~æÚàz®TEu=_6‚#bJ6¢ý”ÀòÏ tè=çpOmúÊÈ Ðûb…’t•­Mã˜vRÿÜÁ›o•-ßÅg DÞ/ÔẦU¶«Fæ¡·õÉ-Ç’âp^‹Mú^ϺŽ"m?‘‘Û #CÊ—®W8èÿHEÝcéÍV€TÑ)š·d [§Á™nÛ;ód¯£I1ÈHšO ‰"Y,¾œ-=Üç…SÜ\Ž”»iÅ&…|ïÕ‘w‚Œc¦N3’G¹âÇ8×qCêÖÞ©º!€*ÊII•£€ªá2êÈ'<‹sLr†B4÷LZÛX´¿»WP©˜PÆùÖÕ‡i·~ÌD\eW1ˆÿ4ùAs½—-b¼e)ÏÒ^.]'Nwh€›3‚B˜ßDß»UÆé‡Ol'n ã¦îíD*×!s­×Sœé“@A¸^~iûr—êéN%Š[ÖH¯#^]Ͷò "¸qj¶ú@µ–YsòE-«C7•–þ&è˜ÎòWudín““€¨vObCYÁ„¶`%Ñì¬àQ)ê—‚0l£Ô-À§–¿ +`T­=:5@ —»àµE¥\míx_ë–"ÛÈš¸N¯7U»ê®I7Ó>`®^>Ö«Ëh­›vËÿîDázÑCmýOY¬×A'ÊIMW@°áô?úŸz¾¶t†¦ïs—Zk£Äm1žªä¶Ïu@'¼Œ}fA*hPúàž’ß´‰„ÉPj^\Ä8ˆp žÈŒ(—®ΨW b£Ï ß/RU¢à»E¤¯éæ‚dµNðªÎšÀHHóꢒZ.bɾPÊÜêììÒˆ1M4}êÇtC.ü $Ŷ· ò¹ŽÚh ÎÆßbäë ”ˆü&«ð)çZ3p8Riˆª``¤nBû® çd~l8݈þ$¬"züOžåÊ F¤ä`±†ðe°Ý ìkþ&݉`DoXuGël \ÈŒ$Oz¥*êæ„¶½k¢:,Š)냅¶ÃÐ;aù L iââ/Ä)'þΩ^¯iÌHB"‹†÷+§B c¢ŸÂ ˜0Ík¤¦o(ÂŒàYÄ@qÒCj-Ïþ©NR®PVåãö!ñpüP‹°Ü–ã WÍ⟠ôuPå$–‚BWÅ üŒMÇÓ„4f¬C` ®‡Ø)!«d *ì¡08ëdƒŸ ÏÊçÊ*EcNio8$Ì =¢`y Çÿ   §€ÇãvÒ‡/0f¬µëwò'!HÀ¡)q"¸Éh]𽦖žŒ>wåêD¬88‰{¶éª¨ÈÀéŠ3çøzŠÔ0Ãd. ¡Q\ÜÞˆˆ\µLšh)M*"|M!ñ†ØŠ6ÓDèi2žžÈe(„’k–iŠp·­^ä2lçPª`@‚¦j‰¤ FŸÊb‰'Ø-"’³hlß2L: ;pº‰£J=QR)ð¤A0ކ–ó*^‹ ƒÈ5%²jÒ£4¬K1N¢€ï<ö’A.²®mÐËà´'¼jÎÖ:…ɪMÎŒ¦‡+gÒ×Bd$2fÄÇæìnòn¨Ô®‚ÒD£U/!ò7ÃìÍ&\0L%Ä*Z,¬Ršª j¥G€dMÄÊïpØ  Dw (Ì£ ì”è1ˆ’Î¥ª&Q`ŽI ŠWðžC01‡“%s¯Ê‚§ç-,†ÄîHüÍ€a6¾©TÁ¯Ÿ ¬W ¨Ò‚s¼Ch%ЍÞGZ‡pD‘i3JªùBg…oÚÀh,p…&bl`3Šà¬'ÏUCæ#O³ ¤žGÈ)ô•‘pI*’À Hr4±ªƒÖÇMàÚÌJX«Ùé3` ~h’îÄ…ÄX’ÉÀL’ÏRD´|8h&©æÌÕBý:ˆb3ô-@`G1¬F›8na'Âp3fpÍ ˜‰†‚Eo,cÞŽLJB’ì¥hƒ8˜ä/å[:G¯Ê",л’Eëd´äíáôÜ'†!òÛ3!4/G„bh99Eä–b§ài05D´¨¢ËIRË4fª?MÚZN‡U Q‰å?óä­‚-ÒÈÁR‚Ž,9À ìA'B‚tü®â3â`$5@/Ôï)‘®'ÄÊWÏ«Jáþ¢æ .ÊVJ=#u5mW8ÂÜÙ .gE¤A8ÑQáø¢åÎ@Æ&Qñö$±;/RÒ"³°¹1 ÂÞRŠƒ†êMÊ@ªS•?‚WÉY/ãætO&§·a¥e*4¾ÚpéWnÐðFdc1XVJògj õ¡ ÐŒˆòãÂ΃“rÝ”£+§éÛEáû, "é[ÖSGóå#‚q*/Zª*ÑéºF ê÷ÓÌØ4) ìÜHßÒˆþK¼N¶|‰DªÆv¥þuŠ¤Ý‚7±Oïëõz7m!jä^µD žJ^è…êC½sšé3•5•“@4|£ÖçV°ðÀ¦p‰.r÷íå"pªµN‰c§’3mZØõ­§X-¦Cá¢*ÃL¹pÜYª(jã6móFÔ°’³×Ujë‹Ö¬O}Aµîæ,ubÕúDjÌ Ô¤SPLòd1!¢áBp¡ÝÉ ;¶£–˜N³RüF’Ö2µŽ¦-u`ªáÊpD¨Õu ) [eÏ3° …ŠqCjbë“3óÑ/Mé5Tñn Ÿ3òâOgdSï8aÆ0ß+V"s,ì'« "oLÖUU6ÏC7xhãµn÷M>í(Y‡O®•wTú¨ dMÒ sî‘n¤´¬C0=Lг·8p§0&F'3S˜!¨Gb U”‚)¾ÉÙ4÷ø&§|is'4'$"v'oxâN‚铜tê)ïLÐÔ9÷òºËºe"d\w³fíd¹¨“[Ï8")£TÔ|×çذO𖌕‹U„BšÌf’GÜZKšq'Ñ@ëKÌ_#µôË @ \먓 И‘cNblñSõA6KsžÕ0²Œ}*^þ‰I2lçr¥GwLêsÓ-@&ñdÆLl Qæq ¢LЧÃeê€u©YrOò®W wDÝ@ó•6/0Pƒ‰ìT÷c["`§0³@Zï(¡/R&Ë~=Uüîwhd°ä¥ìÇÿ‚Š¥Št¸A7z‘ïˆmnÐaË‹2ÐPÎ\q¹@W¿2wî©óP¨âàæcNRç… lZÍ!ž¥·ƒÄ>ËáTÈÕ`íˆ3fx3­˜g‘U¢QÐ+IvÚ@׈ǓÒíp!á³¢õ´5°Ê¾ÉXaÔvxõŒêx°S>6d¦q‰¬ØlHJ=ŠDG1„s¥.’òÚ+9o.ÝD7ƒ ¹(WÍi@pzÊwÅÒp¯sF‹^L:#Ì×¹dÂrzظvšlÀ.òÌ*²âF¬Õ¬N‰HƒÕQK×(¤pe"ÜC—š1”ˆãä¶•‹å7˜î³õ3âq¢aôa¡©@Ku¡¡‚д.(³R¥€ë×,ÿ ƒ [gЋtUAâZVUÈêŸ_™Yh›"1xAYŸNÐÞö~$ÑUY ˜—À‘ê!g鏿˜;vFJ4ÙnÀ¬ù™«?#m‘"'|37YÍ"oîxàÚѪ&U1v@ÿgÙHJ½Ž[püg>}Öôö]$ OË “„:hVŠqbìq¥'¥i]¯ø&µ¤6 Å‹‡á!M»VÎÄSeÁo«®”ûé4XÕ¢V/£æ­FO9{²Þ¬wbÃ|‚™ $KÌüâòǸÒŠ¿9U9g H]ì1À5²Nó¶0l9r™" ±‡xB)‚šÙèi¿O¾ÿX„&ªÒªÁ"„44õŽŽ£Å bÏ&b‚¹Û¢` ½W Y«« T6ÁŒ¼ÆŽ#V_?[á lø×èÿ(ÈÍ|Âü(ã`VpêÉuHè'ºûfB¯«nÜ‹êÚ¤lßTÒǦ‹0Æ­ÃbMÖ“Ì”w[»5,ØšTËý—ÂCJ¥‰Êåâzìµ1‹BÒºXÜÞWä·Ä4ø_3÷wZ×´Nº9Zhg·¹:Ç7O­/B X÷sî+ÅwpŒ‡Ð$uˆ/4/9¾ÑÐ-­*üé0µ8}If—ªu(Ðà N×Rh2VÜcd³¢}°ÊæKÔʪ{H}+¬ÊŽì2`'Øa\ó Q‘Y¶›ò£â<—ƒkåd¦/8£Ä鉢`´ò$|„ì¥ i6ÚâJ–Tu:Y°áù ^Ëè+dˆ0÷ÏŠQX~7‽Szí4öíÿ¾,- Å&þA5-˜WàDë!¿àÏØœ°Xÿ"ÓÈ.DºOŽýHv,pÂy¥¶»[AÖ.ì2 Í4é°«f¥Ö^>¾ãÄ"³'d-JÀ³­(ËÏÅ• ÌçNýÐL{ÞJ®XÀ]‰dCQdÎÉ,±põ:Ágò+M› 팬µÄûu˜êó»ËI1åŠùæùbpb•Ú¾Úq²:ÿR=!Sc¼âèLtd]~abœ–ÇZ´$¥·Ó§[ˆ3j Ôdã‚ò û”uFã-³¦¾D¿3;ÏQxY@šøsç{˜¥¶UõÑzPªL¸Ò^«ù2£JCÐÿù~Ät–"+~9ÿ)ù6JJœûi'½{vaǤî¦ß9»ÎÂf&1òy²iŸ™k–à Ì9"ôjª§{ô'µuìºfŠšŒp¤—Uòbª|_”S øüƒaèT ÿ€"(”@ý‹C¢§ð9†C¢@(ÔYûŠD#ðˆ I Éâ¨d¶›C#QI 2yOãPgäØF¤0çÝ.… ŸÓÀ‘HtâF†Ã¡*Ì¢{)‡Ì*ÕØu>w¦À¬ ¬¡F¥pë=^¾Žß7›¼®ZÉ(0j$2îúÃSä” 6.ß Ù"RJ[î‰ÉÌ Pé\†IŸÉ'Q9Œ*w¼¾lsø¦J—ÎÄ©ùIª"…wo™û«Ïu熣x m>çëª÷€ Zˆ¡(WA W`0æ²\HþÛ½EÂʵ{bSJóõ¤ô;&’6v¬Ÿ°ˆìGV …~ÇÙ+B¢ÍœÅyYÈv¯œL³×§±p­€I^ÞŠM,]š­®Ôò%x¢:I1A[.põË  ŸZÙ,™WOôMPó¾_0lMòÄ„`y´8ÐHå(4ìž9Ž Ì˜Ó@ˆâ…iT®ðó×åöÞ›¾u{`ûìÚeS•EÝÙäš‚nÀ ­Øñg1pùNJþÈÏÛa©–f(²Ò3¢z‹}ª4ÁŸ’ä7êÌ‹;d|F—Y¾ ‹%Z]3 s µ Ÿ·-]ýJæ† b8`GãÀ.ë„7æîr\Â$¸špOYj@ìøi;@#GDJ˜œ»ºnt„¶hŸâEGѺ5ã†ÊPtI.¬0«-%pü_„ '¤:€¢„æc{åCf€‘”Ìcˆ¤q°¸çÅÑ“w-)E¡·ŽuâÙwE«1œ>ÄPÑãÖgGén¸ÐlÞtŽH JêÖs蕳2 ­c@B¯†œ3fפùŽ«<Üâ} :J„Ùê˜5\¤ebzm&ë¤øVß!Kn"Ï̇=T’Ué]eÕÈ«S—"_äÏB±}6Ç«˹²n²ݲR5³ & ¥¤ËC9ˆQ!ÉĥÖ=rµCÆ’,_%9…„Ä ;«aý>j*l¢CÄ@°ÜÄv¯¼†3)C>H#Sx9Š)%Ÿ™—!RÄñ—挫Ó„V’ü–iÈÒȬL†ÅݤÜD¡ü0 LÉÆt†ØÛ¹DKcÔ•›1åPc;Õ•»¼q¦lq*I!vo"ªQŠ(.Úžµ§yXP½G¯c,Às ,L‡Cˆr׊éD¥ÜyÖð\`õ.3ê= Àvu>£&Ì)µDÅTóX¬åå›6“Çé+"j޼7ÞX*i'AK œdú¼ 1³pdüÓ€ j•ì˜õ×6H$q"U=¬$i,ørö¶‰ÚyEó2í™~£Ø¢5‡Ÿêô†ÐyeQtï@-˜ ˆ‡fÉÚŒX Å¡V?VÔ1sV§*B{.‡ä«Z)±Ð·Ôù®«£’ëU4Ða×™´åBY#lÝãËû·þëÍ/ÆžÀ] ¹C&ÅÊðF7½mÉ:Ô-,ã>‹ušDCè9º”(LÝLL} ±p BÂÎ)‰k4 ªC›Õd8^¦<ñß½â]F.q¬’9ÈBÒFv$™:uˆ†¼! ÐUWXìD”‘ÚwD3 €uèæ:-xDì!oÑLÑZ¾š6° ‘˜ËýsQY2ôA !¬h*jóôÍi±K(‰N™DuAòÆh¹õÉjª´‹gH”6ÍáÁÆÆ±1>ÚU¼,TÏ‹rY3€7€©@!wµ@8«Œëbœxd¶öñowš² ¢k–åmtÇŒâ³k´Øæ7ýЬ¥/%,C/%U¸ò?Aòާ\Î…V²š½œì6~§Y§L»ˆÏ‚õòpÇq²­Ú+Ž†×´Û½C ¢zµAy“Ž-ûø­Wõ«" içò#ŽÊQK£Ì—€s ë¥Þ"©ö¢Þî{BûâÈ“S]‡î¶ŸQ^X¤A§gLcâYѲõm×’T*~¢°},“úSes¼´R×iKðdÂerã“©€/Aß–‰àJB!$ˆ”ÈŸ{qóϯœ¥‚”LXÊ>y§ºÁdQi¤u72=N£Æ“[ÒÞ_æ£ûë¾úió‰ Ž‘PªQ‰qÞª¼RN¢y+xƒ÷¿s ²Ö± h= â['Œ2 ðý\ Ì'€94¼4,¡W&™Mc‹˜ð¥Ž¼ ø­é5“a!– KÁ<É 2èºq¡œÑËã ¬W0”¥)ZIÔD¡ {HáB6˜‡©%Ž8»‚ ´ŒB³rL Œ“Ô´ ô0&üž 9’ñ—˜S½˜B Y [̽ þ¯ ä‹ò÷ îAÌy) Èh¼¤*Šé`µŽ-è¯EKÍñ×½D²6›¡9jî1K)‹ÇÒ~ÔK¿,b$D©£7w»ÛËR«@ôB‘:¤(¾$¶5²«ÊácE*Å¢p¬Ld5ð®¤|‹¹$ZÀé!ÍyD<@‰ãv>qV ò6JÉM8»ÃÀÌ΋[‡àëÏ„x–n´ò#É¿;— äsŘc%¥;š¹´KY0, Q4qMû #ËþÏ)pbο*Z€ZÊâ5„0·‡ÜM€CË´»Êºj.éBHr“CEQ³-(Å‘ÒK@ žKÜ  ¦¹WlѲ(Sò€ÀÐYÖÒ9þ Zž¡i61ŠÅ8ûÒ>Aƒ `äŽ26B£r z·‡˜§¾u#ŸÈ†PÁQð³×B5l6µMòž‰ t”zB°CþTŠÒµ#ÃL£‹”ŒÍh‚'ùhL*?Ó°Ó½T¿ƒ´°†<4_¢Ê{ihU=Q¶Lû­¥ÚH4”ˆ”8= »ÊÛÀ»% 5WÁ¼üKÈ3R™Â+KÃA¢²pŒ:÷ÇAŽJ$›’Œ,†yÑJˆ‹ÒÔ2Ú”ŸÈ¢U É¡=в0¹Ó©‘1Ùý…D|¤’‹d¬›ß ݸ¤Á8tIÑÒXºÄ´UºÉ íYH¦4Ê…®D€æÑU%@ÓŸUV0ÔÂóWCLp•p’DY†Y‚tU԰ѳ96+&LÓÐÁ1M›K[l6‚ r´SŽ×Ý€â-ì0‘ðÙ©ëþ¹¢À‘ÑiPiûÚdÝÚÚY‘¤2@Ùê͉šÔ ÅZûEŠâB•œ1Û‚KÿÂR‹¥ÙiÆAû×JDÃÉÆU¡>Â2+c,Ô•RÈzõ™e Úxž¨¢É:ò0!ãÞ):­X‘‡-Bž¬ÔéD¹•º <\©¢àÓ­C|‰²zÇ9!ûšû„-ê\]Á>’pž¿ âµÊå"µ©ºž"ªš30YÊõ Ž5#Æ%ôLÁûž!ÙtÑqŸ$æà,Lƒï ÌËVH.È’@3&Ï=ê$Pí¬4ÏÆóò$1»ìµÏ $©¾[tËI*(\Y6YØmæÉàzb\¡úpY»aªV¸j€&zšq]ܤV’D×2ÜäkN0~V„鑚B³òb²+p:ÔA=Pâœa]ñŸ[âÒÓ“ÊéÿÝÄ=ÀAe‹½¢«£Æ© -Úª˜bVÒâ a £a>¬™þ2‚?š÷±ì„§mȬ gí½”€ŸÌS³ÄA^ב^'k+Ý»LÜ4©2+®7é’ b­¥Û®ÌÊH]jŠª^–\&k„E»=7fSR{ˆ0•ä¥ÂÂ:`4¨ýÕ€?cÞ3Ò>3¤á{U’ëÉ:+]Ú[–³Í¥’–¥îÆÍ¸ÃïÓ8Ä;gÖª< ›Ì«RðÔìPê” .ewªÃX™I¦Ë“¶´S´<Ï¿f! ªq2-¦Z¶QÏéßÕò•Azš+Åö=)TÒ3Š[Š&l‘UWøÅ»X|ËÛ½˜}©agg‚$ž £ÐˆHs¼\fˆRuäD©¥‘Oa09£&,‹¬p<bÌýÙÕC-,#L•ƒ5IÂãÉÒ Ÿ®<ÿ±CyÃÄa¹æa+0Ù«Ò”£Î[ÆŒm•|.ºš2ܘÃ&6·Or¼Zj´ë¯ 7®\ÖAæpclám3G}°Z…»Ôcj¤NG‘óA×Z•QAî4Ù@ãýO@ìKAâPTSÐë~b3Kþ­24ÔrŒ[Ï©29âzÁ;ZÈž¼ËöY<·fZñMެÓÑ™dì~£ù_ \uQ†¥Úlï½:ìisé½Ý/ œ…Û×V¨&kè£ #ÆI:}Zˆ”3m{»Å3ǹþC¶*¨%ÿÈ‘a-í1aºeÌauôD=΂G­ëèÂ<}å/a£NϺs´ìʾÃH«Ø‚YJaÞl"6ÚL [ýkÒ½©0a ¯!{)ÓBÊX&kti!éCÂj3wê…£*Ž! R ¨A;1CϵòI²HOóKnã÷0Kåš3Wçdá¯{+8y»Þd˜ùšš+Å c§ìÌo¡¢V¾çW®ÍKDN`¢Õ鋜Œ[…ã4±C«×b4´¹U06I0m6½5}G¤ys‰· LþS¥—Àʤ·Þ\<[Ч`ñt''mnW2”$Îl¹ M)šîþF®P2ÚòBè¹dÛn-.½.³e!ZÎÚ •§ÃÄkÃîrþÌœ)6 ²‰îŠ-)…=»ÛØý»8ýGÂ0ónWëÖ[貺3œGViú,ɨºøñß9V_}k.W"ö–Š¥=ôG¨˜Q6ñnÇ‚ ÂGàÒ´ ëÒ;fãÆ£²5è”y–LÇ<fN Å ±éZ…›9r ëÏv?ÃNðOlIòÏý—´blfiø’EƒÄqIÓ@ÌÊ.H}v2£àßDk¦K±ÛQD>x#™41ûLˆ÷ûj8·°Lï&·‘1"±¯"Š7V3©ã¤´Ûè¿„ÉØ}Í+€1àA?£³ ð{½ÛÖˆ&0lì&ihwò­öØíšøÃH§ž¬Æ‰µ Ó3§lRg¦4?r‘ró¡ é£KG|½—œ%—™ò\q™IØ*œ{‘½L=Õý<´žq7¶f<AE´‡ãÌÌéÍ#Ëš$ÇÐÑ ;(º[è›fЭAêž…²,i¾.ì·¦y÷LjáýÁ@p & ~C_ðð$D}ÅbÀ8Ä=ÿÀßѨÔD ƒ€#ÏÙD*K ‡Ê±èÀE%‘B£Ð¸L•õ;‘CgÏÈThC—E¤³p• —Má3$""|Õb`)ÛêE1|WdUzlK «Õé’‰„` k’ˤ¶8Lz5fœÔ€6ûÄ–œ°J#QkX] ˜ÖAz«ä‹IïÐøTŠ5zei@k”>¯d¡÷ Æ}W½@çÓHŒZ9>žÃo: ´c±IgØjÂþ˜év°|æÊcÏ?ï{hlº¡„ß_¼ö]íÓõcØpD[ VA=üLǧ»F¥W‰cþËë‹Æ!Qn.úÒ·Aïuø· œBý.ØÀ²éóÂ÷!)ò<Ž%ͺػ4ˆ:º|0)r€5`@$ ú„áPWä4 Äa¯ÇôV F_±·üvƒHc Ûö*þŽ¿â 8ü¦?%•Áe38è m'“Èãòx,Žs•Èä±9LØ+•Êdr9ìfO%¦€(Ñx›òA¥€$ Ufhÿ¦A(Õ$ú+S‘S¢²P-¶q”Ï ’»h '®Ö¬±™KîýBÊãö€ d_‘×ñQÚ6¿>åsðÈ”™G¡÷ˆìŽ';Š´Tj|s!˜Á$²zLvKf”gp×ÍëF|îj: 6Rú‘à¡õ»®7–Êâs†¹µÁáüoöj™ø|§2ÿÎ?ûö÷ôê!”î_7XŸ ÊŒm&xnLG+ßÉåºp³â©&ÊŠVȪîj4¶+à~=NÈ|Bd$õ1/ãHŠ¡@:¾­¢i:ŒÙ«É¢ ¾P©þÕ¢¯Ùþ궪‹¼¹¢(*ëÊ&Þ$©*Œß¤k«`£GÈʈè!ðê*º¤©r ¶+äÒŸ±êê¶Å#Ê ) zËã æk6¹Ì£Âº¥+bÚÀ®û67TT»¢©€l‹a¹çü†•",r‘ÅBè ‘¤F›:À‚Ê­éZŒô·)ZK ÏKQüÞQ³|„ÿ²Š3ÚˆÌ ÂôË­ó¤¯SÌGëZ™Ô`-E€SJ7 ¤qâ3ZMR$†·•k0ÕAÌH¥¥g½•W·ˆ)ígµ*Ø;¦Ñ3-aϬ¤AS«q5z½°ïä\š9ÉML¨Ûl4ù6W@@H j%pÊR߸§ó'#ÊŒ #(I-Nà¢/RSf¤(œ¤» •±ûcÀ‰²>ßÓ õ´Œ·’„³-$/ËŒ~·˜jŽ¿O8K¡Ráêú€kËÃFÒ×ðC6Qï ™³¿D0°=]@Ú¶6‚HÕ[ ‹¶k¢Ú‚äWF|²ZUöZ×G'꿉¡î¿“dÁÏ< }òËZ6?Ѝø³¶öëïš3› Õ ®¬M|ÏEÄ‚vh#"‚áÌë×A|J:•Æ’õ4¨Úë†ÀªÜ«&UD}ðIØS®1 ì¸f ·Z{ÜrK$‘ÒêIÍûñU¦y`"ú_Û¬†Á¤)ä1¦&fD¾RüÅ[~~e-U('# !’M0Åm(#sE [¡$#o„''˜ŠËò*mg9§µÝ:îPj|«5Óâ¢!©*­å4ÚÊÚx}ä…j"Jz“Â8#fýâÃd_“úxlñ1p4Sµ GÜÜhov½×þ±ÓÁ¿dO×$ÃÕ9u]´ùKB ¹I¤ˆ<+© -DÁ-‹Ì™x¤”ßÉsä®Ê4ˆˆdzZÓ¾Ù"äo°(Š¹È…ŽÚâä˜+r!*¢j%!Z´‹Niº¤ÆÍý¸&­ È’t2Ô-ýi«óÈ“º[kH#6wm›;  K¿I­S4[0b¯:´FÄ6Þ]‡Ž”r’rRRˆ\8„Ëh¤žï5 èìˆmc$}F¸@¬W{Šª8¶´RSj((¢iK$B+ƒÆ0‘áäøÈR…_0„DDÑ¥€jRúx5©ç\HÌìP€*ù¾Äˆzø#¨:U¹0qð˜È$¦š0ìúÈ1„cj—~TK«*ž-YbÒÑm·¤äFçµTU%m‹¡éÍlVÖá4&rð¿ÕápaÎL!òRù%98”iA§fÕ>áXýo,Om·ç6e (ÀŠ2ÚæÃ5xVaLŸFB$¼¼„B*<cèÉy-Hnf“Çð†¯²€Ď쮫" —ê|§¹n¢ôyÿžHý_Ü¥[77¬~{Hs&"v㕵¢¶ÒƒO(“ÈÒ g D`Zr©B¡³µÏ%DÓ¨œAµ4«Ú‚Ñ_)‚Ê*y¤äŠûg$«®ÇjæQ¤läyé-®ÇDûy f>b¹­Å‡šQ •U²˜}ªWbN(…Vκ­ÛÚò™H­¥Ð‡ºX›^ dU–I‹F˜SX%¦‡ñßÛ܃2“šàÍXÃÐKΉ­Ý|—äN"í†M®¶d&—' € ÷l{áÈòWbÝ22Ü)3¿vû—‹òó䂸3v‹w.3B­Äÿî<ï&Ž“åºü©éµs1suð÷]½ªu¦„ùì¤ÅgWæÃÞÂ6P­H9‚ãɹ–Æ2ñRfo8”‰™fvæ9ª? É¢æ…*—ž¯5ü%VC;E3fnTÏ“ç’!F³ƒñyDMºƒ2y#é>i•߲рº%EÇì‰æS°ú{+îî}¢[s¿EYÙO»ÿ›ùÍñDeLãWÕìù 7íBêë%7OÇüz´ÿÏ-LʾœÍ#ÇÒØûü{eÀ ZSI3WÒaùõ@<üÆZøÜDW¦cUº ËÉ®ŽÉ¤§‡uJ§AÈ”ØzÊæ“*†+înOж$²ÑÌø]æ;ê¬Q£Ôlãxfʆ‘­ÈŠÍ(gŠó‡‚:Aô×àV%LJªZ#ªÌ¬@ïž ðÔ FTîRÞî¼F„ñ œƒGÊ  ‡Š//ÜrHˆ`Âh[ ß-¨]ïŠd-D}.¾»ÏlÏãø_#`9Èl”‹Üé§\´‚!L.ô‹h‘FÔË/@s'º7ŒzTÉàÆj”_‰øã¦ÜQ®2‹¶ežÄþ°Dï§€ÖåÒjGXOÏdÒÀüÅ^IŽŽæFîJé(†o®Œ®ön¥^¢ŒêßÐ70f„ÎùͲ“¯ûÊ$prÓj{¨›¯úý¦¢³aï§kd¡Ë¢ÀÉ_ÏŽý‰[dÔŸ‚¨Œ¥ò{ú‹røPvØ'–ÁHÊ;îÆ¸h¸÷ ëåZZ)ÈÚŠÕä¡ NŠÑHU âû¦àG$ž©*Œêø±XìJòUL DÊhlïº)&•ÊÎ"0öëO xçªk¤ ’‚Jg Z(\eÚÂ`ï¡àÒ!À$2OŽÿç$™Nœ6Ê´O°vêØÎ#«¼dRÉP¸©‰ 0˜®n†V‘¬£r‘¯è“/Zê‹ìÐÁú¼„ RBðŽß"j˜¸é(žQdOélÞ†—ð–[ŒÚšË ßaöÛ„ø¢Ï! ™‹RB”pB–Ê­)î-þêò¯žãÊÀd¨F×fÅ O ”vk""€Ï)‘–¸€º'nÃ2BçI*Ý2ò!ã"È. "Îö‰ïÒÊ¢q¬¼¬1 ø?¢Û$éÇ‘g$Õnî„HÊǤð+e  ÿ®Ô<ŠpÐRMo‰3.\ß-¸ÿrƒ1ìb-¤hŸ‡ì°©I$ÿ£#2T/Äø»Èæà, ðã dPRÉj#+ò®íl\V±¨«n!D) â67‘ù4bC ä—Ó ìíòÈ"O+’€¾0®éÈ€Ò\TãÂñé?7æêžST'Å^dIµf«çŒ9ÈôvÏŽ¦VðºäÝ=“>&k6²§Zˆõêt“…䞆qˆÏ4†ð¤_-=%À[d[rÎü.XÄL‘Aë®°ÅßsmÌlß#Â]±¶¥Aüwêzÿ¢ fh!J¼ÇÅhpÒžç" fÔ˜-ä·£äۓ„îrw´$‡1#ÉO$óKíª°ÎÊ—ïÅ(!‚W ‡SS= –O V]±$M”²"£#>ÜŒ± ¸FºEQêîãœ2+¼°ø¼"ÛLúu,z¾«æj²ÜI”Fè…4dB>7‹ZˆK%ç4ì¯Bl"i®ŒãŽ~Šïõ$îÀl;"É¡%œjCÔ]¬êöÑ,D 3-TØ LfÍâç£Â»ÊÜ1qÅ'iOüpf>ct['O&JI3©¬Xô“Åòã©›Ud²–k:‘4¡6ENø§ ÆïüþÐiCÏV†åZ¡Ò°¸Ô0˜DžT%cÕ&Dn5Èÿ\±‰I¦ç9â ±âN©mëaOž³?’œšÐ¤$舊(DM‡k «é}R¤øLf¥•²™O˜l.=Ðð|‰áµ[®s õ.Æ•ê‘xèDlò.²­¬gry]ÉH"öCÝ?ëŽDÏësˆ íXÍkRŠ‘-Ë<s•¨É*‘7/c@ˆRÛeF¹]) V®cãÈíÂ*ˆ‹Dw+HT ´¦#p¤°E9ÓVZN.—ÖÄßFºÏ/e&s.Ö‘,€=Sb¨¸æ(‚$lRǺSOèZ#Õ áø¾ˆ¦înÍLÂh /Ö.8ì­ U×$ð¥ÒÑ7Y3)ð-Ë>ìXE¯ú<’°ˆ 0ô¬‘Õý$qúŒ¬êŸÍBà³Æú ­µ·J°Ä9c‘ÿ¦¡naôeÂó·pxòÅiì!Š„SÉ"ôÝlÃ`Š1ÿÆ,Ð":ÎçŒÐšÀÏñu>³×LÖ¢n¬×m·(Ã…MBò¡{”U~±ÈrHwVPÚsÏ*Õ¡÷$­D“€õ7È`oÇrŽîL›Lo^2Ç»•z/Ë"-¬Jþ¯V* ÔÌz*$Ádîe†Š¤2~uq(â×¶åv\¦6;Ï3Ý1‚pŪîÿ1g `rM‘1©wÕ-„÷z6£Â¡Ó²75+ ?¶:€cÁübµab·Ok†¶cQñqÔ2lMJö!øˆ—cV&ŠŠ-V¢‘¼DUÉ’fdµõªjP ˆK%b •A5æÞÍ¢Oø§~—éÅJñ%@©Øí‡ Oèš¼÷šÅF·%x7!€ Dø š×›}2~4žYPjܪ*‘v¸âó„øAÏFV+u5ŒàÅãOÖ;I(‰]µ¢TðtAÓ! ‡‡ÿN icäÜ콎?5©¬­Œå’Ý_%“,lð !ª…e+__”Æž´îö¨Ò€Jç)ã¾ø§npÉŒ7Ü¢‰ö224>Q úIpn¸ÿŒo-(‹‘n•eŒØ›Ô“'5¬hÓæydœP DÖ7Cúç¥ju„äìeMs„Ö‰u*‘0§>ç¹èГ®êL…Á¤’K `X´ˆŠÉÕÉ¢r($,9n#Y¯7‰A©¨v²ñ¡D± MÔ½Óî†Ãœð+d„S=‰7ð½Ç 0rSs´ûÉ+E6Èìj ð̯9åíO˜”6oUMÆãìê6 ’’ê‹Ê!£,˧q€X-¯y *bl¡Ë†C+‡‰*»Ø(x(¸ðiP¶ÕmW”UÃå¨Ñ±É[XÒ€äpfEJs™êŠ&`©FÌäû>ëÓhÓu(w­œ}Ó3"Z]uþ°jÖ纖a溑x¥ŒÇ®Xî6˜Lt=sX7Å¿3IŠÐ¯º²™é}PÀ8OòÖ ¾áñäÀV4 ™L§&ó2$îòÆŠ–TøelåTÖÜÍ…¤íLuÁøÝ‘Ã;b0† „ˇhn‘ ð—â º9=jÇØ™K´t©‘RV‡²ýœ[\rQ°üª‡Âr¼ë³uÆp4 <•Uz§$ˆ›/ö´0†ÇvO®Ø”UCa[4¹ZºÏÄ»Q¿™_²ú2g(y14gp4Ê/6÷m*ûÇ:MBÂÞ~;âanïyô’†Ü|ó‡*!(fŸN@A©*õÈUOg¤SHˆ/4ê¿ X•3ñ‰S<0˜›°sIÈQð]¸W+tgËlP±@ÊÀmÃ-8›KSÓHЙhgÂG¯û„ﯴÚ–͹U^ç}ܻϹ=L½Ib!§ ÷mk‰M™o£Æÿ‚ gã±Oé„ûTî0†ÂSÀ @-¦m•ÚNÁiͶ¡ùrl¹ï( ë\iù^\ô“Öñ„J™›w„IŽjß1‚dPà…®º×¬hÕq¨$½£l†7]°­Î@Q®ãÀˆƒgxgÕœ–Øð…K†Û™#Ï÷â²pÙà&ÐW.©Ý•®heËGˆ …ß‹™÷m Ö4L !׆»>½ÙÊà..2ÉØê1œÝ›O¨?—Óx3€®L}¨¢R^DAÌ—9Zâ)‰‰lUûâ¨wˆ®ò+Ü-Vj i»Îã²Ü$¢¥Ê›âÎ?+©?ÅÀþwÚ4Fïs£a’ÙÒydØæ×¼ž%4ΚÅIS«ZhsN=æwîg“]Ï©lVƒÂ]èšoô>H8¯oUØhø¼cëâ®ý ¸?|ø÷íN;¶ä¬4#DA}:æt5 Ç=&Uur6rÕ±»„ñ0ÑÊܲ+^ãV+ü¯$Ú—ƒƒI¬ˆ–€ñ$Í|áÍb7+ï­â2ð6ºZØj˜4Ë÷ïsK?tÊñÑô4kyâî¤ï 7ï^ÒxñvïÆî-{ehEDhÃ*úÏq¸äÒÕöç½Âˆ NU¿= –ÑÒð‘=áz¹ùuôé³—)Eë-TKªÈ OÿµB¤Uï'3ˆž­¯Sï©RÔ3-3•& î aT"{Ãá@N Åâ1xÓþüdé6~DÀq¨#î"—F¤OèŒF;MàÒ`4íñ=†A¦0iœ* ‹ÎÀÒ¨,$¾ªI$FPý«DfàHYû1¯WàÕšd a"Fbô(TÆQ®XÀThÝÂc&¸E¢ò‰Ìz+•Ði°‹=(˜Þ#•8V r˜Ü«ÀVNcP}`QFnc+—kuhÕö&†J"3©Þ2\ÓB/oÊåf[.ÌJá€}Ö25=|gâ0lôºMŸËJ8«| †“J$Õž,»} Úè1tkP¹\ÇÅúÝ›œ 6áJà“FU«Xg*ûûŸ¬ç`‘D2Wb²"îòEŸÈÓÂ@Éúàæ€mt¾„FrLäÇ$s $R|Ì¡I24½?çû¿ 4'ꊣ=ÊêDƒ+ŒüËO€ Aë[8ʃ0ÄPôr\†PGó–Fq 9G` Pü¡PĆˆ¥jB²Ù¦éZäÆOiEY Í)#1aw>ÏÀjt+¶ú¬úÛ)‘UH’íµŠÜ«OtõÞÆ:ò5`Vòå4TJnæ¸`+ð}©ÓÛÖ‘2Ò}çl¥(¼öö!´f~µª´fË?tÊLË™%í¯È!·•)GÛËg ‰4g–3íôgŸØã»|]“:¢é]šÕ Dñx¹²­xEpµÏ¡Þ03I“NHd÷"àZC·SkTãÅ*jE‘.ɇý¤«T`“%«Ë’ ´T+K ‰ç7ÜüVZCÅ×€ÑÊɾbÝ%nв›ïÑaû ¿Àùlo¤?»hSÊ=‹Þ‰¯®éαTb`ç|ÁzEª£9 ¼~G;êIEGòl¡¡JCûj ›YZjÒ†Õ)(ÅAIgØ¡ÿ ¢s“· RçöfêçŽä MŒÀòuãÐR-’­Os¨kæ¸Y7`ìûž±Ö4ÿL2Ö$ž½Q=$]GÊ¡®ùŸÌÿl§úRË‹Á&lä¬u*ÆŒÃBoà D4²ä…RzO‚/iöµ6޽`$ dÈĨ˜B˜œ”{kjÅ Ì$—`?ÔylHížT ÉHBnYL/"ÆâÚíE¤î*è`Ò‡ùçkq;v·bY`Ú6Š@ãNTʈ‰™…Ößï+…!ø¼!øgÕyÝdðáY›²šû©~„¹µ'œLMòf}³Ô€´ ÙŸBPÙ ÆÄ^QÑVq]ª¹µ,ì`¤)Æ1®Gùùã+˜åÉO.bl‚P-‘t’蓆է4˜†º\Q r5=ÂÁüŒÏœO&ný…Iô,LRK[K1‰i-œj€ùY*Â5á zYÿ97 •èg.¾8pæÚ[› ¾$Æb³‡ÑY…¡l¥ÁÙÍ)ÆÒH–›"šôŒEOÚ'xú? ;†ŠÀX>²ˆ›sȵ“tâI‘6jnÊ9;2á€fת¶nIð=†“³çcIDikF&Ϋ´@<A÷pæ˜×”‰Lu˜¸ùZ¸`ƒåBž…6ïk`¬ó‚SNÑw—Q#>ˆª 1ˆÎXe­Ç)RUÒzûnKsï<¥Ñ´¢'¨Î\,ÙØx5çVÆ B¥¥*£|\}¶…÷î!0Ê• D›¶±àÅÞsÆ#6ç¬Ëc(ûOœÎúùêúéà„ò–«õØóÃ0vË¡"tÔYrš@Ù)²*XIä%l=\bž“NbÁ=ÅMœ§‹e&õç$tý;Þ'…!½W·Ìî0U«ÌBÛÄ‹r;,ß?gÌûg]ÌOÓç{¦Vˆ$^Ÿ`8›çÝÎpp kÉqã*dtU¬æør4ˆH{9²2W6Müsq<)ˆ™µHFN¿l|MýÞg–9ò¬zæÞ’kÁþÓB ÷»ôbµÈÕbT=ÚFo’Gg=Ê+kYëk.3‘Ÿ<|K£›ŸºßFö5½ä–ZÖòFïßùé“¿zëÄ{.¥=†(²ŠÅ€©@”ðß?¡û®’­·’ sã½r ·™8r&¸#¥!¸k@«N¹´! a ø-!±à9jè¦[¹ÒÏ$n q»"ªî³³©iR+²Â•Ò@–²w<¨°¤¯ ³Κ#J¿òÂ%¢‰!Ó÷–A_¾ ȱBÒ@ùÒ;ë"¿QG´,lÄýI3ÁäøBro7Ò I¡Ì/bU¼²Ìx—G2¨HÍž‘+ÈjѼ‡ÐÑÙ’ý‡Ìì•ÂqÐéæJxÌI†IíÀŸ˜Òÿ "Ʋk0¿ŒEM¤AJ¢‰ž¤s¨ÄÙ¥E¬S Òs?óÉU+;jÁ ¨‘Ô3$û:Aé!•“ñ™º:N¨¬C”œLû¡»¡º{) ªC¹ÍËu-¶`æµ£''Ì~‘¬âzl%Ý“B7¨¬ºê•:d«Îäs¢2÷Àï&¸¦DãÄEÓTÊ@Gð‹°QlÏ'›Ý³/¿>Â+ñ¡Òê äs¢è½C:¶ú-+F:º?ÔRàí»¸†ÃüJËÕdU¹wʈ|%ÅJ® *Äò­»•( ²e+¸¨2©ß¦ôåœä¸RJÓŠí¬éwµ"%™ žÀ$¸"eRZ2LXË+ëIÆ“ÇÄE|‡–«•$ȤÍÁ…<9œ´õ€Ý_€@ˆ’J¡ˆ3´Ñ؉[‘«ÖªÈ¬¶t»€ „-ù—WtK‘²n¡…´|Ð,buH\TKݰùö–CR¹ÄØtEV+±ÏܸÔê&Ö¹‰¹Ì"";’“ÅV+‚ÀYGŸ5f‘Q= iëÀÝž¨áÔ¨**Ÿ5(´´'ªJ¥Æs²¦(‚*°£2˜Dzo%I[šÈ9î)œN¿Œ@Ðu9Z‘¼µ-e/KÆ+¯@ÏÓùaD51»Å*µ¼ÀK0™¹árHsfTkÄ k¹AÀÄI!§@”Èx˜ÅD¡Ï 7£ôU¨àØ*¬–Bú‰%¨ˆS0áÜ£Ó2ÕH¼,­vÁA=›[-EíÕIÄ¥ƒÏªÊ|€LpdLÊèK;ûAòu¡“‡ëˆ€#x[P}¼à¾"?²9Aó0´´½ÅÚUÅY3,Z !tð3ŽÂ{ «+I9yöžt‡ÑËPQÍì“ÙÞ5š=¡ÒUUŽt¬žà¤6uð]‰¦U¥[/ÊMœÅ×:uEJ°_d‹¹ÎÒªfà­ÕAáò38|´Â#¡ü¯Ãõ ŠÿP̬1EHDõáÜr ^ aC†¨ÜÑë· ]!IJ?d8›ã`¿ºßÄæÛ=A@5ÆAú<·<õÕ´b¸‰ÇZßâƒ7ÒâÓX‘Y¿dŸÑ`£5½w°µƒÉ“Dõì®jBPê"A,ßL(¬ Ë¢XíÅ-!¾«5KR͇ȤK$×fT‹ ß+yÔJ!H#¾Ô~)B¶@·2o W1¢å ²jyÊ,êr‡ët]<@8â%à€4C³U@Vü¥LÁÒ?íÜ)ÙTTDBÑßåÌ62qc†R ¼¯;‚%ËF,©GX&S¬(âF +ØML?ˆ‹ «&\_Zè*Ë4«Ì£Z÷ k¦Kí‹‘«Š¡ƒ3â"Ê5]P°†Ò{¨Ñ‚:.ÚßÑÔª`ÆEŒÝFþ]8ôç€=5=#GP¬‚Yóa·´†P‰ •%X+™áµ€*Îjõ¯a1’bXU…¸L¨Cs!¿‹®ÄÍ-WçAG¤ÔH£ý8MKŠùúËiž2;ÃÃf;– É<ù6 ‰Ûœ¹T$|9…ˆƒJó¯ '6šµ°VGº‚3‹ËRZ]ÖS\ЄN>Vjب #ÕƒÃÅp‰aÕ„E€6êk©»›žD›ô)Ð2k£Ý2Ñj!2¨ê”Í|g2s*ê‹dK¹137(–±ÉuŒ³É4Ó”Êò`•u2sicÛ¢=ýÈÛ †¿xÆa./Ï„¢boʲ2*ÝœAMž3{œÆ‚\‰mÛn\RËÿúÜ[¨Î4ä’‹àümiŽSQaL‚³õ0¨¤ùšvc'¼¨MMÀ³‚Þ²ñRP&SQËÖéêXÔ…Ïa¡ôûC:<$âÃþ%6â1¡Í’„ˆy6³1k:ZiÂRWCÑ9•C÷«Pæ›â È6ÜÏ™›»u‰•cî`>EàÜ*àNsè[½›&RãÆ˜n6·¥BG§†½i±âY€©Þ…Ú öG„ÆÜ™j•c¸ãÃYu­1äµó,Svœ¬ÛèsôÌÐϹj‡ï ®Ï 5Žfçïh{èÛÉZ'X›¢[j\z¿*dZdPàdГ¾ãOä«þÅäcYRIBÁ‰ÔÛwÏž¬ FçìuveÝ,Ð^T°xØà¾ÉŸ4JžtyñȆTÇñ‘þ |[‡Ò#¸¬Ðåc3dÁ„ °Ë­Ýì±)²RdšN‹É­îLð[©!Hòë$ö¥$%pfТàóæ+Þ›•^çlQáµ6q’Å&ÄñÉÉ÷ &ÃÉ×äì¶!ÝEËη+çíýêe¤ ÏÒŠ¤Ö1)cïF™B9ÎBâŒPÎ&˜¾Ôæð‚AÁSÄMfÁž`N`CûåJú¯ ßhL°¯9ÊŠÆ“óHrjœ‰h‡ú£lñÞ©>t[ä@(“ß é²ú{lŒësÆc ‰^Œ T+j;õe*¬&ŒÍ±ßÜ›û¥Áç2ר´×5lÊ9Þñ5p‡îØÐ¯*óc¿)”[“<-áÏÖ!6|ðAR¾*‡Ø¹$.êcØàËþ û¦^ ÌÖRºíQqËÈ&’Ò: ö&梔¿UrcÉæ‰Û! Eq´`ti¥Ê½<ÈØÂýáÔþ¨7Ç÷Å’îyê^w¬›Iîø„y xÊRHñ®?S½$¤õ1›À£//z’&Ÿk¨ü}äç{¬Aˆ1bÏD—]ˆ[ÈÀB*&ÒŽa ¼‘ÖaÏ®g¢àêbàöaЫ}íÁ´{µTºw¾Þ2nÉnT'/õ¶ÞÎFwÂ!R—¥¸^ýïXjlï'Ø(ã¦Rö¡úî¶Ù”¢þS¥Ûä¸2¿î]6¶‹»¶¯÷ê¦9Ëœôíô\ÉØíÒ%¦ÜËü‰ÔJ)¿øÐeêãÑ#—k¾æž+eI [Iý’ˆþ‚?àÀ(D& †@¡Ð÷ÜD Åañx[ò5Ça0çì†"û„Â`è¨'À¡qx|2e-I °xD¦NžC¥ó¼¦S~C€”y<.F¦JepI„.NB^µyà˜‡V_UúÌ:‰2†Jhöp$ž‰4…ÕK5"ùºDÀÖÈ4ú q´ÁWú$t_}]°˜'¾'c½Åa7GÍž³!~Ôâ¸JÍn˜žIáÒ› )%„Tl“+äÃ)jÀ´ÊÆôÿØÊ¢ò|¥vy Æ€i0mûþ¤Vf›v:«¨@æü(žðÿ¢e-±Zͺ~×€û}¹…žG ãitR&~-ÉÛMa¹NG¡NçµXGØ£Òr-é’Îô¿Ï# 벊­m"t“¹ébò€Oô‚A ¼¯¸Š“ÌÿŸì¢²…²‹ã(ëA¼<Ù¦ˆJˆ“»KÊ 7‡ú¶Â?J#衵°ò³ÀÈ{jÎkrθAHÓôš)çóÔ¡Gë´Šƒ?Í2¶«sp¥0Ú ;ˆªí)¥Ñ„€õ¦3#ƒ-§(ªÈ˜Bìchå8©áé:¡+²Â.ÑÑø”»pjQ9KÎ$@ž+n ) ÅÓ4rØË<ÒŠÑHJϤ(J¶È0MœLèKê€ö&’Éú³É«4éB)âGE$ 52?ÒT¢/‰íÊRÔÍ&»é’F”ÓnqüÓ·¯"š>m‚*­¼iÀEMI*Œ£Î§ l°èêÏk–û) ‹´ ‚Q'ò²¬¤sº&¢\Gó$ž#(ÔÂÉv›†„;hMÔˆ¶obÎÂ×HV –ö„$wˈ’ÒÇíNöOΟ%¬öíÝÈÓé‹¶0„ 2(•Pwɱzºíöf©ŒšC!EˆÓ-–ÖR#•Æy:+lC•¡Ö½‡OÑok)(ÓÓ>­Ï0Óòæ€A÷ª<‘Dšú0”:³ÈIKü¬Çõ2wÜ’ê4øM›DûI “Ò(ŠëÊú\·wÕv~êïÚC!6yþ„¿€ ±þUçêGÊàLÔ;†!yõm#Ÿš>Å–€4-ÓÌheÏ¡ „%†-ÇÇY ŒZ4ÂgM&3ÃôºŸ&~'Or â¯Ð¾Á ··å˜öÑQþk_o̬*9—>zIh/£ù裼Û3Uk¦<ô}ëïGU2C¼`Ã^D¥”È$pHZ™.Šè¹Æ°{špl®'šÓˆ\¯ñN–vÎ?áG;oAÑ)ô–âKrƒ9nà6 HÊ#N4Š¡Í¾~µ@#OMí«òà”³E%$JÀÁø›X&ˆIcCÀŒ× 4C¤8­©ÒìþÞ@Ñü…€¹bG¼{"%nB!í"˲8„ðöäöeËwzíL£È±í ðAr]%“FÅ]Î’Y*1€ !Ý6±ÄÚ½Æ×Ÿã5^q­cCµ>ÂdN$®õ|?øïZIG.ʹbdlæ d‘P'ÆÈCÌ7#L­°“Æ+›tT(z2X.j—²Äa)Ãu }«‹pÈ]˜N%¢ç¢Y½-ΪY®÷¬ïÔ¬”Š}œO1Ь\C#éÞµÁü°eœ\6s~½cé1@#ùte’Q æW=Ø”Ý&‰À¢šDñX„<£|ÓÍö L4$2t¢>0€c³„#©Â8³1øVdù†’°N•´½9+~¢„ÕE?q©âzè&†¨Àé€W¬žÀ¨¹P†qbìOÈT&üâI® àFº(é߆ê¼D~5ŠäÛföP¦¤êHÔLV‚©”£1iâŠl¨‡ È‰š$ïÀþÇÀ ‘°æ¶ ²žOL- Pä½$veobjI”}iB´).GéL¼„À"itìŽFhì“ÂÑ­`ìÏH–‘Jˆúˆ 2(J âtit‚«Hf±Þ¹§¬ŠD¼¢Bx2¹"É.Ã2¨§IöÑ4ŠdðÊ) B¾¥i´Éd.S¨:÷®¹JTáó&2ê‚„úÑ…N®oPª´Ë*þqf‚ðôÊÊZ:-Ï4n„ÈÒcžWæC±ú!èÞ’Ï’qoBŠ(š)»%‡F~iìNITzɦÛ'@Ò¤*‡èú”Ê0킎e.jt nž&N ¬V‚îéš6b²¿JÈf"¾gÉâç.í õÇ{/­úí0µ/Í:ñf¥ e’aK¾ä ­Âò¼Ù`T‰Âß„à¹M/3ˆ`áQ2ðУ­Ó1ì:rv¢JKÉ'5ãº;m êtöòœ$² ;§—ITÌ‹`zgð)‡ö¨Ïø‚ç p ;Î6wÇÈI­zýï¼C°` Î\‰f@Û)DŽåˆzÇ­)  ƒ.Yn2’ñÔjL`ük¿=H‡‘zÍF–sØP3:áb"iZ¸/º§ð¤ƒÏë k1.Ššó³?²ÌL“N¡ÌRÄ0lzÒVy.î¨Å¥²`‡‘&‚Gw¬‚[-9B‡ÌyƒH¡Nhy.›¹dhìˆÔI§zæ’€Ð''²ÄI,ƒôütX†Žd èÓÌŽÈóRýè±C„:ëà!)4;£õ(Î >ãß+ '; À"°ê´¿&’tï”6-D?F|¢R€ÒH! >ž¯|•ÚzkØ¡s)3K¸S2†ÞŒ0Ep˳”¦bŽF¢¾d :i”ˆB¢iˆ_€2ºåÂRÁ‰Û$½¨¿Ê.Z H“æ@±“–u ¡°‘òf6GFeè=ª)gøòŽVá5<¶’ªR¿+‚ èà—'Éä=‰)!ÿ6‹aëÌÃN{2ö`•Þ"²U¦µëjïõNÙÂîåT¤’ 7ˆdŽUFjô€l°r+vÃzës5S¦jNü&d:‹j÷s<¾Güwª±UqÆr-MüÄ+”…’”‘êHë ºrœ*Oú!( ÖâÝE=Dí’!&ˆ#«ˆ ’KÄ?Ëk?bIÇ–¯aû@UïÓc ö^BV§BìõL2¥ðÓP`¦V.ÕhTtp&ÔI9 ¯¤Ñ_D䃧½6¸çcŽxÊæ‡„¨³’`§´"òÑE´‡2QÅßH@ØõM.é­ÒíµlÙÎÁ`A÷`'z“ë|„àd„½2, 9ëw4Ö¬œ°±zãây,ª45­b¢¶ŠE]lº¯6tâ˜Óé?zƳÀ’ã·bã¶±Œä€‚:óaûFS8¤ä©!Ân ?Ðm`†¤ŒQ?% :‡ógAgù à«ÖžüªN2†¿´KÓ TðÉ¿«vT‹þ²¨ P1 êüñáóAé0ߢO42Œ?j€en\•RÀ„u‹j$wvÒp=³AqžV}/ •=#Ùh°¡7Ôîb*$s¸ÏÏFùI¾®×*„*ï8pÛgÿÎI}Dmko—PÄöˆuÀÐôî!ø™QÄk3V±…:ߊe^E£ºfH€Ói¯£gN¢I-p(H%l•ü°ÕK‰øƒ Õ‚xÃ{p¿6•qo™´l¢`–)kôÞÔ´2FCH:‚ívÖ!qùéÿšr ‘äÈ}Ì2 k3ø`CÐ'C ‘€OÔxúB€Ä/a$$-Ï;h/?Õº¥‰¦b˜D~x”2”ÑȈ>‚ˆHGÝXz$9ð|‘ú#gç=j¥>‡÷âª)Da”o’ðN«ƒy=G aèIL:þLÊ2¤çܤŽ\ž+ªøÃ»!*ÁÅ3)}bˆ%²­ ¶òÓĩҹFS°"jœÉƒ¬–ìƒØn ˆ¥˜„ªŸìz¢wm FQvâà ‘Ò3Ü”È%Ý–“]DFj]º†Ž>šâÔÛ¸xzä|–7°'©¬8×ïýésóÂø`h02ù…!€(t0ÿ‰C¢€ ^$ÿ‹€_‘Ð~:üŠ?¤‘·ìž3ˆE$0@,‘ýÌ&èÌÎIŒÌ"Ùô|“¿epødÊ/Ä&9¼\ QÎæè…)T«Oª J ðû±P%Ò9$†a@®ØŸuˆtf!`®ÐåPÉ„f]]¦YãµÚTb%¥ÑðªÂþ´ÇåÓSæ»×jq+¾D'Q*ò}lŒß¡Ò†G;n[-v+¨l×Ü!›HŒN FsòKf /t£Ou•7…«±SÀ5˜–¡ÿCË#ÑúëÓ±®Ì8àiŽ£’aäœ UW@õg3Ñþsþa!¤wyÙô÷ÑóÉ_j1O!üÀ/º2ƒÊ(kb`»káøB*Òj‚" ž©"퓆­3@:¶l²IDûºŒ¬ˆ}E­ °$É;Ôë*/bu­‰³:í*-úé*êÞ‰F(ºÊ‡Bï‚J‹»«cb±Æ‘+˜ÄÂj¬@«Æ "pš( ñ&>i’„“´ÌȨh„ÍS:€§=ª |Û=ò›0Ûº)<<˜E§Óº /gòÐòÌíÔi%N'úô†;ðÀ 6Dqÿ5À(ÚÀµFͪ%E>ðñ) ´ÄÂÄ KÄ=ì{˜¼ òNî±ðqü M)Dä—MÓÍG!•z†~¦bº{Ø®ìüŠGà‡µñ»' €2 ¤“Í’z>ŒÚt¨˜CnQö¼ª+’¢¦¤òÈ/ËìM%,Õtù±/B`®ÖÇëÞÛ<ÑE9£ïM˜®ª*Ônÿ¨°ò,‹Ô ³~Ý ++%Ý­Â+…DK¸ã±æ¶7@§ÌM¼¢’ò/?W5¼B‡N*;ƒc Ùk,H‚]?;²æôQ‚? Œr€2擽Þ¢HÞRÑLN “ÓÌ$ÇMÇ óç©O/{‡: ÕÔ‡hÈegÕ ,±b „"“õÜXT².zî©tÈ~«± `h¯O²j{†U{ÓÃÍÄjzÎÊûqK³}(€qÞ"û²ô¤Î÷åÒTÙµoçê[W4¨ëæÕqš´òé¸röóilj-”>ªSÑ!³OÓeÔî<÷‘#ì|Wvhè•íxôGåÏk€oKÜq ¿+ÙÔJô¾³ÕƒBñn‡*’{UÖá®"ª@¸²Ú“"낤3cÍù@0\Ã×€ wç*±{o"M€Š»×:LXI9Oie=¦ PÍRÐWÏ)¬¾r:¤Lë5ë{ t}ÒSðƒ@&@ç„BˆÙÝwŠ‘A4ã†ÞÛê7£ùE;tŽAS`FuË5äF?‰tUmÅ¢}Ñ“…wÌIíÃòC!Ðwª)¹-ÈåÓÊ7ˆÄ]ú՜Ԟ£Kê RÄRB™hD1Lö þÌ¡…O¨µíÖ×[,‰Ç¸Ü¾Æ(çŒJUOýµÕ¢Y•¢Ø‡¬õôšã4|×+Ü+`ÇË^k–fÇsÄŒ{lƒDQc¢Ù K™»žw§0®–ºHYto/ÝT´ÀŸ:šÙ©Èd¸¬ÕCº@$fO „üás|Ò&½2Èã!>“¥PËC^þã JsîŽ&wöÛ‘l X°œã‘˜F•é^À.u&dòK‰ Jn ±ò©3m \J»bo”צÈ4D’M8îY].–ªfQä¥B´ÕÔh(es´ØüòìŸR6>1Ð>æì{™éækGÉŽ Û¤NzƒLÊBÙ ùÃvq,&ò>ÄÃè5ämU§#¡,¨chƒõ¤Oòd½€mG^¤v]RàùU‰ 7„‚.R>N¦t×O*Mƒ!ãöòää6dì)§“èI› Ý›ÃèÛ$ã–£É ™ZƒöE“1HùÝ&iˆ3©Cñ¯s-4“¥Ãm0ˆQÝf/ÃNcšûaM!rÍíÂ+ÆIì«Û‹$Ê• Øs•ýA•Ѳl [Î=i°‰É/¾V PÈëkA?H36™Ûƒ“¢D0îµû0À@Ù¸ºȱöÀ"Ó¯’Ç7èdÉçP x­ŽÎÛD(ZCÚK—sÕÙLEÐ-œ ±§–ú?[Ùfˆ¶#ÀøñKu8nXæOs˜~“Å«L.M¤7 ÑTâI±,@ ê[HmŽÉ *á|Ôi“µ¤óúë*ûgdõsÙš±ƒ´"ó8ÿÄvËŸÚ‚³2ÞãØ3 áˆÿpŽYèRˆ kê ý•¡¦ÉXqÝ]¦ÔÍŨ&¶ølý…2g7ýŽ ƒS:4ûËèkK‰%Ç´zÖJÓÕ~e§ˆîHs5ôQ÷³•ˆy©+ú{³øþPWP°±Ššø’DüέeÒ´·µÙâ8´ãâV/vf©/ÔJË¢ÈíQNoòã Eœ$Š¿w³;-ÈLW40ޱ£9'ÛzGÓl¶”¾Ú¬¼±V":¤ þ¸ §£È•»j¶ä/º­¥k-Ý#“h™ÂCsÒSûnv WʨÁ$’p'#²çgVš«wÐØQ©CK/al¶^QñµyË0Ë–ž²Âö¸~iî÷Éú4,¹oV*@ÀÚ®3۷ܤUSâGJ¸e剶c‰ Átáè6Ì”‚S÷ËCäCÙIþîM€cò„á"óÊ*³’¢Ë³6sÔzh…`œrnѱ’ 3çºóO4GÐx²®u·V'jê‰Ø¶žu²ï9>šVY7ªk¡ia¶-›œÍfݶÄä:–OÃZòHŠÜ³Ì,G%,y°=–Ù£^Ù*>·÷£Ø#ó*Ò K^ã¦iiÄŠ›|Òl6È(?/:‘]_<÷µ—ñ3è:{± í¶ðÿ^Ä»$ÔØŸ–F±…¸>¯^'ÛÙu䊼§@ÇÚ$A V <ñ)½‘FM$í ¼™b£€Ò‡9eÏ—ªÈsÔPýlËw«)ºM+ãÝj<ó7»C#sÓ±ï³áXblùºÙ…©e ž¶ý°q I„¹º\Ü.‹ü=WÖÔñò|났»þÓ¤™Sf“€¹‰¶5ú7ј*l ƒ/Ãr$z{ŽJíµºqˆ“¼(ã½K´5N°ºV¸ú¾“š qÕ™qVÁôì²k}­²•úÊ  6ãÉ;çáÎ$Ѽ³bÿ‚>)¿… s]9ü ™k‡úX%}«a["ûŸ?ëÄ ë˜Qi’àˆ5ᤫ°Pô¹ }¢8¡‘ZÐ7ó½'«#ˆØ¶[ÿ´´%ˆ±=#Ö8\¡0®1õƒÅ»s<>8Û¶½I…„:3°‰óÁ$‘!“C9½C%Àëª 2Í7Ó  óûZ3 1 ’53+«Q¾£*ÂJ°ZÅ 821ÚTI‡ð¶tSŒyˆ"a~êG.SUÁ¸’?º¨{Æ A;žØôµ© (ê7[:ÅúÏ)X'a¶xÍ1s£/‰ ³È5±”"Júº3")ô;À-£‡¢‡2Âǧ»QsK"–8!öŠé?.¬–*w/ð—“ޏxŒ‹dc h}®¤J &Ãî»ëî–SêŸÊøF‹ä©ñ2ÁA0¥ƒfzØCð¨­#xÃZÆ?HÓ¼þGP{º²T» 4›ß#¤3Ř«³H´ƒ˜1 ¢½LFsͼk!Ä H±‹8¦äP¦[—ÁyË/Z»Ž<0‹ô›€Ç®x¡¿-óæêT“Ãþ) ¬0™ö Ñ¶Â(»ÑTI«,_%ûÝ) Œéo:"…“À®*禘Fi‹ ©ÙªëÓ¿¨Œ›cñ¼›y>Ü•5a`,L Ç:oBvIȹ¢æ8ñÉ e6ú“BBËL,š‰©ÃÃ!,¤:¶áÞœ³³ Ú~¦Áø&[¾‘Zëµòæ"ëKKÁ$1%@´Q£2´*¡©»X.KÞ=D@Dr*ËK¾ª\‚8Âx·†K|.á¶!¼3ó܇Ñ# ±*=7,ë ÒòÂs£,‘J‹ÝÄä<ɵCaH"eÊ>ªÛÇÙ¼53 "›¼* Gc5˜ ô+H/*#‹bçϪê•û¾®ª µ4ÍÌ“ {q‘C,a{aLÁ‰£*ËÂÑ¢‹ÆÒv7D±TÇÙÁÃë”OAß®2gIlü.°‰?73VÉÿ;ˆMå)LD‰q69ÃÎGãï>´¬kUÍ”F;ÁIJ²ÉÁ¬£•ºÙí‘zrK ÷ÅpšÙ/Çzð€ã‹ˆ¥.ÍÉs¸üåÌ+9Œz9ŠˆÇÊ»U®ÉX?œAÓ?3-á/ª ÎÇÕ´8µ4æÇ  +‰s¾¬!»P“½h¶@£R¾+$ÊÂ\$ŽaoºX/Û­´È“òãRûÍ •ûqÄIiËåūݔ'{í‘{=ªR<ê*¨šZH&¬´À²SÄIí›ð:záHdA:úÆ>#‰¡šË)üUÆ…c)Ì Å|i ôNÚ˱RÖÊ™P ©¶ |ÜÕ¤•½ÙæÂ¸ó!¹i±3h ‰EAÓ $ð"«©‡âóÅì*σ©r°%¹´ïUº‡ÈˆJІR¸­Óž,ºgPñ. ‚ˆ3w)b©I/m4ŒK›×]R(;@*#5AIôTÖ€CÒ z~(ÕYˆVáUC:–+ǶÕ.5´ƒn,‰ž?ª1Ò#3Úæª9äWÇ™ °°;åL‘03ÑDQô* JSºÌÐô8˜ñöÒmDùÚ©]š«31´¡¾.d‘yõ)»;H¢Ð}vˆý¢ÙéÊIìDÙP=x}°!ñž”é×ð…´|K‘당½\¬ìÕ¸ax¡°!? [J”ƒÑYˆ˜°@(ŠFj÷¡í!˜Sð1|$Ø= ¬¤U3s#ª {zã`ì£`͹ÐpŸS Ò*ãÕ¯©‰RÛº”*$]ªg'šö³ìx[ó\eŠÑðîÇrÃÀQíÀ9©+)¯+³Ýä±B…*i+”y_¥Õ‘ÙÌ?Å}¶FM"Uà)eÙ€I±†(ûØ”D½» ´3²»ì–l—ÓÓìÄǽ#•Ò¸)Ð…\sUÒñÏ]YÉ‹‰[î­%2´ªG›…@É-E"zE`ˆ=™i¾ÕÜû`-#kâ´•DÞXk§<Â$«-ßÅ /¡cU”Q—ðΩø¯mªKú^Õñ±RÒ)údŸÌ=ˆRN§b¼–)Y”JÂyC:1{&r½A–Øî•™tÄФ;ë!ÍÛɪêŸ-™¡ìÎè°C4ÝŒP‘+U5sžF‰$(”{†›èhãµð>IYÐDBª•A¼¢`¬³ËÈ-¯´Á^¾‰ü´% Ò„èÜZLqáÔo] ¿>ú.0ÇÑœÁ‡Ñ.FlÊK£I[L”’ÕaŒ3™UJl>ŒÜÂ’0#W¡ÑîÜÝr²ÂešESéeKI%ƒá43Oá{E%3ÔëÉs­Ð H_të=%À¯óðL8^éöàÒÆ S¾Žèצ5}¸Ñ´ÄÌFáæºz pÇÏ«^Cò+¨Pô eÉ£©ƒD°”šÀa[]z›45)ç Ž !W$H‹f>X-˜Ž¸RgA š¬©ù%[©•‡ã^al.¤„Ð?õB$Y‡Ì¡ *­²¼V˜}¥é ®Â>fJ$Oª#Êu½ éô-‘e¢$$3n-%ýdc@¼Ú‹¯ð­2úÅõ06A`]äÈ .#—aLh,¤=•’¨')¶X-wÓrñÑÞ%Âb9Ï\uãü`l¹eúisÏ™Èå$FÌ‚GŸÊŸÛ²¬ÊÃ?h‹“aÕÅòxEÐQäÝÂ!Ü›~ÔDœ`(|ˆÎ3¢­&»)62jÜ"›†b ½–ÊÞÃ@éìä¸d+8Œ;èæ#"‡ô¼›¬ÀÞ{cÅ|«VÓÔðÿ|ˆf¤5Š‹(γpe>?€>™«P‰m€&¬ŸCf¼Õî€åµií1ÿ,és딣E!ª^”ÂV›ÀN«iɰ­)i Í^gF ;àœWî]<½JðlBX žT%Äì¹–u¢½WëK,"ÙðáÇôm¾ŽSÆÅ’VÂo’… KIÚ˜‰O(~'.ÂE´3Ä÷ ɤZ^,)kÃí¦v0ý¯›ÁøóX;EH(UÌ=çë¬ñæÀãÛföÔ{’ß°ž§µªÚò²¤{1Rl<R«(Û^±ª¤zçà‘ÚmS#æ[H”Ú^P”+£æ¬Xùä#¬¸àÛC.1ùš«»Þp¤·Ûä*5[m9Á hÇ)ÆSår*îˆKñË'/î.`nÅ9èæV»Üö%€:ÅñÂ.lŸ*UˆüÖ|¿õXæJŸ\%l†æd&‘Á­"žp¤¼WËðÿ»(®ò)É»éSÏÊÊmg*ÃÇ4ŽeC¦NY¯M0¨®›gUEdæ2?ONú}PÉ ˜eÅ0ÔC`d.çÕ:/·Kþp£§à?V} 4d¼Ùç¦ºŽ‘Žƒ0Ь:N¸·8Åâ´êí(Q/ÇEeó%qÅ+úÍ^y8ù—vúBÆòŸášÁ[Øœ}—µ&Šýî–Íh 4:7ÉÓê—!0ßâ¸÷=¿"ÜèZËžlUI•²‡åM‰{c–Ô$‹'WÄf«+¤Ó`ïj.,ï”'‚ËT”EնƳ½ ÕÉâ’¸Ã3èÞþàè~ÞDmÄ…šñÀ´¶ëíP¼k* òj%SJGÖNqZ^uµæjÏæ.2Ú%‡š®}0Ë1ˆúU|R-‘µü‹Á6>IJ®Þ¤„̃!2Y9Òš™vK£­Íï?¹2Hyo¯Aõ°½ÝzÞâÆO©%<œÞ? ûžŒ[`Ûb4%„2Pô3yYEî®I€†€).gåX»£F ËS<“”c€`A«Çé=Amcê÷È÷µ¹H}‰Ú×—w ŒÂÛ;eŽ8¸ÑA¹XýTÚ‰ëÃj9…×d5\{¹§cÆÙúHüAÔ&Ä7FÀQkÇÖðéÙˆ‡†¼.ïù¬#¦_äŸlT½Ûi¬Ÿ¦Ç ;OÖÙ;Lƒ{5ß¼ÓO'¬é%\vDÑÚ-Æ€`@8#ö „!P âþˆbQô( ƒ?_ñ¸@(úC €8Ûü '‘¿%RÔ©ù ‰@S8ìÌ.ŽÃ#²8d–q†IÀ‘I- 1ŠFd³Yœê;@†@£²év)6V_u¸¥ K†Wdï{$Ž…#ŠN`RÊp]mŒÆk i~!m£¿nvª¦6ŽÆfÒZÛîü˜D¨VG¼2m6°@±ó7ÎW ÌOcxé.ŸˆaAZ8Îiÿ|‘Éc3ðB)¯FæÓΞ@®Ï鵇a'Œçõ¹!ûâp¶,Ã*PTIÓÈk3)zy.ïÀRX,”$ë$îÎ(Q!·^K >Š•L‚ËÈx]eæŒä^1(þbY~ík<VÖÚF|!Šô7ÀŽîQÙZ=Ž ¶OPŒXÙõ9Æf<Š6,­yeHý5ŠIøÀë)Ì),¾y®,æ4^á"⨇÷…"S‰@iɱ^.A°Ll¥èEq–ç^@cç•mi1jF¢ø^6)O^ œæBÔÖD§†(0ò+[Vc”%ü‘MË— U*&É3Î9Ÿ°ÊÃÀJªå}VÙfJKÊôî#SMÍÚÇl„\Ó'ÁeCT Ú6VP•MË^R•l­=Á› £g.²²-“~Öt~h0VˆÌìÜ¥;B§ÿ®ñŒãïëMK ~çÞ¢pÄèYƒ²§ÆåfÍ=>®Çó¥cùÒ('_2ŠÞæ¹MzÏÖLf\‹6M#K3–ÕÆ²«Z°†[ otËÑ{Za’<,žÒœ3ïcF¬ø¤´ /ŒȪ-‰Þo%ƒkº,óûÄ…¶‡’aÊ’:ÜQ‘qvb"¢ÌIë§e†˜·´Ö¾_db}prîúË"O¾Ý˾*‡.¸ ^gÛÓݱIŸ=Gij093%Þbj¸ BΣ>xâïäÓeSí ß]Ó{q»M„ÎISrí‰üóòó™n]Ž 'F«Â6[š¨‘&m–œÄs«6=ÞâÕFæÍݰÈGÐå@§eú¤¼<’¿5öIHæ 2«¶$¸¶mŽYÃB4“xÀwi ÿ£LjˆÓgŽÌ¹ê–+Ž„0†J}ÎäéÃXðÅtiNÈEéø†/Ndâ@ZêBß ¸ãÈ&•áøSⶱʴsâÊhŠ0Ð:ÇâÖCà²Ìºk"lY€ |l&©Âè娭î^ðöfZã›ëŒðFüKP‘cvÀB@&#¬dŒ÷îÆ^+øEgwn@·ëv>þi\£B¶Ú'i–éÈ»f²ƒkì¼j Ä0Â*ŸMXÔþ©¸@$ÌWJzÛËwOZÕ*DlîÅ ŒêÊ#*èí ÂN[ª>?Px˜-öæj %KÜí×êDg-Ìœ |V¥"! ð”ìÝ K¸‹+ê’06/§Â5ŠÚÆŽ`ñÈfÕÇ”ä¾Ýñpî‚Ãé*ÐÐX™­\æîZõJÔ» Ný dT¤* ð%¾$,ÚãpÚ1‚JZê¼þâÖHTã°‰ fT·íªóæ´›‰ú°1~•d€0Îßà ƒñ ÇŒ¹èðMí’«ï®yé>ãpŸD dº‘1[n} cLgæyhdÆR"H¨Äq6ú‘oE*fÌžåò*Íp—¥Ú9âwkõ)P£¢Z­QîũާÏHÎB”Œ*ð(‚”c*"É+1ÿÎx·èê#P&pA'‘›%ž¹CN’uk¢ŸFCKÜk(^?N¼É2‘+Ð6b% ¤¬HNFÇ»‰¶·çd›òÓ)¦ù&ZÂIðMÐÔ¾°º“"A ®FæLÿ£YéºvEÊLðÊÇ0¢¾¦M ŠPͰ«ð£2ín•….èN'"dËs pº¨îèJíïÕ -z~K¾¨ñrÿ£Zêª!OƒøCQ -ê§%¯ì)ñ”lŠØ\žä FøðRƒÒ¬v¢DPg–òªÜý‹&¹Díѵ,“8 þ¶Õ‘4€Rh¸qæ†ñlC#0©æªŒéNÜÈÎeJ¢U( ¥Ñv«ó°DÜþR ÅU%â|dÝ7è.ñL¹&“&†iO,!öú¦xPQAgF &Žª/Ò†E1i"Ü‚ "ÁçC®Pµ3ÔZ 6áðİŒcoF¦í "ßh_Åâ4Ñi$ƒ’ÂsÞ­Òà¹íº…ãà°ô Ñ ¦Î†Ä•8ËíϾ©úkü1óªrý*ƒ,³ll®xý.,°3tpC£ æîÓ:BKŠ r4Å%0ô™@Sæ€'0HRè  #C¡æ~)¥Cb¢Äí%ÉwKÆ!BB Ë¡8lj힢ç@'ž‰â6#FΨ UF|«L¼+f>4Ézç†ä% ć$«~½ °Ïg³^—ò¢OoH£þò#?†_F¯POoØk‚@ãS™Ks)­Ï%u9åÚšbæäFª…-0âÈÊ~.ˆ¬q ÕƒXÜËòÌÒä §7‘W0ºÙu RRâŸ>†UpBK JZ”îÚð:í°;5ñEh¤S.Ž©0ªÁ%!„„Yî-ƒ_E//2ÄO×;ë.±F'%TÁT ZPÈnKMª«Mˆë)Ø0:ª1±)àøÝ¯ÍaÓ³"hœc±‡u´fѰ)â“£3Ä´qãViIPÉúät}L² S)±I*úJ\#âAV_,åYUi8«7Uäã„ÕŒnPƲªÑ–Jâr*>Te[S©Š%L«Ñø²u¸ç¶(ûÂbâ7¬rík‚¨.YUBd´Ežs ëcøNԱǗID‰³žÓÂ7Oöž5î9¬c 'éåepÐe$t¯ÆèðÊE¨eAäÜ‘¶Þ¥É{T-¯ô¯®õ^ÎI5 G&[/‚³\h@­C£ ö’EÑå#0q,Ï:²Lȇö´ëEéÖÔ§QÛwBF¡Á¶gÃMÆu’ŠóAõqï%qÀIrvÅ#Ø!PÚ«OqP¥àˆtÍF¿ †5(¡In?’<$Îʳ L„öYÜEIÔJÓî«M Ⱦñ÷n£1<ž¯û2·¾—ïð—r†’Ÿ^ÚªZHQÞÕñ6ÐíZ"6h&„RJŽž5t>Ÿ ÷îœâ(ÔHPÀä’.F1ΟÐ.W1ίÃ^%ůN”>¡ó4,˜‡íê?ð¡vh"I¦±ÊêÎSçJ,óP€D¼–³v Q*)l¸ˆ4F†¢²´íga3˜éduw p‡Wáö#&ð)ŒIJTdÑH’"G*KXk?‘å £v°bã#1r$•t¤²95+2‡ú?èU‚eÏŠ#+ŽÆ[U¶©?³˜$ª>ýе2,Í%ù œMÂS-Qk 8Âel› ݉ú_HÊ› ,Œ°X¢É_öÇ'$\…XxfÄì«åÚÈ „füÝ,í« åìÿm_ ,Ü£ò–4ÖÊ$ì''¨óQwû ô • ²ë3æVϺÓvD¥Îø\µÅ˜’V"AH”bU¸vWJ¿8–ÃKUA{+½kDHg ”§&ìG9¸ÎKk,{"ÒI¸B¸êxCQbNB@Ÿ®‰v“k.œüdwI¢)õ·uBù(噃†Öøc䌗·‰˜©d‰¸í4¢E˘Aó>u.jǘ°RQ;" ÁiCöøù½Õodí_ƒ÷0·d…Võ=×)BϽiúˆfq\r•`ê·™û¡™›t¿gâ!}©wkOºŸ¨Ïolíò_m‘®µšˆ!Š>šòu Áîïr4¨äŽ ç/E:lýE{vÅPˆîmUÊÏ3¼Pˆé$Ê’ÐHÕšGjgeb+”$¯Çz,ý·s6¦é„5—8û×M!‘<ê¢WL<—Ë9•e¨¸ÌÈZ:âgž·Ó*]•hÕìGwÑbõÌäcøä4Šz»ÒK6¼Å]h¤•9 lÜj*jº©f£:ó="—„»C01™ú‘È‹f|šd˜Í«’ë}‡®Ì'zûtŸ ŠÑƒahg’‹"ú¸ g*c£Îœ¢—oÐõ:¢ë ¦Å} v}hˆWy°ö›™´7qþ›âmqDŽ@5“QATgRÚ›Ê@ÖÃ'™q°yº€6.™üU6v [ƒq¡hÆF'Ji’+#å .i! Q~;g–vW¦‰‚ªR‹â;(‰ió¸V&Ž›æ>rÌ?ïØ©¹¬»›Ñ-ªUkRîÚX®L—×+cAñ [®cæ>´Ñ"¹âà—jç8óžäzCš¶úÅKú]pÝ»³øÙ•NÏ„´_Q%lùiwíi¾%ÌVb;­Ë½•ÏëŸssן ]•¸ƒ¼V*ˆÕÝ:Ï,ìñ¯b‹nxgesPU7õÌiú] æh£0:8on@:4þ¥´Y¦5DÏF]x?ì«%1^•È#yë‹ê`(³Æ_2U?<»×©fT¹‰-² óÝ®YÍ ÔÆ>üXÔ…ƒFý„­7“=÷†y%m ÷/Î0é¾úÔyƒí#æe¦ð|&Y¶›Žvæ:í—Uå tßÇP=1M[°Ý¤Ü/˜¾n4‡ç`“ùgøî:†‘v´·-dA;[¥‹yðåLë‚]Y Pq ¦üúŸŠX¶£uoÁ7Öhô$n¬(Rž.;r‘P»É+‰E(U½à¬sƒ •1ÎÈ"ÈgI¾ENFâR¤-d¥UÇv¥]´µ;g‹‡KãÞ¡óÿa¥“§˜pnø…þ™ÔzáîÛúy‚F©ß–1€ú{6âÜò‹è³÷|‘~éE¿©Qˆè^3¿•Ç<ÿ ãx†Êÿ—\´"·í’1烀OøÇÅ¿ƒA Tg?&ì h Áá8Sòþ‡B€`”!ûÅâ@,UûŒÇ¢QÄŽ†?!IT9ý'Žæ™diŠEa0¨ä ŸA_4½ ,„A óP"|–G(tÌö›>}Õã5˜”Î MÅe”9PY\G*³úìúŽV€47ÕÎOCŒÄ%’y”:Ò«¾ã5÷í*3}ª¤ôh8÷ÇIp0I<ä Þa[†j%o‰W ™¥õí¥žB´WØÍ¢}'ˆe ´ÛÛû-m¥Á㘧ýÞ!½Óc› T×mÃãSj[d76ƒË"7Õ/HëYÀ Ž ÒˆnaÖ;ñ}àÁé´8FÛ¥¼Ù¹Të+ú!±Â2t˜'B%ò(oà©6K‚$òPC@ÛŸé;´Ý)‹P¦¤©:¤×¿@J‚¤ï"J¹.h*XÆð|Œ¨o /ðRšé$ªlµ¾M¢±¾o¢›£¯DL‰;N²XÃGH;‡=Ì£ÎÀŒ»æ„%‹8ŽE@BÌ ê-.¨¼)"ªS)=R*Û9°’|ßn³×7:Lð¾¾1ºâÆl´˜ðÏŠž°IÈ:‡ÉL¢N±µÈTpé±ÄÜÝ«Sމ/ó!ÿ$²{•1Ǻ ¡©«ûf°¢ïÂ:ŸÏs;€ J|±žµ‚Ä•4MÒ2“¯ïª¶ù°°Š”ÃÌ3tB‡KçêàÊ0‘û$Ì´,úÒíU.30~T`*K%/òÐ!*ʼ•J¾ÉS ÐÉS¤„&Z¤¡Ï´®ŠÊçú‡bDlµÔ‹º+œ ª×€8¿Î5È=¤µ=ë)­¬1G4L³EaO–dåÁMqD¡ÏjB…T÷ä÷€ÆUe“È ­a¢²Œ¾ê¨ƒów«ûNˆäNÔ™„7®oLÌ[¾Ñ°Æd#H"J¿²ŽN#Ÿ¡èV2Û5hâG±¢‡X´¬©N;èµî…hú ’‚kx:Ó\qQ/Ž^v~J™j&%—„q*\Îb$±ž›å©Ùi¥ù¡Fx všî–h±ÜGͶ젗^#[!¨rOk]ûÒW¶/ʺ›Å§ÛÅ-Ib@VŠÜ€%霫ÆN~¾óv)]%¼ûØü‚.³E–áöÈ"yè«® 2›¬Ïú1Ùògå[ÇÍ*ªXò ±U\0Ž |ñPŠÒ$±8¥'²àþ^/y‹ò5½ D‰;Æ1„œÒcâØœóØtªL«¾€  ™¾d’µ²u Ÿ3²FPÑ!ñôGË¡dÅ•çJ×PR’bÆ{ ‡¾£(D„Ž-™©Fgê¿S"8H-ó(dÓ ëWSñä‡)0åÇê-'Äp½(5+œÈgM%÷5AIQñGe˜±¯ôv¥Ù,CQ°„!Ò›f$èŽEÓ*êγC…#õʉØ@Ž“â?¯üƒ»Àtˆ*T_Óˆ0òí"œ¢9i)óK"Ò¿ò‰ñðévé‡ìrë6–„I:Ù˜qB”€"¤XÊ¿}«I>¢2•ü*Låh¥%g Úÿ‹-ä°õ6Py©aÈ–z8hˆâ%L­‡²éäA „àŸ ÀŽ tÛhñM<‹¢4P NÇêT£ËfkQ3´aÖ“2AÇ̈/b‹2ŠJ¢%f[ÔenVL0 ³ùø•a™~—ΑDãlý§Õ †ý¶ËˆºË’Ò‘€ìD§P“+1«L\I0á¤A8¨ÆÌí(€›–¶MˆãSÒ³Fç󛕯2S;3lΚÅ! V…1>óëÄCS^£›çÔ•Ò{X‰æ±#2á=À” w]÷-˜”¯C³,Ì6Á™ÛYKëxü—D©AÞ•n¬©Úª—0øÙ[µU@ ¹Éijt÷G‘;^t!£´ÂéôHy÷Å]¸”FTácDhX…VBG ŠÌÅN%”YôÈ%ɵI¡óxÈ›¦9¦‡‘x)Zâ×ìˆ s9¨Ÿ ),¥ ñµÆ—˜•…ÌÀòñ¾Õ‰Fzð_W‹Üz¡4ËI•p‰ƒŸ "ªr>ç›y&~ €¥jÎO‹œ´-²;ÉHì¸E5”?ŠlÄsŒ‚]×J¢5rI@¢3tÐ…Ê<íÔ ÷ÁA¹.Aãq:V:Aó|W„,<Ξ0æ§Ì¾‰.—b “1€³9p{íÍø]¶â'¡#VvkDÍ÷ŽÔ9 `2a—/¿*åYÔÑ>Â9&5¤Hbq‚бvFÛ5EtóÝ-Ì¡ôå‘üˆÔá)Ö”ˆÕe{’yøü¿s„ÀKökJˆdwÚrC¸ç G µí–cC¤öã·¦;¥ÍÊÙZÃ×â‘¢‘¢ÊÉ…¤÷îJ /ô¡GZ…Os•=âÀ®u¶¢9ΧêNoÕ}CX{>Z"1©—+]“H_cÄr´NëIYJìKìoÊ/2:ÒåÁCì¤Ì<Æ#Ûm[,6ka-e Á^¿:#W<ûuav¿?À,—?§å‹²M™Ø˜S(Œ¼ |` *ë°Œ½XØÝTÑdм!ÑõŒàM)#cV‡ÎΧØ]f…ð¨Fë·Kž;tjž¥óö‡±ßvÔ¥SÈ|’Ä|e^תlôÓKœøw0ÊUâDôÒ#´‚´9â„jKDq©¥™\Í”•+RSôÊ4^Òô'+lÿî%J+í+w©k)0ª›s¶j^ãåý«?Ôí…õïž…"ŽL œÕÙ‰Š­äÕ"­8¸_2 b<ÁâÜl»á—ÕejoJqàoqUÙŒ*¥Ú™ElžbV±ã¤;Õ;↳ë:¾zlŸƒ# ë¹¢s¸µÚ,«¼B6=Š`ZbÀ ͪ’øÂYªñ¼ Ÿ˜«±J¢ûj‡ëø’Qæ+ê@º›ü41ý7\‰S¦Ù«ž Æ*kC/’Œ¯B ’³dŒí'ë¿€*œ‘Rõ¿á¦JŠ»¸ KzÊ„ Œ—BÕ)»lš š~‹J¬ ›kó³øŒŽ‘Ô#Ó˜%²ìB!Ç%Q-!ó¡ó (C€"jÓ6ÐÇD-&ÁR?Ɉœ+ê¿Y :!¡j4˜xŽ&’H‰¨Ž7¢¯°ÊJXøˆã•:XcÂ(ë,“–#IŽD ¬{é©A#BbŠèòËsA«%"2ÕBõ> ?µì"36##–’Ò!‹Ì¬\¤»S¸ùÄ´ƒþ‰;¡‘/*(µÀ¬·ƒ7:ç¾Cg™ì¤r[„Ÿ“~‡Ó CŒ ,LŸ”ž „=|ˆS©?”<D³Ð{±6ZŽ'hѦp‰¡“[<¤t›½¡2öG´Âð<£)`9øÃ¿Sž ±º ‰*+{ÀJ-- 4B!$¨á°Ç@¡*C «­Ã%7N@3kGÂʾº 3ñ!:ÙÄX’Ä|2»ì=³b³S$°}¦i>pï>› :ÃPÀ¹›ò|!`¡¤|”›f R´Á™% õ·~“XìJú™{( jéq4>Õ8|`šœ ƒxºË \!91F5X¾·y×FÃY¦ãòKÔ—8i§€ x˜3âØ&£˜¢4Á&tZ®a¢s& >Ÿ‘ÿ1³BˤCt£Eš6 ú<ÚJ:Ãý!æDªƒ ÃÊÀ@2+­ø¬µ‚Ÿª ™¢L‡>Ô~9[¾ÛdˆC†Šºýžd[’ÔæB£#Θ}‰`NʪD GzØÎ¥ÂíMaŸ9ä{½ÌÄ¥á±0ù“ÌFüE˜#Z)Äk´*; ·sZ1[$7‘ª7LÓȬl® 4)ÐËe!8Ý;‰}(B×K±¡Ä°šžú‘&(“¯Û³„ òãß­Ñ;ÚmtZ°A®ñ61Ù©Cø·”@Ò3û“ˆq•½Ûé‘ÜïCIç‹ú]ÄXË;A„V Ž;CbÇ®Ê"©Š ó)¡ %ú-êôÇZÉN:Æ2‹9§è¸" "Ý"´'A â>œ9™tE¾é%Ü÷2‘Gèòðê6tÒhA ¸ë(™tZ”rÅ/]#<¢Ó7&:|t§As‰Œ¥ KœÑë;Ít|$ÄO-¼C £ÆE],Ñ1¶#¾¸„MÒÒØJ‹BŠ‘ãÐH†¢o ‘Ô=àÛ<ðŒ±% H}šp¾ÌêÓD b–K ÓÉ)Ò9|ËTä› ÓÜ"“°JaNNñ9E,¯ØéVÅÖÅ‚íH²6KB73è´*W£Ù×C/Ä“ªž„ESZHsž­D£$^¾³?’cÆ](Ÿi¨›oŸkYL52j£"4 3sdË‚½‡%lÅÍáÔQÊm›àz£ BZ·ï*|dÕ“ì6Áó7üÔÔN#,45jµ;¾Scß–”=2³Õsƒs©Ñä(ä0M$I£a8R Wº|¹û—β§Ÿ2XÔ˜}JÛœI1ªÝ#2„%ÕX²ÃäÌ‹™NDU—½©ì¡{ð´4ëB[Ndn­ÃA;—E-XÑ'¨Æq§Pé/Ûæ¬Ê³µ:Ô"sC tÈš¼ùS¤Ã£ÐùȸÝFèϵ’™ÕAÏzØ43JaBMç;QÚ?êR5½1<ˆ5‰ú»…Ïγ^Ü;ßϼÛ[4ŽÜÑ‘@‘·±È8Âyª4lج€ ]’ˆ-aÈ+ﺄĔ-O„üɬ_6Â'>Ô®€$W:Á4Ñ‘UÔR¯3ïíà½R»Š“Ь‹¬«çRz'«“¶Ò„ä)sáÃt©&Ý:®… —ëò·ô¢À À¥ŒÞ{°L¾4-œ$Ê/<´8ÞÊšNš ´¼¿åÜúÕY!}Á$°—ÒÅ7c',jH!—@ÔKÀåø­Â¹£`‚¼s§«Å2EÙ¹´,{›+Z¨›œáRcµ£Cø»U7må’‘E•øá=HÍ}sHø à­ÝÃäæÊ[?âØZf˜=D,‹¸®rÞ¤HK=¡ÄZ‚¶Ú¦S ½ 20€3—‹„ЬdÊ|ïÍ“tTÂ^]¸ÅÑ íò2UÍ*£SòÕFÏ¡=¹D!º´ !H#þ9¼~¼a€ÝÛÜë´À$:N#¬¬Ûá }3Ö£Bi]"‚€5ÓE9ù“[§‰bª3@ÜðtRã,ò;¬[[Ö’f2¯\†ÙL±ãzc5=Ѧ(3;˜ð‘›±[u5e3’9—âPciÛ6ÂíPeÁ³dÆk†—Ñ*ü¥IàÔ‡âlÝ("\ÇEÐÁ(ÙœíYSÕä‚U¹ˆ”ªæAž7m¿Z” A*¬°&y Eã¼Mê¤oUõK…¯Ò芷dûÓã[ØQØ 4F®8Qò£. ºÛd®®*»OϪ$ ÷&ñ~_ùN¶–_å3Þ’`¶I ô–£¸·,’ÒõÅ)j»l>êûÏL§é—RübŸvE2»¸ÒôàÐÊG }-D ¾¨lj—¤Åå¯Rô‘Åñ:\þ Mçãb“ZS 'F¥è~MªâN­nC`†/}²Zƒ¹k9!Q5¡…y,R#9¶aJ&¨&AMŒu¦)Ú ½Ö‡Þb ’-)køæ éË ª<7  ´õzêO~k)~è‰å²¾EÚò—S²¼£Ké,±çÉé·.Õ~¼eàýMcÜ‚<êŽfRyÛÆ'Õ«ÁÖ3ßCCŸl^1ãî¶P~%jý¤~'`zšë´…3ŒÚYã :üN"OŒxM<.vÕC]™'B9Êõ°Ñ‡Ãá’dÛ±û °Ê75`;Œ‹§#Ðäˆfêœçivf—H½]ãQǬHLI=Å­ …ÿŒ>ÎiõL^L3&=¨ÚýDÄ‘Km”$õgVËq(IÉt%ß24×Å߆FSzš¡æ^‰&3JmßýylÛ¥"Å3ÆáîväÁÙÈ~³Æ+ËÛŸèÁ÷qlreÓ³ÿ@H7ç[×haô{‹™Åd¡ñ8ÈŸHÁ7a•Ìù·?¤9n7?Å/«ÂúàÃõ¼¾çíù4Gî½Îb;8ÆŒr4’[Ë#ÓâoLH.bÕSõéœ=– Öüdâ9‹›.>N³gU?ðmÜsZ µU$k^Uø¡»FÏEù ¸í4¡¤~2ÀÕ˜r3gÂ%¤ÍÉuû(¤xËË[×Ö/¾A§`O)×BŠ'AP£\Ú{E‡Ìƒ‰Í¯†E  üì€eÔ¤ÂæA­¦Ÿ…+`šEK­¶—7ÚÅÅÓßγ%UÑ¥µ.Þô<»·§!cˆõê†ÈÎV…Ë.Ž×ï?+U„¬É~-…! †wšB‹4TäçÑîh³+Ömž—0Þ¤oò\Ð>ÕÄ—híJbíUÏ·6]Ò+’š –a( _¼ðK²"u¡ÛfzŽ8YÞì)ÙçºAË$ý!ïæjØ)B{y$£m —Œï\ëµá>ƾƒ#´"'È•é+¦-Vöˆq­I^¦¹åµÔÅðH}: þ"r]×|T¬®Uü!ëM˜êŠ|l®)á…X;§¯_j%kÇ¿H«™\áaõ[5£. e1W•ÝÇîÖÝ€|0û#¿Šw‰r¢zLSãç8ÛSÌ]*y/.æ‹ÊS6Õj„œ}m‘lueh¿Ýpò`td¦Î0¸m.EdZÉúæ od+Gå1GptVa ‹ôÕÞFshU×ä‹Ñ³¡{¬cZLxÀˆA`Ðgì&†B À(€%?"Ð8 ÿŽ=cÀ¹qÿ‚¿¤Ñ—ܦ Æ`r(4Yù"…Já’gôqŠN$Q™d)õCƒ@èÐ)R3„Ó²)d7ŠS¦Yd²¯—Ç&Uº8‹H‘Yl¶;Õ›â’@¾ ŠX`ÓˆPõ)}Ð!•øäfô…RbÉÄ)2¸K.òlÉû8Œå"P¨£ç5pŠa€Sèæ*!R¶@ª¶©”Ê2ÖT`W E8Ð?ív\Z†úŠ`è0šÝf[™mqÐ\öÖÉN¤Ú˜¼ \ÌD-tàgg4ù¼S`±™üJÍe™O"pÂÛÁÀðsŒþY§n:֪ߺýÜ¿"Bº²´@ÖÙ¶‡ò¦³´  z“=ËÒb‹$Kâ@žp¸ ·hX7h0®hIñ¢‘ŒÁ§òý¬)£€Ž>l:Rð€‰cjë ¯úŒžÑû<Ð" ™ ÑT†û½(KŠ“!ï2ʹ‰¢릜@¨ã“+K2 ÷¤Ëã:Ž0s ôøË§ô΂ŰrÈ¢ Úò½E â†)Í«ñ¶3úÝ£)¬â½J(”Œä,̲5EéBR´%“X„©h)éLÑŽrr£Å dØ­rûÆ·iTʱ¼ôµ(J¶ÖPú Áά$b‘Ä‘2#+U"D¶ Ó#̾T‰Ú ÕWÑ)ñ= C<™Eb•D"Ì’ÚœE t6‚ ´ú9j"ª*‹C¶ ¼Ù#‘Ð-+e8ÏL§ü§]5:Ç 2à´S“{hæUŠÍK0GPЪ=à£ÀôªæÝÕ EŸG- ä:¾$S[žøúe,a  ›’Å´]×U裬 †»Ak øÛºHbëtÁ4-Ô¹²ÒëÔ¶Wth/ja`2™Z~>{ã nFÉYŒˆž@(‘¯™Äo䕦ÂM/gNˆ“G™J ¥6×zݶ&x0‰àÊJj-ó†ŽaêÞ|ú@,•&½V—lG@xVç–' dQ‡è±”z‰H5Ü„·çï?yçÐ Xí½F»¸.-Ó‡ ÒÌàòho=Àå ²ŒÙšxø­Þ…1’b-”Z6¼æ¡°{jò%`iweü²r6Byµ;}ïuîŠÜðï:ø›úÏckÕ™'È­Ó|I)ùÙ€}LW×ó &÷Ö/Žù Ï©˜½#ñìÀ”ãƒm7mXš‚"D°¾)BÔÀ3ºD®$¬ÆÀè‘ÚãRÄIf"…ªÛ@*1³7sä«@2ƒ$õ™¤ÐH¡»7p`ü½5Œ ybiH3RJã@~på2ÆxlZüPˆ0ˆ=ˆFBŽÙž\ ë2á A¬M¬± ’“”QÓÌG‡D¨6¶:ñ"sâ@gÑ÷¨“®~ÞÁ.zÏAö;'bZ[/(Ç‘ŸÎí×doIQ<ÉEÖ@›‘À¼1úX^Ä‘oœ›WSˆJ¶!(.?$‚K!»¶“…ÍõGf‚¾“#‰Õ÷¯ˆäl[á’Mhuú¨çúj$|ekÍ£?fGê»$œ´*£íî_®8(4FVvÜG™*Èã¦!†G´dý^±;kΚ‘i…:!å|-KÕGG*‘ñqšr±£6Œxá):ñCvŠÌ†.z¹šO$E’šñú$," nçDåÑ€DùÐz!L|"°½*_:â´)Øvo †èTâ+\…¯3]‘GÛH8Vu2‚(Ôe«ÉFiÓlà•ˆ%.ðÞ¬34ÃTí18Â>ÏRú~è¸Hà#1eÉd@­êEȹ!äxÑs.¥9ë›P@•ñ–¹$[W!a¬È•7ÃÆ|Vš%Rˆ¢i •™rÑB·Ë9ï)(æB« tÚn¶Õòñ›Ã*ˆ–_Í¡uŒû–Î[ˆ£K»kº>À‘aX Jb3_œ[@°Ç+ôÕâÃÚɾ¹aTÈ927s-ïé k/k>Azv2c¶Š&õXFU!ÕÅB5 Ñh*s’«ªtø Q€‘ݼ7Å9‘_Še™”|ÃØ±j‹“ÓH™¢Y‘ý¡/„¤ì€ÅBQìu¶¨åëkå*—ÇLujý‘׳ÍwÈ”ôŽN}ÔÖ£'GTËœ™–g°vÞÑ,±†Ö<2ŽÂ?*UÿçÑ!â¢ÌšàÂóxXɺFYÜIŽß"}¯ŠÔn‘f^ki”â5tá ô†IÍ”|c ¢4t$Õ͈uaöé1>!=ÆPWI–âðmTÉ §mÕâý"ǹL}zHyÙ_]öv¬{Íþ¾yÆ y®?p<ßËÖõ°ž€ªHÇö‹ÊyÿÈNšË\ÝZ¶xùrõeì¹Vi~M|øåro{ÖøÎ8ýLD‘opK¨vâÂrŒ¦ÌÌíTëgö\˼æÇ ‘ˆÄ$É–j!¡MH^kØn"Rmïß` ”㦡.4éK°? ºž ¢Ý;Ëžà.Œñï~äDúœ!I–ÞËÜh Ò3Bpý)6zËdR‹Úœé®‰æDÔ¥n'2†ó Ný0D#о§ ´à'´ôdB•Ž’êbÖkf©†–äN€vêŒUpj ИáBøˆ ¸ê° ùÍ„s ÒÖÐ¥"öëÐ…ö@ &ÄÌ(xC¯VkèðÐpèå{GH”£E†%0ضà 61 YÊ ©®6.¨Ý†‚ébÌko ðgèÕðh ³ m:ñôç-$ä‚!/¥g@ö  ßH¯O×bÔˆö³DPа¯Aøô‹dl F_ ÏÇøHFMf²w„öª@ù  (Ö©bÊîðË øvüÉ  )—áþ¬PÅ%%òóުξ“+•M{2[krH&Ö(¸Mq:ØT‘ æä*X……þW,àÑoêÍ£<¶(ˆ˜þ<ÑÞ쯛F'¬r¶I[ÊâDg€W¦²{ %L(d:4’ˆÏPQÏVNÌk0· ʧ¬gÇŸSDgLnÅ“¼{¨Wȹ  Ç²Ü8R1§lý*zêÞÏík® ÜéÔ賑"âD h¥d.cW4ôU'!@ÎŽ{F%Ò2FŒ¢ò’oŽ>ˆŸ+G!?lÖù âï÷Æ#0¡-àådCdC$^vàr2Œ$‡,è>á` YµN‚×C . ö(}Ì:ðlÊ·3,Ýì„,ËTä ½R%rbh]/Á=ÎÏt‡N3L'ßôÚ"Ê ÌtK%î>„s‘g :wg?ôTìí’nˆä`҈ăfÇî/‘ © „^i$aïø«R|FW+HR"—"…’Ð~N‚Áð‹òq,Ÿ¬ïEb̾¢ ?è¾N‚ uJ­„Ö|ÐïQ6*À ꣩N'*7kÈiâáäeâ0išT–~ŒèäÚ‚þn)- ç2¶¼\‘Yª0Î!w3z±Dô“¶Ðz`M6î5ÿu(ˆÁÄ #t®¤R«ãèx£&,¡lìBluý;ÏÝJa1'YlÛX÷§*TáJ®Žâ.OqÅ^ù2(mÊbÞÅñÖ‹”ІwV«í›òD.U)²Ô¤†H*l/‡Éj$È$Ò"ö±ˆËc'n.ÐA)§XçÕ0·wrl¶(†émÄÆsôúS’HŸ€q2Sƒ¦Ñxb®Ž)«µë šd]‰‡H›D†ê~¾}ì((t=2Bù¥Á­Ë ß-“§¯½;±¦fGDZFãcjãèG™»NË]šr0â!•âÝ]‰­V8€ížÍŠÈ­ºek{#hý:}U°æ°Ç´¡ôgŒ¦3ÈË´Ù±®uz…Å&P!›®Ç×Ó¾§qFÒû·KÄtðõr±Óþ[uüù¢Ê %® vÖÄÞþfèû¾¸¢SáÀ«G?άÒF–Ü»ãIÐ?pG '®Á£N†- ùÛâì~nañË[~åÂæƒÎõl#“i¨D>êéèâƒO–yr&Fämø€Üú‡N=ÞØLipMK¾M;>¹ê`ü‘ W­›¨‘bËVµ¡$y0ví.Î’_ó¯Ìò7àU1i&~žŒ¥Éxš®y¸%µ7EdKvéÔ](_öP9¿þOªr¹Öf>!D*›Ù¤Ýû2Ê¢&—ò’‰KBÀÀP þ…B!Øp! Do¨´Caш¤hŒ@ßðçì"I“GãQ€D½í1ÌâϨDRLD¦ ™ôJ0û¡I! LŠE7ˆI(O¸¤ŽIQÑ tXÔRMI£’xd2Ž„Â£ b%N€•¸sòá$¶UöXÜI&’YàÕøÄ¢“ZçW˜tJ¬¬Aß8Ûƒòç-‚Û1¯˜ôR!™f±F¶~¿ œá`rjƒü ©“i¯ 5ܼA ¶E¢ ±¿¯ZXt#7t R6ô”3pþ°ñ´ñ)` IO‚ã÷PxÆ?wÇÅ-‹g š™È]H+ÅpcUÈ?R5ç©|ßý«…6| îìþœi2$¶$Œ{Nó¦®f“? óNÓ¹mkB ¨HÃ6½½¨s ~§s+*¶5ˆÊ®ˆD(t ë)  6€lþ;jZ·¬ÚšÁ²@š¶1hc*Ì" «^<ì|‡8ë㸠h¢H‰$‰xDZðªÍ'ª±JÄþ8ÐÄ£D€@¦ÃÇÛ6ó¹Ñ›ê…&¨ÂØÈ€Oûs$©œ½0 *:‚És»Zã»(PBK*Šºõ< Ü‚¢Œ‰<ó2(¦³h¤PÇÐàÄÊ #˜æ(ˆ<Ò…C4T|´ÑBóËBƒÇÉS…Ëo›ÔÍ«¨”xFê è¢TD®¤ÀU¨LEmVOK²BɧhS6Œ<§Å¹4 ¶¦¹éZ ¦ÕN:HÍÌý½WOgëŒê¶5ÃxEÉ‚¼ «ÀóµwLF¢u¢"–³ó$Kb0˜žØ=ú±(¡ïˆ@à- ˆö{çŸíÜôý L >‘]¶XÞª.>OqK—uWKr[ÁQS3[›RÌ Õ3OÑtÊÛ6RQÙªêé®Ë^-¨ÕÍ?€"yßÚ„t÷cÇúk`€zQ•8ù–¶[¨‚émä•£•€ŽK(ÆÕjÀ©\Ђ‘sc´{j©A¹³®¸Bo5kJiÌ“\³j,„RH>«»è6ñ¢=iM¢Ÿ—ÊÇɇå­lmÑÃX¢Äæ3g¯NͤҜW€TÃæéeZyÌLm„­=“•Ó}ºÍsÅÝ3ÖcD­+Obã7v{ž®» úù wæU"IjîbúcçõŸÃŒ¯I·crÞ¸ã^›" pϱÔWTûšû`ËÞ¹FÇíÕ™û‘ì*–s.ô‰;§>?IÔ8‡½¾°fzžsf]o¨8bÒåbwÉ9 —G{³Û ®5úœ’$µ‰"F.)™0Ö\FŒz"9îá·¬ôeÎK>d9•$r,fØÉt$Éq•#z”ô qÍj§G\â™Ðm/åi6„Ø?“„S`dùÒ7§"÷ ‚!Ì,‘F2šÍ 2¥Ñ2µÿâaêoÕz?ªsÞ"[\ÌŽ"—è–í ô+!=s÷bÂSy:IpɌâgƱ‰oƒñÁ­7'€¤]§%"šnÙ‰j6‘Ö±ÖªðÕyÈ]è¹x®¢0¶ *í3r &.D‰È±ßdL´¥7âyäŠWŠL©Oà3We c€¦JÜ–c‘4(Ö=µdMYS˜ähš’`;]ënv/¸‰¦´0‡]}$‰ŽÇÒeÄH"LЦ£0™¥ZD> ‚""LåãüÈdÉÚd’%nèbS*[ð|„3Õ ?Ý‹HBL1Ý2VuaÔkOLmGÙÂŽ•_™çxƒÓEˆ’ؤ9Ì–G(© –)T~Ht:· JpÊ™4§vjç£5&U£— ÿz1q%ëS žÈ!­PÎõ¬­ƒ*¥d«‘]³Õ¥¼dzDHUJQõÖòáŠÑŠàt˜Èò^|¡¦©>˜¼“md±ÁºK“`ÓdÜ-,Ñ´‰VcCí N/N%°gR Å!ާ¥|>Ò\‰.Á±Ö¸‘5À+Uf)á·Ö•YÜlœ¢j¨ÄÏôEÈddDMF2µ…§3…&k>‚„H;4.Åd·ëb‘M¶EÈòš•ÐŒÖhvÈõXöVqÎá:d§=ùТé% v [šHfAe*]PõºÅy?{WLG™Í¼Æ“âjYÌ.®·$‚­cž[õð dÖKSWJÉ"Öt‹]Ò~Y}t’WíJ3. i •݃¢j[!‘…ò¤UÜÙ+¤°¶Î¼>ØžÓo‰˜¹—PÖÌòÃ4[̨)TŒYg…Ò[û¸6þ=˜ºä‘/!Ë-\€ [@¥['šÒš¤MLGÉf¦®œŒTfôÄdŽ’ZÈ<ÌÁŒLUg Ê¯œ"¥ïŽÖÕí`©_›€ÿ¨XÊ‹5ˤ¾’œ‘kpIHªkŸ®µH[!ÓSÏ©å‡ø ~)r-ë>šuÍä_eô‡1\ UÆ.FµÚë_ší›DXN1N*<¦‹ &×/UÛ©Î<òù<튤՜ÌŠi?8ão¸©KLTÃ~·½¬J£}9›³‡@7¥0YtÖa®÷Gt…ÉoþF |)5)•çëÞ´^›±ècÿ/bó2\ò¤Ûs¦ô[•ÀŒO¶<.Ù*¬Ç‡òKj¦>_GÔ}6rIÚÍ õpì­7DôÈå%-³Š_¹ÙZWðmžMªÕŠêeß¹ÕDÆÞ3`H ®×8ÛȰ£%匬Š:5Ó:ÈqùÒåž%zK…­õ[¸—ø~½:òI´«úTâ´yEY3Ò"ì5æžé±Øë ËoêrÁ»»•$ƒ ôƒñ+ÈÏeµ(ŒI·xóÇøœ9µdE¬–E§Ì€m>>3Oì´DꄤE­BhLmÖ”®¶ï*nÎ…1:Tê°™È1ɲ³á–; ×®)h,#· P~>©›Óá £©š³òž1E¯ša1>Rÿž’¬¿ú$+³© Þ•RN¢y²ªC$¡¾-Zö;H¸2á6»™7¢?7së·zs0iÃò‹º6Љ©l Âzʰݹ2‰¹$¢°1R4<Ú‹& C6ã÷´KÀJœ ‚á4«Æ!\%¹_’ .(0©<#Å/, *Av¢3Ä”Ø~+ÜÀ Ì7ð®Ž3ù“¬!›,=§ËŸ*B­IÐ![ ÑÆŠkf@ÌCN•`ã )l0²¥¥ÁÀKûÂÈBiB!ªUÁC2KxžƒÍȶ8û¬–Q2ñÞ’šr”3‘?áí!Ñ" 2„ xã˜Éø’›]Šœ#Ó•œ½B¡¸[ Hò(ã´Èƒ§ÊC80" ›ú(4A&Æ9›Ÿ8g¨ó²ÃäG{YÅ὘cÏ k÷ŒK3»Ô©³Åˆó¿€@Á8@ð´¶ów<~ xŠ Ø¶ªØ9€ÔÀK9›1¨Š9A¼¾{„Aú5¸Ä¸Áú¥ÑÒHá²¥ÃcQˆ¹“ì¤rª!ýŸëù*¤JÆk·¯Ö·1÷€<ÃT…>øð1œr¯Ë»#[F 3âøÍ‡œ¤Æ¬:éÁKw& ì·ó(I”1¯ì€ “92h×Ó°¶ËóÆñ=Ó("ªÀ€ +î$¯ÅbLœª 8äg7Zú1*—y™¬ŽJŽ;Ü Û.œ¿K™zì_»1 9k!˜”4'ÄÌCÙ‰#lJ ;œ 6ºwĬ¨!C43ìñt¶œ$ˆÑÝ6+ÅÍc¯G½¨›À¢£º ÂÕ(ºU óÆj].Ç‘ÈǸ~Éøµ ›2rÖ*!¦›qk($ÌBA¦.±®CËï‹ ò‹bÒµÉYC³ªŽL¢ £„-ó¶‡ô~²¶LXòÚB|Ëœ«svRbŸ´›õ1Ø!¬é»‘†"ÙÈO ðíJ¬5€0±Sš¬±sŽÓ¸©›°ÑL‰1žš³X ƒ-òÄ«‹ZVbÓMH™Šê²ÑbíÁ¼¹ªéÖ¨Ô3TpT» «è¤B+Ë0ÍÆÚ„Ž;ɹÒÒú>¡ª] 9Ï.k)JaÛÀõ }¬‡ã°Žz1UŠ$¡¬´H}'3yÖ:¸Èêl9Ùí4Œ:CQa¬¨¾ðã&˜ѲÌD“9™ù"aÙÖŒ5°²Þ•a8ŸÛ°£êžZaÛ7™¤Ší¬ ›yl«˜ª:‹T<—›R>°}®„qŽe¦¿1 …Ö£í¢,\ϼ£‰œH4«@¶ZQ™DtÇ:ý3ŠÈ%ÇÇØ8͘«ºœlö8+ààšÇÕ¼ÇJ?’Ut§Ö§5Tê^Èaôû Å ˆŒ½p~˜êRªr‘«ps/$Ì)ú¤:éË=–Þã!ž4™³pÆCa;¬-gŠh¦’™ŒÞßât‹1s:ëàרHùÎ!Ì¢ôoHš +ߨ}±¹»„ýQ)¦Õ*È*%Ì/\kˆ,·Ûh£!+ËÕ][èæFU-µ¾«7©K‰‰Ô3\Ë Ð-õW’èÁ¼fTçÄåÅ*Íw™]é*Ó^Ù–™%”¤&þ&RAÒ ‘4J×½—Õ8´·Ë¸ÑþÔác<+A‹>¡“k»© Z’*–ÁŒÝšóSX~ÕE àRuÕ­•¨"šî:ǵè„5ÌŒ8\‡’]XÐ=“ª&*Ö_ªÆYOcôÅd¾< Õõºˆv"&{®« }1üª×‘Õ }[·©ÈÆdÊáP *ý–ê¥ä]µ’E#ò‰5»è”9f¾LŸ «r¿CŽÌk¡ê³êm/0…2ðšÜ"‘Fí?BÓ©Fnl82 Þf=ΞÓ*Œèiή©N<&ž"q«gðÕž`ƒÜp}“Óh³Z©aç±ûÒ³ =Ö±ð©7óÇNÆ*¦ b±ìÆÌ,í“\h\¢0ÑSš£&K´ß¹]-¥6ùtΓE™L ƒ¿[욬Žà6ÝckÀkÚ }}AÛ•Oå'Gά4æ…¶¾ˆÈŠˆY"aâjK95Á•´âÜvÇ \Å$O±zfÞL§ ¦xÇÞPÑ5~˜Ì¡­+£éÀ‰yÞ—¤ÒÇ7£Nk)å'ýÝå|¨¢|¢PXD¢¦(dG?ó•4€ÖÆâxäÐ=•PÕv€4š_Ráqå>á›}&Šþâ½Ö¢Í61°Tr£ª3ó”µ0õ'ν’ÃyÒJ%˜ˆaé–Á)éüTãê¬ÃS€b Ñ„ºPžž4‡õÙÔ*Ÿ±ä€ œÊRg˘¦€wD è™˜HüˆÄ~Æ|.yˆÃ5bÝfQ™eí5¯)äòg½òvÑȲ×ÔÆnJ$ ÅÍH®áV±®/Oc£8®Þ¥GÊ[>öXäƒB™I‰IJ<8CŠÞW­eVµAÄ‹G5¹p?œáB^(‹#]¡s®»‹›ì³yìn!ªT#½1û½Õ"Ä®­VÅ?·vP—õOo"¥¥4ù9{áÆö´®½ÃñûV=ßL•˜l!ÆÒoAÚÅ(÷Pi¬ i´îC¤÷FѶ±`‹'‹ƒ¦ý“—Ev"á®>’shóx5V êB¬ì8þ>4e,iìæ)ÖˆF¾ßæ_A ¤!l¯œØæXК¹_èÝèçzÒröy†k,[qçÚ¾šaßFEBž«àÁJm´4© Æ×~,ÔVt†€ò‰X-k8A˜O±‰k²á'ÍânW•ž©=C™v¹“.:ÇÒŠjm¢>í =±½N”´ Æõ¸³R ?*!3gáİ2®(̵ˋ‘×[.MÌW<ãËIáUpÆ‹5K¡'Yâ ¸Õà“9Ìú2+ô³lœÿ‘ (çáæ òÄm®z…ø±î¯¢õýÓ üt}£j|ŸŠòbEb>q¬¸Å÷Ï›‹c°Í;Äé;îÔò' u#ÍòíY®2§pÚžÞˆ1ˆðiœòˆµñ|Ý’Ê7HÒ!ÚÆnà€o¹lAÃnÛm¢)ŸÚ‡T¸€? @$ÿÂ`° .ƒÄbP'ô8ŒC‘°vûA ñ·ävL†DbÑd20ŠKâ2@,Ö#ŠHŸò¸8}?’IÔ7팤Kà´gÕ6†ˆÌ ôi¼ M?‚Î PÉ4¾5˜ËãšÔ2 &™ÆâÓù{âÝ }Éã¶(Ì&_M}>oTù¨¤ÿ­?¢2iÌ[ ’I¨ÕÈíÂ]ŸÊ`ôº,’-p‚ÓâØðÂè£Q¤ÐÍ  §ÔE©PLüš –ˆdõ\?Õ€$€å2›rÜ";ÀER%ǃ×lpH¥¢§EågdPzz|ËÁ=¹3×½O¸Oä×¥›S×aº÷¨eöÿ”~Ë!à …öIlŒQ¯ºûWª.º€.ž’=è"úã'oB:ù.ñê ÆÞ; zL’!À¹ˆÄ޼ñ ˆ¨Ìû„¯¯LC¨É#J~¼Í;¶í›Žø4HêúŸÅ¨â:ê%Péüá¯óF„È/;$¾©³e>i{É'ÈdG'ÈL“Æ h9Ò»@ "ŠŸ¬-JÍ5 Ë޶ޤGŒª7¹ÇúHêJgò^§¡‰ü*È'È£°êBÈòà$Š‹–/ø²'lü¨²"_= HŠû+ L[æÜ##):hrÔ® @.# ý$¢ÉÒŒÔÐ)õdêÑô¤ˆÚA‘T$䣪2žŠMàhà<¬Ä('åHIt¤V Cgò~·S»¸;`MžN)}ñ1¥¶°D#õ 3ÈÄ.Ü@£Fãôg¶–jZ^ØôV$8 ÂC˜2&­Eq›>äHšÁÿW ¸ÙÿŒ'ÍÜ(½fssû«Xª+­‚Ú·i°ê ^ñ:Rá©î$W/3}l‡ÜÓ£Ÿ÷ú)>¸‘"‹ÚŽ}³&º5ê¶šk­0òNG¤W %“¼ˆ)ïݸ•pû§ÕZ H§Ë>Bä@”}’ø)îÆƒä€KÅ×ML²FXÚÜT„døüpà+l"9äŠ(|ãR£"€WÜÀúÈ ‚¯`ÚUÉüû¶ö7LDVb¾Qk\¦¼»MKœF*Yz'â0Ùˆù *í<7&†«‹éx$Œ¥¶IÕ@ûDc²ÔôÌKéP ŒÔ|œÀ;3î©!½b$g 󆙣Ì?] ýN%¤’—$VŠ˜ëg̺sN¼Þ24W¦¡´RÐÑR/F$þ30‚–ROvl$ù¤¶¼Š’üTAkÀ~$DTÄbíO){GTR\‹ùØ?DÕß:Ôή–Œ}tÅ=Á¤GØ@˜ ÑAÉ &DÔh\ò¡4ÈÚ22"zðK£$&±G½Ôàß[¥’ªIS‘…ZR!z™…ŠòÅwÔ™ 1[†Š;±îSÐÑAŠ1Tê¢- cc‰ !~H +-Ž$ „ÑLP¦ÈÛ8ŒAü³°=&®nDP¾ªèê=˜dof01#i gˆ®:¸~ëâzÄ%Ù$›’ðE‹Á UÅܦ°C;!l’­)W2@£‰ƒiLK’&Å%„\tÈ©<±g2¢²Jd²Q½Ó€nP(;úiB2âàQ„:ˆÆ|¥a<Üa 22­³3dAbå Og¨@€ŠôŸ±ü8¿ÎAx‘LÓµUvÁ âkÍ…ïÄòÃWZÉs„ýˆ9p ’ÍÌ •f²:¹þ‰ä•H„Qª’bŸVYÌ?¦`®åp|ߓ㕦œ¿ÐöÔ_Ø$Ì•N²K€DrÞƒ^"'a÷£Ï$:•ŒnWå(·èÌ‹i!ÈÒZÕMk!sôƒ”÷D|cYp„¸88æ“NvÈùwS¡ü4­Á}—(!éÁøihÛj¯ÍvRj¨­¤˜=±ñ˜Ⱦ”¥pÚ<ÒôÃËtÝ)Îî˼ÐÜ|¯qKè¡6ásh”•‰­Ê¹Ý*\ÍÊ¿vtu» «*Ü,^4úa²9|¸ïûjA”’ '˜2Sh\Î¹í¸Œ‚ 8GÜQ½ÔfþÅRH«ˆaØ‚tü½EYß z= ÕÖvSPa—'ì‚7gjI¥µé¼ Þ€Fß*U†Ð2¿8;Nü‘›^nQt;êØÈ ;r/÷¤¯ÓyYkÚžNª7&&£3i( ™8éáJè„Îc»GraûrñT“õusÂÙCF«lˆŽ °4¾T_]ﻄKÍÎX« _ò9¡K­`9_²ju4./8¶Vþг¨; Ú¹ÂâRÖ‘bAI¸MkJ™Üåé5§@&T›Y·®íi ´HFE;;–KÅNtľô“§ÁTîlð†»* ÿHçTÖy RÁ³SQ“1Ýh\uR^ÉMer¤t °ˆÁåÓèH&†N]±6iG²ý Ú!bó2_›9J5»Š+뮳¢ë’˜fh½·½u–ÛMoÛÆi àûrÃæŸA÷qsÚ ‘ÈÅi.Æ‹(Ñ-/ì6º†½ˆlH ’%§ànUrÆ(tÛNYÍ4žî¾Ì–EüŒE¢­1–ÔæÊ@íÓm«J/6i?˹õzŠªí¥Gza„ÖœlÎô‘MsrT’YË1Ôû1·lEq‘ÆÓ…íBµ{rò*3Š«AÚ9´Ûá¸skZ§ºÜ‹€ïMTìY…™ ”¤Í 9>,}·f¥g»ŠL’ŒÄ:ñ>q0‡Zô’,Yz6–6ðK#R=ž­vV2Áôòšqúѽ'`ûhùÇkë§ß”¼ÎRé`?´‘ÑW‰g8">Û£Ã7ðß8›/;iäåÐÔálpAÜ\CžD[!|ñÿÎW'&Àû{}œ”3Ôäž+“ùˆÙÃ@ ëÐߤ¹E¬çà«âÐ\šsO€[4D¸=‡ïUW"|“ïÆÆÒ_ïnŒh¢¨í¼vDž`‡´ç䲊nÉ~&¨’´aö†:+,?ÇpÉ«~“Š`M¼j°|-únäìÉÐéˈ£)@D+ò¹ í¨@©ŠïÀØKÄhjÊgLtÔK0áiœ!ˆ4#d f®ozý‹X¡ „L0=aòÃf¼¢ÏL´LO Êå:0ž¤Ã2‹ÍÀ¥íˆˆ ˜@"ô7"~–ɪ†n¢@ÊËæŒ¾I&”‹#JfoN„ÐûlŸ lÊ’¢ú:†Ì«©Œ(ËúAþ/®ØÊr©GÒm(p\ev"мËͪüg¸žM.f#ˆêáúRPy‰Æ€#üO£>«b|çˆLž¦ÆHFúiªÈ è8íbHlj¯šíÆÔs†„ãäúÁÄBóƒJéIÆ:ŠÜåb7ÆÌ§„t"h"ð¨ pÓiÆ(Æ‚ò†ÍP|¨ªP7/&§Ð Ë/r,LúJ†vÞQ(tÉœ~pÌš‡ÅïÂzDuŒ²N#€Ê#aª­,¶ìqqNª{ÍM&x‡„„pbþzƒä–ÖêxŽ"è. Z{Çö`UÅ /Gz¹§8ßëX"…Lâ‰:Z*I1Ï1xHPÚêʇhj`¤Òà@j¬doñP¶Ì _NÈòëòâj2‰-æþIfãBèÐ)øR{/†m‹ ‚Ä"1ø¶®7,5 ÊÔ¥É)åÛ À´æâ#pXzï´ÛŽ]q}ÑTë÷12´*`¾I*vðRßiDk†ßB®hƒ£Ý/‚šÀIm®”!útx›M™pP ¥0)dBeQi'mìNb_ódok$ä”M€ü+Ï$ _+›C€ÌíA‡|fd€…\AÑg*ãªnϱ Dž¾(m#1v°r¦$Å\9Þ…öÚOÆìrŒ ܰcàºbZ:-‘ ’,†¼‰)¡’£vËŠ`pf2žM+Щä"…\b‹4,ˆ€BZ<-ÚIäò9²‰ÏFÊxh" ›ó,’Ô•”Í©LÑÁøÜÏA&¦I¬û±â’¦ª…jè'ðxÜ“kV"Ƈª/ΣÐDµÂ*®t`'G > .î²ÊèîŒftLŒÅ(¾´'°®fÄÁý>,/L ͼ„0œ’ˆBº.Þ<ñm„„^h·ìH¿&«Iˆ¤,HK‰D¡L¿ ütÍ®ªÖë"›óIÌ/¢j»æ·J‚ËŃ4Œœ; ’äq¢(h~hn\°b#éàInº(ƒJì ÇVþ¬7i+D‚Šå"‹!‰8‰¿à ¹ë0kËy 9O(­'DGk3jÚ€ˆ«#êsóW3„’Øh–°ñ 4knÕe/ÍC9º¥ Bj0³Í:/ä_æIå ðî._L§3†lŒ¶|÷”ÆÏnK ÆéÓ!´qlEl¼×O®(q.‹Âµ Z#ð ­¼Y*A4(ô°pŽÐ*ôæ3šÌfPc¤c‰Cëh"+¼•ÚÜ"tð”,¶aøì òÒ¯HaÓn{2âÔ'PGŠ “¿)//-°:.7ði1$ƒïd¹21¢@ÜÌ”¥õ%õf½‰¬ÓTåØþL_¯ÍB…(ÃiÑ3¨eqÒå"U¢~uÏRâÊÒñ#3Òäì¦Y4TiN-HÑ-OOдã¨'ñŒŽ‘TÏÂN*sO žîàkò'%ó̼` ÈKTvr|3ÇHÀQŒÁ èt’’î{æò¶ƒ8ÑKpÉx„Æ”°ôuM¯@̽:JÓUâšh)lЧÀ/ú<õï3¾‘þÔ0º}6À w‰ ®Paú¢ˆ ^äN4j¶ÄfÝvÙ/Æ8õvývd5*l¶Nª VãuµCR]¬.æÐ"œF– EÿhC]k#k4¾¡u{àŒv`ÚâÌš—$Ò$ɾÅB‡>Kԥ宅V¹î &´@ˆ“Éb›Mï~Š7‰sÜ"EÚhtÔÕìø S[ýst)±VpÔº¸4ÂeÖ.ÍHovˆlz„\m[h¯ì—ˆš8üOëg7…sOM4„¿"^ãìˆ125-{g’†óèâ×§c°0Îg„ˆ-Ü–ékRájRçÏbžK¬&•F·¶å7ô·[Šûv¡%TŒýRµDU;˜iiCÎA èR®:6Е£3£°I-Uˆ«€{Õ>upÌ7ü­3Òôª©GÇŠ¯-*¡pzK°XRŽ’Èì ü#ªô™Ô.ŠõN-Ï`/‚¶Æ¼½&{‚µA*lÇFsø§©ì¤Qb²C'jR‹Nò£R/©l]¬›Mè,¼V‚°ªçKÐd.|þTß5¤âˆ*õ ²,úÅ’$‹{yt’6â„-ÃJQ4„×rÙ÷C'8‡m­î”PÖwjÒàí(æk90¤ÄÓfÕtå\•ô…æÄIô) Uœ²'í'ÐqOË-nx̼¬A‚ž/¿rã}˜Ž–’ŒÑLµÃ`o4Z(Î#µiY1ð¤µòÞ¬±‘ÏŽº ùm3+ ì(²?RWÒ×\0SžÇD‘ÇÔëwm:0È‚¿¯Ê†93—u('R?HÏ•‚J^š‚52Ç'éDflÅ¢„5̶ׇ7¦¯NTÊLì«Ö{©¶èm/Ë“/V/N_c`–Çjz’»LåÈÄVãw¬´êNŸƒ®|ŒtêPýnÖo@ê‰zg›š´úp@³Ôß+í̇ðˆÅ\‚à¤âN›æ‚~RpWh!#‰vWÿ±: hÛt¥X€t8Ü"žÆ0~‡'|Fhe46K›´…„5¸$ñž¯œƒˆåˆ‚.†|êž[R|az‚ø[!³Ç±£â7Žs®•›|vyQƒö'™÷û‡·u2ëÓöƒbAŒy2R—ŠéÐv¦ìiH~¶D‰´gwé7`Ì™ZçÀÑ»˜Ðô„ñ1ÄVIe’püëY¿išÖ­"×ùÿ]v®¥îD4ø•h’˜¾ÐŸª/(j0ñ:£Â'F&ºd°²K³KkŸwߣºpè79B.CTY½YNjËTñ+<79Ç[9 ''k¾•‚•„F#nÚBaõ:سÊgšj9ݺÛJ^ñ!¯É©¤„2 E‹í5èÇf$‰ð™…4¯ 5µnqˆž)´VžÑ9šTª¿N€§5ÚwÅ×'Û]Q»;S©·´ñ¬Üé.LñÁóªµWóƒT­”½GhÍ–Nü3Ÿ¥º­^¢Å m¦‹›‘©K£{È1ÜI  ¶ãƒk“ ˜„'ÎwQRu„¥õ\*`—pQä—¶­³A‹"Ô’(©Z²2â™Ûæ‡ä`ƒãÓÕå£(À¡N¹¶l‰Ý[´Ì"Pú•š£¼M'DT3î0ßå ˜ Ñ](ÉO¼HÁ±/×7Ph `ªçŒ8WVgqÈ–q&µg¥räÃsO|ëIÙšÆKjЖt’”YNÝÛ¾9CΡþyó/4£°Úذûй£€"0­C±È¦­\ÀC©ÞNÃbMLx·Ó€rvæX þ ÉÄ’`z‹ž"þ‰¼ußbw\¬u §}|JÎñkÒÚýUˆËßÇU€õß3ÝÓ¹|RýÌñ„#q —;áKeŽÕøü¼œãü"†!>‚‘=¹:³7b®wGw±©äþd6‹0„-0›û£âõÜÜuv°õ½hœ.X¯Ò#i —-Âã>]bà¿«CÚíϸþUœþ‚¶¦rÓ•8$Ž¢!›•B¡÷•O¬ˆ%(°Ru5*öÖ‘û‹Y :š£”¿)úðñJõ ²O Pžã¨ÇVÖ3 ˜Ùv¦ÍF&¯±C„ûÞcüg•šüýï€ÛÓ6:‡ãX Jj¥™Áá!õC”ޤ—rû U9‘F2Dò$Ë›ø9i:­Ã¨û Ó:ýZ“ÖšóüÛÐ7Áš.<ÿ‹¥°O]¯±¿Ud­=„ @ ûAàp  Ãâ”NC¡ñXl&!‡€äH8I Š¿%8œ&@Àâ1(+ö! Œ?ârðBQ=~D%²¸T.„Чpøä< M¤HŸÑ 4'@Mæs8M4 :¡€"o›j*‰ClÒª%ÿh‰Of`{“êé\}Ýë‘;£ê[-ŠÚf py(šÐí4Œ=²+kãí0Ùí¦¿_N"RÚ”/K×ârÜœJ¾ÓfßÔ}$%(¯Ìáµê¤K/U‡Ìä€[ýžw}ÅtÀi6rOÞ¯uÉl&g¸Ü¢sÝP—CÀëà¼îÎß·˜•tð9gSÆÒ²¶ÏM‚Í ê€-{¼Çc¶ÏÌ8¼}óãùî.Ë»4‡·'¬ ¹ï"È%«òÁíórþ ƒ¢jâé6lJÖ†·Êãž«ˆkäÏ3Î fÑ¥H„"’+‘\à¸Ï˜;Gë} )¨ƒs% Ój̯ r²µkcPÔ$éBf¤%­Ì,9à; ~/м†ÁMCü¹*k,Œ êã€Ó7ÉšZ™«‰šÖÏ"k‚½ÎdË2)¯’zŠÂr‚HË¢ª ´ˆD(z÷(„–¶@à‚ÀòzA6¸»Ø•4L2<õÃ(zßFi’ „ t¯¢ÒÍLó îkÑKKÐ/J©J®¢Õ”z䬠ªúuNÇò Á¾ÓUxÖ!“Ò÷¢mô>»·,¢î¾T:öéºpm†³/(•¸ìv~ÍÊœ³Tµ‹|ù<+2*½¸5‹"KuÁú„·Ð;ó»Ì…³Éërù6ªš­S©CßIØ2Õ‚ÇH“rŪAýE¡•¨ÏV+Únð!øõ¥{?ê&ÜÛL&AdS5›ÌÀ5šÞ®ø I/"œäº_/Ìjß3ÊC@‰Sí2u4 ¶à²ÁüŸH:T†·)꬞ÚÅéÜÙK¼ÅgºúÚú&xëé+jÔàL*ú¼m0ßb«qøë½[Jºrô4”>N •ž½o[íóFZ~ç¿ó6 ²µŠ¿pø ™Á7Èá·ÔéˆcVp4™¼€ÛiÌ §Ù¾™w°ê” nEv¦3Ê¥•¡Ýh,‘"wàå\z”}1XÀ—°¨RIe@ …žöã IÓ.%LdÔ1pޱ‹<Ñ+«`ê 2êTe±©’DLÉ™=êùz±“ìÇ×ã+ˆà üw.{ÑMCd(ë¬w×L *¥rB"$| HK®4…¦`[±9JIcH‚«š±Pr†ž¾hiŒðÙ‘†žó<‚•,lŽ*¡ô½£¦Dß›‚§3Æb+*B¦©Vð73ÌÀ´µÙNìFaÃôû™Êƒg,“y±e䪗¾í[zrëe±ÂBÌ㬕„34‘V9ˆ¹  :U«òšKMóe1Ž^?ÂI8§¤P ê2‘wri$†¢ô¶;B’Ù TkŠ›Í2w‘Õ’?§›í„`‰¨v2ÂÐ9 kÙR¥ibiå*H-qË›å—D^Ò-.äLà ×Än¦Òß1æ¬Âî¾Ï —0šcUH›Sᦠ?ÂhØ(¡\zò&æÓ:NƒC­*¥h€HYœ£ÁR²ÊY u0OÈüH{RxĈ¾Bf«ƒU“xôÙ•râŸ0^`ºxšMáá +ˆLéÎXö×jš °…1“Å`¥yR¦-¤ÒøÛk#Vµ N}”Õpcƒ/y¯7È*ðü©@s’Þ»ˆAI·Q¡ß³'²Ðú+ŠÒb+eKVñž¦]Ôª±"¶´þ5Ë«-ܼ_B¥ €5üMš‹¿o ® ÂÆª[N%¥hXA÷I'©bo¶$ê.” LsÀzà+r¥"殃ìÜÊèËAˆU=– À.MËÜ@%µ6¢SVMËK MÍíÌRTÚ\‹EŽÕ÷Àkl•›¡U4ÄàÙ”8Îà ʆùË©âñ‘‘¦+•5 |¶¯ytk˜žŸ¯ÒV#ñY"778èŠÛ ÑxSXƒ½r ì"l¾Ž•áXÈßvUn0d0 ér{ùÄ­ºi2;Äi§^8m4e—.ÿiÉo%M ʼi°|jȨÄ; ¥\KU1ïA?´¥¦V?e¸\—SuËãÛ}¨$%ÉÄ'‡Þ°F¦-/\ä9lMÿÊÍáÊɲ4Þ¶×±¡F-yž×a@§ áCPj4ðîOB ªWÜr]³.ä#\@ëë(¹çy5Å#­î±—Ò¥ÞÙ©KMª¬à1ã^Gˆd¾§pX•í3ß5ÕC&fÊÞãi_”a¬uÁ²“ZÀš³sñ{Æ=–(áü㉵B¶–Åcíä-- Ý"²Zäÿ6àtNÑgÝŽ$úñg¸¦Š'¤?Ü¡è º>€<ÊI ž=yÉj‡-‚qÔ†œšk5/HC*t&æ.ÝY z0€R&õŠÌZŸ«E]€*â:t‘˱>=‹I{©$^˜¨H:43¢Têœ6u\—¹”ùN†Å²I4ARöˆ«ƒí¤í4É:úûæU¯m¤ôPnšÅ½¤š‚f„íe¶x· †:Þ‚ësÔÄ;ÐËa¸å*ÚcÞKõׇ¼,åÐa^WìÕ8fõ$ÉÇã$)°ßY9.Kñwa¯qâÓP[J¥ëåï­’¯gתꂨ¤CøúÀµo1kâÁí­²^‹§îíô¬^±ÉƒÖ{u ²Å&™®8{Y‘Øi¾€#AÒŸ3&B”ª° *¢Ñ;#ƒ‡á¾º ï#&®™¤Ÿ3I¹IÁ8±}¶y‘:@ º=®ê;£²ò¼Ù¼x´‹1H ™"3‹ºt.jº®»ë¿û ꦞëȧòU¢Á—:ú“0ãú"ûæ›ë|8°‹ê¶Ûí>ŠH¨KÕ€#)Ã.«+ù±¹S—ª“4ø|(h±J S³ƒàŠ W YqC ³S徺Aú¯ )+ éø­‘â,8Ô0d$à ҈‚[c¶8±¢û@8-,Нú꥘z9Ñ‹¡ŠÄ«®‰ ÷—{I3!Ä0ãk£A׋£²ÝŸ2ׯ«A BªÌ¹}œºÒ!Ó\%„¹â#°¨;4d@‘<ÂØ¦›š7±5°ÄÑñÊìž±“ù‹»ï«[‰;s}?óK°ÎŽFë%BˆO ¨šäÉó+°4òoÆõ8¼®OdZ•Û¶\ÙØÚ 8›ìE 8²ü>|C€B@Q…™EŸ¶áÄQp~‰»Ò”a«8+ÌLÜeÌ’´Ûß¹Y"Ùƒ“Gô}ÏkKËÊ L‘MÊ4E` ÛyÛJ¬ªiμ7 ×!KX[b•u87s ýAÓü”& ¿ÔešÙÄU³ÅH$‹ÛqÒËÐLš ÉËQqP }ÌÔé®3ø’ÊlÆ€##+ï¤üc9¯¬aÕHrFcç(¥Ç»;«&Úìq˜«ßÐ…[1QÒÎH}G‘¨<¼Z¢V2I¤1ñáŒT³]|T›"/¨3 Æ’’Qýñ/Uä§ÊÐ3òÃ6ñC5·cŸÜcPL¬ÌE,ÙsXÛX¶ÅcUzg.\$ ëU¡ÀÈ…?Ú‹‹MÒµ©0àÝžÃÃ…±¼šˆÏ:ÈÃQ’1]°å+…ðËv¥2ÿ®Kb @®Iь۵ ´œ#k΢mÚ’Eû=)Ê@P7¤ÇZŸ\É/oUÄ{‹c³¨–Ó¬R‡Óz« RÑœ–ßMYí«¶þ½x¹B8¦Ë;,º©¥Uò’$t¬Ð’Sæ=ÙŠÁ!–+ýnœÚ-\¼"XäBÛ œ¶:„™» 00d?­²È×ô$¨í8 ,ÜI0‚rÖº.%25•C§Áp¨EB“Lݺ ¤)1¢A¼ AœµcƒJÓŠ)Ì•,{êàéåÃm º½eSÞRÕ©úD€5{5kï I¥¹¦ÏFU×üû×všl0Ÿ2vÆë§¡âr lQ)3GP3ß`ÆJÑFPÃO`ûSUB€ž€vw4ˆ:yà›`ø|éw ¢Æ‚£xÏOYT·ý5Êb@µ¡ˆ²WM6³öíè(£jÍØ‰!“åW)×Iƒ:¯ IS­ã¿*>ð¹’¾8ª4’±…¼ÁŠB=Ý¢r;¥¹ÿ½é…) »E‚$ 5›S"J&·¨Ü¢ø›¾ÜåSVðõž[Û-M¤E|+8òÈÙ•þh*¼J$¯1Ò–!›‹’rÀ3IÇkÌZ³¾­æŽè»°gH†Zä÷ÒjU>K„En-hbëb•ÞÒÃÂÖshF§Žü†s>EÒ\žNµ›–G×ÒŸ¥ª3OËÜÑ­‹‘fȺZx ÓDaÓÞV>}Ãdî½Wý—ŒLªâ&›/¼ÊßkzŸp¢â©Sxj1í"ª;]Èê-hä±c|òä°ú1©¬S©°¥2ýŸÒê(ÏH\÷-»ÉH®O5Xí^ˬ›Ì¡¤!¹Úõè[AÞ^@º/áó[_\®6hEñÄIŒnÃç¼Â‹MæëkËߨÚjIæšæTÃqÔÖö;ï…’Ü&Û"åU o ͬÀŠ+˜™˜}±yû»ÕiiÌmÖƒŽšÆBÝqêf’îÓßèiê Ø”ã_=×A‘‰íp;Ðä©·(Ê[ ˜ÂOLº"½íkjÍŸ6ìAµëpövA­©Ñ˜Šé`Ä#•LÍÌM³že,¸nôB =ì¨WX~¢|ký‘_k ܋˞:ÈÓ…ÑÖ,ÉÕèÀÐÒ…¤Ýã4ãYÕ/Õk¥ú7¨÷Ú¶ù({é,d@ ƒU]:æÆ+*?–ÊN]^9MCHt›ñÞýÚjÊÿ‰j/„ 1ŒÁŠò>È9ž¼RÉóV£u¢!›á5ŠO.¸D8ÄnSV®·"Í/‹Ý9»ZLMT%ßP ¿¬Úš/ø™Å0±¾Í5%å45H–¼Átvš³8ÑÒˆJCsez;?¦,䛟3MËzš³Òõæ\8]B ¬jÌy—Kú)£Æj«lëlqìÌ•&D³[Œ¿ò’ŠxJà €@úU¹T±-i8”>@JŶ#JÑ´!XÙk)Œ@…-Ïdð0âÝš65ʼ÷’‘*lv¡âŠiºüT&ããGtx¾E“ xé÷¬ s¦Kõ0¬ž$ùF€5àOè  „aOø`  ¿bP`ò- Å"ˆÄIû$QˆD”’B$ ,bA‚?¤ˆ¤Yù%Îbä2MŒLbX„ä û¤H&ÒYÆK6¡B58„nH)¹lú…Lᕹt:)D…Z*³Êð! Á#ÓiÕ]ŽIcÓðb« ¶Éf1è¤RÄÿ¸_ðòmó£X8)ŒiºÄ&Ùp21­Ûá÷ú3ßLÔO_ùàD~À?í‘Éõ·ÖLui´SCi„S¡~&n{g¯Á¶ïª5ÒEx¸¿±”$CˆØkç»:´sŒÿÝꮲ¸uâQ [q—Ïdÿ×?¿äø0I.føüa´`|N ì¯H“D$ªÛvÓê2¦£ÐCâŒ>ʪl îHòJZ@mø˜®«¬&‰;1 ž„? š¢Êà cÛ¯ $˜¨Ê2bï°°¨ï¨©Ò­SXä ›³-у†8I3*‚GH"@å·k¬S$Q’Lè¶kS⺩è³(é!ˆ£fëÈŽÌÔ‚B)²È†:òàzÏ[¾ë¹oЦÒc"ƒ0ðԚǠ@¤.¬d¼Æ;«»ç4ò«*ˆ.°C–ñ¼±xN@”›—Ÿ ELˆ+s"T‡.©ƒ,±© L#ÃPº«s)øŒVoéúå¨Ðãc?H“ -bJmrøø°éŒ1aQó­¢&½¡³Êhó®­¤¹íqÖnû—Üg´üÆ(ϪD­¼í[à…(Õj$ç—?*'-œ(¬ ã3¤®]fê2°ÄX›Žì‘‚^` mzÄé<¿Úü0÷Æ+2 Í"Ìyó3ãr„à‘½“él§),Þ[Î#Ç·s$J2[cd¾,•ôÖ ÞE—cèR¶ëÞ7ríI¤J(£"š‹J1[ÿ“RŒ“{Ò…ã…æ¨FE"ÍÚ å£ ´¦ ˜šs­°¶ÃÙg!Øä˜ŠE:¯ e#U€MòîØº Qj­¯Œzqˆô#KjÌëÝĶ(ô=¾SÈ‚=h[xBA-?(5“F¡³oKTgê™]…µRdÀ)H²ÚŸŠËÉÝêCsW£4%:¾òЬÎéå>B9å2 ŒCÎŒgϤWŽØO­fµgO•„r.ÏdXFžœÁWX~"•sO/ å“$H¥\.»¤3Û'*ÚbÃб‡NcýÅ#ðýˆ’ `¦ÜÝ„¢¼N‹ÎzË완HUØ0mÀº¸ÁèáaÝȧäfÈãô„Q>™‡ªÎ© wJ…$—&.´@·!ÅB±",ºÚ‰&#b"*2„HÁ»z0ȉ!…üDšRWLðØ 8ňü° Š°×^òQl¥Ãg ¬H+¢ ˆ.ÅT¡Ùˆ|`E´¢Ñ¹û.n´<è®ÍŽÔ,-Õ¬´˜÷"ù @nlÿ6§›I!ˆE/C¢VG`¸ÿ†dat’M$Â^zæDǵvCû iK,¿»7¾C4xiL!Ð…¾£ªÿi§àÖG‡pwVcÃ1ŒäžÇj¦D‚{Ñœ®Dtºðà„ƒCÒ`# äËÉé^R¾m˜Åâ„Zr>.¤Q‘>p ‚ZSpS5/³w„¤‰7p µ+9:C– 9oQ¥²§ðH™Jps¹ÉØÐ¥!*=‡‘ö&Õ0áì¬{ÍôŸ¬ý9Z(9qÝ +4À”Ôs3ÂD›'\€ÐÁÝyJÖ2tBJI7iÊŸÃÉ=(¬ïvT”’Ð!öËè„ÿŽØ~¤yÞúÜÔ™'å_N¹øMÜŒ‹4’e<ÁÿʬoX µI¸‚9G'l8QQÅ7(j>/ÜŒ µ6Hr–¥ƒê¶•6åSȳrLí„"”¼_òñc…â~¤¢¯‹ã¤™Pª:¨cvd–Œ&ÆÕþÐxÞ¿áA7h¤ëšÆDþ‘™udJÍ«MÍbíCkÝ3øœðý„U¼~¿—\Àm¹;ꂪ0ÀTŠ62‘«É¨šC­¦eå©CZúUVÙ6m&`€)ö~é 4´Ð·þAŸóÀæJ£fþ–ÛRmí”Ô0Ë[wME™šU%_›r)i€QWí=Cú2”X +Nø„Vú†¥Ò.KÎjç졤Gdë<-ç4€" äÔVD‚ßZÛ—ó[HÁü˜¯¼_‹èÜŒåŠU$ˆ›=²sOÙ||Èúš´åq®6sŒƒ9Â!’u³_8,(›çãIi—`ž­µ’jŒ=…kE𦘪+ð›ŠßëŸôCSžOªà‘üd¡FòIW ¹Xa õ|‘ê5¾7"iÍìB,ËDœ¹"IŠ€×M}é¨Hbé¡2;²G†Æ¦ }Å!ÖÉ'®¸·y{ûO< f¯mïÀË?1¥ñ×P¨šJæ±Hçð|;jˆ ÑÑ46+d$1LØô#öºï‚n²éïÚâè{BrI öFr%tr'¥Âþ÷iAÚ­›̲üM8~O]«è5ÄØm°Th*ì!ôný†Œ ë(ª6¶âÚëÄ/[›j?nì5Æ~ÊQØ6ìˆãŒ²Ï@ßq@Eþ»bL`.Ô¶•Ïs. ‚J:èÇj¸ÿ„ã% ˆfÌ¡ªôþ ã®2LWÑ ¢x ,Â(¾ƒ$„MÑ" ŠÆÓB7oí!ªÕü¶ˆëñˆÐPÒ¥2@‘§ñŽÌÍì è#‚<¯p$ÎŇ®ÞJøûHU¯øQª‡z¸«>‡¤1íèKÄRýò¦/ˆ6"þ@RОþæöb°Œ†Ž/ É2ü" ˆX6íJ Êf"ÅÓ€A¤*ìj¯xècioèr/ðÎR»z¢oèÇVu.:»Œý!é–¸1S΋bþA¼ª)ãnâ…,9c®*.1ñj;ª¶ƒŒhEªŠ-Ú¯+'øyòf¼Ï!¯‚˯ÓjþRqäð2 ôl"ÏñHß­xp × ,d) ]3ZÌÐŒÄ-I>ÿ… ÝÂÕ1ͪÔCÀ5-ЫÒÚc X…zÈãnGŽ–›D£.h’5E©Ì¨$g=G"$Ó ƒQ*͹4²Ý*Èf+('ôÆlxrRŒä"<#À!C®¬£-äž2橪2Õj]-ÃL«Æ´¯"$µD~’Qíòž(­©´ÛNºïÅ)5޾<ÌÆCªjËÁó?¨Í=ìÞ_ñþE1¦4£M Cv§ÆáR‘'î÷îè%kèùƲø«júò†#Óþ ‚Œ³ƒ‹,c ³× ;çâ8äzó"$ú€5ÅâgézXôÖ½ÈTrBôù<£º[tÚí ú9m™:2à0â Vl*ÂëhÿñÃ0!õ!DÄîOK6”… …|óÓ,‰åÍp^‚sL)<ð{Ä‘(-‚ü“ÂÛ¨´}JˆÎL*´ú»ÑÀÞd¢û‘Ú¹ã¢nP€Š³¢Y%|&ËðþЂʥ=&Ï ù$΂oÐíà U„£%tƒd½GŒ“/já¤éL³TiéÇ€¹Ç"”Ï%.ôL2¯$ôH7ˆø.®¸Ôð-¤a H‹È›NÌÙÒþÚ¨2DZÏUJÔ!Q|õaù”îEM1RÀè€Æ¥L¯Èô‘¨ˆVÀÈUPµ°! öOd*u7ˆq›A² ‘¦^Ä`dO¹ èi*bceLùŒíe øÅƒXªJŒ ®T̶YPPS\s’'¶vŒ»%Uï#­^4úÖ"Ú!¬oÖg‡†Êà XÖ¶‡²‚àq ¬^î˨CTmB¦Y6‚ùb:óT?d1f‘¦jè'©,¼ï"›î§ÀŽ¥A_¶Ycj3Rˆƒ 37µÌrBÈëBLVu¾™‹ªÏÌU 9eÓPÄìNÈë@´:­ìWOoʲ¶uF ^%Ê"¶´ƒMA E.½ oA:tœÕDø2FâÊÈIhÿŒ‚ýUýÊ/æ*Ú“EPf”ú5*x°5Ath RŒSvÞrಠÇnš¡¬ž2¢5ÈŽSæ0ñôsÄ6&ñQ»xŠÃsõ~¦5Õ‡3Q… ‡»(Ê4úR‹q£Ùh‘ëgé3RUVš3Fì€áEÕðjb0:íäÏ)p˜"8–¤†õl¥¡ýNC¿T§Œ'ïÞÓ“+oW.$sk¤¦ÍŒ4šNö4ÑÖ¬˜Y„KÅGO÷+mí"Ò‰5½0j s§Š]"J¿ 5p¦¯X,Çcý6C‰ †oâäéúä’ù¨(nF§NXáÓ—a,²²6” –ÏPÔpÚƒ²[ržtdMHWÆÇ¯Qq'7t2²ca‹œãÐ’Åþ^[¢ n-V ;vVG}%|é¨ñEɘ²ñfòîZ{¸¦›låJAû†S°ð™2Ú¦¿O6˜yÅð½#)lÚ¦Oò‡Íæw,Æá! $0ê¤ÔïDñVé~ñÇ긣f€qI<€b@îh"ÞÏAPÇpNÊ¥{”»‚Å`ŽÅø(âÉÙrh<Ñ¿`(ÍŠ¼gñÎVu;¤,†m…6Ùn‘±æuéÞÅK l¹a–±*†"ªQÿ’¹†x”.¹ÌÒ¥  “&8•ÂŒ–éØÏÐLós#éY+b›M«ôöÂz1LTô#[§7H |!Ræ&$ø7 º Íõ~™LÑÞ‡~àü3˜Þ™×™îKœÕGV÷p/ï%kž3˜ôvh{£8Ü3G¯éúrß•(KÍÚ…šx2öÿ~ÕZUŸú‘‹˜COÔ.š¸ûRO Þë-‹K¾ëY<RƒjqÞ—6] Ã^7×FäÙtXëî- Rd™S ”)^5—iï-£‘‡HñB䈱LänRRÔì……vŒz²T«ï‡Š”åU/1râÎì#è3,6+Ôø)…ªÅHŽ6Aª„Å•)ùŸôx¬áûDmŸ'ÁôŒÿ†”úÎÒ »&ÙÕ§¬c ÅD¢ŠøÀÅEâXÎÁ]g3}ø=7õí_¸WP¸îÑx•ÙiŒUÌÌm+µj‹TÆ?®E4å›íÑ¡íLý¥å)¯9ùÌ0ÞŽ캮¤wƒvnÚmo›Ÿ“Ž!;™ñ7¹Ë‡ŽÙTw<¨hb·g×/Š£/5ˆÐÓY M’ƹí%aü€måP#÷¡Ø­#kìá•5G»ÏpÞÅAµÄ} CðW[bÛ¯hâZI@ÅÆ–i“_-ù¼ãðÔâBŒY³º Ý[O1¶÷«S?·†X¸NÈÞô6dKðA½¦øÎDRÐ)™¡íèOî{:¾ì¬:,å·ÃwQ Þ;71È øù$S HÆNÜ„Ëðª[™h-8ôU¤øÓ¤ªçNîÁ§S6½ñùüa@Üí;\®ìûRz$<HfëÉ-¤ó3(q\x$'%έù:t34®`)¤lå¯9Æ%µ,Çg¼'Z{ šöÐëßÒ»(Á¬±ýt±JÀiHçnÖ—ªÃ’r{Zõ¨Åý‹2Méh (üu"䈹۸<ˆÝò“UÀåyážïLJv–T â±N¼…Ya|õÈ! ù¸ìÞüWÜ•µ™ÞÚó—à ülwb‡µQµÝk6çqŸ=ÏHnahfI¤1ìTAwi®Mþeèß/ÚÂ8±Bøë—Ò–%<`ÅMÇ6Q—¬tê˜!ÞJîïü8…3{ú²¬˜åwšB ª¼5Û§<bçÏG·Tœü+a½ê¢m@ítº:ëØiµ^š@¾Í =œ”r™m¿BÿYÖÐ!›}› ¼yû׬TÀ4¬CÓO¹’̬ϟ™‰Fv:4\ñ[úó¾#²£Ð»Q^pž±7²À0Θª”SÜ–¦º<8˜ã4’]èÔ^œ>Ó‰‘¼wM?"pð?òåM¯/zj‡À2 ±4PµÞ1tš–³a¹Ónbw46‚;¢·Ýùx§•~¼§—¼¡9‰Âò+–,Ç>`8‚ñߪ#ë¹§ž^M’5ï»?sÁ¢V^?*x´šWÒ«¥Q9FNŠ=»™ªëBå þ3`^²•°¿ æüƒ¡Sö‡?¢à$ø‹DŸq—üný‹`dŽ þ}Iä°  ”-¿å )(iŒ¾æ1) N “ôúc˜Ña‘H”Æn§O¥SêpU/’Ï¥õU*’Õ¢ RÅXÖÀ9¤–•ˆVaQ*ôBoG–Çjr¨¤~K—Ï£ ¬ú¯—Ìdï© ;h˜Å&2¨î7 •Lju è_/©Íó@•² —»Iuü´+CbªÙàZ÷ý›;>Ï/¹7í#ww†Tî¥ê ‹”¦óÉË[ »QÞýõ;!-ë¡pÌ|?ŒÅ2€ Å>ÞœoŸ²ø–Ò>ø÷GeX TúC1é€ä´¹o¹ñ`—¢Ž §&ì(ÿ&(úÈì²iòx²Ã‘:‚2Mú§ûpÔ¸-’¾¢LJbÉé‰ë)7‘Bæ*n{ª"€Dº{KéSŒˆ(Él¹.É©s`#í£à#nJ7ŸêkÉ#q¢,ÔŸËôÕ²(SüÃ¥²J ©Æ¨2ðê Ì"à ¨h’:ŦÈÌæŠCP”îÉI‚ìÓI|>˜±u –.ÔÕ 'èu%TAøÚUnTÝ8±CªöàÕnÀçËç²c#Éã;\¢+qüЧȢ|¹!I+H¡ˆûyO­í:,U¤*®ZU6ˆP [R•"O\<†B)ònĺô —W¡@]ó)³›ŽÎO%ëo$©ânøQïºT©ÃøR4&WŒ±6>šÐj;¤ èE£Hý(}½W` UÂçꦞ*v²幨’˜Œ¼9eÀÕ ;¨ÓZCìÛ/ÛÝãè⦅¾×g2§þÈ©c'ò%ÄO -9±Mâ(ù&-Éû6|tŸÉºoXg¯þ%#óš;¹ù-]£©ÑZ ınÙùÛØ…qo>÷*§kÇöñÕj­Š9ó×1ýXË]7§{/ ¥Vý;yûKCƒ^7…\¿šyC]©§Ž^slYŽÓô–È32DðŠ”º{¬vÍÅ‘—²ÂÛ€x&‘Ô'âbÓ¨$)‰Õ€0ìWŠí2gk÷SL•ú¿‡0­c%SŠ­6åJdÓÚ1‰ ,‡)…9aBÿ`q-ä¸,܇ÜK°uïA´ÖE‰S"d–Ä"».=Ïño°‡/¡‘ò>„$¦ÈE Ù$,ž4­× á dMPÞ2RÄß—™Umؘ”Q“K›sH1w?'„ÞŒ›ä`„ Þ#ù%‹] ¢=7À Ÿü6ÄYt¢nË %gþÃÔÔ•LÙ¡w§=n·fXï û%LŒªw¼§×ñ7V0dÐ:€>N|¯`N©UÈW‹D”êÉq)‰bC‰¹ò1/…1EˆèÊrùd½»#ŠZȃVYMÙɹ – PÅ:7…xúL/B(Ÿ4†‘ ž\Yz“ÖÁD¬Ò‹Ò"]ºÊ¹fB¼F'ò„PÓ:bÜÓñUÉY=¾Çì É>_qpÈ·‚¦v1h%L2¦Üê‹ ²i2F¤²A2Éäñö'µnŒ^Š—.±Ú9¥?"•áá~&.ƒEx½ÊëC`%u[ªê²Tár{rÃþ›VþhiûŠÑ^<¨˜ æËBÛ+u@Í£nTÉ)üXÉÉùÉ:K•F= }’©‡Ò%¬ÈP°½¡9z'L"ö9îö@›*¯_@4°#'ñìAàUØûˆ-MkÔ#^šúŒ\K¢3ÅåEh,A !Çñ–V§Nè <“H5´€VP¹fzš'ÌP˜ÅºnŸÆl—“r_(¤è1,–gLyæ@ ݦ*.=øšÉVñ¼m]t[çËÚE/®t\q±|R¥­bIihFkšþXÛšqUø¡ö.iHR64N²ËlCš1«,m‡Áhqn™-°êìªÀ y`Œg6fF§žÄƒ8ƒòu2 &§ß%¤\OÅOÜ6¸VìÖ¿ ]œ&SÆäg‘GS–꟧k–7æ q³0xnÒbß$¨Fñ»‘iÍ$”$ VªôÒiNc¬Èq˜âZþàøû¯.ÀÙH¦¨Ã^E©¥ ¼8(bíëøÆ“z'egŽOôc$ùáÒ[uXõ ºe¡P9Híž&‘Í+uÑYAXó d7ÙHKcõh—mìœ ^êV[§>²À/1å—\†¢ˆ#yTãÌÑ‰Ž¸·‹ydÌìn‘6°I(¦0û"ŒQÄE«ÎÔˆQõ%ºJr(bëá-&êNŸéè·· Ý¿ä3G¸eí‘‹Ú0g¶ª‘Ö›˜Š>xÌäê´ô«ù{/#» E$Z¬ê8Étð!mËvJ—ÕH¹5—k Òš—q1–)Qô˜ÔÙSRðg¾EŠé†^]0§°B‡ŒÙW(­ó‘HFZ¥mg^‚öË|áaýpSŸŒJ?>“V‚‹ä1tÌä!–ˆÜŠŠ^}ã–j¶µ÷ŒœòFmyw}Ä}䂸Be×>Œ³&“ˆl‹î à ±#ƒííŠ}‡Ái$ùÍ%š¸Ô‰g¢±<èÆ|T¡±»†úË´šw{7lFX~DådW­¡b Ý·}L[ÖéÕE*Ì÷_d÷WžV—¹N†?ÉáüVú_”sƒ!{'°“^-\À‘]}¡;` þ¥½eSê¯2îÚä@«bå%ó“Ò”÷3BþouàÎNøÁÞ` eìÄÀ¶‘yÐδ¿BD.47ŽEåp 6ŸÁþ¤_Æ‚;Ù`¦‰¢R¯*qš•sܾ‘亟À‰2Ê`ªëu%®¾J0:¸ód¯òŸŽ y²ÀŒŒY}ž™›ˆ³Œºáì°ƒ?òŸ”ÃQº¡©—«(ŽŒI© 9á˯ öÄ`nÂjü”àŽÁa‘+d$X• Éø¬/(î–jl®òdº$•‰îËP€¡ˆCAµ¨ç²Ë)©-Gñ¼8Èû˜9üÀ[?´9ü#rE=³;<똽|"¡¦¸‡'{رˆéŠ,à}”Âæ3/Ë;µ>2S´À´F›»EžGc«¿{Ž˜î1ʬ‘šCú˜{/$R~ AO¨ã•BºS%B!*+E*¯N©•2~™X‡Ò÷ »Ä.‰ò2³±ô? Cò®ÅÁÓ.@²FPÍÃJ59ÁÖ?ëú¡IEº€ò®ÀP‰ÚüLÃûw;#&7 ¯BV»1W:Ⲟ¬ €e¦,1 y°üh¬{Ô”Ì$Çè´Qö—CëÒZAC:˜yúce2Ý>ø!X〉Òj ë¶-8ó!ËH5*‹ÈÙI*$º”ãŒ(sO¥K ÂӼ©]o€:̵'²‰H3¬‡ëo ›~7¹`¿[VEñŽE¡î‰xÈY+b€1??tÄ)w¯q[¿I²žóLµò‘(­­4­“™`’ ÈÈh«£öÜ¿Ë5 Ì:|/—»{öq•AË ´ Å'”V9ø•6Û(‰ˆþHZÝ ánÇ1Í­».Á¤sˆ"Ý?;@?´’·Ùž,‘ÇŠ 6™Ì+D´(„5ä:(ÄÄXóL0÷Øô)LmGd]¶ë0Çi ÂÛϨ.Êè“ D_¸„ ñb>\©“R7"ô~1b92F Iê;ž»¥s4™¤Ò ì•8ŒKH8“Î9ŸMâÆ>KŸ{c4ôéÌà–ÄkQ¤9{Š¢NáÜS —BŸ¬jHÅÑ·'ºMH²šÙr²sÂÇÉ& <)CË)B­´ÑL· ½É¬ûåJA+ § ¡1Ñ$ãÀdô1ƒÉá(Á§OÃ’¼Cà’£¤)ÐѼÌùL¢‹'»êŒÙÁÙö¡Í¬‘^™ð±ecg?óG¦˜:p±ûjF™ÕÂ2ò#9ÐbèÎ @´ÖÃ/Qpâ,!ïCÃ{¤Ò®ªÌ‹Añe8òµ’+Â1ÇÃvG…6½Tê‡ðmSÙ=Ðz$ÀRQº¤Å®¹ÁÈy±¨dí¢L;0* âűáN>Õ›ÃÀÊâ®Òi»l‰¡+S;TÇ+Ò%¼â0(I¸û±ƒX“Q^@…4)øGËÕ(¤ÔÎÔÆ7Ì/µ{ý {æ“P’¼Š(‘¿¡“†K’‹82ʼ"¯V8…;±.©ø› ÉÒÁ64‹/ ($»-³Aﲜ=ŒI¡ò¬l7"›àÂõZJY{V ö«´­– dK+ر(ÅÅËè°ÁÛÏ áÏû·ab:H¡¯ä#Ñí‰ ²&AWœu¹›.« ;7Ô‚R­$¾(¹š¥U;¸,¸NÝd…~RAïã]&Š[itFzì2øœÎu$‰‚ àG8@D(`ËÊŠXQ3AŸŒ±O\’Ú‹%ØŸ Yp}•ŠM%­Ž9!^)C>Iíõ ê¶×Ø…OUèžiºÕ‘ÐÁKKS­µÕ‹9³ª¬Ã+NBdA»]¼ªÖ[Ÿ™-‡Ô)}ãI­·]K9.¨ð§Z@“JvHÀ‹!t„#`|ÚÝVÉÚ—,·È³®>ÅÙ’³Î:‘Í«=ÆÛ"¸›8EÒ Út]5ê‰ôn9$óàÂóLÜN)o0%ЇәX„aæ"¡}×àD 9”fÑ•_PC™™SœŸ!‹ uC’é}Ázïþ3ÊÓ{ÊÕ£ãF¼µë/Øùö¥â²ò]JÛœüBD ¬†Û¶2‹KW@ÞÞ•´¹"áßò{—ñN2<7êü׸}-:ÑŽåFM%Ô`Š8"QEt¤¡>-"2CieHÑñˆqó«Iü#%y9Èħf"F…,ÕÍÞNÚÈ£D9œ9SqÚRl¶^Œð>¤Û.^㔓DéLá2…f2T»Uq³3Z–>våú357W~ZÊçD¼£Þ¹Õyfãbô]C+? ”Òžbºç©"HE±´ |aϸwyÚ;˜ójãn_ t™Ï«Š^2ÙåO"ÕKz, T¤¼Ói“/Ás_Øa^ˆóy³²úQ7eó$ï"¹=˜¦M?8?fòJF¯¡åÜ‘ú÷yܱ­~g%*ôËÔF?3&Þˆ…ÔËÌncÇ Ì·²Ëkÿ9؈rYvDˆû‚ Ð +ö?áÐøSôEb101ù†£Ñ‡¼†*†C2x#ì+Œ?¥Ðɦ10‹B£oÈÄžtˆÃóøcê…F%tpæ•.N©€º… õ:†DfðÊD®5ƒU+²xdb[.©Hèô§Ì><ˆÑ$ôËp9“Ã铪<šO7£Æ&÷tÐ G›Ñbs¨ŒêçÁCá”ÈŒFX–Dâ8üÆ ÅØ±òúøG¶Ã±X4§G‡ÕàÔ|„+ ¼Á§à}t—OœÈì¥tË4®ok»K·qŒä:—ã[åÖ¹NÖ¦“Æ&Q:e‹%Mî—-Gr q±¿¬1:•÷YÔÓ!˜è4Î h¦má×ïº⿨é¤Ý¢.’0©6èÂÐäŸèÂù:gúnĤèBœ¦%Ï*.çiâƒ/‰XÂÍB¯2 Ì!é­¡ðj&”­pV”ª­ðñ'ILVо Ó Aã’Ø%λ=Äq€‡É 3&¡ÈBRˆÊR˜¬€mÌhÊÈ«I€’<ú§êbnþ«À6ö¥Îaý+Ÿ¨{¥Ín’˜OIJï Äé²ßÄ‹Ô8~±Rt‘¿®’¶~(ñ;TŠÄð¢P‚N$ŒQOb™>%Ï#×AnÓ)»“èL;`0µÀ):FzVIÔB'OJW* “\MŸéMüÐo¸¸°ÈËC5ÇK”GïÐG®¯ öM°SĸªÈÚZ§GÅÁi4 ‘BSµÜ&=ï tÂÖªÑMGÕÿB‡c)únû·¯8@,ŠomŸ‹\ÖÌDõõJGú#²XðvMÃ[gW¡»÷ðéYNâS=S…ké´ªT•¢-ºzøI¡YœÍ•àèÝäSÇö¡Áì©:Žžíºn›¶ö×’ïê—lØŸ¨G#°%ÙÿCé^ ¦jÊ(³ø}Wr^È2¥Ð]×ìÙt€®q¼/ã8ºÌâÐMLè‡@f–v‰¹#sä9Å¡â¸â(KUÒ3‡âB‰·- ÖœÒw’ dŒ5‘ìØŒÉ\K@‘”†C¡‰¡u/Í~ÕÌêâ9d)\3ˇҨPŠð‰ÂÂRìtM%.H~˜& ÚÜë|Lð‰7²š»É!Ü7lÄ£»Ýá:I…ø¦´ºÆ\F‹Ä®’˜PêÏ¢*OÌ£±¢„±Ý3ʃ)zþØÙWCìàVêZb'j†v"BÄàå‡òHo Ç€u€ÿ¡QwL D€DÚÓì¡-Ø™ØóSCu3‡|¦Iâ•áåXð€„=U«àOR†P­õÀÄÀÁ;*„†‚ ˜˜#- ÔÒõ N¼ Dôו©²–à™»›Èn/—Fþ×âÇK±µ”ÂÐB ºUƒ¹ßD„îJTy'åJh›8Êò•Dlîó‘¹úrIÔéMä)H³&D?N ÜŸkŽƒÅ €*™ui¶húIƽr‹‘$?¹;I­irýÐ{âNPEþ¾ÔF›e ¾sÈm°œ'™fÐiQ…Ô‘á!BFù1äâ‹ç†eÓo *ŒO|ÇùA?@­]ƒ•ˆ’È£…¯—¥bP–ÁÊÕÁ®Ê³VŽ?6HÛŒÂä7w.˜Ö•Û@‰q#—) ï½RB0$§ðýC@cE±*.õT¦ ò Œ$ïXµ°§1=ʲmÒÙ¿[õKÑ$úDçäÛu 4^Ùì!𪆾+¨iiì1›™&©Ñçnïñ…°ÉÝ‚M¸µj»2Y¨fz!¥*±Q„Ä¥-O¬N£0ë(èÔæ7®&ŠVè 4kqhŒÄ ëaCÅ_à©ÈtÁÛ¿¤Vø~£2îÛF}Cï “ù?V\¥à¥DU„dG¤F¬Ç ºèúXœ‘|×{­ý¿Ûÿ8P|7†Ìž¿ËË–J#¤yŒ×EÝášh’*þÏó£¡(ÖT&î–‰ðŽ1%”ÉD–÷èe‰•©eãRX†‰e µCmã°` ¥‡›lÊ ……¬Üç:töq¬,Qj-0*§Vli줸#'·:éŽöSèš„ýëX©M»°ÑËó%ãz¹„s,LêkJc§©Œ: ÖKþúæ#©ŒŠø‘Œ{3Òsª&l • 25ÏÅPós1¡a ZN”ép»¡*'Ñ7Áí¯Œ°0á¶d<­35"T²¤ "±ÞmÖvOOÃ1*X¢µTÅÃלÒÖ ÈWG¼à”ƒ þÓEÈQ±þÂrIWya-nÀ£ËÒ„ô«Kä®QÃ~Á…­¥|\ðK˜XÓ7 ®w™b­Jy*NJ¨XãSÄ/¹ÅБUt­Æï'¸e¡¾c%á#x¶±0ä~è©+”ë:ÀÖéb@³ãÊèºF\ÌG5L8ÎÂ×öu·sëü‰ÏRzÛ²$)ÛÖ™h¬0>Õ–!쪧°‹MÍ»÷zë¾°BÏç,è G”möH`Kx²ÉÀÐàpÊ-f Èd"(âeJùgÅìâj ÌmÐãi÷¬ØXçö˜Ðò"g¤t뢄‚ôJ"ý „ððN)þã$´7+ñçöžÀzÄð *HY¢Žé T½HX$q.«/mȳË0Zh2Ù(ê§§Ä ¢>;Q>Ïé“åPˆˆH܆ܦ ìmm!ÐÇëx…Eùê´t,¢j¤Ð†‚nÖbÕÅÈ`Jò§®®°i!BÖ’Ë0¸teŽ\Lž<°â?¦þòPPêˆnkhòm<.-……Ä{)\¸æ¾¥JsDuiÈË*ü´©P#`µÂ6%,Õ,{MºÔ‰½ìŽU ˜ŽT0Kx%&ÖÝ‹å,áÊàD%Jâl§£;¢VÞÏz3«P×£|  %&  aøãkᥚ½EÞ¥ÀáÃëj¯…š£Aþ‘ž}naÄÚ¨I¶«ÍnÁE®ÿaúš Þ¡@Èio$®ÌØŸ,~Ðo¼~eºD'üvÍv¡œUBÄ¦í¼€T·ïäT°èÛÊ£¡÷(ÏzzBüB~Ú„ä)‡`À€òi‡…n O—pT¼®*ÃÀƒëd°~ÔÒ•*E ðÑJ^‡Dt¯x­g u&Š.*æåBÁ™q˜IÊöl‹E«)TgŒ¢À? r©Bâ?ñ•(îˆDb²ƒ)pÖBñ¨õ-"ÎÀsP«)Å~ßÐA-k2Å/êWÄqþú0«`zÌN#ÂÎ)IH]‹6Ò3*ûìèÑËæŠX¾ñukÞÌ¢”v y"s€æËó©ÄÍŠKL~‹F™î̱ï@tt -„Å ©(K¨d*g”¦†a ó3RA82Õ3ܘAðA—ejn F.)&.„:Fþ7)FTÎT&c-§ *Ó(.AKBi‡ëÓp°gÐ)’¢®«ø«L¼Ù%‚Dò„Pç<´ZÙSªyPªÑÃrÈ sGš`KÞÈlj&Â6ʇMrr ™(!âÐ⨉1q4ûîFàáô¢…jQ¥ð†ëüØçøîB„Kª`¯©PæŽKHðÿE Gåj½§žGîT.)˰^:BЭÓÈ0ln9wŠ#‚Vì^Ä×&u»‰,©t0µôf7þ¼£úÛP#? P&Èá µ™nÏdANõ2DáŸ>*Ö<´£t¹§w'AD…µWbÈ› 8¤gѣصOiSÃwmåQa 7…*N°›l–Aó›{ˆq•j ?8­U’Qà+9ĬIŒŽÚ€‘;¥WŸË)m™>þGÑNG(!ˆ3ª”`SN,SZΤq€ —ky¸M•¬Ö8œM¨£¡¯ ºEˆGuŒK ˆ¸¿ N²7“Q1ï´àªè…‘$ð{ù»À f!áÄ–“ozvf&{úDJ+.à-kØ¢Ñê(…‚Ñ…c`Ù‚†ùœªé)£4Ç&õP#Ì ¢“bún‡¯uì.íH´mä¹éÔ< ´WÞ—ÀvKwÒ?kW \",ï­&pF­B© ¦¼ÜäT™Bd…ŠWr^÷`ÃËëxËX¦´bo³¢~q­f mkÑ•$‚;í¢G ÜöSú°_‡èû¾î±7$7X{5¸ÖÀ\4n!UŠß2PÕŠÔÊAúp$C g»Mˆo”lK£sž8O*;–„BÎÈõëKnܰœëÜÞêc¸ˆ”M-ç^zöy¸$¥©Û”Ý"®ª+ÊrÿÄŽºn¯1¨ëÈ”¦G½FÐ@B~¸8(¼U7C ­ ß"¨šûSK.ªC "줹TjÈùŠÌ<  ˆšþóGà"îÌm\P}ÍŒÂdÞÁ®›¸„¡HöÒ Êtê<ÕDN§Cµ~TÖaûK¤‰F{ÔÕÕ!%´ª:ŸÎвá7€ŒÛÓwVÃ`à“/ B„Øs‘ƒ. ܧ(V|‡|5ðÌ.‚ ÑÂ_5¤Ó ÄTÇ®NÛr">ª9L¼—¦÷„¨þUtâ<Àé܃q, ~Ýxw“ž³²z]j¥×<Ê1âwqŸÐf¡,ÒÒnî K…~³5f D®Kg¹X•‰uÞ "ôž¡\-j[ ²~*“MËkÞ ÿi,‰{@ÉR$¢F@?&ðÒå°ê,»%ŠÄ¶¬1½iÝî}¡JòE¡^ÔR/>#û£Ð¢}6 NÑüâÑÒÜš¾ª'f~ÑõM4î'ö¾ó.tà 'ò0 ð¨–t”è»êÿZö‡ëJ“iÒ%¼L„œ÷TÉûd·à‰;(•¾<¤¯žÛ[å*˜O¯"ù]Ù¬!FŸöJ*‘ƒBŸ'­ÙÛ˜â6"åü…8²ŒÒÍ›×LÉÈjb £ÎAŽ¥gölJ;4p ›“'~rŠÒÍd‰Þ¬b$L‹ûáSHÚ’”šF•PÿvÅá0ÚÝz=v#ý‚,üaÁá9M•÷"ÆjQ "ÁpÅΓòþNÓ²t!ÅP‰¦”`×ûUYKÀá‘4hGâèý]êSâLµZúG#íS@âM@+@!KÉmÃçB_XÒèTÑL‡F‡vM×™ˆCü¢?ç†LŠ£¦lí˜Æ÷숒S¢NIÈmI3”Ý ¤/†À&¶öå á„,ADJO%ã¤k “ÄÊ·H‡¦ó/!i»ô&F!;>:rÇ@ H“¬Vq(¤‰ÎP‡'½ãÊð̹"w,ØÁ  ÝÉ»Q‹õÀ‡"œ¼1ÙŸÃúU’¼ÈÛ™fMðî´Èç\È1œ°vÉÊjOÉÛWª¼~=·%9ÛÒA iñ]p”¬)I•”—§±F²é¼©áöá‰ù •(÷"šGÐ"‡›u–Á+ŽfúªÏa±X@ 弡®êÃ#U†r"°Ä2Dê4Ü®iˆLr–v*´™äõ<#vX”£XÝ5™ô"”D¶&¸7þpî[Ø!‰¤‰×úGá:g£ó̸5ö" Ì€´ïn×DS„Äå‘¿H†HÚfgˆÑT{h2¨ÕF Qð«R$°“5á|Éáà\.H8t£ʵÅÔÁ4ž„Js ´\®äµŠ/ênê&¹DTØo1º?)gêÖL½œ’˜vF£’ÚF²z½“ã}­”cê›)4 \ÇWAÃFå#kòES…WrÝ»ÜQ'›vÑ`´’z ²nupìCXAW@¸#y]ý”HGókô²0½M1ù*®ŽnHЬBpßæ‚<)µ;éG¨Å`Ôô4T‚S³kþ<Р~ÎL¼Ÿ¢-—]Ä ˆcHž%ˆ¨Òì‡Eøw;ö}kä1¢º¢ Z©© z©5Hɘ̀kfÍÉm4ÚZåu]ûtr–øŽ«T $I§¹ ¸"-$õ¢¡lêI›ÊÙ®%|l†d¨É‘è^‘Bh©8K}ž©´€›•Ff¦èkÛ˜Ö+Më(“J£€Y[ЬŒ$ãoì¿u{c³ÀëaUÍRýïT¤?%ÅÓPÝ•ö#|iÂ<Ò=o|ðµ^ÚØ¹§ö3­Ó–ÞE¯îˆ¯Ï[f4|+L¿¸ëD9{ú<Õ1±ô½™uÄu‹ðÅ;@µÑ82Lú¨~Þ„ye!ß4ùõß¡güÑÉnýÒü¹H½[ÞÂAr³èê_rùz•ÜÛGQì¡IpÞÂBØ]ϱ´H®ÂåÒyž–Dý.mèXæÔÛh ©ËÊ›ÏWÊø^=ø¬qP\g÷‡Ù¿¡ÿHŸv‹B©‘ _g1Šðš=¯$ZŒ##g¯&Û2º§ü.jö|•/s‚!T¯cfe k`wÔ).\Žœ'‹Šïλ&øàî[BÆ ðû°Úb·…á÷Gìö.¡žV°flÄKgÄ2¥~|¤O3̇Ò> £s©ˆðšéŠŒÚR72™~2ñ'ã//C²CÐ2Bâ‹ ¯;sq,óî:»— »32Ê0++8ªO1°|@Ä%ñá1¾º2 ¨‰7‹ &ºê’jA¿ ȉk­‰!_¯€ùZ¨ûæ#j"$Š"³"À¤ñoˆëñ.«€¨ç)…!¨Â ‡˜s±h}$¥@–—ƒÒê¤Êç‡Úy¦{©H’ ¿?2RÉ?g·Út ¼ºk¢)€Aª›¿ä =ó‹Œ@Ÿ°Áù4ª áãR‰¸¿¯CÒˆ">9‹Z¬“ Ê—¡¶P¯4;%b›˜u·B*s9à}ŸóršŠ ´Ѓ- 6°k&)#¾Й20‡ºÍI Yúiz.1œá€v2 ´žä:B8}”2•‘LƒÙ>ûø‰L 'š'ˆ¸Ä4±ƒQº8ñe9À› Š­ÆÂ³ˆªvìk!Êä9٠滘Œ¸œð5qï²XžCT“9x6骘@4ÙÚEªça ?2|H+!½Yl¼‚š¸ðô3i3²Ñû/¹ß.E‡â·!Êi+‘Õ¦3œé4®@ !1§›i‰H§'a/4B¡¦ ƒIkŸòZC7â{– ê=‚wÂÐ{2qAiúžÁ—Üœb>;ðóI#/±Yç@‚¯Å+K¢¯ãþ¥€L‰nËC;ÊÔÃD CÁHCÛŸ0th'C IAýÆS¦¼* âw“˜£¼™ ™ÿ$Ëý #3 4¹°3x?ÂL Q2𹎤PÅ3FÇCY4QÃÊœs¨4ø~„žÆÈ‚ñ4³2/·ŠJsÏ Kr®iºxÄ(KÀ'ÑZ—£"¼ÏÒ *[©©Î©ÀþÍ ñ1@£¿,“q±©‘¦"›œ2Á®³mÙg•©¨Ì¢›µúvÇ’O›hµñûY*§ùïC\ǬáÈÎi¨»¯¼½.¬V³ëÏÀ‹!Ê©¨‘ÿ¹,*,й£«Ä½s%#A´F1Y >íÅI2Ú¹'Á¯°ŠšÍÛ!4L ¨£cx+Û\Bë½™õ‹‹ÂjÞ§iú ó2:æ‘)]LŠN“ÿ1U¡ú/˹°?¤™Z¯NËEŸ³,1  s|¹¢É*³Ø²RF ê«²(%P3™ '&û."¯4c‰IÎΤÉüÉP+(¾4Å ¶+ãI3¬*úr²‹‹º=+¾ …®Q7º”x΄«‚œ`ÚѺ³Ë›¯Qh !Ý ÀŸœб¯É2üܥΔ¥²M©’4 4÷1ræ $|4»ñÀB£±t~Žö¦Dâá¯Iž€<œT¸QÁ¯”Œã¾Š¡šb§ˆ‘m>s*€!ß—\FDÌYjŠ¡¢8êZÛ‰"©AãŸ5Ð|Ët ¨ãÙ!z_*»,Ìf)<Ä‹Üq !Üqe½’®"ªÆ¬g£«è3A~¼°‚F:m×DÔs©µ:€nû¸RZš ÄŽ×ýq±&cí©k   ÃÅ*k»ðõ§šJ¤‰s­eb–}n4Äú -P qe:u'ŸÌåÇ3—Múºqú=SV˜©Ã13px9‚’ý[,áE#¿¹1ÚBÍKš 5€¿‡ÐŸÉ¢õ¡MbJ³UË$jޏHŒ˜¹gÖ< ]Xã! ñ4£$GMvÌrljK‚€-¦é·*—LëGÖZÀ¶aêQ"µ³GÄÃ?B¢ZC²‚¹V²¹KÛtµ¯¿ä ,3ò‚h±j¹¥5Ùâ˜½ÈøõÆôÓ1ÌûL¨ 2Y§Ô¬É¸ÍS¼#¹–<\EZ,\QþMÙɘ2KÖyФ"oURй761áÑÜé[ý~E?LšU*«“áBíÊÏrŠÜ³‰‰!EdÞÌMˆ“tª8Êh‚©3؛Сò€ ýN“ɺ™¼À‰ÔŽÈ€”ÈÊErÄE]3É8«\Hð«¥/(„'ÂÂM–Ö“×@¥í˜Ú˜B yœ²Â9íDÁvý\QƒÃ#«OK!¥¬÷â¢ÔBãUâʘÒyN¢˜-\fà‚ÏQ&u_,Ø„ j§BÍSõ`_ÞœŠ<¿Ñä ÂVÈŸ+cc-×ÔÊ¢+!Vu|¸«»ˆCv"Ű¢vWZ 8 óΩB ÿ-¡H×ÂbÏ3/J¨‘ ÈzeøÈÀ³à3\Iµåß]ÑWÚ€[h±1º^ ˜0á\t ´Ájß¼f~ $É*ŽNd1â¹`£kSE¨k¼ˆ­¹“qÕ½.­äU}²>…iÍôj¶5â¹ oÛã€[‚º¢‰õÑ“w©š¯.í.ä£ú%./€†XÓôü©„` #ÑL]£\¹Ã%)Õ¡ÚáIÊœ1!Q¥,PæùÑu†º¶ã•SÂAZ›‹«¦O~^¡Ë“Îô¿H£x¢q3¡0’FÞ•&Å“øô~uÛ51Ý€#a SX¡ùú8 D4g¥ž/Œ §šòTm³Î’vx†5R\¥R1[`ˆ4‚E(Õ©›Ë£y/¡_Æü÷GYÌ߬*2|µé1¢ý²:òÊ2àƒb•´È¥ªôÚfÒfs¥Š’|?ý߯Œ3LXÐRö‡æ#Šà½;V\OüHˆô] ;ÐÀ«&¹ÿ4}çÎtéq]Dk\Lúë±L0ÀiFp&ñ` ÂÅâý£ÑÍÕ*¹¼Õ»Â¬Ñឪǜ¬ËÌŠ²PëxŸmHdzÉ#uh¶ziÖ¾e*˜‘k@Öy‡ÒÃù‡YÖµÆL)ª¾h$±‡à¿Ø#áYµîÅ”SœNTúvD Í÷08…Æb•1À#ÎQ‹€óÎÙÐÈIúUUNÆŸæ¾Ñ”ÎÕ–~$‹•Ûyÿºö!ÌIÙÌJ«é^\k•ù/ Ëè¹¼î<Å«¢û i¢Ä0“R:ÍP÷:Vàë…/}'Ä6’óÄ9reù=ˆá¶4ü AMDà!j[&{×òRÔ!ûfÅvªDÓ;6ø‰o離ÌT³ÙWÖ¡°ú2XEË[šOb’”C-«:[?O#ä舺5Š´T¬3ónü"ÆÏé†<;—?¡ÔOŠù]z£YHæI}ÌE}ÚSL4ä†f•)`Êœ™±Û¯+ÿ·yíËV9¸vBŸäü«=hÊÎ…%ý»Ü\ï12ôKš¬kš}`•êFµÄ³NjíŽQ¤"Ôúìå1EJL¹-AÌЕúÒZB_ìÚTu,\ˤ£ø~Gã‹ÍÞàà=žsœ¡Är0ãÙ[ÙðÓÊX¸Šâ,2C`ÌÛ$‹Óbm‰ùS[©j°1ß´‰²ìçCÝôüçÝ#ЊlïÞz8!R ÓäØ‘ç£³ŸÞ›q|Ë¿Ç7XJï·.ƒ.uïgVí{Ãr¹î§ŒK×`õKšÙ4S mêÁí±ÚáHÝÞÌ\4f4$¾NwŸ‡4‰““€Éc7žt·úvPˆ‘K󽑾ŒéÚ$öŒ¿3°‰4µZ7PÉ Š÷f¼¬;»ªRŽUt'™/hKt%$íT÷ÑQŸ.šÿum#ÆFÿ²&CSr/ ½qSç2eh‡4 ²ê×$µ´·‹V!Põø²w÷+’£©íð~¤ÎÍ=Lò ‚_Ìð Nu‡|¤€Aÿ;é4~ÝJâ*|<êz!ËÖQ¸M¥³ü?úH¾EŒµÅO«óΔ¶Øûˆ›rÏÌ,tÌ9óÆâ0c®É?ä§½ŒÂP<&¨¹ËRR«¥©¾4ëPömÜ`<žÙfßOÊŤËc:õ.KqÀ#ãíhå14ÃÇô¡|Ö’ü™Ü¿²Í׿_ÿ(¹žF¾Ç_ºŒ×4T‡86ˆ?«ƒ:†ßÜ£uJžó€Ê­Ï³D Fƒ#åâÏJ”Äõdr,•}boâ\á #¬NÇcÝõiÔÌ;@Qý·]P n/‰L.>Þ`÷ïju˜}v |êÚ|c¼àw˜½@´üð”‘Tz@ÐgFêæ)€€ Oø „Að` þˆD_‘8t2ýŒ£Q(˜<û$P –D’€äï©d:S~ÉâoÈðS ˆÉáRé,ÂO˜C"0ÉLV AƒLã@i““áRxeV /ŒIä¹=FØ^ö:ÜÖf´XÞôºD6?ˆC&ršBàþ™É$´º”*üÿàkuÜ$F#<Õ€Sˆ„Ή&‘C¯¯û¼Â/…MiuºÜ¦ïFªÃ¨ˆ^‡Ý¤Q¼'¥˜Sn0iÜ& 5ˆåߺYcê#5¢í²’;þßÄÛt»¨fN·ÀkpÊ\F·™Lß=»&eåÁ&z å“Ö½·Ì3£ÑÑ¿zÒ ‡uºÒÚe.fè¯("¶è´®ùøÝ-ŒÃ\É)KJÁ¤P þÓ¤HcJõ'ÉRç¸Ht˜&.CPÔ3ÍZ é Ðz@ÅB€& 䉷èòÿ ÁŒ2 ©Â±Jë¶îÊ(„8 Ø™½)JJ†B C ó Î0»¡NŒ€´¨sØòGªª`Ò¹®A/΢4ÙÈSx–*ˆ2¶¥©g¤ä¥¼ðŠ'*°(r·².8ˆÏŠëc!µ'ôK?Çh#JØ# t“º-ê`îÅÔ¥· m4µ?Oc[(aëQ¦«º—©Ëu Ü ¨3¢ êO: ÏDE0Ôcäˆ.Š´Æ~´MP¾A•…A¡Gµ”Ð" Uœ™­M-O$ZÞ¡V™þˆº(S8[(Õu7£hƒõ '5ÃA%$µKØÞÙÀSÙ:«¬r®’½ÒaOØÌE>øÅ´ ¾}Ìx’·Ô ¶Á€ Ö}_i+z”Õ2ʺ¯ ƒ‘Œ;§Æ=Œb‘Ô,cJfΧ­"J$DG $¸°µb2TÛUXÏ+þÀãBý%sep»Þˆä‚P÷J»0€)‚j†F3òNÒÇGòޡм–§èîMH«TÿWðªË‘™j¯fµ¾wóPÉð\¾”öw€NúBK$NÇãKÅEj>¿PÖ½éûÍn:5㓤2ëÔÄ!Z„É—½l’é]=˜Æ¼œ7ºck¦£/°W Ø€M•+Ÿ­šË¶MUɬ…¬iž*©^‹ÁÂJ‚Ó Jï¸ä7²´H{L4«¡ƒ€6dB¡ þe’WšÜ]k¤c@@·@°T2í" p´+×r j¶+®µãœ($›™l3réÀ»à ê-h½"³VâLÞBiNèÂfã@ZhtèÜòöJ«s<«ÐÐ&ˆqž1ÈK€«§.y]I@„‡;7š‹Úb-WîÔ20 O!,ö%D‚Õ“0pÅ⡲@¶‹iÌGÐAU¿Aù dXñD¥¬Æ ë±i†¡£0Õ~RÉ©½†Ç ‚Ãð•Õœx©|K0o_ùka¿¬b"~š3ûˆê©†ÄT§ÛÔ+±TŒæmQiRŸÒ4¤ -GuoÀDÊYj•ffÎÉ*ôÔ#&€­ËÀ 9GÙÕ„¥œ´;3Ô^ŒKÚD áÓ6öú>âìŠHÇm=Øè™r¥$IíûQ.Á‡ôPˆHµ& å×iLÞ$ ú‡ì܈Q‘.¾š0kÈi“­A†ªÃàL‡¦ÆÎ[R‡^RÚú}æ"™4^þà|A’DDÞ¢¡ö·É:*]rنМ“‘.Áj%>ÌšEn*D–/ªvŒÜé,d)xµƒ„Iɪ£µ˜~ÐD y)d¥O$öJîd£«Ð\‚Tʰ~šL¡ãõ‰Âã Hq0~2”~W´ŸJÈ!¨ž¬ª{Hà %é1J±P@S]Ô um½µRf¦€i'YCÚšP}„í•¥M"`‡Õ ¯²Nb§×¹-œ„!ÕÉ5-güG¬•¹8O0À¶À§NÜ‘‰éú¤S@im™¥vvX“[g%˜%&{Æ"n?·È>Ì™ ;°â¥]»ŽÙmCOÉ)ûTtk¢¡ÓJ6&çm¯Uö_¨1 76©O(dIhíÒ!EÀsU0È~QÛÒ Úß}íˆ8*rÓ"Æ † þ{RåT‹Ë¹ìœ–eêÃrLDÄ穲“ZD\ˆ ¶g±xØ—7h$-y4T~¨|L‘k¯²5º´;Œ±;5;©¢”Cƒo`µ–Ì6”K .ýÞ…sr9µZÝÉd#"kä´HîüP:DÙÛ ÜôVÚÂ[¸°Œdâ1ŸTÒ¿g¯IÂ_h¨ÛidCÆ—ÙÏ\d1g¬>vgv覘tíè4£kR#|SgZõumñ­WZ{×(µZ¸°(Í®˜¬°_Û.§¤ Så5€Ÿ™« EêXˆu§‹ñ3&dÁæÔ|[Þ‘)Réþ"ß‘¯;-,(…M+§JJéÙ¥#t_Ö“ˆ“¸ÉZI• \Aåj­¢lý–FÖ¾ÆE„”åÊ­È^õÈÇê<Çjˆa¢Ö¶wÌ„jvªh Ýgu)ªÜ]l>2gÌ}ÚÛ¥ a6 7HKtg}ï ›cÒË&e\^ámånº]g÷±ÃÅ¥>Œ§æv,pÆ'nZ‚&§õ³Õ«q_æÚqiærû×Aº‚@â!^z!Ïä«,bgD€ÚfëÒ)é5ÖIuññÌ.ņëíhú%ãÚ–¤‘7ƒ¨¦Ö%{oA®¢Ö•ÖÉcO × "ØírëõÕÕÙ¹xWÏ&”'³ÆN™2ï^ˆÔW@¼SPMUÿFk§–,½èàz¼À&o„` pðUÆ»­PnÚÝ1®PmŲå_cíKô>=Œ0á\ÕšEVŸí¾{ŠÁîµ£­i›C×õÅT̈eT¤P—ÙöbԹɒã9FÎgõ‹½)„â"Z¿bJÉ …´Fé¸ýÉ %Ž,%‹ä,0Ö†nÑìÄg*&‰&ºSãºWJF¸Æ0Ã8tl0¦‹H>,Ì&¯Døƒ$ÿAø4 P¯œÒpöTNWE>!Ãô¼æ$%Ž´8KFÐCM3¡ô^…*ofd·ÊÎ_ÂJ…bRvibÎ(Kl0@ÈîK¬<¾'nÚ¤nšÃ· §(#-¨&¢Ô$㺮N$¶¼å¯."1 JMÂb¨þLó茧ŽüdJÏFêIŒãå QJð &‘jª$é$M8# ¨ªTÿÆcüFˆJR±TK ¼ôJB@ÇöËÆ¸Žetu¨žg'ÌõåREîRø¦þðRªr»IôªÊ¶I­¶Ó¬Âãp8)mHBÛ v†o,K®«d$¡¦ÜÐ!üúÎèø œ.êÇÆt†i0LÆ GšpMÊ"†·±Àç£$oc@pQ0m£Ø@cßo€ðìÈ OØÕ ¶öî1,0¿¢ü‘Ò,ÌÍ|ôKHÕ‰l}Œºx°nøÈà¸kô÷ ì߯õk´È"`ÿpö’”ØOï Æ|•Гfo ëí+p–°@&«†Pn¦™‘ñÎŽ_¶`Œ¯ ¡Ä^âèEê¶ ŽÒãñn…I.lŽÐ—oŒ‚!Iý1.@‡ú?~jC‘ áôAÈø!%P*I¬´„®^&0f¨Æ²ƒêFdªPÍÏ&±2cÏ$/Ð^¨#Êé ëo€1FÊhɸpQþN$äô Ò (‡ØÒî †jJójuîJgrBNd/ÉjÒÔü鲓ˆ*Í”ØÌð0ÒÀà)lºË&L³Fw3$ÊëK†Ã„¤Þm,m³f2Ž Ä,i '(ң˸ђù?ÐD‘.·üôilîhÂÚH­hÄ“È8M¦Òp¡Pú™Ä[£ Sðí0Ot}êåÀ ÔåcmêùëŽu´X?IÔ£DIžøtâæX¡Ît]6-}ƒšR‰- AB†LÀ !ä LŒôE*ì‹ Ñ´6ÿ’¤$EuI4ì*Ê-*>%  ]/E iQV7nó0Î:/i¾z±Úmð¦ÿL‚õŽ«7å„1Nfîxì¯`¶o\ÌO(’|úÆjÓ´ÔÕ1ïF©ø ‚Eä>ï|rç_BF¹ÉŽ-*ú-©„5DÌ/ oëkMl–É)m T¦àÉ…&nಅHÅ&,% ,e´Xâ-¬u7•t0%£3rÙ=«ìvpDH´õB´kETÖ†ÃWãI¦¯Èõ ëJ„YIlo, E¡%ƒK&â7´îêôvPðÌ(ÀÖ‡^F°«3$Ÿ6`£pÚ£Ò­óÞá¢&uí®t Øx®«&Œ÷MàÔ-Ž^”öÿ2ÅêÐSä®ÅÂRï‡b.ò•apôK«¬úɨɤžÒ"OFÇm6ßLÆ8ô¬VËIWb0ÇÂKŒ+lfâÔ‡Ä^?LuæºÛcØFãJ€A±C¯çÄý‹T\fô$¥ãj"¬õ“_Z²l겓 0JE?VL0à¨ÁY5fî.Ì£ WOYwËfàñI{o*Ö`y¦çoC åã”Æ/’)wcëýESÎå°ó Ç74.ÚBJX–×MŒ@#RáPÊÓ© ƒÇ¼f°lÇDGš<¢—D¥­ ÐxÒ1ºuô.û¬v±Òl+t.·‡sBlîR´Yyõ¨ªÌÍX2òöDÇoaQ·®ÃÌÂÞƒ[¢&nsYJ‚O;F©ÿFdÃÍJ€ ½=v=P†ÿ‡K ¢§öÅ Z+4oÅ@‡x@Ñ`,1 $$Pú‹^$tÙ•¬t±ùž·¯q»Œ;ÛÅpõ4XÔúçAÒ+§LÂû2=ذ*U¤nÓ§†æøQ<Ìa¥ôÛrhg:÷+OT# µTâü·C”É‘»±T›wÁ;-ëW¸XI…86UÂå‘m´kj½¯áÀf§›¡ùÓx½{g_E—qkÜ MÓbMŽ4 Cšöýqêyœõ¬‚¸õƒúPÀ0Êå÷…W=5hÕ6çÎ7îrËѺ({4RXY &®y-ÂàÖ ÅÅιŒ&cz›Õµ-´hÅ¥Z.$x.¨YVi ¥1KB„%¤!ÿÊüoû¢›‡þFææ˜.M%hÌÙn–[¥™ì:z-*t#.Áó·¬ÓI˶ÃPºÊ}å c¦>k™ÄrkDøÚ uM¤¯K§[eÇB§9È€Ò:‰”ìqŸ4@º&eÀ›š¸õåu×êÌ]Zq¡ÝÑ| y £]¶äö¶l‚-ODöÖË€¨ÐÏKI<‹LQÒ›†öÅ,ýVP»¶Õ™¼}_ñµdý1¹[óÓ„¦Ô¾Ú·%xætè}`Z)½9 j§<®¥DWÚ ”òøÝ[L^ìÕ1ÅMè¦Þ`³Sd$´c.Vª´˜pzÚÉŒšH™nûÁJ:³ËMq¿‘ÇD@ê©¡ƒ…wpàKº¨Ú­»9n¸ú~›‡„ RC­Ùi‘™A<±µÑ…Çû>ЉMm#ã­s­.ˆ¸ø6f5„¼5…¹>2žÎªâZ½KÆ #hz¸ÈÈÒ¦£[=Ï-an~~G]6ÎðP0^áø1Ër-wkÞ%(ÁO«ó•ÓŠ¶™ÜU^X`²,oz9k‡sÝÂ;{w¹Ž’Ò_ ¤8HxªU)ñ/|EðéÐ=¡³b<Ö“ÓMY‘pšÌ/‚züÐ_…ƒ´aôâ‚ ñ¼êü?X¡É35,‘áÓÄâõ‚NNJMƒ(/uìÚ.¤#tHºi ¦<;¬Ú©„ Øÿƒ?¡¸P ‡BÐ'ì8ö‹#,lˆAgüù%Éá€)+òS'È# ŠA5›Lf1ø$æ!‘K¤ ¦S4›JÁ—½.].‰H(ÉJEE™Èà’ÙwºV€s´ÎWlÕ Ò p ‘Fð¬dú—T@W‡ýÒ{P†Xv™í† ”ç¥6;Œ"6Âfä[,Œâ;‘»ÇdXI\ŠWÅßÁ,uXešÛ ŠJeoŸ¤å•èù¨gñí—hâ*f+”á&>'Îw#•œ%+Zî+RÀéŠVæ*šƪðiú‘8¯Ãš›,*âb⢎ˆ,l ‰%.+Rè£ Fú¤®,¬E=@H’¹.‚ƒ8±¢ÇÆ ;±°’Æ…5góRˆ< Jbô0J@Š"Nxͧ‡ôBþDµ#ˆì£  ÑúSÄÌš¦*à7:‘»}5Ò 0ÔÇñt˜öŸ*ƉB©“y 4ˆÂ$Ô°‹ i-Ç銚”!KÐÃ=óIû¹hë®þÑŽc<¸!’¢"NÌ<ÑÑ3 ÁFHC“Ô'ìBÝŸòñø·.hCS#®³¶“Ëo²Ôæ>`S¿U: ¯Ïný$;Q«è,q+) h#Š•»(2(˜Ò(±MAus2ËÎuEQ¶–k`´]–…"QåΔ¢Q›™w²êÉi6UÕ|×lü„%q Á/€¶…ð„J _¤± iY Ó‹‡Öƒ7|ÊØ°Êà§`Ì9ú¯¦*YîŠU‡óeb=þÀ8³ù€Œ‚Ú8°ŠÐ×¶ôªÞ„b@Rgvl·MG ÿf¸¯Ôi{ÖP¯¿V[Û$3Ò¬BkìrDlR;ÁxQù?Ôy…fÏ9MñPXhv‹$ôÂÏêÂÌj„Tj9.srÃHÝ R •xƒ?L"]d Ù9û¹Ó/Z6Äßèî«ÅüÎ1ïéÅ¡ºoÔÆ£Ã²:ƒûÙ3m¶û¼­•_pô|ò’ö<]Óm Ñø—žCSJGXþƒ£{o?¿r=^• 5¹8¢4¨$÷lé½À$Vä^•¥Ò1zÁycÑÖ}Š 4u‚(8ªæw³z1,6`ŒÙç GÜŒªÓüÅÙ!Ýnl’²  ¬#DÂ¥Œ`‘¡B€iĽĸ@Ÿ8zN0¾RäKÖ‘h,/í³¢ a û-d¯Ô‡5t¨g’QD03øÈ×r•"H…[¨@JYi|êà6Ø?Rb UoaÚÄÂJëI¢Aˆ 'A@á“#ïvP´ÿFbÒû€ ‡#-˜3“ŠúQ Qø~ChÚ_j?Z¸zGò(ahudÆ9”°ß 4K!͘~Ç¢(òÏÑ&(„°È¦|ÁÞ,qbcò:›8ßj³…$A-¼2ÂÓŠŒ¦‹.B6¨ðüݬ†E ˜§æ– ¤#ÚÆÊ4D€Õ™.[Py¨/éDü º?‚çŠ,žѡa’ÐÄŒ'²¾Èë-8¨…¼®&îpHZ0H’Æ@³Pš`f‘¦Váeá³Õ€Ò\–Û‘VèÅÊøT ÐzÍAZ£aøµGÔ´0«Hê‘¶?CÀ,8„lã·wŠ?%ôc”mÕ€"ÂÕµoŽT“¡ß<É©ùžZר¹Ú’ÆÊÈéӖʤ}1RB¡ìµ” ¦ƒºwÂC–£ NR ­*m?;^‡Ї` œ\ vêVOǧd‘\nÃ6Ó0H!ÚÎ# ¶:WY¢×ªb??I24>”‰6™1'd®µG3õQ}†¤ïÈÀ úyiË™SPáš’¿¦CÖ’Šv/4—°Á Ý)uÓZ$Âø6]³wEÈt|èâÝ-E|äDFQjÊ!²[d) ?çÆA¥ÄR<°q»Ò!ó]ã ¡¦¨­ES!²Fò= ½ùáÐÅ›™ŽÓ9ptF£È§?1§d:#®G,i+0d|“¿9ÒŸo©_€? 4ÞÂUyhÒ†1½$Læ%_ò»Í³5B$Ä¢™¿JØ$b8îÝè4Á>VÛ3GÏÓ´°|õ±÷ ˜ßÀØÌŽ>óÂǾ¤y%ÛL·“)똓0ÁÒ*²åšŠ»,ùXZõˆš£AÕ«IM1Ãg½Q.°ÿ.ö©Õ–NûÜ%j4¯ÑJ®ƒ{-“õ& Ò#u«Áiºâ' òœŠ}±IÚ³',(yB*H¹âÅ;y,7šÍ.™“9ˆœ·0À2ÿ¨Q˜Zí´€˜ù޾ˆ’g£#·Jüè—ª ŠI¼·‹Õˆ lÃŒ+øª; ¡"qX$ ¬<{4‚1á°Û+K~5Û¡¾3ÏAhþ­"uÂ'AžÚØ£Ü;$ò¦Ûý.s˜Ñb#}¿a¯0™µ4IâŒÃè´ê4%™ö1CˆƒÂÞ‹޶ Œ"9^¶°ô.¡¿Eê!2Ê4Áì@šˆ*J–“E¯9˜1Ã0ˆ’ÄÛI¹l?)\)а½~3«ñ¾ëÂ¥œ™¢X°Øñ‚P’ÄW/:ì¨ãŒÀÃF-‘A q€Æù¿7™®=ìdµé%ƒ„2Sf±±¶ˆƒ³¯Y” Iï„Aò=-z$"P¥“¨'a}ȃ³™Ú›x9 @† &Dêû a–cb®›KkTP%ƒ0!3âBáhÙË-¡È£DÂP¡c³TC:ù$§tiH!iÀ‹3zÖ<ƒe¡J 1ÉÉ6¸.A)8#É#k-è}¤à¬¢8ȺAѤsÞ:4CX/ú¹, @tW¼2Ò‘ÒT%Ó(¶1cEÛ‡ùºfÈ[û:{8Œò ‰-ŸèN7´»E‰ÔÌCDcFcÁ³rX?p±¶Ñé>!ïÀt5ò„§b0ÚK“«elc0ÇJÿ@˜º X;ü3ÀsG#z¦J3Àà L¶¢¹Ë+´A›¶C–$Ò0*[ˆT“¹sGÂrÿ¬T-}›(ަúÏ:Å$KÎD•hô? ‰=§º<øȰ‚˜‡›°™ ü‰• K#ÉͶ¨Ú762h8š• ÕF£9FÃY¹‹ð’¤€,5ÒèØ<ûOH è(­CKŸi@L¤ 1x®B»XÌ{}Š»C¼¹@2f*d©Å''ÚÏé*1:€"¹ººÃ­¨Ì¼D´­9½JM6{N”ÓïâD¡P+œ×A35£qì#BÑJy”Ì¡ZË“C¡|<¢AÌ#Ë—Š®D5*Á¼h¿€=Ëä|ß+PŒJòÅS“Å:èÑ´i¿G’¨Ì˜‹B6RÃ;Ûý¥ H ”ŠâïÍ0Ø1³RÆ$%—9ˆÑ>¢îPyÆá¤ƒ.­H ³½3¤siµà}”ÒO©ô8C‰'3 Ð;Å sͨ ÑÜÍùµ¬ð³%-%B«ç•ÚC3xÐí@Í›ïŠS»(T‘F$-Q{M¬ÂN»ýTK¡Â伩¨?aÃtCùÙ±y}#²0l;|t1 rÕ`¡0ÔX,sŒ.8kÌ ;E&ÓÑíF‚³É‚U«fL ’¤ø˜Éb5:I¤R1Ó”ô¢¹ú@ 15ÃÈDb4ÔG%쳫u_>ÈA醓R*Å9»¨CjÖt 3OXr«—דמ³|¥ ÝÇ£<ì¾%t•‚ŸÄt|Óˆ!±ºŒ3‹ø £@¡Ùù‘Á­=‚¤69Š ”J½JY3kŒ£HxÉ4%ƒx¢+óÁÀÖŽT¬DY[§C¼(ä| ¶¬@(Ë<Æâ¨€<ëÁA% pV̨!LºÀ}¯XÈ›ú¯:²rªe?’Â0.^Î|:‰ÅÎkçG³ĺ!Ã9rŒÚ#ž³Ì MØ—:òØy¾2<˜ÜdFÔ­TÝÆœ:,À¤ÁÏÓ˜™Ê†˜“ÉÓ?ýè«; ”ÒÃÔl_ ,’Ê¡‘Óù¾Qýi• I&I(eñ9Šû‘íöʹǫ¡XsÚG>ií?ú÷Ì<3¯û²,{QW>³ˆÌ-ãÁ"AòS¦ÆËkx¶«.¡I– Z¶ªd[•õ6µ· M80«ÖóÊŒ5Üš@ÔÍ Á½½ÛÖ+îN蘡Äà©E: ¡Òs´C£<à½\]­õçP•…¾xÀÓ¥ ,RÃÈíè]PËÑ»ºŽA›g™…”‰ì/€Nd$•ã'Ä%qßH~Ûö »ŽÛK]ÉÚ¬`& >ë"UmKÒ06&Í…9Uî)‰ìë¦ÅRiQùº¬cƸ[£/݇â9ì#ò?Šü@Zˆ@%¤’C®Ä¨üH‘|8†Ë{È2ÇuŽ·•~• ßÚí¥ %ð1¹¬áÔp® =£ž9¢€+”(‰ÆPûËâZk cb ß >¯âò.`|Ô™†©Ø~fc1õö^Èe?ÜæãŒY@Åq µøœÔÉüˆD˜Ìd$í• ÀúL„Ö2„ ^éÓ±CŠº5<3Ø2èÂFð‘,@2ín”uu¥¶`û°U‰b2µ%3>€ ß©$7ÓÆl«+JÿÁí—>-Û»ŸF!Y’Ûÿ›^yÚ“4>þ=W•´1 0å“Q4ÄÄì ]l#–¾dÎÅŠO¤™:bPžØd éUÕÙUÄbÊ5Ÿ*yK½X™QO ª(åû,kb^Œ¶yéMgÈ91õ<\}àV6²ˆ€¯™Ë("³O ‘"™yÔý8i¾n€EŒMàÃ4bìC`Íy ^ȃÆ\M3ξvÄ 'bã ¥çd4ŸNœCêmë&l‰ébž¿Àc >ŠÃ¿ú.4ùòªXX×ë iD-ˆ`†²‘þ©€LKèM×ÒŒ¾ Ä–D2åký‘š|Þ™ØÂkö›ÌãéJÛ9á”ÎHeˆV°Zäh{ÜEƒ\ÓÁ¦eæ7õ¿ZARŒ‘þN)«8ÕýˆIÈè Í•Ça}° 2©€*6›4|ÕaœšÚivb®¨A=m0æå elKž^…Ú í ‡ö]ÞÉîj9NIâ&\M&,aýVŸ[ ¥`™&AÁ±¤?ùYŒÚKd.Qæx¦äøñÄ ^Ô`h}: ¥¡„JÌ*ö#ÖÎñaÀ_CyØ‚2³z>ÙàlÂ7¢óçMèÒj %ª²³[ŸjšSËÀM6Çæ²å Y=ÆöUçó¹%†S>OìîÖM„‚”ÑE¾¤.¹såI¼•‚̽Ÿ M`Ã^ŽÿD ìÇ=Ú›9ëF—Óº,õ¾"Œ¾&w¼¯X·æÎí€ô0 ÷ìyáé¨ æôó'YM2CÎ;ïêV² Kq~JI ´cBî°l²óóÁ “<:5´‰-Ý7q¢ý‡â~²«-¾ÜÓÃýe;šò±AjV¬A³vÞ”Êå©ÃÒèÑÙ¼öG¡ç)ä´arÃ>Á_”;¾ÔsÍì?åtq³ÎÄ4ˆºŠJ7LJ‡ë<¨Ï|(g›?~À:dw<ª¬fï%¢3"õl£˜Þ õÎÉQ“ß] ƒ£N1mx«ÿ¨goó<–¢æÏ ˜‹NËŒÆÙ¤XÞÌÓo=ÝÿA¸ä¯È ïož³€Nˆkâó’BOçÆép8|D¾±Íìæp‹KèÁÝ)ÑÖã±i)Ì^׆ê<ÆA5ïq¼GbEx¾R¦çõµ’ͽt)rÇÎϱ ¤"áì7 „:|2Ù‡ÊnÚN†x¶×ÌŸ‡ëúgÅåRØ¢(DK ڡh?Õ¨ÔŠ?Ôãi6´o0 Vq¤LÇâE΢¤¹ïå68iÖ–¿¯x‘¯Þ¤î²`1¨‰s#’e²æy0Õ÷‰,|ˆ”Üu3(WÀÈPÁ=7CÞMîj5˜?lX®ÖXUtò©p—\7¸ñJØ®»³ |„˜ÜñˆàÁ@Pp<%ý ~Ã_ø[øƒ€€xŒ^4€à¯øŒLÅãòPŠUÄaïÈÔV;†¿eXü½÷;˜ÅgÓùüjvûšÇcñø¬Š*¦MeóÐÖEÕf±˜¼Š# ¾kÔÀ$jµ ªÙ@¯[E‚"¶>-ÖY­–i5†ÙdRúD;C[Ôè}‚‡w‡‚pÔø¼Ö¡ÊãTx4VÆBäXø.^K'¬ÄêQJ#Ø´,Ð?S‚Ít™<ÅE3“AtÀ¤n±)–kaºHíæýÝêôò*¼.ý±áÅsò­ŒF;³¾ºÝ<ô6÷;¹EåøÜžRQµ£ÄlÛ¤7—°z_¸.åVIä¡Çb4Xý—Ø', ˜É©)[þ~#àDëHÒ:{ÁÊâj°5‡û‹¾ÈZ†¿B*b*¡¥îè× «ô¤P²¾q ~‚ÄÇ´`ˆ¬¯j§n š›qÜ`{+ˆ¬>ª¨mÛR¥©ˆûÜ?Íòm ?)\•3‘aú¯.ÂFÑ2Èœ–C ÚÀ¿%ïÂ<È%íJ쉿° &â³(šŒÈ% {O ŸÊ¨ªÁI’¡¹ÈlЪÀ°‚ó)±ªô§c.)½ -¼HܢдlˆÎ*:¡$=1ÃP‰ÁIÖÞ+qñIô›,¢ÌÚ K´¬ëqE ëR#\ŸÒJ/¥ É·m½<â!q]4Ž u“¾…ÙUµBÖR›&÷U­ƒÆµ2TÙiYÈšU­¼± ¥„›S?I¬­<-ífÕNUêVM½‰7ÛÕÊ”ƒ¿ˆzj¿FÇÛbŽ×â&¨-« ¹ «åÅ­%ã;< 7!¡xkÝ2^é,¢Û¢20äÜMµè#©|Ö°¼ˆÒËFÒwí3Š^0"HšË+"«ô¬®8oÕ+Bq¡û)z]uÒhŒð‚Ë,L¡'vôÛÂulíé±’ªŽÊØkõ¦Õ@{«Š%6¬Šª#TS¨,ÓV ©|㍠¶\ÈÂAKòý´¤K- ’»Sêw)¶(ªÊ–¡˜€ ®*ªÀ¼S#‹ÏØ‘úáV–¾}æ“È ÊŸÔ]㦽bQX#öö[·ùøçß&>Gè<{’uè:>¡¬²Ãc›fìvRØÂ ÀâÈZÁ´®áe×S&V‡¬©{sÄrgì2¶NÛHôæ]SI¤x`üÝ宕¡1¡³0²Ç·rW(ìÉ`"µ°¼£÷"í­«¸R÷]Ì]t¥„þ?MKþ5.¡K:U¸a8eù »ÔTOÞzSYà BüòµzŒ´‚üܳ.TÎ9Z-”¨xX sìÕxæLÈ×ñÞ!åp—òòœÉK\¶ÅºKÑ4kÏŽ²€ŸI& 8«âKÜ’¹Zæ¦ÆD˜É£[Q+)ƒ¹¡þÛUqˆ…ãú $Õ—qM%X¬xŠ!û®=E±–¿¤`‰•A`,­¤°6t Ù‘ÏdØ~¿tÒ š %ðôẨ/•ùÙXέ[­ÓHîà$WiË„ÔÂvBy%‚uZùYDH™âQ,µ:¥ÑÔ›ïY‘æžEZßKülÌ€ŸÃ™$ÕZSe¬>@ùG] V‘AÁi5 £*+|Lœ§d‚PSgþ90ÖøâÀ~˜1ÉÔ%b;#Ðt mÍ:Gâ¨‹Ž úÇÑø¨d)ŽŽ²u²b4WQ`ao“Q¹FØY+„¾ ´èÔ—•Ú‘•î>õ@ó˜œ:påVÃC Ó$RˆŽ ¥ì·âí<}óJ”¨ˆ€‘ 9ÃY æÓ6¬>Ú3<,ÀÂÇè°gùè¨G‚_¼IIGì˜`ÎÜ’ÆÂ8à'jwÌsÊ×ÇõYZ1Òa©‰Jt"2_U.ÇeŠxãJqqsÀ¤¨ò’+…¨(°(ô”—œ+Â8 º%a(wà „€2ùëLƒ²®òÁJ·†ÍüH ‹È 8nÄ_hìT ìµÆ&»”Ñ%Vô"V„z…e ÚãÈ#­äJ¢¾[¢"D­\̰”£"UL¨åÐ,¯ÂJJÄfËônìÎÞ EVƒi!ËŽ<ŽÈ§¦œŠ ö­ÄV𠂉gX=̬_M†|fÎƦI…ZÒÂjÜF§Œl/Šyçh÷CRÕ⪩h žÆlºÃ þŒ¤öíªÉåL ã Sk¤ÐÄ䨎!& #®ú/ˆl6Ó…žê¢DŠPw¶ê/ŠÇËÔ:ÎtDLˆo¶læ~-ƒÜ"¥Pä‰è7.Z˜-ã(þ&°½ (¿ ``b `m:ÀîÌH败꠿""Ë(ñ¦A ÆÛŒ`äìJbüG¦`*±Öa¢wÞÉËûcñÞ‘øYQ%ü9îÎ JÚ ub›qŒ™¥ÒJÇz¿‰TjQ^“P®oRiθTÇž¤&.ÚkxÊkJhʣ¤Q¡ ø!´¤ñîò ²±"ØÎ‡žÎƒo¡ôŽÇÒe ±l„VxüQªf"v¤-`ž ðñ«bSmž­®öËüÚÒB_oFãžéÅâ‡éÆyCvDüL†‰ÖÆ+hyç: &t­Èu¢&öMrŒÜ_Cw#êxð"^Øâ¯#I˜$RáÅJÑŠqn@¦êè"^¼Üvèãáý) ÊÜ·" õjNX†Š„i¬ÕÅ‹.àåŽÆšc¬ÒÅZÑb c‚k3¯ ̈» °ñì®¶‹°ªrXñH´¼gU-nŒã2ð § ½"èÚ+ý¬:ÿî".ºÖÍ.oKåow4`]€c"xV;©Š=/Æ]jZŒ6ò òŒ JÊ"²”ǢǙOí3¸yOù<êæJo8ñ¸ÞŠò3<³üÛ1´¾ª‰20Õ  êã@ C˜š Q#‰¶4Œ²‚p-3ç$P>òË! ȵiLþ‹š`ðX%QLç†×òª†Ð2®ÌŠö‰'g¸–骆ôåè´ë x²˜±i× 1 Àù+êá‰ßAˆîyD±JjPU ¼LˆÚ¸›9 N»ñV¾¨ìªkÖ!/s@P<Žúà‹ èÜ´~!¨z0îUd&Ói®"sêr”d7/4œGÍ"Òð p=,ö4”òDÐÄEnÀð-²DÌš”Ðq¨â¡3å@ŽOfL 5oꤓÝSgpJd@©gÙHÏô^;4à}çU1@6!ÿ6iNކ†ÿÔ92J®å0X®€ùíÞ¶«1IŒîƒàr¾v#â£vô»¤`&¬ÕgS®´ó„…<€;óRWÃÉ)f ]MÁ*ò œiÕ K©#”’¹²j€oˆ6#¯*©°^µ.uPñ*ËÌq-t'ÏòUÃSYÆh,RÅ«û" (mNè«’¾ÛªâÅ3žƒm!'Þøo´¤B&DÆÄ+Ê$e$&d”VXº#õ](Úd“Å kïNQ@ú¯­+Q¡*¾±u€¿LK^e­ÅG*«i ÓÏüÔÓ\PB bÈ~»ôK¢D, ²ÙÈjŽÎ®:Â>UDžDnUhìñzIªIƒUà¼Å7YÒo!étÊ,¡>ñtÖ¢&T¯6Ó¶Xv¨k%i$M@eòu—¶Ï¹OÔ«¨üñ•„ñnœfš¤3àŸ"¼Îu—DhZæ#I$õò¸]5:†¦Ò(fo4v< ˆ©Ï3 OèÍõ3ŒNð/wÉè6"ËM•EO·0¶È¾¿'T‘.ORŠƒ¶’9åeC6 z‚˜øodWªË6äþ¥ tÜ]CN»Mz]4%#tPF>‚w P{ænT.¥ìK«Ì+‘ò˜‚?3䢨ì ÎÚ‚5Ïd`ï7R0y¥ugkäEe@¼Å¬‹HNiZ³#&¦ÑJƒ¤¦Ø.ÿ ·Yòün+Rk;¶Š´.Ÿz,,t±2TÍYUÙK cFL¥h£/M™> ÞRkš¨åOoBØ­T@‹KÍs²:äUþŽådd“,]ð­këi…HºoÊuH²òÇ…‚†lc êgüõ´urÁ[ÿ,TS 怎w¥cX7bÀ÷X£*&p÷wVÖsuk^Üë›MØRX©rÖ‚$¥@•Ì`Zœ[«aD˜Aõ»bB© DĬÁéL Š.ç4í,QBDÏÑÂX²RÔ”” ¹#MŠH-u uïg%@±÷v¢êCô즪gôÕ¤EiôUgX‡çO@6;BÊLl鱆›¸›Z¨ö_sæ…¦M·Y®5e¡IxXÂCCäI”®ú·ì:Â4ÍO6#Pà”¼ãÜBjl¤&‰ RK.m0¾ûhNA©ú-™ 2†iÏŸ¦Ô!%P@äñ.ƒhK9¡…³Jôsj…k˜…"¸îÕj¾K Ûm úÀ‡K¯{O ¹uÉ T“El¥~è߇|‡Z<Ž´Ȩ?½Ò{ß*–"ïÌišpuOZî!ó“„Ë(è¦5Ѓ­I×^ŽÏe3Öt+’ŽN–ÐÛ¾Ô^< ÊÇV–(".,¡ãõBÀa¤­-ËÇsåÏýŒ­n¿1†ز1? –n¼níx;ý¨(]’¢}ž¯¡ˆÖ˜Í•™FSô k½Ìj±çbð$ìïì+_ß'¨ ·é¶ûV¹°añ× †Ö‰þ}òœ‘Aìn´a*×gÎT¥P  ßy.({Õ¶9í5»’Ä‚þ?à€4 ýBPØp û‰BñXT ‚FßðˆT~ ‘aQ°4û)‡?%’(d6@‘KˆØpFæ‘xT)~ȡЧ­I•Ë&ÐX4:G‚P¤Q% ‹O†Â!iÐ$û¬€#rðYõi®@ªµh„"p¡S_𫜠c«ð¨uÃ{ƒZ_SyÅZBÐXÙóúï§L£0êüs1BÇæõú$7/‘bå5ûZu"ÇÉrviä²ù©¨æ Õk´¦’µÂ`Ø­Jë1ƒWìvXÓ(Ð0‘º„fcΆÜp’*Ä ùínn4,%ë1nˆkß—îÅ“[kðG`Pë ¯îÕÖ¬ñ|’Ȭ0¬øÖ=‡óˆ†´èk¬Ò§LŠN$GÄ‘/®Ÿcrš&Œò2ø¬*âПí&ÿ¾`h‘./Ú3 Décªè$râ±±)K¤Dn ÐÎGp äŨsà”Â*útŒ#(òA©¢6«=Èj¬—-i¢*ɤ +ë¤q ¹JšS%¡oÒ )Q[ðáGK‚pºKId$€2ºÖÏ1±úí3 ÄÔ<èÛ›4<РôD¨¦(Bi>”²zú1ë‹T#p¬TÌM'½F L2ž‚! ÝÍ/"L”%M‘3£ˆTMŒ$Ž8¬Ã6߀*úh´-3 Ã0̪ú… 'K‹w2¨ ÛÌLµõlª/½93Z ˆõ¿¨2âÀ Œ$ÙiLLÛ$Üg8 Jµ…(}¬­¯ ìŠÊÀ¨’£a6@ ‰TÔLl€,%¾ã+‹h †Å¯ŒU•®‘O·MhZñÒE…Ó8J 3ˆT©Hßo„€¯å ʦÌú¡(E±e¨„u¬Ï»H~¬Ñ ‡Ìgí7V@˜–(¶¤Ÿº!ûKµêW²oò3djóUƒ GRÖ®çhÍ@¨P¬ÞÞz,…m æ ‘m¹ºdQåÞóÚ™æI_@ïÁW’<û²€”›a„ï(üZ…Xˆ‚…íˆTû9˜ïÀê´æ“È â˜¤Uï:V²†ÌñgâþŠÏ²0tèz!›ªØj ÇZèB€UÂÓ5ìœõéúßZ¶cb–ª3Ȧ<¹UTwZ6§éþðð*Яµ´íë'ôqúõ©0¶ï„°·,Œ½ÁG Ek=ü’k#‡Ê­à,léų£Hƒî^¤Xƒ:u¸r€je-× tbr[c7~ýȸÇÒùYPCÙ§µRèˆ[“iì}%$Zu KlU|äúéKUtîHA!µNú³mÄœ:wУݙë&…̨¸(óÚ8[Ž%5¤×âRSëU1êíg†¦LÞŠlC}§ºw¦‘ëgý7=Ù? ÉÈ•: «2Ÿúi}ÅQ0'(¯#\¢8 Q>ˆ2Y–(ú>/ù™¤ÊËä}!E…-øó–¤š, ?æ‡ÉÁ„.Ù½ÆäÙXi4[g†¦TË0˜Cé3“`ÚÀr ŒP[PÎD®º&!1˜€À¤‘.e !V‚I؂ʦÒlXs&8D’*Ž#1œAŒdíK6”©Écàfq:ºåÕå‘'(ãÕ5æîp!ú9_±Ù Ì·ôp)yÿ{í;8Bn\4^C(˜î’—j¨éÀç®R´dM"ËÖG‘ÎqÆÓ$¤‘h¢ Ïà û“\0eÓ@GY;€˜tU£XƒÜ˘j&SÈ=éȺ‹MÛ´Þ8éGÇÒh\hA ¯‘›—–°dÝÿ‚®n&ŸzˆN¡Ñä~æB²{*ÛÜ5yt Å8*‡©ì¡[‡0´¥Ãÿ h2¡JgÚÒ #"Oý·ÍQ^R‹kQ‘ÜK‘‚ÉçÊPÈËÃS´Ì&œCTEvV°ºê—aÛ¦X'Äݺ›d?Y9¾Šå|UÙ_˜9eÏ.¢˜C»Ví÷*í(ÿØÈ6æ£}}S«óŸ—<ÿ¦êà¹o96\Ú· Ex)‡µC\ŠSgÓV,I>¾ç¦…^])(½bvÿD% †Â%>­zŠg¨*˜Ï"NãˆÛ§Žª=ªÁ—ÜŸjŸ¿‰× ã4“apú(-i²ªyt©hW8$w2ûŸ!0™v¬àÖðTS-¤¿–«Y¦ß…ÐZ±»Ìc-8)X>ßô®…wÔäPìgsâá Nãú MÆßNH˧x3´ÄÜ ú!9'Xü}ª»@Ûô»C:q Q­J0ó'mò ’£ÖpU®ÐûQí†m€2ÌÌŠI†¤á ±¯qša.1(ý]®±$£bjüáÝÆ-¯Šüy÷4å€û°ûbX2ÛÛ•ÅJmq,b/dñµ«Î-8û0Bó•¾éd» ¼ô=Îfä¶'yrŽ~¤F„¯ ÜßÝ7#Ujšlñ,sà–&—^¬Òg»>Ɔ ôäL¡õ¡Ä h÷*ÜÖDŒûœ5zI¤’\¤Ü¤ÐÏHU ÿ ÉyLóûmù­ íØA–“ÍÆ”)£`¹BUŠM¼êkCßÄ€Xùª)'®ŽÏEFûdà …ÇŸëÖ­f1Û)4—oÄq”öÕo[ï/&´*šød½¹KTE§±¸³ËyXRÞ>ÐGåKzMt¿@<÷Ó].tï¨êEåÖaÇÓSG 7¥²'A ±oÄgJì½h@²¦»$<¼$’úÁO{m ”û:Óó^ í4ŠÜMÞpýB¦æLnV][ðsÏzu>žnÚ©÷wä:+î,ž{Þ’ƒïm]Ç à<6"=Ù@³óín ˆ1,ÈEdæåN§®–4ú7}‘”M+Úg ŒwrÈQ¹7rï =úP Ë+ª(¯¯£®ŸûN*“ª{ˆ Š‹3³¿!¨™r° ûÑ?J佃9©[ ˆ ð{Èš2 3ú¨zÇ š¯ª±2 !&-Kž¬1׺†Š‹Ì7*œ ;4 Sìp‚=ΉÂl­šÝá5 2ʪá"Ø‹ ˜µŒ—ˆ>©¸ûÁ"Q’8ò*Ê—©Š ÀJÌŠŠ•/ª% {‚±½!•ⳡÿÛ0¢‰6ò÷ù ±1Õ¨ô#µa2­‰, ;\€)©ªXd,’’lj‘ˆsÜŠIJÑ—äAB°2 $X¡+p~-Š»°’#µzxPš/¢{ˆi °™n±ÁX³I©Âs·ð«:”<‘ ¾J°1 ¯£ÏŽL+³vœkYŸ ȸÔM‘—2Ü<œq2¼¢­¡Cy%уšÿ¶(À3n°3bDˇÜ9ãk.YÎKÓ‘Ûj$eÂòW¹˜“¾ ´ºÛ=µ;6*‹Å bª‰˜‘ ¬™»"kØ¿“±›ƒÃ kHt ¯â²‡¼)(à#ª4)Ð|ªÈûš{©´ŠŒyB¼5ÅËqÆ; qàŒ Â*]Š˜î¼)Á‰LFª:§ –:º¸l8»²#3t0Ë¡Ú?ÇL;’’q0£:>txˆÓ’&·Èà) âš1i »GÑä"k{0Tªšº¿ùʸ÷?ˆ·q6B@ú?c…®ã4³Â_¦铪µˆä)ˆã Úì>+ìKkžÔv ådc;£]ºùÐìdäo™3¤$bÊЉ$ ÷ÁÜ6–ƒ 0Špš¬2‚§°»¥ô"ë@–£ÖŠHÂ=»2ý®Â|›Cšš›_ÆsM¾cn—´/)òg>`¯‡¥gˆRIT…Q:ÁÁ­J ·OPA5¼|ž·X}¬O ;’Í1Ú =g‡¡Ã(¬šr/Rí²ûÃÉx±úÈŽ>5ÊûeL[¦RØꧨAÏ Ô°®.ÄO¬²»/¾‰ÙÎ*¨Ób (é—UÓ…EP9 ÅcSºNÂALÁ¥BºÆ}U0D?Q´K*«´ X€½·£¶ Q¶оí>‰dqNXúlêIDøÆÒ÷™Ãš%lƒ®ŒÉ™A0ý-•«èØáâ!é’¨ÔKP€+ªÁHå ЩÁ@{@¬Ú s£=šJȪì2¬ŸŽK½Ç¥^…”Ôÿ05G: **iÛå5<‘)X™5¹ªý‹µHQ‹L†Fš‚E@Eݽ7Ó@˜}aÏCºQé¹HyRYŽ¢SÈíI!¹V͈ÙëkªŠ—©}ŸÈ›½:Èœ[Òÿ8ŒÌˆî:\ÀQÐÌ«l8ŒÕŒ}µ“d©)xÍâ<ÉçÎý'ˆ¸¯è³mPaà ¥ßÊY”€°© ›dÐÛÍ1 SÕÚ+µFúE_:¼À25#¾:åˆAß°i./+¹5<ö®]‘<ã:±nŸõÂlґݲ‡ó+е¨>’™[›Ùç1™¬U(¿äµR‰’­âKó¾ÝÐ}׳`#Èêú«Û“®A‘&¸ãö“KÁ9ÿSsè¬ÖEyV´¤ÉP„ÍæÚ“‹Ms 0ûšÔí”`%ïI¼VÌW‘ =úôà2ÊB8º…ú€”A’9Õ?ÙÁC–1a‚ºE‘)4Œ @ÉÄûö¬"/Å:åœËK¥¿ÀÁ÷öºø|âƒØ5d7Ãô&^$–â=õ—Þî4+@¼œôtÆÉC£Þ‘ÿ‹—ú€9ߪ*4B‹ÐID!.$ãJ©&´æRÓ ýŽÓ Ô­#ÜÚ ! ^³¬ œ ã9X ôeHáTEj+‚¬¨ùÒm¥ q.#Ei‡Ü[¥ ®µ…ÆŒœ@`ÙÜÉQ€_½¨¨yLü˜“h.Äjª*œÌ@è½2…0/jÁò"Dô9”O¯K² ä1–ùkвz«¹÷b½ï²° ¤ÎeY8ÜØÍŠª‰Ì–ã‘Å“Þ}}Ö=¹T'˜9Ã7½ëË4´äVå…Pá!•áã/ª‘›A›Þ[ê“8Žk@ÉjôÙ(´Ÿ"s°Cé¡É­±4¼u1C’bÀDÜ× ŽŽë!ÖnÖ„9ëÛf¸¨†Î¨¹®.*¨]éºY¶u‘É»; JÉß:—ãÓ¸ º¬f0—;tZC¯¨ŠüaG¶Š>¦ÅÐíb‰çM|Ý+º 0¹†°6ß9€G/ Œ=Ý´ŸýÜž³% !Ùl?ÅÄÎQ6 X§×ø]ÜI æ<øŽdjR\{²LŒGjs椑GëB+©jOÚÆ æK¡›ßÚ*l{(gÚ³B„ØK aK<9„Äd ÏÚ3Nìl(éM^W K.­~^ömºc"Ž«dÙ¨( þ~ àeB»Wƒß&lUW)„³¼ÖÀáaüAn˜*ŠãÖ² ž©˜åä@2áÒII|| UU˜bÿ·*ãbcKôäÝ©¶å–hÊ\ã8uüˆ–áåÀ~*ñŽõ<+{N£W¾ö:çíÊ \ ÍC3Seø}¦lÂè~Ëöí Ò”`ruE ~Ú2?³[¶3ØèË–Ñ|ÿ²j £…óVeXe#­f#@¤”°FÜwÏBs˜Û·¢rP¾@‰VMƒ‹Lšî¢þŒ´¤ZöÅq¾ãA„ºl¬AÌÈð¼ùn5 lé€O0ÆŽD%NÎljÍB9•ÍR3\D©ÖRÎõIAn¶ùQ6ˆ7*rìñ6†äz|ºÙ& ÎljÅfíälæQdÆúOKhfhH2þ`m^ ¦±˜WÓ@ãéo©|øâ­‹îÒo_äŒî QÕ³Î)EÐÃź±>l‡Üó«…8ÔýÙ&¶NÑ.΋4¿ecDàÚ´4µl­‹õ$£´Šåhd)ƒ²„Oî²»04jܬù¢ülç‹ß°A:¶í|Œ5œ—Û]{h0½{? ígù&Àh Ë8‘°».è ¤ÈÎ9®Ï|X7~ãð†ºÝð‹ZXñ¶6óеup¬\oýÞÜ9ðŠÃá¯(eV€1\˜j,4á¾ÇFl¯ ­Š”aàùM<°ÿ%äÈÉÆdkÚ垯XÕ.ÎäÇ•?lJkóDë¥U–ãÛš›è>dš¦× r=kàâ‡ì£¼JKTTà§>ƒ:‡¹x‰a n{R»ß¶Å»fPõÝ‹¥Þ?¾ôÊ2íÕxöö²S暤°1—z‚å.à¬1å]=“É\ì´Ãµ³•`æ=]'šosSLj06$Îk s¦®ím°¯_ô;uÉ%°Éß?âcÎ,,˜âZøÜÀÝOR$ `¸6Üe'R沪,ÁL§,Íཬ£ öŸ&î¦_D$Nað9ù6×Dû¥ Ü KaHµW#( ž¥V6ÐlCGE|Ž&²{ŠìhUäÞõ‰Å÷1Ëî >I r~f€>_ (  „?!Oèd4Äa°Ð$T ˆ¿ßq¸¨ ‰Ã!Ì<Fa 9dõ/–L@q™Œm÷(“C_³¹DŽ}†ÉaóÚ†QHã0§äÆ‘L—¾¡²‰ŒŽBþ”ëRˆÌŽM?’Dj0ÚEŽH“J¤PŠü&m°¿ê’É5ÖJ‰C$Ó·íN 1¥Â®`: FáŒÒ O™V|®Dc³„¢ôÌV€öHÄG1”_)™ýØ6“LdÑ÷ƶ?Í©” vs!ÐA6›8ŽjMQ”an[¬F–ï”G^ü¸þT1«É£´KòC‚I·ûãqë€dwÀG–™6Ç=6D²ýÏ–s¤ÞÐZ×qÓ^1³úLÁ¸®,ý:ið”5k¯4˲ø{B ²ò cL×¢040¸M£¨ï03ÂÊ'kÒÉ"©ª6Í;hëP‡£¬Z2ê5/r¾) ãT﯎jv†¤m²¾/ˆË¬³³°:ý){ˆ¯Ê؈")$ËDðâCÂHê›<+‚¸R{”4nÊÏÆÇòþÈ(¬š†LÉ 6çô¸”ʲ›Ä¢ŸÐdBÖt*¦=2Ëû+¿«„ó+/édØÂ>ô{‚HDb) ˜§­îÄø¯”à˜£êeK??óTþþ-Hšh–D v…¡’ò®û¬ r.¾&ÕšfˆÁl|K?IˆU /iÜ|~±hê>—%ïvß.Ï:7T ÓÍ…I³€3~\,\(ý4ÎS–éÕÐí EGÛõ3. ”„=v1ûn´BY£¨ªmeÚ‡Ôka¸À ¯ %3C" N%L®-¢£Bv ˆ‚9ͦ#¢oâ=¤hû©UGï¼–„cÒ¥HàñÝ^þ§YNBŸ® AqÊ({r8T°é"´jìÚ?M¤fŸµmFçCk*_ .× ÁYw£¾›ZwÔ²®äP%]=âÉ|(Ä¢ø ˆ¶±úêRp£Þ«šÛ®r‚$lRU§Ø<³ž€)’YX¿[â›a÷ÚY¤î&®€§–#ªaëË´Œšè‡½ïî~›*8 åP€;ã4”}J?lq¶c¾°8I¶ùŸâ—Ê}°vî,M£¸º E,â› 䢴s¿#'zâ@#÷vˆ4ˆËÍpèÞøŠx²Žþ81¾aQˆÀÛe)é,#ö¾rMÔ dмÂ@+„èt¾FÖpSOf´Ôaøˆ%)¤lG¹H¡üÛÅ‹b±‚´˜×),âS‘!IÃÒã]ë„­„Ó]ãús¢)`p²¢Ì‰²,~ZRÝ©»ZaÎJ÷N¤>¨K7ÂÊýgk X ù/Š#î~'ë«X€ ØÅTȺÌ'Y*݃0œKÊpÅþm¤# ÍÂ?>ýŸ—„ÆbÓ„´ˆ1´LµéÜ b2fŒ]Jf•Zöbx:È’ÍýqÓΚFUÑiè:–%3§Ø]øg…Ï^ð xý²Ä9¦Únçà;‡îÄ/5J}Òòèlhzœìpà¦L'‰›Ùu~°¦!öå]œZY›—äùÂd¼TϲKìM¢PŒˆŠoŒ§¾üG¨“y/¦q´”EÁR~ã*&‡¨YŸ/c[KnT­!FÒ£Ò ½«év=.â²+òÜ#ú¢°$"ŒOi-Œ¤šÐÑi“lò*)f>*c^4„ô†m ßÃ]ÖøÖÞ„ÉåŠD+n}ßÏž5¦n‹þoýÈÉ[wœ]•î—Ï8þÓ1 O8@Æ´ñxÔ­ÊLrsOÖá¦jrqçµj0kkr£”—Ö9ÕóCë]c[ŠÅƒ• úTMè.SË jµ#‚/¹mØüºP›5jöx/›6Ã2]·('piw<Ÿ¬%AR4Ì{ÊD„Ù %¶R|ŠŽGWþËAu®k¯ú?Jý˜Á&@Üø ¿ÎÛÛ¾a´R~bñ Ó«Êí½ 5QÇå¶Ðø9Fâ @Ðú#ºÅM–,&yèºy³+¯fSÏRíõH¡òîìßo«2;âë­sƒ‘¼o¼,-–þ`\×YxgE¿“hȬú4ƒ fdvÈû2Z42 žRbñ‚€³S\ê6äÅ«ÎwĹ^nàSÒJ$§zeÏàº)+ <›6žlÊÊ­KÕ ýºlw³BðHÚú³ƒ )ú¾<øqŽmbvÐíÆF ò¨¢CM¨`B6$g.®ÚÞAþöÆø €Ç&Æ0‡F˜ý/HòK¸è"®§Î |WbTlG/¡éJÏËìÑ l¾AøÀç£lFƒ‚x®(#Là®V¶"´;n»¥\¦ªê­I:!m ÀxÆfÉJµ® m†øèëâÎ ÈQGп-J⢨‹òxM} BYl´2ÌÈ§ËÆÈ ÈÈ&¤ ô$gJG„hJf~±¨´‘‰èTÆį̈Šx$fêÇu‚c 0v@eôæÍß êmš1ŒLM¬.Äïꔈ`‚c¾ÿêL!††KøÝζž°DI‚€‚tæ8ýOBœE`à | ìஎBõc¿ RwMz.%l½cÈÌóàÄ!ô×`&ÊÊ!z¡÷$˜,’Õ(FeÉæ”©Ð Š•îD¾%bò§!#Þ9Ê|¿)¸iÍ8Ì|Œq€,B^4ƒÕþ°Pžƒ)à/Ù'ZK. Ê†Š‘¤"ê‚ÇPÜÄH­í|sð_N‰n¹©Œó/˜äî|B"’Ñ/ ¨üòÊъŠh"©(d 2ãÁò–ðš¡ìà‹LX‰£Êm‹Üa>îC[ 3 FV"bÐêv™H3æ÷+ò£©O |¢BÛ Ù  Yl€ý±A¢^ÿm\Ýp$î²âY&MÐÑçÌìC¶æÍE •î€p¸õDö÷† yä;Ð òn\dÆÐÏ9Ëm)MÌ} ˆÓ%^yçꌫ4V/z­QÖ"©d‹Ôň”B^¡óÞUæ•d#)¸€,XObál<ÓÓÞí' ª~øCO/¸|o¹&ì­ É»Îü'ÍÊãÊ&1 tJ¯çÑ)«È¡å…’³bêg‚væfB¢ÕN"fÒ.Q2«JˆpÎM±É- £ÒÎkÈ£h¹£ºéXÆ.&æŒÑ‹=†E¨ ±*á4ã…j O$ÌßêÕ0“<[jЇ’#5Þ‡ÑÅ—(CîÄèDÏ–Ý%–è#ôܲÜgÍ.ÉR¾ ’R'sÇ@ÈnKb#MbÖ,ÇPe, ʾñJÒsEBœü¦ÁtF—°ˆôãªâkêv¢Xä 2¾&Ü^ ,oæ‹ñôÂñ˜LÏ«C‰ºã,.9Éö"å}ã„äße–Ø‹Q%ó(µ/ ðt †0TÌ#+$€)Ÿ6®Pþ¥heÏ伄 uƒô*(*6ôKvjÐËó4½‡¤ JC;d¡GIH ÂWl*ýŽ ¹§Æ,%Aj|É`“AõAtb¤nœŸÑjõCL|g‚¢µ.#’¶éˆ¿gçŒNYë_ Ñ"8Rë1Œ™ô®6ŒN. H›•fq3¡RPP5„>F]KóõK(M"êùíœtnúðÍÀrMÏ5*âÄãûSí@ «—KÒ·&ë5q²a$³K¢¤ÓO= ØŒ¬Â'ÏM§„*ê¡0•ßP.z¦â­F(Ë“€õN§[J ˆdÖ*½kò’12 n#b˜3U"_JªWsæì(çïï\Eú!Ny.‰Π1q¢õKlîñ`µjήPÒòªÀ¬˜Ê&$. l!´¸Òï̵ïgTlTc¨‹N-E'Ÿ-6Ál>²œÅímö&%Ü3Hr$ÄëÌÀ¶^&œÄå„€,ò€rXCd7<Õ-:çF~¢3ìYsIcøµòs'¥E<Ϊœ£ñGH§–œ†âΓÓgHeN ÀmÏ`C,°‰þd ‰6…Ç` Ù@ ’¬'qb)KA¶HžnAJ ûTDBLðÔ+D‚¯l í±‚@NŸoIU²øèRôf„$v™QLèÆ\ã%’];GÓ§ÔÚ¬žôÝ#¾vÕGPÌý³Ú¿/´èª a ȯŒ/Ȭ&L(Ýmc&ñ™(nȆ~9ÃèÏáú}“‘h“‡D“Êïàk»YÄòi’‚!V"×v_Šù14¡öiŒ²—ŽÛ8R|Á"´ë/ #« cü›·p¼GÑ K 5üÕl© MÝx$¯íÖìê°Ä3IMx<aÑèDÌÄjÁ9·hàÄ"æOõXAËÒOÓí„Pf_Ž2²4ÑÅ5L :…žÄëi[Vr)^pc‚ Ë_I2F † `,Ê wÙzöpƒ.3^®¦êiÿ‡GIdéæ#8©XJaáŒ-íή¯ôp­U§˜R"hÞ}¼È>˜´Þqàò7±q†q#ÙE3çmmÕ_rìãX …õoà }k¾UÑ’’3ÂÀ‹¹=·ƒMyL»'ý?b¡p.$ÇXÔ˜O=ÙŒõ6×G4ðÒXLÈ¨Š¡ØÕãÂî…Ýl !¡¯›33F«A4ÿ]•?T'ò‘ Á8L CbMH  à„ÕäOÉKŒ.8Jl'ãIË|§ò-m¬+ŒêGhÌÛó˜çr?i‘Sõ9n”ÊÖÝG—X¢×ñ™&ÇÑw`0ƒ¢ÝÆœâFøôÌ*z+tÏìl#,‰â¢‹Fœù#â·õSPÛê34íÅ[ÍÒV+Ãa2Y~Â)êæ%ŸKÙa·x‹MqÄ®è7~1.éµI=¦[0¦\‡²¶¸È,RºPP®;ã¿)(‚8Ðð´Þ¦jJp=š:7 )P%æü;øÿ^¸ì¸,µä@ÚeÅ&úì5Mb2©SÁÚA.TOÌôWÓ.ö !´ˆ²t@óÕ4ö\5nþ™½*'·•P@Ý0*ž”¥Ürê·÷Z"v”B”ª|°äÚò …˜BQQKU¨„b‹HRmR||{J*,3Jó2Îãî1jÁ!òiËÆbÓx3Ú®óï›°R…4Ö‡ÖÞ.,!’ö­÷‚&]¹É¿z§O±"‹C4ÁAù ô|ÛrïËI/)´ä‹4**6iÊÀâRõc²¼Ü7R°’o©*· ÷«g5Ú!ª”’ô)†0Ï#éZcLÖ´@bW¡Çφ¼ž;ªÍ38« N+W/'çò4‹ºÐûZÖ¼v¬ìJ‰s!øBŒóW0Lä1;¥áúÂò÷•ÈBýІDr€¯^JŸìÉPœH=˜³€¬·;…–©’jb z#hRy÷p«µÇ¿É)‘¸¸OGdäó ²nÁÓÑ­*‘À‘§føèúÈѳ+#®Âü«¸”)ÔÕxö«Ç–=¦6«,#—‰QË+x, –Aòr ªè.Q:*¾b8Áõ½¼.88a&A«i@3A¿ „ã=„b”vÖZ YMeÃUŒÜä™Cu®†ìfG¹iëìõÇŸdö=éæÃ5g]¹qeøÖ;•ÌtŒÉøî"÷•ùYG^³\áÍ‚ÿ/Æ”¿¥Ùa©?(e8Ÿ(3[WÆ…â’þÆÓà›ºŒ3w\\9ÜZ§æŸ:ÁrÞ  ùÁÀ˜T ~ÃßÑ+òÅá GÜnD_Ñwü‚E ‘@àp ® H¤R \̘EåÀ$ÞAÉa2˜LÝÿ*•Ïâò{ö3¾ærØM.£AR¡àzÔ‚A¥Æ`okÎÁ¥È£19›âٜ͢à[”*'@©BfR»…¥O™Òî@Ztnó5„T¤Q8¬*@Ç>r)ªõ§ÓãÀjЗKŸ@ŸZ|OžÁò˜®A©‘RáÜÌšqxˆÂ°9,¨aª€"s™D éÞ€wûGüÒ§ç û&¦g'âTáúø„G¥™Ôàp9Ø}Ö/™§‚}   ‰wá΢5I\fcñ‡ù°‘l7•v¡˜†¦hï1ÀC0,躂¯èzfÕ®Jz¾qøó½ (úŸÎ;þ¦iØ|$OäПL Ô³n°…:¨³0 #1#n¡©.ã®0ª[NÆhz ìJ ÝIÜ.ŠÀ’þÆGÀµ’AúŠ©hRöŠ¢o ÄÅ¡1Z™°. ­G郔»¨À,7 ”ŠˆÂô—·ÎkàNsCD¹?Ú3ÎHK+PŠ"°~½óÀ ÅI‰»I ¥è¼¨¸ëLÝ¢p²jTïýB~2h+72”>Ò.É,êÈóö)j|®Mk’¸ˆ¤LÍ.¢j[3¾ˆ»ŽõËðŠXÄ6©jº†ÅlÝ$ŠÅkBÊ0í}¸ó<²¢Z”ôî„ñÒ»½H,¢÷Ñéjì».ôóþ÷ψU˜¸ñ‹Û7YH½HEª•%=$(Ä•©íe…} Ku…W³‚&ÌÇjI`*à ­MŒŠà»Š~anš"©Óƒ®hJžÍ©x0ÒA‰‚ˆÄ~[¤x–]#A@3ž‡£)§LÁûHØv£ß"vÍ…{âÙ«.}Á=]¨ãP[ÄœßÚf´ò£ÈT {ìu41î-½ù……Œò—IL8J6NØ„Ùè<øæ=ˆ¼LÙªZ„0³!úpzò÷ݜщk· o@‰ÞâErÜPjÐï|( r4w&~½iœW S»¹U‡åÔMˆ/7Œø7^(jš!üé5 _šÄÉ›S%yÏsñz´ê>hjŸhjH¼af¼_“où¦ZÒëÌE€á $MÕJ[6ÿÛˆ½Ëú|d/>$õÝa….ìñá*_–“|%p7ըśÃHÏH†¥¦þ@ö3¦mO>ô.…˜s:Hÿ7€_!©Œ‚¹X‡³ uä<½¦DRŠás½"&e!æ ¨“¬ °øýÓR‚ O[ #3L–ñrCëX>w”pâY3-å»/bâ…"á"f¥Ð™¶JAW Ógªqó1ø(°—“[Ñ~)T£Ú9KÑß7ã¡7vé6%¢@Ê!SnN„e„21øè_Âÿ+%iEåúñŒ)ÿOç!ê<@fÊ|JW€§Ã€ Ø’EMï^4ˆÐ[˜útį2 âIY™fD¢-·¬Þͨ2 ¨Â¾Ò‹¼^EÉ)(G ‰¡L'E£%…<Ò“é¼>äyïsÈÊS„Ê!&üŒÅæ@›^¹d‰@Á´ž×JX"«ùž.Gp”IÌ#‘ÒÎTã!#ɽ.ìüÀõ‚žàkq@ DêÎ%ÈhkµIÇ@¢Ü9t$)ýŸÄà¥]²€#éQhöñRãQŸoåÀ—cäa¤1-C.EºÎ¤n]L­sŠÊ|Р “€jl”+䮎<úô…8CµÀ*Ú ñÍMh€òj’•©òJµBR›š©ÕpåH*0QóC„itÒ-³B“Õ*BFƒr»*ñò‚Ù 3h™¬°Â`ík;qp²+¤$VÜœ/Žp~¼KNë€ú4„ R²[9È:w‹KjâéAÌ‹Ê9OX/Nå­¡t]OºÃXêNŠØæ%Öêé!<ž¨55z­G|QRR“•@Óv¯ŸS*:TÞ!ZµÊÐÑ36+K<òÙ2ÝÄ9QE_’´ži(ñ¡~¥iØÊÒ–‰–13|©>h+‹jpë½ ¹]?+S%ëC—†…þRØß+Kݲ#ý ¯Œ åe“ÎØ²«P Yl”%ß1dš?[¡¦7´‹Ñû0N]ó˘¥J €.=PBQ])cºøß³t2[صVs)ÔöÒ±;‹VÚGò&“ ÕÇ)Þ‚1M:Æ„ZÈ1þ{ÒÕ“øõ«ã߰与íÈÇÔ…bk£îù›ü3ŒÉ¿57µºæ]˜ç….±ËúïNšöÀø°òµºL#ˆ,±\µ©@·YªóÕÂÐo²ŒSÐë¼zÉErè1òŒo>°Ç®mÍA:¡üX=ìñº¬[A~É]VqeÞ*¥„cpâ~!Éšbœ¨ÿ`ݱy /× X-ÛS¶0¤ºzÊâÙÉD08‚ÕѨM0†5ÆsôËÖ \ŒÜ½g5Zù´ŠG}3–xUTà=dW"HöB©•Žc5$§é©-î¶-Kw—š‚€••æ’b’ëî§sÉëã깬1=oòpÜìrMÌ20­l–á$ž²"®8%­^í<àˆW`|a]¬‰n×®ó0JÓw‘ŠQºÀ ˆv®²…ÈTØÝÄÈ‚?§ F’m2}ƒŠn¸ £¤½8åe¶¾›œ¯BsEhÂ4¹‰ ÂåÌPÒg¨æ‹"¤Ãü‡r! €^>P±ë z¢Hžv¸ÒK.Þ„$ÌäÉ´ÿ6!w•‘Qc”§¶DÔÅ´8~^úÉÌElÿYaŒe:›­{쨧aÁmen#f`ïypriTá5=ý<•qÒvû7ìóÛU|*yÀõ£BiY¿³§ž†å¨GtWæ?{Ň‘¹ §TÍùV´‰ß±ŸþB渃hl†¹Rç§$â2ˆ’'CÍim™$J5Ô “¤MfþÁ ¢hš÷Í"7#ÿE ƒú­s‡”šÀ­9p©@BÙ#¨”7êš#r=/ «BV˜š¬œáÎ ˜À³)Ã(4b¬µ“õ[ç‡Ù#0ŠåJU1Kä‹Û˜Ÿaš k›±õÑC*™a0ЇêS¬`”%RÕ¢Á©Œ 4J¼ZËø»‹Û¬|· ‘˜‰¶È²Èˆ¢ðÆŒq· Ò»z¿±è¨ g%Ó=‹aû’h£q¢HÇ0è­­3b¾»¬HÇ3à‰™±L¤kZ‡ê+šw¾£—¾YÁ.È©ó"§‹Ð™·-‰  HA¡œ‹R#t 80ŠIÐAÀ¤ñ¦št)ˆØé' DYÀŠ\6AßSY3º¶ "›pÌÉ "óä»Ð~™Ró¶jC(|9 ¬Šò€9ÒêT2+h(±‹&8³¥0Èé(´HÛ&:‹hŠ"à "i¬¢[@c‘‘°Ðµ*Fû# »ù‰¹È¼Z_’èé#Yë˜[ ÀJÛ©S ù¡Â‘xˆ‰Ê¼Ûó£Á)ëÀ¤ ‚&Å·¿Ü_¸ì3 Óâ!Qõ3‘ï¯ãþŠä:A:&Ô@!j¬-Ì+Ç3GµÚù¤ãÜ,k³¨b‹+Ò1€4$ˆ»G’2·?$"¤t-ô‚Àz£›÷°’™Ì¨k½p¬àæ7˵;u3‚¬¡ùß.§T’ØÌ²!BGœ Dc:*@‡µêp‘4. ¹ô>3æ"Ä0T2I„±89ðŠÒ^¤ÚÆ Œ³"[]•S!-˜›¬€¶‚Í,r¨Žȹ#€!ŸºRÊÃSÐ*àÿÁ눰Œ88Z¯:T12Ãò5“}Ê\Á²™Ý‰\ÊAŠÃBïEs8£r|«¦§!9¡o¶<™?"ÃLªÁb„ŠáÊhȳ¢÷K  6´½ #=Sá‹èÆ,}àÌ—ôÙ¯`­3’õÀ’ý43YÀésºk>±ZL¸á˜Tr¾l´„ž/£ƒ-ÙžEŒ–@7‡ó]™D%,iÞ!T®XLLÌÂNžâ'Cô”! ò±’ñ= ßO¢P °I¬4¼Ò€ pÆØƒ›p™Òè6´¨=ãФìg—C*¨°Œ°c½ÒÉ-z„*ùÐÉÿɪ®NÈQx3»>K2Ã0ˆ¹ÐÔÌZðбM#µ\ïí& äá>LÙøÒNyã̃&•RÏÜ  °Ò1JÅ8QzFª¨Ã¾€-Ã*·k41ÉP}™É>=@ž³²ô*ü¢l« üÆjïÕêø½·ôÌ ¹Ë>3j á ŒØÌÑ0y‰×Ù-$(õÆëšÆáäRúßXõÅð} õY á /êZVZÞ4HÔÄÈÈ5ìîP„N zšâ94zµ‰[5ÒΡ-à»Xú™‘‘ó§€-ÅÙB‡ÓD¯ù¨ÁS‰@ ßœBÇ¡Ï5> ËÑcׇìöIt×@ÜÓ(t,Ftš/Ѻ² ¹œúTd Qè ]g©Q¯ €ÝŒ*95ÍL‹³]ÒXÔÿ¥øé/‡’”2SOŠÚÄ )‚†9©Ô2løA³5I'œ3àãÊ% $¨Î%”¡Ô¬4­âT(³à×C2Ì«"Ësâ¶ÝO¸R ß‹’p©(ãžµÎñœ ßÚ™Ø •µº t‘¤Öº!L©s³¢ó¸³/x˜ Ý‚HÁ•S¨q…ÌŬÍ $3€ t¦Å°žD†9Â8½LPCVÏäĺ¹š AžQ‘§1M}€mP©È…²e"€ ¾ŠZY:@þ›ÛiÖÙ²‡éòÕÀªÅ ZÝH‘*ü­Lµs¼|9S¹ÈÚ¬2N‹%˜+ó¹òÔ©©±ÜòP<*B.%ê …9-åd½ÕÌ`Ü›’}¥@ýˆ<ÂqIæ¦2˜ÝQ¿sÙ=(P99”•ÕÛ­Ë«°nJiÜ6ë·Ùø{´J¨\Ôp–Bn€2u°Ô¢©<âØ®…Ä¡—+ùÑÕ§ÏëæEå§²»Ý؉ÈZbªˆ‰lHq¨Æ)Ò\l]û)ŠaЉ8QßÁ$é’­TªÓ5xJÁäá*-7Ä!E…¸"Àáž;¹‘?ÅÍ ›ø‹ˆ¨ÁÒ*%n‹²î867Ԩ߼•! Ù ›Ü§^¢V¦Ñò¡Ûµ›ÊÝV:¼æTè²’ „)IëßsIHâÖFãÙ4Äœå‰ÈìüN;^œû҉ɜŒØõ§PŒ²]¿3¢˜‘¡]ûÚUu-8-4#PA(›Ù”K…ý&Í­¹ÒQ·>£eÚ¾/$„ä¯É¤œOâù-Ý~g'€’6Dù\ûö‡ö hÀ¤½öPD*T‡°¬[;H–ª4¯ÞE6•Û.]ž ç8N*†[££K’Tf›²}¬.ìã’wËîGŽ×Ç‚?HˆÐÈŠ¡•%è÷ÖÅèÈ]œ§SÇ¢™`Ö<5a@Ì®]ß[t˜Ï¹GÒÚ±äÙ²6SvXL¬r-q:;BV¸b!^ÕÅ<"P:¢æ6½´×©› ª¶H-óÈ£´31Üf‰«ëöO NÍäÖ:† *É…Õ üæ–Z"Á‹Å#}œäÃܽnm $.ˆjuûs…5ìÁòNžþ>_FÅ.Y¬ÃÜ£nË!·b¥¤kb¢ÚJ¿å–ˆ)ŸÞ¬²ò‚I·:C›-i'­Y.“¡¨f|!ïÉ=ŒMÅ'}ä×>X9zóÏ­[=Hè5rU²]Ȭ¤¬¼ODÿáKÚÔ®™‹b©!ûí–ºÁ‡û»DTÅT â5v‡`½Í¨™ž1½$½3è1‚1Ù:Jc·È;2ìɲb^š’á»D°&ÒˆŒáð0®°eª,$œánÉä6±Ì»•Åà«K:RUAA]"ŽE0±#]|­´ÔPaCYDš†?cöMIaRso&¸3¦á=¾¹-™u›ÖöÀ*¾ZÒª°fì*ˆmò) ’êG£“óÝ ˆE:H<\߇Ѻœ­èë Å60‡ð̱KPvÌ—À•ë€|3Àys:ŽÎ$kZ|wK}*„¿ìízPua µx `Òjms¨²m9æZYZßJ¶‡3vVéß1:P`Ýï)\e‚ù¡`óßkÚ+,õ÷_ý>)ñcïF¬Ð.³XY ‘¢»\EÑRusa±—-\lUÎq€ÿçè¶2c»Οܦ,½ m-¡ã@•žÈÖÍ8¸7-eª9?@ô6…ýžo–<Ô)KécD®Îßü[ëj°)ÊÚÿ¨Â£\¨ˆšDû/×p,%®¨›ÄÐáöê¸ÎÌÀ FªpØsK§kÚB´GZÃ5‰Zg¼_ÈšA¡&•ôÎïg:T—;r@e’èk:J‰õ8B¥(r9}6‡x¶(­ƒÃjG¬¹>!¾ÔZ-v—/r­àÓ~jRé©þú¬Jú³çiËæZjÀqÛ Ëé>8UC EƒÒˆîý‚`ÀX@ÿ†A€/˜„1ÿ€¢Ñ(“ò5… ØtJ‹¢OéD8+–D£ò(0e,™ä²ÉÄæY(Mg’yDJK%Íd´ ìÊû‡Miê„YQÎè0Ú¥JW.‚F«ÏÉ,Ro+•VãùÕ–q<ÓfvJÔâÏhœÄ§U;ª©,¯Qf³)ywÂN¦±Út2gš` Ϭ…¶ne_xè5^žW£°êôR ùirzK Ãù+ße¯O&¹Ô³?Ï0/ÛüÊ?Kñf±úôÖ[ –f€Ô‹žJ¡C‹Rõw³ú…³Ã£º~tw¥££E°r¸¤~IÔ¢`¥0möò Q¾F±oúÍæã0ªÎaκ å£ â:Š+‡ëÚ&)’앤©ä ÷€/8’±+ í¤Ë;¤ÿ¢Écp–$­Ø®JÄJ†9K1þ¶ K ·Ã.c /ÀXÞÂLh‡'Lt2±€ ê4µ'H“ŠºÐúV¯$(c¤¼E'üšÑ¡Ê[J>2º$ç+Èâª=H$þ@ ªÑÉ©*½DÒRà´(Dr÷Èr(Ü;ÈT¬‰´hŠ%x¥¦¨¤Ç#ñä¦ü>’y&·4@È@¨D¶(ñ¤Ž”7H\¨‚Rè³ÊM¨‚X±"Ѽ.é5R„NŒ'Д›Y€IÒ:{WÍ´e?’¾«­iÿ#*äò~ÃNtŠ)múXÚ>ó‚4ñ>s³ì”8 ~îCê$ÔÉ(3øä©H:ŽÚp\pÂKîÌØù³Šrõ€NtÜ\¬t;1P™;ì¼xìÈÉ+G!“ó&¹ÎÍñ ÜPÔ"¤€r«üƒ]à )BHì~@ˆṴ<ÉD-€.v«£ð€ Z—`up¥Ô`%níT ,M‚UWEJ~Ê×Ö2ü€4Ø ×DzÚCO"eOŹeÄû·$¬µWUKq@îs­7j©¢’ns™:PÕ0•¾ö{4·^øÎfX9ðç)nt¾—èqª,ªA13Ø–n'õZ„$¼~ŒŽ¾§å{_aÇú;.r·/ÎÖŽ•ɘÏh3O !ØœX‰7 ®àKJ‹Ùdà'F[§ò)Œ½6Ý"¥ô@ü]I³©°ÞÚÖèê ~ Ë%wr–6G¼›Ý“VWÈ%yóЊ! –Ú'TG[89hxnEµKó2 £R:%@þU*[¥­B„Ôç&tâH2Æ€e /SúŒÐÁHB„Qê¶t¸Y©ÂLîm §ðÿ•u mï†l¤S›HRI\¯p Ìñ R§Ô¢‚Ôê¡2/K§@iä~6û‰Í"/Èœº¤=éPè{ÚHÐã³õ­ †Êbr™ýB©#|Ô# H¬ÒTžªÚ¥M`ŽÜ`“I„Æi)¡Í€u™L"+T¾Â.W}[ ‡«Joøœ~êþšX%6< þ;iŠÐëxŽ+%“V¡VÚ¶:}Dä0¨ý‚džªXõ` Nl˜ËaVœ£+ŸÇï¬6éVíŸù(@+>âùZH¤;cšGu½»nÇgñXþáýÅÊÀ™­d~TŸÊb½Ù§õCh}NîαªH"&ö ¥éJ ß1ˆRÀB J?2ic¬‚#ëúbÙ¼ 3ðƒ:Œ2Æ×¡MCf¡§ð€Å»IÓì4(DHA "¨"¯šÅÅQÊ Ç4i’å=dŠ1Hd*, úÙ¥(ë܇µ"ª?ÒR«¡Š£t-+Jœ{@ÈbÀš<’œL¹J("¸¦Œ£š9R|Ý!Ãp¬È¤p#ÂÑË ûÏT 4 Ð Á­£€³¨Ë¸ÁP¬CÊËÈ2¨'먡«dtÑìT‰³ô-AQ ɤì»rÕóAŠh´¶©"SÒ”³òîÀ¶H$C ŸÌ«TÞ€,[PåX å‡F»ô²ÙÚlÙþªK$åmÛŠªYVÉ4fÓ§iâ+'T/5–Ü'ô|~—­ró®TU¾å>ÏUž˜8 Çs¡“ñøõ,mCäƒÒëa!î2M‰p%ÛQܯ æ“Sê"þão«gQݯ3÷<€1€ÔU`˒Ƹå}£S‚nÒÍš©l´¶õn€'Æ„£KBx¨cÓþj}¼µ”Æ¡¬hû³;Ÿò£-jG]¯2ÞhO‡ÌZÊëµfgä‘ÈÉÁúîʨSê“8HBi¡ ûœi*%ƬTo´¤"{Â*´ï¯ú2©¦+MŠ¸ÊØó»I¯¶¶åF'î¿B°n-B¡ä›nÒh›©`ÐU~ÈôµîÊ¡µ<‘è êñ Ù~AÑã§ç[k͓ŒÛä 5q²–£ôW^0dAÕû8ÄîØX~Û÷Û{×}\l~>ËZ“ŸÈþ_5€7¾w›Í  p„f µ刎çû{¯€³]ƒaï Rd¾cÑS™s¹÷¿Ç“‘11gH˜°g_‘òGqçu$¶µÀò 1ö0n À`ߊÇQÊ5Ë-fж‰qÊ®¨Ö^¶û×…Ë2±BUÄA0Å0“Çò߀&¡o°’tæY‚‹áÑ“GØPÚ±zªƒ¢Ò\ ìƒÄM+ŒA—| #­à‹»’2Ñz¨GȨʢx¤öÚ›£M 7´®Ü|r¨-U »ã©r‘äÁ²ó2DNLK¤Å¼7e ׋ã;¯˜BAúþâÜoñ´~DŽøü=J ²*SŒÒ!<ÍẗÓ‡”)žQ-$±¯PÜaZÚ:lAýÁ×ãñ³,oÕ ó†?ó(,eçÂÒGØT¦=8‘˜:YY¼5•j5Iü~£¼coå Ô'6\cÀ]òêmžÐ ôe“#&¡$w$–ä)o˜øÄüYÔ’RÖ¼¢6Ò‘V…DL¯˜Ðb¤æ]ò‘lAûtöœÇ)>'á2T+$ΡNÎò~Za &e³=ýχGÝÚÊråírP KÖ’ŒxôÆž)—ÕìeTMdKˆMéÐ* ´ÉÃbFPAP^è~R³5^»Ý±t5ÿ­”À,„j¥”2ÒÓ MúðõmP8¸FO:’‚º3 ó®a´t®ºôÙª£,g‡´BRá‘ù{éÍ™-Ç<‘R™míxêD¨˜ÒãÍ$8„¨66R+„_$e ½× m]â2P1yY ¼ÚƒY™ÐêdAõ^ƒ¤xG)]ž"6¢¡š¼a¤5¼*çÎDgûSD28Q&Q"j|ùŒò ýS+Gf̱-+L°»Ísnðü¢£ú3Gµ^þÉúgn‰Q²x‚›Íi(L¥DØÞ²$5Dug™:P§{7Q©(!½ÒÀ—ÌÎƒÎ¬Ž ²YÙDÂb ª­ª6¬Œ{»0mßÈ¥ñå®2ž…¾o%ž°­±âc¼ðš$ l1æ–€HFÇìÚ…ê»Xk`¤¬ÄlÍîÆà òCñ˜Ô¡È?õF¶˜É¨ˆ¥¨˜ËW8èLT©ÕVÒ²yÚÑ~0NIÅH¬NŠ„À>Ëü2ù `M›¿PÒmpß§|Û‹L¤+¥!x˜ö)‹‰öY×ÔêÞÀÏ *ídt\¢Öh QLp«ïõA¬ _þymÌg ú^šµÄ1qÚ€±íWƒ[ZIÉÌú ŒQBJ‘’‡xÉ4‚5)ûhC]Å]Ϊ˜ø6"}Ú¦my¦€)²?ËKxº(dœ“£Ñ³D”’ —¡ë¹ßœ>h¶ ŽÃX´ÈO1ÌÝOH¹a'y´µv…²’Ï–B Š“êGºR<ï,%–‰äìÛÓë(\Å%#!š½>>ääyƒ«M%¹Hít¯b›µ²ÀJäU”åáUµ™Æ^ÖëybRn9í,W†D¤è½ ÄUW0Sž‡@}à£L貕Ãfq—h¾ÙX©u~تsÒ+fW Ñ€ŽÛd½®Š§Cä$È!õM焠ɢcHܔZ>§1ÖV}Çž¥ÒUš²”ÏKöó ¤ˆ&×hŠ[Ôë›KÕÔ¨ÑéãʤJÍãë&Éõ”sÁrʶVx§K°^±*¶È=K!‰:DÚ‡«µ}Ñm”Ð <£õ7‡*¹« Ûu)ªîÌ.G#è´åFtÛO²Vš1£Þ&&ZÈhl#-΢>*ÀµîøvŠ^föØLà) XÿÂÄEòi,`,®rÈòo°=Ç"Š 4ÏÅÚùgþ€Bøˆ+l(m´¨(]â†,”Úô²èÈBð<âÝ#Àì*@£B²é8#¤‰Hö} £àUê@eEkAòtÇ'‡v×B6Ç,*®òKÒ›Š<æÀ™íT(¬j7© åÂ<ØÆÜ²ì$€iž<æãK–ºŽaÔÕ/\èË´þfuhœB:‰PTkìèÂJèrÌôŽ/B¯ëü¥ë‡¶ÅL$Ì/ü®iXÕŠú0ÆúÂHö:Xt†fÃì&È.ryBä¥v#áç'PyéHö ÊüÌÑHT0ép£E Îè>hÍa¨EOaúGJ·¯tìßä!C~@Ê{"jkÌÖöob0o@å #êȘ18ö‰øLLnU®þVNÑÖÒ.&R íe €µFÄÚIÒrbŽ)+úP/ªÛú‹1”~+RB}…J˜ñ*»R`ïÀâ±ÎêÐù eFç£jª*™ŒxëÂtýÎa¥JÖÂo€²œ}ŠlñFÑÐÀé§VسG]D|ñE¦=1nFq!LþÔÑÆÄ¢â^åŠVßÍ”±Èrõd,Â7±¨“‚Æ–ùä0 2Êäùª!j‰S|g¨»Q¢ÙO÷!´Ñ¤øÅ8fÀoCœ°t• ä ÖCP–©8®®øÁIHêC• ¼!ŒüÖCc38K)ÔkòªIÌ¡†•-Ò¨¡Mâ$gP^&T”ï2„Î80.ph‡—ÆÔ¯ÂWr™‚"—Ã]ì¿1äY1ì4„V!Ž¡ ò|€nÞEF¬•Bå 1PæŠzä ¬\/þ°4Q`o/+-+3 ŽÂ]©poøûíd5Êðb–"lèjOבzôK¸Ž~Æ&„ëMDö²ÇB,Ba«„ƒê¡ÈZ^&)?f½11ÚöÑî«FÅFÑ:ò~!Pë ÄYÆlrbªKEeÞT¤Ä)¨÷Ó’‰@ÙÊîÎbQD 4ËëJØÅk Ҕѓ„ÝCì} 8Ð,ÛHåÌŸr‹.×òÆÝôp§k"dÆv$"‡,žŽÐ$ÈØšÈJŒ‚²Y#&þ>ɨÿ¢àœòs^(h”o¯êœëžåk8õÑÚ’öAû£†©I¨ucÔopîæ.Âw¨Ô·§w§V~(òÁS‹·sü\1JÁ"hT¨qÙC-/:¨Lh‚†åEÖQ¶÷M±ÌÆìZRñ|¸eUë´ŠiD0ð’j÷ °áüŽ‘}S¯g:’s0Z L„¥,œ™  ÷Œüð…,q3¹K$˜kfÕEÈRÒÀ ´­ã¢{o|Leï84âäÒbü(.Q¦ñ)Àª,—^É0fl#-GíªôÓ´ÔŽüÆÌb¬xòz‡„_F—Y'FÏMR;ñÝ&b:¶@Ù5 åR͈mÊï¿M‹bH>±€ óaþÇ£Í-®ˆ< J†£ô€^0å0Ý3â2xHòyôl *ïtB“‡(…§Ýó·WJ£_Å 1ÒÌ–‰f,Ú–®m"“fh8a­K]-W0‹¾Þ“àhŽèàmY &Q¯ŒþJË=‚'òŒtj’¶–ZKíñ`J×8ËÀ‚LÇ­õM"ÈW]ÈüjË-,4½”¶mse… c` ˆòð¶s°ô5]’òhHó Æ  Á õ ÙnoÏË4Á èò¥ÁPGiki"7>Š2ʨ‹‚†Š|úIîë+ÿY nhŽTª¸ð…-'3WEµT‘É#…rb,!ˆ”H ÁöœU³BUÙWòt—sðT$'lúJqÒA‘»Fõ…a'^a¨Òfu¥WJp¶StmÈ”AÒñC*êRM#”#u¸%&±i‘qe,s IH†öÓWòÆÉÈ1ƒA¯L7$©)2nvÊÝW8×âyM¦]r­eiÓƒ£… ׿:–,±` K슫Qñbô•ôæo _ŠN˜± opD9 ©¦Õ¦¨*†öo—bÔž5)ìÁSkvöoµ(Ò‡VDNÍd“sW,Mضi8µŽÏÃ,Wʘu"ʘÀï ±<÷deÿ QQaæÚ±Å‘„U÷W¦Ñ)&P"±˜ÆuƒðÚÊ–¯ÆHñZäð|µ‡–Ø2‡·ø] d1w±ôìçTõQU?3Uh¸ª¬$Óq¼#v‚i¦$wWeq‚ÆÏÆÓ³SŠo\ž&—Ïx«öPdŒN¥vâ Õö´0ÃPÕù)`%¹v#f™›Gú·´"Ì úª9†/¯Õ(>ÁYjÝNâÉžbŽ 7дÇîÁ³¢ë4ëYô™b”^ñ.¢yifˆ¸Áöú¦ö^ãoJ„ Ø’'IÍ›)5~xÚ[R·"BÆL6¨•žúß§¦VNñQîò²AjÐ_o¯°1 ÃtPøø5y×,L– ¡EG z”ü$ S2§ qJûÒ …‹³BSdkczÕ@æ*œ†§ŽyçV¦ÙÞá˜ÕŒYmp…¸tc’éÈ.K/‹¿&…šÑ l)qÆ(t`Åhd,ø[”fÜ §4ðù€ õ¥¸/U>ó¹q8gu¯ß\h-®^ñÁ­‘”ÿö¦€‘2jšë.ö¨0âhÏйqóáhÉ8o÷†Æ ¥Hº:Zò”潬œÚû¤0Ôåâb¤ž¯.êQªÃ¹ÿ˜[¢É9üòo8t#­s+YۀʄŽh¨åFð—ÂRØfç 5jµ ÷o÷×poøú–¤în¡Wçq3Zç»BP§NwçtyªÍ¹9–‘µlÚ¯ªeJ<6Yâ~< T¶·„)UyîÙÀå Kðæéj˜‡è«Œ ÇÆEFûmü50bÛ¾˜ù9ÅW­,Æðù —Ñ•ZY¢bû¥OÁÆh§¹‡m½"rÒÀG87¶ûo—[²1ÝÐ-[º‹•Õ¡rö³] šñÿ<|zö™‚PÔVBbQ°±Ñ¥Û¨s©—Áfsçû ¡G¶…X¥"t)‚ëzUü-«“\ñ€¯qÂ^nD€5¬ñ¦vaòëL%Ò.kǼ{rѵŽè#‹Ù£x§óæV'H”LewÎÕÿk¦^Ö9~øÌ~ˆˆ'«${gwdö/ }<Ö«ƒEâeçÈu{ŒÁš”§ql¼¼yûÏÜk·Ü9šÄâ¢á² ñ°6|íFgÇ.šKኢ‡n,£Ãºeê¨á.JeY ›gŸJM›T纽§â6AÖþ.ä&*àÜ/B:‹×Æm'{wô‡üɇʹïBõg‹B¸1嬙xókª¬œÈ¹ÁQEж-~k°‘´çY¼u°'ãêpF`Ë5?GþFgÐqšô0$vSD4;sBãÝYñ œmSUêÿö,l%w³b‘ Ì*) ˜h\¤£Ë=ró^B†uÍÓ© Uûõ`‚6—ÂÁc0ÖŠ¾]Ïe²M®*™èÅëIßD ¾›h'œì^þà å·òŽö•dê[÷æ5hä«°9M«¼ÙhQU¨çĽäâ;gɟ±r]uàîùiÞ7¿´CÜ¥Ø~Uq™SºÓÜ›X¨u–U¨C¹:Q=-QŽm*’”#5 un™˜à–:mÙ°G Øzp (²ú8íîtM ÐΈöI§S§‹<ԯ…üûWØ\ ÿƒ?¡ØP ‡BÐ )û E"Ñ(  ähÛêII@©TB)ãÐh hû›§¸ëòy/A"’øì@ E›>äÑh¤J;”D¢¹|n¡¦Aªïùt¾AM>,Ú(%S‚Ì¡QØ´ñø·D-PÉ{æé?ÝçPiP*Y ”Fä×híåÿ¡Õ Qi|[x‰QäÒg¶N}ŠN×;¥âïvŠT¤0Ì$šá—Å.œUvc†ƒM÷kdš7·-”¦_´ Z`ð¬R{—ÑøóyÄJíUˆ?¢ÔüL2[‹H¯ÈÞ‡mì‰}s Æ`YŽtv)Gûýpj;wQcžräIBA]úRµËR4}Z´bð†ÇóÂìnÏó`‡“µY_ÑBIé58¦kÊ&±Ó‡øÌ IÝ.º+­þœpü A±ºÊW.‘n©ê>¨~°*™¤`¢¦áú ;*0Ì=³­¤ºmjUˆQüʆ;b¿³+iK?H›=“º¨‚4C]©K*Ñ«©ã=CpJ†$z ™;B.j“°ðžz±Â,l‹¡Ç Ú™²1Ðþ7Axáp[VÙŒ±a|Ÿ+5 # ‹Ùë‰àÛ¤Zc[ñ0‚ˆº;ËÏÂó’©ÁnЈc7˜Ë!yE;ÒL­ ªòR1›!7pëœX‰A8’ ±q=0–3@k8’0 ª†Ñ_;âÚ9Ι°‡ÈXÌ Ò6 «¹‡Óu8üº4ˆò#êE"Ñ=pβT >”V)‘öjÅB†¿( ››i^¯9¥¡Û¦ ¸ VˆrEŸÄ= [ž'ë ŠÉGz§È’!ë‚” ±¿#`ç>μäÆã`¨ã'œ…8›Ö Ê(*ˆ$ ‰±@‡%âw/¥¤y—“.cЛš!»­·³Q Ü*”™”ò¦´L-‡ÄJÀ?ñè”+­Æ LòE—P—¨É‹Ú÷‡ÉH’j+AˆyEû¶5ótª³œ>”4%l˜Ÿˆ$ø‡#ø8Ùy¯â(FÑ£¯›0¼c«§ž"P ¤“'l2yK|­-*¦œg¸ÉáŠ3 »0@BÑp’™§ÀÔDá,ùT<ð‹ ìl›áKÊ0“ ê›Ë«Ž»(úl.!·<©”ãЫœ¦¸IKÊw•“·§¬âã)é²»(• £ t8¦›'(޹ªF ) DŠ´Ý'«@ä”À‚$D‘o¾ëÀÎ,)7‰È –ìiB}Fâ¾â LÁ±£Ë ©Zê®$ËÈŒØüJÓ-˜°“…¾;‚<׫¢*¬©µ­P·!¨zš²î>tZKP±¶éq@â—èÎ(d@x¤ƒ€J8Kè®™ÕšϺAòÁ‹(±2Îá>Áô ±º*¸B’•ªÄk–ºó÷°”4Ù‡)ÚÈ‹ mÑi‹¶(ž<„^\­= áPذ>X ºÝ/i¥“²Š«ÑåãkÀÆÂÎàÙ*š mÊÛBPº°Åã‘‹ÙÁ/A ¡8Ä¡Ük¢-ASŽÇÁÅ ã+­ QüY‡Ù Š)ÂÉëÌÌÊŒ# €2î¿ê ³óHOÛ¯ê¸0s$‹Zø’,+#Óƒ£DøÏù šy°Ø}§«kÆ´ê)xL:ñƒR,´Y±– Ê”4¯Ž¼"Óh²Ñ£Â8ÔË”QÕX’ÌÝ 2»ôU¥j” ½º”z¬K¬Nc®[´(ÌÚSÄÌ;ÌH«1$–M8“³cÊBïBL[¸®0Ô­”ç€ ¹²«ùOÓûÈÊ:ç=]5íqùÔé‡ÅÙ‹I=¸Š‰UPR£Äׄ>»KÌ“ÁqM9‹p£ÖÉ1¾ñ‰ 2yĺÞVÛÅÎù¸ùªܶÕ”ŒÁ$ØY[P5{K©óP†95—‘ìÌc7)…iM唳%‡ác‰ä=1ºâ©ÛÛÛÓ¡Y$˜»«%{Ÿù˜X3㘊Îíž8£éA] ²ëÛOaJ4sµ”…Yh™²T§9}Öð°½Ùi±Ÿd– Å“,-‡Êµ,[C§}X„Sâï T¤ÈÅ  rDG¸„Zšŗ€¹³©J#Fõ”ÖëÜ @U[Óp*ª ˘ȟ•ÖÜ([¨} }¼.24Bù-´Eð¶»öŠ-)Àúw• Àc:ˆQ¹ÇØ„3de<ù¡8ƒ Ί«–ZÓ*²ÿ‡Ø— ë{ÙKð·ƒZÊõ¤Ô(A˜¢WÐ}$ ›B;9žâ攵´¼ »»yƒ+OHæ b¡r¤!yQEÇ­ÝÎ… »ûÝÄÖª³2å¨@ýHVÓ×¼*ÊdÑ¢LX×B%&Å‹F)xAJ64mBr‘à¶K‘@IBy£ëXªÑðü4°ëÅV2,1ÑÿOeÂOb‹· p½š ‹ ¸£·»Ð¿]Ï( ]É·:«;|áÓyBÐ,©Âzà\âKZDù–‘”º!Dž TÛ^²ÜÓ˜Í~¢Å¿ ¬ÑÀ|PI;õš=¶µV‰ kâé,ÖûX®lwÉËÈ uØÐtvŸì(!ÉJABi£ÌáÐ]A·ô„¹ý·Çû=ÌœIž‘® Ý.2UcÌ(‰ŠÕ(¬Ú6¢Ä‹ZÝ.£n+&Ú\î“U.6ÝKÔ?¾ÞA™ ‹KmTBÔƒ” … Сó¢Á¹Ô6!Óx$†%H½Û€ΉÃ-HB=ÿWzÝ¢Š„Æâ>¼5˜¨ùÇGªý¦ÍÄdÅqÚ y·d®(úPÀK- ©Ì°¹Wª³˜®òd<øBü¨b¼À1}ÃùÊ S3!Ò߇ÑÛQò©‘ÅOBš\íKæÁßKÈ¿8{ô!KÜ£)5FÙ,æ:+-¯® %Ò]Å|VÙ—³"#šÊ²F^NœdAÐSþ,&HßÜϹ¢Ñc沂Í!›+¾à~Wt(8Ç+¥&Ç3ɦž¥y*Óàû}‡ÓüͅȾ‘Œ î>×$;‡å—¢’C™fbâ-=‚Î; (Êm”Àî'/¶¨gƒ„’§*b¸E ÍtT-ö!u&€ž @Ûš•¹k£¼¬À•±NSfF;¡ÉÆFÑ®¢×'æ'‡À¬¸ù>áI´6¸”%ËÇñéB ´*ÕŸÈt ¤¾šÜ Ǧ™Ò¦°‰[cÞ É–C î+5Æg9•CÒ×K\£ÜhК ’ÔB>yŽ~n2Þ?W…XÇ"VÕ u; }UC-mZËÊ6Ôt‚I½×‰¢D‰Qy`œ E.aS¥1¹ÂÕ§á„Ú5)WŒ­e æÒvË ÁqP:»ìpþfØ J¸ƒ¡“Pð‹Û–eºÁJë—í¼2Ó€Dœo¸BÐ¥t÷Ú#ØdcÁÎ3éH^‘’;™FÕ[jö©eཧ- @á×Í~5Žæ5¶ɦM+A2AéQœéŠÑîÍŽb±m5Έƒk‡Ÿ 3'‹£k·C¼±ð±—²¼£BpFm)¸-ûÎMx©îjŽƒÕ*4!º÷<åãĵ­|àŽÉ°›C³pEΫWŒ×¥q±è<€½ ê 툸n&Jã`¾ƒìCË=c°Ý¤2·¬A¸à‹ ˜}å_ŽˆÜ¡Ñ/¥“ 8ð ñg‹Êž–ÅãÛ]:«8<Ãã:e”X2ö~Ñ1¨ctJ#èDÝòÕÎR¯/Aȉ-j€+·Ù«`ý ï$@­záþPS]”S_GÄC[Q³‹Äm!u>NÉ3}ì9~ºÀO-ê¡49RiÀ{]aþZ€2u4&e8¿1ú@õu%{͇õkL¿—þEìÞÙU’žÓº63âWRL!ž•¶9»Zä,°* µ­@§ýpÆí¸@“4T@O(þaƒkk¦M—î;EB½*ÞK§-Áb45]Èç¤z¿÷s„-Ýè›­ B±4œ vÀ©F`ë‹·3)Þ`Ò¦¾SÐÊ£¢&t‚A»=ö#Ê]÷¹T´+m·ÝãÉ$ݶÚ»¯'g}Wr ¾ üTˆž&R,«â€5=Š‚u=ëcRâge4åšVcÇ+Ã=`ð-xàüÓÙÚÜ´ƒ¼×¹”'uŽº‘áúsÈ'eóU/ÜJ”*~#fô€,í̘Â6ì>ØÆ»ìê˜8‡7ž 2z±M N*zˆ²PèZ8Óeã'|Ì¥!–)=v‹+½J&F?ty[× Ò µ”tG,µ÷ô -~âYMÎK»LÑ#ñ×e’l­ãö&zé®/ˆÿ‚A` D  „!PØ„!ýƒÄaqxŒBŽ?cÏÉyûB€ryDMýƒKað‰$ù”fÒ‡ÜæE$…Nã“—Ü’I*›fR©$µÿE…>©ÑxdF+J©PÙEB3[©R Úœ6I ™O*±8l(k{[f³i¼ "“Iè U­ë{ßfU:Õr“•H¬QÈTU |ã@Øû0Á‘AaXð6Zc„SŸR &†*¬À¡¹ëXe2Ð15çü¼(‘Lxmíê Þkq¯l« ’gœy[ ÙJ3ÙŒþ(†µzÒ­O+cg•Ì#“*-þ Ô‰Dõµ‰<ŠE˜ g6ryU’A‘†Ð3_ls%P5-z ɫ͒âø"n‹öÖ¨îb.Å"NÙAÇò Ȫk ¼)âR‰¿/àÚ=I8»'(SZÖ ­ú è'éËI I’Pè¥R@í;QCD9.º$Ž €†¤MLŒ!¯Šó¡.ã '¡jd|( +ЧF‘’‚#oÒ¹L,Ôº¥ˆ#VFí ¥(Hê<ÛÉôÙI'ê‹9p¢[Dgê ”4¬”à ÂpŠßÍàD¢ ©“GŸíj‹€kÃúœ³Àu8û1çÅ@À SXœF›îÊ#ÈR€´ S#†~Ëà2¨IÀD±h<†¨®r+¦Ï¢À&Ðʈ[PµÍ'ãZŸJ6¡;0`L4]Ž(¶Ôî”Bð€¦©Ðéý9@IU‘ 6RH4ÈB®® Ë­Ë*ÐTð›LPÉï€ÎS%ÜÚ´jl…Y+[St³ÈH™üÖ¦)\+ò”K<) Ú¤k1ZßXš´-ýo;³Œ‚Œ½Ìõ+l`'»SiQùɱé•]m£‘Áø’] žg-$úOŸÕžŒ“¿;¹ Ðêâ•|W×õé~\H#Ü¥arò.ÈÖp¥V'0¬JÀW–„iåv…ä1“æ§ó=jßcÞ¥Mûxp "mXÌ*„í®Ÿõðãžu~G€"Uh£ÚÍ^—#kB™2»߆elszª€ ¤ì-yÙùÌÇ  Ö¡XßíGÚ•íµ¿Ç;HÏóGîß5@ÛâžO- ÝÆãGû¢ J2ßjÉh›RÌo°õNb8@ (p>è‰ãçågí¸\eçé¿|#­z&ýÎÌÒ’Iikî=P2Ò Ú˜û@Jܨ†nž‡û@„q7&°ˆ™}.ù;¸ZÑý( ƒ‚QJ*…q͉©"hIÍi˜$O| Ul’[gEÑbHä+Z ±Ç'â€'¢pýZ©’ÖÓ¹ûa<ŒñuùGp=½BºPÖC‘òݫК”m÷Åȼ¥‰é‚ ÈMÒDœüã%è˘øKR‘ 7åÖ§+êÙK³©Nr¿HØ÷ a¯.Lâ§^ddÿ 71‰E¨¡Nf WÆëA:QDOšo]¹@›¨.Õ–®—ǼS')rÊÓ[C‡ñ©†ÊÄè·[dñЗ7NIÑSû¶Ÿí’g)Yð´ØcJ…Ë"øK“–á†Ö­·[Ϥ¦Gbä®ÇºÆÃVôž9h9~™ëðh`é ¨ðO"„fÒè…ÛÄôÙ=ÇUc –9[ŽsÌ’Újft9XóI‡f÷‹w\Â’ÁFÀÈ®‚ep É*3^¢82*‘­°à‘3€²\¥y¡v&œ ØSA R’´ykçm9ˆ / Û4Gå¹úÜ‘û·§Üh™ãõˆâ|{X#µü¡em˜]ƒNåþÄÈ5.ÅSÊLãrƒNó`ªà t%°uõϳ¶Ü_v¥ÛI¢€Iðg˜‰mª ÀKçâTßüMƒaàQþër½¾H9Š­°ê¥³ÒC$‰È%Žkwµ*1÷B5Zè%J¾ [ñ·Vä)Sý20ã@ha‘²Í`Šñ+]¡ó0†ØÛÌ!÷x @ØçÑ50Ç0 ÍË][(±œ8¼J"=}žŠÚ‹ë×–F_°Ɔ´ÿ·Üà3Â"*ÆíȽÖ~Ûƒ§w<®bwU2ó³rŠ G’.¥ºÈ‡,¹Ô’ÞVIp@Ñ6yh® ÂwIµÈÅgf[ÉÚ6±/’øßaŒÕ)A“#=3¹•OqÝwIROäy=HÓ·z×SådEÔ¤§Ž©÷C—­æu¡3Í¥øø'Øü&bÍõ&Fi2Öù!„ήĠßó%² ±w²5ÍIQFòFk4{ݦt§LbŠä7¡'$‹ÀOÅð€>be\t–™ɵìj/ò¿zjec…vÙ¾·µ°Úy¼ ¹­{#‰–M&D‡åJôkšµï F¢h޽cnâ«¶ý‹&Ýot¿ fç ;Hªzkl¬)ä&Ç ü>ŠLPIÊr™ÉÆžË\ ¦ö‡(þœì¨§*úØHX¡¢rb)œª 2L«ôÊ–ïi臯/ö‰‰Hâô$賃qíY(–ð®î"Ç>Ù̲LŠôŽ(m bÖ„ŸðŠìhÌ .¨§ðÀ¾«¤Ûív¸bB¥.¸ÔËÝÐŽšå°üÎX#Î(T Z¦(H|b0ô ðãÖ2ÔI†ãŠâL°à*"!I(xâŠû­@Õ¡øšÍœ•E°ä°µcäDЪ~œäîÁ%ùLÙ©#̰}Ä>aËZòÐH§Žlc tÝlÀŸ°òõŽ?p*3Ÿ&`Öq4«xrç¯0žOm¨ÂhÏI{ªÅ Áú¿C“ Œ™Î^%Kz©ÊfÜbhâ¨n ý¼Âî¢ÒÑØäÆ6diŠ50} ¨iÊzld-hÈÃøßO_ äPC<Ãhd¤‹²ÙçVVãt®Ì–0 œqHñKĺ0®zDÈã÷‘lÚp¬L%b‡-ð¸M–uiP³#‰î1é­çuI,l®nQ"²Ýfê÷HrÓ2ÎKg°ü~e°ƒ¯É 'þNN*‰©Æøž‡Öb/{ Kèäe@œgÖ%OÁB”ñÉ2K„&n«B³q8YI\ °Òzh•Í3ÏW'1¤å%îü³À )„ÿîÙ¬B´`3}ÃØñ.§éÜn.*9ャ´®ÍÅ–6F')‚üAè(¨,fåg§qÌ*%²×2js ©¨öâ<˜%µ%ìx'Åg¬ÈFòvãn$FngÀ Þ+ j ÉE>THÄätUÜZG Ѓ`Nój Ná0æéã6àP_'çREIK³$xïbH¾æ©²~*ò=Cö§¤m®Ð" ±ðÿˆ:Vqn0xè`ÊÀ7ëB¶'J”"䯋Ê'#R€B óBœi‘,ç¼)Èd}ÑNŒÉé*î Lƒ~ü ÔNð*?g¯cöhñ/nù,ѯ#mŒotã…Oó‰ˆq/` Ãmƪçš3((%HÌzSΫBs"#"gœ“±¯Cd‚œç`øÇf(0¬p¦’L{Eì2%´kP~n«¡KNL§ˆW#[ ³šò• -Yï²"‘–h²©/ÜèGЧj rŠ ÌØ´K($Ø“ÔÇI¨÷ ð*¹%x)ËCT7Œç®ü„îöcBW6Š3øË5Ššˆêä1zošÊO=Ò`+ ¥â΀ >·HœìË”•lL%d‚õ§ô3ËZ¯¶Yg*r¬æ†¿Åù%O”êRTŽŽ-©ÓeŽEVÀ áE ”4ˆ¬+Øùàé¦UÛU¯v/&LøK‹BìT®¿ðŒó·\5f÷S@ 8¸“S.©.vÕ!ø¦õÉ:•)Jûk)BÓßï\Ì5ó·„‘—Ó\O…D¤˜·¨ªn^*v©G«N@Ô.RWQWv[3 Qo¥3FÉ6®Ð[]äËTiM*™O“ ·aÿuGU ð<(ÎrÒ® ›ÓÀ2&ˆïs˜êºã÷,aõFâT‚ÇÝG6_ub×cרâ"m)3z·ÿ A:«·(ãæn}e—bj§$Р¹J¤˜2º ÄÿiŒ¤E,úóÖŸ€d ¦Ö‰ÿl`Vfo‰‚üM0*p7èa#÷rÛ/hk× "ø\å$¸n¶¶JWûs0¤Úöºzi‚råbVi7GsKv!÷}Ìç|‘e`‘PNèlËd5P£„k³T-#mÄJPb#Ž*¡Jõ"¢èB€rHŽ—ïu€-×cÝV7IH¸v5gNRmØÿf ôÛbŠggâ_Ï ±¡>BµóÎìO6æ˜%¤­c«Xx‰,ñÖ•¬0‘‡ q•Ifse—TÞ5œ@6ìyùÿ’7Ù“qÜÄçÿ?/ÜøŸ;¼H.öåñ€p=Õ#,!ÍPqf¸Ø(LĜ狘RЕc‚A1N,7O÷NƒT¾‚Vúkez ™Í·hŠÂÔ9JDyΠd÷'D¹:*xµ­X˜$6ÃoU%$*„@†ªR¶”4)“å¤à– 4M-<-yh®QÓS#¸©LÑ[¯ ]tNX]mÅ _‡øëaE‘`ŒW…Rƒ„÷H‹g>wÙÆ„Ô6â¡çéڣ (sfRøërœc"Ú÷g‹yØÌÒÐ ¦o‰§=×6Gv´.ŒÚ-  †V‚¬¢m_²[5U_P:ú&ˆ}ÇÖÍ`RCÜ­Ê‚V‚_»‘ö®Ðww±r¨åSm ظŒõ;VjÌEª%“š­ÃiQ.Qx˜ßÖêÉX*R„¨%¾+Ù彸W³683·Û‹SüéQ±Z×&â:,L•ö.JfãSšçÃÔ~Eç0Ç-øË4¥omRÈÑ¡üN…-i(%é¿—ìý-žO<Þyä\™?^âZÚì¡\Þ¿z>7*Ôaa~ĤPdŒêí–Cé½3¯î´qÎËì‚„î·€³&a—Áòë½XKõwCÎZ WTÃ}^¯[èO™ÀパáÕ!eI–ðÏ8¨f‹x¤®‚A¸õ¡×,°ÂÞ ¤i]?^˼[Tš]Iuæ"féèrBËñ›Ì‚A×Bü~?àØ0 …Aï¸p ‰C!gì1ý‹#‘ØD|‘GdRP 2>•EŸRÙP,™=¦ÀdÝó9ˆaϸËúwŸÀŸ’YÜþK†Kç´‰H ;’Æ'õWô’E?ŠA+Lª»†Gl‘Ëš¹­Zl±É5¾á%Ç¡[´¾PŽÏgwÈ…¶-=’‚p“úTŸ¾1˜@L[DŽÓ€6ØíBrùfñ‰"J÷ÑT*·þš%—Ößòý,fÃhÇh•ðOYl¹Ç%¯©} 3/±[52;VÂ9/’á ÑÙ3ÂŽbfhþãgɗʧ±Ø´¾‰r„Q5vÎÏêçÀW­•зH·¸ç§ß]×ÕrÑκD³€ ¨"ÌsD{¼ëƒºþ»îØ®´ÈúzÀ¨;@¸«ÈBÚžÁÀ:ÄÂhrðà¥JZÀþ¤®r®²(¢!‰Ú*ƒ1)ìl‡2hËöø#íc:Í ¡üå8Àb‚EN9üÿ€/Ê8ð¤H²ú‡ž,ÊmM~gŠ[Ty !ÉÆ-[+Û|äRw”D]&@¦qæ~7™½à9æu½žÉ°}Ç¢AžS1CH¥@@H&ö~¢’¶‰·t}_MÈ8A£—«¢YÍ“ÛÚ  LæÚ>•ž| ‘ÖC7HòW]9ñ¥²±Dá0‡óU-©Æ¤©’oO©„MŶ;ZLC—Á]pù‘#Ø\Üip¤"c³°‡¦´˜mpHÇ+rÚ_I±€ªÉRØQ Ù‰KŒŽ=¦†íJ¹‚Dýþ#%ˆù½ˆO´(ˆ&ñ¤m,U„wÖej?QÂÌ$Dõ¥#ÌG©ìA¥Ö“蜩¤‡E;mˆa™H&QÏ“—i3Ýñþ€d©°¶³ À-yÒùH™^UÛIûuƒé7ôlTIPÆ£4ÂÚT!‚FYgÁJ€†&¡ÈsãsB"ÝòîÈ鉂Tå8Á%‹dcäöw1¥—¸º,™9˜'6Œ‘1²sI”ž#'=Ð?¤Ñ=!™?vlF2dÓÔ”§†±Að¦W D™MŸ¯¸N`»+[nI4ŵµÐwOGlç‚FÐ/´/1˧œn&úKl#Kdå•Íœ²6³z˜ËaÏ»ÃîtÓäš™M¡”ËÀ …GæL¡&2ù÷.cÅÂDý ÅÀâ ¢HÐIzTÒ]›å~Žãú‚áFi)A–hÍ­Y_RØ•—Z—*ªW(ɆÚÛÝÁdËt‡&Gw eA¢Dtlh·N²Ú®ˆr.²œ¢>'}ÉzåYó[ØFªäù3¤~2i#ûƒ­ä ¥LF=TJç‰6dX_*D¢ XÌLâ/é.?HÊI¡ØŒƒg—¹\*5ѳ¦Ôâ©óÌèÀäÀâàѱ.t¸¸n .™ï‹JcT{¶X…/aä…jåX–&e&„ZBŒÍ¦32Fì:õÔ-ao•u³Fç(nÔÒÂÈG9 —M ~2.ü”ÐýˆÍê!±ÍǽE¢Ë ¹**ÝPGº,„fu™¦üîãmÃ|¼B×½·JÛ ’Sl¼3´iCÅ«WwX¥Qz8{Q!$)aÒ0 WUý~Ù³,“:D«†&v•kYÏ•rÞÅ<¦ÛT¤æßtd–á$Tì½T2;hù´ìYÀøÄߨ0l—^²%B#5Ì=_!t büs+s®›­IÎI;„9W€£;s›RDö, ˆON}³:6¦SéÂú<ø'¤ÜFþí‹NÇ`Û´§Š.5?ø±+¹92C˪š«·íˆó“c¶Kíå²] Ö<×¾¢9™ÀÎ;e\ù܈^¨²¬ûó¥‘-¶ÄdÈyý¶YÒ_×Þ¦÷77ÀA<\˜}’1‘}âÉšÔ‰=½«m’õ ±@,ÿk5Ÿ€OßìT+È‹'(;á‰Ó\ Ûs"AšÂCº¸™YЙ8­ºÇ¬ R%ª¥ +”£Z:Y-3kµâð‰âé/pç¾Øy·[7¥«­:Ѐ ÅŽ«©¤+ú¤Zùˆb,–’ºÃA¡e¬ºK“+Iéº!o+œŠ—|ªšâ¹ó53¨‘9‚³¿Jö¡›§z\#êª) Ž>ÃÚ%ÂÙ T"24§+ ¢ó™µ›”±1*6IT+‹z#«?J @’Å5;¸3“¼(~©É–1((’Û(±°“AuÀCæ;‹4ë䢠‡Hý«ö3&%A\—K·Dbe‡ä4‰c#€>x¾Áˆü'žâˆ`Ç 2­L<£ 'l/ꪻ½t(1šÃ‰jW$ƒ+»aœ3 …'ªÅˆsý Òo’[Ò+ôˆ2Ö‰õ³ŠñK°1õ¹ƒ‚+²’B3‚¤ãý èÌÁaÆbZ±2•PlÇa£9ZxÙ_¢² ±'2=§)ÚB WByÓ¥Ò•Ÿ3ÔY’½‰š%D=µT¿"£@ éaÙa ´SˆRW)à–Ä,£ K ë»Ì[‰£ÅÅJ~CÑB££NÃê·£L‰¨‹|˜ÀRZ©Ì-+ü@­‰ãÄÛÈ%[ý-ê4ÅŠi©˜Ó%*­µ¢ÈêË07«`}ÅÉ ”ÊŸ4>ÅJÏÈâŠ_°`ÊfLº/z ªò‰¤-ˆ¤î4ÒM Ös4ÀCf c[²Äj Sÿ a_‹)œs“q± »‰ë&8Æ3”ÕÏA#Aƒµƒì|™¯iœÈ²áÂJ´¶t8¬ƒ¼Dj=› ³¬Q PŒ“\㺾$œI£ ˆÌà;ª ¾Áõ ±ªÐèИ‰“N¾Â¼9©ÜµHCØ‘I U(£Æ8Ò‘5|O’WDRå7 >ŽªxϲQé’´ÁÏã,¬*9Ä.@ÚâŒêµ£ ä(²ÿ<ûµü £8ÓR[)€ ÎŒ †N ¸%™©¡Kú¤.$<ë®ÅD|Ÿ2šÌu3l¤ÑR Ct¡•AÝd°~ǰހnšÑbKUôŒ=Ü;¢8—´Xl*‹i€«UDÑDèIª=•É4QTä¢JÆPrV(À͹l=Y2‹n9ßâŠ04D: Åæ2ü•|o—\88òw±6 ÝÓÖ)" ¶e~a­eN­ì¶dT©‹z»ñà:â±6ÔýHHH“EkXˆËÅ•ÉüI W©É4MUÕÌÞ‡õò‹-®² Ñ,b¬,®ÀÅÌ+ûçɾÅS¬bù‹ªž|Þ΃ýFîf#ñ6š€kÿ² 716€9KÂP8Ƙ×39"ZRíÃLº’'DS)m”¼?’Y8Ãë'S³Nìn¬¦~ȳz"_j‹6rË<ÚHee¼€ÛjØlѨ2y¶°6¨Ä„cWE«µ_ÏË~Ü ŽÕîú:ðŠK@|Ø|‰l'™;,0V}áà„UÊiâݼÞ¤²U•üØKöè9=…ßþKκDzk±Z’?²P 3¥×Œ‹Mr•ïùÆæa •#=?+ëêš:ÆŸ† o=Íh£ÈSÍmMc[ÁU‚+zš˜}îêš (=Ÿ×½û±”ç$Ó›Iµš6ü”•zLg6Žœ‡Ô>éx|Sz‰Û.5ûR{°6ãÃòò”¥Ó#>0pÏÃB/g§Âャ‰5b7`ŽZéHåžôjÇHˆ…éY¸ìC;Î^¥(Båú¹—dL  ÖcÎs“0áu°ó{ý'A£h/<1™”¦~¹™+¿1šµòugÝbT65ñr£o-Ç? úˆë¶dEXÂ]xŒËÑa\ÀCêäÕÔà ܀,ÉÚÒ¤9¸Ím+‰Î-8çEŶÚÃyr¹ “™3]¹sOŒ”¬U1¨¿(äØÉHîR£(þ'‰–—)#æÛÀްCzÅÏBÈÞ©;3rÛÁnȆŸ¬ˆèÇ®N^<91"0åý(£Jô£w›À`RÁë'5(¶kJK]þæ‹@BhýÏK“óM9Z÷·åG 7Ï›`‡né#ì€:,×b^ðÛ4í%² hôP"ªEÛNè8èuEüåFÍ}öùx ",Ö0œÒ^' žc¼ß:÷Œ¤¥^§å+[4^f€²Ø—ÀÝr‹V±ò³6BJäa‹}´§B·Òì·š¶Â¯u×Î^÷[ÂUǶœ{÷AŸ&Ûò„Â.å²h„M<aÂõ¼ †y,ly$YÓúm¢;¥ç°ýž±5á%Á`ÀÞ°Âj”ø€>à@8#þ „AŸïÈ`" ~¢P¨íýF@1¸ ‰¡OÙ$l’?@Ò¸ëæ]GbïèìÂmÄ&L~M ŽÅb°4vSD”¦:TÞ¨EdÕ+ê­DˆLê’š³ê‰“MÀÛu A$2„š?#”É&rk¥Öa&”Çcó9sæST°FáR„*É)“He²ùÀß¹Æç°‰üÃhÈLãÜ®©<’䤘¨$Î… ¢cßö-df™†à@4˜<"SÏÄ¥39„~;HgÚ'î&'ŠÞâò™…R! ·BrØ-„C ´€áY¬Ø×ÇØA®ñ¹Ÿ_½à˜Mc1XT™­Ü¢û)ƒÛìüD?yœwì{#ì* ޽@f|A úÁÃr"­ãñ® LîÊ#’„"ª#ú‚:Îû"¼0£e =ë)þ®  >¿g¤dåωúЪê6KÂHˆ((hŽ¿OÁï#¢d”¿ê#Í ¢ëj6±E¬¸”ňÙë-ª‰4ˆ†¡Ëê*á! „S¤ÈªÄÁ¢OÛþ즂ºô­H“|Ò¢ðh=®놷ìÉü©<ˆ»Ú„?r”¢ ¢úï¤O0½É"ºÓûŸAN(dîÒôÂû&¥m Ý¢ô‚ľUkhéZa#žó`*J²¬Öð ÕC4ªˆTS¤“ ]ŸñÌÉ€ˆª+± ª°†WΈ™"êëÊÝ4h”ºœ¡Ší!,Ä•ã +$+%ÒØ(l HC ÿŠš Æ‘ó<Öd_MŸ÷B%(Ö2aB/ÚØ†,”éø“?tbyB~ºßp%¶Dp” lªÑÜpãPjM¢­’C© %me"P¥bE8%Ö…¡–²¡–B:ªVˆþ~^Wlr:ÜÔŒÀ4œ¬ÎÃ8 +)nîI¤0  ’µm‚E0þª4ȠЀ) ûDÍ ÍVÎj¡hí(–78®%É@¸ªü _¹¨‚û’fò²ô„/¨ûq¹¤›&@}M(‰ Où3©œÞñHE:”ÍnÖíuS»kt¢âÍn>ÍKÚîÞ™¿n÷U#8=\¶i$ö½•êI¦õéݹà{}4†hw"º¢a½2i¶"µh®ò§ßbñà,‚‹"ù"²ùÁ}Z$Ž«ª:W²Ÿp¤)rE©œ°‰fzK2£/üv±]ß.¦”Þ“Ø#d|ª?ÐÖ\±+D,qð»8]ûÆL‘û?'H†ÛçN ®g¶y”q.Djá*®F$?Ë7íÅ€D§Èù}aÈõ¥2  ÛŽ K γv–ÛÄNhMI¸’êxa“~ÇmÓºX€FÑÛ‡¯Ñg²© ~ÐÄ—,%dF^û0‰Æœ~;õÅ€x^O|˜-6 b}]G}ÞDJ¤Ø¬E­‰/‚ ¤±q>Cù[#¸”Hc¿Uˈ1TŒÑº–²:yˆƒã̘ Õ€TÛÈ\re†9*Å¡ThNPxŽ6Çx£J‚y%Ñ>✤€wê*³2«à°ýkñ\.D(…¥hA®¿žcÌë^’-‰ƒùO›t„eÜC Y¢™¹›úc—Àq'$f”Ó{nÙ•©bK˜¡­ŽäÙªDHž`“,äÆš²3šô¦jQœµ¾Å°?šAXh5™£D6µÈ$2žÓØ/g ¸J±û+¬)Ô+øÑ5žÔpTÍŠ9K†—”µŒ ´~–Î?Xõ‚O2ƒ‚ñÉ ]wêГê|–Ǭ—œt‹©4Ÿæ -‘¬f`»ò`_Vc7/§î—¿2ÖÚÝ”§;‘`ƒÙxÉÀ A³Íè<*`EæúÌA¥R.˜$~èawä~ Ið ðM‰yä¬ý¸r6Ž¡)zÊÒXT‚ø“IÂ]"¤¯ÓàŒÌèè]¢T¸lHb1-gí1¥¼þ&ÓN^$FYéD+¥vÎ8‚B´'“‘ôG‚olÑU1m…uyE{*x ê+§üª?³Låâ[U ÛIã?%g“eÖ¡!Pëáø„ñeÒ-i«å Wmó®?‘$¤¹X¼•?ð¶P”G6,¤ä†ÈHà>í¯ºµ~8V² Í¥›l'À¨ÅVÙtT‹3>&’h=]s¯˜wÆ;JkpØ$‚+NÖÁ«G ÁLåxíHÿ½lóFJ #‡àq뉳§• öFî9!Eõ`ÕÒ­ [ÅV7¤!ôJËâÌ¡Ý+dÍcP '°ÚÍšà‡'öSæ „ÄäFŽ¥k xUËa [`Q÷BÐEÃ%‰rV×­6ŸP˜+Zrºʲd@ü¤®«%h18È«¿O«îÎtRße$ù€gH·JrU¯<$Bˆ>¼Ù¾Øl†6  8I(I¥•(¥‡š Àû¹(¨xºwÙ ×ì«ê²ïÊ8ìÆ}E’ȺÏ/ÇÉ]x?®[Óv&«G0{ìiÝ¡5æè¶*­q’¾ɘrB W‰^Wyݱ"Ò ÂU*ÏG·÷¶Æâ‰Ë¹Õd™Ÿüof%ʞј÷Um<©oà™Ù ??ãž·ÁbR²Š¦\À A,8ø›øVÑ;Äžæï¬¶Ü­;E€Bû±*ÕÃÒãcTªðõ•õªÒ L‚I+®ÛŸ¸™ÖÙØá^»¹ä‘¦bh×I4ø•’„P=?àz­9]rE?ššÍZ‹×•¼‘åŧïãm5¿8#(ØÎ·N%<袼Síà²Cô Á2“E)8‰lMe ó ç†tËŠÐÐÃ>mŒZç¸Bg6{¶ÐÎ’¶Íò!Õ‰»7~Õ9üŸfIÂ{ ïë‰ñBèy¡ûRˆ×¢´’N€Mä_;š¢é¼0?IƒµSœÈ~lO­–A3ÎþhïÞ-cÓ߈%z”Í3Y³‘”ÿ‚ÇÃéÚ‡í½,Û©¤”(•—Úlø6©ž*CM9ÅØ—ÆÔ~.é3¥ø¤>2aÖ¾ø Ú\C¥EFÌ#"¹N*xI Êdv  ^>ZÔÃ$˜¢+Dvž“ÜÞ!¯Á¸2‰ÍÈâMøÕ©’ØÍH6U^ÉÄúpÃBÖd„0`w«¤¿0"ë6Ù„(n‡ˆÔæ6œí:#*8ê#¾n¾†¯¼KìvÅŒciËg¬ü¦¢”Å>éKî!‹ü£ÂÒïÀï"ÂȨÍä…ëê/â Í‚$Ì  ëDÀèyhÞ’¨f_…˜(Š€·ÍlÈ"H/¤”ø@¬XRf6ªHXiæÏúlN$ÑDª¹P¼‹DâmÌÄJ "ê˜#U#¸OëÎhdh×ã:Ëgˆ‘ŒÚÚ‚È&a½åhzÉHs£ò”§8uˆÏ` N*Ûì’žäN;ŽLù €Ï:0ɾü…øDköå ¬£cðÛ°ôRª¤)*ý„¶Ý*›¦xƒTÕËËhà)¨ßÆ´Ä9ÌP‰Ë $Ë‚¹¯\éäTïB ÉÍ`ôäZGgÒmþgéÞ­Ð:…®.ÓdúÀkF”Ãd è¦Öéx Š,/¦ ffd^ªÅh…°ÎžîWé#:ÛNªt„ ÉDzŒD^FÍŠ¢§xsqjp‰Î‡Ëæ;,æsg0ßʬÙi¦º±Ž”0.lGpžôŒ…þå d´*¬ÅpL÷ЈJ¯øL^½2hânœæŒL߉¾LBzÊ{gºUæ†Þ®º¥ý¾ ëX”ÎÃëDVÊÚ—†6”$Gð ,Æz—âH?bˆ^‡í i4é¤\u,úãrž¤ÆÞØÎÀ#- ƒ¡ôþäТå|ºª¼ækª`ŽÚ½%|x†<ÑÉÆ¿-쨈¢Ñ&ÁEL`‡ì3®¯3ð,¢cϨw’ŽÚÌ£2‡¤¿D;©¦Ø+Rø¯`#eçyÅŒÔè(kƒ´÷kO%n³ï2ÖÒÊ.…}0Oæ JØÑ…èÛ‹Žè‹ÒäI0…J<2á3á©“"â$Ä¥[IR‰ÒJßò«MN~Ãèš(á ÍVd†g"èfj¤%È@* ˆ* ì}ÆOÀëêî.„!òSóGæè#°z±(–è°¾öáôBŒ D†Ý‡ÈXíðUð(×(þIDžfn³‡R{sðA÷)±ž$Œr3Ñ ò´˜C`¥éEæðÐB 8ŒäàÌÇ"‡¥nU!BNÊlâ!Jê òë,!Œ¸\qdÂ…Í^GíI,’ÄE±Bn.¨¤Þpåp\^Fàj”O­Rd‚R?èrú)‚Á‘×Aüh%Gó”8EB`²úÒ©’{åM)aÿKÂPÝizœ˜|Èù0™.aüh4ìŸr²òÇ ¸ÕFo Íò½ØôÉE Œ_‘”hŠXÎI skC¤(GmÜ–l¶ÈgÿQ {D-{1i’Å­ T‹mÊjxÑŒ²zQ[Ï¢Ÿr9T¨¬ÌÇ·-rœë’V<ÉtB2p!¯;—S‚*T +©ÎÂt³†þ#êtO‰p`ù«/U8«¬vì¢ÛElq^£#ðåÉ*ed¦bú쓤bbžÄSZà Ö)úß’ ßɦEðŒô±ª¬ËªÆEl¯` {(¼Åh¶%*°æ‹ã’ü¨tÌâVJÔܦ¥LµHœÕúsR;5÷ %'ºht¢Ú‹Ü‹¥Ø}mÔô l&Ì2°ï  aÒ^ÞÃ;L_uöÜ‹q_füÉJöËâGudédpÛSÙHÐüµè× VmB]g”\êBlÒ-𵨜}•–JÏ€ÉC:Ø35Œîî‚ÿÞÔã)L°¤û:©*ÅT´«g¤GtMb¾Îõy¨É,Dþá‚Ī Gp¬¿‹âÀò‘[586CþcrP›m©-¨±4nÏ4ˆ.­–¥'RbÐ’’¦ƒrZ…¥—NEMa¦ðoäfw:Ÿj;¢ûD”Þ%h ¾£édR¿08EE¬{%^©HëG£[Víáokr;¶áJõÌVe"´Lâ´Ï„êt7uV‡Íe:B #ÿS-n…k°Ð ïÂŒCT§‚6æ/Z}㾑”ܺªÊi‚dJ:n\Ô6›âgOîÖÆn—è?õ rb¡P¬uÖ­°0¡é÷ðºr]Wn< ”ìt¥®n Ô*#*€ÞÍ>¼x eµ|²CÅÎÞ ‡õñ´|ÉVdØÏƒ9ê³ltvXÖ ¼ñ¤ÞÂ>ô#÷®¾6tx£àwIkâÕ&Äÿ ÉÏyOÌ«W©† à°µZžâBy¹–>tû+9ösTyÌ®Æa îfhOI”8]y­0A ãjAóQø‰E5‘„m‹"è²gnmŒE÷p¬ÃÍ—² }©ìEìÔ‘±Nº°{*Ò`xg%Ó`ôù¡zn b(70îce!c²`¤dŒCÂ*Å”ÀÒŠoy©¦Î,…N¸o£¯©rëìÙqòö‡Ac-W‚Õ“ï«”äM–¯k´i…ïOq.Ò¬Êú9%¤×£)Å!(ª!G­{-’Ç5¥ö;cx¾Y n”‚´9+‹S§Ù5«Ó§~cÖÌ{Œ¦uÒêƒcÃ%à;´§+Ï™OûtràUÏÚtšT’‚ Cõ«¤µPžì·¤ˆ²ÍeWcwÖÖêAK…_7u:ᥠÖè$Ÿz;/Ô •y§vºèùNbC~[Ž9m®fàdSOúB"øúUè~ñ*ñXÛ6ÔœŽbºµóL²^ÝëÑ3~3QÇZP«3ÀŒW¶uXo?p%Y·"‚èšVrf!½TP°Rxí-ŽV_Y{t¼í‘íþ{l$„v#ùÌuØèq‘bÔå‚lœñº †g[Ô4¸ÚVÌ'{ –zx&çØ±–DõŽî*ÛYk m{†ÿ•Ô #åiF `SæX‹éîŸuu»ƒÁÔ"\¤»êÑ›‚ß µÐõ¬”¼ëžiû¬u,1¥ü‰¹`N~žøLñIIÆ(]]cˆd“å®T ÷ ŸxçC¨ÌÈÑ» *Û£14™‹‰“EŠ@‚R÷˜{Õ(I»Ñ¹˜É¹«B‚8ѱ•±R@±NfDx6ü®ÙbR¯©à Šá.*XíãÀ;,ãa³îŸ¯SÅ¢é›Ðôù´9‘¨+nÞ½À¦ZÊ&g¬šÆÄ—ƒ÷FuÖóÓ¬ÅË&»}ZÎïée…/é^[d×èø_šRO&Ž\w›‹ì#ì?66 òCÀGÄ:+Œ Sl£¹±Âé©åy‚|BÈÔÎOk××JYcú6Fè‰$T%!©Ü{=½ÇI&û(¨äñÏ*õÕœäi38V]d{/À ðŒ…ȯ=ôKÒ´¥' Ô¬îܚݒÄO®{Ç»ŒmBPX7Š/Åû&"XmP©í»YPV'wÇ7Á°E["kÐ\™²Ü㹉©,_šÎuóØ'¥Z;;¢ü¤lxŠQùu.W':•y·F»X¢Qô6óµŠJÕ[´cljq Í‘P#®â<чlwùì^.JÆÝ *½¨&w°ô;(Ûû¾ÉN@±ÿ7^µÔº¡¦0­Ö!7ÖŠ²_mb¨©CöŒ› E¾”¬Ü¥b ·Á»!,ÛJ!žo챑÷eí%x*DÀ/I=ó–nÙ¾ øû”1Éøa óÛÌ2^Q~mócT©î”Íë²úßÞ×Ýwz†f?ûó|‚M‰"ªd"KàÛBûˆ•7z@ a¹aÒi5µ‰µsO“ã Õ‡¥ÓÝqÙH÷f”Ù–cñÚu2îàû¬ \„” ²E1"J•GkP_‰ÃTÐõõŠÜq‚®ÊŸj{ÅzváÎt#{YÕŒüûZ ¨& {AßÐ, Ãß±L>ž‘Ý|‚´Á{×F’OM–Éls°¤–hnøM¬_ÓU›ºT§_Ô»çé¿‹¢pʆ¢ÜÉsÖêI—‘K¼  ƒ\ÓBcı³§°Jt ,m‘ú$–̉C!'i  ”ææ‰;[ Á®–Ý×#—4&Ĉ´ô‹I¢,gä¡–üãùc]E ‹-`PÙ)ø"dì›AÂs]2äRE•\Ôšï€#ŸiÉè#žã×ÂäIoÌÇ)&Ä¢H[3.¤V)¼q!)`näÊ!Ñç\KÃR„‘%HMòè;‡Y>EŽâ›œSñ½èÂ? p¯Î ¾¹ŽiŽÇ$ˆ¹¨GO^AíAx¦Öƒ#ÍœN)ËÍé-ò¤ÔX$‘:µ±þ錂õoˆŽ®†Ô¨ë°!eVJ£ê¼S̹oF)a×M "ñ9”E7Tݻێ2ÁiÉʾ@ä‚^³”*ðñu’†®² Å(9‹+©% åœÃ~ÄÒe›Äµ kzx„6m4*Ф«{U…³€E?sÏA­½ÃÈ- Ÿ›vD²Ô¯EèQÉ!65‘Áʲ&sO\M( ´Ñ=¥ę̂ìZ™Q¸‡ÏêüʾdÀAÔ~Ñàz{Fys.Õ⥪±íN@oàQE±ñôމãß“Y¸Tõ#"3À2«KyìÀZ¥C€ ê_×ùaT’=ÕÈäb[«>²Ú>6ø‡œõot&aÏ"zéCx\l\´ý!*$Œ%Ç6Ò7Pà²É“j^,Ø*Ô²j "TÆÉ͈óíø$:µDfÍr4H4›Vë Gk)Ï&Šº|¯æ O¦ž¬H΄%‰ÄçMêÉR¨D o%“*fìâHrT:0‡ª“w$ !»÷+0vu&=,§:¤e”ºUJö>dyZé¦ZúµEéæîͳ»ƒhFórÓšQP«ÜÆ'uÓ>8BËA´‹m¡JY½fI¦¦2µsZ‚ Ày§eM`…’']• í¹kµK.¢ á@ðëw‚Ýìm&…Ÿ NX­]CF=‰Ö3*!E¤ 9Ðû%8¬NŽÜ ïÜRØÈïx$‘Ó+L¾…bäsbd.÷e?¼RK~ƒ+>±¯n›@4†½”8}¼ME+Éלä7V-¤*{\Ô—WµUPÈ»nö‰¤O÷îBZ‘0Þú2òhJª° ô]—v É9w±Z’a$Ð{.ÞÎh °ÆO±MdÿÄ‘y§N³Ûô€Ô8n™ºÁöq™MÚÙµ3«}ò'³ÚAµ5¹–ãË-T¼ÛÂ[`žü?á˜r’n2Ñx¹š8” ši= (ë*£5ËY8ª+¥ø"FÓ :co²@ (ÀétB <íœ)ðŠí@èŠ)"®¢´Jù&ñþ¼(ÚžÓ€­«„¬âí:ë$§cPA’¿°³æ‹JëÛ߿ʦ1ô”ðÏ áM‰Ë5˜ cµÀîÀ{‰Ël”’}¢ú¦Œ'ðêp—ˆ ²Ð-2¸-+² µ(Ùº£S¸Kx9[) x¤$û­ ««:–¹,Œ),Z¹ Ù;8ªáA€¡Rí++/»Y§.Ù ‘±¨<¨© ®ÑnÄ:' X›DÂݲ(ÚŸ‹T¼BÚ¾4 ã)Ä8ã.ÑÀÄSù1Ø0KÃB£ð+û{»h}7 -8ìG;y›Ü<¨9ȬF¬2¹!p•SرќÁaÀ—RŸ)6Ã#?-}”s4‡ò8 ñ”¹Ü4¾ð• K´ž9öµ;O¡Yç% m­’]‘´±ºæDk*2ÁõűOFC‚²¢Ì!ê“ùn«(þ;“È•;€Ç7è} s`Gúñœü:œ,)ûG3Ûí5²Ñ¿º05¢ë¸ ä"¡Â—0‘#HyÂh¯<45#,±Ü„"T)D°x•*úNŽÀ˜9ÅBÌvÁãTBº›¹·“+¡T5ºa‹Aˆ~C¯?Û)µd¦?C…8¬eIz™¯xæ¨ 7H´Ÿ.ÙÓ¡ÅE!½¤$ÄD}«£ù®cè òG‘Á>I&h tO• ²„mêcAÚg»1š'3ú€݈¼IšY2:ý1¨ìˆ9 á=¸Œ½?Ñ“Kº ÊT!“ìËÚ¹¸œ6œ²Ü#nžd´QÞL:1¯K³ÇãÌÑA¦kЍú8ŠtpL25Ø~“ÁÌL€ñ…Êz0rýœúÓŠðšœm¿´ÐÃCN©ÜÞë8LwÕË ì££Ý ÆM|²Òeš¡IJÅB©ÑWqÍ;âÇÕájÈê¿ÉBVÙÔÕ,ÍžÒÇŒƒ½1”—S "‹SÐõœtä1¡Á™ÑùùI6m¢¬¨3²:r’¿ûý[Èï™Ô¸$8ó˜ €ÔY¬aYepª›nÝ’Ò£=ô8ºÜ_Öå%aÀÕÝOóyG!½4r ?Ú¬G *W°)¿ ÙiÁp¥H@s´QV*R°‹i/ÿÞÈ}d¼x“…§ÂÎÂíbRÄ•ø‚[Ó]0Ax¨ ¿‰³ºÂ"æ; aÞ:oq•ÇML £ŠÏX²?%ÏÒÂc‹È ☈hí&´s“hä•GB{,Õ i‡K¢„ä.4+iB“ÁÇ._9¹ý¥jl*SÁÝcÆ ˆ¶ª<}Þ¡u³ŒÒ"uŒbÉìUÜa ¼7$€“måI ¹P<?ãAu9Òý÷G¡pdIàã,¢tÜ]…Γd`µü}\“j²ã‚žB ÙC$í×yò¬ˆL2M¥ ¢ñ—©ÝOËÈP4—ÄTGuß«½bM.ß4dsµ[dyÎòŒóìK;EˆmVUØ£“ÀW9SdCDt81©ÌUð¯;Åk/,w J¡¾(ÌÖô·‹%iÝØ$ EJ“›¾'ȈãÖCÞJ¦KK3ûÀ_up^Üý‘þ"Oõ®‰ýÉËBÒ àÿÇ£Á9ð}]5@ßUs<ðÁ[Ü`ÆŒÒ)kEÔÄ>”´‘þW4EÜäÝ”…dºå^Õ;eœq,QHSÁÚ¦uÏÙt_Õ©$œó 3:ø9ruO‚QSü T¼¨[;8ÛÊ‘\5ÏÆæ)jÆ¥mÀ—TÞ`ôátBÐçé”ÃʧOR¦Y‹i5dz1Ã0°íç¾–f£Ú 0ëÅæ$J¸®G=IÝ+OVüE”»ˆèíJt@U×lìóAç눽˜52²¿‚˜>;&ý¡­}*–”Ô%Þ³3#¬‹nHÒ%ŒGÀÉ‹*¸Ã;«³ ±ÝkÙƒÄÒo\&@á=c¥ršAš¤Ü1„œU­GÎã/Ù8]Æ€™PA–s^agå½~7Ùà8]MÈËL·ÚÞª©¶Sé4s·±›q§RV¯]xÐ1 ˆ,’=dc#’ú§ß]£ÈÕ>g´4h;W¼…²­EIëÛ6QPàzu]|-ž\ÆV@?Ë2>ûå[ÉÃ8—¯l*>èÛé¨ÖJá8ÔHkÿÕÈÞ6ÌòoÉK‹x¸W+Á¤h³‰¥£—CÞ1Çú PY¤¤E{çM›¼Ÿ[D~ à4!¿Úä>Äo?%np»˜ 2u-‡ÔÍX9ìÈ™‰¤`»En ‰Rp|K´ð©e‡Ö/T“ZA( •ïõ2`4@è5Ç‚ý›~³s¦rQ£ä…\¦öf 5`•×.&YÓW,À×~«¥³ñjmø À¯ÙjU…vÓñ:ß„íÆ õ+²å¡[ÖZŠú ®»O~¬b²Ï?é]÷Þø©A¦R¸›föü N1XµžjvÈ‚«<5o}€6ÒLŽ™ ŠRù%¶æºÊ,ÞnÂ=ÏÇNõ-•ö¹nš5ùªåq ESî3œ.ªåTI¢Šp O%‹HÔdÃ-<¶#’v‡ÍÎËìÿz r8·ì3¿j@J+¾6Üý³ËÌZ`;«žéKb§µå5/*â’AÆ=²ÝJ ‰ŠÑh“Èu&4ÅOk”þx¿ oÒýˆ+xZêÈúy äM_à¡ù3©ÏÑš)ѪE×LÊ€Ù»¤•a;<ÇÚTOukA€èËÇå¥D}¿8OàÈ>Æ£Èqu`\=lm]J%“MÚ•Wøüƒ‡€9Ysý7pˆ"ƒò5ûÙk)êwB¦ÃeÅ›3:&Ñ^auú‹4r³ßð(ñ½.Ó¥ªla,”4R€¯m0wmOçÙkå!ïܰˆ‚ ÏØCúÿ†A0`1ÿŠ¡OàeõGa×¼„#‰Eâðè¬ !+–EãñHÈ/‡K&Óx„Js Ê Qx¤:/˜Ã¡Ñ*D2)S_ùÛþ˜FfpØ$| [~WgPið ºü«Äà@kCæÕKœE+`V½Æ¦‹ÌbT#Öõ1”Å¡SÚš¾€øx„~™MºÆi/ú²¢Öa ='Šƒ[{âo‡>ôØ ìB«2…iŸw8¥  ×Q*ЬàñÎÀ«U¼¤f?Á˜€ê4(UŽ?#ë°yˆ%]‡ØîpëS_ay–>å©òòx³Ö[¼ ÒÍÂ8±v»WÜä?¢Zë|~%ƒÕø)Mò…:êš ‹­è“¬‚· pˆ©,*ø•'âúý?è«Ì,l*Þ%k›²¶JŠ%¥ÈBÂĸnJŒ¦«¨õ!ŒXú³ÑYú‡&-£L‡?ˆ €B…« 3=!*)³ö¦Á êúÈ€ ’z‚IçãT>±k‹%¥Žã º!I²N‚&/¨Ò´Î£]0 Êd³I‹r·Ìª3å +«šb·°¬+düÀ/²;¢dØHܤ›OªÚ% èúÇ¡“@§¸‹ì)#î£ J«s vÜ!kJí°×IQ„=&),ÊÁ¾³ 'SÈòS7ÀJœ2±+¬.öŸµ³¢ÔÁs¤PË«zÇRŸÎÚxËÖ ÑK­âJ…gL*l·ª8äÅy –52|-î¢.±´+r¶˜µÍ̲ŠÄwiÿž ÍBÉ_€-•×X꘢ݣö&µ kú½#°sÎg!,²íS_õƒ¸ÜÃˆÊ Â{ÚÆ½º` !Hd,z$ñ"eƒ¸£ ¹ýÈÙE`¹à _æÒ‚SD-'ÑÔuòM0¤'º:MM~†¦»(AFrxc%+P»–|ƒÚÀØÓ"–Œ\‚t÷O"ñà%©ÁÇüÉ1¥”—DÒ/sߤ«·÷Ðʪ63#(¤¤õÞO¦Y}QgÔ¸¾¹HGÀ“xéb±œžD…7|´'w^Ud|¦Ûíá«‘•‚«Þ[Ó§0ˆ&tòrln¹=•3g[«C«ùñ®äÂM™;/ Ó7°sßÈÿM©±µÇnäRü(+­Ae½ô$gà-yÀ×@·^@ݰÿ0fh=r4FÎ:öZEؤ“fÝ Øó/æ:·’6b£K%-¹ÂH RSì)¬Õ¬ÂÅÒƒM\R} º ÅÀõ‡áë3Ìí–8D:ÔNOà•§â6Ö âqRH†4ƒ’ç‰Y#ðnH–ÊÚ ´½¿2ÆÎDv‚iê5C Õž[2Utñ0èÝ Ü"€sä Ù>玚 9y1Ç0fää–™Mp]ÿ®~ûšŠ¸b¤)µšgrJÒân†Ãøñ8DÆ lÃ0§LÞ' ‘8ýdä@Ù:uhDI®‘ÉÝÕ¢©¬@œ1¿¬¥´Çy~¡b°? I~¹ QÃâHðfv€æàá{ìd³­TM'ç;¬®˜råÇP ;ÙŒš€’¤Fò7Û”] a¸ˆVÀ‹E,qv`³©HRäÞŠþ:ÌÙàLXJ»‡®e«# û‹ —‡q É%•Øœ…³äÒCØÆº`k!!Qy+‘úò™T®&.žy­Â̹¦pÍ™ÈCÄÛ4›#e¾hqíXÔ°ÿ©0ÐÁY×+žQ®š¦>‘wz>ÏýÞu耤a…:”±ÙKZî–¨G‘Ó0C—êØkS]ʲÉTñWqaHN…áìJÍCÖqV?YØl¨ù ŸlQärm]J™»"ªÕöšðYq•JJGØÀɬ۲¬°õÊèvT\!²dí-UQ÷#žÛò’ŠÌX]F [ð)«J“;x—ùâ„JˆÖçí ÌzadñÚÑ5Öd­Ú¡¹ƒ¯¸õѵ-ãOlÂÀ³\•eeW½ãÜãC_ÈË„„îù€B¢¶Gùo6FñË- õqcòÆQ«Ä?¬ÛÔ•ð˜Ó\dâïâ.pî¥J¦3s mRrб™s)A!U…½¬4 |òئbË–…Ì*ùj"-©Ÿ1)– Ôumqâ·‹úWOe'QÌ<’rµÉßIN°Ã­‘±E Âq5Tx´¶ Ñea$o¦bys`´(dã’24¾³ê †Ï% ‡ñ¡•$(·¬gÖ?YžºØ)Ò)+ n§&mÃuâœS8ʼn.¤Ãmðõ XLëOêJ¸N!§S. VZ]5ÈØ:Æ=³äM¶·Þž­uaQ‡îR‰d™®Ìg2_`2B»'R OÆl_Y=E%)†drqMvJî_Èuî¡â)„Éc2­ëh9»©s,öK8ÐíkŽ_v —5Ú0c¼•õu2j1Û3¸cÖXÜQ9‰ŸR¡t’³Žæ"CÏ€B©ó¢R±uíÛçž@*7!¸jñ38š€ŒêÖ/¯crXS½¢´HuRCW€êS]5v³#C¨"aÞ4É¥¨ækãMzP¹sÒØ]C{€tˆšÏMgd„GÕ ]åCðŠaÖæáý²á©Ç5Š‚d\Z–‘Ú>±­$nr‘¿Hô©§}£·Œ.´pÚÒqt;<«/æ„!T·•½§ÈÏmÌæîòîÛ²)ec*Ò‡Ó÷Œ¯µ ³ëÐë ÀÊ™¹iÜÏEÞ”Y|xûëÌêÝ›á25îè7µAÖ©èÄÍAvßµµEi-cÉ0–Z*ÈÈ@ªÁ¬×©˜k©Ö„L&†ãC½f;Î]k"¬k³Úµ¬0ýïÞaòËëÜç ÑaÂËV‹V¨û±÷ù†¤˜Î«Ïýñ¯ì¶X\Î"ôµ в÷¼‹Á[’Bú/$´[ úZ4§{U Îh¬¦ï¼”'F§‰â8¬6…"Ðc)Œ´Eh·ƒVRKjˆºênhNK„åiÄU:h œ~,.‹N6‚Bl‰ØShfFˆÀk¨vï Ð)êæ&)²ÆÍÀÙVjh]‰Žâ¨j|(“°t*¨…o¶‡ø^Ê Î"î-êNí¹6YÏ8upHÚIv´p c\Â"G` R‚ºÐ$œØG ˆÂ2nàtâ‡uÚ9bG§ ƒ\‡i- äj ƒ Nç.Ñ ZO«©Ò=nÛOÜp ’YÑ_‹(ÅîÓd‘‹#g¶Á0 ñÎègHÌu.ágjÕíÜ%ŽæP×ï†ß!þ\ãÎLÓNŠŒøþ Æ"£\þAb È 4' qÐ~Ÿ1¬woÍâ c+`ZIThÄ+‡6&.Žp‰{BÂ6QV‹“„>gRÕb$¬­(˜l\oÒÆ¢KŽÒãGvC¨½¬“D¥%B ¬î¶!ö\ɪ㒠*±væFtèDøt"ã.RŒ Tj&- Ò8Іk¥àöƒLKŽ]¤<ä¨VJPf- ÎJîÚüëx"ï¨#k÷0å‡Xú*ÊHP^)¾«BÃÍ2ÍÄ»‰üÍÂ%˜-¤nÊTzM„ÊÉßË8ƒVW°L¹R¦ŒoÜðj^ËÊ.¸Šw ryïØEbžihø…ŒàG<ÅüFŽàŽÈÓ '!+È‹Žtt„„pÒTKýöÛÑ4óé¦Qp¡…ÅMyäV9‡qÔÃr6PµÄã'oT²Nzbîœ{l/}ê86l.ë&€PâÔ6Iç.†¨¤ª¬)±¦ÔB;Ëb0ÍRͬÀ*nšD;Bje/qÀƲ$<ÕÍ\ðJŸ+ÇF`•D¸:VÂN~ym(u'Nk³!ìÚüиÈ/,ØEÍ.(ÌáM "䂉ɨ5s1$BV<çèÐËi+&ÑŠn²ñN*q˜ÜÂÔÛÊ•2 @áó’(¤ír¯³øPgR°0Oˆj»Lj$¢—ˆböÆ€Ôâ%,]Dò ˼ä"ç”ui\>¨Ž#"ß(ÐÒ¬†e54R‘’\òŠN}BºùsrÊNöJLzbÞÀc¶NÕÓÐ%dpc+yX#Dñd¶Û<Ï…ƒÌŒøî@„µ£ëYm^ILËPfO*pŒi*”ø˜í¢ë">yG¶|•ÕsðkÕ‹E<¢ˆÄ#çR"Ö%2,‘ƒ›£LŽFt¶ðëP°lDV•Ë9AlaŠ]`í¼Ù%ümްAf?I­h¦-;%öbôP¨ôaúúµ·ST¨þPmCÄÿ ìº:é]aG!"®V¹G0­tçJ²13èÇ/ãáN ÀƒÕëHO*"èDiåz6!ˆoÉ>Š"X¤1R‘ß&¨ë,ë2;a‚.!¯VÉ£K…ì‡nÚÔò\Ë4eøÃcÈÏ¢¬&†füæÒohUêêk^òrËÍWlÓJxåibODp ÎÇqÆjÁéØ˜lí^¬èåe ¼$uHaÌiT޾uŽÆ"š‘jìÔÔMiaüÐeÁt2FÌq:¤$6ã {I*)³Û0“ôœNFÖ G–”ÇékÈNKrÎrxÈ ûÌÕ6‰0=gˆ“ ‡>ç—QÆ„ke¶HîàZHôVwD'&χXÎö¤5U)…Ý"«²“ T>ê–¦&ö©Sê¦æ…¤hƒÞì¨gz`éaøürZ@dÂêªL'JG UE%ì4†Ç¤c‰S$Ñ ˆ£Q±`ÊÊm“*žPËÓ)é4E¤ï6czM½DVbÖ”gz°¢íh«¦Ù£‰%…·K錹C™UOGôxÙ2êË)ï=kí%ƒ‡cµ#M¬ME ¢À ä-¾Ôò=÷Z¢·„nÓDïE¤/Vi:¤ã SãÀèDе"Ÿ¢êh ×§ PÌÒM _‚æ•D¤·EíJé2äˆztõ.}Ê$Ni4ÛHºZHÀtatîè—X—å‘[‘Ät„¯,©Ø¦X¿!ø˜m‚)|!Fç „—2AeQ¦µ;LÚÇ4„¸Ô¨n´MAn´!MVÂÛ-ˆÓV«~CÖ¢K¶ ¥Ñ:øë`óY!¢³²Ð*ìpÛÙ“òÇ”Îh7%•“ÆÃwôIûKM0å‡c¸ÐûÎÉML•;<VW!3ÊC/1þèúK1uÙÅÆÃÇOG Û)ú½>óÜ^­_Î7ú¤CÌ7l5õ¼ù²Qu)¶ŽÉ«ŠÝAzNþº«7ñ`ÓZtÍØ÷¸Y!ø‘sß`øn²Ðþ#fOâ&‚s)˜ÊmнIá+ògIÃ)Ò]`>±{Ð\Ê‹¶)#VÚÙx~üÈ€›»NÄ^ ÚFgžºëÅ‘'D² ëƒù>–—•ŒièÓ¼VŒ€®g£9ŠíHþ'R‡Žn·„0œ0-¤k =øª„©cêÎG¥îµ;@Ãì®:½Ì™kî¯Ìª)70Ap/,8I(D^OÏHZ¹§îX+¡­ðhu8£¸2lË9ãežWeŒ¶zÀ V̹§ b(Õc¨Å­õ$Ö1`îN«®á õJJìoY|F´·ˆÓ;³yïÁøüïÜpœc’¬?Ÿû3Ê…Üïi‹Qœdhë0O5¨ÃÔ¿}™ñ‘z(j†°3Õò†¯˜·‰ÝWìÊtîn°XÚ«õ[K[¢ý~€ €X0ü…?á×ô>ýDÀqX˜ AØl^9‹€d’ä‡CàÀY >/ŽLb0 4Ýõ9NãÐÇ´þ[Éà‘xl9}R)€#î¡Q‚ª4èå #)‚R'¯ø¼)ù#’DiÏ›5 …&Va–gÍ"/-¦I#5ÈdjN‹Ô@÷ؼfcU Œ4ÒkM„DqTà%`¨ÍÀÑšÄ !¹Ó1’L„Ê‹ÍÒ3WKÄ^ ˆå¢ºP ®5”È[²–[5"#i‰Ò¥¹9½"…HŒØ3¹ÌÆ„rÓFó1ÝT µÎ¯Dïémƒª íCl-†¥ ¡uu/þ¯‚3¸Dö®^ÀŠôv‹è£§GýË„%Kº÷.«õ ‹”Ò% êfþŸë±þ«¢¯X§A«ZŒµh{t)P@¡%èÓP‰¸¯àÃ Š„=("£¥Ðqþ§*+G bHð8ˆîâ¨G¼€ D¹ª1ŠÖ¨‹Ú ÖqkÆ– Ë^ž·(«)«i$WN∱ NM°= L­‚¢ÍËpº#:$‰jê’O ŠŽ>èä<CS|FÄ#‘kè­Q+¬-Ð#.šÉ-Â'¸à”ûÉÏœ<°*9Q- Bª„2‘kà¹h»(ˆÈç¼Î°¢p€ Âîò¥2ŠB”ò¢.R™_Ÿëaþ¡-ȺÑ(ºO‚=2£’%&),øÍó\*´R©©û*É.‹FÏ êÿÀÃ!IAó™Ðѽy² u@¾Ógìi^ÌÌ«T*h0Ãh 5Ýë› µÓ•H°RxWpQôœÓ€áÎ[Û{ÝP%/ 0XXòº,ƒËXÛUÓ‘<*å[<«VW²}žŠØÈ5wæ'Ú3"\jP¤W{eæY  «®jO ·À3òä^~OœU<|œ;œ‰¾õµ5t²(VÄÂö»‚Ÿna§,¥¹L_B' Ϫ„ ›§¤qm¾¬k®…VŽ‚ƒÐ—‘³¢­±ò–Ö̦Z†¢1hÐDÒò‡!IjZØ;µq¡êŒW\N(¥¢†½•Ûêq4±BÏH6¥¬÷I=¸Èa1_T´jÙð ŸžÊub"kÿÛñÇê[ÃÞqªÝGÃOW ©Ñj3ŠBݺ5M¬…¡‘'ÞPlZ8¸µlÞ«œß§>AIf¡ ®Ð²×ÔÍ(˜;0X»ÀaOÜ!¤.‰!`yíy&ôFIj&ƒÄÞe¸[›ên„–@Fâ«#´>)÷„¶CJRÜc†¡ˆ0Bˆ¹Nzke2”º@“)›8d)–·4ÝáH;,Ô2áZÃ{J #X´\ΪÉfå(À’P–9ne©U‹2c6ç_˜{î‘ÜFE¨ËÔù9L¤f?!ú…Ú`U1;ÂÀÛy®ŒAºµ–¤ËÒŽ+\ð0'.YBމçöÄ ªWó¼ŒÎþ"„<å1”[ieG5&Vº»3kð™B”[`ìVQÇ6TX<xŒ1O)ˆ©Š#MëúB¶"ºÄÇùQ"&QãÃØw ¢ÌÃ"ÑÙ(õÖ¹z“Kf¹Ñ­å“\n¯ì‚A¤(ȈÔ@!S± ¥µ¦Ü߬F"n-Ó€YÐÌåÓšäÔ–•ùâý!ãíBPÊ„°ø°P‡­ gPˆ(ÚCÙŸ@ë2NWd°Z³­Ç9‚§Dm‰½ÇbÕGÔRCJ‚ºˆ‘¹à뜺9Ã0‡ê *)îoÓ¡ôËJrÓWnEvCÔVüW™B‘PHÈ;Ê?J[,x†=f2^ Û™Hó±nsîX r&îò YºX*„ƒó¸¡=1* 3OmóYnTz†³¬í=qÔV„äl1% G«Ãßã á± tŒ¬o’¤OžÌ©)"ƒ\ÔeÜ£˜ÀËŸw°aš²þ•­=åºòÛ-`ÿ€‹ùû1êP+¶Ö½¯Á:aI#y9°æ 8©_gœ¢ÈFØûR´‹Ì—B4Tóx„߇Ù]žÖ>{U R9sDÜØVBúCU}T«d·uWeγ?FôµxÌŠnBh) ’E€3‹jÔí·”2Ù&­œ)’*žA^@{ZOT%A+º¹‰z- ^4.M¸€5°ôE(p‡¶ÇÉnƒ1Á’€é½g!÷›§WZ˜äý¤è¥ MqëiÚ‹î­~˜Ù—P9dÉÎÕ(•¨‡°x䑹HÈð¾ÂçRB˜:þ«£ø¥"FÂt.ŠËÙšÅ]½;®lö—Uú9‚© fo„5Í‘]ÕÙ-Ål¦eILwùL[‘®†e^•,¥å>tI ¾ðáôKhúÓ\«EBpª{¨65´Rˆ£X“ÝvÚ¹ÏdÑ8p‹ß«PC7Æ¡‹O@i¥I ×5Éè–„r„I}eµbû‘̈C(ˆš?Jø¡ñšKÆ•ØÍ»U™7jkNb,øE[b@ëÍ ÖÊ'±ôyD{¹jßÃþ‹Q]iZ6¿PÃ`Dd5}2ŽU©3ªKZ,ÞÌ% °ç‘Ö Ç'ž)L4N¦CìÝøÄ³oÒç êÉ‘\ì¼ØäVWŠ`œ¹RC)CǪ“®'HµW2rï­#RgE¼:´ªxæÎr`æhÔoæµû±9c'/ù®¿¼*à¡éý<ªã3BX&°ú/š/)‚ë¸û¥0y‘„¯óÕ€I¤S‡Ù%Kιñü9j“,AX: ‚ßû)8ºk.ŽšÚÅ­Ù ªAyŠë‰/x§©´´s¥)âô;hàŒž²ÿ®‘”³4¡zþEY2¬Ye#§K%*0żSGAº…2qd•±A'pµ'´BÑð.²»p¾žkô¸Siø‚±ã 3A°Ãÿ»Êry§”{˜Š@nDŽ#(Š«£V 2€(µ!sW¿Ãv¹¨¾ŠSä¾òz3p¨àÄ›Ã9yŠtD¼0ƒ?»%»*å±€29N7›G,˼/°ˆCû)½$Ú±™Ì qÊ¿ËK'Ä’˜}‘«„#Rt%ËÇ€óC#  –¡p¥Dì'Š˜¿|'ŠAEÀhæ™k-®ëꈪ¬Ã ÈæŠë_([¡4B†DQ¥´$Ò1Fdk±a˜*X~G`ú­¢•;„¡s'6bÎ{ ˜sžÆ\#¢’Ddz\`§3££‹…@s˜T9š¡ß,{;:€ÛĽ1]¹[`¨ º°3¡$”#í3¡;—cºROCZôI ¸"¾S1Å`œÉ<,ÂTrÁylA9}‰Ëä™ik§$aÄQL!¹ÛŠA¶:ƒù“;¢…ª¬$ ø¹š9¤JiÞ»ÔD³ý˜t£F¢Á¾LÁ@ã6¯ž¦ë €û C8»ðÃ.úü‹1¶Gä ’«%˜›ˆ‹á\“3ó#üÝ(bð€4‘\à’ ¬"Ã3FÌ‘ª©;B†"¼ÒÁ¢…ÇJç€$ÜÊ⣡®Æ‘§?âç?ÛjxÙ‹2@9“ñÙA9œL°|-˜ÑÂhÆ Dõ=¾‹ÁØ ìÿN!]¹#ȇÆ4¢ÐÄ80£‰ ÈA6•°®»ë%6³@·YÛ²(ƒˆ¢´†àû¿2%ˆ ©¹Ã bÁtÖ;¹8G3¯B ù#ÑQÌ>ûàX©¥tºÐØR²¢w0×? ³º‡(‚ ÄrJù2*AAÒ#¢ùHñ˜P×9Л–K˜Ê8…7;@¬ö‡Ùåºé´d/C}–ã0@].¦ÓÆ@äP»vÄTa–:1¸Tš¨Ry+ÕšÚéj×OtQ'!DÛЌ˲“ZA4Ý:T/A3…@ð¨C€†jTEZºTø¨·ê|Íá6¦j;€ñ6(‹†­ZÀ:HÆb{JØ  ×QãÖ%x‚ua¹Œ´ÎKÎ܇ʈžkF ®°Ê0 c²|ñÁtÿ-ÛÔ´  ºŒ1{ÊCej¯ûœ>`¡É´,Kg¥T7ÚèXð žlôÎ!¢À ë?EGËôŠRKøžš²ÐÈÄÔ´ ,xÞÏrì&±:®@>3c<¸0säÙkØ K£iU…Òòε-GqÛÈå,SË%(á2Ål¹:éMŸ™±Ar>7hûìÕNýÒ ¥MJTó8³)-—5˜™ˆÉØ„¦º®«Ç Øœ˜;: só'ÛÆÒ ‘”zÝ'p©¹Œí6C!‰ÈÍ”è~œ» #úº"´S` SÙBZWÀ§Š‚ Ot4[‚#ä§ÌcÒ²qÒñ 9À×ZÊMÓç’L&H’­‰¼¸$RÁ½œØ(eª±4y5´Mœ¨ÚÑäI„Y?꾩‘ŽŠMº¿s¼?°³ÀíišˆœF‰¼xÊü¿5£ü+¼hO3‹ =x ÙLHÄ¥Ä5²Ô<¯$UC0ΔšÚæÅÁ¦²È¸£çZLÚah–™$«Ý²ÒŒ¤SØ™GÑ£¼!ËFypOSª¹ËØ2n‘ë×T±(Uz¨)©ª©d§%ÅÑô ßœjPªJ“«í–S#y EA,û5R/C… ¦µÂ©;²à2‹à_Z¾ŠÖ uÔÔ'S3y¼b^ÁlR€)ºÞÝgÑ›ÅQ»öÕ•´à",¡+¤MÂjæÁ`}³ò+¼;øÌ:Б1„Éë34º'’Ks\Ò€Šs?L–‹U½c Ìœ.œøÇBQ–Kɧ´u“È`-XÀe‘£¥$ Ûâ¼ò%8529®ñ6Úô‹áPÔ{AžDÿaô«4ME`J’¾Œ’NëC¼#ö«ýÀ]Ô‡ÌEX ÓÓŠÜk™*„(¹lÕ•0`XéE#‚¯ºŽ4n•ÛA“z++8b¡Ñ§UÁ]®Þ@›¥È´õI\¬ÌÝ#&:…ESÊXcÚ,AG²ÀòŸ,ÛDصYûý #ó œàŒÝ{-þázÊÈä ˆjf‚[½)#Œ¸Nsz‡£We„65°3ˆP·bc£×DžÕ€âݹpm(°¡Õž64Ã(‰–9e»Ô&²>B"6ž3±ð~Ô²šbÅ÷¶j:[ }dcLº–EÛ³^è³9ÊülÉmá¹95×ðœŠÉ쪗š’¨áÞbm}á=äen5Ü!¿º;<¡iÝûã´ÃÖV‰Þ=+Ø~9©° fÍË4:U;I‘²Ád—¨Ûa“hy°›‘Ë9p-ÅÁX~n4cd¥\)Ûtfl÷”ŠÄ¡iÀUzˆRµ¯Žˆcœ DPß~d!ÊÑÙ¤óc­ÇéSÓg²(fý jKªÒ¤¯R¶H€ÙÎq¾Ñ sˆ­×;Ì3HÑä8è~W¢ì²NU@@~]ñOVÖi@åÄJ´1ë¶S##ÂôžZ"yo:8ˆŠœ ˆ¹¶>HÚffakË–4r+üoΚ°ÊÀ <¥Ïo¾á>Í2S}¸êÂYéþ*l“:î€á̬1[CÈç™Oa³£à­Œ#±d“Yð;`TéËld}GlªP¬¸6.‹5 ‡Ëi[†Abn(D㇎Cô‘2ÅÒ@2BýÎ>Ï›bAq›„Ì;ÝjÞ}‰:›h*©„Ñ Í:f®m2:¿ ç¾î_l…µæ*âi‡CáROáå.—™ÂÑiž—‡2d³¹9ñ }ËÔXÖ¬ªßtÄkT¤¨9‰÷¦¶å4£•ú r©nF8è˜<È`1Q 0èó n"•A;}¼Ø~¹²n§DMÓ”ÄÞ~õÙɧò1cµ¼G¢~Ñn¼¸\°·m¬Õ†žÊ[»-Nh0SƱGÖ¾“,j¶ÂÁˆnØ2AvÔàòš‘•°ð¹ƒžkA†Ïsˆ½X'F!ÅZJ8˜i“DÙ„¶ÜpM³äÄØ§M yó%ƒ:}ÜAìe.[,E3¤áÒöœâ}ý ƒN6VIžÔJëq5 < ,#‰fðŒvãü¡=IVU <>&‘i¶f·4–/nˆÂ›bü •÷3QÏVóbCªgøÇ`y­Ý½ƒp±Ø›NÄvkŒ¥…tQÕÀ;ç®eÔ9b×£NBWNp2 FU@}­ÌÓoÉà‰9L°½:ߌIZ£.‹ÂsÃk™7+Òm0:â;Zt(=3¹NÄ4eAiÔ£$q2s—¨TjÆÎ·éY“Q-­Q›ÞÖèf1ÁMט16øý]ÏgXƒÒצNH.x Œ -Í»–ƒlI“@ט¾ÂÙób¤‡õÙB/©n¬Ä!° Þ&æDpÛÕdÃâm’Ý'·¢Ä +³Å-+q–: ^eç< ¿MIrpµlH×6F³ÔÙˆõþkŸûºŸ%»Þ¶W,ø^ó†X²cî.nÞíàtùÞuR4¶²YËÙît$@ $zH‰¾eRi#ö\˜L^Ó9sö' “Ã!QTõù? NàÐ ,F ‰Ð"1è¨O7„DjPhU ÿG„K= 5‰Ñ#‘Úlž­ “ÍkÏèŒ6'¸\k°iÌ& 8’SA¸»êkJƒG­q¸}ÿ¹C)³XËì•>l  'ŸÉé¸ÙÔ›ƒƒSi´,c„Mf²xö6="|^ÁËmº«G¡S]þÜÍÆvïèõå C2`,TV¦ÿ¼5wžuR Æ’Q&°¬lôÓv®Ò @¦óiÒHœŸ#@°À¡˜ÛUÒå$èÓáý>&ä9ë¨Ý¥ËBH®.*C(Ä? Ê:³6ì:&ø¨®±üí Ô&ö¾î” Ò¢PXžñ+ŠŸªÊ$†=ª‰©hëÞŸ‹*Hø?k|û ³P¦£Èš¬ú%Îz<Ù2íQû +lˆ~½-üt­Ç¬ ®(‹—(Œä§!6íÊ:ð;Itp5!ú­7é:€¦EÊú\¹ªñ'-¦È{08“;*ðÁý k†¹CmL¸".[û IGêbפOS¢ðF:£ Oðù€hS?3ª¬îŠÓ0`†2-Ôí€3s|»Bés‘@JÈ—"i™ìlX m|˜Î‹Z=$•òÇP •Júè¿éN¾È(z<¾¢.C#D¦ª"Ø&©‹Í:ŸÐÓ•E€µ* 0êÕÌ„U*û1}a6Çj“£3Ê Ÿ+QõS 7ˆ­KT¡“€ˆ±°¢+Nâ2õE &*”¥NE˜`—CƶHŒº*n—3.£Öðå)DUtÝȆy«–‰±±)7ëŸ5AŠw¡ª€Æ­z3P\wûBм¨DÊÕTbúªN\5( üÄ¢kêÁ*k–¬‡!ðÓ)­„›+9z:çÁ@˜ç$B.Z ·OŒmÕ… ÚÆ}OúÆ53X4§ q "­¢i\Ž\UÕ©ú†@sÅ]Ÿ«]KC6îDénÑ•%h (•;<ÂmU>T½@ j€O“Í­Ôi…BÒΟì=‘@cPúÙM!¬b3b%²/-¿ßÌ ;ŠôY–ÏYž&޶œ›ï€r2:¾ÏkΟѩw8-ttÓ¼•›ø3;‘RéÕTVBHýU¥Š°ÓØÚNÉD º‘ÎðX ! ɰ ´¼p©ÐJeÉ€rؒ€vÏQ7ÖËÎc2-o¨™e”*qÅȲöG&Q$=¬-¬ø 4,D=g]±6  ”FÛ\p&°áéòbÌ !°aGå®Áøwް)©ññ»Ô”r"tQÈ Ûœ¸)Y%#¤) SäüÊÓ²GϬ~2(î•ÈZSoÏÙr Õb¾HbôŽ„ü¾—'@Ò ¨h†¹15îÛa(‡ Èž¤š™×³±G‡qˆ/ S(¤ÙI!K‚øG¦xŠ‘ã"€ŽDƒR–JµUÐZãpìÍx2÷îš ™‘zõÛÙœ Ì6Qj9Íl$6QQ¼XØòåÚ7ê+*•²H›z7ê :N)Š’kF\pô„Mw ¾‹sdÒ½ EI9D‘±t~E8Êζ!ŒŒ}®t×5GñÈ‘cñD¿ÒÖk(:ÜyJ ~€èæ]|ÝT E)%6oÎ{…$Ÿ•ª Ìi‘(’”†Éò~°‰œCBrZP§É,t[;íš-í+ %¨˜És¸~¨z€JTÌJ°O‘¯’ÖðÉ­8HÆ€J´ÇßyÉfU-8h3+Ë‘M2&¢T&0>[­(d°„šÀ¾“`Ìœ lPâ€w™ÑZ)µÉd´Ô rôyÃíPDj¶æ•M ‘•¡µÆ_Z§ee¥÷+Jigì^F´Îó¢Ä‡Ü4éVÖ(M7¨¤v­4©Î9ƒ)¬}¢b"8´$èh—\^wM•x/+ã„ÝgD0ÙSaù:GÜÀ™üàÐÒÜðR´¯?Ðþ¤©Ú¾HQD^‡Šã“#t,ê¾Ô­9aÛ|ŸÌÀðO¥–žÑ'9í£<3wa*¸ê¢¬Â”Š„´ ÑÀ`SI,,Óy¬ ȦÐÈ;ã…š—QqN·URMl%B@OnÒËÅ"†•L¡ºL×ÄǦ‡_é²k OhCRÏT6Š—×iî~–¨ÈŒÕ6æå˜9]´€á'OÕ¢Ÿy’ ñ“ Ê>çÔÊ&uT(òÓÙ\½Ñò¬cŸÕ+ÇDöÄK–üÚícŸZîÛÛá-…,È ³¢›Ó! M]Ëå¬):!—«^|ä^I‘š‡ôݪŠÇÌS1ÜÌ”t:k»ì tßüR©9Ø/ºo§Õ.¡Ê—úÎçÂ:¼_f`aùý@'‹EÊô‚ø,ƒ+xd¡Ðê©x3ÐCd{¥L‚BÔоÝ&>FNA1–ò£gÒîm¬™™îkfÁ“QkÖ{óxŽ.hd T¿Y‚—yHQº±‡W ‹ŠAø•à—"­‚—ÍÀbÄþÂz_h—w ã8€âỎ‰>ÍV…ò¶îã0*ÐúùTˤîèsù'åTW¤@ŒÅ£«Ú‘à¶wÑwÚuéÑýµ}Z•©Ôª‘ʽX·‰vç¸#­ÔØ(šE÷Pýxéò:Ê%ÈÌ*©÷®J¨þOX¢“í}d~¥jøñWúª\˜çyËZÜ»mR›g¤„"ó’ ºcX«¸ãµ|À`Ñ£ÚäÎü\‡¦®'ªk¸"&ÃP§øË/.ü1ßrù =Ä‘w9;˜#£ÏÆ+¢`5&Ýä` l!c£+ÛóP† ¹k Ø)•Ö"Þ¾IÉ¥‡eÜ§Šœ¹õÐzúÿpp±Ó§8PÝ\g4\iý'°¨ü|K•P1VÕÛ $?¢^`CU>6«bAâez¸.$Lm}V°¨+Q*¡Š§JÂÒUñV*~ Iðo6ã"Ûm‹°`žb\\x!ô¼ÑÊ„›‹¦f ²ræþi`Ò'¯$Îå!‡2«­LðŠ^…|ßQ.*dø™bäŒKIÓÅSÂÝ 1?IénB|‰Îŧ2ìÓòBüQ˜ÉtºS@÷4ÚÕ ”UCž0ò! ýP"|Še= Orw&[=¢ICqZä°ëuD¨R¬Ý†dÝ3)ƒ®ÿLÅ" MQ%#3ν~‰v|”ìPÙQØHhUÈ·ÈQ2UãI|ÏTèÈcr6‚¶K¤µ0IVºÃ”µR V UM‘ƃ–R2¶wvÚŽ7LåúgC¼ÄX‹XÌ‹ÎçVëˆhIe4 TS˜žK®ŸÎVæ– $éd±n9f.téb±ß d*¶lü«e î“iB^B.x„éx¹K‚Ðj†t}Mn¹ DxkñKD@‚™–sLGõoJ‚ôJ·8·‡p’Ê_ƒlÁ Q)Š 8 7r’+ Õâ¾rofŽäµ¹§¶Ÿdy„RƒR‚@’Öä/ÍF7&Œ‚y "ˆ2õJôçfÀ®pð*R †ø¸n"æõ‰H& 4\tˆx÷,$¡}élc6ý)oZII—‡Ýe( g–²*¥öÚS fXc âE¦õz{Ž Ûháñ‚Xöøß_l×IaTZN‡q Æ‚£™D›.ñV½NÂóNB›¤è;ˤàÀlñS) ã§¼~j&:/6Ž´¦ôvWSB£TO$–Ž$šÖ—B%}6êüã`×pð—êθ†oS§ruLChá8ðc#Ò*¨_¥Ú¸ YŒÅ|l8¨T6CTç?›]k[s7c‡òÒ¥Nô”«Ñ=´¢â1¯TN—_À6û6.s¡Ê ˆO‹™Q×óo½áú×B3g!ë?Ø#lÏ#œÚÊ#8\#¼”^”‰#ѡⵋ1ªÿÑP„ú±Â¯žð[YË7Ã}ø¬…v¶ÏÝp3l5V—ÛŽ¢×BVš6ÜÏFuÒÆ‹¹—Ð$y’ÈV`d<ļßhPPXÛaÛæâ´Cøù‰ø²‹>Îq±,è$ ôjgwezo²Z4«ô¡Â΀¤¬F·›rÎó4˜j{ +S™g¨ÕlšÇ_J#X¡ôâ‹°®v¬½§dkøhÌŸZ„-©Ëá+_ÇÔ"ÓY¤Jp=LÂV!JÖÌ“GÙÔ."­SµÀÉ«¥µ÷§EÄyœšñû…uª™8ÆZ¥ÏœÐ¿RIÙj#Å}Ü©.˜Ô8–ZÉ4DŽfräø•ôX&3\ù('Ô‚¦û¶…rý„eïÇÅ–±o/β~‚Š_ƒ³uK@…œ”çгª&!VK–{FÝÁãgEA™xÄ@⑤~™DÔû@k¹ã·(»(2I÷{Ô¾#¯Ó „_ñAB-<òj'ƒM´Db­Ò‹dtÁjoh(6ÛÁ–¼gä@^ž{~OWÊ‘®§E|kY©Òý¾½ $úu—o^ØÎaæ£W‚§–ñW°(ÿ·OjwÏì\‘dÀ¹ÖT±†½¶~5&½¬#»áùÞþrk¿Õ~ýŒÏð|ˆ²R¦dáBû#õ§¶ªpËìCf±4ÔÿÙÒŠ¸ÄÔˆ/˜óÞ$›Ï®%QŸc—·ÃUô™z º¾ÛLF‚°‘õ¥×;º[HŠC¿ršŽ5~°—ïú(3²º§}vÉ8r©ª é7ˆÁ×&wzÑWQ6Lú*¶»øâª 8òÿƒa¨P€"À @~#güPŠE²£bI‡>åÐRMKãQ@4Íñ5–€âQHt½ý9ˆJ§‘) ö,£Jpêø™©è¤òn÷«Q€,)õ Ã`R©TÕñZªF Ö(ìJ™²O!Ò¨ýΙrˆ\ Q€%2Îÿ‹Wâq ü¾ÃE) eNy„V£‘è…1ˆR™˜´² —Ú€Y` CºÇhtøÕê,õ×SðÀzZqÉS`×8þ‹9ºC%YI†æ!^á– €È€¢SÎ|KŒþçÓúœMÃÿ²ÿÏu¸½­42õ·ã¡þGvy*‡[{X»¿)Úm@}X•êA¥í) R´‰!ÈÒT"ÊCtÐ.Àˆ­‹bÑ %Nët‹&ðc¢—·¬ ;ˆcê°pd í;êE æ†(j\!5hÄ4%LÚ~µ¡*:žE(2%9 ãbÀ+¤Bß­‹À|ÉëÔ?9`¥%o™ý%’$§ÀŒê^Ù ‰ÒÂŽÃïzçJëã<‰)"íM ’À€Ñ;1‘º:þ=QÚô+S‚ ‹)ê±î¬O3Œ¨¤(r¤§343 ü¡¯KÔòÞÃÏŒ”íÇ ´SPxêÄ@ lèMN;E!6ëíP•)}(ÔH2¢>M܃(oéú•+ŠÃ¾Øè•&Ç ”/TKb 3ó=+.ÓÌTxíOŠ Ë¥+SD¾Ìú$#ªÒ-C– À<±zC+ <¸†)ë%ȽEmŒ¶}ºétÜhº„>øÑÔÏ|¶7«2^{bnÃÈŒ@êw7!–"Œ\àþŠ ”ƒñ‰žÒýwV'°„?yÕÖÒЭZgõ äAQÝRX0fJ˜ú‹[Íî™ä÷ÚP‡/QúCJ(6Ae€ õ'Ÿ*â¢Hu´„UPû…ª7¨¤.ƒR(f1w]ª{Kiص0²9èu™èhBT×®{{Q¿Õºc-îÄç° RCZcˆSÜb¸eË‚ñZSñ¦ØXÊ\ô_9ÛuÏsÖb™Eð¬`ñØIýïñ…QžÄ»«±4ÀL¤4JT§¢š¿?zs¨û¿:;³n©áxI÷š3 b¸ÄÃu*$­+GŸ«©ÜŠÒ¸žd[ô%YGÎ=jö­[V™è;w[ÕfO?cjC(ñ«gò“Ûi)ă”æE/é?’ÁÈ#Yv¬ù\¹SÒ¡½ŒÕxÔA© ;©Å¦ ýâqU å×µ8xµØys#ñ* ³PHZ»Ó!i“›„ž [†©Õ¿‚;€(iØÑE2JL£n±êE)èLçѱ\¬:Ÿ¸ì[6Oi]>,ȈÙȱ7Rf?ôVœN«W"Sõ3„°vɺ¼„²0ƒI˜"Ê“º—#´~/6]´¹O„ZùL„žÑ/‡hø„ø¶YÔ£“çxÏ&XâŠÊÓÜJè2XÍ% ýGê|)=;NøŠú‹S<ÄÕ©ºˆ®_RÛ#•œºg0ªäYWŒ”²ºªÒ6l³˜~O÷Pw[“ˆÐ½²¹¨’×ÇJ‹ÍQ¹nÊáã^­p‚e1EW‘Ç`‡å†È'_:KAHrï•‚¸³(‚b¨p!˜·€ ûRj64J™›tl£êus1Æ €žåçü˜$EÌï“wæ°]âO4ƒö €¨Z#n"ˆ ´’…‚ä"º§…°«9 Ü+Ñ®I±˜Èh;@-;rcõ‘0¶È©^ìöŒmØSy¸ áth—å' .©’D~Äèð÷¦}Ž4P6èiP‘‚ð%’¯€"üÕU0ò† _4c–©ú[94?UUužQ]ÔB+%7DòZÀ?–W(Ê¡õ¸y'¦BàY¤!,7Z“y(·êñN3wÕQËìÊ[ieŠî­a=Á!zì_1ö‘ª¥Žvҳʲ¹f&«®[ (¸2‘wÚ©» ¸——«rLÞ¦1Þ«ÇwÊby­$¿’× ºïÜ¡¸»·o1S1v·a—–—î‡Èµ¼}îFˆ™è£r퉄Ëë6¶é‘_Áÿ1…¼ÍÓDï“Êóhwžc "#ò\¹‰õ”¿BOœfDžFŠÄ^šõ·“FDìÍ]u—zÊëXmµ\hæ/Øa§^ÐGÓû´xŠJ+m^cô—Ç«tL½’ãŽv­òÛ·t;ó—®1½Zš±¿ÅI¢’è±æ›<ОdÊtÓ“Í!É_¥5ÜÓ)šjN>@_›Ÿ^*ò;‹+§™öôOd…hèß‚L6¨_÷ùäWYºP†!ô“|Ï;¢gÍ×od«´˜§lÍF»PútÆÃGP ,.üyDwÎñ;kðºmÙŽ[E,Ô«tŒ|jÞ¶ ˆ\º0¹ ¯vº%bÔ“=½÷D…tÎ_ïÞ³.e^wb|ƒ@°W1 ýþ"27@‰"[ Q “ˆÑæ ¨µë.‹2ž™½¥[²ê效ɡ¼¾ 1¨K‚• J¾›ÚϾ ~¢‰©‰áÁªˆí Ñ«¨ó"­ƒj=c¾S•j±ÀòþŽÙö&§`„ aP-±^=ø¨ @²+ºQ¡ä¦ޱ™;!5ëp°©ª¢á$ ¾¡Ú¸B|!ø§ŠÑ“±$(ã¶Ù!ŠÂÂ<ù·Á9¼Ÿ»ì¶"!¤ûõ–ø}’jÞcœ 9ל¡š¹r9û3™ËA£»Ô,âŽëCCJºåŽzäˆp²§£1[9ƒ‡>š O“1½~ ¦;‰J´Â¤iä¹I%“£ÁD 1$ ˆ-ôN'˜Þ—¨}‘´5-”6& ±ó”r'Á<¨“k¬³® #Í€X‹ ÃB½‘;¯I»½`¨8†-j7*XY߃è¸hµ;ƒ¿EépÅÓÞ¼h¯3}·† ÒÈ'šŒF´o¹¨Ä @¼|$€DpŒ !é㣀 QBÑ««`~¦p3`zs‡ó<zE´M¾„ˆRS¯ ?‰Jb¼­‚º©æ$:ËúŸ»qIß8©[:Á2tD$8..«Ð`½Ac‰Fò–½K­­º5\t‡ô ¿'™Ü‹SW;Y¾°íÃÜPºðö=k  L€½± õºŒEÕˆêÏ *L™ú38ùÔÀç§{ÁCÆ&«! 8Ø·2Ž$OÁ&;­ŠP2’“-â¼ ¸™ LÄŒ·'zbºqäŠáÁ‘hˆ1Œ—˜«ª|;;Ó»kÿËb‰µÁ )ãýdªÝ) ¹¤I˜a*2ѱ¾ú\’iDŠÁ¹Q‘%À!Ñ,ÇM;Ã4ŸkÌ»YFò¬4lE±^!¬AÙ×ÍC0Äì'­ ÙŠ3]©SssMt‹‡Ô¤‰™ºœÅÙÈŸjqP9{éµ)%½ªz•¬<½LŒ€–ÂÙ*¡1¾ì….1€¯c "¹g II JКCa+©?òc°™…“¢;Z]:s£«ÓNãÀl@ 9Ü×í8Äfˆ# °¶=`ž)ó«˜|ÈyТ°Ï?Ø}E¼É\2œ¹ÚŽ©©Çp‹ §¯{«»8Cµ,”F0SÿGP´$ÌwÏ|À“\6#â;ªR;9*ªº`Ø—"FÅ´ð0Ý Í3äˆê ­(51|['Áд „)òNÏØ}¤ä&:ã|Al€@úý˜rœ¼Ä““ÃYâÆ · ¸­ &›sEX©4»ˆ`²@q•§ùß"„7•³·ˆ‚¸D5§ü©LÌ-Ó©L?$ºqë¾ÚÉ©5B2ëSŠ£¯»`E™· Ášº¨LÚ2Rsã<†EÀ£ÑÁ‘O¼ï2®7ÚSd“¡öžüt’YOiO?ÉϘB|<œ:äL‡øØÇñ»M»Èî´0AÁ™yŸjмœôƸ‚HàäW[…žBÕ\°û®]aN€¾ídº„p°œ-Òì“‹Þ+«§Œ¿C+rñQpѬ¿“²sÍ€ $†åJ¥ \!Ý{5}ƒÜ3´=fڻ˪G@ [.=9‰šf‹š¸TÀ)ãªÆù&™¥—;Oº£ºä¹t؉|ÕRó†9ƒÁ$TyFê®ÛìÕ"ÞV)`ÄZÑÏ¢1Ô­³gHéû­³œ»˜ K¨¼z‡Ül.iT;H‚$ Ÿ‡•·MÂo2"Ç¿m|S Áà¬$w³ADÔY‘½²ÃÖô=ˆÄ—Bñ϶{ÖÁ貟ÄCÏ Õ¬:ìÀVtàÅê×ttBtÀ×ý6Ý…¦ÚÅ5ŠFKڰԉףU2wð®Ft+X’ȹ*”-uÁR#ÌYñ j?Ä”ñ…­úD³Öú~Ny;¬Ý$e& í¢µí[M•)y·¥˜‹bž5ÒªÌøRÓ}Ö;’dà8#ò!…}’êÛYHˆ|Ù âÅ'· ‰“ßM R-F©<-ÉL3‹#}›ù¦Œÿ¤TX[û²»J:“¯Q\xR³Y;ƒE•Æ»½ÿAÙ¾ØyÈ 6UðYF"hªÁ“ŸŠ5H¶j² }º4=o `­D˜Û¤ &õ¦›EÊÎG—4ˆôFõžß»± {ž¡ýX=X®PŒ¨yÓ4§¦Œo4ùJàåIm*Ò#ìÂêÍDKPZaËh¨Ä©a—Ä­4@ ù§ªÍÅ b>Ø5ýÆÛ§š$í eÝß!ÕÚeÊ\y6  >ìO¹Iüxä+§HRLØ-=Ü겈ÓÄ#O»˜tÑ„@Ádг'»-Ñ’»BÓ „?Å7{ï[ø¤aò@Ðt—TÊ2V“ѵ“‹{ˆU¾Ælj™Ö äd>M‘´ÁÞ:[­Ô§XG±JžJžX *Æ &9« ÁÏ[ÖdÃBð›EÝ@êÉOŠûån2 4’]£å³FV‘²ÏFéFkMMµ¥Íª¾®)æ„ÚÜbÞAx†¦‘ d‡¸CzftÀhJì/QÿBè.ð….^~O:Ý5é„B0‰D³L<]ü¦hÃPÂl`µRBÍÀ- º#ðÀÝ»_ýéClÅäô(ÚëÐ\›Ôo»Ã=dÛ‘§ŒôŠàu-ž‚¥Á0[L I*IÖHdÙ…’j| Öp§žŒ§Ã+²öµŠ| *´ÈƒI / ÿ›^…"¸½8É[PE†Dû¸É±T~hÞXí/¼û²—#)õ)9…V⤒ļ´¢õ3ËÛˆéÈ9Mú¯]Źü˜®æ/ʉó®YZÑü6“¥,ÅzOÆ{ѮӷڮZ)s ¦´†L×bÎZ*¥PaÀ+Ø‚K™µK.Žý5\Ö½îÞhç-¢ff'&}ÎþgÔ™,ºÉšT•Ò$„SWµ)bT™mÓ“W嵺™µ¹TÐsÇàÜwy~>>ììÂW±¤à¾ +€c…ËD¶âò_ ÜV&ÐN0f,ª¼±+j\æ^‰ „^ñÕ¾RèéÁåÚ£ü*o îÏt5Ûš•û¹ì^VØ›˜Ø´Ñ炌Pš©ÃkËʱ•§tbËÀ¹ó¨Æ×çäsµoIúâé›E°¬Pðâ‚»í  )|(uÖœŽžqi§ˆÁPelÝ_èÑXŒÒ/¤¬äÜãš”KW—"¤¾wˆe){Ç/ Ç)Õ´ÊE»{ 3ÊFáR®5ñÈÑð”PÄš®xíì(à LÁÉgð~¸‰šHVœ’y¢ýjEÜæ]Ÿ2³ÐÙl´õ£º¢ø¬]è”l Ö&†Î¦8Ô‰˜•b¢IûPÞxíC„JY[_¡‰¸b¥q.¤,V<]ĶïTé,­ç+£Zžä뀫Pš»â…} Cc”©U4¡„ÛyK¤MVEW1›öCpäY³š;ïÈô¤d<Ù…Û:;™¥ñìòAKãPŠ[êÇÃìÆöh4}à=g$V½¥EŵìøðüÕ±°š$«+Pæ›Cœ`}Mm‹ jùdâ•PW¸Æ×KÁƒY¿Hx[}ï‰,¬öÿ¿!‘+È‹gjðž‚2òrÌjBÛvx»î]–öœºÛjü'Õ„ïWu±Þ¾SióÖÛ𻿒Ê(Øö…Кv¶W=¬]Tè]Uç[ÉÈ®V)!rªà=qøÔÝÕ-§=Àtɪ?…IøKYÈ f­Ý~”N¼ê‘ª$kWõŒ¦!´Rõi.è>`v°¹Ù¥¼À²v tv);‡G勪¯~Û-^EN7ÝA\Ö)xRLÜ-/ídª¿ƒ=ˆÿ®‹G»œìMóK|^(fqK–L:;úvNnl½FüîèµÀX¥Ç²*ûÎÍÐ1–ÝtEóýÅsoÒSJOó3=ÓÆªÀ½aŒÌmŒâÔÁ£5'?Me7.]ó(²-)TPž¿•·ÝFºÖ‹é¸ü.jT¿ˆþÁ`Ð7ô$ C_ð,EûŠâа4 F Ѩ{ò-#Àâh¤r1ŠHc@y„P 3A_3yT. C¡ði˜¡Ãg“ØÔb‰¥¿é< 3£Èhµ,1A½ëÀ‹¢&û²¬Õç¼À+¶Yp8$ì!ŽF7{ErJ†Å*ôÕÖû Èå‘94N"·bñ/٨ᓠۣ؋ã5fQêùÔS!ƒF$y§Äj£pÀQ ¶‰cŒdß÷,–Ú”ÂcR;U7CÕAp;èmng¿‹G%Ø7ìmAŠF&ï›#¯|žÐr7HLÕ¨ÎA£”µJ £Óêø ©Ä†È÷‘9Ù´†k®hzØ<ÈJÜŽ*é",ǯGú(Î#áõ£J ·-Í›r³Žt © *‹AhB…ćòÔƒ:êºâ¸çò‚좎»Ð‡¸  ʬ·hãÂɤi Sé 6„´â2¤Dê{Ú†¿` ~R™ë*»Œ2Š7§ôné=@ Õ-"p2ê¡lZÄ~ÅŠb5Ÿèã² žS›A*²:òÄ’D˜@¼ädÄ2j|j~)([îè¢Ñº(¦ÃJ®ƒ1ij7(* "}Nó!þîT Ãäå¹(YçT¨-ZÝ@hŽÓŠŽÈÉ©ê8´J`Sà¤orý!30NÀ-Ä/¯q4vWõ8ôÔ6cn‚ØŠÔ='Çã0Áo=L:ìå…*ñ¼nŲ́b§©õ³6²m•m£Œå"¤@rä€VÀŽR÷d;I \£z$²úN‚­È€4à@8$ „B_зä5ÿ„€¢P˜{ü …¿¡1¸CÞ= È_8HLû”eR¸¨"] ~E!ñ™d> ‚Å_³·Ôô?˜D€PYëêWB•Ì!1p4êw¿c0™] W¬Jph$p„Ì%rºŒæ5РñÈÍ‚½±Ê­ñÈ­¶!¨Î —à£BŠÉ€µ©^ +­DbVŠsö X¢áæÐJÆJÓ¨ä'µ‰¼f‚°Ãiª¸¥É€åpZ+<þ­k"U‹þbw•Ö;¹†š—„Ñi0ÚeæT¹B0ú¶ñ; âù5û½¿…*vhUÖ½ý¾„JæOûïN¸Ñß¶üÈ•a»òßü‹§á¸Ôuü „è€G´¬ ,>¨«Ñù,YþÎ –bê…ˇëS”r×ÛWâ¢Ñà;-W+ó= â¨ñîÁcÐýرÊQò%C×GƒŸËär?h-?âN¥g3_ù4h†ÏNX¦cÔü°ìHIó£¾JÂЪ³j¾@(L£2!­«›Éðêfã×–¥]>& e°•³J57QS1[M>¡¯‚W;¾ˆÎ*ú^Üj§àe:ý=7]s…ª*,í&X Ø~bª"{*䎬êà! ðÁTÔ­Å Ú[8­b³ãemó6„óEvÓ-l(»º…ÒÀ$ÐðfÒÎQòŽ·4Ú—VªÁÔò„Óè)çáËÝ¿[É&맺Ñ7"…¥%Z9ò¬;ÐF5«=.ôWÙ[Þ€ȵ;~¸Ù‰*M(E- ø¬+)D¨”Q<—¤Ð! BPÿ”øŒÿl°`I2+enݽ¬‘úzMÉ(Bh„)6šÒb*è!ê¦ôtßxûjJu.GèÍš3G!,TÓ.LƒÎú¢WÔu@:‚a¨j±CfYmM’\ûGÚ¤¶PÓÇ/)ù&£TY£“ˆcf +pD\¨CgX®Ká0D/²pÃ¥PgÉ1EPÄIŠ¸ÃÆÔI:p‹Ž—²•¨±Í€.9‚«°¬è=fÏmX+#$ )ˆþ^­Šgšz½è ;ÇìÁOÚOc}&Fq¤‡TŽJÔúäI³Ðë€÷,ù®u¬3X¾–€)Þ[JÉ*Û\¥Ik¶%p‡ÇXìK,+ÌŽ/Îb%c'–AjfDò°§ÖÑ0XŠÅÏÈØeQ S [ ô‰"b áä|‚¹X( ¶\-s£Óˆñ§y^ë媘 väëxBÕ2 EvÉÂÍ@ ÿï{[Võ`¶¤ |îIIò?V¤qjÔ‹•‡¤Ýლ5UžB§5`¬r£*4Õ¥HjRyeŽÁm)–«kÍ­¢qîÃ^r7NUÑ ©Òʹ§C`aaê™è\ŒàÌòM?p3× $.ÍQv&Ú@ïM¯ÓBŽ64ÒJ¹ô‹çîÈãü¹zâœI+U•qé›ìŒŒ!oõ,SáøÞ\”eE4lñιékº™#08})ÅAܦºÓÒÓÊieKqLÉ], Ø'$×òÌô³ƒñÙPLöœþúîmÞ%™Ztg¾3‰ÝÃàFr0õ>« Blô·+ûÒ ì˜-“hM{óÁ`¨>Ýô/j×+€ ì‹h’åe´9«£vS$þÐ(Ï%ú^é •þ+΄äD'˜/„ÈBe<½ÜkÜ•Pí–w%bXªwM Ž ×k 3Ðç(¾ÉŽÌgóê€Úi¶UlJ1Ä:‹ø¬ÔÏ=`”i:­î1áëØB8’;E.¶{> Ú -Fž¬BRÆ}ÔÕ=+MRЛ®LÏõÍWXegs9Ð>LôûpAX­Óæ:äÅBô¦¥–¥6X·ñ©q€lZýbøÝê²Aâ~צ¾UñÚTɦ}6JÚΖ‘uϘråÒ‡Ð9.#áùžê)y;©ÙÞæ¼ßR0j‚Ÿ ÔÊF0ƒ3úÝH€%¢.-ßY©ô‚¼c«`‰E“(Ù+í Æà Ï»AN‡&>©„–›4ÄgÛÜ!PÈ~=®†y»é”Ñ'y‘‡XEÏÎØ>¬uQZá~ÈäG²øÜÅ‘Kõuá÷ÜßUêOŒH²ñê^§(Np®cÎñ/\;Ç¸Ò bëLhYé2b«Œ[l¹Ì¤ #Þ Í‹>Ãé(!lò¼L˜ÅŽä2Hì ¦P–Å̸[ö‘bïV˜ïšMo[¢ÒaþrE¨&Ê[>®Îæbâú‚\–ÊúZ§¾'ªK<<¯¶\+N9åÝ Önäøâ¥¾!e’I vï‹,[g$3.×q†…b½nMO“e:ÑÐ<îžü¦4ÛKb®ª‚Ð ^¸pÚBkÞƒ$VÜŒ3Ï‚ðÿã{ÍžÖl@tÄ"Ù(>·  ¥& ¯Q>±LH—Aôµ‹Þ­PšìŒÒè°Üßþžˆ¾ÍŒ BÆžîÚp|tñ(¢ànd€Ü¯–'‚{ É*ïŒH>B PÊvéRA Qo,l½k2ºo?d'øð²€cÆ4uª²2J@”B®YÍŸ¢ç*۵S,Ò¯ Êþ—éôã§”/)Áôv€í±}‰˜Ž’tûq! rwïv‹ãä˜ñZV(*ým mI¢çËüå‘6%Qþr±¿,£RÞg6¼‰¾k+’væîûIìâñ@OQ´Z†4›Å¦ž†êò€Hèä´ÐÚõŒ@fÆ`'o´jÑ1*X˜&+BL—ç’‡² ÍLÜ1„}rÞÄŽÛ2îöB&^|e¼¦ï]ê›!üh†5§"$rR7ï7©Öòës `eŒa; sRO6p¤: tÊOœ†D|’O½ªæÍ|±Öhðœ2¾ÕŽ_8oÊÄ©Ré,Ú*‚«³ç>AM#SFÕÆ®Ë”8›Ã,BÃÒñF+.Ú!öýñXÞŒ³Ep ÝróüžÅœ3Òbbz¥ÁýòÄË‘ TI‚Ó2àš2'" q/P¥ê /2G‡Ô§­ä¥ñ@eÚ€EÞ±ðÌ:¢˜KW ÑRª2‚ÑH¾ )S;c^áJ˜ÈPèä6ªJeFóLq‰öðOß(™ œrD-FLÈŠÂúȽë2RM¶¸SFú²ã¢3Ìvˆsf=ãwdîÀ¯ˆf­ÉR,„x mVÔt õÇ>%rÑ é,Р-ñŒ]¢…礮ÂÐf¬@êËlRcÌ‘9À MCðÂçñÊ͈¡jÔ;Uêg *GòáE¢ë)ì^¬åGDèbÍáéS‰4þŽ6‡ÄîØíÄòg NÏuXñnÒÈ'‡oBG Š÷ M,ðFjzUgþB¹!’SA-SPÉ #Xø¸õýQÕÂZ“î…c1i;@Õ]â*ì3ý<Ï´ë;)½Aðö•%\ãí‡ÀzA³etÏTICÕÅS‚Œ)Àû-„©¼É ¦«tÔ‘èQª„ÆïK0ŒO‰.­ï1š5ô¸ºŠÀ ³b8)ðø³ž¥‡ØòÍ*4úVv‰'ÔºÍUEE` …Fôâl² f¦nìæŽ„ÓÔ^ÊæoiìÊÆGÇWGm·SÔ³DLBìÖË8P]ƒŠôz!ñÿDâzÿ®Ê‡Õ[)RnH<©ÖGÆãj(dÆÅîÝ#è)ˆLq”%\õFvOÅÅ•î"±Kª¸rîf`Sšóð1j³HVVšBsD#phë¢7$6Ÿ9U@„e‹ò÷ *Э™Kô;;©Ø2TèAWDg°f¦ü ÌÙb b¶T¢QQ”\N|¹H,h«8vá\mÔAHÖܳûC²Æ"ô§!þªì+M51dî±3¢âµk >T//+ù0!FÓ…}wó>I‚awàü¯„hìØC÷¸ )¼(D±R¯fçq.œfÓŽS°é}7fvhQóéÆl+R(÷˜t·ÔqCŸeî]*1˃µˆÑŒ$ØÄý—*wÕ&Áõˆf-~r—L.®TKî·+#,¸©>"«jÑ üöÔïãWíËp²¢…k´Ë&„@W€â½]x¢/µ˜žncà“1[Æ+‚c’e]”uƒu@ ÀõMÔq†L2V&1gŠ@jÃ-kÑpYøqx´ae¶ƒ90š( kƉŒÄ"ž˜ÚÒÙsî{jd&Œ,ÉSÆ#ŽVš7s1ˆeZ±™†B+¼äè4­6§J—IÁ5X|G¸Ë)×p@$wž±­góGU5—y¤58п¢®xaæºlï8»¡Â7ŽŒ¸(N7fj*8ö%¤h‰$ûf*9ö‰'$Zv¤I' þq±ž!ŒbɓÞåQÚZbZqâðÏI£$<å £^@¼—ö›¥Dº4Д׉b嶸3£6”Cõ°B$|¡—–0÷TØl°Î¶C\Tˆ¾•ü˜"„¶£ú0jm\M|¬½]·ÃbÍjk¦5/–•Ÿæ7@JØQì$˜*ÎñŒœÕ3qZÂMž‚ù‰‚uäúdVØ4ÊQób “fX{ÑI¶z%v„Æ.ÿÃö[Ìœ^¯Ÿ…X¹–>B™?3Fù‚¯¢ÅM‰Ûï6ô ÚÓhÚv<¹ã%OÅdôhÈEœ½ó’Ž'[§§ÇÀ5Ó€ ØgÔ{ÜÝ·ñ«œñeÉDŒ‰RrPR*$°žÔŠÔ‚ÐzÎÉPBºËÃzP:¯€"Sïé37O¶Ø¢±LЪ‰1nºŒz&ŽÜuÅœíëŽã<Í„›Æk9ÎNòñÊb]Dï’r¬d{í Žªn¡nÙÓ9ÊÍH#, awóË*_%'$>èCó¬ëšÃ%ŒFÖ›1É<ª4Ö4™ NæÐñú®y{GÚ¤È ãWµ•§k¬!ãôßÙoÓ1±…YÈ‚*žpÇ$ì–"p¾%$ 1_89§Ø¬ñqþ>Y‰¾‹ãm1k ŠgB‡f;åÍ̘±:ÆîûÀ[CÏÛ7‘”÷¡ê%¨›ÓŠ ÄõunS¾¥÷ö*þ™Ç7kU©ƒ²®Œ^®}O`A¶éæ¥ö½ì´ ñum¤V™!Ù$îJäkÚ4Éj$nçY!ï›6n- àhúÍ–0ݼvCòAPð'®­iùà°rrYøuøÉ¯Q –øÃ}[õÌóèo•»‘ V«ÄžQ¯ò…ÖéÔ@´«aˆî7r¦VV ïvñà…]\cÌzÎQÛI\L‰ iýkÆï‰Ñ¸ýC+Ñ=Ùb¹aÍGD˜ êÕŠCîÛßtK]ÍMC™IÈvìÙ›­!öwHpÌc˜˜N ÷øƒA!ýý „ÁQ@(ú‹?c@  Bãì %Ž?%é ª1…Äâ€9”Î(~C_Ï™Ð.y}G¦q©Óæ5Í¡s8ð™+ˆÎ$1ª”RLT#º´â5!˜eðøôj¬û³B,Ϻ´Ú·‚N#иՎ)6œB.0¸X}…ÚaqëÄz%Ãa¯X›¼ç©Ô¤œM !œU£SŒ^ O†Æ¨5H}×(Ìä i¬¢­ ÍÌô6"£¡×chE+¢…@³zènÂe–Ï2)ˆÏ³M<Ê‘ÁA1/ýà q3ŸUi“mLj}Ý™`ÀQ¨F^™ë†Ü¢‘È×*½ˆÍ§ÑËËÿ瓱0 4¶)Rˆ¾ 6Ö¸8Ý ‰° &ËK2†º ̹Oõ?àh6ª’l›1¨úñ$¯s4Ǭ €™£¶ñ¢¨³Ðœ;0øDGûª†!°Û¢Ž»áÍKH¦AO PÔÈQ{f·¡±»d£ËJpKêZï"ÐYþ¾€è[˹Rf«R‰øÌê²=ÊÑò1*&)”ʬ9qŠ"ç0‰š‡ G±"¸©ÎËp´‚4´º`þ¿Šœ„£# ÃR¿¬è$ʧI´«&tP72Hì'ÉàåNîÒdø*I0º*Qk7KÆTª)_IðÜ$QD’„HHõ ö…6~Ïö FÖ:qX§û™-I1ë4†¥‡êfŽ0Ñ3X¦?q‚ms ɵ—uˆò}KXŒ#Hm•W6•c Ivth|C¬6qa.–ß%ÓÆ^0èJ3¤)òÔâŒ<Þ\ð‚PݸŽÊÛ_ýA¦u*0leóšûIÕ™5S]âPDÎü"Ó:¾´¾VÅ2À`"гWsc‹]3©²9}SG`ê5tAÕ,~‘jL5{²µËÐÐ:‰Da G±D-•EWM«o' KR²¬ÌÞ¹ŠcÇú9B§I N™K;‚Í{O€ ÷3¸63}[¦kJ¿[Ǹ†¡‰U3*„bËí¹ž/©ž K»x67ª£(¤š.'Ârˆ#ŒÍ\»kÚ½ãij;Ø!9KÄÚðz¢^GäδÕmŸˆôVÕ/jgJ’ð'Ú¿¾©‘…ùomU¼5ä,žæØ~dÒ,—”ÅÔ„«DŽVMÙ;(åK±ý”1D¡¹ú½"ýŽj milˆ»ƒRªM‰ÙcŽUʾðž˺P&©DrAÚ-G‹Ýr"ÒÒV*µjá$1ü’^‰(e&¦*Ú·›Á_]™8!âë jï¯=rA¸"^’©z3  Ü66¦PÊIÄ.Ê5Ú­(V?!»¬HtÕ“t.ùZ‚G¨À¯²Ž¢¬A#Ð ’˜–l ähíȦ%Ô°IXÁˆª]‰#`ïOLH$¡¬AŠ\dEæ@V°¾I¾OêP›µÖ€‘þ@1ò.dê av$`í¼éCPBHK8Ÿ—H†CM4ƒ;"|™Ô¼a†¢3¯²e!L†&Dâ&èDazÎ]#ñ„÷d~¤ÊÓ!«IZd cez€¡³¨ÄÄ–9è]Éõê£BI-Çû8€AªÐûÈÁ>Š$Íâ©"̪ÔI‘³R ÊŠn?ßÜÀIä5ÅÙL4JcäÇ´{/Ó*䊌qTÀè[ÁLô:É¥/:aˆ®U”6µ+aaFjÒ‹ý¨U‡Äf]ÄT=€üÖë/\«î°É-¯R–§4fœîp-²@éˆL´®ê¹KÛV+9¤µ ˆ%|œVqýÇÕ-êÁõ0YJ»ªS04µjˆMq§äƒ k± O± \Í+v$áˆ1V'Õ§Úýgµ¬£qq†Õœ®i^öXÞk»nk4¾”nv¨4’Œ-sSš6!³…9M 56¼à È­ç+mòâ—Q¹‘^C`÷º­×\QÿI|TRõ‚¿×p° JEAGѨŠvOÚ£Tuj6U Íù‚BÂ/8|g^D¦Ž“,¢¯ «^(᱈o͈½õîÕëA¦U•6ðÄdÓ2 ý3ž ³’ˆÓÒó¤ J„¢YþL–>G£Û7,ìÀA£0!ÍÙæ ,Š[†ÃÐôó—.Á9ý $Šç‡ÕjGeÙ?xsl¼¿0ÉO@KG•Þgñó8A#Fž°U5ª¼åééBóýY„Fu@IøE£M=¦1ôjj¢v”w>ëå\$Ý’kã:’Õº×ÉV7V€'õ˜â•Æž—‚ï+µ®¹%p›E4Œ4ý–g\…Y¤OKa è´ìžò Q°Ö¨1&nA U3·z.%Œô.zŽáWDfüx’ŒqÚÒ‰/~êÞB“·9©t÷j+Í¢[ØÞ_F,»2e»2 âQÝí {+fµš¾>§#s`Ö=êÐÆ¤fáìØ¸Ñ2§ìÉPATÕsíR—Pòα—‡F²ЋDs ÖJ3èä^f—”p³¹aƾÊû±”ç”Y´¿'~œìÃå(~êäqÏnð—\jz‘,MGs~Yg“fapÃchÿ2Ü:´³ðö>!Ûí¾¯™W‰Ö‡>XòCLozÀM9¹i‘=ÀÍÙZ! Ð>VIIž)—N_⦎DS¤XÆ“È-šÀrššÉŠ0*௒M*kÊ¢$C/jM& ‰”ø}Ÿ#»žÉ cþ®‘]•m¢‰í©Ò\·#ÿ=L¡<(ã/CúüZ¤<“{Aó1½‡É,šyÚ¢+¼jä¯êkúÆ2 ˜'¯Ñ‰<¢š¬£‘I§¦ c¡áƒ ã ЙÅò5£k 9ƃ°ûÔ»lxBü®Ø³#K^À£Š #ºR¦°z¨¤‹ÇÇÓGÉDÁ"ʉ CéS3ܧ°Z÷Ó§D9‚$JÛÁ¼ ëGÄÃ?óÁ¸ºÈ$Ú[4`–€Ô¦ùµ-Á>ËC¤Vࢠb#µ/“+Kb1Šž­#©±ÅÈK/8 ½Bz ¡ÃÄ •¤R:Yš‘¼"Ã3t<$9GA¨=ÛÆkÇ™Ø}.ËÌ»:ËôôÌÒŠbCšÔ¼Êêê»HØ¡=1°UK-ë(-Cq‹L~ âI.óÔRcTž!C§y"‹HŸV¨³:q:´µ°.F• °l€%2B,?“Ô£Ò;Ä3Ãä½4üÀU@(•@Ÿ3ðÊ4ÌÔD0¾ºÚ”,ªOÒ¥{i:È}Äs„²Sðrü’MLC Õ$»IÂñ¶óA*„°Ì«¿ËÊM?T÷O,„¡®«â<‘×d”—ü²R®¢c%;LMuÀ€ˆ³È¾šÒàXÜê»sÙ0QrH,ß0b+È+ˆ3I©Ç¼•ªL¾ZT|˜}¡½Î|eEHˆ¹‚7U4¼°”@‘<*|ܬ ã {ÕBÅÜ·Ÿ2½”]E•í—U!Î=9qH*­.ƒ‹PC‡áô  …·˜ƒ»€©¹¼œ‡ÈŽ ñ/€`…×Ïú ¶:‚´TãSêç[™6‰”¼ÐªÁ•Ýqµ½Í>´ ›ÔI”¥¼°´T¦RT®•¶×…é:š–¼bT-~Ò$8ÆòÞVäÂÏÃ¥ ¢x¶šÎ ÎŒBÝÊ Þ3ï] ‚©tL$R>¥zŒÑiZDQµôÙ’ÌËüŒ:âã ©Àؽcë&Ø‚9Ì{KÂW…Ì€ªX³nK¢¯[YÕ#JV*CÜâm[ø8™2Ò3H»¦K©E5 gJ®½ó^VZz×U•ˆ¢ Yš ×s€,W<*Ô@šî Vݤ‡âl¬[¢ó,[ ¯¬å¸±=Ň–Qz4Kܪ5Å5/2+³eV.•È`LX•ru¶BpWJT›ÒôCáê  ¡â‘Ö Ms¾ý{lÝÁ9oVÞ(â¡ ›á 5-Å&Kh‰ÃÓ|]Víx  ô`R•©.mVPd"¹É.­_^(‘ÊÉ ³ã ×S«cD¢Mcm¥¦*|JKÚF³BÚŒ9,Æ:ïQ]AŠ•mŒÙ¼N8á<]RÍ ]Ù­K²ü‘ìFˆ5Q€~¸MÄ“#t¤ÒÙd$Ò0]ñ Œaåu\¸($vÙ%ø¡–u—Å+Ã+Î-ÝÜ Ö*v’c®=Ž®žbÊFÁåyU WuR¥=d½ý[8©’S‰*ÊJÈ~–‘ LŽ :¨›ÂR }>S@,íÁßK@’JŒ>nK¶­‘&jRýŸZRùC *Ôu4 ,£ßŒé?Û3-¦ùZLÓâÕ%ó4 ΢# -iÝÝ%®ô§bÃkµvWØÉkÄöŽOôiæ-Iþ=´ÁÝÜ%ROqT”¢¬Zšž²TæJŽ.j!Ê Ú¨áÜUVUÅgÛ"Ø«^#DzÌ8ÎUÖëܳsJ ‰ÈL†è»bµ-²æy®­yQÙõÒÔÆ¶“ûâÒJ6*ÁW1V]\©+ ŒÐÃ6m>|6™¨:襦V‡Õ„ˆÜäj®p€6™Ú“g˜å«UÖ#˜Ztn£‡Ã3“:%Õ åãø!#GÚûZô8ˆÑÜŠ]O´’"ûlÝÁ¶ÉeÖb;tn¸j¾ ì9‹ÒüĽâ½|ê¨ß‘Qá(>¤ä[^C¹’À"‚L•@Q­Mƒ†¿bØ øŽÁâωgÕ£:;¶EÉ…Ä–vwCìÞeÈb†@jÉ-cKÎÈ Œ9µ®ù16¤8JCÐíòC;%Õ&:¨å"Xä¼|;mèyÆÕ*v³dÐi.4x<ž½©»TebHsHŒ4ÅईFvÿ—Â};¶™/yPëî *(Âèа¡•Š#§Ç¯´:€6ÞŒM©s« ¢Ù/ÈŸ3±M©» ÉÃífËŽ"÷ë$5°SsÈnßJ¡9ål¢Ñ­,GkdÔÀýå(Š\¿/,lZÐVhÅ™ÂøªòœÊön#«’­i•/‘…JòÜpH’¢‹g±ô –É¿6ÕÚÃ¥BÒy`šû# â¿ïæÖè,ÍEiŠ=FÜJ%˜¸ç>ÝÝ”†×éu/˜4Iž´dd DspSƒR03H²ò’/–wGÕLGTdö›`q¸ž‚‰Äb9dñöLuµ– .?𔂦üªÍ\œ‹ï Öè]Äåà˜å? „*€Žgì¶V´+4¤ÓämþW:˜ì¬îÇ×TÏ1ZG#Ka¼c rR¶ÃÙ![µæNou«ßåÜë‡å«nw xuªó'“ýàsug‰éY¨5Â!ò[Xl\x³]B"Õ…ío†;ÍQÞ?ÇÕ¼ •P0i”ÅÍûéGVªöŠú`¢‰î©TÀ÷”rê$¬DHDbk];ÄRZßjNk¡¼£¸o ¬ûÓ&õÖc²L³_ä˶â•úZiWa€ôdÜÓénœG¸Vð¢^…áyØÄ¯Ê¿ µhðÊÊb³U£N%#|„Tê/æ¨ØW‘'.%³cœ«z‘Ls@gQ Â6ÚnTLË«­¯íWn É-JÍeK¤ÖEÌ}J>µFHØà¤ÝæãâŽp­ð:G’ÞëÚÁódŸ63,~EÒ`íâ™j9i×_hËŽ‡üIÂANƒþâZïT2X(޾²Á™¯cxt öt…½ê &ýçË ¶Øvô(öšQþ´ ØÄç{·7ì\*çý€÷/ÃÐQ1Km—;VLŸ¿à„¢‰,Ú!ÿðÚ‰“[ô½~ÖÚ;ˆýþ‚? À(D þ†?!Àȃö$ùŠC0¨°5…BQGÌ É_rp$¦-'}¡@i„ºA¦ÓxÐE‘B¡ÏÈôæE6žÀ¥ Idæ$ýœÑ ”wÕF–M¨ó™x [–VÀµiM K¥ÑéuI<”™ÃaÒ+d. ¸C$W{ÅÆé‹]bÀ´+¯H¥©Í Â'ñéæ-ýQðPkíò6Ÿå!Tyµz¢ú¥Ú¥mDÒm‹Ìµ×‰²ÿ ÑTgö¨´Ú3NbÔ{ö—,ÝΠ”¨–wàf°;#öŠÿœä@j]û‹9ŸÙá(•6 0n¡’µ{]‹Rö¯­tÛ­GÜã6°Æ—ƒó«Ïbá¤ìJ4§.íPŒ.È#.ɯ Ø‹4i²rò!JZ⟴o",ò(ðÒ¢µ@ÉÊXë"ÎPÅ6/ìV‘2È(4i¼›$¤-Nê$×<3Z­Úlò'íógIHîç5òkg ºiü^—A«W@̓2'ïä ¬#¬ ·ˆ¤ ÉÌ äªôØ×IÃ9¾éËF¯%Šº5*%/ä£.¬Iº<Ž¡Â%¡ËR²„4 ½ ƒ²J? ÐÚ`î!Ê\CRrÌ¢Î!ÓÚŽ”§ðä“;Dèr<µS“‘ÿ ./•>ï²U ÑÏ€ÃAÁR“œ¿B’¢Ï¥/üõÖ˼ô«m»FŠÝéɰп1èCÕ Òzï ÑD¢×Kµíƒ'UVÊ]S¶ô9 ñzW¼.‰LÀmzŸN|¬’Dœ«Èµ`ìÝÇM¢U@v˜ ¿EU|丶D‚¨X´¨{äRç‚£J^9D)ˆÕª§¬(#³ XÄ¿0¨"Y4±5òe '*èµýCo¦Z*nÊ:uý?–€ó¢~¼‘T AI³ôÈÇTp5Oj±Í %” ò4hVoÝŽ…OÙ@—SðD»•SG⽨«JÚ—#!Ë‹ê=Ïߥ G)w¸ý¼i‚Y @4JS”9‰Kˆ†*¯²ïw O'$ê•qªhÉuqyæœ%Sp9ö»;\ÔD„qÖKY‹eˆ$y7«}ût+Õá•3Ì%©˜"NÓfÊoÇç`©9=õe½¾[ñÛÓég?‘ºT†:Ét¿#Éú@›`OCTªBO@všúÿŽZd¹ÿ?»Óë! 6"N—É>!ÍÜ‘=ÒDw•ÉQ[¥È¹µâtÓ å OÃBVü\xUcñ‰1Fjd’‹î‡ñ‚%IJÛ`þMÇÉ2có Ô¢r ­ gBk‘T&}$*¦æ8—Ô‚»t'Y?DðT[»iXÀð×ò¨É”'ía”¹Ã¦‚ÛÙ"dQ©%kÛZ°‚ȱ %dëc#:(¡î’ÄvÖÇÚè:æb2Ô„ û v­À‰BS$¹ ™ft‘—€,ÊXÝ‘Ä)éÈÄzºÀ 0Yvâ@Z–B¤Š(~”sÈÓé·$¦ÁFFbÓÔ›NWð1°«N„ ¡G=íbX5¢€–d3C“7Ôašà~é¯õ‡KÂf¹ŒDö8 ä$•]RÈ%٦̒Ôx‚$žE³÷ÂsÝÀÿ[pÕJ"`Â%Q}h¼½…°IüJ­!½€T@>•Û"ëͺhö¶›ü™! vE»9ÈKÉ„±`OÒK5e¯%Ò³ ^*â? Õ¬~|bp(NDIõè½H±Š<â¶ïK‰^_Çý ÎTbãI®w°Éî8„ꩊ¿†RÒPM§v¼•2¬¦$°ò>²³^›ÄzbÔ=ª£ëA©ÆlL¢–רQÔÔQøÄ!E!§Óqa39åW \‡Äz=JsœðY.§àS2hæsK^lÅÄ?ªÐÿ=æ @öÎÈíuœð=X€ž§Ñ©¦±ÿ‘²Ý$ ›gÞ™¤5ßO*$2½¢JÜj4ja£ñƒ<š&àl<¦-ݺQhdlÅ€¯È°ÊH#þ+¥n'Ò  Ô^ìD­éeOSúÔtª Ìs¨‘:ùb]ý1?’Yk×…–íÐE? ˆ~4¤›‘}!Ô0KtJe‰°h‹²HÊ»ê^G¦5H’š9ó [Tn,•a1É ?ó´éF (6Òó'%å—÷¡úDòÔhÉ` ÃÐl}Õ†Ç7Up*&†î€%£kli2&ªAOGiW‹m#€€ªÂºÜ-2ð|4p3žû<€ ÇÒ|g9ëÝDVü±êA‰j‰ÝpZ—òC¹·¿ Íäq9 ‘Ň~o×—QÌ«Wi Ñ”¹ßg±È׎µÔ5pêËþ¢Gñ_ËÚÛ¨%Å÷>äÇÈC©AjŸÐ½:YQû«šY“DUÚZ2ŽZ‡®•$„•bI&ÆHfŒ•€ Ì¿[Ý.êé’²è²;-tKœ Í­åÖMiæðÚþŽD–˜jPK,YÔMCúxêÜ›s•ýƒ‹"…2R ‰2·é»7ë¬bB™ø(õP{2R¾Ïäicèã%âRŽ)Ó‹¸-ÞŒxÆ’jžYZªQ¶&uʸ˜¥/9“kd³9ߌºæÀðÈeqãc„z^Vñ‚E«¦°b¼Qô¨õÓ×Yä pýkÆÁê]j¸Ïu–r¯½sH!sÔÉIFb†*d¨¶ÚéHÍ«Š¸ÖáŠô&›àìGû·²)Ú¬Qnë‘ʸÔêF혛3 ç"þÇS|}Ì3$¼çónæôÎçH³Ëw a7µ œÎ•-Ù ŽØ<‹î»“%‘ ô£šäÚ¡Ñè›*Éö‡=ÝÙhâ@×<`¿ìNo ðaÞSŽ×÷&?pÙQ)owzj83»üÒòl’·x{7 ,‰:sG›ï[;Ö!7ˆ—«"q?ˆšùq£{²@´’VU`ÙT#¢l t=Ã*ì’(}ü èáJï 3¢þöõo¢BÚëWá6Þ:5bùµžy”™ËK€]’£ç¯ñ\2 Áúã9CK¨!óóù¥f°ªìxGG½‡L?£On&¬Ûbíçlõo¨2L$CÈr"${¯âÔŠ5…švRÕéæWíVûnâEˆœìˆ¾îSËÌ>ãŠj+Ä×KX³„Wg«îÊ*(²DH$ë$ÏcŠÂ0×O”º +Ê”uC¢Ëp^Po"%Çôœ‹œ«‚,íEJLp ¸pcxðЦ.ΰp‹‚ aúÏî´‘B$È$$€Wïô ßpRùáþ“Ïpާ¬†‚ª§ ÞD¤Ê¢l z’Žøùo¸›Æœi©@ÜèÖNÄþƒ¬Ež¬.ðÆ£gKÔ.ðÉ.n#Ī$ÂAæ@EKrÀÌþÔ*2 ˆ®bƒ¦ÖàŸÐ ärpl '"Ô+ͰßÁø¤ÇnËgˆÕ ¼ŒD†Sìhþ·éV«ŒLC(&ÃLÑOF.ñžaé ®ÔvÙ¨ .*òö…ù©t«ŽÎ™åàDF„’,þ°¢Ôî(Žæj‰%êlÏÆ¼ñ¶×BâO(rRt¢J6¶k¬ÓÐPp0þl‡ ˜®`ù)¸×+È篈dÐ禜6à ¾–$L!±E\õkØR ÂÔf{¥ü¶ ðhZL&†KöÉgO$ð`q²~ËTâl˜ðÎ4¬ü—PÎQMHZðdqˆ#Qj© É#Á§(ÐÒ$Nl›ªRÓlmI¸¥¢ËgÚwˆèƒ$ Ø&ú¡±ZXn·i¯$…¸+ÑìÍz¡ôÚ Ìæì¼—í–$èìíª¨éÅj†¥Z÷F„¦ðp¼.šô¨rœÍÓ×MC²¼£ï,žEæ¾é€åËЃ+ {©ŽÁj¸ËkS-Ç.‘ê¹nv½º?†%ÒXM͸µâªÉ(i¢2(>ðܹ"%1 *ÉæèëI *°œìx½®¨:Ëô¦#§'‘Ræ'8—«”SÉÔ3T' %K+ 6-X@ÊPH¢`kO¥"¸à ®‡>& î±R‰%!.ΖAªP¡ ä¦gîÍv€hT%æLb–û)LðÚîP¾—ɰ£«ãœ“Іj):$írÉ3vêó¶Â@þ`⢖Ô/Îz\ÞÉOŽ!M±ÎÁÍ£?F>‚ œR3e!þädÁrèë+VÓb~ÓÏäêBp"°"ˆè°Á- ÷BrÅ0q=d‚t*v^m˜É#Lqc bO¬”"R!S̸OkDÅö«”„À¬Ê(Æ…"}Fõ6ŠVކ8\Ât0Ò-BÚprÖ ºlþ÷жƒ%æ_м÷̘þì”üIùJ†@ÁK§Í´­~bDƲJÎE5õh 2¼˜óæL1Ê$®~¶ˆ:ÓÂB$°gž8³ÍH¢ýê-=4 Ëx–oRþR(Òc‡n=ä‡IëÑ$,“HzÊ ¤Á ήÎèÄHæ“Ì5_‘²g‰±:hñ‹(%£XøO2eüÃÀœîù*tè´•b¾“øjÜÝuQî{)ÂŽ©M$)¹DJ,{«•áî„ÌxÐäÏQ:‚ ”J¯²$NºRu*& öãê,@ !Oœq ŽƒóçÑ"ê¥ë4•zgHέ4ÌÖDP«’¢ÔË8\#LGƒ`°¥<‰Ì\YmªÓê°$¦åÓ2IŒ*NÖW@ïmavgÒ(ÖPüÑ5¦´“2þ†u$šeD)ÆA«B…œÝ±JæD£;Ëã%1OõäºÌqƒ£.IÌ!Í‚—¶p<–ËIÉMN¾Æ\ꆢçM…iS1Æ¥µ—óævïΚñ ðjgKsl$ê%0í: °–®ÖWl§g×ALB#Eü²E÷ ”¦ûKœäÎ!BñßL©‰ àIœ¢Jl!ÄÀRq ‚nWRŒRxõÕ øì“p<,å\âþ©Ç"p³-4MžÆ’¿˜ÝsTçt=ϳYò^2 dUó‚s˜ºd á°«ùÆà ˜ÇÝ'*f“Ðnö‚vDÙ „{Xr?ÀÖz¼EqÿHrÀêæm÷*†TÆ0¶:g@"Iü·²©™©dQ(J)bC"¢ ÖχÕôŸ'€åŽ@o'ŒÊe=R¼Ï䀜õâ"YÕt0Ö²RGŒ2xd•G­…AEç1pr‹ÆVxL&_'¬ã‚•Ü,h¼T;qúFÀÅ~Àcd8%{5™Éè€îˆÂ…÷¹™)LGB}eüC¶„…ØZä†nåwùêPøIš%á¾ûŒuF"˜—kî’ö¼z²Lw¯—mAAfùšný¨0…¨>ŒÑ}Y¥ßì”ÎñK +v8LTÄœ¬÷ºñÙ„0e öyŽûJ¼’/b4°keÉ$ãÍ‘5»I£XÛãœcš±dF1¤Eãr&–‹ŸŠížVÖçž:r>^¨<&6åÊPa#a;Y~ß^ï%ˆÎ«òÙošÚ9+[´è?¾ Pd %1IûNEjw¬F™%“›z©[Ê+bq‘é ?W|HŸWN›Ù÷ËN¨¾ þí%êìsŒ@ƒô­Ì‰=ÅØ­‰@Ôô'L7¤/ÂLwZ†¬r™º@p&0oB¢GNÆb°®Ewºfu6‚ }4œw@1¼–'Bìf0{¦A°Îø]MÈ{í7_¨˜¨|¾ʦª…ç'›À13_ ¸ ¯ÎþJ빇MdeW?:¤añ 3*Üwzq C–´6yÝ£<#<ùשµ{ ðËÍ–›ÁLiŽ…»\*„ÆïdCŠÉ+$cØoÞ@/ì ù[Ñì÷*»oD̶HbDÍm€+yËôWT»±Ìtb-{4‘^}n*}~¯Ë$¡; ŽÔa³4 À°^ÇÚö0†ÿ ~Ü#ÑÉ~ºx3ÕþdC(ÌFYÞæP‚PB^ ÿÍ®±BýŒú统K¨Ë ›Ž'Ÿ`V¨PGBK[¹t2ü†™{¤[¹©åJû§›¼NÕÌ›Âsæb–TgA©ðÒÓ2‡šzaŒL ÒwÓÕO'¿úuÏ¥?éo¼ë'Á :ԉ¯¦5›§MÍ%\ˆ¨l)žÂE›Ÿ¸GzùÎ]J¤€Ž¢|ÛÇ™sÊ]¿1SSIbY–/ÏŽHlçšs—Í|Ð ‡õ»m)°_u5Çp4¯QK6´Éœï"et]O_Ò¹aÕ@–ŽÚ—¾Sér ÃÃ{:à7‚xŠ© ¾«š%‡×Ë¢ a‚}iŽ:b? P ƒ€PÐ$=󆀡 8\*þc‘§óö@‘G¤@g´žK Êå¹tr`‰Ë"p¸ô ,Lå’¸\V\û˜M`òÈ\Na*•Ǧð8$áõQž?âqè]Vë’Xõ]–Ad´Hd6mLR§±ê5\0‡'É„öñl Ì"´;EÃiPkq9ÄÂ=[–q–§ôÒ:µ_¢™ŒrǾÇcX*Ü/)0‚Ðb·;xí¤G!uºLV¼?îóê-ça ÒBe’Z‹èÁÄÈ3`zæóåN"±:Ý4 «AÀýZÔ‚=¯oï­»ÿËì¶×Å/;âŽFcYû†ÏA—À{¼Ó¯OnÜ}v5\›Îð=O#i((›ŠÅ%oºߣJ¼"'Ê`à j@ø€-ûŽô¬àf‰ªnk"•®p’¶Ãµ‹„ †Â«Ú8ßÄ-Ò\¹¿Çò§H*¶¹¢°Ë´®$ ¢‚¹ÇˆzX­Ç˃¦Ô%oêÚŸî|; Ÿ¨Zp³<2Њ ®¨î5Hk~¹¿P#ì„ÅûÐ"ª‚¢–,KÄÞ}"°<"­ûO>%h+¤‰¶‚ ©ÃÈD2D0¸; w!2íØÊ#ЩïLI@²ÎM°]ï³'äÍN8È;L•¾‘ÊÌÄ#Mœ£>À2â,!©9ìä!ô2Ñ £(Ê0Ì2ا ‚‚ÏTl‚ب‚¶.n”;¡³3)*ÓMMLúÉ‘Ë Zgô »Û/. –¼TþJ ½›w0p­ËêÙñ|YN¹ú–7òü^™/ê»$XË Ò—.¯,m‚(2û‹|ýz~'ðzFL0Í3=‘½âƒ;ïv+aB]PëO ǨN8µ-Œc Ÿ¶ .ÇKù¬™`=yzLø°ß§ Ç+;뜢¹ÚþŒª2þcRÔ]„ MêêÙ zb^(ºØÑy´ÄL¨Ô‰#¥müFLÙî“Ó­s/, ø $¸ô§OiÆ"í0Aÿxn·–TP0 IÊ&×'‚!r*Ao¤L4¨ì é$²ÐÎU•¡òÒ'"(*`²ÚÏlƒDÓNÓgR¿cá[|*áMb* qËìé}v[lM‘® 6ïìgçm’÷¸\dÙÛt* ”$Dâ>/‹VŸÈ-GKîr@ ¤¸ŒsåÁœî”¹õH;è ÙHZ‚¯¡/¡¿¤*¶üÀ8 ¯+Â8VÐ’ÉO°’¹TÜÞiwå] ’ÂpãÈ›N/äÔXÛ VMlAÆÀAÒaÚSM=†ÊGäR$Åy¦B—ß9+…ñœS~ôSn$i’æ†Ù‹›5xª¼Ž:ò8ùì],Uû¹¨Z}Kœ<Ž…z.aüe™Sq0ƒÀƒ4ÿ”b0F¨>g‚Àf@ïÈ}@’ £Ù<¦Óž7àw㊊omÆi #@ÙAhp¦5ȼËcÐ*k­ºAy:â9‡zGפ©Z[‘ À#’Jr‡™s€Œ…¶óxŸžáV  [¡S´G¤±¹HI ¥÷ Í‹­.éYBYÏ¢_BM-´I•ÎâÔ,Ò}ÚÆé¦Yœ:˜ÃËæ¾añ0J”ÊLWØKŠÚfhÉ¢&Û"¥"n$³2ÄçûJ¦…´HE⸿P Üœ4ªÚ_²›ž¯ÅJÅoAÞœµ'§ÌDù€iUÓÛd‹qXœCè üˆçŒè%^»&DøIÄ:ŸÄ*ø§;^(Úy-ÊÝšji“,3ß-‡ä!tòjTЂ#%%ÄM ( PUÛÌÔh¹TiDÈÔY,ÏÆùš?©jL¥ªÞ´GL†kE“Ä@ˆÍAZÀût“ú©ºC´vœ=]@ñ©6=5ØlpkâµXvb¨]Hƒ3 ˜'B—Ó2¿ ä”’ÀøÚÑ WdåT¹‚1ŠºŽ²ŽVCY•"ÕÖT¶j|ˆ;:°|¨ÚeÉZR³ÖtGi¤Lºx––ø¼G˜îF§Bý€Ìš––BDÿ+û?¤åF–ÇôØ©aÀý4dºË¡•Œh•&|°ŽðÇAùåfµ#á¸7"‚ï´e¯QVqØ ô¢XûŽÑYq»‰T€ý¿ñfψµY¢Ê¹¢ôăÞ}{bC¨'µì+JöÕ—)2!R;­^eò¥íQÚÑLç¶]‰1}ȨÀ¨Âñ‹÷Ç Þ©“teÆÊ˜-V OuÉrÛi«ÌEO±Šå̬ñ¨•DÌŽ¡Ö|â5 ,£‰„…eã ÏW¨gyÕ¨ïI£#£•½—¦–´ãë ²eA™Tú–ÇÞ(”Ëy'–WÂ×0)A#N% :É¢ìŠeh¿•ûR€¼u^“&I•aÏÜVçÐ Ø MgÜjBæp©(›48KN5Ô ª(è‚(&Ðs™ånú!‹u“5Òè ÝVŒ¤í”ÈmÒyÕ»'ã€eÙzpÜs/^Ow‰mD½#铊ÂËlz¦¢'M£ZT[ÚïS™®éÅ™I’Ü÷cÐT"¿¼àD*žŠ’2|§@zr<—1Âö§vH|›è oXÀþ}èÊPå˹œ²-Ò¬®"[±µâÜ eÎÅ]ŽuŸóÜ‹ÓXø’¥¶ìoÈú©Dh³0ÂVš”K¸)™ÇCž¯ô¤CÊÃh£e½È2Š®åN1$ÉlàbÜÝ,­ØZ‚ßT9tÆŸ1ïyîæ|ÖvyÅ3÷³bûyFÄ'4ºÔ˜W Wh}F-ìiñéb-Oh°MX AP ÞPèßVˆ~LvåâM6híÀ-UL©é™íßg!ßZê\Ö ©c8ÄÕ­yo*Jú›¬ýçк¾ÜÍsÚ Í8[jŠç]ƒ°Y b1°~8öàPyp`´‡•»ÒÜø û{ùq5í Å2‚Ü0Xë ²fÍmˆÓB¾³¢x)}1 cë qÄ–“¬pòŽ€ßŸq|%Êò j7Œ§)¨ê¢¡º).©nƒé¤7 j1ÁÜ>¾JÓµü걦8‚%€ û š‰ˆãr‘ y¦è†—#÷òì· ˆ·j׫A€4kO"K 43@µ“¯c:8ÉÀŸ+ú9°»( ߀t+°05n%l"±Òø:ƒ0ê-—ä(£š€¨Ó¹@~Ž‚Yš“D'¨Ù˜’†¼;® ñ# Â2*+B<7Ñ&/Kw2sÞ˜*Ù³xzÅà…‰K-¦“¦ñA4 ÁQ4@,2ެ'ˆ9=‰\6ºh‘0‡š :&’>š œò+ìŠp~#°,jT ™QP9¢/Ò>´b¾œJ›Ä”{¥Ìp.†7¡n;J‰>™é)ô£¨Æ[7–T,Á³TžÙØF¡%¢Tf‘€¨šÈ¢§žÀò’¬6²š×¨²RÄ ÃCã©YLŸ°ê´¿¶°ÓÏ1˜‰>{.;Ù5&’›D±Ã€&¡²¤ é¯YxŒqÒ7œD³CÓ·¬( èD[]É*ž20»&„[ú­²šµ«èŠöË &+˜Æ'Šq° ¾<7Rü¼t›Y5!/˜‰y™ ¸)3B¹Â˜5™ŠÛÂ&Ê@.c|£Cå$›Ç·çª9g* ‰[Јሉ*1(ÓÄaãÊ~Ò=²Ë ´¤²©Å c]"Ì/ÅDЙY6 ¡MI:»½‚·Ì’ÊDKºËÀœÙ¬ˆI²:×”D½±X¸D(¼º¤IH~‰,¸Â̘±øœ@×°‰R¾ûÄ6ÛWÔ_€ç“8ŠÅàz–PíŒi€2ÿ<Œ‡Ì ºJ‚Å,ÁG*»N³›ž±3ª9:)i‚;t?Û7ÜÁJÑ3ÍŠ§$á‹3ÿbÿ·9‘7¼T¹Ð~/a(«€}— Á¼-Fx¨ $ê£ÄJÿˆô¶ t#)€F:Lp‘PyòͲuNcÈGÊÓ:¤ÏŸ)Ó@ªÒ¯sR<˜>³é8z~,ÿ«h„˜‰<Ñ)DkßšB>°…¬S‹²ôÀ¦¥ÑüZσ> zÐÀ€ðÂèú©2BŒ : SÍzÜÈkZ"}²ä,Ð{íÑe‹ø±©?Œa[¦‘¾ŠÌ5;ÚU¨‘ü“à  "zD…14 J2âí6䶇ۅѣ¹Ì“<1Y@Cú©|‹ š–Ù&Nm4hùeaƘlU1IÅð‘Ô%®äOÌþ™4Û²¢4wGÍDÁ; ½B}MÛ}IÜ}Æì¢•“ ºÀL“qœSùL¶MÈú18ŠÎõ!Éò¸:q3}kÓ$É£²rŸ+™¯üqÒT€5ÑyǺYN¦@¹ËŒ5iE6Âü:’‡•{¸[Ÿ“b–#73Tzñ:*©|1xH •( •iSÇ*ðÊTHǶŒ„P‘$Z(Ê„2Ú¯!¨5”ìJ¬e+3'1x—!š—ÜÜÆÈ’ ™ ¿±ÀÕÃ-*ÝÁ­Ðò“51ÒÿÐyM8ð}F$ ¾ ¦L}j´ÒK£zŠ’;. ©ÅjíK,­òK“ÙGô¨éN˜$2L&¤Õ(/$¾ÇÔoA:³*òºÖëÜ%d(xকN9|ÛB€¾ô(ÂÙÍ’©“|g&¡¸%=P ¨‚ÕX†² €%˜C”ÁœT ²SYš³òt* wÂFVÚ|ËK/+¨ÇIÕÄÓ1Ã+Íï—Á:œŸ TZ"ÊN5UGh]š5¾=FÁD# ›7 í!•šÚ:µKkžÊö0»JÂ2\#Ò݃YœÚFT6Æ43@Í· ):¯ÁI¤©íÁ* ­1¹Î àBÚ “5¤‡í–ũކÃ1XÆ%¼Zø˜©4°€K~ÉX–R\Ï–QIÓ†”‚Á¤y5ÜeIÂ1<èú]U]5#µˆ¸t¼—dœ[Q³s¡²äœOÝm‰)I·µÔX—ôïÀ¾”qÀÍ\\‘e%sŠŠ ÓÃW*Ý­“[ÁÌ’‘B’¾Êð1ªµ#7‘3ÙmV -Þl3²éQÛüÜE°áI£Èø™ÛçB) ™DÕEl?<Øø‘S€¹‰°¾Å3"ÀÛª«Ž´Ò»ÆäÁ=Ó·á Öbæ^EZ­…+ âäÙ͈ò«CÛ>9(µ¨Ÿ*ilâ¹™¹ØÇNpˆŒXÆ1:–ÉÀL«',…ÒŠ ‰[¸BÌ)à±½%Ú€6;ÉëÜ< ªû2&JbL‚]è¶[Š J+ÿ £hLüÛ`@«a,üØN6€õ¨¨×S6¥5›Ö’EC1AZ-#… Þã/[˜h*Ñè¢iGQe•õC"©¬Z2+UH '„—B¤·]œTÄܿ튿u°‰I¹˜³)bqÜ+ÉÊâ¥%æ ¼ Ëá­¬\£¿LýužŒ3g±ð(µ&rœ}ÐC2Üü4í(¿ø×œ”f^‚Û=îM¥Ã3ß"lk´æIxâER#¸”zÅs.Ö²2: J[¹²j– 3~–Y*è`TyÊ“™¿#®ƒx“QÀTí£æ>\ÁNÁ:ÝŠ!»·Ö6=@þ ½ý ‰ÈÄÉ´Zv½¢ ·É‚\2å!Îå:…æ5á«cö]P&â®eŒ±ü‚šDò*°4Å_1ÎÚ-jÇ}ÉPq=qÖya$—ÝÏÍvˆ{ˆS* {3­~{³…Ê¡yï„(ÜóÚ$äÁ?óÌÈ„?ãôÞЈæf¯º1ž4æD[É:vR) “«S–i8ŠàhƒW‹Æè i`Zì)Š_VCo<íŸy“¤DÉ>9™¤)6°ðß©®Û¿õë²üÜŠ ‘ɤJA—^±ƒ'+É[ô> ?`.v">$éLÑ'æ"RaƒY¾êÈ%ó¤u;C4áå燵ĭí' ˆÃÖŠŠˆ&&J¶Wêüö›‡í¶.¼­ê,š7ÚOXú¶[À\³;ⶸ n'žíg]ÑL-Ãîôzdß?FQ-c[oØÚ×îW5gì¹íxâ=ú0‡ ?:ÏvûŽçfÊœU@"ÿ³Oô_1µ‡BŠàŠ›^CQŸ«ÄClKo¶Ç.…Ó‹„Y­yR£ä–C[hˆö[†´¥(••ޱ×AÈ%6\èŽ=Ts¸À”ÓIîû8³Îªõc ŽcÊ2s¾t Ï g. […ð¡Ë*r„9ʪ\"5×]öD•ºeCk{/Ù¤ípaš¯b#ËÙ9ÚdQÉ64¦H‡Ì,¾6¿Ü?„žúôÀX|+F¯t ùFT;$@ÑéN×ÑY+SHO7ƒØZœq:Gd´Þ]ýîêºÀÍš$ >ØMȶ+riëU‹ïFçùÄ!€@aå`Äѳ[ÛÛ´Ýøò–ˆwîXœ:ߊé%çóL÷ªæê´@¢ôâÍ”ޫ袓0ûf¸ØÞ|=tu3]W1´þ¦Ö ¹™[’‹™±=(;ß’V^XA4ôf8®/gtÝ,Ÿü‘U’× QqgæîÔ3w |iu ¾€©~ÐÖÃìX#ˆÕõ\6öwíÃú¯"€‡É–Çê~%*Þ…ÐÿD& •/ÊG¢¹,lIè&ü(û„}}Ë"æÃžÉ+MZ1RqßzjÓˆAuØ€ P7ì ~B@P·Ü4 Ä_Ñ7üV¾cPp(=¾¤R«þ<B_9<û*Ìbòé<'7Id êO$’Åd8–û’ÀçqÔFO8‰Àå@ФÞ]§ÄáàH½JU K«tX¬ÞÉ&@ë°(äió[£ÕzËúÕ “Ée@kåæ+g’Íí` uîùW…Ø¡ô¨Œª[­Édôz V9¨À¤ñyL*‘Êߟò©Þb{êkw'¶·/K¦ú,”{*ÿ–G°Wˆõð '­ë^ÒéoEa‚Íé9­ÔNO0˜Ë¦‘ìÚ'ƒÛí@3~,>/Žæ¿¢õh.Ò-Þt”Í€µ'ºõ¼PÈot 'žÏâ4N`¦»«D¨>oDô!mÊP§6ȪŽñ¹Ðiþ‹»/kà´ Mš>ˆ¸ˆŠ.|D â–®“´ä®ž mzƒ3*ŽÅˆãÈ—¬ôD@JÙB0’ˆ¬:¥ÎXÓ·Éqç'R‹&†´Irä•AJñøÿ«p@¡häX4ª„cB«nãØ Â Â@Ž:H)«;´ç¬ôŽ$™öþô€»C(š—<òü© P骒ÄÄè‚Ê RTÿ§²)þŽ4K:ÎÍÁ 5ö¬t*rÊÔJ%A/#3R{¢ñµ 9,ʉ¬õKBôü/˯Lã"!i^ž´õJ/R°ˆ*€Æh-–ˆ"+r@£Ðól‚ÛÎ)›Ê(à]ÅTÄ  ¶ž¿éã#Æ2 @4è%ÞþÍ(½^ß-Öc”Š´òÃø¡ IPÒ/”“~&5ÙÿßkD¾Róå6!õ‘ýIŸ«Ò`€IºŽÓÈésäÆsKo@4TÖ<†Ç±Pÿ¨ñjyc(«@̧ò\Óß.ò¯¡)»}MQÊ$Àô#(Ô½d¢iêKmP€C±RÄέô4íÖØm*žßÕ»Ó,êÂ=f;UKvZïª"ãDÌ«Á!NÓnº»Qv·§Q/ŒybÁšáý«íˆ’'KÚH[}š;T/egÝS¢ñ­JÛ‚ÖäOë}ñ<Î}Ž¢®‹U¨Èl•ŽKOý4Ο˜æÂ³à`Nù…ÖÛ†èÛ§‰¼~Ùˆošh¨åŒm§ÜizçèMÊÐ(_"ý{0”C %uQ´LÐðòuïUM>Ί»î·qû£Øš´/`t}rü;£ÿ?Për›DZn†ŽÀˆ©x­°võžye* ̃ Bz¡Ós%{'Èí=fN©’RiSÇõÇŒ@š9[hòÖâ?Óª)| î½Võß«O¯f¨“´J +¡Yê™ò«Úƒ(„¸Ž77¡]ùë‚L<· ¥4¦ˆñTÍÍñ€‹×SÒ:ë !·"ç^‹¢+4~;RnJ“‰nv¦P¡´• À Ѩ¡&X.Q »$ ôÒåœ|u#î)G‡ÔÉ q=LD·ö„aךͅQÅÿÆÖý^¡Œ8ù,÷>ú˜i¾l+ Dɵ×k¸Tæázãþ×É€m`~¢èRâËd "gýk8xVˆyÿdˆºµ¨â) (ìÝØ,£ÒÍ#‚7eÐm©:R‚ªÊÙn‚ÆV8;Ñõ6æ¼TÏ¡Bö9[óbU²‡AÒ·nUmmgÁäšcr-Ò‰ «e4ûZ©æaÊ U ¨à Ú$4W‡©ø•Baa7Éèz»T´ºÈ)¾$êD›‘Æn|¤xxDŠr+h^ŒP"‡™r9Y€8Ѽ ­„­ŠlhŠI÷ú>ÓñuO‰¼Û£Hà—ª¬v{Ïq²=ǘz ©Â„µH¤¤”`ÞÛŽ ¯p÷¡&S¡êšÈ*"v J™Šdp,YLËDz³Ó9üW·2oe©îÛÅ èû3Ó¬’¢è3B \@,’ÄÚf\®¼ÆÔcN‡Ñ ©¥òÀÍVuV‘y+lZØ·,t‰=N¬ó=î"BGÓ·9è伪ßì¡í‚Š$›Ó!úßÛÄlöÚ+!+jËÈ18UN—EõjÔ^¥Ž,ô¬T‚*p:{Vžê "Tå:‘jUÅe}­@"mé[sìÃe‘uG­8+—BX±¢ƒGðÿÛIv·Ø|õ¿·"ݺIV¦‰T½'†ÁÝXak£w¨Ò¤[v×c¤Xú‰µè:‡kÙ¨ÿmU’0¨îþã=“±Çý#³–«HRÓ K̘ö¾ÔbHN—î ·›´knsU}¥Á–_‹²^Áþ»òf.ÊËÝ—¦‘Sg Õ¼¾ûb«E~³Þ¾(ÃŽa!ûTͬ•A̓äši8FùŒ«õOMµ8²8fV<æµ_Ë,2¢öF©xEÑ ³@¢põ¯Uj³A.L¿± .·Ë«Dp? Ž™…Ï›&égÚÄ­ê¦g(UiCBöVÁ-¤iGxDkÈ™:¢ýsŠÀÏYòŽH„OuÌKN,4ÿ›ëú©ñ+|pb³ âR'æùÖ ]„ù z‘6¿Æi­&0§UöÇÑ™,]ü êFÍ—Uc§‘iƒûGœ_HÇÒ(YŒb¿ZÓ·Ñ]$?±ê4ò¤X²qcäÆœÉ ŸI³rJmeÕÍñéÉÑq8@3–O²ù¹(‰Ù£[–M‘ÇÙBÒ<²†¬ã9þ‰R‘4ïµZýÆÀ;èè(‚îdBƒ³‚>V!›ÅEMGˆzåWÎ 4»;Ç*í®ëu ¨\m„AÍ»GYƵÄ4ë*XŽÍŒH€ÞìšÝò…/v'h.ï÷ËãÖyZÄÂnbë»ÖW$»Ò<î?‹q§Ø$ŸÉ¹dÚÕdr-QÐä´O®ˆ=ÃÛRHnzYѹ|Æ]“j¥uWœ÷ úšÒ‘ ŸA÷,Õ V×rÉ„7‹lJÔqmô”ëÐC4R'Ùè7cÚýá;ç¹Tþ` ÈBI.ÖZºBž•LÁ>ØùÁ¤scz¢Žê·mqV2êUÄt‚šw£Ô¤,R>’'öïî¹g-Ìc¡¨™ü ÏïÙ' j.Öçêv+,fÎ.é†f N+€¾†a«*ü€ Îà+e"IBäÐAð.BŽa°*è ¼Æ(J$î\ÈRtîþ€ þ´¡ø$§jŒâôBÎgbb×ä¶tOÌê´'t‚¬ºÓ£î\…"â*‡ÐK*ÙÀÒ,ŒBÄ$u¨t)g¬?ã´R.*=­ÒƒÐU&îÃãä éÍB» fø§P=©èç§@Ži¼¬ ¨øÓ$ÐÌ0¡°¦õî|Þì™BÕN¤¼] ÐÙ§~ ŒÅ®b±Ç"óê–ÒË|)¤UidEÉ´€æý` ¥ üANÃèJ£Šæ?ªþç«ô¾¬X>I øh§6Ëf±Nò}Çg.•ºÏf·‹Ž®1$@Œð}Û ï«Ñ²ì>í¤Pkh:y&,Ýþ倢Яø†ª8Gjh¥§ ‰†¶Š¯¬Ã胇Ô%B8~b—©‘(ÂŒªïƒû È> Hg/D±Kq™p`n‡a‘ÔËÇÚÁl<,ðø©JJË k¾jê"ïö®Î"K¤ð¤l ýŽ£ ‹ bÎ! ,?j#Šž­%Vë ä/Š(Yf…RPox °HQfèRx.Kþ* 4ʩ־ÀØ0æ„QU%×ÇÕ°†bò0Œ`R(”fîºÝMÊ$„cŠb*…"˜K$v*XÆÚãÏœËÆhÚ®^$F,hähö´b Î&/è\éŽ(ܱÌß ºPñ´".~`«dÓÁúëbÏ'!öÉ@Ufx#Ra­/Ñt½¢zÿï !%~nzº ,Åí`’CnÅñØýŽ-$ÉdLJ.¸²Æ£®Ñʼ<0ˆS$œp¢¶0ÐPŠœ-Å+ ¬¯ IFf’K‚5à )ïD« -!HîúLÏ ÅÌtpæï°Ý G$H+þèÈï³b!¬,¤#DR3”ƒ®DÂgé)1på m% Ì©á­?3¶t&ŠÞˆžL"Ùà+ÈË1¦ç£ ³MÅ1¤.\£N›ÉœnÍ6³rvf‘Δâ*„d\AO|pS¢…fÊA TB«–•C|ÊŠ Üï 9òñÆñqrM3=! ä°ì€/°Q'¬@† æž@fºø† ]ƒú¢—\³IG¬¼G§Úl(#E‘‘EÉdÖÈQ5f’"Nê2Ï8L½%Ï6ç°Ÿ“û0ó *TXl( Ñ'²×­LÔŠ¾OÔ3Mlºpþ’ƒ) âø ¾€ÇŠ ôôj9M®ËÂÜÑü´îü>.´0|0À MÚSNÀšÊ’h”R@ˆRK3NcnœE e ÛD‚d‘)Nzf- b¦*¯‰uISã+"*”Y笄nðGövJ£øwPãPD<’4/ n„¯‰C‰TŽës¤.R<+ó¤d‚¶7ËÐãÐö³ë9r°æ3¤´€-ÂUÈ.@aë[UÀýîCd #)§è0ÒÑÏaë ›èÈèÎt¡qÃKM# ôp©âΨÓ0Èt›(FH¢‚äû1õ3wrlØa÷j°[Pò~j8E^á”\ô@*·%Ðç¢ wH¹hôl*øìj”ÏóÖ@¬ V¦ªj Ç­L Sî?äng6 =6S†ú{4näcÂPó‹ øÒ Yƒð–/qx €4¥ª™9.JOÍSK ÝNéÙUwžt5I¶[X°Xd ?ŒkÁZPDŽ´q„à±·nÇä9صÙÁe-ô‘<”/—‰p"oaŠb<þ9eZEMh‡Ï4b²A5÷Œšê{§©{58b+v\¼ä{÷;(’Ìif ?B|¤˜b&Ø'u[+• òf%Úh˜š‘]Rù6ÈÂÉtRÑV~ÈHË?ÕqòÏ÷àn|¤ê+Ç c¿¡ ¿KéÑT³åEaP‘4/‡Êa÷^ù„ü•¬Ûa޲Vt¶=Ý4!dÆŒ-†P[ŠÏú|ÒØådoŒÀùëÊ¿TjÒœ Ó*‚+Ò'~zá\Äâl(ß)u™iîÒ°® qEœQÄ"£X5³ùC÷Ö³:-»K©¢-ÊÓ)¨aZ|°æg57ÛY’óYárv ËÔ¾–SÕ÷O§iÀκJÈç…,³7áNÉ}ÖfUÑÞðŒøªè’4úvå0“rÎ]¯¡ôcóËõþíö¨ËÈz©iî½Ù.JÎþ’  ¶R®L`R·´AÖŒ wæ"J®³ÊŽzUòKžUL#Å*8G!H¢“CX0RzØ ˆ¸=‘ˆØ=¿ì œç¨q,l²Û›ö.}‘¾{iã$µM#=œüÔø·&{¯i°éÐÔyM?4Ñ ;J‹‘ui#ÔÆ¢PUƒÆÏ¢54þàyK`.X®$W§X;ÑS4ôû;aœ´œ3«$ÇÛ ?i§Ð…;œÖ‰º"2·0ÆrÅ7©6 ¹ÜbE 7PI0Ã}éߺŒ+[$¨"l"UÄi"E›¯MHžË¢™Îí½$  îƒ!èPý‡C§óâ)Eã€H‡?`@ÌŽ5!ÄŸò™ BKG#ÐèèRÿ‰Jᑨ„J15}OÛTüò£Lã÷ÔÖŒŒÆªÄ…ëUˆ?+ŠÔ~5X~I SY¬Z//…Aqˆ0%h¯Sfµ CÚéH²Â&µêåâS²ª „†khšÌâQ©ê5ŒGðrêŽ&!–ɯ5ŠxBÏF£ñû/vD¥¨NhÇÞû–Bp”å*øÄßWÑ×kxìÖpšÇëÙà.½ûÂƧ¶'þSDÖfwG´b娅N¡›ŽVeùÒø‘ø”²DåLéYÜýñÿ^öFûÚ—übý Ý»ì ½€ søþ&¬ jŠ‚ ä+ l 0¨#~£@L2™­Óœš¿(„ʬ B I›œèŸðÚ³É $À«É«•ŸŒ¼Wª.#%<ÒÏ€0“®ê,L F°Ëë}#®ø™£ë”>…4Ì´x”°/ÒЉ)¨‚• "M}ÉÀ ¬C²Úæ'‹¸™Á-SH„¡QëG;3“2¢ÑÍLÚB¢Npd™Ê£È±¡’ÂÂéN¼¯K3àÀ ”Ñ:&Îô E.”ë¿çôL~¿ "×ÄL5D2 YÄò$ã6H@è"ô"¡JHôôÔËÕŒÜò¥V)›”Ü7P2ÐÐö‚¼Ü&mܬ9LÝoY±Hìl‡=hbÑ2Ö GiÚ{ó$ÉàÍMr/Xèüó]Óèív]HCïz¶èUŸh=RºcZR–Ëé~GôáýbW”Esoà´:ЦÙ,ò$Øžôõ€éF7•ÄÊSã}¡PÈÞ$Öd':ˈUŽ”©´¥{q£Y“¦°a8fo7@Õë6‰d×#™KÍhE©LˆvÁz:Ö¯VùôåƒQ`%­Hv€ib›—gNÆ#MÈíÅe®8iJ”Ü-v£¡;ÊnWSh÷¼^¯#ô/¤£»ÜГÓ‹Ìù© >å$4š©ïî} ¿jÉ¢S‹)ª21Ëê5gÆ+r”¯&kúלԌ¿>ò͵j#L)K]‹¶§ôöÂúÚìóއ#Wˆ¦êˆzs;éâüxˆÀåPhêaÊŸþ`£Ô1&,Q’¥)½‚ üú¨½=[¼™\%V\3¥œ'îWí'õÖräørRôˆgGnã3Ç,‚2øóŠ"þ!Ê‘<¢´Ž©먰¿OôG!PD‹‘"Ö~]ì&Ž„8Øn»?‡…i¬d ‘г†]À©lÓSN$0ùJ²ÖyÔªj’‰Ö)æÒë Û]?Iœ*gU2˜XqPú#² ÐSŒƒuàDÂ(Z„³hŒ=ù€ ž¹›‚ŽìúôOy‡& …C²¼ä‘+.g†úR›ë…ƒIÅF’e´ðÕ‰TÜ~$e~ȹD)®§¢”T¢žEo:”ÂŒ¬dëVdÍ÷ìþN A]Ì1Û+4¼B”ýUÅÊ$vÏe)b ŒúÐȽCËùm ±ÙJ‘ º­âD1—Ì2e­ÀuÒŠ‹³a-+ˆGRIOiæE³µ5Ié)—,E)ÑÓõ?Ϥ‚+5‘<óòfßÓ‘Ÿa³œ¯g\¦WÓ„óE“JGQ\s PÖ© g£@bÒ{0+aˆ7¾Ÿjl‡‹órªÈ*•iaˆIªÄJÍHc`þ# ~º>SW€h- ö  ¢(×XôÞ®&˜´r°R—¹¦UÙñÔÉÍ(‘"ï~ÌN­—ô–A>}6‹Ô5Py«…_uGêpUÇåcËùav9…0¼ãè00¡±Å*ÆuÓËZ4sØ£ ²×Þ ¤dG‚ÜÎ“øZ£KTôÅJÉèGmœIYQ~.QÍ]JÁ¸.UØýdXGXÛ]kKݾëÄ?…Â=4tû³ÇSSªeùM$¤¯M#æ¦L;GÏœ…]Ú¶Óì‰i¥€ò"ä™JâP˶ˆ·ÒCHkª-<ŠiR*C!3yºSÈ…Ü5o:2™o¯Y?-l>ÕêÆÐêo§ÞP¶TÇi©±v#r-Ž˜«i+¶PR‹þ5™ÂfŽÊ௄æ ÝÁ¨€ r˜¤u#ÖÆœs2RT+WÇ9«Ø³“'q)ÌÃê®É—!WnŸÑ´÷®_)žû(“6êWî3ÀrdAÛWmX¥kbã8°:âÁû¥”ÀN4¸”äÆÕuâšôŸó(Qf[Ã^h«"º¼ÖC "·n;++rBScã!X€£=ÐAª|ô¹¥~p›‹Ýðæ÷)ìýDEïvÕ¢jÍ bI`>&¼D½«-Y0pT®ÁP8Ï@KªØø¦N´"“ö¾š«:•g‡êBpã[-ª¦ä§\ÙìýåÏy-zm}WìÌMKë þ^}BÔçžF½û»àÇ‹nU»O£’¤)W—A‘ Åë]“*Ú”hèwšîB…æ{ƒWþÛ8sΫr þ4)R%’¬—‹ãz~RÊA$¯•¥uŠ…Ú3ù¼^l+œ;vB=#-̾$ÆY’ä­ävÄàäýôpÃÐižq;FáT*HmXI1×BÔaˆÔºQerbvÓ¾¦~êäš&]3Èô<:Î몋蕛§¬±HÒ5%xŽª³¬°î°â|€#· ‚”½«æ®{{8QÈÛ#-9!ƒ½!#œSþ À¬ŠÑ¹ÙI;”Ù{‹ü¹PaÞ(¨¶.ò5±ã²œ¡®ƒQˆ3ý¼ŽÈº@¢13 !ÁC£)kù “=¹ƒØÊ'˜Ü±òÜX ª ²RÐ:R ‡êÄ/’ᢠ¸ý,cÛ¿‚r 9|ˆ#:“G0ᢠê(‹ü4ã´Žb­@‹&©ùºCâ¶I1œ®`>ÛŽÕ9X#0})ã_⛇ëÓ!º‹:Í6{,0êa«R:*“D‰0¢I^ž¸µ"m•:'<2~)€þÊ{žº=Ò±@P¨9k‹ÁÙÀ™°ü²ˆCIW$»Í¸é:§hï/ãɱÙðÄ€à3ÁŒ kp¦ÃäX±ôA[½²ˆ:jsC»f¹Ë€1¨AÛê¤h‚%è~‹[J ÔÈéC s½sYÁäk‹ùÕ/XŽÄÛÌ2B6“_@ø}¬Šˆšèæé8Çòß0¢É£†ô&ZÅ{6¢k"$3G»{NŽrG%±§Dƒ9¸Š(ªa§:¨Ô/â`¿;$9 % “»%iý€,‡ÙJ ¨æ?ƒÚ š(ˆô“K7{å¼dv¤±²=ËCXŽ¢ skèDj2"ÛU(à~Ã*nÄÊ`$«ãÑkëÁ0ÅK'Ù†Áa·ˆ3E|Q°ݻԕ?™•Ä!†<·¼S€=L„›ë§¹?’‰´ÉÛCxD»%Ã#¹2‡C,H"Ë—$úË'ìX”Û¹ ±àæ:ŒF¢p™k&Eá=¾ªÎKÜÃ9#ä90 $áÂ/ÚS°"“.$à+‹œK!<§2¥1ÚE’‹zx¯ô»¹ãZø•A{¯ $Ì·Ê0‹¶ë]A!Á™ž¶|¿»bqH‡Ël¥ˆÿ¶\*"T0RÍ®ñ)š“É1v+aç?RÜtä1Š…Ä8~=hŠk™ÀYYÏûü‘[9Í¢CM,ó²´®ð£0ÉÀ9áât\¶êW4[Ù9+û7é>sh }´#!ÄN1Ö ¢°â¡2ó<Z û2ÁÙÄ˸M;ø; ª{ˆÃƒ@šŒŸ•©ˆË”kHŸAÍ49À¤ó1!T-t (tžÄlwÊâƒ3˜ç/¸‹·™È1®ª!JP0‘«a Kz'±#ôÅ¡\N!!²U%EBêîA;©¿”z*A:ÌÁHT< ÄVˆ1ã9 •Óp|¹ðBÄP‰ó3±ˆòErê¸Í±3*Âu 1èÊøÆÅ«ÒĺH¥0¢`ž4t+C,ŠÐ¯>¬õN{!ÎëAD«ˆÀ«C¸¬|K|:«»ý û¿‡ì*9#³dæ+0T, ‘DyœsAŽb"3zë5ʸÒñ<ŽR7<€ çL­ ‡âGS­c'êÖÊX”¤• ü¦ìõ´k$ub“U¤Ç”ö‰1ç:“ó+šþQ }53›Œº —躺‡%´ÁŽõq5MŠŠñ”ÑDˆ²ŸÑ1Œ MY`íFE?˜‰XÅ¥ÖPÏ.P£?ô8ò£ëq?ĤÍ×ÐË·5*”ëù.2%˜3 7 ©7K"~ªÐåGÀºS2[Šñ™Jø¥Ð‚;¼Ì»õ-U>&«â;¥ I¤óP”fQ#—\±’‡¢Êƒ9®­’× ³ÆZÕŽò·txÏ{m=!–Í"‡),ñBä`3ÃË¡0ëÀ¨{Ê@thV5ðâë;šE˜ÜQ|÷!1œ¡µÆlМâ—%xÓ«Õ_ZO‹³JûÚ†M?3TtJC£”ÄÃ(²"[®ÊަéÐÂhI™²<%l9‚OV*`ÅŠÆÊ ³²µ1JËD§ †O|?…iÀå;D]RX‡A ,žºþ¼u ¢\¯´¸|åÏ=1¯d¼#´Ã/„*‡Rñy™[l”ÅT»»¥´)™ã„Rsüšu5R¨`yr_Ý}¹2ɵ¨ŒÂIÌ1Y<§¸ÜDÉô03°æ7a”¿Ð;TmÞJ*޼¢„ºsWÛȬ‰éÅ2Ë5Öˆ"£¸pÏD`þOÖ +-¦Àk^€!ìª+˜Q6 PÂh ó©*9X䵤ð}¢ ¶” Ö ‡O‰L- ùVÛç›×íªùçYé=¤2­ 4.!¹¦eCÆHC †™&[Üè“Û-c‡Ô„BÁ5YݪMdí¹{½¿ðÕsÒÁÕTöI‡Û뼄V¼(AàÅ=¥bÂáYáLQ^H„VK¬ ?‡ÓR°SˆCd6‹%ýé[ì®ý¨<² 2ø²²Ýb:ÁÈDÊÙáY:=è!Øè— [¹Tár 7à´0¢ƒ™£ÛA²z‚Õ,óº“Z¹zW84ä¶€¢Hðo15œ‡”D€4}õŽqªÂl²ç±Jó;‡DÎ!ˆ3ŒD¾ÉÕÞ¨YtˆS•V~a° 9+]è²Ö2½)±$õ• ˆž¶kb<á“DêBÌåͪ%1!žr½!üØ3êl³›ê©ólÌà ¨¢&pË’]“Ž«cÁÛ1ˆû¶¥Ìb¦š¨R“¥D‘4¤”¥|ê£fIþycBþ-;í[ÑÜ6ç<áø1òþa,1;†ÐSë»è©²MN¸ÞEaíÄR ¥\€FAlàC›L„±Ø°ØˆÂ{ÐVAR;oV=þÑEýé8%FZJ¬k•&zɹù'íæâ¬;mŽWO¬óyM—ë‚ê-140RÎ$5\ò Õ±…½ÜüW5l¡M,¹ŠÎ›ž~e¼€8ò¼LÕìó3Œüì¢Ë'¨Ž¼õƽAæꜚc 8¾a¢»É¥Æ‰ù9:îXˆÒúc•ä[•ñqiHG'àl÷r¸[‘´wÑG* *ÖL. ’Õ_„Bß.Ž©ûêê{O0ï V²d®$ŒgO;Lϕۙ±nu b6óí`ɱQeìó´ßÌ,A,´Kðòѳ“ºšcûf5Ìð'BkŒ_Œ÷p´öJ&Þcì,11¾à®óõƽ®fÄãvAˆ–iAÈo&Q=)P¦¢?”%q(ñ»V“¨¦ÓPô2Qĺnª¤O&Ë~Såló®)ÉI ‹ï«} å½#~,-Î-CÄÆ½—ž—fUCDà}Ç ŒõÐÙ Ò­f;ØçŒ,msùHÈô[Î÷Ű»@ë²b`·¯, ªÚV¯‰ôGó1‰MQg]õ¹ÛM ©J¾N1äLâ ‰Z,8ÑLà»å’<0¢¡*ˆÊO"$ŠÁ¼n1sÎÀ¿Ÿ þ Î±áÅ]wAçkЈփؚãRøîjÉ<¼S´ÕU?säÕÍnz¶Ê£‡Ü™çÚ¥;%s~@ ö ;™œÚñ:î²/§º’·+ŽRòÔ « oZ[öôGîFÀÅÿ‘ŽñûKù0Vƒ»¼³å•âé¤KË•‘ Æ–nB.׎Š3î­cF,e9|!gÐÀ‹û\¡ô ôÈБ¦é¬mk¢ˆÕ‡N÷;”ªiÞ10ôBQƒLLó=Þ^‰ñïHÔµüàté³pmÎÌYë¸÷o“Å‘\êôØRSü¸dÛñú,_~b…­Ä_n>g1þqõá ý‹y…í9–¦ ªÕ--(¤Ä"”'Üò±]¤Í¨ð(¼b±«[_R[*}ÔàVÙ,ræ¼Æ"“¨¬±:Ñ«³ F':…O"éÔ:9@Gç÷è#ç5žU%I¶‚-~Èã—Ðêk ¬X'™h,ﳊL!’8¤¯WÏ+-›ÜÃŽj¦qîït‘Ö#ó­°ƒÃGó·zµŠ£H覻ˆ$ÛÅ«åîbìH"GñÄð8ø]èF¬ïëÔ†CXžX$ª` ž3GÊÚ¬$¯1þ›!̓ޣì’0ž*ª²Jå¹mÛj,„BMººÞ€ñþ…%èÔ.ÇòR‡+*¢æª,Š «ŠS.1gâ´ýΊK´èÓÚ#‹Œ†8ÀŠ…³ì t‘Ä`<¢ˆ$°ª ö!:îEi*Û)§Ž $’¾`#î‰A“2„ô°¨Ä èDÔ—+Ê,ä0Çü´ÊÎÎêð)â8ÍìšG²iù=¬’8€KÚ>¬"‹Ä®²‘ÊÚÞ³ˆ4Þ>0rä¸àD´Ì›&÷·lcP ”’r…A´ •TÄàyZEDU€Râ¶æ+­ ÃS·­B?)Àphž–˜jÕ•BýQ*¼bˆ@Ú™N Pâ%.[£C¡ÉâKŸÐÚåÊhqëz¤t"0­X™õxBˆÒ)º2Àh“Òס k¼”áM+Î?1bþ¨WÊ„X޾(“ø‚Ë-¾ÊUÛ?µ õ€Wä<ƒ|°©çÅ]lŸÏKác«J:Ø€ˆ’ÁCµÎ''–™èiO»ƒd§íS`«2»7¶q•(twc”,ÿšÉ•bG*©8z?j3Ln’H‘þ°?ÈÓÓ å #~ÑÙ LR2vǞطrGµ]Ñ[Þè°”1úþ Ë Ę֚́¦$yšxô£‹({sÜp ZŸ”²è„4š2 ‘î`J Ó¬Z Z?3¬™æy=ìÏk•+#PSÆ$Õ!tkUìMˆŸÛMªÀJNÜØKH­Š¶»Ó>Jb›2œŽ¶¯sÚ÷˜¬›[¢·<î½{J~½éÖóc&øÉú’§‹%­N¬|&Êà ÒPEÕ·€fîÓën‘ðR±¹Ž{cí]³¸VŽó·TðU9¿$º¨Ñ¡ø#$iꤷ6P 2Y{DU‰¿ö²¦ˆÃÓ(LS8tò‰â”÷¾÷vÞ#dyGµa#–rEzK;‡xïƒ(ŸWsT-ÁT¿÷' åohµü0óHŽS[ZGÈ!]ÀâûN‰m€'y÷€PJk3¸¥,%¶>ˆãê†d¤°?Hˆ?ic‘m–6AZ©RN€¨£½ÛãˆÃþ7+%ŠùÌ }`°¬}™DzĈÂÍDe콚I,à•I{‰ yËê•Ô‘½|$a¦f¹$!-¨k¹È.‘Ñ™ ]/ÁbÅVÿ z8‹æ°¨‘ô-3ž±È„„*P4â5ÓÀO«€)Y¢¬š—,ÙX#ÆE2…’–IVY²ÂEjûÌqú”ÙÌB/g.ÑAõLH”@r5SÊÒÙ¥œˆ3&jH1¦´äTÛToUþÕÝ(›iˇ-Š>ÉÖLÈߺ?#sX :x`_ìXID)uϹ K M*€ÀçÕãÉJnÔ¡6¡ç`Àe…‹Ñá¸Ãr”á))RT¼¥6òÖŸü³bhŠ/QëRæ3ZA‹^ÍG5)g#|ThÈœP[N¤ ®mxƒƒ ô*šzãèî["z\ðö=) ´,Eˆð¦“í`°!éU—ª[l‘X[å ³ »¤pR™N)äÙ[¦; NZׇÄ9™Im7IIÁ’d(êI~SWË6›–!ž=UÝbÌëEÒ•'‘:sêX­?Ç"˜GÖ‚Ñôæ³­‹úëIÑÔ'SÄ¥6xwŽ Ž…ÖL“@Ù níí)ÀE N©d²)ÂlG{>ÐþO°ÃéfO,Ñé­°ü…BÖdSÔÈ/hÍ8Wš¬e¥¬+á§ùçVTÕQÎÓ<²\­EO's#Â’Ÿfcö+j^DJJùC!˜¸çˆ§T±öUøX¤±ò)„™²‡£7Ï8”ÞÐBK¡ð6äFˆy&Ÿ-d°õ‘㬀>Y‰Ú´º‘ êWq‘d.>¸ˆ¢©Pr7ºúÈï m‡4„êçÁ‡|Ô==Õq2Ma »r0 $g¤î`ŒÛ/oö ¹E]¸±úµÎ±GÙ%¨6ÜÉ7O{‘bq;7K|6)Kø;˺;bb’»ložQíuKUpÈ­C½T}‡V Ÿ$J™Ëz9r<ùħGgaæyzÀ1m³ƒòU¥;{$­ú“QŽäÚ·^VÛ[OÔ'‹¤ŠïÏy:“Ri.4¦4Š=<Ü„ ¯¸M’‡()ó‘ëæMÔ˜~²J ö÷w {WpæÇ‘†ý‘íúÏ<Ïò+K´Þ¥¯©$“¬CÞÊ:7.n†3;C¡¼u¬0‚e °¬ƒ,¸ŠíH?õÍ\í˜üØ„´@ÝÖ «ÄµcA§«HÈú‚ì<Õ­ð`€Ü‰ÑŸ“!PifÁ`;ŒÏƒvîY”±xGT›'(µÉc“eîJLìT8{ÞÌÕÕÅòp3”}Óê+ô20¦9úI'ŒÌ6®Ãsz׎õÑîOFgøû±–Ó Å--¿ŒKÞóý2þ«¼uÆY’7r.ÄM<›’øë‚I /l"R±%LGf¶øäo®ôŽî÷¯{o>‹Êµkí¼W½4.ˆÎ  Q[r¤‚ûV¿'be + zQ‡²PÌz@ z5 òµöX,NóüJk\)b˜+DÂDo7lJ7eœª¢8#ÒíŽJˆPÊŠ>áË$«Œ¢C²¢Nû",³I\YIHN€Ü£vcçD—ŠÔ”ðm*@÷¢à*B4-£1#Þ¾lÜñͦÆ,‹´~¯T>ŠN*,J¤xÑÊ|ÍÉÄ¢(i¨EiÒÊÞwP¬ãfì©€UŒ`fjnyGõ¥vÞìlÐàëÌæDnÄ…êFŽìH{ˆP*0sÆž"MRbdÌ&V®-¨ ‹4Ǧr+!þWÍvñ̎ޠˣîPPˆãf>±¢P‡ÍØÿâÔ*0$hJ µ„”ÀojÛG˜+zMÊÆi„ÉÐ$Ǩ´©-,î¢ ÑÄÎn ej¶­ F„LJ¦ Œ?Dr§PÔf1&3hî×Ò~ÇZØíF™®‘ ®šÔÜáC4ÑÈ®ò-È¢ÐêËÉ#–@ UNL#FfWgZá‚,rüPméòlDrRIòÛÏŠ£¤„–tNHïD¼ªÂèîˆ7É>ëäq‰UR£%Ø¢z FÌÛ(Jß,‹gö«,± ¢A©$üĦ,nJß ðÕ˜ç0Ïñº‚H{èÃnìª2Ì¡ö²’IgŒÕ†_ä®ì¤rùh^–hJÊĬȸ]‹å(Oó7'£) F üöDz>ï…F_bPÿ+Ë’±3xxñ¥"I0*΋/Í$Ó1é^é߃¢Rê*ë,ÊnÌ.Ç` P3OdŽ÷<8Wr>òÈJÈ㼘€ ·§dÀÒXOír)IxtKò׆ž:'Vu²׌dÅ$t[³ª!tÐG£%˜CIA¦&îÎR}¬»:Q<}´Q¨O.¢)å–S&u¬žòb8@k´ÆíæZó¤r)g#ëöj/P×e²Pz3PœTæÍ.μ~¢ö¦dù+¨|Jqé4Žò×ë@ëo4.¿o$Ò\Ÿ4PÕiAt6ÁR @®JoÃ¸‡BŽœÓª~pÐg-¦oÁ§MŒèW83!GÐ" 3%ò‚c¥®`1²2ffvcz-¢$óÇP*j«155ïË1ì –t[@¤g%<ÈÇ’"9b°¡":å&eFÒ§²LÄ*"Úum³âF¸ ·´ÝRf#Œ É‚SQ 0®Gì’„Åd¤Df8äbºEfÈìo"êD!‹ÍFEJnØf1tïÄžÉÃ)r|“rîp2·)®è©SVUˆ|u¯-ê58ÂllÔÜ-¢>:“PªôæçþZî[1îZ5jÉ”ô K:ܧ"1ÚéNñ(„µ ñ.ºxUèÕqô°ã2ÑL’)êÈRL@3”Ñ éòÔ:F Ób­ Äw=s»T@ GTelpàÙ>Ï!d®>Œcí@Ob%$el›­…Y¢k1¨>š‹$¤Üù`NG.Yˆêœg†×’äRJò°ãP¤z~¤lÊ/-4Ÿ6¤–G¡eñàOÏ òÓ²,ƶí«O*Ð2‹öžå%gì>ì r kÔdGÌ´–Õ?ïá0-DW•jO² ܵ¢âô®òÈg<›±ƒ[ièdúOmR¿e fj,šŒ»`†¬ATì.‡Î¤*&Õ\ó»A¶£%,“eB¢Q+jÄÔ½´!ÓÆŽí2¿‡DÂfW> ,k<­¸Éº‚Š´´¤0gË$ôr€ßRþfÍj‡g£h« Èò©`œ2Ìqc_ŠÎF} ecÌœ"Q)4t0éãaƨ),Žë¨!£X‡oѰъÉq*ôc‰fµ(85tæf¯ìØ/u0)çÕ/IÞ)`!IüyS[d²dÅÂÀßêœ"¯iQÔ± Ï?v€ A°Ç£—_”#È^Ù¦5fÄYfјANJcï J3/Dú¥ Ÿl'EO#8ÏòÏ‘w²ödl*"(s•Jçg+ŠÄ®»¯Ê‰&}U/E#t8ˆVKplÝgó–æ‹úä¬üÙŽlâULŽ¿sÜO2]GÐÑŠ†ªVå<#ÞË…Nǰ áÁ¯ÒÜ´¸ 53—/PRùWQ#Vô±î)æ”Ä}NÕ¬÷¯ÐɉoPµpLÕxs<õ¼êµ ÕlŠ‘eL ·¦ÔƒV’,.&ã¸÷áø¹”8õpOaó‘n·J¸%AÌG,´ÄpDrïòç‡ Þ1n1-ƒg œ¦oº)fiæÅmñ¿Z柾óöÆeoâ4D°÷¦»Ù3ˆñ~w‹vÓd¹S+1lø¹;©áO’?zlí´®Š.cLpu2£@Œ·|·åmqx@Òn–îoDk%mò{5 ¬¶`é\a%P‡¢Pô-yÍ´¼áùU2FCî„§AzsfTwÜZé8X¬ †Lܶ³8$óÓV¦rvÖ›o«3 K.O{VfÐŽõW%÷?wž~Ñ_ QU9Z×ãk¶öoh}m'ã¥i¨érÃqòôÉå%øªX¤u'7t¾×j›8BRz;Ôcf÷˜=wÊÙ9IcáômD©j£iÒ˜¡ù33¼Jù/gÑeJòOV¨r§çÚÏCqÆ97¹4áéÊ®áþÚ–A÷vZÔZ«4úøå˜Ùè¬àö[©Ëc~º$X‡*Å®'P-ŸÛ%jÒ¼¾±m/@VJåénxXµ­,xH¶%-±"×2% ŠÖÕ|ÝÐJ¯7¿y¢k¡5Öòí]·hê¨gÚ R+J5dîv¶kDw!8`cÅFëQpñiÁ‡'‹vÉ›Ÿ%Y?-@¤Ï­ÌÙAðc–Jf'u›è™x^DG õ8#ò’¥$«5˜£¿ñQ>G<¤“}GWväÚ1&Ìîç툆m³48ã5¬äñVñCÀ»Ž¬™œjRºx˱ՃmˆlÍ@‡×5(O/Æe¹dÙ—¶ðp°äwÇ—‡yžzÀü’nVý–lš¥O}¦lÇQžÚl °ï,PîsÚ+1bð-˹æ1+,K'¹¿e¨Å!VÌ!šÅV§aAã öüjfá»°kÁþ·§g8b%f:ÔFÝ—R䤜B Ä÷·¸ë•M³:[½ Ëýá÷•57æn1%®ÂRöpº…å âèÎox»º¸¢gðØŒØPéòÕ0 A[ôdG(…ÌD—PDG¸.ñWÆ×,²XÍI앑Ȳ4ÊRæmXZ“Ü{3yF À-Šæ$´ Ô‚5µ>9Õhµþ­ ‹Œá_Ê.e:, zXD§CÓJñu/Ì¢h—ÈÎ4ÔâÚ.ÎúyÌ;ÎÙ¦7”É×95Ï[<åŒõ§QR݇C"'#¡öU8u„Õr¦Ã2õÈvÔÈûÆ}K¥b…ÂsÏ,–Wâ+²&AÕ”¡áòÕ©ºêæ%‚fµÛMuÂIa£ò)ܨõª"´ z;M@»RÛ¦‡(w¨¥£õž/º¥\GZÝ^p*$×Ö‘ø’à¦;N,VÅÙä!œÅ‰BŸ ‡u dïÑ0)<ô&ñ7Ù™— áø´`rüà·ù×Ô¡ ÜÙ¦TiŽý!2‘šr<¸Írç…ÓŸœdzo!´¢Om–éª@|Û§ ¼/¨•RWoŒr\<ÛêËo¡öu±A^-¢û£Uuv Æ‘MÏÑ/D‘£~l¯kN«8K“‚N–ðÔ›Xƒ4©ÝDŒÑ¸ûe3x޽äüÿf(¹ù2'Xèï ^Ý¥š‰¾åìCn-fOæyó³_X,/ôñ›ù\œgÖ9Êâën}Ç‚è|Óå ]ÛŸ¸NÿÊѲS´Tcâ è0ÿ…BÀpØ@û…ÂÁQW´\ …¾ãÐA‘Hár zú•%‘èœ* ‡¿&’ˆDqö N$` 4ö~h”*âYIPb2èU * š?(Ri4zœOá0¨3ú“¯Öf0ªäúA2žÚí‰5ªÐ¸\(UšËæñKßóˆôÚEo˜W_õ8Ç“]`—Jl6MH–P£Ô*N0_‡Õ¤0Šž ÿYo˜] ŸWäÕøö–=œÃì™é¦§|»b¤:ÍW:¾Rjt˜d6¿ÀÖtLF¿‡ÔO6ÏÊŒâ¿Ï~Âðô-d‚=z£Çaº\¼GQ•>µY Êÿ“{kÝ—õžg4ó¿y² RXÖ Çć›03~£(j#JË?íB²¯½o[b+*aú¬¬(C˜à«ê›è¿Id8ž‘3 8Jz"¤¾ÏºÒ³6N á  Bê-¨‚"¬¸©cܲŒƒVƒ3 üÚ Šœ(ªkÒL{Ê)2ôõ%OÉø¬¯P¼>¢8‰£p¹°qQþ¤«/[è ÍCPïÈ3k²¡HH‡»È2,£0ƒí$€L.7Ìj_&6OŒØ~°ÓN¢¢,Š9-Eoã8ž³Iv)+<&ŠÊœ¾£h“D¬ÎøÕ«bøLs0¤µëÃ+IH’E7C¾O{Т,H2<œL@DÉ3? "<¤Á‘bX¿/àMLõ†«òpŽ5ÈlðÂQCæ¢+í*¿Z¡¶¢€H||$ÑM᥌Ûý$ ÄôFëcœƒUnT˜…ªs®¿Ýqzå3T2Å{@¸èû9jÕk䜌ګâisÊ$ú»(Z’ɘÀ .«âáT ŒÄÁ”*høåŽ @ãd*QC38 xÙ­Õùû8Ô’¹JLó_.^>II¦v¢Gªši –Aþ¬ ˆ~xšG6UX„0¾‚¸É–üÒ¡êL¢{ßËȤаÀ4ºˆ‘¥ŠmF:zìílü C¯l·U,…¯U[r…UsÞÄJ^C pMÔ•T•^×UÌ 0’%éëA…mtâ¾½LUù8>Ñl‹`»½§•ñx#Ö4hrâÖ Þ9?ÅØ^{4ê4–ä Ý™ýáKÇær¨7°ðŠU‰mu¢Y¡Lu¡*È^Ú„/OH¾lxŠ_htÍØT‘wE&`È1W[î$µ­VÎÚ)lí­Ã°‚zØá$j)ô'ÇÇêó~¬Ô—²’„^žb?!EmÒ&u ZIªpi³°RhË@cH 5[Ö¶ãHÌ(I‹E=ÂpªÖ18=jß •Vò[èN+U»9Õ°‘Í“6*ÇiG?ƒâòQ!S4g­Ï„\N’¶%³FWׇ‰cé 1Ôr±!N«$à±dÌ|^p}Æ€3Æ>Ì:„!¦¡¸7$Ñ‚HíK°ÅKˆOd&û–üåš:§s‘©ÄDV1znfFÃb÷&Çéz=o^B÷*? Bü…Äyx<•Œ¬ˆþŽ#ýc;sÖÄ¢gdŽ]’©†>‰ÁQ;Mn%÷¤K 犄Þ7ºvnÐÞÃn|þV–× ÒsÙ}-íØâøWÐ0Ù¯¹îK•W:€8n6V') åÞ;.1v7Ɖ[&K„C;l…R?VÐáà) _…Â+¹e¼ÙëkžSƒ@â+Ó™€f2¤–ÁiI1‡+-n7¾>a6K ÿ¼& •WÀÞÄÓ8–گLÌmî+Š8ëqÄý’fþûHÊkFéXÍ¥²þ”žÐXÀN *fŽƒý9‘<Í•Ypò@¯És"K„c~‡µšT@›Ê#ë/NT‰§ é; ì…NêBGCf!‘T&œ¬Ý«ÉN2åt»†VzéP\ ‘Dt36Gòû°mñÁ8cìÖJÕ~ ‡­ï3ùæœMDÐ;6zr¿Šú>é¢mj~¤¸sÿ+Õ1'¤á˜ÂZlæªKñWVV{@k'NY Upô‚†¦³í²»LíuwM!öÂ% “².¢£¥ª§«.1óâ\“ÙD‹¡uR–íYëÙj(%#+í€~Xöõ£Âí¯îñ>ƒúÚ%ŠØ%NENêISXשƒÞ ˆ%¨…ÖÁv¤w€h&ê«’S®ç¶zf* óxK1h-Ú˜Õ,^\¶Þj87*£ÉkHnŸ_{‹=ì|¢µ®Á`˜Hu^±† Mí]&“nmD í™ÃA%ìÍf!X_J+ETµ²mA³¬f˜^,Ü…·}Ÿ0º²ØÍ”A°ä¦(7¶Üá“lBUÃròlÂ!·y´=¦WddL§Ôü`ÄÁñ¬*84>êXùÆf;ktX~¶{<íó1 =vy‡P£w Ô²$EÉÜ‚CœIt:`œx.yÜ©çvW„G¦u07, ªÒiÝ$}«Q„ÃùøUˆ|qÛÁ&‘d•BäÊDã¡°*åÁ°‚¸Î yØKaàd¹Ç¯i¹qÆš†:¾˜]§‘ ³Tù陃P¼,ñS'ðÝÚ¹qfq@E8ËZÕIž™ŠU×LI¤¢K{ŒÈQûynF‡8Ò¹¦ò®O2Ól…¡%Xb¤¶³ym"`(FŒzò8ÿHã_Øï±´Ý•®vQÌ. ñÛÌx(áäø¾=3÷~fõÓ¸©Žˆj9õ”›f5sáÖ,»—‰ s¤,E°€x6·Ê.›!Y Ý̅лó¬rpŒ˜ YcÝBf§•À|Ò¥zÀ"ÜoM¢ÑÉfA2⺄­ÃVŽõS4nÒ¯ְ«¦åÎUI—¾ßÊi aË׃j¤P«ÒõÊ’d`oyt|Îë‰C{ï@³ÐYÜðh„ó=ÍÏ©ÁlÝ9Ð#²sP:>SR4/Ò¸Loi6>öæÁþTeÍ-´”x,h¦v[×™Äï#£•9“lÊJde+íŠ#¯á%›Ðju§l)ì™ZG à¨i(|ž}Ëñä´} òdMÞ¥wx¹i8©(½?a£ÛA=Ór¸Ú³ñ¨¨¢?!î7¡@ÀR¦ž š%!¥!³¤+ “   8±%êß2Ëb:õ7i«A•½ƒšŠ²ì© ?{:ñ9Ró¿èì»ñ?ãCÁ2B’2¤¸Ô d!Á‰§¡“µa“Â(¾S–Ž‹I-ÙD6ѮʞZe‡ãx˜Êf™4 +ØŒ©šÆL.=s_3ÚœApÂ1£s*X?ƒ{³A À¡;Å€¤ºy!’¢[–©xˆ1Y¸ ³¬AåXÛˆn "ºC›f¶c6¶ûø8lC™é¦ë^·3,7€Ž,XÝ5l1¡³ªyá’)Û $HZ`½‰ù6Šž°Š=[·©ô @Yü¨áÃŃ؜yš@y• ’ÃT *Qŧ»m¨@ˆ¡BÕW+yK ³ÉCdm³SüÅYó(Ø·¸¯©›ì3ˆ»5c쿈ˆ—€¡;£ 0ˆ£Ù ?\l“A{CqT^iü&é‚ ž¸r£BfC Ý£»°Æƒ>=ƒ"ލ¬J[*#Ht4£¿+²F ³#”$´3’º†³°Ž:«<'Ã!Á ô 9ž¡@îÆ£d¾}½È„/lw90#rê•ê—“‚ÿ¨qË ²ÇüC›Û‡ê2­$>C"Ÿ.‘j©<„‡á;7÷Aj’¼/ ‚e+ÀŽ(? kÂ1}¾P«3ã[á<¨ÁÔ­3/ ±'Œá§9ž«£I4ª1â‡óͺ#¾!ž®”·ªw;A­§”‚*Òh‹‹‚9‚ùŸÄ®Gà9(‚[žœG§ —¼¸œãZÆ„ŒL‰…Éê=£H¡dןxò²ó#Ä(¹Q8™$S ›'ÇAF6 9´+N©©KK2p»iI+ÿJ»€1x'rӋ÷%l#®ržDˆÐ—Ê€~LÙº=XøÀ3ê¾óØ$L(ÁDV*K,Щ«*9ÅL%(k—³ìoÎbϘ}ʬ¬)ôi,aGˆQc&êÇ-"’í¯A„ˆRÔ>êF 8å% ”c;½¨½I~¡Ô1²Û› ¡0ý¸›–Äù@ô((û"<Žk@4«¢ÖÄTÒ)6¤¨£aS­…ª¡ÝÉ\J‰é¶úì½R´¢Œ)¹ùêÍÛ¤)³µŒá£Ã9#¨\ËH\ÂΙ| SLÀË!BwObð¢´o®èÿ±£F’D‚áK\w0zu:®Ú(:U9ºãR¥ÔÃ+Â"/TÄÍ|°A1ÔÊ6ql3»wÈRwÚNà/ko½ÕE§Ä’A~?,L½lºDH™ëœÚé â  Ô0‡ò-Oy…8Ê;ª½æ:ôúÈRŒ ¤½`“Dk†Š#¨ êZœ`—®ä.‚þ®+ œË¤_2\4ŵÅ-R³ÌÌŒÁ„@ó^˜sÆœ• ?©õOØECÛEšÛ”I¡Ç ,ºU3\<ÉÃeÇD£ªr:ÕªbQTšr I‡,zž$I¤Ô”›ÀøîT£Œ †§ºìÁ€éÖ`‡Œ;l:¬ ³¶´ <ìèÐà়\®Ú‚,ãüÌÝvÔ‘£ÝÁ‚*•ë=:…tÃh‘MqÆI&9QäÀ*Ò.&¬¶8Y3Àu8» 8)º8¨¼"9#–)1ÉD};“³â'.‚C9R Bº±8Øp²Z¢XàÔÛ-R2Ù1€œ ;ŽF„så¥Ú>‚çÊÐC(lGq@šÜ9œÙ M!JÊù³§ô‘ËI(l¤Ÿ¨¡A AX|1s BÒC»´S:ÒŸÅv¢Áz ìŠÈø±£Ìp–#8¸À}=™xƒ6€-m§Ç@ý¶ 5œ=5b©Ç±vŒ;£´’ÅžüG•‡©17<Ìv2<` VT’yu‹Ú˜&Ä1Š ˆº€¨šKúToÍG;­£»)Á\ðà¥ûÉ©‹ûšç)ö˜ClXýÑÜ*ÇÑ~!ýf12 ¸d G\¹²ÁÑ3å1\ s: [¬ð¡¢\íj™”©c‰‰H•LžŒÅË”‹ºÍ½›‰•݉…Þˆÿ” EËI$-“ ,Ë LœoÑaî@©~LƧġwqLú RÒI˜¬¬Í¼F}%ÊŠ#½ëÉË×ÁÚ=´5 Ã™žØ ƒNÂR·P–Ub¯>óq5Ù¡Úåû“›!1Tq.[Ô8 Å1Q3sZh|˜CUUÒ¬ÒŠ¨ ‚, Ó•?+§Š)B¥¢˜ëpàZ[`Ѥ*€Ií ßX€ý°ý á3•Órè8…U9Rq¦îÀÈŽVärQÐ~ÑëU14í±ÄoØE¡à ôV3ÚªÍH¸›%²[ÐÒ’bëÀ¶ºÉå&ì»»X†›‚RT’% ´.}ëº9F5=‡Ûw69ɉåZ»1?ܸÞÉ¥ ¤/JDÛ›ð$Q01q½”åÇ$d훣EÝ¥I )ËÀ3üfûJË}áñvÛ€}¸±¯äᩉR! ;¨Ù,º0Ð+£?×<Õ%º\Óñ.ÝŸN2Ü@`«ÑüV5¾¶6ÉŽ£àˆ§ˆÿ£JácíÙMÕ¤¡ŒA’¶GÒí¨lJ1>QÌÝ®‰V‘­q}#y#Í~TèÎ^^8Ü»'¾éãµmRTëý`h®Î•ë}Ù‚¦Xe2¤Zw>4çÞ =Y37]ßˤ9Ñþ‡æ,¸Žõ¾3iU$ PêçE¡&8jm…ÃRkÃå#+9û£Šˆ…½=O>mÉÛ–ÙMŒ^E‰]ÕOÑŠùMˆ¿èˆñ¸P“D‰ªi$$©x:ó¯)*ì•°ÉbÆ3Ѹ%Ηˤçô<ªLvèÜŸ­¾[?1…cqô¿+QgtÔÎc*ØÇF+Òôemºæ§¬ž©€õ–2Î,Í€ÙD\ç>ù =yo„‰yj®“¼G[¬ ±+˜–n«ž•퓚§O¾‰Ä–žìì§–¥šÖ°´†PKÎ?ÝòhE‘î±](&/B+,W¢Ÿ‰Påtk)õögHˆå(û+Ï-FeOm¢`<Щöo*a^å Àî…’$¨~ 櫾ýpªK`›¡FC9„aý,¶ü8˜¢¦'HÐÆêÃövZg¡œ%!ãç̺avuGAÃÜš±Ü»N^Îk‚$ÀH?'Ò^‹…S2Bëpös„_LÒ볕f‰Ãï4«ld$¶ý‰qêk©ž¸÷5NmáßÌŸdwœ>÷Þ ‡ÖT·NkÙºÈàã79½éK6ðŒš9Û¶jòµ/·FÉ6î¦K#ë€?9üŽŒ ÌKqF ˼Ñ(¿Ý#™^d!M$Fç0NÛ¼!vÍÃÂy·¥l>ônf°‘ÙŒÕÄ«àì_ðu¤Eõ¬Q8ì©N ê±iÁ]u *†“´tÕ MÈ}í†ÇQ@Fò:= ¹4ºfHØQØÃÐúÛ»ß<%¾- °ž¿Ù ·­½HL¨¯ó·󄞘ð¾o«¨g7ežêk'yT™òáô­¬µÂ.pÑõÈúd®Â£}Qê jävK¯Ì–] ˜úàõÝJç¥öq=‡FÜâè{iXýâÇD9ÙêoÛôÒí·r^»ãÈÍI4—"p6)‰¡cv@yÀ`Ót´—¿“¿ñ6ž#ï‰LÎýr+Iø¨dÛcÝX¯¬´Þu ŽÔ¼@±@ÍGÆ2€‰ð2Å÷Iî%(ÏãýÀÐ…o'3»ñ1#ìo2GeOËÚÀßz`_²16Ø£J‰Rù7Èïöþ›>ioÌãN|'|rEJYôÓ_1_\@öò)+\ð4yŠÎHÇIíÞÁ Ù^¶¦«¶Î\Œ¡úx|cTÃsbß®µÙÓŸŵ†"ƒ‚Âð€? @ˆ#æ „AŸ `þˆ¢P'à,ŒD€QHÀ þ}H`€ˆÓîM¢ÀTµû/†L@2÷ìR5+•Ìeˆ´iÿ?˜ÏèOø¥+¡Q¨t)Ì6Q•Í"”™;MÏÈ´~–ÿŽÇãTXdvÈG_»4 …aˆÄ¨SHÔ| w¥GçPêånz†P£S¥Î_+ºÜ@@ldÒW^¿Ä+Kú…(˜Ö«õ‹í ?4ÇE€ú:E-O‡MâÒÔÇÖg¢üDKY —Ê.àZŒÂËÞ¿s:{æEý»Ã?y2½Þ²íwnâšÎl‡ äq°Q-+þ?(ªUj±Jž˜ÌC$ϸìÒQ4¸?»ºÇë îöÀ\ýäó>âÏÒVŠ!KÖŠ6¨Ðî° C¸‹£+’€†9ÌS*¡7hS(‰&(úV׬é‹Êµé£× €MÚÅ (hüWÀ/3쎩J(÷¥ïŠ:¯¡@d|Ö=iÖ!J_"B:…4`:>›CÂ-1èƒÂ´£:ݤ©3øü©r¤¦†IóÒ² Tû«)â|ŸÈqdÞ¡©NëÅ5«ïd"r!ˆÓ Ÿ¾(üJ—ÏtÚIè4¢ÈRGÊÓ‚L•¥ìº}£ëiøÝ¥rÑùI¡ˆ£¾‡N±‰þ¬QO¤ÊÚ"É¢c«ð˜ð¹/ »¾ÕÛˆ¼ˆ°îÔúi4ÑõD¤œ:õ»Y*³þÂ7À ^Ýžö̯µð9¯`^© OPýNkìç>¥í{“"Q}0¨'Ó6®É ýii¡”9ú•+S´ôÎðÏÀ×FŸ‘}à/²„`Pgþd¥(2QSI6ZbÝ¥,ìªÓ°Ž ŸØ'ä µŸ ½ŽÑBPõ½yJâÒŠgj¼ þ+‡Ïw˜õ¿UN­R£r‡>Ã.Ô¢YfJ>Ó.{œÁSÜËƪ[Ö×Î0U¨~Í8uâÉh÷5–ÉÙu®}D'íÛŸ1jèlùŠ…o2«,ŸË%E¹àK쎈=p.&/\šÝçè”OhÕN Ó[chv8[Ý›5ïÐ«Ž»ßÍdEG"OšñLªU)½AÈÚ”No¥õêjR)X'šBÝÀ©^Y^Ö:^ùÙ"µü.Ÿ¤iYéç¤kìL“GÀcÖ•¡X|fà'¥u&†ÇÄŽ# £¥ÙÞ€ÖÔg·Ü~ÿÜ{zªëû·K¼ljhîÂ|OYèfãù%¢ èöY¯±ý¼—`T!5ŒæuŽD:#ÑÒ&,Óº³O¢D ÐfÃp·{#q΀9]©/c"%ù,ÂÛ@A ý—(È„V³Od¬Ö ˜®‰‹óaòq¿Ä,΢£°leirÇò_œ%‘#îY4XjÃLQÁw]+ÉžÛéĦ-S© t"# 2=ÀõV$±Z…³†7DÂhõO¡g©â/ [,–È÷c½»€WpDQÝ`Í@4G˜A#lvEF*S¢Æ+elèIô¬P‘ûÌ;— îÑh@ƒeÙwe‰5 (úOcŒ˜鞃"C‰Zû– z ÖÆ® úM’Ó¥Dã@R¥AòUKv” £4­–óœp4ÍÚc8ÌQö¢Î]~M™g {WEì1dG3‹ÉÙ˜Õ}„¨(ŒòëxóÈ|ìe‘ör5â“U„ág«kµïĦ¾c%4}+ù¡.Öªœáá¯u=ªRf' 2ʼnMù{f²“C85Œ<øÆ™Âxd;5ò&³nñ}L«T"'C°]çÌ­mS…ÖÚð n*r¿¡hº ³ ,™d mÃþÑQôJ3j?VI”³*Ó@!ÉqÆŽ/¢‹qhëk§Ð\û½HÍ i+AØœè™ê;Xi0ž¢Æ2M Á° ¢Hlk4MwB`Üm­V#ì²uœ“â½ÉÁ}‰RsFù­fa ¬9zÉ”Œcòá©2úÒ0öW‚zkÄ™Œ4˜­k_ ]ÇhŸ¦y‹hiûˆOš DhËb›iæMx¦^ÌV?ãù£bRÄó1Sù50jƬ; —_À1¿Î½5™Y-PQI¦Ç¾šÅLˆ´ý™mùÚbB‚g¥+«ìžG ÅFÞqÀâ‚È«ÞKÉ#›s2œš:v¾[Œ7ˆùÜå·ÙÏã· æš$Ö—#lo*z2Ì)q±UhWù&Û‚?!°´–Œàå= 'ĵÌ$šghê½#µLµ5räB†ß£{×òs[4÷t n”£„šŸ/뇘fXäF† »B»Ž÷Nr-R™ÔÄ7¾)š†_S:Š?òvÙàèúÙ‚MØ95±‘¦Á«/ ü<**üª.ò™Ò{Ý«ÂY¯^íÁ¯EžñY†«*dÇd Ü`º­‚-Ûf£j.OØ|Ýr±sOpóñÄG\ðQ¿áQaj×ÔÒWø‰|õŽ«°6Â]yB$yrª¾³Q,IÚÜ—°ÂÔZôìF„Z;rÑiÝÏ8r›“ýAX U!L%‘Õf®Ây°l|`}0òÎÒ]e‚ëHS3‘d ëmùá3SÂdÃm›õùFõ|ÊóññVfî…;ÄA!oj—¥M@ÕîyøT ;@bí^ º0 Ä·Ú±­œAP >gZ aŒ&µ)½w›®¨@Hq<Ú··.E¤C¹€4u»4%ѹ¯²Ï…"S)×L 5ºûÈÅxM{`…Ÿ=ÓíPÞ~ ïh¸ñL\zmöøbvã„«FWçÜ©ôºÚîtl%cjþÙZ7?ã*çÑbië*µãfÆÐ®˜¼‹„ŠO”›îôå…y—7Ê&tEë´öí^e ©â}†›ŽÜ½BeŒöwŽÚÓÎÄoĚʅmÌ™ëäÎp@¯ h¸· RºwH bDi‚„¤%0.ìb²‚–+DæYªÔÜf`jëò³¢ªÎkðo)þÎñ!öÝìø¸Œè³b$_É,LðÉ£è_Ëöç©Rÿ hš°2UEšÁ ‹N¬…ªhlììQn–fôŒè&‰òæbBI¬RL¦*‹…¤/£ÖIƒFMi‚a"hDë+m"ª·¢‹‡†äPþà Vf03ˆŠ®Áø–ìz˜"¿¢L•o!ÐàF*¢*вŽ-ZËV@§î«œÖú÷¨~™pä\©ž¿$Ö•¤^9+Б®HïBP‘} ÛL.І§NÄ€&L­­¸†¯-Ô8Ã_ãdBxåmLQiœÊÔǨVõ©nŸ,I¸_c:)p(QŒÆ*è1$ƒlè2¢(ë-Be@ Do²ôiB·.:#ÎUB Ë´âϺíì ÿƒ’çPj'øÜiZ¼Œ@Q·«â-Ž< P¨rPέ«ÖV”¢Ç¢ÔK¸˜ëp’¤áÍl¤Ä•ÑÔgˆ¥ˆÀ+<‰,°æ…öëhÊÎo$®gJÚǤQi×Ñï–ʯþõŽ%í..ò7 ® 2Úˆ ¢†ÿ‰ Œ ãüg ú`KVôg8D+G|HPÆËà [fpè‘ø@°˜Î£Øµ¯4qÎêåÚ1Œ¤ã ›ð‚±ãf¥íÐüК…"à®Æ“Î6’€omô±ÊˆÉ+&÷‘vëƒw Èò*¬°À"PêkP±ÆýåTÿ†R_kÉD+äοʉŒÉ%ò¬SÅ]0` Œ¨½#FOd›(†ärþ$%<¤‚ —ƒV$-Zbèâf ¶$"”‚“,ÆD\?H +FáÆ’‘ œ¾¦Ç&4æãp\2²)ñD²­n‰ŽN£R°ùL&e–ͪä%èV_Ï®)dÒË n2³4Ú¯q¡þ´áú$op˜¯ÆÚÉ.g ŽÕ@&ò' £ŒÛQ$÷l“,S,‰ØŽÇtÃŽ¹$üâiHÖÄÒÉ-ºv¿$/—5‚e?'ŒU†Lf ´–ìõ3´70³^$$ ëçÓ(J_j‚§–i&$;±ÒÙädЊöNp‹@R*PebÖÝ` .Y&¢C@}†$•ªZÖÒÒlfXðôB#Gç -æ#$ËK ÇTãCÈÿŒ±%¤?„÷2dï9šˆÃ’º&„ ¶'ÊŽÄ›1弆‚×”±-(4±ÄÒuãøL²vE-¢‰“&½.«StR”¶¨fÜ”‰e7aõ)ÖœŠŠÿ†Â2¯èX)¤1‹$Æ"b5ŒO1È™;#Ç)i4±¬ Ç!LÔ\PÂnh·l÷lÒ+éú–Q©%‹–.ëýêO%Œöi%å LÜÞÁöA#^~iZ% ÀIЮÕå$ “€ÃFŽÁ*¼‘rœÔŽ"Ìâo¬ÐN¸)TÔ˰B´5†¸‡ñ* âŸ'y1Bb$bê%̵R^Ç«ý)£úÍÔÊ!WNLâ¡9Lû\SªÐ)üðGt-%CÕcÔz¾´dˆdùFèR4àÛµ‰G‚K†„½,¯%Õ„ôe¼ñ•1T%á$b“Œ-pGD2Âí¦†v:cY ‹ïZòj4!TÜëá³ 8Ô%=4.µÅ­äÊô'0 ‹/1sÖõoF¼ò^É>$f¥¶Jš`©‘4©m®u-aëü™cYCId÷Æe5Ÿi-ª\6EWî-ZÒfÎÁD,nÔ"Àã‹Êh¤ –è}FiñiUv¥´FùB(wI.vA.*ªÓôK-ïsW85ã`$&§c^Sv‘ëZñ ±ON,©†…X‚ïE—Î(Ó®a'ØoÉ-.ü>6ùIK‚4e‘hÒtqvê`Wðó<.Zö,÷Hy ”äITqjNÄQCX>6æÛ0²ÍÑR‹Š[lviq); äÔF8É,QD÷/¡ôåm—l³&åeöl*˜Üs"v2ʼnÄÔiÀzSÆÁ“ÑA…ý7H‘C~Ñ—q¶T'‘A(B„¢¾»ŠloolX%Âþ5ÔgM|mÒ#ñQ5CKp[Æ1r¶[Ì;W„çtó!s*ÍÍl»K‡i {&éžË°–쫦Nì‘,+~8ËvòÃXbF’„ -`¢ópÆŒKm:æ$´Ó¡RHFóz´ªVÔXàòZ³žWj"U¼É·Ry¶êå‹%u UnÓ¸¤$Îû 'L£v5ñRMoï#V•8—²‡åÔo7ÖdÒ¸œÏù2¬Õ¹.pP Š«\+Ò\3ždYˆ^ê« ×^Üi×A‘/y!wEU(2|ý)S”·zõMdÇ&±QÚ$È@ô·ç4êOd2 Ǫ=p£V×<ÊJ½*Zå0Ç‘5ʾ‡¸]=ÃÌü«v¬JÚ·l°ô´h±ÕIFËî¼Z²La)NXÞµ@è¹Yx4“‡ws¨>ðeøè1ŽiYŠ£ƒäÙr&U'çÄ  EƒxâòÉŠô°§1Õ’‹K’°[8ô òÿ”¨ #}Ìá*Ú¿Ð"xÃY¸²’Eذì±ûB‹g'Ò¨4(ºÈ“2:´†°Noí–‡‘ ïn&é*ë˜×ZcD™v{¬l!™âGÊsqØýtØ®÷<ÜNÅ“å7bbe‘ѨŠÅ¤¸¢œ¦S Hâó1uK§Óy³ã+Ô–¼­xÿ%~ÀÕ 4ÓªòëeÛŒERˆãgQ7fç]*´üÔK o+É)áú£Ú0­«d*¬‘™’8Ñ4i&1P“„Œ¦Œé X"òìUG‚e­wì²K¸¾æ’M©™ë•ªËµ@ñëê"„šŠC`zÓš VøÞ2~Ð2¶xNœ:žÑ­ª+Lò×÷X9*y úH¶9/QùWÓ83®í§ØS{=’€)â”°™n‡ùž]r0¾p•i5ø!­`3@j{A^oâZ=z[‹è„èÆ…$š™| ¯´´hV„µ×D)†hç$k –˜Îv*ß³9!—&ÈÒÞmDçY£w§¥kgÇŽ ¥cÔ’¾¦0ÃÎ99âŽ"•m‚Nõ´jòÿˆÞöWU±»ç€•ñ±be CU…ú1›{ @‚yœBœ"°ÿšuqŸB`™y ÉSŽ.}5µ옺)2ì$ù1·‡±—<ú7Ëc:yÄÕùfáåί;oR”µð‹5°M4é Ù±°ôEèRÁö»I‚)U®»ê4ku•¶¨¬$çk¹¸,š½‰ÍšÀ ?BÏ™aòíGÒl-mÆ 1S¥%›g,l…·ûâÉ–÷ý˜xèíE1BÏK Ä_3›µÀ-nS›ÆYh{¿ÐÝ8¾ê*Øš»£;VÊ,ÍÝ À󿼤Xs™¸âyÞˆR«çÿÒiž‚[PËÜ÷#‡‰$<,xÔJ'”­U$ˆWCËPŽ&®8(“:õÓ5ñÕüi±ú„3Óª%óŒ=~4ÒΘYrŒ@H™°ÊÕê|çA4»ZÐB°ñÃÂáÚé™¶ÜâVÞUÃúï]‚çn³½:”‰P«×Ë0 B1~"Z%qRô£^Ÿ< nj÷-ÈÅ7>ÂïÔÞn®¢û:æ’P²Ùš¥m²ýhV³MA¬ýª2Y§é°#ãYt€ùÙçŠæiù€uìÔK†cqQbpìö<Çç§s¨ôªUí×ðÓ,ba‚4I©óaÒ'sÜüî™såµ¢¥(„àB•·Œ<-ÇãÏÎQ"çc@ÙküÚlBùFŒÅ2¢÷Ý\2Ý›͆°–â?»Ò®lÑ–¤sG%tÇCʹܹY¾ò³e®$çÈÛȳ$LÒ_@Ÿ†p¨í>! "Ä^Gõ³©°nv*¶IÞ³Þçbºîùíy„;¦®±ØPÃ"-é•8íséÙ˜-n]øÖEƒY¸“¸zÌVÌ VÛŸÄXòÉ, øþƒ>aHP‡?b¸(‹AŸÏÈÐ9F!Àô ÿ~ÆŸ $zÄŸqè 10ÍÞÓLîC&“Hd1@4pô£J¨R‰4’C3™A#ÓÙóöI¢Q$2J\ …$šÄ¨‘é:n}YåµXµ¯¾ëé… ‰$¯A©³8%²vF$–XõMûY¿Á¥SðD”cdV»fÂUD{÷è’Þ\¢=’ÁE¡œà±|§æâÓ7ÇÏš–Ñ&·üΉŸ¡ÉR0–¤)C¢‚7+iúÙ6o{Ì›¯‰#¨yÂj#øŽ=.£Ö˜AkÒBÉ$hÊ­8òU6ì*ÿ"zH°¢Ëª븮Ќ9m–½*Lê>gÄ\Ž&q™þõ¦p3à+¬;“³I à€’KÖâèÂÊô¶ R†Ch3L…(Ò0Ç Ï ™¹òL´É¯[Öì>¬ºÙ:½ˆ܆HìæìA4#»!¯lê“%OJ[6JSlX‹%I„L‹$Ó24–ÌôD*GèQ''³@«€s<œ¾UlÃlÛ*ÈãïCµ {HÛUŠè‚& bJ¡RÚ ØrJI5ÊiDzˆ3Z… &im0ÔÏ2-c*‹fì3ñT§k€0­jJìÃ5!K+rQ5¢L¤£u›4’& jQV«ˆ¤’Œ%L#ß;ÂÕB4Û6Œ‚8·¹Hµ<×à$€Ê°v]º4,ÂQ…6×ÚÉ(Nr>ƒ$Ò"5Sq=HÅ Lkåi3–Í:—´hÄZZÉ` HÍDòŠ;绨ŒGˆ¦G =µÅY€<àÒ× Ñͪa˜@”K "ù¢Ú»(—Jw$Æ+¶:÷ÜÈ58ß`H©oÔHņ­ëPdHtŽ‚:ÈÖ¢–ä'äú&íÀŽRÛÔž‡pÏø4€¯N§Í‡öf~Îúß\ÜXË…^"îE„kN‚i”¢`‰dvü‡2I&9kI´ÉùDí…Âçq¬®ÚDõ²lIŸ"Ús]i÷Âr2f‰Rò"É‚øÚ6‰6Éfôä:„ÝiG ä¢ôNÉTê½æ‰|‹Ö;½ŸŒ®ó¤ÎÚô±?"‡:üAHLå<±²q™3jOàü&´•Q˜# ”â9Çè¨ä¦’VI%¨Ò'  L #Œu#åœ0GþÕS»~*¹8-õÀ¤hL}ö!reX±7mnéiŸSBd‰S´GD1W¼ ¢Ã>RäEé§îäaÌxèô‘ƪh\Šd"½SÅæØÔ‘ÙK$Ýu€šÉ‰Cnkär"žR΋Àzh ¹´Ï F?°L~›‘o1éܺ‚ £"úØô_Œbô=Lñùli ¦=V¢âä ‹oÙv‡ é0$r7.mÁ¤>¦ÁT”'ªÖœÁ¥”fŠ)K7^CœÇC‘„Ž$Î :ßdÌ q@÷œßÈ⤙n(¹Ô®zæªR lŠ3*°bà&ÄÝìÊI‹5;#% ÊHZ¡Jîù˜À—ÖU£È6r*mMò ÍäÍ!Å R;Ħå×â$MŠôjE#y¡gK±~£Vrçá,±ýÉè«@ŒÊìc¨r?™§|½a’%¤ª«uØÙü3 &h"Dûî,ðXÂW¾åÔŒ FI€Eø Jæ2J^çíã›RüöÈ$%X!²5ŠdJ0ôl‡Rµ!T( #UG¾°’jÕVÜ ]F¤™»4 ¤BœŒ»ž5ö©SЦÏ@$z; ^*ÄO'`Í\¢ïþ›ª'JšÅ4‰ÕeþÁòI“ávïøŒ¯øe ¬ôE£ôd²ôI »-k–ÕI¢fÊÆ¹|pÄÁ»9UvDÈ¢b£Ekš( 3³±7Õg~vÈ4¢ðérÊõYˆaÔ?%M²êÃRª56Ênd€ l©ÉHbÑlÖýpn˜òÓÄpñ1Ï" ™ª¹wzG0Ú(¼Ì¡ÇkPt‡Ó£IwkÚ;¦³1<:ÃôžäPŠ?Ë-?ƒ)²áŠÍ‹:°*é^?Ʊò®€ ?,¯À“•üÿm9vºÎî?Ù >ÛÊ'yOßúE›=,·d:¹Ü-~RºÜ/jƒÙ»€jœo½‘‰D¼¦E³V#YòÌÐ F)úw%üõÆgáB<ÑÅiÜ–É#x>§¾ašû†ýQ«‰ÔÔ&¹¤ª±gŸ»3݉W²Ø–ˆA$2©Žâëpç¥?§ÅŸ –;õ±@Hµ³?!×ù´,5æÓVR•dáQ‰D*ZÇrð3dq2–W輨l:˜~(»Ñeö¢-I¶1Ë8à³a“,K{Lx Ž*h#‰ ÇúÍÀÇñÔ#nµš™T”i wÆÀý\´lr­àdg¾Ÿk3ôߣד!›;yõa3VªbÏõ@u„ðE̾¤Ö<®¥žs´wŒ±7·¡»žºÍV @W|·é?HÐÜÿi#§¨qÃeβ˜ŸHÞš~µjªg“£ÚŒçÍõ’âì7‚Y‚„óO_*éEùP'u Ý1ê"Úc»;Ëw•Sj:VÊà ×g\Kp§=Lì7–¢l¾è‡õF‡™(?JéaFqïÛ¦½cKMž‚+ES¡Y%–RõišJ-›^ÚW—”NÂÁéN"ìv€¡Å ¨4Ķ­–PØÙEüØWĸxjD ži1"gøÝt *@•½T*C…^ E˜®†1°e§¯!'Ùås€YdþÚM«ÀõLõ±M¨Æ!Ìlœ“TùVáŸRâo5AJ⤪8‰-úª±Òi­új«óz ²ãœ{©¨ Ä‘©ž@€²bA( >ˆ«¨È!Ó°9+ó!!ÙÜAŽœ›ì:®€}hì5€ ’"º¨½q3²Ð72-«9мÐ~Ü"2±i¢€˜A¸ïûì€#x.úÐ/Úc© ”»ðˆô, Cƒ$õ6{S¤›n ;m´ ¹°b+’¢?âb½È¶ÑÈŒ›œKà«úb©Y¨Â&¡KN8[Ù¦:7y‡¹H©™Ã³Ã»ˆ²¢NÀ’ó€ ô§P•&ë• )“a‘Òˆ4! +“ª»ŽùÄ´Xý)© ;b‡ÒÁq‘±€ƒ4Y¨­ÓϤéÃ;‰§6 é…4t[X³aI9ôšÀ!“"•ð‰B†¡ßZÂ08ÀÒ6lŸëó®´ZÆ`Ž`ÉcÖÀ­éXˆjæ.àç @”;”âÖ +1“dQ“T6-c…;Ñ%$zk¢|Å8Ь[§ZGú “‹¼‹`ý9Pê3‰Ò,ø~ (•(|FžkRG«h» R®¾J€š¬e˜èÉ(P?²(î’“´Ã'°º¹°€LŒ¥\–¢R¬äc%Œ´`Ö¸ˆÂG|MG$/‰#L@*©Œ”¦Ë73",%º’¨œ2мó7©§û)Ó-º=B ½A3´ ùÂF|²8SÚG¡ZG°ì#BìS§ù°5ÚŸ“5-û*@{i»¢?lC??A3,’äy°j”ÆKI\ Ë¥´8»qv9tµ*C‘?úÈ1Rbû¸ªƒÂ.šÕ¥)ÉÆ ÀÞ49ªÒÕœÓ7jSÇ•$­¶ ÈŽZúÀý,‰² lNž©oÉjX3A!Ô!„ 'ù¦Gaþé¬2ø„;b귈ĉtBK'[+’û¼LSí/ UL¤Yú@Lµ6y˧ø™‹) , ˆdi óË9¢¤šŒ®›SËKXÌq¥2¬•EƒŠ¢ˆ ‘ꔄ.€ˆ&êF"©s‚óÊ0›®‘Ä’¹èŸ¢Ö«äÐÁ*äJ!2½:Ô.BK˜|¼`~§J¯ã˜EÚ­„9ˆÓ–H3‘BŒeœ»­¥s«!D²¡Â7ªªÑùv )£ÃÙДzçÓŠL©¼ù†Püh­¢#AÂY…iý `ñˆÐ–?#•,R®‡É²A,ò<¢w’Ø¥ZD&=$¸ŒHKD̨™0¡/P™–Q”»L@˜ °¹ˆ¡›¡ ù3kSC…J‘i‘øú*¸‚8˜µ‹õMK…7Ñ+¶Ë íºé&‹âȼMCäl£ÐÉ9PШ ¨MÓçÀY3 ØÜ\P¤)·qÆ)ü~¢Âæ ÓD1Ü4Œ©ËʳŒ$1*ŒÛ·ÀúÇÑ€§(8ÉA»»‡ØÊ ‘¨´zÆ1ã$Èãù£‚ABÔ¶9j$ël´›½ÑÅiÐÀ°¯€‹£¦—ù!Á\$J¡R´è€!8Û4œ%´o>1Ê$¹QRÐ*LëŸS¨ŠBß*„2¹$Xw¹ß2B߸À·Ö›h°òsÓQš²nª¬L§XÌôÜÆD¤9Sç µ;@)ÙŽ»j© znœÓé-‰ræ öÃ]u¯šÃø¥x—û§£W¤êÛËãˆ9H6MBPy‡üÓEgÑı‡õ{›!63`J b©m½DF’°äj¹|4»âPšŠ3‚°Ä¥HdãTláDð§}oÊ¥•ªÔ±AºF: ô  MnRŒ×„œœ½ûáHõÈÎdyÁ‹ä*‘Ž •0‹aÃF3¬ŠœwVÜ…ÉœÉZaj.“ר [=e®b¨O«¹³̽¶S†Îƒå*•˜HZTëãE$&)ÂR½¢6¥UË ÂI¼­;ÜŒ9¡oÙ%ƒ–ÔDO9%G=Þ™9$NÆ:ÁÇÕ=ÇTk"8‚73GÝdœíÀ°ÂÈì£Ï%üôÀŠ! ý>Àý-[(ôDó3¤Á Ï™¡ËjÎÊv s‚v*‹‡Ýá“„! °Ó¾•ÓÏÕÔÞ³šÈ­Ç9þ<û¥Û\àÚ’Lšƒ&ñ E:YB‹¢ØÈƒ'0XÖ–×*”e4ì^Z3ˆ¿”ÍÜÅd²¢Õ –ÕÔîá™jMtIJ3`àã*%U•ӱޱåoI}•³|a»Ü‹ªÕ+óÄ(*Jˆ¤õÁþßíýœòaÅ ÝëÈÉ)Í6|ÐÝ{¾éÄÃt½©ÜÃ Ò ‰5{ͬ?Çð•·®bÈÒ£ã Piäj ( 4´X”GHC,¢1Ó¤Þ2yÜ„Îê÷Î{Æ‹âÿâAvaÙªZ¨* }°Œ@Ûe™À¾WS«=ÅßÃ"šÆ§ZRÚÎC¹ùÆÎTôͽaP †,4‰ž'+E­RÂ×v}ˆáH«Ìúú8þZ!à "â2ßÕ€´ :ÚË*,®â©œ2‹8ãæPˈÁî'[³,áÏb_/¹Úëßù©p}˜U;šÁ/¡ÜÜì½’+<Ó‰ÕÐEå”4|õšÆ,‰"Ô$Ýé$»ùŠ˜ê/úŸÉ¦R’ž‹-L¦0ÝÜåç ÆÏC…á1ÕJ$‹9Í=œK…\{æ¾1‹ˆZa1£&ÃZÔ6aÌ› PÓ›[òë8óƤ콪ú Ë$›ÍQÅýÁ®!U=\-tÍÀ\Ûâ7R©3‹)>@ :È´³³搜iiIý,Ž!Â"ë›j N²NfÖU7µÔ}ˆ¢{ûwS´ë™Á$«âžª$hYIøk"?Ķ6õØjÎÈã{åÜS½ò—ˆt§Ðï°þ,æÓùˆSŒLÍa qâN¤¤#¹‹+<¡Õ 8T¼çR¬µ*M²ofpž•ï“ÛÐ*W“«ÀP‚=ðÛS=•ØûhëÎÙ®aQdÐD.’õZ€~ }ÃÍÈÛ`›DÍá†{7.6N“*)ûTw-ÞwVÕâž}ò¾§à ‰º<^~iڞŋ{•ÍkûgµŽÌ c Îâý2ÊP¤Ôª™ñ9)°üN›Ì€X+<ëÃÂÐÓöš9ÀÙÕÜ{kg¶»Ïœì¯E?íºÅú Ní”»YOÀÙ«bÿéù©LcÅûú¨\ôœ…æ–_ö€½ %í»2N’~ºk›R^²^;Úìâš`MHS°É1›p‹aHpÙÆZX·€oŠmØ}o'{äÑ%eëTåÛækö¼w³óÅÓ«`C¦»˜Ò ²±ž‹°Úþº:Ÿ\Ê!êŽ_F€âw‹òëÏxó±4£üØ…®Pzßa6"ÝÙg–Ë»£ÑåÞÏ®œ%¢¹ÛŸtçk±\{){3J¤¶V¾Û KIoÒXÓ·qêá³úq´³Ô nÞ’o=ëç¨ÞuÅĦ—±ZNì‡GÄ+Rd>Ûtl¦xI—<÷¨u Á¨ðˆ))ÿïJVLVr>ú ’ÛX÷`äì)åf᪠ÈÌkH}@ònÌ¢“ùð~S&iÉjRoÆès-¶4 A¢åÃ>&Áø:€}Y̯*û… Q \lÁ_fiy<îµô]™‰[ÈÍqî¿n}ÀjYwB‹-hÚ5ôFŒÕ{Ÿ»¦ožùqŸßÅ/Í%”¢ß,^ûáb%‰ûÊrNï1Xʉ‡*z™¬O8ea´°¾îp&{ˆýþþ‚ Ð(D Ã@ød5ù~Å@Qpf„EãÀ(0&ü‚I_Ðð$†C•Kd0˜n%Fâ¯Ù,º2ÅãrY¼Ž=Ñaº@•ŸC_TúPžúÍa²XÜl[{Wh zCî…MÈé€*Ø"Qa›Ègrh$ÊnŒ¾nÓ¸õ®‘Ç¥ó ƒúoy‡Ôe×'þ"m7Šáá²µ–';ÅCcÕ:ŒÞ7™Šß!9ÜîÃ.ÈÁ:zœ¢G!´Él7ÊÌ6£‹ÆUböiŽÆWºƒÌ/ø§i‘Îär‰œ æHí»×ýú ¨ñ¢p‰"ç‘Ïî0ÙÜÁÿ¤–Ë%½‰l¢o%õEd¾z£%俼À z± ¯Ðbnª2„9à‚À¬ê›˜#Ë ´„°hº€6 O¸  ý„!@Xd!úÿˆC8p,úŒE€ (äuù…"ð4–5}¿¥R0¶5LeOèÔzA ˜%ð‰œ†} F¥ 8ìŽQ0˜Ã£ïÀM6G!‘ÇeP5 ñWœÈit9 Îrù°F¤3š]ŠÑ •䆋ŸÜ@Ùœ¢C Ìï8tv‡³H¤q ò †X24K{do†:0ú¹Oè1htÎk‡Hï¹ÏÇ@T:\ŽgR‚HqÚIVš#¿g4=}¶u‚j´³þÿ¾hnùnƒc˜ÈáÚ8üö›‡Hp1«f®[JÕ5Ò¬£ÿËÚ‹iß÷élæòB¼oê\L†~Ú#¸«DV,ô/›üç#hã<‹£/J ²#ëÃ.ª‹B®|:À*œ¨Ij–‡- {~ÂĈݥ°ô,•¢ @»ˆƒ7 ʑĀ.‘±ÉCR™ÄÐ$Ä.e¦‘ü4ñ„P²ï²²…*i+ ?î¼ ?ˆ:,€ïüŽÀ cª•VD’‹Zµ›.Mhãz¸‰m©qŸ V¼”X™e‹H$râfªD2õø¥½Ì:æá_4‚‡ž€UK/]ÐáijÐ¥Âwû3\Þ,$@¾ÓúC;£›£Ôù×Ô¨¥®è®ÉnvãEÀ ÎæRÄ¿«"Õ~ [Ú‚]:[‡êfû:"F¥Ü´*¸Ä,’Ùôü+U[|…ºàI:ÓÍ ñš¸fm±¼ÉüùÖçIË£ÃzwœÎŽ?ˆÁÀuÍ®ÿ-KØÚ½ΔV{jÔ"Õ.ؘ¾ÉC[²{ÒÐtÀÜøV[¬üí™´êØ ’"$/ÔR:„Ñ©g]EŸ…ší\¡k"=a#äçØhF)D?w¢‰×yˆ«Eì"eB¾à£óŒT¿Ò⥉›¿xJ•àÃHL6bA#‹L°†¼‘ÒštªÝ:-² eÚŒ!ñÈ#ôjƒã%…I ‹­×²êŠ!hŒ Ž£ya4Jäuœ(¤ËN*&'&]ªq3Û\ðµÇ¨"bòVÂSN‰?­¢bÚ -G$zÈÒñ‡ùx‰*ÑEÉ6LNLˆöT¦^#¯'c¹©KÊ΂fíãËhª-R°CæwW±%8§â=ÀF,è!:–vg„’™tÎÕÝ:˜tgy”–^ 9F&*=„kL8ĵ0¥5S©r˜ú]ÉZrÀý• 5?ò#ÉŠƒä)Dµ™‹$Ha—oä}÷N&N 4ÖmÄ8OÓÊ‹Ò4¸.ñM$$ÜKOÃo±†r#ô¹_ÌV&$¡q2r†ùG¹qBE^)© ?RáÅ‘žvÆH` \2LCð™ŸØïBÈísH‰\«9·6æêÄ/LÍ×U•©±tDÍC0*J™èSM¡²Pù¡W½6ЪôNÓ)Ô¥v…LTèvJBºÚW<æó>~QY:áS+º«„q˜€Z½5\„LÞ—¤&øè‹rë;³1QÑ2þˆ2Z¥Q‚QXªPhT°‹ÅR_8Ö8ÝkÓRªi©u*éÜìupÔ«3Ôв VpÑCIí*èû½h„œ¬4„ÖºV¥o0¡–‹LfW”:ޤH‰’3/ ËŒVÄ2L[»n]Æ¤ËÆù»E€Š ìsY nfÅŽ®¶u©7Sk£ïQjé«BôZ"Bð$]:fë(ÿr¨h¼3…\—s 7,! ȱöUн`Z´®¼Ô²:^b&¥)Ž/¥sÊíÝ;ç…D„ËÙ(Ow^¨޳„6‹ÂÙKвÚJP0 ¯˜™üâ¾Æw¨eñoŠc;Îwhù¹®O{¢)±md‰–g;e`í ;¸ŽÈ’¦ª÷ñèþ*Ž,‚²ÐU(Ãêˆd–pâ9ï†É»þ€9=KŠnœc冄Îu]dË‘ûÉo…"¹ÞÖ$õ¯Ùa˜º«—Dh¥>¡â|ÍÊÇES9û,2¨±ªJÉ©‹åuäQr7 ª©Pqz—ž#™{r+ ¢·uÎÐC§À#¸D(Çbó`¼È¶YШõBû–šˆe¾#ì¼äâ‚Çâð×$@nl]t>¥1*“% ¼%;ÙtîÞ/“Иé‘ôŸår`÷Ö1mÃUe!¹ÂË©˜áYâ!Fà Å$ÌÅ/rZž¸×¹ÚqYÒ!'byn‡Nx‘Šñw!ªÍx~)UˆJ(ÚÐMòާDÎâ¡U´oÉh~N-m”üÔ:–ÎRÂUpH)µåaëLÚ-vc5:¼¸®èèC/ö2S)ÒÃ=ƒíINû»5T¸½¹°Ïñ‡â‹ñÍã]˜á“JJl7—NîæÃÁgd"1‘Ò¨û°ø£ëòZÂü ¬Ê<î7=+B'ÆD5.ˆÜí¶ sžeïºéÑœ=Ó?Ëu´¶mà^röèT†í,áM#ç$ª¥èâ`Æ€,RwU?iì/4–¼ý_KH7RäcŽ^‘ü°ñ“+VÊSZ͘²&ªz ØÂi°›4ՓЫ¹ ‘Ú\{ä…Ÿ³~©ÑÊ-eW¯8c÷>+—½ÝT‡rViÿkgú¢E.MÖЬWÇs¢F–<ì੔$ÒnÇ ’ûéÞŒñ wLûo;V®®†Äš4¼Ï®ÖÀÎ#ìฬEÆŠÆ~M¼å§â#ŠVïiÞ¡íºX/dúh(W'Œá±”¦Ó—6Õ›pš…ÖRÏд/³FY00Sê†ÇÑãNÆñÂyî×FGË `ˆÒ€Sâ'ÉÆÃ(ÛH«ÎÀ²!Llôk’Ñ´áKŽn÷nŸJ-è9©&1}õ·(Ò8©Æ`‘Ñ"±QA´æ ¾(¹33ƒ< R°‚8ñ«G!³HVn0m€[õúßÔOêJ«O`UçA‰åôÄrî(3HôÕm5Iˆ›£CQ›Aôc&)hT¤V¥²­ƒb…M(­B06ZD4ò0‰3“Hã”P3)+#/ ,¶ þ‘9Otª{^ë‘ä{fQg˜_ÌLë¤!ìV¨’Ш³;"àÕ¤µ4‚dÆCQ·R‚ÖU¬H”êçr®­+ÎKϯBÍ~í¨p#N8§DÖQ-?&jØaÿJ€ ]Ñß]cÚ†,HU·bìÑEˆQ2è-a&hRÅ[r*#sdsþò’¢wm€1Ê1A¥g'³V…Ý1h"¼èMS;Œ WkBFBgÄøwcQl*DUTdÌØÀ3 à2ý{ÏÜmq$3t9XJÇ0n¿>mAX‚S4êQ[)ßî57¥'lõòt롟7¦QjKnb®ÝÊM8³Y ŠfÑd-õI'k5ÇRPq;DïJÆ;°?Y÷Ò®OÌ~ÔtÃ&Mg¬†þ‹ £oidbÎiÜ[ÁÜÀ¬3Ë@Ĥ¬¡P"…yð¬°ø$oô¬*—*v_hºi=jé‰>Êî½Ã7VqÄH…;!ñv# ®%K‰"Ñ(_–ü¢§úÃ'rЮ8P2­=ˬ¾*ÚÀ¯ÝXjì¼.kRîèmÌvï„–¥oÜ‘O#3ÇDX]kPÄ“/x®ëÄRÊuuÅ ŒÂšñª”.+œ4ç˜r^Ö¢k¦¿Xªxy3.ÑAòÀæ”SõþînÕu>­±\…ê=+¾à¬{¥ÊtƒnÈØèãcXV3k„ Õ¨ÁÔ‚DÌøÉð„„ùx‰œûƒç4hxMJØŒå×~:túUbW2J®S‰¸‚’ƒðטU1'Nss£ 3 JÕîõáràì– RLòØ9x¼%-Dc>1Ù4.9&SèÆÌ¯åð.)V˜X†¼ä„›ª*߇y…ñËíCNÏu´ØêÚ7'µ<‡žÐ‰Cu$› =†ËàåUœmW–›f#sI r1•‚~Oˆ°O+ok)é '9$ „° !·‹1wDÀÐé/êɔЗ¢Kn¦¸ÄÄCPP¦'ÈßSÏ„¬î£ÔËÊ>ϧ–…¡0e¥ ¬ƒCø¡bØÁý¯bÄ—ð‚{9»‹WŒ+8¨€9ÝZkÅ=´Õš›fpRÅ› Y“qé‰Ù•k C¬«1™ùʺfqS7›U@›ˆØX¦L’j³Fv7øQ-ו9d L% å§ÓÈ»¯éA¤ùE3Íyáù“zC±WÒüÏâo“.º&>Êešª‹mCP¬¤$»&ÈuU|1V-Ž×„Bó׺ðOí¨€Qš°ôô J\SF;/HCXoè)Ú¦„íQ>åoÈëŒÞUס[*©V+5ªþN—È57ý<­ç>« ù½[††Á…¤$§×d}¦jW0bÐÝt¤¾'Z¸O®˜U"(9—kO=¹T35³“”ƒ0û˜ZÛQmxBq‚û›ð>dÎÚÔ¡©,Rî6´«Vt›H•q„…´¾ºHIzÒIy>mÓMXûâõØb{‚ƒxQ§iLÇ"½4”›È)A$/Õa™ Ê‘%E,Aô’¿KÎ’kè!+*0ûû|O™/µì 2­Ãä}6ÌM͹’75JF±înQœB¼W‡Zœ\ËܽD59þÖoÛÅVÞCéV.ÀµÅÎE Ö.¤ž+«§Á¨|ÉÅÕýƒKÁ—·ï[ªß j\‡¯ :^‘:ÊòzŸ3ÈN¡¸ #„5«põ$(Ú†¥&é{zƒ?©òØÊ¶È#äڨ̓´±+β•!i|`‡ªQròá8hC&Ä!(j^©D \v¦©M|x´è#⤠ÍJ|©-Hó6‘HˆzD¡Â°ªä™6ëzf¦Äò̺›ÌhRE'ÒhJs08̃a5»ˆ|4Ÿ±(4È ‹.¶ ’Ÿ>JótúH°‚ Ëï¼êJq vÙÑh#K>HD ¢!±Ê@ HMQì:~ÒÀ¾)¼Ó6ÉsŒŒÿ4ŠjoÐÕŒN 4HSì²½‰Ä‚(ªtíRP/¤eSÒ °QèÚÄ‘5ªŠA$ ÒU 23=Hª,µ#OíÅ`„)Mmv~ªU´“=¯ýe;ŸïÃò©\ð]Mt2ñû/5p!ë˜#“êRîºÉ:¥+‡¼®ÐŸ¯4”ú§Ê  bu}€´ÊÁè#º%é>/ ÌtYôÝ‘fÖ$w¤uí-Iç ]PšÚ…]ˆÜ6…aGó7Ul§%ë[èÇÃÎ ²³>iMŠ^/cMy¼ÕE)¬O÷UO¨‚“µ®´n}+@UF÷8 Â…Ux”Gp­‚/Ëý?ão8‰0[Ë ¤^ù*“°–臷Ï}~åÖ |zsjSòeÙ3gnÖj“‰*Zp©jõ}ZÎÆÕ¯Xý\«XWÓ y2£s=ÀÍÊ+’rU™x9è}¤Ò€vί3$S.ëlÝË€…î¶eWu¶eÃ.ÏLÞ ÂÏWÝ_dÒ¡û\uûÖÏhÛvc­|Xð w4ü¾[b F 8Ö¶Îj¶QJ–¦·¼LÏqEtˆb4‡¬CQS#„)ú«•%Y‘7l 1›¦•fäUÃÍnE=4‚$‹Nòü$i¯â§Ð™—`CÕίh×IBp8Íx¿6úíÖaNc+¾³'(üÕZkr‹u?½Rb¯sy9Çð%¸¢¼ÍœT!N :Àcáy®y$ jâôÓÊù¬X¢ÆöYN}„½¸"Å ‘èP ”ÒGÓ|_Q±‹pËŽÒhª Þ=ŽˆÀ òM,ÜÂ3tN¸ŸcfVg™ù¹B^⤒«ŒR5T—õV@<¤C$y³ ,V¸üi ­ *NtÇã0‡¤É_+5ºáKf,‡YÔ¨B€ž+3ÒÄŸ±ìç›@ýˆ&‘±)øÒpÈ\€‹Itë;ùÄÕœ½#)­£"†°W¤c•‚0 ¡Ë¦Í”³Œb8;ˆšå›/ëu¿²^k_YMR±±Ó˜(?ŒéàžÓ¡ê0wæë‘*æOö ;”þ›’¾‹¬0—fÙ(ª‰P Í?Ë8Àãxra1'ö?Ör–Msá7Æo?ÛÊVZ $™s6ª)2£ÃñáÔ9û ³U ©ùšØ¼!‚]0ó,È®mâœ9¤)jÈTšIo*t~1×`¼]ÄÉK´.œ^Ëá„¥±”}¼37êÖQÀW±t‚¹â^&SMáÒÂx¨qÁ©‡ì À:Ô5BE4—ŒcÇé8DbMò1ršŠf6¸X?Pþ@‹gL­1l•ñ¼é׫ƒE5¹oœ‘$“*ÆÃ$“½®¯ªIRCä|µš°XÅ`kÒÿ\%A|\YfGÇ=uèz,þ´ªãÚÆ ™/Pk«v•©SN'¼Àš®O PÌ´K眢¬;Ø~ƒ º€P*Öú>@›Ì}8ÑC²:Á«êDØø5ƒ*e"²™Ê¡ä‡·º“‹^»">»=òz X£EØ<Û1›_ ž·ÃÀ^*…ªV8é àOa«Yå8d#7t¡ßüÐËêè4¸¢eí–žçk[V—uÃö?dé;{wO¶er€X¶M缞^‰4òv-Æé5Ò™ÐË™‚ýª­.­¯KÙ–åÐo¤Ï»>¿c"ßvÐ PiÌ{ªt\ë<|I 5ÈÓ]âb|•WbDÖd¸uÔvÇæY višnU ÑîdvdǼ7kl^Œð7|ÊþÕ!÷®¦?‰‘ýß)""ˆåí<»kçGîÒ&o†/:ÿ;UY§Ÿr¤¶+½¨ëœ#;ŽÙ–;¥¸qâ0K ³›ñ¯ÒÀ‰¹Ú¦[Á–ëOµ‚s§k¿Ó؈"[ ¹à¬¬ jhKI™;¬ ë/°+ þ«|–36€¡3c1ã’Á8*î(`Æ;!P¤ì»)Y”ûð±-R¤0‰P¾+pó9Jm,{ñ©"²ƒãûµ¤¢> ©!"ó³x²Ñߦû²q\&œ/bÌšAQ™ [O»XŽq lˆ«­ú´»ë¾=R0»kôAÐ…YÃ¢× ØÌáM0K¢2ñùÃ’ ‡Ø¢–ÔKB³¾.tD™"²Ù³¼Kå­aô4²kDÓEKÅ:›á¦`Ù´6•Âî¯81kª˜®!ƒ®³à“Ü’§ü8¾ó—4!ß6â.Š´/Ì»%3%¸Ù ‹æ–UIìþ4oÍ”2²,Ø*4p³c¾Hõ(F«¶Ó)øbV(Q®Òj¤Ïüzé±JÌÖДp?òþEÒÛ€?«¨Ñ4³‰€‚Oª³³ëÄ,P¡ƒw";­Ì’½ÎÑBÜ ¢²¬BÙÖ]l£"eÇù ¼ RTéÌg.ÅNõJaô¼£)“ÐäVZs¡^–b×<ᇠȅÐð¬­ í»¨¯ÉqF¢Eøƒ‹Gœƒ¢‘x™»õµÐňAÉVÃä 3áÓ{OEyQ·ª6421܃=-Ÿa—5ò’DDm”ÞÍò€yÏD<{@:JÖtUũ›lW?ì¼ã팫„0É9Õ€Ú˜6ÏÛ*¡Qx÷+s'ø÷3J†Ã[³{V´Qä@²8[Cµ|Mž&cÍa¤Z±ÈÒešÂ1“Y¤L´Ô(Š­DÇ2,¬ s©ËEÖ½$Qã—iç7¤W;C[= ;Nš†£ó-eÉW»¾\éc¼Ì4§Sšð´ÂÔ“];SäGÏÖ+º j}ʵ¬«èçYÍœ9:ŒSØl}ÁÈíÀÙœ‹¹1Ê$¼2>;Õ]¾ÂÙ?L€«Õ”L ƒÁËðÒH¢mÏíiNÞ¸‚z'ÌÖ,˜”Ê\~\:Å7䮼ø‚3hê_؃=É–Ö]« Ü^:áZ\¼i80«sí à›£sª7Y"Ñ™ánŸ e¤×^l®Žs¹#é4: ʬ©cMÉ­QQ‹Æ3Ã_ H"†ŠÂ“­¬+\× $W$¬+UÍÆ$ãŽD>öatÙ6³ÞÕ¸ÓøŸœ œò·ZC ÒadDOȾ1aS mò¸-v`*>@—Ü#_¥u; Í‹ V" ¦ ÞÔpÞuŽ(­µÞ¼V0ê˰ðó:ÚT´×AÂôÍâ¦.Ó#¥ÖähÞp¢™2D§ƒ«£lp©˜cݶÝ;¼˜³ÓÜ<éA£{Êmc·8%$'EYbã„:±±,6]“Óˆ&R¯­©™+QŽ´N¦êfFÉÊÄQJS@¶qM¸¤‡LÕcÀ­•˜¡ª Ëž·dÝí è_*˜«0pQLª^ùùÉÃgc¾#õ~Ä2{Ÿ|9Õà·HUCK2A^q!×4Vôo„ô>PÕŠ-[ÍHÐå&¡ƒÄÃÛ–K?»¤ ±éûÞa— {Ý õ‹Z¢ Ìeé=be¹Í=œ-jʸ—ޱ+v)Y;ÆÔkê€$thõƒ5"¥TNNi#¸žúŽÇ)bÚ\£|ç¥ÝüVŒ h50Å;®ÐIl®§Y¬*æ¨}L°ý².@¿˜„ú›Á?ŠDÚšƒvÛ EEi˜Ï]ÍaÚá]{@LÝêÞĆ8#oQÌ%ÌüÀ]‚€9á²5·jð…³(«A–B%¶ßYÂàˆ‚^4’¦U«Mº WÂÖ3ìÖhÀ˜Û›³Ù–ûãZ.Äy¼ÃfÆÒ®Ku –:³ZDÑ#œñ9ÞåÞеsOé•М›€(ù+Fl} ÔËQ¤ÍÃ?TI:Fˆ/kÆP¥Œ–d½`^HNTçX¿íuFËl•0ž/6ÛÐmcè¦EÎ0ÙáaÙµóX&ªÁè˼MÚ¥œ93¤òŠßè‚&ÏNíi‹ýû#eHšÄZ3}oX²Gx™u[·îÑÀæÑÝà:‹²Q§b°|æù«È;±ÑÄ®É’Ô ®8Þ)Øi_mpÊh&v”:)ÂPH¡“¦ö¤(ÆTdÖŠu»ñ9ƒØecI^·\e¸ì]¶*ø¦Þ:6 vŽ{éü`ÿ4UÒù#R¬ÅºÅƒÂ‰®œ>¼ž_¶ÔÁîŠ×K|Ú7úšÃHëmuX’¤ÀùjcHäÜð»¬Ç´=Û5{qg!š@±X¥h¿¤;¨¹1—hzÀ›U"†™„¾Ì#• Ü¢¿mM—æv7¸@êqxêæÜðÁê ¾vügŸWR¯àJÄ«/Ò$_b6rã9&r¦U¾r¥±lŽú=᲌̣Ë(ƒá`®ÉÓˆúC]b!¤ÒöàÃ]dÓ+ˆRÜÔÅÛIP÷g+O”ÓØz aEgL¸{HΓ“i§P_MTþñq¡XÐxÒ2E}3ÔXSý*u‚£ät<©u ¿1˜†nŠe²S+vø–:8›ÏE.ñø9SsM-Ü[Öåe×Û§HO³ïÔûª"òÞ’¼ÞõÃ/Eé2êV¤•‹þíCqË ¯ r¦sØŸc ñã‹qÖð¥hŒ”üÍ̳­0 -¦Q ²h 0P3VÓÏzsœ¸lÉöX^±­Fz)ŒÉUzìmÆè?^k þÞÄóµaã˜Í/bEN¬µôÖ‰«´F:ʆ¥(ÒRôÑL²Nz:‡i~:]\áøž:Qï0÷1ÞŠ’êϸ㣿ØÐI¥ékM•c⼄ró¿Î—ºV…kÖE=ÚMÑ®èÛÿ?å´ä•@ beUïcD…ÇB·&¬°¬ß¤˜šôÞèÂ5 Ü´áåú6ëúˆŒÊ%0Ç ¨Ü1ÙIüUŸo˜ñ¼©"ëóÇqöÖ†ZøÙ÷ üÁˆ”ÎWbÓÓ¨ôpЇŸíA³Oš××éqr$ ílp©¾2ò¤Vô³;%ßäÚ£å[§ÖÕüùÚê¥kd¥Vß›ˆöÿ‚ ÐwÔ$ C@0ø<<ûŠD€qxÄÿˆÄ Ïé%õ dшö5‰G ÀI„4}ÊcS(”掀fQ©LI)ŒOcQ©$j%&Áå44⣿æ“)üe,G%2H”ò aªÐ¤  º9h•Åàó#âå¬]e3HÅÂHü¾\#ÇäÒ”@®êìŠIp‰V_ñŒt“%g®Ëcò ápµR`™7ðE2’\ŸÌ«›A.×þX€ª?å: <ÊRùÞF·YužýŒh0à*àj³?ª¸ø¾r mÁéŠÔ6•™o3xo&%)ÙY(÷ûä‹q²ÅH!`nSí’É´’ áàD°òø™.ò¶è¦ Kh‹³.²ªø¬ š.À&I£¶· ¢Ø‚"LÆî!©êÕ ³ÇûA ­4BçÃJë’’=ìjÓ"ȺD¼¦¹üý Š€¥¤ÈÒDü­I“RÉÆÀ$6Š0ˆ¼J‚)Žj$¸4É$ ¨Ô8Í&,BÒËŸÏCŠ=ïã@Ù1iƒÄ®ÁŠ:DÙ9í“€B®W7ú½¯€EàšS7 µ4ÀUñI,¨4ZX®Rù—ûÈ®²7#©`¥Ô +\‹|ЋÍÑQÿHGhiÜ•‚ÐÇX`pó6R‚¦G"|†ÞXŒ¬ìÑoÂ’Z5 '«ÕQ—@må8~¿8Tå—IKÀHPæÂ}ˆl6¤iœä²Å›Â¼pH™÷1wšap)ƒÚ $EÞ¼(H%X/÷VD‰¯0Ídü´U|ÙÉæRé6E2°Z ðÈ‘(Bs]Á931 ÅX"Ecß…ŒøÆ×Øá<xÑ,4dµâ‚ `¡5¤n<@Îx|“(¼H™3Ñ‘Ì8ÉÓph ¹úKmÑl㆙žôsU±õ–ÉÖÚ#”/*¯9ŠDžßH4N$õ™Vjü<šiK•ÌøFQITæ¼>­ˆ\bSÌ ÇC¢. tìÀ‚àêØÉp$G½gÆÇœa´83qœ·„†Ã[»²Ž¤HÜ™I1ë!èÕÇ:f¤ãe «…`°#¨À°>‡$ã³ØÐòŠaLY‹¨¾-ifð€1°#ˆžš‚øÆO3Ó“$„•šÕ [zZHdÛ1‚AE¡ %*<†Æ)¼ÐÇéï4Ìõú¡Y&H `÷¦Çå=*„¹æó«™$ºF•f ÍÔ2"„/Q' H „ó<Ñ}GžâÊw…¤ ]Ú —¦ O m÷-zs–“´}-ÍO@'޲Ó«šÄ&eBŠXÆ^1™„²^´FQÙº7~49¨¡ùXlÜÈfpdš‹‡ñ"_*1"3Š¿‰Íh ÷¸¬_ZÆŽŒ52°kG$ ·GÀ‹VÊYIã—Äå#–†¼ÏhÄ(‡G°„“H¼é‰$ébí4¨¿Ö? k¸z„âw8E\i 8¶óŽð™!!)ÁЙZ@¥[‚޳•ÀœôªZ êäæº\é_„Y©áÕZæÍ¢…£YžÑ·*8ÞoÚjoîûÑöÁ`åµ:‹*zöÞ%aUÇìR‚\Ç&<_%èý¬r/Wk úê™x¢¦Ú ™ ‡ýYeòÒ"¸«~³ibz{U;1™U)§Ñz×Ksk fKÎ&1cÇìÿ`=’’0ò\È…Œ~­ÊÞš(ghïd³«ð¢˜çe'Üj1¡´çQ윴ÆÐæ^J©Qlîl*¯å:cŸjoüâ86þ~ši¦_ `ÕÏÇ½ßÆ©3šè£ó‰ð óSZmwZâ¸/‡z‚ãG–AŸ º†0é·¶;ý—[ôrI#íìâe¢‡¾&£yÞ,æYÖcDÁ²·©5±›ÓðÀºÝ[È7 !¦ážÅ%=•à#×:UšîÝY ;I9ŠžkË–•5ÏÓ’`›hÅ2k¼÷@!°¬žøºzYZrÓ8ÖÆGÈxßseÄÔŸI3±òÜW;j"–<úA8ÞÙ(@ü[ài©lh2D~DtùhkÕvRÖÜZY­aTnÕ„4ï2‚áLê6 ÒU?‹ÅIñ³IB¸/jäw«/ç$qÉV‘Æ< Àd‹…6æ¬î9lÂmí–dÑÕô ˆÊ&õ‹6DÒÇóëº`&Â^ÞN$´m·ÄE5 ‹!.šgœÜ§"ÓÉh–q—Z­Ð˪/Ž™~ÖFðS1 ˜¼¦K ìÚ·éDpx9ào©û§Ó[ùwvž[_×OâjìŒ&/S-oQ"‚O¹Ù=®ûæÈû"Z@“Ks Ÿ¬±óÙ7Zû—É¡!Ãí[ñ­ugéµ&¿D¯_ÇbAõ _ñ2ëÕTâD¹ñïçÉà´kS@”‹”^øE—NÓFÿNNrZDc©zq®Ü·?–Öµ¼¬Õw¯²^i3÷ˆh3˜Ž76K}ÞÔ¦’è0 Y¨$ˆþóq²3.P\†˜)–Œ¯ø}nöo.GìŒÍ£š7¤Ö(6³üè@•èŒÈÂz»ë‘çŒÜ쀢ji,Ók$"ïz}@ê®d2IPÎŪüh(ìÄ~ª½b…a†ªƒi¼qc$ͬRÓÏP£ÈR7!î4–g”9¢H‹Çh©àá H,ˆeÇîÄŒ*¤ ,ü¨yJÖÌ8b˜xí h6N(:fe<ß ¥‰ò´Nýl|ŽÍPŽO °,ÆÝéhÛ*ªòàNkÔO2´ª,‘œ]¨6`‹^LŒÐñáôŽªãIÆV+­ÂÜ à¶Â]0£0æ9Ž®\ëŸçX¨ ɰÏs êêZKnaö:‚1f·eèüè !㼬élÜjƇè€m óö ËÄd¢Lñª¬ƒÎЋ+༠Î8äÀ#N¼$màƒ(• "ÒL [®€ô º°|r¥ $ÄxÁLN¢ÊÆSFÜÍçxIŽn¨(ÄÑ0bƒÌƒ±î»HB¤ÒDì¶æÉ"®Bt¢Ç”x¼Ç¸åšvƒòÅŽû± 1alGm¦Ó@ï«æîQе ²‹ºíÎ m‹>Ìf>6."ŠÜ& s%BÐLrp’2îFþ pÞ®odr&!×&þ%*ÎÏJü‹-+ )ÎB"ˆ¼G½$KˆÄ†òvM‡ p²…"xÒn솗‚龯Îö_å0 ÂÊ2Qrµç- .;§>^¯ºŸ©˜€¥.¶dí…ÖÙ".¸«Šs.¼uiž¥håëóìIïÌ“.Þ¤Rs` %®OVÔ(›CB4Bî¨bD‹ÎÆ8ò:—(`wDÄ!j &Rœo,t-4³2¬l´~/Ò·Eài3TÕV\‘x³B»$ì(¨á&™ðê½L -(PDh2¬ãž;Íjóæxæ3 pOuLÚ'ºÔGúK00.°Ûª†/É®©8àOô"L*)ŠãpÖáê‡Sî‚!…àÝ*ÞD²±ò…#ј!#âûò{O»"oÔE ÌéhìdæoÔ9êJ\£“¯¬ïâŽàé*å` çÄ4Q` ‰Ÿ¤ª4S)6+ª\.P^û¥`ÿ( ’©É°¿Ц+ÖîÆý9Pü·êÔýÇO-2II ÙGüh:ŠSÓoa+Î2mè[ ¤oËðPÆà³ÑHå«ìT‹0‚ƒŒHnðXo/†+¬rÞë_CS.ºÓ·À·ÌJ]‘uJtž>S3+fK†2g£ù.c6x礀 K%+(‘þTB(„Ɔ‘@[%†þ„¼HäÖi*~€sžÍ±3jTÈʃ?DHItÌîKhQP”KÍ#3‘(3,$™Â8À jÕFÌr.õpsM”Ðcµ2mÇDQ¨G®pÒk©us%#ÞïrD$‘f#Þ6´°B–Ç.eÂ5@`4ËcB:èòHËSÏJ’ȰE,ÉC!í2t£â&Uâ}bSk̰§i1Iš“ÎÐë7,S‰.Û“`Ô˜#“@Ò#žtÏÆà’ ‹F˜€B0©U„Sñ’´lgWçü F8UFëJu‚2oÛÅ=J±H[b¬øöÕç#CâcP{LRp³2ô¦7X` #…É$L™AtP¦ë;²4-QêX?ÎëIuˆäkÕ}Mn*Þd¸vQç0iëóÊ“ S-ƒ`ùÓ"©þu¢FN#>NÎåF\¨4Ü¸ãøæ·H²Jâ«p6ãD4 ²è¬Y§zËÌlßCN2Š?”Vc/î!.GÌÍnÑ Voá-Âäž#Sig«’”.ï'ãÍfLÜ”LÖOJ8fï,` ŒNÌgÒS4ÏY0M‘5ÍÊÐõ¬¢Óúè >m†p/Vƒ§€Ç6Q5ÅCu”¡¢žôLò4š¦ Ô0±sqÿUÕþÓê‚öl±¯ƒ_ê8Vj¥„Ž;׺nêÖW¬„”¨ýhÍMw^Üåÿd w.A;‰è6O£U¦’íL×£x^aúè *g¤í>h¼>*ÆkÈt¯ˆP`ô"Ñt4JvÑMêkÕØ(ø‘õ@-OÓ³½BµWoBäý* 7ÃD6QÇc%½ϵ„ob +H…/Es§MNì„qF·‹3cpN&I †)¢4Ps—Y6˜%ÆÐ†‘$mõkÒd*µŒùvú¯Óœ”åBéï3öÞxð÷üo5>áŽäö 9˜¶¨¯^½T’Ù¦fÂaø×5Qe‘ž—dh!2 RûRø\ncŽÙ³’ª©l?7º”Ô£[L_BÖG ‚¤¤L~±E;ÌÄÈHt´¨ï©rcçJ« ÿ&9ãÞDup#xZ.æå‰C·ùX\3s›f -RÉÜ"sn+ÕAR\lˉC~g× PÙ£2¢ÙQ’j¾©èmå/Œ"]TNJYµ|øæÁ·žÜê*mAÐO/Hc•"êÖMàåÎqÈä5CVçÅš7L?ŠÎK(lxæ€g²Th½`âåtVß #AP2ê-CqàHÇ^˜Ø‡HÂŒ¬]:”­pñ6qŠ9LûilÚw¬õ¯½ «FÃBŸ\æ»q㑆áIbWa:ý2AeÐÜŠ-XµÑy*ðnªkÈ›ÇòÆÑQBf{SoOT3!Jiå9MŸµ£M2xq÷ºWr4žñ ø× Gi£±‹(ËgI[™y _‰x";âšú4´o3r#`©/5’ ë0ïZŸŽÕqMv–up©FQ+U0OvüŸn%$Ôà •0ÞÎd–’¢ÕaCVŠNÁ6*v#¼î‚È:i™ cC½6Ž:£¸Ùž¤T…Ä–´¶TSÇ€yUú3.HEÒÈÄ„y‰ZRói,õšãÆ>ŠCâú@ÆB)™Óá{n'NÂa@"ž‡³_š®Í ¹rý;Nh“V€Iû¹¬²ˆÿC­àöÁª¢ eÆ™VImQ¦ÍuTÌJ-Q§*¬gw $–B¨;¢ÃD×× „ûí^͘”me uxІ#ÔúlÇ-ÛnîìM_¯`´/)M›×"œJ·å`î¤âéºk,¾Á™X­g Y1‚»X·§¯ÎQZ] pIÍ$ŠV]·²”åÅ¥Ž­É Ñ%#¼¼ŸO€Áz±)L¸öÞB¨}h'Ç5³HœÙ¥|Ï;Ö(é ÉàE;ufë¸úkAøÙés˜¸ðËÏÊ© Ë”N¡ËHß)ò–Ñ»‰ÒrµeÊÜfÞ‘ ¤vöþoE£p£0TÅÌ…°éByY³{Ì ¬E»—ø‚à'µÌzÅ#¨i“V2qˆË— ¿i˲z³7sÍ4tÉ–|S œÎó½÷ÄFïb{.‚ï×P«FY»r{i™ûŒN†*•Dâú`€(3þþ…!Ð >þ~ÄàÑP6ÿ‡Cã0Ø´3†Èá‘4ž2û•Db±Ü>$‘Ça“›ô9†¾g“ÇÅÍöõí  é‹Dn0­»0§iã‘¿ j"Ö9@à«­cÌÖ;ï2Ê<ΪìŸî˜¿¢lj‚í+à2á»Bì„¶hT@ÎÂé#Æé¶èÊo ¢ªBºç4ê2^Ø2ʪ*›Âz ªªT6Ê'Ï“XÛ­çüН>.’ Â¡‰ó(ÜŸí3O=èT`®àn¥+ªS7¼Á Gè2dõŸé»|ȺòÌæ‡©Q$Ü‹¤‹k)! åÏ#’Š#ñc®à€Ž¹µHC1•.ïºÓ, N*çÄÑ´.+-Jqš'³è«(¶¦r䪩"T¶Ô‹´Þ³Pªªë£-¼vÅ!Kó?=´t&Û½$…AÍ<ж Üâ›­®z®žöÓ ®ÓÒÍ}:»JDX£)Å 7ÃÊ_N1Ä= ¯RÆÍÊ£M £\Ì;õ"2Ù^—ZH®Éµ3ÙG'â‘3úyd¡”³O ª‚!©¾,ŠÒˆ$RRТ_ ¼ÑáNHœ†B£¾Æ× ë<¥VꮘM îeÅ'ôô„K4²¶ÛøC§³Ì^+xE¬ˆÓ©XbL6ˆ ÙÕ­ÛO4é¼Ðòhú¤)MdDϱµˆÙ‘5ï6vY6°½,¤[G¼ PéT6ë¶„`'õ\¼*°£YYcgîYÄ"ÍdÔV¨eòÇ̼U–ïëS @20¤œÖK¯"‘ÉÙìzö{j©¿BsÈmB~°Ô[ØØAšVÎFš?>昺¤æé»ä7šŸwÒxò"-½¬Ô!ënõ~xS£–÷Ž3Ýv¿¶&w&Ã)•”òÏd?l*ª4YÝ3ÖVÌ&¹ÿ¤À¹OÎq}P&M]b©%tˆ˜é*lë¤(¼úV3*¨mž¢ÖHtÙ )V²ó´ ST…uË “ÍscùTçîš,4é8Ÿ&#èdJ3šíµR7¤Ð[U˜ûHFe«ÃØÑ"žtÊèïÂ÷ÄUI’N}…AÃ'"KÔñ>AFº®¤[Èšã!é$œ¦#…#r‰´Ô Ìbá$&ÝÚ£`ˆœU,ÌlŸ?cNÀ!‰6í=1¶— ?jå%²›pQ’æW§eȦˆ<>ämQ¹²uƒ ãÝxK½¤wÚõŸ¢!ø‰¿s¬BüB+cèï¹è ™¤cñM¼Qú`q_r¸x CåzQxnÔ’@G€ƒ a†‡èQ¾‘ø2üúSJ°.8EI KáF'ª»âBœa\±Q­LLÔ@ý|ç ¼õä•;Ž,îq¿É¬m\nÀ!¹ˆœ£¤*r85u攥@DÊ9Hšä ù͵‘¨PE[Ñ'Ò®W=+” RÄeÔ5ÃüdXxù‰Š8EJÚ± ›$ùÊAW. t EÑúCQÄ2™™±U2ŽE'Ò|°(¼pÒÕ–PxœÒ‘áî¤Óh š¸R%Ft… ”caßB]–gNo³qðFSDÙ§ÒÆ†I×áidÄy^u5’ HaJ+ )ʤ3 سƒR {!¦¶? iFŠzc™FªþaûÝsнüªH$ÒœŒ‘—hqe×·ö”žÌþF.°ÖÚ¿£Ë´ªà Ck›\{¥!ÖJ¥/Fg)FÞ¤™Ê|FV?%l¤¶Ä‚ &'ìø^©MêÉÂfϪÇA“’-WóÇÚ%"6°ÈÊØHSß>TÞ“€)1yDš7ô)Q:DU’2$U4;4t@¬ è6ï­ Ä*„CYÔãqÈÔƒH'oÎJº6Ë;„§ƒï¤¥vðA-ÈñSí©Æ5;J”A¥ò"(‰6ÑÕçj ììpdU«­äøyXªzE¥—¿J‰;÷"±É¯2}(´p‡ïV‹ÛØG>§m¶{’+Œ‰ä›§¶L„ H ËßZŠ¢\̉HTž)Úê*¼âqdƒ™P’>à8s “ °0½vBŒÞ†U$‚¸22[\¬qg‘ìÃðÛÅŠ1 @#§óÛCax¤Ôj<¨Ã×y–NK©mgÙçÐð6½Y!¤ÈÉF¶ËpÌ7©Î® Ê\ùFþtÚ‘'Ò L…dK—^Õ±ÏÑq3˜ùbÎLy¬Öå$•P®Éj­·;ïT”ë]AmõÑ ¥"ÈÌOÖ%œ~ “}?S´=‡]ÒI¾±`12•¸ÇÜÀ °Á(È1ÏGÁøü^ösIùBüjÉtuu^òÔ˜.Ø+SÑ1Æ>’¤Åvè©H’¦0]Dâƒnw•uÞP§Â•EÓy)Ä™ +6gî W ^Û_]Ð'½™^Ó7•µ¶ÍÆÜÛ§IÇUu€*¤VÕÜò-_U˜!V*ù<E?yÅqzKJÆÛm›i¦f€Pv}SY;¶£LczzÐõ*iBÕÇNÃÈ»\ôRšóÇêX†?yøyR60Ê6'"ÑaNz½fÃ|½¥8ǯ…o¿=ÑML¢7èÇW–>|o8J2¬Ò±ù„_G 3Œò<ÆC³ðß½|·KÏsgË%äÇl\ž[i¤Õl¸ü«Äï ½K{ij´ìâÝDDõ3ub x™d!ùqâ™ Í9NÂi83w¸ß©ïoÿ·XÍ«?3+Âk¦· ¬³ ë"ï­Ák"ߤíù=Ûk”˜ôSº[wm/‹w¹Êš=ᦥ«ô‘a$ÑZ5q”zí“ð§ªv'ÃÃ7úÇ#’¶Xâ®9.œ0›ŠCza'!z&-2б ½¢ùéì ʬ#¤(á9òï&;`¶³ý­³6· ™&b˜™ñ ’1P¸ @Ó®9' ¹±4Xœ¡ú~‰ªª³¤9‚>ê‘k¶2©¿J¿*Ñ„ž2a)¢Q+Гªs/:~£XÙ¬ ´=É¥A»ø-:÷? )b¥ñ,ÂÓ_°xÃÙŸ>Ûò(«ušÃ±`Ÿ6è}Ë2¾Êœ‹Ž‹¬ ®H"ƒI®¢´.°íÉÑžâ/‰:ù“/°ñ4A²ñ¢ân:‚£98²È—½À•#9ú§¼"Âá('bÀ ÊrÁbþá‚­ù…4‚™¦z-‘bü4MC32¯eÂ: ¼/©KOº4mª(¢{‰yñ¹( 0ÇaO1¸ÄA±9AðE2?´“€´Ra‘)(ˆ‹<¹ -3 ƒõ³Nµ1Ÿ ’$°ù1,è%ó%«a¹ #²®ja­n©ƒ©‘b ©ÃK©™l–ЊžÃ{;ÈÄBj¥á1?AbHS¸ Ö, {¶Ÿ¬"*Câ‡ò+¸®¼ëë´ Ã kmr«¢&l—8KÊ<|úø­óGž"d½€,$½+IÇ c ‹ý—¬Ò!Fʼ ºÕ"X¡Óå•ÓV#Òø—™Š€‹/jÀq !õŸAùÁlLÛÔC?È !›+‹v+¹™ ›H5Œ`'êÊà4t4€3ZKû{ÉC!­ê~B°ó¸ä@-ºý xÊ9ò’3Š3¢žCó$I¡ËÔ#-1á `Ê(xÊ«»)ž 8*£L9„£pû@•øF M8†ª·ˆ„=# ÄÜÞ€#ËÍÓ~žÑÝ«Áá3R„Ë2d?ÂaË˸ª$››Ä2ÒQ#³>$õ‘SH hjÏ‘2°N(ïŠTžãG¨£4äT¡ë4¸œ¬Ä›%·<‚«¶/%&cB¿"ADA žìo úc®ñæ¾0Õ‹*‡\ì÷L¤ ÜyÆÜáD°-»MPÛ}8ú€½Ü–,á\óHØ@RÔBú(Øe¾Ë*i·†¡àÈ#ƒŒµ r! Âoѱ)ØU,¦@£ô‚¬Å :LƒtÜ5µ?e€‰yDLk3‚5¨­Ëˆú+UTWT5«…ôY ï²(«Šít³twLŒ‘¼¢Ói_E߯ɹY>ShÃ4š"áÊK­áÈúK/›wJaµPõÄ¥«å4¥¬e!½_ V€#ž¹R_ + „E‰ÌF²¡} ™e<Ë)Ú%~žÖ<¤éÐL{Ô5@FjùÔ jÍšQ .tT޼1\œºŒjŸF¼­QL5M>4 ÚE°Ù…(“·ã0ÜvHÉ:€×0˘ù`n,ºÒ_$)FÞ£gžù3@“Ø,!¨ÀÑS’N¼ØŸbV Ð(áéü"BQúžÄ$Ẏi›gÞxo“9G˘öÒ<²ôÅKd´ÐÌt‡vÌ? åZÏŒat¹H ‘Ó¿}Û™·XhíøTo‘nÂQU©ZîÜ–\à¨ÆÙ\Þ­DžóbÌvé¥$ZEº¼óýe8…Dš‚(Á‹7,âÐØÎ'êž8Dä>ïªv5wfu!ÁK)|€-îKçÅ#ex²-oš X ù!hm÷’f’ÀŠWNÍòùý½qõ¾¾…ÉÖ[͉“ ŠGQ›´Ë7GŸ#sÔ;iNA?$õK]“Ñ›Œ|]ѸŸ.±koŒá£\¯žjÕ_AWø{žéñé>G­m½p¹ÏzĆeßFà‘´„-®Úyõ2¦Ô=ÎüR3ïÞÅ(/ž{Æó…AÅ ¯'-7XT¾Œ*WµG\¥0z~æô'¬]ö…du·R(ç{ßôGzÖ$ÙÔà‰ÆÆ¥ª'rlê\ç Rаg˜ßÎ%û@€°0$û~B` GÜ4„¿Ñ0VûÆapðúFdOø¬–M%‘H1ÉTŠ9Ìeñè<–9%•G"2™ÞO<•cÏê$Š&‘EåSh|âƒOI[U7ÕV9D@Àµ‰Ub˜€åO‹$.ÃZzÚk´@M¶/.‡Ê¨õ‹#â9 ‘PëK .=,¨ÅeUWÔrÃKŠÈã2pB±äo÷ g fk’ zwV¥šÓçM¡èä‘ZÅžazlkUz$·*˜Ln+|j ´Ni¸˜ÎÚGP‘IkW§ô–±"…Éw¯û róŽu£1Ô/.üÆb1´ù§c(ˆæA]3æU‡§óñzÊ%:ƒ€òbÐÙk"­'ªÖ½º(«:ƒ¿èº˜Ž ïƒòù¤ÎcÄÅ$k ìáLc䑤ª;TÁªÏ;ô'À€ö®è,(üBIëΕ/ Ÿìùþ™Ÿ®rŠŒº¯;ðˆ½¯Sr«*Â"ñ¢°­,.âˆÀpr<•"0ü\4Hª"!.ZǰËâ5`ªŠÉ‰‹&:çì AϳTÆ.°Â°’ÈHB;°IÚÿÀçìFã%RÈ$« 6¯j"8­Lï2¤T[ñL`š„Ã[ÚTd6Ã7L³ë2KèCÈ« EQÈ}*Ú©î‚ ãM©ÃÏ‘22£ÄmTŠáÒMT(­M¶Dd~Ô€/-ØŽõb/ÓÑù ,4 \­¨ˆ»ñaGs+ŒÙ­jb¬"ê;¦åÚдȹ"pÝ{EÍwSøâ²®¢c ß t7ndG0Äu™ý!®u #°‘ Å_Fö#ììÖU6~ÝØ‚=c pl†^÷A„àè: =é[ˆùjT·waû’W­TRFÎe·$ ¬f7r!ô¶)*OxT0ûKõÞ-~íÂt¢jVFŠO  K–žïTëÈ*Ú°šî@}Öõ'¡0[`Ì‹ 0Xܺˆm)<Ã;è݉)¤€ ñ? C{ÖÂBŒb9’0šcía€SµÂÆ+J:#Äiw˵¦©öÍöÀâAƒ;ð¿AºHnĨ8וOMeZ ºÐÔ_b+یà …À½½]úÀ˜¤¹þ#j7ñ}óƒt–þ­DÒK¤×¦ qøV Ó_Ȭ‡›¤µ?«LšfX”ÿ¹HïA©‹üe+A9Ì›bLñfº®˜ÌHí"êì5VøPW0+Eв3s˜åˆI+üî«uòEØ·tä<­¢.{T+o®©£%wPþWêÿ8Ïq¢ÄpË«›1†CSáœÂúl)ãLÊà;úS(‘!6G›ˆÿ<ª >6lyßÀª¢¦äª”‘P/¤ƒ¡¸$QÄa$I@‚ŽÌ“\ Q§Î&¦LFOú6Œ¤€iSiÃô‹¦Åá z å»và[ l§Mm¦´ÖÔ£¡_!Dˆ¤à x¢Z€~EU¶°´›1l¦{²<õ*‰x„üÅ:(é*Ÿ²ŒQ¯E4€5 Ãå»)$5ú¨¦]jáScð…ÉæZBÍ›s’½ò”B#aŽn4²Ž€\rT³.Dç†à<'­µ5WrA߬†1Ê4…ÉÉTÒ‚Ù¬DãÝ%(5ÕÖX5û$‡ã¶ˆdfÍ÷ÂUh,M‡df«¦J± JZn±PÆRøç£Úr"´Å?×a8'C£_®ô§¡¥ºC_h1‡¶·”¾VM|ÛTu±‹ò@kèû(åBJ“ÿÈKïnLÂ=8,Pˆ<4£‘ÅžBY” pÀ²Üõš=¯([ pܪ¶faŒ÷qš£þs-!#shÚ„VK\sSANnçH× eö †”IÛU´y2ÏÙ9–€å‚Sꀑ"ˆ‹Y–\¿Åø- fÙ„¦Ô LZ\G/öŒä|ÓÔ6Ñé90’Y‘zˆ¼cø6ãjD­­UúZ¡ÿY)Š,6þUÎ<†™®I¥%êbJ¾AfH"hQƒ3xrÃÒy³§Þe:‘ö$´óLŠEÖ§=hYºñ`ûMÕ"& {c'øßônÔ 8Cê5çÆ)*TË´^H1|V2•Ùr#1Iýhfhþ‹`Ž` Ê…ÊŠ&©’=BêµQÊ™L2`òÚcXOûWe·õ·BHØë ,ßP'²¹€î± c7÷`ÊhªúfõOc&çÇ–€4jrvYªÚ(‰F Úmš,H ¸e+tÍJK¢Ta‚ÓmÊÅä€jnÜÞG(¼é§¬fÿÈ+õÞäßg€à¼#g‡õ·š0­U¼hüëÑZÄ8 êòktq¤mñÐKæ[‘“r,N KÛãÅuÌŽž`„fëÂc¾ÍÙÀmzIÿ9«ÕC£vcRöÂü€SðˆÌòœ_;ÑíiJ9ÇÙêÇÃùàØ¶ T6,ß(ÍGa,vJ>)°©ƒ&›½rÜØ{ÆœV Ú¯ôm†•îããøpó%Šiª@ˆ±Oî¼ãlq¢=©°Ø<)¡7k%,%vñ^(Þ­6–ÍÍæ±˜‰ì§pQW ª]~ä ÅK@$…S7ϬU¥–¤y#×ä‚Sà¿7t'þEêrȽܫkÓÒ^÷È놆™È*–âݯü^šá¤{ıh—Ã/_“bVh~d²'ÓÛ.¨¦`Ç3TiM3ÔÌÝw5õ_Фç1lW*¯:ûÅd¼•™Ž‡jªï²¶QÃÆ_üuÜ\ÞˆÏÇÛ~+d¬ئLJHy^’dà“LAÉn}f,[ËÔ,Δ‹)âêÍèöþÆ€r%ò´Ì4Ï%šM®ÂÎ'ŽAb°0ŽŠ´ãÄàLŒAeÆL­.È*p!ëjÔKF!æÞï^ÜæpÊ.Т¨Du…èþi,Ck”^ f®@lÄľ'ê–évmbÚŽØñï@Ñ¢¦ yÀgÍZá Š©ê*¦¾Õêkèr¶#˜z:Ó†öîFd"# ¨¢@fį‚ÛL‚ºO(Š.” "2"JÅ&ÎæËxš,Ò§Î(æ°õ WR"¨|0.(:ÆB«NäAÊìŸmÆÜž¡<ã™L ’© rø&!'Žÿ –Õ vfEþ‡ªf†â G@CdÚþ,žCÞ_¯êú,LèjŠpw ) ¯,`$̺½LH8¨ˆEVzÊ¢pÅþCpE°_.Œ•ÇþÒŠögªz‚2.¬pÁ aÑéh‘ò…SZº'e(f;ó\j¦2Û¯9±¦™Î±'°„Ï LLsÜüÁôë„"t´"iAd ®è1;•¿!j.Ód‚½È–²Ð@n‡d³Áô”ªýQó—’(ó˜têŠø4*ªâ¥Ð +”u+´â?a÷zæ>å7u#±ÿn©4F>ÑßBòF× {i$J´Ó$…°aX§ºŠQCÌíh"‰Ho‹"B1jzŒ&N0دŒ×…H‹l²ô<§$·¶×3v£ ê¡*q€·„p¬I#-kŒR±JL)¯Ô­i· “h›t?TÙk^jŸ[·¢BWph!ð;4näÄÌ6à7PØç)®¯3b€äÌQkj8Ó*Jä)-gŠèlx…£þ­È%R¾”eb W:ŦIéVÒòg1E„ÒÀ¥Ð …2=#3Vmo8 ñGë+énœSöø‡ØÜ _WLr9Œ‚we‹-èèfåSÌaãí$7RwrW’Óo_mô‰iaû‹ˆ M¯©¯±g¨6I£Ø­Ýkë2ÒÓÆ: ¬²T+$êÆ°!Ì“&‘@“éƒ]¯M‹.ÖÓ{jk¨â°¶€µ¡ùµâhuŽá¹GâA7*Ò㤗æSÄIJ3ü%ÞèÉi»FïÖg« ûÊ9êÜ“FD¤ÔJ£|è騵jVâ‡îìè“ØL[‘•,ÍçµúV‹iBðÝ7,(ãr€n•†¨9\zdAT@ \ô©Òl„”s4” -“IÑþYº{ýv¬vàîÛë˜*‡•¾ž•.YÃ¥.è‚#2$¨#Òír¾Áaö›˜j$ÈλRH÷Ë´Y<f(ék.¦l‹hMµr6–ú›*ˆ’pâ!™©Bòä`?f–ôîÓÒ›|«’Gb–êüÌ€-!­˜ØÃ¤ý/­ÂTReêÔ¨þ{éÜç¿Æ«Là«7OIerw”eÍÂÞ¦GEª6©Ð¡/˜¯)KÓ•Ê»QƒiIµ¥Âsè܃7wkña’Äâi{æ$dáÌBî¬H4]*ƒòÊé¹*ÛC¤Š®/löi„ ŒCÚ€ K‘ Ž(èÄ2*°ÛQ„ÊŸÃõ†ÀÒp४rEY¦F¬;ž2qQy­zµÀg$Ïi‚=ò°€2 E zÖeçhý µŽÐ<«$gVãå"§à´Áh#slm‰fÚ5ÕV‚ždm€Ê]UB H§N¥Xq}‘B3é!(:”Hé7-e¿vm“¤êB̲6°ÔlJò¤ðTi^ógsÇÙÔS¶U¥ÖúO ‰° ¿‘Ú‘è>Ðí~ŽJ‘€#=€iI¶ Uþ4÷[ª-Q‚¥ærKzûaý\úR"©æuŽq ÷¼8n® ò? š:Bñÿ°úÉóˆƒÌX>ðä63Žù`¾Hö£$cªxeLZº›TòW¢ìŽÈªˆgfnE7÷:À8žàB˸"‰³hºÀ¬Z:ü\S+§ÚJç@þºÍÍŸµ¯`ñ6/ä›,€Gá:klæŠf‚\ \C§*‡±Ì·¢çA•Ý Tí\ÓÏ’ k9 aE¼ŠÞ Ó³…\÷µ¨ÑøÑ[¶‘ ¥AT³Xí¤![ê¶Dù+µÐOØ7DÉlÙÈÄ¿]ÀkˆóèÒ@ß& ¤[1,*ÌáºzÁ\Sgü»½¨LÕ˜ˆÿ#ð¤bÐ ¶·E;zzÙèra‹Ñ×Û“2C{Å´m×XnaUg´õ“ÊÔAWi¾œMá©hB8¥’KÅHó`3¹nÓ¨h=Y1Ë›T†I¼„>óAñ>–oKK–6´ÊH¨Œ¬Ëª·˜¿7ýš¤ÎG Ry“4•ChŒáê:gs±"‰Ä›eÝ,¹ñ^€º;–5«€ ¢«š”®–¡¹ÇhÕÍ‚kÄkeîÃRg‰ïÃŽ‚_eÉ“Ÿ"O G%Yè¨~Âæ^ 圑¶ÎZb£_•ºhƒnî„¸š½²ˆø÷[ÈŽõÏ`%ïÒfw±³öÝ”m´Å >7g8‰DßáT$釰‹„ëáºävÉø»§¦ò‡(jŽ·û%²èu×7esj§RLDlkÅ×à«y MŠ´aÀ¯1´Õâùljó4Òµú¡ûˆI1žO³ìõœ îrB:A_+ÇU\Fšê$"Ä«^kS)1L¬Äo]µYã~iu&ýˆÜPÖ ?¼äÞ¶©³¢J62Ò©ˆƒ:4ÊÂ.‚Î ‹É(¸|:É;¹1 ºº2€¢2‘o¢‘¾‹ê7/!Fœau'»è0Zw3•KöˆÓÙ—hŒ Pz”j"¸}Ÿ[-9È3ÁÒ's^?Ñé%Ì/BÜÂs¯±ã#x"à¶ÏÌ&6Àù #«“µ)w Êû '¯û‘ I7"³™¸–:(#©›C´ª‰§,+ ñî7ã¸6 7>“t¿»ÔCzÓ0`|¸«©P­šˆ˜žžÁˤ;¿Ër‰(“›2á¥qn9ܸ´¿Ù‡`> Í′š Ü¥ëš<2ö$ú“µ£[Át,­¡â-kä–ü¨!þ ÀÙÅk¡ ™Î©³ïˆaªX~Ž#P:/4 ±} Ûñ;³3™ü>Á‹;SõÅ$4ˆò¡ˆËŠ´2ÆK§‡ù»+™’ ðª/àÁpÙ•Kºs@óî 퇇ûÿíl©ù´ØYÂ~Tâpˆêà²#@‘BËŸ×P»˜ÙþYà}›±•Óã·8½)“Ò¯Œ›‡ÓP½_¶Àƒ$B0ÌDºˆ’)Ó?«Ä5€˜6bËTË:¿<Û¯YyÛšó–à˜ÙÈßIÈÚyyÅÑ!‹Ý-¹|8ðV£§5$¿Ë‘‹Ìn¯äÒ(iÌ?ËÉ¿£xÊAZ¹7[ò’¼2¶œã¯¯U|ÔÎF©ï‰a}щ§2)wRÚ¼ÕA«‚JKd8‹@ŠŠžV«¦ThÐHúW=¹ðü§À}<Öå½™¼Ý´ÂÌ\É£V¸ #ʸ³Üª”½ṁãÀÔâDüŽyFÛ< ÝŸ:Ä’ß?”žµ¼U„å¯){Sm9µ»„OåYõ¡ŒWlyVÓ{7“Õš{Â1Ù™Är_dœ6ÄV^»Ü£Ÿíoó¥^%ν(]r¾ ¨˜×ñ»ܾTƲü?JÚ2™‚Q"® 2œÉÊÑ¢W¹S›c7‚DP½ ×Íò?Ë%ÒTdHc‘΂’)ÈáÁ2бrŒOÃè&PŽXÀ…Œ©”ìÈæ 1€ôÇpCÚE } Ù´9æ`] XѨ¸L¤ š¾mÎ:RÿÅxFØÍ3˜â_Œßãu0ËIn€+K‡Ò=Á‚Íá|¥·Ô ã^$‘Bc`K`‰"’(MöL#é ©«Ò)Ùü{Œõ¯ÞرRÆ®)2*&€–@8,#u¹ck• –Ë•8:\ËÃ+¥s©_8Цö:0’]P½½,€¹CND"-‹[Â-ããèšQkàѯŸU AÍ@V+ÝuT´h»UÑ+ôí{Õi2¨jÝ´ª—ÈÁ’í2áÎæ¯9ê ÌoSâö!ì"¡E%ã¼IGµ­Ìr™ É»I@¬Ömú§{æRjaù¥Ó1VPκlË‹ÂÊ1NáŒ8Õ¦’“cßæYV]® è£õÕîH·ËœŒ¯¼`œ}-ÔCç ÌøúD8}9‘ô¤UÇOÆ£¬Ð«(}-¡PŸ,¹hºB³Ø—løè(ûÉM/øþtÎEy!KÎ4b(iÜ!À°ìï2àÏI0QäÀ©!=-H»¡‘@SÚŰ9[z̺-:½?Ãþ9«3«×1-Xf¼ke9i~PgcÚÂþ¬ÄR,1 À›Q„-€ÍRŽWÜǯžaØ¿ !n.ÕE]F¼ˆœo Ãe›M$¨«Û3¤¢h%ó¼Âg€!«œì,Ä•ÎJQG¢m¥[±Ð­½>·[Ââ£8Û\FÖü ?U·íÒ¶®ÐýÚëÞææE—&¬ÝÜ«>jYµp§ùîÃ}9I‰Ö•ЄRlÁjZÔ«b¼ôŸ®)æÀ‰ÎŒÌZær“Ô GùYM‰´á°”†>®ÉØ—m²cõ$»,íÝ«_ð¬8´M>…ü§væM½¼m¨N;—§¹.?qPµÜÓ±¸VìЉÑTÈVA€%Æ 4~thh†0±‘W§¶ …WŠê–¥ù©ðÓµOì kÛÂfš¶Ž%ZÕÄÿdm7–úe½¾?ãüÄ•¯e^•ì¶r`—Æðž¼©òÔ1å^øƒWñ4p|3ùßRCˆ”Õ­àÒßBS±ý:rÝ~zΩ+!†®' YÈ UáoÁù¸oc\+ #¯FnYñ¹¼M³k`3p%væX‰Kd«†pОÓÐnóúÆÚAMNºƒÅõML›\€„eh·³ž¥µu¯ÆW œrį%Ð\´b¸çœé†ñZƒBæ!åýÄlå55)š;Ç eq Æ,s@Ê¢æ<–¥ßO|ªŽ£oCxCäs³þè/ŸµLáÅx×ÞƒÂïÌïè’•š1Ĉ;¶h‰æýnÒJ5LÏߥr»âô€›µçv¶Ñ("µA;ج nn[Z.(˜ßj{á9¶oW,ÛÎç«xò"ÎnÄ¿½×p+ ‡Ó0U—>;œÿß< ÷XÉ¢—H> ÷¬G¤Bÿ\bܪwF®¡hÙñ¹å/‹$ÄÙ?åKè&œj‹,ɦJ¡ü©ÄÀT•G S¥°Ò#P„„Ò*ÑÔ,ÿ#N«$Ô#PhàFÇô*¡«ct•$ !·.© ì » `LÈïÂ’>S|‘$ ‚d²´„¾~¦G´ðÂ4H ‘;`hö£SÁìÂ0‡½ÍQd„ÓOªÚ4¶'²«œ´k¢þŸÈâQ#LjÚ‚ÉÇûÐ'ô#G2)íTž´tòPzÖ@Ui"ʪd™4m`Π¬"LŽ=êÙ¤·uƒ>Í¿GìVºÊ°Kü¸é%9'²m<Ã(Ò ,}o6RÄÐBit´ T îreØ0),Â$UÃ0âÙObŸK£Sâ Ó $ÿu¶•ú²Ç´\Am ûÒˆáHÕD=r‚ÞÛßt#ɇQÓã èM×¢Cp¶4îc³N2,€IƒG, èâ~™W‰"Ù^ºô|KMÌ W*ÔvÌÙ0Ê«¤‰‰^2û“Éh²˜e'õ¹ 8QrSÉG¬ÖÈÕ\‚®«+¼,õð“Bw´%ê*U ëyØĤҭ0Ý€P-ä–¼Ê~àÓõ"s:Ôr"4•Íé&üëöx¢ÊrŸ|ZçóZ¤ *M¸‡âJU“EÇq¢nòÙ-´ÔRIüÀ™¢iÇö¯”¡s»ì¨¥àÛº6Ç(J²›†Æ ÖOt Þj(¦‘oºªËgîtIM†œq1LÓæúýRZ†ûÖ"Ÿìú‹lѼ?}|á4ꤑE òŸ‰Jn ¢¶2UÀK܈¼÷OZ H,9)„ ŸˆIGï;±øßéI%Me´Æ~¼RbSA/M"¿SÄpÀ!¯ÝÙ7•¾ÇÕbd,Nõ:¿—`à›Ž"ËÍØGzzÚ šLÍÒ•â¨ñàâÐzÎtûB¡úhÉY„P†"1€'ì´ƒÀ¶l³€$M4Ž¥«Bõó$õú¿$h°Ÿ‰*=äê‘R,¼bD…ve·W¦ÿZБ0èÐ$Íõ‘Œ‘ÒX¤^ÃwѬ}HÃàõLQ?(Œ„ “ ØÇú‚•«ôÍR úH£¡ƒñD±ÁqþFÓsÄY½¯ö¢›k˜ª0Ò':êÖÄsD„™&#¸?YASH&KÙÌàI»‰‘œ&RØ‘‚qT±âß’©„sNiû«@Ô„*´…œ²T$d¬^&Æ#;D·ÝbÝrH@Œ& Lžzk*Èz±ú€‰Ql”cø×·"dݥªDS­»Ä‰ªÈSLŒ~SÖ®¶U…g³U(OÇиŸ”ÌJŠjL‰ªË†Í=‰Š€ÑéšúÕ%ª(ž§ e©88Ä –ß= ô1ÂDtÓK–š7s­¶ņŽÜcEjCýÔ¼PLŸ¹Œ]ĉU3qüJåub)çü„§2ZI‹)Îcj55é$À\ŒrT%®¹vå@ Ú¢•­Ú>ú‹&ÑÜÚ7;e0‚b‚£jÚU`·3J{DEfŽu²dÁ/;œ17!Kx~oˆä=5PG¹ºQ«´Q«}¿`z¯QïL¸H°‘6ɶtä›ô˜¾ÏtÜã@>­¼ŒŒ(i)¢\£Î!*a)Y¤çÀøÆ&0Ô÷nâcÖ'¤ý¯ìBîùš†§9ƒY ‘XBº ¥Áý`Dµb‡óÏA*{Gì·2TP'§ØÑ³¬ /š%ŒÒUGM¦zÌɯ”!.Eo‘Í"‘t°ÆÆíѱs¬ÖNsæÄas.è‘<®4ÛØÏVGåršL¹E”ãt1¶r­„ˬ>Ƀ  èO!“—ï¬{rŽÐ`ˆÎBnˆó˜hBh «ƒñ=X{òײ²(®SK×M}ªdpË;<–Ä ï‘jâf—‰ ÑR¹*¨Kôv˜£5Î}ß=áÎ3.h“ŸëźÖV¦´g®àÇ‹f¢“«~§呯GGyd†”pÈïƒQ=ÜnÎ3Š%µô‹h¬à¦¶ëãËCî%&)©ÈíàúÃçJT£|)z.£uœ !?¦d‹bé„'¼À²ý£¬±:d9Ñ"ß&Ñ*\S Ôô$!*³lxëa#Á‚3>@‰_˜ºNK©âY• á‡¢J pä­—ºa{š¾SÙåEÊÍU˜WŠÚ½p£Ní…¡_!ðÖ=¬Ð¤KFǵ¡umÚ1ßMM–ëžAÞ 1Îum'4’Fëg^‹¶ÝëEO8©´Úw^PœÂ¼n <Ÿ5ÞÖú¡iÝΜ˜m—qn‡1ï‘&ƒÓø.RPØüŠ К ä‘n?Ÿî‹ôcí@¿JÎí:ýÀ¸F–"Ð|,ÔUG¢>Ñå ÀÊcÖÙ,A;Ù„›P†„n€É7-c\©Ó,¦Œ²pò€—†—H2éÉ|œB n£\Bz¿³(¦pâùJÀ)ê?.Îy!„§lÉJ‘z.r'ô̹s.Îlèo.øR'HG×]®ö¤NG"̦÷‚0ý Þ™ Ž÷‹ñ#Õq6ìYóš\MØì‰pë {ÆŠ¸(æï4:îHUÀ\P¨w¤&10Pñîk6‘‹:F©!JGêûn|ïl«?lA8"h¢~9‚"‚ÚŽo”Nªð‚êÓù8”9E(‘ls2T$äbDÉÈ‘AmÌÜŽ¸S°ûD„´ÛT@,¢~Ôêf13Ye‹r@]NAþ’«f¦$nŽ';WÿlòZøƒÁ, ´+Xnp¾íļõIC&9ʺªÒíL YÁòïl>˜ä!P\ö0Gt~·ZwOo4ŠÕ`R°“i³°û`CÄEõlõÅ0ì“¡:/!"o‚$M#m0QrDn/ #I×C40‚ËÕ£C®‰@u÷Z˜r¦Òaë;\—§R;UÏ:\PVÌI6:à,ØÚ• ¢ðÇSÛq0«[´=lªPåqB„p$ùwªñ©tqrÝ}/Ki”ZøBêúô·Še~P(|n–4† !¡©„H=hÂÚæÛI7w€µ—uÃ;bߌ?nƒnNÈ,ª lFå†q÷Èãä¦ÃhÏåÂI‡l¬¦²u7ýo`WõE~ÇìQ {~E nBë |5¦a‚pëñ:sê¿n´x,X¬ñk ØrDŠ¿’B_qGgr Êot)‚8þD<ʆ׫8Pu3F>£užL“ Î!ÿ\î­‹„2Rg\ç'ßT´¸åÃʇj n$ÇîÃrÞïI'WßY¨‘pÇÛE‡,À [Ž%¸ N£cmß°ŽƒD2²È£ì»BUo쌘rÖgظ‚ .Xy -XuÎZRIn@_€ Ò,0N‚›õËá``I] "QQý“¶ªçm5’2üz #^Ïy&Gõ",²˜qÊïËE*±ÒžÙL”Ö5/hïM ”‚|b™{ȽËá’Aô¾@2I:Su©ŸJ1¸SÇzÐO{iŠÈɇ¼¦ØýÆh•ªSX:H0¦U`stõœg ‰ ôvÄ{X£!ógJ«ZOíÇMA÷¥µç4½£qx†®ì%4$ÑecÌõYt4g qÌ‘ rI´BÒ5¢¿Õ9¨–›zks`õ׌w¦š¬bw’Ü6$_y`±!ù› I Âšë‘ ÊÌe…žÃä^Ìl“ ]Bâ…lw€³2¾Ðl„#<*ȶ "—ª&ÊC["·‡& »`ÈXب!îÆ]Ô–îŒ+ü‚h&õD„˜zk$y”®–eQ¿ÃΑíãMm¦ñËÍ4Ó¿›çõGI "A ˜Ð%¿[JÊÒ1²ŽÕµ”•^|sÞZ£òÂi¼MjÓ¥óC¶ÆßN뚨ô»1º3”Â-ɪ˜óG,…§öba|”oY“I¸³Ö ¹ $ ä~ãFGug=´¢js!‰XÃxŠº4*(Ð]åë ùkvÁTrütƒ…v3NõÄ™¦¸‡ }0*faz³‚7LG{úú{É)§iS‘2/úŽÒˆëÁò#­ÅWÐêZ“ œ™Ä7p=5YÊÉVˆFŽ—Ê§«ér"LêßšfMeJÖ@ûì¬h®>ZÌ‚%T”ò|xXš§ß±©p4ÏXINíÇ#úæ¿~ó{¬rôõ¯Q> #¶Pxø‹t¼áG‰-Õ½m£­É´Û")æÈ!bP°‹ØÖ"ë5M{kå4¾Vª¯xŽ%0æFñ¾RZ‘‹—¡FØÇ…_™‘°­©L ÑLÔš³U“µ¸v8&aÍ”O—k1Hv‘QpD2NÉ ’èÒ\m…<ÑW^Gt&[Ð"jð›-ÑQ—EqnÁ”p‹²4Sª!ðìpçzeÛ»c]Á-tÃ']%¿ÚŠrC œÙT«˜±ö½Ù)‘œ3fïNI™,òÖÁA}*(J$‘éûXÄ"ù|ÚkDˆKBûdV{‰Í¯OÔÛz0‹„«§qË3é¿{Ÿ•fÙKbwð>ˆãpûÌ3X¾±ìøHˆ²“—àF…#Á€¼lo ©áU|¢™€‚#›˜¨Ó± è…Göjˆ­µ¢{*¹„eĘD‘„‰oar°u0eÊš—VÕÃn]³öm-„Tç벬¸S9{@™+œmÒÁãí å­øLÆ\º}ÁŽú9ÂØ~ún÷S<”‘‘ëÇ€7d¶cÅZ-]ïí¾¢©‘€µÏ\$Éä-žÐ$T¡í›êgÆÙG¨Ìºp«o ©X­´x×Âqa7Z†¾ór"…‘µ=ø]Ç ”š—/OƒÂ~ò%î'?²§ÆïZ´pûqQj ñQÃ4¤ yðz‘E“C{sÀäx(µD7;{õs눸õÊ\ù?§®z%µÔö°PÏ}‹o+käÒ×¼çÈÂp ð¿'2?u î(—ÛíJJÕ¢bÿ? €4 þ…A¡€>†B€0‡ì\ ‹¿a‘#îA HààžJü•IÀr03æaCPLÞŠBSÐTþ`ù†L£±˜D©ù%†锊<ªe—B)S¨¤.‚B"UšääW¬X,0ª$7%ŠD`V •R·\¯Á¦WX|õõDìÐù-þÁ4ð“)dÊ7¦ðiD­W„Xªò[ĺªÆÌ¤°F~‘%\Ñìíîs,´Á%ÙÜø!ç±›‚h6xl²K‚è£4ÔÕñ2À¦TˆÜ»UµB£x¸´_OÝFíuëIJYÃcßÓ* Sq=ü’èßU™áB°÷o#ß%ÄÀ¼/íl‚=ëùáü;›4À?K⮆1©*ì"ÒJκ‹êf¯, ¤ Ö$j Š3©JTèC¾…*jÑü¤4É\ë¤è£G©ÈVŒ½í›ª²9çë ¿€‚ŸI+Û ì>gû36ÍÒ‘2hS´‡É‹–) aþÝ.RÊ#hÚÉ0, "d—=伋¾¨òY ©‹Âô#*D¤«© |^±¸é);!íÔ~“Êé,m*$ëÄÖ“ËIqëF5Úƒ%Èc;-1JjT„%‘aÿ0Ðh:ÙÈСý,®IdhÏ < ¨h|¾ƒ1hÛ:䟩’K&(ÆÈoÊηQH;ŸêDª•Ð*óü–, ̵WU«;Y°ŠÐ‹ÏëŠöY@j‡¶k‘%¥Q¥$¯A‰¡ Á yøí€sAúÌ •º JO ŠZ4šA{¾É#ÿ@rr®¨£H»ýJᱦ 02Œ£HÌÔò|GB؈} ƒSÖåöƒ;(Kðs ©/2å¿vËŽH<Þ•ö~¸þÄ#Í‚Á(.BOF­{½]$ôu‡"«–=‹8 D‘£n0…Mô‚ÊãÌ[mT½(${9¥IsüÛ>¹ÒGZÐ<’µì²{ TrD¦œÈp–ð†Ý™>¹1 MYýÊònkH¹÷š_:GŒ²é†Î3© ÝXIìiÉØò(Ýh*ð×é±²=@u€ÝY>¾i¯¯4}7,GƒÆ”Ò“à(Øà&G—‡³¡Q.Y óÖÛ3ÔM‹>÷Èd»Ødz¹êµøvpymGí׈']b·S26O—2 ê<^$æ"ö‹:Ÿ,Ž‚)ƺ‚HÈ¡‹Xm¸Û,å¶ÏU±\ ÒÜ]’¹ ^gÅm¸•:d ¹Øh4‹©—zÆË” .­hœâ^ÑÝJ+$ 3ô–™kÇ4ŸTCÝsM‚ðì3SBò_PüV„ž£tei<'§L‹¿¤ÜOL[E]± “Ìü–Yboì5Næô˜K¡ý,mÝ—@w¸q ²ÔƒÌð¿Cf{Ù›Èp„0Åôö[ÛÖ^%â&Ð]Z+]+mAº×œ_H.@˜éõØ¢ö" `~Ũj]dª.IrzóGèÙ” ‰ü$V^V›OÉp…×?Úk¶¥ Î£Õæ¦ÐÒºõ4³b9X©¹]Xëù%S–GªCP •{2`ýITl‚PûŠ6b²@£”mºj$FXÓ#µåýÕÊÄÁšÚ¹¦VB/«†õèñ2v„Q6€zôH(Em.R"$gâg À• ZD»QååvøÀÌûMÃHhfó"G^ß…Ö²­Z¯ÂXå‰Q„J9\Ä´î ™'†h©Ûø $l¾rrtŒÉxTt@$öÀ€ÁÚëìY'u}Å—Ù-*#"àJãP¸²Žo—Uf~ 4fŸÏòÚZ^A¡ïh÷À}Þâ CÕ’ógÀîË2êâ6F,OmU4ó'¨ó54–qm¿¬»Ð\G­Ì}ZŒgïòùcé\*§\´q›Õ§EÊb+AWçÕ¡©wjÔ¯ÙÛ•S5m¬¬®´FIQëBÀ·Ç G`¢Mü¦RLYõænyA³žB½ÚEW#™¸&è©<™ >¾°uùx‰ƒ- íñ—Œ'chHü”YO,£‚ô0sïÁw݆ùPˆ6Ëþü—eØý d8¬:f9ˆ¦P® ÀW C}åGÈ4Æ·›¯‹Hm£—Šå¾’p—–$¨¼N –åOd*z·L4õœNmê„CÂTlÐÖÃULf¸5*cjVAúç2µ¸Å©Œ³Pm¤<=,ß#È ™G îXØYV½ýÝ‘Ã"¼]Ìa±ÇXêÍYtqº„:A0ŒûW)œÏ9’£Ïmñ­†X»±Wä»SeXTØÒw$¾>‘» å\a”Sp’Ö‘ìn¨Õ^F'‘Ð+1;bÁvÍTSU#ePr¬qt†}wßæb’kë¸k|b1Â댊ŽÔtgH·ï.÷ÜêÖÛy®)·Mä€2Ç;‰Râ.Ü ´ü%Úƒ&€#€ýv§È‰¡˜ÀýØä©”QÓY$ŒœMé0„ Äãr,ã"–í!¬y0úHɈ3‰^n'ó@9s…3~#öÆ/6ýuÅ}b«z>ïñïÞòÉã÷ÓOÞí¬½€mѱ.ú8MȧlÙÀhMƒ.1 -ùh¡ùbŸú&‡Ñðà!›£Ĥ©û X²Ç6”8Ëï+v #ü“ƒBU=¯¸Ùc:c¤´T˜Ê7 ór¤™ÁB] ‹è«« ŠÞ»ƒ)7Œ ²g(Û&ã©ò„¨–ºÙ¾Sš¼:†6aë4š$Q¾œC¶ƒ¡´ÁÕŸ˜ü9ÂRëé%»ÛÚkUBÐøš™Ú„#ê:$Ê¥?ËÄù–+Å0«ì±Ø¼ÑyÁò ™3Ü»ÊOœx:Z­RGCàÝ ±3C8|kÀSo¨óI¼RVè«¶+w"#?iMž›ì¼‚ã S«¤’ð@ŠØ"€ÙŽ 8£Ÿ«»:SŸ;ê2=U³±@a—yÄŸ"4>Êól ©J&›â©v+²J¶°Ã!W¾ ×<}5*ˆ‘’Å›(~/S2'ãå¨q-F “±3C=ZÒ øÝ=у‘±U!;õœèŠ —7¤¡=¬ùˆ"’¼z „Æ´ì#3Œ‘ÄýJ¨| z¥°l\J:!™m)E:+Ð$‘o?Ú:è|›q YQ¹<ÿÄJë½1Gdw1ôHký>"B­Ú‡Näs¨põ*CymŸ}¦ã¶ |àú„NLV-“ A³ “Ô›¬…A ©R<~ d×D®O%@è°<žŠB?¦ä Asê(C…(tøEd2Ç$¬€1Ñ0TÁ U ›,•?ãЮâ¤2ds>Ì.d;TùšÉ«x2 wšiJîÉôµª-UÅ@²E,ãØTà}P ÑÓ‰Ÿ°{²I ÍœEµâ±QiÑ? ˜­q6œ¨´¢Ô/ðßN©ë¯βQM“ {É~EÉ›Pâ?†ÅÒ· ¦]غÈ!r± (»k¬A”¿}šZr´Ñ²ÚI¢ÐeÊHµwXœ8Ñ#‰“©Ñ½w€!ìÏ3?ˆ@׎jÙ«p¿Í6ˆcüžÍÔ¬yìÞhωa¢ºÜU´ ˜Ê™y¢³JÇ Ò2)j¸¹y×"êŒLDëcP;à6àÄìNËL, t¾Šá\‡Ê(¸³†«Ìœ$Èžø¯F(º‘²Q4°}_XÉ ‘Ú È Í‹ç-úVÔ%Ÿ;» ’¶A |ŒÌ«Z%“FJš]°ó™‘ÕùÑ„¾ #Õåˤ< ¤b{¬‚L Ô÷)½Z5»WhÒOt»4?̃RíÅÉâ1Ç3Â]ªÀšÑâNÒQa"Ýú-] ”» ÁÕÀdh´Ì@²¼›¸>4¶ îú™ÝÖÂáv‰Þ!Õù «p†º Û Ê 4‰Ûžµ È ߵVO°ÆÐP|ÎÍ ÆGÒ'ÃagãìˆJ §ÁË·£çCƒ¥Ö‰%8}âíð{#"ÊÍë8Odá¸í߉¦, ÂååÈ|XbÓ5HÙ±yÖ­ƒ¸ÕG‹ü5S¹V_Á®FF`»E; õî 8xæ°Ù¨°}?HÊd³Ý¡¥É(eî”`פôÂ^*®Q•Z‰ÚJûÝö7ÎiëÂ{aXLù6Î'źVQT,.7à’½Ô¥ˆE³¶ƒ^ѳ}"uÙ4U,þ_ì¿Þ3gLbeM¨ršŠ£=­Ï {%2šÕI‘‰­ÃMÉB6`9Û1$õG(]bº ~-EÇÓ+ØàØ+ ÷å“Eg>m*¹¬Ôî›àfi/niVõKnˆÊ\^7Å™?ÃLd•Äl 4¤LáŠ;à^y`ïŒ8!.Œ†^³ì³‚rÙÛušãï×”9çìðÝ{–f9$C’R*2/ôN[æÓ¾¯¿Ü¢Ô¾F¤ÑmäJû¾D%¯¶x±¦£lhЩM–K¶@î€"¤gêm{ƾ¦1ÁìÍÅ·KWÃ3¿™‡.uÿž¹ÿHUL ¤:,N|Y¸eÛ#í̲nm󙯙­Þ™4gA®‰Ñ(Eèò2Ž–Ýì?\z—ÓOõC”qìáÅfÌÜyxžÈÿ11Úqíè±¾OUïžñ3­ÉÅíNt ˆ¦fËÃkªQ€ÒyovlÂ&±Ó¼Ç)쪓EmëPÔÆÓΩY«dc@º i* ÃÌ¡œ#ë¼²‹Åž¿%ì¾;™J8ý^z\vlk:­à’DFU1%N¬ÿ#ûï]¡pÖd^ÜÏ`J†£Ú€&Ž3Å| ¿ Ûþ¢bÛ‚²¦¬¬yƒð”¶ª#ÙÜ„°å&diÂÂ|%Ãw,~†\ü‰¹#YÆÈ,ÆBA»Ý c§¸ÎªP–4ø˜¿×u@}cJ¡œDA8˜ós#âÓ+`˜ZÎõ!}/Óû@Ý?:ù‡è¼ žåÕ¡v¯'+ç`Óa¶‚6»’‡HƒëÝù_IŒòMF¶UŽ®®D6½—åe Æ*›(· Y˜ú“§E¦TâtVÓþ‘ݺ“>v(“ÃÿÁÕNf~%ýËôÂÛ]·ÁŒÐv•È›3F6E(uÅáÁ:Yá™Sù™K.%ú_ßåŠ1ÏFr»TÒÒ~°—/2ƒÖÙQ±ÜÐbÑ€Öíjs>™Á·O¤…cú_;@¥~ÃK‡·zäedÄ |è¢:µ×@Þ`]Æ­ÿ‰¸,ãÉžÛ’½”Ù#(&—ˆTìš)bæüY“6 »g«¯SdÉ›l­öñÕÖkvzíÆJ L{·0BÁb–(Íõý!”–#^{~!“ÒÀVÛ¢tn(Ò=Pj4íWÆ\‚ßô;aáæ5±e¨ò£ašˆÊ&ÔgçϰBb‡iôɈ jþˆ‡ô?Õ?iОÉÉ¿ê¸^pš¨Ax‘àŸ¢D@#£†fÎ2ʃhQG7cþȓʼno!<Ë·4? `÷¯ö™H–"Q^"¤*V¤Þ+‘îúöÐ…!?‚Wh€?`@#ú ú„!P‡Ô"PàV$ˆE@O¸à=|Hcïù$”'{Êd°èt^K%‹Ã€³8üBý~NcóX4j/7‹Í S$œ.—¿æ`ZM*g¾)ø€&­‡N_”ÐEv8ûÃ#Q¨…N!F‡Q¥/{¶§K­C¡› 6íSÞkUù½6eK§Å¢Uù-–/‡Äb&)¼j—Á2* ?ˆV¨‰lJ5,‚IsP:-OŒA«ñp6¶ß3›×â­¤B±­EãøI&ê=¨’äçÑ,,+¦Æ´Sš\j¿K’ÈäÌ0—­^@÷GÌ~§ÏšG³` ³Šþ›Æm²½ “Õc£usðKì’ã Ö¡— Ô窴´Í2.¯¡Èú´(Î n$É:Ú5 Ò ö*Òº>-R9²0àæ­È”&÷ ËóJÓ1`¸éï˸á€JJù€,L)9g⦋£OÊÖü¾§ú¿€r ü¢ê‹¼â$ˆÒ´è7¨š ž¢±”¢Ã¹¼w)%‘´®à).ªÏ²¬JÉ hº—£Î⦊"¯“"Ì6Çô²ª8È’>åI¨«F~Ío¢†‰HVFú:)qþŸ´Œ²=AnŠ<߈º£&óÜã<Æ3ì ‚L苎")ú  Ï½$(Êûó'¦hd‰V€*öŽFÒ¿[5¨ƒ´¨¿(sÇN JÒЂ2¨Õ:6à ÊÙ` sW(Êœ(ÔN„~Û¬MXA êD¬’5Jô ÔðJ]¬ò*Ë ‡µõy+QMå+ë>*ÀMdÖ²pò’à±Ê/lˉ¼,®ÄÀ à_«/Ù˜Ú_ƒ€ÊÒ>ÇÐ` R"¨dï/Qô#[SHD.›Ðà%ºë¢J‹ü¬(Bn£[ >Yc P}¿ €p¢—%-c[~©7vR„Hˆý~ÒŠ\_{£ÕtfŠä‡ëß\¹Èã;ÛïË2œÈ“ALüµ ›hÉÎc;’=ƒPløíB—Üï}ª¦ÊüH˜…ÅÆúOs¼²ß ÎÍ—.ˆt/}ÜÅi!áÿ* /¾åUÆ›ÕQº+;©² ŽÐF›ŒS–QÝf÷¿ñ=Σ;áùg YÀ­`¹8çl<!¤üÚ³¶$ô§dÊ^ÞãSÌã\»;Η&8–QÙ\˜ÃÛTë‡èWÈÜ'=†ÿðnjn†;N®¾˜¸Ø€J@~£wêh&æ¡(’$ÕȃÆ$¨\zÁU|¯›­B„Ýå-4ô×IÌ)kó¸ÁOÙ37&1’ ‚N³À!Z…åJ='ùNáùkEÑÔRý€4€ˆœ°X8LÝÅ~ƒñj¶±øÜÏy+à.*Aç¾ò—©‡-o)šŸ”S ßšëe® s’Vx¤É!|y-ír½¢“͘2§åbèIÎãcˆ¥Y룧ÖOñF!ˆ±‹žU,)QZ®™L'òZÀ|‘UÇi‰Øü 20UÏö·#@QboxDŸbsâ™…ˆ-²’·XsÝ$¦É*%ÿHä0E„AÍÂÓ`5l¸F¥WäB$Κ=öðœÒš¦“LƒDÊ©ÇÚ“$T¯¡r¢ƒÈÑ CÅ-j˜–/5æ›t“¯9íªX\Ú/W/RweVú¥•«y:¹S6ËãZ1õ¦0¬ÉË TNí.¸ÐKß‘‡b­¥§½€»Ô‰•$†wÎ…Ç>|Ü#Œ„²ÖQ»eq4ƒ:l@”òt›¦ˆØ¥¬^™IÐCä¯3[ľw­ÃËå þ§NœßJNIÍ  :ŠX‘Ê? ºp(Uú)ÜQcÎBõ%«¸—Mâ%X«Õ5ðÔwZùJüî"®bŸIàQˆüç› JH5LÑÌ ÈzƒKõ»J7 pÌÕ6öJM)µå¢§ârŠW ¸«³tѲŒÍ™¢S)WFä Š” Mt2/T]_’”d‰:2Tmen/)Û=Öü¢9LL3U’’UAÈBª²aQ&b*ÅØÊÚKOvs* ôˆùkŠ€.aÆt—"Q Çr­")jva¡$‚£Õ‚²"<µ].À6Ö‚r~m‘y7ƒýR¸å£A¤9k=÷-™ÙP«£,`RÙDJçZÀ!“ŠJ¢ZÁ2ºui­éãÓ üèð[£z†š03+]QĦ’ö‰G!r ʈ#îšGÿÛ£ÏWeo4À¹µñ$c8%Ë!E·'ðƒÎŽfµšÃ—î°‹Õ—™VIQ2£&ÁºUÚ+­H^ô°ºo‹F%yÜÂ,¦ö–ZÖ‚=_¦#µ×šÖ€[ðYª(¦ÖKûxã&T‡ŸO®,Ñ.æ ¼Ù„6Ô™ß눂ÑìvpxžŸ-Ù*?c)¸ò+3Ñô¹]Ytš8éÃI]ú­³dkM5 ‡êòx…Ð¥â2¿ZicÌN·¯àî8æë—ßËŒáhKU¢IHc :d"ã˜Ä…6Ñ'ž*S!;—TÍ+d pqw21ßhŸŒMmp#–ýéSuǶÐrUÕÀ«ÁöD/Þ W†Ö§MwNI‘QÚdMø3cxPÿqÄ_jÇ‚èB€bÊ$î$ó®9¤@5­ç±fJõˆ"ò@råHÎüR¹æüqܵù[ñö—/à›¤É5õÝ¡ÛÅ©¤É §\ê5ìb·su ]H¦RàñûÙv û1ÖQG•ã[#ïGíE¶™Ûz6mpGž`£¸Èëñ0í†0c]`·VÎ,k%|Õ™`&ûZ'j¡Ó{¶Tv—T]D9Ö[²g¡Xñ¨ÌùŽ("RIÝJ©W Ý7cL…{÷ƽ¢½~þuY‚ÅzÀùBöë8.Yâdü¦ãNTš<úêÞ]£æ!GcøïEøü†—îC·r ~iW?—óî¬ÜÏ»Ø§Ž¥ºz^e彨GÖоÀ–$í ÜyÓfd{­ p|øŠ¼Rf¿c´’ÏhéfÈlfðˆÄTE¸é–2$p$ÏmÌtÇþÃ輬¼P>š"¦ì¦¼ÜÇþúÇÌäN^i^žä¸|ªx<ɔNj&î :˨œdbf‘IììCÅâª/¾·G[m=æ2nt•i‚ïâ8¬e•GÄdÔþÇ0¦í诖¢%Ä|¯ÒƒÞu!ðBèf⾞#òäfr$,DªÏfyB¢ø$ð|–½m(ã´ûƒl B*fŒG6\g|¢Ö#D.‹âr¥MB0ˆ²/Ë©bpj¾Ì¨€Ž®bä0”eÒº § br÷i¢˜-~6ÌØ6Çn%Ž®›ÞtdþSh´*ÜtËDeöY®>œ Ýç,·CÇÇ<¥vqôâNUÈ(‚¯ÀÀÈLÖþجà\ldÈ„¸[én‡ÏŽ\Cß éÐÿPŽpnîFüêÙÌK…ª;dd16+¬îÐg¾$«ó1ÊR…JãjçnçÞµ6Dï8.†œÐx!¤NÈ rÒGÒ4ª1&®ýi Ijìªâãí’'#´Ò) ÈÂÖaóÄþ¼$<úGØÑ` Ñ €ó#Æ´ìUìy bÖ;B>½nPž.2ÀíŽÁ&+kHú"< ª¢ÀÛ°J|nö§Ñ謭…æJÂq,&nÜÐ(`&©)¶®ï±(âz¨@’ê²b‚H-dRªéPBŒ¥ÎØ®ÍÚd΃!‰åmê¿ldï0J‰Éö—oM‚ó “ÄŠqoÖ¹cÆbd1*Qé.].ð20ìMÓ0òÄê4t ÒÀ°9'°N¯¢»®`¤õ'‘ö*¤ïq®¦*dÿ ïùå觪~"°$hó$ìxŽz"±"¦ )CªŒàf­öèi”}S”BXXñ‚ÊHÆF 6=+’>’ë–1.žž 6bë0ÇgÖì’°'s:䂹OÔ?Í8Œ©ižŸüÎìÅ ì°æÄÈ* ΂Œv0R%TÉÀ ñè2³°ÌkÖ¾r‡Z¥Nå„ä)Œè˜,G)P¦­Îêº#&è¶onhs¾€„îVç—<íM&K‡r“®‰p^΄Z°¨™J—†Káþf³²ìHÀÆEÆìjës TZ.Ê Ü’²Ÿt<`œˆ *’ö˜ƒB¥"î¤a'…¾î­2B–T´»m÷bHª/è<ꢽj¿ â £Z½rÏ5gÂÇŒ®þÒª-ç8m`c)ØõælÖ ‚ÓmÔ/0~ìL”Ѩ‡ŠI'T+§"R5b#F *$æµE>ê·NñDùçòK±žN²nJâŒÖ³ _"_=²Âf!ôÊÈõí- W30"®ä\lÜVªR3ˆ\éßIA8•! îF«= Äë°6ìªn:¥«3ƒ@ž#´-n–Ú3 yGœUDä]JÒÎñ¿+R¸cm_r™‰‘S Ô³ŠŠ‰gƒMð° <Ÿv@Á*0¡÷]m€"«j$a"Ã&R–UÕê‰ÑØÃF¯TÕJ¦H‰âse]LÒ^‚®Q0ëŽÏê 5¢ÇBà iïK… .ÜþGÊñâúã[VîÊ ÒyYÁð$«¶$¦·Ò,v„®](Ày‚¬"ç@E'F­4u*%Í.ª¢÷+«*r59T^uµ=Z•(û hÆMµ9ER5§M.U%.£ªjÏjÌ*TDï!U€Ÿu(IÇc"æs§[ ‚C0hßgþpä®Á* ¯‚I?èÇ&s;gK„ìÎTú ã[´˜×iR'¾¿rPìÅÊ‘jDú‚I?LASh‚ÎŒçã*UÒ@.Ó dh*0ª·ïéE²ôýq.ÛÏPJ`æ‰6“·€ß .êp[=%J¬sfǽ´Ðv†´ •`’|\«®ë®Ó8‘¦ŸjDøT ‚ÑÒÖi"“.Å·(Îp7^'Ï÷²t¡çÿ`IT£Ï•hh`°Iã]èÆ<´E¤ÎG/IÊ}p,ÜÆÑ.¯IŒaI‚š  3‰;)¸zãø›,2{måY•‚1%D¶ˆqï„Ë9/hÙ¸ÖR‹–nv°`w²<²|üR–ëÌyªÙ5гM0×vÛs0qŨW£m᎙ qØïÒfí }hl‹>ö*áe£¤¸õʈ-©­•ä+ð>%AЭ55ÛT1w(yBìbI3PºöÃA÷SÕ\·Åc'»]O Ñ5êà¥ò_MXÚoõ·~oq%ðse†$7â•#Ç]•}0Å0(Õ´óO»u×ÓKÍó#@-l\T;E‰: 2êõ1Š QÒxs ÷>ßÉÞÀNÞóSäBóhºš[VvZ8ÆÑ&.û0ÝVž9þQÇLŒ:¥r5®ZªÒ[¼ þ; åÄ£&5¥ý(4°î?~i-‹÷¶©âS\ì\*­›¤¼RƒÆc^ÎÛAö7³Õe¿ìÆÿ_F ÖTDÿRç<Â#”éµXÖ«gTæLFÎó%*Å^µBOŒg$Cë¾ÍÓ˜à5 r÷.P€}8]¶ÿ† ¸öƒaèP  "ø”0Á ÔP~GáÑ Iÿ‘F!ÑÈì ‡F$’ˆTZ-$Ч(ûòaŽ€çi“ùõEˆ"’J<:I!I$SútŽ' ŸÉ OºLJ-‹>liüþE"¬@¤TûâÙ.…T¡RË;ìu‡MbS×üŠñ$Öe’š´v_¥D(0èuf&²€'shf Y­¿è3¨ýš}„…_¢RÊÌ’-‰…g÷Øv`|Ðb‘ŒŒHµÅ%]ÔŠê–F#ú¥îŸ\šlœ(Õ2%¨¦çøÀ÷ËÈ«6¨ôî?½Š=¼´7O†^´Ïè· IE}Oå@9+ʬÏ÷ðIüZ1®Þ¿hK â< é!‡¼Ðéb‚¾o£g¢Š;Ö(éÚ0޵ςÛ²m’È3hÒàÅ(/r(Þ®m‹ ª€M"“ ¨2vÞ«)Ú+ãŽÁNt_Ÿ«¼dóJ»@¡Æ1ã”:rl #JP2÷$Ic*=Z$Æ" ’%3ÌR)!Ë,3!޲©£ aðÞ.±3˜ÔÊiÖ6Hú~×T ¢+ÊË¢Ê<ø~2@DÅоɑì«(ðý %aý<ÃÈú²¨£±B‹Ÿ´£–¸ É"Æí§”„Šä#¯ˆKà#èGnkGÈ•X 8Ì'üìôÁm²C³3‚ÇËPÌhÖRJK5¤–‰úËÇí¨‡;‰£·¯tES¨î}ñ €N³ªÑzš’dõ+FL`íJµÛ¯}àRd ³_yý ¦43Îýh×ÞP„8…úŠ¡Ð«Ÿ¦÷ ¬¯XÕFG6 &Ð8LmA®Aˆ:žð«O€Z¤ð?Ë«ÜÞ¨qú-Ž! ç®±\ÝOg ûݧouнHF¢´#Xõïð8×!ÖïYJæøÕÕŽÛç¨f•-lèÒwnÝ9ÏšÐù“º/ºÈúÁ{ Ý¾É!åËÙ”?4pè$6°7¾Iû©{´ÇyÏ8¯eGEª\Ùù¸r©Dì;·j[Èé–!Ñ)²¦ö¤Bv`Dˆ÷=cjÊ n!G¹¶¸÷P34ü–"eÀ?¡îpµ2óP¯Í)91æèz§£(žœr‘`.e¶üÇK,#ä± ôT]T’Äa‰ŸT –™ü"NÝÀ»0_[ámnå—®ÒÒN a¨_$ (.˜’ȱàÆ¡¬€—໕°5 ¡©•ˆ¦_ÉeOQ±Û¨‚!GÙ?s §hŒD _dan£ˆŠHûëv„Yo¢@±‰$räüô‘gï"@$–!P0A öÀ)®>'åT:µx¾ØÂèKÄ ³Ã@[‡óiÅn°'êëÉa®M F’Ž›«?8O¡‡€ìÜRêMrѧedéHAk-‡þÀ†Å.Ha®$‹t©¤9Locd¿bä|£¹xÞ„¡@±Ý}¹¸ÎsHÒŠWëuɉ.w ©òŽõjýZ"á]NÀŽ UÊ™4G‘aºØ<ê ÃõmMø—Y‚Au"]dj˨–]¼!ívºôôj;ˆEõÆ;ŠU=›o2íÕ¾2ZšØÅ2g YYŸ&ZÁdÿŽ^[Ô†aTiLºXoˆ2Y^÷\¹½Tm•qHÁW`sÞ¨Iè9ÄŽ¥Å{ä±ÑUⱉÅ+Qd„Q™¡WÀ!;WèÙЪebØ’f€9¬}ë\TëUã¶‹CMAS8KvV.úZD#d€W5Ÿ¿U:F&µ¢" hŒ LGOr²«†>T+Z°j‚}¡ñz´D×¾®˜<0cÓê‡:8Ý–>{±÷¤ôâì©/Ç -.ÚiNÚòQ’’œ"gZþ«Í _b¦nÒì/•ÅfGÃöõvîÉe{( ÞÙ‹™4’뾉21¾òA&µÊ§±„Jf·Ü ƒuòQ5&¹@@u ‘•¼¤ÿ!TËÔ8j蟛ÚxáåßWi‘Á«ÖïT'¥4‡9w"À&¤s¤ueJÌç$F/ÚÆ‰Ú”Y\«€î—‘J]¢-[Š-7¨.=ÌÓŽ{J+ƒ°÷¶yØ$ÄXÆ:±<'W-GÜ{V® F"›yOo»KY‹e) içÌtFFKÞ’+\Æ7ꫦF °eä‘8’B‚œIØÐ…ë, œ&Ú¯Î1’ú€)‹ç©*tMBý€æ,`D­‚Û’$âQæ,r2äÈöOä„*<”âÎ#ô%©1ÕŒhè  €wÚe4[>8C:g*í§Þ”®·tîDêKõœÄdÁ¸"p&âr°4u¢€=ŒÓÜ•XVWVÛGh$”öCÁ- â+ù²BÙ|¨ŠÄ ‚æ¡öƈrq$Q½]#õq¼#ªø ˆ=r%Mí’þŠ9†ù*“†”Úµ~ï,«]+jŠ,치;0>œ[ŸMÔ‡zá]msS1Ë´§ùLž1vê{ 2£|ßéD'&ˆ' +”Õ‰e6ý« ù—Z™18QYÙNOgZޝŠCÑ(¯¡ŸÈRõ©Ó2§«´Øºùc{9øþÉøHÇÒÍ„•2´qvõw‰6xfÁõ‹¶OÃé«âÄu¸ëÄì“‚)ܽÖM¤ n°’ jê6¢ Æ,V|¬Àœºsù拒Ξ¼—H­‘Ë•«…2H‡ª ÍÝ^‰¤ÞQ2Šf\µtÉÈ6 ”ò^;r½ÎøŒ·¨!Úô¤¼²‚Æ£G(¨ˆ ² n“ˆ‡ ¢–«Þ÷3R©(6bõ¯‘J±Ð½< ²ý’a]7‘‚A2Þ®+ÿ8#N-ú”À˜¾ŸB˜K’88¶ ‚+à žâÂán¢ ~/KÍ1®ÑS®³æ%X°3Ì5j…œ˜Ê0Ñô©Í¤cP b‹[‰ Òs9‘=© á¤a8˜Ó÷’¢Ø—ÙÛ@I–²{ˆr7Âz‹¶qJŸ¹7ÉŸ-ñä"a²º&,8”„<®bÔS±  £cc)_Ÿºþ=‚ßBl¢d)¸Êç¡&7I‘z‰Z’EÃ2´¹ˆ€©»ú¿;ù* /®‡!±) ¬qÀƒ+Œ/%sX-2ËA¥Š€2‹‰Ú7—Kù¥ 4›áf)áf#ŠÃÄ.»¹'8»àbeÑ« ÁjyÍ·ää·ºFü0$*¬ÂÏ­³Ô¡ZCú?ªº½jÀ¨¹¥@{—>Có6úù“Jg¢Û„€*8Ç#yÀši0ál±‘…Ç“T$P‚#‹ 5Ësk“’š˜ÇòhŽ‹Ó2œÜÁ\_¸s.в32Ì£¡–Å(ãÇšµ xµªÜ鯬À€}1IZDž¼rœz’€*ë#ˆ›¨ÚvÇ£ÒH‹í²3J`-±j˜À‹s&=À–#c*"ž¤ðœ%1j¾üŒ ¡ŒÔJ¶»Á³ÅJ"&#úé(kšÚ*.œE@=²7šS• ›;а/LCb”RQ"Ü— y êÀœ³[Ô>Rœ |Hʲ©Æìb8!²ÂÝ1–¾Á€tÒ È×B±¸`¯0Ú¨ê§ÃVÌ‘c‘zÆAéߘ$˜»v¥Ôl3´< }G °áúŠ ËŠ ÛŒ¼Z L6qŸ¡K*H“6àãÉQ(¼´-Iv¸Bµ±{p¦º£6é‚O47p‡:!Îô뎡Ú%ÒöÏT¹°álªò"É·r,,;Dµ«áÿ²P}ø£I¥= â‡Üx*çL|Âx£«Âos8û<‹Ñ:«ÑE. `0‚îrø¬º‚ð›!Î’‰ÝÛn»ýKè~:#x’œÊJu³6 <>N•ÃüIÜ5(ôº·Ë¥Òþ>)¯’sÊcïÌrø! ù5ê{’tôÇñͤÐ(Ỳƒµù( ™µºwL«µÑe´õ(2í¤pÚ¡û-Ò Ž¶cyR¬ñÐQMô·¯Y? )‘ À+À44zëM(=)RØ-¬ T¯<¯¿&?X¿¥°ƒD 0¤9/ÅC€ €YtÓØ|ÈØû!ûÌm,¬0¹â®ò§Áí%¼Ü œqº kÕ¹_¨¸‹0ÄqÅ i±˜§ñÉMìÎÃT¢„¨;¬ͪz-6"â1°†/ 8Ç›ˆˆcžH9¬ºüˆ¡n‡•p@²ía&L¥K<ŒV8tû=CW¥+5’¡Ñ›âNS œ:´Gì$®±tÁÜ‚ AßÍt¤‘ýgRì¡Rß/Yv¨,+«ê9\Ũ8zX‹”ëRTH¡Ö¹3H¢åÑjö×ä =8ú/ñJœ¼}9t¹ß·ËÔaJ¨ 4”S•ˆÄcºLÍ-‰×:T0ÓõNFL{°R›Ñ.$vÑE'Â4=IŸÌIú©å‡’‰s.Õ§©ìm·4­¼gµšN#‡!CÏ›é}Õã³|º¬eª’ßBað‡ËÂzÇ€jˆcÆ£Bû1á«Ô¨žË}iE[µ26TL ÄÅ@HP;Û´¹+TqûH½ÁfW˜{׈~¿¡ì*4Í;‡Nå±U$ \ýœË¥4È0IÒË›×ô’=?¶Ã ÅkÐ’aEIŠ+« £˜`¢ÜøWyI¾|£}Ì1x–!­¥Cê@á#Á Ù ÀÑšíq_“Ô'”­â¶b‹–ë2®õÚ‡Ô_%2©µjÐ4mÞc[ˆ‰Jµz«ª¦0¨ Ê"Ú”ß`8“4{€D þI¤ò_øå[j‹¥ÑÀ’‚›7[+9Zb¥BÙÇ$üÔûP¢S—I‡/ƒÃËÔ— t[Gí ÇbU±2}Ò]@«ùÊB²>u7¼™àI™› ň‡¥ÅIE¬ªÃéÊ–«È[Õ÷:cÜ3ŠëE”„Cëæ½£NÔ{¿Ný¬ùßÇâ]½·žާ(Ú µG^¥ Æ@ÇÛѬ’åÄœõ‰¢{Kâ=ÄÒÛbÙÕÜ%}1ø²ÁDñÖz¬Úk,S`¦K—ôÏ’ –>4˜“‡^q¿¥â¹LfX1î¼Ê*´ºJJŠ`=FÎ ÖBWPLáJj^ÜDää[Œ~,º!8¿¥–Tá(Gàϲô¼„FLʪ8×TùL“ÓP³½±^+ŠYWTDmJzÛ¶5fžæY“2!A+‡FÙN†®hÖZät¾I¥ú㦠ÏÚ»¼¬•ÈWRÅ!5IW¿=ècªãÄmf.Ñ!Ľ ©˜Ž¿)xÑŠ£â3Ô|cÊË“5€&TÆÉô¤F3BÛ®3 ,¯18ªÂ”‘“Í`,>7Lº/·t£€5/Ķ:c¶49Ã3Û¤%ÂðíPdºU¢†›" c㕲á¾,:Î!M]!G†â™Å7eB_ ­ÁXêã—J³äC-UÛÄ”ûSM£| ± =N•¶Xf`f›V„õf¢^Hü Ͳ†@™f6íþŒ~Ž(9LÏ|ÕŠ¦SJÖÒ˜¯H×)½qC1W)¾§¨i&*~>OÈ- ï‘3g»®5ä¦5%Óħ+^¹{1|m¤-:6ŠL/L+‡Ã©Ù¸}¥+#új èön± 42‘×Um­  ©•ýs?ý+\eY)¥9^t(m#Ø<¶afbÕ F Ó¹ˆþpd¨Ðµ þ€D±™ú­ê.¼ÔfÊd)êˆû¯³±Û(¡¤+ Gв¤ÄÜ+«¸ÜH}é˘Ѳ`ui»íG©ô#‰bîjó‰Ä?Ë­P,‡îì¥Zö± &´ø/†äí²ä Ä®6Ó,ópIM®Ë­LNË`^“ŠÝsg ¸ø¹YtÜ47´ñEkIE6aR‡ÕÕ‹.>ªæâ£šÜ~9Y …m!\#] ª¾ÌÓcos…,>|•=äk‡i\éd¿?ʪ´EIâÍR =âÓº§cúÛÉÔÞÑLS•;7"u©f]Ð}ZlÞ³Ê7‡Ÿ1B|'–íøRÚï CfaàÝqFpÕêÛtc iÆVv@ ½j²ãJ!jÂ! Ö™›O\6Uä…–– ;Wù5•à B~o*…›I³ÞÁJëa4N-h½Ã2j£QILÀLK‰*dáºEV/dÐm ÷/9e+ÒM{»û"›­uSnÓNU&> =¿·ûV¸’½ø_ô¡•;<Ý¡-f˜ã†§h*Â=éue€¡ö„[ CM5t:âa ¦p«VÙïqÚñ*Z W‚Œ¡ôlùW Áo*4 —mvÛ RuqLïF}-ò8¹Ò½s\ó¯S嫯ÏwI–ÛÔç[P ‰\–Ö€‚a žâõÞvG’¡%ŽŒ~L’eÀÇè'SñRÜ·vÍ>ü-´P³'Äô0MƒxŸIcJCê„0Ãù€4Ì•…±ÔaLãéÊøË¥Â(§b;'¶a;%7^Ò š®<†Ãë8##Œ{UÚRÛ97”ò…ÿ™ÿ<Ì´Ÿw4Îù;=2v#嬲àÙ(<…©½”¨:ÎS`5_3nŸDÛÑuò–˜ú•® ˜ŽGÂ{¿ú­Rá‰lÆŽblqÉܹñ|aI]¨‰ÜµÊæT d茮bk³çtÕç©Jõm6æ ¾šU¹z ·¶Äê®ónË!vö2ýÙU^‘ FuøRjÀ¸‰Ë{J¢ƒºÈ oUÂöê .|£Ü”¯³{èá)¾Í6eïjüË®ï‡ò±Ã:žº³LNA‹c±»kbî î~€5â“ÒktO·µ¢ÒÐ[ɾÿççsÒ÷‚?àÐ@ÿCa@(„ „C!± $f)‰BŸ±økú‹H À9D@–@£` T}úûš&Љ|–K-ÊoÊUÑbR• Èaª(C4}Ó¢±XÈ [™PbSèUPcž>,Òô„kªD¨5U U ÓâФ"¶Ï.°IUfU™I œD"}Ã#°i f©Y¨á$Û}UM‹À§ØÚ¦ {™HaW3ëUYž=õÕ˜|C ÊÁ4Ш4Ê÷™S(›L6ÛÁD`S)õ™ñsÙeßÔ°"ÆÒ#ô¨žâ–¯´¼C(Ë?jsI «?à„ö¥ú |ðÆK õy,¾yîü}`j»ô6çûŠ**¢òð¥ob<¡IòTмHÊUŸ°«î˜" †µGÒÖ IT>ì?Ìk8“îŠ^ª'ÏX Â@Á §*£)ò‚è&ËÆ Ãøª*1#Tô¢ [l‡ Ί‚ä%²µ,Aó&ç!¦MŒhòAM˜ù&Nš%,JÐûüÀ£.R0ŒµÇ»H뮊jà ¨跲iü¨¨èjd¨ËOó¼êº´Tü'È€6àOè#ò „?á@(d ¿b@¤ý~Å¡ÑHà Ž>äQˆàMˆIdÐÀùŽf@i¤Aõ7f@ÄZL–E¨PIŒÊaK#’ÊTR!.ˆNç5”²núŽNjñ‰ÌþC#‰Oçðè´îQ´?ç2'Üb~ù¸J€s¹LR™ ŒMÔpZ©;ÙßóùÜZ1M¤Ã'rë5:?ÃÃ0Ñ8¤æ}&«ØáÐBý•â¦X+KÿH]!VY–B1­Méð`f×XÆUtȘ§ŸÛ-—­tf ¥Äa7RØ4b!$Ç?îà-ø,ºê#º§ý²†þü\èTï_–Np^KF¢w^Šñô;ü³rõE*^\²0ꯎ* ‡3È"ž¨ŠD %‰ûf~1h2ôî',âà|¿íjL‡3Bø¥¡Žz$—D*™4ª+8Çò –3Ž«´¤A ~‹%Ïê­‘Ò8ɵñÒÙ5o‘þê¢ šÒ¶+ˆü`Ñ© ¸)ªÉ»>é7hÚ|K’˜² ô«²ëœPþ0.‹¦è;K`7ˇÄ4-BY"4Ñ›¾¹C ¦ó"RÁ,I3¿¢NÊø¿Æhêÿ9Ÿè´¼¶>îi)Jkd„; KؽJðô޾Òw´ ø¢ï¾¶hÈQÄÆ>hÚ6°4$´ñdñ½c&/˜„Wdº #xÄL“ŠoH=ÐòCGÜÅ“òøKGâPaWbòµÃ®!þÛH4Íi޼Q&JH›R9rÀCýcÃÙ¡0X«ònÀSG!u)Áitïbû•mÊZ¯ 6È4|o² 4(æx]&}Äp—§#E‡ñze§ÕØ'X« <¥?°ðïÏXºú’y7ñœ&]7I½>ƒ!ëV’i5”‚”osB·$øˆd‹|ô(§šîÄTº,¦ËSqö鬵k-$²ŸË<ÓÇêñB#ñB,ÕahÄ:ÌHxD"¢É[q¹²EGd(J,®ÂwBõ¥³¿“,†wÙeâœ[h\è•õ ó«l)í‡.öú’ÜjàEŸD0âÊk›Q‡Ò^mUò WǾœhƒPˆl„7:’>œ›—0Z\;k¤õhEMè~3¾î!^'1$¶ÕZ´¸kãã²È>Ù"ó"p¤V´#ZâÌ¢:ÃXu^аþÉríHëL—‡˜é´ ‚ªµWr‰ˆûZ$äQ8ÀXíI$Ó!:nÙ‰dÎã“H¸ßؘ•Eçûл¬FW_#£ ¾È·3+Âù­T´/Å(nЙIˆ¡Ææ"=’)ò…X–o–›ìyËš—áT—#îÓˆýBDÒÕŸ{š¾ß Óµi¹7ºRiŽ€?ªö»€ …í›ÆDÑȶj™+éçÇÄ‹#1¹ƒd¤hªÉÆ|-Gƒ[¦ªÃëĽ@ºÓo;KÅ©¯Xܺ ´}Ž”¯p&.‡ÃyÒu«Z²é}ÄÑdãbÁjf‹”:6äî>ÛVR_tšêRÕÀoäÞab&‘4RÃðGíé2_åÁRØÌÓ¥šŒGhÔ”HÕG.‹b^ž `¦„/hƒ3^9,Š'²ŽªÈ»“$‰#ªÆKʕإ¡ª¥tØÒwC ®Ø,â]}ëe³hÖøª]kŒ[ÅÔ-›¸öð7©°ÒªVªNß« Åq6uãlï­U:h²]n8_$Ëþ.´¼®e3¬ÕJN•×Ä‘û¾ÈšÉ}?KŽœÖ™TÒÕ½3ÄûètNÆ9suøþ.µJZ‰m´Í D²ÅJñŠ>&‚òÑâà’¯‡ƒŠÆä<#Ä×-²Aî|Ï£¢·ƒzão:(izô¬ªð`®Ê¢Q£¸¸ïÜàŽ.ÒÂí/Öøb»¨8 *V«’bOÐ&伜æÞ¦ŒäšÍ|jŽììŠ êµân{Ç‚ÞÏä"Bôàâh}¸«NÔz8¤Â\êŠé!ú:® .# nAìÆÉF†Aö—Fb1VŽ× ­B¤åèÔPF¬$³hjN¶E°8¤èÆHËvyìn‹6Z§ªIÄÎL_duÎίJ¾Ê©0bdJ‚ÏH”ÍÎÊÌОŠê¥ÃJ;ñ$†Búé˜6•ÏFc+”ÿ¦"¤FŒ‘ƒØŽB¶ÎÍîxŽ Èä’j€!JT¼…R²¦ÜÃîµ.=lÎÖá†"ê@ÃÍÂáç=­Tìk>ýª^Râo€8Jpß"įä¦Ó¯î¦1€,GàRpŒe°P¬"'!é.¼éLb;â ™çK€¨ÂGÔµmêðnô_‘¨¶Ì̆͢µmìÀ…â%¹")ÈvçÌ®­€*î"$É@°`åÇP¦†¦:e5 † $-¤Õ \(T:0²ù(`K¼;qì¾€N&ZªdTÆ[m½˦)ö£§´ì­°ŸËL—ã8T²0@Zm$¾jÓ¿)ÊÀÊ¥”«Mì*å±®òhò¨Ìî6íÎé&EHÒ¬àŽÀ¤oJ­ ´Ï̔Қ0 6¼ÒÖD§ÒZeÎ’pHFg$®Ë(Ð` "ä~i³ NHß°ïªZEäûÅXª,†÷ði¬ â:ËäгlºÊZ‹oØÎ­*²°íË£‘3Lë4Äjec¢~íîß…pÿmÅÆD(cî¼B *2á'‚0Kω*§0ÊÕ¯Îã*–. ·(,¨ÞN´Îc¢ÀRàrdã²j³œÖ Њlž~̤.e¬œqˆ«-4¨M!£ ì—B~µ'ëà!Hîž ¢\äðr$¼½—nⶸµ=%0M&2v㦽qlm†bîs’n5ˆ\åºv Ч’xfhå0fÔ¯5 µÑk¤ÐbêM;t¬ø3Cliè°ú¸³6v ¯ b%rÍIª»iø´qÎŽ³Ã>ĸ`5B5äÒ°&ZuéRÃ_h̤>îù/×ÛÒWKmÂänŸMòRAbØdŒ"Ê}b´îMY&ÐÀª¬E¯`ZÈ_O€³ÍŽ•Ç¾–ò³pä¼Q±¡,âÅSD¹o°CÑvÄTáô‚í µ †³Ó±Hf J¬øÒ,,! ÌX•xÉóסö˜Äד_QÆX‡¶ ‹A#Ñw#¾¶¨åA-`yçxT¬ÌíÊÊ7ÞñÖüeª£+J„;—fWÎ>è r+@øõÓ_/ùpéüED=)€Ê-ìÃäXå­õ‚'Ú"ìàCç0 lŒ¢åâä”ÖÒ²èq$§Œ”¦p¦‰ –ÿq“÷P ÀX“eséá1qØ:&—*î—i0U–­µX‰u9±|&é Gm&5‰‡GŸ\2Ui@ Ot!.M=@ wÁöqÑmo¶Gއ),¦§ÄJÆê§BKA]¨aòâïò³¬LmÔmÈ #•íU¢ S#"6å± bÐÒV,1róŒãjÌLðAþ˰«VïmTTS.C–½ *óóŒOÄbV}›9,’ª”Çzû(¹XVlj¦båìT‹—`îŒû®v&#/‡v.èäÁ.¨O·u´.>ä€'7Òôí+)u»;¢s8CvH/Eq°;*ø('x-¼ÿ÷T-y7¢DâÓ–9º! n´ xû*A#®£D€¥rž1K{ôN*@§É@Báf¹ì‹‚V2ŽjxÄÎ/Nh^» u”à bNcUŽöìÆ¦”Å _fÝB¯}7*\’²y áúÚ©új&Šó¥7²/#eÓ(HZ¬—©©Ï³‹Ï}é®P¤YsÌïv(¼ˆSŸ(Ãl÷z‘ûO iU„PP"D/RäÃN'Ô€ÚVK‹7N(nèr˜ú»d¦³l>ó"¦Ž~¯m3&y‘dŒO¹VmKÛ"³ê3 œÍBEŠÊ(W¥Ú¹hVÊ ì;æÝC@ív^œÅF\æxe³{êлóõF ° rF‘ÆþNÖOªÑ1ï­t0L³»7A—ˆ˜%Ú}Dnˆý !ÈØ\X;è‡xÔ*eªóZÈ‹Q—ÙÇun‰œsLÑ.ÚPªÙ`0ʲXµ¤¨ÞÓ` 4lö𹨊ßúÄÝüšÊ ­Rµë“$T—33—æ‚ 3ÈŽ&×h¥˜&SÚZµ¸Y7˯ª•jñ*š(W’¶Âò-tó*æç¾D´ö·å§d­QÅʃ¼Jt¼ŸG¹+¼«F§?¸à×ë«i8dúMÎO ÔÕUíø¤Wƒæ\0Î5ä²Ð­ÏHr'÷R§ % ì'5ìµxL$Ù`±0Ì’'ÄÖRɨN#³}8¸J¼ÃöU^ËJ9bv¶¦&fª¤]£š¦([‡{<€¼º\2.üÙf«PWèHÒ1+ÄJEÉCq§óÜ(_eW`àsPÜ<ýTÏ,ư!X:xHë§øî/ˆ ÊI†]LÎAâ9k§h8ùÒ|ÿS0–¢uÎô¨‚xóßÊb÷ [C7ñÏÝþòR©Ê zÕÊ'¾½…ƒ vÎyß#ÐG&n_EÃy7æ/ôËž5•n¯‰ 'š º”ò;¿v’7uIÚgA²Jñ“`¯ç©Ê<ªÈBæÝÔ¡ù”X8ä;EÎûupMïBØü¬8ÀîäO›(¦(*ýÁ¦ËãzS[·hºæœB×PÏ#úש6à¤ÄÖª¬“Yñ¿ñœÐ±ÀèWµ¬òØA|ÑhWê3‹Q»þ%Q`ŠE:È»e÷έâO¼’•-b˜qy­Py»ã[áHÆðʦÜM‹¸ÓDÑ„¶ÿh#§…Íï8n‡~¶±ó3’\+sv…h²â%‘º$H ˜|7MÉ$_ošïòso.ã—‰ðcYvúË>1.;¿ømâ™lXh\ùLEWÒ Hƒ?!4. ~Ãßñ "ÿ‰€ã $&0}Çá )&DŠÄÀ²˜¬6+~¿¦8Ô–a5›Ga18Xm0ŠÉbpÙÌ+;¾ã²ÈK)Åb³ˆD6]JÎÞµUnB©Á¤°Ú &ú³Nã²èM%ŠÑä2(¬j|ÝéÑÙ¬ºzþ±€c±©¬N]NšÚâ3X¨.½L!·NO‚Md²Z“Šàà°iuþ]%Æó*´N-‡Úañ¬èj÷ÛVÁR¼ˆ-½¿Ô8gÖ® NÊç#ù…ÝòçCjOÍ.ªÉánÀ<*t6kÎMjü”×…%ŽÍ&É„w½ šÇxT}?)ýèCiÔ}œNû§ì/íì9‰#¨Þ40;,À OÒ0ß1LJbÞ¼ÈÄú3i›2É Rü‚#¨ë|ì/h{¶NJ$¢"0êvû9‰Ú&·EH¤h±A úDé€HJ…¡-;„7Ⱥ0§5‰ |ImÃR/¬3 ƒ8MVÇhj4àî2"†ÉgÂvï“ 3ÓD(¼'ë"€iÛl{¾Ë Á6(k€l}3Ñb!)ÏÊ?9C@Α0 BŸjª ð: 2Okû/ Ílh£#ïz0£©Ìr2 H«„!jbF„T ~´òAöè#lä†5ã˜ÓÏn£[Ö0ü!ñìFñª-?MµÇëfñÚ)|ýg2ÎÃg 8€ÞËký˜ÊB/½% 9])·É®%ÍÓ\ Îdr4êÉë ¦fúÎçë·ÆPÒá#SõQ¥).†Ö¯¥Ég’}µ¬Ó¨ÙNS¦éý_1˜Æ+K(Àãê0—^ñ™ÿKgû°¶Ë*Î…ìèy»»8ésäÆU°ØŒKhíh‚`þލéÜÀZ¸-P'ë…‰¢8$».ñDA¸ŸIw`—¾¯×›(ü~Ûe(ëê5´g ’4«3seâ¹Ôà#¸ž®½Â]Å Y²£c¼;fQdiÛ"/Ñ”cT×TÈ¢·ÕU"t‰R"÷c€JÊ'óŽ«8í>è~ë7©ù¶ngdƒpèþ™´íyw·ÆØxﺇ¯»O½—eîož¡)^/=µ-¢þµˆ3®D«Ùˆ=†ŽeÚÂy& 9Œ¯'ráRÙÿJ̸”—Œ¥ zécnfvÓ‰)f$Ê ç³QÛÉ*ý50F¢Ï‹3|+Èõ¨‘ÒœÀ˜k/¯\4¥) ÞrÒ‹TŒ!„GßÞV4£Áð ûaz!Jк €á—C&Gk%¢R‰“dM}Ð^6·äH¢ã~JP•ÛÅ÷Yâúf­r:‚ŽÛë~dõ¨™³ÚB>%©føç€öˆ,á£+XVî±Ý9Ì]u¬Â:˜!àd•5:&£—"ã8 )¾°µ®øHŒCQ¶;Â6È#ˆ!jÈŠ«À[ÈûiKq È‘7~bNŽíòf‘õ,ÀŽaÞo$~4Y>#i5˜uU€g &_7fùD²:sÜ®>Òá­ƒüûÞ4iŠÕë.È kÈÄñ‚åYþ(¸º±@k€>J²uáž&Ž4!‚òK å•$G„”çRùŸÌé.é½ÝQ9R•‘i "¨±çJf{)^½¬AÊøx+ £€ÊqJ:ü& ¥¦B3c[-bkÁe‡a2”s-x“.ˆçŠ<’I¼Í@áúB@u[b…Þ+G2íH#“ç0¾¿”€c¢ê¤‰Ô´Wã‡ô@$ ’©"óJ.œ)ÞžT4}&CcU¦Z™DÔ™´»€ PE!Ž”MªœSRNMsG)æº ôsc êq¸åæáP ñ©°û.b (ž NiQ÷3=ÑÚ‡'aw-¦þDf³‘Li©ØJ(ßHÑš”½=ªfdŽfg‘¨#˜n*ý•¬–ee*’ÌlÙY‰¶>ÚÄò/5›[TŽpu~Gé`[÷&Ÿe2‚ë%!e94b4Ît3"*‡´i Ö¨íg@”6LÔW¼®£ô2®v} Û—1`—!µˆI*`·ÄÔç—Ò°Õ)€Ú‰ °9#ª|}ÕqùAGêjÇ <Â’’w [¥£TÀ-HFÙ s•Äi9>ÂïeÒø$î¨ï"ñ+Ó"4ñÆ­âaTÈyÞ~î6¿jKqVÚö™¥ªêêk\Çzê!µÑÁóZ@>`ÊuéPE”øq½`ä1“[â>Úd¸Œ,«æRj¥ž\q¹z6àaúd«½·¦Còí‘­1›>Äh£ÔŠÙ¢$u ä%=×ë*Ø©#”#½Jh<©kBèz·^ÔjFqwN®Ê ‘f'ÏGÙ§j+¾SÚ®V>;Æ%üçíOLò 4õGB@û<õí„F2ÑÞå–cŽlìAÊ×}?€à¤y§3yH~ËÜ€4÷#§ÑããöÉ[醘ØÊX8³`˜ˆÐáÞ!5GÜîJÍkÞ¬òÁlÓè‘Ä+U«åãɪ{ݼ|Ï´ ˆô„3bÔBòˆšé€¦´Bäò’µ€¹P¾{èˆü?¢nÞáFõŒc‚ÿ-œ„PÍÚQ·1­%\FÊ„yêd¯«ƒ R±’ß§ò’&c»PKFo@¼A¹å£ÕpÁCä3jLQÎó Ø¦fðe‰gŒ3æ?¾’hׂûbWŠñ&¸6ŸnEšøîÒZQ°²?et‹Í#ñëšÈ¢>ÑÇJÉa¢gS¨ôeòåæ2߯à‚-“@ÜqÍx„;m‡íÔNYŸºÁe-GÓ…j„FœÍ‘nÈ«P£èÝ5ßÓ§NNuÜ/f‰—ÔjÕ5€ñ[OƒP }*ÉÌùUv¯ uÿò·ê©_®=uêïÞ¶2ê• lguIÞvLWBPìüîæÍ-¦]0ˉI…˜"ܯŒ=Yô¹™œJÊ9ˆ~5Ã…ž“2É:ê—ÉÑ¢ñÆ<‘®I§‡ÑB K?/É"'k)¢ÁY1Ãûx“¡qĤx9à㟴œއé¾J`0JËÀÊ/ +|â{Á1èÂA+Èæ Ê£ 2,(ú3 ð͉pÓ™øñÆA˜|X8C[˜ÐÓ“ z-k÷»É¾¯š '©ˆª{J/™6 r>»0‡´Ûd€"-"ùfl‹1ðHÜ“zyî>ОŸ1Æs•·`…Ž‹²—¸„›°n—û(µ™é/œ<±Ig¶››€+¾ë¹z¶*q‚ œ 9áͰÛeA`‘DÛ/2È£©ó#¹©Š´ ÃC³œ‚E—ÓÚˆ.:ÃhIá 3nÀúÕ™œD@Þ¤„ µ;¨è‘3Q5&Yî³F Q¦+h™J|¢qvL;ÛUœj,¡#ÐìE! •ªÈräÌ »àæ“¥ë –ÙôÀÂp¤Êe)šZ¹>ŒB(š†‘3ª»©´³°žÂˆÝ‹éúÓ-–¼ Ú¾ »¦Ù+#‚ !i;@¤“G":¦1Æ 3><(”²¼0KHˆìD—D ›Ät 2ºo«Ãù‡ã{=Âó¤c.µô ŸËÕ›HÉ"²ÓÇð»¬4¡È‘aÁ[œŠ‚ÈHói6š‰<£E”:‰+·CZG r»›61)›9ƒN7ƒÎ+cQ0Ó¦J9Æó–¹tŒ z\¨ï=[·Ò~ÛçEŠ#ž:Ô#úr¥aéFœ¹Ki†>°- ž³óÿr”£·<!”p”°y1rÿÁR€·)/aƘğ¥t{ÆAeœ,ƒ<´«¶»Ò"üÀ¼ê ±ˆÔ2 Áó+9# L 5r¸ „ÀtµÃt˜€! ìâÁ5ÔÄ>8¶ch˜À§ µ ´œ)+“ƒÂ+!‰&»ÔIQŽ Â¨³ºµh„0æIÚ¶%sp¤›ºšÉ66 ~2a኱G¬âÕKœÉieY¬ˆ˜ï@È’u޶Msx´[™EwCÅس2S:JÙ—=ŒêÄS`šq ©Î‰v9Èr‰–bÆáKˆøã¤‘µ”B¼#LœZd´³]Š€ÉAÓÖS¨}˜Â\F ´÷‰"iÍI'°Qà~Q ™¾ê8imÌê72âÍp!êÄ’ÚùÓd™½Ðj‰Úÿ¦˜®Òk@AïÒU0–£¾4i·‘¹ y·Ì\Ç•ˆ[@2­@[tƃUøÊO·t~OK1£"‘0—½mS¼¡›Zù½rU’!a +Í£Fñ ’‰²Ÿ€…ªqþ¨M=”ÅU²º xˆ¦J˜¥=ž­€;+—Ó\!¨ÓZ˜Pž™MKAl&ËBÊÀ‰äÕʱ{¡AžÃ:ä“a”˜ZDÔÊ–¿kᅫ¾ÁâÓ¦úa7~ЪK¨‡8òªËÝŠXíi§R‚E¡µ4 DÚJÓÉØ¬Ú.!õH|Ë/ÄÚ;¼‚<ØÌÎøü Lù*K¶›?OÂc#9œ…<±ƒÄWóÔqÂΛ­?U[S4šFYJ>¢¸M(öË—½4ɲÑDØËJÔѦJe—Y yÒLO(Mn6•)ÙKõL9×¶3ãû ØLÚ¡)X"­µÆm!”¢3W ±L™ó5„Í;X¤2)͵€â ´;%”Ñ•‘Z¢ÓË„ D­¤ŠÜCC]f€+q¼¬ÃÆ´ «_›<[ ÁÔѽÜL–T$ZÊ[éÂõ†×#jʽ]Ü`·K·øCõRRèè¥ù^MMQÝäT$ðÌA ©jsªÂÕ‰^!ìöRÛ*B°Æe©¤’W.Û²‰©03"ôMÀP‰“IJ&!xÍ£º%4¡¤Ëa¨;öÉ­HŒ“ÑwØÍ»(S°k? ´ÐRpçPà}¸ÜõÍ%ó Lñœ#!i;)6?dÚB „53+X ¹Iü—½ ˆjÿÄ››äULF­<€I©é8{ˆFÅÉ[“qŒ’íÓt+‘KQÙ—@À¾Ós{ JЇú“^DpM½ÔDS×Áᨈ…Ò„-ÇÒʰ»Í¹É[‚N¹t³{C0Íš|[Å¿TÕ׉.ŒeÂÉy¹#Í6v;ãû4œwdn«’ÈdܘëÊ•‚gK9ÿCBÿDÍ®JÉ:*2Mì”äݫҼ9Ÿµè-ñÆ\)ÊÙµ¤’¦ 0΂\ ”^̼'‡Ò F 3’¬ 0ÆIûÁ¥ÃEeDK{>`¾,ÓÐÝO ’¼BÔÈ%Pà)0« 8Ü2;ÇJNvrNÌãS¤;T,ãð«!ZÌæ{ Šc#z:¡èÛ#F”yÊ—^?&Øž¥Š½5}–š—ZûËb“DÔÖ’W_#ôH Ê©üê¶èQáÙ«*:xÁ,6špÓî¢[Á—#½rÓ:bó5b:Þ8€6ˆYº#[u4\©—†}ëÆæV’ÚuÀþ˜`mʶk0Ðäxžf‰¶†Ç¬¸¸NÉôY X—Šk—‰ðZîÈ»¬Ðñ¾ê«¡-HìÑF™È;iuc¨‘p§" Ý¢`dŠ_J1;êü5«‘ïgɳ6×l ¶/L¡xá%*GcÐê¡a.wèk>’J ¦¼oÓs2œe!×H–¡‘¥ˆlŸ•–CS‘e.Ñ.¯í¹¦‡ó4EùËÖ´ÜÍ›”zZ,´F2ã‹3Ti¦ 8/û{=@úg:äfh?k&A%§àÉ4LK>—Ы%*~G-–N1f&»-ìÉðõº ¾$T» F¤«» ~ÃXU8ßI‚k§e˜/úê=sšfsŽbé“2,' k];Ñüˆ«Ýˆ{±"Ãlà­kpˆÒm›µõ»è›L;ùDõ^õ}ûßм\‡ûâ 3äC éXö~Y„ ÈënŒŠœ)n0›J‰D[JsÓ„œbÇJ¼ä½[FÙI'ƒDò‰DQör¯Q£#éUÂ#Pc÷ ‘ïXÃåšš“tЄcp|Ýfï†å²™D^[ N“y¦\c¶,üÊ!6c(þ™ «6Ó )˜µ…:`Ya;Jfc¬îÌŽÞð1-Ô¥ ²ïÖ’¢ƒñÀãÜÂqnF°3¼©ö Å„ 5ÆÁlò„ês"¯©£XEx=ë5¼e ÝTÖ‹.rDã›ìŽ$ŸM¢\cObæhàz–®–€?J3ãúÚóo›:,dŸ)¾ÆX˜ï¯†0óåœcN »Ã°ãµ„RÝ#+»†¢I\þŒIbÅ*Ä/gÈ©4 H^Zk»¦6æù‰r;©€$9RùîEµ ¨ÀÃB9áKoÓ²ÙöúñÞ¨>÷p2 œ]ÓY°— Ūs¶z‰ò²-7w÷Šs‰ÌÛa¬Ð›À…|§ ¾P™ó(Íì!#±¼&x™œ)[ºëšÂ¹×éAõ=™›:úéAéUqºÉ\ˆÝî‚àÀXCò†_p÷ôF$ŠA¢ÀxSñóÇ@ùDø’C$ùDP }K@’ùT¡ÿ†L¡°Ix›È€Ó(@eŒÊ¥¯©óö•2•H#4”=÷ Ud§ìÊO( Íeн*ƒG‰T%1ImóAŸWŸõ¹œFµ™S%Vˆüªs ‰S¡Tz”2ƒ*‰GpÀ9e†œÆdÑøÌƒ „ˆÃ0ÒGÄæ%>‰Q!R 3X•[«ŒRùÅJ-³yd¶A}êßÓh&r#šˆÚc`®ž—(¿?$VQý°£Ú§2gG…§Œ‚zØØTJì¸d£¹ýbë(‹m$Ö}9©xX%Ã-ðÒªXxíbs@„Qèî{j‚4HSÒó9N°‰?é{0‹&JÂÜØ0͉ôó²T!ˆ²2¢¢‰”2¡³§òö‚=+‚2œ®ðúP‰'*<,ó¹M‚Ô‹*NBv « ó0Ã1hꛀ1;€K˜í8ˆü&‚@È¢2ÂÈ T„&IÜbüpj Œ°É”šIË”— DÉB•B º‚ÙÄj w5)L4¤ÌHjžÐ€¬2Õ"KñŒ,ǼïKÒ ÉK‰ü£%ª¨@BÌ4a!/IzÔÔ!qýK­„×!Ì‹|…¥­²T³QŒÓ*SÔÊ•L>s²#CV/ê\—¤ ’@œ¼K:V›®Ò^£¶ Ñ^(ï€6Ôb•E6 [?½è¢-L ÅŠ½ÖBÝÖ »Çg!S‘û#R`$֟탶Ø"JÄéÕ ¥z¹ :}jÊuè}m²Á!ZL3܆1È$›d®‰C.’"Ѭº…'Ì E) F¥?uä Ê·)àï»1¼Ü8$0—¢J•MYQ(£§:àÐ"Q#5ÅWÝ“+ÒÉŇúÕŸO2rµ+¸­±3²C„GÔ%AlÙ‹ÌVÏC©’}”ŠÃµ&LÂs¡N¹Å¦»ÙZBï°eH¥³€*Â¥sã7-UxŸÒóé31 Ç/ék˶#µÕ[P¥ëthï:ã‚Ìn[ã…®·Igö »d ‰·Zà¤Ìi ,²Žç¨ëmaaÏ lóRƒ„çtEçC¹RFL·4BÕ#s—#$·¨þÈÝÒÓÛqÕ]ò”Ñ›Š)F9WTU«¾ÖîÎóúŸ±.Þû!ü ý²KVô=~"v¢[Ssi’2äeh{å´-Ø>öœÖÞ÷ðØ6Ëx•¥ç\’˜\ˆýDˆ®IzQxm退RÐÔü s$uux&C “àN化§“BïH©-GÝÓ…f1¶H„©|ª2³àQ»päŠ2wPð\Asfð#Ò:Î& ýÜ3ÃÆÐ ‹auƒôŒ¢uÔ‚='(凸£³x_ïù…nC×›à8©Õ>¿À9QQ´8‘ôaA93Š"èBŠ R[Ê܇¡–È£{­-Î~”0©ˆdx‚Ž@‡ò°£Ê1‰-F)-–ÚGÞªG‹Q!$M¹¦&u«è9;hÅNÄå¿!Gí +MS¦©HBÈ‚4ÔˆÒÖ`R¢³}B̺%R#&€$nÔ)fÉA‰äùô©Öí&[´*P¼ŠIÖ¬æÔ;.® J¶‘¹º¡çsžrE`£€ÛD‰Ü…ÁoFåUWfŒ†u` zÙ›dYNªtĒֲȇ伨ï‡ÀE²RE0.꘰•”ÐðOsÆ#2¯œ#`4íã!ì¹ð’3S¤<7Œ1Œ}¨ÄbÛ! |„0µˆhÒ˜hø)%*Ö[9ÔGÚ2ziSŒ~Ve±D«`¥ $¸ép=–DÃ’E)FK$îÉŠ niÞÃQý)¬y,¤$Ï¡dŒÉ¦+ŸjªKªŠ(å©H+¡F: HT¨ Ó|ÎÁdÚGÖ:ªmÍ»‚‹QÜC³‘ϹC· µJa¥_Wö $¼rŸ(ä6”«Þâ|°I õ¯Éål‡ùŒ¸ÕÒó1‹2È;nR(°Çq©銤ÞKÒ+Ñ |î¢ê8óTÈ'M•›¤rOBO5R‘ÌlÙ‘ë„JQ*AÜ~ÇéîKß9(nÒ*|¡D_$ËV Vò%;Î X‰<øÉ›®ÁAÓUWY|¯¡ñ#wœ‹ÃU})À"¢Yþ¨2Q@´˜¹JQËÉŠ¼ïÆkY EêQ,§J¢ZH}Ì[FòÒû+ò‰elƒªãÉC¡–$GÝâ‘òf¥w7AN´ÉÆtÎsÀ µ“#\Ö ]§>‘-9çF„nÊ ®#æ.FS”¢-o¶æZT‘º*?´ –4Î>s ý{’“N5cœ.îf •C›ã¶o 5g¼x1h¥ÚÈsŠ;ó‚£ –L¦™Ö¡–uP©–d§Ž X‚[€ÏüG„‘=W©¾x ˜}µ^©pМùQµ5ç¢râëXI†Í DIÛ–DbñüSn<Ût¡í¨JUת G;+.¥oUI <eÿ{R¯˜½X‡ž—0¼Ûv¨çCêÇOÂ;^æ;†xfÛËÛøàýÕ ©#dW;hFü žeçD£ZÚpŠ+òB>™rHmÉøŽôpœ—$©8KI²!ÍÌvâÅ“w6ݰÂZVA\E·.nBɳÃB\姦ÝtÜ@<Ê1ôÃN°vïœ**Ùœ‡¥¢pÈ6hYé¨Ë®CZT@\‡šŒ7«§ì¥ªÝ»)Uä<œ¯ äÆo¤å)Ò}õò«ôÍ`!«„fŽæ"P⫠ÇÚ!f„$‡n"àd$銜Ų=²‰æìæeVNî¤ìͶá*”kÂ"ÿm:ì¸ÊV´kEÈ[p #¨@L@/dr¯eÂ,8«!©Lzðoú¿à jÏi!öTÂr'b$õP(„éͪäÍ4Ôbd©ÌÆ¡ :(I?DP㊿*™ ̤fLïö—ˆ,‚0ŽìƒNÄà P´û¢qÎ"sâ|S D˜PKʋ‚ʼnÜ[϶!g쇆Ðþj&UmÓÅšUCü%¤bÍ€:m€k ~`KH•pL›Î:TÈ´#ïÄÁ®ô§ ˆ|PØ_i2â8Œ j¡u9Hh}/]HÖÀ@aøæ±"BÏ‹¦œÉ/4W˸-JÐ"- Y䛇$°„ßÑTŠa%6ĵ pëc; nT[ä"²ì:lÄ,ň¸ˆkÞìíFxÅýmæ#®ØñOúÚgÕ¯;ìÑ1RrŒÐÞ‘Œ& òå*¨ÙÍ‘€- ¶%^¬©ª=#m@/òu°ø{ȦËé4?’†\‚1ºýŠ„¶âªZMÙ ¤ïk.à ¦kÃÇÐtnÿï ãÏ ·.I‡8Pìå^ö’\j&ˆ(äÝáò~DFÅç$óhW‹LÓ­Šd… íÐÑbïŽ.Õ¤´­03.‰*ÑA` <ÍŸ%3§4ŽË¬JÁ‰y Èàå¤,¤Lžn°‹Ki¦­A,’À‹ÃÜ‹Õi¦Å²ì¡'6¿ ¨ìÕ4¬<Ï}^âêõOÀ«.½b,ËcÎ}/¼ôI8Èôµ322.”Z 6@’2~éÈ'1Fò[ó Y45-HÛ%GÈdÏÀ[–µÄ´BŽW‘S@S¤oÐwN“­i'õ›¨,3 ‚ùò=sp»Q^Er¿"²’SìÃMY)Ï6©|žvõ72uÑWJ¦ÐF.‡EñÔ3'îùSBí Iyu”~Ûã\$bHÐs¼C0iMäš ª|‰\—maýj" Ók(“(Àâ$kU5)•·'Âë4L¦…:PUæìä™Èæ‰ïhú *,Be‚yÓJêç>ŸÕHÏðgçfnO=Æ„²—ò&ö?-/™XÑ´ÚÍ2ÿÃÈ Ã·C¦÷”n_’QmÓ`è=-†vÎBŸ©^^ca¢¥ Bi Nµ³Tƒ}\WË >ç4Ç7µbÜ@TÒŒ-y=b%BdƒVÖsçf¨¢UФ(% O=5´Ú‘ê39ªøñµŸ:q÷1Öî÷L‚jÌ7G—R3¸nÖ êõ^eü‘€‡5;_˜ECÍÚ“+b-‚ETΩ`R&šëôÈ4ˆsð„UŸa*ÇÁòZE_JM;ŠÈ§”í—…^_ÂŽÒâêæ !³—ˆiFÌ‹düìBUBe¦A]VpÎGÈý%çhB6á´]D놂 †.Ô.%P¼ˆ Û]ª™ ¥´•{’ðŽ×u~œ/ÕaÓžye°ø±0éÉV”­õ5$‹¿0×¹ôâS1YÒˆ"HÎòå?Ëô›rÖ…Õ<éâîA•?kÁ8ˆ¶)¤°„LG1f”{—µ $Ë:7<0žkc‡"n=Ñ %Ô—„2ÃÈÞ)Z?$½kœ ÆÝ¥2‚xoR˲[Yé4ÐÒaŽ+ðÏ™ƒ¤eº«Å³zþ·ì‹qrÉ ©[êDƒÅ>¢U{§šx×Ðf\Í×>y|Dh¼ùÏûpÙþjBn̘娎¯v_hÎøJâã§J¡5`3¶:ÎAŽ“ îâÏrƒ Ъ†“·iLÒÿPÅ Ãm¬áýn‹´{ÛTzäÐÖ1gÃÌKNÿ\#ŽM§ .£T†ìîX#.’$C`ü ^ÕEÀì…^7Ei.I_;ø©Œ î¹ùŠdG°Øq#útã:Ÿ3¬Ï—xëä¡ õ‚Y(X‡Œü5/ cuC• SÜ'zZ%ð\*‚«P™55÷IÑeli ‘F` sc6º(Èû…!ú'ÌY5z:t¡E†Rb ¢OÀ`e÷­ø¬„H ;@tv“¡–P66¬1Ölºx¼¨ÒðTgð³ ŠA kåY€5÷rRó³'C»ÌžkÁ–î•/ä[ :S¦\ˆCEç^ÌÒîXµZ|µÙYâx[%Ê×$YÏc ⫟&þ×÷ÔØ­ ]øåʲl(µÓ:ŽÃñ³‚;} JÈh¿-ŽùºŽb¥¾ùÍxúõqëõ(‰‹‚»e3UÐ]™"±Óx$‰švC·›0¡©+¸yØP ±Úõ˜¹°sMÛ¢3vw±›¤"ÃKÈSîÍ%`†̴/f‘y¾xäæ^ÍÃ…}§½p{ûˆ†…;bªlà @o7P3 ùÆ8þ‡ kbC0×Ìj”–V¹+¸#J+*¦òN§+0AŠXÑ‹óÉP­˜2sêC?U¤!÷ÞoF² ) nÔ„)Øû@Îí0XL=Ê,mîñ¹3hÚí:Éx±³ øÒSýúlR‘e̬Ýä¶5™;ú÷ªju{†…ÀZg ÜY°®Œ5qŽ(&]^ xò.Ùv:S³›Âø£ñN<|ÿìtâ¨&8º“tÜ2( Ï™ØU8Ýš©‘ƒHw4âUTUÔˆ öÖ¼Ó×"dA¶¤X•ÄnĉáÝ›ÂP-OUÁ0S°áfŠ)JzrP%\;ÃvI_C¦­àeøêX‰ò- |'zþj66ˆòPE¤ë €0 þ…A€/Èp ò‰b§ð1 }Æà@H´9ùCRY ÿ•JåpÈ û1•Å¡€y´‚-(KÀ³Ù|Åû•Ï@²Š`/Ãâè$®6û—È%¹}b ­Oæ4G¥~( †E¢ÔxÅVXÿ¥BªÐIE¾/¶Ëî’øeŽ Y!TJD2W ¹Êã´Iþ ‡>1“`> U޲Ìn·Hd¢;‚HªŒí¾gl•S®‘ܬ1ï©ÎC©Lcã*¤P%‹[û/¨ÞÀô¾£³˜ïž7ÏÌÃ¥øì•õŽèJ*1Ù$—‰QÌA¦xF‡qwßÒü@›OÑâeXxÌm×ÔoÑŠ¯‰@èO'¸é{^–¼Iî´®hchÏ!Èb:` ê#k›*ó¢Ê»¾´¨bˆ•À‰dñ=CÏNšá N1òë¤ ‹2’‚N±+ø²°êc3vš…Ê1 ¡Tòïq0iTª(zK)Ùñ½#+É $CDm%ÀÞS]Å/Tà%R°¤’JÛÐU€+º*Vb*ùèúÆ8E“Iñò‚/hUD²KhD=m%J‰P]˜v8Ê€ä½tÀ«Jˆ‘<ä q!Ž$W˜Ÿèì¦Ý¾MZ6÷;èžÖ§õÝ+2)µJÛàR â$ ‹²¼ú¥V.7*/¡æ[‰K%¸„4Ô³>ŽÅz`´MsR£vk¸Ëϵïuõq®ú¥(²nÏÚêÇnÛ‹¡dHZùSʺŸ.±[ˆÔ5H‡9ŸîÒ¢DªDèD*WVúüÄ)# Ò2œ Hå+¬ä÷€8òÈÏêmHöM{Ž•#²í,ÇuHso¿¹]ë¡a£u×øÒÆ›VÑÖ¢´í@£6ú™Ï¸öñ~²ŒNúZcwŸH²ˆŽó9g)k˦qKMJ]ÅÀª'ß—R¼Rè.¨5"”‡ÅÓa*n„ö"yKqZåÚ¯ÄêÕS=_‡mq­JQ¬bª½¤‚sÜ]p)È“x¦HƒÌ" +­ƒx‡–‚âSݯ¥7ÚFxýs0i€S XS!z&)Ó¶s-j‡ P½H”ײ©#®€’”GbéáLL‰e ®GþG_£m$ ¤UZº™ò*8Ð4¾“ÕìN˜Z¿Z•G›"1Ç«”w¨z¯5?Mro¯}†Eöí@˜Ylj÷HuJHŠ$v…!²°TÍaC‘|ÓÂ#‰é6ëvL.uº¾å+ä[ÄÅ€Ut= Òñ;ÀÞAÉHîqÄj‡ý©k“Ty# h›:I’G×GGÅ"y $O( š>85È)Œg³ PáY•n$‰RJÈc— ,&æÇ6æP„Ãð൦i&ë½f옘²'CœJü‹²=¢*ãÂ\ÛEcJQ¸ÙöT–¬KŒh69â¢èñ+q)>Èé@¢;¤ñZX¹/M#ž‰1 9Òc=Òô› ±Û’„³,ÛÊ¡Äm˜1‰y"Çü˜SILES q |ê Æ~¡™izy*¥mꋸÄB‰èdŠš €Ò3ò7+3ôðJ•QgæJŠ$X R„Í’bHyD’ë(¨µs|IBŽy£îLD0ÎÎ5,2q½¡2ÞÜIQªB¢¹Ý'H!QDˆ"¶ MŸû§å¾oP yêÕm®hÚÔÖ±`¦ÅK¦PáùRJ᪠( å’³$CJ„°¶ ,‡0qô¡IÅêâÚªhP_òS[°þz=Qýda´_HsmÄÔò ݬcÿeµn|®u š]&·3|¶t¨]id•ö‚™6b›/VÚi¯n¡1ŠÈºùWé´"_1b[€_×z/ÚkÝ=SYäKÐ,‰H¤(çúË‘¼x’¹Ÿ¹·6¸ÂA-HcT¼6’k˧zg)*}dö¬Ä—£sW³eÀ6øõ;%”KowMà~ Ó޹s»Î4ó¾¹’Ò («.à>ß‚¦Á“' ±+‘[Ô'‘V®A¥; 9Ëî¤ùÆ4›ïL:Kô/ÀœËÄ8 < Ù-CŸ€#—¢Ð}4ùÀZ\úõ=ª£4èk°({\øÆŠþÂX|¯º[Ÿ‘Ä“SÖµb2³‹Ÿè²'D4”q»( ¡&âÙ‹K £Ñ·³“Ø“Xè?˜‘¯²Q/ –£"û”rÝ®ú‰Aójž‡Û ¢Øžªó÷#< ‰C”±T”ÂÖ­Ùé-ó×0תºp2Šmûo¢Y ‰ à =°’Ê3ƒÍ*™À0Ð4j\¹AP!¶? @é £tE€0¹‰·;#h Ó¾'“²9YHóCÙÌàР;ð";c:Äl¶° š!úݱô%ˆ²ÈµEÜ™éq«Å–Sï?‰’¯!0*’%ɧ¸Ã6Ió¯iÿ‘ T“ë‹»å¤q•@Ôˆ±…6)GÑÿ2"X¦Ê x~(ðŒù±ÂfšSäHÒË ¤ûþ aç‘‚1ÂÙV¶¢ÕHì¢ú|±²•¸d36Q@9i—ÌsB²43s£"ÝÂB ,úÀ¹ÿC³å»\¤óY5‚Í£‰Ò´!¡‰ ®h¨‹ °#ò‘¦t™,ü1Ã’Ñêݛ軜KïEqë‘»4˜‹3Ãp4T³j¸!ÿÇ‚Ô%Ù£Ó6³£Zˆ¢ZN8º®úÂ9"@~‘XÌãÓ–4Ÿ<̈ˆ°âK§½s…C{­ºì ¨Û+“8¿²j¤£ãLƒ²—äÂ1[мÜЭ9n»¯QPL;sç§’Ý¢¬®Ç|zÄ*†ä:5jü® )7â Il™;ÜIIœë!<¶Ìd>ZL1Œ£H‚§èƒDô{ˆ‚‰2ã  )Eì-?ËH"ÿJql±É#uϰ~ÂümÏD`‡èÇ5Ú‰ÁÒšÛ¨ÜܶCbˆÑçJ¼w&Û0‹àðHò6¢ûüö¿°3Ô®•lÀkÑ#Ó LbÃ«Ñ ­«û üñšScÃÛ²%«9ºÂNB|x¸)"ÂÛÒC1ˆN4}ÊõB$Æ»ú†„7“hÎY"Þ¤:Û z„1©K©|º¸u,:¨+4 C¼šL©Œ¸Q‹œŒ(ž°3²¸ü“µ‰ž‘ŠÈ#Š;9Û-T¾‹â) Œûêñ‡‘»ÿÒ9ªÈyçÊÚÉ£ {܇Ê̺›Ã¯Qð³t>¹ YÄñ©3ó£3Ëh¯có‡ÍG;¢Ã¹"¼jð—ôÂR°»žÐ× af ÓþÃü²ÁÔüR¯1Aø>ø¹«ÃÿM 3™k²kÏ® ®œ1©+Ã9JæÃ+YĨ«”/¤sHYEB1À܈ ¤˜ªB×H~ õN4 ÉáÚ´úóH5T?;›ÂÎD=@ø¾Q°•M>Ov¤QØ/ÌåÀLE’gŤO‰êÀÙt‹©3ü@dëÆ­b¶Œ ¨™49 ÞA;•,”˜™P2Xí˜I Ö2²‡ä´ž±þRZw•ÃR¢Gmx,ù|Ø“õÐià.£»#›…ÖÛÃÌSNdÒ‰í!-S•Ÿ€*hJœÚ)S"E6йOÕŽMÝ©NmÒYH߈!Éñ̳¼‡Ñ>ÙÆT£’DsAK‚…¹Ý³L2 3P}RÛtZ9º×øóž›¿Ö(Ò#U[ŒAbêjÊÊe"Î"sÑÑÿ¤të—Ì`; ’+ñù5ëmD1ÍÝJC³É\v›Ü5‡Áí1\E @­k¼äî@Êë+¥œ”V¹äÙ£"àª,ß r†­Ý^\1A‰‘]E1›LÀœáJ f×¼ »#–‹œèiÚ\+å/ÔrºWÌæ<…š£ªQe‹ «#º´T“´*^³0ºXƒ }’ºAe."*ÞhÑ“K¦ÙBݹ/Pš‰³žŠ”.™¥Ë}=„5Ùa?¡…Ûÿ2©A§¾X5Šñ|ÁˆHÞ\ª)AˆèlâfO˜{™”=€9]=Ô—B{¾-\-‹ ÛÃ,Ä®¢E3£Rmîá›”’™·Äéê14®±<²Ÿ?+ÎÕœÊêÐÛDËP ]¹Ì×´°šV‹✮¯d/\šK¡øÀI4, WɨŒ^¢GIÔ: ‡”¨”4}ÚêÒF‚mÖ‹ŠÑüOTá{J$H’üÛtèª14E:£LyÿÞœ!ã ¤0yë@t‰µÐ·Ý|%ëÅP„ØÆ<ÅüDiTA™1JU_ÛùŒY tSÐíÄV…„ s÷N¼>…¹A+ÖFä˜Û¤&«E@`ê™Ö4ˆ:PŠ"•…“\"­ü°Ø}”‹MX’ð¤Q0{ /ÌÐã_mv<,ëä½tL?³…N.]d ßWA4F~E­½—©4 芭¹ÜBâüÄhÌ8¨ÀÖ ž ŽC´¾-þÒ¼;Å(³ÉÀCÀÎͤ%éq>CÜe áíaAÃ<£æj°ˆMI9)ž•@RŦݹ)=2?gv;ÐÌ= D‘ÖaK¸‡è°£ñ)ÉK VâF=qÛ¬ZÀ,¿Px}±è’ î—b@•jÿÓAKkL¢[q\ú‚â ÞÍ#2ºèf›Pn¾¼ÔF|3lˆ˜JÏR?Wš\ÇÀ‘ Ä·f¶.¥£´´¡ÖÙ«zWª%±½ÓÈ|˜+§gž¨ØéjæŒR3¸ÜîGk«‘ù#Vh{±h²ø(in®PKX­,þã-"«t˜Ûîšêô\_ýQsÄ@¼SB¡gŒÅ©»jtò¦n»r/o¸:ðÖaç‰?Â6m ™ixwJ†WXmµÚzDÚ¤tP./±˜Ã÷Vc¯Ÿó’gƬ?šjÜ;±…ë N|3þ‚‘‚ErBðÖÞ8l-B-;,kÔB/¸¹öƒ·X*ÍÔûlÅ%Ì(¤àÞ1Œø˜}ÀvxúÐÀ¿wûÇã« ¯ÄŽ…\$¿kÆ>—ñAÃiê|(}½] vm%ôwÜ© …m6Œ¨'ÏÈfni§q‰Ìà•NýÇP³Ã²fˆ‹\@€àOÈ#þ „¡PgûúáV- Œ È´^C!‘à2'‹FäPhÄž ‡Æ"1gìÖ' ŒE¥oùD‚}‡¾èSˆP†M_°ù4&‹FÒ¢Óy\º) ŒÂ¢4'Üî-‹Lâ±:d}=QUøtL o®DmàXÝÆ#}^k (ŒN•y}°R¨6 €†a¢ÏŒdN1FTá¼5*7£`)xE±ýÊÍ¡©;¦×¤·ý*©<„d*QXÅ6O;µR€û½˜•R®ð(|?Y¨Í_<½ØÏå¾r Ñ>®Keðmg”ÁE«‘fÇ—=óÁ0̺ßí—C.t«ŸFI¿‡_tà 6jè®K{T&(S޵µ *:Ú³ŠºÒ³5 +pÙ&­²H‡´‰b²” ŒˆÁÄ "lF²!ÉËPê€h³ü‡ê&ˆº(› ‡¾Èªç ³,‚5Œ‚6È"Κò´,«l½§PlšȪ2¸µ2ð2œ7®†,MòjÈ!Œ!ÿD-sb£L(#Ôº¨R$”•£›¸=G¬ìˆ²‘ÿ<¨NkЂ+’L{+ÇŽ¼VÔD2¨Î*ý/¨É¢”š¦HÜŽ¢(Ú6«C ¨OÐJâ6T” òIóÃ2¼«p ŒM‡Û  !Ó0È5TRóÔ½£Éÿ¡LañOÁýQ ˆÃšã>3˜ú-ôí&Œ.m{=e'p<<«3Ö€'É‚o¡„‚;Ö5H:+œÒŽ"¬2è³"ç 5÷∾s SÍd1Fh´“ÂNô%E-PŠÖÑtÝÑçël«O‡ÝA8ný¡'Ðó›I)n+‹dSoÛ_¡Ó aCÌR@‰Æ*Ua¢·ò­q¡pm{’MíÅ ŽÞÈ5¬ý50jÑ\P’ç”))¬ü„;*Ó‚Ñi­m&~ápU*àšš+€//Qéµ°Í{!~¡Êåpÿ¹qc!AeGò礟èÛ¢µIõþ´»Ü˜¢jˬB ·¥È{šÞÉèÛ½€§¿-œ(ËDyÈB+n]tæ<Ï@0  .Ç[Á+˜…yZ\Ò»E¼1ûØ$Pòv‡®r¼¼w¯Y×­ìõhâ°Ù çåÜ ¦ƒÜä°_žÜiÒ¼»¨E(VuçÀö³mß2>pÀoŒ6Öz_KÆhÒ d)\±ï§Ð•óbA"]¤@GÉ‚@ëÍ#æ¤"â7ªµµ±ú‹b]^%½uǶ‰ ‡ „M“»eÜÀyEî`#ÿÔ[*yª ö“¶˜–I©Þ+™ýè:ÌAÏ'ó ßÜYP}ê~²!øòRÚN"¥q¹fv½zPfé\×–¢"²óÑ#­ˆ…"4$Ê ºOvOåeFÉó×B±ˆ°ˆ]ãkajèÜ×bÌS$é…8ƒ¬vÈk*lhñª²‘ü÷_Ù+… È@qúu9 Š\´Fzè@"ÆŽ€&%T ³ß ‡5‚A“|c,n@;¦•"bY §e³ ³ÏQ‘uZ“P/Ç´Á"ÎᖾخMKG·µ‡ã!«©Ñ è¾j!"Š IñÜ0 "BÓão<ç!yd0Tä»rÞÓÀþXFö’Vébºtµ6 v T™8O!än»Š\mšÍph±'ÑUe3Ó} ¦§hG[¨lòØ•–dô-yGE¾Î¤È–££yò@Q­k9Èjz•²\8oÊÈŸÖE–DŠ2:¬©óï¤ Ÿ’óõTûóÙ ¶¯öØZŠc)™U¡µ þe•K BÚDMàŸÃÂEf,/käN ºr ìü ðÄbtX¸ºÐâì!ú! Gö’CðµHâ0üŒ2—ŠÍÐè–™oi¤5$Ч£üY@"­ÖÇÜ£¬í&¹HÙáÛø,,„ð+ˆæ¢ÏsáY½\Y”G’:w‹}'e+3ö:ÿ"Š~ 7y0°¤EE)Tê„´Ys˜°Ì!­‘éÂk_ŽtDÛYcmŒôŸS’ÀÃé!Ÿš’µÃXÚ›_”·©8h`ßY¥ 7Ó£Õ¬X–š´DÖÒ9âì]\°ÒÀõ'­ñ¯o¦¢àÏ[¸0ûΡÈìVȆ±ÅÐ>æ±wõú4S{Láeb?wUç‘·qp Ó¨çÙÙ>O§´»$·r‚ÚfÀ/+kãõŽó ÝcŠã¦‡ŽÛGv1úÚÖgÚñ=aÈnÞV 55‹(õ-nŽé¾5½^#?n-jnCcĨ·³lu|ûT×vSªÀ8Öa´¡ çSò¢2¶¥(¯â• ŠÂúg´Ñøý¾Ê€ÄNôŸä¸Œa[Ú˳ʽ+ZÉæ´#lÆæŠ±¯Bd– æ±EœÝ…–(N|ïzn,J@ãú/#¢2náG¤¤úu¬¹aøb%ŽŽaÍ6Ü+æ‚çð·‚*“OúôÏð!Š×ŽÄÖ«V$‚à ±Þ"$ì¯k°¾ˆnLIH(EqëÛ/À®PxùÚxærkîÔ@ìG,JålFe È"t¯˜ª*¨¨ª/¬èrnË€$†b%lÖfºÍ@¯¯"HÁô¬æ¾"# XÈPAMàcFÔ­lÂÀyaæ¹íÔÁhÞþk.kÏö¿J~CB2æÄÄöÃvÃÊnm °¥Ê Çh'oœ±‹Œ³C†‹NV"jte‹tŒŠþõìNxíøÂ6P…°÷NàAþò(P0ÈB0 t­j‚ÿ°˜cE¥† ?jùÅŒªã–Ä,fn–Õ,VЂŒæ!ññp+¢ YŒ+#¢Eí‚AI>墲 $BB麴Ž@†®ú”KÅdº’«á ö†âÔ£À=Cˆ±‚ÃÔ.gä+âö%VFBË2ÃN䵺ðë”ÙqE†å –i~püÄëÔÉË®ÍÆ2µâ¸òQŽñë€pHuBöµP‡"‚ø¡Ã=‘Q„þªH„ÊbËë:Ir~¸¡þXÄb=QŠž«§Žî…†©)¢öôq?#1 DÇ= ‚f£ˆ¨n3ÄÄP±&–2pÇ,Þ©¾#œÁ²nžo RÂŒôe\~C¼ñ"=#ŸÑáhlP@jÛÇû 1"²¯&)µLB"ÊtUÅľ¶(gªAË^XBçAòtÍ'€u )ìÞÅ)F7oR¤ û¬h.a¹5(ro-æâˆ*uÁöø«*elS)'dXui¤JúCÄy$Hj_%¬ŒQâèQ_4ɼEW4}¶s³˜óRÊ$òþAÏ0á+èQJÊD"æänd¢&2”/8ÓaJ/!v<çG6OŒµæ|agÈ0D$ËqwEå.℞¹åî9m›(Þª6¾14©@½"òÿÔA£ºeBç/\\LwIhY.R rкì úD%žŽÕ:8§p"Ψª.ø%ÅN†Š › D@f¿Ë”Rôù>snâNÿ8 Ä"HÞ~Qý‘déÊ 't Ç+òýl°Jål˜¯Ô¨Ìˆ`^uq©û="*~I‹EˆPÛfùT•’òTpl2šÜ«=JÊQF™;gfįZ@fB‹@ÿâ dоËB asšãÂAõ^ïr¶›M…Dñ@¯Far:ÎôyZ&¸*ɶ0Q’#r;AUR§)ƒ:BÎm7Çž‹ÄD*W‚Žª¥hÖÅ­2Æ Û`úFh|O¶®x|V¬ÃYTlý£‹Ø,γ¬ +m@ª¦9g):¥çD¬»ÈW*jSC’©Užc,F"5Ëâ0×p4_&:mË Â~Sÿ@¦#“Äáªj“ÞYq稄Þ?t_Û[•Ñ ï`ÂAúÑaúþÊ,üÍ,›²w\Eq©ŠW”Ræ˜LC!grüU^ÿ¨.õkÖ=ôº` ôp`ì 'ó<¨§O7FZú±âñ…@p=HRF@å™9·œÞÂBêª&Æ:í©<ÃBþš”^íq^tD)RfÈ+c–è˨ఃBH¢† `o…ç;ÁñD’šÒ*‰WÛ+ÊbçÒ:~I6¼‰çSB*N¤ïLRåŤîÊ~×êæò§m‹Ô×C• ó€Ú÷ íJ) ‚-H‘_­x0ÍÔPLúz0țϼ¾d?5»_“TËtóYwü° ðLà Ò"±ÑT˜7æ²Ôô"¸p.ÄéÙðŸEËøb-®- +\u%v3$ª „³³ùI抑´Î¨×(Ò¡Êú €al™+r‘Äh°uõ>ÙARß;“É¿VÄXOKžò$%ƒ7­‚íÌh£Ygã_ˆ±/lé¡ÍÁ‹”¥÷ÃÎξ3G"À:%‘_¥'@©¢5î÷ö|ÿ³è¾vðÃHÏÇŸ8P4Àó!F ·´˜ªXi‡iP #­ôx펠¶\ÃN!‹W6 ¸ýh.QTø‰ë2Cš¨‡Øo3²Bò]â•sV@\I7S“4Úò§’øgyG6Ñêvi…毶q£7ŒF_T$®XÓÙš@ »±t£Öˆ®ËPð½@t_ Ñ_H:±ÔcëŸ%bà(FÆÂ˜Ê‘ÓuŸ´}¢¹  V¡uÝ€-ôÇôaÆBL«ª¤¯;¢ŒãQ6#Ä0 ˆ£‚#…AëVÚ~ZŠ’™ ™½øaiоÏKQÏèÿ¤ŸšBï¢I8 ýTJ¥Ë” $TT<¾6T7`òxóÝ*ï[¡Ø”Ä$Ðñ)‹QŒö@ÞbÕ@VÄ|.n'v3ÔÞžQ!“e¦kö¹ÚáG T¨éGc'Ÿ¡(gù¡Nà ELP#a«»¤X‰êô«d®gÒóÕ¼»u¹­µ` |ã WÎF™€±ó™w ÌÁ â—JÈ ŸÓÿ‹ÔGix!¸ˆï7è¡ô°àN¤B¹ðÁwe>_6tFŒ©›±9#P+ê£s CzQ‰‹æƒ‘2%sFµÃ<¢ñÚG}`CÔ"rlj:HòÂa{&¨·ó§LÀ.«‹“¨Ç$VÒXœV"kjAÜ›Zc•u»'p®ÊD&ó§¬ý—¹kÆ6ˆvƒÇÊ>îZíJ<ǧ{3ãlËìýGÃÊb|èPY-¼ÍKÙO¼­™MØ3,5 ¶>o*œí3}xûB«Mš…¥ñÝ}BµlF`…l)R:ÇÖxxæ2c¯Üz‡#ºÿ€ úWæ¥-#;@‡BÐÁ§ÙÓkáâŒèæÛý-ÉG‹6bA0yÕ3ü -Dbš8µ—4¥;©ˆÖÔÐuc‚"|åß°ô€2®d8—MC^ò5îtÑôU¸äµa†h´ˆ¤=§\®Ôb2é7±¦-©©),Ä]dž»l§L­½¼Ì*Ѳ¢2!‘£U$aoG@²Ñškॎ”9pGÍ|3먔iÌ¥ªép“`¶U+‘ÙfA¹Æ]¬8®,2ü±×,1‘}-Õo[¯#ÏáÿEÄ|.¾GL æâ7д+3¦í]Xq¼ˆµyd¸€ Ö4ª¾˜¦°¬”$‘•ƒ´r7··‘ÖÁb[ …¾¬¯Tµ@Ü!ê%O”w‘ýé2kà„†8¸#¾ƒ†@yP5åÉæ}=¹.ä´#_¬;ÇvØ`*ÍZX¾PÂúÀ!XFrŹÝB#”ùh“®ÿ~îÿ­À‹Y¬2u#*n¤-WB~€8°XaYèY‰ö?¡ìÏèkO~þ…Ò2ÙÖâßþ– ž„Ù•‹Ÿ¿=gì¬ çîYè,yˆØ-:k7 ÌH‰„«^Ž5÷)(wÝ™~6}¬ýVN%ÉžŽ±IÐŽ6j­"KåÉÄý@¶ÔR!Ò;LÓ‰ùr—J)$z>ñ­ö&¾nÃ{¡ô°> žo˜Þ!óûôëV ƒ>!`"ý‡?âL‡?aQ8ˆ 9ˆDâð¨ˆI!ƒA€9TF#"À¡RçûòiFã“4 ùŸG()”MýE‹Ê©8½ü§Eßu©Q}Â¥huhü‘É#Òɰe¦N€‰Ev»”Eå‘ D*‘†*Ôʶ D¢ÐàUÉ¥î^‹‚q¬U"™]n1z ™L·A. åð~bŸV{î;²Z Öj4:œ¬A-“IEÞâÿ„>4ÑLÝÆ€÷ßB°’ÉF2‹ÐP"÷}Ì++«~äóÍ‹;0ƒpg.½ƒœ°æ_ú‰<#Vžmåª<ªyÔ°è!@¯–‚­H‰Ò'ÏœlCƒ .h3,‡)ŠCúÒM«Äê´à:Š˜¢»€' ͬ œ´l2û:À•®*B» ,/Ùþ¬²*Ú8ê:LñC*,¤½‰*ó$‰’L7Ǽ>¥Š !KÊŠ»À.°²oÊP°µPÃøî"-ºÖȰk )*²ºµ ‘CœÉ¨´Ò‰½«ü9# J ÖÉÈxÏ4¸®©²t‰¥ dvÉÐ:AójÒ•Mò"8‹½`²ì© ²dü²lå‡'ˆ»ä"òãëE¨ªí=4žÒc&´< zKª’c=> J²€ÿQÈtbK)ªu[@î̹ ³•ü:~Ø-,®¶ªø ¦Sˆr&ü©TâÔã9i¥U¸ê+³´ÛºLR™-»kòê'ˆSnɹ§ôóÞt¸û¥J]”?)â‘CÊuZçÆñL.êUv‹Mb¬¨…gB< 6ˆ‚®Ì¬ª€žR¯°Ö¨ã@Ä2¢ºäêî9O°ZPÐ"5ÖX±³– ™B’B£x(“sŸQü±³Ê‚£‘æ* øC‹¾jðéLSþ•BúX$’Š .:–Dˆ[ñþ¤=Ò8Ö¢'®Ó.‰V®ž§Ìš.®¥Fì9žĉR­ž€8tßnæPæigè®+ïgúõd×TÑú÷4Íjm€u‘ÈzÑ? nR¨ß©S\¶.`ñ”B¢Äµí¥!Ýl/óÑkÖuÚ Û2÷ÀAŽÍu*Pòåó*éíEºè( ¶ÎˆtÊXÁ—¤¬ µà#ʨÂôÆõå퀘Êk'Äù›ú&ÛÉrÚÅnŠI7áÎ pènˆ,²ä¨×‹SZÆåå%Ǽ>Ü©:_ÎÑ7TêIû(PkÁu ?Q1«9ãb? k°‡xÈBÛ“mx±C–€w ô%H¬ôrœèÿVPA=ÅÚB«9¯ÈÂÂc]úÞxN-Þµe’·KC†Ah^ ” Ã9}¤ /•Øb…bó¯_ $ÅuŠx ¬>:‚BÆÂvPº>8)°'¸Šÿ¡ái.ÉB‚i,V&Š‘¦bβ€Q/‘‡x®×)E8p 7†–$˜þPÈÓ$ÞkVër&…!‘”ÈhX[ùV} Š85RÆ…»s †ìƸï c {…Yb!²cTÁŠ.æ' ”ý#Ô8Æ.;ÆÜwˆ 2àɤ$U AÓ‘±¼°¸œÎÈâìHÐ9–„X‰ÔOìÚœ„ãc»7+$<³ràPšÉK‘\µË¡üH'Q.*?Ò(z§4•R/þBÆeÞsˆR@Rkr=0µËD´„)И88ˆÜiÎaÆæ†6TH‰Äyk5 šÔß$ qLHò["š©M)ó˜‰ÊuHM w†Ž¤ÂÒÊ8þͽ+¤O’…9(|L‰á@–t°Ïñù-š(û~…iÔÇô´*ÔÈA—Tù‹?Šf¯;…”Mc+¥ÜüÎy* ¥S˜È™GüpJœÚ'DEuO³´(bÿkä8»ƒ ØÊ): ÁúLÑôÝÐqž® ²,œæï "umy‹Ý=Pút]ÛHõ.óUÚÙårA ëªkPƒ–µ˜)Û±)ðVj°XËD¾€.ÎÚÊ"åÞ‰N`I¼Üû‰Þ#â´Ó JZ,ƒ%m%@÷XڤĘ~jMb˜–%ÄHø·SÁ*5µ¬›s”càz•9k3Èú¼Q dgåòJÒÑ:JêP'Î:v–å‰ô—š/iHIqœŽˆÏ0ðBC‚À›¸³s*­j˜ùV,¶±…yT¼\^äz”rk›åánb†¥²1âØu ̩πIû\4Õ·píb¥ü7 PSøEÑ5&дɇ‘¡•yÓ>\#çÔg]¼qM‘ªv%H@$—Z„]l‹#)lÃHO ´"™¥âux:?+ áñ’å…<»ª%}ëŠî©‹Æ;m&#†w…vžú¸tAŸQÙÒ’å€b' ìdkŽ”Çè«À9•“)§!|’c€Åh’È;œW†ÌZæmM¨6ì±*Ì^=Û¹ÁlâÅ'knŽrR t“üÄ…éfZ¨ñ–e:#šéÚ6™úúaêw}|ìB\ÊñšÒH&*u4Ç­Ô8~)äL )ùSÏÜ¢ÉÌ•8µiå&Ú}2–f$E2(˜¯ ÷Nu²ž~:#7¨œ~½rl¹ÑäÄÐÎ1Vá%ÈÎ@ÿ+í^eݸD°òxôÃb6ïH™ä")5l¾ˆ?$MŠh„J³T AÍu2ËMvVÚåQ…§WˆmLH|ôHÊ{kRh¤‹(ÖçrRÊÍj›Káì¾aÐÉ‘9äÿCš§À­vñÕq>ʸ‰c-BÓ0 ý7î' Ó/¢[.‹›¥jœˆˆÖ¨û¬:Z©aë’cƒ[Qê"YxË€yî³92ù?¹È‹C·²|BÛˆŽ’?|¡{±²x~©°’)ªò2ÙÞ>‚<ˆ£á;z┃;>BÞ2™ó)°¬‚é˜æ¼žQ!>¬?7 û«ó@9‡˪5°ž:–B0±’có38²Â*3ü‡@Ú='šÄ=#Yõ-z=' 5[½8¡/» ¡1œZŒÔU¦¢s6csE æ’*BІÄc@‹ˆâ»¸šºˆaëªÂ–# Ž5(¤ìrÇ™ M¨ò™—Ò>¡ n4d|™pÅ"\´?œš iÛˆ#Ô5.Ó½òH¤€­2ˆ‰‘Âr«)aC¥±L­‹ !kxŠt¥„j+Â¥¦ *ÃU:y°°3•#‘ºœO˜ÅHs°ˆ»¥¢œÈ»¼f€D¥Â²'>SäœHx°¤¼a&B’ ±º¸ž7ÛâÛ8:cª!$|ÃèˆGl]qÆG,Á/¹Ø¸Ÿ£dÀ2Ã0¡éŒ§UÀƒw Ö«à,£4E `òZÃŒI<YÃà…ÆtmÐì«1ê:–9qG!kÂC®ã"¥P‚:P~»i°´«)7qSL@%âÞ0™¬ ò–Ô€‘xçƒåÅ<-žQ/ŠjWxÖÍ`"º×-á•#±ÁˆŽG¥6 Pž3wDš‘H†/¤ÇaƲœK ÿUÊ_ÕÓk.Êl#3#€üÔ¸„K‘õ´Ë˜k°È£OŽ«‘6£ SŒN@8™ ºŠ ø:¸à¸äÎ:£ƒ 0H•“VñÛRÜ+ÁL”ÔJÜǺûÅØa±¹ÍžF²KÈ è>(•:äLDBœE‘Œ©;<Ìqò=rÃl "z›»Û1jQ$†ÆèN4OË9óŠ#HÈâ%ÅF;Ë.=E‰p,냟4Ð(¨ž¤ƒÚƒ1ljíX²a»TÛ—±J[Ò¼©ÙÓ±:ªó>à~ÈŠs?…i¡ÝN»ü† b» 󆼭Í+ƒK³T,LWZèªì½,A¿ÃÚº¼c:¥ YwQ7žéôŽl´V‘Vë]ÀmnéºÉ¿Ã’K I!PyZOŒê2Ì©2³¼T 9qª’dD3ˆ÷¤ÙçÒ½C# â‹‹ÞÓú!•8ž[pÉ¡ Î0™>p±¶ ê•;î/Ù^Hà¹h§R‰Ï‘¿Ô1•PÛþ›£-Ù1 ôHr¹Ü¤}D£mŸŽ5³Äu…Üã«¢ÜÎ¥«X…žQ2Þ#´éNh–N O˜ÃúÚ5’܇Q]¢4M$,K8ÊÑüºFáâÚ¢5NHæŽÊ+Ô£ç9›çV½t–1aV…ú’j⻃âmg²3‰È£þ±ú÷VbŒ-*îÒIä£2MZ-⃕+1* ³›¤ºHßðа|ÏraË2òQc>IÆ¢Klj4½xÛ¦ äîÚ=[12P±§qñG;XÙ 8Ä*Û;2€WF5â¾YãT<åOOÜW¬@ìÜ”Îd}åüz; 5Ü e¶%ùeP©aBÖD`®Ìå`ö(M<°#:ìÃ】­]äåsA›’=oÅëh­åƒ ,úHdËÜÜ?˜ž íåBY©Ÿ I°Ö'®HŸ8À­W•ÑºŽ•K]¥>0}üۨU€mgýÙ Œ=DuŒÛa˜×Ò€M!ºãÀ§+[&b=$»l¦¬uØ@®Œ¯åöC\€™RlŒ¡3S(ßW’åà±õî P§h€ŠH»d;H¹€ÜŠ@Ð5ÛKŠd¹¼º½¨êáMVHÁ»šäÇ>™®ÊØä Dv4ÒÑÆ?VPò×"uÓ‰ª‹»2LrNX´4A¸¨CÑ<ξ8¸rpÉÌ< c©}?5ÈB¯Ü˜H]M>´‹Ä" "~@\e¾kíá<Æ´aÇ褟5òÄíÎ(Óv\«ê½ ¯>ˆÄciG¾ªÕ¯æN¸ ꊕççè(=eA”j ñ•Éë–)»¢|J&ÈÕ­Vp–Lu0ý3Òº%¸»Œz¡Äâ‰ó¸aÝ‚KtíËël2‹Ë}DfKŸ† 4$3¾ÁêÞpQÝÂ^dÉ5Ä[‰Þk¡¬ŽkîñR‘ºÎ8YBKžV¯åæš$Þ¡ÒáÓžå•ÑžŒ— }o\ï¾yÐhmU2s;ž¾Ä+À¾Y„Ø¡ÙÌìP.Ž ×š«5–ˆc^ÂÙËžT“# ̲$ >2äÜϽ¿ÎékTî¡Üé@)•èCŠÙEzæ±Tr!Ôgî* ÊñÏ8ߣ¤Žu|¹‰› w ¢Ž#Eø¹ñ2;{ÀR'TÝlõÍŽ¢ƒ"<Xfo×¼ã®Íþ᤻á¢0â‘ 4nÉR{½IÞpEÛ“|w ,5Ô çPÏOñÌ*Ûá1D±é~"¼ QâC¯VÝC_êÅÇgp¢ògÆXIÞ."M±æì¬B­¹u;Wð’_¯>Åš(CUTT0ÐÀD ì‹ µ·AÒŽêœÐŽeÖÖBc%4t4C$VìÍ/-k3õ=õ‚0࣡ñë0£Œ«9 §«Åe»æÓà¶$%À»éDVIÿ´LмÙPàœÏbÚ¹pAÈГêæéÚÐGgšgÅÎ5lÌù¡ÎV¬D)NáD¢½ú¢»ë ³¸m÷ÉA½ D¾§2^Üeö‡Ó® O4l9 ›¼šžwLaú¤ôŠvº .VÏ‘¹*[vŠªð”Rùް1o‰¢ç€\À«¦€$ŒAºòÍË>kÚuëà}äA£ L–ˆ2Õ™7Õ¶G§DY!ìܽÛ&ó•?ƒŽU|bb¬˜LÄÔnèÊ¢C:"'_Ëð€<*“ÉAlAu¯#ÂùaT^^òÆcÒb3K®¯:•p#y‰òøæDŒ&ØÅOe×Á¦ãJÖú'¼ÝQºŒ™SߨØÑì,JÀS£ȧ-•`P×[š Lôͨ(•ù^µÊOõŽ ’æÍP ë†²\ç{‰ÕB¡m= ¦P\´Òrœœ‹æÏ¡AgÄÒ0½“¦…’ÅŠ¿‰€17ó¾úuðçͪ*ò¯lÅm:±Pñ5±úm† æ|^g]­¡a>â7gìÖTŠc]ç.˜‹f|hþ·4q®ÓsÛlªU'àïŽ]‘ög±‰ds'#´áÙîèiî §ˆ í=ˆ‚?`ϸCú C`@F$üŠ?âÑ(\.Ž>cа,…ï#†€¤ X³þ “½eÒ°&dúšD Ówìž}ÉañGä”C‡Ée0º$‡ÂÀ”ú4Z“LRe4 ê[ؤïòÂùC@켊‭+‹»Ý<‰*n»½î8èKà¸óÄ/kÏдÐô;à ÷ABx›Jò Éì¬Ü­zåB²±úï‹ú 'È ¿(j0¾@­,&ïtD†½òÃ4êÂ4ó@žNˆ²ù]kËå·RÚþÓüøÍ8j¼ˆ›vœõ€(àjº.EbNJz’ .ìÒ*YÈRî =- ÿRT-R‰+ŽÍvÆÓí ð72ÝkG4eáL¡k½~¥ÇªR“¡v "JÔj²¡´‹i'•òùO2JÍ+”÷1ÓÛ·,K©bB¹2{ ÖtB)Ç÷d0ýa°†*N×´É|K6¶?!D©ƒõ*O‰º°¨<Ù "Î…§2È×=é½´¤ZÛ4×eU$žj®êÊ!NêÃzYy͵ٙh€ju€[Tœ‹'šH èNª-³dqö®hŽÛ4’®ë2<‡Þu.Ÿ2ØQºäæ(j¸ÁÒ` GMĺ¦"-„ê…f`U*2GÛêûp`5Q\ç÷[µ>H•dƒ$÷%¹)DÙ@¹¼ŒHòmXÝÞ¥h9õÝT€k"ÙÔÓ¼+’bTà­EÉ*yb¼–fÒƒÈùÊØò NÞ5v?Šë©ÔZòÕá–·§žIòÅ\úâèLƲQÎ`§¥B€‘I °iog¨uLYØ{DÉÍ×p…ØäŒ‡T¦ØÒúuí1¤GÒî‰ êuæhž-„Ý!ZTy íJ°zÎÞ<3†ƒæ?˜ñOeH0„ÐPÚìq0z ¹ÂP ã tÄ„ì6‡®¹‰¤7fjž&BÉ: ñ^b ø‡ÚYHŽ/¦˜(?IKË@Éaä7ÇDÔSN[lùû'xª y +KȧÁ‚(¡‹‰r]$Q£&LBŽ[Ls1qÍ·#ƒ *fÍœƒ!†yÉ»Q1´§­©4˜Kì›SH©çÈ£z½_ûMhL)rÔȲT‰012Ŧu,ÈB|dÇ’_ •ŒWà)s¦zLº9Ÿª˜nGA§Éq)U¾_‡]—Êpá—«ìdé'Ÿ¥þØÀRVé ßI£\ÎÉä"1}Í&°§„slKæWMôM´²<}—ÇvM9kL¯€Ö4%úí {ça-)À&g„Ùô´~ÄZR1‚°ŸÄ˜y-Ù,=Íâc${R—ޤÑI3JðúHL­"#mQY h3(b£•TÚ Ë±üò;/-1¦%ƒ2Mr! ÊRy > ôËN€¥3´Ÿ¦Ímtðå—Ȥ¦Ï|²ŽçB¨9BÏ’œ Éè¡ÃòŠI4%] kG4ÿTkÄ{Ô^µ®é@+ȳ=ÔÊç!d "¥¦ò?è|`+ü‰ k4t#´VYD<­@'/b_Ø ´ÊlÞJKRVñŠÈô¡Ä’ù4W»Ö/‰ñ­€¢’—ù7´À-Ù—qépëJ.äÝ%Bè¶ë\!(0Z{€±0ÙôúIñ[G®¨ ÒT”‡¹').ûÄœ‡b–Æ¢˜YTŠZ;CÐV‘õ”Òéw02ï ã"·¨Ê(¶ú(! bq?U¹¢Èa?Ôr,rïë>‰$üŠWÓ¯…lTJnîn.€gW5gÄ Î´¤¤¤æA$›¿4~U‚`JdK=€ãýuùÂáJz’¸Þy3ò3¹7J…ä»Ùg*`S qË{Ò‘íCÀ)0nH–È9bõeíŒÊGiŽô³ÕÆNÛ*|­ô¡Ð1ô€1ÑçjU>TUæ°B ƒÖÌcðg”a?3iÜ4¯:`ÜìŸL‘Ñš¥` ØåÆ{W»Ë)8tÛn¹¶©‚¨š»5î¡\b,ªF³©_’jÀ®+I‡ŠÃø¹Œf)“!4gƒÈ((§\Re9Ë4ñ ]Âjù®º0ŽUÔ:Y–²¦wpSùˆ^û(Sç5?• °…-Š-§‰ QLnµÁ(qGãêcŠX!UæL„ØHE¬Åä†þ#­‚ä¬løglF7•Ibyá­¯Âhè²]à‘eVšdŽHÖ`?hzöYžà.e]©¥nLßW¦ZÛæÆ4-–4ÄÛG¢ÜºÙÈÒ˪BvæËoÞ•®ÙKÉã‘dж^çcF °ëáÚÿ°nJñ–E2]‚ß™zÕи¥«·ÜÚY]ÒÕ÷ÙvS­âç/ÇsHg IðGC•­Ü°œ~?g—q®ÐN uîŸå?±=ô#ˆX:¯›Oùâ,-p5Ÿ>£Òwý’“óe>g½Se .ëßgxA=í­‚€Ê‘tIÇe+h€Y³7ΗmÊ«!+Z…Ôu¬Ä¸Þ¶Í¦n?7@eQ›b¡gˆç{›9S­úvè?<ÜS¤RgJŠÈèHVà&œcâî_êg@ÔvÛcêÓ‹¹úõšÏ·æøÊÎpJCsnŸ¦ÜgªÏó?<Ýéú\=IÝ;õjò´An÷ôÖUƒA´YTÆIF¿ýO‡¸2lX ÀÈÂè¥â(EÂø®Bðx‚n‡nZãlZƨæâO8+KŽÀ ¼~¬‚}'Ä# .á㌒ô F¼Kö?®Îz"h´Aø¹@̘TNºúnzƒ@ÏaôóÄZÎ$è°ãÆìSj̺¾ï¬,,(ˆÂhú¡ü`°fçeNTH„gi`£ÅDçm;VÕ"hqBçòÚ‚ +O$ÝLoì… î½E6âJ pÈЊ®¡pID\hêÔtæ@7Š=ÈjÊË–«öªšßãæ—­Òãí§£ôÝöéi®˜/®]ËŠº'–wÏD±Ï”º0^‘Ï|û ÕEöÃÄSäzÅ„®‹ï@f¥î§*jGLZ¦ˆl6ŰÎa÷ðŠÍ*ì†OºWˆL³ÂeE„â yÌR$gœ5i²,ÔYEþ¨ \ø#@¯è˜Î‚J‚NIM\¼Œ–ãðA0¸oH‚$(¤}àQ(ìubÈãÉkf^ªˆ‚ÃÜîíJ¬¦îh­fSb`$í ŽÈò6-ê Æ ÆTºkÍït÷Ž,•à.ŒÍƒV"MÿNèkŸÌüÜ@ƒk `ÅæZ´‘x..DªB¦'Ö—0”¡$‚ËÂ)‡|¤Íd!ÿ§U„„Ñ/Bp(¼®"ä¶âÂ$ë:Ÿv… ïnV†rhC `?HÜziH¡ bþï€]"+&ñÊåîñÈ›&ä„Èw-“p®ô•R7&Høðıl<ã(ž’« ÐcôíËÀŸÞÈDF›ÆDD±&7N­p6|'“hðP±E ¢ïºÈ$ #-¤ÛÈ>˜ ¬Øê f†¨„ÂQþ*„S nË¢: ¾  ¸aèóÊÀ+ L¾E’xâËÆÚ•£—*DžòÒÍÓ8Æ¿@ ço*ËJ-8£®ãÑÜdF@²jªë*ÌŒ@ !‚9é’§„øX+àÚPD ‡Î,Žvó…@Cìÿ娮’ÖLhc:*ŒVRÔ£lo“^dMªOhjjÆ­sÆg“"ð Ø9gœ9i²çkTGHbê,ƒ1Bùöj¾²Kì]Ê7’>!êI"€k"†îÒªÛ¢<§bZŽ"(`« ›h|.ED°pv¸´VäÎ^ŠN¢Ù–¹"èT8}IæÒjypÔèÆ¤”¸´Fïl¥;t/@„É?<4À"†­Tg“¢ÕÔ<}ÌÀƒR‘7É^z¦TâóîÖÞ)\Îé4ééY*ÿBðÛ Z.Ý*S“H¢À®OñìNwDeþŽrð¢&ø”Žvé/¨3lë Öpü­F 9h"+…¾ˆ#Å„b+؇.Ï’Žô¨,îœì<Ê”ÊTØ«¥ Ýr<¬îy —04êu)i¨ªÑoÉ,å‡6rtŽ7B}µU!ì€,,|6M«£SÆçJ#1ÒjÙð\.Œn›+‹4ŽSbt0*ˆj[S‡(vö€¾‡Of@¦j“Hæ§d16ÊþeNJ“;,®9qÆE0b/2ãÕòšíxÎdÆøL¦ÔpR6c¬ø‹&ÝÅ@߯Í$ ¦fBD$qÌA&® Ër+Hš|ʘ&Jœær, `ôHW*írgg[ cΞ v…î()åÆ&B(p.¤ç²µÐ‘UCòëi´9vK µB>OŽFÕuÞ«3,.‘##q• ¡ûg–`íeIž•E…@é\WŒrˆkõäƒÓHôÔ×%:Ó?U&å] ÚVq=ç°õbøM°×)φ)Hj„Ë£¢2Ìó¾²êéVfxïmMX1å&•²âäÊñµŠ‘È-(œ–ÐYQbÉ©®yË"ôæñ#ÜÉbK$``¦ä¬UlqAv¶—HL7‚Nu¡çwÓÖ¡Pn&àx‚neB´·#aýiï°>d“ &e2ñËl¶5$  "FTõ!­ ®rzÏ«>mñ!Ì…=Š‚+"<·-@”1)L %¤+9m¶ùHM+±þ„…'€J•ÊTQUcS#\1%"MµæéÓòÌBÂwÒÓM'®»ó!*^ø,ûÌ\C m7ø)RÌâhï`W Fã{âh&)„áôÐgV‡n=yÆ™5$ ´IoI´XN )‹„¸g–¸~[ T×-XE"#CS6Ê£+f²Ï&¯Ôðµ5kl@ÖU+PNåï ?˼ Ѿ*0y&Yib#‡H­7o@XVgN¢ÓOp‡Ù 1M[òLÇ "ŠQµÅHÊ„n²´<Å` ΂_ò¥"ÉJO‘[|ïOê…>HDˆ ‚B‚)ÖZËå(‘fáŠJ-pŠÍq‚d®J”´tgÒÙr¤ä)j.¹ÀÁö%2åƒ0fŽnÝWÙH—i&¸F•TC ÒŠÕ6#ÄÄ•lRj¤J*|gИ®³#jt"—Ú.U w¥ê¯røº5$¡slCL†BòðªË$éï‰ '3EvñÙ+Î¥&àÒP"¢9â§“,×3hAòŽÇm™^A/V>E0[ÃYé’Aô&¶.Lò’œÛU~~¬š÷©h‡§=ÉöX8”Í(‰+‘¢žEÇ¥˜C¡_Ž?VM/µ ÝL|m¦íbxY–Ñ­ui+ã…ö+K~TêµvÆPµË:#ôDf#Õÿ;€YŒMf™¥.Éd™zoëK:nô®§kB.šEѲ´e6`屩s:m¤†˜Qe[TÑÞÿd* ¨Šƒ6^óss´ *ÂÙyfW¯*w˜4¦A¤6)0U¯„/Dy¬Ší†nnÏmT?¥Ž¼ðBÉb0Y'±™LôDJWl{ ­l®ýiÙyŠ"‡Vl‡‰/8j¾! 'Ùø½c·¡$"/(#Ž«‘·WîìQ.rñÖf×6ûìƒðè"D•;rÕñˆ^äiV»MƒÄFî1õ$JÖ0Lw|z.è+¬»Æ(ª ,ãn°é¶9‚5„^ù²#)§€¸ûLhy’r–îÇfÑÔÔ* ɘR_ÌìzòœøÁõšñ0 Þ ”/@ÖPÒc­´à(sg¬O~ŒaF5G,&äPÙ–”»©"±ëìBô‰P]Ì:Aí¸.i§V&DâOR÷*Â2¤Jû·¥YkÕ=(E4Q¯Á»Ñ±aøÐgÏy{ÏšL¶vh‹%êÙbõæÙ$â³A¬>R7‰ZØS+"Â.å£c¶9lÔë îyÉüË"¿Ö5béÑ&'DžÍD±¥•¡‚’ÊYÌwÜ!¨ùò|TÁ1›m½­WE /2™”®ñ²cyl¤þ¢Ëºð#Œï*7‚W‡O; ™ ïv2FYjFxíYQ1O!=ÀÊ–Ae܄ǖq‚·Üœ"¯ ¿eY2]ÈV²t‚J³Õr0EyŠ¢ž<‰ý« ב`ùh×ûÌ Zé}aòdÿŠôÑ#ïž_øŒ]”ªÉ‚x·7]’ Ø…@…"9˹^:dB¸IKrè®»DžMz5KÎEƒ±Ëa9c%à¯B첓(”¿ïò Õˆ»x Ý9ƒ2qÄÙÊWiV›3;"ŸWOwÆöÝDù=l€znŽîI2]îN6¹Ùé)Ý[õgš×>o}ñ%R鮉0+gbe[6*…yt6ÃÆíh¿ÙE­Ï‚Ò—¶E­ôú2.‚î$ógåo®Ä&XÁ¦·w Ù ó­Ö7«bºÙUrB²& öU#ÍfÖËšûI󏯍ôZ‡8Êj³* IñðÖ¦ˆò£#Zk>(Ä€˜ mª̦+cq'¥hj-/J‰ý!.í'$«pªÏ7?`EFæ²Jt:€1ÊÖƒÎJÿF‰#ëG6™þÇ®2¸J=H" 1 I«=¢µ‹Xi"t…ÃtSA:Pdf·-Š ¦ÔÎò ðJèØÒÌ$ÿ[.Piþó ±¹öÁÆH=ÄÏ9-r=3 RõŒ?m œY(òx>‡cÌ ssB·ï""9±s%¿túõwIKj0ÐWz0ªÅ×k³9ÍØ[ ŠËÈš•ÖGô\¥KÊ•o¦¯p laêef£4Hk´Â®.؈ÅÀ):'=¤¶:¨ˆXêªjKÕÜVÐÀ¼š¸ M¿WCzõ¯r³ÔôݱkcØØöªØö*]mÒð¼`L’@¾Gõ@œ$êS™6Eî¶³Ü̈Yà6l˜¼é=¨ì%ÖRšå^gìV«6ÿ)7¿t"=WjøÄÖè¯KÔ÷~cµæµŒÕ•W2ªÍ@I1UCÔ\Qv }ó •¥Öýv ~ZQsÚ6ëÇ'S ¡ ð½ŸNke~!=u@ºUÍê*¡Ùˆ9íörkÕcW¤–‹šÅù>ÐíºõñÙÜgéžy.)ù8S†BV9K(Éí¹ÇlbY ý*¬¡Ñø«š$lÊt "Px‘t,„Í©rp¡LaŽ©û•Â*lRÈþe„Aé­7ΛSˆtK¼§—RG‰:ßÌ ˜ÀðþQ<+~oiôD8WÇâ[`ëm‰¦ÑþlXÉH&E|‚•V±Êß(ÌY_€S.A^ƒ~WÍÍ'ìÞÌieä6“‡}‚Z49ÝD˜X÷ˆÁ· æéѲ7Ésœk j.uÖLÒài„ù˜ž–Ù£.(™¹È•z>Q1lm$Tª® 줱µCdLjʶV{ÑÄF‹£¹’N(ô}M¨1ð¿bÔ!©yzÃÑû Ð(•¬à½FP Ÿd²RpàÝè4¹Ù»½q/‘þ7dÆWðLªj3'"Ÿ¦)1Œa¢1þ×¥Œouk•#ù,ÂÎlŽDa=½ Ò÷˪„Mªž’fŠ F衊&æˆKà}ÓJt0çHÖ¡‰Ue(óÏ…¤Éb¬ù%RE¼å…”’æ[ òËóE[¢å‡äEÓ¿ãAˆ;„BÑÝ.SönHäÌ—ÀkEâ·# -{¬F…ÇØnÆ©S¶¢(26¯áúE§Ù 6§î@1©ržÜ:gÀ “8èQ¦™hSž'š½U‰ñµ\Q]ÂÐãŠÊ ¤Ü=Áh)#éÅËÒ´*ùüY«Ì³mÙoº²FKô‰°ƒ¦z“;KH«ëZÅʸÚQµŒ½ÃÏ(Ê줺dšà@³h¦À­¤˜|˜©¹Ih½$S±(}BT¥xåú´‹ªM4ôŽ#êXÁø¥*ò#²‡Ê¹£$kÈ\i2Zª1Ùÿ-à˜¬¾(Œ)Æ|ËŸAÒÉ»†¦ddžap¡YŒ™¹º¨»|=ŠÌˆ–Áj0xƒÈªU†«™ kø9ÓïJPˆ0Û‘BIQ´Úd˜Œ GË´3ñR¢ ýˆXÚ« ˆØ¢ é Z†GX‚ø·„B£fF3G“ YꛚãÈ2Ѥë&ô¶ËèEÒEE RÀ‹´¾a|Â`|šè7â^Këé2§ Ï)¢—$"¼¼q$–Œ#H!΢؈=“úÝ7œºDqÄ ~  džÜ%¤+­Æ:Æ‹sÖÍbÑ–£ý !q0+äká"òðKy¼SÚ4 ¡š$)µs Œj·IÄDºÏ:3­ tߦaªã+ž‚ hŠÛáC+hÊIs Øœ:k -j(zè¶Z^A¤Ô·£%Nl}*"ð¾ð½ðª¡uº²€ ‘'ajE™ ‰9cÏò<2G£|['M)‰Ò˜‡Ù/Ò^4š%&ÉÄ ’»ÔYºkÅ ê<ÂzIòŸ²êRÑ]«ÊKEC )R7À3à ÊX C —Y= 9݇À¬Ã D¢¢hh²’®hꞘÁ͆°àŠÌ‡µ¼¨ ŒÉ1C¹Õ½Rˆº'«ÂÀÙ;5R9]Ä‹ ¡z‘®ò-¬Ý9ô âÓtä.‹ÍÂÊÓ0e8(B€?²ºB ¡}L¡]€È`æ¤[F7š›t¹’JfBP3 }2 }(‰ ±1Ù “r7Èý{2pó¬œø:°Ãê‹Ê]¬3´!zˆ®‰ò?ë¡–…5ˆ³FàЄDéé8ÓzÈÀ~¢„cý}̘|ʽŸ£ƒD“³²ó%˜¨z…<Š—˜Ô¡Ð-JEKHP“±<­üW¾Ky ì™ÚòÍKÚäÙÃD;ˆ‚º0Ô ÚÍÔŸ¦"ª\ôØ,HLE¢Z£·'}!ã@[Ä·O@5Zç\«„Ó5 ûÚ¢hDT›%«¥Kb@g¬\#ÊÉÄZC•'4´Í?€`œD"xœ4á¹úNAÎO µ²*Xƒ´£|ïØÔRÌP¯“ %—C“œñƱ7H¬eÅæÔxœ4›Fõ)IÚª[ƒ?RzÃÃRK|$¹4bt‰½ÒˆÂ\²¹Œ§™¹¤EÖT´¢C}!;б›yJc$¾S[-‰o^…Vä–$£ Ò‹•u̺ˆ“Ù©„hÏüÃr8)ÂÕ Êd»jÓÊrÈÔÈPC·NêžF…öé=ÓÅü¬œ¦ží’Ð’×ð‡ž‰(Ჸ¤ ]\ÔðœK8íX€?»€·"ååÜÈ¦Ý 9²¼šËc[ ÚõH*ª‘‚Óí,-dPbY8ÝsÑ¥SªJ5]mb }!…‰“ts9jÔáèÕ_HaZ¶ ™v6aâ ³È:0“šôåùýG =šh’1Àź6._1Ã+ P=ÔÓ™cÉ™›ÚÀ}Áùú¥tv0”¡Ù©:ÇÍTιx² QcÔÕ¶tíLU^#B„UÛ&YèË:e¨ ~ÕùW>´§ˆ«M8-1¸Ò­©ÃaÍU~&: W»J±u%þ¶½*€ Ž›ª=VéQ੘«œñ({ÞšÔW`ªh`Õá{Ï+ƒ«”d bˆõLˆžûUô†’¼Ò#÷´2ç§ÐŸ-£CÆ:ÜD%Q™æöF›ùÛfL£Eì5ݰ¬<ÄèÐÅ -Ç 2ü`>S¥×ú*/Õ­`ñ¿¸ë+ŠU¦ÃíMJÅßÉ †ÆÌÆHœVðæÍÕ‡ÌÇRëÖ,¶Å3•‡Ñþ.ücäU[™8¸Ñ277”À)Š5ƒz,¶} m+¼¾d=ûÁ½ÈTt¬>Ä»J¿¡æ¤gÅY Ü9_¶nÝÜ9FIì6Ä~T:—4¡7¶~vžêˆª ˜cÚº-ôh«¡Þ;é[¶{´õ¶ÇY\)˜D¶¦«À¦î±F¬a„ëÍÒR‹´mÇ ¦½0 IÜ ³Yj0ÞûU "°ŠíéÀ!>á@.F¬xÐ?¨¸°J5+ *Ø¡«‚ZN"¥œ½¼I £« ŒEÚ€MžZëD<šRÖNåHñQìV6ྤ™«È“äH‚¯ø„£zÁÆÕBάÁÿå±7hS­—[:“â jÝÃ8r¶“i~®Ë[÷ “³ïøpž~ŸÔóÌM§švFÖj ]iЗf…!}_ÏšbB,œ¼- )4PÎ-¯ttöB‡ñ¯%$>Šþ‰ž¦NÃÌé±ÅÝr‹rc©JÍâÿáu ˆžúGe¦Ð_ n„EÌ'KÜ<¹ –=Խ´æÄnî8,ù× ²G‡Laã4`ãy஼åñlç²bnëuãh –ÎR?½ zxmßc¹»›z fmF6ÜQFÕf¼ÍØ#m‚V„·æ¡`ödtñ¿ \èh8Ú¥Èyw±é䥹4Z+&¤"´« K}ÛD6¹Ÿqä]\©u½Âºq ÂW”RX„ò$Ní2Ÿ8Øò=ý,ÓâlN榋!^=ãÜýœÆò 8% “ØrþêæÔŸÃ´žgÜ£^qï¾ÁeˆæÙË¡¤ÚE鿽”úv:f:7ŽWieÐrš8œ€7Yë0}šñ Ý“á\¥àœ/NµtO[n΄) ÃsÍÆž;¨´òÐÀ•0\mޏòçl¤®HÊãC¦Fk¦œ€) EfÉñÐ|®ç瘉é´ëÁ7„À *¤W4Ä…LÕ9c“ÙÝTÖȣΟ]ë º9v@tÜVÈô†ŸÒ¾üôÀ§oÐ8OÍk€J ó/9ºÙÿHÆ?©bT.!o«Ï,蘦§tO¦Ž½žf»­…qþ—*æùfIÜG?¸ÔYÁÿ¾s·ŽNözÕïõÆ8>›¹ÝëòK&…kã Ù±[¦§K)v@¿ Nº°À˜zààt˜CÄ™°(€`Oø#ò „!@H`€ؤJŠ?bQh¼ FáQËúM~D"Ùd¶A …IŸÒ¨$^ˆL¢ñ˜ü]÷?‡P@qù¤ªD‹Ä¦S(ä¶;M‹ÒäÑ m%$ŠS!pȼ~%œÉ¦ôH#êÍ”PA¸ËæÝÜcó÷ÜÈw©?©Ð+ ý™PmÏšüRâ ÑjðL,jE Îë5(üÞéM´Ã²OÜN2DøÐU$TšØü@¨6gÔÞ%®…X €m¤¢/(¥T¶›°5Òé6†L«Èu‘ÿ]„J&S~ŸÿÖMùpÉ\ @øÓØæº,_¯»ÛÁ¹òÚ=ÅíÇõ“ÙfˆÝB: fžé•†Fbñ ô*‚Ü4©’J© Œ;‹´é“ ‡ðk"Õ3Oˆº=ÍHˆ%Âpš M:‚Œ¥Ëž­ „DÐ#Ž&KXŒ¿P€Ò=è#džÑÊÔµ¸ÚU"©ŠL—€HÊ‚À$Ë£‰9QR>ÓÆ úòª2J€‡J*²DÓµ‘‚(‹·o€>Òº„ͬ'ò¡HqB£Æði-€™“ÊPÌ€jkÊ‘³ÓºL¦Ênh‰H‘£‡4ÑC´DŠjó?¢h¤ÓÏ´ÿÒŽ@BÓ)ö‰5k;’ƒK•0øÏ2óA¡TóžþQÎ UJ(‚…7¶2¾¯ÉEu€5"Lsh.¢d¤„<'åq_%µÚ…I*IBèÝÕˆAçoÑéòL9ÔÔ€ÇPGò2]‰‘ëw·p}Š‘J,ܧÎÑb–Jj*?(Ê-ܘñ_hìÅ©v52ÆŽzx„A)5Þz´ìÛÉM"OøŸ°nʹ6&h$-sÙÔU…SEýÀ«Œ6ÈÖQ´þ6}¥´brÝ.˜Ý®Žº>èŒ#X’$š4î40ƒ(3“OŠæõIôçÈö‚RÈ#î„.àN—vXº:ì:.ÁÑìÿ/ Mzm¶™Ð·Ÿ­Ün‹¾«ôè‡PÇü¦Áë) G¸ÓJ*oa Š N÷=Ê>b޵’ÔJôRSÜ›Úröàʦ¨ëàÆóòbû¾´½½´ Ó})Q¾€´Åï_rË£˜šC5¨ V¡LÃ@¼à’”ttåzâ}ùÿ>.†¿­äÈœ­¤×—i¤xÕ/wNÞ9CK¢3ÇäI65yõÒ*)ràž~Iò‚ÃÄ5dH™fŠiO„\GÎûu Ь†švÌQ>DЙC:?ɹ7NNYg#v‰ÜËã§ÌùºÂXQÏs,")ý»6º¦È¢ò7,…¬ò@¨{ú!ÄÜÖ3¤¬$Í‚‘öfY’¬"]k±ú'Rkñ &슷òŸ“£(¨‘ȰVjqœ &ŽÑg)HR„Ÿ(0dB!3 {‰CazJQ¥§çŸ ]Œ5aOæ;3ÒMP²‰kcý`S “â=YŒ‚6? Î1—ˆ©¸§Å I‘º.©JBÂ…$iw‚¤¢«Š\kP%'<8' ߊ³e ÆA…l?,¬!Ñ@A“¨AÈöìÙø2øû,ªxˆ6é(âˆa§~‘øCÅU&á{ “¤mõ—ãØ_ëø’’ ¦¬9*ÁœvÏø0ù‰ ¡s'èyí°¢$`ÈËÒ•³†¶dý!AEd½KàLŒ‘pè^€$ìàIkHI¨‘"Bdœ£a´˜r^%BèÑYh ä! 93,o‡Üêtúc([$Ä1K—BóNuز2oX„'$_ñ H’‚XG‡áÈC/&TáFÒdj‚!séMNÈ: $d°g+!G“#Y-IjeÅé.zí@ {î¡ð—èÌûa£(r¾h#è¹Ch´‘[Ç™ðE(5fEFžž8b7`‡ôihéyGwG\¡œ&Y1¸”ÐØUdj´És á‘™$'¢3dæ, D—J´°Îz¹Ò\XSêY®½s¸Yÿ; *~Šy“¦œìˆ%e*VòvÓ'”X˜ý“eRÁ‘) D¦ =J4pˆ5;L?%Pÿg‰ˆáºØT{®Ýx¯T0¸2‹¤MÅ]Õ©³¢'å ›³Y!d1zôùÒbQÝ)×&ï•7ÅTÍ\²Ñ³´Ð¿š~Xí,~d³ÌÒÜû(Ý5 XºÜŠŠ–±G³„Ñ£ykj ÄriMh· Ï™R³,–“uKõŽ/ЂÛ_«z)¦kƒö•N5(IP5É’¸ƒ¸ò/Ô¨0xV¶[ÖñoHƒÒtî áAUÇ8×5ã{½g'Æ^´FÎiFøc,ßú',ñ?F†îif_9œ)(šÃéÞ“òd‹sï‹8H~ßr~Mï©´{@2fd˜p¥ÒR’ó†àm ø¹3ò…Ë¢„^MþNÑì³3\i@*Qrnµ»@þì¤ÊË:¢:´:_ëáKš’FùD]gë0m’ÛȈsô„˨óÝŒaY‚Õjä^wá4™•ÂÔ<íA¶’âsæhÖê&¼œ´‹Í¸¿R¬0…[/ÇÌëñ<1-aô¾DŽyüëü¿ ï~¹Fç^ª€ í1ƒ…LøÐ’L‹ŒnÇÄ@º"ìÜó’jÈ[[? ÌÞ ¹-¸X|çLvæ²Z`iížbÖ ²å†èŒ í»MQq¹ITÔ~Ú?Ü›6¤À¶tänÌtÌÔᤵ4uçÜ;}‚#$Ó½3²¾R÷»ML^áœ3"DHç0ˆïÖ­“’SÔaÙõ^U^rWUûp 2šÃôµéKôô­kÛw Ù'—è{” Ñ{ž m&dÀm‹jd?ÏÇ­;=ip«ÈÖ ~¥ßf*¾^/nZÒ©Z® †O?°ä)a“wý‹ k±€}†»4[YÄg[\h=IBŒ§ù]ЂÝ!rÖCÓ@µ–å0ÍoŠ0^^öü”·:'„waú.‡èåë!¥xÆcEÎ&Ò ÐrÇh£#zžn6Èm¶—ê°Rír–ªÆïLö":÷¬b#¢ò›Gê̯­h'ãv­Aøùgì,¢ÌÛˆf/.Ãèt®k ‚µ·bÐ@u¯gp*– =ðˆý‡£JgÇsÜ·ðyèT¡î ½ÊÒ­aÿ ô–ç’)§JÑgBȃò"ÊYÏÖ½©jòFÈö¡öl‰x~ê0‚0é̹ÍzæÂõê°°¯4χ0TGNË.SGiĦt¦ô…çhQãž›nZDd~ÖO‹T¿Šà~æ¯^‹f$f»…¢ –þŽÝ‹EJîð-fœÎÎ!ÌêØÅ”SÇÀµI”¶NÊ×ÐýäÌ;owââÙ'òBÁµpkæ@ëkÚßAþlç"òÛˆ’é$â ô€% PÛÌ<%§é¡øçÑ€†Ê¶¼«ÇkTeå0¬ G±±Dþ…ÑzÂ/ËÔÚè rjò)m°É R‰¼‚Ž»$-LÙ1,ïb°±ÈúO¬\ÃFñ±¸‘jêmì¼K(8ÆðœÂ wÂÆQ<²j8©k G^u°ÖàNÉé`/%¬^K²À‰¾.æ– Ã6ã/¬Ýgÿ' Pƒ¬@X‹aü÷KÈçŽN¹§Šýí!ŒÌgäzÆÜ‡<|D¦o X MíÈûf#&ÂvíJ!CwÆ^qÑ|F稅¼âØùCh©ŽŒ¡¦Å,FG–·# ‡ó(Ìì™J®ÓÄÒÚÈ -mŠw ½²Ž1¬pÃb—¡úçJ¤½mrzQ0×ÏKpôjœÃÒ¤g½1Üê'àJmVaøœ¯`í@ jÇò^K{)ª0¡£NŠ-¢Ü ÑÌM&xÅ¢ª†0¢h÷"ŠŽ¢lR…Fêh.©Í5¯1‡»‹®ñIV‹Ñî&Žm,] ®tgÐüùÑæÉÓµH’ޏœŠ' b^§î#ò „óâ{‹(ß­rJg,"F¤áÂ6&ï%8P¨ƒ7ã¶™À³$ݯBÝ(l£‡’zLM¶ïv¨RØ®&•«zipl›*t%éÂ~‹¬®•¢ŠÅi(Ô3†³ª® ÀWÇî°ƒi4Å€jÐ\â/*œú2šÜL>mŠÚÇ¥ÑgKûC4xdníãi#‰_Ks+ÊÂaøàÔ˜ŠÞ%J_'3×1ØÚò mÁh¨‘ÌÁ-Ôeieð½-š.3ZÛf•ñ²©$¼Á fo#hNOà¹+$Ërˆ}ã†O ˜/ª&ðʨnµM‹P\ Œ|¼q ù .A«QB+<­*DnÄ1$¢poGÒLÄI.ç^9ô„Û!õK¦•ðGJðdjó(;m0oÄ$Ýs'H¢ag&èåO† ž-r³éô„ÀÁõAÖÆ‹'B.¸ì†Å"$Í!³,Ms³6SD57d`/)†ï‘U05ï°t(f©Â¿*ÑL Н_E±$¢^‚ňõ Ô—.eAJÐ3o2ÃÞè÷Vû§Á*àÖµÒe6(B¥”rӣˌÊìœò ÊÈ« [al6v \lÉQËöfíœ"æÂ~ñuR4Èͬ¼Ìp/¦­Äܯy!àÜ–’Ü ˜•н­ÐŽ”!K>…HÒy-ÖQêQ7Iê‚Tàø °/z„‰°sCþ ÑÌEÉ‚Å+PDî¢k{CÌ0…N’— ²í‹Æš•þܪ‡kØâr”„Q' IpKÚ1`“â_­$êßÒÈ,Ò©b¢—@cÀ aÊÚÂÜ>fH‘^R,ÎìÆqk;RëDTÜK»íÀp.Š‚é tˆUSþàU–ÑP¼„¢¨„ˆãð¸çU¦EÐnÅ5Ø4¦'-và—Ðæ0BÜ®S—^•%”Ьç$È)ý#äí,kÈD’ÙYK@/ÕW ‘»*é\RÀ!JÍ•’aMeÈÒË á`¤8×e sìÂ~aP‚nÃ6î‡}åG ‹T|IP¤2˜2ÞÙ—!4³¶~¨T:ø)M”@ÚevYÈ·U7"„-LgW±?D”âîJä5ƒX0ïÎ.Ñb%*e¢e_”ÀaÈ_¶BÍþÌBMrâ5ˆAtRširvWsÜ«Γ-5¢[‡ó½Èm<ˆÉ4ê”æó@ˆZ¨r†’b•õšjmñWÈCId¨¥Ç¡üÚÓj°¦‹ œçKž`´=4èTµ„$€÷ér· š—òÌ-ʵjy¯:YXl,æ}O€ ŠÄ'~°Ï˜f¬1ĈBÉ܆dì壮EÒ jÏ%bióVˆm6„\øÂ:¤ ‚K/˜·ó ˜Á*,’âëÆ’ÕP†…Ï#ƘЃNNM¤È­É´]l²pvƒNß$ÚMPËr-‡…~'킳ø$Õ÷†ÉYyZËN÷Ÿs}Šb$:æÈ² F‘ iP>pbešó§ õÌ»ÙÚztB½µÜZ,Z3[i¢@•§ò¨…CB‰¨\ì Uô„ Î7f„xTGxFK¾É)Q'VÇ÷º†ÂèÊbä®—…Foaö"ω”ë955±¡vÌf¸ˆ´Y„ë3 €î®¡´…€2g¨à >g“~Ï|~)‚EÕÄg—IŸÁóªÐËnëÚƒ±ΗÍÝ]7Û+z²Cž–©†Rtú*Tå°G.ƒ)[´EŽÄøaÛ{+FÒ ÍÌJKÏ£f®²ÿ&£UÔ—dbbyû}‹’·y¼ú©G®/¬T¶q~K®gÈ4Aªº*XR·³óšgéHPñ=çâêÓH-.YR¡\MæFQy†—(¥64€°¸´7@Š ÃJ[sË&9ï8ûF {fxýΛ°ûN~u]2¥‚Th„]%=dÍ€Pƒ¯gì“nÖr¡Âçä}j¤£¥<æ,õ_gXJ%E6²ô–SÓ¿jÒHÚÔœ½™e±` EÆ& Öb•YYy©µ!ü°ºŒYbÌ/0`o Q84†=Öª·ƒ. fùo–  Å.u¦˜îá  »Í`¢»%u·Ô‰. £ŒÄbTl'јö’è®±„°rÿ7I!yeI5œ)ñ÷ry> Rö UÄîUM¡©ÂÚÌ1'æÅL5LÛ¸ƒ:6L./ÍÏPO²¨“T)¤í| W|!Ò¡­B7/ç m2?·j¯mB_éÐE.Dý§Rr<ÞA†ÂãÕhü>›N¢?á³z4Ö/ ŠÈ¢Úsö ‡Úås°âér†ÐnVŠäŠ' •Ô.ˆðÓƒUh1¹Ê'ãäS{•c n¯Ýãq ¤"K†ÉèÙ€‹ˆCdQ+ì"¡9¸ÎõÇö=n°C4Ñ •BåAˆPh¼ þ'rÝN߃¹Ën!"×¶ê÷)Й5—°•ÛooéÏŠßNÄûùÒ÷õ¯e|õÂ8 .¶ß*ÿЏš¨'¯*N©>¨Tü­KZœ¥“ÁïAþú6NÓòå§0:&µ¡+²È£)[šŽ+oã–›ªïû'iºV“¹k“; )Ȭƒ$Jƒˆí€+Z*µ´KZnøD¨ä›Åhc¤¢l¢™&n8 ¨q(ƒ7ÏJÈ}.Kú‘()Ñ0¨> [œÒ<®ÒVí"©¼††K‡ûΙ°3 Zv€º.‘1àK’|«éZoC*S¤X»à ¾î¡ô2‚£IHÌ{Óoƒ(½N¨Ò÷ÈÑ;ûG'5CÛ!3®Bçò¤è"îs?¾Õ&µ(Ek,¶hdö¨4(bNˆ(Ë]f}RíƒÊ›Ç¨ƒR4pòœ£!*„ÖÃ4ËòœÓì¥<‰Ì­µlôÄrZ¥BN*uxÏ –Ó6“ä_ÑÖSz¦ë;Ww¶I[Øþ_@nÛ-fÎiÓå´ Ì·£å<¬(ËþàU:J¨!íB>K–'6Wê5 µ¨Ó öü¶È‚*•¶ÖÔÿ1Á°­$ÏÕRåMžéõ£R¾¨«)"£33±WC)i<}m*Jwpºoå!'b‡ãv¤«(ÞJäÍÏ*ÖÀ¯(š!F#yMu°^¯SÒ¹`ŽÖ¦´£<†F(ÝŒEýX¨2‰ûGí*9Õ†dêbîËÆÐÚbâ§{^g?Ñ×1ÿÑüe#‘¿¹†Ë» ¢ðÛLß8a5 Ú|Ú‰¹×–üµ¨~ׇéGíÝÀ̳Ìÿ!<-b‘m"ª5}¶+§ês‚PÙ»ð1 ĤõÖ\]œ3Wµ+´›¤J—1svæ©Ë-ß"S­xÞXΉ¼i#HÞ†~FÖÖSÒžõ*©^«©(+@ B@\ fn ¸-ãÒ¸›kUs°¤@4H@‹1{l¼Ç³ ™u'p<7Š>ÞQ¢geö€r JÙÜ…Nu—¸°mŒq"mÓÄdEá¸ÿ*IŽÀ°Þ‘kx¡Ç¤Ûˆc;J¬eÍ8õ܃¡3z¯1ž€H\DÖšH%Š©² `ÑÉH%j¢ÆUvµKa3I‹ÑSSàm–ÁHY´ JOútÉX•IÀT‹3ñ ¼»26¿GóãtQ\¼1ú=dÒåsîd §*AÈAF‰†ñÊ$fø)Apƒ©>A™ÚN-eAB-©`FØa+x.G7×<é"qƒpk¹•”Rf¼ùÎ8m­€ Hþ†“T£I°«Oâ:±i½Ì"|ANYå ©@iLÉÌa>e9*¹¸.›ût3µæ®uì]¢ >.‚4ø.ÛÀ%¥<¼¦¢¼QlEJª[ù$}SÌË|+Ý`h‚>—Ã8æH¬FØWä þpf¼³¹0¢ec“ÇèüO˜=*R|ÈÓ4P“êÁãé’äTƒIà ’ÈÍœ@ ‰ÒƃKÇôäÝÓrœõiµ ©¤\Ó-§6CVRשO2uÌ™*eÒjÍ2B’&vJâ1N”¨~Tɾ¤'nV:HÓà ¨ÉùˆiŸ–äèåÑA7*OE°B®©R£5j4NbR¡‘óO*Áó:q4IÄ8‹Uº“ ·Î‹^£R•UòTHì`ÑåjÊÇÃU©Útuv’™Éc–§ãL@IØÈWŸÒuYo‡ºy9J˜¡Ã›¡4 …L ä‡óW<¬$lÅ¥ |¨õÏ›îdù—ÊŠ Êô˜²U™Þ_Ÿ‹9&ç%ZPA¦îµÓ¨ô¸¦XêQñ¢¬óä‘[ç«Àkp%JíÈ„c¯´–›Ä!,úÈe,º°•˜­Y"bŽc¨>m_ó’Ec{;EàвÒQ-sŽ7NÛKXøLð@`a'¾B—Ë…¤Ì†Ò «¢±û'':é&W6§Ôý—O÷ŽÂ»ÄüŒ¤jGsæÝá ïðù!6ƒ%œ£­XûFÆÍ)bg/’þõ(¥RÖƒìLîÇ8°í+uKŒƒ¶…äæ&'î?'L…NøÊ$癞L‡¹Vâ'U{ýXS›]Ž„dÍA ¡ªV]#2,0Ò$™«„+@µ ˆ§žnw°ô¤çb?oyÈ#ý‚N1úh¯Âô‹$yÇë¿*¥ ¶™Î{¿5÷¦Â6lNæ^§BqèϰãPêÆä“’ª†„LîÌ ·`gö«i¤ ø€Zx½&k*FW,Š#ϸó3{Ÿ0#y_];ZÙÏ3ÓU,Cj©=®îÙŽ9ˆwŒQ–j¯æäZOrhzÄ…§$ŸÕ„¥;äš`m ùAûp™œä½씂zª–ŸWåGf•nFØ¥ä虳YmFúç(²ÅæÔ„À0(>!°ÉH6šÓB#í¸r%TBlÖ<¯UÀÜ è T¥¨;*HÚ"“Ö>µ{.a}ÏLÄ=íÈÑYz±*•„’>öÝGFÓ“—€;Ì&ꈟ]#=ž®±C„¦DÚƒáJ“$UØGÑû:yÅC+Ç•µé͈?©;A;O`Ìݳr^“\¹ˆëB3¹c…bœúnÛÏVCqKÚóiFÌo÷i‚€ €¸ò `^–T¼9¶S)bb"å­BÞŠRîÙ6S%2|èþ‚ú•WÌ£^ÃEÛ€I2¯‚£˜L¯œ¹öiÒÙî~ôkN>¡ŒÎzyޏsÞ®zÎyÔ ÉC½6º¦Ó®%X~#Û=ˆS~™ ©ËžSP £9!JÍ“+¤+Ö3òi8K‘ŒK1¿“¢V¦ H;ŠÛÀ»±"iª8AΊû¯žèÄ’p †Ô(#ç y~ ãÊi.ê<+¼™ûë¾· h‹¿š¨ê€L¢ƒ_¢B¬«#wµcÒµ Ê1% â±Êþéx ±ÃÞŠûaµûVŽc- šHú¿ùÕK›Dº .sÇ0”ºkª1D_ÆÛŠ‚$ÓTÇp0ù-²G!xêp%ÙÞ8l‘ð£ ÆC䑟C@Ÿ\J·HÑ“Ãp§ =º}*)î¢Ä¢~Æz`“ùý†”#+¦ÐÁ–š?rÀIÌÃÄ“ùpI÷¦S;*ã¦Ó‚‰£‘ù]7«\;y= Užâ 4l—AŸÑ³ÈcÝòtˆ¬SG»sª?©l¢ÊÂ|È£°L`#´;­« @ä©' 뇈c.Ì‘IS™Ù-ŸÉ2?¢Faª :j„ÈóG‰a²¸×Lƒx¯L5®t¢½áO¿ Û2„;Kª/“ÕZ\HZ6ô+Q’Y 1óÜ:Ë% “ïFRŽQÃ9c×p¨¨¥Á{ø©#r²!ïDª¦>ºJcŠ:Ö5ˆø*ð‡§üP-¡=Ã3êášÁÍ™¦£ü‘Dx Z ¬Ìh ·hºžœXÏ´v€*ÂLuŒ]ƒ½ùÈ×½H‹¢Dd›œ#©£&ÍLKœÉ]9±‚ªQ=.‡â<•tÏ@©¨À—ƒ¿Å\JµÀ¨H³ZÃS’¯sŽ•\NÜä2ÒñTᙬҤ¦ <«tÛ,³Ò5ãëfÐu¥<}#” ··Š s³UÑ;O}´½x “=6h¹349ðPu Œ“þ¨Ø lS«Ñ „|È{þCòÅ‚Ì$µ¢ü‡ùŒ›¦¨èÊäÒQ é,Щ ¢t-­K ¬Òœ¨ˆF06$HÕ9Ú¼Öà} ñ:63«,ÁSSzéA’Š£°ú­PÙRz…\ \¢­ô^ÁÚ¥bÞ€!a4:ŽÖ ‡ðÀ¹tŽ>L·Ý½+KùF-ß:;$:ÐÕXµ½±S¦¶i ¸X²<ÔV4„‰zÛÌÚLK»fµ«44Å2âQÞ&AªF/.)ãë{4 çd+LåAX‰K+ÙŽ&Ò„§Kf¾ý/ÅoÏÙ?“,©±+Dó„½åËœsGáÑÕ„"J3a¼Æ\Ö 5P®^=u÷‡ÁiÐ;Ž^. 6W*T‰IÀæ&|-µœ™QPscfpƒYCX´õÛ'³cgœ^üŸÊ¾Pۜ߆ý6‰ITäÕN¨·62]gS>ˆÛO [Âqë^~£¬Rhµ¯7ÌjZ`äÒ²J®5ЏÎÙ÷Ç%áQ$–¡©b°xçbâB–œŽÙÊÉ ;"AªrEqÞÂ`Èl5ý^€2Aç"dì-h”žápiÏìSÀ˜=b¦IJu~#Ò¥Z¶ 7Z¤ª7òšº zÖI¶ÖæMÊÏÝg<…fÛ…ÿ@6å¯&€ÔŠ4üíf†9fý—pœ¤• º¬ðµTÀì5j|8;bªVIåMåÓg³=$,$gÚÚCV0ìÓGÉö~ÅŸ:S^cïÞš³ƒ7ôä‚uˆÍEÔ ¥¼Ä{ å°ØÜíÇÁõ–üeã³W ÚFÍÕ$^·‡í.ôôäãWdXÝ_m ü¢•HmÖµùƒ±˜Ê=d¥Wä¸IH,Е¸´Ü)eièø[ †â¤4Æjyæxe ½"`;‚– 6GIŽÉ;±¢fŹï{µ^Ú•Ô¡¿W& ¾{Øïytûx‰ôîH) ÙQ²çåÍ#õ`Ô3R^#¹;Q8ùû²²ä|vÙ ãÊaã%¤×é?½TÈ}P¥Áv{h¾Ôš÷娀#Ç$–ñ€IH)í¾Î¼  •}Mä6d® àÆ¥R *B-÷¤^”±ËÇRÒïPÀ‡ÚãÒt!Rú>ÈsèhYD˜Ó1h6¥<\Dü§í¢þvˆ†¢Cià˜LµóÄ¿ïÃ\SÆÎý‹“‹oø Ê`Z„OéN¼Þ–j…ž’ªáˆ‚?àÐxDC`pXT ~Å`à8Ä.G_1øKü#Ž€ ñ¨êU~Æ`‰ƒÎd š?¦ÒÉ,–].†ÍŸÐ¸¤²+%“Äóê(/;Т j„}òªC Sésòµ>ª òÇÝ„c’½ìÕÚX ñk®ÖŸ“@L²“ ŸI@·yÄv}HˆÃ*×øßÊ£‘Øl³ÛÎæ³‹ ºô€ Êô›9 ;ξ¡®ŒÆ· Yð·&DÇ'ï“`ÔBÍ4+±«›VÙìk–ªC«ì2×/-ÉrºÝ#¬º\©3Ksq ÁiR\–%ÏBm¹'üDŸ<@.Ò°h«kJqû£ií*š’º»'2¬ê®º®³V¿Â³¬êƨú—HÏâÂÜKª¢’Â2È#ö·ˆ42Ý«JêXÚÀé ÒŒ¾Lkk# b¦ÑꆎÑGó¡8rý.ìk€Ð8òí¿(¬¹rêÌS@ëCʽÃ':¨:Ü®Õi zÕ5lÔÎ|³©t'8Òƒü4˜Y¼4á¸Õ;ŠŒDT¢è›©ÕMÀÖ+N´ÛKÞ !¸m~©0:u’¾é2 =Œ«M{¨ÌE_ Iý ¡wJ ˜ºªÂ0ÿh‰ek ¹’$ s:@ µÓçìE-[Is½ƒ8™äÃRl¹NQvçSVN„Hø)ü׌˜ú$t¥š‹h›°]¬Íळ°®jÚ¨"¥ç4r©‹æwªYŸK²ïw¨RPãEOžÛ€ñ¨¬p¼^jFá­Ñ ¤µ ÿÏ›ã¢IÍ3+Hë ¼øŠàh6§#²ÿÌd=ލ0"“˜æ2rK*žË†à–;H¬ëvÄñ&sYE);ûª;:à Ӣޤ0>˜»*Ò²­ÛiÞuD š»M³ºž°ìïYÁK)÷1ƒpý!F-Í]y­â ¼Ó‰b.¤˜.2l¼É)À!k~¦ç¸ÿÎ9 Rn-ã6d4´‰Qpƒä!h`? P!¯yŽ@„öw_áa~G/”fZÇ@A€¨hýuÚ›Êñ3ªn3„,ÍÎzÂÃÖ(-Ú“™ºœm Ì%ˆ…;<Ä»ó”ETz"p0€—+Ã5á!+¨A ¾ØÚ_`±«+¨L©0#íû\J TD’¤â²ò}ŒxÄ‘ƒ€c`{j|Ѱ“à$Ìé,4uÌ(öÉÓdeQ¥=—BMRxãý91¥FiáyZQ)Àæ‘óp€Œkû‰Pí«©FWÊLanä~¨ð„õK(ÒY›ƒ°‹àà8x²èÒD`+JøG•^Øž †èUò¤÷A À$WãìÚµ¸›0H!>šOn€)´Ú€D,R s·YBY@¯t¯Æ0gXik-À2„>1øÔÞ¦\¥h¶Áý @4¾2ïæt*à Ï)öGº×È@“©,B€5à@(#î áOÈcöÿˆD@8Œ „Dã@¸%ŽEä Z/|Jb Idh/ƒ>â°X4(&Ž€f2ðê}‰Ë“uóGÒ_Ô¹ävb¨F¡ÏÙä"§„GÀ8ìj–þˆÌÀUøDò¿#´DáÈÔvyB¯ÕäúHy>}F®»]®]/ +R; B;u¯Ð¢5;ôNm)|2Uút…S¿ëK5/I£¾s`,ÄB ÀÄk±;ÄG:þªÂ š¬ÆmÈZèYxv…¡ÊEò@‹]ÊIMœ€dwuÖ×d‚Go)æg«¯Êå‘ÝÔ²#­ˆuóV™¯ÉhÌÇjÐø†îYS„^#Z} ×ÉåH'ž+ÅO†â¡ËÙüã<ÏÃð¯)køÍÔ‚#JÓTŒ:);°¾/§â„&É‹\—¹Š¢^ð3/ñ$mºƽ‚Ê—¼Î J‚"+Zð„(I³ž¥«±þž-©'¢êœe €-zªúxÓªP X¯­n¦{Ë\´µÂ` ¯²¢^©¹Ècb±ÇêèOÄÙ+Iħ0"¯Å@!½®Ü„EŽú|¯Ô*ðáÎêZ„{Q“;ñH®j’ˆ¦+:‚–'‰‹4Ÿ¯ú˜ºIó†ì°ÈºŠ‹Ä)âmFÍáúü+(ƒÈŽÈÐÄ4÷ÍM"Ó®«¿,èÐaÊ'ëº$u.ºªjœ€‰Í‰ä¸ˆ.ªcM))‹eVHk¢–ê7\Œ†‹¼U‰ÿK ª º£Tª¾ÏGÏ;6,S£ü£l]›W¹-;ˆ&-ØòÕ¤’—«S£ánDÒD‘i!¯aÿ!•tÊ~_qÛ`ÀMxR¦¼-Ùdò_ØùÚTØÀ»ˆb5M¬½æº¡e¬ƒâê´ÊŸiÃOVEàK£GΖӸÎеÙî:_ ­— Ö¥ÃàsEOÉÍ2ƒE5g [p¨Òâ)ךN("lyîݼ‡gTÃöÅ—žukwH¡' Õ¦çÌ-ØÌætš ©´üj3£Ö~ÈZ¡‹­™‹1œÏ«ãà†È.éò;S€+]å¿LZB<ðêpÍ{RËÕÇ)«hõ' HåR"rµ¡ ­Ya1 ù‹¡TNüôÏï'tÄÊtâÞ–­XλãÁ“„]³\J¶UgP­_xEùoÉöcªÜ~mÏ׼ÌyZ.Јñ¼¾l›/Æ8˜ÈsÇ"/&¬—_…,/‘“õ¶ñÛê]x%%82lóÊa/I ô—}B#Àó¾öäVà —(d´'"Å›)ö{éý¬¯ ‚˜+ï| ±{BDÉ‹hhäá½äpõ¡&$kŸLÙJynÑæ;Pº—1$bpi¹¯ö,ÍØýyNµãÅ'„ ;mÔ”ØçGáÃAP¾1'ÖžCcugá3¼¤d½ÛÓQÄño¶Ç¶l™"¦z#ùÕCr&¾Ï4nkЛ>”|­/ P~ÓNˆ^SQ]F„JUB>šq÷‘Q^4&l²‘œ$}ëì¢H¶îÝ\„!Æ|Èü=fî²lV~Ùжcqü‹–¹>üår&FMñm¤âa ÌYwЕö¿ø%PgãI²_¥ÒMaO²µE„°Ì„\Q`²ÄZ?Ì H'*œ˜‹–‹ws±ø¼'±¯+FõÉÅâà]†`óNièév‚Ìuø¶¥jd)*ÂV½¡þÔ“tŽò—Hˆ1Ä(Èy€=R„œä²BúÍ Rv\P)4z:âÔ‘v¥21™K:"ýÌ,p!2ªŠsD˜QsF€£Î’Fý¦É….¦†~0‘üpÈêa‰.hA»‡Û@¢¹”;E¾ø‰a6 fžtº…X™âpú#ñ%dž¸<‹£Ô‚¥S'J©ì¼*pä6VÄH&K~²õašú¯&ºí‚Žx•óBÖ\›¨´ ÕΆ٢¼(T`ˆ1ãSPÑòŶŽì»¢4h[+ø*¡×!ælñfBRBs2^‘§p.N] y¤å…”Zë£èÞÅ“™&Ë¥³S¼¸—ÕK´ÌÓ Äï'ö€ žß›+«˜®¡$DTÍ”A¾³ír Ç¡+)Š%·—"–&Ú¨Uv¾±„°Å¨çíŤ˜B.&<±aÞj×±_²ëUŠ‚7lÅ ž¦rx°!eBNiš’°4’ýî¾bµ‘ÔúÀ‹ñã¦vÑ ¤é)÷¦’Bl·Ú:,ÌÔEÇAöM–O‰%J»Ø°bû²Ë’Q”rÖ4ö†¸ ¹äÛWôXu1…zsl>ô@íóVSÖV•ùjnñP²”1?ݪE/qüõÖD §[h”‰ŠÇkÒ}^ˆ…=h¨†#ØŠÌâ@+Á4Oä|ÆìHˆ¶S?YíNðAb]VR0Ìâ¡y€&·!Î ¬¸ÌRO­ÛƧ@…6^&AŸ-NkZù,ä`Ž4á$:›¥ }C¼;0/;Þ›yÅa Ý)¬ñà ºdæͼH¥îéwYžì¾³u×nÙVÌÚÊIâ";LÙ5úã¼måécö‚ÍN¦‹Nhv†y™Ê#gbÛyK@6U·ÙÂL4lH‰´\>D׃-oÙvnº„C/µ˜ ´Ô¨%ßwî†Ü’Ê-xYZ“ £Ÿ&/õ¹P$²çæçZð^¦O W2fùo¯CÎí N¹nòs~‹h-ÙBOdƒ—R§³â®3ÈöÄÓè%9/®w™¤2Ýû½úÐ*$ô›Î5δþyˆD°! br´ó¢)Kh„+vl…ókRÈåq|uVB?¤¬]`ñ¤–Z年âú½ö§Äo¬z•¦bÆRÀÔÉaüfŠÈ‡ÇŽUÄ@MtñL6]Cðù%FoJGÎ4Ek Ãði‚:bXÙ¡ò'Šà‹êÓ` 4#ÄUÈè]OÒþÀ.¨Ñoß©nFúIƒN˜«‰eø3)…–¢Ô‰ðb¢—&LÇÆV"å€#£†è—ÈÔ€¢|¹JÍ/Ì‹«^éÎÀpÔ¢æoMŠ–&£)¢]‚bçМèàr|œ*XvÆúªL00‚Gиz¡øµôÛL:íix(ÂŽŠ"ŽUÂÅŒ†`Q ^æ®tNŒX'ÇVÈÊF†Šè(ˆSˆ5‚|k.´w‡ÀœÀªç!F6&ÊnÈðhnë(›Ž¶ø‡¸}É¢œ-PfÇtâ«l¤¨T³,Ôv!ø´â O* xñ(Ýì€ìçࣈ‘®LÎàÔP¢Ã‡\ãmèë@h¢XPè,dk¢p޾wLHvˆúÞGáåD2E¾“ŽŽU‡ü@Nr¤)28ÏÑÍŒ)* PÐ$cŒºBºêcÌÜä"RÁB_‘>ÕQ”ðçÏâÝ.u±È&EÄ÷pÎQâ4"4Ú¦˜NÈÈï<ìð©0„g¨|öjÿ€4ïâ¤Ìû.Šo¯Ž´OpÀä.¥€Ýñ`4qÐ×ÂP%'Æ0±0õbR”R„e&^úš`BXù,JkOpÈL@ÁH¶?hÝé@4¢ˆxEŽJL{¬´õC^D*Ž·˜©‡þ®ˆLk«&&¢ènj&6-oó#Ìpñ’Aƒ‹Ð Q92†úð1h¦‚TŽÄ¾°îÔÊTÃj4m/;žÇi=-ê|´Ñ2D×’xð€dÊ`]RŠ›‹ü³ ræBFEŽ ?@³¨xdÉ8éÃ2upñ‰ÀC."¦Iî×nfMüˆ¢lháé:çˆìËÍ(h"˜B4X ØÇMØ£â 8kŠ2Èô–ò¢ «B’„å® Î}8¢ØSç;Ðv)E8ÊÉâþè­ÑÅ4qÚþJ|Œ’2Ù8OÇ" ª€Agx†Áöf‰oéa µB/LxŽÉ,ˆ18JÛAôÛm@%óªÙ’:}g”Xl˜S`_ŠàÀéNäHê¥gÞ±À,Mc 'höî­@G„Q“È*pE êp0C2ÈUÅðÂëK ¢|±­;ïúC"„ã«HÜ$NdÓ¡Áò*gˆwE _’¶ÇstÖSŒßI}¹fÉÉ®g‹F}Žó:Iû-Ôe9!ÐÑ2HºÈôÛBȲk5§­ðzÂS+ )=N ÕŒ½¾x’-/8mFXn[i|Þ¯j,¿9Q„÷m .XêðÓ´‚t«=Ѭ§àEš,IÂ]FЛ鑈º–Nmô‡ë8¾ô,4ã†ÍㄱèUOÿ'Mì*–ò‘¼!ÉnóP\)"ñ^˜¬Æó’“#Xê`÷ ìbŽçQ~$•*Xæàl¤£B-gˆe)ôîã'j}C‰èí)W( jðq Áê[7n,vøm,‰ï@ÍVÃJÍ(#eQñ çR)cæÌQÐD½éO4ù¤XÝïÀb Á±JIŽ# ÐÞì ¦LÆ¿åÄ5èO š8É8¯Š–ñ“œ ¦Ñ6Õ>š+wLbšðÊÂ5[ÍÎUÑΕ¦?4›ç"/^‡y9ÈM“å>b"ÖÑ2æÈî‘Âë…’Ò¨O ÍÌÒ¤»\` D‡Z45DPf_j=ÎÝ+)BV¦%+V÷ÌCJgÙ³!GÖöé|à‰ªeÊTxŽù-À ´2ó(ºâ¦Æ'+ÃS2ò°ím ­H4À ÓV®‚Å3cq,‚Žß´Ã`ŠO ”FRŒ"§GCù1¹DÊÔVo HäÓm¼„¹+pt&0>БCЯ’Ì┉J¢¢–ÊÌõ}ÉísæRù&Šñ‹‚ÁY+X’ Ó–™“£N©"ôAoà ¤é¥YÑKÔ Š±›YÖHè£F£7­XŸ$ÌåYÎÕ‹w=…ç•ÉV»KñRš4½´‘nsô¾î@UÓ:¬õ¬]–a©-C7)£5î”ðϨãâsîúÝU8êsÿ?` |ØÓ•ut&ÚkÈyZýg·}•mû—4â wTHzFîžÈ¼´RÃ’oºÌFKÙ@Wµ­ó5 ©ÈŠ.·NSŽ"¯ì,,1jħCV1´f€cjàaÕØæŠfôñJ3'ü$z¿r Ͳà åYDíGtÌðÙb  šQ®®¶É9¤høJÄËô—èDëÒFq:™Ü2ó‘D#2HµvS¸’bq–©®&ï)ƒb`ÏòkUo­Þ‘?Fì ¦’Bªi‰‚Cñ!¥—Ésòh ­¸œƒ´?`_#𗱂ªâ˜„0DÔÏ‘²ôÍ£“%+d„2üÏÙX-¡vÃ8JººËÐÇ4ÅÍ+Æ7à&2 õŽû )­Ùï&Jb§" õÄÅ¿ ‡ù=}> 7¤ÒÜÉÎ)ï=?µÂ–ÛÔcÏW %‘Á8J"kÃ?êå/’ÇÀµX1ímüHã„ð&Ä•°'¤õœd:|¤nPžIFñd…&9)÷´¯€ {„¦‘HCÉ$sƒSl5æÂâO*Øü“,²`‘hK cso=Nˆ/Väî•èü+j­#ÞΔt}«ùÛŸ‚ E#ZÂxsHþ³äq^!ÑQ6â2EÄÞ½.¹6E£;2ŸˆQ­æÔ¬aìÝ/„8‚ h“+l¥ÂÄfpÂÙ1zлÂäzr‡þ†ôÊÈ™¿!.HĶæ¢rfaa6ÆF“71!§¨èüQÇd>¢8b^c1Èb“–Öó€IæjH¤¾¤%¦ÆùÞG¥ ñct&VÔC¶ZM!ÿ†«¡*1ö“Ÿ¥g€­z$PHë%bX*¥G~À•+‚­„½7VG8OÐq˜SÅÔ·6*#'D‘#’³bgT±1ˆ¸Ñqú~dýgÊ®Ä5’¸é;–~<I‚¾‡õ2i®R»94¬jú9Kz€-7ÆAÛ«VœdùãõrÑMesm‚Y´Êòn›!D  ¯ØW\¹4q¥Wĵ•Ìê±FFÝ;ŠtÆùµ:D9Gò·`L"‘Æ’I+Z«ÐÀSž»ðVï«þ³+–’×I'`ÅÓ~F­&J:ÊÎ#ã;w ¦Wö­Gª¹d¸ˆÿ½Æß$ hµé­ÉʲOìKú-ÅN-iV”¬Ãjm¹ãaÜ?ŒdR)&·ÎÂßYW/älŸ$O¬µwpÝß9Ï=\áB û,²Á³e<Ò#¢ =2’=L)YÀÞ‰}d+-ǤÆ™³Ìoȧ§Š?QòCWĦ¦÷<ë¼ôŽÙÖ~T\/Ý °±ýø¬áóUñŽ Ë9Á¦ÚE2B¯^,!ÌÞ6âÓÈ!¦4îdiv1á«™q,dªN˜Á“Ru´£ôðGíøtª‘»BŸÝ/>ÞèÇpn˨fàÒK$*BŸµ?œ2‰`±Š™œÍ)pÕñ´™ØÝnö}¬  =(ÿ'^ãî¹n!¼ÃÜsr®°7]T6+ç 1czÄ~Q¨—:æFѤ­¼µ÷>C-•9º–ù]CUS/¡ èPçRCR²‘“ŠËþª° ÄGÎe duÊsH%Ãôœ‹TÃqÀ–o†@(D]üØêÂËÆ(ž•–’(޲©ï0Ôk*;º‡ó×3¯a0—+¶“Üg9´c¸pçÐÿ¥ ô,€´š*˜)ûâߚ±'Cˆˆd #s‘ +]ÂO£Ô1.Z«¡Û'‘¡DŠ¿ HбR0жd&³B}Ÿ‰ÁªƒÁ¸BªSŠl@2ùSDÉF!šëö!ÚP©J±¡Ä¦Lˆ.YÌä®ùP=‚€Gy®¹á¾xˆÒWBiö>D‰HIœ/Y´‚=D¬31›Æ—sÛ£Ü&•JN¹SðœÉöž²ìg²Šz¦ zÀ?q0 Ãû“ì7C‡Crlši¦ì&B.Éí¢f,زAZ›R{KÛÎA´&‹ÜI¤³Y³R=!,±¯œ¤U·ñÅ<“5©ô ´3+œ ©‰ z‹IßÄ3÷$$ªJiÌ!GH}-dm¸ÙË?>‰ú£M¼ôw¯LŸD 6È3+©Ô­<#¤¬+‡Ù½ˆÛÔ¦<Ö’P… ;SöCÉ!z§ÀD½°ô3À3 ø‹6C†ÁúQ3ºê¶R«šùë‰@&ÛwÈ•‘ÔÕš8ܺ@úX1S20;4z ÎvóL«dËÏô¼3\®ÄgLP‰r@ØšÃ[MsP%bAø»l'ƒ²ÐáTÁ¤á.ÜðQ,Ý›yõJ⿹¼·rÄ¿‰á®3wX7q… P·ŒßÀé‘óù+cw1Ð誜D´ÔµÌè—©M'Mq׫°ÇE¢;“©ÉcG Ùç§û~š³ ìþ‹ Ê$Û„ëð›TÊ\ʧ*Í…1£»ö2(ÔÄû“Fª´)2Ó 0“Æu,,J¥\ï6’G»[g(ƒGÐ¥Á»Ú»1ç½›È0‚¦¡Ë‹¾Lâ¡*ƒÈ‰#ú?;4‡È€™ÜûN0$ˆœ¢W«€©¨³ïPrG@S¹C¬Q‘áÅ9K"å¨óáÅAC»OÚz:XSù(óåÓÈ éŒrµ»8~¬Š‰ ªº¦QŒï¹*Í–Ü¿¦Ã%œ¯4YÄ­Ùâ èÍÙàδÛ¦Û%B⬞•É6R q9S%%šÙ¢¨ñÄ5Qˆƒ`‡å)7ñ.tô.€ ž!Æ2c³A¡Xë˧âÙ“ë¢Ö‘ßÂóLLÌFQï^y¨•ŠË_DÓYG`‰ÃWåQÚ.òãO^\ž8‘€Eü‹+Q»¹ÕšS…ưT•Õe•Ë*šŒˆäÊê‹#±Ö:D "ÿŸ›ˆJ¢ÒÌ ­É.vZ•5À(…M Øå+  \`cÉ'³Å#åµä(N ü‡Ø°ËVÊ|ž€2Š|@bÀ’ ÖHÓä!έR9ã>:½¥›Š71ø°ÀÂäÛ:†¶P€:ã*bmšú?× Uªën«›ÿÈêP²ûªÛZ<Â_⊠ˆ´<€!7rcCÝ¢¾Ä9öfªÕ¸m´Ò%é›ÈS{ zžiÄ&•衋üÛA¼%&KÊíÊkÌ€ŠP˜)ÈR-‡&û˜OЈM˜ÂýàVG8ÎnÅß²uŸ‘ÈB èvnåÕØV• h*r;ì'MÞ~J­?ÈüD=åiãRü‚ç­¡²#v%Ò΂ÏìáÓ´ä}ÏÅØ‡Ú5Æ)Ó‚›x©¼“B9VÇDýB!© ‰ÒÄg^ ðTÅ¿¤u„R¦ìpõ!êÍÔ¤ìÎ=8B¡¼– §Âs‘‹1)c³kBÃYáÖ¨ŽSžÛÕÄÉGYÃÖM,ƒéÉkžxüLêÖi1¨Õ<¿Îr<]å›ÀóÆZQe¯©XÖñ¢µVĵ*¹Ü•Á4õö• ëL È¿a‚ÑÎKú“ã¸JlOC~­›™' ©žâò€9öB“â r¦(w€æðûbŸaÙªØÚú¡kž<ŶmRUÞ ­‘Õ¸ŒD†½VÎR2ïFv YBïap˜ÜÓ‰¤E*ï'ã2ÓÔ»µŠc_¯‡Ìîk¦zþð5V!´ÑÎ,KóÈ\صt'£Õ®£Óú+ê/4ˆ`—-,b2l-©%üéÚ–²Èu'RÆÀð§DkܰeÉ>U÷èÚMÛ„&¨Ôß~Š\ ¶Y‰&O“éiÈbxX¬6p»%þN]p‡ P²“áœaõßD;\S9Û%#úK9™:<Û*\¹+.[ü¥ù0dµG☡ËÑ?ù ˜¯ºüÞ¿OÞï¨0’f?LL&/MÚìPòcÔ±Îmw´Œ¯ó¨êþ«¾£ÍÏCIšEÂa§nêi™lîæ0àÄ«w®éØËmŶ#¶ÒfŸv¬¼sà²á÷Söz%¢©“$7qç©Ðã÷sŒv¨aÈPÛ£ðy¡ ÛóÆþÖÔáßzVuË»Æè0ÛA¿Ý$Zmd) ÔÌ?<êjYÝ0ã"ýLHð}ûP•¹«þ绕ӗŠ#¶ßÌ«võ©Mø²*c@Qéqãçá“q,I·ó+j㔽¢%’›‰´%“òý”Iìþˆú‚?`Ð(D$ ‚€0ðF%Å_qx3ö% ãÐù%’?âQ,¦ü–G€pØl¤ ‘Åb‘Y¬š"žBù„.û}Qg€xäf% ‰K”WÐ&¥ —D¨pŠ %Rà’ ÜF+–Çáó(E^»¤Á¤ê„‚¤ ’T,p—ôÊNÄ"1˜Dr% ’Mç@ rIÂN"8i•Bçv ÆiÓ, 9.†ÐïrÉ #EN|éAZxnR¨M"2ìTV3L±P¢û@’9N„Z S÷ÄJ\âI*·ø=®·œ‚X@Gå¾ÌÌ¿«èæ _¡ô€u t‚3ÇÜÅk4é,V].{{ntî¬#ˆñA£p¹%N Æ¿öh" ’$ ¬9¨ŠH†Á08¡½hó A`8à>p›pôŸíSî$C̯¯Àþ²Éb$½ )òÔ¨©’Ú~¯  Hç0hz\§AI²ñ¡èÊ2ù¥ÊR"§;LBù£/iìIǼ ¬Æé~ÇpÜ^”®î´ЬØ„*=)Â'ó‡´@C\(òcú—Lñšr¯S<¦çN‘´ù.ÃGúdúŸ¨â‡)¥ÈB2£°Ïø™E“”½È’Ž;Ñ9ø£»±Ç2¢1`PÌJ*Ø!n»BÑ•[öÞ T:ñ)ÈPƒdûOÓ´|¨j,‡ÕÇô¤‘ÿ^€(D¿$J–Tˆò°ó³œêª•¡þ—3ÐbdzÛS]7eÊLzñ³¨¼T-Gô¶ð#ÏšVì5`Ù0ÒsDqªÃd¹×²C9Äp4(…Òè4YfØÓ<Ú—MmRe(õÌf(j:%‡9ÉŠTXˆkbÃÍ·VÒÈó;‡áÒp’`¨3³5Š,”ƒ8È󪣩ÊuM!ónqOD‘ž€nvn–W4‚K=!÷åꊛ:{.”ÇH#æ¼Ôù’ØîV•eé©*@ÏŸ•…ЂM®­BµWÅ#TëbàF/&$‹¾ju jlWœy.9hòŒ·idXù³bŒ¨möýŽ!qdÍq<@ ¼nªYB"ê:ê¢Êüp k»¤GHïëœæ\Ƚ­ÖgËæ–ÇYU*=#òÀ9Zo^ÙÅ¥3Ý”œº³þú’m/ËoC=•ô°íŬ ›æz"àq–BûY€w‚+¢¬Ú<Ãl‘œÛŽÛ´b¾2Á!v¼ïÙW5ÿØê ÝS€Ü<„5‡G¼›S2!GA¤3’šÚÔl$Õ:‚"ÃŽÄ$Qšcöø‡ûÍYÄäÜ4"NA™V"äq\½TGŒZ¶w ½¼“VÐMé+-‰Õ8\n±.edhˆ—8F?]ƒ^"/­à íÞ¹(wìì¼!¤Žï€)ÞNA`5Òc #Î~µg@®Zú“®ˆˆ“&´W¢à/)i¢Ò„лÅvM±¨ÅRucì‰4Ú„É!À$‡î%(ÌÖ (ÿ0Æ&'iƒÒ¹ñcOM˜ÄG¦ÅŠcÉ]~H–ý N²™¡#U Š÷"¦D¢—7èäGñPHë4ùÊ%†K™gøC|‰VÈ}ûÔ”Át¡œÙ=/0”»¦--‚[Q„J|eòÜ÷N!ª­Ëè’S¡ƒ@Á5·u묗p&.B~YŽÒËÑšŸ©‡´kòf”Záªk‰Ò–5âÙhO˜éÆ&G¡s§WÓ¼˜,–“R¬±ñcKÝ9É;¯fN$®í²9Ôh—s*4¬¢¹ë¿(QµÑ®íÛ¥·v¿'B}…—,éã}dÀ e»¸œ6D¶ŒóüYœ‘˜ý®1÷1ª“ª³O🿒A,ÔôÎt©?4$Î÷˜´nl_qn¶¤Š¾OÏçr3ê[@9ƶK’.ã~¤$Îùß”¦»’œ¦©çIxž¿m™NÛ ­Õ Ѥ­r ššïCQþî÷¥Ä$±5ÓQù«n!AÛBµtG|N.šÅ¦c>ñû5îKí#†H©DSú£Üµ¡zS=hûb€J•Õ\­á:ÙWYĺÑùÛ¡ÖjO!0û½À¢èHO²3-Œ:£Â?ì û“4¬ôÛèÀ„Ôq¥Ì5(;mø-†>e²õ»ÕÑqMmÕ.¯õ^G¶ï ±LH7ÆBÉ”´8g¦èÚc€HLEÀbº­2?ïóÐ!è²0o¨ôÖÇôxœ7©;F˜ãÊ[³²oMîÝ‚V\h«Ð¼.^? &Aà]{GÏnÓõºñ¶ËÈö¿F×ìÉ2{˜\òX¿' ¢`"ÄU¸EÐÖI£z·/©g©ñÀ.kI4YÇÍkäÀäIâc#°ÆÚ!©Ôl”Çê¬0é2X%ˆÏ*4êOH:âr™‹ ÕÏV›Â$ùÂ2™É¬oF¨ëÅX4äÎX„ŽÜ‹­ÃœHì‹fÃb·^0ê¼ËpÌÒ4¦„&D4` 'bxÙX* ÌgÊXg,g)~æE!¤Ö$˜Í¢ÌöøÎÜ¢ë:ÃÜs'æ†Ip8†¬Fn,‹ ê…ÇòÊ;Еê(ùiøèoB¶šíJ´Í@Ä b>a«…Rc®`®ˆ¢²¥4ådŒ©ÆxÅBaÊ‚æáŒk Ä€g*ÜÇËâ/š'Š®¥˜~ ÌÕê¦ÖMÎô)¼7 ª4M¤ï¡òªu¡ö¸¨6(¦ÈùI°'ˆŠžÀ Šàó¬P_‚I‡8¦BYŠâŒ0¶?i~¯` þM¿ î6E‡®: Edb7« jR–å&N˃ªõ e’b®bäWñ²ÿå’õd'Rà­—é— PQâÖ+ŠBcÈ\â²[ª.Jí¬!)$ùm8OÌ›ü¼«P(%Pï$F\íðÁÉÆM±~Ɉ½ðˆ(¤ÖÜKr=&º'( B†­È"‹¦ãް®äÑ­°îk¢*Õf[#àê®T,I‚8aÉqñ?¨ AìØRb9"ÈÌâãqNtYiØâ〡k Z¤ä ¢Ïð&úW*Ì(„²öd¶û±‚  ®òJf¬üä5¯ÇÊ¿"ÇWpûDª!Ò§¤®Êâ~À V­ŽP¸Rœ:î\±¢\L˜E“&*­+’ˆñÍjÎ"2–P°à¹CuH©±!£€­ƒÈšäÎMeÚQâφ?Ë ÆKÒl­&D˜šèuîTžPòìq1ë-Ëp/F Éleżʯ²ÄÏÙ$""™ãªüÊ)ØÀä’Î¢Š­’Ò D8rïÖdÎËÓ–¶§vâqȨC „ÅëHœ7È‹,jªxŽi8Qä¶f˜OÆ«òÚƒÐÒ½ÒJ«êzrÎ{Ò¤réM5 XÖ‡-Füɯ¬ÑŽÜƒÃ¡DØòs:éDõÅ–ÇÄ:JóvO¯P±§®i Î-· §(~’F¿‚X·Ðisº@н†¯3}2B¥!ak䱓ʶìXö¨î¥'w"­öùˆ ñ’ ÃK<³ž/z"Èd¦ª=+,ýÔAZ(]‡‚ðY¦‘KólY0S#®d ¶ØƒÓ,ðhŒâ欶íϬèLH†è±ÆZ×Áò´m‚NîÎÿmê¼ì°ÒFôÌ`*¾kM=ÏVÙt£S†§Dl¿¢xŒÑÕ#Ö~àíT9L/’ňŒÂ8ÕV##÷Acð¥%~½ ±ÖîN† $£6ÄÖºÃpö.4£€}"8m!N$™†“"¡FƒúqŒøÒ!õ­ŒBiا«Æá´2“²:4Jتîד‡µa ‹îsRYCTi ®ÅcJaoÁ kƒ gÂí,¬8Ó^(å5‡­   J馄â]tŸ"k¨òß!ö+dùC•’ªT7J«»FŽókb±jzl‘êÙPDͱ¬P–”t¯>P6OÃ¬Š O‘1ê{)Œm‘Z½üþŠ6h±£¼–‘ÏÁ.Œ|ì`O®¡$Dü%Ðá0Žø%+xÛ%¨Át·ÌøÚMÐ žY/õ䶈o,!©”Bަâç/aðn¡÷P€ ÁfŠæb#qÂzéR¡'e:sTœïþËÌK"Œû"K¬‡ÉÈ?«V²6@:jXY¢e)(\°$¶@“nlâðSVàfDó‚S,󀊄ØËa,b²°'¼ŒÉ¼­’fû68ôŽÕq.vµÂ ÿ€m¨RtÓ8¡÷ol†ÜB2­†c®žvµî·YD‘HPHÍ=ÓÊ$Š †ä!i³–@lù43q3Êàð&ÚB@¼ºHýB_ÅtÌ Q—AÇÚ;Ȇ%Ïì*K\îõsÒƒOÂvM´’ ŠÔ0x6åmµyˆ°cV¶oˆÏ7*¤dÏtÂú³I¼æ€F%ˆúÍ‹wÎ Îñ%^4«n‹´#O%—0—̤Ä:[· üéѦˆæDLéõ€` %O£Qftíj¾tÓ‚?°ñS/F:­ÌvOG`Ux‘«Fš›nºÂnÛÒ´F$:ú'@Û!+)dž*³Db>x’:ø<Å8uö ¥º'1ؾ”âÚ…Èãrch F<ƒ Tâ]ÕòôˆCETâkJØÚPÒ¡eŒÚE~>o,SVXÏGŽULöeH6ZösNŠ&ûH–(}­Å,¦xðeø\±§"Bø‡@$úR¤ brê›1{f”rïÙR’bÿÐôŸ8¹"ƒ”*–â^aô»w£ª/·ï/ŽotãWáN8“ˆ0¶hUVÓ$*CUGоzíiFçÚv²8òYvÛ ¢Ž&K­n~‰Ð(oïrGÚñŽˆÅ³ÝBxÝF¨óA´#;“\%/~åDÚýÃæ÷wóc̶I“±€ÛM "Òf}*Ø:£÷~€øÏˆdjS˜ 4°;7âŠm9N'ò YR$L¨Õ+ ü÷š…Ö¨ÙøBÞm=ƒCSy6×¶$±v:¹îÐ4ô"669VN+eºÊo‘#ˆˆk¶°5) –¦“ú¢âý•}ªJZ’éZ4€Ö0미ÿ…ˆ¬¢?u¦'%@T2å>T5jOgX‰æ )·Xzóbúö±Ä· (}^CE&ºê ×É}1Z>z•©yôævQb?¹ƒ=Æ­.'ˆ;ÚY%ËÑbij(¤;Y'nÐXõXQ±BvgÕJÖÙÿgÌ·[Yšå4,úgÔ€ƒÅd8™4urq$Ù?_€ pªX¥”Ë:©c~°;&úÀX†ˆŽ™r­±,K¥O•M½‘ª‰-nèó¤ÿú#-ÒJ²¹5bv$ oÄbüíi\º–Œw‚–:]ÚÍ—aý Aù©q¢§-F=3K#N>l[ƒƒúôõôWÆœ¹ ØÕ£úÞ¯)Dk哸uÑx ÐÚIá—XCª¾ñˆýˆˆ@ÒÁ9&¥K!€£áöXޝhŒk 5´œxMJƒÓlÓ&˜oª{GÏ'Ä¢Aš .#:êì„üú'½´±I+Õ7KHݵ3j„úˆ»Í‰n¯ƒ‘žBc q•ž‹˜Ì.yùu‹¶ˆ²Öo¬™XÀê\ùw‹†êXÖ,N±n ²c£Thå©Ð5¹j³vëa‡”(*áaÐj ˆ‹Œ(°DÜöe¤ì³M]‚FÌ'/»9ñ7 -R LÛ¸w,m]…–‡…›E¼a¼¼&,<¢Q°hdªíÚ6»´VDvnµÔÊ$'Œ”=*¢.ÒÂY‰à!ÒÛÚP¤t~L¢áð<üX.w¡&ÉJe•ËMH±ºÁ¼ØŒôâ=6 fJ£pýÚ»ãG¬”y™ö!ƒz¿ƒíSÐShK"­Œ'mli  ¬EB?£€ &‹0«‰0ñ•„ˆiÙ¾ÂG MÉØ£5x‡.Ë»Éaî»,G ".öCæ ‰„F)Eǹ =–uHòÈÏœm’Îg=摵wœâx\â%nµÏª œs—CD11bû-¯GM}HOíœúšsÞ÷ ÞÅ?Ú„T¼±p9æ×ÑO=`xuhÁ̓¯%H F;%ÞG(×>~øVòû>•‡ªSÚÁô9Ój›5¡c€?fÉÐ:ß¾&ÖÝ£ÕÎoçãUÍ;’ç$í0%ƒçPÛ.X³ƒ¯ã¸"õfì8šrˆÛ.ö„í•Õ8œ|Ù ¿ͯiÑýdâJvû:>ƒ!Š/˜æü«ü¯p)ß+¬‘¯ ÅvɲµlLP:ò¡×âÕ.7ð&Q’b<úÈ)ÂçCÚÀã¹íd/Wjýz‹ÒPP/óö`ñ¯¬‘¦Éu"(þ6ùÌ|#Ÿ<«æ„”ÊšJ gf<VÐ>˶¦æµoÀÀX0þ…@ßðgä<†CßÀ\†>£€ AŠCâà(Sú•H1'•`ÒX4ž ûIÀóØ4² ý¡A¨XdþAB~Ìäñé³ýµ¯CÒ¡8ê*>Ø@h{˰"D~SÈå]"KƒÏ]¥Ëºu²t"ƒ*Í´]?!Hòà™¬Urá4€µ‚9gÛ@ (Ó³R„¡/L*”ÏUÇ®X‡Íæ¨IhG¬ò=†)ÓmÀ‚žš•\Š)PTžÛ‡êN॓±ÿD'êäα½ô¡@zî’„Yºâªì^ÌÓÏ9QÈ)„Zðzˆ¸a6kƒ|, ŒÝ““Z…/SaühH6ˆ}Þ’ü)<ÐH¾~zê‘:LÌ ¯?bPzEÔïÌšä=‰fß°!Tƒ_èUrÓ|¢ë"^‹…þºÏ|z×jÈ| Xô‰Î8„RºÞLå€gTÇÎ è±P  <—WË^…è.¯ª”¯öÉÒ)£èÉW0Óå)Ò®ŽS‹f ysÒ*¥$º­ºãH}5yLó¼2¯Á<º¸@ÌkÍLÉ€~²ò²uÖÙ;!G±1=6œ?™ãòF¡7C«¨1 A¸£å>½ÑJ/P]/D÷ŠXdy?¦"E×8ÿ„¯‘št˜ç"¹QªÈï 5Ãb J ÈÏ"°ÃøyLmM¬wŒ¡bLP%Ö0—ÀJ9pS$!Q:R¯Ï‚”#1a’ç”y×ê1u¨‰¨nëÂ×Epùë†0mž³d^‡Å±¶Â VÊ! @““6„¦ ©šƒéŽ4òŠE!ƒ¬m`Ó¬Ú3Å)ÁÉ7 ÃRˆ ΔE­% #£‚­i1t¤b’xk/ Ct÷Sʹ{­ý8°t„¬bHê¹ÖB‚|AJÄa”~¥²Ñdá=|„ª<»ÆXs¼‡«*GG¦“Z8e­±BN«–i…Y©x ó\˜ýg–B@—Fª[«ÑX Aæ€IP±€oo؇º8fk2. 𙢔iÏðüU)@™«ÒuF¨¡B#Ê~".ãå¨9ˆ•-v¾e«Šfg‘ ìÝ8ZcñŠ”òæŽÛ0ZÑz£çX¯Þ8û+ QÄFÇ b'¹z$è ™©Ò/&ÏC©³IE(a tÃþ Ô·YB!ã[ 麒B½§j‘qÍÈÞ­I‹&§ ª©Á¯Õr]=^sOÕ†cÔÃ莇ܖ"õœºùæ}fꃓp2hL!þ×êAâÊPª0B‰›+œÚ6rOY"zRྫྷHg˜LgGÍÌ‹“;àÈLUˆ7³êg†Å¿+ –”Z –‰Ô0±¡FA‰ °& Ƕ vAÅY”Ìôð~ ¦ ©ñìu„Í‹‘zl°+ˆ¡©£¡˜õÈAhE¸)òJЙÕ<óu²F«”‚œÂƒ#Õ]ô5B"Qˆ%Œ •X:[g“Pü„dž­’Ç ‘‰;Ba$¹†5\‚ ‰ ”!\Ý›+ë6Ç@ž»Ë’˜‘456G##äw®´ dN’¦Z‘° í¶5Þyæ»iÄ•Ö TäS~ZÊÂ{«jjâÁcåFÑi½Ä„a‹Û&ØI,a‹57?B„²WµcÇ-ºUÔ|orˆ3Å}ÔĦŸ[L57oj¦äÛI‡z ;Ëʃõ¨¶3{S”¥RÕŠ5\Wq‡Ù3¹2,•F8U6@.µcä–_bzèÎ?äƒH<4¼“L‰:U×t‚Ô¥ƒ"%ô¤•ÐÕJOgGôX‰A¡Eigð‘:}Cî­A ÓÕÛ¡ª¦;ç=õ>uxÒØ¢ 34ÇS†£’E²m³WšÃt1®ëÒú‡Y“d“;£M:n~ ì÷|7*dg”ñXuâ+±$‹ê O³áɤ (è˜{xISb[àà”©•2%ºñL)¥УšFØ(uQÁ÷Hþ‹ %Ð Mv 8mU߬´›9]/CÏ™ ¬MnðZ\ÁèÎšë ¨^Œ0ú³Uìú&h!W:7}™Í¼­ Aа•ðâÐpÎÍx„e;¦Ê%ƒÇ€™[ZëùâÀ¡õë}ùÛ¢ñzÄͱIºòœ—O=VÁ÷’«¬Ÿ4;ÅT´'qº–!OÜ~°–úFu£Õ®•«§*¦ÀIÖOϽKV*ªèw“B0UFªÏ“-;\1HÐ×´j&CdfÝc¦b˜½j‹­…×PS¢ ‘‹ƒbköŸ1€Gw`*=m.¸Ž0çÒJ²%¶¼â}JèMàä#i ®ÉWØeÅ­AÍZ&ƒÁ•ÖîNúÉáô óÿ¹F*—t`ÆÎö¿O˜ó+ïìüú!°p Û!R*Øí'‰ó)]ˆ`¸5swÑázUñ†ÛϦ‘#(»KÙ±<ú šø±6 ì˸ʕº‚÷2i3ñ{ ¬8#Žúá€xÀ´¤S‡)P~?˜&èlÂ"¤”а®‘™jþ?@ä@ªI¢Òê*]®Ðä+ 8¬àÓªºä¤ŠÎ%£D¸¸„6 ¾ ®¥k®¹)ø8á_ŠÓç ™³ İ!²8ã8¬30ù¼qí–"‡£Yö«‰‘ºÓ—£_¾«‘&C++²8–|Eb¿>C@A¢A $y‡$Š'˜ƒ,¹¨¢±#Ü£P“m1Hª½³b1œ“Gº{é2:¡œ3“ZŽ­HÍrœ¬²²C½¤¬.=#Ð ¯¤Ús(ú|A‰=ä=6`ç@ÂAFbà ˜¬*º£èÍ¡ ž«˜Š¹À¦ë,™ ÛÂ“Ø Á_°¹b"{sºËë©¡{BÚ…½[ïŸj ê¨CF:),S®§ ¥¹ JìWšk2â)Ne¾HjK˼ >´EÍÙ™¼‰åeX# žšSÈ1ƒ‡Á8ùM¡kÁŒ¢žœC&¢8V¢´Ê)\§ò§53FÀ‹Èã`ºHÝPõ"Ö¤š“O'à±HSaNE ”rV“ÓFUk4¹cËøªÊ#Ñ¢oÇ,Ñ×ÅÕPŽ8KþŸúUÕŽL)ﱫɓ!Y6Ý_ØÑ{?í<Á– VÊ ½“}œËØRl<‹¥Ñ©Tâ:šö¯ã½Û4UhÙ"Љ€(¸8ñ1D-jÊB›¬2V†§ºë`ÒeGÅz¡'È -{Á‹ÕCS¸•Dɽ‡#ÌÞÄ9™yM:$ßµxŽ/ébC˰¡à»Sȶ|)^´öFòÊžlXžÉ, FËß‘¼E0ûÅ%mÝI™*¹|%mY:´ã°¸ž™ r_³ Ó¹³í&GI¡É³?ª¹•Šíu–<ëÍXÛ\TŒ,·H©=S)•ÜŒ=(&Š•ËŠÁÜLÈå©Ê1žµ¹Ân±ý½ÛJ\ùø)5¾Üäàð|JÝ¿‡ÒÑ€Y׎ÕSVÐ~^Ã,Ðý>ÎÀõA¡–aЍˆž á²¨gôŠà˜{è©h«¬áhÁûÁÖ-ÙãÝíîŽ=/G“ÚT’XPØ*ÜÀʦؗŠÎ.æjY+Õ;5®%£X¡V”Žˆ2-³¯X™ké…d£ø$8}ÆQjc+¬ÈwØnuReü!WqØ‘ˆÃK$äØŽú{eˆ1Ì©¯·úÊ;>«t¶é s ÂSãÙøX¢>n¨Ûv1R‹ZÂv~ðìžÈ±\ïÜ{èÏ­+$D˶‡Ö@g奬Ha™@îNÆ€$$X±ún «Æ¥Ê€]8Ü…ÔÐSÜÃ=EË"K1‰ì.Ø´°VˆàþsužQ2˜€> @x#æ „?áOØ`‡ÂŸð€<†?b‘˜È=~Hb@)$–Bü‹€$à‰d=ý/“Ä¥ I¤JhÎ^s¹,¦S9Æd²÷ô¦->ŸQ&òz@{ŠE(gÌÊ/‡SañIM3DŠSé }Š›¯C,2J´úJú¸M¦”J4:ßp–w¹<‘É%7 %í÷uÌæóJ¥2/7¿Fn¨Í–IGŸ`3R™.vI‡á¤ôH”x D­Â2syLÆ…Mâ™8•¬T›ÞbP'Æ=‚‹é!\'ýc’ìü˜tžÅ¾Ãk1óI ¹úÒJ²Óú}r$9â@ØÐGëÞ`­)"ø´É*;/Î)³ÀÂ<–[¬~d!¶€£$\ ÁŽ,f`Û.cþEØr»F¦ý†£E®òK‚ýÐm¯¤HCdAmn‰hÖpKkN$²$ÒXå‚Ó$äQÙÂ0JRšü'$Q·ÀE"‘û‚‡ãõŸ»ÒiY¡pLkk&gàIM™p[êð¥âðs Îάê°LRÃùx²ÇÜ»šÊÕ -w=$…" K¶nŽxΖxlº 4z,ü›ªsx_A{`¼ÂàŸ 5dÅFIƧ ßcW]Æ¥p5¤y\ ÐLÍi.˃¨IÉ ¶‹ m箾Ük–ˆÑ&í¬ N'Èq‘ÊfSò ›‚iZ«µb.AÝ-52ý_âŽ*$<ªJL?ɺ@¤lrm猑á„Ë)bér>à-¡£ùAJêÞ!É9r‘Nv´2hã`IåM¤ž—tÖ‘ÍÀ^q$æó ÏR=\*+Šêº72_££U'·-ÒKÒ3ÂÕþz  íIMªé1AЖ[”öâ?, ,¨´âúÈÊúÏ @g“ág÷Љ8·ÌÁ`-P³étßF³?2)F¿,v€¹¢›C AH¸Ò¤>K€C¼qNÙ×MõŠì‰¢q#9E0xÙXóÈǦèm-(Í(˜…œu÷~, (í­IÒ_´ ÿ¤N¼†nç5-ˆf§ZL Ò‡›­Àz:BQJsä£ßy9*‡ŸöƒH¤åV,mç¼äfÛ0ÉÆÒK wð½ÕÀqiÝ~À4Ì|m‚ã—©=Íá¦Øù[I <’³={üO– ìe¦º7ç ìé"¦+E’í % ¶Ü/åç™Mø±Âš¨xº§ZrÃ:óׯ6Aq†Æ#5Ýç˩ͻZ Ü’ð»>Õb!¹Ãó-Ó‚Ç}Êø›0—•M½Ã«x\¥íÛ>¼·×öUE~¨ïjÒ#k2pÊí´‰ÎA«ýÏUCÑúdîõ(”ÌGv’O8Å›ÏvAçÿ~˜~ çÙêd»ú’wlªðç„ûª‘vùŠ8ûBh÷v–ÒÃacñËž^‹Îmº§e™ÈZÑö_¼ûÈàn’Ȭoñ'ògw ìa¯¶p%.aC]‹‚Á^í{DîúÜ7Øë†ÓR( bD,¢çìtÉPæcL7ŒÜÈ.ÌÞ¤ðZ"Ä¢ÂægtúF 3T¯ÃÒ,öìòJíÎxëÂh²(èv..ÓiºGäÅ01gÈêîFˆ­$ÌÑgÖΨTâê r>­‚çŠd‰Ä©ŒZÔ¨Ç'àvÅ–ôø v8‰hïF¼¦<¹ Ú8Éí@çfXü¤(.f8ÅâH&^b¬Þü¢€ì¦’öžzÂhŒ¶ÄDÚ´.ÒÇ&ê¦â©2 ª—o~‚%†³"BŸaô3æä ë"`ààwÄ£ë^ÚlüÔ `q¶¼j®Áo.#(–Ÿ!þÄKŒK ’$Ž’Ç,ˆß¯òö ¶Åæu„abr&ëtâFJéìÏlóïn¾ð„¬ x±z«{ªò©Q@÷¦PÇmÒÓñ(fæ~eˆ!ãø ‹ÓÍ÷­Z ÏFVóűêžâ åVº â…KðwLÔ‘Éhñƒ /‚Bò†´FI•qnïìràiÞuOÊs&«F ^ÞLŠà.í©güî$¸ÃÔzÝ,DÓ춃”}õ$;£”·R‘X¢ü ”dF±èµ#|”snҦ̓qıp¸oæêr’µ0ÞZÐ>Åþ3°˜¥È•®’pNõ?4v3NvbNmX2ÚýÓ]Aú»ÆÙC~Zu^gfLÎ%0ZµÀ?ðæŽp’4éДó$Î! Äs&Ö„§bí”±J–b…H¥S2“–0…¾–¤ÓiÏNΟM_WI®êJ üÂYjø–©'‰ðïpÞhT/'Œ†ŒôZh¬œîc=©î…C”ÄOÊãcºïG3@6Ë"ÉÔŒe§lk­ìŒÁñ%… M«°aÖv!”Zžâ2·=(OŒÓg2BÍË]ÐAÄ—K (S9Áúh‹¦PÕù4‚ÅŠ@3V„í1i#üLÀþðÏ)¥Á .€¶oG§t\ΆG\œFX,Mìü¤ü^tf×ÊÌ•vðµQ·”ôH”-<…ܺ1ŒÆôË(U^ßÏÔÏBˆ^±édv s%¥L­W9e cæYC` §ŒÞgíçHÁòô,¬ÞÒ³6Ò0Ëa!ýí{dâ%"X].r„wnÙY´BSW—fœì{&ë¹’ëHm-7ÅŸ4 ’…B©Ï†jC†Oau´¦G"ÄéÌoSxZÌæqD.m9Kv–‡)Vu%ai®qN¬þ ›g8±`…€~½SbpÄâGrV‘W YQ'†®ØZ§âü•¢R„¤w¶jŠ7ñžÄG±ÆUw¶¹Ï- _7'טµ[N)gO/¶tQ:¥ JÀlYC‚pÑËr" ~Ùø¹ª/ð/ÄvN#0&áã÷7ô—™YŽÜŒç½ùŸcÞ.õÎï­$í—¾ W( a•Û§VÓÎõ¡pF+ªÌ˜>Á,–ø®UtŽå$OÂLæCð7Þø†´8ÞQ3Sä'45±2€J¾%<ïÅŒ¡=ÿñ¦ èÿƒ!@ "CßÐgü(…D¡P¨l"%D€²“öH“C!ð¨xY ‹Áãpù#öX…Lâ  4îfûŸI€ødæ|û¡FåÐIÌæ MfsWåN‘ ¨Ë(:Óòv†D©(•~=@}YÀöšlsIÌÁ,*µm„N^÷š®Y |ßä Y­+3£€,/êÕÄ ³¾¬p˜&2µH­MaøœJk*ˆD`Õšžk]™Ö£0IG$Îꤕ¬ æ^ÿ”gò0ØÄ‘µÝ€f¸M¾I §Ë4ú8’'¼ÉFy˜z´“¥…Wpw|/R5¿¾m x×[œ™ÕæÐL Î E mßÝŸ7ýáTXÿÊ×¶ç¸àÇ¡îúºÙ»gê€Ú«H“úã$ɺH°"ªÒึ«¢¦®µ*f†*J›h‚!ñß±*ë¾×ÄÈ2e Ì <ˆ> s†Ü·)˃ *ŽÐï¼,{®¾ ù±#')› Ï’ì†ÆLÚØŠ¹ŽÜœŸÂÜ÷¡ëÆ(ª‚HŠGgär–DZqú$H4¼…0/ë8𥒠&%äX½ˆÊ?-€ ù5€¨’‹¥ŒK 4c¾™Ñ€J´Ç¦¬bRج<0‚G@ú™±ð8š¢LºY €HS0ÏÕ)c<±Ë;4óŸ´„Ó7¤*ÒInjŽ#èôjÔ¨‰óœ¼*+†0, <¼+¬%9Gòs§n'D)tíWK¡KÚ¢Û•DGoO³j•)¹êB>æ7®í^ºtœ«¨|øÖŸ±+áK, 9EZ¨«XƒCÎ|"~Ùi^'0UäÏ¢ Ê‘3=.%ùu¡×¶6꡵Z¼ª>³¦nçm€J¬¸YHCk/ï꺅K€ ;÷ºvþÕH…n¯'ºrÆ(°"þûqRûyCjš ŒªšÔ Pò±ï ’žÛ8ï€ȉ;èc(©àÏð£²C]7ˆ×À>™íE˜„=t£¶ÔùV14ìhºÄ©&»¹z¨…V­Â<Úì—&&œcwm¶ÖGë¢g 2%¢]¤Ó·±5>†±ú:}€‰ËWD(­NÙ$;eÿ*êÙ[˜Ç«JîîÕ¾˜¢ô Õ–q|Ýfš+ 5mxã:ºÏ'xà.šÔðè‰1úùN^ÍÈzþý àäGôÁ••x‘’Îmd˜®³†[@]+­Ô¶Ô¨¹‡òáǬŸ4B¤ Êu%uz9~©‰ƒ…] Ä—‚ò¤y1îÂ¥æ,ÆØ N ò¤@?ƒÕ6§D;¤2™H´EiȾ§d^SYù½ðD—ÁŸ0-ñy.NFѼ%‡Æ€¢W”¼ J^48”W|Ø[.‚¬4Ô®èØ© šÐ*d)ÞµálCŒëåÀ¦ÜÊÜq@€*v°J+6Rå¹Ç)V'Ô&_e>$äeGÚÄ“kpü“âjÑä…‡O “ 7*OÚã"¦ï±ò –¢uäT¢ÇH„·bôFb¯qÖ—Dø #pŒN<¯³Ñ×ù‡qÏ,ªË×<ö”Ô&A éFÄá„Z`è¼Ä÷ã›!5‚†e¬¦#Ë[óü6¯ùõš®wà´xWãü®¯²Ü½ að€(õ~²×NŸ¸õ(¥ù‚ŠÀÛê+K§–$sÂÀS¡gmóX03úNaÜ^5mLµÂÒ©Û9Oë4ß'v0®K¢|sB#6ø‚Éfó}•ùèÊX6iÓº!í¨~;©FÆãüY§2‘BRjô ,Åèµ¢RÑ”{Mi€FäõJ¢ñ¥gÒIý¶Ô¼nM«@s¤~¯µ)°¦ÎDè8²V$øýø ®”Œ|÷4kj#néf¤åüg؃áz¯zpF/1ˆB©$øœÈ”ES蔑-¸Æ³ñaFX+±›SÑ;ª´4©rƒ"’ÿ=æëS@‡•§òriù$T0ÜÄ¢E¸Äêú^wVìò¦æ%Jëã›lp@óc\ê8gõc-È&àÿr5jBUóNœÙ’Iz¯ÈåfЪƒrèòÌ€&Ø÷¥Å7(£ìù(UˆaE1–þ§öqˆ2×ÈÉNB¶2D s Ö›Uؽ^ œÀNPÐCßÉwJ·6K€áé´’Yßú=|ÉôFˆþ‡RŠ0@• ªX'ÙÂ:OIóBµñÖµN²;c!Ÿ¨²ùAà÷«eÈz¦±ÚKH³[bûL8ߪŠwä„^D¦þü¨ÊÞ“”1sGž’£Ôò×€*i)‘ËTGQ]Å_ppðÊGÑŠm,嘆þƳÑȦI«Mꆊì¤|AwšÿÈdó…ˆCxºõT×ÜÐhÀ‰3% Kñ°`^h{=j<öª˜ïà"ÓŒ ‰ÈÃÿ¦•É¡j"=GhŽåôŸŽNf©P•¬ûÓ<“˜wò›esl°›búÐɇÔX™§IcÂÄÏ’y„)ÏHHÛm»ÕšyDiH¹*ÔFOèÉw†q}a›ÔÀ”À= ¤¤oïir=âÜŠß;ÐR2OU£,¾[Ø…½ú¼JÒÐs&žq°$¤nÊöd’pLÚ[DŒ+¡yÏX<Ëj¤[‹è Æ÷¡brlå²èßœËe• ”Û¸ç¤ìY­JYÌÝKQ c£Rƒ§ªV»-r¸MC^«6ga'•ÎóU"ÉÛ;¤„šË˜ûè\m÷&æñ°šáÇøœbäõP-®¶Ê@ªÒäOø•=qVïàÁ½6ÒSV”õÌ 6àEž r©éB2D³:¯ç+‰ËùÂ{VŒ;ÙÑ­:1NÔª,“¶ÛQÓQŠÏ€,…Ÿ…›¦Ååÿ§v…Ô"íIxh­Â°‰þ,Ûdäc„cöãZòîþ»„~¥…ÿ‰Ý¤²Þ¿ ÷) ïê³êÀgÖÉ5¤øûKØ}†‰+´á‘‰éKÎÇÜ yøt`9ÖßÚÝÚ^‘¤ïŸÉ÷0ÇŸÈþº»¯5°ß§r»ºÕ›1Õ5h߸‹ §Êé¹aÑŒúr"Ê5&rï#ã‡á¡.‰S‘)Ç8)¨À¦Qq ò¨—#p9b#"w/€°*‚•ÂC( ­1Ü)AáÁ-3žbwˆè‡ |¦¸Ä%-ãø@»Áá*ûÙ¦üAy°<{øø­t k+”ˆ©¡ºž‹ŠD¦›$ /qê4A)Cõ+¸„ˆ·+7 ô(°ßœêÀ‰•5ÀܽÞžÐýRg)3sˆðõùj2šÙƒL q¢òâ§S¼5‡úŽ€!PÒ¶À´™¹,1{ÛØÜ´jû1P˜š¦‡ÑØË "Öˆñ /cÌÁí;¨ØŠØ~ùÁªÓj6ŠÄ#á)c“D;š²k¨”¿%ò<«y(+b¿Ò¨’³Ã8A3ÅùÙ²<’=z%Åz »+bZ«> zΫЮª¡m+æ‘„J¬&6kˆƒ¾‡ëj’‹FS—‹û.¨ â"ð02u0(ì ažÛN°‚cŸáÇA †ª³&®KÇq^¼ñn$IS”Ì,«b¦‚âÀ¡/±›ˆë ¶Sg ª$ãê#Ä JĘ ¡× Ô BúíA$'I·˜¼IƒÃ&»O¥É4«DE Ä>"Ë›{ë¶qNù졲36+X¬‹?ÑG # ‹<£0ø*PÆ3<(û×+ÉfŠ)üˆù‰»p´ìŸÛîÉK<4y¡ù‘’%Êšè–i "\a’¯›yS¿³Q¬¹a ø&s¡ Éïs¬?ÜT1ü”´ J4 ´² |ÈžÔW&º³Ä`8Ì2‰c 'šb'û©ãtJóa˜{ªký&„›'¬iÇó•;ÜË»To@Ѭ¼P¹¬f¡óô+$Rí'‹s|À"áÔî!@{¢œZH DZBAôŠ+bçÅ«š—"ªânj΀8Å‹ˆßÇ›^ÂÑ…Já?ÂaJë§±b0<¿.¦,X“*±@Åò\’i¸a†3´|×¹¬¡ûDê‹£);¹˜Áœ8®¤v±b€ªú¸»d•v¾ŠvJa»´Ò@©»Íl"²iAˆ|y³¼.šÜ:{;›èáŸBwT”0)¾Àré+Ów· p@âà‡ðôA’Ç$òt±á–Àš63+:г¾ 2Æ)ÏSÄô0r H¤6”ðFþ#LýE¢Êˆ!‹I¼'sNŸTe¼âƒFÂp~Œ ° ôͯ0æ3Z 5@—Û-AcHÅm-ÎsÖ‡Ó7£å-R€’;* £ +b‹È†FÀ}ø †Ëj\GDµËxŸ?l„ÂäáÔ¨´‹E\K1»u¬ØçÎ"é¢ê«Tš-™ZecÑ+ZÌ&iaµ±úQé¶Oi•6»š‹të+ñ¸ Ÿ‰2+*¸À q9t4 9…2k-!rJ”±µp¹Ã™¢Òô7²‹õ€Æ"XÚ âå?K•¬Á±&"Œ£âÁèŽaÑ‹pÊÉÍ¢2[Ìò?Dª´Ôµrbj#T,v¬¹/*TÂXì|ºd¤ÑeŒD+² LSÒ“Ó(S <¢ë *D7ÊÜ9ÔØ7ÉÖ3ËsZòª"ZÙ4ê€ÄêïÕú3G•àþ.ß—¡z9ð l¯a¢[ž¢J×¥Š¿ú.)ïN|!«Óã4é}ކ Ìš½|t3œ‹1)©È#2—=¢j˜ëGSü+˳ƒX %üWÑé¡Â\#É4¢zw›YÀØÔÅb¯B8b‰°ŸÐðˆRZÑQÎWrÿC{!ÖAjO˜ð¿Á‹ìåÌ›Ù,u×M 2cäYëGÑíÊÆ{âZ•¥HìEÙKêÏR ââ³íÂ1¼â—ÜS Õ_RRé“É¿{[K®È}”„ï[•ȸyF>[Ó^Q^¾§Ä#‘ëFÊlD£däLYKÑØ†Õ ýÑÑŽ|‘Ñf®µÉÕ‹OÌåòáS)¾‹r­QêŸe‰.N¿6Ìš Øï†®AP°û•á}ÊÜUE´7Û¨­Ñ2  ï£°¸¨Æ? Åxš™ÃNáB3Z¦ ×sF°…=#‰þ[EÖ2Gjâ*TÛ¥ÒRT­P‹UyÂ¥5Íúi¼UÅÄíYT¢Â½ÖÊ»ü\K Ö_eR܈ð±e²¤;­Y¾—úA‰4 Ó*#?0¸ÊK>Ô2( ›1EÈZ-J#aÇ#Ìå¶d!UÓr¶;æ+Ì¥¡&ºAŒ˜ÒèXþΫ®¼'+Ù÷‹:´*Œ€+܉z/•ÝŒ=b=Ý•^¡>d¬¢Q£¨ÜaÛ&¤×ÐöÉRbÛÑ/:à|Â8´›}Ãbˆ\¬Ѧ[ÔH Õ« ùNI›>1 6ãÄAj[Vè@0G™ºžÕMM‡ÝÛà4!GÛpR^6ÃyªWã;”æ/§«´{ú±1Â^⬽%ß%Õãx®5-Ƴ¾ €&¼L'­<–äÉÑj½Ù Ë 5½m•ÎÜkÝVf G}õL‚@?–Ÿb€-,æfÆÖ€ Æ @„Η“8¿„q+Ó¼§¬¿+ctÁãó¤—>*œ‡!)Ã["O#SCÓ×TÝ´«ë69-”¤¨5»hU‰Ì–Ah2”,¾ôš6»îÐôCý¦,ÀªŠ;ÂS±ŠÒþ8a'VȆh;¨ kjâR'š´#LäSޤË5,ïÕ€Øãopƹ/|7¿ÔË\ઙóªÄ— Lt-Ê×°|ÖâN¿¤Q=ùÂáÁÒ½åþT²ÖcŬÀƈ¾”r£ËÂíÊÂb-Úæ Gœ}Í£ÂPþ®1+ÝûˆÌ¾¤[^ôÓ¶+ÊWnäÖ#:eÎJJç&ild4zj†:[ÜeL ßQÕÀ­_9s_"%ÁÞc[EÔhªŠ¥P2´Rã6ž«4`p¿åd¶E‚>OFïj¨æï¨~Õ¾¨'í³cÖ—OTØ®²Å¡Ö ¶8r½iÅpœL{¥Ñño"g³úÖQèù*°ÚÊ'fÚ;‰ŠMVOçT– ”B ûý^Æfh©¤Lð@—Eï\é"ìèÍv\wp`çb ™¥·É¾¨ ââêÁÚqmWÅ£€+C^¢ò‚a+&w]üÚ@þ êŽcÿ%Ö“Íů­dà²i@¦Ó¨;ây 8%  ævb%î‹Ø£N5¯Ja:5”‚‰'T#ŸÂ™y6 j¢öB¨ùgI=+3AÖf*6mˆ«|¸‡ Â.ñ•…Q‰ j.ÙªWv¥øs´88ë;j²k‰@ñ;WØÏQ¸‹1Yu$Ä+7 —b.<ÏR'é-^•íòá¥qâ±>(WmX×-^vRXáÃknÁÞ޵ೇv\dN̾ðó[4¡¼}÷e”y<Ç¢YÖV΢¤æsÕª¥têÒ“áP¿kq=Â’Á?Š|¼Cáþ†RÅþ!¿´}úÛ&Ú:¶,yXªÄÊìFõìhØMuGYT¤Äëñõp‰˜ÿŒÖñ,v•l3âtljۻ“ͯ’IGª.æ ä’š^ô¼Ó§¿·ÈLÆÅ‚? ÏøD¿aÀX„* þaÀf+ ‰Æ@QXôNü’D±YfHü‰Äâ°¨Tz~¦Ñ0$å÷;ŠÍ% )Œfi;}€èÔvµ&ežÃâJ<2+“>ªÓ%D›£ÑÈ3æÅ “Ehò¹]vÄù…I£ÔI¤*&|]@÷z³ê»D†Oé` 5k—Ì08%‚)ˆ˜EdPˆôzMCɨ1ø2±šDèõ¼^++¸Á21©@ е:¬L#;V3pg¾ç-±Ù䕊Ô‰«¦¿p ;Ìz7¡ÅT©)5c—æq1˜]^±ÿŽƒZ$”~9ÍNeÙ˜DNM+ìᯰ/G$áóöp=ÿöþ(î+øÓ4îÃúå1Žcš„"©3Þ¦Œšh‡%náü¿»2,„:M VÓ€N ´ò€‹È„(ïÓ<£$(;B¼¼éCW€m²rÐñYü¼Ä™øêDÌû«2ðëN‰¨€D´¦ñb.“(‰j ®¤Ç¬©ªÂòËR#0”*ˆ‚ò¢Sf-ªzý8ëúµ¶çòÖ®ª 2°¯¡ø ÒD§ûvü@ °ºŸ :i$lŒÊ3ì˲H‚±ª$<×=Ú'È:ÓÁKì²"œ¹A´³^ü Í+³ Õ °å¢õd÷AO‚s2¢«¸¢RˆÊËÔèRN«y-+ÊLÜžõãëÖà ÿBÉ-ús*µâWDhrH’º¼¡Pl6ý Î°.Q2Ž/*Âg"´5d•¢jë°ÿ Mñøä£/Òÿx£,S_S2;d‡8·õT]8Bš+´[/!TˆA‘j¬ã¹Ö,Ô£Öuè‚N`ñ¸ÔÊ3TGN] lº+K´è¢/5æ ‰ Ó} ¢-oR!d;Wb~šGz âÏ”H·§t5še ÿ Sçû/+¶u*á'ˆ •¤i"1˜°Ñ|<¿ÔŽúMÚ˜×(Ôc¼ë›öG:íÖ’/¡Û´1YeÚîJàÀ%+L«sPû¡“*CM«(†s[1÷ÝGöFŸªi%Îж©Ë±aGúù…òuÓYG—¿Éò„)‹èo5W‡1”Ô÷^+iÚiSïPkÖ’gëºq\ÏnbierèuÙ‹&Ó,³-\9 9x0M •”'>èµëIÌí sAV8ªT¸gGå?’ ¢FÈØ•­ÂHúÀ!¯9„xÂ3è›k{oäµnºÆLþÑ´#%`öExZÒq;/åí³«â]]1¼B$„%&¢ø\:iw) 8dP“é~ ¤š6¨RM¡ØVP5 >Òò³I½H °Þ@Ö¶«+ƒc½ñ£wÚÇã”vcõâ×ô¬šqwÄ´…‚ÖÙOñF/0 xÔŒ‰û#nȼ¹7W°Þžxt¯Ò-,4,°›OØïµÒLÈr†YÌAH¼',´Ý:= ®üGøo”dˆ}:¢vˆ™ä‚x 2K‚ˆqdJ“'n>GÈîŒ$|-1H7 ùFu©Aj”à @\y£ñ»µ”ŸÕDE•pýašõ‰2âá\ÄøœSŽM É YKÈ«““à’ìE"s=@#Dõ+á(RDy2Ò Â[‹qBŠ-Ë ÐQ¦òQ&ÅæGÙ.¿#â®KÄ‘hAâTÝ™9ˆ¦^4BÓ*¬bÎWLEm>§á(›‘QÜFgÀã‘SxÉZBÓúÍ¡ËlZiXµ¦05]“[PPt}À)€ýTñO©p¢?6"ÈÐóŠJ œ“%¢Qâ!ŠÊ¡8eÓ "²W‹j¦Åðc'úg¥øH¨ìb1òDýf&ˆ°àæY0D A8•^ßcöžuzEòWVgy¥Š`ûÄ*¡&uWR9Î YeZZ.l|šòºQËZ'§ç¶·–ºËÉ]v^£ÔjÄC,©6˜ÔÙ0$)Z¯+T¬­7PfTCš¡5{uô}+ð¯é¡tS欨â38lc±ì”0Hœði«®=ŽÑÐbª³z8ï}ªÆ¬>ê™÷WÔ X¾Çk‚Ú!”¨Ê´1%šÛs‡a^+ÁézíºØ°j…€2V¡¬¸ó+·¬z©®åb)U*Êjf ST|ªçÞ^bLÄ £G‚ÆF0“•x*¸Ãr×ÃV—0NÏz.oŽŠè.花®ULN¸ R>ãô`ö³ËŒnÆ ÅLh‘N~àƒþéJ‹-,b0ý~GŒ‘JÎvM6– 1EÊ›,¶Eì¢í­>¸Ì²”Àã°µ°ï LX‘ƒxþíã ”O¤Ù)Z§Fd4ír¨QhU.BÉ?Bˆ$Ê@oO¬ü¼YÂ' Îð*Â&m*LŸM¤ê«é&ý ‹°QpŠŸ)êB¢2¹Báòöªc˜ö§ PØõªÞ‰k`Èi/l0ÍNNµÀ H¯ «‰ü‰µ§a@hŒÕR $Èž;+ãôÚ¯vM¨ZoŒ­Ú”°,ÜèüÉPdüèÈúåØž*v‚rPÉ‘ÍRå¯Ú°´oNÈ*Ëpêojä*²ë Þ¤-!Íì~Ä˜ŠŠø¬h Šºœ^ÚÃ!m‡èD’,õ`êd]0ŠeÎÂ$ŽLFQYlJÐ\pÄD8¨¨!ŠdÞ‚mîl&ü‹.zÜ.š0ÎÄQ°F—‰¸G*¨0d—ƒúOâ*Ü  âŒÔ±3« r«š’òDXrà1¨ðíÅq 2 CKT;Q§C™ §l–üÒØpnò}²#£ñ §1ÖìÞ¤)JUèòØÐúoÐÊ[ÄRFðæôg¬³'?³0æÌ–]ª‹.xøIvzpLÔÊÄYË&þÌZ"«dèp†4ð‘)pÞ(ÂÖ1GDOëd"³kÓ€”°JÆ\O²®4òr|Jà?BÔá¤k<øƒ™sƒ6LPöM»$ø¼ÆlkäþdjØMî4Õ8ã^üäþuÊ<0bÄbp•±  °j–  r9)³zÝH©I4q8JTø„pO¯%Êå; {+"lÙ‡¡ ÜC^8§^QrH/u¤€üòÂÝDðgOõ —óª» õÈ`r¬Œ‡oñ)»n—4M¶•®n­v¦f_)Шçbîæ‘Tœâ°+ª¢ $ÔbæuH®h£*Tsß/gA‘K1fôQ'CS\¿ž;/4/ õ'ËÜL¦ 1D<:qe8RËTÍ-Ñ¡D¤Ç˃.&òÐL+¤qÏzÀf2òÿ#²ÚîzVSZ²â;ÓRÛAï›(ÊZq^Û‘¶º"Ö)Í^i[[Ô‹H<ÛŒ"Ëeç]¢XoÃú>%ÞbBr}K%jTGÈxgþ ®ïLé?rµ³·c*³e©õe;qéNßé@ŠÕ‰Ru]{«ü/K_(dDPNR®©D‘UÔ RðkuÑBï[[ÕRöÈÿVðŸÓŒòŽZø>Œ‰ó:òR÷íPçG£)ñîFÈÐÍ×CI¶R0ÖtOä§ÑîA¯kg«ŠÙFÔ˜ÑÆñ0LEð\G„¹dÂ[© ˆ³\¢rÅu÷‚’qñÊGŒ<Ÿ;%m`°^¯¹ekZ“¶ýî²Å¬NÅJ`ޱ»(¦”ŠÏ¢xÄö8wu;‹ä$…”­*öŠ7ª°–'AE.`€MÚóú²uéˆkd¢ŒhÓç +d`.#%œPÑâJé>Äó¢#4Üã ›ŽòA¬Óõ¸qïB˜ÙˆƒïaÓ)‘gUPÆ.§,Ô±3uê¢qz¾(êÎ3ä,µ{5bËSJ2)áblÇUUL‰ÉY­PîØŠž$@eÖø‹[4Kjtv‡KøygU•°•~¬åu£8B°Z9x—ð¤Ç¯päpµ¯jÅX>%©“µƒÊ,C.MòäæNްIn”x•å• K¸‘¤ño^µ«eO°iH€$:êÖÙÛs¦—›9øÄ)'!¹L xFMhêºÍ(¿—¿”®ÒƒBî"¯[\pcA‰ìØ‘2PÁ¢Ä²k¤ÈCR1Wèáûj4B~fÙQ$7abv®¶ H%«Æ –H“<½Òn‚ù!_d|žPºô¢·´§l×=ç^îðE÷U­RóEc™®±'{¨¨RK&G†í†ã*1û4TÁû[LgKK¨‚ñ„öUƚ܀ZPÐk©um:,2îuK DÂüä@O´×f¼Ð2dPÏZ…>p׆L„HDV;¸¤ötWéÐdÍ0¦gA t ›Y»X}.³(™¬¸{TŒÉ² O~Ê«±?¯ÎÒ‰®Â+ —”W“ÇF‹öîÕñÁqÀb»™Bw¶+Y«bêTLÚ404%¨FYŒ7“,à øšq¦¦V@ ^|ïGA6é“`Mòð;‘›ÔE±º‡K•#„ŠíiÃOÁ¸ K©Væ<;K…‡ÄÄLv7üYR„Š›@šPŠ*BRKh_toé¸^£rº©;(ê£Hø@5yàÁñÀ”³V'9š½Ø"÷“—ï°lA¤@’ÆlÁB">ÜÄ¥¹|×=د(Q²•Õ´•»§Ì+ˆQo0Ü‘UBÓ9M~½Ø/1Bëƒð›sé_áþòT-[%_"‰aSøª²"ÇgzA‚Rͱ2Z7[n¶Ãœ£zåØiˆñl€ Ñ3$–¼«¼5–›·Ô®î7uÚ m׬†¦]M)>ÿJ£XšëϼGsj'·7»3® §<¹s"ÂsŒ™Æ—š‹eç*œw™¾v£õHiH¾(…y€±¿µÈ.¦ ß“pŠ*3}uöf¢¤wè÷4±% ÞÇÒ$Vi Û1Iüˆ«'x2‡«Î@“æìäÖÁ)Ç wG‘ƽ§×ñxÍ»—Ú,O EµÎ[[mkþIN7>µ¦m‡!ùM¾Îõö#Ú¬¢W/ÝF¸®5Bû£âƒg œýúK%dT1ZLI›H;ÊßÄÐŒ.œdÝDúˆ¦È#%•×ö,J+ãýzÓ?Iê÷¬Ù\ìÙ±*C>€•Zõîüÿœf#ÛµßY‡ˆg •Jºž)ØK°øû~<±é/Êc"G›}ž÷týfeÕêti«µ¤RåÑÅ4+Ft¶2è­©uq͆#ŽÀL1hº«ÍF¤˜tZ ù†í-qîÓŸ—wü¹}áùõœüéDCÖtr„} @*ÙEu¿Ž¦: ª˜²K\ð³×£õžòiÂ7Áôýéß·Ó_ØÝJB~ÀßÐWü …>áXsøÄâ‘",B!7è AG£Ài41öø•呈Œ¢™æ‘X´F;‡¿¢“@‚€E(HtZ= éÊu& Mç¤Ø—EêÀ ,N-XŽWgÒŠ`Ii¯€j“yôzE[”I€ÔsæñE§/ÛŒƒ ¾AáÕ8”NdzbéÏÈP&x|ŧØ7üS1¹É£ÙlMï¡hßZ\ìFE G±0ìlú>ÖÁhvŽ6ô„=·€ö&-¥}E)X(0‚Ϲ“Xœ:ßáY÷iú‰Æ¶€8•Ú݆'cñ?åOˆDŠÏ@ába½bïAû4EjÊ]5p9òÖ‡.ÚÆÓ«‡û ( PÌ€-bd£ ¬ká*I*ˆ£Ð¼2Kùþ‹!Ë£„ŠAìH á2K¢è­¯­Šh´Ÿ®Ãžå¦ûî‚ÂÀ’†>±ÔÝ> » ®CÇ0à f‡¼ ‡,ò„jĨ^Ÿ¤ Ã--ª§úvu*@­Â6sŸYPÉ!Å΃ßH¤T“1¶‚'tØ HŠ1+£ÕKH›„ø&Sg jÃñ6U` §WËãZðàLÚL*B‘#UJŒNgów@l¾K‘fø[ò†REKÙLÃÄæÊ¬Ë$”Q¹¨¬WˆÔ íÓÀ¬~ÏhžiQIÙ\vƒ›šóácJb/ Æe‡©Ó‚ M¸ £ÄƤ©:ºNé´·Ê÷ ãZººî‰5íŽW ôA1ôµæPj,”!(V9™1«¤ÀñRòvÖÔ¦£QÀ’º·+)ÜËJ!„Ï u=Dý+ ¨?Mzp \RF·o1ýÄå’ þý;ê»3'-³'ÆÔÙE“ )Ô•.ñIØÅHñhXÃ-Õ&KìM@€{ZŸ´oÎIÜ‹á[Ú­9Àé YŸ25ä€ìup*´$HTã±'ö¼ø"gýjBhû‹[ A¯e¶&ÄÖ[XÃôiŠQK³'JðZàÿ1#Î1cÖ±g2ÊIŠ>Ҩ̋k³Vu­ ›z›[` „6hC—Ò`‡->±þcSòáĵ±´ŒüÊqç#Jì†Ó ˆ;`4¤‰Úº’º¨ !;E±tÀ©“ŒH¡t2Pn·<üb#VSŽxÄVB¡tiø”·½Ù49lëб’„ýÍ2ßj1@FVü§WZÒj‰­¡浞Q]|kYý(„P–iEŒð}©ò¡ ›­Z` —–vÆ?"#¥"ƼšÊÇ“Ã9S%­õÈŒo‹ë[!%=W#“w/œ™!2e,b|bƒëíÌÖÈâ:Mp圜"èOq1è1Q 9T2J™€¢¯Ù ƒfᜠn®8¬›DhlÌ•|JˆÒðBvŠp ç€t³ß¬K‚¼Dzó$¬mmä¥å%è)‰œ@OÂ÷]!âYL\æº ºÞ1tsÚLE)_aA<ª’l5”åèjì•*“ÃS´š×¾vd¢ŒP¡`œ9Wå:Jvò>•y2% ìB¹<žaÅ4¥¾G;78xœä‚­Eû/VpDLüw%>FÃø'%«4}#‰ ÒŸX€f]åioœèGu€Ž›Hü&$É‘HHì¤üvirÃØ›@ÚÝuIdÊN˜ÒQ MMËÙÙѳQAÇõTO•J×gh”9]A­nw¨ê:ÔÌ̆D9?çnƒ]½:SsZ™Ó‡ÄþŽõQi&äñIÔüsv4¶¬UúR­»åhGˆò’À¥©°û›S²Q¢@p ô™¥ê‘2$«À?Èô„7ÕR[Ø…>æL ®zPMŽUØüšÐÙ7悚˜êbA™Ã"éDÓl~„ŒxÉ#¢PE‹9åw®á»¬Û.à'…Zé8Fª•ðšò%MÀ«™sÜSvr“4Á(h3ÆSxДùCíøý¯ñ¤;¼É%#¾N¡Øµ¾Õd¾º¨¶ÍaøÝ`¬‡Únƒ¶’›*á £;dn]%æ©D’ñms“ |‘äý¡&!7Aµûj¨–ßÇẗyŸçë³™–DÇú?O4c1,BôŒˆçØ2“ÊuiÙär€¢<ùëóƒÆÅu˜÷ìÂJÞ”$Ú9ìÝÍ–ôzÚvÞÂnw…6ý£FÖzŒí·°ÀHÕËSwj»> r­l£æ¡²èÜ€1Á4»nIXÙ"Â-kKŸ©½§.C¸lLÁÛ¹ÞíGåHç4¾„£*ÑÂ*¢4éU¥¾ñ^øî44¼4 縟|š—«þèD[ÂÞ2õ/ )ø–@ ^¸cìU‘E ŽÙçËiñ}YDɯ¬§…>™”Êáí’ÁZÖsôEæ eœŠXæÒÖ• TO‡dÒD ±t)'mÐWº"Aa–üªL`òËW|Îb© M{·‚Zé‹#ŸŒ/¥¯µ¦Áš,0+«üá±6õ¸‰¿±æÐÝH¤>ܶùäŽ_ã JÆáÓ)‰º¹®ÒÉv<>¥ÇŠôtâ÷$$(>ªXX¹ÙÌ¡4ð0#{H=›§ªê».¤uYÀ•d òÊs™l%+-wÏÙ¡M“2HºW xvfå‡ÏÕð‹ÃB ±O±‘QÒÎ¿Ë %›# ™6SÙëÆ8©1¢a3ð5kO·± ±n” ¹x›œ£ ‡ëëºÐŒyb¶pŠ#ã"4!­«*õ"s‹ ËÚË·¶™á¤ø 5¹\¨"@““ "ç(zжªP 0lBª ;®«uˆ°÷ 8É 9Û”P¦- †ˆ*}¶äˆ{U4«ó¥ã¹(ÉÛƒ©Û¡±ßŸÑ¹JN°jÄ5d4R™˜§X~5Û´y¨9„Œ j—’·ú™14ŸƒUŠ¡’b§€+Øžµ w½³Í´#c#ò*+RTÄyªD#d9sæ';×–ä¿S ‘“Û¦ûV<A&¡}4¹Ù§ 6ãA"ùˆÑBЦ£W2œ/²’TK9¼e4Y&‘L“107á<2”F£ ”¼9QáC΋Á8¿B;`À‰ô*T1ã˜DB†Üq0­ÀÃ#i‹ÃGE‘h ;)ò?E¬CFé¥,YâÍ$k™1ê&ƒÑ"Ië@Z«j—’s~ᤓtMHª‡¨à~‹9žš÷Àk#<ㆈäG¥k¤ n²b ²ƒn é÷0tb1´ ßCº¢Àñ'F¼gµSBjkR¸&´,A•52œ¸p‘©JÃB!ߤëù™)i [«x»4j9t™ñ d*B²Š Ø÷@´•’q„–’©°ê­›;ÉÉKÚ“qý)Ûïˆè !âÀ€*=(ÄŸ+«ª¤iEY–¯:¢ jŒ¤è¶Œ“ä7)Z8ÛÐ ô¨\wój)Í3*¸+»Î°Üª[¼š8\8@æB¥0É辺ˆ8Øáã`£ƒÈúF’Ä6#»Á \Þ-䱇7XŇ¡}D`4ƒÖ³|>J‡¨ù N;y IÄk´‰)䟌¼»ršÚ 1¹ñŸá'C1¹‡ÛŒ³‡¹“0KžÍ9™A’Äü"ÎE”š¿Ž‚Ê1u)ó¾¢%+CÒ.j—ÂÜ0yןŠ#¨Y‹ZÛˆ9—¤SÄô>58~!CA4€Ëc‘Òâº2þŬ £êÌ•̰ñÉÉÕÌ‘þ-ÄxÙ Éü&ñCùÛœ1™ ðº¨ñ  ³t%H‘g¨¶ªN+;\ª«MÃâ“Ã!ç(Áò  ¹ÐKà=µq­Ð¼¹¥[€1ÛÃ"ª$êRÈPÄË!›1(›¨+mŸ#¥ cŠ¡Û­ý>SP»tl9¥Å›™E2“㟉ðµqµ¢u6©óÌ*ðÈ£^3sŠ·²Ô5 @šù š©MIŒE’í± œ£TÑLÉ"+Ó¤m߈<êW4bÀÕƒáJ?NMoÍ(]ÏŸ±Ò—²j1rÈY÷6>c ­Ü2\ĦÀ±Ê™•9”ÇíÅ¥TòGäq’ŵY-°ª`“!”V¨#͸ÉÔÊ«·í$QòÒBúØÔ¢È‰RUÁu Ýg4À“Ö<–µqÔfCRÒ£¼œÌZ”•"‰“à:‘WJ|œé*TJ‚ÂȼF´ÄÏÊ$š£'¸“q†ÞÕPÄ®µn‡æDY% ]5(\¿—U¾06+00”_,Áe±^=ÀòE4ÑÔ‹dàÙðC0V~!Uû­VO-v˜RòÈÝ.¬Á‘¿aÖͽ—R¾bRØ›¡â¿Øèæðê¾olÁ-]‰¢¿Ì¥ÜNq…]tÀ¥’S}Á%©•FÈ¡C唳8Þ$½ %Íž1ćäˆ|¸2=bªDœ£ßò§ö>ÕÎò7Ú9ìJ‰u`€~Ö^ª“ä´»¢tZ+m»»@Z±ÃÐ@¡"‚é ÏI!ŽÀºNôø ˜ºO]£ZÛŠ£œQ‚·[”Âè´az댳æD íÇ}Z¤=³9&=¬ÐÉCü-ƒ¬å+—RyyMµ/ë84ÇF áU¥ƒf£di…Cû¬émçûͯ-•Úξµ¸=?[àòŒ{t?°Ð¤)X‰¤*\®³ÛeÔà=žO¨®Ì'8ØË(ΔêÉ?5]Só ³l¾d²€*yŒy`36€Ê ¹µ;Ž‚Áƒ³;ø%}¶á‚4*C=GîxAš—W²Þ\¼ÊºúSNm]eĨ‚Œ:A63Ê•û¦¤*Ì¥½QþnQ&Þ=NÁ‘ÞF¤Õ²<$Ýú©XR'dG ÍÛN º`«ÎH+žn™./€2ØlÆuD¬ƒw€2˜îÎÝ\üg„.Z*E[ù}R6ë ‘?mV»Ø•mCÏ’¥×辸/õÜ=©ÙtŒ½SŠˆBê&±ðÏ“@=)ßIL¥Úv41 Ta©ÿ×òðµ­6ŒËl«øËa$¡ée¢á&ŸGŠÄ[Ó7%,‹î+¹âV~ÍJ\<$YA3æ+ÖIÔ˜æÂm¤8~Œ~D²ÚZ€ß6š¤M.¥ÉèºT85Q„ò[j×-Ùë­«Àû9þjŒËáÖ•fQñZQŠV(môÊa&7À ÷g„M8Ù?~A "’îù(Šk¡£šiLÄ‹¥Še˜Êö)¬GK x†_~cš£ é8‰C¯eã€ñÝm=Å "8),…i–­(œ´ÑeÀ†ù1‚9‰¦Åòðò²É/Ló‘W„Üš‘Î?FÒI[̹<©ŽiÙõž˜D_ Ï(ñ¡•twTúˆMÙ<8òŒŽê[~x€и=2a~øÜÜ™$!Ì—¥lœð¤®Ö1“ã7¨x!’M?g éÓœÆìåiø= —yÒ²Bˆ2ZµöTgfYàx“a^¡ùU³k 4wC»Ûq¨ÊwU\&r„‰™ÔiQᣃ@ ï…‘ü½ÃU¥–’ .@†6 ß!R,¾O1µ¦š¢hSŽVdœëÕ«þ}sâT Ã:ÎÔk’jÎ䯑OÒ ®y8½t¼¥Øê‚Ümv_Ò­JÔv¬A03~o©/^눢êwI;re…ŸÁw¿BwC6v@I€®üPºLÁ}ÃMðxøëÃÌ=`}86“v6'-䎓ÁDUài\ÈïRÏø€ŸP0$ÿ‚·ô6ÿ}Ä@Q8lUý …€1¸äL}ÇcÑHlf+Êc0ø¬f='Ãã’¸ƒ„Ãß´¸¬zD‡ÆjPº AK~Ðjuº”>Y:ŽFçºûú«)ž¿6°=¶±\fÌ‚£dƒÆm {[æÎ–ÂèoˆMÄ}ŒÇ+™|:ÆIÕˆ¬þŠá o«H=3…å!·ú4§7cEm8jÅrðÿ§ê,³JõÎï±Dö›}¾&7A¿è5šS ‹X,5½mNƒE¼ëé5çý÷‘ ‘Ä㜗öx ´Œåžþ<µ¦±méûÚ¤§¨ÿ{|ouº *—ËCðqîlj¤ò°½®jÛÌû£`T''ò=™ÌtŠ7‹«Ù¼c-<Ô¹>!öê/$ê|Ÿ£fQf@®‹6”úØß‹”ß-Ý0­Ôòü˜@º¼K2£râCÎÍË2·ˆ:± Mª…Èå-6Lèÿ£úÌ­¿(;6ï\è ³kÒÛ‘³Ö5Ú-1›¸î#2MbòÓ,7éS^à®qò=P#uEŸ³l‚„°tl¼ãocS/»œIÿÆ)uÅlÏ!첬ˆÌ6Â"ïulòûps©LÕÈ ”L¿Hˆ›oÚ(m¥¨ôÑ¢½íiÏ\¾rêK—”ÊÚlnÍÐîFy¿2”ù*õÀï#'§üa‘1ý&Ù½Âw‹é3îµz•rÒ_/] éü§PËAoƒùõ–ƒV[.jÀ’­ø rJ@¡7°óÊZ̈¶·FÜM Kfå•£œ·n‰™,==çx —Ô¬Hò>!/Þ &GPCVÊÈWm-¥C’²øJÁ(%'X‚š…Ê•–[{3ʸ¢•r‰Žä2"¥ôÊ“õðúYÒù8ĉ»6 ‘—¢×6§)@öu_Â_!.93²X¸»Pk=ë$zÈÖ(ZL†D/V ¯Øüº@*Ë6‰à}²Xd`ÉËžÁdÄñÇÜœ5 ­z%ÆrîȱÁlÆÁ,žù]-I¬8|RÑ1¬ØÎÔ¡Â|*ÇDökÝrWa-ßVþI%t€÷²’æx!?Žcõ|Ëc^ÊPj3r’eÒÄ×ïãÚqPfaœ¤¸yÈ›ç;ñX¬c,|G±¨=€kOÕ—+Kg!d%i¬•¸¿òÈ\ž‘’0©Ž¡s‹ÐÏ!'–åIì£,-•“©š‹IëÌ;11"bÒe–Ì’!nE7›vêŒÛ[¡àÇ'¥K „DÌ6\ÍJ¥ÒãWÓ*¹º–JÜÝ! Ø¥­˜’OMA}HpãXŸ ‹^œ º“ÊH›ðÿiËìµ·YFã¬X„óm1³ÐÀ™+ÅIª™è= â¡\wQõ,ZXc #ü½Ã ¸Ð"ПhÏ™=VLƒ"(ùTòÒ?(Ò3œñê‡g”>àu")Z}‘Üdši=°3 8Lcfíà‚|«²ò΀Bû@%3tœ =(æ’‘$+°´ÁÈ[<ÉŠ•T‰¯¾?ÀÁýÚü¥@©Hp—òše˵ڑù*¨ªê²¶~ãß 0i8Ï9¥éYèµ |&¡2µçC Ë _ tä¾¢*íZ£CV€X€Å4mÞhœçroÚz¤‘²TŠæ~ÝÁòúŠ~ ^‹X´Ù·F—DYÂ1u±G5D™©ýJ¹>¼Í¸d£‹]¹\)öŸG·DOVLòUŒÕOƒ6a¤ãh ô ˆ™¶(C×ù)“”Îï2éOu¯±)YÌ ËH’–½À`cU %&,æXý·€¢¼Íˆª.7@©ÀKX‰É]g8³³ÕISZÉ$4]å-:i„쉨ÍõO…nPâaÁ;Ì’ÝŒ6–Wy—‘è§ÇŠšaÝ?ÊØN /)8¹\ð²ì+§§Ô€˜äV}W¨?”g6Ù¼³né¯gùç,.Ì¥p‰•ø€',u.Ôoñ7¢e³– ÜLé@|=‚~˜Œ‹3ÛFŠÌ^™Ï¥Ö¡ƒò…KrÀ-ñeÑ2—ë‘ù¦±ÉgŒ¶â|Ó]ðžAMð®¼é$M<´Ù†œúò`ªÂ=uJ¬L»K4K&ÝŠ°kºOI‰rÑ3ºñ*öÜ-«MmÑp `Ø¡}¯‰.?’3#$m-,PÍßS’G‹ÞûKK‚å7+?~$Ýiµ£÷”×P »È’øÊ/ÓÖ ¦¨êbäÕc…A!.*$,jÀLO -fLdÄÝÄø^C,ËBIƲP,,ŽaôÉÈ ªäŦðå–×êòÈKÒÈLSb¡LМæ¶5 ã¢Ú3dP†Öꤾ´A vPKÈùéR"kàÚÉH…ð÷.€ñ‰ŠÓ^þm¦cŠLK,0kNÐ!ô^Iì-$¥í”pƒÞ•éÞP)“Ç` pÌ3Ų“J@³ H½®* æBÊÅçn&>ùLV—DÔ¿èÊHZkÇ8*eðd -*c(:÷ÏµÍØïÀ)c JÉðÅ‚xx—fJ‰ˆ£œ¯wªLæÎÈÍdv ªÈåªV gl£ÁùeæÒïÊ`…ÄYã&P$ʬåÉð± qÅìÐI' kÂᦱ ª¨6±.4¹ÎDÔlý$Þ÷c/™Ä ¹ñT#Î)¢„cPrå[,–j # ¯h§¯N¹ÑìwO LèÚÅsæSi ú|LPÂh-nmî8ž‚–¬|^LýãP³g^ÔMHGʼ©€°æpÖƒ’Ûi’e-·aô/q~6‚ž°ÅÀt.–ü¥ÊãÃ\6N¾¦ì8þ$bR~„&ín¥ä¬î ÆKf‚ !ðl jr=Ð^¹‰aæ¾abܘÊnÞúÎáûcª-f·+‘ ê¨PB½+#+¬Û!®ò-d-¥r؉`¦Êð‚…é!æðëë^Æ=LP¹Xô+`vä­¢œi“‹¾½²¨µ…ªåi‚袹®,ã]ætèB7ÌÁ<ø¦RädbBþj¢"QTî%*œ«bvï8¯Ã ­Í ä¾ð f/°Ó-ÈšMKÞ ¿à– ð«i`C2."°“ /q6’lmD´U…À\°J!å'Lh€CŠ~ÍtñnW'}&IÊ¿ ¢6ˆœrÍÒH½Ä2NžÍ&ïÉŒˆ&" jÎËqLDHõ‡ÝqÍ.²L’º¹¬j_6$ÛLôKTÝ£(b*/kÀ}q‘=ì^“AÐä°R qÊÈŒððâ*ZfÖŽPpPHæ0¤93¸âÁ0€?Èzç©Ð¤Ä‹>2ÍÙ².Ð ´Ç¦F®.{ª:´'o&£MÏ ®´ñ±ØGëF¨b83c-hNêK}$Å5E<ý¥Îãcƒb±"Ò±gÂbˆ6|Îr!oʶìƱ[°Ô™)^ªððÃР¸ÂOv•¶‰†n¾'ö—ì@âÊnHO[.IJf!÷J…1K­«þ®k/ÉÊòr²PQuO*بc¼$ £E¦¬Ò´P« èÀø3 ­ùT²ð##÷I ÂYbž÷dC+½É[/“çKzfœðíàˈ×"DÞeÆ™DRú"m’%5%2-o+ð$"=dÞä¤mÀ0dIUg‘f Ë+,F%BâÚÓä¿‚60b2þÏ®)ˆµiñ“‘ò*ÀñT=çBƒn£µ½VëYéð¡I’ÏvôkG¢ƒs‚@Y$”}SbžÂOE„2PpüsÆ¡A¯s|-·Î°VàÕS"~K‘ÿTËÅzŒld°Ê ÷b¶ó`|Ôˆ,;‚9hxo«•"†merGÈ!8ö_HÝ7€Þ ¢…ow~˜E{O©·KòÖ¨Ž —StÒ¶SG¦#´'F4*Þ}†ÝU)yj9N–2Éê.%4]‚ kªhç„䂲oòÊI~˜’±Gm>UrÝÄ­ .iˆIS”¥öP-hDö+-hÎ×Y5ääÔ[%ÁpƉ@ïº.6-IH üï}G•{*Zcµ5¥£_e’Ü’Ë'ZDÈñj’"tØM`θ¬—owrñƒ®ÇwU¾Ìkµ•×q¾*À¶O£ Ô,¦öneiñT˜‹× g²" ”- P+¢ËË0,çõÄš7u ºŒcVÌhè¸l0šƒ÷iDb"͇˜y‰Ë/;Ä2}”/÷Årkjðq'‹IJáTò Ì8Ü’Ämèm{³ä全mƒ“/â-³äVi: ±™}Ëðµv¶¬ã,±õ*ì%ÊÜID‚™'pËN vUª—†¶ènÚ¿â*55/÷89”ŠÖôR­åyò&êÛ8‚²Íþ-bþFˆÆUe[ú7O ¯©’÷©váÍLëN¡XöÆÉòs¸Òð&¼/tTFÏq¼n§xo¨!ŸS7CöœKK± õKm#¨e5„úXŒ¹Ëk8ˆøÖv|ËÙpÂU÷ë %V Ë\0×–õl‡—/èÐZ þŧIWÖÆŒú§£Ñu)‰:¨+’ªãh0ÜCÄÃ$ÑMºà÷—ÜðÏŽY;ø¶¹†*¹¬*ÂÜ×ïç@¼#ƒ‚ëñMb~h—<ÿ¹s:·U³•Pu@öëˆ2—§¯dsLtq|þ+Ì,”Õ6KHVˆ¢Ö5bã+eÑ…†¿0£·!ò¦p¸¬X×Eʬ#l±jøg@íw¥£+g;éÛY/vÍ‘X ·8¦m-Kf\¯íšÏí’€¶÷"—F]`Ï ·qÃBI'+u y$‘99ω*«‡Í%IÛ[Îr³ˆã ¤Ï%Z†eΘàkz¬ì¸Ú›;jÿÕ1 hê‡Â‰™R\²ç_”­ÃЯ.‡Ìلϼ„ÔäçÆV=&¨Jððªü /°J/øMºmÁ•ª 1ë0©Ȥµè" ”:)ò§¸Ù¿i£~›* šj„Ám² Ë2Šã'ì-&ŒÚ®Ï€éz|%k 6Ž*ËÅÂHâÉ©\N2L 2¤Çè#Ž&­¾bˆ°¶‡âàœ?Ф8H ’8þ`ðÔ9ˆ„<Ųk|ÅÌPz<â É3t¦É2`¤¯ ©-¨ù%€hS2Ž=Éò“°+ã8¶ò¤ÐÍ" :7Lz‚% ”BÏ`¨ôâ’±ªñrð¨SIô…´°ÑþàÌà j~¤ÈbP¿-ڮ៬<á20M ˜ªŒŠ"¼=)ŒŸNI¤¬ÛŸ@ªBgý–ãØ–ZØ  Ç,$0ÚÀ ‹%u+.®ÔÃQ¨òO QH «*õ‹†úË J€yø¨B7UR‘ÏÀð“HW²~õŸô1cˆc9Ì,CEªìÒ&ÑÆ@š>À£bOjJYJø=dGê”EÕšL•ËÔ=¡Ö%®´ch#LÈ×D¡Ž%táZ"²@Ò‰s®©zñ¡UʪGhUg‡ÎŠ¥›¦«‹åþ•2Qkz•àq»•ƒ[˜F’¾@’Íß;5Õ¦œ^îzU•\ÌI÷ž} ~’Ér¸WaeÄ© ;F”s¨U)§#tÒµ;ñä¼µ¶ÑòýiN!òÈžÚb‡8(¸Ç$WJ™DM(ìBó.AÚ –mÏñ ceÜ‹{¯Â±Ô p1MM02˜µæóÓãÎ:0y’-˜?Ü! ;11·wøXJ¢°g.©É1ÃG ‡Û/Mêù»˜·øudM2‘¢«¢LXUWp6 ½’" YRkÝÐ&M×»Ã6±=u€3¶dŸûc‘pi íà9,$Àî“H.æ×1 u‹$‡½²Û& lx‰MÝQå %#{ ™?˜§?”,&„|9‚p… ¹ ,&m˜²FÂGÙæaŒüJ6€&x)»œöBQŒWLHø”,ù(Dæ¹DvïÂS{',¡v1 D.fþ¾ j$}ÌaÑ(‘úéÔ<éä(²Ä\À â‰Ñ!Í6äúJ£’ÇmÏÝ·¼èœÿ§}ë-JN6û1@ ŒIجÀlCÐQƒ†òTÕÝë·vÄr"—:¥¨ãu{P;”có:¤¯õ¥Bv’ˆ»pLGDDiÔ”Sš%¬´‹Ñ¶#ÇüV  1èpGaa)2]!Ð ÔVÄjm#ùWB€ ñœÌòC»—È?äë'%M‰€ià^]s¤™ÀÚhÿ¡ûtW”äC(rå‘ P«Á133.Û"™‹x…PE°š Ä}v¤'(ÜËÞqÎÈÄ{@G ½5` Üþ-yå úŒƒñ!,ºäé]—šŽ¬Ÿ2’aä\éUÄÁ€$óØ„Wº·žÌR©&‡T‰ «Ž!*5¶f`gM$‚‡€IŽ?!x ~TDãœÐY (<p¼ApJ+˜ ·%e­Ç³Ù0˜ÄbS唉•ç~kzºJDæjœé aK2‡·TAþ:#$Ž×§–Ø`0ßä>Š ì¼˶o 땤-%–½ ª×V÷œšõ'‡ë‚)­äš‚ | ± $ÕbnÅåJ<ðgM"¶[”e DTŠÉÜ—[«Ob3LDšñ2G€ˆž>¢ˆšÿäJþÆY# SFÚTþâÉ¥)8Qá+èø¬å2­Mœèæ[nÝd=@B8™óJ‡Crá\% ´º¸9°Œ;ݾnv›; xÚùfpÑlg¨xõó»ï~ †`[Ÿqð¬ü¹¯Õ&Reõ±c#“>´ì}¢ +LHô õ;œÉ'+òˆ²à.–"$JÚ½þQñ…j«ãøLr@½"º*¬ìm(Ä %}ÎóC%gòu þv`YÜÐåÍ©rR»ÏLp*zcTWAüÖÑ?t§és´®vòG!þ°ŠgšªÄó(‡å­Üç±ëWéÜ{æ šDMbD¡^Y¢7¨æelœUÙ7MZ)ŠEÕªˆ¶Ì¼ÁÌp|Ç+¬õ»7€è%g®—9aKç+”˜ÓY?aMÂŽIÉSYÛ:Üäeöò†Îß*³|­kŠÙž2V_,ôø7ȇM8Ÿ  ™§¼ÌC3ºeRþì9Ãì”À«C°¡Á¼ ‘ ²G1ÞÇøÐìRÁ À´ÃG„S&ûY2Ü­6:¬Cùeγ`è¿/à ¤Y ¡«²’ŠŠ ã‘!mQŠÊ ôDÑ<°Ð|$7B¨Ê<=  2Àî "É»š¤LëD¹<º\>SêOË9^½D,Š.„ H¾/]¾°ÞÐÔ=SÄ»$,„˜…BHÅÝD1Š›F˜š>»G!Ô™ñV*áb)ª>Mdº¨}FpœA¥ ä1£Z3kÕ¼RЦ¢ÕVÕS¡iFtGÖ¹¢Ø‹§È•Ê3}Ž’¾Äˆ r¥0:*Á@À™3fC„ hñ²ñ!AS+¡DTxų•Hx}!Iè*" Dùÿ&ä5{u½ˆ»ØD¬Öd)¹Ús[΢Ñ kn¢ÿAÔç¬>CÀü,V©µ ™ÔÑ4•ÓŸœ‘Ñ< õÎòÆÔÙà¾7¹üH|»$YéÉ(µ§$ÿÑÚØzZêÁ-l *IÅùCØ£G£jX««>E(–õ=&sÒB˜ [ÿ·{%Š„%k Ä þ®»ž2úëzfU8‘£6*·1=y¾*’íeÔIì•\ˆ®"*Ød4õ~ ]ãÅ.q\þXs¹‰D†.2›@é!A>Þª{¹ˆ:H³âK5p©›A(• 呇ú‰S–¸êÙ*IÑÜ«í2ü&¾QL££=®»Ð8$NªÐDoЛlšß×nA õÓKÀ#2Ø•q’µ ’šZ´Ô² ÁÁ«Y¾âþ[Šx9%âÚ‰¥\Ù4žéŽ[˜¦¾`Š ¡ÄÏÍLàê0}ÂÜ'­Š“—@í²ó=WpµŒ¸í•Õð1TF¸&(0”1sI³²ŠªÙ±ñü—ºµÉ% Ж‹/™ãˆ°löÀ¹ü1»ßÓ¡ ü0jƒP=U%˜ÅS;+ ý2ëc™™FQ«á~–m3ªô¥PÙÏ@#¯²(bt¦ ßNÙÄ[‰R­YݬK¸«Æ 4ÔçW´C *ÓÅQ Ù´}Yè¨ZèzDjRRåT½:]„[²'Þ%$ÛÃHѬõ¡¨,ebÕ‰Jb¹Õ@°þC|¾È¬ äo\ÅqÛÀ«Œ=¢äI!މ Zºá³ Ü »%"œÀ„¹Ñ1•¹É¶Ür¡M€ úëãDA›LEØS ä,JÈÌUF¸}ñ"V 4•Ë*CŸ•fL,´6¢õžÕºàØŠ‹Äº[Á(Y鈸¼ x8“ »ó®PCòØ>…Y@Œ;扲aaºÀ3Í ñFcàÂ]Šž…}Ãç2£¥5Ÿ´5üÕL-‰Ü¸²a-›(Ž íˆa ¿8¿â}œM]Æ•nèY´ ¡ÛªlÖÁ[£ô2ôÆOÛwßÝöVY.“þÍ'3ÔÞ‚ ˜Ä˜]¡ubv[±õ1AéêОF@UX Ù9è‡ÜÛð+ô•?#IàýŽéò¨HžÔê鱽YbL£¥Ü*ç6¢W‡Þ!]b[À$F§‚¤áHÕB¿eaa$*º×–²½¶âX‰ÞûêBĬ#¢,ZÑØiüç‚ ŸËâC÷Y‚ Û´[³H_CÅß ­ÞaòÊž³Ž‹ÅR·Ì~ˆˆò¤¸ŽP2±óÀËÖ@Ç-\ex\*Flhª²ˆ5ëÙ«âS¨¬æ*£ ™À&¬µ/%ÆŠHjnX¤•™Áí»ÆO%a6x|´B–€+/N@Œt´0r»Ö¼94Àe´‘žižj /ÛѬèªE’žƒdb>I>- N§‹“¢û=‰±D e[,¼߬>¢L÷šQb]MG&¤v½¾!|ïÂxR`‰5Þ×™ÜÚ=õí ŒñæÒíBg.;ë/4Í´mkZ)â›§«2½jb$:†?ºdpø³±÷ tì‰6\ÂbSà¼Y V"®pÌ1™©æ–«å>ób"‰=sC0†b ç*Å!'#Ù‡:|å©(›í„°Sh‹‹ f¯Z´®v¤bÓ¢^M33Átc>ÉBµ‘uóÐÅ=~X•‹'5¶ä£PÜ®¼H‘ö&ð g]q]é[w4¡æ#íY6õLðöiGͯM›æÎp°ËЂ,ˆšíÞm‰‹ˆIY¼T8%sC²MwáN.ßL²›ŽV B¼?¯\Û¯P‹éò4Ákò³¥Dú)¥°¼.Ûˆô3ÅøÔ1ØS áÁ¹ý;¶0J|À½næ2b@{"¿‘Wø¯ usháiV[ØÅ¤°9óòéªÎtÁGçõ³Ä£/ÁD˜f(Ài¤ïnZ>Çi^?yn™+Br1M𲑠_˜¼gšf•Ù“Hwµ ƒ/Âü¬QYÅûCtñ/´=Õ͘²ôùܨˆŒ½‚«[ª+éªÌʱeRæšÅ‘½Œ!y ‰6¥Ç5e>M{ú S㜓!ðŽá‹[‹•ÙüçŸVu )r¥6ûþÙÆ?L.ÕáÃq¬Ý%´ÔcDÆ­s"Å"í»Ý9€$#š 8»P…Ò€4XßFìœ|E·,c²£yçQg£òŸäéh˜JÁj¡ðÑšÙû鳺ÔòÁʺ‘örµMˆ›9™†Çó)«ÐF¬(шQ4 v‹$H‘"Cñ‘“QÔ)û}·¼cÖˆ‚àÐ@ î†A€oøƒú%‰E_À(Ä:ˆ?á¸ëòE Ec'ì¦7Éäñج‰ù.ŒB#¯©Àu2§Ó‡Ôž?¡€"°ˆsâ•ß4ú-I$‡Sß2y4be¦Æ QÙKöDbQÐ-¦IŽËâÜn‡B(¶dBx‰O€Õˆ•¤ a°Ã°T­‹‡L¡Oºm•ÿYFî)$ÊÜÿ°Õ טôO+³Ûå1Ûµ’B‚E¢Ry%¢ÓV°ÉðS §<`£s*.jk©¯Q¢W¼#öãD‚g¡ñØ…ËSåÜh½ K©_½jºÝëãû·ÑpÀ=.mèöv#{èRVÖs{ .?þàA`Î*)®C”ø¢M!ü¦¨rÀ• Oè’; ’üÜÉj2Ï¢J°¿Hà' \0ÍÒ÷¶jzüº!È3’Â$ì¸Á=l›\Š8ï(’ñûý£ªQðHÐ"6’,2$‚ŒI(cA.­K°°N+%µÏºÅè2Hý¢±‹ ƒ/ÒÌBN[ÆÁ,/kªæB(d‰Ä®2.ŒEÀ¤ Ï«F1íúE?i:d°ÐÎrežð‚I3ÎSz “Ë[k'5hÃÆ±€3ÛëÎHë2‘Ià#P‚JËJB‘¡Ž­Z™Óˆ„”Ó½sªÁC EDŽ,Çõj±"K ýDTÓ’­R*`"eÊ- „C଒FëòdÐU/´3C£ ,”¸¬£7ܨ%:‰T§ã:†A§ëØü/Ò%vÇËàxP5ñþêÈOKȼ-‹L~¶õûÁ*Ö”*HeöìV3 fÐÓí)ÿA *ü«)´t¦»Kläï[lÛÊ#y ~#lŠ-GnÌ gÇŽr6 (©&<&6=øì!Ø^ÎpS`í" i먩¶ÝCt`ŒM0UùŒÓ >±»%^½ÚÃǧbÙâžêÞì“«çH$Ü”¤êÖ¢Jܺö/Ø!ÿGWslÛ þè5/: Áo–J ‡X*´í<€Q»v‘n¸S¸Ÿ´´aÀØÇç»Í<ÕæÝÈ…²‰HÀR;ªñÁý&-0b!º'HD×~dóÒ&ÿ¤]¡þýÙ°Ô/¥®yòýâ4ă#¬o~ƒîÇõVº©c¸áà%ïw䛺EÒæšÇÈå³nÆÁ²=Â]O!šSCmÿœª©üþB„Jè4ˆ’Zn ~$B*þÖñ.HŽpºDÒÊÓùh€•f$ã`j./a~(f’N*ÓV TŒö)™k!ƒíS¨5F¯ß9ugUG!R 6!¤(PD)2€5ŠÅ^»½m)€ªs•SKЇú—$ºÞ©@wp‘ìÁ‡¾°„<3 l#žô ÕZp䊯gˆ®Ë *`&Ø´¨—âé•A1êîžbÚy–!>Ñݽ§B—Û¶ç` ¶çü=Kƒü‡wÖÍ_|V_G™³$„å8þr¬¹¬ÀSǰ “ÄU9ÑúI€1çáp Y—h’Iâ9Ág¼Z»å•hF¹3¼}]i 2Œè8YRXYqRŒYå§…=,U<•|S%ò8x>¿Sdµˆ/e A‰¤ÒÛ3mjËÅ÷älôÕ<œ"ªì‡IÅ$ÀbT#e¤ôŸ?{©Mmåm©äb`‹òK)F bË€ŸcdðÅX™7È0‰±vS0X¿#x”ÄÈe›êÆ3 …–hœ:µz£Rj‹ ]~ ´¾½-;Ï’cͨÙ)cPý‰N*,J“‹,RÙM¦®„Ô¯µªéسì1½ŠÀ‰¦€J!R¶ixz&<±X3Œ½³êu[Ã(²Å,é*ÙdËGV$:€$¶E]Ì©ŒÒœIVÆmulÊ8Å€’HÔG«S„YOˆbOªZÔ)ï'¾ÈDC õ„lþL0†àg_+n¬ɶ*;’! í>”ðd‰’»*ÕæÈThÚž$­{l„“¤G³É&ˆA®’,µˆ"ù;ÅÂhJí·ÉÊS‘ýG °äŒ”W•SÝo{'9Ø2þï(j±wœƒ?3@}Pƒ_¥ìÖV­ PÊ›-c„øÇ«ÔøÚ|=Þ²0·-Ÿ,ßbûKrå1T‰tBHSE„û!éŽÊmS:Îᙸrø¦b€¶‘L äóþ§uüö,âNcÒmÄÉ®ä¢Ù ØCnËB„úÈ>+E3$¶—5~GFäMŸ@˜®¼•g€d¤ú­&gÛØþ•c¥P$´Â\º\mV)7 Žã±ém¤UŠé¼ÁH ðÀ ‡Ø×Ýc¾e-,¼í#AÄAû^nÑ´'zÜb€4 @X  „?¡O¨`Ä^Ñ0TUù†>q·Üuÿ„HdPð$–.ü~Ê@R¹(þ‘B!†Vƒäóp4õó?—Í¥pù¼†ƒœÈaò—ìæ—Ó%ñ÷ü>©1Mç5JdÞ»+“Ö$ {%FS–ÙôÊdœo¯€©’ØÌ>9¦U+Ò™lÞO-‡Ö-’˜|ô T“Ñë6½R“ªKä’[¶V§TX³S–Vµ9ƒU#¯¹|æï—èä2xˆ&ÿ%ŒÜòêľ‹Ý!’x´„µS,ô®ÌýÛØ²·k " ¿Üp0]ÿ-§ÞcõlÌŠ¹|’Ûq±üø¸ÿ—í¦ô8u>3?|Ãéõ?®W˜îý8‹"…?úB½%jS+*»q8Kñ£î“ö¾¸ÈT“¤ì2–”°Î²ü‹´à ©‘ Nœµà#Fª)ézZѧ)zžø90PPCG I:˜Ã9-J:媑 ´´3Fž'ª2ÁŸ®ùúÃ)ò*)E-  ‡¼¼–¥²;à¦>i‹†-Mëz¼Gä;;±´m?¯;Îã¦îÂÑ#±òRœ¥±„Npl~ž¥ëªû'2ŒÆ(Sú­£óþƒ¹Àž›¿çóFåÅ/<¬»PP[–º¨RÞO‡ÜÒÔBÔ2SÔtQ!¡Ô "íZ/FTl蜴q-¦/ë¡N· "Á¥õx©='ó ¥‰-F¦IÇòˆÆ‰{ b#°ùø§¹ Jƒ#)»–ì¥*Ä’ºÈ{¬ª"g²ŸUÏÇêCUÉodIüa®UÏ»¶Ê®1^¢ R3uÄHBO^wjV¼Vhý¤™¦°kû9?,åb4ÏÛ.¬B.ÞÄîzL‹ÅÏ À[¹=ž¦ÓNå©jrŒÄo‚ŸS³I>–‡KI{àj—ë–‡Ì÷rÃ*”…+¼‰^<¹^(F´Ý,˜ £÷«÷H¦6Àª¿q¹³Yæç#0ˆs[&5¦R‘Øô$¹*Ćєn3í¹\Bª> :ÕŒ[„œÈ(UÒè&‡ÂÕ[ÕË'3#¿·3zë5¯…)º.É2–ë¨dßk'´þü…W‡çW•ºc­mòý4æÃ¸; ¹62íât+UÑœ!\¼žÁöõzê#´´èègiÈŸÌvƒS²¯Ð¦^n:ÕéxKb±§ñ>jZãîû×òwŽéý+ œó¿ÕOÛôAd…xÕ줚*%gÀÁUòþÖ©7^æä’¶tް—MA©}“—nz€©B£ùþ¾qþ¾[9!G†n¼çÜ?Ø3êqð :vBÁü)omÍ=áø‚C¨!Ìlª´l5b†#)”@¦ GaqL#`,¦;§þ‚Ê[#ñ0ª´ÈAÁãv¯ô*#jñ-_’·®?’HYѬý Þ!È\¬Å2qÍ­Dm8‚%úµãQ-KÃÞ3)sÌÜÙ© 4p5×®—”­ ÚQyfõ">… óÏ;È3jtëÔÖ¦R„TcÁõ¼ÔFŒˆ$·NB;HØ~ïádI„”°„©kõŒ.q='^Á”º]NI¹½(ÈZ£Jç ¤è–rU%rI>aô¸5DÏÔd3p,ÍJxþbÞdëŽMÖv<ù?‰‰7E²íjéZÃá ÏÎ¥'&Gå¢ô!MqòbN|$„Ú¬´èÃø\‹Èó?A¾~ϨÐÌÕ„Á¬U…T7 €›%n†f8éÆIe“ž"é@ª4höŽ!#€7Ä•_Dy I{¡V¯4›–¦Ï4•k0¨O(Á'zœ s–WGTv”Ãt y[:;$¦*pV2C&rI¡‡¡í–È\Æ" žµ§ÕgpaçA+­k4F©NÓòéuëuüFDFMécA¥N><•À™á4"аþŽ·“ÎFR¡“ræd¼Ú— ,6ŒCýÐÁ¢ äÉ!ŠD2~˜gë ijw!GÀ—Ó`O’{}ö„“zĘ+²ÂD2à¬Z»/’™=lgö2U¤2OK‹–,“I3Ï7ÿ&e9Š¢ˆ#Àۈ숹†’Iz*Zaý$تŠ1P´«u[òLÄæ¡8#’Û$¿h&6¨4<Þl;yTqøWÉ>ô¥;½mR~~Æ~¹ìa…Ru¦ ßX(92éçDÎf*bqpï=ÍÚ+øJgít­n…aIû|GMlm7¬È”Ii?)X$:]*à‚?x‰*g #í:GDÜîHéLZEÅ-d:#&==¸“ýÐÃTy‹Í#¼kà0Y'1+µHòÙâÕITd 7Cè—±Y'ËS¡)éž"ÏBDIØ­I;³<Žª¼#L‡â6ˆ7šáÖÙÜàOÄAgªäÙ¿õ„ýU+þ\ƒíÎènÛ˜õ5¶&Ï\›Gì.Ǭíyh» .O§îîø’µ¨ó¨¤“§Y“;-ÓÊÅëj!£íŸ;c  žÕÒ[Æ8êH¼7-X¹ÁÄTGFÖÑÈh†—³ÄXÅÙªñîP¹šøÜ9`vNDÛ®ŸðPr†óEçëlOÜ5c‰&/;:ÍH¡¹ý×øÖ°i>{¦û×óÙpNIÉ Š¡vJ<HÌøÑÌ»O}Ož~‘•DÅñ6½†[+”¨8  ¤)“{ iãÍ®ØÅó3}ÄçìÑ$¶ rÕ$ë(Ø·Áþؼq’Å3gqQNÖý ÏÈz«§­fËj )šÑâRT|?WÀlSŒÖ†ˆfÕ å¼ä»JYB˜žN>Êy-º@—É8¶é„{µú—0íß©jÞ±¨ÖêüVO´¼6JC2È÷*HCc¥¶þijù²CÖ–‚Õ‡Á˜pÒ¡–€®›®Edqbã‹Í˜Ï­YÙ×)ð}¡µQ(ò~òÅq‚:Æ?^‰nÜ. —ij3€^Ï 8ﺟÏÃ8ÿ€Ðz±ë•Œ®î6P>ðm‹^tÒ?ü*·o¡4{Cøè5"­Èe ‰Ï¢`|’©Þ“îÇ9mÃ']œa¶«|Ú€ä¯Ø©¿HîœíkjÛ›ŠW˜ÊN7«ð6"R龜÷Ì0<é¤á BOhûÃ∌~'¢œ é+”*ÖÃé>˜ÂZ¢!LºŒ†ÑgþÆŠ;¢âlïš”C®Þì”,ˆ¼:çà#/뀨tœ…„4c 0ËJ…ht…  U¨dåÉB*ƒ ² jšmZö©ê\É8h$¤øO [ª¢? ¦áKò©Œöðb‡ú×¥âF†p¤ê2Ϙ} „Þ' }ŒD`„Ž'"ÔÈh6±ª©'ª@ZbR’°Ä C@¨ Ú…ÏÆÒ†¾Fn &zCZ@+0'¯\Jù j*¥–ú¯àûæ>¡ÏˆG’%÷°2‘*;ªŠ,nj"…P·ï t&*HåVÊ¢#'¬£å¬áô0ÅV>„'®rïaøâʶy¬hj€§®Ôø†àE- A¨tDÍŽ7¨òõ"ìâC–•®fËb°ò*ÍÚá‰`ú¾˜Z"ÈóNÂȱ:×j)‹Ì˜æö‚B½K Xž*ìO,‚#¢ÐÞòãÉâÐ*àÔ çà ¤ª[pÂ]0±8¥ª ÎÊNâDF³$eZQƒX".âe¶0o$Xl¶Ÿ¯d[Í@œ²B¾d•Êø¤ñÄçJB1LN¥„šÍŽÃoMçü_âÞLä ›‰!'¤t&×-Y(+>§b\ð »JB¼Ïø¤Rœ¢Qp"¢2ŠbÃî) pLÕ…;!Á ®+îbžL+'þlãzä§üQD˪!¦åéx=lZ`Jz!í«2YÃì°S¢~Ÿð¶&.Œœ°ÂSªZ«a%£–ÍiHÎÉ>A ÌÕåºÎ·,F®Œ>e¼$I™DÕç‘ð„ð,…Ft# …ˬS«Ìt‹Ì^nsQB)f#«\y¬>ã³t$­9!"N4gFY#ö·£íˆ¨“+p!Ò8ps¢Ü1¯zÍë8žâ©ÃŽ7³1RLDU5°ÐÑáŠù%©29j4ZÕ’Ôñ&šª } ÔÞêì^nv¼—gêlbcjZ¤Ì®rÔjQ3¨:ãóXç睊Œ¹à M¤f'ïz»ÆV¾ôÈhïŠÖGl4eWà ]&`±h¥¥òmJ)"t(|¹4>ùÇ^¨\ÌR¦Òú§´`°f-l14t'!ö5¤SÂÚ²Ú#âŸH"±DK~uì*qo0µïsAG‰.p¥E ÞnÌl`P_-H”zmLÅg7Žj¢JJ‹g¤PñÐ%dθŒ×0§4öhk#d’†´‘KbÞGEÊ>ÄF×r ›Áõ§{"É2… "Hêt@.Ó ¡öS¢3“ÔÞòˆ19/ý(i‹"K$zC '±ÞötÙ#N„_Âð²õ%¤ô±Œ#¦+´°)â_0‘ê|±‡·èuSDn— g‰JUk%°‰F«ECìw¤lÃFóG³’ž &­iþQ"OL0> ,’R#+°‰¢Þ>Ô%´np¨H³ %´xæÇL’5=4/MJáþFŠõƃâ:†ç0g‘ôúÙøD'^M±½?È’ÃJ+pyj6Þ“ÀLjÄ!þŽäB`Í6&ƒ’¢”lìgk¾—j¤åÒR±kC%N‘tª(´Œ3h®‹Í s 2‚JÙ’°j-WŽ]&"°CLŒ¼ÆÎ1Rÿ+ ?$a²G8U± Ó†á0,À>Õâ!‡^çfHRöe…¬±®ZL þ=kÕdÉß(ÂD¬pËÒœ‰&_‘³` t.¨Èf †ìœÉ÷4ºÐXm#Û<´Ô  ,2R€¯5”#>‡-ã*nPÃŒygŽÊ3äy­o•çü¿³Bô½ÔI rRx„l<£úŠËÆéÿ5çz•pXùÒÔ”1Úâ‹Õ²‹LÔç(M¶¡L¢‹xi4Óå(ˆq¾?­4ë¶;´Aøñ´éd‚ ±bâڢ⥪JÖ‡bÐ,3§¢QŽOmY"-yqöI`¿ B¢&òΊgPa'lí`ÈálP”ä¶ñ šL8XF`¾¨ôSKÞé‹%­#T°å.)[¬ë/gƒÃN­50Ÿ³&ž¤õjZ÷Çw XÐfó*ôÑzCgÔÏŽÑ,íXçpÀPt•|iþ[®Î)ðŸQ§~7bŠ_®stÖhrSMw3 ¶·ã\­öÃîÖ›,ü?xG‘åt`’rowä ‰Oh~a¤¢Õ,À &øé7`—s*SµÞåóGFNÇ …Ç„1Iwbnƒ0W76Žx3äsø -î׬­’¥ÀÇaOÑÕ+WFW‘›jÙ<jíEb?F0“턞2iakÕ GT÷#W'¤ªpŠ=u qñ8‹4õ¶tBÈã.³É…f²³&KÖ³J2`‰þ9y\{¦øQ("5•Z\—¸î%i&!êHaXiPo†ãüÆó¸ ÒúTq½*ù:äƒvå«pr¯-V=bsí%+VHŒãI[³cµÆGòÉHBKkÙuù›$àÎX}°å,I‘ÆywjBù)Þ4dS,3Û--¢ø4åSÝ™÷y²ö‹˜"è½u–áæÏ,¯_6EMÃð)õ£€ý ²ûÓ à oÚQ5W+`4=s`¦~ÊhÓ‰’=+D)˜(“åæøTY;ωà Ç’ïañ觬ušÅ¢9âLô©60&á±®¥‹ÆŠ"$pâ..±wT!ù) Ä8ýØ©;ñ˜x (-J4‹ÈN´ñRò´E74pv¥ùÏb œ9×gC0ÒrkQ\ªPg33nùòU¥çBJ1Ta€ÍïëzÓQzn²ªò=gë$5éÞŒ mT ð÷H©ÔãbC ·ç2âX¢¤1L‚v}™Ôq‘ µZmä;ª¦°Ã5«‚ c[°«yNÃy0®ÆÕqùtä‘ïJã)nÏ…Œ‡/ªµ˜Å«w÷jŒ’˜[Ä™S¤´ì #%$´ôxšñQɦW nx§B5£“§Aô¶ÅÍ&öÃb’úûÚõiȆ¢o/ZOnÐPc Ș©‹i¨V?ǩ٩\hÔÒ,Â}„yÌ]1­YM%+ReYœàugº)A©…Š5Ãó[ „ÈlhAVB±%¥ÁÏÒ¢EGÔ|s+#bzfƱöeæ&«¨Ñ™šÈwv-Hu:ZœE&1 qmî%ô¹8ÊV#©¬üga_6õ°B؈8_}ÉìVòfGP2´$6ú-úrµœö¯+Ÿ+`h6ã‡ü~YŠô×··ôv 8<çñÄjÐ’ÖC 9¹(‘gfLøÇ;û€»ãa í¤¼Uu•l»¿7ã6Un,‹Õ‚ªgní¿"c àŽÖÏÞ¨"hG†0)œòÛ'Ѩ‚Îmè÷â{ýY¢:¾E×Tœ·çLæÍbC#3p¥Óv¤’Toâþ†ò`ÒàlêíÐ u›—¤<ýS®Ulh‚ÜüÕtZ%z¤¸K™ÉÞmX®$¡ßêbnb©î”îç+Ëâ’rÂú pħ‹ÉCìƒìThï‡^çÔèj)àcal¸\?Ù ábÈöPnÎPl&z55ú÷©?Ÿ"Ÿ®¡°À9ÌšRìÈh¼Ì§ãä½0Ö>` …Ó^…ÅÒïúŒÚÇŸ˜jùUX©¦õ&>²gŠ">ºKÜÝ·rb8ùávß„ˆÓ:XÈòýÕ"~ÝÞöª±Zí½à´+=ètæœaîõô­¿+ÏW¼ÄrÓ:žíG¯ FÉ¥5f'vî®hQž+—-ƒð¢‹ÌÎ"hE>”Ã4ÇÈHÉï½w¹¸ã¤ëÂÉYQñDç [óÐ}×”rŽ  ÿƒa84 Cá Nþ‹DÀOØÓò9„cˆÓö B ±gô~=‘ÆsTŽb•Gã¹Ô=Ο`Zqù#ÑæðŠÖG*“>jº•õUЫW½nk–A ´ITb5Í&Qh3âÙ8€¨`UÎa1 IaõWÕ¾3ˆßðÐ Ö zÏ@ò9Cþ?&ÃB Ò¨\ Ý!Á`¨“Y5õ/¾Dëà ‡/”„Ãn0XþF/“bð1˜k«”Ú ºP§Ýê·Ûld"É€ƒjxqð 1’‚Ö#÷~.ÀÿØõcò¨f…¢Q9^\‹Ðo¬q;דΕV+o|F?1¬Wb{Ë sz¢1l#n?N²“$È2F½bF‘¤ÌÊj˜³Àœ¼®cÛ#I3´†¶¯B,¢<¬ªœ‡ž‘BެëóLå0Mœ-+ RTFéT9­Ä *ʤºGúG€Ïú¯!³Fð¦hÓB½$ÌBFʹ 4x>CsF¨³Âê7íâøÙ¯"  H` +ê¯Kä<Ñ8ˆšT¢M®CX+ÂôÄ+µ ô€SBF¬Cgë*§ªŠw/=¡Bzš¨“z…ª¯Àí¨RDT*#64ˆ8 Jj-)¡õzS$”œäð7Ò"Lì¢Õò½U08 V ;?²X+)IÒU6§)Ó†£(¢>+˜À¨<€èIˆµÁ¦´)ìÆ¢l‡¶v²uÙMh BäÅ4E•ÁÿLuùü‘ÏÌD’óRéþ 8Oê>š©/u€‡àpƒ>2:U‡Ç¨4@ª³‹òýVèøŽ( 2‘Ž ³”µˆOHæ3Y*¸M?cPäJ±lîÏÖkdý2·Õ'fdR*5œ&Ùšö‰Ö³ý„«ú:ê¬ÔÒÓ¸R=g4 ¯‹ZÜÌý0HýâˆëòjÎç¸rcf¶lÂ9ˆ#óÔªâŽM3Ÿ1{»Û^¡ë-Ù«Ò°úd4DòÀ—ž„UGÛ…P½—²uÊg Ô[²±Ñ@'þª~Hì í,éÂ?ƒ1nJößñ5èm“´Å¤nD1rYý&á"=«CÕó'Û×–"u ãñŒªØ|%@gªúSo㦲¦.ò8Ä¿±sÛeHì»ÑôÄ( ‚JÊ)r5qâ'ò‰g¹I6ØÙÉÖr7|¹5Þ~Çâb{ „ÅNL[óQJ õ¢£ä0¬QEF•=%ðéѻ݆ F9ÅÜj@`0-˜æ@’i•w„q`ŸPF‹Lϱ·"&ºQS…Oå œ‡üÔá:&¯ˆ §³Kâÿ/Omζsª¹±p ýWʘ!²dQ˰† ˜ÝÛpÉmSãél¯Ä(¦š'„ô“<èp `ÉáQRÐÛIyHùˆôÚ¿ÉD Çp¨Äe ¤ !îX˜°eî±]iWo¤Ö ¨H«†kD}éDR„Û³= p½14$}Üðû6daZ£YÑô·8ÈÝHIBTÀ@gMcœ&¢ŸŒ~9 áË1úãÔœSŠiÊUÆÔ\…ÜXÒ‘ÿœ¤ˆh`*FF奿–rF$#÷­ È49ï)ל²#’%³v$+|KMñù·Çpoœ=(ä¦78ò4"ÆéØHiܘ”=©ÚÏ%sÞÈÿC´TçJO¹1aŠM—¦-H|K“är@:c8_ðüa0EŸFÉÇ (KýªtµÒªØIéDhnÇA%&&Íd•„€b$Ÿ5J–Oš"DP£¦h‡È÷â?R¡=eL2õ @M±9¯è½`â0y` @4‰R€så̽'çŸ%:Íj5Mž¢ª33e;Ú™tµ–̸ “Ï@ÐêÒ5 ÀÞ[ƒ£äÛ·´¡m÷£„åyóÉë^%Uˆîåî\¸«.,IÎk¾,:\×›1ÌË—‹éÙ[ºbnLQþÔ[æîZ’ñIטjN+q’âñ×Ö£»“EòÚæéÊxCŠ"@EQ³ õeBë§ëð¨‹Å„Öƒ•Ñy£TÈç÷¾3…60 ¿Ñ™q'Ï“ ¡»§×k…¯m­‡t˜‚:ÙÓôå;fêGÄÕ#¢èõ@dá´‡« F!8ˆ+¨Ð[‚¤gã6Öxv;—ú‡Þ¦È$#Q•½ÝÐf i “Ë¡0u¨þHíûfnvá²a­5=EÖë0F’Ó~Ó„ã3ëÑB‰ð‡ ž×Më·©ùãÝ–IÌ'«o–É"0‡ùZ‰ªt· 'º ,Êð2im<~¬yó“Ù©Ú8¨¢Ž,¢äŠƒhŠ /ÒC8‚—L Bµ+;ò j)d³ò8¹ “kÍ4a¶¬L ‰Š¬‰éC´“¶´²&š®ÐÃB»Q§Á¢¹ºå“ß+9é*@} þ'iU§!?7 ±¥­º·53Œ7é[@“\%Sv ±){ꧪ å¤Jl+ZÁŽ«e1I—û ¥Â…¹“SG±³ñCz‰Ÿ($ :ZÞ'0~<øê¹Ñß-¡•¦2´¡šr¿Bb-³£°²¾4ãs63½+Û i)ët# €‰© a¥•»ƒëUˆõ–«õ#B‰!D+· -1.(/~ 0kFJ.Ày ˜ ›dH;#D4C;ð:ÏÒ“Ã1c»+è¤`ª•¬Y›[§9Î ZF®”#bo‰3?1œ_¹ú ­û³»^’ª¶I L& Kä+{¹±F%C!©ñ3Žš%GËM¤Óál2µ;A<ìTJ„D z)Ùû´Qz¹ãc¿1OExšÓgˆ³ó³ø¡9Ó£±BE—ë”DZZ Iˆl3KÈé~µ4(—H“Gâ/”œw,;ïÅ¢âd³*D·Óž¥²| â¤\œ¬G½J(<Óîˆ{Ë€*ÍÊÉs¨?h䲪@–#ˆÄ¼§ƒâ¹º±"6Á ÀäÌééê ¼¨ØÈZ\Ã\K4òC–@Ž,z -4½*#sHiÆÍÔ>ÒáÌ2³Ñ›û=ļű;8ñ Á#ž“  xÝ=\Ýœªù¹i ©¦¨qG‡È½êø9€†GJó¼ÓlÌô/ć$?ÅØÁ6äœj“™Ík%üµˆ¾Šlìqty(‹yAÛq ïêÙŽPä!ìBc³ô¾¨ E«Ly*{û²Óº5Ó €AÌM³„¤P»,I€½3ò‹¥2§ÑÚ>¤lïC°4¶—ägÁÓ3¹ó‹‹bºC ¶¤4 Ôï¼ ‚2<Ǻb4¤+‡/$é—ùãÁ ¹ CÅôxÁÒ Ñ@˜¨ƒãŸ<-´º¯:o¬{6£ L$ËNâHšÒBQt–étœäÁʹ#Ð3³^¶äSD:g+M=<á0I-Ål[7\å2æòs¥p¶an¡1Ãú'F S‘zÃÂêsŒDâ>qÅ‹o“´á‹`ƒix¯#”ÎE‹êF¹¶,»Ñ1Ûá–˸«HÊÆ›W«M¨’ÐÖi4C]R4|M`¹SãÜ–zÛb·ãÏCqxZæY4„{%ÔãêÖÌȈzÈ• Ï} UúòÑ ÛÏ =¨ÊsÓŽÙhõäi4^fcí² cÜ„Ì) IYº ë€‹z]Ãk蚬‰n†ž]†AµÒB3%ÞÄÑ šÇ¸lh!ÖU…û)ý“[µPD!‡óÔM‘¾!-m,N|ÑF›Iñ[ªßð%Æ'Ñ¢/&ˆé­Ã¥$ÔPéû!Øl6H*Ræ>©¨Û2ãÓŸ`r­ó°M}Wb°S="Ü›Í äÆ7z ¼Dy 6i€I-65fо—ÿ–hHFx×R7MŒÍ;HT%ŒÚ]6ÎÁ"q¼Ðò⎿NLæ‡Ýir€²£Ì'ÉF/ª­Š€¢StÉÚ¶_![G0~2£ã§´™¿NžÍ>àλ.w~@íi?:¥Ü_.DÁ¶‘!äb=ÐÞXòøØ6Íhžy¹ÌV*7qéPCh9s‰‰tˆûˆ^Èê]Ä'ä&ìÓN(¾Sam%ŽÁÖæôù³ƒ Íe=BŽmÚý€>ŽšÚC)ó` 1ånJ²;­Æc£«Ä[ÀÅœ¦sj5·àóü.öÁÚ㽊nÙÆ¦¦:¾ç5taå·M•Ú¡ƒ¾ 9Fbd)ÞöâM“G„-m…ZˆEI5¬Ê†zŠ)HyÜbÊËK— òœR¶m=á®c4çÆ˜‘ËÉ4cylÜ~nÖV¢ØÙÒ[ÍI]|RtæV͘/ùCÀ •Ilp•%àÇ”,ñm«Oz÷/¹2º±r@Ï.V5±ÉŽ,™nÄö¼"ˆ¤ ïD®¨Õ¬Pû\›äZÖsÂ^ƒÐ¼ÞŠSŽ«ÝÝw©hâò0äÛˆ½å¡…^ÉÒNE³Âo®E|/ÛwŠé?¾¬Õw1DmZSBÔŠ‡ ÇfѺ̪±C­켟3W0(2â Û?\\ì-|¶0}^î^ @Eå=G=©“ñc“´•Å\¶º#!¨rîU‚*¸|©ò»Õü,=‰¹¥šZ›L,|(ÑzË5ÝJ|•"ßNæAzãO/J0‹! ÀÕB3[ííßÝÝöTC«©r(âˆÏ@©ù¢Ýt›ÕAkNÏLùpä‹ööh|ÃãòoE=—"WûJL*>ŒJ·q5§Ñ"8kú\˜¨qƒ3H¿½$_½©¢¼ÅWY92Ö|JÜk§quêu,­ˆ³ "N™tð® ŽøñeYÅy­-W+YSAeìG½$׋>‘»µÏ`NN M޹%=¢‰éó¬ gâÁ7u'µÂ¹Ôì ÓM*"§ÎŸvc Ûz0Ë8¤óFÝN¤Jj¯rTæ$2?ŠÞ_¹¹C‹äéìÀ£ÐE⊓4”:ŽÉR®-“ß6Ël¹zCAUºM"Ç#ŠÁ„ê!^q¿AT_7ËÂ)¢%-l^ЈÕ/ÁŒ_`2?ÑqØñ¿iPÏ)ãûùõ»ºÄÉl—løˆ1!å–ÁIü×ÕJCÜÄîI¯DËSû‚ Ï˜@†?!Ϩ€"%}À€0`5G@‘ø´uüý’?äÒx´X+”À¥` T®O/ŒE¡ÏÉu'ŒH¢ÑHÐ{›Ï Qð$b ú’?f‘ˆ56_:Îj•pžE/§€¢Ó:årÁa–@¬vI=6)¤MåðÀ4¾‹„>lqŠ bO'¸>/ÔtÊöÿ‹M`P ,ž—_“\¡Ôÿ ´`ò¸HRµ®ÓdRzF~M-ÊY%r*ŽIpŠF%ôˆ¤¾Ç1XîðjÅfM7ºÕ;úFÊM"º×h/~E’á6‡Iæø¦¡ÎJêixƲ 7‹t ZŽÆ6ʤ]d1ݸ ‘ªrí#î) k"×£îr—¢Ê¢¤°ªŽz—©k‚nªAHšò¿É<,ë Éú“¨*k)í»iJ¶•íªL¥·àK<޹k3v›ÇGâO¤N¡ü—± []'P#©bp޵*4é=ÉL&†$O€³¾m$½¿pûÞü$ÏâtÑêk ƒ,zMÌC©§Jê)!¢ |F’&ï+µ¢‚›Åpº.ƒ) ;üÒD±ÉøŒ&î Å 1 ¢h"ŒÂ©Õ3¤­à ÈÊ»6M R{Fr(IЋñðÈ0p>Áèt’2t$v~-èby03B[3/’´®U“ªJ¤‹")´ š Õ+„J Ïdú@ìÍ8¥rë"ÍT J½>KÎÇQ®½“+Ë­#Á9¥o-`Ø Š¢‚Š#–M /€W2ö«vqûL´üdß©m‹æ¸%ñ¬£ lÕRÁëŽÆkMjŒR ‚\°±˜-’¤.éëc€ÔrÄ*Š^&’O‘ ü}dXµ„ºË]HÅj Elʗ£è£ê„$ï*á3b’Â(jËR &Wà4Rª—Qþ—âþ¸< ¢*æfs½î‰QèûüªS5eKIÔí#Ã’ì’í 2*õ‚)Ýoòá˪œ•¨2z®¢Êmh~×*iûàLŒ.©º0Äl¾³2XÎIBË7\ͦ$ Êuf¹:EA$ÒžÀé43NŽ´Œ;¶ô(RÇ´í9báÁ8[ Æ’"ÍìZª”?Xê÷˜×'é'JB—ÊnŽBƒN©lFFÅ"æ–ûÀ"»ñ¡Rî¾ë¾Ý‚ªŽ©¿p ;½®b….¥!ʼ¶ŽUÉy"J ¦ž¡÷ˆ‰Je4éU¤ä• ¥&à* $ĺò’ÙÜ Í’·è«ºLId nìõ–Á$^0$†åN«˜IΡ90u·  ªídÐõÓº±þ”Ì\PåÆ2w@êÑtËõœD(ßWBçIä<§àNŽ‘‘pP­QÞ>œT7K”¾·*—¨8ç!‚0h¡ã3ÔRI‰æÅXîÚàzȽ>Ä.©bD}*± Æ"tØ™¶$ÑR>6EâeÍœF„ëN/î?˜Áú#è…HnRÏÉAŽ$u;£"d¬*iAhÈÆ‹ãÛ~\Ú<¶õ‘ZÁŒî`~«³æÈêS—¤˜ —S²éVšÝ%3¦¼0 VJ/DË–EñøÄ‰[®€ 1Ià ‰•”y)eåÆ8–w@sˆ€}ÉxØGØ$À¤YÉ×:Ê\T„D¥ÆÙÄ™•9ÒRf¥ì¹•ÎÈãBJ€RbàIßû<PH†= ÈÊ[l9²=èÚ5ŒQ`“îh›„Ê]B3vÑ …FŒ`Êk—²ùL¼²ÈdÞëÎ%ª°›À©¨?, E Ä=tdb ˆ øË÷tÖúžžíúwB’^¥2öô¬DÙõ’`_$}NÐÖý>Ê¡uœäiåšHAHˆûË¥ììE®C!×+²4Á™80ªùy+Ë´’=]]êÊ“U†8ÄVdã+²İɨìÌy^T+eNÖpb „Ê8qâ§è0•‚=7äR”•Od½1'Lа©–Njg[`4„ÞP;8."1¤Vp®\ƹMÅ„n¢ØÚ—H>ÌCi$Rä W›0iP¦¶Üˆ4G|¨T$„{ ú¸Õˆxêª/}kı°HÀF˜\J´¢+‰³¢“7.2À„»ŒE`Ì®Ý:€‚T‰´e×i²*Y2”éTlãawV•žJéé†6tºÚ˜ìÏç¥^žÕi9"¤Ø3'Eqi¸#h¶^½:,6„Ïùj·Ÿf X¤vÜ É\î¢-•`EgQ\ÔØº¯ôÔg¦Ã(Ù©FäŒ+ öY0u§Œ%t¤ZÒM%ó ~6’®3+‚©Ìº]sü¼É£#€ekÁ!Îl“8‚—Tì±ÑÙ¶æƒU]'y¯¥B1˜„»%ï¡pJöà©9.ˆR©TíDŽÏ§LnI;,Ÿ$LìCñëdŠuxº©Ö „e^1‡)èY› (øÿ›Óîÿ·«c§iU–ÅõÜŠ}çÙaÖͬ'¤^½ñ'T ’‰;Z–›# ±ÑcÊqlj3´ÕY‘ÒýI)’6!˜†Þ5§—¦##ªÜ~]ð€\'U ;|h{a¹ É:VÂÒg¹€[|U/jf™bÂXÔžã¹60E`ÌŠÆ]ú@’ŒÖ·vâÚ`z냻ÉS7d˜ÉRx¤ç%×\¯Í—Õ È‘C¥jÝ¥‹–Å-6J‡DÉ6è#$k‰¼JA¼Ûóc+¼–]µâþ÷yX¨nê^TÌ‘8õÛ[žÚµÞ¤nqšz!ÍÞî·¹m0V²¼×'h¬Ù5PØGe¯ͱÄÛî€sõº¼›0•ʘ¨RN¤­¤#²®î6tü !ºß³RKÕ†$¯4…²~x?ùó…%RñB¯Œ£M6¯Cªwñ$tкúƒP®¦Á0…å$ÚœÄÝè° ÝÚ É–9S1/O1õÀ•äÓ~ÌŽò;¾Õúzx+¼0úµl°Ú8SÔµ±FxºÚ€TÜ=œQ•!÷õë;ÒxôMU4x~)Þ,Ú}ðüŸy<~yé½TrkF\æçcn‘ýÎ’„„¨Œ^+J! ÖJ^T訂 jÅMhýÅB$O&†©â±‰iÖ$å:ÁI´+©–ºŽÔãê–q‰ l‹~ÁЍ€ µìí,¢hdîjÐm(šlj’E’’.¬oöÌb>m¯ÖbR¾N@ÞNXÐeªø¸®d^¨g“B”°ÏSr­å ˆ„ç.ÝLl î;¥J¾£ºløèL¦h‚øhtÈ‹ñ(:ÇŽøE"D_ü`MäjÀÉÂÀ)èk¬ÝKúzÅcIþ$ᵎÎrèÐ"‹Vs‚çÆN¬ªWLû¦$LÄëÁ¾ñ):§q0u-_ %GêÖoÅ`°ƒ.¦åÖÿ„v<¨_èÂ’%þ¤ŽbàÈì2¶ÇêÐk&ÛFä!çÎö‘LuF¦•ðå§ô ɼ£¢%/Æ Ð1 æS/”_ ì¼ †ü—Ͷ!€²ËÖ—ÅÒXO +öÿ«rÜÀ :FF?£¤º¶"n(0%£ ŨŒ,ÎB"VU)Êa` RÃF鮈ôÍ2 ˆšÔ…2ÚH¢ä¨raŸBÈÞ,kc# …+‚ÎÄt–‹º–âVgÑb¸ó *,6Ʀø+NÇ “oì0.P æÖG*I…0â†jüTcüÃÀ ¢­JÈæð‡Ð(dléno%ÒVùi|@"^.©Ê™"žÈà©þdp´á2náEÙ Žm0üDØ€.ñ r€tÇž!2Ý Åëç¬ä©œä®G/"L[).ÂNžÉ|¬Kº)m¾û®Lc¯ÑX\ç.¡ýÉÊŸÈlTźépR1E.³'ã1 1RAÑ ¨o,kmÍŸ’ƪ&Àª@_Ó(ÿËö]Æ P†N¶$€î²©F\rçøWÅFøÇQ ¾²îoÃR$DgÊY#ÒÇé*L 2 ?Ï4j‚ ‰´ßg,'O&j<­)öcRÂp!mx@0쳊N R#HÀ,…3àaóî¨b‚VšµkhÀNÃx!ÒtŸf¼ä ^ŽÆ(Û" S/„Æë» ¤Wl¼ºmò+qÿ@%BɨìèÆ5"!÷”¶$ÌÔ„Lld^þ{*Í“Mà…§1 m€§ÇTšÓ>˜‰ö¤iÜ@*rcO#\1f»kbŠ‹ÒäÐ̱°ÂWOôŠ”L¤-‰Lå—t6þÇŸMm7Cnì°`ƒe ¢ÑŸ3ŠcGînRmb$9JøOïÂáìr³Šº»É,@¬½LeRjÀ[(<†2fïáòZF(2箯 þ*‘H?Ô¥R} Óáö2i:’L`Ó\ò«FhsóW5,€ ìRcGP¶cæ3ª¥NšÎìDXÈF´Óâ ã³ÌР2$òõCÚ”3bGÒì>f :â-«Öžº<©áB2гº<­äç vÍ‚ÂÞG+/Åí‘—"Fâ~±µ*³ÇT2)ܯS²Rº4«É|³ˆI†N“¨çLÊ c3LüÁoÓ.øÖ"(Õ1w"´ÎÔ“£BBÏÏæÍC)%„ŒgÔ‹.ûÉ7T+0se\p(}hRäj¢ríõ%Œ)I¾"ÏÑ4@66JdéR¯ð[ƒºã¥V â7. šî†ŽÐCZâoXôvHR:OÐ$Iлt¾.· CH¹³jó†×¤y3ïR6E,u$(Öµ^ä1Cóäˆ~@vŽÊ)é?h ,w¥J÷²MnN3TåÖŒ Q—fcMàާë üM]4Î{u¡ú<± R×rÞT2¥`vp«ƒ'¯S7„’’øV®_T˜w0Jü’”eªŽÓÎ)”ÿ 0|ðn-U ºÕÄÌ,”vm ªw’¨slR+ÀŒ¼`H’½W•(ä°ª2à/ÈŒuÀGR`u>åuÍe_@ 'L_=³r×VÊBÈc‰.5ß r€“ì‚ÐDÌ2iÅg·–˜¦dâêxN¾¦´%h€wpàÅJb•à,wBËȨÈ7W V"Z”J‹³ÿZï¨ÎhÌ}kK°V©WeO68+x¢1A^Ó?†'·n’Ç6qxÈó¨ ñ†.:l ‚pO¤#üM—N¦E!"yo'G›èÐeÐ"Ô#ºÈâ©Lp ˆË§' Yi™‹³Œšëª§G¦N´Qr½F‹:s/|'LâTZmG‹6¡Zñ¨Ž°&ú‰tsuâ}jpå´¦á²äÏÅÜ’÷)6âZ ɧð?,š²ïajì'PÐTªi±öM|y`Dñbrðô¯.¼tÉe’#úÕøÕNKÙsÑžà ÍH´üRJò¨¸Ö¦4+ºEuD²PÂåã„àhJ‡a¨\ŒÖ®¦×H·nåTêÇèÃ"H‘(^#|a ÿ0?}íÕLÖ “%ê)70"eÌ›œ¨ñJd€LÍ]ÓÒ“¬µóµTŽŽ%kŽ!“{UW¡–ü,yAŸYyCîAšnÎsB>ÒZhŒÃRžÊ¢"DóVžžË–J¼I•²‹ÄƒÎF`Еc¸k"¶);ÓʹÈÓLí~˜ doØ=™±#•+„ZhRJbê hÌçÅŽ;–r:ÐÖîǨ²éìb’Ñ9w¯«‡°Lö'2„œWEª‹ì!uE™ÒEúˆÒu®/råz·9ô™¡‡TÇo‹*.@Þ [C®b‡FÿRQj¬DÛ/eXÈi½Ysw'ÌVáq¨› xþßêB/µ»IUº'µe×X„1T%`µvn^1Vãý‡ b¡)œql‹1ø±ljDÆÚž¦B Å¥]L´Q«%ª9j¿Qxä®ìZhÐŒvEâŸwµ, ú„±]tÊV©rcTõnmJùIYsŠðl ˆÝkN”í‡j§•ö@õö¾.º¦Èk§y «Ö‡#¥ž`«‚4DÖwkâǨĺ/¢ü³—¶ÖïsÏfE`¥Í}I ZHºý¯cr‹¯³D jˆlIs=“N<¨bšFu}NâIpVÌŠ)Ù3tø—¥T·”:OK+Jäf°c"Hšy·P ´aWm8g6¢À1?Ä¬Ì UšEmB’{ë-”é9B;ÇùᥡüýPr†ºkV.ª•bîQ¥ŽrHB™‚Èþ³"VsB²] j‹(¤;bÑÕ:·¯yRQ*/Ø¿ fÛ•¢HÆ ã£Ci5̼2ø?%ÙX¢Ô)I#Úa‹[œ³¼û´4Ý‚àÝò’ê^`œß:¬ÿW×~ðEÖÜu·PY®2s€%ó¨"º¾û¨«Ö¨$ëVö œ¼joÈÛ—;y4}’ êÞËÞ4›¥ö«Ò&ï5H©T5@qÎH(™ÞOYÛ¯á%{W·À}r¯ª½‡Ð=5ô«Êæ€pÞ Z§˜«Ù&.¼ã¶ïõ–‡?®S³Ž,2³¶QäÀ­àj˜©{íÞHµj‡5¬ÈORÛö+¡Ó:ºm–u-ÛúÐ[-ÊŒ=÷ªåz‡SOXôÉ)6KЯÚP‰íLe&ÈlaÒX žÊVzlÔ#¿È¨ ÎZFhÀç)àDB4U0DŽk‚˜j¶Ân‚¬a|“?íÖÕo/E!Å»3K\"êµeS˜ç#N´©ŒpCc½ÅÏ£/?‚ªi÷%;Ýß% cº¯~« ¼˜¡9§¿Ûü˜–šGiÄdx™+UêMCÕ ¹cùÍ×é[Ke\n ݽ¬#ãБô¬R“Z—œ¿çS³Â}ÀÀpX0ü…?á×ô<‰CbÈ4*ÿ„bQØŒn$‘Dâ±é4ž7 ˆÂŸ7Ø`ø™f’é &—F!÷ôÀ ~Ðçѹãþ‹¡¿d2*tJ},§Sâ/ª´ÞY¨Â€µÚ]:]@«>€öXmP¥Á¢Tº\ú@†Òãv;(SƒXè'ÍþœÁK)1È:ºáòÊ\J…CƒÂ*ûUš­Cñì„Ñ>ŒË(zÛò‹†I)ûdzTŸP)×÷Ì7±ÛQ ·}޲}.µÁgÙšÛg0§K#zv‚EÍ‘Nb:-\~N†Ë£2à_¬ÿ‰^@0׿œ é´kÀú˜ YéK:–›Í/ë ùbvÔë §5Gûð†:Jš€—.í³l£©Ê:ŽŸ<(’€§Ïp¸ °"4„5+Ò –1-#”顎d>‹­è‚"ÎÁȸ{F,K’%Rþ£©k’{€ð–"O’Ëš‡>ª³ (ˆ{iµ¬òN“§ÊrúäOcO ˆC„¡¾¯Pí#(dÊŠDj ÉhRÆÄÇðJʃ&GÂ3lz"ƒ%Ìø¼*ˆ¡°Žz.à q( Ùüº!E¯(lK¸‹I«sŠE較,€NÚ‚Èçí~®è5@@(D¥ËB%CÔó/S¦ ’DÄÏok0S‘ô ò!&˜,)ƒôõ$Q‰ìĬo"Ä«UBœÂ¯jµO |kÜ3úÆùXS©t<–ÂY((P»ÃO/‘#à®+µb5^ ƒ ±¨S®­´-Ó4ˆÝ³Xä2ÎÊGLïz€ðÀO"LJ>G¦>ùQòU–†)isWj›‡O¡TÄ8½‹DФÕÅLĵ“þ_^ØùûrÉé…çÕØj†° j–5 +°ò¢¶,P kCë[Èsa•CXØ·Ò¥Ä*íÖM©ƒw„ŸùírNÏ’Æn­²°…j§ÞÄÖˆZ¦2§óÈŸ¯b]•#{«]!RÀV`B6óžíàùC|,àZt¥¤Ý¡Gí@$#¶-ýC—¾S¶0‡¾WæþæVýÙKlý¾Ó‰ÔQäŒëÕ¯}pÂÄàß T/b7;g(ô7hªÏ”˜Ïë:EʾItã‹*w° ?T81úŒÑé÷¹ÚÄÈ åï8©þõÔ¨g*ï|ªoú;ó²_>SBfa…1¤Æ[iõ=à ·áø¤ÇÙìGnß™0ûGã7{°Z¹Ô"ÿA"KÆthD® qá0&±–2ý`¸l®8˜>8Ÿ"=zëÉ$6Ö4RŒ”7ÆÔ¿¤7Ì¡‚$¹Ó3C8ïÙ´G„ˆ §—Pðû²ië Š–ÚËqÿMЬ%„ãÔ‹SŠ €¼À²<~^ K+©Ø†ÂÂiˆyN.å.00·àH–PƒÃô¼g>ˆ“ou`?²ÈO‘‘e Ì–åRY\«„}Cñ_/mTi0ƒü–tÿ Gâ—T‘ñ‡E3¢ïWDU_ÀFR]Õ«Ð`¯½ÉB#2…“ ¿n )VšÂ ¬­—‰QêD’-ŸqŒäù.†L@ÓRVb€G¦¦³-‰ 7ÑA4H8dÉé…ˆù9RïˆD{(éØÎKš ¶ ¦²YŤ~¶¤1+!GÈ›–8,èáãRDÁr”ìNçÉ‹“ÔÅ‚(¯Œ,vB/„QG}`¤gF“ø†«uX“G©^PCâ˜DgÜþ›s–n›${L*E… !€éÝ"4ÇC¡S5ÓIP$„®õÙɨ>4#}ó¥ªä')UʯôL”h¦Ž¼M!Êê?WÍð±¿Që[g»3¦§I1úëOKÆ'Óˆ¸2ºiÖ—hÆeVT°‹¹£™ð%Á3Sa éüˆgÈôÕµ,˜;Ÿ<‡†~¿(ú@¥M™sÍò@­AôäyžD!éÌj ðª ©£VÙ8X"·ó065ÉÝ­ÅŸ0jYe5;M‹<>ÌL…rèØ²¹QJ¤»Q-í…/· é:¨=ޱÖgÙ6hÔ‚†Ùê6` q#:ŽSRŽÇê´ª3ñQ5)FGPç é±SÒùò=ÙìzU‘ïr¶=UCNÜ0¤dÄ´céY E+Å07_Ì'ì‘ôàI@ÈÛΦ‘lªeXì+à>7ø¬x‘ ÈÖJ`·¶ˆk6ª©u*Ø}±ÔÊSUoŒª rÿ#=‚˜ÉåÊtÿ])é{®äÅ£ÈÈÀ%;š£ìe³»‡£MQaD¶M×9kgCÇòލî5gaS¦§6×¶Wg„@áF Ç•ÛI4È©f1†Ÿ@™y%e·ÀLüòW»yD÷Ò<©*¨I¯$ŽÅWKtaÑ÷É­w>ªp)Pñmz>¬®WŠÓj®‡Ä±6P꘻¹SÈÈlãã1Ðí¨ÙÞ÷xaÜöŸbç Ê¯ý·‰ü»ô/^ÙEÊäš…€fYœa ÃeA) QûXm­:“#åx©–|©wfoFæaÎ%JÜÛÆÐcÓîÞʤWmâ%ð?>'Újt÷Ñ9åÄ·.¢5w»»qß§éX†ïË[„3¡yչˀX©u| ñWØbõæŒaCgÊâÍ”d÷pXÕ“˜,'ìÉÔ§dm”8ˆ к…(üF ÊÁO]ïê–§òCÎ^wµ„Åß~rËðTy?ž£Û+1 ûh Bd:Cׯ“ â#`y4+hz¶j"°H†+£ ›ò§Á®*£ì«Ú³ÐŠ9‰–j\­r?ˆÊ<Š—µ Hر€‰3B—A{E{T°*4,q…<‚1C¤¼£”*•©A £B};ö&‹•²3§¡—‹»f>ä8ÒD Î1"ˆÌ•1­±˜÷¼Ö¨~»ºb›â´$¡Âz =ëbBá ‘?¾#«ùɈI²7)Ë´K¡ `ƒ0Zlbžœz¥¡ë±›xÛ:ð•Aãˆ}{ø <* )4+f10œ;¢«XŒ4 Ê9Š±ŽªùŸ Ó®z3YÔ0€òCùñ¬8† °‰ ¹;CCŽ€(†–|#ÁÛr­0ô•3²“3¸ÄHØ«Œ"”a0y*0»ÁH¯ë¾$¢`À™O"c¨pŽs”ò°Q£0ºcF‰z£ü :µ£ØÛ& ;a5D«³T?*©¾cÀ>¢dAŠQ:JÂ[O‰«Ë±{| Ḛ̀™”+B>‚AAZ¶(3ê±Ð|ˆ›y‡! ‹ aôºl‘¡¹E:–‰:±c¢'¡5>ØCûŠ,âè¼B=ÃuŸ|K³žTYºóÁS·Žðï³4 ˆôÎ|;Ðjîo,*“¸$)éãú€â`Ñ9¨'l0š`£ÔRÏL$Bù¨/ÁÔ HÌ6!ÁC°‘C,ïÉxÛzŠBqŸ?ƒS¤mÉ©Ï`‚œ¨VDf̃>+s ¹_R$A ëø;D`1À}@¦8{ ÏÁÏ5²R¬½?ˆô…=ÓÃà|*²Ÿ³ø–V@FëÚ‘‡@ |£,€|º£éØ =ô'€§¸2ÎÉ0"­›ˆ)ïˆÍ®­©…(‹p·Á´%1°  ýÔ%¦­DˆŸAtûº¢â:h†‰»hSä%3ÂÙËà ÿ|¨X"*Ó˳Vi™Ô4jœ¥¦ ÆZ”í‹, ˸³2î4É¢íT–éà£ÜQ˜aø»Ä‹×1šËP—‰Ê˜t¦ÒMiN…T1MA¤‡Ú3ÂÒ ¥n$ê:͸ªµò×¼h¿ s¹<•4°ÜEJ¡"ü³Tš½‹ÎUè@éÁM¨óÎÄUÏDV‰‡ ä¥Yªý:|šÖ ¿\8ŒúJÒd9zS:4j™ag¯DoNc‚ˆë& ´(¸²¡X«=Á£ÌŠU°«) ¯·Û¬ž *K”°åÉN@š.uß™…Ù;EO!mØ “"­&»Q‰¡Zˆi”WáÂÏ*ÑI"ù2sÚªkLN›ú¼¦#“á•"|»¦šƒZ*¬Œ1ØAÏà“tØAãOû¡°b€«­Ó´ÝÊII<]‹• ã´TúNÒY5%Ub5Ÿ{×F9¸Û2Ø6X«bë£<9†;zÐ"£À -Y¦ÇÒUJ&9¨”@EQ/Ò 8|7,ä`_£!%‹¢Ó¦Špläqã1l¢2°Ð—4©±¨ÖF™D9À6@5|MQ¡VBê6ËÛƒªŸšÙ"iI8šÙÊšÜm.‚ùrÀé–/"ƒ?«J‰”Sú+ÊøŠJZd=äh}EØ“š5ãŠëWÅâ/Øi†RÃÒÝ`’‰a?`¼Ü3ûG rÉY-Ϙ}$Ðàࢌ5ºª^tÊëL®á Ò7qû‰£ª;BDC>^È{Æ4ºÄšØ–@sœ{Õ2X¦(~DlÕÐ e,¸òF«W›À–Ôv)<\ˆz½Ô€]ÁaBŸ5~bJͶ’o[bù”=nB_¬Ï·3Q¢£¿ (8Ž–iÛ=Îf–¡ 0;ž%xŒÜº“²_S8ö`EŽñVR[|Åé’¡ü^£Ó7¡£Ü/Ñ–ö†.#øa´:²Š_N­WÀÛhóÍíh—)øÄŠÊ%:74Îþ¹TcO-ò‘5êÙf¯ª¬iÔÈ¥¢#ó‰ež5ÄœˆW©=#U™*E }=l®EA(ЙÖPˆ¦ ŽJ$`[ýÂêÅڜĩcHÊ* K)̦TÃËÈŠ=­¶9Tµ ‹.C˜|5·ýDJ%ÉVüÁ›åI„Á‰òöœf¼æ°”ž6W3ø+Ø“Vû¦ æt¶ªÄ瑨U]W\`R$ ´ùdØ|c»Ê#–K»PÖ$öolï;ŒÄˆë‹gf&F±¸1‚ø=Z0ºä‚–ùt>Z-EŽ0›ntÝÁ¾6¦Â_°‡×y"çH»_öC2ò¶ã¶)ôÂVÍO¾ËÏ¥â‡ÈØÒ%úÃeïHª±™…°0â G‘º‹A—œ½mo‰¾)îè£sÝ’° FœÖê+NH‡ð°•dnˆÌúd¼-®"¯ilµ…ÇÆpŠ ‹˜ÖÜ8䦿-,ñÜþs6ÑIEå`Zù$œ*2äOí­µâïPª @æÌmˆ«Ð¿µÜ„‰y{âJžÁ½uœg™ñ­¤Mæ€òñÝzœ5±Ü¹—ÒÓ ¬´ÈM^nÕÜ.âDѳ±ÔÌŠ¤ Ì­wGˆmý¦.Ÿ@=sÄu/"äplŸ:2*ÀàaTO±”Mç 1=ÿ‡Ö·™Uúµ¹½u)®åR-6Ÿ5Ìð„21Ÿ&½s4)*ÒE½Ãkäô ––±œé¤›ã2ËúÚ\!)îÿQ‡ ÄŒjŒK3'¦÷rò²ÔõÙr¥eÛ{1äÑ>~2½%Ü)ÝFX˜+òš¬­öºr‘¥µ7-Í4†îáßÔÊXÆé½q´9ŽXFp‹uÎm£ó¬•â^ˆj×è¶È¼™…ÈÒ'€©ýnaÍÐn\îªXý¸À¹B™Ùˆ‘U=l*o™×Ë(ªª½æêdö&/ª©åÜs9ø×7:ÜDŒÁSþ)<^%y™„jŒ,îåé÷‹F AµpóÏ.O¡—¥'<<ðTpö3r–`b»Qa+ÇË nµø¡Ï+@ž’†dæD½[Ù¢"«£@šøãFGmÉ]na6åÀrѦŽk‡ ÍZ4w Ê Â–plï'»†Ÿ°­qSDmk§Û´! ´3a¯—,­u„³åeW“Ý÷÷.Ø›¼qÏߊTý —Š¥’*D§­Æø:·ŒÌ?•öHF; [¼ë gfä¹Êܺ=仩ˆôòìPôÄ‹[h‘30›ÈêËã~aDÝ IÒâzòWë<Þß=¨…3àÿ+ù_wöY×{"§‰Ïsr­¥0€ P0¿!P8~Ä@Ñ7ÜUÿ‡A ¯¨à=Åßñà Š"”Eä’ô¶I’K_ÒHdÖdœI$RI$)ù}‚¨QÇÔEû"‰§°©+‚ϦRÍV/ƒÍ T Ê“D‡N“Èõ^=2‘H(Ó¸ü‘P)ÀY•È @ìR :¹¬ÝìòØ¢/5X«@ õÂËhÓ*„€”_ß÷;UólžL¬ÀF–}'ÃÀ§R¬ÌVIbÃ?Àû:$‹ƒZð+ì"¢ÕY4ü ¿} “@¹ оja•ˆ*SˆÄbë¸I¬;Ÿ¼EdN ¨Ì#Ö,lFç½g®z?Ez'º‘Ù!0¸‚–~,N3ª+ÐÙ€ìòŒ¹­H‹F¸¢°BˆÛ€)’Œê.jÄ£#I .£Ch‹J'Ê"“ £Ê$$Ž· »¨ÏÂX—7 2ߦIk¼ˆ¡É”v~¿éºr²Fîc®âH¯Cè­µÈôFŸ.Jr¸:J´²ÀÁ*?)․›“ |.hqí3±àJc8ïÄ£(‰óÞÝÅM›þʬS9í ó¬ªº'ýA «Ë±#%ËôJî“—¦mÂ}G©ká@¶,\ŠÕ½(=ç".\(ýŸ‰ˆ£Dj"€Ê¤Šü²¦¯Ã¤ºu¾ E8¨<ƱD6âŸe‰ÂA("°î–æ‡Ûà¤ÍuÈò±óŽÿ×HóÕ”€L^`œújç}-ì[¡J%ª‡)*–"~¡Ñ=b!Ìò@Ø;€Úº‚Äå¯Òh±= ð¹«èãØþQö,‰"hr|Û^8„ÒÏnçæü…?-‰¸&®]æ±3J‘€68ÏAAëÍÞïrœ‘(“LÆ’YˆøNgú+<"#u謔Ÿø.2™oðú#ÉLp\~÷4lä:Y‡©ÒȽ…ÙÉÞˆÕ°‹gƒÑ ž{UÈ—z+ëV$Zþª;ǃ”]{ Ê v µÚ7qü;ì4.?$ ø¿Ö§ÒÈ£ÓiúÚÍcHqÇIÅ5µ¾H ™±j õötF@Ê>Dë%ó‘åðSR‘Ö)¶¬÷L #Ð`ºB ?‰½ à24ÑîsWL(~îÍâ«v0ÁIPÀÏ&˜\Ì@"õ&ÌâuÜ— v/‘5ÆLÉyO Ѷs<íÞHÿ/qPâ³ÐÖ‡ña' ÚESŽ‘Si'È!ù²v §!ÔZæ-k¡Õ8]á9£?’(¶É ˜Óf~§–,”d”@,*7‡9G|Ñ’är IŽ ÒˆäÃ=ŒÈ´ºçZá\jl¶ÈÊ@•’ŒSÄÜ7†x¤›Ã€RBC:Uaƒµ8‹4”¼ ÍXA8v¤ãJL¤¡$KŽÅ•®´Ü^Péi(† ÃeBè—Gb#ÊÑùæÚ[ke-S4œ ÉÓ„gJ6ˆ@hYNtdy ÖƒT S@dÉx,Un€§Ô`ñIá9ú~ …jRA|·‚ôN$i™¨æ}yÛ £T±"åŠd€gAD‹™N˜¤”é5C—'J×9ká·' G•¡àÌž¥Õ¿CÙdIT¥¸&9êøGä'{”’‚¾d<ê  $ƒf¦Q×DÔÑÆ?ü}£"‚Y Íž-Ô¢<þeblj­ÙÀÈQHQISð5%Oó[@2 cí@²º!Šq“bÆO;E¾u *ô§Qy»ExEW\öŠí†Mã€#–S¶“@ÕÞÇéšM)ÀŽM€–À’y†¼VÏ^¬²6m½-W#Üë%QßÕdC=§›Rò¤[sCX”»÷4 AGZÎv¡©Œ)„^J­¶Øq͉𫰹’®6G+=]ޝ‚¯.w€B—)c{°ÑDÙE@µ£Õš@“Ô|séTŠÙ _(é’LsyŒ© fhÔ娫4à»Ö 1!´˜3ú¸Â¬K^ZëTèðãO¥¢ØÊ×64Nx€Xé*€@X“ò‚RDBŠeä*9(ÿa­®Šü§:Æ“WñDÀE¾¢÷»&Ž$'p®Kã=x[¨ú‚DLÏIWS"ŸÒøiT;ËäN]€¿/y Å™« ´ÚÄK¨œHŠ¡˜g½©¿êÝ z](Ky pãñ¬Dôä¡s!Çk]û?¹?^]ìO¤p5—ÅræÚ×c1Ýîºr Ö«O¼¬œW` ž’,ý‡k*¨–ø"B¬¼ €%Þe¸‰´òðù Ÿ0j³Ã¢+û¼@¥ßâ@Q¶5 Œ ¡áUI$Õå´¯t!ˆZ-,½Úk‚‹HZcæ#à´I HòâRƒW½çl*N©ÁXímǦøR±–)4Úƒ^g¥«Yéz2¼lÄ[k‚eÉkðµðA·K,Ž*dÒêo®O²¡‰\Ó ã øAêÆUN$*‰ÄwÇ·ÜÖc{%E²{_aÓ.x”-Ù·m3BBk™qÑ™¾¿ºaO#йTLzÄËbhLoQIVQÍÉå[Æ‚ì¥c…/NâÒ{²î`ö}—Ýõ%="7©­ìéžË:?É€ÂÇ¥]¤rÊS¨K•¨bcyÆÎ÷¨IrsYØ.ùͪwéˆW–¥ç„}Ó…¾ØJ¨×øE6 \Uƒ|?*”« IKm£ì†6wôO¥_å²à¾ÄnL»¤;öl¸fîBã¨ÌÛÂÊüŠ"<¸ß`¡Ú"GèTçÝ܉¶Ú‰Æç€9ë£a Œªï¦%&zö¤¸ub*)"æôÖ‡fΞÅ8·‡¢kªt  &JŒdìÍðüc޹ÈbŒÍÖì ¼Ï¤ŠDͪ·¥ ͬÐoG~ùO¸Ö¯Äµ,ôbe:-æ€DpÒNΛoÑkªj޼ëÌm f< Ü„âîø¡ðé.0»ïPûRâéôÜæ4phc)ÛB*¬î^îè4ååæ~ ÈC¤~&G$ODVN°% ! ‚.‡c*yc4T<´ —©¢ò+f”«$ýnð™ f7º4«l× Ø&š³g^\ÃbìB8 o R^e2d‚œ®{¦Ž¡ 6˜N²À‡ºµú¢rÅ”ëÎΡ±nÝl¾‹°ô1 ‰#Là’E\c1ãäØÐ{®2Ѩ²lãá#Š8@¥ªg¦zA „)È\÷N´Üc i«$­ÞEœ2±zmÃG" …Ë! ¦ÊVpN¶Â€…€9gàS„ž½ P„‘ cf)$Ç Mxô¥úëäj‹Œw(bxÛn²Xìø÷múýÐx‚«¼c#=3pžäïê稒é1 ä6h\è еè°ðî5È6ç-zâîˆÝmŽ-ʵ%¶nbœR\¼¬w8ê" 2BLòüÿ­ÞTr*ÝÄ«¹#CvÔPk11Ó ¥¸«º°£¤þÎð1lmÎK¤húe«à6"ÄÔ8`£ÄŽ-(Œ<7þz……æú*’^NÑ7bZAŠÆÆ'À¦pD·R,K£Ð$‘é?ËeaüšXІx0€þ eEp4”¥Ž^r« è§@.H»°hStô¢‘M&Y ’9‘7“XOÌ|­ørŠp‘O@°™BÊxß̽ì@ŸO­+AÿÐu ‡©;Òy)pŠÙƶ kšb‚œj…¢v4ti RùÍÄ».¡ð’©È§Š¨€!JQ ª’`¤-Qr+DY!+ºÈëÆÖÔÄõÏž›J†ƒªÎä@äÂZÂgÿ)„º·)V»´!)ϸ§OZ„æŽZ2ï*¥×N[ ”†*Xð#($µï'ðô:„(3IÅH+,5b$ìÔÕG#ª³ÆQ ŽÍB¾-(Á‰ô‡rh­@Í øôRR «E•"@M˜çt… ãñ.ç²×LJ Óð%£ Õ0 ޼Góìï•ëAŒmUé ðn“€rOq_…«(çEH§M~ò@ g3RNôDtz"ór4¦ô³Ž÷LÆŠ“[‹VVö?ö.åî–§c,ÃH@ÏCêl§D•¬O6ÿsl¬ò]CN´¯éK‰µW‡ºžÖá3í$ç6žÐ‘@´܃CìÕ›aŒ¸OÈw †T@¢Å%ÐóËEWé´q5Nu.žù·Q®´àŠÙjP8´3³4¯å1c@±è4ãδ§8h®‰i¶^o_5_+2¹?5*`ÏwhŠN ²É^ån4 Œ¼4ó_ J„×:y È€ rX“cjq}kQðK•ê¦nˆÔå—&¹*º(ÓéNÇc4Êå¾ÿAþDl¯—]Ow(ë¼.dFOBE,‡‚þÇiIvV““h=ÏMF$#…ªÛÎb QЛj­Ú7sX$RÖ¢’…Ö«P}cE†‹#*÷÷ÓUæ›JºÎnÙWî°N¤lm_ohl·ÖÿÕP™È5D` D±M5³Õp×Û#޲P0Žã)I¶³ÊÏ5„Šyv7;‰rš·…i…Ìòò·ƒbçwWú l©²øƒiqëºx(N·üy´ƒ4QJÈ:rUÖÍèû† ®S}ìÓ u£pßIÃàú•u-‚ £´+qiñKô;—€ÞÁ Ñÿ/ÓŒ@H„ƒáBŸ ÆnG8„D»\ xgª;a"„T‹^ý±wJ¸'d ¦[lêàï6ÇhÒÕf1 wVªu7”©3RizëS9wÄsʉBR»?†ïQ3Ð;ÂmÄ$cñPJ¥~ržD ƒisq˜¢«y%ÌÞ¡N ë7c.^?ò2È:X™Âôv5bp¤(ûk€Æc?‹ë}´(‡%i·I *8‹Põ³3‘P2b##Æ·‡ÉÀr˜Ê2£5NË€7mZƒéwQü ëx»`›‰B9fÁøsG6ï–&}Œ´@yz„Æ!0u㓲ºß98Ò?ò]†Áð–U ¼¡†Mz²ª×¡rüï·3Îb"®ÍKwBç/F·¡PDÐLâ¾$¾s¹.÷s­ò+M‰Û!­^@AJ’ÏHÁ6oLÔj¤yÖ“×»9ª»c w÷–ÆKè %<„üÑ}¼²Ïü¶¼.6áËmYì;/t'q°jMÓˆi»(úî"I äÎ[ú¦»©n5˜6wÃ#„õ¬Ñ…*ï×mL“¥ûHëÅ•Ùlë,úSš’i›W:†«0‰0›´…L¬‘A}Š þ‘MÕÊæ[¹•I—? “ÿÙ´:!̈ðuRÁhS•5NAr'È)É+d`§Vk#qP¸:þGüâíS0ȵÌÓ¹@§S<nwücÓ;ÚebY^“?R+]Úµ@KÉ…€àhÎ ÷È6iûêÛÓ™ø¤çÙh• Ä+ÂÚ€ ‘ læ3ÆzìËŠf²·ϱ½¦t£h¢ ⲇêx>…E:ƒ¼Ñ?Øo‘§k…MË£H;gº/wÄ ·æß¾cv–«“y³š:™sy`3mŒìGÁzk‘ «ô»BK=±[ShZ=€öÂÉÎ]s'݉Ë/ ‰@ ø ûƒ?¡P€"H”9ù‡B€ ˜Ô@„?¢¯Ç쎇G#ðÀ,ž!!’Æ"ð¨ài—A%O©ÔÚ+J£ðètÒˆ’½©YTb=‘¿e‘ØTÄ%’ÐhPøäB1%ŽC Ï¸pɧÖíÊíXŒ>nID"KO]çO¦¥î}D¸>cI Â*¯D$¶|–刂Á£€l•þ‰kRÓ9¤ªÓ_¬ÉaÖx†H ¢­Õ3@= >GTcñÉU>}!•l!I¦‘ñ½¢GçÖ¨U^QÙC#•\áÁ#7õiME TM#Ó¹>‡g9Àþ’ŸaàÚ*4ù Çd¬?íÔÏ”ËÃaŒOºÑý‡Qh䧨šï+-Iï0)£<¡-.‹«0ŠÓ^>ÈZ¼¨‹ªF•$*|ÁLê ÷£ë ¼¿’Ì‘£‹b­ÂGûjН.% Ÿª$(ù€0S,‡?HBÒª/©¢nEJ‚å·ò Âø©šFÜ?JŒ~º "8ÞŸ‰ûºúÑ$ph’¹ h‰%KûβÎ#®‘Eo à‚#êz–…)òaüŸHòŸ!¢OùøÆA1|E@8¨ØŽHÑ*¬Ÿï¼¾n’£Rpºi77ꜧL2ö@ ‡3][QŸKKƒD°ƒ…Kk¸ùµmdË'jŒKo$É=ÊV¦R(2|°£‘*9Â3Å‘J9ò=EÉî]1T¿ÖT"ãAÒ±üÔ£ð1ï\×3CA%"ëä° Í%'5“Ê7V3º½éõd± Hú^…5Р-ÇØ$šF "JŸaw ÿFRèRÃ\¬1-Ó Ð…xñ²X´ås¡ "?ÒÖ• cŸ±|ã^OOkWÖÕ»ƒº¶Â>°ßw¨á h„D´è{¼µšÉ™ L[ …'‡â4ª+þJ¢¦‰òŸŸY¹r™xèThŒ^÷. »/ Êu"(·N¶£®ëë¶0/ê¤Ó¼¼~/2Ê·z¤¦\© Ú¶2¯§s"lðÓsöO³Bó´öLy=H¯²A|‡;ƒsÔM&ª]Ï‚ÍÑ/çUÒF9þÁ"»¦ë«u;¸z%Sí7Îä«Îq3X/,ªlqË!Òãn~FGâÓ¹x¼nˆ÷¹~çŸ2Ðò·7HÎ]»L–Ú^»*>×j Ї$­&³ ‘+1|€¿„¶Û¹ÔúJNBálíõð®Wš>Ó+Âz œŠ°V¤Í\z0L©é4ÄA)*<ÊZ<“r\apjÏ}›×þ¸•B0(]¸VBá];ðAOΞôܹNZ7rK8ƒ?²ˆºPÛ¸q¯¹ž:8Z V±>D®ê¯HA”%A'Y €÷GD•t·±þiYkÌ9<ÂrÊ¢“tOšÃuüEJz´\1i/rˆÝGª¹5%þ!ÅRhŸØÖˆµì=ir‡nl½[HƒT€ˆ‘y!Ðø}·)ñÜšS,&‘ÖâÿàŠ \.%Йµ‚ëN™/1ñ(ŽV¾QÁA± Gñ¤LcöF='–ßRyóv°@«5CRFL%>Nh‰$ùB¶¢º5+<´'×DñŽ’”ò5ѹeøIŽÉ5H„Îx„Cd‰ I´¶)9´D"=eîY@B}!ؔώ#ñàNÂ… Çü¦„9b‰Rt¦3’tQÜ‘ÈôÀ„ ÌM$q^X<ó¥&“c4“Z[<2$¨¥Jåtîmí­£ßRHÿ%D¨ÌAÆšè1’*-#¶_@#r™ËákOBª[%ÔÆ=ç|†Aô üŒ½tEQöôâu¨ó:¨.LË%µ'SâÔF›Ó1¡EéüòH±±2þ®N²/µ ¸ÊŠZºIôù'T4𦄶«ÓðqU7!é,íb¢hIfìÉ#¢©§RÖLxǰ5®Sß3®žpϰZcqË_ä"–É{WÊ¡®,)“ˆ¬Dš!ýpÑ:ÂÍä¶‹Mu\îa†Äª,™ØZ¬Â²TtíMI],¥”&)¢ D®ÓU“$ʉÒbÝq£ ¸þèS‚q®¨J7bŒgå¸F}ä/1öå¥äݤD­ ¼àÍ*,ãt\±xií½®²‰WYjk—*µ›¨•t k>Háa$†154ƒâÄR%§bï€*(?gϾu ¤' ì £§²âþÏà=uUë»;k{J$q‚ï\÷ÎÖÙœuMÃcé%H“ö§Ãõ\ܘL?’ÛV”ÀÒL²4å¡ùSN4¥!bt÷@y4”tƒ±w$å‘»tEæ†KU¸\n>¥Q¹Ñ'Xz媙’Dÿ,©:d¤¼!8ÆÈ¶¨£X¥ôTáHL–FbÖ}=æ¬_ʤ©¶Þ-do m4RWÒL¾Q$:Ä´ö’fit]ËëE Ë1ð諞C„V€Š–š¹f,’Ú‹VÙè”®Ù°„«×ëÊۺǤÑ'Kü±˜œ´&èþ{ëÐ ›”Û͉kœŠ1i'I«ÊU-ê“`0i²ì ˆå·.‚ËQ®naþØî¤'§«N[ £Hï»AVšò1q‡ðÕàË€8ÝÖiž{IéõÒ® …@,9 ImÚžÐWèôÒÜuÛ)åLÖÓFò[éÙUœAyЗɇ=LöÞ)\Û[N²pê·¢ÇëÔºëM8¤ù,®nñ’—¼}í4¶µ¼ØøQ"ó­Ì·]Ĺ…‘{žò‰Î¸¥‘œ.œª(°N±"»Mªm®¤Øz ÌÈ;~©e e®hköA>™£?s|¹€ÛSYêGmÒy!W, ˆ`² F·‹}Ÿ`$ ¥k1PÈæõê%Þ„áwÊ8–´«<€nMW9B-:Þ6ˆ’0XiÖë¿9葨 ÖâO[õ9bWü×oÜ—dz}Á—몷°xkyéÅQ2ÈF S¾r\¸HuÊÕ’6…]„Wc§;æÑ!dø)_B²#7´.Œ$ÇP2Y"ä§Ðy†¶¶¨¾†ZxÁÜš¥'Q$ùW¢Ê"¾¢{ü6ø?¡¸Èq×¶{¾êâ»É?’ÍË­9 0œº€,"EÀzC"„ˆ€°¿ˆµ˜:"é¶2ñ#–êò‚µ6 ¯¢Þªáˆ!‰Õ?4·‚Í¿9Ã?±Æ¥ÒXÀ» ›¥(Џ@-ð*êÀz7&¡ç¢Ñ=À©²«@#J¡RUS+°SöÁHŸ¨¸6Ñ0 ð¸ ñ‡Ù##;N0’‘,3£Å¹›3Rª¬´7iÙ 0ª3¹>¢ºA²—,6•X¤6›"BªûÆ”+Ö!ZR5ØS Ì7[‹áK³@Ä*ñ¹²ß®LK Y—ÂÑl8:ªÂ”Lˆª˜ûг¢¸úo Œ+1ó-A«>€ .Á»¶A1à¡{Õ2?Âêò±KĹ2y ðÒ#Ò?Ž‘2›{Q2Ì)ˆ’‹ú0$yʘ»»¹¬®s@˜ݽC’œìKšK±0‚17»2Ü29“*€ ø>ÛŒˆQ4 $ŸŠ¿'zŸ Ë s\†Bü=5$€H()‚È"M“}¶!{â9=zÔ'" ©RF.¼?¸¥«=ÆjÓ œ^Åù01Aå!ƒa“sØ”)±´Òóň~[;/p¡-é·‹üŒÀlJ[S¥17Ûð§ÅÂô"¡É 1É)S¼2^;¬Å@´ j¡ìP¸óæˆcI)i޲Ÿ’Êœ¯´q)c[6´\JÁï|S:zð›’ëê·ò?œÚ©ê©ËÉÔC‡ øÛc™2Ñ2KJËa²i‹¶ÒÈ¡ˆC¬HžÌh!¬v+:•t[§šWˆA¤¹“†ÍðªÀ—ÔFZZ¯iÉ(p~“A’£˜²)Ѵ之ؒy^A‘½†Ck³ˆ©ÉÄ¢Óÿ*9‡’UàÔÆØ}ôß(©5±à‡)²ÿ)Äo‹„§ˆ“†MP¹|Z¤d/C=ÈÁ‘€4;$c1At-ÁÑÓ“rCÇÔž¼SÞ;YÔZޱB»¶"J7&`¦08{ÆѾ»m¤Ü zã€0×À¼¶Ñ¢6Ô±sƒ €‡±ß™ÍÀC É«… ÕR‚(ÏCÉ2À2ÈÉCÜËãºbÉakOÌ 9CO@}ŸÜ„¨QBcˈfFOýJ©Å’á»|èEª›]SÚ Uã%Å*ª¤Œ;¼Œ›E}.°ñ*‹ù ]-a7<šƒÝ½”™Ó¯kÉâÜ;£™}-Ôm[RëºíÝâBìa•¤™0ð½$aàá²5và.gÅò ‘¾)‰ÑýÅteÎÛUÕ L[­cå,\ܰµºS½‘ÇÎ`²Ûô;(«&ˆ­¹’*d-×Âì5Ìø¥‰48rðâ*}eXÌýe³r#ËÞS»ÙÁ„9A–ÒÄ@›ô¹(•?P{×õ/€ \Ìzßµ…4(¨¹•Ÿ·s Þœj‰›Â ‘S¢áDe¢ª2Ô¼QÂôgh¶émChÔ£s/Cv$çYNü¸žšÇž`mŸå؃)êÙèȃ̸ð¾»ìLf4ĶàtpУbUX÷6 p &á%‹¤µa¾kÑ»ÑÐ?£ªº$ÎŒbˆý΀5õÔýDŠ´Ë-Á5™Ú£Þ1®K)ñ{ÅR `„A€,—‘з:zÅþiïµ)¥ˆ÷‘ÖàB=šÅqQÉŽX•s>[ a7båúÛÜÜkË M¤ •ÈÌ5ê#ª`œÝÔhI¬~!ìã„٠䢙-“ì3bõóhÁEæ<Ê·xMAÇ*œñ¢ÈnŠ¢qc Ň8U…é¹Âà¯Æ6‡[‡-O§,»£Wkj ºuöV¤;È݉äKÝ‹¹Öfæ©äYÿ#€;òÄJÛj2]Îí MGªýŸÇ[ Ñ%öqoqHœº­c-VÎ’©Q>ò @jU9jK‹¸–ÆÃDàs‡A,¤"â}ö}z‹CÉ“"9òdìÒcÔÝŒÑEÇF¬ä‰U»« Öi–µKÁw(NoN¤™Ûê›3ï*•JÒÊj{âºuܤ„ øäB•‘Óï¤r³—`,2pp~¨fi臔ª§¡E®JÐŒNÀ¡Ew-O¨<ÙBš°éMà M?Ê#ž–©A6~£BŸ~ÀôlÓm'¬¶l­Þ'bÏ1 É>©Ò´ tN§8³AkH(¹ÃF`ˆçÌxnÏ íÊØÆaüاÊC7‡ƒ¹7+‘h´‹}ní6C²pÉ^þXQ«gJ*"<˜Þ-eÓF?_JFkï`–µnuÏïG5ÓõÀšOm`l;s~k­y0¸4;¯ä‚àÐ@þþ†?!ÐÇð$ýŠBÑxƒî5E°`B„B¤Ïùz9~D€²É0 eFcRÈäšG2B'ÐI4þ „Hä "!A Q(PI õSžO$§Ü²X ®HêoªLþGX®¤sgÜòGkI¢êòj¶I«häòLø¾Q ×à–¨ÚîT×ýë ž=ñÓ¨%“¹Õ@RÊIJ]G­€N‡=m“¿ëÌ›çU;™K£ÖèfNA°X@ Ô*øøž÷Øç¼ŽYÅæe²ƒGµO 7ÅßÙÈôðë‘é_öˆ†TGîÅ)tê|Z/,Å~ïzš ÌšR"‰”1i:<'€D zBO“ É6Ì"«>‰b! Oâ‘·irrü(MÂd¿«‚¡Ä(Ö¹©’V‡(Jûè¦)”vG±ú €zÈÑ©ø±£PtS ²ÉR/"Œš!²JTªG©ã4‰=¬í(lJçE“&'«,ʰ¨ ¿©2<–5Šª„Ú(RúNÛNðKܦJ “Cˆeé6Ïìù'ÔTÛ,¾O)ÿ3²Àøø ¨3¤Ú+²±E³zDÇ‘4^¸Ô*16“ûþÁ0mY.Šd¬3¨¢Y9 ð»Ìëô7o’ÞŠOÍ! <ÐÈÂÌûHçԯä„N µ7l› ’L©’<ÉÎÖ«'K&w7LÈ£ˆŠF.lÄ,ôCñ5LìûFÿ!EF“%ÔÙK?xŸ³õª“RˆB°ÊV3eüˆ¢OûÓu€ë×MxÚɹ*œ‰.!Ìý):"E”¶+SÀ ªH2‘ú¸à >V€y/ô‰ýYÊl–ÛË6…5gãM¤·dÇâ!Íסù$(dÎþ¥ÐL¬[W¨šÉÔÅœ÷O5n‹T³ø5S…$Ò¥ð»€í¼Ø‚5báS¼ëk¤î´¬#—NqxfJÕ@æ,º†5Ù[ö‡_·,¯M°)ú=aúýG svŽ+s€4¼÷g%”¥¡{ÍÒÕP§íüÒì%Éæšù\)³Þõh>Ýgjö®›¤ÐL*ðŒ!–çwâ+v;î³?A#ÍÞ­åæ¸Õ’Ö¸óäÛe;eúŽlgåú‘î’­;¶F*ƱFhtø‘£œ÷'… ^3ñ85ä(É·‘쑉_~ͽô¸–i 4&í>2¨B Hþ8¤I‡cþÖ—á+äõ.KŽû®b@ÿ­aøšŸá'WkvJþÏ£Œx ŠZçÎIÁ$‘ï›%2“# ˆÆ Ÿö¦WÒ!îyñPÉÇ•R’ 21tÓÍv;6œÀþ8q8ƒ)óB„‡¢ IdÝ©v=*Q‹…sä8ÖØ¸IäE¬*~HøžÍ,cHºž£Ö¶LC8G²1ÇOÖežìz&N™ú-WÅtÞl±¡ ÍeDÁÏëw8¡_ÌÂWéŒ%ÄJ&ù;—¥T/j?UœH!:ŽcÌî 0BÚÚU­LUæóQ3u#„ŒïÎÄt°éäØK5- .FŽ£IŸ‡IŸ­² ±ÀfõŸ’9Yd‘/då±°ÁšëΤËݾ±E äf¼/:ı~ÖRNŠâC;Šm5µUD%ªx“m‰TÅb§lž,h‰ud#ˆ5—«eM–Ø-M¤\0 á$ DͲî2ÐVØ2ÙÚ dL´Rˆ}^rC9’`«²r·^Oûù:Jèúc¾ûÈÕ¸®k:»Ú÷tf¨ý•5bù­YÄÉõTÌ}ŸàS&dé OäžX3¢ V­e:ñMo™%VÜéNîþºÆè™À,ƒ&G)µ£jÚ¢b¯íù'3Kz 6¨'9ÖÙ4¥{Ón0›á{xaN“½/4ת0èÕ}^¥^VšU`Ò‡ô¿´LïÚÀAáØpÿ(ÈVšnÏ + 1ÃxÈÒ`Ú©Y†'Ö‰„Wd‰¹™PÒÐ$šì'îD­†J­ A¤vB†ûAQGÇÎÐ+zóè:HzÇ–F1jÎæJLŽü¥ÑÐq´¾D¥^À"n2d¹CèIPdžëÝÆàJU5ÂHγ–¡élLñ,ì‚Ôäz€hHjŸ;wNòÁHFiSTÑÌ@&T{>µÌY™†d‡#™Hã”H" êhZþ‡Ñm±¦7UdÅ'-€5d ±Í}º˜÷á¸Í²— YUòL }Nf‰ÏFÉ€™ôHg»GèÕ©L³ò•^LvÒrùl:T=¸«›û6“ÖodÐwºögwf{õ$Ã@V/àûO‡}"/Ø$u³¢YÈ”Ûa`2.wà¤qïZk$L?­ãù¨6çΘOÔ2®¸V·]ÆŠ|ia±Gj|téÜ=iÆH…ÔX{ìžB"dYgÀÖ+[Ohn\u!ª#Ò†ÅL’©H•%ƒÅNcô *e|::0füÉœ¸%û=iÃ^çÜÿ¦À;83í7u^jVãëìH¾K3°s§b¥ÕÂ>à‚lÛ¬Tðo)?ZcF{Tï!>pÞúe½=²Ð¦:è©~nî9>F-&Š›Mk*IkÈÜÊ 'Ây,#&u߈ É)}À?8| ]W‘•ôHEêå¬×3jú&*éi"íkc:]ý‰/pFK‘®ýñB9ûk^pGL˜äÔÑ)š!ÄB¢m\«B—êªÑ¦žíît㶽ņÅÏn®­ n¬ˆÂ@˜ã0#FîŒÌp†$Ä%ÏÊÚîÒ5NÀ:Kü$ë6+âÊ?âX:ÌX$ÊÄr®4ëçšLJòNèØUÌþ¯, nn´§>KÎ ÞoTö®"¼²M &HBºçäm¦"Hú*p‚CæBÜ¡úRé„àŒJpš‘ŒqèÀý®lÊͬéÐ0âdz¢ð¦– ò€J¿ èn7mò—p4¹n,åÂy ¡ô€©NU)œ>J*MÍ*¾J0LÚÃâl¢ÁîèÒNôûƒð×nd(HS éÂ?m þ±Vàì&èƒòz¥†_k@LC&#‚@Ì*$Õ£†ï§“îZ²èÖuB@ Xºb…2n¬ðTcúÚÆµ&öϾàOr'æ<º+BÏèÀ(C&£ˆ*y":‰@=b°7fväñ>nÃ$€Fï&$€ ŽuÎ)úˆÐ—ð¤MÈÀMJpÊ>PTMQS H$Õ‹êˆÇ,JQnÃp&MжOt?æwÆ(Šn€üP–à©? ß#líH™Œø·°’‚øH‰à‘~ƒ¾Öêd{¯¾G%Ù X#ÉzJ«žG¨Õ1 ¡®0ÐŒh‰Cð²‘D¹ ÔÄpnÑçmŠŒcé a !Å|ËÜ…PK°4Æ1µJŸ†ï$°r*c¬Ô 'ÃúZ:¤‘…lG²J „ gp^LQr-²p2nk(éb<ïò6à‹ô5BÊjMÑ6U/J¨%ÍÖð`….*NïJsÇ\+ ÚÓ¡äH(,®gk!ŽØ5H^oåÐû&žqæøpêÊBª8Â\³f8îTn®jêe‡,ó#y ß0ê2ÿ1¾ÂmZ”ÖòÎd{±|ÏmVjNòê“î<2̉*ÏXœ§ºû±&2ÓÍ*­‰ n%çH×ÑfЧc°ž‘“Ñ£þ¦DbHÁê匰p ¢RD"㜈î\ÿn¶VÑ8RhÐä &ß,hßdG'E?f<3ð?+ ÀQHÐl¶÷Q2î GÍ&ê­éÛ# I ÑS“e8ÛGÐr€ QÇÒÊÄï- Ò!Ĉ3ðYͤÊ, #’JHƒwhOE(:½r{ ó2gi;¨í"4ÔâB8Xç5üÍ<+òôÂË@ª]/"e?bÊ+ì4gâ?0ÀIjÜâ¨ï1JôÆf¢­Üûª¢åÓ Ôb0°ÅO8ÚqÛ: ,l”NtjMf±°šön2$¥[‹/U"dï§VfÎå‡Às‰¬Áó=i!ÑâH_Tü‚¦ŒeóF¦tÂ92<·O„-’>•9A50ÂæÂuÌrTuJ·uÁO"Eé¹Oj”-„FÌiüô£¿ À ô¯¾*Í`Òh™RDÕr¥Ënïš?ï›RÈáJŒ,‚i •F·²TÐUþl**¢¾–¯ˆ!MnÀ¦¦óS—b©-̦½Dc1Aó+R½ñ@!Q×ȦgñÖ»pޱ•? ”åȶâï l0Ö1èË”«P1žU"@8¡ Dˆœ…G>£KEF<–¦±ï ƒ]í4’pê&*æƒÖŠnIq2:STÃ¬Ê þl ULñ÷*]‘'–:gf°úpv"ˆ¹Bn·/Æ“g äÊöÄn€Žbö/Ã-#C.~Úò½Ò¦¢%2V¨¶eGIPI°ÇŠ^ν"iFÏçL;âÊ(Cwé­YKÑ(`Åã-‹áfVŠfUi‹DwRBŸDâ=tŒ#G Ní"ßf“$Î…¶ê±s¦VðËFÒ¾©Ï©aÑfQ N÷UN¯V)ò¡^1òPW~УJ¢£î¦Š&Xòù5:â°œLeÃ3‡+öñ'”Ê*q®7YÍAc3|ÚÓP× íY7LBÈû嘩ÊLP¤Ý |{­Ü¤Ë ‰-mÎ4DýÑÈÀÐ/ÍXaSÚR„î+㬻lòp ¬Ô1F1Xï÷{j&«® 0þXø¨^|fg8\1¨\¥‰ì9^¼Ž¡m€æT8*°ói~å0,˜>Æ=7ÈtX.õ̦®'coÎ¥)ÚÀ¬ónTq) Ń˜Tø–¦¦’¶`õ>Ꚙ‚5tá÷M*"œ®ªÆw“q7±7™Jv3†‹ÄàUdìK€¢eÂŽ­*\+,bíåN¶Ð6ĉ .„êšVQ‰X‘b‚¢„ékºýN$[¯pÂïá'"µ}IŒ}L À©ù?Á·TFýù¿ˆg56âXoŠ˜,¦O—)‰ ÕôÄ1Èægê¦jxÒ·–¦$çE+åŒéÚ\/ó6¶y8ÞLìÍ bi6ÿTH ð(èSU »e Lö|ü ¡„ s£×™6ð›˜;„Оû·ˆË¬³6ò.¤ïdŽO zÂð3nfµ.˜qk‘9£D¹#¨o è‘M6–ük UY]©a SýWur7Î*¶U &q•kå£Ý~Æï?oK*æ+OÑ2ø©õÁìF»w.È…€…ôºÊuë M°—Âo+#ØÑÔ´¢mâå®À®ò|ü` =ÍjLQ9g<ˆU KÑ>N¾Ö˜Ã„‘*D›P X³Ÿl8$¬®So™Ð¸Z§¯%„ nN©x’‰ £ñ–n ³É%øèUR=;iû†:Ñš’2ZssÆZعºÓŸÀíIV¤Z£û’ Æ• œÇ5Œ˜”9Õb+„Ü¥Õ)=`ïškEÃèn?öˆThC¼Gs5+N— ²˜"m'Q[Tî¡òŠtÛrn4ýt §.óD€b¸…8j'øKÀÒ%Žå±C²±¢íÜÓ ´ßäc¾€&òÝÔ¬ÖìPû±S^6åk‹£X5‰\)Àw<ôxµ—RéÅËÎöÇ%Áþí¸ßëš"P •9)j¹ŠŠ.K8ù›˜·ªï™ŽÆßI´R˜ÍxÇkÄ6”±Ø1=ЉӴzñ\3:h›öA4¤û”Ý’lè^â˜M·»é61;o!Qd kLFúÓi$¼ça«”õT©× 3æÁ‘1Ž¡ö_®»‹ˆÜÃÖ;ÑÌväN…®È!„‰8|÷ËÕÖ ‹§«3*sÊTŸ»®Ð‹ÐÝ[WéºçÜý\ÔÆ¸Bá°¥FÙ|ÐV¨™J x1Ëd¼k¯N[¬ïy¢Ž ®þhÍ:ÀâtÍw‹zG©u¨=dJ­2¼œ€>´–×ÄzŒzîoYX*QIWªÊjΡcƒˆN‰”þN©“¾½LkUiUZ켜©Rç×ó¹Oþ‰E€jtÒLæï~Ê´~g¢ø×Ș‰š[s¢ùt8=Ô¡êfÏ3Úi¥µlÃ*i!Š_ØŸ¥ôšØxK+7‘"—ù•„oõà3pãh™Ö³Ÿïã±l"ð€’>Qm¢ ’”ftÜI‹ÐÙ#l•#WP;S»m6äùJ"çý˜y¦å«¶îà”¿MÝ´ÔsÊÕE.¡=ëÅöcö\Ô=jRþÞiÐc²®º,€\aYè瞺vt•‰%™/˜Ø±8ûÏ‹D}yŸ»öZYsÊ¡Y§ÓËvÒþ?à€4 …B€pØ$=þý‰CÀ‘P^>£x¨ü‘B€ÒXÔ*8úÊáòP4IûƒÅÀR'ä> Càðy„ji žA¨sÙ´ê>ù¥L%ÑH¬>eΦÏz´¬ ‡Ì ó¨T~6¥>kˆÔjSQM ñ,4©ÃfÔ(%–W0ŸÀ¨°¨Ì ašF¬i´ÂìÿƒÖ(¯¼ubSA„Ƨ° ö 4Á2–ì¨aXÁà"Qè­6Þ”ãŸ`­tS$’ÍŸXýbõÍÄb@}õÖ¬Nµ–Ø&øÆ¬ð.CÛ¡äUžü¬Ô6ãÜ¿aü8nÕð ñAü¬À¹RŠå¡u¸–w˜ÇãZÊ_ ë„Ñî’(zäý-üê3&É¢ú„»¨j>›%ÉJ\±·oû´‰%ÍbRèú`‡¥,bÜïo: Ò±:Ü¿ ÉÓò&Êsæå/góÙ­Íd.3ÉJtÑ"ìLjܧIsî-IÓÒÕ#’Z&Ô¦h»‹¸ ^&b´‚;)¤zÎ KùýK¨J¼É N* €HDÔ²@ m)KìD·5,ô¼±¼ðŸ"IÈ›-LK̸N‚O4ŸÎDPLkc2‹ÁÑ2 ˜Gn;}!nS™1Q3šF„Ìlôêö<êú*øNTÒ °¤P0'»“5<ÌQ’º& ¡­`'RÓ:«ÁüÖNð…<lõOQM %:3CÐ÷Ô/8…9Jl‘+cʆ«fÖ%Ó+âGˆ|¶ùÆ)]1¤/ôH†¹W[LZõMDö(´‚‹U!4°½XOª$VÝ)09hJ>”Ë—bê+ûÀñiM«v ‹œ·FÓm@ÖñÎ$˳„ß\d5…Dæå9e!U€•ô¦ŠÖ'ã•h-rü݈-X" 9Tl±ÖmÜVˆ00 A[­S–soŸ‰„:­ã®éh•Ò’ÜÍ®!U|[n`Ô­n÷»c…¢¶VÁ1¿› øZìúi9Z‚Ô]ÞvDy¼Â³ÒÜræ¹îYmZKSÎ:Ózi±Wγ–­…£rs±·&©4—+;àøG›eÿ™`R<]I®ÖOíd¬×Km*m4Va@Ÿ©¤+r¥o>Äç>ª颱}â ‚m6Ä:ú/̪Øìû6%zî•ÝlüÇC2Ñ-MÛÛt†Á&,ÒÎÞä=?R Ð‘oJYÓBJσ³¤ô˜ƒÀæÇÙ‹yÆÕY¬¦|ÌsYH”+WGÕ{€"H@‘5r¦V#þ$°B… QH"©YÀª$äÆÍ¬9,¥'&ŽÌœ!%{Ãéº6†ñ€ q-Oœ¨X) 0­´ö²SrÞ!`ÿy€ ‹>´\CKIkŒd•¤¼¡VÑ \P%§¸³ËqÊ>„ ·µw`,m(à˜ç¹ˆw¬ñy3óÔ©ZäÀ”Á ߣ{¸z«Ä;î‰slf®ÅÆCt  JL1,s h‚bjˈͱ²P¿ýXê@Û’Âu KÁjG΀S¨aÈ“Á‰Ž|¼‘&¸ÙÞM`+3>%ÜAm-ÜIs,Zdi(M·¶½Çúµ!éµø÷.Ë‘c"ÉVc,uk×ɘqRæEÇ; £_DŠ8ãv’!pù8†:"ìK¦Ø ´$ƒ¼ÇRô&>v/£¼²"¦á(.È,­Òó¿TŒµ™6rÃIº·:Ò H-#?,H$É> ùÒ’èTâ—²à@liÊ3b‘»©Xä¦\ÍJD½Vl¯gÅ`±ËƒJä)ü¨f¤è”±Òlk LûI†;ºòø­æ|™ç¡j!‘ æŠÔUEE)ñŸ=‰yÇ€ÐòT6>Ø×´m&k¢#o 1¯aRC8}Ä5ÝÃbêbŒš£‹EÔ{F×䙫¬±AÓÙ¼‡È•J…ö(’žƒ2_Û`d••ؼ÷À¹zï¥ÕÙ”¼bk–ÖiFÕ˜Úž“‹C;r1šÂ!ù[¬$§mµšÊO±ž©XÏIË*\EAV*+sE{µ£Ê)K\J!*mߊK$9ˆ†Mœ#Cé¶DWùÙO Ìž£Æaiñ²ÕV\s=_™{ :î?~VÈþŸfD‹µÊ|ûÔÆo÷Å‹S&"L*‘ŸâFJ÷h’)qPl­wHúk;ru$@€'-0€*äd¸ð'ƒÝu‚“”&ÖŒA™%•òîzµlË(鼯ÚÝR"`XÑ„’¢Î`© º fhŒÊ"ÎÓ›uäáÌÙ „R¿&f¯f)5ÃÈmND1× RùgVA¶Ž¤µA–ê 0º¶²,ɶFˬþ*»= ÕZÞ®Å;‚d#&Ê<‚ª Aéõ¼!q ˜Áå©@–§¡#ÕYž 4^®^6Œ–×%DtʱìÃÓ½¡Df@Óô=-²r· '&a=õÚ’"í5l Jæ´To¬ŒÀÚ4[ŒFÒJÔ³8¤Ìƒ³vùE­ª£dÍdzæ;$’Xð¦ a AàêÌÓDâìZ¿YÒÁ{öã=ÙÌ0è|æíïhÊ®1ÅÅé VA«1ÑG’Ç.í\æÅ}jLpâ™®cÜØ.r$­‰Öû¢<ä8…tÞžJV®&[K=T¼œ‰¤‡ÐÙ •ÐBi¦‡ý!ó2ÕH+*?U~îC¦íƒ™çþ>›×'Lv.l2,RJVáËî ñá§ÒŽC+Ó¿4P„–0þ´.5Ù•žš‘&J›±ù&¿¨¹¸Žã 1¢Ö½aˆ/àÌ a®5K¦œ+$ÒÉ’³7"QÆ12µ.úf«ÇŽi?¦è~.i¯К1iš­*‰é•±jÚ–èß99"‰K>²°ig²+'<’ï¶š/‡ò"¿ËÉ?i¡¡ë ©¬‘, :¶Á;êø¢,'°íˆ“ØL-3c7Êã9kŽBâ'Á¸”°…@AG óÙö¥BF.¨4qèÏ1œ?”S¥Äjk¥ ±™½£{®ùH8’‹6±œŒ9§Š)šÀle®øíÅ#z¾ÒTA ­©¾IšÅ܆9<=™Œ$ £y›;êĨ„•š,‘DšÄkç‰IÈc†›Úæ»à³¹:æ‰IK:¢‰äóP+òž#qÚ7⊠úæÇ:Ë"¼È)¿XBÔ¾,7áß>Ê®œ[‘²\Ãóɤ‰*æ®0ƒ‹вéÒóéà©ñ˜)ƒ8ƒ?—‰eC¢À¥àĺ@—€"–=Ì2¾ÆË9Z—Zòpß”–Q‘™Zꉤ1ÃW™²£8h•ÍW ÑªÂJª Ó€† R!¸ºí¢‘äK{™”˜¾s¿L:Í{|¹kÄ›„ÜL–ÔN>ÚÏ2ŒòÉ&JÚ°6|JzÊL›€”‰I§,™+"´™#¬‡â°DÓÉr§y®8`¬+eŠTÈ·¸öƒÃüB9ªøŽBcGû€š"2‰H JH~@¼’‰Y‹६üÿ,B)—d_ éiCI”„OÄ1‹7Rl(!YÀñ”(„.§³° ˆ|Í¥É$FÁÔ®x5iÄHô¿:B’<ð¸ÃQ M<‹ŸÀúœã»ÏX±³@¬ oÏÁ•Ñ=Ã'¢äÄ›a/JAykk¨!@BÒšRœ£º_O,üMñƒÂ©1“¬‚››0S¡°6¼ý/t€߇Ú9Ìã‡Ó‰$)äÒr‘2ÁÃDçâÔ{ÖÆd«ÒÌ$)I/•­!¯éxÑj™\²m ¨ƒ±ç’‚ësÁ ]‰qc¾ ÏdÚˆ«>!øB"È«³ž ºêdÀ¼HH‚ÙOÛ0Yû´MŒÄŸ —¤)wÅ´öM©ñ‘ѹE• ä¢,† )°zÿ7‚ITs×@R¼,Ê'Ë 4±‹P «¾펢½€jQ€D‘‚â‰i¼ì¤š¿·¸Ý¹sCÅ£|¬ãKºÚ»¯8G±¤ÀÏ붘yâ~!QN¶ÙÙCâô¦D½½Œr¨=…¶„@NXÇÏñVˆ¼„Jµ7±m°°¡cœRïÌœ;$è~ÔC˜l¾£ Rà@RW´°ƒ½1ÆœcF9PßR }¡U%ÂÚAYÑFSz)”EÛ&‘±9&ÂÈcÞ ©5êÉÙœ+º*ý6ö1³Õ“ªæËæÐ"Lm³àQÅRÛÃíÒɨYaˆÀô‡ y¡Jø©5f?¥Ôƒ’7ƒV´³Ÿ©ƒ½ @¥D:Êê;½M˜ ÌK$m5¨½¥·vD¢l¸â˜¢»ük·Îøï6ÝYÁÀ€;u(%nÜ$\Pª+‘àê\íX7yp4òo Q´¸ÈÔ¹KMϬ™Å­Ö·X‡×º½’³#° o9òÿÙús«e# È3:ß·a›ëWª KÛB:ص2Ëg–j[pµL Õ~ÐÊc9èß–Èü»¡ë÷B¼P;!ÅLIº(…Vüë*]ȉ<-Êë°Ó|“«ÑË»¢Â©/C(‹¦”"£¸ê: (²Ï!ãÁÀyel”*áÜ»»Ž ²ð}Æœ'»=ƒ:í Kˆ»òCÃвbËß[íÒ(ÞÂbøºÝC6ÓTœ*¨…@ KÎ*õÍ–mK‹Ð’Rµb*‘\äܸhã!à¾j\µð#Èß(¥8‰šžMâ­©¢2¢ ñ¬á" t°+$8 ¥;¥jÛŸàzd1ŽÈec€-FmjÏ!?™óhIY¢´J\Ô,Ê¢òOsjG)A–•É/;ÕÇU½¥E…ºÞ^M4LëƒÅ{Ó ~¹-ÏúÜÑ@öPC]åR#DGb¢2$Ãx~±ÅGŒMa.*¸v62iáaÜ\åÖ;ºFKêOb‚Eˆ Q‘ÇíÔ/D2AÛJbOí¬Iç·É8—€Ý¸c\g3Ë5iâ¸eN­´FÅèܤa¿@ðÌp4„aÒoÀt·D°Pžd­q$O#«er#O#uX xBú#d™›WFÆv¡Ú;ÏJUR0ЬÂ'ªD]NSS6ê¤snK^bê)Fë±´( rÆzy‡ÕÕ‹&“lB¹˜RôÌ9ÍIà ¶eo8|5°{ÎÛmÈðøêi¹ˆ KÊGÖ˜˜Gˆ#¡IJShò€4-=-Aø¥ÍbÃ^Zé4³”QA»°<,;ÇŽ#¡XžèuBd`jôÐVR;Ø·&æ+ë¥;㼘BJ3VZ"Œ{W&¨€&Žw5ùM€=:4àèmÀ(>u&õe‰¶< Ô_<^íGåBB‰×Kõ“=í ©ZÉç1Ži#ÜrÉlò`ý—."(Æ 3XÚnåSTörH³ëóý̼`5¸ÍÊÍ]C“ÈÔꥂµ)4ô«YYß!k©Q$‘”wÄÝðíêó˜=½c¤M"*í?1€IÀ/ÓEÍA€#T¾ë‚n0ǶáLÜCZ{¦³× nñˆË.T»9HWçCOk‡ˆå,tÐÖY*—Œr9×SaÃô›ëB“—pZheiöñ.Ök¬0Õ­îh½En%`…þâ{ŸTFù|Ž=ù®NÝ:lœÀ‡ý© ùAÜúFXψÐêiõ0™©&~éôè3?Ž¡àšË=cOgñçm&‚f+'•~õØmí—`”˃x·¡ßú!Ñ¥øOŠ×x¤ ¢.“à»=Þ0ÔÑR+Îj"ŽÞ Ò yÜxçÚcTF½bšèv,b_AäüPÒíµî@ ­¶·ÄîÊöÞÊñã]QÆÝÅ6+ D3ÕÂ_“e4†9ÆnÏO‡õ(GD¼’æçôè˜G´bK¯ Ðø>ï+âìeªX×o,GC¨ƒµH ᜂԷ{%C’6ðK+uC3)m#ûõÜÆf®ìŒm²7¸ r‚*"}È.¨„Ñ~¬[ Ù˜¤äBAàˆxð@€àOè  ü„aP` êˆ?bQ8€ ÿŒ#PGô2 Ã20•÷'Jdï°¶9F!Ï©¬ 7‰Êå É\2W ŽE"±ä21-C)ˆÄN—-†I@qÈäVŽNæu(0«Ä¨1 E–'ŒÆªO{dÜ UˆF,oØeZ {^k–K5uûšÉäh¼¾5„?0ÀH­SL‹ÅfèÄ®‘aºA¢²›ã=†´Qˆ¬Î½J§À€ñËcÞAHÒêYþ‰ŠÓÀˆ¾ÿ0ŽR&z€5¤H"¸ž CŽ©gŸ˜Ç/φX ÑÍãÿ­Îé"ÉœbÝeHß=X4ö<ÝL1?(DWØ©q=ào¢Ö£ËÞ£¥ª™­É[f–±, X–²ãöõ) s|ã> kºÆ±ÏB¯70Ò.ÚDŠ|*HÃÔÕ=O³zƒ7Lâ%à ° #†¬t©*N¢.˜=OC»(›€‚;©š`˜)ñþ¡¢Ã£OÛ&lû®RB/¤îÊ4Ä´4¥ 5±J.ô)Êz¤Ž>hÚô:OÚVÏëï€,Fð"ªÂ %­I,œßDîëtû®®CuIï`–¥kH ¢S{pˆ5¨¬-I©lJ-ÅðÈ!Ê Ë%Òñÿ*’$ÚÝÏê[öýɨDm=V´hâK¨ìÌ’ÈÜ¢’´È•p–¶'Ô$ö‰¹KKGÙˆŠ$Ä©”N™Û©+®1+u¹H5NmhïX`‘+·Ò"•ÖqsklÆè$☲4Ž5W´Ë"¬Utùq¼ÉÅ3CWUiýKAw]ÕM*Ž$¯uC‡óT‰µ n<‰ÜϪ zäT/Wb+=¯‡@)*&©ch“ÜüG€Hz¤ Å|ŸØÊVîV· 6‘k÷!´$¬¬Ãvéfr5­ÔÕ:X ›ÊJE:ˆ;Hóhœ¤üj¦‚V CU°ØU5ÕqÞ="5yòu4›½SÀ½¯Úê<¦êµJ4é0h7‚·c.#†ƒo€ Õ+ô»õßWØH \ŸŽëé÷Ò…6šºKäÊw½ÖÝQ -]àê}} _Ul8¨/•m¡ zžF_uì«Ó±Ý‘%dÁŠ8’¨Ý_#$I°âð^OC•0<’³rïˆbZ¤M¥À¤n"éø©÷L¶S„f¯á+š÷,÷Uªò_Tõ£ž}ÐÄ\o Ý.r’s×yŽB-”Ç7aù S"W䙣#2Zàý‡„ŽA²vôÈ#1]Œ™"4VÉ*b‘˜Òò=€„qÌî,Åc„CŠÑ#„®6«7—I*†ê,±’¤r⓾%qĽ¹ •§ ÄÀéA¢æÈ º|EDŒŠš¦vw_™nC À„1IR ‚övd¶C›qüª"›ŠæmðãÕ¥IÅÀEffe*Ä•Ë5ovÒIæ8ûf  ÃÒ z œˆ‡¡`w¢\å4;" ЉE|H¡bïѲK"õi0œ‹ÃŽD€”ƒð™ÉåJ½ +YxM¼ƒ·x1GüoÏ|÷•çØßaÉvF>¸P¾#@Véu«5} ZÄfp…ñÉÂú($X[Q] LøDÝð×¥LDý·F[¤¥^ÒÁ¼¥dñNƒ 1MÑÌ–Š¿È$PRì:T§#H3&ÄÜÌ9ð F i 5Tš;ÔZDj&ïÙc³fJ@˜¡Q$ÄœŽ<öhÚX"­,Œ¤ÈŒæ3.ŸjÖ:% ‰áPÿ_uq¢ÙÙ¹É!I„!EðÑk¢¥¬@ #¥ƒdÍ^ ý_sÍüX´*Mã¸ú>ë†y÷¸àÓ;b•‘¤÷¤Hç\kA:T†!¨• bþJôýà=ÃÑÚ‹gª9u¸¹]f@]ÁX'݈®¦w XsXmVî¾Ðàƒ—TÐ!и¹³¶"“«Ì„Ñè‚.’kMSè´õx÷Àä¹²ô¸ß˜™žw—2@ì!ƒ$@õ_x,B¯Bn˜RÄ™éܤñûQ+ô¯¥UAÉ\È$µæÆ–éœú\ÙOi@Ιç|îÝœŽ 0¿É§E&\°H‰À„bÊ$õ~>¨­Õ5 ŸŠ™qÀê2¨1Îzi2aíÚ04r¼#§ ÍÓ¼%ì¬ \ó¸¹%ÁƬDwfIH=OúŸ±‚!È©þÇ×2ã>é¶%¦$–ÒsXÐÓˆbi . –‘e'Õ dØùÄN¨ïÛÝP©t¤ÙˆòËP@›™_Ôeôé:ä­¼@%M Œ†iÂ)êÜåyE„M¼Èå/æÔ(xŠÅâ$Ó„Ô(w©à†&<c}—ÐÄ™¦Ët‘´N뢌œ"P¼À*ž^)”d¾‹-H‘ÖçÆb,Rg|t²’"GÅøÉà:Wy‡Û0ÐçŠ41Øçp4ÿ”åŸ+–-)T¢N‡˜³¯¦Ìê;#›SµQŠÆò¥}3Äe·k4à‡ @¥!—‹ÚøÐ÷1jYⳄ¼à–¿4mzœe!Îù}ÒnM Qêå¯îõ”÷îSôFH*@Ó¤ï¡aJ05Wf¤)î-“TЭâN¢œ™{vÝÖÒOŒQ‘vXJHøÒ:¨Ù_FóÐÖ ò'å€ÙÕ³Gý|k ´2o,š6JY> ™çKÌU‰ãÞ5¦NÊõŸÇ{Jí é_Iâ÷&àý5Ràî\$5:RÔ…ë¹4oU‘uä9¤Ò&g|N¬†&î¼…oøRܼKD*Á‹¦äð…¦x!úbJZHä*§í(– 6[B¢­¢1+ð9â¤&fRÍÆZÊ|<ö~lú-Žlšc|§å¤C  8"£ZÓ†vW̘¹dø+È! ÔÓz]¯Î_ Þ¦ôB¬Ì¯By‰\WÌ\Ãb†x,DãHüqÎîÂç¨ûÉt!@‚¼Ïáüý'\îZ½æÈÄKÔÿJÀ´€¥ÃÖéÅÖÔî¸ÀDxÍJ:å d¤cU Áè½§ô0Xw%‰Z¬Í8`Jà}Môv&Æ®÷ k–ïh\|ª:IˆnŠÅ,:N4ó…jJN´Ÿ-¸Ñˆ˜ư¸îÜÔ&VÝo&ÜEÚÄC¥ ªÎÈ{…ím,ØBFÍ…‚bhf_÷ÂÊ’¥ü²&tꤔIÆæP`“â.–×"¤Éë"éŠt’ƒ<5K°ÍÖÏB¤ pÔ·N´^Ð}EÚÏê–ÝB`¬Ì£ 'h¡ Qlô/@ܬDå VSfyl¬Ý‚NoKÕ (ÔŠÇ©Aü+Âæc'Ìï0HÚè ¾Š,Üå"M" ÌÉ‚hc#¬D—‘Zb$UK+!n¤íl«§ª±1þ)iVƒiÞ–)$ªÎçbªB­ƒyÅJV‚kwû('€Š¦rÖAúÖ  ‚ý+ ¬Âç cøp²Zgd®"`-£ÔˆÐ_+¦ýŒÇïºÒÍÊK…x>æ±g‚Ò¸X)â¦ï¸{ &öCÜ"0$€±k#'©ô¦"‹%vÙаÇ24}åKg®Ùcî ß(¨!ÌxÐÂ<Ý áåÜR‡ ÏksH!0ólX)ç1ij¿¨"]e-2³"„O3H|…åO6ŒÇ*ÖÓhÙÎ4…†“(Ùp´É­œ%hNÚ\q|™f¦†¼¡BhlfAëžl…,ø,.g u «Y }+‡€øêxïãIãuAª†O«#ÔÝs"•*GŽB¯Šœ!†n‰mþêÔõ4zÜ®«6i§)ËDd乆µ9ÂZ'e÷±ãMÙ À¡ôÆ0 LˆñtBÏŒöÎE?ðþ«¨²Ì. Ú°FnëÎø¢.¹k|(oÒùÓMÐ&Tʤ"‰p]3Æ bUÌ¢gÂO4²:_q“Rp±Eìr›ÓâƒpÖFÔÖ-FÉ„F2@üUF"ëT; CÛH>T‚Dì¢u¯+«–Òï7ü¦§µ7BCÄ0šSÕ$ôD‡|›‚<fpi×S#ZýäNwÂ@=O:ßrÑEíTÆÅ­÷µãNˆÕË—PLð’EM8®M2ìgr±HÝm¹!GÒçÁò©Ìá%Ô‘RÉ´–-=RŒ†'Ñ/S#L޲w*PO'B$–»j+[bʯ *ùIs iuà-Ê>tá(-Ú³”³#\-ÚTTT°Žan·]TܳŒîäø—Š"þ3ßR§€ˆÂÝLìÉ(Ôp60½S8¸lÕ‡—hS+Ò¶!ˤ¦Ð`Ä®L”Òì$±”<ÎæJ¡;…](ÇTÂè>Oy–€*”†ŸL3=Rãq`fr¬²²VÒq¶ñw1]w %÷8dxà¦qÓʺòÓãtÂî‰TLÀÏ+`&s²4#DŠÉâˆÕ<‚ŒzΈîKºààâ<Îë`¯60î¨67ÈœûZ‘Õ ÖÄ/€3 îÙïà«°C!Á÷SΔv7œ–µVÛÓõ/P§3ZÜÓzà+ËõNÕ&ün¤JJòŒ¼ÝgÚô2œô7Ãr¾ç¢  šÓ¹ˆªÍM ï¢$&kè:F¶vÀ †Ö‹{S1U'ñ,ê7piì7â4fì¾â£<æd«Q #CZNäðµí<7‚Üèpåƒ ÑÒèÏ;¶8”tÜÚ*C.t¥ ÈD¦©U.Õ+ tÑ(ÊCU1S! w3GÔó!F؇kã}e,¿†LêW/‘ÒZ¥·“O%@¢3&JÂ7ŽQ+s_Â1vL"MøóÕ†7ˆ­ƒÀ±ª©K5ê£EZØ îí(Ö”.ôx‘ªùõi}çµ>¸lH‡Ð"j#@±æ7‚Ö-Œ¾™#Ñ;`,¦f-ÔJÆØRœ(Y/xOUNírñ˜FÏ–k]L,‹ŒxC|ÈX«“ò3k«[y½H²™2‚\h+v@¡!òO˜Ø0g¡Œ²@¢ 6pšÎ#´» wžò‘„Åñjy4¯5‰ `:¶rÇüÉâ‘%::«bN…Ð&FÏ®RÞ¤f3jsSâј»ŒÌÚGSZV±1åÒ`b½=Ê -–hµ!¥4„µ ôÿnCVòŠi“OƒE‡+—jmvb­A/s_W|Kìz6oB‰e¦…\—„ƒˆSiy{LõEɦ5Âì%A ‹϶°"[O¨ "fëè—AÌGP äaÎ Ú: 1ÔœïÍ]jhbܯƒv¶‹9†óÈêW˜Ã ñ38n‹²¢§®÷;'}+›*—ʱ¹»F¢HÎ$)0Õ¥/— ——$¬ë8ieö—‡ƒf/˜igš=ú¥ G‡%Iú.$§}xçæ¹y¾ÅŠê²;\•ÆvÔËyU+—‹´Û³Nìpyuu!…y·Eü`pÒÛ} {àÙu|É/J$ êg¼âFÜ;¤À ð‰ü¨o§¾$hŒ‚ x´)z¼ê]l<'¯‚ß»©ªcV±}X—zgŠYqýx•³7¿Hô}ŠÜ_ÇT¤: Ðp.¶OíË…ˆF‚˰ ÄmÐû¦O_‰H¯ „)¥!—ؽuË,aÍX<ÅÂ¥×4µòÄeöù‰Ï5O¿[`tœÉ”»•›ÊuqdÐÐÞw$‰56w` ¯áó§f'p&þ±ü‰Äù"Ö6&ð»ÈËȉºœ\ïÎËæv»nÓDxcxÅÛ^¡¶|ç2t+±BRXØ+’Àzšb†¦#]«­¯G²ÒlE¾™+¶í ˆêzFÖ_–ãOZêíw*Být¥¤f•qº<©Ë#´öˆT‘Êzòô6`!C¥€Ëtg|k±Â2L¿+†ÍŸ@¾ÝÉy+ Mý1ð'BR;©ÃcÇÒX'U|°&kxÍ“—þ5mðµyÂ+ÝZÛÆcß $\ŒjšZЍo… ‡7ð»k5CÝLîña•Ë9pPÖ1hN·œx?y£¢…ÕÛ ‡ãx¹{;.Ý‘püÙÀ—vÕ)Št3;Ñ.x-9«S”±á’öþÅüi>+dw¶y•YuÊTÏÒJòêÁöØŽìž~DJIç‹‘rÐ`~zp±p9u€1²ÇnnÚ,:ȳ‘M߇cÍoBˆ&m9áøUäÐÈ7ÕSÖ$±ãÅÎíp%yê½´Hb‚gД¤ý–+ŒHWÓ8ø–\f§çðú8 B'Fb.„{›uìw "·õkú}œùÔ¬Ó«|]§e8ÒÒÓÙ¹=¦ù rU^³ª­½0YÃç<~m¢™¢FãLAðBÑß<¥\…ƒe&õ‹º ^Ò9è-°ææ(ý‘eq~t!µ²L Ñã¿9S¿äq.É*Išz*ënI#±}¼8§Øwà}Xb‰y£o´,»ºôB– Øÿƒ?¡HTü‡C!€8”LˆEàÏødf3}Çá€)Ný‡?"r !ý C$ñP ²3.™FfRy¬*TøŸèXœž>û¡D¡“*‡™C%“H4ºU«D#2YdÊoÓà•È´b™Vâ´¹óàmA¢‘XÍIÿq™Ôj2©”–qcˆX n½t¤ÅoQYdNðþ•rªÌ Ïf¿W_öøÕ†+6¿Fd2,&n¯‡ääÔëMó­‰ã2Àô~¼ÿ•d¬¯êµ¢¹}ÁÙ4˜,— ÚìßpÊ[k™E–º8e®Õ>âñ2ÍkäÝÝÂ(º@ {kâR]‚/‚–J¨‘ùW“Øâ½ÿM䟋†‚$©8-hcÈ’©JŠ•;o{D‚<‡¬"Bo«ð{¼Œ©ü¥è#øÈ&O ë ISx†QB\ôq•:H* ¾*hS«3 «þó¢Or±HD`%@ª‰Ž° ª\–EÒ¶.ÛŠÀAmj—* ‹Ì’Ÿ­ºD™D¨C·)¨©:–ø!ˤÂ(¨œF~¥‰t~ßÈhCÄ’©j*J•EJB.“½H#p¥Çµ Mô½.*)“º-l< ‰cîüKHT3(8®:$—3S‹!45Sº¬•(´“·CRIdfŽ$¯"'(4uàô q‹H“Êrj“¼Lň×g옃UŽì¡U£õ( g$PÚa6Rè„È.Ò" ![ Èz\tà–M*š~&Mƒt‚%ÈËl6­æè3À ´„Q¨«¶‰£¯D,”ÌLBEp4Ö8sÚìtClÃPÚÏôë>¯PÊ,Œ}¸©%yZŠõrÌÕ*² C‹«Z>™V¨•N~ej,4ÈË;¤ë¥ñ â—4ÊÖÅô ˸K¹ýyCH5"îét” ‰¼•¼;†_ :Nëx]ÖŠÊÝ0„$èš]°%Ö: SjF‰.wÛs€Kµm$´’3a³“¼2ì¬{ “»y ñ:§Â\¢àZüÒ€”V“¼‘†å"—&šïHqún$pÌ?ÅùŒ‹€æv¥$åGÒ=™¶Âî‰RPQd±¥žE´ûŸb~Ç´¿Ã±ˆ#5!P„‚(€å!³IXªô™/…ô^Iˆõ2P_QµX‚–†\{…î-]5øZ *Î]ÃrJ≅䓦æüÑ#GÈ쯼DÜ""2 •ú‚$”ƒ¨%Å-÷rÃ#+Œ­Ê ºv,i©˜9¨¥¦bÛáSNñyC¤„Ld‰þ‹oùº=Â8i¤DåÑŽÓĆþ3Lê·¶D“†‘–IiXüoëimä,¤¡A GRÁ¾GÅ-s:4kŠ¢×M3'¨x’Á·8I’‰ÏT}¶R9’ $R\Ö‘” âŒ×#åÐÅ‘&TÈúvš‡+Òé ÁÅ(­œ>p…—@ŽI̼=äî›ûŠ6Áb+Wü} Ps²^'ÐO¯,¥5d”(¼zèÈR3ÊÒ$¨…0­E"®jɵЯ¸‰6E‘!•ꪎ‹m¢ÄàÔQAv ±ãù킃cÑA•«*Gáb3Rð®´,ü\¨¤³9€"—èÜ­! ºZÉÂÆeb)mÙ(B–îe)i@Ô%:ÞˆzÞ"K<}·6€|GÚ’%HDzÄÂèj %‘V}ÒfîhÕ…$Ry9')”u•1òL)\‘-0 jó2wô„$£·:Èüæ6¦ñ!Jh¡’Àùµ ×» @DªB¥‡pîÊ÷|B™I¹œÀèøe’ù©Ëº³ÕE’Ágšw-wL†Õ°xŸq¾¼„C9†o4Mä‹a×b5·]•‘‚¸¦ñ3½f‚ÒªÒ(<”!GÅŠ?¢<ÌFN­Ñ 󈽀 ßž%ÒšÀm¢Dµ–âE/—ÅÙ9Y9\€ "„äù)Þâx˜NÑ­G ºÎ‘ú híûȬíÕ˜‘òONì¸ý«Èe:bqR†"b4rwš›Y’‚€óñ0 S¡`¦#¯4h¬»ë qtw1n!º‡oŽýÖ~Q²²7Þ^% ƒ@ ”䬗1š,êU´šóuY^ ­—XñV¼V>Ib’Îä–”O+ŒH$ä.ÎÆžI*8­û"ç2Ë!š%Æ.ŸNæ1·òYwN„ª»UÆÒ]³ÅçÖt£Ø ×Õå›™”Yž‡%wÜ©}Q »"·é“'[S å.¬ÔT‚¼ò—è¾PÒyÜÖ’ 9,ƒB.–ˆ¶çÒt}<4Í ÚÊÿ(ºàÇèqÝk£ë[›kKù䶉‚ocµ(³Ô„3. 2øfZ‘;µ<££ô¡›Õ¼ÛµÜ﫜;Ô÷ËgÝ.Qw±lÒ}UãÉPµm•‡’+´Âêú7ôf8/LC©~]šÉ©Cë–¾9Uò¥Ñ»æ@’Ú…ßV}÷…:“ Sà<ù%f6§ã"¨îu¦6æÃR®û5Ä]ᯯdy†¹l¢Ø PÞ:ݯ‹²‘V¢‡[€B26;QÊ5N%›šG÷qâGA/2³5·Xu“4°wRšWqÃྡྷ梠9>¥7Y™¦™=””?T”ä)mΕ,üѼäºxÖcLö•²(Ä º€cêc]A˜ç«©á”×D2”ýwPsxOç[Hüß $ÆÊÿDêÌç"FðÞ|6!+Êìh­wKá|#@nÖSè~Œô’'°‡SØ¡¹ä|»a##ꯨ¡IS6Kµ æ³w6h@woÒfi&;QöuWv'q<œ¬~;ÓT·#5>(¼ 2{CÍYY#K 㸠; Ô9ê¯ [ržÊf°¸Ñ°Ø~¿›œ²>ª‚&[´/3là‰³ ¢ù [™’SQ‘1.%p‰5 ¥ÂSA0ß r¤Aΰ"`œŠŸˆpâ¹ê`¤ñËгÿ)Âa‰,°šiŸÐ#úé¨ùp(µÀr8X'Büáª>ðتÄѹ¨øÌ+ß#s¥Â)³‹¥ñ¹«%¥ë4ƒ%ÁX*yM» Á3 ¬sþˆqv¶Úˆ2Jòˆàâ§Pï#Ë€3¹Ó^š(ä1ÌIˆk÷¦}-²Î%8ŽÚ èiþ&‚_—SDjöžs.q/òhʲ¨C"¨À® Æ™ÒF2ó’Rµ’óƒ<9º+%›€3в‰9©,# ÷ÀB ¡ÂY¡J÷ˆÌj¼C˜²y^²IZ8Ò'!|F[£+l,+RT1)¾Â3qÇ&ŒKÃôÒ\4¼¸zЇÁ ’vE"Ãz©®s5šñ¤¿kÕ ß–‹r¤ÒÛ¨á7@Â, 1GÃÁ¨Þº ë"‚‰•i,«À “Z“³Ç¨`‚z<*] |—°!KÈÃÔQ¹ Ú­ú½¶J¯+ZÜÇ$W‰÷;)l&óå¥daÄð~,bÓ‘BO-ë0Šô™¤ã ¨¹Y ¨À8,O¨”?Äú(7Y¯ #:òë=x¢IÇ´àƒâÁÑ¥¿jBg˜s‘´|k´z$À¦óí34µ¤áY3ؼJ‘äÇi ¬Ú0 ó;ÊÔ>Sk2HÞ ‘5Ì9<ÌÈÛL>JêüeÉ Çù0J ° 6²L7ÆpôCRm8`}¯8ƒ9xƒ¤Û›ØÃ[È·c‡éfAG¥y;IÃWËc‚Šºœéh¢I;"ãÛÄR@ª[‘ëç¥dX1q&<<6´8Ü‘[u*ymú½·bÃ<T¥ÄË%d¤G¡I,q„©Âø±¸}¾¨ž Ï“7y|+ÿ<ª ÂðŸ*ôö3ëhû%3Iy¬.t3‡Ô?D‚ѵ±ÝOT§¡V0«OKÄØ#‰^Ã"ìÚ¨ùr¼Š-?$¦ðÓP4$á|7H6D“¤àº <Éä°.ÔÞ«\s½D ¹•±‡àíºSÞ„ôS 4 „R>œb߸ðÖ¨€Á'"Ë:³ôÆhÓ®„6A‘PœðÃC@³øAEÌá®ÃÌT¹ì‡£-À8‚Js8xÑÈ,¸ í¿<*3l·‰lSKR9p a§»lÅjN2“T8¬sæN+4;`˜À¢L’ÌeŒÃ yÝ£¹ý˜òÏÔÆEê÷‰d¡{»>»(å%Í+É%T«)KRJàÅ*Ÿ yCšÇ'4@¡+FNªëÈQ¢¯˜Š¼™D™Òr@[VPû3£ N˜}KB†¯Z¢ÁPôbML3I¢OFSæ–Â1×’ªHî̄ϳâ(C#CI×›œeœbÚ¤zfÉE0¦¾2ô¦3izÖêÌxèQRVD«Ï×uJ­ÛïüL€Y’?¹AÔE<‘-²š‡!*âOÃK¡qÙ“ºÕJûÿ³3¢"ImRñuã¾TßWJõGrÔ°#mˆÌµàÏÒƒ83ü¸ۗQÉDûD|Ô‰â¸ýZÌñrŽÛw±jí¾”_›ä§ñ E Š*&U<êLhÛS«ú>è}6\L:£Ë©äòÓÔ‹ÅJÚ$QСM¯Ë4ɪ+Ó’ðº4!~±c¿¥ú½½$‚’SÚ EDšBl–Ñ[9÷RR«'Òì1ÇÖ-€$=ˆØÄy6ÀÁKr–´È‰”•“±àE£â[ŸÄtTÓuBŸCwˆbr\.S²³º€«†Û±‘?ð‰Ð"×®ªµ·{y›> CI’ê´u°³E!(81È-˜¥5ì·*0¶Ø’€v¸²ƒ$IBÜ Ì0",¡É ˆ|ûÔ˳L ÀÍ?:çÍ-‰‰9E»Ë:¤áv’݉‘Eæeõ[™^㘠 ’¶Â½³½¹ól(‚ì]¹ôL+û;Ëàõá \Ë"³ÊXßbRÒ‹ó$æÄ½X0FY÷á²I÷& µkîËÔµ´<ÒáæÀŽÿ»ÚCí©…ÆÖÈÄЉSýˆZ­êáð5uâ¾1Ã]Jf†LÑl´ä^¼‰%7cfmød ÃÖ¢a¼þdÇî[þ2–Ç€oð½ÏÓ’+Úç¦æA;YŽu^[r×ÁjŠ`¦ ÆJ؇@h1"VB:˜`Òí?žn«<¤ÙéË%öÒªŽ$¡¢Õà@ˆÄMêC4UØÜÌ¥ÃFÕ,Ò8¢Ð[SMŽÔí]4ÂW :Sqùµ<~`¥\6 –d×ò{Ôà\ØaL­sœ5®Ãäx[eĪMAkž@yZ¥é+Z¿ˆ8N>ÒU‘ä0Æòû¦+·%IdåXŒÝž¸ŸÈÕ”C%/g›½\³FgÝ£ ¦Nr¥›U.Ùþ]-êy´µ¨v±Ö’›@ç=ˆùID\3w>‰yíØ¿ç±¿·¥ !ÜI4´{âB`ÏL±‡ö$j†{ Ê/×P|ºíQÍù÷t~×j”톛¨µƒÓ&æ²ú/†öNW8{9˜vV®{Ò)õ7Ãû)u7~ÔwŒÌÊW´¿«üp»åó¢8û¢n[ŠæNÙVþ¡pZ‰ÐL'ÌÎkµs¸Û!9:g†zT<[ƒé¥`äpÓÐ;>‡z½Õ¬Ê°'¢9ðpê×d.*~߯¥›mèÒñ°<£¶‡ÉEŒjC#º"Op{~Y,ÎWžZF˜›öšN;é_*ˆ ~Á@p$ C_pð,F?âÐØÃú)GbÉR"‚¿dÈH9’åÐ÷Ü–G‹?â’XÄÖuŠ7§ÏŠRS Ée3XÌ6KMc I,Ö€øŠQ*Õz$b‰Óçsh=b7c²Mj°¸¥~ɱÒ_ÖÀ>O5¢]!vkf^‹Ò©±hž±}aiÑÚ.OB„Æ$²P6F?!±Éò j݆0®@±Ð\¾$…}IÁ:}$Ò-—˜@㘴¦ÉŒ@öP}& 0¼2ö¨>}ú âIä´ý¤6VØ?å3 <ŽO)¾?ß=z$ÃN œßmð,†Fa8†Ë€ü½&^1¤’ÀïOê}GS¸qãºèoN¶„õß.Û†!¬È˜)ï š¤ì @¦)pÆjŠ,BɃ^ƒ¾,ÚËžÐúˆâg¤H‘¢j³€(G 'PÛFÃ;ÉJF»+š,¢0Œ+.º¶(Iã ÂÀC.“©é‚°Œ:¯Ð¢9;È3@ ÝòI+&¨`‘À‘²jç¡òRX‚¤òž·+íìT¤!ªúŸC(ªvæÅK#ì<ÑÁþ¢*ròЃ¤g½ 4¡ª2@Ή҉1h/(îô¬æ¦±2ÿ$jÕ$QN’@ó$¬ZD€3  <©sè(ŽŠ"‘"(ÃŒ‚©ôÛòKhR”¤´µ(…½¨ž$©…&° š>,”k7Çðš ·%(" 6Joþ;(zjóCç²0\Ì™ùHÌÉŠê»¶U¹.¢)MÇsMJþÐ -²‹4‰K/gÑNÏ [íÞÕó›ø©ç® Þ¬H=—%);…°L ƒ ïrîžcìó•R€hÃý'#´àkã”\]&5“!ã(®Ì§ë9 ghÌÒ7˜Ý½E@”¬¦æá©»~³ ü§Ç¶ûeGJb1¡Ÿ÷Qú¬YŒ¤bé­7µü§±Ÿ™Ó˜±í\ùfWCÌà2:÷¹rúwZAµt·Êþ¯¹¬j}“RHLÜ@•Áü“¼Ê›—Ey~*);|¬Œ$m%‹;ä`I&q¬¾lU[ÕLÀB8¦ˆ²N|ÍÑnm†Ÿž€=EÑÛ/e;,i¬]†ÉuÔsEFÐaùÑg(f˜rQÃÏóq(¶on×}# ">B ¬2ïgÒ«ÂV.„‡ñK“°É<üêN;mŒ‚·-ó;®¢ép@ø~W „òÕ/À —"ÜÓÎiX}õ×'7º© `–@ÑúÛúúVh ª÷¾²œñPÄdæÂôT\S"¦0…¤?׳«pó4§Šíú¤z`ÝCTúBß0V­u¨È˜ìœl6ê-ñ·ÈYÎjÁøJõQ³{f Fï’Â<2Q¢@F‹«/okG”òƒ—|+EQ}׳‚(¡¹º.|¸7·ÔQ³xðÙt?vÃb›ÚeOðÿB',›Nóã`ëî ÇR–M]óú†‘ 5ìï¥këR-Ö"ÁŽ$Dc–MOI‘ŒÌ±>ƒäDeAy*óÅlZ×ʈ1ú”SEÄ”´öe ‰kJ]yªh|g!þj/˜SÞâü¦õn?6N^ÈëQ1Mö²Ò‚ÜÁ¸0®AWª]‘’йiƒ"Ô@Ì®zB‰2!+à$8úØh2òÐ϶ɈéS4S¥BáF•Èü^ÅLšµÅ“UBM*ë½§ª2@Ïô‰ æXÈ­ÄýbÉŠ$ôí ,­#ZLDƒgO¥zñ¢Ä6™r:Q:‘ø”Ò±m$&B:Xå¼±<Ép‡¬•Þo^zù3QÙ· ¸Üªk$= <@Ù*ÑÞKœ%ʹ‰)þFÉ* ÎãFœšJºg‹ûpޝÂÐ fYÖ˜QEwÊÕšßâCÍ+È­TAÏŠô̶Õè‡Ò„M¨æš") WÛPóå!­ñöË <;”Å”ÕG,FE$!ºÃf´¬¬£²XètÈÝqöHË“ª­'í—É)E]`A5DELŒ+ÛÁ©mÅ>tË•:àh¥üƒ¥Y…ùDp üs.í1PHìOVè±ÑûÏ}Ž!'šsUózè™…eŒ6ß6±^)ù Ší!±*cšø\³nÎ+Ôù“0¥Ñc½@ ZJÑpê‹®¾Œ ¤Êp±IƒÀiÊdë¢"j¸â»¶!¤Œ‘Ò“~jîËÁCÈ€«ÁÊRWQhz®g¬CÀ†]‡Ö+.,udó$ÂsÌŒ¥¬¨¢Êyõ]un6Ê j°t°6ƒ#‘ßhHmÎmjñÆ>AqTüH´‚茈eƒ Ð 8ŽÊB‰M8ÂS0¥Ï* êÈCÆ9ÀçR!ù0î«E®0_CHÄo‡ˆJ0¯Ô bwi­É $kŒó=–›;õ£&`öªýõ‹¤”|Cf8Vuò[u—r÷±Çg‰'V!Ù5§‡]A i ¢%3"@'ÅoC³KTäïêi¢Î3¾§×¤nb÷ëaÞ¤Þ‹tŒ_‚¶ô~†s‘F-;ºGªÉC`|rp,š*@@€6`OØ  ÿ„aO¸`þˆA¢@V-Å€q¸³ò=H_28”( ‚?cJW!€ãˆœ-7œEæoùLæ%,ŒNŸñô‚a”Ìgoùd1÷1–Mb‘XĦœÑ%5*$J•}Xf5zuc)–Q%•yD¦Üý¨Hjó$bN˜ÌeЈ•8‰Hß l$b‰W°¾­‘Y6Gu„NcQº¾ByÆÁ¨‘h• -D?/PifJq4ƒÂ*ñ f#¤–H¤wðIè4䥼Žû­¶æ±1s–‡+óí \Ó0£q±ðZ‡­­8"É3>ˆ)Ìä‘[N€iR>¨ƒÈ‰\§óiNÚSJ}o½mò ã"ÏàР´Š´0*––D¬K€à®Ècß>D󵶢߈òXÁUï]“=*`C"Ö-kD€J3Ü|©²Éf&§‚,§b¥ò«Ý)Å€ ÇLÅ®ú΂_9ÝC`ä|öƒ/Ëúš†`§Û2‰ÊÑ\vî(Zhð²P.)…ÇH„hÙjuŽø+­/,1ôñ$ØÒ[ ™¢Y¥€¤ÊvÚ‡Ûˆe;WåÈb¥hPñs߀ Ú©5â¼§EF8[¸Ä½yµ?Â&,*ˆkìNh‰6—ê LÙe»7úä‡S¨´K Á‡ä¡ÛÀ Šá²Í¥’´Q8Z—ŠU'ìJÐæ˜ª*R¢]É™J¤šà "Ȇ10è-­úûôÕ*èw:ãR>*“pÊZ̤ ›ûå‡l÷¯pÝö––1-£öÕýdWÞgÊÁV‰ŸðÂ|û’ I•hü2È Ð2†„á\¢š$/#7äºyH*R;jɺæÆÇH©D6ŠˆÁ>tàQ 2|핇@Œ_;|‚dݤ®ò&wÛy)z 8а0µ‡ªÉw/å«¿7È ÑPX¥³G=!¤,Ï81þÀK 0‡é™&ÃXY2Ä,+ì>ò w̳4u­©f°òI–pε™ ؾãÊd &­I>,·h°™Äf"®D‘©fm´DDŒ‹ ™ž/*t¤¨Ò æ‡éëZEÄ9,‚Ø[ª¬šìRÕÄN](º,ª7¬®ˆ#“;%J&ÀvƒÔ;Ó\.µ£…AÓ±÷?Ì…JØ ?À1(•×rX´“â3õ†š#(C¤Üw.Š .R÷`NRP“áè²R¢5FÈ!šf²?‰4ž$-x„,¹ ëyé|©¦sÂ…^qD¥á®rUàëÿ!Gu¶Aôh]Ù•GT‘¡rþ×ç;þ"rµ+¥ìJ\³85©Bµ>át+Yp¸¡õ@‰Óä Nà g«WZŸ o#î=6ó—KÀ&²¶éôaímt½`ÎਦDo›K4àÉaæÙ€m‹Ñ$·0 UŒB^Ð]ûIÒ<á¦,!Män™ÑõHúGâœt`5(º>IËyª.bOÑýNI Øa€±3úWGäh`ªz½Zbr%pÔÖs¥Bˆ‡ I—°m¢qö¬Ì%šó0›²Ê9@€)ߢ‰ÕñÃdõ¤peÄ‘TKjL -3%ˆ»HJ¨!Ƨ"TêɧPdy2ÀÉdÔI¡ZKÔþ3H.{ÉŒòE9êÊp/èìŽbªñã@Š}NÑZfP ð¡šc*§zY»sµ×׺’ç|üwö•ÙÖ0Eì»÷]Ì¢ÝFÇä\jŽÙÂ0…o f¶’>…äJNM ŒA@Êú ,Ræ‰Ôª¶×¸Ø}#s6‡ OrÞ¨š= µÆNö<‡°+CIWé+®è÷"a[©',Ò^Vßz±LïodíÃN|Qie” &¥_’j>qI1·¦%‘Šõ\çA §à_±Ëð,ðüw--…£‚s,0kž—‚W_—´Òåü™’‡K"bÒæ¥,7¨ŒQ ,'°˜èÚ©bP uve|©\Ð×§Z‹¥’|“ø¸§oƒ@"ÏØäŠØ7„‰ÂC'Žfê[,ñ¸ʼÁitl #ŸÐU(3GÙ#mlú•4[+KQÆ–‘(ßÄ礭.I&[)(ò‰dö^ƇVÙÃÛ£àTÕÖãê©H1ò²YòNÒÛl‘(–6 9s6ǪNr­znêÖ\k•@”-®2§—é>!Yßšž)7Òcþ* h¶ N—ê¿!-ümÁÈÜs•*À•u¤Ž$¥B‚3Àã£z_è‘W8ÈÂU,¬« ÒÚ N¥ôBŠ#ÙÌämŽGæ3¨!cs÷U_¨×›œ3j•â¨ñI;>Ë”«Ã€Óóéa"VàäÍs˜¥ ÌZ$œNΪΖ“—K—M]Ñö4={EæB+6ë´çÚ å”þŒ>müU‰ÄæÇa¤-2É98º=HƒE!ùÅYÄ8&6Sv»ã>PŹºÉuP÷©UÒ“¨ï|$›ØÄ5Ìuû" VäÀõ>ãÙ*'qO4—,†÷[ø*ÈøËnÉ %ôœ²šì¥Á-8Üé€É5 §jTRçk)Ïemཱ#åÈ•üéx¬À&=ÐÆ Ÿˆqá»s‡NK:ÜDʈS¾tüoé]Á z¯£óïg\ªüIßb&ò©iY½säÒÃ,²òiÕ,¦Ë…;„\¡À—æ*Mý"<+F&ì¾âj&µüZHfã6ëÏŠ|¯"BF=oHDé&#mDçŘ=Îü)Åì(F(mhÅ‘'³í¶þö}È·É€PÉ¢*FÞ;†¨ˆŠ\'ü£Å¾ý­ú …Òí mèè ËŠô¦£Èæ"ÄAðDã£Ä× ‹#\Æn­†¢tB¯î&eÎX*ÀîäàXj–‰,{LÌáPbs,²FøTÈÛZLÆ8æáôÖ«v$k0Í¢R€%+‚E(~×nhÆ®Ð8ø üuª’…íJüI†ä¥¢÷A!‹ü4+üS¨®Qó‡RäâLýâî{ÈP ÐN#þ#Èî{à.ü‹Œ±Šºeb­IªÏQX0…d*ªPK (œÉF*œðîb«‘IQD¦PÌì™ï0ØÊPHËÌüÉ4!‹QÎUå’Gi)ä—lêÏÆ6bþˈâ„%+~P†ì×'rš. G‘B¾âj¢B,YÂZP^þðœ{L‡ ÖoBj$ÉoÐÇÇÃ"&ÎbÌlµ ŽÐ”-|ß-Ú¤„WŒòsb#-k楋†±!É$FÎÖ"1 „\0½G|4#ÖºJ¬M)FpŒ?aö A²"ÎæTPºÒ¦\)J=«ë" K"rNPs'ÍPͧïÍ-QºÔí€d2¨El^è°Í-¤æÊª*…’dŽü"RFÂçÔ!LüåŒÐ!¼TF’ªÇc bÂUçœo†¨%ƒRË/1oL0„šè1@Æ­²d¥#²øI2þ¿EHGn,FÑ,ÏѤd~ Îž¨p;Š)US@OôëÄìb‘ ˜Nq qº%ŒžJ‘h/ïÈz®g¤\î«ß"*†“…_$à¢Iƒ'’6E ˜"œ0MÖënzYPøZNÏ/2‘@ÔéHÑhœ¾Oä Î.­h¸Òå$PС ©Ëõ a pàÅN!'³®Ãj”­~€ääçŠÐÕí›@Ž]1ß§ÌJLé«TQqð»G‚sóI-J ÈqæŠì[é^‘%Ò^ÒKDš+~‡ ŽL°“1–’“Ђ¢0€‹#=íµ#ôǦ¾ŽèîöŠ÷‡ªkã7.´ýkþp“îÛ"Ê"qH)¢RZEìǨ>ôÎ8=°ì«Âöpèë5 ´i-Õ$p¦¥A C#Ö‡J‡¨ÐÁ)&©0†/íî J HJ» ¦q™§ò¯¥¤b’ÒœÏ Rá$íŽ[ïüˆÒê÷ò’ÎmRTM ­j¨\S˜¡¢ É m!þÕm²…µ?Ro³Ž7.uT;bÞ’q"#ÚÏŽ*IÞEÓäòLZë…ÁM/Ä÷Ò¾É`š(a-ì¿FßF¦ÓÈ}ó}?ªœ6ˆf]$š6„š’á èåÅ_Glþ»D+?QqÊõqB#¸¦(¼¥dpôRöR"7…\V«V¦Ðe@ªJä  {2T®õö&fhÐáÃuRÄÌid`¿d¨@’d•¯TšµúW&+qR–I2aszY,±LB=hÏ$ݪ#H…0¯íZ ‡ÊÇ¢LÚ"MQí1cpl#Ñ-Ä ½ÄÇ —-.5Â*¶`îÜ’×.oàD©¼c‚®Ú$ì½Dà’·C)‚ZKÕCíŠ×±µ&‘_ò×Ô×N7VâfÏk<(ú!KQƒŒÎî`²+Õk)<A7B%0¼*H¸„äæïOÄ"A¯q¬ž=õ‰óú’8Ín8½H\mo|TÓ&ÅjjTbÌB~p"óÊWE'ŽYwCH*“+Õ$pXFÒNF8÷D¤ÿ %^l½ñ‘clº|¢¤b[Âq$²Î9Ñ@ÅÖÚ­ 9.’#RGŽáí…#Š”EЄåÓZ*81W_ôªÒuaíŒO‚MNå­kpŽö¦Ëe¥÷Hëà %t§Êù©Tˆî¼ê4V¤ @ƒÈkèì•-h‚QR’‚ˆ‡­;*ƾn7T ’¤ØÓÇ9`@RÙsþØwHÂrÏÓ¢ü¡øå”Pbµ pÝ–H²4j¦$å3  Ý-‰*¢S|7«ü{2,åctIœs1L´-Y)26ôclÈc¶Ú˜©`u5¶Ä)Jëùgdm|c³ MËzòRDâMF‚j†C‚óH B }ê¬ä¤ðÎø­mN°7ŸTkŠÂq'ÎJ˜øPÆ]-ðX"¤wʸEd ý§œpdNJ,sçJÕ3bO˜8ëb¥H®PŠÿë§m7ä•J¤ÂB7"®YIpäýŒ÷”‰;K’Ós‹ñ#2Fó$JJúàʬÈŃ,lŠóæ´!Vá.xN‡æ¥P!$·¶iwdçI«>mÛs<Õ0CM8…?¸4ú!óDf™¬VÄšDâœAÂ0¶¶Óêˆb´Þ÷!÷ýíëR²! ©|6ô£~!”¡ ¯ áô†j>y &Wuesñ„¢^Ö. …ä;/–,1-œãðû••7t8ØÃ_†êf%6+WíK/ÛB%IõHì~²"•Y®\ Ò›9ât.½WqeÏ3mú8Ò‘Çy*ý¦ñºW©›X(ŽNÐÚå—*Òš󹃟Ø\X+¸ç%”if(äb  ±½/BO,"«ú«,y"h“!±¦Ô#ðxÜŒ«#/ªT'|«±–ãÒÙIE0Np"Xîyˆ£RšozVÉc°à5m0Ä1W¾Ò;,·!ù(¡ì®²{^w¾M"SEÄlü3µŽD—‰/°I²±¦ùXüEIYs’¹úi&8;ùŽbvü"…AsE:•,ï±ÒØ·Mž…Âõ3Kw-³5j„ÙN¶i³^fù¥Ô,’ ¬¤Pbc…6“êCŒ® ­“Ì@ðùS ÷äPzïøŽÒÇo޼kòßk‘DÆ3Ô{W#DÌ’•æðË¥Yr“aö·ãP®ñbþmph?…@]'d‹P¾F'Å !ò^̰Œd’6”ì¦ô8¿ZÀ]6ÇEN¹7à ¸Q¤„£"J/䚺[´åºÍ·¤à£ïz÷'ù¥ã¹§©$笾¼»¹yœ'´TšZ"‰4 –Y|ºoXкÙ1’°ÑÎ$§ïK«†ù9‡ƒêW#rJ UHŽp ©°¥Ÿ¢#ñ¨Zûæ^ºÎ¼w*fíƒ »¼¯Ð#\œ°ÆÞÿ[˜òñ=my[ˆ9Ó†nRFÐNè…Dšu6D÷ˆë~G|±Oãiƒ0­Å«³¤Ì@¦|*é½G×ãàÃDbk÷Bî¤ ¶ÍLßšÕX±äÅ<¾Èîu¬RJòJŠú}¦Œ$(ï»+9cÔVm¢¿Â1»[¿râ'j¥†IÏpƒ°ÓaK.£Ác³•òZݦ©=Õ[ÙD~–À×9ÊòUç ¶#ÏöN. “Ä/ý‡™K÷€YÛÈb;æ©vÓáÛâ&:w½bw‚™CÚîT­usj}éÜ<@ˆV’© @Ûv¦|b†FÛ,'Ý’q¼¬l”$tú,;ÆÄ5!˜\DØÜ$Kýv>@?·¿]()ɼ"Ók£Û’#‚€*aÅ©2G'p¼åëB®Ù@Pór¯Cß—Ãèò~NÉTø–jEqBë½Hº²îaxÐã$¥7¯ÛN6•HD&³M—J”•Srñæ–@ªS±+%)óŠdGˆ—÷Q‘6äWnE”)Ë*M1Ê’Mi[Ì~OÄGg ä'T²®íeµ¢ôçklù¥0Ù»³W*ôM.H°GË"!ï¢8Ò3‹‚g—ñÃëzλWTGW's+ˆávÔÅ"-ìgQ?ÁÑs¼ÎW¿iʲ:j¯y¥ÖÙ8"A¹ø£·ìý*­643º¿ º«Ð½ëb_ž­{oªç…»zu³…LöÉîzµ¼ ­Y=4ú¨NkÕãCyXHjÈ lC›,«˜–!,dÕGó2œ8<6 ä ûÁÀ˜;ü „q+ô†€±—Ìl¿#²^.“BãàiSúY —Aã Ycú/3‡ÂæqP½ÿ&ŸOâóÉ,šg9‹CgQù ÅõM‰Ï¦Ð™ô^'AƒÔá°¹ ’M}ìùœúu‡ÅãoM®^®#àË•¦C3…ÐÀ6;Öùz¢Ë"q0n½ŸV땉%j;>´ÃèÀ*¤ÉªÒ'Q\tnT‹Ä_q9 >oÐerPÙâíW“NªÉŒJÿÕŸòÌVqØI­ø©ž‚C?“m*Rj¹QˆDxÀ ŠY:×®õÉ /kÈEæ2ˆ!ÐLæ2Ÿ<ì€'Pû¤vÏ ÛóvQ™÷,¸Ü4Hè4â&!mC„– ëÂÊÕ0+"ë#­éýÁyü÷·J:Hû€Ú™±ƒ,‚´{~žñbÖ½ëÃ.Œ#1aîŸ@@CV†§Ñ¬.³±ò|ï0Íz*ï0(*ð‹§M›Æê·r¢ëÔ*£é‹:šÂëb:)ÓøŸ#Šå ²L~¡ç´Û=ib} µ ÂDê'$ïrωsF佩zbÐF(4£3?¨j&Â`¼½Ô KB¨›:ÖÏÌZQB´ÓS‹˜4 £ ·`½P€“´ ÏTóãO` j™Ö²\&,„¸·Æ {0<Í#HETÛj´É§ã;¦)óA ʲ‹æ‘ØÏB3ÖÀ ÿ/Д|Æpüïa¥òcôã ”M8˜ÑÒœ2™³¨zê–+ÊZ2þQõ“Q^‡å¾‘D—Bž¨‹ü?‘RiÔt5­}ÅÓiìÃàè]žŒ¸ˆíµ|£²]eMº(»Õ$«ªn?ŠVXœI/‡ª•p$ Vz¯KÓz ާÓH]ÉH‹ºÒHFW*–Qiò¯bÕ!ü¯!ïÚ T½ÈýbÔ€ƒS1S¬D¿¬ÈK'.¤Ø=·² ñ•·bÑLÕƒk§íq î;†‰2Ž6Ot jôî´Ç´HÜ:uòΫÑsÏ'€Ró¢÷ê¨K±º ·è ‰ã©Ž# ¢Ö¤Þ£4“&4ÛX–e)ÞÕ¦Ö|%sAì:sw-¦ËÀŒÝO·"òÇðå?“”¢‹çé2^x@.ù‹/IôÈ|/MÃxÅ[M<ûè®’èèçí6÷ÜÝ>²ñ`©c;h]¡è4‚Òø¡8BY’)ŒÅ›BX¨•Ì*d$EFì F¨à·»Æî€!:yém;H(DI‹¿biÝU‘SêÜÇû}ŠqÍ;hN¯Gã\8Êñ¨üV];`éÝ/>*…WØ„gä–‚6ÌëïyŠ9’d\®ñnC%ù˸ò:dX“/O ÈÐÖ&ZL‰z{Há"õ^í1Sj°´—¨¾Ë›y?bvÀd}•+ø7i Ö)+ ’ÑTË®½áûÕb›$,q6¿°þê匄²5*LQ©ŽÃñ±A‘öÜV#† þ:$?Mz!é\šƒNIœ™MaJ`‚òõ “2`…yÒºåÂÿˆ‰h¤N=öLBVckXÐÆ%æãd¯!NÚÇ:Ì^ŠƒZÊÖ+hƊݱO»÷c`Ù\‡NÎOM¡þ¿êZx£ñ¶ñ÷0ÞÅúqªy±LT)…ǼCt2ÆgY*mÈÊ?;G ?»Ò^/̉­DÎ?Yi p†?§´Ï@R5o‡¦ŠÈ™' QjñÃJjLÕ%Óíב’>ªó B“9Òʬ©Uì„—§HFaäU÷,§{Ý ¬RÅ1XY<…>Œ¡ ç!hÀ`3¿_ßK—ªö¤‰ÑË@Û‰ z¡2.pHd¢¦ƒægV³'Ð[ï].Qˆþo§¨O© ¥ˆ©…›UÊò8}öÝßÅøÞÒ]ü~ÃçñÆ9v \R‹¦%ÛX„frÅ¡}Qi‰€ÂÕâ´+ÀÁ£ï0Nˆú$!ô!$}šÑòxgt9N¸©GA)ÍÃñz~6igie$ÑHûZç´‹Œýˆ=ëœ?~DënÞ’–)þ–UÃKàJ´‘Ö;zèÐôöˆ¸þ>ùß-÷´|:YÞÊÛ¯ýÁ‹‚üºxÄîw¥N/š¢Âƒ;Ëz¼D”=wUù™ˆº8~ýí¹-rÃ)É1i£^nxãd—>dçãz¾•B&W¯/DfMß "Füš˜›¿¶ôÆ ˦88·Œ‰^!â÷;iS Ò412Cp“<«ð’ŠË%3õ–+Ô {š¥Â œ3Ôª‹±û»’ò&³âéˆÄŽ3Ý* –B‹Þ«á–PŠºø¢¿3z2:JÐ,pÝÃ"eSä-¢×qð9S³Â5°ÊÕÁ’÷¼‹tp†ªšAK¢µà®$Ca§|0Â÷A¼@> ©d½á¾b§-š‘ |‡Ûz=º›&Qß»šÿšñ‘ú£ÒM®ãì*­AÒö¢˜Ò=@º¨&KŽ’@½ zf¯ƒµAh) c!¤,[âÅÙ ³ºô   zD>š**¹ˆ>x‘$I—¸•2Jª›s8Ú„™“¹˜³®&°Í‡Ëˆ¸mG KêÛ“–›k•FÓ+±c÷²x=ÒT›á¤iÛº"y I±ªƒLzÑ-EÅ*Í4Ò¢$T-¹‰Ä‰¥ŒHÍ% \ Æ(“â#=yú´]B¢i•Û# }4Š]ÇB­š›ãÚû˜èÚ±+¢¯sˆº,EDfëP§iäIcµ°ÄŠŽŠ[ÉDìr1á.4&ˆˆçšÆˆ„¾äª¨ˆ‹Ô#žÝ”Ùh(ê¢(Hȧ¼=ÑCB§–37º*鳜§6:æC¡:j›ÂÓ|Åš, o¡ÁºB‹X‘©'©³»ƒ•Ç,¶Èô8 ã˦ ¼t ”䲌é÷ xÈ«,4:5Ø®&JL7£¿É¢±ze ãgE±ÿÃ’·qÓ¼<ÉêÜL[-7ÐÚ˜ ½ ìY"dŸCª9¼è˜1‰Û¹rÀóv/ZP¢™Ã8¿âÈC‚ÊI}º™‹$¸Ô–“@•4£NüRG±±MM§D*ÀœË‡ém$DÊCl’‡ñR„«Ù¿)˜4ºë¤§)¬8¹í'º8ˆ·›ÅNЂňÎ("v½Ò«¶ Õ¿` CTÿª £ú\(Y0ÑE0ª¡ºÊJ«¢¢ ÃcôGψ>[žü¾¤AEÅqSM‚\?²¬1T4¶0¶ E•{}4XµŸøžMš¢½ÒÚ˜²dº0H|£ÒQ‹!+Å~§P˜³VÌŽ*ÈŠÏ /1VDj¸ŠkQšÎ#Œ³BSO ¼C³Ù E1VY5$EŽA}‡ãÑ Õj—‰÷ØM>\:OÕ[TÆ{ÁTn$ê*‘ô`Ãë ‰zž³º8ÐËv×(3Ô9b؈΢é) DùíZÌ]©,TIƒ*!Qð¥ýÊoýë0ùq4"g“ìe»D8§if¼£c!Ii+ ªr’ô>T,¿OÞl<¾ºŸž iáÒYUE‡Ú¸ Ïí.³ý(+•Á#ÏÒaa3·%céÃ: ?ð}¶ê@àâz:Š:ßž q µ*9«{;ÑDéYüœ7I Ÿ™h]{®­‰¸ªÕŽIa±(TóZÉ“¾®”)@™¶2Û°ýd;¾Neä ÙŽÐøS܈Ü!]ƨŽ-ñA‚oŒx³ºƒÂ´¡ , ³ín˜2ë!íç¿Î9ëÕVU½98¯X+ô?œ¼ÁJ‘£ئ‰ã‘æÉÛ´Áq<°;Ô*96äTD$Ã8›EP®U¦K¨ÖÍlu¡K.¡ò5ÔÔ:à%@ãÂæV]ÜËô±—8˜½ŽU¯uŽ<¼·Øs•fbcÔŠ+Bø™Æ¨Ÿ¹$¬Aº³º/Ò:YÁWÀº<É ‹ÉP„Û©áß \c«´°Î†®ži>½;€:”]3å'®¼ÐËa¾OC)6”êTMCxö02)ø° ÓÛ•>¢ã-˜è÷*€Ôf«ƒÝ¼ÄƒÚHCÕ¥¦R”Xˆ‡‘Åe4{dšPºޱµ³ Ýg›unfn½T[ƒŸ~c/}Oæì.êú¡ôW¹ˆªïèc;K„è6 ö1ùÊ(}ìp– idͲ¤óP ±Zåô‡Ê¥) zXæ¬ÔÅ”'òêît'™¤Ë–ÝŒ]ŒU?0ý=žAêfK[A†Ü‘cH W™Ä†=ÜêðÜ Ž‹‚ì«Ã¥ Q€4‰TâhÄŠˆ]Ú)ËèzC¿z«Óf=<|!ñ·R”M [KŸ}6/pÎÛÍkk_ÜKLKÀŒk_D{I¹@¥]¤üdP¾s¥Ð}»šÑ¿üáÛh¿¸M:l˹Ò8Ð"Jk_ÎÔl»Þ*›ç+ÜUj=éн˜9·c5ó‰³ÑÔh_\‰ð|JZ«u.6ï¶X6 ¢*`~bÍ^2Ø•~…á_n”ã:À瀂ÝÁ^<¼²äñÛÄ]š j{‘qœ…ˆ±µ¼Ô¶·.’´°³Lp4ÿšfgž6.l§ÓñÃRö¼/3Ý>t%É&µúÁÊŠn椌Žàr…Ëw*º¹Ž38Ô&M“'i#¬–(Ð÷©a‡V~ænX>«åXWgéÛ”úí_2OF~¢Ûµ—¹>ÇÕiæ#ÅG;z‹}ª‡Áÿ—Å6‡8ZÀØ8},Ý ,ÿ5kX@–¾ß(—nÍÕ×{‚âc­~ÊÕ¢Oîæ[ß$H§m”Â-6Dr#2Å>s»á~˜‹MHf°.Z{Æ—ÈëjW–ïöåVÞâ½ÞˆžÖ\´n^9Eš*W †l/RU/Ïvð[pF«á¯ã©Ïòã_b¬,â§ž=V$ wû»qïcꌊöK²fcʰÅÛ[Ú¯N[ÖÏㄾaAžªs52¤ô]yœ1Í YfÆÍgÖxŸŸ¢/YO÷ ®^1ýg·õœ6û}ù‚ó,–w¥É,ÕG äÜÔ ׬§¥unŒ@G®`VèU…±Þ½¸p|îÈÜtFÝõÜ[Rõ£([ 4‹îÓÊ_õÖ“VÿÁƒtÖîM·ž–ÕúEç^Ò 27ŽóÙ«g x=L]ÀÚ¼•^ÐE¡ 3»ž× Äç“•Žg¨£8°$­{;Ì‹\Áâ•ˆŠ¥ùޱÎ/â*Ð*¼ Ê,г£šl¨‰‰ä^Qâ†æ^š¢Û|N‡Ý«=ýÒ=L=Jâƒìˬæ7C[ú÷eôS< ú±* Ë´³Ï–{˜7¼‰Ñ|U ÄÊ!á7ÃsìÖàù²÷;ÝÁÉc‚?`À@ü†B€8„"$ÅbÑxÄ:'‚¢Pé†þ’C£±øTJ ý†?% <&S’?¥ yÄŽI+ŽÃŸsø”àù¢Dq'Õ&:¦Q¦´—Ð¥+‰Ggï¸í-ŸOê@jZ:ô²P¤V(ì-5“A*ð ,ÖЫѪô)lZ_¶€¨Ò¹mjlÖbÙ˜· •ÍnÅ^¯¾B£µú„J-p‹KjÀ%¡+FðÀ=w% ´ÁÚû…Â$˜€^û{…óP¯Ü1 h u„xÒÝÕ~+Á3°È•~¯Ýb0Š4[u²ˆT!ØøGzæÍeº f·5¼Åo»\§»Çì†MzSüt ‰:_r¨z þ&ªªšªíÖÚ@©#šÐ%¨ê䊮b ò" ¼,ª 2:‹4ˆR„٦Ϭë€)jZEK²~öŸïƒæ¦®k²ŠÀhÛâ‹¢L *ЍQ¸ª#ˆ"^é¼*K64£‚Ý9h3@· PJjþ¡RZƤB˜õŸél  Hhò¸Fp b‘,èªVž ò+ŸìÊ6½HçÒ„‰4 [þÐB'üX}¦¨êáLÉ#’©?ðâÕ$‹œ¨•µ) >P¨j£:Â*ËÑHÅ+ÔL²æÁôiþêKÈÁÿ51(”þ—©jctàºå IÌJ¾çÚ,ã/Ì)4áþÐ9³\¾†+ëškPÔ‹ôÐM¨:i-2¢ET¬äܨ“Ò˜•ÖµEd‚9Q‹Ì†41ô‘8“’$¸½jÕÀWGÕR>©Š‚…KŸ—¹ðÈéjîȧô"·«ô’lì‰2ÉJds ?•öàT®íŽŸ¢ÓÊ0$˜£ƒ‰à7õY3è’Ú˜ÛžúºC*dMüÂ}ðE*—Ø‹‚®¯¦­UNyøît÷ü²ƒvy¦”ÓÈO'Ÿ«Ú3ÖÎ(„£10îÆ~£¸"q= Ò¼‡WwçFØM׸¤VQ?$¬MX‰*ý2kß"XDœ)*5áÉjM½ov¶°;åtÇQv¼ñ©.qÀÀ ç ç--”æûÙº©å º¾áüu•ñRG€ I:“nWÜ2­Zd¼þcÒ·È3Br¦võGÛÞ°Ø·=c8Eaó(M(•2Þb\ª17Pa/Dbp·Q_sÍÁè’ÞŠ;åe©ÀÅòC ª·F*°ÿ¶`å€Ý|ª±Ú“"Aœkb…É©šcA› ^(EA³”’ðCA+ˆhÊYäaFuJLx0ʽdö:FÕ\Õ Ys3å1AU°Ô`ésP+zH,…lù\¢9€d9gÄI@¢ #Îwȸ‹Aˆ…"êAd¤…/%¤¬ÏŠ3NŒ¹ÀFtJ”’Î`}D—XÓˆî2H0nš£ä-/)²~CdNírËôÔoàÜÃ[Éy¼ÌCzž*m•r‘ç!’,Æž+cñ¿¢HŠc4UŽŠRBI±ŸS6´~Cåàoˆ"./«"WGU<šhþ7K(ˆ$OÑ !iÑ„ƒI’:ÛH›aY‡þ•Í’èOæ, œ)ÕÒ‰ßÑñ8a ²BÂôÀTHü¤’¸ ¶Gô’òTPR1$ôx_ÎQŒyÚ½Å&b$: O²’ë G£üÝZNÉšýc“°R==>T$¡"¤Ä Mk Œ¯iTdDßbl¡L]·’(ZÊ•k˜ *CšÎãûiRV,( ¯ÜÙ8—„Zn¿•š?2Þ£å1˜ÙÐÈÞË&{ õNZcsG's©rKV±Ä(‹JoA‚; ai_P66‘VWÍÔ™|*ò̹HûS+5E>ŒI·“R… ØŠ:lûLÙë •¡D‡Ñ™k%!t“\¬êõHZøD,ZìšÃHv`¯áOev±£b”×õÅ*Ol¤¶ºÏ m©Ô‡‡äµ€´ âûC+1K§?S QFø~öÃÔ¹BÞe€üFlî û;:”ŠÝöND µ¯xÏ‘Vdת•°ÂºzÆ»¸•'‹P|tÔØàÅÙ#•/g°ŠxÚ¹ º@¥¤éÚ¸YÕFÜZ/r÷Z”<úqá˜Ø%WÔÃNÚ1ˆü,É^Yìºúrv8”€ÂP@й-+ö¾1‘]±W ÅÅY!ê«&(ÙÌÁ‰=n2'åBŠ`{GKé4pLœZ› JÉÕ̹œy*™M"ÆaØ17sñRÓìÔ¯Âe0'Š?° ¨HOŠÙB…6ê“°c÷Ùìk%akø©7®wD’Ÿœy r©Mp–JÃ>Í_®Öü£¨ºþf _v‰ÃuI7¾e/t¹5êdñ8(ä¹²cþ&tîG¦RMXŽªë?±äNÚì*b]V®uËiš+ÿ¢ð$wn8§ZHNbå†%¬ r:úD"[ÏK®!ó=èî~$!¹4&{ƒS›·-OÙ¬Á•¦Ä%çSc£š>˶zX}иg–B¶òb¸2òBæ±ÍŸ–1W3Cƒ! ^æŽX•Ç€LvÊHd@¯ð1ÊP¶Ò_™Q RÉ!§va4ç6nµ ‚÷é=¹©Ðúh’û¼ö%ôá Wm]qG¼'·,4邱ÙnµÙ÷]ø9“&µçemKL•°Š—áàïNø–íI–žÒ¨ßf$Ú©\mÌÕuը޽·ÍÞ×p,O¨y…iìÑ0Q¨Ç½{YX´ý¿ ’óòïÈ0Jä*ÖÅ&ÉO>În¹ Oû=}g äñˆfÆÛµÎVÂ÷Ëä·…‡Oý½ªÂ¿ˆmïdËîÃ/ÜÃtñœ½Ÿ/h¬§Ê}+ °Å˜é8·jòµEzú)ÈšˆìyÏ„Cþçèäç Záúj┉y,¾‡/:‡Lëˆ Ú¤³ ˜ÆhH ‚õoméž+\U¦ã 2KÐ éæ(gf ˜ë:ò"’Ü¢’7OÌ®†KÈx’ðǦ C$€çÈäíh+éÌ”AúèBp£¯^‰« /¬ê°ÏDl«D£°2¼ƒÐnK »ƒÞ5¤ró™ ³).µp΢Å\jÆYŠ:Ãá®?„hÛ°Œk°-'ÒXŽÞyNž´¬šzN'¸äþòùi¼|B‰ ãT»ePΰhìã¾Ð¢„a2Ïð®åêãˆæg¤þvPÞˆí ºþäÒ1)„H¾4êe–ùŒt'븚˪ú+V5O²ipÉìz!ÇT’i ÍíÃklb&Pv%„†&z²1VNI8¨ö(‹¸tцø° rÁ¢ç)–à¤ä“-ìÍ©¬b ^ñDä©ÊÈàp*±–+FUzJ§Ò"GU¾`pwËö¬ð â.Ôì^¨Š`U¢¾*²£±^¶(ë,†±BE b´‘l$îº èî ‰â’ÂÕk®‘€!RPØBÚáüÔBHnƒ^ø¨ƒ}±ÙpÐ’ ¶ #qöºEý 1÷(ô¯ÏLe¨·ŠææK`ß$òoΘR^©ÅX±IFhÒ@"˘(|ÒZY)Òê ´KjY Ð}1·êÓlÆÿ':Y¤W d´Bç b0×ëÐdBæh,Ú…¯v”e¾ÌÅ)c8 ƒÐJ‹B½i¼J‘}Èœ¼Ï6Í€úoÎ_s ¦n’! K*DIÚ/ª:wÉÕdž˜èNt/]JˆKÇLï hDÎZ¬–°/´ýˆN×óDÓ,&§Mþ›É„ð^&«š¨‹ÂÌï áôÝ.PZ³:ù Û:…«"Z-3ÌhÊŽOØ*ﺩɺº±º×f(x ;oÎåP€‰$Úénž—&ÊŠèZß%§3k ‘fàéN¤¥ˆ%ó¸ú*XdPܽÆÂ* ú­72̤mŠ' ƒ°B$KDêêÎU†”ŠåsG-¯•IHÝöºÔ‹Šv—Ò×.T>Ï` Ô…zç†üDËW(vbóÞà¥*vn÷h(hÎÚfL¥“î÷ ª#òÜjZ®$è‚0fи€f.Ç/èîNMÙ!õHc4Œ²’JDÑÒG2z)ޟȦAô·"^ª“O£ ÒžüP˜…M5 øìn.r¤“%™,Eýh‚pª^ç…F±".wÏ?Â0€Hê?†å+ò×R÷fìèZÄ$D+á±UHI yÔJ¼Qö¥Žbž‘ÊàæLÐ-~’žê ®ó,xüaûk[£O.Sîbr*B®gh1óÙjåSåæ«Õ$SÈÐNrhtïüÒ²P|kzYŒºÉ ©ï>’3tÌÒn¦P`ÂDXŒ;BˆWò "Lk ñ¢fŒ,iñC* (M'L9MÏ XNGU+Ž14°EÓ ‡É.9¢:aï@ªNefÝ.Ƴë¯R´^¡ò‡ˆ0Ñ0d TúŽæ %ë "NÉ ríó† É Zëªm¦ö)Ô$M,¦!êwÆr޲£DJü˜PÎ+í&XUò(–\®A„¸*tXJXµ*\º½’„YŒ$§.ŽVÀŽç.åU*èîKÖ}-q=KÐ×öÓe’ð©â ¶ï õp¾$þå&º8UìúñÕjý-bá´ÎôÖ^„VŒxu a'Ë&¨ç˜á¥!_ç†Âö·rïõ:>x ¶(3V‘? Èš…§…PMC6óz‡bfÔdŸ»oнFÀ*f/§ÚÇ«0ˆõ‚B„uF[r1$6Ⱥ¯èøåüÞó[ï¢DSy¤M:±ZÊñ§O¢Ç©Î$ƒ$'ìðy×~ÄKY-7pørÇÃS‘_ˆ²—ŒŒ(ªÏfÄÛ)Ëa&°Š' fÒï†NK6£~G3•H*¬ÊuGf‰æÊÆó§RÕH¨äa‹vö×xÒDý5¥ƒþR£ˆfjàOëz3pzŒâ¯»% Öøp†U@â™1r¯J‹Œ:ûDþ¶wìqOf _(ÖEÒàŽDP×mÒß³¿‚Ũ°U»3(;(/‹>ôÇô‡4_ËFð/ÄÞctxêý>²°¬Cn7’¿–[{éÆ$+D»’ˆÿ†ÃÓúÐ0”qòæ±§$ ‡ÉT ‡„Šê:’ܺ sY®1•:…àI—”v»Nz[QÌôìâ2V¯Ñ)VÈÙ(t饦$F`ÈE?.2pËCp_uAþWëÑ2ëùqu¿CƒþXUúî¢æ`Æw9·æøÀYv7ÁcXJìLZZí3mƒU0jà®WZ˜u|îG— ¾î%<XÎ'œ[Ço]Ds‰3Elî]N¶)5µCÕ(ºˆhÖ¹‘¶^¡™m&€·6Ý9œ4 ;to1ë¢F*;iitò(C@zƒ Xx …¯=GÃï(¯Nß'kšgŽL+«¨4'ò_5Z(LpÄ© /6¥‘àóŒŠZ¨}$ ©ÄänCþµzíxN¢íî—ùrl0cËã3¨¬×s¡rE –z]WÖ2ãI)Š™S,Õ7fÆ7íÖ$~n²^˶U…~+æêŸí”$™b{8ôI$í'dÂÐÇ5ó:e¨Ò‹0¸¦ïûŽ”W›K!™ ƨ’«®HÐ%é/0õku‘Ù#˜"±0 Û*êÒDиª·ù ­@«W€ŒÐ.on“#ƒ3¾Õ#[£ÊªÚJ‰xòm]B% !æ+óM2òÑÄWªÔ½Y hpˆ(›spS¥XxÆ& 5}¢ATÈåœr¦¶»’UÙzÉÊ^ú¦mö¬ä½«Â…Nþ„•dÕoì12¥´øžR…¯¥Vö°޶Ã8Q¦—–iX“+Y»È;2å xÎvM¶uJB/,šŽLb`¨9a[o<ýŠë]йTFijêƒ ‹S§†vÞŽH|ëÔgo  ‚c&¢“ÎÂv3>©Úð/¨uÚòЊŠiIAãÒº¨ŠX$FmP¢C)$l±Ù7ÁQâ¤Ñ‹†˜›=z%1~¢NEÈ)JbÊüùÑxµKfî Èxà˜yioÜtZ{€®C›e÷(-;‹EpŸ”ÏFDrxH-ƒÜ©OZã¯eTàd’‘‹²­£”fhÅ*·¼dI..gÇ²Š«"ø÷+4Ž»…âÚdÓƒ/‹Ê,5r[W‰±½ƒ»Ï6gœ%|€ _»fž³V©›}m†) Ï8j¢˜XX6¹,Òh)!ŽÑÎàP!Ѱ!Tëü½’^¥¹Ù XÆÓQÝ3:Š÷¯m[n—oˆŒÜ{¨TðÏÐÔý"0÷ñ¼ìy,4zéúÍ ûù´¨ïü3|™ ›ûj |ƒ™Å9#—퓘ȗ°Öî§œ$]¥•`iGTXBÆ,½²œ„?ï»9Áÿ•" UKDý‰Nä¯7–[‚󓬗§f'|øT²îÛ…oáó‡” ‚¡«–WÍÆY—V®=¿T°À/T©µ¾.yC27rbÕ‡Ôò2°ðsœ±`º±Õ.¯´ž%½C—R\.+Ö¹L·&ÐP¯ãˆ÷ðÓŽ×+„qhÄ  „äEeõZ¨<'þhÕxÎØã² \‰ç gÆê+úÄÌ;Šô’½ë¸oñ¦÷3]z”äòêД9†l”gÜ4¥½ˆ½ž3}õSínã‘BÝŒÆHÀ^|‘ÿÓI‡~ôäÉ{KÐ3Ê`šÚÎ|§g¥,ipbÞ!ðWé!;TŽÌBC,ñ‡~›²rË„5³Ä"qݾJáãx×Þýþàò«éÞ¨àªìͺ}$9ëXv´˜ž3¸ÙÂðå†}Ý[yÉ*p3°1ú—ÕpqýrüÙç$Û&®Ôޏ’¹ûF0~T,v8X¬‚>à€(3þ ÂáÈsú! †Ã À(sð ˆFßЗì| !ŠÂ`@Ôž%’Ê`@ t^û—“Yœ2>ý„Ìä YÌ^g%Pç1¸LVg ŽD$°¨\Ô “¾§’Ìd ö­LA•Ð=}ïa¨Nd±¸dîg.©Ö$µ9í¦]P¤Â#w °I-—Q¡ð;ã`ëO`Ns…Âd³š„Ææÿ¦Â(0(”/ø†Ef5­JOP±Çê›ÈÑxÓi²²­pg9©Ìô·JfZ—C-÷ ÌWÕÒãšÙ,ÞŸ6½Ä59/3).œÝ²ñ*"] K¸÷pŸm¿Lu=€æÄžôî3X½š“ë~9ëçñÝóÇõ1¼êjž¿Nô#i*ü̧®Ò¨1©Ê>äm©þü)ʆB¨ccŸ°2¨'«áþ‹§¯[ø„&/bÒÞ$)**œ¨è2§«óîü+ Ó¾…Åiê§0›ô‹¼ ’ô?à#>ˆ1ÎP©Á¨œ²´L¦o2bà€Nyý Í{W!ÊR Ú=Ètp|Ì g =í»`¸LÜê„J)¬˜*üèýÃÓ›"Ö®Íz †*muó¢´µï2í]µÈò?Ù)ZóTÍsèèôÌÈ„D© ”ŠÒGúü©£h«ª˜ Œõª¬B¨J°»3ˆ"®ŒßÈDjµ/Ó‰£,ÊüâBê™;–j +éf©À‚‚ÌVõÛ3!uïZ"ºýoÙPªº(·Lþ–)¢é$ŒxÒù Ëíú Þ¦“Qù¤¨»Ñ‘úOBâÉV6‡$«“–F…©F€@©ÓÇü'\¢S欚˖F¥3£¹2FQ);S)+®¥s;‘õ#5ºÍäT"Ò&²62ÃUÓWdß`ðÛ´#›ŸïJ!.¦q_/¾¨ÛF~»vÏ9@t€ m#ÐÕ•-8.4‘v8h……ºR™æ Ì+ºªpȼh'>щ+2’«fß½>8ÂQ”Ìœ:ú«F¾°žðÅäÅùgü~r¼×fš¯Ç—ÎÅà<EÊÄyo®ëé.Å#lS«µM3Ñ£órÉ[‡„Џèµ#mu®=l·DÍOÒnB«­u3²b—ÞÙ'+ µ÷<Å×d Oë9(å°ÛW R~Åå&…dî’öpE@‹¿2 X9!3'Õ¾ÂAþ}Vc“‡D§"8›ž(L‡\ƒ2²¾NIìn!3ò6V«˜ Éùt•„¬=Xò­u Õ‘wÀERøn¨­_“V[‡ô 9 Å26† ,6ldÔ̰РöRêiãè×—d*×y]øê¥ø:þê®’25Õ ÏädHùÕQéâÏËHJšùP*q‘×6Ê,>å’d§2TA)@«å98´ï9»2©éD€ €¬-tÏÐ ­júd’ }®;wÂÑ Î±âI‚ *RBO†=ŸÛ(?ÞÈ ½žÉJ@Šæ²wŠZYË&ê–­ C.5T¦P OäÍá´þûfK´u¥¹VZÉÈ5ðm¨Vò9Y™Doqc†FyÓy““™úQ‡Éx’x$ØŸ…âR÷ ±J_£›˜îWVÙym-Z|:’FP]ƒb&•ÁŽ‘H’y70È”” ÈÎÄV›¤ª?«¦œ£IË^ÀnW~Åiˆ\AùHj ­$ô¨To¬ÆÒî“O&HÏÓKdž½f·2$Sýuò¼€G²ýr®ï$ŒµAøÝ~Eg¶Ï²…PÃÿ‡“œJÖá ûšËBY·Tf#K¡ÕihèœXp.%(«QHåÀYTÖpµŠãA4c¥v®Ñ¼ÇcTmÙVE¥à•ûÉv&réÖç×CE’fpFž¢°¥ÊÖm)b9™"ñM} è»_X MSgQ#vTڧ­=~`¼‚5˸ª3òˆ ­Ø/Ñuüß $‘’T®ö@#³2bÛú5¥Orù5°v¡Õ˜´íikÎ(i¶u‚»“5ú~Ã>x2þQX ÇÙ%ÑÌNR±Í³.u:Ë‡Ž›Ä íš ápO“.•¥éƒ¦{tùÕó=nøÈä²”zæÕñüÂ/-­¹…Û%dbC£rTQ†g:ÜÅ^°-, íýY~/³£cŒÈÆÉ¨dmoz”ë«äôŘY¨$_/>©ó¶íPÜ]©ø*Bš½`êð X€}œËE’V2ÜEÊ­·®€HàÝ·=F°:ްxm>èÉAP{»bUn¡›G[Ÿ$G|50ƒoW¶ÑÉý%æ÷Õ Ð8êÍt×EÞ—µÛáBêÔŽ5xîuÂB6>u6è‘,‡oä‘w¶Ì˜I$‚Bk?b4Ö­ƒý¿ÆË§È5Pu™ýÚuÌ/©¯—ëVòHü€—!»«} ZmJ¾/)¾á¬¨‰ ¿7KïŽò©ò"6㘬CÕ»Á92‡ ‘Šk¨Å›Úhžˆ†:Ò„œ³U ÀŒ¨@ ™ ¼}0zHÀy@­Â!ˆxˆ*ê4ãi'i¢®ÀŶÀ‡( šúK®Øó J.¸&;˜KÂ.c“Ð1˜Ó1Ž#'@›;‘£°3÷ ‘׉0“‘O¬CŸ·K&pBÊã$¸‹¨q#/ ù/"²9pªrÂÛy0К™“÷BŠ«.ÚÞ™ ŒÊò"º§ŸÉ>&Є83Ôí²Yè¯YÒ<+éàý)³X>³ö³Ùd¶K·‡Ü2:2ýÁ‚:™ž@cöŒŠ®žaü®ÙFR5€"k?›Š¥aœ¾`°É¬ J©ˆq©sÏ9|_®J½c’y²’4Y å%™Ÿœª3Á:W‡Û+€l6.*˺©’ 2öܽÎÅüS½©–lrâ›?áé‰Ó3\$Á¤H|-ªBºqªµº ¨œ‹ó ²ˆ—*‘¾€¸Hs~>Zæ3ØzI£Äš¢t‰&è%Ú£¨¶šÉIý;P}@»ü€Å¢ ˜³œ=+t³t‰+ºÆ™â´ÆX·B«t ¡àŸ¬«âZò4"?«Ó“&³)Âë¾X»$¨0¬Ù왂ì¹ß“œŸÈ3tÂ"®Z籡.¯šˆ®ò¨7`ý(Xê‘ÙÊž¼¨!?ÌJáêd¨¢›H€*NC:§§c ¹Y5§ÁæF•K\pA˜Aøü!óì·úŽ XLÉ©DIïŽ àJ©Ÿ¼Ê¢#þ´\Ç)ê¨2Cž³ò7Áð ҧ“j<КžÉ* è¿ËÁ1|Ð)7$ȯ‰‹ š?êR´"FÍ*^‰{éÀú¹Gö¼¤ó.‘@§c'»ïªÙæ/¤ØL[Nšâv;ê—JË¢W=ÊY ›…?ºÄ´‹È‘ø.£%+v,S •ŒY𠙘ÍÆ¯½¸ÕÉ´*©ñï0tÆó–„E)ŽFÄÿ¸¼°âiµt9 ‰t­ð} ʵ¼mH3â½E-(Ó‡ëG’Cã1¤ò&T‹Î¼‰Mäë><åÏ,J²¬ÜLÄßµKÍ9š¶¢Ö–80Úcº3254=›¢ÆÄRR|Ã#Ù®œ‰º€Ëð<'Ò•Q‰>’ydÅ ×Ó³Y¯Œ°½ÂÌ9åò…²ò1cÔU“£$i Èæ6=kÒ¡ÁTóÿKô,4W=EIBü¤ R¾‡á8ˆq²¸(ÃŽ!ø0ðâ ñ؉ìœ=ªÍ5PW}Y FÄ;ØÅÐ и×1püb<7 »sÇØ˜|›ó¡Uû\ dÓ#$ì€9Þ«;ùOdd­\=Ÿ’Ÿ,[——ÅN-¨ŠÓè°} 5AFÌéˆÍüïÄ£ºTËë_R*£ó‘Û`Ø­ŸˆüûÕd==B‡TÛÁÖÑÁ:u&0µnÄÙ‘aÊRv—ʼ\:¶ŒáÌ0„T`~’ùºÙð.ÜIÁÁÏ0è…Îõ©’XƒV@ó]‡2%¨ˆ% ĤʈZ;´¼Q¸|‹õÄ2vÅaÔø¬ ˆ‚§6U¶3Áb {̤ ,³ >-ÃÜ«Cµ¿8eW|›([@©ñš°¸~™¿°Ù7.ƒ (sTýÝ>E(-m¹Á }*ì=‘¸(UIl& ÛuIÌÚšúc Y Ù@}YVÌ‹K j>]¢Ï/+yR»ñ]HºJ¨E7JWQ•´Ôù ’êì^ôÄLÙšÏ}ö'm;¶Í à)²´Eã‹ò3’ÿÁ8 $͵ŸÕ¨‹õF„Œ+IÕÙ´¨0%˵uè)„Ͱ„Âì¯Úõ(©Èâ0ٚƽÍU3SÊkª‚ËÇX¨ë÷q¶×²êÐ1ý ²´Ý1œ J7¿MšÖÚ:kLd×/n$O„^¤”4Î'ŸÁDæÆþM Õœ•Q1¹ÁD)R²ÚÙ1Ü­06³Å8¨Hµ„ˆ®e2`Á7báãÓ{ž7L?¹|¡O•(§|üaÔùÒ@Ó#sMDÉüºd/Z=ñÖñ©P{€Üh­=tð5،̬Ÿ„ +ÑðùDºá šƒ/"3Ÿ`ƒB<Ó¯c£?ù/ÖxÚÇa™øE±F’ ·›çæQ#»#ŒÿÃއ듣-•⌿˜àó#œY¸{›®|±ÌKºohòæ ôœRSåè¼C+ÓѪ"…ÖÚ]_ H©ÑñÑ#$ˆý‡ÆÃ=Ÿ7“×Óâm0m :3­å>¾!±¦îg¯VŽ_áU6KÜ®)ôv×$‰Ö¤RÒ¬ÖææâÃ-æyÓg A‹…WòÛ¸­B_.닽Ìß&;˜¥Û2þËÖMb6*I IÔ<°Þñ¯ðŸïDYd;=®ŠËÛËkŒeè,Zgµ±¨…›+B8íÆ? pÓ!DÆw67DtoX"fÏäz«ÞJñšS¤˜ZåR›ûUâÕ‚R_Ô¤R®¡͘õÛ¿£^òcàZ»éh‚PµœN#8¹2kì4J™æ¼µŠP)Ó1á®[“LíSŒºaN[ø\“r<2jŸ?0àp‘Î@LèÒ;¾&ûÈNX×jÞ´Çq%5]êò4sP*2yùa˜;tãhW€[åFË`Ê+Î6œŒZØ >œ©¶ùÝÞç`0|ÌTZi¨«½¦[S ¬#`ÂY<™ ÊwæQ.¿ûß¶‹¿r.€—¯¸òc—›ÏVÌšv¦?¨$V;@´®dYèö)ãÅÓÝ<í… Ð5„s 3 µ§ÕœÍ˜¢Y[èàÅ>ÂåvŠ:#Ì5OTyiÔQf1£CÅYƒ:r.¼›B'f`{Ê #>åÚǃRˆŠ£ë³ÅYlMÑ"§WlÖÁ›¦r |Só’šö„¨œ<{ä»j:/¹ÆŽÀÊOÅè;^<0–¬-æÞK’þÂÉk;um«b£Úña©BßðéÝæJ(€? P0,ûB_P°6ýÄ``£þ- Œâ€î=Æ#`)$–"‹?ãr˜ÜžG$“ÇŸp9,n.ŠCÀ“¸ò}-ˆÆa°·Ôì %™FÁ4¸æ'–Fâ±hHc£F°=v|ü®Þö9<ž1'šI+ô Þ#F‚h“*­–#+”Å¡òZ4Ê¿F¨Ç UX}®)vÔ±W¸q{dn8ˆb‰qÀE«÷˜´ãŠšáîñJþZKÌ©ÏV¶S«“Dn3hÆÛß§ÀäS™H¢‘‹H SIÏÅ+0Úü–Sçö}—É@W‹Ëg½2Þ(H-ÃÅî@겞¾w«'ÛncÒš‡J-΋FèÙûßPØ$ˆÚâ'mZRª¤­óÜÄ´@ 0ç§Ê2  í²â­Ÿ BØ”¤¨Â¾¸¦OÚ¦À€#¸9 ìû¤Ž¤AlkpŠ4*“ŠÌŸðRó1Ìó¤Ç6‡òض-˜ªÀJ†£q+ë ìšìÕÀH+Šà¡¬râÍÅŽÚ(Ç+ï BèÆ(èê kÚI1&HòÌ¡H²Ç¡ú¨N$Ì‹2¨kV‡Á "ˆì¤­š(yÑ0'ªçÚNÌ'i’R°Èh¢e>€l0’¨„Âä´¸ Ð¥*ÁÉ:Œ“¹° rƒ§©ó×¾j×©Ê«Š¢F³¢w'Ѻw.é:« 8¯ 1 ê5x’"h¢âŒ2'µj!ìdö顳‹)#IîP¯³Ò"ƒ?)Ô¥,ùÁkŠSg€J3ãÆUJìÏ·òÍë.1­Nö èÂq$°ÂN¢*´UëS»2~4 I<ìÀܬR1y€ ý£b78õ!HZRäÂÄKióÌÞOGôqV'äßL§ÓÍòâU…·g!j3ú£0ˆ>oVVY ôí$‡®”Œ*¬þˆ~3í´u*€­[Pùi+Ûã«,ðF‰# šÛ¸óú°¥-h¯ÎÑE»E×Ã8ÇP¨*jÌ`#–³ÚCŒÎE*“¤ŒiGªÃÁi-5p TÎÇ ¯Æ¸Rößkà‚ß_ÖïËI¨ÉÚ™./ìŸæóPº¢6«ÃÕs:úòeÖ}Ò#¥§"4ñþ’ªª&¡q ø¨‹Ý8ÐLƒœó\€ ¬#j«ûà!<+Î`hl¤÷ܺ"ékH:O6v\ÈÞI'}UXiþÂ# _^ƒï7¢µ'Í·ºÜ+WA¬¬,GJŽúÎÍ#1uBÏ õ]%vâRy* k«‘ñ¥ÖžxN9ƒˆ¼Ô:4ÜDK «WÀ¾­¶Qâ®cYÅNÏ90.Èâ-‡‰„@c `”¨¥5Q+cfPt 6CI”eÎqšÂŒÆØÛ)Im»ÀÕxýŠLµ6åúI YžZd9ó–ÇÚê@p(òC¨¿ œzÿ"ÄÉ8¶¥ªÈ3]ä,Ä48˜ùGé)h%d$göŒBš6ÌÙ>$dt£ŒRvyã7è>£z.1¨š·YÛøÿcD wIȤw¨$¥á(êý"{JÀ¸~Ü‹ÉÙ\I¤ƒ¨Hdô ©_5h¹]#'àÞˆ¾&M¨¢† &apþe§aÁvvNâ‘UZ±]m´Ô挗4¨b„Dï “¤³ì+š¥.o9B±8BÄCfq™É©Šh #»A°¬¶ÂB]!+El¤âª_eÔx"ä6Y¶‚„ç©)„Xñ"0…ÊÚ.ìÍŠÄcÑöa%°IÙqZ™ŠyeÚ#èc‡êœ3æ:u›täÛåBq4Ãè–0*DÊ/BPúVk­¸îH©ð’©² §¦­’³.©S¹ÊtPþ›½xX;"K´Þ±¸L>Ü|±yŒê_ØÏ$Šð)E-;P˜2û¨M§ˆ-áÆ)³ eJÙªSØ}ÉD¡Nb¤*£Ä5öÔՈ䎑ˆXñ5·ÿ§•jå…L¹à¤Êí7‰EV€"Êu…0*bDÂ1<êŠD§ÛRvn†Az‰àn$â¶—µ>s)æ#¹Ø€æ%éÅN0„}ÚE¶Óå<^zÞ¨½8¼€”Q2ž›ŠvfOGW¿RYV?¤DE±jb@Zbv†+AdîmÝQ0ï‹ct 7~¼¢µ[Tc9„ù™·“û éÓó+å|°Å(ÖǦS‘òlW‚ËfíkÖ,tmɤØÚbò_›ð°ˆ¡‹‘‚®$½‰Ò&Tj“Õ #½„’VØöbj¼ic×¢n·;&êxDª±"dGId~Q1E~IÆf§±Ÿ²ª„åDZ"Õ7qðôé?õ¨d_»Ñ½¸t“,ÜF05†ÃÏC­» WÕœ@Ivºõ^üõ‚CæXÈòüÊ"«"Hɸ…¹KpâÁcóÆ[‡H.8•ÐÈý·´oÙlF©`øRSïâ%¦èb¦\W¡îíw»¤ÊüÆnÌYš.v(qeWÙXКy…o4käÑ­»ñTI¸à2òÆé=Ðíægå­fN®c¹Å4§E«Xÿa–²l€V™ 3Þ¿¼RæÆÜë§§KÏ^î:­KÙáUr1n êX]Ä?AN˜Ò§CÒ„¾.ó¨îU?(ƒpGú£FôÚ¿ÁùvsÕ¡z$C÷CV®®¿…²3VO¢ÓÇšú÷§¿öu=3Új iÐ ŒÏìÔ´F ¹Ø©lcâ¨'¿EÓõ8Q6æ¿U“MØ&»$Iõ3ÒRɱb~O‰Ù'Z¼©m­JAÔÓTÚ„DÕ”Jº½wÒj"ŽÌd…ª-„pZì¨g°8tò¨O–Ù£´„fZr©´ùbŒâKüüŒ A®h7AøuOF¼…>*Ì:+íÊɈ¯"ì*Xfë7i>rNÔNcå6ë(™ qßdxÑŒNIìz¼.„ønfcÎh¶¥¤Ó& ¹+á/ªÑï¨T,òGF^â«\È≭8œíôVÐÎ.cÇÿ iHE0àkbCP3Ðæê« Å‡À]ô•"Ù ï—‹“ –C>û­"aI¢ÿ@üŠF:£²×Ñ› e®^¦@ñBck6G¦ ë¬èÍ€úŽ®GJ,kh“Ñž§í Ÿˆ˜¨bÙB,þŠèCDFcˆû¨G16ÌÁ%PQ±TÉ£€ã‹œ ¬"Hž¯É‚ÅP–ßeB¸«¨ZâÂwÒ„.ÈVrE4èMÞGm܉‘zň+êºOä+$¡Äó ÒãQA!÷ I1(è±BÑÐ(•’ 5jüŠIê†Ïqc’ž§Î7â¸c¸CÔú…¯+.Û†§Í"üŽ ˜iœw±ÔæÅzrÄ!ãPëq­ÇB'mäÅ(ƒÍ/ºWbÆh¼;’d‰q)¨N)%(381H–ó5¡©6èS³ZÉ&aÒNöœåëÎ~iÈ§äƒ ¨r^'ÖT&¾ëÈ*ŠIá ÌÒWòØïš$«rr3`‡TÐËüI.â`^§|³râ¹2Öü¬l†H*ò5/Iná‡h“î S0gçÖŒ 3Å0;# :MH‹GNâÒÇ®GŠ:CQ)Ä )Ên;„\ŠFg,ˆUÿJpfìý Çæqçþ. Äò‹‹ú»'Áø¿1°!q¶iž«ë¼c.ò-¦"¤c©½ €ÌC4Üqî¡M¶ KšêŠ›0'ÊM¢="ñLÒjËK†üLW:Ž ªÏóG¡8¤kIO^ÃèØ®Ò :”µFQCCHŠ`0n6ójp*²vݬb±îä1Ôp°®üX$ŒkiŸ”˜f0Å/*°Ùká/SO-°ˆjŒ'TêPÈôŽ5lã>¨^!ˆqìH÷E‡°€âÈT–…4²§T÷´›5­L+´:NÚ¶Èÿ‚<ဇ%éþàÀ±̞µUt®ð¦'3/ìÔŽË{Q£­W0Æò/ÌéÔckkdêÄòîȱ J€mÑ%2ömÈz‘?µ°H2a&hí/ŽŠåéô¤ŒoÎ×ÕxPeCÑ^ÿ-ˆ“ |³ot\KÔHÔäÒtåffèT³cQ?WˆÙ‰ze¬`¢¢Šy Dn-è>Ì.f*îöT¶k´Tqå8j˜ñê賬N¨s†árŒ(ÌâuK[U¥Ä¼¨éYLãEBŒøs$âªÄAîåõiLeÅ ÔÚ¤FápæÄ’ßcž6‹Æn:L™^ôý-Ñœ®æE'3' ,sK@#9Lí9‡hµ?QK·ÇCòö’Òɵ¯Gåi!©²‚«5Lnþ,°TEìwP¦ü³Ð.t.ø‰´ÊÀ‘LqW(ƨû«Àå´;Cú<'’‚„)5‡pnÖ(Dí$qŒÞ0€™äjðˆ¶/—h•–£oÑT#ŠæL:{ñÀ{–ÿj댉ƒ‹hìšä "Î>ëê¨r´gMœêîlÔ–›%©òáÒÌòè~£ö¼ð³\«1×ͦ#Á­zâ¿0b?°à™äì<+í -wµaIÞë°!&0ÛòXð5ôn‹¶Ét¬/-Á9NVT#Â.0ÍbE…T—îÇC8}toÓ„q.ÖTÓ‰62n:¨*;6mÔª„FYB·A X¸»xÓ÷!Èöÿ¹Í!„\…PH,.¶t~䂿Åê,1ûz+8¹ÆÝ>jpkó ~v¦•°Èï4uK6fg2l!ñ>Â%ÇOŠ~¨l.ìqÓN‘Úh¯›FNi@±Ù6NˆE÷4N&¾O,² tú¸v¦¸gN¦óX7Ÿ_õÃÂÓàÄ¢±eò0ÆÂ‚»t7Úúf§×4èT£¡ý㇔Çä†=WÈíEUVøMP8a~ö@'‘œs/¨\OÛ ôÆ Lºaõ(“‹`4ë†Õ?‡v-nk\âÆ˜!2.@ GHÞøì¼¯ÑY-mƒôàz7I“]"ùuxP·ø´XìðÇ )²H,â…uF øZ­Bƒd¬ V*Ber‰^~c="8«ÆEõ?‘J^5lg8¦[™ªò!dÂÔâ±}æ1`°õ^ÑŠTnæÃ·ý~H‚{ùÇòJ¹Í}9 *k®®ëÄã]·îalžäb(”ØôJðBŠîè `rðˆ3ŠmD0– ²=£(Å ¬&ÜzV†Õ+%Bœ)+iOLéi”*Xp3 “Tk‘0óªÎ7;’!øèKTì ÆŠR"5¸}hG©Ö=QN'ÿ`ï–ØW`§òÒd‚–7m!–d02’x®‚BIYÔ¨ý΄H-”äkt´Ðc˨V½íÒkï@ò9s“Ê®ÚSå2— ÷ÌPp-Høj™Hyg«­iÒHTƒ5Sšº3öO%½[ǾåUu˜x‘Ú'oPpÄúå` w1Ö˜GŠXjkºyÆ|,n •õ±+)F‡äj°´æ÷ˆ":>€÷eZQ4>ÌÈ鯀åO‡£rv)tœ&{N©žI9’W<ŽÆb¨¢»R‚½§êo¡©9eµ ‡¤žóï¡æº›Øœs7ˆK©• –0Ʋº‰ÊEzPbö  ¯Û"àçop.å£ÙÄ쓃Iˆ¤µ²¢°öåç D´lùp$êîyEÖÿ«ƒ3º¨§ò1ó<˜ލàªø Á’‰"ùÌ݆Ÿyϼl !õDG7ƒ@»µKI”A+ã´p¥I¥X”ò9Œˆ°L~’ þG$Ò2ˆÍiQ»t¢\…ÅÑ×Kü0/ì÷JÞ‘rÏ kÖ“Œò¼%ª««Zs,òù™ °ú"Š™‡9UÄ:ÃÎÓ¸œ_W1º©Õ0#'$ûíÔ#fÎ+¢(ŠˆÞQç"òž§ÏÈö"Ð{^®¼´^ KU”ø&ܵj®¦ï°åššÙÈV&CP^´€â"¶mXÏÃÚó’“ÐépÉÒ˜Ò/V,¨F;%4©œaB8¹YÔUÏVã3Ì7U»´ž>Kª@C"ì¢ëv V8¨jºçªàÀ†Ôk|ÝC…n.#ÔYmR#¤Õ@<«Dí"7‚Áñ΃²ôÚIP¥Ä¹±8»½™‡oˆL<+ß ;*<7¸!9S1’ãVó­\ôý} ‚…œDùqBâöj”clºrV£GØlZðè'ݪvéf/"Äq|V)ÙN˜ à!ó·¬x ºF¥šÊù¾c¢Ü·KѬ%0$àg \P]}qœ¡å#IÉžIó@R (žT;0]•ì”B‚Ðs0•&ŸVòDütăZ·z.= ¤B¶™ù@åD\É:í—Œâ3ÙI$ì3ÊÚ’Ú«Cu¸×Ð"^fý" ‘k¹ÿóz¹=×KUN[ueºP–ò3ŠûNÔ©§ý-ÆÏ.é1hG[KRA^‚<8±ì#ÊîÐz>+î=×7†4­ÃŽŠp&ý¼Í²ß(ß™f±tޤà½Gáý¥ñY$9±ø¸^›D¥Ñ3_tÇÚôÕWBÙ Ìz}GBf&ÕM$»;®êåÕt»vO¾­”ÆR¢¿Ò²S“fðdV»]X8§¿<ÝÐÆu_¶5BœmL¸Š—ØåéN^¶+îß.Ã9åQ– çðƒ?!'ð?âP)Eâ0è´^ýdÀ$\õ“A€­yT:IJ$ÜÎI$|MÀÓ˜óöI ‘I#±êfû鹌Æ#H¢3u2 ù«I'q@:üˆÈ¡Ó5v¬ù‡H©ÕÙÜ*.N䔹 2e±Wf2)Ü:Eßì°«Ö.úÃ\€7È$F³ªD_öxfõE±X¡Õ ƒþó ‚ZáP,}úÿÊ5Ù‚ ]­R¤¶!šÈÁ,[*]µ]ÁN£Ñî/G¤Mß*- ¯àÄ$•ÙE²÷ëV¦8ÐÅíÝ¿‚g°+„ckÚ?áS Õäå+]‰ÃâˆÑaß ‡E ü¢ˆRvå&hs¦#,Z ÉŽÓ@ ŽúHÊ1ëÚ¬#˶(ƒ|$IB¦¹1@bþÊ’‰¢‰mDÈD«¯ø®¼- ´" BwD­š.DzˆŠ´±;§²ô$OhÆ#Ì )/ôHÜ8ët·%ˆâÄCÑB@”FŠ$‚ Òà‘,¬Ì>†1òDŒœÉ©"Êý(­`ŸqzæF's™€:æOjêDý!Pœªæ¢¨„[³èôe6ŸÍÓ;?ÒL|ÉI€ndH·=+•.€ ´çIF±ó âÃt‡IsP-ÊÒʧ&1»Ý^ªÈÛØ'mÌ:„)Ñt½6à)G"‰ÝœÊŒJ­<õò­9”‹ R;º¸¤ÓU>YÀ +=!ŽÕ7ØèôuvG÷· SŠ)ßtâ Ä&6Ü…ICGìÙmE‹£ù@` ʘ©ÓÆÈ ’h‹Ï/XÚ …R(¸êP›&é8çÚý‘"+)Š€‘X…D‹ºÇÉGëz„U 2Ë]?djÓµ:º§I†›\JÀ“0¬5Ïl¡è†?Y>³%Þz¼ž~²‘"´Ÿ¢ë¬{¿Q&ovI›(Ã-(Eþ9IÿržÕ,–`WCP»'.u‘Ó5ªø5Ú|†I¯€”Úw¡ÌÀvÒ:'3 '3M|YGäšÇتzŠjÑ>T~¡Mâ))\)ùɸ#ëˆ3l…E Ë1â ÚíËãõP¡’+M6ª‹êH2Ê”b;7Moѯš}'ض(Õì u#Z€WµÞ,½æáwÐÀ¿¿™w1ú‚ù@~º³˜Ýbyý«3ÅPüOs¼tcýê'~I‡©°jèÉ”™çÌLL¢81ÕÀCÖ„Œ3¡H)8Í£ˆ/ZU@ „Et°C$@”Rvrd3$…²>ÅÖŒR?n-ò™C¤ðT8$¨I…UmŠšÓ§ÉM³å9•¼õ»TÒ©¨¤²&nŠ8Ô~s!tS€5þ?˜ôNÄ£6MÈ2#%tø£¹ç–dƲÔeŒ1(g‰î UÌê@ûµrd1ƒbD¡ÄBˆbbQT<9#Ê舜†ìvmé¨WïÕ –Íl™N9í£€„ AŠ+驦C•ÈVU—JeqyLÆ7#66Ñ>©µò‰í̽'-Y±,òˆD„±<¡I~B !bšjI=½yn‹µo•—>ãĤeZ“Z»%™Ykƒù0;2ŠÚ¡zh` v°.²ùyª®Á3ÒLÚJAq÷s yM£ˆØ¶#cÄXµÎý<óÄG‰C@‹øÞ±0xœš V‡­Š£®8ñe$¬s™‘ñ¿(vòï(jØÂ…&üÇX,£jÕMJÊ·H§ŒFMÀàø0‡Lúñ Á.¢ï¼¼‘—–‚ ¡¨:øE/,ÏÕ·§#÷ë;–}Ó¥óâøšâ)€ƒ˜©Måf±Šm4T=~íøÝe»ã`½T7LñDNµY„i°ƒîÛºN¤® w–+ºø›FÈ3¿Êtº@€6í6Q9æ ˜êCç#m>”>6‘µ¢µfi8Eè4™ÚË8Kvå©…-0+õ铱!‚Ðî,Ï£Îr3ö±ï©C,ö? Ÿ,$äÛ3Ç6²F€™,Ê“ÌyçÒ`Ñcî_^¢BÑ vm©lT£¾’6¤µ‹‰œ̼Q8ëÁn•(õ®ç¼>ÆçE ¤âÝA˜ò´¹ƒ\äõŸM0Nz»U4ÒG“ˆØúy›ej䪻•ôPÑìÖõ”gä6–Ò=m©]5if‚÷•òËkC9ÚÓÃqH|·D¯˜la«d¡ªœkddJ:Yúcñ&áÔ÷„Z·-x„‹ Hx“àõ1íG¸ãu¥x§± ‚ ªì²ÜyÙlXZ&¼.«CƒòÕ¤ôó‡ë¥-µƒŸYnmœJàhqÙ3ÍÎx~ÛçIˆ®sÎ&º¡ñïO=47hɨ-^D‰|W ·ø†Eµ¬¬á^ -‰ä–-1Õ:ÍÛ=xeXLçNˆ®à<[ªž¡9ŽvkÕïeeÝ?)t¨ 96¯0ÊÉú;;õi„v¹û¶â>ŒF®-îLÝvÒn³QºjÌvü6Ò1‘ûª¶ë³—Ê)œH~;»Ø‡ù»ù ãþ1ÂJ–›¦7è±;¥ŒB¥5ž3“­Šê¥ ³a-—b¶£ÚÓ–«l YÍ<ãBŸkM¢«÷;˜Ý.CB ³;è‚@X§ £&ÙM³Iñ®¸Å`®»‘/º7 ˜§)¤µ³‰<ô&»¯'û³‰‰´Ž±‰Ž8›¼éMˆqÈ[ï«<ór4#¢¡#›iBè§™°ÀØ:ІÔBAe¾è™œ°ÔB}ŠL4˜†°ÛD8 kÅŽùÛ”•·9ˆ‡+xá•pýŸ€’Q˜Œ0着r3@+Å’kô=!u+áU–|ÂØ{¬Èà h¤/€®›&©?±2ÉÀB„¥£+Ÿ+Kš)€!r÷"Æ*{²T€!§ ‹é#!õùˆ 5Bû‘æ&„‘Á«"éI´0A1‡)B%â/ƒp<‹bÁ‘¿Ã‡Ê B)°]­ø›Æ¿³›z§)Q¢œ_¨ð7û›Æ9Խ˯£kV„'¶QbF¬1-ÃlƃäêIšŸ©CŸÒ,ž$ ¿Š†¹ qíQ«@B†£4_3 µàš‘9<Ú)W‘;U½17ú* 4ž#õ0Iˆ6ëÏìM‡Ð‡ø² ³‚ް§!añÀÍ¢™O€Ã+;¦1¨¦ƒ @Ê(iòŽ ©È¯À“µ¶Éì¤òóq3d)ë«S†â’&!hR×Ë4 “»«Ð0“€A*@3q=™&¯ìK” í£QK‹ª5)ÍœìÁŒi)h~KÁ¨ëÜ›,¼Ðƒ;sâÃ:œ ¼ŽD´ª ª°²U–)â!rå-ƒ3ãï‰35Ž‘”Ÿ|#L*…Á€ËÃaHtűXÍ­ †LR¢‡ÄEƒhF9½­¢)Š*L5À˃Á7+ç’Ãú5YßÑ09hŽúõH©{¢È‘DX;Ÿ¯ûÞø¨èó®Ü±¾q=Ÿ²˜buô¸ B:!Æ—tB$¤«¨dD–ñj«RKÃñ]ÈÙøëkkÊä;1ÚŠì1ÍÉ€Méâ#ê*ÀÀ« y¶4³¥¼Ôª Š@ïÏd¶’F+… Y4Çd† ä #,;¼ñ|Dzj˜´ŠL[ÊÌÃùÐZ#¹Ê¬¼|Ñùh?é•®C«DÈëÛ}¯›‰Á¢º¾›¨¹h?Ig ¼VJB´¬ n¢‚T.“åCÜ8¤¬[R©[9@­™å/ d)ò“DŒ^ÈP|ÄaÌ<ê¥I€ИÐ+ŸÑl2h±I3-a&´ÊøÃ+î;·êª"ƒŠ-A4Ÿš›€ªq™™Î»)ìIGJŽùwQ]„ ’:³²ˆ»’¶Hø›͘Özä#ºª é]¥dù8ì $¤Ñt^ë9:µS³ÒÈxŸ'ðNjÑhÔ¨Ä*¥$ªI›ôcô1›QߌDëH„ƒŒ…t¶!ž>€}‘ÂÆ•YC¬™ù]ÑÔà³|3] ‘ÁQA™åK9T44¡2ÚÃKÈ:Œm:søºÍˆºa½íi6<Ç“Çë)„n!ô:¦áUZø=œœur¢‚ÆC³ØÃÓ`Ó<#œkÓWØÃO^@B²Wƒt²øTŠÐÃ[R<¡WËÌ· à öY²¿"+ ¹ùÉY‹Äø5 ÑlËà€3ëÁÍ6­r*Hú•ÃÊc+8Õ o݉$C$žúÚ©‹®œ;Ô ø$í¥¼Á˜È&ì5ÕnŠCGÖ1Á.ÐÔV¬l]8Ri ÀœÍV@ÃÀB"»Qš¼ 5ÕP|“ÌÒ‡Â8ÊÜ̶+9RL@Yé²A½Þ k©"IÔ§{š,CÅнk› àñw,C'ü‚Åd½Í%M°«`„˜µJˆ€ä4}þË._ùóEÛ³¶“P"ÝÒcqÔÂ>›ÑÙ@8ÌA1QZ:® T-bkj‰ÙÙ‡ž/1ߨŒ˜úwÏÛr6­ƒÚÂh6‰¿$Ãܬ1‡~9 ¦­zH 4û*»R·PÛO»R……"ªX¼±Œ –D„&Áö]PƒP­Õj˜ë  ,ÄKõ+Ó…·Rd`È0¬²"«N{ú¼ù¤"mñYMºØ¤2¹aµBgáOKkPD˜ÃK9=EõžÒh;:ÕÕ Ê#c»síߤ4GF)î)³è‹«1kµ³¢ÝÐ5ʹ„ZåQ  ¬5،݀ ä,³ŸM Í +  ¡å¤6XäAûÒ^´ =LÊs×(•/âÛ_)ԗ͵ÑÝ1ìƒ'è÷^ˆîÅp}@Bj>qb»” §4àŒt`T®¼…‚ÜKLJò·è}LŽDÇ9IøM­x‘¢œ!GX„þ„U)òàf‚2E»›ñEf7Pqöã]©Ñ¹åÉ€1ñaÚ˜äÌÅ94F£Í‡ÏK—GË@ž¶¦Ôâ?™«jj-°€÷õêk;=n=›Ù¿¢ ¶¤^q+Žda«?€Ï•ìÕ^ŽÙ)úØùÕÁ•Ò[¹£ë-‘­1ÖÄÇÒ;TÆi±]ã½*Ž˜ËSDKT¶](@ÍÀ¡„^{jù¦Û‹­C&‰Fh‰Ì_þä“cH1ÙÊt×\«Ô5Nj)ÎÄî ,E«éÑLfâïGñwi‘]P,ʇþ‰7œîMÒˆ‰] *®ŽÒª wßö(,òC¬™ÚŒ*®ßÞ«Î!b£4:VÌ+Ø)ˆjo!bÀÈ­_رKÈe@gœ>1TU.Ö3ú,ÀŠ+-É%|µ^k¦Üæ•.âö¬ˆ£ ÅÅüc=óÞh›°®²SÃ.å.º”½ û~äÏ Ë¥‘‘µ s"£þCêQ4 cv[”™>Cœn ”­eð›»·èïÜF[ît [$)i¡€K<ÅëvAÈ)E½½ôáÔðâ<¹9hÍ—‡âÉ϶™!ê⇔ûEbøg-§®ýq°LÇÕ°«FJ¥:È} uñ•UåЗr¥UŸ6–Ö7î)Z%˜¤©ˆ-¤ gú4‚Y=× †fhdæ¸Ý11M£Ÿ—v éO#6;‡­{$ÂÕ·Q&Á ú˜BYÛl±íWlÞ Ʀ·ßˆèÉ@½CŒoˆÛ@C„ŽéObµ^e™ö:6s²bçÖÄãXÕáu8Éž7Ç^ˆ¥Ó“&¦Õ}yÚËÁ<îN¼ÆoN#’¸ˆŽÒc>Å‘­ÌåÕ‡¿<€1âs Ë+Œ—?dÁI@H¼ø’iµDúîSýI•mŒ˜ÃWXë^;&¹‰|˘LQžcZIeˆÍìÞù:¶¥ã b“RÉUÍHõÛ…lǰw…µý^L#-“M.6Ê•Žòx‹-5ä¢î€¿üÐ>ÜÚ±Z9ÿ[¨5°íkùv.y¹]ï15º¥n¡4°ŠúrñÏ{Æ9@e‚Þì= ¸Vn§Iæ§6vA&kål;ù|žs14§(nzoÜ8v¬Áër,ÆJªtàu"¼5ÄFt+l1ÒlÊ=ÁÅÔŽqÔµ«áCjÙ¼rP\°‰¸¢€òÁ DBh€(¢‹-±fáûŒŒ~1±E–Ò ³—v ôl H›ˆù‚ ÏøCfû†¡Ï¨€ %?¢ÏÈÄQû‹?€±øÛö$ŽÂñð(UŽÈã²  ŽQ#É£³X@u0ŽÎ€q‡äúM(|Qds 40˜P!ÀhcîL ª<êÕ@L²-“I¨¯Š|Âi¥S¡Ô©,"aJ¥HéRiòºVŸÓéõ>ŠGnR}Urák°‹–%o„HäÑÔ¢;½Þu(¿.­À©TÉT†[ÉÀ§‘xÄúÛ‹ƒáõ`,;þaQ‘ÈçÓxÜša( [ ÑI…~B â<¸À¾EQ!Õ[ê,Rû\"Sh¶ýIÖ¿ñ•ܰÊ€ô`+EÚ-Ÿ•xduû0×±D¤9 ä#¦þ±¿iM²•:ͪž{ÀÉêt§» ºtò»Š[Ú/È#lÀL:òŒ÷‚?q€¸¨ÆKÛìe«I4w¾Áíz)¦èÜka>Ò¨"ž¨¼;Ÿi﫲ŸñX[]Äv(;Á€7L‹hˆÅ„IÉ3‡f@*; ˜mÞ‹6­#Öƒv VE(7Ë[áÀåOÛíSÑf†e"¡¢$ÙÀ¼.†õ‡´§…@2C¤©'+çhý Ò/}”§4ØÐTYÏâFTK *8DmL!",TI3P)E|”&3vGÜÙ ŠŒ•vŸ‹’©CcÒ /ÔÊ\–ép±á?#´ÖëH))£²Ä@yZKºmŠýk7ňÐM‹õP¨½ôèú°p 9?@ô¿ ‘šp~4—ÀFÑÙ!;äŒÈ…ñrt+¥Ê’ˆÂ^›L‚‡ñöä¼Pê8Cgh“"Ò ‚ÛQJ!CeêÂF~Ì”+!¤<ˆ9pÿ‰Òc“¬ä‡<ˆqãy‹Í}D€ÀÃæwèÈðÆ¥•)ÐÚ>0±ØƒFBó_Rû@ÒÍ_ Ÿâ 5*Ø> ˜ÓX<¦½²È"òsjBCÁldåÒ¼@BMnY¥;ŽRE$£Kö“œÓˆAPÑ©®¢´ú)qÌÒÀ‡ñ ᥶S¸>?‘Ù@t4И[ÔüéûÁuhà[{ˆboµú?0¯Šæa @Â׆ö¢3÷d$u96Ù>œx.ÓU„#*ÐË`Jý¯b«€DÎË”u¢VÁÛ^ÂêûlY‘Nô …S©œ^š±ÔÃqÀíNe¦îÎqû5ènñ4ÙaícAU˜œ¦4ÙO§ãùTD~f™r‰K¡Ðèº#^c䙕nž[Ì8¯8‡¸Ìå¤# ë›)ˆÒ3Å!Å/…• À)å˜EˆÐB~F=CWÉz|è'#m…Šœ“X¿+Ÿž“UZM¬à{zEÑŠ1_?£‡úFð@½uËDS$q@p(ÿgYü×›5´wJUÌP8Äç¶ ì>˵× «V‘JðÒLÜM«µ5æy[}Ñ ±qFü0„ƒÑCûØóóGÓÉe4,V'S„}<²´÷Þˆ”åè­3¿¦L mLôƒºcñT¥ ~OÊv²œd^µ²ÊÐñùœdŒ¿à4ÊFa!öîM PÇ}yc-ñˆYó_ úTЋêàÞùÀ×oOìç¨jæ&?Ç9ßì" Žð ¸“´ˆo&º‚åQ‹Ð3 ¾â »—I:Ê€ ŽŸ‚â´<‡·² nt™(u8J9$8,ïÔïRpO@c “¯^Ö2¬¹Jx,Ÿƒx2Èv“ ë® 'ÈŒ‚RÇ[C¹áÜd~(ã òB© 6ÓÙ™|á~éŠWrI¥˜"õo@ÕKqbMÒï 9ͪ8?Ó/ÑÓ7žt^;ñ0×0‡ýfª¡>rUu»ÄÄ=¬òÆöü:¦¹õ¤Kðóœò*F¿ Ö]FúvoXQ ±[”üO“&fÏ!Ž¿{'!ùíDy÷¢¼ãC¼nǵOIš; gM‡Þ)$j¨NT>—_À#b^âËôÙl*ìÞèö&&Ò$#¦î0¢ìÖæòRïz·*LÍ!úÔ¤dœáòeŒSkÚ¢ â#žýLgŽ.Çç0ûn²®…¢geœš§Ì’ã c‰IÍZóÃb"4EÜÕ¥)ìÞ›®FÙ hÐ.ä¨ä‹.®%HJéδždÞÞêOÈi0,©‡ã¨ÔÜM´„É` jT'CbBQgâÀ%€Î¢]§ÅRKŒ\À–ú=ï ö€ ¤$+,"BQç®´#Îläˆ,s‚t>â …-–½ë SË×â-ìvOf¾¯Â'Dv.K~ µKD"£¨ü«ôÀB:VcÂF ¶uGÌFDýðìs€j÷ξ­-–Ä$aŽù-X2ΚøÁü°®:qNö0§Ð‚HÜ“!ö¬"TYN:ÕcqÃ2yÊö(«zOIb p J”r¬¸B”L±x/2"°An~þgôô¨@Ûéö0ïØŸŽ‚Ë¯88޳‡â†$ ¤/Øß®@°„Íë¦ñ 2“HCd6Kȼ”MÖä@V|t­Â× xõ'0z ˜$Ì@€Nº\,ïE1>³-R[T§²O"¬ÂeÜÚDØò.;ãö@mvQÄd³ŠC$ü­ÆŽ¡1 Z ´±R#¬R»Eü#&‚<±·˜„bQÄY£@ÚO³( ±²†°î% fAg‚Ìù ) ÷ÆhmC´tEÀ8•*¶°‰lËÂ>×i`ßêð[c~£éèÐ(–¶B((ù†šù.¼Mé¸qÐúš)OÆÉ`•d6Lnø¢°g 7Ǭ¤/+¬¶Šòš®r|y -?"IYàv øí¡öƱ€r­ª;°:ÙcÎà ÊÆ’Ã" ¹ (ʘð¾!þèèŠ,  ^- Ð, @, z, ‚, (=s‡H n- HHàÛ»ÛÔÚ(Ø]Ø£ÓUÔ2Ò–×ÕPÔïÔRØfÚìÚmŠèÛ£·w’ŸjüBŸôê&½¼”Kj›> Š Üë BÆ .¡ /Users/jakepetroules/OpenSource/qt/qbs/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif HLinomntrRGB XYZ Î 1acspMSFTIEC sRGBöÖÓ-HP cprtP3desc„lwtptðbkptrXYZgXYZ,bXYZ@dmndTpdmddĈvuedL†viewÔ$lumiømeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ óQÌXYZ XYZ o¢8õXYZ b™·…ÚXYZ $ „¶ÏdescIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view¤þ_.ÏíÌ \žXYZ L VPWçmeassig CRT curv #(-27;@EJOTY^chmrw|†‹•šŸ¤©®²·¼ÁÆËÐÕÛàåëðöû %+28>ELRY`gnu|ƒ‹’š¡©±¹ÁÉÑÙáéòú &/8AKT]gqz„Ž˜¢¬¶ÁËÕàëõ !-8COZfr~Š–¢®ºÇÓàìù -;HUcq~Œš¨¶ÄÓáðþ +:IXgw†–¦µÅÕåö'7HYj{Œ¯ÀÑãõ+=Oat†™¬¿Òåø 2FZn‚–ª¾Òçû  % : O d y ¤ º Ï å û  ' = T j ˜ ® Å Ü ó " 9 Q i € ˜ ° È á ù  * C \ u Ž § À Ù ó & @ Z t Ž © Ã Þ ø.Id›¶Òî %A^z–³Ïì &Ca~›¹×õ1OmŒªÉè&Ed„£Ãã#Ccƒ¤Åå'Ij‹­Îð4Vx›½à&Il²ÖúAe‰®Ò÷@eНÕú Ek‘·Ý*QwžÅì;cвÚ*R{£ÌõGp™Ãì@j”¾é>i”¿ê  A l ˜ Ä ð!!H!u!¡!Î!û"'"U"‚"¯"Ý# #8#f#”#Â#ð$$M$|$«$Ú% %8%h%—%Ç%÷&'&W&‡&·&è''I'z'«'Ü( (?(q(¢(Ô))8)k))Ð**5*h*›*Ï++6+i++Ñ,,9,n,¢,×- -A-v-«-á..L.‚.·.î/$/Z/‘/Ç/þ050l0¤0Û11J1‚1º1ò2*2c2›2Ô3 3F33¸3ñ4+4e4ž4Ø55M5‡5Â5ý676r6®6é7$7`7œ7×88P8Œ8È99B99¼9ù:6:t:²:ï;-;k;ª;è<' >`> >à?!?a?¢?â@#@d@¦@çA)AjA¬AîB0BrBµB÷C:C}CÀDDGDŠDÎEEUEšEÞF"FgF«FðG5G{GÀHHKH‘H×IIcI©IðJ7J}JÄK KSKšKâL*LrLºMMJM“MÜN%NnN·OOIO“OÝP'PqP»QQPQ›QæR1R|RÇSS_SªSöTBTTÛU(UuUÂVV\V©V÷WDW’WàX/X}XËYYiY¸ZZVZ¦Zõ[E[•[å\5\†\Ö]']x]É^^l^½__a_³``W`ª`üaOa¢aõbIbœbðcCc—cëd@d”dée=e’eçf=f’fèg=g“géh?h–hìiCišiñjHjŸj÷kOk§kÿlWl¯mm`m¹nnknÄooxoÑp+p†pàq:q•qðrKr¦ss]s¸ttptÌu(u…uáv>v›vøwVw³xxnxÌy*y‰yçzFz¥{{c{Â|!||á}A}¡~~b~Â#„å€G€¨ kÍ‚0‚’‚ôƒWƒº„„€„ã…G…«††r†×‡;‡ŸˆˆiˆÎ‰3‰™‰þŠdŠÊ‹0‹–‹üŒcŒÊ1˜ÿŽfŽÎ6žnÖ‘?‘¨’’z’ã“M“¶” ”Š”ô•_•É–4–Ÿ— —u—à˜L˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ ¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/xcode/0000755000175100017510000000000015232633614022414 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs0000644000175100017510000000452715232633614025701 0ustar runnerrunnerProject { property var sdks: {} Product { Depends { name: "xcode" } consoleApplication: { console.info("Developer directory: " + xcode.developerPath); console.info("SDK: " + xcode.sdk); console.info("Target devices: " + xcode.targetDevices.join(", ")); console.info("SDK name: " + xcode.sdkName); console.info("SDK version: " + xcode.sdkVersion); console.info("Latest SDK name: " + xcode.latestSdkName); console.info("Latest SDK version: " + xcode.latestSdkVersion); console.info("Available SDK names: " + xcode.availableSdkNames.join(", ")); console.info("Available SDK versions: " + xcode.availableSdkVersions.join(", ")); var targetOsToKey = function(targetOS) { if (targetOS.includes("ios")) return "iphoneos"; if (targetOS.includes("ios-simulator")) return "iphonesimulator"; if (targetOS.includes("macos")) return "macosx"; if (targetOS.includes("tvos")) return "appletvos"; if (targetOS.includes("tvos-simulator")) return "appletvsimulator"; if (targetOS.includes("watchos")) return "watchos"; if (targetOS.includes("watchos-simulator")) return "watchossimulator"; throw "Unsupported OS" + targetOS; } var actualList = project.sdks[targetOsToKey(qbs.targetOS)]; console.info("Actual SDK list: " + actualList.join(", ")); var msg = "Unexpected SDK list [" + xcode.availableSdkVersions.join(", ") + "]"; var testArraysEqual = function(a, b) { if (!a || !b || a.length !== b.length) { throw msg; } for (var i = 0; i < a.length; ++i) { var version1 = a[i].split('.'); var version2 = b[i].split('.'); for (var j = 0; j < version1.length; ++j) { if (version1[j] !== version2[j]) throw msg; } } } testArraysEqual(actualList, xcode.availableSdkVersions); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/0000755000175100017510000000000015232633614024216 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/main.m0000644000175100017510000000053615232633614025324 0ustar runnerrunner#import int main() { NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary]; BOOL success = [[infoPlist objectForKey:@"QBS"] isEqualToString:@"org.qt-project.qbs.testdata.embedInfoPlist"]; fprintf(success ? stdout : stderr, "%s\n", [[infoPlist description] UTF8String]); return success ? 0 : 1; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs0000644000175100017510000000241515232633614027633 0ustar runnerrunnerProject { CppApplication { Depends { name: "lib" } Depends { name: "mod" } name: "app" consoleApplication: true files: ["main.m"] cpp.frameworks: ["Foundation"] cpp.rpaths: [cpp.rpathOrigin] cpp.minimumMacosVersion: "10.6" bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist" }) install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } name: "lib" bundle.isBundle: false bundle.embedInfoPlist: true files: ["main.m"] cpp.frameworks: ["Foundation"] cpp.sonamePrefix: "@rpath" bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist.dylib" }) install: true installDir: "" } LoadableModule { Depends { name: "cpp" } name: "mod" bundle.isBundle: false bundle.embedInfoPlist: true files: ["main.m"] installDir: "" cpp.frameworks: ["Foundation"] bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist.bundle" }) Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/0000755000175100017510000000000015232633614025230 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/en.lproj/0000755000175100017510000000000015232633614026757 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/en.lproj/EnglishResource0000644000175100017510000000000015232633614031771 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/Widget.h0000644000175100017510000000234615232633614026631 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo(); qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/Widget.cpp0000644000175100017510000000236315232633614027163 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs0000644000175100017510000000123615232633614031657 0ustar runnerrunnerProject { property bool includeHeaders: true Library { Depends { name: "cpp" } Depends { name: "bundle" } property bool isShallow: { console.info("isShallow: " + bundle.isShallow); return bundle.isShallow; } name: "Widget" bundle.isBundle: true bundle.publicHeaders: project.includeHeaders ? ["Widget.h"] : undefined bundle.privateHeaders: project.includeHeaders ? ["WidgetPrivate.h"] : base bundle.resources: ["BaseResource", "en.lproj/EnglishResource"] files: ["Widget.cpp"].concat(bundle.publicHeaders || []).concat(bundle.privateHeaders || []) } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/WidgetPrivate.h0000644000175100017510000000233215232633614030157 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/frameworkStructure/BaseResource0000644000175100017510000000000015232633614027523 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/0000755000175100017510000000000015232633614025104 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c0000644000175100017510000000003115232633614026166 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs0000644000175100017510000000223315232633614031405 0ustar runnerrunnerimport qbs.BundleTools import qbs.TextFile CppApplication { Depends { name: "bundle" } cpp.minimumMacosVersion: "10.7" files: ["main.c", "ByteArray-Info.plist"] type: base.concat(["txt_output"]) Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: true bundle.identifierPrefix: "com.test" } Rule { inputs: ["aggregate_infoplist"] Artifact { filePath: input.fileName + ".out" fileTags: ["txt_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName + " from " + input.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var plist = new BundleTools.infoPlistContents(input.filePath); var content = plist["DataKey"]; var int8view = new Uint8Array(content); file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(String.fromCharCode.apply(null, int8view)); file.close(); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist0000644000175100017510000000054615232633614030761 0ustar runnerrunner DataKey VGhlIGRhdGEgdmFsdWU= StringKey The string value qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/0000755000175100017510000000000015232633614022772 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs0000644000175100017510000000061615232633614025164 0ustar runnerrunnerProduct { Depends { name: "cpp" } consoleApplication: true type: ["application"] condition: qbs.targetOS.includes("darwin") Group { cpp.automaticReferenceCounting: true files: ["arc.m", "arc.mm"] } Group { cpp.automaticReferenceCounting: false files: ["mrc.m", "mrc.mm"] } files: "main.m" cpp.minimumMacosVersion: "10.7" } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/arc.m0000644000175100017510000000010715232633614023713 0ustar runnerrunner#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/arc.mm0000644000175100017510000000010715232633614024070 0ustar runnerrunner#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/main.m0000644000175100017510000000013615232633614024074 0ustar runnerrunner#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/mrc.mm0000644000175100017510000000010515232633614024102 0ustar runnerrunner#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/objc-arc/mrc.m0000644000175100017510000000010515232633614023725 0ustar runnerrunner#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoPlistVariables/0000755000175100017510000000000015232633614025112 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoPlistVariables/Info.plist0000644000175100017510000000156615232633614027072 0ustar runnerrunner Curly ${EXECUTABLE_NAME} Braces $(EXECUTABLE_NAME) At @EXECUTABLE_NAME@ CurlyMult ${EXECUTABLE_NAME}_${PRODUCT_NAME} BracesMult $(EXECUTABLE_NAME)_$(PRODUCT_NAME) AtMult @EXECUTABLE_NAME@_@PRODUCT_NAME@ CurlyNested ${${EXE}_NAME} BracesNested ${${EXE}_NAME} WithDefault ${NON_EXISTING:default=DEFAULT} qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoPlistVariables/main.c0000644000175100017510000000003115232633614026174 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs0000644000175100017510000000063415232633614031424 0ustar runnerrunnerCppApplication { Depends { name: "bundle" } cpp.minimumMacosVersion: "10.7" files: ["main.c", "Info.plist"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: true bundle.identifierPrefix: "com.test" bundle.extraEnv: { var result = original; result["EXE"] = "EXECUTABLE"; return result; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign/0000755000175100017510000000000015232633614023105 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs0000644000175100017510000000437415232633614025417 0ustar runnerrunnerimport "../multiarch-helpers.js" as Helpers Project { name: "p" // we do not have the access to xcode version in qbs.architectures so we need to pass it here property string xcodeVersion property bool isBundle: true property bool enableSigning: true property bool multiArch: false property bool multiVariant: false CppApplication { name: "A" version: "1.0.0" bundle.isBundle: project.isBundle files: "app.cpp" codesign.enableCodeSigning: project.enableSigning codesign.signingType: "ad-hoc" install: true installDir: "" qbs.architectures: multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } DynamicLibrary { Depends { name: "cpp" } name: "B" version: "1.0.0" bundle.isBundle: project.isBundle files: "app.cpp" codesign.enableCodeSigning: project.enableSigning codesign.signingType: "ad-hoc" install: true installDir: "" qbs.architectures: multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } LoadableModule { Depends { name: "cpp" } name: "C" version: "1.0.0" bundle.isBundle: project.isBundle files: "app.cpp" codesign.enableCodeSigning: project.enableSigning codesign.signingType: "ad-hoc" install: true installDir: "" qbs.architectures: multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } StaticLibrary { Depends { name: "cpp" } name: "D" version: "1.0.0" bundle.isBundle: project.isBundle files: "app.cpp" codesign.enableCodeSigning: project.enableSigning codesign.signingType: "ad-hoc" install: true installDir: "" qbs.architectures: multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign/app.cpp0000644000175100017510000000003115232633614024363 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/0000755000175100017510000000000015232633614024731 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/lib.c0000644000175100017510000000040215232633614025637 0ustar runnerrunner#include int foo() { #ifdef __i386__ printf("Hello from " VARIANT " i386\n"); #endif #ifdef __x86_64__ printf("Hello from " VARIANT " x86_64\n"); #endif #ifdef __arm64__ printf("Hello from " VARIANT " arm64\n"); #endif return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs0000644000175100017510000001365515232633614031071 0ustar runnerrunnerimport qbs.Utilities import "../multiarch-helpers.js" as Helpers Project { minimumQbsVersion: "1.8" condition: xcodeVersion property string xcodeVersion CppApplication { Depends { name: "singlelib" } Depends { name: "bundle" } property bool isShallow: { console.info("isShallow: " + bundle.isShallow); return bundle.isShallow; } name: "singleapp" targetName: "singleapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" cpp.minimumIosVersion: "8.0" // Turn off multiplexing aggregate: false multiplexByQbsProperties: [] qbs.architecture: Helpers.getNewArch(qbs, project.xcodeVersion) install: true installDebugInformation: false installDir: "" } CppApplication { Depends { name: "singlelib" } Depends { name: "bundle" } name: "singleapp_agg" targetName: "singleapp_agg" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" cpp.minimumIosVersion: "8.0" // Force aggregation when not needed aggregate: true qbs.architectures: [Helpers.getNewArch(qbs, project.xcodeVersion)] qbs.buildVariants: ["release"] install: true installDebugInformation: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "singlelib" targetName: "singlelib" files: ["lib.c"] cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] // Turn off multiplexing aggregate: false multiplexByQbsProperties: [] qbs.architecture: Helpers.getNewArch(qbs, project.xcodeVersion) install: true installDebugInformation: false installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "multiapp" targetName: "multiapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" cpp.minimumIosVersion: "8.0" install: true installDebugInformation: false installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "fatmultiapp" targetName: "fatmultiapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" cpp.minimumIosVersion: "8.0" qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.architecture: Helpers.getNewArch(qbs, project.xcodeVersion) multiplexByQbsProperties: Helpers.enableOldArch(qbs, project.xcodeVersion) ? ["architectures", "buildVariants"] : ["buildVariants"] qbs.buildVariants: "debug" install: true installDebugInformation: false installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "fatmultiappmultivariant" targetName: "fatmultiappmultivariant" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" cpp.minimumIosVersion: "8.0" qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["debug", "profiling"] install: true installDebugInformation: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilib" targetName: "multilib" files: ["lib.c"] cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["release", "debug", "profiling"] install: true installDebugInformation: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilib-no-release" targetName: "multilib-no-release" files: ["lib.c"] cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["debug", "profiling"] install: true installDebugInformation: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "multilibB" } name: "multilibA" files: ["lib.c"] cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["debug", "profiling"] install: true installDebugInformation: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilibB" files: ["lib.c"] cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["debug", "profiling"] install: true installDebugInformation: false installDir: "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/app.c0000644000175100017510000000005715232633614025657 0ustar runnerrunnerextern int foo(); int main() { return foo(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign-destination-directory/0000755000175100017510000000000015232633614027426 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign-destination-directory/main.c0000644000175100017510000000012415232633614030513 0ustar runnerrunner#include int main(void) { printf("Hello, World!\n"); return 0; } ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign-destination-directory/project-build-directory.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/codesign-destination-directory/project-build-direct0000644000175100017510000000033215232633614033362 0ustar runnerrunnerProject { CppApplication { name: "app" files: ["main.c"] codesign.enableCodeSigning: true codesign.signingType: "ad-hoc" destinationDirectory: project.buildDirectory } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/lipo-symlinks/0000755000175100017510000000000015232633614024124 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/lipo-symlinks/lib.cpp0000644000175100017510000000003415232633614025373 0ustar runnerrunnerint foo() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/lipo-symlinks/lipo-symlinks.qbs0000644000175100017510000000122715232633614027447 0ustar runnerrunnerimport "../multiarch-helpers.js" as Helpers Project { name: "p" // we do not have the access to xcode version in qbs.architectures so we need to pass it here property string xcodeVersion property bool multiArch: false property bool multiVariant: false DynamicLibrary { Depends { name: "cpp" } name: "A" version: "1.2.3" bundle.isBundle: false files: "lib.cpp" install: true installDir: "" qbs.architectures: multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } }qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/privacymanifest/0000755000175100017510000000000015232633614024516 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/privacymanifest/privacymanifest.qbs0000644000175100017510000000110015232633614030421 0ustar runnerrunnerProject { Library { Depends { name: "cpp" } Depends { name: "bundle" } property bool isShallow: { console.info("isShallow: " + bundle.isShallow); return bundle.isShallow; } Group { condition: qbs.targetOS.includes("darwin") files: ["PrivacyInfo.xcprivacy"] fileTags: ["bundle.input.privacymanifest"] } name: "Lib" bundle.isBundle: true bundle.publicHeaders: ["Lib.h"] files: ["Lib.cpp"].concat(bundle.publicHeaders || []) } }qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/privacymanifest/Lib.cpp0000644000175100017510000000236715232633614025740 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/privacymanifest/Lib.h0000644000175100017510000000234615232633614025402 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo(); qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/privacymanifest/PrivacyInfo.xcprivacy0000644000175100017510000000065515232633614030707 0ustar runnerrunner NSPrivacyTracking NSPrivacyTrackingDomains NSPrivacyAccessedAPITypes NSPrivacyCollectedDataTypes qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/multiarch-helpers.js0000644000175100017510000000641215232633614025303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Host = require("qbs.Host"); var Utilities = require("qbs.Utilities"); // Typically, multiple architectures are used for migration from "old" arch to a "new" one // For example: x86 -> x86_64 on macOS, armv7 -> arm64 on iOS function enableOldArch(qbs, xcodeVersion) { return qbs.targetOS.includes("macos") && xcodeVersion && (Utilities.versionCompare(xcodeVersion, "10") < 0 || Utilities.versionCompare(xcodeVersion, "12.2") >= 0) || (qbs.targetOS.includes("ios") && !qbs.targetOS.includes("ios-simulator") && Utilities.versionCompare(xcodeVersion, "14") < 0) } function getNewArch(qbs, xcodeVersion) { const isNewXcode = xcodeVersion && Utilities.versionCompare(xcodeVersion, "12.2") >= 0; if (qbs.targetOS.includes("macos")) return isNewXcode ? "arm64" : "x86_64"; else if (qbs.targetOS.includes("ios-simulator")) return "x86_64"; else if (qbs.targetOS.includes("ios")) return "arm64" else if (qbs.targetOS.includes("tvos")) return "arm64" else if (qbs.targetOS.includes("watchos")) return "armv7k" throw "unsupported targetOS: " + qbs.targetOS; } function getOldArch(qbs, xcodeVersion) { if (qbs.targetOS.includes("macos")) return xcodeVersion && Utilities.versionCompare(xcodeVersion, "12.2") >= 0 ? "x86_64" : "x86"; else if (qbs.targetOS.includes("ios-simulator")) return "x86" else if (qbs.targetOS.includes("ios")) return "armv7a" throw "unsupported targetOS: " + qbs.targetOS; } function getArchitectures(qbs, xcodeVersion) { return enableOldArch(qbs, xcodeVersion) ? [getOldArch(qbs, xcodeVersion), getNewArch(qbs, xcodeVersion)] : [getNewArch(qbs, xcodeVersion)]; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/0000755000175100017510000000000015232633614023505 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/deep.json0000644000175100017510000001046415232633614025322 0ustar runnerrunner{ "directories": [ "Contents", "Contents/_CodeSignature", "Contents/Applications", "Contents/Applications/F.app", "Contents/Applications/F.app/Contents", "Contents/Applications/F.app/Contents/_CodeSignature", "Contents/Applications/F.app/Contents/MacOS", "Contents/Applications/F.app/Contents/Resources", "Contents/Executables", "Contents/Frameworks", "Contents/Frameworks/A.framework", "Contents/Frameworks/A.framework/Versions", "Contents/Frameworks/A.framework/Versions/A", "Contents/Frameworks/A.framework/Versions/A/_CodeSignature", "Contents/Frameworks/A.framework/Versions/A/Headers", "Contents/Frameworks/A.framework/Versions/A/PrivateHeaders", "Contents/Frameworks/A.framework/Versions/A/Resources", "Contents/Frameworks/B.framework", "Contents/Frameworks/B.framework/Versions", "Contents/Frameworks/B.framework/Versions/A", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature", "Contents/Frameworks/B.framework/Versions/A/Headers", "Contents/Frameworks/B.framework/Versions/A/PrivateHeaders", "Contents/Frameworks/B.framework/Versions/A/Resources", "Contents/Headers", "Contents/MacOS", "Contents/PlugIns", "Contents/PlugIns/C.bundle", "Contents/PlugIns/C.bundle/Contents", "Contents/PlugIns/C.bundle/Contents/_CodeSignature", "Contents/PlugIns/C.bundle/Contents/Headers", "Contents/PlugIns/C.bundle/Contents/MacOS", "Contents/PlugIns/C.bundle/Contents/PrivateHeaders", "Contents/PlugIns/C.bundle/Contents/Resources", "Contents/PrivateHeaders", "Contents/Resources" ], "files": [ "Contents/_CodeSignature/CodeResources", "Contents/Applications/F.app/Contents/_CodeSignature/CodeResources", "Contents/Applications/F.app/Contents/Info.plist", "Contents/Applications/F.app/Contents/MacOS/F", "Contents/Applications/F.app/Contents/PkgInfo", "Contents/Applications/F.app/Contents/Resources/resource.txt", "Contents/Executables/G", "Contents/Frameworks/A.framework/Versions/A/_CodeSignature/CodeResources", "Contents/Frameworks/A.framework/Versions/A/A", "Contents/Frameworks/A.framework/Versions/A/Headers/dummy.h", "Contents/Frameworks/A.framework/Versions/A/PrivateHeaders/dummy_p.h", "Contents/Frameworks/A.framework/Versions/A/Resources/Info.plist", "Contents/Frameworks/A.framework/Versions/A/Resources/resource.txt", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeResources", "Contents/Frameworks/B.framework/Versions/A/B", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeDirectory", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeRequirements", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeRequirements-1", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeResources", "Contents/Frameworks/B.framework/Versions/A/_CodeSignature/CodeSignature", "Contents/Frameworks/B.framework/Versions/A/Headers/dummy.h", "Contents/Frameworks/B.framework/Versions/A/PrivateHeaders/dummy_p.h", "Contents/Frameworks/B.framework/Versions/A/Resources/Info.plist", "Contents/Frameworks/B.framework/Versions/A/Resources/resource.txt", "Contents/Frameworks/libD.dylib", "Contents/Frameworks/libE.a", "Contents/Headers/dummy.h", "Contents/Info.plist", "Contents/MacOS/MainApp", "Contents/PkgInfo", "Contents/PlugIns/C.bundle/Contents/_CodeSignature/CodeResources", "Contents/PlugIns/C.bundle/Contents/Headers/dummy.h", "Contents/PlugIns/C.bundle/Contents/Info.plist", "Contents/PlugIns/C.bundle/Contents/MacOS/C", "Contents/PlugIns/C.bundle/Contents/PrivateHeaders/dummy_p.h", "Contents/PlugIns/C.bundle/Contents/Resources/resource.txt", "Contents/PrivateHeaders/dummy_p.h", "Contents/Resources/resource.txt" ], "symlinks": [ "Contents/Frameworks/A.framework/A", "Contents/Frameworks/A.framework/Headers", "Contents/Frameworks/A.framework/PrivateHeaders", "Contents/Frameworks/A.framework/Resources", "Contents/Frameworks/A.framework/Versions/Current", "Contents/Frameworks/B.framework/B", "Contents/Frameworks/B.framework/Headers", "Contents/Frameworks/B.framework/PrivateHeaders", "Contents/Frameworks/B.framework/Resources", "Contents/Frameworks/B.framework/Versions/Current" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/dummy_p.h0000644000175100017510000000001515232633614025324 0ustar runnerrunner#pragma once qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/main-bundle.qbs0000644000175100017510000001355615232633614026421 0ustar runnerrunnerimport "../multiarch-helpers.js" as Helpers Project { readonly property bool enableCodeSigning: !qbs.targetOS.includes("ios") || qbs.targetOS.includes("ios-simulator") property bool multiplexArchitectures: false property bool multiplexBuildVariants: false property string xcodeVersion Product { Depends { name: "bundle" } condition: { console.info("bundle.isShallow: " + bundle.isShallow); console.info("qbs.targetOS: " + qbs.targetOS); console.info("enableCodeSigning: " + project.enableCodeSigning); return false; } } // main bundle Application { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "A" } // framework Depends { name: "B" } // static framework Depends { name: "C" } // loadable module Depends { name: "D" } // dynamic library Depends { name: "E" } // static library Depends { name: "F" } // application Depends { name: "G" } // executable Depends { name: "H"; bundle.isForMainBundle: false; } // executable, not copied name: "MainApp" bundle.isBundle: true bundle.isMainBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] installDir: "" } DynamicLibrary { Depends { name: "cpp" } name: "A" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } StaticLibrary { Depends { name: "cpp" } name: "B" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] bundle.isForMainBundle: true // static library is not copied by default, override codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } LoadableModule { Depends { name: "cpp" } name: "C" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] // qbs.buildVariants: project.isMultiplexed ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } DynamicLibrary { Depends { name: "cpp" } name: "D" bundle.isBundle: false codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } StaticLibrary { Depends { name: "cpp" } name: "E" bundle.isBundle: false bundle.isForMainBundle: true codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } // bundle application Application { Depends { name: "cpp" } name: "F" bundle.isBundle: true bundle.resources: ["resource.txt"] codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } // non-bundle application Application { Depends { name: "cpp" } name: "G" bundle.isBundle: false codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } // non-bundle application Application { Depends { name: "cpp" } name: "H" bundle.isBundle: false codesign.enableCodeSigning: project.enableCodeSigning qbs.architectures: project.multiplexArchitectures ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] qbs.buildVariants: project.multiplexBuildVariants ? ["debug", "release"] : [] files: ["dummy.c"] install: false installDir: "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/dummy.h0000644000175100017510000000003215232633614025004 0ustar runnerrunner#pragma once int main(); qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/shallow-signed.json0000644000175100017510000000417415232633614027326 0ustar runnerrunner{ "directories": [ "_CodeSignature", "Applications", "Applications/F.app", "Applications/F.app/_CodeSignature", "Executables", "Frameworks", "Frameworks/A.framework", "Frameworks/A.framework/_CodeSignature", "Frameworks/A.framework/Headers", "Frameworks/A.framework/PrivateHeaders", "Frameworks/B.framework", "Frameworks/B.framework/_CodeSignature", "Frameworks/B.framework/Headers", "Frameworks/B.framework/PrivateHeaders", "Headers", "PlugIns", "PlugIns/C.bundle", "PlugIns/C.bundle/_CodeSignature", "PlugIns/C.bundle/Headers", "PlugIns/C.bundle/PrivateHeaders", "PrivateHeaders" ], "files": [ "MainApp", "Info.plist", "PkgInfo", "resource.txt", "_CodeSignature/CodeResources", "Applications/F.app/_CodeSignature/CodeResources", "Applications/F.app/F", "Applications/F.app/Info.plist", "Applications/F.app/PkgInfo", "Applications/F.app/resource.txt", "Executables/G", "Frameworks/A.framework/_CodeSignature/CodeResources", "Frameworks/A.framework/A", "Frameworks/A.framework/Headers/dummy.h", "Frameworks/A.framework/Info.plist", "Frameworks/A.framework/PrivateHeaders/dummy_p.h", "Frameworks/A.framework/resource.txt", "Frameworks/B.framework/_CodeSignature/CodeDirectory", "Frameworks/B.framework/_CodeSignature/CodeRequirements", "Frameworks/B.framework/_CodeSignature/CodeRequirements-1", "Frameworks/B.framework/_CodeSignature/CodeResources", "Frameworks/B.framework/_CodeSignature/CodeSignature", "Frameworks/B.framework/B", "Frameworks/B.framework/Headers/dummy.h", "Frameworks/B.framework/Info.plist", "Frameworks/B.framework/PrivateHeaders/dummy_p.h", "Frameworks/B.framework/resource.txt", "Frameworks/libD.dylib", "Frameworks/libE.a", "Headers/dummy.h", "PlugIns/C.bundle/_CodeSignature/CodeResources", "PlugIns/C.bundle/C", "PlugIns/C.bundle/Headers/dummy.h", "PlugIns/C.bundle/Info.plist", "PlugIns/C.bundle/PrivateHeaders/dummy_p.h", "PlugIns/C.bundle/resource.txt", "PrivateHeaders/dummy_p.h" ], "symlinks": [] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/dummy.c0000644000175100017510000000003115232633614024776 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/shallow-unsigned.json0000644000175100017510000000304615232633614027666 0ustar runnerrunner{ "directories": [ "Applications", "Applications/F.app", "Executables", "Frameworks", "Frameworks/A.framework", "Frameworks/A.framework/Headers", "Frameworks/A.framework/PrivateHeaders", "Frameworks/B.framework", "Frameworks/B.framework/Headers", "Frameworks/B.framework/PrivateHeaders", "Headers", "PlugIns", "PlugIns/C.bundle", "PlugIns/C.bundle/Headers", "PlugIns/C.bundle/PrivateHeaders", "PrivateHeaders" ], "files": [ "MainApp", "Info.plist", "PkgInfo", "resource.txt", "Applications/F.app/F", "Applications/F.app/Info.plist", "Applications/F.app/PkgInfo", "Applications/F.app/resource.txt", "Executables/G", "Frameworks/A.framework/A", "Frameworks/A.framework/Headers/dummy.h", "Frameworks/A.framework/Info.plist", "Frameworks/A.framework/PrivateHeaders/dummy_p.h", "Frameworks/A.framework/resource.txt", "Frameworks/B.framework/B", "Frameworks/B.framework/Headers/dummy.h", "Frameworks/B.framework/Info.plist", "Frameworks/B.framework/PrivateHeaders/dummy_p.h", "Frameworks/B.framework/resource.txt", "Frameworks/libD.dylib", "Frameworks/libE.a", "Headers/dummy.h", "PlugIns/C.bundle/C", "PlugIns/C.bundle/Headers/dummy.h", "PlugIns/C.bundle/Info.plist", "PlugIns/C.bundle/PrivateHeaders/dummy_p.h", "PlugIns/C.bundle/resource.txt", "PrivateHeaders/dummy_p.h" ], "symlinks": [] } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/main-bundle/resource.txt0000644000175100017510000000000015232633614026063 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/deploymentTarget/0000755000175100017510000000000015232633614024641 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-apple/deploymentTarget/main.c0000644000175100017510000000236415232633614025736 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs0000644000175100017510000000113215232633614027525 0ustar runnerrunnerCppApplication { files: ["main.c"] // Minimum deployment targets that: // - will actually link (as of Xcode 8.1) // - exist for the given architecture(s) cpp.minimumMacosVersion: { if (qbs.architecture === "arm64") return "11.0"; if (qbs.architecture === "x86_64h") return "10.12"; return "10.6"; } cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].includes(qbs.architecture) ? "7.0" : "6.0" cpp.minimumTvosVersion: "9.0" cpp.minimumWatchosVersion: "2.0" cpp.driverFlags: ["-v"] cpp.linkerFlags: ["-v"] } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxqt.cpp0000644000175100017510000013200715232633614022135 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxqt.h" #include "../shared.h" #include #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; TestBlackboxQt::TestBlackboxQt() : TestBlackboxBase (SRCDIR "/testdata-qt", "blackbox-qt") { setNeedsQt(); } std::optional TestBlackboxQt::findShaderTools(bool *hasViewCount) { QDir::setCurrent(testDataDir); rmDirR(relativeBuildDir()); QbsRunParameters checkParams; checkParams.command = "resolve"; checkParams.arguments << QStringLiteral("-f") << "find-shadertools.qbs"; if (runQbs(checkParams) != 0) { qWarning() << "fail to resolve find-shadertools.qbs" << m_qbsStderr; return std::nullopt; } if (!m_qbsStdout.contains("is qt6: ")) { qWarning() << "stdout does not contain 'is qt6:'" << m_qbsStdout; return std::nullopt; } if (!m_qbsStdout.contains("is static qt: ")) { qWarning() << "stdout does not contain 'is static qt:'" << m_qbsStdout; return std::nullopt; } if (!m_qbsStdout.contains("is shadertools present: ")) { qWarning() << "stdout does not contain 'is shadertools present:'" << m_qbsStdout; return std::nullopt; } if (!m_qbsStdout.contains("has viewCount: ")) { qWarning() << "stdout does not contain 'has viewCount:'" << m_qbsStdout; return std::nullopt; } const bool isQt6 = m_qbsStdout.contains("is qt6: true"); const bool isStaticQt = m_qbsStdout.contains("is static qt: true"); const bool isShadertoolsPresent = m_qbsStdout.contains("is shadertools present: true"); if (hasViewCount) { *hasViewCount = m_qbsStdout.contains("has viewCount: true"); } return isQt6 && !isStaticQt && isShadertoolsPresent; } void TestBlackboxQt::addQObjectMacroToGeneratedCppFile() { QDir::setCurrent(testDataDir + "/add-qobject-macro-to-generated-cpp-file"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("moc"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("object.cpp.in", "// ", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("moc"), m_qbsStdout.constData()); } void TestBlackboxQt::autoQrc() { QDir::setCurrent(testDataDir + "/auto-qrc"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app"})), 0); QVERIFY2(m_qbsStdout.simplified().contains("resource data: resource1 resource2"), m_qbsStdout.constData()); } void TestBlackboxQt::cachedQml() { QDir::setCurrent(testDataDir + "/cached-qml"); if ((runQbs() != 0) && m_qbsStderr.contains("Dependency 'Qt.qml' not found for product 'app'")) QSKIP("Qt version too old"); QString dataDir = relativeBuildDir() + "/install-root/data"; QVERIFY2(m_qbsStdout.contains("qmlcachegen must work: true") || m_qbsStdout.contains("qmlcachegen must work: false"), m_qbsStdout.constData()); if (m_qbsStdout.contains("qmlcachegen must work: false") && QFile::exists(dataDir + "/main.cpp")) { // If C++ source files were installed then Qt.qmlcache is not available. See project file. QSKIP("No QML cache files generated."); } QVERIFY(QFile::exists(dataDir + "/main.qmlc")); QVERIFY(QFile::exists(dataDir + "/MainForm.ui.qmlc")); QVERIFY(QFile::exists(dataDir + "/stuff.jsc")); } void TestBlackboxQt::combinedMoc() { QDir::setCurrent(testDataDir + "/combined-moc"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling moc_theobject.cpp")); QVERIFY(!m_qbsStdout.contains("creating amalgamated_moc_theapp.cpp")); QVERIFY(!m_qbsStdout.contains("compiling amalgamated_moc_theapp.cpp")); QbsRunParameters params(QStringList("modules.Qt.core.combineMocOutput:true")); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling moc_theobject.cpp")); QVERIFY(m_qbsStdout.contains("creating amalgamated_moc_theapp.cpp")); QVERIFY(m_qbsStdout.contains("compiling amalgamated_moc_theapp.cpp")); } void TestBlackboxQt::createProject() { QDir::setCurrent(testDataDir + "/create-project"); QVERIFY(QFile::copy(testSourceDir + "/../../../../examples/helloworld-qt/main.cpp", QDir::currentPath() + "/main.cpp")); QbsRunParameters createParams("create-project"); createParams.profile.clear(); QCOMPARE(runQbs(createParams), 0); createParams.expectFailure = true; QVERIFY(runQbs(createParams) != 0); QVERIFY2(m_qbsStderr.contains("already contains qbs files"), m_qbsStderr.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); } void TestBlackboxQt::dbusAdaptors() { QDir::setCurrent(testDataDir + "/dbus-adaptors"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::dbusInterfaces() { QDir::setCurrent(testDataDir + "/dbus-interfaces"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::emscriptenHtml() { QDir::setCurrent(testDataDir + "/emscripten-html"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("is emscripten: false")) QSKIP("Skipping emscripten test"); QVERIFY(m_qbsStdout.contains("is emscripten: true")); const auto relativeInstallRoot = relativeBuildDir() + QStringLiteral("/install-root/"); QVERIFY(!regularFileExists(relativeInstallRoot + QStringLiteral("qtloader.js"))); QVERIFY(!regularFileExists(relativeInstallRoot + QStringLiteral("qtlogo.svg"))); QVERIFY(!regularFileExists(relativeInstallRoot + QStringLiteral("app.html"))); const QStringList params = {QStringLiteral("products.app.generateHtml:true")}; QCOMPARE(runQbs(QbsRunParameters("resolve", params)), 0); QCOMPARE(runQbs(QbsRunParameters("build", params)), 0); QVERIFY(regularFileExists(relativeInstallRoot + QStringLiteral("qtloader.js"))); QVERIFY(regularFileExists(relativeInstallRoot + QStringLiteral("qtlogo.svg"))); QVERIFY(regularFileExists(relativeInstallRoot + QStringLiteral("app.html"))); } void TestBlackboxQt::forcedMoc() { QDir::setCurrent(testDataDir + "/forced-moc"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("using qt4")) QSKIP("Qt version too old"); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStderr.contains("Hello from slot"), m_qbsStderr.constData()); } void TestBlackboxQt::includedMocCpp() { QDir::setCurrent(testDataDir + "/included-moc-cpp"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("using qt4")) QSKIP("Qt version too old"); QVERIFY2(!m_qbsStdout.contains("compiling moc_myobject.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("myobject.cpp", "#include ("generate"); QTest::addColumn("installDir"); QTest::newRow("don't generate") << false << QString(); QTest::newRow("don't generate with install info") << false << QString("blubb"); QTest::newRow("generate only") << true << QString(); QTest::newRow("generate and install") << true << QString("blubb"); } void TestBlackboxQt::metaTypes() { QDir::setCurrent(testDataDir + "/metatypes"); QFETCH(bool, generate); QFETCH(QString, installDir); const QStringList args{"modules.Qt.core.generateMetaTypesFile:" + QString(generate ? "true" : "false"), "modules.Qt.core.metaTypesInstallDir:" + installDir, "-v", "--force-probe-execution"}; QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); const bool canGenerate = m_qbsStdout.contains("can generate"); const bool cannotGenerate = m_qbsStdout.contains("cannot generate"); QVERIFY(canGenerate != cannotGenerate); const bool expectFiles = generate && canGenerate; const bool expectInstalledFiles = expectFiles && !installDir.isEmpty(); QCOMPARE(runQbs(QStringList("--clean-install-root")), 0); const QString productDir = relativeProductBuildDir("mylib"); const QString outputDir = productDir + "/qt.headers"; QVERIFY(!regularFileExists(outputDir + "/moc_unmocableclass.cpp.json")); QCOMPARE(regularFileExists(outputDir + "/moc_mocableclass1.cpp.json"), expectFiles); QCOMPARE(regularFileExists(outputDir + "/mocableclass2.moc.json"), expectFiles); QCOMPARE(regularFileExists(productDir + "/mylib_metatypes.json"), expectFiles); QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/some-prefix/" + installDir + "/mylib_metatypes.json"), expectInstalledFiles); } void TestBlackboxQt::mixedBuildVariants() { QDir::setCurrent(testDataDir + "/mixed-build-variants"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); const bool isMsvc = m_qbsStdout.contains("is msvc: true"); const bool isNotMsvc = m_qbsStdout.contains("is msvc: false"); if (isMsvc) { QVERIFY2(m_qbsStderr.contains("not allowed"), m_qbsStderr.constData()); } else { QVERIFY(isNotMsvc); QVERIFY2(m_qbsStderr.contains("not supported"), m_qbsStderr.constData()); } } void TestBlackboxQt::mocAndCppCombining() { QDir::setCurrent(testDataDir + "/moc-and-cxx-combining"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::mocChangeTracking() { QDir::setCurrent(testDataDir + "/moc-change-tracking"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling moc_class.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("moc-change-tracking.qbs", "// ", ""); QCOMPARE(runQbs(), 0); QVERIFY2( m_qbsStdout.contains("compiling amalgamated_moc-change-tracking.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("moc-change-tracking.qbs"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); } void TestBlackboxQt::mocFlags() { QDir::setCurrent(testDataDir + "/moc-flags"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); QbsRunParameters params; params.expectFailure = true; params.arguments << "Qt.core.mocFlags:-E"; QVERIFY(runQbs(params) != 0); } void TestBlackboxQt::mocCompilerDefines() { QDir::setCurrent(testDataDir + "/moc-compiler-defines"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::mocSameFileName() { QDir::setCurrent(testDataDir + "/moc-same-file-name"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("compiling moc_someclass.cpp"), 2); } void TestBlackboxQt::noMocRunAfterTouchingOtherCppFile() { QDir::setCurrent(testDataDir + "/no-moc-run-after-touching-other-cpp-file"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("moc header1.h")); QVERIFY(m_qbsStdout.contains("moc header2.h")); QVERIFY(m_qbsStdout.contains("compiling moc_header1.cpp")); QVERIFY(m_qbsStdout.contains("compiling moc_header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("linking")); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("moc header1.h")); QVERIFY(!m_qbsStdout.contains("moc header2.h")); QVERIFY(!m_qbsStdout.contains("compiling moc_header1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling moc_header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("linking")); } void TestBlackboxQt::noRelinkOnQDebug() { QFETCH(QString, checkMode); QFETCH(bool, expectRelink); QVERIFY(QDir::setCurrent(testDataDir + "/no-relink-on-qdebug")); rmDirR("default"); // Target check. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("is emscripten: true")) QSKIP("Irrelevant for emscripten"); QVERIFY(m_qbsStdout.contains("is emscripten: false")); QVERIFY2(m_qbsStdout.contains("is GCC: "), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("is MinGW: "), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("is Darwin: "), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("is static qt: "), m_qbsStdout.constData()); const bool isGCCLike = m_qbsStdout.contains("is GCC: true"); const bool isMingw = m_qbsStdout.contains("is MinGW: true"); const bool isDarwin = m_qbsStdout.contains("is Darwin: true"); const bool isStaticQt = m_qbsStdout.contains("is static qt: true"); if (!isGCCLike) expectRelink = false; else if (isMingw || isDarwin || isStaticQt) expectRelink = true; // Initial build. QbsRunParameters params("resolve"); if (isGCCLike && !checkMode.isEmpty()) params.arguments << ("modules.cpp.exportedSymbolsCheckMode:" + checkMode); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("linking"), 2); // Inserting the qDebug() statement will pull in weak symbols. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("lib.cpp", "// qDebug", "qDebug"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("linking"), expectRelink ? 2 : 1); // Also check the opposite case. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("lib.cpp", "qDebug", "// qDebug"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("linking"), expectRelink ? 2 : 1); } void TestBlackboxQt::noRelinkOnQDebug_data() { QTest::addColumn("checkMode"); QTest::addColumn("expectRelink"); QTest::newRow("default") << QString() << false; QTest::newRow("relaxed") << QString("ignore-undefined") << false; QTest::newRow("strict") << QString("strict") << true; } void TestBlackboxQt::pkgconfig() { QDir::setCurrent(testDataDir + "/pkgconfig"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); } void TestBlackboxQt::pkgconfigQt() { QFETCH(QStringList, arguments); QFETCH(bool, success); QDir::setCurrent(testDataDir + "/pkgconfig-qt"); rmDirR(relativeBuildDir()); QbsRunParameters dumpParams("resolve", {"-f", "dump-libpath.qbs"}); QCOMPARE(runQbs(dumpParams), 0); auto lines = QString::fromUtf8(m_qbsStdout).split('\n'); const QString needle = "libPath="; qbs::Internal::removeIf( lines, [&needle](const auto &line) { return !line.startsWith(needle); }); QCOMPARE(lines.size(), 1); const auto libPath = lines[0].mid(needle.size()); auto prefix = QFileInfo(libPath).path(); if (prefix.endsWith("/lib") && !prefix.startsWith("/lib")) prefix = QFileInfo(prefix).path(); const auto pkgConfigPath = libPath + "/pkgconfig/"; if (!QFileInfo(pkgConfigPath).exists()) QSKIP("No *.pc files found"); rmDirR(relativeBuildDir()); QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); // need to override prefix for the downloaded Qt params.environment.insert("PKG_CONFIG_QT5CORE_PREFIX", prefix); params.environment.insert("PKG_CONFIG_QT6CORE_PREFIX", prefix); params.arguments << "moduleProviders.qbspkgconfig.extraPaths:" + pkgConfigPath; params.arguments << arguments; QCOMPARE(runQbs(params) == 0, success); if (!success) QVERIFY(m_qbsStderr.contains("Dependency 'Qt.core' not found for product 'p'")); } void TestBlackboxQt::pkgconfigQt_data() { QTest::addColumn("arguments"); QTest::addColumn("success"); QTest::newRow("pkgconfig") << QStringList() << true; QTest::newRow("dummy") << QStringList({"products.p.qbsModuleProviders:dummyProvider"}) << false; QTest::newRow("cross-compiling") << QStringList({"moduleProviders.qbspkgconfig.sysroot:/some/fake/sysroot"}) << false; } void TestBlackboxQt::pkgconfigNoQt() { QDir::setCurrent(testDataDir + "/pkgconfig-qt"); rmDirR(relativeBuildDir()); QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); params.arguments << "moduleProviders.qbspkgconfig.libDirs:nonexistent"; params.expectFailure = true; QCOMPARE(runQbs(params) == 0, false); QVERIFY2(m_qbsStderr.contains("Dependency 'Qt.core' not found for product 'p'"), m_qbsStderr); // QBS-1777: basic check for JS exceptions in case of missing Qt QVERIFY2(!m_qbsStderr.contains("Error executing provider for module 'Qt.core'"), m_qbsStderr); } void TestBlackboxQt::pluginMetaData() { QDir::setCurrent(testDataDir + "/plugin-meta-data"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("using qt4")) QSKIP("Qt version too old"); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QVERIFY2(runQbs(QbsRunParameters("run", QStringList{"-p", "app"})) == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("all ok!"), m_qbsStderr.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("metadata.json"); waitForFileUnlock(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("moc"), m_qbsStdout.constData()); } void TestBlackboxQt::pluginSupport_data() { QTest::addColumn("invalidPlugin"); QTest::newRow("request valid plugins") << false; QTest::newRow("request invalid plugin") << true; } void TestBlackboxQt::pluginSupport() { QDir::setCurrent(testDataDir + "/plugin-support"); QFETCH(bool, invalidPlugin); QbsRunParameters resolveParams("resolve"); if (invalidPlugin) { resolveParams.arguments << "modules.m1.useDummy:true"; resolveParams.expectFailure = true; } bool resolveResult = runQbs(resolveParams) == 0; if (m_qbsStdout.contains("using qt4")) QSKIP("Qt version too old"); QCOMPARE(resolveResult, !invalidPlugin); if (invalidPlugin) { QVERIFY2(m_qbsStderr.contains("Plugin 'dummy' of type 'imageformats' was requested, " "but is not available"), m_qbsStderr.constData()); return; } const bool isStaticQt = m_qbsStdout.contains("static Qt: true"); const bool isDynamicQt = m_qbsStdout.contains("static Qt: false"); QVERIFY(isStaticQt != isDynamicQt); if (isStaticQt) QVERIFY2(m_qbsStdout.contains("platform plugin count: 1"), m_qbsStdout.constData()); else QVERIFY2(m_qbsStdout.contains("platform plugin count: 0"), m_qbsStdout.constData()); const auto extractList = [this](const char sep) { const int listStartIndex = m_qbsStdout.indexOf(sep); const int listEndIndex = m_qbsStdout.indexOf(sep, listStartIndex + 1); const QByteArray listString = m_qbsStdout.mid(listStartIndex + 1, listEndIndex - listStartIndex - 1); return listString.isEmpty() ? QByteArrayList() : listString.split(','); }; const QByteArrayList enabledPlugins = extractList('%'); if (isStaticQt) QCOMPARE(enabledPlugins.size(), 2); else QVERIFY(enabledPlugins.empty()); const QByteArrayList allPlugins = extractList('#'); QVERIFY(allPlugins.size() >= enabledPlugins.size()); QCOMPARE(runQbs(), 0); for (const QByteArray &plugin : allPlugins) { QCOMPARE(m_qbsStdout.contains("qt_plugin_import_" + plugin + ".cpp"), enabledPlugins.contains(plugin)); } } void TestBlackboxQt::qdoc() { QDir::setCurrent(testDataDir + "/qdoc"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); if (m_qbsStdout.contains("Qt is too old")) QSKIP("Skip test since qdoc3 does not work properly"); QCOMPARE(runQbs(), 0); QVERIFY(QFileInfo(relativeProductBuildDir("QDoc Test") + "/qdoctest.qch").exists()); } void TestBlackboxQt::qmlDebugging() { QDir::setCurrent(testDataDir + "/qml-debugging"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); if (isNotGcc) QSKIP("The remainder of this test only applies to gcc"); QVERIFY(isGcc); QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app", m_qbsStdout))); if (!nm.waitForStarted()) QSKIP("The remainder of this test requires nm"); QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); const QByteArray output = nm.readAllStandardOutput(); QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); } void TestBlackboxQt::qobjectInObjectiveCpp() { if (!HostOsInfo::isMacosHost()) QSKIP("only applies on macOS"); const QString testDir = testDataDir + "/qobject-in-mm"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::qmlTypeRegistrar_data() { QTest::addColumn("importName"); QTest::addColumn("installDir"); QTest::newRow("don't generate") << QString() << QString(); QTest::newRow("don't generate with install info") << QString() << QString("blubb"); QTest::newRow("generate only") << QString("People") << QString(); QTest::newRow("generate and install") << QString("People") << QString("blubb"); } void TestBlackboxQt::qmlTypeRegistrar() { QDir::setCurrent(testDataDir + "/qmltyperegistrar"); QFETCH(QString, importName); QFETCH(QString, installDir); rmDirR(relativeBuildDir()); const QStringList args{"modules.Qt.qml.importName:" + importName, "modules.Qt.qml.typesInstallDir:" + installDir}; if ((runQbs(QbsRunParameters("resolve", args)) != 0) && m_qbsStderr.contains("Dependency 'Qt.qml' not found for product 'myapp'")) QSKIP("Qt version too old"); const bool hasRegistrar = m_qbsStdout.contains("has registrar"); const bool doesNotHaveRegistrar = m_qbsStdout.contains("does not have registrar"); QVERIFY(hasRegistrar != doesNotHaveRegistrar); if (doesNotHaveRegistrar) QSKIP("Qt version too old"); QbsRunParameters buildParams; buildParams.arguments << "--command-echo-mode" << "command-line"; QCOMPARE(runQbs(buildParams), 0); const bool enabled = !importName.isEmpty(); QCOMPARE(m_qbsStdout.contains("--foreign-types"), enabled); QCOMPARE(m_qbsStdout.contains("myapp_qmltyperegistrations.cpp.o"), enabled); const QString buildDir = relativeProductBuildDir("myapp"); QCOMPARE(regularFileExists(buildDir + "/myapp.qmltypes"), enabled); QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/" + installDir + "/myapp.qmltypes"), enabled && !installDir.isEmpty()); } void TestBlackboxQt::qtKeywords() { QDir::setCurrent(testDataDir + "/qt-keywords"); QbsRunParameters params(QStringList("modules.Qt.core.enableKeywords:false")); params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.arguments.clear(); QVERIFY(runQbs(params) != 0); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackboxQt::quickCompiler() { QDir::setCurrent(testDataDir + "/quick-compiler"); if ((runQbs() != 0) && m_qbsStderr.contains("'Qt.quick' has version 4.8.7, but it needs to be at least 5.0.0.")) QSKIP("Qt version too old"); const bool hasCompiler = m_qbsStdout.contains("compiler available"); const bool doesNotHaveCompiler = m_qbsStdout.contains("compiler not available"); QVERIFY2(hasCompiler || doesNotHaveCompiler, m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling qml_subdir_test_qml.cpp"), hasCompiler); if (doesNotHaveCompiler) QSKIP("qtquickcompiler not available"); QVERIFY2(m_qbsStdout.contains("generating loader source"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("generating loader source"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("qml/subdir/test.qml"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating loader source"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters(QStringList{"config:off", "modules.Qt.quick.useCompiler:false"})), 0); QVERIFY2(m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling qml_subdir_test_qml.cpp"), m_qbsStdout.constData()); } void TestBlackboxQt::qtScxml() { QDir::setCurrent(testDataDir + "/qtscxml"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("QtScxml not present")) QSKIP("QtScxml module not present"); QVERIFY2(m_qbsStdout.contains("state machine name: qbs_test_machine"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.Qt.scxml.additionalCompilerFlags:--blubb"))), 0); QbsRunParameters params; params.expectFailure = true; QVERIFY2(runQbs(params) != 0, m_qbsStdout.constData()); } // see, https://bugreports.qt.io/projects/QBS/issues/QBS-1839 // checks Qt.xml framework is linked correctly void TestBlackboxQt::qtXml() { QDir::setCurrent(testDataDir + "/qt-xml"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::removeMocHeaderFromFileList() { QDir::setCurrent(testDataDir + "/remove-moc-header-from-file-list"); QCOMPARE(runQbs(), 0); QString projectFile("remove-moc-header-from-file-list.qbs"); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "\"file.h\"", "// \"file.h\""); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// \"file.h\"", "\"file.h\""); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::shadertools_data() { QTest::addColumn("projectName"); QTest::addColumn("linesToCheck"); QTest::newRow("basic") << "basic" << QStringList{ "qsb.*basic_shader.frag.qsb.*", "qsb.*--glsl ['\"]100 es,120,150['\"] --hlsl 50 --msl 20 -O -g", }; QTest::newRow("defines") << "defines" << QStringList{"qsb.*defines_shader.frag.qsb.*-DTEST_DEFINE_1=1.*-DTEST_DEFINE_2=1"}; QTest::newRow("tessellation") << "tessellation" << QStringList{ "qsb.*tessellation_shader.vert.qsb.*--glsl.*410,320es", "qsb.*tessellation_shader.tesc.qsb.*--glsl.*410,320es.*" "--msltess --tess-mode triangles --tess-vertex-count 3"}; QTest::newRow("viewcount") << "viewcount" << QStringList{ "qsb.*basic_shader.frag.qsb.*", "qsb.*--glsl ['\"]100 es,120,150['\"] --hlsl 50 --msl 20 --view-count 4", }; } void TestBlackboxQt::shadertools() { QFETCH(QString, projectName); QFETCH(QStringList, linesToCheck); bool hasViewCount = false; const auto shaderToolsFound = findShaderTools(&hasViewCount); QVERIFY(shaderToolsFound.has_value()); if (!shaderToolsFound.value()) QSKIP("Test requires Qt 6, dynamic Qt build and Qt Shader Tools"); if (projectName == "viewcount" && !hasViewCount) { QSKIP("Test requires Qt 6.7.0 or later"); } QDir::setCurrent(testDataDir + "/shadertools"); rmDirR(relativeBuildDir()); rmDirR(relativeBuildDir()); QbsRunParameters params; params.arguments << QStringLiteral("-f") << projectName + ".qbs" << "--command-echo-mode" << "command-line"; QCOMPARE(runQbs(params), 0); for (const auto &line : linesToCheck) { const QRegularExpression pattern(line); const QRegularExpressionMatch match = pattern.match(m_qbsStdout); QVERIFY2(match.hasMatch(), qPrintable(m_qbsStdout)); } } void TestBlackboxQt::shadertoolsLinking_data() { QTest::addColumn("enableLinking"); QTest::newRow("linking enabled") << true; QTest::newRow("linking disabled") << false; } void TestBlackboxQt::shadertoolsLinking() { QFETCH(bool, enableLinking); const auto shaderToolsFound = findShaderTools(); QVERIFY(shaderToolsFound.has_value()); if (!shaderToolsFound.value()) QSKIP("Test requires Qt 6, dynamic Qt build and Qt Shader Tools"); QDir::setCurrent(testDataDir + "/shadertools-linking"); QbsRunParameters params; params.arguments << QString("modules.Qt.shadertools.enableLinking:%1").arg(enableLinking); params.expectFailure = !enableLinking; if (enableLinking) { QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling shader.frag.qsb")); } else { QVERIFY(runQbs(params) != 0); } } void TestBlackboxQt::staticQtPluginLinking() { QDir::setCurrent(testDataDir + "/static-qt-plugin-linking"); QCOMPARE(runQbs(QStringList("products.p.type:application")), 0); const bool isStaticQt = m_qbsStdout.contains("Qt is static"); QVERIFY2(m_qbsStdout.contains("creating static import") == isStaticQt, m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.type:staticlibrary"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("creating static import"), m_qbsStdout.constData()); } void TestBlackboxQt::trackAddMocInclude() { QDir::setCurrent(testDataDir + "/trackAddMocInclude"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddMocInclude/work"); // The build must fail because the main.moc include is missing. QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::track_qobject_change() { QDir::setCurrent(testDataDir + "/trackQObjChange"); copyFileAndUpdateTimestamp("bla_qobject.h", "bla.h"); QCOMPARE(runQbs(), 0); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); const QString productFilePath = relativeExecutableFilePath("i", m_qbsStdout); QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); QString moc_bla_objectFileName = relativeProductBuildDir("i") + '/' + inputDirHash("qt.headers") + "/moc_bla.cpp" + objectSuffix; QVERIFY2(regularFileExists(moc_bla_objectFileName), qPrintable(moc_bla_objectFileName)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("bla_noqobject.h", "bla.h"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(productFilePath)); QVERIFY(!QFile(moc_bla_objectFileName).exists()); } void TestBlackboxQt::track_qrc() { QDir::setCurrent(testDataDir + "/qrc"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("using qt4")) QSKIP("Qt version too old"); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QString fileName = relativeExecutableFilePath("i", m_qbsStdout); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); QVERIFY2(regularFileExists(fileName), qPrintable(fileName)); QDateTime dt = QFileInfo(fileName).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); { QFile f("stuff.txt"); f.remove(); QVERIFY(f.open(QFile::WriteOnly)); f.write("bla"); f.close(); } REPLACE_IN_FILE("i.qbs", "//\"test.cpp\"", "\"test.cpp\""); waitForFileUnlock(); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc bla.qrc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); QVERIFY(regularFileExists(fileName)); QVERIFY(dt < QFileInfo(fileName).lastModified()); WAIT_FOR_NEW_TIMESTAMP(); touch("i.qbs"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); // Turn on big resources. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(QbsRunParameters("resolve", {"modules.Qt.core.enableBigResources:true"})), 0); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc (pass 1) bla.qrc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("rcc (pass 2) bla.qrc"), m_qbsStdout.constData()); // Check null build. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Building"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); // Turn off big resources. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(QbsRunParameters("resolve", {"modules.Qt.core.enableBigResources:false"})), 0); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc bla.qrc"), m_qbsStdout.constData()); // Check null build. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Building"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); } void TestBlackboxQt::unmocable() { QDir::setCurrent(testDataDir + "/unmocable"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStderr.contains("No relevant classes found. No output generated.")); } QTEST_MAIN(TestBlackboxQt) qbs-src-3.3.1/tests/auto/blackbox/testdata/0000755000175100017510000000000015232633614020213 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/0000755000175100017510000000000015232633614022750 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/main3.cpp0000644000175100017510000000013415232633614024461 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void unusedFunc3(); int main() { unusedFunc3(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/dynamiclib.cpp0000644000175100017510000000012115232633614025561 0ustar runnerrunner#include "../dllexport.h" void usedFunc(); DLL_EXPORT void f() { usedFunc(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/unused1.cpp0000644000175100017510000000007515232633614025042 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void unusedFunc1() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs0000644000175100017510000000431015232633614026212 0ustar runnerrunnerimport qbs.Utilities Project { StaticLibrary { name: "staticlib 1" Depends { name: "cpp" } files: ["unused1.cpp", "used.cpp"] } StaticLibrary { name: "staticlib2" Depends { name: "cpp" } files: ["unused2.cpp"] } StaticLibrary { name: "staticlib3" Depends { name: "cpp" } files: ["unused3.cpp"] } StaticLibrary { name: "staticlib4" Depends { name: "cpp" } files: ["unused4.cpp"] } DynamicLibrary { name: "dynamiclib" property string linkWholeArchive Depends { name: "cpp" } Probe { id: dummy property stringList toolchain: qbs.toolchain property string compilerVersion: cpp.compilerVersion property string dummy: product.linkWholeArchive // To force probe re-execution property bool isEmscripten: qbs.toolchain.contains("emscripten") configure: { if (!toolchain.includes("msvc") || toolchain.includes("clang-cl") || Utilities.versionCompare(compilerVersion, "19.0.24215.1") >= 0) { console.info("can link whole archives"); } else { console.info("cannot link whole archives"); } console.info("is emscripten: " + isEmscripten); } } Depends { name: "staticlib 1"; cpp.linkWholeArchive: product.linkWholeArchive } Depends { name: "staticlib2"; cpp.linkWholeArchive: product.linkWholeArchive } Depends { name: "staticlib3" } Depends { name: "staticlib4"; cpp.linkWholeArchive: product.linkWholeArchive } files: ["dynamiclib.cpp"] } CppApplication { name: "app1" Depends { name: "dynamiclib" } files: ["main1.cpp"] } CppApplication { name: "app2" Depends { name: "dynamiclib" } files: ["main2.cpp"] } CppApplication { name: "app3" Depends { name: "dynamiclib" } files: ["main3.cpp"] } CppApplication { name: "app4" Depends { name: "dynamiclib" } files: ["main4.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/unused3.cpp0000644000175100017510000000007515232633614025044 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void unusedFunc3() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/unused4.cpp0000644000175100017510000000007515232633614025045 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void unusedFunc4() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/unused2.cpp0000644000175100017510000000007515232633614025043 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void unusedFunc2() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/main4.cpp0000644000175100017510000000013515232633614024463 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void unusedFunc4(); int main() { unusedFunc4(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/main2.cpp0000644000175100017510000000013515232633614024461 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void unusedFunc2(); int main() { unusedFunc2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/main1.cpp0000644000175100017510000000013515232633614024460 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void unusedFunc1(); int main() { unusedFunc1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/whole-archive/used.cpp0000644000175100017510000000002415232633614024410 0ustar runnerrunnervoid usedFunc() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/0000755000175100017510000000000015232633614024407 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs0000644000175100017510000000204315232633614031311 0ustar runnerrunnerimport "MyStaticLib.qbs" as MyStaticLib import qbs.Host Project { property bool removeDuplicates property string libDir: buildDirectory + "/lib" property bool dummy: { // most BSD systems (including macOS) use LLVM linker now console.info("is bfd linker: " + ((qbs.toolchain.includes("gcc") && !qbs.toolchain.includes("emscripten")) && !Host.os().includes("bsd"))) } qbsSearchPaths: "." MyStaticLib { name: "requestor1" } MyStaticLib { name: "requestor2" } MyStaticLib { name: "provider"; Group { files: "provider2.c" } } CppApplication { consoleApplication: true Depends { name: "requestor1"; cpp.link: false } Depends { name: "requestor2"; cpp.link: false } Depends { name: "provider"; cpp.link: false } cpp.libraryPaths: project.libDir cpp.removeDuplicateLibraries: project.removeDuplicates cpp.staticLibraries: ["requestor1", "requestor2", "provider", "requestor2"] files: "main.c" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/requestor1.c0000644000175100017510000000006615232633614026667 0ustar runnerrunnervoid provider1(); void requestor1() { provider1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/MyStaticLib.qbs0000644000175100017510000000030415232633614027277 0ustar runnerrunnerStaticLibrary { Properties { condition: isForDarwin bundle.isBundle: false } Depends { name: "cpp" } files: name + ".c" destinationDirectory: project.libDir } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/main.c0000644000175100017510000000015415232633614025477 0ustar runnerrunnervoid requestor1(); void requestor2(); int main(void) { requestor1(); requestor2(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/provider2.c0000644000175100017510000000002415232633614026463 0ustar runnerrunnervoid provider2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/requestor2.c0000644000175100017510000000006615232633614026670 0ustar runnerrunnervoid provider2(); void requestor2() { provider2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/remove-duplicate-libs/provider.c0000644000175100017510000000002415232633614026401 0ustar runnerrunnervoid provider1() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/0000755000175100017510000000000015232633614024441 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs0000644000175100017510000000156515232633614027500 0ustar runnerrunnerimport qbs.Host import qbs.Utilities // non-existent versions of Windows should print a QBS warning // (but will still compile and link since we avoid passing a // bad value to the linker) CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && qbs.targetOS.includes("windows"); } files: ["main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: "5.3" cpp.defines: [ "QBS_WINVER=0x503", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs0000644000175100017510000000152015232633614027464 0ustar runnerrunner// just to make sure three-digit minimum versions work on macOS // this only affects the value of __MAC_OS_X_VERSION_MIN_REQUIRED, // not the actual LC_VERSION_MIN_MACOSX command which is limited to two import qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && qbs.targetOS.includes("macos"); } files: ["main.mm"] consoleApplication: true cpp.frameworks: "Foundation" cpp.minimumMacosVersion: qbs.architecture === "arm64" ? "11.0" : "10.7.1" } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs0000644000175100017510000000213715232633614030711 0ustar runnerrunnerimport qbs.Utilities // no minimum versions are specified, and explicitly set to undefined in // case the profile has set it import qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: undefined cpp.minimumMacosVersion: undefined cpp.minimumIosVersion: undefined cpp.minimumAndroidVersion: undefined Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/main.mm0000644000175100017510000000575215232633614025731 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #import int main() { // This gets set by -mmacosx-version-min. If left undefined, defaults to the current OS version. std::cout << "__MAC_OS_X_VERSION_MIN_REQUIRED=" << __MAC_OS_X_VERSION_MIN_REQUIRED << std::endl; bool print = false; NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@"/usr/bin/otool"]; [task setArguments:[NSArray arrayWithObjects:@"-l", [[[NSProcessInfo processInfo] arguments] firstObject], nil]]; NSPipe *pipe = [NSPipe pipe]; [task setStandardOutput:pipe]; [task launch]; NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; [task waitUntilExit]; NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *line; NSEnumerator *enumerator = [[result componentsSeparatedByString:@"\n"] objectEnumerator]; while ((line = [enumerator nextObject]) != nil) { if ([line rangeOfString:@"LC_VERSION_MIN_MACOSX"].location != NSNotFound) print = true; if (print && [line rangeOfString:@"version"].location != NSNotFound) { std::cout << [[line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] UTF8String] << std::endl; print = false; continue; } #ifdef __clang__ #if __clang_major__ >= 10 && __clang_minor__ >= 0 if ([line rangeOfString:@"LC_BUILD_VERSION"].location != NSNotFound) print = true; if (print && [line rangeOfString:@"minos"].location != NSNotFound) { std::cout << [[line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] UTF8String] << std::endl; print = false; } #endif #endif // __clang__ } } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs0000644000175100017510000000234715232633614026743 0ustar runnerrunnerimport qbs.Utilities // a specific version of the operating systems is specified // when the application is run its output should confirm // that the given values took effect import qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && qbs.targetOS.includes("windows") || qbs.targetOS.includes("macos"); } files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { condition: qbs.targetOS.includes("windows") cpp.minimumWindowsVersion: "6.2" cpp.defines: [ "QBS_WINVER=0x602", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } Properties { condition: qbs.targetOS.includes("macos") cpp.frameworks: "Foundation" cpp.minimumMacosVersion: qbs.architecture === "arm64" ? "11.0" : "10.7" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/main.cpp0000644000175100017510000000711615232633614026076 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef _WIN32 #include #include #include #include #include #include #include #endif int main(int argc, char *argv[]) { if (argc != 1) return 1; #ifdef _WIN32 #if defined(__clang__) std::cout << "Unsupported compiler" << std::endl; return 0; #endif #if defined(WINVER) && defined(QBS_WINVER) std::cout << "WINVER=" << WINVER << std::endl; std::string command = TOOLCHAIN_INSTALL_PATH; std::replace(command.begin(), command.end(), '/', '\\'); command = "\"\"" + command; #ifdef __GNUC__ command += "\\objdump.exe\" -p \""; #else command += "\\dumpbin.exe\" /HEADERS \""; #endif command += argv[0]; command += "\" > qbs-test-dumpbin.txt\""; int status = ::system(command.c_str()); if (status != 0) return status; std::ifstream in("qbs-test-dumpbin.txt"); std::string s; while (std::getline(in, s)) { #ifdef __GNUC__ static const char *majorOSystemVersion = "MajorOSystemVersion\t"; if (s.find(majorOSystemVersion) != std::string::npos) std::cout << s.substr(std::strlen(majorOSystemVersion)); static const char *minorOSystemVersion = "MinorOSystemVersion\t"; if (s.find(minorOSystemVersion) != std::string::npos) std::cout << ".0" << s.substr(std::strlen(minorOSystemVersion)) << " operating system version" << std::endl; static const char *majorSubsystemVersion = "MajorSubsystemVersion\t"; if (s.find(majorSubsystemVersion) != std::string::npos) std::cout << s.substr(std::strlen(majorSubsystemVersion)); static const char *minorSubsystemVersion = "MinorSubsystemVersion\t"; if (s.find(minorSubsystemVersion) != std::string::npos) std::cout << ".0" << s.substr(std::strlen(minorSubsystemVersion)) << " subsystem version" << std::endl; #else if (s.find("operating system version") != std::string::npos || s.find("subsystem version") != std::string::npos) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); std::cout << s << std::endl; } #endif } unlink("qbs-test-dumpbin.txt"); #else std::cout << "WINVER is not defined" << std::endl; #endif #endif return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs0000644000175100017510000000164315232633614027452 0ustar runnerrunnerimport qbs.Utilities // no minimum versions are specified so the profile defaults will be used import qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/0000755000175100017510000000000015232633614025037 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/0000755000175100017510000000000015232633614026507 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/0000755000175100017510000000000015232633614027645 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/outer.qbs0000644000175100017510000000060515232633614031513 0ustar runnerrunnerModule { Depends { name: "inner" } Probe { id: foo2 property string barz property string named: product.name configure: { console.info("running second probe " + named); barz = "goodbye"; found = true; } } property string something: inner.something property string somethingElse: foo2.barz } qbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/0000755000175100017510000000000015232633614027622 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/inner.qbs0000644000175100017510000000061415232633614031445 0ustar runnerrunnerimport qbs.Probes Module { property bool alt: false Probe { id: foo property string baz property bool useAlt: alt property string named: product.name configure: { console.info("running probe " + named); baz = useAlt ? "hahaha" : "hello"; found = true; } } property string something: foo.baz } qbs-src-3.3.1/tests/auto/blackbox/testdata/probes-in-nested-modules/probes-in-nested-modules.qbs0000644000175100017510000000176715232633614032405 0ustar runnerrunnerProject { Product { name: "a" Depends { name: "outer" } inner.alt: true property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); console.info("product " + name + ", outer.something = " + outer.something); console.info("product " + name + ", outer.somethingElse = " + outer.somethingElse); return true; } type: ["foo"] } Product { name: "b" Depends { name: "inner" } inner.alt: true property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); return true; } type: ["foo"] } Product { name: "c" Depends { name: "inner" } inner.alt: false property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); return true; } type: ["foo"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dependency-scanning-loop/0000755000175100017510000000000015232633614025076 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs0000644000175100017510000000170015232633614032466 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile CppApplication { name: "app" cpp.includePaths: buildDirectory Group { files: "main.cpp" fileTags: ["cpp", "custom.in"] } Rule { inputs: "custom.in" Artifact { filePath: FileInfo.completeBaseName(input.filePath) + ".h" fileTags: "hpp" } Artifact { filePath: "custom.txt" fileTags: "whatever" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + outputs.hpp[0].fileName; cmd.sourceCode = function() { var f = new TextFile(outputs.hpp[0].filePath, TextFile.WriteOnly); f.writeLine("int main() {}"); f.close(); f = new TextFile(outputs.whatever[0].filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp0000644000175100017510000000002215232633614026520 0ustar runnerrunner#include qbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/0000755000175100017510000000000015232633614027556 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/0000755000175100017510000000000015232633614031226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/broken/0000755000175100017510000000000015232633614032506 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/broken/broken.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/broken/brok0000644000175100017510000000005615232633614033367 0ustar runnerrunnerModule { validate: { throw "broken!"; } } ././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/exported-property-in-disabled-product.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/exported-property-i0000644000175100017510000000073415232633614033447 0ustar runnerrunnerProject { CppApplication { name: "app" Depends { name: "dep"; required: false } files: "main.cpp" } Product { name: "dep" condition: eval(conditionString) property string conditionString Depends { name: "nosuchmodule"; required: false } Depends { name: "broken"; required: false } Export { Depends { name: "cpp" } cpp.dynamicLibraries: ["nosuchlib"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/main.cpp0000644000175100017510000000001615232633614031203 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/0000755000175100017510000000000015232633614022733 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/cdefgabc.txt.in0000644000175100017510000000005015232633614025612 0ustar runnerrunner${c} ${d} ${e} ${f} ${g} ${a} ${b} ${c} qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/output.txt.in0000644000175100017510000000027415232633614025444 0ustar runnerrunnerfoo bar baz ${foo} bar baz foo ${bar} baz foo bar ${baz} ${foo} ${bar} baz ${foo} bar ${baz} ${foo} ${bar} ${baz} foo${bar}baz foo\${bar}baz foo\\${bar}baz foo\\\${bar}baz foo${$}{bar}baz qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/texttemplatetest.qbs0000644000175100017510000000111715232633614027062 0ustar runnerrunnerProduct { name: "one" type: ["text"] files: ["output.txt.in"] Depends { name: "texttemplate" } texttemplate.dict: ({ foo: "fu", bar: "BAR", baz: "buzz", }) Group { files: ["cdefgabc.txt.in"] texttemplate.outputFileName: "lalala.txt" texttemplate.dict: ({ c: "do", d: "re", e: "mi", f: "fa", g: "so", a: "la", b: "ti", }) } Group { files: ["output_at.txt.in"] texttemplate.placeholder: "@@" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/output_at.txt.in0000644000175100017510000000025015232633614026122 0ustar runnerrunnerfoo bar baz @foo@ bar baz foo @bar@ baz foo bar @baz@ @foo@ @bar@ baz @foo@ bar @baz@ @foo@ @bar@ @baz@ foo@bar@baz foo\@bar@baz foo\\@bar@baz foo\\\@bar@baz foo@@@baz qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/expected/0000755000175100017510000000000015232633614024534 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/expected/output.txt0000644000175100017510000000021615232633614026634 0ustar runnerrunnerfoo bar baz fu bar baz foo BAR baz foo bar buzz fu BAR baz fu bar buzz fu BAR buzz fooBARbaz foo\BARbaz foo\\BARbaz foo\\\BARbaz foo${bar}baz qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/expected/lalala.txt0000644000175100017510000000003015232633614026514 0ustar runnerrunnerdo re mi fa so la ti do qbs-src-3.3.1/tests/auto/blackbox/testdata/texttemplate/expected/output_at.txt0000644000175100017510000000021115232633614027313 0ustar runnerrunnerfoo bar baz fu bar baz foo BAR baz foo bar buzz fu BAR baz fu bar buzz fu BAR buzz fooBARbaz foo\BARbaz foo\\BARbaz foo\\\BARbaz foo@baz qbs-src-3.3.1/tests/auto/blackbox/testdata/versionscript/0000755000175100017510000000000015232633614023125 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versionscript/versionscript0000644000175100017510000000005515232633614025762 0ustar runnerrunner{ global: dummyGlobal; local: dummyLocal; }; qbs-src-3.3.1/tests/auto/blackbox/testdata/versionscript/testlib.c0000644000175100017510000000240615232633614024741 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummyLocal() {} void dummyGlobal() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/versionscript/versionscript.qbs0000644000175100017510000000152715232633614026553 0ustar runnerrunnerDynamicLibrary { type: base.concat("custom") Depends { name: "cpp" } files: ["testlib.c"] Group { name: "version script" files: ["versionscript"] fileTags: ["versionscript"] } Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.warn("---" + product.cpp.nmPath + "---"); } return [cmd]; } } Probe { id: checker property bool isLinux: qbs.targetOS.includes("linux") property bool isGcc: qbs.toolchain.contains("gcc") configure: { console.info("is gcc for Linux: " + (isLinux && isGcc)); } } qbs.installPrefix: "" install: true installDir: "" } qbs-src-3.3.1/tests/auto/blackbox/testdata/product-in-exported-module/0000755000175100017510000000000015232633614025412 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/product-in-exported-module/modules/0000755000175100017510000000000015232633614027062 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/product-in-exported-module/modules/m/0000755000175100017510000000000015232633614027316 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/product-in-exported-module/modules/m/m.qbs0000644000175100017510000000016115232633614030257 0ustar runnerrunnerModule { Depends { name: "dummy"; condition: { console.info("product: " + product.name); return false; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/product-in-exported-module/product-in-exported-module.qbs0000644000175100017510000000025315232633614033320 0ustar runnerrunnerProject { Product { name: "importing" Depends { name: "dep" } } Product { name: "dep" Export { Depends { name: "m" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/grpc/0000755000175100017510000000000015232633614021146 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/grpc/conanfile.txt0000644000175100017510000000013115232633614023640 0ustar runnerrunner[requires] grpc/1.54.3 [tool_requires] protobuf/3.21.12 grpc/1.54.3 [generators] QbsDeps qbs-src-3.3.1/tests/auto/blackbox/testdata/grpc/grpc.cpp0000644000175100017510000000357315232633614022615 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include class ServiceImpl final : public Qbs::Grpc::Service { grpc::Status doWork( grpc::ServerContext* context, const Qbs::Request* request, Qbs::Response* reply) override { (void)context; reply->set_name(request->name()); return grpc::Status::OK; } }; int main(int, char**) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs0000644000175100017510000000217015232633614023452 0ustar runnerrunnerimport qbs.Host CppApplication { name: "grpc_cpp" consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasDependencies; } Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++17" cpp.minimumMacosVersion: "10.15" cpp.warningLevel: "none" qbs.buildVariant: "release" Depends { name: "protobuf.cpp"; required: false } Depends { name: "grpc++"; id: grpcpp; required: false } protobuf.cpp.useGrpc: true property bool hasDependencies: { console.info("has grpc: " + protobuf.cpp.present); console.info("has modules: " + grpcpp.present); return protobuf.cpp.present && grpcpp.present; } files: "grpc.cpp" Group { files: "grpc.proto" fileTags: "protobuf.grpc" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/grpc/grpc.proto0000644000175100017510000000026715232633614023173 0ustar runnerrunnersyntax = "proto3"; package Qbs; message Request { string name = 1; } message Response { string name = 1; } service Grpc { rpc doWork(Request) returns (Response) {} } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-changes/0000755000175100017510000000000015232633614023454 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-changes/multiple-changes.qbs0000644000175100017510000000140115232633614027420 0ustar runnerrunnerProject { property bool prop: false Product { name: "test" type: ["out-type"] Group { name: "Rule input" files: ["dummy.txt"] fileTags: ["in-type"] } Group { name: "irrelevant" files: ["*.blubb"] } Rule { inputs: ["in-type"] Artifact { filePath: "dummy.out" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("prop: " + project.prop); } return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-changes/dummy.txt0000644000175100017510000000000015232633614025336 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/clean/0000755000175100017510000000000015232633614021275 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/clean/main.cpp0000644000175100017510000000235215232633614022727 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/clean/dep.cpp0000644000175100017510000000241515232633614022553 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/clean/clean.qbs0000644000175100017510000000123015232633614023062 0ustar runnerrunnerProject { DynamicLibrary { Depends { name: "cpp" } version: "1.1.0" name: "dep" files: "dep.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } CppApplication { consoleApplication: true name: "app" property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); console.info("executable suffix: " + cpp.executableSuffix); console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } Depends { name: "dep" } files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/0000755000175100017510000000000015232633614025631 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/0000755000175100017510000000000015232633614026416 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/0000755000175100017510000000000015232633614030066 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/0000755000175100017510000000000015232633614030611 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs0000644000175100017510000000001215232633614032116 0ustar runnerrunnerGroup { } qbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs0000644000175100017510000000004015232633614032116 0ustar runnerrunnerModule { condition: false } qbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp0000644000175100017510000000003115232633614027253 0ustar runnerrunnerint main() { return 0; } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken0000644000175100017510000000013715232633614033173 0ustar runnerrunnerCppApplication { qbsSearchPaths: "qbs" Depends { name: "Foo" } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableRtti/0000755000175100017510000000000015232633614022304 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/enableRtti/main.cpp0000644000175100017510000000330515232633614023735 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #if defined(__GNUC__) && !(defined(__cpp_rtti) || defined(__GXX_RTTI)) #error RTTI is disabled! #endif #if defined(_MSC_VER) && !defined (_CPPRTTI) #error RTTI is disabled! #endif class I { public: virtual ~I() { } virtual void x() { } }; class A : public I { void x() override { } }; class B : public I { void x() override { } }; int main() { const auto a = new A(); B *b = dynamic_cast(a); (void)b; delete a; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableRtti/rtti.qbs0000644000175100017510000000043115232633614023773 0ustar runnerrunnerProject { property bool treatAsObjcpp: false CppApplication { cpp.cxxLanguageVersion: "c++11" cpp.treatWarningsAsErrors: true Group { files: ["main.cpp"] fileTags: [project.treatAsObjcpp ? "objcpp" : "cpp"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/0000755000175100017510000000000015232633614022421 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/hello.ts0000644000175100017510000000003515232633614024072 0ustar runnerrunnerconsole.log("Hello world!"); qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/main.ts0000644000175100017510000000102315232633614023711 0ustar runnerrunnerimport Animals = require("./animals"); import Foo = require("./foo"); import Extra = require("./woosh/extra"); function main() { var mammals: Animals.Mammal[] = []; mammals.push(new Animals.Human()); mammals.push(new Animals.Dog()); mammals.push(new Animals.Cat()); // Make everyone speak for (var i = 0; i < mammals.length; ++i) { console.log(mammals[i].speak()); } (new Extra.Boom()); var greeting: string = (new Foo.Greeter()).getGreeting(); console.log(greeting); } main(); qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/extra.js0000644000175100017510000000010615232633614024077 0ustar runnerrunnerif (console) { console.log("This doesn't do anything useful!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/foo.ts0000644000175100017510000000013715232633614023555 0ustar runnerrunnerexport class Greeter { public getGreeting(): string { return "guten Tag!"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/typescript.qbs0000644000175100017510000000200515232633614025333 0ustar runnerrunnerProject { NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib" } typescript.warningLevel: "pedantic" typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" nodejs.applicationFile: "main.ts" name: "animals" files: [ "animals.ts", "extra.js", "woosh/extra.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" name: "lib" files: [ "foo.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true name: "lib2" files: [ "foo2.ts" ] } NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib2" } typescript.singleFile: true nodejs.applicationFile: "hello.ts" name: "single" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/woosh/0000755000175100017510000000000015232633614023560 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/woosh/extra.ts0000644000175100017510000000002615232633614025251 0ustar runnerrunnerexport class Boom { } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/animals.ts0000644000175100017510000000055015232633614024415 0ustar runnerrunnerexport interface Mammal { speak(): string; } export class Cat implements Mammal { public speak() { return "Meow"; // a cat says meow } } export class Dog implements Mammal { public speak() { return "Woof"; // a dog says woof } } export class Human implements Mammal { public speak() { return "Hello"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/typescript/foo2.ts0000644000175100017510000000000115232633614023625 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-no-inputs/0000755000175100017510000000000015232633614024065 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-no-inputs/rule-with-no-inputs.qbs0000644000175100017510000000127615232633614030454 0ustar runnerrunnerimport qbs.TextFile Product { name: "theProduct" type: ["output"] version: "1" property bool dummy: false Rule { inputs: [] multiplex: true Artifact { filePath: "output.out" fileTags: ["output"] } prepare: { console.info("running the rule: " + product.dummy); var cmd = new JavaScriptCommand(); cmd.description = "creating output"; cmd.sourceCode = function() { console.info(product.version); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-dependency/0000755000175100017510000000000015232633614024000 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-dependency/missing-dependency.qbs0000644000175100017510000000146615232633614030303 0ustar runnerrunnerimport qbs.TextFile Project { Product { name: "theDep" type: ["genheader"] Rule { multiplex: true Artifact { filePath: project.buildDirectory + "/theHeader.h" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } } CppApplication { name: "theApp" cpp.includePaths: [project.buildDirectory] files: ["main.cpp"] Depends { name: "bundle" } bundle.isBundle: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-dependency/main.cpp0000644000175100017510000000240215232633614025426 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/0000755000175100017510000000000015232633614024132 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/disappeared-profile.qbs0000644000175100017510000000031715232633614030561 0ustar runnerrunnerProduct { type: ["out1", "out2"] Depends { name: "m" } Group { files: ["in1.txt"] fileTags: ["in1"] } Group { files: ["in2.txt"] fileTags: ["in2"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/0000755000175100017510000000000015232633614026356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/0000755000175100017510000000000015232633614030026 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/0000755000175100017510000000000015232633614030262 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs0000644000175100017510000000143515232633614031230 0ustar runnerrunnerModule { property string p1 property string p2 Rule { inputs: ["in1"] Artifact { filePath: "dummy1.txt" fileTags: ["out1"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName + " with " + product.m.p1; cmd.sourceCode = function() {}; return [cmd]; } } Rule { inputs: ["in2"] Artifact { filePath: "dummy2.txt" fileTags: ["out2"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName + " with " + product.m.p2; cmd.sourceCode = function() {}; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/in2.txt0000644000175100017510000000000015232633614025351 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/disappeared-profile/in1.txt0000644000175100017510000000000015232633614025350 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/localDeployment/0000755000175100017510000000000015232633614023346 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs0000644000175100017510000000166615232633614027221 0ustar runnerrunnerimport qbs.Host Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } type: ["application"] consoleApplication: true name: "HelloWorld" destinationDirectory: "bin" Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } Group { qbs.install: true qbs.installDir: "share" files: ['main.cpp'] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/localDeployment/main.cpp0000644000175100017510000000357415232633614025007 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include int main(int argc, char *argv[]) { if (argc != 1) return 1; std::string s = argv[0]; for (auto &c : s) { if (c == '\\') c = '/'; } const std::string mainFilePath = std::string(s.substr(0, s.find_last_of("/")) + "/../share/main.cpp"); std::ifstream in(mainFilePath.c_str()); if (!in.is_open()) { std::cerr << "Failed to open file: " << mainFilePath; return 1; } std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); std::cout << str << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/0000755000175100017510000000000015232633614026446 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/file.cpp0000644000175100017510000000002115232633614030062 0ustar runnerrunner#include "pch.h" qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/pch.h0000644000175100017510000000240215232633614027367 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/main.cpp0000644000175100017510000000237415232633614030104 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "pch.h" int main() { } ././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-0000644000175100017510000000057615232633614033132 0ustar runnerrunnerCppApplication { name: "MyApp" consoleApplication: true Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } Group { files: ["file.cpp"] cpp.defines: ["MYDEF=1"] cpp.cxxFlags: base.concat(qbs.toolchain.includes("clang-cl") ? ["-Wno-clang-cl-pch"] : []) } cpp.treatWarningsAsErrors: true files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/0000755000175100017510000000000015232633614025654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/0000755000175100017510000000000015232633614026422 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h0000644000175100017510000000003615232633614027340 0ustar runnerrunner#pragma once void lib1_foo();qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs0000644000175100017510000000021515232633614027675 0ustar runnerrunnerProduct { files: "lib.h" Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.sourceDirectory } } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/app/0000755000175100017510000000000015232633614026434 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h0000644000175100017510000000002115232633614027356 0ustar runnerrunner#include "lib.h" qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs0000644000175100017510000000010515232633614027717 0ustar runnerrunnerCppApplication { Depends { name: "lib" } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp0000644000175100017510000000004115232633614030057 0ustar runnerrunner#include "app.h" int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs0000644000175100017510000000015515232633614026623 0ustar runnerrunnerProject { references: [ "app/app.qbs", "lib/lib.qbs", "other/other.qbs", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/other/0000755000175100017510000000000015232633614026775 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs0000644000175100017510000000107715232633614030632 0ustar runnerrunnerimport qbs.TextFile Product { type: "testproduct" files: "../lib/lib.h" Rule { multiplex: true Artifact { fileTags: ["testproduct"] filePath: "fubar" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating text file"; cmd.sourceCode = function() { var tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine("blubb"); tf.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/ruleCycle/0000755000175100017510000000000015232633614022142 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ruleCycle/happy.grass0000644000175100017510000000003015232633614024315 0ustar runnerrunnerhappy! happy! joy! joy! qbs-src-3.3.1/tests/auto/blackbox/testdata/ruleCycle/ruleCycle.qbs0000644000175100017510000000247415232633614024607 0ustar runnerrunnerProject { Product { name: "the cycle of life" type: "cow" Group { files: ["happy.grass"] fileTags: ["grass"] } Rule { inputs: ["grass"] outputFileTags: ["cow"] outputArtifacts: [{ filePath: input.completeBaseName + ".cow", fileTags: ["cow"] }] prepare: { console.info("The cow feeds on grass."); } } Rule { inputs: ["cow"] Artifact { filePath: input.completeBaseName + ".cow_pat" fileTags: ["cow_pat"] } prepare: { console.info("The cow pat falls out of the cow."); } } Rule { inputs: ["cow_pat"] Artifact { filePath: input.completeBaseName + ".fertilizer" fileTags: ["fertilizer"] } prepare: { console.info("The cow pat is used as fertilizer."); } } Rule { inputs: ["fertilizer"] outputFileTags: ["grass"] outputArtifacts: [{ filePath: input.completeBaseName + ".grass", fileTags: ["grass"] }] prepare: { console.info("The fertilizer lets the grass grow."); } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-override-prefix/0000755000175100017510000000000015232633614024774 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-override-prefix/missing-override-prefix.qbs0000644000175100017510000000001415232633614032257 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/0000755000175100017510000000000015232633614025553 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/0000755000175100017510000000000015232633614027223 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/0000755000175100017510000000000015232633614031056 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs0000644000175100017510000000115215232633614033417 0ustar runnerrunnerModule { Probe { id: propProbe property stringList prop: [] configure: { prop = ["probe"]; found = true; } } property stringList prop: propProbe.found ? propProbe.prop : ["other"] Rule { multiplex: true outputFileTags: "the-output" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating dummy"; cmd.sourceCode = function() { console.info("prop: " + JSON.stringify(product.mymodule.prop)); } return [cmd]; } } } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/probes-and-array-properties.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-array-properties/probes-and-array-properties.q0000644000175100017510000000017615232633614033301 0ustar runnerrunnerProduct { name: "theProduct" type: ["the-output"] Depends { name: "mymodule" } // mymodule.prop: ["product"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/0000755000175100017510000000000015232633614022437 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/TestLib.h0000644000175100017510000000245115232633614024160 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TESTLIB_H #define TESTLIB_H int testFunction(); #endif // TESTLIB_H qbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/cpp-library.qbs0000644000175100017510000000134315232633614025373 0ustar runnerrunnerProject { property bool dummy: { if (qbs.toolchain.includes("emscripten")) { console.info("is emscripten"); } else if (qbs.targetOS.includes("windows")) { console.info("is windows"); } else if (qbs.targetOS.includes("darwin")) { console.info("is darwin"); } else if (qbs.targetOS.includes("unix")){ console.info("is unix"); } } CppLibrary { name: "testlib" publicHeaders: ["TestLib.h"] privateHeaders: ["TestLibPrivate.h"] files: ["TestLib.cpp"] qbs.installPrefix: "" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/TestLib.cpp0000644000175100017510000000260415232633614024513 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "TestLib.h" #include "TestLibPrivate.h" int testFunction() { privateFunction(); return 42; } void privateFunction() { // Private implementation } qbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/TestLibPrivate.h0000644000175100017510000000250215232633614025510 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TESTLIBPRIVATE_H #define TESTLIBPRIVATE_H void privateFunction(); #endif // TESTLIBPRIVATE_H qbs-src-3.3.1/tests/auto/blackbox/testdata/cpp-library/main.cpp0000644000175100017510000000244015232633614024067 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "TestLib.h" int main() { return testFunction() - 42; } qbs-src-3.3.1/tests/auto/blackbox/testdata/makefile-generator/0000755000175100017510000000000015232633614023754 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/makefile-generator/app.qbs0000644000175100017510000000154515232633614025250 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); console.info("executable suffix: " + cpp.executableSuffix); return result; } name: "the app" consoleApplication: true cpp.cxxLanguageVersion: "c++11" cpp.separateDebugInformation: false Properties { condition: qbs.targetOS.includes("macos") bundle.embedInfoPlist: false cpp.minimumMacosVersion: "10.7" } files: "main.cpp" qbs.installPrefix: "/usr/local" install: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/makefile-generator/main.cpp0000644000175100017510000000012315232633614025400 0ustar runnerrunner#include int main() { std::cout << "Hello, World!" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/0000755000175100017510000000000015232633614024256 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs0000644000175100017510000000226515232633614031035 0ustar runnerrunnerimport qbs.TextFile Product { type: ["txt.out"] qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } FileTagger { patterns: ["*.txt"] fileTags: ["txt.in"] } Rule { multiplex: true requiresInputs: false explicitlyDependsOn: ["txt.in"] Artifact { filePath: "output.txt" fileTags: product.type qbs.install: true } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var inputList = explicitlyDependsOn["txt.in"]; var fileNameList = []; for (var i = 0; i < inputList.length; ++i) fileNameList.push(inputList[i].fileName); fileNameList.sort(); var f = new TextFile(output.filePath, TextFile.WriteOnly); try { f.write(fileNameList.join('')); } finally { f.close(); } }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/0000755000175100017510000000000015232633614025034 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/file1.txt0000644000175100017510000000000015232633614026563 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/0000755000175100017510000000000015232633614026324 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/file2.txt0000644000175100017510000000000015232633614030054 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/0000755000175100017510000000000015232633614024245 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/0000755000175100017510000000000015232633614026467 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/missing-project-file.qbs0000644000175100017510000000011515232633614033225 0ustar runnerrunnerCppApplication { files: [ "file.cpp", "main.cpp" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/file.cpp0000644000175100017510000000001515232633614030106 0ustar runnerrunnervoid f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/main.cpp0000644000175100017510000000001615232633614030114 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/0000755000175100017510000000000015232633614027014 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p3.qbs0000644000175100017510000000000015232633614030033 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p2.qbs0000644000175100017510000000000015232633614030032 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p1.qbs0000644000175100017510000000000015232633614030031 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/empty-dir/0000755000175100017510000000000015232633614026157 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/missing-project-file/empty-dir/irrelevant.txt0000644000175100017510000000000015232633614031061 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/find/0000755000175100017510000000000015232633614021133 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/find/find-cli.qbs0000644000175100017510000000177115232633614023335 0ustar runnerrunnerimport qbs.TextFile Product { Depends { name: "cli"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["cli.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("cli", "present")) tools["toolchainInstallPath"] = product.moduleProperty("cli", "toolchainInstallPath"); var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/0000755000175100017510000000000015232633614025555 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file1.txt0000644000175100017510000000000015232633614027304 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file2.txt0000644000175100017510000000000015232633614027305 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file3.txt0000644000175100017510000000000015232633614027306 0ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/install-duplicates-no-error.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates-no-error/install-duplicates-no-error.q0000644000175100017510000000135415232633614033304 0ustar runnerrunnerProject { Product { name: "p1" Group { files: ["file1.txt"] qbs.install: true } } Product { name: "p2" Group { files: ["file1.txt"] qbs.install: true } } Product { name: "p3" Group { files: ["file2.txt"] qbs.install: true } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } Product { name: "p4" Group { files: ["file2.txt"] qbs.install: true } aggregate: true multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/0000755000175100017510000000000015232633614022220 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.cpp0000644000175100017510000000027715232633614025601 0ustar runnerrunner#include "foo.capnp.h" #include int main() { ::capnp::MallocMessageBuilder message; auto foo = message.initRoot(); foo.setStr("hello"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/imports/0000755000175100017510000000000015232633614023715 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/imports/foo.capnp0000644000175100017510000000011315232633614025516 0ustar runnerrunner@0x8a2efe67220790be; struct Foo { num @0 :UInt32; str @1 :Text; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/foo.capnp0000644000175100017510000000011315232633614024021 0ustar runnerrunner@0x8a2efe67220790be; struct Foo { num @0 :UInt32; str @1 :Text; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/greeter-client.cpp0000644000175100017510000000116515232633614025640 0ustar runnerrunner#include "greeter.capnp.h" #include #include int main(int argc, char *argv[]) { const char address[] = "localhost:5050"; capnp::EzRpcClient client(address); Greeter::Client greeter = client.getMain(); auto& waitScope = client.getWaitScope(); for (int i = 0; i < 2; ++i) { auto request = greeter.sayHelloRequest(); request.initRequest().setName("hello workd"); auto promise = request.send(); auto response = promise.wait(waitScope); std::cout << response.getResponse().getName().cStr() << std::endl; } return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs0000644000175100017510000000150015232633614030220 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "capnproto.cpp"; required: false } condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); if (!capnproto.cpp.present) console.info("capnproto is not present"); return result && capnproto.cpp.present; } cpp.minimumMacosVersion: "10.8" capnproto.cpp.importPaths: "." files: [ "baz.capnp", "capnproto_absolute_import.cpp", "imports/foo.capnp", ] qbs.buildVariant: "release" } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/greeter.capnp0000644000175100017510000000031315232633614024675 0ustar runnerrunner@0x85150b117366d14b; struct HelloRequest { name @0 :Text; } struct HelloResponse { name @0 :Text; } interface Greeter { sayHello @0 (request: HelloRequest) -> (response: HelloResponse); } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.qbs0000644000175100017510000000136415232633614030225 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "capnproto.cpp"; required: false } condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); if (!capnproto.cpp.present) console.info("capnproto is not present"); return result && capnproto.cpp.present; } cpp.minimumMacosVersion: "10.8" files: [ "bar.capnp", "capnproto_relative_import.cpp", "foo.capnp", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/conanfile.txt0000644000175100017510000000012015232633614024710 0ustar runnerrunner[requires] capnproto/1.0.2 [tool_requires] capnproto/1.0.2 [generators] QbsDeps qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/baz.capnp0000644000175100017510000000021315232633614024013 0ustar runnerrunner@0xc967c84bcca70a1d; using Foo = import "/imports/foo.capnp"; struct Baz { foo @0 :Foo.Foo; # Use type "Foo" defined in foo.capnp. } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/greeter-server.cpp0000644000175100017510000000130015232633614025657 0ustar runnerrunner#include "greeter.capnp.h" #include #include #include class GreeterImpl final: public Greeter::Server { public: ::kj::Promise sayHello(SayHelloContext context) override { auto response = context.getResults().initResponse(); response.setName(context.getParams().getRequest().getName()); return kj::READY_NOW; }; }; int main(int argc, char *argv[]) { const char address[] = "localhost:5050"; capnp::EzRpcServer server(kj::heap(), address); auto& waitScope = server.getWaitScope(); // Run forever, accepting connections and handling requests. kj::NEVER_DONE.wait(waitScope); } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.cpp0000644000175100017510000000033515232633614030222 0ustar runnerrunner#include "baz.capnp.h" #include int main() { ::capnp::MallocMessageBuilder message; auto baz = message.initRoot(); auto foo = baz.initFoo(); foo.setStr("hello"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.cpp0000644000175100017510000000033515232633614030217 0ustar runnerrunner#include "bar.capnp.h" #include int main() { ::capnp::MallocMessageBuilder message; auto bar = message.initRoot(); auto foo = bar.initFoo(); foo.setStr("hello"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs0000644000175100017510000000267715232633614025242 0ustar runnerrunnerimport qbs.Host Project { CppApplication { Depends { name: "capnproto.cpp"; required: false } condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); if (!capnproto.cpp.present) console.info("capnproto is not present"); return result && capnproto.cpp.present; } name: "server" consoleApplication: true cpp.minimumMacosVersion: "10.8" // workaround for broken capnproto cpp.libraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] capnproto.cpp.useRpc: true files: [ "greeter.capnp", "greeter-server.cpp" ] qbs.buildVariant: "release" } CppApplication { Depends { name: "capnproto.cpp"; required: false } name: "client" consoleApplication: true capnproto.cpp.useRpc: true cpp.minimumMacosVersion: "10.8" cpp.libraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] files: [ "greeter.capnp", "greeter-client.cpp" ] qbs.buildVariant: "release" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs0000644000175100017510000000136215232633614025600 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "capnproto.cpp"; required: false } condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); if (!capnproto.cpp.present) console.info("capnproto is not present"); return result && capnproto.cpp.present; } cpp.minimumMacosVersion: "10.8" files: [ "capnproto_cpp.cpp", "foo.capnp" ] qbs.buildVariant: "release" } qbs-src-3.3.1/tests/auto/blackbox/testdata/capnproto/bar.capnp0000644000175100017510000000020215232633614024001 0ustar runnerrunner@0xc967c84bcca70a1d; using Foo = import "foo.capnp"; struct Bar { foo @0 :Foo.Foo; # Use type "Foo" defined in foo.capnp. } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/0000755000175100017510000000000015232633614025734 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/0000755000175100017510000000000015232633614027404 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newermodule/0000755000175100017510000000000015232633614031732 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newermodule/newermodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newermodule/newermod0000644000175100017510000000011315232633614033470 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++14" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/oldmodule/0000755000175100017510000000000015232633614031370 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/oldmodule/oldmodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/oldmodule/oldmodule.0000644000175100017510000000011315232633614033350 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/0000755000175100017510000000000015232633614032117 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestmodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestm0000644000175100017510000000011315232633614033517 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++26" } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/maximum-cxx-language-version.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/maximum-cxx-language-version0000644000175100017510000000036015232633614033377 0ustar runnerrunnerCppApplication { name: "app" property bool enableNewestModule: true Depends { name: "oldmodule" } Depends { name: "newermodule" } Depends { name: "newestmodule"; condition: enableNewestModule } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/main.cpp0000644000175100017510000000001615232633614027361 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/require/0000755000175100017510000000000015232633614021667 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/require/blubb.js0000644000175100017510000000061415232633614023314 0ustar runnerrunnervar TextFile = require("qbs.TextFile") var zort = require("./zort.js") function createCommands(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Write an empty file"; cmd.filePath = filePaths[0]; cmd.sourceCode = function() { var f = new TextFile(filePath, TextFile.WriteOnly); f.close(); } return [cmd, zort.createCommand(filePaths)]; } qbs-src-3.3.1/tests/auto/blackbox/testdata/require/require.qbs0000644000175100017510000000071615232633614024056 0ustar runnerrunnerimport 'blubb.js' as blubb Product { type: ["text"] Rule { multiplex: true Artifact { fileTags: ["text"] filePath: "one.txt" } Artifact { fileTags: ["text"] filePath: "two.txt" } prepare: { var filePaths = outputs.text.map(function (artifact) {return artifact.filePath; }); return blubb.createCommands(filePaths); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/require/zort.js0000644000175100017510000000044715232633614023230 0ustar runnerrunnervar File = require("qbs.File") function createCommand(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Create another empty file"; cmd.filePaths = filePaths; cmd.sourceCode = function() { File.copy(filePaths[0], filePaths[1]); }; return cmd; } qbs-src-3.3.1/tests/auto/blackbox/testdata/prevent-floating-point-values/0000755000175100017510000000000015232633614026123 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/prevent-floating-point-values/prevent-floating-point-values.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/prevent-floating-point-values/prevent-floating-point-valu0000644000175100017510000000013415232633614033424 0ustar runnerrunnerProduct { name: "p" property bool dummy: { console.info("version: " + version); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/0000755000175100017510000000000015232633614022461 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/modules/0000755000175100017510000000000015232633614024131 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/modules/mymodule/0000755000175100017510000000000015232633614025764 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/modules/mymodule/mymodule.qbs0000644000175100017510000000014415232633614030325 0ustar runnerrunnerimport qbs.Environment Module { setupRunEnvironment: { Environment.putEnv("MY_MODULE", 1); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/lib.cpp0000644000175100017510000000001515232633614023727 0ustar runnerrunnervoid f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/file1.cpp0000644000175100017510000000001515232633614024161 0ustar runnerrunnervoid f1() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/file2.cpp0000644000175100017510000000001515232633614024162 0ustar runnerrunnervoid f2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/lib.h0000644000175100017510000000001215232633614023371 0ustar runnerrunnervoid f(); qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/main.cpp0000644000175100017510000000013115232633614024104 0ustar runnerrunnerint main() { int i; // Should trigger a warning and thus a process-exited message. } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-session/qbs-session.qbs0000644000175100017510000000076515232633614025446 0ustar runnerrunnerProject { StaticLibrary { name: "theLib" Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" Group { name: "sources" files: "lib.cpp" } Group { name: "headers" files: "lib.h" } } CppApplication { name: "theApp" consoleApplication: true cpp.cxxLanguageVersion: "c++14" cpp.warningLevel: "all" files: "main.cpp" install: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/0000755000175100017510000000000015232633614024373 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/three.txt0000644000175100017510000000000015232633614026231 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/one.txt0000644000175100017510000000000015232633614025703 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/two.txt0000644000175100017510000000000015232633614025733 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/dynamicMultiplexRule.qbs0000644000175100017510000000155715232633614031272 0ustar runnerrunnerimport qbs.TextFile Project { Product { type: ["stuff"] Group { files: ["one.txt", "two.txt", "three.txt"] fileTags: ["text"] } Rule { multiplex: true inputs: "text" outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: "stuff-from-" + inputs.text.length + "-inputs", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("narf!"); f.close(); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiplexed-tool/0000755000175100017510000000000015232633614023522 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/multiplexed-tool/tool.cpp0000644000175100017510000000013015232633614025175 0ustar runnerrunner#include int main() { #ifdef WRONG_VARIANT return EXIT_FAILURE; #endif } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs0000644000175100017510000000442515232633614027545 0ustar runnerrunnerimport qbs.Host Project { CppApplication { name: "tool" targetName: { var result = name; if (qbs.buildVariant === "debug") result += "-debug"; return result; } consoleApplication: true property bool _testPlatform: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Profile { name: "debugProfile" baseProfile: project.profile qbs.buildVariant: "debug" } Profile { name: "releaseProfile" baseProfile: project.profile qbs.buildVariant: "release" } multiplexByQbsProperties: "profiles" qbs.profiles: ["debugProfile", "releaseProfile"] files: "tool.cpp" Properties { condition: qbs.buildVariant === "debug" cpp.defines: "WRONG_VARIANT" } Export { Rule { multiplex: true inputsFromDependencies: "application" Artifact { filePath: "tool.out" fileTags: "tool.output" } prepare: { var cmd = new Command(input.filePath, []); cmd.description = "creating " + output.fileName; return cmd; } } } } Product { name: "p" type: "tool.output" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Depends { name: "tool"; profiles: "releaseProfile" } } Product { name: "p2" type: "tool.output" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Depends { name: "helper" } } Product { name: "helper" Export { Depends { name: "tool"; profiles: "releaseProfile" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-products/0000755000175100017510000000000015232633614023027 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-products/list-products.qbs0000644000175100017510000000043615232633614026355 0ustar runnerrunnerProject { Product { name: "a" } Product { name: "b" multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["mips", "vax"] qbs.buildVariants: ["debug", "release"] } Product { name: "c" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/0000755000175100017510000000000015232633614030010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/0000755000175100017510000000000015232633614031460 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/broken/0000755000175100017510000000000015232633614032740 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/broken/broken.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/broken/br0000644000175100017510000000005615232633614033267 0ustar runnerrunnerModule { validate: { throw "broken!"; } } ././@LongLink0000644000000000000000000000017700000000000011610 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/exported-dependency-in-disabled-product.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/exported-dependen0000644000175100017510000000065115232633614033347 0ustar runnerrunnerProject { Application { name: "app" Depends { name: "dep"; required: false } files: "main.cpp" } Product { name: "dep" condition: eval(conditionString) property string conditionString Depends { name: "nosuchmodule"; required: false } Depends { name: "broken"; required: false } Export { Depends { name: "cpp" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/main.cpp0000644000175100017510000000001615232633614031435 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/project_filepath_check/0000755000175100017510000000000015232633614024672 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/project_filepath_check/project1.qbs0000644000175100017510000000005115232633614027124 0ustar runnerrunnerCppApplication { files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/project_filepath_check/project2.qbs0000644000175100017510000000005215232633614027126 0ustar runnerrunnerCppApplication { files: "main2.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/project_filepath_check/main2.cpp0000644000175100017510000000001615232633614026401 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/project_filepath_check/main.cpp0000644000175100017510000000235115232633614026323 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-property-values/0000755000175100017510000000000015232633614025671 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.q0000644000175100017510000000206115232633614033530 0ustar runnerrunnerProject { Product { name: "low" Export { property string prop: "low"; property string prop2: "low" } } Product { name: "higher1" Export { Depends { name: "low" } low.prop: "higher1" } } Product { name: "higher2" Export { Depends { name: "low" } low.prop: "higher2" } } Product { name: "highest1" Export { Depends { name: "low" } Depends { name: "higher1" } Depends { name: "higher2" } low.prop: "highest1" low.prop2: "highest" } } Product { name: "highest2" Export { Depends { name: "low" } Depends { name: "higher1" } Depends { name: "higher2" } low.prop: "highest2" low.prop2: "highest" } } Product { name: "toplevel" Depends { name: "highest1" } Depends { name: "highest2" } low.prop: name property bool dummy: { console.info("final prop value: " + low.prop); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-file/0000755000175100017510000000000015232633614023664 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-file/file.qbs0000644000175100017510000000506515232633614025320 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var origPath = FileInfo.joinPaths(product.sourceDirectory, "original.txt"); var copyPath = FileInfo.joinPaths(product.sourceDirectory, "copy.txt"); console.info("copy path: "+copyPath); var original = new TextFile(origPath, TextFile.WriteOnly); original.close(); File.copy(origPath, copyPath); var origTimestamp = File.lastModified(origPath); var copyTimestamp = File.lastModified(copyPath); if (origTimestamp > copyTimestamp) throw new Error("Older file has newer timestamp."); File.remove(origPath); var copy = new TextFile(copyPath, TextFile.WriteOnly); copy.writeLine(File.exists(origPath)); copy.writeLine(File.exists(copyPath)); copy.close(); var zePath = FileInfo.joinPaths(product.sourceDirectory, "zePath"); if (File.exists(zePath)) throw new Error(zePath + " already exists."); var created = File.makePath(zePath); if (!created || !File.exists(zePath)) throw new Error("zePath was not created."); var entries = File.directoryEntries(product.sourceDirectory, File.AllEntries | File.NoDotAndDotDot); if (entries.length < 3 || !entries.includes("file.qbs")) throw new Error("Directory did not contain file.qbs"); entries = File.directoryEntries(product.sourceDirectory, File.Dirs | File.NoDotAndDotDot); if (entries.length < 1 || !entries.includes("zePath")) throw new Error("Directory did not contain only zePath"); var moveSource = FileInfo.joinPaths(product.sourceDirectory, "tomove.txt"); var moveTarget = FileInfo.joinPaths(product.sourceDirectory, "moved.txt"); File.move(moveSource, moveTarget); if (File.exists(moveSource)) throw new Error("Moved file still exists under old name"); if (!File.exists(moveTarget)) throw new Error("Moved file does not exist under new name"); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/properties-in-export-items/0000755000175100017510000000000015232633614025451 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/properties-in-export-items/properties-in-export-items.qbs0000644000175100017510000000137215232633614033421 0ustar runnerrunnerProject { minimumQbsVersion: "1.6" Product { name: "dep" Export { property string theDefine: "" Depends { name: "cpp" } cpp.defines: [theDefine] } } Application { name: "p1" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "dep" } dep.theDefine: "P1" cpp.minimumMacosVersion: "10.9" files: ["main1.cpp"] } Application { name: "p2" consoleApplication: true Depends { name: "dep" } cpp.minimumMacosVersion: "10.9" Group { dep.theDefine: "P2" files: ["main2.cpp"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/properties-in-export-items/main2.cpp0000644000175100017510000000237315232633614027170 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef P2 int main() { } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/properties-in-export-items/main1.cpp0000644000175100017510000000237315232633614027167 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef P1 int main() { } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/reproducible-build/0000755000175100017510000000000015232633614023767 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/reproducible-build/file1.cpp0000644000175100017510000000240315232633614025472 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ static void f() { } void f1() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs0000644000175100017510000000067615232633614030263 0ustar runnerrunnerCppApplication { name: "the product" files: ["file1.cpp", "file2.cpp", "main.cpp"] cpp.cxxFlags: ["-flto"] Probe { id: checker property bool isGcc: qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("clang") property string objectSuffix: cpp.objectSuffix configure: { console.info("is gcc: " + isGcc); console.info("object suffix: " + objectSuffix); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/reproducible-build/file2.cpp0000644000175100017510000000240315232633614025473 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ static void f() { } void f2() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/reproducible-build/main.cpp0000644000175100017510000000242515232633614025422 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f1(); void f2(); int main() { f1(); f2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/0000755000175100017510000000000015232633614023647 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/0000755000175100017510000000000015232633614025317 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/m/0000755000175100017510000000000015232633614025553 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m4.qbs0000644000175100017510000000015415232633614026602 0ustar runnerrunnerModule { condition: qbs.architecture === "d" validate: { console.info("loaded m4"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m3.qbs0000644000175100017510000000015415232633614026601 0ustar runnerrunnerModule { condition: qbs.architecture === "c" validate: { console.info("loaded m3"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m1.qbs0000644000175100017510000000015415232633614026577 0ustar runnerrunnerModule { condition: qbs.architecture === "a" validate: { console.info("loaded m1"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m2.qbs0000644000175100017510000000015415232633614026600 0ustar runnerrunnerModule { condition: qbs.architecture === "b" validate: { console.info("loaded m2"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs0000644000175100017510000000061515232633614030014 0ustar runnerrunnerProject { Product { name: "p1" qbs.architecture: "a" Depends { name: "m" } } Product { name: "p2" qbs.architecture: "b" Depends { name: "m" } } Product { name: "p3" multiplexByQbsProperties: "architectures" aggregate: false qbs.architectures: ["b", "c", "d"] Depends { name: "m" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-artifact-path/0000755000175100017510000000000015232633614024366 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs0000644000175100017510000000065215232633614031253 0ustar runnerrunnerProject { property string artifactDir Product { type: "t" Rule { multiplex: true Artifact { filePath: project.artifactDir + "/file.out" fileTags: "t" } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() {}; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/filetagsfilter-merging/0000755000175100017510000000000015232633614024645 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/filetagsfilter-merging/filetagsfilter-merging.qbs0000644000175100017510000000144515232633614032012 0ustar runnerrunnerimport qbs.TextFile MyApplication { name: "myapp" type: base.concat("extra-output") property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" Group { fileTagsFilter: "application" qbs.installDir: "binDir" fileTags: "extra-input" } Rule { inputs: "extra-input" Artifact { filePath: input.baseName + ".txt" fileTags: "extra-output" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/filetagsfilter-merging/main.cpp0000644000175100017510000000001615232633614026272 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/filetagsfilter-merging/MyApplication.qbs0000644000175100017510000000031115232633614030120 0ustar runnerrunnerCppApplication { consoleApplication: true Group { fileTagsFilter: "application" qbs.install:true qbs.installPrefix: product.name qbs.installDir: "wrong" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/driver-linker-flags/0000755000175100017510000000000015232633614024062 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/driver-linker-flags/main.cpp0000644000175100017510000000001615232633614025507 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs0000644000175100017510000000054515232633614030444 0ustar runnerrunnerCppApplication { files: "main.cpp" Properties { condition: toolchainProbe.found cpp.driverLinkerFlags: ["-nostartfiles"] } Probe { id: toolchainProbe condition: qbs.toolchain.includes("gcc") configure: { console.info("toolchain is GCC-like"); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/retagged-output-artifact/0000755000175100017510000000000015232633614025126 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/retagged-output-artifact/retagged-output-artifact.qbs0000644000175100017510000000242715232633614032555 0ustar runnerrunnerimport qbs.File import qbs.TextFile Product { name: "p" type: "p_type" property bool useTag1 Rule { multiplex: true outputFileTags: ["tag1", "tag2"] outputArtifacts: [{filePath: "a1.txt", fileTags: product.useTag1 ? "tag1" : "tag2"}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { inputs: "tag1" Artifact { filePath: "a2.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: "tag2" Artifact { filePath: "a3.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/0000755000175100017510000000000015232633614024161 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/0000755000175100017510000000000015232633614025631 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/lower/0000755000175100017510000000000015232633614026761 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs0000644000175100017510000000073115232633614030621 0ustar runnerrunnerModule { property stringList listProp: [ "lower" ] Rule { inputs: ["intype"] Artifact { filePath: "dummy.out" fileTags: "outtype" } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { console.warn("listProp = " + JSON.stringify(product.lower.listProp)); }; cmd.silent = true; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher2/0000755000175100017510000000000015232633614027161 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher2/higher2.qbs0000644000175100017510000000011115232633614031211 0ustar runnerrunnerModule { Depends { name: "lower" } lower.listProp: ["higher2"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher3/0000755000175100017510000000000015232633614027162 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher3/higher3.qbs0000644000175100017510000000011115232633614031213 0ustar runnerrunnerModule { Depends { name: "lower" } lower.listProp: ["higher3"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher1/0000755000175100017510000000000015232633614027160 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/modules/higher1/higher1.qbs0000644000175100017510000000011115232633614031207 0ustar runnerrunnerModule { Depends { name: "lower" } lower.listProp: ["higher1"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/product.qbs0000644000175100017510000000040115232633614026343 0ustar runnerrunnerProduct { type: "outtype" name: "toplevel" Depends { name: "higher1" } Depends { name: "higher2" } Depends { name: "higher3" } lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-property-order/dummy.txt0000644000175100017510000000000015232633614026043 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-list-in-probe/0000755000175100017510000000000015232633614023631 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs0000644000175100017510000000050215232633614027753 0ustar runnerrunnerProject { CppApplication { Probe { id: theProbe property pathList result configure: { result = ["main.cpp"] found = true } } property pathList res: theProbe.found ? theProbe.result : [] Group { name: "files" files: res } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp0000644000175100017510000000003415232633614025256 0ustar runnerrunnerint main() { return 0; }qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/0000755000175100017510000000000015232633614025041 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/test.in0000644000175100017510000000000015232633614026336 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/0000755000175100017510000000000015232633614026511 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/myothermodule/0000755000175100017510000000000015232633614031406 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/myothermodule/myothermodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/myothermodule/myothermod0000644000175100017510000000012115232633614033512 0ustar runnerrunnerModule { Depends { name: "depmodule" } depmodule.listProp: ["myother"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/0000755000175100017510000000000015232633614030467 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs0000644000175100017510000000077415232633614033164 0ustar runnerrunnerModule { property string prop property stringList listProp: [] Rule { inputs: ["dep-in"] outputFileTags: "dep-out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating dep-out artifact"; cmd.sourceCode = function() { console.info("prop: " + product.depmodule.prop); console.info("listProp: " + product.depmodule.listProp); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/0000755000175100017510000000000015232633614030344 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs0000644000175100017510000000113615232633614032707 0ustar runnerrunnerModule { Depends { name: "depmodule" } Probe { id: theProbe configure: { found = true; } } property bool found: theProbe.found depmodule.prop: found ? "yes" : "no" depmodule.listProp: theProbe.found ? ["my"] : [] Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating out artifact"; cmd.sourceCode = function() { console.info("found: " + product.mymodule.found); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/test2.in0000644000175100017510000000000015232633614026420 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs0000644000175100017510000000010115232633614032366 0ustar runnerrunnerProject { references: [ "dependee.qbs", "dependency.qbs" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs0000644000175100017510000000042415232633614027321 0ustar runnerrunnerProduct { name: "dependee" Depends { name: "myothermodule" } Depends { name: "dependency" } type: ["out", "dep-out"] Group { files: "test.in" fileTags: ["dep-in"] } Group { files: "test2.in" fileTags: ["in"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs0000644000175100017510000000013315232633614027663 0ustar runnerrunnerProduct { name: "dependency" Export { Depends { name: "mymodule" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/0000755000175100017510000000000015232633614021011 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/0000755000175100017510000000000015232633614022461 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/0000755000175100017510000000000015232633614023716 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/0000755000175100017510000000000015232633614024235 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs0000644000175100017510000000001315232633614025255 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/0000755000175100017510000000000015232633614024234 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs0000644000175100017510000000001315232633614025253 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/0000755000175100017510000000000015232633614024233 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs0000644000175100017510000000011315232633614025252 0ustar runnerrunnerModule { property bool p1 property string p2 property bool x } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/m/0000755000175100017510000000000015232633614022715 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs0000644000175100017510000000005115232633614023654 0ustar runnerrunnerModule { property bool prop: false } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/lsp.qbs0000644000175100017510000000101715232633614022315 0ustar runnerrunnerProject { Product { name: "dep" Depends { name: "m" } Depends { name: "Prefix"; submodules: ["m1", "m2", "m3"] } m.prop: true } Product { Depends { name: "dep" } files: "toplevel.txt" Group { prefix: "subdir/" Group { files: ["file1.txt", "file2.txt"] } } } references: "other.qbs" MyProduct { name: "dummy" } Product { name: "p" Depends { name: "Prefix.m1" } Prefix.m1.p1: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/MyProduct.qbs0000644000175100017510000000016615232633614023451 0ustar runnerrunner// This is a simple forwarder ... /* ... that we are indenting to test non-zero line and column numbers */ Product {} qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/other.qbs0000644000175100017510000000001315232633614022633 0ustar runnerrunnerProduct {} qbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/subdir/0000755000175100017510000000000015232633614022301 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/subdir/file1.txt0000644000175100017510000000000015232633614024030 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/subdir/file2.txt0000644000175100017510000000000015232633614024031 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lsp/toplevel.txt0000644000175100017510000000000015232633614023372 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/0000755000175100017510000000000015232633614025012 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/modules/0000755000175100017510000000000015232633614026462 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/modules/buildenv/0000755000175100017510000000000015232633614030272 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/modules/buildenv/buildenv.qbs0000644000175100017510000000031415232633614032607 0ustar runnerrunnerimport qbs.Environment Module { property string varPrefix: "BUILD_ENV_" setupBuildEnvironment: { Environment.putEnv(product.buildenv.varPrefix + product.name.toUpperCase(), "1"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/modules/m/0000755000175100017510000000000015232633614026716 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/modules/m/m.qbs0000644000175100017510000000130015232633614027653 0ustar runnerrunnerimport qbs.Environment import qbs.TextFile Module { additionalProductTypes: ["m.target"] Rule { multiplex: true Artifact { filePath: "m.output" fileTags: "m.target" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); var env = Environment.getEnv("BUILD_ENV_" + product.name.toUpperCase()); if (env) f.writeLine(env); f.close(); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-build-environment/setup-build-environment.qbs0000644000175100017510000000032215232633614032315 0ustar runnerrunnerProject { Product { name: "first_product" Depends { name: "buildenv" } Depends { name: "m" } } Product { name: "second_product" Depends { name: "m" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/0000755000175100017510000000000015232633614025170 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/0000755000175100017510000000000015232633614026640 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/0000755000175100017510000000000015232633614031151 5ustar runnerrunner././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib0000644000175100017510000000134415232633614033407 0ustar runnerrunnerimport qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) cpp.rpaths: [product.theotherlib.baseDir] Group { name: "theotherlib dll" files: FileInfo.joinPaths(product.theotherlib.baseDir, cpp.dynamicLibraryPrefix + "theotherlib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "theotherlib dll import" condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.theotherlib.baseDir, "theotherlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thethirdlib/0000755000175100017510000000000015232633614031142 5ustar runnerrunner././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thethirdlib/thethirdlib.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thethirdlib/thethirdlib0000644000175100017510000000126415232633614033372 0ustar runnerrunnerimport qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) Group { name: "thethirdlib dll" condition: false files: FileInfo.joinPaths(product.theotherlib.baseDir, cpp.dynamicLibraryPrefix + "thethirdlib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "thethirdlib dll import" condition: false files: FileInfo.joinPaths(product.thethirdlib.baseDir, "thethirdlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/0000755000175100017510000000000015232633614030107 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs0000644000175100017510000000150515232633614032066 0ustar runnerrunnerimport qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) cpp.rpaths: [product.thelib.baseDir] Group { name: "thelib dll" files: FileInfo.joinPaths(product.thelib.baseDir, cpp.dynamicLibraryPrefix + "thelib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "thelib dll import" condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.thelib.baseDir, "thelib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } Group { name: "to be ignored" filesAreTargets: true files: "broken.cpp" fileTags: ["cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/broken.cpp0000644000175100017510000000001515232633614032067 0ustar runnerrunnersyntax error qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib3.cpp0000644000175100017510000000021615232633614026524 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void theThirdLibFunc() { std::cout << "Hello from thethirdlib!" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib2.cpp0000644000175100017510000000021615232633614026523 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void theOtherLibFunc() { std::cout << "Hello from theotherlib!" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib5.cpp0000644000175100017510000000003115232633614026521 0ustar runnerrunnervoid staticLibFunc() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/thelibs.qbs0000644000175100017510000000033115232633614027326 0ustar runnerrunnerProject { Dll { name: "thelib" files: "lib1.cpp" } Dll { name: "theotherlib" files: "lib2.cpp" } Dll { name: "thethirdlib" files: "lib3.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/main.cpp0000644000175100017510000000032415232633614026617 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void theOtherLibFunc(); DLL_IMPORT void theFourthLibFunc(); void theThirdLibFunc() { } int main() { theOtherLibFunc(); theThirdLibFunc(); theFourthLibFunc(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib1.cpp0000644000175100017510000000020415232633614026517 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void theLibFunc() { std::cout << "Hello from thelib!" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs0000644000175100017510000000062015232633614026410 0ustar runnerrunnerDynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.minimumMacosVersion: "10.7" // For -rpath } install: true installImportLib: true qbs.installPrefix: "" installDir: "" importLibInstallDir: "" } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib4.cpp0000644000175100017510000000016315232633614026526 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void theLibFunc(); DLL_EXPORT void theFourthLibFunc() { theLibFunc(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs0000644000175100017510000000237215232633614027164 0ustar runnerrunnerimport qbs.Host Project { CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "theapp" cpp.minimumMacosVersion: "10.7" // For -rpath Depends { name: "theotherlib" } Depends { name: "thethirdlib" } Depends { name: "thefourthlib" } Depends { name: "staticlib" } files: "main.cpp" Group { fileTagsFilter: "dynamiclibrary" qbs.install: true qbs.installSourceBase: buildDirectory } } Dll { name: "thefourthlib" Depends { name: "thelib" } files: "lib4.cpp" Export { Depends { name: "cpp" } cpp.rpaths: [qbs.installRoot] } } StaticLibrary { name: "staticlib" Depends { name: "cpp" } Depends { name: "theotherlib" } files: "lib5.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/0000755000175100017510000000000015232633614025654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/including.cpp0000644000175100017510000000240515232633614030335 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/jsFileChange.cpp0000644000175100017510000000236315232633614030706 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void jsFileChange() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js0000644000175100017510000000025515232633614027767 0ustar runnerrunnervar File = require("qbs.File"); function fileList() { return []; } function filesFromFs(path) { return File.exists(path + "/fileExists.cpp") ? ["fileExists.cpp"] : []; } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.q0000644000175100017510000000125315232633614033500 0ustar runnerrunnerimport qbs.Environment import "fileList.js" as FileList CppApplication { property stringList filesFromEnv: Environment.getEnv("QBS_TEST_PULL_IN_FILE_VIA_ENV") ? ["environmentChange.cpp"] : [] files: ["main.cpp"].concat(FileList.fileList()).concat(filesFromEnv).concat(FileList.filesFromFs(path)) Group { condition: Environment.getEnv("INCLUDE_PATH_TEST") name: "file that needs help from the environment to find a header" files: "including.cpp" } Probe { id: checker property bool isGcc: qbs.toolchain.contains("gcc") configure: { console.info("is gcc: " + isGcc); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/main.cpp0000644000175100017510000000235215232633614027306 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/environmentChange.cpp0000644000175100017510000000237015232633614032034 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void environmentChange() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/0000755000175100017510000000000015232633614027107 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/hiddenheaderqbs.h0000644000175100017510000000233215232633614032372 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/0000755000175100017510000000000015232633614022502 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/imports/0000755000175100017510000000000015232633614024177 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/imports/Helper2/0000755000175100017510000000000015232633614025500 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/imports/Helper2/helper2.js0000644000175100017510000000002615232633614027375 0ustar runnerrunnervar suffix = ".tool"; qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/tool.qbs0000644000175100017510000000327615232633614024176 0ustar runnerrunnerimport qbs.FileInfo import "helper.js" as Helper import Helper2 CppApplication { name: "MyTool" consoleApplication: true property stringList toolTags: ["MyTool.tool"] Depends { name: "Exporter.qbs" } Exporter.qbs.artifactTypes: ["installable", "blubb"] files: ["tool.cpp"] install: true qbs.installPrefix: project.installPrefix Group { files: ["helper.js"] qbs.install: true qbs.installDir: "qbs/modules/MyTool" } Group { files: ["imports/Helper2/helper2.js"] qbs.install: true qbs.installDir: "qbs/imports/Helper2" } Group { fileTagsFilter: ["application"] fileTags: toolTags } Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.installDir: "qbs/modules/MyTool" } Export { property stringList toolTags: exportingProduct.toolTags property stringList outTags: [importingProduct.outTag] property var helper2Obj: Helper2 Rule { inputs: Helper.toolInputs() explicitlyDependsOnFromDependencies: toolTags outputFileTags: parent.outTags outputArtifacts: [{ filePath: FileInfo.completeBaseName(input.fileName) + product.MyTool.helper2Obj.suffix, fileTags: product.MyTool.outTags }] prepare: { var cmd = new Command(explicitlyDependsOn["MyTool.tool"][0].filePath, [input.filePath, output.filePath]); cmd.description = "compiling" + input.fileName + " to " + output.fileName; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/helper.js0000644000175100017510000000005515232633614024317 0ustar runnerrunnerfunction toolInputs() { return ["cpp.in"]; } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/exports-qbs-products.qbs0000644000175100017510000000000015232633614027327 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs0000644000175100017510000000206615232633614025050 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() // if cpp module is not available, we can't check the architecture && (qbs.architecture === undefined || qbs.architecture === Host.architecture()); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "consumer" qbsSearchPaths: "default/install-root/usr/qbs" property string outTag: "cpp" Depends { name: "MyLib" } Depends { name: "MyTool" } files: ["consumer.cpp"] cpp.defines: { var defs = []; if (MyLib.configuration.feature_x) defs.push("FEATURE_X"); if (MyLib.configuration.feature_y) defs.push("FEATURE_Y"); return defs; } Group { files: ["helper.cpp.in"] fileTags: ["cpp.in"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/consumer.cpp0000644000175100017510000000005515232633614025041 0ustar runnerrunnervoid helper(); int main() { helper(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/exports-qbs.qbs0000644000175100017510000000055115232633614025501 0ustar runnerrunnerimport qbs.FileInfo Project { property string installPrefix: "/usr" qbsSearchPaths: sourceDirectory Product { name: "local" Export { property bool dummy Depends { name: "cpp" } cpp.includePaths: ["/somelocaldir/include"] } } references: ["consumer.qbs", "lib.qbs", "tool.qbs"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/mylib.h0000644000175100017510000000063015232633614023766 0ustar runnerrunner#if defined(_WIN32) || defined(WIN32) # define DLL_EXPORT __declspec(dllexport) # define DLL_IMPORT __declspec(dllimport) #else # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_IMPORT __attribute__((visibility("default"))) # endif #ifdef MYLIB_BUILD #define MYLIB_EXPORT DLL_EXPORT #else #define MYLIB_EXPORT DLL_IMPORT #endif namespace MyLib { MYLIB_EXPORT void f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/tool.cpp0000644000175100017510000000060315232633614024162 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { if (argc != 3) return EXIT_FAILURE; std::ifstream in(argv[1]); if (!in) return EXIT_FAILURE; std::ofstream out(argv[2]); if (!out) return EXIT_FAILURE; char ch; while (in.get(ch)) out.put(ch); return in.eof() && out ? EXIT_SUCCESS : EXIT_FAILURE; } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/lib.qbs0000644000175100017510000000360515232633614023763 0ustar runnerrunnerimport qbs.FileInfo DynamicLibrary { name: "MyLib" multiplexByQbsProperties: ["buildVariants"] aggregate: false qbs.buildVariants: ["debug", "release"] qbs.installPrefix: project.installPrefix Depends { name: "cpp" } Depends { name: "Exporter.qbs" } Exporter.qbs.fileName: name + "_" + qbs.buildVariant + ".qbs" Exporter.qbs.excludedDependencies: ["local"] Exporter.qbs.additionalContent: " condition: qbs.buildVariant === '" + qbs.buildVariant + "'" property string headersInstallDir: "include" cpp.defines: ["MYLIB_BUILD"] cpp.variantSuffix: qbs.buildVariant === "debug" ? "d" : "" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["mylib.cpp"] property var configuration: ({feature_x: false, feature_y: true}) Group { name: "API headers" files: ["mylib.h"] qbs.install: true qbs.installDir: headersInstallDir } install: true installImportLib: true installDir: "lib" Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.install: true qbs.installDir: "qbs/modules/MyLib" } Export { Depends { name: "cpp" } property string includeDir: exportingProduct.sourceDirectory property var configuration: exportingProduct.configuration Properties { cpp.includePaths: [includeDir] cpp.dynamicLibraries: [] } Properties { condition: undefined cpp.dynamicLibraries: ["nosuchlib"] } Depends { name: "local" } local.dummy: true Properties { prefixMapping: [{ prefix: includeDir, replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) }] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/helper.cpp.in0000644000175100017510000000026115232633614025071 0ustar runnerrunner#include #ifdef FEATURE_X #error "feature x must not be present!" #endif #ifndef FEATURE_Y #error "feature y is required!" #endif void helper() { MyLib::f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-qbs/mylib.cpp0000644000175100017510000000006415232633614024322 0ustar runnerrunner#include "mylib.h" namespace MyLib { void f() {} } qbs-src-3.3.1/tests/auto/blackbox/testdata/new-output-artifact/0000755000175100017510000000000015232633614024135 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs0000644000175100017510000000175715232633614030600 0ustar runnerrunnerimport qbs.TextFile Product { name: "theProduct" type: ["output"] property int artifactCount: 99 Group { files: ["input.txt"] fileTags: ["input"] } qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true } Rule { inputs: ["input"] outputFileTags: ["output"] outputArtifacts: { var list = []; for (var i = 0; i < product.artifactCount; ++i) list.push({ filePath: "output_" + i + ".out", fileTags: ["output"]}); return list; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["output"].length; ++i) { var f = new TextFile(outputs["output"][i].filePath, TextFile.WriteOnly); f.close(); } } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/new-output-artifact/input.txt0000644000175100017510000000000015232633614026023 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/0000755000175100017510000000000015232633614022304 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/main.c0000644000175100017510000000247515232633614023404 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { void *memory = malloc(8); free(memory); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/main.mm0000644000175100017510000000022415232633614023561 0ustar runnerrunner#include #include int main() { std::string s = "Hello World"; (void)s; sel_registerName("qbs"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/main.s0000644000175100017510000000004715232633614023415 0ustar runnerrunner.globl _main .globl main _main: main: qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/main.m0000644000175100017510000000012215232633614023401 0ustar runnerrunner#include int main() { sel_registerName("qbs"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/staticmain.c0000644000175100017510000000241715232633614024610 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ extern int cpp(); int main() { return cpp(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/main.cpp0000644000175100017510000000247315232633614023742 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::string s = "Hello World"; (void)s; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs0000644000175100017510000000273015232633614025106 0ustar runnerrunnerProject { CppApplication { consoleApplication: true name: "LinkedProduct-Assembly" property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } files: qbs.targetOS.includes("darwin") ? "darwin.s" : "main.s" installDir: "" cpp.linkerPath: cpp.compilerPathByLanguage["c"] } CppApplication { consoleApplication: true name: "LinkedProduct-C" files: ["main.c"] installDir: "" } CppApplication { condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C" files: ["main.m"] installDir: "" cpp.libraries: ["ObjC"] } CppApplication { consoleApplication: true name: "LinkedProduct-C++" files: ["main.cpp"] installDir: "" } CppApplication { condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C++" files: ["main.mm"] installDir: "" cpp.libraries: ["ObjC"] } CppApplication { Depends { name: "LinkedProduct-C++StaticLibrary" } name: "LinkedProduct-BlankApp" files: ["staticmain.c"] installDir: "" } StaticLibrary { Depends { name: "cpp" } name: "LinkedProduct-C++StaticLibrary" files: ["staticlib.cpp"] installDir: "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/darwin.s0000644000175100017510000000005715232633614023756 0ustar runnerrunner.globl _main .globl main _main: main: ret qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerMode/staticlib.cpp0000644000175100017510000000252015232633614024765 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern "C" int cpp(); int cpp() { std::cout << "Hello world" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/empty-profile/0000755000175100017510000000000015232633614023007 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs0000644000175100017510000000005315232633614026310 0ustar runnerrunnerCppApplication { files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/empty-profile/main.cpp0000644000175100017510000000003115232633614024431 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/importing-product/0000755000175100017510000000000015232633614023701 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/importing-product/header.h.in0000644000175100017510000000001615232633614025704 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/importing-product/importing-product.qbs0000644000175100017510000000207515232633614030102 0ustar runnerrunnerimport qbs.File Project { Product { name: "dep" Export { Depends { name: "cpp" } cpp.includePaths: [importingProduct.buildDirectory + "/random_dir"] Rule { inputs: ["hpp_in"] Artifact { filePath: product.buildDirectory + "/random_dir/" + input.completeBaseName fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying file"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } } CppApplication { name: "theProduct" Depends { name: "dep" } Group { files: ["header.h.in"] fileTags: ["hpp_in"] } files: ["main.cpp"] } CppApplication { name: "theProduct2" Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/importing-product/main.cpp0000644000175100017510000000235715232633614025340 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/0000755000175100017510000000000015232633614023171 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp0000644000175100017510000000257515232633614026332 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); std::printf("Hello World! The magic number is %d.", n); return n; } qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs0000644000175100017510000000242015232633614026654 0ustar runnerrunnerimport qbs.Host Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch"); return result; } type: "application" consoleApplication: true name: "Hello World" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "my static lib" } cpp.defines: [ 'DEFINE="whitespaceless"', 'DEFINEWITHSPACE="contains space"', 'DEFINEWITHTAB="contains\ttab"', 'DEFINEWITHBACKSLASH="backslash\\\\"', ] } Product { type: "staticlibrary" name : "my static lib" files : [ "my static lib.cpp" ] Depends { name: "cpp" } Depends { name: "helper lib" } } Product { type: "staticlibrary" name : "helper lib" files : [ "some helper/some helper.h", "some helper/some helper.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory + '/some helper'] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/main.cpp0000644000175100017510000000265515232633614024631 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int bla(); int main() { std::printf(DEFINE"\n"); std::printf(DEFINEWITHSPACE"\n"); std::printf(DEFINEWITHTAB"\n"); std::printf(DEFINEWITHBACKSLASH"\n"); return bla(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/some helper/0000755000175100017510000000000015232633614025374 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.cpp0000644000175100017510000000243615232633614030310 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "some helper.h" int getSomeNumber() { return 156; } qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.h0000644000175100017510000000244315232633614027753 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER_H #define HELPER_H extern int getSomeNumber(); #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/proper quoting/my static lib helper.cpp0000644000175100017510000000240615232633614027563 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int helper_function() { return 156; } qbs-src-3.3.1/tests/auto/blackbox/testdata/discard-unused-data/0000755000175100017510000000000015232633614024034 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs0000644000175100017510000000141315232633614030363 0ustar runnerrunnerCppApplication { name: "app" type: base.concat("custom") property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("is Darwin: " + product.qbs.targetOS.includes("darwin")); console.info("---" + product.cpp.nmPath + "---"); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/discard-unused-data/main.cpp0000644000175100017510000000004415232633614025462 0ustar runnerrunnervoid unusedFunc() {} int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/subprofile-change-tracking/0000755000175100017510000000000015232633614025410 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/subprofile-change-tracking/subprofile-change-tracking.qbs0000644000175100017510000000030615232633614033313 0ustar runnerrunnerProject { CppApplication { name: "app1"; files: ["main1.cpp"] } CppApplication { name: "app2" qbs.profiles: ["qbs-autotests-subprofile"] files: ["main2.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/subprofile-change-tracking/main2.cpp0000644000175100017510000000235115232633614027123 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/subprofile-change-tracking/main1.cpp0000644000175100017510000000235115232633614027122 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/env-normalization/0000755000175100017510000000000015232633614023667 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/env-normalization/env-normalization.qbs0000644000175100017510000000031115232633614030045 0ustar runnerrunnerimport qbs.Environment Product { Probe { id: dummy property var env: Environment.currentEnv() configure: { console.info(JSON.stringify(env)); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/0000755000175100017510000000000015232633614025262 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs0000644000175100017510000000057215232633614030456 0ustar runnerrunnerCppApplication { files: ["app.c"] property bool enableObjectiveC: qbs.targetOS.includes("darwin") Group { name: "C/C++" files: [ "test.c", "test.cpp", ] } Group { name: "Objective-C" condition: enableObjectiveC files: [ "test.m", "test.mm", ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.cpp0000644000175100017510000000000015232633614026733 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/compilerDefinesByLanguage.qbs0000644000175100017510000001757015232633614033052 0ustar runnerrunnerProject { CppDefinesApp { name: "A" // eqiuvalent to ["c"] since we always need some compiler defines // for the architecture detection, etc. cpp.enableCompilerDefinesByLanguage: [] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "B" cpp.enableCompilerDefinesByLanguage: ["cpp"] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "C" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objc"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (!cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "D" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "E" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["cpp", "objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "F" cpp.enableCompilerDefinesByLanguage: ["c", "cpp"] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "G" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objc", "objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (!cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.mm0000644000175100017510000000000015232633614026562 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.c0000644000175100017510000000000015232633614026373 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.m0000644000175100017510000000000015232633614026405 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/app.c0000644000175100017510000000003515232633614026204 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/soversion/0000755000175100017510000000000015232633614022242 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/soversion/soversion.qbs0000644000175100017510000000041015232633614024773 0ustar runnerrunnerDynamicLibrary { name: "mylib" property bool useVersion property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } version: useVersion ? "1.2.3" : undefined Depends { name: "cpp" } files: ["lib.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/soversion/lib.cpp0000644000175100017510000000001515232633614023510 0ustar runnerrunnervoid f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/0000755000175100017510000000000015232633614023606 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/p3.cpp0000644000175100017510000000004615232633614024634 0ustar runnerrunner#include int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/p2.cpp0000644000175100017510000000004415232633614024631 0ustar runnerrunner#include int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/artifact-scanning.qbs0000644000175100017510000000105015232633614027704 0ustar runnerrunnerProject { CppApplication { name: "p1" consoleApplication: true cpp.includePaths: ["."] files: [ "p1.cpp", "shared.h", ] } CppApplication { name: "p2" consoleApplication: true cpp.includePaths: ["."] files: [ "p2.cpp", "shared.h", ] } CppApplication { name: "p3" consoleApplication: true cpp.includePaths: [".", "subdir"] files: [ "p3.cpp", ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/external1.h0000644000175100017510000000003715232633614025662 0ustar runnerrunner#include qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/p1.cpp0000644000175100017510000000007015232633614024627 0ustar runnerrunner#include #include int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/shared.h0000644000175100017510000000002715232633614025224 0ustar runnerrunner#include qbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/subdir/0000755000175100017510000000000015232633614025076 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/subdir/external2.h0000644000175100017510000000000015232633614027141 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifact-scanning/external-indirect.h0000644000175100017510000000000015232633614027366 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installed_artifact/0000755000175100017510000000000015232633614024047 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installed_artifact/installed_artifact.qbs0000644000175100017510000000070515232633614030414 0ustar runnerrunnerApplication { name: "installedApp" type: "application" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "cpp" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/installed_artifact/main.cpp0000644000175100017510000000235115232633614025500 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/import-assignment/0000755000175100017510000000000015232633614023673 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-assignment/imports/0000755000175100017510000000000015232633614025370 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-assignment/imports/MyImport/0000755000175100017510000000000015232633614027150 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-assignment/imports/MyImport/myimport.js0000644000175100017510000000005215232633614031363 0ustar runnerrunnervar key1 = "value1"; var key2 = "value2"; qbs-src-3.3.1/tests/auto/blackbox/testdata/import-assignment/import-assignment.qbs0000644000175100017510000000104015232633614030055 0ustar runnerrunnerimport MyImport Product { type: "outtype" property var importValue: MyImport Rule { multiplex: true Artifact { fileTags: "outtype" filePath: "dummy" } prepare: { var cmd = new JavaScriptCommand; cmd.silent = true; cmd.sourceCode = function() { console.info("key 1 = " + product.importValue.key1); console.info("key 2 = " + product.importValue.key2); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/0000755000175100017510000000000015232633614025465 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/0000755000175100017510000000000015232633614027135 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/0000755000175100017510000000000015232633614030403 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/higher.qbs0000644000175100017510000000011015232633614032350 0ustar runnerrunnerModule { Depends { name: "lower" } lower.listProp: ["higher"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/0000755000175100017510000000000015232633614030265 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs0000644000175100017510000000061315232633614032124 0ustar runnerrunnerModule { property stringList listProp Rule { inputs: ["intype"] outputFileTags: "outtype" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("listProp: " + JSON.stringify(input.lower.listProp)); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/list-properties-with-outer.qbs0000644000175100017510000000033515232633614033447 0ustar runnerrunnerProduct { type: ["outtype"] Depends { name: "higher" } lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] lower.listProp: outer.concat(["group"]) } } qbs-src-3.3.1/tests/auto/blackbox/testdata/list-properties-with-outer/dummy.txt0000644000175100017510000000000015232633614027347 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/0000755000175100017510000000000015232633614023246 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/subdir2/0000755000175100017510000000000015232633614024620 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/subdir2/theheader.h0000644000175100017510000000000015232633614026710 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/file.c0000644000175100017510000000002415232633614024325 0ustar runnerrunnervoid func(void) { } qbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/main.cpp0000644000175100017510000000004615232633614024676 0ustar runnerrunner#include int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs0000644000175100017510000000052315232633614027010 0ustar runnerrunnerCppApplication { Probe { id: dummy property stringList toolchain: qbs.toolchain configure: { if (toolchain.includes("msvc")) console.info("msvc"); } } files: [ "file.c", "main.cpp", "subdir/theheader.h", "subdir2/theheader.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/subdir/0000755000175100017510000000000015232633614024536 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/buildenv-change/subdir/theheader.h0000644000175100017510000000000015232633614026626 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/0000755000175100017510000000000015232633614023441 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/fileDependencies.qbs0000644000175100017510000000071115232633614027375 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "myapp" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "cpp" } cpp.includePaths: ["awesomelib"] files: ["src/narf.h", "src/narf.cpp", "src/zort.cpp"] // Group { // fileTagsFilter: product.type // qbs.install: true // } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/src/0000755000175100017510000000000015232633614024230 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/src/zort.cpp0000644000175100017510000000243315232633614025734 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" int main() { doStuff(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/src/narf.cpp0000644000175100017510000000243315232633614025664 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void doStuff() { doAwesomeStuff(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/src/narf.h0000644000175100017510000000235415232633614025333 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void doStuff(); qbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/0000755000175100017510000000000015232633614025570 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h0000644000175100017510000000250715232633614027405 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "magnificent.h" void doAwesomeStuff() { std::printf(magnificentMessage); } qbs-src-3.3.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/magnificent.h0000644000175100017510000000252115232633614030225 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAGNIFICENT_H #define MAGNIFICENT_H const char magnificentMessage[] = "Just. Wow."; #endif // MAGNIFICENT_H qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/0000755000175100017510000000000015232633614022032 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/assembly.qbs0000644000175100017510000000465615232633614024373 0ustar runnerrunnerimport qbs.TextFile Project { Product { name: "properties" type: ["properties"] Depends { name: "cpp" } Rule { multiplex: true Artifact { filePath: "properties.json" fileTags: ["properties"] } prepare: { var cmd = new JavaScriptCommand(); cmd.outputFilePath = outputs.properties[0].filePath; cmd.toolchain = product.qbs.toolchain; cmd.architecture = product.qbs.architecture; cmd.silent = true; cmd.sourceCode = function () { var tf = new TextFile(outputFilePath, TextFile.WriteOnly); try { const data = { "qbs.toolchain": toolchain, "qbs.architecture": architecture, }; tf.writeLine(JSON.stringify(data, undefined, 4)); } finally { tf.close(); } }; return [cmd]; } } } StaticLibrary { name : "testa" files : [ "testa.s" ] Depends { name: "cpp" } condition: qbs.toolchain.includes("gcc") Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name : "testb" files : [ "testb.S" ] Depends { name: "cpp" } condition: qbs.toolchain.includes("gcc") Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name : "testc" files : [ "testc.sx" ] Depends { name: "cpp" } condition: qbs.toolchain.includes("gcc") Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name: "testd" Group { condition: product.condition files: ["testd_" + qbs.architecture + ".asm"] } Depends { name: "cpp" } condition: qbs.toolchain.includes("msvc") && (qbs.architecture === "x86" || qbs.architecture === "x86_64") Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/testd_x86.asm0000644000175100017510000000011115232633614024355 0ustar runnerrunner.386 .model flat, stdcall .code foo PROC nop RET foo ENDP END qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/testb.S0000644000175100017510000000004115232633614023272 0ustar runnerrunner#define bla nop symbolb: bla qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/testa.s0000644000175100017510000000004015232633614023330 0ustar runnerrunner.globl symbola symbola: nop qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/testd_x86_64.asm0000644000175100017510000000005615232633614024676 0ustar runnerrunner.code foo PROC nop RET foo ENDP END qbs-src-3.3.1/tests/auto/blackbox/testdata/assembly/testc.sx0000644000175100017510000000004115232633614023523 0ustar runnerrunner#define bla nop symbolb: bla qbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-imported-file/0000755000175100017510000000000015232633614024602 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js0000644000175100017510000000013315232633614026573 0ustar runnerrunnerfunction prepare(cmd) { cmd.sourceCode = function() { console.info("old output"); }; } qbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs0000644000175100017510000000073115232633614031701 0ustar runnerrunnerimport "prepare.js" as PrepareHelper Product { type: ["output"] Group { files: ["test.txt"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "dummy" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); PrepareHelper.prepare(cmd); cmd.description = "creating output"; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-imported-file/test.txt0000644000175100017510000000000015232633614026310 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/0000755000175100017510000000000015232633614024014 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir1/0000755000175100017510000000000015232633614024653 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir1/file1.txt0000644000175100017510000000001315232633614026406 0ustar runnerrunnerdir1/file1 qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir1/file2.txt0000644000175100017510000000001315232633614026407 0ustar runnerrunnerdir1/file2 qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/install-duplicates.qbs0000644000175100017510000000020715232633614030323 0ustar runnerrunnerProduct { Group { files: ["*.txt"] prefix: "**/" qbs.install: true qbs.installDir: "files" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir2/0000755000175100017510000000000015232633614024654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file1.txt0000644000175100017510000000001315232633614026407 0ustar runnerrunnerdir2/file1 qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file2.txt0000644000175100017510000000001315232633614026410 0ustar runnerrunnerdir2/file2 qbs-src-3.3.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file3.txt0000644000175100017510000000001315232633614026411 0ustar runnerrunnerdir2/file3 qbs-src-3.3.1/tests/auto/blackbox/testdata/archiver-flags/0000755000175100017510000000000015232633614023110 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/archiver-flags/lib.cpp0000644000175100017510000000001715232633614024360 0ustar runnerrunnervoid func() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/archiver-flags/archiver-flags.qbs0000644000175100017510000000056115232633614026516 0ustar runnerrunnerStaticLibrary { Depends { name: "cpp" } files: "lib.cpp" Properties { condition: toolchainProbe.found cpp.archiverFlags: ["/WX:NO"] } Probe { id: toolchainProbe condition: qbs.toolchain.includes("msvc") configure: { console.info("toolchain is MSVC"); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/0000755000175100017510000000000015232633614022600 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/modules/0000755000175100017510000000000015232633614024250 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/modules/m/0000755000175100017510000000000015232633614024504 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/modules/m/m.qbs0000644000175100017510000000025115232633614025445 0ustar runnerrunnerimport "../../TheScanner.qbs" as TheScanner Module { Group { condition: product.enableGroup TheScanner { condition: product.moduleScanner } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir2/0000755000175100017510000000000015232633614024152 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir2/file.inc0000644000175100017510000000000015232633614025552 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir2/file2.in0000644000175100017510000000000015232633614025471 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/scanner-item.qbs0000644000175100017510000000133715232633614025700 0ustar runnerrunnerimport qbs.File import qbs.FileInfo Product { type: "t" Depends { name: "m" } property bool productScanner property bool moduleScanner property bool enableGroup Group { files: ["subdir1/file1.in", "subdir2/file2.in"] fileTags: "i" } TheScanner { condition: productScanner } Rule { inputs: "i" Artifact { filePath: FileInfo.baseName(input.fileName) + ".out" fileTags: "t" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "handling " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/TheScanner.qbs0000644000175100017510000000017115232633614025340 0ustar runnerrunnerimport qbs.FileInfo Scanner { inputs: "i" searchPaths: [FileInfo.path(input.filePath)] scan: ["file.inc"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir1/0000755000175100017510000000000015232633614024151 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir1/file1.in0000644000175100017510000000000015232633614025467 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-item/subdir1/file.inc0000644000175100017510000000000015232633614025551 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/0000755000175100017510000000000015232633614024073 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/0000755000175100017510000000000015232633614025174 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l0000644000175100017510000000513615232633614027031 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/0000755000175100017510000000000015232633614025335 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l0000644000175100017510000000523615232633614027173 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %option outfile="numberscanner.c" header-file="numberscanner.h" %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs0000644000175100017510000001174615232633614027666 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs.FileInfo import qbs.Probes import qbs.TextFile import "flexoptionsreader.js" as FlexOptionsReader Project { Product { name: "genlexer" type: "application" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "cpp" } Group { files: ["numbers.l"] fileTags: ["flex"] } Probes.PathProbe { id: flexProbe names: ["flex"] platformSearchPaths: ["/usr/local/bin", "/usr/bin", "/bin"] } property bool isFlexAvailable: flexProbe.found Rule { inputs: ["flex"] outputFileTags: ["c", "hpp"] outputArtifacts: { var options = FlexOptionsReader.readFlexOptions(input.filePath); var sourceFileName = options["outfile"] || "lex.yy.c"; var headerFileName = options["header-file"]; var result = [{ filePath: "GeneratedFiles/" + sourceFileName, fileTags: ["c"], cpp: { defines: ["CRUCIAL_DEFINE"] } }]; if (headerFileName) { result.push({ filePath: "GeneratedFiles/" + headerFileName, fileTags: ["hpp"] }); } return result; } prepare: { var cmd; if (product.isFlexAvailable) { // flex is available. Let's call it. cmd = new Command("flex", [input.filePath]); cmd.workingDirectory = product.buildDirectory + "/GeneratedFiles"; } else { // No flex available here, generate some C source and header. cmd = new JavaScriptCommand(); cmd.sourceFileName = outputs["c"][0].filePath; cmd.headerFileName = outputs["hpp"] ? outputs["hpp"][0].filePath : ""; cmd.sourceCode = function() { var fsrc = new TextFile(sourceFileName, TextFile.WriteOnly); if (headerFileName) { fsrc.write("#include \"" + FileInfo.fileName(headerFileName) + "\"\n\n"); var fhdr = new TextFile(headerFileName, TextFile.WriteOnly); fhdr.write("// a rather empty header file\n"); fhdr.close(); } fsrc.write("\n#ifndef CRUCIAL_DEFINE\n"); fsrc.write("# error CRUCIAL_DEFINE is missing!\n"); fsrc.write("#endif\n\n"); fsrc.write("int main() { return 0; }\n"); fsrc.close(); }; } cmd.description = "flexing " + FileInfo.fileName(input.filePath); return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js0000644000175100017510000000671115232633614031435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ var TextFile = require("qbs.TextFile"); function readFlexOptions(filePath) { function splitOptions(str) { var options = []; var opt = ""; var inquote = false; for (var i = 0; i < str.length; ++i) { if (str[i] === '"') { opt += '"'; inquote = !inquote; } else if (str[i] === ' ' && !inquote) { options.push(opt); opt = ""; } else { opt += str[i]; } } if (opt.length) options.push(opt); return options; } function unquote(str) { var l = str.length; if (l > 2 && str[0] === '"' && str[l - 1] === '"') return str.substr(1, l - 2); return str; } function parseOptionLine(result, str) { var options = splitOptions(str); var re = /^(outfile|header-file)=(.*)$/; var reres; for (var k in options) { re.lastIndex = 0; reres = re.exec(options[k]); if (reres === null) continue; result[reres[1]] = unquote(reres[2]); } } var tf = new TextFile(filePath); var line; var optrex = /^%option\s+(.*$)/; var res; var options = {}; while (!tf.atEof()) { line = tf.readLine(); if (line === "%%") break; optrex.lastIndex = 0; res = optrex.exec(line); if (res === null) continue; parseOptionLine(options, res[1]); } tf.close(); return options; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-type-recursive/0000755000175100017510000000000015232633614024463 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linker-type-recursive/static.cpp0000644000175100017510000000013415232633614026454 0ustar runnerrunner#include extern "C" { void funcCxx() { std::cout << "Hi!" << std::endl; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-type-recursive/main.c0000644000175100017510000000006315232633614025552 0ustar runnerrunnervoid funcCxx(); int main(void) { funcCxx(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-type-recursive/linker-type-recursive.qbs0000644000175100017510000000076315232633614031450 0ustar runnerrunnerimport qbs.Host Project { StaticLibrary { name: "StaticCxx" files: "static.cpp" } StaticLibrary { name: "StaticC" Depends { name: "StaticCxx" } files: "static.c" } CppApplication { Depends { name: "StaticC" } property bool dummy: { if (qbs.targetPlatform !== Host.platform() || qbs.architecture !== Host.architecture()) console.info("no host target"); } files: "main.c" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-type-recursive/static.c0000644000175100017510000000002015232633614026106 0ustar runnerrunnervoid funcC() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/0000755000175100017510000000000015232633614020762 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cli/Libby.cs0000755000175100017510000000020215232633614022347 0ustar runnerrunnernamespace Fake { public class Libby { public static int Cool() { return 45; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/Module.vb0000755000175100017510000000023715232633614022545 0ustar runnerrunnerNamespace Fake Public Class [Mod] Public Shared Function Cool() As Integer Return 420 End Function End Class End Namespace qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/HelloWorld.cs0000755000175100017510000000042415232633614023367 0ustar runnerrunnerusing Fake; public class HelloWorld { public static void Main() { System.Console.WriteLine("Hello world!"); System.Console.WriteLine(Mod.Cool()); System.Console.WriteLine(Libby.Cool()); System.Console.WriteLine(Libby2.Cool()); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/fshello.fs0000644000175100017510000000003715232633614022750 0ustar runnerrunnerprintfn "Hello World from F#!" qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/fshello.qbs0000644000175100017510000000016015232633614023122 0ustar runnerrunnerApplication { Depends { name: "cli" } type: "application" name: "fshello" files: "fshello.fs" } qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/Module.cs0000644000175100017510000000020115232633614022527 0ustar runnerrunnernamespace Fake { public class Mod { public static int Cool() { return 420; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/dotnettest.qbs0000644000175100017510000000213515232633614023667 0ustar runnerrunnerProject { Application { Depends { name: "cli" } Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.includes("mono") } Depends { name: "NetLib" } type: "application" name: "Hello" files: ["HelloWorld.cs"] Group { fileTagsFilter: product.type qbs.install: true } } // Mono's VB compiler doesn't support modules yet, and if we try with C#, it crashes anyways NetModule { condition: !qbs.toolchain.includes("mono") Depends { name: "cli" } name: "HelloWorldModule" files: ["Module.vb"] Group { fileTagsFilter: product.type qbs.install: true } } DynamicLibrary { Depends { name: "cli" } name: "NetLib" files: ["Libby.cs", "Libby2.cs"] // fill-in for missing NetModule Group { condition: qbs.toolchain.includes("mono") files: ["Module.cs"] } Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cli/Libby2.cs0000755000175100017510000000020315232633614022432 0ustar runnerrunnernamespace Fake { public class Libby2 { public static int Cool() { return 22; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/0000755000175100017510000000000015232633614024714 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/0000755000175100017510000000000015232633614026364 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/0000755000175100017510000000000015232633614032066 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/main.cppqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/main.cp0000644000175100017510000000001615232633614033333 0ustar runnerrunnerint main() {} ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/module_with_files.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/module_0000644000175100017510000000060715232633614033440 0ustar runnerrunnerModule { property stringList fileTags property bool overrideTags property bool filesAreTargets Depends { name: "cpp" } Group { prefix: path + '/' files: "main.cpp" fileTags: product.module_with_files.fileTags overrideTags: product.module_with_files.overrideTags filesAreTargets: product.module_with_files.filesAreTargets } } qbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs0000644000175100017510000000305115232633614032123 0ustar runnerrunnerCppApplication { name: "app" type: base.concat("dummy") consoleApplication: true Properties { condition: qbs.targetOS.includes("darwin") bundle.embedInfoPlist: false } Probe { id: toolchainProbe property stringList toolchain: qbs.toolchain property string executableSuffix: cpp.executableSuffix configure: { console.info("is gcc: " + toolchain.includes("gcc")); console.info("executable suffix: " + executableSuffix); found = true; } } Rule { multiplex: true inputs: "cpp" Artifact { filePath: "dummy" fileTags: "dummy" cpp.cxxLanguageVersion: "hoppla" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { if (output.cpp.cxxLanguageVersion !== "hoppla") throw "This cannot be!"; }; return cmd; } } Rule { multiplex: true inputs: "cpp" requiresInputs: false Artifact { filePath: "dummy2"; fileTags: "dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("cpp artifacts: " + (product.artifacts.cpp ? product.artifacts.cpp.length : 0)) }; return cmd; } } Depends { name: "module_with_files" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/sanitizer/0000755000175100017510000000000015232633614022223 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs0000644000175100017510000000305415232633614024744 0ustar runnerrunnerCppApplication { Depends { name: "Sanitizers.address" } Sanitizers.address.enabled: sanitizer === "address" property string sanitizer property bool supportsSanitizer: { if (qbs.toolchain.includes("mingw") || qbs.toolchain.contains("emscripten")) return false; if (sanitizer === "address") return Sanitizers.address._supported; if (qbs.toolchain.includes("clang-cl")) { if (cpp.toolchainInstallPath.includes("Microsoft Visual Studio") && qbs.architecture === "x86_64") { // 32 bit sanitizer shipped with VS misses the x86_64 libraries return false; } // only these are supported return sanitizer === "address" || sanitizer === "undefined"; } if (!qbs.toolchain.includes("gcc")) return false; if (qbs.targetOS.includes("ios")) { // thread sanitizer is not supported return sanitizer !== "thread"; } return true; } condition: { if (!sanitizer) return true; if (!supportsSanitizer) console.info("Compiler does not support sanitizer"); return supportsSanitizer; } qbs.buildVariant: "release" cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" consoleApplication: true cpp.runtimeLibrary: "static" cpp.driverFlags: sanitizer && sanitizer !== "address" ? ["-fsanitize=" + sanitizer] : [] cpp.debugInformation: true files: "sanitizer.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp0000644000175100017510000000006315232633614024736 0ustar runnerrunnerint main(int argc, char *argv[]) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/group-condition-change/0000755000175100017510000000000015232633614024556 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/group-condition-change/input_kaputt.txt0000644000175100017510000000000015232633614030034 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/group-condition-change/group-condition-change.qbs0000644000175100017510000000113115232633614031624 0ustar runnerrunnerProject { property bool kaputt: true Product { type: ["kaputt"] Group { name: "kaputt" condition: project.kaputt files: "input_kaputt.txt" fileTags: "input.kaputt" } Rule { inputs: "input.kaputt" Artifact { filePath: "output.kaputt" fileTags: "kaputt" } prepare: { var cmd = new Command("jibbetnich", [output.filePath]); cmd.silent = true; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probeProperties/0000755000175100017510000000000015232633614023377 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probeProperties/main.c0000644000175100017510000000236415232633614024474 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs0000644000175100017510000000213515232633614027273 0ustar runnerrunnerimport qbs.Probes Project { CppApplication { Probes.PathProbe { id: probe1 names: ["bin/tool"] platformSearchPaths: [product.sourceDirectory] } Probes.PathProbe { id: probe2 names: ["tool"] platformSearchPaths: [product.sourceDirectory + "/bin"] } targetName: { console.info("probe1.fileName=" + probe1.fileName); console.info("probe1.path=" + probe1.path); console.info("probe1.filePath=" + probe1.filePath); console.info("probe2.fileName=" + probe2.fileName); console.info("probe2.path=" + probe2.path); console.info("probe2.filePath=" + probe2.filePath); console.info("probe3.fileName=" + probe3.fileName); console.info("probe3.path=" + probe3.path); console.info("probe3.filePath=" + probe3.filePath); return name; } } Probes.PathProbe { id: probe3 names: ["tool"] platformSearchPaths: [project.sourceDirectory + "/bin"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probeProperties/bin/0000755000175100017510000000000015232633614024147 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probeProperties/bin/tool0000644000175100017510000000000015232633614025035 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/0000755000175100017510000000000015232633614026511 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/input.txt0000644000175100017510000000000015232633614030377 0ustar runnerrunner././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/changed-inputs-from-dependencies.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/changed-inputs-from-depe0000644000175100017510000000341615232633614033225 0ustar runnerrunnerimport qbs.File import qbs.TextFile Project { Product { name: "dep" type: "dep_tag" files: "input.txt" FileTagger { patterns: "*.txt"; fileTags: "inp_tag" } Rule { inputs: "inp_tag" Artifact { filePath: input.baseName + ".intermediate"; fileTags: "int_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } Rule { inputs: "int_tag" Artifact { filePath: input.baseName + ".dep"; fileTags: "dep_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } Product { name: "p" type: "p_tag" Depends { name: "dep" } Rule { inputsFromDependencies: "dep_tag" outputFileTags: "p_tag" outputArtifacts: { var dummy = new TextFile(input.filePath, TextFile.ReadOnly); dummy.close(); return [{ filePath: input.baseName + ".p", fileTags: "p_tag" }] } prepare: { console.info("running final prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/referenceErrorInExport/0000755000175100017510000000000015232633614024654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/referenceErrorInExport/main.c0000644000175100017510000000236415232633614025751 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/referenceErrorInExport/referenceErrorInExport.qbs0000644000175100017510000000054715232633614032032 0ustar runnerrunnerProject { CppApplication { Depends { name: "other" } files: ["main.c"] cpp.includePaths: ["."] } DynamicLibrary { name: "other" files: ["main.c"] property stringList includePaths: [] Export { Depends { name: "cpp" } cpp.includePaths: includePaths } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/0000755000175100017510000000000015232633614023043 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/after/0000755000175100017510000000000015232633614024144 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/after/product3.qbs0000644000175100017510000000016415232633614026417 0ustar runnerrunnerProduct { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["zoo.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/after/trackProducts.qbs0000644000175100017510000000014715232633614027505 0ustar runnerrunnerProject { name: "trackProducts" references: ["product1.qbs", "product2.qbs", "product3.qbs"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp0000644000175100017510000000242715232633614025464 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::printf("zoo\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/0000755000175100017510000000000015232633614024305 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp0000644000175100017510000000242715232633614025601 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::printf("foo\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/trackProducts.qbs0000644000175100017510000000012715232633614027644 0ustar runnerrunnerProject { name: "trackProducts" references: ["product1.qbs", "product2.qbs"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/product1.qbs0000644000175100017510000000016415232633614026556 0ustar runnerrunnerProduct { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["foo.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/product2.qbs0000644000175100017510000000016415232633614026557 0ustar runnerrunnerProduct { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["bar.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp0000644000175100017510000000242715232633614025562 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::printf("bar\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/ld/0000755000175100017510000000000015232633614020612 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ld/coreutils.h0000644000175100017510000000241415232633614022775 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT int foo(); qbs-src-3.3.1/tests/auto/blackbox/testdata/ld/coreutils.cpp0000644000175100017510000000242015232633614023325 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" int foo() { return 42; } qbs-src-3.3.1/tests/auto/blackbox/testdata/ld/main.cpp0000644000175100017510000000253115232633614022243 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" #include int main(int argc, char *argv[]) { std::printf("%d\n", foo()); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/ld/ld.qbs0000644000175100017510000000106715232633614021724 0ustar runnerrunnerProject { Library { Depends { name: "cpp" } name: "coreutils" targetName: "qbs can handle any file paths, even the crazy ones! ;)" files: ["coreutils.cpp", "coreutils.h"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.sonamePrefix: "@rpath" } Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { Depends { name: "coreutils" } files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/date-property/0000755000175100017510000000000015232633614023012 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/date-property/date-property.qbs0000644000175100017510000000105015232633614026314 0ustar runnerrunnerProduct { type: "date" property var theDate: new Date(1999, 11, 31); Rule { multiplex: true Artifact { filePath: "dummy"; fileTags: "date" } prepare: { var cmd = new JavaScriptCommand; cmd.silent = true; cmd.sourceCode = function() { var d = product.theDate; console.info("The stored date was " + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate()); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/combined-sources/0000755000175100017510000000000015232633614023454 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/combined-sources/combined-sources.qbs0000644000175100017510000000026715232633614027431 0ustar runnerrunnerCppApplication { name: "theapp" files: [ "combinable.cpp", "main.cpp", ] Group { files: ["uncombinable.cpp"] fileTags: ["cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/combined-sources/combinable.cpp0000644000175100017510000000002215232633614026245 0ustar runnerrunnerstatic int i = 1; qbs-src-3.3.1/tests/auto/blackbox/testdata/combined-sources/main.cpp0000644000175100017510000000001715232633614025102 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/combined-sources/uncombinable.cpp0000644000175100017510000000002215232633614026610 0ustar runnerrunnerstatic int i = 2; qbs-src-3.3.1/tests/auto/blackbox/testdata/partially-built-dependency/0000755000175100017510000000000015232633614025445 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/partially-built-dependency/partially-built-dependency.qbs0000644000175100017510000000257715232633614033421 0ustar runnerrunnerimport qbs.File import qbs.TextFile Project { property bool minimalDependency Product { name: "p" type: "obj" Depends { name: "cpp" } Depends { condition: project.minimalDependency === undefined; name: "dep" } Depends { condition: project.minimalDependency !== undefined name: "dep" minimal: project.minimalDependency } Rule { inputsFromDependencies: "cpp" Artifact { filePath: input.fileName fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description ="copying " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } CppApplication { name: "dep" Rule { multiplex: true Artifact { filePath: "main.cpp"; fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("int main() {}"); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/0000755000175100017510000000000015232633614021636 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/imports/0000755000175100017510000000000015232633614023333 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/0000755000175100017510000000000015232633614026021 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs0000644000175100017510000000011615232633614031201 0ustar runnerrunnernamespace QbsTest; table Foo { name:string; count:int; } root_type Foo; qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp0000644000175100017510000000115715232633614025655 0ustar runnerrunner#include "baz_generated.h" #include "imported_foo/imported_foo_generated.h" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); auto newBaz = QbsTest::CreateBaz(builder, newFoo); builder.Finish(newBaz); auto baz = GetBaz(builder.GetBufferPointer()); assert(baz->foo()->name()->str() == "John Doe"); assert(baz->foo()->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp0000644000175100017510000000107615232633614026561 0ustar runnerrunner#include "bar_generated.h" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); auto newBar = QbsTest::CreateBar(builder, newFoo); builder.Finish(newBar); auto bar = GetBar(builder.GetBufferPointer()); assert(bar->foo()->name()->str() == "John Doe"); assert(bar->foo()->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat.c0000644000175100017510000000152315232633614022731 0ustar runnerrunner#include "foo_builder.h" #include #undef ns #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(QbsTest, x) // Specified in the schema. #define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0) int main() { void *buffer = NULL; size_t size = 0; flatcc_builder_t builder; flatcc_builder_init(&builder); flatbuffers_string_ref_t name = flatbuffers_string_create_str(&builder, "John Doe"); ns(Foo_create_as_root(&builder, name, 42)); buffer = flatcc_builder_finalize_aligned_buffer(&builder, &size); ns(Foo_table_t) foo = ns(Foo_as_root(buffer)); test_assert(strcmp(ns(Foo_name(foo)), "John Doe") == 0); test_assert(ns(Foo_count(foo)) == 42); free(buffer); flatcc_builder_clear(&builder); printf("The FlatBuffer was successfully created and accessed!\n"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs0000644000175100017510000000151315232633614027227 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } flatbuf.cpp.filenameExtension: "hpp" files: [ "flat_filename_extension.cpp", "foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/bar.fbs0000644000175100017510000000012115232633614023070 0ustar runnerrunnerinclude "foo.fbs"; namespace QbsTest; table Bar { foo:Foo; } root_type Bar; qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp0000644000175100017510000000076115232633614026520 0ustar runnerrunner#include "foo.fbs.h" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); builder.Finish(newFoo); auto foo = GetFoo(builder.GetBufferPointer()); assert(foo->name()->str() == "John Doe"); assert(foo->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/conanfile.txt0000644000175100017510000000013015232633614024327 0ustar runnerrunner[requires] flatbuffers/24.3.25 [tool_requires] flatbuffers/24.3.25 [generators] QbsDeps qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs0000644000175100017510000000141715232633614024140 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } files: [ "flat.cpp", "foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs0000644000175100017510000000150615232633614026521 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } flatbuf.cpp.filenameSuffix: ".fbs" files: [ "flat_filename_suffix.cpp", "foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/baz.fbs0000644000175100017510000000014715232633614023110 0ustar runnerrunnerinclude "imported_foo/imported_foo.fbs"; namespace QbsTest; table Baz { foo:Foo; } root_type Baz; qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/foo.fbs0000644000175100017510000000011615232633614023113 0ustar runnerrunnernamespace QbsTest; table Foo { name:string; count:int; } root_type Foo; qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs0000644000175100017510000000146215232633614026563 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } files: [ "flat_relative_import.cpp", "bar.fbs", "foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs0000644000175100017510000000142215232633614023574 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuffers.c"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuffers.c.present); return flatbuffers.c.present; } files: [ "flat.c", "foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs0000644000175100017510000000157115232633614026567 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } flatbuf.cpp.importPaths: "imports/" files: [ "flat_absolute_import.cpp", "baz.fbs", "imports/imported_foo/imported_foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat.cpp0000644000175100017510000000076715232633614023302 0ustar runnerrunner#include "foo_generated.h" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); builder.Finish(newFoo); auto foo = GetFoo(builder.GetBufferPointer()); assert(foo->name()->str() == "John Doe"); assert(foo->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs0000644000175100017510000000162515232633614025660 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "flatbuf.cpp"; required: false } consoleApplication: true condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasFlatbuffers; } property bool hasFlatbuffers: { console.info("has flatbuffers: " + flatbuf.cpp.present); return flatbuf.cpp.present; } flatbuf.cpp.importPaths: "imports/" flatbuf.cpp.keepPrefix: true files: [ "flat_keep_prefix.cpp", "baz.fbs", "imports/imported_foo/imported_foo.fbs", ] qbsModuleProviders: "conan" } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp0000644000175100017510000000077115232633614027231 0ustar runnerrunner#include "foo_generated.hpp" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); builder.Finish(newFoo); auto foo = GetFoo(builder.GetBufferPointer()); assert(foo->name()->str() == "John Doe"); assert(foo->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp0000644000175100017510000000107615232633614026564 0ustar runnerrunner#include "baz_generated.h" #include using namespace QbsTest; int main() { flatbuffers::FlatBufferBuilder builder; auto name = builder.CreateString("John Doe"); auto newFoo = QbsTest::CreateFoo(builder, name, 42); auto newBaz = QbsTest::CreateBaz(builder, newFoo); builder.Finish(newBaz); auto baz = GetBaz(builder.GetBufferPointer()); assert(baz->foo()->name()->str() == "John Doe"); assert(baz->foo()->count() == 42); std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-invalidation/0000755000175100017510000000000015232633614025425 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-invalidation/file.in0000644000175100017510000000000015232633614026662 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-invalidation/artifacts-map-invalidation.qbs0000644000175100017510000000420215232633614033344 0ustar runnerrunnerimport qbs.File Project { Product { name: "dep" type: "dep.out" Group { files: "file.in" fileTags: "dep.in" } Rule { inputs: "dep.in" outputFileTags: "dep.out" outputArtifacts: { if (!product.artifacts["dep.in"] || product.artifacts["dep.in"].length !== 1) throw "source file not in artifacts map!" if (product.artifacts["dep.out"] && product.artifacts["dep.out"].length !== 0) throw "generated artifact already in map!"; return [{filePath: "file.out", fileTags: "dep.out"}]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } Product { name: "p" type: "p.out" Depends { name: "dep" } Rule { inputsFromDependencies: "dep.out" Artifact { filePath: "myfile.out"; fileTags: "p.out" } prepare: { var dep; for (var i = 0; i < product.dependencies.length; ++i) { if (product.dependencies[i].name === "dep") { dep = product.dependencies[i]; break; } } if (!dep) throw "dependency not found"; if (!dep.artifacts["dep.in"] || dep.artifacts["dep.in"].length !== 1) throw "source file not in dependency's artifacts map!" if (!dep.artifacts["dep.out"] || dep.artifacts["dep.out"].length !== 1) throw "generated artifact not in dependency's artifacts map!"; var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/0000755000175100017510000000000015232633614024060 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/output.txt0000644000175100017510000000006415232633614026161 0ustar runnerrunnerthis is a plain text file this is a plain text file qbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/input.bin0000644000175100017510000000200015232633614025701 0ustar runnerrunnerêѸvÊ·€Rˆ–'€.¶wl É >}“ä‹‚ûb»-Å(âóOOtà™:e"ãšlhėʉœO*¨à§d4·ÑœihÆÉ’‹{ŒŒ*æÍŽÅõàOœƒ¢¿Z”Ó®ø±ÿØ ;oþX§·õUl§‰X†ÙvÓÑðÒ¦iªS˜öš¸H+,Ä¢„j2@Ödq*:g¥§w¦Ï°:;ãŸ[èKýΕÉRâîV2xžÈЍ«®³4‘Ý{xÇ»IG¾”D¾~fsT‡6mÅaì—¨—€ ¿¹’ƒ×ûcíÄòyë}Ý@ˆº9lí0ÑkÑß/ÆŒ£nn­Ø]MxãmMŽd8µéþf}‘êÖKJàë7¨ÛD÷£gÿ䃟Ç'NòÊ HýîíÏ}¾{ê»ÑʳO†Ç|ú×ÅÃÅölCË¡Qßá’Ânfîf]ù o a°æ÷«Ôü¾FÙ}s-òþä{Ç$˵zà2ƒ{t–­ç½ÂmT7§W“‹˜C)Ç ˆÑ t-Á•߈Ž`çëF¬¯ÚYŒÂ`"Ça;cåÑÞÕG‹Eú”¯‘aëü^}ürk\ðÍen[̤Ês´“ÆŽÙH-zT¼Á²)o4—¦l®\°oÙUÀWB tOx7Rñ¤R{Í\ZQŠ÷%×jÁÞÄ«ü«ô“úcž åž½lÖ+v ¾µóx^=PC_Ñ<'Î;™?ƒì©­—ÀiYÆ}]òùÅU9}Ä.‚ŽÑÒªYr&©gí¿x‡Å‚¶­#r¡’ÎëôØ/š Ž ²}xzh„sdÍs-v³ƒ%±>ã[]k¶n¦ÊùtÑ5ìp™M?a‚3d½¡)S­•r»Ž©s¾ uÑxÆf)?km‚K¶^pXÆ€É",‡~ë †Hк<ÈYÍÅXáJ¹AŒøóx3±è€Þ'¿,™®1îÅï³™6r…t°@À`Ǧäń£]ìI80tôÔJsóŽvH¶ô@þôp·þ÷u ×DÏvæÿÔC¬`Ÿ‰¤©@JOýïòÎh õÚ¦dI¸´ý³R/¢t ®«Ãt]QÃJb@/rPÅUIpVz2ô6ξæ"‰¢ŠåÄ–Ï´ëˆ!ëZ'x¦×n…ƒI.‹H5'w/‡C¹iÁë\Ý -´².œÖ @îh×Ó?Ù›“)Zƒâ+E†Í€sC2j0”.8,qbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs0000644000175100017510000000177715232633614030450 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Product { name: "the-product" type: "output" Group { files: "input.bin" fileTags: "binary" } Group { files: "input.txt" fileTags: "text" } Rule { inputs: ["text", "binary"] Artifact { filePath: "output." + FileInfo.completeSuffix(input.filePath) fileTags: "output" } prepare: { var binary; var prefixArgs; if (Host.os().includes("windows")) { binary = product.qbs.windowsShellPath; prefixArgs = ["/c", "type"]; } else { binary = "cat"; prefixArgs = []; } var inputPath = FileInfo.toNativeSeparators(input.filePath); var cmd = new Command(binary, prefixArgs.concat([inputPath, inputPath])); cmd.stdoutFilePath = output.filePath; cmd.highlight = "filegen"; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/output.bin0000644000175100017510000000400015232633614026104 0ustar runnerrunnerêѸvÊ·€Rˆ–'€.¶wl É >}“ä‹‚ûb»-Å(âóOOtà™:e"ãšlhėʉœO*¨à§d4·ÑœihÆÉ’‹{ŒŒ*æÍŽÅõàOœƒ¢¿Z”Ó®ø±ÿØ ;oþX§·õUl§‰X†ÙvÓÑðÒ¦iªS˜öš¸H+,Ä¢„j2@Ödq*:g¥§w¦Ï°:;ãŸ[èKýΕÉRâîV2xžÈЍ«®³4‘Ý{xÇ»IG¾”D¾~fsT‡6mÅaì—¨—€ ¿¹’ƒ×ûcíÄòyë}Ý@ˆº9lí0ÑkÑß/ÆŒ£nn­Ø]MxãmMŽd8µéþf}‘êÖKJàë7¨ÛD÷£gÿ䃟Ç'NòÊ HýîíÏ}¾{ê»ÑʳO†Ç|ú×ÅÃÅölCË¡Qßá’Ânfîf]ù o a°æ÷«Ôü¾FÙ}s-òþä{Ç$˵zà2ƒ{t–­ç½ÂmT7§W“‹˜C)Ç ˆÑ t-Á•߈Ž`çëF¬¯ÚYŒÂ`"Ça;cåÑÞÕG‹Eú”¯‘aëü^}ürk\ðÍen[̤Ês´“ÆŽÙH-zT¼Á²)o4—¦l®\°oÙUÀWB tOx7Rñ¤R{Í\ZQŠ÷%×jÁÞÄ«ü«ô“úcž åž½lÖ+v ¾µóx^=PC_Ñ<'Î;™?ƒì©­—ÀiYÆ}]òùÅU9}Ä.‚ŽÑÒªYr&©gí¿x‡Å‚¶­#r¡’ÎëôØ/š Ž ²}xzh„sdÍs-v³ƒ%±>ã[]k¶n¦ÊùtÑ5ìp™M?a‚3d½¡)S­•r»Ž©s¾ uÑxÆf)?km‚K¶^pXÆ€É",‡~ë †Hк<ÈYÍÅXáJ¹AŒøóx3±è€Þ'¿,™®1îÅï³™6r…t°@À`Ǧäń£]ìI80tôÔJsóŽvH¶ô@þôp·þ÷u ×DÏvæÿÔC¬`Ÿ‰¤©@JOýïòÎh õÚ¦dI¸´ý³R/¢t ®«Ãt]QÃJb@/rPÅUIpVz2ô6ξæ"‰¢ŠåÄ–Ï´ëˆ!ëZ'x¦×n…ƒI.‹H5'w/‡C¹iÁë\Ý -´².œÖ @îh×Ó?Ù›“)Zƒâ+E†Í€sC2j0”.8,êѸvÊ·€Rˆ–'€.¶wl É >}“ä‹‚ûb»-Å(âóOOtà™:e"ãšlhėʉœO*¨à§d4·ÑœihÆÉ’‹{ŒŒ*æÍŽÅõàOœƒ¢¿Z”Ó®ø±ÿØ ;oþX§·õUl§‰X†ÙvÓÑðÒ¦iªS˜öš¸H+,Ä¢„j2@Ödq*:g¥§w¦Ï°:;ãŸ[èKýΕÉRâîV2xžÈЍ«®³4‘Ý{xÇ»IG¾”D¾~fsT‡6mÅaì—¨—€ ¿¹’ƒ×ûcíÄòyë}Ý@ˆº9lí0ÑkÑß/ÆŒ£nn­Ø]MxãmMŽd8µéþf}‘êÖKJàë7¨ÛD÷£gÿ䃟Ç'NòÊ HýîíÏ}¾{ê»ÑʳO†Ç|ú×ÅÃÅölCË¡Qßá’Ânfîf]ù o a°æ÷«Ôü¾FÙ}s-òþä{Ç$˵zà2ƒ{t–­ç½ÂmT7§W“‹˜C)Ç ˆÑ t-Á•߈Ž`çëF¬¯ÚYŒÂ`"Ça;cåÑÞÕG‹Eú”¯‘aëü^}ürk\ðÍen[̤Ês´“ÆŽÙH-zT¼Á²)o4—¦l®\°oÙUÀWB tOx7Rñ¤R{Í\ZQŠ÷%×jÁÞÄ«ü«ô“úcž åž½lÖ+v ¾µóx^=PC_Ñ<'Î;™?ƒì©­—ÀiYÆ}]òùÅU9}Ä.‚ŽÑÒªYr&©gí¿x‡Å‚¶­#r¡’ÎëôØ/š Ž ²}xzh„sdÍs-v³ƒ%±>ã[]k¶n¦ÊùtÑ5ìp™M?a‚3d½¡)S­•r»Ž©s¾ uÑxÆf)?km‚K¶^pXÆ€É",‡~ë †Hк<ÈYÍÅXáJ¹AŒøóx3±è€Þ'¿,™®1îÅï³™6r…t°@À`Ǧäń£]ìI80tôÔJsóŽvH¶ô@þôp·þ÷u ×DÏvæÿÔC¬`Ÿ‰¤©@JOýïòÎh õÚ¦dI¸´ý³R/¢t ®«Ãt]QÃJb@/rPÅUIpVz2ô6ξæ"‰¢ŠåÄ–Ï´ëˆ!ëZ'x¦×n…ƒI.‹H5'w/‡C¹iÁë\Ý -´².œÖ @îh×Ó?Ù›“)Zƒâ+E†Í€sC2j0”.8,qbs-src-3.3.1/tests/auto/blackbox/testdata/output-redirection/input.txt0000644000175100017510000000003215232633614025753 0ustar runnerrunnerthis is a plain text file qbs-src-3.3.1/tests/auto/blackbox/testdata/no-profile/0000755000175100017510000000000015232633614022265 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/no-profile/no-profile.qbs0000644000175100017510000000012615232633614025045 0ustar runnerrunnerProduct { property bool dummy: { console.info("profile: " + project.profile); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/0000755000175100017510000000000015232633614022526 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/myapp.desktop0000644000175100017510000000030515232633614025245 0ustar runnerrunner[Desktop Entry] GenericName=Image Editor GenericName[fr]=Éditeur d'images Comment=Create images and edit photographs Comment[fr]=Créer des images et éditer des photographies Icon=overridden.png qbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs0000644000175100017510000000175315232633614025556 0ustar runnerrunnerProject { CppApplication { name: "main" install: true property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } files: [ "main.cpp", "myapp.desktop", "myapp.appdata.xml", ] Depends { name: "freedesktop" } freedesktop.appName: "My App" freedesktop.desktopKeys: ({ 'Icon': "myapp.png" }) freedesktop.hicolorRoot: project.sourceDirectory + "/icons/" Group { name: "hicolor" prefix: project.sourceDirectory + "/icons/" files: [ "48x48/apps/myapp.png", "48x48@2/apps/myapp.png", "64x64/apps/myapp.png", "64x64@2/apps/myapp.png", "64x64/mimetypes/application-format.png", "scalable/apps/myapp.png", ] fileTags: "freedesktop.appIcon" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/0000755000175100017510000000000015232633614023641 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64@2/0000755000175100017510000000000015232633614024616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64@2/apps/0000755000175100017510000000000015232633614025561 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64@2/apps/myapp.png0000644000175100017510000000000015232633614027403 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48@2/0000755000175100017510000000000015232633614024622 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48@2/apps/0000755000175100017510000000000015232633614025565 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48@2/apps/myapp.png0000644000175100017510000000000015232633614027407 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64/0000755000175100017510000000000015232633614024434 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64/apps/0000755000175100017510000000000015232633614025377 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64/apps/myapp.png0000644000175100017510000000000015232633614027221 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64/mimetypes/0000755000175100017510000000000015232633614026450 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/64x64/mimetypes/application-format.png0000644000175100017510000000000015232633614032735 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/scalable/0000755000175100017510000000000015232633614025407 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/scalable/apps/0000755000175100017510000000000015232633614026352 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/scalable/apps/myapp.png0000644000175100017510000000000015232633614030174 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48/0000755000175100017510000000000015232633614024440 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48/apps/0000755000175100017510000000000015232633614025403 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/icons/48x48/apps/myapp.png0000644000175100017510000000000015232633614027225 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/main.cpp0000644000175100017510000000003515232633614024154 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml0000644000175100017510000000066515232633614026016 0ustar runnerrunner myapp.desktop CC0 MyApp

The coolest app ever

This is a cool application.

https://software.house/myapp GPL-2.0+ Coding Wizard qbs-src-3.3.1/tests/auto/blackbox/testdata/installable-as-auxiliary-input/0000755000175100017510000000000015232633614026250 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-i0000644000175100017510000000576315232633614033334 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Host import qbs.TextFile Project { name: "p" CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "app" Depends { name: "installed-header" } Rule { multiplex: true auxiliaryInputsFromDependencies: ["installable"] Artifact { filePath: "main.cpp"; fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("#include "); f.writeLine("int main() {"); f.writeLine(" f();"); f.writeLine("}"); f.close(); }; return cmd; } } } Product { name: "installed-header" type: ["header"] property string installDir: "include" qbs.installPrefix: "" Group { fileTagsFilter: "header" qbs.install: true qbs.installDir: installDir } Export { Depends { name: "cpp" } cpp.includePaths: FileInfo.joinPaths(qbs.installRoot, exportingProduct.installDir); } Rule { multiplex: true Artifact { filePath: "theheader.h.in"; fileTags: "header.in" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { // Artificial delay. var file = new TextFile(output.filePath, TextFile.WriteOnly); file.writeLine("#include "); file.writeLine("inline void f() {"); file.writeLine(' std::cout << "f-impl" << std::endl;'); file.writeLine("}"); file.close(); } }; return [cmd]; } } Rule { inputs: "header.in" Artifact { filePath: "theheader.h"; fileTags: "header" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/external-libs/0000755000175100017510000000000015232633614022764 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/external-libs/external-libs.qbs0000644000175100017510000000162515232633614026250 0ustar runnerrunnerimport qbs.TextFile Project { property string libDir: buildDirectory + "/libs" StaticLibrary { name: "lib1" destinationDirectory: project.libDir Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib1.cpp"] } StaticLibrary { name: "lib2" destinationDirectory: project.libDir Depends { name: "cpp" } Depends { name: "lib1" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib2.cpp"] } CppApplication { Depends { name: "lib1"; cpp.link: false } Depends { name: "lib2"; cpp.link: false } files: ["main.cpp"] cpp.libraryPaths: [project.libDir] cpp.staticLibraries: ["lib1", "lib2", "lib1"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/external-libs/lib2.cpp0000644000175100017510000000006515232633614024321 0ustar runnerrunnervoid func_lib1(); void func_lib2() { func_lib1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/external-libs/main.cpp0000644000175100017510000000006315232633614024413 0ustar runnerrunnervoid func_lib2(); int main() { func_lib2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/external-libs/lib1.cpp0000644000175100017510000000002515232633614024314 0ustar runnerrunnervoid func_lib1() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/nodejs/0000755000175100017510000000000015232633614021475 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nodejs/hello.qbs0000644000175100017510000000077415232633614023317 0ustar runnerrunnerimport qbs.Host NodeJSApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } nodejs.applicationFile: "hello.js" name: "hello" } qbs-src-3.3.1/tests/auto/blackbox/testdata/nodejs/hello.js0000644000175100017510000000006115232633614023133 0ustar runnerrunnerif (console) { console.log("hello world"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-language-version/0000755000175100017510000000000015232633614024261 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs0000644000175100017510000000210615232633614031035 0ustar runnerrunnerCppApplication { name: "app" files: ["main.cpp"] Probe { id: compilerProbe property stringList toolchain: qbs.toolchain property string compilerVersion: cpp.compilerVersion configure: { var isNewerMsvc; var isEvenNewerMsvc; var isOlderMsvc; var isGcc; if (toolchain.includes("clang-cl")) { isEvenNewerMsvc = true; isNewerMsvc = true; } else if (toolchain.includes("msvc")) { if (compilerVersion >= "19.12.25831") isEvenNewerMsvc = true; if (compilerVersion >= "18.00.30723") isNewerMsvc = true; else isOlderMsvc = true; } else { isGcc = true; } console.info("is newer MSVC: " + isNewerMsvc); console.info("is even newer MSVC: " + isEvenNewerMsvc); console.info("is older MSVC: " + isOlderMsvc); console.info("is GCC: " + isGcc); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-language-version/main.cpp0000644000175100017510000000001615232633614025706 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/0000755000175100017510000000000015232633614025312 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs0000644000175100017510000000106115232633614031547 0ustar runnerrunnerimport qbs.TextFile Product { type: "custom" Group { files: "dummy.txt" fileTags: "input" } Rule { inputs: "input" Artifact { fileTags: "custom" filePath: "oldfile" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating file"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt0000644000175100017510000000000015232633614027174 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/0000755000175100017510000000000015232633614023461 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/after/0000755000175100017510000000000015232633614024562 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/after/lib2.cpp0000644000175100017510000000257115232633614026123 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib2.h" #include void print_two_numbers(int a, int b, int c) { std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/after/lib2.h0000644000175100017510000000241015232633614025560 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void print_two_numbers(int a, int b, int c); qbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/before/0000755000175100017510000000000015232633614024723 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/before/renameDependency.qbs0000644000175100017510000000005715232633614030702 0ustar runnerrunnerCppApplication { files: ["*.cpp", "*.h"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/before/lib.cpp0000644000175100017510000000260115232633614026174 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" #include void print_two_numbers(int a, int b/*, int c*/) { std::cout << "a=" << a << ", b=" << b /*<< ", c=" << c */ << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/before/lib.h0000644000175100017510000000241415232633614025643 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void print_two_numbers(int a, int b/*, int c*/); qbs-src-3.3.1/tests/auto/blackbox/testdata/renameDependency/before/main.cpp0000644000175100017510000000247315232633614026361 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "lib.h" int main() { print_two_numbers(2, 3); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-textfile/0000755000175100017510000000000015232633614024571 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs0000644000175100017510000000300315232633614027120 0ustar runnerrunnerimport qbs.TextFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var file1 = new TextFile("file1.txt", TextFile.WriteOnly); file1.write("First line.\n"); // Do not close the file to test the auto close functionality. }; commands.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var file1 = new TextFile("file1.txt", TextFile.WriteOnly | TextFile.Append); file1.write("Second line.\nThird line."); file1.close(); file1 = new TextFile("file1.txt", TextFile.ReadWrite); var file2 = new TextFile("file2.txt", TextFile.WriteOnly); file2.writeLine(file1.atEof()); while (true) { var line = file1.readLine(); if (!line || line.length == 0) break; file2.writeLine(line); } file1.truncate(); file2.writeLine(file1.filePath()); file2.writeLine(file1.atEof()); file1.close(); file2.close(); }; commands.push(cmd); return commands; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/0000755000175100017510000000000015232633614025726 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/modules/0000755000175100017510000000000015232633614027376 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/0000755000175100017510000000000015232633614030310 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs0000644000175100017510000000014015232633614031724 0ustar runnerrunnerModule { property string productInBase: product.name property string productInTop: "" } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/0000755000175100017510000000000015232633614030200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs0000644000175100017510000000024315232633614031510 0ustar runnerrunnerModule { Depends { name: "base" } base.productInTop: product.name property string productInTop: product.name property string productInExport: "" } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.q0000644000175100017510000000206515232633614033626 0ustar runnerrunnerProject { qbsSearchPaths: [ path ] Product { name: "mylib" Export { Depends { name: "top" } top.productInExport: exportingProduct.name } } Product { type: "rule-output" name: "myapp" Depends { name: "mylib" } Rule { alwaysRun: true multiplex: true requiresInputs: false outputFileTags: "rule-output" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("base.productInBase evaluated in: " + product.base.productInBase); console.info("base.productInTop evaluated in: " + product.base.productInTop); console.info("top.productInExport evaluated in: " + product.top.productInExport); console.info("top.productInTop evaluated in: " + product.top.productInTop); } return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/generator/0000755000175100017510000000000015232633614022201 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/generator/input.none.txt0000644000175100017510000000000015232633614025025 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/generator/generator.qbs0000644000175100017510000000230215232633614024673 0ustar runnerrunnerimport qbs.TextFile CppApplication { name: "app" files: "main.cpp" Group { files: "input.txt" fileTags: "generator.in" } Rule { inputs: ["generator.in"] Artifact { filePath: "file1.cpp"; fileTags: ["cpp", "file1"]; alwaysUpdated: false } Artifact { filePath: "file2.cpp"; fileTags: ["cpp", "file2"]; alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "potentially generating files"; cmd.sourceCode = function() { var f = new TextFile(input.filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); if (content.includes("file1")) { f = new TextFile(outputs.file1[0].filePath, TextFile.WriteOnly); f.writeLine("void f1() {}"); f.close(); } if (content.includes("file2")) { f = new TextFile(outputs.file2[0].filePath, TextFile.WriteOnly); f.writeLine("void f2() {}"); f.close(); } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/generator/input.file1.txt0000644000175100017510000000001215232633614025071 0ustar runnerrunnerfile1.cpp qbs-src-3.3.1/tests/auto/blackbox/testdata/generator/input.both.txt0000644000175100017510000000002415232633614025030 0ustar runnerrunnerfile1.cpp file2.cpp qbs-src-3.3.1/tests/auto/blackbox/testdata/generator/main.cpp0000644000175100017510000000007215232633614023630 0ustar runnerrunnervoid f1(); void f2(); int main() { f1(); f2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/generator/input.file2.txt0000644000175100017510000000001215232633614025072 0ustar runnerrunnerfile2.cpp qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/0000755000175100017510000000000015232633614023652 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/thelib.cpp0000644000175100017510000000007015232633614025622 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void libFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/install-locations.qbs0000644000175100017510000000273315232633614030025 0ustar runnerrunnerProject { name: "Install-Locations" property bool dummy: { var toolchain = "unknown"; if (qbs.toolchain.includes("emscripten")) { toolchain = "emscripten"; } else if (qbs.targetOS.includes("darwin")) { if (qbs.targetOS.includes("macos")) toolchain = "macos"; else toolchain = "darwin"; } else if (qbs.targetOS.includes("windows")) { if (qbs.toolchain.includes("mingw")) toolchain = "mingw"; else toolchain = "msvc"; } else { toolchain = "unix"; } console.info("===toolchain:" + toolchain + "==="); } CppApplication { name: "theapp" files: "main.cpp" cpp.separateDebugInformation: true Group { fileTagsFilter: "application" fileTags: "some-tag" } } DynamicLibrary { name: "thelib" installImportLib: true Depends { name: "cpp" } cpp.separateDebugInformation: true files: "thelib.cpp" } LoadableModule { name: "theloadablemodule" Depends { name: "cpp" } cpp.separateDebugInformation: true files: "theplugin.cpp" } Project { name: "subproject" Plugin { name: "theplugin" Depends { name: "cpp" } cpp.separateDebugInformation: true files: "theplugin.cpp" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/main.cpp0000644000175100017510000000001615232633614025277 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/theplugin.cpp0000644000175100017510000000007315232633614026355 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void pluginFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/0000755000175100017510000000000015232633614024563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/mingw.json0000644000175100017510000000246215232633614026603 0ustar runnerrunner{ "app": { "fileName": "theapp.exe", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "appDsym": { "fileName": "theapp.exe.debug", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "thelib.dll", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "dllDsym": { "fileName": "thelib.dll.debug", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "lib": { "fileName": "thelib.lib", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" }, "plugin": { "fileName": "theplugin.dll", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "pluginDir", "subDir": "" }, "pluginDsym": { "fileName": "theplugin.dll.debug", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "dsymDir", "subDir": "" }, "loadableModule": { "fileName": "theloadablemodule.dll", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "loadableModuleDsym": { "fileName": "theloadablemodule.dll.debug", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/unix.json0000644000175100017510000000226415232633614026445 0ustar runnerrunner{ "app": { "fileName": "theapp", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "appDsym": { "fileName": "theapp.debug", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "libthelib.so", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" }, "dllDsym": { "fileName": "libthelib.so.debug", "defaultInstallDir": "/lib", "customInstallDir": "dsymDir", "subDir": "" }, "plugin": { "fileName": "libtheplugin.so", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "pluginDir", "subDir": "" }, "pluginDsym": { "fileName": "libtheplugin.so.debug", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "dsymDir", "subDir": "" }, "loadableModule": { "fileName": "libtheloadablemodule.so", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" }, "loadableModuleDsym": { "fileName": "libtheloadablemodule.so.debug", "defaultInstallDir": "/lib", "customInstallDir": "dsymDir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/emscripten.json0000644000175100017510000000133515232633614027631 0ustar runnerrunner{ "app": { "fileName": "theapp.js", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "appDsym": { "fileName": "theapp.wasm.debug.wasm", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "libthelib.so", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" }, "plugin": { "fileName": "libtheplugin.so", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "pluginDir", "subDir": "" }, "loadableModule": { "fileName": "libtheloadablemodule.so", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/macos.json0000644000175100017510000000255315232633614026565 0ustar runnerrunner{ "app": { "fileName": "theapp", "defaultInstallDir": "/Applications", "customInstallDir": "bindir", "subDir": "theapp.app/Contents/MacOS" }, "appDsym": { "fileName": "theapp.app.dSYM", "defaultInstallDir": "/Applications", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "thelib", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "libdir", "subDir": "thelib.framework" }, "dllDsym": { "fileName": "thelib.framework.dSYM", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "dsymDir", "subDir": "" }, "plugin": { "fileName": "theplugin", "defaultInstallDir": "/Library/Install-Locations/PlugIns", "customInstallDir": "pluginDir", "subDir": "theplugin.bundle/Contents/MacOS" }, "pluginDsym": { "fileName": "theplugin.bundle.dSYM", "defaultInstallDir": "/Library/Install-Locations/PlugIns", "customInstallDir": "dsymDir", "subDir": "" }, "loadableModule": { "fileName": "theloadablemodule", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "libdir", "subDir": "theloadablemodule.bundle/Contents/MacOS" }, "loadableModuleDsym": { "fileName": "theloadablemodule.bundle.dSYM", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "dsymDir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/darwin.json0000644000175100017510000000247615232633614026753 0ustar runnerrunner{ "app": { "fileName": "theapp", "defaultInstallDir": "/Applications", "customInstallDir": "bindir", "subDir": "theapp.app" }, "appDsym": { "fileName": "theapp.app.dSYM", "defaultInstallDir": "/Applications", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "thelib", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "libdir", "subDir": "thelib.framework" }, "dllDsym": { "fileName": "thelib.framework.dSYM", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "dsymDir", "subDir": "" }, "plugin": { "fileName": "theplugin", "defaultInstallDir": "/Library/Install-Locations/PlugIns", "customInstallDir": "pluginDir", "subDir": "theplugin.bundle" }, "pluginDsym": { "fileName": "theplugin.bundle.dSYM", "defaultInstallDir": "/Library/Install-Locations/PlugIns", "customInstallDir": "dsymDir", "subDir": "" }, "loadableModule": { "fileName": "theloadablemodule", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "libdir", "subDir": "theloadablemodule.bundle" }, "loadableModuleDsym": { "fileName": "theloadablemodule.bundle.dSYM", "defaultInstallDir": "/Library/Frameworks", "customInstallDir": "dsymDir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-locations/data/msvc.json0000644000175100017510000000243215232633614026427 0ustar runnerrunner{ "app": { "fileName": "theapp.exe", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "appDsym": { "fileName": "theapp.pdb", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "dll": { "fileName": "thelib.dll", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "dllDsym": { "fileName": "thelib.pdb", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" }, "lib": { "fileName": "thelib.lib", "defaultInstallDir": "/lib", "customInstallDir": "libdir", "subDir": "" }, "plugin": { "fileName": "theplugin.dll", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "pluginDir", "subDir": "" }, "pluginDsym": { "fileName": "theplugin.pdb", "defaultInstallDir": "/lib/install-locations/plugins/", "customInstallDir": "dsymDir", "subDir": "" }, "loadableModule": { "fileName": "theloadablemodule.dll", "defaultInstallDir": "/bin", "customInstallDir": "bindir", "subDir": "" }, "loadableModuleDsym": { "fileName": "theloadablemodule.pdb", "defaultInstallDir": "/bin", "customInstallDir": "dsymDir", "subDir": "" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-install-dir/0000755000175100017510000000000015232633614024061 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs0000644000175100017510000000022215232633614030432 0ustar runnerrunnerCppApplication { consoleApplication: true files: ["main.cpp"] qbs.installPrefix: "" install: true installDir: "../whatever" } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-install-dir/main.cpp0000644000175100017510000000001615232633614025506 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/allowed-values/0000755000175100017510000000000015232633614023137 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/allowed-values/modules/0000755000175100017510000000000015232633614024607 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/allowed-values/modules/a/0000755000175100017510000000000015232633614025027 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/allowed-values/modules/a/a.qbs0000644000175100017510000000066215232633614025762 0ustar runnerrunnerModule { // tests VariantValue property stringList prop PropertyOptions { name: "prop" description: "Some prop" allowedValues: ["foo", "bar"] } // tests JSValue property stringList prop2 // setter for otherProp property stringList otherProp: prop2 PropertyOptions { name: "otherProp" description: "Some other prop" allowedValues: ["foo", "bar"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/allowed-values/allowed-values.qbs0000644000175100017510000000067415232633614026601 0ustar runnerrunnerProduct { Depends { name: "a" } // tests VariantValue property string prop PropertyOptions { name: "prop" description: "Some prop" allowedValues: "foo" } // tests JSValue property string prop2 // setter for otherProp property string otherProp: prop2 PropertyOptions { name: "otherProp" description: "Some other prop" allowedValues: "foo" } name: "p" } qbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/0000755000175100017510000000000015232633614030617 5ustar runnerrunner././@LongLink0000644000000000000000000000020700000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/source-artifact-in-inputs-from-dependencies.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/source-artifa0000644000175100017510000000313315232633614033306 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Project { Product { name: "dep1" Group { files: ["header.h"] qbs.install: true qbs.installDir: "include1" } } Product { name: "dep2" Group { files: ["header.h"] qbs.install: true qbs.installDir: "include2" } } Product { name: "p" type: ["custom"] Depends { name: "dep1" } Depends { name: "dep2" } Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "output.txt" fileTags: ["custom"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); var artifactList = inputs["installable"]; for (var i = 0; i < (artifactList ? artifactList.length : 0); ++i) { var artifact = artifactList[i]; tf.writeLine(FileInfo.joinPaths(artifact.qbs.installDir, artifact.fileName)); } } finally { if (tf) tf.close(); } } return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/header.h0000644000175100017510000000000015232633614032206 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/0000755000175100017510000000000015232633614025274 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/lib3.cpp0000644000175100017510000000007215232633614026630 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib3Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs0000644000175100017510000000232515232633614032311 0ustar runnerrunnerProject { DynamicLibrary { id: idLib1 name: "lib1" Depends { name: "cpp" } files: ["lib1.cpp"] Depends { name: "bundle" } bundle.isBundle: false Probe { id: checker property bool isGcc: qbs.toolchain.contains("gcc") configure: { console.info("is gcc: " + isGcc); } } } DynamicLibrary { id: idLib2 name: "lib2" Depends { name: "cpp" } files: ["lib2.cpp"] Depends { name: "bundle" } bundle.isBundle: false } DynamicLibrary { id: idLib3 name: "lib3" Depends { name: "cpp" } files: ["lib3.cpp"] Depends { name: "bundle" } bundle.isBundle: false } CppApplication { name: "main" files: "main.cpp" Depends { name: "lib1"; cpp.link: false } Depends { name: "lib2"; cpp.link: false } Depends { name: "lib3"; cpp.link: false } cpp.libraryPaths: [ idLib1.buildDirectory, idLib2.buildDirectory, idLib3.buildDirectory ] cpp.dynamicLibraries: [ "lib1", "lib2", "lib1", "lib3", "lib2", "lib1" ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/lib2.cpp0000644000175100017510000000007215232633614026627 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib2Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/main.cpp0000644000175100017510000000027515232633614026730 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void lib1Func(); DLL_IMPORT void lib2Func(); DLL_IMPORT void lib3Func(); int main() { lib1Func(); lib2Func(); lib3Func(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-library-duplicates/lib1.cpp0000644000175100017510000000007215232633614026626 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib1Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/0000755000175100017510000000000015232633614023012 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/modules/0000755000175100017510000000000015232633614024462 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/modules/themodule/0000755000175100017510000000000015232633614026450 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/modules/themodule/themodule.qbs0000644000175100017510000000030115232633614031137 0ustar runnerrunnerModule { Group { cpp.defines: ["REQUIRED_FOR_FILE3"] Group { prefix: product.sourceDirectory + '/' files: ["file3.cpp", "file3.h"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/file3.h0000644000175100017510000000235115232633614024166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file3(); qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/main.cpp0000644000175100017510000000255315232633614024447 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "file1.h" #include "file2.h" #include "file3.h" #include "other.h" int main() { file1(); file2(); file3(); other(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/nested-groups.qbs0000644000175100017510000000222215232633614026316 0ustar runnerrunnerCppApplication { consoleApplication: true Depends { name: "themodule" } cpp.includePaths: ["subdir"] property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: ["main.cpp"] Group { prefix: "subdir/" cpp.defines: ["REQUIRED_FOR_FILE1", "BREAKS_FILE2"] fileTags: ["cpp"] // This group has no files, and that's okay. Group { files: ["other.cpp", "other.h"] Group { cpp.defines: outer.concat(["ALSO_REQUIRED_FOR_FILE1"]) files: ["file1.cpp", "file1.h"] } Group { cpp.defines: ["REQUIRED_FOR_FILE2"] files: ["file2.cpp", "file2.h"] } Group { name: "disabled" condition: false Group { name: "indirectly disabled" condition: true files: ["main2.cpp"] } } Group { name: "no tags" fileTags: [] files: ["main3.cpp"] } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/0000755000175100017510000000000015232633614024302 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/other.h0000644000175100017510000000235115232633614025575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void other(); qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/main3.cpp0000644000175100017510000000235215232633614026017 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/other.cpp0000644000175100017510000000253415232633614026133 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE1 #error "missing define" #endif #ifndef BREAKS_FILE2 #error "missing define" #endif void other() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/file1.cpp0000644000175100017510000000254615232633614026015 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE1 #error "missing define" #endif #ifndef ALSO_REQUIRED_FOR_FILE1 #error "missing define" #endif void file1() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/file2.cpp0000644000175100017510000000253515232633614026014 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef BREAKS_FILE2 #error "unexpected define" #endif #ifndef REQUIRED_FOR_FILE2 #error "missing define" #endif void file2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/main2.cpp0000644000175100017510000000235215232633614026016 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/file2.h0000644000175100017510000000235115232633614025455 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file2(); qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/subdir/file1.h0000644000175100017510000000235115232633614025454 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file1(); qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-groups/file3.cpp0000644000175100017510000000244615232633614024526 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE3 #error "missing define" #endif void file3() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/escaped-linker-flags/0000755000175100017510000000000015232633614024173 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs0000644000175100017510000000074115232633614030664 0ustar runnerrunnerCppApplication { name: "app" property bool escapeLinkerFlags Properties { condition: escapeLinkerFlags cpp.linkerFlags: ["-Wl,-s"] } Properties { condition: !escapeLinkerFlags cpp.linkerFlags: ["-s"] } files: ["main.cpp"] Probe { id: checker property bool isUnixGcc: qbs.toolchain.contains("gcc") && !qbs.targetOS.contains("macos") configure: { console.info("is gcc: " + isUnixGcc); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/escaped-linker-flags/main.cpp0000644000175100017510000000001715232633614025621 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/0000755000175100017510000000000015232633614023664 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/firstlib.h0000644000175100017510000000024615232633614025655 0ustar runnerrunner#include "../dllexport.h" #ifdef FIRSTLIB # define FIRSTLIB_EXPORT DLL_EXPORT #else # define FIRSTLIB_EXPORT DLL_IMPORT #endif FIRSTLIB_EXPORT void firstLib(); qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/0000755000175100017510000000000015232633614025334 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper3/0000755000175100017510000000000015232633614026676 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper3/helper3.qbs0000644000175100017510000000012115232633614030741 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.includePaths: "/somedir/include3" } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper1/0000755000175100017510000000000015232633614026674 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper1/helper1.qbs0000644000175100017510000000016115232633614030741 0ustar runnerrunnerModule { Depends { name: "cpp" } Depends { name: "helper2" } cpp.includePaths: "/somedir/include1" } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper2/0000755000175100017510000000000015232633614026675 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper2/helper2.qbs0000644000175100017510000000012115232633614030737 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.includePaths: "/somedir/include2" } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheFirstLib_windows.pc0000644000175100017510000000051315232633614030140 0ustar runnerrunnerprefix=/opt/the firstlib Name: TheFirstLib Description: TheFirstLib Version: 1.0 URL: http://www.example.com/thefirstlib Cflags: -DTheFirstLib -I"${prefix}/include" -DHAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER -I/otherdir/include1 -I/otherdir/include2 Libs: -L"${prefix}/lib" -lTheFirstLib Requires: Qt5Core Requires.private: SomeHelper qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/secondlib.cpp0000644000175100017510000000020315232633614026325 0ustar runnerrunner#include "secondlib.h" #ifndef HAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER # error I CANT LIVE WITHOUT IT! #endif void secondLib() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheSecondLib.pc0000644000175100017510000000027215232633614026514 0ustar runnerrunnerconfig1=a b config2=c Name: TheSecondLib Description: The second lib Version: 2.0 Cflags: -I/opt/thesecondlib/include Libs: -L/opt/thesecondlib/lib -lTheSecondLib Requires: TheFirstLib qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheFirstLib.pc0000644000175100017510000000053515232633614026372 0ustar runnerrunnerprefix=/opt/the firstlib Name: TheFirstLib Description: TheFirstLib Version: 1.0 URL: http://www.example.com/thefirstlib Cflags: -DTheFirstLib -I"${prefix}/include" -pthread -DHAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER -I/otherdir/include1 -I/otherdir/include2 Libs: -L"${prefix}/lib" -lTheFirstLib -pthread Requires: Qt5Core Requires.private: SomeHelper qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs0000644000175100017510000000754715232633614030061 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { Product { name: "dummy" Export { Depends { name: "TheFirstLib" } } } Product { name: "SomeHelper" Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.versionEntry: "1.0" } StaticLibrary { Depends { name: "cpp" } Depends { name: "bundle" } bundle.isBundle: false name: "BoringStaticLib" files: ["boringstaticlib.cpp"] Export { Depends { name: "cpp" } cpp.defines: ["HAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER"] } } DynamicLibrary { name: "TheFirstLib" version: "1.0" Depends { name: "SomeHelper" } Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.excludedDependencies: ["Qt.core", "helper3"] Exporter.pkgconfig.requiresEntry: "Qt5Core" Exporter.pkgconfig.urlEntry: "http://www.example.com/thefirstlib" Depends { name: "cpp" } cpp.defines: ["FIRSTLIB"] Depends { name: "bundle" } bundle.isBundle: false qbs.installPrefix: "/opt/the firstlib" installDir: "lib" installImportLib: true Export { prefixMapping: [{prefix: "/somedir", replacement: "/otherdir"}] Depends { name: "BoringStaticLib" } Depends { name: "cpp" } Depends { name: "Qt.core"; required: false } Depends { name: "helper1" } Depends { name: "helper3" } property bool someCondition: Host.os().includes("windows") // hostOS for easier testing property bool someOtherCondition: someCondition Properties { condition: !someOtherCondition cpp.driverFlags: ["-pthread"] } cpp.defines: exportingProduct.name cpp.includePaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "include")] Qt.core.mocName: "muck" } Group { name: "api_headers" files: ["firstlib.h"] qbs.install: true qbs.installDir: "include" } files: ["firstlib.cpp"] } DynamicLibrary { name: "TheSecondLib" version: "2.0" Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.descriptionEntry: "The second lib" Exporter.pkgconfig.transformFunction: (function(product, moduleName, propertyName, value) { if (moduleName === "cpp" && propertyName === "includePaths") return value.filter(function(p) { return p !== product.sourceDirectory; }); return value; }) Exporter.pkgconfig.customVariables: ({config1: "a b", config2: "c"}) Depends { name: "cpp" } cpp.defines: ["SECONDLIB"] Depends { name: "bundle" } bundle.isBundle: false installDir: "/opt/thesecondlib/lib" installImportLib: true qbs.installPrefix: "" Depends { name: "TheFirstLib" } Export { Depends { name: "TheFirstLib" } Depends { name: "dummy" } Depends { name: "cpp" } cpp.includePaths: [ "/opt/thesecondlib/include", exportingProduct.sourceDirectory, importingProduct.buildDirectory ] property string hurz: importingProduct.name cpp.defines: hurz.toUpperCase() Rule { property int n: 5 Artifact { filePath: "dummy" fileTags: ["d1", "d2"] cpp.warningsAreErrors: true } } } Group { name: "api_headers" files: ["secondlib.h"] qbs.install: true qbs.installDir: "/opt/thesecondlib/include" } files: ["secondlib.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/secondlib.h0000644000175100017510000000025315232633614025777 0ustar runnerrunner#include "../dllexport.h" #ifdef SECONDLIB # define SECONDLIB_EXPORT DLL_EXPORT #else # define SECONDLIB_EXPORT DLL_IMPORT #endif SECONDLIB_EXPORT void secondLib(); qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/boringstaticlib.cpp0000644000175100017510000000005715232633614027551 0ustar runnerrunnerint calculateLuckyNumber() { return 12 * 13; } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-pkgconfig/firstlib.cpp0000644000175100017510000000005315232633614026204 0ustar runnerrunner#include "firstlib.h" void firstLib() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/installable/0000755000175100017510000000000015232633614022505 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installable/main.cpp0000644000175100017510000000235115232633614024136 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/installable/installable.qbs0000644000175100017510000000221615232633614025507 0ustar runnerrunnerimport qbs.TextFile Project { CppApplication { type: ["application"] name: "app" consoleApplication: true Group { files: ["main.cpp"] qbs.install: true } install: true installDebugInformation: false installDir: "" } Product { name: "install-list" type: ["install-list"] Depends { name: "app" } Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "installed-files.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.installable.length; ++i) file.writeLine(inputs.installable[i].filePath); file.close(); }; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/0000755000175100017510000000000015232633614020765 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ico/icon_32x32.png0000644000175100017510000000123115232633614023261 0ustar runnerrunner‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/icon_16x16.png0000644000175100017510000000121115232633614023263 0ustar runnerrunner‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/dmg.iconset/0000755000175100017510000000000015232633614023177 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_32x32.png0000644000175100017510000000253615232633614025504 0ustar runnerrunner‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_256x256.png0000644000175100017510000002605015232633614025661 0ustar runnerrunner‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_16x16.png0000644000175100017510000000074715232633614025512 0ustar runnerrunner‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_128x128.png0000644000175100017510000001221015232633614025646 0ustar runnerrunner‰PNG  IHDR€€Ã>aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚qbs-src-3.3.1/tests/auto/blackbox/testdata/ico/ico.qbs0000644000175100017510000000343715232633614022255 0ustar runnerrunnerProject { Product { Depends { name: "ico" } type: ["ico"] name: "icon" files: [ "icon_16x16.png", "icon_32x32.png" ] } Product { Depends { name: "ico" } type: ["ico"] name: "icon-alpha" files: [ "icon_16x16.png", "icon_32x32.png" ] ico.alphaThreshold: 50 } Product { Depends { name: "ico" } type: ["ico"] name: "icon-big" files: [ "dmg.iconset/icon_16x16.png", "dmg.iconset/icon_32x32.png", "dmg.iconset/icon_128x128.png", ] Group { name: "raw" prefix: "dmg.iconset/" files: [ "icon_256x256.png", "icon_512x512.png", ] ico.raw: true } } Product { Depends { name: "ico" } type: ["cur"] name: "cursor" files: [ "icon_16x16.png", "icon_32x32.png" ] } Product { Depends { name: "ico" } type: ["cur"] name: "cursor-hotspot" Group { files: ["icon_16x16.png"] ico.cursorHotspotX: 8 ico.cursorHotspotY: 9 } Group { files: ["icon_32x32.png"] ico.cursorHotspotX: 16 ico.cursorHotspotY: 17 } } Product { Depends { name: "ico" } type: ["cur"] name: "cursor-hotspot-single" Group { files: ["icon_16x16.png"] ico.cursorHotspotX: 8 ico.cursorHotspotY: 9 } } Product { Depends { name: "ico" } type: ["ico", "cur"] name: "iconset" files: ["dmg.iconset"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/always-run/0000755000175100017510000000000015232633614022315 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/always-run/transformer.qbs0000644000175100017510000000102215232633614025361 0ustar runnerrunnerimport qbs.TextFile Product { type: ["blubb"] Transformer { alwaysRun: false Artifact { filePath: "blubb.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "yo"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("blubb"); f.close(); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/always-run/rule.qbs0000644000175100017510000000116115232633614023772 0ustar runnerrunnerimport qbs.TextFile Product { type: ["blubb"] Group { files: ["dummy.txt"] fileTags: ["dummy"] } Rule { alwaysRun: false inputs: ["dummy"] Artifact { filePath: "blubb.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "yo"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("blubb"); f.close(); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/always-run/dummy.txt0000644000175100017510000000000015232633614024177 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installed-source-files/0000755000175100017510000000000015232633614024570 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installed-source-files/readme.txt0000644000175100017510000000002615232633614026564 0ustar runnerrunnerimportant information qbs-src-3.3.1/tests/auto/blackbox/testdata/installed-source-files/main.cpp0000644000175100017510000000236415232633614026225 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs0000644000175100017510000000062715232633614031661 0ustar runnerrunnerCppApplication { consoleApplication: true files: ["main.cpp"] qbs.installPrefix: "" Group { fileTagsFilter: ["cpp"] qbs.install: true } Group { // this overwrites the properties of the group below fileTagsFilter: ["text"] qbs.install: true } Group { files: ["readme.txt"] fileTags: ["text"] qbs.install: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/enable-time-trace/0000755000175100017510000000000015232633614023471 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/enable-time-trace/enable-time-trace.qbs0000644000175100017510000000066215232633614027462 0ustar runnerrunnerProject { CppApplication { qbs.installPrefix: "" property bool dummy: { console.info("supports time trace: " + cpp._supportsTimeTrace); } name: "enable-time-trace" files: ["main.cpp"] cpp.enableTimeTrace: true Group { fileTagsFilter: "time_trace" qbs.install: true qbs.installDir: "share/enable-time-trace" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/enable-time-trace/main.cpp0000644000175100017510000000003515232633614025117 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/0000755000175100017510000000000015232633614022264 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/indirect_global.h0000644000175100017510000000026715232633614025563 0ustar runnerrunner#pragma once #if defined(INDIRECT_LIBRARY) #define INDIRECT_EXPORT __attribute__((visibility("default"))) #else #define INDIRECT_EXPORT __attribute__((visibility("default"))) #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/rpath-link.qbs0000644000175100017510000000361615232633614025052 0ustar runnerrunnerimport qbs.FileInfo Project { property bool enableConsumer: false property bool enableRPathLink: false DynamicLibrary { name: "indirect" Probe { id: targetInfo property bool isUnixGcc: qbs.targetOS.includes("unix") && !qbs.targetOS.contains("darwin") && qbs.toolchain.includes("gcc") configure: { console.info("is gcc on unix: " + isUnixGcc) } } Depends { name: "cpp" } cpp.defines: "INDIRECT_LIBRARY" files: [ "indirect.cpp", "indirect.h", "indirect_global.h", ] qbs.installPrefix: "" installDir: "/lib" } DynamicLibrary { name: "direct" Depends { name: "cpp" } Depends { name: "indirect" } Depends { name: "Exporter.qbs" } cpp.defines: "DIRECT_LIBRARY" Group { name: "public headers" files: [ "direct.h", "direct_global.h", ] qbs.install: true qbs.installDir: headersInstallDir } files: "direct.cpp" Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.installDir: "/qbs/modules/direct-installed" } qbs.installPrefix: "" installDir: "/lib" property string headersInstallDir: "/include" Export { Depends { name: "cpp" } cpp.includePaths: qbs.installRoot + '/' + exportingProduct.headersInstallDir } } CppApplication { name: "consumer" condition: enableConsumer qbsSearchPaths: qbs.installRoot + "/qbs" Depends { name: "direct-installed" } Properties { condition: project.enableRPathLink cpp.rpathLinkDirs: qbs.installRoot + "/lib" } files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/direct.h0000644000175100017510000000021115232633614023701 0ustar runnerrunner#ifndef DIRECT_H #define DIRECT_H #include "direct_global.h" class DIRECT_EXPORT Direct { public: Direct(); }; #endif // DIRECT_H qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/direct_global.h0000644000175100017510000000035715232633614025234 0ustar runnerrunner#ifndef DIRECT_GLOBAL_H #define DIRECT_GLOBAL_H #if defined(DIRECT_LIBRARY) #define DIRECT_EXPORT __attribute__((visibility("default"))) #else #define DIRECT_EXPORT __attribute__((visibility("default"))) #endif #endif // DIRECT_GLOBAL_H qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/direct.cpp0000644000175100017510000000012315232633614024236 0ustar runnerrunner#include "direct.h" #include "indirect.h" Direct::Direct() { Indirect ind; } qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/main.cpp0000644000175100017510000000006215232633614023712 0ustar runnerrunner#include int main() { Direct d; } qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/indirect.h0000644000175100017510000000015015232633614024232 0ustar runnerrunner#pragma once #include "indirect_global.h" class INDIRECT_EXPORT Indirect { public: Indirect(); }; qbs-src-3.3.1/tests/auto/blackbox/testdata/rpath-link/indirect.cpp0000644000175100017510000000005715232633614024573 0ustar runnerrunner#include "indirect.h" Indirect::Indirect() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/library-type/0000755000175100017510000000000015232633614022636 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/library-type/library-type.cpp0000644000175100017510000000007015232633614025762 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void libFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/library-type/library-type.qbs0000644000175100017510000000145215232633614025772 0ustar runnerrunnerProject { property bool dummy: { const isWin = qbs.targetOS.includes("windows"); const isDarwin = qbs.targetOS.includes("darwin"); const isMac = qbs.targetOS.includes("macos"); const toolGcc = qbs.toolchain.includes("gcc") || qbs.toolchain.includes("emscripten"); console.info("is windows: " + (isWin ? "yes" : "no")); console.info("is darwin: " + (isDarwin ? "yes" : "no")); console.info("is macos: " + (isMac ? "yes" : "no")); console.info("is gcc: " + (toolGcc ? "yes" : "no")); } Library { Depends { name: "cpp" } Depends { name: "bundle" } name: "mylib" files: ["library-type.cpp"] qbs.installPrefix: "" config.install.staticLibraries: true bundle.isBundle: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/0000755000175100017510000000000015232633614026523 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/main.cpp0000644000175100017510000000001615232633614030150 0ustar runnerrunnerint main() {} ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/add-filetag-to-generated-artifact.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/add-filetag-to-generate0000644000175100017510000000211415232633614033015 0ustar runnerrunnerimport qbs.File Project { property bool enableTagging CppApplication { name: "my_app" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" Group { condition: project.enableTagging fileTagsFilter: ["application"] fileTags: ["app-to-compress"] } } Product { name: "my_compressed_app" type: ["compressed_application"] Depends { name: "my_app" } Rule { inputsFromDependencies: ["app-to-compress"] Artifact { filePath: "compressed-" + input.fileName fileTags: ["compressed_application"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "compressing " + input.fileName; cmd.highlight = "linker"; cmd.sourceCode = function () { File.copy(input.filePath, output.filePath); }; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/undefined-target-platform/0000755000175100017510000000000015232633614025262 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs0000644000175100017510000000051015232633614033034 0ustar runnerrunnerimport qbs.File import qbs.FileInfo Product { name: "undefined-target-platform" qbs.targetPlatform: undefined readonly property bool _validate: { if ((qbs.targetOS instanceof Array) && qbs.targetOS.length === 0) return true; throw "Invalid qbs.targetOS value: " + qbs.targetOS; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/0000755000175100017510000000000015232633614023256 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/testlib/0000755000175100017510000000000015232633614024724 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py0000644000175100017510000000111115232633614027226 0ustar runnerrunnerfrom conans import ConanFile class Testlib(ConanFile): name = "testlib" description = "Represents an arbitrary package, for instance on bintray" license = "none" version = "1.2.3" settings = "os" options = {"opt": [True, False]} default_options = {"opt": False} def source(self): pass def build(self): pass def package(self): pass def package_info(self): self.cpp_info.libs = ["testlib1","testlib2"] self.env_info.ENV_VAR = "TESTLIB_ENV_VAL" self.user_info.user_var = "testlib_user_val" qbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/testapp/0000755000175100017510000000000015232633614024736 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py0000644000175100017510000000116715232633614027253 0ustar runnerrunnerfrom conans import ConanFile class TestApp(ConanFile): name = "testapp" description = "Our project package, to be inspected by the Qbs ConanfileProbe" license = "none" version = "6.6.6" settings = "os" options = {"opt": [True, False], "forceFailure": [True, False]} default_options = {"opt": False, "forceFailure": False} requires = "testlib/1.2.3@qbs/testing" def configure(self): assert(not self.options.forceFailure) self.options["testlib"].opt = self.options.opt def source(self): pass def build(self): pass def package(self): pass qbs-src-3.3.1/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs0000644000175100017510000000124515232633614032156 0ustar runnerrunnerimport qbs.Probes import qbs.TextFile Project { readonly property bool forceFailure: false Probes.ConanfileProbe { id: conan conanfilePath: path + "/conanfile.py" options: ({opt: "True", forceFailure: (project.forceFailure ? "True" : "False")}) settings: ({os: "AIX"}) } property var check: { var tf = new TextFile(buildDirectory + "/results.json", TextFile.WriteOnly); var o = { json: conan.json.deps_env_info["ENV_VAR"], dependencies: conan.dependencies["testlib"].libs, generatedFilesPath: conan.generatedFilesPath }; tf.write(JSON.stringify(o)); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbsVersion/0000755000175100017510000000000015232633614022346 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/qbsVersion/qbs-version.qbs0000644000175100017510000000130315232633614025322 0ustar runnerrunnerProject { property string qbsVersion property int qbsVersionMajor property int qbsVersionMinor property int qbsVersionPatch Product { property bool dummy: { if (qbsVersion !== qbs.version || qbsVersionMajor !== qbs.versionMajor || qbsVersionMinor !== qbs.versionMinor || qbsVersionPatch !== qbs.versionPatch) throw("expected " + [qbsVersion, qbsVersionMajor, qbsVersionMinor, qbsVersionPatch].join(", ") + ", got " + [qbs.version, qbs.versionMajor, qbs.versionMinor, qbs.versionPatch].join(", ")); return false; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-type/0000755000175100017510000000000015232633614022470 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-type/plugin-type.qbs0000644000175100017510000000155715232633614025464 0ustar runnerrunnerProject { name: "plugin_type" property bool dummy: { const isWin = qbs.targetOS.includes("windows"); const isDarwin = qbs.targetOS.includes("darwin"); const isMac = qbs.targetOS.includes("macos"); const toolGcc = qbs.toolchain.includes("gcc") || qbs.toolchain.includes("emscripten"); console.info("is windows: " + (isWin ? "yes" : "no")); console.info("is darwin: " + (isDarwin ? "yes" : "no")); console.info("is macos: " + (isMac ? "yes" : "no")); console.info("is gcc: " + (toolGcc ? "yes" : "no")); } Plugin { Depends { name: "bundle" } Depends { name: "cpp" } name: "myplugin" files: ["plugin-type.cpp"] qbs.installPrefix: "" installDir: config.install.pluginsDirectory // enforce install static plugins bundle.isBundle: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-type/plugin-type.cpp0000644000175100017510000000010615232633614025446 0ustar runnerrunner#include "../dllexport.h" extern "C" DLL_EXPORT void pluginFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/deprecated-property/0000755000175100017510000000000015232633614024175 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/deprecated-property/modules/0000755000175100017510000000000015232633614025645 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/0000755000175100017510000000000015232633614027633 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs0000644000175100017510000000120615232633614030575 0ustar runnerrunnerimport qbs.Environment Module { property bool newProp property bool expiringProp property bool forgottenProp PropertyOptions { name: "newProp" description: "Use this, it's good!" } PropertyOptions { name: "expiringProp" description: "Use newProp instead." removalVersion: Environment.getEnv("REMOVAL_VERSION") } PropertyOptions { name: "veryOldProp" description: "Use newProp instead." removalVersion: "1.3" } PropertyOptions { name: "forgottenProp" description: "Use newProp instead." removalVersion: "1.8" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs0000644000175100017510000000021515232633614030664 0ustar runnerrunnerProduct { Depends { name: "themodule" } themodule.newProp: true themodule.expiringProp: false themodule.veryOldProp: false } qbs-src-3.3.1/tests/auto/blackbox/testdata/QTBUG-51237/0000755000175100017510000000000015232633614021554 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/0000755000175100017510000000000015232633614023224 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/mymodule/0000755000175100017510000000000015232633614025057 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/mymodule/mymodule.qbs0000644000175100017510000000016315232633614027421 0ustar runnerrunnerModule { property stringList theProperty: [] //property stringList otherProperty: theProperty.concat([]) } qbs-src-3.3.1/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs0000644000175100017510000000067715232633614024076 0ustar runnerrunnerProduct { type: "custom" Depends { name: "mymodule" } Rule { multiplex: true outputFileTags: ["custom"] prepare: { var theProperty = product.mymodule.theProperty; if (!theProperty) throw "Oh no!"; var dummy = new JavaScriptCommand(); dummy.silent = true; dummy.sourceCode = function() {}; return [dummy]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-variant-defaults/0000755000175100017510000000000015232633614024561 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs0000644000175100017510000000114715232633614031641 0ustar runnerrunnerCppApplication { property bool validate: { var valid = true; if (qbs.buildVariant === "release") { valid = !qbs.enableDebugCode && !qbs.debugInformation && qbs.optimization === "fast"; } else if (qbs.buildVariant === "debug") { valid = qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "none"; } else if (qbs.buildVariant === "profiling") { valid = !qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "fast"; } if (!valid) throw "Invalid defaults"; return valid; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp0000644000175100017510000000003115232633614026203 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/0000755000175100017510000000000015232633614023214 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/modules/0000755000175100017510000000000015232633614024664 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/0000755000175100017510000000000015232633614026531 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs0000644000175100017510000000203515232633614031105 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Module { property bool enableGroup property bool enableRule property bool enableTagger Group { condition: enableGroup FileTagger { condition: module.enableTagger patterns: "*.narf" fileTags: ["narf"] } Rule { condition: module.enableRule inputs: ["narf"] outputFileTags: ["zort"] outputArtifacts: [{ filePath: product.name + "." + input.fileName + ".zort", fileTags: ["zort"] }] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("NARF! ZORT!"); f.close(); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/foo.narf0000644000175100017510000000000015232633614024635 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/ruleConditions.qbs0000644000175100017510000000043315232633614026724 0ustar runnerrunnerProduct { type: ["application", "zort"] consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "cpp" } Depends { name: "narfzort" } files: [ "main.cpp", "foo.narf" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/ruleConditions/main.cpp0000644000175100017510000000236415232633614024651 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/0000755000175100017510000000000015232633614026723 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp0000644000175100017510000000235115232633614030351 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/non-broken-files-in-broken-product.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/non-broken-files-in-br0000644000175100017510000000012615232633614033022 0ustar runnerrunnerCppApplication { consoleApplication: true files: ["fine.cpp", "broken.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp0000644000175100017510000000000715232633614030704 0ustar runnerrunnerbroken qbs-src-3.3.1/tests/auto/blackbox/testdata/toplevel-searchpath/0000755000175100017510000000000015232633614024165 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/0000755000175100017510000000000015232633614026762 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/imports/0000755000175100017510000000000015232633614030457 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/imports/MyProduct.qbs0000644000175100017510000000001415232633614033107 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/blackbox/testdata/toplevel-searchpath/toplevel-searchpath.qbs0000644000175100017510000000001615232633614030643 0ustar runnerrunnerMyProduct { } qbs-src-3.3.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/0000755000175100017510000000000015232633614026517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/lib.cpp0000644000175100017510000000001415232633614027764 0ustar runnerrunnervoid l() {} ././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-mult0000644000175100017510000000054515232633614033212 0ustar runnerrunnerStaticLibrary { name: "l" Depends { condition: qbs.targetOS.includes("darwin"); name: "bundle" } Properties { condition: qbs.targetOS.includes("darwin"); bundle.isBundle: false } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] Depends { name: "cpp" } files: ["lib.cpp"] install: false } qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/0000755000175100017510000000000015232633614023344 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy2/0000755000175100017510000000000015232633614024561 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy2/dummy2.pc0000644000175100017510000000014615232633614026323 0ustar runnerrunnerName: dummy2 Description: dummy2 package Version: 0.0.2 Requires: Libs: -Ldummydir2 -ldummy2 Cflags: qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/0000755000175100017510000000000015232633614025014 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/0000755000175100017510000000000015232633614027002 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs0000644000175100017510000000202115232633614031472 0ustar runnerrunnerimport qbs.Probes Module { property string packageName property string libDir Probes.PkgConfigProbe { id: theProbe name: packageName libDirs: [libDir] } property bool probeSuccess: theProbe.found property stringList libs: theProbe.libs property stringList cFlags: theProbe.cflags property string packageVersion: theProbe.modversion Rule { multiplex: true outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.name + " found: " + product.themodule.probeSuccess); console.info(product.name + " libs: " + JSON.stringify(product.themodule.libs)); console.info(product.name + " cflags: " + JSON.stringify(product.themodule.cFlags)); console.info(product.name + " version: " + product.themodule.packageVersion); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy1/0000755000175100017510000000000015232633614024560 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy1/dummy1.pc0000644000175100017510000000014615232633614026321 0ustar runnerrunnerName: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -Ldummydir1 -ldummy1 Cflags: qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe/pkg-config.qbs0000644000175100017510000000074415232633614026104 0ustar runnerrunnerProject { property string packageBaseName Product { name: "theProduct1" type: ["theType"] Depends { name: "themodule" } themodule.packageName: project.packageBaseName + "1" themodule.libDir: path + "/dummy1" } Product { name: "theProduct2" type: ["theType"] Depends { name: "themodule" } themodule.packageName: project.packageBaseName + "2" themodule.libDir: path + "/dummy2" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/moved-file-dependency/0000755000175100017510000000000015232633614024356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/moved-file-dependency/main.cpp0000644000175100017510000000004715232633614026007 0ustar runnerrunner#include int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/moved-file-dependency/subdir1/0000755000175100017510000000000015232633614025727 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/moved-file-dependency/subdir1/theheader.h0000644000175100017510000000000015232633614030017 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/moved-file-dependency/moved-file-dependency.qbs0000644000175100017510000000013015232633614031222 0ustar runnerrunnerCppApplication { cpp.includePaths: ["subdir1", "subdir2"] files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/0000755000175100017510000000000015232633614024517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/lib3.cpp0000644000175100017510000000007215232633614026053 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib3Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs0000644000175100017510000000742715232633614031544 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { DynamicLibrary { // Product dependency, installed name: "lib1" Depends { name: "cpp" } property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: ["lib1.cpp"] install: !qbs.targetOS.includes("darwin") installImportLib: true installDir: "lib1" importLibInstallDir: installDir Group { condition: qbs.targetOS.includes("darwin") fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installSourceBase: destinationDirectory } } DynamicLibrary { // Product dependency, non-installed name: "lib2" Depends { name: "cpp" } Depends { name: "lib5" } install: false Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib2.cpp"] } DynamicLibrary { // Non-dependency, referred to by full path name: "lib3" Depends { name: "cpp" } files: ["lib3.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } installImportLib: true installDir: "lib3" importLibInstallDir: installDir } DynamicLibrary { // Non-dependency, referred to by name name: "lib4" Depends { name: "cpp" } files: ["lib4.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } // Testing shows that clang (8.0) does not find dynamic libraries via // the -L
and -l mechanism unless the name is "lib.a". Properties { condition: Host.os().includes("windows") && qbs.toolchain.includes("clang") cpp.dynamicLibraryPrefix: "lib" cpp.dynamicLibraryImportSuffix: ".a" } installImportLib: true installDir: "lib4" importLibInstallDir: installDir } DynamicLibrary { // Recursive product dependency name: "lib5" Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib5.cpp"] } CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "app" consoleApplication: true files: "main.cpp" install: false Depends { name: "lib1" } Depends { name: "lib2" } Depends { name: "lib3"; cpp.link: false } Depends { name: "lib4"; cpp.link: false } property string fullInstallPrefix: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) property string lib3FilePath: FileInfo.joinPaths(fullInstallPrefix, "lib3", cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.includes("windows") ? cpp.dynamicLibraryImportSuffix : cpp.dynamicLibrarySuffix)) cpp.dynamicLibraries: [lib3FilePath, "lib4"] cpp.libraryPaths: FileInfo.joinPaths(fullInstallPrefix, "lib4") } Probe { id: osPrinter property bool isWindows: qbs.targetOS.includes("windows") configure: { console.info("is windows"); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/lib2.cpp0000644000175100017510000000014615232633614026054 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void lib5Func(); DLL_EXPORT void lib2Func() { lib5Func(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/lib5.cpp0000644000175100017510000000007215232633614026055 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib5Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/main.cpp0000644000175100017510000000035115232633614026146 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void lib1Func(); DLL_IMPORT void lib2Func(); DLL_IMPORT void lib3Func(); DLL_IMPORT void lib4Func(); int main() { lib1Func(); lib2Func(); lib3Func(); lib4Func(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/lib1.cpp0000644000175100017510000000007215232633614026051 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib1Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/setup-run-environment/lib4.cpp0000644000175100017510000000007215232633614026054 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT void lib4Func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-variant/0000755000175100017510000000000015232633614023141 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linker-variant/main.cpp0000644000175100017510000000001615232633614024566 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs0000644000175100017510000000064115232633614026577 0ustar runnerrunnerCppApplication { name: "p" property string linkerVariant Probe { id: gccProbe property bool isGcc: qbs.toolchain.includes("gcc") configure: { console.info("is GCC: " + isGcc); if (isGcc) found = true; } } Properties { condition: gccProbe.found cpp.linkerVariant: linkerVariant } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/input-tags-change-tracking/0000755000175100017510000000000015232633614025331 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs0000644000175100017510000000354715232633614033167 0ustar runnerrunnerimport qbs.TextFile Product { name: "p" type: "p_tag" property string generateInput Group { condition: generateInput == "no" files: "input.txt" fileTags: ["txt", "empty"] } Rule { condition: generateInput == "static" multiplex: true Artifact { filePath: "input.txt"; fileTags: ["txt", "empty"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } Rule { condition: generateInput == "dynamic" multiplex: true outputFileTags: ["txt", "empty"] outputArtifacts: [{filePath: "input.txt", fileTags: ["txt", "empty"]}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } Rule { inputs: "txt" outputFileTags: "p_tag" outputArtifacts: { if (input.fileTags.includes("empty")) return []; return [{ filePath: input.fileTags.includes("y") ? "y.out" : "x.out", fileTags: "p_tag" }] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/input-tags-change-tracking/input.txt0000644000175100017510000000000615232633614027225 0ustar runnerrunnerempty qbs-src-3.3.1/tests/auto/blackbox/testdata/symlink-removal/0000755000175100017510000000000015232633614023344 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs0000644000175100017510000000057215232633614027210 0ustar runnerrunnerimport qbs.File Product { type: "removal" Rule { multiplex: true outputFileTags: "removal" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.remove(product.sourceDirectory + "/dir1"); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/0000755000175100017510000000000015232633614024560 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/modules/0000755000175100017510000000000015232633614026230 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/0000755000175100017510000000000015232633614030027 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/outdated.qbs0000644000175100017510000000005615232633614032350 0ustar runnerrunnerModule { priority: 100 version: "1" } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/ritchie.qbs0000644000175100017510000000052415232633614032166 0ustar runnerrunnerModule { condition: qbs.targetOS.containsAny(["Deep Purple", "Rainbow"]) priority: 1 // Overrides the more general "lord.qbs" instance, // which also matches on "Deep Purple". version: "2" Depends { name: "texttemplate" } texttemplate.dict: ({DID: "slipped", THING: "litchi", IDOL: "ritchie"}) } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/lord.qbs0000644000175100017510000000031615232633614031476 0ustar runnerrunnerModule { condition: qbs.targetOS.containsAny(["Deep Purple", "Whitesnake"]) version: "3" Depends { name: "texttemplate" } texttemplate.dict: ({DID: "chewed", THING: "cord", IDOL: "lord"}) } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/0000755000175100017510000000000015232633614030021 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/0000755000175100017510000000000015232633614031471 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/0000755000175100017510000000000015232633614033270 5ustar runnerrunner././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/0000644000175100017510000000007415232633614033273 0ustar runnerrunnerModule { condition: !qbs.targetOS.includes("Beatles") } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/choose-module-instance.qbs0000644000175100017510000000062415232633614031636 0ustar runnerrunnerimport qbs.FileInfo Project { qbsSearchPaths: [ ".", path, "modules/..", FileInfo.path(FileInfo.joinPaths(path, "modules")), "other-searchpath" ] Product { Depends { name: "limerick"; versionAtLeast: "2" } type: ["text"] files: ["gerbil.txt.in"] Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in0000644000175100017510000000021715232633614027172 0ustar runnerrunnerI once had a gerbil named Bobby, Who had an unusual hobby. He ${DID} on a ${THING}, and now -- oh my ${IDOL}, now all that's left is a blobby. qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/0000755000175100017510000000000015232633614023625 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp0000644000175100017510000000016715232633614025716 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void plugin3_hello() { std::puts("plugin3 says hello!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp0000644000175100017510000000016715232633614025717 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void plugin4_hello() { std::puts("plugin4 says hello!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp0000644000175100017510000000016715232633614025676 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void helper2_hello() { std::puts("Hello from helper2!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs0000644000175100017510000000425515232633614027754 0ustar runnerrunnerimport qbs.Host Project { CppApplication { name: "myapp" files: ["main.cpp"] Depends { name: "plugin1" // not to be linked cpp.link: Host.os() === undefined } Depends { name: "plugin2" } // not to be linked Depends { name: "plugin3" // supposed to be linked property bool theCondition: true cpp.link: theCondition && product.name === "myapp" } Depends { name: "plugin4" } // supposed to be linked Depends { name: "helper1" } // supposed to be linked } DynamicLibrary { name: "plugin1" install: false files: ["plugin1.cpp"] Depends { name: "cpp" } } DynamicLibrary { name: "plugin2" install: false files: ["plugin2.cpp"] Depends { name: "cpp" } Export { Parameters { cpp.link: false // marker 1 } } } DynamicLibrary { name: "plugin3" install: false files: ["plugin3.cpp"] Depends { name: "cpp" } Export { Parameters { cpp.link: false } } } DynamicLibrary { name: "plugin4" install: false files: ["plugin4.cpp"] Depends { name: "cpp" } Export { Parameters { // property bool theCondition: true cpp.link: true // theCondition TODO: Make this work } } } DynamicLibrary { name: "helper1" install: false files: ["helper1.cpp"] Depends { name: "cpp" } Depends { name: "helper2"; cpp.link: false /* marker 2 */ } Export { Depends { name: "cpp" } Depends { name: "helper2"; cpp.link: false } } } DynamicLibrary { name: "helper2" install: false files: ["helper2.cpp"] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.defines: ["USING_HELPER2"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp0000644000175100017510000000016715232633614025715 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void plugin2_hello() { std::puts("plugin2 says hello!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/main.cpp0000644000175100017510000000033315232633614025254 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT void plugin3_hello(); DLL_IMPORT void plugin4_hello(); DLL_IMPORT void helper1_hello(); int main() { plugin3_hello(); plugin4_hello(); helper1_hello(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp0000644000175100017510000000016715232633614025714 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void plugin1_hello() { std::puts("plugin1 says hello!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp0000644000175100017510000000041115232633614025665 0ustar runnerrunner#include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) #else # define EXPORT #endif #ifndef USING_HELPER2 #error define USING_HELPER2 missing #endif EXPORT void helper1_hello() { std::puts("helper1 says hello!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/symbolLinkMode/0000755000175100017510000000000015232633614023143 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs0000644000175100017510000000677715232633614026623 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { property bool shouldInstallLibrary: true property bool lazy: false Application { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "cpp" } Depends { name: "functions"; cpp.symbolLinkMode: product.symbolLinkMode cpp.link: !(product.qbs.targetOS.includes("linux") && product.symbolLinkMode === "weak") } property string symbolLinkMode: project.lazy ? "lazy" : "weak" name: "driver" files: ["main.cpp"] consoleApplication: true installDir: "bin" property string installLib: "SHOULD_INSTALL_LIB=" + project.shouldInstallLibrary cpp.defines: { if (symbolLinkMode === "weak") { return qbs.targetOS.includes("darwin") ? ["WEAK_IMPORT=__attribute__((weak_import))", installLib] : ["WEAK_IMPORT=__attribute__((weak))", installLib]; } return ["WEAK_IMPORT=", installLib]; } cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" cpp.rpaths: [cpp.rpathOrigin + "/../lib"] } DynamicLibrary { Depends { name: "cpp" } Depends { name: "indirect"; cpp.symbolLinkMode: "reexport" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "functions" files: ["lib.cpp"] install: project.shouldInstallLibrary installDir: "lib" cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" cpp.rpaths: [cpp.rpathOrigin] Properties { condition: qbs.targetOS.includes("darwin") cpp.sonamePrefix: "@rpath" } Export { // let the autotest pass on Linux where reexport is not supported Depends { name: "indirect"; condition: !qbs.targetOS.includes("darwin") } // on Linux, there is no LC_WEAK_LOAD_DYLIB equivalent (the library is simply omitted // from the list of load commands entirely), so use LD_PRELOAD to emulate qbs.commonRunEnvironment: { var env = original || {}; if (project.shouldInstallLibrary) { env["LD_PRELOAD"] = FileInfo.joinPaths(qbs.installRoot, "lib", "libfunctions.so"); } return env; } } } DynamicLibrary { Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "indirect" installDir: "lib" files: ["indirect.cpp"] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" Properties { condition: qbs.targetOS.includes("darwin") // reexport is incompatible with rpath, // "ERROR: ld: file not found: @rpath/libindirect.dylib for architecture x86_64" cpp.sonamePrefix: qbs.installRoot + "/lib" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp0000644000175100017510000000022315232633614024412 0ustar runnerrunnerint somefunction() { return 42; } #include static const auto func = []() { std::printf("Lib was loaded!\n"); return 0; }(); qbs-src-3.3.1/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp0000644000175100017510000000055315232633614024576 0ustar runnerrunnerextern WEAK_IMPORT int somefunction(); extern void indirect(); #include int main() { std::printf("meow\n"); if (&somefunction != nullptr) std::printf("somefunction existed and it returned %d\n", somefunction()); else std::printf("somefunction did not exist\n"); #if SHOULD_INSTALL_LIB indirect(); #endif return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/symbolLinkMode/indirect.cpp0000644000175100017510000000002415232633614025444 0ustar runnerrunnervoid indirect() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/0000755000175100017510000000000015232633614025771 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/test.cpp.in0000644000175100017510000000001515232633614030055 0ustar runnerrunnervoid f() { } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/artifacts-map-change-tracking.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/artifacts-map-change-tracki0000644000175100017510000000525215232633614033151 0ustar runnerrunnerimport qbs.File Project { CppApplication { name: "TheApp" targetName: "TheBinary" Rule { inputs: "cpp.in" Artifact { filePath: "test.cpp"; fileTags: 'cpp' } prepare: { console.info("running rule for " + output.fileName); var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } files: ["main.cpp", /* 'test.txt' */] Group { files: "test.cpp.in" fileTags: "cpp.in" } } Product { name: "meta" type: "custom" Depends { name: "TheApp" } Group { files: "dummy.in" fileTags: "dummy.in" } Rule { inputs: ["dummy.in"] Artifact { filePath: "dummy"; fileTags: 'custom' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "printing artifacts"; cmd.sourceCode = function() { var dep; for (var i = 0; i < product.dependencies.length; ++i) { var d = product.dependencies[i]; if (d.name === "TheApp") { dep = d; break; } } for (var p in dep.artifacts) { var list = dep.artifacts[p]; for (var i = 0; i < list.length; ++i) console.info(list[i].fileName); } File.copy(input.filePath, output.filePath); }; return cmd; } } } Product { name: "p" type: "p_type" Rule { multiplex: true Artifact { filePath: "dummy1"; fileTags: "d_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var blubb = product.artifacts.qbs; }; return cmd; } } Rule { inputs: "d_type" Artifact { filePath: "dummy2"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/main.cpp0000644000175100017510000000003715232633614027421 0ustar runnerrunnervoid f(); int main() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/test.txt0000644000175100017510000000000015232633614027477 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/dummy.in0000644000175100017510000000000015232633614027442 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/generate-linker-map-file/0000755000175100017510000000000015232633614024757 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs0000644000175100017510000000153615232633614032237 0ustar runnerrunnerProject { CppApplication { name: "app-map" files: ["main.cpp"] // lld-link has different flag for map files, test it by switching to "lld" linkerVariant Properties { condition: qbs.toolchain.includes("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: true } CppApplication { name: "app-nomap" files: ["main.cpp"] Properties { condition: qbs.toolchain.includes("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: false } CppApplication { name: "app-nomap-default" files: ["main.cpp"] } Probe { id: toolchainProbe property bool isUsed: qbs.toolchain.includes("msvc") || qbs.toolchain.includes("gcc") configure: { console.info("use test: " + isUsed); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/generate-linker-map-file/main.cpp0000644000175100017510000000241215232633614026406 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/0000755000175100017510000000000015232633614023156 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/object-lib-deps.qbs0000644000175100017510000000636315232633614026640 0ustar runnerrunnerProject { property bool useExport: true ObjectLibrary { name: "consumed" Depends { name: "cpp" } files: "consumed.cpp" } StaticLibrary { name: "consumer" Depends { name: "cpp" } Depends { name: "consumed" } files: "consumer.cpp" } ObjectLibrary { name: "a" Depends { name: "cpp" } files: ["a1.cpp", "a2.cpp"] } ObjectLibrary { name: "b" Depends { name: "cpp" } Depends { name: "a" } files: "b.cpp" } ObjectLibrary { name: "c" Depends { name: "cpp" } Depends { name: "a" } files: "c.cpp" } ObjectLibrary { name: "r" Depends { name: "cpp" } Depends { name: "b" } Depends { name: "c" } files: "d.cpp" Group { condition: qbs.targetOS.includes("darwin") files: ["d.mm"] } Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["WITH_SETUPAPI"] cpp.staticLibraries: !project.useExport ? ["setupapi"] : [] } Properties { condition: qbs.targetOS.includes("darwin") cpp.defines: ["WITH_ZLIB"] cpp.staticLibraries: !project.useExport ? ["z"] : [] cpp.frameworks: !project.useExport ? ["Foundation"] : [] } Properties { condition: { console.info(qbs.targetOS); return qbs.targetOS.includes("linux") || qbs.targetOS.includes("hurd") } cpp.defines: ["WITH_PTHREAD", "WITH_ZLIB"] cpp.staticLibraries: !project.useExport ? ["pthread", "z"] : [] } Properties { condition: qbs.toolchain.contains("emscripten") cpp.defines: ["WITH_WEBSOCK"] cpp.staticLibraries: !project.useExport ? ["websocket.js"] : [] } Export { condition : project.useExport Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("linux") || qbs.targetOS.includes("hurd") cpp.staticLibraries: ["pthread", "z"] } Properties { condition: qbs.targetOS.contains("darwin") cpp.staticLibraries: ["z"] cpp.frameworks: ["Foundation"] } Properties { condition: qbs.targetOS.contains("windows") cpp.staticLibraries: ["setupapi"] } Properties { condition: qbs.toolchain.contains("emscripten") cpp.staticLibraries: ["websocket.js"] } } } ObjectLibrary { name: "e" Depends { name: "cpp" } Depends { name: "r" } files: "e.cpp" Export { Depends { name: "r" } } } CppApplication { name: "objectLibDeps" type: "application" consoleApplication: true Depends { name: "e" } Depends { name: "consumer" } Properties { condition: qbs.targetOS.includes("linux") || qbs.targetOS.includes("hurd") cpp.driverFlags: ["-static"] } files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/e.cpp0000644000175100017510000000004615232633614024106 0ustar runnerrunnerint d(); int e() { return d(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/a1.cpp0000644000175100017510000000010715232633614024161 0ustar runnerrunner#include void a1() { std::cout << "a1" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/consumer.cpp0000644000175100017510000000016515232633614025517 0ustar runnerrunner#include void consumed(); void consumer() { consumed(); std::cout << "consumer" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/a2.cpp0000644000175100017510000000010715232633614024162 0ustar runnerrunner#include void a2() { std::cout << "a2" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/b.cpp0000644000175100017510000000004315232633614024100 0ustar runnerrunnervoid a1(); void b() { a1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/d.mm0000644000175100017510000000027515232633614023740 0ustar runnerrunner#import void printGreeting() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSLog (@"Hello darkness, my old friend!"); [pool drain]; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/consumed.cpp0000644000175100017510000000012315232633614025473 0ustar runnerrunner#include void consumed() { std::cout << "consumed" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/main.cpp0000644000175100017510000000011215232633614024600 0ustar runnerrunnerint e(); void consumer(); int main() { consumer(); return e(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/d.cpp0000644000175100017510000000155615232633614024114 0ustar runnerrunner#if defined(WITH_ZLIB) #include #endif #if defined(WITH_WEBSOCK) #include #endif #ifdef WITH_PTHREAD #include #elif defined(WITH_SETUPAPI) #include #include #endif void b(); void c(); int d() { b(); c(); int result = 0; #if defined(WITH_ZLIB) const char source[] = "Hello, world"; uLongf buffer_size = compressBound(sizeof(source)); result += static_cast(buffer_size); #endif #if defined(WITH_WEBSOCK) const bool supported = emscripten_websocket_is_supported(); (void) supported; #endif #ifdef WITH_PTHREAD pthread_t self = pthread_self(); result += static_cast(self); #elif defined(WITH_SETUPAPI) CABINET_INFO ci; ci.SetId = 0; SetupIterateCabinet(L"invalid-file-path", 0, NULL, NULL); result += ci.SetId; #endif return result; } qbs-src-3.3.1/tests/auto/blackbox/testdata/object-lib-deps/c.cpp0000644000175100017510000000004315232633614024101 0ustar runnerrunnervoid a2(); void c() { a2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/0000755000175100017510000000000015232633614024172 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/modules/0000755000175100017510000000000015232633614025642 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/modules/leaf/0000755000175100017510000000000015232633614026551 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs0000644000175100017510000000101715232633614030166 0ustar runnerrunnerModule { property string scalarProp: "leaf" property stringList listProp: ["leaf"] Rule { inputs: ["rule-input"] outputFileTags: "rule-output" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("scalar prop: " + product.leaf.scalarProp); console.info("list prop: " + JSON.stringify(product.leaf.listProp)); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/0000755000175100017510000000000015232633614027264 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/nonleaf.qbs0000644000175100017510000000015515232633614031416 0ustar runnerrunnerModule { Depends { name: "leaf" } // leaf.scalarProp: "nonleaf" // leaf.listProp: ["nonleaf"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/property-precedence.qbs0000644000175100017510000000060415232633614030660 0ustar runnerrunnerProject { references: ["dep.qbs"] Product { name: "toplevel" type: ["rule-output"] Depends { name: "leaf" } Depends { name: "nonleaf" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["rule-input"] } // leaf.scalarProp: "product" // leaf.listProp: ["product"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/dummy.txt0000644000175100017510000000000015232633614026054 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-precedence/dep.qbs0000644000175100017510000000027615232633614025456 0ustar runnerrunnerProduct { name: "dep" Export { Depends { name: "leaf" } Depends { name: "nonleaf" } // leaf.scalarProp: "export" // leaf.listProp: ["export"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/env-merging/0000755000175100017510000000000015232633614022431 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/env-merging/main.c0000644000175100017510000000015415232633614023521 0ustar runnerrunner#include #include int main() { printf("PATH=%s", getenv("PATH")); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/env-merging/env-merging.qbs0000644000175100017510000000173115232633614025360 0ustar runnerrunnerimport qbs.Host Project { CppApplication { name: "tool" files: "main.c" } Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "p" type: "custom" Depends { name: "tool" } Rule { inputsFromDependencies: "application" outputFileTags: "custom" prepare: { var cmd = new Command(input.filePath, []); cmd.description = "running tool"; cmd.environment = ["PATH=/opt/tool/bin"]; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/0000755000175100017510000000000015232633614024010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/header2.h0000644000175100017510000000240615232633614025475 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once void printPersonalGreeting(); qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/header1.h0000644000175100017510000000250415232633614025473 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #include inline void printGreeting() { std::cout << "Tach." << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/pch.h0000644000175100017510000000236015232633614024734 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "header1.h" qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/pch-change-tracking.qbs0000644000175100017510000000031015232633614030306 0ustar runnerrunnerCppApplication { files: [ "header1.h", "header2.cpp", "header2.h", "main.cpp", ] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/main.cpp0000644000175100017510000000250315232633614025440 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "header2.h" #include "pch.h" int main() { printGreeting(); printPersonalGreeting(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/pch-change-tracking/header2.cpp0000644000175100017510000000025715232633614026032 0ustar runnerrunner#include "header2.h" // header1 is forced-included via pch. void printPersonalGreeting() { printGreeting(); std::cout << "Was geht, Rumpelstilzchen?" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/vcs/0000755000175100017510000000000015232633614021006 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/vcs/main.cpp0000644000175100017510000000053415232633614022440 0ustar runnerrunner#include #include int main() { std::cout << "==" << "repoState=" << VCS_REPO_STATE << ";" << "latestTag=" << VCS_REPO_LATEST_TAG << ";" << "commitsSinceTag=" << VCS_REPO_COMMITS_SINCE_TAG << ";" << "commitSha=" << VCS_REPO_COMMIT_SHA << "==" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/vcs/vcstest.qbs0000644000175100017510000000103615232633614023210 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "vcs" } vcs.headerFileName: "my-repo-state.h" files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/0000755000175100017510000000000015232633614030511 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/input.txt0000644000175100017510000000001015232633614032400 0ustar runnerrunnerold.txt qbs-src-3.3.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/p.qbs0000644000175100017510000000300515232633614031455 0ustar runnerrunnerimport qbs.File import qbs.TextFile Product { type: ["mytype.final"] Group { files: ["input.txt"] fileTags: ["mytype.in"] } Rule { inputs: ["mytype.in"] Artifact { filePath: "output.txt" fileTags: ["mytype.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } Rule { inputs: ["mytype.out"] outputFileTags: ["mytype.final", "dummy"] outputArtifacts: { var file; var inFile = new TextFile(input.filePath, TextFile.ReadOnly); try { file = inFile.readLine(); if (!file) throw "no file name found"; } finally { inFile.close(); } return [ { filePath: file, fileTags: ["mytype.final"] }, { filePath: "dummy", fileTags: ["dummy"], alwaysUpdated: false } ]; } prepare: { var cmd = new JavaScriptCommand(); var output = outputs["mytype.final"][0]; cmd.description = "generating " + output.fileName; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, outputFilePath); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-root-from-project-file/0000755000175100017510000000000015232633614026164 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/install-root-from-project-file/install-root-from-project-file.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/install-root-from-project-file/install-root-from-project-0000644000175100017510000000036715232633614033226 0ustar runnerrunnerProduct { name: "p" property string installRoot qbs.installRoot: installRoot Group { qbs.install: true qbs.installPrefix: "/install-prefix" qbs.installDir: "/install-dir" files: ["file.txt"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-root-from-project-file/file.txt0000644000175100017510000000000015232633614027632 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/0000755000175100017510000000000015232633614023515 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs0000644000175100017510000000072215232633614030011 0ustar runnerrunnerimport qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var dummy = File.directoryEntries(product.sourceDirectory, File.Files); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-eval.qbs0000644000175100017510000000013515232633614027320 0ustar runnerrunnerimport qbs.File Product { name: File.directoryEntries(sourceDirectory, File.Files)[0] } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs0000644000175100017510000000065615232633614026641 0ustar runnerrunnerimport qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { File.copy(input.filePath, output.filePath); var cmd = new JavaScriptCommand(); cmd.description = "no-op"; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/copy-eval.qbs0000644000175100017510000000026415232633614026125 0ustar runnerrunnerimport qbs.File Product { name: { File.copy(sourceDirectory + "/copy-eval.qbs", sourceDirectory + "/copy-eval2.qbs"); return "blubb" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs0000644000175100017510000000063215232633614026613 0ustar runnerrunnerimport qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-probe.qbs0000644000175100017510000000043715232633614027505 0ustar runnerrunnerimport qbs.File Product { Probe { id: theProbe property string baseDir: project.sourceDirectory property stringList subDirs configure: { subDirs = File.directoryEntries(baseDir, File.AllDirs); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/copy-probe.qbs0000644000175100017510000000040515232633614026302 0ustar runnerrunnerimport qbs.File Product { Probe { id: theProbe property string baseDir: project.sourceDirectory configure: { File.copy(baseDir + "/copy-probe.qbs", baseDir + "/copy-probe2.qbs"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/test.txt0000644000175100017510000000000015232633614025223 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs0000644000175100017510000000070215232633614030027 0ustar runnerrunnerimport qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var dummy = File.directoryEntries(product.sourceDirectory, File.Files); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/run-multiplexed/0000755000175100017510000000000015232633614023351 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs0000644000175100017510000000142415232633614027217 0ustar runnerrunnerimport qbs.Host CppApplication { aggregate: false consoleApplication: true name: "app" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] files: "main.cpp" Probe { id: checker property string targetPlatform: qbs.targetPlatform property string targetArchitecture: qbs.architecture configure: { var result = targetPlatform === Host.platform() && targetArchitecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + targetPlatform + "/" + targetArchitecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/run-multiplexed/main.cpp0000644000175100017510000000001615232633614024776 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/msvc-asm-flags/0000755000175100017510000000000015232633614023033 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm0000644000175100017510000000007715232633614026361 0ustar runnerrunnerinclude header.inc .code main proc mov ecx, 16 main endp endqbs-src-3.3.1/tests/auto/blackbox/testdata/msvc-asm-flags/include/0000755000175100017510000000000015232633614024456 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc0000644000175100017510000000000015232633614026367 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs0000644000175100017510000000037615232633614026370 0ustar runnerrunnerStaticLibrary { condition: qbs.toolchain.includes("msvc") && !qbs.architecture.contains("arm64") && !qbs.architecture.contains("armv7") Depends { name: "cpp" } files: "msvc-asm-flags.asm" cpp.assemblerFlags: ["/I", "include"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/0000755000175100017510000000000015232633614023507 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/modules/0000755000175100017510000000000015232633614025157 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/0000755000175100017510000000000015232633614027145 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/m.qbs0000644000175100017510000000011115232633614030101 0ustar runnerrunnerimport "utils.js" as Utils Module { validate: { Utils.helper(); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/utils.js0000644000175100017510000000005615232633614030644 0ustar runnerrunnerfunction helper() { console.info("helper"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/imports-conflict/imports-conflict.qbs0000644000175100017510000000022215232633614027506 0ustar runnerrunnerProject { Product { name: "Utils" } Product { Depends { name: "Utils" } Depends { name: "themodule" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/0000755000175100017510000000000015232633614022463 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/0000755000175100017510000000000015232633614024331 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/hello.cpp0000644000175100017510000000015115232633614026135 0ustar runnerrunnermodule; #include module helloworld; void helloImpl() { std::cout << "Hello world!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/declaration-implementation.qbs0000644000175100017510000000137115232633614032352 0ustar runnerrunner// Checks that module can be split into a declaration module and good old cpp implementation file CppApplication { name: "decl-impl" condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "hello.cppm", "hello.cpp", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/CMakeLists.txt0000644000175100017510000000103115232633614027064 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(declaration_implementation VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(declaration_implementation) target_sources(declaration_implementation PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES hello.cppm ) target_sources(declaration_implementation PRIVATE hello.cpp main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(declaration_implementation PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/hello.cppm0000644000175100017510000000013115232633614026310 0ustar runnerrunnerexport module helloworld; export void helloImpl(); export void hello() { helloImpl(); }qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/decl-impl/main.cpp0000644000175100017510000000006015232633614025755 0ustar runnerrunnerimport helloworld; int main() { hello(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/0000755000175100017510000000000015232633614024006 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/CMakeLists.txt0000644000175100017510000000122215232633614026543 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(library_module VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_library(library_module_lib SHARED) target_sources(library_module_lib PUBLIC FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES lib/hello.cppm ) add_executable(library_module_app) target_sources(library_module_app PRIVATE app/main.cpp ) target_link_libraries(library_module_app library_module_lib) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(library_module_lib PRIVATE "-fmodules-ts") target_compile_options(library_module_app PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/lib/0000755000175100017510000000000015232633614024554 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/lib/dllexport.h0000644000175100017510000000324415232633614026745 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DLLEXPORT_H #define DLLEXPORT_H #if defined(_WIN32) || defined(WIN32) #define DLL_EXPORT __declspec(dllexport) #define DLL_IMPORT __declspec(dllimport) #else #define DLL_EXPORT __attribute__((visibility("default"))) #define DLL_IMPORT __attribute__((visibility("default"))) #endif #ifdef LIB_STATIC #define LIB_EXPORT #else #ifdef LIB_DYNAMIC #define LIB_EXPORT DLL_EXPORT #else #define LIB_EXPORT DLL_IMPORT #endif #endif #endif // include guard qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/lib/hello.cppm0000644000175100017510000000022615232633614026540 0ustar runnerrunnermodule; #include "dllexport.h" #include export module helloworld; export LIB_EXPORT void hello() { std::cout << "Hello world!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/library-module.qbs0000644000175100017510000000303515232633614027445 0ustar runnerrunner// Checks module in a library Project { DynamicLibrary { condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) // TODO: investigate why MinGW 11 fails || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } name: "lib" Depends { name: "cpp" } files: [ "lib/hello.cppm", ] install: true cpp.defines: "LIB_DYNAMIC" cpp.rpaths: cpp.rpathOrigin cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } CppApplication { condition: qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16) consoleApplication: true name: "app" Depends { name: "lib" } files: [ "app/main.cpp" ] install: true cpp.rpaths: [cpp.rpathOrigin + "/../lib"] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/app/0000755000175100017510000000000015232633614024566 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/lib-mod/app/main.cpp0000644000175100017510000000006015232633614026212 0ustar runnerrunnerimport helloworld; int main() { hello(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/0000755000175100017510000000000015232633614024173 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/c.cppm0000644000175100017510000000007615232633614025301 0ustar runnerrunner export module c; import b; export void baz() { bar(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/CMakeLists.txt0000644000175100017510000000076215232633614026740 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(dependent_modules VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(dependent_modules) target_sources(dependent_modules PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.cppm b.cppm c.cppm ) target_sources(dependent_modules PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(dependent_modules PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/main.cpp0000644000175100017510000000004515232633614025622 0ustar runnerrunnerimport c; int main() { baz(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/b.cppm0000644000175100017510000000007615232633614025300 0ustar runnerrunner export module b; import a; export void bar() { foo(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/a.cppm0000644000175100017510000000015115232633614025271 0ustar runnerrunner module; #include export module a; export void foo() { std::cout << "Hello world!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dep-mods/dependent-modules.qbs0000644000175100017510000000131515232633614030316 0ustar runnerrunner// check the (private) dependency chain between modules CppApplication { name: "dep-mods" condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.cppm", "b.cppm", "c.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std/0000755000175100017510000000000015232633614024565 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std/main.cpp0000644000175100017510000000011215232633614026207 0ustar runnerrunnerimport std; int main() { std::cout << "Hello World!" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std/import-std.qbs0000644000175100017510000000167615232633614027410 0ustar runnerrunner// Checks simple case with a single module. Project { CppStd {} CppApplication { name: "import-std" Depends { name: "CppStd" } condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 15) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 18)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "main.cpp" ] cpp.cxxLanguageVersion: "c++23" cpp.forceUseCxxModules: true Properties { condition: qbs.toolchainType === "clang" cpp.cxxFlags: ["-Wno-reserved-module-identifier"] cpp.cxxStandardLibrary: "libc++" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/single-mod/0000755000175100017510000000000015232633614024521 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/single-mod/CMakeLists.txt0000644000175100017510000000071415232633614027263 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(single_module VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(single_module) target_sources(single_module PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES hello.cppm ) target_sources(single_module PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(single_module PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/single-mod/single-module.qbs0000644000175100017510000000125715232633614030001 0ustar runnerrunner// Checks simple case with a single module. CppApplication { name: "single-mod" condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "hello.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/single-mod/hello.cppm0000644000175100017510000000016415232633614026506 0ustar runnerrunnermodule; #include export module helloworld; export void hello() { std::cout << "Hello world!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/single-mod/main.cpp0000644000175100017510000000006015232633614026145 0ustar runnerrunnerimport helloworld; int main() { hello(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dot-in-name/0000755000175100017510000000000015232633614024573 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dot-in-name/CMakeLists.txt0000644000175100017510000000070515232633614027335 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(dot_in_name VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(dot_in_name) target_sources(dot_in_name PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.module.cppm ) target_sources(dot_in_name PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(dot_in_name PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dot-in-name/main.cpp0000644000175100017510000000005315232633614026221 0ustar runnerrunnerimport a.mod; int main() { hello(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dot-in-name/dot-in-name.qbs0000644000175100017510000000123415232633614027412 0ustar runnerrunner// Checks that module name can contain a dot CppApplication { condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.module.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/dot-in-name/a.module.cppm0000644000175100017510000000015615232633614027162 0ustar runnerrunnermodule; #include export module a.mod; export void hello() { std::cout << "Hello world!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/0000755000175100017510000000000015232633614025314 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/c.cppm0000644000175100017510000000017615232633614026423 0ustar runnerrunnermodule; #include export module c; export import b; export void baz() { std::cout << "hello c" << std::endl; }qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/CMakeLists.txt0000644000175100017510000000073615232633614030062 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(export_import VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(export_import) target_sources(export_import PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.cppm b.cppm c.cppm ) target_sources(export_import PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(export_import PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/main.cpp0000644000175100017510000000007315232633614026744 0ustar runnerrunnerimport c; int main() { baz(); bar(); foo(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/b.cppm0000644000175100017510000000017615232633614026422 0ustar runnerrunnermodule; #include export module b; export import a; export void bar() { std::cout << "hello b" << std::endl; }qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/a.cppm0000644000175100017510000000014515232633614026415 0ustar runnerrunner module; #include export module a; export void foo() { std::cout << "Hello a!\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/export-import/export-import.qbs0000644000175100017510000000140015232633614030647 0ustar runnerrunner// checks that module is re-exported. in this case, that module should be added to // module map in dependent files CppApplication { condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.cppm", "b.cppm", "c.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std-compat/0000755000175100017510000000000015232633614026046 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std-compat/main.cpp0000644000175100017510000000023015232633614027471 0ustar runnerrunnerimport std.compat; int main() { std::cout << "Hello from std.compat!" << std::endl; printf("Using printf from std.compat\n"); return 0; }qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/import-std-compat/import-std-compat.qbs0000644000175100017510000000174515232633614032147 0ustar runnerrunner// Checks simple case with a single module. Project { CppStd { useStdCompat: true } CppApplication { name: "import-std-compat" Depends { name: "CppStd" } condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 15) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 18)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "main.cpp" ] cpp.cxxLanguageVersion: "c++23" cpp.forceUseCxxModules: true Properties { condition: qbs.toolchainType === "clang" cpp.cxxFlags: ["-Wno-reserved-module-identifier"] cpp.cxxStandardLibrary: "libc++" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/0000755000175100017510000000000015232633614024677 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/CMakeLists.txt0000644000175100017510000000072115232633614027437 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(partitions VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(partitions) target_sources(partitions PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.cppm b.cppm b.p.cppm ) target_sources(partitions PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(partitions PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/main.cpp0000644000175100017510000000004515232633614026326 0ustar runnerrunnerimport b; int main() { baz(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/b.cppm0000644000175100017510000000021615232633614026000 0ustar runnerrunner module; #include export module b; export import :p; export void baz() { bar(); std::cout << "hello from module b\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/b.p.cppm0000644000175100017510000000020315232633614026232 0ustar runnerrunner module; #include export module b:p; import a; export void bar() { foo(); std::cout << "hello from b.p\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/a.cppm0000644000175100017510000000016015232633614025775 0ustar runnerrunner module; #include export module a; export void foo() { std::cout << "hello from module a\n"; } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/partitions-dependency-on-module.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-depmod/partitions-dependency-on-module.q0000644000175100017510000000134115232633614033265 0ustar runnerrunner// Checks that module partiton can depend on other modules CppApplication { name: "part-depmod" condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.cppm", "b.cppm", "b.p.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/0000755000175100017510000000000015232633614024200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/b.p1.cppm0000644000175100017510000000016315232633614025621 0ustar runnerrunner module; #include export module b:p1; export void b_p1() { std::cout << "hello from b.part1\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/CMakeLists.txt0000644000175100017510000000077415232633614026750 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(partitions VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(partitions) target_sources(partitions PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.p1.cppm a.p2.cppm a.cppm b.p1.cppm b.p2.cppm b.cppm ) target_sources(partitions PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(partitions PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/partitions-recursive.qbs0000644000175100017510000000145115232633614031111 0ustar runnerrunner// Checks two modules split into partitions, one depends on the other CppApplication { name: "part-rec" condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.cppm", "a.p1.cppm", "a.p2.cppm", "b.cppm", "b.p1.cppm", "b.p2.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/a.p2.cppm0000644000175100017510000000014515232633614025621 0ustar runnerrunner module; #include module a:p2; void a_p2() { std::cout << "hello from a.part2\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/main.cpp0000644000175100017510000000005715232633614025632 0ustar runnerrunnerimport b; int main() { b_p1(); b(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/b.cppm0000644000175100017510000000045515232633614025306 0ustar runnerrunner module; #include export module b; import :p2; // private partition export import :p1; // public partition import a; export void b() { b_p1(); b_p2(); std::cout << "hello from module b\n"; // these are also visible as they are public in module a a_p1(); a(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/a.cppm0000644000175100017510000000032015232633614025274 0ustar runnerrunner module; #include export module a; import :p2; // private partition export import :p1; // public partition export void a() { a_p1(); a_p2(); std::cout << "hello from module a\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/a.p1.cppm0000644000175100017510000000016315232633614025620 0ustar runnerrunner module; #include export module a:p1; export void a_p1() { std::cout << "hello from a.part1\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-rec/b.p2.cppm0000644000175100017510000000014515232633614025622 0ustar runnerrunner module; #include module b:p2; void b_p2() { std::cout << "hello from b.part2\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/0000755000175100017510000000000015232633614024657 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/partitions.qbs0000644000175100017510000000127115232633614027563 0ustar runnerrunner// Checks module split into partitions CppApplication { condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: [ "a.cppm", "a.p1.cppm", "a.p2.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/CMakeLists.txt0000644000175100017510000000072515232633614027423 0ustar runnerrunnercmake_minimum_required(VERSION 3.29) project(partitions VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) add_executable(partitions) target_sources(partitions PRIVATE FILE_SET all_my_modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES a.p1.cppm a.p2.cppm a.cppm ) target_sources(partitions PRIVATE main.cpp ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(partitions PRIVATE "-fmodules-ts") endif() qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/a.p2.cppm0000644000175100017510000000014015232633614026273 0ustar runnerrunner module; #include module a:p2; void bar() { std::cout << "bar from part2\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/main.cpp0000644000175100017510000000006015232633614026303 0ustar runnerrunnerimport a; int main() { foo(); baz(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/a.cppm0000644000175100017510000000031415232633614025756 0ustar runnerrunner module; #include export module a; import :p2; // private partition export import :p1; // public partition export void baz() { foo(); bar(); std::cout << "baz from module\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/partitions/a.p1.cppm0000644000175100017510000000015615232633614026301 0ustar runnerrunner module; #include export module a:p1; export void foo() { std::cout << "foo from part1\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/0000755000175100017510000000000015232633614024175 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-b/0000755000175100017510000000000015232633614025162 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-b/b.p1.cppm0000644000175100017510000000023015232633614026576 0ustar runnerrunner module; #include "../dllexport.h" #include export module b:p1; export LIB_EXPORT void b_p1() { std::cout << "hello from b.part1\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-b/b.cpp0000644000175100017510000000035615232633614026113 0ustar runnerrunner module; #include module b; import :p1; import :p2; import a; void b() { b_p1(); b_p2(); std::cout << "hello from module b\n"; // these are also visible as they are public in module a a_p1(); a(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-b/b.cppm0000644000175100017510000000026015232633614026262 0ustar runnerrunner module; #include "../dllexport.h" #include export module b; import :p2; // private partition export import :p1; // public partition export LIB_EXPORT void b(); qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-b/b.p2.cppm0000644000175100017510000000021215232633614026577 0ustar runnerrunner module; #include "../dllexport.h" #include module b:p2; LIB_EXPORT void b_p2() { std::cout << "hello from b.part2\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-a/0000755000175100017510000000000015232633614025161 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-a/a.p2.cppm0000644000175100017510000000021215232633614026575 0ustar runnerrunner module; #include "../dllexport.h" #include module a:p2; LIB_EXPORT void a_p2() { std::cout << "hello from a.part2\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-a/a.cppm0000644000175100017510000000041715232633614026264 0ustar runnerrunner module; #include "../dllexport.h" #include // workaround for gcc bug export module a; import :p2; // private partition export import :p1; // public partition export LIB_EXPORT void a() { a_p1(); a_p2(); std::cout << "hello from module a\n"; }qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/lib-a/a.p1.cppm0000644000175100017510000000023015232633614026574 0ustar runnerrunnermodule; #include "../dllexport.h" #include export module a:p1; export LIB_EXPORT void a_p1() { std::cout << "hello from a.part1\n"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/dllexport.h0000644000175100017510000000324415232633614026366 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DLLEXPORT_H #define DLLEXPORT_H #if defined(_WIN32) || defined(WIN32) #define DLL_EXPORT __declspec(dllexport) #define DLL_IMPORT __declspec(dllimport) #else #define DLL_EXPORT __attribute__((visibility("default"))) #define DLL_IMPORT __attribute__((visibility("default"))) #endif #ifdef LIB_STATIC #define LIB_EXPORT #else #ifdef LIB_DYNAMIC #define LIB_EXPORT DLL_EXPORT #else #define LIB_EXPORT DLL_IMPORT #endif #endif #endif // include guard qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/app/0000755000175100017510000000000015232633614024755 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/app/main.cpp0000644000175100017510000000005715232633614026407 0ustar runnerrunnerimport b; int main() { b_p1(); b(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/cxx-modules/part-lib/partitions-library.qbs0000644000175100017510000000550015232633614030542 0ustar runnerrunner// Checks two modules split into partitions, one depends on the other Project { DynamicLibrary { condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } name: "liba" Depends { name: "cpp" } files: [ "dllexport.h", "lib-a/a.cppm", "lib-a/a.p1.cppm", "lib-a/a.p2.cppm", ] install: true cpp.defines: "LIB_DYNAMIC" cpp.rpaths: cpp.rpathOrigin cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true Depends { name: "bundle" } bundle.isBundle: false } DynamicLibrary { condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } name: "libb" Depends { name: "cpp" } Depends { name: "liba" } files: [ "dllexport.h", "lib-b/b.cpp", "lib-b/b.cppm", "lib-b/b.p1.cppm", "lib-b/b.p2.cppm", ] install: true cpp.defines: "LIB_DYNAMIC" cpp.rpaths: cpp.rpathOrigin cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true Depends { name: "bundle" } bundle.isBundle: false } CppApplication { name: "app" condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) return true; console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } Depends { name: "libb" } Depends { name: "liba" } consoleApplication: true files: [ "app/main.cpp" ] install: true cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-propertylist/0000755000175100017510000000000015232633614025525 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-propertylist/propertylist.qbs0000644000175100017510000001114215232633614031013 0ustar runnerrunnerimport qbs.Process import qbs.PropertyList import qbs.TextFile Product { type: ["Pineapple Steve"] property bool dummy: { var plistobj = new PropertyList(); if (!plistobj.isEmpty()) { throw "newly created PropertyList was not empty!"; } if (plistobj.format() !== undefined) { throw "newly created PropertyList did not have an undefined format"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() somehow had an effect on an empty PropertyList"; } plistobj.readFromString('{"key":["value"]}'); if (plistobj.isEmpty() || plistobj.format() !== "json") { throw "readFromString did not set format to JSON or object thinks it is empty"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() had no effect on a non-empty PropertyList"; } var obj = { "Array": ["ListItem1", "ListItem2", "ListItem3"], "Integer": 1, "Boolean": true, "String": "otherString" }; var infoplist = new TextFile("test.xml", TextFile.WriteOnly); infoplist.write(JSON.stringify(obj)); infoplist.close(); var process = new Process(); process.exec("plutil", ["-convert", "xml1", "test.xml"]); process.close(); var xmlfile = new TextFile("test.xml", TextFile.ReadOnly); var propertyList = new PropertyList(); propertyList.readFromString(xmlfile.readAll()); xmlfile.close(); var jsontextfile = new TextFile("test.json", TextFile.WriteOnly); jsontextfile.write(propertyList.toJSON()); jsontextfile.close(); propertyList.writeToFile("test2.json", "json-compact"); propertyList.writeToFile("test3.json", "json-pretty"); process = new Process(); process.exec("plutil", ["-convert", "json", "test.xml"]); process.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.xml"); if (propertyList.format() !== "json") { // yes, JSON -- ignore the file extension throw "expected property list format json but got " + propertyList.format(); } if (propertyList.isEmpty()) { throw "PropertyList was 'empty' after being loaded with data"; } var opensteptextfile = new TextFile("test.openstep.plist", TextFile.WriteOnly); opensteptextfile.write('{ rootObject = ( "val1", "val3", "val5", /* comment */ "val7", "val9", ); }'); opensteptextfile.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.openstep.plist"); if (propertyList.format() !== "openstep") { throw "expected property list format openstep but got " + propertyList.format(); } var jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["rootObject"].length != 5) { throw "going from OpenStep to a JSON string to a JSON object somehow broke"; } propertyList.clear(); propertyList.readFromString('foobarz'); jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["foo"] !== "barz") { throw "the XML plist did not get parsed properly"; } propertyList.writeToFile("woof.xml", "xml1"); propertyList.readFromFile("woof.xml"); if (propertyList.format() !== "xml1") { throw "round trip writing and reading XML failed"; } propertyList.writeToFile("woof.plist", "binary1"); propertyList.readFromFile("woof.plist"); if (propertyList.format() !== "binary1") { throw "round trip writing and reading binary failed"; } if (jsonObj["foo"] !== "barz") { throw "the binary plist did not get parsed properly"; } if (propertyList.toString("json") !== propertyList.toString("json-compact") || propertyList.toJSON() !== propertyList.toJSON("compact")) { throw "json and json-compact formats were not equivalent"; } if (propertyList.toString("json") === propertyList.toString("json-pretty") || propertyList.toJSON() === propertyList.toJSON("pretty")) { throw "json and json-pretty formats were not different"; } if (propertyList.toString("xml1") !== propertyList.toXMLString()) { throw 'toString("xml1") and toXMLString() were not equivalent'; } return true; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dot-dot-pc-file/0000755000175100017510000000000015232633614023102 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/0000755000175100017510000000000015232633614024347 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc0000644000175100017510000000013615232633614030571 0ustar runnerrunnerName: qbs.metatest.module Description: just a test Version: 0.0.1 Cflags: -DTHE_MAGIC_DEFINE qbs-src-3.3.1/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp0000644000175100017510000000012115232633614024524 0ustar runnerrunner#ifndef THE_MAGIC_DEFINE #error "missing the magic define" #endif int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs0000644000175100017510000000027615232633614026505 0ustar runnerrunnerCppApplication { name: "p" Depends { name: "qbs-metatest-module"; } files: "main.cpp" moduleProviders.qbspkgconfig.libDirs: "libdir" qbsModuleProviders: "qbspkgconfig" } qbs-src-3.3.1/tests/auto/blackbox/testdata/successive-changes/0000755000175100017510000000000015232633614023775 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/successive-changes/input.in0000644000175100017510000000000015232633614025452 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs0000644000175100017510000000136415232633614030272 0ustar runnerrunnerimport qbs.TextFile Project { property string version: "1" Product { name: "theProduct" type: ["output"] Group { files: ["input.in"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "output.out" fileTags: ["output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating output"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write(project.version); } return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/bom-sources/0000755000175100017510000000000015232633614022451 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/bom-sources/theheader.h0000644000175100017510000000000015232633614024541 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/bom-sources/main.cpp0000644000175100017510000000005115232633614024075 0ustar runnerrunner#include "theheader.h" int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/bom-sources/bom-sources.qbs0000644000175100017510000000011215232633614025410 0ustar runnerrunnerCppApplication { name: "app" files: ["main.cpp", "theheader.h"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/loadablemodule/0000755000175100017510000000000015232633614023164 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs0000644000175100017510000000257515232633614026655 0ustar runnerrunnerimport qbs.Host Project { LoadableModule { Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "CoolPlugIn" files: ["exported.cpp", "exported.h"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "cpp" } Depends { name: "CoolPlugIn"; cpp.link: false } consoleApplication: true name: "CoolApp" files: ["main.cpp"] cpp.cxxLanguageVersion: "c++11" cpp.libraries: [qbs.targetOS.includes("windows") ? "kernel32" : "dl"] Properties { condition: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") cpp.rpaths: [cpp.rpathOrigin] } Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/loadablemodule/main.cpp0000644000175100017510000000641115232633614024616 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifdef _WIN32 #include #define PREFIX "" #define SUFFIX ".dll" #define dlopen(path, mode) LoadLibraryA(path) #define dlsym(handle, symbol) GetProcAddress(handle, symbol) #define dlclose(handle) FreeLibrary(handle) #elif defined(__APPLE__) #define PREFIX "" #define SUFFIX ".bundle" #else #define PREFIX "lib" #define SUFFIX ".so" #endif #ifndef _WIN32 #include #endif int main() { auto lib = dlopen(PREFIX "CoolPlugIn" SUFFIX, RTLD_LAZY); if (lib) { auto fptr = dlsym(lib, "foo"); if (fptr) std::cout << "foo = " << ((int (*)(void))fptr)() << std::endl; else std::cout << "function foo not found in CoolPlugIn" << std::endl; dlclose(lib); return fptr ? 0 : 1; } else { std::cout << "CoolPlugIn not loaded" << std::endl; } return 1; } qbs-src-3.3.1/tests/auto/blackbox/testdata/loadablemodule/exported.cpp0000644000175100017510000000245215232633614025525 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "exported.h" extern "C" { int foo() { return 42; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/loadablemodule/exported.h0000644000175100017510000000243715232633614025175 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" extern "C" { DLL_EXPORT int foo(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/0000755000175100017510000000000015232633614023370 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/test.in0000644000175100017510000000000615232633614024673 0ustar runnerrunnerblubb qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/modules/0000755000175100017510000000000015232633614025040 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/0000755000175100017510000000000015232633614027125 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs0000644000175100017510000000156515232633614031130 0ustar runnerrunnerimport qbs.File Module { FileTagger { patterns: ["*.in"] fileTags: "test-input" } property string testProperty Rule { inputs: ['test-input'] Artifact { fileTags: "test-output" filePath: input.fileName + ".out" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "making output from input"; cmd.sourceCode = function() { // console.info('Change in source code'); console.info(input.TestModule.testProperty); File.copy(input.filePath, output.filePath); } var dummyCmd = new JavaScriptCommand(); dummyCmd.silent = true; dummyCmd.sourceCode = function() {}; return [cmd, dummyCmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/lib.cpp0000644000175100017510000000241515232633614024644 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/source3.cpp0000644000175100017510000000235215232633614025461 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/source1.cpp0000644000175100017510000000235115232633614025456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs0000644000175100017510000000027515232633614025752 0ustar runnerrunnerProduct { name: "ruletest" type: "test-output" Depends { name: "TestModule" } Group { files: "test.in" TestModule.testProperty: project.testProperty } } qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/source2.cpp0000644000175100017510000000235215232633614025460 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs0000644000175100017510000000535315232633614027262 0ustar runnerrunnerimport qbs.Environment import qbs.File import qbs.TextFile Project { property var projectDefines: ["blubb2"] property string fileContentSuffix: "suffix 1" property string testProperty: "default value" CppApplication { name: qbs.enableDebugCode ? "product 1.debug" : "product 1.release" cpp.defines: ["blubb1"] files: "source1.cpp" } CppApplication { Depends { name: 'library' } name: "product 2" cpp.defines: project.projectDefines files: "source2.cpp" } CppApplication { name: "product 3" cpp.defines: Environment.getEnv("QBS_BLACKBOX_DEFINE") files: "source3.cpp" } DynamicLibrary { Depends { name: "cpp" } name: "library" files: "lib.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } Product { name: "generated text file" type: ["my_output"] property string fileContentPrefix: "prefix 1" Rule { multiplex: true Artifact { filePath: "nothing"; fileTags: ["my_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.fileContentPrefix); } return cmd; } } Rule { multiplex: true Artifact { filePath: "generated.txt"; fileTags: ["my_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.filePath; cmd.highlight = "codegen"; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(product.fileContentPrefix + "contents 1" + project.fileContentSuffix); file.close(); } return cmd; } } } Product { Depends { name: "ruletest" } type: ["test-output2"] Rule { inputsFromDependencies: ['test-output'] Artifact { fileTags: "test-output2" filePath: input.fileName + ".out2" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "making output from other output"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } references: "ruletest.qbs" qbsSearchPaths: "." } qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/0000755000175100017510000000000015232633614026162 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/precompiled-and-prefix-headers.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/precompiled-and-prefix-hea0000644000175100017510000000037415232633614033202 0ustar runnerrunnerCppApplication { name: "MyApp" consoleApplication: true cpp.includePaths: [product.buildDirectory] cpp.prefixHeaders: [ "prefix.h" ] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/pch.h0000644000175100017510000000233315232633614027106 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/main.cpp0000644000175100017510000000235215232633614027614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/prefix.h0000644000175100017510000000233315232633614027631 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/0000755000175100017510000000000015232633614025763 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/0000755000175100017510000000000015232633614026531 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h0000644000175100017510000000003615232633614027447 0ustar runnerrunner#pragma once void lib1_foo();qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/0000755000175100017510000000000015232633614026543 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h0000644000175100017510000000002115232633614027465 0ustar runnerrunner#include "lib.h" qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs0000644000175100017510000000014015232633614030025 0ustar runnerrunnerCppApplication { cpp.includePaths: project.sourceDirectory + "/lib" files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp0000644000175100017510000000004115232633614030166 0ustar runnerrunner#include "app.h" int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs0000644000175100017510000000012615232633614026730 0ustar runnerrunnerProject { references: [ "app/app.qbs", "other/other.qbs", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/0000755000175100017510000000000015232633614027104 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs0000644000175100017510000000107715232633614030741 0ustar runnerrunnerimport qbs.TextFile Product { type: "testproduct" files: "../lib/lib.h" Rule { multiplex: true Artifact { fileTags: ["testproduct"] filePath: "fubar" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating text file"; cmd.sourceCode = function() { var tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine("blubb"); tf.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/archiver/0000755000175100017510000000000015232633614022016 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/archiver/archivable.qbs0000644000175100017510000000036515232633614024631 0ustar runnerrunnerProduct { name: "archivable" type: "archiver.archive" Depends { name: "archiver" } archiver.workingDirectory: path Group { files: ["list.txt"] fileTags: ["archiver.input-list"] } files: ["test.txt"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/archiver/list.txt0000644000175100017510000000003015232633614023523 0ustar runnerrunnertest.txt archivable.qbs qbs-src-3.3.1/tests/auto/blackbox/testdata/archiver/test.txt0000644000175100017510000000000015232633614023524 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/system-include-paths/0000755000175100017510000000000015232633614024275 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/system-include-paths/system-include-paths.qbs0000644000175100017510000000012215232633614031061 0ustar runnerrunnerCppApplication { files: ["main.cpp"] cpp.systemIncludePaths: ["subdir"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/system-include-paths/main.cpp0000644000175100017510000000013015232633614025717 0ustar runnerrunner#include #include int main() { printStuff(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/system-include-paths/subdir/0000755000175100017510000000000015232633614025565 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/system-include-paths/subdir/gagagugu.h0000644000175100017510000000010115232633614027515 0ustar runnerrunnervoid printStuff() { puts("alalalalonglonglilonglonglong"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/0000755000175100017510000000000015232633614022246 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test1/0000755000175100017510000000000015232633614023306 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test1/test1.qbs0000644000175100017510000000024315232633614025054 0ustar runnerrunnerCppApplication { name: "test1" type: base.concat("autotest") Depends { name: "autotest" } autotest.arguments: "--dummy" files: "test1.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test1/test1.cpp0000644000175100017510000000043315232633614025052 0ustar runnerrunner#include #include int main(int argc, char *[]) { if (argc != 2) { std::cerr << "This test needs exactly one argument" << std::endl; std::cerr << "FAIL" << std::endl; return EXIT_FAILURE; } std::cout << "PASS" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test3/0000755000175100017510000000000015232633614023310 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test3/test3.qbs0000644000175100017510000000024115232633614025056 0ustar runnerrunnerCppApplication { name: "test3" type: base.concat("autotest") Depends { name: "autotest" } autotest.allowFailure: true files: "test3.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test3/test3.cpp0000644000175100017510000000023515232633614025056 0ustar runnerrunner#include #include int main() { std::cerr << "I am an awful test"; std::cerr << "FAIL" << std::endl; return EXIT_FAILURE; } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test2/0000755000175100017510000000000015232633614023307 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test2/test2.qbs0000644000175100017510000000025215232633614025056 0ustar runnerrunnerCppApplication { name: "test2" type: base.concat("autotest") Depends { name: "autotest" } autotest.workingDir: sourceDirectory files: "test2.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test2/test2.cpp0000644000175100017510000000041615232633614025055 0ustar runnerrunner#include #include #include int main() { std::ifstream input("test2-resource.txt"); if (!input.is_open()) { std::cerr << "Test resource not found"; return EXIT_FAILURE; } std::cout << "PASS" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/test2/test2-resource.txt0000644000175100017510000000000015232633614026724 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotests/autotests.qbs0000644000175100017510000000133515232633614025012 0ustar runnerrunnerimport qbs.Host Project { references: ["test1", "test2", "test3"] AutotestRunner { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "cpp" // Make sure build environment is set up properly. condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/export-rule/0000755000175100017510000000000015232633614022501 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/export-rule/blubber.cpp0000644000175100017510000000235215232633614024624 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void hook() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/export-rule/myapp.blubb0000644000175100017510000000003315232633614024633 0ustar runnerrunnervoid justSomeFunction() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/export-rule/export-rule.qbs0000644000175100017510000000217115232633614025477 0ustar runnerrunnerimport qbs.File Project { Application { name: "MyApp" files: ["main.cpp", "myapp.blubb"] Depends { name: "blubber" } } StaticLibrary { name: "blubber" files: ["blubber.cpp"] Depends { name: "cpp" } Export { Depends { name: "cpp" } property bool enableTagger property string description: "creating C++ source file."; FileTagger { condition: enableTagger patterns: ["*.blubb"] fileTags: ["blubb"] } Rule { inputs: ["blubb"] Artifact { filePath: input.completeBaseName + ".cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = product.blubber.description; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/export-rule/main.cpp0000644000175100017510000000016615232633614024134 0ustar runnerrunnerextern void justSomeFunction(); extern void hook(); int main() { justSomeFunction(); hook(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/0000755000175100017510000000000015232633614022053 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs0000644000175100017510000000310515232633614026627 0ustar runnerrunnerimport qbs.Host Project { StaticLibrary { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "proto_lib" Depends { name: "cpp" } cpp.minimumMacosVersion: "10.8" protobuf.cpp.importPaths: product.sourceDirectory Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } files: [ "import.proto", "subdir/myenum.proto", ] Export { Depends { name: "cpp" } Depends { name: "protobuf.cpp"; required: false } cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" cpp.includePaths: exportingProduct.protobuf.cpp.outputDir } } CppApplication { condition: proto_lib.present name: "consumes_proto_lib" consoleApplication: true files: [ "import-main.cpp", ] Depends { name: "proto_lib" required: false } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/import.proto0000644000175100017510000000014315232633614024450 0ustar runnerrunnersyntax = "proto2"; import "subdir/myenum.proto"; message MyMessage { required string msg = 1; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs0000644000175100017510000000176515232633614026430 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "addressbook_nanopb" consoleApplication: true Depends { name: "cpp" } cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.nanopb"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.nanopb.present); console.info("has modules: false"); return protobuf.nanopb.present; } protobuf.nanopb.importPaths: product.sourceDirectory files: [ "addressbook_nanopb.proto", "addressbook_nanopb.options", "main_nanopb.cpp", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs0000644000175100017510000000161615232633614025730 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "addressbook_cpp" consoleApplication: true Depends { name: "cpp" } cpp.minimumMacosVersion: "10.15" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } files: [ "addressbook.proto", "main.cpp", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs0000644000175100017510000000153115232633614026057 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "addressbook_objc" consoleApplication: true Depends { name: "cpp" } Depends { name: "protobuf.objc"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.objc.present); console.info("has modules: false"); return protobuf.objc.present; } files: [ "addressbook.proto", "main.m", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/import-main.cpp0000644000175100017510000000314115232633614025012 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { MyMessage message; message.set_msg("msg"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.proto0000644000175100017510000000154315232633614027000 0ustar runnerrunner// See README.txt for information and build instructions. // // Note: START and END tags are used in comments to define sections used in // tutorials. They are not part of the syntax for Protocol Buffers. // // To get an in-depth walkthrough of this file and the related examples, see: // https://developers.google.com/protocol-buffers/docs/tutorials // [START declaration] syntax = "proto3"; package tutorial; // [END declaration] // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs0000644000175100017510000000202715232633614025745 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "app" consoleApplication: true property path theImportDir protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory]) cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } files: [ "needs-import-dir.proto", "needs-import-dir-main.cpp", "subdir/myenum.proto", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/conanfile.txt0000644000175100017510000000012215232633614024545 0ustar runnerrunner[requires] protobuf/3.21.12 [tool_requires] protobuf/3.21.12 [generators] QbsDeps qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/main.m0000644000175100017510000000373615232633614023166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "Addressbook.pbobjc.h" int main(int argc, char* argv[]) { AddressBook *addressBook = [[AddressBook alloc] init]; Person *person = [[Person alloc] init]; person.name = @"name"; person.id_p = 1; person.email = @"email"; Person_PhoneNumber *number = [[Person_PhoneNumber alloc] init]; number.number = @"number"; number.type = Person_PhoneType_Mobile; [addressBook.peopleArray addObject:person]; [addressBook release]; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/main_nanopb.cpp0000644000175100017510000000477515232633614025055 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Kai Dohmen (psykai1993@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include "addressbook_nanopb.pb.h" static_assert(std::is_array().name)>::value, ""); static_assert(std::is_array().email)>::value, ""); static_assert(std::is_array().phones)>::value, ""); bool writeString(pb_ostream_t *stream, const pb_field_t *field, void *const *) { constexpr auto str = "0123456789"; if (!pb_encode_tag_for_field(stream, field)) return false; return pb_encode_string(stream, reinterpret_cast(str), strlen(str)); } int main() { std::array buffer = {}; tutorial_Person_PhoneNumber phoneNumber; phoneNumber.number.funcs.encode = writeString; phoneNumber.type = tutorial_Person_PhoneType_WORK; auto ostream = pb_ostream_from_buffer(buffer.data(), buffer.size()); assert(pb_encode(&ostream, tutorial_Person_PhoneNumber_fields, &phoneNumber)); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/main.cpp0000644000175100017510000000423415232633614023506 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include "addressbook.pb.h" using google::protobuf::util::TimeUtil; int main(int /*argc*/, char* /*argv*/[]) { GOOGLE_PROTOBUF_VERIFY_VERSION; tutorial::AddressBook addressBook; auto person = addressBook.add_people(); person->set_name("name"); person->set_id(1); person->set_email("email"); auto phone_number = person->add_phones(); phone_number->set_number("number"); phone_number->set_type(tutorial::Person::MOBILE); *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(nullptr)); google::protobuf::ShutdownProtobufLibrary(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/import.qbs0000644000175100017510000000166715232633614024106 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } name: "app" consoleApplication: true protobuf.cpp.importPaths: [sourceDirectory] cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } files: [ "import.proto", "import-main.cpp", "subdir/myenum.proto", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook.proto0000644000175100017510000000232215232633614025437 0ustar runnerrunner// See README.txt for information and build instructions. // // Note: START and END tags are used in comments to define sections used in // tutorials. They are not part of the syntax for Protocol Buffers. // // To get an in-depth walkthrough of this file and the related examples, see: // https://developers.google.com/protocol-buffers/docs/tutorials // [START declaration] syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto"; // [END declaration] // [START java_declaration] option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; // [END java_declaration] // [START csharp_declaration] option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; // [END csharp_declaration] // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/subdir/0000755000175100017510000000000015232633614023343 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto0000644000175100017510000000007415232633614025743 0ustar runnerrunnersyntax = "proto2"; enum MyEnum { VAL1 = 0; VAL2 = 1; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto0000644000175100017510000000013415232633614026320 0ustar runnerrunnersyntax = "proto2"; import "myenum.proto"; message MyMessage { required string msg = 1; } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.options0000644000175100017510000000015115232633614027322 0ustar runnerrunnertutorial.Person.name max_size:128 tutorial.Person.email max_size:256 tutorial.Person.phones max_count:16 qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp0000644000175100017510000000315315232633614026665 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { MyMessage message; message.set_msg("msg"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/separate-debug-info/0000755000175100017510000000000015232633614024034 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/separate-debug-info/foo.cpp0000644000175100017510000000244015232633614025323 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT int getAnswer() { return 42; } qbs-src-3.3.1/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs0000644000175100017510000001075615232633614030375 0ustar runnerrunnerProject { CppApplication { name: "app1" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true Probe { id: osProbe property stringList targetOS: qbs.targetOS property stringList toolchain: qbs.toolchain configure: { console.info("is windows: " + (targetOS.includes("windows") ? "yes" : "no")); console.info("is macos: " + (targetOS.includes("macos") ? "yes" : "no")); console.info("is darwin: " + (targetOS.includes("darwin") ? "yes" : "no")); console.info("is gcc: " + (toolchain.includes("gcc") ? "yes" : "no")); console.info("is msvc: " + (toolchain.includes("msvc") ? "yes" : "no")); console.info("is emscripten: " + (toolchain.includes("emscripten") ? "yes" : "no")); } } } DynamicLibrary { Depends { name: "cpp" } name: "foo1" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: true } LoadableModule { Depends { name: "cpp" } name: "bar1" files: ["foo.cpp"] cpp.separateDebugInformation: true } CppApplication { name: "app2" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: false } DynamicLibrary { Depends { name: "cpp" } name: "foo2" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: false } LoadableModule { Depends { name: "cpp" } name: "bar2" files: ["foo.cpp"] cpp.separateDebugInformation: false } CppApplication { name: "app3" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } DynamicLibrary { Depends { name: "cpp" } name: "foo3" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } LoadableModule { Depends { name: "cpp" } name: "bar3" files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } CppApplication { name: "app4" type: ["application"] files: ["main.cpp"] consoleApplication: true cpp.separateDebugInformation: true } DynamicLibrary { Depends { name: "cpp" } name: "foo4" type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true } LoadableModule { Depends { name: "cpp" } name: "bar4" files: ["foo.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true } CppApplication { name: "app5" type: ["application"] files: ["main.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } DynamicLibrary { Depends { name: "cpp" } name: "foo5" type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } LoadableModule { Depends { name: "cpp" } name: "bar5" files: ["foo.cpp"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/separate-debug-info/main.cpp0000644000175100017510000000236415232633614025471 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/pseudo-multiplexing/0000755000175100017510000000000015232633614024231 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pseudo-multiplexing/pseudo-multiplexing.qbs0000644000175100017510000000036115232633614030756 0ustar runnerrunnerProject { Product { name: "a" multiplexByQbsProperties: ["architectures"] Depends { name: "cpp" } } Product { name: "b" multiplexByQbsProperties: [] Depends { name: "cpp" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/0000755000175100017510000000000015232633614022546 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/lib.cpp0000644000175100017510000000001515232633614024014 0ustar runnerrunnervoid f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/list.gcc0000644000175100017510000000001115232633614024167 0ustar runnerrunner-ltheLib qbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/main.cpp0000644000175100017510000000004315232633614024173 0ustar runnerrunnervoid f(); int main() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/command-file.qbs0000644000175100017510000000105615232633614025612 0ustar runnerrunnerProject { StaticLibrary { name: "theLib" destinationDirectory: project.buildDirectory Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib.cpp"] } CppApplication { name: "theApp" cpp.libraryPaths: project.buildDirectory files: ["main.cpp"] cpp.staticLibraries: ['@' + sourceDirectory + '/' + (qbs.toolchain.includes("msvc") ? "list.msvc" : "list.gcc")] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/command-file/list.msvc0000644000175100017510000000001315232633614024405 0ustar runnerrunnertheLib.lib qbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/0000755000175100017510000000000015232633614022616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/main.cpp0000644000175100017510000000236415232633614024253 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/install-tree.qbs0000644000175100017510000000033215232633614025726 0ustar runnerrunnerCppApplication { files: ["main.cpp"] qbs.installPrefix: "" Group { files: ["data/**/*.txt"] qbs.install: true qbs.installDir: "content" qbs.installSourceBase: "data" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/0000755000175100017510000000000015232633614023527 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/subdir2/0000755000175100017510000000000015232633614025101 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/subdir2/baz.txt0000644000175100017510000000000015232633614026404 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/subdir1/0000755000175100017510000000000015232633614025100 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/subdir1/bar.txt0000644000175100017510000000000015232633614026373 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/install-tree/data/foo.txt0000644000175100017510000000000015232633614025041 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rpathlink-deduplication/0000755000175100017510000000000015232633614025031 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp0000644000175100017510000000004315232633614033114 0ustar runnerrunnerint dynamicFunc() { return 1; }qbs-src-3.3.1/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp0000644000175100017510000000010315232633614033267 0ustar runnerrunnerextern int dynamicFunc(); int main() { return dynamicFunc(); }qbs-src-3.3.1/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs0000644000175100017510000000241615232633614032361 0ustar runnerrunnerProject { DynamicLibrary { Depends { name: "bundle" } Depends { name: "cpp" } bundle.isBundle: false name: "DynamicLibraryA" files: ["rpathlink-deduplication-lib.cpp"] } DynamicLibrary { Depends { name: "bundle" } Depends { name: "cpp" } Depends { name: "DynamicLibraryA" } bundle.isBundle: false name: "DynamicLibraryB" files: ["rpathlink-deduplication-lib.cpp"] } DynamicLibrary { Depends { name: "bundle" } Depends { name: "cpp" } Depends { name: "DynamicLibraryA" } bundle.isBundle: false name: "DynamicLibraryC" files: ["rpathlink-deduplication-lib.cpp"] } CppApplication { Depends { name: "bundle" } Depends { name: "DynamicLibraryB" } Depends { name: "DynamicLibraryC" } consoleApplication: true bundle.isBundle: false cpp.removeDuplicateLibraries: false files: "rpathlink-deduplication-main.cpp" property bool test: { if (cpp.useRPathLink) console.info("useRPathLink: true"); else console.info("useRPathLink: false"); console.info("===" + cpp.rpathLinkFlag + "==="); } } }qbs-src-3.3.1/tests/auto/blackbox/testdata/non-default-product/0000755000175100017510000000000015232633614024105 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/non-default-product/non-default-product.qbs0000644000175100017510000000063015232633614030505 0ustar runnerrunnerProject { CppApplication { name: "default app" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" } CppApplication { name: "non-default app" Depends { name: "default app" } consoleApplication: true builtByDefault: false files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/non-default-product/main.cpp0000644000175100017510000000235115232633614025536 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-rules/0000755000175100017510000000000015232633614024057 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs0000644000175100017510000000166315232633614030440 0ustar runnerrunnerimport qbs.TextFile Product { name: "wildcards-and-rules" type: "mytype" files: ["*.inp", "*.dep"] FileTagger { patterns: "*.inp" fileTags: ["inp"] } FileTagger { patterns: "*.dep" fileTags: ["dep"] } Rule { multiplex: true inputs: ["inp"] explicitlyDependsOn: ["dep"] Artifact { filePath: "test.mytype" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating output artifact"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.inp.length; ++i) file.writeLine(inputs.inp[i].fileName); file.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-rules/input1.inp0000644000175100017510000000000015232633614025775 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/0000755000175100017510000000000015232633614024433 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/0000755000175100017510000000000015232633614026103 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/0000755000175100017510000000000015232633614027451 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/module1.qbs0000644000175100017510000000017215232633614031526 0ustar runnerrunnerModule { Group { filesAreTargets: true fileTags: ["final"] files: ["module-fish.txt"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/module-fish.txt0000644000175100017510000000001415232633614032421 0ustar runnerrunnerModule fish qbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/step1.txt0000644000175100017510000000000315232633614026221 0ustar runnerrunnerhi qbs-src-3.3.1/tests/auto/blackbox/testdata/explicitly-depends-on/explicitly-depends-on.qbs0000644000175100017510000000675515232633614031377 0ustar runnerrunnerimport qbs.File import qbs.TextFile Project { // Cases: // step1 + in-product final -> step2 -> step3 -> final => rule cycle // step1 + dependency final -> step2 -> step3 -> final => ok // step1 + module filesAreTargets final -> step2 -> step3 -> final => ok name: "proj1" property bool useModule: false Product { name: "prod1" type: "final" property bool useExplicitlyDependsOn: false property bool useExplicitlyDependsOnFromDependencies: false Depends { condition: !project.useModule name: "prod2" } Depends { condition: project.useModule name: "module1" } Group { files: ["step1.txt"] fileTags: ["step1"] } Rule { inputs: ["step3"] outputFileTags: ["final"] Artifact { filePath: "final.txt" fileTags: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step3 -> final"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: ["step2"] outputFileTags: ["step3"] Artifact { filePath: "step3.txt" fileTags: ["step3"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step2 -> step3"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: ["step1"] outputFileTags: ["step2"] Artifact { filePath: "step2.txt" fileTags: ["step2"] } Properties { condition: useExplicitlyDependsOn explicitlyDependsOn: ["final"] } Properties { condition: useExplicitlyDependsOnFromDependencies explicitlyDependsOnFromDependencies: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step1 -> step2"; cmd.sourceCode = function() { console.info("Using explicitlyDependsOnArtifact: " + explicitlyDependsOn["final"][0].fileName) File.copy(input.filePath, output.filePath); }; return cmd; } } } Product { name: "prod2" type: "final" condition: !project.useModule Rule { multiplex: true requiresInputs: false outputFileTags: ["final"] Artifact { filePath: "product-fish.txt" fileTags: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating 'product-fish.txt' tagged with 'final'"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.ReadWrite); file.write("Lots of fish."); file.close() }; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/0000755000175100017510000000000015232633614025752 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/0000755000175100017510000000000015232633614030042 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt0000644000175100017510000000000015232633614032600 0ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracki0000644000175100017510000000045415232633614033112 0ustar runnerrunnerProduct { Group { name: "recursive" files: "**/file.txt" } Group { name: "directories" prefix: "nonrecursive/" files: "subdi?/file.txt" } Group { prefix: "nonrecursive/empty/" name: "no files" files: "*.txt" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/0000755000175100017510000000000015232633614030474 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/0000755000175100017510000000000015232633614032046 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txtqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.t0000644000175100017510000000000015232633614033140 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/0000755000175100017510000000000015232633614032045 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txtqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.t0000644000175100017510000000000015232633614033137 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/0000755000175100017510000000000015232633614030043 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt0000644000175100017510000000000015232633614032601 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-files/0000755000175100017510000000000015232633614022704 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-files/changed-files.qbs0000644000175100017510000000137115232633614026106 0ustar runnerrunnerimport qbs.TextFile CppApplication { type: ["application", "stuff"] consoleApplication: true files: ["file1.cpp", "file2.cpp", "main.cpp"] Rule { inputs: ["cpp"] outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: input.completeBaseName + ".stuff", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("crazy stuff"); f.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/changed-files/file1.cpp0000644000175100017510000000235015232633614024410 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f1() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/changed-files/file2.cpp0000644000175100017510000000235015232633614024411 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/changed-files/main.cpp0000644000175100017510000000235115232633614024335 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/changed-rule-inputs/0000755000175100017510000000000015232633614024071 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/changed-rule-inputs/changed-rule-inputs.qbs0000644000175100017510000000202015232633614030450 0ustar runnerrunnerProject { Product { name: "p1" type: "p1" Rule { alwaysRun: true multiplex: true Artifact { fileTags: "p1" filePath: "p1-dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() {}; return cmd; } } } Product { name: "p2" type: "p2" Depends { name: "p1" } Rule { requiresInputs: false multiplex: true inputsFromDependencies: "p1" Artifact { fileTags: "p2" filePath: "p2-dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() {}; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/system-run-paths/0000755000175100017510000000000015232633614023456 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/system-run-paths/lib.cpp0000644000175100017510000000235315232633614024733 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void func() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs0000644000175100017510000000147215232633614027434 0ustar runnerrunnerProject { property bool setRunPaths Product { name: "theLib" type: ["dynamiclibrary"] Depends { name: "cpp" } qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } files: ["lib.cpp"] } CppApplication { name: "app" Depends { name: "theLib" } files: ["main.cpp"] property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } cpp.rpaths: qbs.installRoot + "/lib" cpp.systemRunPaths: project.setRunPaths ? [qbs.installRoot + "/lib"] : [] } Probe { id: checker property bool isUnix: qbs.targetOS.contains("unix") configure: { console.info("is unix: " + isUnix); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/system-run-paths/main.cpp0000644000175100017510000000240415232633614025106 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void func(); int main() { func(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/0000755000175100017510000000000015232633614022254 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/mult-files-common-suffixes.qbs0000644000175100017510000000042315232633614030163 0ustar runnerrunnerBaseApp { inputSelectors: [ {names : "tool"}, {names : "super-tool"}, ] inputNameSuffixes: ".1" inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/super-tool.1"] outputCandidatePaths: [["bin/tool.1"], ["bin/super-tool.1"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/environment-paths.qbs0000644000175100017510000000037215232633614026446 0ustar runnerrunnerimport qbs.FileInfo BaseApp { inputNames: "tool" inputSearchPaths: ["bin", "usr/bin"] // env takes precedence inputEnvironmentPaths: "SEARCH_PATH" outputFilePaths: ["usr/bin/tool"] outputCandidatePaths: [["usr/bin/tool"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs0000644000175100017510000000047515232633614027663 0ustar runnerrunnerBaseApp { inputSelectors: [ {names : "tool", nameSuffixes: [".0", ".1", ".2"]}, {names : "super-tool", nameSuffixes: [".1"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/super-tool.1"] outputCandidatePaths: [["bin/tool.0", "bin/tool.1"], ["bin/super-tool.1"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/non-existent.qbs0000644000175100017510000000016615232633614025421 0ustar runnerrunnerBaseApp { inputNames: "nonexistent" inputSearchPaths: "bin" outputCandidatePaths: [["bin/nonexistent"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs0000644000175100017510000000043715232633614026702 0ustar runnerrunnerBaseApp { inputSelectors: [ {names : "tool", nameSuffixes: ".2"}, {names : "super-tool", nameSuffixes: ".1"}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.2", "bin/super-tool.1"] outputCandidatePaths: [["bin/tool.2"], ["bin/super-tool.1"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs0000644000175100017510000000047115232633614027652 0ustar runnerrunnerBaseApp { inputSelectors: [ "tool", ["tool.0", "tool.1", "tool.2"], {names : ["tool.3", "tool.4"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool", "bin/tool.1", "bin/tool.3"] outputCandidatePaths: [["bin/tool"], ["bin/tool.0", "bin/tool.1"], ["bin/tool.3"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/mult-files.qbs0000644000175100017510000000051415232633614025044 0ustar runnerrunnerBaseApp { inputSelectors: [ "tool.1", ["tool.2"], {names : "tool.3"}, {names : ["tool.4"]} ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/tool.2", "bin/tool.3", "bin/tool.4"] outputCandidatePaths: [["bin/tool.1"], ["bin/tool.2"], ["bin/tool.3"], ["bin/tool.4"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs0000644000175100017510000001255215232633614024303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com). ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.Probes Product { property varList inputSelectors property varList inputNames property varList inputNameSuffixes property pathList inputSearchPaths property var inputNameFilter property var inputCandidateFilter property stringList inputEnvironmentPaths property stringList outputFilePaths property var outputCandidatePaths Probes.PathProbe { id: probe selectors: inputSelectors names: inputNames nameSuffixes: inputNameSuffixes nameFilter: inputNameFilter candidateFilter: inputCandidateFilter searchPaths: inputSearchPaths platformSearchPaths: [] environmentPaths: inputEnvironmentPaths } property bool validate: { var compareArrays = function(lhs, rhs) { if (lhs.length !== rhs.length) return false; for (var i = 0; i < lhs.length; ++i) { if ((lhs[i] instanceof Array) && (rhs[i] instanceof Array)) { if (!compareArrays(lhs[i], rhs[i])) return false; } else if (FileInfo.resolvePath(path, lhs[i]) !== FileInfo.resolvePath(path, rhs[i])) { return false; } } return true; }; if (outputCandidatePaths) { var actual = probe.allResults.map(function(file) { return file.candidatePaths; }); if (!compareArrays(actual, outputCandidatePaths)) { throw "Invalid canndidatePaths: actual = " + JSON.stringify(actual) + ", expected = " + JSON.stringify(outputCandidatePaths); } } if (!probe.found) { if (probe.filePath) { throw "Invalid filePath: actual = " + JSON.stringify(probe.filePath) + ", expected = 'undefined'"; } if (probe.fileName) { throw "Invalid fileName: actual = " + JSON.stringify(probe.fileName) + ", expected = 'undefined'"; } if (probe.path) { throw "Invalid path: actual = " + JSON.stringify(probe.path) + ", expected = 'undefined'"; } throw "Probe failed to find files"; } if (outputFilePaths) { var actual = probe.allResults.map(function(file) { return file.filePath; }); if (!compareArrays(actual, outputFilePaths)) { throw "Invalid filePaths: actual = " + JSON.stringify(actual) + ", expected = " + JSON.stringify(outputFilePaths); } } if (probe.allResults.length !== 1) return; // check that single-file interface matches the first value in allResults var expectedFilePath = probe.allResults[0].filePath; if (probe.filePath !== expectedFilePath) { throw "Invalid filePath: actual = " + probe.filePath + ", expected = " + expectedFilePath; } var expectedFileName = probe.allResults[0].fileName; if (probe.fileName !== expectedFileName) { throw "Invalid fileName: actual = " + probe.fileName + ", expected = " + expectedFileName; } var expectedPath = probe.allResults[0].path; if (FileInfo.resolvePath(path, probe.path) !== FileInfo.resolvePath(path, expectedPath)) { throw "Invalid path: actual = " + probe.path + ", expected = " + expectedPath; } var expectedCandidatePaths = probe.allResults[0].candidatePaths; if (!compareArrays(probe.candidatePaths, expectedCandidatePaths)) { throw "Invalid candidatePaths: actual = " + JSON.stringify(probe.candidatePaths) + ", expected = " + JSON.stringify(expectedCandidatePaths); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/0000755000175100017510000000000015232633614023024 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/tool.40000644000175100017510000000000015232633614024054 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/tool0000644000175100017510000000000015232633614023712 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/super-tool.10000644000175100017510000000000015232633614025205 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/tool.30000644000175100017510000000000015232633614024053 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/tool.10000644000175100017510000000000015232633614024051 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/bin/tool.20000644000175100017510000000000015232633614024052 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/single-file.qbs0000644000175100017510000000021215232633614025154 0ustar runnerrunnerBaseApp { inputNames: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] outputCandidatePaths: [["bin/tool"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/usr/0000755000175100017510000000000015232633614023065 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/usr/bin/0000755000175100017510000000000015232633614023635 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/usr/bin/tool0000644000175100017510000000000015232633614024523 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs0000644000175100017510000000021615232633614026776 0ustar runnerrunnerBaseApp { inputSelectors: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] outputCandidatePaths: [["bin/tool"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs0000644000175100017510000000030615232633614027012 0ustar runnerrunnerBaseApp { inputNames: "tool" inputSearchPaths: "bin" inputNameSuffixes: [".0", ".1", ".2"] outputFilePaths: ["bin/tool.1"] outputCandidatePaths: [["bin/tool.0", "bin/tool.1"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs0000644000175100017510000000052215232633614026161 0ustar runnerrunnerimport qbs.FileInfo BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" inputCandidateFilter: { var fi = FileInfo; return function(f) { return fi.fileName(f) == "tool.2"; } } outputFilePaths: ["bin/tool.2"] outputCandidatePaths: [["bin/tool.1", "bin/tool.2"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/name-filter.qbs0000644000175100017510000000035715232633614025173 0ustar runnerrunnerBaseApp { inputNames: "tool" inputSearchPaths: "bin" inputNameFilter: { return function(n) { return n + ".2" }; } outputFilePaths: ["bin/tool.2"] outputCandidatePaths: [["bin/tool.2"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs0000644000175100017510000000023415232633614027764 0ustar runnerrunnerBaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1"] outputCandidatePaths: [["bin/tool.1"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs0000644000175100017510000000031715232633614027235 0ustar runnerrunnerBaseApp { inputSelectors: [ "tool.1", "nonexistent", "tool.2", ] inputSearchPaths: "bin" outputCandidatePaths: [["bin/tool.1"], ["bin/nonexistent"], ["bin/tool.2"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs0000644000175100017510000000022015232633614030105 0ustar runnerrunnerBaseApp { inputSelectors: ["tool"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] outputCandidatePaths: [["bin/tool"]] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf-library-install/0000755000175100017510000000000015232633614025161 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf-library-install/hello/0000755000175100017510000000000015232633614026264 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf-library-install/hello/world.proto0000644000175100017510000000013415232633614030476 0ustar runnerrunnersyntax = "proto3"; package protobuf.library.hello; message World { int32 value = 1; }; qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf-library-install/protobuf-library.qbs0000644000175100017510000000204015232633614031166 0ustar runnerrunnerimport qbs.Host StaticLibrary { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result && hasProtobuf; } Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" protobuf.cpp.importPaths: product.sourceDirectory Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); return protobuf.cpp.present; } Group { fileTagsFilter: "protobuf.hpp" qbs.installDir: "include" qbs.installSourceBase: protobuf.cpp.outputDir qbs.install: true } files: [ "hello.proto", "hello/world.proto", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/protobuf-library-install/hello.proto0000644000175100017510000000017115232633614027350 0ustar runnerrunnersyntax = "proto3"; package protobuf.library; import "hello/world.proto"; message Hello { hello.World world = 1; }; qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/0000755000175100017510000000000015232633614024550 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/input1.txt0000644000175100017510000000000015232633614026517 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking-product.qbs0000644000175100017510000000240015232633614033266 0ustar runnerrunnerimport "irrelevant.js" as Irrelevant import "custom1prepare1.js" as Custom1Prepare import "custom2prepare" as Custom2Prepare import "probe1.js" as ProbeFunc Product { name: "customProduct" type: ["custom1", "custom2"] property string irrelevant: Irrelevant.irrelevant() property string dummy: probe1.result Group { files: "input1.txt" fileTags: "input.custom1" } Group { files: "input2.txt" fileTags: "input.custom2" } Rule { inputs: "input.custom1" Artifact { filePath: "dummy.custom1"; fileTags: "custom1" } prepare: { return Custom1Prepare.prepare(); } } Rule { inputs: "input.custom2" Artifact { filePath: "dummy.custom2"; fileTags: "custom2" } prepare: { return Custom2Prepare.prepare(); } } Probe { id: probe1 property string input: Irrelevant.irrelevant() property string result configure: { found = true; console.info("running probe1"); return ProbeFunc.probe1Func(); } } Probe { id: probe2 configure: { console.info("running probe2"); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/0000755000175100017510000000000015232633614026245 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/0000755000175100017510000000000015232633614031200 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command2.jsqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2comm0000644000175100017510000000011415232633614033367 0ustar runnerrunnervar Irrelevant = require("../../irrelevant.js"); function sourceCode() { } ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command1.jsqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2comm0000644000175100017510000000006115232633614033370 0ustar runnerrunnervar Irrelevant = require("../../irrelevant.js"); qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom1command.js0000644000175100017510000000011015232633614030030 0ustar runnerrunnervar Irrelevant = require("./irrelevant.js"); function sourceCode() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js0000644000175100017510000000053715232633614030147 0ustar runnerrunnervar Custom1Command = require("./custom1command.js"); var Irrelevant = require("./irrelevant.js"); function prepare() { console.info("running custom1 prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "running custom1 command"; cmd.sourceCode = function() { return Custom1Command.sourceCode(); }; return cmd; } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js0000644000175100017510000000023215232633614030136 0ustar runnerrunnervar CustomPrepare = require("./custom1prepare2.js"); var Irrelevant = require("./irrelevant.js"); function prepare() { return CustomPrepare.prepare(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs0000644000175100017510000000013315232633614031611 0ustar runnerrunnerProject { qbsSearchPaths: ["."] references: "import-change-tracking-product.qbs" } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js0000644000175100017510000000005715232633614027263 0ustar runnerrunnerfunction irrelevant() { return "irrelevant"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/probe1.js0000644000175100017510000000013315232633614026273 0ustar runnerrunnervar Probe2 = require("./probe2.js") function probe1Func() { return Probe2.probe2Func(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/0000755000175100017510000000000015232633614027523 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js0000644000175100017510000000000015232633614033103 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js0000644000175100017510000000045515232633614033122 0ustar runnerrunnervar Custom2Command = require("custom2command"); function prepare() { console.info("running custom2 prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "running custom2 command"; cmd.sourceCode = function() { return Custom2Command.sourceCode(); }; return cmd; } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/input2.txt0000644000175100017510000000000015232633614026520 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-change-tracking/probe2.js0000644000175100017510000000005615232633614026300 0ustar runnerrunnerfunction probe2Func() { return "probeData"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/0000755000175100017510000000000015232633614023667 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/modules/0000755000175100017510000000000015232633614025337 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/0000755000175100017510000000000015232633614027635 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/higher-level.qbs0000644000175100017510000000014415232633614032716 0ustar runnerrunnerModule { Depends { name: "lowerlevel" } lowerlevel.propDependency: "value in higherlevel" } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/0000755000175100017510000000000015232633614027517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs0000644000175100017510000000076015232633614032466 0ustar runnerrunnerModule { property string propDependency: "value in lowerlevel module" property string prop: propDependency property string someOtherProp Rule { inputs: ["dummy-input"] outputFileTags: "mytype" prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { }; var prop = product.lowerlevel.prop; cmd.description = "lowerlevel.prop is '" + prop + "'"; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/product.qbs0000644000175100017510000000067415232633614026065 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "lowerlevel" } lowerlevel.someOtherProp: "blubb" } } Product { type: "mytype" name: "toplevel" Depends { name: "higherlevel" } Depends { name: "lowerlevel" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["dummy-input"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nested-properties/dummy.txt0000644000175100017510000000000015232633614025551 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-timeout/0000755000175100017510000000000015232633614023547 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-timeout/test-main.cpp0000644000175100017510000000255515232633614026163 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { std::this_thread::sleep_for(std::chrono::seconds(5)); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs0000644000175100017510000000205415232633614027776 0ustar runnerrunnerimport qbs.Host Project { CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "testApp" type: ["application", "autotest"] Depends { name: "autotest" } cpp.cxxLanguageVersion: "c++11" cpp.minimumOsxVersion: "10.8" // For Properties { condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } files: "test-main.cpp" } AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rule-connection-with-excluded-inputs/0000755000175100017510000000000015232633614027403 5ustar runnerrunner././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-connection-with-excluded-inputs/rule-connection-with-excluded-inputs.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-connection-with-excluded-inputs/rule-connection-with0000644000175100017510000000222415232633614033403 0ustar runnerrunnerProduct { name: "p" type: "p_type" Rule { multiplex: true Artifact { filePath: "x.txt"; fileTags: "x" } Artifact { filePath: "y.txt"; fileTags: "y" } Artifact { filePath: "p.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } Rule { multiplex: true Artifact { filePath: "x2.txt"; fileTags: "x" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } Rule { multiplex: true inputs: "x" excludedInputs: "y" Artifact { filePath: "dummy"; fileTags: "p_type" } prepare: { console.info("inputs.x: " + (inputs.x ? inputs.x.length : 0)); console.info("inputs.y: " + (inputs.y ? inputs.y.length : 0)); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/0000755000175100017510000000000015232633614026061 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/b.inp0000644000175100017510000000000015232633614027000 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/c.inp0000644000175100017510000000000015232633614027001 0ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inputs.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inpu0000644000175100017510000000200415232633614033277 0ustar runnerrunnerimport qbs.TextFile Product { name: "p" type: ["p.out"] property bool enableTagger FileTagger { condition: enableTagger patterns: ["*.inp"] fileTags: ["p.in"] } Rule { multiplex: true requiresInputs: false inputs: ["p.in"] Artifact { filePath: "output.txt" fileTags: ["p.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write('('); var inputsList = inputs["p.in"]; if (inputsList) { for (var i = 0; i < inputsList.length; ++i) f.write(inputsList[i].fileName + ','); } f.write(')'); }; return [cmd]; } } files: ["a.inp", "b.inp", "c.inp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/a.inp0000644000175100017510000000000015232633614026777 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/0000755000175100017510000000000015232633614022234 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/0000755000175100017510000000000015232633614030640 5ustar runnerrunner././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/outputArtifacts-missing-fileTags.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/outputArtifact0000644000175100017510000000057215232633614033605 0ustar runnerrunnerCppApplication { type: base.concat("txt") files : ["main.cpp"] Rule { inputs: ["application"] outputArtifacts: [{ filePath: input.completeBaseName + ".txt" }] outputFileTags: ["txt"] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/main.cpp0000644000175100017510000000003115232633614032262 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDir/0000755000175100017510000000000015232633614026612 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDir/nonexistentWorkingDir.qbs0000644000175100017510000000057415232633614033705 0ustar runnerrunnerApplication { name: "kaputt" type: ["nutritious"] Rule { multiplex: true Artifact { filePath: "Stulle" fileTags: ["nutritious"] } prepare: { var cmd = new Command("ls"); cmd.workingDirectory = "/does/not/exist"; cmd.silent = true; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/0000755000175100017510000000000015232633614030636 5ustar runnerrunner././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/outputArtifacts-missing-filePath.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/outputArtifact0000644000175100017510000000054215232633614033600 0ustar runnerrunnerCppApplication { type: base.concat("txt") files : ["main.cpp"] Rule { inputs: ["application"] outputArtifacts: [{ fileTags: ["txt"] }] outputFileTags: ["txt"] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/main.cpp0000644000175100017510000000003115232633614032260 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/tag-mismatch/0000755000175100017510000000000015232633614024612 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/tag-mismatch/tag-mismatch.qbs0000644000175100017510000000176315232633614027706 0ustar runnerrunnerProduct { name: "p" type: "p_type" Rule { multiplex: true outputFileTags: ["x"] outputArtifacts: [{filePath: "dummy1", fileTags: ["x","y","z"]}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["y"] Artifact { filePath: "dummy2"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["x"] Artifact { filePath: "dummy3"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/0000755000175100017510000000000015232633614030731 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/boom.txt.in0000644000175100017510000000004515232633614033032 0ustar runnerrunnerBoom! shake-shake-shake the ${what}! ././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/texttemplate-unknown-placeholder.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/texttemplate-u0000644000175100017510000000024115232633614033633 0ustar runnerrunnerProduct { type: ["text"] Depends { name: "texttemplate" } texttemplate.dict: ({ wat: "room" }) // typo in key name files: [ "boom.txt.in" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-graph-versions/0000755000175100017510000000000015232633614024257 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/build-graph-versions/main.cpp0000644000175100017510000000001715232633614025705 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-graph-versions/build-graph-versions.qbs0000644000175100017510000000005315232633614031030 0ustar runnerrunnerCppApplication { files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-temporarydir/0000755000175100017510000000000015232633614025466 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-temporarydir/jsextensions-temporarydir.qbs0000644000175100017510000000113415232633614033447 0ustar runnerrunnerimport qbs.File import qbs.TemporaryDir Product { targetName: { var dir; var dirPath; try { dir = new TemporaryDir(); dirPath = dir.path(); if (!dirPath) throw "path is empty"; if (!dir.isValid()) throw "dir is not valid"; if (!File.exists(dirPath)) throw "dir does not exist"; } finally { if (!dir.remove()) throw "could not remove"; } if (File.exists(dirPath)) throw "dir was not removed"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-artifacts/0000755000175100017510000000000015232633614024470 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-artifacts/conflicting-artifacts.qbs0000644000175100017510000000050415232633614031453 0ustar runnerrunnerProject { CppApplication { name: "a" targetName: "theName" destinationDirectory: project.buildDirectory files: ["main.cpp"] } CppApplication { name: "b" targetName: "theName" destinationDirectory: project.buildDirectory files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/conflicting-artifacts/main.cpp0000644000175100017510000000235115232633614026121 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/emscripten-artifacts/0000755000175100017510000000000015232633614024342 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/emscripten-artifacts/main.cpp0000644000175100017510000000235115232633614025773 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/emscripten-artifacts/emscripten-artifacts.qbs0000644000175100017510000000023615232633614031201 0ustar runnerrunnerCppApplication { name: "app" property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/0000755000175100017510000000000015232633614022736 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/after/0000755000175100017510000000000015232633614024037 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs0000644000175100017510000000401315232633614027267 0ustar runnerrunnerimport qbs.TextFile import qbs.Host Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: 'someapp' type: 'application' consoleApplication: true property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); } Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "foosource", "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp0000644000175100017510000000253515232633614025474 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int foo(); int main(int argc, char **argv) { std::printf("there's %d foo here\n", foo()); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/before/0000755000175100017510000000000015232633614024200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs0000644000175100017510000000377615232633614027447 0ustar runnerrunnerimport qbs.TextFile import qbs.Host Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: 'someapp' type: 'application' consoleApplication: true property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); } Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp0000644000175100017510000000251215232633614025630 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char **argv) { std::printf("there's no foo here\n"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/0000755000175100017510000000000015232633614025076 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/file.h0000644000175100017510000000001215232633614026157 0ustar runnerrunnervoid f(); qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/lib.cpp0000644000175100017510000000001415232633614026343 0ustar runnerrunnervoid l() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/file.cpp0000644000175100017510000000005015232633614026514 0ustar runnerrunner#include void f() { l(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/multiple-configurations.qbs0000644000175100017510000000046115232633614032471 0ustar runnerrunnerProject { StaticLibrary { name: "lib" Depends { name: "cpp" } files: ["lib.cpp", "lib.h"] } CppApplication { name: "app" Depends { name: "lib" } cpp.includePaths: project.sourceDirectory files: ["file.cpp", "file.h", "main.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/lib.h0000644000175100017510000000001215232633614026006 0ustar runnerrunnervoid l(); qbs-src-3.3.1/tests/auto/blackbox/testdata/multiple-configurations/main.cpp0000644000175100017510000000005315232633614026524 0ustar runnerrunner#include int main() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/0000755000175100017510000000000015232633614024750 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/0000755000175100017510000000000015232633614026420 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/m/0000755000175100017510000000000015232633614026654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/m/m.qbs0000644000175100017510000000064615232633614027625 0ustar runnerrunnerModule { property bool p Rule { multiplex: true Artifact { filePath: "dummy" fileTags: ["out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating dummy"; cmd.sourceCode = function() { console.info("m.p: " + product.m.p); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/transformer-data-rescue.qbs0000644000175100017510000000014415232633614032213 0ustar runnerrunnerCppApplication { type: base.concat(["out"]) Depends { name: "m" } files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/rescue-transformer-data/main.cpp0000644000175100017510000000001615232633614026375 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-fileinfo/0000755000175100017510000000000015232633614024540 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs0000644000175100017510000000531315232633614027044 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] property string messyPath: path + "/../" + FileInfo.fileName(path) Rule { multiplex: true outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var output = new TextFile(FileInfo.joinPaths(product.sourceDirectory, "output.txt"), TextFile.WriteOnly); output.writeLine(FileInfo.baseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.canonicalPath(product.messyPath)); output.writeLine(FileInfo.cleanPath("/usr/local//../bin/")); output.writeLine(FileInfo.completeBaseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fileName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz", ["unix"])); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz", ["windows"])); output.writeLine(FileInfo.isAbsolutePath("blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("../blubb.tar.gz")); output.writeLine(FileInfo.joinPaths("/", "tmp", "blubb.tar.gz")); output.writeLine(FileInfo.joinPaths("//", "/tmp/", "/blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/")); output.writeLine(FileInfo.path("/")); output.writeLine(FileInfo.path("d:/")); output.writeLine(FileInfo.path("d:/", ["unix"])); output.writeLine(FileInfo.path("d:/", ["windows"])); output.writeLine(FileInfo.relativePath("/tmp", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/tmp", "/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.pathListSeparator()); output.writeLine(FileInfo.pathSeparator()); output.close(); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-library-names/0000755000175100017510000000000015232633614024404 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-library-names/invalid-library-names.qbs0000644000175100017510000000056315232633614031310 0ustar runnerrunnerProject { minimumQbsVersion: "1.6" property var values: [null, undefined, 5, [], ""] property int valueIndex CppApplication { cpp.dynamicLibraries: [project.values[project.valueIndex]] cpp.staticLibraries: [project.values[project.valueIndex]] cpp.libraries: [project.values[project.valueIndex]] files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-library-names/main.cpp0000644000175100017510000000235215232633614026036 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/0000755000175100017510000000000015232633614023107 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript10000644000175100017510000000002215232633614025616 0ustar runnerrunnerTEST_SYMBOL1 = 0; qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript_recursive0000644000175100017510000000004015232633614027624 0ustar runnerrunnerTEST_SYMBOL_FROM_RECURSIVE = 1; qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/testlib.c0000644000175100017510000000235315232633614024724 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummy() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/scripts/0000755000175100017510000000000015232633614024576 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/scripts/linkerscript_in_directory0000644000175100017510000000004015232633614031776 0ustar runnerrunnerTEST_SYMBOL_FROM_DIRECTORY = 1; qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript20000644000175100017510000000002215232633614025617 0ustar runnerrunnerTEST_SYMBOL2 = 1; qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript_to_include0000644000175100017510000000007515232633614027752 0ustar runnerrunnerTEST_SYMBOL_FROM_INCLUDE = 1; INCLUDE linkerscript_recursive qbs-src-3.3.1/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs0000644000175100017510000000374615232633614026524 0ustar runnerrunnerimport qbs.TextFile DynamicLibrary { type: base.concat("custom") Depends { name: "cpp" } files: ["testlib.c"] Group { name: "linker scripts" files: [ "linkerscript1", "linkerscript2", ] fileTags: ["linkerscript"] } cpp.libraryPaths: [ product.sourceDirectory, // location of linkerscripts that are included ] Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.warn("---" + product.cpp.nmPath + "---"); } return [cmd]; } } Rule { multiplex: true requiresInputs: false Artifact { filePath: product.buildDirectory + "/linkerscript_with_includes" fileTags: ["linkerscript"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourcePath = product.sourceDirectory; cmd.buildPath = product.buildDirectory; cmd.sourceCode = function() { var file = new TextFile(buildPath + "/linkerscript_with_includes", TextFile.WriteOnly); file.write("SEARCH_DIR(\"" + sourcePath + "/scripts\")\n" + "INCLUDE linkerscript_to_include\n" + "INCLUDE linkerscript_in_directory\n"); file.close(); } cmd.highlight = "codegen"; cmd.description = "generating linkerscript with SEARCH_DIR and INCLUDE"; return [cmd]; } } Probe { id: checker property bool isGcc: qbs.toolchain.contains("gcc") property bool isLinux: qbs.targetOS.contains("linux") configure: { console.info("is Linux gcc: " + (isGcc && isLinux)) } } qbs.installPrefix: "" install: true installDir: "" } qbs-src-3.3.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/0000755000175100017510000000000015232633614024222 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/aux-inputs-from-deps.qbs0000644000175100017510000000424615232633614030746 0ustar runnerrunnerimport qbs.File import qbs.TextFile import "util.js" as Utils Project { CppApplication { name: "app" files: ["main.cpp"] Depends { name: "dep" } } Product { name: "p" type: ["p.out"] Depends { name: "dep" } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["hpp"] Artifact { filePath: "dummy.out" fileTags: ["p.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating dummy.out"; cmd.sourceCode = function() { File.copy(project.buildDirectory + "/dummy.h", output.filePath); }; return [cmd]; } } } Product { name: "dep" type: ["hpp"] property bool sleep: true Rule { inputs: ["blubb.in"] Artifact { filePath: project.buildDirectory + "/dummy.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating header"; cmd.sourceCode = function() { if (product.sleep) Utils.sleep(1000); File.copy(input.filePath, output.filePath); } return [cmd]; } } Rule { multiplex: true Artifact { filePath: "dummy.blubb" fileTags: ["blubb.in"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating blubb.in"; cmd.sourceCode = function() { if (product.sleep) Utils.sleep(1000); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } Export { Depends { name: "cpp" } cpp.includePaths: [project.buildDirectory] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/util.js0000644000175100017510000000025115232633614025533 0ustar runnerrunnerfunction sleep(timeInMs) { var referenceTime = new Date(); var time = null; do { time = new Date(); } while (time - referenceTime < timeInMs); } qbs-src-3.3.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/main.cpp0000644000175100017510000000004315232633614025647 0ustar runnerrunner#include int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/0000755000175100017510000000000015232633614022530 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/after/0000755000175100017510000000000015232633614023631 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs0000644000175100017510000000132415232633614026655 0ustar runnerrunnerimport qbs.Host Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: 'someapp' type: 'application' consoleApplication: true property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); } Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp", "zort.h", "zort.cpp" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp0000644000175100017510000000246315232633614025340 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "zort.h" #include void Zort::shout() { std::printf("ZORT!\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/after/zort.h0000644000175100017510000000245415232633614025005 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ZORT_H #define ZORT_H class Zort { public: void shout(); }; #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp0000644000175100017510000000265115232633614025265 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include "zort.h" #include int main(int argc, char **argv) { std::printf("Hello World!\n"); Narf narf; narf.shout(); Zort zort; zort.shout(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/before/0000755000175100017510000000000015232633614023772 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs0000644000175100017510000000124215232633614027015 0ustar runnerrunnerimport qbs.Host Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: 'someapp' type: 'application' consoleApplication: true property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); } Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp0000644000175100017510000000256615232633614025433 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include int main(int argc, char **argv) { std::printf("Hello World!\n"); Narf narf; narf.shout(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp0000644000175100017510000000246315232633614025431 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include void Narf::shout() { std::printf("NARF!\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/trackAddFile/before/narf.h0000644000175100017510000000245415232633614025076 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef NARF_H #define NARF_H class Narf { public: void shout(); }; #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-without-sources/0000755000175100017510000000000015232633614025430 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-without-sources/lib.cpp0000644000175100017510000000001515232633614026676 0ustar runnerrunnervoid f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs0000644000175100017510000000037615232633614033362 0ustar runnerrunnerProject { StaticLibrary { name: "a" Depends { name: "cpp" } files: ["lib.cpp"] } Product { type: qbs.targetOS.includes("darwin") ? undefined : ["staticlibrary"] name: "b" Depends { name: "cpp" } Depends { name: "a" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/check-timestamps/0000755000175100017510000000000015232633614023454 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/check-timestamps/file.h0000644000175100017510000000001215232633614024535 0ustar runnerrunnervoid f(); qbs-src-3.3.1/tests/auto/blackbox/testdata/check-timestamps/file.cpp0000644000175100017510000000004015232633614025071 0ustar runnerrunner#include "file.h" void f() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/check-timestamps/check-timestamps.qbs0000644000175100017510000000016015232633614027421 0ustar runnerrunnerCppApplication { name: "app" files: [ "file.cpp", "file.h", "main.cpp", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/check-timestamps/main.cpp0000644000175100017510000000001615232633614025101 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-extension-instantiation/0000755000175100017510000000000015232633614026535 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-extension-instantiation/invalid-extension-instantiation.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-extension-instantiation/invalid-extension-instant0000644000175100017510000000104715232633614033600 0ustar runnerrunnerimport qbs.Environment import qbs.File import qbs.FileInfo import qbs.Utilities Product { name: "theProduct" type: ["mytype"] property string extension Rule { multiplex: true Artifact { filePath: "dummy" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = eval("new " + product.extension); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/0000755000175100017510000000000015232633614023604 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/rock.coal0000644000175100017510000000000515232633614025375 0ustar runnerrunnercoal qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/0000755000175100017510000000000015232633614025254 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/0000755000175100017510000000000015232633614026616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.c0000644000175100017510000000235515232633614030331 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper3() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.qbs0000644000175100017510000000023115232633614030663 0ustar runnerrunnerModule { Depends { name: "cpp" } Group { name: "Helper3 Sources" files: ["helper3.c"] } validate: { throw "Nope."; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper8/0000755000175100017510000000000015232633614026623 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper8/helper8.c0000644000175100017510000000002615232633614030334 0ustar runnerrunnervoid helper8(void) {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper8/helper8.qbs0000644000175100017510000000050215232633614030676 0ustar runnerrunnerModule { version: "8" Probe { id: baseNameProbe property string baseName configure: { baseName = "helper" } } property string fileName: baseNameProbe.baseName + version + ".c" Group { condition: version === "8" prefix: path + "/" files: fileName } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/0000755000175100017510000000000015232633614026620 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.qbs0000644000175100017510000000034015232633614030670 0ustar runnerrunnerModule { Depends { name: "cpp" } Depends { name: "helper6" required: false } Group { name: "Helper5 Sources" files: ["helper5.c"] cpp.defines: ["COMPILE_FIX"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.c0000644000175100017510000000243415232633614030333 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper5() { #ifndef COMPILE_FIX nothatcantwork #endif } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/0000755000175100017510000000000015232633614026617 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.c0000644000175100017510000000235515232633614030333 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper4() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.qbs0000644000175100017510000000022715232633614030672 0ustar runnerrunnerModule { Depends { name: "cpp" } Depends { name: "helper5" } Group { name: "Helper4 Sources" files: ["helper4.c"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/0000755000175100017510000000000015232633614026615 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.qbs0000644000175100017510000000041215232633614030662 0ustar runnerrunnerModule { Depends { name: "cpp" } Group { name: "Helper2 Sources" files: ["helper2.c"] } Group { name: "some other file from helper2" prefix: product.sourceDirectory + '/' files: ["someotherfile.txt"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.c0000644000175100017510000000235515232633614030327 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/0000755000175100017510000000000015232633614026621 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.c0000644000175100017510000000235515232633614030337 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper6() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.qbs0000644000175100017510000000023415232633614030674 0ustar runnerrunnerModule { Depends { name: "cpp" } Group { name: "Helper6 Sources" files: ["helper6.c"] } validate: { throw "Go away."; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/0000755000175100017510000000000015232633614026622 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs0000644000175100017510000000004415232633614030675 0ustar runnerrunnerHelper7Base { directory: path } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c0000644000175100017510000000002615232633614030332 0ustar runnerrunnervoid helper7(void) {} qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/0000755000175100017510000000000015232633614026533 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/chunk.coal0000644000175100017510000000000615232633614030477 0ustar runnerrunnerchunk qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs0000644000175100017510000000206715232633614030526 0ustar runnerrunnerimport qbs.FileInfo Module { Depends { name: "cpp" } Depends { name: "helper2" } additionalProductTypes: ["diamond"] Group { name: "Helper Sources" files: ["diamondc.c"] } Group { name: "Additional Chunk" prefix: path + "/" files: ["chunk.coal"] } Group { name: "some other file from helper" prefix: project.sourceDirectory + '/' files: ["someotherfile2.txt"] } FileTagger { patterns: ["*.coal"] fileTags: ["coal"] } Rule { inputs: ["coal"] explicitlyDependsOn: ["application"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, input.baseName + ".diamond") fileTags: ["diamond"] } prepare: { var cmd = new Command(FileInfo.joinPaths(product.buildDirectory, product.targetName), [input.filePath, output.filePath]); cmd.description = "compiling " + input.fileName + " to " + output.fileName; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/diamondc.c0000644000175100017510000000327115232633614030460 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "usage: diamondc input.coal output.diamond"); return 1; } FILE *in = fopen(argv[1], "r"); if (in) { fclose(in); } else { return 1; } FILE *out = fopen(argv[2], "w"); if (out) { fprintf(out, "diamond\n"); fclose(out); } else { return 1; } return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/imports/0000755000175100017510000000000015232633614025301 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs0000644000175100017510000000022015232633614030103 0ustar runnerrunnerModule { property string directory property string fileName Group { prefix: directory + "/" files: fileName } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs0000644000175100017510000000165615232633614027714 0ustar runnerrunnerimport qbs.Host Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "dep" } Depends { name: "helper" } Depends { name: "helper3" required: false } Depends { name: "helper7" } helper7.fileName: "helper7.c" Depends { name: "helper8" } type: ["diamond"] files: [ "rock.coal" ] } Product { name: "dep" Export { Depends { name: "helper4" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/someotherfile2.txt0000644000175100017510000000000015232633614027262 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/groups-in-modules/someotherfile.txt0000644000175100017510000000000015232633614027200 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-filetagger/0000755000175100017510000000000015232633614024625 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-filetagger/main.custom0000644000175100017510000000001715232633614027003 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs0000644000175100017510000000032015232633614031741 0ustar runnerrunnerCppApplication { name: "theApp" property bool enableTagger files: ["main.custom"] FileTagger { condition: enableTagger patterns: ["*.custom"] fileTags: ["cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/0000755000175100017510000000000015232633614026242 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/per-group-define-in-export-item.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/per-group-define-in-expor0000644000175100017510000000045315232633614033076 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "cpp" } Group { cpp.defines: ["MAIN"] files: ["main.cpp"] } } } Application { name: "app" Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/main.cpp0000644000175100017510000000004115232633614027665 0ustar runnerrunner#ifdef MAIN int main() {} #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-command-property/0000755000175100017510000000000015232633614025137 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs0000644000175100017510000000161315232633614032573 0ustar runnerrunnerimport qbs.TextFile Product { name: "p" property string errorType type: ["output"] Group { files: ["input.txt"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "dummy" fileTags: ["output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating output"; if (product.errorType === "qobject") cmd.dummy = new TextFile(input.filePath, TextFile.ReadOnly); else if (product.errorType === "input") cmd.dummy = input; else if (product.errorType === "artifact") cmd.dummy = product.artifacts.qbs[0]; else throw "invalid error type " + product.errorType; cmd.sourceCode = function() { } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/invalid-command-property/input.txt0000644000175100017510000000000015232633614027025 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/0000755000175100017510000000000015232633614022676 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/modules/0000755000175100017510000000000015232633614024346 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/modules/higher/0000755000175100017510000000000015232633614025614 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/modules/higher/higher.qbs0000644000175100017510000000021015232633614027562 0ustar runnerrunnerModule { Depends { name: "lower" required: false versionAtLeast: "1.0" versionBelow: "10.0" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/modules/lower/0000755000175100017510000000000015232633614025476 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/modules/lower/lower.qbs0000644000175100017510000000001315232633614027327 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/blackbox/testdata/versioncheck/versioncheck.qbs0000644000175100017510000000037315232633614026073 0ustar runnerrunnerProduct { property string requestedMinVersion property string requestedMaxVersion Depends { name: "higher" } Depends { name: "lower" versionAtLeast: requestedMinVersion versionBelow: requestedMaxVersion } } qbs-src-3.3.1/tests/auto/blackbox/testdata/cpu-features/0000755000175100017510000000000015232633614022616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/cpu-features/main.cpp0000644000175100017510000000001615232633614024243 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs0000644000175100017510000000073415232633614025734 0ustar runnerrunnerCppApplication { Depends { name: "cpufeatures" } cpufeatures.x86_sse2: true cpufeatures.x86_avx: true cpufeatures.x86_avx512f: false files: ["main.cpp"] property bool dummy: { console.info("is x86: " + (qbs.architecture === "x86")); console.info("is x64: " + (qbs.architecture === "x86_64")); console.info("is gcc: " + qbs.toolchain.includes("gcc")); console.info("is msvc: " + qbs.toolchain.includes("msvc")); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/0000755000175100017510000000000015232633614025732 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/broken.cpp.in0000644000175100017510000000002615232633614030321 0ustar runnerrunnervoid f() { blubb(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/main.cpp.in0000644000175100017510000000001615232633614027764 0ustar runnerrunnerint main() {} ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/output-artifact-auto-tagging.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/output-artifact-auto-tagging0000644000175100017510000000176115232633614033401 0ustar runnerrunnerimport qbs.File CppApplication { consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Group { files: ["broken.cpp.in", "main.cpp.in"] fileTags: ["cpp.in"] } Rule { multiplex: true inputs: ["cpp.in"] outputFileTags: ["cpp"] outputArtifacts: [{ filePath: "main.cpp" }, { filePath: "broken.nomatch" }] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating main.cpp"; cmd.sourceCode = function() { File.copy(product.sourceDirectory + "/main.cpp.in", product.buildDirectory + "/main.cpp"); File.copy(product.sourceDirectory + "/broken.cpp.in", product.buildDirectory + "/broken.nomatch"); }; return [cmd]; } } FileTagger { patterns: ["*.nomatch"] fileTags: ["utter nonsense"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/variant-suffix/0000755000175100017510000000000015232633614023161 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs0000644000175100017510000000174715232633614026647 0ustar runnerrunnerStaticLibrary { name: "l" Group { condition: qbs.targetOS.includes("darwin") Depends { name: "bundle" } Properties { bundle.isBundle: false } } aggregate: false property string variantSuffix property bool multiplex: false Properties { condition: multiplex qbs.buildVariants: ["debug", "release"] multiplexByQbsProperties: ["buildVariants"] } Properties { condition: variantSuffix !== undefined cpp.variantSuffix: variantSuffix } cpp.staticLibraryPrefix: "lib" cpp.staticLibrarySuffix: ".ext" qbs.installPrefix: "" config.install.staticLibraries: true Depends { name: "cpp" } files: ["lib.cpp"] Probe { id: targetOSProbe property stringList targetOS: qbs.targetOS configure: { console.info("is Windows: " + targetOS.includes("windows")); console.info("is Apple: " + targetOS.includes("darwin")); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/variant-suffix/lib.cpp0000644000175100017510000000001415232633614024426 0ustar runnerrunnervoid f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/0000755000175100017510000000000015232633614024667 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep2.txt0000644000175100017510000000002215232633614026254 0ustar runnerrunnervoid helper2() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/modules/0000755000175100017510000000000015232633614026337 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/modules/m/0000755000175100017510000000000015232633614026573 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/modules/m/m.qbs0000644000175100017510000000011115232633614027527 0ustar runnerrunnerModule { property bool discoverDep6 property bool discoverDep7 } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep5.txt0000644000175100017510000000000015232633614026253 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep4.txt0000644000175100017510000000002215232633614026256 0ustar runnerrunnervoid helper4() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep6.txt0000644000175100017510000000000015232633614026254 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/main.cpp0000644000175100017510000000001615232633614026314 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/scanner-change-tracking.qbs0000644000175100017510000000141715232633614032055 0ustar runnerrunnerimport qbs.FileInfo import "subdir/helper.js" as Helper CppApplication { name: "app" property bool discoverDep5 Depends { name: "m" } Scanner { condition: true inputs: 'none' recursive: false scan: { if (FileInfo.fileName(filePath) === "helper.cpp") // recursive case return ["dep4.txt"]; var deps = ["dep1.txt", "dep3.txt", "helper.cpp"]; deps = deps.concat(Helper.additionalDependencies(product)); if (product.m.discoverDep6) deps.push("dep6.txt"); if (input.m.discoverDep7) deps.push("dep7.txt"); return deps; } searchPaths: { return [product.sourceDirectory] } } files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep7.txt0000644000175100017510000000000015232633614026255 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/dep1.txt0000644000175100017510000000002215232633614026253 0ustar runnerrunnervoid helper1() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/helper.cpp0000644000175100017510000000000015232633614026640 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/subdir/0000755000175100017510000000000015232633614026157 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/subdir/helper.js0000644000175100017510000000023415232633614027773 0ustar runnerrunnerfunction additionalDependencies(product) { var deps = [/*'dep2.txt'*/]; if (product.discoverDep5) deps.push("dep5.txt"); return deps; } qbs-src-3.3.1/tests/auto/blackbox/testdata/scanner-change-tracking/subdir/dep3.txt0000644000175100017510000000002215232633614027545 0ustar runnerrunnervoid helper3() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/0000755000175100017510000000000015232633614026453 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/0000755000175100017510000000000015232633614030123 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/d/0000755000175100017510000000000015232633614030346 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/d/d.qbs0000644000175100017510000000010115232633614031270 0ustar runnerrunnerModule { Depends { name: "b"; } Depends { name: "c"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/a/0000755000175100017510000000000015232633614030343 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/a/a.qbs0000644000175100017510000000011215232633614031264 0ustar runnerrunnerModule { validate: { throw "Module cannot be loaded"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/c/0000755000175100017510000000000015232633614030345 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/c/c.qbs0000644000175100017510000000006615232633614031300 0ustar runnerrunnerModule { Depends { name: "a"; required: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/b/0000755000175100017510000000000015232633614030344 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/b/b.qbs0000644000175100017510000000004515232633614031273 0ustar runnerrunnerModule { Depends { name: "a" } } ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/transitive-invalid-dependencies.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-invalid-dependencies/transitive-invalid-depend0000644000175100017510000000051515232633614033450 0ustar runnerrunnerProduct { property bool modulePresent: { console.info("b.present = " + b.present); console.info("c.present = " + c.present); console.info("d.present = " + d.present); } Depends { name: "b"; required: false } Depends { name: "c"; required: false } Depends { name: "d"; required: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/no-such-profile/0000755000175100017510000000000015232633614023225 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs0000644000175100017510000000006615232633614026750 0ustar runnerrunnerProduct { name: "theProduct" property int p } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/0000755000175100017510000000000015232633614026046 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/test.cpp0000644000175100017510000000001415232633614027524 0ustar runnerrunnervoid f() {} ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/build-data-of-disabled-product.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/build-data-of-disabled-pro0000644000175100017510000000010715232633614032742 0ustar runnerrunnerCppApplication { name: "app" files: ["main.cpp", "test.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/main.cpp0000644000175100017510000000004315232633614027473 0ustar runnerrunnervoid f(); int main() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-export/0000755000175100017510000000000015232633614024035 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-export/main.cpp0000644000175100017510000000243515232633614025471 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef THE_DEFINE #error "missing define" #endif int main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/conditional-export/conditional-export.qbs0000644000175100017510000000053515232633614030371 0ustar runnerrunnerProject { property bool enableExport: false Product { name: "dep" Export { condition: project.enableExport Depends { name: "cpp" } cpp.defines: ["THE_DEFINE"] } } CppApplication { name: "theProduct" Depends { name: "dep" } files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/0000755000175100017510000000000015232633614022775 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/Foo.h0000644000175100017510000000040115232633614023664 0ustar runnerrunner#ifndef FOO_H #define FOO_H #include #ifdef FOO_LIB_STATIC #define FOO_LIB_EXPORT #else #ifdef FOO_LIB #define FOO_LIB_EXPORT DLL_EXPORT #else #define FOO_LIB_EXPORT DLL_IMPORT #endif #endif FOO_LIB_EXPORT int someFooWork(); #endif // FOO_H qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/cmake/0000755000175100017510000000000015232633614024055 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt0000644000175100017510000000024215232633614026613 0ustar runnerrunnercmake_minimum_required(VERSION 3.10) project(qbs_import) find_package(Bar PATHS REQUIRED) add_executable(Consumer main.cpp) target_link_libraries(Consumer Bar) qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp0000644000175100017510000000007315232633614025505 0ustar runnerrunner#include int main() { return someFooWork(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp0000644000175100017510000000006615232633614024226 0ustar runnerrunner#include "Foo.h" int someFooWork() { return 42; } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs0000644000175100017510000000254215232633614025505 0ustar runnerrunnerimport qbs.Probes Product { Depends { name: "cpp" } Probes.BinaryProbe { id: cmakeProbe names: "cmake" } Probes.BinaryProbe { id: ninjaProbe names: ["ninja"] } property bool test: { var data = { cmakeFound: cmakeProbe.found, cmakeFilePath: cmakeProbe.filePath, crossCompiling: qbs.targetPlatform !== qbs.hostPlatform, installPrefix: qbs.installPrefix }; data.buildEnv = {} Object.assign(data.buildEnv, cpp.buildEnv); // deep copy buildEnv from a probe if (qbs.toolchain.includes("gcc")) { data.buildEnv["CC"] = cpp.cCompilerName; data.buildEnv["CXX"] = cpp.cxxCompilerName; } else { data.buildEnv["CC"] = cpp.compilerName; data.buildEnv["CXX"] = cpp.compilerName; } if (ninjaProbe.found) { data.generator = "Ninja"; } else { if (qbs.toolchain.includes("msvc")) { data.generator = "NMake Makefiles" } else if (qbs.toolchain.includes("mingw")) { data.generator = "MinGW Makefiles"; } else if (qbs.toolchain.includes("gcc")) { data.generator = "Unix Makefiles"; } } console.info("---" + JSON.stringify(data) + "---"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs0000644000175100017510000000422615232633614026272 0ustar runnerrunnerimport qbs.FileInfo Project { property bool isStatic: false property bool isBundle: false property string headersInstallDir: "include" Product { name: "DllExport" Depends { name: "Exporter.cmake" } Group { name: "API headers" files: ["../dllexport.h"] qbs.install: true qbs.installDir: project.headersInstallDir } Group { fileTagsFilter: ["Exporter.cmake.package"] qbs.install: true qbs.installDir: "/lib/cmake/DllExport" } Export { Depends { name: "cpp" } cpp.includePaths: FileInfo.joinPaths( exportingProduct.qbs.installRoot, exportingProduct.qbs.installPrefix, project.headersInstallDir) } } Library { type: project.isStatic ? "staticlibrary" : "dynamiclibrary" Depends { name: "cpp" } Depends { name: "DllExport" } Depends { name: "Exporter.cmake" } Exporter.cmake.packageName: "Bar" name: "Foo" files: ["Foo.cpp"] version: "1.2.3" cpp.includePaths: "." cpp.defines: "FOO_LIB" Group { name: "API headers" files: ["Foo.h"] qbs.install: true qbs.installDir: project.headersInstallDir } install: true installImportLib: true Group { fileTagsFilter: ["Exporter.cmake.package"] qbs.install: true qbs.installDir: "/lib/cmake/Bar" } Export { Depends { name: "cpp" } cpp.includePaths: FileInfo.joinPaths( exportingProduct.qbs.installRoot, exportingProduct.qbs.installPrefix, project.headersInstallDir) cpp.defines: ["FOO=1"].concat(project.isStatic ? ["FOO_LIB_STATIC"] : []) cpp.commonCompilerFlags: "-DOTHER_DEF=1" cpp.linkerFlags: exportingProduct.qbs.toolchain.contains("gcc") ? ["-s"] : [] } Depends { name: 'bundle' } bundle.isBundle: qbs.targetOS.includes("darwin") && project.isBundle } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-shadow-products/0000755000175100017510000000000015232633614025371 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probes-and-shadow-products/probes-and-shadow-products.qbs0000644000175100017510000000034015232633614033253 0ustar runnerrunnerProduct { name: "p" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Export { Probe { id: dummy configure: { found = true; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/dependenciesProperty/0000755000175100017510000000000015232633614024406 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp0000644000175100017510000000236415232633614026661 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs0000644000175100017510000000240315232633614031307 0ustar runnerrunnerimport qbs.TextFile import qbs.FileInfo Project { Product { name: "newDependency" } Product { type: "deps" name: "product1" Depends { name: "product2" } // Depends { name: 'product2' } // Depends { name: 'newDependency' } Rule { multiplex: true inputsFromDependencies: "application" Artifact { fileTags: ["deps"] filePath: product.name + '.deps' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(JSON.stringify(product.dependencies, undefined, 2)); file.close(); } return cmd; } } } Product { type: "application" consoleApplication: true name: "product2" property string narf: "zort" Depends { name: "cpp" } cpp.defines: ["SMURF"] files: ["product2.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/0000755000175100017510000000000015232633614025064 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/0000755000175100017510000000000015232633614026534 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/0000755000175100017510000000000015232633614030522 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs0000644000175100017510000000100215232633614033210 0ustar runnerrunnerimport qbs.Probes Module { Probes.PkgConfigProbe { id: theProbe name: "dummy" } property stringList libs: theProbe.libs Rule { multiplex: true outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.name + " libs: " + JSON.stringify(product.themodule.libs)); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/0000755000175100017510000000000015232633614026667 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/0000755000175100017510000000000015232633614027500 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/0000755000175100017510000000000015232633614030602 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/pkgconfig/0000755000175100017510000000000015232633614032551 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/pkgconfig/dummy.pcqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/pkgconfig/dum0000644000175100017510000000014715232633614033263 0ustar runnerrunnerName: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -L/usr/dummy -ldummy1 Cflags: qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/pkg-config.qbs0000644000175100017510000000077615232633614027631 0ustar runnerrunnerProject { property string packageBaseName Product { name: "theProduct1" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot1" } Product { name: "theProduct2" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot2" } Product { name: "theProduct3" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot1" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/0000755000175100017510000000000015232633614026670 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/0000755000175100017510000000000015232633614027501 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/0000755000175100017510000000000015232633614030603 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/pkgconfig/0000755000175100017510000000000015232633614032552 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/pkgconfig/dummy.pcqbs-src-3.3.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/pkgconfig/dum0000644000175100017510000000014715232633614033264 0ustar runnerrunnerName: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -L/usr/dummy -ldummy1 Cflags: qbs-src-3.3.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/0000755000175100017510000000000015232633614027526 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in0000644000175100017510000000000015232633614031437 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in0000644000175100017510000000000015232633614031440 0ustar runnerrunner././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/usings-as-sole-inputs-non-multiplexed.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/usings-as-sole-inpu0000644000175100017510000000302115232633614033267 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Project { Product { name: "p1" type: "custom" Group { files: "custom1.in" fileTags: "custom.in" } } Product { name: "p2" type: "custom" Group { files: "custom2.in" fileTags: "custom.in" } } Rule { inputs: "custom.in" Artifact { filePath: FileInfo.baseName(input.filePath) + ".out" fileTags: "custom" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } Product { name: "p3" type: "custom-plus" Depends { name: "p1" } Depends { name: "p2" } Rule { inputsFromDependencies: "custom" Artifact { filePath: FileInfo.fileName(input.filePath) + ".plus" fileTags: "custom-plus" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/0000755000175100017510000000000015232633614026652 5ustar runnerrunner././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/transitive-optional-dependencies.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/transitive-optional-depe0000644000175100017510000000004615232633614033523 0ustar runnerrunnerProduct { Depends { name: "a" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/0000755000175100017510000000000015232633614030322 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/0000755000175100017510000000000015232633614030542 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/a.qbs0000644000175100017510000000006615232633614031473 0ustar runnerrunnerModule { Depends { name: "b"; required: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/0000755000175100017510000000000015232633614030543 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/b.qbs0000644000175100017510000000004015232633614031465 0ustar runnerrunnerModule { condition: false } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-config-import-export/0000755000175100017510000000000015232633614025072 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-config-import-export/config.json0000644000175100017510000000023715232633614027234 0ustar runnerrunner{ "group": { "key1": "value1", "key2": "value2" }, "key": "value", "listKey": [ "valueOne", "valueTwo" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt0000644000175100017510000000013115232633614027073 0ustar runnerrunnergroup.key1: "value1" group.key2: "value2" key: "value" listKey: ["valueOne", "valueTwo"] qbs-src-3.3.1/tests/auto/blackbox/testdata/distribution-include-paths/0000755000175100017510000000000015232633614025470 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/distribution-include-paths/distribution-include-paths.qbs0000644000175100017510000000013015232633614033446 0ustar runnerrunnerCppApplication { files: ["main.cpp"] cpp.distributionIncludePaths: ["subdir"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/distribution-include-paths/main.cpp0000644000175100017510000000013015232633614027112 0ustar runnerrunner#include #include int main() { printStuff(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/distribution-include-paths/subdir/0000755000175100017510000000000015232633614026760 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/distribution-include-paths/subdir/gagagugu.h0000644000175100017510000000010115232633614030710 0ustar runnerrunnervoid printStuff() { puts("alalalalonglonglilonglonglong"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/0000755000175100017510000000000015232633614025746 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/0000755000175100017510000000000015232633614030543 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/0000755000175100017510000000000015232633614032213 5ustar runnerrunner././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/aModule/qbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/aModul0000755000175100017510000000000015232633614033355 5ustar runnerrunner././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/aModule/aModule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/aModul0000644000175100017510000000001315232633614033351 0ustar runnerrunnerModule { } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/export-to-outside-searchpath.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/export-to-outside-searchpath0000644000175100017510000000057615232633614033434 0ustar runnerrunnerProject { Project { qbsSearchPaths: ["qbs-resources"] Product { name: "otherProduct" Depends { name: "dep" } } Product { name: "dep" Export { Depends { name: "aModule" } } } } Project { Product { name: "theProduct" Depends { name: "dep" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-module-definition/0000755000175100017510000000000015232633614025110 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/linker-module-definition/testlib.cpp0000644000175100017510000000314315232633614027263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include void foo() { std::printf("foo\n"); } void bar() { std::printf("bar\n"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-module-definition/testapp.cpp0000644000175100017510000000312715232633614027277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ extern void foo(); extern void bar(); int main() { foo(); bar(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-module-definition/testlib.def0000644000175100017510000000002015232633614027226 0ustar runnerrunnerEXPORTS foo bar qbs-src-3.3.1/tests/auto/blackbox/testdata/linker-module-definition/linker-module-definition.qbs0000644000175100017510000000131615232633614032515 0ustar runnerrunnerimport qbs.Host Project { CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "testapp" Depends { name: "testlib"} files: ["testapp.cpp"] } DynamicLibrary { name: "testlib" Depends { name: "cpp"} files: ["testlib.cpp", "testlib.def"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/configure/0000755000175100017510000000000015232633614022174 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/configure/modules/0000755000175100017510000000000015232633614023644 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/configure/modules/definition/0000755000175100017510000000000015232633614025774 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs0000644000175100017510000000166415232633614027777 0ustar runnerrunnerimport qbs.Process Module { name: 'definition' Depends { name: 'cpp' } Probe { id: node property stringList targetOS: qbs.targetOS property stringList windowsShellPath: qbs.windowsShellPath property string result configure: { var cmd; var args; var p = path; if (targetOS.includes("windows")) { cmd = windowsShellPath; args = ["/c", "date", "/t"]; } else { cmd = 'date'; args = []; } var p = new Process(); if (0 === p.exec(cmd, args)) { found = true; result = p.readLine(); } else { found = false; result = undefined; } p.close(); } } cpp.defines: node.found ? 'TEXT="Configured at ' + node.result + '"' : undefined } qbs-src-3.3.1/tests/auto/blackbox/testdata/configure/main.cpp0000644000175100017510000000245515232633614023632 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::printf("%s..\n", TEXT); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/configure/configure.qbs0000644000175100017510000000134415232633614024666 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { property bool enabled: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } property string name: 'configure' qbsSearchPaths: '.' Product { type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nsisDependencies/0000755000175100017510000000000015232633614023476 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nsisDependencies/main.c0000644000175100017510000000003115232633614024560 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/nsisDependencies/hello.nsi0000644000175100017510000000023115232633614025310 0ustar runnerrunnerPage directory Page instfiles Section "" SetOutPath "$INSTDIR" File "${buildDirectory}\app.exe" File "${buildDirectory}\lib.dll" SectionEnd qbs-src-3.3.1/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs0000644000175100017510000000406315232633614027473 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Project { property bool dummy: { console.info("is Windows: " + qbs.targetOS.includes("windows")); } NSISSetup { name: "inst" destinationDirectory: project.buildDirectory Depends { name: "app" } Depends { name: "lib" } Properties { condition: nsis.present nsis.defines: ["buildDirectory=" + FileInfo.toWindowsSeparators(project.buildDirectory)] } files: ["hello.nsi"] } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] destinationDirectory: project.buildDirectory install: false } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } }; return [cmd]; } } destinationDirectory: project.buildDirectory install: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/0000755000175100017510000000000015232633614023177 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/e.cpp0000644000175100017510000000240215232633614024125 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int d(); int e() { return d(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/a1.cpp0000644000175100017510000000244315232633614024207 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void a1() { std::cout << "a1" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/a2.cpp0000644000175100017510000000244315232633614024210 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void a2() { std::cout << "a2" << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/b.cpp0000644000175100017510000000237715232633614024135 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void a1(); void b() { a1(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/d.mm0000644000175100017510000000027515232633614023761 0ustar runnerrunner#import void printGreeting() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSLog (@"Hello darkness, my old friend!"); [pool drain]; } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/static-lib-deps.qbs0000644000175100017510000000620715232633614026677 0ustar runnerrunnerProject { property bool useExport: true StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a1.cpp", "a2.cpp", ] } StaticLibrary { name: "b" Depends { name: "cpp" } Depends { name: "a" } files: [ "b.cpp", ] } StaticLibrary { name: "c" Depends { name: "cpp" } Depends { name: "a" } files: [ "c.cpp", ] } StaticLibrary { name: "d" Depends { name: "cpp" } Depends { name: "b" } Depends { name: "c" } files: [ "d.cpp", ] Group { condition: qbs.targetOS.includes("darwin") files: ["d.mm"] } Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["WITH_SETUPAPI"] cpp.staticLibraries: !project.useExport ? ["setupapi"] : [] } Properties { condition: qbs.targetOS.includes("darwin") cpp.defines: ["WITH_ZLIB"] cpp.staticLibraries: !project.useExport ? ["z"] : [] cpp.frameworks: !project.useExport ? ["Foundation"] : [] } Properties { condition: { console.info(qbs.targetOS); return qbs.targetOS.includes("linux") || qbs.targetOS.includes("hurd") } cpp.defines: ["WITH_PTHREAD", "WITH_ZLIB"] cpp.staticLibraries: !project.useExport ? ["pthread", "z"] : [] } Properties { condition: qbs.toolchain.contains("emscripten") cpp.defines: ["WITH_WEBSOCK"] cpp.staticLibraries: !project.useExport ? ["websocket.js"] : [] } Export { condition : project.useExport Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("linux") || qbs.targetOS.includes("hurd") cpp.staticLibraries: ["pthread", "z"] } Properties { condition: qbs.targetOS.contains("darwin") cpp.staticLibraries: ["z"] cpp.frameworks: ["Foundation"] } Properties { condition: qbs.targetOS.contains("windows") cpp.staticLibraries: ["setupapi"] } Properties { condition: qbs.toolchain.contains("emscripten") cpp.staticLibraries: ["websocket.js"] } } } StaticLibrary { name: "e" Depends { name: "cpp" } Depends { name: "d" } files: [ "e.cpp", ] Export { Depends { name: "d" } } } CppApplication { name: "staticLibDeps" type: "application" consoleApplication: true Depends { name: "e" } Properties { condition: qbs.targetOS.includes("linux") || qbs.targetOS.includes("hurd") cpp.driverFlags: ["-static"] } files: [ "main.cpp", ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/main.cpp0000644000175100017510000000240515232633614024630 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int e(); int main() { return e(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/d.cpp0000644000175100017510000000411115232633614024123 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #if defined(WITH_ZLIB) #include #endif #if defined(WITH_WEBSOCK) #include #endif #ifdef WITH_PTHREAD #include #elif defined(WITH_SETUPAPI) #include #include #endif void b(); void c(); int d() { b(); c(); int result = 0; #if defined(WITH_ZLIB) const char source[] = "Hello, world"; uLongf buffer_size = compressBound(sizeof(source)); result += static_cast(buffer_size); #endif #if defined(WITH_WEBSOCK) const bool supported = emscripten_websocket_is_supported(); (void) supported; #endif #ifdef WITH_PTHREAD pthread_t self = pthread_self(); result += static_cast(self); #elif defined(WITH_SETUPAPI) CABINET_INFO ci; ci.SetId = 0; SetupIterateCabinet(L"invalid-file-path", 0, NULL, NULL); result += ci.SetId; #endif return result; } qbs-src-3.3.1/tests/auto/blackbox/testdata/static-lib-deps/c.cpp0000644000175100017510000000237715232633614024136 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void a2(); void c() { a2(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-host/0000755000175100017510000000000015232633614023722 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-host/host.qbs0000644000175100017510000000236515232633614025414 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host import qbs.TextFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var output = new TextFile(FileInfo.joinPaths(product.sourceDirectory, "output.txt"), TextFile.WriteOnly); output.writeLine("architecture: " +Host.architecture()); output.writeLine("os: " + Host.os()); output.writeLine("platform: " + Host.platform()); output.writeLine("osVersion: " + Host.osVersion()); output.writeLine("osBuildVersion: " + Host.osBuildVersion()); output.writeLine("osVersionParts: " + Host.osVersionParts()); output.writeLine("osVersionMajor: " + Host.osVersionMajor()); output.writeLine("osVersionMinor: " + Host.osVersionMinor()); output.writeLine("osVersionPatch: " + Host.osVersionPatch()); output.writeLine("nullDevice: " + Host.nullDevice()); output.close(); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/nsis/0000755000175100017510000000000015232633614021167 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/nsis/hello.qbs0000644000175100017510000000054615232633614023006 0ustar runnerrunnerNSISSetup { name: "Qbs Hello" targetName: "qbs-hello-" + qbs.architecture property bool dummy: { console.info("is Windows: " + qbs.targetOS.includes("windows")); } Properties { condition: nsis.present nsis.defines: ["batchFile=hello.bat"] nsis.compressor: "lzma-solid" } files: ["hello.nsi", "hello.bat"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/nsis/hello.bat0000644000175100017510000000002215232633614022754 0ustar runnerrunnerecho Hello world! qbs-src-3.3.1/tests/auto/blackbox/testdata/nsis/hello.nsi0000644000175100017510000000056115232633614023007 0ustar runnerrunnerSetCompressor zlib !ifdef Win64 Name "Qbs Hello - ${qbs.architecture} (64-bit)" !else Name "Qbs Hello - ${qbs.architecture} (32-bit)" !endif OutFile "you-should-not-see-a-file-with-this-name.exe" InstallDir "$DESKTOP\Qbs Hello" RequestExecutionLevel user Page directory Page instfiles Section "" SetOutPath "$INSTDIR" File "${batchFile}" SectionEnd qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/0000755000175100017510000000000015232633614025354 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/0000755000175100017510000000000015232633614027024 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newermodule/0000755000175100017510000000000015232633614031352 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newermodule/newermodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newermodule/newermodul0000644000175100017510000000010715232633614033454 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c99" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/oldmodule/0000755000175100017510000000000015232633614031010 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/oldmodule/oldmodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/oldmodule/oldmodule.qb0000644000175100017510000000010715232633614033316 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c90" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newestmodule/0000755000175100017510000000000015232633614031537 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newestmodule/newestmodule.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newestmodule/newestmod0000644000175100017510000000010715232633614033465 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c11" } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/main.c0000644000175100017510000000003115232633614026436 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/maximum-c-language-version/maximum-c-language-version.qbs0000644000175100017510000000137615232633614033233 0ustar runnerrunnerCppApplication { name: "app" property bool enableNewestModule: true Probe { id: osProbe property string toolchainType: qbs.toolchainType property string compilerVersion: cpp.compilerVersion configure: { console.info("is msvc: " + (toolchainType === "msvc" || toolchainType === "clang-cl")); var isOld = (toolchainType === "msvc" && compilerVersion < "19.29.30138") || (toolchainType === "clang-cl" && compilerVersion < "13"); console.info("is old msvc: " + isOld); found = true; } } Depends { name: "oldmodule" } Depends { name: "newermodule" } Depends { name: "newestmodule"; condition: enableNewestModule } files: "main.c" } qbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/0000755000175100017510000000000015232633614025706 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/0000755000175100017510000000000015232633614027356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/myconfig/0000755000175100017510000000000015232633614031171 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/myconfig/myconfig.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/myconfig/myconfig.qb0000644000175100017510000000005715232633614033332 0ustar runnerrunnerModule { property bool typeDecider: true } qbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/main.cpp0000644000175100017510000000235115232633614027337 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type0000644000175100017510000001042615232633614033327 0ustar runnerrunnerimport qbs.TextFile Project { CppApplication { consoleApplication: true name: "no-match" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" } Project { CppApplication { consoleApplication: true name: "app1" files: "main.cpp" } CppApplication { consoleApplication: true name: "app2" files: "main.cpp" } CppApplication { consoleApplication: true name: "app3" files: "main.cpp" } Product { type: myconfig.typeDecider ? ["application"] : [] Depends { name: "cpp" } Depends { name: "myconfig" } consoleApplication: true name: "app4" files: "main.cpp" } Product { name: "other-product" type: "other" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "other" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); } return cmd; } } Export { Depends { productTypes: "other2" } } } Product { name: "yet-another-product" type: "other2" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "other2" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); } return cmd; } } } Product { name: "helper" Export { Depends { productTypes: "other" } } } CppApplication { condition: false consoleApplication: true name: "disabled-app" files: "main.cpp" } DynamicLibrary { Depends { name: "cpp" } name: "lib-product" files: "main.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } CppApplication { type: base.concat(["app-list"]) consoleApplication: true name: "app list" Depends { productTypes: ["application"] limitToSubProject: true } Depends { name: "helper" } files: ["main.cpp"] Rule { multiplex: true inputsFromDependencies: ["application", "other", "other2"] Artifact { filePath: "app-list.txt" fileTags: "app-list" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "collecting apps"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs["application"].length; ++i) file.writeLine(inputs["application"][i].filePath); for (i = 0; i < inputs["other"].length; ++i) file.writeLine(inputs["other"][i].filePath); for (i = 0; i < inputs["other2"].length; ++i) file.writeLine(inputs["other2"][i].filePath); file.close(); }; return cmd; } } } Product { name: "dummy" Depends { productTypes: [] } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/0000755000175100017510000000000015232633614021643 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/0000755000175100017510000000000015232633614024050 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs0000644000175100017510000000256215232633614026771 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); console.info("executable suffix: " + cpp.executableSuffix); return result; } qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true Probe { id: pathCheck property string theDir: { if (qbs.targetOS.includes("windows")) { if (qbs.toolchain.includes("mingw")) return cpp.toolchainInstallPath; if (qbs.toolchain.includes("clang") && qbs.sysroot) return qbs.sysroot + "/bin"; } } configure: { if (theDir) console.info("add to PATH: " + theDir); found = true; } } files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/types.h0000644000175100017510000000325415232633614025371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/lexer.l0000644000175100017510000000045115232633614025344 0ustar runnerrunner%{ #include #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return ID; {AND} return AND; {OR} return OR; {NOT} return NOT; %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/parser.y0000644000175100017510000000117315232633614025540 0ustar runnerrunner%{ #include %} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/0000755000175100017510000000000015232633614024202 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/types.h0000644000175100017510000000325415232633614025523 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/lexer.l0000644000175100017510000000045415232633614025501 0ustar runnerrunner%{ #include #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return ID; {AND} return AND; {OR} return OR; {NOT} return NOT; %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/yacc_output.qbs0000644000175100017510000000050515232633614027250 0ustar runnerrunnerCppApplication { Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/parser.y0000644000175100017510000000122015232633614025663 0ustar runnerrunner%{ #include %} %output "parser.cxx" %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/modules/0000755000175100017510000000000015232633614023313 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/0000755000175100017510000000000015232633614025625 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs0000644000175100017510000000065315232633614030652 0ustar runnerrunnerimport qbs.Process Module { Depends { name: "lex_yacc" } Probe { id: bisonProbe property string yaccBinary: lex_yacc.yaccBinary configure: { var p = Process(); found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().includes("bison"); p.close(); } } Properties { condition: bisonProbe.found lex_yacc.yaccFlags: "-y" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/0000755000175100017510000000000015232633614024162 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/types.h0000644000175100017510000000325415232633614025503 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lex_outfile.qbs0000644000175100017510000000060215232633614027206 0ustar runnerrunnerCppApplication { qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lexer.l0000644000175100017510000000045415232633614025461 0ustar runnerrunner%option outfile="quark.cpp" %{ #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return 1; {AND} return 2; {OR} return 3; {NOT} return 4; %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/parser.y0000644000175100017510000000117315232633614025652 0ustar runnerrunner%{ #include %} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/0000755000175100017510000000000015232633614024010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lex_prefix.qbs0000644000175100017510000000060215232633614026662 0ustar runnerrunnerCppApplication { qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/types.h0000644000175100017510000000325715232633614025334 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define BLASTYPE YaccType extern TreePtr root; int blalex(); void blaerror(const char *); qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lexer.l0000644000175100017510000000045315232633614025306 0ustar runnerrunner%option prefix="bla" %{ #include void blaerror(const char *e) { std::cerr << e; } extern "C" int blawrap() { return 1; } extern BLASTYPE blalval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} blalval.s = blatext; return 1; {AND} return 2; {OR} return 3; {NOT} return 4; %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/parser.y0000644000175100017510000000122515232633614025476 0ustar runnerrunner%{ #include %} %define api.prefix {bla} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { blaparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/0000755000175100017510000000000015232633614024263 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs0000644000175100017510000000034215232633614027411 0ustar runnerrunnerimport qbs.Host CppApplication { Depends { name: "lex_yacc" } consoleApplication: true cpp.includePaths: ".." files: [ "g1.l", "g1.y", "g2.l", "g2.y", "main.c", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g1.l0000644000175100017510000000024015232633614024743 0ustar runnerrunner%option noyywrap %{ #include #ifdef _MSC_BUILD #pragma message("whatever") #else #pragma whatever #endif void g1error(const char *e) { } %} %% %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g2.y0000644000175100017510000000007715232633614024771 0ustar runnerrunner%{ int g2lex(); void g2error(const char *s); %} %% expr: '1' qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/main.c0000644000175100017510000000246515232633614025362 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int g1parse(); int g2parse(); int main() { g1parse(); g2parse(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g1.y0000644000175100017510000000007715232633614024770 0ustar runnerrunner%{ int g1lex(); void g1error(const char *s); %} %% expr: '1' qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g2.l0000644000175100017510000000012415232633614024745 0ustar runnerrunner%option noyywrap %{ #include void g2error(const char *e) { } %} %% %% qbs-src-3.3.1/tests/auto/blackbox/testdata/lexyacc/unistd.h0000644000175100017510000000022015232633614023314 0ustar runnerrunner#ifndef MY_UNISTD_H #define MY_UNISTD_H #ifdef _MSC_BUILD #include #define isatty _isatty #else #include_next #endif #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/0000755000175100017510000000000015232633614024010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/app.qbs0000644000175100017510000000041315232633614025275 0ustar runnerrunnerProduct { consoleApplication: true type: "application" name: "blubb_user" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: "main.cpp" Depends { name: "blubb_header" } Depends { name: "cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/header.qbs0000644000175100017510000000160715232633614025753 0ustar runnerrunnerimport qbs.TextFile Product { name: "blubb_header" type: "hpp" files: "blubb_header.h.in" property string blubbProp: project.blubbProp Rule { multiplex: true Artifact { filePath: "blubb_header.h" fileTags: "hpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating blubb_header.h"; cmd.highlight = "codegen"; cmd.blubbProp = product.blubbProp; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write("#define BLUBB_PROP " + blubbProp); file.close(); } return cmd; } } Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.buildDirectory } } qbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/main.cpp0000644000175100017510000000245515232633614025446 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "blubb_header.h" int main() { #if BLUBB_PROP != 5 blubb(); #endif } qbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/blubb_header.h.in0000644000175100017510000000000015232633614027152 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/productproperties/productproperties.qbs0000644000175100017510000000013115232633614030307 0ustar runnerrunnerProject { property string blubbProp: "5" references: ["header.qbs", "app.qbs"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/0000755000175100017510000000000015232633614025122 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file4.txt0000644000175100017510000000000015232633614026654 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file1.txt0000644000175100017510000000000015232633614026651 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file2.txt0000644000175100017510000000000015232633614026652 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs0000644000175100017510000000233315232633614032541 0ustar runnerrunnerProject { Product { name: "TextFileContainer1" type: "txt_container" Group { files: ["file1.txt", "file2.txt"] fileTags: "txt" } } Product { name: "TextFileContainer2" Group { files: ["file3.txt"] fileTags: "txt" } } Product { name: "TextFileContainer3" Group { files: ["file4.txt"] fileTags: "txt" } } Product { name: "TextFileGatherer" type: "printed_txt" Depends { name: "TextFileContainer1" } Depends { name: "TextFileContainer2" } Rule { inputsFromDependencies: "txt" multiplex: true Artifact { filePath: "blubb" fileTags: "printed_txt" alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "gathering text files"; cmd.sourceCode = function() { for (i in inputs.txt) console.info(inputs.txt[i].filePath); }; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file3.txt0000644000175100017510000000000015232633614026653 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/0000755000175100017510000000000015232633614024102 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs0000644000175100017510000000021715232633614030500 0ustar runnerrunnerProduct { qbs.installPrefix: "" Group { qbs.install: true qbs.installSourceBase: "." files: ["dir/**"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/dir/0000755000175100017510000000000015232633614024660 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/dir/wasser.txt0000644000175100017510000000000015232633614026713 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/0000755000175100017510000000000015232633614026150 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/blubb.txt0000644000175100017510000000000015232633614027765 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/0000755000175100017510000000000015232633614023030 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/modules/0000755000175100017510000000000015232633614024500 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/0000755000175100017510000000000015232633614026630 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/module.qbs0000644000175100017510000000051615232633614030626 0ustar runnerrunnerimport qbs.Probes Module { name: 'definition' Depends { name: 'cpp' } property string modulePath: path Probes.IncludeProbe { id: includeNode names: "fakeopenssl/sha.h" platformSearchPaths: [modulePath] } cpp.defines: includeNode.found ? 'TEXT="' + includeNode.path + '"' : undefined } qbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/fakeopenssl/0000755000175100017510000000000015232633614031142 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/fakeopenssl/sha.h0000644000175100017510000000000015232633614032054 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/main.cpp0000644000175100017510000000245515232633614024466 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::printf("%s..\n", TEXT); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs0000644000175100017510000000137415232633614026361 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { property string name: 'includeLookup' qbsSearchPaths: '.' Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-binaryfile/0000755000175100017510000000000015232633614025071 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs0000644000175100017510000000360115232633614027724 0ustar runnerrunnerimport qbs.BinaryFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var source = new BinaryFile("source.dat", BinaryFile.WriteOnly); source.write([ 0x01, 0x02 ]); // First data. // Do not close the file to test the auto close functionality. }; commands.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { source = new BinaryFile("source.dat", BinaryFile.ReadWrite); source.seek(source.size()); source.write([ 0x03, 0x04 ]); // Second data. source.close(); source = new BinaryFile("source.dat", BinaryFile.ReadWrite); var destination = new BinaryFile("destination.dat", BinaryFile.WriteOnly); destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); while (true) { var data = source.read(1); if (!data || data.length == 0) break; destination.write(data); } source.resize(0); // truncate destination.write([ 0x05, 0x06 ]); // Third data. destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); source.close(); destination.close(); source = new BinaryFile("destination.dat", BinaryFile.ReadOnly); destination = new BinaryFile("destination2.dat", BinaryFile.WriteOnly); destination.write(source.read(8)); }; commands.push(cmd); return commands; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/probe-change-tracking/0000755000175100017510000000000015232633614024345 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/probe-change-tracking/probe-change-tracking.qbs0000644000175100017510000000177015232633614031213 0ustar runnerrunnerProject { Probe { id: tlpProbe property int confValue configure: { console.info("running tlpProbe"); confValue = 5; } } property int tlpCount: tlpProbe.confValue Project { Probe { id: subProbe property int confValue configure: { console.info("running subProbe"); confValue = 7; } } property int subCount: subProbe.confValue Product { name: "theProduct" property bool runProbe property int v1: project.tlpCount property int v2: project.subCount Probe { id: productProbe condition: product.runProbe property int v1: product.v1 property int v2: product.v2 configure: { console.info("running productProbe: " + (v1 + v2)); } } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/rtti-change-tracking/0000755000175100017510000000000015232633614024220 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/rtti-change-tracking/rtti-change-tracking.qbs0000644000175100017510000000045015232633614030733 0ustar runnerrunnerCppApplication { Probe { id: gccTester property bool isGcc: qbs.toolchain.contains("gcc") configure: { if (isGcc) console.info("is gcc"); else console.info("is not gcc"); } } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/rtti-change-tracking/main.cpp0000644000175100017510000000001615232633614025645 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/0000755000175100017510000000000015232633614023165 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/script-interp-missing0000755000175100017510000000002215232633614027357 0ustar runnerrunner#!/does/not/exist qbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/script-interp-noexec0000755000175100017510000000002515232633614027172 0ustar runnerrunner#!$PWD/script-noexec qbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs0000644000175100017510000000252415232633614026651 0ustar runnerrunnerimport qbs.Host Project { property bool dummy: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } qbsSearchPaths: base.concat(["qbs"]) Product { Depends { name: "script-test" } name: "script-ok" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-missing" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/script-ok0000755000175100017510000000001215232633614025017 0ustar runnerrunner#!/bin/sh qbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/script-noexec0000644000175100017510000000000015232633614025661 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/qbs/0000755000175100017510000000000015232633614023752 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/0000755000175100017510000000000015232633614025422 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/0000755000175100017510000000000015232633614027703 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/script-test.qbs0000644000175100017510000000206115232633614032672 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Module { name: "script-test" Rule { inputs: ["script"] Artifact { filePath: FileInfo.joinPaths(project.buildDirectory, input.fileName) fileTags: ["application"] } prepare: { var cmds = []; var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { var tf = new TextFile(input.filePath, TextFile.ReadOnly); var s = tf.readAll().replace("$PWD", project.buildDirectory); tf.close(); var tf2 = new TextFile(output.filePath, TextFile.ReadWrite); tf2.write(s); tf2.close(); }; cmds.push(cmd); if (output.fileName !== "script-noexec") { var cmd2 = new Command("chmod", ["+x", output.filePath]); cmd2.silent = true; cmds.push(cmd2); } return cmds; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/0000755000175100017510000000000015232633614023503 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp0000644000175100017510000000236415232633614026217 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/empty.m0000644000175100017510000000003215232633614025012 0ustar runnerrunnerint main2() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs0000644000175100017510000000017715232633614027653 0ustar runnerrunnerCppApplication { Group { files: ["main.m"] fileTags: ["objcpp"] } cpp.frameworks: ["Foundation"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs0000644000175100017510000000013615232633614030426 0ustar runnerrunnerCppApplication { Group { files: ["main.cpp"] fileTags: ["objcpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/none.qbs0000644000175100017510000000023515232633614025151 0ustar runnerrunnerCppApplication { files: ["emptymain.cpp"] Group { condition: qbs.targetOS.includes("darwin") files: ["empty.m", "empty.mm"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/empty.mm0000644000175100017510000000003215232633614025167 0ustar runnerrunnerint main3() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs0000644000175100017510000000011415232633614027302 0ustar runnerrunnerCppApplication { files: ["main.m"] cpp.frameworks: ["Foundation"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/main.m0000644000175100017510000000011415232633614024601 0ustar runnerrunner#import int main() { @throw [NSError new]; } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/main.cpp0000644000175100017510000000300315232633614025127 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #if defined(__GNUC__) && !(defined(__cpp_exceptions) || defined(__EXCEPTIONS)) #error Exceptions are disabled! #endif int main() { #ifdef FORCE_FAIL_VS #error "Microsoft Visual C++ cannot disable exceptions at compile-time" #endif throw std::runtime_error("failed"); } qbs-src-3.3.1/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs0000644000175100017510000000026115232633614026372 0ustar runnerrunnerCppApplication { files: ["main.cpp"] cpp.treatWarningsAsErrors: true cpp.defines: qbs.toolchain.includes("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/0000755000175100017510000000000015232633614023303 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs0000644000175100017510000000246715232633614027113 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.TextFile Project { Probe { id: projectBuilder property stringList refs: [] property string sourceDir: sourceDirectory configure: { var tempDir = FileInfo.joinPaths(sourceDir, "temp"); File.makePath(tempDir); var srcDir = FileInfo.joinPaths(sourceDir, "src"); var projectDirs = File.directoryEntries(srcDir, File.Dirs | File.NoDotAndDotDot); var list = []; for (var it = 0; it < projectDirs.length; ++it) { var name = projectDirs[it]; var productSrcDir = FileInfo.joinPaths(srcDir, name); var productFilePath = FileInfo.joinPaths(tempDir, name + ".qbs"); var file = new TextFile(productFilePath, TextFile.WriteOnly); try { file.writeLine("CppApplication"); file.writeLine("{"); file.writeLine("\tfiles: [ \"" + productSrcDir + "/*.cpp\" ]"); file.writeLine("}"); } finally { file.close(); } list.push(productFilePath); } found = true; refs = list; } } references: projectBuilder.refs } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/src/0000755000175100017510000000000015232633614024072 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/src/app2/0000755000175100017510000000000015232633614024734 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/src/app2/main.cpp0000644000175100017510000000003115232633614026356 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/src/app/0000755000175100017510000000000015232633614024652 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/dynamic-project/src/app/main.cpp0000644000175100017510000000003115232633614026274 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/build-directories/0000755000175100017510000000000015232633614023624 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/build-directories/build-directories.qbs0000644000175100017510000000200315232633614027737 0ustar runnerrunnerProject { Product { name: "p1" type: "blubb1" Rule { multiplex: true outputFileTags: "blubb1" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.buildDirectory); } return cmd; } } } Product { name: "p2" type: "blubb2" Depends { name: "p1" } Rule { inputsFromDependencies: "blubb1" outputFileTags: "blubb2" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.buildDirectory); console.info(project.buildDirectory); console.info(project.sourceDirectory); } return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/no-exported-symbols/0000755000175100017510000000000015232633614024145 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/no-exported-symbols/lib.cpp0000644000175100017510000000003215232633614025412 0ustar runnerrunnerstatic void someFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs0000644000175100017510000000137115232633614030610 0ustar runnerrunnerProject { DynamicLibrary { name: "the_lib" Depends { name: "cpp" } files: ["lib.cpp", "lib.h"] Export { Depends { name: "cpp" } cpp.includePaths: path } Probe { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { if (toolchain.includes("msvc") && !toolchain.includes("clang-cl")) console.info("compiler is MSVC") else console.info("compiler is not MSVC") } } } CppApplication { name: "the_app" property bool link Depends { name: "the_lib"; cpp.link: product.link } files: "main.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/no-exported-symbols/lib.h0000644000175100017510000000011615232633614025062 0ustar runnerrunner#ifndef TEST_LIB #define TEST_LIB inline int success() { return 0; } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/no-exported-symbols/main.cpp0000644000175100017510000000006715232633614025600 0ustar runnerrunner#include int main() { return success(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-race-condition/0000755000175100017510000000000015232633614025642 5ustar runnerrunner././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition0000644000175100017510000000437315232633614033223 0ustar runnerrunnerProduct { name: "p" type: ["custom1", "custom2", "custom3", "custom4", "custom5"] Rule { multiplex: true outputFileTags: "custom1" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader1"; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { for (var t in product.artifacts) { var l = product.artifacts[t]; for (var j = 0; j < l.length; ++j) var fileName = l[j].fileName; } } }; return cmd; } } Rule { multiplex: true outputFileTags: "helper" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "helper"; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["helper"] outputFileTags: ["custom2", "custom3", "custom4"] outputArtifacts: { console.info("writer"); var artifacts = []; for (var i = 0; i < 1000; ++i) { artifacts.push({ filePath: "dummyt1" + i, fileTags: ["custom2"] }); artifacts.push({ filePath: "dummyt2" + i, fileTags: ["custom3"] }); artifacts.push({ filePath: "dummyt3" + i, fileTags: ["custom4"] }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "writer dummy command"; cmd.sourceCode = function() { }; return cmd; } } Rule { multiplex: true outputFileTags: "custom5" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader2"; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { for (var t in product.artifacts) { var l = product.artifacts[t]; for (var j = 0; j < l.length; ++j) var fileName = l[j].fileName; } } }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/0000755000175100017510000000000015232633614026307 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/0000755000175100017510000000000015232633614027757 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/amodule/0000755000175100017510000000000015232633614031405 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/amodule/m.qbs0000644000175100017510000000023515232633614032350 0ustar runnerrunnerimport qbs.File Module { Depends { name: "depmodule" } Properties { condition: File.exists("blubb") depmodule.prop: "blubb" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/depmodule/0000755000175100017510000000000015232633614031735 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/depmodule/m.qbs0000644000175100017510000000004415232633614032676 0ustar runnerrunnerModule { property string prop } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/import-in-properties-condition.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/import-in-properties-condition/import-in-properties-condi0000644000175100017510000000005415232633614033433 0ustar runnerrunnerProduct { Depends { name: "amodule" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/bool-value-in-profile/0000755000175100017510000000000015232633614024322 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/bool-value-in-profile/bool-value-in-profile.qbs0000644000175100017510000000001415232633614031133 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/blackbox/testdata/response-files/0000755000175100017510000000000015232633614023151 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/response-files/cat-response-file.cpp0000644000175100017510000000431015232633614027173 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include using namespace std; int main(int argc, char *argv[]) { if (argc < 3) { cerr << "cat-response-file: not enough arguments: " << argc - 1 << endl; return 1; } if (strlen(argv[2]) < 2) { cerr << "cat-response-file: second argument is too short: " << argv[2] << endl; return 2; } if (argv[2][0] != '@') { cerr << "cat-response-file: second argument does not start with @: " << argv[2] << endl; return 3; } ifstream inf(argv[2] + 1); if (!inf.is_open()) { cerr << "cat-response-file: cannot open input file " << argv[2] + 1 << endl; return 4; } ofstream ouf(argv[1]); if (!ouf.is_open()) { cerr << "cat-response-file: cannot open output file " << argv[1] << endl; return 5; } string line; while (getline(inf, line)) ouf << line << endl; inf.close(); ouf.close(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/response-files/response-files.qbs0000644000175100017510000000617015232633614026622 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host import qbs.TextFile Project { CppApplication { name: "cat-response-file" files: ["cat-response-file.cpp"] cpp.enableExceptions: true } Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "response-file-text" type: ["text"] Depends { name: "cpp" } Depends { name: "cat-response-file" } qbs.installPrefix: "" Group { fileTagsFilter: ["text"] qbs.install: true } Rule { inputsFromDependencies: ["application"] Artifact { filePath: "response-file-content.txt" fileTags: ["text"] } prepare: { var filePath = inputs["application"][0].filePath; var args = [output.filePath, "foo", "with space", "bar"]; var cmd = new Command(filePath, args); cmd.responseFileThreshold = 1; cmd.responseFileArgumentIndex = 1; cmd.responseFileUsagePrefix = '@'; cmd.silent = true; return cmd; } } } Product { name: "lotsofobjects" type: ["dynamiclibrary"] // clang-cl does not use response file internally, thus linker complains that command is // too long. This can be worked around by calling the linker directly Properties { condition: qbs.toolchain.includes("clang-cl") cpp.linkerMode: "manual" } Depends { name: "cpp" } Rule { multiplex: true outputFileTags: ["cpp"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 1000; ++i) artifacts.push({filePath: "source-" + i + ".cpp", fileTags: ["cpp"]}); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + outputs["cpp"].length + " dummy source files"; cmd.outputFilePaths = outputs["cpp"].map(function (a) { return a.filePath; }); cmd.sourceCode = function () { var index = 0; outputFilePaths.map(function (fp) { var tf = new TextFile(fp, TextFile.WriteOnly); try { tf.writeLine("extern int foo" + index + "() { return 0; }"); ++index; } finally { tf.close(); } }); }; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/host-os-properties/0000755000175100017510000000000015232633614024001 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/host-os-properties/main.cpp0000644000175100017510000000025015232633614025426 0ustar runnerrunner#include int main() { std::printf("HOST_ARCHITECTURE = %s\n", HOST_ARCHITECTURE); std::printf("HOST_PLATFORM = %s\n", HOST_PLATFORM); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs0000644000175100017510000000117115232633614030276 0ustar runnerrunnerimport qbs.Host CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } consoleApplication: true cpp.defines: [ 'HOST_ARCHITECTURE="' + Host.architecture() + '"', 'HOST_PLATFORM="' + Host.platform() + '"' ] files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/installpackage/0000755000175100017510000000000015232633614023175 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installpackage/lib.cpp0000644000175100017510000000237115232633614024452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/installpackage/installpackage.qbs0000644000175100017510000000206215232633614026666 0ustar runnerrunnerProject { CppApplication { name: "public_tool" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "mylib" } files: ["main.cpp"] installDir: "bin" installDebugInformation: false } CppApplication { name: "internal_tool" Depends { name: "mylib" } files: ["main.cpp"] } DynamicLibrary { Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "cpp" } name: "mylib" files: ["lib.cpp"] Group { name: "public headers" files: ["lib.h"] qbs.install: true qbs.installDir: "include" } installDir: "lib" installDebugInformation: false } InstallPackage { archiver.type: "tar" builtByDefault: true name: "tar-package" Depends { name: "public_tool" } Depends { name: "mylib" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/installpackage/lib.h0000644000175100017510000000256015232633614024117 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #ifdef MYLIB # define MYLIB_EXPORT DLL_EXPORT #else # define MYLIB_EXPORT DLL_IMPORT #endif MYLIB_EXPORT void f(); qbs-src-3.3.1/tests/auto/blackbox/testdata/installpackage/main.cpp0000644000175100017510000000240515232633614024626 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" int main() { f(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcard_renaming/0000755000175100017510000000000015232633614023664 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs0000644000175100017510000000014515232633614030044 0ustar runnerrunnerProduct { qbs.installPrefix: "" Group { qbs.install: true files: "*" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/wildcard_renaming/pioniere.txt0000644000175100017510000000000015232633614026225 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-with-dependencies/0000755000175100017510000000000015232633614025460 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs0000644000175100017510000000245015232633614033435 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Project { CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "helper-app" type: ["application", "test-helper"] consoleApplication: true install: true files: "helper-main.cpp" cpp.executableSuffix: ".exe" Group { fileTagsFilter: "application" fileTags: "test-helper" } } CppApplication { name: "test-app" type: ["application", "autotest"] Depends { name: "autotest" } files: "test-main.cpp" } AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } arguments: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, "bin") auxiliaryInputs: "test-helper" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-with-dependencies/test-main.cpp0000644000175100017510000000046415232633614030071 0ustar runnerrunner#include #include #include int main(int argc, char *argv[]) { std::cout << "i am the test app" << std::endl; const std::string fullHelperExe = std::string(argv[1]) + "/helper-app.exe"; return std::system(fullHelperExe.c_str()) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } qbs-src-3.3.1/tests/auto/blackbox/testdata/autotest-with-dependencies/helper-main.cpp0000644000175100017510000000014315232633614030363 0ustar runnerrunner#include int main() { std::cout << "i am the helper" << std::endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/0000755000175100017510000000000015232633614023645 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/qbs/0000755000175100017510000000000015232633614024432 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/qbs/imports/0000755000175100017510000000000015232633614026127 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/qbs/imports/CppApplication.qbs0000644000175100017510000000001415232633614031537 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/import-searchpath.qbs0000644000175100017510000000030215232633614030001 0ustar runnerrunnerProject { Project { qbsSearchPaths: ["qbs"] references: ["src/import-searchpath-app1.qbs"] } Project { references: ["src/import-searchpath-app2.qbs"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/src/0000755000175100017510000000000015232633614024434 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/src/import-searchpath-app1.qbs0000644000175100017510000000005715232633614031436 0ustar runnerrunnerCppApplication { files: ["somefile.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/src/somefile.cpp0000644000175100017510000000000015232633614026731 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/src/main.cpp0000644000175100017510000000001715232633614026062 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata/import-searchpath/src/import-searchpath-app2.qbs0000644000175100017510000000005315232633614031433 0ustar runnerrunnerCppApplication { files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata/out-of-date-marking/0000755000175100017510000000000015232633614023765 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/out-of-date-marking/main.c0000644000175100017510000000006015232633614025051 0ustar runnerrunner#include int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/out-of-date-marking/out-of-date-marking.qbs0000644000175100017510000000106115232633614030244 0ustar runnerrunnerimport qbs.TextFile CppApplication { name: "app" files: "main.c" cpp.includePaths: buildDirectory Rule { multiplex: true alwaysRun: true Artifact { filePath: "myheader.h"; fileTags: "hpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/error-info/0000755000175100017510000000000015232633614022275 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/error-info/helper.js0000644000175100017510000000016015232633614024107 0ustar runnerrunnervar x; function doSomethingBad() { nothinghere.works; } function doSomethingEvil() { throw "OUCH!"; } qbs-src-3.3.1/tests/auto/blackbox/testdata/error-info/error-info.qbs0000644000175100017510000000346415232633614025075 0ustar runnerrunnerimport "helper.js" as Helper Project { property bool fail1: false property bool fail2: false property bool fail3: false property bool fail4: false property bool fail5: false property bool fail6: false property bool fail7: false Product { name: "myproduct" type: ["foo", "bar"] Rule { multiplex: true Artifact { fileTags: ["foo"] filePath: { var path = "foo"; if (project.fail1) throw "fail1"; return path; } } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function () { }; cmd.silent = true; if (project.fail2) generate.an.error; if (project.fail6) Helper.doSomethingEvil(); return cmd; } } Rule { multiplex: true outputFileTags: ["bar"] outputArtifacts: { var list = []; list.push({ fileTags: ["bar"], filePath: "bar" }); if (project.fail3) throw "fail3"; if (project.fail5) Helper.doSomethingBad(); return list; } prepare: { var cmd = new JavaScriptCommand(); cmd.fail7 = project.fail7; cmd.sourceCode = function () { if (fail7) will.fail; }; cmd.silent = true; if (project.fail4) generate.an.error; return cmd; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-disabled-product/0000755000175100017510000000000015232633614025267 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-disabled-product/change-in-disabled-product.qbs0000644000175100017510000000014015232633614033045 0ustar runnerrunnerProduct { condition: false files: [ 'test1.txt', // 'test2.txt' ] } qbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-disabled-product/test2.txt0000644000175100017510000000000015232633614027057 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/change-in-disabled-product/test1.txt0000644000175100017510000000000015232633614027056 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/0000755000175100017510000000000015232633614025436 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/overrideProjectProperties.qbs0000644000175100017510000000245715232633614033400 0ustar runnerrunnerProject { property string nameSuffix: "" property bool someBool property int someInt property stringList someStringList Product { consoleApplication: true type: "application" property string mainFile: "" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } name: "MyApp" + nameSuffix Depends { name: "cpp" } files: { // Check types of the project's custom properties here. // Provoke a build error if the expected types do not match. var wrongFile = "doesnotexist.cpp"; if (typeof project.someBool != "boolean") { console.info("someBool has a wrong type: " + typeof project.someBool); return wrongFile; } if (typeof project.someInt != "number") { console.info("someInt has a wrong type: " + typeof project.someInt); return wrongFile; } if (typeof project.someStringList != "object") { console.info("someStringList has a wrong type: " + typeof project.someStringList); return wrongFile; } // Return the mainFile property that is set on the command line. return [mainFile]; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs0000644000175100017510000000031115232633614030245 0ustar runnerrunnerDynamicLibrary { name: "helperLib" files: "helperlib.cpp" Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/project_using_helper_lib.qbs0000644000175100017510000000046215232633614033207 0ustar runnerrunnerProject { property bool linkSuccessfully: false references: linkSuccessfully ? ["helper_lib.qbs"] : [] CppApplication { consoleApplication: true Depends { condition: project.linkSuccessfully name: "helperLib" } files: "main2.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/main2.cpp0000644000175100017510000000250515232633614027152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" void DLL_IMPORT helperFunc(); int main() { helperFunc(); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/main.cpp0000644000175100017510000000237015232633614027070 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/overrideProjectProperties/helperlib.cpp0000644000175100017510000000242715232633614030115 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" void DLL_EXPORT helperFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/smart-relinking/0000755000175100017510000000000015232633614023321 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs0000644000175100017510000000164215232633614027141 0ustar runnerrunnerProject { minimumQbsVersion: "1.6" Probe { id: tcProbe property stringList toolchain: qbs.toolchain property stringList targetOS: qbs.targetOS configure: { found = toolchain.includes("gcc") && targetOS.includes("unix"); if (!found) console.info("project disabled"); } } DynamicLibrary { condition: tcProbe.found name: "lib" property stringList defines: [] cpp.defines: defines Depends { name: "cpp" } files: ["lib.cpp"] } CppApplication { condition: tcProbe.found name:"app" Depends { name: "lib" } Depends { name: "staticlib" } files: ["main.cpp"] } StaticLibrary { condition: tcProbe.found name: "staticlib" Depends { name: "lib" } Depends { name: "cpp" } files: "staticlib.cpp" } } qbs-src-3.3.1/tests/auto/blackbox/testdata/smart-relinking/lib.cpp0000644000175100017510000000055315232633614024576 0ustar runnerrunner#include __attribute__ ((visibility ("default"))) void publicFunc() { #ifdef PRINTF std::printf("Tach\n"); #endif } __attribute__ ((visibility ("hidden"))) void privateFunc() { } #ifdef PRIV2 __attribute__ ((visibility ("hidden"))) void privateFunc2() { } #endif #ifdef PUB2 __attribute__ ((visibility ("default"))) void publicFunc2() { } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata/smart-relinking/main.cpp0000644000175100017510000000006515232633614024752 0ustar runnerrunnervoid publicFunc(); int main() { publicFunc(); } qbs-src-3.3.1/tests/auto/blackbox/testdata/smart-relinking/staticlib.cpp0000644000175100017510000000003015232633614025774 0ustar runnerrunnerstatic void myFunc() {} qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-process/0000755000175100017510000000000015232633614024423 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-process/main.cpp0000644000175100017510000000104115232633614026047 0ustar runnerrunner#include #include #include int main(int argc, char *argv[]) { if (argc != 2 || std::strcmp(argv[1], "help") != 0) { std::fprintf(stderr, "First argument to this program must be 'help'.\n"); return 1; } const char *env = std::getenv("SOME_ENV"); if (!env || std::strcmp(env, "why, hello!") != 0) { std::fprintf(stderr, "The SOME_ENV environment variable must be 'why, hello!'.\n"); return 1; } std::printf("qbs jsextensions-process test\n"); return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata/jsextensions-process/process.qbs0000644000175100017510000001153615232633614026616 0ustar runnerrunnerimport qbs.Environment import qbs.FileInfo import qbs.Host import qbs.Process import qbs.TextFile Project { Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } Depends { name: "cpp" } type: ["dummy"] name: "dummy" files: ["main.cpp"] Rule { multiplex: true inputs: ["application"] outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var exeFilePath = FileInfo.joinPaths(product.buildDirectory, product.cpp.executablePrefix + "dummy" + product.cpp.executableSuffix); // Synchronous run, successful. var process = new Process(); var pathVal = "why, hello!"; process.setEnv("SOME_ENV", pathVal); process.exec(exeFilePath, ["help"], true); var output = new TextFile("output.txt", TextFile.WriteOnly); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, successful. process = new Process(); process.setEnv("SOME_ENV", pathVal); output.writeLine(process.start(exeFilePath, ["help"])); output.writeLine(process.waitForFinished()); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, unsuccessful. process = new Process(); output.writeLine(process.errorString()); output.writeLine(process.start("blubb", [])); output.writeLine(process.errorString()); process.close(); // Synchronous run, unsuccessful. process = new Process(); output.writeLine(process.errorString()); output.writeLine(process.exec("blubb", [])); output.writeLine(process.errorString()); process.close(); // Synchronous run, unsuccessful (throw). process = new Process(); try { process.exec("blubb", [], true); } catch (e) { output.writeLine(e); } finally { process.close(); } // closeWriteChannel test process = new Process(); if (Host.os().includes("windows")) process.start(product.qbs.windowsShellPath, ["/C", product.qbs.windowsSystemRoot + "\\system32\\sort.exe"]); else process.start("cat", []); process.writeLine("should be"); process.closeWriteChannel(); process.writeLine("should not be"); if (!process.waitForFinished()) process.kill(); output.write(process.readStdOut()); process.close(); // readLine and atEnd var testReadlineFile = new TextFile("123.txt", TextFile.WriteOnly); testReadlineFile.writeLine("1"); testReadlineFile.writeLine("2"); testReadlineFile.writeLine("3"); testReadlineFile.close(); process = new Process(); if (Host.os().includes("windows")) process.exec(product.qbs.windowsShellPath, ["/C", "type", "123.txt"], true); else process.exec("cat", ["123.txt"], true); while(!process.atEnd()) output.write(process.readLine()); // TODO: Test all the other Process methods as well. output.close(); }; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/0000755000175100017510000000000015232633614027356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/0000755000175100017510000000000015232633614031026 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/m/0000755000175100017510000000000015232633614031262 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/m/m.qbs0000644000175100017510000000025115232633614032223 0ustar runnerrunnerModule { property bool doFail Depends { name: "cpp" } cpp.libraries: ["nosuchlib"] validate: { if (doFail) throw "Failure!"; } } qbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/main.cpp0000644000175100017510000000001615232633614031003 0ustar runnerrunnerint main() {} ././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/property-assignment-in-failed-module.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/property-assignment-0000644000175100017510000000014415232633614033407 0ustar runnerrunnerCppApplication { name: "app" Depends { name: "m"; required: false } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata/installed-transformer-output/0000755000175100017510000000000015232633614026070 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs0000644000175100017510000000141215232633614027626 0ustar runnerrunnerimport qbs.TextFile Product { name: "install-test" type: ["text"] qbs.installPrefix: "" Group { qbs.install: true qbs.installDir: "textfiles" fileTagsFilter: "text" } Rule { multiplex: true Artifact { filePath: "HelloWorld.txt" fileTags: ["text"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating file:'" + output.fileName + "'"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.writeLine("Hello World!") file.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata/not-always-updated/0000755000175100017510000000000015232633614023735 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata/not-always-updated/not-always-updated.qbs0000644000175100017510000000137115232633614030170 0ustar runnerrunnerimport qbs.TextFile Product { type: "p" Rule { multiplex: true Artifact { filePath: "dummy.txt"; fileTags: "t1"; alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating dummy"; cmd.sourceCode = function() {}; return cmd; } } Rule { inputs: "t1" Artifact { filePath: "o.txt"; fileTags: "p" } prepare: { var cmd = new JavaScriptCommand; cmd.description = "creating final"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxexamples.h0000644000175100017510000000363015232633614022773 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOXEXAMPLES_H #define TST_BLACKBOXEXAMPLES_H #include "tst_blackboxbase.h" class TestBlackboxExamples : public TestBlackboxBase { Q_OBJECT private: QStringList collectExamples(const QString &dirPath); public: TestBlackboxExamples(); private slots: void baremetal_data(); void baremetal(); void examples_data(); void examples(); }; #endif // TST_BLACKBOXEXAMPLES_H qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/0000755000175100017510000000000015232633614020635 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/0000755000175100017510000000000015232633614023766 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs0000644000175100017510000000357115232633614027634 0ustar runnerrunnerimport qbs.Host import qbs.Utilities Project { QtApplication { condition: { if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { // qt4 moc can't be used with pluginMetaData console.info("using qt4"); return false; } var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "app" consoleApplication: true Depends { name: "thePlugin" } cpp.cxxLanguageVersion: "c++11" Properties { condition: qbs.targetOS.includes("unix") cpp.rpaths: [cpp.rpathOrigin] } config.install.binariesDirectory: "" files: ["app.cpp"] } Library { type: Qt.core.staticBuild ? "staticlibrary" : "dynamiclibrary" name: "thePlugin" Depends { name: "cpp" } Depends { name: "Qt.core" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.defines: [Qt.core.staticBuild ? "QT_STATICPLUGIN" : "QT_PLUGIN"] cpp.cxxLanguageVersion: "c++11" cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.includePaths: ["."] Qt.core.pluginMetaData: ["theKey=theValue"] config.install.dynamicLibrariesDirectory: "" config.install.staticLibrariesDirectory: "" files: ["theplugin.cpp"] Group { files: ["metadata.json"] fileTags: ["qt_plugin_metadata"] } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/metadata.json0000644000175100017510000000005015232633614026434 0ustar runnerrunner{ "theOtherKey" : "theOtherValue" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/app.cpp0000644000175100017510000000523115232633614025253 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #ifdef QT_STATIC Q_IMPORT_PLUGIN(ThePlugin) #endif int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QJsonObject metaData; for (const QStaticPlugin &p : QPluginLoader::staticPlugins()) { const QJsonObject &md = p.metaData(); if (md.value("className") == "ThePlugin") { metaData = md; break; } } #ifdef QT_STATIC if (metaData.isEmpty()) { qDebug() << "no static metadata"; return 1; } #else if (!metaData.isEmpty()) { qDebug() << "static metadata"; return 1; } #endif if (metaData.isEmpty()) metaData = QPluginLoader("thePlugin").metaData(); const QJsonValue v = metaData.value(QStringLiteral("theKey")); if (!v.isArray()) { qDebug() << "value is" << v; return 1; } const QJsonArray a = v.toArray(); if (a.size() != 1 || a.first() != QLatin1String("theValue")) { qDebug() << "value is" << v; return 1; } const QJsonValue v2 = metaData.value(QStringLiteral("MetaData")).toObject() .value(QStringLiteral("theOtherKey")); if (v2.toString() != QLatin1String("theOtherValue")) { qDebug() << "metadata:" << metaData; return 1; } qDebug() << "all ok!"; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/theplugin.cpp0000644000175100017510000000263715232633614026501 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include class ThePlugin : public QObject { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qbs.ThePlugin" FILE "metadata.json") }; #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/0000755000175100017510000000000015232633614023713 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/car.xml0000644000175100017510000000062415232633614025204 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.h0000644000175100017510000000330015232633614026243 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONTROLLER_H #define CONTROLLER_H #include "ui_controller.h" #include "car_interface.h" class Controller : public QWidget { Q_OBJECT public: Controller(QWidget *parent = nullptr); protected: void timerEvent(QTimerEvent *event); private slots: void on_accelerate_clicked(); void on_decelerate_clicked(); void on_left_clicked(); void on_right_clicked(); private: Ui::Controller ui; org::example::Examples::CarInterface *car; }; #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.qbs0000644000175100017510000000065015232633614026606 0ustar runnerrunnerCppApplication { name: "controller" condition: Qt.dbus.present Depends { name: "Qt.dbus"; required: false } Depends { name: "Qt.widgets" } cpp.cxxLanguageVersion: "c++11" files: [ "controller.cpp", "controller.h", "controller.ui", "main.cpp", ] Group { name: "DBUS Interface" files: ["car.xml"] fileTags: ["qt.dbus.interface"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.ui0000644000175100017510000000276215232633614026444 0ustar runnerrunner Controller 0 0 255 111 Controller 9 6 Controller Qt::AlignCenter Decelerate Accelerate Right Left qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp0000644000175100017510000000625715232633614026614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include "controller.h" #include "car_interface.h" Controller::Controller(QWidget *parent) : QWidget(parent) { ui.setupUi(this); car = new org::example::Examples::CarInterface("org.example.CarExample", "/Car", QDBusConnection::sessionBus(), this); startTimer(1000); } void Controller::timerEvent(QTimerEvent *event) { Q_UNUSED(event); if (car->isValid()) ui.label->setText("connected"); else ui.label->setText("disconnected"); } void Controller::on_accelerate_clicked() { car->accelerate(); } void Controller::on_decelerate_clicked() { car->decelerate(); } void Controller::on_left_clicked() { car->turnLeft(); } void Controller::on_right_clicked() { car->turnRight(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp0000644000175100017510000000531015232633614025342 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #else #include > #endif #include #include "controller.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Controller controller; controller.show(); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/0000755000175100017510000000000015232633614024253 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h0000644000175100017510000000561615232633614025742 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef PERSON_H #define PERSON_H #include #include //![0] class Person : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) QML_ELEMENT public: Person(QObject *parent = nullptr); QString name() const; void setName(const QString &); int shoeSize() const; void setShoeSize(int); private: QString m_name; int m_shoeSize; }; //![0] #endif // PERSON_H qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp0000644000175100017510000000534415232633614026273 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "person.h" // ![0] Person::Person(QObject *parent) : QObject(parent), m_shoeSize(0) { } QString Person::name() const { return m_name; } void Person::setName(const QString &n) { m_name = n; } int Person::shoeSize() const { return m_shoeSize; } void Person::setShoeSize(int s) { m_shoeSize = s; } // ![0] qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs0000644000175100017510000000126415232633614030403 0ustar runnerrunnerimport qbs.Utilities CppApplication { name: "myapp" Depends { name: "Qt.qml" } Qt.qml.importVersion: "1" cpp.includePaths: sourceDirectory qbs.installPrefix: "" files: [ "main.cpp", "person.cpp", "person.h", ] Group { files: "example.qml" fileTags: "qt.core.resource_data" } Probe { id: versionProbe property string version: Qt.core.version configure: { if (Utilities.versionCompare(version, "5.15") >= 0) console.info("has registrar"); else console.info("does not have registrar"); found = true; } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp0000644000175100017510000000573515232633614025715 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "person.h" int main(int argc, char ** argv) { QCoreApplication app(argc, argv); QQmlEngine engine; QQmlComponent component(&engine, QUrl("qrc:example.qml")); auto *person = qobject_cast(component.create()); if (person) { qWarning() << "The person's name is" << person->name(); qWarning() << "They wear a" << person->shoeSize() << "sized shoe"; } else { qWarning() << component.errors(); } return EXIT_SUCCESS; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml0000644000175100017510000000475415232633614026433 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // ![0] import People 1.0 Person { name: "Bob Jones" shoeSize: 12 } // ![0] qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackQObjChange/0000755000175100017510000000000015232633614023623 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackQObjChange/i.qbs0000644000175100017510000000064215232633614024564 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "i" property bool dummy: { console.info("object suffix: " + cpp.objectSuffix); console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.h" ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla.cpp0000644000175100017510000000247115232633614025071 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "bla.h" int main() { MyObject obj; obj.setObjectName("I am the object!"); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla_noqobject.h0000644000175100017510000000242515232633614026601 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla_qobject.h0000644000175100017510000000244215232633614026243 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qdoc/0000755000175100017510000000000015232633614021563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc0000644000175100017510000000012415232633614023356 0ustar runnerrunner/*! \page index.html \title QDoc Test QDoc Test is a test for QDoc. */qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs0000644000175100017510000000152015232633614023216 0ustar runnerrunnerimport qbs.Host import qbs.Utilities Product { condition: { if (Utilities.versionCompare(Qt.core.version, "5.0.0") < 0) { console.info("Qt is too old"); return false; } if (qbs.targetPlatform !== Host.platform() || qbs.architecture !== Host.architecture()) { console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return false; } return true; } name: "QDoc Test" type: ["qdoc-html", "qch"] Depends { name: "Qt.core" } files: ["qdoc.qdoc"] Group { name: "main qdocconf file" files: "qdoc.qdocconf" fileTags: "qdocconf-main" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf0000644000175100017510000000043015232633614024224 0ustar runnerrunnerproject = QDoc Test description = QDoc Test headerdirs = . sourcedirs = . exampledirs = . outputdir = doc/html qhp.projects = QDocTest qhp.QDocTest.file = qdoctest.qhp qhp.QDocTest.namespace = org.qt-project.QDocTest qhp.QDocTest.virtualFolder = doc qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools-linking/0000755000175100017510000000000015232633614024615 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools-linking/shader.frag0000644000175100017510000000021315232633614026720 0ustar runnerrunner#version 440 precision mediump float; layout(location = 0) out vec4 fragColor; void main() { fragColor = vec4(1.0, 0.0, 0.0, 1.0); }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools-linking/shadertools-linking.qbs0000644000175100017510000000032115232633614031300 0ustar runnerrunnerimport qbs QtApplication { name: "shadertools-linking-test" type: "application" Depends { name: "Qt.shadertools" } files: ["shader.frag", "main.cpp"] Qt.shadertools.enableLinking: true }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools-linking/main.cpp0000644000175100017510000000027115232633614026245 0ustar runnerrunner#include #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); return 0; }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qtscxml/0000755000175100017510000000000015232633614022330 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs0000644000175100017510000000437615232633614024544 0ustar runnerrunnerimport qbs.Environment import qbs.FileInfo import qbs.Host import qbs.Utilities Project { QtApplication { name: "app" Depends { name: "Qt.scxml"; required: false } Properties { condition: Qt.scxml.present && Utilities.versionCompare(Qt.core.version, "5.13.0") != 0 cpp.defines: ["HAS_QTSCXML"] } Qt.scxml.className: "QbsStateMachine" Qt.scxml.namespace: "QbsTest" Qt.scxml.generateStateMethods: true files: ["main.cpp"] Group { files: ["dummystatemachine.scxml"] fileTags: ["qt.scxml.compilable"] } } Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "runner" type: ["runner"] Depends { name: "app" } Rule { inputsFromDependencies: ["application"] outputFileTags: ["runner"] prepare: { var cmd = new Command(input.filePath); cmd.description = "running " + input.filePath; var envVars = {}; if (Host.os().includes("windows")) { envVars["PATH"] = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); } else if (Host.os().includes("macos")) { envVars["DYLD_LIBRARY_PATH"] = input["Qt.core"].libPath; envVars["DYLD_FRAMEWORK_PATH"] = input["Qt.core"].libPath; } else { envVars["LD_LIBRARY_PATH"] = input["Qt.core"].libPath; } for (var varName in envVars) { var oldValue = Environment.getEnv(varName) || ""; var newValue = envVars[varName] + FileInfo.pathListSeparator() + oldValue; cmd.environment.push(varName + '=' + newValue); } return [cmd]; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qtscxml/main.cpp0000644000175100017510000000045515232633614023764 0ustar runnerrunner#ifdef HAS_QTSCXML #include #endif #include int main() { #ifdef HAS_QTSCXML QbsTest::QbsStateMachine machine; std::cout << "state machine name: " << qPrintable(machine.name()) << std::endl; #else std::cout << "QtScxml not present" << std::endl; #endif } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qtscxml/dummystatemachine.scxml0000644000175100017510000000016615232633614027124 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/0000755000175100017510000000000015232633614024716 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/moc-and-cxx-combining.qbs0000644000175100017510000000015015232633614031502 0ustar runnerrunnerQtApplication { cpp.combineCxxSources: true files: ["main.cpp", "myobject.h", "myobject.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/main.cpp0000644000175100017510000000007115232633614026344 0ustar runnerrunner#include "myobject.h" int main() { useMyObject(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/myobject.h0000644000175100017510000000010315232633614026675 0ustar runnerrunner#ifndef MYOBJECT_H #define MYOBJECT_H void useMyObject(); #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/myobject.cpp0000644000175100017510000000027215232633614027237 0ustar runnerrunner#include "myobject.h" #include class MyObject : public QObject { Q_OBJECT public: void use() {} }; void useMyObject() { MyObject().use(); } #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/create-project/0000755000175100017510000000000015232633614023544 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/create-project/dummy.txt0000644000175100017510000000000015232633614025426 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/0000755000175100017510000000000015232633614023405 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.h0000644000175100017510000000351015232633614024322 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CAR_H #define CAR_H #include #include class Car : public QGraphicsObject { Q_OBJECT public: Car(); QRectF boundingRect() const; public Q_SLOTS: void accelerate(); void decelerate(); void turnLeft(); void turnRight(); Q_SIGNALS: void crashed(); protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); void timerEvent(QTimerEvent *event); private: QBrush color; qreal wheelsAngle; // used when applying rotation qreal speed; // delta movement along the body axis }; #endif // CAR_H qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp0000644000175100017510000001135515232633614024663 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "car.h" #include #include static const double Pi = 3.14159265358979323846264338327950288419717; QRectF Car::boundingRect() const { return {-35, -81, 70, 115}; } Car::Car() : color(Qt::green), wheelsAngle(0), speed(0) { startTimer(1000 / 33); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsFocusable, true); } void Car::accelerate() { if (speed < 10) ++speed; } void Car::decelerate() { if (speed > -10) --speed; } void Car::turnLeft() { if (wheelsAngle > -30) wheelsAngle -= 5; } void Car::turnRight() { if (wheelsAngle < 30) wheelsAngle += 5; } void Car::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(Qt::gray); painter->drawRect(-20, -58, 40, 2); // front axel painter->drawRect(-20, 7, 40, 2); // rear axel painter->setBrush(color); painter->drawRect(-25, -79, 50, 10); // front wing painter->drawEllipse(-25, -48, 50, 20); // side pods painter->drawRect(-25, -38, 50, 35); // side pods painter->drawRect(-5, 9, 10, 10); // back pod painter->drawEllipse(-10, -81, 20, 100); // main body painter->drawRect(-17, 19, 34, 15); // rear wing painter->setBrush(Qt::black); painter->drawPie(-5, -51, 10, 15, 0, 180 * 16); painter->drawRect(-5, -44, 10, 10); // cocpit painter->save(); painter->translate(-20, -58); painter->rotate(wheelsAngle); painter->drawRect(-10, -7, 10, 15); // front left painter->restore(); painter->save(); painter->translate(20, -58); painter->rotate(wheelsAngle); painter->drawRect(0, -7, 10, 15); // front left painter->restore(); painter->drawRect(-30, 0, 12, 17); // rear left painter->drawRect(19, 0, 12, 17); // rear right } void Car::timerEvent(QTimerEvent *event) { Q_UNUSED(event); const qreal axelDistance = 54; qreal wheelsAngleRads = (wheelsAngle * Pi) / 180; qreal turnDistance = ::cos(wheelsAngleRads) * axelDistance * 2; qreal turnRateRads = wheelsAngleRads / turnDistance; // rough estimate qreal turnRate = (turnRateRads * 180) / Pi; qreal rotation = speed * turnRate; setTransform(QTransform().rotate(rotation), true); setTransform(QTransform::fromTranslate(0, -speed), true); update(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/THIS.IS.A.STRANGE.FILENAME.CAR.XML0000644000175100017510000000062415232633614030116 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp0000644000175100017510000000663015232633614025042 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "car.h" #include "car_adaptor.h" #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #include #include #else #include #include #include #endif #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QGraphicsScene scene; scene.setSceneRect(-500, -500, 1000, 1000); scene.setItemIndexMethod(QGraphicsScene::NoIndex); const auto car = new Car(); scene.addItem(car); QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(Qt::darkGray); view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Qt DBus Controlled Car")); view.resize(400, 300); view.show(); new CarInterfaceAdaptor(car); QDBusConnection connection = QDBusConnection::sessionBus(); connection.registerObject("/Car", car); connection.registerService("org.example.CarExample"); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.qbs0000644000175100017510000000062115232633614024660 0ustar runnerrunnerCppApplication { name: "car" condition: Qt.dbus.present cpp.cxxLanguageVersion: "c++11" Depends { name: "Qt.dbus"; required: false } Depends { name: "Qt.widgets" } files: [ "car.cpp", "car.h", "main.cpp", ] Group { name: "DBUS Adaptor" files: ["THIS.IS.A.STRANGE.FILENAME.CAR.XML"] fileTags: ["qt.dbus.adaptor"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-xml/0000755000175100017510000000000015232633614022057 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-xml/qt-xml.qbs0000644000175100017510000000021715232633614024010 0ustar runnerrunnerCppApplication { Depends { name: "Qt.core" } Depends { name: "Qt.xml" } cpp.cxxLanguageVersion: ["c++20"] files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-xml/main.cpp0000644000175100017510000000077715232633614023522 0ustar runnerrunner#include #include #include void testDom() { QDomDocument doc("test"); QDomElement element = doc.createElement("element"); element.setAttribute("attr", "foo"); doc.appendChild(element); qDebug() << doc.toString(); } int main(int argc, char *argv[]) { QCoreApplication::setApplicationName("LinkFailureTest"); QCoreApplication::setApplicationVersion("1.0.0"); QCoreApplication app(argc, argv); testDom(); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/0000755000175100017510000000000015232633614021422 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/bla.qrc0000644000175100017510000000016515232633614022671 0ustar runnerrunner stuff.txt subdir/ qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/stuff.txt0000644000175100017510000000002015232633614023302 0ustar runnerrunnera resource file qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/test.cpp0000644000175100017510000000001715232633614023103 0ustar runnerrunnervoid test() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/i.qbs0000644000175100017510000000172615232633614022367 0ustar runnerrunnerimport qbs.Host import qbs.Utilities Project { Product { condition: { if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { console.info("using qt4"); return false; } var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); console.info("executable suffix: " + cpp.executableSuffix); return result; } consoleApplication: true type: "application" name: "i" Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.qrc", //"test.cpp", ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/bla.cpp0000644000175100017510000000273115232633614022667 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { QFileInfo f(":/stuff.txt"); if (!f.exists()) return 1; if (!f.isFile()) return 2; QFileInfo d(":/subdir"); if (!d.exists()) return 3; if (!d.isDir()) return 4; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/subdir/0000755000175100017510000000000015232633614022712 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qrc/subdir/dummy.txt0000644000175100017510000000000015232633614024574 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/0000755000175100017510000000000015232633614022273 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt1-test.cpp0000644000175100017510000000010415232633614024454 0ustar runnerrunner#include H::H() { const auto s = tr("H message"); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt2-main.cpp0000644000175100017510000000026515232633614024432 0ustar runnerrunner#include class M : public QObject { Q_OBJECT public: M() { auto s = tr("M message"); // auto s2 = tr("M message 2"); } }; int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt1-dummy2.cpp0000644000175100017510000000002315232633614024712 0ustar runnerrunnerstatic void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/noqt-main.cpp0000644000175100017510000000001615232633614024677 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt2-new.cpp0000644000175100017510000000015615232633614024276 0ustar runnerrunner#include class N : public QObject { Q_OBJECT public: N() { auto s = tr("N message"); } }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt1-dummy.cpp0000644000175100017510000000002315232633614024630 0ustar runnerrunnerstatic void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt2-dummy2.cpp0000644000175100017510000000002315232633614024713 0ustar runnerrunnerstatic void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/lupdate_de_DE.ts0000644000175100017510000000013715232633614025322 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/input.txt0000644000175100017510000000017615232633614024177 0ustar runnerrunner#include class C : public QObject { Q_OBJECT public: C() { auto s = tr("C message"); } }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt2-dummy.cpp0000644000175100017510000000002315232633614024631 0ustar runnerrunnerstatic void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/lupdate.qbs0000644000175100017510000000471315232633614024445 0ustar runnerrunnerimport qbs.File Project { QtApplication { name: "qt1" Depends { name: "Qt.widgets" } /*cpp.includePaths: "subdir"*/ // cpp.cxxLanguageVersion: "c++17" Group { name: "ignored" files: "qt1-main.cpp" fileTags: ["cpp", "qt.untranslatable"] } Group { name: "with extra include path" cpp.includePaths: outer.concat("subdir") files: "qt1-test.cpp" } Group { name: "translatable generator input" files: "input.txt" fileTags: "cpp.in" } Group { name: "non-translatable generator input" files: "input2.txt" fileTags: "cpp.in.nontranslatable" } files: [ "mainwindow.ui", "qt1-dummy.cpp", "qt1-dummy2.cpp", "subdir/header.h", ] Rule { inputs: "cpp.in" Artifact { filePath: "generated_" + input.baseName + ".cpp"; fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "filegen"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: "cpp.in.nontranslatable" Artifact { filePath: "generated_" + input.baseName + ".cpp"; fileTags: ["cpp", "qt.untranslatable"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "filegen"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } QtApplication { name: "qt2" Depends { name: "qt1" } // Tests "minimal" propagation in Executor files: [ "qt2-dummy.cpp", "qt2-dummy2.cpp", "qt2-main.cpp", /*"qt2-new.cpp"*/ ] } CppApplication { name: "noqt" Depends { name: "qt2" } // Tests "minimal" propagation in Executor files: "noqt-main.cpp" } Product { name: "translations" Depends { name: "Qt.core" } files: "lupdate_de_DE.ts" } QtLupdateRunner {} } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/subdir/0000755000175100017510000000000015232633614023563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/subdir/header.h0000644000175100017510000000012115232633614025156 0ustar runnerrunner#include class H : public QObject { Q_OBJECT public: H(); }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/qt1-main.cpp0000644000175100017510000000001615232633614024423 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/mainwindow.ui0000644000175100017510000000120215232633614025001 0ustar runnerrunner MainWindow 0 0 800 600 The title 0 0 800 19 qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lupdate/input2.txt0000644000175100017510000000020415232633614024251 0ustar runnerrunner#include class C : public QObject { Q_OBJECT public: C() { auto s = tr("ignored message"); } }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/0000755000175100017510000000000015232633614024412 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.cpp0000644000175100017510000000014115232633614025660 0ustar runnerrunner#include #include "lib.h" SymbolsTest::SymbolsTest() { // qDebug() << "hallo"; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs0000644000175100017510000000163215232633614027570 0ustar runnerrunnerProject { CppApplication { name: "app" Depends { name: "lib" } Depends { name: "Qt.core" } property bool dummy: { var isGCC = qbs.toolchain.includes("gcc") && !qbs.toolchain.includes("emscripten") console.info("is GCC: " + isGCC); console.info("is MinGW: " + qbs.toolchain.includes("mingw")); console.info("is Darwin: " + qbs.targetOS.includes("darwin")); console.info("is emscripten: " + qbs.toolchain.contains("emscripten")); console.info("is static qt: " + Qt.core.staticBuild); } files: "main.cpp" } DynamicLibrary { name: "lib" Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" cpp.defines: "SYMBOLSTEST_LIBRARY" files: [ "lib.cpp", "lib.h", ] Export { Depends { name: "Qt.core" } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.h0000644000175100017510000000045715232633614025337 0ustar runnerrunner#ifndef SYMBOLSTEST_H #define SYMBOLSTEST_H #include #if defined(SYMBOLSTEST_LIBRARY) # define SYMBOLSTEST_EXPORT Q_DECL_EXPORT #else # define SYMBOLSTEST_EXPORT Q_DECL_IMPORT #endif class SYMBOLSTEST_EXPORT SymbolsTest { public: SymbolsTest(); }; #endif // SYMBOLSTEST_H qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/main.cpp0000644000175100017510000000001715232633614026040 0ustar runnerrunnerint main() { } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/0000755000175100017510000000000015232633614023561 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/0000755000175100017510000000000015232633614024352 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/subdir/0000755000175100017510000000000015232633614025642 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/subdir/test.qml0000644000175100017510000000003615232633614027333 0ustar runnerrunnerimport QtQuick 2.0 Item { } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs0000644000175100017510000000110015232633614027204 0ustar runnerrunnerCppApplication { Depends { name: "Qt.quick" // Must fail when using Qt4 versionAtLeast: "5" } Qt.quick.useCompiler: Qt.quick.compilerAvailable cpp.cxxLanguageVersion: "c++11" Probe { id: qtQuickCompilerProbe property bool hasCompiler: Qt.quick.compilerAvailable configure: { if (hasCompiler) console.info("compiler available"); else console.info("compiler not available"); } } files: [ "main.cpp", "qml.qrc", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/main.cpp0000644000175100017510000000063715232633614025217 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/qml/subdir/test.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml.qrc0000644000175100017510000000014215232633614025056 0ustar runnerrunner qml/subdir/test.qml qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-flags/0000755000175100017510000000000015232633614022505 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-flags/blubb.h0000644000175100017510000000251715232633614023751 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class Blubb : public QObject { Q_OBJECT public: Blubb() { } void makeBlubb() { } }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-flags/main.cpp0000644000175100017510000000242715232633614024142 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "blubb.h" int main() { Blubb().makeBlubb(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-flags/moc-flags.qbs0000644000175100017510000000006515232633614025065 0ustar runnerrunnerQtApplication { files: ["main.cpp", "blubb.h"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig/0000755000175100017510000000000015232633614022604 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig/main.cpp0000644000175100017510000000303015232633614024230 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef QT_CORE_LIB #include #include #else #include #endif int main(int argc, char **argv) { #ifdef QT_CORE_LIB QCoreApplication app(argc, argv); qDebug() << "Hello world!"; #else (void)argc; (void)argv; std::cout << "Skip this test" << std::endl; #endif } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs0000644000175100017510000000152115232633614025261 0ustar runnerrunnerimport qbs.Host import qbs.Probes Project { property string name: 'pkgconfig' CppApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: project.name Probes.PkgConfigProbe { id: pkgConfig name: "QtCore" minVersion: '4.0.0' maxVersion: '5.99.99' } files: 'main.cpp' cpp.cxxFlags: pkgConfig.cflags cpp.linkerFlags: pkgConfig.libs } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/0000755000175100017510000000000015232633614023226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/pkgconfig-qt.qbs0000644000175100017510000000016515232633614026330 0ustar runnerrunnerQtApplication { name: "p" files: "main.cpp" qbsSearchPaths: "." qbsModuleProviders: "qbspkgconfig" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/main.cpp0000644000175100017510000000001615232633614024653 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/dump-libpath.qbs0000644000175100017510000000017015232633614026321 0ustar runnerrunnerQtApplication { files: "main.cpp" property bool test: { console.info("libPath="+Qt.core.libPath) } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/module-providers/0000755000175100017510000000000015232633614026526 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/pkgconfig-qt/module-providers/dummyProvider.qbs0000644000175100017510000000005715232633614032105 0ustar runnerrunnerModuleProvider { relativeSearchPaths: "" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/0000755000175100017510000000000015232633614023277 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/main.mm0000644000175100017510000000017415232633614024560 0ustar runnerrunner#include class Foo : public QObject { Q_OBJECT }; int main() { Foo foo; return 0; } #include "main.moc" qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/qobject-in-mm.qbs0000644000175100017510000000011215232633614026442 0ustar runnerrunnerCppApplication { Depends { name: "Qt.core" } files: ["main.mm"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/0000755000175100017510000000000015232633614023645 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs0000644000175100017510000000165115232633614027367 0ustar runnerrunnerimport qbs.Utilities QtGuiApplication { condition: { // pluginTypes empty for Qt4 if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { console.info("using qt4"); return false; } return true; } Probe { id: staticProbe property bool isStaticQt: Qt.gui.isStaticLibrary property var plugins: Qt.plugin_support.effectivePluginsByType property var allPlugins: Qt.plugin_support.allPluginsByType configure: { console.info("static Qt: " + isStaticQt); console.info("requested image plugins: %" + plugins.imageformats + "%"); console.info("all image plugins: #" + allPlugins.imageformats + "#"); console.info("platform plugin count: " + (plugins.platforms || []).length); } } Depends { name: "m1" } Depends { name: "m2" } files: "plugin-support-main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/0000755000175100017510000000000015232633614025315 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m2/0000755000175100017510000000000015232633614025633 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m2/m2.qbs0000644000175100017510000000044315232633614026661 0ustar runnerrunnerModule { Depends { name: "Qt.plugin_support" } Properties { condition: Qt.plugin_support.allPluginsByType && Qt.plugin_support.allPluginsByType.imageformats Qt.plugin_support.pluginsByType: ({imageformats: Qt.plugin_support.allPluginsByType.imageformats[1]}) } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m1/0000755000175100017510000000000015232633614025632 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m1/m1.qbs0000644000175100017510000000066415232633614026664 0ustar runnerrunnerModule { property bool useDummy Depends { name: "Qt.plugin_support" } Properties { condition: useDummy Qt.plugin_support.pluginsByType: ({imageformats: "dummy"}) } Properties { condition: Qt.plugin_support.allPluginsByType && Qt.plugin_support.allPluginsByType.imageformats Qt.plugin_support.pluginsByType: ({imageformats: Qt.plugin_support.allPluginsByType.imageformats[0]}) } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support-main.cpp0000644000175100017510000000001615232633614030300 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/0000755000175100017510000000000015232633614024665 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/main.cpp0000644000175100017510000000242315232633614026316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { qDebug("Tach."); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs0000644000175100017510000000066115232633614031427 0ustar runnerrunnerProject { Probe { id: tcProbe property bool isMsvc: qbs.toolchain.contains("msvc") configure: { console.info("is msvc: " + isMsvc); } } QtApplication { Properties { condition: qbs.toolchain.includes("msvc") Qt.core.qtBuildVariant: "release" qbs.buildVariant: "debug" } Qt.core.qtBuildVariant: "dummy" files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/unmocable/0000755000175100017510000000000015232633614022602 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/unmocable/foo.h0000644000175100017510000000007315232633614023536 0ustar runnerrunner#define Q_OBJECT 156 int someNumber() { return Q_OBJECT; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/unmocable/main.cpp0000644000175100017510000000010015232633614024221 0ustar runnerrunner#include "foo.h" int main() { return someNumber() - 156; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/unmocable/unmocable.qbs0000644000175100017510000000025715232633614025262 0ustar runnerrunnerApplication { Depends { name: "Qt.core" } files: ["main.cpp"] Group { files: ["foo.h"] fileTags: ["unmocable"] overrideTags: false } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/emscripten-html/0000755000175100017510000000000015232633614023750 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/emscripten-html/emscripten-html.qbs0000644000175100017510000000056415232633614027577 0ustar runnerrunnerProduct { name: "app" type: generateHtml ? ["application", "qthtml"] : ["application"] Depends { name: "Qt.core" } files: "main.cpp" property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } property bool generateHtml: false Group { fileTagsFilter: ["qthtml"] qbs.install: true } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/emscripten-html/main.cpp0000644000175100017510000000235115232633614025401 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qml-debugging/0000755000175100017510000000000015232633614023357 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qml-debugging/main.cpp0000644000175100017510000000345615232633614025017 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #include using Application = QGuiApplication; #define AH_SO_THIS_IS_QT5 #else #include #include #define AH_SO_THIS_IS_QT4 using Application = QApplication; #endif int main(int argc, char *argv[]) { Application app(argc, argv); #ifdef AH_SO_THIS_IS_QT5 QQmlApplicationEngine engine; engine.load(QUrl("blubb")); #else QDeclarativeView view; view.setSource(QUrl("blubb")); #endif return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs0000644000175100017510000000077315232633614026617 0ustar runnerrunnerQtApplication { name: "debuggable-app" consoleApplication: true Depends { name: "Qt.quick" } Qt.quick.qmlDebugging: true files: "main.cpp" Probe { id: checker property bool isGcc: qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("emscripten") property string executableSuffix: cpp.executableSuffix configure: { console.info("is gcc: " + isGcc); console.info("executable suffix: " + executableSuffix); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/find-shadertools.qbs0000644000175100017510000000110515232633614024606 0ustar runnerrunnerimport qbs.Utilities CppApplication { name: "check_shadertools" Depends { name: "Qt.core" } Depends { name: "Qt.shadertools"; required: false } property bool dummy: { console.info("is qt6: " + JSON.stringify(Utilities.versionCompare(Qt.core.version, "6.0") >= 0)); console.info("is static qt: " + JSON.stringify(Qt.core.staticBuild)); console.info("is shadertools present: " + JSON.stringify(Qt.shadertools.present)); console.info("has viewCount: " + JSON.stringify(Utilities.versionCompare(Qt.core.version, "6.7.0") >= 0)); } }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/linker-variant/0000755000175100017510000000000015232633614023563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs0000644000175100017510000000041515232633614027642 0ustar runnerrunnerQtApplication { Probe { id: qtConfigProbe property stringList moduleConfig: Qt.core.moduleConfig configure: { console.info("Qt requires gold: " + moduleConfig.includes("use_gold_linker")); } } files: "main.cpp" } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/linker-variant/main.cpp0000644000175100017510000000007415232633614025214 0ustar runnerrunner#include int main() { qDebug() << "Tach."; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/0000755000175100017510000000000015232633614023164 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/multiview.qbs0000644000175100017510000000031315232633614025715 0ustar runnerrunnerimport qbs QtApplication { name: "shadertools-test" type: "application" Depends { name: "Qt.shadertools" } Qt.shadertools.multiView: true files: ["basic_shader.frag", "main.cpp"] }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/viewcount.qbs0000644000175100017510000000035715232633614025723 0ustar runnerrunnerimport qbs QtApplication { name: "view-count-test" type: "application" Depends { name: "Qt.shadertools" } Qt.shadertools.useQt6Versions: true Qt.shadertools.viewCount: 4 files: ["basic_shader.frag", "main.cpp"] }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/basic.qbs0000644000175100017510000000043515232633614024756 0ustar runnerrunnerimport qbs QtApplication { name: "shadertools-test" type: "application" Depends { name: "Qt.shadertools" } Qt.shadertools.useQt6Versions: true Qt.shadertools.optimized: true Qt.shadertools.debugInformation: true files: ["basic_shader.frag", "main.cpp"] }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/defines_shader.frag0000644000175100017510000000042215232633614026766 0ustar runnerrunner#version 440 precision mediump float; #ifndef TEST_DEFINE_1 #error "TEST_DEFINE_1 is not defined" #endif #ifndef TEST_DEFINE_2 #error "TEST_DEFINE_2 is not defined" #endif layout(location = 0) out vec4 fragColor; void main() { fragColor = vec4(1.0, 0.0, 0.0, 1.0); }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/tessellation.qbs0000644000175100017510000000053415232633614026403 0ustar runnerrunnerimport qbs QtApplication { name: "shadertools-test" type: "application" Depends { name: "Qt.shadertools" } Qt.shadertools.glslVersions: ["410", "320es"] Qt.shadertools.tessellationVertexCount: 3 Qt.shadertools.tessellationMode: "triangles" files: ["tessellation_shader.vert", "tessellation_shader.tesc", "main.cpp"] }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/tessellation_shader.vert0000644000175100017510000000054515232633614030126 0ustar runnerrunner// vertex shader #version 410 core // vertex position layout (location = 0) in vec3 aPos; // texture coordinate layout (location = 1) in vec2 aTex; layout(location = 0) out vec2 TexCoord; void main() { // convert XYZ vertex to XYZW homogeneous coordinate gl_Position = vec4(aPos, 1.0); // pass texture coordinate though TexCoord = aTex; }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/tessellation_shader.tesc0000644000175100017510000000110515232633614030075 0ustar runnerrunner#version 410 core layout (vertices=4) out; layout(location = 0) in vec2 TexCoord[];// varying output to evaluation shader layout(location = 0) out vec2 TextureCoord[]; void main() { gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; TextureCoord[gl_InvocationID] = TexCoord[gl_InvocationID]; if (gl_InvocationID == 0) { gl_TessLevelOuter[0] = 16; gl_TessLevelOuter[1] = 16; gl_TessLevelOuter[2] = 16; gl_TessLevelOuter[3] = 16; gl_TessLevelInner[0] = 16; gl_TessLevelInner[1] = 16; } }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/main.cpp0000644000175100017510000000003515232633614024612 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/basic_shader.frag0000644000175100017510000000021315232633614026430 0ustar runnerrunner#version 440 precision mediump float; layout(location = 0) out vec4 fragColor; void main() { fragColor = vec4(1.0, 0.0, 0.0, 1.0); }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/shadertools/defines.qbs0000644000175100017510000000043515232633614025312 0ustar runnerrunnerimport qbs QtApplication { name: "shadertools-defines-test" type: "application" Depends { name: "Qt.shadertools" } Qt.shadertools.useQt6Versions: true Qt.shadertools.defines: ["TEST_DEFINE_1=1", "TEST_DEFINE_2=1"] files: ["defines_shader.frag", "main.cpp"] }qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lrelease/0000755000175100017510000000000015232633614022431 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lrelease/lrelease.qbs0000644000175100017510000000104315232633614024732 0ustar runnerrunnerimport qbs.Host Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "lrelease-test" type: ["ts"] Depends { name: "Qt.core" } files: ["de.ts", "hu.ts"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lrelease/hu.ts0000644000175100017510000000074115232633614023417 0ustar runnerrunner Application My hovercraft is full of eels A légpárnásom tele van angolnákkal I will not buy this record; it is scratched Nem fogok vásárolni ezt a rekordot; ez karcos qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/lrelease/de.ts0000644000175100017510000000124415232633614023372 0ustar runnerrunner Application I am hunry Ich bin Ungar I am thirsty Ich bin Donnerstag Please press Control Bitte drücken Sie den Kontrolleur No keyboard detected. Please press F1 to continue Sehr witzig qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-compiler-defines/0000755000175100017510000000000015232633614024636 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.cpp0000644000175100017510000000011415232633614026604 0ustar runnerrunner#include "object.h" Object::Object(QObject *parent) : QObject(parent) { } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.h0000644000175100017510000000450015232633614026254 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include // These were not defined during the moc run (QBS-1592). // Do not use Q_OS_UNIX here as it is a fallback value which is defined when nothing else is. #if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(Q_OS_HURD) \ || defined(Q_OS_WASM) class Object : public QObject { Q_OBJECT public: explicit Object(QObject *parent = nullptr); }; #endif #endif // OBJECT_H qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-compiler-defines/moc-compiler-defines.qbs0000644000175100017510000000010415232633614031341 0ustar runnerrunnerQtApplication { files: ["main.cpp", "object.h", "object.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-compiler-defines/main.cpp0000644000175100017510000000010115232633614026256 0ustar runnerrunner#include "object.h" int main() { QObject o; return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/0000755000175100017510000000000015232633614022370 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/0000755000175100017510000000000015232633614024065 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/0000755000175100017510000000000015232633614025355 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/resource2.txt0000644000175100017510000000001215232633614030020 0ustar runnerrunnerresource2 qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/resource3.txt0000644000175100017510000000001215232633614030021 0ustar runnerrunnerresource3 qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/resource1.txt0000644000175100017510000000001215232633614026527 0ustar runnerrunnerresource1 qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs0000644000175100017510000000223015232633614024627 0ustar runnerrunnerimport qbs.Host Project { QtApplication { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "app" files: ["main.cpp"] Group { prefix: "qrc-base/" Qt.core.resourcePrefix: "/thePrefix" Qt.core.resourceSourceBase: "qrc-base" files: ["resource1.txt"] fileTags: ["qt.core.resource_data"] Group { prefix: "qrc-base/subdir/" Qt.core.resourceSourceBase: "qrc-base/subdir" files: ["resource2.txt"] Group { prefix: "qrc-base/subdir/" Qt.core.resourcePrefix: "/theOtherPrefix" files: ["resource3.txt"] } } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/auto-qrc/main.cpp0000644000175100017510000000107115232633614024017 0ustar runnerrunner#include #include int main() { QFile resource1(":/thePrefix/resource1.txt"); if (!resource1.open(QIODevice::ReadOnly)) return 1; QFile resource2(":/thePrefix/resource2.txt"); if (!resource2.open(QIODevice::ReadOnly)) return 2; QFile resource3(":/theOtherPrefix/resource3.txt"); if (!resource3.open(QIODevice::ReadOnly)) return 3; std::cout << "resource data: " << resource1.readAll().constData() << resource2.readAll().constData() << resource3.readAll().constData() << std::endl; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/forced-moc/0000755000175100017510000000000015232633614022653 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs0000644000175100017510000000156515232633614025407 0ustar runnerrunnerimport qbs.Host import qbs.Utilities QtApplication { condition: { if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { console.info("using qt4"); return false; } var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } files: "main.cpp" Group { name: "QObject service provider" files: "createqtclass.h" fileTags: ["hpp", "unmocable"] } Group { name: "QObject service user" files: "myqtclass.h" fileTags: ["hpp", "mocable"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/forced-moc/createqtclass.h0000644000175100017510000000032415232633614025661 0ustar runnerrunner#ifndef CREATEQTCLASS_H #define CREATEQTCLASS_H #include #define CREATE_QT_CLASS(className) \ class className : public QObject \ { \ Q_OBJECT \ public: \ Q_SIGNAL void mySignal(); \ } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/forced-moc/main.cpp0000644000175100017510000000054615232633614024310 0ustar runnerrunner#include "myqtclass.h" #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); MyQtClass c; QObject::connect(&c, &MyQtClass::mySignal, [] { qDebug() << "Hello from slot"; qApp->quit(); }); QTimer::singleShot(0, &c, &MyQtClass::mySignal); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/forced-moc/myqtclass.h0000644000175100017510000000015115232633614025041 0ustar runnerrunner#ifndef MYQTCLASS_H #define MYQTCLASS_H #include "createqtclass.h" CREATE_QT_CLASS(MyQtClass); #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/0000755000175100017510000000000015232633614022633 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/stuff.js0000644000175100017510000000005415232633614024317 0ustar runnerrunnerfunction title() { return "Wello Horld!"; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/MainForm.ui.qml0000644000175100017510000000116015232633614025470 0ustar runnerrunnerimport QtQuick 2.6 Rectangle { property alias mouseArea: mouseArea property alias textEdit: textEdit width: 360 height: 360 MouseArea { id: mouseArea anchors.fill: parent } TextEdit { id: textEdit text: qsTr("Enter some text...") verticalAlignment: Text.AlignVCenter anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 Rectangle { anchors.fill: parent anchors.margins: -10 color: "transparent" border.width: 1 } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/main.qml0000644000175100017510000000052015232633614024267 0ustar runnerrunnerimport QtQuick 2.6 import QtQuick.Window 2.2 import "stuff.js" as Stuff Window { visible: true width: 640 height: 480 title: Stuff.title() MainForm { anchors.fill: parent mouseArea.onClicked: { console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"')) } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/main.cpp0000644000175100017510000000052315232633614024263 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(qApp->applicationDirPath() + QStringLiteral("/data/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs0000644000175100017510000000163715232633614025347 0ustar runnerrunnerimport qbs.Utilities CppApplication { name: "app" consoleApplication: true Depends { name: "Qt.core" } Depends { name: "Qt.quick" } Depends { name: "Qt.qml" } install: true installDir: "" qbs.installPrefix: "" Qt.qml.generateCacheFiles: true Qt.qml.cacheFilesInstallDir: "data" files: [ "main.cpp", "MainForm.ui.qml", "main.qml", "stuff.js" ] // Install the C++ sources to tell the blackbox test that Qt.qmlcache is not available. Group { condition: !Qt.qml.cachingEnabled fileTagsFilter: ["cpp"] qbs.install: true qbs.installDir: "data" } Probe { id: qtVersionProbe property string qtVersion: Qt.core.version configure: { console.info("qmlcachegen must work: " + (Utilities.versionCompare(qtVersion, "5.11") >= 0)) } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/cached-qml/qml.qrc0000644000175100017510000000023115232633614024127 0ustar runnerrunner main.qml MainForm.ui.qml qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/0000755000175100017510000000000015232633614026763 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/file.h0000644000175100017510000000022115232633614030046 0ustar runnerrunner#pragma once #include class MyObject : public QObject { Q_OBJECT public: MyObject(); signals: void someSignal(); }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/file.cpp0000644000175100017510000000014515232633614030406 0ustar runnerrunner#include "file.h" MyObject::MyObject() {} int main() { MyObject o1; } #include ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/remove-moc-header-from-file-list.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/remove-moc-header-fro0000644000175100017510000000013015232633614032763 0ustar runnerrunnerQtApplication { name: "p" files: [ "file.h", "file.cpp" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/0000755000175100017510000000000015232633614022650 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp0000644000175100017510000000025115232633614026064 0ustar runnerrunner#include class MocableClass2 : public QObject { Q_OBJECT public: MocableClass2(QObject *parent) : QObject(parent) {} }; #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h0000644000175100017510000000020115232633614025523 0ustar runnerrunner#include class MocableClass1 : public QObject { Q_OBJECT public: MocableClass1(QObject *parent = nullptr); }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp0000644000175100017510000000020015232633614026337 0ustar runnerrunner#include class UnmocableClass : public QObject { public: UnmocableClass(QObject *parent) : QObject(parent) {} }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs0000644000175100017510000000112515232633614025371 0ustar runnerrunnerimport qbs.Utilities StaticLibrary { name: "mylib" Depends { name: "Qt.core" } qbs.installPrefix: "some-prefix" Probe { id: capabilitiesChecker property string version: Qt.core.version configure: { if (Utilities.versionCompare(version, "5.15") >= 0) console.info("can generate"); else console.info("cannot generate"); found = true; } } files: [ "mocableclass1.cpp", "mocableclass1.h", "mocableclass2.cpp", "unmocableclass.cpp", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp0000644000175100017510000000013715232633614026066 0ustar runnerrunner#include "mocableclass1.h" MocableClass1::MocableClass1(QObject *parent) : QObject(parent) {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/0000755000175100017510000000000015232633614030360 5ustar runnerrunner././@LongLink0000644000000000000000000000020400000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/no-moc-run-after-touching-other-cpp-file.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/no-moc-run-af0000644000175100017510000000016215232633614032660 0ustar runnerrunnerQtApplication { name: "app" files: [ "header1.h", "header2.h", "main.cpp" ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/header2.h0000644000175100017510000000010315232633614032035 0ustar runnerrunner#include class Test2 : public QObject { Q_OBJECT }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/header1.h0000644000175100017510000000010315232633614032034 0ustar runnerrunner#include class Test1 : public QObject { Q_OBJECT }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/no-moc-run-after-touching-other-cpp-file/main.cpp0000644000175100017510000000007515232633614032012 0ustar runnerrunner int main(int /*argc*/, char * /*argv*/[]) { return 0; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/0000755000175100017510000000000015232633614024315 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/after/0000755000175100017510000000000015232633614025416 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/after/main.cpp0000644000175100017510000000304115232633614027044 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); const auto obj = new MyObject(&app); return app.exec(); } #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/0000755000175100017510000000000015232633614025557 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/test.qbs0000644000175100017510000000015515232633614027246 0ustar runnerrunnerApplication { Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/main.cpp0000644000175100017510000000301415232633614027205 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); const auto obj = new MyObject(&app); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-keywords/0000755000175100017510000000000015232633614023126 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-keywords/main.cpp0000644000175100017510000000021315232633614024552 0ustar runnerrunner#include class AnObject : public QObject { Q_OBJECT signals: void someSignal(); }; int main() { } #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/qt-keywords/qt-keywords.qbs0000644000175100017510000000005215232633614026123 0ustar runnerrunnerQtApplication { files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/combined-moc/0000755000175100017510000000000015232633614023171 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/combined-moc/main.cpp0000644000175100017510000000007515232633614024623 0ustar runnerrunner#include "theobject.h" int main() { TheObject object; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/combined-moc/theobject.h0000644000175100017510000000010715232633614025307 0ustar runnerrunner#include class TheObject : public QObject { Q_OBJECT }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/combined-moc/combined-moc.qbs0000644000175100017510000000014315232633614026232 0ustar runnerrunnerQtApplication { name: "theapp" files: [ "main.cpp", "theobject.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/0000755000175100017510000000000015232633614025473 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/lib.cpp0000644000175100017510000000002315232633614026740 0ustar runnerrunnervoid function() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs0000644000175100017510000000117215232633614033041 0ustar runnerrunnerProduct { name: "p" Probe { id: staticQtChecker property bool staticQt: Qt.core.staticBuild configure: { found = staticQt; if (found) console.info("Qt is static"); } } Group { condition: type.includes("application") files: "main.cpp" } Group { condition: type.includes("staticlibrary") files: "lib.cpp" } Depends { name: "Qt.core" } Depends { name: "Qt.gui" } Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild && !qbs.toolchain.includes("emscripten") } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/main.cpp0000644000175100017510000000017715232633614027130 0ustar runnerrunner#include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/0000755000175100017510000000000015232633614030162 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/object.h0000644000175100017510000000240315232633614031600 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ class Object { public: void f(); }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/object.cpp.in0000644000175100017510000000256715232633614032553 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include // class InternalClass : public QObject // { // Q_OBJECT // }; void Object::f() { } // #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/main.cpp0000644000175100017510000000243015232633614031611 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" int main() { Object o; o.f(); } ././@LongLink0000644000000000000000000000020200000000000011575 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/add-qobject-macro-to-generated-cpp-file.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/add-qobject-ma0000644000175100017510000000111215232633614032650 0ustar runnerrunnerimport qbs.File QtApplication { name: "p" files: ["main.cpp", "object.h"] Group { files: "object.cpp.in" fileTags: "cpp.in" } Rule { inputs: "cpp.in" Artifact { filePath: input.completeBaseName fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generatating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } cpp.includePaths: path } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/0000755000175100017510000000000015232633614024171 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/moc-same-file-name.qbs0000644000175100017510000000114015232633614030230 0ustar runnerrunnerQtApplication { name: "app" cpp.cxxLanguageVersion: "c++11" files: "main.cpp" Group { name: "src1" Qt.core.generatedHeadersDir: product.buildDirectory + "/qt.headers_src1" prefix: name + '/' files: [ "someclass.cpp", "someclass.h", "somefile.cpp", ] } Group { name: "src2" prefix: name + '/' Qt.core.generatedHeadersDir: product.buildDirectory + "/qt.headers_src2" files: [ "someclass.cpp", "someclass.h", "somefile.cpp", ] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/0000755000175100017510000000000015232633614025041 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/somefile.cpp0000644000175100017510000000020415232633614027344 0ustar runnerrunner#include class MyClass1 : public QObject { Q_OBJECT }; static void f() { MyClass1 m; } #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/someclass.cpp0000644000175100017510000000015115232633614027533 0ustar runnerrunner#include "someclass.h" namespace Src1 { SomeClass::SomeClass(QObject *parent) : QObject(parent) { } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/someclass.h0000644000175100017510000000030115232633614027175 0ustar runnerrunner#ifndef SOMECLASS1_H #define SOMECLASS1_H #include namespace Src1 { class SomeClass : public QObject { Q_OBJECT public: SomeClass(QObject *parent = nullptr); }; } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/main.cpp0000644000175100017510000000017215232633614025621 0ustar runnerrunner#include "src1/someclass.h" #include "src2/someclass.h" int main() { Src1::SomeClass sc1; Src2::SomeClass sc2; } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/0000755000175100017510000000000015232633614025042 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/somefile.cpp0000644000175100017510000000020415232633614027345 0ustar runnerrunner#include class MyClass2 : public QObject { Q_OBJECT }; static void f() { MyClass2 m; } #include qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/someclass.cpp0000644000175100017510000000015115232633614027534 0ustar runnerrunner#include "someclass.h" namespace Src2 { SomeClass::SomeClass(QObject *parent) : QObject(parent) { } } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/someclass.h0000644000175100017510000000030115232633614027176 0ustar runnerrunner#ifndef SOMECLASS2_H #define SOMECLASS2_H #include namespace Src2 { class SomeClass : public QObject { Q_OBJECT public: SomeClass(QObject *parent = nullptr); }; } #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-change-tracking/0000755000175100017510000000000015232633614024436 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-change-tracking/moc-change-tracking.qbs0000644000175100017510000000017215232633614030746 0ustar runnerrunnerDynamicLibrary { Depends {name: "Qt.core" } files: ["class.cpp", "class.h"] // cpp.combineCxxSources: true } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-change-tracking/class.cpp0000644000175100017510000000005215232633614026244 0ustar runnerrunner#include "class.h" void Class1::foo() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/moc-change-tracking/class.h0000644000175100017510000000023715232633614025716 0ustar runnerrunner#pragma once #include class Class1 : public QObject { Q_OBJECT public: Class1() = default; void foo(); signals: void ready(); }; qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/0000755000175100017510000000000015232633614023760 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/main.cpp0000644000175100017510000000015515232633614025411 0ustar runnerrunner#include "myobject.h" int main() { MyObject o; QObject::connect(&o, &QObject::destroyed, [] { }); } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/myobject.h0000644000175100017510000000016515232633614025747 0ustar runnerrunner#ifndef MYOBJECT_H #define MYOBJECT_H #include class MyObject : public QObject { Q_OBJECT }; #endif qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs0000644000175100017510000000047015232633614027613 0ustar runnerrunnerimport qbs.Utilities QtApplication { condition: { if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { console.info("using qt4"); return false; } return true; } files: [ "main.cpp", "myobject.cpp", "myobject.h", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/myobject.cpp0000644000175100017510000000006315232633614026277 0ustar runnerrunner#include "myobject.h" #include qbs-src-3.3.1/tests/auto/blackbox/testdata-java/0000755000175100017510000000000015232633614021132 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/0000755000175100017510000000000015232633614022053 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/HelloWorld8.java0000644000175100017510000000024115232633614025056 0ustar runnerrunnerpackage io.qt.qbs; public class HelloWorld8 { public class Other { @java.lang.annotation.Native public final int countOfThings = 0; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/engine.c0000644000175100017510000000305215232633614023464 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include // javac 1.8 is required to generate native headers #ifdef JNI_VERSION_1_8 #include "Car_InternalCombustionEngine.h" #endif JNIEXPORT void JNICALL Java_Car_00024InternalCombustionEngine_run(JNIEnv *env, jobject obj) { printf("Native code performing complex internal combustion process (%p, %p)!\n", env, obj); } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Manifest.mf0000644000175100017510000000003215232633614024140 0ustar runnerrunnerSome-Property: Some-Value qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Manifest2.mf0000644000175100017510000000010015232633614024216 0ustar runnerrunnerSome-Property: Some-Value Additional-Property: Additional-Value qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/RandomStuff.java0000644000175100017510000000012115232633614025140 0ustar runnerrunnerpackage glob; public class RandomStuff { public static void bar() { } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Ship.java0000644000175100017510000000036415232633614023624 0ustar runnerrunnerclass Ship implements Vehicle { public boolean isInSpace; public void go() { if (isInSpace) System.out.println("Flying (this is a space ship)!"); else System.out.println("Sailing!"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/vehicles.qbs0000644000175100017510000000627615232633614024377 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host import qbs.Utilities Project { DynamicLibrary { Depends { name: "cpp" } Depends { name: "car_jar" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } property bool _testPlatform: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "native" files: ["engine.c"] qbs.installPrefix: "" install: true installDir: "" } JavaClassCollection { Depends { name: "random_stuff" } name: "cc" java.additionalCompilerFlags: ["-Xlint:all"] files: [ "Car.java", "HelloWorld.java", "Jet.java", "NoPackage.java", "Ship.java", "Vehicle.java", "Vehicles.java" ] Group { condition: Utilities.versionCompare(java.version, "1.8") >= 0 files: ["Car8.java", "HelloWorld8.java"] } Export { Depends { name: "java" } java.manifestClassPath: [exportingProduct.targetName + ".jar"] } } JavaJarFile { name: "random_stuff" files: ["RandomStuff.java"] qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } Export { Depends { name: "java" } java.manifestClassPath: [exportingProduct.targetName + ".jar"] } } JavaJarFile { name: "car_jar" files: ["Car.java", "Vehicle.java"] Group { condition: Utilities.versionCompare(java.version, "1.8") >= 0 files: ["Car8.java"] } Export { Depends { name: "cpp" } cpp.systemIncludePaths: { var paths = importingProduct.java.jdkIncludePaths; if (Utilities.versionCompare(importingProduct.java.version, "1.8") >= 0) { paths.push(exportingProduct.buildDirectory); // generated JNI headers } return paths; } Depends { name: "java" } java.manifestClassPath: [exportingProduct.targetName + ".jar"] } qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } } JavaJarFile { Depends { name: "random_stuff" } Depends { name: "car_jar" } Depends { name: "native" } name: "jar_file" entryPoint: "Vehicles" files: ["Jet.java", "Ship.java", "Vehicles.java", "Manifest.mf", "Manifest2.mf"] java.manifest: { var mf = original; mf["Extra-Property"] = "Crazy-Value"; return mf; } qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/inner-class/0000755000175100017510000000000015232633614024271 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/inner-class/InnerClass.java0000644000175100017510000000021015232633614027166 0ustar runnerrunnerpublic class InnerClass { private final InnerInnerClass clazz = new InnerInnerClass(); private class InnerInnerClass { } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/inner-class/inner-class.qbs0000644000175100017510000000005115232633614027212 0ustar runnerrunnerJavaJarFile { files: ["**/*.java"] } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Jet.java0000644000175100017510000000015115232633614023435 0ustar runnerrunnerclass Jet implements Vehicle { public void go() { System.out.println("Flying!"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Vehicles.java0000644000175100017510000000142315232633614024460 0ustar runnerrunnerimport java.util.ArrayList; import glob.RandomStuff; class Vehicles { public static void main(String[] args) { System.loadLibrary("native"); RandomStuff.bar(); ArrayList vehicles = new ArrayList(); for (int i = 0; i < 3; i++) { vehicles.add(new Car()); } for (int i = 0; i < 3; i++) { vehicles.add(new Jet()); } for (int i = 0; i < 4; i++) { Ship ship = new Ship(); ship.isInSpace = i % 2 == 0; vehicles.add(ship); } for (int i = 0; i < vehicles.size(); i++) { vehicles.get(i).go(); } // doesn't compile, must be a bug // delete vehicles; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/HelloWorld.java0000644000175100017510000000043715232633614024775 0ustar runnerrunnerpackage io.qt.qbs; public class HelloWorld { public static void main(String[] args) { System.out.println("Tach."); } public class Internal { public native void something(); } public class Other { public final int countOfThings = 0; } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Car.java0000644000175100017510000000065515232633614023431 0ustar runnerrunnerclass Car implements Vehicle { private InternalCombustionEngine engine; public Car() { engine = new InternalCombustionEngine(); } public void go() { System.out.println("Driving!"); engine.run(); } public class InternalCombustionEngine { public native void run(); public class ChemicalReaction { public native void occur(); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Vehicle.java0000644000175100017510000000005415232633614024274 0ustar runnerrunnerinterface Vehicle { public void go(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/NoPackage.java0000644000175100017510000000014615232633614024547 0ustar runnerrunner// package this.should.not.be.parsed; public class NoPackage { public static void doSomething() {} } qbs-src-3.3.1/tests/auto/blackbox/testdata-java/java/Car8.java0000644000175100017510000000107215232633614023513 0ustar runnerrunnerclass Car8 implements Vehicle { private InternalCombustionEngine engine; public Car8() { engine = new InternalCombustionEngine(); } public void go() { System.out.println("Driving!"); engine.run(); } public class InternalCombustionEngine { public native void run(); public class ChemicalReaction { public native void occur(); public class Atoms { @java.lang.annotation.Native public int hydrogenAtomCount; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/0000755000175100017510000000000015232633614021631 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/0000755000175100017510000000000015232633614023200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/main.qml0000644000175100017510000000021115232633614024631 0ustar runnerrunnerimport QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs0000644000175100017510000000063615232633614025263 0ustar runnerrunnerQtApplication { name: "qmlapp" Depends { name: "Qt.quick" } Depends { name: "Qt.android_support" } Properties { condition: qbs.targetOS.includes("android") Qt.android_support.extraPrefixDirs: path } Android.sdk.packageName: "my.qmlapp" Android.sdk.apkBaseName: name Qt.android_support.qmlImportPaths: path files: [ "main.cpp", "qml.qrc", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/src/0000755000175100017510000000000015232633614023767 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/src/main/0000755000175100017510000000000015232633614024713 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml0000644000175100017510000001167715232633614030520 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/src/main/assets/0000755000175100017510000000000015232633614026215 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/src/main/assets/dummyasset.txt0000644000175100017510000000000015232633614031137 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/main.cpp0000644000175100017510000000111015232633614024621 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { if (qEnvironmentVariableIsEmpty("QTGLESSTREAM_DISPLAY")) { qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", QByteArray("213")); qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", QByteArray("120")); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qml-app/qml.qrc0000644000175100017510000000012715232633614024500 0ustar runnerrunner main.qml qbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/0000755000175100017510000000000015232633614024543 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs0000644000175100017510000000065415232633614030171 0ustar runnerrunnerCppApplication { name: "minimalnative" qbs.buildVariant: "release" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.sdk.packageName: "my.minimalnative" Android.sdk.apkBaseName: name Android.ndk.appStl: "stlport_shared" files: "src/main/native/native.c" Group { files: "libdependency.so" fileTags: "android.nativelibrary" } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/0000755000175100017510000000000015232633614025332 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/0000755000175100017510000000000015232633614026256 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/0000755000175100017510000000000015232633614027544 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c0000644000175100017510000000033515232633614031177 0ustar runnerrunner#include #include jstring Java_minimalnative_MinimalNative_stringFromNative(JNIEnv* env, jobject thiz) { (void)thiz; return (*env)->NewStringUTF(env, "This message comes from native code."); } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml0000644000175100017510000000103215232633614032043 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/0000755000175100017510000000000015232633614027177 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/0000755000175100017510000000000015232633614027624 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/minimal/0000755000175100017510000000000015232633614031252 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/minimal/MinimalNative.javaqbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/minimal/MinimalNa0000644000175100017510000000070615232633614033045 0ustar runnerrunnerpackage minimalnative; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class MinimalNative extends Activity { @Override public void onCreate(Bundle savedInstanceState) { TextView tv = new TextView(this); tv.setText(stringFromNative()); setContentView(tv); } public native String stringFromNative(); static { System.loadLibrary("minimal"); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/minimal-native/libdependency.so0000644000175100017510000000000015232633614027701 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/0000755000175100017510000000000015232633614022542 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/0000755000175100017510000000000015232633614023151 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/0000755000175100017510000000000015232633614023736 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/0000755000175100017510000000000015232633614025547 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/Interface1.aidl0000644000175100017510000000022515232633614030362 0ustar runnerrunnerpackage io.qbs.aidltest; import io.qbs.aidltest.Interface2; interface Interface1 { void doSomething(in Interface2 param1, in Bundle param2); } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/MainActivity.java0000644000175100017510000000061415232633614031014 0ustar runnerrunnerpackage io.qbs.aidltest; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView label = new TextView(this); label.setText("Hello world!"); setContentView(label); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/Interface2.aidl0000644000175100017510000000013015232633614030356 0ustar runnerrunnerpackage io.qbs.aidltest; interface Interface2 { void someFunc(in Bundle params); } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/aidl.qbs0000644000175100017510000000024115232633614024157 0ustar runnerrunnerApplication { name: "io.qbs.aidltest" Android.sdk.aidlSearchPaths: path files: [ "AndroidManifest.xml", "io/qbs/aidltest/*", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml0000644000175100017510000000103115232633614026326 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/0000755000175100017510000000000015232633614025750 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/0000755000175100017510000000000015232633614026357 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/0000755000175100017510000000000015232633614027144 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/lib3/0000755000175100017510000000000015232633614027775 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/lib3/lib3.java0000644000175100017510000000012115232633614031463 0ustar runnerrunnerpackage io.qbs.lib3; public class lib3 { public static void foo() { } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib6.java0000644000175100017510000000002615232633614027445 0ustar runnerrunnerpublic class lib6 { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib5.java0000644000175100017510000000002615232633614027444 0ustar runnerrunnerpublic class lib5 { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib4.java0000644000175100017510000000002615232633614027443 0ustar runnerrunnerpublic class lib4 { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib8.java0000644000175100017510000000002615232633614027447 0ustar runnerrunnerpublic class lib8 { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/0000755000175100017510000000000015232633614026537 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/0000755000175100017510000000000015232633614027463 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xmlqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xm0000644000175100017510000000145015232633614033100 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/0000755000175100017510000000000015232633614030254 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/values/0000755000175100017510000000000015232633614031553 5ustar runnerrunner././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/values/strings.xmlqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/values/strings0000644000175100017510000000010415232633614033162 0ustar runnerrunner dummy qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/0000755000175100017510000000000015232633614030404 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/0000755000175100017510000000000015232633614031013 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/0000755000175100017510000000000015232633614031437 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/dummy/0000755000175100017510000000000015232633614032572 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/dummy/Dummy.javaqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/dummy/D0000644000175100017510000000065015232633614032701 0ustar runnerrunnerpackage io.qt.dummy; import android.app.Activity; import android.os.Build; import io.qbs.lib3.lib3; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("armeabi")) { System.loadLibrary("lib1"); System.loadLibrary("lib2"); } lib3.foo(); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/0000755000175100017510000000000015232633614030243 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/lib2.cpp0000644000175100017510000000234715232633614031605 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/lib1.cpp0000644000175100017510000000234715232633614031604 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs0000644000175100017510000000463515232633614032606 0ustar runnerrunnerProject { DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false Depends { name: "lib6" } Depends { name: "lib8" } name: "lib3" files: ["io/qbs/lib3/lib3.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib4" files: ["lib4.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib5" files: ["lib5.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib6" files: ["lib6.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib7" files: ["lib7.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false Depends { name: "lib7"; Android.sdk.embedJar: false } name: "lib8" files: ["lib8.java"] } Application { name: "twolibs" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy" Depends { productTypes: ["android.nativelibrary"] } Depends { name: "lib3"; Android.sdk.embedJar: true } Depends { name: "lib4"; Android.sdk.embedJar: false } Depends { name: "lib5" } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib7.java0000644000175100017510000000002615232633614027446 0ustar runnerrunnerpublic class lib7 { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/teapot/0000755000175100017510000000000015232633614023125 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/teapot/teapot.qbs0000644000175100017510000001145515232633614025136 0ustar runnerrunnerimport qbs.File Project { minimumQbsVersion: qbs.version StaticLibrary { name: "native-glue" qbs.targetPlatform: "android" cpp.warningLevel: "none" Depends { name: "cpp" } Group { id: glue_sources prefix: Android.ndk.ndkDir + "/sources/android/native_app_glue/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [glue_sources.prefix] cpp.dynamicLibraries: ["log"] } } StaticLibrary { name: "ndk-helper" qbs.targetPlatform: "android" cpp.warningLevel: "none" Depends { name: "Android.ndk" } Depends { name: "cpp" } Depends { name: "native-glue" } Probe { id: ndkHelperProbe property string ndkDir: Android.ndk.ndkDir property string samplesDir: Android.ndk.ndkSamplesDir property string dir configure: { var paths = [samplesDir + "/teapots/common/ndk_helper/", ndkDir + "/sources/android/ndk_helper/"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(paths[i])) { dir = paths[i]; break; } } } } property string ndkDir: ndkHelperProbe.dir Group { id: ndkhelper_sources prefix: ndkHelperProbe.dir files: ["*.cpp", "*.h"].concat( !File.exists(ndkHelperProbe.dir + "/gl3stub.cpp") ? ["gl3stub.c"] : []) } Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.ndkDir] cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] } } StaticLibrary { name: "android_cpufeatures" qbs.targetPlatform: "android" Depends { name: "cpp" } Group { id: cpufeatures_sources prefix: Android.ndk.ndkDir + "/sources/android/cpufeatures/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [cpufeatures_sources.prefix] cpp.dynamicLibraries: ["dl"] } } CppApplication { name: "TeapotNativeActivity" qbs.targetPlatform: "android" Depends { name: "Android.ndk" } Depends { name: "cpp" } Depends { name: "android_cpufeatures" } Depends { name: "native-glue" } Depends { name: "ndk-helper" } Probe { id: teapotProbe property string samplesDir: Android.sdk.ndkSamplesDir property string dir configure: { var paths = ["/teapots/classic-teapot/src/main", "/Teapot/app/src/main", "/Teapot"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(samplesDir + paths[i])) { dir = samplesDir + paths[i]; break; } } } } Probe { id: teapotProbeJni property string samplesDir: Android.ndk.ndkSamplesDir property string jniDir configure: { var paths = ["/teapots/classic-teapot/src/main/cpp/", "/Teapot/app/src/main/jni/", "/Teapot/jni/"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(samplesDir + paths[i])) { jniDir = samplesDir + paths[i]; break; } } } } Group { name: "C++ sources" prefix: teapotProbeJni.jniDir files: [ "TeapotNativeActivity.cpp", "TeapotRenderer.cpp", "TeapotRenderer.h", "teapot.inl", ] } FileTagger { patterns: ["*.inl"]; fileTags: ["hpp"] } version: "2.0" Android.sdk.apkBaseName: name Android.sdk.packageName: "com.sample.teapot" Android.sdk.sourceSetDir: teapotProbe.dir Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] cpp.useRPaths: false // Export ANativeActivity_onCreate(), // Refer to: https://github.com/android-ndk/ndk/issues/381 cpp.linkerFlags: ["-u", "ANativeActivity_onCreate"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/no-native/0000755000175100017510000000000015232633614023531 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/no-native/no-native.qbs0000644000175100017510000000044015232633614026136 0ustar runnerrunnerApplication { qbs.targetPlatform: "android" name: "com.example.android.basicmediadecoder" Android.sdk.sourceSetDir: Android.sdk.sdkDir + "/samples/android-BasicMediaDecoder/Application/src/main" Android.sdk.versionCode: 5 Android.sdk.versionName: "5.0" } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/0000755000175100017510000000000015232633614023033 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/test.keystore0000644000175100017510000000240415232633614025601 0ustar runnerrunnerþíþíqbstestwgð§º0‚¶0 +*‚¢Õ¸ÍRú9×CŽ!–Yç5!ÒÞÀCJ<‡‚¿"ß_Ùõ…™'¢èÒ²¬œS_þ_Í^·Òesz¿I¡eg̃gÿ¬Lõˆ£*«ä¤<ƒzý6ºN· õè®w鳈¿•B柧avç¼—ÀÂ¥ë‘òÙ Y&‚v§²gꤘëe¤,Ë·Ùúu`’ï?-‡2»ñZó¼ð÷á 5 Ž]ÆJ3¤¿y:LJ…¾±é!÷‰®º‹Eh@wÚ×¶7,DL,›mfë®ÛÇ÷Ÿ ¤&¶Ìݙ،™² ojŸáXž+N_—õs¿6ÈŒ\ΆQÀZCçÃ0¯*õìà=цki€ûp<‰Ø›¯XLeç_¹ƒ@©‰ Å^N7(SÄ›Ç"+*^ókdp³“5œ8U{¯§ƒsx5ê`+yzi:'"¨$uBëšÁ0yñ~MÒÛˆù"ˆù{ '¶ªD¤%3;Ó±ØWÇc7[BÏÕdÔ$äÈ´¹RÕIB,ºÇy£í‰uUûl0I6X.5090‚þ0‚g wÂ2Š0  *†H†÷  021 0 UUS10U Android10Uqbs test0 210118213023Z 480605213023Z021 0 UUS10U Android10Uqbs test0Ÿ0  *†H†÷ 0‰Ä>_¬¢Å\öe_ÉÇÑòrž'Ë1[Þ¤%ØRP ôåÊc¥Kó½ õv‹Óиåå.þ.UPmÖNL#@ö-wÖ:…‘!ôÆ™ÿ —÷U™;é)V¾¿CÁ²êF¢÷/ׂ@Õ‹ V† mûòƒc“6—È+&G@$’¨7Éàñ£!00Ué>rÛ!i‡&y~š`(Z… Î0  *†H†÷  ƒ€wGg5V÷k0òòO)¾S>ŒhE‰5È•¦õ¡…+5$Ñ~TàÑ]IyTr.BÞã,4R‚É$Y:®ré„jÞ›Vá}Sž-e½áï.í–?åeŸøÃóÓad1Àz/éÂýbJÒgöãuW†ù)™0Uؼáÿ@;柋¦k½>²üƒiT:¹%QevŸR›qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/MainWindow.cpp0000644000175100017510000000017715232633614025620 0ustar runnerrunner#include "MainWindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { } MainWindow::~MainWindow() { } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/MainWindow.h0000644000175100017510000000033215232633614025256 0ustar runnerrunner#ifndef MAINWINDOW_H #define MAINWINDOW_H #include class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); }; #endif // MAINWINDOW_H qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/main.cpp0000644000175100017510000000025415232633614024464 0ustar runnerrunner#include "MainWindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/TestQt6.java0000644000175100017510000000260415232633614025212 0ustar runnerrunnerpackage org.qbs.example; import org.qtproject.qt.android.bindings.QtActivity; import android.os.*; import android.content.*; import android.app.*; import android.util.Log; import java.lang.String; import android.content.Intent; import org.qbs.example.*; public class TestQt6 extends QtActivity { public static native void testFunc(String test); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("qbs", "onCreate Test"); Intent theIntent = getIntent(); if (theIntent != null) { String theAction = theIntent.getAction(); if (theAction != null) { Log.d("qbs onCreate ", theAction); } } } @Override public void onDestroy() { Log.d("qbs", "onDestroy"); System.exit(0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d("qbs onActivityResult", "requestCode: "+requestCode); if (resultCode == RESULT_OK) { Log.d("qbs onActivityResult - resultCode: ", "SUCCESS"); } else { Log.d("qbs onActivityResult - resultCode: ", "CANCEL"); } } @Override public void onNewIntent(Intent intent) { Log.d("qbs", "onNewIntent"); super.onNewIntent(intent); setIntent(intent); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/qt-app.qbs0000644000175100017510000000122015232633614024737 0ustar runnerrunnerProject { QtGuiApplication { Depends { name: "Lib" } files: ["main.cpp", "MainWindow.cpp", "MainWindow.h" ] Group { condition: Qt.core.versionMajor == 5 files: ["Test.java"] } Group { condition: Qt.core.versionMajor == 6 files: ["TestQt6.java"] } Android.sdk.packageName: "my.qtapp" Android.sdk.apkBaseName: name Depends { name: "Qt"; submodules: ["core", "widgets"] } } StaticLibrary { name: "Lib" Export { Depends { name: "Qt.android_support"; } } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/qt-app/Test.java0000644000175100017510000000260215232633614024615 0ustar runnerrunnerpackage org.qbs.example; import org.qtproject.qt5.android.bindings.QtActivity; import android.os.*; import android.content.*; import android.app.*; import android.util.Log; import java.lang.String; import android.content.Intent; import org.qbs.example.*; public class Test extends QtActivity { public static native void testFunc(String test); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("qbs", "onCreate Test"); Intent theIntent = getIntent(); if (theIntent != null) { String theAction = theIntent.getAction(); if (theAction != null) { Log.d("qbs onCreate ", theAction); } } } @Override public void onDestroy() { Log.d("qbs", "onDestroy"); System.exit(0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d("qbs onActivityResult", "requestCode: "+requestCode); if (resultCode == RESULT_OK) { Log.d("qbs onActivityResult - resultCode: ", "SUCCESS"); } else { Log.d("qbs onActivityResult - resultCode: ", "CANCEL"); } } @Override public void onNewIntent(Intent intent) { Log.d("qbs", "onNewIntent"); super.onNewIntent(intent); setIntent(intent); } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/0000755000175100017510000000000015232633614026650 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/multiple-apks-per-project.qbsqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/multiple-apks-per-proje0000644000175100017510000000011415232633614033257 0ustar runnerrunnerProject { references: [ "product1", "product2", ] } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/0000755000175100017510000000000015232633614030412 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/0000755000175100017510000000000015232633614031201 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/0000755000175100017510000000000015232633614032125 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xmlqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/Andro0000644000175100017510000000145115232633614033114 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/0000755000175100017510000000000015232633614033046 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/0000755000175100017510000000000015232633614033046 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qt/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/0000755000175100017510000000000015232633614033046 5ustar runnerrunner././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qt/dummy2/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/0000755000175100017510000000000015232633614033046 5ustar runnerrunner././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qt/dummy2/Dummy.javaqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/0000644000175100017510000000060015232633614033044 0ustar runnerrunnerpackage io.qt.dummy2; import android.app.Activity; import android.os.Build; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("armeabi")) { System.loadLibrary("p2lib1"); System.loadLibrary("p2lib2"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/0000755000175100017510000000000015232633614032705 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/lib2.cppqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/l0000644000175100017510000000234715232633614033071 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/lib1.cppqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/l0000644000175100017510000000234715232633614033071 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs0000644000175100017510000000144115232633614032663 0ustar runnerrunnerProject { DynamicLibrary { Depends { name: "cpp" } name: "p2lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p2lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" } Application { name: "twolibs2" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy2" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/0000755000175100017510000000000015232633614030411 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs0000644000175100017510000000222015232633614032655 0ustar runnerrunnerProject { DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p1lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" Properties { qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined overrideListProperties: true } cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p1lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } Application { name: "twolibs1" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy1" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/0000755000175100017510000000000015232633614031200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/0000755000175100017510000000000015232633614032124 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xmlqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/Andro0000644000175100017510000000145115232633614033113 0ustar runnerrunner qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/0000755000175100017510000000000015232633614032715 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/values/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/v0000755000175100017510000000000015232633614033103 5ustar runnerrunner././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/values/strings.xmlqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/v0000644000175100017510000000010515232633614033101 0ustar runnerrunner dummy1 qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/0000755000175100017510000000000015232633614033045 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/0000755000175100017510000000000015232633614033045 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qt/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/0000755000175100017510000000000015232633614033045 5ustar runnerrunner././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qt/dummy1/qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/0000755000175100017510000000000015232633614033045 5ustar runnerrunner././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qt/dummy1/Dummy.javaqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/0000644000175100017510000000070715232633614033053 0ustar runnerrunnerpackage io.qt.dummy1; import android.app.Activity; import android.os.Build; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("x86") || abis.contains("mips")) { System.loadLibrary("p1lib1"); } if (abis.contains("armeabi")) { System.loadLibrary("p1lib2"); } } } qbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/0000755000175100017510000000000015232633614032704 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/lib2.cppqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/l0000644000175100017510000000234715232633614033070 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/lib1.cppqbs-src-3.3.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/l0000644000175100017510000000234715232633614033070 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxapple.cpp0000644000175100017510000017203215232633614022614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxapple.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; using qbs::Profile; class QFileInfo2 : public QFileInfo { public: QFileInfo2(const QString &path) : QFileInfo(path) { } bool isRegularFile() const { return isFile() && !isSymLink(); } bool isRegularDir() const { return isDir() && !isSymLink(); } bool isFileSymLink() const { return isFile() && isSymLink(); } bool isDirSymLink() const { return isDir() && isSymLink(); } }; static QString getEmbeddedBinaryPlist(const QString &file) { QProcess p; p.start("otool", QStringList() << "-v" << "-X" << "-s" << "__TEXT" << "__info_plist" << file); p.waitForFinished(); return QString::fromUtf8(p.readAllStandardOutput()).trimmed(); } static QVariantMap readInfoPlistFile(const QString &infoPlistPath) { if (!QFile::exists(infoPlistPath)) { qWarning() << infoPlistPath << "doesn't exist"; return {}; } QProcess plutil; plutil.start("plutil", { QStringLiteral("-convert"), QStringLiteral("json"), infoPlistPath }); if (!plutil.waitForStarted()) { qWarning() << plutil.errorString(); return {}; } if (!plutil.waitForFinished()) { qWarning() << plutil.errorString(); return {}; } if (plutil.exitCode() != 0) { qWarning() << plutil.readAllStandardError().constData(); return {}; } QFile infoPlist(infoPlistPath); if (!infoPlist.open(QIODevice::ReadOnly)) { qWarning() << infoPlist.errorString(); return {}; } QJsonParseError error; const auto json = QJsonDocument::fromJson(infoPlist.readAll(), &error); if (error.error != QJsonParseError::NoError) { qWarning() << error.errorString(); return {}; } return json.object().toVariantMap(); } static QString getInfoPlistPath(const QString &bundlePath) { QFileInfo contents(bundlePath + "/Contents"); if (contents.exists() && contents.isDir()) return contents.filePath() + "/Info.plist"; // macOS bundle return bundlePath + "/Info.plist"; } static QString getPrivacyManifestPath(const QString &bundlePath) { QFileInfo resources(bundlePath + "/Resources"); if (resources.exists()) return resources.filePath() + "/PrivacyInfo.xcprivacy"; // macOS bundle return bundlePath + "/PrivacyInfo.xcprivacy"; } static bool testVariantListType(const QVariant &variant, QMetaType::Type type) { if (variant.userType() != QMetaType::QVariantList) return false; for (const auto &value : variant.toList()) { if (value.userType() != type) return false; } return true; } static QString findFatLibrary(const QString &dir, const QString &libraryName) { QDirIterator it(dir, {}, QDir::AllEntries, QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); if (it.fileInfo().fileName() == libraryName) { QProcess lipo; lipo.start("lipo", { QStringLiteral("-info"), it.filePath() }); if (!lipo.waitForStarted() || !lipo.waitForFinished() || lipo.exitCode() != 0) return {}; auto output = lipo.readAllStandardOutput(); if (output.contains(QByteArrayLiteral("Architectures in the fat file"))) return QDir::cleanPath(it.filePath()); } } return {}; } enum class CodeSignResult { Failed = 0, Signed, Unsigned }; using CodeSignData = QMap; static std::pair parseCodeSignOutput(const QByteArray &output) { CodeSignData data; if (output.contains("code object is not signed at all")) return {CodeSignResult::Unsigned, data}; const auto lines = output.split('\n'); for (const auto &line: lines) { if (line.isEmpty() || line.startsWith("CodeDirectory") || line.startsWith("Sealed Resources") || line.startsWith("Internal requirements")) { continue; } const int index = line.indexOf('='); if (index == -1) return {CodeSignResult::Failed, {}}; data[line.mid(0, index)] = line.mid(index + 1); } return {CodeSignResult::Signed, data}; } static std::pair getCodeSignInfo(const QString &path) { QProcess codesign; codesign.start("codesign", { QStringLiteral("-dv"), path }); if (!codesign.waitForStarted() || !codesign.waitForFinished()) return {CodeSignResult::Failed, {}}; const auto output = codesign.readAllStandardError(); return parseCodeSignOutput(output); } // Up to macOS 15, codesign writes the internal requirement of a static // framework to a separate _CodeSignature/CodeRequirements-1 file; macOS 26 no // longer produces it, so the expected bundle structure must drop it there. static bool isExpectedBundleFile(const QString &relativeFilePath) { if (relativeFilePath.endsWith("_CodeSignature/CodeRequirements-1")) return HostOsInfo::hostOsVersion() < qbs::Version(26); return true; } TestBlackboxApple::TestBlackboxApple() : TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple") { } void TestBlackboxApple::initTestCase() { if (!HostOsInfo::isMacosHost()) { QSKIP("only applies on macOS"); return; } TestBlackboxBase::initTestCase(); } void TestBlackboxApple::appleMultiConfig() { const auto xcodeVersion = findXcodeVersion(); if (!xcodeVersion) QSKIP("requires Xcode profile"); QDir::setCurrent(testDataDir + "/apple-multiconfig"); QCOMPARE(runQbs(QbsRunParameters(QStringList{ "qbs.installPrefix:''", QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString()})), 0); if (m_qbsStdout.contains("isShallow: false")) { QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/MacOS/singleapp_agg").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/singlelib").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/Current").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/MacOS/fatmultiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant_debug").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant_profiling").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/Info.plist") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/PkgInfo") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_debug").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_profiling").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/Current").isDirSymLink()); for (const QString variant : { "release", "debug", "profiling" }) { const QString arch = HostOsInfo::hostOSArchitecture() == "arm64" ? "arm64" : "x86_64"; for (const QString &arch : {arch}) { QProcess process; process.setProgram("/usr/bin/arch"); process.setArguments({ "-arch", arch, "-e", "DYLD_IMAGE_SUFFIX=_" + variant, defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp" }); process.start(); process.waitForFinished(); QCOMPARE(process.exitCode(), 0); const auto processStdout = process.readAllStandardOutput(); QVERIFY2(processStdout.contains("Hello from " + variant.toUtf8() + " " + arch.toUtf8()), processStdout.constData()); } } } else if (m_qbsStdout.contains("isShallow: true")) { QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/singleapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/singleapp_agg").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/multiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/fatmultiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" "fatmultiappmultivariant").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" "fatmultiappmultivariant_debug").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" "fatmultiappmultivariant_profiling").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Info.plist") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/PkgInfo") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib_debug").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib_profiling").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Info.plist").isRegularFile()); } else { QVERIFY2(false, qPrintable(m_qbsStdout)); } } void TestBlackboxApple::aggregateDependencyLinking() { const auto xcodeVersion = findXcodeVersion(); if (!xcodeVersion) QSKIP("requires Xcode profile"); // XCode 11 produces warning about deprecation of 32-bit apps, but still works const bool hasX86Mac = xcodeVersion < qbs::Version(12); const bool hasArmMac = xcodeVersion >= qbs::Version(12, 2); QDir::setCurrent(testDataDir + "/aggregateDependencyLinking"); QbsRunParameters params{QStringList{"-p", "multi_arch_lib"}}; params.arguments << QStringLiteral("products.multi_arch_lib.hasX86Mac:%1").arg(hasX86Mac); params.arguments << QStringLiteral("products.multi_arch_lib.hasArmMac:%1").arg(hasArmMac); QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("Cannot build fat binaries")) QSKIP("Building fat binaries is not supported for this profile"); QCOMPARE(runQbs(QStringList{"-p", "just_app", "--command-echo-mode", "command-line"}), 0); int linkedInLibrariesCount = QString::fromUtf8(m_qbsStdout).count(QStringLiteral("libmulti_arch_lib.a")); QCOMPARE(linkedInLibrariesCount, 1); const auto fatLibPath = findFatLibrary(testDataDir, QStringLiteral("libmulti_arch_lib.a")); QVERIFY(!fatLibPath.isEmpty()); QVERIFY2(QString::fromUtf8(m_qbsStdout).contains(fatLibPath), m_qbsStdout); } void TestBlackboxApple::appiconset() { QDir::setCurrent(testDataDir + QLatin1String("/ib/appiconset")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "appiconset.qbs"; QCOMPARE(runQbs(params), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("appiconset") + "/appiconset.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto content = readInfoPlistFile(infoPlistPath); QVERIFY(!content.isEmpty()); if (m_qbsStdout.contains("bundle.isShallow: false")) { QCOMPARE(content.value(QStringLiteral("CFBundleIconFile")), QStringLiteral("AppIcon")); QCOMPARE(content.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); QVERIFY(regularFileExists(relativeProductBuildDir("appiconset") + "/appiconset.app/Contents/Resources/AppIcon.icns")); } else if (m_qbsStdout.contains("bundle.isShallow: true")) { const auto icons = content.value(QStringLiteral("CFBundleIcons")).toMap(); QVERIFY2(!icons.isEmpty(), "Info.plist doesn't contain CFBundleIcons key"); const auto primaryIcon = icons.value(QStringLiteral("CFBundlePrimaryIcon")).toMap(); QVERIFY2(!primaryIcon.isEmpty(), "Info.plist doesn't contain CFBundlePrimaryIcon key"); QCOMPARE(primaryIcon.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); } else { QVERIFY2(false, "Cannot determine bundle type"); } } void TestBlackboxApple::iconcomposer() { const auto xcodeVersion = findXcodeVersion(); if (!xcodeVersion || *xcodeVersion < qbs::Version(26)) QSKIP("Icon Composer .icon format requires Xcode 26 or newer"); QDir::setCurrent(testDataDir + QLatin1String("/ib/iconcomposer")); const QString iconPath = QDir::currentPath() + "/AppIcon.icon"; QDir iconDir(iconPath); if (!iconDir.exists() || iconDir.entryList(QDir::Files | QDir::NoDotAndDotDot).isEmpty() || (iconDir.entryList(QDir::Files | QDir::NoDotAndDotDot).size() == 1 && iconDir.exists("README.txt"))) { QSKIP("This test requires a valid AppIcon.icon file created with Icon Composer. " "Replace the placeholder with a real .icon bundle to run this test."); } QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconcomposer.qbs"; QCOMPARE(runQbs(params), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("iconcomposer") + "/iconcomposer.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto content = readInfoPlistFile(infoPlistPath); QVERIFY(!content.isEmpty()); const bool isShallow = m_qbsStdout.contains("bundle.isShallow: true"); const bool isDeep = m_qbsStdout.contains("bundle.isShallow: false"); QVERIFY2(isShallow || isDeep, "Cannot determine bundle type"); if (isDeep) { QCOMPARE(content.value(QStringLiteral("CFBundleIconFile")), QStringLiteral("AppIcon")); QCOMPARE(content.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); } else if (isShallow) { const auto icons = content.value(QStringLiteral("CFBundleIcons")).toMap(); QVERIFY2(!icons.isEmpty(), "Info.plist doesn't contain CFBundleIcons key"); const auto primaryIcon = icons.value(QStringLiteral("CFBundlePrimaryIcon")).toMap(); QVERIFY2(!primaryIcon.isEmpty(), "Info.plist doesn't contain CFBundlePrimaryIcon key"); QCOMPARE(primaryIcon.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); } } void TestBlackboxApple::assetCatalog() { QFETCH(bool, flatten); QDir::setCurrent(testDataDir + QLatin1String("/ib/assetcatalog")); rmDirR(relativeBuildDir()); if (!findXcode()) QSKIP("requires Xcode profile"); QbsRunParameters params; const QString flattens = "modules.ib.flatten:" + QString(flatten ? "true" : "false"); const QString macosTarget = "modules.cpp.minimumMacosVersion:'10.15'"; // Make sure a dry run does not write anything params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << "--dry-run" << flattens << macosTarget; QCOMPARE(runQbs(params), 0); QVERIFY(!directoryExists(relativeBuildDir())); if (m_qbsStdout.contains("Skip this test")) QSKIP("Skip this test"); params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << flattens << macosTarget; QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); // empty asset catalogs must still produce output QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Assets.car")); // this asset catalog happens to have an embedded icon set, // but this should NOT be built since it is not in the files list QVERIFY(!(bool)m_qbsStdout.contains(".iconset")); // now we'll add the iconset rmDirR(relativeBuildDir()); params.arguments.push_back("project.includeIconset:true"); QCOMPARE(runQbs(params), 0); QVERIFY(!(bool)m_qbsStdout.contains("compiling empty.xcassets")); QVERIFY((bool)m_qbsStdout.contains("compiling empty.iconset")); // make sure the nibs/storyboards are in there QString nib = relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/MainMenu.nib"; QStringList nibFiles; if (flatten) { QVERIFY(regularFileExists(nib)); } else { QVERIFY(directoryExists(nib)); nibFiles = QStringList() << "designable.nib" << "keyedobjects.nib"; } QString storyboardc = relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Storyboard.storyboardc"; QStringList storyboardcFiles; if (HostOsInfo::hostOsVersion() >= qbs::Version(10, 10)) { QVERIFY(directoryExists(storyboardc)); storyboardcFiles = QStringList() << "1os-k8-h10-view-qKA-a5-eUe.nib" << "Info.plist" << "Iqk-Fi-Vhk-view-HRv-3O-Qxh.nib" << "Main.nib" << "NSViewController-Iqk-Fi-Vhk.nib" << "NSViewController-Yem-rc-72E.nib" << "Yem-rc-72E-view-ODp-aO-Dmf.nib"; if (!flatten) { storyboardcFiles << "designable.storyboard"; storyboardcFiles.sort(); } } QCOMPARE(QDir(nib).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), nibFiles); QCOMPARE(QDir(storyboardc).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), storyboardcFiles); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QCOMPARE(QDir(nib).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), QStringList()); QCOMPARE(QDir(storyboardc).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), QStringList()); } void TestBlackboxApple::assetCatalog_data() { QTest::addColumn("flatten"); QTest::newRow("flattened") << true; QTest::newRow("unflattened") << false; } void TestBlackboxApple::assetCatalogsEmpty() { if (findXcodeVersion() < qbs::Version(5)) QSKIP("requires Xcode 5 or above"); QDir::setCurrent(testDataDir + QLatin1String("/ib/empty-asset-catalogs")); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); } void TestBlackboxApple::assetCatalogsMultiple() { if (findXcodeVersion() < qbs::Version(5)) QSKIP("requires Xcode 5 or above"); QDir::setCurrent(testDataDir + QLatin1String("/ib/multiple-asset-catalogs")); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); } void TestBlackboxApple::bundleStructure() { QFETCH(QString, productName); QFETCH(QString, productTypeIdentifier); QDir::setCurrent(testDataDir + "/bundle-structure"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); params.arguments << "project.buildableProducts:" + productName; if (productName == "ABadApple" || productName == "ABadThirdParty") params.expectFailure = true; rmDirR(relativeBuildDir()); const int status = runQbs(params); if (status != 0) { QVERIFY2( m_qbsStderr.contains( "Bundle product type " + productTypeIdentifier.toLatin1() + " is not supported."), m_qbsStderr.constData()); return; } QCOMPARE(status, 0); const bool enableCodeSigning = m_qbsStdout.contains("enableCodeSigning: true"); const bool isShallow = m_qbsStdout.contains("bundle.isShallow: true"); QString expectedStructureFile; if (!isShallow) { QVERIFY2(enableCodeSigning, m_qbsStdout); expectedStructureFile = "deep.json"; } else { expectedStructureFile = enableCodeSigning ? "shallow-signed.json" : "shallow-unsigned.json"; } const QString expectedStructurePath = testDataDir + "/bundle-structure/" + expectedStructureFile; QFile structureFile(expectedStructurePath); QVERIFY2( structureFile.open(QIODevice::ReadOnly), qPrintable(QString("Could not open %1").arg(expectedStructurePath))); QJsonParseError parseError; const auto expectedStructure = QJsonDocument::fromJson(structureFile.readAll(), &parseError); QVERIFY2(parseError.error == QJsonParseError::NoError, qPrintable(parseError.errorString())); const auto allProducts = expectedStructure.object(); QVERIFY2( allProducts.contains(productName), qPrintable(QString("Product %1 not found in %2").arg(productName, expectedStructureFile))); const auto productStructure = allProducts.value(productName).toObject(); const QString bundleExtension = productStructure.value("extension").toString(); const QString bundlePath = defaultInstallRoot + "/" + productName + bundleExtension; std::unordered_set expectedPaths; // Check directories const auto directories = productStructure.value("directories").toArray(); for (const auto &dir : directories) { const QString dirPath = bundlePath + "/" + dir.toString(); expectedPaths.insert(dirPath); QVERIFY2( QFileInfo2(dirPath).isRegularDir(), qPrintable(QString("Directory does not exist: %1").arg(dirPath))); } // Check files const auto files = productStructure.value("files").toArray(); for (const auto &file : files) { const QString relativeFilePath = file.toString(); if (!isExpectedBundleFile(relativeFilePath)) continue; const QString filePath = bundlePath + "/" + relativeFilePath; expectedPaths.insert(filePath); QVERIFY2( QFileInfo2(filePath).isRegularFile(), qPrintable(QString("File does not exist: %1").arg(filePath))); } // Check symlinks const auto symlinks = productStructure.value("symlinks").toArray(); for (const auto &symlink : symlinks) { const QString symlinkPath = bundlePath + "/" + symlink.toString(); expectedPaths.insert(symlinkPath); QVERIFY2( QFileInfo2(symlinkPath).isSymLink(), qPrintable(QString("Symlink does not exist: %1").arg(symlinkPath))); } // Check that there are no extra entries beyond what's expected QDirIterator it( bundlePath, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (it.hasNext()) { const QString absolutePath = it.next(); const QString relativePath = QDir(bundlePath).relativeFilePath(absolutePath); QVERIFY2( expectedPaths.count(absolutePath) != 0, qPrintable(QString("Unexpected file/directory found in bundle: %1").arg(relativePath))); } } void TestBlackboxApple::bundleStructure_data() { QTest::addColumn("productName"); QTest::addColumn("productTypeIdentifier"); QTest::newRow("A") << "A" << "com.apple.product-type.application"; QTest::newRow("ABadApple") << "ABadApple" << "com.apple.product-type.will.never.exist.ever.guaranteed"; QTest::newRow("ABadThirdParty") << "ABadThirdParty" << "org.special.third.party.non.existent.product.type"; QTest::newRow("B") << "B" << "com.apple.product-type.framework"; QTest::newRow("C") << "C" << "com.apple.product-type.framework.static"; QTest::newRow("D") << "D" << "com.apple.product-type.bundle"; QTest::newRow("E") << "E" << "com.apple.product-type.app-extension"; QTest::newRow("F") << "F" << "com.apple.product-type.xpc-service"; QTest::newRow("G") << "G" << "com.apple.product-type.in-app-purchase-content"; } void TestBlackboxApple::mainBundle() { QFETCH(bool, multiplexArchitectures); QFETCH(bool, multiplexBuildVariants); QDir::setCurrent(testDataDir + "/main-bundle"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); const auto xcodeVersion = findXcodeVersion(); if (!xcodeVersion) QSKIP("requires Xcode profile"); params.arguments << "project.xcodeVersion:" + xcodeVersion->toString(); if (multiplexArchitectures) params.arguments << "project.multiplexArchitectures:true"; if (multiplexBuildVariants) params.arguments << "project.multiplexBuildVariants:true"; rmDirR(relativeBuildDir()); const int status = runQbs(params); QCOMPARE(status, 0); const bool enableCodeSigning = m_qbsStdout.contains("enableCodeSigning: true"); const bool isShallow = m_qbsStdout.contains("bundle.isShallow: true"); QString expectedStructureFile; if (!isShallow) { QVERIFY2(enableCodeSigning, m_qbsStdout); expectedStructureFile = "deep.json"; } else { expectedStructureFile = enableCodeSigning ? "shallow-signed.json" : "shallow-unsigned.json"; } const QString expectedStructurePath = testDataDir + "/main-bundle/" + expectedStructureFile; QFile structureFile(expectedStructurePath); QVERIFY2( structureFile.open(QIODevice::ReadOnly), qPrintable(QString("Could not open %1").arg(expectedStructurePath))); QJsonParseError parseError; const auto expectedStructure = QJsonDocument::fromJson(structureFile.readAll(), &parseError); QVERIFY2(parseError.error == QJsonParseError::NoError, qPrintable(parseError.errorString())); const auto structure = expectedStructure.object(); const QString appPath = defaultInstallRoot + "/MainApp.app"; std::unordered_set expectedPaths; // Check directories const auto directories = structure.value("directories").toArray(); for (const auto &dir : directories) { const QString dirPath = appPath + "/" + dir.toString(); expectedPaths.insert(dirPath); QVERIFY2( QFileInfo2(dirPath).isRegularDir(), qPrintable(QString("Directory does not exist: %1").arg(dirPath))); } // Check files const auto files = structure.value("files").toArray(); for (const auto &file : files) { const QString relativeFilePath = file.toString(); if (!isExpectedBundleFile(relativeFilePath)) continue; const QString filePath = appPath + "/" + relativeFilePath; expectedPaths.insert(filePath); QVERIFY2( QFileInfo2(filePath).isRegularFile(), qPrintable(QString("File does not exist: %1").arg(filePath))); } // Check symlinks const auto symlinks = structure.value("symlinks").toArray(); for (const auto &symlink : symlinks) { const QString symlinkPath = appPath + "/" + symlink.toString(); expectedPaths.insert(symlinkPath); QVERIFY2( QFileInfo2(symlinkPath).isSymLink(), qPrintable(QString("Symlink does not exist: %1").arg(symlinkPath))); } // Check that there are no extra entries beyond what's expected QDirIterator it(appPath, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (it.hasNext()) { const QString absolutePath = it.next(); const QString relativePath = QDir(appPath).relativeFilePath(absolutePath); // skip debug build variants manually if (multiplexBuildVariants && QFileInfo(absolutePath).baseName().endsWith("_debug")) continue; QVERIFY2( expectedPaths.count(absolutePath) != 0, qPrintable(QString("Unexpected file/directory found in bundle: %1").arg(relativePath))); } } void TestBlackboxApple::mainBundle_data() { QTest::addColumn("multiplexArchitectures"); QTest::addColumn("multiplexBuildVariants"); QTest::newRow("no multiplexing") << false << false; QTest::newRow("multiplex architectures") << true << false; QTest::newRow("multiplex build variants") << false << true; QTest::newRow("multiplex architectures and build variants") << true << true; } void TestBlackboxApple::byteArrayInfoPlist() { QDir::setCurrent(testDataDir + "/byteArrayInfoPlist"); QCOMPARE(runQbs(), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("byteArrayInfoPlist") + "/byteArrayInfoPlist.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto outFilePath = relativeProductBuildDir("byteArrayInfoPlist") + "/bytearrayInfoPlist-Info.plist.out"; QFile file(outFilePath); QVERIFY(file.exists()); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), "The data value"); } void TestBlackboxApple::codesign() { QFETCH(int, expectedCount); QFETCH(bool, isBundle); QFETCH(bool, enableSigning); QFETCH(bool, multiArch); QFETCH(bool, multiVariant); const auto xcode = findXcode(); if (!xcode) QSKIP("requires Xcode profile"); const auto xcodeVersion = qbs::Version::fromString(xcode->value("version").toString()); const bool isSigned = xcode->value("isSignedByDefault").toBool() || enableSigning; QDir::setCurrent(testDataDir + "/codesign"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); // the test can't use xcode module to determine version itself params.arguments << QStringLiteral("project.xcodeVersion:") + xcodeVersion.toString(); params.arguments << QStringLiteral("project.isBundle:%1").arg(isBundle ? "true" : "false"); params.arguments << QStringLiteral("project.enableSigning:%1") .arg(enableSigning ? "true" : "false"); params.arguments << QStringLiteral("project.multiArch:%1").arg(multiArch ? "true" : "false"); params.arguments << QStringLiteral("project.multiVariant:%1") .arg(multiVariant ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); const int codeSignCount = QString::fromUtf8(m_qbsStdout).count(QStringLiteral("codesign ")); QCOMPARE(codeSignCount, expectedCount); const auto appName = isBundle ? QStringLiteral("A.app") : QStringLiteral("A"); const auto appPath = defaultInstallRoot + "/" + appName; QVERIFY(QFileInfo(appPath).exists()); auto codeSignInfo = getCodeSignInfo(appPath); QVERIFY(codeSignInfo.first != CodeSignResult::Failed); QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, isSigned); QCOMPARE(codeSignInfo.second.isEmpty(), !isSigned); if (!codeSignInfo.second.isEmpty()) { QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); } const auto libName = isBundle ? QStringLiteral("B.framework") : QStringLiteral("libB.1.0.0.dylib"); const auto libPath = defaultInstallRoot + "/" + libName; QVERIFY(QFileInfo(libPath).exists()); codeSignInfo = getCodeSignInfo(libPath); QVERIFY(codeSignInfo.first != CodeSignResult::Failed); QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, isSigned); QCOMPARE(codeSignInfo.second.isEmpty(), !isSigned); if (!codeSignInfo.second.isEmpty()) { QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); } const auto pluginPath = defaultInstallRoot + "/" + QStringLiteral("C.bundle"); QVERIFY(QFileInfo(pluginPath).exists()); QVERIFY(QFileInfo(pluginPath).isDir() == isBundle); codeSignInfo = getCodeSignInfo(pluginPath); QVERIFY(codeSignInfo.first != CodeSignResult::Failed); QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, isSigned); QCOMPARE(codeSignInfo.second.isEmpty(), !isSigned); if (!codeSignInfo.second.isEmpty()) { QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); } const auto staticLibName = isBundle ? QStringLiteral("D.framework") : QStringLiteral("libD.a"); const auto staticLibPath = defaultInstallRoot + "/" + staticLibName; QVERIFY(QFileInfo(staticLibPath).exists()); codeSignInfo = getCodeSignInfo(staticLibPath); QVERIFY(codeSignInfo.first != CodeSignResult::Failed); // static libraries are not signed by default so we check for enableSigning instead of isSigned QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning); QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning); if (!codeSignInfo.second.isEmpty()) { QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); } } void TestBlackboxApple::codesign_data() { QTest::addColumn("expectedCount"); QTest::addColumn("isBundle"); QTest::addColumn("enableSigning"); QTest::addColumn("multiArch"); QTest::addColumn("multiVariant"); QTest::newRow("standalone, unsigned") << 0 << false << false << false << false; QTest::newRow("bundle, unsigned") << 0 << true << false << false << false; QTest::newRow("standalone, signed") << 4 << false << true << false << false; QTest::newRow("bundle, signed") << 4 << true << true << false << false; // here we only sign the resulting lipo artifact QTest::newRow("standalone, signed, multiarch") << 4 << false << true << true << false; QTest::newRow("bundle, signed, multiarch") << 4 << true << true << true << false; // here we sign all artifacts QTest::newRow("standalone, signed, multivariant") << 8 << false << true << false << true; QTest::newRow("bundle, signed, multivariant") << 8 << true << true << false << true; QTest::newRow("standalone, signed, multiarch, multivariant") << 8 << false << true << true << true; QTest::newRow("bundle, signed, multiarch, multivariant") << 8 << true << true << true << true; } void TestBlackboxApple::codesignDestinationDirectory() { // checks that codesign does not break when destinationDirectory is set QDir::setCurrent(testDataDir + "/codesign-destination-directory"); QCOMPARE(runQbs(), 0); } void TestBlackboxApple::deploymentTarget() { QFETCH(QString, sdk); QFETCH(QString, os); QFETCH(QString, arch); QFETCH(QString, cflags); QFETCH(QString, lflags); QDir::setCurrent(testDataDir + "/deploymentTarget"); if (!findXcode()) QSKIP("requires Xcode profile"); QbsRunParameters params; params.arguments = QStringList() << "--command-echo-mode" << "command-line" << "modules.qbs.targetPlatform:" + os << "qbs.architectures:" + arch; rmDirR(relativeBuildDir()); int status = runQbs(params); const QStringList skippableMessages = QStringList() << "There is no matching SDK available for " + sdk + "." << "x86_64h will be mis-detected as x86_64 with Apple Clang < 6.0" << "clang: error: unknown argument: '-mtvos-version-min" << "clang: error: unknown argument: '-mtvos-simulator-version-min" << "clang: error: unknown argument: '-mwatchos-version-min" << "clang: error: unknown argument: '-mwatchos-simulator-version-min"; if (status != 0) { for (const auto &message : skippableMessages) { if (m_qbsStderr.contains(message.toUtf8())) QSKIP(message.toUtf8()); } } QCOMPARE(status, 0); QVERIFY2(m_qbsStderr.contains(cflags.toLatin1()), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains(lflags.toLatin1()), m_qbsStderr.constData()); } void TestBlackboxApple::deploymentTarget_data() { static const QString macos = QStringLiteral("macos"); static const QString ios = QStringLiteral("ios"); static const QString ios_sim = QStringLiteral("ios-simulator"); static const QString tvos = QStringLiteral("tvos"); static const QString tvos_sim = QStringLiteral("tvos-simulator"); static const QString watchos = QStringLiteral("watchos"); static const QString watchos_sim = QStringLiteral("watchos-simulator"); QTest::addColumn("sdk"); QTest::addColumn("os"); QTest::addColumn("arch"); QTest::addColumn("cflags"); QTest::addColumn("lflags"); const auto xcodeVersion = findXcodeVersion(); QTest::newRow("macos arm64") << "macosx" << macos << "arm64" << "-triple arm64-apple-macosx11.0" << "-platform_version macos 11.0.0"; if (xcodeVersion < qbs::Version(10)) { QTest::newRow("macos x86") << "macosx" << macos << "x86" << "-triple i386-apple-macosx10.6" << "-macosx_version_min 10.6"; } QTest::newRow("macos x86_64") << "macosx" << macos << "x86_64" << "-triple x86_64-apple-macosx10.6" << "10.6"; if (xcodeVersion >= qbs::Version(6)) QTest::newRow("macos x86_64h") << "macosx" << macos << "x86_64h" << "-triple x86_64h-apple-macosx10.12" << "10.12"; if (xcodeVersion < qbs::Version(16)) { QTest::newRow("ios armv7a") << "iphoneos" << ios << "armv7a" << "-triple thumbv7-apple-ios6.0" << "6.0"; QTest::newRow("ios armv7s") << "iphoneos" << ios << "armv7s" << "-triple thumbv7s-apple-ios7.0" << "7.0"; } if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios arm64") << "iphoneos" << ios << "arm64" << "-triple arm64-apple-ios7.0" << "7.0"; if (xcodeVersion < qbs::Version(16)) { QTest::newRow("ios-simulator x86") << "iphonesimulator" << ios_sim << "x86" << "-triple i386-apple-ios6.0" << "6.0"; if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios-simulator x86_64") << "iphonesimulator" << ios_sim << "x86_64" << "-triple x86_64-apple-ios7.0" << "7.0"; } if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios-simulator arm64") << "iphonesimulator" << ios_sim << "arm64" << "-triple arm64-apple-ios7.0" << "7.0"; if (xcodeVersion >= qbs::Version(7)) { if (xcodeVersion >= qbs::Version(7, 1)) { QTest::newRow("tvos arm64") << "appletvos" << tvos << "arm64" << "-triple arm64-apple-tvos9.0" << "9.0"; QTest::newRow("tvos-simulator x86_64") << "appletvsimulator" << tvos_sim << "x86_64" << "-triple x86_64-apple-tvos9.0" << "9.0"; } QTest::newRow("watchos armv7k") << "watchos" << watchos << "armv7k" << "-triple thumbv7k-apple-watchos2.0" << "2.0"; QTest::newRow("watchos-simulator x86") << "watchsimulator" << watchos_sim << "x86" << "-triple i386-apple-watchos2.0" << "2.0"; } } void TestBlackboxApple::dmg() { if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) QSKIP("Skip this test when running on GitHub"); QDir::setCurrent(testDataDir + "/apple-dmg"); QCOMPARE(runQbs(), 0); } void TestBlackboxApple::embedInfoPlist() { QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist")); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); QCOMPARE(runQbs(params), 0); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/app").isEmpty()); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/liblib.dylib").isEmpty()); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/mod.bundle").isEmpty()); params.arguments = QStringList(QLatin1String("modules.bundle.embedInfoPlist:false")); params.expectFailure = true; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/app").isEmpty()); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/liblib.dylib").isEmpty()); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/mod.bundle").isEmpty()); } void TestBlackboxApple::frameworkStructure() { QDir::setCurrent(testDataDir + QLatin1String("/frameworkStructure")); QbsRunParameters params; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("isShallow: false")) { QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Widget")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Headers/Widget.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/PrivateHeaders/WidgetPrivate.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/BaseResource")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/en.lproj/EnglishResource")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/Current")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Resources")); } else if (m_qbsStdout.contains("isShallow: true")) { QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers/Widget.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders/WidgetPrivate.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/BaseResource")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/en.lproj/EnglishResource")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); } else { QVERIFY2(false, qPrintable(m_qbsStdout)); } params.command = "resolve"; params.arguments = QStringList() << "project.includeHeaders:false"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); } void TestBlackboxApple::iconset() { QDir::setCurrent(testDataDir + QLatin1String("/ib/iconset")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconset.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("iconset") + "/white.icns")); } void TestBlackboxApple::iconsetApp() { QDir::setCurrent(testDataDir + QLatin1String("/ib/iconsetapp")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconsetapp.qbs"; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("isShallow: false")) { QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + "/iconsetapp.app/Contents/Resources/white.icns")); } else if (m_qbsStdout.contains("isShallow: true")) { QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + "/iconsetapp.app/white.icns")); } else { QVERIFY2(false, qPrintable(m_qbsStdout)); } } void TestBlackboxApple::privacymanifest() { QDir::setCurrent(testDataDir + "/privacymanifest"); QbsRunParameters params; params.arguments = QStringList() << "-f" << "privacymanifest.qbs"; QCOMPARE(runQbs(params), 0); const auto privacymanifestPath = getPrivacyManifestPath( relativeProductBuildDir("Lib") + "/Lib.framework"); QVERIFY(QFile::exists(privacymanifestPath)); const auto content = readInfoPlistFile(privacymanifestPath); QVERIFY(!content.isEmpty()); QCOMPARE(content.value(QStringLiteral("NSPrivacyTracking")), false); QCOMPARE(content.value(QStringLiteral("NSPrivacyTrackingDomains")), QVariantList()); QCOMPARE(content.value(QStringLiteral("NSPrivacyAccessedAPITypes")), QVariantList()); QCOMPARE(content.value(QStringLiteral("NSPrivacyCollectedDataTypes")), QVariantList()); } void TestBlackboxApple::infoPlist() { QDir::setCurrent(testDataDir + "/infoplist"); QbsRunParameters params; params.arguments = QStringList() << "-f" << "infoplist.qbs"; QCOMPARE(runQbs(params), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("infoplist") + "/infoplist.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto content = readInfoPlistFile(infoPlistPath); QVERIFY(!content.isEmpty()); // common values QCOMPARE(content.value(QStringLiteral("CFBundleIdentifier")), QStringLiteral("org.example.infoplist")); QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist")); QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), QStringLiteral("infoplist")); if (!content.contains(QStringLiteral("SDKROOT"))) { // macOS-specific values QCOMPARE(content.value("LSMinimumSystemVersion"), QStringLiteral("10.7")); QCOMPARE(content.value("NSPrincipalClass"), QStringLiteral("NSApplication")); QCOMPARE(content.value(QStringLiteral("NSSupportsAutomaticGraphicsSwitching")), true); } else { // QBS-1447: UIDeviceFamily was set to a string instead of an array const auto family = content.value(QStringLiteral("UIDeviceFamily")); if (family.isValid()) { // Prior to Qt 5.15, int gets converted to a double when exporting plist as JSON QVERIFY(testVariantListType(family, QMetaType::LongLong) || testVariantListType(family, QMetaType::Double)); } const auto caps = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); if (caps.isValid()) QVERIFY(testVariantListType(caps, QMetaType::QString)); const auto orientations = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); if (orientations.isValid()) QVERIFY(testVariantListType(orientations, QMetaType::QString)); } } void TestBlackboxApple::infoPlistVariables() { QDir::setCurrent(testDataDir + "/infoPlistVariables"); QbsRunParameters params; params.arguments = QStringList() << "-f" << "infoPlistVariables.qbs"; QCOMPARE(runQbs(params), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("infoPlistVariables") + "/infoPlistVariables.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto content = readInfoPlistFile(infoPlistPath); QVERIFY(!content.isEmpty()); QCOMPARE(content.value(QStringLiteral("Curly")), QStringLiteral("infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("Braces")), QStringLiteral("infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("At")), QStringLiteral("infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("CurlyMult")), QStringLiteral("infoPlistVariables_infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("BracesMult")), QStringLiteral("infoPlistVariables_infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("AtMult")), QStringLiteral("infoPlistVariables_infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("CurlyNested")), QStringLiteral("infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("BracesNested")), QStringLiteral("infoPlistVariables")); QCOMPARE(content.value(QStringLiteral("WithDefault")), QStringLiteral("DEFAULT")); } void TestBlackboxApple::lipoSymlinks() { QFETCH(bool, multiArch); QFETCH(bool, multiVariant); const auto xcodeVersion = findXcodeVersion(); if (!xcodeVersion) QSKIP("requires Xcode profile"); QDir::setCurrent(testDataDir + "/lipo-symlinks"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); // the test can't use xcode module to determine version itself params.arguments << QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString(); params.arguments << QStringLiteral("project.multiArch:%1").arg(multiArch ? "true" : "false"); params.arguments << QStringLiteral("project.multiVariant:%1") .arg(multiVariant ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); const auto libraryDirPath = QStringList{{relativeBuildDir(), "install-root"}}.join("/"); const auto checkSymLink = [](const auto &path, const auto &targetPath) { QFileInfo fi(path); return fi.exists() && fi.isSymbolicLink() && fi.symLinkTarget() == targetPath; }; const auto libraryPath = QFileInfo(QStringList{{libraryDirPath, "libA.1.2.3.dylib"}}.join("/")).absoluteFilePath(); QVERIFY(QFileInfo(libraryPath).exists() && !QFileInfo(libraryPath).isSymbolicLink()); QVERIFY(checkSymLink(QStringList{{libraryDirPath, "libA.1.2.dylib"}}.join("/"), libraryPath)); QVERIFY(checkSymLink(QStringList{{libraryDirPath, "libA.1.dylib"}}.join("/"), libraryPath)); QVERIFY(checkSymLink(QStringList{{libraryDirPath, "libA.dylib"}}.join("/"), libraryPath)); if (multiArch && multiVariant) { // in this case there are 2 libs and 2 sets of symlinks const auto debugLibraryPath = QFileInfo(QStringList{{libraryDirPath, "libA_debug.1.2.3.dylib"}}.join("/")) .absoluteFilePath(); QVERIFY( QFileInfo(debugLibraryPath).exists() && !QFileInfo(debugLibraryPath).isSymbolicLink()); QVERIFY(checkSymLink( QStringList{{libraryDirPath, "libA_debug.1.2.dylib"}}.join("/"), debugLibraryPath)); QVERIFY(checkSymLink( QStringList{{libraryDirPath, "libA_debug.1.dylib"}}.join("/"), debugLibraryPath)); QVERIFY(checkSymLink( QStringList{{libraryDirPath, "libA_debug.dylib"}}.join("/"), debugLibraryPath)); } } void TestBlackboxApple::lipoSymlinks_data() { QTest::addColumn("multiArch"); QTest::addColumn("multiVariant"); QTest::newRow("standalone") << false << false; QTest::newRow("multiArch") << true << false; QTest::newRow("multiVariant") << false << true; QTest::newRow("multiArch, multiVariant") << true << true; } void TestBlackboxApple::objcArc() { QDir::setCurrent(testDataDir + QLatin1String("/objc-arc")); QCOMPARE(runQbs(), 0); } void TestBlackboxApple::overrideInfoPlist() { QDir::setCurrent(testDataDir + "/overrideInfoPlist"); QCOMPARE(runQbs(), 0); const auto infoPlistPath = getInfoPlistPath( relativeProductBuildDir("overrideInfoPlist") + "/overrideInfoPlist.app"); QVERIFY(QFile::exists(infoPlistPath)); const auto content = readInfoPlistFile(infoPlistPath); QVERIFY(!content.isEmpty()); // test we do not override custom values by default QCOMPARE(content.value(QStringLiteral("DefaultValue")), QStringLiteral("The default value")); // test we can override custom values QCOMPARE(content.value(QStringLiteral("OverriddenValue")), QStringLiteral("The overridden value")); // test we do not override special values set by Qbs by default QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), QStringLiteral("overrideInfoPlist")); // test we can override special values set by Qbs QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("My Bundle")); } void TestBlackboxApple::xcode() { if (!findXcode()) QSKIP("requires Xcode profile"); QProcess xcodeSelect; xcodeSelect.start("xcode-select", QStringList() << "--print-path"); QVERIFY2(xcodeSelect.waitForStarted(), qPrintable(xcodeSelect.errorString())); QVERIFY2(xcodeSelect.waitForFinished(), qPrintable(xcodeSelect.errorString())); QVERIFY2(xcodeSelect.exitCode() == 0, qPrintable(xcodeSelect.readAllStandardError().constData())); const QString developerPath(QString::fromLocal8Bit(xcodeSelect.readAllStandardOutput().trimmed())); std::multimap sdks; QProcess xcodebuildShowSdks; xcodebuildShowSdks.start("xcrun", QStringList() << "xcodebuild" << "-showsdks"); QVERIFY2(xcodebuildShowSdks.waitForStarted(), qPrintable(xcodebuildShowSdks.errorString())); QVERIFY2(xcodebuildShowSdks.waitForFinished(), qPrintable(xcodebuildShowSdks.errorString())); QVERIFY2(xcodebuildShowSdks.exitCode() == 0, qPrintable(xcodebuildShowSdks.readAllStandardError().constData())); const auto lines = QString::fromLocal8Bit(xcodebuildShowSdks.readAllStandardOutput().trimmed()) .split('\n', Qt::SkipEmptyParts); for (const QString &line : lines) { static const std::regex regexp("^.+\\s+\\-sdk\\s+([a-z]+)([0-9]+\\.[0-9]+)$"); const auto ln = line.toStdString(); std::smatch match; if (std::regex_match(ln, match, regexp)) sdks.insert({ match[1], match[2] }); } const auto getSdksByType = [&sdks]() { QStringList result; std::string sdkType; QStringList sdkValues; for (const auto &sdk: sdks) { if (!sdkType.empty() && sdkType != sdk.first) { result.append(QStringLiteral("%1:['%2']") .arg(QString::fromStdString(sdkType), sdkValues.join("','"))); sdkValues.clear(); } sdkType = sdk.first; sdkValues.append(QString::fromStdString(sdk.second)); } return result; }; QDir::setCurrent(testDataDir + "/xcode"); QbsRunParameters params; params.arguments = (QStringList() << (QStringLiteral("modules.xcode.developerPath:") + developerPath) << (QStringLiteral("project.sdks:{") + getSdksByType().join(",") + "}")); QCOMPARE(runQbs(params), 0); } QTEST_MAIN(TestBlackboxApple) std::optional TestBlackboxApple::findXcode(int *status) { QTemporaryDir temp; QbsRunParameters params = QStringList({"-f", testDataDir + "/find/find-xcode.qbs"}); params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-xcode") + "/xcode.json"); if (!file.open(QIODevice::ReadOnly)) return {}; auto result = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); if (!result["present"].toBool()) return {}; return result; } std::optional TestBlackboxApple::findXcodeVersion() { const auto xcode = findXcode(); if (!xcode) return {}; return qbs::Version::fromString(xcode->value("version").toString()); } qbs-src-3.3.1/tests/auto/blackbox/blackbox-providers.qbs0000644000175100017510000000101515232633614022706 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-providers" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-providers/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxproviders.cpp", "tst_blackboxproviders.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxjava.cpp0000644000175100017510000002450515232633614022435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxjava.h" #include "../shared.h" #include #include #include #include #include using qbs::Internal::HostOsInfo; using qbs::Profile; TestBlackboxJava::TestBlackboxJava() : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java"), m_blacklistedJdks(qgetenv("QBS_AUTOTEST_JDK_BLACKLIST")) { } static QProcessEnvironment processEnvironmentWithCurrentDirectoryInLibraryPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(HostOsInfo::libraryPathEnvironmentVariable(), (QStringList() << env.value(HostOsInfo::libraryPathEnvironmentVariable()) << ".") .join(HostOsInfo::pathListSeparator())); return env; } void TestBlackboxJava::java() { #if defined(Q_OS_WIN32) && !defined(Q_OS_WIN64) QSKIP("QTBUG-3845"); #endif const SettingsPtr s = settings(); Profile p(profileName(), s.get()); int status; const auto jdkTools = findJdkTools(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + "/java"); status = runQbs(); if (p.value("java.jdkPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("jdkPath")) { QSKIP("java.jdkPath not set and automatic detection failed"); } if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Skip test in cross-compiled build"); QCOMPARE(status, 0); const QStringList classFiles = QStringList() << "Jet" << "Ship" << "Vehicles"; QStringList classFiles1 = QStringList(classFiles) << "io/qt/qbs/HelloWorld" << "NoPackage"; for (QString &classFile : classFiles1) { classFile = relativeProductBuildDir("cc") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(classFile), qPrintable(classFile)); } for (const QString &classFile : classFiles) { const QString filePath = relativeProductBuildDir("jar_file") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(filePath), qPrintable(filePath)); } const QString jarFilePath = relativeProductBuildDir("jar_file") + '/' + "jar_file.jar"; QVERIFY2(regularFileExists(jarFilePath), qPrintable(jarFilePath)); // Now check whether we correctly predicted the class file output paths. QCOMPARE(runQbs(QbsRunParameters("clean")), 0); for (const QString &classFile : std::as_const(classFiles1)) { QVERIFY2(!regularFileExists(classFile), qPrintable(classFile)); } // This tests various things: java.manifestClassPath, JNI, etc. QDir::setCurrent(relativeBuildDir() + "/install-root"); QProcess process; process.setProcessEnvironment(processEnvironmentWithCurrentDirectoryInLibraryPath()); process.start(HostOsInfo::appendExecutableSuffix(jdkTools["java"]), QStringList() << "-jar" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QVERIFY2(process.exitCode() == 0, process.readAllStandardError().constData()); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Driving!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying (this is a space ship)!"), stdOut.constData()); QVERIFY2(stdOut.contains("Sailing!"), stdOut.constData()); QVERIFY2(stdOut.contains("Native code performing complex internal combustion process ("), stdOut.constData()); } process.start("unzip", QStringList() << "-p" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Class-Path: random_stuff.jar car_jar.jar"), stdOut.constData()); QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData()); QVERIFY2(stdOut.contains("Some-Property: Some-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Additional-Property: Additional-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Extra-Property: Crazy-Value"), stdOut.constData()); } } static QString dpkgArch(const QString &prefix = QString()) { QProcess dpkg; dpkg.start("/usr/bin/dpkg", QStringList() << "--print-architecture"); dpkg.waitForFinished(); if (dpkg.exitStatus() == QProcess::NormalExit && dpkg.exitCode() == 0) return prefix + QString::fromLocal8Bit(dpkg.readAllStandardOutput().trimmed()); return {}; } void TestBlackboxJava::javaDependencyTracking() { QFETCH(QString, jdkPath); QFETCH(QString, javaVersion); QDir::setCurrent(testDataDir + "/java"); QbsRunParameters rp; rp.arguments.push_back("--check-outputs"); if (!jdkPath.isEmpty()) { if (m_blacklistedJdks.contains(jdkPath)) QSKIP("skipping blacklisted JDK"); rp.arguments << ("modules.java.jdkPath:" + jdkPath); } if (!javaVersion.isEmpty()) rp.arguments << ("modules.java.languageVersion:'" + javaVersion + "'"); rmDirR(relativeBuildDir()); const bool defaultJdkPossiblyTooOld = jdkPath.isEmpty() && !javaVersion.isEmpty(); rp.expectFailure = defaultJdkPossiblyTooOld; QVERIFY(runQbs(rp) == 0 || (defaultJdkPossiblyTooOld && m_qbsStderr.contains("invalid source release"))); } void TestBlackboxJava::javaDependencyTracking_data() { QTest::addColumn("jdkPath"); QTest::addColumn("javaVersion"); const SettingsPtr s = settings(); Profile p(profileName(), s.get()); auto getSpecificJdkVersion = [](const QString &jdkVersion) -> QString { if (HostOsInfo::isMacosHost()) { QProcess java_home; java_home.start("/usr/libexec/java_home", {"--version", jdkVersion, "--failfast"}); java_home.waitForFinished(); if (java_home.exitStatus() == QProcess::NormalExit && java_home.exitCode() == 0) return QString::fromLocal8Bit(java_home.readAllStandardOutput().trimmed()); } else if (HostOsInfo::isWindowsHost()) { QSettings settings("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\" + jdkVersion, QSettings::NativeFormat); return settings.value("JavaHome").toString(); } else { QString minorVersion = jdkVersion; if (minorVersion.startsWith("1.")) minorVersion.remove(0, 2); const QStringList searchPaths = { "/usr/lib/jvm/java-" + minorVersion + "-openjdk" + dpkgArch("-"), // Debian "/usr/lib/jvm/java-" + minorVersion + "-openjdk", // Arch "/usr/lib/jvm/jre-1." + minorVersion + ".0-openjdk", // Fedora "/usr/lib64/jvm/java-1." + minorVersion + ".0-openjdk", // OpenSuSE }; for (const QString &searchPath : searchPaths) { if (QFile::exists(searchPath + "/bin/javac")) return searchPath; } } return {}; }; static const auto knownJdkVersions = QStringList() << "1.7" << "1.8" << "1.9" << QString(); // default JDK; QStringList seenJdkVersions; for (const auto &jdkVersion : knownJdkVersions) { QString specificJdkPath = getSpecificJdkVersion(jdkVersion); if (jdkVersion.isEmpty() || !specificJdkPath.isEmpty()) { const auto jdkPath = jdkVersion.isEmpty() ? jdkVersion : specificJdkPath; if (!jdkVersion.isEmpty()) seenJdkVersions << jdkVersion; if (!seenJdkVersions.empty()) { const auto javaVersions = QStringList() << knownJdkVersions.mid(0, knownJdkVersions.indexOf(seenJdkVersions.last()) + 1) << QString(); // also test with no explicitly specified source version for (const auto ¤tJavaVersion : javaVersions) { const QString rowName = (!jdkPath.isEmpty() ? jdkPath : "default JDK") + QStringLiteral(", ") + (!currentJavaVersion.isEmpty() ? ("Java " + currentJavaVersion) : "default Java version"); QTest::newRow(rowName.toLatin1().constData()) << jdkPath << currentJavaVersion; } } } } if (seenJdkVersions.empty()) QSKIP("No JDKs installed"); } void TestBlackboxJava::javaDependencyTrackingInnerClass() { const SettingsPtr s = settings(); Profile p(profileName(), s.get()); QDir::setCurrent(testDataDir + "/java/inner-class"); QbsRunParameters params; int status = runQbs(params); if (p.value("java.jdkPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("jdkPath")) { QSKIP("java.jdkPath not set and automatic detection failed"); } QCOMPARE(status, 0); } QTEST_MAIN(TestBlackboxJava) qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxtutorial.cpp0000644000175100017510000000511515232633614023353 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackboxtutorial.h" #include #include static QStringList collectProjects(const QString &dirPath) { QStringList result; QDir dir(dirPath); const auto subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); for (const auto &subDir : subDirs) { const auto path = dir.filePath(subDir); if (!QFileInfo::exists(path + "/myproject.qbs")) continue; result.append(dir.relativeFilePath(path)); } return result; } TestBlackboxTutorial::TestBlackboxTutorial() : TestBlackboxBase(SRCDIR "/../../../tutorial/", "blackbox-tutorial") {} void TestBlackboxTutorial::tutorial_data() { QTest::addColumn("project"); const auto projects = collectProjects(testDataDir); for (const auto &project : projects) { QTest::newRow(project.toUtf8().data()) << project; } } void TestBlackboxTutorial::tutorial() { QFETCH(QString, project); QVERIFY(QDir::setCurrent(testDataDir + "/" + project)); QCOMPARE(runQbs(), 0); } QTEST_MAIN(TestBlackboxTutorial) qbs-src-3.3.1/tests/auto/blackbox/blackbox-tutorial.qbs0000644000175100017510000000101115232633614022530 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-tutorial" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "../../../tutorial/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxtutorial.cpp", "tst_blackboxtutorial.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxproviders.cpp0000644000175100017510000005144515232633614023534 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackboxproviders.h" #include "../shared.h" #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) TestBlackboxProviders::TestBlackboxProviders() : TestBlackboxBase(SRCDIR "/testdata-providers", "blackbox-providers") { } void TestBlackboxProviders::allowedValues() { QFETCH(QStringList, arguments); QFETCH(bool, expectFailure); QDir::setCurrent(testDataDir + "/allowed-values"); rmDirR(relativeBuildDir()); QbsRunParameters params; params.arguments = arguments; params.expectFailure = expectFailure; QVERIFY2(runQbs(params) == int(expectFailure), m_qbsStderr); } void TestBlackboxProviders::allowedValues_data() { QTest::addColumn("arguments"); QTest::addColumn("expectFailure"); QTest::newRow("invalid js value") << QStringList{} << true; QTest::newRow("invalid variant value") << QStringList{"moduleProviders.provider.aProperty:three"} << true; QTest::newRow("valid variant value") << QStringList{"moduleProviders.provider.aProperty:one"} << false; } void TestBlackboxProviders::brokenProvider() { QDir::setCurrent(testDataDir + "/broken-provider"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsothermodule'")); QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsmetatestmodule'")); QCOMPARE(m_qbsStderr.count("This provider is broken"), 2); } void TestBlackboxProviders::conanProvider() { QFETCH(bool, generateConanFiles); QFETCH(bool, successExpected); const auto executable = findExecutable({"conan"}); if (executable.isEmpty()) QSKIP("conan is not installed or not available in PATH."); const auto conanVersion = this->conanVersion(executable); if (!conanVersion.isValid()) QSKIP("Can't get conan version."); if (compare(conanVersion, qbs::Version(2, 6)) < 0) QSKIP("This test apples only to conan 2.6 and newer."); const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; if (!QFileInfo(profilePath).exists()) QSKIP("conan profile is not installed, run './scripts/setup-conan-profiles.sh'."); // install testlibdep first QProcess conan; QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); QVERIFY(waitForProcessSuccess(conan)); // install testlib second QDir::setCurrent(testDataDir + "/conan-provider/testlib"); conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); QVERIFY(waitForProcessSuccess(conan)); // install header lib third QDir::setCurrent(testDataDir + "/conan-provider/testlibheader"); conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); QVERIFY(waitForProcessSuccess(conan)); // install lib-order-test QDir::setCurrent(testDataDir + "/conan-provider/lib-order-test"); conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); QVERIFY(waitForProcessSuccess(conan)); // now build an app using those libs QDir::setCurrent(testDataDir + "/conan-provider"); rmDirR(relativeBuildDir()); rmDirR("build"); if (generateConanFiles) { QStringList arguments{ "install", ".", "-g=QbsDeps", "--profile:all=qbs-test", "--output-folder=build"}; QProcess conan; conan.start(executable, arguments); QVERIFY(waitForProcessSuccess(conan)); } QbsRunParameters buildParams( "build", {"--force-probe-execution", "moduleProviders.conan.installDirectory:" + QDir::currentPath() + "/build"}); buildParams.expectFailure = !successExpected; QCOMPARE(runQbs(buildParams) == 0, successExpected); } void TestBlackboxProviders::conanProvider_data() { QTest::addColumn("generateConanFiles"); QTest::addColumn("successExpected"); QTest::addRow("no conan files generated") << false << false; QTest::addRow("conan files generated") << true << true; } void TestBlackboxProviders::conanFileProbe() { const auto executable = findExecutable({"conan"}); if (executable.isEmpty()) QSKIP("conan is not installed or not available in PATH."); const auto conanVersion = this->conanVersion(executable); if (!conanVersion.isValid()) QSKIP("Can't get conan version."); if (compare(conanVersion, qbs::Version(2, 6)) < 0) QSKIP("This test apples only to conan 2.6 and newer."); const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; if (!QFileInfo(profilePath).exists()) QSKIP("conan profile is not installed, run './scripts/setup-conan-profiles.sh'."); // install testlib QProcess conan; QDir::setCurrent(testDataDir + "/conanfile-probe/testlib"); conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); QVERIFY(waitForProcessSuccess(conan)); // now build an app QDir::setCurrent(testDataDir + "/conanfile-probe"); QCOMPARE(runQbs(QbsRunParameters{"resolve"}), 0); QCOMPARE(runQbs(QbsRunParameters{"build"}), 0); } void TestBlackboxProviders::moduleProviders() { QDir::setCurrent(testDataDir + "/module-providers"); // Resolving in dry-run mode must not leave any data behind. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); QVERIFY(!QFile::exists(relativeBuildDir())); // Initial build. QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY(QFile::exists(relativeBuildDir())); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app1"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app2"), m_qbsStdout.constData()); // Rebuild with overridden module provider config. The output for product 2 must change, // but no setup script must be re-run, because both config values have already been // handled in the first run. const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); // Forcing Probe execution triggers a re-run of the setup script. But only once, // because the module provider config is the same now. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) << "--force-probe-execution")), 0); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); // Now re-run without the module provider config override. Again, the setup script must // run once, for the config value that was not present in the last run. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); } // Checks regression - when loading 2 modules from the same provider, the second module should // come from provider cache void TestBlackboxProviders::moduleProvidersCache() { QDir::setCurrent(testDataDir + "/module-providers-cache"); QbsRunParameters params("resolve", {"-v"}); QCOMPARE(runQbs(params), 0); const auto qbsmetatestmoduleMessage = "Re-checking for module \"qbsmetatestmodule\" with " "newly added search paths from module provider"; const auto qbsothermoduleMessage = "Re-checking for module \"qbsothermodule\" with " "newly added search paths from module provider"; QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 1); // We didn't change providers, so both modules should come from cache. params.arguments << "project.dummyProp:value"; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 2); } void TestBlackboxProviders::nonEagerModuleProvider() { QDir::setCurrent(testDataDir + "/non-eager-provider"); QbsRunParameters params("resolve"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsmetatestmodule")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsothermodule")), m_qbsStdout); QVERIFY2(!m_qbsStdout.contains(("Running setup script for nonexistentmodule")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: from_provider_a")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: from_provider_a")), m_qbsStdout); } void TestBlackboxProviders::probeInModuleProvider() { QDir::setCurrent(testDataDir + "/probe-in-module-provider"); QbsRunParameters params; params.command = "build"; params.arguments << "--force-probe-execution"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("Running probe"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); WAIT_FOR_NEW_TIMESTAMP(); touch("probe-in-module-provider.qbs"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.prop: \"value\""), m_qbsStdout); QVERIFY2(!m_qbsStdout.contains("Running probe"), m_qbsStdout); } void TestBlackboxProviders::providersCondition() { QDir::setCurrent(testDataDir + "/providers-condition"); QbsRunParameters params("resolve"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("p1.qbsmetatestmodule.prop: from_provider_a"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: from_provider_b")), m_qbsStdout); } void TestBlackboxProviders::providersConditionProbes() { QDir::setCurrent(testDataDir + "/providers-condition-probes"); QbsRunParameters params("resolve"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("p1.qbsmetatestmodule.prop: from_provider_a"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: from_provider_b")), m_qbsStdout); } // Tests whether it is possible to set providers properties in a Product or from command-line void TestBlackboxProviders::providersProperties() { QDir::setCurrent(testDataDir + "/providers-properties"); QbsRunParameters params("build"); params.arguments = QStringList("moduleProviders.provider_b.someProp: \"first,second\""); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.listProp: [\"someValue\"]"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains( "p.qbsothermodule.listProp: [\"first\",\"second\"]"), m_qbsStdout); } // checks that we can set qbs module properties in providers and provider cache works corectly void TestBlackboxProviders::qbsModulePropertiesInProviders() { QDir::setCurrent(testDataDir + "/qbs-module-properties-in-providers"); QbsRunParameters params("resolve"); QCOMPARE(runQbs(params), 0); // We have 2 products in 2 configurations, but second product should use the cached value // so we should have only 2 copies of the module, not 4. QCOMPARE(m_qbsStdout.count("Running setup script for qbsmetatestmodule"), 2); // Check that products get correct values from modules QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); } void TestBlackboxProviders::qbsModuleProviders_data() { QTest::addColumn("arguments"); QTest::addColumn("firstProp"); QTest::addColumn("secondProp"); QTest::newRow("default") << QStringList() << "from_provider_a" << "undefined"; QTest::newRow("override") << QStringList("projects.project.qbsModuleProviders:provider_b") << "from_provider_b" << "from_provider_b"; QTest::newRow("override list a") << QStringList("projects.project.qbsModuleProviders:provider_a,provider_b") << "from_provider_a" << "from_provider_b"; QTest::newRow("override list b") << QStringList("projects.project.qbsModuleProviders:provider_b,provider_a") << "from_provider_b" << "from_provider_b"; } // Tests whether it is possible to set qbsModuleProviders in Product and Project items // and that the order of providers results in correct priority void TestBlackboxProviders::qbsModuleProviders() { QFETCH(QStringList, arguments); QFETCH(QString, firstProp); QFETCH(QString, secondProp); QDir::setCurrent(testDataDir + "/qbs-module-providers"); QbsRunParameters params("resolve"); params.arguments << arguments << "-f" << "qbs-module-providers.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: " + firstProp).toUtf8()), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: " + secondProp).toUtf8()), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p2.qbsmetatestmodule.prop: " + firstProp).toUtf8()), m_qbsStdout); QVERIFY2(m_qbsStdout.contains(("p2.qbsothermodule.prop: " + secondProp).toUtf8()), m_qbsStdout); } void TestBlackboxProviders::qbsModuleProvidersCliOverride_data() { QTest::addColumn("arguments"); QTest::addColumn("propertyValue"); QTest::newRow("default") << QStringList() << "undefined"; QTest::newRow("project-wide") << QStringList("project.qbsModuleProviders:provider_a") << "from_provider_a"; QTest::newRow("concrete project") << QStringList("projects.innerProject.qbsModuleProviders:provider_a") << "from_provider_a"; QTest::newRow("concrete product") << QStringList("products.product.qbsModuleProviders:provider_a") << "from_provider_a"; QTest::newRow("concrete project override project-wide") << QStringList({ "project.qbsModuleProviders:provider_a", "projects.innerProject.qbsModuleProviders:provider_b"}) << "from_provider_b"; QTest::newRow("concrete product override project-wide") << QStringList({ "project.qbsModuleProviders:provider_a", "products.product.qbsModuleProviders:provider_b"}) << "from_provider_b"; } // Tests possible use-cases how to override providers from command-line void TestBlackboxProviders::qbsModuleProvidersCliOverride() { QFETCH(QStringList, arguments); QFETCH(QString, propertyValue); QDir::setCurrent(testDataDir + "/qbs-module-providers-cli-override"); QbsRunParameters params("resolve"); params.arguments = arguments; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), m_qbsStdout); } void TestBlackboxProviders::qbsModuleProvidersCompatibility_data() { QTest::addColumn("arguments"); QTest::addColumn("propertyValue"); QTest::newRow("default") << QStringList() << "from_scoped_provider"; QTest::newRow("scoped by name") << QStringList("project.qbsModuleProviders:qbsmetatestmodule") << "from_scoped_provider"; QTest::newRow("named") << QStringList("project.qbsModuleProviders:named_provider") << "from_named_provider"; } // Tests whether scoped providers can be used as named, i.e. new provider machinery // is compatible with the old one void TestBlackboxProviders::qbsModuleProvidersCompatibility() { QFETCH(QStringList, arguments); QFETCH(QString, propertyValue); QDir::setCurrent(testDataDir + "/qbs-module-providers-compatibility"); QbsRunParameters params("resolve"); params.arguments = arguments; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), m_qbsStdout); } void TestBlackboxProviders::qbspkgconfigModuleProvider() { QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider/libs"); rmDirR(relativeBuildDir()); const auto commonParams = QbsRunParameters(QStringLiteral("install"), { QStringLiteral("--install-root"), QStringLiteral("install-root") }); auto dynamicParams = commonParams; dynamicParams.arguments << "config:library" << "projects.libs.isBundle:false"; QCOMPARE(runQbs(dynamicParams), 0); QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider"); rmDirR(relativeBuildDir()); const auto sysroot = testDataDir + "/qbspkgconfig-module-provider/libs/install-root"; QbsRunParameters params; params.arguments << "moduleProviders.qbspkgconfig.sysroot:" + sysroot; QCOMPARE(runQbs(params), 0); } void TestBlackboxProviders::qtBug51237() { const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile profile("qbs_autotests_qtBug51237", s.get()); profile.p.setValue("moduleProviders.provider.theProperty", QStringList()); s->sync(); QDir::setCurrent(testDataDir + "/QTBUG-51237"); QbsRunParameters params; params.profile = profile.p.name(); QCOMPARE(runQbs(params), 0); } void TestBlackboxProviders::removalVersion() { QDir::setCurrent(testDataDir + "/removal-version"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains( "Property 'deprecated' was scheduled for removal in version 2.2.0, but is still present")); } QTEST_MAIN(TestBlackboxProviders) qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxapple.h0000644000175100017510000000502315232633614022254 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXAPPLE_H #define TST_BLACKBOXAPPLE_H #include "tst_blackboxbase.h" #include namespace qbs { class Version; } // namespace qbs class TestBlackboxApple : public TestBlackboxBase { Q_OBJECT public: TestBlackboxApple(); public slots: void initTestCase() override; private slots: void appleMultiConfig(); void aggregateDependencyLinking(); void appiconset(); void assetCatalog(); void assetCatalog_data(); void assetCatalogsEmpty(); void assetCatalogsMultiple(); void bundleStructure(); void bundleStructure_data(); void byteArrayInfoPlist(); void codesign(); void codesign_data(); void codesignDestinationDirectory(); void deploymentTarget(); void deploymentTarget_data(); void dmg(); void embedInfoPlist(); void frameworkStructure(); void iconcomposer(); void iconset(); void iconsetApp(); void infoPlist(); void mainBundle(); void mainBundle_data(); void privacymanifest(); void infoPlistVariables(); void lipoSymlinks(); void lipoSymlinks_data(); void objcArc(); void overrideInfoPlist(); void xcode(); private: std::optional findXcode(int *status = nullptr); std::optional findXcodeVersion(); }; #endif // TST_BLACKBOXAPPLE_H qbs-src-3.3.1/tests/auto/blackbox/blackbox.qbs0000644000175100017510000000136115232633614020677 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "find" prefix: "find/" files: ["**/*"] fileTags: [] } Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackbox.cpp", "tst_blackbox.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) .concat(qbsbuildconfig.enableUnitTests ? ["QBS_ENABLE_UNIT_TESTS"] : []) .concat("QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version)) } qbs-src-3.3.1/tests/auto/blackbox/testdata-clangdb/0000755000175100017510000000000015232633614021603 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-clangdb/project1/0000755000175100017510000000000015232633614023332 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/blackbox/testdata-clangdb/project1/project.qbs0000644000175100017510000000212715232633614025511 0ustar runnerrunner// $ g++ 'i like spaces.cpp' '-DSPACES="!have \\fun\x5c!\n"' '-DSPICES=%T% # && $$ 1>&2 '\''\n'\''\n' '-DSLICES=(42>24)' && ./a.out // SPACES=!have \fun\! // SPICES=%T% # && $$ 1>&2 '\n' // SLICES=1 Project { Application { Probe { id: dummy property bool isMingw: qbs.toolchain.includes("mingw") property bool isMsvc: qbs.toolchain.includes("msvc") property var buildEnv: cpp.buildEnv configure: { if (!buildEnv) return; if (isMsvc) { console.info("is msvc"); console.info("INCLUDE=" + buildEnv["INCLUDE"]); console.info("LIB=" + buildEnv["LIB"]); } else if (isMingw) { console.info("is mingw"); console.info("PATH=" + buildEnv["PATH"]); } } } targetName: "i like spaces" Depends { name: "cpp" } cpp.defines: base.concat([ "SPACES=\"!have \\\\fun\\x5c!\\n\"", "SPICES=%T% # && $$ 1>&2 '\\n'\\n", "SLICES=(42>24)" ]); files: ["i like spaces.cpp"] } } qbs-src-3.3.1/tests/auto/blackbox/testdata-clangdb/project1/i like spaces.cpp0000644000175100017510000000274715232633614026444 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include using namespace std; #define _STR(x) #x #define STR(x) _STR(x) int main(int argc, char **argv) { int garbage; int unused = garbage; cout << "SPACES=" << SPACES << "SPICES=" STR(SPICES) << "SLICES=" << SLICES << endl; return 0; } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxbaremetal.cpp0000644000175100017510000002730315232633614023447 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackboxbaremetal.h" #include "../shared.h" #include #include static bool extractToolset(const QByteArray &output, QByteArray &toolchain, QByteArray &architecture) { const QRegularExpression re("%%([\\w\\-]+)%%, %%(\\w+)%%"); QRegularExpressionMatchIterator it = re.globalMatch(output); if (!it.hasNext()) return false; const QRegularExpressionMatch match = it.next(); toolchain = match.captured(1).toLocal8Bit(); architecture = match.captured(2).toLocal8Bit(); return true; } static bool extractCompilerIncludePaths(const QByteArray &output, QStringList &compilerIncludePaths) { const QRegularExpression re("%%([^%%]+)%%"); QRegularExpressionMatchIterator it = re.globalMatch(output); if (!it.hasNext()) return false; const QRegularExpressionMatch match = it.next(); compilerIncludePaths = match.captured(1).split(","); return true; } static bool extractQuitedValue(const QByteArray &output, QString &pattern) { const QRegularExpression re("%%(.+)%%"); const QRegularExpressionMatch match = re.match(output); if (!match.hasMatch()) return false; pattern = match.captured(1); return true; } static QByteArray unsupportedToolsetMessage(const QByteArray &output) { QByteArray toolchain; QByteArray architecture; extractToolset(output, toolchain, architecture); return "Unsupported toolchain '" + toolchain + "' for architecture '" + architecture + "'"; } static QByteArray brokenProbeMessage(const QByteArray &output) { QByteArray toolchain; QByteArray architecture; extractToolset(output, toolchain, architecture); return "Broken probe for toolchain '" + toolchain + "' for architecture '" + architecture + "'"; } TestBlackboxBareMetal::TestBlackboxBareMetal() : TestBlackboxBase (SRCDIR "/testdata-baremetal", "blackbox-baremetal") { } void TestBlackboxBareMetal::targetPlatform() { QDir::setCurrent(testDataDir + "/target-platform"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); const bool hasNoPlatform = m_qbsStdout.contains("has no platform: true"); QCOMPARE(hasNoPlatform, true); const bool hasNoOS = m_qbsStdout.contains("has no os: true"); QCOMPARE(hasNoOS, true); } void TestBlackboxBareMetal::application_data() { QTest::addColumn("testPath"); QTest::newRow("one-object-application") << "/one-object-application"; QTest::newRow("two-object-application") << "/two-object-application"; QTest::newRow("one-object-asm-application") << "/one-object-asm-application"; } void TestBlackboxBareMetal::application() { QFETCH(QString, testPath); QDir::setCurrent(testDataDir + testPath); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); QCOMPARE(runQbs(QbsRunParameters("build")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); } void TestBlackboxBareMetal::staticLibraryDependencies() { QDir::setCurrent(testDataDir + "/static-library-dependencies"); QCOMPARE(runQbs(QStringList{"-p", "lib-a,lib-b,lib-c,lib-d,lib-e"}), 0); QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); const QByteArray output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY(output.contains("lib-a")); QVERIFY(output.contains("lib-b")); QVERIFY(output.contains("lib-c")); QVERIFY(output.contains("lib-d")); QVERIFY(output.contains("lib-e")); } void TestBlackboxBareMetal::externalStaticLibraries() { QDir::setCurrent(testDataDir + "/external-static-libraries"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::sharedLibraries() { QDir::setCurrent(testDataDir + "/shared-libraries"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); QCOMPARE(runQbs(QbsRunParameters("build")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("Hello from app"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Hello from lib"), m_qbsStdout.constData()); } void TestBlackboxBareMetal::userIncludePaths() { QDir::setCurrent(testDataDir + "/user-include-paths"); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::systemIncludePaths() { QDir::setCurrent(testDataDir + "/system-include-paths"); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::distributionIncludePaths() { QDir::setCurrent(testDataDir + "/distribution-include-paths"); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::compilerIncludePaths() { QDir::setCurrent(testDataDir + "/compiler-include-paths"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (!m_qbsStdout.contains("compilerIncludePaths:")) QFAIL("No compiler include paths exists"); QStringList includePaths; QVERIFY(extractCompilerIncludePaths(m_qbsStdout, includePaths)); QVERIFY(includePaths.count() > 0); for (const auto &includePath : includePaths) { const QDir dir(includePath); QVERIFY(dir.exists()); } } void TestBlackboxBareMetal::preincludeHeaders() { QDir::setCurrent(testDataDir + "/preinclude-headers"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::defines() { QDir::setCurrent(testDataDir + "/defines"); QCOMPARE(runQbs(), 0); } void TestBlackboxBareMetal::compilerListingFiles_data() { QTest::addColumn("generateListing"); QTest::addColumn("customListingSuffix"); QTest::newRow("do-not-generate-compiler-listing") << false << ""; QTest::newRow("generate-default-compiler-listing") << true << ""; QTest::newRow("generate-custom-compiler-listing") << true << ".lll"; } void TestBlackboxBareMetal::compilerListingFiles() { QFETCH(bool, generateListing); QFETCH(QString, customListingSuffix); QDir::setCurrent(testDataDir + "/compiler-listing"); rmDirR(relativeBuildDir()); QStringList args = {QStringLiteral("modules.cpp.generateCompilerListingFiles:%1") .arg(generateListing ? "true" : "false")}; if (!customListingSuffix.isEmpty()) args << QStringLiteral("modules.cpp.compilerListingSuffix:%1").arg(customListingSuffix); QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); if (m_qbsStdout.contains("unsupported toolset:")) QSKIP(unsupportedToolsetMessage(m_qbsStdout)); if (!m_qbsStdout.contains("compiler listing suffix:")) QFAIL("No current compiler listing suffix pattern exists"); QString compilerListingSuffix; if (!extractQuitedValue(m_qbsStdout, compilerListingSuffix)) QFAIL("Unable to extract current compiler listing suffix"); if (!customListingSuffix.isEmpty()) QCOMPARE(compilerListingSuffix, customListingSuffix); QCOMPARE(runQbs(QbsRunParameters(args)), 0); const QString productBuildDir = relativeProductBuildDir("compiler-listing"); const QString hash = inputDirHash("."); const QString mainListing = productBuildDir + "/" + hash + "/main.c" + compilerListingSuffix; QCOMPARE(regularFileExists(mainListing), generateListing); const QString funListing = productBuildDir + "/" + hash + "/fun.c" + compilerListingSuffix; QCOMPARE(regularFileExists(funListing), generateListing); } void TestBlackboxBareMetal::linkerMapFile_data() { QTest::addColumn("generateMap"); QTest::addColumn("customMapSuffix"); QTest::newRow("do-not-generate-linker-map") << false << ""; QTest::newRow("generate-default-linker-map") << true << ""; QTest::newRow("generate-custom-linker-map") << true << ".mmm"; } void TestBlackboxBareMetal::linkerMapFile() { QFETCH(bool, generateMap); QFETCH(QString, customMapSuffix); QDir::setCurrent(testDataDir + "/linker-map"); rmDirR(relativeBuildDir()); QStringList args = {QStringLiteral("modules.cpp.generateLinkerMapFile:%1") .arg(generateMap ? "true" : "false")}; if (!customMapSuffix.isEmpty()) args << QStringLiteral("modules.cpp.linkerMapSuffix:%1").arg(customMapSuffix); QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); if (!m_qbsStdout.contains("linker map suffix:")) QFAIL("No current linker map suffix pattern exists"); QString linkerMapSuffix; if (!extractQuitedValue(m_qbsStdout, linkerMapSuffix)) QFAIL("Unable to extract current linker map suffix"); if (!customMapSuffix.isEmpty()) QCOMPARE(linkerMapSuffix, customMapSuffix); QCOMPARE(runQbs(QbsRunParameters(args)), 0); const QString productBuildDir = relativeProductBuildDir("linker-map"); const QString linkerMap = productBuildDir + "/linker-map" + linkerMapSuffix; QCOMPARE(regularFileExists(linkerMap), generateMap); } void TestBlackboxBareMetal::compilerDefinesByLanguage() { QDir::setCurrent(testDataDir + "/compiler-defines-by-language"); QbsRunParameters params(QStringList{ "-f", "compiler-defines-by-language.qbs" }); QCOMPARE(runQbs(params), 0); } void TestBlackboxBareMetal::toolchainProbe() { QDir::setCurrent(testDataDir + "/toolchain-probe"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (m_qbsStdout.contains("broken probe:")) QFAIL(brokenProbeMessage(m_qbsStdout)); } QTEST_MAIN(TestBlackboxBareMetal) qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxbaremetal.h0000644000175100017510000000450015232633614023106 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOXBAREMETAL_H #define TST_BLACKBOXBAREMETAL_H #include "tst_blackboxbase.h" class TestBlackboxBareMetal : public TestBlackboxBase { Q_OBJECT public: TestBlackboxBareMetal(); private slots: void targetPlatform(); void application_data(); void application(); void staticLibraryDependencies(); void externalStaticLibraries(); void sharedLibraries(); void userIncludePaths(); void systemIncludePaths(); void distributionIncludePaths(); void compilerIncludePaths(); void preincludeHeaders(); void defines(); void compilerListingFiles_data(); void compilerListingFiles(); void linkerMapFile_data(); void linkerMapFile(); void compilerDefinesByLanguage(); void toolchainProbe(); private: }; #endif // TST_BLACKBOXBAREMETAL_H qbs-src-3.3.1/tests/auto/blackbox/blackbox-windows.qbs0000644000175100017510000000100515232633614022362 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-windows" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-windows/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxwindows.cpp", "tst_blackboxwindows.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxandroid.cpp0000644000175100017510000020553515232633614023140 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxandroid.h" #include "../shared.h" #include #include #include #include #include #include using qbs::Internal::none_of; using qbs::Profile; QMap TestBlackboxAndroid::findAndroid(int *status, const QString &profile) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList({"-f", "find-android.qbs", "qbs.architecture:x86"}); params.profile = profile; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-android") + "/android.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return { {"sdk", QDir::fromNativeSeparators(tools["sdk"].toString())}, {"sdk-build-tools-dx", QDir::fromNativeSeparators(tools["sdk-build-tools-dx"].toString())}, {"sdk-build-tools-d8", QDir::fromNativeSeparators(tools["sdk-build-tools-d8"].toString())}, {"ndk", QDir::fromNativeSeparators(tools["ndk"].toString())}, {"ndk-samples", QDir::fromNativeSeparators(tools["ndk-samples"].toString())}, {"jar", QDir::fromNativeSeparators(tools["jar"].toString())}, }; } TestBlackboxAndroid::TestBlackboxAndroid() : TestBlackboxBase(SRCDIR "/testdata-android", "blackbox-android") { } static QString theProfileName(bool forQt) { return forQt ? "qbs_autotests-android-qt" : profileName(); } void TestBlackboxAndroid::android() { QFETCH(QString, projectDir); QFETCH(QStringList, productNames); QFETCH(QList, expectedFilesLists); QFETCH(QStringList, customProperties); QFETCH(bool, enableAapt2); QFETCH(bool, generateAab); QFETCH(bool, isIncrementalBuild); QFETCH(bool, enableD8); // skip tests on github except when run in docker - this var is not propagated into the image if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) QSKIP("Skip Android tests when running on GitHub"); const SettingsPtr s = settings(); Profile p(theProfileName(projectDir == "qml-app" || projectDir == "qt-app"), s.get()); if (!p.exists()) QSKIP("Qt is not installed"); int status; const auto androidPaths = findAndroid(&status, p.name()); QCOMPARE(status, 0); const auto sdkPath = androidPaths["sdk"]; if (sdkPath.isEmpty()) QSKIP("Android SDK is not installed"); const auto ndkPath = androidPaths["ndk"]; if (ndkPath.isEmpty() && projectDir != "no-native") QSKIP("Android NDK is not installed"); const auto ndkSamplesPath = androidPaths["ndk-samples"]; static const QStringList ndkSamplesDirs = QStringList() << "teapot" << "no-native"; if (!ndkPath.isEmpty() && !QFileInfo(ndkSamplesPath).isDir() && ndkSamplesDirs.contains(projectDir)) QSKIP("NDK samples directory not present"); const QString buildSubDir = enableAapt2 ? (generateAab ? "aab" : "aapt2") : "aapt"; QDir::setCurrent(testDataDir + "/" + projectDir); if (!isIncrementalBuild) rmDirR(relativeBuildDir(buildSubDir)); static const QStringList configNames { "debug", "release" }; for (const QString &configName : configNames) { auto currentExpectedFilesLists = expectedFilesLists; const QString configArgument = "config:" + configName; QbsRunParameters resolveParams("resolve"); resolveParams.buildDirectory = buildSubDir; resolveParams.arguments << configArgument << customProperties; resolveParams.profile = p.name(); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line", configArgument}); buildParams.buildDirectory = buildSubDir; buildParams.profile = p.name(); QCOMPARE(runQbs(buildParams), 0); for (const QString &productName : std::as_const(productNames)) { const QByteArray tag(QTest::currentDataTag()); QCOMPARE(m_qbsStdout.count("generating BuildConfig.java"), isIncrementalBuild ? 0 : productNames.size()); const QString packageName = productName + (generateAab ? ".aab" : ".apk"); QVERIFY(m_qbsStdout.contains(packageName.toLocal8Bit())); const QString packageFilePath = buildSubDir + "/" + relativeProductBuildDir(productName, configName) + '/' + packageName; QVERIFY2(regularFileExists(packageFilePath), qPrintable(packageFilePath)); const QString jarFilePath = androidPaths["jar"]; QVERIFY(!jarFilePath.isEmpty()); QProcess jar; jar.start(jarFilePath, QStringList() << "-tf" << packageFilePath); QVERIFY2(jar.waitForStarted(), qPrintable(jar.errorString())); QVERIFY2(jar.waitForFinished(), qPrintable(jar.errorString())); QVERIFY2(jar.exitCode() == 0, qPrintable(jar.readAllStandardError().constData())); QByteArrayList actualFiles = jar.readAllStandardOutput().trimmed().split('\n'); for (QByteArray &f : actualFiles) f = f.trimmed(); QByteArrayList missingExpectedFiles; QByteArrayList expectedFiles = currentExpectedFilesLists.takeFirst(); for (const QByteArray &expectedFile : expectedFiles) { if (expectedFile.endsWith("/libgdbserver.so") && configName == "release") continue; auto it = std::find(actualFiles.begin(), actualFiles.end(), expectedFile); if (it != actualFiles.end()) { actualFiles.erase(it); continue; } missingExpectedFiles << expectedFile; } if (!missingExpectedFiles.empty()) QFAIL(QByteArray("missing expected files:\n") + missingExpectedFiles.join('\n')); if (!actualFiles.empty()) { QByteArray msg = "unexpected files encountered:\n" + actualFiles.join('\n'); auto isFileSharedObject = [](const QByteArray &f) { return f.endsWith(".so"); }; const auto isQmlToolingLib = [](const QByteArray &f) { return f.contains("qmltooling"); }; if (none_of(actualFiles, isFileSharedObject) || qbs::Internal::all_of(actualFiles, isQmlToolingLib)) { qWarning() << msg; } else { QFAIL(msg); } } } if (projectDir == "multiple-libs-per-apk") { const auto dexCompilerPath = enableD8 ? androidPaths["sdk-build-tools-d8"] : androidPaths["sdk-build-tools-dx"]; QVERIFY(!dexCompilerPath.isEmpty()); const auto lines = m_qbsStdout.split('\n'); const auto it = std::find_if(lines.cbegin(), lines.cend(), [&](const QByteArray &line) { return !line.isEmpty() && line.startsWith(dexCompilerPath.toUtf8()); }); QVERIFY2(it != lines.cend(), qPrintable(m_qbsStdout.constData())); const auto line = *it; QVERIFY2(line.contains("lib3.jar"), qPrintable(line.constData())); QVERIFY2(!line.contains("lib4.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib5.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib6.jar"), qPrintable(line.constData())); QVERIFY2(!line.contains("lib7.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib8.jar"), qPrintable(line.constData())); } } } void TestBlackboxAndroid::android_data() { const SettingsPtr s = settings(); const Profile p(profileName(), s.get()); const Profile pQt(theProfileName(true), s.get()); QStringList archsStringList = p.value(QStringLiteral("qbs.architectures")).toStringList(); if (archsStringList.empty()) archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs QByteArrayList archs; std::transform(archsStringList.begin(), archsStringList.end(), std::back_inserter(archs), [] (const QString &s) { return s.toUtf8().replace("armv7a", "armeabi-v7a") .replace("armv5te", "armeabi") .replace("arm64", "arm64-v8a"); }); const auto cxxLibPath = [&p, &pQt](const QByteArray &oldcxxLib, bool forQt) { const bool usesClang = (forQt ? pQt : p).value(QStringLiteral("qbs.toolchainType")) .toString() == "clang"; const QByteArray path = "lib/${ARCH}/"; return path + (usesClang ? QByteArrayLiteral("libc++_shared.so") : oldcxxLib); }; qbs::Version version(5, 13); QStringList qmakeFilePaths = pQt.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")). toStringList(); if (qmakeFilePaths.size() >= 1) version = TestBlackboxBase::qmakeVersion(qmakeFilePaths[0]); bool singleArchQt = (version < qbs::Version(5, 14)); QByteArray qtVersionMajor((version >= qbs::Version(6, 0)) ? "6" : "5"); QByteArrayList archsForQt; if (singleArchQt) { archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; if (archsStringList.empty()) archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs } else { QStringList archsForQtStringList = pQt.value(QStringLiteral("qbs.architectures")) .toStringList(); if (archsForQtStringList.empty()) archsForQtStringList << pQt.value("qbs.architecture").toString(); std::transform(archsForQtStringList.begin(), archsForQtStringList.end(), std::back_inserter(archsForQt), [] (const QString &s) { return s.toUtf8(); }); } QByteArrayList ndkArchsForQt; std::transform(archsForQt.begin(), archsForQt.end(), std::back_inserter(ndkArchsForQt), [] (const QString &s) { return s.toUtf8().replace("armv7a", "armeabi-v7a") .replace("armv5te", "armeabi") .replace("arm64", "arm64-v8a"); }); auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst, bool aabPackage) { const QByteArray &archPlaceHolder = "${ARCH}"; QByteArrayList result; QByteArray base( aabPackage ? "base/" : ""); for (const QByteArray &entry : lst) { if (entry.contains(archPlaceHolder)) { for (const QByteArray &arch : std::as_const(archs)) result << (base + QByteArray(entry).replace(archPlaceHolder, arch)); } else { result << (base + entry); } } return result; }; auto commonFiles = [](bool generateAab, bool codeSign = true, QString keyAlias="androiddebugkey") { QByteArrayList files; if (generateAab) files << "base/manifest/AndroidManifest.xml" << "base/dex/classes.dex" << "BundleConfig.pb"; else files << "AndroidManifest.xml" << "classes.dex"; if (codeSign) files << QByteArray("META-INF/" + keyAlias.toUpper().left(8).toUtf8() + ".RSA") << QByteArray("META-INF/" + keyAlias.toUpper().left(8).toUtf8() + ".SF") << "META-INF/MANIFEST.MF"; return files; }; QTest::addColumn("projectDir"); QTest::addColumn("productNames"); QTest::addColumn>("expectedFilesLists"); QTest::addColumn("customProperties"); QTest::addColumn("enableAapt2"); QTest::addColumn("generateAab"); QTest::addColumn("isIncrementalBuild"); QTest::addColumn("enableD8"); const auto aaptVersion = [](bool enableAapt2) { return QString("modules.Android.sdk.aaptName:") + (enableAapt2 ? "aapt2" : "aapt"); }; bool enableAapt2 = false; const auto packageType = [](bool generateAab) { return QString("modules.Android.sdk.packageType:") + (generateAab ? "aab" : "apk"); }; bool generateAab = false; bool isIncrementalBuild = false; const auto dexCompilerVersion = [](bool enableD8) { return QString("modules.Android.sdk.dexCompilerName:") + (enableD8 ? "d8" : "dx"); }; bool enableD8 = true; auto qtAppExpectedFiles = [&](bool generateAab, bool enableAapt2, bool codeSign = true, QString keyAlias="androiddebugkey") { QByteArrayList expectedFile; if (singleArchQt) { expectedFile << commonFiles(generateAab, codeSign, keyAlias) + expandArchs(ndkArchsForQt, { cxxLibPath("libgnustl_shared.so", true), "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", "lib/${ARCH}/libplugins_imageformats_libqtga.so", "lib/${ARCH}/libplugins_imageformats_libqtiff.so", "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", "lib/${ARCH}/libplugins_styles_libqandroidstyle.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", "lib/${ARCH}/libQt5Widgets.so", "lib/${ARCH}/libqt-app.so"}, generateAab); } else { expectedFile << commonFiles(generateAab, codeSign, keyAlias) + expandArchs(ndkArchsForQt, { cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Widgets_${ARCH}.so", "lib/${ARCH}/libqt-app_${ARCH}.so"}, generateAab); } if (generateAab) expectedFile << "base/resources.pb" << "base/native.pb"; else expectedFile << "resources.arsc"; if (version >= qbs::Version(5, 14)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_styles_qandroidstyle_${ARCH}.so"}, generateAab); if (version < qbs::Version(6, 0) && version >= qbs::Version(5, 14)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 5)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6Svg_${ARCH}.so", "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); if (!enableAapt2 && version < qbs::Version(6, 0)) expectedFile << "res/layout/splash.xml"; return expectedFile; }; auto codeSignProperties = [&](bool codeSign, QString keyStorePath, QString keystorePassword, QString keyPassword, QString keyAlias) { if (!codeSign) return QStringList{"modules.codesign.enableCodeSigning:false"}; return QStringList{ "modules.codesign.enableCodeSigning:true", "modules.codesign.keystorePath:" + keyStorePath, "modules.codesign.keystorePassword:" + keystorePassword, "modules.codesign.keyPassword:" + keyPassword, "modules.codesign.keyAlias:" + keyAlias, }; }; bool codeSign = true; QString keyStorePath(testDataDir + "/qt-app/test.keystore"); QString keystorePassword("qbsKeystoreTest"); QString keyPassword("qbsKeyTest"); QString keyAlias("qbsTest"); QTest::newRow("qt app") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2, codeSign, keyAlias))) << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, keyPassword, keyAlias) << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8;; codeSign = false; QTest::newRow("qt app no signing") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2, codeSign, keyAlias))) << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, keyPassword, keyAlias) << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; codeSign = true; QTest::newRow("qt app aapt2") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2, codeSign, keyAlias))) << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, keyPassword, keyAlias) << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("qt app aab") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2, codeSign, keyAlias))) << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, keyPassword, keyAlias) << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; codeSign = false; QTest::newRow("qt app aab no signing") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2, codeSign, keyAlias))) << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, keyPassword, keyAlias) << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; const QByteArrayList ndkArchsForQtSave = ndkArchsForQt; ndkArchsForQt = {ndkArchsForQt.first()}; QTest::newRow("qt app (single arch)") << "qt-app" << QStringList("qt-app") << (QList() << (QByteArrayList() << qtAppExpectedFiles(generateAab, enableAapt2))) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), "modules.qbs.architectures:" + archsForQt.first()} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; ndkArchsForQt = ndkArchsForQtSave; auto teaPotAppExpectedFiles = [&](const QByteArrayList &archs, bool generateAab) { QByteArrayList expectedFile; expectedFile << commonFiles(generateAab) + expandArchs(archs, { "assets/Shaders/ShaderPlain.fsh", "assets/Shaders/VS_ShaderPlain.vsh", cxxLibPath("libgnustl_shared.so", false), "lib/${ARCH}/libTeapotNativeActivity.so", "res/layout/widgets.xml", "res/mipmap-hdpi-v4/ic_launcher.png", "res/mipmap-mdpi-v4/ic_launcher.png", "res/mipmap-xhdpi-v4/ic_launcher.png", "res/mipmap-xxhdpi-v4/ic_launcher.png"}, generateAab); if (generateAab) expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; else expectedFile << "resources.arsc"; return expectedFile; }; generateAab = false; enableAapt2 = false; QTest::newRow("teapot") << "teapot" << QStringList("TeapotNativeActivity") << (QList() << teaPotAppExpectedFiles(archs, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("teapot aapt2") << "teapot" << QStringList("TeapotNativeActivity") << (QList() << teaPotAppExpectedFiles(archs, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("teapot aapt2 aab") << "teapot" << QStringList("TeapotNativeActivity") << (QList() << teaPotAppExpectedFiles(archs, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = false; generateAab = false; QTest::newRow("minimal-native") << "minimal-native" << QStringList("minimalnative") << (QList() << commonFiles(generateAab) + expandArchs({archs.first()}, { "lib/${ARCH}/libminimalnative.so", cxxLibPath("libstlport_shared.so", false), "lib/${ARCH}/libdependency.so"}, generateAab)) << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", "modules.qbs.architecture:" + archsStringList.first(), aaptVersion(enableAapt2)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("minimal-native aapt2") << "minimal-native" << QStringList("minimalnative") << (QList() << commonFiles(generateAab) + (QByteArrayList() << "resources.arsc") + expandArchs({archs.first()}, { "lib/${ARCH}/libminimalnative.so", cxxLibPath("libstlport_shared.so", false), "lib/${ARCH}/libdependency.so"}, generateAab)) << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", "modules.qbs.architecture:" + archsStringList.first(), aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("minimal-native aapt2 aab") << "minimal-native" << QStringList("minimalnative") << (QList() << commonFiles(generateAab) + (QByteArrayList() << "base/resources.pb" << "base/native.pb") + expandArchs({archs.first()}, { "lib/${ARCH}/libminimalnative.so", cxxLibPath("libstlport_shared.so", false), "lib/${ARCH}/libdependency.so"}, generateAab)) << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", "modules.qbs.architecture:" + archsStringList.first(), aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; auto qmlAppExpectedFiles = [&](bool generateAab, bool enableAapt2) { QByteArrayList expectedFile; if (singleArchQt) { expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", "lib/${ARCH}/libplugins_imageformats_libqtga.so", "lib/${ARCH}/libplugins_imageformats_libqtiff.so", "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", "lib/${ARCH}/libQt5Network.so", "lib/${ARCH}/libQt5Qml.so", "lib/${ARCH}/libQt5QuickParticles.so", "lib/${ARCH}/libQt5Quick.so", "lib/${ARCH}/libqmlapp.so"}, generateAab); } else { expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { "assets/android_rcc_bundle.rcc", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Network_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Qml_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Quick_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "QmlModels_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "QmlWorkerScript_${ARCH}.so", "lib/${ARCH}/libqmlapp_${ARCH}.so"}, generateAab); if (version < qbs::Version(5, 15)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so"}, generateAab); if (version >= qbs::Version(5, 15) && version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_StateMachine_qtqmlstatemachine_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript.2_workerscriptplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models.2_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(5, 14) && version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so"}, generateAab); if (version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 5)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6Svg_${ARCH}.so", "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 0)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 5)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); else expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); } if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", "lib/${ARCH}/libplugins_tls_qcertonlybackend_${ARCH}.so", "lib/${ARCH}/libplugins_tls_qopensslbackend_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Window_quickwindowplugin_${ARCH}.so", }, generateAab); if (version >= qbs::Version(6, 0) && version < qbs::Version(6, 3)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6QuickControls2Impl_${ARCH}.so", "lib/${ARCH}/libQt6QuickControls2_${ARCH}.so", "lib/${ARCH}/libQt6QuickParticles_${ARCH}.so", "lib/${ARCH}/libQt6QuickShapes_${ARCH}.so", "lib/${ARCH}/libQt6QuickTemplates2_${ARCH}.so", "lib/${ARCH}/libQt6Sql_${ARCH}.so", "lib/${ARCH}/libplugins_sqldrivers_qsqlite_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Basic_impl_qtquickcontrols2basicstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Basic_qtquickcontrols2basicstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_impl_qtquickcontrols2fusionstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_qtquickcontrols2fusionstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_impl_qtquickcontrols2imaginestyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_qtquickcontrols2imaginestyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Material_impl_qtquickcontrols2materialstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Material_qtquickcontrols2materialstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Universal_impl_qtquickcontrols2universalstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Universal_qtquickcontrols2universalstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_impl_qtquickcontrols2implplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_qtquickcontrols2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_LocalStorage_qmllocalstorageplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_NativeStyle_qtquickcontrols2nativestyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Particles_particlesplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Shapes_qmlshapesplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Templates_qtquicktemplates2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Timeline_qtquicktimelineplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Layouts_qquicklayoutsplugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick_tooling_quicktoolingplugin_${ARCH}.so", "lib/${ARCH}/libQt6QmlLocalStorage_${ARCH}.so", "lib/${ARCH}/libQt6QmlXmlListModel_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2QuickImpl_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2Utils_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2_${ARCH}.so", "lib/${ARCH}/libQt6QuickLayouts_${ARCH}.so", "lib/${ARCH}/libQt6QuickTimeline_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_XmlListModel_qmlxmllistmodelplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Dialogs_qtquickdialogsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Dialogs_quickimpl_qtquickdialogs2quickimplplugin_${ARCH}.so"}, generateAab); else expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick_Window_quickwindow_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_tooling_quicktooling_${ARCH}.so"}, generateAab); } } if (generateAab) expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; else expectedFile << "resources.arsc"; if (!enableAapt2 && version < qbs::Version(6, 0)) expectedFile << "res/layout/splash.xml"; return expectedFile; }; auto qmlAppCustomMetaDataExpectedFiles = [&](bool generateAab, bool enableAapt2) { QByteArrayList expectedFile; if (singleArchQt) { expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "assets/dummyasset.txt", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", "lib/${ARCH}/libplugins_imageformats_libqtga.so", "lib/${ARCH}/libplugins_imageformats_libqtiff.so", "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", "lib/${ARCH}/libQt5Network.so", "lib/${ARCH}/libQt5Qml.so", "lib/${ARCH}/libQt5QuickParticles.so", "lib/${ARCH}/libQt5Quick.so", "lib/${ARCH}/libqmlapp.so"}, generateAab); } else { expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { "assets/android_rcc_bundle.rcc", "assets/dummyasset.txt", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Network_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Qml_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "Quick_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "QmlModels_${ARCH}.so", "lib/${ARCH}/libQt" + qtVersionMajor + "QmlWorkerScript_${ARCH}.so", "lib/${ARCH}/libqmlapp_${ARCH}.so"}, generateAab); if (version < qbs::Version(5, 15)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so"}, generateAab); if (version >= qbs::Version(5, 15) && version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_StateMachine_qtqmlstatemachine_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript.2_workerscriptplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models.2_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(5, 14) && version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so"}, generateAab); if (version < qbs::Version(6, 0)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 5)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6Svg_${ARCH}.so", "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 0)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 5)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); else expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); } if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", "lib/${ARCH}/libplugins_tls_qcertonlybackend_${ARCH}.so", "lib/${ARCH}/libplugins_tls_qopensslbackend_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Window_quickwindowplugin_${ARCH}.so", }, generateAab); if (version >= qbs::Version(6, 0) && version < qbs::Version(6, 3)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6QuickControls2Impl_${ARCH}.so", "lib/${ARCH}/libQt6QuickControls2_${ARCH}.so", "lib/${ARCH}/libQt6QuickParticles_${ARCH}.so", "lib/${ARCH}/libQt6QuickShapes_${ARCH}.so", "lib/${ARCH}/libQt6QuickTemplates2_${ARCH}.so", "lib/${ARCH}/libQt6Sql_${ARCH}.so", "lib/${ARCH}/libplugins_sqldrivers_qsqlite_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Basic_impl_qtquickcontrols2basicstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Basic_qtquickcontrols2basicstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_impl_qtquickcontrols2fusionstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_qtquickcontrols2fusionstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_impl_qtquickcontrols2imaginestyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_qtquickcontrols2imaginestyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Material_impl_qtquickcontrols2materialstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Material_qtquickcontrols2materialstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Universal_impl_qtquickcontrols2universalstyleimplplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_Universal_qtquickcontrols2universalstyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_impl_qtquickcontrols2implplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Controls_qtquickcontrols2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_LocalStorage_qmllocalstorageplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_NativeStyle_qtquickcontrols2nativestyleplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Particles_particlesplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Shapes_qmlshapesplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Templates_qtquicktemplates2plugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Timeline_qtquicktimelineplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Layouts_qquicklayoutsplugin_${ARCH}.so"}, generateAab); if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick_tooling_quicktoolingplugin_${ARCH}.so", "lib/${ARCH}/libQt6QmlLocalStorage_${ARCH}.so", "lib/${ARCH}/libQt6QmlXmlListModel_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2QuickImpl_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2Utils_${ARCH}.so", "lib/${ARCH}/libQt6QuickDialogs2_${ARCH}.so", "lib/${ARCH}/libQt6QuickLayouts_${ARCH}.so", "lib/${ARCH}/libQt6QuickTimeline_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_XmlListModel_qmlxmllistmodelplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Dialogs_qtquickdialogsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Dialogs_quickimpl_qtquickdialogs2quickimplplugin_${ARCH}.so"}, generateAab); else expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick_Window_quickwindow_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_tooling_quicktooling_${ARCH}.so"}, generateAab); } } if (generateAab) expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; else expectedFile << "resources.arsc"; if (!enableAapt2 && version < qbs::Version(6, 0)) expectedFile << "res/layout/splash.xml"; return expectedFile; }; QStringList qmlAppCustomProperties; if (singleArchQt) { qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false", "modules.qbs.architecture:" + archsForQt.first()}; } else { qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false"}; } // aapt tool for the resources works with a directory option pointing to the parent directory // of the resources (res). // The Qt.android_support module adds res/values/libs.xml (from Qt install dir). So the res from // Qt install res directory is added to aapt. This results in adding res/layout/splash.xml to // the package eventhough the file is not needed. // On the other hand aapt2 requires giving all the resources files. // Also when enabling aapt2 the resources.arsc is always created, eventhough no resources are // declared. enableAapt2 = false; generateAab = false; QTest::newRow("qml app") << "qml-app" << QStringList("qmlapp") << (QList() << qmlAppExpectedFiles(generateAab, enableAapt2)) << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("qml app aapt2") << "qml-app" << QStringList("qmlapp") << (QList() << qmlAppExpectedFiles(generateAab, enableAapt2)) << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("qml app aab") << "qml-app" << QStringList("qmlapp") << (QList() << qmlAppExpectedFiles(generateAab, enableAapt2)) << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) << packageType(generateAab)) << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = false; generateAab = false; QTest::newRow("qml app with custom metadata") << "qml-app" << QStringList("qmlapp") << (QList() << (QByteArrayList() << qmlAppCustomMetaDataExpectedFiles(generateAab, enableAapt2))) << QStringList{"modules.Android.sdk.automaticSources:true", aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("qml app with custom metadata aapt2") << "qml-app" << QStringList("qmlapp") << (QList() << (QByteArrayList() << qmlAppCustomMetaDataExpectedFiles(generateAab, enableAapt2))) << QStringList{"modules.Android.sdk.automaticSources:true", aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; if (!singleArchQt) { QTest::newRow("qml app with custom metadata aab") << "qml-app" << QStringList("qmlapp") << (QList() << (QByteArrayList() << qmlAppCustomMetaDataExpectedFiles(generateAab, enableAapt2))) << QStringList{"modules.Android.sdk.automaticSources:true", aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; } isIncrementalBuild = false; enableAapt2 = false; generateAab = false; auto noNativeExpectedFiles = [&](bool generateAab) { QByteArrayList expectedFile; expectedFile << commonFiles(generateAab) + expandArchs(archs, { "res/drawable-hdpi-v4/ic_action_play_disabled.png", "res/drawable-hdpi-v4/ic_action_play.png", "res/drawable-hdpi-v4/ic_launcher.png", "res/drawable-hdpi-v4/tile.9.png", "res/drawable-mdpi-v4/ic_action_play_disabled.png", "res/drawable-mdpi-v4/ic_action_play.png", "res/drawable-mdpi-v4/ic_launcher.png", "res/drawable/selector_play.xml", "res/drawable-xhdpi-v4/ic_action_play_disabled.png", "res/drawable-xhdpi-v4/ic_action_play.png", "res/drawable-xhdpi-v4/ic_launcher.png", "res/drawable-xxhdpi-v4/ic_launcher.png", "res/layout/sample_main.xml", "res/menu/action_menu.xml", "res/raw/vid_bigbuckbunny.mp4"}, generateAab); if (generateAab) expectedFile << "base/resources.pb"; else expectedFile << "resources.arsc"; return expectedFile; }; QTest::newRow("no native") << "no-native" << QStringList("com.example.android.basicmediadecoder") << (QList() << noNativeExpectedFiles(generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("no native aapt2") << "no-native" << QStringList("com.example.android.basicmediadecoder") << (QList() << noNativeExpectedFiles(generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("no native aab") << "no-native" << QStringList("com.example.android.basicmediadecoder") << (QList() << noNativeExpectedFiles(generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = false; generateAab = false; QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest") << (QList() << (QByteArrayList() << commonFiles(generateAab))) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("aidl aapt2") << "aidl" << QStringList("io.qbs.aidltest") << (QList() << (QByteArrayList() << commonFiles(generateAab) << "resources.arsc")) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("aidl aab") << "aidl" << QStringList("io.qbs.aidltest") << (QList() << (QByteArrayList() << commonFiles(generateAab) << "base/resources.pb")) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = false; generateAab = false; enableD8 = false; QTest::newRow("multiple libs") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << commonFiles(generateAab) + expandArchs(archs, { "resources.arsc", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableD8 = true; QTest::newRow("multiple libs with d8") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << commonFiles(generateAab) + expandArchs(archs, { "resources.arsc", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableD8 = false; enableAapt2 = true; QTest::newRow("multiple libs aapt2") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << commonFiles(generateAab) + expandArchs(archs, { "resources.arsc", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("multiple libs aab") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << commonFiles(generateAab) + expandArchs(archs, { "resources.pb", "native.pb", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab)) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = false; generateAab = false; auto expectedFiles1 = [&](bool generateAab) { QByteArrayList expectedFile = qbs::toList(qbs::toSet(commonFiles(generateAab) + expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, { "lib/${ARCH}/libp1lib1.so", cxxLibPath("libstlport_shared.so", false)}, generateAab) + expandArchs(QByteArrayList{archs}, { "lib/${ARCH}/libp1lib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab))); if (generateAab) expectedFile << "base/resources.pb" << "base/native.pb"; else expectedFile << "resources.arsc"; return expectedFile; }; auto expectedFiles2 = [&](bool generateAab) { QByteArrayList expectedFile = commonFiles(generateAab) + expandArchs(archs, { "lib/${ARCH}/libp2lib1.so", "lib/${ARCH}/libp2lib2.so", cxxLibPath("libstlport_shared.so", false)}, generateAab); return expectedFile; }; QTest::newRow("multiple apks") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") << QList{expectedFiles1(generateAab), expectedFiles2(generateAab)} << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; QTest::newRow("multiple apks aapt2") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") << (QList() << expectedFiles1(generateAab) << (QByteArrayList() << expectedFiles2(generateAab) << "resources.arsc")) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; QTest::newRow("multiple apks aab") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") << (QList() << expectedFiles1(generateAab) << (QByteArrayList() << expectedFiles2(generateAab) << "base/resources.pb" << "base/native.pb")) << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; } QTEST_MAIN(TestBlackboxAndroid) qbs-src-3.3.1/tests/auto/blackbox/blackbox-examples.qbs0000644000175100017510000000101115232633614022503 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "blackbox-examples" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "../../../examples/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxexamples.cpp", "tst_blackboxexamples.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxproviders.h0000644000175100017510000000500515232633614023170 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOXPROVIDERS_H #define TST_BLACKBOXPROVIDERS_H #include "tst_blackboxbase.h" class TestBlackboxProviders : public TestBlackboxBase { Q_OBJECT public: TestBlackboxProviders(); private slots: void allowedValues(); void allowedValues_data(); void brokenProvider(); void conanProvider(); void conanProvider_data(); void conanFileProbe(); void moduleProviders(); void moduleProvidersCache(); void nonEagerModuleProvider(); void probeInModuleProvider(); void providersCondition(); void providersConditionProbes(); void providersProperties(); void qbsModulePropertiesInProviders(); void qbsModuleProviders_data(); void qbsModuleProviders(); void qbsModuleProvidersCliOverride(); void qbsModuleProvidersCliOverride_data(); void qbsModuleProvidersCompatibility(); void qbsModuleProvidersCompatibility_data(); void qbspkgconfigModuleProvider(); void qtBug51237(); void removalVersion(); }; #endif // TST_BLACKBOXPROVIDERS_H qbs-src-3.3.1/tests/auto/blackbox/tst_blackboxjava.h0000644000175100017510000000316315232633614022077 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackboxJava : public TestBlackboxBase { Q_OBJECT public: TestBlackboxJava(); private slots: void java(); void javaDependencyTracking(); void javaDependencyTracking_data(); void javaDependencyTrackingInnerClass(); private: const QStringList m_blacklistedJdks; }; #endif // TST_BLACKBOX_H qbs-src-3.3.1/tests/auto/blackbox/tst_blackbox.cpp0000644000175100017510000157103615232633614021602 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackbox.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; class MacosTarHealer { public: MacosTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) { // work around absurd tar behavior on macOS qputenv("COPY_EXTENDED_ATTRIBUTES_DISABLE", "true"); qputenv("COPYFILE_DISABLE", "true"); } } ~MacosTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) { qunsetenv("COPY_EXTENDED_ATTRIBUTES_DISABLE"); qunsetenv("COPYFILE_DISABLE"); } } }; QMap TestBlackbox::findCli(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-cli.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-cli") + "/cli.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"path", QDir::fromNativeSeparators(tools["path"].toString())}}; } QMap TestBlackbox::findNodejs(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-nodejs.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-nodejs") + "/nodejs.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"node", QDir::fromNativeSeparators(tools["node"].toString())}}; } QMap TestBlackbox::findTypeScript(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-typescript.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-typescript") + "/typescript.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"tsc", QDir::fromNativeSeparators(tools["tsc"].toString())}}; } QString TestBlackbox::findArchiver(const QString &fileName, int *status) { if (fileName == "jar") return findJdkTools(status).value(fileName); QString binary = findExecutable(QStringList(fileName)); if (binary.isEmpty()) { const SettingsPtr s = settings(); qbs::Profile p(profileName(), s.get()); binary = findExecutable(p.value("archiver.command").toStringList()); } return binary; } bool TestBlackbox::prepareAndRunConan() { QString executable = findExecutable({"conan"}); if (executable.isEmpty()) { qInfo() << "conan is not installed or not available in PATH."; return false; } const auto conanVersion = this->conanVersion(executable); if (!conanVersion.isValid()) { qInfo() << "Can't get conan version."; return false; } if (compare(conanVersion, qbs::Version(2, 6)) < 0) { qInfo() << "This test apples only to conan 2.6 and newer."; return false; } const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test-libs"; if (!QFileInfo(profilePath).exists()) { qInfo() << "conan profile is not installed, run './scripts/setup-conan-profiles.sh'"; return false; } QProcess conan; QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); rmDirR("build"); QStringList arguments{"install", ".", "--profile:all=qbs-test-libs", "--output-folder=build"}; conan.start(executable, arguments); return waitForProcessSuccess(conan, 60000); } bool TestBlackbox::lexYaccExist() { return !findExecutable(QStringList("lex")).isEmpty() && !findExecutable(QStringList("yacc")).isEmpty(); } qbs::Version TestBlackbox::bisonVersion() { const auto yaccBinary = findExecutable(QStringList("yacc")); QProcess process; process.start(yaccBinary, QStringList() << "--version"); if (!process.waitForStarted()) return qbs::Version(); if (!process.waitForFinished()) return qbs::Version(); const auto processStdOut = process.readAllStandardOutput(); if (processStdOut.isEmpty()) return qbs::Version(); const auto line = processStdOut.split('\n')[0]; const auto words = line.split(' '); if (words.empty()) return qbs::Version(); return qbs::Version::fromString(words.last()); } QMap TestBlackbox::getRepoStateFromApp() const { QMap result; const int startIndex = m_qbsStdout.indexOf("=="); if (startIndex == -1) return result; const int endIndex = m_qbsStdout.indexOf("==", startIndex + 2); if (endIndex == -1) return result; const QByteArray data = m_qbsStdout.mid(startIndex + 2, endIndex - startIndex - 2); const QList entries = data.split(';'); for (const QByteArray &entry : entries) { const int eqPos = entry.indexOf('='); if (eqPos != -1) result.insert(QString::fromLatin1(entry.left(eqPos)), entry.mid(eqPos + 1)); } return result; } void TestBlackbox::sevenZip() { QDir::setCurrent(testDataDir + "/archiver"); QString binary = findArchiver("7z"); if (binary.isEmpty()) QSKIP("7zip not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "modules.archiver.type:7zip")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.7z"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "l" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); const QByteArray output = listContents.readAllStandardOutput(); QVERIFY2(output.contains("2 files"), output.constData()); QVERIFY2(output.contains("test.txt"), output.constData()); QVERIFY2(output.contains("archivable.qbs"), output.constData()); } void TestBlackbox::sourceArtifactInInputsFromDependencies() { QDir::setCurrent(testDataDir + "/source-artifact-in-inputs-from-dependencies"); QCOMPARE(runQbs(), 0); QFile outFile(relativeProductBuildDir("p") + "/output.txt"); QVERIFY2(outFile.exists(), qPrintable(outFile.fileName())); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); const QByteArrayList output = outFile.readAll().trimmed().split('\n'); QCOMPARE(output.size(), 2); bool header1Found = false; bool header2Found = false; for (const QByteArray &line : output) { const QByteArray &path = line.trimmed(); if (path == "include1/header.h") header1Found = true; else if (path == "include2/header.h") header2Found = true; } QVERIFY(header1Found); QVERIFY(header2Found); } void TestBlackbox::staticLibWithoutSources() { QDir::setCurrent(testDataDir + "/static-lib-without-sources"); QCOMPARE(runQbs(), 0); } void TestBlackbox::suspiciousCalls() { const QString projectDir = testDataDir + "/suspicious-calls"; QDir::setCurrent(projectDir); rmDirR(relativeBuildDir()); QFETCH(QString, projectFile); QbsRunParameters params(QStringList() << "-f" << projectFile); QCOMPARE(runQbs(params), 0); QFETCH(QByteArray, expectedWarning); QVERIFY2(m_qbsStderr.contains(expectedWarning), m_qbsStderr.constData()); } void TestBlackbox::suspiciousCalls_data() { QTest::addColumn("projectFile"); QTest::addColumn("expectedWarning"); QTest::newRow("File.copy() in Probe") << "copy-probe.qbs" << QByteArray(); QTest::newRow("File.copy() during evaluation") << "copy-eval.qbs" << QByteArray("File.copy()"); QTest::newRow("File.copy() in prepare script") << "copy-prepare.qbs" << QByteArray("File.copy()"); QTest::newRow("File.copy() in command") << "copy-command.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() in Probe") << "direntries-probe.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() during evaluation") << "direntries-eval.qbs" << QByteArray("File.directoryEntries()"); QTest::newRow("File.directoryEntries() in prepare script") << "direntries-prepare.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() in command") << "direntries-command.qbs" << QByteArray(); } void TestBlackbox::systemIncludePaths() { const QString projectDir = testDataDir + "/system-include-paths"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); } void TestBlackbox::distributionIncludePaths() { const QString projectDir = testDataDir + "/distribution-include-paths"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); } void TestBlackbox::tar() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); MacosTarHealer tarHealer; QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "modules.archiver.type:tar")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.tar.gz"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "tf" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(listContents.readAllStandardOutput(), listFile.readAll()); } void TestBlackbox::textTemplate() { QVERIFY(QDir::setCurrent(testDataDir + "/texttemplate")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QString outputFilePath = relativeProductBuildDir("one") + "/output.txt"; QString expectedOutputFilePath = QFINDTESTDATA("expected/output.txt"); TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); outputFilePath = relativeProductBuildDir("one") + "/lalala.txt"; expectedOutputFilePath = QFINDTESTDATA("expected/lalala.txt"); TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); // Test @var@ syntax outputFilePath = relativeProductBuildDir("one") + "/output_at.txt"; expectedOutputFilePath = QFINDTESTDATA("expected/output_at.txt"); TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); } static QStringList sortedFileList(const QByteArray &ba) { auto list = QString::fromUtf8(ba).split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts); std::sort(list.begin(), list.end()); return list; } void TestBlackbox::zip() { QFETCH(QString, binaryName); int status = 0; const QString binary = findArchiver(binaryName, &status); QCOMPARE(status, 0); if (binary.isEmpty()) QSKIP("zip tool not found"); QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << "modules.archiver.type:zip" << "modules.archiver.command:" + binary); QCOMPARE(runQbs(params), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.zip"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; if (binaryName == "zip") { // zipinfo is part of Info-Zip listContents.start("zipinfo", QStringList() << "-1" << outputFile); } else { listContents.start(binary, QStringList() << "tf" << outputFile); } QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(sortedFileList(listContents.readAllStandardOutput()), sortedFileList(listFile.readAll())); // Make sure the module is still loaded when the java/jar fallback is not available params.command = "resolve"; params.arguments << "modules.java.jdkPath:/blubb"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); } void TestBlackbox::zip_data() { QTest::addColumn("binaryName"); QTest::newRow("zip") << "zip"; QTest::newRow("jar") << "jar"; } void TestBlackbox::zipInvalid() { QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << "modules.archiver.type:zip" << "modules.archiver.command:/bin/something"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("unrecognized archive tool: 'something'"), m_qbsStderr.constData()); } TestBlackbox::TestBlackbox() : TestBlackboxBase (SRCDIR "/testdata", "blackbox") { } void TestBlackbox::allowedValues() { QFETCH(QString, property); QFETCH(QString, value); QFETCH(QString, invalidValue); QDir::setCurrent(testDataDir + "/allowed-values"); rmDirR(relativeBuildDir()); QbsRunParameters params; if (!property.isEmpty() && !value.isEmpty()) { params.arguments << QStringLiteral("%1:%2").arg(property, value); } params.expectFailure = !invalidValue.isEmpty(); QCOMPARE(runQbs(params) == 0, !params.expectFailure); if (params.expectFailure) { const auto errorString = QStringLiteral("Value '%1' is not allowed for property").arg(invalidValue); QVERIFY2(m_qbsStderr.contains(errorString.toUtf8()), m_qbsStderr.constData()); } } void TestBlackbox::allowedValues_data() { QTest::addColumn("property"); QTest::addColumn("value"); QTest::addColumn("invalidValue"); QTest::newRow("default") << QString() << QString() << QString(); QTest::newRow("allowed (product, CLI)") << "products.p.prop" << "foo" << QString(); QTest::newRow("not allowed (product, CLI)") << "products.p.prop" << "bar" << "bar"; QTest::newRow("allowed (product, JS)") << "products.p.prop2" << "foo" << QString(); QTest::newRow("not allowed (product, JS)") << "products.p.prop2" << "bar" << "bar"; QTest::newRow("allowed single (module, CLI)") << "modules.a.prop" << "foo" << QString(); QTest::newRow("not allowed single (module, CLI)") << "modules.a.prop" << "baz" << "baz"; QTest::newRow("allowed mult (module, CLI)") << "modules.a.prop" << "foo,bar" << QString(); QTest::newRow("not allowed mult (module, CLI)") << "modules.a.prop" << "foo,baz" << "baz"; QTest::newRow("allowed single (module, JS)") << "modules.a.prop2" << "foo" << QString(); QTest::newRow("not allowed single (module, JS)") << "modules.a.prop2" << "baz" << "baz"; QTest::newRow("allowed mult (module, JS)") << "modules.a.prop2" << "foo,bar" << QString(); QTest::newRow("not allowed mult (module, JS)") << "modules.a.prop2" << "foo,baz" << "baz"; // undefined should always be allowed QTest::newRow("undefined (product)") << "products.p.prop" << "undefined" << QString(); QTest::newRow("undefined (module)") << "modules.a.prop" << "undefined" << QString(); } void TestBlackbox::addFileTagToGeneratedArtifact() { QDir::setCurrent(testDataDir + "/add-filetag-to-generated-artifact"); QCOMPARE(runQbs(QStringList("project.enableTagging:true")), 0); QVERIFY2(m_qbsStdout.contains("compressing my_app"), m_qbsStdout.constData()); const QString compressedAppFilePath = relativeProductBuildDir("my_compressed_app") + '/' + appendExecSuffix("compressed-my_app", m_qbsStdout); QVERIFY2(regularFileExists(compressedAppFilePath), qPrintable(compressedAppFilePath)); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("project.enableTagging:false"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(!regularFileExists(compressedAppFilePath)); } void TestBlackbox::alwaysRun() { QFETCH(QString, projectFile); QDir::setCurrent(testDataDir + "/always-run"); rmDirR(relativeBuildDir()); QbsRunParameters params("build", QStringList() << "-f" << projectFile); if (projectFile.contains("transformer")) { params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("removed"), m_qbsStderr.constData()); return; } QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("yo")); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "alwaysRun: false", "alwaysRun: true"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); } void TestBlackbox::alwaysRun_data() { QTest::addColumn("projectFile"); QTest::newRow("Transformer") << "transformer.qbs"; QTest::newRow("Rule") << "rule.qbs"; } void TestBlackbox::archiverFlags() { QDir::setCurrent(testDataDir + "/archiver-flags"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (!m_qbsStdout.contains("toolchain is MSVC")) QSKIP("Test applies to MSVC toolchain only"); QCOMPARE(runQbs(QStringList({"-n", "--command-echo-mode", "command-line"})), 0); const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray archiveLine; for (const QByteArray &line : output) { if (line.contains("lib.exe") && line.contains(".lib")) { archiveLine = line; break; } } QVERIFY(!archiveLine.isEmpty()); QVERIFY2(archiveLine.contains("/WX"), archiveLine.constData()); } void TestBlackbox::artifactsMapChangeTracking() { QDir::setCurrent(testDataDir + "/artifacts-map-change-tracking"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheBinary"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Change name of target binary. Command must be re-run, because the file name of an // artifact changed. WAIT_FOR_NEW_TIMESTAMP(); const QString projectFile("artifacts-map-change-tracking.qbs"); REPLACE_IN_FILE(projectFile, "TheBinary", "TheNewBinary"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("TheBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add file tag to generated artifact. Command must be re-run, because it enumerates the keys // of the artifacts map. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "fileTags: 'cpp'", "fileTags: ['cpp', 'blubb']"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add redundant file tag to generated artifact. Command must not be re-run, because // the artifacts map has not changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "fileTags: ['cpp', 'blubb']", "fileTags: ['cpp', 'blubb', 'blubb']"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(!m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Rebuild the app. Command must not be re-run, because the artifacts map has not changed. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(!m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add source file to app. Command must be re-run, because the artifacts map has changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "/* 'test.txt' */", "'test.txt'"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QEXPECT_FAIL("", "change tracking could become even more fine-grained", Continue); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); } void TestBlackbox::artifactsMapInvalidation() { const QString projectDir = testDataDir + "/artifacts-map-invalidation"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); TEXT_FILE_COMPARE(relativeProductBuildDir("p") + "/myfile.out", "file.in"); } void TestBlackbox::artifactsMapRaceCondition() { QDir::setCurrent(testDataDir + "/artifacts-map-race-condition"); QCOMPARE(runQbs(), 0); } void TestBlackbox::artifactScanning() { const QString projectDir = testDataDir + "/artifact-scanning"; QDir::setCurrent(projectDir); QbsRunParameters params(QStringList("-vv")); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p1.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p2.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p3.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("shared.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("external1.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir/external2.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("external-indirect.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p1.cpp"); params.command = "resolve"; params.arguments << "modules.cpp.treatSystemHeadersAsDependencies:true"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external1.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); // on macOS, there are 2 iostream files, and <__cxx03/iostream> QVERIFY(m_qbsStderr.count("scanning \"iostream\"") >= 1); } void TestBlackbox::buildDirectories() { const QString projectDir = QDir::cleanPath(testDataDir + QLatin1String("/build-directories")); const QString projectBuildDir = projectDir + '/' + relativeBuildDir(); QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); const QStringList outputLines = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', Qt::SkipEmptyParts); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p1")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p2")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectBuildDir), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData()); } void TestBlackbox::buildDirPlaceholders_data() { QTest::addColumn("buildDir"); QTest::addColumn("setProjectFile"); QTest::addColumn("successExpected"); QTest::newRow("normal dir, with project file") << "somedir" << true << true; QTest::newRow("normal dir, without project file") << "somedir" << false << true; QTest::newRow("@project, with project file") << "somedir/@project" << true << true; QTest::newRow("@project, without project file") << "somedir/@project" << false << false; QTest::newRow("@path, with project file") << "somedir/@path" << true << true; QTest::newRow("@path, without project file") << "somedir/@path" << false << false; } void TestBlackbox::buildDirPlaceholders() { QFETCH(QString, buildDir); QFETCH(bool, setProjectFile); QFETCH(bool, successExpected); const QString projectDir = testDataDir + "/build-dir-placeholders"; rmDirR(projectDir); QVERIFY(QDir().mkpath(projectDir)); QDir::setCurrent(projectDir); QFile projectFile("build-dir-placeholders.qbs"); QVERIFY(projectFile.open(QIODevice::WriteOnly)); projectFile.write("Product {\n}\n"); projectFile.flush(); rmDirR(relativeBuildDir()); QbsRunParameters params; params.buildDirectory = buildDir; if (setProjectFile) { params.arguments << "-f" << "build-dir-placeholders.qbs"; } params.expectFailure = !successExpected; QCOMPARE(runQbs(params) == 0, successExpected); } void TestBlackbox::buildEnvChange() { QDir::setCurrent(testDataDir + "/buildenv-change"); QbsRunParameters params; params.expectFailure = true; params.arguments << "-k"; QVERIFY(runQbs(params) != 0); const bool isMsvc = m_qbsStdout.contains("msvc"); QVERIFY2(m_qbsStdout.contains("compiling file.c"), m_qbsStdout.constData()); QString includePath = QDir::currentPath() + "/subdir"; params.environment.insert("CPLUS_INCLUDE_PATH", includePath); params.environment.insert("CL", "/I" + includePath); QVERIFY(runQbs(params) != 0); params.command = "resolve"; params.expectFailure = false; params.arguments.clear(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling file.c"), isMsvc); includePath = QDir::currentPath() + "/subdir2"; params.environment.insert("CPLUS_INCLUDE_PATH", includePath); params.environment.insert("CL", "/I" + includePath); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling file.c"), isMsvc); params.environment = QProcessEnvironment::systemEnvironment(); QCOMPARE(runQbs(params), 0); params.command = "build"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::buildGraphVersions() { QDir::setCurrent(testDataDir + "/build-graph-versions"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QFile bgFile(relativeBuildGraphFilePath()); QVERIFY2(bgFile.open(QIODevice::ReadWrite), qPrintable(bgFile.errorString())); bgFile.write("blubb"); bgFile.close(); // The first attempt at simple rebuilding as well as subsequent ones must fail. QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); // On re-resolving, the error turns into a warning and a new build graph is created. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::buildVariantDefaults_data() { QTest::addColumn("configName"); QTest::newRow("default") << QString(); QTest::newRow("debug") << QStringLiteral("debug"); QTest::newRow("release") << QStringLiteral("release"); QTest::newRow("profiling") << QStringLiteral("profiling"); } void TestBlackbox::buildVariantDefaults() { QFETCH(QString, configName); QDir::setCurrent(testDataDir + "/build-variant-defaults"); QbsRunParameters params{QStringLiteral("resolve")}; if (!configName.isEmpty()) params.arguments << QLatin1String("config:") + configName; QCOMPARE(runQbs(params), 0); } void TestBlackbox::capnproto() { QFETCH(QString, projectFile); QFETCH(QStringList, arguments); QDir::setCurrent(testDataDir + "/capnproto"); rmDirR(relativeBuildDir()); if (QTest::currentDataTag() == QLatin1String("cpp-conan") || QTest::currentDataTag() == QLatin1String("rpc-conan")) { if (!prepareAndRunConan()) QSKIP("conan is not prepared, check messages above"); } QbsRunParameters params{QStringLiteral("resolve"), {QStringLiteral("-f"), projectFile}}; params.arguments << arguments; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); if (m_qbsStdout.contains("capnproto is not present")) QSKIP("capnproto is not present"); params.command = QStringLiteral("build"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::capnproto_data() { QTest::addColumn("projectFile"); QTest::addColumn("arguments"); QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp.qbs") << pkgConfigArgs; QTest::newRow("rpc-pkgconfig") << QStringLiteral("greeter_cpp.qbs") << pkgConfigArgs; QTest::newRow("relative import") << QStringLiteral("capnproto_relative_import.qbs") << pkgConfigArgs; QTest::newRow("absolute import") << QStringLiteral("capnproto_absolute_import.qbs") << pkgConfigArgs; QStringList conanArgs( {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); QTest::newRow("cpp-conan") << QStringLiteral("capnproto_cpp.qbs") << conanArgs; QTest::newRow("rpc-conan") << QStringLiteral("greeter_cpp.qbs") << conanArgs; } void TestBlackbox::changedFiles_data() { QTest::addColumn("useChangedFilesForInitialBuild"); QTest::newRow("initial build with changed files") << true; QTest::newRow("initial build without changed files") << false; } void TestBlackbox::changedFiles() { QFETCH(bool, useChangedFilesForInitialBuild); QDir::setCurrent(testDataDir + "/changed-files"); rmDirR(relativeBuildDir()); const QString changedFile = QDir::cleanPath(QDir::currentPath() + "/file1.cpp"); QbsRunParameters params1; if (useChangedFilesForInitialBuild) params1 = QbsRunParameters(QStringList("--changed-files") << changedFile); // Initial run: Build all files, even though only one of them was marked as changed // (if --changed-files was used). QCOMPARE(runQbs(params1), 0); QCOMPARE(m_qbsStdout.count("compiling"), 3); QCOMPARE(m_qbsStdout.count("creating"), 3); WAIT_FOR_NEW_TIMESTAMP(); touch(QDir::currentPath() + "/main.cpp"); // Now only the file marked as changed must be compiled, even though it hasn't really // changed and another one has. QbsRunParameters params2(QStringList("--changed-files") << changedFile); QCOMPARE(runQbs(params2), 0); QCOMPARE(m_qbsStdout.count("compiling"), 1); QCOMPARE(m_qbsStdout.count("creating"), 1); QVERIFY2(m_qbsStdout.contains("file1.cpp"), m_qbsStdout.constData()); } void TestBlackbox::changedInputsFromDependencies() { QDir::setCurrent(testDataDir + "/changed-inputs-from-dependencies"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("input.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); } void TestBlackbox::changedRuleInputs() { QDir::setCurrent(testDataDir + "/changed-rule-inputs"); // Initial build. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Re-build: p1 is always regenerated, and p2 has a dependency on it. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Remove the dependency. p2 gets re-generated one last time, because its set of // inputs changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("changed-rule-inputs.qbs", "inputsFromDependencies: \"p1\"", "inputsFromDependencies: \"p3\""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Now the artifacts are no longer connected, and p2 must not get rebuilt anymore. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); } void TestBlackbox::changeInDisabledProduct() { QDir::setCurrent(testDataDir + "/change-in-disabled-product"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("change-in-disabled-product.qbs", "// 'test2.txt'", "'test2.txt'"); QCOMPARE(runQbs(), 0); } void TestBlackbox::changeInImportedFile() { QDir::setCurrent(testDataDir + "/change-in-imported-file"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("old output"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("prepare.js", "old output", "new output"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("new output"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("prepare.js"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("output"), m_qbsStdout.constData()); } void TestBlackbox::changeTrackingAndMultiplexing() { QDir::setCurrent(testDataDir + "/change-tracking-and-multiplexing"); QCOMPARE(runQbs(QStringList("modules.cpp.staticLibraryPrefix:prefix1")), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 2); QCOMPARE(m_qbsStdout.count("creating prefix1l"), 2); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.cpp.staticLibraryPrefix:prefix2"))), 0); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 0); QCOMPARE(m_qbsStdout.count("creating prefix2l"), 2); } static QJsonObject findByName(const QJsonArray &objects, const QString &name) { for (const QJsonValue &v : objects) { if (!v.isObject()) continue; QJsonObject obj = v.toObject(); const QString objName = obj.value(QStringLiteral("name")).toString(); if (objName == name) return obj; } return {}; } static void readDepsOutput(const QString &depsFilePath, QJsonDocument &jsonDocument) { jsonDocument = QJsonDocument(); QFile depsFile(depsFilePath); QVERIFY2(depsFile.open(QFile::ReadOnly), qPrintable(depsFile.errorString())); QJsonParseError jsonerror; jsonDocument = QJsonDocument::fromJson(depsFile.readAll(), &jsonerror); if (jsonerror.error != QJsonParseError::NoError) { qDebug() << jsonerror.errorString(); QFAIL("JSON parsing failed."); } } void TestBlackbox::dependenciesProperty() { QDir::setCurrent(testDataDir + QLatin1String("/dependenciesProperty")); QCOMPARE(runQbs(), 0); const QString depsFile(relativeProductBuildDir("product1") + "/product1.deps"); QJsonDocument jsondoc; readDepsOutput(depsFile, jsondoc); QVERIFY(jsondoc.isArray()); QJsonArray dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 2); QJsonObject product2 = findByName(dependencies, QStringLiteral("product2")); QJsonArray product2_type = product2.value(QStringLiteral("type")).toArray(); QCOMPARE(product2_type.size(), 1); QCOMPARE(product2_type.first().toString(), QLatin1String("application")); QCOMPARE(product2.value(QLatin1String("narf")).toString(), QLatin1String("zort")); QJsonArray product2_cppArtifacts = product2.value("artifacts").toObject().value("cpp").toArray(); QCOMPARE(product2_cppArtifacts.size(), 1); QJsonArray product2_deps = product2.value(QStringLiteral("dependencies")).toArray(); QVERIFY(!product2_deps.empty()); QJsonObject product2_qbs = findByName(product2_deps, QStringLiteral("qbs")); QVERIFY(!product2_qbs.empty()); QJsonObject product2_cpp = findByName(product2_deps, QStringLiteral("cpp")); QJsonArray product2_cpp_defines = product2_cpp.value(QLatin1String("defines")).toArray(); QCOMPARE(product2_cpp_defines.size(), 1); QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("SMURF")); QJsonArray cpp_dependencies = product2_cpp.value("dependencies").toArray(); QVERIFY(!cpp_dependencies.isEmpty()); int qbsCount = 0; for (const auto dep : cpp_dependencies) { if (dep.toObject().value("name").toString() == "qbs") ++qbsCount; } QCOMPARE(qbsCount, 1); // Add new dependency, check that command is re-run. const QString projectFile("dependenciesProperty.qbs"); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// Depends { name: 'newDependency' }", "Depends { name: 'newDependency' }"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); // Add new Depends item that does not actually introduce a new dependency, check // that command is not re-run. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// Depends { name: 'product2' }", "Depends { name: 'product2' }"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); // Change property of dependency, check that command is re-run. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"products.product2.narf:zortofsky"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); product2 = findByName(dependencies, QStringLiteral("product2")); QCOMPARE(product2.value(QLatin1String("narf")).toString(), QLatin1String("zortofsky")); // Change module property of dependency, check that command is re-run. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"products.product2.narf:zortofsky", "products.product2.cpp.defines:DIGEDAG"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); product2 = findByName(dependencies, QStringLiteral("product2")); product2_deps = product2.value(QStringLiteral("dependencies")).toArray(); product2_cpp = findByName(product2_deps, QStringLiteral("cpp")); product2_cpp_defines = product2_cpp.value(QStringLiteral("defines")).toArray(); QCOMPARE(product2_cpp_defines.size(), 1); QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG")); } void TestBlackbox::dependencyScanningLoop() { QDir::setCurrent(testDataDir + "/dependency-scanning-loop"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::deprecatedProperty() { QFETCH(QString, version); QFETCH(QString, mode); QFETCH(bool, expiringWarning); QFETCH(bool, expiringError); QDir::setCurrent(testDataDir + "/deprecated-property"); QbsRunParameters params(QStringList("-q")); params.expectFailure = true; params.environment.insert("REMOVAL_VERSION", version); if (!mode.isEmpty()) params.arguments << "--deprecation-warnings" << mode; QVERIFY(runQbs(params) != 0); m_qbsStderr = QDir::fromNativeSeparators(QString::fromLocal8Bit(m_qbsStderr)).toLocal8Bit(); const bool hasExpiringWarning = m_qbsStderr.contains(QByteArray( "deprecated-property.qbs:4:29 The property 'expiringProp' is " "deprecated and will be removed in Qbs ") + version.toLocal8Bit()); QVERIFY2(expiringWarning == hasExpiringWarning, m_qbsStderr.constData()); const bool hasRemovedOutput = m_qbsStderr.contains( "deprecated-property.qbs:5:28 The property 'veryOldProp' can no " "longer be used. It was removed in Qbs 1.3.0."); QVERIFY2(hasRemovedOutput == !expiringError, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Property 'forgottenProp' was scheduled for removal in version " "1.8.0, but is still present."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("themodule/m.qbs:22:5 Removal version for 'forgottenProp' " "specified here."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 1 + int(expiringWarning && !expiringError), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("is deprecated") == int(expiringWarning), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("was removed") == int(!expiringError), m_qbsStderr.constData()); } void TestBlackbox::deprecatedProperty_data() { QTest::addColumn("version"); QTest::addColumn("mode"); QTest::addColumn("expiringWarning"); QTest::addColumn("expiringError"); const auto current = QVersionNumber::fromString(QBS_VERSION); const QString next = QVersionNumber(current.majorVersion(), current.minorVersion() + 1) .toString(); const QString nextNext = QVersionNumber(current.majorVersion(), current.minorVersion() + 2) .toString(); const QString nextMajor = QVersionNumber(current.majorVersion() + 1).toString(); QTest::newRow("default/next") << next << QString() << true << false; QTest::newRow("default/nextnext") << nextNext << QString() << false << false; QTest::newRow("default/nextmajor") << nextMajor << QString() << true << false; QTest::newRow("error/next") << next << QString("error") << true << true; QTest::newRow("error/nextnext") << nextNext << QString("error") << true << true; QTest::newRow("error/nextmajor") << nextMajor << QString("error") << true << true; QTest::newRow("on/next") << next << QString("on") << true << false; QTest::newRow("on/nextnext") << nextNext << QString("on") << true << false; QTest::newRow("on/nextmajor") << nextMajor << QString("on") << true << false; QTest::newRow("before-removal/next") << next << QString("before-removal") << true << false; QTest::newRow("before-removal/nextnext") << nextNext << QString("before-removal") << false << false; QTest::newRow("before-removal/nextmajor") << nextMajor << QString("before-removal") << true << false; QTest::newRow("off/next") << next << QString("off") << false << false; QTest::newRow("off/nextnext") << nextNext << QString("off") << false << false; QTest::newRow("off/nextmajor") << nextMajor << QString("off") << false << false; } void TestBlackbox::disappearedProfile() { QDir::setCurrent(testDataDir + "/disappeared-profile"); QbsRunParameters resolveParams; // First, we need to fail, because we don't tell qbs where the module is. resolveParams.expectFailure = true; QVERIFY(runQbs(resolveParams) != 0); // Now we set up a profile with all the necessary information, and qbs succeeds. qbs::Settings settings(QDir::currentPath() + "/settings-dir"); qbs::Profile profile("p", &settings); profile.setValue("m.p1", "p1 from profile"); profile.setValue("m.p2", "p2 from profile"); profile.setValue("preferences.qbsSearchPaths", QStringList({QDir::currentPath() + "/modules-dir"})); settings.sync(); resolveParams.command = "resolve"; resolveParams.expectFailure = false; resolveParams.settingsDir = settings.baseDirectory(); resolveParams.profile = profile.name(); QCOMPARE(runQbs(resolveParams), 0); // Now we change a property in the profile, but because we don't use the "resolve" command, // the old profile contents stored in the build graph are used. profile.setValue("m.p2", "p2 new from profile"); settings.sync(); QbsRunParameters buildParams; buildParams.profile.clear(); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("creating dummy1.txt with p1 from profile"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating dummy2.txt with p2 from profile"), m_qbsStdout.constData()); // Now we do use the "resolve" command, so the new property value is taken into account. QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(!m_qbsStdout.contains("creating dummy1.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating dummy2.txt with p2 new from profile"), m_qbsStdout.constData()); // Now we change the profile again without a "resolve" command. However, this time we // force re-resolving indirectly by changing a project file. The updated property value // must still not be taken into account. profile.setValue("m.p1", "p1 new from profile"); settings.sync(); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("modules-dir/modules/m/m.qbs", "property string p1", "property string p1: 'p1 from module'"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating dummy1.txt"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating dummy2.txt"), m_qbsStdout.constData()); // Now we run the "resolve" command without giving the necessary settings path to find // the profile. resolveParams.expectFailure = true; resolveParams.settingsDir.clear(); resolveParams.profile.clear(); QVERIFY(runQbs(resolveParams) != 0); QVERIFY2(m_qbsStderr.contains("profile"), m_qbsStderr.constData()); } void TestBlackbox::discardUnusedData() { QDir::setCurrent(testDataDir + "/discard-unused-data"); rmDirR(relativeBuildDir()); QFETCH(QString, discardString); QFETCH(bool, symbolPresent); QbsRunParameters params; if (!discardString.isEmpty()) params.arguments << ("modules.cpp.discardUnusedData:" + discardString); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("is Darwin"), m_qbsStdout.constData()); const bool isDarwin = m_qbsStdout.contains("is Darwin: true"); const QString output = QString::fromLocal8Bit(m_qbsStdout); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(match.lastCapturedIndex(), 1); const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; nm.start( nmPath, QStringList(QDir::currentPath() + '/' + relativeExecutableFilePath("app", m_qbsStdout))); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray nmOutput = nm.readAllStandardOutput(); QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); if (!symbolPresent && !isDarwin) QSKIP("Unused symbol detection only supported on Darwin"); QVERIFY2(nmOutput.contains("unusedFunc") == symbolPresent, nmOutput.constData()); } void TestBlackbox::discardUnusedData_data() { QTest::addColumn("discardString"); QTest::addColumn("symbolPresent"); QTest::newRow("discard") << QString("true") << false; QTest::newRow("don't discard") << QString("false") << true; QTest::newRow("default") << QString() << true; } void TestBlackbox::dotDotPcFile() { QDir::setCurrent(testDataDir + "/dot-dot-pc-file"); QCOMPARE(runQbs(), 0); } void TestBlackbox::driverLinkerFlags() { QDir::setCurrent(testDataDir + QLatin1String("/driver-linker-flags")); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (!m_qbsStdout.contains("toolchain is GCC-like")) QSKIP("Test applies on GCC-like toolchains only"); QFETCH(QString, linkerMode); QFETCH(bool, expectDriverOption); const QString linkerModeArg = "modules.cpp.linkerMode:" + linkerMode; QCOMPARE(runQbs(QStringList({"-n", "--command-echo-mode", "command-line", linkerModeArg})), 0); const QByteArray driverArg = "-nostartfiles"; const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray compileLine; QByteArray linkLine; for (const QByteArray &line : output) { if (line.contains(" -c ")) compileLine = line; else if (line.contains("main.cpp.o")) linkLine = line; } QVERIFY(!compileLine.isEmpty()); QVERIFY(!linkLine.isEmpty()); QVERIFY2(!compileLine.contains(driverArg), compileLine.constData()); QVERIFY2(linkLine.contains(driverArg) == expectDriverOption, linkLine.constData()); } void TestBlackbox::driverLinkerFlags_data() { QTest::addColumn("linkerMode"); QTest::addColumn("expectDriverOption"); QTest::newRow("link using compiler driver") << "automatic" << true; QTest::newRow("link using linker") << "manual" << false; } void TestBlackbox::dynamicLibraryInModule() { QDir::setCurrent(testDataDir + "/dynamic-library-in-module"); const QString installRootSpec = QString("qbs.installRoot:") + QDir::currentPath(); QbsRunParameters libParams(QStringList({"-f", "thelibs.qbs", installRootSpec})); libParams.buildDirectory = "libbuild"; QCOMPARE(runQbs(libParams), 0); QbsRunParameters appParams("build", QStringList({"-f", "theapp.qbs", installRootSpec})); appParams.buildDirectory = "appbuild"; QCOMPARE(runQbs(appParams), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); appParams.command = "run"; QCOMPARE(runQbs(appParams), 0); QVERIFY2(m_qbsStdout.contains("Hello from thelib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Hello from theotherlib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("thirdlib"), m_qbsStdout.constData()); QVERIFY(!QFileInfo::exists(appParams.buildDirectory + '/' + qbs::InstallOptions::defaultInstallRoot())); } void TestBlackbox::symlinkRemoval() { if (HostOsInfo::isWindowsHost()) QSKIP("No symlink support on Windows."); QDir::setCurrent(testDataDir + "/symlink-removal"); QVERIFY(QDir::current().mkdir("dir1")); QVERIFY(QDir::current().mkdir("dir2")); QVERIFY(QFile::link("dir2", "dir1/broken-link")); QVERIFY(QFile::link(QFileInfo("dir2").absoluteFilePath(), "dir1/valid-link-to-dir")); QVERIFY(QFile::link(QFileInfo("symlink-removal.qbs").absoluteFilePath(), "dir1/valid-link-to-file")); QCOMPARE(runQbs(), 0); QVERIFY(!QFile::exists("dir1")); QVERIFY(QFile::exists("dir2")); QVERIFY(QFile::exists("symlink-removal.qbs")); } void TestBlackbox::usingsAsSoleInputsNonMultiplexed() { QDir::setCurrent(testDataDir + QLatin1String("/usings-as-sole-inputs-non-multiplexed")); QCOMPARE(runQbs(), 0); const QString p3BuildDir = relativeProductBuildDir("p3"); QVERIFY(regularFileExists(p3BuildDir + "/custom1.out.plus")); QVERIFY(regularFileExists(p3BuildDir + "/custom2.out.plus")); } void TestBlackbox::variantSuffix() { QDir::setCurrent(testDataDir + "/variant-suffix"); QFETCH(bool, multiplex); QFETCH(bool, expectFailure); QFETCH(QString, variantSuffix); QFETCH(QString, buildVariant); QFETCH(QVariantMap, fileNames); QbsRunParameters params; params.command = "resolve"; params.arguments << "--force-probe-execution"; if (multiplex) params.arguments << "products.l.multiplex:true"; else params.arguments << ("modules.qbs.buildVariant:" + buildVariant); if (!variantSuffix.isEmpty()) params.arguments << ("modules.cpp.variantSuffix:" + variantSuffix); QCOMPARE(runQbs(params), 0); const QString fileNameMapKey = m_qbsStdout.contains("is Windows: true") ? "windows" : m_qbsStdout.contains("is Apple: true") ? "apple" : "unix"; if (variantSuffix.isEmpty() && multiplex && fileNameMapKey == "unix") expectFailure = true; params.command = "build"; params.expectFailure = expectFailure; params.arguments = QStringList("--clean-install-root"); QCOMPARE(runQbs(params) == 0, !expectFailure); if (expectFailure) return; const QStringList fileNameList = fileNames.value(fileNameMapKey).toStringList(); for (const QString &fileName : fileNameList) { QFile libFile("default/install-root/lib/" + fileName); QVERIFY2(libFile.exists(), qPrintable(libFile.fileName())); } } void TestBlackbox::variantSuffix_data() { QTest::addColumn("multiplex"); QTest::addColumn("expectFailure"); QTest::addColumn("variantSuffix"); QTest::addColumn("buildVariant"); QTest::addColumn("fileNames"); QTest::newRow("default suffix, debug") << false << false << QString() << QString("debug") << QVariantMap({std::make_pair(QString("windows"), QStringList("libl.ext")), std::make_pair(QString("apple"), QStringList("libl.ext")), std::make_pair(QString("unix"), QStringList("libl.ext"))}); QTest::newRow("default suffix, release") << false << false << QString() << QString("release") << QVariantMap({std::make_pair(QString("windows"), QStringList("libl.ext")), std::make_pair(QString("apple"), QStringList("libl.ext")), std::make_pair(QString("unix"), QStringList("libl.ext"))}); QTest::newRow("custom suffix, debug") << false << false << QString("blubb") << QString("debug") << QVariantMap({std::make_pair(QString("windows"), QStringList("liblblubb.ext")), std::make_pair(QString("apple"), QStringList("liblblubb.ext")), std::make_pair(QString("unix"), QStringList("liblblubb.ext"))}); QTest::newRow("custom suffix, release") << false << false << QString("blubb") << QString("release") << QVariantMap({std::make_pair(QString("windows"), QStringList("liblblubb.ext")), std::make_pair(QString("apple"), QStringList("liblblubb.ext")), std::make_pair(QString("unix"), QStringList("liblblubb.ext"))}); QTest::newRow("default suffix, multiplex") << true << false << QString() << QString() << QVariantMap({std::make_pair(QString("windows"), QStringList({"libl.ext", "libld.ext"})), std::make_pair(QString("apple"), QStringList({"libl.ext", "libl_debug.ext"})), std::make_pair(QString("unix"), QStringList())}); QTest::newRow("custom suffix, multiplex") << true << true << QString("blubb") << QString() << QVariantMap({std::make_pair(QString("windows"), QStringList()), std::make_pair(QString("apple"), QStringList()), std::make_pair(QString("unix"), QStringList())}); } void TestBlackbox::vcsGit() { const QString gitFilePath = findExecutable(QStringList("git")); if (gitFilePath.isEmpty()) QSKIP("git not found"); // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); ccp(testDataDir + "/vcs", repoDir.path()); QDir::setCurrent(repoDir.path()); QProcess git; git.start(gitFilePath, QStringList("init")); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"config", "user.name", "My Name"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"config", "user.email", "me@example.com"})); QVERIFY(waitForProcessSuccess(git)); QCOMPARE(runQbs({"resolve", {"-f", repoDir.path()}}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); // Run without git metadata. QbsRunParameters params("run", QStringList{"-f", repoDir.path()}); params.workingDir = repoDir.path() + "/.."; params.buildDirectory = repoDir.path(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); QMap newRepoState = getRepoStateFromApp(); QVERIFY(newRepoState.contains("repoState")); QVERIFY(newRepoState.contains("latestTag")); QVERIFY(newRepoState.contains("commitsSinceTag")); QVERIFY(newRepoState.contains("commitSha")); QCOMPARE(newRepoState["repoState"], QByteArray("none")); QCOMPARE(newRepoState["latestTag"], QByteArray("none")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("none")); QCOMPARE(newRepoState["commitSha"], QByteArray("none")); QMap oldRepoState = newRepoState; // Initial commit git.start(gitFilePath, QStringList({"add", "main.cpp"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "initial commit"})); QVERIFY(waitForProcessSuccess(git)); // Run with git metadata. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("none")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("none")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("g"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); oldRepoState = newRepoState; // Run with no changes. QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Run with changed source file. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Add tag with dash WAIT_FOR_NEW_TIMESTAMP(); touch("dummy.txt"); git.start(gitFilePath, QStringList({"add", "dummy.txt"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "dummy!"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"tag", "-a", "v1.0.0-beta", "-m", "Version 1.0.0-beta"})); QVERIFY(waitForProcessSuccess(git)); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("v1.0.0-beta")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("0")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("g"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); oldRepoState = newRepoState; // Add new file to repo. Add new tag WAIT_FOR_NEW_TIMESTAMP(); touch("blubb.txt"); git.start(gitFilePath, QStringList({"add", "blubb.txt"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "blubb!"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"tag", "-a", "v1.0.0", "-m", "Version 1.0.0-beta"})); QVERIFY(waitForProcessSuccess(git)); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("v1.0.0")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("0")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("g"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); // https://bugreports.qt.io/projects/QBS/issues/QBS-1814 oldRepoState = newRepoState; WAIT_FOR_NEW_TIMESTAMP(); touch("loremipsum.txt"); git.start(gitFilePath, QStringList({"add", "loremipsum.txt"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "loremipsum!"})); QVERIFY(waitForProcessSuccess(git)); // Remove .git/logs/HEAD QFile::remove(repoDir.path() + "/.git/logs/HEAD"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("v1.0.0")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("1")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("g"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); } void TestBlackbox::vcsSubversion() { const QString svnadminFilePath = findExecutable(QStringList("svnadmin")); if (svnadminFilePath.isEmpty()) QSKIP("svnadmin not found"); const QString svnFilePath = findExecutable(QStringList("svn")); if (svnFilePath.isEmpty()) QSKIP("svn not found"); if (HostOsInfo::isWindowsHost() && qEnvironmentVariableIsSet("GITHUB_ACTIONS")) QSKIP("Skip this test when running on GitHub"); // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); QProcess proc; proc.setWorkingDirectory(repoDir.path()); proc.start(svnadminFilePath, QStringList({"create", "vcstest"})); QVERIFY(waitForProcessSuccess(proc)); const QString projectUrl = "file://" + repoDir.path() + "/vcstest/trunk"; proc.start(svnFilePath, QStringList({"import", testDataDir + "/vcs", projectUrl, "-m", "initial import"})); QVERIFY(waitForProcessSuccess(proc)); QTemporaryDir checkoutDir; QVERIFY(checkoutDir.isValid()); proc.setWorkingDirectory(checkoutDir.path()); proc.start(svnFilePath, QStringList({"co", projectUrl, "."})); QVERIFY(waitForProcessSuccess(proc)); // Initial runs QDir::setCurrent(checkoutDir.path()); QbsRunParameters failParams; failParams.command = "run"; failParams.expectFailure = true; const int retval = runQbs(failParams); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); if (m_qbsStderr.contains("svn too old")) QSKIP("svn too old"); QCOMPARE(retval, 0); QMap newRepoState = getRepoStateFromApp(); QVERIFY(newRepoState.contains("repoState")); QVERIFY(newRepoState.contains("latestTag")); QVERIFY(newRepoState.contains("commitsSinceTag")); QVERIFY(newRepoState.contains("commitSha")); QCOMPARE(newRepoState["repoState"], QByteArray("1")); QCOMPARE(newRepoState["latestTag"], QByteArray("none")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("none")); QCOMPARE(newRepoState["commitSha"], QByteArray("none")); QMap oldRepoState = newRepoState; QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Run with changed source file. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Add new file to repo. WAIT_FOR_NEW_TIMESTAMP(); touch("blubb.txt"); proc.start(svnFilePath, QStringList({"add", "blubb.txt"})); QVERIFY(waitForProcessSuccess(proc)); proc.start(svnFilePath, QStringList({"commit", "-m", "blubb!"})); QVERIFY(waitForProcessSuccess(proc)); QCOMPARE(runQbs(QbsRunParameters("run")), 0); newRepoState = getRepoStateFromApp(); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); } void TestBlackbox::vcsMercurial() { const QString hgFilePath = findExecutable(QStringList("hg")); if (hgFilePath.isEmpty()) QSKIP("hg not found"); // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); ccp(testDataDir + "/vcs", repoDir.path()); QDir::setCurrent(repoDir.path()); QProcess hg; hg.start(hgFilePath, QStringList{"init"}); QVERIFY(waitForProcessSuccess(hg)); const QStringList credentials{"--config", "ui.username=\"My Name \""}; QCOMPARE(runQbs({"resolve", {"-f", repoDir.path()}}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); // Run without hg metadata QbsRunParameters params("run", QStringList{"-f", repoDir.path()}); params.workingDir = repoDir.path() + "/.."; params.buildDirectory = repoDir.path(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); QMap newRepoState = getRepoStateFromApp(); QVERIFY(newRepoState.contains("repoState")); QVERIFY(newRepoState.contains("latestTag")); QVERIFY(newRepoState.contains("commitsSinceTag")); QVERIFY(newRepoState.contains("commitSha")); QCOMPARE(newRepoState["repoState"], QByteArray("none")); QCOMPARE(newRepoState["latestTag"], QByteArray("none")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("none")); QCOMPARE(newRepoState["commitSha"], QByteArray("none")); QMap oldRepoState = newRepoState; // Initial commit hg.start(hgFilePath, QStringList{"add", "main.cpp"}); QVERIFY(waitForProcessSuccess(hg)); hg.start(hgFilePath, credentials + QStringList{"commit", "-m", "initial commit"}); QVERIFY(waitForProcessSuccess(hg)); // Run with hg metadata. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); QCOMPARE(newRepoState["latestTag"], QByteArray("null")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("1")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("m"))); oldRepoState = newRepoState; // Run with no changes. QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Run with changed source file. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Add tag with dash WAIT_FOR_NEW_TIMESTAMP(); hg.start(hgFilePath, credentials + QStringList{"tag", "v1.0.0-beta"}); QVERIFY(waitForProcessSuccess(hg)); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("v1.0.0-beta")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("1")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("m"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); oldRepoState = newRepoState; // Add new file to repo. Add new tag WAIT_FOR_NEW_TIMESTAMP(); touch("blubb.txt"); hg.start(hgFilePath, QStringList{"add", "blubb.txt"}); QVERIFY(waitForProcessSuccess(hg)); hg.start(hgFilePath, credentials + QStringList{"commit", "-m", "blubb!"}); QVERIFY(waitForProcessSuccess(hg)); hg.start(hgFilePath, credentials + QStringList{"tag", "v1.0.0"}); QVERIFY(waitForProcessSuccess(hg)); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState["latestTag"], QByteArray("v1.0.0")); QCOMPARE(newRepoState["commitsSinceTag"], QByteArray("1")); QVERIFY(newRepoState["commitSha"] != QByteArray("none")); QVERIFY(newRepoState["commitSha"].startsWith(QByteArray("m"))); QVERIFY(oldRepoState["repoState"] != newRepoState["repoState"]); } void TestBlackbox::versionCheck() { QDir::setCurrent(testDataDir + "/versioncheck"); QFETCH(QString, requestedMinVersion); QFETCH(QString, requestedMaxVersion); QFETCH(QString, actualVersion); QFETCH(QString, errorMessage); QbsRunParameters params; params.expectFailure = !errorMessage.isEmpty(); params.arguments << "-n" << ("products.versioncheck.requestedMinVersion:'" + requestedMinVersion + "'") << ("products.versioncheck.requestedMaxVersion:'" + requestedMaxVersion + "'") << ("modules.lower.version:'" + actualVersion + "'"); QCOMPARE(runQbs(params) == 0, errorMessage.isEmpty()); if (params.expectFailure) QVERIFY2(QString(m_qbsStderr).contains(errorMessage), m_qbsStderr.constData()); } void TestBlackbox::versionCheck_data() { QTest::addColumn("requestedMinVersion"); QTest::addColumn("requestedMaxVersion"); QTest::addColumn("actualVersion"); QTest::addColumn("errorMessage"); QTest::newRow("ok1") << "1.0" << "1.1" << "1.0" << QString(); QTest::newRow("ok2") << "1.0" << "2.0.1" << "2.0" << QString(); QTest::newRow("ok3") << "1.0" << "2.5" << "1.5" << QString(); QTest::newRow("ok3") << "1.0" << "2.0" << "1.99" << QString(); QTest::newRow("bad1") << "2.0" << "2.1" << "1.5" << "needs to be at least"; QTest::newRow("bad2") << "2.0" << "3.0" << "1.5" << "needs to be at least"; QTest::newRow("bad3") << "2.0" << "3.0" << "3.5" << "needs to be lower than"; QTest::newRow("bad4") << "2.0" << "3.0" << "3.0" << "needs to be lower than"; // "bad" because the "higer" module has stronger requirements. QTest::newRow("bad5") << "0.1" << "0.9" << "0.5" << "Impossible version constraint"; } void TestBlackbox::versionScript() { QDir::setCurrent(testDataDir + "/versionscript"); QCOMPARE(runQbs(QbsRunParameters("resolve", {"qbs.installRoot:" + QDir::currentPath()})), 0); const bool isLinuxGcc = m_qbsStdout.contains("is gcc for Linux: true"); const bool isNotLinuxGcc = m_qbsStdout.contains("is gcc for Linux: false"); if (isNotLinuxGcc) QSKIP("version script test only applies to Linux"); QVERIFY(isLinuxGcc); QCOMPARE(runQbs(QbsRunParameters(QStringList("-q"))), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; nm.start(nmPath, QStringList(QDir::currentPath() + "/libversionscript.so")); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray allSymbols = nm.readAllStandardOutput(); QCOMPARE(nm.exitCode(), 0); QVERIFY2(allSymbols.contains("dummyLocal"), allSymbols.constData()); QVERIFY2(allSymbols.contains("dummyGlobal"), allSymbols.constData()); nm.start(nmPath, QStringList() << "-g" << QDir::currentPath() + "/libversionscript.so"); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray globalSymbols = nm.readAllStandardOutput(); QCOMPARE(nm.exitCode(), 0); QVERIFY2(!globalSymbols.contains("dummyLocal"), allSymbols.constData()); QVERIFY2(globalSymbols.contains("dummyGlobal"), allSymbols.constData()); } void TestBlackbox::wholeArchive() { QDir::setCurrent(testDataDir + "/whole-archive"); QFETCH(QString, wholeArchiveString); QFETCH(bool, ruleInvalidationExpected); QFETCH(bool, dllLinkingExpected); const QbsRunParameters resolveParams("resolve", QStringList("products.dynamiclib.linkWholeArchive:" + wholeArchiveString)); QCOMPARE(runQbs(QbsRunParameters(resolveParams)), 0); const bool linkerSupportsWholeArchive = m_qbsStdout.contains("can link whole archives"); const bool linkerDoesNotSupportWholeArchive = m_qbsStdout.contains("cannot link whole archives"); QVERIFY(linkerSupportsWholeArchive != linkerDoesNotSupportWholeArchive); if (m_qbsStdout.contains("is emscripten: true")) QSKIP("Irrelevant for emscripten"); QVERIFY(m_qbsStdout.contains("is emscripten: false")); QCOMPARE(runQbs(QbsRunParameters(QStringList({ "-vvp", "dynamiclib" }))), 0); const bool wholeArchive = !wholeArchiveString.isEmpty(); const bool outdatedVisualStudio = wholeArchive && linkerDoesNotSupportWholeArchive; const QByteArray invalidationOutput = "Value for property 'staticlib 1:cpp.linkWholeArchive' has changed."; if (!outdatedVisualStudio) QCOMPARE(m_qbsStderr.contains(invalidationOutput), ruleInvalidationExpected); QCOMPARE(m_qbsStdout.contains("linking"), dllLinkingExpected && !outdatedVisualStudio); QbsRunParameters buildParams(QStringList("-p")); buildParams.expectFailure = !wholeArchive || outdatedVisualStudio; buildParams.arguments << "app1"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app2"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app4"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app3"; buildParams.expectFailure = true; QVERIFY(runQbs(QbsRunParameters(buildParams)) != 0); } void TestBlackbox::wholeArchive_data() { QTest::addColumn("wholeArchiveString"); QTest::addColumn("ruleInvalidationExpected"); QTest::addColumn("dllLinkingExpected"); QTest::newRow("link normally") << QString() << false << true; QTest::newRow("link whole archive") << "true" << true << true; QTest::newRow("link whole archive again") << "notfalse" << false << false; } static bool symlinkExists(const QString &linkFilePath) { return QFileInfo(linkFilePath).isSymLink(); } void TestBlackbox::clean() { QDir::setCurrent(testDataDir + "/clean"); // Can't clean without a build graph. QbsRunParameters failParams("clean"); failParams.expectFailure = true; QVERIFY(runQbs(failParams) != 0); // Default behavior: Remove all. QCOMPARE(runQbs(), 0); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); const QString appObjectFilePath = relativeProductBuildDir("app") + '/' + inputDirHash(".") + "/main.cpp" + objectSuffix; const QString appExeFilePath = relativeExecutableFilePath("app", m_qbsStdout); const QString depObjectFilePath = relativeProductBuildDir("dep") + '/' + inputDirHash(".") + "/dep.cpp" + objectSuffix; const QString depLibBase = relativeProductBuildDir("dep") + '/' + QBS_HOST_DYNAMICLIB_PREFIX + "dep"; const bool isEmscripten = m_qbsStdout.contains("is emscripten: true"); const bool isNotEmscripten = m_qbsStdout.contains("is emscripten: false"); QCOMPARE(isEmscripten, !isNotEmscripten); QString depLibFilePath; QStringList symlinks; if (qbs::Internal::HostOsInfo::isMacosHost()) { depLibFilePath = depLibBase + ".1.1.0" + QBS_HOST_DYNAMICLIB_SUFFIX; symlinks << depLibBase + ".1.1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + ".1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } else if (qbs::Internal::HostOsInfo::isAnyUnixHost()) { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1.0"; if (!isEmscripten) { symlinks << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } } else { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } QVERIFY2(regularFileExists(appObjectFilePath), qPrintable(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"))), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Remove all, with a forced re-resolve in between. // This checks that rescuable artifacts are also removed. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "modules.cpp.optimization:none")), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "modules.cpp.optimization:fast")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Dry run. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-n"))), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependency only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-p") << "dep")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependent product only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-p") << "app")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); } void TestBlackbox::conditionalExport() { QDir::setCurrent(testDataDir + "/conditional-export"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("missing define"), m_qbsStderr.constData()); params.expectFailure = false; params.arguments << "project.enableExport:true"; params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::conditionalFileTagger() { QDir::setCurrent(testDataDir + "/conditional-filetagger"); QbsRunParameters params(QStringList("products.theApp.enableTagger:false")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling")); params.arguments = QStringList("products.theApp.enableTagger:true"); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling")); } void TestBlackbox::configure() { QDir::setCurrent(testDataDir + "/configure"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("Configured at"), m_qbsStdout.constData()); } void TestBlackbox::conflictingArtifacts() { QDir::setCurrent(testDataDir + "/conflicting-artifacts"); QbsRunParameters params(QStringList() << "-n"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Conflicting artifacts"), m_qbsStderr.constData()); } void TestBlackbox::cxxLanguageVersion() { QDir::setCurrent(testDataDir + "/cxx-language-version"); rmDirR(relativeBuildDir()); QFETCH(QString, version); QFETCH(QVariantMap, requiredFlags); QFETCH(QVariantMap, forbiddenFlags); QbsRunParameters resolveParams; resolveParams.command = "resolve"; resolveParams.arguments << "--force-probe-execution"; resolveParams.arguments << "modules.cpp.useLanguageVersionFallback:true"; if (!version.isEmpty()) resolveParams.arguments << ("modules.cpp.cxxLanguageVersion:" + version); QCOMPARE(runQbs(resolveParams), 0); QString mapKey; if (version == "c++17" && m_qbsStdout.contains("is even newer MSVC: true")) mapKey = "msvc-brandnew"; else if (m_qbsStdout.contains("is newer MSVC: true")) mapKey = "msvc-new"; else if (m_qbsStdout.contains("is older MSVC: true")) mapKey = "msvc_old"; else if (m_qbsStdout.contains("is GCC: true")) mapKey = "gcc"; QVERIFY2(!mapKey.isEmpty(), m_qbsStdout.constData()); QbsRunParameters buildParams; buildParams.expectFailure = mapKey == "gcc" && (version == "c++17" || version == "c++21"); buildParams.arguments = QStringList({"--command-echo-mode", "command-line"}); const int retVal = runQbs(buildParams); if (!buildParams.expectFailure) QCOMPARE(retVal, 0); const QString requiredFlag = requiredFlags.value(mapKey).toString(); if (!requiredFlag.isEmpty()) QVERIFY2(m_qbsStdout.contains(requiredFlag.toLocal8Bit()), m_qbsStdout.constData()); const QString forbiddenFlag = forbiddenFlags.value(mapKey).toString(); if (!forbiddenFlag.isEmpty()) QVERIFY2(!m_qbsStdout.contains(forbiddenFlag.toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::cxxLanguageVersion_data() { QTest::addColumn("version"); QTest::addColumn("requiredFlags"); QTest::addColumn("forbiddenFlags"); QTest::newRow("C++98") << QString("c++98") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++98"))}) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); QTest::newRow("C++11") << QString("c++11") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++0x"))}) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); QTest::newRow("C++14") << QString("c++14") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++1y")), std::make_pair(QString("msvc-new"), QString("/std:c++14")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("C++17") << QString("c++17") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++1z")), std::make_pair(QString("msvc-new"), QString("/std:c++latest")), std::make_pair(QString("msvc-brandnew"), QString("/std:c++17")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("C++21") << QString("c++21") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++21")), std::make_pair(QString("msvc-new"), QString("/std:c++latest")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("default") << QString() << QVariantMap() << QVariantMap({std::make_pair(QString("gcc"), QString("-std=")), std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); } void TestBlackbox::conanfileProbe_data() { QTest::addColumn("forceFailure"); QTest::newRow("success") << false; QTest::newRow("failure") << true; } void TestBlackbox::conanfileProbe() { QFETCH(bool, forceFailure); QString executable = findExecutable({"conan"}); if (executable.isEmpty()) QSKIP("conan is not installed or not available in PATH."); const auto conanVersion = this->conanVersion(executable); if (!conanVersion.isValid()) QSKIP("Can't get conan version."); if (compare(conanVersion, qbs::Version(2, 0)) >= 0) QSKIP("This test does not apply to conan 2.0 and newer."); // We first build a dummy package testlib and use that as dependency // in the testapp package. QDir::setCurrent(testDataDir + "/conanfile-probe/testlib"); QStringList arguments{"create -o opt=True -s os=AIX . testlib/1.2.3@qbs/testing"}; QProcess conan; conan.start(executable, arguments); QVERIFY(waitForProcessSuccess(conan)); QDir::setCurrent(testDataDir + "/conanfile-probe/testapp"); QCOMPARE(runQbs(QbsRunParameters("resolve", {"--force-probe-execution", QStringLiteral("projects.conanfile-probe-project.forceFailure:") + (forceFailure ? "true" : "false")})), forceFailure ? 1 : 0); QFile file(relativeBuildDir() + "/results.json"); QVERIFY(file.open(QIODevice::ReadOnly)); QVariantMap actualResults = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); const auto generatedFilesPath = actualResults.take("generatedFilesPath").toString(); // We want to make sure that generatedFilesPath is under the project directory, // but we don't care about the actual name. QVERIFY(directoryExists(relativeBuildDir() + "/genconan/" + QFileInfo(generatedFilesPath).baseName())); const QVariantMap expectedResults = { { "json", "TESTLIB_ENV_VAL" }, { "dependencies", QVariantList{"testlib1", "testlib2"} }, }; QCOMPARE(actualResults, expectedResults); } void TestBlackbox::conflictingPropertyValues_data() { QTest::addColumn("overrideInProduct"); QTest::newRow("don't override in product") << false; QTest::newRow("override in product") << true; } void TestBlackbox::conflictingPropertyValues() { QFETCH(bool, overrideInProduct); QDir::setCurrent(testDataDir + "/conflicting-property-values"); if (overrideInProduct) REPLACE_IN_FILE("conflicting-property-values.qbs", "// low.prop: name", "low.prop: name"); else REPLACE_IN_FILE("conflicting-property-values.qbs", "low.prop: name", "// low.prop: name"); WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(QString("resolve")), 0); if (overrideInProduct) { // Binding in product itself overrides everything else, module-level conflicts // are irrelevant. QVERIFY2(m_qbsStdout.contains("final prop value: toplevel"), m_qbsStdout.constData()); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); } else { // Only the conflicts in the highest-level modules are reported, lower-level conflicts // are irrelevant. // prop2 does not cause a conflict, because the values are the same. QVERIFY2(m_qbsStdout.contains("final prop value: highest"), m_qbsStdout.constData()); QVERIFY2(m_qbsStderr.contains("Conflicting scalar values for property 'prop'"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("values.qbs") == 2, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("values.qbs:20:23"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("values.qbs:30:23"), m_qbsStderr.constData()); } } void TestBlackbox::cpuFeatures() { QDir::setCurrent(testDataDir + "/cpu-features"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); const bool isX86 = m_qbsStdout.contains("is x86: true"); const bool isX64 = m_qbsStdout.contains("is x64: true"); if (!isX86 && !isX64) { QVERIFY2(m_qbsStdout.contains("is x86: false") && m_qbsStdout.contains("is x64: false"), m_qbsStdout.constData()); QSKIP("Not an x86 host"); } const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isMsvc = m_qbsStdout.contains("is msvc: true"); if (!isGcc && !isMsvc) { QVERIFY2(m_qbsStdout.contains("is gcc: false") && m_qbsStdout.contains("is msvc: false"), m_qbsStdout.constData()); QSKIP("Neither GCC nor MSVC"); } QbsRunParameters params(QStringList{"--command-echo-mode", "command-line"}); params.expectFailure = true; runQbs(params); if (isGcc) { QVERIFY2(m_qbsStdout.contains("-msse2") && m_qbsStdout.contains("-mavx") && m_qbsStdout.contains("-mno-avx512f"), m_qbsStdout.constData()); } else { QVERIFY2(m_qbsStdout.contains("/arch:AVX"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("/arch:AVX2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("/arch:SSE2") == isX86, m_qbsStdout.constData()); } } void TestBlackbox::cxxModules_data() { QTest::addColumn("projectDir"); QTest::newRow("single-module") << "single-mod"; QTest::newRow("dot-in-name") << "dot-in-name"; QTest::newRow("export-import") << "export-import"; QTest::newRow("import-std") << "import-std"; QTest::newRow("import-std-compat") << "import-std-compat"; QTest::newRow("dependent-modules") << "dep-mods"; QTest::newRow("declaration-implementation") << "decl-impl"; QTest::newRow("library-module") << "lib-mod"; QTest::newRow("partitions") << "partitions"; QTest::newRow("partitions-recursive") << "part-rec"; QTest::newRow("partitions-dependency-on-module") << "part-depmod"; QTest::newRow("partitions-library") << "part-lib"; } void TestBlackbox::cxxModules() { QFETCH(QString, projectDir); QDir::setCurrent(testDataDir + "/cxx-modules/" + projectDir); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(QbsRunParameters{"resolve"}), 0); if (m_qbsStdout.contains("Unsupported toolchainType")) QSKIP("Modules are not supported for this toolchain"); QCOMPARE(runQbs(QbsRunParameters{"build"}), 0); } void TestBlackbox::cxxModulesChangesTracking() { const auto checkContains = [this](const QStringList &files) { for (const auto &file : files) { if (!m_qbsStdout.contains(QByteArrayLiteral("compiling ") + file.toUtf8())) return false; } return true; }; const auto checkNotContains = [this](const QStringList &files) { for (const auto &file : files) { if (m_qbsStdout.contains(QByteArrayLiteral("compiling ") + file.toUtf8())) return false; } return true; }; QDir::setCurrent(testDataDir + "/cxx-modules/dep-mods"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(QbsRunParameters{"resolve"}), 0); if (m_qbsStdout.contains("Unsupported toolchainType")) QSKIP("Modules are not supported for this toolchain"); QbsRunParameters buildParams{"build"}; QCOMPARE(runQbs(buildParams), 0); QVERIFY2(checkContains({"a.cppm", "b.cppm", "c.cppm", "main.cpp"}), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(checkContains({"main.cpp"}), m_qbsStdout.constData()); QVERIFY2(checkNotContains({"a.cppm", "b.cppm", "c.cppm"}), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("c.cppm"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(checkContains({"c.cppm", "main.cpp"}), m_qbsStdout.constData()); QVERIFY2(checkNotContains({"a.cppm", "b.cppm"}), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("b.cppm"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(checkContains({"b.cppm", "c.cppm", "main.cpp"}), m_qbsStdout.constData()); QVERIFY2(checkNotContains({"a.cppm"}), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("a.cppm"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(checkContains({"a.cppm", "b.cppm", "c.cppm", "main.cpp"}), m_qbsStdout.constData()); } void TestBlackbox::dateProperty() { QDir::setCurrent(testDataDir + "/date-property"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("The stored date was 1999-12-31"), m_qbsStdout.constData()); } void TestBlackbox::renameDependency() { QDir::setCurrent(testDataDir + "/renameDependency"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/renameDependency/work"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("lib.h"); QFile::remove("lib.cpp"); ccp("../after", "."); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); } void TestBlackbox::separateDebugInfo() { QDir::setCurrent(testDataDir + "/separate-debug-info"); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.debugInformation:true"))), 0); const bool isWindows = m_qbsStdout.contains("is windows: yes"); const bool isNotWindows = m_qbsStdout.contains("is windows: no"); QVERIFY(isWindows != isNotWindows); const bool isMacos = m_qbsStdout.contains("is macos: yes"); const bool isNotMacos = m_qbsStdout.contains("is macos: no"); QVERIFY(isMacos != isNotMacos); const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); const bool isNotDarwin = m_qbsStdout.contains("is darwin: no"); QVERIFY(isDarwin != isNotDarwin); const bool isGcc = m_qbsStdout.contains("is gcc: yes"); const bool isNotGcc = m_qbsStdout.contains("is gcc: no"); QVERIFY(isGcc != isNotGcc); const bool isMsvc = m_qbsStdout.contains("is msvc: yes"); const bool isNotMsvc = m_qbsStdout.contains("is msvc: no"); QVERIFY(isMsvc != isNotMsvc); const bool isEmscripten = m_qbsStdout.contains("is emscripten: yes"); const bool isNotEmscripten = m_qbsStdout.contains("is emscripten: no"); QVERIFY(isEmscripten != isNotEmscripten); if (isDarwin) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Resources/DWARF/app1")); QCOMPARE(QDir(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.app.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("app3") + "/app3.app.dSYM")); if (isMacos) { QVERIFY(regularFileExists(relativeProductBuildDir("app3") + "/app3.app/Contents/MacOS/app3.dwarf")); } else { QVERIFY(regularFileExists(relativeProductBuildDir("app3") + "/app3.app/app3.dwarf")); } QVERIFY(directoryExists(relativeProductBuildDir("app4") + "/app4.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Resources/DWARF/app4")); QCOMPARE(QDir(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("app5") + "/app5.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Resources/DWARF/foo1")); QCOMPARE(QDir(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/foo2.framework.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo3") + "/foo3.framework.dSYM")); if (isMacos) { QVERIFY(regularFileExists(relativeProductBuildDir("foo3") + "/foo3.framework/Versions/A/foo3.dwarf")); } else { QVERIFY(regularFileExists(relativeProductBuildDir("foo3") + "/foo3.framework/foo3.dwarf")); } QVERIFY(directoryExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF/libfoo4.dylib")); QCOMPARE(QDir(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("foo5") + "/libfoo5.dylib.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Resources/DWARF/bar1")); QCOMPARE(QDir(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + "/bar2.bundle.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar3") + "/bar3.bundle.dSYM")); if (isMacos) { QVERIFY(regularFileExists(relativeProductBuildDir("bar3") + "/bar3.bundle/Contents/MacOS/bar3.dwarf")); } else { QVERIFY(regularFileExists(relativeProductBuildDir("bar3") + "/bar3.bundle/bar3.dwarf")); } QVERIFY(directoryExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Resources/DWARF/bar4.bundle")); QCOMPARE(QDir(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("bar5") + "/bar5.bundle.dwarf")); } else if (isGcc && isNotEmscripten) { const QString exeSuffix = isWindows ? ".exe" : ""; const QString dllPrefix = isWindows ? "" : "lib"; const QString dllSuffix = isWindows ? ".dll" : ".so"; QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1" + exeSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2" + exeSuffix + ".debug")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + '/' + dllPrefix + "foo1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + '/' + "foo2" + dllSuffix + ".debug")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + '/' + dllPrefix + "bar1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + '/' + dllPrefix + "bar2" + dllSuffix + ".debug")); } else if (isEmscripten) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.wasm.debug.wasm")); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.wasm.debug.wasm")); } else if (isMsvc) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + "/bar1.pdb")); // MSVC's linker even creates a pdb file if /Z7 is passed to the compiler. } else { QSKIP("Unsupported toolchain. Skipping."); } } void TestBlackbox::trackAddFile() { QList output; QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QString unchangedObjectFile = relativeBuildDir() + "/someapp/narf.cpp" + objectSuffix; QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("trackAddFile.qbs"); touch("main.cpp"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); } void TestBlackbox::trackExternalProductChanges() { QDir::setCurrent(testDataDir + "/trackExternalProductChanges"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); QbsRunParameters params; params.environment.insert("QBS_TEST_PULL_IN_FILE_VIA_ENV", "1"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2(!m_qbsStdout.contains("Installing"), m_qbsStdout.constData()); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY2(!m_qbsStdout.contains("compiling jsFileChange.cpp"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("fileList.js", "return []", "return ['jsFileChange.cpp']"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); REPLACE_IN_FILE("fileList.js", "['jsFileChange.cpp']", "[]"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); QFile cppFile("fileExists.cpp"); QVERIFY(cppFile.open(QIODevice::WriteOnly)); cppFile.write("void fileExists() { }\n"); cppFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling fileExists.cpp")); QVERIFY2( m_qbsStdout.contains("[trackExternalProductChanges] installing "), m_qbsStdout.constData()); if (isNotGcc) QSKIP("The remainder of this test requires a GCC-like toolchain"); QVERIFY(isGcc); rmDirR(relativeBuildDir()); params.environment = QbsRunParameters::defaultEnvironment(); params.environment.insert("INCLUDE_PATH_TEST", "1"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("hiddenheaderqbs.h"), m_qbsStderr.constData()); params.command = "resolve"; params.environment.insert("CPLUS_INCLUDE_PATH", QDir::toNativeSeparators(QDir::currentPath() + "/hidden")); params.expectFailure = false; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::trackGroupConditionChange() { QbsRunParameters params; params.expectFailure = true; QDir::setCurrent(testDataDir + "/group-condition-change"); QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("jibbetnich")); params.command = "resolve"; params.arguments = QStringList("project.kaputt:false"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); } void TestBlackbox::trackRemoveFile() { QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); QList output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); QString unchangedObjectFile = relativeBuildDir() + "/someapp/narf.cpp" + objectSuffix; QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("trackAddFile.qbs"); QFile::remove("main.cpp"); QFile::copy("../before/trackAddFile.qbs", "trackAddFile.qbs"); QFile::copy("../before/main.cpp", "main.cpp"); QVERIFY(QFile::remove("zort.h")); QVERIFY(QFile::remove("zort.cpp")); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("resolve"))), 0); touch("main.cpp"); touch("trackAddFile.qbs"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); // the object file for the removed cpp file should have vanished too QVERIFY(!regularFileExists(relativeBuildDir() + "/someapp/zort.cpp" + objectSuffix)); } void TestBlackbox::trackAddFileTag() { QList output; QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); touch("trackFileTags.qbs"); waitForFileUnlock(); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); } void TestBlackbox::trackRemoveFileTag() { QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); // check if the artifacts are here that will become stale in the 2nd step QVERIFY(regularFileExists( relativeProductBuildDir("someapp") + '/' + inputDirHash(".") + "/main_foo.cpp" + objectSuffix)); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp")); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo")); QList output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../before", "."); touch("main.cpp"); touch("trackFileTags.qbs"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QVERIFY(!output.isEmpty()); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); // check if stale artifacts have been removed QCOMPARE( regularFileExists( relativeProductBuildDir("someapp") + '/' + inputDirHash(".") + "/main_foo.cpp" + objectSuffix), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp"), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo"), false); } void TestBlackbox::trackAddProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product3")); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); } void TestBlackbox::trackRemoveProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); QVERIFY(m_qbsStdout.contains("linking product3")); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("zoo.cpp"); QFile::remove("product3.qbs"); copyFileAndUpdateTimestamp("../before/trackProducts.qbs", "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); QVERIFY(!m_qbsStdout.contains("linking product3")); } void TestBlackbox::wildcardRenaming() { QDir::setCurrent(testDataDir + "/wildcard_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); WAIT_FOR_NEW_TIMESTAMP(); QFile::rename(QDir::currentPath() + "/pioniere.txt", QDir::currentPath() + "/fdj.txt"); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/fdj.txt").exists()); } void TestBlackbox::recursiveRenaming() { QDir::setCurrent(testDataDir + "/recursive_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(QFile::rename(QDir::currentPath() + "/dir/wasser.txt", QDir::currentPath() + "/dir/wein.txt")); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wein.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); } void TestBlackbox::recursiveWildcards() { QDir::setCurrent(testDataDir + "/recursive_wildcards"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file1.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists()); QFile outputFile(defaultInstallRoot + "/output.txt"); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txt")); outputFile.close(); WAIT_FOR_NEW_TIMESTAMP(); QFile newFile("dir/subdir/file3.txt"); QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString())); newFile.close(); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file3.txt").exists()); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txtfile3.txt")); outputFile.close(); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY2(newFile.remove(), qPrintable(newFile.errorString())); QVERIFY2(!newFile.exists(), qPrintable(newFile.fileName())); QCOMPARE(runQbs(QbsRunParameters("install", QStringList{ "--clean-install-root"})), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file1.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists()); QVERIFY(!QFileInfo(defaultInstallRoot + "/dir/file3.txt").exists()); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txt")); } void TestBlackbox::referenceErrorInExport() { QDir::setCurrent(testDataDir + "/referenceErrorInExport"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2( m_qbsStderr.contains("referenceErrorInExport.qbs:2:5 Error while handling product " "'referenceErrorInExport':"), m_qbsStderr.constData()); QVERIFY2( m_qbsStderr.contains("referenceErrorInExport.qbs:5:27 While evaluating here"), m_qbsStderr.constData()); QVERIFY2( m_qbsStderr.contains("referenceErrorInExport.qbs:15:31 includePaths is not defined"), m_qbsStderr.constData()); } void TestBlackbox::removeDuplicateLibraries_data() { QTest::addColumn("removeDuplicates"); QTest::newRow("remove duplicates") << true; QTest::newRow("don't remove duplicates") << false; } void TestBlackbox::removeDuplicateLibraries() { QDir::setCurrent(testDataDir + "/remove-duplicate-libs"); QFETCH(bool, removeDuplicates); const QbsRunParameters resolveParams("resolve", {"-f", "remove-duplicate-libs.qbs", "project.removeDuplicates:" + QString(removeDuplicates? "true" : "false")}); QCOMPARE(runQbs(resolveParams), 0); const bool isBfd = m_qbsStdout.contains("is bfd linker: true"); const bool isNotBfd = m_qbsStdout.contains("is bfd linker: false"); QVERIFY2(isBfd != isNotBfd, m_qbsStdout.constData()); QbsRunParameters buildParams("build"); buildParams.expectFailure = removeDuplicates && isBfd; QCOMPARE(runQbs(buildParams) == 0, !buildParams.expectFailure); } void TestBlackbox::reproducibleBuild() { QFETCH(bool, reproducible); QDir::setCurrent(testDataDir + "/reproducible-build"); QbsRunParameters params("resolve"); params.arguments << QString("modules.cpp.enableReproducibleBuilds:") + (reproducible ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); const QString objectSuffix = parsedObjectSuffix(m_qbsStdout); if (isNotGcc) QSKIP("reproducible builds only supported for gcc"); QVERIFY(isGcc); QCOMPARE(runQbs(), 0); QFile object( relativeProductBuildDir("the product") + '/' + inputDirHash(".") + '/' + "file1.cpp" + objectSuffix); QVERIFY2(object.open(QIODevice::ReadOnly), qPrintable(object.fileName())); const QByteArray oldContents = object.readAll(); object.close(); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!object.exists()); params.command = "build"; QCOMPARE(runQbs(params), 0); if (reproducible) { QVERIFY(object.open(QIODevice::ReadOnly)); const QByteArray newContents = object.readAll(); QVERIFY(oldContents == newContents); object.close(); } QCOMPARE(runQbs(QbsRunParameters("clean")), 0); } void TestBlackbox::reproducibleBuild_data() { QTest::addColumn("reproducible"); QTest::newRow("non-reproducible build") << false; QTest::newRow("reproducible build") << true; } void TestBlackbox::responseFiles() { QDir::setCurrent(testDataDir + "/response-files"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "install"; params.arguments << "--install-root" << "installed"; QCOMPARE(runQbs(params), 0); QFile file("installed/response-file-content.txt"); QVERIFY(file.open(QIODevice::ReadOnly)); const QList expected = QList() << "foo" << qbs::Internal::shellQuote(QStringLiteral("with space")).toUtf8() << "bar" << ""; QList lines = file.readAll().split('\n'); for (auto &line : lines) line = line.trimmed(); QCOMPARE(lines, expected); } void TestBlackbox::retaggedOutputArtifact() { QDir::setCurrent(testDataDir + "/retagged-output-artifact"); QbsRunParameters resolveParams("resolve"); resolveParams.arguments = QStringList("products.p.useTag1:true"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); const QString a2 = relativeProductBuildDir("p") + "/a2.txt"; const QString a3 = relativeProductBuildDir("p") + "/a3.txt"; QVERIFY2(QFile::exists(a2), qPrintable(a2)); QVERIFY2(!QFile::exists(a3), qPrintable(a3)); resolveParams.arguments = QStringList("products.p.useTag1:false"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(a2), qPrintable(a2)); QVERIFY2(QFile::exists(a3), qPrintable(a3)); resolveParams.arguments = QStringList("products.p.useTag1:true"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(a2), qPrintable(a2)); QVERIFY2(!QFile::exists(a3), qPrintable(a3)); } void TestBlackbox::rpathlinkDeduplication() { QDir::setCurrent(testDataDir + "/rpathlink-deduplication"); QbsRunParameters resolveParams{"resolve"}; QCOMPARE(runQbs(resolveParams), 0); const bool useRPathLink = m_qbsStdout.contains("useRPathLink: true"); const bool dontUseRPathLink = m_qbsStdout.contains("useRPathLink: false"); QVERIFY2(useRPathLink || dontUseRPathLink, m_qbsStdout); if (dontUseRPathLink) QSKIP("Only applies to toolchains that support rPathLink"); const QString output = QString::fromLocal8Bit(m_qbsStdout); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*===(.*)===.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString linkFlag = match.captured(1); QbsRunParameters buildParams; buildParams.arguments = QStringList({"--command-echo-mode", "command-line"}); QCOMPARE(runQbs(buildParams), 0); // private DynamicLibraryA is a dependency for 2 other libs but should only appear once const auto libDir = QFileInfo(relativeProductBuildDir("DynamicLibraryA")).absoluteFilePath(); QCOMPARE(m_qbsStdout.count((linkFlag + libDir).toUtf8()), 1); } void TestBlackbox::rttiChangeTracking() { QDir::setCurrent(testDataDir + "/rtti-change-tracking"); // Check toolchain QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); const bool isGcc = m_qbsStdout.contains("is gcc"); const bool isNotGcc = m_qbsStdout.contains("is not gcc"); QCOMPARE(isGcc, !isNotGcc); if (isNotGcc) QSKIP("Test only applies with gcc-like toolchains"); QbsRunParameters buildParams; buildParams.arguments << "--command-echo-mode" << "command-line"; // Do not set rtti manually. This means "use compiler default", so the flag should not appear // on the command line. QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2( !m_qbsStdout.contains("-frtti") && !m_qbsStdout.contains("-fno-rtti"), m_qbsStdout.constData()); // Switch rtti off. The respective flag should appear. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"modules.cpp.enableRtti:false"})), 0); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("-fno-rtti"), m_qbsStdout.constData()); // Now build without setting the property again. // The command line should be the same as on the initial run. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2( !m_qbsStdout.contains("-frtti") && !m_qbsStdout.contains("-fno-rtti"), m_qbsStdout.constData()); } void TestBlackbox::ruleConditions_data() { QTest::addColumn("enableGroup"); QTest::addColumn("enableRule"); QTest::addColumn("enableTagger"); QTest::addColumn("fileShouldExist"); QTest::newRow("all off") << false << false << false << false; QTest::newRow("group off, rule off, tagger on") << false << false << true << false; QTest::newRow("group off, rule on, tagger off") << false << true << false << false; QTest::newRow("group off, rule on, tagger on") << false << true << true << false; QTest::newRow("group on, rule off, tagger off") << true << false << false << false; QTest::newRow("group on, rule off, tagger on") << true << false << true << false; QTest::newRow("group on, rule on, tagger off") << true << true << false << false; QTest::newRow("all on") << true << true << true << true; } void TestBlackbox::ruleConditions() { QFETCH(bool, enableGroup); QFETCH(bool, enableRule); QFETCH(bool, enableTagger); QFETCH(bool, fileShouldExist); QDir::setCurrent(testDataDir + "/ruleConditions"); rmDirR(relativeBuildDir()); static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; const QStringList args{ "modules.narfzort.enableGroup:" + b2s(enableGroup), "modules.narfzort.enableRule:" + b2s(enableRule), "modules.narfzort.enableTagger:" + b2s(enableTagger)}; QCOMPARE(runQbs(args), 0); QVERIFY(QFileInfo(relativeExecutableFilePath("ruleConditions", m_qbsStdout)).exists()); QCOMPARE( QFileInfo(relativeProductBuildDir("ruleConditions") + "/ruleConditions.foo.narf.zort") .exists(), fileShouldExist); } void TestBlackbox::ruleConnectionWithExcludedInputs() { QDir::setCurrent(testDataDir + "/rule-connection-with-excluded-inputs"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("inputs.x: 2") && m_qbsStdout.contains("inputs.y: 0"), m_qbsStdout.constData()); } void TestBlackbox::ruleCycle() { QDir::setCurrent(testDataDir + "/ruleCycle"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Cycle detected in rule dependencies")); } void TestBlackbox::ruleWithNoInputs() { QDir::setCurrent(testDataDir + "/rule-with-no-inputs"); QVERIFY2(runQbs() == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); QVERIFY2(runQbs() == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); QbsRunParameters params("resolve", QStringList() << "products.theProduct.version:1"); QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); params.command = "resolve"; params.arguments = QStringList() << "products.theProduct.version:2"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); params.command = "resolve"; params.arguments = QStringList() << "products.theProduct.version:2" << "products.theProduct.dummy:true"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); } void TestBlackbox::ruleWithNonRequiredInputs() { QDir::setCurrent(testDataDir + "/rule-with-non-required-inputs"); QbsRunParameters params("build", {"products.p.enableTagger:false"}); QCOMPARE(runQbs(params), 0); QFile outFile(relativeProductBuildDir("p") + "/output.txt"); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); QByteArray output = outFile.readAll(); QCOMPARE(output, QByteArray("()")); outFile.close(); params.command = "resolve"; params.arguments = QStringList({"products.p.enableTagger:true"}); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); output = outFile.readAll(); QCOMPARE(output, QByteArray("(a.inp,b.inp,c.inp,)")); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("generating"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("a.inp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating"), m_qbsStdout.constData()); } void TestBlackbox::runMultiplexed() { QDir::setCurrent(testDataDir + "/run-multiplexed"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params("run"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.arguments = QStringList{"-p", "app"}; QVERIFY(runQbs(params) != 0); params.expectFailure = false; params.arguments.last() = "app {\"buildVariant\":\"debug\"}"; QCOMPARE(runQbs(params), 0); params.arguments.last() = "app {\"buildVariant\":\"release\"}"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::sanitizer_data() { QTest::addColumn("sanitizer"); QTest::newRow("none") << QString(); QTest::newRow("address") << QStringLiteral("address"); QTest::newRow("undefined") << QStringLiteral("undefined"); QTest::newRow("thread") << QStringLiteral("thread"); } void TestBlackbox::sanitizer() { QFETCH(QString, sanitizer); QDir::setCurrent(testDataDir + "/sanitizer"); rmDirR(relativeBuildDir()); QbsRunParameters params("build", {"--command-echo-mode", "command-line"}); if (!sanitizer.isEmpty()) { params.arguments.append( {QStringLiteral("products.sanitizer.sanitizer:\"") + sanitizer + "\""}); } QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains(QByteArrayLiteral("Compiler does not support sanitizer"))) QSKIP("Compiler does not support the specified sanitizer"); if (!sanitizer.isEmpty()) { QVERIFY2(m_qbsStdout.contains(QByteArrayLiteral("fsanitize=") + sanitizer.toLatin1()), qPrintable(m_qbsStdout)); } else { QVERIFY2(!m_qbsStdout.contains(QByteArrayLiteral("fsanitize=")), qPrintable(m_qbsStdout)); } } void TestBlackbox::scannerItem_data() { QTest::addColumn("inProduct"); QTest::addColumn("inModule"); QTest::addColumn("enableGroup"); QTest::addColumn("successExpected"); QTest::newRow("all off") << false << false << false << false; QTest::newRow("product scanner") << true << false << false << true; QTest::newRow("module scanner, group off") << false << true << false << false; QTest::newRow("module scanner, group on") << false << true << true << true; } void TestBlackbox::scannerItem() { QFETCH(bool, inProduct); QFETCH(bool, inModule); QFETCH(bool, enableGroup); QFETCH(bool, successExpected); static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; QDir::setCurrent(testDataDir + "/scanner-item"); rmDirR(relativeBuildDir()); const QbsRunParameters params( {"-f", "scanner-item.qbs", "products.scanner-item.productScanner:" + b2s(inProduct), "products.scanner-item.moduleScanner:" + b2s(inModule), "products.scanner-item.enableGroup:" + b2s(enableGroup)}); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("handling file1.in"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir1/file.inc"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.contains("handling file1.in"), successExpected); QVERIFY2(!m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir2/file.inc"); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("handling file1.in"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("handling file2.in"), successExpected); } void TestBlackbox::scannerChangeTracking() { QDir::setCurrent(testDataDir + "/scanner-change-tracking"); // Initial run: No matching inputs, so main.cpp has no dependencies. QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("dep1.txt"); touch("dep2.txt"); touch("subdir/dep3.txt"); touch("dep4.txt"); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); touch("helper.cpp"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); // Now fix the input tags. dep1.txt and helper.cpp should become dependencies now. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("scanner-change-tracking.qbs", "inputs: 'none'", "inputs: 'cpp'"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep2.txt"); touch("subdir/dep3.txt"); touch("dep4.txt"); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Make the scanner recursive. This should discover dep4.txt. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("scanner-change-tracking.qbs", "recursive: false", "recursive: true"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep2.txt"); WAIT_FOR_NEW_TIMESTAMP(); touch("dep4.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); touch("subdir/dep3.txt"); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Extend the search path. This should discover dep3.txt. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE( "scanner-change-tracking.qbs", "return [product.sourceDirectory]", "return [product.sourceDirectory, product.sourceDirectory + '/subdir']"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep2.txt"); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Do a dummy change in the scan script. This should invalidate the scan result, // but not rebuild the cpp file, because the new scan result is the same as the old one. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("scanner-change-tracking.qbs", "scan: {", "scan: { "); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Invalidating 1 dependency scanner(s)"), m_qbsStdout.constData()); QEXPECT_FAIL(nullptr, "Re-scanning currently implies re-building.", Continue); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Change the helper script. This should trigger re-building, because a new dependency // is added there. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("subdir/helper.js", "/*'dep2.txt'*/", "'dep2.txt'"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep2.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Discover dep5 via a product property. Qbs should notice that the property value // was read during the previous run of the scan script and that it had a different value then. QbsRunParameters params; params.command = "resolve"; params.arguments << "products.app.discoverDep5:true"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep5.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep6.txt"); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Discover dep6 via a module property. params.arguments << "modules.m.discoverDep6:true"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep6.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Discover dep7 via a module property. The difference to the case above is that // this one is read via an artifact, not via a product. params.arguments << "modules.m.discoverDep7:true"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep7.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); // Now disable the scanner and verify that changes to the former dependencies do not // trigger a re-build anymore. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("scanner-change-tracking.qbs", "condition: true", "condition: false"); QCOMPARE(runQbs(), 0); QEXPECT_FAIL( nullptr, "Conceptually, losing dependencies should not necessitate a re-build.", Continue); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("dep1.txt"); touch("dep2.txt"); touch("subdir/dep3.txt"); touch("dep4.txt"); touch("dep5.txt"); touch("dep6.txt"); touch("dep7.txt"); touch("helper.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::scanResultInOtherProduct() { QDir::setCurrent(testDataDir + "/scan-result-in-other-product"); QCOMPARE(runQbs(QStringList("-vv")), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStderr.contains("The file dependency might get lost during change tracking"), m_qbsStderr.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("lib/lib.h"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); } void TestBlackbox::scanResultInNonDependency() { QDir::setCurrent(testDataDir + "/scan-result-in-non-dependency"); QCOMPARE(runQbs(QStringList("-vv")), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); QVERIFY2(m_qbsStderr.contains("The file dependency might get lost during change tracking"), m_qbsStderr.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("lib/lib.h"); QCOMPARE(runQbs(), 0); QEXPECT_FAIL("", "QBS-1532", Continue); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); } void TestBlackbox::setupBuildEnvironment() { QDir::setCurrent(testDataDir + "/setup-build-environment"); QCOMPARE(runQbs(), 0); QFile f(relativeProductBuildDir("first_product") + QLatin1String("/m.output")); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll().trimmed(), QByteArray("1")); f.close(); f.setFileName(relativeProductBuildDir("second_product") + QLatin1String("/m.output")); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll().trimmed(), QByteArray()); } void TestBlackbox::setupRunEnvironment() { QDir::setCurrent(testDataDir + "/setup-run-environment"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QString appFilePath = QDir::currentPath() + "/dryrun/" + relativeExecutableFilePath("app", m_qbsStdout); QbsRunParameters failParams("run", QStringList({"--setup-run-env-config", "ignore-lib-dependencies"})); failParams.expectFailure = true; failParams.expectCrash = m_qbsStdout.contains("is windows"); QVERIFY(runQbs(QbsRunParameters(failParams)) != 0); QVERIFY2(failParams.expectCrash || m_qbsStderr.contains("lib"), m_qbsStderr.constData()); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QbsRunParameters dryRunParams("run", QStringList("--dry-run")); dryRunParams.buildDirectory = "dryrun"; QCOMPARE(runQbs(dryRunParams), 0); QVERIFY2(m_qbsStdout.contains("Would start target") && m_qbsStdout.contains(QDir::toNativeSeparators(appFilePath).toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::staticLibDeps() { QFETCH(bool, withExport); QFETCH(bool, importPrivateLibraries); QFETCH(bool, successExpected); QDir::setCurrent(testDataDir + "/static-lib-deps"); rmDirR(relativeBuildDir()); QStringList args{ QStringLiteral("project.useExport:%1").arg(withExport ? "true" : "false"), QStringLiteral("modules.cpp.importPrivateLibraries:%1") .arg(importPrivateLibraries ? "true" : "false")}; QbsRunParameters params(args); params.expectFailure = !successExpected; QCOMPARE(runQbs(params) == 0, successExpected); } void TestBlackbox::staticLibDeps_data() { QTest::addColumn("withExport"); QTest::addColumn("importPrivateLibraries"); QTest::addColumn("successExpected"); QTest::newRow("no Export, with import") << false << true << true; QTest::newRow("no Export, no import") << false << false << false; QTest::newRow("with Export, with import") << true << true << true; QTest::newRow("with Export, no import") << true << false << true; } void TestBlackbox::objectLibDeps() { QFETCH(bool, withExport); QFETCH(bool, importPrivateLibraries); QFETCH(bool, successExpected); QDir::setCurrent(testDataDir + "/object-lib-deps"); rmDirR(relativeBuildDir()); QStringList args{ QStringLiteral("project.useExport:%1").arg(withExport ? "true" : "false"), QStringLiteral("modules.cpp.importPrivateLibraries:%1") .arg(importPrivateLibraries ? "true" : "false")}; QbsRunParameters params(args); params.expectFailure = !successExpected; QCOMPARE(runQbs(params) == 0, successExpected); } void TestBlackbox::objectLibDeps_data() { return staticLibDeps_data(); } void TestBlackbox::rpathLink() { QDir::setCurrent(testDataDir + "/rpath-link"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); const bool isUnixGcc = m_qbsStdout.contains("is gcc on unix: true"); const bool isNotUnixGcc = m_qbsStdout.contains("is gcc on unix: false"); QCOMPARE(isUnixGcc, !isNotUnixGcc); if (isNotUnixGcc) QSKIP("only applies with gcc on unix systems"); // First build and install the libs QCOMPARE(runQbs(), 0); // Now that the libs are installed, resolve with consumer. QCOMPARE(runQbs(QbsRunParameters("resolve", {"project.enableConsumer:true"})), 0); // Building should fail initially, as the indirect dependency's location is not specified. QbsRunParameters failParams; failParams.expectFailure = true; QVERIFY(runQbs(failParams) != 0); QVERIFY2(m_qbsStderr.contains("needed by"), m_qbsStderr.constData()); // Now add the rpath-link and expect success. QCOMPARE( runQbs(QbsRunParameters( "resolve", {"project.enableConsumer:true", "project.enableRPathLink:true"})), 0); QCOMPARE(runQbs(), 0); } void TestBlackbox::smartRelinking() { QDir::setCurrent(testDataDir + "/smart-relinking"); rmDirR(relativeBuildDir()); QFETCH(bool, strictChecking); QbsRunParameters params(QStringList() << (QString("modules.cpp.exportedSymbolsCheckMode:%1") .arg(strictChecking ? "strict" : "ignore-undefined"))); QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("project disabled")) QSKIP("Test does not apply on this target"); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Irrelevant change. WAIT_FOR_NEW_TIMESTAMP(); touch("lib.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new private symbol. WAIT_FOR_NEW_TIMESTAMP(); params.command = "resolve"; params.arguments << "products.lib.defines:PRIV2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove private symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new public symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments << "products.lib.defines:PUB2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove public symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new undefined symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments << "products.lib.defines:PRINTF"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(strictChecking == m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove undefined symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(strictChecking == m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); } void TestBlackbox::smartRelinking_data() { QTest::addColumn("strictChecking"); QTest::newRow("strict checking") << true; QTest::newRow("ignore undefined") << false; } static QString soName(const QString &readElfPath, const QString &libFilePath) { QProcess readElf; auto env = QProcessEnvironment::systemEnvironment(); env.insert(QStringLiteral("LC_ALL"), QStringLiteral("C")); // force readelf to use US encoding readElf.setProcessEnvironment(env); readElf.start(readElfPath, QStringList() << "-a" << libFilePath); if (!readElf.waitForStarted() || !readElf.waitForFinished() || readElf.exitCode() != 0) { qDebug() << readElf.errorString() << readElf.readAllStandardError(); return {}; } const QByteArray output = readElf.readAllStandardOutput(); const QByteArray magicString = "Library soname: ["; const int magicStringIndex = output.indexOf(magicString); if (magicStringIndex == -1) return {}; const int endIndex = output.indexOf(']', magicStringIndex); if (endIndex == -1) return {}; const int nameIndex = magicStringIndex + magicString.size(); const QByteArray theName = output.mid(nameIndex, endIndex - nameIndex); return QString::fromLatin1(theName); } void TestBlackbox::soVersion() { const QString readElfPath = findExecutable(QStringList("readelf")); if (readElfPath.isEmpty() || readElfPath.endsWith("exe")) QSKIP("soversion test not applicable on this system"); QDir::setCurrent(testDataDir + "/soversion"); QFETCH(QString, soVersion); QFETCH(bool, useVersion); QFETCH(QString, expectedSoName); QbsRunParameters params; params.arguments << ("products.mylib.useVersion:" + QString((useVersion ? "true" : "false"))); if (!soVersion.isNull()) params.arguments << ("modules.cpp.soVersion:" + soVersion); const QString libFilePath = relativeProductBuildDir("mylib") + "/libmylib.so" + (useVersion ? ".1.2.3" : QString()); rmDirR(relativeBuildDir()); const bool success = runQbs(params) == 0; QVERIFY(success); QVERIFY2(regularFileExists(libFilePath), qPrintable(libFilePath)); if (m_qbsStdout.contains("is emscripten: true")) QEXPECT_FAIL(nullptr, "Emscripten does not produce dynamic libraries of elf format", Abort); QCOMPARE(soName(readElfPath, libFilePath), expectedSoName); } void TestBlackbox::soVersion_data() { QTest::addColumn("soVersion"); QTest::addColumn("useVersion"); QTest::addColumn("expectedSoName"); QTest::newRow("default") << QString() << true << QString("libmylib.so.1"); QTest::newRow("explicit soVersion") << QString("1.2") << true << QString("libmylib.so.1.2"); QTest::newRow("empty soVersion") << QString("") << true << QString("libmylib.so.1.2.3"); QTest::newRow("no version, explicit soVersion") << QString("5") << false << QString("libmylib.so.5"); QTest::newRow("no version, default soVersion") << QString() << false << QString("libmylib.so"); QTest::newRow("no version, empty soVersion") << QString("") << false << QString("libmylib.so"); } void TestBlackbox::sourceArtifactChanges() { QDir::setCurrent(testDataDir + "/source-artifact-changes"); bool useCustomFileTags = false; bool overrideFileTags = true; bool filesAreTargets = false; bool useCxx11 = false; static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; const auto resolveParams = [&useCustomFileTags, &overrideFileTags, &filesAreTargets, &useCxx11] { return QbsRunParameters("resolve", QStringList{ "modules.module_with_files.overrideTags:" + b2s(overrideFileTags), "modules.module_with_files.filesAreTargets:" + b2s(filesAreTargets), "modules.module_with_files.fileTags:" + QString(useCustomFileTags ? "custom" : "cpp"), "modules.cpp.cxxLanguageVersion:" + QString(useCxx11 ? "c++11" : "c++98") }); }; #define VERIFY_COMPILATION(expected) \ do { \ QVERIFY2(m_qbsStdout.contains("compiling main.cpp") == expected, m_qbsStdout.constData()); \ QVERIFY2(QFile::exists(appFilePath) == expected, qPrintable(appFilePath)); \ if (expected) \ QVERIFY2(m_qbsStdout.contains("cpp artifacts: 1"), m_qbsStdout.constData()); \ else \ QVERIFY2(m_qbsStdout.contains("cpp artifacts: 0"), m_qbsStdout.constData()); \ } while (false) // Initial build. QCOMPARE(runQbs(resolveParams()), 0); QVERIFY2(m_qbsStdout.contains("is gcc: "), m_qbsStdout.constData()); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const QString appFilePath = QDir::currentPath() + '/' + relativeExecutableFilePath("app", m_qbsStdout); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Overwrite the file tags. Now the source file is no longer tagged "cpp" and nothing // should get built. WAIT_FOR_NEW_TIMESTAMP(); touch("modules/module_with_files/main.cpp"); useCustomFileTags = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(false); // Now the custom file tag exists in addition to "cpp", and the app should get built again. overrideFileTags = false; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Mark the cpp file as a module target. Now it will no longer be considered an input // by the compiler rule, and nothing should get built. WAIT_FOR_NEW_TIMESTAMP(); touch("modules/module_with_files/main.cpp"); filesAreTargets = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(false); // Now just revert the last change. filesAreTargets = false; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Change a relevant cpp property. A rebuild is expected. useCxx11 = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line"})), 0); if (isGcc) { QVERIFY2(m_qbsStdout.contains("-std=c++11") || m_qbsStdout.contains("-std=c++0x"), m_qbsStdout.constData()); } #undef VERIFY_COMPILATION } void TestBlackbox::overrideProjectProperties() { QDir::setCurrent(testDataDir + "/overrideProjectProperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("overrideProjectProperties.qbs") << QStringLiteral("project.nameSuffix:ForYou") << QStringLiteral("project.someBool:false") << QStringLiteral("project.someInt:156") << QStringLiteral("project.someStringList:one") << QStringLiteral("products.MyAppForYou.mainFile:main.cpp"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("MyAppForYou", m_qbsStdout))); QVERIFY(QFile::remove(relativeBuildGraphFilePath())); QbsRunParameters params; params.arguments << QStringLiteral("-f") << QStringLiteral("project_using_helper_lib.qbs"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); rmDirR(relativeBuildDir()); params.arguments = QStringList() << QStringLiteral("-f") << QStringLiteral("project_using_helper_lib.qbs") << QStringLiteral("project.linkSuccessfully:true"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::partiallyBuiltDependency_data() { QTest::addColumn("mode"); QTest::addColumn("expectBuilding"); QTest::newRow("default") << QByteArray("default") << true; QTest::newRow("minimal") << QByteArray("minimal") << false; QTest::newRow("full") << QByteArray("full") << true; } void TestBlackbox::partiallyBuiltDependency() { QFETCH(QByteArray, mode); QFETCH(bool, expectBuilding); QDir::setCurrent(testDataDir + "/partially-built-dependency"); rmDirR(relativeBuildDir()); QbsRunParameters params({"-p", "p"}); if (mode == "minimal") params.arguments << "project.minimalDependency:true"; else if (mode == "full") params.arguments << "project.minimalDependency:false"; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.count("generating main.cpp"), 1); QCOMPARE(m_qbsStdout.count("copying main.cpp"), 1); QCOMPARE(m_qbsStdout.count("compiling main.cpp"), expectBuilding ? 2 : 1); QVERIFY2(m_qbsStdout.contains("linking") == expectBuilding, m_qbsStdout.constData()); } void TestBlackbox::pathProbe_data() { QTest::addColumn("projectFile"); QTest::addColumn("successExpected"); QTest::newRow("non-existent") << QString("non-existent.qbs") << false; QTest::newRow("non-existent-selector.qbs") << QString("non-existent-selector.qbs") << false; QTest::newRow("single-file") << QString("single-file.qbs") << true; QTest::newRow("single-file-selector") << QString("single-file-selector.qbs") << true; QTest::newRow("single-file-selector-array") << QString("single-file-selector-array.qbs") << true; QTest::newRow("single-file-mult-variants") << QString("single-file-mult-variants.qbs") << true; QTest::newRow("mult-files") << QString("mult-files.qbs") << true; QTest::newRow("mult-files-mult-variants") << QString("mult-files-mult-variants.qbs") << true; QTest::newRow("single-file-suffixes") << QString("single-file-suffixes.qbs") << true; QTest::newRow("mult-files-suffixes") << QString("mult-files-suffixes.qbs") << true; QTest::newRow("mult-files-common-suffixes") << QString("mult-files-common-suffixes.qbs") << true; QTest::newRow("mult-files-mult-suffixes") << QString("mult-files-mult-suffixes.qbs") << true; QTest::newRow("name-filter") << QString("name-filter.qbs") << true; QTest::newRow("candidate-filter") << QString("candidate-filter.qbs") << true; QTest::newRow("environment-paths") << QString("environment-paths.qbs") << true; } void TestBlackbox::pathProbe() { QDir::setCurrent(testDataDir + "/path-probe"); QFETCH(QString, projectFile); QFETCH(bool, successExpected); rmDirR(relativeBuildDir()); QbsRunParameters buildParams("build", QStringList{"-f", projectFile}); buildParams.expectFailure = !successExpected; buildParams.environment.insert("SEARCH_PATH", "usr/bin"); QCOMPARE(runQbs(buildParams) == 0, successExpected); if (!successExpected) QVERIFY2(m_qbsStderr.contains("Probe failed to find files"), m_qbsStderr); } void TestBlackbox::pathListInProbe() { QDir::setCurrent(testDataDir + "/path-list-in-probe"); QCOMPARE(runQbs(), 0); } void TestBlackbox::pchChangeTracking() { QDir::setCurrent(testDataDir + "/pch-change-tracking"); bool success = runQbs() == 0; if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); WAIT_FOR_NEW_TIMESTAMP(); touch("header1.h"); success = runQbs() == 0; if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); QVERIFY(m_qbsStdout.contains("compiling header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("header2.h"); success = runQbs() == 0; if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY(success); QVERIFY2(!m_qbsStdout.contains("precompiling pch.h (cpp)"), m_qbsStdout.constData()); } void TestBlackbox::perGroupDefineInExportItem() { QDir::setCurrent(testDataDir + "/per-group-define-in-export-item"); QCOMPARE(runQbs(), 0); } void TestBlackbox::pkgConfigProbe() { const QString exe = findExecutable(QStringList() << "pkg-config"); if (exe.isEmpty()) QSKIP("This test requires the pkg-config tool"); QDir::setCurrent(testDataDir + "/pkg-config-probe"); QFETCH(QString, packageBaseName); QFETCH(QStringList, found); QFETCH(QStringList, libs); QFETCH(QStringList, cflags); QFETCH(QStringList, version); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << ("project.packageBaseName:" + packageBaseName)); QCOMPARE(runQbs(params), 0); const QString stdOut = m_qbsStdout; QVERIFY2(stdOut.contains("theProduct1 found: " + found.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 found: " + found.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 libs: " + libs.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 libs: " + libs.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 cflags: " + cflags.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 cflags: " + cflags.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 version: " + version.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 version: " + version.at(1)), m_qbsStdout.constData()); } void TestBlackbox::pkgConfigProbe_data() { QTest::addColumn("packageBaseName"); QTest::addColumn("found"); QTest::addColumn("libs"); QTest::addColumn("cflags"); QTest::addColumn("version"); QTest::newRow("existing package") << "dummy" << (QStringList() << "true" << "true") << (QStringList() << "[\"-Ldummydir1\",\"-ldummy1\"]" << "[\"-Ldummydir2\",\"-ldummy2\"]") << (QStringList() << "[]" << "[]") << (QStringList() << "0.0.1" << "0.0.2"); // Note: The array values should be "undefined", but we lose that information when // converting to QVariants in the ProjectResolver. QTest::newRow("non-existing package") << "blubb" << (QStringList() << "false" << "false") << (QStringList() << "[]" << "[]") << (QStringList() << "[]" << "[]") << (QStringList() << "undefined" << "undefined"); } void TestBlackbox::pkgConfigProbeSysroot() { const QString exe = findExecutable(QStringList() << "pkg-config"); if (exe.isEmpty()) QSKIP("This test requires the pkg-config tool"); QDir::setCurrent(testDataDir + "/pkg-config-probe-sysroot"); QCOMPARE(runQbs(QStringList("-v")), 0); QCOMPARE(m_qbsStderr.count("PkgConfigProbe: found packages"), 2); const QString outputTemplate = "theProduct%1 libs: [\"-L%2/usr/dummy\",\"-ldummy1\"]"; QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("1", QDir::currentPath() + "/sysroot1").toLocal8Bit()), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("2", QDir::currentPath() + "/sysroot2").toLocal8Bit()), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("3", QDir::currentPath() + "/sysroot1").toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::pluginDependency() { QDir::setCurrent(testDataDir + "/plugin-dependency"); // Build the plugins and the helper2 lib. QCOMPARE(runQbs(QStringList{"--products", "plugin1,plugin2,plugin3,plugin4,helper2"}), 0); QVERIFY(m_qbsStdout.contains("plugin1")); QVERIFY(m_qbsStdout.contains("plugin2")); QVERIFY(m_qbsStdout.contains("plugin3")); QVERIFY(m_qbsStdout.contains("plugin4")); QVERIFY(m_qbsStdout.contains("helper2")); QVERIFY(!m_qbsStderr.contains("SOFT ASSERT")); // Build the app. Plugins 1 and 2 must not be linked. Plugin 3 must be linked. QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); QByteArray output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY(!output.contains("plugin1")); QVERIFY(!output.contains("plugin2")); QVERIFY(!output.contains("helper2")); // Test change tracking for parameter in Parameters item. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("plugin-dependency.qbs", "false // marker 1", "true"); QCOMPARE(runQbs(QStringList{"-p", "plugin2"}), 0); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY2(!output.contains("plugin1"), output.constData()); QVERIFY2(!output.contains("helper2"), output.constData()); QVERIFY2(output.contains("plugin2"), output.constData()); // Test change tracking for parameter in Depends item. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("plugin-dependency.qbs", "false /* marker 2 */", "true"); QCOMPARE(runQbs(QStringList{"-p", "helper1", "--command-echo-mode", "command-line"}), 0); output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY2(output.contains("helper2"), output.constData()); // Check that the build dependency still works. QCOMPARE(runQbs(QStringLiteral("clean")), 0); QCOMPARE(runQbs(QStringList{"--products", "myapp", "--command-echo-mode", "command-line"}), 0); QVERIFY(m_qbsStdout.contains("plugin1")); QVERIFY(m_qbsStdout.contains("plugin2")); QVERIFY(m_qbsStdout.contains("plugin3")); QVERIFY(m_qbsStdout.contains("plugin4")); } void TestBlackbox::precompiledAndPrefixHeaders() { QDir::setCurrent(testDataDir + "/precompiled-and-prefix-headers"); const bool success = runQbs() == 0; if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY(success); } void TestBlackbox::precompiledHeaderAndRedefine() { QDir::setCurrent(testDataDir + "/precompiled-headers-and-redefine"); const bool success = runQbs() == 0; if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY(success); } void TestBlackbox::preventFloatingPointValues() { QDir::setCurrent(testDataDir + "/prevent-floating-point-values"); QCOMPARE(runQbs(QStringList("products.p.version:1.50")), 0); QVERIFY2(m_qbsStdout.contains("version: 1.50"), m_qbsStdout.constData()); } void TestBlackbox::probeChangeTracking() { QDir::setCurrent(testDataDir + "/probe-change-tracking"); // Product probe disabled, other probes enabled. QbsRunParameters params; params.command = "resolve"; params.arguments = QStringList("products.theProduct.runProbe:false"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Product probe newly enabled. params.arguments = QStringList("products.theProduct.runProbe:true"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with unchanged probe. WAIT_FOR_NEW_TIMESTAMP(); touch("probe-change-tracking.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Re-resolving with changed configure scripts. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "console.info", " console.info"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with added property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "condition: product.runProbe", "condition: product.runProbe\nproperty string something: 'x'"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with changed property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "'x'", "'y'"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with removed property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "property string something: 'y'", ""); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with unchanged probe again. WAIT_FOR_NEW_TIMESTAMP(); touch("probe-change-tracking.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Enforcing re-running via command-line option. params.arguments.prepend("--force-probe-execution"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); } void TestBlackbox::probeProperties() { QDir::setCurrent(testDataDir + "/probeProperties"); const QByteArray dir = QDir::cleanPath(testDataDir).toLocal8Bit() + "/probeProperties"; QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("probe1.fileName=bin/tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe1.path=" + dir), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe1.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.fileName=tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.path=" + dir + "/bin"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe3.fileName=tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe3.path=" + dir + "/bin"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe3.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); } void TestBlackbox::probesAndShadowProducts() { QDir::setCurrent(testDataDir + "/probes-and-shadow-products"); QCOMPARE(runQbs(QStringList("--log-time")), 0); QVERIFY2(m_qbsStdout.contains("2 probes encountered, 1 configure scripts executed"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("probes-and-shadow-products.qbs"); QCOMPARE(runQbs(QStringList("--log-time")), 0); QVERIFY2(m_qbsStdout.contains("2 probes encountered, 0 configure scripts executed"), m_qbsStdout.constData()); } void TestBlackbox::probeInExportedModule() { QDir::setCurrent(testDataDir + "/probe-in-exported-module"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("probe-in-exported-module.qbs"))), 0); QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("listProp: myother,my"), m_qbsStdout.constData()); } void TestBlackbox::probesAndArrayProperties() { QDir::setCurrent(testDataDir + "/probes-and-array-properties"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("prop: [\"probe\"]"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probes-and-array-properties.qbs", "//", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("prop: [\"product\",\"probe\"]"), m_qbsStdout.constData()); } void TestBlackbox::productProperties() { QDir::setCurrent(testDataDir + "/productproperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("productproperties.qbs"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("blubb_user", m_qbsStdout))); } void TestBlackbox::propertyAssignmentInFailedModule() { QDir::setCurrent(testDataDir + "/property-assignment-in-failed-module"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:false"))), 0); QbsRunParameters failParams; failParams.expectFailure = true; QVERIFY(runQbs(failParams) != 0); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:true"))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); failParams.expectFailure = false; QCOMPARE(runQbs(failParams), 0); } void TestBlackbox::propertyChanges() { QDir::setCurrent(testDataDir + "/propertyChanges"); const QString projectFile("propertyChanges.qbs"); QbsRunParameters params(QStringList({"-f", "propertyChanges.qbs", "qbs.enableDebugCode:true"})); // Initial build. QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("making output from input")); QVERIFY(m_qbsStdout.contains("default value")); QVERIFY(m_qbsStdout.contains("making output from other output")); QFile generatedFile(relativeProductBuildDir("generated text file") + "/generated.txt"); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 1suffix 1")); generatedFile.close(); // Incremental build with no changes. QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build with no changes, but updated project file timestamp. WAIT_FOR_NEW_TIMESTAMP(); touch(projectFile); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed for first product WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "blubb1", "blubb01"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via project for second product. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "blubb2", "blubb02"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via command line for second product. params.command = "resolve"; params.arguments << "project.projectDefines:blubb002"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via environment for third product. params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.environment.remove("QBS_BLACKBOX_DEFINE"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.environment.remove("QBS_BLACKBOX_DEFINE"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, module property changed via command line. params.arguments << "qbs.enableDebugCode:false"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.release")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, non-essential dependency removed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "Depends { name: 'library' }", "// Depends { name: 'library' }"); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, prepare script of a transformer changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "contents 1", "contents 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 2suffix 1")); generatedFile.close(); // Incremental build, product property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "prefix 1", "prefix 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 1")); generatedFile.close(); // Incremental build, project property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "suffix 1", "suffix 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("making output from input")); QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 2")); generatedFile.close(); // Incremental build, module property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "default value", "new value"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("making output from input")); QVERIFY(m_qbsStdout.contains("making output from other output")); QVERIFY(m_qbsStdout.contains("new value")); // Incremental build, prepare script of a rule in a module changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("modules/TestModule/module.qbs", "// console.info('Change in source code')", "console.info('Change in source code')"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("making output from input")); QVERIFY(m_qbsStdout.contains("making output from other output")); } void TestBlackbox::propertyEvaluationContext() { const QString testDir = testDataDir + "/property-evaluation-context"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("base.productInBase evaluated in: myapp"), 1); QCOMPARE(m_qbsStdout.count("base.productInTop evaluated in: myapp"), 1); QCOMPARE(m_qbsStdout.count("top.productInExport evaluated in: mylib"), 1); QCOMPARE(m_qbsStdout.count("top.productInTop evaluated in: myapp"), 1); } void TestBlackbox::qtBug51237() { const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile profile("qbs_autotests_qtBug51237", s.get()); profile.p.setValue("mymodule.theProperty", QStringList()); s->sync(); QDir::setCurrent(testDataDir + "/QTBUG-51237"); QbsRunParameters params; params.profile = profile.p.name(); QCOMPARE(runQbs(params), 0); } void TestBlackbox::dynamicMultiplexRule() { const QString testDir = testDataDir + "/dynamicMultiplexRule"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); const QString outputFilePath = relativeProductBuildDir("dynamicMultiplexRule") + "/stuff-from-3-inputs"; QVERIFY(regularFileExists(outputFilePath)); WAIT_FOR_NEW_TIMESTAMP(); touch("two.txt"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(outputFilePath)); } void TestBlackbox::dynamicProject() { const QString testDir = testDataDir + "/dynamic-project"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("compiling main.cpp"), 2); } void TestBlackbox::dynamicRuleOutputs() { const QString testDir = testDataDir + "/dynamicRuleOutputs"; QDir::setCurrent(testDir); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDir + "/work"); QCOMPARE(runQbs(), 0); const QString appFile = relativeExecutableFilePath("genlexer", m_qbsStdout); const QString headerFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.h"; const QString sourceFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.c"; const QString sourceFile2 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/lex.yy.c"; // Check build #1: source and header file name are specified in numbers.l QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); QDateTime appFileTimeStamp1 = QFileInfo(appFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../after/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #2: no file names are specified in numbers.l // flex will default to lex.yy.c without header file. QDateTime appFileTimeStamp2 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp1 < appFileTimeStamp2); QVERIFY(!QFile::exists(headerFile1)); QVERIFY(!QFile::exists(sourceFile1)); QVERIFY(regularFileExists(sourceFile2)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../before/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #3: source and header file name are specified in numbers.l QDateTime appFileTimeStamp3 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp2 < appFileTimeStamp3); QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); } void TestBlackbox::emptyProfile() { QDir::setCurrent(testDataDir + "/empty-profile"); const SettingsPtr s = settings(); const qbs::Profile buildProfile(profileName(), s.get()); bool isMsvc = false; auto toolchainType = buildProfile.value(QStringLiteral("qbs.toolchainType")).toString(); QbsRunParameters params; params.profile = "none"; if (toolchainType.isEmpty()) { const auto toolchain = buildProfile.value(QStringLiteral("qbs.toolchain")).toStringList(); if (!toolchain.isEmpty()) toolchainType = toolchain.first(); } if (!toolchainType.isEmpty()) { params.arguments = QStringList{QStringLiteral("qbs.toolchainType:") + toolchainType}; isMsvc = toolchainType == "msvc" || toolchainType == "clang-cl"; } if (!isMsvc) { const auto tcPath = QDir::toNativeSeparators( buildProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString()); auto paths = params.environment.value(QStringLiteral("PATH")) .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); if (!tcPath.isEmpty() && !paths.contains(tcPath)) { paths.prepend(tcPath); params.environment.insert( QStringLiteral("PATH"), paths.join(HostOsInfo::pathListSeparator())); } } QCOMPARE(runQbs(params), 0); } using ASet = QSet; namespace { QString JS() { static const auto suffix = QStringLiteral(".js"); return suffix; } QString WASM() { static const auto suffix = QStringLiteral(".wasm"); return suffix; } QString WASMJS() { static const auto suffix = QStringLiteral(".wasm.js"); return suffix; } QString HTML() { static const auto suffix = QStringLiteral(".html"); return suffix; } } // namespace void TestBlackbox::emscriptenArtifacts() { QDir::setCurrent(testDataDir + "/emscripten-artifacts"); QFETCH(QString, executableSuffix); QFETCH(QString, wasmOption); QFETCH(int, buildresult); QFETCH(ASet, suffixes); const QStringList params = { QStringLiteral("modules.cpp.executableSuffix:%1").arg(executableSuffix), QStringLiteral("modules.cpp.driverLinkerFlags:%1").arg(wasmOption)}; ASet possibleSuffixes = {JS(), WASM(), WASMJS(), HTML()}; QbsRunParameters qbsParams("resolve", params); int result = runQbs(qbsParams); QCOMPARE(result, 0); if (m_qbsStdout.contains("is emscripten: false")) QSKIP("Skipping emscripten test"); QVERIFY(m_qbsStdout.contains("is emscripten: true")); result = runQbs(QbsRunParameters("build", params)); QCOMPARE(result, buildresult); if (result == 0) { const auto app = QStringLiteral("app"); const auto appWithoutSuffix = relativeProductBuildDir(app) + QLatin1Char('/') + app; ASet usedSuffixes; for (const auto &suffix : suffixes) { usedSuffixes.insert(suffix); QVERIFY(regularFileExists(appWithoutSuffix + suffix)); } possibleSuffixes.subtract(usedSuffixes); for (const auto &unusedSuffix : possibleSuffixes) { QVERIFY(!regularFileExists(appWithoutSuffix + unusedSuffix)); } } QCOMPARE(runQbs(QbsRunParameters("clean")), 0); } void TestBlackbox::emscriptenArtifacts_data() { QTest::addColumn("executableSuffix"); QTest::addColumn("wasmOption"); QTest::addColumn("buildresult"); QTest::addColumn("suffixes"); QTest::newRow(".js WASM=0") << ".js" << "-sWASM=0" << 0 << ASet{JS()}; QTest::newRow(".js WASM=1") << ".js" << "-sWASM=1" << 0 << ASet{JS(), WASM()}; QTest::newRow(".js WASM=2") << ".js" << "-sWASM=2" << 0 << ASet{JS(), WASM(), WASMJS()}; QTest::newRow(".js WASM=779") << ".js" << "-sWASM=779" << 0 << ASet{JS(), WASM()}; QTest::newRow(".wasm WASM=0") << ".wasm" << "-sWASM=0" << 1 << ASet{}; QTest::newRow(".wasm WASM=1") << ".wasm" << "-sWASM=1" << 0 << ASet{WASM()}; QTest::newRow(".wasm WASM=2") << ".wasm" << "-sWASM=2" << 0 << ASet{WASM(), WASMJS()}; QTest::newRow(".wasm WASM=848") << ".wasm" << "-sWASM=848" << 0 << ASet{WASM()}; QTest::newRow(".html WASM=0") << ".html" << "-sWASM=0" << 0 << ASet{JS(), HTML()}; QTest::newRow(".html WASM=1") << ".html" << "-sWASM=1" << 0 << ASet{JS(), HTML(), WASM()}; QTest::newRow(".html WASM=2") << ".html" << "-sWASM=2" << 0 << ASet{JS(), HTML(), WASM(), WASMJS()}; QTest::newRow(".html WASM=233") << ".html" << "-sWASM=233" << 0 << ASet{JS(), HTML(), WASM()}; } void TestBlackbox::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("nonexistentWorkingDir") << "The working directory '.does.not.exist' for process '.*ls.*' is invalid."; QTest::newRow("outputArtifacts-missing-filePath") << "Error in Rule\\.outputArtifacts\\[0\\]\n\r?" "Property filePath must be a non-empty string\\."; QTest::newRow("outputArtifacts-missing-fileTags") << "Error in Rule\\.outputArtifacts\\[0\\]\n\r?" "Property fileTags for artifact 'outputArtifacts-missing-fileTags\\.txt' " "must be a non-empty string list\\."; QTest::newRow("texttemplate-unknown-placeholder") << "Placeholder 'what' is not defined in textemplate.dict for 'boom.txt.in'"; QTest::newRow("tag-mismatch") << "tag-mismatch.qbs:8:18.*Artifact '.*dummy1' has undeclared file tags " "\\[\"y\",\"z\"\\]."; } void TestBlackbox::erroneousFiles() { QFETCH(QString, errorMessage); QDir::setCurrent(testDataDir + "/erroneous/" + QTest::currentDataTag()); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QString err = QString::fromLocal8Bit(m_qbsStderr); if (!err.contains(QRegularExpression(errorMessage))) { qDebug().noquote() << "Output: " << err; qDebug().noquote() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } } void TestBlackbox::errorInfo() { QDir::setCurrent(testDataDir + "/error-info"); QCOMPARE(runQbs(), 0); QbsRunParameters resolveParams; QbsRunParameters buildParams; buildParams.expectFailure = true; resolveParams.command = "resolve"; resolveParams.arguments = QStringList() << "project.fail1:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:24"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail2:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:36"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail3:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:51"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail4:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:66"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail5:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("helper.js:4"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail6:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("helper.js:8"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail7:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("JavaScriptCommand.sourceCode"), m_qbsStderr); QVERIFY2(m_qbsStderr.contains("error-info.qbs:57"), m_qbsStderr); } void TestBlackbox::escapedLinkerFlags() { QDir::setCurrent(testDataDir + "/escaped-linker-flags"); QbsRunParameters params("resolve", QStringList("products.app.escapeLinkerFlags:false")); QCOMPARE(runQbs(params), 0); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); if (isNotGcc) QSKIP("escaped linker flags test only applies on plain unix with gcc and GNU ld"); QVERIFY(isGcc); params.command = "build"; QCOMPARE(runQbs(params), 0); params.command = "resolve"; params.arguments = QStringList() << "products.app.escapeLinkerFlags:true"; QCOMPARE(runQbs(params), 0); params.command = "build"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Encountered escaped linker flag"), m_qbsStderr.constData()); } void TestBlackbox::exportedDependencyInDisabledProduct() { QDir::setCurrent(testDataDir + "/exported-dependency-in-disabled-product"); QFETCH(QString, depCondition); QFETCH(bool, compileExpected); rmDirR(relativeBuildDir()); const QString propertyArg = "products.dep.conditionString:" + depCondition; QCOMPARE(runQbs(QStringList(propertyArg)), 0); QCOMPARE(m_qbsStdout.contains("compiling"), compileExpected); } void TestBlackbox::exportedDependencyInDisabledProduct_data() { QTest::addColumn("depCondition"); QTest::addColumn("compileExpected"); QTest::newRow("dependency enabled") << "true" << true; QTest::newRow("dependency directly disabled") << "false" << false; QTest::newRow("dependency disabled via non-present module") << "nosuchmodule.present" << false; QTest::newRow("dependency disabled via failed module") << "broken.present" << false; } void TestBlackbox::exportedPropertyInDisabledProduct() { QDir::setCurrent(testDataDir + "/exported-property-in-disabled-product"); QFETCH(QString, depCondition); QFETCH(bool, successExpected); const QString propertyArg = "products.dep.conditionString:" + depCondition; QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(propertyArg))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QbsRunParameters buildParams; buildParams.expectFailure = !successExpected; QCOMPARE(runQbs(buildParams) == 0, successExpected); } void TestBlackbox::exportedPropertyInDisabledProduct_data() { QTest::addColumn("depCondition"); QTest::addColumn("successExpected"); QTest::newRow("dependency enabled") << "true" << false; QTest::newRow("dependency directly disabled") << "false" << true; QTest::newRow("dependency disabled via non-present module") << "nosuchmodule.present" << true; QTest::newRow("dependency disabled via failed module") << "broken.present" << true; } void TestBlackbox::systemRunPaths() { const QString lddFilePath = findExecutable(QStringList() << "ldd"); if (lddFilePath.isEmpty()) QSKIP("ldd not found"); QDir::setCurrent(testDataDir + "/system-run-paths"); QFETCH(bool, setRunPaths); rmDirR(relativeBuildDir()); QbsRunParameters params("resolve"); params.arguments << QString("project.setRunPaths:") + (setRunPaths ? "true" : "false"); QCOMPARE(runQbs(params), 0); const bool isUnix = m_qbsStdout.contains("is unix: true"); const bool isNotUnix = m_qbsStdout.contains("is unix: false"); if (isNotUnix) QSKIP("only applies on Unix"); QVERIFY(isUnix); const QString exe = relativeExecutableFilePath("app", m_qbsStdout); params.command = "build"; QCOMPARE(runQbs(params), 0); QProcess ldd; ldd.start(lddFilePath, QStringList() << exe); QVERIFY2(ldd.waitForStarted(), qPrintable(ldd.errorString())); QVERIFY2(ldd.waitForFinished(), qPrintable(ldd.errorString())); QVERIFY2(ldd.exitCode() == 0, ldd.readAllStandardError().constData()); const QByteArray output = ldd.readAllStandardOutput(); const QList outputLines = output.split('\n'); QByteArray libLine; for (const auto &line : outputLines) { if (line.contains("theLib")) { libLine = line; break; } } QVERIFY2(!libLine.isEmpty(), output.constData()); QVERIFY2(setRunPaths == libLine.contains("not found"), libLine.constData()); } void TestBlackbox::systemRunPaths_data() { QTest::addColumn("setRunPaths"); QTest::newRow("do not set system run paths") << false; QTest::newRow("do set system run paths") << true; } void TestBlackbox::exportRule() { QDir::setCurrent(testDataDir + "/export-rule"); QbsRunParameters params(QStringList{"modules.blubber.enableTagger:false"}); params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.command = "resolve"; params.arguments = QStringList{"modules.blubber.enableTagger:true"}; params.expectFailure = false; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("creating C++ source file"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling myapp.cpp"), m_qbsStdout.constData()); } void TestBlackbox::exportToOutsideSearchPath() { QDir::setCurrent(testDataDir + "/export-to-outside-searchpath"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Dependency 'aModule' not found for product 'theProduct'."), m_qbsStderr.constData()); } void TestBlackbox::exportsCMake() { QFETCH(QStringList, arguments); QDir::setCurrent(testDataDir + "/exports-cmake"); rmDirR(relativeBuildDir()); QbsRunParameters findCMakeParams("resolve", {"-f", "find-cmake.qbs"}); QCOMPARE(runQbs(findCMakeParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStdout); const QRegularExpression pattern( QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString jsonString = match.captured(1); const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8()); const QJsonObject jsonData = jsonDoc.object(); rmDirR(relativeBuildDir()); const QStringList exporterArgs{"-f", "exports-cmake.qbs"}; QbsRunParameters exporterRunParams("build", exporterArgs); exporterRunParams.arguments << arguments; QCOMPARE(runQbs(exporterRunParams), 0); if (!jsonData.value(u"cmakeFound").toBool()) { QSKIP("cmake is not installed"); return; } if (jsonData.value(u"crossCompiling").toBool()) { QSKIP("test is not applicable with cross-compile toolchains"); return; } const auto cmakeFilePath = jsonData.value(u"cmakeFilePath").toString(); QVERIFY(!cmakeFilePath.isEmpty()); const auto generator = jsonData.value(u"generator").toString(); if (generator.isEmpty()) { QSKIP("cannot detect cmake generator"); return; } QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); const auto buildEnv = jsonData.value(u"buildEnv").toObject(); for (auto it = buildEnv.begin(), end = buildEnv.end(); it != end; ++it) { if (it.key() == "PATH") { auto paths = it.value().toString().split(HostOsInfo::pathListSeparator()); paths.append(env.value(it.key()).split(HostOsInfo::pathListSeparator())); env.insert(it.key(), paths.join(HostOsInfo::pathListSeparator())); } else { env.insert(it.key(), it.value().toString()); } } const auto installPrefix = jsonData.value(u"installPrefix").toString(); const auto cmakePrefixPath = QFileInfo(relativeBuildDir()).absoluteFilePath() + "/install-root/" + installPrefix + "/lib/cmake"; const auto sourceDirectory = testDataDir + "/exports-cmake/cmake"; QProcess configure; configure.setProcessEnvironment(env); configure.setWorkingDirectory(sourceDirectory); configure.start( cmakeFilePath, {".", "-DCMAKE_PREFIX_PATH=" + cmakePrefixPath, "-G" + generator}); QVERIFY(waitForProcessSuccess(configure, 120000)); QProcess build; build.setProcessEnvironment(env); build.setWorkingDirectory(sourceDirectory); build.start(cmakeFilePath, QStringList{"--build", "."}); QVERIFY(waitForProcessSuccess(build)); } void TestBlackbox::exportsCMake_data() { QTest::addColumn("arguments"); QTest::newRow("dynamic lib") << QStringList("project.isStatic: false"); QTest::newRow("static lib") << QStringList("project.isStatic: true"); QTest::newRow("framework") << QStringList("project.isBundle: true"); } void TestBlackbox::exportsPkgconfig() { QDir::setCurrent(testDataDir + "/exports-pkgconfig"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("creating TheFirstLib.pc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating TheSecondLib.pc"), m_qbsStdout.constData()); QFile sourcePcFile(HostOsInfo::isWindowsHost() ? "TheFirstLib_windows.pc" : "TheFirstLib.pc"); QString generatedPcFilePath = relativeProductBuildDir("TheFirstLib") + "/TheFirstLib.pc"; QFile generatedPcFile(generatedPcFilePath); QVERIFY2(sourcePcFile.open(QIODevice::ReadOnly), qPrintable(sourcePcFile.errorString())); QVERIFY2(generatedPcFile.open(QIODevice::ReadOnly), qPrintable(generatedPcFile.errorString())); QCOMPARE(generatedPcFile.readAll().replace("\r", ""), sourcePcFile.readAll().replace("\r", "")); sourcePcFile.close(); generatedPcFile.close(); TEXT_FILE_COMPARE(relativeProductBuildDir("TheSecondLib") + "/TheSecondLib.pc", "TheSecondLib.pc"); WAIT_FOR_NEW_TIMESTAMP(); touch("firstlib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating TheFirstLib.pc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating TheSecondLib.pc"), m_qbsStdout.constData()); } void TestBlackbox::exportsQbs() { QDir::setCurrent(testDataDir + "/exports-qbs"); QCOMPARE(runQbs({"resolve", {"-f", "exports-qbs.qbs"}}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); // First we build exportable products and use them (as products) inside // the original project. QCOMPARE(runQbs(QStringList{"-f", "exports-qbs.qbs", "--command-echo-mode", "command-line"}), 0); QVERIFY2(m_qbsStdout.contains("somelocaldir"), m_qbsStdout.constData()); // Now we build an external product against the modules that were just installed. // We try debug and release mode; one module exists for each of them. QbsRunParameters paramsExternalBuild(QStringList{"-f", "consumer.qbs", "--command-echo-mode", "command-line", "modules.qbs.buildVariant:debug",}); paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-debug"; QCOMPARE(runQbs(paramsExternalBuild), 0); QVERIFY2(!m_qbsStdout.contains("somelocaldir"), m_qbsStdout.constData()); paramsExternalBuild.arguments = QStringList{"-f", "consumer.qbs", "modules.qbs.buildVariant:release"}; paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-release"; QCOMPARE(runQbs(paramsExternalBuild), 0); // Trying to build with an unsupported build variant must fail. paramsExternalBuild.arguments = QStringList{"-f", "consumer.qbs", "modules.qbs.buildVariant:profiling"}; paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-profile"; paramsExternalBuild.expectFailure = true; QVERIFY(runQbs(paramsExternalBuild) != 0); QVERIFY2(m_qbsStderr.contains("Dependency 'MyLib' not found for product 'consumer'"), m_qbsStderr.constData()); // Removing the condition from the generated module leaves us with two conflicting // candidates. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{ "-f", "exports-qbs.qbs", "modules.Exporter.qbs.additionalContent:''"})), 0); QCOMPARE(runQbs(), 0); QVERIFY(runQbs(paramsExternalBuild) != 0); QVERIFY2(m_qbsStderr.contains("There is more than one equally prioritized candidate " "for module 'MyLib'."), m_qbsStderr.constData()); // Change tracking for accesses to product.exports (negative). QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"-f", "exports-qbs.qbs"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("exports-qbs.qbs"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Rebuilding the target binary should not cause recreating the module file. WAIT_FOR_NEW_TIMESTAMP(); touch("mylib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating MyLib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Changing a setting that influences the name of a target artifact should cause // recreating the module file. const QbsRunParameters resolveParams("resolve", QStringList{"-f", "exports-qbs.qbs", "modules.cpp.dynamicLibrarySuffix:.blubb"}); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.count("creating MyLib") == 2, m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Change tracking for accesses to product.exports (positive). WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("tool.qbs", "exportingProduct.toolTags", "[]"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); QVERIFY2(m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); } void TestBlackbox::externalLibs() { QDir::setCurrent(testDataDir + "/external-libs"); QCOMPARE(runQbs(), 0); } void TestBlackbox::fileDependencies() { QDir::setCurrent(testDataDir + "/fileDependencies"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(m_qbsStdout.contains("compiling zort.cpp")); const QString productFileName = relativeExecutableFilePath("myapp", m_qbsStdout); QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); // Incremental build without changes. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling")); QVERIFY(!m_qbsStdout.contains("linking")); // Incremental build with changed file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/awesome.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); // Incremental build with changed 2nd level file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/magnificent.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); // Change the product in between to force the list of dependencies to get rescued. REPLACE_IN_FILE("fileDependencies.qbs", "//", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/magnificent.h"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("[myapp] compiling narf.cpp"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); } void TestBlackbox::fileTagsFilterMerging() { QDir::setCurrent(testDataDir + "/filetagsfilter-merging"); QCOMPARE(runQbs(QStringList{"-f", "filetagsfilter-merging.qbs"}), 0); const QString installedApp = defaultInstallRoot + "/myapp/binDir/" + QFileInfo(relativeExecutableFilePath("myapp", m_qbsStdout)).fileName(); QVERIFY2(QFile::exists(installedApp), qPrintable(installedApp)); const QString otherOutput = relativeProductBuildDir("myapp") + "/myapp.txt"; QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); } void TestBlackbox::flatbuf() { QFETCH(QString, projectFile); QDir::setCurrent(testDataDir + "/flatbuf"); rmDirR(relativeBuildDir()); if (!prepareAndRunConan()) QSKIP("conan is not prepared, check messages above"); QbsRunParameters resolveParams( "resolve", QStringList{"-f", projectFile, "moduleProviders.conan.installDirectory:build"}); QCOMPARE(runQbs(resolveParams), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const bool withFlatbuffers = m_qbsStdout.contains("has flatbuffers: true"); const bool withoutFlatbuffers = m_qbsStdout.contains("has flatbuffers: false"); QVERIFY2(withFlatbuffers || withoutFlatbuffers, m_qbsStdout.constData()); if (withoutFlatbuffers) QSKIP("flatbuf module not present"); QbsRunParameters runParams("run"); QCOMPARE(runQbs(runParams), 0); } void TestBlackbox::flatbuf_data() { QTest::addColumn("projectFile"); // QTest::newRow("c") << QString("flat_c.qbs"); QTest::newRow("cpp") << QString("flat_cpp.qbs"); QTest::newRow("relative import") << QString("flat_relative_import.qbs"); QTest::newRow("absolute import") << QString("flat_absolute_import.qbs"); QTest::newRow("filename suffix") << QString("flat_filename_suffix.qbs"); QTest::newRow("filename extension") << QString("flat_filename_extension.qbs"); QTest::newRow("keep prefix") << QString("flat_keep_prefix.qbs"); } void TestBlackbox::freedesktop() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); if (HostOsInfo::isMacosHost()) QSKIP("Does not apply on macOS"); QDir::setCurrent(testDataDir + "/freedesktop"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("is emscripten: true")) QSKIP("Irrelevant for emscripten"); QVERIFY(m_qbsStdout.contains("is emscripten: false")); // Check desktop file QString desktopFilePath = defaultInstallRoot + "/usr/local/share/applications/myapp.desktop"; QVERIFY(QFile::exists(desktopFilePath)); QFile desktopFile(desktopFilePath); QVERIFY2(desktopFile.open(QIODevice::ReadOnly), qPrintable(desktopFile.errorString())); QByteArrayList lines = desktopFile.readAll().split('\n'); // Automatically filled line: QVERIFY(lines.contains("Exec=main")); // Name specified in `freedesktop.name` property QVERIFY(lines.contains("Name=My App")); // Overridden line: QVERIFY(lines.contains("Icon=myapp.png")); // Untouched line: QVERIFY(lines.contains("Terminal=false")); // Untouched localized line: QVERIFY(lines.contains("GenericName[fr]=Éditeur d'images")); // Untouched localized line: QVERIFY(lines.contains("Comment[fr]=Créer des images et éditer des photographies")); // Check AppStream file QVERIFY(QFile::exists(defaultInstallRoot + "/usr/local/share/metainfo/myapp.appdata.xml")); // Check hicolor icon files QVERIFY( QFile::exists(defaultInstallRoot + "/usr/local/share/icons/hicolor/48x48/apps/myapp.png")); QVERIFY(QFile::exists( defaultInstallRoot + "/usr/local/share/icons/hicolor/48x48@2/apps/myapp.png")); QVERIFY( QFile::exists(defaultInstallRoot + "/usr/local/share/icons/hicolor/64x64/apps/myapp.png")); QVERIFY(QFile::exists( defaultInstallRoot + "/usr/local/share/icons/hicolor/64x64@2/apps/myapp.png")); QVERIFY(QFile::exists( defaultInstallRoot + "/usr/local/share/icons/hicolor/64x64/mimetypes/application-format.png")); QVERIFY(QFile::exists( defaultInstallRoot + "/usr/local/share/icons/hicolor/scalable/apps/myapp.png")); } void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); QCOMPARE(runQbs(), 0); const QString installedFilePath = defaultInstallRoot + "/textfiles/HelloWorld.txt"; QVERIFY2(QFile::exists(installedFilePath), qPrintable(installedFilePath)); } void TestBlackbox::installLocations_data() { QTest::addColumn("testCase"); QTest::newRow("default values") << QString("default"); QTest::newRow("explicit values, direct") << QString("direct"); QTest::newRow("explicit values, using config.install module") << QString("config"); QTest::newRow("explicit values, using installpaths module") << QString("installpaths"); } void TestBlackbox::installLocations() { QFETCH(QString, testCase); QDir::setCurrent(testDataDir + "/install-locations"); rmDirR(relativeBuildDir()); QbsRunParameters params("resolve"); QCOMPARE(runQbs(params), 0); // Extract toolchain name from console output const QString output = QString::fromLocal8Bit(m_qbsStdout); const QRegularExpression pattern( QRegularExpression::anchoredPattern(".*===toolchain:(.*)===.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString toolchain = match.captured(1); QVERIFY2(toolchain != "unknown", qPrintable(output)); if (testCase != "default") { const QString binDir = "bindir"; const QString libDir = "libdir"; const QString pluginDir = "pluginDir"; const QString dsymDir = "dsymDir"; if (testCase == "direct") { params.arguments.push_back("products.theapp.installDir:" + binDir); if (toolchain == "msvc" || toolchain == "mingw") { params.arguments.push_back("products.thelib.installDir:" + binDir); params.arguments.push_back("products.theloadablemodule.installDir:" + binDir); } else { params.arguments.push_back("products.thelib.installDir:" + libDir); params.arguments.push_back("products.theloadablemodule.installDir:" + libDir); } params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir); params.arguments.push_back("products.theplugin.installDir:" + pluginDir); params.arguments.push_back("products.theapp.debugInformationInstallDir:" + dsymDir); params.arguments.push_back("products.thelib.debugInformationInstallDir:" + dsymDir); params.arguments.push_back( "products.theloadablemodule.debugInformationInstallDir:" + dsymDir); params.arguments.push_back("products.theplugin.debugInformationInstallDir:" + dsymDir); } else if (testCase == "config") { params.arguments.push_back("modules.config.install.binariesDirectory:" + binDir); params.arguments.push_back("modules.config.install.applicationsDirectory:" + binDir); if (toolchain == "msvc" || toolchain == "mingw") { params.arguments.push_back( "modules.config.install.dynamicLibrariesDirectory:" + binDir); } else { params.arguments.push_back( "modules.config.install.dynamicLibrariesDirectory:" + libDir); } params.arguments.push_back("modules.config.install.frameworksDirectory:" + libDir); params.arguments.push_back("modules.config.install.importLibrariesDirectory:" + libDir); params.arguments.push_back("modules.config.install.pluginsDirectory:" + pluginDir); params.arguments.push_back( "modules.config.install.loadableModulesDirectory:" + pluginDir); params.arguments.push_back( "modules.config.install.debugInformationDirectory:" + dsymDir); } else if (testCase == "installpaths") { params.arguments.push_back("modules.installpaths.bin:" + binDir); params.arguments.push_back("modules.installpaths.applications:" + binDir); params.arguments.push_back("modules.installpaths.lib:" + libDir); params.arguments.push_back("modules.installpaths.frameworks:" + libDir); params.arguments.push_back("modules.installpaths.plugins:" + pluginDir); params.arguments.push_back("modules.installpaths.loadableModules:" + pluginDir); params.arguments.push_back( "modules.config.install.debugInformationDirectory:" + dsymDir); } } QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); const QString jsonFilePath = testDataDir + "/install-locations/data/" + toolchain + ".json"; QFile jsonFile(jsonFilePath); QVERIFY2(jsonFile.open(QIODevice::ReadOnly), qPrintable(jsonFilePath)); QJsonParseError parseError; const auto jsonDoc = QJsonDocument::fromJson(jsonFile.readAll(), &parseError); QVERIFY2(parseError.error == QJsonParseError::NoError, qPrintable(parseError.errorString())); const auto jsonObject = jsonDoc.object(); const QString installRoot = QDir::currentPath() + "/default/install-root"; const QString installPrefix = (toolchain == "msvc" || toolchain == "mingw" || toolchain == "emscripten") ? QString() : "/usr/local"; const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/'; // Verify all binaries exist in expected locations for (auto it = jsonObject.begin(); it != jsonObject.end(); ++it) { const QString key = it.key(); const auto info = it.value().toObject(); const QString fileName = info.value("fileName").toString(); const QString installDir = testCase == "default" ? info.value("defaultInstallDir").toString() : info.value("customInstallDir").toString(); const QString subDir = info.value("subDir").toString(); const QString filePath = QDir::cleanPath( fullInstallPrefix + '/' + installDir + '/' + subDir + '/' + fileName); QVERIFY2( QFile::exists(filePath), qPrintable(QString("File does not exist: %1").arg(filePath))); } } void TestBlackbox::inputsFromDependencies() { QDir::setCurrent(testDataDir + "/inputs-from-dependencies"); QCOMPARE(runQbs(), 0); const QList output = m_qbsStdout.trimmed().split('\n'); QVERIFY2(output.contains((QDir::currentPath() + "/file1.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(output.contains((QDir::currentPath() + "/file2.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(output.contains((QDir::currentPath() + "/file3.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(!output.contains((QDir::currentPath() + "/file4.txt").toUtf8()), m_qbsStdout.constData()); } void TestBlackbox::installPackage() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); MacosTarHealer tarHealer; QDir::setCurrent(testDataDir + "/installpackage"); QCOMPARE(runQbs(), 0); const QString tarFilePath = relativeProductBuildDir("tar-package") + "/tar-package.tar.gz"; QVERIFY2(regularFileExists(tarFilePath), qPrintable(tarFilePath)); QProcess tarList; tarList.start(binary, QStringList() << "tf" << tarFilePath); QVERIFY2(tarList.waitForStarted(), qPrintable(tarList.errorString())); QVERIFY2(tarList.waitForFinished(), qPrintable(tarList.errorString())); const QList outputLines = tarList.readAllStandardOutput().split('\n'); QList cleanOutputLines; for (const QByteArray &line : outputLines) { const QByteArray trimmedLine = line.trimmed(); if (!trimmedLine.isEmpty()) cleanOutputLines.push_back(trimmedLine); } QCOMPARE(cleanOutputLines.size(), 3); for (const QByteArray &line : std::as_const(cleanOutputLines)) { QVERIFY2(line.contains("public_tool") || line.contains("mylib") || line.contains("lib.h"), line.constData()); } } void TestBlackbox::installRootFromProjectFile() { QDir::setCurrent(testDataDir + "/install-root-from-project-file"); const QString installRoot = QDir::currentPath() + '/' + relativeBuildDir() + "/my-install-root/"; QCOMPARE(runQbs(QbsRunParameters(QStringList("products.p.installRoot:" + installRoot))), 0); const QString installedFile = installRoot + "/install-prefix/install-dir/file.txt"; QVERIFY2(QFile::exists(installedFile), qPrintable(installedFile)); } void TestBlackbox::libraryType_data() { QTest::addColumn("libraryType"); QTest::newRow("dynamic") << QStringLiteral("dynamic"); QTest::newRow("static") << QStringLiteral("static"); } void TestBlackbox::libraryType() { QFETCH(QString, libraryType); QDir::setCurrent(testDataDir + "/library-type"); rmDirR(relativeBuildDir()); QStringList args{QStringLiteral("modules.config.build.libraryType:") + libraryType}; QCOMPARE(runQbs(QbsRunParameters("build", args)), 0); const bool isWindows = m_qbsStdout.contains("is windows: yes"); const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); const bool isGcc = m_qbsStdout.contains("is gcc: yes"); QVERIFY(isWindows || isDarwin || isGcc); const QString installRoot = QDir::currentPath() + '/' + relativeBuildDir() + "/install-root"; QString filePath; if (libraryType == QLatin1String("dynamic")) { if (isWindows) { filePath = installRoot + QStringLiteral("/bin/mylib.dll"); } else if (isDarwin) { filePath = installRoot + QStringLiteral("/lib/libmylib.dylib"); } else if (isGcc) { filePath = installRoot + QStringLiteral("/lib/libmylib.so"); } } else { if (isWindows && !isGcc) { filePath = installRoot + QStringLiteral("/lib/mylib.lib"); } else { filePath = installRoot + QStringLiteral("/lib/libmylib.a"); } } if (filePath.isEmpty()) QSKIP("Cannot determine file name"); QVERIFY2(QFileInfo::exists(filePath), qPrintable(filePath)); } void TestBlackbox::pluginType_data() { QTest::addColumn("pluginType"); QTest::newRow("dynamic plugin") << QStringLiteral("pluginType:dynamic"); QTest::newRow("static plugin") << QStringLiteral("pluginType:static"); QTest::newRow("static library") << QStringLiteral("libraryType:static"); } void TestBlackbox::pluginType() { QFETCH(QString, pluginType); QDir::setCurrent(testDataDir + "/plugin-type"); rmDirR(relativeBuildDir()); QStringList args{QStringLiteral("modules.config.build.") + pluginType}; QCOMPARE(runQbs(QbsRunParameters("build", args)), 0); const bool isWindows = m_qbsStdout.contains("is windows: yes"); const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); const bool isGcc = m_qbsStdout.contains("is gcc: yes"); QVERIFY(isWindows || isDarwin || isGcc); const QString installRoot = QDir::currentPath() + '/' + relativeBuildDir() + "/install-root"; const QString pluginsDir = QStringLiteral("/lib/plugin_type/plugins"); QString filePath; if (pluginType == QLatin1String("pluginType:dynamic")) { if (isWindows) { filePath = installRoot + pluginsDir + QStringLiteral("/myplugin.dll"); } else if (isDarwin) { filePath = installRoot + pluginsDir + QStringLiteral("/myplugin.bundle"); } else if (isGcc) { filePath = installRoot + pluginsDir + QStringLiteral("/libmyplugin.so"); } } else { if (isWindows && !isGcc) { filePath = installRoot + pluginsDir + QStringLiteral("/myplugin.lib"); } else { filePath = installRoot + pluginsDir + QStringLiteral("/libmyplugin.a"); } } if (filePath.isEmpty()) QSKIP("Cannot determine file name"); QVERIFY2(QFileInfo::exists(filePath), qPrintable(filePath)); } void TestBlackbox::installable() { QDir::setCurrent(testDataDir + "/installable"); QCOMPARE(runQbs(), 0); QFile installList(relativeProductBuildDir("install-list") + "/installed-files.txt"); QVERIFY2(installList.open(QIODevice::ReadOnly), qPrintable(installList.errorString())); QCOMPARE(installList.readAll().count('\n'), 2); } void TestBlackbox::installableAsAuxiliaryInput() { QDir::setCurrent(testDataDir + "/installable-as-auxiliary-input"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("f-impl"), m_qbsStdout.constData()); } void TestBlackbox::installTree() { QDir::setCurrent(testDataDir + "/install-tree"); QbsRunParameters params; params.command = "install"; QCOMPARE(runQbs(params), 0); const QString installRoot = relativeBuildDir() + "/install-root/"; QVERIFY(QFile::exists(installRoot + "content/foo.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir1/bar.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt")); } void TestBlackbox::invalidArtifactPath_data() { QTest::addColumn("baseDir"); QTest::addColumn("isValid"); QTest::newRow("inside, normal case") << "subdir" << true; QTest::newRow("inside, build dir 1") << "project.buildDirectory" << true; QTest::newRow("inside, build dir 2") << "subdir/.." << true; QTest::newRow("outside, absolute") << "/tmp" << false; QTest::newRow("outside, relative 1") << "../../" << false; QTest::newRow("outside, relative 2") << "subdir/../../.." << false; } void TestBlackbox::invalidArtifactPath() { QFETCH(QString, baseDir); QFETCH(bool, isValid); rmDirR(relativeBuildDir()); QDir::setCurrent(testDataDir + "/invalid-artifact-path"); QbsRunParameters params(QStringList("project.artifactDir:" + baseDir)); params.expectFailure = !isValid; QCOMPARE(runQbs(params) == 0, isValid); if (!isValid) QVERIFY2(m_qbsStderr.contains("outside of build directory"), m_qbsStderr.constData()); } void TestBlackbox::invalidCommandProperty_data() { QTest::addColumn("errorType"); QTest::newRow("assigning QObject") << QString("qobject"); QTest::newRow("assigning input artifact") << QString("input"); QTest::newRow("assigning other artifact") << QString("artifact"); } void TestBlackbox::invalidCommandProperty() { QDir::setCurrent(testDataDir + "/invalid-command-property"); QFETCH(QString, errorType); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.errorType:" + errorType))), 0); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("unsuitable"), m_qbsStderr.constData()); } void TestBlackbox::invalidLibraryNames() { QDir::setCurrent(testDataDir + "/invalid-library-names"); QFETCH(QString, index); QFETCH(bool, success); QFETCH(QStringList, diagnostics); QbsRunParameters params(QStringList("project.valueIndex:" + index)); params.expectFailure = !success; QCOMPARE(runQbs(params) == 0, success); for (const QString &diag : std::as_const(diagnostics)) QVERIFY2(m_qbsStderr.contains(diag.toLocal8Bit()), m_qbsStderr.constData()); } void TestBlackbox::invalidLibraryNames_data() { QTest::addColumn("index"); QTest::addColumn("success"); QTest::addColumn("diagnostics"); QTest::newRow("null") << "0" << false << QStringList("is null"); QTest::newRow("undefined") << "1" << false << QStringList("is undefined"); QTest::newRow("number") << "2" << false << QStringList("does not have string type"); QTest::newRow("array") << "3" << false << QStringList("does not have string type"); QTest::newRow("empty string") << "4" << true << (QStringList() << "WARNING: Removing empty string from value of property " "'cpp.dynamicLibraries' in product 'invalid-library-names'." << "WARNING: Removing empty string from value of property " "'cpp.staticLibraries' in product 'invalid-library-names'." << "WARNING: Removing empty string from value of property " "'cpp.libraries' in product 'invalid-library-names'."); } void TestBlackbox::invalidExtensionInstantiation() { rmDirR(relativeBuildDir()); QDir::setCurrent(testDataDir + "/invalid-extension-instantiation"); QbsRunParameters params; params.expectFailure = true; params.arguments << (QString("products.theProduct.extension:") + QTest::currentDataTag()); QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("invalid-extension-instantiation.qbs:17") && m_qbsStderr.contains('\'' + QByteArray(QTest::currentDataTag()) + "' cannot be instantiated"), m_qbsStderr.constData()); } void TestBlackbox::invalidExtensionInstantiation_data() { QTest::addColumn("dummy"); QTest::newRow("Environment"); QTest::newRow("File"); QTest::newRow("FileInfo"); QTest::newRow("Utilities"); } void TestBlackbox::invalidInstallDir() { QDir::setCurrent(testDataDir + "/invalid-install-dir"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("outside of install root"), m_qbsStderr.constData()); } void TestBlackbox::cli() { int status; findCli(&status); QCOMPARE(status, 0); const SettingsPtr s = settings(); qbs::Profile p("qbs_autotests-cli", s.get()); if (!p.exists()) QSKIP("No suitable Common Language Infrastructure test profile"); QDir::setCurrent(testDataDir + "/cli"); QbsRunParameters params(QStringList() << "-f" << "dotnettest.qbs"); params.profile = p.name(); status = runQbs(params); if (p.value("cli.toolchainInstallPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("toolchainInstallPath")) QSKIP("cli.toolchainInstallPath not set and automatic detection failed"); QCOMPARE(status, 0); rmDirR(relativeBuildDir()); QbsRunParameters params2(QStringList() << "-f" << "fshello.qbs"); params2.profile = p.name(); QCOMPARE(runQbs(params2), 0); rmDirR(relativeBuildDir()); } void TestBlackbox::combinedSources() { QDir::setCurrent(testDataDir + "/combined-sources"); QbsRunParameters params(QStringList("modules.cpp.combineCxxSources:false")); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("compiling combinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling uncombinable.cpp")); QVERIFY(!m_qbsStdout.contains("compiling amalgamated_theapp.cpp")); params.arguments = QStringList("modules.cpp.combineCxxSources:true"); params.command = "resolve"; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("combinable.cpp"); touch("main.cpp"); touch("uncombinable.cpp"); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling combinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling uncombinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling amalgamated_theapp.cpp")); } void TestBlackbox::commandFile() { QDir::setCurrent(testDataDir + "/command-file"); QbsRunParameters params(QStringList() << "-p" << "theLib"); QCOMPARE(runQbs(params), 0); params.arguments = QStringList() << "-p" << "theApp"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::compilerDefinesByLanguage() { QDir::setCurrent(testDataDir + "/compilerDefinesByLanguage"); QbsRunParameters params(QStringList { "-f", "compilerDefinesByLanguage.qbs" }); QCOMPARE(runQbs(params), 0); } void TestBlackbox::cppLibrary() { QDir::setCurrent(testDataDir + "/cpp-library"); QCOMPARE(runQbs(), 0); // Determine target OS from qbs output const bool isWindows = m_qbsStdout.contains("is windows"); const bool isDarwin = m_qbsStdout.contains("is darwin"); const bool isUnix = m_qbsStdout.contains("is unix"); const bool isEmscripten = m_qbsStdout.contains("is emscripten"); QVERIFY(isWindows || isDarwin || isUnix || isEmscripten); const QString libExtension = isWindows ? ".dll" : (isDarwin ? ".dylib" : ".so"); const QString libDir = relativeBuildDir() + "/install-root/" + (isWindows ? "/bin/" : "/lib/"); const QString libFile = (isWindows ? "testlib" : "libtestlib") + libExtension; QVERIFY(QFileInfo(libDir + libFile).exists()); // Test header installation - headers should be installed in subdirectories const QString publicHeaderPath = relativeBuildDir() + "/install-root/include/cpp-library/testlib/TestLib.h"; const QString privateHeaderPath = relativeBuildDir() + "/install-root/include/cpp-library/testlib/private/TestLibPrivate.h"; QVERIFY(QFileInfo(publicHeaderPath).exists()); QVERIFY(QFileInfo(privateHeaderPath).exists()); } void TestBlackbox::jsExtensionsFile() { QDir::setCurrent(testDataDir + "/jsextensions-file"); QFile fileToMove("tomove.txt"); QVERIFY2(fileToMove.open(QIODevice::WriteOnly), qPrintable(fileToMove.errorString())); fileToMove.close(); fileToMove.setPermissions(fileToMove.permissions() & ~(QFile::ReadUser | QFile::ReadOwner | QFile::ReadGroup | QFile::ReadOther)); QbsRunParameters params(QStringList() << "-f" << "file.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!QFileInfo("original.txt").exists()); QFile copy("copy.txt"); QVERIFY(copy.exists()); QVERIFY(copy.open(QIODevice::ReadOnly)); const QList lines = copy.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 2); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "true"); } void TestBlackbox::jsExtensionsFileInfo() { QDir::setCurrent(testDataDir + "/jsextensions-fileinfo"); QbsRunParameters params(QStringList() << "-f" << "fileinfo.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 28); int i = 0; QCOMPARE(lines.at(i++).trimmed().constData(), "blubb"); QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable( QFileInfo(QDir::currentPath()).canonicalFilePath())); QCOMPARE(lines.at(i++).trimmed().constData(), "/usr/bin"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "c:/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "true"); QCOMPARE(lines.at(i++).trimmed().constData(), HostOsInfo::isWindowsHost() ? "true" : "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "true"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(i++).trimmed().constData(), "/"); QCOMPARE(lines.at(i++).trimmed().constData(), HostOsInfo::isWindowsHost() ? "d:/" : "d:"); QCOMPARE(lines.at(i++).trimmed().constData(), "d:"); QCOMPARE(lines.at(i++).trimmed().constData(), "d:/"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "../blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "\\tmp\\blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "c:\\tmp\\blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable(HostOsInfo::pathListSeparator())); QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable(HostOsInfo::pathSeparator())); } void TestBlackbox::jsExtensionsHost() { QDir::setCurrent(testDataDir + "//jsextensions-host"); QbsRunParameters params(QStringList { "-f", "host.qbs" }); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 10); int i = 0; QCOMPARE(lines.at(i++).trimmed().constData(), "architecture: " + HostOsInfo::hostOSArchitecture()); QStringList list; for (const auto &s : HostOsInfo::canonicalOSIdentifiers(HostOsInfo::hostOSIdentifier())) list.push_back(s); QCOMPARE(lines.at(i++).trimmed().constData(), "os: " + list.join(',')); QCOMPARE(lines.at(i++).trimmed().constData(), "platform: " + HostOsInfo::hostOSIdentifier()); QCOMPARE(lines.at(i++).trimmed().constData(), "osVersion: " + HostOsInfo::hostOsVersion().toString()); QCOMPARE(lines.at(i++).trimmed().constData(), "osBuildVersion: " + (HostOsInfo::hostOsBuildVersion().isNull() ? "undefined" : HostOsInfo::hostOsBuildVersion())); QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionParts: " + HostOsInfo::hostOsVersion().toString(',')); QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionMajor: " + QString::number( HostOsInfo::hostOsVersion().majorVersion())); QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionMinor: " + QString::number( HostOsInfo::hostOsVersion().minorVersion())); QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionPatch: " + QString::number( HostOsInfo::hostOsVersion().patchLevel())); QString nullDevice = HostOsInfo::isWindowsHost() ? QStringLiteral("NUL") : QStringLiteral("/dev/null"); QCOMPARE(lines.at(i++).trimmed().constData(), "nullDevice: " + nullDevice); } void TestBlackbox::jsExtensionsProcess() { QDir::setCurrent(testDataDir + "/jsextensions-process"); QCOMPARE(runQbs({"resolve", {"-f", "process.qbs"}}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params(QStringList() << "-f" << "process.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 15); QCOMPARE(lines.at(0).trimmed().constData(), "0"); QVERIFY(lines.at(1).startsWith("qbs ")); QCOMPARE(lines.at(2).trimmed().constData(), "true"); QCOMPARE(lines.at(3).trimmed().constData(), "true"); QCOMPARE(lines.at(4).trimmed().constData(), "0"); QVERIFY(lines.at(5).startsWith("qbs ")); QCOMPARE(lines.at(6).trimmed().constData(), "Unknown error"); QCOMPARE(lines.at(7).trimmed().constData(), "false"); QVERIFY(lines.at(8).trimmed() != "Unknown error"); QCOMPARE(lines.at(9).trimmed().constData(), "Unknown error"); QCOMPARE(lines.at(10).trimmed().constData(), "-1"); QVERIFY(lines.at(11).trimmed() != "Unknown error"); QVERIFY(lines.at(12).startsWith("Error running ")); QCOMPARE(lines.at(13).trimmed().constData(), "should be"); QCOMPARE(lines.at(14).trimmed().constData(), "123"); } void TestBlackbox::jsExtensionsPropertyList() { if (!HostOsInfo::isMacosHost()) QSKIP("temporarily only applies on macOS"); QDir::setCurrent(testDataDir + "/jsextensions-propertylist"); QbsRunParameters params(QStringList() << "-nf" << "propertylist.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("test.json"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QFile file2("test.xml"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); QFile file3("test2.json"); QVERIFY(file3.exists()); QVERIFY(file3.open(QIODevice::ReadOnly)); QByteArray file1Contents = file1.readAll(); QCOMPARE(file3.readAll(), file1Contents); //QCOMPARE(file1Contents, file2.readAll()); // keys don't have guaranteed order QJsonParseError err1, err2; QCOMPARE(QJsonDocument::fromJson(file1Contents, &err1), QJsonDocument::fromJson(file2.readAll(), &err2)); QVERIFY(err1.error == QJsonParseError::NoError && err2.error == QJsonParseError::NoError); QFile file4("test.openstep.plist"); QVERIFY(file4.exists()); QFile file5("test3.json"); QVERIFY(file5.exists()); QVERIFY(file5.open(QIODevice::ReadOnly)); QVERIFY(file1Contents != file5.readAll()); } void TestBlackbox::jsExtensionsTemporaryDir() { QDir::setCurrent(testDataDir + "/jsextensions-temporarydir"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::jsExtensionsTextFile() { QDir::setCurrent(testDataDir + "/jsextensions-textfile"); QbsRunParameters params(QStringList() << "-f" << "textfile.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("file1.txt"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QCOMPARE(file1.size(), qint64(0)); QFile file2("file2.txt"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); const QList lines = file2.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 6); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "First line."); QCOMPARE(lines.at(2).trimmed().constData(), "Second line."); QCOMPARE(lines.at(3).trimmed().constData(), "Third line."); QCOMPARE(lines.at(4).trimmed().constData(), qPrintable(QDir::currentPath() + "/file1.txt")); QCOMPARE(lines.at(5).trimmed().constData(), "true"); } void TestBlackbox::jsExtensionsBinaryFile() { QDir::setCurrent(testDataDir + "/jsextensions-binaryfile"); QbsRunParameters params(QStringList() << "-f" << "binaryfile.qbs"); QCOMPARE(runQbs(params), 0); QFile source("source.dat"); QVERIFY(source.exists()); QVERIFY(source.open(QIODevice::ReadOnly)); QCOMPARE(source.size(), qint64(0)); QFile destination("destination.dat"); QVERIFY(destination.exists()); QVERIFY(destination.open(QIODevice::ReadOnly)); const QByteArray data = destination.readAll(); QCOMPARE(data.size(), 8); QCOMPARE(data.at(0), char(0x00)); QCOMPARE(data.at(1), char(0x01)); QCOMPARE(data.at(2), char(0x02)); QCOMPARE(data.at(3), char(0x03)); QCOMPARE(data.at(4), char(0x04)); QCOMPARE(data.at(5), char(0x05)); QCOMPARE(data.at(6), char(0x06)); QCOMPARE(data.at(7), char(0xFF)); QFile destination2("destination2.dat"); QVERIFY(destination2.exists()); QVERIFY(destination2.open(QIODevice::ReadOnly)); QCOMPARE(destination2.readAll(), data); } void TestBlackbox::lastModuleCandidateBroken() { QDir::setCurrent(testDataDir + "/last-module-candidate-broken"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Dependency 'Foo' not found for product " "'last-module-candidate-broken'"), m_qbsStderr); } void TestBlackbox::ld() { QDir::setCurrent(testDataDir + "/ld"); QCOMPARE(runQbs(), 0); } void TestBlackbox::symbolLinkMode() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + "/symbolLinkMode"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; const QStringList commonArgs{"-p", "driver", "--setup-run-env-config", "ignore-lib-dependencies", "qbs.installPrefix:''"}; rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.shouldInstallLibrary:true"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("somefunction existed and it returned 42"), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.shouldInstallLibrary:false"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("somefunction did not exist"), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.lazy:false"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("Lib was loaded!\nmeow\n"), m_qbsStdout.constData()); if (HostOsInfo::isMacosHost()) { rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.lazy:true"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("meow\n") && m_qbsStdout.contains("Lib was loaded!\n"), m_qbsStdout.constData()); } } void TestBlackbox::linkerMode() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + "/linkerMode"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("qbs.installPrefix:''"))), 0); if (m_qbsStdout.contains("is emscripten: true")) QSKIP("not applicable for emscripten"); QVERIFY(m_qbsStdout.contains("is emscripten: false")); QCOMPARE(runQbs(), 0); auto testCondition = [&](const QString &lang, const std::function &condition) { if ((lang == "Objective-C" || lang == "Objective-C++") && HostOsInfo::hostOs() != HostOsInfo::HostOsMacos) return; const QString binary = defaultInstallRoot + "/LinkedProduct-" + lang; QProcess deptool; if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) deptool.start("otool", QStringList() << "-L" << binary); else deptool.start("readelf", QStringList() << "-a" << binary); QVERIFY(deptool.waitForStarted()); QVERIFY(deptool.waitForFinished()); QByteArray deptoolOutput = deptool.readAllStandardOutput(); if (HostOsInfo::hostOs() != HostOsInfo::HostOsMacos) { QList lines = deptoolOutput.split('\n'); int sz = lines.size(); for (int i = 0; i < sz; ++i) { if (!lines.at(i).contains("NEEDED")) { lines.removeAt(i--); sz--; } } deptoolOutput = lines.join('\n'); } QCOMPARE(deptool.exitCode(), 0); QVERIFY2(condition(deptoolOutput), deptoolOutput.constData()); }; const QStringList nocpplangs = QStringList() << "Assembly" << "C" << "Objective-C"; for (const QString &lang : nocpplangs) testCondition(lang, [](const QByteArray &lddOutput) { return !lddOutput.contains("c++"); }); const QStringList cpplangs = QStringList() << "C++" << "Objective-C++"; for (const QString &lang : cpplangs) testCondition(lang, [](const QByteArray &lddOutput) { return lddOutput.contains("c++"); }); const QStringList objclangs = QStringList() << "Objective-C" << "Objective-C++"; for (const QString &lang : objclangs) testCondition(lang, [](const QByteArray &lddOutput) { return lddOutput.contains("objc"); }); } void TestBlackbox::linkerVariant_data() { QTest::addColumn("theType"); QTest::newRow("default") << QString(); QTest::newRow("bfd") << QString("bfd"); QTest::newRow("gold") << QString("gold"); QTest::newRow("mold") << QString("mold"); } void TestBlackbox::linkerVariant() { QDir::setCurrent(testDataDir + "/linker-variant"); QFETCH(QString, theType); QStringList resolveArgs("--force-probe-execution"); if (!theType.isEmpty()) resolveArgs << ("products.p.linkerVariant:" + theType); QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); const bool isGcc = m_qbsStdout.contains("is GCC: true"); const bool isNotGcc = m_qbsStdout.contains("is GCC: false"); QVERIFY2(isGcc != isNotGcc, m_qbsStdout.constData()); QbsRunParameters buildParams("build", QStringList{"--command-echo-mode", "command-line"}); buildParams.expectFailure = true; runQbs(buildParams); if (isGcc && !theType.isEmpty()) QCOMPARE(m_qbsStdout.count("-fuse-ld=" + theType.toLocal8Bit()), 1); else QVERIFY2(!m_qbsStdout.contains("-fuse-ld"), m_qbsStdout.constData()); } void TestBlackbox::linkerTypeRecursive() { QDir::setCurrent(testDataDir + "/linker-type-recursive"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("no host target")) QSKIP("The rest of the test only applies to host targets"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("Hi!"), m_qbsStdout.constData()); } void TestBlackbox::lexyacc() { if (!lexYaccExist()) QSKIP("lex or yacc not present"); QDir::setCurrent(testDataDir + "/lexyacc/one-grammar"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const QString parserBinary = relativeExecutableFilePath("one-grammar", m_qbsStdout); QCOMPARE(runQbs(), 0); QProcess p; const QByteArray magicString = "add to PATH: "; const int magicStringIndex = m_qbsStdout.indexOf(magicString); if (magicStringIndex != -1) { const int newLineIndex = m_qbsStdout.indexOf('\n', magicStringIndex); QVERIFY(newLineIndex != -1); const int dirIndex = magicStringIndex + magicString.length(); const QString dir = QString::fromLocal8Bit(m_qbsStdout.mid(dirIndex, newLineIndex - dirIndex)); QProcessEnvironment env; env.insert("PATH", dir); p.setProcessEnvironment(env); } p.start(parserBinary, QStringList()); QVERIFY2(p.waitForStarted(), qPrintable(p.errorString())); p.write("a && b || c && !d"); p.closeWriteChannel(); QVERIFY2(p.waitForFinished(), qPrintable(p.errorString())); QVERIFY2(p.exitCode() == 0, p.readAllStandardError().constData()); const QByteArray parserOutput = p.readAllStandardOutput(); QVERIFY2(parserOutput.contains("OR AND a b AND c NOT d"), parserOutput.constData()); QDir::setCurrent(testDataDir + "/lexyacc/two-grammars"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.expectFailure = false; params.command = "resolve"; params.arguments << (QStringList() << "modules.lex_yacc.uniqueSymbolPrefix:true"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStderr.contains("whatever"), m_qbsStderr.constData()); params.arguments << "modules.lex_yacc.enableCompilerWarnings:true"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); const QByteArray outputToCheck = m_qbsStdout + m_qbsStderr; QVERIFY2(outputToCheck.contains("whatever"), outputToCheck.constData()); } void TestBlackbox::lexyaccOutputs() { if (!lexYaccExist()) QSKIP("lex or yacc not present"); QFETCH(QString, lexOutputFilePath); QFETCH(QString, yaccOutputFilePath); QbsRunParameters params; if (!lexOutputFilePath.isEmpty()) params.arguments << "modules.lex_yacc.lexOutputFilePath:" + lexOutputFilePath; if (!yaccOutputFilePath.isEmpty()) params.arguments << "modules.lex_yacc.yaccOutputFilePath:" + yaccOutputFilePath; #define VERIFY_COMPILATION(file) \ if (!file.isEmpty()) { \ QByteArray expected = "compiling " + file.toUtf8(); \ if (!m_qbsStdout.contains(expected)) { \ qDebug() << "Expected output:" << expected; \ qDebug() << "Actual output:" << m_qbsStdout; \ QFAIL("Expected stdout content missing."); \ } \ } const auto version = bisonVersion(); if (version >= qbs::Version(2, 6)) { // prefix only supported starting from bison 2.6 QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_prefix")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(yaccOutputFilePath); } QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_outfile")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(yaccOutputFilePath); if (version >= qbs::Version(2, 4)) { // output syntax was changed in bison 2.4 QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/yacc_output")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(lexOutputFilePath); } #undef VERIFY_COMPILATION } void TestBlackbox::lexyaccOutputs_data() { QTest::addColumn("lexOutputFilePath"); QTest::addColumn("yaccOutputFilePath"); QTest::newRow("none") << QString() << QString(); QTest::newRow("lexOutputFilePath") << QString{"lex_luthor.cpp"} << QString(); QTest::newRow("yaccOutputFilePath") << QString() << QString{"shaven_yak.cpp"}; } void TestBlackbox::linkerLibraryDuplicates() { QDir::setCurrent(testDataDir + "/linker-library-duplicates"); rmDirR(relativeBuildDir()); QFETCH(QString, removeDuplicateLibraries); QStringList runParams; if (!removeDuplicateLibraries.isEmpty()) runParams.append(removeDuplicateLibraries); QCOMPARE(runQbs(QbsRunParameters("resolve", runParams)), 0); const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); if (isNotGcc) QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); QVERIFY(isGcc); QCOMPARE(runQbs(QStringList { "--command-echo-mode", "command-line" }), 0); const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray linkLine; for (const QByteArray &line : output) { if (line.contains("main.cpp.o")) linkLine = line; } QVERIFY(!linkLine.isEmpty()); /* Now check the the libraries appear just once. In order to avoid dealing * with the different file extensions used in different platforms, we check * only for the library base name. But we must also take into account that * the build directories of each library will contain the library base name, * so we now exclude them. */ QByteArrayList elementsWithoutPath; for (const QByteArray &element: linkLine.split(' ')) { if (element.indexOf('/') < 0) elementsWithoutPath.append(element); } QByteArray pathLessLinkLine = elementsWithoutPath.join(' '); typedef QMap ObjectCount; QFETCH(ObjectCount, expectedObjectCount); for (auto i = expectedObjectCount.begin(); i != expectedObjectCount.end(); i++) { QCOMPARE(pathLessLinkLine.count(i.key()), i.value()); } } void TestBlackbox::linkerLibraryDuplicates_data() { typedef QMap ObjectCount; QTest::addColumn("removeDuplicateLibraries"); QTest::addColumn("expectedObjectCount"); QTest::newRow("default") << QString() << ObjectCount { { "lib1", 1 }, { "lib2", 1 }, { "lib3", 1 }, }; QTest::newRow("enabled") << "modules.cpp.removeDuplicateLibraries:true" << ObjectCount { { "lib1", 1 }, { "lib2", 1 }, { "lib3", 1 }, }; QTest::newRow("disabled") << "modules.cpp.removeDuplicateLibraries:false" << ObjectCount { { "lib1", 3 }, { "lib2", 2 }, { "lib3", 1 }, }; } void TestBlackbox::linkerScripts() { const QString sourceDir = QDir::cleanPath(testDataDir + "/linkerscripts"); QbsRunParameters runParams("resolve", {"qbs.installRoot:" + QDir::currentPath()}); runParams.buildDirectory = sourceDir + "/build"; runParams.workingDir = sourceDir; QCOMPARE(runQbs(runParams), 0); const bool isGcc = m_qbsStdout.contains("is Linux gcc: true"); const bool isNotGcc = m_qbsStdout.contains("is Linux gcc: false"); if (isNotGcc) QSKIP("linker script test only applies to Linux"); QVERIFY(isGcc); runParams.command = "build"; QCOMPARE(runQbs(runParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); const QRegularExpressionMatch match = pattern.match(output); QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); const auto verifySymbols = [nmPath](const QByteArrayList& symbols) -> bool { QProcess nm; nm.start(nmPath, QStringList(QDir::currentPath() + "/liblinkerscripts.so")); if (!nm.waitForStarted()) { qDebug() << "Wait for process started failed."; return false; } if (!nm.waitForFinished()) { qDebug() << "Wait for process finished failed."; return false; } if (nm.exitCode() != 0) { qDebug() << "nm returned exit code " << nm.exitCode(); return false; } const QByteArray nmOutput = nm.readAllStandardOutput(); for (const QByteArray& symbol : symbols) { if (!nmOutput.contains(symbol)) { qDebug() << "Expected symbol" << symbol << "not found in" << nmOutput.constData(); return false; } } return true; }; QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE", "TEST_SYMBOL_FROM_DIRECTORY", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/linkerscript_to_include", "TEST_SYMBOL_FROM_INCLUDE = 1;", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying included file"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/scripts/linkerscript_in_directory", "TEST_SYMBOL_FROM_DIRECTORY = 1;\n", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying file in directory"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/linkerscript_recursive", "TEST_SYMBOL_FROM_RECURSIVE = 1;\n", "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying recursive file"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED"})); } void TestBlackbox::linkerModuleDefinition() { QDir::setCurrent(testDataDir + "/linker-module-definition"); QCOMPARE(runQbs({"build"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs({"run"}), 0); const auto verifyOutput = [this](const QByteArrayList &symbols) { for (const QByteArray &symbol : symbols) { if (!m_qbsStdout.contains(symbol)) { qDebug() << "Expected symbol" << symbol << "not found in" << m_qbsStdout; return false; } } return true; }; QVERIFY(verifyOutput({"foo", "bar"})); } void TestBlackbox::listProducts() { QDir::setCurrent(testDataDir + "/list-products"); QCOMPARE(runQbs(QbsRunParameters("list-products")), 0); m_qbsStdout.replace("\r\n", "\n"); QVERIFY2(m_qbsStdout.contains( "a\n" "b {\"architecture\":\"mips\",\"buildVariant\":\"debug\"}\n" "b {\"architecture\":\"mips\",\"buildVariant\":\"release\"}\n" "b {\"architecture\":\"vax\",\"buildVariant\":\"debug\"}\n" "b {\"architecture\":\"vax\",\"buildVariant\":\"release\"}\n" "c\n"), m_qbsStdout.constData()); } void TestBlackbox::listPropertiesWithOuter() { QDir::setCurrent(testDataDir + "/list-properties-with-outer"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("listProp: [\"product\",\"higher\",\"group\"]"), m_qbsStdout.constData()); } void TestBlackbox::listPropertyOrder() { QDir::setCurrent(testDataDir + "/list-property-order"); const QbsRunParameters params(QStringList() << "-q"); QCOMPARE(runQbs(params), 0); const QByteArray firstOutput = m_qbsStderr; QVERIFY(firstOutput.contains("listProp = [\"product\",\"higher3\",\"higher2\",\"higher1\",\"lower\"]")); for (int i = 0; i < 25; ++i) { rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (m_qbsStderr != firstOutput) break; } QCOMPARE(m_qbsStderr.constData(), firstOutput.constData()); } void TestBlackbox::require() { QDir::setCurrent(testDataDir + "/require"); QCOMPARE(runQbs(), 0); } void TestBlackbox::rescueTransformerData() { QDir::setCurrent(testDataDir + "/rescue-transformer-data"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp") && m_qbsStdout.contains("m.p: undefined"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp") && !m_qbsStdout.contains("m.p: "), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.p:true"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp") && m_qbsStdout.contains("m.p: true"), m_qbsStdout.constData()); } void TestBlackbox::multipleChanges() { QDir::setCurrent(testDataDir + "/multiple-changes"); QCOMPARE(runQbs(), 0); QFile newFile("test.blubb"); QVERIFY(newFile.open(QIODevice::WriteOnly)); newFile.close(); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "project.prop:true")), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("prop: true")); } void TestBlackbox::multipleConfigurations() { QDir::setCurrent(testDataDir + "/multiple-configurations"); QbsRunParameters params(QStringList{"config:x", "config:y", "config:z"}); params.profile.clear(); struct DefaultProfileSwitcher { DefaultProfileSwitcher() { const SettingsPtr s = settings(); oldDefaultProfile = s->defaultProfile(); s->setValue("defaultProfile", profileName()); s->sync(); } ~DefaultProfileSwitcher() { const SettingsPtr s = settings(); s->setValue("defaultProfile", oldDefaultProfile); s->sync(); } QVariant oldDefaultProfile; }; DefaultProfileSwitcher dps; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 3); QCOMPARE(m_qbsStdout.count("compiling file.cpp"), 3); QCOMPARE(m_qbsStdout.count("compiling main.cpp"), 3); } void TestBlackbox::multiplexedTool() { QDir::setCurrent(testDataDir + "/multiplexed-tool"); QCOMPARE(runQbs(QStringLiteral("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("creating tool.out"), 4); } void TestBlackbox::nestedGroups() { QDir::setCurrent(testDataDir + "/nested-groups"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("nested-groups", m_qbsStdout))); } void TestBlackbox::nestedProperties() { QDir::setCurrent(testDataDir + "/nested-properties"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("value in higherlevel"), m_qbsStdout.constData()); } void TestBlackbox::newOutputArtifact() { QDir::setCurrent(testDataDir + "/new-output-artifact"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeBuildDir() + "/install-root/output_98.out")); const QString the100thArtifact = relativeBuildDir() + "/install-root/output_99.out"; QVERIFY(!regularFileExists(the100thArtifact)); QbsRunParameters params("resolve", QStringList() << "products.theProduct.artifactCount:100"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(the100thArtifact)); } void TestBlackbox::noExportedSymbols_data() { QTest::addColumn("link"); QTest::addColumn("dryRun"); QTest::newRow("link") << true << false; QTest::newRow("link (dry run)") << true << true; QTest::newRow("do not link") << false << false; } void TestBlackbox::noExportedSymbols() { QDir::setCurrent(testDataDir + "/no-exported-symbols"); QFETCH(bool, link); QFETCH(bool, dryRun); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"--force-probe-execution", QString("products.the_app.link:") + (link ? "true" : "false")})), 0); const bool isMsvc = m_qbsStdout.contains("compiler is MSVC"); const bool isNotMsvc = m_qbsStdout.contains("compiler is not MSVC"); QVERIFY2(isMsvc || isNotMsvc, m_qbsStdout.constData()); if (isNotMsvc) QSKIP("Test applies with MSVC only"); QbsRunParameters buildParams; if (dryRun) buildParams.arguments << "--dry-run"; buildParams.expectFailure = link && !dryRun; QCOMPARE(runQbs(buildParams) == 0, !buildParams.expectFailure); QVERIFY2(m_qbsStderr.contains("This typically happens when a DLL does not export " "any symbols.") == buildParams.expectFailure, m_qbsStderr.constData()); } void TestBlackbox::noProfile() { QDir::setCurrent(testDataDir + "/no-profile"); QbsRunParameters params; params.profile = "none"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("profile: none"), m_qbsStdout.constData()); } void TestBlackbox::noSuchProfile() { QDir::setCurrent(testDataDir + "/no-such-profile"); QbsRunParameters params(QStringList("products.theProduct.p:1")); params.profile = "jibbetnich"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Profile 'jibbetnich' does not exist"), m_qbsStderr.constData()); } void TestBlackbox::nonBrokenFilesInBrokenProduct() { QDir::setCurrent(testDataDir + "/non-broken-files-in-broken-product"); QbsRunParameters params(QStringList() << "-k"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("fine.cpp")); QVERIFY(runQbs(params) != 0); QVERIFY(!m_qbsStdout.contains("fine.cpp")); // The non-broken file must not be recompiled. } void TestBlackbox::nonDefaultProduct() { QDir::setCurrent(testDataDir + "/non-default-product"); QCOMPARE(runQbs(), 0); const QString defaultAppExe = relativeExecutableFilePath("default app", m_qbsStdout); const QString nonDefaultAppExe = relativeExecutableFilePath("non-default app", m_qbsStdout); QVERIFY2(QFile::exists(defaultAppExe), qPrintable(defaultAppExe)); QVERIFY2(!QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--all-products")), 0); QVERIFY2(QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); } void TestBlackbox::notAlwaysUpdated() { QDir::setCurrent(testDataDir + "/not-always-updated"); QCOMPARE(runQbs(), 0); QCOMPARE(runQbs(), 0); } static void switchProfileContents(qbs::Profile &p, qbs::Settings *s, bool on) { const QString scalarKey = "leaf.scalarProp"; const QString listKey = "leaf.listProp"; if (on) { p.setValue(scalarKey, "profile"); p.setValue(listKey, QStringList() << "profile"); } else { p.remove(scalarKey); p.remove(listKey); } s->sync(); } static void switchFileContents(QFile &f, bool on) { f.seek(0); QByteArray contents = f.readAll(); f.resize(0); if (on) contents.replace("// leaf.", "leaf."); else contents.replace("leaf.", "// leaf."); f.write(contents); f.flush(); } void TestBlackbox::propertyPrecedence() { QDir::setCurrent(testDataDir + "/property-precedence"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile profile("qbs_autotests_propPrecedence", s.get()); profile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... s->sync(); const QStringList args = QStringList() << "-f" << "property-precedence.qbs"; QbsRunParameters params(args); params.profile = profile.p.name(); QbsRunParameters resolveParams = params; resolveParams.command = "resolve"; // Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0] QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("scalar prop: leaf\n") && m_qbsStdout.contains("list prop: [\"leaf\"]\n"), m_qbsStdout.constData()); params.arguments.clear(); // Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: profile\n") && m_qbsStdout.contains("list prop: [\"profile\"]\n"), m_qbsStdout.constData()); // Case 3: [cmdline=0,prod=0,export=0,nonleaf=1,profile=0] QFile nonleafFile("modules/nonleaf/nonleaf.qbs"); QVERIFY2(nonleafFile.open(QIODevice::ReadWrite), qPrintable(nonleafFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 5: [cmdline=0,prod=0,export=1,nonleaf=0,profile=0] QFile depFile("dep.qbs"); QVERIFY2(depFile.open(QIODevice::ReadWrite), qPrintable(depFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 9: [cmdline=0,prod=1,export=0,nonleaf=0,profile=0] QFile productFile("property-precedence.qbs"); QVERIFY2(productFile.open(QIODevice::ReadWrite), qPrintable(productFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 11: [cmdline=0,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 13: [cmdline=0,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 15: [cmdline=0,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Command line properties wipe everything, including lists. // Case 17: [cmdline=1,prod=0,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, false); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 18: [cmdline=1,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 19: [cmdline=1,prod=0,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 20: [cmdline=1,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 21: [cmdline=1,prod=0,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 22: [cmdline=1,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 23: [cmdline=1,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 24: [cmdline=1,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 25: [cmdline=1,prod=1,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 26: [cmdline=1,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 27: [cmdline=1,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 28: [cmdline=1,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 29: [cmdline=1,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 30: [cmdline=1,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 31: [cmdline=1,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 32: [cmdline=1,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); } void TestBlackbox::productDependenciesByType() { QDir::setCurrent(testDataDir + "/product-dependencies-by-type"); QCOMPARE(runQbs(), 0); QFile appListFile(relativeProductBuildDir("app list") + "/app-list.txt"); QVERIFY2(appListFile.open(QIODevice::ReadOnly), qPrintable(appListFile.fileName())); const QList appList = appListFile.readAll().trimmed().split('\n'); QCOMPARE(appList.size(), 6); QStringList apps = QStringList() << QDir::currentPath() + '/' + relativeExecutableFilePath("app1", m_qbsStdout) << QDir::currentPath() + '/' + relativeExecutableFilePath("app2", m_qbsStdout) << QDir::currentPath() + '/' + relativeExecutableFilePath("app3", m_qbsStdout) << QDir::currentPath() + '/' + relativeExecutableFilePath("app4", m_qbsStdout) << QDir::currentPath() + '/' + relativeProductBuildDir("other-product") + "/output.txt" << QDir::currentPath() + '/' + relativeProductBuildDir("yet-another-product") + "/output.txt"; for (const QByteArray &line : appList) { const QString cleanLine = QString::fromLocal8Bit(line.trimmed()); QVERIFY2(apps.removeOne(cleanLine), qPrintable(cleanLine)); } QVERIFY(apps.empty()); } void TestBlackbox::productInExportedModule() { QDir::setCurrent(testDataDir + "/product-in-exported-module"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("product: importing"), m_qbsStdout.constData()); } void TestBlackbox::properQuoting() { QDir::setCurrent(testDataDir + "/proper quoting"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params(QStringLiteral("run"), QStringList() << "-q" << "-p" << "Hello World"); params.expectFailure = true; // Because the exit code is non-zero. QCOMPARE(runQbs(params), 156); const char * const expectedOutput = "whitespaceless\ncontains space\ncontains\ttab\n" "backslash\\\nHello World! The magic number is 156."; QCOMPARE(unifiedLineEndings(m_qbsStdout).constData(), expectedOutput); } void TestBlackbox::propertiesInExportItems() { QDir::setCurrent(testDataDir + "/properties-in-export-items"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("p1", m_qbsStdout))); QVERIFY(regularFileExists(relativeExecutableFilePath("p2", m_qbsStdout))); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); } void TestBlackbox::protobuf_data() { QTest::addColumn("projectFile"); QTest::addColumn("properties"); QTest::addColumn("hasModules"); QTest::addColumn("successExpected"); QTest::newRow("cpp-pkgconfig") << QString("addressbook_cpp.qbs") << QStringList({"project.qbsModuleProviders:qbspkgconfig"}) << true << true; QTest::newRow("cpp-conan") << QString("addressbook_cpp.qbs") << QStringList( {"project.qbsModuleProviders:conan", "qbs.buildVariant:release", "moduleProviders.conan.installDirectory:build"}) << true << true; QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << false << true; QTest::newRow("nanopb") << QString("addressbook_nanopb.qbs") << QStringList() << false << true; QTest::newRow("import") << QString("import.qbs") << QStringList() << true << true; QTest::newRow("missing import dir") << QString("needs-import-dir.qbs") << QStringList() << true << false; QTest::newRow("provided import dir") << QString("needs-import-dir.qbs") << QStringList("products.app.theImportDir:subdir") << true << true; QTest::newRow("create proto library") << QString("create-proto-library.qbs") << QStringList() << true << true; } void TestBlackbox::protobuf() { QDir::setCurrent(testDataDir + "/protobuf"); QFETCH(QString, projectFile); QFETCH(QStringList, properties); QFETCH(bool, hasModules); QFETCH(bool, successExpected); rmDirR(relativeBuildDir()); if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { if (!prepareAndRunConan()) QSKIP("conan is not prepared, check messages above"); } QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties); QCOMPARE(runQbs(resolveParams), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const bool withProtobuf = m_qbsStdout.contains("has protobuf: true"); const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false"); QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData()); if (withoutProtobuf) QSKIP("protobuf module not present"); const bool hasMods = m_qbsStdout.contains("has modules: true"); const bool dontHaveMods = m_qbsStdout.contains("has modules: false"); QVERIFY2(hasMods == !dontHaveMods, m_qbsStdout.constData()); QCOMPARE(hasMods, hasModules); QbsRunParameters runParams("run"); runParams.expectFailure = !successExpected; QCOMPARE(runQbs(runParams) == 0, successExpected); } void TestBlackbox::protobufLibraryInstall() { QDir::setCurrent(testDataDir + "/protobuf-library-install"); rmDirR(relativeBuildDir()); QbsRunParameters resolveParams("resolve", QStringList{"qbs.installPrefix:/usr/local"}); QCOMPARE(runQbs(resolveParams), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); const bool withProtobuf = m_qbsStdout.contains("has protobuf: true"); const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false"); QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData()); if (withoutProtobuf) QSKIP("protobuf module not present"); QbsRunParameters buildParams("build"); buildParams.expectFailure = false; QCOMPARE(runQbs(buildParams), 0); const QString installRootInclude = relativeBuildDir() + "/install-root/usr/local/include"; QVERIFY(QFileInfo::exists(installRootInclude + "/hello.pb.h") && QFileInfo::exists(installRootInclude + "/hello/world.pb.h")); } void TestBlackbox::pseudoMultiplexing() { // This is "pseudo-multiplexing" on all platforms that initialize qbs.architectures // to an array with one element. See QBS-1243. QDir::setCurrent(testDataDir + "/pseudo-multiplexing"); QCOMPARE(runQbs(), 0); } void TestBlackbox::qbsConfig() { QbsRunParameters params("config"); #ifdef QBS_ENABLE_UNIT_TESTS QTemporaryDir tempSystemSettingsDir; params.environment.insert("QBS_AUTOTEST_SYSTEM_SETTINGS_DIR", tempSystemSettingsDir.path()); QTemporaryDir tempUserSettingsDir; QVERIFY(tempSystemSettingsDir.isValid()); QVERIFY(tempUserSettingsDir.isValid()); const QStringList settingsDirArgs = QStringList{"--settings-dir", tempUserSettingsDir.path()}; // Set values. params.arguments = settingsDirArgs + QStringList{"--system", "key.subkey.scalar", "s"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--system", "key.subkey.list", "['sl']"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--user", "key.subkey.scalar", "u"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--user", "key.subkey.bool", "true"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--user", "key.subkey.uint", "42"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--user", "key.subkey.sint", "-42"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"key.subkey.list", "[\"u1\",\"u2\"]"}; QCOMPARE(runQbs(params), 0); // Check outputs. const auto valueExtractor = [this] { const QByteArray trimmed = m_qbsStdout.trimmed(); return trimmed.mid(trimmed.lastIndexOf(':') + 2); }; params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"u\"")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"u\"")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.bool"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("true")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.uint"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("42")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.sint"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("-42")); params.arguments = settingsDirArgs + QStringList{"--list", "--system", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"s\"")); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\", \"sl\"]")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\"]")); params.arguments = settingsDirArgs + QStringList{"--list", "--system", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"sl\"]")); // Remove some values and re-check. params.arguments = settingsDirArgs + QStringList{"--unset", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--system", "--unset", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"s\"")); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\"]")); // Check preferences.ignoreSystemSearchPaths params.arguments = settingsDirArgs + QStringList{"--system", "preferences.qbsSearchPaths", "['/usr/lib/qbs']"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"preferences.qbsSearchPaths", "['/home/user/qbs']"}; QCOMPARE(runQbs(params), 0); qbs::Settings settings(tempUserSettingsDir.path(), tempSystemSettingsDir.path()); const qbs::Preferences prefs(&settings, "SomeProfile"); QVERIFY2(prefs.searchPaths().contains("/usr/lib/qbs") && prefs.searchPaths().contains("/home/user/qbs"), qPrintable(prefs.searchPaths().join(','))); settings.setValue("profiles.SomeProfile.preferences.ignoreSystemSearchPaths", true); QVERIFY2(!prefs.searchPaths().contains("/usr/lib/qbs") && prefs.searchPaths().contains("/home/user/qbs"), qPrintable(prefs.searchPaths().join(','))); #else qDebug() << "ability to redirect the system settings dir not compiled in, skipping" "most qbs-config tests"; #endif // QBS_ENABLE_UNIT_TESTS bool canWriteToSystemSettings; QString testSettingsFilePath; { QSettings testSettings( qbs::Settings::defaultSystemSettingsBaseDir() + "/dummyOrg" + "/dummyApp.conf", QSettings::IniFormat); testSettings.setValue("dummyKey", "dummyValue"); testSettings.sync(); canWriteToSystemSettings = testSettings.status() == QSettings::NoError; testSettingsFilePath = testSettings.fileName(); } if (canWriteToSystemSettings) QVERIFY(QFile::remove(testSettingsFilePath)); // Check that trying to write to actual system settings causes access failure. params.expectFailure = !canWriteToSystemSettings; params.environment.clear(); params.arguments = QStringList{"--system", "key.subkey.scalar", "s"}; QCOMPARE(runQbs(params) == 0, canWriteToSystemSettings); if (!canWriteToSystemSettings) { QVERIFY2(m_qbsStderr.contains("You do not have permission to write to that location."), m_qbsStderr.constData()); } else { // cleanup system settings params.arguments = QStringList{"--system", "--unset", "key.subkey.scalar"}; QCOMPARE(runQbs(params) == 0, canWriteToSystemSettings); } } void TestBlackbox::qbsConfigAddProfile() { QbsRunParameters params("config"); QTemporaryDir settingsDir1; QTemporaryDir settingsDir2; QVERIFY(settingsDir1.isValid()); QVERIFY(settingsDir2.isValid()); const QStringList settingsDir1Args = QStringList{"--settings-dir", settingsDir1.path()}; const QStringList settingsDir2Args = QStringList{"--settings-dir", settingsDir2.path()}; QFETCH(QStringList, args); QFETCH(QString, errorMsg); // Step 1: Run --add-profile. params.arguments = settingsDir1Args; params.arguments << "--add-profile"; params.arguments << args; params.expectFailure = !errorMsg.isEmpty(); QCOMPARE(runQbs(params) == 0, !params.expectFailure); if (params.expectFailure) { QVERIFY(QString::fromLocal8Bit(m_qbsStderr).contains(errorMsg)); return; } params.expectFailure = false; params.arguments = settingsDir1Args; params.arguments << "--list"; QCOMPARE(runQbs(params), 0); const QByteArray output1 = m_qbsStdout; // Step 2: Set properties manually. for (int i = 1; i < args.size(); i += 2) { params.arguments = settingsDir2Args; params.arguments << ("profiles." + args.first() + '.' + args.at(i)) << args.at(i + 1); QCOMPARE(runQbs(params), 0); } params.arguments = settingsDir2Args; params.arguments << "--list"; QCOMPARE(runQbs(params), 0); const QByteArray output2 = m_qbsStdout; // Step3: Compare results. QCOMPARE(output1, output2); } void TestBlackbox::qbsConfigAddProfile_data() { QTest::addColumn("args"); QTest::addColumn("errorMsg"); QTest::newRow("no arguments") << QStringList() << QString("Profile name missing"); QTest::newRow("empty name") << QStringList{"", "p", "v"} << QString("Profile name must not be empty"); QTest::newRow("no properties") << QStringList("p") << QString("Profile properties must be provided"); QTest::newRow("one property") << QStringList{"p", "p", "v"} << QString(); QTest::newRow("two properties") << QStringList{"p", "p1", "v1", "p2", "v2"} << QString(); QTest::newRow("missing value") << QStringList{"p", "p"} << QString("Profile properties must be key/value pairs"); QTest::newRow("missing values") << QStringList{"p", "p1", "v1", "p2"} << QString("Profile properties must be key/value pairs"); } void TestBlackbox::qbsConfigImport() { QFETCH(QString, format); QDir::setCurrent(testDataDir + "/qbs-config-import-export"); QbsRunParameters params("config"); QTemporaryDir settingsDir; QVERIFY(settingsDir.isValid()); const QStringList settingsDirArgs = QStringList{"--settings-dir", settingsDir.path()}; params.arguments = settingsDirArgs; params.arguments << "--import" << "config." + format; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs; params.arguments << "--list"; QCOMPARE(runQbs(params), 0); const QByteArray output = m_qbsStdout; const auto lines = output.split('\n'); QCOMPARE(lines.count(), 5); QCOMPARE(lines[0], "group.key1: \"value1\""); QCOMPARE(lines[1], "group.key2: \"value2\""); QCOMPARE(lines[2], "key: \"value\""); QCOMPARE(lines[3], "listKey: [\"valueOne\", \"valueTwo\"]"); QCOMPARE(lines[4], ""); } void TestBlackbox::qbsConfigImport_data() { QTest::addColumn("format"); QTest::newRow("text") << QStringLiteral("txt"); QTest::newRow("json") << QStringLiteral("json"); } void TestBlackbox::qbsConfigExport() { QFETCH(QString, format); QDir::setCurrent(testDataDir + "/qbs-config-import-export"); QbsRunParameters params("config"); QTemporaryDir settingsDir; const QString fileName = "config." + format; const QString filePath = settingsDir.path() + "/" + fileName; QVERIFY(settingsDir.isValid()); const QStringList commonArgs = QStringList{"--settings-dir", settingsDir.path(), "--user"}; std::pair values[] = { {"key", "value"}, {"listKey", "[\"valueOne\",\"valueTwo\"]"}, {"group.key1", "value1"}, {"group.key2", "value2"} }; for (const auto &value: values) { params.arguments = commonArgs; params.arguments << value.first << value.second; QCOMPARE(runQbs(params), 0); } params.arguments = commonArgs; params.arguments << "--export" << filePath; QCOMPARE(runQbs(params), 0); QVERIFY(QFileInfo(filePath).canonicalPath() != QFileInfo(fileName).canonicalPath()); QFile exported(filePath); QFile expected(fileName); QVERIFY(exported.open(QIODevice::ReadOnly | QIODevice::Text)); QVERIFY(expected.open(QIODevice::ReadOnly | QIODevice::Text)); QCOMPARE(exported.readAll(), expected.readAll()); } void TestBlackbox::qbsConfigExport_data() { QTest::addColumn("format"); QTest::newRow("text") << QStringLiteral("txt"); QTest::newRow("json") << QStringLiteral("json"); } static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) { int totalSize = -1; QElapsedTimer timer; timer.start(); QByteArray msg; while (totalSize == -1 || msg.size() < totalSize) { if (data.isEmpty()) session.waitForReadyRead(1000); if (timer.elapsed() >= testTimeoutInMsecs()) return QJsonObject(); data += session.readAllStandardOutput(); if (totalSize == -1) { static const QByteArray magicString = "qbsmsg:"; const int magicStringOffset = data.indexOf(magicString); if (magicStringOffset == -1) continue; const int sizeOffset = magicStringOffset + magicString.length(); const int newlineOffset = data.indexOf('\n', sizeOffset); if (newlineOffset == -1) continue; const QByteArray sizeString = data.mid(sizeOffset, newlineOffset - sizeOffset); bool isNumber; const int size = sizeString.toInt(&isNumber); if (!isNumber || size <= 0) return QJsonObject(); data = data.mid(newlineOffset + 1); totalSize = size; } const int bytesToTake = std::min(totalSize - msg.size(), data.size()); msg += data.left(bytesToTake); data = data.mid(bytesToTake); } return QJsonDocument::fromJson(QByteArray::fromBase64(msg)).object(); } static void sendSessionPacket(QProcess &sessionProc, const QJsonObject &message) { const QByteArray data = QJsonDocument(message).toJson().toBase64(); sessionProc.write("qbsmsg:"); sessionProc.write(QByteArray::number(data.length())); sessionProc.write("\n"); sessionProc.write(data); } void TestBlackbox::qbsLanguageServer_data() { QTest::addColumn("request"); QTest::addColumn("location"); QTest::addColumn("insertLocation"); QTest::addColumn("insertString"); QTest::addColumn("expectedReply"); QTest::addRow("follow to module") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << QString() << QString() << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); QTest::addRow("follow to submodules") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:5:35") << QString() << QString() << ((testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:1:1\n") + (testDataDir + "/lsp/modules/Prefix/m2/m2.qbs:1:1\n") + (testDataDir + "/lsp/modules/Prefix/m3/m3.qbs:1:1")); QTest::addRow("follow to product") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:9:19") << QString() << QString() << (testDataDir + "/lsp/lsp.qbs:2:5"); QTest::addRow("follow to module, non-invalidating insert") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << "5:9" << QString("property bool dummy\n") << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); QTest::addRow("follow to module, invalidating insert") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << QString() << QString("property bool dummy\n") << QString(); QTest::addRow("follow to file in product") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:10:25") << QString() << QString() << (testDataDir + "/lsp/toplevel.txt:1:1"); QTest::addRow("follow to file in group (first element)") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:13:34") << QString() << QString() << (testDataDir + "/lsp/subdir/file1.txt:1:1"); QTest::addRow("follow to file in group (last element)") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:13:48") << QString() << QString() << (testDataDir + "/lsp/subdir/file2.txt:1:1"); QTest::addRow("follow \"references\"") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:16:24") << QString() << QString() << (testDataDir + "/lsp/other.qbs:1:1"); QTest::addRow("follow item from import path") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:17:7") << QString() << QString() << (testDataDir + "/lsp/MyProduct.qbs:2:74"); QTest::addRow("follow built-in item") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:18:7") << QString() << QString() << QString(); QTest::addRow("follow to module in binding (first segment)") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:21:12") << QString() << QString() << (testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:1:1"); QTest::addRow("follow to module in binding (last segment)") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:21:17") << QString() << QString() << (testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:1:1"); QTest::addRow("follow to module property") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:21:20") << QString() << QString() << (testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:2:19"); QTest::addRow("follow to module property 2") << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:6:13") << QString() << QString() << (testDataDir + "/lsp/modules/m/m.qbs:2:19"); QTest::addRow("completion: LHS, module prefix") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("P") << QString("Prefix.m1\nPrefix.m2\nPrefix.m3"); QTest::addRow("completion: LHS, module name") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("Prefix.m") << QString("m1\nm2\nm3"); QTest::addRow("completion: LHS, module property right after dot") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("Prefix.m1.") << QString("p1 bool\np2 string\nx bool"); QTest::addRow("completion: LHS, module property with identifier prefix") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("Prefix.m1.p") << QString("p1 bool\np2 string"); QTest::addRow("completion: simple RHS, module property") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("property bool dummy: Prefix.m1.p") << QString("p1 bool\np2 string"); QTest::addRow("completion: complex RHS, module property") << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("property bool dummy: { return Prefix.m1.p") << QString("p1 bool\np2 string"); } void TestBlackbox::qbsLanguageServer() { QFETCH(QString, request); QFETCH(QString, location); QFETCH(QString, insertLocation); QFETCH(QString, insertString); QFETCH(QString, expectedReply); QDir::setCurrent(testDataDir + "/lsp"); QProcess sessionProc; sessionProc.start(qbsExecutableFilePath, QStringList("session")); QVERIFY(sessionProc.waitForStarted()); QByteArray incomingData; // Wait for and verify hello packet. QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData); const QString socketPath = receivedMessage.value("lsp-socket").toString(); QVERIFY(!socketPath.isEmpty()); // Resolve project. QJsonObject resolveMessage; resolveMessage.insert("type", "resolve-project"); resolveMessage.insert("top-level-profile", profileName()); resolveMessage.insert("project-file-path", QDir::currentPath() + "/lsp.qbs"); resolveMessage.insert("build-root", QDir::currentPath()); resolveMessage.insert("settings-directory", settings()->baseDirectory()); sendSessionPacket(sessionProc, resolveMessage); bool receivedReply = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } } QVERIFY(receivedReply); // Employ client app to send request. QProcess lspClient; const QFileInfo qbsFileInfo(qbsExecutableFilePath); const QString clientFilePath = HostOsInfo::appendExecutableSuffix( qbsFileInfo.absolutePath() + "/qbs_lspclient"); QStringList args{"--socket", socketPath, request, location}; if (!insertString.isEmpty()) args << "--insert-code" << insertString; if (!insertLocation.isEmpty()) args << "--insert-location" << insertLocation; lspClient.start(clientFilePath, args); QVERIFY2(lspClient.waitForStarted(), qPrintable(lspClient.errorString())); QVERIFY2(lspClient.waitForFinished(), qPrintable(lspClient.errorString())); QString errMsg; if (lspClient.exitStatus() != QProcess::NormalExit) errMsg = lspClient.errorString(); if (errMsg.isEmpty()) errMsg = QString::fromLocal8Bit(lspClient.readAllStandardError()); QVERIFY2(lspClient.exitCode() == 0, qPrintable(errMsg)); QVERIFY2(errMsg.isEmpty(), qPrintable(errMsg)); QString output = QString::fromUtf8(lspClient.readAllStandardOutput().trimmed()); output.replace("\r\n", "\n"); QCOMPARE(output, expectedReply); QJsonObject quitRequest; quitRequest.insert("type", "quit"); sendSessionPacket(sessionProc, quitRequest); QVERIFY(sessionProc.waitForFinished(3000)); } void TestBlackbox::qbsSession() { QDir::setCurrent(testDataDir + "/qbs-session"); QProcess sessionProc; sessionProc.start(qbsExecutableFilePath, QStringList("session")); // Uncomment for debugging. /* connect(&sessionProc, &QProcess::readyReadStandardError, [&sessionProc] { qDebug() << "stderr:" << sessionProc.readAllStandardError(); }); */ QVERIFY(sessionProc.waitForStarted()); const auto sendPacket = [&sessionProc](const QJsonObject &message) { sendSessionPacket(sessionProc, message); }; static const auto envToJson = [](const QProcessEnvironment &env) { QJsonObject envObj; const QStringList keys = env.keys(); for (const QString &key : keys) envObj.insert(key, env.value(key)); return envObj; }; static const auto envFromJson = [](const QJsonValue &v) { const QJsonObject obj = v.toObject(); QProcessEnvironment env; for (auto it = obj.begin(); it != obj.end(); ++it) env.insert(it.key(), it.value().toString()); return env; }; QByteArray incomingData; // Wait for and verify hello packet. QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type"), "hello"); QCOMPARE(receivedMessage.value("api-level").toInt(), 9); QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2); // Resolve & verify structure QJsonObject resolveMessage; resolveMessage.insert("type", "resolve-project"); resolveMessage.insert("top-level-profile", profileName()); resolveMessage.insert("configuration-name", "my-config"); resolveMessage.insert("project-file-path", QDir::currentPath() + "/qbs-session.qbs"); resolveMessage.insert("build-root", QDir::currentPath()); resolveMessage.insert("settings-directory", settings()->baseDirectory()); QJsonObject overriddenValues; overriddenValues.insert("products.theLib.cpp.cxxLanguageVersion", "c++17"); resolveMessage.insert("overridden-properties", overriddenValues); resolveMessage.insert("environment", envToJson(QbsRunParameters::defaultEnvironment())); resolveMessage.insert("data-mode", "only-if-changed"); resolveMessage.insert("max-job-count", 2); resolveMessage.insert("log-time", true); resolveMessage.insert( "module-properties", QJsonArray::fromStringList( {"cpp.cxxLanguageVersion", "cpp.executableSuffix", "cpp.objectSuffix"})); sendPacket(resolveMessage); bool receivedLogData = false; bool receivedStartedSignal = false; bool receivedProgressData = false; bool receivedReply = false; QString objectSuffix; QString executableSuffix; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QCOMPARE(projectData.value("name").toString(), "qbs-session"); const QJsonArray products = projectData.value("products").toArray(); QCOMPARE(products.size(), 2); for (const QJsonValue &v : products) { const QJsonObject product = v.toObject(); const QString productName = product.value("name").toString(); QVERIFY(!productName.isEmpty()); QVERIFY2(product.value("is-enabled").toBool(), qPrintable(productName)); const QJsonObject moduleProps = product.value("module-properties").toObject(); objectSuffix = moduleProps.value("cpp.objectSuffix").toString(); executableSuffix = moduleProps.value("cpp.executableSuffix").toString(); bool theLib = false; bool theApp = false; if (productName == "theLib") theLib = true; else if (productName == "theApp") theApp = true; QVERIFY2(theLib || theApp, qPrintable(productName)); const QJsonArray groups = product.value("groups").toArray(); if (theLib) QVERIFY(groups.size() >= 3); else QVERIFY(!groups.isEmpty()); for (const QJsonValue &v : groups) { const QJsonObject group = v.toObject(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); const auto findArtifact = [&sourceArtifacts](const QString &fileName) { for (const QJsonValue &v : sourceArtifacts) { const QJsonObject artifact = v.toObject(); if (QFileInfo(artifact.value("file-path").toString()).fileName() == fileName) { return artifact; } } return QJsonObject(); }; const QString groupName = group.value("name").toString(); const auto getCxxLanguageVersion = [&group, &product] { QJsonObject moduleProperties = group.value("module-properties").toObject(); if (moduleProperties.isEmpty()) moduleProperties = product.value("module-properties").toObject(); return moduleProperties.toVariantMap().value("cpp.cxxLanguageVersion") .toStringList(); }; if (groupName == "sources") { const QJsonObject artifact = findArtifact("lib.cpp"); QVERIFY2(!artifact.isEmpty(), "lib.cpp"); QCOMPARE(getCxxLanguageVersion(), {"c++17"}); } else if (groupName == "headers") { const QJsonObject artifact = findArtifact("lib.h"); QVERIFY2(!artifact.isEmpty(), "lib.h"); } else if (groupName == "theApp") { const QJsonObject artifact = findArtifact("main.cpp"); QVERIFY2(!artifact.isEmpty(), "main.cpp"); QCOMPARE(getCxxLanguageVersion(), {"c++14"}); } } } break; } else if (msgType == "log-data") { if (receivedMessage.value("message").toString().contains("activity")) receivedLogData = true; } else if (msgType == "task-started") { receivedStartedSignal = true; } else if (msgType == "task-progress") { receivedProgressData = true; } else if (msgType != "new-max-progress") { QVERIFY2(false, qPrintable(QString("Unexpected message type '%1'").arg(msgType))); } } QVERIFY(receivedReply); QVERIFY(receivedLogData); QVERIFY(receivedStartedSignal); QVERIFY(receivedProgressData); // Add a dependency and re-resolve. QJsonObject addDepsRequest; addDepsRequest.insert("type", "add-dependencies"); addDepsRequest.insert("product", "theApp"); addDepsRequest.insert("group", "theApp"); addDepsRequest.insert("dependencies", QJsonArray::fromStringList({"mymodule"})); sendPacket(addDepsRequest); receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("dependencies-added")); QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) { for (const auto item : error[QStringLiteral("items")].toArray()) { const auto description = QStringLiteral("Project file updates are not enabled"); if (item.toObject()[QStringLiteral("description")].toString().contains(description)) QSKIP("File updates are disabled"); } qDebug() << error; } QVERIFY(error.isEmpty()); receivedReply = false; sendPacket(resolveMessage); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } } QVERIFY(receivedReply); // First build: No install, log time, default command description. QJsonObject buildRequest; buildRequest.insert("type", "build-project"); buildRequest.insert("log-time", true); buildRequest.insert("install", false); buildRequest.insert("data-mode", "only-if-changed"); sendPacket(buildRequest); receivedReply = false; receivedLogData = false; receivedStartedSignal = false; receivedProgressData = false; bool receivedCommandDescription = false; bool receivedProcessResult = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-built") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QCOMPARE(projectData.value("name").toString(), "qbs-session"); } else if (msgType == "log-data") { if (receivedMessage.value("message").toString().contains("activity")) receivedLogData = true; } else if (msgType == "task-started") { receivedStartedSignal = true; } else if (msgType == "task-progress") { receivedProgressData = true; } else if (msgType == "command-description") { if (receivedMessage.value("message").toString().contains("compiling main.cpp")) receivedCommandDescription = true; } else if (msgType == "process-result") { QCOMPARE(receivedMessage.value("exit-code").toInt(), 0); receivedProcessResult = true; } else if (msgType != "new-max-progress") { QVERIFY2(false, qPrintable(QString("Unexpected message type '%1'").arg(msgType))); } } QVERIFY(receivedReply); QVERIFY(receivedLogData); QVERIFY(receivedStartedSignal); QVERIFY(receivedProgressData); QVERIFY(receivedCommandDescription); QVERIFY(receivedProcessResult); const QString &exeFilePath = QDir::currentPath() + '/' + relativeProductBuildDir("theApp", "my-config") + '/' + "theApp" + executableSuffix; QVERIFY2(regularFileExists(exeFilePath), qPrintable(exeFilePath)); const QString defaultInstallRoot = QDir::currentPath() + '/' + relativeBuildDir("my-config") + "/install-root"; QVERIFY2(!directoryExists(defaultInstallRoot), qPrintable(defaultInstallRoot)); // Clean. QJsonObject cleanRequest; cleanRequest.insert("type", "clean-project"); cleanRequest.insert("settings-dir", settings()->baseDirectory()); cleanRequest.insert("log-time", true); sendPacket(cleanRequest); receivedReply = false; receivedLogData = false; receivedStartedSignal = false; receivedProgressData = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-cleaned") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } else if (msgType == "log-data") { if (receivedMessage.value("message").toString().contains("activity")) receivedLogData = true; } else if (msgType == "task-started") { receivedStartedSignal = true; } else if (msgType == "task-progress") { receivedProgressData = true; } else if (msgType != "new-max-progress") { QVERIFY2(false, qPrintable(QString("Unexpected message type '%1'").arg(msgType))); } } QVERIFY(receivedReply); QVERIFY(receivedLogData); QVERIFY(receivedStartedSignal); QVERIFY(receivedProgressData); QVERIFY2(!regularFileExists(exeFilePath), qPrintable(exeFilePath)); // Second build: Do not log the time, show command lines. buildRequest.insert("log-time", false); buildRequest.insert("command-echo-mode", "command-line"); sendPacket(buildRequest); receivedReply = false; receivedLogData = false; receivedStartedSignal = false; receivedProgressData = false; receivedCommandDescription = false; receivedProcessResult = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-built") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QVERIFY(projectData.isEmpty()); } else if (msgType == "log-data") { if (receivedMessage.value("message").toString().contains("activity")) receivedLogData = true; } else if (msgType == "task-started") { receivedStartedSignal = true; } else if (msgType == "task-progress") { receivedProgressData = true; } else if (msgType == "command-description") { if (QDir::fromNativeSeparators(receivedMessage.value("message").toString()) .contains("/main.cpp")) { receivedCommandDescription = true; } } else if (msgType == "process-result") { QCOMPARE(receivedMessage.value("exit-code").toInt(), 0); receivedProcessResult = true; } else if (msgType != "new-max-progress") { QVERIFY2(false, qPrintable(QString("Unexpected message type '%1'").arg(msgType))); } } QVERIFY(receivedReply); QVERIFY(!receivedLogData); QVERIFY(receivedStartedSignal); QVERIFY(receivedProgressData); QVERIFY(receivedCommandDescription); QVERIFY(receivedProcessResult); QVERIFY2(regularFileExists(exeFilePath), qPrintable(exeFilePath)); QVERIFY2(!directoryExists(defaultInstallRoot), qPrintable(defaultInstallRoot)); // Install. QJsonObject installRequest; installRequest.insert("type", "install-project"); installRequest.insert("log-time", true); const QString customInstallRoot = QDir::currentPath() + "/my-install-root"; QVERIFY2(!QFile::exists(customInstallRoot), qPrintable(customInstallRoot)); installRequest.insert("install-root", customInstallRoot); sendPacket(installRequest); receivedReply = false; receivedLogData = false; receivedStartedSignal = false; receivedProgressData = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "install-done") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } else if (msgType == "log-data") { if (receivedMessage.value("message").toString().contains("activity")) receivedLogData = true; } else if (msgType == "task-started") { receivedStartedSignal = true; } else if (msgType == "task-progress") { receivedProgressData = true; } else if (msgType != "new-max-progress") { QVERIFY2(false, qPrintable(QString("Unexpected message type '%1'").arg(msgType))); } } QVERIFY(receivedReply); QVERIFY(receivedLogData); QVERIFY(receivedStartedSignal); QVERIFY(receivedProgressData); QVERIFY2(!directoryExists(defaultInstallRoot), qPrintable(defaultInstallRoot)); QVERIFY2(directoryExists(customInstallRoot), qPrintable(customInstallRoot)); // Retrieve modified environment. QJsonObject getRunEnvRequest; getRunEnvRequest.insert("type", "get-run-environment"); getRunEnvRequest.insert("product", "theApp"); const QProcessEnvironment inEnv = QProcessEnvironment::systemEnvironment(); QVERIFY(!inEnv.contains("MY_MODULE")); getRunEnvRequest.insert("base-environment", envToJson(inEnv)); sendPacket(getRunEnvRequest); receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("run-environment")); error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QProcessEnvironment outEnv = envFromJson(receivedMessage.value("full-environment")); QVERIFY(outEnv.keys().size() > inEnv.keys().size()); QCOMPARE(outEnv.value("MY_MODULE"), QString("1")); // Add two files to library and re-build. QJsonObject addFilesRequest; addFilesRequest.insert("type", "add-files"); addFilesRequest.insert("product", "theLib"); addFilesRequest.insert("group", "sources"); addFilesRequest.insert("files", QJsonArray::fromStringList({QDir::currentPath() + "/file1.cpp", QDir::currentPath() + "/file2.cpp"})); sendPacket(addFilesRequest); receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("files-added")); error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) { for (const auto item: error[QStringLiteral("items")].toArray()) { const auto description = QStringLiteral("Project file updates are not enabled"); if (item.toObject()[QStringLiteral("description")].toString().contains(description)) QSKIP("File updates are disabled"); } qDebug() << error; } QVERIFY(error.isEmpty()); receivedReply = false; sendPacket(resolveMessage); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QJsonArray products = projectData.value("products").toArray(); bool file1 = false; bool file2 = false; for (const QJsonValue v : products) { const QJsonObject product = v.toObject(); const QString productName = product.value("full-display-name").toString(); const QJsonArray groups = product.value("groups").toArray(); for (const QJsonValue &v : groups) { const QJsonObject group = v.toObject(); const QString groupName = group.value("name").toString(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); for (const QJsonValue &v : sourceArtifacts) { const QString filePath = v.toObject().value("file-path").toString(); if (filePath.endsWith("file1.cpp")) { QCOMPARE(productName, QString("theLib")); QCOMPARE(groupName, QString("sources")); file1 = true; } else if (filePath.endsWith("file2.cpp")) { QCOMPARE(productName, QString("theLib")); QCOMPARE(groupName, QString("sources")); file2 = true; } } } } QVERIFY(file1); QVERIFY(file2); } } QVERIFY(receivedReply); receivedReply = false; receivedProcessResult = false; bool compiledFile1 = false; bool compiledFile2 = false; bool compiledMain = false; bool compiledLib = false; buildRequest.remove("command-echo-mode"); sendPacket(buildRequest); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-built") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } else if (msgType == "command-description") { const QString msg = receivedMessage.value("message").toString(); if (msg.contains("compiling file1.cpp")) compiledFile1 = true; else if (msg.contains("compiling file2.cpp")) compiledFile2 = true; else if (msg.contains("compiling main.cpp")) compiledMain = true; else if (msg.contains("compiling lib.cpp")) compiledLib = true; } else if (msgType == "process-result") { QCOMPARE(receivedMessage.value("exit-code").toInt(), 0); receivedProcessResult = true; } } QVERIFY(receivedReply); QVERIFY(!receivedProcessResult); QVERIFY(compiledFile1); QVERIFY(compiledFile2); QVERIFY(!compiledLib); QVERIFY(!compiledMain); // Remove one of the newly added files again and re-build. WAIT_FOR_NEW_TIMESTAMP(); touch("file1.cpp"); touch("file2.cpp"); touch("main.cpp"); QJsonObject removeFilesRequest; removeFilesRequest.insert("type", "remove-files"); removeFilesRequest.insert("product", "theLib"); removeFilesRequest.insert("group", "sources"); removeFilesRequest.insert("files", QJsonArray::fromStringList({QDir::currentPath() + "/file1.cpp"})); sendPacket(removeFilesRequest); receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("files-removed")); error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); receivedReply = false; sendPacket(resolveMessage); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QJsonArray products = projectData.value("products").toArray(); bool file1 = false; bool file2 = false; for (const QJsonValue v : products) { const QJsonObject product = v.toObject(); const QString productName = product.value("full-display-name").toString(); const QJsonArray groups = product.value("groups").toArray(); for (const QJsonValue &v : groups) { const QJsonObject group = v.toObject(); const QString groupName = group.value("name").toString(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); for (const QJsonValue &v : sourceArtifacts) { const QString filePath = v.toObject().value("file-path").toString(); if (filePath.endsWith("file1.cpp")) { file1 = true; } else if (filePath.endsWith("file2.cpp")) { QCOMPARE(productName, QString("theLib")); QCOMPARE(groupName, QString("sources")); file2 = true; } } } } QVERIFY(!file1); QVERIFY(file2); } } QVERIFY(receivedReply); receivedReply = false; receivedProcessResult = false; compiledFile1 = false; compiledFile2 = false; compiledMain = false; compiledLib = false; sendPacket(buildRequest); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-built") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } else if (msgType == "command-description") { const QString msg = receivedMessage.value("message").toString(); if (msg.contains("compiling file1.cpp")) compiledFile1 = true; else if (msg.contains("compiling file2.cpp")) compiledFile2 = true; else if (msg.contains("compiling main.cpp")) compiledMain = true; else if (msg.contains("compiling lib.cpp")) compiledLib = true; } else if (msgType == "process-result") { QCOMPARE(receivedMessage.value("exit-code").toInt(), 0); receivedProcessResult = true; } } QVERIFY(receivedReply); QVERIFY(receivedProcessResult); QVERIFY(!compiledFile1); QVERIFY(compiledFile2); QVERIFY(!compiledLib); QVERIFY(compiledMain); // Rename a file and re-build. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(QFile::rename("lib.cpp", "theLib.cpp")); QJsonObject renameFilesRequest; renameFilesRequest.insert("type", "rename-files"); renameFilesRequest.insert("product", "theLib"); renameFilesRequest.insert("group", "sources"); QJsonObject sourceAndTarget( {qMakePair(QString("source-path"), QJsonValue(QDir::currentPath() + "/lib.cpp")), qMakePair(QString("target-path"), QJsonValue(QDir::currentPath() + "/theLib.cpp"))}); renameFilesRequest.insert("files", QJsonArray{sourceAndTarget}); sendPacket(renameFilesRequest); receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("files-renamed")); error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); receivedReply = false; sendPacket(resolveMessage); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-resolved") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QJsonArray products = projectData.value("products").toArray(); bool hasOldFile = false; bool hasNewFile = false; for (const QJsonValue v : products) { const QJsonObject product = v.toObject(); const QString productName = product.value("full-display-name").toString(); const QJsonArray groups = product.value("groups").toArray(); for (const QJsonValue &v : groups) { const QJsonObject group = v.toObject(); const QString groupName = group.value("name").toString(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); for (const QJsonValue &v : sourceArtifacts) { const QString filePath = v.toObject().value("file-path").toString(); if (filePath.endsWith("lib.cpp")) { hasOldFile = true; } else if (filePath.endsWith("theLib.cpp")) { QCOMPARE(productName, QString("theLib")); QCOMPARE(groupName, QString("sources")); hasNewFile = true; } } } } QVERIFY(!hasOldFile); QVERIFY(hasNewFile); } } QVERIFY(receivedReply); receivedReply = false; compiledLib = false; sendPacket(buildRequest); while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QVERIFY(!receivedMessage.isEmpty()); const QString msgType = receivedMessage.value("type").toString(); if (msgType == "project-built") { receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); } else if ( msgType == "command-description" && receivedMessage.value("message").toString().contains("compiling theLib.cpp")) { compiledLib = true; } } QVERIFY(receivedReply); QVERIFY(compiledLib); // Get generated files. QJsonObject genFilesRequestPerFile; genFilesRequestPerFile.insert("source-file", QDir::currentPath() + "/main.cpp"); genFilesRequestPerFile.insert("tags", QJsonArray{QJsonValue("obj")}); QJsonObject genFilesRequestPerProduct; genFilesRequestPerProduct.insert("full-display-name", "theApp"); genFilesRequestPerProduct.insert("requests", QJsonArray({genFilesRequestPerFile})); QJsonObject genFilesRequest; genFilesRequest.insert("type", "get-generated-files-for-sources"); genFilesRequest.insert("products", QJsonArray({genFilesRequestPerProduct})); sendPacket(genFilesRequest); receivedReply = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("generated-files-for-sources")); const QJsonArray products = receivedMessage.value("products").toArray(); QCOMPARE(products.size(), 1); const QJsonArray results = products.first().toObject().value("results").toArray(); QCOMPARE(results.size(), 1); const QJsonObject result = results.first().toObject(); QCOMPARE(result.value("source-file"), QDir::currentPath() + "/main.cpp"); const QJsonArray generatedFiles = result.value("generated-files").toArray(); QCOMPARE(generatedFiles.count(), 1); QCOMPARE( QFileInfo(generatedFiles.first().toString()).fileName(), "main.cpp" + objectSuffix); receivedReply = true; } QVERIFY(receivedReply); // Release project. const QJsonObject releaseRequest{qMakePair(QString("type"), QJsonValue("release-project"))}; sendPacket(releaseRequest); receivedReply = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("project-released")); const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); receivedReply = true; } QVERIFY(receivedReply); // Get build graph info. QJsonObject loadProjectMessage; loadProjectMessage.insert("type", "resolve-project"); loadProjectMessage.insert("configuration-name", "my-config"); loadProjectMessage.insert("build-root", QDir::currentPath()); loadProjectMessage.insert("settings-dir", settings()->baseDirectory()); loadProjectMessage.insert("restore-behavior", "restore-only"); loadProjectMessage.insert("data-mode", "only-if-changed"); sendPacket(loadProjectMessage); receivedReply = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); if (receivedMessage.value("type") != "project-resolved") continue; receivedReply = true; const QJsonObject error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); const QString bgFilePath = QDir::currentPath() + '/' + relativeBuildGraphFilePath("my-config"); const QJsonObject projectData = receivedMessage.value("project-data").toObject(); QCOMPARE(projectData.value("build-graph-file-path").toString(), bgFilePath); QCOMPARE(projectData.value("overridden-properties"), overriddenValues); } QVERIFY(receivedReply); // Send unknown request. const QJsonObject unknownRequest({qMakePair(QString("type"), QJsonValue("blubb"))}); sendPacket(unknownRequest); receivedReply = false; while (!receivedReply) { receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type").toString(), QString("protocol-error")); receivedReply = true; } QVERIFY(receivedReply); QJsonObject quitRequest; quitRequest.insert("type", "quit"); sendPacket(quitRequest); QVERIFY(sessionProc.waitForFinished(3000)); } void TestBlackbox::radAfterIncompleteBuild_data() { QTest::addColumn("projectFileName"); QTest::newRow("Project with Rule") << "project_with_rule.qbs"; QTest::newRow("Project with Transformer") << "project_with_transformer.qbs"; } void TestBlackbox::radAfterIncompleteBuild() { QDir::setCurrent(testDataDir + "/rad-after-incomplete-build"); rmDirR(relativeBuildDir()); const QString projectFileName = "project_with_rule.qbs"; // Step 1: Have a directory where a file used to be. QbsRunParameters params(QStringList() << "-f" << projectFileName); QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile", "oldfile/newfile"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile/newfile", "newfile"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "newfile", "oldfile/newfile"); QCOMPARE(runQbs(params), 0); // Step 2: Have a file where a directory used to be. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile/newfile", "oldfile"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile", "newfile"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "newfile", "oldfile"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::subProfileChangeTracking() { QDir::setCurrent(testDataDir + "/subprofile-change-tracking"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile subProfile("qbs-autotests-subprofile", s.get()); subProfile.p.setValue("baseProfile", profileName()); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include1")); s->sync(); QCOMPARE(runQbs(), 0); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include2")); s->sync(); QbsRunParameters params; params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("main1.cpp")); QVERIFY(m_qbsStdout.contains("main2.cpp")); } void TestBlackbox::successiveChanges() { QDir::setCurrent(testDataDir + "/successive-changes"); QCOMPARE(runQbs(), 0); QbsRunParameters params("resolve", QStringList() << "products.theProduct.type:output,blubb"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); params.arguments << "project.version:2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QFile output(relativeProductBuildDir("theProduct") + "/output.out"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); const QByteArray version = output.readAll(); QCOMPARE(version.constData(), "2"); } void TestBlackbox::installedApp() { QDir::setCurrent(testDataDir + "/installed_artifact"); QCOMPARE(runQbs(), 0); const QByteArray output = m_qbsStdout; QVERIFY(regularFileExists( defaultInstallRoot + appendExecSuffix(QStringLiteral("/usr/bin/installedApp"), output))); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("qbs.installRoot:" + testDataDir + "/installed-app"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists( testDataDir + appendExecSuffix("/installed-app/usr/bin/installedApp", output))); QFile addedFile(defaultInstallRoot + QLatin1String("/blubb.txt")); QVERIFY(addedFile.open(QIODevice::WriteOnly)); addedFile.close(); QVERIFY(addedFile.exists()); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--clean-install-root")), 0); QVERIFY(regularFileExists( defaultInstallRoot + appendExecSuffix(QStringLiteral("/usr/bin/installedApp"), output))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/src/main.cpp"))); QVERIFY(!addedFile.exists()); // Check whether changing install parameters on the product causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installPrefix: \"/usr\"", "qbs.installPrefix: '/usr/local'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists( defaultInstallRoot + appendExecSuffix(QStringLiteral("/usr/local/bin/installedApp"), output))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/src/main.cpp"))); // Check whether changing install parameters on the artifact causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installDir: \"bin\"", "qbs.installDir: 'custom'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists( defaultInstallRoot + appendExecSuffix(QStringLiteral("/usr/local/custom/installedApp"), output))); // Check whether changing install parameters on a source file causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installDir: \"src\"", "qbs.installDir: 'source'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/source/main.cpp"))); // Check whether changing install parameters on the command line causes re-installation. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("qbs.installRoot:" + relativeBuildDir() + "/blubb"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeBuildDir() + "/blubb/usr/local/source/main.cpp")); // Check --no-install rmDirR(relativeBuildDir()); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--no-install")), 0); QCOMPARE(QDir(defaultInstallRoot).entryList(QDir::NoDotAndDotDot).size(), 0); // Check --no-build (with and without an existing build graph) QbsRunParameters params("install", QStringList() << "--no-build"); QCOMPARE(runQbs(params), 0); rmDirR(relativeBuildDir()); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Build graph not found"), m_qbsStderr.constData()); } void TestBlackbox::installDuplicates() { QDir::setCurrent(testDataDir + "/install-duplicates"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Cannot install files")); } void TestBlackbox::installDuplicatesNoError() { QDir::setCurrent(testDataDir + "/install-duplicates-no-error"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::installedSourceFiles() { QDir::setCurrent(testDataDir + "/installed-source-files"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/readme.txt"))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/main.cpp"))); } void TestBlackbox::toolLookup() { QbsRunParameters params(QStringLiteral("setup-toolchains"), QStringList("--help")); params.profile.clear(); QCOMPARE(runQbs(params), 0); } void TestBlackbox::topLevelSearchPath() { QDir::setCurrent(testDataDir + "/toplevel-searchpath"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("MyProduct"), m_qbsStderr.constData()); params.arguments << ("project.qbsSearchPaths:" + QDir::currentPath() + "/qbs-resources"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::checkProjectFilePath() { QDir::setCurrent(testDataDir + "/project_filepath_check"); QbsRunParameters params(QStringList("-f") << "project1.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(params), 0); params.arguments = QStringList("-f") << "project2.qbs"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("project file")); params.arguments = QStringList("-f") << "project2.qbs"; params.command = "resolve"; params.expectFailure = false; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("main2.cpp"), m_qbsStdout.constData()); } void TestBlackbox::checkTimestamps() { QDir::setCurrent(testDataDir + "/check-timestamps"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY(QFile::remove(relativeBuildGraphFilePath())); WAIT_FOR_NEW_TIMESTAMP(); touch("file.h"); QCOMPARE(runQbs(QStringList("--check-timestamps")), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::chooseModuleInstanceByPriorityAndVersion() { QFETCH(QString, idol); QFETCH(QStringList, expectedSubStrings); QFETCH(bool, expectSuccess); QDir::setCurrent(testDataDir + "/choose-module-instance"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList("modules.qbs.targetPlatform:" + idol)); params.expectFailure = !expectSuccess; if (expectSuccess) { QCOMPARE(runQbs(params), 0); } else { QVERIFY(runQbs(params) != 0); return; } const QString installRoot = relativeBuildDir() + "/install-root/"; QVERIFY(QFile::exists(installRoot + "/gerbil.txt")); QFile file(installRoot + "/gerbil.txt"); QVERIFY(file.open(QIODevice::ReadOnly)); const QString content = QString::fromUtf8(file.readAll()); for (const auto &str : expectedSubStrings) { if (content.contains(str)) continue; qDebug() << "content:" << content; qDebug() << "substring:" << str; QFAIL("missing substring"); } } void TestBlackbox::chooseModuleInstanceByPriorityAndVersion_data() { QTest::addColumn("idol"); QTest::addColumn("expectedSubStrings"); QTest::addColumn("expectSuccess"); QTest::newRow("ringo") << "Beatles" << QStringList() << false; QTest::newRow("ritchie1") << "Deep Purple" << QStringList{"slipped", "litchi", "ritchie"} << true; QTest::newRow("ritchie2") << "Rainbow" << QStringList{"slipped", "litchi", "ritchie"} << true; QTest::newRow("lord") << "Whitesnake" << QStringList{"chewed", "cord", "lord"} << true; } class TemporaryDefaultProfileRemover { public: TemporaryDefaultProfileRemover(qbs::Settings *settings) : m_settings(settings), m_defaultProfile(settings->defaultProfile()) { m_settings->remove(QStringLiteral("defaultProfile")); } ~TemporaryDefaultProfileRemover() { if (!m_defaultProfile.isEmpty()) m_settings->setValue(QStringLiteral("defaultProfile"), m_defaultProfile); } private: qbs::Settings *m_settings; const QString m_defaultProfile; }; void TestBlackbox::assembly() { QDir::setCurrent(testDataDir + "/assembly"); QCOMPARE(runQbs(QbsRunParameters("build", {"-p", "properties"})), 0); const QVariantMap properties = ([&]() { QFile propertiesFile(relativeProductBuildDir("properties") + "/properties.json"); if (propertiesFile.open(QIODevice::ReadOnly)) return QJsonDocument::fromJson(propertiesFile.readAll()).toVariant().toMap(); return QVariantMap{}; })(); QVERIFY(!properties.empty()); const auto toolchain = properties.value("qbs.toolchain").toStringList(); const auto architecture = properties.value("qbs.architecture").toString(); QVERIFY(!toolchain.empty()); const bool haveGcc = toolchain.contains("gcc"); const bool haveMSVC = toolchain.contains("msvc"); if (toolchain.contains("emscripten")) { QSKIP("Skipping test for emscripten"); } if (haveMSVC && (architecture.contains("arm"))) { QSKIP("Skipping test for MSVC ARM"); } QCOMPARE(runQbs(QbsRunParameters("build")), 0); QCOMPARE(m_qbsStdout.contains("assembling testa.s"), haveGcc); QCOMPARE(m_qbsStdout.contains("compiling testb.S"), haveGcc); QCOMPARE(m_qbsStdout.contains("compiling testc.sx"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtesta.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtestb.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtestc.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating testd.lib"), haveMSVC); } void TestBlackbox::autotestWithDependencies() { QDir::setCurrent(testDataDir + "/autotest-with-dependencies"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QStringList({"-p", "autotest-runner"})), 0); QVERIFY2(m_qbsStdout.contains("i am the test app") && m_qbsStdout.contains("i am the helper"), m_qbsStdout.constData()); } void TestBlackbox::autotestTimeout() { QFETCH(QStringList, resolveParams); QFETCH(bool, expectFailure); QFETCH(QString, errorDetails); QDir::setCurrent(testDataDir + "/autotest-timeout"); QbsRunParameters resolveParameters("resolve", resolveParams); QCOMPARE(runQbs(resolveParameters), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters buildParameters(QStringList({"-p", "autotest-runner"})); buildParameters.expectFailure = expectFailure; if (expectFailure) { QVERIFY(runQbs(buildParameters) != 0); QVERIFY( m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout") && m_qbsStderr.contains(errorDetails.toLocal8Bit())); } else QVERIFY(runQbs(buildParameters) == 0); } void TestBlackbox::autotestTimeout_data() { QTest::addColumn("resolveParams"); QTest::addColumn("expectFailure"); QTest::addColumn("errorDetails"); QTest::newRow("no timeout") << QStringList() << false << QString(); QTest::newRow("timeout on test") << QStringList({"products.testApp.autotest.timeout:2"}) << true << QString("testApp"); QTest::newRow("timeout on runner") << QStringList({"products.autotest-runner.timeout:2"}) << true << QString("testApp"); } void TestBlackbox::autotests_data() { QTest::addColumn("evilPropertySpec"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("missing arguments") << QString("products.test1.autotest.arguments:[]") << QByteArray("This test needs exactly one argument"); QTest::newRow("missing working dir") << QString("products.test2.autotest.workingDir:''") << QByteArray("Test resource not found"); QTest::newRow("missing flaky specifier") << QString("products.test3.autotest.allowFailure:false") << QByteArray("I am an awful test"); QTest::newRow("everything's fine") << QString() << QByteArray(); } void TestBlackbox::autotests() { QDir::setCurrent(testDataDir + "/autotests"); QFETCH(QString, evilPropertySpec); QFETCH(QByteArray, expectedErrorMessage); QbsRunParameters resolveParams("resolve"); if (!evilPropertySpec.isEmpty()) resolveParams.arguments << evilPropertySpec; QCOMPARE(runQbs(resolveParams), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters testParams(QStringList{"-p", "autotest-runner"}); if (!evilPropertySpec.isEmpty()) testParams.expectFailure = true; QCOMPARE(runQbs(testParams) == 0, !testParams.expectFailure); if (testParams.expectFailure) { QVERIFY2(m_qbsStderr.contains(expectedErrorMessage), m_qbsStderr.constData()); return; } QVERIFY2(m_qbsStdout.contains("running test test1") && m_qbsStdout.contains("running test test2") && m_qbsStdout.contains("running test test3"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.count("PASS"), 2); QCOMPARE(m_qbsStderr.count("FAIL"), 1); } void TestBlackbox::auxiliaryInputsFromDependencies() { QDir::setCurrent(testDataDir + "/aux-inputs-from-deps"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating dummy.out"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.dep.sleep:false"))), 0); WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating dummy.out"), m_qbsStdout.constData()); } void TestBlackbox::explicitlyDependsOn() { QFETCH(QString, useExplicitlyDependsOn); QFETCH(QString, useExplicitlyDependsOnFromDependencies); QFETCH(QString, useModule); QFETCH(bool, expectFailure); QDir::setCurrent(testDataDir + "/explicitly-depends-on"); QbsRunParameters params("", QStringList("products.prod1.useExplicitlyDependsOn:" + useExplicitlyDependsOn) << "products.prod1.useExplicitlyDependsOnFromDependencies:" + useExplicitlyDependsOnFromDependencies << "projects.proj1.useModule:" + useModule); params.expectFailure = expectFailure; rmDirR(relativeBuildDir()); if (params.expectFailure) { // Build should fail because a rule cycle is created within the product when // explicitlyDependsOn is used. QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cycle detected in rule dependencies"), m_qbsStderr.constData()); } else { // When explicitlyDependsOnFromDependencies is used, build should succeed due to the // "final" tag being pulled in from dependencies. QCOMPARE(runQbs(params), 0); if (useModule == QLatin1String("false")) { QVERIFY2(m_qbsStdout.contains("creating 'product-fish.txt' tagged with 'final'"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Using explicitlyDependsOnArtifact: product-fish.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step1 -> step2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step2 -> step3"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step3 -> final"), m_qbsStdout.constData()); } else { QVERIFY2(!m_qbsStdout.contains("creating 'product-fish.txt' tagged with 'final'"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Using explicitlyDependsOnArtifact: module-fish.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step1 -> step2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step2 -> step3"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step3 -> final"), m_qbsStdout.constData()); } } } void TestBlackbox::explicitlyDependsOn_data() { QTest::addColumn("useExplicitlyDependsOn"); QTest::addColumn("useExplicitlyDependsOnFromDependencies"); QTest::addColumn("useModule"); QTest::addColumn("expectFailure"); QTest::newRow("useExplicitlyDependsOn -> causes cycle") << "true" << "false" << "false" << true; QTest::newRow("explicitlyDependsOnFromDependencies + product") << "false" << "true" << "false" << false; QTest::newRow("explicitlyDependsOnFromDependencies + module + filesAreTargets") << "false" << "true" << "true" << false; } static bool haveMakeNsis() { QStringList regKeys; regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS") << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); for (const QString &key : std::as_const(regKeys)) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QStringLiteral(".")).toString(); if (!str.isEmpty()) paths.prepend(str); } bool haveMakeNsis = false; for (const QString &path : std::as_const(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/makensis")))) { haveMakeNsis = true; break; } } return haveMakeNsis; } void TestBlackbox::nsis() { if (!haveMakeNsis()) { QSKIP("makensis is not installed"); return; } QDir::setCurrent(testDataDir + "/nsis"); QVERIFY(runQbs() == 0); const bool targetIsWindows = m_qbsStdout.contains("is Windows: true"); const bool targetIsNotWindows = m_qbsStdout.contains("is Windows: false"); QCOMPARE(targetIsWindows, !targetIsNotWindows); QCOMPARE(m_qbsStdout.contains("compiling hello.nsi"), targetIsWindows); QCOMPARE( m_qbsStdout.contains("SetCompressor ignored due to previous call with the /FINAL switch"), targetIsWindows); QVERIFY(!QFile::exists(defaultInstallRoot + "/you-should-not-see-a-file-with-this-name.exe")); } void TestBlackbox::nsisDependencies() { if (!haveMakeNsis()) { QSKIP("makensis is not installed"); return; } QDir::setCurrent(testDataDir + "/nsisDependencies"); QCOMPARE(runQbs(), 0); const bool targetIsWindows = m_qbsStdout.contains("is Windows: true"); const bool targetIsNotWindows = m_qbsStdout.contains("is Windows: false"); QCOMPARE(targetIsWindows, !targetIsNotWindows); QCOMPARE(m_qbsStdout.contains("compiling hello.nsi"), targetIsWindows); } void TestBlackbox::outOfDateMarking() { QDir::setCurrent(testDataDir + "/out-of-date-marking"); for (int i = 0; i < 25; ++i) { QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating myheader.h"), qPrintable(QString::number(i))); QVERIFY2(m_qbsStdout.contains("compiling main.c"), qPrintable(QString::number(i))); } } void TestBlackbox::enableExceptions() { QFETCH(QString, file); QFETCH(bool, enable); QFETCH(bool, expectSuccess); QDir::setCurrent(testDataDir + QStringLiteral("/enableExceptions")); QbsRunParameters params; params.arguments = QStringList() << "-f" << file << (QStringLiteral("modules.cpp.enableExceptions:") + (enable ? "true" : "false")); params.expectFailure = !expectSuccess; rmDirR(relativeBuildDir()); if (!params.expectFailure) QCOMPARE(runQbs(params), 0); else QVERIFY(runQbs(params) != 0); } void TestBlackbox::enableExceptions_data() { QTest::addColumn("file"); QTest::addColumn("enable"); QTest::addColumn("expectSuccess"); QTest::newRow("no exceptions, enabled") << "none.qbs" << true << true; QTest::newRow("no exceptions, disabled") << "none.qbs" << false << true; QTest::newRow("C++ exceptions, enabled") << "exceptions.qbs" << true << true; QTest::newRow("C++ exceptions, disabled") << "exceptions.qbs" << false << false; if (HostOsInfo::isMacosHost()) { QTest::newRow("Objective-C exceptions, enabled") << "exceptions-objc.qbs" << true << true; QTest::newRow("Objective-C exceptions in Objective-C++ source, enabled") << "exceptions-objcpp.qbs" << true << true; QTest::newRow("C++ exceptions in Objective-C++ source, enabled") << "exceptions-objcpp-cpp.qbs" << true << true; QTest::newRow("Objective-C, disabled") << "exceptions-objc.qbs" << false << false; QTest::newRow("Objective-C exceptions in Objective-C++ source, disabled") << "exceptions-objcpp.qbs" << false << false; QTest::newRow("C++ exceptions in Objective-C++ source, disabled") << "exceptions-objcpp-cpp.qbs" << false << false; } } void TestBlackbox::enableRtti() { QDir::setCurrent(testDataDir + QStringLiteral("/enableRtti")); QbsRunParameters params; params.arguments = QStringList() << "modules.cpp.enableRtti:true"; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isMacosHost()) { params.arguments = QStringList() << "modules.cpp.enableRtti:true" << "project.treatAsObjcpp:true"; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); } params.expectFailure = true; params.arguments = QStringList() << "modules.cpp.enableRtti:false"; rmDirR(relativeBuildDir()); QVERIFY(runQbs(params) != 0); if (HostOsInfo::isMacosHost()) { params.arguments = QStringList() << "modules.cpp.enableRtti:false" << "project.treatAsObjcpp:true"; rmDirR(relativeBuildDir()); QVERIFY(runQbs(params) != 0); } } void TestBlackbox::enableTimeTrace() { QDir::setCurrent(testDataDir + "/enable-time-trace"); rmDirR(relativeBuildDir()); QbsRunParameters params("resolve"); params.arguments << "modules.cpp.enableTimeTrace:true"; QCOMPARE(runQbs(params), 0); const bool supportsTimeTrace = m_qbsStdout.contains("supports time trace: true"); const bool notSupported = m_qbsStdout.contains("supports time trace: false"); QVERIFY(supportsTimeTrace != notSupported); if (notSupported) QSKIP("Time trace only supported for Clang toolchain"); QCOMPARE(runQbs(), 0); const QString filePath = defaultInstallRoot + "/share/enable-time-trace/" + "/main.cpp.time_trace.json"; QVERIFY2(regularFileExists(filePath), qPrintable(filePath)); } void TestBlackbox::envMerging() { QDir::setCurrent(testDataDir + "/env-merging"); QbsRunParameters params("resolve"); QString pathVal = params.environment.value("PATH"); pathVal.prepend(HostOsInfo::pathListSeparator()).prepend("/opt/blackbox/bin"); const QString keyName = HostOsInfo::isWindowsHost() ? "pATh" : "PATH"; params.environment.insert(keyName, pathVal); QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(QByteArray("PATH=/opt/tool/bin") + HostOsInfo::pathListSeparator().toLatin1()) && m_qbsStdout.contains(HostOsInfo::pathListSeparator().toLatin1() + QByteArray("/opt/blackbox/bin")), m_qbsStdout.constData()); } void TestBlackbox::envNormalization() { QDir::setCurrent(testDataDir + "/env-normalization"); QbsRunParameters params; params.environment.insert("myvar", "x"); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isWindowsHost()) QVERIFY2(m_qbsStdout.contains("\"MYVAR\":\"x\""), m_qbsStdout.constData()); else QVERIFY2(m_qbsStdout.contains("\"myvar\":\"x\""), m_qbsStdout.constData()); } void TestBlackbox::generatedArtifactAsInputToDynamicRule() { QDir::setCurrent(testDataDir + "/generated-artifact-as-input-to-dynamic-rule"); QCOMPARE(runQbs(), 0); const QString oldFile = relativeProductBuildDir("p") + "/old.txt"; QVERIFY2(regularFileExists(oldFile), qPrintable(oldFile)); WAIT_FOR_NEW_TIMESTAMP(); QFile inputFile("input.txt"); QVERIFY2(inputFile.open(QIODevice::WriteOnly), qPrintable(inputFile.errorString())); inputFile.resize(0); inputFile.write("new.txt"); inputFile.close(); QCOMPARE(runQbs(), 0); QVERIFY2(!regularFileExists(oldFile), qPrintable(oldFile)); const QString newFile = relativeProductBuildDir("p") + "/new.txt"; QVERIFY2(regularFileExists(newFile), qPrintable(oldFile)); QVERIFY2(m_qbsStdout.contains("generating"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("generating"), m_qbsStdout.constData()); } void TestBlackbox::generateLinkerMapFile() { QDir::setCurrent(testDataDir + "/generate-linker-map-file"); QCOMPARE(runQbs(), 0); const bool isUsed = m_qbsStdout.contains("use test: true"); const bool isNotUsed = m_qbsStdout.contains("use test: false"); QVERIFY(isUsed != isNotUsed); if (isUsed) { QVERIFY(QFile::exists(relativeProductBuildDir("app-map") + "/app-map.map")); QVERIFY(!QFile::exists(relativeProductBuildDir("app-nomap") + "/app-nomap.map")); QVERIFY(!QFile::exists(relativeProductBuildDir("app-nomap-default") + "/app-nomap-default.map")); } else { QSKIP("Unsupported toolchain. Skipping."); } } void TestBlackbox::generator() { QFETCH(QString, inputFile); QFETCH(QStringList, toBeCompiled); QDir::setCurrent(testDataDir + "/generator"); if (!inputFile.isEmpty()) { WAIT_FOR_NEW_TIMESTAMP(); QFile input(inputFile); QFile output("input.txt"); QVERIFY2(!output.exists() || output.remove(), qPrintable(output.errorString())); QVERIFY2(input.copy(output.fileName()), qPrintable(input.errorString())); touch(output.fileName()); } QCOMPARE(runQbs(), 0); QCOMPARE(toBeCompiled.contains("main.cpp"), m_qbsStdout.contains("compiling main.cpp")); QCOMPARE(toBeCompiled.contains("file1.cpp"), m_qbsStdout.contains("compiling file1.cpp")); QCOMPARE(toBeCompiled.contains("file2.cpp"), m_qbsStdout.contains("compiling file2.cpp")); } void TestBlackbox::generator_data() { QTest::addColumn("inputFile"); QTest::addColumn("toBeCompiled"); QTest::newRow("both") << "input.both.txt" << QStringList{"main.cpp", "file1.cpp", "file2.cpp"}; QTest::newRow("file1") << "input.file1.txt" << QStringList{"file1.cpp"}; QTest::newRow("file2") << "input.file2.txt" << QStringList{"file2.cpp"}; QTest::newRow("none") << "input.none.txt" << QStringList(); QTest::newRow("both again") << "input.both.txt" << QStringList{"file1.cpp", "file2.cpp"}; QTest::newRow("no update") << QString() << QStringList(); } void TestBlackbox::nodejs() { const SettingsPtr s = settings(); qbs::Profile p(profileName(), s.get()); int status; findNodejs(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + QLatin1String("/nodejs")); status = runQbs(); if (p.value("nodejs.toolchainInstallPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("toolchainInstallPath")) { QSKIP("nodejs.toolchainInstallPath not set and automatic detection failed"); } if (p.value("nodejs.packageManagerPrefixPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("nodejs.packageManagerPrefixPath")) { QSKIP("nodejs.packageManagerFilePath not set and automatic detection failed"); } if (p.value("nodejs.interpreterFilePath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("interpreterPath")) { QSKIP("nodejs.interpreterFilePath not set and automatic detection failed"); } if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(status, 0); QbsRunParameters params; params.command = QLatin1String("run"); QCOMPARE(runQbs(params), 0); QVERIFY((bool)m_qbsStdout.contains("hello world")); QVERIFY(regularFileExists(relativeProductBuildDir("hello") + "/hello.js")); } void TestBlackbox::typescript() { if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) QSKIP("Skip this test when running on GitHub"); if (qEnvironmentVariableIsSet("EMSDK")) QSKIP("Skip this test when running with wasm"); const SettingsPtr s = settings(); qbs::Profile p(profileName(), s.get()); int status; findTypeScript(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + QLatin1String("/typescript")); QbsRunParameters params; params.expectFailure = true; status = runQbs(params); if (p.value("typescript.toolchainInstallPath").toString().isEmpty() && status != 0) { if (m_qbsStderr.contains("Path\" must be specified")) QSKIP("typescript probe failed"); if (m_qbsStderr.contains("typescript.toolchainInstallPath")) QSKIP("typescript.toolchainInstallPath not set and automatic detection failed"); if (m_qbsStderr.contains("nodejs.interpreterFilePath")) QSKIP("nodejs.interpreterFilePath not set and automatic detection failed"); } if (status != 0) qDebug() << m_qbsStderr; QCOMPARE(status, 0); params.expectFailure = false; params.command = QStringLiteral("run"); params.arguments = QStringList() << "-p" << "animals"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/animals.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/extra.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js")); } void TestBlackbox::undefinedTargetPlatform() { QDir::setCurrent(testDataDir + "/undefined-target-platform"); QCOMPARE(runQbs(), 0); } void TestBlackbox::importInPropertiesCondition() { QDir::setCurrent(testDataDir + "/import-in-properties-condition"); QCOMPARE(runQbs(), 0); } void TestBlackbox::importSearchPath() { QDir::setCurrent(testDataDir + "/import-searchpath"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling somefile.cpp"), m_qbsStdout.constData()); } void TestBlackbox::importingProduct() { QDir::setCurrent(testDataDir + "/importing-product"); QCOMPARE(runQbs(), 0); } void TestBlackbox::importsConflict() { QDir::setCurrent(testDataDir + "/imports-conflict"); QCOMPARE(runQbs(), 0); } void TestBlackbox::includeLookup() { QDir::setCurrent(testDataDir + "/includeLookup"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("definition.."), m_qbsStdout.constData()); } void TestBlackbox::inputTagsChangeTracking_data() { QTest::addColumn("generateInput"); QTest::newRow("source artifact") << QString("no"); QTest::newRow("generated artifact (static)") << QString("static"); QTest::newRow("generated artifact (dynamic)") << QString("dynamic"); } void TestBlackbox::inputTagsChangeTracking() { QDir::setCurrent(testDataDir + "/input-tags-change-tracking"); const QString xOut = QDir::currentPath() + '/' + relativeProductBuildDir("p") + "/x.out"; const QString yOut = QDir::currentPath() + '/' + relativeProductBuildDir("p") + "/y.out"; QFETCH(QString, generateInput); const QbsRunParameters resolveParams("resolve", QStringList("products.p.generateInput:" + generateInput)); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("generating input.txt") == (generateInput == "static")); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: [\"txt\", \"empty\"]", "Tags: \"txt\""); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: \"txt\"", "Tags: [\"txt\", \"y\"]"); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: [\"txt\", \"y\"]", "Tags: [\"txt\", \"empty\"]"); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); } void TestBlackbox::outputArtifactAutoTagging() { QDir::setCurrent(testDataDir + QLatin1String("/output-artifact-auto-tagging")); QCOMPARE(runQbs(), 0); QVERIFY( regularFileExists(relativeExecutableFilePath("output-artifact-auto-tagging", m_qbsStdout))); } void TestBlackbox::outputRedirection() { QDir::setCurrent(testDataDir + "/output-redirection"); QCOMPARE(runQbs(), 0); TEXT_FILE_COMPARE("output.txt", relativeProductBuildDir("the-product") + "/output.txt"); TEXT_FILE_COMPARE("output.bin", relativeProductBuildDir("the-product") + "/output.bin"); } void TestBlackbox::wildCardsAndRules() { QDir::setCurrent(testDataDir + "/wildcards-and-rules"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("creating output artifact")); QFile output(relativeProductBuildDir("wildcards-and-rules") + "/test.mytype"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 1); output.close(); // Add input. WAIT_FOR_NEW_TIMESTAMP(); touch("input2.inp"); QbsRunParameters params; params.expectFailure = true; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("creating output artifact")); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 2); output.close(); // Add "explicitlyDependsOn". WAIT_FOR_NEW_TIMESTAMP(); touch("dep.dep"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("creating output artifact")); // Add nothing. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("creating output artifact")); } void TestBlackbox::wildCardsAndChangeTracking_data() { QTest::addColumn("dirToModify"); QTest::addColumn("expectReResolve"); QTest::newRow("root path") << QString(".") << false; QTest::newRow("dir with recursive match") << QString("recursive1") << false; QTest::newRow("non-recursive base dir") << QString("nonrecursive") << true; QTest::newRow("empty base dir with file patterns") << QString("nonrecursive/empty") << true; } void TestBlackbox::wildCardsAndChangeTracking() { QFETCH(QString, dirToModify); QFETCH(bool, expectReResolve); const QString srcDir = testDataDir + "/wildcards-and-change-tracking"; QDir::setCurrent(srcDir); rmDirR("default"); QDir::current().mkdir("nonrecursive/empty"); QCOMPARE(runQbs({"resolve"}), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch(dirToModify + "/blubb.txt"); QCOMPARE(runQbs({"resolve"}), 0); QCOMPARE(m_qbsStdout.contains("Resolving"), expectReResolve); } void TestBlackbox::loadableModule() { QDir::setCurrent(testDataDir + QLatin1String("/loadablemodule")); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("foo = 42"), m_qbsStdout.constData()); } void TestBlackbox::localDeployment() { QDir::setCurrent(testDataDir + "/localDeployment"); QFile main("main.cpp"); QVERIFY(main.open(QIODevice::ReadOnly)); QByteArray content = main.readAll(); content.replace('\r', ""); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(content), m_qbsStdout.constData()); } void TestBlackbox::makefileGenerator() { QDir::setCurrent(testDataDir + "/makefile-generator"); const QbsRunParameters params("generate", QStringList{"-g", "makefile"}); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isWindowsHost()) return; if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QProcess make; make.setWorkingDirectory(QDir::currentPath() + '/' + relativeBuildDir()); const QString customInstallRoot = QDir::currentPath() + "/my-install-root"; make.start("make", QStringList{"INSTALL_ROOT=" + customInstallRoot, "install"}); QVERIFY(waitForProcessSuccess(make)); QVERIFY(QFile::exists(relativeExecutableFilePath("the app", m_qbsStdout))); QVERIFY(!QFile::exists(relativeBuildGraphFilePath())); QProcess app; app.start(customInstallRoot + "/usr/local/bin/the app", QStringList()); QVERIFY(waitForProcessSuccess(app)); const QByteArray appStdout = app.readAllStandardOutput(); QVERIFY2(appStdout.contains("Hello, World!"), appStdout.constData()); make.start("make", QStringList("clean")); QVERIFY(waitForProcessSuccess(make)); QVERIFY(!QFile::exists(relativeExecutableFilePath("the app", m_qbsStdout))); } void TestBlackbox::maximumCLanguageVersion() { QDir::setCurrent(testDataDir + "/maximum-c-language-version"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); const bool isMsvc = m_qbsStdout.contains("is msvc: true"); if (isMsvc && m_qbsStdout.contains("is old msvc: true")) QSKIP("MSVC supports setting the C language version only from version 16.8, and Clang from version 13."); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c11") || m_qbsStdout.contains("c1x"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); if (isMsvc) QVERIFY2(!m_qbsStdout.contains("c11"), m_qbsStdout.constData()); else QVERIFY2(m_qbsStdout.contains("c99"), m_qbsStdout.constData()); } void TestBlackbox::maximumCxxLanguageVersion() { QDir::setCurrent(testDataDir + "/maximum-cxx-language-version"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2( m_qbsStdout.contains("c++26") || m_qbsStdout.contains("c++2c") || m_qbsStdout.contains("c++latest"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c++14") || m_qbsStdout.contains("c++1y"), m_qbsStdout.constData()); } void TestBlackbox::minimumSystemVersion() { rmDirR(relativeBuildDir()); QDir::setCurrent(testDataDir + "/minimumSystemVersion"); QFETCH(QString, file); QFETCH(QString, output); QbsRunParameters params({ "-f", file + ".qbs" }); params.command = "resolve"; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); params.command = "run"; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("Unsupported compiler")) QSKIP("Unsupported compiler"); if (!m_qbsStdout.contains(output.toUtf8())) { qDebug() << "expected output:" << qPrintable(output); qDebug() << "actual output:" << m_qbsStdout.constData(); } QVERIFY(m_qbsStdout.contains(output.toUtf8())); } static qbs::Version fromMinimumDeploymentTargetValue(int v, bool isMacOS) { if (isMacOS && v < 100000) return qbs::Version(v / 100, v / 10 % 10, v % 10); return qbs::Version(v / 10000, v / 100 % 100, v % 100); } static int toMinimumDeploymentTargetValue(const qbs::Version &v, bool isMacOS) { if (isMacOS && v < qbs::Version(10, 10)) return (v.majorVersion() * 100) + (v.minorVersion() * 10) + v.patchLevel(); return (v.majorVersion() * 10000) + (v.minorVersion() * 100) + v.patchLevel(); } static qbs::Version defaultClangMinimumDeploymentTarget() { QProcess process; process.start("/usr/bin/xcrun", {"-sdk", "macosx", "clang++", "-target", "x86_64-apple-macosx-macho", "-dM", "-E", "-x", "objective-c++", "/dev/null"}); if (waitForProcessSuccess(process)) { const auto lines = process.readAllStandardOutput().split('\n'); for (const auto &line : lines) { static const QByteArray prefix = "#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ "; if (line.startsWith(prefix)) { bool ok = false; int v = line.mid(prefix.size()).trimmed().toInt(&ok); if (ok) return fromMinimumDeploymentTargetValue(v, true); break; } } } return qbs::Version(); } void TestBlackbox::minimumSystemVersion_data() { QTest::addColumn("file"); QTest::addColumn("output"); // Don't check for the full "version X.Y.Z\n" on macOS as some older versions of otool don't // show the patch version. Instead, simply check for "version X.Y" with no trailing \n. const QString unspecified = []() -> QString { if (HostOsInfo::isMacosHost()) { const auto v = defaultClangMinimumDeploymentTarget(); auto result = "__MAC_OS_X_VERSION_MIN_REQUIRED=" + QString::number(toMinimumDeploymentTargetValue(v, true)); if (v >= qbs::Version(10, 14)) result += "\nminos "; else result += "\nversion "; result += QString::number(v.majorVersion()) + "." + QString::number(v.minorVersion()); return result; } if (HostOsInfo::isWindowsHost()) return "WINVER is not defined\n"; return ""; }(); const QString specific = []() -> QString { if (HostOsInfo::isMacosHost()) { if (HostOsInfo::hostOSArchitecture() == "arm64") return "__MAC_OS_X_VERSION_MIN_REQUIRED=110000\nminos 11.0\n"; else return "__MAC_OS_X_VERSION_MIN_REQUIRED=1070\nversion 10.7\n"; } if (HostOsInfo::isWindowsHost()) return "WINVER=1538\n6.02 operating system version\n6.02 subsystem version\n"; return ""; }(); QTest::newRow("unspecified") << "unspecified" << unspecified; QTest::newRow("unspecified-forced") << "unspecified-forced" << unspecified; if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacosHost()) QTest::newRow("specific") << "specific" << specific; if (HostOsInfo::isWindowsHost()) QTest::newRow("fakewindows") << "fakewindows" << "WINVER=1283\n5.03 operating system " "version\n5.03 subsystem version\n"; if (HostOsInfo::isMacosHost()) { if (HostOsInfo::hostOSArchitecture() == "arm64") { QTest::newRow("macappstore") << "macappstore" << "__MAC_OS_X_VERSION_MIN_REQUIRED=110000"; } else { QTest::newRow("macappstore") << "macappstore" << "__MAC_OS_X_VERSION_MIN_REQUIRED=1071"; } } } void TestBlackbox::missingBuildGraph() { QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); QDir::setCurrent(tmpDir.path()); QFETCH(QString, configName); const QStringList commands({"clean", "dump-nodes-tree", "status", "update-timestamps"}); const QString actualConfigName = configName.isEmpty() ? QString("default") : configName; QbsRunParameters params; params.expectFailure = true; params.arguments << QLatin1String("config:") + actualConfigName; for (const QString &command : std::as_const(commands)) { params.command = command; QVERIFY2(runQbs(params) != 0, qPrintable(command)); const QString expectedErrorMessage = QString("Build graph not found for " "configuration '%1'").arg(actualConfigName); if (!m_qbsStderr.contains(expectedErrorMessage.toLocal8Bit())) { qDebug() << command; qDebug() << expectedErrorMessage; qDebug() << m_qbsStderr; QFAIL("unexpected error message"); } } } void TestBlackbox::missingBuildGraph_data() { QTest::addColumn("configName"); QTest::newRow("implicit config name") << QString(); QTest::newRow("explicit config name") << QString("customConfig"); } void TestBlackbox::missingDependency() { QDir::setCurrent(testDataDir + "/missing-dependency"); QbsRunParameters params; params.expectFailure = true; params.arguments << "-p" << "theApp"; QVERIFY(runQbs(params) != 0); QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "-p" << "theDep")), 0); params.expectFailure = false; params.arguments << "-vv"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStderr.contains("false positive")); } void TestBlackbox::missingProjectFile() { QDir::setCurrent(testDataDir + "/missing-project-file/empty-dir"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("No project file given and none found in current directory"), m_qbsStderr.constData()); QDir::setCurrent(testDataDir + "/missing-project-file"); params.arguments << "-f" << "empty-dir"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("No project file found in directory"), m_qbsStderr.constData()); params.arguments = QStringList() << "-f" << "ambiguous-dir"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("More than one project file found in directory"), m_qbsStderr.constData()); params.expectFailure = false; params.arguments = QStringList() << "-f" << "project-dir"; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("project-dir/file.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::missingOverridePrefix() { QDir::setCurrent(testDataDir + "/missing-override-prefix"); QbsRunParameters params; params.expectFailure = true; params.arguments << "blubb.whatever:false"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Property override key 'blubb.whatever' not understood"), m_qbsStderr.constData()); } void TestBlackbox::moduleConditions() { QDir::setCurrent(testDataDir + "/module-conditions"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("loaded m1"), 1); QCOMPARE(m_qbsStdout.count("loaded m2"), 2); QCOMPARE(m_qbsStdout.count("loaded m3"), 1); QCOMPARE(m_qbsStdout.count("loaded m4"), 1); } void TestBlackbox::movedFileDependency() { QDir::setCurrent(testDataDir + "/moved-file-dependency"); const QString subdir2 = QDir::currentPath() + "/subdir2"; QVERIFY(QDir::current().mkdir(subdir2)); const QString oldHeaderFilePath = QDir::currentPath() + "/subdir1/theheader.h"; const QString newHeaderFilePath = subdir2 + "/theheader.h"; QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QFile f(oldHeaderFilePath); QVERIFY2(f.rename(newHeaderFilePath), qPrintable(f.errorString())); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); f.setFileName(newHeaderFilePath); QVERIFY2(f.rename(oldHeaderFilePath), qPrintable(f.errorString())); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::msvcAsmLinkerFlags() { QDir::setCurrent(testDataDir + "/msvc-asm-flags"); QCOMPARE(runQbs(), 0); } void TestBlackbox::badInterpreter() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + QLatin1String("/badInterpreter")); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params("run"); params.expectFailure = true; const QRegularExpression reNoSuchFileOrDir("bad interpreter:.* No such file or directory"); const QRegularExpression rePermissionDenied("bad interpreter:.* Permission denied"); params.arguments = QStringList() << "-p" << "script-interp-missing"; QCOMPARE(runQbs(params), 1); QString strerr = QString::fromLocal8Bit(m_qbsStderr); QVERIFY2(strerr.contains(reNoSuchFileOrDir), m_qbsStderr); params.arguments = QStringList() << "-p" << "script-interp-noexec"; QCOMPARE(runQbs(params), 1); strerr = QString::fromLocal8Bit(m_qbsStderr); QVERIFY2(strerr.contains(reNoSuchFileOrDir) || strerr.contains(rePermissionDenied) || strerr.contains("script-noexec: bad interpreter: execve: Exec format error"), qPrintable(strerr)); params.arguments = QStringList() << "-p" << "script-noexec"; QCOMPARE(runQbs(params), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList() << "-p" << "script-ok")), 0); } void TestBlackbox::bomSources() { QDir::setCurrent(testDataDir + "/bom-sources"); const bool success = runQbs() == 0; if (!success) QSKIP("Assuming compiler cannot deal with byte order mark"); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); touch("theheader.h"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::boolValueInProfile() { QbsRunParameters params("config"); params.arguments << "profiles.boolReadTest.qbs.debugInformation" << "true"; QCOMPARE(runQbs(params), 0); QDir::setCurrent(testDataDir + "/bool-value-in-profile"); params.command = "build"; params.arguments.clear(); params.profile = "boolReadTest"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::buildDataOfDisabledProduct() { QDir::setCurrent(testDataDir + QLatin1String("/build-data-of-disabled-product")); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); // Touch a source file, disable the product, rebuild the project, verify nothing happens. WAIT_FOR_NEW_TIMESTAMP(); touch("test.cpp"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.condition:false"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); // Enable the product again, rebuild the project, verify that only the changed source file // is rebuilt. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.condition:true"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); } void TestBlackbox::qbsVersion() { const auto v = qbs::LanguageInfo::qbsVersion(); QDir::setCurrent(testDataDir + QLatin1String("/qbsVersion")); QbsRunParameters params; params.arguments = QStringList() << "project.qbsVersion:" + v.toString() << "project.qbsVersionMajor:" + QString::number(v.majorVersion()) << "project.qbsVersionMinor:" + QString::number(v.minorVersion()) << "project.qbsVersionPatch:" + QString::number(v.patchLevel()); QCOMPARE(runQbs(params), 0); params.arguments.push_back("project.qbsVersionPatch:" + QString::number(v.patchLevel() + 1)); params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::transitiveInvalidDependencies() { QDir::setCurrent(testDataDir + "/transitive-invalid-dependencies"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("b.present = false"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("c.present = true"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("d.present = false"), m_qbsStdout); } void TestBlackbox::transitiveOptionalDependencies() { QDir::setCurrent(testDataDir + "/transitive-optional-dependencies"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::groupsInModules() { QDir::setCurrent(testDataDir + "/groups-in-modules"); QCOMPARE(runQbs({"resolve"}), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling rock.coal to rock.diamond")); QVERIFY(m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); QVERIFY(m_qbsStdout.contains("compiling helper2.c")); QVERIFY(!m_qbsStdout.contains("compiling helper3.c")); QVERIFY(m_qbsStdout.contains("compiling helper4.c")); QVERIFY(m_qbsStdout.contains("compiling helper5.c")); QVERIFY(!m_qbsStdout.contains("compiling helper6.c")); QVERIFY(m_qbsStdout.contains("compiling helper7.c")); QVERIFY(m_qbsStdout.contains("compiling helper8.c")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling rock.coal to rock.diamond")); QVERIFY(!m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); WAIT_FOR_NEW_TIMESTAMP(); touch("modules/helper/diamondc.c"); waitForFileUnlock(); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling diamondc.c")); QVERIFY(m_qbsStdout.contains("compiling rock.coal to rock.diamond")); QVERIFY(m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); QVERIFY(regularFileExists(relativeProductBuildDir("groups-in-modules") + "/rock.diamond")); QFile output(relativeProductBuildDir("groups-in-modules") + "/rock.diamond"); QVERIFY(output.open(QIODevice::ReadOnly)); QCOMPARE(output.readAll().trimmed(), QByteArray("diamond")); } void TestBlackbox::grpc_data() { QTest::addColumn("projectFile"); QTest::addColumn("arguments"); QTest::addColumn("hasModules"); QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); // on macOS, openSSL is hidden from pkg-config by default if (qbs::Internal::HostOsInfo::isMacosHost()) { pkgConfigArgs << "moduleProviders.qbspkgconfig.extraPaths:/usr/local/opt/openssl@1.1/lib/pkgconfig"; } QTest::newRow("cpp-pkgconfig") << QString("grpc_cpp.qbs") << pkgConfigArgs << true; QStringList conanArgs( {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); QTest::newRow("cpp-conan") << QString("grpc_cpp.qbs") << conanArgs << true; } void TestBlackbox::grpc() { QDir::setCurrent(testDataDir + "/grpc"); QFETCH(QString, projectFile); QFETCH(QStringList, arguments); QFETCH(bool, hasModules); rmDirR(relativeBuildDir()); if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { if (!prepareAndRunConan()) QSKIP("conan is not prepared, check messages above"); } QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile}); resolveParams.arguments << arguments; QCOMPARE(runQbs(resolveParams), 0); const bool withGrpc = m_qbsStdout.contains("has grpc: true"); const bool withoutGrpc = m_qbsStdout.contains("has grpc: false"); QVERIFY2(withGrpc || withoutGrpc, m_qbsStdout.constData()); if (withoutGrpc) QSKIP("grpc module not present"); const bool hasMods = m_qbsStdout.contains("has modules: true"); const bool dontHaveMods = m_qbsStdout.contains("has modules: false"); QVERIFY2(hasMods == !dontHaveMods, m_qbsStdout.constData()); QCOMPARE(hasMods, hasModules); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters runParams; QCOMPARE(runQbs(runParams), 0); } void TestBlackbox::hostOsProperties() { QDir::setCurrent(testDataDir + "/host-os-properties"); QCOMPARE(runQbs(QStringLiteral("resolve")), 0); if (m_qbsStdout.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QStringLiteral("run")), 0); QVERIFY2(m_qbsStdout.contains( ("HOST_ARCHITECTURE = " + HostOsInfo::hostOSArchitecture().toUtf8()).data()), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains( ("HOST_PLATFORM = " + HostOsInfo::hostOSIdentifier().toUtf8()).data()), m_qbsStdout.constData()); } void TestBlackbox::ico() { QDir::setCurrent(testDataDir + "/ico"); QbsRunParameters params; params.expectFailure = true; params.arguments << "--command-echo-mode" << "command-line"; const int status = runQbs(params); if (status != 0) { if (m_qbsStderr.contains("Could not find icotool in any of the following locations:")) QSKIP("icotool is not installed"); if (!m_qbsStderr.isEmpty()) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty()) qDebug("%s", m_qbsStdout.constData()); } QCOMPARE(status, 0); QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon") + "/icon.ico")); { QFile f(relativeProductBuildDir("icon") + "/icon.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x2'); // 2 images QVERIFY(b.find("\x89PNG") == std::string::npos); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon-alpha") + "/icon-alpha.ico")); { QFile f(relativeProductBuildDir("icon-alpha") + "/icon-alpha.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x2'); // 2 images QVERIFY(b.find("\x89PNG") == std::string::npos); QVERIFY2(m_qbsStdout.contains("--alpha-threshold="), m_qbsStdout.constData()); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon-big") + "/icon-big.ico")); { QFile f(relativeProductBuildDir("icon-big") + "/icon-big.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x5'); // 5 images QVERIFY(b.find("\x89PNG") != std::string::npos); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor") + "/cursor.cur")); { QFile f(relativeProductBuildDir("cursor") + "/cursor.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x2'); // 2 images QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor-hotspot") + "/cursor-hotspot.cur")); { QFile f(relativeProductBuildDir("cursor-hotspot") + "/cursor-hotspot.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x2'); // 2 images const bool hasCursorHotspotBug = m_qbsStderr.contains( "does not support setting the hotspot for cursor files with multiple images"); if (hasCursorHotspotBug) { QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); qWarning() << "this version of icoutil does not support setting the hotspot " "for cursor files with multiple images"; } else { QCOMPARE(b.at(10), '\x8'); QCOMPARE(b.at(12), '\x9'); QCOMPARE(b.at(26), '\x10'); QCOMPARE(b.at(28), '\x11'); } } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor-hotspot-single") + "/cursor-hotspot-single.cur")); { QFile f(relativeProductBuildDir("cursor-hotspot-single") + "/cursor-hotspot-single.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x1'); // 1 image // No version check needed because the hotspot can always be set if there's only one image QCOMPARE(b.at(10), '\x8'); QCOMPARE(b.at(12), '\x9'); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("iconset") + "/dmg.ico")); { QFile f(relativeProductBuildDir("iconset") + "/dmg.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x5'); // 5 images } QVERIFY(QFileInfo::exists(relativeProductBuildDir("iconset") + "/dmg.cur")); { QFile f(relativeProductBuildDir("iconset") + "/dmg.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x5'); // 5 images QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); } } void TestBlackbox::importAssignment() { QDir::setCurrent(testDataDir + "/import-assignment"); QCOMPARE(runQbs(QStringList("project.qbsSearchPaths:" + QDir::currentPath())), 0); QVERIFY2(m_qbsStdout.contains("key 1 = value1") && m_qbsStdout.contains("key 2 = value2"), m_qbsStdout.constData()); } void TestBlackbox::importChangeTracking() { QDir::setCurrent(testDataDir + "/import-change-tracking"); QCOMPARE(runQbs(QStringList({"-f", "import-change-tracking.qbs"})), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in imported file that is not used in any rule or command. WAIT_FOR_NEW_TIMESTAMP(); touch("irrelevant.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in directly imported file only used by one prepare script. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1prepare1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in recursively imported file only used by one prepare script. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1prepare2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in imported file used only by one command. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1command.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in file only used by one prepare script, using directory import. WAIT_FOR_NEW_TIMESTAMP(); touch("custom2prepare/custom2prepare2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in file used only by one command, imported via search path. WAIT_FOR_NEW_TIMESTAMP(); touch("imports/custom2command/custom2command1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in directly imported file only used by one Probe WAIT_FOR_NEW_TIMESTAMP(); touch("probe1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in indirectly imported file only used by one Probe WAIT_FOR_NEW_TIMESTAMP(); touch("probe2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change everything at once. WAIT_FOR_NEW_TIMESTAMP(); touch("irrelevant.js"); touch("custom1prepare1.js"); touch("custom1prepare2.js"); touch("custom1command.js"); touch("custom2prepare/custom2prepare1.js"); touch("imports/custom2command/custom2command2.js"); touch("probe2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); } void TestBlackbox::probesInNestedModules() { QDir::setCurrent(testDataDir + "/probes-in-nested-modules"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.count("running probe a"), 1); QCOMPARE(m_qbsStdout.count("running probe b"), 1); QCOMPARE(m_qbsStdout.count("running probe c"), 1); QCOMPARE(m_qbsStdout.count("running second probe a"), 1); QVERIFY(m_qbsStdout.contains("product a, outer.somethingElse = goodbye")); QVERIFY(m_qbsStdout.contains("product b, inner.something = hahaha")); QVERIFY(m_qbsStdout.contains("product c, inner.something = hello")); QVERIFY(m_qbsStdout.contains("product a, inner.something = hahaha")); QVERIFY(m_qbsStdout.contains("product a, outer.something = hahaha")); } QTEST_MAIN(TestBlackbox) qbs-src-3.3.1/tests/auto/blackbox/tst_clangdb.h0000644000175100017510000000411615232633614021041 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TST_CLANGDB_H #define QBS_TST_CLANGDB_H #include "tst_blackbox.h" #include class TestClangDb : public TestBlackboxBase { Q_OBJECT public: TestClangDb(); private slots: void initTestCase() override; void ensureBuildTreeCreated(); void checkCanGenerateDb(); void checkDbIsValidJson(); void checkDbIsConsistentWithProject(); void checkClangDetectsSourceCodeProblems(); private: int runProcess(const QString &exec, const QStringList &args, QByteArray &stdErr, QByteArray &stdOut); qbs::Version clangVersion(); const QString projectDir; const QString projectFileName; const QString buildDir; const QString sourceFilePath; const QString dbFilePath; bool isMsvc = false; bool isMingw = false; QProcessEnvironment processEnvironment; }; #endif // Include guard. qbs-src-3.3.1/tests/auto/blackbox/tst_clangdb.cpp0000644000175100017510000001766115232633614021405 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Christian Gagneraud. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_clangdb.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include using qbs::InstallOptions; using qbs::Internal::HostOsInfo; int TestClangDb::runProcess(const QString &exec, const QStringList &args, QByteArray &stdErr, QByteArray &stdOut) { QProcess process; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(processEnvironment); process.setProcessEnvironment(env); process.start(exec, args); const int waitTime = 10 * 60000; if (!process.waitForStarted() || !process.waitForFinished(waitTime)) { stdErr = process.readAllStandardError(); return -1; } stdErr = process.readAllStandardError(); stdOut = process.readAllStandardOutput(); sanitizeOutput(&stdErr); sanitizeOutput(&stdOut); if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { if (!stdErr.isEmpty()) qDebug("%s", stdErr.constData()); if (!stdOut.isEmpty()) qDebug("%s", stdOut.constData()); } return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } qbs::Version TestClangDb::clangVersion() { QByteArray stdErr; QByteArray stdOut; if (runProcess("clang-check", QStringList("--version"), stdErr, stdOut) != 0) return qbs::Version(); stdOut.remove(0, stdOut.indexOf("LLVM version ") + 13); stdOut.truncate(stdOut.indexOf('\n')); return qbs::Version::fromString(QString::fromLocal8Bit(stdOut)); } TestClangDb::TestClangDb() : TestBlackboxBase(SRCDIR "/testdata-clangdb", "blackbox-clangdb"), projectDir(QDir::cleanPath(testDataDir + "/project1")), projectFileName("project.qbs"), buildDir(QDir::cleanPath(projectDir + "/" + relativeBuildDir())), sourceFilePath(QDir::cleanPath(projectDir + "/i like spaces.cpp")), dbFilePath(QDir::cleanPath(buildDir + "/compile_commands.json")) { } void TestClangDb::initTestCase() { TestBlackboxBase::initTestCase(); QDir::setCurrent(projectDir); } void TestClangDb::ensureBuildTreeCreated() { QCOMPARE(runQbs(), 0); QVERIFY(QFile::exists(buildDir)); isMsvc = m_qbsStdout.contains("is msvc"); isMingw = m_qbsStdout.contains("is mingw"); if (isMsvc || isMingw) { sanitizeOutput(&m_qbsStdout); const auto lines = m_qbsStdout.split('\n'); for (const auto &line : lines) { static const QByteArray includeEnv = "INCLUDE="; static const QByteArray libEnv = "LIB="; static const QByteArray pathEnv = "PATH="; if (line.startsWith(includeEnv)) processEnvironment.insert("INCLUDE", line.mid(includeEnv.size())); if (line.startsWith(libEnv)) processEnvironment.insert("LIB", line.mid(libEnv.size())); if (line.startsWith(pathEnv)) processEnvironment.insert("PATH", line.mid(pathEnv.size())); } } } void TestClangDb::checkCanGenerateDb() { QbsRunParameters params; params.command = "generate"; params.arguments << "--generator" << "clangdb"; QCOMPARE(runQbs(params), 0); QVERIFY(QFile::exists(dbFilePath)); } void TestClangDb::checkDbIsValidJson() { QFile file(dbFilePath); QVERIFY(file.open(QFile::ReadOnly)); const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); QVERIFY(!doc.isNull()); QVERIFY(doc.isArray()); } void TestClangDb::checkDbIsConsistentWithProject() { QFile file(dbFilePath); QVERIFY(file.open(QFile::ReadOnly)); const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); // We expect only one command for now const QJsonArray array = doc.array(); QVERIFY(array.size() == 1); // Validate the "command object" const QJsonObject entry = array.at(0).toObject(); QVERIFY(entry.contains("directory")); QVERIFY(entry.value("directory").isString()); QVERIFY(entry.contains("arguments")); QVERIFY(entry.value("arguments").isArray()); QVERIFY(entry.value("arguments").toArray().size() >= 2); QVERIFY(entry.contains("file")); QVERIFY(entry.value("file").isString()); QVERIFY(entry.value("file").toString() == sourceFilePath); // Validate the compile command itself, this requires a previous build since the command // line contains 'deep' path that are created during Qbs build run QByteArray stdErr; QByteArray stdOut; QStringList arguments; const QJsonArray jsonArguments = entry.value("arguments").toArray(); QString executable = jsonArguments.at(0).toString(); for (int i=1; i/i like spaces.cpp:11:5: warning: Assigned value is garbage or undefined // int unused = garbage; // ^~~~~~~~~~ ~~~~~~~ // <...>/i like spaces.cpp:11:9: warning: Value stored to 'unused' during its initialization is never read // int unused = garbage; // ^~~~~~ ~~~~~~~ // 2 warnings generated. void TestClangDb::checkClangDetectsSourceCodeProblems() { QByteArray stdErr; QByteArray stdOut; QStringList arguments; const QString executable = findExecutable(QStringList("clang-check")); if (executable.isEmpty()) QSKIP("No working clang-check executable found"); // Older clang versions do not support the "arguments" array in the compilation database. // Should we really want to support them, we would have to fall back to "command" instead. if (clangVersion() < qbs::Version(3, 7)) QSKIP("This test requires clang-check to be based on at least LLVM 3.7.0."); // clang-check.exe does not understand MSVC command-line syntax if (isMsvc) arguments << "-extra-arg-before=--driver-mode=cl"; else if (isMingw) arguments << "-extra-arg-before=--driver-mode=g++"; arguments << "-analyze" << "-p" << relativeBuildDir() << sourceFilePath; QVERIFY(runProcess(executable, arguments, stdErr, stdOut) == 0); const QString output = QString::fromLocal8Bit(stdErr); QVERIFY(output.contains(QRegularExpression(QStringLiteral("warning.*undefined"), QRegularExpression::CaseInsensitiveOption))); QVERIFY(output.contains(QRegularExpression(QStringLiteral("warning.*never read"), QRegularExpression::CaseInsensitiveOption))); } QTEST_MAIN(TestClangDb) qbs-src-3.3.1/tests/auto/blackbox/tst_blackbox.h0000644000175100017510000003056415232633614021242 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackbox : public TestBlackboxBase { Q_OBJECT public: TestBlackbox(); private slots: void allowedValues(); void allowedValues_data(); void addFileTagToGeneratedArtifact(); void alwaysRun(); void alwaysRun_data(); void archiverFlags(); void artifactsMapChangeTracking(); void artifactsMapInvalidation(); void artifactsMapRaceCondition(); void artifactScanning(); void assembly(); void autotestWithDependencies(); void autotestTimeout(); void autotestTimeout_data(); void autotests_data(); void autotests(); void auxiliaryInputsFromDependencies(); void badInterpreter(); void bomSources(); void boolValueInProfile(); void buildDataOfDisabledProduct(); void buildDirectories(); void buildDirPlaceholders_data(); void buildDirPlaceholders(); void buildEnvChange(); void buildGraphVersions(); void buildVariantDefaults_data(); void buildVariantDefaults(); void capnproto(); void capnproto_data(); void changedFiles_data(); void changedFiles(); void changedInputsFromDependencies(); void changedRuleInputs(); void changeInDisabledProduct(); void changeInImportedFile(); void changeTrackingAndMultiplexing(); void checkProjectFilePath(); void checkTimestamps(); void chooseModuleInstanceByPriorityAndVersion(); void chooseModuleInstanceByPriorityAndVersion_data(); void clean(); void cli(); void combinedSources(); void commandFile(); void compilerDefinesByLanguage(); void cppLibrary(); void conditionalExport(); void conditionalFileTagger(); void configure(); void conflictingArtifacts(); void cxxLanguageVersion(); void cxxLanguageVersion_data(); void conanfileProbe_data(); void conanfileProbe(); void conflictingPropertyValues_data(); void conflictingPropertyValues(); void cpuFeatures(); void cxxModules_data(); void cxxModules(); void cxxModulesChangesTracking(); void dateProperty(); void dependenciesProperty(); void dependencyScanningLoop(); void deprecatedProperty(); void deprecatedProperty_data(); void disappearedProfile(); void discardUnusedData(); void discardUnusedData_data(); void dotDotPcFile(); void driverLinkerFlags(); void driverLinkerFlags_data(); void dynamicLibraryInModule(); void dynamicMultiplexRule(); void dynamicProject(); void dynamicRuleOutputs(); void emptyProfile(); void emscriptenArtifacts(); void emscriptenArtifacts_data(); void enableExceptions(); void enableExceptions_data(); void enableRtti(); void enableTimeTrace(); void envMerging(); void envNormalization(); void erroneousFiles_data(); void erroneousFiles(); void errorInfo(); void escapedLinkerFlags(); void explicitlyDependsOn(); void explicitlyDependsOn_data(); void exportedDependencyInDisabledProduct(); void exportedDependencyInDisabledProduct_data(); void exportedPropertyInDisabledProduct(); void exportedPropertyInDisabledProduct_data(); void exportRule(); void exportToOutsideSearchPath(); void exportsCMake(); void exportsCMake_data(); void exportsPkgconfig(); void exportsQbs(); void externalLibs(); void fileDependencies(); void fileTagsFilterMerging(); void flatbuf(); void flatbuf_data(); void freedesktop(); void generatedArtifactAsInputToDynamicRule(); void generateLinkerMapFile(); void generator(); void generator_data(); void groupsInModules(); void grpc_data(); void grpc(); void hostOsProperties(); void ico(); void importAssignment(); void importChangeTracking(); void importInPropertiesCondition(); void importSearchPath(); void importingProduct(); void importsConflict(); void includeLookup(); void inputTagsChangeTracking_data(); void inputTagsChangeTracking(); void inputsFromDependencies(); void installable(); void installableAsAuxiliaryInput(); void installedApp(); void installDuplicates(); void installDuplicatesNoError(); void installedSourceFiles(); void installedTransformerOutput(); void installLocations_data(); void installLocations(); void installPackage(); void installRootFromProjectFile(); void installTree(); void libraryType_data(); void libraryType(); void pluginType_data(); void pluginType(); void invalidArtifactPath_data(); void invalidArtifactPath(); void invalidCommandProperty_data(); void invalidCommandProperty(); void invalidExtensionInstantiation(); void invalidExtensionInstantiation_data(); void invalidInstallDir(); void invalidLibraryNames(); void invalidLibraryNames_data(); void jsExtensionsFile(); void jsExtensionsFileInfo(); void jsExtensionsHost(); void jsExtensionsProcess(); void jsExtensionsPropertyList(); void jsExtensionsTemporaryDir(); void jsExtensionsTextFile(); void jsExtensionsBinaryFile(); void lastModuleCandidateBroken(); void ld(); void linkerMode(); void linkerVariant_data(); void linkerVariant(); void linkerTypeRecursive(); void lexyacc(); void lexyaccOutputs(); void lexyaccOutputs_data(); void linkerLibraryDuplicates(); void linkerLibraryDuplicates_data(); void linkerScripts(); void linkerModuleDefinition(); void listProducts(); void listPropertiesWithOuter(); void listPropertyOrder(); void loadableModule(); void localDeployment(); void makefileGenerator(); void maximumCLanguageVersion(); void maximumCxxLanguageVersion(); void minimumSystemVersion(); void minimumSystemVersion_data(); void missingBuildGraph(); void missingBuildGraph_data(); void missingDependency(); void missingProjectFile(); void missingOverridePrefix(); void moduleConditions(); void movedFileDependency(); void msvcAsmLinkerFlags(); void multipleChanges(); void multipleConfigurations(); void multiplexedTool(); void nestedGroups(); void nestedProperties(); void newOutputArtifact(); void noExportedSymbols_data(); void noExportedSymbols(); void noProfile(); void noSuchProfile(); void nodejs(); void nonBrokenFilesInBrokenProduct(); void nonDefaultProduct(); void notAlwaysUpdated(); void nsis(); void nsisDependencies(); void outOfDateMarking(); void outputArtifactAutoTagging(); void outputRedirection(); void overrideProjectProperties(); void partiallyBuiltDependency_data(); void partiallyBuiltDependency(); void pathProbe_data(); void pathProbe(); void pathListInProbe(); void pchChangeTracking(); void perGroupDefineInExportItem(); void pkgConfigProbe(); void pkgConfigProbe_data(); void pkgConfigProbeSysroot(); void pluginDependency(); void precompiledAndPrefixHeaders(); void precompiledHeaderAndRedefine(); void preventFloatingPointValues(); void probeChangeTracking(); void probeProperties(); void probesAndShadowProducts(); void probeInExportedModule(); void probesAndArrayProperties(); void probesInNestedModules(); void productDependenciesByType(); void productInExportedModule(); void productProperties(); void propertyAssignmentInFailedModule(); void propertyChanges(); void propertyEvaluationContext(); void propertyPrecedence(); void properQuoting(); void propertiesInExportItems(); void protobuf_data(); void protobuf(); void protobufLibraryInstall(); void pseudoMultiplexing(); void qbsConfig(); void qbsConfigAddProfile(); void qbsConfigAddProfile_data(); void qbsConfigImport(); void qbsConfigImport_data(); void qbsConfigExport(); void qbsConfigExport_data(); void qbsLanguageServer_data(); void qbsLanguageServer(); void qbsSession(); void qbsVersion(); void qtBug51237(); void radAfterIncompleteBuild(); void radAfterIncompleteBuild_data(); void recursiveRenaming(); void recursiveWildcards(); void referenceErrorInExport(); void removeDuplicateLibraries_data(); void removeDuplicateLibraries(); void reproducibleBuild(); void reproducibleBuild_data(); void require(); void rescueTransformerData(); void responseFiles(); void retaggedOutputArtifact(); void rpathlinkDeduplication(); void rttiChangeTracking(); void ruleConditions_data(); void ruleConditions(); void ruleConnectionWithExcludedInputs(); void ruleCycle(); void ruleWithNoInputs(); void ruleWithNonRequiredInputs(); void runMultiplexed(); void sanitizer_data(); void sanitizer(); void scannerItem_data(); void scannerItem(); void scannerChangeTracking(); void scanResultInOtherProduct(); void scanResultInNonDependency(); void setupBuildEnvironment(); void setupRunEnvironment(); void staticLibDeps(); void staticLibDeps_data(); void objectLibDeps(); void objectLibDeps_data(); void rpathLink(); void smartRelinking(); void smartRelinking_data(); void soVersion(); void soVersion_data(); void sourceArtifactChanges(); void subProfileChangeTracking(); void successiveChanges(); void symbolLinkMode(); void symlinkRemoval(); void renameDependency(); void separateDebugInfo(); void sevenZip(); void sourceArtifactInInputsFromDependencies(); void staticLibWithoutSources(); void suspiciousCalls(); void suspiciousCalls_data(); void systemIncludePaths(); void distributionIncludePaths(); void systemRunPaths(); void systemRunPaths_data(); void tar(); void textTemplate(); void toolLookup(); void topLevelSearchPath(); void trackAddFile(); void trackAddFileTag(); void trackAddProduct(); void trackExternalProductChanges(); void trackGroupConditionChange(); void trackRemoveFile(); void trackRemoveFileTag(); void trackRemoveProduct(); void transitiveInvalidDependencies(); void transitiveOptionalDependencies(); void typescript(); void undefinedTargetPlatform(); void usingsAsSoleInputsNonMultiplexed(); void variantSuffix(); void variantSuffix_data(); void vcsGit(); void vcsSubversion(); void vcsMercurial(); void versionCheck(); void versionCheck_data(); void versionScript(); void wholeArchive(); void wholeArchive_data(); void wildCardsAndRules(); void wildCardsAndChangeTracking_data(); void wildCardsAndChangeTracking(); void wildcardRenaming(); void zip(); void zip_data(); void zipInvalid(); private: QMap findCli(int *status); QMap findNodejs(int *status); QMap findTypeScript(int *status); QString findArchiver(const QString &fileName, int *status = nullptr); bool prepareAndRunConan(); static bool lexYaccExist(); static qbs::Version bisonVersion(); QMap getRepoStateFromApp() const; }; #endif // TST_BLACKBOX_H qbs-src-3.3.1/tests/auto/language/0000755000175100017510000000000015232633614016400 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/CMakeLists.txt0000644000175100017510000000031215232633614021134 0ustar runnerrunneradd_qbs_test(language DEFINES "QBS_VERSION=\"${QBS_VERSION}\"" DEPENDS qbsquickjsheaders Qt6Core5Compat SOURCES tst_language.cpp tst_language.h ) qbs-src-3.3.1/tests/auto/language/tst_language.cpp0000644000175100017510000047431715232633614021601 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_language.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(QList) using namespace qbs; using namespace qbs::Internal; static QString testDataDir() { return testDataSourceDir(SRCDIR "/testdata"); } static QString testProject(const char *fileName) { return testDataDir() + QLatin1Char('/') + QLatin1String(fileName); } class JSSourceValueCreator { FileContextPtr m_fileContext; std::vector> m_strings; public: JSSourceValueCreator(const FileContextPtr &fileContext) : m_fileContext(fileContext) { } JSSourceValuePtr create(const QString &sourceCode) { JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_fileContext); auto str = std::make_unique(sourceCode); value->setSourceCode(*str.get()); m_strings.push_back(std::move(str)); return value; } }; TestLanguage::TestLanguage(ILogSink *logSink, Settings *settings) : m_logSink(logSink) , m_settings(settings) , m_wildcardsTestDirPath(QDir::tempPath() + QLatin1String("/_wildcards_test_dir_")) { m_rand.seed(QTime::currentTime().msec()); qRegisterMetaType >("QList"); } TestLanguage::~TestLanguage() = default; QHash TestLanguage::productsFromProject(ResolvedProjectPtr project) { QHash result; const auto products = project->allProducts(); for (const ResolvedProductPtr &product : products) result.insert(product->name, product); return result; } template typename C::value_type findByName(const C &container, const QString &name) { auto endIt = std::end(container); auto it = std::find_if(std::begin(container), endIt, [&name] (const typename C::value_type &thing) { return thing->name == name; }); if (it != endIt) return *it; return typename C::value_type(); } ResolvedModuleConstPtr TestLanguage::findModuleByName(ResolvedProductPtr product, const QString &name) { return findByName(product->modules, name); } QVariant TestLanguage::productPropertyValue(ResolvedProductPtr product, QString propertyName) { QStringList propertyNameComponents = propertyName.split(QLatin1Char('.')); if (propertyNameComponents.size() > 1) return product->moduleProperties->property(propertyNameComponents); return getConfigProperty(product->productProperties, propertyNameComponents); } void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool *handled) { const QByteArray dataTag = QTest::currentDataTag(); if (dataTag == "init") { *handled = true; bool exceptionCaught = false; try { resolveProject(projectFileName); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } else if (dataTag == "cleanup") { *handled = true; project.reset(); } else { *handled = false; } } TopLevelProjectPtr TestLanguage::resolveProject(const char *relProjectFilePath) { if (relProjectFilePath) defaultParameters.setProjectFilePath(testProject(relProjectFilePath)); defaultParameters.expandBuildConfiguration(); ProjectResolver resolver(defaultParameters, m_engine.get(), m_logger); return project = resolver.resolve(); } void TestLanguage::init() { // clear caches, otherwise StoredVariantValues may end up being at the same address // as the destroyed value m_engine->reset(); m_logSink->setLogLevel(LoggerInfo); defaultParameters = {}; defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); defaultParameters.setTopLevelProfile(profileName()); defaultParameters.setMaxJobCount(1); defaultParameters.setConfigurationName("default"); defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); defaultParameters.setSearchPaths({SRCDIR "/../../../share/qbs"}); QVERIFY(m_tempDir.isValid()); } #define HANDLE_INIT_CLEANUP_DATATAGS(fn) {\ bool handled;\ handleInitCleanupDataTags(fn, &handled);\ if (handled)\ return;\ QVERIFY(!!project);\ } void TestLanguage::initTestCase() { m_logger = Logger(m_logSink); m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation); QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); } void TestLanguage::additionalProductTypes() { bool exceptionCaught = false; try { resolveProject("additional-product-types.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("p"); QVERIFY(!!product); const QVariantMap cfg = product->productProperties; QVERIFY(cfg.value("hasTag1").toBool()); QVERIFY(cfg.value("hasTag2").toBool()); QVERIFY(cfg.value("hasTag3").toBool()); QVERIFY(!cfg.value("hasTag4").toBool()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::baseProperty() { bool exceptionCaught = false; try { resolveProject("baseproperty.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toStringList(), QStringList() << "boo"); QCOMPARE(cfg.value("zort").toStringList(), QStringList() << "bar" << "boo"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::baseValidation() { try { resolveProject("base-validate/base-validate.qbs"); QVERIFY2(false, "exception expected"); } catch (const qbs::ErrorInfo &e) { QVERIFY2(e.toString().contains("Parent succeeded, child failed."), qPrintable(e.toString())); } } void TestLanguage::brokenDependencyCycle() { QFETCH(QString, projectFileName); try { resolveProject(qPrintable(projectFileName)); } catch (const qbs::ErrorInfo &e) { QVERIFY2(false, qPrintable(e.toString())); } } void TestLanguage::brokenDependencyCycle_data() { QTest::addColumn("projectFileName"); QTest::newRow("one order of products") << "broken-dependency-cycle1.qbs"; QTest::newRow("another order of products") << "broken-dependency-cycle2.qbs"; } void TestLanguage::buildConfigStringListSyntax() { bool exceptionCaught = false; try { QVariantMap overriddenValues; overriddenValues.insert("project.someStrings", "foo,bar,baz"); defaultParameters.setOverriddenValues(overriddenValues); resolveProject("buildconfigstringlistsyntax.qbs"); QVERIFY(!!project); QCOMPARE(project->projectProperties().value("someStrings").toStringList(), QStringList() << "foo" << "bar" << "baz"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::builtinFunctionInSearchPathsProperty() { bool exceptionCaught = false; try { QVERIFY(resolveProject("builtinFunctionInSearchPathsProperty.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::chainedProbes() { bool exceptionCaught = false; try { resolveProject("chained-probes/chained-probes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); const QString prop1Val = project->products.front()->moduleProperties ->moduleProperty("m", "prop1").toString(); QCOMPARE(prop1Val, QLatin1String("probe1Val")); const QString prop2Val = project->products.front()->moduleProperties ->moduleProperty("m", "prop2").toString(); QCOMPARE(prop2Val, QLatin1String("probe1Valprobe2Val")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::versionCompare() { bool exceptionCaught = false; try { QVERIFY(resolveProject("versionCompare.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::canonicalArchitecture() { bool exceptionCaught = false; try { resolveProject("canonicalArchitecture.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("x86")); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::rfc1034Identifier() { bool exceptionCaught = false; try { resolveProject("rfc1034identifier.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("this-has-special-characters-" "uh-oh-Undersc0r3s-Are.Bad")); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::throwThings_data() { QTest::addColumn("type"); QTest::addColumn("result"); QTest::addRow("bool") << "bool" << "true"; QTest::addRow("int") << "int" << "43"; QTest::addRow("string") << "string" << "an error"; QTest::addRow("list") << "list" << R"([ "an", "error" ])"; QTest::addRow("object") << "object" << R"({ "reason": "overheating", "result": "crash" })"; } void TestLanguage::throwThings() { QFETCH(QString, type); QFETCH(QString, result); bool exceptionCaught = false; try { defaultParameters.setOverriddenValues({{"project.throwType", type}}); resolveProject("throw.qbs"); } catch (const ErrorInfo &e) { exceptionCaught = true; QVERIFY2(e.toString().contains(result), qPrintable(e.toString())); } QVERIFY(exceptionCaught); } void TestLanguage::conditionalDepends() { bool exceptionCaught = false; ResolvedProductPtr product; ResolvedModuleConstPtr dependency; try { defaultParameters.setOverriddenValues({std::make_pair(QString("products." "multilevel_module_props_overridden.dummy3.loadDummy"), true)}); resolveProject("conditionaldepends.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); product = products.value("conditionaldepends_derived"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("conditionaldepends_derived_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("product_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("product_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("project_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("project_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy2"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("module_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy2"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("multilevel_module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("multilevel_module_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("multilevel_module_props_overridden"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("multilevel2_module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3_loader"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("contradictory_conditions1"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("contradictory_conditions2"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("unknown_dependency_condition_false"); QVERIFY(!!product); dependency = findModuleByName(product, "doesonlyexistifhellfreezesover"); QVERIFY(!dependency); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::convertStringList() { FileContextPtr fileContext = FileContext::create(); fileContext->setFilePath("/dev/null"); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *scope = Item::create(&pool, ItemType::Scope); scope->setProperty("x", sourceValueCreator.create("[\"a\", \"b\"]")); Evaluator evaluator(m_engine.get()); auto variantValue = evaluator.variantValue(scope, "x"); // despite we have a stringList prop, we evaluate it as a QVariantList QCOMPARE(variantValue.userType(), QMetaType::Type::QVariantList); // and we have to convert it explicitly #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) variantValue.convert(QMetaType(QMetaType::QStringList)); #else variantValue.convert(QMetaType::QStringList); #endif QCOMPARE(variantValue.userType(), QMetaType::Type::QStringList); QCOMPARE(variantValue, QStringList({"a", "b"})); } void TestLanguage::correctDeclInParentLookup() { ErrorInfo exception; try { resolveProject("correct-decl-in-parent-lookup.qbs"); QVERIFY(project); QCOMPARE(project->products.size(), size_t(1)); const ResolvedProductConstPtr theProduct = productsFromProject(project).value("p"); QVERIFY(theProduct); QCOMPARE( theProduct->moduleProperties->moduleProperty("dummy", "cxxFlags").toStringList(), QStringList("x")); } catch (const ErrorInfo &e) { exception = e; } QVERIFY2(!exception.hasError(), qPrintable(exception.toString())); } void TestLanguage::delayedError() { QFETCH(bool, productEnabled); try { QFETCH(QString, projectFileName); QVariantMap overriddenValues; overriddenValues.insert("project.enableProduct", productEnabled); defaultParameters.setOverriddenValues(overriddenValues); resolveProject(projectFileName.toLatin1()); QCOMPARE(productEnabled, false); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); const ResolvedProductConstPtr theProduct = productsFromProject(project).value("theProduct"); QVERIFY(!!theProduct); QCOMPARE(theProduct->enabled, false); } catch (const ErrorInfo &e) { if (!productEnabled) qDebug() << e.toString(); QCOMPARE(productEnabled, true); } } void TestLanguage::delayedError_data() { QTest::addColumn("projectFileName"); QTest::addColumn("productEnabled"); QTest::newRow("product enabled, module validation error") << "delayed-error/validation.qbs" << true; QTest::newRow("product disabled, module validation error") << "delayed-error/validation.qbs" << false; QTest::newRow("product enabled, module not found") << "delayed-error/nonexisting.qbs" << true; QTest::newRow("product disabled, module not found") << "delayed-error/nonexisting.qbs" << false; } void TestLanguage::dependencyOnAllProfiles() { bool exceptionCaught = false; try { TemporaryProfile p1("p1", m_settings); p1.p.setValue("qbs.architecture", "arch1"); TemporaryProfile p2("p2", m_settings); p2.p.setValue("qbs.architecture", "arch2"); QVariantMap overriddenValues; overriddenValues.insert("project.profile1", "p1"); overriddenValues.insert("project.profile2", "p2"); defaultParameters.setOverriddenValues(overriddenValues); resolveProject("dependencyOnAllProfiles.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(3)); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(!!mainProduct); QCOMPARE(mainProduct->dependencies.size(), size_t { 2 }); for (const ProductDependency &p : mainProduct->dependencies) { QCOMPARE(p.product->name, QLatin1String("dep")); QVERIFY(p.product->profile() == "p1" || p.product->profile() == "p2"); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::dependsItemInGroup_data() { QTest::addColumn("enableGroup1"); QTest::addColumn("enableGroup2"); QTest::addColumn("enableDepends"); QTest::addColumn("dependencyExpected"); QTest::newRow("all disabled") << false << false << false << false; QTest::newRow("only Depends enabled") << false << false << true << false; QTest::newRow("only inner Group enabled") << false << true << false << false; QTest::newRow("inner Group and Depends enabled") << false << true << true << false; QTest::newRow("only outer Group enabled") << true << false << false << false; QTest::newRow("only outer Group and Depends enabled") << true << false << true << false; QTest::newRow("only Groups enabled") << true << true << false << false; QTest::newRow("everything enabled") << true << true << true << true; } void TestLanguage::dependsItemInGroup() { QFETCH(bool, enableGroup1); QFETCH(bool, enableGroup2); QFETCH(bool, enableDepends); QFETCH(bool, dependencyExpected); bool exceptionCaught = false; try { const QVariantMap overriddenValues{ std::make_pair("products.main.enableGroup1", enableGroup1), std::make_pair("products.main.enableGroup2", enableGroup2), std::make_pair("products.main.enableDepends", enableDepends)}; defaultParameters.setOverriddenValues(overriddenValues); resolveProject("depends-item-in-group.qbs"); QVERIFY(project); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(mainProduct); QCOMPARE(mainProduct->dependencies.empty(), !dependencyExpected); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::derivedSubProject() { bool exceptionCaught = false; try { resolveProject("derived-sub-project/project.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::disabledPropertiesItem_data() { QTest::addColumn("setInProduct"); QTest::addColumn("setInHigher1"); QTest::addColumn("setInHigher2"); QTest::addColumn("setInLower"); QTest::addColumn("expectedValue"); QTest::addColumn("expectedListValue"); QTest::addColumn("expectedProductValue"); QTest::newRow("default") << false << false << false << false << QString("default") << QStringList{"N_GREATER_7", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("lower only") << false << false << false << true << QString("default_fromLower") << QStringList{"N_GREATER_7", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("higher2 only") << false << false << true << false << QString() << QStringList{"N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("lower and higher2") << false << false << true << true << QString() << QStringList{"N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("higher1 only") << false << true << false << false << QString("fromHigher1") << QStringList{"N_GREATER_7", "N_GREATER_6", "WITH_HIGHER1_PROP", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("lower and higher1") << false << true << false << true << QString("fromHigher1") << QStringList{"N_GREATER_7", "N_GREATER_6", "WITH_HIGHER1_PROP", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition2", "default"}; QTest::newRow("product only") << true << false << false << false << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("product and lower") << true << false << false << true << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("product and higher2") << true << false << true << false << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("product, higher2 and lower") << true << false << true << true << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("product and higher1") << true << true << false << false << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "N_GREATER_6", "WITH_HIGHER1_PROP", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("product, higher1 and higher2") << true << true << true << false << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "WITH_HIGHER1_PROP", "N_GREATER_5", "N_LESS_20", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; QTest::newRow("all") << true << true << true << true << QString("fromProduct") << QStringList{"WITH_PRODUCT_PROP", "N_GREATER_7", "WITH_HIGHER2_PROP", "N_GREATER_6", "WITH_HIGHER1_PROP", "N_GREATER_5", "N_LESS_20", "WITH_LOWER_PROP", "N_NON_ZERO"} << QStringList{"condition1", "condition2", "default"}; } void TestLanguage::disabledPropertiesItem() { QFETCH(bool, setInLower); QFETCH(bool, setInHigher1); QFETCH(bool, setInHigher2); QFETCH(bool, setInProduct); QFETCH(QString, expectedValue); QFETCH(QStringList, expectedListValue); QFETCH(QStringList, expectedProductValue); QVariantMap overriddenValues; overriddenValues.insert("modules.lower.setProp", setInLower); overriddenValues.insert("modules.higher1.setProp", setInHigher1); overriddenValues.insert("modules.higher2.setProp", setInHigher2); overriddenValues.insert("products.p.setProp", setInProduct); defaultParameters.setOverriddenValues(overriddenValues); bool exceptionCaught = false; try { resolveProject("disabled-properties-item/disabled-properties-item.qbs"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductConstPtr &p = *products.constBegin(); QCOMPARE(p->moduleProperties->moduleProperty("lower", "prop").toString(), expectedValue); QCOMPARE( p->moduleProperties->moduleProperty("lower", "listProp").toStringList(), expectedListValue); QCOMPARE(p->productProperties.value("productProp").toStringList(), expectedProductValue); } void TestLanguage::disabledSubProject() { bool exceptionCaught = false; try { resolveProject("disabled-subproject.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::dottedNames_data() { QTest::addColumn("useProduct"); QTest::addColumn("useModule"); QTest::addColumn("expectSuccess"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("missing product dependency") << false << true << false << QString("Item 'a.b' is not declared. Did you forget to add a Depends item"); QTest::newRow("missing module dependency") << true << false << false << QString("Item 'x.y' is not declared. Did you forget to add a Depends item"); QTest::newRow("missing both dependencies") << false << false << false << QString(); QTest::newRow("ok") << true << true << true << QString(); } void TestLanguage::dottedNames() { QFETCH(bool, expectSuccess); try { QFETCH(bool, useProduct); QFETCH(bool, useModule); const QVariantMap overridden{ std::make_pair("projects.theProject.includeDottedProduct", useProduct), std::make_pair("projects.theProject.includeDottedModule", useModule) }; defaultParameters.setOverriddenValues(overridden); resolveProject("dotted-names/dotted-names.qbs"); QVERIFY(expectSuccess); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), useProduct ? 2 : 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("a.b", "c").toString(), QString("p")); QCOMPARE(product->moduleProperties->moduleProperty("x.y", "z").toString(), QString("p")); } catch (const ErrorInfo &e) { QVERIFY(!expectSuccess); QFETCH(QString, expectedErrorMessage); if (!expectedErrorMessage.isEmpty()) QVERIFY2(e.toString().contains(expectedErrorMessage), qPrintable(e.toString())); } } void TestLanguage::duplicateMultiplexValues_data() { QTest::addColumn("dummy"); QTest::newRow("duplicate-multiplex-value") << true; QTest::newRow("duplicate-multiplex-value2") << true; } void TestLanguage::duplicateMultiplexValues() { bool exceptionCaught = false; try { resolveProject(qPrintable(QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"))); QVERIFY(project); const std::vector products = project->allProducts(); QCOMPARE(products.size(), 2); bool x86 = false; bool arm = false; for (const ResolvedProductPtr &p : products) { if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "x86") x86 = true; else if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "arm") arm = true; } QVERIFY(x86); QVERIFY(arm); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::emptyJsFile() { bool exceptionCaught = false; try { resolveProject("empty-js-file.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::enumerateProjectProperties() { bool exceptionCaught = false; try { resolveProject("enum-project-props.qbs"); QVERIFY(!!project); const auto products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductConstPtr product = *products.begin(); QCOMPARE(product->groups.size(), size_t(1)); const auto files = product->groups.front()->files; QVERIFY(files); QCOMPARE(files->size(), size_t(1)); const QString fileName = FileInfo::fileName(files->front()->absoluteFilePath); QCOMPARE(fileName, QString("dummy.txt")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::evalErrorInNonPresentModule_data() { QTest::addColumn("moduleRequired"); QTest::addColumn("errorMessage"); QTest::newRow("module required") << true << "broken.qbs:2:5 Element at index 0 of list property 'broken' " "does not have string type"; QTest::newRow("module not required") << false << QString(); } void TestLanguage::evalErrorInNonPresentModule() { QFETCH(bool, moduleRequired); QFETCH(QString, errorMessage); try { QVariantMap overridden{std::make_pair("products.p.moduleRequired", moduleRequired)}; defaultParameters.setOverriddenValues(overridden); resolveProject("eval-error-in-non-present-module.qbs"); QVERIFY(errorMessage.isEmpty()); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); } catch (const ErrorInfo &e) { QVERIFY(!errorMessage.isEmpty()); QVERIFY2(e.toString().contains(errorMessage), qPrintable(e.toString())); } } void TestLanguage::defaultValue() { bool exceptionCaught = false; try { QFETCH(QString, prop1Value); QVariantMap overridden; if (!prop1Value.isEmpty()) overridden.insert("modules.lower.prop1", prop1Value); defaultParameters.setOverriddenValues(overridden); resolveProject("defaultvalue/egon.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); const ResolvedProductPtr product = products.value("egon"); QVERIFY(!!product); QStringList propertyName = QStringList() << "lower" << "prop2"; QVariant propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedProp2Value); QCOMPARE(propertyValue, expectedProp2Value); propertyName = QStringList() << "lower" << "listProp"; propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedListPropValue); QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::defaultValue_data() { QTest::addColumn("prop1Value"); QTest::addColumn("expectedProp2Value"); QTest::addColumn("expectedListPropValue"); QTest::newRow("controlling property with random value") << "random" << QVariant("withoutBlubb") << QVariant(QStringList({"other"})); QTest::newRow("controlling property with blubb value") << "blubb" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other"})); QTest::newRow("controlling property with egon value") << "egon" << QVariant("withEgon") << QVariant(QStringList({"egon", "other"})); QTest::newRow("controlling property not overwritten") << "" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other"})); } void TestLanguage::environmentVariable() { bool exceptionCaught = false; try { // Create new environment: const QString varName = QStringLiteral("PRODUCT_NAME"); const QString productName = QLatin1String("MyApp") + QString::number(m_rand.generate()); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(varName, productName); QProcessEnvironment origEnv = defaultParameters.environment(); // store orig environment defaultParameters.setEnvironment(env); resolveProject("environmentvariable.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::errorInDisabledProduct() { bool exceptionCaught = false; try { resolveProject("error-in-disabled-product.qbs"); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 5); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("unknown_module") << "Dependency 'neitherModuleNorProduct' not found"; QTest::newRow("multiple_exports") << "Multiple Export items in one product are prohibited."; QTest::newRow("multiple_properties_in_subproject") << "Multiple instances of item 'Properties' found where at most one " "is allowed."; QTest::newRow("importloop1") << "Loop detected when importing"; QTest::newRow("nonexistentouter") << "outer is not defined"; QTest::newRow("invalid_file") << "does not exist"; QTest::newRow("invalid-parameter-rhs") << "access is not defined"; QTest::newRow("invalid-parameter-type") << "Value assigned to property 'stringParameter' does not have type 'string'."; QTest::newRow("invalid_property_type") << "Unknown type 'nonsense' in property declaration."; QTest::newRow("reserved_name_in_import") << "Cannot reuse the name of built-in extension 'TextFile'."; QTest::newRow("throw_in_property_binding") << "something is wrong"; QTest::newRow("no-configure-in-probe") << "no-configure-in-probe.qbs:2:5.*Probe.configure must be set"; QTest::newRow("dependency_cycle") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle2") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle3") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle3a") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle4") << "Cyclic dependencies detected."; QTest::newRow("references_cycle") << "Cycle detected while referencing file '.*references_cycle.qbs'."; QTest::newRow("subproject_cycle") << "Cycle detected while loading subproject file 'subproject_cycle.qbs'."; QTest::newRow("invalid_stringlist_element") << "Element at index 1 of list property 'files' does not have string type."; QTest::newRow("undefined_stringlist_element") << "Element at index 1 of list property 'files' is undefined. String expected."; QTest::newRow("undefined_stringlist_element_in_probe") << "Element at index 1 of list property 'l' is undefined. String expected."; QTest::newRow("undeclared_item") << "Item 'cpp' is not declared."; QTest::newRow("undeclared-parameter1") << "Parameter 'prefix2.suffix.nope' is not declared."; QTest::newRow("undeclared-parameter2") << "Cannot set parameter 'foo.bar', " "because 'myproduct' does not have a dependency on 'foo'."; QTest::newRow("undeclared_property_wrapper") << "Property 'doesntexist' is not declared."; QTest::newRow("undeclared_property_in_export_item") << "Property 'blubb' is not declared."; QTest::newRow("undeclared_property_in_export_item2") << "Item 'something' is not declared."; QTest::newRow("undeclared_property_in_export_item3") << "Property 'blubb' is not declared."; QTest::newRow("undeclared_module_property_in_module") << "Property 'noSuchProperty' is not declared."; QTest::newRow("unknown_item_type") << "Unexpected item type 'Narf'"; QTest::newRow("invalid_child_item_type") << "Items of type 'Project' cannot contain items of type 'Depends'."; QTest::newRow("conflicting_fileTagsFilter") << "Conflicting fileTagsFilter in Group items"; QTest::newRow("duplicate_sources") << "Duplicate source file '.*main.cpp'" ".*duplicate_sources.qbs:2:12.*duplicate_sources.qbs:4:16."; QTest::newRow("duplicate_sources_wildcards") << "Duplicate source file '.*duplicate_sources_wildcards.qbs'" ".*duplicate_sources_wildcards.qbs:2:12" ".*duplicate_sources_wildcards.qbs:4:16."; QTest::newRow("oldQbsVersion") << "The project requires at least qbs version \\d+\\.\\d+.\\d+, " "but this is qbs version " QBS_VERSION "."; QTest::newRow("wrongQbsVersionFormat") << "The value '.*' of Project.minimumQbsVersion is not a valid version string."; QTest::newRow("properties-item-with-invalid-condition") << "properties-item-with-invalid-condition.qbs:4:19.*" "cannot read property 'includes' of undefined"; QTest::newRow("misused-inherited-property") << "Binding to non-item property"; QTest::newRow("undeclared_property_in_Properties_item") << "Item 'blubb' is not declared"; QTest::newRow("conflicting-properties-in-export-items") << "Export item in inherited item redeclares property 'theProp' with different type."; QTest::newRow("invalid-property-option") << "PropertyOptions item refers to non-existing property 's0meProp'"; QTest::newRow("missing-colon") << "Invalid item 'dummy.cxxFlags'. Did you mean to set a module property?"; QTest::newRow("syntax-error-in-probe") << "syntax-error-in-probe.qbs:4:20.*fngkgsdjfgklkf is not defined"; QTest::newRow("wrong-toplevel-item") << "wrong-toplevel-item.qbs:1:1.*The top-level item must be of type 'Project' or " "'Product', but it is of type 'Artifact'."; QTest::newRow("conflicting-module-instances") << "There is more than one equally prioritized candidate for module " "'conflicting-instances'."; QTest::newRow("overwrite-inherited-readonly-property") << "overwrite-inherited-readonly-property.qbs" ":2:21.*Cannot set read-only property 'readOnlyString'."; QTest::newRow("overwrite-readonly-module-property") << "overwrite-readonly-module-property.qbs" ":3:30.*Cannot set read-only property 'readOnlyString'."; QTest::newRow("original-in-product-property") << "original-in-product-property.qbs" ":2:21.*The special value 'original' can only be used with module properties."; QTest::newRow("rule-without-output-tags") << "rule-without-output-tags.qbs:2:5.*A rule needs to have Artifact items or " "a non-empty outputFileTags property."; QTest::newRow("original-in-module-prototype") << "module-with-invalid-original.qbs:2:24.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item") << "original-in-export-item.qbs:5:32.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item2") << "original-in-export-item2.qbs:4:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("original-in-export-item3") << "original-in-export-item3.qbs:6:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("mismatching-multiplex-dependency") << "mismatching-multiplex-dependency.qbs:9:9.*Dependency from product " "'b \\{\"architecture\":\"mips\"\\}' to product 'a'" " not fulfilled. There are no eligible multiplex candidates."; QTest::newRow("ambiguous-multiplex-dependency") << "ambiguous-multiplex-dependency.qbs:10:9.*Dependency from product 'b " "\\{\"architecture\":\"x86\"\\}' to product 'a' is ambiguous. Eligible multiplex " "candidates: a \\{\"architecture\":\"x86\",\"buildVariant\":\"debug\"\\}, " "a \\{\"architecture\":\"x86\",\"buildVariant\":\"release\"\\}."; QTest::newRow("dependency-profile-mismatch") << "dependency-profile-mismatch.qbs:10:5.*Product 'main' depends on 'dep', " "which does not exist for the requested profile 'profile47'."; QTest::newRow("dependency-profile-mismatch-2") << "dependency-profile-mismatch-2.qbs:15:9 Dependency from product 'main' to " "product 'dep' not fulfilled. There are no eligible multiplex candidates."; QTest::newRow("invalid-references") << "invalid-references.qbs:2:17.*Cannot open '.*nosuchproject.qbs'"; QTest::newRow("missing-js-file") << "missing-js-file.qbs.*Cannot open '.*javascriptfile.js'.*missing-js-file.js:1"; QTest::newRow("frozen-object") << "'key' is read-only"; QTest::newRow("frozen-object-list") << "object is not extensible"; QTest::newRow("module-property-binding-in-project") << "Module properties cannot be set in Project items"; QTest::newRow("module-with-id") << "Module items cannot have an id property"; QTest::newRow("module-var-in-product") << "module-var-in-product.qbs:4:19 Use of 'module' is only allowed in Module items"; QTest::newRow("recursive-property-direct") << "refers to itself"; QTest::newRow("recursive-property-indirect") << "refers to itself.*via 'b'.*via 'c'"; QTest::newRow("recursive-property-indirect-via-module") << "refers to itself.*via 'a'"; } void TestLanguage::erroneousFiles() { QFETCH(QString, errorMessage); QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"); try { resolveProject(qPrintable("/erroneous/" + fileName)); } catch (const ErrorInfo &e) { const QRegularExpression reg(errorMessage, QRegularExpression::DotMatchesEverythingOption); if (!e.toString().contains(reg)) { qDebug() << "Message: " << e.toString(); qDebug() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } return; } QEXPECT_FAIL("undeclared_property_in_Properties_item", "Too expensive to check", Continue); QEXPECT_FAIL("original-in-export-item3", "Too expensive to check", Continue); QVERIFY(!"No error thrown on invalid input."); } void TestLanguage::exports() { bool exceptionCaught = false; try { defaultParameters.setDeprecationWarningMode(DeprecationWarningMode::On); resolveProject("exports.qbs"); QVERIFY(!!project); Set warningLocations; QHash products = productsFromProject(project); QCOMPARE(products.size(), 22); ResolvedProductPtr product; product = products.value("myapp"); QVERIFY(!!product); QStringList propertyName = QStringList() << "dummy" << "defines"; QVariant propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYAPP" << "USE_MYLIB" << "USE_MYLIB2"); propertyName = QStringList() << "dummy" << "includePaths"; QVariantList propertyValues = product->moduleProperties->property(propertyName).toList(); QCOMPARE(propertyValues.size(), 3); QVERIFY(propertyValues.at(0).toString().endsWith("/app")); QVERIFY(propertyValues.at(1).toString().endsWith("/testdata/lib")); QVERIFY(propertyValues.at(2).toString().endsWith("/testdata/lib")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp")); QVERIFY(product->moduleProperties->moduleProperty("dummy", "somePath").toString() .endsWith("/subdir")); product = products.value("mylib"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB"); QVERIFY(product->moduleProperties->moduleProperty("dummy", "somePath").toString() .endsWith("/subdir")); product = products.value("mylib2"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB2"); product = products.value("A"); QVERIFY(!!product); QVERIFY(contains(product->dependencies, ProductDependency{products.value("B"), false})); QVERIFY(contains(product->dependencies, ProductDependency{products.value("C"), false})); QVERIFY(contains(product->dependencies, ProductDependency{products.value("D"), false})); product = products.value("B"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); QCOMPARE(product->exportedModule.productDependencies, std::vector{"C"}); product = products.value("C"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); product = products.value("D"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); product = products.value("myapp2"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "cFlags"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BASE_PRODUCTWITHINHERITEDEXPORTITEM" << "PRODUCT_PRODUCTWITHINHERITEDEXPORTITEM"); propertyName = QStringList() << "dummy" << "cxxFlags"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "-bar"); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList({"ABC", "DEF"})); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp2")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "upperCaseProductName").toString(), QString("MYAPP2")); // Check whether we're returning incorrect cached values. product = products.value("myapp3"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp3")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "upperCaseProductName").toString(), QString("MYAPP3")); // Verify we refer to the right "project" variable. product = products.value("sub p2"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "someString").toString(), QString("sub1")); product = products.value("libE"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "LIBD" << "LIBC" << "LIBA" << "LIBB"); propertyName = QStringList() << "dummy" << "productName"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toString(), QString("libE")); product = products.value("depender"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(2)); for (const ResolvedModulePtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("dependency"), qPrintable(m->name)); } QCOMPARE(product->productProperties.value("featureX").toBool(), true); QCOMPARE(product->productProperties.value("featureY").toBool(), false); QCOMPARE(product->productProperties.value("featureZ").toBool(), true); product = products.value("broken_cycle3"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(3)); for (const ResolvedModulePtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("broken_cycle1") || m->name == QString("broken_cycle2"), qPrintable(m->name)); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileContextProperties() { bool exceptionCaught = false; try { resolveProject("filecontextproperties.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toString(), defaultParameters.projectFilePath()); QString dirPath = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); QCOMPARE(cfg.value("zort").toString(), dirPath); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileInProductAndModule_data() { QTest::addColumn("file1IsTarget"); QTest::addColumn("file2IsTarget"); QTest::addColumn("addFileToProduct"); QTest::addColumn("successExpected"); QTest::newRow("file occurs twice in module as non-target") << false << false << false << false; QTest::newRow("file occurs twice in module as non-target, and in product as well") << false << false << true << false; QTest::newRow("file occurs in module as non-target and target") << false << true << false << true; QTest::newRow("file occurs in module as non-target and target, and in product as well") << false << true << true << false; QTest::newRow("file occurs in module as target and non-target") << true << false << false << true; QTest::newRow("file occurs in module as target and non-target, and in product as well") << true << false << true << false; QTest::newRow("file occurs twice in module as target") << true << true << false << false; QTest::newRow("file occurs twice in module as target, and in product as well") << true << true << true << false; } void TestLanguage::fileInProductAndModule() { bool exceptionCaught = false; QFETCH(bool, file1IsTarget); QFETCH(bool, file2IsTarget); QFETCH(bool, addFileToProduct); QFETCH(bool, successExpected); try { defaultParameters.setOverriddenValues(QVariantMap{ std::make_pair("modules.module_with_file.file1IsTarget", file1IsTarget), std::make_pair("modules.module_with_file.file2IsTarget", file2IsTarget), std::make_pair("products.p.addFileToProduct", addFileToProduct), }); resolveProject("file-in-product-and-module.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; QVERIFY2(e.toString().contains("Duplicate"), qPrintable(e.toString())); } QCOMPARE(exceptionCaught, !successExpected); } void TestLanguage::getNativeSetting() { bool exceptionCaught = false; try { resolveProject("getNativeSetting.qbs"); QString expectedTargetName; if (HostOsInfo::isMacosHost()) { if (HostOsInfo::hostOsVersion() >= qbs::Version(11)) expectedTargetName = QStringLiteral("macOS"); else expectedTargetName = QStringLiteral("Mac OS X"); } else if (HostOsInfo::isWindowsHost()) { expectedTargetName = QStringLiteral("Windows"); } else { expectedTargetName = QStringLiteral("Unix"); } QVERIFY(!!project); QHash products; for (const ResolvedProductPtr &product : project->allProducts()) products.insert(product->targetName, product); ResolvedProductPtr product = products.value(expectedTargetName); QVERIFY(!!product); ResolvedProductPtr product2 = products.value(QStringLiteral("fallback")); QVERIFY(!!product2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::groupConditions_data() { QTest::addColumn("groupCount"); QTest::addColumn>("groupEnabled"); QTest::newRow("init") << size_t(0) << std::vector(); QTest::newRow("no_condition_no_group") << size_t(1) << std::vector{ true }; QTest::newRow("no_condition") << size_t(2) << std::vector{ true, true }; QTest::newRow("true_condition") << size_t(2) << std::vector{ true, true }; QTest::newRow("false_condition") << size_t(2) << std::vector{ true, false }; QTest::newRow("true_condition_from_product") << size_t(2) << std::vector{ true, true }; QTest::newRow("true_condition_from_project") << size_t(2) << std::vector{ true, true }; QTest::newRow("condition_accessing_module_property") << size_t(2) << std::vector{ true, false }; QTest::newRow("cleanup") << size_t(0) << std::vector(); } void TestLanguage::groupConditions() { HANDLE_INIT_CLEANUP_DATATAGS("groupconditions.qbs"); QFETCH(size_t, groupCount); QFETCH(std::vector, groupEnabled); QCOMPARE(groupCount, groupEnabled.size()); const QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QCOMPARE(product->groups.size(), groupCount); for (size_t i = 0; i < groupCount; ++i) { if (product->groups.at(i)->enabled != groupEnabled.at(i)) { QFAIL(qPrintable( QString("groups.at(%1)->enabled != %2").arg(i).arg(bool(groupEnabled.at(i))))); } } } void TestLanguage::groupName() { bool exceptionCaught = false; try { resolveProject("groupname.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); ResolvedProductPtr product = products.value("MyProduct"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(2)); GroupConstPtr group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, QString("MyProduct")); group = product->groups.at(1); QVERIFY(!!group); QCOMPARE(group->name, QString("MyProduct.MyGroup")); product = products.value("My2ndProduct"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(3)); group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, QString("My2ndProduct")); group = product->groups.at(1); QVERIFY(!!group); QCOMPARE(group->name, QString("My2ndProduct.MyGroup")); group = product->groups.at(2); QVERIFY(!!group); QCOMPARE(group->name, QString("Group 2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::homeDirectory() { try { resolveProject("homeDirectory.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("home"); QVERIFY(!!product); QDir dir = QDir::home(); QCOMPARE(product->productProperties.value("home").toString(), dir.path()); QCOMPARE(product->productProperties.value("homeSlash").toString(), dir.path()); dir.cdUp(); QCOMPARE(product->productProperties.value("homeUp").toString(), dir.path()); dir = QDir::home(); QCOMPARE(product->productProperties.value("homeFile").toString(), dir.filePath("a")); QCOMPARE(product->productProperties.value("bogus1").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a~b"))); QCOMPARE(product->productProperties.value("bogus2").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a/~/bb"))); QCOMPARE(product->productProperties.value("user").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("~foo/bar"))); } catch (const ErrorInfo &e) { qDebug() << e.toString(); } } void TestLanguage::identifierSearch_data() { QTest::addColumn("expectedHasNarf"); QTest::addColumn("expectedHasZort"); QTest::addColumn("sourceCode"); QTest::newRow("no narf, no zort") << false << false << QString( "Product {\n" " name: {\n" " var foo = 'bar';\n" " console.info(foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, no zort") << true << false << QString( "Product {\n" " name: {\n" " var foo = 'zort';\n" " console.info(narf + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("no narf, zort") << false << true << QString( "Product {\n" " name: {\n" " var foo = 'narf';\n" " console.info(zort + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = foo + zort;\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("2 narfs, 1 zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = narf + foo + zort;\n" " return foo;\n" " }\n" "}\n"); } void TestLanguage::identifierSearch() { QFETCH(bool, expectedHasNarf); QFETCH(bool, expectedHasZort); QFETCH(QString, sourceCode); bool hasNarf = !expectedHasNarf; bool hasZort = !expectedHasZort; IdentifierSearch isearch; isearch.add("narf", &hasNarf); isearch.add("zort", &hasZort); QbsQmlJS::Engine engine; QbsQmlJS::Lexer lexer(&engine); lexer.setCode(sourceCode, 1); QbsQmlJS::Parser parser(&engine); QVERIFY(parser.parse()); QVERIFY(parser.ast()); isearch.start(parser.ast()); QCOMPARE(hasNarf, expectedHasNarf); QCOMPARE(hasZort, expectedHasZort); } void TestLanguage::idUsage() { bool exceptionCaught = false; try { resolveProject("idusage.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 5); QVERIFY(products.contains("product1_1")); QVERIFY(products.contains("product2_2")); QVERIFY(products.contains("product3_3")); ResolvedProductPtr product4 = products.value("product4_4"); QVERIFY(!!product4); auto product4Property = [&product4] (const char *name) { return product4->productProperties.value(QString::fromUtf8(name)).toString(); }; QCOMPARE(product4Property("productName"), product4->name); QCOMPARE(product4Property("productNameInBaseOfBase"), product4->name); GroupPtr group = findByName(product4->groups, "group in base product"); QVERIFY(!!group); QCOMPARE(qPrintable(group->prefix), "group in base product"); group = findByName(product4->groups, "another group in base product"); QVERIFY(!!group); QCOMPARE(qPrintable(group->prefix), "another group in base product"); ResolvedProductPtr product5 = products.value("product5"); QVERIFY(!!product5); QCOMPARE(product5->moduleProperties->moduleProperty("deepdummy.deep.moat", "zort") .toString(), QString("zort in dummy")); QCOMPARE(int(product5->allEnabledFiles().size()), 1); QVERIFY(product5->allEnabledFiles().at(0)->absoluteFilePath.endsWith("dummy.txt")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::idUniqueness() { bool exceptionCaught = false; try { resolveProject("id-uniqueness.qbs"); } catch (const ErrorInfo &e) { exceptionCaught = true; const QList items = e.items(); QCOMPARE(items.size(), 3); QCOMPARE(items.at(0).toString(), QString::fromUtf8("The id 'baseProduct' is not unique.")); QVERIFY(items.at(1).toString().contains("id-uniqueness.qbs:5:5 First occurrence is here.")); QVERIFY(items.at(2).toString().contains("id-uniqueness.qbs:8:5 Next occurrence is here.")); } QVERIFY(exceptionCaught); } void TestLanguage::importCollection() { bool exceptionCaught = false; try { resolveProject("import-collection/project.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("da product"); QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("C1f1C1f2C2f1C2f2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::inheritedPropertiesItems_data() { QTest::addColumn("buildVariant"); QTest::addColumn("productName"); QTest::newRow("debug build") << "debug" << "product_debug"; QTest::newRow("release build") << "release" << "product_release"; } void TestLanguage::inheritedPropertiesItems() { bool exceptionCaught = false; try { QFETCH(QString, buildVariant); QFETCH(QString, productName); defaultParameters.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); resolveProject("inherited-properties-items/inherited-properties-items.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); QVERIFY(!!products.value(productName)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::invalidBindingInDisabledItem() { bool exceptionCaught = false; try { resolveProject("invalidBindingInDisabledItem.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::invalidOverrides() { QFETCH(QString, key); QFETCH(QString, expectedErrorMessage); const bool successExpected = expectedErrorMessage.isEmpty(); bool exceptionCaught = false; try { defaultParameters.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); resolveProject("invalid-overrides.qbs"); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; if (successExpected) qDebug() << e.toString(); else QVERIFY2(e.toString().contains(expectedErrorMessage), qPrintable(e.toString())); } QEXPECT_FAIL("no such module in product", "not easily checkable", Continue); QCOMPARE(!exceptionCaught, successExpected); } void TestLanguage::invalidOverrides_data() { QTest::addColumn("key"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("no such project") << "projects.myproject.x" << QString("Unknown project 'myproject' in property override."); QTest::newRow("no such project property") << "projects.My.Project.y" << QString("Unknown property: projects.My.Project.y"); QTest::newRow("valid project property override") << "projects.My.Project.x" << QString(); QTest::newRow("no such product") << "products.myproduct.x" << QString("Unknown product 'myproduct' in property override."); QTest::newRow("no such product (with module)") << "products.myproduct.cpp.useRPaths" << QString("Unknown product 'myproduct' in property override."); QTest::newRow("no such product property") << "products.MyProduct.y" << QString("Unknown property: products.MyProduct.y"); QTest::newRow("valid product property override") << "products.MyProduct.x" << QString(); // This cannot be an error, because the semantics are "if some product in the project has // such a module, then set that property", and the code that does the property overrides // does not have a global view. QTest::newRow("no such module") << "modules.blubb.x" << QString(); QTest::newRow("no such module in product") << "products.MyProduct.cpp.useRPaths" << QString("Invalid module 'cpp' in property override."); QTest::newRow("no such module property") << "modules.cpp.blubb" << QString("Unknown property: modules.cpp.blubb"); QTest::newRow("no such module property (per product)") << "products.MyOtherProduct.cpp.blubb" << QString("Unknown property: products.MyOtherProduct.cpp.blubb"); QTest::newRow("valid per-product module property override") << "products.MyOtherProduct.cpp.useRPaths" << QString(); } void TestLanguage::invalidPropOnNonRequiredModule_data() { QTest::addColumn("useExistingModule"); QTest::addColumn("errorExpected"); QTest::newRow("existing module") << true << true; QTest::newRow("non-existing module") << false << false; } void TestLanguage::invalidPropOnNonRequiredModule() { QFETCH(bool, useExistingModule); QFETCH(bool, errorExpected); try { defaultParameters.setOverriddenValues( {std::make_pair("project.useExistingModule", useExistingModule)}); resolveProject("invalid-prop-on-non-required-module"); QVERIFY(!errorExpected); } catch (const ErrorInfo &e) { const QString errorString = e.toString(); QVERIFY2(errorExpected, qPrintable(errorString)); QVERIFY2(errorString.contains("Property 'nosuchprop' is not declared"), qPrintable(errorString)); } } void TestLanguage::itemPrototype() { FileContextPtr fileContext = FileContext::create(); fileContext->setFilePath("/dev/null"); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *proto = Item::create(&pool, ItemType::Product); proto->setProperty("x", sourceValueCreator.create("1")); proto->setProperty("y", sourceValueCreator.create("1")); Item *item = Item::create(&pool, ItemType::Product); item->setPrototype(proto); item->setProperty("y", sourceValueCreator.create("x + 1")); item->setProperty("z", sourceValueCreator.create("2")); Evaluator evaluator(m_engine.get()); JSContext * const ctx = m_engine->context(); QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "x")).toInt(), 1); QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "y")).toInt(), 1); QVERIFY(JS_IsUndefined(evaluator.property(proto, "z"))); QCOMPARE(getJsVariant(ctx, evaluator.property(item, "x")).toInt(), 1); QCOMPARE(getJsVariant(ctx, evaluator.property(item, "y")).toInt(), 2); QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 2); } void TestLanguage::itemScope() { FileContextPtr fileContext = FileContext::create(); fileContext->setFilePath("/dev/null"); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *scope1 = Item::create(&pool, ItemType::Scope); scope1->setProperty("x", sourceValueCreator.create("1")); Item *scope2 = Item::create(&pool, ItemType::Scope); scope2->setScope(scope1); scope2->setProperty("y", sourceValueCreator.create("x + 1")); Item *item = Item::create(&pool, ItemType::Scope); item->setScope(scope2); item->setProperty("z", sourceValueCreator.create("x + y")); Evaluator evaluator(m_engine.get()); JSContext * const ctx = m_engine->context(); QCOMPARE(getJsVariant(ctx, evaluator.property(scope1, "x")).toInt(), 1); QCOMPARE(getJsVariant(ctx, evaluator.property(scope2, "y")).toInt(), 2); QVERIFY(JS_IsUndefined(evaluator.property(scope2, "x"))); QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 3); } void TestLanguage::jsExtensions() { QFile file(testProject("jsextensions.js")); QVERIFY(file.open(QFile::ReadOnly)); QTextStream ts(&file); QString code = ts.readAll(); QVERIFY(!code.isEmpty()); m_engine->evaluate(JsValueOwner::Caller, code, file.fileName(), 1); if (m_engine->checkForJsError({})) { const ErrorInfo ex = m_engine->getAndClearJsError(); QFAIL(qPrintable(ex.toString())); } } void TestLanguage::jsImportUsedInMultipleScopes_data() { QTest::addColumn("buildVariant"); QTest::addColumn("expectedProductName"); QTest::newRow("debug") << QString("debug") << QString("MyProduct_debug"); QTest::newRow("release") << QString("release") << QString("MyProduct"); } void TestLanguage::jsImportUsedInMultipleScopes() { QFETCH(QString, buildVariant); QFETCH(QString, expectedProductName); bool exceptionCaught = false; try { defaultParameters.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), buildVariant)}); resolveProject("jsimportsinmultiplescopes.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); QCOMPARE(product->name, expectedProductName); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::keepLoadingDependencies() { QString error; try { resolveProject("keep-loading-dependencies.qbs"); QFAIL("Should not get here!"); } catch (const ErrorInfo &e) { error = e.toString(); } QVERIFY2(error.contains("Dependency 'none.m1' not found"), qPrintable(error)); QVERIFY2(error.contains("Dependency 'none.m2' not found"), qPrintable(error)); QVERIFY2(error.contains("Dependency 'none.m3' not found"), qPrintable(error)); QVERIFY2(!error.contains("QBS_CHECK"), qPrintable(error)); } void TestLanguage::localProfileAsTopLevelProfile() { bool exceptionCaught = false; try { defaultParameters.setTopLevelProfile("test-profile"); resolveProject("local-profile-as-top-level-profile.qbs"); QVERIFY(!!project); QCOMPARE(int(project->products.size()), 1); const PropertyMapConstPtr &props = project->products.front()->moduleProperties; QCOMPARE(props->qbsPropertyValue("architecture"), "arm"); QCOMPARE(props->qbsPropertyValue("targetPlatform"), "macos"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::moduleMergingVariantValues() { bool exceptionCaught = false; try { resolveProject("module-merging-variant-values/module-merging-variant-values.qbs"); QVERIFY(!!project); QCOMPARE(int(project->products.size()), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::moduleNameCollisions_data() { QTest::addColumn("projectFile"); QTest::addColumn("collisionExpected"); QTest::newRow("simple collision (one order)") << "simple-collision1.qbs" << true; QTest::newRow("simple collision (other order)") << "simple-collision2.qbs" << true; QTest::newRow("collision with more components") << "complex-collision.qbs" << true; QTest::newRow("no collision (same length)") << "no-collision1.qbs" << false; QTest::newRow("no collision (different length)") << "no-collision2.qbs" << false; } void TestLanguage::moduleNameCollisions() { QFETCH(QString, projectFile); QFETCH(bool, collisionExpected); try { const QString compositeProjectFilePath = QString("module-name-collisions/") + projectFile; QVERIFY(resolveProject(qPrintable(compositeProjectFilePath))); QVERIFY(!collisionExpected); } catch (const ErrorInfo &e) { const QString errorString = e.toString(); QVERIFY2(collisionExpected, qPrintable(errorString)); QVERIFY2(errorString.contains("not allowed"), qPrintable(errorString)); } } void TestLanguage::moduleParameters_data() { QTest::addColumn("inputProperties"); QTest::addColumn("expectedModuleParameters"); QTest::addColumn("errorExpected"); QTest::newRow("no overrides") << QVariantMap{ std::make_pair("project.overrideFromModule", "false"), std::make_pair("project.overrideFromExport", "false"), std::make_pair("project.overrideFromProduct", "false")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromParameters")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromParameters")})})} << false; QTest::newRow("override from product") << QVariantMap{ std::make_pair("project.overrideFromModule", "false"), std::make_pair("project.overrideFromExport", "false"), std::make_pair("project.overrideFromProduct", "true")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})})} << false; QTest::newRow("override from export") << QVariantMap{ std::make_pair("project.overrideFromModule", "false"), std::make_pair("project.overrideFromExport", "true"), std::make_pair("project.overrideFromProduct", "false")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromExportDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromParameters")})})} << false; QTest::newRow("override from export and product") << QVariantMap{ std::make_pair("project.overrideFromModule", "false"), std::make_pair("project.overrideFromExport", "true"), std::make_pair("project.overrideFromProduct", "true")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})})} << false; QTest::newRow("override from module") << QVariantMap{ std::make_pair("project.overrideFromModule", "true"), std::make_pair("project.overrideFromExport", "false"), std::make_pair("project.overrideFromProduct", "false")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromModuleDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromParameters")})})} << false; QTest::newRow("override from module and product") << QVariantMap{ std::make_pair("project.overrideFromModule", "true"), std::make_pair("project.overrideFromExport", "false"), std::make_pair("project.overrideFromProduct", "true")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})})} << false; QTest::newRow("override from module and export") << QVariantMap{ std::make_pair("project.overrideFromModule", "true"), std::make_pair("project.overrideFromExport", "true"), std::make_pair("project.overrideFromProduct", "false")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromExportDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromParameters")})})} << true; QTest::newRow("override from module, export and product") << QVariantMap{ std::make_pair("project.overrideFromModule", "true"), std::make_pair("project.overrideFromExport", "true"), std::make_pair("project.overrideFromProduct", "true")} << QVariantMap{ std::make_pair("higher", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})}), std::make_pair("dep", QVariantMap{std::make_pair("lower", QVariantMap{std::make_pair("param", "fromProductDepends")})})} << false; } void TestLanguage::moduleParameters() { QFETCH(QVariantMap, inputProperties); QFETCH(QVariantMap, expectedModuleParameters); QFETCH(bool, errorExpected); try { defaultParameters.setOverriddenValues(inputProperties); resolveProject("module-parameters/module-parameters.qbs"); QVERIFY(!errorExpected); QVERIFY(project); QCOMPARE(int(project->products.size()), 2); const ResolvedProductPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(mainProduct); QCOMPARE(int(mainProduct->moduleParameters.size()), 2); for (auto it = expectedModuleParameters.cbegin(); it != expectedModuleParameters.cend(); ++it) { const auto findInProduct = [&](const QString &moduleName) { for (auto it = mainProduct->moduleParameters.cbegin(); it != mainProduct->moduleParameters.cend(); ++it) { if (it.key()->name == moduleName) return it.value(); } return QVariantMap(); }; const QVariantMap actual = findInProduct(it.key()); const QVariantMap expected = it.value().toMap(); const bool same = qVariantMapsEqual(actual, expected); if (!same) { qDebug().noquote() << "---" << expected; qDebug().noquote() << "+++" << actual; } QVERIFY(same); } } catch (const ErrorInfo &e) { QVERIFY2(errorExpected, qPrintable(e.toString())); } } void TestLanguage::modulePrioritizationBySearchPath_data() { QTest::addColumn("searchPaths"); QTest::addColumn("expectedVariant"); QTest::newRow("foo has priority") << QStringList{"./foo", "./bar"} << "foo"; QTest::newRow("bar has priority") << QStringList{"./bar", "./foo"} << "bar"; } void TestLanguage::modulePrioritizationBySearchPath() { QFETCH(QStringList, searchPaths); QFETCH(QString, expectedVariant); bool exceptionCaught = false; try { defaultParameters.setOverriddenValues( {std::make_pair(QStringLiteral("project.qbsSearchPaths"), searchPaths)}); resolveProject("module-prioritization-by-search-path/project.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); const QString actualVariant = product->moduleProperties->moduleProperty ("conflicting-instances", "moduleVariant").toString(); QCOMPARE(actualVariant, expectedVariant); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::moduleProperties_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValue"); QTest::newRow("init") << QString() << QVariant(); QTest::newRow("merge_lists") << "defines" << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE"); QTest::newRow("merge_lists_and_values") << "defines" << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE"); QTest::newRow("merge_lists_with_duplicates") << "cxxFlags" << QVariant(QStringList() << "-foo" << "BAR" << "-foo" << "BAZ"); QTest::newRow("merge_lists_with_prototype_values") << "rpaths" << QVariant(QStringList() << "/opt/qt/lib" << "$ORIGIN"); QTest::newRow("list_property_that_references_product") << "listProp" << QVariant(QStringList() << "x" << "123"); QTest::newRow("list_property_depending_on_overridden_property") << "listProp2" << QVariant(QStringList() << "PRODUCT_STUFF" << "DEFAULT_STUFF" << "EXTRA_STUFF"); QTest::newRow("overridden_list_property") << "listProp" << QVariant(QStringList() << "PRODUCT_STUFF"); QTest::newRow("shadowed-list-property") << "defines" << QVariant(QStringList() << "MyProject" << "shadowed-list-property"); QTest::newRow("shadowed-scalar-property") << "someString" << QVariant(QString("MyProject_shadowed-scalar-property")); QTest::newRow("merged-varlist") << "varListProp" << QVariant(QVariantList() << QVariantMap({std::make_pair("d", "product")}) << QVariantMap({std::make_pair("c", "qtcore")}) << QVariantMap({std::make_pair("a", true), std::make_pair("b", QVariant())})); QTest::newRow("cleanup") << QString() << QVariant(); } void TestLanguage::moduleProperties() { HANDLE_INIT_CLEANUP_DATATAGS("moduleproperties.qbs"); QFETCH(QString, propertyName); QFETCH(QVariant, expectedValue); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); const QVariant value = product->moduleProperties->moduleProperty("dummy", propertyName); QCOMPARE(value, expectedValue); } void TestLanguage::modulePropertiesInGroups() { defaultParameters.setProjectFilePath(testProject("modulepropertiesingroups.qbs")); bool exceptionCaught = false; try { resolveProject(); QVERIFY(!!project); const QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("grouptest"); QVERIFY(!!product); GroupConstPtr g1; GroupConstPtr g11; GroupConstPtr g12; GroupConstPtr g2; GroupConstPtr g21; GroupConstPtr g211; for (const GroupPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g2") g2 = g; else if (g->name == "g1.1") g11 = g; else if (g->name == "g1.2") g12 = g; else if (g->name == "g2.1") g21 = g; else if (g->name == "g2.1.1") g211 = g; } QVERIFY(!!g1); QVERIFY(!!g2); QVERIFY(!!g11); QVERIFY(!!g12); QVERIFY(!!g21); QVERIFY(!!g211); const QVariantMap productProps = product->moduleProperties->value(); const auto &productGmod1List1 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(productGmod1List1, QStringList() << "gmod1_list1_proto" << "gmod1_string_proto"); const auto &productGmod1List2 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(productGmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto"); const auto &productGmod1List3 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(productGmod1List3, QStringList() << "product" << "gmod1_string_proto"); const int productP0 = moduleProperty(productProps, "gmod.gmod1", "p0").toInt(); QCOMPARE(productP0, 1); const int productDepProp = moduleProperty(productProps, "gmod.gmod1", "depProp").toInt(); QCOMPARE(productDepProp, 0); const auto &productGmod2String = moduleProperty(productProps, "gmod2", "gmod2_string") .toString(); QCOMPARE(productGmod2String, QString("gmod1_string_proto")); const auto &productGmod2List = moduleProperty(productProps, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(productGmod2List, QStringList() << "gmod1_string_proto" << "commonName_in_gmod1" << "gmod4_string_proto_gmod3_string_proto" << "gmod3_string_proto" << "gmod2_list_proto"); const QVariantMap g1Props = g1->properties->value(); const auto &g1Gmod1List1 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g1Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1"); const auto &g1Gmod1List2 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g1Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1"); const auto &g1Gmod1List3 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g1Gmod1List3, QStringList() << "product" << "g1"); const int g1P0 = moduleProperty(g1Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g1P0, 3); const int g1DepProp = moduleProperty(g1Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g1DepProp, 1); const auto &g1Gmod2String = moduleProperty(g1Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g1Gmod2String, QString("g1")); const auto &g1Gmod2List = moduleProperty(g1Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g1Gmod2List, QStringList() << "g1" << "commonName_in_gmod1" << "g1_gmod4_g1_gmod3" << "g1_gmod3" << "gmod2_list_proto"); const QVariantMap g11Props = g11->properties->value(); const auto &g11Gmod1List1 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g11Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1.1"); const auto &g11Gmod1List2 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g11Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1" << "g1.1"); const auto &g11Gmod1List3 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g11Gmod1List3, QStringList() << "product" << "g1.1"); const int g11P0 = moduleProperty(g11Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g11P0, 5); const int g11DepProp = moduleProperty(g11Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g11DepProp, 2); const auto &g11Gmod2String = moduleProperty(g11Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g11Gmod2String, QString("g1.1")); const auto &g11Gmod2List = moduleProperty(g11Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g11Gmod2List, QStringList() << "g1.1" << "commonName_in_gmod1" << "g1.1_gmod4_g1.1_gmod3" << "g1.1_gmod3" << "gmod2_list_proto"); const QVariantMap g12Props = g12->properties->value(); const auto &g12Gmod1List1 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g12Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1.2"); const auto &g12Gmod1List2 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g12Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1" << "g1.2"); const auto &g12Gmod1List3 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g12Gmod1List3, QStringList() << "product" << "g1.2"); const int g12P0 = moduleProperty(g12Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g12P0, 9); const int g12DepProp = moduleProperty(g12Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g12DepProp, 1); const auto &g12Gmod2String = moduleProperty(g12Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g12Gmod2String, QString("g1.2")); const auto &g12Gmod2List = moduleProperty(g12Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g12Gmod2List, QStringList() << "g1.2" << "commonName_in_gmod1" << "g1_gmod4_g1.2_gmod3" << "g1.2_gmod3" << "gmod2_list_proto"); const QVariantMap g2Props = g2->properties->value(); const auto &g2Gmod1List1 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g2Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g2Gmod1List2 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto"); const int g2P0 = moduleProperty(g2Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g2P0, 6); const int g2DepProp = moduleProperty(g2Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g2DepProp, 2); const auto &g2Gmod2String = moduleProperty(g2Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g2Gmod2String, QString("g2")); const auto &g2Gmod2List = moduleProperty(g2Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g2Gmod2List, QStringList() << "g2" << "commonName_in_gmod1" << "g2_gmod4_g2_gmod3" << "g2_gmod3" << "gmod2_list_proto"); const QVariantMap g21Props = g21->properties->value(); const auto &g21Gmod1List1 = moduleProperty(g21Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g21Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g21Gmod1List2 = moduleProperty(g21Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QEXPECT_FAIL(nullptr, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod1List2, QStringList() << "grouptest" << "g2.1" << "gmod1_list2_proto"); const int g21P0 = moduleProperty(g21Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g21P0, 6); const int g21DepProp = moduleProperty(g21Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g21DepProp, 2); const auto &g21Gmod2String = moduleProperty(g21Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g21Gmod2String, QString("g2")); const auto &g21Gmod2List = moduleProperty(g21Props, "gmod2", "gmod2_list") .toStringList(); QEXPECT_FAIL(nullptr, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod2List, QStringList() << "g2" << "commonName_in_gmod1" << "g2.1_gmod4_g2.1_gmod3" << "g2.1_gmod3" << "gmod2_list_proto"); const QVariantMap g211Props = g211->properties->value(); const auto &g211Gmod1List1 = moduleProperty(g211Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g211Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g211Gmod1List2 = moduleProperty(g211Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g211Gmod1List2, QStringList() << "g2.1.1"); const int g211P0 = moduleProperty(g211Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g211P0, 17); const int g211DepProp = moduleProperty(g211Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g211DepProp, 2); const auto &g211Gmod2String = moduleProperty(g211Props, "gmod2", "gmod2_string").toString(); QEXPECT_FAIL(nullptr, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2String, QString("g2.1.1")); const auto &g211Gmod2List = moduleProperty(g211Props, "gmod2", "gmod2_list") .toStringList(); QEXPECT_FAIL(nullptr, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2List, QStringList() << "g2.1.1" << "commonName_in_gmod1" << "g2.1.1_gmod4_g2.1.1_gmod3" << "g2.1.1_gmod3" << "gmod2_list_proto"); product = products.value("grouptest2"); QVERIFY(!!product); g1.reset(); g11.reset(); for (const GroupPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g1.1") g11 = g; } QVERIFY(!!g1); QVERIFY(!!g11); QCOMPARE(moduleProperty(g1->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList(), QStringList({"G1"})); QCOMPARE(moduleProperty(g11->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList(), moduleProperty(g1->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList()); QCOMPARE(moduleProperty(g11->properties->value(), "gmod.gmod1", "gmod1_string").toString(), QString("G1.1")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modulePropertyOverridesPerProduct() { bool exceptionCaught = false; try { defaultParameters.setOverriddenValues({ std::make_pair("modules.dummy.rpaths", QStringList({"/usr/lib"})), std::make_pair("modules.dummy.someString", "m"), std::make_pair("products.b.dummy.someString", "b"), std::make_pair("products.c.dummy.someString", "c"), std::make_pair("products.c.dummy.rpaths", QStringList({"/home", "/tmp"})) }); resolveProject("module-property-overrides-per-product.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 3); const ResolvedProductConstPtr a = products.value("a"); QVERIFY(!!a); const ResolvedProductConstPtr b = products.value("b"); QVERIFY(!!b); const ResolvedProductConstPtr c = products.value("c"); QVERIFY(!!c); const auto stringPropertyValue = [](const ResolvedProductConstPtr &p) -> QString { return p->moduleProperties->moduleProperty("dummy", "someString").toString(); }; const auto listPropertyValue = [](const ResolvedProductConstPtr &p) -> QStringList { return p->moduleProperties->moduleProperty("dummy", "rpaths").toStringList(); }; const auto productPropertyValue = [](const ResolvedProductConstPtr &p) -> QStringList { return p->productProperties.value("rpaths").toStringList(); }; QCOMPARE(stringPropertyValue(a), QString("m")); QCOMPARE(stringPropertyValue(b), QString("b")); QCOMPARE(stringPropertyValue(c), QString("c")); QCOMPARE(listPropertyValue(a), QStringList({"/usr/lib"})); QCOMPARE(listPropertyValue(b), QStringList({"/usr/lib"})); QCOMPARE(listPropertyValue(c), QStringList({"/home", "/tmp"})); QCOMPARE(listPropertyValue(a), productPropertyValue(a)); QCOMPARE(listPropertyValue(b), productPropertyValue(b)); QCOMPARE(listPropertyValue(c), productPropertyValue(c)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::moduleScope() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("modulescope.qbs")); resolveProject(); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); auto intModuleValue = [product] (const QString &name) -> int { return product->moduleProperties->moduleProperty("scopemod", name).toInt(); }; QCOMPARE(intModuleValue("a"), 2); // overridden in module instance QCOMPARE(intModuleValue("b"), 1); // genuine QCOMPARE(intModuleValue("c"), 3); // genuine, dependent on overridden value QCOMPARE(intModuleValue("d"), 2); // genuine, dependent on genuine value QCOMPARE(intModuleValue("e"), 1); // genuine QCOMPARE(intModuleValue("f"), 2); // overridden QCOMPARE(intModuleValue("g"), 156); // overridden, dependent on product properties QCOMPARE(intModuleValue("h"), 158); // overridden, base dependent on product properties } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::moduleWithProductDependency() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("module-depends-on-product.qbs")); resolveProject(); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); ResolvedProductPtr product = products.value("p1"); QVERIFY(product); QCOMPARE(int(product->dependencies.size()), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modules_data() { QTest::addColumn("expectedModulesInProduct"); QTest::addColumn("expectedProductProperty"); QTest::newRow("init") << QStringList(); QTest::newRow("no_modules") << (QStringList() << "qbs") << QString(); QTest::newRow("qt_core") << (QStringList() << "qbs" << "dummy" << "dummyqt.core") << QString("1.2.3"); QTest::newRow("qt_gui") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui") << QString("guiProperty"); QTest::newRow("qt_gui_network") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui" << "dummyqt.network") << QString("guiProperty,networkProperty"); QTest::newRow("deep_module_name") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax1") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax2") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("dummy_twice") << (QStringList() << "qbs" << "dummy") << QString(); QTest::newRow("cleanup") << QStringList(); } void TestLanguage::modules() { HANDLE_INIT_CLEANUP_DATATAGS("modules.qbs"); QFETCH(QStringList, expectedModulesInProduct); QFETCH(QString, expectedProductProperty); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); const ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QStringList modulesInProduct; for (ResolvedModuleConstPtr m : product->modules) modulesInProduct += m->name; modulesInProduct.sort(); expectedModulesInProduct.sort(); QCOMPARE(modulesInProduct, expectedModulesInProduct); QCOMPARE(product->productProperties.value("foo").toString(), expectedProductProperty); } void TestLanguage::multipleModuleBackendsViaOwnProperty_data() { QTest::addColumn("type"); QTest::addColumn("expectedValue"); QTest::newRow("default") << QString() << QString("value1"); QTest::newRow("no-op override") << QString("type1") << QString("value1"); QTest::newRow("actual override") << QString("type2") << QString("value2"); } void TestLanguage::multipleModuleBackendsViaOwnProperty() { QFETCH(QString, type); QFETCH(QString, expectedValue); bool exceptionCaught = false; try { if (!type.isEmpty()) { defaultParameters.setOverriddenValues( {{"modules.multiple_backends_via_own_property.type", type}}); } resolveProject("multiple-module-backends-via-own-property.qbs"); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(1)); QCOMPARE( products.front() ->moduleProperties->moduleProperty("multiple_backends_via_own_property", "value") .toString(), expectedValue); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::multiplexedExports() { bool exceptionCaught = false; try { resolveProject("multiplexed-exports.qbs"); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(4)); std::set pVariants; for (const auto &product : products) { if (product->name != "p") continue; static const auto buildVariant = [](const ResolvedProductConstPtr &p) { return p->moduleProperties->qbsPropertyValue("buildVariant").toString(); }; static const auto cppIncludePaths = [](const ResolvedProductConstPtr &p) { return p->moduleProperties->moduleProperty("cpp", "includePaths").toStringList(); }; if (buildVariant(product) == "debug") { pVariants.insert(product); QCOMPARE(cppIncludePaths(product), QStringList("/d")); } else if (buildVariant(product) == "release") { pVariants.insert(product); QCOMPARE(cppIncludePaths(product), QStringList("/r")); } } QCOMPARE(int(pVariants.size()), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::multiplexingByProfile() { QFETCH(QString, projectFileName); QFETCH(bool, successExpected); try { defaultParameters.setDryRun(true); resolveProject(qPrintable("/multiplexing-by-profile/" + projectFileName)); QVERIFY(successExpected); QVERIFY(!!project); } catch (const ErrorInfo &e) { QVERIFY2(!successExpected, qPrintable(e.toString())); } } void TestLanguage::multiplexingByProfile_data() { QTest::addColumn("projectFileName"); QTest::addColumn("successExpected"); QTest::newRow("same profile") << "p1.qbs" << true; QTest::newRow("dependency on non-multiplexed") << "p2.qbs" << true; QTest::newRow("dependency by non-multiplexed") << "p3.qbs" << false; QTest::newRow("dependency by non-multiplexed with Depends.profile") << "p4.qbs" << true; } void TestLanguage::nonApplicableModulePropertyInProfile() { QFETCH(QString, targetOS); QFETCH(QString, toolchain); QFETCH(bool, successExpected); try { defaultParameters.setOverriddenValues({std::make_pair("project.targetOS", targetOS), std::make_pair("project.toolchain", toolchain)}); resolveProject("non-applicable-module-property-in-profile.qbs"); QVERIFY(!!project); QVERIFY(successExpected); } catch (const ErrorInfo &e) { QVERIFY2(!successExpected, qPrintable(e.toString())); QVERIFY2(e.toString().contains("Loading module 'multiple_backends' for product 'p' failed " "due to invalid values in profile 'theProfile'"), qPrintable(e.toString())); QVERIFY2(e.toString().contains("backend3Prop"), qPrintable(e.toString())); } } void TestLanguage::nonApplicableModulePropertyInProfile_data() { QTest::addColumn("targetOS"); QTest::addColumn("toolchain"); QTest::addColumn("successExpected"); QTest::newRow("no matching property (1)") << "os1" << QString() << false; QTest::newRow("no matching property (2)") << "os2" << QString() << false; // The point here is that there's a second, lower-prioritized candidate with a matching // condition that doesn't have the property. This candidate must not throw an error. QTest::newRow("matching property") << "os2" << "tc" << true; } void TestLanguage::nonRequiredProducts() { bool exceptionCaught = false; try { QFETCH(bool, subProjectEnabled); QFETCH(bool, dependeeEnabled); QVariantMap overriddenValues; if (!subProjectEnabled) overriddenValues.insert("projects.subproject.condition", false); else if (!dependeeEnabled) overriddenValues.insert("products.dependee.condition", false); defaultParameters.setOverriddenValues(overriddenValues); resolveProject("non-required-products.qbs"); QVERIFY(!!project); const auto products = productsFromProject(project); QCOMPARE(products.size(), 4 + !!subProjectEnabled); const ResolvedProductConstPtr dependee = products.value("dependee"); QCOMPARE(subProjectEnabled, !!dependee); if (dependee) QCOMPARE(dependeeEnabled, dependee->enabled); const ResolvedProductConstPtr depender = products.value("depender"); QVERIFY(!!depender); const QStringList defines = depender->moduleProperties->moduleProperty("dummy", "defines") .toStringList(); QCOMPARE(subProjectEnabled && dependeeEnabled, defines.contains("WITH_DEPENDEE")); for (const auto &name : std::vector({ "p3", "p2", "p1"})) { const ResolvedProductConstPtr &product = products.value(name); QVERIFY2(product, name); QVERIFY2(!product->enabled, name); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::nonRequiredProducts_data() { QTest::addColumn("subProjectEnabled"); QTest::addColumn("dependeeEnabled"); QTest::newRow("dependee enabled") << true << true; QTest::newRow("dependee disabled") << true << false; QTest::newRow("sub project disabled") << false << true; } void TestLanguage::outerInGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs")); resolveProject(); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("OuterInGroup"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(3)); GroupPtr group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, product->name); QVERIFY(group->files); QCOMPARE(group->files->size(), size_t(1)); SourceArtifactConstPtr artifact = group->files->front(); QVariant installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere")); group = product->groups.at(2); QVERIFY(!!group); QCOMPARE(group->name, QString("Special Group")); QVERIFY(group->files); QCOMPARE(group->files->size(), size_t(1)); artifact = group->files->front(); installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere/else")); const QVariant stringProp = artifact->properties->moduleProperty("dummy", "someString"); QCOMPARE(stringProp.toString(), "s1s2s3"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::overrideProductPropFromSubProjectItem() { bool exceptionCaught = false; try { resolveProject("override-product-prop-from-subproject-item.qbs"); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(1)); QCOMPARE(products.front()->productProperties.value("theProp").toString(), "overridden"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::overriddenPropertiesAndPrototypes() { bool exceptionCaught = false; try { QFETCH(QString, osName); QFETCH(QString, backendName); defaultParameters.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", osName)}); resolveProject("overridden-properties-and-prototypes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->moduleProperty( "multiple_backends", "prop").toString(), backendName); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::overriddenPropertiesAndPrototypes_data() { QTest::addColumn("osName"); QTest::addColumn("backendName"); QTest::newRow("first backend") << "os1" << "backend 1"; QTest::newRow("second backend") << "os2" << "backend 2"; } void TestLanguage::overriddenVariantProperty() { bool exceptionCaught = false; try { const QVariantMap objectValue{std::make_pair("x", 1), std::make_pair("y", 2)}; defaultParameters.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); resolveProject("overridden-variant-property.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->productProperties.value("myObject").toMap(), objectValue); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::parameterTypes() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("parameter-types.qbs")); resolveProject(); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::projectPropertyForwarding() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("project-property-forwarding.qbs")); resolveProject(); QVERIFY(project); QCOMPARE(project->projectProperties().value("prop").toString(), "parent"); QCOMPARE(int(project->subProjects.size()), 1); QCOMPARE( project->subProjects.front()->projectProperties().value("prop").toString(), "parent2"); QCOMPARE(int(project->subProjects.front()->subProjects.size()), 1); QCOMPARE( project->subProjects.front() ->subProjects.front() ->projectProperties() .value("prop") .toString(), "parent22"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::pathProperties() { bool exceptionCaught = false; try { resolveProject("pathproperties.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QString projectFileDir = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); const QVariantMap productProps = product->productProperties; QCOMPARE(productProps.value("projectFileDir").toString(), projectFileDir); QStringList filesInProjectFileDir = QStringList() << FileInfo::resolvePath(projectFileDir, "aboutdialog.h") << FileInfo::resolvePath(projectFileDir, "aboutdialog.cpp"); QCOMPARE(productProps.value("filesInProjectFileDir").toStringList(), filesInProjectFileDir); QStringList includePaths = product->moduleProperties->property( QStringList() << "dummy" << "includePaths").toStringList(); QCOMPARE(includePaths, QStringList() << projectFileDir); QCOMPARE(productProps.value("base_fileInProductDir").toString(), FileInfo::resolvePath(projectFileDir, QStringLiteral("foo"))); QCOMPARE(productProps.value("base_fileInBaseProductDir").toString(), FileInfo::resolvePath(projectFileDir, QStringLiteral("subdir/bar"))); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::probesAndMultiplexing() { bool exceptionCaught = false; try { resolveProject("probes-and-multiplexing.qbs"); QVERIFY(project); QCOMPARE(int(project->products.size()), 3); QStringList architectures{"x86", "x86_64", "arm"}; for (const ResolvedProductPtr &product : project->products) { const QString arch = product->moduleProperties->moduleProperty("qbs", "architecture") .toString(); QVERIFY2(architectures.removeOne(arch), qPrintable(arch)); QCOMPARE(product->productProperties.value("archFromProbe").toString(), arch); bool foundGroup = false; for (const GroupPtr &group : product->groups) { if (group->name == "theGroup") { foundGroup = true; QCOMPARE(group->properties->moduleProperty("qbs", "sysroot"), "/" + arch); } } QVERIFY(foundGroup); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::profileValuesAndOverriddenValues() { bool exceptionCaught = false; try { TemporaryProfile tp(QStringLiteral("tst_lang_profile"), m_settings); Profile profile = tp.p; profile.setValue("dummy.defines", "IN_PROFILE"); profile.setValue("dummy.cFlags", "IN_PROFILE"); profile.setValue("dummy.cxxFlags", "IN_PROFILE"); profile.setValue("qbs.architecture", "x86"); defaultParameters.setTopLevelProfile(profile.name()); QVariantMap overriddenValues; overriddenValues.insert("modules.dummy.cFlags", "OVERRIDDEN"); defaultParameters.setOverriddenValues(overriddenValues); resolveProject("profilevaluesandoverriddenvalues.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantList values; values = product->moduleProperties->moduleProperty("dummy", "cxxFlags").toList(); QCOMPARE(values.length(), 1); QCOMPARE(values.front().toString(), QString("IN_PROFILE")); values = product->moduleProperties->moduleProperty("dummy", "defines").toList(); QCOMPARE(values, QVariantList() << QStringLiteral("IN_FILE") << QStringLiteral("IN_PROFILE")); values = product->moduleProperties->moduleProperty("dummy", "cFlags").toList(); QCOMPARE(values.length(), 1); QCOMPARE(values.front().toString(), QString("OVERRIDDEN")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::projectFileLookup() { QFETCH(QString, projectFileInput); QFETCH(QString, projectFileOutput); QFETCH(bool, failureExpected); try { SetupProjectParameters params; params.setProjectFilePath(projectFileInput); params.finalizeProjectFilePath(); QVERIFY(!failureExpected); QCOMPARE(params.projectFilePath(), projectFileOutput); } catch (const ErrorInfo &) { QVERIFY(failureExpected); } } void TestLanguage::projectFileLookup_data() { QTest::addColumn("projectFileInput"); QTest::addColumn("projectFileOutput"); QTest::addColumn("failureExpected"); const QString baseDir = testDataDir(); const QString multiProjectsDir = baseDir + "/dirwithmultipleprojects"; const QString noProjectsDir = baseDir + "/dirwithnoprojects"; const QString oneProjectDir = baseDir + "/dirwithoneproject"; QVERIFY(QDir(noProjectsDir).exists() && QDir(oneProjectDir).exists() && QDir(multiProjectsDir).exists()); const QString fullFilePath = multiProjectsDir + "/project.qbs"; QTest::newRow("full file path") << fullFilePath << fullFilePath << false; QTest::newRow("base dir ") << oneProjectDir << (oneProjectDir + "/project.qbs") << false; QTest::newRow("empty dir") << noProjectsDir << QString() << true; QTest::newRow("ambiguous dir") << multiProjectsDir << QString() << true; } void TestLanguage::productConditions() { bool exceptionCaught = false; try { resolveProject("productconditions.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 6); ResolvedProductPtr product; product = products.value("product_no_condition"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_true_condition"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_condition_dependent_of_module"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_false_condition"); QVERIFY(!!product); QVERIFY(!product->enabled); product = products.value("product_probe_condition_false"); QVERIFY(!!product); QVERIFY(!product->enabled); product = products.value("product_probe_condition_true"); QVERIFY(!!product); QVERIFY(product->enabled); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::productDirectories() { bool exceptionCaught = false; try { resolveProject("productdirectories.qbs"); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product; product = products.value("MyApp"); QVERIFY(!!product); const QVariantMap config = product->productProperties; QCOMPARE(config.value(QStringLiteral("buildDirectory")).toString(), product->buildDirectory()); QCOMPARE(config.value(QStringLiteral("sourceDirectory")).toString(), testDataDir()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertiesBlocks_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValue"); QTest::addColumn("expectedStringValue"); QTest::newRow("init") << QString() << QVariant() << QString(); QTest::newRow("property_append") << QString("dummy.defines") << QVariant(QStringList{"APPENDED", "SOMETHING"}) << QString(); QTest::newRow("property_set_indirect") << QString("dummy.cFlags") << QVariant(QStringList("VAL")) << QString(); QTest::newRow("property_overwrite") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("property_append_indirect") << QString("dummy.defines") << QVariant(QStringList{"TWO", "ONE"}) << QString(); QTest::newRow("property_append_to_indirect_derived") << QString("dummy.cFlags") << QVariant(QStringList{"BASE", "PROPS"}) << QString(); QTest::newRow("property_append_to_indirect_derived2") << QString("dummy.cFlags") << QVariant(QStringList{"PROPS", "PRODUCT"}) << QString(); QTest::newRow("property_append_to_indirect_derived3") << QString("dummy.cFlags") << QVariant(QStringList{"PROPS", "BASE", "PRODUCT"}) << QString(); QTest::newRow("property_append_to_indirect_merged") << QString("dummy.rpaths") << QVariant(QStringList{"TWO", "ONE", "$ORIGIN"}) << QString(); QTest::newRow("multiple_exclusive_properties") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("multiple_exclusive_properties_no_match") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("multiple_exclusive_properties_append") << QString("dummy.defines") << QVariant(QStringList{"TWO", "ONE"}) << QString(); QTest::newRow("condition_refers_to_product_property") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString("OVERWRITTEN"); QTest::newRow("condition_refers_to_project_property") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString("OVERWRITTEN"); QTest::newRow("ambiguous_properties") << QString("dummy.defines") << QVariant(QStringList{"TWO", "THREE", "ONE"}) << QString(); QTest::newRow("inheritance_overwrite_in_subitem") << QString("dummy.defines") << QVariant(QStringList() << QString("OVERWRITTEN_IN_SUBITEM")) << QString(); QTest::newRow("inheritance_retain_base1") << QString("dummy.defines") << QVariant(QStringList{"BASE", "SOMETHING", "SUB"}) << QString(); QTest::newRow("inheritance_retain_base2") << QString("dummy.defines") << QVariant(QStringList{"BASE", "SOMETHING", "SUB"}) << QString(); QTest::newRow("inheritance_retain_base3") << QString("dummy.defines") << QVariant(QStringList{"BASE", "SOMETHING", "SUB"}) << QString(); QTest::newRow("inheritance_retain_base4") << QString("dummy.defines") << QVariant(QStringList{"BASE", "SOMETHING"}) << QString(); QTest::newRow("inheritance_condition_in_subitem1") << QString("dummy.defines") << QVariant(QStringList() << QString("SOMETHING") << QString("SUB")) << QString(); QTest::newRow("inheritance_condition_in_subitem2") << QString("dummy.defines") << QVariant(QStringList() << QString("SOMETHING")) << QString(); QTest::newRow("condition_references_id") << QString("dummy.defines") << QVariant(QStringList() << QString("OVERWRITTEN")) << QString(); QTest::newRow("using_derived_Properties_item") << "dummy.defines" << QVariant(QStringList() << "string from MyProperties") << QString(); QTest::newRow("conditional-depends") << QString("dummy.defines") << QVariant() << QString(); QTest::newRow("use-module-with-properties-item") << QString("module-with-properties-item.stringProperty") << QVariant(QString("overridden in Properties item")) << QString(); QTest::newRow("cleanup") << QString() << QVariant() << QString(); } void TestLanguage::propertiesBlocks() { defaultParameters.setDeprecationWarningMode(DeprecationWarningMode::On); HANDLE_INIT_CLEANUP_DATATAGS("propertiesblocks.qbs"); QFETCH(QString, propertyName); QFETCH(QVariant, expectedValue); QFETCH(QString, expectedStringValue); QVERIFY(!!project); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QVariant v = productPropertyValue(product, propertyName); QCOMPARE(v, expectedValue); if (!expectedStringValue.isEmpty()) { v = productPropertyValue(product, "someString"); QCOMPARE(v.toString(), expectedStringValue); } } void TestLanguage::propertiesBlockInGroup_data() { QTest::addColumn("withGroup"); QTest::addColumn("moduleGroup"); QTest::addColumn("expectedValue"); QTest::newRow("with group, use primary module group") << true << "module_group" << QStringList{"FEATURE_ENABLED", "THE_GROUP", "BASEDEF", "MODULE_DEFINE", "MODULE_GROUP"}; QTest::newRow("with group, use alternative module group") << true << "module_group_alt" << QStringList{ "FEATURE_ENABLED", "THE_GROUP", "BASEDEF", "MODULE_DEFINE", "MODULE_GROUP_ALT"}; QTest::newRow("without group, use primary module group") << false << "module_group" << QStringList{"BASEDEF", "MODULE_DEFINE", "MODULE_GROUP"}; QTest::newRow("without group, use alternative module group") << false << "module_group_alt" << QStringList{"BASEDEF", "MODULE_DEFINE", "MODULE_GROUP_ALT"}; } void TestLanguage::propertiesBlockInGroup() { QFETCH(bool, withGroup); QFETCH(QString, moduleGroup); QFETCH(QStringList, expectedValue); bool exceptionCaught = false; try { defaultParameters.setOverriddenValues( {std::make_pair(QString("products.in-group.featureEnabled"), withGroup), std::make_pair(QString("modules.module_with_group.group"), moduleGroup)}); resolveProject("properties-block-in-group.qbs"); QVERIFY(!!project); QCOMPARE(project->allProducts().size(), size_t(1)); const ResolvedProductConstPtr product = project->allProducts().front(); const QStringList productValue = moduleProperty(product->moduleProperties->value(), "dummy", "defines").toStringList(); QCOMPARE(productValue, expectedValue); const auto groupIt = std::find_if(product->groups.cbegin(), product->groups.cend(), [](const GroupConstPtr &g) { return g->name == "the group"; }); QVERIFY(groupIt != product->groups.cend()); const QStringList groupValue = moduleProperty((*groupIt)->properties->value(), "dummy", "defines").toStringList(); QCOMPARE(groupValue, QStringList{"GROUP_ONLY"}); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertiesItemInModule() { bool exceptionCaught = false; try { resolveProject("properties-item-in-module.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); for (const ResolvedProductPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "productName").toString(), p->name); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertyAssignmentInExportedGroup() { bool exceptionCaught = false; try { resolveProject("property-assignment-in-exported-group.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); for (const ResolvedProductPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "someString").toString(), QString()); for (const GroupPtr &g : p->groups) { const QString propValue = g->properties->moduleProperty("dummy", "someString").toString(); if (g->name == "exported_group") QCOMPARE(propValue, QString("test")); else QCOMPARE(propValue, QString()); } } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbs1275() { bool exceptionCaught = false; try { resolveProject("qbs1275.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.count(), 5); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbsPropertiesInProjectCondition() { bool exceptionCaught = false; try { resolveProject("qbs-properties-in-project-condition.qbs"); QVERIFY(!!project); QVERIFY(!project->enabled); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbsPropertyConvenienceOverride() { bool exceptionCaught = false; try { defaultParameters.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); resolveProject("qbs-property-convenience-override.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->qbsPropertyValue("installPrefix") .toString(), QString("/opt")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::relaxedErrorMode() { m_logSink->setLogLevel(LoggerMinLevel); QFETCH(bool, strictMode); try { defaultParameters.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict : ErrorHandlingMode::Relaxed); resolveProject("relaxed-error-mode/relaxed-error-mode.qbs"); QVERIFY(!strictMode); const auto productMap = productsFromProject(project); const ResolvedProductConstPtr brokenProduct = productMap.value("broken"); QVERIFY(!brokenProduct->enabled); QVERIFY(brokenProduct->location.isValid()); QCOMPARE(brokenProduct->allFiles().size(), size_t(0)); const ResolvedProductConstPtr dependerRequired = productMap.value("depender required"); QVERIFY(!dependerRequired->enabled); QVERIFY(dependerRequired->location.isValid()); QCOMPARE(dependerRequired->allFiles().size(), size_t(1)); const ResolvedProductConstPtr dependerNonRequired = productMap.value("depender nonrequired"); QVERIFY(dependerNonRequired->enabled); QCOMPARE(dependerNonRequired->allFiles().size(), size_t(1)); const ResolvedProductConstPtr recursiveDepender = productMap.value("recursive depender"); QVERIFY(!recursiveDepender->enabled); QVERIFY(recursiveDepender->location.isValid()); QCOMPARE(recursiveDepender->allFiles().size(), size_t(1)); const ResolvedProductConstPtr missingFile = productMap.value("missing file"); QVERIFY(missingFile->enabled); QCOMPARE(missingFile->groups.size(), size_t(1)); QVERIFY(missingFile->groups.front()->enabled); QVERIFY(missingFile->groups.front()->files); QCOMPARE(missingFile->groups.front()->files->size(), size_t(2)); const ResolvedProductConstPtr fine = productMap.value("fine"); QVERIFY(fine->enabled); QCOMPARE(fine->allFiles().size(), size_t(1)); } catch (const ErrorInfo &e) { QVERIFY2(strictMode, qPrintable(e.toString())); } } void TestLanguage::relaxedErrorMode_data() { QTest::addColumn("strictMode"); QTest::newRow("strict mode") << true; QTest::newRow("relaxed mode") << false; } void TestLanguage::requiredAndNonRequiredDependencies() { QFETCH(QString, projectFile); QFETCH(bool, exceptionExpected); try { resolveProject(qPrintable("required-and-nonrequired-dependencies/" + projectFile)); QVERIFY(!!project); QVERIFY(!exceptionExpected); } catch (const ErrorInfo &e) { QVERIFY(exceptionExpected); QVERIFY2(e.toString().contains("validation error!"), qPrintable(e.toString())); } } void TestLanguage::requiredAndNonRequiredDependencies_data() { QTest::addColumn("projectFile"); QTest::addColumn("exceptionExpected"); QTest::newRow("same file") << "direct-dependencies.qbs" << true; QTest::newRow("dependency via module") << "dependency-via-module.qbs" << true; QTest::newRow("dependency via export") << "dependency-via-export.qbs" << true; QTest::newRow("more indirection") << "complicated.qbs" << true; QTest::newRow("required chain (module)") << "required-chain-module.qbs" << false; QTest::newRow("required chain (export)") << "required-chain-export.qbs" << false; QTest::newRow("required chain (export indirect)") << "required-chain-export-indirect.qbs" << false; } void TestLanguage::suppressedAndNonSuppressedErrors() { try { resolveProject("suppressed-and-non-suppressed-errors.qbs"); QFAIL("failure expected"); } catch (const ErrorInfo &e) { QVERIFY2(e.toString().contains("easter bunny"), qPrintable(e.toString())); QVERIFY2(!e.toString().contains("TheBeautifulSausage"), qPrintable(e.toString())); } } void TestLanguage::throwingProbe() { QFETCH(bool, enableProbe); try { QVariantMap properties; properties.insert(QStringLiteral("products.theProduct.enableProbe"), enableProbe); defaultParameters.setOverriddenValues(properties); resolveProject("throwing-probe.qbs"); QVERIFY(!!project); QVERIFY(!enableProbe); } catch (const ErrorInfo &e) { QVERIFY2(enableProbe, qPrintable(e.toString())); } } void TestLanguage::throwingProbe_data() { QTest::addColumn("enableProbe"); QTest::newRow("enabled probe") << true; QTest::newRow("disabled probe") << false; } void TestLanguage::qualifiedId() { QString str = "foo.bar.baz"; QualifiedId id = QualifiedId::fromString(str); QCOMPARE(id.size(), 3); QCOMPARE(id.toString(), str); id = QualifiedId("blubb.di.blubb"); // c'tor does not split QCOMPARE(id.size(), 1); QList ids; ids << QualifiedId::fromString("a") << QualifiedId::fromString("a.a") << QualifiedId::fromString("b") << QualifiedId::fromString("c.a") << QualifiedId::fromString("c.b.a") << QualifiedId::fromString("c.c"); QList sorted = ids; std::sort(sorted.begin(), sorted.end()); QCOMPARE(ids, sorted); } void TestLanguage::recursiveProductDependencies() { bool exceptionCaught = false; try { resolveProject("recursive-dependencies/recursive-dependencies.qbs"); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 4); const ResolvedProductConstPtr p1 = products.value("p1"); QVERIFY(!!p1); const ResolvedProductConstPtr p2 = products.value("p2"); QVERIFY(!!p2); const ResolvedProductPtr p3 = products.value("p3"); QVERIFY(!!p3); const ResolvedProductPtr p4 = products.value("p4"); QVERIFY(!!p4); QVERIFY(p1->depsAsProductList() == std::vector({p3, p4})); QVERIFY(p2->depsAsProductList() == std::vector({p3, p4})); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileTags_data() { QTest::addColumn("numberOfGroups"); QTest::addColumn("expectedFileTags"); QTest::newRow("init") << size_t(0) << QStringList(); QTest::newRow("filetagger_project_scope") << size_t(1) << (QStringList() << "cpp"); QTest::newRow("filetagger_product_scope") << size_t(1) << (QStringList() << "asm"); QTest::newRow("filetagger_static_pattern") << size_t(1) << (QStringList() << "yellow"); QTest::newRow("unknown_file_tag") << size_t(1) << (QStringList() << "unknown-file-tag"); QTest::newRow("set_file_tag_via_group") << size_t(2) << (QStringList() << "c++"); QTest::newRow("override_file_tag_via_group") << size_t(2) << (QStringList() << "c++"); QTest::newRow("add_file_tag_via_group") << size_t(2) << (QStringList() << "cpp" << "zzz"); QTest::newRow("prioritized_filetagger") << size_t(1) << (QStringList() << "cpp1" << "cpp2"); QTest::newRow("cleanup") << size_t(0) << QStringList(); } void TestLanguage::fileTags() { HANDLE_INIT_CLEANUP_DATATAGS("filetags.qbs"); QFETCH(size_t, numberOfGroups); QFETCH(QStringList, expectedFileTags); QHash products = productsFromProject(project); ResolvedProductPtr product; const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); QVERIFY(!!(product = products.value(productName))); QCOMPARE(product->groups.size(), numberOfGroups); GroupPtr group = *(product->groups.end() - 1); QVERIFY(!!group); QVERIFY(group->files); QCOMPARE(group->files->size(), size_t(1)); SourceArtifactConstPtr sourceFile = group->files->front(); QStringList fileTags = sourceFile->fileTags.toStringList(); fileTags.sort(); QCOMPARE(fileTags, expectedFileTags); } void TestLanguage::useInternalProfile() { const QString profile(QStringLiteral("theprofile")); defaultParameters.setTopLevelProfile(profile); resolveProject("use-internal-profile.qbs"); QVERIFY(!!project); QCOMPARE(project->profile(), profile); QCOMPARE(project->products.size(), size_t(1)); const ResolvedProductConstPtr product = project->products[0]; QCOMPARE(product->profile(), profile); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "defines").toString(), profile); } void TestLanguage::wildcards_data() { QTest::addColumn("useGroup"); QTest::addColumn("filesToCreate"); QTest::addColumn("projectFileSubDir"); QTest::addColumn("prefix"); QTest::addColumn("patterns"); QTest::addColumn("excludePatterns"); QTest::addColumn("expected"); const bool useGroup = true; for (int i = 0; i <= 1; ++i) { const bool useGroup = i; const QByteArray dataTagSuffix = useGroup ? " group" : " nogroup"; QTest::newRow(QByteArray("simple 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h") << QStringList() << (QStringList() << "foo.h" << "bar.h"); QTest::newRow(QByteArray("simple 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "foo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("simple 3") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << QStringList() << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("exclude 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << (QStringList() << "bar*") << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("exclude 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*") << (QStringList() << "*.qbs") << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("non-recursive") + dataTagSuffix) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/*") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp"); QTest::newRow(QByteArray("absolute paths") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << m_wildcardsTestDirPath + "/?oo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("relative paths with dotdot") + dataTagSuffix) << useGroup << (QStringList() << "bar.h" << "bar.cpp") << QString("TheLaughingLlama") << QString() << (QStringList() << "../bar.*") << QStringList() << (QStringList() << "bar.h" << "bar.cpp"); } QTest::newRow(QByteArray("recursive 1")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("recursive 2")) << useGroup << (QStringList() << "d/1.h" << "b/d/1.h" << "b/c/d/1.h" << "d/e/1.h" << "b/d/e/1.h" << "b/c/d/e/1.h" << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h" << "a/d/e/1.h" << "a/b/d/e/1.h" << "a/b/c/d/e/1.h" << "a/d/1.cpp" << "a/b/d/1.cpp" << "a/b/c/d/1.h" << "a/d/e/1.cpp" << "a/b/d/e/1.cpp" << "a/b/c/d/e/1.cpp") << QString() << QString() << (QStringList() << "a/**/d/*.h") << QStringList() << (QStringList() << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h"); QTest::newRow(QByteArray("recursive 3")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**/**/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("prefix")) << useGroup << (QStringList() << "subdir/foo.h" << "subdir/foo.cpp" << "subdir/bar.h" << "subdir/bar.cpp") << QString() << QString("subdir/") << (QStringList() << "*.h") << QStringList() << (QStringList() << "subdir/foo.h" << "subdir/bar.h"); QTest::newRow(QByteArray("non-existing absolute path")) << useGroup << QStringList() << QString() << QString("/dir") << (QStringList() << "*.whatever") << QStringList() << QStringList(); QTest::newRow(QByteArray("case sensitivity")) << useGroup << (QStringList{"test1.txt", "test2.TXT"}) << QString() << QString() << (QStringList{"*.TXT"}) << QStringList() << (HostOsInfo::isWindowsHost() ? QStringList{"test1.txt", "test2.TXT"} : QStringList("test2.TXT")); } void TestLanguage::wildcards() { QFETCH(bool, useGroup); QFETCH(QStringList, filesToCreate); QFETCH(QString, projectFileSubDir); QFETCH(QString, prefix); QFETCH(QStringList, patterns); QFETCH(QStringList, excludePatterns); QFETCH(QStringList, expected); // create test directory QDir::setCurrent(QDir::tempPath()); { QString errorMessage; if (QFile::exists(m_wildcardsTestDirPath)) { if (!removeDirectoryWithContents(m_wildcardsTestDirPath, &errorMessage)) { qDebug() << errorMessage; QVERIFY2(false, "removeDirectoryWithContents failed"); } } QVERIFY(QDir().mkdir(m_wildcardsTestDirPath)); } // create project file const QString groupName = "Keks"; QString dataTag = QString::fromLocal8Bit(QTest::currentDataTag()); dataTag.replace(' ', '_'); if (!projectFileSubDir.isEmpty()) { if (!projectFileSubDir.startsWith('/')) projectFileSubDir.prepend('/'); if (projectFileSubDir.endsWith('/')) projectFileSubDir.chop(1); QVERIFY(QDir().mkpath(m_wildcardsTestDirPath + projectFileSubDir)); } const QString projectFilePath = m_wildcardsTestDirPath + projectFileSubDir + "/test_" + dataTag + ".qbs"; { QFile projectFile(projectFilePath); QVERIFY(projectFile.open(QIODevice::WriteOnly)); QTextStream s(&projectFile); using Qt::endl; s << "Application {" << endl << " name: \"MyProduct\"" << endl; if (useGroup) { s << " Group {" << endl << " name: " << toJSLiteral(groupName) << endl; } if (!prefix.isEmpty()) s << " prefix: " << toJSLiteral(prefix) << endl; if (!patterns.empty()) s << " files: " << toJSLiteral(patterns) << endl; if (!excludePatterns.empty()) s << " excludeFiles: " << toJSLiteral(excludePatterns) << endl; if (useGroup) s << " }" << endl; s << "}" << endl << endl; } // create files for (QString filePath : std::as_const(filesToCreate)) { filePath.prepend(m_wildcardsTestDirPath + '/'); QFileInfo fi(filePath); if (!QDir(fi.path()).exists()) QVERIFY(QDir().mkpath(fi.path())); QFile file(filePath); QVERIFY(file.open(QIODevice::WriteOnly)); } // read the project bool exceptionCaught = false; ResolvedProductPtr product; try { defaultParameters.setProjectFilePath(projectFilePath); resolveProject(); QVERIFY(!!project); const QHash products = productsFromProject(project); product = products.value("MyProduct"); QVERIFY(!!product); GroupPtr group; if (useGroup) { QCOMPARE(product->groups.size(), size_t(HostOsInfo::isMacosHost() ? 4 : 2)); for (const GroupPtr &rg : product->groups) { if (rg->name == groupName) { group = rg; break; } } } else { QCOMPARE(product->groups.size(), size_t(HostOsInfo::isMacosHost() ? 3 : 1)); group = product->groups.front(); } QVERIFY(!!group); QVERIFY(group->files); QCOMPARE(group->files->size(), expected.size()); // we assume all files are wildcards QVERIFY(!!group->wildcards); QStringList actualFilePaths; for (const SourceArtifactPtr &artifact : *group->files) { QString str = artifact->absoluteFilePath; int idx = str.indexOf(m_wildcardsTestDirPath); if (idx != -1) str.remove(0, idx + m_wildcardsTestDirPath.size() + 1); actualFilePaths << str; } actualFilePaths.sort(); expected.sort(); QCOMPARE(actualFilePaths, expected); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const SettingsPtr s = settings(); TestLanguage tl(ConsoleLogger::instance().logSink(), s.get()); return QTest::qExec(&tl, argc, argv); } qbs-src-3.3.1/tests/auto/language/tst_language.h0000644000175100017510000001706015232633614021232 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_LANGUAGE_H #define TST_LANGUAGE_H #include #include #include #include #include #include #include #include class TestLanguage : public QObject { Q_OBJECT public: TestLanguage(qbs::ILogSink *logSink, qbs::Settings *settings); ~TestLanguage(); private slots: void init(); void initTestCase(); void additionalProductTypes(); void baseProperty(); void baseValidation(); void brokenDependencyCycle(); void brokenDependencyCycle_data(); void buildConfigStringListSyntax(); void builtinFunctionInSearchPathsProperty(); void chainedProbes(); void canonicalArchitecture(); void conditionalDepends(); void convertStringList(); void correctDeclInParentLookup(); void delayedError(); void delayedError_data(); void dependencyOnAllProfiles(); void dependsItemInGroup_data(); void dependsItemInGroup(); void derivedSubProject(); void disabledPropertiesItem_data(); void disabledPropertiesItem(); void disabledSubProject(); void dottedNames_data(); void dottedNames(); void duplicateMultiplexValues_data(); void duplicateMultiplexValues(); void emptyJsFile(); void enumerateProjectProperties(); void evalErrorInNonPresentModule_data(); void evalErrorInNonPresentModule(); void environmentVariable(); void errorInDisabledProduct(); void erroneousFiles_data(); void erroneousFiles(); void exports(); void fileContextProperties(); void fileInProductAndModule_data(); void fileInProductAndModule(); void fileTags_data(); void fileTags(); void groupConditions_data(); void groupConditions(); void groupName(); void getNativeSetting(); void homeDirectory(); void identifierSearch_data(); void identifierSearch(); void idUsage(); void idUniqueness(); void importCollection(); void inheritedPropertiesItems_data(); void inheritedPropertiesItems(); void invalidBindingInDisabledItem(); void invalidOverrides(); void invalidOverrides_data(); void invalidPropOnNonRequiredModule_data(); void invalidPropOnNonRequiredModule(); void itemPrototype(); void itemScope(); void jsExtensions(); void jsImportUsedInMultipleScopes_data(); void jsImportUsedInMultipleScopes(); void keepLoadingDependencies(); void localProfileAsTopLevelProfile(); void moduleMergingVariantValues(); void moduleNameCollisions_data(); void moduleNameCollisions(); void moduleParameters_data(); void moduleParameters(); void modulePrioritizationBySearchPath_data(); void modulePrioritizationBySearchPath(); void moduleProperties_data(); void moduleProperties(); void modulePropertiesInGroups(); void modulePropertyOverridesPerProduct(); void moduleScope(); void moduleWithProductDependency(); void modules_data(); void modules(); void multipleModuleBackendsViaOwnProperty_data(); void multipleModuleBackendsViaOwnProperty(); void multiplexedExports(); void multiplexingByProfile(); void multiplexingByProfile_data(); void nonApplicableModulePropertyInProfile(); void nonApplicableModulePropertyInProfile_data(); void nonRequiredProducts(); void nonRequiredProducts_data(); void outerInGroup(); void overrideProductPropFromSubProjectItem(); void overriddenPropertiesAndPrototypes(); void overriddenPropertiesAndPrototypes_data(); void overriddenVariantProperty(); void parameterTypes(); void projectPropertyForwarding(); void pathProperties(); void probesAndMultiplexing(); void productConditions(); void productDirectories(); void profileValuesAndOverriddenValues(); void projectFileLookup(); void projectFileLookup_data(); void propertiesBlocks_data(); void propertiesBlocks(); void propertiesBlockInGroup_data(); void propertiesBlockInGroup(); void propertiesItemInModule(); void propertyAssignmentInExportedGroup(); void qbs1275(); void qbsPropertiesInProjectCondition(); void qbsPropertyConvenienceOverride(); void relaxedErrorMode(); void relaxedErrorMode_data(); void requiredAndNonRequiredDependencies(); void requiredAndNonRequiredDependencies_data(); void suppressedAndNonSuppressedErrors(); void throwingProbe(); void throwingProbe_data(); void defaultValue(); void defaultValue_data(); void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); void throwThings_data(); void throwThings(); void useInternalProfile(); void versionCompare(); void wildcards_data(); void wildcards(); private: QHash productsFromProject( qbs::Internal::ResolvedProjectPtr project); qbs::Internal::ResolvedModuleConstPtr findModuleByName( qbs::Internal::ResolvedProductPtr product, const QString &name); QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); void handleInitCleanupDataTags(const char *projectFileName, bool *handled); qbs::Internal::TopLevelProjectPtr resolveProject(const char *relProjectFilePath = nullptr); qbs::ILogSink * const m_logSink; qbs::Settings * const m_settings; qbs::Internal::Logger m_logger; std::unique_ptr m_engine; qbs::Internal::TopLevelProjectPtr project; qbs::SetupProjectParameters defaultParameters; const QString m_wildcardsTestDirPath; QTemporaryDir m_tempDir; QRandomGenerator m_rand; }; #endif // TST_LANGUAGE_H qbs-src-3.3.1/tests/auto/language/testdata/0000755000175100017510000000000015232633614020211 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/versionCompare.qbs0000644000175100017510000000113515232633614023714 0ustar runnerrunnerimport qbs.Utilities Product { name: { var e = "unexpected comparison result"; if (Utilities.versionCompare("1.5", "1.5") !== 0) throw e; if (Utilities.versionCompare("1.5", "1.5.0") !== 0) throw e; if (Utilities.versionCompare("1.5", "1.6") >= 0) throw e; if (Utilities.versionCompare("1.6", "1.5") <= 0) throw e; if (Utilities.versionCompare("2.5", "1.6") <= 0) throw e; if (Utilities.versionCompare("1.6", "2.5") >= 0) throw e; return "versionCompare"; } } qbs-src-3.3.1/tests/auto/language/testdata/jsimportsinmultiplescopes.js0000644000175100017510000000030115232633614026113 0ustar runnerrunnerfunction getName(qbsModule) { if (qbsModule.debugInformation) return "MyProduct_debug"; else return "MyProduct"; } function getInstallDir() { return "somewhere"; } qbs-src-3.3.1/tests/auto/language/testdata/groupconditions.qbs0000644000175100017510000000214015232633614024143 0ustar runnerrunnerProject { property bool someTrueProperty: true Product { name: "no_condition_no_group" files: ["main.cpp"] } Product { name: "no_condition" Group { files: ["main.cpp"] } } Product { name: "true_condition" Group { condition: true files: ["main.cpp"] } } Product { name: "false_condition" Group { condition: false files: ["main.cpp"] } } Product { name: "true_condition_from_product" property bool anotherTrueProperty: true Group { condition: anotherTrueProperty files: ["main.cpp"] } } Product { name: "true_condition_from_project" Group { condition: project.someTrueProperty files: ["main.cpp"] } } Product { name: "condition_accessing_module_property" Group { condition: qbs.targetOS.includes("narf") files: ["main.cpp"] qbs.install: false } } } qbs-src-3.3.1/tests/auto/language/testdata/dotted-names/0000755000175100017510000000000015232633614022575 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dotted-names/modules/0000755000175100017510000000000015232633614024245 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dotted-names/modules/x/0000755000175100017510000000000015232633614024514 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dotted-names/modules/x/y/0000755000175100017510000000000015232633614024764 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs0000644000175100017510000000005415232633614026132 0ustar runnerrunnerModule { property string z: "default" } qbs-src-3.3.1/tests/auto/language/testdata/dotted-names/dotted-names.qbs0000644000175100017510000000077415232633614025700 0ustar runnerrunnerProject { name: "theProject" property bool includeDottedProduct property bool includeDottedModule Project { condition: project.includeDottedProduct Product { name: "a.b" Export { property string c: "default" } } } Product { name: "p" Depends { name: "a.b"; condition: project.includeDottedProduct } Depends { name: "x.y"; condition: project.includeDottedModule } a.b.c: "p" x.y.z: "p" } } qbs-src-3.3.1/tests/auto/language/testdata/homeDirectory.qbs0000644000175100017510000000066115232633614023540 0ustar runnerrunnerProject { Product { name: "home" // These should resolve property path home: "~" property path homeSlash: "~/" property path homeUp: "~/.." property path homeFile: "~/a" // These are sanity checks and should not property path bogus1: "a~b" property path bogus2: "a/~/bb" property path user: "~foo/bar" // we don't resolve other-user paths } } qbs-src-3.3.1/tests/auto/language/testdata/groupname.qbs0000644000175100017510000000054115232633614022715 0ustar runnerrunnerProject { Product { name: "MyProduct" Group { name: product.name + ".MyGroup" files: "*" } } Product { name: "My2ndProduct" Group { name: product.name + ".MyGroup" files: ["narf"] } Group { files: ["zort"] } } } qbs-src-3.3.1/tests/auto/language/testdata/broken-dependency-cycle1.qbs0000644000175100017510000000050115232633614025466 0ustar runnerrunnerProject { Product { name: "p1" Export { property bool c: true Depends { name: "p2"; condition: c } } } Product { name: "p2" Depends { name: "p1" } p1.c: false } Product { name: "p3" Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/exports.qbs0000644000175100017510000000735015232633614022431 0ustar runnerrunnerimport "exports_product.qbs" as ProductWithInheritedExportItem Project { Product { type: "app" name: "myapp" Depends { name: "mylib" } Depends { name: "dummy" } Depends { name: "qbs" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] dummy.includePaths: ["./app"] } references: [ "subdir/exports-mylib.qbs", "subdir2/exports-mylib2.qbs" ] Product { type: "app" name: "A" Depends { name: "qbs" } Depends { name: "B" } } Product { type: "lib" name: "B" Export { Depends { name: "C" } Depends { name: "qbs" } } } Product { type: "lib" name: "C" Export { Depends { name: "D" } Depends { name: "qbs" } } } Product { type: "lib" name: "D" } Product { type: "app" name: "myapp2" Depends { name: "productWithInheritedExportItem" } Depends { name: "qbs" } } ProductWithInheritedExportItem { name: "productWithInheritedExportItem" Export { dummy.cFlags: base.concat("PRODUCT_" + exportingProduct.name.toUpperCase()) dummy.cxxFlags: ["-bar"] Properties { dummy.defines: base.concat(["DEF"]) } } } Product { type: "app" name: "myapp3" Depends { name: "productWithInheritedExportItem"; versionAtLeast: "2.0" } } Project { name: "sub1" Product { name: "sub p1" Export { Depends { name: "dummy" } dummy.someString: project.name } } } Project { name: "sub2" Product { name: "sub p2" Depends { name: "sub p1" } } } ParentWithExport { name: "libA" Export { Depends { name: "libB" } } } ParentWithExport { name: "libB" } ParentWithExport { name: "libC" Export { Depends { name: "libA" } } } ParentWithExport { name: "libD" Export { Depends { name: "libA" } } } Product { name: "libE" Depends { name: "libD" } Depends { name: "libC" } Group { qbs.install: false } } Product { name: "dependency" Probe { id: configProbe property var config configure: { var obj = {}; obj.featureX = true; obj.featureY = false; obj.featureZ = true; config = obj; found = true; } } property var config: configProbe.config Export { property bool depend: false property var config: exportingProduct.config Group { condition: depend Depends { name: "cpp" } Properties { cpp.includePaths: ["."] } } } } Product { name: "depender" Depends { name: "dependency" } property bool featureX: dependency.config.featureX property bool featureY: dependency.config.featureY property bool featureZ: dependency.config.featureZ } Product { name: "broken_cycle1" Export { property bool depend: true Depends { name: "broken_cycle3"; condition: depend } } } Product { name: "broken_cycle2" Export { Depends { name: "broken_cycle1" } broken_cycle1.depend: false } } Product { name: "broken_cycle3" Depends { name: "broken_cycle2" } } } qbs-src-3.3.1/tests/auto/language/testdata/empty-js-file.qbs0000644000175100017510000000006015232633614023401 0ustar runnerrunnerimport "empty-js-file.js" as Empty Product { } qbs-src-3.3.1/tests/auto/language/testdata/baseproperty_base.qbs0000644000175100017510000000010115232633614024421 0ustar runnerrunnerProduct { property var narf property var zort: ["bar"] } qbs-src-3.3.1/tests/auto/language/testdata/moduleproperties.qbs0000644000175100017510000000370515232633614024327 0ustar runnerrunnerProject { name: "MyProject" property string projectName: name Product { name: "merge_lists" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } dummy.defines: ["THE_PRODUCT"] } Product { name: "merge_lists_and_values" Depends { name: "dummyqt"; submodules: ["network", "gui"] } Depends { name: "dummy" } dummy.defines: "THE_PRODUCT" } Product { name: "merge_lists_with_duplicates" Depends { name: "dummy" } dummy.cxxFlags: ["-foo", "BAR", "-foo", "BAZ"] } Product { name: "merge_lists_with_prototype_values" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } } Product { name: "list_property_that_references_product" type: ["blubb"] Depends { name: "dummy" } dummy.listProp: ["x"] } Product { name: "list_property_depending_on_overridden_property" Depends { name: "dummy" } dummy.listProp2: ["PRODUCT_STUFF"] dummy.controllingProp: true } Product { name: "overridden_list_property" Depends { name: "dummy" } Properties { overrideListProperties: true dummy.listProp: ["PRODUCT_STUFF"] } } Product { name: "shadowed-list-property" property string productName: name Depends { name: "dummy" } dummy.defines: [projectName, productName] } Product { name: "shadowed-scalar-property" property string productName: name Depends { name: "dummy" } dummy.someString: projectName + "_" + productName } Product { name: "merged-varlist" property string productName: name Depends { name: "dummy" } Depends { name: "dummyqt.core" } dummy.controllingProp: true dummy.varListProp: ({d: "product"}) } } qbs-src-3.3.1/tests/auto/language/testdata/modules/0000755000175100017510000000000015232633614021661 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummy2/0000755000175100017510000000000015232633614023076 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummy2/dummy2.qbs0000644000175100017510000000022415232633614025020 0ustar runnerrunnerModule { additionalProductTypes: ["tag3"] property var defines property var someTrueProp: true property var someFalseProp: false } qbs-src-3.3.1/tests/auto/language/testdata/modules/deepdummy/0000755000175100017510000000000015232633614023652 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/deepdummy/deep/0000755000175100017510000000000015232633614024567 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/deepdummy/deep/moat/0000755000175100017510000000000015232633614025527 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/deepdummy/deep/moat/dummydeepmoat.qbs0000644000175100017510000000020215232633614031102 0ustar runnerrunnerModule { property string depth: "abysmal" Depends { name: "dummy"; id: dummyId } property string zort: dummyId.zort } qbs-src-3.3.1/tests/auto/language/testdata/modules/broken/0000755000175100017510000000000015232633614023141 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/broken/broken.qbs0000644000175100017510000000056515232633614025136 0ustar runnerrunnerModule { Probe { id: theProbe property stringList broken property stringList fine configure: { broken = [["x"]]; fine = ["x"] found = true; } } property stringList broken: theProbe.broken property stringList fine: theProbe.fine.filter(function(incl) { return incl != "y"; }); } qbs-src-3.3.1/tests/auto/language/testdata/modules/gmod2/0000755000175100017510000000000015232633614022671 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/gmod2/gmod2.qbs0000644000175100017510000000031215232633614024404 0ustar runnerrunnerModule { property int prop: 0 property string gmod2_string: "gmod2_string_proto" property string commonName: "commonName_in_gmod2" property stringList gmod2_list: ["gmod2_list_proto"] } qbs-src-3.3.1/tests/auto/language/testdata/modules/scopemod/0000755000175100017510000000000015232633614023472 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/scopemod/scopemod.qbs0000644000175100017510000000030315232633614026006 0ustar runnerrunnerModule { property int a: 1 property int b: 1 property int c: a + 1 property int d: b + 1 property int e: 1 property int f: 1 property int g: 1 property int h: 1 } qbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-product-dependency/0000755000175100017510000000000015232633614027711 5ustar runnerrunner././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-product-dependency.qbsqbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-produc0000644000175100017510000000004615232633614033364 0ustar runnerrunnerModule { Depends { name: "p2" } } qbs-src-3.3.1/tests/auto/language/testdata/modules/module_with_group/0000755000175100017510000000000015232633614025415 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/module_with_group/module_with_group.qbs0000644000175100017510000000072415232633614031663 0ustar runnerrunnerModule { Depends { name: "dummy" } property string moduleDefine: "module_define" property string group Group { name: "module_group" condition: group == name Properties { dummy.defines: [moduleDefine.toUpperCase(), name.toUpperCase()] } } Group { name: "module_group_alt" condition: group == name product.dummy.defines: [moduleDefine.toUpperCase(), name.toUpperCase()] } } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummy3/0000755000175100017510000000000015232633614023077 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummy3/dummy3.qbs0000644000175100017510000000014215232633614025021 0ustar runnerrunnerModule { property bool loadDummy: false Depends { name: "dummy"; condition: loadDummy } } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/0000755000175100017510000000000015232633614023361 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/network/0000755000175100017510000000000015232633614025052 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/network/dummynetwork.qbs0000644000175100017510000000027115232633614030326 0ustar runnerrunnerModule { Depends { name: "dummyqt"; submodules: ["core"] } property string networkProperty: "networkProperty" Depends { name: "dummy" } dummy.defines: ["QT_NETWORK"] } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/gui/0000755000175100017510000000000015232633614024145 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/gui/dummygui.qbs0000644000175100017510000000041615232633614026515 0ustar runnerrunnerModule { Depends { name: "dummyqt.core" } property string guiProperty: "guiProperty" property string someString: "ene mene muh" Depends { name: "dummy" } dummy.defines: ["QT_GUI"] dummy.someString: someString dummy.zort: dummyqt.core.zort } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/core/0000755000175100017510000000000015232633614024311 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs0000644000175100017510000000111615232633614027023 0ustar runnerrunnerModule { property int versionMajor: 5 property int versionMinor: 0 property int versionPatch: 0 property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString() property string coreProperty: "coreProperty" property string coreVersion: version property string zort: "zort in dummyqt.core" Depends { name: "dummy" } dummy.defines: ["QT_CORE"] dummy.rpaths: ["/opt/qt/lib"] dummy.cFlags: [zort] dummy.varListProp: [{c: "qtcore"}] Properties { dummy.productName: product.name } } qbs-src-3.3.1/tests/auto/language/testdata/modules/gmod3/0000755000175100017510000000000015232633614022672 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/gmod3/qmod3.qbs0000644000175100017510000000020515232633614024421 0ustar runnerrunnerModule { Depends { name: "gmod2" } property string gmod3_string: "gmod3_string_proto" gmod2.gmod2_list: [gmod3_string] } qbs-src-3.3.1/tests/auto/language/testdata/modules/gmod4/0000755000175100017510000000000015232633614022673 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/gmod4/gmod4.qbs0000644000175100017510000000027615232633614024421 0ustar runnerrunnerModule { Depends { name: "gmod2" } Depends { name: "gmod3" } property string gmod4_string: "gmod4_string_proto" gmod2.gmod2_list: [gmod4_string + "_" + gmod3.gmod3_string] } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends_via_own_property/0000755000175100017510000000000015232633614031034 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends_via_own_property/Backend.qbs0000644000175100017510000000012315232633614033066 0ustar runnerrunnerModule { condition: false property string type property string value } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends_via_own_property/backend1.qbs0000644000175100017510000000010015232633614033202 0ustar runnerrunnerBackend { condition: type === "type1" value: "value1" } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends_via_own_property/backend2.qbs0000644000175100017510000000010015232633614033203 0ustar runnerrunnerBackend { condition: type === "type2" value: "value2" } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends/0000755000175100017510000000000015232633614025346 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs0000644000175100017510000000013515232633614027524 0ustar runnerrunnerModule { condition: qbs.targetOS.includes("os1") property string prop: "backend 1" } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs0000644000175100017510000000021015232633614027520 0ustar runnerrunnerModule { condition: qbs.targetOS.includes("os2") && qbs.toolchain.includes("tc") priority: 1 property string backend3Prop } qbs-src-3.3.1/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs0000644000175100017510000000017615232633614027532 0ustar runnerrunnerModule { condition: qbs.targetOS.includes("os2") property string prop: "backend 2" property string backend2Prop } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummy3_loader/0000755000175100017510000000000015232633614024425 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummy3_loader/dummy3_loader.qbs0000644000175100017510000000010515232633614027674 0ustar runnerrunnerModule { Depends { name: "dummy3" } dummy3.loadDummy: true } qbs-src-3.3.1/tests/auto/language/testdata/modules/gmod/0000755000175100017510000000000015232633614022607 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/gmod/gmod1/0000755000175100017510000000000015232633614023616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/gmod/gmod1/gmod1.qbs0000644000175100017510000000106315232633614025334 0ustar runnerrunnerModule { Depends { name: "gmod2" } Depends { name: "gmod4" } property stringList gmod1_list1: ["gmod1_list1_proto", gmod1_string] property stringList gmod1_list2: ["gmod1_list2_proto"] property stringList gmod1_list3: [gmod1_string] property string gmod1_string: "gmod1_string_proto" property string commonName: "commonName_in_gmod1" property int depProp: gmod2.prop property int p0: p1 + p2 property int p1: 0 property int p2: 0 gmod2.gmod2_string: gmod1_string gmod2.gmod2_list: [gmod1_string, commonName] } qbs-src-3.3.1/tests/auto/language/testdata/modules/module_with_file/0000755000175100017510000000000015232633614025200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/module_with_file/module-with-file.qbs0000644000175100017510000000056715232633614031072 0ustar runnerrunnerModule { property bool file1IsTarget property bool file2IsTarget Group { prefix: product.sourceDirectory + '/' files: "zort" filesAreTargets: product.module_with_file.file1IsTarget } Group { prefix: product.sourceDirectory + '/' files: "zort" filesAreTargets: product.module_with_file.file2IsTarget } } qbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-properties-item/0000755000175100017510000000000015232633614027245 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-properties-item/module-with-properties-item.qbsqbs-src-3.3.1/tests/auto/language/testdata/modules/module-with-properties-item/module-with-propertie0000644000175100017510000000033015232633614033431 0ustar runnerrunnerModule { property bool boolProperty: true property string stringProperty: "set in Module item" Properties { condition: boolProperty stringProperty: "overridden in Properties item" } } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummy/0000755000175100017510000000000015232633614023014 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/modules/dummy/dummy.qbs0000644000175100017510000000173115232633614024660 0ustar runnerrunnerimport "dummy_base.qbs" as DummyBase DummyBase { condition: true additionalProductTypes: ["tag2"] property bool falseProperty: false property stringList defines property stringList cFlags property stringList cxxFlags property stringList rpaths: ["$ORIGIN"] property string someString property string productName: product.name property string upperCaseProductName: productName.toUpperCase() property string zort: "zort in dummy" property pathList includePaths property path somePath property stringList listProp: product.type.includes("blubb") ? ["123"] : ["456"] property bool controllingProp: false property stringList listProp2: controllingProp ? ["DEFAULT_STUFF", "EXTRA_STUFF"] : ["DEFAULT_STUFF"] property varList varListProp: [{a: controllingProp, b: someString}] Probe { id: QBS_1821 property stringList Flags: cxxFlags configure: {} } } qbs-src-3.3.1/tests/auto/language/testdata/modules/dummy/dummy_base.qbs0000644000175100017510000000010315232633614025642 0ustar runnerrunnerModule { condition: false property pathList includePaths } qbs-src-3.3.1/tests/auto/language/testdata/outerInGroup.qbs0000644000175100017510000000075515232633614023371 0ustar runnerrunnerProject { Product { name: "OuterInGroup" Depends { name: "dummy" } qbs.installDir: "/somewhere" dummy.someString: "s1" Properties { dummy.someString: outer.concat("s2") } files: ["main.cpp"] Group { Group { name: "Special Group" files: ["aboutdialog.cpp"] qbs.installDir: outer + "/else" dummy.someString: outer.concat("s3") } } } } qbs-src-3.3.1/tests/auto/language/testdata/propertiesblocks.qbs0000644000175100017510000001312415232633614024313 0ustar runnerrunnerimport "propertiesblocks_base.qbs" as ProductBase Project { Product { name: "property_append" Depends { name: "dummy" } dummy.defines: ["SOMETHING"] Properties { dummy.defines: ["APPENDED"] } } Product { name: "property_set_indirect" Depends { name: "dummyqt.core" } Properties { dummyqt.core.zort: "VAL" } } Product { name: "property_overwrite" Depends { name: "dummy" } Properties { dummy.defines: ["OVERWRITTEN"] } } Product { name: "property_append_indirect" Depends { name: "dummy" } property stringList myDefines: ["ONE"] dummy.defines: myDefines Properties { dummy.defines: ["TWO"] } } ProductBase { name: "property_append_to_indirect_derived" Properties { dummy.cFlags: outer.concat("PROPS") } } ProductBase { name: "property_append_to_indirect_derived2" Properties { dummy.cFlags: "PROPS" } dummy.cFlags: ["PRODUCT"] } ProductBase { name: "property_append_to_indirect_derived3" Properties { dummy.cFlags: "PROPS" } dummy.cFlags: base.concat("PRODUCT") } Product { name: "property_append_to_indirect_merged" Depends { name: "dummy" } property string justOne: "ONE" dummy.rpaths: [justOne] Properties { dummy.rpaths: ["TWO"] } } Product { name: "multiple_exclusive_properties" Depends { name: "dummy" } Properties { dummy.defines: ["OVERWRITTEN"] } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } Properties { condition: undefined dummy.defines: ["SOMETHING"] } } Product { name: "multiple_exclusive_properties_no_match" Depends { name: "dummy" } Properties { condition: undefined dummy.defines: ["OVERWRITTEN"] } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } } Product { name: "multiple_exclusive_properties_append" Depends { name: "dummy" } dummy.defines: ["ONE"] Properties { dummy.defines: ["TWO"] } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } } Product { name: "ambiguous_properties" Depends { name: "dummy" } dummy.defines: ["ONE"] Properties { dummy.defines: ["TWO"] } Properties { condition: false dummy.defines: outer.concat(["IMPOSSIBLE"]) } Properties { dummy.defines: ["THREE"] } } Product { name: "condition_refers_to_product_property" property bool narf: true property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: narf dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } property bool zort: true Product { name: "condition_refers_to_project_property" property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: project.zort dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } ProductBase { name: "inheritance_overwrite_in_subitem" dummy.defines: ["OVERWRITTEN_IN_SUBITEM"] } ProductBase { name: "inheritance_retain_base1" dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_retain_base2" Properties { condition: true dummy.defines: base.concat("SUB") } Properties { condition: undefined dummy.defines: ["GNAMPF"] } } ProductBase { name: "inheritance_retain_base3" Properties { condition: true dummy.defines: base.concat("SUB") } // no dummy.defines binding } ProductBase { name: "inheritance_retain_base4" Properties { condition: false dummy.defines: ["NEVERMORE"] } // no "else case" for dummy.defines. The value is derived from ProductBase. } ProductBase { name: "inheritance_condition_in_subitem1" defineBase: false dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_condition_in_subitem2" defineBase: false // no dummy.defines binding } Product { id: knolf name: "gnampf" } Product { name: "condition_references_id" Depends { name: "dummy" } Properties { condition: knolf.name === "gnampf" dummy.defines: ["OVERWRITTEN"] } } Product { name: "using_derived_Properties_item" Depends { name: "dummy" } MyProperties { condition: true dummy.defines: ["string from MyProperties"] } } Product { name: "conditional-depends" Depends { name: "dummy" condition: false } Properties { condition: false dummy.defines: ["a string"] } } Product { name: "use-module-with-properties-item" Depends { name: "module-with-properties-item" } } } qbs-src-3.3.1/tests/auto/language/testdata/duplicate-multiplex-value.qbs0000644000175100017510000000021215232633614026020 0ustar runnerrunnerProduct { name: "p" multiplexByQbsProperties: "architectures" aggregate: false qbs.architectures: ["x86", "arm", "x86"] } qbs-src-3.3.1/tests/auto/language/testdata/id-uniqueness.qbs0000644000175100017510000000040615232633614023511 0ustar runnerrunnerimport "idusagebase.qbs" as DerivedProduct Project { id: theProject DerivedProduct { id: baseProduct // OK - even though 'baseProduct' is used in the base item. } DerivedProduct { id: baseProduct // ERROR } } qbs-src-3.3.1/tests/auto/language/testdata/modulescope.qbs0000644000175100017510000000040015232633614023231 0ustar runnerrunnerimport "modulescope_base.qbs" as MyProduct Project { MyProduct { name: "product1" property int e: 12 property int f: 13 scopemod.a: 2 scopemod.f: 2 scopemod.g: e * f scopemod.h: base + 2 } } qbs-src-3.3.1/tests/auto/language/testdata/dirwithoneproject/0000755000175100017510000000000015232633614023754 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dirwithoneproject/project.qbs0000644000175100017510000000000015232633614026117 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/qbs-property-convenience-override.qbs0000644000175100017510000000007615232633614027501 0ustar runnerrunnerProduct { name: "p" qbs.installPrefix: "/usr/local" } qbs-src-3.3.1/tests/auto/language/testdata/use-internal-profile.qbs0000644000175100017510000000030015232633614024755 0ustar runnerrunnerProject { name: "theproject" Profile { name: "theprofile" dummy.defines: name } Product { name: "theproduct" Depends { name: "dummy" } } }qbs-src-3.3.1/tests/auto/language/testdata/enum-project-props.qbs0000644000175100017510000000041215232633614024466 0ustar runnerrunnerProject { property string anExistingFile: "dummy.txt" Product { files: { for (var k in project) { if (k === "anExistingFile") return [project[k]]; } return []; } } } qbs-src-3.3.1/tests/auto/language/testdata/empty-js-file.js0000644000175100017510000000000015232633614023222 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/aboutdialog.cpp0000644000175100017510000000000015232633614023175 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/overridden-properties-and-prototypes.qbs0000644000175100017510000000010415232633614030234 0ustar runnerrunnerProduct { name: "p" Depends { name: "multiple_backends" } } qbs-src-3.3.1/tests/auto/language/testdata/nativesettings.ini0000644000175100017510000000001615232633614023756 0ustar runnerrunnerosname = Unix qbs-src-3.3.1/tests/auto/language/testdata/idusage_group2.qbs0000644000175100017510000000014015232633614023632 0ustar runnerrunnerimport "idusage_group.qbs" as MyGroup MyGroup { name: "between the hammer and the anvil" } qbs-src-3.3.1/tests/auto/language/testdata/conditionaldepends_base.qbs0000644000175100017510000000023015232633614025553 0ustar runnerrunnerProduct { name: 'conditionaldepends_base' property bool someProp: false Depends { condition: someProp name: 'dummy' } } qbs-src-3.3.1/tests/auto/language/testdata/modules.qbs0000644000175100017510000000256615232633614022401 0ustar runnerrunnerProject { Product { name: "no_modules" property var foo } Product { name: "qt_core" dummyqt.core.version: "1.2.3" property var foo: dummyqt.core.coreVersion Depends { name: "dummyqt.core" } } Product { name: "qt_gui" property var foo: dummyqt.gui.guiProperty Depends { name: "dummyqt.gui" } } Product { name: "qt_gui_network" property var foo: dummyqt.gui.guiProperty + ',' + dummyqt.network.networkProperty Depends { name: "dummyqt" submodules: ["gui", "network"] } } Product { name: "deep_module_name" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy.deep.moat" } } Product { name: "deep_module_name_submodule_syntax1" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy.deep" submodules: ["moat"] } } Product { name: "deep_module_name_submodule_syntax2" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy" submodules: ["deep.moat"] } } Product { name: "dummy_twice" Depends { name: "dummy" } Depends { name: "dummy" } } } qbs-src-3.3.1/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs0000644000175100017510000000142215232633614027564 0ustar runnerrunnerProject { Product { name: "product1" property bool dummyProp: { if (!(dummy.cFlags instanceof Array)) throw new Error("dummy.cFlags: Array type expected."); if (!(dummy.cxxFlags instanceof Array)) throw new Error("dummy.cxxFlags: Array type expected."); if (!(dummy.defines instanceof Array)) throw new Error("dummy.defines: Array type expected."); return true; } consoleApplication: true Depends { name: "dummy" } // dummy.cxxFlags is set via profile and is not overridden dummy.defines: ["IN_FILE"] // set in profile, overridden in file dummy.cFlags: ["IN_FILE"] // set in profile, overridden on command line } } qbs-src-3.3.1/tests/auto/language/testdata/module-parameters/0000755000175100017510000000000015232633614023637 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/0000755000175100017510000000000015232633614025307 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/broken/0000755000175100017510000000000015232633614026567 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs0000644000175100017510000000022515232633614030555 0ustar runnerrunnerModule { Depends { name: "higher"; lower.param: "shouldNeverAppear" } validate: { throw "As the name indicates, this module is broken."; } } qbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/higher/0000755000175100017510000000000015232633614026555 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs0000644000175100017510000000013215232633614030526 0ustar runnerrunnerModule { Depends { name: "lower" } Parameters { lower.param: "fromParameters" } } qbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/lower/0000755000175100017510000000000015232633614026437 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs0000644000175100017510000000007515232633614030300 0ustar runnerrunnerModule { Parameter { property string param: "origin" } } qbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/highest/0000755000175100017510000000000015232633614026742 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs0000644000175100017510000000021515232633614031102 0ustar runnerrunnerModule { Depends { name: "higher" condition: project.overrideFromModule lower.param: "fromModuleDepends" } } qbs-src-3.3.1/tests/auto/language/testdata/module-parameters/module-parameters.qbs0000644000175100017510000000175015232633614027777 0ustar runnerrunnerProject { property bool overrideFromModule property bool overrideFromExport property bool overrideFromProduct Product { name: "dep" Export { Depends { name: "higher"; condition: project.overrideFromExport lower.param: "fromExportDepends" } Parameters { lower.param: "fromParameters" } } } Product { name: "main" Depends { name: "dep" condition: project.overrideFromProduct lower.param: "fromProductDepends" } Depends { name: "higher" condition: project.overrideFromProduct lower.param: "fromProductDepends" } Depends { name: "dep"; condition: !project.overrideFromProduct } Depends { name: "higher"; condition: !project.overrideFromProduct } Depends { name: "highest" } Depends { name: "broken"; required: false } } } qbs-src-3.3.1/tests/auto/language/testdata/broken-dependency-cycle2.qbs0000644000175100017510000000050115232633614025467 0ustar runnerrunnerProject { Product { name: "p1" Export { property bool c: true Depends { name: "p2"; condition: c } } } Product { name: "p3" Depends { name: "p1" } } Product { name: "p2" Depends { name: "p1" } p1.c: false } } qbs-src-3.3.1/tests/auto/language/testdata/invalidBindingInDisabledItem.qbs0000644000175100017510000000051515232633614026400 0ustar runnerrunnerProject { Product { name: "product1" condition: false someNonsense: "Bitte stellen Sie die Tassen auf den Tisch." } Product { name: "product2" Group { condition: false moreNonsense: "Follen. Follen. Hünuntergefollen. Auf dön Töppüch." } } } qbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/0000755000175100017510000000000015232633614027546 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-export.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-expo0000644000175100017510000000041015232633614033335 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "failing-validation" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep"; required: false } } } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-module.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-modu0000644000175100017510000000021515232633614033331 0ustar runnerrunnerProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect"; required: false } } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/direct-dependencies.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/direct-dependencies0000644000175100017510000000016315232633614033367 0ustar runnerrunnerProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation" } } qbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/0000755000175100017510000000000015232633614031216 5ustar runnerrunner././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validation-indirect/qbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-val0000755000175100017510000000000015232633614033330 5ustar runnerrunner././@LongLink0000644000000000000000000000022500000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validation-indirect/failing-validation-indirect.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-val0000644000175100017510000000006615232633614033334 0ustar runnerrunnerModule { Depends { name: "failing-validation" } } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validation/qbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-val0000755000175100017510000000000015232633614033330 5ustar runnerrunner././@LongLink0000644000000000000000000000020300000000000011576 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validation/failing-validation.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-val0000644000175100017510000000007015232633614033327 0ustar runnerrunnerModule { validate: { throw "validation error!"; } } qbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/complicated.qbs0000644000175100017510000000030115232633614032533 0ustar runnerrunnerProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect" } Depends { name: "failing-validation-indirect"; required: false } } ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-export-indirect.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/required-chain-expo0000644000175100017510000000057515232633614033351 0ustar runnerrunnerProject { Product { name: "dep2" Export { Depends { name: "dep1" } } } Product { name: "dep1" Export { Depends { name: "failing-validation-indirect" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep2"; required: false } } } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/dependency-via-export.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/dependency-via-expo0000644000175100017510000000036715232633614033343 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "failing-validation" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep" } } } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/dependency-via-module.qbsqbs-src-3.3.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/dependency-via-modu0000644000175100017510000000017415232633614033330 0ustar runnerrunnerProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect" } } qbs-src-3.3.1/tests/auto/language/testdata/keep-loading-dependencies.qbs0000644000175100017510000000011115232633614025674 0ustar runnerrunnerProduct { Depends { name: "none"; submodules: ["m1", "m2", "m3"] } } qbs-src-3.3.1/tests/auto/language/testdata/conditionaldepends.qbs0000644000175100017510000000421615232633614024571 0ustar runnerrunnerimport "conditionaldepends_base.qbs" as CondBase Project { CondBase { name: 'conditionaldepends_derived' someProp: true } CondBase { name: 'conditionaldepends_derived_false' someProp: "knolf" === "narf" } Product { name: "product_props_true" property bool someTrueProp: true Depends { condition: someTrueProp; name: "dummy" } } Product { name: "product_props_false" property bool someFalseProp: false Depends { condition: someFalseProp; name: "dummy" } } property bool someTruePrjProp: true Product { name: "project_props_true" Depends { condition: project.someTruePrjProp; name: "dummy" } } property bool someFalsePrjProp: false Product { name: "project_props_false" Depends { condition: project.someFalsePrjProp; name: "dummy" } } Product { name: "module_props_true" Depends { name: "dummy2" } Depends { condition: dummy2.someTrueProp; name: "dummy" } } Product { name: "module_props_false" Depends { name: "dummy2" } Depends { condition: dummy2.someFalseProp; name: "dummy" } } Product { name: "multilevel_module_props_true" Depends { name: "dummy3" } dummy3.loadDummy: true } Product { name: "multilevel_module_props_false" Depends { name: "dummy3" } } Product { name: "multilevel_module_props_overridden" Depends { name: "dummy3" } } Product { name: "multilevel2_module_props_true" Depends { name: "dummy3_loader" } } Product { name: "contradictory_conditions1" Depends { condition: false; name: "dummy" } Depends { condition: true; name: "dummy" } // this one wins } Product { name: "contradictory_conditions2" Depends { condition: true; name: "dummy" } // this one wins Depends { condition: false; name: "dummy" } } Product { name: "unknown_dependency_condition_false" Depends { condition: false; name: "doesonlyexistifhellfreezesover" } } } qbs-src-3.3.1/tests/auto/language/testdata/dirwithmultipleprojects/0000755000175100017510000000000015232633614025211 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dirwithmultipleprojects/project2.qbs0000644000175100017510000000000015232633614027436 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dirwithmultipleprojects/project.qbs0000644000175100017510000000000015232633614027354 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/project-property-forwarding.qbs0000644000175100017510000000032315232633614026406 0ustar runnerrunnerProject { property string prop: "parent" Project { property string prop: parent.prop + "2" Project { property bool dummy: { console.info("prop: " + prop); } } } } qbs-src-3.3.1/tests/auto/language/testdata/additional-product-types.qbs0000644000175100017510000000046015232633614025650 0ustar runnerrunnerProduct { name: "p" type: ["tag1"] Depends { name: "dummy" } Depends { name: "dummy2" } property bool hasTag1: type.includes("tag1") property bool hasTag2: type.includes("tag2") property bool hasTag3: type.includes("tag3") property bool hasTag4: type.includes("tag4") } qbs-src-3.3.1/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs0000644000175100017510000000033415232633614030152 0ustar runnerrunnerProject { Product { name: "mysterious creature" files: ["easter bunny"] } Product { name: "tasty food" condition: false Depends { name: "TheBeautifulSausage" } } } qbs-src-3.3.1/tests/auto/language/testdata/recursive-dependencies/0000755000175100017510000000000015232633614024644 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/recursive-dependencies/recursive-dependencies.qbs0000644000175100017510000000043015232633614032003 0ustar runnerrunnerProject { Product { name: "p1" Depends { name: "p3" } } Product { name: "p2" Depends { name: "p3" } } Product { name: "p3" Export { Depends { name: "p4" } } } Product { name: "p4" } } qbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/0000755000175100017510000000000015232633614027120 5ustar runnerrunner././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbsqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-r0000644000175100017510000000066615232633614033120 0ustar runnerrunnerProject { property bool useExistingModule Product { name: "a" condition: project.useExistingModule Depends { name: "deploader" } Depends { name: "dep" } dep.nosuchprop: true } Product { name: "b" condition: !project.useExistingModule Depends { name: "deploader" } Depends { name: "random"; required: false } random.nosuchprop: true } } qbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/0000755000175100017510000000000015232633614030570 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/0000755000175100017510000000000015232633614032527 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbsqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/dep0000644000175100017510000000050115232633614033216 0ustar runnerrunnerModule { // This indirection exists to properly model QBS-1776. // "deploader" corresponds to "bundle", and "dep" corresponds to "codesign" Depends { condition: project.useExistingModule; name: "dep"; required: false } Depends { condition: !project.useExistingModule; name: "random"; required: false } } qbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/0000755000175100017510000000000015232633614031340 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs0000644000175100017510000000001215232633614032610 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/exports_product.qbs0000644000175100017510000000033615232633614024166 0ustar runnerrunnerProduct { Export { version: "2.0" Depends { name: "dummy" } dummy.cFlags: ["BASE_" + exportingProduct.name.toUpperCase()] dummy.cxxFlags: ["-foo"] dummy.defines: ["ABC"] } } qbs-src-3.3.1/tests/auto/language/testdata/idusage_group.qbs0000644000175100017510000000011015232633614023545 0ustar runnerrunnerGroup { id: baseGroup name: "base" prefix: baseGroup.name } qbs-src-3.3.1/tests/auto/language/testdata/subdir2/0000755000175100017510000000000015232633614021563 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/subdir2/exports-mylib2.qbs0000644000175100017510000000053715232633614025177 0ustar runnerrunnerStaticLibrary { name: "mylib2" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" Export { Depends { name: "dummy" } dummy.defines: [exportingProduct.definePrefix + exportingProduct.name.toUpperCase()] dummy.includePaths: ["./lib"] } } qbs-src-3.3.1/tests/auto/language/testdata/idusage.qbs0000644000175100017510000000135415232633614022344 0ustar runnerrunnerimport "idusagebase.qbs" as DerivedProduct Project { id: theProject property int initialNr: 0 DerivedProduct { id: product1 } Product { id: product2 property int nr: theProject.initialNr + product1.nr + 1 name: "product2_" + nr } Product { id: product3 property int nr: product2.nr + 1 name: "product3_" + nr } DerivedProduct { id: product4 nr: product3.nr + 1 name: "product4_" + nr } Product { name: "product5" Depends { name: "deepdummy.deep.moat"; id: moat } Group { Group { condition: moat.present files: "dummy.txt" } } } } qbs-src-3.3.1/tests/auto/language/testdata/rfc1034identifier.qbs0000644000175100017510000000046415232633614024051 0ustar runnerrunnerimport qbs.Utilities CppApplication { name: Utilities.rfc1034Identifier("this!has@special#characters$uh-oh,Undersc0r3s_Are.Bad") Properties { condition: qbs.targetOS.includes("darwin") bundle.infoPlist: { return {"CFBundleIdentifier": "$(PRODUCT_NAME:rfc1034identifier)"}; } } } qbs-src-3.3.1/tests/auto/language/testdata/product-with-property.qbs0000644000175100017510000000005015232633614025226 0ustar runnerrunnerProduct { property string theProp } qbs-src-3.3.1/tests/auto/language/testdata/propertiesblocks_base.qbs0000644000175100017510000000041115232633614025300 0ustar runnerrunnerProduct { property bool defineBase: true Depends { name: "dummy" } Properties { condition: defineBase dummy.defines: ["BASE"] } dummy.defines: ["SOMETHING"] property stringList myCFlags: ["BASE"] dummy.cFlags: myCFlags } qbs-src-3.3.1/tests/auto/language/testdata/filetags.qbs0000644000175100017510000000307315232633614022521 0ustar runnerrunnerProject { FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Product { name: "filetagger_project_scope" files: ["main.cpp"] } Product { name: "filetagger_product_scope" files: ["drawline.asm"] FileTagger { patterns: "*.asm" fileTags: ["asm"] } } Product { name: "filetagger_static_pattern" files: "Banana" FileTagger { patterns: "Banana" fileTags: ["yellow"] } } Product { name: "unknown_file_tag" files: "narf.zort" } Product { name: "set_file_tag_via_group" Group { files: ["main.cpp"] fileTags: ["c++"] } } Product { name: "override_file_tag_via_group" Group { files: "main.cpp" // gets file tag "cpp" through the FileTagger fileTags: ["c++"] } } Product { name: "add_file_tag_via_group" Group { overrideTags: false files: "main.cpp" fileTags: ["zzz"] } } Product { name: "prioritized_filetagger" files: ["main.cpp"] FileTagger { patterns: ["*.cpp"] fileTags: ["cpp1"] priority: 3 } FileTagger { patterns: ["*.cpp"] fileTags: ["cpp2"] priority: 3 } FileTagger { patterns: ["*.cpp"] fileTags: ["ignored"] priority: 2 } } } qbs-src-3.3.1/tests/auto/language/testdata/overridden-variant-property.qbs0000644000175100017510000000006415232633614026405 0ustar runnerrunnerProduct { name: "p" property var myObject } qbs-src-3.3.1/tests/auto/language/testdata/environmentvariable.qbs0000644000175100017510000000012115232633614024764 0ustar runnerrunnerimport qbs.Environment Product { name: Environment.getEnv("PRODUCT_NAME") } qbs-src-3.3.1/tests/auto/language/testdata/override-product-prop-from-subproject-item.qbs0000644000175100017510000000017615232633614031252 0ustar runnerrunnerProject { SubProject { filePath: "product-with-property.qbs" Properties { theProp: "overridden" } } } qbs-src-3.3.1/tests/auto/language/testdata/filecontextproperties.qbs0000644000175100017510000000014315232633614025357 0ustar runnerrunnerProduct { name: "product1" property string narf: filePath property string zort: path } qbs-src-3.3.1/tests/auto/language/testdata/zort0000644000175100017510000000000015232633614021120 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dependencyOnAllProfiles.qbs0000644000175100017510000000041015232633614025463 0ustar runnerrunnerProject { property string profile1 property string profile2 Product { name: "dep" qbs.profiles: [project.profile1, project.profile2] } Product { name: "main" Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/language/testdata/idusagebase.qbs0000644000175100017510000000063315232633614023176 0ustar runnerrunnerimport "idusagebasebase.qbs" as DeriveMeCrazy import "idusage_group.qbs" as MyGroup import "idusage_group2.qbs" as MyGroup2 DeriveMeCrazy { id: baseProduct property int nr: theProject.initialNr + 1 name: "product1_" + nr property string productName: baseProduct.name MyGroup { name: "group in base product" } MyGroup2 { name: "another group in base product" } } qbs-src-3.3.1/tests/auto/language/testdata/property-assignment-in-exported-group.qbs0000644000175100017510000000047315232633614030344 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "dummy" } Group { name: "exported_group" dummy.someString: "test" files: ["narf"] } } } Product { Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/0000755000175100017510000000000015232633614024570 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/0000755000175100017510000000000015232633614026240 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix2/0000755000175100017510000000000015232633614027617 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs0000644000175100017510000000006215232633614031703 0ustar runnerrunnerModule { Depends { name: "prefix2.suffix" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/0000755000175100017510000000000015232633614031123 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs0000644000175100017510000000001315232633614033130 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/0000755000175100017510000000000015232633614027616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/0000755000175100017510000000000015232633614031136 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/0000755000175100017510000000000015232633614032442 5ustar runnerrunner././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suf0000644000175100017510000000001215232633614033153 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs0000644000175100017510000000001315232633614031675 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/0000755000175100017510000000000015232633614031122 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/suffix.qbs0000644000175100017510000000005315232633614033133 0ustar runnerrunnerModule { Depends { name: "prefix1" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/0000755000175100017510000000000015232633614031135 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qb0000644000175100017510000000001215232633614032771 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/0000755000175100017510000000000015232633614032522 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/su0000644000175100017510000000001215232633614033065 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/0000755000175100017510000000000015232633614032523 5ustar runnerrunner././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/su0000644000175100017510000000001215232633614033066 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs0000644000175100017510000000015415232633614027765 0ustar runnerrunnerProduct { Depends { name: "prefix1.middle1.suffix1" } Depends { name: "prefix1.middle1.suffix2" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs0000644000175100017510000000014415232633614030736 0ustar runnerrunnerProduct { Depends { name: "prefix1.middle1" } Depends { name: "prefix1.middle1.suffix1" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/simple-collision2.qbs0000644000175100017510000000005415232633614030642 0ustar runnerrunnerProduct { Depends { name: "prefix2" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/simple-collision1.qbs0000644000175100017510000000006315232633614030641 0ustar runnerrunnerProduct { Depends { name: "prefix1.suffix" } } qbs-src-3.3.1/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs0000644000175100017510000000014315232633614027764 0ustar runnerrunnerProduct { Depends { name: "prefix1.middle1" } Depends { name: "prefix1.middle2.suffix" } } qbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/0000755000175100017510000000000015232633614025475 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/imports/0000755000175100017510000000000015232633614027172 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs0000644000175100017510000000012515232633614031526 0ustar runnerrunnerProperties { condition: qbs.buildVariant === "debug" name: "product_debug" } qbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs0000644000175100017510000000013115232633614032055 0ustar runnerrunnerProperties { condition: qbs.buildVariant === "release" name: "product_release" } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-product.qbsqbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-pro0000644000175100017510000000011415232633614033476 0ustar runnerrunnerProduct { name: "product_default" DebugName {} ReleaseName {} } qbs-src-3.3.1/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items.qbs0000644000175100017510000000015115232633614033465 0ustar runnerrunnerProject { qbsSearchPaths: sourceDirectory references: "inherited-properties-items-product.qbs" } qbs-src-3.3.1/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs0000644000175100017510000000020115232633614027405 0ustar runnerrunnerProduct { Profile { name: "test-profile" qbs.architecture: "arm" qbs.targetPlatform: "macos" } } qbs-src-3.3.1/tests/auto/language/testdata/eval-error-in-non-present-module.qbs0000644000175100017510000000016415232633614027134 0ustar runnerrunnerProduct { name: "p" property bool moduleRequired Depends { name: "broken"; required: moduleRequired } } qbs-src-3.3.1/tests/auto/language/testdata/productconditions.qbs0000644000175100017510000000143015232633614024470 0ustar runnerrunnerimport qbs.Probes Project { Product { name: "product_no_condition" } Product { name: "product_true_condition" condition: 1 === 1 } Product { name: "product_false_condition" condition: 1 === 2 } Product { name: "product_condition_dependent_of_module" condition: qbs.architecture !== (qbs.architecture + "foo") } Product { name: "product_probe_condition_true" condition: trueProbe.found Probe { id: trueProbe configure: { found = true; } } } Product { name: "product_probe_condition_false" condition: falseProbe.found Probe { id: falseProbe configure: { found = false; } } } } qbs-src-3.3.1/tests/auto/language/testdata/builtinFunctionInSearchPathsProperty.qbs0000644000175100017510000000024615232633614030260 0ustar runnerrunnerimport qbs.Environment Project { qbsSearchPaths: { if (!Environment.getEnv("PATH")) throw "Environment.getEnv doesn't seem to work"; } } qbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/0000755000175100017510000000000015232633614025106 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/0000755000175100017510000000000015232633614026556 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/lower/0000755000175100017510000000000015232633614027706 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/lower/lower.qbs0000644000175100017510000000056715232633614031555 0ustar runnerrunnerModule { property bool setProp property string value: "fromLower" property string prop: "default" property stringList listProp property int n: 0 Group { condition: setProp module.prop: outer + "_" + value module.listProp: "WITH_LOWER_PROP" } Group { condition: n module.listProp: ["N_NON_ZERO"] } } qbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/higher2/0000755000175100017510000000000015232633614030106 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/higher2/higher2.qbs0000644000175100017510000000043315232633614032145 0ustar runnerrunnerModule { Depends { name: "lower" } property bool setProp Properties { condition: setProp lower.prop: undefined lower.listProp: "WITH_HIGHER2_PROP" } Properties { condition: lower.n > 6 lower.listProp: "N_GREATER_6" } } qbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/higher1/0000755000175100017510000000000015232633614030105 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/modules/higher1/higher1.qbs0000644000175100017510000000076615232633614032154 0ustar runnerrunnerModule { Depends { name: "lower" } property bool setProp property string value: "fromHigher1" Properties { condition: setProp lower.prop: value lower.listProp: "WITH_HIGHER1_PROP" } Properties { condition: lower.n > 5 lower.listProp: "N_GREATER_5" } Properties { condition: lower.n < 10 lower.listProp: "N_LESS_10" } Properties { condition: lower.n < 20 lower.listProp: "N_LESS_20" } } qbs-src-3.3.1/tests/auto/language/testdata/disabled-properties-item/disabled-properties-item.qbs0000644000175100017510000000102415232633614032507 0ustar runnerrunnerProduct { name: "p" Depends { name: "higher1" } Depends { name: "higher2" } property bool setProp property string value: "fromProduct" property stringList productProp: "default" lower.n: 10 Group { condition: setProp product.lower.prop: value product.lower.listProp: "WITH_PRODUCT_PROP" product.productProp: "condition1" } Group { condition: lower.n > 7 product.lower.listProp: "N_GREATER_7" product.productProp: "condition2" } } qbs-src-3.3.1/tests/auto/language/testdata/base-validate/0000755000175100017510000000000015232633614022712 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/base-validate/modules/0000755000175100017510000000000015232633614024362 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/base-validate/modules/m/0000755000175100017510000000000015232633614024616 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/base-validate/modules/m/m.qbs0000644000175100017510000000030615232633614025560 0ustar runnerrunnerMParent { condition: true validate: { var parentResult = base; if (!parentResult) throw "Parent failed"; throw "Parent succeeded, child failed."; } } qbs-src-3.3.1/tests/auto/language/testdata/base-validate/modules/m/MParent.qbs0000644000175100017510000000006315232633614026672 0ustar runnerrunnerModule { condition: false validate: true } qbs-src-3.3.1/tests/auto/language/testdata/base-validate/base-validate.qbs0000644000175100017510000000004615232633614026122 0ustar runnerrunnerProduct { Depends { name: "m" } } qbs-src-3.3.1/tests/auto/language/testdata/narf.zort0000644000175100017510000000000015232633614022045 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/ParentWithExport.qbs0000644000175100017510000000017615232633614024213 0ustar runnerrunnerProduct { Export { Depends { name: "dummy" } dummy.defines: [exportingProduct.name.toUpperCase()] } } qbs-src-3.3.1/tests/auto/language/testdata/idusagebasebase.qbs0000644000175100017510000000017615232633614024033 0ustar runnerrunnerProduct { id: baseBaseProduct name: "ace of base" property string productNameInBaseOfBase: baseBaseProduct.name } qbs-src-3.3.1/tests/auto/language/testdata/probes-and-multiplexing.qbs0000644000175100017510000000062615232633614025475 0ustar runnerrunnerProduct { multiplexByQbsProperties: "architectures" qbs.architectures: ["x86", "x86_64", "arm"] property string archFromProbe: theProbe.archOut Probe { id: theProbe property string archIn: qbs.architecture property string archOut configure: { archOut = archIn; } } Group { name: "theGroup" qbs.sysroot: "/" + theProbe.archOut } } qbs-src-3.3.1/tests/auto/language/testdata/jsimportsinmultiplescopes.qbs0000644000175100017510000000025315232633614026272 0ustar runnerrunnerimport "jsimportsinmultiplescopes.js" as MyFunctions Product { name: MyFunctions.getName(qbs) qbs.installDir: MyFunctions.getInstallDir() files: "main.cpp" } qbs-src-3.3.1/tests/auto/language/testdata/relaxed-error-mode/0000755000175100017510000000000015232633614023706 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/relaxed-error-mode/file1.txt0000644000175100017510000000000015232633614025435 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/relaxed-error-mode/relaxed-error-mode.qbs0000644000175100017510000000121015232633614030104 0ustar runnerrunnerProject { Product { name: "recursive depender" Depends { name: "depender required" } files: "file1.txt" } Product { name: "broken" Depends { name: "nosuchmodule" } } Product { name: "depender required" Depends { name: "broken" } files: "file1.txt" } Product { name: "depender nonrequired" Depends { name: "broken"; required: false } files: "file1.txt" } Product { name: "missing file" files: ["file1.txt", "file3.txt", "file2.txt"] } Product { name: "fine" files: "file2.txt" } } qbs-src-3.3.1/tests/auto/language/testdata/relaxed-error-mode/file2.txt0000644000175100017510000000000015232633614025436 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/main.cpp0000644000175100017510000000000015232633614021627 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/0000755000175100017510000000000015232633614022672 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/egon.qbs0000644000175100017510000000031115232633614024324 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "higher" } } } Product { name: "egon" Depends { name: "dep" } lower.prop1: "blubb" } } qbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/modules/0000755000175100017510000000000015232633614024342 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/modules/higher/0000755000175100017510000000000015232633614025610 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/modules/higher/higher.qbs0000644000175100017510000000025215232633614027564 0ustar runnerrunnerModule { Depends { name: "lower" } lower.prop2: lower.prop1 === "egon" ? "withEgon" : original lower.listProp: lower.prop1 === "egon" ? ["egon"] : original } qbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/modules/lower/0000755000175100017510000000000015232633614025472 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/modules/lower/lower.qbs0000644000175100017510000000030615232633614027330 0ustar runnerrunnerModule { property string prop1 property string prop2: prop1 === "blubb" ? "withBlubb" : "withoutBlubb" property stringList listProp: prop1 === "blubb" ? ["blubb", "other"] : ["other"] } qbs-src-3.3.1/tests/auto/language/testdata/defaultvalue/test.txt0000644000175100017510000000000015232633614024400 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/getNativeSetting.qbs0000644000175100017510000000163415232633614024210 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities import qbs.Host Project { Product { name: "p1" targetName: { if (Host.os().includes("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductName"); } else if (Host.os().includes("windows")) { var productName = Utilities.getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName"); if (productName.includes("Windows")) { return "Windows"; } return undefined; } else { return Utilities.getNativeSetting(FileInfo.joinPaths(path, "nativesettings.ini"), "osname"); } } } Product { name: "p2" targetName: Utilities.getNativeSetting("/dev/null", undefined, "fallback"); } } qbs-src-3.3.1/tests/auto/language/testdata/multiplexed-exports.qbs0000644000175100017510000000101215232633614024750 0ustar runnerrunnerProject { Product { name: "dep" multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] property string includeDir: qbs.buildVariant === "debug" ? "/d" : "/r" Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.includeDir } } Product { name: "p" Depends { name: "dep" } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } } qbs-src-3.3.1/tests/auto/language/testdata/non-required-products.qbs0000644000175100017510000000134115232633614025170 0ustar runnerrunnerProject { Product { name: "depender" Depends { name: "dummy" } Depends { name: "dependee"; required: false } Properties { condition: dependee.present dummy.defines: ["WITH_DEPENDEE"] } } Project { name: "subproject" Product { name: "dependee" } } Product { name: "p1" condition: p2.present Depends { name: "p2"; required: false } } Product { name: "p2" condition: p3.present Depends { name: "p3"; required: false } } Product { name: "p3" condition: nosuchmodule.present Depends { name: "nosuchmodule"; required: false } } } qbs-src-3.3.1/tests/auto/language/testdata/chained-probes/0000755000175100017510000000000015232633614023074 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/chained-probes/modules/0000755000175100017510000000000015232633614024544 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/chained-probes/modules/m/0000755000175100017510000000000015232633614025000 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/chained-probes/modules/m/m.qbs0000644000175100017510000000064615232633614025751 0ustar runnerrunnerModule { Probe { id: probe1 property string probe1Prop configure: { probe1Prop = "probe1Val"; found = true } } Probe { id: probe2 property string inputProp: prop1 property string probe2Prop configure: { probe2Prop = inputProp + "probe2Val"; found = true } } property string prop1: probe1.probe1Prop property string prop2: probe2.probe2Prop } qbs-src-3.3.1/tests/auto/language/testdata/chained-probes/chained-probes.qbs0000644000175100017510000000004615232633614026466 0ustar runnerrunnerProduct { Depends { name: "m" } } qbs-src-3.3.1/tests/auto/language/testdata/correct-decl-in-parent-lookup.qbs0000644000175100017510000000013715232633614026471 0ustar runnerrunnerProduct { name: "p" Depends { name: "dummy" } dummy.cxxFlags: base.concat(["x"]) } qbs-src-3.3.1/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs0000644000175100017510000000016015232633614027730 0ustar runnerrunnerProject { condition: qbs.targetOS.includes("whatever") Product { name: "never reached" } } qbs-src-3.3.1/tests/auto/language/testdata/canonicalArchitecture.qbs0000644000175100017510000000012415232633614025207 0ustar runnerrunnerimport qbs.Utilities Product { name: Utilities.canonicalArchitecture("i386") } qbs-src-3.3.1/tests/auto/language/testdata/dummy.txt0000644000175100017510000000000015232633614022073 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/disabled-subproject.qbs0000644000175100017510000000076115232633614024651 0ustar runnerrunnerProject { SubProject { condition: false filePath: "nosuchfile.qbs" } SubProject { Properties { condition: false } filePath: "nosuchfile.qbs" } SubProject { condition: true Properties { condition: false } filePath: "nosuchfile.qbs" } SubProject { condition: false Properties { condition: true } filePath: "nosuchfile.qbs" } } qbs-src-3.3.1/tests/auto/language/testdata/modulescope_base.qbs0000644000175100017510000000010315232633614024223 0ustar runnerrunnerProduct { Depends { name: "scopemod" } scopemod.h: e * f } qbs-src-3.3.1/tests/auto/language/testdata/multiplexing-by-profile/0000755000175100017510000000000015232633614025000 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/multiplexing-by-profile/p4.qbs0000644000175100017510000000060115232633614026027 0ustar runnerrunnerProject { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Product { name: "p1" qbs.profiles: ["profile1"] Depends { name: "p2"; profiles: ["profile1"] } } Product { name: "p2" qbs.profiles: ["profile1", "profile2"] } } qbs-src-3.3.1/tests/auto/language/testdata/multiplexing-by-profile/p3.qbs0000644000175100017510000000102115232633614026023 0ustar runnerrunnerProject { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Profile { name: "profile3" qbs.architecture: "hurz" } Profile { name: "profile4" qbs.architecture: "zonk" } Product { name: "p1" qbs.profiles: ["profile1", "profile2"] Depends { name: "p2" } } Product { name: "p2" qbs.profiles: ["profile3", "profile4"] } } qbs-src-3.3.1/tests/auto/language/testdata/multiplexing-by-profile/p2.qbs0000644000175100017510000000055115232633614026031 0ustar runnerrunnerProject { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Product { name: "p1" qbs.profiles: ["profile1"] } Product { name: "p2" qbs.profiles: ["profile1", "profile2"] Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/multiplexing-by-profile/p1.qbs0000644000175100017510000000042415232633614026027 0ustar runnerrunnerProject { Profile { name: "theProfile" qbs.architecture: "dummy" } Product { name: "p1" qbs.profiles: ["theProfile"] } Product { name: "p2" qbs.profiles: ["theProfile"] Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/narf0000644000175100017510000000000015232633614021050 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/invalid-overrides.qbs0000644000175100017510000000032215232633614024343 0ustar runnerrunnerProject { name: "My.Project" property bool x Product { name: "MyProduct" property bool x } Product { name: "MyOtherProduct" Depends { name: "cpp" } } } qbs-src-3.3.1/tests/auto/language/testdata/jsextensions.js0000644000175100017510000000420715232633614023306 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ (function() { // Function wrapper to keep the environment clean. /* * poor man's JS test suite */ var testctx = {}; function initTestContext(name) { testctx.nr = 1; testctx.name = name; } function verify(c) { if (!c) throw testctx.name + ": verification #" + testctx.nr + " failed."; testctx.nr++; } /* * Tests for extensions of JavaScript builtin types. */ var a = ["one", "two", "three"]; initTestContext("Array.prototype.contains"); for (var k in a) verify(k !== "contains"); verify(a.includes("one")); verify(a.includes("two")); verify(a.includes("three")); verify(!a.includes("four")); })() // END function wrapper qbs-src-3.3.1/tests/auto/language/testdata/erroneous/0000755000175100017510000000000015232633614022232 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency_cycle4.qbs0000644000175100017510000000005515232633614026322 0ustar runnerrunnerProduct { Depends { name: "module-a" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency_cycle3.qbs0000644000175100017510000000026215232633614026321 0ustar runnerrunnerProject { Product { type: ["a"] name: "A" Depends { name: "B" } } Product { name: "B" Depends { productTypes: ["a"] } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared-parameter1.qbs0000644000175100017510000000016215232633614027105 0ustar runnerrunnerProduct { Depends { name: "prefix2.suffix" } Depends { name: "readonly"; prefix2.suffix.nope: "nope" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/conflicting-properties-in-export-items.qbs0000644000175100017510000000011015232633614032464 0ustar runnerrunnerParentWithExport { Export { property string theProp } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/oldQbsVersion.qbs0000644000175100017510000000013715232633614025534 0ustar runnerrunnerProject { minimumQbsVersion: "999.5.4" Product { qbs.enableSound: true } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/references_cycle.qbs0000644000175100017510000000006715232633614026244 0ustar runnerrunnerProject { references: ["references_cycle2.qbs"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/0000755000175100017510000000000015232633614023702 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/no_such_property/0000755000175100017510000000000015232633614027304 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/no_such_property/no-such-property.qbs0000644000175100017510000000015215232633614033247 0ustar runnerrunnerModule { Depends { name: "module_with_parameters" } module_with_parameters.noSuchProperty: true } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/prefix2/0000755000175100017510000000000015232633614025261 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/prefix2/prefix2.qbs0000644000175100017510000000006215232633614027345 0ustar runnerrunnerModule { Depends { name: "prefix2.suffix" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/prefix2/suffix/0000755000175100017510000000000015232633614026565 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/prefix2/suffix/suffix.qbs0000644000175100017510000000001315232633614030572 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/0000755000175100017510000000000015232633614030165 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-0000644000175100017510000000007115232633614033163 0ustar runnerrunnerimport "missing-js-file.js" as MissingJsFile Module { } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.jsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.0000644000175100017510000000005415232633614033165 0ustar runnerrunnervar userfile = require("javascriptfile.js") qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-wrong-property-option/0000755000175100017510000000000015232633614032462 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-wrong-property-option/m.qbs0000644000175100017510000000023015232633614033420 0ustar runnerrunnerModule { property string someProp PropertyOptions { name: "s0meProp" description: "Oops, spelt the property name wrong" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/recursion_helper/0000755000175100017510000000000015232633614027252 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/recursion_helper/recursion_helper.qbs0000644000175100017510000000005215232633614033326 0ustar runnerrunnerModule { property bool a: product.a } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module_with_parameters/0000755000175100017510000000000015232633614030445 5ustar runnerrunner././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module_with_parameters/module_with_parameters.qbsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module_with_parameters/module_with_para0000644000175100017510000000032115232633614033707 0ustar runnerrunnerModule { Parameter { property bool boolParameter } Parameter { property int intParameter } Parameter { property stringList stringListParameter } Parameter { property string stringParameter } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-invalid-original/0000755000175100017510000000000015232633614031366 5ustar runnerrunner././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-invalid-original/module-with-invalid-original.qbsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-invalid-original/module-wit0000644000175100017510000000005315232633614033375 0ustar runnerrunnerModule { property string p: original } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-id/0000755000175100017510000000000015232633614026532 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs0000644000175100017510000000001215232633614032742 0ustar runnerrunnerModule {} qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs0000644000175100017510000000003715232633614031577 0ustar runnerrunnerModuleWithIdParent { id: foo } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-a/0000755000175100017510000000000015232633614025405 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-a/module-a.qbs0000644000175100017510000000005415232633614027616 0ustar runnerrunnerModule { Depends { name: "module-b" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/0000755000175100017510000000000015232633614030166 5ustar runnerrunner././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/conflicting-instance1.qbsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/conflicting-insta0000644000175100017510000000001315232633614033516 0ustar runnerrunnerModule { } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/conflicting-instance2.qbsqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/conflicting-insta0000644000175100017510000000001315232633614033516 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-b/0000755000175100017510000000000015232633614025406 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/module-b/module-b.qbs0000644000175100017510000000005415232633614027620 0ustar runnerrunnerModule { Depends { name: "module-a" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/readonly/0000755000175100017510000000000015232633614025517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/erroneous/modules/readonly/readonly.qbs0000644000175100017510000000011715232633614030042 0ustar runnerrunnerModule { readonly property string readOnlyString: "I cannot be changed!" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/no-configure-in-probe.qbs0000644000175100017510000000005715232633614027047 0ustar runnerrunnerProduct { Probe { id: hurz } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/ParentItem.qbs0000644000175100017510000000014615232633614025012 0ustar runnerrunnerProduct { property bool cpp readonly property string readOnlyString: "I cannot be changed!" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/recursive-property-indirect-via-module.qbs0000644000175100017510000000013515232633614032470 0ustar runnerrunnerProduct { Depends { name: "recursion_helper" } property bool a: recursion_helper.a } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs0000644000175100017510000000010115232633614030467 0ustar runnerrunnerProduct { Depends { name: "module-with-invalid-original" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/subproject_cycle3.qbs0000644000175100017510000000011515232633614026360 0ustar runnerrunnerProject { SubProject { filePath: "subproject_cycle.qbs" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/missing-js-file.qbs0000644000175100017510000000007315232633614025741 0ustar runnerrunnerProduct { Depends { name: "missing-js-file-module" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/throw_in_property_binding.qbs0000644000175100017510000000010215232633614030221 0ustar runnerrunnerProduct { name: { throw "something is wrong"; } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/references_cycle2.qbs0000644000175100017510000000006715232633614026326 0ustar runnerrunnerProject { references: ["references_cycle3.qbs"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/frozen-object-list.qbs0000644000175100017510000000044615232633614026465 0ustar runnerrunner Product { Probe { id: probe property varList output configure: { output = [{"key": "value"}]; found = true; } } property var test: { var result = probe.output; result.push({}); return result; } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/importloop1.qbs0000644000175100017510000000004515232633614025225 0ustar runnerrunnerimport "importloop2.qbs" as X X {} qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs0000644000175100017510000000055615232633614026326 0ustar runnerrunnerProject { Product { name: "A" Depends { name: "B" } files: ["main.cpp"] } Product { name: "B" Depends { name: "C" } files: ["main.cpp"] } Product { name: "C" Depends { name: "A" } files: ["main.cpp"] } Product { name: "D" files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared-parameter2.qbs0000644000175100017510000000012415232633614027104 0ustar runnerrunnerProduct { name: "myproduct" Depends { name: "readonly"; foo.bar: "bla" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/nonexistentouter.qbs0000644000175100017510000000006415232633614026376 0ustar runnerrunnerProject { Product { name: outer } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/duplicate_sources.qbs0000644000175100017510000000012215232633614026451 0ustar runnerrunnerProduct { files: ["main.cpp"] Group { files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/multiple_exports.qbs0000644000175100017510000000005015232633614026353 0ustar runnerrunnerProduct { Export {} Export {} } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/unknown_item_type.qbs0000644000175100017510000000014315232633614026515 0ustar runnerrunnerNarf { zort: 1 // This invalid binding should not hide the "Unexpected item type" error. } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid_stringlist_element.qbs0000644000175100017510000000005715232633614030364 0ustar runnerrunnerProduct { files: ["foo", ["zoo"], "bar"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid-property-option.qbs0000644000175100017510000000010615232633614027554 0ustar runnerrunnerProduct { Depends { name: "module-with-wrong-property-option" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undefined_stringlist_element_in_probe.qbs0000644000175100017510000000022315232633614032547 0ustar runnerrunnerProduct { Probe { id: dummy property stringList l configure: { l = ["a", undefined, "b"] } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid_property_type.qbs0000644000175100017510000000005315232633614027372 0ustar runnerrunnerProduct { property nonsense esnesnon } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/mismatching-multiplex-dependency.qbs0000644000175100017510000000046315232633614031404 0ustar runnerrunnerProject { Product { name: "a" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["x86", "arm"] } Product { name: "b" Depends { name: "a" } multiplexByQbsProperties: ["architectures"] qbs.architectures: ["mips", "ppc"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs0000644000175100017510000000025515232633614027510 0ustar runnerrunnerProject { Product { name: "a" Export { x.y.z: original } } Product { name: "b" Depends { name: "a" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/module-var-in-product.qbs0000644000175100017510000000011115232633614027067 0ustar runnerrunnerProduct { property bool p Group { module.p: true } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_item.qbs0000644000175100017510000000005515232633614026065 0ustar runnerrunnerProduct { cpp.defines: ["SUPERCRAZY"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/rule-without-output-tags.qbs0000644000175100017510000000034615232633614027706 0ustar runnerrunnerProduct { Rule { inputs: "input-tag" prepare: { var cmd = new JavaScriptCommand; cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs0000644000175100017510000000004115232633614031563 0ustar runnerrunnerProject { qbs.sysroot: "/" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/misused-inherited-property.qbs0000644000175100017510000000005515232633614030245 0ustar runnerrunnerParentItem { cpp.compilerName: "blubb" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs0000644000175100017510000000033015232633614027503 0ustar runnerrunnerProject { Product { name: "a" Export { Properties { x.y.z: original } } } Product { name: "b" Depends { name: "a" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item3.qbs0000644000175100017510000000017215232633614032203 0ustar runnerrunnerProject { Product { name: "p1" Export { blubb: false } } Product { Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/original-in-product-property.qbs0000644000175100017510000000005115232633614030505 0ustar runnerrunnerProduct { property int n: original } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid_file.qbs0000644000175100017510000000005715232633614025370 0ustar runnerrunnerProduct { files: ["main.cpp", "other.h"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/original-in-export-item.qbs0000644000175100017510000000027115232633614027424 0ustar runnerrunnerProject { Product { name: "a" Export { property string p: original } } Product { name: "b" Depends { name: "a" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undefined_stringlist_element.qbs0000644000175100017510000000010715232633614030673 0ustar runnerrunnerProduct { property string blubb files: ["foo", blubb, "bar"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/importloop2.qbs0000644000175100017510000000004515232633614025226 0ustar runnerrunnerimport "importloop1.qbs" as X X {} qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid-references.qbs0000644000175100017510000000006015232633614026502 0ustar runnerrunnerProject { references: "nosuchproject.qbs" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property_wrapper.qbs0000644000175100017510000000011715232633614030552 0ustar runnerrunnerProject { SubProject { filePath: "undeclared_property.qbs" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs0000644000175100017510000000056315232633614031075 0ustar runnerrunnerProject { Product { name: "a" multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["x86", "arm"] qbs.buildVariants: ["debug", "release"] } Product { name: "b" Depends { name: "a" } multiplexByQbsProperties: ["architectures"] qbs.architectures: ["x86", "arm"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/subproject_cycle.qbs0000644000175100017510000000011615232633614026276 0ustar runnerrunnerProject { SubProject { filePath: "subproject_cycle2.qbs" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid-parameter-type.qbs0000644000175100017510000000034215232633614027323 0ustar runnerrunnerProduct { Depends { name: "module_with_parameters" } Depends { name: "readonly" module_with_parameters.boolParameter: "This is not an error." module_with_parameters.stringParameter: 123 } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/references_cycle3.qbs0000644000175100017510000000006615232633614026326 0ustar runnerrunnerProject { references: ["references_cycle.qbs"] } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property.qbs0000644000175100017510000000004215232633614027007 0ustar runnerrunnerProduct { doesntexist: 123 } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_module_property_in_module.qbs0000644000175100017510000000010315232633614032405 0ustar runnerrunnerProduct { name: "p" Depends { name: "no_such_property" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/ParentWithExport.qbs0000644000175100017510000000007515232633614026232 0ustar runnerrunnerProduct { Export { property bool theProp } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/unknown_module.qbs0000644000175100017510000000007415232633614026006 0ustar runnerrunnerProduct { Depends { name: "neitherModuleNorProduct" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/multiple_properties_in_subproject.qbs0000644000175100017510000000016015232633614031773 0ustar runnerrunnerProject { SubProject { Properties { condition: false } Properties { name: "blubb" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/overwrite-inherited-readonly-property.qbs0000644000175100017510000000007715232633614032441 0ustar runnerrunnerParentItem { readOnlyString: "changing the unchangeable" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item2.qbs0000644000175100017510000000024215232633614032200 0ustar runnerrunnerProject { Product { name: "p1" Export { something.other: "x" } } Product { Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/wrong-toplevel-item.qbs0000644000175100017510000000001515232633614026655 0ustar runnerrunnerArtifact { } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/main.cpp0000644000175100017510000000356015232633614023666 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs0000644000175100017510000000044115232633614030456 0ustar runnerrunnerProject { Profile { name: "profile1" } Profile { name: "profile2" } Product { name: "dep" qbs.profiles: ["profile1", "profile2"] } Product { name: "main" Depends { name: "dep"; profiles: ["profile47"]; } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs0000644000175100017510000000026215232633614026462 0ustar runnerrunnerProject { Product { name: "B" Depends { productTypes: ["a"] } } Product { type: ["a"] name: "A" Depends { name: "B" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/frozen-object.qbs0000644000175100017510000000047315232633614025514 0ustar runnerrunner Product { Probe { id: probe property var output configure: { output = {"key": "value"} found = true } } property var test: { "use strict" var result = probe.output; result.key = "newValue"; return result; } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/subproject_cycle2.qbs0000644000175100017510000000011615232633614026360 0ustar runnerrunnerProject { SubProject { filePath: "subproject_cycle3.qbs" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/wrongQbsVersionFormat.qbs0000644000175100017510000000006215232633614027260 0ustar runnerrunnerProject { minimumQbsVersion: "hfyh1234wat?" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/module-with-id.qbs0000644000175100017510000000010115232633614025561 0ustar runnerrunnerProduct { name: "p" Depends { name: "module-with-id" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs0000644000175100017510000000023415232633614032451 0ustar runnerrunnerProduct { Depends { name: "cpp" } Properties { condition: cpp.nonexistingproperty.includes("somevalue") cpp.defines: ["ABC"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item.qbs0000644000175100017510000000030015232633614032111 0ustar runnerrunnerProject { Product { name: "p1" Export { Depends { name: "cpp" } cpp.blubb: "x" } } Product { Depends { name: "p1" } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/overwrite-readonly-module-property.qbs0000644000175100017510000000014615232633614031750 0ustar runnerrunnerProduct { Depends { name: "readonly" } readonly.readOnlyString: "changing the unchangeable" } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid-parameter-rhs.qbs0000644000175100017510000000017415232633614027141 0ustar runnerrunnerProduct { Depends { name: "prefix2.suffix" } Depends { name: "readonly"; prefix2.suffix.nope: access.will.fail } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/undeclared_property_in_Properties_item.qbs0000644000175100017510000000007215232633614032732 0ustar runnerrunnerProduct { Properties { blubb.bla: "x" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/syntax-error-in-probe.qbs0000644000175100017510000000012515232633614027125 0ustar runnerrunnerProduct { Probe { id: hurz configure: { fngkgsdjfgklkf } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs0000644000175100017510000000035015232633614030316 0ustar runnerrunnerProject { Profile { name: "profile1" } Product { name: "dep" qbs.profiles: ["profile1"] } Product { name: "main" Depends { name: "dep"; profiles: ["profile47"]; } } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/conflicting-module-instances.qbs0000644000175100017510000000007215232633614030507 0ustar runnerrunnerProduct { Depends { name: "conflicting-instances" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/missing-colon.qbs0000644000175100017510000000013215232633614025516 0ustar runnerrunnerProduct { Depends { name: "dummy" } qbsSearchPaths: ".." dummy.cxxFlags { } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/recursive-property-indirect.qbs0000644000175100017510000000012115232633614030423 0ustar runnerrunnerProduct { property bool a: b property bool b: c property bool c: a } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/invalid_child_item_type.qbs0000644000175100017510000000005115232633614027605 0ustar runnerrunnerProject { Depends { name: "foo" } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs0000644000175100017510000000026215232633614030224 0ustar runnerrunnerProduct { type: "app" Group { fileTagsFilter: "app" qbs.install: true } Group { fileTagsFilter: "app" qbs.install: false } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/reserved_name_in_import.qbs0000644000175100017510000000006515232633614027641 0ustar runnerrunnerimport "../idusagebase.qbs" as TextFile Product { } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/duplicate_sources_wildcards.qbs0000644000175100017510000000014615232633614030513 0ustar runnerrunnerProduct { files: ["*.qbs"] Group { files: ["duplicate_sources_wildcards.qbs"] } } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/recursive-property-direct.qbs0000644000175100017510000000004315232633614030077 0ustar runnerrunnerProduct { property bool a: a } qbs-src-3.3.1/tests/auto/language/testdata/erroneous/dependency_cycle.qbs0000644000175100017510000000045415232633614026241 0ustar runnerrunnerProject { Product { name: "A" Depends { name: "B" } files: ["main.cpp"] } Product { name: "B" Depends { name: "C" } files: ["main.cpp"] } Product { name: "C" Depends { name: "A" } files: ["main.cpp"] } } qbs-src-3.3.1/tests/auto/language/testdata/module-depends-on-product.qbs0000644000175100017510000000022515232633614025714 0ustar runnerrunnerProject { Product { name: "p1" Depends { name: "module-with-product-dependency" } } Product { name: "p2" } } qbs-src-3.3.1/tests/auto/language/testdata/buildconfigstringlistsyntax.qbs0000644000175100017510000000006015232633614026573 0ustar runnerrunnerProject { property stringList someStrings } qbs-src-3.3.1/tests/auto/language/testdata/baseproperty.qbs0000644000175100017510000000022215232633614023433 0ustar runnerrunnerimport "baseproperty_base.qbs" as BaseProduct BaseProduct { name: "product1" narf: base.concat(["boo"]) zort: base.concat(["boo"]) } qbs-src-3.3.1/tests/auto/language/testdata/modulepropertiesingroups.qbs0000644000175100017510000000450715232633614026117 0ustar runnerrunnerProject { Product { name: "grouptest" Depends { name: "gmod.gmod1" } Depends { name: "gmod3" } Depends { name: "gmod4" } gmod.gmod1.gmod1_list2: base.concat([name, gmod.gmod1.gmod1_string]) gmod.gmod1.gmod1_list3: ["product"] gmod.gmod1.p1: 1 Group { name: "g1" files: ["Banana"] gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 2 gmod2.prop: 1 gmod2.commonName: "g1" gmod3.gmod3_string: "g1_gmod3" gmod4.gmod4_string: "g1_gmod4" Group { name: "g1.1" gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 4 gmod2.prop: 2 gmod2.commonName: name gmod3.gmod3_string: "g1.1_gmod3" gmod4.gmod4_string: "g1.1_gmod4" } Group { name: "g1.2" gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 8 gmod2.commonName: name gmod3.gmod3_string: "g1.2_gmod3" } } Group { name: "g2" files: ["zort"] gmod.gmod1.gmod1_string: name gmod.gmod1.p1: 2 gmod.gmod1.p2: 4 gmod2.prop: 2 gmod3.gmod3_string: name + "_gmod3" gmod4.gmod4_string: name + "_gmod4" Group { name: "g2.1" Group { name: "g2.1.1" gmod.gmod1.gmod1_list2: [name] gmod.gmod1.p2: 15 } } } } Product { name: "grouptest2" Depends { name: "gmod.gmod1" } Group { name: "g1" gmod.gmod1.gmod1_list2: ["G1"] Group { name: "g1.1" gmod.gmod1.gmod1_string: "G1.1" } } } Product { name: "module-property-in-group-condition" Depends { name: "cpp" } Group { condition: qbs.architecture === "x86_64" cpp.includePaths: "." } } } qbs-src-3.3.1/tests/auto/language/testdata/file-in-product-and-module.qbs0000644000175100017510000000026215232633614025744 0ustar runnerrunnerProduct { name: "p" Depends { name: "module_with_file" } property bool addFileToProduct Group { files: "zort" condition: addFileToProduct } } qbs-src-3.3.1/tests/auto/language/testdata/drawline.asm0000644000175100017510000000000015232633614022506 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/properties-item-in-module.qbs0000644000175100017510000000020415232633614025733 0ustar runnerrunnerProject { Product { name: "a"; Depends { name: "dummyqt.core" } } Product { name: "b"; Depends { name: "dummyqt.core" } } } qbs-src-3.3.1/tests/auto/language/testdata/Banana0000644000175100017510000000003215232633614021307 0ustar runnerrunnerPeanut butter jelly time! qbs-src-3.3.1/tests/auto/language/testdata/subdir/0000755000175100017510000000000015232633614021501 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/subdir/pathproperties_base.qbs0000644000175100017510000000016615232633614026256 0ustar runnerrunnerProduct { property path base_fileInProductDir: "foo" property path base_fileInBaseProductDir: path + "/bar" } qbs-src-3.3.1/tests/auto/language/testdata/subdir/exports-mylib.qbs0000644000175100017510000000074715232633614025036 0ustar runnerrunnerStaticLibrary { name: "mylib" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" property path aPath: "." dummy.somePath: aPath Export { Depends { name: "dummy" } Depends { name: "mylib2" } dummy.defines: [exportingProduct.definePrefix + exportingProduct.name.toUpperCase()] dummy.includePaths: ["./lib"] dummy.somePath: exportingProduct.aPath } } qbs-src-3.3.1/tests/auto/language/testdata/properties-block-in-group.qbs0000644000175100017510000000073715232633614025751 0ustar runnerrunnerProduct { name: "in-group" property bool featureEnabled: true Depends { name: "dummy" } Depends { name: "module_with_group" } dummy.defines: ["BASEDEF"] Group { condition: featureEnabled name: "the group" files: ["dummy.txt" ] Properties { condition: name === "the group" dummy.defines: ["FEATURE_ENABLED", name.toUpperCase().replace(' ', '_')] } dummy.defines: "GROUP_ONLY" } } qbs-src-3.3.1/tests/auto/language/testdata/duplicate-multiplex-value2.qbs0000644000175100017510000000024715232633614026112 0ustar runnerrunnerProduct { name: "p" multiplexByQbsProperties: ["architectures", "buildVariants", "architectures"] aggregate: false qbs.architectures: ["x86", "arm"] } qbs-src-3.3.1/tests/auto/language/testdata/pathproperties.qbs0000644000175100017510000000042315232633614023770 0ustar runnerrunnerimport "subdir/pathproperties_base.qbs" as ProductBase ProductBase { name: "product1" property path projectFileDir: "." property pathList filesInProjectFileDir: ["./aboutdialog.h", "aboutdialog.cpp"] Depends { name: "dummy" } dummy.includePaths: ["."] } qbs-src-3.3.1/tests/auto/language/testdata/throw.qbs0000644000175100017510000000070315232633614022063 0ustar runnerrunnerProject { property string throwType property bool dummy: { if (throwType === "bool") throw true; if (throwType === "int") throw 43; if (throwType === "string") throw "an error"; if (throwType === "list") throw ["an", "error"]; if (throwType === "object") throw { result: "crash", reason: "overheating" }; throw "type missing"; } } qbs-src-3.3.1/tests/auto/language/testdata/productdirectories.qbs0000644000175100017510000000003615232633614024634 0ustar runnerrunnerProduct { name: "MyApp" } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/0000755000175100017510000000000015232633614023654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/import-collection/imports/0000755000175100017510000000000015232633614025351 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/import-collection/imports/Collection/0000755000175100017510000000000015232633614027444 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/import-collection/imports/Collection/file2.js0000644000175100017510000000004115232633614030776 0ustar runnerrunnerfunction f2() { return "C1f2"; } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/imports/Collection/file1.js0000644000175100017510000000004115232633614030775 0ustar runnerrunnerfunction f1() { return "C1f1"; } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/product.qbs0000644000175100017510000000030215232633614026036 0ustar runnerrunnerimport Collection as Collection1 import "collection" as Collection2 Product { name: "da product" targetName: Collection1.f1() + Collection1.f2() + Collection2.f1() + Collection2.f2() } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/collection/0000755000175100017510000000000015232633614026007 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/import-collection/collection/file2.js0000644000175100017510000000004115232633614027341 0ustar runnerrunnerfunction f2() { return "C2f2"; } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/collection/file1.js0000644000175100017510000000004115232633614027340 0ustar runnerrunnerfunction f1() { return "C2f1"; } qbs-src-3.3.1/tests/auto/language/testdata/import-collection/project.qbs0000644000175100017510000000005515232633614026031 0ustar runnerrunnerProject { references: ["product.qbs"] } qbs-src-3.3.1/tests/auto/language/testdata/derived-sub-project/0000755000175100017510000000000015232633614024066 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/derived-sub-project/subproject.qbs0000644000175100017510000000001415232633614026750 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/language/testdata/derived-sub-project/DerivedSubProject.qbs0000644000175100017510000000001715232633614030156 0ustar runnerrunnerSubProject { } qbs-src-3.3.1/tests/auto/language/testdata/derived-sub-project/project.qbs0000644000175100017510000000021215232633614026236 0ustar runnerrunnerProject { DerivedSubProject { filePath: "subproject.qbs" Properties { name: "something" } } } qbs-src-3.3.1/tests/auto/language/testdata/qbs1275.qbs0000644000175100017510000000111115232633614022016 0ustar runnerrunnerProject { Product { name: "v-bug" Export { Depends { name: "cpp"} cpp.defines: "" } } Product { name: "e-bug" Export { Depends { name: "v-bug" } } } Product { name: "u-bug" Export { Depends { name: "c-bug" } } } Product { name: "c-bug" Export { Depends { name: "e-bug" } } } Product { name: "H-bug" Depends { name: "e-bug" } Depends { name: "u-bug" } Group { qbs.install: true } } } qbs-src-3.3.1/tests/auto/language/testdata/dirwithnoprojects/0000755000175100017510000000000015232633614023772 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/dirwithnoprojects/.gitignore0000644000175100017510000000001615232633614025757 0ustar runnerrunner* !.gitignore qbs-src-3.3.1/tests/auto/language/testdata/module-property-overrides-per-product.qbs0000644000175100017510000000056715232633614030341 0ustar runnerrunnerProject { Product { Depends { name: "dummy" } name: "a" property stringList rpaths: dummy.rpaths } Product { Depends { name: "dummy" } name: "b" property stringList rpaths: dummy.rpaths } Product { Depends { name: "dummy" } name: "c" property stringList rpaths: dummy.rpaths } } qbs-src-3.3.1/tests/auto/language/testdata/throwing-probe.qbs0000644000175100017510000000030215232633614023661 0ustar runnerrunnerProduct { name: "theProduct" property bool enableProbe Probe { id: whatever condition: enableProbe configure: { throw "Error!"; } } } qbs-src-3.3.1/tests/auto/language/testdata/delayed-error/0000755000175100017510000000000015232633614022747 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/delayed-error/validation.qbs0000644000175100017510000000025015232633614025605 0ustar runnerrunnerProject { property bool enableProduct: true Product { name: "theProduct" condition: project.enableProduct Depends { name: "m" } } } qbs-src-3.3.1/tests/auto/language/testdata/delayed-error/modules/0000755000175100017510000000000015232633614024417 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/delayed-error/modules/m/0000755000175100017510000000000015232633614024653 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/delayed-error/modules/m/m.qbs0000644000175100017510000000007015232633614025613 0ustar runnerrunnerModule { validate: { throw "Validation error!"; } } qbs-src-3.3.1/tests/auto/language/testdata/delayed-error/nonexisting.qbs0000644000175100017510000000026315232633614026024 0ustar runnerrunnerProject { property bool enableProduct: true Product { name: "theProduct" condition: project.enableProduct Depends { name: "nosuchmodule" } } } qbs-src-3.3.1/tests/auto/language/testdata/parameter-types.qbs0000644000175100017510000000073415232633614024046 0ustar runnerrunnerProject { Product { name: "foo" qbsSearchPaths: "./erroneous" Depends { name: "module_with_parameters" } Depends { name: "bar" module_with_parameters.boolParameter: true module_with_parameters.intParameter: 156 module_with_parameters.stringParameter: "hello" module_with_parameters.stringListParameter: ["la", "le", "lu"] } } Product { name: "bar" } } qbs-src-3.3.1/tests/auto/language/testdata/depends-item-in-group.qbs0000644000175100017510000000070715232633614025040 0ustar runnerrunnerProject { Product { name: "dep" } Product { name: "main" property bool enableGroup1 property bool enableGroup2 property bool enableDepends Group { condition: enableGroup1 Group { condition: product.enableGroup2 property bool forwarded: product.enableDepends Depends { name: "dep"; condition: forwarded } } } } } qbs-src-3.3.1/tests/auto/language/testdata/multiple-module-backends-via-own-property.qbs0000644000175100017510000000041115232633614031042 0ustar runnerrunnerProduct { name: "p" multiplexByQbsProperties: ["profiles"] qbs.profiles: ["theProfile"] Depends { name: "multiple_backends_via_own_property" } Profile { name: "theProfile" multiple_backends_via_own_property.type: "type1" } } qbs-src-3.3.1/tests/auto/language/testdata/error-in-disabled-product.qbs0000644000175100017510000000161715232633614025705 0ustar runnerrunnerProject { Product { name: "a" condition: false property stringList l: [undefined] } Product { name: "b" condition: false Group { name: { throw "boo!" } } } Product { name: "c" Group { condition: false name: { throw "boo!" } } } Project { condition: false Project { condition: true Product { name: "d" condition: { throw "ouch!" } } } } Product { condition: false Rule { inputs: [5] } } Project { condition: false minimumQbsVersion: false } Product { name: "e" condition: dummy.falseProperty Depends { name: "does.not.exist" } Depends { name: "dummy" } } } qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/0000755000175100017510000000000015232633614027367 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/product.qbs0000644000175100017510000000007215232633614031555 0ustar runnerrunnerProduct { Depends { name: "conflicting-instances" } } qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/0000755000175100017510000000000015232633614030133 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/0000755000175100017510000000000015232633614031603 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/conflicting-instances/qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/conflict0000755000175100017510000000000015232633614033325 5ustar runnerrunner././@LongLink0000644000000000000000000000017200000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/conflicting-instances/bar.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/conflict0000644000175100017510000000006415232633614033327 0ustar runnerrunnerModule { property string moduleVariant: "bar" } qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/project.qbs0000644000175100017510000000005415232633614031543 0ustar runnerrunnerProject { references: ["product.qbs"] } qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/0000755000175100017510000000000015232633614030152 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/0000755000175100017510000000000015232633614031622 5ustar runnerrunner././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/conflicting-instances/qbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/conflict0000755000175100017510000000000015232633614033344 5ustar runnerrunner././@LongLink0000644000000000000000000000017200000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/conflicting-instances/foo.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/conflict0000644000175100017510000000006415232633614033346 0ustar runnerrunnerModule { property string moduleVariant: "foo" } qbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/0000755000175100017510000000000015232633614026063 5ustar runnerrunner././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/module-merging-variant-values.qbsqbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/module-merging-variant-valu0000644000175100017510000000017315232633614033331 0ustar runnerrunnerProduct { multiplexByQbsProperties: ["architectures"] qbs.architectures: ["a1", "a2"] Depends { name: "m2" } } qbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/modules/0000755000175100017510000000000015232633614027533 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/modules/m2/0000755000175100017510000000000015232633614030051 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/modules/m2/m2.qbs0000644000175100017510000000071715232633614031103 0ustar runnerrunnerModule { Depends { name: "m1" } m1.arch: qbs.architecture property string arch: qbs.architecture validate: { if (qbs.architecture !== "a1" && qbs.architecture !== "a2") throw "Unexpected arch " + qbs.architecture; if (arch !== qbs.architecture) throw "Oops: " + arch + "/" + qbs.architecture; if (m1.arch !== qbs.architecture) throw "Oops: " + m1.arch + "/" + qbs.architecture; } } qbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/modules/m1/0000755000175100017510000000000015232633614030050 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/language/testdata/module-merging-variant-values/modules/m1/m1.qbs0000644000175100017510000000027215232633614031075 0ustar runnerrunnerModule { condition: qbs.architecture === "a1" || qbs.architecture === "a2" property string arch qbs.architecture: undefined // We do something like this in GenericGCC.qbs } qbs-src-3.3.1/tests/auto/language/testdata/non-applicable-module-property-in-profile.qbs0000644000175100017510000000067215232633614031020 0ustar runnerrunnerProject { property string targetOS property string toolchain Product { name: "p" multiplexByQbsProperties: ["profiles"] qbs.profiles: ["theProfile"] Depends { name: "multiple_backends" } Profile { name: "theProfile" qbs.targetOS: [project.targetOS] qbs.toolchain: [project.toolchain] multiple_backends.backend3Prop: "value" } } } qbs-src-3.3.1/tests/auto/language/testdata/MyProperties.qbs0000644000175100017510000000001715232633614023360 0ustar runnerrunnerProperties { } qbs-src-3.3.1/tests/auto/language/language.qbs0000644000175100017510000000122115232633614020666 0ustar runnerrunnerimport qbs.Utilities QbsUnittest { Depends { name: "qbsversion" } Depends { name: "qbsconsolelogger" } testName: "language" condition: qbsbuildconfig.enableUnitTests Properties { condition: qbs.toolchain.contains("mingw") cpp.cxxFlags: "-Wno-maybe-uninitialized" } files: [ "tst_language.cpp", "tst_language.h" ] cpp.defines: base.concat([ "QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version), "SRCDIR=" + Utilities.cStringQuote(path) ]) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-3.3.1/tests/auto/tools/0000755000175100017510000000000015232633614015755 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/tools/tst_tools.cpp0000644000175100017510000010745715232633614020531 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_tools.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; namespace std { template struct hash> { std::size_t operator()(const std::vector &v) const noexcept { return hashRange(v); } }; } // namespace std TestTools::TestTools(Settings *settings) : m_settings(settings), testDataDir(testWorkDir("tools")) { } TestTools::~TestTools() { qDeleteAll(m_tmpDirs); } void TestTools::initTestCase() { QDir().mkpath(testDataDir); } void TestTools::fileSaver() { QVERIFY(QDir::setCurrent(testDataDir)); static const char *fn = "foo.txt"; const auto run = [](const std::function &func) { if (QFile::exists(fn)) QVERIFY(QFile::remove(fn)); func(); if (QFile::exists(fn)) QVERIFY(QFile::remove(fn)); }; // failing to open the file means nothing works run([] { Internal::FileSaver fs(fn); QVERIFY(!fs.device()); QVERIFY(!fs.write("hello")); QVERIFY(!fs.commit()); QVERIFY(!QFile::exists(fn)); }); // verify that correct usage creates a file with the right contents run([] { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello")); }); // failing to commit writes nothing run([] { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(!QFile::exists(fn)); }); // verify that correct usage creates a file with the right contents and does not overwrite run([] { { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello")); } const auto lm = QFileInfo(fn).lastModified(); QVERIFY(lm.isValid()); waitForNewTimestamp("."); { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); } const auto lm2 = QFileInfo(fn).lastModified(); QVERIFY(lm2.isValid()); QCOMPARE(lm, lm2); // timestamps should be the same since content did not change waitForNewTimestamp("."); { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello2")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello2")); } const auto lm3 = QFileInfo(fn).lastModified(); QVERIFY(lm3.isValid()); QVERIFY(lm != lm3); // timestamps should differ since the content changed waitForNewTimestamp("."); { // Test overwriteIfUnchanged Internal::FileSaver fs(fn, true); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello2")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello2")); } const auto lm4 = QFileInfo(fn).lastModified(); QVERIFY(lm4.isValid()); QVERIFY(lm3 != lm4); // timestamps should differ since we always overwrite }); } void TestTools::testFileInfo() { QCOMPARE(FileInfo::fileName("C:/waffl/copter.exe"), QString("copter.exe")); QCOMPARE(FileInfo::baseName("C:/waffl/copter.exe.lib"), QString("copter")); QCOMPARE(FileInfo::completeBaseName("C:/waffl/copter.exe.lib"), QString("copter.exe")); QCOMPARE(FileInfo::suffix("C:/waffl/copter.exe.lib"), QString("lib")); QCOMPARE(FileInfo::completeSuffix("C:/waffl/copter.exe.lib"), QString("exe.lib")); QCOMPARE(FileInfo::path("abc"), QString(".")); QCOMPARE(FileInfo::path("/abc/lol"), QString("/abc")); QCOMPARE(FileInfo::path("/fileInRoot"), QString(QLatin1Char('/'))); if (HostOsInfo::isWindowsHost()) QCOMPARE(FileInfo::path("C:/fileInDriveRoot"), QString("C:/")); QVERIFY(!FileInfo::isAbsolute("bla/lol")); QVERIFY(FileInfo::isAbsolute("/bla/lol")); if (HostOsInfo::isWindowsHost()) { QVERIFY(FileInfo::isAbsolute("C:\\bla\\lol")); QVERIFY(FileInfo::isAbsolute("C:\\")); QVERIFY(FileInfo::isAbsolute("C:/")); QVERIFY(!FileInfo::isAbsolute("C:")); } QCOMPARE(FileInfo::resolvePath("/abc/lol", "waffl"), QString("/abc/lol/waffl")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../foo/bar"), QString("/abc/def/ghi/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../../foo/bar"), QString("/abc/def/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc", "../../../foo/bar"), QString("/foo/bar")); if (HostOsInfo::isWindowsHost()) { QCOMPARE(FileInfo::resolvePath("C:/share", ".."), QString("C:/")); QCOMPARE(FileInfo::resolvePath("C:/share", "D:/"), QString("D:/")); QCOMPARE(FileInfo::resolvePath("C:/share", "D:"), QString()); // should soft-assert } QCOMPARE(FileInfo("/does/not/exist").lastModified(), FileTime()); } void TestTools::fileCaseCheck() { QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/CamelCase")); QVERIFY2(tempFile.open(), qPrintable(tempFile.errorString())); QFileInfo tempFileInfo(tempFile.fileName()); const QString lowerFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toLower(); const QString upperFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toUpper(); QVERIFY(FileInfo::isFileCaseCorrect(tempFileInfo.absoluteFilePath())); if (QFile::exists(lowerFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(lowerFilePath)); if (QFile::exists(upperFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(upperFilePath)); } void TestTools::testProfiles() { TemporaryProfile tpp("parent", m_settings); Profile parentProfile = tpp.p; TemporaryProfile tpc("child", m_settings); Profile childProfile = tpc.p; parentProfile.removeBaseProfile(); parentProfile.remove("testKey"); QCOMPARE(parentProfile.value("testKey", "none").toString(), QLatin1String("none")); parentProfile.setValue("testKey", "testValue"); QCOMPARE(parentProfile.value("testKey").toString(), QLatin1String("testValue")); childProfile.remove("testKey"); childProfile.removeBaseProfile(); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); childProfile.setBaseProfile("parent"); QCOMPARE(childProfile.value("testKey").toString(), QLatin1String("testValue")); // Change base profile and check if the inherited value also changes. TemporaryProfile tpf("foo", m_settings); Profile fooProfile = tpf.p; fooProfile.setValue("testKey", "gnampf"); childProfile.setBaseProfile("foo"); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("gnampf")); ErrorInfo errorInfo; childProfile.setBaseProfile("SmurfAlongWithMe"); childProfile.value("blubb", QString(), &errorInfo); QVERIFY(errorInfo.hasError()); errorInfo.clear(); childProfile.setBaseProfile("parent"); parentProfile.setBaseProfile("child"); QVERIFY(!childProfile.value("blubb", QString(), &errorInfo).isValid()); QVERIFY(errorInfo.hasError()); QVERIFY(!childProfile.allKeys(Profile::KeySelectionNonRecursive).empty()); errorInfo.clear(); QVERIFY(childProfile.allKeys(Profile::KeySelectionRecursive, &errorInfo).empty()); QVERIFY(errorInfo.hasError()); } void TestTools::testSettingsMigration() { QFETCH(QString, baseDir); QFETCH(bool, hasOldSettings); Settings settings(baseDir); if (hasOldSettings) { // checks that we do not copy old "profiles/" dir anymore QVERIFY(!QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles/right.txt") .exists()); QVERIFY(!settings.value("key", Settings::UserScope).toString().isEmpty()); } else { QVERIFY(!QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles").exists()); QVERIFY(settings.allKeys(Settings::UserScope).empty()); } } void TestTools::testSettingsMigration_data() { QTest::addColumn("baseDir"); QTest::addColumn("hasOldSettings"); QTest::newRow("settings dir with lots of versions") << setupSettingsDir1() << true; QTest::newRow("settings dir with only a fallback") << setupSettingsDir2() << true; QTest::newRow("no previous settings") << setupSettingsDir3() << false; } QString TestTools::setupSettingsDir1() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); const Version thisVersion = Version::fromString(QBS_VERSION); Version predecessor; if (thisVersion.patchLevel() > 0) { predecessor.setMajorVersion(thisVersion.majorVersion()); predecessor.setMinorVersion(thisVersion.minorVersion()); predecessor.setPatchLevel(thisVersion.patchLevel() - 1); } else if (thisVersion.minorVersion() > 0) { predecessor.setMajorVersion(thisVersion.majorVersion()); predecessor.setMinorVersion(thisVersion.minorVersion() - 1); predecessor.setPatchLevel(99); } else { predecessor.setMajorVersion(thisVersion.majorVersion() - 1); predecessor.setMajorVersion(99); predecessor.setPatchLevel(99); } const auto versions = QList() << Version(0, 1, 0) << Version(1, 0, 5) << predecessor << Version(thisVersion.majorVersion() + 1, thisVersion.minorVersion(), thisVersion.patchLevel()) << Version(thisVersion.majorVersion(), thisVersion.minorVersion() + 1, thisVersion.patchLevel()) << Version(thisVersion.majorVersion(), thisVersion.minorVersion(), thisVersion.patchLevel() + 1) << Version(99, 99, 99); for (const Version &v : versions) { const QString settingsDir = baseDir->path() + "/qbs/" + v.toString(); QSettings s(settingsDir + "/qbs.conf", HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat); const QString profilesDir = settingsDir + "/profiles"; QDir::root().mkpath(profilesDir); const QString magicString = v == predecessor ? "right" : "wrong"; QFile f(profilesDir + '/' + magicString + ".txt"); f.open(QIODevice::WriteOnly); s.setValue("org/qt-project/qbs/key", profilesDir + magicString); } return baseDir->path(); } QString TestTools::setupSettingsDir2() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); const QString settingsDir = baseDir->path(); QSettings s(settingsDir + QLatin1String("/qbs.conf"), HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat); const QString profilesDir = settingsDir + QLatin1String("/qbs/profiles"); QDir::root().mkpath(profilesDir); QFile f(profilesDir + "/right.txt"); f.open(QIODevice::WriteOnly); s.setValue("org/qt-project/qbs/key", profilesDir + "right"); return baseDir->path(); } QString TestTools::setupSettingsDir3() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); return baseDir->path(); } void TestTools::testBuildConfigMerging() { TemporaryProfile tp(QLatin1String("tst_tools_profile"), m_settings); Profile profile = tp.p; profile.setValue(QStringLiteral("topLevelKey"), QStringLiteral("topLevelValue")); profile.setValue(QStringLiteral("qbs.toolchain"), QStringLiteral("gcc")); profile.setValue(QStringLiteral("qbs.architecture"), QStringLiteral("Jean-Claude Pillemann")); profile.setValue(QStringLiteral("cpp.treatWarningsAsErrors"), true); QVariantMap overrideMap; overrideMap.insert(QStringLiteral("qbs.toolchain"), QStringLiteral("clang")); overrideMap.insert(QStringLiteral("qbs.installRoot"), QStringLiteral("/blubb")); SetupProjectParameters params; params.setSettingsDirectory(m_settings->baseDirectory()); params.setTopLevelProfile(profile.name()); params.setConfigurationName(QStringLiteral("debug")); params.setOverriddenValues(overrideMap); const ErrorInfo error = params.expandBuildConfiguration(); QVERIFY2(!error.hasError(), qPrintable(error.toString())); const QVariantMap finalMap = params.finalBuildConfigurationTree(); QCOMPARE(finalMap.size(), 3); QCOMPARE(finalMap.value(QStringLiteral("topLevelKey")).toString(), QStringLiteral("topLevelValue")); const QVariantMap finalQbsMap = finalMap.value(QStringLiteral("qbs")).toMap(); QCOMPARE(finalQbsMap.size(), 4); QCOMPARE(finalQbsMap.value(QStringLiteral("toolchain")).toString(), QStringLiteral("clang")); QCOMPARE(finalQbsMap.value(QStringLiteral("configurationName")).toString(), QStringLiteral("debug")); QCOMPARE(finalQbsMap.value(QStringLiteral("architecture")).toString(), QStringLiteral("Jean-Claude Pillemann")); QCOMPARE(finalQbsMap.value(QStringLiteral("installRoot")).toString(), QLatin1String("/blubb")); const QVariantMap finalCppMap = finalMap.value(QStringLiteral("cpp")).toMap(); QCOMPARE(finalCppMap.size(), 1); QCOMPARE(finalCppMap.value(QStringLiteral("treatWarningsAsErrors")).toBool(), true); } void TestTools::testProcessNameByPid() { QCOMPARE(qAppName(), processNameByPid(QCoreApplication::applicationPid())); } int toNumber(const QString &str) { int res = 0; for (const QChar &c : str) res = (res * 10) + c.digitValue(); return res; } void TestTools::set_operator_eq() { { Set set1, set2; QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert(1); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); set2.insert(1); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set2.insert(1); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert(2); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); } { Set set1, set2; QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert("one"); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); set2.insert("one"); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set2.insert("one"); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert("two"); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); } { Set a; Set b; a += "otto"; b += "willy"; QVERIFY(a != b); QVERIFY(!(a == b)); } { Set s1, s2; s1.reserve(100); s2.reserve(4); QVERIFY(s1 == s2); s1 << 100 << 200 << 300 << 400; s2 << 400 << 300 << 200 << 100; QVERIFY(s1 == s2); } } void TestTools::set_swap() { Set s1, s2; s1.insert(1); s2.insert(2); s1.swap(s2); QCOMPARE(*s1.begin(),2); QCOMPARE(*s2.begin(),1); } void TestTools::set_size() { Set set; QVERIFY(set.size() == 0); QVERIFY(set.empty()); QVERIFY(set.size() == set.size()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.insert(2); QVERIFY(set.size() == 2); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(2); QVERIFY(set.size() == 0); QVERIFY(set.empty()); QVERIFY(set.size() == set.size()); } void TestTools::set_capacity() { Set set; size_t n = set.capacity(); QVERIFY(n == 0); for (int i = 0; i < 1000; ++i) { set.insert(i); QVERIFY(set.capacity() >= set.size()); } } void TestTools::set_reserve() { Set set; set.reserve(1000); QVERIFY(set.capacity() >= 1000); for (int i = 0; i < 500; ++i) set.insert(i); QVERIFY(set.capacity() >= 1000); for (int j = 0; j < 500; ++j) set.remove(j); QVERIFY(set.capacity() >= 1000); } void TestTools::set_clear() { Set set1, set2; QVERIFY(set1.size() == 0); set1.clear(); QVERIFY(set1.size() == 0); set1.insert("foo"); QVERIFY(set1.size() != 0); set2 = set1; set1.clear(); QVERIFY(set1.size() == 0); QVERIFY(set2.size() != 0); set2.clear(); QVERIFY(set1.size() == 0); QVERIFY(set2.size() == 0); } void TestTools::set_remove() { Set set1; const size_t max = 500; for (size_t i = 0; i < max; ++i) set1.insert(QString::number(i)); QCOMPARE(set1.size(), max); for (size_t j = 0; j < max; ++j) { set1.remove(QString::number((j * 17) % max)); QCOMPARE(set1.size(), max - j - 1); } } void TestTools::set_contains() { Set set1; for (int i = 0; i < 500; ++i) { QVERIFY(!set1.contains(QString::number(i))); set1.insert(QString::number(i)); QVERIFY(set1.contains(QString::number(i))); } QCOMPARE(set1.size(), size_t { 500 }); for (int j = 0; j < 500; ++j) { int i = (j * 17) % 500; QVERIFY(set1.contains(QString::number(i))); set1.remove(QString::number(i)); QVERIFY(!set1.contains(QString::number(i))); } } void TestTools::set_containsSet() { Set set1; Set set2; // empty set contains the empty set QVERIFY(set1.contains(set2)); for (int i = 0; i < 500; ++i) { set1.insert(QString::number(i)); set2.insert(QString::number(i)); } QVERIFY(set1.contains(set2)); set2.remove(QString::number(19)); set2.remove(QString::number(82)); set2.remove(QString::number(7)); QVERIFY(set1.contains(set2)); set1.remove(QString::number(23)); QVERIFY(!set1.contains(set2)); // filled set contains the empty set as well Set set3; QVERIFY(set1.contains(set3)); // the empty set doesn't contain a filled set QVERIFY(!set3.contains(set1)); // verify const signature const Set set4; QVERIFY(set3.contains(set4)); } void TestTools::set_find() { Set set1; for (int i = 0; i < 500; ++i) { QVERIFY(set1.find(QString::number(i)) == set1.end()); set1.insert(QString::number(i)); const auto it = set1.find(QString::number(i)); QVERIFY(it != set1.end()); QVERIFY(*it == QString::number(i)); } QCOMPARE(set1.size(), size_t { 500 }); for (int j = 0; j < 500; ++j) { int i = (j * 17) % 500; const auto it = set1.find(QString::number(i)); QVERIFY(it != set1.end()); QVERIFY(*it == QString::number(i)); set1.remove(QString::number(i)); QVERIFY(set1.find(QString::number(i)) == set1.end()); } } void TestTools::set_begin() { Set set1; Set set2 = set1; { const auto i = set1.constBegin(); const auto j = set1.cbegin(); const auto k = set2.constBegin(); const auto ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } set1.insert(44); { const auto i = set1.constBegin(); const auto j = set1.cbegin(); const auto k = set2.constBegin(); const auto ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } set2 = set1; { const auto i = set1.constBegin(); const auto j = set1.cbegin(); const auto k = set2.constBegin(); const auto ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } } void TestTools::set_end() { Set set1; Set set2 = set1; { const auto i = set1.constEnd(); const auto j = set1.cend(); const auto k = set2.constEnd(); const auto ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() == set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } set1.insert(44); { const auto i = set1.constEnd(); const auto j = set1.cend(); const auto k = set2.constEnd(); const auto ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() != set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } set2 = set1; { const auto i = set1.constEnd(); const auto j = set1.cend(); const auto k = set2.constEnd(); const auto ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() != set1.constEnd()); QVERIFY(set2.constBegin() != set2.constEnd()); } set1.clear(); set2.clear(); QVERIFY(set1.constBegin() == set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } struct IdentityTracker { int value, id; }; inline bool operator==(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value == rhs.value; } inline bool operator<(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value < rhs.value; } void TestTools::set_insert() { { Set set1; QVERIFY(set1.size() == 0); set1.insert(1); QVERIFY(set1.size() == 1); set1.insert(2); QVERIFY(set1.size() == 2); set1.insert(2); QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); set1.remove(2); QVERIFY(set1.size() == 1); QVERIFY(!set1.contains(2)); set1.insert(2); QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); } { Set set1; QVERIFY(set1.size() == 0); set1 << 1; QVERIFY(set1.size() == 1); set1 << 2; QVERIFY(set1.size() == 2); set1 << 2; QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); set1.remove(2); QVERIFY(set1.size() == 1); QVERIFY(!set1.contains(2)); set1 << 2; QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); } { Set set; QCOMPARE(set.size(), size_t { 0 }); const int dummy = -1; IdentityTracker id00 = {0, 0}, id01 = {0, 1}, searchKey = {0, dummy}; QCOMPARE(set.insert(id00).first->id, id00.id); QCOMPARE(set.size(), size_t { 1 }); QCOMPARE(set.insert(id01).first->id, id00.id); // first inserted is kept QCOMPARE(set.size(), size_t { 1 }); QCOMPARE(set.find(searchKey)->id, id00.id); } } void TestTools::set_reverseIterators() { Set s; s << 1 << 17 << 61 << 127 << 911; std::vector v(s.begin(), s.end()); std::reverse(v.begin(), v.end()); const Set &cs = s; QVERIFY(std::equal(v.begin(), v.end(), s.rbegin())); QVERIFY(std::equal(v.begin(), v.end(), s.crbegin())); QVERIFY(std::equal(v.begin(), v.end(), cs.rbegin())); QVERIFY(std::equal(s.rbegin(), s.rend(), v.begin())); QVERIFY(std::equal(s.crbegin(), s.crend(), v.begin())); QVERIFY(std::equal(cs.rbegin(), cs.rend(), v.begin())); } void TestTools::set_stlIterator() { Set set1; for (int i = 0; i < 25000; ++i) set1.insert(QString::number(i)); { int sum = 0; auto i = set1.cbegin(); while (i != set1.end()) { sum += toNumber(*i); ++i; } QVERIFY(sum == 24999 * 25000 / 2); } { int sum = 0; auto i = set1.cend(); while (i != set1.begin()) { --i; sum += toNumber(*i); } QVERIFY(sum == 24999 * 25000 / 2); } } void TestTools::set_stlMutableIterator() { Set set1; for (int i = 0; i < 25000; ++i) set1.insert(QString::number(i)); { int sum = 0; auto i = set1.begin(); while (i != set1.end()) { sum += toNumber(*i); ++i; } QVERIFY(sum == 24999 * 25000 / 2); } { int sum = 0; auto i = set1.end(); while (i != set1.begin()) { --i; sum += toNumber(*i); } QVERIFY(sum == 24999 * 25000 / 2); } { Set set2 = set1; Set set3 = set2; auto i = set2.begin(); auto j = set3.begin(); while (i != set2.end()) { i = set2.erase(i); } QVERIFY(set2.empty()); QVERIFY(!set3.empty()); j = set3.end(); while (j != set3.begin()) { j--; if (j + 1 != set3.end()) set3.erase(j + 1); } if (set3.begin() != set3.end()) set3.erase(set3.begin()); QVERIFY(set2.empty()); QVERIFY(set3.empty()); i = set2.insert("foo").first; QCOMPARE(*i, QLatin1String("foo")); } } void TestTools::set_setOperations() { Set set1, set2; set1 << "alpha" << "beta" << "gamma" << "delta" << "zeta" << "omega"; set2 << "beta" << "gamma" << "delta" << "epsilon" << "iota" << "omega"; Set set3 = set1; set3.unite(set2); QVERIFY(set3.size() == 8); QVERIFY(set3.contains("alpha")); QVERIFY(set3.contains("beta")); QVERIFY(set3.contains("gamma")); QVERIFY(set3.contains("delta")); QVERIFY(set3.contains("epsilon")); QVERIFY(set3.contains("zeta")); QVERIFY(set3.contains("iota")); QVERIFY(set3.contains("omega")); Set set4 = set2; set4.unite(set1); QVERIFY(set4.size() == 8); QVERIFY(set4.contains("alpha")); QVERIFY(set4.contains("beta")); QVERIFY(set4.contains("gamma")); QVERIFY(set4.contains("delta")); QVERIFY(set4.contains("epsilon")); QVERIFY(set4.contains("zeta")); QVERIFY(set4.contains("iota")); QVERIFY(set4.contains("omega")); QVERIFY(set3 == set4); Set set5 = set1; set5.intersect(set2); QVERIFY(set5.size() == 4); QVERIFY(set5.contains("beta")); QVERIFY(set5.contains("gamma")); QVERIFY(set5.contains("delta")); QVERIFY(set5.contains("omega")); Set set6 = set2; set6.intersect(set1); QVERIFY(set6.size() == 4); QVERIFY(set6.contains("beta")); QVERIFY(set6.contains("gamma")); QVERIFY(set6.contains("delta")); QVERIFY(set6.contains("omega")); QVERIFY(set5 == set6); Set set7 = set1; set7.subtract(set2); QVERIFY(set7.size() == 2); QVERIFY(set7.contains("alpha")); QVERIFY(set7.contains("zeta")); Set set8 = set2; set8.subtract(set1); QVERIFY(set8.size() == 2); QVERIFY(set8.contains("epsilon")); QVERIFY(set8.contains("iota")); Set set9 = set1 | set2; QVERIFY(set9 == set3); Set set10 = set1 & set2; QVERIFY(set10 == set5); Set set11 = set1 + set2; QVERIFY(set11 == set3); Set set12 = set1 - set2; QVERIFY(set12 == set7); Set set13 = set2 - set1; QVERIFY(set13 == set8); Set set14 = set1; set14 |= set2; QVERIFY(set14 == set3); Set set15 = set1; set15 &= set2; QVERIFY(set15 == set5); Set set16 = set1; set16 += set2; QVERIFY(set16 == set3); Set set17 = set1; set17 -= set2; QVERIFY(set17 == set7); Set set18 = set2; set18 -= set1; QVERIFY(set18 == set8); } void TestTools::set_makeSureTheComfortFunctionsCompile() { Set set1, set2, set3; set1 << 5; set1 |= set2; set1 |= 5; set1 &= set2; set1 &= 5; set1 += set2; set1 += 5; set1 -= set2; set1 -= 5; set1 = set2 | set3; set1 = set2 & set3; set1 = set2 + set3; set1 = set2 - set3; } void TestTools::set_initializerList() { Set set = {1, 1, 2, 3, 4, 5}; QCOMPARE(set.size(), size_t { 5 }); QVERIFY(set.contains(1)); QVERIFY(set.contains(2)); QVERIFY(set.contains(3)); QVERIFY(set.contains(4)); QVERIFY(set.contains(5)); // check _which_ of the equal elements gets inserted (in the QHash/QMap case, it's the last): const Set set2 = {{1, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; QCOMPARE(set2.size(), size_t { 5 }); const int dummy = -1; const IdentityTracker searchKey = {1, dummy}; QCOMPARE(set2.find(searchKey)->id, 0); Set emptySet{}; QVERIFY(emptySet.empty()); Set set3{{}, {}, {}}; QVERIFY(!set3.empty()); } void TestTools::set_intersects() { Set s1; Set s2; QVERIFY(!s1.intersects(s1)); QVERIFY(!s1.intersects(s2)); s1 << 100; QVERIFY(s1.intersects(s1)); QVERIFY(!s1.intersects(s2)); s2 << 200; QVERIFY(!s1.intersects(s2)); s1 << 200; QVERIFY(s1.intersects(s2)); Set s3; s3 << 500; QVERIFY(!s1.intersects(s3)); s3 << 200; QVERIFY(s1.intersects(s3)); } void TestTools::stringutils_join() { QFETCH(std::vector, input); QFETCH(std::string, separator); QFETCH(std::string, expectedResult); QCOMPARE(join(input, separator), expectedResult); } void TestTools::stringutils_join_data() { QTest::addColumn>("input"); QTest::addColumn("separator"); QTest::addColumn("expectedResult"); QTest::newRow("data1") << std::vector() << std::string() << std::string(); QTest::newRow("data2") << std::vector() << std::string("separator") << std::string(); QTest::newRow("data3") << std::vector({"one"}) << std::string("separator") << std::string("one"); QTest::newRow("data4") << std::vector({"one"}) << std::string("separator") << std::string("one"); QTest::newRow("data5") << std::vector({"a", "b"}) << std::string(" ") << std::string("a b"); QTest::newRow("data6") << std::vector({"a", "b", "c"}) << std::string(" ") << std::string("a b c"); } void TestTools::stringutils_join_empty() { std::vector list; std::string string = join(list, std::string()); QVERIFY(string.empty()); } void TestTools::stringutils_join_char() { QFETCH(std::vector, input); QFETCH(char, separator); QFETCH(std::string, expectedResult); QCOMPARE(join(input, separator), expectedResult); } void TestTools::stringutils_join_char_data() { QTest::addColumn>("input"); QTest::addColumn("separator"); QTest::addColumn("expectedResult"); QTest::newRow("data1") << std::vector() << ' ' << std::string(); QTest::newRow("data5") << std::vector({"a", "b"}) << ' ' << std::string("a b"); QTest::newRow("data6") << std::vector({"a", "b", "c"}) << ' ' << std::string("a b c"); } void TestTools::stringutils_trimmed() { std::string a; a = "Text"; QCOMPARE(a, std::string("Text")); QCOMPARE(trimmed(a), std::string("Text")); QCOMPARE(a, std::string("Text")); a = " "; QCOMPARE(trimmed(a), std::string("")); QCOMPARE(a, std::string(" ")); a = " a "; QCOMPARE(trimmed(a), std::string("a")); a = "Text"; QCOMPARE(trimmed(std::move(a)), std::string("Text")); a = " "; QCOMPARE(trimmed(std::move(a)), std::string("")); a = " a "; QCOMPARE(trimmed(std::move(a)), std::string("a")); } void TestTools::hash_tuple() { using Key = std::tuple; Key key0{0, 5}; Key key1{10, 20}; Key key2{30, 40}; std::unordered_map map; map.insert({key1, 1}); map.insert({key2, 2}); QCOMPARE(map[key0], 0); QCOMPARE(map[key1], 1); QCOMPARE(map[key2], 2); } void TestTools::hash_range() { using Key = std::vector; Key key0; Key key1{1}; Key key2{1, 2}; std::unordered_map map; map.insert({key1, 1}); map.insert({key2, 2}); QCOMPARE(map[key0], 0); QCOMPARE(map[key1], 1); QCOMPARE(map[key2], 2); } void TestTools::span() { std::vector vec; qbs::Internal::span span(vec); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const SettingsPtr s = settings(); TestTools tt(s.get()); return QTest::qExec(&tt, argc, argv); } qbs-src-3.3.1/tests/auto/tools/CMakeLists.txt0000644000175100017510000000020415232633614020511 0ustar runnerrunneradd_qbs_test(tools DEFINES "QBS_VERSION=\"${QBS_VERSION}\"" SOURCES tst_tools.cpp tst_tools.h ) qbs-src-3.3.1/tests/auto/tools/tools.qbs0000644000175100017510000000045515232633614017630 0ustar runnerrunnerimport qbs.Utilities QbsUnittest { Depends { name: "qbsversion" } testName: "tools" condition: qbsbuildconfig.enableUnitTests files: [ "tst_tools.cpp", "tst_tools.h" ] cpp.defines: base.concat(["QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version)]) } qbs-src-3.3.1/tests/auto/tools/tst_tools.h0000644000175100017510000000663515232633614020172 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include QT_BEGIN_NAMESPACE class QTemporaryDir; QT_END_NAMESPACE namespace qbs { class Settings; } class TestTools : public QObject { Q_OBJECT public: TestTools(qbs::Settings *settings); ~TestTools(); public slots: virtual void initTestCase(); private slots: void fileSaver(); void fileCaseCheck(); void testBuildConfigMerging(); void testFileInfo(); void testProcessNameByPid(); void testProfiles(); void testSettingsMigration(); void testSettingsMigration_data(); void set_operator_eq(); void set_swap(); void set_size(); void set_capacity(); void set_reserve(); void set_clear(); void set_remove(); void set_contains(); void set_containsSet(); void set_find(); void set_begin(); void set_end(); void set_insert(); void set_reverseIterators(); void set_stlIterator(); void set_stlMutableIterator(); void set_setOperations(); void set_makeSureTheComfortFunctionsCompile(); void set_initializerList(); void set_intersects(); void stringutils_join(); void stringutils_join_data(); void stringutils_join_empty(); void stringutils_join_char(); void stringutils_join_char_data(); void stringutils_trimmed(); void hash_tuple(); void hash_range(); void span(); private: QString setupSettingsDir1(); QString setupSettingsDir2(); QString setupSettingsDir3(); qbs::Settings * const m_settings; QList m_tmpDirs; const QString testDataDir; }; qbs-src-3.3.1/tests/auto/buildgraph/0000755000175100017510000000000015232633614016736 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/buildgraph/buildgraph.qbs0000644000175100017510000000031615232633614021566 0ustar runnerrunnerQbsUnittest { Depends { name: "qbsconsolelogger" } testName: "buildgraph" condition: qbsbuildconfig.enableUnitTests files: [ "tst_buildgraph.cpp", "tst_buildgraph.h" ] } qbs-src-3.3.1/tests/auto/buildgraph/CMakeLists.txt0000644000175100017510000000020415232633614021472 0ustar runnerrunneradd_qbs_test(buildgraph SOURCES tst_buildgraph.cpp tst_buildgraph.h DEPENDS qbsquickjsheaders ) qbs-src-3.3.1/tests/auto/buildgraph/tst_buildgraph.cpp0000644000175100017510000001215615232633614022462 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_buildgraph.h" #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; const TopLevelProjectPtr project = TopLevelProject::create(); TestBuildGraph::TestBuildGraph(ILogSink *logSink) : m_logSink(logSink) { project->buildData = std::make_unique(); } void TestBuildGraph::initTestCase() { } void TestBuildGraph::cleanupTestCase() { } bool TestBuildGraph::cycleDetected(const ResolvedProductConstPtr &product) { try { CycleDetector(Logger(m_logSink)).visitProduct(product); return false; } catch (const ErrorInfo &) { return true; } } ResolvedProductConstPtr TestBuildGraph::productWithDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData = std::make_unique(); const auto root = new Artifact; root->product = product; const auto child = new Artifact; child->product = product; product->buildData->addRootNode(root); product->buildData->addNode(root); product->buildData->addNode(child); qbs::Internal::connect(root, child); qbs::Internal::connect(child, root); return product; } ResolvedProductConstPtr TestBuildGraph::productWithLessDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData = std::make_unique(); const auto root = new Artifact; const auto child = new Artifact; const auto grandchild = new Artifact; root->product = product; child->product = product; grandchild->product = product; product->buildData->addRootNode(root); product->buildData->addNode(root); product->buildData->addNode(child); product->buildData->addNode(grandchild); qbs::Internal::connect(root, child); qbs::Internal::connect(child, grandchild); qbs::Internal::connect(grandchild, root); return product; } // root appears as a child, but in a different tree ResolvedProductConstPtr TestBuildGraph::productWithNoCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData = std::make_unique(); const auto root = new Artifact; const auto root2 = new Artifact; root->product = product; root2->product = product; product->buildData->addRootNode(root); product->buildData->addRootNode(root2); product->buildData->addNode(root); product->buildData->addNode(root2); qbs::Internal::connect(root2, root); return product; } void TestBuildGraph::testCycle() { QVERIFY(cycleDetected(productWithDirectCycle())); QVERIFY(cycleDetected(productWithLessDirectCycle())); QVERIFY(!cycleDetected(productWithNoCycle())); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); TestBuildGraph tbg(ConsoleLogger::instance().logSink()); return QTest::qExec(&tbg, argc, argv); } qbs-src-3.3.1/tests/auto/buildgraph/tst_buildgraph.h0000644000175100017510000000514515232633614022127 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BUILDGRAPH_H #define TST_BUILDGRAPH_H #include #include #include #include #include class TestBuildGraph : public QObject { Q_OBJECT public: TestBuildGraph(qbs::ILogSink *logSink); private slots: void initTestCase(); void cleanupTestCase(); void testCycle(); private: qbs::Internal::ResolvedProductConstPtr productWithDirectCycle(); qbs::Internal::ResolvedProductConstPtr productWithLessDirectCycle(); qbs::Internal::ResolvedProductConstPtr productWithNoCycle(); bool cycleDetected(const qbs::Internal::ResolvedProductConstPtr &product); qbs::ILogSink * const m_logSink; }; #endif // TST_BUILDGRAPH_H qbs-src-3.3.1/tests/auto/cmdlineparser/0000755000175100017510000000000015232633614017445 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/cmdlineparser/cmdlineparser.qbs0000644000175100017510000000161415232633614023006 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { Depends { name: "qbsversion" } Depends { name: "qbsconsolelogger" } testName: "cmdlineparser" files: ["tst_cmdlineparser.cpp", "../../../src/app/qbs/qbstool.cpp"] cpp.defines: base.concat([ "SRCDIR=" + Utilities.cStringQuote(path), "QBS_VERSION=" +Utilities.cStringQuote(qbsversion.version) ]) // TODO: Make parser a static library? Group { name: "parser" prefix: "../../../src/app/qbs/parser/" files: [ "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", "parsercommand.cpp", "parsercommand.h", ] } } qbs-src-3.3.1/tests/auto/cmdlineparser/CMakeLists.txt0000644000175100017510000000115715232633614022211 0ustar runnerrunnerset(PARSER_SOURCES commandlineoption.cpp commandlineoption.h commandlineoptionpool.cpp commandlineoptionpool.h commandlineparser.cpp commandlineparser.h commandpool.cpp commandpool.h commandtype.h parsercommand.cpp parsercommand.h ) list_transform_prepend(PARSER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../src/app/qbs/parser/") add_qbs_test(cmdlineparser DEFINES "QBS_VERSION=\"${QBS_VERSION}\"" INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../../../src" SOURCES tst_cmdlineparser.cpp ../../../src/app/qbs/qbstool.cpp ${PARSER_SOURCES} ) qbs-src-3.3.1/tests/auto/cmdlineparser/tst_cmdlineparser.cpp0000644000175100017510000002622315232633614023700 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../shared.h" #include #include #include #include #include #include #include #include using namespace qbs; class TestCmdLineParser : public QObject { Q_OBJECT public: TestCmdLineParser() { ConsoleLogger::instance().logSink()->setEnabled(false); } private slots: void initTestCase() { QVERIFY(m_projectFile.open()); m_fileArgs = QStringList() << "-f" << m_projectFile.fileName(); } void testResolve_data() { QTest::addColumn("args"); QTest::addColumn("expectedJobCount"); QTest::newRow("default job count") << QStringList() << BuildOptions::defaultMaxJobCount(); QTest::newRow("explicit job count") << QStringList("-j5") << 5; } void testResolve() { QFETCH(QStringList, args); QFETCH(int, expectedJobCount); CommandLineParser parser; QVERIFY(parser.parseCommandLine(QStringList("resolve") << args << m_fileArgs)); QCOMPARE(parser.command(), ResolveCommandType); QCOMPARE(parser.jobCount(profileName()), expectedJobCount); } void testValidCommandLine() { QStringList args; args.push_back("-vvk"); args.push_back("-v"); args << "--products" << "blubb"; args << "--changed-files" << "foo,bar" << m_fileArgs; args << "--check-timestamps"; args << "--check-outputs"; CommandLineParser parser; QVERIFY(parser.parseCommandLine(args)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); QCOMPARE(parser.command(), BuildCommandType); QCOMPARE(parser.products(), QStringList() << "blubb"); QCOMPARE(parser.buildOptions(QString()).changedFiles().size(), 2); QVERIFY(parser.buildOptions(QString()).keepGoing()); QVERIFY(parser.forceTimestampCheck()); QVERIFY(parser.forceOutputCheck()); QVERIFY(!parser.logTime()); QCOMPARE(parser.buildConfigurations().size(), 1); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), defaultLogLevel()); QVERIFY(parser.parseCommandLine(QStringList() << "-t" << m_fileArgs)); QVERIFY(parser.logTime()); // Note: We cannot just check for !parser.logTime() here, because if the test is not // run in a terminal, "--show-progress" is ignored, in which case "--log-time" // takes effect. QVERIFY(parser.parseCommandLine(QStringList() << "-t" << "--show-progress" << m_fileArgs)); QVERIFY(parser.showProgress() != parser.logTime()); QVERIFY(parser.parseCommandLine(QStringList() << "-vvqqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerWarning); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerDebug); QVERIFY(parser.parseCommandLine(QStringList() << "--log-level" << "trace" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); // Second "global" profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList() << "profile:a" << m_fileArgs << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); // Second build configuration-specific profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:debug" << "profile:a" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:a-debug" << "profile:a" << "config:b-debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 2); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("a-debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.configurationName").toString(), QLatin1String("b-debug")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Redundant build request QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:debug" << "profile:a" << "config:debug" << "profile:a")); QCOMPARE(parser.buildConfigurations().size(), 1); QVERIFY(parser.parseCommandLine(QStringList() << "config:debug" << "profile:a" << "config:release" << "profile:b" << m_fileArgs)); QCOMPARE(parser.buildConfigurations().size(), 2); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.configurationName").toString(), QLatin1String("release")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Non-global property takes precedence. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "profile:a" << "config:debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); // Digits are always handled as option parameters. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "-j" << "123")); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "-j123")); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); // Argument list separation for the "run" command. QVERIFY(parser.parseCommandLine(QStringList("run") << m_fileArgs << "config:custom" << "-j123")); QCOMPARE(parser.command(), RunCommandType); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("custom")); QVERIFY(parser.runArgs().empty()); QVERIFY(parser.parseCommandLine(QStringList("run") << m_fileArgs << "-j" << "123" << "--" << "config:custom")); QCOMPARE(parser.command(), RunCommandType); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("default")); QCOMPARE(parser.runArgs(), QStringList({"config:custom"})); // show-version QVERIFY(parser.parseCommandLine(QStringList("show-version"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList("--version"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList("-V"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList{"run", "--setup-run-env-config", "x,y,z"})); QCOMPARE(parser.runEnvConfig(), QStringList({"x", "y", "z"})); } void testInvalidCommandLine() { QFETCH(QStringList, commandLine); CommandLineParser parser; QVERIFY(!parser.parseCommandLine(commandLine)); } void testInvalidCommandLine_data() { QTest::addColumn("commandLine"); QTest::newRow("Unknown short option") << (QStringList() << m_fileArgs << "-x"); QTest::newRow("Unknown long option") << (QStringList() << m_fileArgs << "--xyz"); QTest::newRow("Invalid position") << (QStringList() << m_fileArgs << "-vjv"); QTest::newRow("Missing jobs argument") << (QStringList() << m_fileArgs << "-j"); QTest::newRow("Missing products argument") << (QStringList() << m_fileArgs << "--products"); QTest::newRow("Wrong argument") << (QStringList() << "-j" << "0" << m_fileArgs); QTest::newRow("Invalid list argument") << (QStringList() << "--changed-files" << "," << m_fileArgs); QTest::newRow("Invalid log level") << (QStringList() << "--log-level" << "blubb" << m_fileArgs); QTest::newRow("Unknown numeric argument") << (QStringList() << m_fileArgs << "-123"); QTest::newRow("Unknown parameter") << (QStringList() << m_fileArgs << "debug"); QTest::newRow("Too many arguments") << (QStringList("help") << "build" << "clean"); QTest::newRow("Property assignment for clean") << (QStringList("clean") << "profile:x"); QTest::newRow("Property assignment for dump-nodes-tree") << (QStringList("dump-nodes-tree") << "profile:x"); QTest::newRow("Property assignment for status") << (QStringList("status") << "profile:x"); QTest::newRow("Property assignment for update-timestamps") << (QStringList("update-timestamps") << "profile:x"); QTest::newRow("Argument for show-version") << (QStringList("show-version") << "config:debug"); } private: QTemporaryFile m_projectFile; QStringList m_fileArgs; }; QTEST_MAIN(TestCmdLineParser) #include "tst_cmdlineparser.moc" qbs-src-3.3.1/tests/auto/api/0000755000175100017510000000000015232633614015366 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/tst_api.h0000644000175100017510000001310215232633614017177 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TST_API_H #define QBS_TST_API_H #include #include #include namespace qbs { class ErrorInfo; class SetupProjectParameters; } class BuildDescriptionReceiver; class LogSink; class ProcessResultReceiver; class TaskReceiver; class TestApi : public QObject { Q_OBJECT public: TestApi(); ~TestApi() override; private slots: void initTestCase(); void init(); void addQObjectMacroToCppFile(); void addedFilePersistent(); void baseProperties(); void buildErrorCodeLocation(); void buildGraphInfo(); void buildGraphLocking(); void buildProject(); void buildProject_data(); void buildProjectDryRun(); void buildProjectDryRun_data(); void buildSingleFile(); void canonicalToolchainList(); void changeContent(); void changeDependentLib(); void checkOutputs(); void checkOutputs_data(); void commandExtraction(); void dependencyOnMultiplexedType(); void disabledInstallGroup(); void disabledProduct(); void disabledProject(); void disappearedWildcardFile(); void duplicateProductNames(); void duplicateProductNames_data(); void emptyFileTagList(); void emptySubmodulesList(); void enableAndDisableProduct(); void errorInSetupRunEnvironment(); void excludedInputs(); void explicitlyDependsOn(); void exportSimple(); void exportWithRecursiveDepends(); void fallbackGcc(); void fileTagger(); void fileTagsFilterOverride(); void generatedFilesList(); void groupVisibility(); void infiniteLoopBuilding(); void infiniteLoopBuilding_data(); void infiniteLoopResolving(); void inheritQbsSearchPaths(); void installableFiles(); void isRunnable(); void linkDynamicLibs(); void linkDynamicAndStaticLibs(); void linkDynamicAndObjectLibs(); void linkStaticAndDynamicLibs(); void linkObjectAndDynamicLibs(); void listBuildSystemFiles(); void localProfiles(); void localProfiles_data(); void missingSourceFile(); void mocCppIncluded(); void multiArch(); void multiplexing(); void newOutputArtifactInDependency(); void newPatternMatch(); void noAssertsInRelaxedMode(); void nonexistingProjectPropertyFromCommandLine(); void nonexistingProjectPropertyFromProduct(); void objC(); void projectDataAfterProductInvalidation(); void processResult(); void processResult_data(); void projectInvalidation(); void projectLocking(); void projectPropertiesByName(); void projectWithPropertiesItem(); void projectWithProbeAndProfileItem(); void propertiesBlocks(); void rc(); void referencedFileErrors(); void referencedFileErrors_data(); void references(); void relaxedModeRecovery(); void removeFileDependency(); void renameProduct(); void renameTargetArtifact(); void renamedQbsSource(); void resolveProject(); void resolveProject_data(); void resolveProjectDryRun(); void resolveProjectDryRun_data(); void restoredWarnings(); void restoreAndResolve(); void ruleConflict(); void runEnvForDisabledProduct(); void softDependency(); void sourceFileInBuildDir(); void subProjects(); void targetArtifactStatus_data(); void targetArtifactStatus(); void timeout(); void timeout_data(); void toolInModule(); void trackAddQObjectHeader(); void trackRemoveQObjectHeader(); void transformerData(); void transformers(); void typeChange(); void uic(); private: qbs::SetupProjectParameters defaultSetupParameters(const QString &projectFileOrDir) const; qbs::ErrorInfo doBuildProject(const QString &projectFilePath, BuildDescriptionReceiver *buildDescriptionReceiver = 0, ProcessResultReceiver *procResultReceiver = 0, TaskReceiver *taskReceiver = 0, const qbs::BuildOptions &options = qbs::BuildOptions(), const QVariantMap &overriddenValues = QVariantMap()); QString getProductFilePath(const QString &productNameOrFilePath); LogSink * const m_logSink; const QString m_sourceDataDir; const QString m_workingDataDir; }; #endif // Include guard. qbs-src-3.3.1/tests/auto/api/CMakeLists.txt0000644000175100017510000000044215232633614020126 0ustar runnerrunneradd_qbs_test(api DEFINES "QBS_RELATIVE_LIBEXEC_PATH=\"${QBS_RELATIVE_LIBEXEC_PATH}\"" "QBS_RELATIVE_SEARCH_PATH=\"${QBS_RELATIVE_SEARCH_PATH}\"" "QBS_RELATIVE_PLUGINS_PATH=\"${QBS_RELATIVE_PLUGINS_PATH}\"" SOURCES tst_api.cpp tst_api.h ) qbs-src-3.3.1/tests/auto/api/api.qbs0000644000175100017510000000114415232633614016646 0ustar runnerrunnerimport qbs.Utilities QbsAutotest { testName: "api" files: ["../shared.h", "tst_api.h", "tst_api.cpp"] cpp.defines: base.concat([ "SRCDIR=" + Utilities.cStringQuote(path), "QBS_RELATIVE_LIBEXEC_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeLibexecPath), "QBS_RELATIVE_SEARCH_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeSearchPath), "QBS_RELATIVE_PLUGINS_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativePluginsPath) ]) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-3.3.1/tests/auto/api/testdata/0000755000175100017510000000000015232633614017177 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/objc/0000755000175100017510000000000015232633614020114 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/objc/main.mm0000644000175100017510000000072015232633614021372 0ustar runnerrunner#import #include int main(int argc, char **argv) { // We support both C++ std::cout << "Hello from C++" << std::endl; // And Objective-C NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; NSString *productVersion = [version objectForKey:@"ProductVersion"]; NSLog(@"Hello, macOS %@!", productVersion); // So it's Objective-C++ } qbs-src-3.3.1/tests/auto/api/testdata/objc/objc.qbs0000644000175100017510000000023315232633614021536 0ustar runnerrunnerProject { CppApplication { condition: qbs.targetOS.includes("macos") files: "main.mm" cpp.frameworks: [ "Foundation" ] } } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlib-dynamiclib/0000755000175100017510000000000015232633614024221 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-staticlib-dynamiclib/mystaticlib.cpp0000644000175100017510000000015215232633614027247 0ustar runnerrunner#include "../dllexport.h" DLL_IMPORT int dynamic_foo(); int static_foo() { return dynamic_foo() * 13; } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlib-dynamiclib/link-staticlib-dynamiclib.qbs0000644000175100017510000000103315232633614031747 0ustar runnerrunnerProject { CppApplication { Depends { name: "mystaticlib" } name: "app" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: ["main.cpp"] } StaticLibrary { Depends { name: "cpp" } Depends { name: "mydynamiclib" } name: "mystaticlib" files: ["mystaticlib.cpp"] } DynamicLibrary { name: "mydynamiclib" Depends { name: "cpp" } files: ["mydynamiclib.cpp"] } } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlib-dynamiclib/mydynamiclib.cpp0000644000175100017510000000010715232633614027404 0ustar runnerrunner#include "../dllexport.h" DLL_EXPORT int dynamic_foo() { return 12; } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlib-dynamiclib/main.cpp0000644000175100017510000000010215232633614025642 0ustar runnerrunnerint static_foo(); int main() { return static_foo() - 156; } qbs-src-3.3.1/tests/auto/api/testdata/is-runnable/0000755000175100017510000000000015232633614021416 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/is-runnable/is-runnable.qbs0000644000175100017510000000034315232633614024344 0ustar runnerrunnerProject { CppApplication { name: "app" } DynamicLibrary { name: "lib" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/excluded-inputs/0000755000175100017510000000000015232633614022314 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/excluded-inputs/excluded-inputs.qbs0000644000175100017510000000720215232633614026141 0ustar runnerrunnerimport qbs.File import qbs.TextFile Project { Product { name: "dep" type: "the_tag" Rule { multiplex: true Artifact { filePath: "file1.txt" fileTags: "the_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("the_content"); f.close(); }; return cmd; } } Rule { inputs: "the_tag" excludedInputs: "the_other_tag" Artifact { filePath: "file2.txt" fileTags: "the_other_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); var f = new TextFile(output.filePath, TextFile.Append); f.writeLine("the_other_content"); f.close(); }; return cmd; } } Group { fileTagsFilter: "the_other_tag" fileTags: "the_tag" } } Product { name: "p" type: "p_type" Depends { name: "dep" } Rule { multiplex: true inputsFromDependencies: "the_tag" Artifact { filePath: "dummy1.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName;; if (!inputs["the_tag"] || inputs["the_tag"].length != 2) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { multiplex: true inputsFromDependencies: "the_tag" excludedInputs: "the_other_tag" Artifact { filePath: "dummy2.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName;; if (!inputs["the_tag"] || inputs["the_tag"].length != 1) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { multiplex: true explicitlyDependsOnFromDependencies: "the_tag" excludedInputs: "the_other_tag" Artifact { filePath: "dummy3.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; if (!explicitlyDependsOn["the_tag"] || explicitlyDependsOn["the_tag"].length != 1) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } } qbs-src-3.3.1/tests/auto/api/testdata/buildgraph-locking/0000755000175100017510000000000015232633614022744 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/buildgraph-locking/buildgraph-locking.qbs0000644000175100017510000000001415232633614027213 0ustar runnerrunnerProject { } qbs-src-3.3.1/tests/auto/api/testdata/project-with-probe-and-profile-item/0000755000175100017510000000000015232633614026055 5ustar runnerrunner././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/project-with-probe-and-profile-item/project-with-probe-and-profile-item.qbsqbs-src-3.3.1/tests/auto/api/testdata/project-with-probe-and-profile-item/project-with-probe-and-pro0000644000175100017510000000051715232633614033065 0ustar runnerrunnerProject { property bool probesEvaluated: probe.found Probe { id: probe configure: { found = true; } } Profile { name: "the-profile" cpp.includePaths: { if (!probesEvaluated) throw "project-level probes not evaluated"; } } } qbs-src-3.3.1/tests/auto/api/testdata/restored-warnings/0000755000175100017510000000000015232633614022654 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs0000644000175100017510000000071615232633614027044 0ustar runnerrunnerimport qbs.Process 1.5 Project { CppApplication { name: "theProduct" cpp.blubb: true files: ["file.cpp", "main.cpp"] } Product { name: "theOtherProduct" property bool dummy: { throw "this one comes from a thread"; } } Product { name: "aThirdProduct" property bool moreFiles: false Group { condition: moreFiles files: ["blubb.txt"] } } } qbs-src-3.3.1/tests/auto/api/testdata/restored-warnings/file.cpp0000644000175100017510000000001415232633614024272 0ustar runnerrunnervoid f() {} qbs-src-3.3.1/tests/auto/api/testdata/restored-warnings/main.cpp0000644000175100017510000000001615232633614024301 0ustar runnerrunnerint main() {} qbs-src-3.3.1/tests/auto/api/testdata/export-item-with-group/0000755000175100017510000000000015232633614023557 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-item-with-group/export-item-with-group.qbs0000644000175100017510000000055015232633614030646 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "cpp" } Group { files: ["main.cpp"] } } } Application { name: "app" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/api/testdata/export-item-with-group/main.cpp0000644000175100017510000000235215232633614025211 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/0000755000175100017510000000000015232633614025116 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/modules/0000755000175100017510000000000015232633614026566 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/0000755000175100017510000000000015232633614030134 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs0000644000175100017510000000005315232633614032207 0ustar runnerrunnerModule { Depends { name: "module2" } } qbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/0000755000175100017510000000000015232633614030135 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs0000644000175100017510000000010415232633614032206 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.defines: ["HAS_FOO"] } qbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/main2.cpp0000644000175100017510000000241615232633614026633 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { #ifndef HAS_FOO blubb(); #endif } qbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/main1.cpp0000644000175100017510000000235115232633614026630 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/export-with-recursive-depends.qbsqbs-src-3.3.1/tests/auto/api/testdata/export-with-recursive-depends/export-with-recursive-depends.qb0000644000175100017510000000036315232633614033363 0ustar runnerrunnerProject { CppApplication { name: "app1" files: "main1.cpp" Export { Depends { name: "module1" } } } CppApplication { name: "app2" Depends { name: "app1" } files: "main2.cpp" } } qbs-src-3.3.1/tests/auto/api/testdata/export-simple/0000755000175100017510000000000015232633614022007 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/export-simple/main.cpp0000644000175100017510000000257015232633614023443 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT int lib1_hello(); int main() { std::puts("application says hello!"); return lib1_hello(); } qbs-src-3.3.1/tests/auto/api/testdata/export-simple/lib1.cpp0000644000175100017510000000253115232633614023343 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT int lib1_hello() { std::puts("lib1 says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/export-simple/export-simple.qbs0000644000175100017510000000172715232633614025335 0ustar runnerrunnerProject { Application { name : "HelloWorld" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: 'dummy' } } Product { name: 'dummy' Group { files: 'main.cpp' qbs.install: true } Export { Depends { name: 'dummy2' } Properties { // QBS-550 condition: false qbs.optimization: "ludicrous speed" } } } Product { name: 'dummy2' Group { files: 'lib1.cpp' qbs.install: true } Export { Depends { name: 'lib1' } } } DynamicLibrary { name : "lib1" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/project-with-properties-item/0000755000175100017510000000000015232633614024744 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs0000644000175100017510000000034615232633614033223 0ustar runnerrunnerProject { property string binPath: "/usr/bin" property string libPath: "/usr/lib" Properties { condition: qbs.targetOS.includes("macos") binPath: "/Users/boo" libPath: "/Libraries/foo" } } qbs-src-3.3.1/tests/auto/api/testdata/restore-and-resolve/0000755000175100017510000000000015232633614023077 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/restore-and-resolve/broken-product.qbs0000644000175100017510000000067015232633614026547 0ustar runnerrunnerimport qbs.TextFile syntax error Product { type: "t" Rule { multiplex: true Artifact { filePath: "dummy.txt"; fileTags: "t" } prepare: { var cmd = JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { new TextFile(output.filePath, TextFile.WriteOnly); }; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/restore-and-resolve/restore-and-resolve.qbs0000644000175100017510000000006115232633614027503 0ustar runnerrunnerProject { references: "broken-product.qbs" } qbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/0000755000175100017510000000000015232633614024004 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/imports/0000755000175100017510000000000015232633614025501 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/imports/Foo.qbs0000644000175100017510000000013615232633614026733 0ustar runnerrunnerProduct { type: "application" consoleApplication: true Depends { name: 'bli' } } qbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/0000755000175100017510000000000015232633614025356 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/0000755000175100017510000000000015232633614027026 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/0000755000175100017510000000000015232633614027564 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/m.qbs0000644000175100017510000000010615232633614030524 0ustar runnerrunnerModule { Depends {name : "cpp" } cpp.defines: ["HAVE_BLA"] } qbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/main.cpp0000644000175100017510000000245315232633614025440 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HAVE_BLI #error HAVE_BLI missing! #endif int main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/prj.qbs0000644000175100017510000000026715232633614025313 0ustar runnerrunnerimport "imports/Foo.qbs" as Foo Project { qbsSearchPaths: "subdir" Project { qbsSearchPaths: "subdir2" Foo { files: "main.cpp" } } } qbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/0000755000175100017510000000000015232633614025274 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/0000755000175100017510000000000015232633614026744 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/0000755000175100017510000000000015232633614027512 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/m.qbs0000644000175100017510000000010615232633614030452 0ustar runnerrunnerModule { Depends {name : "cpp" } cpp.defines: ["HAVE_BLI"] } qbs-src-3.3.1/tests/auto/api/testdata/missing-qobject-header/0000755000175100017510000000000015232633614023523 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/missing-qobject-header/main.cpp0000644000175100017510000000243015232633614025152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" int main() { MyObject().func(); } qbs-src-3.3.1/tests/auto/api/testdata/missing-qobject-header/myobject.h0000644000175100017510000000247415232633614025517 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: void func(); }; qbs-src-3.3.1/tests/auto/api/testdata/missing-qobject-header/myobject.cpp0000644000175100017510000000241415232633614026044 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" void MyObject::func() { } qbs-src-3.3.1/tests/auto/api/testdata/multiplexing/0000755000175100017510000000000015232633614021720 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/multiplexing/multiplexing.qbs0000644000175100017510000000645115232633614025156 0ustar runnerrunnerimport qbs.TextFile Project { Project { name: "subproject 1" Product { name: "multiplex-using-export" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Depends { name: "multiplex-with-export" } } Product { name: "multiplex-without-aggregator-2-depend-on-non-multiplexed" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Depends { name: "no-multiplexing" } } Product { name: "multiplex-with-aggregator-2" aggregate: true multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] qbs.architecture: "Atari ST" } Product { name: "multiplex-with-aggregator-2-dependent" Depends { name: "multiplex-with-aggregator-2" } } Product { name: "non-multiplexed-with-dependencies-on-multiplexed" Depends { name: "multiplex-without-aggregator-2" } } Product { name: "non-multiplexed-with-dependencies-on-multiplexed-via-export1" Depends { name: "multiplex-with-export" } } Product { name: "non-multiplexed-with-dependencies-on-multiplexed-via-export2" Depends { name: "nonmultiplex-with-export" } } Product { name: "non-multiplexed-with-dependencies-on-aggregation-via-export" Depends { name: "nonmultiplex-exporting-aggregation" } } } Project { name: "subproject 2" Product { name: "no-multiplexing" } Product { name: "multiplex-without-aggregator-2" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] } Product { name: "multiplex-with-export" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Export { Depends { name: "multiplex-without-aggregator-2" } } } Product { name: "nonmultiplex-with-export" Export { Depends { name: "multiplex-without-aggregator-2" } } } Product { name: "nonmultiplex-exporting-aggregation" Export { Depends { name: "multiplex-with-aggregator-2" } } } Product { name: "multiplex-without-aggregator-4" multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["TRS-80", "C64"] qbs.buildVariants: ["debug", "release"] } Product { name: "multiplex-without-aggregator-4-depends-2" multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["TRS-80", "C64"] qbs.buildVariants: ["debug", "release"] Depends { name: "multiplex-without-aggregator-2" } } } Product { name: "aggregate-with-dependencies-on-aggregation-via-export" Depends { name: "nonmultiplex-exporting-aggregation" } aggregate: true multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] qbs.architecture: "Atari ST" } } qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/0000755000175100017510000000000015232633614023517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/stable.h0000644000175100017510000000253615232633614025150 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /* Add C includes here */ #if defined __cplusplus /* Add C++ includes here */ # include # include #endif qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/precompiled-header-new.qbs0000644000175100017510000000050515232633614030546 0ustar runnerrunnerCppApplication { name: "MyApp" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Group { name: "precompiled headers" files: ["stable.h"] fileTags: ["cpp_pch_src"] } files: ["myobject.h", "main.cpp", "myobject.cpp"] } qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/main.cpp0000644000175100017510000000334215232633614025151 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" #include #include #include using namespace std; int main() { MyObject obj; list lst; lst.push_back(1); lst.push_back(2); lst.push_back(3); lst.push_back(4); lst.push_back(5); lst.push_back(6); lst.push_back(7); lst.push_back(8); lst.push_back(9); reverse(lst.begin(), lst.end()); for (list::iterator it=lst.begin(); it != lst.end(); ++it) cout << *it << ", "; cout << endl; return 0; } qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/myobject.h0000644000175100017510000000251015232633614025502 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MYOBJECT_H #define MYOBJECT_H class MyObject { public: MyObject(); ~MyObject(); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-new/myobject.cpp0000644000175100017510000000263515232633614026045 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "myobject.h" MyObject::MyObject() { std::cout << "MyObject::MyObject()\n"; } MyObject::~MyObject() { std::cout << "MyObject::~MyObject()" << std::endl; } qbs-src-3.3.1/tests/auto/api/testdata/rename-product/0000755000175100017510000000000015232633614022124 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rename-product/lib.cpp0000644000175100017510000000241515232633614023400 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" MY_EXPORT void f() { } qbs-src-3.3.1/tests/auto/api/testdata/rename-product/main.cpp0000644000175100017510000000237615232633614023564 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-3.3.1/tests/auto/api/testdata/rename-product/rename.qbs0000644000175100017510000000062715232633614024107 0ustar runnerrunnerProject { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" files: "main.cpp" } DynamicLibrary { name: "TheLib" Depends { name: "cpp" } cpp.defines: "MY_EXPORT=DLL_EXPORT" files: "lib.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/enable-and-disable-product/0000755000175100017510000000000015232633614024244 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/enable-and-disable-product/enable-and-disable-product.qbs0000644000175100017510000000027515232633614032024 0ustar runnerrunnerCppApplication { property string prop: undefined // Influences source artifact properties and the product condition condition: prop cpp.visibility: prop files: "main.cpp" } qbs-src-3.3.1/tests/auto/api/testdata/enable-and-disable-product/main.cpp0000644000175100017510000000235115232633614025675 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/local-profiles/0000755000175100017510000000000015232633614022112 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/local-profiles/local-profiles.qbs0000644000175100017510000000236715232633614025544 0ustar runnerrunnerProject { property string windowsProfile: "windowsProfile" property bool enableProfiles property string mingwToolchain: "mingw" property string mingwProfile: "mingwProfile" Profile { name: windowsProfile qbs.targetPlatform: "windows" } Profile { name: project.mingwProfile condition: enableProfiles baseProfile: project.windowsProfile qbs.toolchainType: project.mingwToolchain } Application { name: "app" Depends { name: "cpp"; required: false } aggregate: false multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] qbs.profile: project.mingwProfile } Library { type: "dynamiclibrary" name: "lib" Depends { name: "cpp"; required: false } property string clangToolchain: "clang" property string clangProfileName: "clangProfile" Profile { name: product.clangProfileName condition: project.enableProfiles qbs.targetPlatform: "linux" qbs.toolchainType: product.clangToolchain } multiplexByQbsProperties: ["profiles"] qbs.profiles: [project.mingwProfile, "clangProfile"] } } qbs-src-3.3.1/tests/auto/api/testdata/run-disabled-product/0000755000175100017510000000000015232633614023226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/run-disabled-product/run-disabled-product.qbs0000644000175100017510000000007015232633614027761 0ustar runnerrunnerCppApplication { name: "app" condition: false } qbs-src-3.3.1/tests/auto/api/testdata/build-single-file/0000755000175100017510000000000015232633614022472 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/build-single-file/compiled.cpp0000644000175100017510000000243115232633614024772 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void f() { std::cout << "test"; } qbs-src-3.3.1/tests/auto/api/testdata/build-single-file/pch.h0000644000175100017510000000002415232633614023411 0ustar runnerrunner#include qbs-src-3.3.1/tests/auto/api/testdata/build-single-file/ignored2.cpp0000644000175100017510000000000015232633614024675 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/build-single-file/ignored1.cpp0000644000175100017510000000000015232633614024674 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/build-single-file/build-single-file.qbs0000644000175100017510000000136315232633614026477 0ustar runnerrunnerimport qbs.TextFile CppApplication { consoleApplication: true files: ["ignored1.cpp", "ignored2.cpp", "compiled.cpp"] cpp.includePaths: [buildDirectory] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } install: true installDir: "" Rule { multiplex: true Artifact { filePath: "generated.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var header = new TextFile(output.filePath, TextFile.WriteOnly); header.close(); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/api/testdata/disabled-product/0000755000175100017510000000000015232633614022424 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/disabled-product/disabled-product.qbs0000644000175100017510000000023515232633614026360 0ustar runnerrunnerCppApplication { condition: false files: "main.cpp" Group { condition: qbs.targetOS.includes("stuff") qbs.install: false } } qbs-src-3.3.1/tests/auto/api/testdata/disabled-product/main.cpp0000644000175100017510000000002315232633614024047 0ustar runnerrunnerthiswillnotcompile qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-js/0000755000175100017510000000000015232633614022365 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-js/infinite-loop.qbs0000644000175100017510000000065515232633614025656 0ustar runnerrunnerProduct { type: "mytype" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "mytype" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "running infinite loop"; cmd.sourceCode = function() { while (true) ; } return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/0000755000175100017510000000000015232633614024570 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.cpp0000644000175100017510000000256715232633614026554 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" #include // class InternalClass : public QObject // { // Q_OBJECT // }; void Object::f() { } // #include "object.moc" qbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.h0000644000175100017510000000240315232633614026206 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ class Object { public: void f(); }; qbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/main.cpp0000644000175100017510000000243015232633614026217 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" int main() { Object o; o.f(); } ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/add-qobject-macro-to-cpp-file.qbsqbs-src-3.3.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/add-qobject-macro-to-cpp-file.qb0000644000175100017510000000010515232633614032501 0ustar runnerrunnerQtApplication { files: ["main.cpp", "object.h", "object.cpp"] } qbs-src-3.3.1/tests/auto/api/testdata/project-invalidation/0000755000175100017510000000000015232633614023324 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-invalidation/project.late-error.qbs0000644000175100017510000000027215232633614027555 0ustar runnerrunnerProduct { type: "mytype" Rule { inputs: ["mytype"] Artifact { filePath: "blubb" fileTags: "mytype" } prepare: [] } } qbs-src-3.3.1/tests/auto/api/testdata/project-invalidation/project.early-error.qbs0000644000175100017510000000007315232633614027743 0ustar runnerrunnerProduct { type: "mytype" files: "nosuchfile.txt" } qbs-src-3.3.1/tests/auto/api/testdata/project-invalidation/project.no-error.qbs0000644000175100017510000000003715232633614027243 0ustar runnerrunnerProduct { type: "mytype" } qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/0000755000175100017510000000000015232633614021531 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/object.narf.h0000644000175100017510000000260115232633614024074 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class ObjectNarf : public QObject { Q_OBJECT public: ObjectNarf(QObject *parent = nullptr); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/object.narf.cpp0000644000175100017510000000251115232633614024427 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.narf.h" #include ObjectNarf::ObjectNarf(QObject *parent) : QObject(parent) {} qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/m.a.i.n.cpp0000644000175100017510000000253615232633614023401 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.narf.h" #include #include int main() { ObjectNarf obj; std::puts("..."); } qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/lots-of-dots.qbs0000644000175100017510000000067015232633614024575 0ustar runnerrunnerProject { QtGuiApplication { type: "application" consoleApplication: true name: "lots.of.dots" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } cpp.cxxLanguageVersion: "c++11" files : [ "m.a.i.n.cpp", "object.narf.h", "object.narf.cpp", "polka.dots.qrc", "dotty.matrix.ui" ] } } qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/dotty.matrix.ui0000644000175100017510000000065415232633614024543 0ustar runnerrunner Form 0 0 400 300 Form qbs-src-3.3.1/tests/auto/api/testdata/lots-of-dots/polka.dots.qrc0000644000175100017510000000014415232633614024315 0ustar runnerrunner m.a.i.n.cpp qbs-src-3.3.1/tests/auto/api/testdata/timeout-process/0000755000175100017510000000000015232633614022341 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/timeout-process/main.cpp0000644000175100017510000000255715232633614024002 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { std::this_thread::sleep_for(std::chrono::seconds(700)); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/timeout-process/timeout.qbs0000644000175100017510000000310015232633614024530 0ustar runnerrunnerimport qbs.Host Project { CppApplication { type: "application" consoleApplication: true // suppress bundle generation files: "main.cpp" name: "infinite-loop" cpp.cxxLanguageVersion: "c++11" cpp.minimumOsxVersion: "10.8" // For Properties { condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } } Product { condition: { const result = qbs.targetPlatform === Host.platform() && (qbs.architecture === undefined || qbs.architecture === Host.architecture()); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } type: "product-under-test" name: "caller" Depends { name: "infinite-loop" } Depends { name: "cpp" // Make sure build environment is set up properly. condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } Rule { inputsFromDependencies: "application" outputFileTags: "product-under-test" prepare: { var cmd = new Command(inputs["application"][0].filePath); cmd.description = "calling application that runs forever"; cmd.timeout = 3; return cmd; } } } } qbs-src-3.3.1/tests/auto/api/testdata/file-tagger/0000755000175100017510000000000015232633614021365 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/file-tagger/bla.txt0000644000175100017510000000021315232633614022660 0ustar runnerrunner#include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-3.3.1/tests/auto/api/testdata/file-tagger/moc_cpp.qbs0000644000175100017510000000203015232633614023507 0ustar runnerrunnerimport qbs.TextFile import qbs.FileInfo Project { Product { type: "application" consoleApplication: true name: "moc_cpp" Depends { name: "Qt.core" } Group { files: 'bla.txt' fileTags: ['text'] } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function () { var file = new TextFile(input.filePath, TextFile.ReadOnly); var text = file.readAll(); file.close(); file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(text); file.close(); } cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/0000755000175100017510000000000015232633614022043 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-within-project/0000755000175100017510000000000015232633614025603 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-within-project/tool-input.txt0000644000175100017510000000000015232633614030444 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-within-project/main.cpp0000644000175100017510000000026715232633614027240 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { assert(argc == 2); std::ofstream file(argv[1]); assert(file.is_open()); file << "content"; } qbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs0000644000175100017510000000307115232633614032053 0ustar runnerrunnerimport qbs.Host Project { CppApplication { name: "thetool" consoleApplication: true files: "main.cpp" property bool dummy: { const result = qbs.targetPlatform === Host.platform() && (qbs.architecture === undefined || qbs.architecture === Host.architecture()); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } install: true installDir: "" qbs.installPrefix: "" Group { fileTagsFilter: ["application"] fileTags: ["thetool.thetool"] } Export { Depends { name: "cpp" } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["thetool.thetool"] Artifact { filePath: "tool-output.txt" fileTags: ["thetool.output"] } prepare: { var cmd = new Command(explicitlyDependsOn["thetool.thetool"][0].filePath, output.filePath); cmd.description = "running the tool"; return [cmd]; } } } } Product { name: "user-in-project" type: ["thetool.output"] Depends { name: "thetool" } } } qbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-outside-project/0000755000175100017510000000000015232633614025755 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-outside-project/use-outside-project.qbs0000644000175100017510000000015215232633614032374 0ustar runnerrunnerProduct { name: "user-outside-project" type: ["thetool.output"] Depends { name: "thetool" } } qbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/0000755000175100017510000000000015232633614027425 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/0000755000175100017510000000000015232633614031103 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/thetool.qbs0000644000175100017510000000144415232633614033273 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host Module { Depends { name: "cpp" } Group { name: "thetool binary" files: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..", "thetool" + (Host.os().includes("windows") ? ".exe" : ""))); fileTags: ["thetool.thetool"] filesAreTargets: true } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["thetool.thetool"] Artifact { filePath: "tool-output.txt" fileTags: ["thetool.output"] } prepare: { var cmd = new Command(explicitlyDependsOn["thetool.thetool"][0].filePath, output.filePath); cmd.description = "running the tool"; return [cmd]; } } } qbs-src-3.3.1/tests/auto/api/testdata/project-locking/0000755000175100017510000000000015232633614022271 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-locking/project-locking.qbs0000644000175100017510000000001415232633614026065 0ustar runnerrunnerProject { } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/0000755000175100017510000000000015232633614022165 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/mystaticlibhelper.cpp0000644000175100017510000000240615232633614026417 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int helper_function() { return 156; } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper1/0000755000175100017510000000000015232633614023525 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper1/helper1.h0000644000175100017510000000244415232633614025242 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER1_H #define HELPER1_H extern int getSomeNumber(); #endif qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper1/helper1.cpp0000644000175100017510000000247615232633614025602 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "helper1.h" #include int getSomeNumber() { return 12 * getOddNumber(); } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/mystaticlib.cpp0000644000175100017510000000257115232633614025222 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); std::printf("Hello World! The magic number is %d.", n); return n; } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/link-static-lib.qbs0000644000175100017510000000220315232633614025657 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "HelloWorld" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "mystaticlib" } } StaticLibrary { name : "mystaticlib" files : [ "mystaticlib.cpp" ] Depends { name: "cpp" } Depends { name: "helper1" } } StaticLibrary { name : "helper1" files : [ "helper1/helper1.h", "helper1/helper1.cpp" ] Depends { name: "cpp" } Depends { name: "helper2" } Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory + '/helper1'] } } StaticLibrary { name : "helper2" files : [ "helper2/helper2.h", "helper2/helper2.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory + '/helper2'] } } } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper2/0000755000175100017510000000000015232633614023526 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper2/helper2.cpp0000644000175100017510000000242715232633614025600 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "helper2.h" int getOddNumber() { return 13; } qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/helper2/helper2.h0000644000175100017510000000244315232633614025243 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER2_H #define HELPER2_H extern int getOddNumber(); #endif qbs-src-3.3.1/tests/auto/api/testdata/link-static-lib/main.cpp0000644000175100017510000000243415232633614023620 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int bla(); int main() { return bla(); } qbs-src-3.3.1/tests/auto/api/testdata/command-extraction/0000755000175100017510000000000015232633614022773 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/command-extraction/command-extraction.qbs0000644000175100017510000000005115232633614027272 0ustar runnerrunnerCppApplication { files: "main.cpp" } qbs-src-3.3.1/tests/auto/api/testdata/command-extraction/main.cpp0000644000175100017510000000235115232633614024424 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/0000755000175100017510000000000015232633614023206 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/generated-files-list.qbs0000644000175100017510000000131315232633614027722 0ustar runnerrunnerimport qbs.Utilities CppApplication { Depends { name: "Qt.widgets" } consoleApplication: true property bool dummy: { var isEmScripten = qbs.toolchain.includes("emscripten"); console.info("is emscripten: " + isEmScripten); if (isEmScripten) { console.info("generates worker.js: " + (Utilities.versionCompare(cpp.compilerVersion, "3.1.68") < 0)) } } cpp.cxxLanguageVersion: "c++11" cpp.debugInformation: false cpp.separateDebugInformation: false files: [ "main.cpp", "mainwindow.cpp", "mainwindow.h", "mainwindow.ui" ] Depends { name: "bundle" } bundle.isBundle: false } qbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/main.cpp0000644000175100017510000000260715232633614024643 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } qbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/mainwindow.cpp0000644000175100017510000000266615232633614026100 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } qbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/mainwindow.ui0000644000175100017510000000116615232633614025725 0ustar runnerrunner MainWindow 0 0 400 300 MainWindow qbs-src-3.3.1/tests/auto/api/testdata/generated-files-list/mainwindow.h0000644000175100017510000000305015232633614025531 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H qbs-src-3.3.1/tests/auto/api/testdata/relaxed-mode-recovery/0000755000175100017510000000000015232633614023401 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/relaxed-mode-recovery/relaxed-mode-recovery.qbs0000644000175100017510000000031115232633614030305 0ustar runnerrunnerProject { Product { name: "dep" Export { Depends { name: "blubb" } } } Product { name: "p1"; Depends { name: "dep" } } Product { name: "p2"; Depends { name: "dep" } } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-resolving/0000755000175100017510000000000015232633614023761 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-resolving/infinite-loop-resolving.qbs0000644000175100017510000000007015232633614031247 0ustar runnerrunnerProduct { type: { while (true); return "Haha!"; } } qbs-src-3.3.1/tests/auto/api/testdata/fallback-gcc/0000755000175100017510000000000015232633614021470 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/fallback-gcc/fallback-gcc.qbs0000644000175100017510000000106315232633614024470 0ustar runnerrunnerCppApplication { name: "app" cpp._skipAllChecks: true Profile { name: "unixProfile" qbs.targetOS: ["unix"] qbs.toolchain: ["gcc"] // qbs.targetPlatform: "unix" // qbs.toolchainType: "gcc" } Profile { name: "gccProfile" qbs.targetOS: [] qbs.toolchain: ["gcc"] // qbs.targetPlatform: undefined // qbs.toolchainType: "gcc" } multiplexByQbsProperties: ["profiles"] qbs.profiles: ["unixProfile", "gccProfile"] } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/0000755000175100017510000000000015232633614021752 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/same-base-name/lib.c0000644000175100017510000000247315232633614022672 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern void printHelloC() { printf("Hello from C in " __FILE__ "\n"); } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/main.c0000644000175100017510000000276615232633614023055 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ extern void printHelloC(); extern void printHelloCpp(); #ifdef __APPLE__ extern void printHelloObjc(); extern void printHelloObjcpp(); #endif int main() { printHelloC(); printHelloCpp(); #ifdef __APPLE__ printHelloObjc(); printHelloObjcpp(); #endif return 0; } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/lib.cpp0000644000175100017510000000252415232633614023227 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern "C" void printHelloCpp() { std::cout << "Hello from C++ in " << __FILE__ << std::endl; } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/same-base-name.qbs0000644000175100017510000000136515232633614025241 0ustar runnerrunnerProject { CppApplication { type: "application" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "basenamelib" } name: "basename" files: "main.c" } StaticLibrary { Depends { name: "cpp" } name: "basenamelib" files: [ "lib.c", "lib.cpp" ] Group { condition: qbs.targetOS.includes("darwin") files: [ "lib.m", "lib.mm" ] } Export { Depends { name: "cpp" } cpp.frameworks: qbs.targetOS.includes("darwin") ? "Foundation" : undefined } } } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/lib.m0000644000175100017510000000016715232633614022702 0ustar runnerrunner#import extern void printHelloObjc() { NSLog(@"Hello from Objective-C in " __FILE__); } qbs-src-3.3.1/tests/auto/api/testdata/same-base-name/lib.mm0000644000175100017510000000027215232633614023054 0ustar runnerrunner#include #import extern "C" void printHelloObjcpp() { NSLog(@"Hello from Objective-C++..."); std::cout << "...in " __FILE__ << std::endl; } qbs-src-3.3.1/tests/auto/api/testdata/moc-cpp/0000755000175100017510000000000015232633614020535 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/moc-cpp/moc-cpp.qbs0000644000175100017510000000044715232633614022607 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "moc_cpp" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "Qt.core" } files: ["bla.cpp"] } } qbs-src-3.3.1/tests/auto/api/testdata/moc-cpp/bla.cpp0000644000175100017510000000254615232633614022006 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-3.3.1/tests/auto/api/testdata/installed-artifact/0000755000175100017510000000000015232633614022751 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/installed-artifact/main.cpp0000644000175100017510000000235115232633614024402 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs0000644000175100017510000000131015232633614027225 0ustar runnerrunner Project { CppApplication { name: "other app" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: ["main.cpp"] } CppApplication { name: "installedApp" type: "application" consoleApplication: true Depends { name: "other app" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" install: true installDebugInformation: false installDir: "bin" Group { fileTagsFilter: "obj" qbs.install: true qbs.installDir: "objects" } } } qbs-src-3.3.1/tests/auto/api/testdata/QBS-728/0000755000175100017510000000000015232633614020142 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/QBS-728/QBS-728.qbs0000644000175100017510000000026215232633614021614 0ustar runnerrunnerProduct { property bool isBlubbOS: qbs.targetOS.includes("blubb-OS") qbs.profiles: isBlubbOS ? ["blubb-profile"] : [project.profile] qbs.architecture: "blubb-arch" } qbs-src-3.3.1/tests/auto/api/testdata/codegen/0000755000175100017510000000000015232633614020603 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/codegen/codegen.qbs0000644000175100017510000000537415232633614022727 0ustar runnerrunnerimport qbs.FileInfo Project { property string name: 'codegen' property string osSpecificName: name.toUpperCase() + '_' + qbs.targetPlatform.toUpperCase() Product { type: 'application' consoleApplication: true name: project.name property var replacements: ({ NUMBERTYPE: "int", STRINGTYPE: "char **", FUNCTIONNAME: "main" }) property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Group { files: 'foo.txt' fileTags: ['text'] } Depends { name: 'cpp' } Depends { name: 'Qt.core' } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { function expandMacros(str, table) { var rex = /\$\w+/; var m = rex.exec(str); while (m != null) { str = str.substr(0, m.index) + table[m[0].substr(1)] + str.substr(m.index + m[0].length); m = rex.exec(str); } return str; } // check whether multipart module name translation is working var actual = product.moduleProperty("Qt.core", "mocName"); if (!actual || !actual.includes("moc")) throw "multipart module name translation is broken"; // check whether we can access project properties here var expected = "CODEGEN_" + product.moduleProperty("qbs", "targetPlatform").toUpperCase(); if (project.osSpecificName !== expected) throw "Wrong project property value: " + project.osSpecificName + "\nexpected: " + expected; var code = '$NUMBERTYPE $FUNCTIONNAME($NUMBERTYPE, $STRINGTYPE) { return 0; }'; code = expandMacros(code, product.replacements); var args = ['echo ' + code + '>' + output.filePath] var cmd if (product.moduleProperty("qbs", "hostOS").includes('windows')) { cmd = new Command(product.qbs.windowsShellPath, ['/C'].concat(args)); } else { args[0] = args[0].replace(/\(/g, '\\(') args[0] = args[0].replace(/\)/g, '\\)') args[0] = args[0].replace(/;/g, '\\;') cmd = new Command(product.qbs.shellPath, ['-c'].concat(args)) } cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/codegen/foo.txt0000644000175100017510000000001415232633614022122 0ustar runnerrunnerHello World qbs-src-3.3.1/tests/auto/api/testdata/uic/0000755000175100017510000000000015232633614017757 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/uic/ui.ui0000644000175100017510000000126415232633614020736 0ustar runnerrunner MainWindow 0 0 800 600 MainWindow 0 0 800 25 qbs-src-3.3.1/tests/auto/api/testdata/uic/bla.h0000644000175100017510000000235315232633614020671 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "ui.h" qbs-src-3.3.1/tests/auto/api/testdata/uic/ui.h0000644000175100017510000000235615232633614020553 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "ui_ui.h" qbs-src-3.3.1/tests/auto/api/testdata/uic/bla.cpp0000644000175100017510000000246615232633614021231 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "bla.h" int main() { Ui::MainWindow mainWindow; Q_UNUSED(mainWindow); } qbs-src-3.3.1/tests/auto/api/testdata/uic/uic.qbs0000644000175100017510000000035115232633614021245 0ustar runnerrunnerProject { QtGuiApplication { type: "application" consoleApplication: true name: "ui" files: [ "bla.cpp", "bla.h", "ui.ui", "ui.h" ] } } qbs-src-3.3.1/tests/auto/api/testdata/project-editing/0000755000175100017510000000000015232633614022266 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/file.h0000644000175100017510000000233215232633614023356 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/api/testdata/project-editing/project-editing.qbs0000644000175100017510000000137015232633614026065 0ustar runnerrunnerCppApplication { Group { name: "Existing Group 1" files: ["existingfile1.txt"] } property string aFile: "existingfile2.txt" Group { name: "Existing Group 2" files: product.aFile } Group { name: "Existing Group 3" files: { var file = "existingfile3.txt"; return file; } } Group { name: "Existing Group 4" prefix: "subdir/" files: [] } Group { name: "Existing Group 5" prefix: "blubb" files: [] } Group { name: "Group with wildcards" files: "*.klaus" } Group { name: "Other group with wildcards" files: "*.wildcard" } files: "main.cpp" } qbs-src-3.3.1/tests/auto/api/testdata/project-editing/newfile2.txt0000644000175100017510000000000015232633614024530 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/test.wildcard0000644000175100017510000000000015232633614024746 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/existingfile3.txt0000644000175100017510000000000015232633614025572 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/file.cpp0000644000175100017510000000233215232633614023711 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/api/testdata/project-editing/existingfile2.txt0000644000175100017510000000000015232633614025571 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/newfile3.txt0000644000175100017510000000000015232633614024531 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/main.cpp0000644000175100017510000000233215232633614023716 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/api/testdata/project-editing/existingfile1.txt0000644000175100017510000000000015232633614025570 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/project-with-no-files.qbs0000644000175100017510000000007715232633614027132 0ustar runnerrunnerCppApplication { Group { files: "file.cpp" } } qbs-src-3.3.1/tests/auto/api/testdata/project-editing/subdir/0000755000175100017510000000000015232633614023556 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/subdir/file.txt0000644000175100017510000000000015232633614025224 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/newfile1.txt0000644000175100017510000000000015232633614024527 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-editing/newfile4.txt0000644000175100017510000000000015232633614024532 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/properties-blocks/0000755000175100017510000000000015232633614022646 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs0000644000175100017510000000100515232633614027020 0ustar runnerrunnerProduct { Depends { name: 'cpp' } Properties { type: 'application' consoleApplication: true name: 'HelloWorld' } Properties { condition: name == 'HelloWorld' cpp.defines: ['DEFINE_IN_PROPERTIES'] } Properties { condition: qbs.targetOS.includes("weird") cpp.staticLibraries: "abc" } Group { cpp.defines: outer.concat(['HAVE_MAIN_CPP', cpp.debugInformation ? '_DEBUG' : '_RELEASE']) files: ['main.cpp'] } } qbs-src-3.3.1/tests/auto/api/testdata/properties-blocks/main.cpp0000644000175100017510000000301715232633614024277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef DEFINE_IN_PROPERTIES # error missing define DEFINE_IN_PROPERTIES #endif int main() { #ifdef _DEBUG std::puts("Hello World! (debug version)"); #else std::puts("Hello World! (release version)"); #endif } qbs-src-3.3.1/tests/auto/api/testdata/project-properties-by-name/0000755000175100017510000000000015232633614024365 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-properties-by-name/project-properties-by-name.qbs0000644000175100017510000000071015232633614032260 0ustar runnerrunnerProject { name: "toplevel" property stringList theDefines: [] Project { name: "subproject1" CppApplication { name: "subproduct1" files: ["main1.cpp"] cpp.defines: project.theDefines } } Project { name: "subproject2" CppApplication { name: "subproduct2" files: ["main2.cpp"] cpp.defines: project.theDefines } } } qbs-src-3.3.1/tests/auto/api/testdata/project-properties-by-name/main2.cpp0000644000175100017510000000250515232633614026101 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SUB2 #error "Missing define" #endif #ifdef SUB1 #error "Extraneous define" #endif int main() { } qbs-src-3.3.1/tests/auto/api/testdata/project-properties-by-name/main1.cpp0000644000175100017510000000250515232633614026100 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SUB1 #error "Missing define" #endif #ifdef SUB2 #error "Extraneous define" #endif int main() { } qbs-src-3.3.1/tests/auto/api/testdata/new-output-artifact-in-dependency/0000755000175100017510000000000015232633614025641 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/new-output-artifact-in-dependency/lib.cpp0000644000175100017510000000241515232633614027115 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-dependency.qbsqbs-src-3.3.1/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-depen0000644000175100017510000000056115232633614033205 0ustar runnerrunnerProject { Library { type: "dynamiclibrary" //Depends { name: "cpp" } name: "lib" files: "lib.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } CppApplication { name: "app" files: "main.cpp" Depends { name: "lib" } } } qbs-src-3.3.1/tests/auto/api/testdata/new-output-artifact-in-dependency/main.cpp0000644000175100017510000000240215232633614027267 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ //void f(); int main() { // f(); } qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-dynamic/0000755000175100017510000000000015232633614024352 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-dynamic/precompiled-header-dynamic.qbs0000644000175100017510000000142515232633614032236 0ustar runnerrunnerimport qbs.File CppApplication { name: "MyApp" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } cpp.includePaths: [product.buildDirectory] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } Group { files: ["autogen.h.in"] fileTags: ["hpp.in"] } files: ["main.cpp"] Rule { inputs: ["hpp.in"] Artifact { filePath: "autogen.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-dynamic/autogen.h.in0000644000175100017510000000012715232633614026572 0ustar runnerrunner#ifndef AUTOGEN_IN_H #define AUTOGEN_IN_H inline void f() { } #endif // AUTOGEN_IN_H qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-dynamic/pch.h0000644000175100017510000000236015232633614025276 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "autogen.h" qbs-src-3.3.1/tests/auto/api/testdata/precompiled-header-dynamic/main.cpp0000644000175100017510000000236315232633614026006 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { f(); } qbs-src-3.3.1/tests/auto/api/testdata/app-without-sources/0000755000175100017510000000000015232633614023141 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/app-without-sources/b.c0000644000175100017510000000246215232633614023532 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int foo(); // defined in a.cpp int main() { return foo(); } qbs-src-3.3.1/tests/auto/api/testdata/app-without-sources/a.c0000644000175100017510000000236415232633614023532 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo() { return 42; } qbs-src-3.3.1/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs0000644000175100017510000000145415232633614027616 0ustar runnerrunnerProject { StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a.c", ] } StaticLibrary { name: "b" Depends { name: "a" } Depends { name: "cpp" } files: [ "b.c", ] } CppApplication { name: "appWithoutSources" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } // HACK: cpp.entryPoint currently not working 100% with gcc Properties { condition: qbs.toolchain.includes("msvc") cpp.entryPoint: "main" cpp.libraries: ["ucrt", "kernel32"] } cpp.entryPoint: undefined Depends { name: "a" } Depends { name: "b" } } } qbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/0000755000175100017510000000000015232633614024611 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/0000755000175100017510000000000015232633614026261 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/myothermodule/0000755000175100017510000000000015232633614031156 5ustar runnerrunner././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/myothermodule/myothermodule.qbsqbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/myothermodule/myothermodul0000644000175100017510000000005415232633614033630 0ustar runnerrunnerModule { Depends { name: "mymodule" } } qbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/mymodule/0000755000175100017510000000000015232633614030114 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/modules/mymodule/mymodule.qbs0000644000175100017510000000114315232633614032455 0ustar runnerrunnerimport qbs.TextFile Module { property string direct property string indirect: direct ? "set" : "unset" Rule { inputs: ["txt"] Artifact { filePath: product.moduleProperty("mymodule", "indirect") fileTags: ["mymodule"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/two-default-property-values.qbs0000644000175100017510000000036515232633614032736 0ustar runnerrunnerProduct { name: "two-default-property-values" type: "mymodule" Depends { name: "mymodule" } Depends { name: "myothermodule" } mymodule.direct: "dummy" Group { files: ["test.txt"] fileTags: ["txt"] } } qbs-src-3.3.1/tests/auto/api/testdata/two-default-property-values/test.txt0000644000175100017510000000000015232633614026317 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/0000755000175100017510000000000015232633614025236 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/0000755000175100017510000000000015232633614026706 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/0000755000175100017510000000000015232633614030541 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs0000644000175100017510000000007515232633614033105 0ustar runnerrunnerModule { setupRunEnvironment: { trallala } } ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.qbsqbs-src-3.3.1/tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.0000644000175100017510000000006415232633614033276 0ustar runnerrunnerCppApplication { Depends { name: "mymodule" } } qbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/0000755000175100017510000000000015232633614023160 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs0000644000175100017510000000021015232633614027641 0ustar runnerrunnerProduct { qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } } qbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/dir/0000755000175100017510000000000015232633614023736 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/dir/file1.txt0000644000175100017510000000000015232633614025465 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/dir/subdir/0000755000175100017510000000000015232633614025226 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/recursive-wildcards/dir/subdir/file2.txt0000644000175100017510000000000015232633614026756 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/empty-filetag-list/0000755000175100017510000000000015232633614022717 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/empty-filetag-list/dontcompilethis.cpp0000644000175100017510000000002115232633614026621 0ustar runnerrunnerThis is not C++. qbs-src-3.3.1/tests/auto/api/testdata/empty-filetag-list/empty-filetag-list.qbs0000644000175100017510000000013715232633614027147 0ustar runnerrunnerCppApplication { Group { files: "dontcompilethis.cpp" fileTags: [] } } qbs-src-3.3.1/tests/auto/api/testdata/target-artifact-status/0000755000175100017510000000000015232633614023601 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/target-artifact-status/target-artifact-status.qbs0000644000175100017510000000141215232633614030710 0ustar runnerrunnerimport qbs.TextFile Product { name: "p" type: "p_type" property bool enableTagging Rule { multiplex: true Artifact { filePath: "a1"; fileTags: "p_type" } Artifact { filePath: "a2"; fileTags: "x" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating outputs"; cmd.sourceCode = function() { var f = new TextFile(outputs.p_type[0].filePath, TextFile.WriteOnly); f.close(); f = new TextFile(outputs.x[0].filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Group { condition: enableTagging fileTagsFilter: "x" fileTags: "p_type" } } qbs-src-3.3.1/tests/auto/api/testdata/buildgraph-info/0000755000175100017510000000000015232633614022251 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/buildgraph-info/buildgraph-info.qbs0000644000175100017510000000005315232633614026030 0ustar runnerrunnerProduct { qbs.shellPath: "/bin/bash" } qbs-src-3.3.1/tests/auto/api/testdata/transformers/0000755000175100017510000000000015232633614021724 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/transformers/main.cpp0000644000175100017510000000437315232633614023363 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include using namespace std; bool displayTextFile(const string &dirPath, const string &fileName) { string fullPath = dirPath + fileName; ifstream istream(fullPath.c_str()); if (!istream.is_open()) { cout << "Cannot open " << fileName << endl; return false; } cout << "---" << fileName << "---" << endl; char buf[256]; unsigned int i = 1; while (istream.good()) { istream.getline(buf, sizeof(buf)); cout << i++ << ": " << buf << endl; } return true; } int main(int, char **argv) { string appPath(argv[0]); size_t i = appPath.find_last_of('/'); if (i == string::npos) i = appPath.find_last_of('\\'); if (i == string::npos) // No path, plain executable was called appPath.clear(); else appPath.resize(i + 1); if (!displayTextFile(appPath, "foo.txt")) return 1; if (!displayTextFile(appPath, "bar.txt")) return 2; cout << "-------------" << endl; return 0; } qbs-src-3.3.1/tests/auto/api/testdata/transformers/transformers.qbs0000644000175100017510000000561015232633614025162 0ustar runnerrunnerimport qbs.File import qbs.TextFile import qbs.Xml import qbs.FileInfo Project { Product { name: "HelloWorld" type: "application" consoleApplication: true Group { files: ["main.cpp"] fileTags: ["main"] } Depends { name: "cpp" } Rule { // no inputs -> just a generator multiplex: true Artifact { filePath: "foo.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.txt"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this is a generated file.\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } Rule { multiplex: true // no inputs -> just a generator Artifact { filePath: "foo.xml" fileTags: "xml" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.xml"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var doc = new Xml.DomDocument(); var root = doc.createElement("root"); doc.appendChild(root); var tag = doc.createElement("Greeting"); root.appendChild(tag); tag.appendChild(doc.createTextNode("text node")); doc.save(output.filePath); } return cmd; } } Rule { inputs: ["main"] Artifact { filePath: "bar.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating bar.txt"; cmd.highlight = "linker"; cmd.inputFileName = input.filePath; cmd.sourceCode = function() { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this file was generated from " + inputFileName + ".\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } } } qbs-src-3.3.1/tests/auto/api/testdata/project-data-after-product-invalidation/0000755000175100017510000000000015232633614027010 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/project-data-after-product-invalidation/file.cpp0000644000175100017510000000235015232633614030433 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() { } ././@LongLink0000644000000000000000000000017200000000000011603 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/project-data-after-product-invalidation/project-data-after-product-invalidation.qbsqbs-src-3.3.1/tests/auto/api/testdata/project-data-after-product-invalidation/project-data-after-pro0000644000175100017510000000014515232633614033205 0ustar runnerrunnerCppApplication { name: "theProduct" files: [ "file.cpp", "main.cpp", ] } qbs-src-3.3.1/tests/auto/api/testdata/project-data-after-product-invalidation/main.cpp0000644000175100017510000000235115232633614030441 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/filetagsfilter_override/0000755000175100017510000000000015232633614024102 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/filetagsfilter_override/InstalledApp.qbs0000644000175100017510000000027015232633614027170 0ustar runnerrunnerCppApplication { type: "application" consoleApplication: true Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "hurz" } } qbs-src-3.3.1/tests/auto/api/testdata/filetagsfilter_override/main.cpp0000644000175100017510000000235115232633614025533 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/filetagsfilter_override/filetagsfilter_override.qbs0000644000175100017510000000034715232633614031520 0ustar runnerrunnerimport "InstalledApp.qbs" as InstalledApp InstalledApp { files: "main.cpp" config.install.install: false Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "habicht" } } qbs-src-3.3.1/tests/auto/api/testdata/rule-conflict/0000755000175100017510000000000015232633614021745 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rule-conflict/pch1.h0000644000175100017510000000233215232633614022751 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/api/testdata/rule-conflict/pch2.h0000644000175100017510000000233215232633614022752 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-3.3.1/tests/auto/api/testdata/rule-conflict/rule-conflict.qbs0000644000175100017510000000023115232633614025216 0ustar runnerrunnerCppApplication { files: "main.cpp" Group { name: "pch files" files: ["pch1.h", "pch2.h"] fileTags: "cpp_pch_src" } } qbs-src-3.3.1/tests/auto/api/testdata/rule-conflict/main.cpp0000644000175100017510000000235115232633614023376 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/0000755000175100017510000000000015232633614023530 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/modules/0000755000175100017510000000000015232633614025200 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/modules/brokenmodule/0000755000175100017510000000000015232633614027666 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/modules/brokenmodule/brokenmodule.qbs0000644000175100017510000000003415232633614033060 0ustar runnerrunnerModule { syntax error } qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/cycle.qbs0000644000175100017510000000021315232633614025332 0ustar runnerrunnerProject { property string productName: "p1" Product { name: project.productName } references: ["referenced-file-errors.qbs"] } qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/wrongtype.qbs0000644000175100017510000000001315232633614026267 0ustar runnerrunnerModule { } qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/okay2.qbs0000644000175100017510000000002715232633614025263 0ustar runnerrunnerProduct { name: "p4" } qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/emptydir/0000755000175100017510000000000015232633614025365 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/emptydir/.gitignore0000644000175100017510000000000015232633614027343 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/referenced-file-errors.qbs0000644000175100017510000000074115232633614030572 0ustar runnerrunnerProject { references: [ "ambiguousdir", "cycle.qbs", "emptydir", "nosuchfile.qbs", "okay.qbs", "wrongtype.qbs", ] SubProject { filePath: "cycle.qbs" Properties { productName: "p3" } } SubProject { filePath: "nosuchfile.qbs" } SubProject { filePath: "okay2.qbs" } Product { name: "p5" Depends { name: "brokenmodule" } } } qbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/0000755000175100017510000000000015232633614026222 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/p2.qbs0000644000175100017510000000000015232633614027240 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/p1.qbs0000644000175100017510000000000015232633614027237 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/referenced-file-errors/okay.qbs0000644000175100017510000000002715232633614025201 0ustar runnerrunnerProduct { name: "p2" } qbs-src-3.3.1/tests/auto/api/testdata/build-properties-source/0000755000175100017510000000000015232633614023766 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/build-properties-source/main.cpp0000644000175100017510000000252515232633614025422 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef WORLD # error WORLD is not defined #endif int main() { std::puts("Hello " WORLD "!"); } qbs-src-3.3.1/tests/auto/api/testdata/build-properties-source/build-properties-source.qbs0000644000175100017510000000054215232633614031265 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "HelloWorld" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: 'cpp' } Group { cpp.defines: ['WORLD="BANANA"'] files : [ "main.cpp" ] } } } qbs-src-3.3.1/tests/auto/api/testdata/change-dependent-lib/0000755000175100017510000000000015232633614023134 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs0000644000175100017510000000100215232633614027571 0ustar runnerrunnerProject { Application { name : "HelloWorld" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "mylib" } } DynamicLibrary { name : "mylib" version: "1.2.3" Group { files : [ "mylib.cpp" ] } Depends { name: "cpp" } cpp.defines: ["XXXX"] Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/change-dependent-lib/main.cpp0000644000175100017510000000257315232633614024573 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT int mylib_hello(); int main() { std::puts("application says hello!"); return mylib_hello(); } qbs-src-3.3.1/tests/auto/api/testdata/change-dependent-lib/mylib.cpp0000644000175100017510000000253415232633614024760 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT int mylib_hello() { std::puts("mylib says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/new-pattern-match/0000755000175100017510000000000015232633614022535 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/new-pattern-match/new-pattern-match.qbs0000644000175100017510000000003715232633614026602 0ustar runnerrunnerProduct { files: "*.txt" } qbs-src-3.3.1/tests/auto/api/testdata/timeout-js/0000755000175100017510000000000015232633614021277 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/timeout-js/timeout.qbs0000644000175100017510000000074215232633614023477 0ustar runnerrunnerProduct { type: "product-under-test" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "product-under-test" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "running infinite loop"; cmd.sourceCode = function() { while (true) ; } cmd.timeout = 3; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/0000755000175100017510000000000015232633614024567 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static2.h0000644000175100017510000000015415232633614026311 0ustar runnerrunner#ifndef STATIC2_H #define STATIC2_H class TestMe { public: void hello() const; }; #endif // STATIC2_H qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static2.cpp0000644000175100017510000000015515232633614026645 0ustar runnerrunner#include "static2.h" #include void TestMe::hello() const { std::puts("static2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/dynamic1.cpp0000644000175100017510000000026315232633614027001 0ustar runnerrunner#include #include "../dllexport.h" void static1_hello(); DLL_EXPORT int dynamic1_hello() { static1_hello(); std::puts("dynamic1 says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs0000644000175100017510000000254315232633614032672 0ustar runnerrunnerProject { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "static1" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name: "static1" files: [ "static1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } Depends { name: "static2" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name: "static2" files: [ "static2.cpp", "static2.h" ] Depends { name: "cpp" } Probe { id: tcPrinter property bool isGcc: qbs.toolchain.contains("gcc") property bool isEmscripten: qbs.toolchain.contains("emscripten") configure: { console.info("is gcc: " + isGcc); console.info("is emscripten: " + isEmscripten); } } } } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static1.cpp0000644000175100017510000000024515232633614026644 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT void dynamic2_hello(); void static1_hello() { dynamic2_hello(); std::puts("static1 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/main.cpp0000644000175100017510000000027615232633614026224 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); int main() { int result = dynamic1_hello(); std::puts("application says hello!"); return result; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/dynamic2.cpp0000644000175100017510000000025515232633614027003 0ustar runnerrunner#include "../dllexport.h" #include "static2.h" #include DLL_EXPORT void dynamic2_hello() { TestMe tm; tm.hello(); std::puts("dynamic2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/remove-file-dependency/0000755000175100017510000000000015232633614023525 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/remove-file-dependency/someheader.h0000644000175100017510000000240315232633614026011 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ inline int magicValue() { return 156; } qbs-src-3.3.1/tests/auto/api/testdata/remove-file-dependency/main.cpp0000644000175100017510000000253715232633614025164 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "someheader.h" #include int main() { std::printf("The magic value is %d.\n", magicValue()); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/remove-file-dependency/removeFileDependency.qbs0000644000175100017510000000020215232633614030322 0ustar runnerrunnerCppApplication { files: ["main.cpp"] // Do not reference header files here to force them to be FileDependency objects. } qbs-src-3.3.1/tests/auto/api/testdata/dependency-on-multiplexed-type/0000755000175100017510000000000015232633614025240 5ustar runnerrunner././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/dependency-on-multiplexed-type/dependency-on-multiplexed-type.qbsqbs-src-3.3.1/tests/auto/api/testdata/dependency-on-multiplexed-type/dependency-on-multiplexed-type.0000644000175100017510000000053315232633614033303 0ustar runnerrunnerProject { Product { name: "dep"; type: "x" } Product { name: "p1" multiplexByQbsProperties: "architectures" qbs.architectures: ["a", "b"] aggregate: true Depends { productTypes: "x" } multiplexedType: "x" } Product { name: "p2" Depends { productTypes: "x" } } } qbs-src-3.3.1/tests/auto/api/testdata/no-asserts-in-relaxed-mode/0000755000175100017510000000000015232633614024245 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/no-asserts-in-relaxed-mode/no-asserts-in-relaxed-mode.qbs0000644000175100017510000000024515232633614032023 0ustar runnerrunnerProject { Product { name: "p" Depends { name: "dep" } } Product { name: "dep" property bool p: { throw "oops"; } } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/0000755000175100017510000000000015232633614026054 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/0000755000175100017510000000000015232633614027524 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/m/0000755000175100017510000000000015232633614027760 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/m/m.qbs0000644000175100017510000000015315232633614030722 0ustar runnerrunnerModule { Scanner { inputs: "i" searchPaths: { while (true); } scan: [] } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/infinite-loop.qbs0000644000175100017510000000063615232633614031344 0ustar runnerrunnerProduct { type: "t" Depends { name: "m" } Group { files: "file.in" fileTags: "i" } Rule { inputs: "i" Artifact { filePath: "dummy" fileTags: "t" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/file.in0000644000175100017510000000000015232633614027311 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/projectd0000644000175100017510000000000015232633614020722 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/0000755000175100017510000000000015232633614024546 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/dynamic1.cpp0000644000175100017510000000027215232633614026760 0ustar runnerrunner#include "../dllexport.h" #include "object2.h" #include DLL_EXPORT int dynamic1_hello() { TestMe tm; tm.hello(); std::puts("dynamic1 says hello!"); return 1; } qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/object2.cpp0000644000175100017510000000030015232633614026573 0ustar runnerrunner#include "object2.h" #include "../dllexport.h" #include DLL_IMPORT void dynamic2_hello(); void TestMe::hello() const { dynamic2_hello(); std::puts("object2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/main.cpp0000644000175100017510000000020615232633614026174 0ustar runnerrunner#include void object1_hello(); int main() { object1_hello(); std::puts("application says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/object2.h0000644000175100017510000000015415232633614026247 0ustar runnerrunner#ifndef OBJECT2_H #define OBJECT2_H class TestMe { public: void hello() const; }; #endif // OBJECT2_H qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/dynamic2.cpp0000644000175100017510000000017115232633614026757 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void dynamic2_hello() { std::puts("dynamic2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/object1.cpp0000644000175100017510000000026515232633614026604 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); void object1_hello() { int n = dynamic1_hello(); std::printf("object%d says hello!\n", n); } qbs-src-3.3.1/tests/auto/api/testdata/link-objectlibs-dynamiclibs/link-objectlibs-dynamiclibs.qbs0000644000175100017510000000310615232633614032624 0ustar runnerrunnerProject { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "object1" } } ObjectLibrary { name: "object1" files: [ "object1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } Probe { id: osCheck property bool isNormalUnix: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") property bool isGcc: qbs.toolchain.contains("gcc") property bool isEmscripten: qbs.toolchain.contains("emscripten") configure: { console.info("is normal unix: " + (isNormalUnix ? "yes" : "no")); console.info("is gcc: " + isGcc); console.info("is emscripten: " + isEmscripten); } } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "object2" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } ObjectLibrary { name: "object2" files: [ "object2.cpp", "object2.h" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/soft-dependency/0000755000175100017510000000000015232633614022266 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/soft-dependency/main.cpp0000644000175100017510000000240315232633614023715 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { thisShouldNotLink(); } qbs-src-3.3.1/tests/auto/api/testdata/soft-dependency/soft-dependency.qbs0000644000175100017510000000026515232633614026067 0ustar runnerrunnerCppApplication { Depends { name: "nosuchmodule" required: false } Properties { condition: nosuchmodule.present files: "main.cpp" } } qbs-src-3.3.1/tests/auto/api/testdata/type-change/0000755000175100017510000000000015232633614021403 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/type-change/main.cpp0000644000175100017510000000235115232633614023034 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-3.3.1/tests/auto/api/testdata/type-change/type-change.qbs0000644000175100017510000000013115232633614024311 0ustar runnerrunnerProduct { files: "main.cpp" Depends { name: "cpp" } // type: "application" } qbs-src-3.3.1/tests/auto/api/testdata/productNameWithDots/0000755000175100017510000000000015232633614023146 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/productNameWithDots/lib.cpp0000644000175100017510000000235115232633614024421 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void foo() {} qbs-src-3.3.1/tests/auto/api/testdata/productNameWithDots/app.cpp0000644000175100017510000000236415232633614024437 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/productNameWithDots/productNameWithDots.qbs0000644000175100017510000000055715232633614027633 0ustar runnerrunnerProject { CppApplication { name: "myapp" consoleApplication: true property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "foo.bar.bla" } files: ["app.cpp"] } StaticLibrary { Depends { name: "cpp" } name: "foo.bar.bla" files: ["lib.cpp"] } } qbs-src-3.3.1/tests/auto/api/testdata/renamed-qbs-source-file/0000755000175100017510000000000015232633614023610 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/renamed-qbs-source-file/the-product/0000755000175100017510000000000015232633614026046 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/renamed-qbs-source-file/the-product/the-prodduct.qbs0000644000175100017510000000001415232633614031152 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/api/testdata/renamed-qbs-source-file/renamed-qbs-source-file.qbs0000644000175100017510000000025115232633614030726 0ustar runnerrunnerProject { references: "the-product/the-prodduct.qbs" Product { Group { files: "the-product/*.qbs" fileTags: [] } } } qbs-src-3.3.1/tests/auto/api/testdata/missing-source-file/0000755000175100017510000000000015232633614023063 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/missing-source-file/file2.txt.missing0000644000175100017510000000000015232633614026263 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/missing-source-file/missing-source-file.qbs0000644000175100017510000000013615232633614027456 0ustar runnerrunnerProduct { files: [ "file1.txt", "file2.txt", "file3.txt", ] } qbs-src-3.3.1/tests/auto/api/testdata/missing-source-file/file1.txt0000644000175100017510000000000015232633614024612 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/missing-source-file/file3.txt0000644000175100017510000000000015232633614024614 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/0000755000175100017510000000000015232633614023417 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/c.in0000644000175100017510000000000015232633614024157 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/compiler.cpp0000644000175100017510000000026215232633614025735 0ustar runnerrunner#include #include int main(int argc, char *argv[]) { assert(argc == 3); std::ofstream target(argv[2]); assert(target); target << argv[1]; } qbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/explicitly-depends-on.qbs0000644000175100017510000000443615232633614030355 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host import qbs.TextFile Project { CppApplication { name: "compiler" files: ["compiler.cpp"] Group { fileTagsFilter: ["application"] fileTags: ["compiler"] } } Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "p" type: ["mytype"] Depends { name: "compiler" } Depends { name: "cpp" } Rule { inputs: ["mytype.in"] explicitlyDependsOnFromDependencies: ["compiler"] Artifact { filePath: input.fileName + ".out" fileTags: product.type } prepare: { var compiler = explicitlyDependsOn["compiler"][0].filePath; var cmd = new Command(compiler, [input.filePath, output.filePath]); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; return [cmd]; } } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["compiler"] Artifact { filePath: "compiler-name.txt" fileTags: product.type } prepare: { var nameCmd = new JavaScriptCommand(); nameCmd.description = "writing compiler name"; nameCmd.sourceCode = function() { var compiler = explicitlyDependsOn["compiler"][0].filePath; var file = new TextFile(output.filePath, TextFile.WriteOnly); file.write("compiler file name: " + FileInfo.baseName(compiler)); file.close(); } return [nameCmd]; } } FileTagger { patterns: "*.in" fileTags: ["mytype.in"] } files: ["a.in", "b.in", "c.in"] } } qbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/b.in0000644000175100017510000000000015232633614024156 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/explicitly-depends-on/a.in0000644000175100017510000000000015232633614024155 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rename-target-artifact/0000755000175100017510000000000015232633614023525 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rename-target-artifact/lib.cpp0000644000175100017510000000241515232633614025001 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" MY_EXPORT void f() { } qbs-src-3.3.1/tests/auto/api/testdata/rename-target-artifact/main.cpp0000644000175100017510000000237615232633614025165 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-3.3.1/tests/auto/api/testdata/rename-target-artifact/rename.qbs0000644000175100017510000000077515232633614025514 0ustar runnerrunnerProject { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" qbs.buildVariant: "release" files: "main.cpp" } DynamicLibrary { name: "TheLib" targetName: "the_lib" Depends { name: "cpp" } cpp.defines: "MY_EXPORT=DLL_EXPORT" qbs.buildVariant: "release" files: "lib.cpp" Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/process-result/0000755000175100017510000000000015232633614022171 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/process-result/process-result.qbs0000644000175100017510000000257115232633614025677 0ustar runnerrunnerimport qbs.Host Project { CppApplication { name: "app" consoleApplication: true files: ["main.cpp"] } Product { condition: { var result = qbs.targetPlatform === Host.platform() && qbs.architecture === Host.architecture(); if (!result) console.info("target platform/arch differ from host platform/arch (" + qbs.targetPlatform + "/" + qbs.architecture + " vs " + Host.platform() + "/" + Host.architecture() + ")"); return result; } name: "app-caller" type: "mytype" Depends { name: "app" } Depends { name: "cpp" } property bool redirectStdout property bool redirectStderr property int argument Rule { inputsFromDependencies: ["application"] outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath, [product.argument]); if (product.redirectStdout) cmd.stdoutFilePath = product.buildDirectory + "/stdout.txt"; if (product.redirectStderr) cmd.stderrFilePath = product.buildDirectory + "/stderr.txt"; cmd.description = "building app-caller"; return [cmd]; } } } } qbs-src-3.3.1/tests/auto/api/testdata/process-result/main.cpp0000644000175100017510000000257015232633614023625 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { std::cout << "stdout"; std::cerr << "stderr"; return atoi(argv[1]); } qbs-src-3.3.1/tests/auto/api/testdata/multi-arch/0000755000175100017510000000000015232633614021244 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/multi-arch/multi-arch.qbs0000644000175100017510000000273615232633614024030 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile Project { property string hostProfile property string targetProfile Product { property stringList myProfiles name: "p1" type: "output" qbs.profiles: myProfiles ? myProfiles : [project.targetProfile, project.hostProfile] Group { files: "host+target.input" fileTags: "input" } qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: qbs.profile } } Product { name: "p2" type: "output" qbs.profiles: [project.hostProfile] Group { files: "host-tool.input" fileTags: "input" } qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: qbs.profile } } Rule { inputs: "input" Artifact { filePath: FileInfo.baseName(input.fileName) + ".output" fileTags: "output" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(product.moduleProperty("qbs", "architecture")); file.close(); } return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/multi-arch/host-tool.input0000644000175100017510000000000015232633614024243 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/multi-arch/host+target.input0000644000175100017510000000000015232633614024552 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/nonexistingprojectproperties/0000755000175100017510000000000015232633614025250 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/nonexistingprojectproperties/nonexistingprojectproperties.qbs0000644000175100017510000000001415232633614034023 0ustar runnerrunnerProject { } qbs-src-3.3.1/tests/auto/api/testdata/nonexistingprojectproperties/invalidaccessfromproduct.qbs0000644000175100017510000000005415232633614033053 0ustar runnerrunnerProject { Product { type: project.blubb } } qbs-src-3.3.1/tests/auto/api/testdata/source-file-in-build-dir/0000755000175100017510000000000015232633614023671 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/source-file-in-build-dir/file.cpp0000644000175100017510000000235215232633614025316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/api/testdata/source-file-in-build-dir/source-file-in-build-dir.qbs0000644000175100017510000000112715232633614031073 0ustar runnerrunnerimport qbs.TextFile CppApplication { name: "theProduct" type: base.concat(["dummy"]) Rule { multiplex: true Artifact { filePath: "generated.cpp" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } Group { name: "the group" files: "**/*.cpp" } } qbs-src-3.3.1/tests/auto/api/testdata/build-error-code-location/0000755000175100017510000000000015232633614024143 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/build-error-code-location/build-error-code-location.qbs0000644000175100017510000000025215232633614031615 0ustar runnerrunnerProduct { name: "p" type: ["p.out"] Rule { multiplex: true outputFileTags: ["p.out"] outputArtifacts: { } prepare: {} } } qbs-src-3.3.1/tests/auto/api/testdata/base-properties/0000755000175100017510000000000015232633614022303 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/base-properties/imports/0000755000175100017510000000000015232633614024000 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/base-properties/imports/Foo.qbs0000644000175100017510000000015115232633614025227 0ustar runnerrunnerBar { type: "application" consoleApplication: true cpp.defines: base.concat(["FROM_FOO"]) } qbs-src-3.3.1/tests/auto/api/testdata/base-properties/imports/Bar.qbs0000644000175100017510000000010615232633614025210 0ustar runnerrunnerProduct { Depends { name: "cpp" } cpp.defines: ["FROM_BAR"] } qbs-src-3.3.1/tests/auto/api/testdata/base-properties/main.cpp0000644000175100017510000000261415232633614023736 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FROM_FOO #error FROM_FOO missing! #endif #ifndef FROM_BAR #error FROM_BAR missing! #endif #ifndef FROM_PRJ #error FROM_PRJ missing! #endif int main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/base-properties/prj.qbs0000644000175100017510000000021015232633614023576 0ustar runnerrunnerimport "imports/Foo.qbs" as Foo Project { Foo { cpp.defines: base.concat(["FROM_PRJ"]); files: "main.cpp" } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-process/0000755000175100017510000000000015232633614023427 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs0000644000175100017510000000173715232633614026722 0ustar runnerrunnerimport qbs.Host Project { CppApplication { type: "application" consoleApplication: true // suppress bundle generation files: "main.cpp" name: "infinite-loop" cpp.cxxLanguageVersion: "c++11" Properties { condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } } Product { type: "mytype" name: "caller" Depends { name: "infinite-loop" } Depends { name: "cpp" // Make sure build environment is set up properly. condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } Rule { inputsFromDependencies: "application" outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath); cmd.description = "calling application that runs forever"; return cmd; } } } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-process/main.cpp0000644000175100017510000000251315232633614025060 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { std::this_thread::sleep_for(std::chrono::seconds(700)); } qbs-src-3.3.1/tests/auto/api/testdata/disabled_install_group/0000755000175100017510000000000015232633614023710 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/disabled_install_group/disabled_install_group.qbs0000644000175100017510000000032215232633614031125 0ustar runnerrunnerCppApplication { consoleApplication: true files: "main.cpp" config.install.install: false Group { condition: false qbs.install: true fileTagsFilter: product.type } } qbs-src-3.3.1/tests/auto/api/testdata/disabled_install_group/main.cpp0000644000175100017510000000235215232633614025342 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-3.3.1/tests/auto/api/testdata/lib-same-source/0000755000175100017510000000000015232633614022166 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/lib-same-source/main.cpp0000644000175100017510000000243415232633614023621 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::puts("Hello WOrld!"); } qbs-src-3.3.1/tests/auto/api/testdata/lib-same-source/lib-same-source.qbs0000644000175100017510000000074615232633614025673 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name : "HelloWorldApp" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } Product { type: "staticlibrary" name : "HelloWorldLib" Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } } qbs-src-3.3.1/tests/auto/api/testdata/empty-submodules-list/0000755000175100017510000000000015232633614023466 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/empty-submodules-list/empty-submodules-list.qbs0000644000175100017510000000012415232633614030461 0ustar runnerrunnerCppApplication { Depends { name: "dummy" submodules: [] } } qbs-src-3.3.1/tests/auto/api/testdata/transformer-data/0000755000175100017510000000000015232633614022450 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/transformer-data/transformer-data.qbs0000644000175100017510000000163115232633614026431 0ustar runnerrunnerimport qbs.File import qbs.TextFile Product { type: ["theType"] Rule { multiplex: true Artifact { filePath: "artifact1" fileTags: ["type1"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } Rule { inputs: ["type1"] Artifact { filePath: "artifact2" fileTags: ["theType"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } qbs-src-3.3.1/tests/auto/api/testdata/group-visibility/0000755000175100017510000000000015232633614022520 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/group-visibility/modules/0000755000175100017510000000000015232633614024170 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/group-visibility/modules/m/0000755000175100017510000000000015232633614024424 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/group-visibility/modules/m/m.qbs0000644000175100017510000000041115232633614025363 0ustar runnerrunnerModule { Group { name: "should not be visible (module)" Group { name: "should be visible (module)" files: [] Group { name: "should also not be visible (module)" } } } } qbs-src-3.3.1/tests/auto/api/testdata/group-visibility/group-visibility.qbs0000644000175100017510000000027015232633614026547 0ustar runnerrunnerProduct { Depends { name: "m" } Group { name: "should be visible (product)" files: [] } Group { name: "should not be visible (product)" } } qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/0000755000175100017510000000000015232633614021204 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs0000644000175100017510000000222315232633614023717 0ustar runnerrunnerimport qbs.File import qbs.FileInfo DynamicLibrary { name: "echoplugin" Depends { name: "Qt.core" } Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Group { condition: Qt.core.versionMajor >= 5 files: [ "echoplugin.h", "echoplugin.cpp", ] } Group { condition: Qt.core.versionMajor >= 5 files: ["echoplugin.json.source"] fileTags: ["json_in"] } Group { condition: Qt.core.versionMajor < 5 files: "echoplugin_dummy.cpp" } cpp.includePaths: buildDirectory Rule { condition: Qt.core.versionMajor >= 5 inputs: ["json_in"] Artifact { filePath: "echoplugin.json" fileTags: ["qt_plugin_metadata"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/echoplugin.cpp0000644000175100017510000000247515232633614024055 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "echoplugin.h" QString EchoPlugin::echo(const QString &message) { return message; } qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/echoplugin.json.source0000644000175100017510000000000315232633614025524 0ustar runnerrunner{} qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/echoplugin.h0000644000175100017510000000310315232633614023507 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ECHOPLUGIN_H #define ECHOPLUGIN_H #include #include #include "echointerface.h" class EchoPlugin : public QObject, EchoInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.EchoInterface" FILE "echoplugin.json") Q_INTERFACES(EchoInterface) public: QString echo(const QString &message); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/echoplugin_dummy.cpp0000644000175100017510000000235715232633614025267 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummyFunc() {} qbs-src-3.3.1/tests/auto/api/testdata/qt5-plugin/echointerface.h0000644000175100017510000000312215232633614024152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ECHOINTERFACE_H #define ECHOINTERFACE_H #include //! [0] class EchoInterface { public: virtual ~EchoInterface() {} virtual QString echo(const QString &message) = 0; }; QT_BEGIN_NAMESPACE #define EchoInterface_iid "org.qt-project.Qt.Examples.EchoInterface" Q_DECLARE_INTERFACE(EchoInterface, EchoInterface_iid) QT_END_NAMESPACE //! [0] #endif qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/0000755000175100017510000000000015232633614022430 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/lib4.h0000644000175100017510000000307415232633614023437 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB4_H #define LIB4_H #include "../dllexport.h" #include #ifdef TEST_LIB # define LIB_EXPORT DLL_EXPORT #else # define LIB_EXPORT DLL_IMPORT #endif class LIB_EXPORT TestMe { public: TestMe(); void hello1() const; inline void hello2() const { hello2Impl(); } private: void hello2Impl() const; }; #endif // LIB4_H qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/lib3.cpp0000644000175100017510000000265615232633614023776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT void lib3_hello() { std::puts("lib3 says hello!"); } DLL_EXPORT char* lib3_greeting() { static char greeting[] = "hello"; return greeting; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs0000644000175100017510000000332515232633614026373 0ustar runnerrunnerProject { Application { name : "HelloWorld" property bool dummy: { console.info("is emscripten: " + qbs.toolchain.includes("emscripten")); } Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "lib1" } Depends { name: "lib4" } } DynamicLibrary { name : "lib1" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } Depends { name: "lib2" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib2" cpp.visibility: 'default' Group { files : [ "lib2.cpp" ] } Depends { name: "cpp" } Depends { name: "lib3" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib3" cpp.visibility: 'hidden' Group { files : [ "lib3.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib4" cpp.visibility: 'hiddenInlines' cpp.defines: "TEST_LIB" Group { files : [ "lib4.h", "lib4.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } } } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/lib2.cpp0000644000175100017510000000257615232633614023776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT void lib3_hello(); DLL_EXPORT void lib2_hello() { std::puts("lib2 says hello!"); lib3_hello(); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/main.cpp0000644000175100017510000000265015232633614024063 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include DLL_IMPORT int lib1_hello(); int main() { std::puts("application says hello!"); TestMe test; test.hello1(); test.hello2(); return lib1_hello(); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/lib1.cpp0000644000175100017510000000261215232633614023764 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT void lib2_hello(); DLL_EXPORT int lib1_hello() { std::puts("lib1 says hello!"); lib2_hello(); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs/lib4.cpp0000644000175100017510000000262615232633614023774 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib4.h" TestMe::TestMe() { } void TestMe::hello1() const { std::puts("lib4 says hello!"); } void TestMe::hello2Impl() const { std::puts("lib4 says hello inline!"); } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/0000755000175100017510000000000015232633614024473 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/0000755000175100017510000000000015232633614026143 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/m/0000755000175100017510000000000015232633614026377 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/m/m.qbs0000644000175100017510000000012215232633614027335 0ustar runnerrunnerModule { Scanner { inputs: "i" scan: { while (true); } } }qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/infinite-loop.qbs0000644000175100017510000000063615232633614027763 0ustar runnerrunnerProduct { type: "t" Depends { name: "m" } Group { files: "file.in" fileTags: "i" } Rule { inputs: "i" Artifact { filePath: "dummy" fileTags: "t" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/infinite-loop-scanning-scan/file.in0000644000175100017510000000000015232633614025730 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/0000755000175100017510000000000015232633614024567 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static2.h0000644000175100017510000000015415232633614026311 0ustar runnerrunner#ifndef STATIC2_H #define STATIC2_H class TestMe { public: void hello() const; }; #endif // STATIC2_H qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static2.cpp0000644000175100017510000000030015232633614026635 0ustar runnerrunner#include "../dllexport.h" #include "static2.h" #include DLL_IMPORT void dynamic2_hello(); void TestMe::hello() const { dynamic2_hello(); std::puts("static2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/dynamic1.cpp0000644000175100017510000000027215232633614027001 0ustar runnerrunner#include "../dllexport.h" #include "static2.h" #include DLL_EXPORT int dynamic1_hello() { TestMe tm; tm.hello(); std::puts("dynamic1 says hello!"); return 1; } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs0000644000175100017510000000310615232633614032666 0ustar runnerrunnerProject { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "static1" } } StaticLibrary { name: "static1" files: [ "static1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } Probe { id: osCheck property bool isNormalUnix: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") property bool isGcc: qbs.toolchain.contains("gcc") property bool isEmscripten: qbs.toolchain.contains("emscripten") configure: { console.info("is normal unix: " + (isNormalUnix ? "yes" : "no")); console.info("is gcc: " + isGcc); console.info("is emscripten: " + isEmscripten); } } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "static2" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } StaticLibrary { name: "static2" files: [ "static2.cpp", "static2.h" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static1.cpp0000644000175100017510000000026515232633614026646 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); void static1_hello() { int n = dynamic1_hello(); std::printf("static%d says hello!\n", n); } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/main.cpp0000644000175100017510000000020615232633614026215 0ustar runnerrunner#include void static1_hello(); int main() { static1_hello(); std::puts("application says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/dynamic2.cpp0000644000175100017510000000017115232633614027000 0ustar runnerrunner#include "../dllexport.h" #include DLL_EXPORT void dynamic2_hello() { std::puts("dynamic2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/rc/0000755000175100017510000000000015232633614017603 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rc/rc.qbs0000644000175100017510000000032015232633614020711 0ustar runnerrunnerApplication { type: "application" consoleApplication: true name: "rctest" Depends { name: 'cpp' } cpp.includePaths: "subdir" files: [ "main.cpp", "test.rc" ] } qbs-src-3.3.1/tests/auto/api/testdata/rc/main.cpp0000644000175100017510000000237015232633614021235 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/rc/subdir/0000755000175100017510000000000015232633614021073 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rc/subdir/rc-include.h0000644000175100017510000000000015232633614023257 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/rc/test.rc0000644000175100017510000000062115232633614021107 0ustar runnerrunner#define IDR_VERSION1 1 #include IDR_VERSION1 VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEOS 0x00000004 FILETYPE 0x00000000 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "FFFF0000" BEGIN VALUE "FileVersion", "1.0.0.0\0" VALUE "ProductVersion", "1.0.0.0\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0xFFFF, 0x0000 END END qbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/0000755000175100017510000000000015232633614023730 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/implicit-indirect.qbs0000644000175100017510000000012115232633614030042 0ustar runnerrunnerProject { references: ["subdir1/subproject.qbs", "subdir2/subproject.qbs"] } qbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/subdir2/0000755000175100017510000000000015232633614025302 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/subdir2/subproject.qbs0000644000175100017510000000001415232633614030164 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/explicit.qbs0000644000175100017510000000014615232633614026261 0ustar runnerrunnerProject { Product { name: "blubb" } Product { name: "blubb" } Product { name: "blubb" } } qbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/implicit.qbs0000644000175100017510000000007415232633614026252 0ustar runnerrunnerProject { Product { } Product { } Product { } } qbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/subdir1/0000755000175100017510000000000015232633614025301 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/duplicate-product-names/subdir1/subproject.qbs0000644000175100017510000000001415232633614030163 0ustar runnerrunnerProduct { } qbs-src-3.3.1/tests/auto/api/testdata/disappeared-wildcard-file/0000755000175100017510000000000015232633614024164 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/disappeared-wildcard-file/file1.txt0000644000175100017510000000000015232633614025713 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/disappeared-wildcard-file/disappeared-wildcard-file.qbs0000644000175100017510000000006115232633614031655 0ustar runnerrunnerProduct { name: "dummy" files: "*.txt" } qbs-src-3.3.1/tests/auto/api/testdata/disappeared-wildcard-file/file2.txt0000644000175100017510000000000015232633614025714 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/check-outputs/0000755000175100017510000000000015232633614021775 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/check-outputs/check-outputs.qbs0000644000175100017510000000152615232633614025306 0ustar runnerrunnerimport qbs.File Project { Product { type: 'application' consoleApplication: true Group { files: 'foo.txt' fileTags: ['text'] } Depends { name: 'cpp' } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } Artifact { fileTags: ['ghost'] filePath: input.baseName + '.ghost' } prepare: { var cmd = new JavaScriptCommand(); cmd.inp = inputs["text"][0].filePath; cmd.out = outputs["cpp"][0].filePath; cmd.description = "generating " + outputs["cpp"][0].fileName; cmd.sourceCode = function() { File.copy(inp, out); }; return cmd; } } } qbs-src-3.3.1/tests/auto/api/testdata/check-outputs/foo.txt0000644000175100017510000000003115232633614023313 0ustar runnerrunnerint main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/disabled-project/0000755000175100017510000000000015232633614022412 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/disabled-project/disabled-project.qbs0000644000175100017510000000015115232633614026331 0ustar runnerrunnerimport qbs.File Project { condition: File.exists("blubb"); references: "blubb/nosuchfile.qbs" } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/0000755000175100017510000000000015232633614024546 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/dynamic1.cpp0000644000175100017510000000026315232633614026760 0ustar runnerrunner#include #include "../dllexport.h" void object1_hello(); DLL_EXPORT int dynamic1_hello() { object1_hello(); std::puts("dynamic1 says hello!"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/link-dynamiclibs-objectlibs.qbs0000644000175100017510000000254315232633614032630 0ustar runnerrunnerProject { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "object1" } Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } ObjectLibrary { name: "object1" files: [ "object1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } Depends { name: "object2" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } ObjectLibrary { name: "object2" files: [ "object2.cpp", "object2.h" ] Depends { name: "cpp" } Probe { id: tcPrinter property bool isGcc: qbs.toolchain.contains("gcc") property bool isEmscripten: qbs.toolchain.contains("emscripten") configure: { console.info("is gcc: " + isGcc); console.info("is emscripten: " + isEmscripten); } } } } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/object2.cpp0000644000175100017510000000015515232633614026603 0ustar runnerrunner#include "object2.h" #include void TestMe::hello() const { std::puts("object2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/main.cpp0000644000175100017510000000027615232633614026203 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); int main() { int result = dynamic1_hello(); std::puts("application says hello!"); return result; } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/object2.h0000644000175100017510000000015415232633614026247 0ustar runnerrunner#ifndef OBJECT2_H #define OBJECT2_H class TestMe { public: void hello() const; }; #endif // OBJECT2_H qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/dynamic2.cpp0000644000175100017510000000025515232633614026762 0ustar runnerrunner#include "../dllexport.h" #include "object2.h" #include DLL_EXPORT void dynamic2_hello() { TestMe tm; tm.hello(); std::puts("dynamic2 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/link-dynamiclibs-objectlibs/object1.cpp0000644000175100017510000000024515232633614026602 0ustar runnerrunner#include "../dllexport.h" #include DLL_IMPORT void dynamic2_hello(); void object1_hello() { dynamic2_hello(); std::puts("object1 says hello!"); } qbs-src-3.3.1/tests/auto/api/testdata/added-file-persistent/0000755000175100017510000000000015232633614023353 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/added-file-persistent/file.cpp0000644000175100017510000000235015232633614024776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() { } qbs-src-3.3.1/tests/auto/api/testdata/added-file-persistent/main.cpp0000644000175100017510000000237215232633614025007 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-3.3.1/tests/auto/api/testdata/added-file-persistent/added-file-persistent.qbs0000644000175100017510000000012315232633614030232 0ustar runnerrunnerCppApplication { files: [ 'main.cpp', /* 'file.cpp' */ ] } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp/0000755000175100017510000000000015232633614020542 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/moc-hpp/moc-hpp.qbs0000644000175100017510000000056015232633614022615 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "moc_hpp" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files : [ "object.h", "object.cpp" ] } } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp/object.cpp0000644000175100017510000000257615232633614022526 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" #include Object::Object(QObject *parent) : QObject(parent) {} int main() { Object obj; std::printf("Hello World\n"); } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp/object.h0000644000175100017510000000257115232633614022166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = nullptr); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/simple-probe/0000755000175100017510000000000015232633614021575 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/simple-probe/simple-probe.qbs0000644000175100017510000000135115232633614024702 0ustar runnerrunnerimport qbs.Probes CppApplication { Probe { id: probe1 property string someString configure: { someString = "one"; found = true; } } Probe { id: probe2 configure: { found = false; } } type: ["application"] name: "MyApp" consoleApplication: { if (!probe1.found) throw "probe1 not found"; if (probe2.found) throw "probe2 unexpectedly found"; if (probe1.someString !== "one") throw "probe1.someString expected to be \"one\"." return true } property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } files: ["main.cpp"] } qbs-src-3.3.1/tests/auto/api/testdata/simple-probe/main.cpp0000644000175100017510000000236415232633614023232 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-3.3.1/tests/auto/api/testdata/references/0000755000175100017510000000000015232633614021320 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/invalid2.qbs0000644000175100017510000000007315232633614023537 0ustar runnerrunnerProject { references: "subdir-with-multiple-projects" }qbs-src-3.3.1/tests/auto/api/testdata/references/invalid1.qbs0000644000175100017510000000006415232633614023536 0ustar runnerrunnerProject { references: "subdir-with-no-project" }qbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-one-project/0000755000175100017510000000000015232633614026004 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-one-project/test.txt0000644000175100017510000000000015232633614027512 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-one-project/p.qbs0000644000175100017510000000001415232633614026745 0ustar runnerrunnerProject { } qbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/0000755000175100017510000000000015232633614027241 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject2.qbs0000644000175100017510000000000015232633614032200 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject1.qbs0000644000175100017510000000000015232633614032177 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject3.qbs0000644000175100017510000000000015232633614032201 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-no-project/0000755000175100017510000000000015232633614025637 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/subdir-with-no-project/test.txt0000644000175100017510000000000015232633614027345 0ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/references/valid.qbs0000644000175100017510000000006615232633614023130 0ustar runnerrunnerProject { references: "subdir-with-one-project" } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/0000755000175100017510000000000015232633614021542 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/toplevelproject.qbs0000644000175100017510000000055115232633614025473 0ustar runnerrunnerProject { name: "top level project" references: ["subproject2"] Project { condition: true name: "app-project" CppApplication { name: "app" Depends { name: "testLib" } cpp.defines: "MY_EXPORT=" files: "subproject1/main.cpp" } } qbsSearchPaths: ["resources"] } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject2/0000755000175100017510000000000015232633614024004 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject2/subproject2.qbs0000644000175100017510000000051015232633614026751 0ustar runnerrunnerProject { name: "subproject2" property string libNamePrefix: "test" SubProject { filePath: "subproject3/subproject3.qbs" inheritProperties: true Properties { name: "overridden name" condition: qbs.targetOS.length > 0 libNameSuffix: "Lib" } } } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/0000755000175100017510000000000015232633614026247 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/testlib.cpp0000644000175100017510000000245215232633614030424 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "../../../dllexport.h" MY_EXPORT void f() {} qbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/subproject3.qbs0000644000175100017510000000063115232633614031221 0ustar runnerrunnerimport LibraryType Project { condition: false property string libNameSuffix: "blubb" Product { name: project.libNamePrefix + project.libNameSuffix type: LibraryType.type() Depends { name: "cpp" } Depends { name: "QtCoreDepender" } cpp.defines: "MY_EXPORT=Q_DECL_EXPORT" files: "testlib.cpp" Export { Depends { name: "cute.core" } } } } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject1/0000755000175100017510000000000015232633614024003 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/subproject1/main.cpp0000644000175100017510000000237615232633614025443 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/0000755000175100017510000000000015232633614023554 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/0000755000175100017510000000000015232633614025224 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDepender/0000755000175100017510000000000015232633614030070 5ustar runnerrunner././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDepender/qtcoredepender.qbsqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDepender/qtcoredepender.qb0000644000175100017510000000005515232633614033420 0ustar runnerrunnerModule { Depends { name: "cute.core" } } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/cute/0000755000175100017510000000000015232633614026164 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/0000755000175100017510000000000015232633614027114 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/cuteglobal.h0000644000175100017510000000004115232633614031401 0ustar runnerrunner#define Q_DECL_EXPORT DLL_EXPORT qbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/core.qbs0000644000175100017510000000010415232633614030546 0ustar runnerrunnerModule { Depends { name: "cpp" } cpp.includePaths: [path] } qbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/imports/0000755000175100017510000000000015232633614025251 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/0000755000175100017510000000000015232633614027517 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/type.js0000644000175100017510000000005515232633614031036 0ustar runnerrunnerfunction type() { return "dynamiclibrary"; } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/0000755000175100017510000000000015232633614022327 5ustar runnerrunnerqbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/object2.mm0000644000175100017510000000031515232633614024211 0ustar runnerrunner#include "object2.h" Object2::Object2(QObject *parent) : QObject(parent) {} #include "moc_object2.cpp" #include int main2() { Object2 obj; printf("Hello World\n"); return 0; } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/object.cpp0000644000175100017510000000263115232633614024303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" Object::Object(QObject *parent) : QObject(parent) {} #include "moc_object.cpp" #include int main() { Object obj; std::printf("Hello World\n"); } qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/object.h0000644000175100017510000000257115232633614023753 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = nullptr); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/object2.h0000644000175100017510000000257515232633614024041 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT2_H #define OBJECT2_H #include class Object2 : public QObject { Q_OBJECT public: Object2(QObject *parent = nullptr); }; #endif qbs-src-3.3.1/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs0000644000175100017510000000072715232633614026174 0ustar runnerrunnerProject { Product { type: "application" consoleApplication: true name: "moc_hpp_included" property bool dummy: { console.info("executable suffix: " + cpp.executableSuffix); } Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files: ["object.cpp", "object.h"] Group { condition: qbs.targetOS.includes("darwin") files: ["object2.mm", "object2.h"] } } } qbs-src-3.3.1/tests/auto/api/tst_api.cpp0000644000175100017510000044613215232633614017547 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_api.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERIFY_NO_ERROR(errorInfo) \ QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())) #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(m_workingDataDir) class LogSink: public qbs::ILogSink { public: QString output; void doPrintWarning(const qbs::ErrorInfo &error) override { qDebug("%s", qPrintable(error.toString())); warnings.push_back(error); } void doPrintError(const qbs::ErrorInfo &error) override { qDebug("%s", qPrintable(error.toString())); errors.push_back(error); } void doPrintMessage(qbs::LoggerLevel, const QString &message, const QString &) override { output += '\n' + message; } QList warnings; QList errors; }; class BuildDescriptionReceiver : public QObject { Q_OBJECT public: QString descriptions; QStringList descriptionLines; void handleDescription(const QString &, const QString &description) { descriptions += description; descriptionLines << description; } }; class ProcessResultReceiver : public QObject { Q_OBJECT public: QString output; std::vector results; void handleProcessResult(const qbs::ProcessResult &result) { results.push_back(result); output += result.stdErr().join(QLatin1Char('\n')); output += result.stdOut().join(QLatin1Char('\n')); } }; class TaskReceiver : public QObject { Q_OBJECT public: QString taskDescriptions; void handleTaskStart(const QString &task) { taskDescriptions += task; } }; static void removeBuildDir(const qbs::SetupProjectParameters ¶ms) { QString message; const QString dir = params.buildRoot() + '/' + params.configurationName(); if (!qbs::Internal::removeDirectoryWithContents(dir, &message)) qFatal("Could not remove build dir: %s", qPrintable(message)); } static bool waitForFinished(qbs::AbstractJob *job, int timeout = 0) { if (job->state() == qbs::AbstractJob::StateFinished) return true; QEventLoop loop; QObject::connect(job, &qbs::AbstractJob::finished, &loop, &QEventLoop::quit); if (timeout > 0) { QTimer timer; QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.setSingleShot(true); timer.start(timeout); loop.exec(); return timer.isActive(); // Timer ended the loop <=> job did not finish. } loop.exec(); return true; } TestApi::TestApi() : m_logSink(new LogSink) , m_sourceDataDir(testDataSourceDir(SRCDIR "/testdata")) , m_workingDataDir(testWorkDir(QStringLiteral("api"))) { } TestApi::~TestApi() { delete m_logSink; } void TestApi::initTestCase() { QString errorMessage; qbs::Internal::removeDirectoryWithContents(m_workingDataDir, &errorMessage); QVERIFY2(qbs::Internal::copyFileRecursion(m_sourceDataDir, m_workingDataDir, false, true, &errorMessage), qPrintable(errorMessage)); QVERIFY(copyDllExportHeader(m_sourceDataDir, m_workingDataDir)); } void TestApi::init() { m_logSink->warnings.clear(); m_logSink->errors.clear(); m_logSink->setLogLevel(qbs::LoggerInfo); } void TestApi::addQObjectMacroToCppFile() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("add-qobject-macro-to-cpp-file", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("object.cpp", "// ", ""); errorInfo = doBuildProject("add-qobject-macro-to-cpp-file", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); } static bool isAboutUndefinedSymbols(const QString &_message) { const QString message = _message.toLower(); return message.contains("undefined") || message.contains("unresolved"); } void TestApi::addedFilePersistent() { // On the initial run, linking will fail. const QString relProjectFilePath = "added-file-persistent"; ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject(relProjectFilePath, nullptr, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); receiver.output.clear(); // Add a file. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); const qbs::SetupProjectParameters params = defaultSetupParameters(relProjectFilePath); REPLACE_IN_FILE(params.projectFilePath(), "/* 'file.cpp' */", "'file.cpp'"); std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(nullptr); // Remove the file again. qbs must unschedule the rule application again. // Consequently, the linking step must fail as in the initial run. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(params.projectFilePath(), "'file.cpp'", "/* 'file.cpp' */"); errorInfo = doBuildProject(relProjectFilePath, nullptr, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); // Add the file again. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(params.projectFilePath(), "/* 'file.cpp' */", "'file.cpp'"); setupJob.reset(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(nullptr); // qbs must remember that a file was scheduled for rule application. The build must then // succeed, as now all necessary symbols are linked in. errorInfo = doBuildProject(relProjectFilePath); VERIFY_NO_ERROR(errorInfo); } void TestApi::baseProperties() { const qbs::ErrorInfo errorInfo = doBuildProject("base-properties/prj.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::buildGraphInfo() { SettingsPtr s = settings(); qbs::Internal::TemporaryProfile p("bgInfoProfile", s.get()); p.p.setValue("qbs.targetPlatform", "xenix"); qbs::SetupProjectParameters setupParams = defaultSetupParameters("buildgraph-info"); setupParams.setTopLevelProfile(p.p.name()); setupParams.setOverriddenValues({std::make_pair("qbs.architecture", "arm")}); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const QString bgFilePath = setupParams.buildRoot() + QLatin1Char('/') + relativeBuildGraphFilePath(); QVERIFY2(QFileInfo::exists(bgFilePath), qPrintable(bgFilePath)); qbs::Project::BuildGraphInfo bgInfo = qbs::Project::getBuildGraphInfo(bgFilePath, QStringList()); QVERIFY(bgInfo.error.hasError()); // Build graph is still locked. setupJob.reset(nullptr); const QStringList requestedProperties({"qbs.architecture", "qbs.shellPath", "qbs.targetPlatform"}); bgInfo = qbs::Project::getBuildGraphInfo(bgFilePath, requestedProperties); QVERIFY2(!bgInfo.error.hasError(), qPrintable(bgInfo.error.toString())); QCOMPARE(bgFilePath, bgInfo.bgFilePath); QCOMPARE(bgInfo.profileData.size(), 1); QCOMPARE(bgInfo.profileData.value(p.p.name()).toMap().size(), 1); QCOMPARE(bgInfo.profileData.value(p.p.name()).toMap().value("qbs").toMap().value( "targetPlatform"), p.p.value("qbs.targetPlatform")); QCOMPARE(bgInfo.overriddenProperties, setupParams.overriddenValues()); QCOMPARE(bgInfo.requestedProperties.size(), requestedProperties.size()); QCOMPARE(bgInfo.requestedProperties.value("qbs.architecture").toString(), QString("arm")); QCOMPARE(bgInfo.requestedProperties.value("qbs.shellPath").toString(), QString("/bin/bash")); QCOMPARE(bgInfo.requestedProperties.value("qbs.targetPlatform").toString(), QString("xenix")); } void TestApi::buildErrorCodeLocation() { const qbs::ErrorInfo errorInfo = doBuildProject("build-error-code-location/build-error-code-location.qbs"); QVERIFY(errorInfo.hasError()); const qbs::ErrorItem errorItem = errorInfo.items().front(); QCOMPARE(errorItem.description(), QString("Rule.outputArtifacts must return an array of objects.")); const qbs::CodeLocation errorLoc = errorItem.codeLocation(); QCOMPARE(QFileInfo(errorLoc.filePath()).fileName(), QString("build-error-code-location.qbs")); QCOMPARE(errorLoc.line(), 7); QCOMPARE(errorLoc.column(), 26); } void TestApi::buildGraphLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("buildgraph-locking"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); Q_UNUSED(project); // Case 1: Setting up a competing project from scratch. setupJob.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("lock"), qPrintable(setupJob->error().toString())); // Case 2: Setting up a non-competing project and then making it competing. qbs::SetupProjectParameters setupParams2 = setupParams; setupParams2.setBuildRoot(setupParams.buildRoot() + "/2"); setupJob.reset(qbs::Project().setupProject(setupParams2, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const QString buildDirName = relativeBuildDir(setupParams2.configurationName()); const QString lockFile = setupParams2.buildRoot() + '/' + buildDirName + '/' + buildDirName + ".bg.lock"; QVERIFY2(QFileInfo(lockFile).isFile(), qPrintable(lockFile)); qbs::Project project2 = setupJob->project(); QVERIFY(project2.isValid()); setupJob.reset(project2.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("lock"), qPrintable(setupJob->error().toString())); QVERIFY2(QFileInfo(lockFile).isFile(), qPrintable(lockFile)); // Case 3: Changing the build directory of an existing project to something non-competing. qbs::SetupProjectParameters setupParams3 = setupParams2; setupParams3.setBuildRoot(setupParams.buildRoot() + "/3"); setupJob.reset(qbs::Project().setupProject(setupParams3, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); project2 = qbs::Project(); QVERIFY2(!QFileInfo(lockFile).exists(), qPrintable(lockFile)); const QString newLockFile = setupParams3.buildRoot() + '/' + buildDirName + '/' + buildDirName + ".bg.lock"; QVERIFY2(QFileInfo(newLockFile).isFile(), qPrintable(newLockFile)); qbs::Project project3 = setupJob->project(); QVERIFY(project3.isValid()); // Case 4: Changing the build directory again, but cancelling the job. setupJob.reset(project3.setupProject(setupParams2, m_logSink, nullptr)); QThread::sleep(1); setupJob->cancel(); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(!QFileInfo(lockFile).exists(), qPrintable(lockFile)); QVERIFY2(QFileInfo(newLockFile).isFile(), qPrintable(newLockFile)); setupJob.reset(nullptr); project3 = qbs::Project(); QVERIFY2(!QFileInfo(newLockFile).exists(), qPrintable(newLockFile)); } void TestApi::buildProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productNameOrFilePath); const QString projectFilePath = projectSubDir + QLatin1Char('/') + projectSubDir + QLatin1String(".qbs"); qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); removeBuildDir(params); ProcessResultReceiver resultReceiver; qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath, nullptr, &resultReceiver); if (resultReceiver.output.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); VERIFY_NO_ERROR(errorInfo); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); const QString productFilePath = getProductFilePath(productNameOrFilePath); if (!productFilePath.isEmpty()) { QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); QVERIFY2(QFile::remove(productFilePath), qPrintable(productFilePath)); } WAIT_FOR_NEW_TIMESTAMP(); qbs::BuildOptions options; options.setForceTimestampCheck(true); errorInfo = doBuildProject(projectFilePath, nullptr, nullptr, nullptr, options); VERIFY_NO_ERROR(errorInfo); if (!productFilePath.isEmpty()) QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::buildProject_data() { QTest::addColumn("projectSubDir"); QTest::addColumn("productNameOrFilePath"); QTest::newRow("BPs in Sources") << QString("build-properties-source") << QString("HelloWorld"); QTest::newRow("code generator") << QString("codegen") << QString("codegen"); QTest::newRow("link static libs") << QString("link-static-lib") << QString("HelloWorld"); QTest::newRow("link staticlib dynamiclib") << QString("link-staticlib-dynamiclib") << QString("app"); QTest::newRow("precompiled header new") << QString("precompiled-header-new") << QString("MyApp"); QTest::newRow("precompiled header dynamic") << QString("precompiled-header-dynamic") << QString("MyApp"); QTest::newRow("lots of dots") << QString("lots-of-dots") << QString("lots.of.dots"); QTest::newRow("Qt5 plugin") << QString("qt5-plugin") << relativeProductBuildDir("echoplugin") + '/' + qbs::Internal::HostOsInfo::dynamicLibraryName("echoplugin"); QTest::newRow("Q_OBJECT in source") << QString("moc-cpp") << QString("moc_cpp"); QTest::newRow("Q_OBJECT in header") << QString("moc-hpp") << QString("moc_hpp"); QTest::newRow("Q_OBJECT in header, moc_XXX.cpp included") << QString("moc-hpp-included") << QString("moc_hpp_included"); QTest::newRow("app and lib with same source file") << QString("lib-same-source") << QString("HelloWorldApp"); QTest::newRow("source files with the same base name but different extensions") << QString("same-base-name") << QString("basename"); QTest::newRow("simple probes") << QString("simple-probe") << QString("MyApp"); QTest::newRow("application without sources") << QString("app-without-sources") << QString("appWithoutSources"); QTest::newRow("productNameWithDots") << QString("productNameWithDots") << QString("myapp"); QTest::newRow("only default properties") << QString("two-default-property-values") << relativeProductBuildDir("two-default-property-values") + "/set"; QTest::newRow("Export item with Group") << QString("export-item-with-group") << QString("app"); QTest::newRow("QBS-728") << QString("QBS-728") << QString(); } void TestApi::buildProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productNameOrFilePath); const QString projectFilePath = projectSubDir + QLatin1Char('/') + projectSubDir + QLatin1String(".qbs"); qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); removeBuildDir(params); qbs::BuildOptions options; options.setDryRun(true); const qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath, nullptr, nullptr, nullptr, options); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!QFileInfo::exists(relativeBuildDir()), qPrintable(QDir(relativeBuildDir()) .entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System).join(", "))); } void TestApi::buildProjectDryRun_data() { return buildProject_data(); } void TestApi::buildSingleFile() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("build-single-file"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::BuildOptions options; options.setFilesToConsider(QStringList(setupParams.buildRoot() + "/compiled.cpp")); options.setActiveFileTags(QStringList("obj")); m_logSink->setLogLevel(qbs::LoggerMaxLevel); std::unique_ptr buildJob(project.buildAllProducts(options)); BuildDescriptionReceiver receiver; ProcessResultReceiver resultReceiver; connect(buildJob.get(), &qbs::BuildJob::reportProcessResult, &resultReceiver, &ProcessResultReceiver::handleProcessResult); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &receiver, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); if (resultReceiver.output.contains("mingw32_gt_pch_use_address")) QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(receiver.descriptions.count("compiling"), 2); QCOMPARE(receiver.descriptions.count("precompiling"), 1); QVERIFY2(receiver.descriptions.contains("generating generated.h"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling compiled.cpp"), qPrintable(receiver.descriptions)); } void TestApi::canonicalToolchainList() { // All the known toolchain lists should be equal QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "clang", "llvm", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "llvm", "gcc"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang-cl", "msvc"})), QStringList({"clang-cl", "msvc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "gcc"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw", "gcc"})), QStringList({"mingw", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc"})), QStringList({"gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"msvc"})), QStringList({"msvc"})); // Single names should canonicalize to the known lists QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang-cl"})), QStringList({"clang-cl", "msvc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw"})), QStringList({"mingw", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc"})), QStringList({"gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"msvc"})), QStringList({"msvc"})); // Missing some in the middle QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "llvm", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "clang", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "llvm"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc"})), QStringList({"clang", "llvm", "gcc"})); // Sorted wrong, missing some in the middle QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc", "llvm", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "mingw"})), QStringList({"mingw", "gcc"})); // Duplicates QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang", "xcode", "xcode", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc", "llvm", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "clang", "xcode", "xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "gcc", "llvm", "clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "gcc", "clang", "gcc", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "gcc", "llvm", "llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "gcc", "gcc", "mingw"})), QStringList({"mingw", "gcc"})); // Custom insanity QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "gcc", "llvm", "clang", "xcode", "insane"})), QStringList({"crazy", "insane", "xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "gcc", "llvm", "clang", "xcode", "insane", "crazy"})), QStringList({"crazy", "insane", "xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "insane", "gcc", "trade", "llvm", "clang", "xcode", "insane", "mark", "crazy"})), QStringList({"crazy", "insane", "trade", "mark", "xcode", "clang", "llvm", "gcc"})); } void TestApi::checkOutputs() { QFETCH(bool, check); qbs::SetupProjectParameters params = defaultSetupParameters("/check-outputs"); qbs::BuildOptions options; options.setForceOutputCheck(check); removeBuildDir(params); qbs::ErrorInfo errorInfo = doBuildProject("/check-outputs", nullptr, nullptr, nullptr, options); if (check) QVERIFY(errorInfo.hasError()); else VERIFY_NO_ERROR(errorInfo); } void TestApi::checkOutputs_data() { QTest::addColumn("check"); QTest::newRow("checked outputs") << true; QTest::newRow("unchecked outputs") << false; } qbs::GroupData findGroup(const qbs::ProductData &product, const QString &name) { const auto groups = product.groups(); for (const qbs::GroupData &g : groups) { if (g.name() == name) return g; } return qbs::GroupData(); } static qbs::Project::ProductSelection defaultProducts() { return qbs::Project::ProductSelectionDefaultOnly; } void TestApi::changeContent() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-editing"); std::unique_ptr job; qbs::Project project; qbs::ProjectData projectData; qbs::ProductData product; const auto resolve = [&] { job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); product = projectData.allProducts().front(); }; resolve(); QVERIFY(product.groups().size() >= 5); // Error handling: Invalid product. qbs::ErrorInfo errorInfo = project.addGroup(qbs::ProductData(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("invalid")); // Error handling: Empty group name. errorInfo = project.addGroup(product, QString()); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("empty")); WAIT_FOR_NEW_TIMESTAMP(); errorInfo = project.addGroup(product, "New Group 1"); VERIFY_NO_ERROR(errorInfo); errorInfo = project.addGroup(product, "New Group 2"); VERIFY_NO_ERROR(errorInfo); resolve(); QVERIFY(product.groups().size() >= 10); // Error handling: Group already inserted. errorInfo = project.addGroup(product, "New Group 1"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("already")); // Error handling: Add list of files with double entries. errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "file.cpp" << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("more than once"), qPrintable(errorInfo.toString())); // Add files to empty array literal. WAIT_FOR_NEW_TIMESTAMP(); qbs::GroupData group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.h" << "file.cpp"); VERIFY_NO_ERROR(errorInfo); // Error handling: Add the same file again. resolve(); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("already"), qPrintable(errorInfo.toString())); // Remove one of the newly added files again. WAIT_FOR_NEW_TIMESTAMP(); errorInfo = project.removeFiles(product, group, QStringList("file.h")); VERIFY_NO_ERROR(errorInfo); // Error handling: Try to remove the same file again. resolve(); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "file.h"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("not known"), qPrintable(errorInfo.toString())); // Error handling: Try to remove a file from a complex list. group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "existingfile2.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Remove file from product's 'files' binding. WAIT_FOR_NEW_TIMESTAMP(); errorInfo = project.removeFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); resolve(); // Add file to non-empty array literal. WAIT_FOR_NEW_TIMESTAMP(); group = findGroup(product, "Existing Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); VERIFY_NO_ERROR(errorInfo); resolve(); // Add files to list represented as a single string. WAIT_FOR_NEW_TIMESTAMP(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "newfile2.txt"); VERIFY_NO_ERROR(errorInfo); resolve(); // Add files to list represented as an identifier. WAIT_FOR_NEW_TIMESTAMP(); group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile3.txt"); VERIFY_NO_ERROR(errorInfo); resolve(); // Add files to list represented as a block of code (not yet implemented). group = findGroup(product, "Existing Group 3"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile4.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Add file to group with directory prefix. WAIT_FOR_NEW_TIMESTAMP(); group = findGroup(product, "Existing Group 4"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.txt"); VERIFY_NO_ERROR(errorInfo); resolve(); // Error handling: Add file to group with non-directory prefix. group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("prefix"), qPrintable(errorInfo.toString())); // Remove group. WAIT_FOR_NEW_TIMESTAMP(); group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.removeGroup(product, group); VERIFY_NO_ERROR(errorInfo); resolve(); // Error handling: Try to remove the same group again. errorInfo = project.removeGroup(product, group); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("does not exist"), qPrintable(errorInfo.toString())); // Add a file to a group where the file name is already matched by a wildcard. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QFile newFile("koerper.klaus"); QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString())); newFile.close(); errorInfo = project.addFiles(product, group, QStringList() << newFile.fileName()); VERIFY_NO_ERROR(errorInfo); resolve(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QCOMPARE(group.sourceArtifactsFromWildcards().size(), 1); QCOMPARE(group.sourceArtifactsFromWildcards().front().filePath(), QFileInfo(newFile).absoluteFilePath()); // Error checking: Try to remove a file that originates from a wildcard pattern. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Other group with wildcards"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "test.wildcard"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("pattern"), qPrintable(errorInfo.toString())); // Check whether building will take the added and removed cpp files into account. // This must not be moved below the re-resolving test!!! qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); BuildDescriptionReceiver rcvr; std::unique_ptr buildJob(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &rcvr, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling file.cpp")); QVERIFY(!rcvr.descriptions.contains("compiling main.cpp")); // Error handling: Try to change the project during a build. buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); errorInfo = project.addGroup(projectData.products().front(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("in progress"), qPrintable(errorInfo.toString())); waitForFinished(buildJob.get()); errorInfo = project.addGroup(projectData.products().front(), "blubb"); VERIFY_NO_ERROR(errorInfo); project = qbs::Project(); job.reset(nullptr); buildJob.reset(nullptr); removeBuildDir(setupParams); // Add a file to the top level of a product that does not have a "files" binding yet. setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir + "/project-editing/project-with-no-files.qbs")); resolve(); WAIT_FOR_NEW_TIMESTAMP(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); resolve(); rcvr.descriptions.clear(); buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &rcvr, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling main.cpp")); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); } void TestApi::commandExtraction() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("/command-extraction"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); qbs::ProductData productData = projectData.allProducts().front(); qbs::ErrorInfo errorInfo; const QString projectDirPath = QDir::cleanPath(QFileInfo(setupParams.projectFilePath()).path()); const QString sourceFilePath = projectDirPath + "/main.cpp"; // Before the first build, no rules exist. qbs::RuleCommandList commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.size(), 0); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("No rule"), qPrintable(errorInfo.toString())); qbs::BuildOptions options; options.setDryRun(true); std::unique_ptr buildJob(project.buildAllProducts(options)); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); productData = projectData.allProducts().front(); errorInfo = qbs::ErrorInfo(); // After the build, the compile command must be found. commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.size(), 1); QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())); const qbs::RuleCommand command = commands.front(); QCOMPARE(command.type(), qbs::RuleCommand::ProcessCommandType); QVERIFY(!command.executable().isEmpty()); QVERIFY(!command.arguments().empty()); } void TestApi::dependencyOnMultiplexedType() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("/dependency-on-multiplexed-type"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); const QList allProducts = projectData.allProducts(); QCOMPARE(allProducts.size(), 5); int depCount = 0; int p1Count = 0; int p2Count = 0; for (const qbs::ProductData &p : allProducts) { if (p.name() == "dep") { ++depCount; QCOMPARE(p.dependencies().size(), 0); } else if (p.name() == "p1") { ++p1Count; if (p.multiplexConfigurationId().isEmpty()) // aggregate QCOMPARE(p.dependencies().size(), 3); else QCOMPARE(p.dependencies().size(), 1); } else { QVERIFY(p.name() == "p2"); ++p2Count; QVERIFY(p.dependencies().contains("dep")); } } QCOMPARE(depCount, 1); QCOMPARE(p1Count, 3); QCOMPARE(p2Count, 1); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); } void TestApi::changeDependentLib() { qbs::ErrorInfo errorInfo = doBuildProject("change-dependent-lib"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("change-dependent-lib.qbs", "cpp.defines: [\"XXXX\"]", "cpp.defines: [\"ABCD\"]"); errorInfo = doBuildProject("change-dependent-lib"); VERIFY_NO_ERROR(errorInfo); } void TestApi::enableAndDisableProduct() { BuildDescriptionReceiver bdr; qbs::ErrorInfo errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("enable-and-disable-product.qbs"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("undefined", "'hidden'"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(bdr.descriptions.contains("linking")); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); content = projectFile.readAll(); content.replace("'hidden'", "undefined"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); } void TestApi::errorInSetupRunEnvironment() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("error-in-setup-run-environment"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); const qbs::ProductData product = project.projectData().products().front(); bool exceptionCaught = false; try { const SettingsPtr s = settings(); qbs::RunEnvironment runEnv = project.getRunEnvironment(product, qbs::InstallOptions(), QProcessEnvironment(), QStringList(), s.get()); qbs::ErrorInfo error; const QProcessEnvironment env = runEnv.runEnvironment(&error); QVERIFY(error.hasError()); QVERIFY2(error.toString().contains("trallala"), qPrintable(error.toString())); } catch (const qbs::ErrorInfo &) { exceptionCaught = true; } QVERIFY(!exceptionCaught); } void TestApi::excludedInputs() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("excluded-inputs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(job->error().toString())); QVERIFY(project.isValid()); const qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.products().size(), 2); qbs::ProductData depProduct; qbs::ProductData pProduct; for (const qbs::ProductData &p : projectData.products()) { if (p.name() == "dep") depProduct = p; else if (p.name() == "p") pProduct = p; } QVERIFY(depProduct.isValid()); QVERIFY(pProduct.isValid()); int theTagCount = 0; for (const qbs::ArtifactData &artifact : depProduct.targetArtifacts()) { if (!artifact.fileTags().contains("the_tag")) continue; ++theTagCount; QFile f(artifact.filePath()); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); const QByteArray content = f.readAll(); QVERIFY2(content.contains("the_content"), content.constData()); QCOMPARE(artifact.fileTags().contains("the_other_tag"), content.contains("the_other_content")); } QCOMPARE(theTagCount, 2); int dummyCount = 0; for (const qbs::ArtifactData &artifact : pProduct.targetArtifacts()) { QFileInfo fi(artifact.filePath()); QVERIFY2(fi.exists(), qPrintable(fi.filePath())); if (fi.fileName().startsWith("dummy")) ++dummyCount; } QCOMPARE(dummyCount, 3); } static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project &project) { qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); std::unique_ptr buildJob(project.buildAllProducts(buildOptions)); waitForFinished(buildJob.get()); return buildJob->error(); } void TestApi::disabledInstallGroup() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("disabled_install_group"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); qbs::ProductData product = projectData.allProducts().front(); const QList targets = product.targetArtifacts(); QCOMPARE(targets.size(), 1); QVERIFY(targets.front().isGenerated()); QVERIFY(targets.front().isExecutable()); QVERIFY(targets.front().isTargetArtifact()); QCOMPARE(projectData.installableArtifacts().size(), 0); QCOMPARE(product.targetExecutable(), targets.front().filePath()); } void TestApi::disabledProduct() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-product"); VERIFY_NO_ERROR(errorInfo); } void TestApi::disabledProject() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-project"); VERIFY_NO_ERROR(errorInfo); } void TestApi::disappearedWildcardFile() { const qbs::SetupProjectParameters setupParams = defaultSetupParameters("disappeared-wildcard-file/disappeared-wildcard-file.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); VERIFY_NO_ERROR(setupJob->error()); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); QVERIFY(projectData.isValid()); QList products = projectData.allProducts(); QCOMPARE(products.size(), 1); QCOMPARE(products.first().groups().size(), 1); QCOMPARE(products.first().groups().first().allFilePaths().size(), 2); std::unique_ptr buildJob(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); WAIT_FOR_NEW_TIMESTAMP(); const QString fileToRemove = QFileInfo(setupParams.projectFilePath()).path() + "/file2.txt"; QVERIFY(QFile::remove(fileToRemove)); buildJob.reset(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); QVERIFY(buildJob->error().hasError()); QVERIFY2(buildJob->error().toString().contains( tr("Source file '%1' has disappeared.") .arg(fileToRemove)), qPrintable(buildJob->error().toString())); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); VERIFY_NO_ERROR(setupJob->error()); project = setupJob->project(); projectData = project.projectData(); QVERIFY(projectData.isValid()); products = projectData.allProducts(); QCOMPARE(products.size(), 1); QCOMPARE(products.first().groups().size(), 1); QCOMPARE(products.first().groups().first().allFilePaths().size(), 1); buildJob.reset(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); } void TestApi::renamedQbsSource() { const qbs::SetupProjectParameters setupParams = defaultSetupParameters("renamed-qbs-source-file/renamed-qbs-source-file.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); VERIFY_NO_ERROR(setupJob->error()); qbs::Project project = setupJob->project(); QCOMPARE(project.projectData().allProducts().size(), 2); std::unique_ptr buildJob(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); WAIT_FOR_NEW_TIMESTAMP(); const QString oldFilePath = QFileInfo(setupParams.projectFilePath()).path() + "/the-product/the-prodduct.qbs"; const QString newFilePath = QFileInfo(setupParams.projectFilePath()).path() + "/the-product/the-product.qbs"; QVERIFY(QFile::rename(oldFilePath, newFilePath)); REPLACE_IN_FILE(setupParams.projectFilePath(), "prodduct", "product"); buildJob.reset(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); QVERIFY(buildJob->error().hasError()); QVERIFY2(buildJob->error().toString().contains( tr("Source file '%1' has disappeared.") .arg(oldFilePath)), qPrintable(buildJob->error().toString())); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); VERIFY_NO_ERROR(setupJob->error()); project = setupJob->project(); QCOMPARE(project.projectData().allProducts().size(), 2); buildJob.reset(project.buildAllProducts({})); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); } void TestApi::duplicateProductNames() { QFETCH(QString, projectFileName); const qbs::ErrorInfo errorInfo = doBuildProject("duplicate-product-names/" + projectFileName); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Duplicate product name"), qPrintable(errorInfo.toString())); } void TestApi::duplicateProductNames_data() { QTest::addColumn("projectFileName"); QTest::newRow("Names explicitly set") << QString("explicit.qbs"); QTest::newRow("Unnamed products in same file") << QString("implicit.qbs"); QTest::newRow("Unnamed products in files of the same name") << QString("implicit-indirect.qbs"); } void TestApi::emptyFileTagList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-filetag-list"); VERIFY_NO_ERROR(errorInfo); } void TestApi::emptySubmodulesList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-submodules-list"); VERIFY_NO_ERROR(errorInfo); } void TestApi::explicitlyDependsOn() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("explicitly-depends-on", &receiver); VERIFY_NO_ERROR(errorInfo); if (m_logSink->output.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QVERIFY2(receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); QFile txtFile(relativeProductBuildDir("p") + "/compiler-name.txt"); QVERIFY2(txtFile.open(QIODevice::ReadOnly), qPrintable(txtFile.errorString())); const QByteArray content = txtFile.readAll(); QCOMPARE(content, QByteArray("compiler file name: compiler")); receiver.descriptions.clear(); errorInfo = doBuildProject("explicitly-depends-on", &receiver); QVERIFY2(!receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); touch("compiler.cpp"); waitForFileUnlock(); errorInfo = doBuildProject("explicitly-depends-on", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); } void TestApi::exportSimple() { const qbs::ErrorInfo errorInfo = doBuildProject("export-simple"); VERIFY_NO_ERROR(errorInfo); } void TestApi::exportWithRecursiveDepends() { const qbs::ErrorInfo errorInfo = doBuildProject("export-with-recursive-depends"); VERIFY_NO_ERROR(errorInfo); } void TestApi::fallbackGcc() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("fallback-gcc/fallback-gcc.qbs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); VERIFY_NO_ERROR(job->error()); qbs::ProjectData project = job->project().projectData(); QVERIFY(project.isValid()); QList products = project.allProducts(); QCOMPARE(products.size(), 2); for (const qbs::ProductData &p : std::as_const(products)) { if (p.profile() == "unixProfile") { qbs::PropertyMap moduleProps = p.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"unix"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"gcc"})); QCOMPARE(QFileInfo(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString()) .completeBaseName(), QString("g++")); QCOMPARE(moduleProps.getModuleProperty("cpp", "dynamicLibrarySuffix").toString(), QString(".so")); } else { QCOMPARE(p.profile(), QString("gccProfile")); qbs::PropertyMap moduleProps = p.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList()); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"gcc"})); QCOMPARE(QFileInfo(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString()) .completeBaseName(), QString("g++")); QCOMPARE(moduleProps.getModuleProperty("cpp", "dynamicLibrarySuffix").toString(), QString()); } } } void TestApi::fileTagger() { BuildDescriptionReceiver receiver; const qbs::ErrorInfo errorInfo = doBuildProject("file-tagger/moc_cpp.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc bla.cpp"), qPrintable(receiver.descriptions)); } void TestApi::fileTagsFilterOverride() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("filetagsfilter_override"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); const qbs::ProductData product = projectData.allProducts().front(); QList installableFiles = product.installableArtifacts(); QCOMPARE(installableFiles.size(), 1); QVERIFY(installableFiles.front().installData().installFilePath().contains("habicht")); } void TestApi::generatedFilesList() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("generated-files-list"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); QCOMPARE(isEmscripten, !isNotEmscripten); const bool generatesWorkerJs = m_logSink->output.contains("generates worker.js: true"); const bool doesNotGenerateWorkerJs = m_logSink->output.contains("generates worker.js: false"); if (isEmscripten) QCOMPARE(doesNotGenerateWorkerJs, !generatesWorkerJs); else QVERIFY(!generatesWorkerJs && !doesNotGenerateWorkerJs); qbs::Project project = setupJob->project(); qbs::BuildOptions options; options.setExecuteRulesOnly(true); const std::unique_ptr buildJob(project.buildAllProducts(options)); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); const qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.products().size(), 1); const qbs::ProductData product = projectData.products().front(); QString uiFilePath; QVERIFY(product.generatedArtifacts().size() >= 6); const auto &artifacts = product.generatedArtifacts(); for (const qbs::ArtifactData &a : artifacts) { QVERIFY(a.isGenerated()); QFileInfo fi(a.filePath()); using qbs::Internal::HostOsInfo; const QStringList possibleFileNames = QStringList() << "main.cpp.o" << "main.cpp.obj" << "mainwindow.cpp.o" << "mainwindow.cpp.obj" << "moc_mainwindow.cpp" << "moc_mainwindow.cpp.o" << "moc_mainwindow.cpp.obj" << "ui_mainwindow.h" << "generated-files-list.wasm" << "generated-files-list.worker.js" << "generated-files-list.js" << "generated-files-list.html" << qbs::Internal::HostOsInfo::appendExecutableSuffix( "generated-files-list"); QVERIFY2(possibleFileNames.contains(fi.fileName()) || fi.fileName().endsWith(".plist") || fi.fileName().contains("qt_plugin_import"), qPrintable(fi.fileName())); } const auto groups = product.groups(); for (const qbs::GroupData &group : groups) { const auto artifacts = group.sourceArtifacts(); for (const qbs::ArtifactData &a : artifacts) { QVERIFY(!a.isGenerated()); QVERIFY(!a.isTargetArtifact()); if (a.fileTags().contains(QLatin1String("ui"))) { uiFilePath = a.filePath(); break; } } if (!uiFilePath.isEmpty()) break; } QVERIFY(!uiFilePath.isEmpty()); const QStringList directParents = project.generatedFiles(product, uiFilePath, false); QCOMPARE(directParents.size(), 1); const QFileInfo uiHeaderFileInfo(directParents.front()); QCOMPARE(uiHeaderFileInfo.fileName(), QStringLiteral("ui_mainwindow.h")); QVERIFY(!uiHeaderFileInfo.exists()); const QStringList allParents = project.generatedFiles(product, uiFilePath, true); if (isEmscripten) QCOMPARE(allParents.size(), generatesWorkerJs ? 5 : 4); //built with "-pthread" support else QCOMPARE(allParents.size(), 3); } void TestApi::groupVisibility() { qbs::SetupProjectParameters setupParams = defaultSetupParameters( "group-visibility/group-visibility.qbs"); std::unique_ptr job( qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::ProjectData project = job->project().projectData(); QCOMPARE(project.allProducts().size(), 1); qbs::ProductData product = project.allProducts().front(); const QList groups = product.groups(); QCOMPARE(groups.size(), 3); for (const qbs::GroupData &g : groups) { QVERIFY2( g.name().contains("should be visible") || g.name() == "group-visibility", qPrintable(g.name())); } } void TestApi::infiniteLoopBuilding() { QFETCH(QString, projectDirName); qbs::SetupProjectParameters setupParams = defaultSetupParameters(projectDirName + "/infinite-loop.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QTimer::singleShot(1000, buildJob.get(), &qbs::AbstractJob::cancel); QVERIFY(waitForFinished(buildJob.get(), testTimeoutInMsecs())); QVERIFY(buildJob->error().hasError()); } void TestApi::infiniteLoopBuilding_data() { QTest::addColumn("projectDirName"); QTest::newRow("JS Command") << QString("infinite-loop-js"); QTest::newRow("Process Command") << QString("infinite-loop-process"); QTest::newRow("Scanner (scan property)") << QString("infinite-loop-scanning-scan"); QTest::newRow("Scanner (searchPaths property)") << QString("infinite-loop-scanning-searchpaths"); } void TestApi::infiniteLoopResolving() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("infinite-loop-resolving"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); QTimer::singleShot(1000, setupJob.get(), &qbs::AbstractJob::cancel); QVERIFY(waitForFinished(setupJob.get(), testTimeoutInMsecs())); QVERIFY2(setupJob->error().toString().toLower().contains("cancel"), qPrintable(setupJob->error().toString())); } void TestApi::inheritQbsSearchPaths() { const QString projectFilePath = "inherit-qbs-search-paths/prj.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(m_workingDataDir + '/' + projectFilePath); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("qbsSearchPaths: \"subdir\"", "//qbsSearchPaths: \"subdir\""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject(projectFilePath); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'bli' not found"), qPrintable(errorInfo.toString())); QVariantMap overriddenValues; overriddenValues.insert("project.qbsSearchPaths", QStringList() << m_workingDataDir + "/inherit-qbs-search-paths/subdir"); errorInfo = doBuildProject(projectFilePath, nullptr, nullptr, nullptr, qbs::BuildOptions(), overriddenValues); VERIFY_NO_ERROR(errorInfo); } template typename T::value_type findElem(const T &list, Pred p) { const auto it = std::find_if(list.cbegin(), list.cend(), p); return it == list.cend() ? typename T::value_type() : *it; } void TestApi::installableFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("installed-artifact"); QVariantMap overriddenValues; overriddenValues.insert(QStringLiteral("qbs.installRoot"), QStringLiteral("/tmp")); setupParams.setOverriddenValues(overriddenValues); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 2); qbs::ProductData product = findElem(projectData.allProducts(), [](const qbs::ProductData &p) { return p.name() == QLatin1String("installedApp"); }); QVERIFY(product.isValid()); const QList beforeInstallableFiles = product.installableArtifacts(); QCOMPARE(beforeInstallableFiles.size(), 3); for (const qbs::ArtifactData &f : beforeInstallableFiles) { if (!QFileInfo(f.filePath()).fileName().startsWith("main")) { QVERIFY(f.isExecutable()); const auto expectedTargetFilePath = appendExecSuffix( QStringLiteral("/tmp/usr/bin/installedApp"), m_logSink->output.toLocal8Bit()); QCOMPARE(f.installData().localInstallFilePath(), expectedTargetFilePath); QCOMPARE(product.targetExecutable(), expectedTargetFilePath); break; } } setupParams = defaultSetupParameters("recursive-wildcards"); setupParams.setOverriddenValues(overriddenValues); job.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); product = projectData.allProducts().front(); const QList afterInstallableFiles = product.installableArtifacts(); QCOMPARE(afterInstallableFiles.size(), 2); for (const qbs::ArtifactData &f : afterInstallableFiles) QVERIFY(!f.isExecutable()); QCOMPARE(afterInstallableFiles.front().installData().localInstallFilePath(), QLatin1String("/tmp/dir/file1.txt")); QCOMPARE(afterInstallableFiles.last().installData().localInstallFilePath(), QLatin1String("/tmp/dir/file2.txt")); } void TestApi::isRunnable() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("is-runnable"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const QList products = project.projectData().products(); QCOMPARE(products.size(), 2); for (const qbs::ProductData &p : products) { QVERIFY2(p.name() == "app" || p.name() == "lib", qPrintable(p.name())); if (p.name() == "app") QVERIFY(p.isRunnable()); else QVERIFY(!p.isRunnable()); } } void TestApi::linkDynamicLibs() { const qbs::ErrorInfo errorInfo = doBuildProject("link-dynamiclibs"); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); if (isEmscripten) QEXPECT_FAIL(nullptr, "Emscripten does not support dynamic linking", Abort); QVERIFY(isNotEmscripten); VERIFY_NO_ERROR(errorInfo); } void TestApi::linkDynamicAndStaticLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); m_logSink->output.clear(); const qbs::ErrorInfo errorInfo = doBuildProject("link-dynamiclibs-staticlibs", &bdr, nullptr, nullptr, options); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); if (isEmscripten) QEXPECT_FAIL(nullptr, "Emscripten does not support dynamic linking", Abort); VERIFY_NO_ERROR(errorInfo); QVERIFY(isNotEmscripten); const bool isGcc = m_logSink->output.contains("is gcc: true"); const bool isNotGcc = m_logSink->output.contains("is gcc: false"); if (isNotGcc) QSKIP("The remainder of this test applies only to GCC"); QVERIFY(isGcc); // The dependent static libs should not appear in the link command for the executable. static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX "'? "); QString appLinkCmd; for (const QString &line : std::as_const(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); QVERIFY(!appLinkCmd.contains("static1")); QVERIFY(!appLinkCmd.contains("static2")); } void TestApi::linkDynamicAndObjectLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); m_logSink->output.clear(); const qbs::ErrorInfo errorInfo = doBuildProject( "link-dynamiclibs-objectlibs", &bdr, nullptr, nullptr, options); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); if (isEmscripten) QEXPECT_FAIL(nullptr, "Emscripten does not support dynamic linking", Abort); VERIFY_NO_ERROR(errorInfo); QVERIFY(isNotEmscripten); const bool isGcc = m_logSink->output.contains("is gcc: true"); const bool isNotGcc = m_logSink->output.contains("is gcc: false"); if (isNotGcc) QSKIP("The remainder of this test applies only to GCC"); QVERIFY(isGcc); // The dependent object libs should not appear in the link command for the executable. static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX "'? "); QString appLinkCmd; for (const QString &line : std::as_const(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); QVERIFY(!appLinkCmd.contains("object1")); QVERIFY(!appLinkCmd.contains("object2")); } void TestApi::linkStaticAndDynamicLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); m_logSink->output.clear(); const qbs::ErrorInfo errorInfo = doBuildProject( "link-staticlibs-dynamiclibs", &bdr, nullptr, nullptr, options); const bool isNormalUnix = m_logSink->output.contains("is normal unix: yes"); const bool isNotNormalUnix = m_logSink->output.contains("is normal unix: no"); QVERIFY2(isNormalUnix != isNotNormalUnix, qPrintable(m_logSink->output)); const bool isGcc = m_logSink->output.contains("is gcc: true"); const bool isNotGcc = m_logSink->output.contains("is gcc: false"); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); if (isEmscripten) QEXPECT_FAIL(nullptr, "Emscripten does not support dynamic linking", Abort); VERIFY_NO_ERROR(errorInfo); QVERIFY(isNotEmscripten); if (isNotGcc) QSKIP("The remainder of this test applies only to GCC"); QVERIFY(isGcc); // The dependencies libdynamic1.so and libstatic2.a must not appear in the link command for the // executable. The -rpath-link line for libdynamic1.so must be there. static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX "'? "); QString appLinkCmd; for (const QString &line : std::as_const(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); if (isNormalUnix) { const std::regex rpathLinkRex("-rpath-link=\\S*/" + relativeProductBuildDir("dynamic2").toStdString()); const auto ln = appLinkCmd.toStdString(); QVERIFY(std::regex_search(ln, rpathLinkRex)); } QVERIFY(!appLinkCmd.contains("libstatic2.a")); QVERIFY(!appLinkCmd.contains("libdynamic2.so")); } void TestApi::linkObjectAndDynamicLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); m_logSink->output.clear(); const qbs::ErrorInfo errorInfo = doBuildProject( "link-objectlibs-dynamiclibs", &bdr, nullptr, nullptr, options); const bool isNormalUnix = m_logSink->output.contains("is normal unix: yes"); const bool isNotNormalUnix = m_logSink->output.contains("is normal unix: no"); QVERIFY2(isNormalUnix != isNotNormalUnix, qPrintable(m_logSink->output)); const bool isGcc = m_logSink->output.contains("is gcc: true"); const bool isNotGcc = m_logSink->output.contains("is gcc: false"); const bool isEmscripten = m_logSink->output.contains("is emscripten: true"); const bool isNotEmscripten = m_logSink->output.contains("is emscripten: false"); if (isEmscripten) QEXPECT_FAIL(nullptr, "Emscripten does not support dynamic linking", Abort); VERIFY_NO_ERROR(errorInfo); QVERIFY(isNotEmscripten); if (isNotGcc) QSKIP("The remainder of this test applies only to GCC"); QVERIFY(isGcc); // The dependencies libdynamic1.so and object2.o must not appear in the link command for the // executable. The -rpath-link line for libdynamic1.so must be there. static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX "'? "); QString appLinkCmd; for (const QString &line : std::as_const(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); if (isNormalUnix) { const std::regex rpathLinkRex( "-rpath-link=\\S*/" + relativeProductBuildDir("dynamic2").toStdString()); const auto ln = appLinkCmd.toStdString(); QVERIFY(std::regex_search(ln, rpathLinkRex)); } QVERIFY(!appLinkCmd.contains("object2.o")); QVERIFY(!appLinkCmd.contains("libdynamic2.so")); } void TestApi::listBuildSystemFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("subprojects/toplevelproject.qbs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const auto buildSystemFiles = job->project().buildSystemFiles(); QVERIFY(buildSystemFiles.count(setupParams.projectFilePath())); QVERIFY(buildSystemFiles.count(setupParams.buildRoot() + "/subproject2/subproject2.qbs")); QVERIFY(buildSystemFiles.count(setupParams.buildRoot() + "/subproject2/subproject3/subproject3.qbs")); } void TestApi::localProfiles() { QFETCH(bool, enableProfiles); qbs::SetupProjectParameters setupParams = defaultSetupParameters("local-profiles/local-profiles.qbs"); setupParams.setOverriddenValues( {std::make_pair(QString("project.enableProfiles"), enableProfiles)}); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); QString taskDescriptions; const auto taskDescHandler = [&taskDescriptions](const QString &desc, int, qbs::AbstractJob *) { taskDescriptions += '\n' + desc; }; connect(job.get(), &qbs::AbstractJob::taskStarted, taskDescHandler); waitForFinished(job.get()); const QString error = job->error().toString(); QVERIFY2(job->error().hasError() == !enableProfiles, qPrintable(error)); if (!enableProfiles) { QVERIFY2(error.contains("does not exist"), qPrintable(error)); return; } QVERIFY2(taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions)); qbs::ProjectData project = job->project().projectData(); QList products = project.allProducts(); QCOMPARE(products.size(), 4); qbs::ProductData libMingw; qbs::ProductData libClang; qbs::ProductData appDebug; qbs::ProductData appRelease; for (const qbs::ProductData &p : std::as_const(products)) { if (p.name() == "lib") { if (p.profile() == "mingwProfile") libMingw = p; else if (p.profile() == "clangProfile") libClang = p; } else if (p.name() == "app") { const QString buildVariant = p.moduleProperties().getModuleProperty("qbs", "buildVariant").toString(); if (buildVariant == "debug") appDebug = p; else if (buildVariant == "release") appRelease = p; } } QVERIFY(libMingw.isValid()); QVERIFY((libClang.isValid())); QVERIFY(appDebug.isValid()); QVERIFY(appRelease.isValid()); QCOMPARE(appDebug.profile(), QLatin1String("mingwProfile")); QCOMPARE(appRelease.profile(), QLatin1String("mingwProfile")); qbs::PropertyMap moduleProps = libMingw.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"windows"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"mingw", "gcc"})); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), qbs::Internal::HostOsInfo::appendExecutableSuffix(QString("g++"))); } moduleProps = libClang.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"linux", "unix"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"clang", "llvm", "gcc"})); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), qbs::Internal::HostOsInfo::appendExecutableSuffix(QString("clang++"))); } moduleProps = appDebug.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("none")); moduleProps = appRelease.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("fast")); taskDescriptions.clear(); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); connect(job.get(), &qbs::AbstractJob::taskStarted, taskDescHandler); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); QVERIFY2(!taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions)); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(setupParams.projectFilePath()); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("\"clang\"", "\"gcc\""); projectFile.resize(0); projectFile.write(content); projectFile.close(); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project().projectData(); products = project.allProducts(); QCOMPARE(products.size(), 4); int clangProfiles = 0; for (const qbs::ProductData &p : std::as_const(products)) { if (p.profile() == "clangProfile") { ++clangProfiles; moduleProps = p.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), qbs::Internal::HostOsInfo::appendExecutableSuffix(QString("g++"))); } } } QCOMPARE(clangProfiles, 1); } void TestApi::localProfiles_data() { QTest::addColumn("enableProfiles"); QTest::newRow("profiles enabled") << true; QTest::newRow("profiles disabled") << false; } void TestApi::missingSourceFile() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("missing-source-file/missing-source-file.qbs"); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); m_logSink->setLogLevel(qbs::LoggerMinLevel); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::ProjectData project = job->project().projectData(); QCOMPARE(project.allProducts().size(), 1); qbs::ProductData product = project.allProducts().front(); QCOMPARE(product.groups().size(), 1); qbs::GroupData group = product.groups().front(); QCOMPARE(group.allSourceArtifacts().size(), 2); QFile::rename("file2.txt.missing", "file2.txt"); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project().projectData(); QCOMPARE(project.allProducts().size(), 1); product = project.allProducts().front(); QCOMPARE(product.groups().size(), 1); group = product.groups().front(); QCOMPARE(group.allSourceArtifacts().size(), 3); } void TestApi::mocCppIncluded() { // Initial build. qbs::ErrorInfo errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); // Touch header and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile headerFile("object.h"); QVERIFY2(headerFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(headerFile.errorString())); headerFile.write("\n"); headerFile.close(); errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); // Touch cpp file and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile cppFile("object.cpp"); QVERIFY2(cppFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(cppFile.errorString())); cppFile.write("\n"); cppFile.close(); errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); } void TestApi::multiArch() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("multi-arch"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile tph("host", s.get()); qbs::Profile hostProfile = tph.p; hostProfile.setValue("qbs.architecture", "host-arch"); qbs::Internal::TemporaryProfile tpt("target", s.get()); qbs::Profile targetProfile = tpt.p; targetProfile.setValue("qbs.architecture", "target-arch"); QVariantMap overriddenValues; overriddenValues.insert("project.hostProfile", hostProfile.name()); overriddenValues.insert("project.targetProfile", targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QCOMPARE(project.profile(), profileName()); const qbs::ProjectData projectData = project.projectData(); const QList &products = projectData.products(); QCOMPARE(products.size(), 3); QList hostProducts; QList targetProducts; for (const qbs::ProductData &p : products) { QVERIFY2(p.profile() == hostProfile.name() || p.profile() == targetProfile.name(), qPrintable(p.profile())); if (p.profile() == hostProfile.name()) hostProducts.push_back(p); else targetProducts.push_back(p); } QCOMPARE(hostProducts.size(), 2); QCOMPARE(targetProducts.size(), 1); QCOMPARE(targetProducts.front().name(), QLatin1String("p1")); QStringList hostProductNames = QStringList() << hostProducts.front().name() << hostProducts.last().name(); QCOMPARE(hostProductNames.count("p1"), 1); QCOMPARE(hostProductNames.count("p2"), 1); const QString p1HostMultiplexCfgId = hostProducts.at(0).multiplexConfigurationId(); const QString p2HostMultiplexCfgId = hostProducts.at(1).multiplexConfigurationId(); const QString p1TargetMultiplexCfgId = targetProducts.at(0).multiplexConfigurationId(); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString outputBaseDir = setupParams.buildRoot() + '/'; QFile p1HostArtifact(outputBaseDir + relativeProductBuildDir("p1", QString(), p1HostMultiplexCfgId) + "/host+target.output"); QVERIFY2(p1HostArtifact.exists(), qPrintable(p1HostArtifact.fileName())); QVERIFY2(p1HostArtifact.open(QIODevice::ReadOnly), qPrintable(p1HostArtifact.errorString())); QCOMPARE(p1HostArtifact.readAll().constData(), "host-arch"); QFile p1TargetArtifact(outputBaseDir + relativeProductBuildDir("p1", QString(), p1TargetMultiplexCfgId) + "/host+target.output"); QVERIFY2(p1TargetArtifact.exists(), qPrintable(p1TargetArtifact.fileName())); QVERIFY2(p1TargetArtifact.open(QIODevice::ReadOnly), qPrintable(p1TargetArtifact.errorString())); QCOMPARE(p1TargetArtifact.readAll().constData(), "target-arch"); QFile p2Artifact(outputBaseDir + relativeProductBuildDir("p2", QString(), p2HostMultiplexCfgId) + "/host-tool.output"); QVERIFY2(p2Artifact.exists(), qPrintable(p2Artifact.fileName())); QVERIFY2(p2Artifact.open(QIODevice::ReadOnly), qPrintable(p2Artifact.errorString())); QCOMPARE(p2Artifact.readAll().constData(), "host-arch"); const QString installRoot = outputBaseDir + relativeBuildDir() + '/' + qbs::InstallOptions::defaultInstallRoot(); std::unique_ptr installJob(project.installAllProducts(qbs::InstallOptions())); waitForFinished(installJob.get()); QVERIFY2(!installJob->error().hasError(), qPrintable(installJob->error().toString())); QFile p1HostArtifactInstalled(installRoot + "/host/host+target.output"); QVERIFY2(p1HostArtifactInstalled.exists(), qPrintable(p1HostArtifactInstalled.fileName())); QFile p1TargetArtifactInstalled(installRoot + "/target/host+target.output"); QVERIFY2(p1TargetArtifactInstalled.exists(), qPrintable(p1TargetArtifactInstalled.fileName())); QFile p2ArtifactInstalled(installRoot + "/host/host-tool.output"); QVERIFY2(p2ArtifactInstalled.exists(), qPrintable(p2ArtifactInstalled.fileName())); // Specifying the same profile twice should not result in an attempt to multiplex. overriddenValues.insert("project.targetProfile", hostProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(!setupJob->error().hasError()); QCOMPARE(int(setupJob->project().projectData().products().size()), 2); // The same, but this time attaching the properties via the product name. overriddenValues.remove(QStringLiteral("project.targetProfile")); overriddenValues.insert("products.p1.myProfiles", targetProfile.name() + ',' + targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(!setupJob->error().hasError()); QCOMPARE(int(setupJob->project().projectData().products().size()), 2); } struct ProductDataSelector { void clear() { name.clear(); qbsProperties.clear(); } bool matches(const qbs::ProductData &p) const { return name == p.name() && qbsPropertiesMatch(p); } bool qbsPropertiesMatch(const qbs::ProductData &p) const { for (auto it = qbsProperties.begin(); it != qbsProperties.end(); ++it) { if (!qbs::qVariantsEqual( it.value(), p.moduleProperties().getModuleProperty("qbs", it.key()))) return false; } return true; } QString name; QVariantMap qbsProperties; }; static qbs::ProductData takeMatchingProduct(QList &products, const ProductDataSelector &s) { qbs::ProductData result; auto it = std::find_if(products.begin(), products.end(), [&s] (const qbs::ProductData &pd) { return s.matches(pd); }); if (it != products.end()) { result = *it; products.erase(it); } return result; } void TestApi::multiplexing() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("multiplexing"); std::unique_ptr setupJob( qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QList products = project.projectData().allProducts(); qbs::ProductData product; ProductDataSelector selector; selector.name = "no-multiplexing"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-without-aggregator-2"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-with-export"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "nonmultiplex-with-export"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "nonmultiplex-exporting-aggregation"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-using-export"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "multiplex-without-aggregator-2-depend-on-non-multiplexed"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.clear(); selector.name = "multiplex-without-aggregator-4"; selector.qbsProperties["architecture"] = "C64"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "TRS-80"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-without-aggregator-4-depends-2"; selector.qbsProperties["architecture"] = "C64"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.qbsProperties["architecture"] = "TRS-80"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.clear(); selector.name = "multiplex-with-aggregator-2"; selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 0); selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 0); selector.qbsProperties["architecture"] = "Atari ST"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "multiplex-with-aggregator-2-dependent"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed-via-export1"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 4); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed-via-export2"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 3); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-aggregation-via-export"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "aggregate-with-dependencies-on-aggregation-via-export"; selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "Atari ST"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 4); QVERIFY(products.empty()); } void TestApi::newOutputArtifactInDependency() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-output-artifact-in-dependency", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); const QByteArray linkingLibString = QByteArray("linking ") + qbs::Internal::HostOsInfo::dynamicLibraryName("lib").toLatin1(); QVERIFY(!receiver.descriptions.contains(linkingLibString)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("new-output-artifact-in-dependency.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray contents = projectFile.readAll(); contents.replace("//Depends", "Depends"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); errorInfo = doBuildProject("new-output-artifact-in-dependency", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); QVERIFY(receiver.descriptions.contains(linkingLibString)); } void TestApi::newPatternMatch() { TaskReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-pattern-match", nullptr, nullptr, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.taskDescriptions.contains("Resolving"), qPrintable(m_logSink->output)); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match", nullptr, nullptr, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); WAIT_FOR_NEW_TIMESTAMP(); QFile f("test.txt"); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.close(); errorInfo = doBuildProject("new-pattern-match", nullptr, nullptr, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match", nullptr, nullptr, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); WAIT_FOR_NEW_TIMESTAMP(); f.remove(); errorInfo = doBuildProject("new-pattern-match", nullptr, nullptr, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); } void TestApi::noAssertsInRelaxedMode() { qbs::SetupProjectParameters setupParams = defaultSetupParameters( "no-asserts-in-relaxed-mode/no-asserts-in-relaxed-mode.qbs"); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); const std::unique_ptr job( qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); } void TestApi::nonexistingProjectPropertyFromProduct() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties/invalidaccessfromproduct.qbs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QEXPECT_FAIL("", "QBS-432", Abort); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::nonexistingProjectPropertyFromCommandLine() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties"); removeBuildDir(setupParams); QVariantMap projectProperties; projectProperties.insert(QStringLiteral("project.blubb"), QStringLiteral("true")); setupParams.setOverriddenValues(projectProperties); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::objC() { const qbs::ErrorInfo errorInfo = doBuildProject("objc"); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectDataAfterProductInvalidation() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-data-after-" "product-invalidation/project-data-after-product-invalidation.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts().empty()); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(project.projectData().products().size(), 1); const qbs::ProductData productAfterBulding = project.projectData().products().front(); QVERIFY(!productAfterBulding.generatedArtifacts().empty()); QFile projectFile(setupParams.projectFilePath()); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); QVERIFY(!content.isEmpty()); content.replace("\"file.cpp", "// \"file.cpp"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); QVERIFY(!project.isValid()); project = setupJob->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts() == productAfterBulding.generatedArtifacts()); buildJob.reset(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts() != productAfterBulding.generatedArtifacts()); } void TestApi::processResult() { waitForFileUnlock(); removeBuildDir(defaultSetupParameters("process-result")); QFETCH(int, expectedExitCode); QFETCH(bool, redirectStdout); QFETCH(bool, redirectStderr); QVariantMap overridden; overridden.insert("products.app-caller.argument", expectedExitCode); overridden.insert("products.app-caller.redirectStdout", redirectStdout); overridden.insert("products.app-caller.redirectStderr", redirectStderr); ProcessResultReceiver resultReceiver; const qbs::ErrorInfo errorInfo = doBuildProject("process-result", nullptr, &resultReceiver, nullptr, qbs::BuildOptions(), overridden); if (m_logSink->output.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(expectedExitCode != 0, errorInfo.hasError()); QVERIFY(resultReceiver.results.size() > 1); const qbs::ProcessResult &result = resultReceiver.results.back(); QVERIFY2(result.executableFilePath().contains("app"), qPrintable(result.executableFilePath())); QCOMPARE(expectedExitCode, result.exitCode()); QCOMPARE(expectedExitCode == 0, result.success()); QCOMPARE(result.error(), QProcess::UnknownError); struct CheckParams { CheckParams(bool r, QString f, QByteArray c, QStringList co) : redirect(r) , fileName(std::move(f)) , expectedContent(std::move(c)) , consoleOutput(std::move(co)) {} bool redirect; QString fileName; QByteArray expectedContent; const QStringList consoleOutput; }; const std::vector checkParams({ CheckParams(redirectStdout, "stdout.txt", "stdout", result.stdOut()), CheckParams(redirectStderr, "stderr.txt", "stderr", result.stdErr()) }); for (const CheckParams &p : checkParams) { QFile f(relativeProductBuildDir("app-caller") + '/' + p.fileName); QCOMPARE(f.exists(), p.redirect); if (p.redirect) { QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll(), p.expectedContent); QCOMPARE(p.consoleOutput, QStringList()); } else { QCOMPARE(p.consoleOutput.join("").toLocal8Bit(), p.expectedContent); } } } void TestApi::processResult_data() { QTest::addColumn("expectedExitCode"); QTest::addColumn("redirectStdout"); QTest::addColumn("redirectStderr"); QTest::newRow("success, no redirection") << 0 << false << false; QTest::newRow("success, stdout redirection") << 0 << true << false; QTest::newRow("failure, stderr redirection") << 1 << false << true; } void TestApi::projectInvalidation() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-invalidation"); QVERIFY(QFile::copy("project.no-error.qbs", "project-invalidation.qbs")); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.early-error.qbs", "project-invalidation.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY(project.isValid()); // Error in Loader, old project still valid. WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.late-error.qbs", "project-invalidation.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY(!project.isValid()); // Error in build data re-resolving, old project not valid anymore. } void TestApi::projectLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-locking"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr)); std::unique_ptr setupJob2(project.setupProject(setupParams, m_logSink, nullptr)); waitForFinished(setupJob2.get()); QVERIFY(setupJob2->error().hasError()); QVERIFY2(setupJob2->error().toString() .contains("Cannot start a job while another one is in progress."), qPrintable(setupJob2->error().toString())); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); } void TestApi::projectPropertiesByName() { const QString projectFile = "project-properties-by-name/project-properties-by-name.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFile); QVERIFY(errorInfo.hasError()); QVariantMap overridden; overridden.insert("project.theDefines", QStringList() << "SUB1" << "SUB2"); errorInfo = doBuildProject(projectFile, nullptr, nullptr, nullptr, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.clear(); overridden.insert("projects.subproject1.theDefines", QStringList() << "SUB1"); errorInfo = doBuildProject(projectFile, nullptr, nullptr, nullptr, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.insert("projects.subproject2.theDefines", QStringList() << "SUB2"); errorInfo = doBuildProject(projectFile, nullptr, nullptr, nullptr, qbs::BuildOptions(), overridden); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectWithPropertiesItem() { const qbs::ErrorInfo errorInfo = doBuildProject("project-with-properties-item"); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectWithProbeAndProfileItem() { const qbs::ErrorInfo errorInfo = doBuildProject("project-with-probe-and-profile-item"); VERIFY_NO_ERROR(errorInfo); } void TestApi::propertiesBlocks() { const qbs::ErrorInfo errorInfo = doBuildProject("properties-blocks"); VERIFY_NO_ERROR(errorInfo); } void TestApi::rc() { BuildDescriptionReceiver bdr; ProcessResultReceiver prr; const auto buildRc = [this, &bdr, &prr]() { bdr.descriptions.clear(); bdr.descriptionLines.clear(); prr.output.clear(); prr.results.clear(); const qbs::ErrorInfo errorInfo = doBuildProject("rc", &bdr, &prr); if (errorInfo.hasError()) qDebug() << prr.output; return errorInfo; }; const auto rcFileWasCompiled = [&bdr]() { return bdr.descriptions.contains("compiling test.rc"); }; qbs::ErrorInfo error = buildRc(); VERIFY_NO_ERROR(error); QCOMPARE(rcFileWasCompiled(), qbs::Internal::HostOsInfo::isWindowsHost()); WAIT_FOR_NEW_TIMESTAMP(); error = buildRc(); VERIFY_NO_ERROR(error); QVERIFY(!rcFileWasCompiled()); touch("subdir/rc-include.h"); error = buildRc(); VERIFY_NO_ERROR(error); QCOMPARE(rcFileWasCompiled(), qbs::Internal::HostOsInfo::isWindowsHost()); } void TestApi::referencedFileErrors() { QFETCH(bool, relaxedMode); qbs::SetupProjectParameters params = defaultSetupParameters("referenced-file-errors"); params.setDryRun(true); params.setProductErrorMode(relaxedMode ? qbs::ErrorHandlingMode::Relaxed : qbs::ErrorHandlingMode::Strict); m_logSink->setLogLevel(qbs::LoggerMinLevel); std::unique_ptr job(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(job->error().hasError() != relaxedMode, qPrintable(job->error().toString())); const qbs::Project project = job->project(); QCOMPARE(project.isValid(), relaxedMode); if (!relaxedMode) return; const QList products = project.projectData().allProducts(); QCOMPARE(products.size(), 5); for (const qbs::ProductData &p : products) QCOMPARE(p.isEnabled(), p.name() != "p5"); } void TestApi::referencedFileErrors_data() { QTest::addColumn("relaxedMode"); QTest::newRow("strict mode") << false; QTest::newRow("relaxed mode") << true; } qbs::SetupProjectParameters TestApi::defaultSetupParameters(const QString &projectFileOrDir) const { QFileInfo fi(m_workingDataDir + QLatin1Char('/') + projectFileOrDir); QString projectDirPath; QString projectFilePath; if (fi.isDir()) { projectDirPath = fi.absoluteFilePath(); projectFilePath = projectDirPath + QLatin1Char('/') + projectFileOrDir + QStringLiteral(".qbs"); } else { projectDirPath = fi.absolutePath(); projectFilePath = fi.absoluteFilePath(); } qbs::SetupProjectParameters setupParams; auto environment = QProcessEnvironment::systemEnvironment(); environment.insert("QBS_AUTOTEST_CODE_SIGNING_REQUIRED", "0"); setupParams.setEnvironment(environment); setupParams.setProjectFilePath(projectFilePath); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Strict); setupParams.setOverrideBuildGraphData(true); QDir::setCurrent(projectDirPath); setupParams.setBuildRoot(projectDirPath); const SettingsPtr s = settings(); const qbs::Preferences prefs(s.get(), profileName()); setupParams.setSearchPaths(prefs.searchPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); setupParams.setPluginPaths(prefs.pluginPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); setupParams.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); setupParams.setTopLevelProfile(profileName()); setupParams.setMaxJobCount(2); setupParams.setConfigurationName(QStringLiteral("default")); setupParams.setSettingsDirectory(settings()->baseDirectory()); return setupParams; } void TestApi::references() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("references/invalid1.qbs"); const QString projectDir = QDir::cleanPath(m_workingDataDir + "/references"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); QString errorString = job->error().toString(); QVERIFY2(errorString.contains("does not contain"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/invalid2.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); errorString = job->error().toString(); QVERIFY2(errorString.contains("contains more than one"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/valid.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData topLevelProject = job->project().projectData(); QCOMPARE(topLevelProject.subProjects().size(), 1); const QString subProjectFileName = QFileInfo(topLevelProject.subProjects().front().location().filePath()).fileName(); QCOMPARE(subProjectFileName, QString("p.qbs")); } void TestApi::relaxedModeRecovery() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("relaxed-mode-recovery"); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); if (m_logSink->errors.size() != 4) { for (const qbs::ErrorInfo &error : std::as_const(m_logSink->errors)) qDebug() << error.toString(); } QCOMPARE(m_logSink->errors.size(), 4); for (const qbs::ErrorInfo &error : std::as_const(m_logSink->errors)) { QVERIFY2(!error.toString().contains("ASSERT") && (error.toString().contains("Dependency 'blubb' not found") || error.toString().contains("Product 'p1' had errors and was disabled") || error.toString().contains("Product 'p2' had errors and was disabled")), qPrintable(error.toString())); } } void TestApi::renameProduct() { // Initial run. qbs::ErrorInfo errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("TheLib", "thelib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and don't adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); const int libNameIndex = contents.lastIndexOf("thelib"); QVERIFY(libNameIndex != -1); contents.replace(libNameIndex, 6, "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'thelib' not found"), qPrintable(errorInfo.toString())); } void TestApi::renameTargetArtifact() { // Initial run. BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); receiver.descriptions.clear(); // Rename library file name. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("the_lib", "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); } void TestApi::removeFileDependency() { qbs::ErrorInfo errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs"); VERIFY_NO_ERROR(errorInfo); QFile::remove("someheader.h"); ProcessResultReceiver receiver; errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs", nullptr, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(receiver.output.contains("someheader.h"), qPrintable(receiver.output)); } void TestApi::resolveProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productNameOrFilePath); const qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir); removeBuildDir(params); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); const QString productFilePath = getProductFilePath(productNameOrFilePath); QVERIFY2(!QFile::exists(productFilePath), qPrintable(productFilePath)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProject_data() { return buildProject_data(); } void TestApi::resolveProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productNameOrFilePath); qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir); params.setDryRun(true); removeBuildDir(params); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); const QString productFilePath = getProductFilePath(productNameOrFilePath); QVERIFY2(!QFile::exists(productFilePath), qPrintable(productFilePath)); QVERIFY(!regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProjectDryRun_data() { return resolveProject_data(); } void TestApi::restoredWarnings() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("restored-warnings"); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); // Initial resolving: Errors are new. std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(toSet(m_logSink->warnings).size(), 1); QVERIFY2( m_logSink->warnings.first().toString().contains("Superfluous version"), qPrintable(m_logSink->warnings.first().toString())); QCOMPARE(toSet(m_logSink->errors).size(), 4); for (const qbs::ErrorInfo &e : std::as_const(m_logSink->errors)) { const QString msg = e.toString(); QVERIFY2( msg.contains("Property 'blubb' is not declared") || msg.contains("this one comes from a thread") || msg.contains("Product 'theOtherProduct' had errors and was disabled") || msg.contains("Product 'theProduct' had errors and was disabled"), qPrintable(msg)); } m_logSink->warnings.clear(); m_logSink->errors.clear(); // Re-resolving with no changes: Errors come from the stored build graph. job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(toSet(m_logSink->warnings).size(), 1); QCOMPARE(toSet(m_logSink->errors).size(), 4); m_logSink->warnings.clear(); m_logSink->errors.clear(); // Re-resolving with changes: Errors come from the re-resolving, stored ones must be suppressed. QVariantMap overridenValues; overridenValues.insert("products.aThirdProduct.moreFiles", true); setupParams.setOverriddenValues(overridenValues); job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(toSet(m_logSink->warnings).size(), 1); QVERIFY2( m_logSink->warnings.first().toString().contains("Superfluous version"), qPrintable(m_logSink->warnings.first().toString())); QCOMPARE(toSet(m_logSink->errors).size(), 5); // One more for the additional group for (const qbs::ErrorInfo &e : std::as_const(m_logSink->errors)) { const QString msg = e.toString(); QVERIFY2( msg.contains("Property 'blubb' is not declared") || msg.contains("blubb.txt' does not exist") || msg.contains("this one comes from a thread") || msg.contains("Product 'theOtherProduct' had errors and was disabled") || msg.contains("Product 'theThirdProduct' had errors and was disabled") || msg.contains("Product 'theProduct' had errors and was disabled"), qPrintable(msg)); } m_logSink->warnings.clear(); m_logSink->errors.clear(); } void TestApi::restoreAndResolve() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("restore-and-resolve"); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); // Initial resolving finishes with warnings due to syntax error. std::unique_ptr resolveJob( qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(resolveJob.get()); QVERIFY2(!resolveJob->error().hasError(), qPrintable(resolveJob->error().toString())); QVERIFY(!m_logSink->errors.isEmpty()); QVERIFY(resolveJob->project().projectData().products().isEmpty()); // Fix syntax error. Next attempt at resolving still fails, because the failed file is not // in the list of build system files and therefore the default RestoreAndTrackChanges mode // cannot detect any changes. m_logSink->errors.clear(); REPLACE_IN_FILE("broken-product.qbs", "syntax error", ""); WAIT_FOR_NEW_TIMESTAMP(); resolveJob.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(resolveJob.get()); QVERIFY2(!resolveJob->error().hasError(), qPrintable(resolveJob->error().toString())); QVERIFY(!m_logSink->errors.isEmpty()); QVERIFY(resolveJob->project().projectData().products().isEmpty()); // Now force a new resolve, which should succeed. m_logSink->errors.clear(); setupParams.setRestoreBehavior(qbs::SetupProjectParameters::RestoreAndResolve); resolveJob.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(resolveJob.get()); QVERIFY2(!resolveJob->error().hasError(), qPrintable(resolveJob->error().toString())); QVERIFY(m_logSink->errors.isEmpty()); QCOMPARE(int(resolveJob->project().projectData().products().size()), 1); // Build the product. BuildDescriptionReceiver bdr; std::unique_ptr buildJob( resolveJob->project().buildAllProducts(qbs::BuildOptions())); connect( buildJob.get(), &qbs::BuildJob::reportCommandDescription, &bdr, &BuildDescriptionReceiver::handleDescription); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY2(bdr.descriptions.contains("creating dummy.txt"), qPrintable(bdr.descriptions)); buildJob.reset(nullptr); // Now force a new resolve again and verify that nothing gets rebuilt. m_logSink->errors.clear(); bdr.descriptions.clear(); resolveJob.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(resolveJob.get()); QVERIFY2(!resolveJob->error().hasError(), qPrintable(resolveJob->error().toString())); QVERIFY(m_logSink->errors.isEmpty()); QCOMPARE(int(resolveJob->project().projectData().products().size()), 1); buildJob.reset(resolveJob->project().buildAllProducts(qbs::BuildOptions())); connect( buildJob.get(), &qbs::BuildJob::reportCommandDescription, &bdr, &BuildDescriptionReceiver::handleDescription); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY2(bdr.descriptions.isEmpty(), qPrintable(bdr.descriptions)); } void TestApi::ruleConflict() { const qbs::ErrorInfo errorInfo = doBuildProject("rule-conflict"); QVERIFY(errorInfo.hasError()); const QString errorString = errorInfo.toString(); QVERIFY2(errorString.contains("conflict") && errorString.contains("pch1.h") && errorString.contains("pch2.h"), qPrintable(errorString)); } void TestApi::runEnvForDisabledProduct() { const qbs::SetupProjectParameters params = defaultSetupParameters("run-disabled-product/run-disabled-product.qbs"); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const qbs::ProjectData projectData = project.projectData(); const QList products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); qbs::RunEnvironment runEnv = project.getRunEnvironment( product, qbs::InstallOptions(), QProcessEnvironment(), QStringList(), settings().get()); qbs::ErrorInfo runError; const QProcessEnvironment env = runEnv.runEnvironment(&runError); QVERIFY2(runError.toString().contains("Cannot run disabled product 'app'"), qPrintable(runError.toString())); runError.clear(); runEnv.runTarget(QString(), QStringList(), true, &runError); QVERIFY2(runError.toString().contains("Cannot run disabled product 'app'"), qPrintable(runError.toString())); } void TestApi::softDependency() { const qbs::ErrorInfo errorInfo = doBuildProject("soft-dependency"); VERIFY_NO_ERROR(errorInfo); } void TestApi::sourceFileInBuildDir() { VERIFY_NO_ERROR(doBuildProject("source-file-in-build-dir")); qbs::SetupProjectParameters setupParams = defaultSetupParameters("source-file-in-build-dir"); const QString generatedFile = relativeProductBuildDir("theProduct") + "/generated.cpp"; QVERIFY2(regularFileExists(generatedFile), qPrintable(generatedFile)); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData projectData = job->project().projectData(); QCOMPARE(projectData.allProducts().size(), 1); const qbs::ProductData product = projectData.allProducts().front(); QCOMPARE(product.profile(), profileName()); const qbs::GroupData group = findGroup(product, "the group"); QVERIFY(group.isValid()); QCOMPARE(group.allFilePaths().size(), 1); } void TestApi::subProjects() { const qbs::SetupProjectParameters params = defaultSetupParameters("subprojects/toplevelproject.qbs"); removeBuildDir(params); // Check all three types of subproject creation, plus property overrides. qbs::ErrorInfo errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling both the project with the dependency and the one with the dependent // should not cause an error. WAIT_FOR_NEW_TIMESTAMP(); QFile f(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("condition: true", "condition: false"); f.resize(0); f.write(contents); f.close(); f.setFileName(params.buildRoot() + "/subproject2/subproject2.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: qbs.targetOS.length > 0", "condition: false"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling the project with the dependency only is an error. // This tests also whether changes in sub-projects are detected. WAIT_FOR_NEW_TIMESTAMP(); f.setFileName(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: false", "condition: true"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'testLib' not found"), qPrintable(errorInfo.toString())); } void TestApi::targetArtifactStatus_data() { QTest::addColumn("enableTagging"); QTest::newRow("tagging off") << false; QTest::newRow("tagging on") << true; QTest::newRow("tagging off again") << false; } void TestApi::targetArtifactStatus() { QFETCH(bool, enableTagging); qbs::SetupProjectParameters params = defaultSetupParameters("target-artifact-status/target-artifact-status.qbs"); params.setOverriddenValues({std::make_pair("products.p.enableTagging", enableTagging)}); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); const qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); const qbs::ProjectData projectData = project.projectData(); const QList products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); QCOMPARE(product.targetArtifacts().size(), enableTagging ? 2 : 1); } void TestApi::timeout() { QFETCH(QString, projectDirName); QFETCH(QString, cancelOutput); const auto setupParams = defaultSetupParameters(projectDirName + "/timeout.qbs"); std::unique_ptr setupJob{ qbs::Project().setupProject(setupParams, m_logSink, nullptr)}; waitForFinished(setupJob.get()); if (m_logSink->output.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); auto project = setupJob->project(); const auto products = project.projectData().products(); QList helperProducts; qbs::ProductData productUnderTest; for (const auto &product : products) { if (!product.type().contains(QLatin1String("product-under-test"))) helperProducts.append(product); else productUnderTest = product; } const std::unique_ptr buildHelpersJob{ project.buildSomeProducts(helperProducts, qbs::BuildOptions())}; QVERIFY(waitForFinished(buildHelpersJob.get(), testTimeoutInMsecs())); if (buildHelpersJob->error().hasError()) { qDebug().noquote() << buildHelpersJob->error().toString(); QFAIL("Could not build helper products"); } const std::unique_ptr buildJob(project.buildOneProduct(productUnderTest, qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get(), testTimeoutInMsecs())); QVERIFY(buildJob->error().hasError()); const auto errorString = buildJob->error().toString(); QVERIFY2(errorString.contains("cancel"), qPrintable(errorString)); QVERIFY(errorString.contains("timeout")); QVERIFY(errorString.contains(cancelOutput)); } void TestApi::timeout_data() { QTest::addColumn("projectDirName"); QTest::addColumn("cancelOutput"); QTest::newRow("JS Command") << QString("timeout-js") << QString("infinite loop"); QTest::newRow("Process Command") << QString("timeout-process") << QString("infinite-loop"); } void TestApi::toolInModule() { QVariantMap overrides({std::make_pair("qbs.installRoot", m_workingDataDir + "/tool-in-module/use-outside-project")}); qbs::SetupProjectParameters params = defaultSetupParameters("tool-in-module/use-within-project/use-within-project.qbs"); params.setOverriddenValues(overrides); std::unique_ptr setupJob( qbs::Project().setupProject(params, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); if (m_logSink->output.contains("target platform/arch differ from host platform/arch")) QSKIP("Cannot run binaries in cross-compiled build"); std::unique_ptr buildJob(setupJob->project() .buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString toolOutput = relativeProductBuildDir("user-in-project") + "/tool-output.txt"; QVERIFY2(QFile::exists(toolOutput), qPrintable(toolOutput)); params = defaultSetupParameters("tool-in-module/use-outside-project/use-outside-project.qbs"); setupJob.reset(qbs::Project().setupProject(params, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const auto project = setupJob->project(); const auto projectData = project.projectData(); const auto products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); const auto groups = product.groups(); for (const qbs::GroupData &group : groups) QVERIFY(group.name() != "thetool binary"); buildJob.reset(setupJob->project().buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString toolOutput2 = relativeProductBuildDir("user-outside-project") + "/tool-output.txt"; QVERIFY2(QFile::exists(toolOutput2), qPrintable(toolOutput2)); } void TestApi::trackAddQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("CppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", nullptr, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("CppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::trackRemoveQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); removeBuildDir(params); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("CppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("CppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", nullptr, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); } void TestApi::transformerData() { const qbs::SetupProjectParameters params = defaultSetupParameters("transformer-data/transformer-data.qbs"); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); qbs::ErrorInfo error; const qbs::ProjectTransformerData projectTData = project.transformerData(&error); QVERIFY2(!error.hasError(), qPrintable(error.toString())); QCOMPARE(projectTData.size(), 1); const qbs::ProductTransformerData productTData = projectTData.first().second; QCOMPARE(productTData.size(), 2); bool firstTransformerFound = false; bool secondTransformerFound = false; for (const qbs::TransformerData &tData : productTData) { if (tData.inputs().empty()) { firstTransformerFound = true; QCOMPARE(tData.outputs().size(), 1); QCOMPARE(QFileInfo(tData.outputs().first().filePath()).fileName(), QString("artifact1")); QCOMPARE(tData.commands().size(), 1); QCOMPARE(tData.commands().first().type(), qbs::RuleCommand::JavaScriptCommandType); } else { secondTransformerFound = true; QCOMPARE(tData.inputs().size(), 1); QCOMPARE(QFileInfo(tData.inputs().first().filePath()).fileName(), QString("artifact1")); QCOMPARE(tData.outputs().size(), 1); QCOMPARE(QFileInfo(tData.outputs().first().filePath()).fileName(), QString("artifact2")); QCOMPARE(tData.commands().size(), 1); QCOMPARE(tData.commands().first().type(), qbs::RuleCommand::JavaScriptCommandType); } } QVERIFY(firstTransformerFound); QVERIFY(secondTransformerFound); } void TestApi::transformers() { const qbs::ErrorInfo errorInfo = doBuildProject("transformers/transformers.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::typeChange() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("type-change", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("type-change.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("//", ""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject("type-change", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); } void TestApi::uic() { const qbs::ErrorInfo errorInfo = doBuildProject("uic"); VERIFY_NO_ERROR(errorInfo); } qbs::ErrorInfo TestApi::doBuildProject( const QString &projectFilePath, BuildDescriptionReceiver *buildDescriptionReceiver, ProcessResultReceiver *procResultReceiver, TaskReceiver *taskReceiver, const qbs::BuildOptions &options, const QVariantMap &overriddenValues) { qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); params.setOverriddenValues(overriddenValues); params.setDryRun(options.dryRun()); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, nullptr)); if (taskReceiver) { connect(setupJob.get(), &qbs::AbstractJob::taskStarted, taskReceiver, &TaskReceiver::handleTaskStart); } waitForFinished(setupJob.get()); if (setupJob->error().hasError()) return setupJob->error(); const std::unique_ptr buildJob(setupJob->project().buildAllProducts(options)); if (buildDescriptionReceiver) { connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, buildDescriptionReceiver, &BuildDescriptionReceiver::handleDescription); } if (procResultReceiver) { connect(buildJob.get(), &qbs::BuildJob::reportProcessResult, procResultReceiver, &ProcessResultReceiver::handleProcessResult); } waitForFinished(buildJob.get()); return buildJob->error(); } QString TestApi::getProductFilePath(const QString &productNameOrFilePath) { if (productNameOrFilePath.isEmpty()) return {}; return productNameOrFilePath.contains('/') ? productNameOrFilePath : relativeExecutableFilePath(productNameOrFilePath, m_logSink->output.toLocal8Bit()); } QTEST_MAIN(TestApi) #include "tst_api.moc" qbs-src-3.3.1/tests/auto/shared.h0000644000175100017510000003277715232633614016254 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TEST_SHARED_H #define QBS_TEST_SHARED_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REPLACE_IN_FILE(filePath, oldContent, newContent) \ do { \ QFile f((filePath)); \ QVERIFY2(f.open(QIODevice::ReadWrite), qPrintable(f.errorString())); \ QByteArray content = f.readAll(); \ const QByteArray savedContent = content; \ content.replace((oldContent), (newContent)); \ QVERIFY(content != savedContent); \ f.resize(0); \ f.write(content); \ } while (false) inline int testTimeoutInMsecs() { bool ok; int timeoutInSecs = qEnvironmentVariableIntValue("QBS_AUTOTEST_TIMEOUT", &ok); if (!ok) timeoutInSecs = 600; return timeoutInSecs * 1000; } // On Windows, it appears that a lock is sometimes held on files for a short while even after // they are closed. The likelihood for that seems to increase with the slowness of the machine. inline void waitForFileUnlock() { bool ok; int timeoutInSecs = qEnvironmentVariableIntValue("QBS_AUTOTEST_IO_GRACE_PERIOD", &ok); if (!ok) timeoutInSecs = qbs::Internal::HostOsInfo::isWindowsHost() ? 1 : 0; if (timeoutInSecs > 0) QTest::qWait(timeoutInSecs * 1000); } using SettingsPtr = std::unique_ptr; inline SettingsPtr settings() { const QString settingsDir = QLatin1String(qgetenv("QBS_AUTOTEST_SETTINGS_DIR")); return std::make_unique(settingsDir); } inline QString profileName() { const QString suiteProfile = QLatin1String( qgetenv("QBS_AUTOTEST_PROFILE_" QBS_TEST_SUITE_NAME)); if (!suiteProfile.isEmpty()) return suiteProfile; const QString profile = QLatin1String(qgetenv("QBS_AUTOTEST_PROFILE")); return !profile.isEmpty() ? profile : QLatin1String("none"); } inline QString relativeBuildDir(const QString &configurationName = QString()) { return !configurationName.isEmpty() ? configurationName : QLatin1String("default"); } inline QString relativeBuildGraphFilePath(const QString &configName = QString()) { return relativeBuildDir(configName) + QLatin1Char('/') + relativeBuildDir(configName) + QLatin1String(".bg"); } inline bool regularFileExists(const QString &filePath) { const QFileInfo fi(filePath); return fi.exists() && fi.isFile(); } inline bool directoryExists(const QString &dirPath) { const QFileInfo fi(dirPath); return fi.exists() && fi.isDir(); } struct ReadFileContentResult { QByteArray content; QString errorString; }; inline ReadFileContentResult readFileContent(const QString &filePath) { ReadFileContentResult result; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { result.errorString = file.errorString(); return result; } result.content = file.readAll(); return result; } inline QByteArray diffText(const QByteArray &actual, const QByteArray &expected) { QByteArray result; QList actualLines = actual.split('\n'); QList expectedLines = expected.split('\n'); int n = 1; while (!actualLines.isEmpty() && !expectedLines.isEmpty()) { QByteArray actualLine = actualLines.takeFirst(); QByteArray expectedLine = expectedLines.takeFirst(); if (actualLine != expectedLine) { result += QStringLiteral("%1: actual: %2\n%1:expected: %3\n") .arg(n, 2) .arg(QString::fromUtf8(actualLine)) .arg(QString::fromUtf8(expectedLine)) .toUtf8(); } n++; } auto addLines = [&result, &n] (const QList &lines) { for (const QByteArray &line : std::as_const(lines)) { result += QStringLiteral("%1: %2\n") .arg(n) .arg(QString::fromUtf8(line)) .toUtf8(); n++; } }; if (!actualLines.isEmpty()) { result += "Extra unexpected lines:\n"; addLines(actualLines); } if (!expectedLines.isEmpty()) { result += "Missing expected lines:\n"; addLines(expectedLines); } return result; } #define READ_TEXT_FILE(filePath, contentVariable) \ QByteArray contentVariable; \ { \ auto c = readFileContent(filePath); \ QVERIFY2(c.errorString.isEmpty(), \ qUtf8Printable(QStringLiteral("Cannot open file %1. %2") \ .arg(filePath, c.errorString))); \ contentVariable = std::move(c.content); \ } #define TEXT_FILE_COMPARE(actualFilePath, expectedFilePath) \ { \ READ_TEXT_FILE(actualFilePath, ba1); \ READ_TEXT_FILE(expectedFilePath, ba2); \ if (ba1 != ba2) { \ QByteArray msg = "File contents differ:\n" + diffText(ba1, ba2); \ QFAIL(msg.constData()); \ } \ } template inline QString prefixedIfNonEmpty(const T &prefix, const QString &str) { if (str.isEmpty()) return QString(); return prefix + str; } inline QString uniqueProductName(const QString &productName, const QString &multiplexConfigurationId) { return productName + prefixedIfNonEmpty(QLatin1Char('.'), multiplexConfigurationId); } inline QString relativeProductBuildDir(const QString &productName, const QString &configurationName = QString(), const QString &multiplexConfigurationId = QString()) { const QString fullName = uniqueProductName(productName, multiplexConfigurationId); QString dirName = qbs::Internal::HostOsInfo::rfc1034Identifier(fullName); const QByteArray hash = QCryptographicHash::hash(fullName.toUtf8(), QCryptographicHash::Sha1); dirName.append('.').append(hash.toHex().left(8)); return relativeBuildDir(configurationName) + '/' + dirName; } inline QString appendExecSuffix(const QString &productName, const QByteArray &output) { const QByteArray marker = "executable suffix: "; const int markerOffset = output.indexOf(marker); if (markerOffset == -1) return ".error"; const int suffixOffset = markerOffset + marker.size(); const int newlineOffset = output.indexOf('\n', suffixOffset); if (newlineOffset == -1) return ".error"; return productName + QString::fromLocal8Bit( output.mid(suffixOffset, newlineOffset - suffixOffset).trimmed()); } inline QString relativeExecutableFilePath( const QString &productName, const QByteArray &output, const QString &configName = QString()) { const auto relativeDir = relativeProductBuildDir(productName, configName) + QLatin1Char('/'); return relativeDir + appendExecSuffix(productName, output); } inline void waitForNewTimestamp(const QString &testDir) { // Waits for the time that corresponds to the host file system's time stamp granularity. if (qbs::Internal::HostOsInfo::isWindowsHost()) { QTest::qWait(1); // NTFS has 100 ns precision. Let's ignore exFAT. } else { const QString nameTemplate = testDir + "/XXXXXX"; QTemporaryFile f1(nameTemplate); if (!f1.open()) qFatal("Failed to open temp file"); const QDateTime initialTime = QFileInfo(f1).lastModified(); int totalMsPassed = 0; while (totalMsPassed <= 2000) { static const int increment = 50; QTest::qWait(increment); totalMsPassed += increment; QTemporaryFile f2(nameTemplate); if (!f2.open()) qFatal("Failed to open temp file"); if (QFileInfo(f2).lastModified() > initialTime) return; } qWarning("Got no new timestamp after two seconds, going ahead anyway. Subsequent " "test failure might not be genuine."); } } inline void touch(const QString &fn) { QFile f(fn); int s = f.size(); if (!f.open(QFile::ReadWrite)) qFatal("cannot open file %s", qPrintable(fn)); f.resize(s+1); f.resize(s); } inline void copyFileAndUpdateTimestamp(const QString &source, const QString &target) { QFile::remove(target); if (!QFile::copy(source, target)) qFatal("Failed to copy '%s' to '%s'", qPrintable(source), qPrintable(target)); touch(target); } inline QString parsedObjectSuffix(const QByteArray &output) { const QByteArray marker = "object suffix: "; const int markerOffset = output.indexOf(marker); if (markerOffset == -1) return ".fail"; const int suffixOffset = markerOffset + marker.size(); const int newlineOffset = output.indexOf('\n', suffixOffset); if (newlineOffset == -1) return ".fail"; return QString::fromLocal8Bit(output.mid(suffixOffset, newlineOffset - suffixOffset).trimmed()); } inline QString inputDirHash(const QString &dir) { return QCryptographicHash::hash(dir.toLatin1(), QCryptographicHash::Sha1).toHex().left(16); } inline QString testDataSourceDir(const QString &dir) { QDir result; QString testSourceRootDirFromEnv = QDir::fromNativeSeparators(qEnvironmentVariable("QBS_TEST_SOURCE_ROOT")); if (testSourceRootDirFromEnv.isEmpty()) { result.setPath(dir); } else { QDir testSourceRootDir(dir); while (testSourceRootDir.dirName() != "tests") testSourceRootDir = QFileInfo(testSourceRootDir, "").dir(); QString relativeDataPath = testSourceRootDir.relativeFilePath(dir); QString absoluteDataPath = QDir(testSourceRootDirFromEnv).absoluteFilePath(relativeDataPath); result.setPath(absoluteDataPath); } if (!result.exists()) qFatal("Expected data folder '%s' to be present, but it does not exist. You may set " "QBS_TEST_SOURCE_ROOT to the 'tests' folder in your qbs repository to configure " "a custom location.", qPrintable(result.absolutePath())); return result.absolutePath(); } inline QString testWorkDir(const QString &testName) { QString dir = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QBS_TEST_WORK_ROOT"))); if (dir.isEmpty()) { dir = QCoreApplication::applicationDirPath() + QStringLiteral("/../tests/auto/"); } else { if (!dir.endsWith(QLatin1Char('/'))) dir += QLatin1Char('/'); } return QDir::cleanPath(dir + testName + "/testWorkDir"); } inline bool copyDllExportHeader(const QString &srcDataDir, const QString &targetDataDir) { QFile sourceFile(srcDataDir + "/../../dllexport.h"); if (!sourceFile.exists()) return true; const QString targetPath = targetDataDir + "/dllexport.h"; QFile::remove(targetPath); return sourceFile.copy(targetPath); } #endif // Include guard. qbs-src-3.3.1/tests/auto/auto.qbs0000644000175100017510000000134215232633614016274 0ustar runnerrunnerProject { name: "Autotests" references: [ "api/api.qbs", "blackbox/blackbox-android.qbs", "blackbox/blackbox-apple.qbs", "blackbox/blackbox-baremetal.qbs", "blackbox/blackbox-clangdb.qbs", "blackbox/blackbox-examples.qbs", "blackbox/blackbox-java.qbs", "blackbox/blackbox-joblimits.qbs", "blackbox/blackbox-providers.qbs", "blackbox/blackbox-qt.qbs", "blackbox/blackbox-tutorial.qbs", "blackbox/blackbox-windows.qbs", "blackbox/blackbox.qbs", "buildgraph/buildgraph.qbs", "cmdlineparser/cmdlineparser.qbs", "language/language.qbs", "pkgconfig/pkgconfig.qbs", "tools/tools.qbs", ] } qbs-src-3.3.1/tests/tests.qbs0000644000175100017510000000300515232633614015514 0ustar runnerrunnerimport qbs.FileInfo Project { references: [ "auto/auto.qbs", "benchmarker/benchmarker.qbs", "clang-format-test/clang-format-test.qbs", "fuzzy-test/fuzzy-test.qbs", "lspclient/lspclient.qbs", ] AutotestRunner { Depends { name: "Qt.core" } Depends { name: "qbs resources" } Depends { name: "qbs_cpp_scanner" } Depends { name: "qbs_qt_scanner" } arguments: project.autotestArguments wrapper: project.autotestWrapper environment: { var env = base; env.push("QBS_INSTALL_DIR=" + FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix)); if (qbs.hostOS.contains("windows") && qbs.targetOS.contains("windows")) { var path = ""; for (var i = 0; i < env.length; ++i) { if (env[i].startsWith("PATH=")) { path = env[i].substring(5); break; } } path = Qt.core.binPath + ";" + path; var arrayElem = "PATH=" + path; if (i < env.length) env[i] = arrayElem; else env.push(arrayElem); } if (qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin")) { env.push("DYLD_FRAMEWORK_PATH=" + Qt.core.libPath); env.push("DYLD_LIBRARY_PATH=" + Qt.core.libPath); } return env; } } } qbs-src-3.3.1/tests/clang-format-test/0000755000175100017510000000000015232633614017174 5ustar runnerrunnerqbs-src-3.3.1/tests/clang-format-test/CMakeLists.txt0000644000175100017510000000014515232633614021734 0ustar runnerrunneradd_qbs_app(clang-format-test DEPENDS Qt${QT_VERSION_MAJOR}::Core SOURCES clang-format.cpp ) qbs-src-3.3.1/tests/clang-format-test/clang-format-test.qbs0000644000175100017510000000026515232633614023235 0ustar runnerrunnerQtApplication { Depends { name: "Qt.core" } files: "clang-format.cpp" cpp.cxxLanguageVersion: "c++20" cpp.minimumMacosVersion: "11.0" cpp.warningLevel: "none" } qbs-src-3.3.1/tests/clang-format-test/clang-format.cpp0000644000175100017510000004574715232633614022273 0ustar runnerrunner// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // // KEEP THIS FILE COMPILABLE TO ENSURE THAT WE TEST AGAINST VALID CODE. // // NOTE: Nice, includes are sorted #include #include #include #include #include #include #include #include static int aGlobalInt = 3; // ------------------------------------------------------------------------------------------------- // Preprocessor // ------------------------------------------------------------------------------------------------- // NOTE: Ops, preprocessor branches are not indented ("#define" vs "# define") #if defined(TEXTEDITOR_LIBRARY) #define TEXTEDITOR_EXPORT Q_DECL_EXPORT #else #define TEXTEDITOR_EXPORT Q_DECL_IMPORT #endif // ------------------------------------------------------------------------------------------------- // Macros // ------------------------------------------------------------------------------------------------- #define QTCREATOR_UTILS_EXPORT // qtcassert.h: namespace Utils { void writeAssertLocation(const char *msg) { std::printf("%s", msg); } } // namespace Utils #define QTC_ASSERT_STRINGIFY_HELPER(x) #x #define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x) #define QTC_ASSERT_STRING(cond) \ ::Utils::writeAssertLocation("\"" cond "\" in file " __FILE__ \ ", line " QTC_ASSERT_STRINGIFY(__LINE__)) // NOTE: Ops, macro definitions: are more verbose #define QTC_ASSERT(cond, action) \ if (cond) { \ } else { \ QTC_ASSERT_STRING(#cond); \ action; \ } \ do { \ } while (0) #define QTC_CHECK(cond) \ if (cond) { \ } else { \ QTC_ASSERT_STRING(#cond); \ } \ do { \ } while (0) #define QTC_GUARD(cond) ((cond) ? true : (QTC_ASSERT_STRING(#cond), false)) void lala(int foo) { Q_UNUSED(foo) Q_UNUSED(foo); QTC_ASSERT(true, return); // NOTE: Ops, extra space with QTC_ASSERT macro and return keyword QTC_ASSERT(true, return;); while (true) QTC_ASSERT(true, break); // ...but this is fine } // ------------------------------------------------------------------------------------------------- // Namespaces // ------------------------------------------------------------------------------------------------- namespace N { namespace C { struct Foo {}; struct Bar {}; namespace { class ClassInUnnamedNamespace {}; } // namespace // NOTE: Nice, namespace end comments are added/updated automatically } // namespace C struct Baz {}; } // namespace N namespace N2 {} // ------------------------------------------------------------------------------------------------- // Forward declarations // ------------------------------------------------------------------------------------------------- // NOTE: Ops, no one-liner anymore: forward declarations within namespace namespace N { struct Baz; } class SourceLocation; class SourceRange; class ClangString; QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE QT_FORWARD_DECLARE_CLASS(QTextDocument) QT_FORWARD_DECLARE_CLASS(QTextBlock); // ------------------------------------------------------------------------------------------------- // Using declarations, using directives, using alias, typedefs // ------------------------------------------------------------------------------------------------- // NOTE: OK, using directives are not sorted using namespace std; using namespace N2; using namespace N; // NOTE: Nice, using declarations are sorted using N::C::Bar; using N::C::Foo; // NOTE: OK, typedefs are not sorted typedef N::C::Foo TypedefedFoor; typedef N::C::Bar TypedefedBar; // NOTE: OK, using aliases are not sorted using AliasedFoor = N::C::Foo; using AliasedBar = N::C::Bar; // ------------------------------------------------------------------------------------------------- // Comments // ------------------------------------------------------------------------------------------------- // NOTE: OK, reflowing/wrapping of comments is turned off for now. // This is a fancy comment that might be reflowed or not or not or not or not or not or not or not or not or not. // NOTE: Nice, comments after declarations are aligned int foo; // fancy comment describing foo int superDuperFoo; // fancy comment describing superDuperFoo int lalaFoo; // fancy comment describing lalaFoo // ------------------------------------------------------------------------------------------------- // Function declarations // ------------------------------------------------------------------------------------------------- void f(); void f2() {} void f3(int parameter1, int parameter2, int parameter3); // NOTE: Ops, awkward placement of parameter list, there is no equivalent of // PenaltyBreakBeforeFirstCallParameter for parameter list void f3( int parameter1, int parameter2, int parameter3, int parameter4, int parameter5, int parameter6); void f3( int parameter1, int parameter2, int parameter3, int parameter4, int parameter5, int parameter6, int parrameter7, int p = aGlobalInt); bool operator==(N::Baz, N::Baz); template void fancyTemplateFunction(); template void variadicTemplateFunction(Type *...arg); // ------------------------------------------------------------------------------------------------- // Inside functions // ------------------------------------------------------------------------------------------------- int myfunction(int parameter1, int parameter2) { // Function calls myfunction(parameter1, parameter2); // Casts int value = 3; int z = (int) value; int a = static_cast(value + z); // Pointer/references alignment int *p = nullptr; int &r = *p; // Operators int result = parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + parameter1; // Long expressions int someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt = -1; bool condition1 = false; bool condition2 = false; // NOTE: Ops, alignment of readable, boolean and complex expressions will be reverted if (condition1 || condition2 || someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt) { return value; } // Initializer lists vector x{1, 2, 3, 4}; vector y{{}, {}, {}, {}}; new int[3]{1, 2, 3}; // Streams // NOTE: OK, there is a heuristic (endl, '\n') to wrap statements with stream operators. cout << "Hello" << parameter1 << endl << parameter2 << endl << result << endl << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt; cout << "Hello" << parameter1 << '\n' << parameter2 << '\n' << a << '\n' << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt; // ...but here not: cout << "Hello" << parameter1 << '\t' << parameter2 << '\t' << z << '\t' << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt << r; return 1; } // ------------------------------------------------------------------------------------------------- // Ternary Operator // ------------------------------------------------------------------------------------------------- bool ternary() { bool someWhatLongerName; bool someWhatLongerName2; bool isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue = false; bool isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue = false; bool yesno = true ? true : false; bool sino = isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue ? someWhatLongerName : someWhatLongerName2; bool danet = isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue ? someWhatLongerName : someWhatLongerName2; return yesno && sino && danet; } // ------------------------------------------------------------------------------------------------- // Penalty Test // ------------------------------------------------------------------------------------------------- int functionToCall(int parameter1) { return 1; } int functionToCall(int paramter1, int parameter2) { return 1; } int functionToCall(int paramter1, int parameter2, int parameter3) { return 1; } int functionToCall(int paramter1, int parameter2, int parameter3, int parameter4, int parameter5) { return 1; } int functionToCall( int paramter1, int parameter2, int parameter3, int parameter4, int parameter5, int paramete6) { return 1; } int functionToCall( int paramter1, int parameter2, int parameter3, int parameter4, int parameter5, int paramete6, int parameter6) { return 1; } bool functionToCallSt(const QString ¶mter1, const QStringList &list) { return 1; } void emitAddOutput(const QString &text, int priority) {} void emitAddOutput(const QString &text, int priority, int category) {} void penaltyTests(bool isThatTrue) { int valueX = 3; int valueY = 1; int valueZ = 1; int valueXTimesY = valueX * valueY; int unbelievableBigValue = 1000000; int unlimitedValueunbelievableBigValue = 1000000; QString arguments; QString argumentsVeryLong; const QFile::OpenMode openMode = isThatTrue ? QIODevice::ReadOnly : (QIODevice::ReadOnly | QIODevice::Text); const auto someValue10 = functionToCall(valueX, valueY, valueXTimesY); const auto someValue11 = functionToCall( valueX, valueY, valueXTimesY, unbelievableBigValue, unbelievableBigValue); const auto someValue12 = functionToCall( valueX, valueY, valueXTimesY, unbelievableBigValue, unbelievableBigValue * unbelievableBigValue, unbelievableBigValue); const auto someValue13 = functionToCall( valueX, valueY, valueXTimesY, unbelievableBigValue, functionToCall(functionToCall(valueX), functionToCall(valueY)), unbelievableBigValue); const auto someValue14WithAnOutstandingLongName = functionToCall( valueX, valueY, valueXTimesY, unbelievableBigValue, functionToCall(functionToCall(valueX), functionToCall(valueY)), unbelievableBigValue); const bool someValue20 = functionToCall(valueX, valueY, valueXTimesY) || functionToCall(3); const bool someValue21 = functionToCall(valueX, valueY, valueXTimesY) || functionToCall(valueX, valueY); emitAddOutput( QCoreApplication::tr("Starting: \"%1\" %2") .arg("/some/very/very/very/very/long/path/to/an/executable", arguments), functionToCall(3), functionToCall(3) | valueX); emitAddOutput( QCoreApplication::tr("Starting: \"%1\" %2") .arg("/some/very/very/very/very/long/path/to/an/executable", argumentsVeryLong), functionToCall(3), functionToCall(3) | unlimitedValueunbelievableBigValue | unlimitedValueunbelievableBigValue); const QString path; const bool someLongerNameNNNNNNNNNN = functionToCallSt( path, QStringList(QLatin1String("-print-env"))); } // ------------------------------------------------------------------------------------------------- // Classes and member functions // ------------------------------------------------------------------------------------------------- class Base1 {}; class Base2 {}; class MyClass : public QObject, public Base1, public Base2 { Q_OBJECT public: friend class FriendX; // for X::foo() friend class OtherFriendY; // for Y::bar() MyClass() {} MyClass(int d1) : data1(d1) {} MyClass(int d1, int d2) : data1(d1) , data2(d2) , data3(d2) {} MyClass( int initialData1, int initialData2, int initialData3, int initialData4, int initialData5, int initialData6) : data1(initialData1) , data2(initialData2) , data3(initialData3) , data4(initialData4) , data5(initialData5) , data6(initialData6) { // NOTE: Ops, manual alignment of QObject::connect() arguments is reverted // (we tend to write emitter/receiver on separate lines) connect(this, &MyClass::inlineZeroStatements, this, &MyClass::nonInlineSingleStatement); } void inlineZeroStatements() {} void inlineSingleStatement() { aGlobalInt = 2; } void inlineMultipleStatements() { aGlobalInt = 2; aGlobalInt = 3; } void nonInlineZeroStatements(); void nonInlineSingleStatement(); void nonInlineMultipleStatements(); virtual void shortVirtual(int parameter1, int parameter2, int parameter3) = 0; // NOTE: Ops, awkward placement of "= 0;" virtual void longerVirtual( int parameter1, int parameter2, int parameter3, int parameter4, int parameter5) = 0; int someGetter() const; private: int data1 = 0; int data2 = 0; int data3 = 0; int data4 = 0; int data5 = 0; int data6 = 0; }; void MyClass::nonInlineZeroStatements() {} void MyClass::nonInlineSingleStatement() { aGlobalInt = 2; } void MyClass::nonInlineMultipleStatements() { aGlobalInt = 2; aGlobalInt = 2; } template class TemplateClass {}; // ------------------------------------------------------------------------------------------------- // Enums // ------------------------------------------------------------------------------------------------- // NOTE: OK, enums: one-liner are possible enum MyEnum { SourceFiles = 0x1, GeneratedFiles = 0x2, AllFiles = SourceFiles | GeneratedFiles }; // NOTE: OK, enums: a comment breaks one-liners enum MyEnumX { OSourceFiles = 0x1 // fancy }; // NOTE: OK, enums: longer ones are wrapped enum MyOtherEnum { XSourceFiles = 0x1, XGeneratedFiles = 0x2, XAllFiles = XSourceFiles | XGeneratedFiles }; enum { Match_None, Match_TooManyArgs, Match_TooFewArgs, Match_Ok } matchType = Match_None; // NOTE: Ops, awkward placement of "= value;" at enum definition+use // ------------------------------------------------------------------------------------------------- // Lambdas // ------------------------------------------------------------------------------------------------- void takeLambda(std::function) {} void takeLambdaWithSomeLongerNameHa(std::function) {} bool UtilsFiltered(QVector, std::function) { return true; } void lambda() { auto shortLambda = []() { return 1; }; auto longLambda = []() { aGlobalInt = 3; return; }; takeLambda([]() { return true; }); takeLambda([]() { aGlobalInt = 3; return aGlobalInt; }); // NOTE: Ops, lambda: capture and parameter list should be on separate line int thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo; takeLambdaWithSomeLongerNameHa( [&]() { return thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo; }); QVector myClasses; UtilsFiltered(myClasses, [](const N::Baz &) { return 1; }); // NOTE: Ops, lambda: lambda not started on new line in if-condition if (UtilsFiltered(myClasses, [](const N::Baz &) { return 1; })) { ++aGlobalInt; } } // ------------------------------------------------------------------------------------------------- // Control flow // ------------------------------------------------------------------------------------------------- int fn(int, int, int) { return 1; } void controlFlow(int x) { int y = -1; // if if (true) fn(1, 2, 3); int value = 3; if (value) { value += value + 1; --value; } if (x == y) fn(1, 2, 3); else if (x > y) fn(1, 2, 3); else fn(1, 2, 3); if (x == y) { fn(1, 2, 3); return; } else if (x > y) { fn(1, 2, 3); } else { fn(1, 2, 3); } // switch switch (x) { case 0: ++aGlobalInt; return; case 1: fn(1, 2, 3); ++aGlobalInt; break; case 2: fn(1, 2, 3); break; default: break; } // do-while do { value += value + 1; ++value; } while (true); // for QVector myVector; for (int i = 0; i < myVector.size(); ++i) ++aGlobalInt; for (QVector::const_iterator i = myVector.begin(); i != myVector.end(); ++i) ++aGlobalInt; QVector myVectorWithLongName; for (QVector::const_iterator i = myVectorWithLongName.begin(), ei = myVectorWithLongName.end(); i != ei; ++i) { } forever { ++aGlobalInt; --aGlobalInt; } } // ------------------------------------------------------------------------------------------------- // Function declarations and calls - extreme cases // ------------------------------------------------------------------------------------------------- void extremeFunction(const char[]) {} void extremeFunction( int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter) { extremeFunction( uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter); int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue = 3; ++uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue; extremeFunction( "some super duper super duper super duper super duper super duper super duper long"); // BreakStringLiterals splits the string. extremeFunction("some super duper super duper super duper super duper super duper super duper " "super duper long"); } void extremeFunction2( int parameter1, int parameter2, int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong) { extremeFunction2( parameter1, parameter2, parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong); } void extremeFunction3( int parameter1, int parameter2, int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX) { extremeFunction3( parameter1, parameter2, parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX); } // ------------------------------------------------------------------------------------------------- // Misc // ------------------------------------------------------------------------------------------------- static Q_LOGGING_CATEGORY(log, "qtc.cpptools.builtineditordocumentprocessor", QtWarningMsg) int hello; // NOTE: Ops, awkward placement of next token after Q_LOGGING_CATEGORY (semicolon helps) // ------------------------------------------------------------------------------------------------- int main() {} #include "clang-format.moc" qbs-src-3.3.1/tests/benchmarker/0000755000175100017510000000000015232633614016126 5ustar runnerrunnerqbs-src-3.3.1/tests/benchmarker/commandlineparser.cpp0000644000175100017510000001503415232633614022340 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { static QString resolveActivity() { return "resolving"; } static QString ruleExecutionActivity() { return "rule-execution"; } static QString nullBuildActivity() { return "null-build"; } static QString allActivities() { return "all"; } CommandLineParser::CommandLineParser() = default; void CommandLineParser::parse() { QCommandLineParser parser; parser.setApplicationDescription("This tool aims to detect qbs performance regressions " "using valgrind."); parser.addHelpOption(); QCommandLineOption oldCommitOption(QStringList{"old-commit", "o"}, "The old qbs commit.", "old commit"); parser.addOption(oldCommitOption); QCommandLineOption newCommitOption(QStringList{"new-commit", "n"}, "The new qbs commit.", "new commit"); parser.addOption(newCommitOption); QCommandLineOption testProjectOption(QStringList{"test-project", "p"}, "The example project to use for the benchmark.", "project file path"); parser.addOption(testProjectOption); QCommandLineOption qbsRepoOption(QStringList{"qbs-repo", "r"}, "The qbs repository.", "repo path"); parser.addOption(qbsRepoOption); QCommandLineOption activitiesOption(QStringList{"activities", "a"}, QStringLiteral("The activities to benchmark. Possible values (CSV): %1,%2,%3,%4") .arg(resolveActivity(), ruleExecutionActivity(), nullBuildActivity(), allActivities()), "activities", allActivities()); parser.addOption(activitiesOption); QCommandLineOption thresholdOption(QStringList{"regression-threshold", "t"}, "A relative increase higher than this is considered a performance regression. " "All temporary data from running the benchmarks will be kept if that happens.", "value in per cent"); parser.addOption(thresholdOption); QCommandLineOption sequentialOption( QStringList{"sequential", "s"}, "Run the valgrind processes sequentially, rather than in parallel. This can help to " "prevent OOM situations with large test projects."); parser.addOption(sequentialOption); parser.process(*QCoreApplication::instance()); const QList mandatoryOptions = QList() << oldCommitOption << newCommitOption << testProjectOption << qbsRepoOption; for (const QCommandLineOption &o : mandatoryOptions) { if (!parser.isSet(o)) throwException(o.names().constFirst(), parser.helpText()); if (parser.value(o).isEmpty()) throwException(o.names().constFirst(), QString(), parser.helpText()); } m_oldCommit = parser.value(oldCommitOption); m_newCommit = parser.value(newCommitOption); if (m_oldCommit == m_newCommit) { throw Exception(QStringLiteral("Error parsing command line: " "'new commit' and 'old commit' must be different commits.\n%1").arg(parser.helpText())); } m_testProjectFilePath = parser.value(testProjectOption); m_qbsRepoDirPath = parser.value(qbsRepoOption); const QStringList activitiesList = parser.value(activitiesOption).split(','); m_activities = Activities(); for (const QString &activityString : activitiesList) { if (activityString == allActivities()) { m_activities = ActivityResolving | ActivityRuleExecution | ActivityNullBuild; break; } else if (activityString == resolveActivity()) { m_activities = ActivityResolving; } else if (activityString == ruleExecutionActivity()) { m_activities |= ActivityRuleExecution; } else if (activityString == nullBuildActivity()) { m_activities |= ActivityNullBuild; } else { throwException(activitiesOption.names().constFirst(), activityString, parser.helpText()); } } m_regressionThreshold = 50; if (parser.isSet(thresholdOption)) { bool ok = true; const QString rawThresholdValue = parser.value(thresholdOption); m_regressionThreshold = 10 * rawThresholdValue.toInt(&ok); if (!ok) throwException(thresholdOption.names().constFirst(), rawThresholdValue, parser.helpText()); } m_sequential = parser.isSet(sequentialOption); } void CommandLineParser::throwException(const QString &optionName, const QString &illegalValue, const QString &helpText) { const QString errorText(QStringLiteral("Error parsing command line: Illegal value '%1' " "for option '--%2'.\n%3").arg(illegalValue, optionName, helpText)); throw Exception(errorText); } void CommandLineParser::throwException(const QString &missingOption, const QString &helpText) { const QString errorText(QStringLiteral("Error parsing command line: Missing mandatory " "option '--%1'.\n%3").arg(missingOption, helpText)); throw Exception(errorText); } } // namespace qbsBenchmarker qbs-src-3.3.1/tests/benchmarker/activities.h0000644000175100017510000000307615232633614020451 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_ACTIVITY_H #define QBS_BENCHMARKER_ACTIVITY_H #include namespace qbsBenchmarker { enum Activity { ActivityResolving = 1, ActivityRuleExecution = 2, ActivityNullBuild = 4 }; Q_DECLARE_FLAGS(Activities, Activity) Q_DECLARE_OPERATORS_FOR_FLAGS(Activities) } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/valgrindrunner.h0000644000175100017510000000622315232633614021342 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKRUNNER_H #define QBS_BENCHMARKER_BENCHMARKRUNNER_H #include "activities.h" #include #include namespace qbsBenchmarker { class ValgrindResult { public: ValgrindResult(Activity a, qint64 ic, qint64 mem) : activity(a), instructionCount(ic), peakMemoryUsage(mem) {} Activity activity; qint64 instructionCount; qint64 peakMemoryUsage; }; class ValgrindRunner { public: ValgrindRunner( Activities activities, QString testProject, const QString &qbsBuildDir, const QString &baseOutputDir, bool sequential); void run(); QList results() const { return m_results; } private: void traceResolving(); void traceRuleExecution(); void traceNullBuild(); void traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif); QStringList qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const; QStringList wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const; QStringList valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const; void addToResults(const ValgrindResult &results); qint64 runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); qint64 runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); const Activities m_activities; const QString m_testProject; const QString m_qbsBinary; const QString m_baseOutputDir; const bool m_sequential; QList m_results; std::mutex m_resultsMutex; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/CMakeLists.txt0000644000175100017510000000057015232633614020670 0ustar runnerrunnerset(SOURCES activities.h benchmarker-main.cpp benchmarker.cpp benchmarker.h commandlineparser.cpp commandlineparser.h exception.h runsupport.cpp runsupport.h valgrindrunner.cpp valgrindrunner.h ) add_qbs_app(qbs_benchmarker DEPENDS Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent SOURCES ${SOURCES} ) qbs-src-3.3.1/tests/benchmarker/runsupport.h0000644000175100017510000000325215232633614020542 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_RUNSUPPORT_H #define QBS_BENCHMARKER_RUNSUPPORT_H #include #include #include QT_BEGIN_NAMESPACE class QByteArray; QT_END_NAMESPACE namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString& workingDir = QString(), QByteArray *output = nullptr, int *exitCode = nullptr); } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/runsupport.cpp0000644000175100017510000000521015232633614021071 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "runsupport.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString &workingDir, QByteArray *output, int *exitCode) { QStringList args = commandLine; const QString command = args.takeFirst(); QProcess p; if (!workingDir.isEmpty()) p.setWorkingDirectory(workingDir); p.start(command, args); if (!p.waitForStarted()) throw Exception(QStringLiteral("Process '%1' failed to start.").arg(command)); p.waitForFinished(-1); if (p.exitStatus() != QProcess::NormalExit) { throw Exception(QStringLiteral("Error running '%1': %2") .arg(command, p.errorString())); } if (exitCode) *exitCode = p.exitCode(); if (p.exitCode() != 0) { QString errorString = QStringLiteral("Command '%1' finished with exit code %2.") .arg(command).arg(p.exitCode()); const QByteArray stdErr = p.readAllStandardError(); if (!stdErr.isEmpty()) { errorString += QStringLiteral("\nStandard error output was: '%1'") .arg(QString::fromLocal8Bit(stdErr)); } throw Exception(errorString); } if (output) *output = p.readAllStandardOutput().trimmed(); } } // namespace qbsBenchmarker qbs-src-3.3.1/tests/benchmarker/commandlineparser.h0000644000175100017510000000462215232633614022006 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_COMMANDLINEPARSER_H #define QBS_BENCHMARKER_COMMANDLINEPARSER_H #include "activities.h" #include namespace qbsBenchmarker { class CommandLineParser { public: CommandLineParser(); void parse(); Activities activies() const { return m_activities; } QString oldCommit() const { return m_oldCommit; } QString newCommit() const { return m_newCommit; } QString testProjectFilePath() const { return m_testProjectFilePath; } QString qbsRepoDirPath() const { return m_qbsRepoDirPath; } int regressionThreshold() const { return m_regressionThreshold; } bool sequential() const { return m_sequential; } private: [[noreturn]] void throwException(const QString &optionName, const QString &illegalValue, const QString &helpText); [[noreturn]] void throwException(const QString &missingOption, const QString &helpText); Activities m_activities; QString m_oldCommit; QString m_newCommit; QString m_testProjectFilePath; QString m_qbsRepoDirPath; int m_regressionThreshold = 0; bool m_sequential = false; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/exception.h0000644000175100017510000000350315232633614020276 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_EXCEPTION_H #define QBS_BENCHMARKER_EXCEPTION_H #include #include namespace qbsBenchmarker { class Exception : public QException { public: explicit Exception(QString description) : m_description(std::move(description)) {} ~Exception() throw() override = default; QString description() const { return m_description; } private: void raise() const override { throw *this; } Exception *clone() const override { return new Exception(*this); } QString m_description; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/benchmarker.cpp0000644000175100017510000001327515232633614021123 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "benchmarker.h" #include "exception.h" #include "runsupport.h" #include "valgrindrunner.h" #include #include #include #include namespace qbsBenchmarker { Benchmarker::Benchmarker( Activities activities, QString oldCommit, QString newCommit, QString testProject, QString qbsRepo, bool sequential) : m_activities(activities) , m_oldCommit(std::move(oldCommit)) , m_newCommit(std::move(newCommit)) , m_testProject(std::move(testProject)) , m_qbsRepo(std::move(qbsRepo)) , m_sequential(sequential) { } Benchmarker::~Benchmarker() { if (!m_commitToRestore.isEmpty()) { try { runProcess(QStringList() << "git" << "checkout" << m_commitToRestore, m_qbsRepo); } catch (const Exception &e) { qDebug("Failed to restore original commit %s: %s", qPrintable(m_commitToRestore), qPrintable(e.description())); } } } void Benchmarker::benchmark() { rememberCurrentRepoState(); runProcess(QStringList() << "git" << "checkout" << m_oldCommit, m_qbsRepo); const QString oldQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_oldCommit; std::cout << "Building from old repo state..." << std::endl; buildQbs(oldQbsBuildDir); runProcess(QStringList() << "git" << "checkout" << m_newCommit, m_qbsRepo); const QString newQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_newCommit; std::cout << "Building from new repo state..." << std::endl; buildQbs(newQbsBuildDir); std::cout << "Now running valgrind. This can take a while." << std::endl; ValgrindRunner oldDataRetriever( m_activities, m_testProject, oldQbsBuildDir, m_baseOutputDir.path() + "/benchmark-data." + m_oldCommit, m_sequential); ValgrindRunner newDataRetriever( m_activities, m_testProject, newQbsBuildDir, m_baseOutputDir.path() + "/benchmark-data." + m_newCommit, m_sequential); if (m_sequential) { oldDataRetriever.run(); newDataRetriever.run(); } else { QFuture oldFuture = QtConcurrent::run( [&oldDataRetriever] { oldDataRetriever.run(); }); QFuture newFuture = QtConcurrent::run( [&newDataRetriever] { newDataRetriever.run(); }); oldFuture.waitForFinished(); newFuture.waitForFinished(); } const auto oldValgrindResults = oldDataRetriever.results(); for (const ValgrindResult &valgrindResult : oldValgrindResults) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.oldInstructionCount = valgrindResult.instructionCount; benchmarkResult.oldPeakMemoryUsage = valgrindResult.peakMemoryUsage; } const auto newValgrindResults = newDataRetriever.results(); for (const ValgrindResult &valgrindResult : newValgrindResults) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.newInstructionCount = valgrindResult.instructionCount; benchmarkResult.newPeakMemoryUsage = valgrindResult.peakMemoryUsage; } std::cout << "Done!" << std::endl; } void Benchmarker::rememberCurrentRepoState() { QByteArray commit; int exitCode = 0; try { runProcess(QStringList() << "git" << "symbolic-ref" << "--short" << "HEAD", m_qbsRepo, &commit, &exitCode); } catch (const Exception &) { if (exitCode == 0) { // runProcess did not throw because of the exit code. throw; } // Fallback, in case git cannot retrieve a nice symbolic name. runProcess(QStringList() << "git" << "describe" << "HEAD", m_qbsRepo, &commit); } m_commitToRestore = QString::fromLatin1(commit); } void Benchmarker::buildQbs(const QString &buildDir) const { if (!QDir::root().mkpath(buildDir)) throw Exception(QStringLiteral("Failed to create directory '%1'.").arg(buildDir)); runProcess(QStringList() << QCoreApplication::applicationDirPath() + "/qbs" << "resolve" << "config:benchmarker" << "qbs.buildVariant:profiling" << "qbs.installPrefix:''" << "-f" << m_qbsRepo + "/qbs.qbs", buildDir); runProcess(QStringList() << QCoreApplication::applicationDirPath() + "/qbs" << "build" << "config:benchmarker", buildDir); } } // namespace qbsBenchmarker qbs-src-3.3.1/tests/benchmarker/valgrindrunner.cpp0000644000175100017510000002560715232633614021704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "valgrindrunner.h" #include "exception.h" #include "runsupport.h" #include #include #include #include #include #include #include #include #include namespace qbsBenchmarker { ValgrindRunner::ValgrindRunner( Activities activities, QString testProject, const QString &qbsBuildDir, const QString &baseOutputDir, bool sequential) : m_activities(activities) , m_testProject(std::move(testProject)) , m_qbsBinary(qbsBuildDir + "/benchmarker/install-root/bin/qbs") , m_baseOutputDir(baseOutputDir) , m_sequential(sequential) { if (!QDir::root().mkpath(m_baseOutputDir)) throw Exception(QStringLiteral("Failed to create directory '%1'.").arg(baseOutputDir)); } void ValgrindRunner::run() { if (m_sequential) { if (m_activities & ActivityResolving) traceResolving(); if (m_activities & ActivityRuleExecution) traceRuleExecution(); if (m_activities & ActivityNullBuild) traceNullBuild(); return; } std::deque> futures; if (m_activities & ActivityResolving) futures.push_back(QtConcurrent::run([this]{ traceResolving(); })); if (m_activities & ActivityRuleExecution) futures.push_back(QtConcurrent::run([this]{ traceRuleExecution(); })); if (m_activities & ActivityNullBuild) futures.push_back(QtConcurrent::run([this]{ traceNullBuild(); })); while (!futures.empty()) { futures.front().waitForFinished(); futures.pop_front(); } } void ValgrindRunner::traceResolving() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.resolving.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.resolving.massif"; traceActivity(ActivityResolving, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceRuleExecution() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.rule-execution.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.rule-execution.massif"; runProcess(qbsCommandLine("resolve", buildDirCallgrind, false)); runProcess(qbsCommandLine("resolve", buildDirMassif, false)); traceActivity(ActivityRuleExecution, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceNullBuild() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.null-build.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.null-build.massif"; runProcess(qbsCommandLine("build", buildDirCallgrind, false)); runProcess(qbsCommandLine("build", buildDirMassif, false)); traceActivity(ActivityNullBuild, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif) { QString activityString; QString qbsCommand; bool dryRun = false; switch (activity) { case ActivityResolving: activityString = "resolving"; qbsCommand = "resolve"; break; case ActivityRuleExecution: activityString = "rule-execution"; qbsCommand = "build"; dryRun = true; break; case ActivityNullBuild: activityString = "null-build"; qbsCommand = "build"; break; } const QString outFileCallgrind = m_baseOutputDir + "/outfile." + activityString + ".callgrind"; const QString outFileMassif = m_baseOutputDir + "/outfile." + activityString + ".massif"; qint64 instructionCount = 0; qint64 memUsage = 0; const auto callgrindRunner = [this, qbsCommand, buildDirCallgrind, dryRun, outFileCallgrind] { return runCallgrind(qbsCommand, buildDirCallgrind, dryRun, outFileCallgrind); }; const auto massifRunner = [this, qbsCommand, buildDirMassif, dryRun, outFileMassif] { return runMassif(qbsCommand, buildDirMassif, dryRun, outFileMassif); }; if (m_sequential) { instructionCount = callgrindRunner(); memUsage = massifRunner(); } else { QFuture callGrindFuture = QtConcurrent::run(callgrindRunner); QFuture massifFuture = QtConcurrent::run(massifRunner); callGrindFuture.waitForFinished(); instructionCount = callGrindFuture.result(); massifFuture.waitForFinished(); memUsage = massifFuture.result(); } addToResults(ValgrindResult(activity, instructionCount, memUsage)); } QStringList ValgrindRunner::qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const { QStringList commandLine = QStringList() << m_qbsBinary << command << "-qq" << "-d" << buildDir << "-f" << m_testProject; if (dryRun) commandLine << "--dry-run"; return commandLine; } QStringList ValgrindRunner::wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const { return QStringList() << "valgrind" << "--smc-check=all" << "--trace-children=yes" << ("--tool=" + tool) << ("--" + tool + "-out-file=" + outFile) << commandLine; } QStringList ValgrindRunner::valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const { return wrapForValgrind(qbsCommandLine(qbsCommand, buildDir, dryRun), tool, outFile); } void ValgrindRunner::addToResults(const ValgrindResult &result) { std::lock_guard locker(m_resultsMutex); m_results.push_back(result); } qint64 ValgrindRunner::runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "callgrind", outFile)); QFile f(outFile); if (!f.open(QIODevice::ReadOnly)) { throw Exception(QStringLiteral("Failed to open file '%1': %2") .arg(outFile, f.errorString())); } while (!f.atEnd()) { const QByteArray line = f.readLine().trimmed(); static const QByteArray magicString = "summary: "; if (!line.startsWith(magicString)) continue; const QByteArray icString = line.mid(magicString.size()); bool ok; const qint64 iCount = icString.toLongLong(&ok); if (!ok) { throw Exception(QStringLiteral("Unexpected line in callgrind output file " "'%1': '%2'.") .arg(outFile, QString::fromLocal8Bit(line))); } return iCount; } throw Exception(QStringLiteral("Failed to find summary line in callgrind " "output file '%1'.").arg(outFile)); } qint64 ValgrindRunner::runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "massif", outFile)); QByteArray ms_printOutput; runProcess(QStringList() << "ms_print" << outFile, QString(), &ms_printOutput); QBuffer buffer(&ms_printOutput); buffer.open(QIODevice::ReadOnly); QByteArray peakSnapshot; const QString exceptionStringPattern = QStringLiteral("Failed to extract peak memory " "usage from file '%1': %2").arg(outFile); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine(); static const QByteArray magicString = " (peak)"; const int magicStringOffset = line.indexOf(magicString); if (magicStringOffset == -1) continue; int delimiterOffset = line.lastIndexOf(',', magicStringOffset); if (delimiterOffset == -1) delimiterOffset = line.lastIndexOf('[', magicStringOffset); if (delimiterOffset == -1) { const QString details = QStringLiteral("Failed to extract peak snapshot from " "line '%1'.").arg(QString::fromLocal8Bit(line)); throw Exception(exceptionStringPattern.arg(details)); } peakSnapshot = line.mid(delimiterOffset + 1, magicStringOffset - delimiterOffset).trimmed(); break; } if (peakSnapshot.isEmpty()) throw Exception(exceptionStringPattern.arg("No peak marker found")); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine().simplified(); if (!line.startsWith(QByteArray(peakSnapshot + ' '))) continue; const QList entries = line.split(' '); if (entries.size() != 6) { const QString details = QStringLiteral("Expected 6 entries in line '%1', but " "there are %2.").arg(QString::fromLocal8Bit(line)).arg(entries.size()); throw Exception(exceptionStringPattern.arg(details)); } QByteArray peakMemoryString = entries.at(2); peakMemoryString.replace(',', QByteArray()); bool ok; qint64 peakMemoryUsage = peakMemoryString.toLongLong(&ok); if (!ok) { const QString details = QStringLiteral("Failed to parse peak memory value '%1' " "as a number.").arg(QString::fromLocal8Bit(peakMemoryString)); throw Exception(exceptionStringPattern.arg(details)); } return peakMemoryUsage; } const QString details = QStringLiteral("Failed to find snapshot '%1'.") .arg(QString::fromLocal8Bit(peakSnapshot)); throw Exception(exceptionStringPattern.arg(details)); } } // namespace qbsBenchmarker qbs-src-3.3.1/tests/benchmarker/benchmarker-main.cpp0000644000175100017510000001205715232633614022042 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "benchmarker.h" #include "commandlineparser.h" #include "exception.h" #include #include #include using namespace qbsBenchmarker; static bool hasRegression = false; static int relativeChange(qint64 oldVal, qint64 newVal) { return newVal == 0 ? 0 : (newVal - oldVal) * 1000 / oldVal; } static QByteArray relativeChangeString(int change) { QByteArray changeString = QByteArray::number(change / 10); changeString += " % (" + QByteArray::number(change) + " ‰)"; if (change > 0) changeString.prepend('+'); return changeString; } static void printResults(Activity activity, const BenchmarkResults &results, int regressionThreshold) { std::cout << "========== Performance data for "; switch (activity) { case ActivityResolving: std::cout << "Resolving"; break; case ActivityRuleExecution: std::cout << "Rule Execution"; break; case ActivityNullBuild: std::cout << "Null Build"; break; } std::cout << " ==========" << std::endl; const BenchmarkResult result = results.value(activity); const char * const indent = " "; std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl; std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl; int change = relativeChange(result.oldInstructionCount, result.newInstructionCount); if (change > regressionThreshold) hasRegression = true; std::cout << indent << "Relative change: " << relativeChangeString(change).constData() << std::endl; std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes" << std::endl; std::cout << indent << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl; change = relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage); if (change > regressionThreshold) hasRegression = true; std::cout << indent << "Relative change: " << relativeChangeString(change).constData() << std::endl; } static void printResults(Activities activities, const BenchmarkResults &results, int regressionThreshold) { if (activities & ActivityResolving) printResults(ActivityResolving, results, regressionThreshold); if (activities & ActivityRuleExecution) printResults(ActivityRuleExecution, results, regressionThreshold); if (activities & ActivityNullBuild) printResults(ActivityNullBuild, results, regressionThreshold); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(); } catch (const Exception &e) { std::cerr << qPrintable(e.description()) << std::endl; return EXIT_FAILURE; } Benchmarker benchmarker( clParser.activies(), clParser.oldCommit(), clParser.newCommit(), clParser.testProjectFilePath(), clParser.qbsRepoDirPath(), clParser.sequential()); try { benchmarker.benchmark(); printResults(clParser.activies(), benchmarker.results(), clParser.regressionThreshold()); if (hasRegression) { benchmarker.keepRawData(); std::cout << "Performance regression detected. Raw benchmarking data available " "under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl; } } catch (const Exception &e) { benchmarker.keepRawData(); std::cerr << qPrintable(e.description()) << std::endl; std::cerr << "Build data available under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl; return EXIT_FAILURE; } } qbs-src-3.3.1/tests/benchmarker/benchmarker.h0000644000175100017510000000505715232633614020567 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKER_H #define QBS_BENCHMARKER_BENCHMARKER_H #include "activities.h" #include #include #include #include namespace qbsBenchmarker { class BenchmarkResult { public: qint64 oldInstructionCount; qint64 newInstructionCount; qint64 oldPeakMemoryUsage; qint64 newPeakMemoryUsage; }; using BenchmarkResults = QHash; class Benchmarker { public: Benchmarker( Activities activities, QString oldCommit, QString newCommit, QString testProject, QString qbsRepo, bool sequential); ~Benchmarker(); void benchmark(); void keepRawData() { m_baseOutputDir.setAutoRemove(false ); } BenchmarkResults results() const { return m_results; } QString rawDataBaseDir() const { return m_baseOutputDir.path(); } private: void rememberCurrentRepoState(); void buildQbs(const QString &buildDir) const; const Activities m_activities; const QString m_oldCommit; const QString m_newCommit; const QString m_testProject; const QString m_qbsRepo; const bool m_sequential; QString m_commitToRestore; QTemporaryDir m_baseOutputDir; BenchmarkResults m_results; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-3.3.1/tests/benchmarker/benchmarker.qbs0000644000175100017510000000141115232633614021113 0ustar runnerrunnerQtApplication { name: "qbs_benchmarker" type: "application" consoleApplication: true cpp.cxxLanguageVersion: "c++20" cpp.minimumMacosVersion: "11.0" condition: Qt.concurrent.present Depends { name: "qbsbuildconfig" } Depends { name: "Qt.concurrent" required: false } files: [ "activities.h", "benchmarker-main.cpp", "benchmarker.cpp", "benchmarker.h", "commandlineparser.cpp", "commandlineparser.h", "exception.h", "runsupport.cpp", "runsupport.h", "valgrindrunner.cpp", "valgrindrunner.h", ] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } } qbs-src-3.3.1/changelogs/0000755000175100017510000000000015232633614014615 5ustar runnerrunnerqbs-src-3.3.1/changelogs/changes-1.11.1.md0000644000175100017510000000050615232633614017265 0ustar runnerrunner# Important bugfixes * Speed up run environment setup (QTCREATORBUG-20175). * Fix qbs command line generated by the Visual Studio project generator (QBS-1303). * Install all required header files when building Qbs with qmake. * Fix undefined behavior in the qbscore library where a reference to a temporary object was stored. qbs-src-3.3.1/changelogs/changes-1.12.0.md0000644000175100017510000000355715232633614017276 0ustar runnerrunner# General * Added new module `Exporter.qbs` for creating qbs modules from products. * Added new module `Exporter.pkgconfig` for creating pkg-config metadata files. * Introduced the concept of system-level qbs settings. * Added a Makefile generator. * All command descriptions now contain the product name. # Language * The `explicitlyDependsOn` property of the `Rule` item no longer considers target artifacts of product dependencies. The new property `explicitlyDependsOnFromDependencies` can be used for that purpose. * The `excludedAuxiliaryInputs` property of the `Rule` item has been renamed to `excludedInputs`. The old name is now deprecated. * Added a new property type `varList`. * Added `FileInfo.suffix` and `FileInfo.completeSuffix`. * The deprecated JS extensions `XmlDomDocument` and `XmlDomElement` have been removed. Use `Xml.DomDocument` and `Xml.DomDocument` instead. # C/C++ Support * For MSVC static libraries, compiler-generated PDB files are now tagged as `debuginfo_cl` to make them installable. * The `cxxLanguageVersion` property can now be set to different values in different modules, and the highest value will be chosen. # Qt Support * Amalgamation builds work properly now in the presence of "mocable" files. * Fixed some redundancy on the linker command line. # Other modules * Added support for `%option outfile` and `%output` to the `lex_yacc` module. * The `vcs` module now creates the header file even if no repository is present. # Autotest support * Added an `auxiliaryInputs` property to the `AutotestRunner` item for specifying run-time dependencies of test executables. * The `AutotestRunner` item now has a `workingDirectory` property. By default, the respective test executable's location is used. # Important bug fixes * Disabled products no longer cause their exported dependencies to get pulled into the importing product (QBS-1250). qbs-src-3.3.1/changelogs/changes-1.10.1.md0000644000175100017510000000123515232633614017264 0ustar runnerrunner# Important bugfixes * Fix assertion on project loading (QBS-1275). * Fix crash when the "original" value is misused (QBS-1255). * Fix qtquickcompiler support for qml files in subdirectories (QBS-1261). * Fix constant rebuilding after moving an external header file (QBS-1285). * Fix GCC support for "bare metal" systems (QBS-1263, QBS-1265). * Fix using ids in Depends items (QBS-1264). * Fix access to module instances in dependency parameters (QBS-1253). * Fix race condition when creating Inno Setup, NSIS, or WiX installers. * Fix release builds for Android with NDK r12 and above (QBS-1256). * Fix parametrized dependencies in Export and Module items (QBS-1287). qbs-src-3.3.1/changelogs/changes-1.19.0.md0000644000175100017510000000471415232633614017301 0ustar runnerrunner# General * New codesign module was added to implement code signing for Apple, Android and Windows platforms (QBS-899, QBS-1546). * It is now possible to build Qbs with Qt 6. * Project files update API depending on the Qt.gui module was removed. This allows to enable project files update API unconditionally when building Qbs. * Convenience items such as Application, DynamicLibrary and StaticLibrary now properly install artifacts when multiplexing. # C/C++ Support * Qbs now supports multiple MSVC compiler versions installed in one Visual Studio installation (QBS-1498). Also, multiple compiler versions are properly detected by qbs setup-toolchains. * It is now possible to specify Windows SDK version for the MSVC and clang-cl toolchains via the new cpp.windowsSdkVersion property. * baremetal: Fix generation of compiler listing files with custom extension for the SDCC compiler. * baremetal: Fix generation of compiler listing files for the ARMCC compiler. * baremetal: Fix detection for Keil toolchains. * baremetal: Add support for HCS08 architectures to SDCC and IAR toolchains (QBS-1631, QBS-1629). * baremetal: Add support for HCS12 architectures to GCC and IAR toolchains (QBS-1630, QBS-1550). # Qt Support * Fix possible command line length issue with qmlimportscanner (QBS-1633). * Fix accessing binaries from libexec for Qt 6.1 and above (QBS-1636). # Android Support * Added a workaround for the Qt.Network module dependencies for 5.15.0 < Qt < 5.15.3 (QTBUG-87288) * Fix aapt command invocation on Windows. * Added support for ndk 22.1.7171670. # Documentation * Added How-To about codesigning on Apple platforms. * Cocoa Touch Application example is brought up-to date to use modern Apple practices. * Added example how to use the cpp.linkerVariant property. * Added missing documentation for the cpp.toolchainInstallPath property. * Added missing documentation for the supported 'bare-metal' architectures. # Important Bug Fixes * Added support for Xcode 12.5 (QBS-1644). * Fix support for Python 3.9 for building Apple DMG images (QBS-1642). # Infrastructure * Ubuntu Focal image was updated to use Qt 5.15.2 and Qbs 1.17.1. * Added automated tests for Qt 6 for macOS, Linux and Windows. * Added a self-hosted runner to run 'bare-metal' tests on Windows. # Contributors * Andrey Filipenkov * Denis Shienkov * Christian Kandeler * Jan Blackquill * Jake Petroules * Ivan Komissarov * Max Bespalov * Mitch Curtis * Orgad Shaneh * Raphaël Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-1.20.0.md0000644000175100017510000000410115232633614017257 0ustar runnerrunner# General * CMake and Qbs builds now fully support building with Qt6. * Qbs now prints the old properties set when refusing to build a project with changed properties. * Added convenience command to qbs-config to add a profile in one go instead of setting properties separately (QTCREATORBUG-25463). * Added profiling timer for module providers. # C/C++ Support * Added support for the COSMIC COLDFIRE (also known as M68K) compiler (QBS-1648). * Added support for the COSMIC HCS08 compiler (QBS-1641). * Added support for the COSMIC HCS12 compiler (QBS-1640). * Added support for the COSMIC STM8 compiler (QBS-1639). * Added support for the COSMIC STM32 compiler (QBS-1638). * Added support for the new Digital Mars toolchain (QBS-1636). * The new cpp.enableCxxLanguageMacro property was added for the MSVC toolchain that controls the /Zc:__cplusplus required for proper support of the new C++ standards (QBS-1655). * Added support for the "c++20" language version for the MSVC toolchain which results in adding the /std:c++latest flag (QBS-1656). # Qt Support * Consider "external" modules * Fix support for qml binaries that were moved to the libexec directory in Qt 6.2 (QBS-1636). # Android Support * Added option to use dex compiler d8 instead of dx. * Ministro support was removed. * Fix link with static stl on Android (QBS-1654) * The default Android Asset Packaging Tool was change from aapt to aapt2. # Apple Support * Qbs now uses embedded build specs from Xcode 12.4 when bundle.useXcodeBuildSpecs is true instead of older specs from Xcode 9.2. # Important Bug Fixes * Fix handling cpp.linkerWrapper with the MSVC toolchain (QBS-1653). # Infrastructure * Windows-only tests are moved to a separate tst_blackbox_windows binary. * Qbs was updated to 1.18.2 in Docker images as well as in GitHub actions jobs. * Added Qbs build and tests with the MinGW toolchain. * Added CMake build with Qt6 on Linux. # Contributors * Christian Kandeler * Denis Shienkov * Eike Ziller * Ivan Komissarov * Jan Blackquill * Mitch Curtis * Oswald Buddenhagen * Raphaël Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-1.24.1.md0000644000175100017510000000023015232633614017263 0ustar runnerrunner# C/C++ Support Fix macros and include paths retrieval for IAR # Build System Add fix for cmake >= 3.18 # Contributors * Denis Shienkov * Eike Ziller qbs-src-3.3.1/changelogs/changes-1.20.1.md0000644000175100017510000000055515232633614017271 0ustar runnerrunner# General * Fixed target linker flags on FreeBSD (QBS-1312). * Fixed file time precision on FreeBSD. * Added additional logging to the Qt module provider when no qmakes were found. * Some fixes to CMake build. * Fixed incorrect usage of the qmlcachegen binary (QBS-1676). # Android Support * Added stripping for release builds. * Fix generation of aab packages. qbs-src-3.3.1/changelogs/changes-2.0.1.md0000644000175100017510000000133215232633614017202 0ustar runnerrunner# General * Fixed crash when importing missing JavaScript file (QBS-1730). # C/C++ Support * Fixed building applications with mingw toolchain and Qt6 (QBS-1724). # Apple Support * Added support for Xcode 14.3. * Fixed codesigning on macOS (QBS-1722). * Fixed detecting Xcode via xcode-select tool. # Qt Support * Fixed support for Qt 6.3 on iOS. * Fixed install-qt.sh to properly support Qt for iOS. * Do not setup Qt in qbspkgconfig when cross compiling (QBS-1717). # Build System * Fixed qbsbuildconfig module. * Fixed build with Qt6.5. * Updated CI to test via Qt 6.5 on macOS and Windows. * Updated CI to test via Xcode 14.2 on macOS. # Contributors * Björn Schäpers * Christian Kandeler * Ivan Komissarov * Kai Dohmen qbs-src-3.3.1/changelogs/changes-2.0.2.md0000644000175100017510000000054515232633614017210 0ustar runnerrunner# General * Fixed handling of non-string exceptions (QBS-1734). * Fixed Utilities.versionCompare() for four-segment versions numbers (QBS-1733). # Qt Support * Added special handling for unclean paths in prl files (QBS-1732). * Fixed support for static plugins and Qt >= 6.5 (QBS-1732). # Contributors * Christian Kandeler * Ivan Komissarov * Leon Buckel qbs-src-3.3.1/changelogs/changes-1.14.1.md0000644000175100017510000000023415232633614017266 0ustar runnerrunner# Important bugfixes * Qt support: Fix static builds on Windows (QBS-1465). * Qt support: Fix static builds with Qt >= 5.13.1. * Darwin: Adapt to Xcode 11. qbs-src-3.3.1/changelogs/changes-2.0.0.md0000644000175100017510000000111315232633614017176 0ustar runnerrunner# General * Switched JavaScript engine from QtScript to QuickJS * Removed the long-deprecated loadFile() and loadExtension() functions * Removed the qmake project files # Qt support * Adapt to androiddeployqt on Windows no longer accepting tool paths without suffix in 6.4 (QTBUG-111558) # BareMetal support * Added support for HPPA architectures # Other modules * Renamed "name" to "appName" in the freedesktop module to prevent clash with built-in property # Infrastructure * Added USBSAN CI job # Contributors * Christian Kandeler * Ivan Komissarov * Orgad Shaneh * Pino Toscano qbs-src-3.3.1/changelogs/changes-2.5.0.md0000644000175100017510000000302015232633614017202 0ustar runnerrunner# Language * `Product` items can now contain `Scanner` items. * `Group` items can now contain other items, namely `Depends`, `FileTagger`, `Rule`, and `Scanner`. * `Group` items can now act like `Properties` items. Top-level properties can be set via the `product` and `module` prefixes, respectively. * The conditions of `Properties` items can now overlap, allowing more than one such item to contribute to the value of list properties. * The "else case" semantics for `Properties` items is now deprecated. Instead, `Properties` items can be marked as containing fallback values by giving them a condition with the special value `undefined`. * The conditions of `Properties` items now default to `true`. * Introduced the special `module` variable for `Module` items, which acts like `product` in `Product` items. * Resolving values of path properties in `Export` items relative to the exporting product's location is now deprecated. # C/C++ Support * Added support for C++20 modules. # Android support * Added new properties `Android.sdk.d8Desugaring` and `Android.sdk.extraResourcePackages`. # Qt Support * Added new property `Qt.core.translationsPath`. * Adapted to changes in framework releases (QBS-1816). # Other * Added experimental WebAssembly support via emscripten. * The `freedesktop` module now supports localization and deployment of more than one icon. * The JSON API now supports renaming files. # Contributors * Aaron McCarthy * Christian Kandeler * Danya Patrushev * Ivan Komissarov * Leon Buckel * Roman Telezhynskyi qbs-src-3.3.1/changelogs/changes-1.15.0.md0000644000175100017510000000327715232633614017300 0ustar runnerrunner# General * Added a session command which offers a JSON-based API for interaction with other tools via stdin/ stdout. This allows for proper Qbs support in IDEs that do not use Qt or even C++. # Language * Probes are now evaluated before Profile items and can be used to create profiles on project level. * AutotestRunner got a separate job pool. * Added a timeout property to Command, JavaScriptCommand and AutotestRunner. This allows to identify and kill stuck commands. # C/C++ Support * Ensure proper support of Xcode 11. * Linker map files can be generated with all toolchains. * Bare metal toolchains can now generate listing files. * Improve the command line output filtering of bare metal toolchains. * Added support for clang in mingw mode on Windows. * Added msp430 support to GCC and IAR. * Added STM8 support to IAR and SDCC. * Added IDE project generators for IAR Embedded Workbench for ARM, AVR, 8051, MSP430, and STM8 architectures. * Added IDE project generators for KEIL uVision v4 for ARM and 8051 architectures. * Added more bare metal project examples for various target platforms. * The IAR, KEIL and SDCC toolchains are now found automatically in various. locations by the setup-toolchains command and by probes if no installPath is set in the profile. # Infrastructure * Automated build and testing on Ubuntu, macOS and Windows. * Added Ubuntu bionic Docker image which replaces Debian stretch. * Updated Qt in the Ubuntu and Windows Docker images to 5.12. * When building Qbs, Qt libraries can now be bundled on Linux, macOS and Windows. # Contributors * Alberto Mardegan * Christian Kandeler * Denis Shienkov * Ivan Komissarov * Jochen Ulrich * Joerg Bornemann * Richard Weickelt qbs-src-3.3.1/changelogs/changes-2.6.0.md0000644000175100017510000000242115232633614017207 0ustar runnerrunner# General * Command descriptions are now printed with the product name as the prefix instead of the suffix. * When building only specific products via the `-p` option, dependent products are not necessarily built in their entirety anymore. Instead, only the artifacts required for the requested products are built. * ConanfileProbe now supports Conan 2 and QbsDeps generator. # Language * Added new `Rule` property `auxiliaryInputsFromDependencies`. * The `Rule` property `explicitlyDependsOnFromDependencies` now matches all artifacts from the dependencies, not just target artifacts. * The version requirement in a `Depends` item is now checked earlier, fixing the problem that a non-matching version of a library could break project resolving if it was found before the matching version. # API * Added a mode that loads a build graph followed by a forced re-resolve. * In IDE mode, messages of type "error" instead of "warning" are now emitted for errors that would stop the build in non-IDE mode (QBS-1818). # Darwin support * Added privacy manifest support for frameworks (QBS-1812). # Qt Support * Added `lupdate` support via the new `QtLupdateRunner` item (QBS-486). # Contributors * Christian Kandeler * Ivan Komissarov * Marcus Tillmanns * Orgad Shaneh * Turkaev Usman qbs-src-3.3.1/changelogs/changes-1.24.0.md0000644000175100017510000000045315232633614017271 0ustar runnerrunner# General * Users can now control if and when warnings for deprecated properties are emitted. * Added FileInfo.executableSuffix(). # Qt Support * Minimum windows version is now 10.0, like for cmake and qmake. # Contributors * Christian Kandeler * Ivan Komissarov * Petr Mikhalicin * Raphael Cotty qbs-src-3.3.1/changelogs/changes-1.18.2.md0000644000175100017510000000171615232633614017301 0ustar runnerrunner# C/C++ Support * qbs-setup-toolchains is now able to detect clang-cl properly * The Library and Include probes take more paths into account on Linux to better support containerization systems such as Flatpak. * Xcode autodetection now uses xcode-select to find Xcode on the system. # Protocol Buffers Support (Protobuf Module) * A missing nanopb generator file extension on windows has been added. * The problem that property _libraryName was incorrect when protobuf was not found has been fixed. # Android Support * An assertion when building Android applications using additional java classes with native methods has been fixed (QBS-1628). # Qt Support * A problem related to handling Qt6EntryPoint in the Qt module provider has been fixed. # Infrastructure * A Qt4 docker image for basic testing has been added. # Contributors * Christian Kandeler * Eike Ziller * Ivan Komissarov * Jan Blackquill * Kai Dohmen * Raphaël Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-1.8.00000644000175100017510000000317015232633614016613 0ustar runnerrunnerFeatures: * General: * It is no longer strictly required to provide a profile. * Sub-second timestamp resolutions are now supported on Unix systems. * Added a convenient replacement for product.moduleProperty("module", "property"), namely product.module.property. * The loadFile and loadExtension functions are deprecated in favor of the new require function, which accepts arguments of either form accepted by the deprecated functions. * Added new tool qbs-create-project to set up a new qbs project from an existing source tree. * FileTagger items can now have conditions. * Probe items can now appear directly under a Project item. * Cpp module: * Added support for QNX and the QCC toolchain * Added the cpp.useRPathLink property to control whether to use the -rpath-link linker option. * Provided the means to easily combine source files for the C language family in order to support "amalgamation builds". * Introduced cpp.treatSystemHeadersAsDependencies. * Qt modules: * Introduced property Qt.core.combineMocOutput. * Introduced Qt.core.enableKeywords for simple disabling of the "signals", "slots" and "emit" symbols. Important bug fixes: * Improved scalability of parallel builds on Linux by starting Process commands via a dedicated launcher process. Behavior changes: * The base directory for source files changed from the product source directory to the parent directory of the file where the files are listed. qbs-src-3.3.1/changelogs/changes-1.9.0.md0000644000175100017510000000531215232633614017213 0ustar runnerrunner# General * Setting module property values from the command line can now be done per product. * Introduced new properties `qbs.architectures` and `qbs.buildVariants` to allow product multiplexing by `qbs.architecture` and `qbs.buildVariant`, respectively. * When rebuilding a project, the environment, project file and property values are taken from the existing build graph. # Language * `Depends` items can now be parameterized to set special module parameters for one particular product dependency. The new item type `Parameter` is used to declare such parameters in a module. The new item type `Parameters` is used to allow products to set default values for such parameters in their `Export` item. * The functions `loadExtension` and `loadFile` have been deprecated and will be removed in a future version. Use the `require` function instead. # Custom Rules and Commands * Artifacts corresponding to the `explicitlyDependsOn` property are now available under this name in rules and commands. * A rule's `auxiliaryInputs` and `explicitlyDependsOn` tags are now also matched against rules of dependencies, if these rules are creating target artifacts. * Rules now have a property `requiresInputs`. If it is `false`, the rule will be run even if no artifacts are present that match its input tags. * Added a new property `relevantEnvironmentVariables` to the `Command` class. Use it if the command runs an external tool whose behavior can be influenced by special environment variables. # C/C++ Support * Added the `cpp.link` parameter to enable library dependencies to be excluded from linking. * When pulling in static library products, the new `Depends` parameter `cpp.linkWholeArchive` can now be specified to force all the library's objects into the target binary. * When pulling in library products, the new `Depends` parameter `cpp.symbolLinkMode` can now be specified to control how the library is linked into the target binary on Apple platforms: specifically, whether the library is linked as weak, lazy, reexported, and/or upward (see the `ld64` man page for more information). * The property `cpp.useCxxPrecompiledHeader`, as well as the variants for the other languages, now defaults to true. * The property `cpp.cxxLanguageVersion` now gets mapped to MSVC's `/std` option, if applicable. # Apple * Added support for building macOS disk images. # Android * Product multiplexing is no longer done via profiles, but via architecture, employing the new `qbs.architectures` property (see above). As a result, the `setup-android` command now sets up only one profile, rather than one for each architecture. * Added support for NDK Unified Headers. # Documentation * Added a "How-to" section. qbs-src-3.3.1/changelogs/changes-3.1.0.md0000644000175100017510000000274715232633614017216 0ustar runnerrunner# General * Qbs now prints information about files being installed. * New modules were added for fine-tuning builds: `config.build`, `config.install` and `installpaths`. * The `install` property in convenience items such as `CppApplication` now defaults to `true`. * The `texttemplate` module received support for an alternative syntax (QBS-1833). * The `Process` service now has an `errrorString` method. * The `vcs` module now supports the `Mercurial` tool and there are new properties `repoLatestTag`, `repoCommitsSinceTag`, and `repoCommitSha`. * Added a `Graphviz` generator to visualize project structures. * The bundled QuickJS was updated to version 0.10.1. # Language * Expansion of wildcards appearing on the right-hand side of a `files` property is now done in a case-sensitive manner on non-Windows hosts (QBS-1844). # C/C++ support * The `CppStd` convenience item was introduced to be able to use the `std.cppm` C++ module without having to build it for every product. * The gcc module now detects the `Alpha` architecture. # API * The LSP support was extended to implement "go to definition" for module names, module properties, user-defined items and the content of the `files` and `references` properties. # Qt Support * Fixed iOS support with Qt >= 6.8 (QBS-1839). # Apple support * Added support for Xcode 26.0. * Added support for embedding dependencies into a bundle. # Contributors * Christian Kandeler * Ivan Komissarov * Jan Blackquill * Pino Toscano * Roman Telezhynskyi qbs-src-3.3.1/changelogs/changes-1.7.00000644000175100017510000000204715232633614016614 0ustar runnerrunnerFeatures: * Added a generator for Visual Studio projects. * The Group item is now nestable. * Stricter type checking for properties. * Added support for generating qrc files. * Added full support for the QtScxml module. * Introduced cpp.soVersion. * Added support for building Inno Setup packages. * Tentative support for Visual Studio 2017. * We now assume UTF-8 encoding for project files. * In Scanner items, input.fileName now contains a filename rather than the full path. * Warnings encountered during project resolving are now stored and re-displayed when the project is loaded. * Documentation was improved in several places, most notably for the Rule item. * Support for the deprecated Transformer item was removed. Important bug fixes: * Long paths on Windows are handled (QBS-1068). * Cyclic module dependencies are detected (QBS-1044). * The libqbscore soname now includes the minor version, so that it will not stay the same across ABI changes (QBS-1002). qbs-src-3.3.1/changelogs/changes-1.23.0.md0000644000175100017510000000066215232633614017272 0ustar runnerrunner# C/C++ Support * Added new module Sanitizers.address for simple cross-platform ASan configuration. # Qt Support * Add the now-required /permissive- flag for MSVC automatically. # Android Support * Support use of cmdline-tools in addition to SDK tools. * Consider .jar files also in the product itself, not just in dependencies. # Contributors * Christian Kandeler * Dmitry Shachnev * Ivan Komissarov * Max Bespalov * Orgad Shaneh qbs-src-3.3.1/changelogs/changes-2.4.2.md0000644000175100017510000000062515232633614017213 0ustar runnerrunner# General * Fixed possible crash when exiting Qbs Session (QBS-1803). * Fixed possible "undefined" value passed to the filterFunction in ProcessCommandExecutor. # JSON API * Undefined module properties are omitted now. # Docker * Linux images now contain GNU Debugger. # CI * CI now collects and prints coredumps on Mac and Linux on test failure. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.9.1.md0000644000175100017510000000037315232633614017216 0ustar runnerrunner# Important bugfixes * Lower the response file threshold on Windows to fix build failures with mingw (QBS-1201). * Fix explicitly specified build variant being ignored for Darwin targets (QBS-1202). * Fix building for the AVR architecture (QBS-1203). qbs-src-3.3.1/changelogs/changes-1.12.2.md0000644000175100017510000000104115232633614017262 0ustar runnerrunner# Important bugfixes * The Visual Studio 2017 Build Tools are properly supported now. * Android NDK r18 is properly supported now. * Removed invalid assertion that prevented deriving from the Properties item. * Fixed build error on some BSD hosts (QBS-1395). * setup-qt fixes: * The QtWebkit module is now properly detected (QBS-1399). * The case of the qtmain library being called "qt5main" is properly handled now (QBS-767). * Building against a Qt that was built with sanitizing support works out of the box now (QBS-1387). qbs-src-3.3.1/changelogs/changes-2.4.0.md0000644000175100017510000000142715232633614017212 0ustar runnerrunner# General * Added a Conan module provider (QBS-1665). * Added a flatbuffers module (QBS-1666). * Rules trying to create artifacts outside the build directory is now a hard error (QBS-1268). * More details are now printed when a command times out (QBS-1750). * Updated the bundled quickjs library. # Language * The pkg-config based fallback provider was removed. * It is no longer allowed to attach a QML id to a module item. # Apple support * Fixed symlinks for multi-arch binaries on Apple platforms (QBS-1797). # C/C++ Support * Added new cpp.importPrivateLibraries property that controls whether to automatically import external libraries from dependencies. # Documentation * Added more tutorials. # Contributors * Christian Kandeler * Ivan Komissarov * Kai Dohmen * Raphael Cotty qbs-src-3.3.1/changelogs/changes-1.17.1.md0000644000175100017510000000035715232633614017277 0ustar runnerrunner# Important bugfixes * Android: Fix support for Qt 5.15 (QBS-1580). * Android: Allow exporting of Qt modules in Export items (QBS-1576) * Darwin: Fix ios-simulator builds with XCode 12 # Contributors * Raphaël Cotty * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.12.1.md0000644000175100017510000000100515232633614017261 0ustar runnerrunner# Important bugfixes * Lifted the restriction that the -march option cannot appear in cpp.*Flags (QBS-1018). * All required header files get installed now (QBS-1370). * Fixed rpaths not ending up on the command line under certain circumstances (QBS-1372). * Fixed possible crash when scanning qrc files (QBS-1375). * Fixed spurious re-building of .pc and .qbs module files. * Fixed possible crash on storing a build graph after re-resolving. * Fixed possible assertion on input artifacts with alwaysUpdated == false. qbs-src-3.3.1/changelogs/changes-1.19.2.md0000644000175100017510000000033715232633614017300 0ustar runnerrunner# Important Bug Fixes * codesign: Fix checking if product is a framework (QBS-1649) * codesign: Add additional signing flags at end of command (QBS-1651) * codesign: Add new codesign.timestampAlgorithm property (QBS-1651) qbs-src-3.3.1/changelogs/changes-1.6.00000644000175100017510000000163115232633614016611 0ustar runnerrunner* Added lex_yacc module. * Introduced property cpp.systemRunPaths. * Introduced the ability to check a module's version in a Depends item. * Introduced cpp.driverFlags, which allows specifying flags to be passed to the compiler driver (in any mode), but never the system linker. * Introduced cpp.linkerMode property to allow selection of the correct linker (C driver, C++ driver, or system linker) based on the objects being linked. * Added automatic escaping of arguments passed to the cpp.linkerFlags and cpp.platformLinkerFlags properties using the -Wl or -Xlinker syntaxes. To revert to the old behavior, Project.minimumQbsVersion can be set to a version lower than 1.6. * Each build configuration now requires a unique name, which is specified on the command line in the same place that qbs.buildVariant used to be specified. This allows building for multiple configurations with the same variant. qbs-src-3.3.1/changelogs/changes-1.7.20000644000175100017510000000045215232633614016614 0ustar runnerrunnerImportant bug fixes: * macOS: Fixed App Extension builds on older versions of Xcode/macOS * Windows: Fixed handling of files on network shares * Fixed syntax error in Qt module that occurred with static Qt builds * Several fixes for the Visual Studio generator (QBS-1077, QBS-1100) qbs-src-3.3.1/changelogs/changes-1.22.0.md0000644000175100017510000000210715232633614017265 0ustar runnerrunner# General * A new Host service was introduced, providing information about the host system that used to be available from the qbs module, but did not really belong there. In addition, some more qbs module properties have moved to the FileInfo service. * The product variable in Export items now points to the importing product, rather than the exporting one. * Probes are now also available in ModuleProvider items. # C/C++ Support * Added support for the Open Watcom toolchain. * Reduced unneeded re-linking on Linux by ignoring changes to weak symbols in library dependencies by default. # Qt Support * Android multi-arch packages are supported again wth Qt >= 6.3. * We now use cpp.systemIncludePaths for Qt headers, so that building Qt applications no longer triggers warnings from Qt headers unrelated to the user code. # Infrastructure * Added coverage for Digital Mars compiler. * Added coverage for static Qt builds. # Contributors * Christian Kandeler * Denis Shienkov * Ivan Komissarov * Jan Blackquill * Leena Miettinen * Marius Gripsgard * Mitch Curtis * Raphael Cotty qbs-src-3.3.1/changelogs/changes-1.7.10000644000175100017510000000037115232633614016613 0ustar runnerrunnerImportant bug fixes: * Fixed race condition in qmake build (QBS-1091) * Qt Creator no longer leaves empty build directories behind after cancelled project loading (QTCREATORBUG-17543) * Fixed an exception crossing the API boundary qbs-src-3.3.1/changelogs/changes-3.0.1.md0000644000175100017510000000021415232633614017201 0ustar runnerrunner # Apple support * Fixed support for booleans in .plist files on Apple Silicon macs. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.11.0.md0000644000175100017510000000606715232633614017274 0ustar runnerrunner# General * Added `qbs.targetPlatform` and `qbs.hostPlatform` properties which are scalar versions of `qbs.targetOS` and `qbs.hostOS`. `qbs.targetPlatform` is a "write-only" property that can be used to set the OS/platform that is being targeted, while `qbs.targetOS` and `qbs.hostOS` should continue to be used to *read* the OS/platform that is being targeted. `qbs.targetOS` is also now read-only. * The "run" functionality as used by the command-line command of the same name now considers an executable's library dependencies, that is, it adds the paths they are located in to the respective environment variable (e.g. PATH on Windows). # Language * Modules can now declare target artifacts using the new `filesAreTargets` property of the `Group` item. * The Module.setupRunEnvironment script now has a new parameter `config`. Users can set it via the `--setup-run-env-config` option of the `run` command. The only value currently supported is `ignore-lib-dependencies`, which turns off the abovementioned injection of library dependencies' paths into the run environment. * Module.setupBuildEnvironment and Module.setupRunEnvironment now have access to the `product` and `project` variables. With regards to accessing module properties, these script now behave like rules, rather than normal properties. * Added the `BinaryFile` service for reading and writing binary data files. * The `SubProject` item now has a condition property. # C/C++ Support * Added property `cpp.rpathOrigin` which evaluates to `@loader_path` on Darwin and `$ORIGIN` on other Unix-like platforms. * Added the `qbs.toolchainType` property, which is a scalar version of the `qbs.toolchain` property and is used to set the current toolchain. * Added `cpp.driverLinkerFlags` for flags to be passed to the compiler driver only when linking. * We now properly support `"c++17"` as a possible value of `cpp.cxxLanguageVersion`. * The auto-detection mechanism for GCC-like compilers now considers typical mingw prefixes. # Qt Support * Added the Qt.scxml.generateStateMethods property to back the --statemethods option. # Command-line interface * Configuration names are now passed as "config:". * Options do not have to precede property assignments anymore. * Referencing a non-existing product in a property override now results in an error. # Documentation * Major overhaul of the module and item reference for improved readability. * Added a how-to on the topic of pre-compiled headers. * Added documentation for the built-in XML support. * Added documentation for qbs.Utilities. * Added documentation on how to target specific platforms. # Important bug fixes * Fixed some inconsistencies related to item ids (QBS-1016, QBS-1262). * Fixed slow project resolving on macOS (QBS-1277). * Fixed problems with qtquickcompiler support in Qt 5.11 (QBS-1299). * Fixed race conditions in multi-configuration builds (QBS-1308). # Other * The `InnoSetup`, `nsis`, and `wix` modules' rules now have a dependency on installable artifacts of dependencies. * Introduced the `ico` module for creating .ico and .cur files. qbs-src-3.3.1/changelogs/changes-1.8.10000644000175100017510000000077615232633614016625 0ustar runnerrunnerImportant bug fixes: * Qbs-specific build errors are now correctly linked in Qt Creator's issues pane (QBS-1151). * Fixed automatic base profile assignment for MSVC Qt installations (QBS-1141) * Various QNX fixes (QBS-1136, QBS-1137, QBS-1138, QBS-1139, QBS-1143). Behavior changes: * Users now get early error messages if they forget the "modules", "products" or "projects" prefix in command line property overrides such as "modules.cpp.enableExceptions:false". qbs-src-3.3.1/changelogs/changes-3.0.0.md0000644000175100017510000000253715232633614017212 0ustar runnerrunner# General * Infinite recursion in property assignments is now properly diagnosed instead of triggering a crash (QBS-1793). * Errors during project resolving print a sort of stack trace now, giving users a better idea about what is going wrong. * The JavaScript backend was switched to `QuickJS-NG`, which is actively maintained. * Added support for C++ standard library modules - "import std;" and "import std.compat;". * Fixed support for arm64/armv7 with MSVC. * Fixed Conan module provider when there are multiple values in array. # Language * Introduced new property `minimal` to `Depends` item that controls whether the dependency should get built in its entirety or only as far as needed by the rules in the depending product. * Relative paths in `Export` items are now resolved relative to the importing product. * Top-level list property assignments no longer act as fallbacks for `Properties` items, but unconditionally contribute to the aggregate value of the property. # API * It is now possible to add dependencies to a product. # Darwin support * The `bundle` module now uses file tags instead of properties to collect header and resource files (QBS-1726). # Qt Support * A `Qt.shadertools` module was added. * moc now uses response files, if necessary. # Contributors * Christian Kandeler * Danya Patrushev * Ivan Komissarov * Richard Weickelt qbs-src-3.3.1/changelogs/changes-3.1.2.md0000644000175100017510000000014615232633614017207 0ustar runnerrunner# General * Fixed CMake build with Qt >= 6.10. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.13.0.md0000644000175100017510000000322615232633614017270 0ustar runnerrunner# General * Added a lot more documentation. * The `--show-progress` command line option is now supported on Windows. # Language * Introduced module providers. * The `Depends` item now falls back to `pkg-config` to locate dependencies whose names do not correspond to a qbs module. * Added the concept of job pools for limiting concurrent execution of commands by type. * Added support for rules without output artifacts. * Added `atEnd` function to the `Process` service. * Added `canonicalPath` function to the `FileInfo` service. * Removed the need to add "import qbs" at the head of project files. * The `Application`, `DynamicLibrary` and `StaticLibrary` items now have properties for more convenient installation of target binaries. # C/C++ Support * Added recursive dependency scanning of GNU ld linkerscripts. * Added new `cpp` property `linkerVariant` to force use of `gold`, `bfd` or `lld`. # Qt Support * It is no longer required to call `setup-qt` before building Qt projects. * Introduced the property `Qt.core.enableBigResources` for the creation of "big" Qt resources. * Static builds now pull in the default set of plugins as specified by Qt, and the user can specify the set of plugins by type. * Files can be explicitly tagged as mocable now. # Other modules * Added `protobuf` support for C++ and Objective-C. * Introduced the `texttemplate` module, a facility similar to qmake's `SUBSTITUTES` feature. # Android Support * The `AndroidApk` item was deprecated, a normal `Application` item can be used instead. * Building Qt apps is properly supported now, by making use of the `androiddeployqt` tool. # Autotest support * Introduced the `autotest` module. qbs-src-3.3.1/changelogs/changes-2.3.1.md0000644000175100017510000000064715232633614017215 0ustar runnerrunner# Language * Fixed look-up of qbs properties in module providers via probes (QBS-1742). # Apple support * Fixed codesign module when multiplexing over build variants (QBS-1775). # Qt support * Fixed retrieving minimum macOS/iOS versions for Qt 6.7.1. # CI * Fixed release jobs. * Fixed macOS 14.2 job. * Updated GitHub actions to recent versions to avoid warnings. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-3.2.0.md0000644000175100017510000000202515232633614017204 0ustar runnerrunner# General * Fixed restoring integer configuration values (QBS-1739). * Fixed resoures location detection when Qbs is called via symlink on macOS (QBS-1873). * Updated QuickJS to version 0.11.0. # Fixed missing TLS plugins in Qbs build with bundled Qt. # Language * The `SubProject` item can now override properties of a loaded `Product` item (QBS-1661). * Module properties provided via the command line are now considered when evaluating the respective module's condition (QBS-1841). # C/C++ support * Added an `ObjectLibrary` item (QBS-1834). * Added a `CppLibrary` convenience item. * Added support for C++26. * Added a `cpp.rpathLinkDirs` property (QBS-1501). * With MSVC, manifest files are now also generated for DLLs (QBS-1857). # Apple * Added support for IconComposer icons (QBS-1871). * Updated dmgbuild to fix an issue with backround images on macOS Tahoe 26.2 (QBS-1872). * Fixed provisioning profiles location with XCode 26 (QBS-1875). # Contributors * Björn Schäpers * Christian Kandeler * Denis Shienkov * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-2.1.1.md0000644000175100017510000000032715232633614017206 0ustar runnerrunner# General * Fixed Probe lookup in multiplexed products. * Fixed excessively slow module merging in some circumstances. * Fixed building QuickJS on x86 systems. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-2.4.1.md0000644000175100017510000000065415232633614017214 0ustar runnerrunner# General * Fix LibraryProbe to take into account libraries both with and without the "lib" prefix. This fixes the Conan provider for MinGW. * Conan module provider no longer sets platform to "none" for baremetal toolchains (QBS-1795). # CI * CI now covers Conan tests for all platforms. Conan is also included in Linux images now. * GDB is now included in Linux images. # Contributors * Christian Kandeler * Ivan Komissarovqbs-src-3.3.1/changelogs/changes-1.16.0.md0000644000175100017510000001224115232633614017270 0ustar runnerrunner# General * A new freedesktop module helps UNIX application developers to follow the freedesktop.org guidelines. * The Android module now allows resourcesDir, sourcesDir and assetsDir to be specified as relative paths. * A new ConanfileProbe allows better and more flexible integration of Qbs and the Conan package manager. * A new hostArchitecture property has been added to the qbs module. # Language * List properties in modules are now merged according to inter-module dependencies. This is important when flags like cpp.staticLibraries are contributed by multiple modules with dependencies between each other. (QBS-1517). * Dependency matching of multiplexed products is now less strict and does not require all multiplex properties to match. For instance, if product A is multiplexed over qbs.architecture and qbs.buildVariant while product B is only multiplexed over one of these axes, then Qbs no longer fails (QBS-1515). # C/C++ Support * The Renesas RL78 architecture is now supported in GCC and IAR and the toolchains are auto-detected by qbs-setup-toolchains. * The Renesas RX as well as the RH850, V850, 78K are now supported in IAR and the toolchains are auto-detected by qbs-setup-toolchains. * The MPLAB X32 GCC-based toolchain is now auto-detected on Windows. * Multiple occurrences of static libraries on the linker command line are now pruned and the last instance always wins when using GCC or LLVM-based toolchains. This avoids problems with excessively long linker command lines (QBS-1273). * Clang-cl and MSVC toolchains use the compiler frontend instead of the linker when linking. The old behavior can be restored by setting cpp.linkerMode to "manual". This allows to use sanitizers with clang-cl by passing "-fsanitise=xxx" via cpp.driverFlags (QBS-1522). * The clang-cl toolchain now uses "link.exe" as the default linker. "lld-link.exe" can be explicitly selected by setting cpp.linkerVariant to "lld" (QBS-1522). * The MSVC, clang-cl and MinGW toolchains are now automatically detected if the profile does not set an explicit installation location, for instance because no profile was given. * Installation of separate debug information can now be enabled and configured by simply setting the installDebugInformation and debugInformationInstallDir properties in the Application and Library convenience items. This works for toolchains based upon GCC, MSVC or clang-cl. * Xcode version 11.4 is now supported on macOS. # Qt Support * Qbs now supports Qt 5.14 for Android which comes as a multi-architecture package. The qbs-setup-android tool has been updated accordingly (QBS-1497). * JSON metatype files generated by moc (Qt >= 5.15) are supported by setting Qt.core.generateMetaTypesFile and Qt.core.metaTypesInstallDir (QBS-1531). * Pure debug builds of Qt (>= 5.14) with MinGW are now properly supported. They don't have the 'd' suffix (QTBUG-80792). * The QML type declaration mechanism introduced in Qt 5.15 is now supported by the Qt.qml module (QBS-1531). * Generated qmltypes files are now named according to the product's targetName property (QTBUG-82710). # Documentation * The how-to chapter has been extended with sections about debugging Qbs files and about building separate debug information in C++ projects. * The item and module reference documentation has been improved for the cpp.libraryPaths, cpp.dynamicLibraries (QBS-1516), qbs.toolchainType and qbs.toolchain properties as well as the Export item and the Library convenience item. * Documentation for various path probes has been added (QBS-1187). * The README was extended and a CONTRIBUTING file has been added which provides useful information for potential contributors. This is important for people looking at our github mirror. # Infrastructure * The Debian Docker image has been removed. * We are now using ccache and clcache in our CI pipelines to shrink the build time. * Clang-tidy is now used to identify potential problems in the code base and a lot of action was taken upon a lot of findings. * A Docker image for testing Qbs with Android and Qt has been added. # Important Bug Fixes * Fix nullpointer access and heap-use-after-free error (QBS-1485). * Select the right instance when Depends.profiles is used on a dependency with an aggregator product (QBS-1513). * Fix crash when specifying a non-existing profile in Depends.profiles (QBS-1514). * Try harder to detect GCC toolchains in qbs-setup-toolchains (QBS-1524). * Code signing for Core Foundation Bundles on macOS has been fixed. * Automatic artifact scanning now prefers artifacts from product dependencies if multiple candidates are found. This improves dependency tracking in complex projects (QBS-1532). * The grpcIncludePath property in the probufcpp module has been fixed (QBS-1542). * Qbs does no longer crash when accessing a property of a non-existent module in "IDE mode". # Contributors * Alberto Mardegan * Björn Schäpers * BogDan Vatra * Christian Kandeler * Christian Stenger * Denis Shienkov * Ivan Komissarov * Jochen Ulrich * Joerg Bornemann * Leon Buckel * Marius Sincovici * Maximilian Goldstein * Mitch Curtis * Oliver Wolff * Orgad Shaneh * Raphaël Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-1.14.0.md0000644000175100017510000000167015232633614017272 0ustar runnerrunner# Language * The `PathProbe` item was extended to support looking for multiple files and filtering candidate files. # C/C++ Support * Added support for Visual Studio 2019. * Added support for clang-cl. * Various improvements for bare-metal toolchains, including new example projects and support for the SDCC toolchain. # Qt Support * Added the `Qt.android_support.extraLibs` property. # Other modules * The `pkgconfig` module now has a `sysroot` property. * Added gRPC support to the `protobuf.cpp` module. # Android Support * Removed support for NDK < r19. * Added new `Android.sdk` properties `versionCode` and `versionName`. # Infrastructure * Added configuration files for Travis CI. * Various fixes and improvements in the Debian Docker image; updated to to Qt 5.11.3. # Contributors * BogDan Vatra * Christian Kandeler * Christian Stenger * Davide Pesavento * Denis Shienkov * hjk * Ivan Komissarov * Joerg Bornemann * Richard Weickelt qbs-src-3.3.1/changelogs/changes-3.3.1.md0000644000175100017510000000050515232633614017207 0ustar runnerrunner# General * Fixed reading integer values from profiles. # Language * The build configuration name "profiling" now maps to the "profiling" build variant by default. # Qt support * Fixed lookup of the metatypes files for Qt versions before 6.5. # Contributors * Christian Kandeler * Ivan Komissarov * Thorbjørn Lindeijer qbs-src-3.3.1/changelogs/changes-2.2.1.md0000644000175100017510000000040615232633614017205 0ustar runnerrunner# Language * Fixed JavaScript Date() constructor on Windows (QBS-1768). # C/C++ support * Worked around crash in cl.exe when retrieving built-in defines (QBS-1743). # CI * Fixed building release packages. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.22.1.md0000644000175100017510000000054615232633614017273 0ustar runnerrunner# General * Adapted to changes in Xcode 13.3 (QBS-1693). * Re-added several bugfixes from 1.21.1 that got lost in 1.22.0. # Qt Support * Fixed building against static Qt 6 (QBS-1692). # Android Support * Fixed wrong include path being added to the command line (QBS-1691). # Documentation * Fixed outdated use of "product" in Export items (QBS-1694). qbs-src-3.3.1/changelogs/changes-1.10.0.md0000644000175100017510000000353715232633614017272 0ustar runnerrunner# General * Added the `vcs` module to provide VCS repository information. Git and Subversion are supported initially. * Added initial support for the Universal Windows Platform. * Improved a lot of error messages. # Language * Profiles can now be defined within a project using the `Profile` item. * Groups without a prefix now inherit the one of the parent group. * Both the `Module` and the `FileTagger` item now have a `priority` property, allowing them to override conflicting instances. * It is now possible to add file tags to generated artifacts by setting the new `fileTags` property in a group that has a `fileTagsFilter`. * Added new open mode `TextFile.Append`. * Added the `filePath` function to the `TextFile` class. * `Process` and `TextFile` objects in rules, commands and configure scripts are now closed automatically after script execution. # C/C++ Support * Added the `cpufeatures` module for abstracting compiler flags related to CPU features such as SSE. * Added property `cpp.discardUnusedData` abstracting linker options that strip unneeded symbols or sections. * Added property `cpp.variantSuffix` for making binary names unique when multiplexing products. * Added property `cpp.compilerDefinesByLanguage` providing the compiler's pre-defined macros. # Android * The deprecated `apkbuilder` tool is no longer used. # Qt * Added support for the Qt Quick compiler. * Added support for `qmlcachegen`. # Command-line interface * Removed some non-applicable options from a number of tools. * The `run` command can now deploy and run Android apps on devices, and deploy and run iOS and tvOS apps on the simulator. * Added new command `list-products`. # Documentation * Added porting guide for qmake projects. * Added in-depth descriptions of all command-line tools. * Added "How-to" for creating modules for third-party libraries. * Added a man page. qbs-src-3.3.1/changelogs/changes-3.3.0.md0000644000175100017510000000122015232633614017201 0ustar runnerrunner# Language * Scanner items now participate in change tracking (QBS-1092). # C/C++ support * Introduced new property `cpp.libraries` (QBS-1157). * Added support for clang's `-ftime-trace` flag. * Static linking on Unix systems will now use response files if necessary (QBS-751). * Added support for the `LoongArch` architecture. * Fixed WebAssembly support for emscripten >= 3.1.68 (QBS-1876) # Qt support * Moc scanner now supports the Q_NAMESPACE_EXPORT macro. # Apple * Fixed installation of code-signed static frameworks on macOS 26. # Contributors * Christian Kandeler * Ivan Komissarov * Maximilian Hrabowski * Pino Toscano * Thorbjørn Lindeijer qbs-src-3.3.1/changelogs/changes-2.1.0.md0000644000175100017510000000156715232633614017214 0ustar runnerrunner# General * Improved speed and correctness of project resolving. * Fixed possible segmentation fault when quitting a session. * Fixed regression in BinaryFile (QBS-1740). * Added possibility to import and export Qbs settings in the JSON format (QBS-1685). # Modules * Dependencies are no longer merged by default in the qbspkgconfig module provider (QBS-1710). * Protobuf modules now export the desired c++ version (c++17 on macOS, c++14 otherwise). # Apple Support * Updated dmgbuild to the upstream. # Documentation * Added documentation for the path, filePath, product and project variables. * Added sample codesign settings to the Cocoa Touch Application example. # Build System * Updated Qt static Docker image to Qt 6.5.0 and Qbs 1.24. # Contributors * Andrey Filipenkov * Christian Kandeler * Denis Shienkov * Ivan Komissarov * Marc Mutz * Raphael Cotty * Thiemo van Engelen qbs-src-3.3.1/changelogs/changes-1.23.2.md0000644000175100017510000000026615232633614017274 0ustar runnerrunner# Qt Support * Set _ENABLE_EXTENDED_ALIGNED_STORAGE for MSVC # Documentation * Fix installation with cmake # Contributors * Christian Kandeler * Ivan Komissarov * Marius Gripsgard qbs-src-3.3.1/changelogs/changes-1.6.10000644000175100017510000000040715232633614016612 0ustar runnerrunnerFeatures: * Added cpp.linkerWrapper property. Important bug fixes: * Fixed a number of bugs evaluating module properties (QBS-845, QBS-1005). * Fixed x86_64 > x86 cross compiling (QBS-1028). * Fixed dynamic rules with generated inputs (QBS-1029). qbs-src-3.3.1/changelogs/changes-1.18.0.md0000644000175100017510000000517115232633614017276 0ustar runnerrunner# General * capnp: The outputDir property is now public and read-only. * setup-toochains: Include the Xcode version into the profile name profile when auto-detection an Xcode installation. * innosetup module: Add support for InnoSetup v6 * JSON API: Use the full display name of multiplexed products in the dependencies array. This allows clients to for example to properly update the search path for multiplexed dynamic libraries. # Language * Deprecate the product variable inside Export items in favor of a new exportingProduct variable. It will be removed in Qbs 1.20 (QBS-1576). * Qbs now checks string and stringList values according to the allowedValues property in the PropertyOptions item. # Protocol Buffers Support (Protobuf Module) * The deprecated protocBinary property has been removed. Use compilerPath instead. * A nanopb submodule has been added. * The outputDir property is now public and read-only. # C/C++ Support * baremetal: cpp.generateCompilerListingFiles has been implemented for KEIL ARM Clang * baremetal: cpp.enableDefinesByLanguage does now work with SDCC as well. # Qt Support * Moc is now disabled when building aggregate products. # Android Support * Support for the new directory layout of Qt6 has been added (QBS-1609). * Input file generation for androiddeployqt has been improved (QBS-1613). * Debugging experience of multi-architecture Android projects with Qbs and Qt Creator has been improved. Binaries are now generated in a directory layout that Qt Creator expects and debug information is no longer stripped away. # Documentation * baremetal: A new WiFi access point example for the ESP8266 MCU using the GCC toolchain has been added. * baremetal: A new example for Nordic's pca10001 board has been added. It supports GCC, KEIL and IAR. * baremetal: The stm32f103 example supports IAR as well. * A howto has been added showing how to easily disable compiler warnings. * Instructions for building Qbs with CMake have been added (QBS-1618). # Important Bug Fixes * Qt modules could not be used in Export item when building for Android (QBS-1576). * Variable substitution in Info.plist files was broken for '@VAR@' syntax (QBS-1601). * CppApplication failed to build for Android when using Qt > 5.14.0 and multiplexing over multiple architectures (QBS-1608). * Moc output was broken when including Boost project header files (QBS-1621). # Contributors * Alberto Mardegan * André Pönitz * Christian Kandeler * Christian Stenger * Cristian Adam * Denis Shienkov * Eike Ziller * Ivan Komissarov * Jochen Ulrich * Kai Dohmen * Mitch Curtis * Orgad Shaneh * Raphaël Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-2.1.2.md0000644000175100017510000000105215232633614017203 0ustar runnerrunner# General * Fixed handling JS floating-point values for x86. * Fixed scope pollution and potential crash when assigning to provider properties (QBS-1747). * Fixed potential access to freed JSValues (QBS-1751). # Qt * Fixed building against Qt with "profiling" build variant (QBS-1758). # Apple * Fixed bundle module with Xcode-less profiles. * Fixed ApplicationExtension with Xcode-less profiles. # Infrastructure * Added CI job to be able to test XCode-less profiles on macOS. # Contributors * Christian Kandeler * Dmitry Shachnev * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-2.2.0.md0000644000175100017510000000233115232633614017203 0ustar runnerrunner# General * Improved speed of project resolving by employing multiple CPU cores, if available. * Improved speed of probes execution on macOS. * Object and array (var and varList) properties are now immutable in Probe items. # Language * Modules can now contain `Parameters` items. * ModuleProviders can now contain `PropertyOptions` items. # C/C++ support * Allow `"mold"` as value for `cpp.linkerVariant`. * The systemIncludePaths property is now handled correctly for clang-cl. # Apple support * Updated dmgbuild tool. This fixes bug that additional licenses are not shown in the combobox in the resulting DMG image. # Qt support * Only create qbs modules for those Qt modules that products actually need. * Users can now opt out of using RPATH when linking on Linux. # Other * Protobuf module now requires pkg-config or built-in runtime. * Protobuf module now requires C++17 on all platforms. * Capnproto module: the outputDir property is now mutable. * Added support for Groups to the VisualStudio generator. * pkgconfig module provider: mergeDependencies property is deprecated. # Contributors * Christian Kandeler * Dmitrii Meshkov * Ivan Komissarov * Nick Karg * Serhii Olendarenko * Thiemo van Engelen * Thorbjørn Lindeijer qbs-src-3.3.1/changelogs/changes-3.1.1.md0000644000175100017510000000030315232633614017201 0ustar runnerrunner# C/C++ support * Modules support: Properly handle absolute paths in the files pointing to the std modules. # Contributors * Christian Kandeler * Ivan Komissarov * Orgad Shaneh * Pino Toscano qbs-src-3.3.1/changelogs/changes-1.17.0.md0000644000175100017510000000651215232633614017275 0ustar runnerrunner# General * The lookup order in PathProbe changed to [environmentPaths, searchPaths, platformEnvironmentPaths, platformSearchPaths]. * The pathPrefix and platformPaths properties have been removed from the PathProbe item. They were deprecated since Qbs 1.13. * The protocBinary property in the protobuf module has been renamed to compilerPath. * A new module capnp for Cap'n Proto in C++ applications has been added. Cap'n Proto is a serialization protocol similar to protobuf. * The qbs-setup-android tool got a --system flag to install profiles system-wide similar to qbs-setup-qt and qbs-setup-toolchains. # Language * The product and project variables are now available on the right-hand-side of moduleProvider expressions and the default scope is product (QBS-1587). # C/C++ Support * Lots of improvements have been made on toolchain support for bare-metal devices in general. Bare-metal targets can be selected by setting qbs.targetPlatform to 'none'. * KEIL: The ARMCLANG, C166 and C251 toolchains are now supported. * IAR: National's CR16, Microchip's AVR32, NXP's M68K, Renesas' M8/16C/M32C/R32C/SuperH targets and RISC-V targets are now supported. * GCC: National's CR16, NXP M68K, Renesas M32C/M32R/SuperH/V850 as well as RISC-V and Xtensa targets are now supported. * MSVC: Module definition files can now be used to provide the linker with information about exports and attributes (QBS-571). * MSVC: "/external:I" is now used to set system include paths (QBS-1573). * MSVC: cpp.generateCompilerListingFiles is now supported to generate assembler listings. * Xcode: macOS framework paths on the command line are now automatically deduplicated (QBS-1552). * Xcode: Support for Xcode 12.0 has been added (QBS-1582). # Qt Support * The Qt for Android modules have been cleaned up. Support for ARMv5, MIPS and MIPS64 targets has been removed (QBS-1496). * Initial support for Qt6 has been added. # Android Support * A packageType property has been added to the Android.sdk module which allows to create Android App bundles (aab) instead of apk packages only. * A aaptName property has been added to the Android.sdk module which allows to use aapt2 (QBS-1562) since aapt has been deprecated. # Documentation * New bare-metal examples have been added and existing examples have been ported to more toolchains. * A new how-to about cpp.rPaths has been added (QBS-1204). * Various minor improvements have been made. # Important Bug Fixes * Building Qt for Android applications as static libraries has been fixed (QBS-1545). * Trailing slashes are no longer removed from Visual Studio environment variables (QBS-1551). * The MSVC cpp module did not use the cpp.distributionIncludePaths property (QBS-1572). * The visual studio generator has been fixed to work with Visual Studio 16.6 (QBS-1569). * Fixed extraction of build information from CONFIG and QT_CONFIG variables in Qt installations (QBS-1387). * The version number is no longer appended to .so files on Android (QBS-1578). * Compiler defines are now correctly passed to moc when processing header files (QBS-1592). # Contributors * Alberto Mardegan * Christian Gagneraud * Christian Kandeler * Christian Stenger * Denis Shienkov * Ivan Komissarov * Jake Petroules * Jochen Ulrich * Mitch Curtis * Oliver Wolff * Raphaël Cotty * Richard Weickelt * Sergey Zhuravlev qbs-src-3.3.1/changelogs/changes-3.0.3.md0000644000175100017510000000111515232633614017204 0ustar runnerrunner# General * Fixed spurious complaint about property binding loop (QBS-1845). # CI * Ad-hoc signed macOS artifacts are now published by release jobs. # C/C++ support * Made defines and include paths for windres unique. * Fixed support for STABLE and CURRENT releases for FreeBSD. * Fixed default values for qbspkgconfig search paths on FreeBSD. # Qt support * Fixed building Qt apps for iOS-simulator when qbs.architecture is undefined. * Fixed duplicate JSON metadata files appearing on qmlregistrar command lines. # Contributors * Björn Schäpers * Christian Kandeler * Pino Toscano qbs-src-3.3.1/changelogs/changes-2.2.2.md0000644000175100017510000000100615232633614017203 0ustar runnerrunner# General * Fixed name collision check for multi-part modules (QBS-1772). * Fixed potential assertion when attaching properties on non-present modules (QBS-1776). # C/C++ * Fixed handling assember flags with MSVC (QBS-1774). # Qt * Fixed the qbspkgconfig Qt provider for the case when there is no Qt (QBS-1777). # Other * Make protobuf usable without qbspkgconfig again (QBS-1663). * Add support for the definePrefix option to qbspkgconfig. # Contributors * Björn Schäpers * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-2.5.1.md0000644000175100017510000000042715232633614017213 0ustar runnerrunner# General * Fixed use of wrong declaration when looking up properties via the parent item (QBS-1821). * Fixed crash when resolving Probes. # CI * Updated to Qt 6.7.3 for macOS (QBS-1799). * Switched macOS jobs to macOS 13. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/changelogs/changes-1.23.1.md0000644000175100017510000000115315232633614017267 0ustar runnerrunner# C/C++ Support * Added support for c17 and c2x values in cpp.cLanguageVersion. * Added support for cpp.cLanguageVersion for the MSVC toolchain. * Fix passing linker scripts to iar and keil toolchains (QBS-1704). # Qt Support * Adapted to new location of qscxmlc in Qt 6.3. * Adapted to new location of qhelpgenerator in Qt 6.3. * Fixed setting up Qt 6.3 with qbspkgconfig. * Added QtScript module to the source tarballs (QBS-1703). # Other modules * Fixed protobuf linking on macOS 11. * Fixed handling empty variables in qbspkgconfig (QBS-1702) # Contributors * Christian Kandeler * Ivan Komissarov * Orgad Shaneh qbs-src-3.3.1/changelogs/changes-1.21.0.md0000644000175100017510000000412015232633614017261 0ustar runnerrunner# General * A new qbsModuleProviders property was added to Project and Product items which allows to specify which providers will be run (QBS-1604). * Added a new library for reading *.pc files which allows to avoid launching multiple pkg-config processes and also gives QBS more information about dependencies between *.pc files (QBS-1615). * A new qbspkgconfig provider was added which will replace the fallback provider (QBS-1614). This new provider uses the built-in library and is capable of setting Qt libraries as well. * capnproto and protobuf modules can now use runtime provided by the qbspkgconfig provider. * A new ConanfileProbe.verbose property was added which can be useful to debug problems with Conan. * Qbs no longer migrates the "profiles/" dir from earlier Qbs versions (QTCREATORBUG-26475). Old directories might be cleaned up manually. * FileInfo now always uses high-precision timer on all OSes. * Fixed a problem with overriding stringList properties in ModuleProviders from command-line. # C/C++ Support * Added support for c++23. * Add Elbrus E2K architecture for the GCC toolchain (QBS-1675). * COSMIC cpp module now avoids using relative file paths as much as possible. * Some refactoring was done in the cpp modules to share more code. # Android Support * Added Android.ndk.buildId property which allows to overwrite the default value (sha1) for the --build-id linker flag. * Fixed reading *.prl files with Qt >= 6.0. * Fixed rcc path with Qt >= 6.2. # Documentation * Added a new page with the list of ModuleProviders. * Qt provider now has its own page. * Clarified that application won't be runnable by default, unless env or rpaths are set correctly. # Infrastructure * Added standalone job for building documentation. * Xcode version was bumped to 12.5.1. * Added OpenSUSE Leap docker image. * Added Android tests with different NDK versions. * Fixed QMake build with Qt 6. # Contributors * Christian Kandeler * Christian Stenger * Davide Pesavento * Denis Shienkov * Ivan Komissarov * Kai Dohmen * Orgad Shaneh * Raphaël Cotty * Richard Weickelt * Thorbjørn Lindeijer qbs-src-3.3.1/changelogs/changes-2.3.0.md0000644000175100017510000000254415232633614017212 0ustar runnerrunner# General * Added an LSP language server that provides support for following symbols and completion in IDEs (QBS-395). * Module properties are now directly available within groups in modules (QBS-1770). * Added possibility to export products to CMake via the new Exporter.cmake module. * Deprecated the pkgconfig-based fallback module provider. * If a project needs to be re-resolved, we now print the reason. * Added some tutorials. * Wildards handling was rewritten to track changes more accurate. * Module 'validate' scripts are no longer run for erroneous product in IDE mode. * Add example how to use Exporters. # C/C++ Support * Private dependencies of products are not traversed more than once anymore (QBS-1714). # Language * Module properties are now accessible for groups in modules (QBS-1770). * Fixed pathList properties in Probes (QBS-1785). * The qbspkgconfig.mergeDependencies property was removed. * ModuleProviders now support the 'allowedValues' property of the PropertyOptions item (QBS-1748). # Apple * Adapted darwin support to Xcode 15.3. # CI * Changed Linux Docker images from Focal to Jammy. * Updated compilers and linters to recent versions. * Added clang-format job to check code style. * The project.withExamples property was removed. # Contributors * Christian Kandeler * Dmitrii Meshkov * Ivan Komissarov * Raphael Cotty * Richard Weickelt qbs-src-3.3.1/changelogs/changes-1.13.1.md0000644000175100017510000000106115232633614017264 0ustar runnerrunner# Important bugfixes * Qt support: Plugins are no longer linked into static libraries when building against a static Qt (QBS-1441). * Qt support: Fixed excessively long linker command lines (QBS-1441). * Qt support: Host libraries are now looked up at the right location (QBS-1445). * Qt support: Fixed failure to find Qt modules in Qt Creator when re-parsing a project that hasn't been built yet. * macOS: Properties in bundle.infoPlist are no longer overridden (QBS-1447). * iOS: Fixed generation of default Info.plist (QBS-1447). qbs-src-3.3.1/changelogs/changes-1.19.1.md0000644000175100017510000000047015232633614017275 0ustar runnerrunner# C/C++ Support * Fix system include support with MSVC >= 19.29.30037 # Qt Support * Fix possible command line length issue with qmlimportscanner when cross-compiling (QBS-1633). # Apple platforms * Fix stripping debug symbols in multiplexed products when cpp.separateDebugInformation is false (QBS-1647) qbs-src-3.3.1/changelogs/changes-2.6.1.md0000644000175100017510000000057315232633614017216 0ustar runnerrunner# General * Fixed vcs module behavior when .git/logs/HEAD is not present (QBS-1814). # Language * Fixed behavior of SubProject.inheritProperties (QBS-1836). # Darwin support * Fixed generating iOS codesign entitlements (QBS-1826). # Qt support * Fixed Qt module provider when multiple qmake binaries are present in PATH. # Contributors * Christian Kandeler * Ivan Komissarov qbs-src-3.3.1/CONTRIBUTING.md0000644000175100017510000000741115232633614014737 0ustar runnerrunner# Contributing to Qbs The main source code repository is hosted at [codereview.qt-project.org](https://codereview.qt-project.org/q/project:qbs/qbs). The Qbs source code is also mirrored on [code.qt.io](https://code.qt.io/cgit/qbs/qbs.git/) and on [GitHub](https://github.com/qbs/qbs). Please note that those mirrors are read-only and we do not accept pull-requests on GitHub. However, we gladly accept contributions via [Gerrit](https://codereview.qt-project.org/q/project:qbs/qbs). This document briefly describes steps required to be able to propose changes to the Qbs project. See the [Qt Contribution Guidelines](https://wiki.qt.io/Qt_Contribution_Guidelines) page, [Setting up Gerrit](https://wiki.qt.io/Setting_up_Gerrit) and [Gerrit Introduction](https://wiki.qt.io/Gerrit_Introduction) for more details about how to upload patches to Gerrit. ## Preparations * [Set up](https://wiki.qt.io/Setting_up_Gerrit#How_to_get_started_-_Gerrit_registration) a Gerrit account * Tweak your SSH config as instructed [here](https://wiki.qt.io/Setting_up_Gerrit#Local_Setup) * Use the recommended Git settings, defined [here](https://wiki.qt.io/Setting_up_Gerrit#Configuring_Git) * Get the source code as described below ## Cloning Qbs Clone Qbs from the [code.qt.io](https://code.qt.io/cgit/qbs/qbs.git/) mirror ``` git clone git://code.qt.io/qbs/qbs.git ``` Alternatively, you can clone from the mirror on the [GitHub](https://github.com/qbs/qbs) ``` git clone https://github.com/qbs/qbs.git ``` Set up the Gerrit remote ``` git remote add gerrit ssh://@codereview.qt-project.org:29418/qbs/qbs ``` ## Setting up git hooks Install the hook generating Commit-Id files into your top level project directory: ``` gitdir=$(git rev-parse --git-dir); scp -p -P 29418 codereview.qt-project.org:hooks/commit-msg "${gitdir}/hooks/" ``` This hook automatically adds a "Change-Id: …" line to the commit message. Change-Id is used to identify new Patch Sets for existing [Changes](https://wiki.qt.io/Gerrit_Introduction#Terminology). ## Making changes Commit your changes in the usual way you do in Git. After making changes, you might want to ensure that Qbs can be built and autotests pass: ``` qbs build -p autotest-runner ``` See ["Appendix A: Building Qbs"](http://doc.qt.io/qbs/building-qbs.html) for details. In case your changes might significantly affect performance (in either way), the 'qbs_benchmarker' tool can be used (Linux only, requires Valgrind to be installed): ``` qbs_benchmarker -r -o -n -a -p ``` Use 'qbs_benchmarker --help' for details. ## Pushing your changes to Gerrit After committing your changes locally, push them to Gerrit ``` git push gerrit HEAD:refs/for/master ``` Gerrit will print a URL that can be used to access the newly created Change. ## Adding reviewers Use the "ADD REVIEWER" button on the Change's web page to ask people to do the review. To find possible reviewers, you can examine the Git history with 'git log' and/or 'git blame' or ask on the mailing list: qbs@qt-project.org ## Modifying Commits During the review process, it might be necessary to do some changes to the commit. To include you changes in the last commit, use ``` git commit --amend ``` This will edit the last commit instead of creating a new one. Make sure to preserve the Change-Id footer when amending commits. For details, see [Updating a Contribution With New Code](https://wiki.qt.io/Gerrit_Introduction#Updating_a_Contribution_With_New_Code) ## Abandoning changes Changes which are inherently flawed or became inapplicable should be abandoned. You can do that on the Change's web page with the "ABANDON" button. Make sure to remove the abandoned commit from your working copy by using '[git reset](https://git-scm.com/docs/git-reset)'. qbs-src-3.3.1/CMakeLists.txt0000644000175100017510000000425615232633614015252 0ustar runnerrunnercmake_minimum_required(VERSION 3.10) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.15") cmake_policy(VERSION 3.15) endif() ## Add paths to check for cmake modules: list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(FeatureSummary) include(QbsBuildConfig) include(QbsDocumentation) file(STRINGS VERSION QBS_VERSION) project(Qbs VERSION ${QBS_VERSION}) # Force C++ standard, do not fall back, do not use compiler extensions set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Set up Qt stuff: set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) if(WITH_TESTS) enable_testing() set(QT_TEST_COMPONENT Test) set(IMPLICIT_DEPENDS Qt${QT_VERSION_MAJOR}::Test) endif() find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent Core Gui Network Widgets Xml ${QT_TEST_COMPONENT} REQUIRED ) find_package(Qt${QT_VERSION_MAJOR} OPTIONAL_COMPONENTS Script QUIET) if (Qt6_FOUND) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core5Compat REQUIRED) if(NOT TARGET Qt6Core5Compat) if(CMAKE_VERSION VERSION_LESS 3.18) set_property(TARGET Qt6::Core5Compat PROPERTY IMPORTED_GLOBAL TRUE) # hack for CMake < 3.18 endif() add_library(Qt6Core5Compat ALIAS Qt6::Core5Compat) endif() if (Qt6Core_VERSION VERSION_GREATER_EQUAL 6.9.0) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS CorePrivate REQUIRED) endif() else() if(NOT TARGET Qt6Core5Compat) add_library(Qt6Core5Compat INTERFACE) endif() find_package(Qt${QT_VERSION_MAJOR} OPTIONAL_COMPONENTS DocTools) endif() if (QBS_INSTALL_HTML_DOCS OR QBS_INSTALL_QCH_DOCS) find_package(Python3 COMPONENTS Interpreter) if (Qt6_FOUND) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Tools REQUIRED) else() find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Help REQUIRED) endif() endif() add_definitions(-DQT_NO_QSNPRINTF -D_UCRT_NOISY_NAN) add_subdirectory(src) add_subdirectory(doc) add_subdirectory(share) if(WITH_TESTS) add_subdirectory(tests) endif() qbs-src-3.3.1/doc/0000755000175100017510000000000015232633614013250 5ustar runnerrunnerqbs-src-3.3.1/doc/qbs-online.qdocconf0000644000175100017510000000170715232633614017042 0ustar runnerrunnerinclude(config/qbs-project.qdocconf) HTML.footer = \ " \n" \ " \n" include($QT_INSTALL_DOCS/global/qt-html-templates-online.qdocconf) # Add an .html file with sidebar content, used in the online style HTML.stylesheets += config/style/qt5-sidebar.html qbs-src-3.3.1/doc/qbs-hugo.qdocconf0000644000175100017510000000020315232633614016506 0ustar runnerrunnerinclude(config/qbs-project.qdocconf) syntaxhighlighting = true HTML.prologue = "
" HTML.footer += "
" qbs-src-3.3.1/doc/images/0000755000175100017510000000000015232633614014515 5ustar runnerrunnerqbs-src-3.3.1/doc/images/qbs-build-process.png0000644000175100017510000001232715232633614020566 0ustar runnerrunner‰PNG  IHDRIé8H>t PLTE°P°p°±Q½½¬ËȱR³V ´Xµ[¸a¹c¹cºf ºf!»g&¼k(½l0¿q6Áu8Âw:°P:°p:°:½P:½p:½:Ë:ˬ:ËÈ:ØÈ:Øä@Ä|HÇ‚PɇXÌ`Î’eÏ–f°Pf°pf½Pf½pfËfجfØäfåäfåÿhјnÒ›pÓxÖ£×§ƒÙ«‡Ú­Ü²½PËpËåÈòÿ—߸Ÿá½§äïæÈ¶ËP¶Ëp¶Ø¶å¬¶åȶåä¶òÿ¶ÿÿ·éοëÓÇîÙÏðÞ×óäÛØpÛØÛåÛåÈÛòäÛòÿÛÿÿßõéçøïïúô÷ýúÿåÿò¬ÿòÈÿòäÿÿÈÿÿäÿÿÿ$ɱÂrIDATxÚí {Ú8†Ew’í¶»Ë®YÜvzÃ$l›Ì´dC–dfHH;íd€ÐÙ6ÜBþÿÿb…/\,K::8GÏÓ(±MùüZ::–t$æB¥vÕq˜îä8û箙¾gP±*ͦö¯i6s¥~šI¶óU°[:±é%ynAÖ¹žsšV’ƒ\ô¦z¹^JIVªÀwUßN'Éóømm¦’äÁøm”RI2ß¿­n6•$³ÝôúɰßWD’HI"I$‰$‘$’D’HI"I$ÓFòë™ëŽ–ÉØi|TàÿÊ·Ž_ýæ,I’QEïËF‡Êä²ï]„¿tf¹G2€z1w™OráÄìƒ÷šäøˆ1;Sãùs›±WsyP»‡;|&@9¼ì óÿòOج|`£Cer’>nr ¯;îÐ.ÏrŸäøèUgî2¿Lú'x¡õ/ì¸WoÊDr’.7:~#ò¡0Ë}’Ã'µùËf$ý³É«Ÿw¿·§$7gy@òéïó—Í‘ôNL?@$‡ö»oË•$ÃˈäÒï˜Ð‰Q»Ã˨v/'ù€­?’œÎ,_hqÂË|¤Ó‡·4Dræ=c/l^IYÆÎ¼sgyèÙä]æ^ï,xA¯\"yÿæ@<×;Ìo_pÛ _Ð;NTÙ,/äÔD$“üµ¶ITwE$‰$‘$’D’HI"I$‰$‘$’Dÿ7>îI5)¼Þ”J’¥ðÛj:©$Ù(‚ßÖÞq:íIz€vnN’= xi 1§@mÜÉ6hÙ¯¤×ï:ÌÁ•’vÞH0¿«ßƒ1–çû¹–›f’®{\d)w8pSN2}êˆ$‘$’D’ÔIÒJ$‰$‘$’¤•H’:"IZ‰$‘$uD’´IRG$‰$‘$’¤ŽH’V"I$‰$‘$­D’ÔIÒJ$•§Ö¿DRAêïåÅ­‘”M'Ö$:éÔªI©ÔvJ~iìW ÍÀOÉÁAn¶ðy~¿O$“¥Fî`!€áЪÉ©·]l¯>D$W¦èx³˜ÉUi©Q\0Dr¥ yWC=mΉäÊ´Êyô]L"¹*uW¿Ððמ6‘\•ªVœ—ì–UI5„ªÙ‘\^kKµ¶W,öˆä’–$+¶N#[%’ÑÞè{õa·†q’Jû<¿×'’ Õª&l‹­"9k<¶ŠÝä.9m"vVœJ}¾‰©[à ɖ|.ïÖhÜ{’ý}%Kvµ‹Û½ûM²n*ûŸŽï1ɮʒĻ5Îï)ÉA¼Î ‹›«ôï#ÉfN}wNUÒ XG’}=^ ÷L{÷‹¤hg…ÀÛ’án X’í|IŸAT¬Ö=!©ýVµ>(D$!ªŸ>ã‡$P“Ð7Ö­EÎMÑádá! ê:+wüñëšèÖ i¢‹A] ’†º½uÚá!i°+¶<X/I±á¯g|“î…Rß~Ú­¡“¤àÕt7ùÙ²´ÛMIÑaÔ É…2©`KïäƒÀxHŠí{$ƒ4ê,’'­ç '&à!™dºIX»ÇGÏmÆ6:>É/ü—댙œxÿÑ.¦ &Ë "™¨³bF²Ðq¯Þ”½?†OøVóxa½|ðûø(óò m·†’ §åÍHNÊÝï¯Æ_¿å4¯ß”ÛM¡I…ˆH&*A2cóºÍËå/Ÿ?Ú)K´@SÕ“tŠ 5G|ý¿LmBòÅ<Õ¤Úò’³v$»I#‰£j·ûJÏVÊyESýuØÉ„‘Ä‘$¯½–§ I"üDKÛ,’8’ä¤Ív‡;ì›´ÝÉH„Diò'UG¾Ét¢€øæÚÞq°Dƒ…Žê{ïFI (‚¥¡8 ¨Zû' GÃ.û ¹ÏÜ`$1ôR$ÚÇqLEƒ/£lÑH$q~É&ˆñnøHbs`æ`ÀF›‰šI ÒiŽ$Ü”[cóþàæO‚DC Ú% I 7h˜¤îHbÀÁmã$uFƒN¸0OR_$ñ¡éØ&ø1-Ó×Zæ×¨4·¨|J%üdI$$UOó50 I•SÏ»Hbå­9 (ÂP &’jBtLßà")6ÖÇ´ÎÙõ‚äº5 )¢#)^k4pÉÄ@ sc$™¬’"\7Ãú“ ‡ùE/’uf,Ä‚–¤ˆƒbq ¼$c¿ô!Y° 3Éxu¼kÃcZceçž…ý“\Ña‹i±Iô$ïDh"ß×Ýþ8K¶-Ê»$£[±-½$oOÀ·xùš¼1)e°ûbÝoqÖ­r“‡5"NÞCºñÈ:‘ô'”bÝ g½Hºîþ\¸DR…±¤ý»‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D’H®)ɦâTaM­©‡–$s§¿9:Óã¼$ݵJ%"I$‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D2ÎÍw‹Î#¦9=tœƒvÊIV­ýFS{Øå Ù<°ŒÅÜ@ìo¯j*À€dvMÇv^~róÆ(’¤¼¾z×’­‰ŒQ»§ÒE‘¬V ëÙñžÔÇQ#¦£„ˆ'©µŸq£’ðÆÿ¤$ñaÆ(‚dÑ@HuÛ’¨n8ŒQɬ‰í˜âoŒ"îàá`­Hb1F ÉÛsò/ÅbŒÖŸ$c´þ$±£õ'‰E.‘$’D’HI"I$ï1É‘T#m|T&’T&M’ÍÁ]ÌŸèÌŠé‘\U‘ŸÛŒ½Üån¯ùŒÙ™šW»ý>Ëá³YHÞM²Ðq‡OÞsZO÷Ž|Ü HòWoÊÁEü¼]&’«ïÇõÛšwär£ã“œ€ûàÄá“Úôw$¿ž!&9ùqõóî÷vI¯¸~ØDCÒ«$˜Iíwß:—DRžäå¤Á^»'^D@2t4¾uæ3OCɼìýqƒäõnÙ´>†Ir/‚1OPèh¸'3} a&æiè"ÉÅ=c/ìÍE’œ §í/h|ôª3_»¹£1|Zó-Pm¾êÇô4ô½ã,­Hýd¦‘­Ý¡£áÿ²9˨v ¶8¡£áöK Ï={Üg>´ç¼ ÏÑðŽ|wd‚žÆ½}˜yáocß%›õÌ×$Ö¾ "I$‰$‘$’D’HI"I$—Z³xÄ$ó­{ÓHrï^Y£˜F’M^™Dø?âxw»-¬•OþY,Æ(ŠdßÞèy“X ‹1Š´2 § ²t(ñi,Æ(Ú^×!£ø[¹C©Ï#1FKZ¾^qû&°¹——\{ ‰1ZêCÔ·2ˆäÈ›9Æ(몡0FéX¡ƒ1JËZæÑ}^5‘áý߈$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D2}$Ùë#½ùÛë¯ÈFö¿ÇÙ”$Ù+•¦5õŠE>í_Ê·Ñ‘T/Mgªfƒ9Y-e›2¼Òô¥Så(Hj‘¦+ݬ7~mBAR“4Méä¶-od«(Hê’¦%µó¥ÿbP±ZÆIꓦÅ\*+ú6IꔦŬ U-@’Z¥éq!ã›{@’š¥)®Ø1\ )Žá•¦45s±”T³§à$õKSY±KNÌÚÑÛ*vAIBHS—Ž-‹Ý°ª8’ ÒT¥ó¼XÕ ’k‘’¦èݰ’ölÛN©@Lš’tj%zÛ:±Žµ“„“¦ u‹[ Ÿ`/®•$¤4.¤Ldh+Wék# + È…¼Ãƒ³N5‘–åB*òà^ip.¤Žá•&‘ZyU£œñ=8†WZrr_åBmg»§Œ¤iISÝ:4ñ2¼Ò>§¢úç«$1¼ÒÙŽƒœ–ÍV~¿/IÒ ´$íYî@W{vhÕ¥Hš”&îcm5öѯúß^iæP±bx¥a0¦Žá•†¢ ‹ßü2¼Ò¸Uq¿Šá•fÔ…/þ ¯´ø¯ŸÀsã¢íÃ+ S—È­¶ø$I4ÒbyR†Æ€#º^i1d×ñt«Û›á•¶Ú((ιIöH¿9ÃtHK¦Op”HÙ›¿1q‚½‡™i‰õ‰Œ\*ö%Þ#}~Èšé–\_ÜÑt©Á&ŠÓ½GÓ“¼>÷ÂÂE±+Æl—¦U_¬#þèá.çã£ç|ÏÏ—»üØëàW³Ús½“±3“ßߌ¹·;7µ‡‰JÓ®oõ¬#?m~ t¾Ë9Ï;|+ß÷ÞÎÈã£×ÿ` t²»/ß¶v|”y)b߃±B–Ä…Ô¬ïîaL!?-Ø$9ÜÙÛñÞûqý¶æåÁÁ‰R~ˆSö {p,‰ ©[ß]Î¥˜ŸlÜîÍ=SÊJ7C¥Ã'¿|þüiGœ¤ïÁ±$.¤~}KK§Ø×§ôÅ<Õäëî;LP”>.m‰£$¶´öÌ”fJkSÿM´ ç± ¬› 4N¿¾;Â&„âÏæ-úU`b”ry¡ÒÐg'éÅ˰$¡qÚõÝÊ#æoîr~C)ã^Å»™—Á/zÆ&m£É †‹¹IBãôê[^&vÓó Ý88ú– {4€ÇÄ¥iÖ빪ˆ?KÒ²Üak˜BiJôÅ´5 âÏœ’c ¥)Ð'.6þµ&y¯ QrL¡4y}bË^Üà/†WšÒ¬<ݪà ¯4…VU}ºÝ®0¼ÒÔµôÊÓy„¯ÃðJ‹ï}×£è>T†WZüâ ¶¤_Ÿá•&ð$ãÏ–Ž51¼Ò„š} ø³;Æ?^i‚®(ÄHý]cò ¯4Ñ×#í³Gîž'ÂðJw.õÎhZ%ÇðJKâ\ê‹?[9äÉðJKä\jZÜ †ŸÆðJCä\ÆñÓ^ihœËx~Ã+ ‰s98ˆç§1¼Ò¤œËº2‡ nÌÃ+MÊ¿R&ðÿ0¼Ò<0‘(9†Wš´‘ á É`x¥É;—RaE¢aB ¯4I"þLø£ ¯4%Îe§— Ì0¼Ò9— ,J";ÆðJS•„[¹dm+Ã+Ís™ÔOcx¥™q.ûi ¯4Îe+—ØOcx¥©v.W÷šHõÕ0¼ÒT§•=yrý‡ ¯4õÎå½Ë²}Ú ¯4 iùˆ‡ü8 Ã+MKZ2 §`ìᕦɹŒV2ÍðJÓ•nÍVP3G‚ᕦϹ\˜A£jh…ᕦ1͆äÔùi ¯4çR¡ŸÆðJÓï\*õÓ^iÚËþU¥Ÿ¦r¯äóü½é®Q:8p‘’tK'.‘$’D2yÚ;&’å*%YlI5ÉiI"I$‰$‘LIµ ä}&©V.‘$’©&™oI5)Û%’D’HJ¤Ü9‘Ä(—HI"I$‰$‘4L²{Xt1±ô'Áë:Ϊ°ˆÓ’“cz“ål×Â$«Ö~£©{¢Ô ÙR»Yß^¾Bg4É^±6´*¿´È ’‡Šøé—-JI²kA¶ó’omƒ<äš™'9ê€{Ǻ–\¨À.>Ú(Æ&Y­7¢Ç{R62,w»“¤lId:69è¨È^dýŽ ©vâQ<ÛSJþÙú6¸ÜHsAÒÀœ”¶¥º®iM‘ö„áxS‘xÕÊÁOkï?Šw kEòq‡\¦ùU\?I,r‰$‘$’D’HI"I$‰$‘$’©!9"’jH*ظP7ɯgT&•|4ÜÉѼ…SG™ô‹ÅCs§ˆd é9ßÜ÷å.GÍÿ`ÌÎÔ‚Í|''6|`|S_¾°è•æ†HNj@2|îß:ó™¢/L²Ðá{J¿Ÿî†î~Ü ·EîLv ö/ 6¥~ͯµËan„døP Óçî~œÌ§(„™²/L²ü¸~ëïšz¹ÑñINH}ð•ù›ŸÏ‚&9¿Óxð܇OýmÜŸÖn^#÷à“œü¸úy÷{;‚¤_\ƒC›an‚äô¡$ùs¿|à© 2u^†äÐ~÷­s‰›d(… ›>wöüÇ37ÈÔÉ•!y9i`p×î9’ásçíɧŸìÂ4CArRAþ¸Aòz·<5yÔÍ=ùjp,€²Ô«o=dÉQàruspoɃ3áתoKó€ EYM7½$'÷wáVöŽ—ï%™’nw? `‹ï-_tãÿ ܆Ô—[fIEND®B`‚qbs-src-3.3.1/doc/images/qbs-settings-gui.png0000644000175100017510000007520415232633614020440 0ustar runnerrunner‰PNG  IHDReÕ?ϘzKIDATxÚí{|e¾ÿ³ºêTpwÏË=ççùýw¤^V=—¥p÷·g邲»¶âîžÕPu¥€®PhW‘V.M¥¡”k¸X®å#(‘K( ¥)e€›®ÚÁfšYí¸Íï;ód¦Ó4iS(ÚÖÏûõ¼tòtîòÎ÷yž<_SYYYiié‰'JJJ<øÑG}¨²WÃÞ–=mÙ]À·GT7Eø+Ânºõ˜ɆäD2#ù‘,I®4ÑÿŽ?~àÀªª*A‚MAr"™‘üH–$WšÈœôÂ_ãÿâÊŸ×^÷·ºÏj?CAAAAAù.²!9‘ÌH~$K’+MGŽQ"ËÏ…¿ùÿ†‚‚‚‚‚‚b,äG²$¹ÒDÚ¬û¬®¶¦¥}!K’+Mûöíã?ãýŸúQPPPPPPÚ²$¹ÒDƒ‚¨q¶ærMÌâ.ýtñ’Ëxþrâh¥üáyzI•m¢•Ë•îËÎÜê­)—Vý„ -ÐKªŒgÛãçOÍ9ž—ôá¤ÁÛþƒ -ÐKªŒg[”ïN¹tþn Êu-dIr¥‰ÆÔÒ‹O}ŸF/îó™Óš~öóÐøñ¡§§”ñãé%UÒŸbn¥_ÙÞêí¿oÜ<ìkû¶L¢B ô’*éOo»ýì‡?Û÷GÓGÿi::ÚtêJ¡…þ“*éOo‹‚ÒíÅwéÜÞõ…¯OuÆëo.]³ýìy«/?¼õчŸù¤âb×÷é;þÑÎw^Ÿñêô×­+¶”UV_݉;iôáGs·ºð¡ \¿B–$Wšè')—«/G/'ݾçÓ¾7.ôÌ3¡gRC©j¡…gž¡Jú­kÛjï‰êm¿ÿj×#-‡G·ÕZ¦Jú­kÛOªNþìÃ?š'ÝRö«:ý«[K•B ô’*éO´BÌsFAéîr±âø´Çÿû‘Ÿ<òÌä¿Ìœú{Zxä'iÇ+.ÒŸÎ8‹ùÉÿ¸Î^èê>w¾÷ í'iBZfÆTu‡ÿËvµ\ðºžúÉ#¶§ÙKõ ©Ç+•õ/–Ÿ9ɼûèY¼M((×µ+Mô»Nß%_ô’·X‰,[e™¢–°2•(3oq¬m«.¤P2,˃£Z¨å`X™J”ypa¬mg}’K¡dX–§þ§Ÿ[)´VæGÿI+Äý\–«ì¼qó*Ï‘_<4¢pïI­æÂÁí[>.)S6<vÝ»a&?÷Ž»œ£ø½ú’ÊcOg»¶ÚË ënõ¯‰[e´ð§Ñ*Ú¼&Ѱ-;“÷þò{¶þ{k¶¾óÜÓœ¦ú³Ç¼úôc¬þ­¼Í•ÜE¼×((Å—;wî¼È]ŒZ|#G)–,²$M>ý´RR´(óéßÑ ±¶½¸r„ÒgyH +™,Y9 †˜“h…XÛÚú(uXR,…•¤É:ñK*´ D™¥¿¢?Ñ 1‹‚Ò­¥ìãMÇ ßK­¥†Ês¥F¾zÿÉÒ7Ð_‡{v÷Ç%û·®¡ÊŸ¿´œã.:7½;|دw~|¬ôØÇÏþÿ^YeÜœ«:ýÊcÒ†µ¬9pè“ò NÿÓM>ì‰õÅ»î¡ ÿ{Üœ3ç¼wÒÊóVmûä詪Š3EKfÑ:ìq”–Už;sø õLhá×Ê™üvçÇ%öl Ê_ä¸Õoüjø°‘k¶î§¦©¥•/œ÷¾û»¤¤ßes{ly_­<…÷¥ƒB®4_8!j‰Ç—±¶Ç—±¶Ç—±¶EAéÞâþhõC&—œ9g¬ôZ^È*ðœ;Ïv›±lOUU%mxdû’‡{ðtå¹³JýêÜlÛÓ7P½Ó£´Ò㫞 -Ð:+ö…×Ù2oRâosN{QeÎÆÃ¬²òÔÇ?UW¦#½™ôHâo3Oœ.?¯üéüy¼×((r¥iÇŽô9j©žô§ŽÛci…XÛ^,ú]Çí±´B¬mGîIí¸=–Vˆµ- J÷–Soxðþ·)3VVœø*×í?yrÿºïÿ¯OUVþ½¬<}ì­~GëPù_NÞuðdŒýŸ;sêäúÅ™´Ú y;+Nü•º‰¡üê੊ŠÓJ}áÞcl+õ ?;¨”þô3õOú[ggÞ”ŸŒ|ýÄIÇÏÔó ŸöÉÔÖ9¶oËïFþ„åϯç´B¬mQPº·x˦ÜÿÀo笥å³'öþÏýä}ðáæ¼—¸?åh¹÷ÄþµÜÿ¸ãÔY¶ò¡M ¸ÿh/ÏUœ=uÌ™>rĈ‘§½•ú>KKv¾ùÆ¢O<^­¦òí_>:iþVv¬›éõg¼Ñ((r¥iëÖ­••±ÊùíÅÿ÷ùöóP%ý©ƒ ©œûdû…ÍÏ´Ÿ¯€*éOo»ñäŽÑ{žm?_UÒŸ:Þ¥ÛËîU îzŸ±|xâ Õb/xè¿&/ΙÊ*G>3ûhéYª/ûdÿsO<Ì*ú¯ÔmŽ“;t¯mØÛ_rV—õR}…çØ;æ_jõã?øðuýŠÍ–Yê®fœ*¯ ufLøOzù»¿n<ãvü¿¡÷­Þ{L_`û߾襇Ÿø«ºÏŠ–¼¥ëÿ­°­¢…å»Ò o°>ªýwSæ;]w¥ƒB®4mÙ²¥‚þÆ.•‡ŸŸ¿ðâ3ôýtZ —TÙñVáròPÕ¾yÜ¿¹X8‚ -ÐKªŒgÛK3œ9ÿ½ûéA[¥B ô’*ã:. Jw—³ee'8qì”Ûµÿ™:ú¥ürÃ_ÏP6ÙÒ²ˆMÎPÆûòË/¿úê«ævÈ*úˆ†²[<¾$W—ú²/=Ïa•3gΫôåÒ¥KáKðåÒ¥K¸ ôa_~ñÅ%%%‡4œNçÑ£G©²«¾$Wš¬V+| ¾³\¸p᪶«//¿Àí Çû’"ËCœ*TÙU_’+MK–,¹ _W’é—%|P]vÿÉtã›{ÎãM½Ý—¥– ÃÞú¸õ9÷ízÀôÇÒvb ò3ͬÅí Çû’Ú`Ûû’*»êKråÕû2ÑôÓƒ|0(]|ÓtSrÞa¼C ø²ñ¶ÛM/œÓ^žZúäW÷¶ß*È;“ï_Ðó}y¨-Ì—´p5¾ÌÏÏ¿êøò„ÀÛ~3xЫ;µïßÂþ<³IåMÛ1åÛºõ™§— s·NNÉ;†7ôd_RCë»ÿÞoþ‰Ï”‡\ºLßß/o gßýM=Õ7˜†Îßã5úÒøTŸ°Lž_R£J×ñ§¡7Óú·ý4ãDm7€>àKr¥iñâÅWçËÿ1Ýð¿zp)Sÿ–Íí˜:è§‹|Ê_Ë^2}ÿ½ÒÏÏ­hšéÓ>zVžkÄ z¶/¥J[Ú—v*Ú;·‘=½ö,|ùÝ]ô¥0xa×­¦‰Ô<«û²$çñ‡Þr² Kþ:þ̓5Ôâòªé¦ù•aDgliƒš/à.Ðû}I®¼&_Þ÷ÛkºAï¹Üÿú˜û_ʵÙV®´Ù^½÷–§mIúÛ[¦›Wk ^Øh4+=Ö—äÂûMË)^ÌyiTÞ±ãK'¤¬ôà]=ß—’ ^†wyÓ”°Ã§´¦É›pËÈVnÞ½oÏâ_–üõáaï†;ï÷¿2Zõå‡I¦‰¶=ôÏ`ÇžýKJNÔ—ô~_’+Myyy×2Þ‡5:Ñ ú}få¤A¿]¡¶> {rÞÞq®}[ÿ•)¾°³•èñ¾”üÑ·@ía®Ïû÷~¯íW:&ý%Ë ¾Ì"_ú÷ÏüÛ5‚òœ+£Ä©ÿ2(£F—U¥Ÿ+ÿ Êw¾ýî.´ÇÐ|I®¼&_–„(l~ñ‡ƒÿ´Iþf{ñ!6ÞçÁ?-ñi+ïxñGôW|ɽŗÁ@uÀÿEëhðŸX“`ú=Õ¿z5çÏ?ýMØ—?Í®U5I]ô' @ßøÓ¸ùkZ×O¸‘ƽó!ÐW|i±Xºw¾‚€@åø·¼ÿ¾ýmõs€^áËÏu̯|Ï í×ç|G Ïø’\Ùý¾l†º©mjÀŸVðxAóá_ÆëËÜÜÜë:›xóôj_’+M‹-Âü±àËlH®ì‚/O=žëåË… ÆéËÐã¹¾$W—àKø| _ðeL$ÿ)KƤI›D<¾_.X°àZ|¹mÛ¶+W®|³·¢©pä€~©ïØ]ž ×ß—äÊkõåüùóéWœG¥3ûÆÂKë½ýó¼_á™Ð›|É(((à8.΋i‘Ê''N9äÙ›J)ëM¦~ɳ=B Õ½kƧ¾³"ûIªÌq}N¡¤Ó:Mà>*½À/+šM7²š©J{¬X™2ŒÕdfû÷®˜nÎ^’‘Øÿ&ÓH—Øs˺ìq¨òÖ„çözÂ''VZ´•§YJZeû=È|ifjëš2R€/;õ%#ÎæÙ©4ÙtÃ-¦_{jÿ˸ƒ‡.B¡€g9¹g|æ&/ÇùEÙ³dâm¦ç\­CbdÞ(‡$Þ&sè­¯Ÿ¦9®[Bµ™¦›ïH_Ëñ‚ϵá>Ó÷²œŸÑþiCÚO¶ý$çó;\g©ó¼À_X—ñ“»L ɾl‡·¥.òø…:ï.Zy¸åxŒ£HE)Cdl§©që<iW+½MxL Ïú’$×¾$( 5m/s\á—â1’Ðz.ðä4½Æ³ÊÐåtÓ÷§Ù/Q 'É¡Ïr Ý,†š¨=6Ç­lP+]BsH¢8PvÎyxPòrZr玞}œí<žuš¹5$oÚ9[Ù-µ„£Jß)—§&Æ”Óh^ë—Ћ }Ü—d·nöå–-[h‚õxâË$Ó v³æËòežûsò%š¢&ÑdµµV§ŸéiæK˽ýrÜŸ‡´xÔÈÀä|±/;]‡Îç1S"µÜÜùƒMs#. Ö$ß‘ôÄ~¬fªe·€‡àËN}¹lÙ²ªªª8/†Å—yîF£>©=“|ÉÚEUê©TíÅŒ Õ—ÔßIq¡§]ϡхñ¬£û’V6Æ—²Pëóbí!Œ$Öx?¤óO+ªÂc ðeGãc>Ü¥ñ±ä'és{ ·? Kµ¶ôÔ ëW"9£/eû”VÖáƒäÈC–§h_[_¶Èçh?ã³w 2¹­’ú5'XOGº0žu4_ÒÊ4žhXÆ&^ 5 ¥´<8ûHÔ=Ps1é|’µ„4Ú,”«MÇŸâ1ø2º/ãl€mïKòÓŠ¢<Ö˜© êñ‘CÆöXb’JõÆØÞ‹/ÕþËpÜôHÕšm4çûÔ(Ðcpa<ëÐùŒ2S{CÍþ#ú\”ËVŽº‡ç2jFf•ã3Öú1@àËî߇ùRmö”EQìX4²$‰b'cj”5$ùÚ×i]YY[Žc²Z‰çúº/ß}÷ÝoÁ—â1ŠÉœb ÞW=ß—äÊoÇ—ÊØR·Ù_À—| À—ð%ø¾_—àKøRA®wþ559u³7P]ü*Mwà•h*»Ìk1æàKø2L}Ö ¦kñGœÐ\ç^=Éœ¯Ì¥ç6Î¥¾ì1¾¤ÉðæGƒê¯ë½(Ëý» ÓÝ1ÚÎ= ¾ì1¾¤™c)…f„,©¦Óe[¤òɉSyö²IYû%ÏöÊ\?” d|ê;+²Ÿ¤J53I“Ó:=Ç龤åx.†%ˆ¶û›5_–/óÜŸóy‘D“ 9¥i¼ÜùÒÔ–Éù¢2eí‘ôÄ~¬fªe·€g àËox|,øÿ0_ê.dú¤Rc$kVÍÑבÏ)!i¾¤MjÅõÄŠr%±Æû!.­¨ OÀ—ߨ/i€Onnnü‰£I4Òçö„n@–j))45ÃúÛquÍûù¦—]Ê:õöì§Øï,;õ%™•v>>{· ‡d¡2sè­¬§©u—ì;ÉZBmÊ©¥wšýSþ‹aù¢Wå±ÖQ¡ÃdòÓÛcUêmSÆD¬j×É61nô`#o•µæ|ŸkÖ8—Q«/«Ÿ±Ö²_öðù ˜/ÝJ°(‹¢Ø±¹dIÅ«¤£l&É‘;S*ñ8|Ù+|)£ Ï)¶à}_vûù8æâ_ð%_—àKø| _€/áËèH²F&oöð | _ƤE,U'gÿ À—}Ê—lŠööÄ?i{_Jð%€¾èKšœ}Á‚²¤š¸&m+-)ÃØL°Ó¬¥_ åóhö×IÙÛÙî¼+¦›-ë²Ç  Ê[žÛëm`{ªv,f“ÊŽÊ(Øa}!­ð45€/{V{,t„/©¦óPRÍóu[ê"_¨óî"Û ·7øR.~þ‡’q‚XÇ)³®³¼]ž%IŠKçþºŒŸ„SšxWSeVÑQ^à…Óiy‚å5€/{–/eY.((ÐeIËTÓéV”ú&ÓHu®v5Ôôryj¢´ÇÊ4Õºä˜óððì#¡¶)Àš9%A¦[l¡Ê!æmúE)CH½xÔ¾ìqã}8ŽÓ}IËñlpç6Íh´5úÒçx_ÏÛ¥‡ŒF_²ì(.±Å1óîÇ-¥úN*–<¡¯¾ìYãcÙÀŸø‡ù½kŒñ¥,ÔúüÝ—-Ry²é†,G T3ÌÕ—”GsHêF-¤•mã!¾ø²‡ú’øäææÆ5̇ÙN>g6Ý8,c/…š…RZœ}ÄàKe!ËN¾”k\«(Ðì ¾dý—“­»9Wœý,ú/¾ìÑ¿¿äy¾Kë7û&Ysë¨ôŸbaåRO#ýµ¢ø-ö§~ɳ—dŒ£*ÐÓÖ—£LãÜjöÍ€w—9ñ~Åš…Y'¢=à˾6_$‰¢c|L”:߃ÿÔNûI}=ï3X¾Äü±­´ǨÁöŸ’gØl…éÉwÜ`J(öñ¨| _¶ 1ùÊbÛRKvv^áNhÆsð%| ¾„/ø€/ø€/ø¾_öN_²)ÚÛÿ¤íà˾ïKšœ}Á‚²¤š¸&m+-)ÃØ³Ó¬%e:ÙòɉSyöRri6ë¬GP¦–U¾ì5í±tÁ¾¤šN·j Õfšn¾-u‘Ç/ÔywÑdx”À‹¦_§¹Ú)ƒt±§F🱌8xèBA–=j=ø²×øR–å‚‚]–´L5nð,7æÎ}§\žæÅWcØ©¢2©ìz.«Ï"À—½i¼Çqº/i9žMîüÁ¦¹1"K™i÷7k^,!/ê©4Û×ãYø²—eâæô®1Æ—²PëóX™çn4ês¥·)V=žE€/{™/i€Onnn\Ã|˜óäs”hzXÆ&^ 5 ¥´L /I„4¢çö„n@–jmé#š^ó«‚ŒZ¾ì}¿¿äy¾Kë7û&ÙøØQé>Yñâc¦ÄEy¬ò6Ós5 f¬zðåwe¾IE)<>ˆyQm¤•EQÔG Ū_~ç÷¡¯>:Å–8ëÀ—ßÍùð$ç»P¾Äü±àKø| _€/áK¾àË>‹×öJZáévÕRQÊ;3v_ÇKõn§ÓÆÍñâ5Ÿ3`ÈœÛå“Ôéø¹z-p§NqPèŠÛ}?þ„/¯’“¹ÿ1<ûH{›9æ½0ÍvDsÇ›ÚòFQïQ“-eôROc‡ç Â÷*Çtsާ±"÷ÿÞ•©Ü%÷¼{~˜y¼E>þiº_—W‰;wìðìãßüqÛæ&“OÚ^1N%ßÞßÖ{û縛"ÎYF¸Í—t¯ò¼Kž`w‰n׈ìÒ¹ôÉ{‘ø¾Œ¡<;e æÒ,ûY¨'wì¨ÌME™Så ¦„<Ç%¶®wÅ‹ÏZY|)9­ÓÙV™çy„°ÒjÜ(ÿ URJê•®m«éS ÷¦§zò«çŠ^yȼVko•s~6©ðtØ—ÚôC-r9íM ›Ö7ØáHžáâ›[¤òtÓ÷YÍÀÔ1|ÎkÙQèèëÝuxo__—ÝCK¨6Ótss¾—üžIN£-%Š/—ü¬3µð Ÿ÷-z“–×{Æγd"9©È]-Š—­ã²$'An#­ùº­„xwÑ[´¼RÝŠVVöVt”â´¾@Ë;}ÍÍþÝ´àà5’ü’Õ´b¹¯[„#”ž“vÒàZ@ÚÞì©…ËëÒt×ÐÅbHâýg2‡Þúzñižô£äØËÁoÏ~ªŸéi¯„iÿtd¯Óé[Dî§Wù&!x?9쥎ÌúOœÈ€/áËNˆðu2Í”-;dÜícT¦a>z#-´„.Sl—åÔ²LKµ.§›—•oHêF}çö)ÿ–kîØÁû´j¥uŒå„ÒB8òŽgmUTUçœ=È4‹Wχ¼Xè8êv»]ŽÍæ„›]hÈÕ"S[kkUªi“Ú£ü =|šVþ~S¢ ÓäàKø²{|éÎlš+^’>I3Š-¥újÆN/Å—â±$CÒiÇÌ»7lå]2‘¤+±­,­½¡îy²½Õ8þr—i!­@>ž`;Ëü­´ß—˜””t_RÒÔìüª´%ÿ±ŒÄþú  Á‰‹™/-÷öËq‡µmìseiXàK| _v[|Iͪ- zò•—R‹)š·µFŠÏÿ =ÕœTO­¸Y®ÏõÑçóQn0úëÌ»ô­œ3̶¢½Ý•q@_¹pä&6j†ýµ)aç0ýשö€FÄ»zXYüü¦oÔó º’e ¾l„/ð%|y}¡–Õ ÓM£3·ó’àKi™5œj}g%Y>ï\FËyj§9I¶Ï¼›rM;}Ô=ÙDËw˜^ö‘ɼkhÍ¥Îó’,U»Vé[±½±ú û|µ74<¨•†ùÐËAæ²æoà¶=MåwŸ´Ž Ë&3ñ6-¾¼B¾L³Ô±ð%¾„/¯#Aÿ³éFÖÎ9*½€µzr'>¾(sÜVÿºí[ÙÓê¤z[Æã쯷&<·Wùå»BEñ[z«iVÑim«‰7šç¤'ö ×·Þv6D(G UY¼ënç¹fÿTuØ-ÙtNvšæËǦŒEbÝ™ø_—×IEIŽV/ª•?êPíµºY»ä¶[…ôÞÐö¡¯§rñ ÐŒqŽ_—=šLgˆþ‘.A?õc¿ù‹Ø¡}γÊ>mx¾ì;È~¯‡ãƒW¼ò—}Qf‚•=Žw5î,À—| À—| _€/áKð%|Ùz7NhMÈÕéBÖÈäÍñýø¤ºøUúféDk¸~—`¸Ùçv9]a<Þ¹»nÈ·ŒÌ¹]>)$úÚÜI‘;å¾ö+^pº*b½ã”d&)œ”-Öæ—?q§ÿs.—2­"¾ì™RZv šœ]›Ç5 -b©:'ûçñìªÎ½z’9ß{…¿à¼ÖKÓ/Áp-Êœ´&”\Sˆïl'=5—ddþKö¥¦ðßo›êøôw]Süç$®‰õŽ·Hç^™Rì Æ~æÒ¤ÿRHÊ3Ýb˜”_ö0ŒÓÈuÍ—ž})©ŸžežØkÜWu’^š~ †ki3‡{ƒw]ÅöOã9Û‰ÔS}I¹Ïò¼zªå=’Ïé3Ý_ 4ZÑ¥«~ǵû&©ÙÙàKàËž)Ë/²(ŠšCÕY[›œÖ鬿ÁäÙý“T(ÏNÆêÓ,ûÅv¾¬soHVçw½ù¾§×»k˜/©&£°MNû`ê;^¡™}p;¬o°]=<ÃÅ+•4Qû蔵]tÍøÔE¨9¥Ù¼µr[_ÆZAæK3SÃg8ÍzPniB¹Å<šÕLÊÞ.tâËÖÔ+¶qƒX–¿kCjÂÍlÛ| é5ŸúHÙ»ú›ó½¼à÷|HŸ‰£-%FÙ¹­ôñ7µð /Š'm¯(éG¸ }zÒ é$WSç?•9ôV–ù„&Œ¥ŒÐ›=u¢py]úîºØØÊò_>cÙíø2U<;}ÍF_ÆXAI`2 ƒ²¬Hužê¤}Mm/MÉ6 y'ˆuœ2u{ZQUG¾lílS’Z+)?¥rºð´ÂAÊìóéh2÷ˆ»ÇÎm|Æ&Ž8§šž¥ƒN»oü­ö:>±Eä>qzëXUÅŠß Î<j7=½v·£ÜU&Åþ /;<^Ÿ_éªlñïfÙiØ;N_&ŠÜÊóc5ßEÏß°s¶m¿äÙn_]÷CZyŒµT93¡òcgɘs:¼|3>€/{z{,åö¢@Aÿ‚ß"—«Ík9)ÉmýLOÓØÝ1J²ÌÔZœL£68!mè9¥k쯶íÛ“)WkK-bôûUQ²l²Ô%_F]Ailh^ë—¤NÚceš°]rÌy˜ÅFQ}I‚œ\¸ßív»\Nkúò„±ïväèumÛc—+w&|#”4Ÿ {ò¦„ÎYÎÏbû2Ê]e®+½_é5ôÎþ e›¬µ(°†Zä¾Tþh©Ü®º#ø¾üvÐUÔ"K2Ž}\RË$ ’šËtÕÑK–¢RwŒcæÝ«éGŒ„?.µ†Í ¶²ä?–‘Ø_MÃ2s½Å j<_F]AòÑó…MµìÚ^ás¼ÏšÔ,+Ñ}9n é¾û’’’KHüµyžšã“¸Rœý¬qPÛ„ ¡(çF©¥çúÀØyáKÝdíï*[ӘЛu^Þqýù©WZ€ÝŸ}ÍÊø²ùÒÂâK¥ÝUêBŸ§.(¾TsRz´ø‘̧¼4Ä—´‡!æmú¿²OGøR[Yi˜¾IP÷t/ŒÐUÛ1D­]‰F_F]A ™DjèKÒš[[/MmMÍrT±‹pÎüqÄÞÚµÇ6EÜ%êc£ØÑ¥N7޼õ³o{­¾4æ>ëi¹pç%ûªt?¹S3™kÎ#mLf¸«ÎÓ;/CZ|™Ñ>__öÊ–Œ½3a.'(™%]ó~N}Q.@–êíÙO±ßDR;m†é¦Ñ™Ô%øRZf=‘ºÜùJ¼e?K{¨q.Ö;º¢ùRédÞ(ȲğÉL¼­}|y¾¤3$ÓO²–Ð 4 åô >MѪ_Z³z2Yvò¥\ãZEfñe¤ƒ ­Ð.0$_q¨£Ø¥ï^ïò%§u^ªÚ»H7n (Ëuž-t¯èÌ£ÞÕH_j—!­ÿ’žŠÈéùÙ‘ý3åù‘Cð%ðe!èS†ð°&VjC³M£ùthývAÿ6Ì• kôˑ͜}¾ÞP™UtBÖB:ýWêúÊÍ~e¸ e:';M÷¥Þ‘µ¹ÕÓY{ls™ÞÜ:>c-;Cã¥UhÃVi¼É’Œ1c4_¶;nSô_5Èõ¶ôl“-d'Þ·hßÛƒ}ÙÚyjûÒ¸VKzøþ´¿«ÎÓ;/™/m÷c=ÛD8ÆB¡˜¾Dÿ%ðe¯G–$QŒòSµºƒ_ÖÉbÔÍ¢~Zw¼§«>qÚ­Ôñ…I×|€¾0 5¶?Óþ——tyBûùu:º«ö)ÿÌ:/Ûm"ažàKz£‚w¹q ×UJ×Ðy €/è£2"@àKø| _€/áK¾àK¾ìe½'˜×Šxʾ„/;€%Éð”|Ù—|¹eË–ùÑ ú«ôe8m=ø²ùR„ DÈ’j¨¾Óm›ùp’,šüsGñ{R Øœ¨w&.Ç龤åx6QÒHæÎr:2Íâ Z½Á” èS®/Ê|6Ü›úŽÛăðeïËþÄ?̇¼H¹=Z´pÍ5Æ—zÜp/¤”–\kP)‹ÂkÊໆ.ÆoN¾ì}¾¤>¹¹¹ñ óaP.CJæ<>{7/ÉßZ6ö_ŽÎØä—dÑŠú8gì£õË ÿ0 ñNñhÓž9ÿ2dÜŒ¡ø²Wþþ’çù.­ð*ÃyÈŽPγ¤iñeþíI³?°†‡ÂÒ€ ¿\¶¥l0­R™ð²Ã‡öX€/¿CóÈ¢(R¤Øì]Âú/[ÿ Iê_Ú®-‰í+À—ß•ù}î¹Æá?àKø2R=çãñ[€/áKðå7ëËÿ3¥§ø¾DAAAAA/QPPPPPàK”NÊØµ †/žŠµÂŒKÜ—_Xs>ž]½^B¿ýjþŒ ÜÕëV*^ßZ»aïg›÷ú_L¯ø×Ù—VïôQý[;kßœåµUÎ)‰/ów× ¼µµöÍ–Ö¬^ÁE]§ýYé'ÐÉÃv}Ž~íå÷…5ËVœ¿grÕ²­¾G'Ÿ}dî¥õ}FïÂêÕâ™D/{]ÉñüýÊÙ«ùLœ°õ šQ/æGجOÿ ÙÂų«´­‚ÐxÕŒ·ãz•{&Ÿó| }ýµÐ(-~­bÂVšÐ"ø‹É•žPèBñ…X[½_õµ|ñ³î:o(tnÃùœª„|ŸÅx¢"ÏJ?N¶ësôk/ï_¤Ãýíÿ¦×È!édýB^hj¾¤¡ŽÁ?â±D/{]É«’å‹»_nìè#잊/Ë7TÑ2¾J÷_²·CïÈ î„*c§yÿjŸ¨'@Ç*_s>§"æ>ÛŸ•~?l×éèÝàKåükÿ-ýÓÀ×¢.ȇ×^¹–kA/áËoI–ž¿k¿íùjù¬ úXY_ž$On’¿n ý×¹—½ÿ`õ|ÿT;_¦mm°?Ý|dË%æKªñ•}QÇöÖœÿ¶—}rm®j‡øûšw½jk›ð÷ÆÆ§Ô…@£øqEø¬|§jáÚnô¥® [±Ô¿Îòy´·¸¶¢îm}ë]‹úf=2ß_ý%{¾<|\dí¨ñExvñe„/Ï}Òø û«µïd—ëBÿ8°¢ŠÉá‹_±'y£åÂæ‹ÍêrË™ý¾ÿsµG§vÔ½—Ù>C•GøOäÒ çcÝ«ÿ3¹Rÿ·ó÷† û·_ÆÕ0ƒ‚_öÌòȬ öÚȵ o¾{þÙ¿_AŸ2_¸¡úï^þ„§O„¿¿i®ø·É”<œ ù¾±Ž>T¾<÷™Ñ—c ?W>8Êê^œUõþ)å#ãÈŠ*ò¥:'ßW[V\zÁRÃQc`m½Ò£³“vÐr`ÃÅ'ß¾ää[B_‹O>A&l¤¯Þ¡+Uõ¯¼}á½’&ZþÐZ‰'ÝîËGæ^Þ¼÷SÒÛ[{ëæ¿ë ¿ÅâbËùÖ*“C}}îoF]E×¢½Y÷¤_ô+OK#=-olý\qé—Õ ïîýìÍY ýÖ\Œþ4¶=«¨ñeާ9ôecø[ÚGtпS3>;¾¢îÅ·/9j¿ÖÏjs=Ï_ÍRquG_uQ¹;7\úCÞ§ž&%/õ/ĺWyê¿[ªŸœuÉ­¬¬œØï×Òá¸{&s«Ô=ÇÓ0ƒ‚_ö‚öØ›¬|Òé=7ÿ–~YmP=¯~ýcùk†oÇÍ46GÿgO{5^yTX±³öí·½,¾<³%<ÞgÚ!òh“¡Ï¦â‘ô³iô)þäÕ}ùû Q?â•|Ù•ÝÔ“_}Ù®)²í[Lƒb6^ŠÖÛþ]‹|³ÔÊÖ]=»Wd+_C{fÛöع#[my—ö_éhjËj´¿J/šõÖÎæ¹fõfQ`÷5o^Í8²{Ò/Õ?Ö¿@¾Œz¯Âÿvìá•ÿuÆ…U긪«èÈ@A/{niýLœUówƒáX—}ª‚ ¶mMR>ƒôöEµ-_ž«Ú©÷«­üDžÖXÇPƒ6¾Ô>^õÀ{tÝ}Ùö-nÿlÄ|×Ú½Y»¿S¼7D뿬t6µ\9æ£NA9,Î6g¢œ€~VÊCx•¾Œøç@aeu(ÊF]ùZ:þQPàËíKÖ Äš*õˆt_€}@(_¨¿^<¥Â`¾¯•1–Ú?{ÚC¨¡¡u }Þ¥gx#|©­\aoh ñWþ ~õ«ô5µ‹/›žŠã#¥}IýƘ鑹ß°TtÕÉ»fÜÿ… Ê×)mWJ“i÷Æ—,fý²ñ½CÁЗ_ü¢ÚœÕ5ø’"fêòôÙ/éF”Õç9ê½báµaTmåK/=‰ø¾ìkí±rèëàÛoŸ{4ÜaóåjKÕ£3¸beYùM$µ5Ñ7ë¿_n >9¿¦:î‰ÔÿÙÿ^ùÆ:s°†ö0}¯²||MU _V:[B ôÉë}bþ§Ü—ÑâKøò÷%}7¢¶G¹öÊ 3*û©2DëÂg]uò®÷Ïž–PSpõŠKï}ôE¨µÿ²mgáüO?>UÿJg¿¸êKÖRªœ£&³®ú2Σ¯Wþ üã˜ýÓ7Öþ…×Jÿeô{U±£–ú,¿Ú`¥_[žS—¿|Ó _¢À—}«<±´NÚª|¬Ð×d'ÿµ>bv‹5üóƒ'ò>«ÓjÿÎ7¾’ÙöÖ¡ÖÕŽ)ã$iì"í–'4®üHÞgZnÎ\¸øeDËÚc¿™ß“Dí’÷7ã[ü¦úë}Û¿koùÌÍÊ5ŠEï¿T‡ê°‘8qu®¥ŒÄQò|©oÞ¦=vcçí±q,¸êTP½’ÙRãþ²…]`Ô{¥üÛ©Õþí|ýÕÎ1Ûfñ{ø² šqîÉY碘uFÕ“3:˜÷¤âÉYU¿ˆSÒ³ªžHÇ­þÆç+hÎT]y3v\Õñ[Ï»vOú…ÍÇùùÚ/‘~¿·)VÏhˆÿü[새çè¯ïä·l¸¨÷Ljï±îU¬;ávï¥;SÕèUFžc¾ø¥‡–ʼCõŽy>%ýºÎ;¨ŒÇQ~øxêÊ)õÇ‹¼ÛEÞT°ú[ûêßѧR~rzåbãአûaÌ‹×6ÕÃy5‡=WŸº²÷£OñÃbøå;_Ò«–}Ôpæb°²ê‹?v¬˜¾öò+³¾­é‚»pôéÿv¬ª©òbàð!?ZPQàKø²3_†€| À—| À—| _€/¿-_nÙ²e~4¨o6ø2Œ  ,ˆ%ÕP}§Û6óÇ2û›L¦þ /¯+zw‚y-›’µÎ½!ÙtÕß|ßÓëÝ5áµÅJKÊ0“Ê4ëA À—½«=–N:—TÓéV-òåtÓ÷ï0xy¡Ú½%ÉtÃàÄÅäË ·•Œ8µð /Š'm¯Ðòz.تÍ4Ý|[ê"_¨óîºÏô½á–ãx˜¾ìM¾”e¹  @—%-SM§[<ù7™Fº¥ö²Á9wðÐ…äKOîØ!©µíeÎåâ„æ€g¹qeÑwÊå©ÁÃðe/ïÃqœîKNÉ#Û9wþ`Ó\½Ñ6àš{—Iñ¥cæÝ[J;^|Ù[ÇDz?ñó r)dti!cc6‹/Ý_š·é« ~/ÉAïc|) µ>À—½Ï—4À'777ža>Œ–Ðå ÓM·'¿ãâ|eŽ÷©Ÿ’õ_6¸ói9Ï~–šdkœ‹iy¥·©E>g6Ý8,c/…š…RZœ}À—½ò÷—<Ïwiýù¢5}<‘ò²Ïgñ%ÁÙç›4²ŠN°¾ÌfÿÒ$«•^à“ñ,|ù]˜¯@®uÙ½‚>ÞgvÛJYÅö?‘$ª…*¾üÍï#ÙÆ ºÁ”`±Ù¬™“(jL³Æó¾lb^q;6[²3³-+œÞ:<àK¾àK¾àKø| _€/áKðåwÞ—lŠööÄ?i;ø²ïû’&g_°`A„,©&®IÛÅJKÊ06ì4ëAš9¯E*Ÿœ8ågoªéªì—<Û£N¶«|ÙkÚcé‚#|I5nÕªÍ4ÝL³´{üBw×}¦ï ·o‘J“M7ÜbúU±§F🱌H¸ Š/£×€/{/eY.((ÐeIËTÓéVÏrc:LÑwÊå©a^Ìq5†*#®ç‚±êñ,|Ù›Æûp§û’–ãÙ$àÎo›ÌD¡TšdºÁîoÖ¼XB^Ìs«Ï"À—½l|,øÿ0Ÿ w1¾”…ZŸ?Àâȹ¹¹q óaΓÏQîèa›x)Ô,”Òòàì#$BÑs{ ·? Kµ¶ôM¯ùUAF­_ö¾ß_ò<ߥõ›ýGH“l|ì¨ôŸ¬xñ1S⊢Î'v¡|‰ùcÀ—ð%ø¾_—| À—}¯í•´ÂÓíª¥¢”!wf쾎–êÝN§+Œ›ãÅk>gÀ9·Ë'©Óñs ôZàNâ¡Ð·û<~† | _^%'sÿcxö‘ö6sÌ{aší::‰æŽ7µå¢Þ£&[Ê襞ÆÏ„ïUŽéæOcEîÿ½+S¹Kîy÷ü0óx‹|ü!Ó,$t¾„/¯wîØáÙÇ¿ùã¶ÍM&Ÿ´½bœJ¾½¿­÷öÏq7Eœ³Œp)š/é^åy+–<Áîݮ٥-ré“÷"*ð%|ByvÊ0Ì¥Yö³POîØQ™›Š2§ÊL yŽKl]µ²øRrZ§³­3Ïóa¥Õ¸7Pþª¤”Ô+]5ÚVÓ§î)LNõä?VϽòy­ÖÞ*;æülRáé°/µé‡ZärÚ›A69¬o°Ã=<ÃÅ7·Håé¦ï³š©bøœ×²£ÐÑ×»ëðÞ"¾¾„/»‡–Pm¦éæþæ|//ø=’œF[J_.ùYgjáA?ï?Zô&-¯÷Œ1œgÉDrR‘»Z/[Ç dIN‚ÜFZóu[ /ðhy¥º­¬ì­è(Äi}–wúš›ý»iÁÁ+j$ù%«iÅ"r_·G(='í¤Áµ€´½ÙS' —×¥ÿ计‹ÅÄûÏd½õõâÓdš)[2vȸ5ÚǨLÃ|ôFiA–%þLfâmZ|y…|™f;!©#báK| _^G‚þfÓ¬sTzkÿôäN| }Q測þuÛ ¶²§ÕIõ¶ŒÇÙ_oMxn¯òËw…Šâ·ôVÓ¬¢ÓÚVo4ÏIOì®/n½ílˆPŽª²x×ÝÎsÍþ©ê°[²éœì4Í—!M‹Äº3=ð%¾„/¯7’$Š’­^2T+Ô¡:Úku³vÉm· 齡íB_)Nåâ ã¾„/{4™Îý'"]‚~êÇ~ó±Cûœg•}Úð.|Ùwý^ǯ&xå/û¢Ì+{;îjÜY€/ø€/ø¾_—àKø²'ônœÐš«Ò…¬‘É›ãûñIuñ«ô+ÌÒ‰Ü)×pý.Áp-²ÏírºÂx¼5rwÝo™s»|RHôµ¹“"wÊ}í7V¼àtUÄzÇ)ÉLR8)[¬Í/â:Oÿç\.eZE|Ù31¤´ì49»6kZÄRuNöÏãÙU{õ$s¾?ö 1~Áy­—¦_‚áZ”9iM(¹¦ß!ØNzj.ÉÈü—ìKMá¿ß6Õñé5øÏ?H\ëo‘ν>2¥ØŒý.Ì¥Iÿ¥”gºÅ0)1¾ìa§‘ëš/=úRR?==Ê<±×2¸¯ê$;½4ý ×Òf÷ï.ºŠ7ìŸÆs¶©§ú’rŸåyõT3Ê{$ŸÓgº¿h:þ´¢KWýŽk÷MR³³Á—À—=S–+^dQ5‡ª³¶69­ÓY̓ɳ=ú'©Pž2ŒÕ§Yö‹í|YçÞ¬Îïzó}O¯w×0_RMFa!›œöÁÔw¼B3ûàvXß`»z y†‹W*i¢öÑ)j»èšñ©‹>PsJ³ykå¶¾Œµ‚Ì—f¦†Ïpšõ ÜþÒ„r‹y4«™”½]èÄ—­©Wlã±,+~׆Ԅ›Ù¶yŽªöwvrgâÂCÚ ºiÖƒ=ÉQâKº™Øñj¢˜ÉCŸ×§íÕƒæöw•Öœ:rÊÅK©†ÝJ9NÉP7ûšÙ;ži+JO¸…þÚ?)üæê;gÛîq¬¤àl²bŸÄâË…ˆ/€/{:²X_<ó'Ã2¶ûx^ITiHÓ{ª¾²0}ø@Ók>õ‘²wõ7ç{yÁïù>G[JŒ² r[éãojáA^OÚ^QÒpAúô¤ÒI$®¦Î*sè­,ó MK¡7{êDáòºôÝ5t±±9”å¿|ƲÛ/ðeªxvúš¾Œ±‚’Àd@eY‘ê<ÕIûšÚ^š’l@ò"Në8eêö´¢ªŽ|ÙÚÙ¦$µVR~Jåtái…%‚$”ÙçÓ%ÐdîwÛøŒM/pN5=Kvßø[íu:}b‹È}âôÖ±ªŠ¿œy ÔnzzínG¹«LŠý^vx¼>¿ÒUÙâßͲӰwœ¾L¹•çÇj¾‹ž¿açlÛ~ɳݾºòk©rfBåÇÎ ’1çtxùf|,_öôöXÊíE‚þ¿E.W›×#rR’Ûú™ž¦±9ºc”d™©µ&8™FmpB8ÚÐsJר_mÛ·'S®:×–ZÄè-ö!«¢dÙd©K ¾Œº‚ÒØ8мÖ/I´ÇÊ4a»ä˜ó0‹¢ú’9¹p¿Ûív¹œÖô1ä cßí ÈÑ;êÚ¶Ç.WîLøF(i>'öäL ³œŸÅöe”»Ê]Wz¿ÒkèýAÊ6YkQ`; µ6È7}© üÑR¹]uGð%|ùí «¨E<–d0û¸¤–I$5—骣—,E¥îÇÌ»WÓ \j ›AmeÉ,#±¿>š†eæ2z‹Ôx¾Œº‚ä;¢ç ›jÙ-´½4ÂçxŸ52&¨YV¢ûrÜ@Ó}÷%%%=–økó<5Ç'q¥8ûYã8 ¶ ACQÎSKÏõ±ó2—ºÉÚßU¶¦1¡7ë¼4¼ãúóS¯´»?7ú2š•ðe/ò¥…Å—J»«>Ô…>O)\P|©æ¤ôhñ#™Oyiˆ/iCÌÛô ~eŸŽð¥¶²Ò.:0}“ î-è^¡«¶cˆZ»¾Œº‚2‰ÔЗ¤5·¶^šÚššå¨báœù㈽µkmЏKÔÇF±£Kn>yë'f9Þö[}iÌ}ÖÓráÎKöUé~r§f2לGÚ˜ÌpW#œ§w^†´ø2'¢}¾¾ì3”-{gÂ\NP2Kºæýœú¢\þ€,ÕÛ³Ÿb¿‰¤vÚ ÓM£3©Kð¥´Ìz"u=4¸ó•xË~–öPã\¬wtEó¥Ò%6ȼQe‰?“™x[ûøò*|IgH¦Ÿd-¡hÊé|š:¢U¿´fõd²ìäK¹ÆµŠÍâËHZ¡]þ`H¾âPG±K3Þ½ÞåKNë¼Tµw‘nÝ@Q–ë<[è^Ñ™G½«‘¾Ô:/CZÿ%=3‘Óó³#ûgÊó#‡àKàË>BЧ áaM¬Ô†f›2FóéÐúí‚þl˜+Öè—#›9û|½¡2«è„¬…tú¯Ôõ•›ýÊp6ÊtNvšîK½#3js«§³öØç2½¹u|ÆZv†ÆK«Ð†­Òx“%cÆh¾lwܦè¿jëmé#Ø&[>ÈN¼5<Ѿ=¶û²µó2Ôö¤q­–ôðýiW#œ§w^2_þÚ4îÇz¶‰2pŒ „B1}‰þKàË^,I¢å§ju¿¬“Ũ›Eý´îxOW}â´[©ã “®ù}ajl¦ý//éò„öóëttWíSþ™u^¶ÛDÂ<=À—ôþFïr㮫”®¡ó_ÐGdD€À—ð%ø¾_—| À—|ÙËz7N0¯ñ”| _vK’%à)ø²/ùrË–-ó£AõWéËpÚzðeò¥  ,ˆ%ÕP}§Û6óá$Y4ùçŽâ÷&¤°9QïL\xÔþ^xþÏÌíÚŽ®Ø-/„'ƒ5/òŠ-x¾ìMí±tÁ¾¤šN·bùCú›ó½¼PíÞB³]k“˜/'#ÞžüŽÇÏW{vÑ´à£-%´~s6¥Ú $AñBö½ýXædðe¯ñ¥,˺,iYŽcÒ2ò"åÇÐSøÖ9fk97–kYG\sYê¥óE/Q½Ã×€ùоì­ã}8ŽÓ}IËñl¢¤‘2Ì4ätdšÅ´zƒ)Aѧ\_”ùl¸=6õ·?ˆàËÞ7>– ü‰˜y‘r z´h1àškŒ/õ¸3à^H)-¹Ö R… Ö”Áw ]Œßœ|Ùû|I|rssãæÃ \†”Ìy|ön^’¾#´l쿱É/É¢ÿõqÎØGë—þa@â;œâѦ=sþeȸ5C ðe¯üý%Ïó]Z?àU†ó) œgIÓâËüÛ“f` …¥A~5¸lJÙ`Z¥2áe‡í±_~‡æ+EQ¤H±Ù»„õ_¶þA’Ô¿´][ÛW€/¿+óûÜsÃÀ—ðe4¤zÎÇã·"_—àKø€/ø€/øt‰ wãóÚ˜séI²F&oöâÙUuñ«4WŸWBf±ë‡ìs»è_”ÃéVO‹—?q§ZÎåò‰Ý3˜ZàNâèí¾âvŸ§=ÊÂe:áòTc´6ðe_À»âÅg­§¯bÀ;?bb#-bi’é†<÷çñìªÎ½zM?„7ã:Òd¹·ß÷ï÷LêÔÂ~¤+…¤<Ó-Y®Ï»åîy÷ü0óx‹|ü!Ó,úùoÛ•šœššt+~ |ÙGð䎞}üj|ééЗ’êKO“Úà.÷ _²·CïÈ—Ö{û縻ɗ¹cGd—¶È¥OÞ»Pd³wy ¾ì=²\ñ"›H–šCÝJ¦Ì&§u:«y0y¶GÐH…òì”a¬>Ͳ_lçË:÷6íÍ÷=½Þ]Ã|I5……4ÿ»²·Ôw¼B3ûàvXß`»z y†‹W*ƒÞ5£S Dua|ê"}ÎÛ×m'àÚnô¥®FJV_6óÇØ¬Â4¥ðº¢w[[ÚÅJ‹öÖO³ÔfP”ôçä1ó<öœDÄ—ñ4B®Î—‡nïKª„/¯#²X_<ó'Ã2¶ûxž> ÝÖ‰”¬ØS-ð•…éÚ^£üÒ-¡ÚLÓÍ4]»—üžÉ‚£-%F_¹­ô¹9µð /Š'm¯Ðòz.H¾L5Ý@vp5uþS™CoeÙQ\ ( çfO(\^—þ#–MLÿTe9Už±ìö |Yñ[´¼Ó׌'ÝîKY¨üØYAßE8§ÃË7·È—ÓMß¿Ã\@oqµ{ 5 °7ì­¿-u‘Ç/ÔywÝgúÞp‹ÒáY¢<'EîjQ¼l7žjK¼Ÿö6„BõŸ¨{ާpu¾ôx<í}I•ðåu1µöØ–ò¡©÷fµÈåjƒjc»<šùýLOÓØý£ö0$u£ö)ÓNhfñež»‘ÕÖØ_¥• ýX²,‡ê\ ôT*zŽköá«ROÖ9ÝÔ»_}Ývã[ÜàŒžBUôryjÂωSÛ•Tëbcˆbì¾ Û}ùÅ_”””}yôèQª„/¯/nÝ—â±$ƒáè–un‘ C6è%}†ºÄV_:fÞý¸¥4b·áþKí:¨­,ùéÙÄ-Ug«/Ù'µñð]w_F¼Å®¹á·£m}ø|N:¾àzø’)“ÊÃ*gΜilllÖ€/¯§/-,¾Tßr´ÏAJCM¢âKÏrj|óh™Oyiˆ/iCÌÛô ~e®Žð¥¶²\üü¦oÔ½Ý uMF,túºÑ—An£òH‹#ë³Ù·êN6Æ—²PëóXÜoU+ù|1“_p|iDV/¯;eKÆÞ™0—$úÄsÍûù¦—]þ€,ÕÛ³Ÿb¿‰¤ö· ÓM£3·“|)-³žHý£°ÁO‘bžý,í¡Æ¹˜–Wz›bøR*J2ȼQe‰?“™x[ûø¾üæ}ÉÞâÛ“ßqq¾2ÇûzÜOß™h¸Ö°ŒMÔ¹Ý,”Òòàì#äMûÌ»éÙpúÈM´LÏŒñ%ðeŸ'èS†ð°&V lSÆè#f¾`xÿ6Ì••^à—Ã…zÛ)gŸ¯7±f)ƒZ[¤rÚíRO£þ¹ÉVnöHUGÒÒçd§é¾Ô;2Ñ{ý|©ÿž$Š2å‹ÖôñÊûžºè}¾þ.4ûßz_8ެ·e<Î*oMxn/sV üžø²/#K’(JíëÕê~ß!‹Q7‹F'{×Ç—7šçäYÖùÚ¿Ir­£Èîôñ>³#º-£¾õ±ž“ð&¾#‹u^úpÌW| @/BòØ‹‹Šl+ wø£|S‘lãÑï|,6›5s’ò+[Ûék<žì?e+´;øj| @ŸiU¸âvl¶dgf[V8½u¸À—ð%ø¾_—àKø€/ø²GA CZó1€/{ /·mÛvåÊ•o÷¶´yYÀ—=Ô—óçÏÏÍÍ¥Ô*tUßÖmmƤ_ö|_2 8Ž‹s«Ç|š´Ú­ÌàJ3vî{Ì”X¬ÌÝ%‹=Ml¦W>˜<[« É4ºš'«ÂËëlo´ÎÂ*Vf§ Ófv=gàËžåKFÜͳM4!™šK™çs¸’"z{·U©,öT |eaúpªôiù%ú›ó½~¾Ú½…ƒ„óK¨)ºîH_Ëñ‚ϵá>Ó÷²œŸá±ø²Çù’X¼x1´Ó [ÄRJÜ1.ue×âU¶Ïb_'«•ZêÁ¹\É™åi¤•Æ<…Ê|ÙátJ½Kh¦ ³)uÎyxPòr ÏÀ—=Í—[¶l„xÓ3ÔØgQ«éR5éRÔ,öí*ï”4X†,ÁÖt’ËMm˜œ~M€/{/—-[VUUÿ†”€ÚT’n¹3q¡j¾(Yì²Ò¾š£ù’ÒùRŽIÕ—Ë©‘Ö£¥¸°ø2è]c¬_ö¬ñ±‡îêøXÇÌ»‡¤nlÕ’5'žŽ•ÅÞ5ïç´àòd©Þžý­à•ZHœ”Ôwtæv^’j‚ßpÿ¥|ŽÚxÇgïä,Tf½u‚C~¾ì¾ìR¬Ns‚.u°kÀ³šN‹”ñ±Q³Ø×Û¦Œa•$K‡²šSr»(Ö¤Jê°ÌµLc¾$‚¾©j½2žÖœïC¬ ðeŸœß'jû©íe¥6š•z ªøóá€/áKð%| À—| À—| _€/¿³¾ r['˜×~ÓóÄJ²F&oöðX|Ù9q'ðºŽÜ ¿ù|Ñ”_E ¾ƒL,M¶”ÑK=xî¾ Ï{ôèÑ®ÎÛ4kùI¾Q_JúRR³©4á¹ø²5?IAAÇqqnUã˜O³¨»EeþØfÿ¾ÇL‰ÅÊİ’Ó:Mýú˜yžG`é-›ôÊ“gk•!™/ÍHìO•ý^^g{ƒå'Q+³S†±õ³ŠbO¶.”[Ì£Ùj“²·³ p½+¦O-ÜCY©Ù´´+]5¡Øõm}Ùz’£Ò ü2ýµœ2w†sŠ¥þ}£LO»´“opå?”¸Ð¯ž†~¶i–ýšò¯Ø-/„÷f^ä[ð/_öµü—q7Ï6ÙÆ bÞF –{û Ï>BUž%iö"wµ(^¶Ž8ÐôÅmU*‹=Õ_IÆ¢JŸš\š²šô7ç{ý|µ{ y+œŸ$¤äÿº#}-Ç >׆ûLßËr~íèrñó?¼ˆÄ:N™Ÿ=­¨Š)jjÑQ^ð;­Š±vúšcÕ}I+(sÁsu‚ÿLö¸ƒÌåÄûÏP‚”׋Oó<éøJŽéæ´âKìèE)C†[޳³U®‚öëù¦m) )“ÑÏîgzšò´Å ÙÚÍø²Où’X¼x1´Ó ©ÿD5.uÔ syUe9µ ¥Z—Ó]'«•ZR̹\Q”§‘ò_Rœç–´pÍ9›Å—¬Þ%4‡$šœ]vÎyxPòr‰bQΫÃù #tdš”]rÌy8,ìܱƒ3öiSZSÇXNĪ×}ÉÎ|šýÛ];7%(dÙ­Ãý—Õžk¨*u5 v±¿9â*î|Ò$e+;_ôÕ;| ˜0_öY_v)½W}ÅjK=M!Í"yîÆ¶N¨d¢|ÑùƒMsõõþK2©-“óÅhK¢×LPès¼OÑgD¥;w,…}úÑÝóž}Ÿ/ +-–zˆFé ÉLª/—S#­G‹¿®,¾ z×ëcZ*§ýd9ªØŠÎ™?f^¤8ò®Œú ŽÐA½¡=V9óWûšùR—½Ò<¹è5ƦÙ? ©v7ž-Y_y)齕²(\°¦ frø²/Œ=|øpWÇÇ:fÞ=$ucs¨–¬9¡æÈö™wS/ õÛ‘ih™QW¥kÞÏiÁåÈR½=û)ZZ,IœfÓ£3·ó’ð¡åpÿ¥|ŽÚxÇgïä,TR÷áëéh¾TT—e'_Ê5®Uö±ø’õS.už—d©Â>Ÿ–×{›bÕ|)Û§üóí 3Ü<‚M‡,O±NVê³$_¦ÙNH²¬EËYôɤÈzaÃWA×L7±Vß²Â? H|‡SÖiÚ3ç_†Œ[#៾ìí¾ìR¬NsÅRl¼hÀ³š,R¤Œ­·e<ÎÚ!oMxn/Ç:ëmSưJeL/Ü8àv±VPjÃ̵Lc¾T¢4Ÿ2~'<žÖœï‹kV¿n;Mž½$cŒÖO9ñFóœôÄ~ááµÅáÛµž©ÚÏ+ëmé#ôÆØÚ$Û›T£Ý%AR$úPæ~ý4‚þ${ãÀZe5!<ô—þÕ/àKÌïÓŠ,I¢(ÅS©TSm4#*õ’Ç‘ÚìSí§, o.w^ßIvŽm¿Êµ‰,ð%|ÙópÏ»ç®Ì#ñ×€/¿‹Hüe/Æ_¾àK¾„/À—ð%ø¾_—׃ ·u‚yí7=€Uº52y³7Ðn À¶fg[¬ëœÞº(ê?ãt89¡ÿ€ðåÕw¯ëHÀ½ð[È-vš/ºÉ–2Z›¨çRíx›&ºß<3=UÉÄùzq›I€Ù¤}Tm‚\€/ã†Í{ôèÑ®ÎÛ4kùI¾Q_JúRR³©4õä'’®‚fõ›V~0NZÇÒ¤ƒ\›¹&þSÒËæ„›;¼R€/ãð%£  €ã¸8·ªq̧YÔÕ¤W¡fÿ¾ÇL‰ÅÊ,©’Ó:Í›ú˜yžG`™:šôÊ“gk•”Ó2<É*ͰºÎö†>GkH¬ÌNžèµètÌ3Ê-æÑlµIÙÛÙ¸ÞÓ§ÔlZÚ•®šPìú¶¾l=I6 ,Í.KI1Ã9ÅR ÿ¾Q¦§]ÚÉ7¸òJ\èWOC?Û4Ë~MùWì–Â{3/òŠ-]ºsöº3,5˜òÒ²"3ñ6Zç¡ôMu™Œ¡ÿ¤Ü´¤.evxšÈ÷mšž©³ùÉê}õûEÍ—ÍþÝ´r±¿ÎöÓ9ð%¾ì_2ânžm²4ļ%½ §k^2‘&a/rW‹âeë¸ô9NFq[•ÊbOµÀW’±XêÖHØßœïõóÕî-ä­p~’’ÿëŽôµ/ø\(ñH–ó³hGWRk H^Ä b§ÌÏžVTÒòL-:Ê ~§U1ÖN_s¬z£/ie.x®NðŸÉ7`y#¥¡æýg(AÊëŧyž\v%ÇtsZñ%vtJéE 5ÙÙ*WAûõ|HqÞhK‰ê°Ù4i;åi вµ›Ó¥KȶŸä|~I{isWóÜašØýSB¡ë¼r’‰·³þhj\Ê…²£0,ûÛ“ßñ´ê¹É:òõè,P†/ðe÷ù’X¼x1´ó–@±”>åÇ¥Žº3a.¯*²,§¶¡TërºëdµRë9k‘ËEy)s$ÅOn-Udƒs6‹/Y½‹F¦H$ Ù9çáAÉË%Š™8¯ç7ŒÐ‘)¦’s ;w,˨¥·¦jyK¢Ô·æ‹VÏ|šýÛ];75_´ª™pÿeuñŸY&K–»Øßq”/š4IÙÊνDõ_ƒ¡Y4ÞKP¦†Ï6¤¶6¼4fñ¬Xñºc‚"Ô?&G§¯õ ¢ÈŸ±¤ dšågmöW© €câ„/ðe÷ú²Ké½jì³”¼’ž¦f‘#*Õ<$ÙÌ{”É&j}«/ÅcÉZ1=¥ó¥š/úsýZ舱¥Áñ&N¤ñ*è%kD ÉõE™Ï†ÛcSßqûƒêС¸/!†/ËeKƲs TÉÇ©™¹…ßG1(}›QRj;?U«ëéB´e€/¯Í—Ë–-«ªªŠÃù"µ©&$ÝrgâBÕõÔ8™Õ:Sòù|Yi±ÔC4JMâª/—S#­þ)p-`ñeлÆXóÐjêÊ,G[Ñ9óÇL$ÆŒN pä€ê í±Ê™G>Ê|ÙhlA\t‚cÓìŠ{"®‚¬¯¼”ôæPY.XS3±Åy ]õe8¨Õ})d¾¤!ǦvÄhø2>_ÒøØÃ‡wu|¬cæÝCR76‡jÉš i`ŽlŸy7õR¿™†–©1º*]ó~N .@–êíÙOÑ ÔbIâ¤Þ¸Ñ™ÛyIøÐr¸ÿR>Gm¼ã³w rH*©ûp‚õt4_*ªË²“lä×*ŠÒXpÆzû–:ÏK²TaŸOËë½M±ê ¾”íSþùö„neMÓ!ËS¬“•ú,É—i¶’,kär}2)²^ØðUÐð%ÓM¬Õ·¬ðÔ§È)ë4í™ó/CÆ­‘⾄®ú²EVRXfwL¼\øüÂí±júM†$ÕR7j–ã’,Ëø7 €/¯’.5ÀêÔ9P,ÅÆ‹<«É"EÊøØz[Æã,”¹5á¹½륫·MÃ*•15Êjª{¸]¬”Ú0s-Ó˜/•(ͧ ~ §5çûb|ÂW¿n;Mž½$cŒÖO9ñFóœôÄ~ááµÅáÛµžExÚÏ+ëmé#ôÆØÚ$Û›T£Ý%A’œÊܯŸFЀdoX«yá¡¿lô¯~Éñ]B_zÚö_¶./™¨ß±á˜~t8ß~^‚6±_öèw ÒÄSÉ‚ )š•zIŽãHmö©öS–†7—;¯ï$;Gж_5À“ºz WK“ßïç‘ã_bþØxpÏ»‡ýÊ"Îzðåw‰¿ì‹cŪ_ð%_—àKø| _€/áËëAÛ:Á¼ö›À*]È™¼ÙèÞ½V¿Êæ0ºú»áÝø-Ü €/;&î^ךìô[È-vš/š&I­M/uîÕ“ÌùþkºdÏö®xñYëiükÀ—ßÂü±Gíêü±ÝH³'ÿ[ð¥Ô©/YÚȦoúÛCgw#bÎ<€/¿Ñü$ÇŹUc>Í¢®&½ 5û÷=fJ,VfI•œÖpââÇÌó<k“lÒ+Lž­URBÈð$«4åé:Ûú­!±2;eXx¢×¢ØQ”Pn1f«MÊÞ.„¯éS ÷PVj6-íJWM(v}[_¶ž$›–f—¥¤˜áœb©‚ß(ÓÓ.íä\ù%.¤ Òç\ÅfÁ½ù¾§×»ëBjŠ•Ñ)¢:?íÔ‘SvØÃI»rìU5îÕÚ ïf+Lú¼[Kï¬GF_ú]Rnf§çPJ¯xQŸŒ—m[ãÞÀÎfôÕ.M9ôÅK‘“_v¿/q7Ï6ÙÆ bÞÆ’^…Ó5/™HÙEîjQ¼l7²|QÜV¥²ØS-ð•d,–úƒeöèoÎ÷úùj÷òV8?IHÉÿuGúZŽ|® dš,çgÑŽ®¤Ö¼ˆÄ:N™Ÿ=­¨*¤å!™Zt”üNë ´¼Ó׫ÞèKZA™ ž«üg²Ç dÞH9œyÿJòzñiž'_É1ÝœV|‰RzQBMÒí!ÇQ%É¢Ëú{%‹ÜÚšJû'ÝžüŽÇϳ¤(·'Ívûyº.Z¦œ ´}Ïpi¾ÔÓè¾d3§–’PfŸÏuÉb}ñÌŸ ËØîãyIéúÝH{{ÝV ¼»H™À}¥7À­Lõîñúüü»À—ÝïKbñâÅtÐÎÛ3ÅRÕ¸ÔQw&ÌåUR@–åÔ6”j]Nw¬Vj©%[dE0yžFÊI“[ÓàœÍâKVïši sÒ’sÎÃ’—K‹r^Î(™¦9—s ;w,˨¥·¦êI?Ú×·æ‹VÏ|šýÛ];75_´1­GuñŸÃ)´Ô$ØÅþf–A:Ë~Ö8׺ÁvÊþWr¬•ûŠ!(kæý¼S_¯2Èiµ{Û¤%”UM_““é©=Wz¿Â¿X|y½|Ù¥ô^5öYJ^IOSH³H^Û¤Qí*™(_tþ`Ó\ý0AÍäˈÇ“óÅhK¢×°<‘>G¸ÓX©æ!1$œ÷hkævõ­¾%kÄô”^Ì—j¾èÏõk¡#:Ä–Ç_´в§ø½$­=v¥ã|„/I‡Úw‚ð…³e¶Û_z¢øòJqö³Æc¾4&¤,¤«©WºK&RºÍ`›C|Ù­¾\¶lYUUUü¶È©M5!é–;ªæ«§J%)Šòù|¹ÖW)é ÉLª/—S#­G Ë®,¾¤Î?c}ÌC« •YŽ*¶¢sæ™?H9weÐO pä€ê í±Ê™ç¸Ú‡ÔLlÆFàÉE'¨16Íþ©q=IN½ÂÚK#|©éШ^Í—â±ûM NÍ—®9Dø’† “¹]Jk-4×}iiM"ýó.ýLÔ[q$ÂÄ_v/i|ìáÇ»:>–"j lÕ’5'Ò@Ù>ónêtú¨½´‰–•þ<ÒÀ¼ŸÓ‚Ë¥z{öSì·‰$NJq<:s;/ÉÿZ÷_Êç¨w|önAÉB%uNˆöà ¦º,;ùR®q­¢°Å—¬Ÿr©ó¼$K¬Ëp½·)V½Á—25cÞž0혩éå)ÖÉJá‰-ÍvB’ø—³èÓ£†nÔwHŽÜìi)?#YÆZ˜»àËÐEjžd-e¹Î£tâ²Öcƒ/ó_úƒ!ùŠCíve¾,[2–ÚÀ9Ai¦oú¥U»V±uàK|Ùý¾ìR¬Ns‚l¼hÀ£ û,RÆÇÖÛ2g-‡·&<·—cõ¶)cô!e5Õ=Ü.Ö JšÉµLc¾T$äSÆï„ÇÓšó}1bÍŠâ·Âm§É³—dŒÑú)'Þhž“žØ/<¼¶ø¬ÖÔ¥ž©ÚÏ+ëmé#ôÆØÚ$Û›T£Ý¥žNŠDÊܯ ö9áöRgŽº[¥©yh_ÛcõeN•·2H8i†%}ŒîËðåÖ³šlù ;ñvÖ²ô}Hg®tôª;×o…>¢¾À—½`~Y’DQЧR©¦ÚhFTê%9Ž#µÙ§ÚPYÞ\î¼>¾“ìü‚EQ”¯á~‰BG›ËŸtë¹w~þªçÝsWæ‘øëÀ—ßE$þ²ã¯_ð%_—àKø| _€/áËëAÛ:Á¼ö›À*]È™¼ÙÛÍé;ª‹_es]ýÝðnüè;e³Z²³—ìtžoûcNÉc_Ÿ½Ò¶‡ë`érqa^¶ÅºÙQåw¬r½Ûét¹Ïãg¢À—½Ò—q'ðºŽÐD©ßB¾h±Ó|ÑM¶”ÑÚ@ñRç^=ɜ₩»ÑI¾h=Sf÷ÒàZ¦L·”:3;3†eîÖÄÖT4åGT“ž™Aó ѼNN¾9ÊýŽÑÄL4;RFÆdZyPꚈK ™ÙdI>H€/{ïü±Gíêü±ÝH³'ÿ[ð¥Ô©/Yâ­¦oúÛCgwØϫûh²Ž¼cpæÍÙËÙôñÊ7çÛ´¼WÍ$ʔ꫃GšŒž’Éðì 嶪‰kZ¿j4«y:S’o×'>À—½5?IAAÇqqnUã˜O³¨«I¯BÍþ}4[i±21¬ä´Ng™>fžçÂS§ê•&ÏÖ*)§eiFbeêÔ„—×ÙÞÐçh ‰•Ù)ÃŒ³¡FG(·˜G³Õ&eoÂ×ô©…{(+5›–v¥«&»¾­/[OrTz_Vf—¥ÉÐÃ9ÅR ÿ¾Q4õ¹vò ®ü‡Rés®JÖòy­w×…Ô ÐG§°lÏSGNÙaç˱WÕ¸Wk'¼›­0yèón­yS¾ô»6¤&ÜÌN;Ï¡æÄ^ñ¢>/۶ƽE~Ú¥)‡þ x)U²Ì 5MpŸãd)V®XS†¥ÙN³Yà'ت´`ñ æKIIŽ­ê9<ãž|Åßnò6¯šìSfkQºm¡u‚¾zʶ=ÞvºÂöG-¾ìåù/ãnžm²4ļ}ΆÓ5/™HÙEîjQ¼l7²|QÜV¥²ØS-ð•d,–úƒ&.§¬&ýÍù^?_íVRs„ó“¨áËék9^ð¹6(Ù˜ŸE;ºÍ H^Ä b§ÌÏžVTÒòL-:Ê ~§šÐc§E­7ú’VPæ‚çêÿ™ìq™7ÊÊþJòzñiž'_¡Oü´âKìèŠB,”Lɱ•㨒dÑeý½’EnmM¥ý“BnO~ÇãçYR”Û“f»ý<]—šE¤±Ó|ÑLBi…%‚$”Ùç3Éb}ñÌŸ ËØîãyIÍ‘B{{ÝV ¼»H™x}¥7ÀM_D¯Ï¥ƒ–:YYÞ´ê¢?jÉXB5ÎÅTiµõ¸?Î7`LÆn‰Å÷öO·í°¤ bžN³ì—¢4ÆyÀô«ŽõIÚú+]­oÜù¢—è(zV,y¾¾ì#¾$/^Lí¼=S,%QKE¹¥xUe9µ ¥Z—Ó]'«•ZjÉpGO#å¿dÙ¯Âášs6‹/Y½Kh¦X†´äœóð äåÅ¢œW‡3 @¦FrÌy8,ìܱƒ3ö[Sµ¼%Qê[óE«g>Í~‰í®›š/ZmmÔógöYÏ’`û›Yé,ûYãDçÆ|^IáK ã y@Y3ïçúÒx•AþH«Ý í±´LYÕô5)1™žÚs¥÷«p$åîIô…ÔœB 87û‘NI{BVNºï&ÅÁáྩpÜjR—Ó4>ûr3©02î§o áü3\$òÎB%Xg{&•Ò]bm³”‰ ¾¾ì#¾ìRz¯û,µ›ª)¤Y$ÏÝØÖ©•áTVJÊ*Ó\ý0A=ã£g¹©-Ô%&†D[ʽ†¥ºô9ÂíœÆJc"eåå¼G™W¢Ö·úR<–¬eÓSz1_’V†˜bKƒã/Ú‡¾ì)~/Ik]é8áKÒ¡ö M>¯pþ˶¾ôDñå•âìg'Öš/Zó%e!}\M½nÔ]2qȸ5Á¶‡n÷ÔË)¡ËÑ¿FÐWº ÓŠÂ¥ £¿æ)’Sû5[¿m„*Vü¦ý˜죄ڮÖ7š®q’í¬Òœûü¥oSCR™Îœ¶å1@ø²WûrÙ²eUUUñoØ"_¤6Õ„¤[îLdŸžõBé¡$}Pú|¾€\kˆ«”tÐô¡¬úr9k G'®,¾¤Î?c}ÌC« •YŽ*¶¢sæ™?H9weÐO pä€ê í±Ê™ç¸Ú‡ÔLlÆFàÉE'¨16Íþ©q=ÊÈu²èÖ^Ú…|Ñâ1 /]s‰ð% VòE+Y¬µÐ\÷¥¦Zþy—~&ê­8OþK缟ßp_"³Ý¯Fü>åü[#+wI9ŠÒiôåùu¤Ó‹ô¥z3sÚ~1c-eõßôÌø²÷=|øpWÇÇRdC-Í¡Z²æ¥N¶Ï¼›Z䜾€’HyæÝJžú+Zpù²ToÏ~Šý6‘ÄICNFgnç%9à?BËáþKùµñŽÏÞ-È!Y¨¤îà Ñ~8Á>…³ìäK¹ÆµŠ"!6±~Ê¥Îó’,±.ÃõÞ¦Xõ_ÊÔŒy{ ·b¦¦C–§´.½+$¶4Û I–µVÇå,úô¨^¡¾CrÌfOCHùÉ2ÖÂÜ_†.R;ð$k‰(Ëu¥SÏ­ù2_ñ¥?HClj·+ó%µjR8§§¡oú¥U»V±u:õ%Wbg«|&µ9]½ó£Õ;O7¤Ú¹Làdƒ]]ÕôAí-£©F¨£šî›G¹‡R™šÂšµÇ*ÙAU¨——$=È4ˇDÀ—½Ñ—]j€Õ©s. @ x”aŸEÊøØz[Æã,†¸5á¹½ë*«·M£ét(«©îáv%kcCr-ÓôŸ}Ê'rx<­9ß㣵BýDVì•<{IÆ­Ÿrâæ9é‰ýÂÃk‹ÏjMQêYªýæ¡Þ–>BoŒÝ©Mbà±½É~2ÈÎz:)}(s¿EÙç„ÛKIœ9ên•¦æ¡Q|ilÕ—9UÞÊ á¤–ô1º/ÃG”[Ïj²åƒìÄÛYË65–Ò™ëQš~+ôÅû²ER¾¬¼®ô׆ &XÕãzw¥bÁ×m'ô{_혯×ÏÜãq¡ŸiŽhm:vDi«ð¨ÍÅ>H€/1¿OHý=ÅñT*ÕJØe'J}§Qˆ²Ó6ûT*KÛË×Çw’_0Oò5Ü/Qèhs¹ã“n=w©;Â6Yäy?Ï·?!—ë÷ûÙ™¶È—‹,k+–¥¶CìÆ ~ÚZ@_—=÷¼{îÊ<=¸Z«Ö:ŠÚ°Ù^†¨_ö$þ²ã¯_ð%_—àKø| _€/áËëÍ 3Á¼¶+X•IÚîÌØÝÁ^Û+i…§ñÈ|Ù=ÄÀë:B¥v1_´ä˜÷Â4[G:<™ûíS?€/¯6ìÑ£G»:l7ÒÜ.ƒÕµ£'ñ1× À—ÝâKFAAÇqqnUã˜O³¨«I¯BÍþ}4[i±21¬ä´NgÓ‡>fžçÂS§ê•&ÏÖ*)+ciFbeêÔ„—×ÙÞÐçh ‰•Ù)ÃŒ³¡FÅ»âE–…Ñ»búÔÂ=”‰ZKS\ÃV œ$£2ײzšêv½».¼¥P®ïŸR‡'­õ®ŸºèuNó6S§F?™èWäs®JÖr{µàË>™ÿ2îæÙ&Û¸ACÌÛX¶pºæ%ÉLEîjQ¼l7²UøÕ´TYì©øJ²KýA—Ó4ßýÍù^?ÏR‡ó“„”ü_w¤¯åxÁçÚ dcv~õðzs+Ë=2µè(/øªðvªi1X}޽Lü”…fQWò¢¨ûWŽKk{”YËG[JBZÞÍg,»ýÏrkÐNbLô+’”|[9Ž*ÊÂá²þ^ÉÍ‚¸_öa_‹/¦ƒvºa‹XJé,Æ¥Ž¢ÜR¼ª@ÊN•åÔ6”j]Nw¬Vj©%ÃI=ä'–OŠÕ78g³ø’Õ»„æDÓ‘ÊÎ9J^.Q,Êyu8¿’±‚Ñ—ÊþýHÏlåQé~uÿQÛccŸLÔ+j²Ïy–U’8sŠ1¾Äü>"K’(JñT*ÕT͈J}|#gÔþËÒð&qµ‘º²vÔ“‰~EʉñðeÃ=ïž»21À—ðeÇÁÙÇ‹¸_—àKø| _€/áK¾àËžCÛ:Á¼¶Kù¢‹R†Ü™±»ƒ5¼¶WÒ O÷å‡Qº\\˜—m±nv”µÿekH®w;.÷yü_vq'ðºŽÜ »˜/ZrÌ{aš­#ê ¿ú$-Â1šxˆ’«ddL¦…¥®‰¸{4iÕÓ¤EþÕàËnÍ{ôèÑ®ÎÛ4·™¾µ{Ðç•û`„%?ÿCJ–³»ÇmU³Ä´f†iæ6RMJòíú,ƒ_vƒ/ÇŹUc>Í9îVgdmöï£ÙY‹•iT%§u:›Cõ1ó<À&oÒ+Lž­URNËÒŒÄþTÙ?áåu¶7Z§o+³S†…'ƒ-ŠAzW¼8Imnõ®˜>µpåmfSÑ®tÕ°hþØQ™kY=Mu»Þ]ÞR(×÷ŸfÙž´Ö»f|ê¢ÔtÓÄë¶rG'ýŠ|ÎUÉZ>¯ÖÃEÒä°¾Á¶} y†‹WR[S®é©#§|P¼”*)&f/wØß§„šjÊëª÷j¶É¤ìÝ¢º>h%÷•:+Ÿr¦ïZgì«Ï1Ý<ÞvºÂöÇ»†Â—ø²»}Ɉ»y¶É6nÐó6–̓µ|Rª2S‘»Z/[Ç d˜ÝV¥²ØS-ð•d/ªô©É¥)7Hs¾×ÏW»·PÚÈp~5[Öék9^ð¹6(˜ŸE=¼ÞÜÊò“L-:Ê ~§*¼¾f½>Ç^&~Ê"ÂòB³ý+Ç¥µ=’uF[JBZÞÍg,»ý_VüÛI¬“‰~E’’8:ÇQ%É¢Ëú{%7K´¸¶Áµ@McR' —×¥ÿˆùŒ¦ƒ§3¡ï ×ç°—·'¿ãñó,ãÊíI³Ý~žÎ–)õf‹päÓ¯v8Ö'iÖ¯tµÞ¥óE/Ñ)QèY±ä ø_^/_‹/¦ƒvºa‹XJ]hãRGÝ™0—W˜nú~–SÛPªu9Ýu²Z©%Ål‘©äyÉOÆŒW ÎÙ,¾dõ.¡™&D§àÉ9çáAÉË%ŠE9¯çWÒžó_²œ\쨔ZdŒšPšê®'ݯå¿4—òE3R~fwŸ).]ŸG=™`(úQflE¨ö³m&fë ç]gø =*¡:-ë'íd¥÷+ýl“Âá#qÅnS '²vç‡S£pu’È; •`w³ú-TJ§ÁÚfË–Œ…/ðåõòe—Ò{ÕØg©=gMª>)æp7¶ujDe8U–’?Ë4W?LPë¿dqžê¥C¢-eˆ^3AÕ¡îK5?Éqýˆîyv”/ÚÝæ¸ôR1¢âÑ(ù¼¢žL Æ‘=Åï%ií±+çCm/‡h:®ä?ÆZ¡õJQ;=Ýâm_¶&kMÌ)(çãj=ªŸd;« ~þ‡ƒÒ·©ÃeeºtQ<ÈàËîõå²e˪ªªâß°E¾Hmª I·Ü™Èa*a™xÑg·Ïç ȵ†ðHIM-LEÔ¤éÑ>ÊZ¤EýˆÆú0Æ—weÐZ8r@G¾l{\ò´òR/Û狎z2¬‘¶ýé+H¢p²èjteé6Û¢ŽÓIß$¨û j£‚é9C‘/Ã'ÓÆ—jšÓÖÙc¬¥¬>Âñì þéàËnð%=|øpWÇÇ:fÞ=$ucs¨–¬9Az#ÛgÞM„N_@Iž<ón¥Oýa-¸üYª§~DZAéG”ÏQ񾄪ÛyIøÐr8Ò’ÏQïøìÝdY¨ÌzëëéN|©öS.už—d‰õö­÷6Åò%ë7 —™nbm¹Q}ëd¢^QÛ¨vL6Ð uîeÆV_ÊÏF™7 ²,ñg2o3Æ—ñû2¤ö¡R²‡WÆX±WÖ«¤ßT¡nT缟2ÍòI0ðewÐ¥X:çн\êÐЀG½Y¤Œ­·e<Κ[žÛËÔuëmSưJ¥ËMYM)¹]ÉÚp•\Ë4ý—AßT-HzМï‹ñiïi/'Þhž“žØ/<еølÄ  úžÙÊ£Ò üêþ£¶ÇÆ>™¨WÔdŸó,«$qæG§šýáÒUÏÉN‹Ç—ÆöXãrÑ”z™çˆÒ0@ß$†Œ[#á_-¾ì™ÐO(¼‰§R©V"¡(;Qêã ŒÔþËÒð&q‡RRWÖŽz2ѯH¹ QŽg‡Ýõ ~?Ï "H|‰ùc;÷å¼{îÊ<‚ûð%|Ùa¬Æ_öñøÑÀ—ð%ø¾_—àKø虾DAAAAAé{¥{|¹úè}G((((((}µï®É—Ï ¸‰(((((}¾ï®É—L™ˆ2QPPPPúpdÙ±,ãõ%ð¾àK¾àK¾àK¾àKDõåÄ&ìË¿ 6Š/çÏŸï@lÈ•Š// 6a_V 6a_^@l¾<€Ø„}Y €Ø(¾\°`AbC®T|y± û² ± ûÒ €Ø(¾\¸páqĆ\©øòÄ&ìËÄFñå¢E‹œˆ ¹Ò”——w±!Wš–,Yb·Û?@4È’äJSAAÁºuë>@4È’äJÓš5k–/_¾yóæ=h ù‘,I®4­_¿~åʕ˖-[µjÕöíÛw`×.r"™‘dI–$Wš6mÚd³ÙèÅÒ¥K-Ë»ï¾ûÎ;ï¼õÖ[YYYsæÌ™5kÖ›o¾ùÆodddÌœ9óµ×^{õÕW_yå•éÓ§O›6-==}Ê”)/¿üòŸÿüç—^zéÅ_|á…ÒT&OžlVyþùçŸSù“Êÿ¶åÑø€ï6Qía¦¦r “Ù‡iˆ|DV"7‘¡ÈSd+r™‹üE#—‘ÑÈkd7r™Ž|GÖ#÷‘ɃdCr"™‘üH–$WþXÓ†o~¹·IEND®B`‚qbs-src-3.3.1/doc/images/qbs-dmg.png0000644000175100017510000012065215232633614016563 0ustar runnerrunner‰PNG  IHDR•óf ¼ôPLTE~ÖŠêèêããã}ÔˆtÅ~rÃ|mºwl¹uvÇ€o»yxÉ‚q¾{p¾z×Ö×ËÈÊÐÎС¡¡¢°£j´sÙØÙ=jCæäæ~Õ‰}ÔˆÖŠ€×‹|Ӈ،‚Ù{Ò†ƒÚŽ|ÓˆzÑ…ÕŠ׋€Ö‹|Ò‡èæèÙØÙÙŒàÞàüûü„ÚÛÕÚÖ‹ÛÙÛåäåãá䂨ÝÛܱ¾²„߆á‘IÌYÀëÅÛÃíÈyÒ„¾êĽé°¼±ƒÜŽlÌö„ÜvÏ‚}ÔùƒÞÂëǪâ±oÍ÷wЃ±å·Äðɇâ“zÐ…ÖÖ×´çº{Ö‡zÎò­ä´yÔ…FËWÕúìëíÝÜÞrÏø@ËSuÑùÙרÇôÍ»æÁNÌ^ÿÿÿyÓúHÉY¿íÉ|Ñ÷ÄÃĹá¾}׈ŽÚ—‹‰‹4ÉK˜Þþ‘Úþa¿é®±´z΋wÉíeËqÓÑÒÍËÌ|Ô‚rÆí¿¾À°ÆP\WnÁç´Ûº~Ö…–t€Ö–ËÈÇ{ÐõfÃí[ºæÇð̤ӾÀá¸qÇzkÂu؈ØñÛÂñÌ·¹¼½Ù¯hµ•˜£~ihi±àÅ{Ð|¦¥§™Ý¡)ÈEuÎõÎÏҖó{ÑçrËä›Ì¸­Ð¯˜sqsovgüc_ü¾Eñïñ˜ßï¯Ö´¤²‹ÅÇÌÅé¾]{}soTÊñÅWlm^a_?6@¬ÚÁµ®«vž™«¾”m¶wöûöËúÑ·èË~ÐŽÈ=}Ôþ„¬¡¤šL¹Z^[LMTJmÈñ—œ¦È-¸Ñ§š™›h‹Š†}yé÷ꉵ¨q„t„fALSM2"åèëJ`häÞÜ–°™m““ûTN–ÞóÁº¶¥Å§|¤˜‘Žy•Šz|‚Å“|Â…þ¿*™ÐžoÑyð¾n[Ëh+E4 Ǫ7’ÚçQ±àçÕÏä³´ÌÕÒãÍǸɹ~«ƒ„[ÿ½k¸˜üKB_M5¯ÉÖÒßÒꛛ싊tº},Oa…ÐééÏ´©¸«ƒØæÃ–“ÒØï{yj¨rW°¢WtRNSþþµþééÞÞéÞéÝÓáäã"õºeÚ5Æ´ïgžNIDATxÚì”1«ÓPÇ{ÝÅ‚ø<%=¿ƒ[á†Ð劷CÀ2fséP¸J–¦öeȤdxƒ%P§(…R-µÃ[úž‚&¾\?~pýÜ0Y™[~±vÔÓœž»Š]ÜeªÂ6©=ÇPK*+ˆ€ŸÎ&“ÉÙ×"§>GNV>“#ŠoŽ»ÝîñC‹!ìÖ3Öoܾ»n› DùSª+ 0 \¦‹ÂBOõ¾@hëÜþT0žÒ­7ÎÆ¾@¨XZœ<Ì&%g'9"ò͇bµ)‘Ý?êtºÝÎñˆáÈ|pçöíÛ#éGŒUÚ.åTŵÒÜN‡3Fþ25à±^h”:Ëx?0]ì/‚¨|µ?wl¥ |Œ5ÒjëEJ¢•s˜ kd…};‹ÐèOW§u¨Ó¦r¡Ã Ö–Y7ߤ»ö[Ó:_Ñ-¦Rp֨׉šù¡·˜JÂ"zü~ÿQwxy||ùü¬ÌÝðó¢ë¡ó3‘÷4?^YSùªÒ®‡û!Á“µö›t·ÉVÕöë~Ê:d´mvuhîW½¬züþ³¡éí0N ’tµÙå%¶kÌ^¾»Y,‰™õøú÷õÈÂ#j߇·gŒè¯‡Owˆ®ˆØøÔ¦!æéStB¦ˆ­j+=U>zÃ!xËDâB¨Šf|’õij¬·ž%2e,+õ©õêbPÆê©¥¨¤¬L™c“9BËÅÍÂ8J–”QÇl-Mæ9%¸ks°^çy`"'K%Ò¥¸K¥ŽŒQ&ÀÆ·õ‰Hu¬¬„,– ‰Çc„…L›ÌgƩرrÄ£€É1ÜÅXf¶pWÅgÜé,Ný'rÎP0”¬ƒŒ™‹EÀÒ)¦Yb§©¼Ÿ%ÿÈ£ƒ„a Ã\€s$K^ n–zÈé-Â샿u* EUÀ€±¯Q›.ËÈÿ¼•×¶¾‰53b”D.˜)Õ=­ #Š–-•mE‹mýŠ^ÜlV©ù]Pþ«'÷Ïu…)ÒNtLÖíõx~n²fÑ{&yì3‰žÓE8kÌÍh“ªERºAqX×L]îP‡ê°P¾4"»™Ô@,PB¹Ÿ4F@õC}Ð#%u%í'µ¤ÑØq¢î;eîçÍrÕtçsÅÝ’”ùN¿lÑAÊÜ0 àa 7­È±+ÉàÍ,²Ëªºèº÷¿LŸœæÏP˜à±¿<¢—´~?+Åá]A¸™úë¤1Ž~¿¯ÌÆ¥p9 ›WŬTü#ÃõÀ}@­Ä{Ý?訧”í/]Ö<ŽÈ7«ƒ8Jf¹©/‹q„Œq#R èÀFEÐ c`"„§“îcÔc®½XÐ2)/ÊL“ æe‹§l Tþ¡úQÁã®`¿è=M:+j_ð+°YAåù²³‚³-¹é0zWðøùíñÚz#w­¢¸‹4Ïê’i¡†¡'aCimݶ ¼%:©Oš\”žêA{ÖÞ k©oPßÔ5‹kO35S ¦¹÷XsõIµ‰¼U…µ%ØŒøD®¤}U_‚f¯øiÞ¼¹8¨(2[Ó‹Ò²’· îU²g¤æ ™‚’pPì¤5]s•í®@ç\}RÑôtÄžô äIW[“Î òW a-E¯ ø©´ùæÏ³‚µ«Æ\ QÁ_Eøãu·ê4Ex@ñöÏìÉĤ…€œ‹‚‚—‚w¾ÿ¹Öž¤‰Q«á´“Ïv¯• =ªŠ5ÑÖļùR<Ü|sÓŠ…XEðÃ\&Hj4DVе já BZ«‡(ÇPïfaÅ@mûÚ Jºöt…ç!UIË“Úf *=ð£YÃ&å°EE $s­O꒔ǠÆ\ëImË ÜAíï”xV°d®õ—\å¬Ô+* -rT ¤î¢— j¶eÝß|ÆUÙn,Ŷ…·mfÁ‰n‹²Þ&"{x=èJÚH…AòsšZØIƒ”Gwž -ª ®V+sR'm |Nêê>¨µP4Ïþ”§1¾‚ÄXÒ¯ÒGSSÐ=Wa®Z ÅAªÆ\ZýZ©û3—±IåB{®ÛAËÿUÐX–IÏ ê½|þ€{¥„*–ëýSwdk˜-Z3°ŒV+ï¥Êšï×>õxq²Àá¤:“Ú-“jÒxM9N/•ӘΤËìŸØ´“ù£¨ µ&Õjn¦Ö{[IsØl/|§ TÝ* îG®Íž´ÊÚ”¹üRAË ú¿*ЬÀ0goƒ^+¸M¤GsîÃþZA g|5³‚êý®ÊVÏ«p?6^Iç@,É[XTϦ©J3¡Ž? á }PפBªáÚvÚð\¥uҙ罒ÆA”Û. A…4dª<Óy«§Ô+mÑ7ÓµéÎó&W*Ö!VóÇÈeê#—d.PÛÎ ú¯¬ 7Ò£‚Ç*¤ÿ_ŽKºW°çòú‘ôÌÅ{e{ƒ·ª àD3Qÿô­™äÝ,U 'óMðj‰À±rÓ~kžWÔPQu»Wunß™´‰¢å¦ýÖwj­;Uno6†“¤íÛ',o=H £y¸ÿd§~P ÐEX"N )ËYÔZðÈ\qÍ%¹H…,;•x]Á$&gÙsÉ£ Ž\~暎\I¬g[V0ÿZ$2•¯ïËûïoÄð¸ñê+§t¸@¹c”3”µ™-I× U¯Õ{À‚†Â47IjE™G忦ÈoýIaØ«@³¨¡‡ÞH¹Ç1¨êNob6iëƒ6Ò\'J8r-ÌÝI·ÌõŠ2—HÒ‘ë¨` Ë N*{[·ƒî¹f Ë iq»T`¬€eù¥‚Ím¹T0}[ÞáõÀßü,ƒÇ (%Ûá®~Ytß~/-ðäIt­ ëò@‰EÅüQHõ¤Üo b«(sA jR+I+J¹s‚Åûv¡‘THÃŽ­YǰÞPÓØü vÐêzæ:¨ó¶û{.¯*X/,Â\îY]*³‚r­àv­  ×væ2{ƒÿ¯¼ýüÈ;Qrú©"¬$óh¹“T2)PÒP« ê¤ÅTŠ¿3&Í9-éd Ëø /;Rh¾¤ƒ6K¹ö¤¬n¾aä²/Ö:*8*8=*Àë в NgЫ‚1éÌUŸ+Øgþ ¶pOz|‹Uy㮥uãnè&&)Øjp(WÛ«¯z9٩Ô”,ªÏ„ˆVaú¯A— fý/_S€º/¾UÆx–®â›3éãë¢4úÎNeä¤t—&eðê† nuåBæ’8'8€‘ËmàNµÕ†?Ô&bO+X2—IzÒ™+iV°´ÙÖvËý^ÁÈÅ:*9+°‹¶YÁ—ïïûªœõ¤ç”",”€Ì½K2³»×N€/UÒ±É1):­²Óìõ¢L C% ë¬gÒ:(ÿA©cœ•Õ«wJ$•²ÐAU³• ˜Ô+!çÒ©’JQ.&E§'’’È\ƒf®cP¥ŸZä¢kæ:tµÅŠT€Ç pÏE虞Iß|{÷8A·|ÁÑéÞ`«H †FFQ‘¼3$QR%ÿP•2©BwA?YˆR(X~; wªÒ (’Lbã§Ç¸*äEÑ)ï”힋Ġ; žTÔ/ o¼W°wJ=U€Ç œ•="Wë´%}ÈÕiäºuÚ*àÌ… íû»\•|M73ÙŠ|€æT€¼R”¹¡xÀ òöšy¯|Ô®'ÔI9éøÍ+EtZ(ãAÒ–Ô-€ÿ‡ç°Ú;Ýíæ°È\wzÜ)D»Ý+xEÇ>½sœè¡‚“Aå®{®{çE 8cXîò×¹® ^F_ß.o¿¿éÔ¹t õ£ØÈúk;Â:÷?öt@<‹;õ¤Lj,-RPÏU:]Æ;¤°ë4l§óÊÔ>éA]jAõqíô°k$ Ê¥Ó¹CæhÛ¯NI+û²µÛš{ƒ#Íúæ°Û¯¼ E¸hÏ¥A÷×¹²‚bô%*@RÿCw4¢SŠ¿*ð?$}P˜Í nöÜVìäÇ>Øo¾ÍeÇy"ˆÂ–`xêªî¶;¾H‘¢,"Ä !±ƒ÷Î9íK2  a&±¿8U_ÛÕû×T@ê yà„- ê4…Ê÷ôp‹5W ï(Z9BhZôi‰¬y/FüàÈZ±ÖЦ~-bØÿo4Uæ@cQ?Ð(©è¨ÌÇ“µîQµÂl'jYhZv”2†irÛÑt¡—‚Ò¬ÞÑx¶¼xþFÁê§‚žW:òJG^@¥À)ˆOëo|Æeˆ0µWÏ4h³1ƒ _V¿†Æ¶éfKÈŠÝv4ÃÝëâ >Ò(4nɉ6¡yG„ð^ˆP^ˆ”KÊD è(”Y ež6¶d÷©æÑWû=Óôòu &9ÖQ^>»òj@ñ•–(òr ¼ñ!»õI)P°DV,O+;ã… R|¯€¬#Äw²uÛÑÑâR¾*ˆÞ¸ârתtÛ4¸¥=S/Þx(9® {Ì¥Ïú Õ`WOÔðyEX(·7¢FTá[ ¡E¨ pi@M(#j¡êáƒ(6ZptŸrãö|Ë'ªðˆ@= -ˆ–‰¦Žæ3¯5ðVhÏ‹hNR ¼¾S`'êDŸR¨ ‰eª‹] æ¿G’‚Q~Q`‡‚qW2χ‚Ð*?ÿÖÒß›ßqî×ÈFK€¾w¡Sì÷êÄ8Fë3‚¨‰¨ºÓè¨Õ-“kÙÉ—B4;QßQªÛßBƒÓo púÉÔº€–׎ÆT2ý’»³*ŒØ±¥7ÚLè2UH¹ÁÊÓ ëPæÅ¥¦èìD÷¼òÚ˜”Ðl§MXèW¥+è¶Ü¿Wа®tÞ(¯7/*˜•WÀ–òÒÏïh•_ÌnÈúÍë9ƒHº+„ïÏë쩨6.Øæ,­Bs¾ ÅvwgÏ¢  hÊÆ~x!P϶[ òÖŽÖ’4°TTÙÆ®Vóî eY&º:ToT#…´!XÊyD HOÁ`¹xë8k¹SyÁ P:…ôP^¥‚íß fKD•×Ìœ¹bÓ‡‚1×wâBË ¶nÛ›‚ü¡`ýTw@ÿú ­ÒúH°ßW¶$’á±Ñ~§jˆ–ᯉ(~©ß_#ˆÚæêDh‰îw hbØü÷Xž)„:P@B“ÆÅBsžØy¼ÝJI^ïpMÔ;Ê7BhÕå Ô–º£*½ è4m-¨‚µræµ–ôPÀÑÕ³+û¡ßOË¡ ] ìT[Ì-·œ¦»lAAì ž_üð;Zå×–T®Ý,Xà–ÀþÜ¿‹vE g4[ê>kêD½d ¶·ßr©@ ¨u”¬@UM‘ PyÄ«]¨Ÿè¬{ôÅ€&ßQ¯¼ÐJå…ú˜å4 7›vY±=^PƈÐÚ²¯‘„ÖÂ0„–J4] B Ì»‚,þ¿ t*}U0襀ž?Ä© I•w½~Y32Û˜é%4ÃåYjOþA0ÁJ¦™1Ñq´ 5îñÂq¹®¢–µÍ‰f¡ÖbòLÔXxn‰¨ï( 1Ѿº®fÙÑ~JGJ¥žåeμÒP‹ÐÌ++/FßèCÁ,Ôj¥­ïˆø–gj0ºÍňšÐÙYi͉f¡ %nb 6Ä¡€LóÞ4mŒ´Qdž?ÑýÉ<ìÚWÜ;ÊÓNšÀlšbN6‡õ¼.t`µ)hþŸ L €Úó¨€VØ"¶}¯`´ŽÚ¥ _ñ è•—3/‹õô+w~¤Vç ÒuoeŒ‹RWwÈxRœèÂ%(¢fãâØ^h¯Œì 5)ášÜÝò@ÔGç·j°â>«Î8QD/h¶@Q„jMœGePIhñ"Ô,„yÂ{µ6¥ìÁEDÓÝKìy¥ ÔìNt1o„ºwmW°…y…uƒŽJ{&4åÝ– Z(XõTPƒyÌ»‚Õ¥`T^Y¶ÌŸP°,T°T¼~ÿO´®W/eݨ4K:Þ#ÆDÃz\=Ü—%RˆIh¸Ð¸? O"Ž'€>Us;Zv´µ‚MJ4€²–øÜQ'êý¦‰®¢Ó”.ŽßQ 1DC¨6,è%€.b™×À¾‹9}–éácÚ:ÊëPp¢‡5“‚‚ õ|*0¡%·®àB™„òÚ€f ö¦`=óú´…'Z1‹üÁ“MÜR<í#A­zLnMÁA€Æ9wž­S ¢FÔ€jŒ7õ÷™heg™kª"éìGcGÛŽÞ‰– hD2†P‹PDÕÑ-h˜·˜âé<ª(ãпâ/QM_ˆ¾ˆÎý•Žbç:¿*‹¤ò Ÿ= v(`rez;ª=¤o=ÌÖê$TPAûPóŽÆ¥À~`«üÆbX&=òÁò¢SX½Ö¹§pø9{jüz¢®1e¡ ¨ pÁÞâ긞ý†"ÍS8¹zŽ>#$H9Ñ ÔT‹·1ÛÚˆÖjÏr×ÚW#ETÄä7´$–·—òŠÅº×¢1Ñv˹çÔÚ›—‚ˆñMAª½RðˆKÁòoÉfŸ¾*ð®à-¯ò©`Ðó`™<ÏóýªÎ;OËÈDø_™5ýLCG¡^ˆRsä[2’:rœZïr/ôeXpñt¢‘Äu€îÓ:{ ·ÑíÖ>Ñ@çpDp¢Å¬9õ^ Rlõ#/×:Úó‚Sî’‚øP`š cÍÉ/B»‚ùDOgW`iWà³_ –ª¼¾W`Pð;{û@ú ÍßG;naᯡöólºJ™Yîæ¯H¢‹…gu-Ü1…Ð Š˜¨,:šp4 ìö†pñžƒT]Ð Ñ$”“uÐêò¦\*ÑRvtê] õ},+И²jš‡ÍB3'2Ê‹¨õ±pð³>¥¤D0¯f&ôSA¸ÙfÓ5mÝÑô®À¥+/-}*À¶]Á|*¸ ½m¼Vt‡°li_­)Që¨I›ò޾PÙó£/ùr ú¦Aô)ÿ;‚Ye_õÕÉŸ; Êðƒ­RX3—"8ß5ÃêxÉlq/j©¡ñ]f5 ¨à•Uµd@µ¡h¢ £¦‰[“xÙhzå¼w³ø”@kù@µH kŒiUT+Úû*%V¤UÎ5Å ÀdgnW“})-‚3"È=»E 5‚‘VDp\Ñäh»uš9T#ÀžŽ­EPFÉÇ`¾:)jÏ2¥2kœQÒ¤GÞ-b i†ªâh|už_bŽâѦ¼J…¨¢ŠIŽ‚ÿo(J¢SZº P\cO#*+n:@7-}o±Õ£®Ê'­¿–I h&Z€ oM±‘˜}­^³(ú²âè:ú tâ· œåæM &¸þ_x+ÐÅ&ôeåŠiôUGÊ<É¢/ ¯´Íò¨d #-[#8ŸØý=)¯È²ð$PŽ™'ô•šº)oþ¥¾ÛÑ'P/éU7ìCM³!š7G “ž9PÓ¢@U_ºšäu¨bÓ$b6Ïûæh ô]곉y¤½¢3êV{:jæ>ôTš×4Ð…è,¨)Qè™'u” 4z83k"úD›i­Û(æÇ¤kEwjøZŠxö™Š5µDÔc_ -*w49о€Žö@³äÁaŒ@ïÌi«}}‰@ó:Ðöõ鋎ìøóÓbF³F80œÁܼI8REÕQu4„ QstsÔK²ÂÛÔÁÙ™•Ðe­K‹¸çM_å"Ò!Ãíq„1„¨˜5PQShŠbó#tû“ÆGwö¡8t4Ôº1¤ˆ|C¶œy/½G@cˆ£"˜.hEM-"ðwkûúˆà`Z|:F6ÑÒºÀs mƳ©CÒIT¬¡Õ1Œ!Öué®Ëл.cº æè6ÐÅÑù&i¨–n áþ7[<¾.)jFt»¢­/ K3†U+á!)2åÒ"¥ŒàŒbòUt~ÿ8‚÷Õ¢#«èGR^Dn 9¬a4kxEŪ„CÕöC–Å!+Dß&¶ÐTsÊz7†ìÀfü- SŸÌS ÓÍ2PZ€R.B ȪË@ÃÒŽêg*H€–×½¯@uÈER“‹H±–…¨ŠØ÷†1„Ø=‚7# jÌÅ‹d[~oÆõ®Ë(U—a‹¿Ì±¦Œü¤¢%Ðè»é2Ö_€†.8¢b¿¢?{ cˆ£é>µÂb Ý  ¨¤‹Yãp4[áÜ)4 #þ.5ýÔe¤, §4cÈ<ãçf Yº.(§9D©Ëúº-ÿ6kÄ'µÔÔh q´Í*ëªJcˆJûŠw2¢"0† $C¶‹|3†X7†,Ñ'A‰}U”¼~‹€è0†D/}™i Lj_D‡1äÁúA5†`ÅeRÝï ÏÁ?21ZzPJŠÇ…Š| u¿Þ!2Œ!-š^éa¿R2Pâîr5÷¥¡ÚQ!Æ­)© ¡…ƒÆ`KT°×b+*U.¢Õò½/éÒôU"‚ô£Ê&Šº …im4†:u”›“Ú‹HGÙ×ÝÂldãó%ëŬÁ;+‡YcªŒÃÑ0†Ñ)¥».Ctc#C—¡jÚuw¹ˆ÷7u4?Ú‡èz1†ˆ~3†üv¢û7cˆØ³õ%£¯Šîµ/ž.×¶ŠÚG0õ#z@G“ÓÜãòûÛR¦ãàŽ°a QÿWWû6~‹ôé5µ.I@¡Ëèè$4†GWù¢ËàΈbó>tÕ¬±Çeƒj•Z,ÐC›Y#iCïÆ¢Â²³GDt#:1“GÒ“@þ4†¼$"hö~‰Ž¾Á‚¾€š£{‰RjÕ¨¡£‘-\@ƒ—ÄoÆæ÷ $u¹ˆWpA.£cõ ªgY¥)@{òY{÷"a ¦Ë¨šÈY¥i ás°C2Œ!›ÈC¥wtºŒS.’úëŒáoÍñpcî?J!‹\„ ÅåwCkž}¢’´£¶³3t¼ù(ô†>Um¼7*xŠØý täª>³]èw©m<Ñ5W0tVð·rŸþqðÆdèŸf )þÎªËø;k±ž ËÐw]FèaŠU•õDéD©¡_Cb(©úèxCØPª¸G;!,!2P°ŽÒi 1 ˆ¯½‹í>MÍy¢¬›¡#×Ñsš€nx•¦8j¹Æ¯`·\Ÿ¦Ãä"6Uµ¶tm˪¯zWäbäò ¶¦ Ãòã/:ÍYºéÖ>Ø1ÏàÙ¨«­ÔQhÚ!@mBCr¢±!µ‡·«.#áN<‡1$Õ¯‡ß€ýz $ Jv?eAu ÜÐ!ÁM׆âîmX* Ké¬@zU¦p­ÀÐÏ xT€™ܯHÒÙVúíûf „ƒQ]tb “i Q ]b_æo¨eGõjÖ ŽnЀ(C—qAË#ÀMU Í.I_ùˆÏ!á€m訊ydº‡[Ê7›)(KHp ¹xS1—8Œ!âÆ©cHô žÿXdui r…Q­ˆC‹ ÜòµV¶±ý#–aÖÀ~zê2èb Iª7k´i}C”‚ ´`q¿”£4QŸýຌ<Œ!©ýgß;Í|(iƒB¶£8¡þÞÐÛ­š ÀA ´ªÆ™ (?“44½äÌõ²\d¹€¹ÈÁ§ä].¢^²C€F«(*ˆ³ñ F.û+tt­¨WPÜÒ¾©-P’ÆÞ ËØÝâ:a?’½\—a3Tô”‹°ª£!oÄÑu].Bªn )«Y#é0†|=M—A)ÑSÛ§t\>,¢BŽ&C³‰Í¬ÜªÕ­Žòо¬_C) ¹ˆ  (ŒÔse—‹hBzVÀkÓràXó}ÅSš²7( B±¶f¡¡Ux¼PPñ ”DcH]Ìœ\—a¥k—p`€e(çûÅRR×eD©Œ!ȹÈÁ§.£6(¹.#^å"éáÆäÆûzC" 5ôILïf ½+fvjCÈE®Æs(Ü‘+ cHª =š.(* Cgù‘è¬ '¹jžñYÁí–rå3WúH0†Œ î¿Êi Y*xy®´C\—!ŠsHì…·¡¡L’‡.ã5u†*Ðp5†¼ ]uÛ˜*wcÈaº ¡äK(J@%Mcˆ±¸Y•¼³£À€ò0†˜Ë¨’¡/eÏEÈ•´Ú@1}uT Ъ’Ò*ÜP]*¸#—¤<å"³­ðéWÙ®èG–K íH¯À>ùîÏŸÚR‰Ó¢1{¶DuóŠé2ì¾\ªÝ¬AÝñ†h„\Ä!‡}ÿø³Fp]†¡]—?Œ!t•‹XC–»© TO”tÈE $-ÜPºÈE^ ¨çÚ].‚tʆrVäêGƒ¥3A1º§¦mÆ) Œ\öí"iT`(Œ!× Š£¸ðah4Tb9†1ä5* ÏÕ¨ï6Ü·¿Ý {À5”nÖ(73ײ …p& Wcˆ¡Xö7_«n´:t-§.CuÈEìé—Ýòè¨fž¨}ÀÜ þŠÃb蔋T’džõ4> èÃQ<4™SE)È•3‹Qõ¡' †vå× "r žv0±9KŠ ì§œÆô.)ȵŸ˜^4”ÚøÍ+xyKðOCdê2l,h÷¦5m› ˆ¬‚ÛÐedÛ˜ÊÞä"4Q+dC𘓠;ª÷ 4 4 «\Äu¨D¹ç hè(ŸÆù*Tw%ñ§êºWŒDÝrŒË @{®íÉ6ˆºèÍQÉã4†¼U.”.Mùù?U€ÅÒPZü*žKeõ«T`(ž¦ø}Ï‚+:OùP Â̬‘Ü!käðô\Ù¦1¤&‚1ÄÑPé)%Väšrê(‰oq3Жë‰Í_-W’bG.m=ÝâPµMÉå"–ÃÛriŠU0ü*0†ü¦1f [[w­)ßͬ!OòÇÕícCŠë2°Pzب;àDm œ)m˜ÑÂlÅ®v‰4FGYO³†õ—(_Ò¤Ét¶)švCÅþN†c7Tž].âÆ9³W”V i¹Û<Á²½¡ÑÑÊ:+ІÒ@=—ŠÌ H©¡&A®î†æK‚m[­‚R§ eTðjè§1t‡1¤ß!—Ã+Œ!IjT….ã _0òb aCT:jÈ+ÉW:§ºê2€âÃÐi ᕨ†J—‹@Ë®™ ëzCÝí!wMÚgÖ(jáB¶\„©z®W¢ $¯¬¤¡áüºTе‚øVÁ£ç*dW¤JBŸÆ’¬­mc,•ßã‡1DcH7k@"Ìú¥Ó¬±u”ŒºC´Øe¶†ª¡ì(¢¦­²ü¾óÃ5 rOvyÑÐXGTÕgt¹Hœ˜r•ö‰ô«Š~@l(EGw{ÆÊ÷p1†Ø¡ç‰#Ð8rKù¨àÆ=Wüfúw”³‚(VAšÈYÁm© ¡DE` y¸1äqL]† 7kÄ¡ËØ5S_ksšèf)pJÑeìY:úÊŽŠ¥¨CZ)S—Q0éhèwgqÓ¼«O4qc»1DÜ‚ª •£È¨¡â¨m @Õ„b2M(ž‹ñ¸Û>4 eVF(7Z®Ó’«ç’­@z‘:Œ!¥¡«4%«£Ã¯2!«.o)ÛìÞèNÐel›T¡2Œ!D4Q×eÜø.S—á/ŠÞ¯º &rcHÌf}î(F §.ƒ©£ hÊ7ì¨ÆTÍ ÛP›<!r‹Ž*ÙxÆìh¡¿5†ðMî12B®‰ö\¼Vpô ÂG@§1$ŸÔ¿« r8+ˆ¼¶å”ßa ±E®¶E~7†<ïÙµƒW]FŠeC67†ˆ&7†ÍEò›1Dž˜Š¡ T€ÂrAÕЋYÖe5´Æ ;+Æ ô4†j¹ ›RCsCU¬‚WÚb™ø°,Ô!Mù¬@Hf®Ð8 × rh覣‚ê?aæz\Œ!û»1$ÙJÕ¥*UI]ØQ¿e IÚ%ê"‘ì¨â•8B@CJW]†^uÓ2Q¦4Œ!JIÿÑBêÆM €=Ü-ÓÖ…†ê¨Så è¥ñ ·+ ¶Óíµ² êj äú¬ÀsÑwšezO꺌:!ѦSl®ú«t¨Ø>€ª šêj ±M> Ô_È6´T Ýr ‘Wœ e"[‚åj )7找›5b x5†°ë¤¡‹\äj ©16tC«•bè0†\+¸\Ê#6’ÅbèЀh¢jc IKñb 9ÑÍsÙF4P«à»ß~°ßÙmhIQ`qcYZ+žmúšÜ¬±WKkIm9tµju4V˜±©ËE tp0ØÖ?ï4PÞ¥jJ»ë2üd¨*Pô§}p,~Çv1†TG ¨& õôÐ~CKi¢ #@¡aT`;šDCQÁFµ¡AÔÚR …¬-5´²ŸC‹C|ám!TÀØr¹ñã"©g.ñ âi ɳ†¼™5¦„§ÃÚ¼5Ä-Œ* z‹ÔѼC‹€ý<žÑP°ÍX ¸• ]Œ!âÆÆíÓ²u;ré5—©.•.¨ú=}«úv ÆQAxwVða Ùì‹a Q±ýè5×1+Ðn ‹.üÓ¬1!Ddúp rÏ@sCu¢¬©žºŒPc¡n yÊvê2vñ™±üoÆÇ]6Ü%w4ëD‡1„VcHRÚŠ«DVcHºCãDÏ\ºJS-£c.¶wò ‚Ê”¦Ì¶‹¬©C.t›Æ‡/ÆéÆÞVpcˆDCºYC»¤CêÐeh×ep}s1`Lìh6Ô;Ðn QøÄFg6Òöµ±& ­„"ÄÍcÈkãÏ#Ocȣȷ!·âè0†„d¥l†¦zÑ€$%7¡È™‹¼‚tVÀ¡WPžШÀ!ª´¶E=s=9eËtT`¹´6v[+H÷Í!C—A–4ÝñÀ–¶Éñ«Æ‰gÓrÿWcÈC€Ú·' mÀU\hßÞ]b¨°K¶z5Ð9±­É¤wéÆô‰&ºC Æ|C,J5ôb 9+x.TB‚ ¥¥‚ÇY!W’ž«Ì ¦1di+Ár©àb ©®Ë8›ï*Ñ…ÕöLŇU‘t¨¤a )S—ah>QhÛ¹£)Òi ÑÀÉQÃôDi5†àˆ*¬†6öD7G!(̰Ä9*-×D“¨çêÆG‘k³ 2rÝ— |œ ¤)@w^!³ìyöÓ’Ö ­^re]¥)ÉÜßÃÒ_S0]Æób ÙÚ,.Æ,ÔÑô•²Í¡Ëhq÷½5t¨~¡µôXŒ!7°n )LÆÊÄ JìhDuvé1]5 ù5!™ ý0†´ª_«1$'3†ði y*½Ëu¢[ÑÏ €¢‚×5*ÐY[l(Ÿä¥ „âÏÇY[¿âM ˜5ì‘ùœ©šJ@mHý³Æ§.C µmÒ!™Ycê2 £C±¯m ÚQý0†DV›}MTjî¢`ƒ ­§1„#66~_ÉëÝP«Ç!»òT£¡ÒÐÃ5 2ÑL«1$"*`Aý,ðï+†RB†²¡‹1䣥ǧ1¹X«W€ê}wcˆ ÆÓŸâ¨$~Y‰¤ÅBô¡ËaÖ5ô4†È7PÞ8.º „oHŒ­LÝ¥fÖ¯oC*P—”úšÆ>ÕD´ l¨ùî–ËÐÓbhè(Ù9l°/™Ð¹®¼*Q襂™ëøFϬ~ ~ S®¸üÜÞŒ!"È™ô<¯Ö4Í…4δ·áÚ·P°”L—g×ïe ’Rð;}ø¤›5†1¤ë(¸&rT€ Vv j¨Ï¬ª¡ž hÊ‘k[QMúVÁ“£.¼çª].² cHpô¡ÁPþ¬@Ô+˜Æ‰Š£½{ÆåÇ__þ☿ àÆ"C—‘4ÉŬa¨;0å!‘r]†ËEìêùBC·a )tè2ìøO È6Œ!®1tZܬ1ÐÝOŠ)6îæ. >;¸†\â(”I7BšwcH¯à’‹QApcH@. ÷!MÙÖ €ö\<Å况‚àl— tVðÝþäÑ9äìï‚y)Vï©ËÕi ™h±Uz¢V PÜŠ!z³µS oŪǛ¿3“à9SHÆÈe8:‹!»Û‘ŽêtC€VDZUÊ&JØÛvT¸D¶ŠG1(WæÒ2P6ì¸2@#‚‚‘œs•K1ÄÑ^Bé(]QÞ§‚ågåM©ßl P,Öm‰+*ź‚ÊÁŠb®-õbÈ/ø:®_CFÕWù=ìZ a¶Èe¨dZ".bñÐéÕsKÅÓBlKëe LŒÿ*!C.(õb3)Q‰²?lQ=Ð%â"QÖ œ¨(Ê&<â"èÃV™hsTøÁ‰¹`«´2Š!—¹¸ PÊ Ø Ö·h wK&²›‚v-†`±‹BA   rŸ ¶¦‚Y Á÷N–ÇY 1¹—5ðL§ÚËüàÄÖsø..Èx<îíBt-k¬¨D.ãyQÓš¾1ä2Ü`e÷bHqtÓtÏŒü¾(1C–Y !d@–dsñ÷¹äR a‹¹ö‹‚åM€-\”†uUl(ØBÁXìÃRÍT|±Ÿ¤«‚ ì;þB¶§—‘í¸„Q¡‘Ëxm!¥70-«šÿ”½ÅE.¹Œ’kä2r¾å2€ì@©ç2€î¤{d@È_ºŽ6Ì}x +5V¨8Êõ%£¨¹?ß*+.Žöbȉ {ÃVMÙ¤+(Š!\". b®©O鵯Ò˜ˆMÅL©Å³ò,Ldã  $Aí€áà‘ñ‘ås1DÜ ï,WÊ¡@Þˆn_¦~½+؆‚„¹èMùË‹![ÅC!PÙâÏoáß3 ໽i9V{+†¬¿£œšâ»{1ÄÑÔÑýñx˜ŠLÔ/¿Òk.c=3 .P+ºJ»£´ŒbÈšÖ@ý ¾^ ažCpáæDŠDk ”€Ž¹xÌõõ\¡ .ëïm*J@é ‡-̵Pz+† 8P˜ T¥GSdΕþñbˆ[1îe û¹R´‡-ö3¢t°mõsäìïþõ»>ø‚rGy ÍÖsŽJ騭ìSvtUÚ™}õÙåJt  ‹E1d/ì77·,ÚÑZ'ZQ‚1—£(†¤3.RöY ¡M[ e*ˆSu4lU³‹=Ð$]A |S œ ¨b®P0æ:m=ÃgûE_– “/‰™GKƒpIz´µq:˘GYƒŠåPèâ/U~]ãB£bµ":Š!Z°Õv  tCàϪ& kC䌋¨Ðr-†-Ø-9v hÌÅ'Ê'Ê2â"@]AÁ#Ðý@-]ÁãTP. F1$lݤ:®Ø-§­‰Ò@å¦ÀP 1{}R¼8‘Ë(ŸItæ2¸ ¬Q¦ÌÔ/?Qa³@ÉËèq,³^3–žË¨)²^ c¯h  ”ûþ@•Ùðû]{YƒÉQÊ(9Êq±kG¿’á€]™ ¬Fú:Ð*‹b.ÿüÄì ÒM²{ú®€ÙÈ]AÑo ž§‚"-Ø©€¿+ȹ¦Æ¢UÒßdzòÑ¥¬ñD.Õálv/kˆ£„}•ú íø{;úòûék½3rÆ«'<ôX¡£–" Xö@ÅÑk1D¬£*´g£(kË,†$Ä…R/†hÜýÖQZPCôV /¡,=.òå¹í˜ë“‚×% ¤£F#š”W<Ú­¯"m*øZ –®`öU®Å”þúuCH¢²L6s=dû¥=—A74‰£2P>ËMF.c¢\8Ó(†X‚À>©t”úžðdG1$?2n[4Š!JtE7Lúåë³(†8J´jè^¶tεcÎ(†è\ß‹!(ÐSAÃb§‚91ÌbÈ›‚ýªÀ\Á3¶zQ wËŸ^ ABþ–ËÀÏÊ£beæ2å‰âÔYÏedÿwk#—q¢¯Äyä2RGÕQAJïÅlÅ4Š!+íF©ùc¢²[!G«ÿ5èÅ}C[ ×âèâs%ml½bMÉîÅÔìxÓK1ÄF\de~S`® ‰ýOõMèT[9»‚ ´q £²> uä2>Z Är3Cˆ¢ËàæM».—²¯I|Oª³¬Áù Tµ”®q¾ ²¨õ¸HT‚”puúY ¡LœÖGlkÖÅ@G1䅹ȰʚF1„äÙü ÛV ÅQÂi23só£â Š+(SA ̹֟ ;ùï’G1„pT¼úN[$5G(#—ATÌõ‹\†l·D‹™Òƒe>®Q !d@šR‰[¢Q ’YßË<Ê&_ÿ3v7«‘QÀ |ˆóQu;׺·¡1ÜEo‚¨ ¢Ž q“E°ÛÙ8D%Ùa"8ÉRŒ`\ú3;™MÀA˜yA\Z眪®{Ûö£¦'éîù“éúu»;éþe©®–Fy„‹`ÆE¼æˆ]Š6”rE ñbÊm‹!DɃ̋,š*ˆóbl[{qækâ¢VÐÕ M‘¶0WÀVAoF!EkS1ÄKþ«‚òsûhp-1d_fÚ(—€æÑ€q݈Ë`æ Q5óÈÄí(htŸ;ùŸ8.bÄBÃE˜$º%†x °‰êò o…~#† ÷\IJ7„ùH¤Ññ~ÓYÁÏ?9/ã¢L UÀÌ‹QU !ç 8UÐ× ²¾ ± ¸¯b0Z4£)f“Û»U_ AAGÁy·—Å=Ể;D ©âLÖh,ÊMC°(æ("¹¼A¢žÓŽ\Cæ`¾!b‹Pd Ò(mÄ2!GbHÔg\¤D»|C\C€Ý€Œ L¼‰!Ÿ|YÆ·µym*h8“y$†xa@ÀEâqÅ©åu¡Å®ÁõV ¢)”+kk#†8"‰!ƲaÕ=T Xe 0Y#/—dQ*†8ȲK”=D"^$hQÈbˆz79šeÖÃ&jS´£ ¸HhÀÍ·g<–¨wÉnæe߇›ûáüËç?oÆŸÝcœG楜Y8 çJ7Y:Ðë†Ò¶úRAKÔѼe.èÐ x\¦„DwWÀà|ŠÊªT1¤÷Èc1$eaÙ¯2¦bˆ™”ËÈQ†Øj%N£«„ ¯øpq@’yf®s&kX‘ä‰!b„Q, ˆ®>Pä=ÅE`„‹gàl–ë³(±Ì+z  ."Ë8›9ŠŸ|ðüÓÑøá›ÅÕÅÕE:˜]\œ§OWé³]f©±2 ù{ÔŽÚÂM[ž4ä©/¾Š¡)¨muRI´ebHÏ!†&pMÖ`tÈ YÖcàŽ"Ñ &4.U a•5¨pQ7Ž‚G£p$Ê%—ËÞÆ2äBœÇøÒKésŸ¢C#¸1dÈb+.ÒÙï§C^ ½s¼%†@ШÎË12Á"Eg0\£ÏôqCš‹¶†‹—Q£!GQ ŒÊeÈÜá22°?ÿú‹o7ö¤°È=ÝC{]#;ÕDº"†ìi´­ÑU Y01j64 @P³Oèãù™î•:~Ü=žyqŒ¦ˆ!!D”¤, TЖ¶8‹!Ž]C°ˆ!u^,óŠÈÒÖ@Y iÉcc\F—¹Œ~†¬àËsï‹A-!CÌì””W"yæS4&†8ôEÖC‚ÒÏÝÌ~$2ÿâðøŸÇ£90ñD Y4¡ˆ!$.+¡W²Ø¨©¶ˆ!#ăÍKá ,†0îüþYÚ+ÿc|úüƒ×d­‹‚¹¶ p\jM¡Zµ&†” @ÅŸÅ€†¦ÐD iiºj`TYcVdÆéàV Öhe@ÚÙË™Ë ‰‚Ç.âPg¥Q1øS4-ÊáA+[ãþ£¹‰!3¥˜I¼ìE@lM X`ÃEhVÄJQÝ^¢{d7ÛÌ€Ä@2¯øþÙï'oÞ»÷æ›rº'w£ßŸœÏǤÕW±yµ’bUÐ!X´â"¥ר-Ö¶<šÒ9Cvs½q8C/¦]íVŒ£Œ-IT¸ ,\`•5ÈÃD Á™_„¾59ºŸª?XÝ|ûÊú•»»õúq³zöîúúôX÷ŠÞ¯D?‡±¢{¤â">‚‡"†´rcÁÄ'7G5±.E £!E]Š¢Í+ÁŽîmŸ^¼x¸}åÑíÙ¹¬et¹¶ T7öVA;CvT€1¤F‘&bH¶"R@Ä·À„˜°ü.£3.8êksÛP¹ îAÁC —!WQäEˆ¾k˜%ZÄ&”ÒÝ?¼¸:ýõn}}¾Zí§OLJÏÞX_?==,÷+À}C |U$ÅE†‘‚2.b76„œÌ ±D—E AÉádUŽìãÑç/.íütUZsHÌÄ!.¾JAS j[µ‚mxn¸Š!Z¶Õú¸™—Yä)E¡ÍbHä‰20¨!mW.£3.£_—­qÑlŽº/7bÆXÄ|C,J>~-G°ÕÓo×/žþö`ýÊ/ç×wëÇ××ïݬì~eabÈXÖ˜op‘°—ÙpCjt"†ÔyMÄ—¢ñBVåh2~þðòÅçGÓ‘Vå¢0 Ì ¨á½%!ê¼Øé;lcCâÐ[´V`b[‘ÈãMqUºþjCH_µEe Â,kPú ‘"k˜² ä$Zl¨bU.ƒ²âˆ- º*O?Z_Ë#¯ã´g¾}°Öñѳ¼*2C3Cìméa¿£.‹!ÎÞj{0$GR”SÔe1„ƒF=¤U9ɽŸØÇ{—/>|qùæI¹Ê®N«x3¯"†ô&†XdÐDBÑÏøŠ‹ ¹‚*†ÔèÌböUÒ#ã*†,€ö‚SÃésèFŸ«N¹ õ™h Ðk¶Ä¡FY}&“+ú A¢¶WO¿ZušöÌñáõúÃýëõ݃¿çÇ`eÌ€HµóYÐÄ61¤·ûаí9C¶q¶h:#Ñxñäö仓ñxxùùwߥÍ2¹RWe©NU*†x-ÍËmW;*pŠ‹ÄÍËQæ«€Š! ¹wª8sLLQ{ׇíKT1¤à":c@ˆGM&d¶&pŠöÄK[•ãëõ»7²<×ëןþ–vγ§ÇùÞ^êKÑ©bÒ+tòŸªB)#M‡]bˆÍ‹&bÈ`Q é1ØÇãú?þéòò§OäãôúïÏ®*#— RMBYXa\AŸ+P÷+L+¨mé¼bÓo|1dÑsf­äÙI60˜ª¬a¸ÂÞ_Œ[È aÇGîܹzóî³³,Z,9ä”crNrjåPŸ3å†rHnœåʽ %’rãÂBŠKJ¹”¸ñüŸgÞygñZvwü¾Ù}þÏÎ7³³3¿U)(Ñeà<ê þ"ž5±*;‹.# Vº2­ìÊÅ]Óh¿i“lŸÌm£‹‚K³F—å"ü:+Œ!º1ÄäÎÿjc=Z¯«{zÏÕ{[(ôr À-1˜èu…Þ¯øhö•FüsQ=1¡`wX5‚&§%z“Rš’2 ÅFa ‰JcÎÐÇéðÝ*m#è2ðykÍ‚Ôhcˆ©Cڄʹ.¶@ƒ.cºÂÍ8® =ï^¤m0l‚IWºÎM¯CX"¡‡bD"OÖaÆÁ⿹4µÔ×U¢ t¥WD‰¾kßš{Ô•ŽÔ…]]©ê¤…þS ©«Aê!„* øÑ€Ö¥)ucˆaiÊ,+ª‘#s­#zÂbÖ02†ÄIâ!r†5HÌ#r|ÅPškT’š.h“=FãX—1NÖöñë•Mg6/¹{qfeY9•Oo¿¸³]5úŒ!5;Â46:©>‘‹caYvA\PÔÕÆS!]™?Ë–ù—Ž?>8€ AºÐõ¥ù4èÿч”—‹„:jDˆ Ï¢å%U"p•¤.IKi Kúæxcˆ5h“XžÄ2b^ß¶Ý¥BuiÖ 4o–¨è2tcnÃÖ!f&MÚ‰¼.#Ý\^ԻŖñÊÍO¨%o/ùÂE,+±°ðzeFëù³¥6cˆ—‹`Þ1ÔŒ!‰¡®Ðd[¢]µ*-$"ÞâdY™ÏãÒÀÀà ýà1Hƒ®Ð îŠn…"ëÓÊ´Ž$‚˜"cEœŠ$#´8hºÉ cˆó¨+Ó’­™£Æ¤íÂb¼„Ca6Ö*êlSÔU]hèjZÖü‹Yƒ K}f€–ƶͿÁVoº;nìæ ïîÞ}´róí7ëi;ùÉ>^V6MÝõöÅ·Ý_Vu½1D£ªŽ¬ŠŸ©¸iy¥Á(ŠËª¬•ÿ*ëÔCp¨ˆtEF¯GyØ;Ö£q ·/õŽÍ¯vÅ×Õäº ]"oBɹ.m¼1¤Ž* ̨¨OËycˆÔè~cH¿YÃCìŒ!:Cò¿C¥1ÄØ¨U…Æ®të“Û/\Xx{ó¬‹xO¹ùÉí%w7­ßµëÔä£GŸ´b 鈄£b ÉJcHV5†àQ(*~:MB˺2©K$¨ËñÚÞ'¿fÍÃÁÞšbô®YSíJ‹ˆ £‹º:ucˆ‰ú#‘{”ã#Hc^Îv€öC:Ä.ÆGY©&È‘IËè;0\]—am{Í?P*“Ѩ-Ý"QÎáqE(Œš6w…Ú²ëÍ™Í<ÎÐ/²õS§Ý¾}{Ñ£õo_~X·aÌÑ[q†Lƒ1ÄøÖ?ÙH‰\$–=É9Àß*«>Po Šþ¾C]Aökèrlpà’ïî¡-kBWÆÕ"p>-¼ÖøU$­J@ó†ëp†#È$‚˜#ºBZNPÌ–öÃMÁMa퓜Ê,º \Q(í†Cl‚CŽ*¨”Ï„®›5lÜÒ:è2¬S¥„Q-ën˦ ³Nœx‚Ý’›h›ìí¾·§^L¾<䯆uk‡Ÿr|¶oL«š1ÄõC‚\ĘR’Z•5µ1&mâ©Å‚t…•‡Ü º1–î ­Ä3ÔÕJ¨`Û,"Àx-I« õcHHËiÌU…´†cˆé7†¤….Ãx HªPz@# ÉD@i¶Œf• 5A—‘hÔ1]ᶬ¿{÷â»c7/§Ý_ô¹ð‹û'®½}ãòèûoÍSZ¤Ý¥„&@xÂÏÀIå8Û@Œ!¡MFs?i ÔéR£.=.•® †ß_hÎ¥Ácr]¡÷öUJ%-“hŽV ]•‹--@[þAªUMª"X6†¤¨6–DœÛ0«fĪf ]Ìo*¢™Wt0kD@3×¶–Qo Q¼’rÆ£ŽÍ¼Ç…öäûOˆi ù½i99yÿÄ!k×Þu`ÒÚQßN*6†èLž~V7†$Tô7h”i”Æ[C2 "ïjq]@6†ÍЕž¬ê׬ ¦àÖübЄckz˜BÿI]éôE *dÞ¢"ŸV©7‰ã¼Œ +!ˆ ©ÜCUT¤)„Ú|ìdcHæQ%¨7†`²™ÂºŒŽ‘SßRè2J³ÓäU5Xeå¸jL T—hn 4ÍLñæ‹%£-¬ÛNÞÿm<[6iÒ˜‰ö¿nü˜ç9ÿ%[QMY½×€Xì 7„xT”YQlÅn2TL(1>_¹´wÅ¿Ç1ÚgÜé3†¤Fê²TZ­G i™ 1êl0†0Út¥1„.Z¾æÎN”r¼1Äx]^zŒZ#h0†¤u¹H,f T\æQ5ïË­[t©Œ³Ç?fÌ£F/¿aø) L4 ­ 1V[˜×¬mÉb„t€jAc²ÄôºXhzp-+{íýç Ï"³ÿŠ@…<šü=]ESb–úcƒ1DÌ5]†‚Ä R9sUŒ&ýÆ”© Õ….#ÃüØèuá¸u Æ j¾×”Õ•Úþòðø ë&mÛ¶lÿþe£ÏÞÙ(Ì–ÚâžÌ5›ÒÁ\«Æ8h@ ue@‹º%H/¾þ™Æ×ÁCÿÔD@ÑgÊ›P*¨z  <þ-FáNc”î šÊ™ï‰7† ¡‘Ò¢Ÿð¸bÖð†H$Âß\‰†ÚRðOQ? Tíx]FJ¨ÅK].Òá½ÔòJÜ«^n=~Ùámû/_¾¼ÛÇ“Žý@¶b ‘§cÇšc£¦f ‡œÓÆÚN 1nuå‹_Ÿðôñ÷ãGþ5®-Ué"0>‚5‡RñicHÖ-ý*±Ô%¨j‰_%Sù‚Š1s^—QœœVè2šÖÑ^0†ô¡±ÊÅA”m2šU^4)v?³ƒ¨Óaÿ$£jÆËmã/Þvàèû·½?¥R *V¢iþÕÆäeÅ› ˆ&´Œ!1P>aÆÙ7_í¼òóÓ§sµA÷ëS¾Ä &¬"í#¨§•˜Âb|Z6¤"~“«HÒ’D.R5†`"Fp`à{ù±8Y|Е@GàáŠÍS ®X;‰\D‰1ÄJŠ †P\à¬ûE×Ù«L Da8àXÍßÉd’I )¶ÄBüjAðDm´Pl;¬ìµ²µ±ðlìl,TÐÊÖ{°ò¼çd2‰? ßîf¿'ÉœwB²;›<Ë÷fCBj JèpýëÃûÏo>~̽òðÇ[ëä"ŽQq{C­ÆÆ 2¥¨!EÉé0¿7†,Ǻ¨£[¯_½ù|çÛ÷G^nÛä“'OdúY©«©àÏéfòÏ® C©ÕÒJ*MY#X¥)Œë:‰1„hÁœÆèÞxÓeèØ*/^¾Æé`Ö ’VV4͆¶›.#V¹HAmc :5{c÷Ê݇oÞ¼ùðùùŸOÞ¦pMjÖè¼ t•¦ƒ1$UcˆÛ£j ™<ÑŠêÊ":êòío>~zþíÆÅ K:±€eh–œ3-‹±Í°,ÙØ|ZN|» „-Ÿñ½À.¿"è iµN"0+º“¦t3†\J«„Ãõ Öt0†ðB€_l_ùh ©r fo ±nÕ€Ìj qDÔêÏ~þøøñ㟿Þ>1"aÔmgú h ÿ¯6àh Y……}´@U.¨8{h6?Í·?¼üòô˽[äWt1 Ú#Á*M‘“ÔE5IëÒ©ëo¿ÊߨF`¥.w@'CfÎ×b}rc¯™„fJƪ˳Fð@¿-PõU]DѬ è2€F¹ ShlÕe jÖ(¨³†?{ŠÛ“³è­ê Õ’-6¬1†8ôŽC†1DÇÕRä"Öã?k]<ãt¼õîý—³xfFFÛ"IÎì"PcHYªõ«1$”ºŠ1$ÕШƒ1dR”³‡̘ÿŽ€¸ 3Œ!çàÀÀO”Á¬!t`Ñet«ˆ5†L¦ScH túõÅÞ6¬'RÌ-6ƒ%̉hœºCŒÚ]¸Ú1~Á¥(#f42:­rcm5ktj AY!z¢b ºÒýÍ2ß©Ä *ºY4_ûò.£ £M‰u£) []´lu=DíŽm43:h8 RkVô?A«1äœèRô\˜±UcÁcã@– Ó¹«.CQÚËEzCr·Óe„¾C€Vc†‡\·7†=˜5Ô›–˜5flµ‹CqE=æTc^NŒzϨÊE²ÊEP:Új \$_ÎÒ“õD¥’·Gb Ñ€ÎÉKœ@óf ¡Á‚ÖU¹ÈxŒ "‚ÁcÈ!‚j ‰¢²ÓI$'f ò\D1kàh°T]†©rfnº »ÉE’I!ÙÁ耭§4¥àO^>ÇFjM²þäDÂ1@¯îJ4}‘…aø^vg ‰j Á”ÈEöƃT´¥Qß¡c¯ (Ñ鄺àb5ŽÆ å’=aŸÆu¥–Rb K­XÃh1†”´B€¸ÄPÓ²ñ ‰*M±NMæ@“¢ŽÒ_ÆÌAv:ê2°'UcÈN—AÔ(ºê2Zì4_t²ÏÐû }F(8<ÐìÂåÞdn:¸Ç‹†Ñ Ô¸ŠÆÞÏÙöŒ dNrM0¹Íbuóö›\i¥4¨¥ #½ÎF¬lfôrÀRmžMd6ò¯"[‘a 8c€ZAc–3"jšÖD&–´$‚…[èJ“/Š\ÄéÐb±²V®åWôh ¹"ÆnSÕeÈ…ýxÚŠQy_!‹ôƒê2Æd ¨TY‹YÃ2šoÅ%ÉHOÎ!pºü¢ËÓÑf.[6[K£º—Êژg¿¡.sZ¦* ½ÇýYñ1 ½íZÂà1`øÎ§>ä"RW3j]ׯsMÈ¡ñ†Í-"Íd{tƒÑ4<óÌ@î ·GcóuƬmQ7´ßA'ÉvTÛ…BÉé¸JC .ÍQZšÕZ®¿ŒðT{1Â5x08ÔKƒ'51$C BÀICh‡„,YšµC?Dß»'YrB+ÌY¾þ­w÷?Ÿ¤*z?­½Rä™5'† YÀ °JJДˆ]JR}NBaF,Õ"¸S—Û1§kpà ÐK8<1„ØüCb\FBÖÈYc)"kd´ Œ—^ŒpfmõÍêêê»Õ7°ÀÊ›ÔB5øï´ÐçHoiu¢JI{–V )ÌÈâc 1ü™³„«”Þe`êàРQÉVS›Ž0o,ÉîK{€V# Øò¢pO‰+ùØr+M 1 KO#¾ŠŽ…YMR¤ôGf"†<$bHÞTˆ¬Aƒ¡ÁȪÙȘ‚˲ÇQ^*JAk Yc¥" È\j™+®Ü–ʼ\. (…(ùJ¬ÂÚ²€uUP’RÈr¥’–buEbIR«½g%K”E¤çæp"Ÿ[ê5êæDP`¿Œ§ÚÊ mUà‹â@ÈPCm¥ÆBHÔ(­ˆ¥e§ö¬˜ŠYSnÍ-ИJ%Bbˆv çrç*LhÅWÉ&Rºå¤ðFÒÒó„Bd ã.Y#Ë€s5í.\=)ÃáJà"Ëk5Ƕ=Y ¸p¸íذpG½A PFµÉ\Õgg}Ý£:,\[ÚîEÀüäP}ùå«ÇzL 1#ø2þ]OÃELL®a 1¤ô¾æpŠÉi[6½\2Þ8¾$w.&Ð2×áéÀv¹÷ÂÒŠ‹ Λ,0ð0šðULr Ï¥–A›––`—‰’{Ò1$“QÄ7œÁ©e°»Ø/èæœBÏOE©¡¤8 #\SCO÷*«žÁ¨x£F½¾Ý”.—û*%\pìžÄß;WÚäIŽf »~œ4ŽÛ6T€Ú¶×ºðZ‡³ŽPßä(/ߦ‰!ŠM}b¼0‹Xk0*2 æ`ɽðcBr!q°¤t0äèp&h7HTc¡ä½…X@”脯¢ö¤11ÄÒQJÄMM”¢–ay“Œ’jÄW1AC4Jâ‹Ò:M•±)”yÜ«©»Ó5õͱ,”.¥p˜‹ -­ÕÀ¿ÆÏ~pús"í *Áæ Â+(«ÐI,?»HÇÕ -á0*;ÍÖg.ÝÀ–¾Â?ø;¾^0ï<áp•(]Uåòd19‹@CôT¿t~*eG…·!$ s™N%Ü™´.À“ز²ôÏ'üsU€Dr׿+lµnóÞZÖÈfÈ-`) Э"Y@¹Ê‰[D aêlärib5–ˆ!Fš¢iê ïE6'†0=W$bˆCJê9Â1¤¨2!Í—‘E—´—‘}[sÚáY¯=n F§õú7êÔëWû-XŸµÃ!”¸—ªll/+£ÎÉÉ×Ýö”›ûáNwzPña–øëAkëz3è Æðõcïhxr¸9‘å—k˺C°Å:CÔ%bRRöUŽnâPËÊ{Ü­V6> /Ûr!ý““Ãínë?!÷CyÞ”úqWðÞ[LbûÀf&¬ 4úÄ À$Å’jJŠÄœf‘ÔœKuâ«èº¹@ Qw˜Ñ™–â×)Ú›–f`äŒ9.c)["bˆ’bi¥Orïknůw¥Ã½qã|2½iNoG‡ýÆywzÛô¯Üo]áòñ°´½?ÞúÙôoú×ýðÏ.XÔù1:Û­žþX¿êú_&Óú`´Õ÷oáÙÁÑõ $ñr-&†`RQ1Œˆ!ÊÕX!Ÿ&&† ô} æçø4Ò¿žU·6UÈÖÙe²é×›QÈ?—áÍnuë8¼é·M sÇX¥^%|Ã$ XÊüí²„RÒ-’Zù¢úBJº‘P–Ÿf‹)bôN_Â3Žqd˜EÄ﨡½(Цp(Ÿ~‚”¡ï¨QÒWÜ6ŒŠ°ÝÊè°¿7>=hìîI;Äõß—bú«ñ­)Ývøeæß Æ[³J¥±Û9nïM7?ƒE—þù~Å©ò‹_/Íðãþh8èü¨ìmlúÛû{ ƒQ1ˆbÆÄLþõ#‚‹è:C`Ú¦‰!¦Yx £â…g³)†<Àþ¶·wt¾þ±ÛÙ] Ã64TÈõ ”Õ­íïà¼÷êLÇX`ܵÀZ°`)€$|kš¢™xÍ|‘²‚Rã1„%Ä"khЇYwˆ!…„Âb\=2›`üeëŒyÚ¢8ÎÒÏà”P‰*!11N±:¥Ã Eêz·Drø‰P&'K„(R‡H‰êÅQ$ˆH0DJ†ˆªTÁÊÒ©]:ñ úïl'fsyöÿå=ûÝó|Ú1j¯×<««»ÖQCÛ¬U6)CíÉÍ>²‚jòpyy}¤YÑÈÊg›•“íÉà¦Wwâ¬è>²r öo)+ ÄLB ¡NbáÕ}v U0e%q"¤Yé´Â8+y’üÍ’Ç,ÉY©¢Îj7W“¦BV\Dˆàõj‚”â¾}­6ub&i— ) ÖÃokÊŘžK~I Y{F A;f‰!ð‚7è°i‚Ë`œÝ;ju^cÁIMלujwäãÓ‰×þSEÕÂÑÀYߨtL©×|¼ÐWhtRö'> Çר`ÍÚð¶6är2ð*Ó«ÃBÿWÉ¥ròP­ý½/MÎu…®•¢ûbÅŠY›ô#Gl‘RÜ4,™ï?’ä æ=îu­¤¨L¿Ç’ÕDòÛÈM4=¨]ÿÐ9Ü(ÍB°CÏDñt“8­.’Iœ]BSœC–R =í3O yEÄE²ÆÚ› »Nhyx"•&)HÐe™ÀEðŸUÜ"„Ë<.ÃþJ ³½@·NºÌíGåÑ=ÚäærÞ®—Fݰs" ãî R6*“°wQßï…#L½áAûT÷Gå2æ¡rØE|~îVǼ{éð\ïŸÖó¶]f<ÄÄ|îØÙ”‚;höÚ~®¥ 1yŠ(«ã$ká•ì÷Âaù¤öuA²³ ‰Ný¬?5Wå.ÏöÅ­Œ Ár–C€ÖwF q8Œp‘ƒš’C¬©mKpÇ’–`ŠŠûŒ²¼îïXîwmê[³ÜeÁŸ›ý¸Оê/®~ð×oÞnÿqvíľ²C\$U>MžB ÊËq×ï¾#Ïü€7Ù%ãÚCüx„(¾JOˆ!ÓÂ8Ì)˜möl¥%jÎQRÞ€{¶*Ív…/~E A‘"† ¡DÖȺD‡ÎÀ ”!Á'A1$‡ø"=ʾ—çqÌs9°<Ëñ<°ÂRÊ^hÛ¹)åñ(OX Yf¤kRx‘¡÷(ÇNi;’K¥J½0ÇÍÌÎ G{¼…F "†È;½íŒ [¹þéÅ ‚'vÏÁ[Gb;Êl6P¬ÐKšËø/[£óUøµUH$ªÂE²¤ÁþU%†¨áâ*Y#%nÄÑŽË4™¤iBy"†àC—ÞÔçÉ›a¤Ôàu…Ç““5ØèS4‚€íÆrlÜ$½Æ‘Òœ`¡”˜’âLÓWFG8æÕ‰!¼´/6~ox1d Tp‘k'† l¯WÞ4Ú·òyÓ zÁ·‰¿%J5]žaG-¤fÑ4†kúšB¯q` š²RjSZª4§–­ÈÜF ÑÔ(ê5ü8CVv¹ô<àÌ%XùL ÉÂe@:¤N Y%íÄNÖˆ —ñÖ‰!™—IÓ —¡éx•ð&B¤¡CŒRëÄ•@G$|°‰Ò•î.âÄ œG'†D£4ª^YÍÈ@nž ž‚(ô=¤RÕ+üC ‰§L/)¯) ôL Y^R`"†Hš¼øv"†L•Rú|›x…kÄ‹ã2.VŸìqbÈÒUϸŒ“ ¤~óB8ŒZ҆˗!)%jIøÌ¬g~‘Δ&;ƒýÃØ¹åÈ QÔR²‡zØÐ‚„ñ1;ÈþW×-Æ„H™¿Öœß;Ý´ÙŸ ÖÆ- ìËÓâsÇl¹6Ö@–K®\].²H¹W0½W°\¹˜*:èU..M‰ FT”€¾VðåÆ×ë‡1dÂÕ¡f 9Šä3 Ÿ,M—QF]ÆÑ!âìºýG³Òå"…¥ë2Dgè2*š •_“/”Êjr¥Ñ¬¡(ÅP3†8Š Iéi á§1ÄQ½ä";Ph ¤¬‘+*Š *€1ä­‚È¥KHSòÍ@uh«ðj¹*º ¬¨ Œ!Âb1踌!2C^u*ŸCO—‹|äf Élk˜ì/±LTsA.òÐeº,J&)äÚóºM¸ ì¸C~˜1duT¦ƒŠ_økƒ…1¤øÂÓ` Ù VE.ò\Œ\ˆ‘›~ý†1ÄÏø0®$*Ýò1¤„1(шÆ µÝ­qËùõn'㬿?EFcˆ8¦ íòÆòocH¦­Cª\DWC/ P Ööa#;µ\x·•È%Ï Âò…w+ÐhËŠï(ç©æÚŠ\§’=ç\|}…nf cH3 —˜ŠÙ£rvY‡£d(«ýX7TB4]º C§®ËøÙt× ˆ MÒP×€`Ò„½8èæÆœ´ng0†è` TóN*@¿~rî(u¾å:Þ*¨«ï@£­A’x@¥¢žë«¶Å*ÆïÝ¢ƒ1dfnÆýËÂŽÚ︢û‚åc€&C™/´ˆtcH†.c‘énÖ¨©ÙuRY-(Æ„¯æ†’›5ÆM%ù`»1d*º%J+óOɦ~ÈËh ji–RÚ˜E³‚}HS*p4=*(÷ ²¡bh¹Uð1”¼­4VÀ2u”øøÜ*øcHiÆÒ!³p–›1$µïÎ@“¡j¨4cˆŒDúqa«/•‡1dÛˆµËï.]†b®îèa¨–vŸ«ð’MOÂݲ ©4I×€H3†4A¦C(N>P”òD•Ã4Üs½T JVAÛrt% 2C¢Ì'‘ m­¯Æ@ŸÆOÑnÖcˆ`Ê"ÔœÕÆæ(Ïsè2—‹”I7lšwæ]ŸºŒ|C0úЀÔ'¿›5LâÆJ3¦D§£b(4 2Ϧ·zåÌ…Ö¦7äšmㆧØ^ýĦ з `ë{V´ðœcH)þ²5tsqT „ m0fÑ"††1df%ÚêÃnÖ€ý!DïÅÒ™C—%‰8Ê/èÒQièÆNzG³l”€Âõ.B¼“ÜÍq3[ÒUU¶Á²ì5©¯G€m(iS–ô\‹ä†Š£«à)IWŒ\»0GÅ+à¨`ð«ÅÞ^+xC¢GÃ’©‹-$Ïùf 9B—qYÒYì¨Cžr‘Í×v2T0|⼫V” ¥0k$% Ì|þaì\v¤†(‰¨*ÛmLš $V‰%ÿÿ?Ô½eÇ Ä,è>Ó“:IFžä oP²Ü€V+õCüTx-†p#±oò¤™{äó,†¼F1ÄD«q®š]”…¾MhÊSÁs.¥YòÑ‹!êsy1¤£+Ðs.M<_ú*• ÖMu*ˆ¹¶-놹ʷ³’ó(kðÿQÖI©ç2TîÅÝòfY T ¨Ú hÈpteÔQA.# ~ó ëjEœñ j2Ñå,†¼¢@c­\ŒèŸ‹!9}”L8ºt” TêÏ1»'OÒ®ÅF[If4Å.¨Êˆ¦PÁf;P™èTÅ%s®£CŽŠ†H®þQb­„w¯×qëñç—]sU‰¦@Åÿòý¦îg1ÄÉf°­Ï¸È:PyuTR–ŽŠ£r/†(Z¯–YÖÐ’%ÊüQ ‘…–^Õz-†(NÖ@sHʹˆG±9W b¡À®Å¹)°nK’}K¶]¦‚:`®ikCÖßüüІƒ,ô&°‘t´èVõ£]Úã“E€*P!*¹£ …p¢)¤Œ8¤Xé¨ü½¥êºì[)×\ÆjrE³âŸ¸ ×îè,†ÚˆŽ¸Hz *RlÌ…úsmTñã4Ы‚=¨Ø[Ì%SÁ@×i«Iþ»‚t«æQ ¹+èè­ÂA…ë5%g°’ÖFNlŸ¹Œ¨8Š’ýVôp´]ɈfGkßz-%m¸MÕ]‰F.óÊš¾w×[1$Í H {ÑD4UÅÙ•#Ý&:æësQèè›Ïu¢PЈ^dÙ€RAz(Ø€¾õ¾J[º‚å¡ @l W„~·¥Wû(†È,†ˆÉ(†DÊGbIŸšg1$ЙËà9°Cä·bÄÝz.ƒ×ÿ±E%É@µP–GQ YåZ 9 ËÝ"½2Qí蘋¨êP TÚB´=QÌuS…¨SAŸë´%D§‚£+˜è[¦¤• ’©þ®àøz)†pÅäx•ÑÀ°ßròTÅ3U;ª@q¨}–5è¶hÖEˆö¶GGD:М PK[C k )ç@¹~é¨IÃ÷@袲!Ž£Dƪ¹üeW¢Fú›‚ôPðçbPh–?+X­¿Û’¥£"s®åÛµ²%a£e…[áØx¡‘ůEùÎbH&šã¨€‡OT‰¶Èe8ºàUÕQJHô‚<ÃÔ5œe1d [ èïÅ|E-ÂÆæCF1dïhÄEXx—Yö¥»Ì¥0‡wø÷¹Žè«$ J4ú*ÛSAÌåh ´Õ `k*ÊbÈe–5Þ'YUQ¿>4KâÕhl`°ââ ÐýüQGÅeCã=Q®…#Šÿ!—Q!)Ú–ˆš„|ª? Åì9å’zGe ¿CR!ºš£ûD9—œ¨½ÍET;ZÄõ¹ž öÔÑõ-!dଠ´+øT¶©àÍåȘë'Ї‚õ´U^(†|ÇÞ9mãîØè YéÅe1ä“Ôñ½.¨åê(vçÈe(sV™ËhËY˜ËP¢4‰2—‘Åí—Š£42 -Š!YS 6Q!ŠÝ™è¢Q ÑLôY 1 .oÌõé½Ö \õ9× î(\mi( *Ž^¼a.Þ7èT }ß|O·bˆ´(†8ÅmyCìÅ\F\먜hÕ@KÜË¨ŽšÑ£V ±¬µ,޾f.C²èDsGkã¥3g1D£¬7ùæ6_5â"³â(×D«êm.Ê:b®%q®s¥|¢úP°„‚|*V;þ`kYBA› ú\Ê=ÎbHYì_ êæWéE1$õdÒ|5v›/¹ŒcCˆ–V >è‰Fx`KBEÈeͼ/P˜Ëè5c¢kÚ®q‘çAÞ¸Š”|` j‘ Q*gù#2 Ô^ Îz+NÆŒ‹MDk  ¨”íh&kÎåvu¢Òª¦-â"CÁŒ‹Ü(ÐtQ Õd æ\oPO­+°§û­¯’kÞ¡ÀÑ=Š!¸Gެ¡Nàx€ðdÓMüñj®Ä8j¾F\¨Öì(®ãq‚â*ÿªñª‡–ÝQq”g ¹ ô™²-¨”Tv¢ìJ½‰ýìÂÅz`¨#áX££¹€b.ã\D-׿¢p¸'(¢Û‹(›­®%qªhcÀ$çÚ òS<¼>U¢O1W £R‘|ëe¤·bˆ)~Ôk1ÄõG¯Å–5f1d]2 mglä2è,†¬Zµ' /Éx³é7#÷€Ë+Ð(†-QQªî—(ã"øb “r®ØØÒã"Q ©Œ‹|d\dÙ¬ÜÐ{1¤Ö?*Ž–§GÇ\Ž•PðñTðŒ¦ÐÖþå,†¨ðÐvdAÔ;ë‹w„D1$Êr.Ÿ­©—5¨Õ@õàýÐ9ãúÏ«#Š3Ë@åP#j¯Q ¨`z„cÆEm¨a® /T˜¬%º`Íú®àg¾*ø ô¢ÀY¢‡£¥4*(T@t*ÈŒ‹È´F1äÝ¥²9YÒ}ÅMo"«K©¹é‘/q‘{.㌋x]";š‰&–5"—a;e•—1—gŸ‹íÌeÈ,k¤Ö3 Z]{Y£5GßÚ÷‡«3Ž*P¤nÅG%-Ôf š„è ¨õ¹ êh\Xs©|ûe®;â)¸ÅEP®] ò‹°sÙq܆‚(ä­¡dÀ@ …,² d—üÿÿDU—”(u'™ 3ížÓjUYfK4u¦U°ì¬@!é¨;îõú“~CVŠ5…'?ý½ ËÍ’qPÊa !ª -Ôs cÈ]—aÔe|œS K â•É_Ôe˜,D³O'jE¢—®É@óV‰J6 ‰+^:úÑG^“m -ÉL+ÐT$»vÔ'ÝÑ*ð£C®tV — $Ðí¨Àÿ¯‚Ewtc.û¦šdhúõ0†èN«¸•Ìÿ˜¼4 ‡)§¶5 m@gy±=>Ðe”òyNL‘1_ýºŒŽnûš ‚SGÅOÔæ@Õ]žtT¶ ºp$Ÿ3û Ó(®'Ô§1„¨¾ðœD.,{ê¹v4_r³hòMcR&\ʼ˜K´L|ÎytwcȽ*H_*˜¿1†ˆª…Öuyr§qòà<ÑUiÆ.o’íºŒ"˜§ºC‡þÐe¨XWöÈFtÐed©ƒ.#uÜÐ̉²ªÕÇÜb:ÌJTµ<ùgç@;SþÛÒ8ãEKnhö§[ÈE&›ä3QTY¶š,¤)u¬ r¥„@QÁ<‹ÈXý*gFÔ?ø#K:*°K3_¶‘ësT@sîò2˜ºY#Æ K‰·?.Œ×£ºíº úûªfùV—®ùjœý™¥]Åìèfx€üDÝ›‡ÄŠü 4`¾1̉‹-DuG c ä†JGçlC®(çœlß8µ Vï¨%ÕZ M!ªhÎÖ+ØXAb&ßV°ô ¼UÐÑïŒ!z1†ÌaÖpy„7;kdˆ97Ïô4†Hè2xQ¥¦sËðÈuÓšOô¥R/f Ì §ˆrI°¤XÔžu#”͉†‡D4h¶5lr3†$a.ÍÕ½ÉE„ÝÍfDÉn‘k¨€Ò9+0\Âߥ)Ò+ài@-zC:磂ǭCj7†TV =ׂgåçß!^ÊÝR”z*«ñý—lÍQ*‚5Îà ÑotíæLõ¹ë2 èrE7ºh&*jRÄhÖXÌÓ‰Š'êDó*Ù´ˆìèëj á²|¾rä2ir‘õDƒÄU 'j^ª­Y++H2T°}[Áh«àmßµeÞ!±rT’ÇÉËÑ»ƒ"®±*!@¹.cúqÿc":7¹Hw`P—ImÐed%:ßuI²Ò¬á@?öËÓ€jÖYT¨·ª 0†üÒÑÜЂ°“¿]š\¤æ²éŸó€гi]¬à—^ÁÜ+0K¬ ¡sË厶ô^”âoV _+С‚zV@cÈŸ³ÍÊùì0kpa'øŠàôZPÆÅéçâ;êîD -tK.¿-@U¹øÓÝJG3PüBì]¨IÔP–µEðLTW"{¾1‰¨ ;ÅŠ½Chï¢h*‹µŒÙ˜5äzž䲇s©²‚˜ól¼#Q-ÍrÏøXzz¸o7ô]>¨ÀYÁÛyñÍÂ]õ9Ûi ¡Ø¢tcHz:Ðåߌ!±¤ë2°'HzÑedÉÝí1 šå]Ô€&îj X õÕ2Im;{CêëG3†¤f !êO‘u °½«2WC5ß+Xv´åÒ/älßT;÷d3+Xn¸ü`®ùVÁ¤¶ŒÆ:΄WÍòC'ÞÊÓš»1Ävð@­ »Iö°v zC­ýà ¨ØMþ,jR) ¥Øüxx˜5Šw4cZ¯Š‰ò¿’¤*JÙÑòÈ@-Pɧ1„¹Š¹dz¼ð¡ƒ%ª¬@ìZ eöß|ZòohT€¿7ÅXôÕ`M>Œ! U`Y`ºÃbVݪiè­!êÊ7|i ©&+âvcˆ ¨Õ†Zç•é)1¹±HE¤®ËàVÍ?žÕeãv¦_p¸”Uvš hht6/DmêO ÅňòÿvO‹häBïÕlG){+*ª@çyÖŽšD¿5]¾V Gt¬@¾«À¼¤V±‚ýW ½‚燆ëßhÎmí4†p Qf™b¦6dÈ.2«Q-o¡Ë Zý˜MÎŒF‘ºŒtÑexñúq›‰¾‹›† /Í¡I‰â˳âR‡—¦â -;ºê@GŠO1m)Dý-^«uNhm¦Lc娀p‰À` Ñw«@–ÞÖXÁÝÒ*P‰û©´C°3’¼Èh ™M‘»Mä2 f °™Ä9ê»1$Ðt>ä"É&‹û¶r“‹Xe¬÷4u³>½3EĘq/(JAIÙ¨.ôÓ¢@M…®¨†¦ÓbVRVŸ{®â‡\„sIj̨ _¤);ñª)ÐVÁ2#¶:C¸Q(+p檨@sT@Ô>êÒŒ!þä<ãÝó(ÆÜ!bM˜>7¹¸â4ºucH"J]FC]ÙýU—a±°1•7¦U¸k¬€ÇâDZ ÔºUš:ZÔ€šåØY¤p žvt4†D.ó-žˆš—²©Â0ñŸhTÀ‰F>i Péô\VÆ $÷ ´U0GKT`¬À€6cÈ`Ö˜%Mf^ÚƒŠ³CkܲYi ™Þ‹^âqP]B.¨M]—QԊͺí(þbj(‹»¬Èm›6³†µU_UvlíhC–Ñ­nËŽ¦›1$í¨Mh»oÕ³’@‹9Ь† *XÅ(æŠ ¦±sêl+rÙºFèÝÑVAÝÑÏÕ¢aÖhwÀ‰—Ô$ñ Ñ&¶ø‘¹¨—“Äwòe)Ö.ØîºŒ„Or-–®è]—1=AÖpöl‡‡D8úÍWTÒh 1騹$ýh¡Ô ò¥ˆù»ËE̹dð@¹{¬€£ýQ|SÚ²I¼çº¡m+H@¿­ aϯÆ¡1¤â‡1¤àÄ4ðÅ‚[,Pã!B4Œ!õ0†h“‹„A£XÈE0_à@G]ǃôÈ‹+ÐU€ºOFTJ!ªkÙ}^+Df ¢ÞŒ!…Æ<èè#Zv”¹5¸ ˆ~º\k$++˜Æ ì}HSªhT¹¢‚.Mñf Ñ_¡­JcȺ£©WP¦k¬Í¶œr‘ÑbZB—±X ‰ÈfMRã:È'i?#š.ƒß±-ŸÆ¿é2<”DßnKÓeÜPê2PÌD´²!Uïw‰É˜@qý¨·ÍËl':Ctz ®Η¼2Ì¥÷ v–Cý— 4û”€¢‚•,‘kµe>!¶ ”tÔi 9Qä!ïÃÂÙn|£ºŒºŒbƒDT³ ÛQº=>;Öjq£Ÿ*Z1ÜcˆºŒ³Æ³e /Üjâ±]ÔÐÓgŠ5š…èjE6NdQe Ð{ ‹–}3—¹D„yÚ–·kT0ÅÎ"S p9×È•T²3W÷«tôým½-tMÔ ÕÑ#jSQæ Ôt*a ³†É¨Ëxû4­ØGŒo ¸\¨.¡Ëx–åÐe4¡P ]—¡£1„ %P}Ä¢?¢tÙQ;Ð7Q)¼â™‰æW7†,cÈŽL“hC9äœÆf?!@(rÍDç–ËcˆGŸç¢¾³éRõw&ƒ1dêð’uþ÷ °Õ±Nî8g ¢¬à/¼VÒdšôp`s>3ÏÁ¬aÚÞdŽCŒh±çÛhŸÙƒ¬§1ñòa ‰{¹üš(5 <ëå"å0kL}A³ïhéh†xK(i !jï‰Ã퉠Ýò#Œ!¹é:ZÌ>—\uG‘«}©Ö¨`ùZA+@[Èt)-×Uš’GÊÉûn i{ù«1Ä×K¥‹q¶ÁÂiokTb|ŒE‡+P_pÖrCêŽ~º{Ï‹Mú>bÄf¥.Ã0H4û¢­‡1ÄE­Í¨—@ßͼ4Ý!M²ÆU"Ɉr²‡¹C.¹€ sÑ\Ñ+˜ ˾­`‰/Dï^AI¨U w–h]¼£VÊ +°n a[FTÝç÷i ‰ÛN»1d~HŒÙŸÉõÐexèB,iC]fׇ–»1¤jb¨¸×Ùd‹Ô@W<&šcµI^ˆv9Kµ@Ó€Z3†XC§mØÙJh±¹h ©½ç¢;ÒZ®¦ÄÏØAšR† cH¯às¢x¸ô iʵa.[Kä"zCD¡Ó!‚ ÈðËûÔ€äú½1äAcˆ^Œ!ÒÑÍOcˆZÎDí&‰÷ ãf ÝB´¸% ê¢‘_¶­š¯=!&†1d&j6ÊE˜KKñ-í¬Ò2V îÒŒ!Š ªˆ|•¦¤»1äkÌu7†Ü+«4EþŒ•G«H\ "Ý Ës ]Æ*Æ!Oò;*JŽ£&Œ!æ|ל'fDרÀ"J_h3†Q9P7 4£á€ÕÌ›‰[7k,HÚ!rj@FÔˆö\Ù2×;PæB ¡‚Ê\Î Ô|‰ ¢Èu 2T@”¹Æ j´µ¤VM2è#Ppò½1$«íN 5t¯—nÝò>Œ!y4†àyê™ÆÉv5ÐÚt!A)›fá;A;ºU ‚/æ!rCÀÂ^ J³Æób áεLô‘- %w¶ ³Ð€¸µ\”‹ðº §˜C®/hÎâQÁ€ÎDÝÆ À¨ç ”¹ˆö R¯@¢‚W¾ÈERT ¨ ^!?ÄCqÕe¼@«,7cˆà3_u:C„±táþºŒ,BTtFDÉÆ*Qô§#êÂú²ÅVOcHÎÐ.Åä²7T¹²h7†p%ºj uû¦¢×UOuño+˜u+ 1dùZÁ=×,—\ ÏÊï3ç1PïgÖÄU°òC¿ChÖÈØºÆ¿s R:Êb\¨Ë0¼]†Ø]†ºíáyån yH7† hÞ<+hëÆ’ÈÝ’D{®&±«1Ä.Ækô\vä²£‚¹U`Â÷V¯Æ cÈ‹¹ðìÞ+pVð¾WàòÚÑø× 0gD]F˜5ÂèjùÇ‹7š­£c†YƒºŒY,ÙÖчÔªú#T@?f ÷p—‹Ø ËP%š‹„.CCæT~ü˜Ó]¢B¼­fòFüqAeGý¥úø;«Xäª5ä"@Ç\ù‡Exöj«1opXÁk—‹s-—\@=PÑÇ!ùß Ù£»1$—cn]ŠH˜5º€g‡.£lDC—Q’šÊŠ«Æö}&×S.rè2€š&UW ÿc )ŽP_!jGµ¨8Q«Ы1$?ò¤{;û*ªÞr­nuG“´\ü¶žK€ªiŠ ª#×(M)èVPYAäZ[©£ëQïèô^Amhýú÷ïÝ".S¨«XøJMiÖ0óA—Ñѵ§@@éf@-E±5PÙÑJ4Œ!@7¢Ô;±Xãf±Õd ÍD“mƒYƒ¨6ÔH)§“µCÞ¥¬*«j_ÑúÕõM@·=ÐÑÂ\c½-¡1¤·µX« ¢­±‚dërV g®µCôj Ù]F¨ßݱ]—ñj¨5ë ¨jD¿ê2vÔi ±=̵C^2?¸’—Vï↗¨jߘ5Š Æ@U*ÐuDói )蜛1Ä=P!QÁ2T¯Û+Ƚ‚@ßú z«`þ— êwÆ^I)¿áYÁgš1d>Œ!€M¯Æþ ãøÝ8·xGãm‹½ËEÌ7~´Z×eŠ ÂÓb•Ûq¢QÙѶØð…¤êÂ%nõb ±W>Ñmr˯®IW¹si Ù¢g.ý¶‚ÑÒÑѲ¹0ŒŽm騺Ü+Èz7†@>&KÚùÑbƒ.Cx(&Ä”6=ÓuÅ›;Œ!©90€*?mͲйáÕæ Ebòˆ¨u Q tç,¹t ÈÕ¸>j16Zu»¢²(Q!j†Á‰¨KG_ÜY鯠«f[YQnU­çJca *°Ó‚bYAÎáúeD¥ËEÆMqöOgg·Û:…Ñ‘Â?\!Äž='fìH‘P."µW‰»òþïÃþ¾=ã™8$JÏ9M²¼W·™8«ü´¬11¢¾:SËF•TË!а¬q÷\FE§ŽJC13ÑU$w4^}¯TWÏe¬D—^ Ñ@tš m}‰‹°2ïÅ«@­nDÇbÈÙ‹!XüQlCs––¹×bˆ£ñ“¹è¶º‚†Æ£¢}®Šö¾Š¨¶¹ÀƆÎo­'{Êe°–2grªD£ðQ;QC0ªÎíÅŽ ®TZ.ƒÅæ2‹!ªýÅPÏ€Øl†Î…ñ•NˆFGcCkâe}*†”>WQ ŸCÖ¦ ú×AÁÍÐ;Q¿K"Є þ¢ œ‹ Ö]Á¦y®s]ÿúë,*@ç¦à6 j(^)1C´700‘ç2f7aÅI•ŽF¼"ÝÑ™h-†L~ˆQÞÑk.£Ä!—!‚\Æ$†J$ZP›ª™[¯ÖÞl R‰,†ÌSìŽ"²´ ˆx1ÄÛâÅCÐ"ÚÚMD)÷× ã"|1ÃQÁT<€F¥‚ùµ²Lƒ‚$81»‚ÝV‰»p.*Xerzb1äd½I<ï ÅPŠÏ§$Cæœì¢Æ–Žž%yãrc1$š1Óê¨ÐÅsæNz.#êüY\ä€*‹!!?²œGôL4Ê»qÅI‹?8gmè"ñ eÛc›/µ’û\Dãõ¡‚mj ¢ï€ò×µ¹¤)Ø}Ε nMAEa1ä:¡¬qfÛc,†häB°â¦¶!—‘&¢ÌeŒh":)Q1Ôš%æ2OŽÅ”¹ŒRsËyJ†F 3 ÁP0%¥ ¨ºïÅ,Ì„¦(–ÅîÞˆÞô ­"ר@9—g@¼ò¹‚1.Ò }Mé nÌ <.2*¸ŽÅCÏPÀbÈï'AGiöbˆŽÅƒP I=ý4æ2QÉj(—ô€î¹Œˆ¥ ­¹Œ¹‰@=—1–52Qq4߀N@SEÑCYã’R‹‹¤U‰²rÙXì0„˧©ëèeÞ0ü¥¢]A¡æ°Ê?(® Ù MüOo_îÅe¡9_°Í×+®á¹ŒdûÈ‹ú6=J146´CˆÊSYC¹ GÓ¥CD (kô\†.˜TÑY€î¡ñ /kŒÅ©8jæ[1„è9«²E4Ë0×ìs-D±÷MI. AÕÑQæºY1D€º‚-ÆÀ¹„ ÔЭ)ȽÒ$*À‹uG+ÄOÄóuÒ5÷bˆÁþ½È_ Ã¯ÕÙUÿç;Ø­rÝÑ¥du÷Kã_C%®¦ÁÐéÚ2 Sñ\ÆmîŨŸC&!:Cˆ–2‹!KCý5J 5)ÉŒ üÐûGÂcÈ¥¢&蕇Á;ª˜K[1ÄÈ“‚´z1䑚‚tP0)LT4§‰ ØÌï 0RH+Ø¥KSº‚Ž.·±âŽ)æéÜʈ? ËâQyCx*o@££Ê±æ¹à5ï‰q‘äO‡ŧ"‹¿øè9³¬áè#õbH†¤Þi°«н¡Í€}¤T´D 4CC’¯q‘›L‹¡²ŠÔcÓ®Ž ÂSâq‘¬@MŠC$ÔólQ¦˜w“çæ¶*à\Ë QDS ˆ&¢]4ôêÅßX ©¹ Qe«2dS+†,‰½n®uÕ\†òeT Å8ü,«þÒrD™Ëàj7Ëâ¿ "¢lç_Z.c;×bˆÖbÑeGÐ4'¢“–†úƪ?a!^ ){1„¿¨1ã\¹DC”ö›%&yR°ÆZ Y\ÁtP4:šâ¨Àö÷T9 ÎÕã"“ÛjÅßã‰G8î©Cþ»¤æ2¦(K+†ºªz„CÿÀC!k:eCñC.§j/kœã7R‹!I^â"öÑ(†_þÈ=”5"PFg`Aæg4Úå5oJt9÷¸HÆ\@S0ô<%ÌM´+À\+䛡TÒS4¥äúÍìî ¤n6©RAè[ˆb%> .b úÆÆ3,/ Ÿ·91—1”5’¡ê¹ŒÌ03 <ˆÍ‹!*RËDÅQ“‰ú!ÙsZËG[.#ò«KhÊ2¢8Ò8`ÿ¸Cp®ŒÅ¢ ˆ?~a1伬2CV ë\K¾li•eJól¨q-:ª½’’PÁJ=šÒæRW5|¢à  Ô<âõ0WLP\ÁLc1¤F¤e»'Åàqñ²FªÅ¼·²†L‘e OÖÜ èk.ƒßmês~¨\)üh̆F¢N\+*9M\9ö²†oP¯šø7¢ ®‰D{$”èbèšèD€q‘‰(ßë\‹û: èÍè® çjÒ£x\„hWPº‚>—ÎMÁM‰rg¹ZžlÕbH-kpdì* ÝÒ„[‹á9—T’T4ÆTzYC¦Ž²?sA[Íњˈ†²RUßk$«ê?½!$î{1$Jlh2}8ÿa(줡t(†¬Ø–PR‹ŒÅ•w¿(g*)ã\»‚…¨ºñ6*Ѓu‹Š!PÄwα£Pð ”>W¬¶0WLÛ܃¥ÔŠ!0"zÖ˜°‚‡y¼"5¡-.R “([ËeØ  U \{ÌÊ'b¢ÐZÖX+ V$´\FŠŽÆ¨†ÚYå+ºŽÅ¹C–$P™…»ÚД Ðlh‰‹C$Î7ŸKžã":( ê "P°:(HTÀ¹¼²ÇEÖnKãP i Š6ŸCnë¥CJÏeÔêžhF1dÁFÆVÖ€squ´CBäÕw”ÅšчúÑ65—t˽¬ÑŠ!¦ZfŽôëghôn~Ë€ŒÅ¹™çЋ!¸ÙtKY7QC“¡ æÊ^vÛ°":‰Œs)ô¹‘è¹^ðçÅ®ÀmÅÁ–‘si 8WnsÕ®s…V ùc±±y|Ø\ë»·–˘øEÏ€Š!1‚:O8„=s",†ä—bÈ£¢ç ÓƒŠº9вìŬ³jàÕPŠ!+3¼¢^ )Ëõ¸9—jE{1ä˜YZ1„è¨ >¡ùU–³•%_š‚… ¦]ÁDtTP£)§W'í5—qWO/¤i*Y ÄÏe°YÉbˆ]Èe¤!—!šÌpðÆ%ãÿêh Ê ÈÄ?Žî¹Œ[´“D§c1$g ­â_^K/†‹¡ÅÑ ÇbHŒÕÉž‰Ã\‡3V‰(£)#z— ؂ϋ!²ædÄ®`mhð¹z_Å7vW0GÌU{ñʲ†Š!vÅÖB¶[Z½òÔ˯ŦaËÑÏ‹!3Šº9ø2þ¶ç2$ e’ƒ vdÓS1$íÅ,½¢§‰Û_¦t,†¬¸uÎ%þRG»‚ ]Á#Úƒú‡?=‘îÿª`†‚ì ˆÄ'WWóªës1DX ¹Œ.GÖ_JRË*,†D­‡ŠCPÏeTT¦¢DÑ»ÀðsEãs.cc1Dk÷c¾ L7ßÅ©¢sEhÜ¢®^ MeŽ4CdjÅ’€f¸¢%Z::ɲÏÅ{é×5Úó&Uçê訠Å T°úÆ6«+˜£RÁ ô `uQ›Éɉ¨èè‚ ‹!C.ã¾70˜­™÷_¯:«70޹ mq½e%jL¬h$2–R‰úÂOÈù¾øRô¡Rj1$åO,¹NªÉQM zˆ PÍ †Î"õg–XèÜŠ!@ƒH¤‚+Qí  z eƒ‚è â“¢i@:*ÀÊÿšµÎ•$ï(‹!ÅPA1ä Cð!ÝPJJLð®0Å)êËP|ͬ;ªY܉¸;Ïõ÷ÆéFt(†„ û­B/R ŒÅØ‹!@¹/†,@/޲ˆjK*Ž&Ü*¬_þEÁB@©à2*(;ÊbHí³x¡5Ï]÷Uî¹ Kdè2ÚZâ–+J^ y ‰_ásÞ šz.ƒƒÂË|™»¶¸ˆj”åµ’ö\Æ^ É›¡µ‚{¼•¡RžË¶×3×C1d1;[/kÕC1„hJ”mu¤ÆE|.¢c1DÚ\]ÁÒ,Ó® ¥Pçê z1dT°¦Ô‹!*X>Câ¡Ò˜­Óo,†ð!õ;KÔ±§–ËÀ¬S-kp·Š‹æ„²ÊX ºnI® ]gƒ*D×B´-Ð^£ ;ZQ/†¨'ÁGk1Ä#M³ÕÔ3 ¡¡“ªl{Jã#ã"J”sÅ}.åEWt© «¥¢Å‹!±e@ˆJGk_…O¾mX"ë ü÷¢ì¶R/†ä¡r þTjý*¢H4IHó^ Ѹô\F‹Ü(j64øÍ9zßsWÙs¸00—a¸£` •^ )™U‚äUY yl;:ºíÅGYFMÅPh2tÏ€hË€p®çÂP/è"º•ŽBAP)k¦­ °×*TP¢ÔhJ³ÅOànK–T%ø"Ô® „ÛAÞ •u/†à®ƒbÈéw;™¤•5VÏ€„ìw™žŠ!bË䥯Ez1$ÕbHl ¢ç©–5”è–fq”»å^ q4 q‘„ø»£­¢Y_‹!M@WĦc1¤¡·ÙÐí¶CÚ\Ü÷2R‹!\xJ˜‹¨¬C1wØBú¤à¶+PG="£%ŠhJλ+Ð'+‹!¿ ¹Œâ-šV ®Ì²,åïòc/†¨¦V I^ !:æ2õbHCo ý·bȽ£ø‘zºµbHCg%™fîÿV›a#¼uC¹¾r|&Ê4çÂzÿÝÑ×bˆ¸‚­+X]>)X¡€s­Ã\@ÅÞz_¥)í¶Ž ¢)8ýù ‹!8;±ß[Û½¬Ñ¶¹c.CÐ 4‰£bhy-†0.R3 øæµ—5‚¡›IîÅÆEZDöbH’²—5bö »Ä ÕU¢3jh(æÂÒËÍØdñ;_|ÊEÎW­*3>Q· Ñ® ™ÖTÐl ˆÎyT òT Iµ’ƲFʵ"’e/k¬žË€Š”+Iéµ4šÍD™ËèhºVÔ¤´bÈÆ#S“¡âÅ¢š=>ËèŒCÆÝÑ4õ¹¼’^‹!‹Q% ŸÊj(`®ËQAl ü¹‚¹*xØÆ>)ȃ­ îDo¯ ¦ƒ‚»¯¬…Œj$1—ë_æµC¤æ2æ´£7$²Ò!—”Å¢­2«ÝØ€â®ÃbHìÅGo³ù04‹!qJÒÊ‘«@™I@U2:Ç­bhº±vôb½èŠzÄ|Ú\ÚŠ!:¯âèAÂ'È‹‚TÑQA®Åa1äá bS°î¨ýTÁü°=ا­œ‚\OWÙÂõ6\~;7ˆØÂé|=Ù[W»ÔÎ 8eèèÉ®øøã±BÐÍPÙº-@ÃÉ®’‰n9yF%ø©Óµ*èe¢å|Æ…²ìß­ˆA@å*¶y'9]·_ Cm«*Š›j›·ðïm3ät¿b.¢ÜXPœ«¡T° :ZlÏ €ºÚ¢>WÙNŽÞ·“+kG7W꺸-ÛSðñcøé»·÷÷÷·7ûçÏ7~üçûŸ¿½ØïïþþçŸÚù8Ã.Ç»½ èÛ‡q@?Þˆ¾9Š·wàvÎÑ·ßþx@ÁØmåÍòïß;úôÏŽ¶wnÿûï ôhߨWtœ lE¿¿%K´Í5¢o]É6×ûë\ï®ÀP²¥dcúþÍOáçŸ~üaxûþûï¿ýêk{ÿú«oíÍN}ûíW_ÙÉo¿ýú[\„7œó/7 gá$P\èW@ù±qdý4n–(¯jï@¿÷[5ŒdCyŽo@E¿¶S;¢ßVÔÞ1Â?¢öçr´ÎE”;Î…“Žþ·£ˆö¹^PœÚÅâý{{??þôó߿ŠIU¬ýTIEND®B`‚qbs-src-3.3.1/doc/qbs.qdoc0000644000175100017510000025240015232633614014710 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ // ********************************************************************** // NOTE: the sections are not ordered by their logical order to avoid // reshuffling the file each time the index order changes (i.e., often). // Run the fixnavi.pl script to adjust the links to the index order. // ********************************************************************** /*! \page index.html \nextpage overview.html \title Qbs Manual \section1 Version \qbsversion \QBS is a tool that helps simplify the build process for developing projects across multiple platforms. \QBS can be used for any software project, regardless of programming language, toolkit, or libraries used. \note Please report bugs and suggestions to the \l{http://bugreports.qt.io/}{Qt Bug Tracker}. \list \li \l{Introduction} \li \l{Setup} \list \li \l{Installing} \li \l{Configuring Profiles and Preferences} \li \l{Managing Qt Versions} \endlist \li \l{Usage} \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Target Platforms} \li \l{Using the Shell} \li \l{Generators} \li \l{Multiplexing} \li \l{Custom Modules and Items} \li \l{Special Property Values} \li \l{Module Providers} \endlist \li \l{Tutorial} \list \li \l{tutorial-1.html}{Console Application} \li \l{tutorial-2.html}{Static Library} \li \l{tutorial-3.html}{Dynamic Library} \li \l{tutorial-4.html}{Convenience Items} \li \l{tutorial-5.html}{Autotest} \li \l{tutorial-6.html}{Project Properties} \li \l{tutorial-7.html}{Buildconfig Module} \li \l{tutorial-8.html}{Configurable Library} \li \l{tutorial-9.html}{Version Header} \li \l{tutorial-10.html}{C++20 Modules} \endlist \li \l{How-tos} \li \l{Reference} \list \li \l{List of All Items} \list \li \l{List of Language Items} \li \l{List of Convenience Items} \li \l{List of Probes} \endlist \li \l{List of Built-in Services} \li \l{Command-Line Interface} \li \l{List of Modules} \li \l{List of Module Providers} \li \l{Command and JavaScriptCommand} \endlist \li \l{Appendix A: Building Qbs} \li \l{Appendix B: Migrating from Other Build Systems} \li \l{Appendix C: The JSON API} \li \l{Appendix D: Licenses and Code Attributions} \endlist */ /*! \previouspage index.html \page overview.html \nextpage setup.html \title Introduction \QBS is a build automation tool designed to conveniently manage the build process of software projects across multiple platforms. \section1 Features \QBS provides the following benefits: \list \li Declarative paradigm \li Well-defined language \li Platform and programming language independence \li Correct and fast incremental builds \li Extensible architecture \li Easy integration to IDEs \endlist \section2 Declarative Paradigm When writing a project, it is important to describe the build tasks and dependencies between them, rather than the build order. It is difficult to determine the correct build order in complex projects, especially during parallel builds. The build tool should bear that burden, not the developer. With a declarative language, \QBS enables you to express intent rather than specifying single build steps. This provides the appropriate level of abstraction for a build system. For example, \e dependencies can be created between \e products, such that the target \e artifacts of the dependency can be used as input to the build \e rules in the context of the depending product. In addition, you can \e export dependencies and \e properties to other products. \QBS is modular with clean interfaces between modules. A \e module is a collection of properties and \e {language items} that are used for building a product if the product depends on the module. The properties that can be set for a module are used to control the behavior of the toolchain used to build the module. \QBS itself knows nothing about file types or extensions, and therefore all source files in a product are handled equally. However, you can assign \e {file tags} to an artifact to act as markers or to specify a file type. \QBS applies a rule to the source files of the project and chooses the ones that match the input file tags specified by the rule. It then creates artifacts in the build graph that have other filenames and file tags. Products and projects can contain \e probes that are run prior to building, for instance to locate dependent headers, libraries, and other files outside the project directory. \section2 Well-Defined Language \QBS projects are specified in a QML dialect. QML is a concise, easy to learn, and intuitive language that is used successfully in the Qt project. Its core is declarative, but it can be extended with JavaScript snippets for extra flexibility. \QBS builds applications based on the information in a project file. Each project file specifies one \l{Project}{project} that can contain several \l{Product}{products}. You specify the type of the product, such as an \e application, and the dependencies the product has on other products. The product type determines the set of \l{Rule}{rules} that \QBS applies to produce artifacts from input files. The input files can be divided into \l{Group}{groups} according to their type or purpose, for example. A group can also be used to attach \l{Properties}{properties} to products. The following is an example of a minimal project file that specifies the product type, application name, source file, and a dependency on the \l{cpp} module: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } } \endcode For more information, see \l{Language Introduction}. \section2 Platform and Programming Language Independence \QBS can be used for any software project, regardless of programming language, toolkit, or libraries used. \QBS has built-in support for building applications for Windows, Linux, macOS, Android, iOS, tvOS, watchOS, QNX, and FreeBSD, as well as for cross-compilation. It can be easily extended to support further platforms. Invoking \l{build}{qbs build} from the command line automatically builds the project for the current host platform using the best available toolchain and settings, unless a default profile is set. You can configure additional profiles for each toolchain you want to use and select the profile to use at build time. For example, to build applications for Android devices, you would need to set up a profile for the Android toolchain and select it when you build the application. If you name the profile \e Android, you would then enter the following command: \code qbs build profile:Android \endcode For more information, see \l{Building Applications}. Platform and programming language support is implemented as a set of \l{List of Modules}{modules} that your product depends on. In the language example above, the dependency on the \l{cpp} module determines that the C++ sources are compiled and linked into a binary. Alternatively, you could use the \l{CppApplication} convenience item that implies a dependency on the \l{cpp} module: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode Additionally, if the sources use Qt, you need a dependency to the \l{Qt.core} module, and so on. In addition to building projects, \QBS can install the build artifacts to a location from where they can be run on the desktop or on a device. \QBS modules can be used to create installers for the end users of the applications. For example, the \l{dmg} module contains properties and rules for building Apple Disk Images, which are typically used to distribute applications and installers on macOS. The \l{innosetup}, \l{nsis}, and \l{wix} modules contain properties and rules for building installers for Windows platforms. \section2 Correct and Fast Incremental Builds \QBS is an all-in-one tool that generates a build graph from a high-level project description (like qmake or CMake) and additionally undertakes the task of executing the commands in the low-level build graph (like make). \QBS automatically takes advantage of multi-processor and multi-core systems to achieve maximum build parallelization. By default, running \c qbs without any arguments is roughly equivalent to running \c {make -j} where \c n is the number of CPU cores. Similarly, \QBS allows the number of concurrent jobs to be explicitly specified using its own \c -j option. \QBS has knowledge about the whole project, and therefore builds remain correct even when you build sub-projects, because \QBS ensures that all dependencies are built too. This virtually eliminates the need for clean builds. \QBS uses dynamic build graphs with build rules that can generate a variable number of files and that are executed only when needed. When figuring out which rules to execute, \QBS starts at the product type and then looks for a way to produce artifacts with matching file tags from source files, using a chain of rules that are connected by their respective input and output tags. For an example of how rules are applied when building products, see \l{Rules and Product Types}. The \QBS build rules can produce a variable number of outputs. If the input changes, only the required rules are applied at build time. If a rule is applied, all the dependent rules are applied as well, but only those. This feature ensures the correctness of the build graph after source code changes without having to re-configure the whole project. Changing properties that do not affect the build, because they are not used by rules, will not cause the project to be rebuilt. The use of properties is tracked. Generated artifacts that cease to exist are deleted to avoid picking outdated generated artifacts and indefinitely increasing the size of the build directory. Fast incremental builds are crucial for a fast edit-build-run cycle. Instead of retrieving the timestamps of generated files, \QBS uses the time stamps stored in the build graph. This is especially important on Windows, where file system operations are slow. If the project files were not changed, the build graph is loaded from disk. It is stored in a binary format that can be loaded much faster than the real project files. The project files are parsed only if they were changed. \section2 Extensible Architecture You can create your own custom \l{List of Modules}{modules} and \l{List of Language Items}{items} and make \QBS aware of them. You store the custom modules and items in a subdirectory of the project directory and specify the path to the subdirectory as a value of the \l{Project::}{qbsSearchPaths} property. For example, if the custom module is located at \c my-modules/modules/modulename/modulename.qbs, you would specify it in the project file as follows: \code Project { qbsSearchPaths: "my-modules" \endcode For more information, see \l{Custom Modules and Items}. \section2 IDE Integration \QBS can be used not only from the command line, but also in combination with an IDE, such as Qt Creator or Visual Studio Code. These IDEs directly support \QBS projects using the new \QBS \l{session} feature. Thus, these IDEs can retrieve all the information required to build a single file or project through a session's JSON protocol \l{Appendix C: The JSON API}{API}. In addition, \QBS can generate projects for Visual Studio, IAR EW, and Keil uVision, but it still is an experimental option. For more information, see \l {Generators}. \section3 Qt Creator \l{http://doc.qt.io/qtcreator/index.html}{Qt Creator} provides accurate information about the build progress and displays a project tree that reflects the logical structure of the project, instead of presenting low-level information, such as the file system structure. Adding or removing source files keeps the existing project file structure intact. For more information about using \QBS to build projects from Qt Creator, see \l{http://doc.qt.io/qtcreator/creator-project-qbs.html}{Setting Up Qbs}. \section3 Visual Studio Code \l{https://code.visualstudio.com/}{Visual Studio Code} provides the \l{https://marketplace.visualstudio.com/items?itemName=qbs-community.qbs-tools} {qbs-community} plugin that provides accurate information about the build progress and displays a project tree that reflects the logical structure of the project. Also, it can provide low-level information, such as the file system structure. For more information about using \QBS to build projects from Visual Studio Code, see \l{https://github.com/denis-shienkov/vscode-qbs/blob/master/docs/how-to.md} {How To}. \section1 Build Process \image qbs-build-process.png The build process of a product starts by examining the \l{Product::}{type} property of the product. It contains a list of \e {file tags} that are similar to MIME types. The following example product contains one file tag, \e application: \code Product { Depends { name: "cpp" } type: ["application"] files: ["main.cpp", "class.cpp", "class.h"] } \endcode \QBS then searches through all \e rules available in the context, meaning rules that are defined in the project or those that are made available through the dependency on a module, such as the compiler and linker rules pulled in from the \c cpp dependency in the example. When \QBS finds a rule that produces one or more artifacts with the relevant file tag, it looks at the depencencies of that rule and finds out that it produces artifacts tagged \c obj. It then finds a rule that produces \c obj artifacts that takes \c .cpp artifacts as input. \code Module { // ... Rule { inputs: ["cpp"] Artifact { filePath: input.fileName + ".o" fileTags: ["obj"] } prepare: { // g++ -c main.cpp -o main.o ... } } //... } \endcode There is no rule in the current context that produces \c .cpp files, but we have defined \c .cpp files as inputs for the product. When we added a dependency on the \l{cpp} module, that dependency also pulled in another \QBS primitive called the \l{FileTagger}{file tagger}. The file tagger looked for files matching the pattern \c *.cpp, and then applied the \c cpp tag to those input files: \code Module { // ... FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } //... } \endcode Since the \c .cpp files are input files, they by definition have no other dependencies, and we can go back the opposite way in the tree starting with the compiler rule described above. This design works well for generated files. The \c .cpp artifacts could come from another rule that produced them by processing some other input, either instead of or in addition to the raw files listed in the product. The compiler rule will be invoked twice, once for each \c .cpp file, producing a separate object file for each one. Then the linker rule will be invoked. Its \c multiplex property is set to \c true, which means that instead of producing one output per input and invoking the rule multiple times, all input will be collected before invoking the rule only once to produce the final application object. The standard versus multiplex rules map well to the compiler and linker processes. The compiler takes one input file to produce one output file, whereas the linker takes multiple input files to produce one output file. Finally, after the linker rule has been invoked, it produces an artifact tagged \c application. Because the product's type property did not contain other file tags, the build process is now complete. */ /*! \previouspage overview.html \page setup.html \nextpage installing.html \title Setup \list \li \l{Installing} \li \l{Configuring Profiles and Preferences} \li \l{Managing Qt Versions} \endlist */ /*! \previouspage reference.html \page building-qbs.html \nextpage porting-to-qbs.html \title Appendix A: Building Qbs \QBS can be \l{Installing}{installed from binary packages} or built from sources, as described in this appendix. In addition, this appendix describes how to use Docker images for developing \QBS. \section1 Supported Platforms \QBS can be installed and run on the following platforms: \list \li Windows 7, or later \li Linux (tested on Debian 8 and 9, Ubuntu 16.04, OpenSuSE 13.2, and Arch Linux) \li macOS 10.7, or later \endlist \section1 System Requirements To build \QBS from the source, you need: \list \li Qt 5.15, or later \li Windows: MinGW with GCC 4.9 or Microsoft Visual Studio 2015, or later \li Linux: GCC 4.9, or later, or Clang 3.9.0, or later \li macOS: Xcode 6.2, or later \endlist An installed toolchain has to match the one that Qt was compiled with. \section2 Documentation Building the \QBS documentation requires Python 2.7 or 3.2 or above, as well as some third party Python modules. These can be installed via \c pip: \code pip install beautifulsoup4 lxml \endcode Regenerating the man page requires the \c help2man tool. \section1 Building \QBS with СMake To build \QBS, enter the following commands: \code mkdir build && cd build cmake -DQt5_DIR=${QT_DIR}/lib/cmake/Qt5/ .. make \endcode Where \c ${QT_DIR} is the directory where Qt is installed. Passing the \c Qt5_DIR option is not necessary if \c qmake is present in \c PATH. Depending on your platform, you might use \c mingw32-make, \c nmake, or \c jom instead of \c make. Alternatively, you can use the \l{https://cmake.org/cmake/help/latest/generator/Ninja.html}{Ninja} generator: \code cmake -GNinja -DQt5_DIR=${QT_DIR}/lib/cmake/Qt5/ .. ninja \endcode \section2 CMake Configure Options \QBS recognizes the following CMake options (passed to CMake in the form of \c{-DOPTION=value}) to customize the build: \table \header \li Option \li Notes \li Default value \row \li WITH_TESTS \li Enable autotests. \li \c ON \row \li WITH_UNIT_TESTS \li Enable additional autotests. \li \c OFF \li \c OFF \row \li INSTALL_PUBLIC_HEADERS \li Whether to install public headers. \li \c ON \endtable \section2 Using ccache with CMake To enable using \l{https://ccache.dev}{ccache} when building \QBS, pass the following options to CMake: \code cmake -DQt5_DIR=${QT_DIR}/lib/cmake/Qt5/ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. \endcode \section1 Building \QBS with \QBS It is also possible to build \QBS with the previously installed \QBS version. To build \QBS, enter the following command in the source directory: \code qbs \endcode This will use the \c defaultProfile or pick up the Qt version and the toolchain from the \c PATH if the \c defaultProfile is not set. See \l {Configuring Profiles and Preferences} for details about profiles. To run automatic tests, the \c autotest-runner product should be built: \code qbs build -p autotest-runner \endcode \QBS will use an empty profile when running tests which means it will try to autodetect toolchains, Qt versions and other things based on the system environment. It is possible to specify which profile should be used during the test-run by passing the \c QBS_AUTOTEST_PROFILE environment variable. This variable should be set prior to building \QBS itself; otherwise the \c resolve command should be used to update the environment stored in the buildgraph: \code export QBS_AUTOTEST_PROFILE=qt qbs resolve qbs build -p autotest-runner \endcode It is also possible to set up a separate profile for a particular testsuite. A profile for the \c tst_blackbox_android suite can be set up as follows: \code qbs setup-android pie export QBS_AUTOTEST_PROFILE_BLACKBOX_ANDROID=pie \endcode It might be useful to set up the directory with the \QBS settings to isolate the test environment: \code export QBS_AUTOTEST_SETTINGS_DIR=~/path/to/qbs/settings \endcode \section2 \QBS Build Options The \c qbsbuildconfig module can be used to customize the build. Properties of that module can be passed using command line as follows: \code qbs build modules.qbsbuildconfig.enableAddressSanitizer:true \endcode \QBS recognizes the following properties: \table \header \li Property \li Default value \li Notes \row \li enableAddressSanitizer \li \c false \li Whether to use address sanitizer or not. Enabling this option will add the -fsanitize=address flag. \row \li enableUnitTests \li \c false \li Enable additional autotests. Enabling this option will export some symbols that would otherwise be private. \row \li enableRPath \li \c true \li Use this property to disable the use of rpath. This can be used when packaging \QBS for distributions which do not permit the use of rpath, such as Fedora. \row \li installApiHeaders \li \c true \li Holds whether to install the header files for the \QBS libraries or not. This option is required to build against the \QBS libraries. \row \li enableBundledQt \li \c false \li Holds whether the Qt libraries that \QBS depends on will be bundled with \QBS during the \c install step. This option is only implemented on macOS. \row \li libDirName \li \c "lib" \li Directory name used by \c libInstallDir and \c importLibInstallDir properties. \row \li appInstallDir \li \c "bin" \li Relative directory path under the install prefix path to put application binaries. \row \li libInstallDir \li \c "bin" on Windows, \c libDirName otherwise \li Relative directory path under the install prefix path where to put shared libraries (excluding plugins, see the \c relativePluginsPath property). \row \li importLibInstallDir \li \c libDirName \li Relative directory path under the install prefix path where to put import libs. \row \li libexecInstallDir \li \c appInstallDir on Windows, \c "libexec/qbs" otherwise \li Relative directory path under the install prefix path where to put auxiliary binaries executed by the \QBS libraries. \row \li systemSettingsDir \li \c undefined \li Directory that will be used by \QBS to store its settings. If not specified, a default platform-dependent directory is used. \row \li installManPage \li \c true on Unix, \c false otherwise \li Whether to install man pages. \row \li installHtml \li \c true \li Whether to install HTML help pages. \row \li installQch \li \c false \li Whether to install qch files. See \l{https://doc.qt.io/qt-5/qthelp-framework.html}{The Qt Help Framework} for details about qch files. \row \li generatePkgConfigFiles \li auto-detected \li Whether to generate files for pkg-config. \row \li generateQbsModules \li auto-detected \li Whether to generate \QBS modules for the exported \QBS libraries. Use this when building another product against \QBS libraries using \QBS as build system. \row \li docInstallDir \li \c "share/doc/qbs/html" \li Relative directory path under the install prefix path where to put documentation. \row \li pkgConfigInstallDir \li \c libDirName + \c "/pkgconfig" \li Relative directory path under the install prefix path where to put pkg-config files. \row \li qbsModulesBaseDir \li \c libDirName + \c "/qbs/modules" \li Relative directory path under the install prefix path where to put \QBS modules. Applies only when \c generateQbsModules is \c true. \row \li relativeLibexecPath \li \c "../" + \c libexecInstallDir \li Path to the auxiliary binaries relative to the application binary. \row \li relativePluginsPath \li \c "../" + \c libDirName \li Path to plugin libraries relative to the application binary. \row \li relativeSearchPath \li \c ".." \li Relative path to the directory where to look for \QBS development modules and items. \row \li libRPaths \li auto-detected \li List of rpaths. \row \li resourcesInstallDir \li \c "" \li Relative directory path under the install prefix path where to put shared resources like documentation, \QBS user modules and items. \row \li pluginsInstallDir \li \c libDirName + \c "/qbs/plugins" \li Relative path to the directory where to put plugins to. \endtable \section1 Using Docker A set of Docker images for developing \QBS (which are maintained by the \QBS team) is available \l{https://hub.docker.com/u/qbsbuild/}{on Docker Hub}. Both Windows 10 and Debian Linux container types are available. \note The source code for the \QBS development Docker images is located in the \c{docker/} directory of the \QBS source tree, if you wish to build them yourself. \section2 Linux Containers The easiest way to get started is to build \QBS using a Linux container. These types of containers are supported out of the box on all the supported host platforms: Windows, macOS, and Linux. The images provide everything that is necessary to build and test \QBS: \list \li Qt SDK for building \QBS with \c qmake \li Latest stable release of \QBS for building \QBS with \QBS \endlist We are using docker-compose for building and running the Docker images because it simplifies the Docker command line and ensures that the correct image tag is used. All available images are listed in the \c docker-compose.yml file in the project root directory. Run the following command to download the \QBS development image based on Ubuntu 20.04 \e Focal: \code docker-compose pull focal \endcode You can then create a new container with the \QBS source directory mounted from your host machine's file system, by running: \code docker-compose run --rm focal \endcode You will now be in an interactive Linux shell where you can develop and build \QBS. \section2 Windows Containers To build \QBS for Windows using Windows containers, your host OS must be running Windows 10 Pro and have Hyper-V enabled. \l{https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers}{Switch your Docker environment to use Windows containers}. We are using docker-compose for building and running the Docker images because it simplifies the Docker command line and ensures that the correct image tag is used. All available images are listed in the \c docker-compose.yml file in the project root directory. Run the following command to download the \QBS development image based on Windows 10: \code docker-compose pull windows \endcode You can then create a new container with the \QBS source directory mounted from your host machine's file system, by running: \code docker-compose run --rm windows \endcode If you want to use Windows containers on a macOS or Linux host, you will have to create a virtual machine running Windows 10 and register it with \c{docker-machine}. There is at least \l{https://github.com/StefanScherer/windows-docker-machine}{one Open Source project} that helps to facilitate this by using using Packer, Vagrant, and VirtualBox. The \c{docker run} command to spawn a Windows container on a Unix host will look slightly different (assuming \c windows is the name of the Docker machine associated with the Windows container hosting VM): \code eval $(docker-machine env windows) docker-compose run --rm windows \endcode \section2 Building Release Packages Release packages for \QBS for Windows can be built using the following command on Windows: \code docker-compose run --rm windows cmd /c scripts\make-release-archives \endcode For building release packages for Windows on macOS or Linux: \code eval $(docker-machine env windows) docker-compose run --rm windows cmd /c scripts\\make-release-archives \endcode */ /*! \previouspage setup.html \page installing.html \nextpage configuring.html \title Installing \QBS binaries are available for Windows, macOS, Linux, and FreeBSD. On all platforms, \QBS binaries are part of the \l{Qt Creator} and \l{Qt SDK} installers. You can find the \c qbs executable in the \c bin directory of Qt Creator, or within the application bundle's \c MacOS directory on macOS. \QBS can also be built locally from sources. For more information, see \l{Appendix A: Building Qbs}. \section1 Windows The Qt Project provides prebuilt binaries for Windows (x86 and x64) at \l{https://download.qt.io/official_releases/qbs/}. For commercial customers of The Qt Company, the binaries are available in the \l {Qt Account}. The binaries are packaged in a .zip folder that can be extracted to a location of your choice. \QBS is also available as a \l Chocolatey package, which can be installed in the usual way: \code choco install qbs \endcode The \c .nupkg file can also be downloaded directly from \l{https://download.qt.io/official_releases/qbs/} for \l{https://chocolatey.org/security#organizational-use-of-chocolatey}{offline installation}. \section1 macOS \QBS can be conveniently installed on macOS with the \l{MacPorts} or \l{Homebrew} package managers: \code brew install qbs \endcode or \code port install qbs \endcode \section1 Linux and FreeBSD \QBS is \l{https://repology.org/metapackage/qbs/versions}{available via the package management systems} of Linux distributions, and FreeBSD. */ /*! \previouspage installing.html \page configuring.html \nextpage qt-versions.html \title Configuring Profiles and Preferences Profiles contain properties that apply to one or more projects. They are stored independently of the project files and are usually not shared between build hosts. Typically, profiles contain module properties, such as installation paths of tools or libraries on the host computer. This approach has the following advantages, among others: \list \li Team members with different computer setups can work together smoothly because no host-specific settings end up in the project files. \li Different versions of a tool or library can be used to build the same project without affecting each other. \endlist For example, a profile for building C++ applications contains at least the installation path and the type of the compiler toolchain. A profile for building Qt applications contains the toolchain-specific properties as well as \l{Qt::qmakeFilePaths}{the path to the Qt installation}. This topic describes profiles stored in the \QBS settings. In some cases it might be beneficial to keep profiles explicitly in the project sources. This can be achieved with the \l{Profile} item. \section1 Setting Up Toolchain Profiles \QBS comes with a helper tool \l{setup-toolchains} that can create profiles for many toolchains. Open a terminal window and type: \code qbs setup-toolchains --detect \endcode This will automatically set up a profile for each detected toolchain on your computer. You can list the existing profiles by running: \code qbs config --list profiles \endcode Some toolchains, especially for bare-metal targets, may require additional module properties. Those can be added with the \l{config} or the \l{config-ui} tools. Now you should be ready to build your first project with \QBS. Go into examples/helloworld-minimal and type: \code qbs build profile: \endcode You have successfully built your first \QBS project. If you want to build projects that use Qt, additional steps might be necessary. Please refer to \l{Managing Qt Versions} for more information. \section1 Global Preferences In addition to profiles, \QBS provides some global preferences such as \c qbsSearchPaths and \c defaultProfile. \section1 Managing Profiles and Preferences You can use the \l{config} command to manage all \QBS configuration settings, such as profiles and global preferences from the command line, for example: \code qbs config profiles..qbs.architecture arm \endcode For convenience, \QBS provides a tool \l{config-ui} where you can manage the settings in a hierarchical view. \image qbs-settings-gui.png \QBS Settings displays the keys in the specified settings directory and their values. To expand all keys, select \uicontrol View > \uicontrol {Expand All} (\key Ctrl+E or \key Cmd+E on macOS). To collapse all keys, select \uicontrol {Collapse All} (\key Ctrl+C or \key Cmd+C). To change the value of a key, double-click it and enter the new value. To save your changes, select \uicontrol File > \uicontrol Save. To refresh the settings from the settings directory, select \uicontrol File > \uicontrol Reload. */ /*! \previouspage configuring.html \page qt-versions.html \nextpage usage.html \title Managing Qt Versions \section1 Introduction If your environment has the right \c qmake binary in its \c PATH and is also set up properly for a matching toolchain, then you do not necessarily need a profile to build projects with a Qt dependency. Otherwise, you should create one: \code qbs setup-qt /usr/bin/qmake myqt \endcode This will create the \c myqt profile which can then be used on the command line: \code qbs profile:myqt \endcode \note If the \c setup-toolchains command has found more than one toolchain, you will need to manually link your Qt profile to one of them, like this: \code qbs config profiles.myqt.baseProfile \endcode \section1 Multiple Qt Builds To support multiple Qt builds, or in fact any combination of related settings, you need to create several profiles. The following example illustrates how to set up three different profiles, each for a different Qt build: \code qbs setup-qt ~/dev/qt/4.7/bin/qmake qt47 qbs setup-qt ~/dev/qt/4.8/bin/qmake qt48 qbs setup-qt ~/dev/qt/5.0/qtbase/bin/qmake qt5 \endcode You can set the default Qt build like this: \code qbs config defaultProfile qt5 \endcode To choose a Qt build that is different from the default, use: \code qbs build profile:qt48 \endcode You can set other properties in a profile (not just Qt ones), in the same way you override them from the command line. For example: \code qbs setup-qt C:\Qt\5.0.0\qtbase\bin\qmake.exe qt5 qbs config profiles.qt5.qbs.architecture x86_64 qbs config profiles.qt5.baseProfile msvc2010 \endcode The last example uses the inheritance feature of profiles. All settings in the profile set as \c baseProfile are known in the derived profile as well. They can of course be overridden there. */ /*! \previouspage qt-versions.html \page usage.html \nextpage language-introduction.html \title Usage \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Target Platforms} \li \l{Using the Shell} \li \l{Generators} \li \l{Multiplexing} \li \l{Custom Modules and Items} \li \l{Special Property Values} \li \l{Module Providers} \endlist */ /*! \previouspage usage.html \page language-introduction.html \nextpage building-applications.html \title Language Introduction \QBS uses project files (*.qbs) to describe the contents of a project. A project contains one or more \l{Product}{products}. A product is the target of a build process, typically an application, library or maybe a tar ball. \note \QBS source files are assumed to be UTF-8 encoded. \section1 The Obligatory Hello World Example \QBS project files are written using a QML dialect. A very simple C++ hello world project looks like this: \code ---helloworld.qbs--- Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } } \endcode \a Application describes the product we want to build. In this case, an application. This is just a shortcut for writing \code Product { type: "application" // ... } \endcode The \a name is the name of the product. In this case it is also the name of the produced executable (on Windows, the ".exe" extension is added by default). In the property \a files, we specify the source files for our product. Unlike QML, the right-hand side can be either a string or a string list. A single string is converted to a stringlist containing just one element. So we could have also written \code files: [ "main.cpp" ] \endcode \a Depends adds the dependency to the \l{cpp} module. This is necessary to let \QBS know that we have a C++ project and want to compile main.cpp with a C++ compiler. For more information about \QBS modules, see \l{Modules}. \section1 Reusing Project File Code QML-like inheritance works also in \QBS. \code ---CrazyProduct.qbs--- Product { property string craziness: "low" files: [ "Crazy.h", "Crazy.cpp" ] } ---hellocrazyworld.qbs--- import "CrazyProduct.qbs" as CrazyProduct CrazyProduct { craziness: "enormous" name: "hellocrazyworld" files: base.concat(["main.cpp"]) // ... } \endcode You can put JS code into separate \c{.js} files and then import them. \code ---helpers.js--- function planetsCorrectlyAligned() { // implementation } ---myproject.qbs--- import "helpers.js" as Helpers Product { name: "myproject" Group { condition: Helpers.planetsCorrectlyAligned() file: "magic_hack.cpp" } // ... } \endcode See \l {Special Property Values} for more details about the \l base property. \section1 Modules A \e module is a collection of properties and language items that are used for building a product if the product depends on (or loads) the module. For example, the \a cpp module looks like this (simplified): \code Module { name: "cpp" property string warningLevel property string optimization property bool debugInformation property pathList includePaths // ... FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Rule {...} // compiler Rule {...} // application linker Rule {...} // static lib linker Rule {...} // dynamic lib linker } \endcode The properties that can be set for the \a cpp module are used to control the behavior of your C++ toolchain. In addition, you can use FileTaggers and Rules that are explained later. As soon as your product depends on a module, it can set the properties of the module. You specify the optimization level for your product (and all build variants) like this: \code ---helloworld.qbs--- Application { name: "helloworld" files: ["main.cpp"] cpp.optimization: "ludicrousSpeed" Depends { name: "cpp" } } \endcode A module can depend on other modules. For example, the \l{Qt.core} module depends on the \l{cpp} module. The module dependencies are transitive, i.e. in a Product, all dependent modules are accessible: \code Application { name: "helloworld" files: ["main.cpp"] Depends { name: "Qt.core" } // the "cpp" module is available since // "Qt.core" depends on "cpp". cpp.optimization: "ludicrousSpeed" } \endcode \section2 Different Properties for a Single File Not only the product, but all the source files of the product can have their own set of module properties. For example, assume you have some files that are known to crash your compiler if you turn on optimizations. You want to turn off optimizations for just these files and this is how you do it: \code Application { name: "helloworld" files: "main.cpp" Group { files: ["bad_file.cpp", "other_bad_file.cpp"] cpp.optimization: "none" } Depends { name: "cpp" } } \endcode \section2 Selecting Files by Properties Sometimes you have a file that is only going to be compiled on a certain platform. This is how you do it: \code Group { condition: qbs.targetOS.includes("windows") files: [ "harddiskdeleter_win.cpp", "blowupmonitor_win.cpp", "setkeyboardonfire_win.cpp" ] } Group { condition: qbs.targetOS.includes("linux") files: [ "harddiskdeleter_linux.cpp", "blowupmonitor_linux.cpp", "setkeyboardonfire_linux.cpp" ] } \endcode In the above example, \l{qbs::targetOS}{qbs.targetOS} is a property of the target of the the \l{qbs} module. The \c qbs module is always implicitly loaded. Its main properties are: \list \li \l{qbs::}{buildVariant} that specifies the name of the build variant for the current build. \li \l{qbs::}{targetOS} that specifies the operating system you want to build the project for. \endlist You can set these properties on the command line or by using a profile. \code $ qbs # qbs.buildVariant:debug, profile: (or profile:none, if no default profile exists) $ qbs config:release # qbs.buildVariant:release, profile: $ qbs config:debug config:release # builds two configurations of the project $ qbs profile:none # all module properties have their default values \endcode To select files by build variant: \code Group { condition: qbs.buildVariant == "debug" files: "debughelper.cpp" } \endcode To set properties for a build variant: \code Properties { condition: qbs.buildVariant == "debug" cpp.debugInformation: true cpp.optimization: "none" } \endcode Or, to use a more QML-like style: \code cpp.debugInformation: qbs.buildVariant == "debug" ? true : false cpp.optimization: qbs.buildVariant == "debug" ? "none" : "fast" \endcode \section1 Property Types While properties in \QBS generally work the same way as in QML, the set of possible property types has been adapted to reflect the specific needs of a build tool. The supported types are as follows: \table \header \li Property type \li Example \li Description \row \li \c bool \li \c{property bool someBoolean: false} \li The usual boolean values. \row \li \c int \li \c{property int theAnswer: 42} \li Integral numbers. \row \li \c path \li \c{property path aFile: "file.txt"} \li File paths resolved relative to the directory the product they are associated with is located in. \row \li \c pathList \li \c{property pathList twoFiles: ["file1.txt", "./file2.txt"]} \li A list of \c path values. \row \li \c string \li \c{property string parentalAdvisory: "explicit lyrics"} \li JavaScript strings. \row \li \c stringList \li \c{property stringList realWorldExample: ["no", "not really"]} \li A list of JavaScript strings. \row \li \c var \li \c{property var aMap: ({ key1: "value1", key2: "value2" })} \li Generic data, as in QML. \row \li \c varList \li \c{property var aMapList: [{ key1: "value1", key2: "value2" }, { key1: "value3" }]} \li A list of generic data, typically JavaScript objects. \endtable \section1 Overriding Property Values from the Command Line Property values set in project files or profiles can be overridden on the command line. The syntax is \c{.:}. The following command lines demonstrate how to set different kinds of properties: \code $ qbs projects.someProject.projectProperty:false # set a property of a project $ qbs products.someProduct.productProperty:false # set a property of a product $ qbs modules.cpp.treatWarningsAsErrors:true # set a module property for all products $ qbs products.someProduct.cpp.treatWarningsAsErrors:true # set a module property for one product \endcode Property values on the command line can also be expressed in JavaScript form, the same way as you would write them in a project file. Make sure to take care of proper quoting, so that the shell does not interpret any of the values itself. Properties of type \c stringList can also be provided as comma-separated values, if none of the strings contain special characters: \code $ qbs projects.someProject.listProp:'["a", "b", "c"]' $ qbs projects.someProject.listProp:a,b,c # same as above $ qbs projects.someProject.listProp:'["a b", "c"]' # no CSV equivalent \endcode \section1 File Tags and Taggers \QBS itself knows nothing about C++ files or file extensions. All source files in a product are handled equally. However, you can assign \a{file tags} to an artifact to act as a marker or to specify a file type. An artifact can have multiple file tags. For example, you can use the \a Group item to group files with the same file tags (or a set of properties). \code Product { Group { files: ["file1.cpp", "file2.cpp"] fileTags: ["cpp"] } Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode When you load the \a cpp module, you also load the following item: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode This construct means that each source file that matches the pattern \c{*.cpp} (and has not explicitly set a file tag) gets the file tag \c{cpp}. The above example can be simplified to \code Product { Depends: "cpp" files: ["file1.cpp", "file2.cpp"] Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode The \a FileTagger from the \a cpp module automatically assigns the \c cpp file tag to the source files. Groups that just contain the \a files property can be more simply expressed by using the \a files property of the product. File tags are used by \a rules to transform one type of artifact into another. For instance, the C++ compiler rule transforms artifacts with the file tag \c cpp to artifacts with the file tag \c{obj}. In addition, it is possible to use file taggers to tag files and specify custom file tags: \code Product { Depends: "cpp" Group { overrideTags: false // The overrideTags property defaults to true. fileTags: ["foobar"] files: ["main.cpp"] // Gets the file tag "cpp" through a FileTagger item and // "foobar" from this group's fileTags property. } // ... } \endcode \section1 Rules \QBS applies a \e rule to a pool of artifacts (in the beginning it is just the set of source files of the project) and chooses the ones that match the input file tags specified by the rule. Then it creates output artifacts in the build graph that have other filenames and file tags. It also creates a script that transforms the input artifacts into the output artifacts. Artifacts created by one rule can (and typically do) serve as inputs to another rule. In this way, rules are connected to one another via their input and output file tags. For examples of rules, see the share/qbs/modules directory in the \QBS repository. You can define rules in your own module to be provided along with your project. Or you can put a rule directly into your project file. For more information, see \l{Rule}. */ /*! \previouspage language-introduction.html \page building-applications.html \nextpage running-applications.html \title Building Applications This section assumes that \QBS is present in \c PATH. For the details how to install \QBS, see the \l{Installing} page. To build applications from the command line, enter the following commands: \code cd examples/collidingmice qbs \endcode By default, \QBS uses all the CPU cores available to achieve maximum build parallelization. To explicitly specify the number of concurrent jobs, use the \c -j option. For example, to run 4 concurrent jobs, enter the following command: \code qbs -j4 \endcode The application is built using the default build profile that is set up in your \QBS configuration. You can use the \l{config} command to set the max number of jobs per profile. For example, to set four jobs as the default option for a profile named \e Android, enter the following command: \code qbs config profiles.Android.preferences.jobs 4 \endcode To build with other profiles than the default one, specify options for the \l{build} command. For example, to build debug and release configurations with the \e Android profile, enter the following command: \code qbs build profile:Android config:debug config:release \endcode The position of the property assignment is important. In the example above, the profile property is set for all build configurations that come afterwards. To set a property just for one build configuration, place the assignment after the build configuration name. In the following example, the property \l{cpp::treatWarningsAsErrors} {cpp.treatWarningsAsErrors} is set to \c true for debug only and \l{cpp::optimization}{cpp.optimization} is set to \c small for release only. \code qbs build config:debug modules.cpp.treatWarningsAsErrors:true config:release modules.cpp.optimization:small \endcode Projects are built in the debug build configuration by default. */ /*! \previouspage running-applications.html \page installing-files.html \nextpage {Target Platforms} \title Installing Files To install your project, specify the necessary information in the project file: \code Application { Group { name: "Icons" files: "*.png" qbs.install: true qbs.installDir: "share/icons/myproject" } Group { name: "Docs" fileTagsFilter: "generated_docs" qbs.install: true qbs.installDir: "share/man/man7" } } \endcode In this example, we want to install some \c{.png} files and documentation built by the project. The Application is installed automatically unless the \l{Application::install}{install} property is set to \c false. When building, \QBS installs artifacts into the default root folder, namely \c{/install-root}. The \l{qbs::installPrefix}{qbs.installPrefix} and \l{qbs::installDir}{qbs.installDir} properties are appended to the root folder. \code qbs build qbs.installPrefix:/usr \endcode In this example, the executable will be installed into the \c{/install-root/usr/bin} folder and the QML files will be installed into the \c{/install-root/usr/share/myproject} folder. To skip installation during the build, use the \c --no-install option. To override the default location, use the \c --install-root option of the \c{qbs install} command: \code qbs build --no-install qbs.installPrefix:/usr sudo qbs install --no-build --install-root / \endcode In this example, artifacts will be installed directly into the \c /usr folder. Since the \c{qbs install} command implies \c build, we use the \c --no-build parameter to ensure that we do not accidentally rebuild the project, thereby changing the artifacts' owner to \c root. Sometimes, it makes sense to install the application into a temporary root folder, keeping the same folder structure within that root folder as in the examples above; for instance, when building a Linux package such as \c deb or \c rmp. To install the application into the \c /tmp/myProjectRoot folder, use the following command: \code $ qbs install --install-root /tmp/myProjectRoot \endcode In this example, the executable will be installed into the \c{/tmp/myProjectRoot/usr/bin} folder and QML files will be installed into the \c{/tmp/myProjectRoot/usr/share/myproject} folder. To remove all files from the install root prior to installing, use the \c --clean-install-root parameter: \code qbs install --clean-install-root --install-root /tmp/myProjectRoot \endcode For more information about how the installation path is constructed, see \l {Installation Properties}. */ /*! \previouspage building-applications.html \page running-applications.html \nextpage installing-files.html \title Running Applications Qbs has the convenience \l{run}{qbs run} command that simplifies running applications. For example, entering the following command runs the Qt Creator application: \code qbs run --products qtcreator \endcode By default, running an application also builds it and installs it to a location from where it can be run on the desktop or on a device. Also, this command \l{Module::setupRunEnvironment}{sets up} the environment so that the application can find dependent libraries. This is not the case when running the binary manually - you'll have to make sure that the app will find its dependencies and/or is relocatable. You can achieve that by \l{How do I make use of rpaths?}{configuring rpaths} properly or setting the appropriate environment variable for the respective host system. */ /*! \previouspage {Target Platforms} \page shell.html \nextpage generators.html \title Using the Shell To use the \QBS shell, enter the following command: \code qbs shell \endcode This is mainly a debugging tool. It opens a shell with the same environment that \QBS uses when building the project, so you can, for example, inspect which environment variables will be set up. */ /*! \previouspage multiplexing.html \page custom-modules.html \nextpage special-property-values.html \title Custom Modules and Items Users of \QBS are not limited to the pre-defined \l{List of Modules}{modules} and \l{List of Language Items}{items}, they can also create their own. Here we describe how to set up custom modules and items so that \QBS will find them. \section1 File System Layout Items and modules are located under a common base directory, whose name and location is completely arbitrary. We will refer to it as \c search-path here. This directory has two subdirectories \c modules and \c imports, which contain \QBS modules and items, respectively. \section1 Custom Modules To introduce a custom module \c mymodule, create a directory \c{search-path/modules/mymodule/}. \note Module names are case-sensitive, and this also goes for the corresponding directory name. Then, put a file containing an instance of the \l{Module} in there and give it the \c{.qbs} extension. This module will be pulled in if a \l{Product}{product} declares a \l{Depends}{dependency} on \c mymodule. \section1 Custom Items To introduce a custom item \c MyItem, create the file \c{search-path/imports/MyItem.qbs}. \note Item file names must start with a capital letter due to the fact that type names can only start with a capital letter. Otherwise, the file will be silently ignored. \section1 Making \QBS Aware of Custom Modules and Items To be able to use your custom modules and items, you need to make them known to \QBS. You can do this per project or globally. \section2 Project-specific Modules and Items Let's assume you have a project that is located in \c{project_dir} and you have created some modules in \c{project_dir/custom-stuff/modules/} as well as some items in \c{project_dir/custom-stuff/imports/} that you want to use in the project. To achieve this, your top-level project file should look like this: \code // ... Project { // .. qbsSearchPaths: "custom-stuff" // .. } \endcode \note For technical reasons, the custom modules and items will not be available in the file that contains the \l{Project::qbsSearchPaths} {Project.qbsSearchPaths} property. Any product that wants to make use of them needs to be in a different file that is pulled in via the \l{Project::references}{Project.references} property, for example. This is not a serious limitation, since every well-structured project will be split up in this manner. \section2 Making Custom Modules and Items Available Across Projects What if your modules and items are generally useful and you want to access them in several projects? In this case, it is best to add the location to your preferences. For example: \code qbs config preferences.qbsSearchPaths /usr/local/share/custom-qbs-extensions \endcode */ /*! \previouspage custom-modules.html \page special-property-values.html \nextpage module-providers.html \title Special Property Values Depending on the context, \QBS provides the following special values for use in property bindings and JavaScript code: \list \li \l base \li \l exportingProduct \li \l filePath \li \l importingProduct \li \l module \li \l original \li \l outer \li \l path \li \l product \li \l project \endlist \section2 \c base This value is useful when making use of inheritance. It stands for the value of the respective property in the item one level up in the inheritance chain. For instance: \code Product { // defined in MyProduct.qbs Depends { name: "mymodule" } mymodule.someProperty: ["value1"] } ------ some other file ------ MyProduct { mymodule.someProperty: base.concat(["value2"]) // => ["value1", "value2"] } \endcode \section2 \c exportingProduct Within an \l Export item, you can use the \c exportingProduct variable to refer to the product which defines the Export item: \code Product { Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.sourceDirectory } } \endcode \section2 \c filePath This value holds the full file path to the \c .qbs file it appears in. This property is rarely used, but might be useful when debugging: \code Product { property bool dummy: { console.info("I'm located at " + filePath); } } \endcode \section2 \c importingProduct Within an \l Export item, you can use the \c importingProduct variable to refer to the product that pulls in the resulting module: \code Product { Export { Depends { name: "cpp" } cpp.includePaths: importingProduct.buildDirectory } } \endcode Usually, you should use the \l product variable instead for consistency with \l Module items. \section2 \c module This value holds the properties of the module that contains the current item: \code Module { property bool enableGroup property bool enableRule Group { condition: enableGroup // available without qualification because Module is a direct parent item Rule { condition: module.enableRule // Shortcut for product..enableRule // ... } } } \endcode \section2 \c original On the right-hand side of a module property binding, this refers to the value of the property in the module itself (possibly overridden from a profile). Use it to set a module property conditionally: \code Module { // This is mymodule property string aProperty: "z" } ---------- Product { Depends { name: "mymodule" } Depends { name: "myothermodule" } // "y" if myothermodule.anotherProperty is "x", "z" otherwise: mymodule.aProperty: myothermodule.anotherProperty === "x" ? "y" : original } \endcode \note In all but the most exotic cases, a \l{Properties} item is the preferred way to achieve the same result: \code Product { Depends { name: "mymodule" } Depends { name: "myothermodule" } Properties { condition: myothermodule.anotherProperty === "x" mymodule.aProperty: "y" } \endcode \section2 \c outer This value is used in nested items, where it refers to the value of the respective property in the surrounding item. It is only valid in \l{Group} and \l{Properties} items: \code Product { Depends { name: "mymodule" } mymodule.someProperty: ["value1"] Group { name: "special files" files: ["somefile1", "somefile2"] mymodule.someProperty: outer.concat(["value"]) // => ["value1", "value2"] } } \endcode \section2 \c path This value holds the path to the folder where the \c .qbs file is located. Use it to e.g. add the product's directory to file paths: \code Product { Depends { name: "cpp" } cpp.includePaths: path } \endcode \section2 \c product This value holds the properties of the product that contains the current item or pulls in the current module: \code Module { Rule { Artifact { fileTags: product.type filePath: { var result = input.fileName; // module properties are available as well if (product.qbs.buildVariant === "debug") result = result + "_debug"; result = result + ".out"; return result; } } } } \endcode Within the \l Export item, same as \l importingProduct. \section2 \c project This value holds the properties of the project that references the current item or pulls in the current module: \code Project { property bool enableProduct: true Product { name: "theProduct" condition: project.enableProduct } } \endcode If the nearest project in the project tree does not have the desired property, \QBS looks it up in the parent project, potentially all the way up to the top-level project. */ /*! \previouspage special-property-values.html \page module-providers.html \nextpage tutorial.html \title Module Providers There are use cases for which a pre-defined module is not flexible enough. For instance, the overall set of modules related to a certain task might depend on some information present on the local platform. Use Module Providers to create new modules during the \c resolve stage, for example when locating external dependencies such as libraries. Consider the following example: \code CppApplication { files: "main.cpp" Depends { name: "zlib" } qbsModuleProviders: ["conan", "qbspkgconfig"] } \endcode Here, we want to use the \l{https://www.zlib.net}{zlib} compression library in our application. Since there is no pre-defined module called \c "zlib", \QBS will try to create it using Module Providers. \QBS will invoke all providers specified in the \l{Product::qbsModuleProviders}{qbsModuleProviders} property and those providers will create the requested module if possible. Providers contribute to the \l{Product::}{qbsSearchPaths} in the order specified by this property, so modules generated by providers specified earlier are prioritised. In the example above, modules created by the \l conan provider have higher priority than modules created by \c qbspkgconfig. \section1 Lookup Based on Module Name Originally, the \l{Qt} module provider was a the only provider in \QBS and we wanted to make its usage transparent to users. Thus, it was implemented by automatically kicking in when \QBS saw the dependency on the \c Qt module such as "Qt.core". It is also possible to specify the order of providers explicitly: \code CppApplication { files: "main.cpp" Depends { name: "Qt.core" } qbsModuleProviders: ["Qt", "qbspkgconfig"] } \endcode That way, users have more control over the module priorities. Note that setting the \c qbsModuleProviders property disables the lookup based on the module name entirely. \section1 Provider Eagerness Historically, providers were implemented in an \e eager way meaning that once a provider is called, it creates as many modules as it can. For example, when called, the \l{qbspkgconfig} provider created a module for each .pc file found in the system. Even though providers are quite fast, this violates the zero-overhead principle (you don't pay for what you don't use). Thus, we introduced non-eager providers which only create one module at a time when that module is requested by the \l{Depends} item. This behavior is controlled by the \l{ModuleProvider::isEager}{isEager} property. We advise against using eager providers in new code. \section1 Selecting Module Providers As described above, you can select which providers to run using the \l{Product::qbsModuleProviders}{qbsModuleProviders} property. This property can be set on the Product as well as the \l{Project::qbsModuleProviders}{Project} level: \code $ qbs resolve project.qbsModuleProviders:providerA \ # sets property globally for the Project projects.SomeProject.qbsModuleProviders:providerB \ # overrides property for the specific Project products.SomeProduct.qbsModuleProviders:providerC \ # overrides property for the specific Product \endcode \section1 Parameterizing Module Providers You can pass information to module providers from the command line, via profiles or from within a product, in a similar way as you would do for modules. For instance, the following invocation of \QBS passes information to two module providers \c a and \c b: \code $ qbs moduleProviders.a.p1:true moduleProviders.a.p2:true moduleProviders.b.p:false \endcode \QBS will set the properties of the respective module providers accordingly. In the above example, module provider \c a needs to declare two boolean properties \c p1 and \c p2, and they will be set to \c true and \c false, respectively. \note The following section contains some implementation details. Reading this section is not required for most people's everyday work. \section1 How \QBS Uses Module Providers If \QBS encounters a \l Depends item whose name does not match a known module, it checks whether such a module can be generated. This procedure works as follows: \list 1 \li If the \l{Product::qbsModuleProviders}{qbsModuleProviders} property is not \c undefined, for each provider name in the list, all \l{Project::qbsSearchPaths}{search paths} are scanned for a file called \c {module-providers/.qbs} or \c {module-providers//provider.qbs}. \li If the \l{Product::qbsModuleProviders}{qbsModuleProviders} property is \c undefined, \l{Project::qbsSearchPaths}{search paths} are scanned for a file called \c {module-providers//provider.qbs}, where \c is the name of the dependency as specified in the \c Depends item. Multi-component names such as "a.b" are turned into nested directories, and each of them is scanned, starting with the deepest path. For instance, if the dependency's name is \c {a.b}, then \QBS will look for \c {a/b/provider.qbs} and then \c {a/provider.qbs}. \li If such a file is found, it needs to contain a \l ModuleProvider item. This item is instantiated, which potentially leads to the creation of one or more modules, and \QBS retrieves the search paths to find these modules from the item. The details are described in the \l ModuleProvider documentation. \li If a matching module provider was found and provided new search paths, a second attempt will be made to locate the dependency using the new paths. The search for a matching module provider ends as soon as one was found, regardless of whether it created any modules or not. \endlist */ /*! \previouspage shell.html \page generators.html \nextpage multiplexing.html \title Generators Generators are a \QBS sub-tool and set of APIs that enable arbitrary processing to be performed on the build graph. Currently, they are used to integrate \QBS with popular IDEs, such as Microsoft Visual Studio, and to generate Clang compilation databases. \section1 Generating Microsoft Visual Studio Projects To generate a project for another build system, such as Microsoft Visual Studio, use the \l{generate}{qbs generate} command and specify a generator using the \l{generate-generator}{-g} option. For example: \code # For Visual Studio qbs generate -g visualstudio2015 \endcode \QBS will then generate a series of files in the current directory, based on the generator that was chosen. The resulting project files can be opened in the respective IDE and all work can be performed there. The project files will expose as much information as possible to the IDE and will use \QBS to perform the actual build. \note You cannot modify build system files and expect the changes to be reflected in \QBS. You must edit your \QBS project files and re-run \l{generate}{qbs generate} in order for the changes to be reflected in your IDE. \section1 Generating IAR Embedded Workbench Projects To generate a project for \l{https://www.iar.com/iar-embedded-workbench/} {IAR Embedded Workbench}, use the \l{generate}{qbs generate} command and specify a generator using the \l{generate-generator}{-g} option. For example: \code # For IAREW v8xxxx qbs generate -g iarew8 profile: qbs generate -g iarew8 -d -f profile: \endcode \note You need to specify a specific QBS profile, which is required for a generator to fetch a target architecture to generate the project. \note IAR EW generator creates a native target project. Supported IAR EW generators are listed in a table below: \table \header \li Generator \li IAR EW Version \li Target Architecture \row \li iarew8 \li All 8.x.y versions \li ARM \row \li iarew7 \li All 7.x.y versions \li AVR, MSP430 \row \li iarew10 \li All 10.x.y versions \li 8051 (aka MCS51) \row \li iarew3 \li All 3.x.y versions \li STM8 \endtable \section1 KEIL uVision Projects To generate a project for \l{https://www2.keil.com/mdk5/uvision/} {KEIL uVision}, use the \l{generate}{qbs generate} command and specify a generator using the \l{generate-generator}{-g} option. For example: \code # For KEIL UV5 qbs generate -g keiluv5 profile: qbs generate -g keiluv5 -d -f profile: \endcode \note You need to specify a specific QBS profile, which is required for a generator to fetch a target architecture to generate the project. \note KEIL UV generator creates a native target project. Supported KEIL UV generators are listed in a table below: \table \header \li Generator \li KEIL UV Version \li Target Architecture \row \li keiluv5 \li All 5.x.y versions \li 8051 (aka MCS51), ARM \endtable \section1 Generating Clang Compilation Databases To generate a \l{JSON Compilation Database Format Specification} {Clang compilation database (clangdb)}, use the following command: \code qbs generate --generator clangdb \endcode \section1 Generating Makefiles To generate a Makefile, use the following command: \code qbs generate --generator makefile \endcode \section2 Targets The generated Makefile will contain targets for all output artifacts known to \QBS. In addition, the following targets are created for every product: \list \li \c {} to build the product \li \c {clean-} to remove all files generated by the above target \li \c {install-} to install the product's artifacts that have \c{qbs.install} set \endlist In the above list, the placeholder \c{} stands for the product's name with all characters that are not ASCII letters, digits, dots or underscores replaced with underscore characters. The special target \c all builds all products whose \l{Product::builtByDefault}{builtByDefault} property is enabled. This is the default target. It is complemented by \c install and \c clean. \note The Makefile will not be able to build artifacts created by \l{JavaScriptCommand}{JavaScriptCommands}, because there is no command line to run for them. \section2 Pre-defined Variables The build directory and the install root are set to whatever you specified when calling the generator. If you did not specify anything, \QBS' default values are used. You can override these values when invoking the \c make tool by explicitly setting the \c{BUILD_ROOT} and \c{INSTALL_ROOT} variables, respectively. For instance: \code $ qbs generate -g makefile config:make modules.qbs.installRoot:/opt/mydir $ make -f make/Makefile # Will install to /opt/mydir $ make -f make/Makefile INSTALL_ROOT=/opt/myotherdir # Will install to /opt/myotherdir \endcode \section2 Spaces in Directory Names Due to the difficulties involved in making this work correctly, \QBS will refuse to generate a Makefile if the source, build or install root directories contain spaces. It will try to handle spaces in file names of output artifacts, though. \section2 Platform-specific Differences in Format \QBS assumes that the Makefile will be invoked on the current host platform, so that platform's tools will be used for copying and removing files, and path separators will be converted to backslashes on Windows. When dealing with spaces in artifact names, on Unix-like systems compatibility with GNU make is assumed with regards to quoting. \section1 Limitations Due to the high flexibility of the \QBS project format and build engine, some projects may be too complex to produce an equivalent project file for another build system. This list of limitations aims to be as small as possible, but one of the most notable (at least for the Microsoft Visual Studio generator) is that certain properties must contain the same value across all build configurations. For example, the following is not allowed: \code Product { // ERROR: 'name' property cannot have different values based on the configuration name: qbs.configuration === "debug" ? "MyProduct_debug" : "MyProduct" } \endcode \note This limitation only applies when property values are varied on the configuration name. For example, the following is OK (as long as the value of xyz itself does not vary across configurations): \code Product { // OK property bool isDebug: name: isDebug ? "MyProduct_debug" : "MyProduct" } \endcode The properties to which the limitation applies includes but is not limited to: \list \li \l{Product::name}{Product.name} \li \l{bundle::isBundle}{bundle.isBundle} \endlist If a simple workaround is possible in a particular case (for example, varying \l{Product::targetName}{Product.targetName} across configuration instead of \l{Product::name}{Product.name}, the generator will typically suggest it in the error message. */ /*! \previouspage generators.html \page multiplexing.html \nextpage custom-modules.html \title Multiplexing Multiplexing is an advanced \QBS feature that allows a product to be transparently built in multiple \e passes along with an optional, final \e aggregate pass that allows the output artifacts of the initial passes to be combined or otherwise operated on in some way. The multiplexing feature is used to implement certain platform-specific behavior: specifically, it allows applications and libraries on Apple platforms to be compiled into \e fat binaries containing multiple CPU architectures, the creation of Apple frameworks containing multiple \e variants (for example, combined debug and release builds), and the creation of Android application and library packages containing native code built for multiple Android ABIs. A product can be multiplexed over the \l{qbs::architectures} {qbs.architectures} property (which maps to \l{qbs::architecture} {qbs.architecture}), \l{qbs::buildVariants}{qbs.buildVariants} property (which maps to \l{qbs::buildVariant}{qbs.buildVariant}), and \l{qbs::profiles} {qbs.profiles} (which maps to \l{Project::profile}{Project.profile}). For example, to build a "fat" \c iOS binary containing two architectures, use the following command: \code qbs build modules.qbs.targetPlatform:ios modules.qbs.architectures:arm64,armv7a \endcode \note The implementation details around multiplexing are subject to change. Product multiplexing works by examining the \l{Product::multiplexByQbsProperties}{Product.multiplexByQbsProperties} property, which can be set to the list of properties your product should multiplex over. For example, \c multiplexByQbsProperties might contain two strings, \c "architectures" and \c "buildVariants". \QBS evaluates the values of \c qbs.architectures and \c qbs.buildVariants, which in turn might contain the values \c ["x86", "x86_64"] and \c ["debug", "release"]. \QBS will build all the possible configurations of the product: \c {(x86, debug)}, \c {(x86, release)}, \c {(x86_64, debug)}, and \c {(x86_64, release)}. If the \l{Product::aggregate}{Product.aggregate} property is \c true, the product will also be built a fifth time, with the values of the multiplexed properties left undefined. The aggregate product will have an automatic dependency on the original four instances of the product, allowing it to collect their output artifacts and to operate on them. The aggregate product is used in situations where the target artifacts of the individually multiplexed instances must be combined into one final aggregate artifact that makes up the overall product. Bundle products on Apple platforms use the aggregate product to create the bundle artifacts (such as \c Info.plist and \c PkgInfo) that are independent of a particular architecture or build variant. In addition, they use the \c lipo tool to join together the built native code for different architectures (such as \c x86 and \c x86_64) into the final, multi-architecture fat binary that the app bundle contains. */ /*! \previouspage json-api.html \page attributions.html \title Appendix D: Licenses and Code Attributions \section1 Licenses The \QBS library and tools are available under commercial licenses from \l{Qt Licensing}{The Qt Company}. In addition, they are available under \l{GNU Lesser General Public License, Version 3} (LGPL version 3) and \l{GNU General Public License, version 2} (GPL version 2). Shared functionality, which might be pulled in by user build scripts, is available under commercial licenses, \l{GNU Lesser General Public License, Version 2.1} (LGPL version 2.1) with \l{The Qt Company LGPL Exception version 1.1}, and LGPL version 3. Autotests are available under commercial licenses and \l{GNU General Public License Version 3, Annotated with The Qt Company GPL Exception 1.0}. Examples are available under commercial licenses and \l{BSD}. \section2 GNU Lesser General Public License, Version 3 \quotefile ../LICENSE.LGPLv3 \section2 GNU General Public License Version 3, Annotated with The Qt Company GPL Exception 1.0 \quotefile ../LICENSE.GPL3-EXCEPT \section2 GNU Lesser General Public License, Version 2.1 \quotefile ../LICENSE.LGPLv21 \section2 The Qt Company LGPL Exception version 1.1 \quotefile ../LGPL_EXCEPTION.txt \section1 Third-Party Attibutions \QBS contains third-party code, which we gratefully acknowledge: \generatelist{groupsbymodule attributions-qbs} */ qbs-src-3.3.1/doc/CMakeLists.txt0000644000175100017510000000157215232633614016015 0ustar runnerrunnerset(_DOC_SOURCES ../README.md ../CONTRIBUTING.md classic.css external-resources.qdoc fixnavi.pl howtos.qdoc qbs.qdoc qbs-online.qdocconf config/style/qt5-sidebar.html ) file(GLOB_RECURSE _DOC_APPENDIX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/appendix/*") file(GLOB_RECURSE _DOC_REFERENCE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/reference/*") file(GLOB_RECURSE _DOC_TEMPLATES_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/templates/*") file(GLOB_RECURSE _DOC_IMAGES_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/images/*") file(GLOB_RECURSE _DOC_TARGETS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targets/*") add_qbs_documentation( "qbs.qdocconf" SOURCES ${_DOC_SOURCES} ${_DOC_APPENDIX_SOURCES} ${_DOC_REFERENCE_SOURCES} ${_DOC_TEMPLATES_SOURCES} ${_DOC_IMAGES_SOURCES} ${_DOC_TARGETS_SOURCES} ) add_subdirectory(man) qbs-src-3.3.1/doc/tutorial.qdoc0000644000175100017510000010330115232633614015761 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage module-providers.html \page tutorial.html \nextpage tutorial-1.html \title Tutorial The tutorial describes the process of creating a typical \QBS project and explains core concepts. \list \li \l{tutorial-1.html}{Console Application} \li \l{tutorial-2.html}{Static Library} \li \l{tutorial-3.html}{Dynamic Library} \li \l{tutorial-4.html}{Convenience Items} \li \l{tutorial-5.html}{Autotest} \li \l{tutorial-6.html}{Project Properties} \li \l{tutorial-7.html}{Buildconfig Module} \li \l{tutorial-8.html}{Configurable Library} \li \l{tutorial-9.html}{Version Header} \li \l{tutorial-10.html}{C++20 Modules} \endlist */ /*! \previouspage tutorial.html \page tutorial-1.html \nextpage tutorial-2.html \title Console Application Let's start with a mandatory Hello World example. There is a Hello World example in the \l{overview.html#well-defined-language}{overview section}, but this time we will create a real-world project. We will start with a simple \QBS project file: \snippet ../tutorial/chapter-1/myproject.qbs 0 Here, we set the \l{Project::name}{name} of the project to \c "My Project" - it is mainly used for IDEs but can also be used to reference a project when setting properties from command-line. We also set the \l{Project::minimumQbsVersion}{minimumQbsVersion} - this property can be useful if the project depends on features that are not present in earlier \QBS versions. The \l{Project::references}{references} property contains the path to a file that describes our application. This file is located in a separate \c app directory - typically, projects tend to have quite a complicated structure but \QBS does not enforce any specific layout, so we will simply put each product in a separate directory. The application file sets several properties: \snippet ../tutorial/chapter-1/app/app.qbs 0 The \l{Product::name}{name} property identifies the product. The \l{Product::targetName}{targetName} property sets the name of the resulting binary (without the \c .exe extension on Windows, which is appended automatically). By default, \l{Product::targetName}{targetName} defaults to \l{Product::name}{name}. The \l{Product::files}{files} property contains a single \c main.c file which is a trivial \e{hello world} application: \snippet ../tutorial/chapter-1/app/main.c 0 We set \l{Product::consoleApplication}{consoleApplication} to \c true to indicate that our application is going to be used from a terminal. For example, on Windows, this will spawn a new console window if you double-click the resulting binary, while on macOS it will create a standalone binary file instead of an \l{https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html}{application bundle}. By default, \QBS installs binaries into an \e{installation root} folder which by default is named \c install-root and located under the build directory. This folder will contain only resulting artifacts without the build leftovers and files will have the same layout as in the target system. In order to skip installation of the specific Application product, set the \l{Application::install}{CppApplication.install} property to \c false. See the \l{installing-files.html}{Installing Files} section for more details. We can now build and run our application from the project directory: \code chapter-1 $ qbs build ... Building for configuration default compiling main.c [My Application] ... linking myapp [My Application] ... Build done for configuration default. chapter-1 $ qbs run ... Starting target. Full command line: .../default/install-root/usr/local/bin/myapp Hello, world \endcode The \QBS output to console and default installation location may vary between different platforms. In most cases, \QBS should be able to find the default compiler (for example, GCC or Clang on Linux, Visual Studio on Windows, or Xcode on macOS), but if that's not the case, see the \l{configuring.html}{configuring} section. In the following chapters, we will continue to improve our project: we will add a library and make it configurable. */ /*! \previouspage tutorial-1.html \page tutorial-2.html \nextpage tutorial-3.html \title Static Library Let's add a static library to our project so we can reuse some code. Analogous to what we did for the application, we put the file into the \c{lib} directory and add it to the \l{Project::references}{references} property in our project. The modified project may look like this: \snippet ../tutorial/chapter-2/myproject.qbs 0 Let's take a look at the the library file now: \snippet ../tutorial/chapter-2/lib/lib.qbs 0 It contains the \l{StaticLibrary} item which sets the \l{Product::type}{type} of the product to \c "staticlibrary" and sets some defaults like where to install that library. The \l{StaticLibrary} item inherits the \l{CppLibrary} item which pulls in the dependency on the \l{cpp} module. As before, we set the \l{Product::files}{files} property with a header: \snippet ../tutorial/chapter-2/lib/lib.h 0 And we set the implementation file of our library: \snippet ../tutorial/chapter-2/lib/lib.c 0 We will keep our library really simple - it only contains one function, which we will later use in our application. The source file requires a \c "CRUCIAL_DEFINE" to be passed to a preprocessor. That is why we set the \l{cpp::defines}{cpp.defines} property: \snippet ../tutorial/chapter-2/lib/lib.qbs 1 Next, we need to tell \QBS where to look for public headers of our library when building products that depend on it. By default, \QBS knows nothing about the layout of our library, so we tell it to look for headers in the library's source directory using the \l{Export} item: \snippet ../tutorial/chapter-2/lib/lib.qbs 2 You can export any \l{Module} property within the \l{Export} item - it will be merged in the depending product with other properties. For example, you can export \l{cpp::defines}{cpp.defines} or specific \l{cpp::commonCompilerFlags}{compiler flags} that are required to use this product. We depend on the \l{cpp} module twice - once within the \l{StaticLibrary} item and once in the \l{Export} item. This is because by default \QBS does not export anything when depending on this product and the dependencies in this item (as well as properties set in this item) are private to this product while dependencies and properties set in the \l{Export} item are for export only. Finally, we have some Apple-specific settings. You can skip this part of the tutorial if you are using some other platform. We depend on the \l{bundle} module and set the \l{bundle::isBundle}{bundle.isBundle} to false: \snippet ../tutorial/chapter-2/lib/lib.qbs 3 By default, \QBS builds static and dynamic libraries as \l{https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html}{Frameworks} on macOS. So, to keep things simple, we disable the framework build and build a plain old static library file here. */ /*! \previouspage tutorial-2.html \page tutorial-3.html \nextpage tutorial-4.html \title Dynamic Library Let's now turn our static library into a dynamic library. It is a bit trickier with dynamic libraries since several things should be tweaked. First, we need to be able to mark methods (or classes) in our library as exported. Second, we need to tell our application where to look for our library at run time using \l{https://en.wikipedia.org/wiki/Rpath}{rpaths}. Some compilers, like MSVC, require us to mark which symbols we want to export or import. The \l{https://stackoverflow.com/a/6840659}{canonical} way would be to define some helper macros. Let's start with a header that defines those helper macros: \snippet ../tutorial/chapter-3/lib/lib_global.h 0 This header defines the \c MYLIB_EXPORT macro that expands either to an "export" or to an "import" directive based on the presence of the \c MYLIB_LIBRARY macro. We can use this macro to mark a function as follows: \snippet ../tutorial/chapter-3/lib/lib.h 0 The modified library product may look like this: \snippet ../tutorial/chapter-3/lib/lib.qbs 0 The most important change is that we changed the item type from \l{StaticLibrary} to \l{DynamicLibrary}. We moved the \c "lib.h" header into the \l{CppLibrary::publicHeaders}{publicHeaders} property. That way, the header will be installed with the library to the \c{/include/my project/mylib/} directory. If you do not want to ship headers with your library, simply put those into the \l{Product::files}{files} property like we did in the previous chapter. We also added the \c MYLIB_LIBRARY to the list of \l{cpp::defines}{defines}. We do this only when building the library but we are not exporting it - that way the users of our library will have methods marked for import rather than export. Finally, we set \l{cpp::sonamePrefix}{cpp.sonamePrefix} to \c "@rpath". This is required only for Apple platforms, see \l{https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html}{Run-Path Dependent Libraries} for details. It is also required to set \l{cpp::rpaths}{cpp.rpaths} in our application file. Since the library is installed to the \c{lib} directory and the application is installed to the \c{bin} directory, we need to tell the loader to look in the \c{lib} directory. The \l{jsextension-fileinfo.html#relativePath}{FileInfo.relativePath} method can help us: \snippet ../tutorial/chapter-3/app/app.qbs 0 On Linux, this expression would be equivalent to this: \c{cpp.rpaths: ["$ORIGIN/../lib"]}. Don't forget to \c{import qbs.FileInfo} in order to be able to use the \l{jsextension-fileinfo.html} extension. To make the example complete, here's how the full \c app/app.qbs file should look like: \snippet ../tutorial/chapter-3/app/app.qbs 1 */ /*! \previouspage tutorial-3.html \page tutorial-4.html \nextpage tutorial-5.html \title Convenience Items As you might have noticed, we are repeating ourselves when setting the same properties in our products - we set \l{Product::version}{version}, \l{cpp::rpaths}{cpp.rpaths}, and so on. For a single application and a library, that is not a big deal, but what if we have a dozen libraries? Luckily, this can be achieved using item \l{language-introduction.html#reusing-project-file-code}{inheritance} - we move the common code to the base item and in the real product we will only set what is specific to that product (for example, the list of \l{Product::files}{files}). First, we need to tell \QBS where to look for our new base items. This can be achieved using the \l{Project::qbsSearchPaths}{qbsSearchPaths} property. We set this property to \c "qbs" so that \QBS will search our items in the \c{qbs} directory located in the project directory: \snippet ../tutorial/chapter-4/myproject.qbs 0 \note This directory has a pre-defined structure: base items should be located under the \c{imports} subdirectory. See \l{Custom Modules and Items} for details. Let's create a base item for all our applications and move common code there: \snippet ../tutorial/chapter-4/qbs/imports/MyApplication.qbs 0 As you see, we managed to extract most of the code here, and our application file now only contains what's relevant to it: \snippet ../tutorial/chapter-4/app/app.qbs 0 Now let's do the same for our library: \snippet ../tutorial/chapter-4/qbs/imports/MyLibrary.qbs 0 Here, we introduce a helper property, \c libraryMacro, with a default value calculated based on the capitalized product name. Since the name of out library product is \c "mylib", this property will expand to \c "MYLIB_LIBRARY". We can also override the default value for the macro in products that inherit our item like this: \code MyLibrary { libraryMacro: "SOME_OTHER_LIBRARY_MACRO" } \endcode Let's take a look at the refactored library file: \snippet ../tutorial/chapter-4/lib/lib.qbs 0 We managed to extract the reusable parts to common base items leaving the actual products clean and simple. Unfortunately, item inheritance comes with a price - when both parent and child items set the same property (\l{cpp::defines}{cpp.defines} in our case), the value in the child item wins. To work around this, the special \l{special-property-values.html#base}{base} value exists - it gives access to the base item's value of the current property and makes it possible to extend its value rather than override it. Here, we concatenate the list of defines from the base item \c{["MYLIB_LIBRARY"]} with a new list, specific to this product (namely, \c{['CRUCIAL_DEFINE']}). */ /*! \previouspage tutorial-4.html \page tutorial-5.html \nextpage tutorial-6.html \title Autotest Now that we can re-use our base items, let's add a simple autotest. We inherit the new item from the \c MyApplication item and add an \c "autotest" type: \snippet ../tutorial/chapter-5/qbs/imports/MyAutoTest.qbs 0 This additional type is required for the helper \l{AutotestRunner} item. This item runs all products with the \c "autotest" type when it is being built. It also implicitly depends on all such products, so they will be built before running as well. Let's add this item to our top-level \l{Project} item: \code Project { name: "My Project" minimumQbsVersion: "2.0" // ... AutotestRunner { timeout: 60 } } \endcode Here we set the \l{AutotestRunner::timeout}{timeout} property to 60 seconds so that our runner kills tests that run way too long. Now we need to add our first test. Let's create a new product with the following content: \snippet ../tutorial/chapter-5/test/test.qbs 0 Here we depend on our library (which we are going to test), set the product \l{Product::name}{name}, and specify the source file, which looks like this: \snippet ../tutorial/chapter-5/test/test.c 0 The test compares the value from the library with the value from the command line. Don't forget to add the new test product to the references property in the Project: \snippet ../tutorial/chapter-5/myproject.qbs 0 Now we can build the autotest product - this will also launch our test: \code $ qbs build -p "autotest-runner" ... running test mytest [autotest-runner] Build done for configuration default. \endcode */ /*! \previouspage tutorial-5.html \page tutorial-6.html \nextpage tutorial-7.html \title Project Properties It would be nice if our project was configurable. Let's add some properties to our root project file: \snippet ../tutorial/chapter-6/myproject.qbs 0 Now we can use those properties in our helper items and in products: \snippet ../tutorial/chapter-6/qbs/imports/MyApplication.qbs 0 Here, we access the project file using the special \l{special-property-values.html#project}{project} value. If the nearest project in the project tree does not have the desired property, \QBS looks it up in the parent project, potentially all the way up to the top-level project. Let's now disable the tests if \c project.withTests is \c false: \snippet ../tutorial/chapter-6/myproject.qbs 1 Here we use the \l{Properties} item within the \l{SubProject} item. This item allows to override a subproject's properties which can be useful when adding some other \QBS project as a Git submodule. Of course, it is not very useful in our particular case since we only set the \l{Project::condition}{Project.condition} property. We could achieve the same effect by setting the \l{SubProject::condition}{condition} property of the \l{SubProject} item: \code SubProject { filePath: "test/test.qbs" condition: parent.withTests } \endcode Another way would be to disable the test product. That way, an IDE would still show the whole project tree including disabled tests: \code // qbs/imports/MyAutoTest.qbs MyApplication { condition: project.withTests type: base.concat(["autotest"]) } \endcode Let's finally make our \l{AutotestRunner} configurable too: \snippet ../tutorial/chapter-6/myproject.qbs 2 There are several ways to override project properties from the command line. First, the special \c project variable can be used to set the properties of the top-level project: \code $ qbs resolve project.withTests:false \endcode You can also refer to properties using project's \l{Project::name}{name}: \code $ qbs resolve "projects.My Project.withTests:false" \endcode This can again be useful for accessing the properties of external sub-projects. Note that since the project name contains spaces, we use quotes here. */ /*! \previouspage tutorial-6.html \page tutorial-7.html \nextpage tutorial-8.html \title Config Module In the previous chapter, we added some properties to our main \l{Project} file. While this is a perfect approach for \e public properties of the project, sometimes we want to add some \e private properties for better tuning. Of course, we could put everything in the \l{Project} file, but that would make it very convoluted. Also, accessing the top-level project all the way from products makes things strongly tied. Let's create a file named \c{module.qbs} and put it into the \c{qbs/modules/config/install} directory, near the \c{qbs/imports} directory: \code // qbs/modules/config/install/module.qbs ConfigInstall { } \endcode Here we inherit the \l{ConfigInstall} item in order to re-use its properies. Since custom \l{Project::qbsSearchPaths}{qbsSearchPaths} are searched first, now our version will be used instead of built-in one. First, let's change the default value of the \l{ConfigInstall::importLibraries}{config.install.importLibraries} in order to install import libraries on Windows: \code // qbs/modules/config/install/module.qbs ConfigInstall { importLibraries: true } \endcode We could extend the \l{config.install} module with additional properties, but that could create collisions when someone tries to include the source code of your project into their project. Thus, we will create a new \c{config.myproject} module and use the same approach with the base item as \QBS does for the \c{config.install} module. Let's create a new item and add a new property to it: \snippet ../tutorial/chapter-7/qbs/imports/ConfigMyProject.qbs 0 We added the \c{enableAddressSanitizer} property and a dependency on the \l{Sanitizer.address} module if that property is set to \c{true}. Now let's use the item in a module: \snippet ../tutorial/chapter-7/qbs/modules/config/myproject/module.qbs 0 Now we can use our module in the \c{MyLibrary.qbs} item by pulling in the new module using the \l{Depends} item: \snippet ../tutorial/chapter-7/qbs/imports/MyLibrary.qbs 0 Now we can enable sanitizer build by setting the \c{enableAddressSanitizer} property from command-line: \code $ qbs resolve modules.config.myproject.enableAddressSanitizer:true $ qbs build \endcode Instead of the \c{config.myproject.enableAddressSanitizer} property, we could also use the property in the \l{Project} item similar to how we did in the previous chapter. There is no strong preference which way to use, however using modules for configuration is more flexible as it is also possible to set properties of other modules as described below. \QBS \l{Module}{modules} have the feature to automatically export properties of other modules. Those exported properties are merged in the resulting product. We can use this feature to set the \l{cpp::rpaths}{cpp.rpaths} in our module rather than in products: \snippet ../tutorial/chapter-7/qbs/imports/ConfigMyProject.qbs 1 Here, we inject the dependency on the \l{cpp} module and calculate the \c{libRPaths} property. This is a relative path from the \c{product.installDir} (which is either \c{"bin"} or \c{"lib"}, depending on product type) to \l{ConfigInstall::dynamicLibrariesDirectory}{dynamicLibrariesDirectory} (which is \c{"lib"} by default). Finally, we set \l{cpp::rpaths}{cpp.rpaths} to this property. This way, those \c rpaths will be automatically exported to all products that depend on the \c{config.myproject} module. We should also update the \c{MyApplication} item to add a dependency on the \c{"config.myproject"} in order to inject \l{cpp::rpaths}{cpp.rpaths} we set in the module: \snippet ../tutorial/chapter-7/qbs/imports/MyApplication.qbs 0 */ /*! \previouspage tutorial-7.html \page tutorial-8.html \nextpage tutorial-9.html \title Configurable Library In this chapter, we will make our library more configurable to be able to choose between static and dynamic builds. We need to do some modifications to export macros in the \c lib/lib_global.h header: \snippet ../tutorial/chapter-8/lib/lib_global.h 0 Here' we added a new branch when \c MYLIB_STATIC_LIBRARY is defined. In that case, we make the \c MY_LIB_EXPORT macro empty. Now, let's modify the \c qbs/imports/MyLibrary.qbs file as follows: \snippet ../tutorial/chapter-8/qbs/imports/MyLibrary.qbs 0 First thing to notice is that we changed the type of the item from \l{DynamicLibrary} to the \l{Library} item which is a common base item for dynamic and static libraries. Second, we change our \e{export macro} to be different in the static and dynamic builds to correspond with the changes we made to the \c lib_global.h: \code readonly property string _nameUpper : name.replace(" ", "_").toUpperCase() property string libraryMacro: _nameUpper + "_LIBRARY" property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY" cpp.defines: config.build.libraryType === "static" ? [staticLibraryMacro] : [libraryMacro] \endcode Note that in a static build we export the \c MYLIB_STATIC_LIBRARY macro so that the dependent products will know whether they link to a static or dynamic library: \code Export { ... cpp.defines: exportingProduct.config.build.libraryType === "static" ? [exportingProduct.staticLibraryMacro] : [] } \endcode Now we can build our project in dynamic or static mode: \code $ qbs resolve modules.config.build.libraryType:static && qbs build ... $ ls default/install-root/usr/local/lib/ libmylib.1.0.0.so libmylib.1.0.so libmylib.1.so libmylib.so $ rm -r default $ qbs resolve modules.config.myproject.staticBuild:true modules.config.install.staticLibraries:true && qbs build ... $ $ ls default/install-root/usr/local/lib/ libmylib.a \endcode \note \QBS does not install static libraries by default, thats why we set the \l{ConfigInstall::staticLibraries}{config.install.staticLibraries} property to \c{true} to enforce installation of the static library. We can also change the default in the \c{config.install} module: \code // qbs/modules/config/install/module.qbs ConfigInstall { ... importLibraries: true staticLibraries: true ... } \endcode */ /*! \previouspage tutorial-8.html \page tutorial-9.html \nextpage tutorial-10.html \title Version Header To create new files, such as version headers, during the build, use \l{Rules}. Every command \QBS executes, such as compile or linker commands, is described by a corresponding Rule in a Module or a Product. In this section, we will create a simple header with a string constant based on the variable in our project. First, we add this variable to our \c config.myproject base item: \snippet ../tutorial/chapter-9/qbs/imports/ConfigMyProject.qbs 0 Next, we create a new file, \c{version.h.in}, located in the \c{version-header} directory. This file contains the template for our header: \snippet ../tutorial/chapter-9/version-header/version.h.in 0 Now we create a file called \c{version-header.qbs} in the same directory. This file contains a \l{Product} with a \l{Rule} that turns the \c{version.h.in} into a real header. Let's go through the contents of the file: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 0 First, we import \l{TextFile Service}{TextFile}. We will need this class to read the template and write the resulting header. Second, we declare a new \l{Product} named \c{"version_header"} and with the \c{"hpp"} type. This is the type of the artifact we will create in the Rule. Third, we add the dependency on the \c config.myproject module to use the new \c config.myproject.productVersion variable. We also add a \l{Group} with the template file and assign the \c{version_h_in} tag to the file: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 1 \QBS Rules work with file tags, instead of working with files directly, which makes it easy to reuse rules. The name of the tag is chosen arbitrarily here. We could use the name of the file as a tag, but to avoid confusion between file name and file tag, we use underscores in the tag instead of dots. Now we can create a Rule itself: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 2 Here, we specify that our Rule takes files tagged as \c "version_h_in" and produces an \l{Artifact} with the name \c "version.h" and tagged \c "hpp". By default, files are created in the \l{Product::destinationDirectory}{Product.destinationDirectory} folder. We add the \c "hpp" tag for the header as this is the tag the \l{cpp}{cpp module} uses for headers. That way, \QBS can track changes and process our generated file the same way it treats all other headers. Note that earlier we set the product type to \c "hpp" as well. \QBS requires that artifact type should match the product type directly or be accessible via the chain of Rules. Otherwise, the Rule won't be executed. For details, see the \l{Rules and Product Types} section. The actual code generation happens in the \l{Rule::prepare}{Rule.prepare} script: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 3 In this script, we create a \l {JavaScriptCommand} object and set some meta properties, such as the description and highlight. For details about Commands, see \l{Command and JavaScriptCommand}. In the sourceCode variable, we create a JavaScript function that opens the \l{The inputs and outputs Variables}{input file}, reads its content using the \l{TextFile Service}{TextFile} object, replaces the \c "${PRODUCT_VERSION}" placeholder with the actual value in the \c product.config.myproject.productVersion variable, and writes the resulting content into the \l{The inputs and outputs Variables}{output file}. Finally, we export the \l{Product::buildDirectory}{exportingProduct.buildDirectory} so that products that depend on this product can include our generated header: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 4 The full content of the file should look like this: \snippet ../tutorial/chapter-9/version-header/version-header.qbs 5 Let's now add our Product into the root project so \QBS will be aware of it: \snippet ../tutorial/chapter-9/myproject.qbs 0 We also need to add the dependency on the \c "version_header" to our application: \snippet ../tutorial/chapter-9/app/app.qbs 0 Now we can include the header in the \c main.c file and print the contents of the string constant: \snippet ../tutorial/chapter-9/app/main.c 0 Let's try and run our application. You should see something like this: \code $ qbs run -p "My Application" Starting target. Full command line: .../default/install-root/usr/local/bin/myapp Hello, world Hello from library ProductVersion = 1.0.0 \endcode */ /*! \previouspage tutorial-9.html \page tutorial-10.html \nextpage howtos.html \title C++20 Modules This tutorial implies you have some knowledge about C++20 modules. If not, see \l{https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp}{Overview of modules in C++} for introduction. \section1 Named Modules Using C++20 modules with \QBS is pretty straightforward. Let's suppose you have a module file that exports a single function \c printHello: \snippet ../tutorial/chapter-10-1/hello.cppm 0 \note Currently, Clang only recognizes \c .cppm files as modules, however, for GCC and MSVC \QBS also recognizes \c .ixx files as C++ modules. \QBS assigns the \c "cppm" file tag to these files. You can assign this tag manually to module files with different extensions. This function is later used in the \c main.cpp file as follows: \snippet ../tutorial/chapter-10-1/main.cpp 0 The project file simply lists files and sets the \l{cpp::forceUseCxxModules}{cpp.forceUseCxxModules} property to \c true. \code // myproject.qbs CppApplication { consoleApplication: true files: ["hello.cppm", "main.cpp"] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true } \endcode Now, you can build the project by simply calling \c{qbs}, assuming that your compiler supports C++20 modules. \section1 Module Partitions \l{https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp?view=msvc-170#module-partitions}{Module partitions} are treated as regular modules and should also have the same extension or assigned the \c "cppm" tag manually. See this \l{https://github.com/qbs/qbs/tree/2.5/examples/cxx-modules/mod3}{example} on how to use both interface module and partitions. \section1 Modules and Libraries Using modules in dynamic libraries requires using the same export/import macros as it was shown in the \l{tutorial-3.html}{Dynamic Library} section: \snippet ../tutorial/chapter-10-2/lib/hello.cppm 0 As shown in that section, the library \c .qbs file should also define the \c MYLIB_LIBRARY macro in order to mark symbols as exported: \code // lib/lib.qbs DynamicLibrary { name: "mylib" files: ["hello.cppm", "lib_global.h"] version: "1.0.0" Depends { name: "cpp" } cpp.defines: "MYLIB_LIBRARY" cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true // ... } \endcode For more details, see the complete \l{https://github.com/qbs/qbs/tree/2.5/tutorial/chapter-10-2}{example}. \section1 Import std module Starting with C++23, you can use the standard library as a module by using \c{import std;} or \c{import std.compat;}. In order to use \c{import std;}, you need to define the \l{CppStd} product somewhere in your project and add a dependency on it to products that require the \c{std} module: \code Project { CppStd {} CppApplication { Depends { name: "CppStd" } } } \endcode Here's a simple example that demonstrates the use of the standard library module: \snippet ../tutorial/chapter-10-3/main.cpp 0 The project file needs to be configured to use C++23 and enable the standard library module: \snippet ../tutorial/chapter-10-3/myproject.qbs 0 \note This feature requires a compiler and standard library that support the C++23 standard library module. Currently, this feature is experimental and may not be available in all toolchains. The full product file may look like this: \snippet ../tutorial/chapter-10-3/myproject.qbs 1 In order to use \c{import std.compat;}, you will also need to set the \l{CppStd::useStdCompat}{CppStd.useStdCompat} property to \c{true}: \code CppStd { useStdCompat: true } \endcode */ qbs-src-3.3.1/doc/codeattributions.qdoc0000644000175100017510000002375315232633614017514 0ustar runnerrunner/*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-ds_store.html attribution \target ds_store \title ds_store \brief MIT License Manipulate Finder .DS_Store files from Python Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/ds_store. \l{https://github.com/al45tair/ds_store}{Project Homepage}, upstream version: 1.1.2 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton 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. \endcode */ /*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-dmgbuild.html attribution \target dmgbuild \title dmgbuild \brief MIT License macOS command line utility to build disk images Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/dmgbuild. \l{https://github.com/al45tair/dmgbuild}{Project Homepage}, upstream version: 1.3.1 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton 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. \endcode */ /*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-mac_alias.html attribution \target mac_alias \title mac_alias \brief MIT License Generate/parse Mac OS Alias records from Python Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/mac_alias. \l{https://github.com/al45tair/mac_alias}{Project Homepage}, upstream version: 2.0.6 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton 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. \endcode */ /*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-biplist.html attribution \target biplist \title biplist \brief BSD 3-clause "New" or "Revised" License biplist is a library for reading/writing binary plists. Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/biplist. \l{https://bitbucket.org/wooster/biplist}{Project Homepage}, upstream version: 1.0.2 \badcode Copyright (c) 2010, Andrew Wooster \endcode \l{https://spdx.org/licenses/BSD-3-Clause.html}{BSD 3-clause "New" or "Revised" License}. \badcode Copyright (c) 2010, Andrew Wooster All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of biplist nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \endcode */ /*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-cppscanner.html attribution \target cppscanner \title cppscanner \brief MIT License The cpp scanner module is used to parse C/C++ files and to find includes in them. The sources can be found in src/plugins/scanner/cpp. \badcode Copyright (c) 2008 Roberto Raggi \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode // Copyright (c) 2008 Roberto Raggi // // 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. \endcode */ /*! \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-quickjs.html attribution \target quickjs \title QuickJS \brief MIT License The JavaScript engine used to evaluate all JavaScript code in \QBS project files. The sources can be found in src/shared/quickjs. \badcode Copyright (c) 2017-2021 Fabrice Bellard Copyright (c) 2017-2021 Charlie Gordon \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode QuickJS Javascript Engine Copyright (c) 2017-2021 Fabrice Bellard Copyright (c) 2017-2021 Charlie Gordon 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. \endcode */ qbs-src-3.3.1/doc/external-resources.qdoc0000644000175100017510000000655515232633614017765 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \externalpage https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW28 \title Adopt the @2x Naming Convention */ /*! \externalpage https://login.qt.io/ \title Qt Account */ /*! \externalpage https://www.qt.io/ide/ \title Qt Creator */ /*! \externalpage https://www.qt.io/download/ \title Qt SDK */ /*! \externalpage https://doc.qt.io/qt-5/licensing.html \title Qt Licensing */ /*! \externalpage https://www.gnu.org/licenses/gpl-2.0.html \title GNU General Public License, version 2 */ /*! \externalpage http://www.linfo.org/bsdlicense.html \title BSD */ /*! \externalpage https://chocolatey.org/packages/qbs \title Chocolatey */ /*! \externalpage https://www.macports.org/ports.php?by=name&substr=qbs \title MacPorts */ /*! \externalpage https://brew.sh/ \title Homebrew */ /*! \externalpage http://www.typescriptlang.org \title TypeScript */ /*! \externalpage http://www.typescriptlang.org/docs/handbook/compiler-options.html \title Compiler Options */ /*! \externalpage https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html \title DYLD documentation */ /*! \externalpage https://dmgbuild.readthedocs.io/en/latest/settings.html#background \title dmgbuild - Settings */ /*! \externalpage http://www.jrsoftware.org/isinfo.php \title Inno Setup */ /*! \externalpage http://nodejs.org \title Node.js */ /*! \externalpage http://wixtoolset.org \title Windows Installer XML Toolset */ /*! \externalpage https://clang.llvm.org/docs/JSONCompilationDatabase.html \title JSON Compilation Database Format Specification */ /*! \externalpage https://github.com/protocolbuffers/protobuf \title protoc */ /*! \externalpage https://github.com/nanopb/nanopb \title nanopb */ /*! \externalpage https://ccache.samba.org/ \title ccache */ /*! \externalpage https://ccache.samba.org/manual.html#_precompiled_headers \title ccache documentation about precompiled headers */ qbs-src-3.3.1/doc/man/0000755000175100017510000000000015232633614014023 5ustar runnerrunnerqbs-src-3.3.1/doc/man/man.qbs0000644000175100017510000000467215232633614015316 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Utilities Product { name: "qbs man page" type: ["manpage"] Depends { productTypes: ["qbsapplication"]; condition: updateManPage } Depends { name: "qbsbuildconfig" } property bool updateManPage: false property string help2ManFilePath: help2ManProbe.filePath Group { name: "man page" files: ["qbs.1"] qbs.install: qbsbuildconfig.installManPage qbs.installDir: "share/man/man1" } Group { name: "additional sections" files: ["see-also.h2m"] fileTags: ["man.section"] } Rule { condition: updateManPage multiplex: true // TODO: Remove in 1.14. explicitlyDependsOn: ["application"] property stringList explicitlyDependsOnFromDependencies: ["application"] inputs: ["man.section"] Artifact { filePath: "qbs.1" fileTags: ["manpage"] } prepare: { var help2ManExe = product.help2ManFilePath; if (!help2ManExe) throw "Cannot update man page: help2man not available"; if (Utilities.versionCompare(product.qbs.version, "1.9") < 0) throw "Cannot update man page: qbs >= 1.9 required"; var qbsApp; for (var i = 0; i < explicitlyDependsOn.application.length; ++i) { var artifact = explicitlyDependsOn.application[i]; if (artifact.product.name === "qbs_app") qbsApp = ModUtils.artifactInstalledFilePath(artifact); } var args = [qbsApp, "-o", output.filePath, "--no-info", "--name=the Qbs build tool"]; var sections = inputs ? inputs["man.section"] : []; for (var i = 0; i < sections.length; ++i) args.push("--include=" + sections[i].filePath); var help2ManCmd = new Command(help2ManExe, args); help2ManCmd.description = "creating man page"; var copyCmd = new JavaScriptCommand(); copyCmd.silent = true; copyCmd.sourceCode = function() { File.copy(output.filePath, FileInfo.joinPaths(product.sourceDirectory, output.fileName)); } return [help2ManCmd, copyCmd]; } } Probes.BinaryProbe { id: help2ManProbe names: ["help2man"] } } qbs-src-3.3.1/doc/man/see-also.h2m0000644000175100017510000000025515232633614016145 0ustar runnerrunner[SEE ALSO] For detailed help on a command, use the .B help command. For instance: .IP qbs help build .PP The full documentation for .B qbs is available at . qbs-src-3.3.1/doc/man/CMakeLists.txt0000644000175100017510000000020015232633614016553 0ustar runnerrunnerif (QBS_INSTALL_MAN_PAGE) install(FILES qbs.1 DESTINATION ${QBS_RESOURCES_INSTALL_DIR}/man/man1 COMPONENT qbs_docs) endif() qbs-src-3.3.1/doc/man/qbs.10000644000175100017510000000325715232633614014701 0ustar runnerrunner.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .TH QBS "1" "April 2026" "qbs 3.3.0" "User Commands" .SH NAME qbs \- the Qbs build tool .SH SYNOPSIS .B qbs [\fI\,command\/\fR] [\fI\,command parameters\/\fR] .SH DESCRIPTION Qbs 3.3.0, a cross\-platform build tool. .SS "Built-in commands:" .TP build Build (parts of) a project. This is the default command. .TP clean Remove the files generated during a build. .TP dump\-nodes\-tree Dumps the nodes in the build graph to stdout. .TP generate Generate project files for another build tool. .TP help Show general or command\-specific help. .TP install Install (parts of) a project. .TP list\-products Lists all products in the project, including sub\-projects. .TP resolve Resolve a project without building it. .TP run Run an executable generated by building a project. .TP session Starts a session for an IDE. .TP shell Open a shell with a product's environment. .TP show\-version Print the Qbs version number to stdout. .TP status Show the status of files in the project directory. .TP update\-timestamps Mark the build as up to date. .SS "Auxiliary commands:" .TP config This tool manages qbs settings. .TP config\-ui This tool displays qbs settings in a GUI. .TP create\-project This tool creates a qbs project from an existing source tree. .TP setup\-android This tool creates qbs profiles from Android SDK and NDK installations. .TP setup\-qt This tool creates qbs profiles from Qt versions. .TP setup\-toolchains This tool creates qbs profiles from toolchains. .SH "SEE ALSO" For detailed help on a command, use the .B help command. For instance: .IP qbs help build .PP The full documentation for .B qbs is available at . qbs-src-3.3.1/doc/doc.qbs0000644000175100017510000000737615232633614014541 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Probes Project { references: ["man/man.qbs"] Product { name: "qbs documentation" builtByDefault: false type: Qt.core.config.contains("cross_compile") ? ["qbsdoc.qdoc-html-fixed"] : [ "qbsdoc.qdoc-html-fixed", "qch"] property string fixedHtmlDir: FileInfo.joinPaths(buildDirectory, "qdoc-html-fixed") Depends { name: "Qt.core" } Depends { name: "qbsbuildconfig" } Depends { name: "qbsversion" } Probes.BinaryProbe { id: pythonProbe names: ["python3", "python"] // on Windows, there's no python3 } property string pythonPath: pythonProbe.found ? pythonProbe.filePath : undefined files: [ "../README.md", "../CONTRIBUTING.md", "classic.css", "external-resources.qdoc", "fixnavi.pl", "howtos.qdoc", "qbs.qdoc", "tutorial.qdoc", "qbs-online.qdocconf", "config/*.qdocconf", "config/style/qt5-sidebar.html", "appendix/**/*", "reference/**/*", "templates/**/*", "images/**", "targets/**", ] Group { name: "main qdocconf file" files: "qbs.qdocconf" fileTags: "qdocconf-main" } Group { name: "fix-imports script" files: ["fix-qmlimports.py"] fileTags: ["qbsdoc.fiximports"] } property string versionTag: qbsversion.version.replace(/\.|-/g, "") Qt.core.qdocEnvironment: [ "QBS_VERSION=" + qbsversion.version, "SRCDIR=" + path, "QT_INSTALL_DOCS=" + Qt.core.docPath, "QBS_VERSION_TAG=" + versionTag ] Rule { inputs: ["qdoc-png"] explicitlyDependsOn: ["qbsdoc.fiximports"] multiplex: true outputFileTags: ["qdoc-html", "qbsdoc.dummy"] // TODO: Hack. Rule injection to the rescue? outputArtifacts: [{filePath: "dummy", fileTags: ["qbsdoc.dummy"]}] prepare: { if (!product.pythonPath) throw "Python executable was not found"; var scriptPath = explicitlyDependsOn["qbsdoc.fiximports"][0].filePath; var htmlDir = FileInfo.path(FileInfo.path(inputs["qdoc-png"][0].filePath)); var fixCmd = new Command(product.pythonPath, [scriptPath, htmlDir]); fixCmd.description = "fixing bogus QML import statements"; return [fixCmd]; } } Rule { inputs: ["qdoc-html"] Artifact { filePath: FileInfo.joinPaths(product.fixedHtmlDir, input.fileName) fileTags: ["qbsdoc.qdoc-html-fixed"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } Group { fileTagsFilter: ["qbsdoc.qdoc-html-fixed"] qbs.install: qbsbuildconfig.installHtml qbs.installDir: qbsbuildconfig.docInstallDir qbs.installSourceBase: product.fixedHtmlDir } Group { fileTagsFilter: ["qdoc-css", "qdoc-png"] qbs.install: qbsbuildconfig.installHtml qbs.installDir: qbsbuildconfig.docInstallDir qbs.installSourceBase: Qt.core.qdocOutputDir } Group { fileTagsFilter: ["qch"] qbs.install: qbsbuildconfig.installQch qbs.installDir: qbsbuildconfig.docInstallDir } } } qbs-src-3.3.1/doc/howtos.qdoc0000644000175100017510000007314615232633614015456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage tutorial-8.html \nextpage reference.html \page howtos.html \title How-tos This page provides concrete instructions for common scenarios. \list \li \l{How do I build a Qt-based project?} \li \l{How do I make my app build against my library?} \li \l{How do I build release with debug information?} \li \l{How do I separate and install debugging symbols?} \li \l{How do I use precompiled headers?} \li \l{How do I make use of rpaths?} \li \l{How do I make sure my generated sources are getting compiled?} \li \l{How do I run my autotests?} \li \l{How do I use ccache?} \li \l{How do I create a module for a third-party library?} \li \l{How do I build against libraries that provide pkg-config files?} \li \l{How do I create application bundles and frameworks on iOS, macOS, tvOS, and watchOS?} \li \l{How do I apply C/C++ preprocessor macros to only a subset of the files in my product?} \li \l{How do I disable a compiler warning?} \li \l{How do I make the state of my Git repository available to my source files?} \li \l{How do I limit the number of concurrent jobs for the linker only?} \li \l{How do I add QML files to a project?} \li \l{How do I define a reusable Group of files that can be included in other \QBS files?} \li \l{How do I access properties of a base type?} \li \l{How do I print the value of a property?} \li \l{How do I debug \QBS scripts?} \li \l{How do I sign an application for an Apple platform?} \endlist \section1 How do I build a Qt-based project? First of all, your project files need to declare \l{Depends}{dependencies} on \l{Qt} modules. To build the project, you need a matching \e profile. The following commands set up and use a Qt-specific profile: \code $ qbs setup-qt /usr/bin/qmake qt $ cd my_project $ qbs profile:qt \endcode If you plan to use this profile a lot, consider making it the default one: \code $ qbs config defaultProfile qt $ cd my_project $ qbs \endcode See \l{Managing Qt Versions} for more details. \note These instructions are only relevant for building from the command line. If you use Qt Creator, profiles are set up automatically from the information in the Kit. \section1 How do I make my app build against my library? This is achieved by introducing a \e dependency between the two products using the \l{Depends} item. Here is a simple, but complete example: \code Project { CppApplication { name : "the-app" files : [ "main.cpp" ] Depends { name: "the-lib" } } DynamicLibrary { name: "the-lib" Depends { name: "cpp" } files: [ "lib.cpp", "lib.h", ] Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } } } \endcode The product \c the-lib is a dynamic library. It expects other products to build against it, and for that purpose, it exports an include path (via an \l{Export} item), so that the source files in these products can include the library's header file. The product \c the-app is an application that expresses its intent to link against \c the-lib by declaring a dependency on it. Now \c main.cpp can include \c lib.h (because of the exported include path) and the application binary will link against the library (because the linker \l{Rule}{rule} in the \l{cpp} module considers library dependencies as inputs). \note In a non-trivial project, the two products would not be defined in the same file. Instead, you would put them into files of their own and use the \l{Project::references}{Project.references} property to pull them into the project. The product definitions would stay exactly the same. In particular, their location in the project tree is irrelevant to the relationship between them. \section2 Choosing Between Dynamic and Statically-built Qt Projects To build \c "the-lib" as either a dynamic or static library, depending on how Qt was built, you can use the following code: \code Product { name: "the-lib" type: Qt.core.staticBuild ? "staticlibrary" : "dynamiclibrary" Depends { name: "Qt.core" } // ... } \endcode \section1 How do I build release with debug information? You can simply use the \c{"profiling"} \l{qbs::buildVariant}{qbs.buildVariant}: \code qbs build qbs.buildVariant:profiling \endcode \section1 How do I separate and install debugging symbols? First, you need to set the \l{cpp::debugInformation}{cpp.debugInformation} and \l{cpp::separateDebugInformation}{cpp.separateDebugInformation} properties to \c true or use some conditional expression in your product: \code CppApplication { // ... cpp.debugInformation: qbs.buildVariant !== "release" cpp.separateDebugInformation: true } \endcode Now, you can install your \l{Application}{application}, \l{DynamicLibrary}{dynamic library} or \l{LoadableModule}{loadable module} among with its debugging symbols as follows: \code CppApplication { // ... install: true installDir: "bin" installDebugInformation: true debugInformationInstallDir: "bin" } \endcode If you are not using \l{List of Convenience Items}{convenience items}, you can install debug symbols manually using the \l{Group} item. If the \l{cpp::separateDebugInformation}{cpp.separateDebugInformation} property is set to \c true, \QBS will create debugging symbols with the corresponding file tags \c "debuginfo_app" (for an application), \c "debuginfo_dll" (for a dynamic library), or \c "debuginfo_loadablemodule" (for a macOS plugin). \code Product { type: "application" Depends { name: "cpp" } cpp.debugInformation: qbs.buildVariant !== "release" cpp.separateDebugInformation: true Group { fileTagsFilter: cpp.separateDebugInformation ? ["debuginfo_app"] : [] qbs.install: true qbs.installDir: "bin" qbs.installSourceBase: buildDirectory } } \endcode If you're building a shared library, you need to use the \c "debuginfo_dll" tag instead: \code Product { type: "dynamic_library" // ... Group { fileTagsFilter: cpp.separateDebugInformation ? ["debuginfo_dll"] : [] qbs.install: true qbs.installDir: "lib" qbs.installSourceBase: buildDirectory } } \endcode If you're building a macOS plugin, you need to use the \c "debuginfo_loadablemodule" tag instead: \code Product { type: "loadablemodule" // ... Group { fileTagsFilter: cpp.separateDebugInformation ? ["debuginfo_loadablemodule"] : [] qbs.install: true qbs.installDir: "PlugIns" qbs.installSourceBase: buildDirectory } } \endcode \section1 How do I use precompiled headers? If you use a \l Group item to add a precompiled header file to a product and mark it with the \l{filetags-cpp}{relevant file tag} (\c c_pch_src, \c cpp_pch_src, \c objc_pch_src, or \c objcpp_pch_src), it is used automatically. Only one precompiled header is allowed per product and language. For example: \code CppApplication { name: "the-app" files: ["main.cpp"] Group { files: ["precompiled-header.pch"] fileTags: ["cpp_pch_src"] } } \endcode \section1 How do I make use of rpaths? rpath designates the run-time search path used by the dynamic linker when loading libraries on UNIX platforms. This concept does not apply to Windows. Suppose you have a project with two dynamic library products \c LibraryA and \c LibraryB and one dependent application product. Also, \c LibraryB depends on \c LibraryA. The application is installed to the \c bin folder and the libraries are installed to the \c lib folder next to the \c bin folder. You want the application to be able to find the dependent libraries relative to its own location. This can be achieved by usage of the \l{cpp::rpaths}{cpp.rpaths} property. First, you need to set \l{cpp::rpaths}{cpp.rpaths} in your libraries so they can find dependent libraries in the same folder where they are located. This can be done as follows: \snippet ../examples/rpaths/rpaths.qbs 0 We are setting \l{cpp::rpaths}{cpp.rpaths} to \l{cpp::rpathOrigin}{cpp.rpathOrigin} which expands to \c "$ORIGIN" on Linux and to \c "@loader_path" on macOS. On macOS you also need to set \l{cpp::sonamePrefix}{cpp.sonamePrefix} to \c "@rpath" to tell the dynamic linker to use RPATHs when loading this library. \c LibraryB looks exactly the same: \snippet ../examples/rpaths/rpaths.qbs 1 In a real project, it might be a good idea to move common properties to some base item and inherit it in library items. The application item is a bit different. It sets \l{cpp::rpaths}{cpp.rpaths} to the \c "lib" folder which is located one level up from the \c bin folder: \snippet ../examples/rpaths/rpaths.qbs 2 \section1 How do I make sure my generated sources are getting compiled? The rules in a \QBS project do not care whether its inputs are actual source files listed on the right-hand side of a \l{Product::files}{files} property or artifacts that were generated by another rule. For instance, the C++ compiler rule considers all input files of type "cpp", no matter how they got into the product. The following example project demonstrates this. One of its source files exists in the repository, the other one is generated at build time. Both are getting compiled the same way. \note Do not try to add the generated files to a \c files property. Declaring them as rule outputs is all that is needed to make \QBS know about them. \code import qbs.TextFile CppApplication { files: ["impl.cpp", "impl.h"] cpp.includePaths: sourceDirectory Rule { multiplex: true Artifact { filePath: "main.cpp"; fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("#include "); f.writeLine("int main()"); f.writeLine("{"); f.writeLine(" return functionFromImpl();"); f.writeLine("}"); f.close(); }; return cmd; } } } \endcode \section1 How do I run my autotests? There are two simple things you need to do in your project. Firstly, you mark your test executables as such. This is done by adding the tag \c{"autotest"} to the product type: \code CppApplication { name: "test1" type: base.concat("autotest") // ... } \endcode The second step is to instantiate an \l AutotestRunner product in your project: \code Project { // ... AutotestRunner { name: "run_my_tests" } } \endcode Building an AutotestRunner product does not produce artifacts, but triggers execution of all applications whose products are tagged as autotests: \code $ qbs -p run_my_tests test1: PASS test2: PASS test3: FAIL ... \endcode See the \l{AutotestRunner}{AutotestRunner documentation} for how to fine-tune the behavior. \section1 How do I use ccache? \l ccache is a popular C/C++ compiler cache on Unix to speed up compiling the same content multiple times. \QBS excels at tracking dependencies and avoiding needless recompilations, so for linear development of one project and configuration using ccache has little benefit. But if you switch between revisions of a project, or build the same project with different configurations, a global cache like ccache can speed up compilations significantly. ccache can be used by setting up symbolic links to compiler executables (such as \c g++, \c gcc) in the file system. In this setup, the use of ccache is transparent to \QBS. If you prefer to call ccache explicitly, you should set \l{cpp::compilerWrapper}{cpp.compilerWrapper} to \c ccache. \note Using precompiled headers might prevent ccache from actually using cached results. To work around this, you can set \c{sloppiness=pch_defines,time_macros} in your local ccache options. See the \l{ccache documentation about precompiled headers} for further details. \section1 How do I create a module for a third-party library? If you have pre-built binary files in your source tree, you can create modules for them and then introduce dependencies between your project and the modules to pull in the functionality of a third-party library. Create the following folder structure to store the module files: \code $projectroot/modules/ThirdParty \endcode Then create a file in the directory that specifies the module properties for each supported toolchain. The filename must have the \c .qbs extension. The module will be pulled in if a product declares a dependency on it. In the following example, \c lib1.dylib is a multi-architecture library containing both 32-bit and 64-bit code. \code ---ThirdParty.qbs--- Module { Depends { name: "cpp" } cpp.includePaths: ["/somewhere/include"] Properties { condition: qbs.targetOS.includes("android") cpp.dynamicLibraries: ["/somewhere/android/" + Android.ndk.abi + "/lib1.so"] } Properties { condition: qbs.targetOS.includes("macos") cpp.dynamicLibraries: ["/somewhere/macos/lib1.dylib"] } Properties { condition: qbs.targetOS.includes("windows") && qbs.architecture === "x86" cpp.dynamicLibraries: ["/somewhere/windows_x86/lib1.lib"] } Properties { condition: qbs.targetOS.includes("windows") && qbs.architecture === "x86_64" cpp.dynamicLibraries: ["/somewhere/windows_x86_64/lib1.lib"] } } \endcode Finally, declare dependencies on \c ThirdParty in your project: \code CppApplication { name: "the-app" files: ["main.cpp"] Depends { name: "ThirdParty" } } \endcode \section1 How do I create application bundles and frameworks on iOS, macOS, tvOS, and watchOS? Creating an application bundle or framework is achieved by introducing a dependency on the \l{bundle} module and setting the \l{bundle::isBundle} {bundle.isBundle} property to \c true. Here is a simple example for an application: \code Application { Depends { name: "cpp" } Depends { name: "bundle" } bundle.isBundle: true name: "the-app" files: ["main.cpp"] } \endcode and for a framework: \code DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } bundle.isBundle: true name: "the-lib" files: ["lib.cpp", "lib.h"] } \endcode \QBS also supports building static frameworks. You can create one by replacing the \l{DynamicLibrary} item with a \l{StaticLibrary} item in the example above. \note When using the \l{Application} item (or convenience items, such as \l{CppApplication}, \l{DynamicLibrary}, and \l{StaticLibrary}), your products will be built as bundles on Apple platforms by default (this behavior is subject to change in a future release). To explicitly control whether your product is built as a bundle, set the \c bundle.isBundle property. Setting the \l{Product::}{consoleApplication} property of your product will also influence whether your product is built as a bundle. Building your application against your framework is the same as linking a normal dynamic or static library; see the \l{How do I make my app build against my library?} section for an example. \section1 How do I build against libraries that provide pkg-config files? Just add a \l Depends item that matches the name of the pkg-config module, set the \l Product::qbsModuleProviders property to \c "qbspkgconfig", and \QBS will employ \l{https://www.freedesktop.org/wiki/Software/pkg-config}{pkg-config} to find the headers and libraries if no matching \QBS module can be found. For instance, to build against the OpenSSL library, you would write this: \code qbsModuleProviders: "qbspkgconfig" Depends { name: "openssl" } \endcode That's it. The pkg-config behavior can be fine-tuned via the \l qbspkgconfig provider. Internally, this functionality is implemented via \l {Module Providers} \section1 How do I apply C/C++ preprocessor macros to only a subset of the files in my product? Use a \l{Group} item to define a subset of project files. To add macros within the group, you need to use the \c outer.concat property, because you are adding macros to those specified in the outer scope. In the following example, \c MACRO_EVERYWHERE is defined for all files in the \l{Product} unless a Group overrides the macro, whereas \c MACRO_GROUP is only defined for \c groupFile.cpp. \code Product { Depends { name: "cpp" } cpp.defines: ["MACRO_EVERYWHERE"] Group { cpp.defines: outer.concat("MACRO_GROUP") files: "groupFile.cpp" } } \endcode The \c cpp.defines statements inside a \c Group only apply to the files in that \c Group, and therefore you cannot use a \c Group to include a bunch of files and globally visible macros. The macros must be specified in a \l{Properties} item at the same level as the \c Group if they need to be visible to files outside the \c Group: \code Product { Depends { name: "cpp" } Group { condition: project.supportMyFeature files: "myFile.cpp" } property stringList commonDefines: ["ONE", "TWO"] Properties { condition: project.supportMyFeature cpp.defines: commonDefines.concat("MYFEATURE_SUPPORTED") } } \endcode \section1 How do I disable a compiler warning? You can use the \l {cpp::commonCompilerFlags}{cpp.commonCompilerFlags} property to pass flags to the compiler. For example, to disable deprecation warnings: \code CppApplication { // ... readonly property bool isMsvc: qbs.toolchain.includes("msvc") cpp.commonCompilerFlags: isMsvc ? "/wd4996" : "-Wno-deprecated-declarations" } \endcode It is also possible to disable all warnings at once by setting the \l {cpp::commonCompilerFlags}{cpp.warningLevel} property to \c "none". Usually this approach is discouraged, but it can be useful in some cases, such as when compiling third party code: \code Group { cpp.warningLevel: "none" files: [ "3rdparty.h", "3rdparty.cpp" ] } \endcode \section1 How do I make the state of my Git repository available to my source files? Add a dependency to the \l{vcs} module to your product: \code CppApplication { // ... Depends { name: "vcs" } // ... } \endcode Your source files will now have access to a macro whose value is a string representing the current Git or Subversion HEAD: \code #include #include int main() { std::cout << "I was built from " << VCS_REPO_STATE << std::endl; } \endcode This value is also available via the \l{vcs::repoState}{vcs.repoState} property. \section1 How do I limit the number of concurrent jobs for the linker only? \target job-pool-howto While it is usually desirable to run as many compiler jobs as there are CPU cores, the same is not true for linker jobs. The reason is that linkers are typically I/O bound rather than CPU bound. When building large libraries, they also tend to use up enormous amounts of memory. Therefore, we'd like to make sure that only a few linkers are running at the same time without limiting other types of jobs. In \QBS, this is achieved via \e{job pools}. There are several ways to make use of them. Firstly, you can provide a limit via the command line: \code $ qbs --job-limits linker:4 \endcode The above call instructs \QBS to run at most four linker instances at the same time, while leaving the general number of concurrent jobs at the default value, which is derived from the number of CPU cores. The \c linker string on the command line refers to the job pool of the same name, which the \l{cpp-job-pools}{cpp module} assigns to all its commands that invoke a linker. Secondly, you can set a limit via the settings, either generally or for a specific profile: \code $ qbs config preferences.jobLimit.linker 4 $ qbs config profiles.myprofile.preferences.jobLimit.linker 2 \endcode And finally, you can also set the limit per project or per product, using a \l JobLimit item: \code Product { name: "my_huge_library" JobLimit { jobPool: "linker" jobCount: 1 } // ... } \endcode The above construct ensures that this specific library is never linked at the same time as any other binary in the project. Job limits set on the command line override those from the settings, which in turn override the ones defined within a project. Use the \c{--enforce-project-job-limits} option to give the job limits defined via \c JobLimit items maximum precedence. \section1 How do I add QML files to a project? The simplest way to add QML files to a project is to add them to a \l {https://doc.qt.io/qt/resources.html}{Qt resource file}: \code QtGuiApplication { // ... files: "main.cpp" Group { prefix: "qml/" files: ["main.qml", "HomePage.qml"] fileTags: ["qt.qml.qml", "qt.core.resource_data"] } } \endcode In the example above, we declare each QML file as having the \l {filetags-qtcore}{"qt.core.resource_data"} file tag. This ensures that it is added to a generated resource file. \section1 How do I define a reusable Group of files that can be included in other \QBS files? Suppose you have an application and tests for that application, and that the project is structured in the following way: \badcode ├── app │ ├── app.qbs │ ├── ... │ └── qml │ └── ui │ ├── AboutPopup.qml │ └── ... ├── my-project.qbs └── tests ├── tst_app.cpp ├── ... └── tests.qbs \endcode Both projects need access to the QML files used by the application. To demonstrate how this can be done, we'll create a file named \c qml-ui.qbs and put it in the \c app/qml/ui directory: \code Group { prefix: path + "/" fileTags: ["qt.qml.qml", "qt.core.resource_data"] files: [ "AboutPopup.qml", // ... ] } \endcode This Group is a variation of the one in the \l {How do I add QML files to a project?}{section above}. If no prefix is specified, the file names listed in the \c files property are resolved relative to the \e importing product's (e.g. \c app.qbs) directory. For that reason, we set the prefix to inform \QBS that the file names should be resolved relative to the \e imported item instead: \c qml-ui.qbs. Conveniently, this also means that we don't need to specify the path prefix for each file. The application can then import the file like so: \code import "qml/ui/qml-ui.qbs" as QmlUiFiles QtGuiApplication { // ... files: "main.cpp" QmlUiFiles {} } \endcode The tests can use a relative path to import the file: \code import "../app/qml/ui/qml-ui.qbs" as QmlUiFiles QtGuiApplication { // ... files: "tst_app.cpp" QmlUiFiles {} } \endcode \section1 How do I access properties of a base type? You can use the \l base property. For example, to append to a list of files that come from the base type, you can use \c {base.concat()}: \code // TestBase.qbs QtGuiApplication { files: [ "TestCaseBase.h", "TestCaseBase.cpp" ] } \endcode \code // tst_stuff.qbs TestBase { files: base.concat(["tst_stuff.cpp"]) } \endcode See \l {Special Property Values} for more details. \section1 How do I print the value of a property? Use the \l {Console API}{console API}. For example, suppose your project is not built the way you expect it to be, and you suspect that \c qbs.targetOS has the wrong value: \code readonly property bool unix: qbs.targetOS.includes("unix") \endcode To find out the value of \c qbs.targetOS, use \c {console.info()}: \code readonly property bool unix: { console.info("qbs.targetOS: " + qbs.targetOS) return qbs.targetOS.includes("unix") } \endcode It is also possible to throw an exception with the text saying what is wrong - this might be useful if the property contains invalid or unsupported value: \code readonly property bool unix: { if (qbs.targetOS.includes("darwin")) throw "Apple platforms are not supported"; return qbs.targetOS.includes("unix") } \endcode \section1 How do I debug \QBS scripts? To debug the value of a specific property, see the \l{How do I print the value of a property} section. Similar debugging techniques could be used within \l{Rule}{Rules} or \c .js files. It is also possible to increase \QBS' logging level using the \c --more-verbose (\c -v) option of the \c{qbs build} command: \code qbs build -v config:release \endcode \QBS uses the Qt Categorized Logging system which allows to configure logging categories in \l{https://doc.qt.io/qt-5/qloggingcategory.html#configuring-categories}{multiple ways}. For example, to enable debug logging for the \c moduleloader category, use the following command: \code QT_LOGGING_RULES="qbs.moduleloader.debug=true" qbs resolve \endcode To list all the files in the project directory and show whether they are known to qbs in the respective configuration, use the \c{qbs status} command: \code qbs status config:release \endcode \section1 How do I sign an application for an Apple platform? To sign an application for an Apple platform, you need to use the \l{codesign} module. \code Depends { name: "codesign" } \endcode Several properties should be set to do signing as shown below. Make sure that bundle and team indentifiers match the one used for signing: \code bundle.identifierPrefix: "com.johndoe" codesign.teamIdentifier: "John Doe" \endcode It is also possible to use an ID of the team identifier instead of a name: \code codesign.teamIdentifier: "1234ABCDEF" \endcode \QBS will then try to find the matching signing identity and provisioning profile based on \l{codesign::signingType}{codesign.signingType}. It is also possible to specify \l{codesign::signingIdentity}{codesign.signingIdentity} manually: \code codesign.signingIdentity: "Apple Development: johndoe@apple.com (ABCDEF1234)" \endcode It is also possible to use an ID of the signing identity instead of a name: \code codesign.signingIdentity: "ABCDEF1234567890ABCDEF1234567890ABCDEF12" \endcode If \QBS cannot find the suitable provisioning profile, you can specify it manually as well: \code codesign.provisioningProfile: "abcdef12-1234-5678-1111-abcdef123456" \endcode */ qbs-src-3.3.1/doc/classic.css0000644000175100017510000001032015232633614015377 0ustar runnerrunnerBODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: Arial, Geneva, Helvetica, sans-serif; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 100%; } h3.fn,span.fn { background-color: #eee; border-width: 1px; border-style: solid; border-color: #ddd; font-weight: bold; padding: 6px 0px 6px 10px; margin: 42px 0px 0px 0px; } hr { border: 0; color: #a0a0a0; background-color: #ccc; height: 1px; width: 100%; text-align: left; margin: 34px 0px 34px 0px; } table.valuelist { border-width: 1px 1px 1px 1px; border-style: solid; border-color: #dddddd; border-collapse: collapse; background-color: #f0f0f0; } table.indextable { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 110%; } table td.largeindex { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 120%; } table.valuelist th { border-width: 1px 1px 1px 2px; padding: 4px; border-style: solid; border-color: #666; color:white; background-color:#666; } th.titleheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 110%; } th.largeheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 120%; } p { margin-left: 4px; margin-top: 8px; margin-bottom: 8px; } a:link { color: #0046ad; text-decoration: none } a:visited { color: #672967; text-decoration: none } a.obsolete { color: #661100; text-decoration: none } a.compat { color: #661100; text-decoration: none } a.obsolete:visited { color: #995500; text-decoration: none } a.compat:visited { color: #995500; text-decoration: none } body { background: #ffffff; color: black } table.generic, table.annotated { border-width: 1px; border-color:#bbb; border-style:solid; border-collapse:collapse; } table td.memItemLeft { width: 180px; padding: 2px 0px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; white-space: nowrap } table td.memItemRight { padding: 2px 8px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; } table tr.odd { background: #f0f0f0; color: black; } table tr.even { background: #e4e4e4; color: black; } table.annotated th { padding: 3px; text-align: left } table.annotated td { padding: 3px; } table tr pre { padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; border: none; background: none } tr.qt-style { background: #96E066; color: black } body pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } table tr.qt-code pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } span.preprocessor, span.preprocessor a { color: darkblue; } span.comment { color: darkred; font-style: italic } span.string,span.char { color: darkgreen; } .title { text-align: center } .subtitle { font-size: 0.8em } .small-subtitle { font-size: 0.65em } .qmlitem { padding: 0; } .qmlname { white-space: nowrap; font-weight: bold; font-size: 125%; } .qmltype { font-weight: bold; font-size: 125%; } .qmlproto, .qmldoc { // border-top: 1px solid #84b0c7; } .qmlproto { padding: 0; //background-color: #e4e4e4;//#d5e1e8; //font-weight: bold; //-webkit-border-top-left-radius: 8px; //-webkit-border-top-right-radius: 8px; //-moz-border-radius-topleft: 8px; //-moz-border-radius-topright: 8px; } .qmldoc { border-top: 1px solid #e4e4e4; //padding: 2px 5px; //background-color: #eef3f5; //border-top-width: 0; //-webkit-border-bottom-left-radius: 8px; //-webkit-border-bottom-right-radius: 8px; //-moz-border-radius-bottomleft: 8px; //-moz-border-radius-bottomright: 8px; } .qmldoc p, .qmldoc dl, .qmldoc ul { //margin: 6px 0; } *.qmlitem p { //margin-top: 0px; //margin-bottom: 0px; } qbs-src-3.3.1/doc/fix-qmlimports.py0000755000175100017510000001322015232633614016616 0ustar runnerrunner#!/usr/bin/env python3 ############################################################################# ## ## Copyright (C) 2017 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# from __future__ import print_function import os import glob import errno import sys import argparse import shutil import urllib from subprocess import Popen, PIPE import re from collections import Counter import platform useShell = (platform.system() == 'Windows') gotSoup = True try: from bs4 import BeautifulSoup except ImportError: print('Warning: Failed to import BeautifulSoup. Some functionality is disabled.', file=sys.stderr) gotSoup = False qmlTypeString = ' QML Type' # Modifies a QML Type reference page to look like a generic # JavaScript reference - Removes the 'QML Type' strings from # the titles as well as the import statement information. # This is used in the Installer Framework docs, which contain # JS reference documentation generated using commands specific # to documenting QML code. # # Parameters: a Beautiful Soup object constructed with an opened # html file to process. # # Returns True if the element tree was modified, False otherwise def modifyQMLReference(soup): pageTitle = soup.head.title.string soup.head.title.string = pageTitle.replace(qmlTypeString, '') for t in soup.find_all('h1', class_='title'): t.string = t.string.replace(qmlTypeString, '') for table in soup.find_all('table'): td = table.find('td') if td and td.string: if 'Import Statement:' in td.string: td.parent.extract() return True return False if __name__ == '__main__': parser = argparse.ArgumentParser( description = """Removes bogus import statements from the offline docs""") parser.add_argument('outputdir', help = 'output directory of the generated html files') args = parser.parse_args() if not gotSoup: print('Error: This script requires the Beautiful Soup library.', file=sys.stderr) sys.exit(1) if not os.path.isdir(args.outputdir): print('Error: No such directory:', args.outputdir, file=sys.stderr) sys.exit(1) # compile a list of all html files in the outputdir htmlFiles = [] for f in os.listdir(args.outputdir): fullPath = os.path.join(args.outputdir, f) if os.path.isdir(fullPath): continue if os.path.splitext(f)[1] == '.html': htmlFiles.append(fullPath) sys.stdout.flush() modified = {} pre_blocks = {} fileCount = 0 progStep = max(16, len(htmlFiles)) / 16 for html in htmlFiles: fileCount += 1 if not (fileCount % progStep): print('.', end='') sys.stdout.flush() with open(html, 'r+', encoding='utf8') as file_: try: soup = BeautifulSoup(file_, 'lxml') actions = [] val = 0 if modifyQMLReference(soup): actions.append('Removed QML type info') for a in actions: modified[a] = modified.get(a, 0) + 1 if actions: file_.seek(0) file_.write(str(soup)) file_.truncate() file_.close() except (AttributeError, KeyError): print('\nFailed to parse', html, ':', sys.exc_info()[0], file=sys.stderr) except IOError as e: print('\nError:', e, file=sys.stderr) except ValueError as e: print('\nError:', e, file=sys.stderr) if 'lxml' in str(e): print('(If using pip, try \"pip install lxml\")', file=sys.stderr) quit(1) for k, v in modified.items(): print ('\n\t', k, 'in %d files' % v, end='') pb = pre_blocks.get(k, 0) if pb: print (' (', pb, '
 blocks)', sep='', end='')
    print('\n')
qbs-src-3.3.1/doc/config/0000755000175100017510000000000015232633614014515 5ustar  runnerrunnerqbs-src-3.3.1/doc/config/macros.qdocconf0000644000175100017510000000560115232633614017521 0ustar  runnerrunnermacro.QBS               = "Qbs"
macro.qbsversion        = $QBS_VERSION

macro.defaultvalue      = "Default:"
macro.nodefaultvalue    = "Default: Undefined"
macro.appleproperty     = "This property is specific to Apple platforms."
macro.androidproperty   = "This property is specific to Android platforms."
macro.unixproperty      = "This property is specific to Unix platforms."
macro.windowsproperty   = "This property is specific to Windows."
macro.baremetalproperty = "This property is specific to bare-metal platforms."
macro.funsince.HTML     = "

This function was introduced in version \1.

" macro.aacute.HTML = "á" macro.Aring.HTML = "Å" macro.aring.HTML = "å" macro.Auml.HTML = "Ä" macro.author = "\\b{Author:}" macro.BR.HTML = "
" macro.copyright.HTML = "©" macro.eacute.HTML = "é" macro.gui = "\\b" macro.HR.HTML = "
" macro.iacute.HTML = "í" macro.key = "\\b" macro.macos = "macOS" macro.menu = "\\b" macro.oslash.HTML = "ø" macro.ouml.HTML = "ö" macro.QA = "\\e{Qt Assistant}" macro.QD = "\\e{Qt Designer}" macro.QL = "\\e{Qt Linguist}" macro.QQV = "\\e{Qt QML Viewer}" macro.param = "\\e" macro.raisedaster.HTML = "*" macro.rarrow.HTML = "→" macro.reg.HTML = "®" macro.return = "Returns" macro.starslash = "\\c{*/}" macro.begincomment = "\\c{/*}" macro.endcomment = "\\c{*/}" macro.uuml.HTML = "ü" macro.mdash.HTML = "—" macro.pi.HTML = "Π" macro.beginqdoc.HTML = "/*!" macro.endqdoc.HTML = "*/" macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv" macro.beginfloatleft.HTML = "
" macro.beginfloatright.HTML = "
" macro.endfloat.HTML = "
" macro.clearfloat.HTML = "
" macro.emptyspan.HTML = "" macro.CMAKE = "CMake" # Embed YouTube content by video ID - Example: \youtube dQw4w9WgXcQ # Also requires a .jpg thumbnail for offline docs. In .qdocconf, add: # # HTML.extraimages += images/dQw4w9WgXcQ.jpg # qhp.ProjectName.extraFiles += images/dQw4w9WgXcQ.jpg # macro.youtube.HTML = "
\n\n" \ "
\n" qbs-src-3.3.1/doc/config/style/0000755000175100017510000000000015232633614015655 5ustar runnerrunnerqbs-src-3.3.1/doc/config/style/qt5-sidebar.html0000644000175100017510000000152115232633614020662 0ustar runnerrunner

Qbs Manual

qbs-src-3.3.1/doc/config/qbs-project.qdocconf0000644000175100017510000000220115232633614020457 0ustar runnerrunnerinclude($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf) include($QT_INSTALL_DOCS/global/compat.qdocconf) include($QT_INSTALL_DOCS/global/fileextensions.qdocconf) project = "Qbs" description = "Qbs Manual" #Words to ignore for auto-linking ignorewords += macOS headerdirs = sourcedirs = .. imagedirs = ../images ../templates/images exampledirs = .. include(macros.qdocconf) sources.fileextensions = "*.qdoc" qhp.projects = Qbs qhp.Qbs.file = qbs.qhp qhp.Qbs.namespace = org.qt-project.qbs.$QBS_VERSION_TAG qhp.Qbs.virtualFolder = doc qhp.Qbs.indexTitle = Qbs qhp.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.customFilters.Qbs.name = Qbs $QBS_VERSION qhp.Qbs.customFilters.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.indexRoot = qhp.Qbs.subprojects = manual qhp.Qbs.subprojects.manual.title = Qbs Manual qhp.Qbs.subprojects.manual.indexTitle = Qbs Manual qhp.Qbs.subprojects.manual.type = manual # Doxygen compatibility commands macro.see = "\\sa" macro.function = "\\fn" navigation.homepage = "Qbs Manual" buildversion = "Qbs $QBS_VERSION" qbs-src-3.3.1/doc/fixnavi.pl0000644000175100017510000001473615232633614015264 0ustar runnerrunner#! /usr/bin/perl -w ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# use strict; my @files = (); my %defines = (); for (@ARGV) { if (/^-D(.*)$/) { $defines{$1} = 1; } elsif (/^-/) { printf STDERR "Unknown option '".$_."'\n"; exit 1; } else { push @files, $_; } } int(@files) or die "usage: $0 [-D]... \n"; my @toc = (); my %title2page = (); my $doctitle = ""; my $curpage = ""; my $intoc = 0; my %prev_skips = (); my %next_skips = (); my %define_skips = (); my %polarity_skips = (); my $prev_skip = ""; my $next_skip = ""; my $define_skip = ""; my $polarity_skip = 0; for my $file (@files) { my $skipping = 0; # no nested ifs! open FILE, $file or die "File $file cannot be opened.\n"; while () { if (/^\h*\\if\h+defined\h*\(\h*(\H+)\h*\)/) { $skipping = !defined($defines{$1}); if (!$intoc) { $define_skip = $1; $polarity_skip = $skipping; } } elsif (/^\h*\\else/) { $skipping = 1 - $skipping; } elsif (/^\h*\\endif/) { $skipping = 0; } elsif (keys(%title2page) == 1 && /^\h*\\list/) { $intoc++; } elsif (!$intoc) { if ($skipping && /^\h*\\previouspage\h+(\H+)/) { $prev_skip = $1; } elsif ($skipping && /^\h*\\nextpage\h+(\H+)/) { $next_skip = $1; } elsif (/^\h*\\page\h+(\H+)/) { $curpage = $1; } elsif (/^\h*\\title\h+(.+)$/) { if ($curpage eq "") { die "Title '$1' appears in no \\page.\n"; } if (length($define_skip)) { $define_skips{$1} = $define_skip; $polarity_skips{$1} = $polarity_skip; $prev_skips{$1} = $prev_skip; $next_skips{$1} = $next_skip; $define_skip = $prev_skip = $next_skip = ""; } $title2page{$1} = $curpage; $doctitle = $1 if (!$doctitle); $curpage = ""; } } else { if (/^\h*\\endlist/) { $intoc--; } elsif (!$skipping && /^\h*\\(?:o|li)\h+\\l\h*{(.*)}$/) { push @toc, $1; } } } close FILE; } my %prev = (); my %next = (); my $last = $doctitle; for my $title (@toc) { $next{$last} = $title2page{$title}; $prev{$title} = $title2page{$last}; $last = $title; } for my $file (@files) { open IN, $file or die "File $file cannot be opened a second time?!\n"; open OUT, '>'.$file.".out" or die "File $file.out cannot be created.\n"; my $cutting = 0; while () { if (!$cutting) { if (/^\h*\\contentspage/) { $cutting = 1; } } else { if (/^\h*\\title\h+(.+)$/) { if (defined($define_skips{$1})) { print OUT " \\if defined(".$define_skips{$1}.")\n"; if ($polarity_skips{$1}) { print OUT " \\previouspage ".$prev_skips{$1} if ($prev_skips{$1}); print OUT " \\else\n"; } } print OUT " \\previouspage ".$prev{$1} if ($prev{$1}); if (defined($define_skips{$1})) { if (!$polarity_skips{$1}) { print OUT " \\else\n"; print OUT " \\previouspage ".$prev_skips{$1} if ($prev_skips{$1}); } print OUT " \\endif\n"; } print OUT " \\page ".$title2page{$1}; if (defined($define_skips{$1})) { print OUT " \\if defined(".$define_skips{$1}.")\n"; if ($polarity_skips{$1}) { print OUT " \\nextpage ".$next_skips{$1} if ($next_skips{$1}); print OUT " \\else\n"; } } print OUT " \\nextpage ".$next{$1} if ($next{$1}); if (defined($define_skips{$1})) { if (!$polarity_skips{$1}) { print OUT " \\else\n"; print OUT " \\nextpage ".$next_skips{$1} if ($next_skips{$1}); } print OUT " \\endif\n"; } print OUT "\n"; $cutting = 0; } else { next; } } print OUT $_; } close OUT; close IN; rename($file.".out", $file) or die "Cannot replace $file with new version.\n"; } qbs-src-3.3.1/doc/appendix/0000755000175100017510000000000015232633614015060 5ustar runnerrunnerqbs-src-3.3.1/doc/appendix/qbs-porting.qdoc0000644000175100017510000003454515232633614020210 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage building-qbs.html \page porting-to-qbs.html \nextpage json-api.html \title Appendix B: Migrating from Other Build Systems You can use the \l{create-project}{qbs create-project} command to automatically generate \QBS project files from an arbitrary directory structure. This is a useful starting point when migrating from other build tools, such as qmake or CMake. To use the tool, switch to the project directory and run the \c {qbs create-project} command, which is located in the \c bin directory of the \QBS installation directory (or the Qt Creator installation directory). After generating the initial .qbs file, add the missing configuration variables and functions to it, as described in the following sections. \section1 Migrating from qmake The following sections describe the \QBS equivalents of qmake variable values. \section2 CONFIG Specify project configuration and compiler options. \section3 console Set the \l{Product::consoleApplication}{Product.consoleApplication} property to \c true for the \l{Application}, \l{CppApplication},or \l{QtApplication} item. For example: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } consoleApplication: true } \endcode \section3 ordered This qmake variable has no direct equivalent in \QBS. Instead, the build order is determined by implicit and explicit dependencies between products. To add an explicit dependency, add a \l{Depends} item to a \l{Product}{product}: \code CppApplication { name: "myapp" Depends { name: "mylib" } } \endcode The \c myapp product depends on and links to the \c mylib product, and is therefore built after it. \section3 qt In qmake, the Qt dependency is implicit, whereas in \QBS it is not. If \c {CONFIG -= qt}, add a \l{Depends} item to specify that the \l{Product}{product} depends on the \l{cpp} module: \code Product { Depends { name: "cpp" } } \endcode \section2 DEFINES Set the \l{cpp::defines}{cpp.defines} property for the \l{Product}{product}. \note To reference \c cpp.defines, you must specify a dependency on the \l{cpp} module. \code Product { Depends { name: "cpp" } cpp.defines: ["SUPPORT_MY_FEATURES"] } \endcode \section2 DESTDIR We recommend that you use the \l{Installing Files}{installation mechanism} to specify the location of the target file: \code Application { Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: "share/myproject" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode If that is not possible, you can use the \l{Product::}{destinationDirectory} property: \code DynamicLibrary { name: "mydll" destinationDirectory: "libDir" } \endcode \section2 HEADERS, SOURCES, FORMS, RESOURCES, OTHER_FILES Include header, source, form, and resource files as well as any other files as values of a \l{Product::files}{Product.files} or \l{Group::files}{Group.files} property: \code QtApplication { name: "myapp" files: ["myapp.h", "myapp.cpp", "myapp.ui", "myapp.qrc", "readme.txt"] } \endcode \QBS uses \l{FileTagger}{file taggers} to figure out what kind of file it is dealing with. \section2 ICON There is no direct equivalent in \QBS. If you add a \l{Depends} {dependency} to the \l{ib} module and add the \c .xcassets directory as a value of the \l{Product::files}{Product.files} property, \QBS takes care of setting the application icon automatically when building for Apple platforms: \code Application { name: "myapp" files [".xcassets"] Depends { name: "ib" } } \endcode Alternatively, you can set the icon name as the value of the \l{bundle::infoPlist}{bundle.infoPlist} parameter, specify a dependency to the \l{ib} module, and add the application \c .icns file as a value of the \l{Product::}{files} property: \code Application { name: "myapp" files ["myapp.icns"] Depends { name: "ib" } bundle.infoPlist: ({"CFBundleIconFile": "myapp"}) \endcode \section2 INCLUDEPATH Add the paths to the include files as values of the \l{cpp::includePaths} {cpp.includePaths} property: \code CppApplication { cpp.includePaths: ["..", "some/other/dir"] } \endcode \section2 LIBS For libraries that are part of the project, use \l{Depends} items. To pull in external libraries, use the \l{cpp::libraryPaths} {cpp.libraryPaths} property for the Unix \c -L (library path) flags and the \l{cpp::dynamicLibraries}{cpp.dynamicLibraries} and \l{cpp::staticLibraries} {cpp.staticLibraries} properties for the \c -l (library) flags. For example, \c {LIBS += -L/usr/local/lib -lm} would become: \code CppApplication { cpp.libraryPaths: ["/usr/local/lib"] cpp.dynamicLibraries: ["m"] } \endcode \section2 OUT_PWD Use the \l{Product::buildDirectory}{Product.buildDirectory} property to refer to the base output directory of the generated artifacts. \section2 PWD Corresponds to the the file-scope variable \c path. \section2 _PRO_FILE_ Corresponds to the file-scope variable \c filePath when used in a \l{Project}{project} or \l{Product}{product}. \section2 _PRO_FILE_PWD_ Corresponds to the \l{Project::sourceDirectory}{Project.sourceDirectory} or \l{Product::sourceDirectory}{Product.sourceDirectory} property. \section2 QMAKE_ASSET_CATALOGS Add a \l{Depends}{dependency} to the \l{ib} module and add the \c .xcassets directory as a value of the \l{Product::}{files} property: \code Application { name: "myapp" files [".xcassets"] Depends { name: "ib" } } \endcode \section2 QMAKE_BUNDLE_DATA For the time being, you can manually place files in the appropriate location using the \l{Installing Files}{installation mechanism}. Better solutions are under development. \section2 QMAKE_BUNDLE_EXTENSION Set the \l{bundle::extension}{bundle.extension} property. \note Unlike qmake, \QBS automatically prepends a period (.) to the property value. \section2 QMAKE_{C,CXX,OBJECTIVE}_CFLAGS{_DEBUG,_RELEASE} Use the \l{cpp::commonCompilerFlags}{cpp.commonCompilerFlags} property or the properties corresponding to each compiler flags variable: \table \header \li qmake Variable \li cpp Module Property \row \li \c QMAKE_CFLAGS_DEBUG \c QMAKE_CFLAGS_RELEASE \li \l{cpp::cFlags}{cpp.cFlags} \row \li \c QMAKE_CXXFLAGS_DEBUG \c QMAKE_CXXFLAGS_RELEASE \li \l{cpp::cxxFlags}{cpp.cxxFlags} \row \li \c QMAKE_OBJECTIVE_CFLAGS \li \l{cpp::objcFlags}{cpp.objcFlags} \l{cpp::objcxxFlags}{cpp.objcxxFlags} \endtable Use \l{Properties} items or simple conditionals as values of the \l{qbs::buildVariant}{qbs.buildVariant} property to simulate the \c _DEBUG and \c _RELEASE variants of the qmake variables. \section2 QMAKE_FRAMEWORK_BUNDLE_NAME Set the \l{bundle::bundleName}{bundle.bundleName} property (which is derived from \l{Product::targetName}{Product.targetName}) combined with \l{bundle::extension}{bundle.extension}. \section2 QMAKE_FRAMEWORK_VERSION Set the \l{bundle::frameworkVersion}{bundle.frameworkVersion} property. \section2 QMAKE_INFO_PLIST Include the \c info.plist file as a value of \l{Product::}{files} property and specify a dependency to the \l{bundle} module: \code Application { name: "myapp" files ["info.plist"] Depends { name: "bundle" } } \endcode \QBS will automatically add any necessary properties to your \c Info.plist file. Typically, it determines the appropriate values from the other properties in the project, and therefore you do not need to use the \c {Info.plist.in > Info.plist} configuration mechanism. Further, you almost never need to embed placeholders into the source \c Info.plist file. Set the \l{bundle::processInfoPlist}{bundle.processInfoPlist} property to \c false to disable this behavior: \code \\ ... bundle.processInfoPlist: false \endcode In addition to, or instead of, using an actual \c Info.plist file, you can add \c Info.plist properties using the \l{bundle::infoPlist} {bundle.infoPlist} property. For example: \code \\ ... bundle.infoPlist: ({ "NSHumanReadableCopyright": "Copyright (c) 2017 Bob Inc", "Some other key", "Some other value, & XML special characters are no problem! >;) éžå‡¡!" }) \endcode \section2 QMAKE_LFLAGS Set the \l{cpp::linkerFlags}{cpp.linkerFlags} property for the \l{Product} {product}. \section2 QMAKE_{MACOSX,IOS,TVOS,WATCHOS}_DEPLOYMENT_TARGET For each qmake deployment target variable, use the corresponding property of the \l{cpp} module: \table \header \li qmake Variable \li cpp Module Property \row \li \c QMAKE_MACOSX_DEPLOYMENT_TARGET \li \l{cpp::minimumMacosVersion}{cpp.minimumMacosVersion} \row \li \c QMAKE_IOS_DEPLOYMENT_TARGET \li \l{cpp::minimumIosVersion}{cpp.minimumIosVersion} \row \li \c QMAKE_TVOS_DEPLOYMENT_TARGET \li \l{cpp::minimumTvosVersion}{cpp.minimumTvosVersion} \row \li \c QMAKE_WATCHOS_DEPLOYMENT_TARGET \li \l{cpp::minimumWatchosVersion}{cpp.minimumWatchosVersion} \endtable \section2 QMAKE_RPATHDIR Set the \l{cpp::rpaths}{cpp.rpaths} property for the \l{Product}{product}. \section2 QMAKE_SONAME_PREFIX Use the \l{cpp::sonamePrefix}{cpp.sonamePrefix} property for the \l{Product} {product}. \section2 QML_IMPORT_PATH Used only for Qt Creator QML syntax highlighting. Inside a \l{Product}, \l{Application}, \l{CppApplication}, or \l{QtApplication}, create a \c qmlImportPaths property: \code Product { name: "myProduct" property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"] } \endcode \section2 QT Add a \l{Depends} item to the \l{Product}{product} that specifies the dependencies to \l{Qt} modules. For example: \code QtApplication { Depends { name: "Qt.widgets" } } \endcode You could also use the following form that is equivalent to the previous one: \code QtApplication { Depends { name: "Qt"; submodules: "widgets" } } \endcode \section2 QTPLUGIN Building static applications often requires linking to static QPA plugins, such as \c qminimal. You can use the following syntax to enable \QBS to link to the required plugins: \code QtApplication { name: "myapp" Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild } } \endcode \section2 RC_FILE Add Windows resource files to the value of the \l{Product::files} {Product.files} property. \section2 TARGET Use the \l{Product::targetName}{Product.targetName} property to specify the base file name of target artifacts. \section2 TEMPLATE \section3 app Use \l{Application} or \l{CppApplication} as the \l{Product}{product}: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode This is roughly equivalent to: \code Product { name: "helloworld" type: "application" files: "main.cpp" Depends { name: "cpp" } } \endcode \section3 lib Use either \l{DynamicLibrary} or \l{StaticLibrary} as the \l{Product} {product}, depending on whether the value of \c CONFIG in the .pro file is \c shared or \c static. For example, if the value is \c shared: \code DynamicLibrary { name: "mydll" files: ["mySourceFile.cpp"] Depends { name: "cpp" } } \endcode \section3 subdirs In a \l{Project} item, specify subdirectories as values of the \l{Project::}{references} property: \code Project { references: [ "app/app.qbs", "lib/lib.qbs" ] } \endcode \section2 message(), warning(), error(), log() You can use the \l{Console API} to print info, warning, error, and log messages to the console. \code Product { name: { console.info("--> now evaluating the product name"); return "theName"; } Depends { name: "cpp" } cpp.includePath: { throw "An error occurred." } } \endcode */ qbs-src-3.3.1/doc/appendix/json-api.qdoc0000644000175100017510000011375115232633614017460 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage porting-to-qbs.html \nextpage attributions.html \page json-api.html \title Appendix C: The JSON API This API is the recommended way to provide \QBS support to an IDE. It is accessible via the \l{session} command. \section1 Packet Format All information is exchanged via \e packets, which have the following structure: \code packet = "qbsmsg:" [] \endcode First comes a fixed string indentifying the start of a packet, followed by the size of the actual data in bytes. After that, further meta data might follow. There is none currently, but future extensions might add some. A line feed character marks the end of the meta data section and is followed immediately by the payload, which is a single JSON object encoded in Base64 format. We call this object a \e message. \section1 Messages The message data is UTF8-encoded. Most messages are either \e requests or \e replies. Requests are messages sent to \QBS via the session's standard input channel. Replies are messages sent by \QBS via the session's standard output channel. A reply always corresponds to one specific request. Every request (with the exception of the \l{quit-message}{quit request}) expects exactly one reply. A reply implies that the requested operation has finished. At the very least, it carries information about whether the operation succeeded, and often contains additional data specific to the respective request. Every message object has a \c type property, which is a string that uniquely identifies the message type. All requests block the session for other requests, including those of the same type. For instance, if client code wishes to restart building the project with different parameters, it first has to send a \l{cancel-message}{cancel} request, wait for the current build job's reply, and only then can it request another build. The only other message beside \l{cancel-message}{cancel} that can legally be sent while a request is currently being handled is the \l{quit-message}{quit} message. A reply object may carry an \c error property, indicating that the respective operation has failed. If this property is not present, the request was successful. The format of the \c error property is described \l{ErrorInfo}{here}. In the remainder of this page, we describe the structure of all messages that can be sent to and received from \QBS, respectively. The property tables may have a column titled \e Mandatory, whose values indicate whether the respective message property is always present. If this column is missing, all properties of the respective message are mandatory, unless otherwise noted. \section1 The \c hello Message This message is sent by \QBS exactly once, right after the session was started. It is the only message from \QBS that is not a response to a request. The value of the \c type property is \c "hello", the other properties are as follows: \table \header \li Property \li Type \row \li api-level \li int \row \li api-compat-level \li int \row \li lsp-socket \li string \endtable The value of \c api-level is increased whenever the API is extended, for instance by adding new messages or properties. The value of \c api-compat-level is increased whenever incompatible changes are being done to this API. A tool written for API level \c n should refuse to work with a \QBS version with an API compatibility level greater than \c n, because it cannot guarantee proper behavior. This value will not change unless it is absolutely necessary. The value of \c api-compat-level is always less than or equal to the value of \c api-level. The value of \c lsp-socket is a path to a local domain socket (on Unix) or a named pipe (on Windows). It provides a server implementing the \l{https://microsoft.github.io/language-server-protocol}{Language Server Protocol}. \section1 Resolving a Project To instruct \QBS to load a project from disk, a request of type \c resolve-project is sent. The other properties are: \table \header \li Property \li Type \li Mandatory \row \li build-root \li \l FilePath \li yes \row \li configuration-name \li string \li no \row \li data-mode \li \l DataMode \li no \row \li deprecation-warning-mode \li string \li no \row \li dry-run \li bool \li no \row \li environment \li \l Environment \li no \row \li error-handling-mode \li string \li no \row \li force-probe-execution \li bool \li no \row \li log-time \li bool \li no \row \li log-level \li \l LogLevel \li no \row \li max-job-count \li int \li no \row \li module-properties \li list of strings \li no \row \li overridden-properties \li object \li no \row \li project-file-path \li FilePath \li if resolving from scratch \row \li restore-behavior \li string \li no \row \li settings-directory \li string \li no \row \li top-level-profile \li string \li no \row \li wait-lock-build-graph \li bool \li no \endtable The \c environment property defines the environment to be used for resolving the project, as well as for all subsequent \QBS operations on this project. The \c error-handling-mode specifies how \QBS should deal with issues in project files, such as assigning to an unknown property. The possible values are \c "strict" and \c "relaxed". In strict mode, \QBS will immediately abort and set the reply's \c error property accordingly. In relaxed mode, \QBS will continue to resolve the project if possible. A \l{warning-message}{warning message} will be emitted for every error that was encountered, and the reply's \c error property will \e not be set. The default error handling mode is \c "strict". If the \c log-time property is \c true, then \QBS will emit \l log-data messages containing information about which part of the operation took how much time. The \c module-properties property lists the names of the module properties which should be contained in the \l{ProductData}{product data} that will be sent in the reply message. For instance, if the project to be resolved is C++-based and the client code is interested in which C++ version the code uses, then \c module-properties would contain \c{"cpp.cxxLanguageVersion"}. Properties that have the value \c undefined will not be sent. The \c overridden-properties property is used to override the values of module, product or project properties. The possible ways to specify keys are described \l{Overriding Property Values from the Command Line}{here}. The \c restore-behavior property specifies if and how to make use of an existing build graph. The value \c "restore-only" indicates that a build graph should be loaded from disk and used as-is. In this mode, it is an error if the build graph file does not exist. The value \c "resolve-only" indicates that the project should be resolved from scratch and that an existing build graph should be ignored. In this mode, it is an error if the \c "project-file-path" property is not present. The default value is \c "restore-and-track-changes", which uses an existing build graph if possible and re-resolves the project if no build graph was found, if the parameters are different from the ones used when the project was last resolved, or if other relevant changes are detected, such as updated time stamps in a project file. The \c "restore-and-resolve" value is similar to \c "restore-and-track-changes", but also re-resolves the project if no changes were detected. The \c top-level-profile property specifies which \QBS profile to use for resolving the project. It corresponds to the \c profile key when using the \l resolve command. All other properties correspond to command line options of the \l resolve command, and their semantics are described there. When the project has been resolved, \QBS will reply with a \c project-resolved message. The possible properties are: \table \header \li Property \li Type \li Mandatory \row \li error \li \l ErrorInfo \li no \row \li project-data \li \l TopLevelProjectData \li no \endtable The \c error-info property is present if and only if the operation failed. The \c project-data property is present if and only if the conditions stated by the request's \c data-mode property are fulfilled. All other project-related requests need a resolved project to operate on. If there is none, they will fail. There is at most one resolved project per session. If client code wants to open several projects or one project in different configurations, it needs to start additional sessions. \section1 Building a Project To build a project, a request of type \c build-project is sent. The other properties, none of which are mandatory, are listed below: \table \header \li Property \li Type \row \li active-file-tags \li string list \row \li changed-files \li \l FilePath list \row \li check-outputs \li bool \row \li check-timestamps \li bool \row \li clean-install-root \li bool \row \li data-mode \li \l DataMode \row \li dry-run \li bool \row \li command-echo-mode \li string \row \li enforce-project-job-limits \li bool \row \li files-to-consider \li \l FilePath list \row \li install \li bool \row \li job-limits \li list of objects \row \li keep-going \li bool \row \li log-level \li \l LogLevel \row \li log-time \li bool \row \li max-job-count \li int \row \li module-properties \li list of strings \row \li products \li list of strings or \c "all" \endtable All boolean properties except \c install default to \c false. The \c active-file-tags and \c files-to-consider are used to limit the build to certain output tags and/or source files. For instance, if only C/C++ object files should get built, then \c active-file-tags would be set to \c "obj". The objects in a \c job-limits array consist of a string property \c pool and an int property \c limit. If the \c log-time property is \c true, then \QBS will emit \l log-data messages containing information about which part of the operation took how much time. If \c products is an array, the elements must correspond to the \c full-display-name property of previously retrieved \l ProductData, and only these products will get built. If \c products is the string \c "all", then all products in the project will get built. If \c products is not present, then products whose \l{Product::builtByDefault}{builtByDefault} property is \c false will be skipped. The \c module-properties property has the same meaning as in the \l{Resolving a Project}{resolve-project} request. All other properties correspond to options of the \l build command. When the build has finished, \QBS will reply with a \c project-built message. The possible properties are: \table \header \li Property \li Type \li Mandatory \row \li error \li \l ErrorInfo \li no \row \li project-data \li \l TopLevelProjectData \li no \endtable The \c error-info property is present if and only if the operation failed. The \c project-data property is present if and only if the conditions stated by the request's \c data-mode property are fulfilled. Unless the \c command-echo-mode value is \c "silent", a message of type \c command-description is emitted for every command to be executed. It consists of two string properties \c highlight and \c message, where \c message is the message to present to the user and \c highlight is a hint on how to display the message. It corresponds to the \l{Command and JavaScriptCommand}{Command} property of the same name. For finished process commands, a message of type \c process-result might be emitted. The other properties are: \table \header \li Property \li Type \row \li arguments \li list of strings \row \li error \li string \row \li executable-file-path \li \l FilePath \row \li exit-code \li int \row \li stderr \li list of strings \row \li stdout \li list of strings \row \li success \li bool \row \li working-directory \li \l FilePath \endtable The \c error string is one of \c "failed-to-start", \c "crashed", \c "timed-out", \c "write-error", \c "read-error" and \c "unknown-error". Its value is not meaningful unless \c success is \c false. The \c stdout and \c stderr properties describe the process's standard output and standard error output, respectively, split into lines. The \c success property is \c true if the process finished without errors and an exit code of zero. The other properties describe the exact command that was executed. This message is only emitted if the process failed or it has printed data to one of the output channels. \section1 Cleaning a Project To remove a project's build artifacts, a request of type \c clean-project is sent. The other properties are: \table \header \li Property \li Type \row \li dry-run \li bool \row \li keep-going \li bool \row \li log-level \li \l LogLevel \row \li log-time \li bool \row \li products \li list of strings \endtable The elements of the \c products array correspond to a \c full-display-name of a \l ProductData. If this property is present, only the respective products' artifacts are removed. If the \c log-time property is \c true, then \QBS will emit \l log-data messages containing information about which part of the operation took how much time. All other properties correspond to options of the \l clean command. None of these properties are mandatory. After all artifacts have been removed, \QBS replies with a \c project-cleaned message. If the operation was successful, this message has no properties. Otherwise, a property \c error of type \l ErrorInfo indicates what went wrong. \section1 Installing a Project Installing is normally part of the \l{Building a Project}{build} process. To do it in a separate step, the \c install property is set to \c false when building and a dedicated \c install-project message is sent. The other properties are: \table \header \li Property \li Type \row \li clean-install-root \li bool \row \li dry-run \li bool \row \li install-root \li \l FilePath \row \li keep-going \li bool \row \li log-level \li \l LogLevel \row \li log-time \li bool \row \li products \li list of strings \row \li use-sysroot \li bool \endtable The elements of the \c products array correspond to a \c full-display-name of a \l ProductData. If this property is present, only the respective products' artifacts are installed. If the \c log-time property is \c true, then \QBS will emit \l log-data messages containing information about which part of the operation took how much time. If the \c use-sysroot property is \c true and \c install-root is not present, then the install root will be \l{qbs::sysroot}{qbs.sysroot}. All other properties correspond to options of the \l install command. None of these properties are mandatory. \target cancel-message \section1 Canceling an Operation Potentially long-running operations can be aborted using the \c cancel-job request. This message does not have any properties. There is no dedicated reply message; instead, the usual reply for the request associated with the currently running operation will be sent, with the \c error property set to indicate that it was canceled. If there is no operation in progress, this request will have no effect. In particular, if it arrives after the operation that it was supposed to cancel has already finished (i.e. there is a race condition), the reply received by client code will not contain a cancellation-related error. \section1 Adding, Removing and Renaming Source Files Source files can be added to, removed from and renamed in \QBS project files with the \c add-files, \c remove-files and \c rename-files messages, respectively. These three requests have the same set of properties: \table \header \li Property \li Type \row \li files \li see below \row \li group \li string \row \li product \li string \endtable The \c files property specifies which files should be added, removed or renamed. For the \c add-files and \c remove-files messages, this is a \c FilePath list. For the \c rename-files message, this is a list of objects with two properties \c source-path and \c target-path, each of which is a \c FilePath. The \c product property corresponds to the \c full-display-name of a \l ProductData and specifies to which product to apply the operation. The \c group property corresponds to the \c name of a \l GroupData and specifies to which group in the product to apply the operation. After the operation has finished, \QBS replies with a \c files-added, \c files-removed and \c files-renamed message, respectively. Again, the properties are the same: \table \header \li Property \li Type \li Mandatory \row \li error \li \l ErrorInfo \li no \row \li failed-files \li \l FilePath list \li no \endtable If the \c error property is present, the operation has at least partially failed and \c failed-files will list the files that could not be added or removed. \section1 Adding Dependencies Dependencies can be added to a product with the \c add-dependencies message. The properties are: \table \header \li Property \li Type \row \li dependencies \li list of strings \row \li group \li string \row \li product \li string \endtable The \c dependencies property specifies which modules and/or products should be added. The \c product property corresponds to the \c full-display-name of a \l ProductData and specifies which product to add the dependencies to. The \c group property corresponds to the \c name of a \l GroupData and specifies in which group the resulting \c Depends items should appear. After the operation has finished, \QBS replies with a \c dependencies-added message. If and only if the operation failed, it will carry a property \c error of type \c ErrorInfo. \section1 The \c get-run-environment Message This request retrieves the full run environment for a specific executable product, taking into account the \l{Module::setupRunEnvironment}{setupRunEnvironment} scripts of all modules pulled in by the product. The properties are as follows: \table \header \li Property \li Type \li Mandatory \row \li base-environment \li \l Environment \li no \row \li config \li list of strings \li no \row \li product \li string \li yes \endtable The \c base-environment property defines the environment into which the \QBS-specific values should be merged. The \c config property corresponds to the \l{--setup-run-env-config} option of the \l run command. The \c product property specifies the product whose environment to retrieve. The value must correspond to the \c full-display-name of some \l ProductData in the project. \QBS will reply with a \c run-environment message. In case of failure, it will contain a property \c error of type \l ErrorInfo, otherwise it will contain a property \c full-environment of type \l Environment. \section1 The \c get-generated-files-for-sources Message This request allows client code to retrieve information about which artifacts are generated from a given source file. Its sole property is a list \c products, whose elements are objects with the two properties \c full-display-name and \c requests. The first identifies the product to which the requests apply, and it must match the property of the same name in a \l ProductData in the project. The latter is a list of objects with the following properties: \table \header \li Property \li Type \li Mandatory \row \li source-file \li \l FilePath \li yes \row \li tags \li list of strings \li no \row \li recursive \li bool \li no \endtable The \c source-file property specifies a source file in the respective product. The \c tags property constrains the possible file tags of the generated files to be matched. This is relevant if a source files serves as input to more than one rule or the rule generates more than one type of output. If the \c recursive property is \c true, files indirectly generated from the source file will also be returned. The default is \c false. For instance, íf this property is enabled for a C++ source file, the final link target (e.g. a library or an application executable) will be returned in addition to the object file. \QBS will reply with a \c generated-files-for-sources message, whose structure is similar to the request. It also has a single object list property \c products, whose elements consist of a string property \c full-display-name and an object list property \c results. The properties of these objects are: \table \header \li Property \li Type \row \li source-file \li \l FilePath \row \li generated-files \li \l FilePath list \endtable The \c source-file property corresponds to an entry of the same name in the request, and the \c generated-files are the files which are generated by \QBS rules that take the source file as an input, taking the constraints specified in the request into account. Source files for which the list would be empty are not listed. Similarly, products for which the \c results list would be empty are also omitted. \note The results may be incomplete if the project has not been fully built. \section1 Closing a Project A project is closed with a \c release-project message. This request has no properties. \QBS will reply with a \c project-released message. If no project was open, the reply will contain an \c error property of type \l ErrorInfo. \target quit-message \section1 Closing the Session To close the session, a \c quit message is sent. This request has no properties. \QBS will cancel all currently running operations and then close itself. No reply will be sent. \section1 Progress Messages While a request is being handled, \QBS may emit progress information in order to enable client code to display a progress bar. \target task-started \section2 The \c task-started Message This is always the first progress-related message for a specific request. It appears at most once per request. It consists of a string property \c description, whose value can be displayed to users, and an integer property \c max-progress that indicates which progress value corresponds to 100 per cent. \target task-progress \section2 The \c task-progress Message This message updates the progress via an integer property \c progress. \target new-max-progress \section2 The \c new-max-progress Message This message is emitted if the original estimated maximum progress has to be corrected. Its integer property \c max-progress updates the value from a preceding \l task-started message. \section1 Messages for Users There are two types of messages that purely contain information to be presented to users. \target log-data \section2 The \c log-data Message This object has a string property \c message, which is the text to be shown to the user. \target warning-message \section2 The \c warning Message This message has a single property of type \l ErrorInfo. The name of the property is either \c warning or \c error, depending on how the client should display it. \section1 The \c protocol-error Message \QBS sends this message as a reply to a request with an unknown \c type. It contains an \c error property of type \l ErrorInfo. \section1 Project Data If a request can alter the build graph data, the associated reply may contain a \c project-data property whose value is of type \l TopLevelProjectData. \section2 TopLevelProjectData This data type represents the entire project. It has the same properties as \l PlainProjectData. If it is part of a \c project-resolved message, these additional properties are also present: \table \header \li Property \li Type \row \li build-directory \li \l FilePath \row \li build-graph-file-path \li \l FilePath \row \li build-system-files \li \l FilePath list \row \li overridden-properties \li object \row \li profile-data \li object \endtable The value of \c build-directory is the top-level build directory. The \c build-graph-file-path value is the path to the build graph file. The \c build-system-files value contains all \QBS project files, including modules and JavaScript helper files. The value of \c overridden-properties is the one that was passed in when the project was last \l{Resolving a Project}{resolved}. The \c profile-data property maps the names of the profiles used in the project to the respective property maps. Unless profile multiplexing is used, this object will contain exactly one property. \section2 PlainProjectData This data type describes a \l Project item. The properties are as follows: \table \header \li Property \li Type \row \li is-enabled \li bool \row \li location \li \l FilePath \row \li name \li string \row \li products \li \l ProductData list \row \li sub-projects \li \l PlainProjectData list \endtable The \c is-enabled property corresponds to the project's \l{Project::condition}{condition}. The \c location property is the exact position in a \QBS project file where the corresponding \l Project item was defined. The \c products and \c sub-projects are what the project has pulled in via its \l{Project::references}{references} property. \section2 ProductData This data type describes a \l Product item. The properties are as follows: \table \header \li Property \li Type \row \li build-directory \li \l FilePath \row \li dependencies \li list of strings \row \li full-display-name \li string \row \li generated-artifacts \li \l ArtifactData list \row \li groups \li \l GroupData list \row \li is-enabled \li bool \row \li is-multiplexed \li bool \row \li is-runnable \li bool \row \li location \li \l Location \row \li module-properties \li \l ModulePropertiesData \row \li multiplex-configuration-id \li string \row \li name \li string \row \li properties \li object \row \li target-executable \li \l FilePath \row \li target-name \li string \row \li type \li list of strings \row \li version \li string \endtable The elements of the \c dependencies array correspond to the full-display-name properties of the products that this product has pulled in via \l Depends items. The \c generated-artifacts are files that are created by the \l{Rule}{rules} in this product. The \c groups list corresponds to the \l Group items in this product. In addition, a "pseudo-group" is created for the \l{Product::files}{files} property of the product itself. Its name is the same as the product's. The \c is-enabled property corresponds to the product's \l{Product::condition}{condition}. A product may also get disabled if it contains errors and \QBS was was instructed to operate in relaxed mode when the project was \l{Resolving a Project}{resolved}. The \c is-multiplexed property is true if and only if the product is \l{Multiplexing}{multiplexed} over one ore more properties. The \c is-runnable property indicates whether one of the product's target artifacts is an executable file. In that case, the file is available via the \c target-executable property. The \c location property is the exact position in a \QBS project file where the corresponding \l Product item was defined. The \c module-properties object provides the values of the module properties that were requested when the project was \l{Resolving a Project}{resolved}. The \c name property is the value given in the \l{Product::name}{Product item}, whereas \c full-display-name is a name that uniquely identifies the product in the entire project, even in the presence of multiplexing. In the absence of multiplexing, it is the same as \c name. In either case, it is suitable for being presented to users. See the \l Product item documentation for a description of the other properties. \section2 GroupData This data type describes a \l Group item. The properties are: \table \header \li Property \li Type \row \li is-enabled \li bool \row \li location \li \l Location \row \li module-properties \li \l ModulePropertiesData \row \li name \li string \row \li prefix \li string \row \li source-artifacts \li \l ArtifactData list \row \li source-artifacts-from-wildcards \li \l ArtifactData list \endtable The \c is-enabled property corresponds to the groups's \l{Group::condition}{condition}. However, if the group's product is disabled, this property will always be \c false. The \c location property is the exact position in a \QBS project file where the corresponding \l Group item occurs. The \c module-properties object provides the values of the module properties that were requested when the project was \l{Resolving a Project}{resolved}. If no module properties are set on the Group level and the value would therefore be the same as in the group's product, then this property is omitted. The \c source-artifacts list corresponds the the files listed verbatim in the group's \l{Group::files}{files} property. The \c source-artifacts-from-wildcards list represents the the files expanded from wildcard entries in the group's \l{Group::files}{files} property. See the \l Group item documentation for a description of the other properties. \section2 ArtifactData This data type represents files that occur in the project, either as sources or as outputs of a rules. \QBS project files, on the other hand, are not artifacts. The properties are: \table \header \li Property \li Type \row \li file-path \li \l FilePath \row \li file-tags \li list of strings \row \li install-data \li object \row \li is-executable \li bool \row \li is-generated \li bool \row \li is-target \li bool \row \li module-properties \li \l ModulePropertiesData \endtable The \c install-data property is an object whose \c is-installable property indicates whether the artifact gets installed. If so, then the \l FilePath properties \c install-file-path and \c install-root provide further information. The \c is-target property is true if the artifact is a target artifact of its product, that is, \c is-generated is true and \c file-tags intersects with the \l{Product::type}{product type}. The \c module-properties object provides the values of the module properties that were requested when the project was \l{Resolving a Project}{resolved}. This property is only present for generated artifacts. For source artifacts, the value can be retrieved from their \l{GroupData}{group}. The other properties should be self-explanatory. \section2 ModulePropertiesData This data type maps fully qualified module property names to their respective values. \section1 Other Custom Data Types There are a number of custom data types that serve as building blocks in various messages. They are described below. \section2 FilePath A \e FilePath is a string that describes a file or directory. FilePaths are always absolute and use forward slashes for separators, regardless of the host operating system. \section2 Location A \e Location is an object representing a file path and possibly also a position within the respective file. It consists of the following properties: \table \header \li Property \li Type \li Mandatory \row \li file-path \li \l FilePath \li yes \row \li line \li int \li no \row \li column \li int \li no \endtable \section2 ErrorInfo An \e ErrorInfo is an object representing error information. Its sole property \c items is an array of objects with the following structure: \table \header \li Property \li Type \li Mandatory \row \li description \li string \li yes \row \li location \li \l Location \li no \endtable \section2 DataMode This is the type of the \c data-mode property in a \l{Resolving a project}{resolve} or \l{Building a project}{build} request. It is used to indicate under which circumstances the reply message should include the project data. The possible values have string type and are as follows: \list \li \c "never": Do not attach project data to the reply. \li \c "always": Do attach project data to the reply. \li \c "only-if-changed": Attach project data to the reply only if it is different from the current project data. \endlist The default value is \c "never". \section2 LogLevel This is the type of the \c log-level property that can occur in various requests. It is used to indicate whether the client would like to receive \l log-data and/or \l{warning-message}{warning} messages. The possible values have string type and are as follows: \list \li "error": Do not log anything. \li "warning": \QBS may emit \l{warning-message}{warnings}, but no \l log-data messages. \li "info": In addition to warnings, \QBS may emit informational \l log-data messages. \li "debug": \QBS may emit debug output. No messages will be generated; instead, the standard error output channel will be used. \endlist The default value is \c "info". \section2 Environment This data type describes a set of environment variables. It is an object whose keys are names of environment variables and whose values are the values of these environment variables. */ qbs-src-3.3.1/doc/reference/0000755000175100017510000000000015232633614015206 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/modules/0000755000175100017510000000000015232633614016656 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/modules/flatbuf-c-module.qdoc0000644000175100017510000000476515232633614022670 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype flatbuf.c \inqmlmodule QbsModules \since Qbs 2.4 \brief Provides support for \l{https://google.github.io/flatbuffers/}{FlatBuffers} for the C language. The \c flatbuf.c module provides support for generating C headers and sources from flatbuffers definition files using the \c flatcc tool. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"flatbuffers.input"} \li \c{*.fbs} \li 2.4.0 \li Source files with this tag are considered inputs to the \c flatcc compiler. \endtable \section2 Dependencies This module depends on the \c flatcc module which can be created via the \l{conan}{Conan} module provider. */ /*! \qmlproperty string flatbuf.c::compilerName The name of the \c flatcc binary. \defaultvalue \c "flatcc" */ /*! \qmlproperty string flatbuf.c::compilerPath The path to the \c flatcc binary. Use this property to override the auto-detected location. \defaultvalue \c auto-detected */ /*! \qmlproperty pathList flatbuf.c::importPaths The list of import paths that are passed to the \c flatcc tool via the \c -I option. \defaultvalue \c [] */ qbs-src-3.3.1/doc/reference/modules/qnx-module.qdoc0000644000175100017510000000512115232633614021616 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype qnx \inqmlmodule QbsModules \since Qbs 1.8 \brief Provides support for building QNX applications using the QNX SDK. The \c qnx module contains properties and rules for QNX development. It has been tested with the QNX 6.5, 6.6, and 7.0 SDKs. */ /*! \qmlproperty string qnx::sdkDir The SDK base directory. \defaultvalue Determined automatically if the QNX SDK is installed at one of the standard locations, such as \c ~/qnx700, \c /opt/qnx700, or \c C:\\qnx700. */ /*! \qmlproperty string qnx::configurationDir The QNX configuration directory. Equivalent to the \c{QNX_CONFIGURATION} environment variable. \defaultvalue \c{~/.qnx} */ /*! \qmlproperty string qnx::hostDir The QNX host directory. Equivalent to the \c{QNX_HOST} environment variable. You should not normally need to set this property as it will be set to an appropriate value based on your host operating system and the installed QNX SDK in \l{qnx::}{sdkDir}. \defaultvalue Determined automatically. */ /*! \qmlproperty string qnx::targetDir The QNX target directory. Equivalent to the \c{QNX_TARGET} environment variable. You should not normally need to set this property as it will be set to an appropriate value based on the installed QNX SDK in \l{qnx::}{sdkDir}. \defaultvalue Determined automatically. */ qbs-src-3.3.1/doc/reference/modules/qt-scxml-module.qdoc0000644000175100017510000000531415232633614022564 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.scxml \inqmlmodule QbsModules \brief Provides Qt SCXML support. The Qt.scxml module provides support for the Qt SCXML module, which enables creating state machines from SCXML files. \section2 Relevant File Tags \target filetags-scxml \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.scxml.compilable"} \li - \li 1.7 \li Source files with this tag serve as inputs to the rule running the Qt SCXML compiler, which will create a C++ class representing a state machine. \endtable */ /*! \qmlproperty string Qt.scxml::className The class name of the generated state machine. By default, the compiler will use the \c name attribute of the input file's \c{} tag. \nodefaultvalue */ /*! \qmlproperty string Qt.scxml::generateStateMethods If this property is \c true, the Qt SCXML compiler will generate read and notify methods for states. \defaultvalue \c false \since 1.11 */ /*! \qmlproperty string Qt.scxml::namespace The C++ namespace in which to put the generated class. By default, the compiler will place the class in the global namespace. \nodefaultvalue */ /*! \qmlproperty string Qt.scxml::qscxmlcName The base name of the Qt SCXML compiler. Set this value if your system uses a name different from the default value. \defaultvalue \c{"qscxmlc"} */ qbs-src-3.3.1/doc/reference/modules/config-install-module.qdoc0000644000175100017510000000365415232633614023732 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype config.install \inqmlmodule QbsModules \since Qbs 3.1 \brief Provides properties for configuring installation paths and rules for various build artifacts. The \c{config.install} module contains properties that configure built-in items such as \l{Application}, \l{Library}, and \l{Plugin}. An example showing how to enable installation of static libraries: \code qbs modules.config.install.staticLibraries:true \endcode An example showing how to change the install diretory for dynamic libraries: \code qbs modules.config.install.dynamicLibrariesDirectory:opt/lib \endcode For the list of available properties, see the \l{ConfigInstall} item. */ qbs-src-3.3.1/doc/reference/modules/qt-modules.qdoc0000644000175100017510000001172415232633614021625 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qt-modules.html \inmodule qbs-modules \title Qt Modules \brief Provides Qt support. The \c{Qt.*} modules contain properties and rules for Qt. Qt modules are generated by the \l[QML]{Qt} module provider. \section1 Creating Dependencies to Qt Modules The Qt modules are grouped using the prefix \c Qt. If your product depends on the Qt.core and Qt.network modules, you could write: \code Depends { name: "Qt.core" } Depends { name: "Qt.network" } \endcode Or, alternatively: \code Depends { name: "Qt"; submodules: [ "core", "network" ] } \endcode The Qt modules that have properties and relevant file tags are described in separate topics. \section1 List of Submodules \table \header \li Submodule Name \li Qt Module Name \li Notes \row \li axcontainer \li QAxContainer \li This module is only available on Windows. \row \li axserver \li QAxServer \li This module is only available on Windows. \row \li concurrent \li Qt Concurrent \li \row \li \l{Qt.core}{core} \li Qt Core \li For more information, see \l{Qt.core}. \row \li \l{Qt.dbus}{dbus} \li Qt D-Bus \li For more information, see \l{Qt.dbus}. \row \li \l{Qt.declarative}{declarative} \li Qt Quick 1 \li Provides the \c{Qt Quick 1} module. For more information, see \l{Qt.declarative}. \row \li designer \li Qt Designer \li \row \li enginio \li Qt Enginio \li \row \li \l{Qt.gui}{gui} \li Qt GUI \li For more information, see \l {Qt.gui}. \row \li help \li Qt Help \li You do not need this module for building \c qdoc documentation, because that functionality is part of the Qt.core module. This module is for using Qt classes such as \c QHelpEngine. \row \li multimedia \li Qt Multimedia \li \row \li multimediawidgets \li Qt Multimedia Widgets \li \row \li network \li Qt Network \li \row \li opengl \li Qt OpenGL \li \row \li phonon \li Phonon (Qt 4 only) \li \row \li printsupport \li Qt Print Support \li \row \li \l{Qt.quick}{quick} \li Qt Quick 2 \li Provides the \c{Qt Quick} module (Qt Quick 2). For more information, see \l{Qt.quick}. \row \li quickcontrols2 \li Qt Quick Controls 2 \row \li \l{Qt.qml}{qml} \li Qt QML \li For more information, see \l{Qt.qml}. \row \li qmltest \li Qt Quick Test \li \row \li script \li Qt Script \li \row \li \l{Qt.scxml}{scxml} \li Qt Scxml \li For more information, see \l {Qt.scxml}. \row \li sql \li Qt SQL \li \row \li svg \li Qt SVG \li \row \li testlib \li Qt Test \li \row \li webkit \li Qt WebKit \li \row \li webkitwidgets \li Qt WebKit Widgets \li \row \li widgets \li Qt Widgets \li \row \li xml \li Qt XML \li You do not need this module for the \c QXmlStreamReader and \c QXmlStreamWriter classes, because those classes are a part of the \c Qt.core module. This module provides the deprecated DOM and SAX classes. \row \li xmlpatterns \li Qt XML Patterns \li \li \endtable */ qbs-src-3.3.1/doc/reference/modules/protobufobjc-module.qdoc0000644000175100017510000000726415232633614023520 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype protobuf.objc \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for protocol buffers for the Objective-C language. The \c protobuf.objc module provides support for generating Objective-C headers and sources from proto definition files using the \l protoc tool. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"protobuf.input"} \li \c{*.proto} \li 1.13.0 \li Source files with this tag are considered inputs to the \c protoc compiler. \row \li \c{"protobuf.hpp"} \li \li 1.18.0 \li This tag is attached to the header files generated by \c protoc compiler. \endtable */ /*! \qmlproperty string protobuf.objc::compilerName The name of the protoc binary. \since Qbs 1.17 \defaultvalue \c "protoc" */ /*! \qmlproperty string protobuf.objc::compilerPath The path to the protoc binary. Use this property to override the auto-detected location. \since Qbs 1.17 \defaultvalue \c auto-detected */ /*! \qmlproperty pathList protobuf.objc::importPaths The list of imports that are passed to the \c protoc tool via the \c --proto_path option. These imports should contain the proto files. They are used to determine the relative structure of the generated files. \note The paths are passed to \c protoc in the same order as specified in this property and \c protoc output may differ depending on that order. \defaultvalue \c [] */ /*! \qmlproperty string protobuf.objc::includePath The path where protobuf Objective-C headers are located. Set this property to override the default location. \note If frameworkPath is specified, this property has no effect. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.objc::libraryPath \note If frameworkPath is specified, this property has no effect. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.objc::frameworkPath The path where \c Protobuf.framework is located. Set this property to override the default location. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.objc::outputDir \readonly The directory where the \c protoc compiler generated files are placed. The value of this property is automatically set by \QBS and cannot be changed by the user. */ qbs-src-3.3.1/doc/reference/modules/protobufnanopb-module.qdoc0000644000175100017510000001056415232633614024055 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype protobuf.nanopb \inqmlmodule QbsModules \since Qbs 1.18 \brief Provides support for protocol buffers for embedded systems. The \c protobuf.nanopb module provides support for generating nanopb C headers and sources from proto definition files using the \l nanopb plugin for the \l protoc tool suitable for embedded systems. A simple qbs file that uses protobuf can be written as follows: \code CppApplication { Depends { name: "protobuf.nanopb" } files: ["foo.proto", "main.cpp"] } \endcode A generated header now can be included in the C++ sources: \code #include int main(int argc, char* argv[]) { Foo bar; bar.has_answer = true; bar.answer = 42; return 0; } \endcode Nanopb .options files to define nanopb specific proto options are supported. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"protobuf.input"} \li \c{*.proto} \li 1.13.0 \li Source files with this tag are considered inputs to the \c protoc compiler. \row \li \c{"protobuf.hpp"} \li \li 1.18.0 \li This tag is attached to the header files generated by \c protoc compiler. \endtable */ /*! \qmlproperty string protobuf.nanopb::compilerName The name of the protoc binary. \defaultvalue \c "protoc" */ /*! \qmlproperty string protobuf.nanopb::compilerPath The path to the protoc binary. Use this property to override the auto-detected location. \defaultvalue \c auto-detected */ /*! \qmlproperty pathList protobuf.nanopb::importPaths The list of imports that are passed to the \c protoc tool via the \c --proto_path option. These imports should contain the proto files. They are used to determine the relative structure of the generated files. \note The paths are passed to \c protoc in the same order as specified in this property and \c protoc output may differ depending on that order. \defaultvalue \c [] */ /*! \qmlproperty string protobuf.nanopb::includePath The path where protobuf nanopb C headers are located. Set this property to override the default location. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.nanopb::libraryPath The path where the protobuf nanopb runtime library is located. Set this property to override the default location. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.nanopb::outputDir \readonly The directory where the \c protoc compiler generated files are placed. The value of this property is automatically set by \QBS and cannot be changed by the user. */ /*! \qmlproperty string protobuf.nanopb::pluginName The name of the nanopb protoc plugin. \defaultvalue \c "protoc-gen-nanopb" */ /*! \qmlproperty string protobuf.nanopb::pluginPath The path to the nanopb protoc plugin. Use this property to override the auto-detected location. \defaultvalue \c auto-detected */ qbs-src-3.3.1/doc/reference/modules/qt-shadertools-module.qdoc0000644000175100017510000002005615232633614023765 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.shadertools \inqmlmodule QbsModules \brief Provides Qt Shader Tools support. The Qt.shadertools module provides functionality for compiling and processing shaders in \QBS projects. It supports various shader languages including GLSL, HLSL, and MSL. \section2 Relevant File Tags \target filetags-qtshadertools \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{qt.shader} \li \c{*.vert, *.tesc, *.tese, *.frag, *.comp} \li \c{3.0} \li Source files with these extensions are considered shaders and are processed by the qsb tool. \row \li \c{qt.shader.vertex} \li \c{*.vert} \li \c{3.0} \li Source files with this extension are considered vertex shaders. \row \li \c{qt.shader.fragment} \li \c{*.frag} \li \c{3.0} \li Source files with this extension are considered fragment shaders. \row \li \c{qt.shader.compute} \li \c{*.comp} \li \c{3.0} \li Source files with this extension are considered compute shaders. \row \li \c{qt.shader.tessellation} \li \c{*.tesc} \li \c{3.0} \li Source files with this extension are considered tessellation shaders. These shaders are automatically processed by using tessellation properties. \row \li \c{qt.compiled_shader} \li n/a \li \c{3.0} \li This tag is attached to the output artifacts of the rule that runs the qsb tool. \endtable \section2 Example \code QtApplication { name: "shader-app" type: "application" Depends { name: "Qt.shadertools" } files: ["shader.frag", "shader.vert"] Qt.shadertools.glslVersions: ["300 es", "330"] Qt.shadertools.hlslVersions: ["50"] Qt.shadertools.mslVersions: ["12"] } \endcode For more details on the \c{qsb} tool, see \l{https://doc.qt.io/qt-6/qtshadertools-qsb.html}{its documentation} */ /*! \qmlproperty string Qt.shadertools::generatedShadersDir The directory where compiled shaders will be placed. \defaultvalue \c{"shaders"} */ /*! \qmlproperty string Qt.shadertools::qsbName The name of the Qt Shader Tools compiler executable. \defaultvalue \c{"qsb"} */ /*! \qmlproperty stringList Qt.shadertools::glslVersions List of GLSL versions to generate. Each version should be specified as a string, for example \c{"100 es"} for GLSL ES 1.00. If this property is set to \c{[]}, GLSL generation is disabled. \defaultvalue \c{[]} */ /*! \qmlproperty stringList Qt.shadertools::hlslVersions List of HLSL (shader model) versions to generate. The versions follow GLSL-style version numbers, where 50 corresponds to Shader Model 5.0. If this property is set to \c{[]}, HLSL generation is disabled. \defaultvalue \c{[]} */ /*! \qmlproperty stringList Qt.shadertools::mslVersions List of Metal Shading Language versions to generate. 12 corresponds to version 1.2. If this property is set to \c{[]}, MSL generation is disabled. \defaultvalue \c{[]} */ /*! \qmlproperty bool Qt.shadertools::useQt6Versions Use default version used by Qt6. This is equivalent to passing \c{--qt6} switch to the \c{qsb} tool. \defaultvalue \c{false} */ /*! \qmlproperty bool Qt.shadertools::tessellation Whether the shaders are used in a pipeline that uses tessellation. By default, \QBS adds flags contolled by \l{tessellationMode} and \l{tessellationVertexCount} properties for all files with the \c{"qt.shader.tessellation"} file tag. Set this property to \c{false} to disable tessellation options for such files. \defaultvalue \c{true} */ /*! \qmlproperty string Qt.shadertools::tessellationMode The tessellation mode. Can be either \c{"triangles"} or \c{"quads"}. This property must be specified when a tessellation control shader is used. \defaultvalue \c{"triangles"} */ /*! \qmlproperty int Qt.shadertools::tessellationVertexCount The output vertex count from the tessellation control stage. \defaultvalue \c{3} */ /*! \qmlproperty int Qt.shadertools::viewCount The number of views a vertex shader is used with. Relevant for multiview functionality (GL_OVR_multiview2, VK_KHR_multiview, D3D12 view instancing). \defaultvalue \c{undefined} */ /*! \qmlproperty bool Qt.shadertools::batchable Whether vertex shaders should be made batchable for use with Qt Quick. \defaultvalue \c{false} */ /*! \qmlproperty int Qt.shadertools::zOrderLocation When \l{Qt.shadertools::batchable}{batchable} is true, this specifies the location for the additional vertex input that is injected with location 7 by default. Use this property to change the location of the injected vertex input to another value. This becomes relevant if the vertex shader has many inputs and 7 is in use and would clash. \defaultvalue \c{undefined} */ /*! \qmlproperty bool Qt.shadertools::optimized Whether to perform SPIR-V optimizations using spirv-opt. \defaultvalue \c{false} */ /*! \qmlproperty stringList Qt.shadertools::defines List of preprocessor defines to be active during shader compilation. Defines should be added as \c{"="} pairs. \defaultvalue \c{[]} */ /*! \qmlproperty bool Qt.shadertools::debugInformation Whether to generate full debug information for SPIR-V. \defaultvalue \c{false} */ /*! \qmlproperty bool Qt.shadertools::addResourceData Whether to automatically add the compiled shaders to the Qt resource data. \defaultvalue \c{true} */ /*! \qmlproperty bool Qt.shadertools::enableLinking Set this property to \c{true} to enable linking to the QtShaderTools library. For example: \code QtApplication { name: "shader-app" Depends { name: "Qt.shadertools" } Qt.shadertools.enableLinking: true } \endcode The Qt.shadertools module can be used in two ways: \list \li Using the \c{qsb} tool to compile shaders. \li Linking directly to the \l{https://doc.qt.io/qt-6/qtshadertools-index.html}{QtShaderTools} library and using the \l{https://doc.qt.io/qt-6/qshaderbaker.html}{QShaderBaker} class. \endlist This property and \l{useCompiler} property controls which mode is used. You can also enable both modes by setting both properties to \c{true}. \defaultvalue \c{false} */ /*! \qmlproperty bool Qt.shadertools::useCompiler Whether to use the Qt Shader Tools compiler. Set this property to \c{false} to disable the qsb tool. This is set to \c{false} by default if \l{Qt.shadertools::enableLinking}{enableLinking} is \c{true}. \defaultvalue \c{true} */ qbs-src-3.3.1/doc/reference/modules/texttemplate-module.qdoc0000644000175100017510000001001015232633614023521 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype texttemplate \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for text template files. The \c texttemplate module provides support for text template files. \section2 Example Consider the following text file \e{greeting.txt.in}. \code ${greeting} ${name}! \endcode This can be used in a project like this: \code Product { type: ["text"] files: ["greeting.txt.in"] Depends { name: "texttemplate" } texttemplate.dict: ({ greeting: "Hello", name: "World" }) } \endcode Which will create the file \e{greeting.txt}. \code Hello World! \endcode The same result can be achieved using the alternative placeholder format: \code Product { type: ["text"] files: ["greeting.txt.in"] Depends { name: "texttemplate" } texttemplate.placeholder: "@@" texttemplate.dict: ({ greeting: "Hello", name: "World" }) } \endcode Where \e{greeting.txt.in} contains: \code @greeting@ @name@! \endcode \section2 Placeholder Syntax The texttemplate module supports two placeholder formats, controlled by the \c{placeholder} property. A placeholder \c{${foo}} is replaced by its corresponding value in \e{texttemplate.dict}. Placeholder names consist of alphanumeric characters only. The placeholder \c{${$}} is always replaced with \c{$}. If you need a literal \c{${foo}} in your template, use \c{${$}{foo}}. When \c{texttemplate.placeholder} is set to \c{"@@"}, placeholders use the format \c{@foo@} instead. Placeholders that are not defined in the dictionary will produce an error. \section2 Relevant File Tags \target filetags-texttemplate \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"texttemplate.input"} \li \c{*.in} \li 1.13.0 \li Source files with this tag serve as inputs for the text template rule. \endtable */ /*! \qmlproperty var texttemplate::dict The dictionary containing values for all keys used in the template file. \defaultvalue \c{{}} */ /*! \qmlproperty string texttemplate::outputFileName The output file name that is assigned to produced artifacts. \defaultvalue Complete base name of the input file */ /*! \qmlproperty string texttemplate::outputTag The output tag that is assigned to produced artifacts. \defaultvalue \c{"text"} */ /*! \qmlproperty string texttemplate::placeholder The placeholder format to use for text template files. Possible values: \c{"${}"}, \c{"@@"} \defaultvalue \c{"${}"} \since Qbs 3.1 */ qbs-src-3.3.1/doc/reference/modules/qt-gui-module.qdoc0000644000175100017510000000372415232633614022225 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.gui \inqmlmodule QbsModules \brief Provides Qt GUI support. The Qt.gui module provides support for the Qt GUI module, which contains base classes for graphical user interface (GUI) components. \section2 Relevant File Tags \target filetags-gui \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"ui"} \li \c{*.ui} \li 1.0 \li Source files with this tag serve as inputs to the rule running the \c uic tool. \endtable */ /*! \qmlproperty string Qt.gui::uicName The base name of the \c uic tool. Set this property if your system uses a name such as \c uic-qt4. \defaultvalue \c{"uic"} */ qbs-src-3.3.1/doc/reference/modules/archiver-module.qdoc0000644000175100017510000001142215232633614022614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype archiver \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building archives. The \c archiver module contains the properties and rules for creating (compressed) archives. The output artifact has the file tag \c "archiver.archive". The sole input artifact is a text file containing the list of files to package, with one file path per line. The paths can be relative, in which case they will be looked for in \l{archiver::}{workingDirectory}. The file tag of this input artifact is \c "archiver.input-list". */ /*! \qmlproperty stringList archiver::flags Custom options not covered by any of the other properties. \defaultvalue \c [] */ /*! \qmlproperty string archiver::archiveBaseName The base name of the archive file. That is, the file name without any extensions. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty string archiver::compressionLevel How much effort to put into the compression of a \c 7-Zip or \c zip archive. Possible values for zip are: \list \li \c undefined \li \c "0" \li \c "1" \li \c "2" \li \c "3" \li \c "4" \li \c "5" \li \c "6" \li \c "7" \li \c "8" \li \c "9" \endlist 7-Zip only supports 0 and the odd numbers above. Higher numbers result in a smaller archive, but the compression process will take more time. If the value is left undefined, the default compression level is used. \nodefaultvalue */ /*! \qmlproperty string archiver::compressionType How to compress a \c tar or \c zip archive. Possible options are: \list \li \c "bz2" \li \c "deflate" \li \c "gz" \li \c "none" \li \c "store" \li \c undefined, which uses the archiver's default compression type. \li \c "xz" \li \c "Z" \endlist \defaultvalue \c{"gz"} for \c tar archives, otherwise \c undefined. */ /*! \qmlproperty string archiver::outputDirectory Where to put the archive file. \defaultvalue \l{Product::destinationDirectory} {product.destinationDirectory} */ /*! \qmlproperty string archiver::type Which kind of archiver to use. The currently supported values are: \list \li \c "7zip" \li \c "tar" \li \c "zip" \endlist \nodefaultvalue */ /*! \qmlproperty string archiver::workingDirectory The directory in which to execute the archiver tool specified by \l{archiver::}{command}. \nodefaultvalue */ /*! \qmlproperty string archiver::command The path to the executable used to create the archive. This is usually the native tool corresponding to the archive type being produced, but may fall back to another tool also capable of producing that archive type if the native tool is not installed on the host system. This behavior is especially useful on platforms such as Windows, where the native tools for producing \c tar and \c zip archives in particular are much less likely to be installed. The following table lists the supported \l{archiver::type}{archive types} and the tools capable of producing them, listed in search order from left to right: \table \header \li Type \li Supported tools \row \li 7zip \li 7z \row \li tar \li tar, 7z \row \li zip \li zip \e (Info-Zip), 7z, jar \e (from Java JDK) \endtable \defaultvalue Depends on \l{archiver::}{type}. */ qbs-src-3.3.1/doc/reference/modules/pkgconfig-module.qdoc0000644000175100017510000000617215232633614022766 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype pkgconfig \inqmlmodule QbsModules \since 1.13 \brief Allows to configure the pkg-config tool. The \c pkgconfig module is used to fine-tune the behavior of the \c {pkg-config} tool, which is \l{How do I build against libraries that provide pkg-config files?}{potentially employed} when looking up dependencies. */ /*! \qmlproperty string pkgconfig::executableFilePath The path to the \c {pkg-config} executable. \defaultvalue auto-detected */ /*! \qmlproperty stringList pkgconfig::libDirs Set this if you need to overwrite the default search directories. The values given here will be forwarded to the tool via the \c PKG_CONFIG_LIBDIR environment variable. \note You do not need to set this for cross-compilation in order to point \c {pkg-config} to the sysroot. \QBS does that for you. \nodefaultvalue */ /*! \qmlproperty bool pkgconfig::staticMode If this property is \c true, then calls to \c{pkg-config} will include the \c{--static} option. Set this if your product is to be linked statically. \defaultvalue \c false */ /*! \qmlproperty path pkgconfig::sysroot This property controls the value of the \l{PkgConfigProbe::sysroot}{PkgConfigProbe.sysroot} property. Set this property if you need to overwrite the default search sysroot path used by \c pkg-config. This can be useful if \c pkg-config files are located in the directory other than qbs.sysroot. This is the case on macOS platform - all XCode profiles are sysrooted to the SDK directory, but \c pkg-config is typically intalled using Brew and resides in the \c /usr/local directory. Setting this property to \c undefined or empty (\c "") value will use pkg-config's default search paths: \code qbs build modules.pkgconfig.sysroot:undefined \endcode \defaultvalue \c "" on macOS, \c qbs.sysroot on other platforms */ qbs-src-3.3.1/doc/reference/modules/java-module.qdoc0000644000175100017510000001364615232633614021744 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype java \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides Java support. The \c java module contains the properties and rules for building Java projects. \section2 Relevant File Tags \target filetags-java \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"java.class"} \li - \li 1.4 \li This tag is attached to the output artifacts of the rule that runs the \c javac tool. \row \li \c{"java.jar"} \li - \li 1.4 \li This tag is attached to the output artifacts of the rule that runs the \c jar tool. \row \li \c{"java.java"} \li \c{*.java} \li 1.4 \li Source files with this tag serve as inputs to the rule running the \c javac tool. \row \li \c{"java.manifest"} \li \c{*.mf} \li 1.8 \li The contents of files with this tag will be aggregated with the values in \l{java::}{manifest}. \endtable */ /*! \qmlproperty stringList java::additionalClassPaths The locations beside this product's class output path to consider when compiling. \nodefaultvalue */ /*! \qmlproperty stringList java::additionalCompilerFlags A list of compiler flags not covered by any of the properties in this module. \nodefaultvalue */ /*! \qmlproperty stringList java::additionalJarFlags A list of archiver flags not covered by any of the properties in this module. \nodefaultvalue */ /*! \qmlproperty stringList java::bootClassPaths A list of non-standard bootstrap class files. \nodefaultvalue */ /*! \qmlproperty string java::compilerFilePath The command to invoke when compiling Java sources. \defaultvalue \l compilerName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::compilerName The file name of the Java compiler. \defaultvalue \c{"javac"} */ /*! \qmlproperty bool java::enableWarnings Whether warnings are emitted when compiling Java sources. \defaultvalue \c true */ /*! \qmlproperty string java::interpreterFilePath The command to invoke when executing Java code. \defaultvalue \l interpreterName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::interpreterName The file name of the Java interpreter. \defaultvalue \c{"java"} */ /*! \qmlproperty string java::jarFilePath The command to run when creating or extracting \c jar files. \defaultvalue \l jarName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::jarName The file name of the \c jar tool. \defaultvalue \c{"jar"} */ /*! \qmlproperty pathList java::jdkIncludePaths \since Qbs 1.4.1 A list of include paths for native header files. Applications using JNI to interface with native code should add these paths to \l{cpp::includePaths}{cpp.includePaths}. \defaultvalue Determined automatically. */ /*! \qmlproperty string java::jdkPath The base path of the Java Development Kit (JDK). This is equivalent to the \c JAVA_HOME environment variable, and by default will be determined automatically from one of the following: \list \li \c JAVA_HOME environment variable (all platforms) \li Registry (Windows) \li \c java_home tool (macOS) \li Known JDK paths (other Unix platforms) \endlist \defaultvalue Determined automatically. */ /*! \qmlproperty string java::languageVersion The Java language version to interpret source code as. If left undefined, the compiler will use its default. \nodefaultvalue */ /*! \qmlproperty string java::runtimeVersion The version of the Java runtime to generate compatible bytecode for. If left undefined, the compiler will use its default. \nodefaultvalue */ /*! \qmlproperty var java::manifest \since Qbs 1.4.2 The properties to add to the manifest file when building a JAR. The contents of this property will be aggregated with the values from any files tagged \l{filetags-java}{"java.manifest"}. If this property and a manifest file contain the same key, this property will take precedence. If left undefined, this property will not be taken into account. \nodefaultvalue */ /*! \qmlproperty stringList java::manifestClassPath A list of entries to add to the manifest's Class-Path when building a JAR. \nodefaultvalue */ /*! \qmlproperty bool java::warningsAsErrors If this property is \c true, the compiler will abort where it would normally emit a warning. \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/modules/dmg-module.qdoc0000644000175100017510000003165115232633614021566 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype dmg \inqmlmodule QbsModules \since Qbs 1.9 \brief Provides support for building Apple Disk Images. The \c dmg module contains properties and rules for building Apple Disk Images, which are typically used to distribute applications and installers on macOS. This module is only available on Apple platforms. \QBS enables you to build macOS disk images with custom backgrounds and icon layouts. Most applications on macOS are installed via a \c .dmg file, which is usually customized by using a custom image background and icon layout. Unfortunately, it is challenging to construct such DMG files correctly, because the layout relies on several undocumented proprietary file formats, some of which date back to the Mac OS Classic days, and which are even nested within one another. Most of the existing tools to create DMG files do so by using AppleScript to manipulate the Finder graphically to generate the appropriate icon layout, which is both unstable and incompatible with headless build servers, because the necessary OS services to launch graphical applications may not be running at all. Many projects create the primary \c .DS_Store file manually, and commit the result to their source repository. This binary blob is difficult to inspect and edit, and might not be backwards compatible with older versions of the OS, depending on how it was generated. \QBS takes a different approach. It generates the necessary files programmatically, in an entirely reproducible manner. There are no external dependencies that need to be separately installed nor do any binary blobs need to be committed to your source repository. \section2 Appearance Properties Appearance properties are used to control the contents of the .DS_Store file and its embedded Alias and Bookmark records, that will be generated by \QBS in order to control the appearance of the disk image when mounted in Finder. \section2 License Properties License properties are used to control the content and appearance of the license prompt displayed when a user attempts to mount the resulting disk image via Finder. \section2 Relevant File Tags \target filetags-dmg The file tags determine how the tagged files are handled. \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"dmg.input"} \li n/a \li 1.9 \li Tagged files are copied into the disk image. The \l{dmg::}{sourceBase} property controls the destination directory and hierarchy of copied files within the disk image. \row \li \c{"dmg.license.input"} \li \c{*.txt}, \c{*.rtf}, \c{*.html}, \c{*.doc}, \c{*.docx}, \c{*.odt}, \c{*.xml}, \c{*.webarchive} \li 1.9 \li Tagged files are converted into rich text and used for the license prompt when mounting the DMG. \row \li \c{"icns"} \li \c{*.icns} \li 1.3 \li The tagged file is added as the Apple Disk Image volume icon, which will show up in the Finder as an overlay on the file icon. \row \li \c{"tiff"} \li \c{*.tif}, \c{*.tiff} \li 1.9 \li The tagged file is used as the background image of the directory as shown in Finder when the DMG file is mounted. \endtable */ /*! \qmlproperty string dmg::volumeName The name of the disk image that is displayed in Finder when the DMG is mounted. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty bool dmg::badgeVolumeIcon Whether to render the user-supplied icon (\l{filetags-dmg}{"icns"}) on top of the default volume icon instead of using it directly. This generally gives the disk image icon a better and more consistent appearance. \defaultvalue \c{false} */ /*! \qmlproperty string dmg::format The format to create the disk image in. Allowed values include but are not limited to \c{"UDZO"}, \c{"UDBZ"}, and \c{"ULFO"}. \defaultvalue \c{"UDBZ"} */ /*! \qmlproperty int dmg::compressionLevel The \c zlib, \c bzip2, or \c lzfse compression level for UDZO, UDBZ, or ULFO disk images. \defaultvalue \c 9 in release mode, otherwise \c undefined. */ /*! \qmlproperty string dmg::sourceBase The base directory of the files that are going to be embedded in the DMG (\l{filetags-dmg}{"dmg.input"}). The source base directory is omitted from the target directory path of the DMG directory. \defaultvalue The directory of the current file to be embedded, relative to the product's source directory. */ /*! \qmlproperty string dmg::backgroundColor The background color of the disk image as seen when mounted in Finder. For the full list of supported color names and formats, see the \l{dmgbuild - Settings} documentation. For more information about how to use an image for the background instead, see \l{filetags-dmg}{"tiff"}. \nodefaultvalue */ /*! \qmlproperty int dmg::iconSize The width and height of the file icons as seen when the disk image is mounted in Finder. \defaultvalue \c{128} */ /*! \qmlproperty int dmg::windowX The x position of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{100} */ /*! \qmlproperty int dmg::windowY The y position of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{100} */ /*! \qmlproperty int dmg::windowWidth The width of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{640} */ /*! \qmlproperty int dmg::windowHeight The height of the Finder window that displays the disk image contents when it is mounted. \note The window height includes the height of the standard macOS title bar (22 points). \defaultvalue \c{480} */ /*! \qmlproperty list dmg::iconPositions A list of objects containing the \c{path}, \c{x}, and \c{y} properties, which correspond to disk image-relative file paths and visual coordinates of file icons in the disk image as seen when it is mounted in Finder. For example: \code dmg.iconPositions: [ {"path": "Applications", "x": 128, "y": 128}, {"path": "Foo Bar.app", "x": 256, "y": 128} ] \endcode This property is useful for specifying the positions of files where you do not have direct control over the corresponding \QBS artifact, or there is no corresponding \QBS artifact (for example, "Foo Bar.app" is a directory, which has no equivalent artifact in the build graph). For files to which you are directly applying the \l{filetags-dmg}{dmg.input} file tag, you should use the \l{dmg::}{iconX} and \l{dmg::}{iconY} properties instead. \nodefaultvalue */ /*! \qmlproperty int dmg::iconX The x position of the file icon in the Finder window that displayed the disk image contents when it is mounted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.input}. It cannot be used at the product level to affect all files. If you do not have access to the artifact corresponding to the file whose position you want to set, use the \l{dmg::}{iconPositions} property instead. \defaultvalue \c{windowWidth / 2} */ /*! \qmlproperty int dmg::iconY The y position of the file icon in the Finder window that displayed the disk image contents when it is mounted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.input}. It cannot be used at the product level to affect all files. If you do not have access to the artifact corresponding to the file whose position you want to set, use the \l{dmg::}{iconPositions} property instead. \defaultvalue \c{windowHeight / 2} */ /*! \qmlproperty string dmg::defaultLicenseLocale The locale of the default license to display when there is no license whose locale matches the system locale. \defaultvalue \c{"en_US"} */ /*! \qmlproperty string dmg::licenseLocale The locale of the license file. Defaults to a value guessed from the file path, specifically the base name of any \c .lproj directory found in the file's path. If the locale could not be determined from the file path and this property is not set, an error will be emitted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue Determined automatically. */ /*! \qmlproperty string dmg::licenseLanguageName The name of the language associated with the license file, localized to that language. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"English"} */ /*! \qmlproperty string dmg::licenseAgreeButtonText The text shown on the \e Agree button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Agree"} */ /*! \qmlproperty string dmg::licenseDisagreeButtonText The text shown on the \c Disagree button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Disagree"} */ /*! \qmlproperty string dmg::licensePrintButtonText The text shown on the \c Print button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Print"} */ /*! \qmlproperty string dmg::licenseSaveButtonText The text shown on the \e Save button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Save"} */ /*! \qmlproperty string dmg::licenseInstructionText An instruction text associated with the license file that will be shown on the license dialog, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"If you agree with the terms of this license, press \"Agree\" to install the software. If you do not agree, press \"Disagree\"."} */ /*! \qmlproperty string dmg::dmgSuffix The file extension for disk images. This should not normally need to be changed. \defaultvalue \c{".dmg"} */ /*! \qmlproperty string dmg::hdiutilPath The path to the \c hdiutil binary used to perform disk image related operations. This should not normally need to be changed. \defaultvalue \c{"/usr/bin/hdiutil"} */ /*! \qmlproperty string dmg::textutilPath The path to the \c textutil binary used to convert license agreement files to rich text format. This should not normally need to be changed. \defaultvalue \c{"/usr/bin/textutil"} */ qbs-src-3.3.1/doc/reference/modules/android-ndk-module.qdoc0000644000175100017510000000664315232633614023214 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Android.ndk \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building native Android libraries. The \c Android.ndk module contains the properties and rules to create native libraries for use in Android applications. Normally, you will not use this module directly, but instead work with the \l{DynamicLibrary}, \l{StaticLibrary} and \l Application items that \QBS provides. Here is what the project file for the \c hello-jni example that comes with the NDK could look like: \code CppApplication { name: "HelloJni" Android.sdk.packageName: "com.example.hellojni" qbs.architectures: ["arm", "x86"] files: "app/src/main/jni/hello-jni.c" } \endcode \section2 Relevant File Tags \target filetags-android-ndk \table \header \li Tag \li Since \li Description \row \li \c{"android.nativelibrary"} \li 1.4.0 \li Attached to dynamic libraries that will end up in APK packages. You do not normally need to use the tag explicitly, as it is the default type of the \l{DynamicLibrary} item for Android targets. \endtable */ /*! \qmlproperty string Android.ndk::abi The ABI name as it appears under \c "lib/" in the application package. Corresponds to \c APP_ABI in \c Android.mk. \nodefaultvalue */ /*! \qmlproperty string Android.ndk::buildId Value to pass to the --build-id linker flag. Plain --build-id option is used when buildId property is empty. \since Qbs 1.21 \defaultvalue \c "sha1" */ /*! \qmlproperty string Android.ndk::appStl The library to use for C++. The possible values are: \list \li \c "c++_shared" \li \c "c++_static" \endlist \defaultvalue \c{"c++_shared"} */ /*! \qmlproperty path Android.ndk::ndkDir The NDK base directory. \nodefaultvalue */ /*! \qmlproperty string Android.ndk::platform The versioned platform name. \defaultvalue \c{"android-16"} for 32 bit arm ABIs and \c{"android-21"} for all 64 bit ABIs and x86. x86 ABI has broken wstring support in android-16 to android-19. */ qbs-src-3.3.1/doc/reference/modules/config-build-module.qdoc0000644000175100017510000000327115232633614023356 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype config.build \inqmlmodule QbsModules \since Qbs 3.1 \brief Provides properties for configuring building. The \c{config.build} module contains properties that configure built-in items such as \l{Application}, \l{Library}, and \l{Plugin}. An example showing how change the default library type: \code qbs modules.config.build.libraryType:static \endcode For the list of available properties, see the \l{ConfigBuild} item. */ qbs-src-3.3.1/doc/reference/modules/ib-module.qdoc0000644000175100017510000002030715232633614021405 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype ib \inqmlmodule QbsModules \since Qbs 1.1 \brief Provides support for Apple Interface Builder and related tools and file types. The \c ib module contains properties and rules for building Interface Builder documents, storyboards, asset catalogs, and icon sets. This module is available on all platforms but is only usable on Apple platforms. \section2 Relevant File Tags \target filetags-ib The file tags determine how the tagged directories and files are handled. \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"assetcatalog"} \li \c{*.xcassets} \li 1.3 \li Tagged directories are compiled into compiled asset catalog archives (\c .car files) on supported platforms, or a collection of loose resource files. The resulting files will be automatically tagged \l{filetags-bundle}{bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"iconcomposer"} \li \c{*.icon} \li 3.2 \li Tagged directories are Icon Composer icon bundles created with the Icon Composer tool in Xcode 26 or later. These layered, adaptive icon files are compiled using \c actool alongside asset catalogs. The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. Icon Composer icons can coexist with traditional asset catalog icons in the same project. \row \li \c{"iconset"} \li \c{*.iconset} \li 1.3 \li Tagged directories are compiled into Apple ICNS files. The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"nib"} \li \c{*.nib}, \c{*.xib} \li 1.1 \li Tagged "NIB" and "XIB" files will be compiled. The output may be a flat file or a bundle (directory structure). The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"png"} \li \c{*.png} \li 1.9 \li Tagged PNG files may be converted into multi-resolution TIFFs. Source files should adopt the \l{Adopt the @2x Naming Convention} {@2x naming convention} in order to be properly grouped. The resulting files will be given the \l{filetags-dmg}{tiff} file tag. \row \li \c{"storyboard"} \li \c{*.storyboard} \li 1.3 \li Tagged storyboard files will be compiled. The output may be a flat file or a bundle (directory structure). The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \endtable */ /*! \qmlproperty bool ib::warnings Whether to print warnings when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty bool ib::errors Whether to print errors when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty bool ib::notices Whether to print notifications when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty stringList ib::flags Additional flags to pass to the underlying tool (\c ibtool, \c actool, \c iconutil). \nodefaultvalue \defaultvalue \c{true} */ /*! \qmlproperty string ib::ibtoolName \since Qbs 1.3 The name of the \c ibtool binary used to compile NIBs and storyboards. This property should not normally need to be changed. \defaultvalue \c{"ibtool"} */ /*! \qmlproperty string ib::ibtoolPath \since Qbs 1.3 The directory where the \c ibtool binary is located. This property should not normally need to be changed. \defaultvalue \c{ibtoolName} */ /*! \qmlproperty bool ib::flatten Compiles XIBs and storyboards into flattened (non-wrapper) files. Set to \c{false} to preserve editability of the resulting NIB and storyboard bundles in Interface Builder. This property should not normally need to be changed. \defaultvalue \c{true} */ /*! \qmlproperty string ib::module \since Qbs 1.3 Sets the name of the module that the NIB or storyboard is a part of. Requires Xcode 6 or newer. \nodefaultvalue */ /*! \qmlproperty bool ib::autoActivateCustomFonts \since Qbs 1.3 Instructs the \c ibtool compiler to add custom fonts to the application's \c Info.plist when compiling XIBs and storyboards, which will cause the fonts to activate upon application launch. Requires Xcode 6 or newer. \defaultvalue \c{true} */ /*! \qmlproperty string ib::actoolName \since Qbs 1.3 The name of the \c actool binary used to compile asset catalogs. This property should not normally need to be changed. \defaultvalue \c{"actool"} */ /*! \qmlproperty string ib::actoolPath \since Qbs 1.3 The directory where the \c actool binary is located. This property should not normally need to be changed. \defaultvalue \c{actoolName} */ /*! \qmlproperty string ib::appIconName \since Qbs 1.3 The name of the resource in the asset catalog that will be used as the application's icon. Used to generate the partial \c Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no application icon will be specified. \nodefaultvalue */ /*! \qmlproperty string ib::launchImageName \since Qbs 1.3 The name of the resource in the asset catalog that will be used as the application's launch image. Used to generate the partial \c Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no launch image will be specified. This property is specific to iOS. \nodefaultvalue */ /*! \qmlproperty bool ib::compressPngs \since Qbs 1.3 Whether to compress PNG image files when building asset catalogs. \defaultvalue \c{true} */ /*! \qmlproperty string ib::iconutilName \since Qbs 1.3 The name of the \c iconutil binary used to compile icon sets. This property should not normally need to be changed. \defaultvalue \c{"iconutil"} */ /*! \qmlproperty string ib::iconutilPath \since Qbs 1.3 The directory where the \c iconutil binary is located. This property should not normally need to be changed. \defaultvalue \c{iconutilName} */ qbs-src-3.3.1/doc/reference/modules/capnprotocpp-module.qdoc0000644000175100017510000000706315232633614023527 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype capnproto.cpp \inqmlmodule QbsModules \since Qbs 1.17 \brief Provides support for Cap'n Proto for the C++ language. The \c capnproto.cpp module provides support for generating C++ headers and sources from proto definition files using the \c capnpc tool. A simple qbs file that uses Cap'n Proto can be written as follows: \code CppApplication { Depends { name: "capnproto.cpp" } files: ["foo.capnp", "main.cpp"] } \endcode A generated header now can be included in the C++ sources: \code #include int main(int argc, char* argv[]) { ::capnp::MallocMessageBuilder message; auto foo = message.initRoot(); foo.setAnswer(42); return 0; } \endcode \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"capnproto.input"} \li \c{*.capnp} \li 1.17.0 \li Source files with this tag are considered inputs to the \c capnpc compiler. \endtable \section2 Dependencies This module depends on the \c capnp module and on the \c capnp-rpc module if \l{capnproto.cpp::useRpc}{useRpc} property is \c true. These modules are created by the \l{Module Providers} via the \c pkg-config tool. */ /*! \qmlproperty string capnproto.cpp::compilerName The name of the capnp binary. \defaultvalue \c "capnpc" */ /*! \qmlproperty string capnproto.cpp::compilerPath The path to the protoc binary. Use this property to override the auto-detected location. \defaultvalue \c auto-detected */ /*! \qmlproperty pathList capnproto.cpp::importPaths The list of import paths that are passed to the \c capnpc tool via the \c --import-path option. \defaultvalue \c [] */ /*! \qmlproperty string capnproto.cpp::outputDir The directory where the \c capnpc compiler generated files are placed. \defaultvalue \c product.buildDirectory + "/capnp" */ /*! \qmlproperty bool capnproto.cpp::useRpc Use this property to enable support for the RPC framework. A simple qbs file that uses rpc can be written as follows: \quotefile ../examples/capnproto/calculator_cpp/calculator_cpp.qbs \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/modules/ico-module.qdoc0000644000175100017510000000734015232633614021567 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype ico \inqmlmodule QbsModules \since Qbs 1.11 \brief Provides support for building ICO (.ico) and CUR (.cur) files. The \c ico module contains properties and rules for building Microsoft Windows Icon (.ico) and Microsoft Windows Cursor (.cur) files. \note This module relies on the \c icotool command-line tool from the \c icotools package, which must be installed separately and found in the \c PATH or an appropriate system binaries directory for your system (for example, \c /usr/bin or \c /usr/local/bin). \section2 Relevant File Tags \target filetags-ico \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"cur"} \li n/a \li 1.11 \li The rule that creates cursor (.cur) files attaches this tag to its output artifact. \row \li \c{"ico"} \li n/a \li 1.11 \li The rule that creates icon (.ico) files attaches this tag to its output artifact. \row \li \c{"png"} \li \c{"*.png"} \li 1.11 \li Source files with this tag indicate PNG files which are used as inputs to create icon or cursor files. \endtable */ /*! \qmlproperty int ico::cursorHotspotX The cursor hotspot x coordinate. Only relevant when building .cur files. This property must be set individually for each input PNG file. \note \c icoutils version 0.32 or greater is required to set the hotspot in cursor files with multiple images. \nodefaultvalue */ /*! \qmlproperty int ico::cursorHotspotY The cursor hotspot y coordinate. Only relevant when building .cur files. This property must be set individually for each input PNG file. \note \c icoutils version 0.32 or greater is required to set the hotspot in cursor files with multiple images. \nodefaultvalue */ /*! \qmlproperty bool ico::raw Whether to store the input file as a raw PNG, as supported in Windows Vista. Only relevant when building .ico files. This property must be set individually for each input PNG file. It is recommended to set this value only for icon sizes larger than or equal to 256x256. \defaultvalue \c{false} */ /*! \qmlproperty string ico::icotoolFilePath The full path of the \c icotool binary. This property should not normally need to be changed if \QBS was able to automatically detect it. \defaultvalue Determined automatically. */ qbs-src-3.3.1/doc/reference/modules/wix-module.qdoc0000644000175100017510000001753615232633614021634 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype wix \inqmlmodule QbsModules \since Qbs 1.2 \brief Provides Windows Installer XML Toolset support. The \c wix module contains properties and rules for building MSI and EXE setup packages with the \l{Windows Installer XML Toolset}. This module is available on all platforms. \section2 Relevant File Tags \target filetags-wix \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"msi"} \li - \li 1.2 \li The rule that creates the Microsoft Installer setup file attaches this tag to its output artifact. \row \li \c{"wixpdb"} \li - \li 1.2 \li The rule that creates the Microsoft Installer setup file or WiX setup executable attaches this tag to the associated debug symbol file. \row \li \c{"wixsetup"} \li - \li 1.2 \li The rule that creates the WiX setup executable attaches this tag to its output artifact. \row \li \c{"wxi"} \li \c{*.wxi} \li 1.2 \li This tag is attached to WiX include files. \row \li \c{"wxl"} \li \c{*.wxl} \li 1.2 \li This tag is attached to WiX localization files. \row \li \c{"wxs"} \li \c{*.wxs} \li 1.2 \li This tag is attached to WiX source files. Each source file will be compiled into one WiX object file. \endtable */ /*! \qmlproperty bool wix::debugInformation Whether to generate debug information. \sa {qbs::debugInformation}{qbs.debugInformation} \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty stringList wix::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode wix.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty bool wix::enableQbsDefines Whether to define preprocessor macros corresponding to values from the project and product objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \defaultvalue \c{true} */ /*! \qmlproperty bool wix::visualStudioCompatibility Whether to pass most of the same preprocessor macros to the compiler as Visual Studio does. This allows easier authoring of WiX files that are compatible with both \QBS and MSBuild. \defaultvalue \c{true} */ /*! \qmlproperty pathList wix::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty bool wix::treatWarningsAsErrors Whether warnings will be handled as errors and cause the build to fail. \defaultvalue \c{false} */ /*! \qmlproperty string wix::warningLevel The severity of warnings to emit. The higher the level, the more warnings will be shown. Possible values include: \c{"none"}, \c{"normal"}, \c{"pedantic"} \defaultvalue \c{"normal"} */ /*! \qmlproperty bool wix::verboseOutput Whether to display verbose output from the compiler and linker. \defaultvalue \c{false} */ /*! \qmlproperty stringList wix::compilerFlags A list of additional flags for the Candle compiler. \nodefaultvalue */ /*! \qmlproperty stringList wix::linkerFlags A list of additional flags for the Light linker. \nodefaultvalue */ /*! \qmlproperty stringList wix::cultures A list of localizations to include in the MSI. If left undefined, includes all localizations. \nodefaultvalue */ /*! \qmlproperty stringList wix::extensions A list of extension assemblies to link into the output. Possible values include: \list \li custom assemblies \li \c{"WixBalExtension"} \li \c{"WixComPlusExtension"} \li \c{"WixDependencyExtension"} \li \c{"WixDifxAppExtension"} \li \c{"WixDirectXExtension"} \li \c{"WixFirewallExtension"} \li \c{"WixGamingExtension"} \li \c{"WixIisExtension"} \li \c{"WixMsmqExtension"} \li \c{"WixNetFxExtension"} \li \c{"WixPSExtension"} \li \c{"WixSqlExtension"} \li \c{"WixTagExtension"} \li \c{"WixUIExtension"} \li \c{"WixUtilExtension"} \li \c{"WixVSExtension"} \endlist \defaultvalue \c{["WixBalExtension"]} if the product type is an EXE setup application, otherwise \c{undefined}. */ /*! \qmlproperty string wix::version The WiX version. Consists of four numbers separated by dots. For example, "3.7.1224.0". \nodefaultvalue */ /*! \qmlproperty int wix::versionMajor The WiX major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int wix::versionMinor The WiX minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list wix::versionParts The WiX version as a list. For example, WiX version 3.7.1224.0 would correspond to a value of \c[3, 7, 1224, 0]. \defaultvalue \c [] */ /*! \qmlproperty int wix::versionPatch The WiX patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int wix::versionBuild The fourth WiX version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path wix::toolchainInstallPath The WiX installation directory. This property should not normally need to be changed. \defaultvalue Determined automatically by searching the registry for the latest version. */ /*! \qmlproperty path wix::toolchainInstallRoot The WiX binaries directory. This property should not normally need to be changed. \defaultvalue Determined automatically by searching the registry for the latest version. */ /*! \qmlproperty string wix::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"candle.exe"} */ /*! \qmlproperty string wix::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \l{wix::}{compilerName} */ /*! \qmlproperty string wix::linkerName The name of the linker binary. This property should not normally need to be changed. \defaultvalue \c{"light.exe"} */ /*! \qmlproperty string wix::linkerPath The directory where the linker binary is located. This property should not normally need to be changed. \defaultvalue \l{wix::}{linkerName} */ qbs-src-3.3.1/doc/reference/modules/autotest-module.qdoc0000644000175100017510000000503615232633614022665 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype autotest \inqmlmodule QbsModules \since Qbs 1.13 \brief Allows to fine-tune autotest execution. The \c autotest module provides properties that allow autotest applications to specify how exactly they should be run. */ /*! \qmlproperty bool autotest::allowFailure Autotests for which this property is \c true can return a non-zero exit code without causing the entire \l AutotestRunner to fail. Use this for tests that are known to be unreliable. \defaultvalue \c false */ /*! \qmlproperty stringList autotest::arguments The list of arguments to invoke the autotest with. If not specified, then the \l{AutotestRunner::arguments}{arguments} property of the \l AutotestRunner that invokes the autotest is used. \nodefaultvalue */ /*! \qmlproperty string autotest::workingDir The working directory for running the autotest. If not specified, then the \l{AutotestRunner::workingDir}{workingDir} property of the \l AutotestRunner that invokes the autotest is used. \nodefaultvalue */ /*! \qmlproperty int autotest::timeout The time limit for the execution of the autotest. If not specified, the \l{AutotestRunner::timeout}{timeout} property of the \l AutotestRunner that invokes the autotest is used. \nodefaultvalue \since Qbs 1.15 */ qbs-src-3.3.1/doc/reference/modules/qbs-module.qdoc0000644000175100017510000006064415232633614021610 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype qbs \inqmlmodule QbsModules \since Qbs 1.0 \brief Comprises general properties. The \c qbs module is implicitly loaded in every product. It contains properties of the current build environment, independent of the used programming languages and toolchains. \section2 Installation Properties Typically, you use \l{Group} items to specify the target directories for installing files. To install a group of files, set the \l{qbs::install} {qbs.install} property of the Group to \c true. The value of \l{qbs::installDir}{qbs.installDir} specifies the path to the directory where the files will be installed. You can specify a base directory for all installation directories as the value of \l{qbs::installPrefix} {qbs.installPrefix}. For example, the following properties specify where a set of QML files and an application executable are installed on Windows and Linux: \badcode Application { name: "myapp" Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: condition: qbs.targetOS.includes("unix") ? "share/myapp" : "resources" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } qbs.installPrefix: condition: qbs.targetOS.includes("unix") ? "usr/local" : "MyApp" } \endcode On Windows, the QML files will ultimately get installed in \c{MyApp\resources} and the application executable in \c MyApp\bin, for instance under \c{C:\Program Files}. On Linux, the QML files will be installed in \c /usr/local/share/myapp and the executable in \c /usr/local/bin. By default, \l{qbs::installRoot}{qbs.installRoot} creates the \c install-root directory in the build directory for packaging the binaries before installation. It is a temporary directory that is usually not available when the application is run, and it should therefore not be set in the project files. You can override the default value from the command line, as described in \l{Installing Files}. \section2 Multiplexing Properties The following properties are specific to \l{Multiplexing} {product multiplexing}: \list \li \l{qbs::}{architectures} \li \l{qbs::}{buildVariants} \li \l{qbs::}{profiles} \endlist */ /*! \qmlproperty string qbs::configurationName \since Qbs 1.6 \readonly The name of the current build configuration. The build configuration is set via the command line parameter \c config. For more information, see \l{build}{build}. \defaultvalue \c{"default"} */ /*! \qmlproperty string qbs::buildVariant The name of the build variant for the current build. Possible values are \c{"debug"}, \c{"release"} and \c{"profiling"}. A debug build usually contains additional debug symbols that are needed for debugging the application and has optimizations turned off. A profiling build usually contains debug symbols and has optimizations turned on. This is useful for profiling tools or when you need to retain debug symbols in a release build. A release build is a build without debug information and with optimizations enabled. \defaultvalue \c{"release"} if \l{qbs::configurationName}{qbs.configurationName} is \c{"release"}, \c{"profiling"} if \l{qbs::configurationName}{qbs.configurationName} is \c{"profiling"}. Otherwise \c{"debug"} */ /*! \qmlproperty bool qbs::debugInformation Whether to generate debug information. \defaultvalue \c{true} if \l{qbs::buildVariant}{qbs.buildVariant} is \c{"debug"} or \c{"profiling"}. Otherwise \c{false}. */ /*! \qmlproperty bool qbs::enableDebugCode Whether to enable debug functionality in the product. Not to be confused with generation of debug symbols or the code optimization level. The property changes the following things when enabled: \list \li Passes a flag to the Windows linker to link against a debug Windows CRT (common runtime) library (for example /MTd instead of /MT) \endlist The property changes the following things when disabled: \list \li Passes the \c{NDEBUG} define to the compiler \endlist Typically, this property is enabled for debug builds and disabled for release or profiling builds. \defaultvalue \c{true} for debug builds, \c{false} otherwise. */ /*! \qmlproperty string qbs::optimization The general type of optimization that should be performed by all toolchains. Allowed values are: \list \li \c{"fast"} \li \c{"none"} \li \c{"small"} \endlist \defaultvalue \c{"none"} if \l{qbs::buildVariant}{qbs.buildVariant} is \c{"debug"}. Otherwise \c{"fast"}. */ /*! \qmlproperty string qbs::targetPlatform \since 1.11 The OS you want to build the project for. This property is typically set in a profile or for a particular product where the target OS is always known (such as an Apple Watch app written in native code). For example, a profile used for building for the iOS Simulator platform will have this property set to the \c ios-simulator value: \code profiles.xcode-iphonesimulator.qbs.targetPlatform: "ios-simulator" \endcode You should generally treat this property as \e{write-only} and avoid using it to test for the current target OS. Instead, use the \l{qbs::}{targetOS} property for conditionals. \section2 Relation between targetPlatform and targetOS This table describes the possible values and matching between the \c targetPlatform and the \l{qbs::}{targetOS} properties: \table \header \li Target Platform \li Target OS \row \li \c{"aix"} \li \c{["aix", "unix"]} \row \li \c{"android"} \li \c{["android", "linux", "unix"]} \row \li \c{"dos"} \li \c{["dos"]} \row \li \c{"freebsd"} \li \c{["freebsd", "bsd", "unix"]} \row \li \c{"haiku"} \li \c{["haiku"]} \row \li \c{"hpux"} \li \c{["hpux", "unix"]} \row \li \c{"hurd"} \li \c{["hurd", "unix"]} \row \li \c{"integrity"} \li \c{["integrity", "unix"]} \row \li \c{"ios"} \li \c{["ios", "darwin", "bsd", "unix"]} \row \li \c{"ios-simulator"} \li \c{["ios-simulator", "ios", "darwin", "bsd", "unix"]} \row \li \c{"linux"} \li \c{["linux", "unix"]} \row \li \c{"lynx"} \li \c{["lynx"]} \row \li \c{"macos"} \li \c{["macos", "darwin", "bsd", "unix"]} \row \li \c{"netbsd"} \li \c{["netbsd", "bsd", "unix"]} \row \li \c{"openbsd"} \li \c{["openbsd", "bsd", "unix"]} \row \li \c{"os2"} \li \c{["os2"]} \row \li \c{"qnx"} \li \c{["qnx", "unix"]} \row \li \c{"solaris"} \li \c{["solaris", "unix"]} \row \li \c{"tvos"} \li \c{["tvos", "darwin", "bsd", "unix"]} \row \li \c{"tvos-simulator"} \li \c{["tvos-simulator", "tvos", "darwin", "bsd", "unix"]} \row \li \c{"unix"} \li \c{["unix"]} \row \li \c{"vxworks"} \li \c{["vxworks"]} \row \li \c{"watchos"} \li \c{["watchos", "darwin", "bsd", "unix"]} \row \li \c{"watchos-simulator"} \li \c{["watchos-simulator", "watchos", "darwin", "bsd", "unix"]} \row \li \c{"windows"} \li \c{["windows"]} \row \li \c{"none"} \li \c{["none"]} \row \li \c{undefined} \li \c{[]} \endtable \note The "none" value is usually used for a bare-metal platforms. \sa {Target Platforms} \defaultvalue \l{platform}{Host.platform()} */ /*! \qmlproperty string qbs::architecture The target platform's processor architecture. \c{undefined} indicates that the target platform is architecture-independent (for example the CLR or JVM). This property is typically set in a profile. Commonly used values are: \c{"x86"}, \c{"x86_64"}, and \c{"arm"}. \section2 Supported Processor Architectures This table describes the possible values of the \l{qbs::}{architecture} property: \table \header \li Architecture \li Description \row \li \c{"78k"} \li 16- and 8-bit accumulator-based register-bank CISC architecture microcontroller family manufactured by Renesas Electronics \row \li \c{"alpha"} \li 64-bit ISA architecture of the Alpha family processors developed by DEC \row \li \c{"arm"} \li 32-bit RISC architecture for computer processors developed by Acorn RISC Machine \note There are a lot of sub-variants of the ARM architecture. Some specialized \QBS modules differentiate between them, making use of values such as \c "armv7a". Please consult the respective module-specific documentation for information on what kind of value to use. \row \li \c{"arm64"} \li 64-bit RISC architecture for computer processors developed by Acorn RISC Machine \row \li \c{"avr"} \li 8-bit modified Harvard RISC architecture microcontroller family manufactured by Microchip Technology \row \li \c{"avr32"} \li 32-bit RISC architecture microcontroller family developed by Atmel \row \li \c{"c166"} \li 16-bit architecture microcontroller family developed by Infineon \row \li \c{"cr16"} \li 16-bit compact RISC architecture microcontroller family developed by National Semiconductor \row \li \c{"e2k"} \li 512-bit Russian wide VLIW microprocessor developed by Moscow Center of SPARC Technologies (MCST) and fabricated by TSMC \row \li \c{"hcs8"} \li 8-bit HC08 and S08 microcontroller family from Freescale Semiconductor \row \li \c{"hcs12"} \li 16-bit HC12 and S12 microcontroller family from Freescale Semiconductor \row \li \c{"hppa"} \li 64-bit PA-RISC processor architecture developed by Hewlett-Packard \row \li \c{"ia64"} \li 64-bit ISA architecture of the Itanium family processors developed by Intel \row \li \c{"m16c"} \li 16-bit CISC microcontrollers featuring high ROM code efficiency manufactured by Renesas Electronics \row \li \c{"m32c"} \li 32- and 16-bit CISC microcontrollers featuring high ROM code efficiency manufactured by Renesas Electronics \row \li \c{"m32r"} \li 32-bit RISC microcontrollers for general industrial and car-mounted systems, digital AV equipment, digital imaging equipment manufactured by Renesas Electronics \row \li \c{"m68k"} \li 16- and 32-bit CISC microprocessor, developed by Motorola Semiconductor Products Sector, and further improved as ColdFire architecture developed by NXP \row \li \c{"mcs251"} \li 8-, 16-, and 32-bit microcontroller family which is a next binary compatible generation for the \c "mcs51" family \row \li \c{"mcs51"} \li 8-bit Harvard architecture microcontroller family developed by Intel \row \li \c{"mips"} \li 32-bit RISC microprocessor without interlocked pipelined stages architecture developed by MIPS Computer Systems \row \li \c{"mips64"} \li 64-bit RISC microprocessor without interlocked pipelined stages architecture developed by MIPS Computer Systems \row \li \c{"msp430"} \li 16-bit mixed-signal microcontroller family manufactured by Texas Instruments \row \li \c{"ppc"} \li 32-bit RISC architecture processor family developed by Apple–IBM–Motorola alliance \row \li \c{"ppc64"} \li 64-bit RISC architecture processor family developed by Apple–IBM–Motorola alliance \row \li \c{"r32c"} \li 32-bit CISC microcontrollers with improved code efficiency and processing performance manufactured by Renesas Electronics \row \li \c{"rh850"} \li 32-bit automotive microcontroller family manufactured by Renesas Electronics \row \li \c{"riscv"} \li Open and free standard instruction set architecture based on established RISC principles \row \li \c{"rl78"} \li 16- and 8-bit accumulator-based register-bank CISC architecture with 3-stage instruction pipelining microcontroller family manufactured by Renesas Electronics \row \li \c{"rx"} \li High performance 32-bit CISC microcontroller family manufactured by Renesas Electronics \row \li \c{"s390x"} \li 64- and 32-bit System/390 processor architecture developed by IBM \row \li \c{"sh"} \li 32-bit RISC architecture processor family developed by Hitachi and currently manufactured by Renesas Electronics \row \li \c{"sparc"} \li 32-bit RISC architecture processor family developed by Sun Microsystems and Fujitsu \row \li \c{"sparc64"} \li 64-bit RISC architecture processor family developed by Sun Microsystems and Fujitsu \row \li \c{"stm8"} \li 8-bit microcontroller family manufactured by STMicroelectronics \row \li \c{"v850"} \li 32-bit RISC microcontroller family manufactured by Renesas Electronics \row \li \c{"x86"} \li 32-bit ISA architecture processor family developed by Intel \row \li \c{"x86_16"} \li 16-bit ISA architecture processor family developed by Intel \row \li \c{"x86_64"} \li 64-bit ISA architecture processor family developed by AMD \row \li \c{"xtensa"} \li 32-bit architecture with a compact 16- and 24-bit instruction set developed by Tensilica \endtable \nodefaultvalue */ /*! \qmlproperty stringList qbs::toolchain Contains the list of string values describing the toolchain and toolchain family that is used to build a project. This property is deduced from the \l{qbs::}{toolchainType} property and is typically used to test for a particular toolchain or toolchain family in conditionals: \code Properties { // flags for GCC condition: qbs.toolchain.includes("gcc") cpp.commonCompilerFlags: ... } Properties { // flags for MSVC condition: qbs.toolchain.includes("msvc") cpp.commonCompilerFlags: ... } \endcode Unlike \l{qbs::}{toolchainType}, which contains a single value, \c qbs.toolchain is a string list which also contains the toolchain family. This allows to make conditions and checks simpler. For example, instead of: \code (qbs.toolchainType === "xcode" || qbs.toolchainType === "clang" || qbs.toolchainType === "gcc") \endcode use: \code qbs.toolchain.includes("gcc") \endcode since XCode, GCC and Clang belong to the \c "gcc" family. \section2 Relation between toolchainType and toolchain This table describes the possible values and matching between the \l{qbs::}{toolchainType} and the \c toolchain properties: \table \header \li Toolchain Type \li Toolchain \row \li \c{"clang"} \li \c{["clang", "llvm", "gcc"]} \row \li \c{"clang-cl"} \li \c{["clang-cl", "msvc"]} \row \li \c{"cosmic"} \li \c{["cosmic"]} \row \li \c{"dmc"} \li \c{["dmc"]} \row \li \c{"gcc"} \li \c{["gcc"]} \row \li \c{"iar"} \li \c{["iar"]} \row \li \c{"keil"} \li \c{["keil"]} \row \li \c{"llvm"} \li \c{["llvm", "gcc"]} \row \li \c{"mingw"} \li \c{["mingw", "gcc"]} \row \li \c{"msvc"} \li \c{["msvc"]} \row \li \c{"qcc"} \li \c{["qcc"]} \row \li \c{"sdcc"} \li \c{["sdcc"]} \row \li \c{"watcom"} \li \c{["watcom"]} \row \li \c{"xcode"} \li \c{["xcode", "clang", "llvm", "gcc"]} \endtable \nodefaultvalue */ /*! \qmlproperty string qbs::toolchainType \since Qbs 1.11 The toolchain that is going to be used for this build. For example, to build a project using the \c "clang" toolchain, simply do \code qbs build qbs.toolchainType:clang \endcode You should generally treat this property as \e{write-only} and avoid using it to test for the current toolchain. Instead, use the \l{qbs::}{toolchain} property for conditionals. Typical values include: \c{"gcc"}, \c{"clang"}, \c{"clang-cl"}, \c{"mingw"}, \c{"msvc"}, and \c{"xcode"}. Also see \l{Relation between toolchainType and toolchain}. By default, \c qbs.toolchainType is automatically detected based on the \l{qbs::}{targetOS} property: \table \header \li Target OS \li Toolchain \row \li \c{"darwin"} \li \c{"xcode"} \row \li \c{"freebsd"} \li \c{"clang"} \row \li \c{"haiku"} \li \c{"gcc"} \row \li \c{"qnx"} \li \c{"qcc"} \row \li \c{"unix"} \li \c{"gcc"} \row \li \c{"vxworks"} \li \c{"gcc"} \row \li \c{"windows"} \li \c{"msvc"} \endtable \defaultvalue Determined automatically. */ /*! \qmlproperty string qbs::sysroot The \c sysroot of the target platform. This property is typically set in a profile for cross-compiling. \nodefaultvalue */ /*! \qmlproperty path qbs::shellPath \since Qbs 1.5 The platform-specific file path corresponding to the command line interpreter. On Windows, this is the path to \c{cmd.exe}, which is held in the \c{COMSPEC} environment variable (typically, \c{C:/Windows/System32/cmd.exe}), On Unix-like platforms, this is \c{/bin/sh}. \defaultvalue \c{"%COMSPEC%"} on Windows, \c{"/bin/sh"} on Unix */ /*! \qmlproperty stringList qbs::targetOS \readonly Contains the list of string values describing the OS and OS family that is used to build a project. This property is calculated based on the \l{qbs::}{targetPlatform} property and is typically used to test for a particular OS or OS family in conditionals: \code Group { // Includes all Unix-like platforms, such as: Linux, BSD, Apple platforms and others. condition: qbs.targetOS.includes("unix") files: ... } Group { // Includes all Apple platforms, such as macOS, iOS, and iOS Simulator. condition: qbs.targetOS.includes("darwin") files: ... } Group { // Includes only macOS condition: qbs.targetOS.includes("macos") files: ... } \endcode Avoid using \l{qbs::}{targetPlatform} for this purpose. For example, instead of: \code qbs.targetPlatform === "macos" || qbs.targetPlatform === "ios" || qbs.targetPlatform === "tvos" || qbs.targetPlatform === "watchos" \endcode use \code qbs.targetOS.includes("darwin") \endcode However, in some cases using \l{qbs::}{targetPlatform} would be acceptable, such as when the resulting condition would be simpler while still being correct: \code qbs.targetPlatform === "linux" \endcode versus \code qbs.targetOS.includes("linux") && !qbs.targetOS.includes("android") \endcode For the complete list of possible values, see \l{Relation between targetPlatform and targetOS}. \nodefaultvalue */ /*! \qmlproperty string qbs::version \readonly \since Qbs 1.4.1 The version number of \QBS as a string. For example, \c "1.4.1". */ /*! \qmlproperty int qbs::versionMajor \readonly \since Qbs 1.4.1 The major version number of \QBS. */ /*! \qmlproperty int qbs::versionMinor \readonly \since Qbs 1.4.1 The minor version number of \QBS. */ /*! \qmlproperty int qbs::versionPatch \readonly \since Qbs 1.4.1 The patch version number of \QBS. */ /*! \qmlproperty bool qbs::install Whether to install a certain set of files. This property is typically set in a \l{Group} item to mark a number of files as installable. \note Artifacts for which this property is enabled automatically receive the file tag \c "installable". This is useful for writing packaging-related rules. \defaultvalue \c{false} */ /*! \qmlproperty string qbs::installSourceBase \since Qbs 1.4 The base directory of the local files that are going to be installed. The source base directory is omitted from the target directory path specified in \l{qbs::}{installDir}. \defaultvalue The directory of the current file to be installed, relative to the product's source directory. */ /*! \qmlproperty string qbs::installDir The installation directory for the files of a \l{Product}{product} or a \l{Group}. The value of this property is a path that is relative to \l{qbs::} {installPrefix}. \nodefaultvalue */ /*! \qmlproperty string qbs::installPrefix \since Qbs 1.1 The global installation prefix. It is implicitly prepended to all values of \l{qbs::}{installDir}. The value of this property itself is relative to the \l{qbs::}{installRoot} in the context of installation. \defaultvalue \c "/usr/local" on Unix, \c "" otherwise */ /*! \qmlproperty string qbs::installRoot \since Qbs 1.4 The global installation root. It is implicitly prepended to all values of \l{qbs::}{installPrefix} in the context of installation. \note This property is fundamentally different from \l{qbs::}{installDir} and \l{qbs::}{installPrefix} in that it must not be visible to the code being built. In fact, the install root is often just a temporary location used to package the binaries, which should therefore not assume they will be in that location at run-time. For the same reason, this property is usually not set from within project files. \defaultvalue \c{/install-root} */ /*! \qmlproperty stringList qbs::architectures \since Qbs 1.9 The architectures the product will be built for. \nodefaultvalue */ /*! \qmlproperty stringList qbs::buildVariants \since Qbs 1.9 The build variants the product will be built for. \nodefaultvalue */ /*! \qmlproperty stringList qbs::profiles \since Qbs 1.9 The profiles for which the product should be built. For each profile listed here, one instance of the product will be built according to the properties set in the respective profile. \defaultvalue \l{Project::profile}{[project.profile]} */ qbs-src-3.3.1/doc/reference/modules/qt-android_support-module.qdoc0000644000175100017510000000562115232633614024653 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.android_support \inqmlmodule QbsModules \brief Provides Qt support for the Android platform. The \c Qt.android_support module provides the glue for \QBS' Qt and Android support. It is automatically pulled in by \c Qt.core, so you do not need to add an explicit dependency to it in your product, unless you want to set one of its properties. */ /*! \qmlproperty string Qt.android_support::qmlRootDir The root directory of the product's QML files. This information is passed to the \c androiddeployqt tool, which will use it to decide which resources to include in the APK file. \defaultvalue \c product.sourceDirectory */ /*! \qmlproperty stringList Qt.android_support::deploymentDependencies Use this property to completely override the Qt deployment dependencies of your app. Corresponds to qmake's ANDROID_DEPLOYMENT_DEPENDENCIES. \defaultvalue \c undefined */ /*! \qmlproperty stringList Qt.android_support::extraPlugins Additional non-asset files to be packaged. Corresponds to qmake's ANDROID_EXTRA_PLUGINS. \defaultvalue \c undefined */ /*! \qmlproperty stringList Qt.android_support::extraLibs Additional libs to be packaged and loaded on start-up (mind the order). Corresponds to qmake's ANDROID_EXTRA_LIBS. \defaultvalue \c undefined */ /*! \qmlproperty stringList Qt.android_support::qmlImportPaths Additional directories to search for QML imports. \defaultvalue \c undefined \since 1.22 */ /*! \qmlproperty bool Qt.android_support::verboseAndroidDeployQt Enable this property if you want verbose output from the \c androiddeployqt tool. \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/modules/bundle-module.qdoc0000644000175100017510000004447015232633614022273 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype bundle \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides Core Foundation bundle support. The \c bundle module contains properties and rules for building and working with Core Foundation bundles on Apple platforms (commonly known as CFBundles or simply \e bundles), directories with a standardized hierarchical structure that hold executable code and resources. Examples include applications, frameworks, and plugins. This module is available on all platforms but is currently only useful on Apple platforms. \note Core Foundation bundles are not to be confused with Mach-O loadable modules, which are also referred to as (loadable) \e bundles in Apple parlance. In \QBS, Core Foundation bundles are referred to as \e bundles, while Mach-O loadable bundles are referred to as \e {loadable modules}. \target dependency-parameters-bundle \section2 Dependency Parameters \table \header \li Parameter \li Type \li Since \li Default \li Description \row \li \c{isForMainBundle} \li \c{bool} \li 3.1 \li true \li If \c{false}, the dependency will not be copied into this main bundle. \endtable \section2 Relevant File Tags \target filetags-bundle \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"bundle.content"} \li - \li 1.8 \li Attached to the output artifacts of the rule that produces the bundle. \row \li \c{"infoplist"} \li \c{Info.plist}, \c{*-Info.plist} \li 1.5 \li Source files with this tag are Info property lists files or fragments that are merged into the bundle's final \c Info.plist. \row \li \c{"bundle.input.public_hpp"} \li n/a \li 3.0 \li Source files with this tag will be copied to the \c{Headers} directory within a bundle. \row \li \c{"bundle.input.private_hpp"} \li n/a \li 3.0 \li Source files with this tag will be copied to the \c{PrivateHeaders} directory within a bundle. \row \li \c{"bundle.input.resources"} \li n/a \li 3.0 \li Source files with this tag will be copied to the \c{Resources} directory within a bundle. \endtable \section2 Main bundles It is possible to create a bundle that contains other products within itself. This is useful for big applications which depend on custom frameworks and/or other applications. Creating a main bundle is quite easy, simply set the \l{isMainBundle} property to \c true and all dependencies will be copied automatically to appropriate locations: \code CppApplication { name: "main" files: "main.cpp" Depends { name: "mylib" } Depends { name: "bundle" } bundle.isMainBundle: true } DynamicLibrary { name: "mylib" Depends { name: "cpp" } files: "mylib.cpp" install: false // skip installing the framework } \endcode In order to exclude a dependency from the main bundle, set the \l{bundle::isForMainBundle} property to \c false in the product: \code DynamicLibrary { name: "otherlib" Depends { name: "bundle" } bundle.isForMainBundle: false } \endcode Alternatively, set the \c{bundle.isForMainBundle} dependency parameter in the main bundle itself: \code CppApplication { name: "main" Depends { name: "otherlib"; bundle.isForMainBundle: false } // ... } \endcode See the full example the the \l{https://github.com/qbs/qbs/tree/master/examples/main-bundle}{examples} folder. \note Currently, static frameworks and libraries are not supported as an input to a main bundle. */ /*! \qmlproperty bool bundle::isBundle Whether the product should actually be packaged as a bundle as opposed to a flat file. This allows a product indirectly dependent on the \c{bundle} module to retain control of whether it should actually be built as a bundle. \defaultvalue \c{true} for applications and dynamic libraries on Apple platforms, \c{false} otherwise. */ /*! \qmlproperty bool bundle::isForMainBundle \since Qbs 3.1 Set this property to \c false to skip copying of this product into any dependent main bundle. \defaultvalue \c true. \sa isMainBundle */ /*! \qmlproperty bool bundle::isMainBundle \since Qbs 3.1 Whether to copy dependencies into this bundle. \defaultvalue \c false \sa isForMainBundle */ /*! \qmlproperty bool bundle::isShallow \readonly Whether the bundle directory tree is \e shallow. That is, whether it lacks a \c Contents subdirectory. This is the default on all platforms other than macOS. \defaultvalue \c{false} on macOS, otherwise \c{true}. */ /*! \qmlproperty string bundle::identifierPrefix A prefix for the product's bundle identifier. If \l{bundle::}{identifier} is left unset, the bundle identifier will be a concatenation of this value and the \l{Product::targetName}{Product.targetName} property formatted as an RFC-1034 identifier, separated by a period (.). This corresponds to the organization identifier in Xcode. \defaultvalue \c{org.example} */ /*! \qmlproperty string bundle::identifier The bundle's identifier. If left unset, the bundle identifier will be a concatenation of the \l{bundle::}{identifierPrefix} value and the \l{Product::targetName}{Product.targetName} propertyy formatted as an RFC-1034 identifier, separated by a period (.). \defaultvalue A combination of \l{bundle::}{identifierPrefix} and the product's target name formatted as an RFC-1034 identifier. */ /*! \qmlproperty string bundle::extension The extension of the bundle's wrapper directory, without the leading period (.). This property should not normally need to be set unless creating a custom bundle type. \defaultvalue \c{"app"} for \c{"APPL"} packages, \c{"framework"} for \c{"FMWK"} packages, and \c{"bundle"} for \c{"BNDL"} and custom packages. */ /*! \qmlproperty string bundle::packageType The four-letter file type code of the bundle, specified in the bundle's \c PkgInfo file and in the bundle's \c Info.plist as the value for the \c CFBundlePackageType key. This property should almost never need to be changed, even though specifying an alternative package type for custom bundles is allowed. \defaultvalue \c{"APPL"} for applications, \c{"FMWK"} for frameworks, and \c{"BNDL"} for custom bundles. */ /*! \qmlproperty bool bundle::generatePackageInfo \since Qbs 1.5 Whether to generate a \c PkgInfo file for the bundle. This property should almost never need to be changed, even though enabling it when specifying an alternative package type for custom bundles using \l{bundle::}{packageType} is allowed. \defaultvalue \c{true} for applications, otherwise \c{false}. */ /*! \qmlproperty string bundle::signature The four-letter signature specific to the bundle, also known as the creator code, specified in the bundle's \c PkgInfo file and in the bundle's \c Info.plist as the value for the \c CFBundleSignature key. This property should normally never need to be set. \defaultvalue \c{"????"} */ /*! \qmlproperty string bundle::bundleName The file name of the bundle's wrapper directory. This property should not normally need to be changed. \defaultvalue A combination of the product's \l{Product::}{targetName} and bundle's \l{bundle::}{extension}. */ /*! \qmlproperty string bundle::frameworkVersion For framework bundles, the version of the framework. Not used for other package types. \defaultvalue \c{"A"} */ /*! \qmlproperty pathList bundle::publicHeaders A list of public header files to copy to a framework bundle's \c Headers subdirectory. It is recommended to attach the \c{"bundle.input.public_hpp"} file tag to headers instead: \code CppApplication { Depends { name: "bundle" } files: "main.cpp" Group { name: "public headers" files: ["header.h"] fileTags: ["bundle.input.public_hpp", "hpp"] } } \endcode \note Since \l{Group::fileTags}{Group.fileTags} property replaces file tags attached by the \l{FileTagger} item, the \c{"hpp"} tag should also be present. \nodefaultvalue */ /*! \qmlproperty pathList bundle::privateHeaders A list of private header files to copy to a framework bundle's \c PrivateHeaders subdirectory It is recommended to attach the \c{"bundle.input.private_hpp"} file tag to headers instead: \code CppApplication { Depends { name: "bundle" } files: "main.cpp" Group { name: "private headers" files: ["header.h"] fileTags: ["bundle.input.private_hpp", "hpp"] } } \endcode \note Since \l{Group::fileTags}{Group.fileTags} property replaces file tags attached by the \l{FileTagger} item, the \c{"hpp"} tag should also be present. \nodefaultvalue */ /*! \qmlproperty pathList bundle::resources A list of resources to copy to a bundle's \c Resources subdirectory. Files will automatically be copied into \c lproj subdirectories corresponding to the input files' paths. It is recommended to attach the \c{"bundle.input.resources"} file tag to resources instead: \code CppApplication { Depends { name: "bundle" } files: "main.cpp" Group { name: "resources" files: ["file.txt"] fileTags: ["bundle.input.resources"] } } \endcode \nodefaultvalue */ /*! \qmlproperty var bundle::infoPlist A dictionary of key-value pairs to add to the bundle's \c Info.plist. The contents of this property will be aggregated with the values from any \c plist files. If this property and any \c plist files contain the same key, this property will take precedence. However, it might be overridden during postprocessing (see \l{bundle::}{processInfoPlist}). If \c undefined, will not be taken into account. \nodefaultvalue */ /*! \qmlproperty bool bundle::processInfoPlist Whether to perform post-processing on the aggregated \c Info.plist contents. If this property is \c{true}, various post-processing operations will be applied to the bundle's property list dictionary after it has been aggregated from the contents of any \c plist files on disk, and the \l{bundle::}{infoPlist} property. First, values from a list of defaults will be added to the dictionary if they were not already present. Second, values from the \c AdditionalInfo key of the platform SDK's \c Info.plist file will be added to the dictionary if they were not already present, as well as some other miscellaneous keys, such as \c BuildMachineOSBuild and \c UIDeviceFamily (on iOS). Finally, variable expansions will be performed such that substrings of the form \c $(VAR) or \c ${VAR} will be replaced with their corresponding environment variables. \defaultvalue \c{true} */ /*! \qmlproperty bool bundle::embedInfoPlist Whether to create a \c{__TEXT} section in the product's executable containing the processed \c Info.plist. Only applies to command line applications. \defaultvalue \c{true} if the product is a command line tool, otherwise \c{false}. */ /*! \qmlproperty string bundle::infoPlistFormat The file format to write the product's resulting \c Info.plist in. Possible values are: \list \li \c{"binary1"} \li \c{"json"} \li \c{"same-as-input"} \li \c{"xml1"} \endlist \defaultvalue \c{"binary1"} for iOS, \c{"same-as-input"} or \c{"xml1"} for macOS depending on whether a \c plist file is used, and \c{undefined} for all other operating systems. */ /*! \qmlproperty string bundle::infoPlistPath \readonly The path that the \c Info.plist file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::infoStringsPath \readonly \since Qbs 1.5 The path that the \c InfoPlist.strings file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::pkgInfoPath \readonly The path that the \c PkgInfo file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::versionPlistPath \readonly The path that the \c version.plist file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::executablePath \readonly The path that the main executable file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::contentsFolderPath \readonly The path of the bundle's \c Contents subdirectory. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::applicationsFolderPath \readonly The path of the directory where dependent applications will be copied. This property applies only if \l{isMainBundle} is \c true. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::documentationFolderPath \readonly \since Qbs 1.5 The path of the directory where documentation will be written. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::executableFolderPath \readonly The path of the directory where the main exectuable will be written. The path is relative to the directory that contains the bundle. Not to be confused with \l{bundle::}{executablesFolderPath}. */ /*! \qmlproperty string bundle::executablesFolderPath \readonly The path of the directory where auxiliary executables will be copied. The path is relative to the directory that contains the bundle. Not to be confused with \l{bundle::}{executableFolderPath}. */ /*! \qmlproperty string bundle::frameworksFolderPath \readonly The path of the directory where internal frameworks will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::javaFolderPath \readonly \since Qbs 1.5 The path of the directory where Java content will be written. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::localizedResourcesFolderPath \readonly \since Qbs 1.5 The path of the directory where localized resource files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::pluginsFolderPath \readonly The path of the directory where plugins will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::privateHeadersFolderPath \readonly The path of the directory where private header files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::publicHeadersFolderPath \readonly The path of the directory where public headers files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::scriptsFolderPath \readonly The path of the directory where script files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::sharedFrameworksFolderPath \readonly The path of the directory where shared frameworks will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::sharedSupportFolderPath \readonly The path of the directory where shared support files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::unlocalizedResourcesFolderPath \readonly The path of the directory where non-localized resource files will be copied. The path is relative to the directory that contains the bundle. This is the same as the base resources path. */ /*! \qmlproperty bool bundle::useBuiltinXcodeBuildSpecs Set this property to \c true to use Xcode \c .xcspec files shipped with \QBS. This property can be used as a workaround when using a new Xcode version that is not supported by \QBS yet. \default false */ /*! \qmlproperty string bundle::versionsFolderPath \readonly \since Qbs 1.5 The path of the bundle's \c Versions subdirectory. The path is relative to the directory that contains the bundle. This is only relevant for (non-shallow) framework bundles. */ qbs-src-3.3.1/doc/reference/modules/qt-dbus-module.qdoc0000644000175100017510000000522515232633614022374 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.dbus \inqmlmodule QbsModules \brief Provides Qt D-Bus support. The Qt.dbus module provides support for the Qt D-Bus module, which contains classes for inter-process communication over the D-Bus protocol. \section2 Relevant File Tags \target filetags-debus \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.dbus.adaptor"} \li - \li 1.5 \li Source files with this tag serve as inputs to the rule running the \c qdbusxml2cpp tool, which will create an adaptor class. \row \li \c{"qt.dbus.interface"} \li - \li 1.5 \li Source files with this tag serve as inputs to the rule running the \c qdbusxml2cpp tool, which will create an interface class. \endtable */ /*! \qmlproperty string Qt.dbus::xml2cppName The base name of the \c qdbusxml2cpp tool. Set this property if your system uses a name different from the default value. \defaultvalue \c{"qdbusxml2cpp"} */ /*! \qmlproperty stringList Qt.dbus::xml2CppHeaderFlags A list of additional flags when running the \c qdbusxml2cpp tool to create header files. \defaultvalue \c [] */ /*! \qmlproperty stringList Qt.dbus::xml2CppSourceFlags A list of additional flags when running the \c qdbusxml2cpp tool to create source files. \defaultvalue \c [] */ qbs-src-3.3.1/doc/reference/modules/codesign-module.qdoc0000644000175100017510000002347615232633614022620 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype codesign \inqmlmodule QbsModules \since Qbs 1.19 \brief Provides code signing support. The \c codesign module contains properties and rules for code signing on Apple and Android platforms. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"codesign.entitlements"} \li \c{*.entitlements} \li 1.19.0 \li \l{https://developer.apple.com/documentation/bundleresources/entitlements}{Xcode entitlements} \row \li \c{"codesign.provisioningprofile"} \li \c{*.mobileprovision, *.provisionprofile} \li 1.19.0 \li Xcode provisioning profiles \row \li \c{"codesign.signed_artifact"} \li n/a \li 1.19.0 \li This tag is attached to all signed artifacts such as applications or libraries \endtable */ /*! \qmlproperty string codesign::signingTimestamp URL of the timestamp authority RFC 3161 server to be contacted to authenticate code signing. \c undefined or \c empty indicates that a system-specific default should be used; \c{"none"} explicitly disables the use of timestamp services on Apple platforms. \since Qbs 1.19 \defaultvalue \c "none" on Apple, \c undefined otherwise */ /*! \qmlproperty stringList codesign::codesignFlags Additional flags passed to the \c{codesign} tool. \since Qbs 1.19 \nodefaultvalue */ /*! \qmlproperty string codesign::codesignName The name of the \c{codesign} binary. \since Qbs 1.19 \defaultvalue Determined automatically */ /*! \qmlproperty string codesign::codesignPath Path to the \c{codesign} tool. \since Qbs 1.19 \defaultvalue Determined automatically */ /*! \qmlproperty bool codesign::enableCodeSigning Whether to actually perform code signing. \since Qbs 1.19 \defaultvalue \c false */ /*! \qmlproperty string codesign::provisioningProfile Name or UUID of the provisioning profile to embed in the product. Typically this should be left blank to allow \QBS to use automatic provisioning. \since Qbs 1.19 \defaultvalue \c undefined \appleproperty */ /*! \qmlproperty path codesign::provisioningProfilesPath Path to directory containing provisioning profiles installed on the system. This should not normally need to be changed. \since Qbs 1.19 \defaultvalue \c{"~/Library/MobileDevice/Provisioning Profiles"} \appleproperty */ /*! \qmlproperty string codesign::signingIdentity Search string used to find the certificate to sign the product. This does not have to be a full certificate name like "Mac Developer: John Doe (XXXXXXXXXX)", and can instead be a partial string like "Mac Developer" or the certificate's SHA1 fingerprint. The search string should generally be one of the following: \list \li 3rd Party Mac Developer Application \li 3rd Party Mac Developer Installer \li Developer ID Application \li Developer ID Installer \li iPhone Developer \li iPhone Distribution \li Mac Developer \endlist It is also possible to use the special \c "-" value to use the ad-hoc signing. See \l{https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html#//apple_ref/doc/uid/TP40012582-CH31-SW41}{Maintaining Your Signing Identities and Certificates} for complete documentation on the existing certificate types. In general you should use \l{codesign::signingType}{signingType} instead. \since Qbs 1.19 \defaultvalue Determined by \l{codesign::signingType}{signingType} \appleproperty */ /*! \qmlproperty string codesign::signingType Type of code signing to use. This should generally be used in preference to an explicit signing identity like "Mac Developer: John Doe (XXXXXXXXXX)" since it is not user specific and can be set in a project file. Possible values include: \c{"app-store"}, \c{"apple-id"}, \c{"ad-hoc"}, which sign for the App Store or Mac App Store, Developer ID, and Ad-hoc code signing, respectively. \section1 Relation between the signingType and signingIdentity The following table shows how the signingIdentity's default value is calculated. \table \header \li \c qbs.targetOS \li \c codesign.signingType \li \c qbs.buildVariant \li \c codesign.signingIdentity \row \li {1, 4} \c "macos" \li \c "ad-hoc" \li any \li \c "-" \row \li {1, 2} \c "app-store" \li \c "debug", \c "profiling" \li \c "Mac Developer" \row \li \c "release" \li \c "3rd Party Mac Developer Application" \row \li \c "apple-id" \li any \li \c "Developer ID Application" \row \li {1, 2} \c "ios", \c "tvos", \c "watchos" \li {1, 2} \c "app-store" \li \c "debug", \c "profiling" \li \c "iPhone Developer" \row \li \c "release" \li \c "iPhone Distribution" \endtable \since Qbs 1.19 \defaultvalue Determined automatically \appleproperty */ /*! \qmlproperty string codesign::teamIdentifier Human readable name or 10-digit identifier of the Apple development team that the signing identity belongs to. This is used to disambiguate between multiple certificates of the same type in different teams. Typically this can be left blank if the development machine is only signed in to a single development team, and should be set in a profile otherwise. \since Qbs 1.19 \defaultvalue \c undefined \appleproperty */ /*! \qmlproperty bool codesign::useApksigner If \c true, the package is signed using apksignerFilePath binary. Set this property to \c false to use the jarsignerFilePath one. Set by the Android.sdk module. \since Qbs 1.19 \defaultvalue \c true \androidproperty */ /*! \qmlproperty string codesign::keystorePath The absolute path to the keystore file. \since Qbs 1.19 \defaultvalue \c "${HOME}/.android/debug.keystore" \androidproperty */ /*! \qmlproperty string codesign::keystorePassword The keystore password. \since Qbs 1.19 \defaultvalue \c "android" \androidproperty */ /*! \qmlproperty string codesign::keyPassword The key password. \since Qbs 1.19 \defaultvalue \c "android" \androidproperty */ /*! \qmlproperty string codesign::keyAlias The key alias. \since Qbs 1.19 \defaultvalue \c "androiddebugkey" \androidproperty */ /*! \qmlproperty string codesign::subjectName Specifies the name of the subject of the signing certificate. This value can be a substring of the entire subject name. \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::rootSubjectName Specifies the name of the subject of the root certificate that the signing certificate must chain to. This value may be a substring of the entire subject name of the root certificate. \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::hashAlgorithm Specifies the default hash algorithm used on the signing certificate. The possible values are \c sha1, \c sha256, \c sha384, and \c sha512. \note Only available in Windows 10 kit builds 20236 and later. \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::timestampAlgorithm Specifies the default timestamp algorithm used together with the \c signingTimestamp property. The possible values are \c sha1, \c sha256. \note If this value is not set, then the default sha1 algorithm will be used. \since Qbs 1.19.2 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::certificatePath Specifies the full path to the signing certificate file (*.pfx). \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::certificatePassword Specifies the password to use when opening a signing certificate file (*.pfx). \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ /*! \qmlproperty string codesign::crossCertificatePath Specifies the full path to the additional certificate file (*.cer). \since Qbs 1.19 \defaultvalue \c undefined \windowsproperty */ qbs-src-3.3.1/doc/reference/modules/cpufeatures-module.qdoc0000644000175100017510000001214415232633614023341 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype cpufeatures \inqmlmodule QbsModules \since Qbs 1.10 \brief Provides support for fine-tuning CPU features. The \c cpufeatures module offers properties for enabling or disabling specific CPU features. Use it if you want to override the compiler defaults for a given platform. The compiler rules in the \l{cpp} module evaluate this module's properties and generate matching compiler flags. All properties in this module are of type \c bool and have the following semantics: \list \li The default value \c undefined has no effect on the compiler command line. \li If the value is \c true and the compiler has a flag to enable the feature, that flag is added to the command line if it is applicable to the current architecture. For example, enabling the property \c x86_sse2 would result in the GCC option \c{-msse2}. \li If the value is \c false and the compiler has a flag to disable the feature, that flag is added to the command line if it is applicable to the current architecture. For example, disabling the property \c x86_sse2 would result in the GCC option \c{-no-msse2}. \endlist */ /*! \qmlproperty bool cpufeatures::arm_neon Whether to use NEON instructions in ARM binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::arm_vfpv4 Whether to use VFPv4 instructions in ARM binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::mips_dsp Whether to use DSP instructions in MIPS binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::mips_dspr2 Whether to use DSPr2 instructions in MIPS binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx Whether to use AVX instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx2 Whether to use AVX2 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512bw Whether to use AVX-512-BW instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512cd Whether to use AVX-512-CD instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512dq Whether to use AVX-512-DQ instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512er Whether to use AVX-512-ER instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512f Whether to use AVX-512 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512ifma Whether to use AVX-512-IFMA instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512pf Whether to use AVX-512-PF instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512vbmi Whether to use AVX-512-VBMI instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512vl Whether to use AVX-512-VL instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_f16c Whether to use F16C instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse2 Whether to use SSE2 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse3 Whether to use SSE3 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_ssse3 Whether to use SSSE3 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse4_1 Whether to use SSE4.1 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse4_2 Whether to use SSE4.2 instructions in x86 binaries. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/modules/install-paths-module.qdoc0000644000175100017510000000770315232633614023603 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Janet Black. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype installpaths \inqmlmodule QbsModules \since Qbs 3.1 \brief Provides properties for install directories. The \c installpaths module contains properties indicating directories where files should be installed to in a manner allowing distributors to make necessary adjustments. Example usage: \code qbs modules.installPaths.libexec:lib64/libexec \endcode \note On Debian-like Linux distributions, this module also provides some convenience auto-detection mechanism using the \c dpkg-architecture tool: If installPaths::autotedect is true, \QBS will query the library paths from the system. */ /*! \qmlproperty string installpaths::autotedect Whether to try autodetecting paths using system tools. This property has an effect only on Debian-like Linux systems. \defaultvalue \c false */ /*! \qmlproperty string installpaths::applications The location where to install applictaton bundles on Apple platforms. \defaultvalue \c "Applications" */ /*! \qmlproperty string installpaths::bin The location where to install binaries. \defaultvalue \c "bin" */ /*! \qmlproperty string installpaths::etc The location where to install configs. \defaultvalue \c "etc" */ /*! \qmlproperty string installpaths::frameworks The location where to install Frameworks on Apple platforms. \defaultvalue \c "Library/Frameworks" */ /*! \qmlproperty string installpaths::include The location where to install include files. \defaultvalue \c "include" */ /*! \qmlproperty string installpaths::lib The location where to install libraries. \defaultvalue \c "lib" */ /*! \qmlproperty string installpaths::libexec The location where to install additional executables. \defaultvalue \c{"libexec/"} + \l{subdir} */ /*! \qmlproperty string installpaths::library The location where to install support files on Apple platforms. \defaultvalue \c "Library" */ /*! \qmlproperty string installpaths::loadableModules The location where to install loadable modules (bundle plugins) on Apple platforms. \defaultvalue \c "Library//PlugIns" */ /*! \qmlproperty string installpaths::subdir The additional directory appended to the libexec, share and plugins paths. \defaultvalue lower-case \l{Project::name}{Project.name} */ /*! \qmlproperty string installpaths::plugins The location where to install plugins. On Apple platforms, non-bundle loadable modules are also installed here. \defaultvalue \l{lib} + \c{"/"} + \l{subdir} + \c{"/plugins"} */ /*! \qmlproperty string installpaths::share The location where to install resources. \defaultvalue \c{"share/"} + \l{subdir} */ qbs-src-3.3.1/doc/reference/modules/typescript-module.qdoc0000644000175100017510000001172215232633614023222 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype typescript \inqmlmodule QbsModules \since Qbs 1.3 \brief Provides TypeScript support. The \c typescript module contains properties and rules for building \l{TypeScript} applications and may be used in combination with the \l{nodejs} module to run the applications directly from \QBS. */ /*! \qmlproperty string typescript::warningLevel The severity of warnings to emit. The higher the level, the more warnings will be shown. \c{pedantic} causes the TypeScript to emit warnings on expressions and declarations with an implied \e any type. \defaultvalue \c{"normal"} */ /*! \qmlproperty string typescript::targetVersion The ECMAScript target version for generated JavaScript code. If left undefined, the TypeScript \l{Compiler Options}{compiler default} is used. \nodefaultvalue */ /*! \qmlproperty string typescript::moduleLoader If TypeScript modules are being used, the JavaScript module loading mechanism to use in the generated JavaScript code. If left undefined, modules are not used. See \l{Compiler Options} for a list of possible values. \nodefaultvalue */ /*! \qmlproperty bool typescript::stripComments Whether to remove comments from the generated JavaScript files. \defaultvalue \l{qbs::debugInformation}{!qbs.debugInformation} */ /*! \qmlproperty bool typescript::generateDeclarations Whether to generate the corresponding \c .d.ts files during compilation. These are TypeScript's equivalent of header files. \defaultvalue \c{false} */ /*! \qmlproperty bool typescript::generateSourceMaps Whether to generate the corresponding \c .map files during compilation. \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty stringList typescript::compilerFlags A list of additional flags for the TypeScript compiler. \nodefaultvalue */ /*! \qmlproperty bool typescript::singleFile Whether to compile all TypeScript source files to a single JavaScript output file. The default is to compile each TypeScript file to a corresponding JavaScript file. This property is incompatible with \l{typescript}{moduleLoader}. \defaultvalue \c{false} */ /*! \qmlproperty string typescript::version The TypeScript version. Consists of four numbers separated by dots. For example, "1.0.0.0". \nodefaultvalue */ /*! \qmlproperty int typescript::versionMajor The TypeScript major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int typescript::versionMinor The TypeScript minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list typescript::versionParts The TypeScript version as a list. For example, TypeScript version 1.0 would correspond to a value of \c[1, 0, 0, 0]. \defaultvalue \c [] */ /*! \qmlproperty int typescript::versionPatch The TypeScript patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int typescript::versionBuild The fourth TypeScript version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path typescript::toolchainInstallPath The TypeScript installation directory. This property should not normally need to be changed if \c{tsc} is available by searching the PATH environment variable. \nodefaultvalue */ /*! \qmlproperty string typescript::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"tsc"} */ /*! \qmlproperty string typescript::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \c{compilerName} */ qbs-src-3.3.1/doc/reference/modules/vcs-module.qdoc0000644000175100017510000001456415232633614021616 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype vcs \inqmlmodule QbsModules \since Qbs 1.10 \brief Provides support for version control systems (Git, SVN, Mercurial). The \c vcs module provides information about the current state of the project's repository. This is useful for embedding version information directly into your binaries, such as the latest tag, number of commits since the tag, and current commit hash. By default, a C header file is generated, which defines macros representing the repository state. This allows C/C++ code to access this information at run time. Supported version control systems: \list \li Git \li Subversion (SVN) \li Mercurial (hg) \endlist For example: \code #include #include int main() { std::cout << "I was built from " << VCS_REPO_STATE << std::endl; std::cout << "Latest tag: " << VCS_REPO_LATEST_TAG << std::endl; std::cout << "Commits since tag: " << VCS_REPO_COMMITS_SINCE_TAG << std::endl; std::cout << "Commit SHA: " << VCS_REPO_COMMIT_SHA << std::endl; } \endcode Above, a header file called \c{vcs-repo-state.h} is created, defining a macro called \c VCS_REPO_STATE, which expands to a character constant describing the current state of the repository. For Git, this would be the current HEAD's commit hash. Example: \code VCS_REPO_STATE = "v1.2.3-5-gabcdef0" VCS_REPO_LATEST_TAG = "v1.2.3" VCS_REPO_COMMITS_SINCE_TAG = "5" VCS_REPO_COMMIT_SHA = "gabcdef0" \endcode For Git repositories without any tags, the commit hash will be used instead. For Mercurial repositories, the full repository state is always shown. For SVN, only \l{vcs::}{repoState} is currently available. */ /*! \qmlproperty string vcs::headerFileName The name of the C header file to be generated. This header file defines the following macros: \list \li \c VCS_REPO_STATE — Full repository state string \li \c VCS_REPO_LATEST_TAG — Latest tag reachable from HEAD (or "none") \li \c VCS_REPO_COMMITS_SINCE_TAG — Number of commits since latest tag (or "none") \li \c VCS_REPO_COMMIT_SHA — Current commit SHA (or "none") \endlist Set this to \c undefined to disable header file generation. \defaultvalue \c{"vcs-repo-state.h"} */ /*! \qmlproperty string vcs::repoDir The root directory of the repository. \defaultvalue The top-level project directory (\l{Project::sourceDirectory} {project.sourceDirectory}). */ /*! \qmlproperty string vcs::repoState The full repository state string. For Git, this corresponds to the output of: \c {git describe --tags --always --long HEAD} Example values: \list \li \c abc1234 (no tags) \li \c abc1234-0-gabc1234 (at tag) \li \c v1.0.0-3-gabc1234 (3 commits after tag) \endlist For Mercurial, this corresponds to the output of: \c {hg log -r . --template "{latesttag}-{latesttagdistance}-m{node|short}"} Example values: \list \li \c null-0-m000000000000 (empty repo) \li \c null-1-mabc1234 (no tags) \li \c null-3-mabc1234 (4 commits, no tags) \li \c v1.0.0-1-mabc1234 (at tag) \li \c v1.0.0-3-mabc1234 (4 commits after tag) \endlist For SVN, this is the current revision number. \nodefaultvalue */ /*! \qmlproperty string vcs::repoLatestTag The latest reachable tag in the repository. For Git, this is the \c TAG component from \c git describe output. If no tags are present, this will be set to \c "none". For Mercurial, this is the \c {latesttag} component from the template. For SVN, this property is currently not set and will be \c "none". \nodefaultvalue \since Qbs 3.1.0 */ /*! \qmlproperty string vcs::repoCommitsSinceTag The number of commits since the latest tag. For Git, this is the \c N component from \c git describe output. If no tags are present, this will be set to \c "none". For Mercurial, this is the \c {latesttagdistance} component from the template. For SVN, this property is currently not set and will be \c "none". \nodefaultvalue \since Qbs 3.1.0 */ /*! \qmlproperty string vcs::repoCommitSha The abbreviated commit hash of HEAD. For Git, this is the \c gSHA component from \c git describe output. If no tags are present, this will be set to the commit hash prefixed with \c g. For Mercurial, this is the \c m{node|short} component from the template. For SVN, this property is currently not set and will be \c "none". \nodefaultvalue \since Qbs 3.1.0 */ /*! \qmlproperty string vcs::toolFilePath Set this property if the tool has an unusual name in your local installation, or if it is located in a directory that is not in the build environment's \c PATH. \defaultvalue The file name of the version control tool corresponding to \l{vcs::type}{type}. */ /*! \qmlproperty string vcs::type The version control system used in the project. Currently, the supported values are \c{"git"}, \c{"hg"} and \c{"svn"}. \defaultvalue auto-detected */ qbs-src-3.3.1/doc/reference/modules/exporter-cmake.qdoc0000644000175100017510000001113515232633614022455 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Raphael Cotty (raphael.cotty@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Exporter.cmake \inqmlmodule QbsModules \since Qbs 2.3 \brief Provides support for generating \CMAKE packages from dynamic, static and header library products. The Exporter.cmake module contains the properties and rules to create a \CMAKE config \l{https://cmake.org/cmake/help/v3.29/manual/cmake-packages.7.html#config-file-packages}{files} from the \l Export item of a \l Product. For instance, suppose you are creating a library. To allow exporting to \CMAKE, you would write something like the following: \code DynamicLibrary { name: "mylibrary" qbs.installPrefix: "/opt/mylibrary" Depends { name: "Exporter.cmake" } Exporter.cmake.packageName: "MyLibrary" property string headersInstallDir: "include" // ... Group { name: "API headers" files: ["mylib.h"] qbs.install: true qbs.installDir: headersInstallDir } Group { fileTagsFilter: ["Exporter.cmake.package"] qbs.installDir: "lib/cmake/MyLibrary" } Export { Depends { name: "cpp" } cpp.includePaths: FileInfo.joinPaths( exportingProduct.qbs.installRoot, exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) } } \endcode To build against this library, from within your \CMAKE project, you simply use \l{https://cmake.org/cmake/help/v3.29/command/find_package.html}{find_package}: \code find_package(MyLibrary PATHS REQUIRED) add_executable(Consumer main.cpp) target_link_libraries(Consumer MyLibrary) \endcode \section2 Relevant File Tags \target filetags-exporter-qbs \table \header \li Tag \li Since \li Description \row \li \c{"Exporter.cmake.package"} \li 2.3.0 \li This tag is attached to all generated module files. \row \li \c{"Exporter.cmake.configFile"} \li 2.3.0 \li This tag is attached to the generated config file. \row \li \c{"Exporter.cmake.versionFile"} \li 2.3.0 \li This tag is attached to the generated version file. \endtable */ /*! \qmlproperty string Exporter.cmake::configFileName The name of the generated config file. \defaultvalue \c{packageName + "Config.cmake"} */ /*! \qmlproperty string Exporter.cmake::versionFileName The name of the generated version file. \defaultvalue \c{packageName + "ConfigVersion.cmake"} */ /*! \qmlproperty string Exporter.cmake::packageName The name of the \CMAKE package. \defaultvalue \l{Product::targetName}{Product.targetName} */ qbs-src-3.3.1/doc/reference/modules/lexyacc-module.qdoc0000644000175100017510000001047315232633614022446 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype lex_yacc \inqmlmodule QbsModules \since Qbs 1.6 \brief Provides support for the \c lex and \c yacc tools. The \c lex_yacc module allows you to create scanners and parsers via the POSIX tools \c lex and \c yacc, respectively. These tools are closely related and share a number of properties, which is why they are represented by a single module. \section2 Relevant File Tags \target filetags-lexyacc \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"lex.input"} \li \c{*.l} \li 1.6 \li Source files with this tag serve as inputs to the \c lex tool. \row \li \c{"yacc.input"} \li \c{*.y} \li 1.6 \li Source files with this tag serve as inputs to the \c yacc tool. \endtable */ /*! \qmlproperty bool lex_yacc::enableCompilerWarnings \since Qbs 1.8 Whether compiler warnings are displayed. Because \c lex and \c yacc are known to produce files that will trigger compiler warnings, such warnings are suppressed by default. Set this property to \c true if you want to see them. \defaultvalue \c{false} */ /*! \qmlproperty string lex_yacc::lexBinary The file path of the \c lex tool. \defaultvalue \c{"lex"} */ /*! \qmlproperty stringList lex_yacc::lexFlags Additional command-line options for the \c lex tool. \defaultvalue \c [] */ /*! \qmlproperty string lex_yacc::lexOutputFilePath The output file for the \c lex tool. This corresponds to \c{%option outfile} in the .l file. If \c{%option outfile} is set in the .l file then this property is ignored. \defaultvalue \c undefined \since 1.12 */ /*! \qmlproperty string lex_yacc::outputTag The file tag for the generated scanner and parser sources. Use \l{filetags-cpp}{"cpp"} if you want to use a C++ compiler on them. \defaultvalue \l{filetags-cpp}{"c"} */ /*! \qmlproperty bool lex_yacc::uniqueSymbolPrefix If this property is \c true, the prefix \c yy normally used for the generated lexer and parser functions is replaced by the base name of the file provided as input to \c lex and \c yacc, respectively. Enable this property if you want to use more than one lexer or parser in a single product. \note Enabling this property requires that the associated lexer and scanner source files have the same base name. It also assumes a variant of \c lex that supports the non-POSIX option \c{-P}, such as \c flex. \defaultvalue \c{false} */ /*! \qmlproperty string lex_yacc::yaccBinary The file path of the \c yacc tool. \defaultvalue \c{"yacc"} */ /*! \qmlproperty stringList lex_yacc::yaccFlags Additional command-line options for the \c yacc tool. \defaultvalue \c [] */ /*! \qmlproperty string lex_yacc::yaccOutputFilePath Main output file for the \c yacc tool. This corresponds to \c{%output} in the .y file. If \c{%output} is set in the .y file then this property is ignored. \defaultvalue \c undefined \since 1.12 */ qbs-src-3.3.1/doc/reference/modules/exporter-qbs-module.qdoc0000644000175100017510000001100015232633614023434 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Exporter.qbs \inqmlmodule QbsModules \since Qbs 1.12 \brief Provides support for generating \QBS modules from products. The Exporter.qbs module contains the properties and rules to create a \QBS module from the \l Export item of a \l Product. Such a module acts as your product's interface to other projects written in \QBS. For instance, suppose you are creating a library. To allow other products both within and outside of your project to make use of it, you would write something like the following: \code DynamicLibrary { name: "mylibrary" qbs.installPrefix: "/opt/mylibrary" Depends { name: "Exporter.qbs" } property string headersInstallDir: "include" // ... Group { name: "API headers" files: ["mylib.h"] qbs.install: true qbs.installDir: headersInstallDir } Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.installDir: "qbs/modules/mylibrary" } Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] prefixMapping: [{ prefix: exportingProduct.sourceDirectory, replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) }] } } \endcode To build against this library, from within your project or any other one, you simply declare a \l{Depends}{dependency}: \code Depends { name: "mylibrary" } \endcode \section2 Relevant File Tags \target filetags-exporter-qbs \table \header \li Tag \li Since \li Description \row \li \c{"Exporter.qbs.module"} \li 1.12.0 \li This tag is attached to the generated module file. \endtable */ /*! \qmlproperty stringList Exporter.qbs::artifactTypes Artifacts that match these tags will become \l{Group::filesAreTargets}{target artifacts} of the generated module, so they can get picked up by the rules of depending products. If you do not specify anything here, all installed artifacts of the product are considered. \note You can only limit the default set of artifacts by setting this property, but you cannot extend it, because only artifacts that are to be installed are considered. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.qbs::additionalContent The value of this property will be copied verbatim into the generated module. \defaultvalue \c undefined */ /*! \qmlproperty stringList Exporter.qbs::excludedDependencies Normally, all \l Depends items in the \l Export item are copied into the generated module. However, if there are any exported dependencies that only make sense for products in the same project, then you can enter their names into this array, and they will get filtered out. \note You should strive to structure your projects in such a way that you do not need to set this property. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.qbs::fileName The name of the generated module file. \defaultvalue \c {product.targetName + ".qbs"} */ qbs-src-3.3.1/doc/reference/modules/cpp-module.qdoc0000644000175100017510000015712515232633614021606 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype cpp \inqmlmodule QbsModules \since Qbs 1.0 \brief Provides C/C++ support. The \c cpp module contains the properties and rules for toolchains of the C/C++ family. On Apple platforms, this includes support for Objective-C/C++. \section2 Setting Up the Run Environment When running an application that has dependencies on dynamic libraries, the script specified by \l{Module::setupRunEnvironment}{Module.setupRunEnvironment} automatically adds the locations of the libraries to the environment. That is, to \c PATH on Windows, \c DYLD_LIBRARY_PATH on macOS, and \c LD_LIBRARY_PATH on Linux and other Unix platforms. If the value \c{"ignore-lib-dependencies"} shows up in the \c config array, this behavior is disabled. Users can set the value via the \l run command. \target dependency-parameters-cpp \section2 Dependency Parameters \table \header \li Parameter \li Type \li Since \li Default \li Description \row \li \c{link} \li \c{bool} \li 1.9 \li undefined \li If \c{false}, the dependency will not be linked, even if it is a valid input for a linker rule. This property affects library dependencies only. \row \li \c{linkWholeArchive} \li \c{bool} \li 1.9 \li undefined \li If \c{true}, then if the dependency is a static library, all of its objects will be pulled into target binary, even if their symbols do not appear to be used. This parameter is mainly useful when creating a dynamic library from static libraries. \row \li \c{symbolLinkMode} \li \c{string} \li 1.9 \li undefined \li Attribute specifying how the library or framework will be linked. May contain the values: "weak", "lazy", "reexport", and "upward"; refer to the Apple ld64 man page for full details. \c{undefined} uses normal linking. Currently only applies when linking for Apple platforms. Note that \c "lazy" mode is deprecated and doesn't work with Xcode 15 and above. \endtable \section2 Relevant File Tags \target filetags-cpp \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"application"} \li n/a \li 1.0.1 \li The rule that creates executable files (typically via a linker) attaches this tag to its output artifact. \row \li \c{"asm"} \li \c{*.s} (for GCC-like toolchains), \c{*.asm} (for MSVC) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's assembler. One object file is generated for each such file. \row \li \c{"asm_cpp"} \li \c{*.S}, \c{*.sx} \li 1.1.0 \li Like \c{"asm"}, but for source files that need preprocessing. This tag only has an effect with GCC-like toolchains. \row \li \c{"c"} \li \c{*.c} (if \c combineCSources is not enabled) \li 1.0.1 \li Source files with this tag serve as inputs to a rule invoking the toolchain's C compiler. One object file is generated for each such file. \row \li \c{"c.combine"} \li \c{*.c} (if \c combineCSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single C file, which will then be compiled. \row \li \c{"cpp"} \li \c{*.C}, \c{*.cpp}, \c{*.cxx}, \c{*.c++}, \c{*.cc} (if \c combineCxxSources is not enabled) \li 1.0.1 \li Source files with this tag serve as inputs to a rule invoking the toolchain's C++ compiler. One object file is generated for each such file. \row \li \c{"cpp.combine"} \li \c{*.C}, \c{*.cpp}, \c{*.cxx}, \c{*.c++}, \c{*.cc} (if \c combineCxxSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single C++ file, which will then be compiled. \row \li \c{"c_pch_src"}, \c{"cpp_pch_src"}, \c{"objc_pch_src"}, \c{"objcpp_pch_src"} \li - \li 1.5 \li Files with this tag will be turned into precompiled headers for C, C++, Objective-C and Objective-C++, respectively. There can be only one such file per product and language. \row \li \c{"def"} \li - \li 1.17.0 \li This tag is used for a module-definition file (.def) to be passed to the linker. Such a file provides the linker with information about exports, attributes, and other information about the program to be linked. This file tag only has an effect with the MSVC toolchain. \row \li \c{"dynamiclibrary"} \li n/a \li 1.0.1 \li The rule that creates dynamic libraries (typically via a linker) attaches this tag to its output artifact. \row \li \c{"dynamiclibrary_import"} \li n/a \li 1.0.0 \li This tag is used for import libraries of dynamic libraries. For example, the MSVC linker rule creates a \c{dynamiclibrary_import} artifact \c{foo.lib} in addition to a \c{dynamiclibrary} artifact \c{foo.dll}. \row \li \c{"hpp"} \li \c{*.h}, \c{*.H}, \c{*.hpp}, \c{*.hxx}, \c{*.h++} \li 1.0.1 \li This tag is used for header files (C, C++, Objective-C and Objective-C++). No rule in this module generates output artifacts from such files directly, but the compiler rule will have a dependency on all rules that create such files. \row \li \c{"linkerscript"} \li - \li 1.5.0 \li This tag is used for \c ld linker scripts. You can provide such a file if you need to replace the default linker script. This file tag only has an effect with GCC-like toolchains. The linker needs to be \c{ld}-compatible. \row \li \c{"native.pe.manifest"} \li *.manifest \li 1.8.0 \li This tag is automatically assigned to Microsoft manifest files. Manifests are embedded into the resulting binary. \row \li \c{"obj"} \li n/a \li 1.0.1 \li The rule that creates object files (typically via a compiler) attaches this tag to its output artifacts. Such files are usually intermediate artifacts of the build process and rarely need to be referenced in project files. \row \li \c{"objc"} \li \c{*.m} (if \c combineObjcSources is not enabled) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's Objective-C compiler. One object file is generated for each such file. \row \li \c{"objc.combine"} \li \c{*.m} (if \c combineObjcSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single Objective-C file, which will then be compiled. \row \li \c{"objcpp"} \li \c{*.mm} (if \c combineObjcxxSources is not enabled) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's Objective-C++ compiler. One object file is generated for each such file. \row \li \c{"objcpp.combine"} \li \c{*.mm} (if \c combineObjcxxSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single Objective-C++ file, which will then be compiled. \row \li \c{"rc"} \li \c{*.rc} \li 1.1.0 \li Files with this tag serve as inputs to the Windows resource compiler. One object file is generated for each such file. The tag has no effect on target platforms other than Windows. \row \li \c{"staticlibrary"} \li n/a \li 1.0.1 \li The rule that creates static libraries (typically via a linker) attaches this tag to its output artifact. \row \li \c{"objectlibrary"} \li n/a \li 3.2.0 \li The \l ObjectLibrary item attaches this tag to its \c "obj" artifacts. \row \li \c{"versionscript"} \li - \li 1.5.0 \li This tag is used for \c ld linker scripts. You can provide such a file if you need fine-grained control over the symbols present in a shared library. This file tag only has an effect with GCC-like toolchains. The linker needs to be \c{ld}-compatible. \row \li \c{"time_trace"} \li n/a \li 3.3.0 \li This tag is attached to \c{.time_trace.json} files produced by the compiler. \endtable \section2 Relevant Job Pools \target cpp-job-pools \table \header \li Pool \li Since \li Description \row \li \c{"assembler"} \li 1.13 \li The job pool used by rules that run the toolchain's assembler. This is only relevant for direct invocations of the assembler binary, not for running it indirectly via the compiler. \row \li \c{"compiler"} \li 1.13 \li The job pool used by rules that run a compiler. All language variants use the same pool. \row \li \c{"linker"} \li 1.13 \li The job pool used by rules that run a linker. \endtable */ /*! \qmlproperty bool cpp::allowUnresolvedSymbols \since Qbs 1.2 Set to \c true if you want the linking step to succeed even if the resulting binary contains unresolved symbols. Normally, this makes little sense, but in special cases it is possible that the respective symbols will be available at load time even if they are not present during linking. \nodefaultvalue */ /*! \qmlproperty string cpp::architecture The target architecture. \defaultvalue \l{qbs::architecture}{qbs.architecture} */ /*! \qmlproperty string cpp::endianness \since Qbs 1.9 Specifies the endianness of the target platform's processor architecture (\c{"big"} or \c{"little"}). The value is automatically detected from the compiler's default values, but can also be manually set in order to select a specific endianness when targeting bi-endian architectures like MIPS and PowerPC. \defaultvalue Compiler default value. */ /*! \qmlproperty bool cpp::debugInformation Whether to generate debug information. \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty bool cpp::combineCSources \since Qbs 1.8 Enabling this property on a \l{Product}{product} instructs the \l{FileTagger}{file tagger} to attach the tag \c{"c.combine"} to C sources, rather than \c{"c"}. As a result, all C sources of the product will be combined into a single file, which is then compiled. This can speed up initial compilation significantly, but is of course detrimental in the context of incremental builds. Also, perfectly legal code may fail to compile with this option due to the merging of translation units. To enable this property in a product that has sources that cannot be merged, put the sources into a dedicated \l{Group} and set their \l{Group::} {fileTags} property to \c{"c"}, overriding the file tagger. \note Module properties set on specific source files (that is, at the Group level) will not be taken into account when building the combined file. You either need to set these properties at the product level or prevent the respective files from getting combined via the mechanism described above. \defaultvalue \c false */ /*! \qmlproperty bool cpp::combineCxxSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for C++. The \l{filetags-cpp} {relevant file tags} are \c{"cpp"} and \c{"cpp.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::combineObjcSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for Objective-C. The \l{filetags-cpp} {relevant file tags} are \c{"objc"} and \c{"objc.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::combineObjcxxSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for Objective-C++. The \l{filetags-cpp} {relevant file tags} are \c{"objcpp"} and \c{"objcpp.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::createSymlinks \unixproperty Whether to create version alias symlinks when building a dynamic library. \defaultvalue \c true */ /*! \qmlproperty bool cpp::discardUnusedData \since Qbs 1.10 If this property is \c true, the linker will discard data from objects that it determines to be unused. With MSVC and on Apple platforms, the granularity is per symbol, elsewhere it is per section. \nodefaultvalue */ /*! \qmlproperty bool cpp::separateDebugInformation \since Qbs 1.4 Whether to store debug information in an external file or bundle instead of within the binary. The type of files that will be generated when this property is \c{true} is dependent on the compiler and target platform: \list \li With MSVC, this property controls the generation of \c{.pdb} (Program Debug Database) files. \li On Apple platforms with GCC or Clang, this property controls the generation of \c{.dSYM} (DWARF Symbol) bundles or, if \l{cpp::}{dsymutilFlags} contains the \c{-f} or \c{--flat} flags, \c{.dwarf} symbol files. \li On other platforms with GCC or Clang (including Windows/MinGW), this property controls the generation of \c{.debug} symbol files. \endlist \defaultvalue \c{true} for MSVC and with GCC or Clang on Apple platforms, otherwise \c{false}. \sa debugInformation, {How do I separate and install debugging symbols?} */ /*! \qmlproperty stringList cpp::defines A list of preprocessor macros that gets passed to the compiler. To set macro values, use the following syntax: \code cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty stringList cpp::platformDefines A list of preprocessor macros that are used for all projects that are built for the current target platform. User project files usually do not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty pathList cpp::systemIncludePaths A list of include paths that are passed as system include paths to the compiler. For header files in those paths, warnings will be ignored. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty stringList cpp::systemRunPaths \since Qbs 1.6 The paths the dynamic linker uses on process start-up to locate dynamic libraries. \defaultvalue Auto-detected for host builds on Linux via \c ldconfig, \c{["/lib", "/usr/lib"]} otherwise on Unix, \c [] on Windows. */ /*! \qmlproperty pathList cpp::libraryPaths A list of library search paths. The paths will be passed to the linker in the appropriate way. For example, the \c {-L} argument will be used when using \c {ld}-like linkers. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue \sa libraries, dynamicLibraries, staticLibraries, {How do I create a module for a third-party library?} */ /*! \qmlproperty stringList cpp::libraries A List of libraries to be linked. If the library is part of your project, consider using a \l{Depends} item instead. Each library can be specified in one of two ways: \list \li An absolute file path (for example, \c "/foo/bar.lib"), in which case it is passed directly to the linker, ignoring \l libraryPaths. \li A library basename (for example, \c "bar"), in which case the directory that contains the library must be provided via \l libraryPaths. \endlist Relative paths (\c "foo/bar.lib") are not allowed. When giving an absolute path, the more specific properties \l staticLibraries or \l dynamicLibraries should be preferred, depending on the type of the library. \nodefaultvalue \sa libraryPaths, {How do I create a module for a third-party library?} */ /*! \qmlproperty stringList cpp::dynamicLibraries Like \l libraries, but expressing the intention to link dynamic libraries specifically. \note \QBS does currently not enforce that only dynamic libraries will be linked. \nodefaultvalue */ /*! \qmlproperty stringList cpp::staticLibraries Like \l libraries, but expressing the intention to link static libraries specifically. \note \QBS does currently not enforce that only static libraries will be linked. \nodefaultvalue */ /*! \qmlproperty string cpp::executablePrefix A string to prepend to the executable file \l{Product::targetName}{name}. \defaultvalue \c "" */ /*! \qmlproperty string cpp::dynamicLibraryPrefix A string to prepend to the dynamic library file \l{Product::targetName}{name}. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c "" or \c "lib" */ /*! \qmlproperty string cpp::loadableModulePrefix \appleproperty A string to prepend to the Darwin loadable module file \l{Product::targetName}{name}. \defaultvalue \c "" */ /*! \qmlproperty string cpp::staticLibraryPrefix A string to prepend to the static library file \l{Product::targetName}{name}. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c "" or \c "lib" */ /*! \qmlproperty string cpp::executableSuffix A string to append to the executable file \l{Product::targetName}{name}. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c "" or \c ".exe" */ /*! \qmlproperty string cpp::dynamicLibrarySuffix A string to append to the dynamic library file \l{Product::targetName}{name}. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c ".so", \c ".dll" or \c "dylib" */ /*! \qmlproperty string cpp::dynamicLibraryImportSuffix \windowsproperty A string to append to the dynamic library import file \l{Product::targetName}{name}. \defaultvalue \c ".lib" */ /*! \qmlproperty string cpp::loadableModuleSuffix \appleproperty A string to append to the Darwin loadable module file \l{Product::targetName}{name}. \defaultvalue \c ".bundle" */ /*! \qmlproperty string cpp::staticLibrarySuffix A string to append to the executable file \l{Product::targetName}{name}. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c ".a" or \c ".lib" */ /*! \qmlproperty string cpp::debugInfoSuffix A string to append to the debug information file name. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c ".debug", \c ".pdb" or \c ".dwarf" */ /*! \qmlproperty string cpp::debugInfoBundleSuffix \appleproperty A string to append to the debug information bundle name. \defaultvalue \c ".dSYM" */ /*! \qmlproperty string cpp::objectSuffix A string to append to the generated object files. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c ".o" or \c ".obj" */ /*! \qmlproperty string cpp::linkerMapSuffix A string to append to the generated linker memory map files. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical value is \c ".map" */ /*! \qmlproperty string cpp::compilerListingSuffix A string to append to the generated compiler listing files. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical value is \c ".lst" */ /*! \qmlproperty string cpp::assemblerListingSuffix A string to append to the generated assembler listing files. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical value is \c ".lst" */ /*! \qmlproperty pathList cpp::prefixHeaders \since Qbs 1.0.1 A list of files to automatically include at the beginning of each source file in the \l{Product}{product}. \nodefaultvalue */ /*! \qmlproperty string cpp::optimization The optimization level. \defaultvalue \l{qbs::optimization}{qbs.optimization} */ /*! \qmlproperty bool cpp::treatWarningsAsErrors Whether warnings will be handled as errors and cause the build to fail. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::useCPrecompiledHeader \since Qbs 1.5 Whether to use a precompiled header for compiling C sources if one is present. Set this property to \c false in a \l Group item to disable precompiled headers for some sources even though a precompiled header is present in the product. See \l{filetags-cpp}{Relevant File Tags} for the associated file tags. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useCxxPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for C++. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useObjcPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for Objective-C. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useObjcxxPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for Objective-C++. \defaultvalue \c true */ /*! \qmlproperty string cpp::warningLevel The warning level for the compiler: \c{"none"} or \c{"all"}. \defaultvalue \c{"all"} */ /*! \qmlproperty stringList cpp::driverFlags \since Qbs 1.6 A list of flags that are added to all compilation and linking commands performed by the compiler driver, independently of the language. \nodefaultvalue */ /*! \qmlproperty stringList cpp::driverLinkerFlags \since Qbs 1.11 A list of flags that are added to all linking commands performed by the compiler driver, independently of the language. \nodefaultvalue */ /*! \qmlproperty stringList cpp::commonCompilerFlags \since Qbs 1.0.1 A list of flags that are added to all compilation commands independently of the language. \nodefaultvalue */ /*! \qmlproperty string cpp::compilerVersion Compiler version string consisting of major, minor and patch numbers, separated by a dot. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionMajor \since Qbs 1.4 The major version of the compiler. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionMinor \since Qbs 1.4 The minor version of the compiler. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionPatch \since Qbs 1.4 The patch level component of the compiler version. \nodefaultvalue */ /*! \qmlproperty stringList cpp::assemblerFlags \since Qbs 1.5 A list of additional flags for the assembler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cppFlags A list of additional flags for the C preprocessor. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cFlags A list of additional flags for the C compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cxxFlags A list of additional flags for the C++ compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cLanguageVersion \since Qbs 1.4 The version of the C standard with which the code must comply. If this property is set, the corresponding compiler and linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. If the list contains more than one value, the highest version is chosen. Possible values include: \c{"c89"}, \c{"c99"}, \c{"c11"}, \c{"c17"}, \c{"c2x"}. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cxxLanguageVersion \since Qbs 1.4 The version of the C++ standard with which the code must comply. If this property is set, the corresponding compiler and linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. If the list contains more than one value, the highest version is chosen. Possible values include: \c{"c++98"}, \c{"c++11"}, \c{"c++14"}, \c{"c++17"}, \c{"c++20"}, \c{"c++23"}, \c{"c++26"}. \nodefaultvalue */ /*! \qmlproperty bool cpp::useLanguageVersionFallback \since Qbs 1.11 Whether to explicitly use the language standard version fallback values in compiler command line invocations. By default, \QBS will automatically substitute fallback values for the C and C++ language standard versions specified by the \l cLanguageVersion and \l cxxLanguageVersion properties, which are passed to the \c{-std=} compiler command line option with GNU-compatible toolchains, if it detects that you are using an older toolchain which does not support the standard values. The substitutions are made as follows: \table \header \li Value \li Substitute \row \li c++11 \li c++0x \row \li c11 \li c1x \row \li c++14 \li c++1y \row \li c++17 \li c++1z \endtable If this property is explicitly set to \c true, \QBS will always use the fallback values. If this property is explicitly set to \c false, \QBS will never use the fallback values. This property has no effect with the Microsoft Visual C++ compiler. \nodefaultvalue */ /*! \qmlproperty string cpp::cxxStandardLibrary \since Qbs 1.4 The C++ standard library to link to. If this property is set, the corresponding compiler and linker flags will be added, assuming the value is valid for the current toolchain. If the value is left undefined, the compiler default will be used. Possible values include: \c{"libstdc++"}, \c{"libc++"}. \nodefaultvalue */ /*! \qmlproperty stringList cpp::objcFlags A list of additional flags for the Objective-C compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::objcxxFlags A list of additional flags for the Objective-C++ compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::linkerFlags A list of additional flags for the linker. These flags should \e not be escaped using the \c -Wl or \c -Xlinker syntaxes, as \QBS will do this automatically based on the linker being used. \sa linkerMode \nodefaultvalue */ /*! \qmlproperty string cpp::assemblerName \since Qbs 1.5 The name of the assembler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::toolchainInstallPath The directory path where the toolchain is installed. This property is set in the build profile. This is usually the base property from which all compiler and tool paths are automatically derived. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::assemblerPath \since Qbs 1.5 The full path of the assembler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::compilerName The name of the main compiler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::compilerPath The full path of the main compiler binary. This property is set in the build profile. If the toolchain provides different compilers for different languages, \l{cpp::}{compilerPathByLanguage} is used. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty var cpp::compilerPathByLanguage \since Qbs 1.3 A \c{string} to \c{string} map that maps file tags to full paths of compiler binaries. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty stringList cpp::compilerWrapper \since Qbs 1.1 A wrapper binary and its arguments for wrapping compiler calls. This is useful for compiler wrappers, such as \c ccache. \nodefaultvalue */ /*! \qmlproperty string cpp::linkerName \since Qbs 1.1.1 The name of the linker binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::linkerPath \since Qbs 1.1.1 The full path of the linker binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty stringList cpp::linkerWrapper \since Qbs 1.6.2 A wrapper binary and its arguments for wrapping linker calls. This is useful for linker wrappers as needed by Bullseye Coverage, for example. \nodefaultvalue */ /*! \qmlproperty string cpp::entryPoint \since Qbs 1.3 The name of the entry point of an executable or dynamic library. If this property is left undefined, the toolchain's default is used. \nodefaultvalue */ /*! \qmlproperty string cpp::runtimeLibrary \since Qbs 1.3.3 The type of the runtime library used. Accepted values are \c{"static"} and \c{"dynamic"}. If this property is set to \c{undefined}, the default runtime library of the toolchain is used. \note This property is only functional for MSVC and MinGW. \defaultvalue \c{"dynamic"} for MSVC and MinGW, \c{undefined} for other compilers. */ /*! \qmlproperty bool cpp::enableExceptions \since Qbs 1.5 Whether to enable exceptions in C++ code. \defaultvalue \c{true} */ /*! \qmlproperty bool cpp::enableSuspiciousLinkerFlagWarnings \since Qbs 1.8 Whether to print warnings about escaped linker flags (such as \c -Xlinker and \c -Wl). \defaultvalue \c{true} */ /*! \qmlproperty string cpp::exceptionHandlingModel \since Qbs 1.5 The exception handling model to use. For MSVC, this can be \c{"default"}, \c{"seh"} or \c{"externc"}. For all other compilers, \c{"default"} indicates the default or the only exception handling model. \defaultvalue \c{"default"} */ /*! \qmlproperty bool cpp::enableRtti \since Qbs 1.5 Whether to enable runtime type information in C++ code. \nodefaultvalue */ /*! \qmlproperty bool cpp::enableReproducibleBuilds \since Qbs 1.5 Whether the compiler should try to generate reproducible object files. Some compilers (notably GCC) use random numbers for generating symbol names that have to be different in every compilation unit. This is avoided by setting this property to \c{true}. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::enableTimeTrace \since Qbs 3.3 Whether the compiler should generate time trace profiling information. When enabled and supported by the compiler, compilation of C and C++ source files will additionally produce \c{.time_trace.json} files alongside the regular object files. These files can be inspected with trace viewers such as Chromium's \c{about:tracing} page. If the toolchain does not support time trace generation, this property has no effect. The generated files are assigned the \c{"time_trace"} file tag. This option is currently supported only for the \c clang toolchain. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::treatSystemHeadersAsDependencies \since Qbs 1.8 Whether included header files found via \l{cpp::}{systemIncludePaths}, \l{cpp::}{distributionIncludePaths}, or \l{cpp::}{compilerIncludePaths} will be added to the dependencies of the respective object file. This means that modification of such header files (or any of the headers they include) will cause recompilation. \defaultvalue \c{false} */ /*! \qmlproperty stringList cpp::dsymutilFlags \since Qbs 1.4.1 \appleproperty Additional flags for the \c dsymutil tool. \note If this property contains the \c{-f} or \c{--flat} options, this will cause \QBS to generate "flat" (single-file) \c{.dwarf} debug symbol files instead of \c{.dSYM} bundles (directories) when \l{cpp::}{separateDebugInformation} is set to \c{true}. \nodefaultvalue */ /*! \qmlproperty string cpp::dsymutilPath \since Qbs 1.4 \appleproperty The full path of the \c dsymutil binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::lipoPath \since Qbs 1.9 \appleproperty The full path of the \c lipo binary. \defaultvalue Determined automatically. */ /*! \qmlproperty pathList cpp::frameworkPaths \appleproperty A list of framework search paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty pathList cpp::systemFrameworkPaths \appleproperty A list of framework search paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. Header files in frameworks in those paths will not cause warnings. \nodefaultvalue */ /*! \qmlproperty stringList cpp::frameworks \appleproperty A list of frameworks to be linked. If the framework is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty stringList cpp::weakFrameworks \appleproperty A list of frameworks to be weakly linked. If the framework is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty bool cpp::automaticReferenceCounting \since Qbs 1.4 \appleproperty Whether to enable Automatic Reference Counting (ARC) for Objective-C and Objective-C++ source code. If left undefined, uses the compiler default (probably \c{false}). \nodefaultvalue */ /*! \qmlproperty bool cpp::requireAppExtensionSafeApi \since Qbs 1.4 \appleproperty Whether to enforce the use of only app-extension-safe APIs on Apple platforms. This is necessary for building Application Extensions in OS X Yosemite and iOS 8 and above. If left undefined, uses the compiler and linker defaults (probably \c{false}). \nodefaultvalue */ /*! \qmlproperty string cpp::minimumIosVersion \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of iOS that the product should run on. Passes \c{-miphoneos-version-min=} to the compiler. If set to undefined, compiler defaults will be used. \note \QBS sets minimum version to \c "6.0" for \c armv7a because earlier iOS versions are broken in recent XCode installations. \defaultvalue \c "6.0" for \c armv7a, \c undefined otherwise */ /*! \qmlproperty string cpp::minimumOsxVersion \obsolete \appleproperty Deprecated in \QBS 1.5.2. Use \l{cpp::minimumMacosVersion} instead. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumMacosVersion \since Qbs 1.5.2 \appleproperty A version number in the format \c{[major].[minor]}indicating the earliest version of macOS that the product should run on. Passes \c{-mmacosx-version-min=} to the compiler. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumWatchosVersion \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Apple watchOS that the product should run on. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumTvosVersion \since Qbs 1.5 \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Apple tvOS that the product should run on. If left undefined, compiler defaults will be used. \note \QBS sets the minimum version to \c "6.0", because earlier tvOS versions are not supported by recent XCode installations by default. \defaultvalue \c "6.0 */ /*! \qmlproperty string cpp::archiverName The name of the archiver binary. This property is usually predetermined by the toolchain and may be overridden. For instance, when enabling link-time optimization in a gcc-based toolchain, \c{"gcc-ar"} has to be used instead of \c{"ar"}. \defaultvalue Depends on the selected toolchain. */ /*! \qmlproperty string cpp::archiverPath The full path of the archiver binary. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::archiverFlags Additional flags that are appended to the archiver command. \defaultvalue An empty list \since Qbs 3.0.0 */ /*! \qmlproperty string cpp::exportedSymbolsCheckMode \since Qbs 1.4.1 \unixproperty Controls how \QBS determines whether an updated dynamic library causes relinking of dependents. The default value is \c "ignore-undefined", which means that undefined symbols being added or removed do not cause any relinking. If that should happen, for example because dependent products are linked with an option such as \c "--no-undefined", this property can be set to \c "strict". \defaultvalue \c "ignore-undefined" */ /*! \qmlproperty string cpp::linkerMode \since Qbs 1.6 Controls whether to automatically use an appropriate compiler frontend instead of the system linker when linking binaries. The default is \c{"automatic"}, which chooses either the C++ compiler, C compiler, or system linker specified by the \l{cpp::}{linkerName} and \l{cpp::}{linkerPath} properties, depending on the type of object files present on the linker command line. Set this property to \c{"manual"} to explicitly specify the linker using the \l{cpp::}{linkerName} and \l{cpp::}{linkerPath} properties. \defaultvalue \c "automatic" */ /*! \qmlproperty string cpp::linkerVariant \since Qbs 1.13 Set this property to force the use of a specific linker. A non-empty value will result in the \c {-fuse-ld} option being emitted when linking with \c gcc, \c clang or \c clang-cl. Other toolchains do not support this property. The possible values for \c clang and \c gcc are \c "bfd", \c "gold", \c "lld" and \c "mold", the possible values for \c clang-cl are \c "link" and \c "lld". The following example demonstrates how to change the linker for different toolchains: \code Properties { condition: qbs.toolchain.includes("gcc") cpp.linkerVariant: "gold" } Properties { condition: qbs.toolchain.includes("clang-cl") cpp.linkerVariant: "lld" } \endcode \nodefaultvalue */ /*! \qmlproperty string cpp::nmName \since Qbs 1.2 \unixproperty The name of the \c nm binary. This property is set in the build profile. \defaultvalue \c{"nm"} */ /*! \qmlproperty string cpp::nmPath \since Qbs 1.2 \unixproperty The full path of the \c nm binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::objcopyName \since Qbs 1.4 \unixproperty The name of the \c objcopy binary. This property is set in the build profile. \defaultvalue \c{"objcopy"} */ /*! \qmlproperty string cpp::objcopyPath \since Qbs 1.4 \unixproperty The full path of the \c objcopy binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::stripName \since Qbs 1.4 \unixproperty The name of the \c strip binary. This property is set in the build profile. \defaultvalue \c{"strip"} */ /*! \qmlproperty string cpp::stripPath \since Qbs 1.4 \unixproperty The full path of the \c strip binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty bool cpp::positionIndependentCode \unixproperty Whether to generate position-independent code. If this property is left undefined, position-independent code is generated for libraries, but not for applications. \nodefaultvalue */ /*! \qmlproperty string cpp::rpathOrigin \since Qbs 1.11 \unixproperty A placeholder value used in an \c rpath string to refer to the directory containing the referring executable or shared library. \defaultvalue \c{"@loader_path"} on Mach-O based platforms (macOS, iOS, tvOS, watchOS); \c{"$ORIGIN"} on ELF based platforms (Linux and most other Unix-like platforms). */ /*! \qmlproperty stringList cpp::rpaths \unixproperty A list of \c rpaths that are passed to the linker. Paths that also appear in \l{cpp::}{systemRunPaths} are ignored. This property has no effect if \l useRPaths is not enabled. \nodefaultvalue \sa{How do I make use of rpaths?} */ /*! \qmlproperty stringList cpp::rpathLinkDirs \since Qbs 3.2 \unixproperty A list of \c paths that are passed to the linker as arguments to the \l rpathLinkFlag. Setting this property might be required in some cases when \l useRPaths is disabled. This property has no effect if \l useRPathLink is not enabled. \nodefaultvalue */ /*! \qmlproperty string cpp::sonamePrefix \since Qbs 1.5 \unixproperty A library name or full library path. If defined, the value of this property is used as a path to be prepended to the built shared library's \c SONAME identifier. The \c SONAME (\c LC_ID_DYLIB on Apple platforms, \c DT_SONAME on other Unix-like platforms) is the identifier that the dynamic linker will later use to reference the library. On Apple platforms, the path may contain the following placeholders: \list \li \c @rpath - Expands to paths defined by \c LC_RPATH Mach-O commands in the current process executable or the referring libraries. \li \c @executable_path - Expands to the current process executable location. \li \c @loader_path - Expands to the referring executable or library location. \endlist In most cases, using \c @rpath is sufficient and recommended. However, the prefix may be also specified using different placeholders, or an absolute path. For more information, see the \l{DYLD documentation} on dynamic library install names. \nodefaultvalue \sa{How do I make use of rpaths?} */ /*! \qmlproperty string cpp::soVersion \since Qbs 1.7 \unixproperty The version number to be appended to the soname in ELF shared libraries. \defaultvalue The major part of \l{Product::version}{product.version} if a version is set, otherwise \c []. */ /*! \qmlproperty bool cpp::useRPaths \since Qbs 1.3 \unixproperty If \c{false}, prevents the linker from writing \c rpaths to the binary. \defaultvalue \c{true} */ /*! \qmlproperty bool cpp::useRPathLink \since Qbs 1.8 \unixproperty Whether to use the \c{-rpath-link} linker option for transitive shared objects. \defaultvalue \c{true} on non-Darwin Unix platforms or when targeting macOS 10.4.x and older. */ /*! \qmlproperty string cpp::rpathLinkFlag \since Qbs 1.9 The rpath link flag used by the linker. \defaultvalue \l{qbs::toolchain}{toolchain}-dependent, typical values are \c "-rpath-link=" or \c "-L" */ /*! \qmlproperty string cpp::variantSuffix \since Qbs 1.10 A suffix to add to a product's target name if that product is of the \l{Product::type}{type} \c staticlibrary or \c dynamiclibrary. On Darwin platforms, applications and loadable modules are also affected. By default, this property is left empty on all platforms unless the product is multiplexed over the \l{qbs::buildVariants}{qbs.buildVariants} property. In that case, for the debug variant of the product, the default value is \c{"d"} on Windows and \c{"_debug"} on Darwin platforms, such as macOS. On all other platforms and in release mode, the default value is \c []. For example, building a dynamic library called \c MyLib that is multiplexed over the \l{qbs::buildVariants}{qbs.buildVariants} property with MSVC will produce files called \c{MyLib.dll} (for the release version of the product) and \c{MyLibd.dll} (for the debug version). \defaultvalue Platform-specific. */ /*! \qmlproperty string cpp::visibility \unixproperty The visibility level for exported symbols. Possible values include: \c{"default"}, \c{"hidden"}, \c{"hiddenInlines"}, and \c{"minimal"}, which combines \c{"hidden"} and \c{"hiddenInlines"}. \defaultvalue \c{"default"} */ /*! \qmlproperty bool cpp::generateManifestFile \since Qbs 1.5.0 \windowsproperty Whether to auto-generate a manifest file and include it in the binary. Set this property to \c false if you provide your own \c rc file. \defaultvalue \c{true} */ /*! \qmlproperty string cpp::windowsApiCharacterSet \since Qbs 1.0.1 \windowsproperty The character set used in the Win32 API. The value \c "unicode" defines the preprocessor symbols \c UNICODE and \c _UNICODE, \c "mbcs" defines \c _MBCS, and setting the value to \c undefined will use the default character set. \defaultvalue \c{"unicode"} */ /*! \qmlproperty string cpp::windowsApiFamily \since Qbs 1.10 \windowsproperty The Windows API family that the application or library is targeting. This value is used when building Universal Windows Platform applications. Possible values include: \c{"desktop"}, \c{"pc"}, \c{"phone"}, \c{"server"}, and \c{"system"}, which are mapped to the corresponding set of possible values for the \c WINAPI_FAMILY preprocessor define in the Windows SDK. \defaultvalue Undefined, which lets the Windows SDK headers determine the default. */ /*! \qmlproperty stringList cpp::windowsApiAdditionalPartitions \since Qbs 1.10 \windowsproperty A list of additional Windows API partitions to enable in addition to the ones implicitly enabled by the value of \l{cpp::}{windowsApiFamily} (\c WINAPI_FAMILY). This value is used when building Windows Store applications. For example, setting \l{cpp::}{windowsApiFamily} to \c{"pc"} and this property to \c{["phone"]} will allow you to create Windows Store applications that target all Universal Windows Platform device families (\c "Universal" apps). Possible values include: \c{"app"}, \c{"desktop"}, \c{"pc"}, \c{"phone"}, \c{"server"}, and \c{"system"}, which are mapped to the corresponding set of possible \c WINAPI_PARTITION_* preprocessor defines in the Windows SDK. \defaultvalue Undefined, which lets the Windows SDK headers determine the default partitions based on the value of \c WINAPI_FAMILY. \sa windowsApiFamily */ /*! \qmlproperty bool cpp::requireAppContainer \since Qbs 1.10 \windowsproperty Whether the generated executable or dynamic-link library \e requires an AppContainer execution environment. Set to \c true when creating Universal Windows Platform applications. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumWindowsVersion \windowsproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Windows that the product should run on. Defines \c WINVER, \c _WIN32_WINNT, and \c _WIN32_WINDOWS, and applies a version number to the linker flags \c /SUBSYSTEM and \c /OSVERSION for MSVC or \c --major-subsystem-version, \c --minor-subsystem-version, \c --major-os-version, and \c --minor-os-version for MinGW. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty bool cpp::alwaysUseLipo \since Qbs 1.9 Whether to always use \c lipo when combining Mach-O output files on Apple platforms, even if there is only one CPU architecture. This value should not normally need to be changed. \defaultvalue \c{false} */ /*! \qmlproperty var cpp::compilerDefinesByLanguage \since Qbs 1.10 A \c{string} to \c{string} to \c{string} map of language tags to list of preprocessor macros that are used for all projects that are using the current toolchain. User project files usually do not set this property. \note This property will not be usable without also setting \l{cpp::}{enableCompilerDefinesByLanguage}. \nodefaultvalue */ /*! \qmlproperty pathList cpp::compilerIncludePaths \since Qbs 1.6 A list of \c #include search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::compilerFrameworkPaths \since Qbs 1.6 A list of framework search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::compilerLibraryPaths \since Qbs 1.6 A list of library search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::distributionFrameworkPaths \since Qbs 1.8 A list of distribution-specific framework search paths, prioritized after \l{cpp::}{systemFrameworkPaths}. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::distributionIncludePaths \since Qbs 1.8 A list of distribution-specific include paths that are passed as system include paths to the compiler, prioritized after \l{cpp::}{systemIncludePaths}. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::distributionLibraryPaths \since Qbs 1.8 A list of distribution-specific library search paths. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty stringList cpp::enableCompilerDefinesByLanguage \since Qbs 1.10 A list of languages (one or more of \c{"c"}, \c{"cpp"}, \c{"objc"}, \c{"objcpp"}) to extract the list of default compiler defines for in \l{cpp::}{compilerDefinesByLanguage}. Because this has performance implications, no languages are enabled by default. \nodefaultvalue */ /*! \qmlproperty bool cpp::generateLinkerMapFile \since Qbs 1.13 Whether to auto-generate a linker map file. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::generateCompilerListingFiles \since Qbs 1.15 Whether to auto-generate compiler listing files. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::generateAssemblerListingFiles \since Qbs 1.15 \baremetalproperty Whether to auto-generate an assembler listing files. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::removeDuplicateLibraries \since Qbs 1.16 Whether the list of the objects and libraries is reduced to a list of unique values before being passed to the linker. \defaultvalue \c{true} */ /*! \qmlproperty string cpp::windowsSdkVersion \since Qbs 1.19 Which Windows SDK version should be used with MSVC toolchain. By default, the latest SDK is used. \windowsproperty \nodefaultvalue */ /*! \qmlproperty string cpp::enableCxxLanguageMacro \since Qbs 1.20 Whether to set the \c{/Zc:__cplusplus} macro (\l{https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus}) This property only applies to MSVC toolchain. clang-cl also supports this option, but it has no effect. \windowsproperty \defaultvalue \c{true} for MSVC, \c{false} for clang-cl */ /*! \qmlproperty string cpp::importPrivateLibraries \since Qbs 2.4 Whether to automatically import external libraries from dependencies. If set to true in the product that depends on the static library, the external dependencies (such as \l{cpp::staticLibraries}{staticLibraries} and \l{cpp::dynamicLibraries}{dynamicLibraries}) of this library are also added to products that depend on this library. \code StaticLibrary { files: "lib.cpp" cpp.staticLibraries: ["l", "y"] } \endcode If set to false, the explicit \l{Export} item is required: \code StaticLibrary { files: "lib.cpp" Export { Depends { name: "cpp" } cpp.staticLibraries: ["l", "y"] } } \endcode We recommend using the \l{Export} item as it provides more flexibility. \note The default value is subject to change. \defaultvalue \c{true} */ /*! \qmlproperty bool cpp::forceUseCxxModules \since Qbs 2.5 Set this property to \c true to force support for C++20 Modules. On details how to use modules, see the corresponding \l{tutorial-10.html}{section} in the tutorial. By default, modules support is disabled since this feature is considered experimental. \note The default value is subject to change. \defaultvalue \c{false} */ qbs-src-3.3.1/doc/reference/modules/qt-quick-module.qdoc0000644000175100017510000000545015232633614022553 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.quick \inqmlmodule QbsModules \brief Provides Qt Quick 2 support. The Qt.quick module provides support for Qt Quick 2. \sa Qt.qml, Qt.declarative \section2 Relevant File Tags \target filetags-quick \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.quick.qrc"} \li \c{*.qrc} \li 1.10 \li Qt resource files with this file tag will be picked up by the Qt Quick compiler rule, and all QML files in the resource will be compiled. This file tag will only be added automatically if the Qt Quick compiler is available. \endtable */ /*! \qmlproperty bool Qt.quick::compilerAvailable Whether the Qt installation contains the Qt Quick compiler. \defaultvalue auto-detected \since 1.10 */ /*! \qmlproperty bool Qt.quick::useCompiler Whether to make use of the Qt Quick compiler. \defaultvalue \l compilerAvailable \since 1.11 */ /*! \qmlproperty bool Qt.quick::qmlDebugging Whether QML debugging support should be compiled into your binaries. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.quick::qmlImportsPath The absolute path to the directory where Qt's QML imports are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.quick::qmlPath The absolute path to the directory where Qt's QML files are installed. This property is left undefined for Qt 4. \defaultvalue Determined by \l{setup-qt}. */ qbs-src-3.3.1/doc/reference/modules/protobufcpp-module.qdoc0000644000175100017510000001313515232633614023357 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype protobuf.cpp \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for protocol buffers for the C++ language. The \c protobuf.cpp module provides support for generating C++ headers and sources from proto definition files using the \l protoc tool. A simple qbs file that uses protobuf can be written as follows: \code CppApplication { Depends { name: "protobuf.cpp" } files: ["foo.proto", "main.cpp"] } \endcode A generated header now can be included in the C++ sources: \code #include int main(int argc, char* argv[]) { Foo bar; bar.set_answer(42); google::protobuf::ShutdownProtobufLibrary(); return 0; } \endcode \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"protobuf.input"} \li \c{*.proto} \li 1.13.0 \li Source files with this tag are considered inputs to the \c protoc compiler. \row \li \c{"protobuf.grpc"} \li \li 1.14.0 \li Source files with this tag are considered as gRPC files. \row \li \c{"protobuf.hpp"} \li \li 1.18.0 \li This tag is attached to the header files generated by \c protoc compiler. \endtable \section2 Dependencies The \l protobuf.cpp module requires runtime libraries to be operational. It depends on the \c "protobuflib" module which can be created by the \l qbspkgconfig or fallback module providers (the corresponding packages are \c protobuf or \c protobuf-lite). If \l useGrpc is set to true, the \l protobuf.cpp module also depends on the \c "grpc++" module. */ /*! \qmlproperty string protobuf.cpp::compilerName The name of the protoc binary. \since Qbs 1.17 \defaultvalue \c "protoc" */ /*! \qmlproperty string protobuf.cpp::compilerPath The path to the protoc binary. Use this property to override the auto-detected location. \since Qbs 1.17 \defaultvalue \c auto-detected */ /*! \qmlproperty pathList protobuf.cpp::importPaths The list of imports that are passed to the \c protoc tool via the \c --proto_path option. These imports should contain the proto files. They are used to determine the relative structure of the generated files. \note The paths are passed to \c protoc in the same order as specified in this property and \c protoc output may differ depending on that order. \defaultvalue \c [] */ /*! \qmlproperty string protobuf.cpp::outputDir \readonly The directory where the \c protoc compiler generated files are placed. The value of this property is automatically set by \QBS and cannot be changed by the user. */ /*! \qmlproperty bool protobuf.cpp::useGrpc Whether to use gRPC framework. Use this property to enable support for the modern open source high performance RPC framework by Google, gRPC (\l{https://www.grpc.io}). A simple qbs file that uses grpc can be written as follows: \code CppApplication { Depends { name: "protobuf.cpp" } protobuf.cpp.useGrpc: true files: ["main.cpp"] Group { files: "grpc.proto" fileTags: "protobuf.grpc" } } \endcode \note that \c protobuf.grpc tag should be assigned manually because gRPC uses same \c *.proto files and \QBS can't detect whether to generate gRPC or \c protobuf. The following \c grpc.proto file... \code syntax = "proto3"; package Qbs; message Request { string name = 1; } message Response { string name = 1; } service Grpc { rpc doWork(Request) returns (Response) {} } \endcode ...can be used in the C++ sources as follows: \code #include class Service final : public Qbs::Grpc::Service { grpc::Status doWork( grpc::ServerContext* context, const Qbs::Request* request, Qbs::Response* reply) override { (void)context; reply->set_name(request->name()); return grpc::Status::OK; } }; \endcode \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/modules/asan-module.qdoc0000644000175100017510000000540615232633614021740 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Sanitizers.address \inqmlmodule QbsModules \brief Provides AddressSanitizer support. Provides support for the \l{https://clang.llvm.org/docs/AddressSanitizer.html}{AddressSanitizer} tool, which uses compiler instrumentation to detect memory corruption bugs at runtime. */ /*! \qmlproperty string Sanitizers.address::detectUseAfterReturn Controls whether support for detecting problems with stack use after returning from a function should be built into the application. The possible values are: \list \li \c "always": Check for this type of problem unconditionally. \li \c "runtime": Build with this capability, but only do the respective checks if they are explicitly requested at runtime. \li \c "never": Do not build with support for this check. \endlist \note Only the clang compiler (starting at 13.0) supports the full set of values. With GCC and MSVC, "runtime" maps to "always". \defaultvalue \c "always" */ /*! \qmlproperty bool Sanitizers.address::detectUseAfterScope Controls whether to detect bugs relating the use of variables after they've gone out of scope. \note This property has no effect when building with with GCC and MSVC. \defaultvalue \c true */ /*! \qmlproperty bool Sanitizers.address::enabled Controls whether to enable AddressSanitizer. \note You do not need to check if the current toolchain supports AddressSanitizer: If \QBS detects that it doesn't, this property has no effect. \defaultvalue \c true */ qbs-src-3.3.1/doc/reference/modules/flatbuf-cpp-module.qdoc0000644000175100017510000000777015232633614023227 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype flatbuf.cpp \inqmlmodule QbsModules \since Qbs 2.4 \brief Provides support for \l{https://google.github.io/flatbuf/}{flatbuf} for the C++ language. The \c flatbuf.cpp module provides support for generating C++ headers and sources from flatbuf definition files using the \c flatc tool. A simple qbs file that uses flatbuf can be written as follows: \code CppApplication { Depends { name: "flatbuf.cpp" } files: ["foo.fbs", "main.cpp"] } \endcode A generated header now can be included in the C++ sources: \code #include int main(int argc, char* argv[]) { flatbuf::FlatBufferBuilder builder; auto foo = QbsTest::CreateFoo(builder, 42); return 0; } \endcode \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"flatbuf.input"} \li \c{*.fbs} \li 2.4.0 \li Source files with this tag are considered inputs to the \c flatc compiler. \endtable \section2 Dependencies This module depends on the \c flatbuffers module which can be created via the \l{conan}{Conan} module provider. */ /*! \qmlproperty string flatbuf.cpp::compilerName The name of the \c flatc binary. \defaultvalue \c "flatc" */ /*! \qmlproperty string flatbuf.cpp::compilerPath The path to the \c flatc binary. Use this property to override the auto-detected location. \defaultvalue \c auto-detected */ /*! \qmlproperty string flatbuf.cpp::filenameExtension The extension appended to the generated file names. If not specified, the default extension (\c ".h") is used. This property corresponds to the \c --filename-ext option of the \c flatc tool. \nodefaultvalue */ /*! \qmlproperty string flatbuf.cpp::filenameSuffix The suffix appended to the generated file names. If not specified, the default suffix (\c "_generated") is used. This property corresponds to the \c --filename-suffix option of the \c flatc tool. \nodefaultvalue */ /*! \qmlproperty pathList flatbuf.cpp::importPaths The list of import paths that are passed to the \c flatc tool via the \c -I option. \defaultvalue \c [] */ /*! \qmlproperty string flatbuf.cpp::includePrefix Prefix path prepended to any generated include statements. This property corresponds to the \c --include-prefix option of the \c flatc tool. \nodefaultvalue */ /*! \qmlproperty bool flatbuf.cpp::keepPrefix Whether to keep original prefix of schema include statement. This property corresponds to the \c --keep-prefix option of the \c flatc tool. \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/modules/xcode-module.qdoc0000644000175100017510000001103715232633614022115 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype xcode \inqmlmodule QbsModules \since Qbs 1.5 \brief Provides Xcode support. The \c xcode module contains properties and rules for Xcode-based development. This module provides the foundation for several other modules on Apple platforms, including the \l{cpp} and \l{ib} modules. */ /*! \qmlproperty path xcode::developerPath The developer directory of the Xcode installation. Corresponds to the \c DEVELOPER_DIR environment variable. \defaultvalue The developer directory of the Xcode installation at its default location in \c /Applications. For example, \c{"/Applications/Xcode.app/Contents/Developer"}. */ /*! \qmlproperty string xcode::sdk The version of the Xcode SDK used to build products. This can be specified as a full canonical SDK name (\c{"macosx10.10"}), a platform version number (\c{"10.10"}), or a platform identifier (\c{"macosx"}), in which case the latest SDK available for that platform will be used. \defaultvalue The latest SDK available in the Xcode installation for the current platform. Determined by \l{qbs::targetOS}{qbs.targetOS}. */ /*! \qmlproperty stringList xcode::targetDevices A list of the Apple devices targeted by this product. For macOS, watchOS, and tvOS, this should always be \c "mac", \c "watch", and \c "tv", respectively. For iOS, this can be one or both of \c "iphone" and \c "ipad". \defaultvalue The list of all device types supported by the current platform. Determined by \l{qbs::targetOS}{qbs.targetOS}. */ /*! \qmlproperty string xcode::sdkName \readonly The canonical name of the SDK used to build products. For example, \c macosx10.9. \defaultvalue \l{xcode::}{sdk} */ /*! \qmlproperty string xcode::sdkVersion \readonly The version number of the SDK used to build products. For example, 10.9. \defaultvalue \l{xcode::}{sdk} */ /*! \qmlproperty string xcode::latestSdkName \readonly The canonical name of the latest SDK available in the Xcode installation. For example, \c {macosx10.10}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty string xcode::latestSdkVersion \readonly The version number of the latest SDK available in the Xcode installation. For example, 10.10. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty stringList xcode::availableSdkNames \readonly The canonical names of all SDKs available in the Xcode installation for the current platform. For example, \c {[macosx10.9, macosx10.10]}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty stringList xcode::availableSdkVersions \readonly The version numbers of all SDK available in the Xcode installation for the current platform. For example, \c {[10.9, 10.10]}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty path xcode::platformPath \readonly The path of the platform directory containing \l{xcode::}{sdkPath}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty path xcode::sdkPath \readonly The path of the SDK used to build products. Equivalent to \l{qbs::sysroot}{qbs.sysroot}. \defaultvalue Determined by \l{xcode::}{developerPath} and \l{xcode::}{sdk}. */ qbs-src-3.3.1/doc/reference/modules/qt-qml-module.qdoc0000644000175100017510000001314715232633614022232 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.qml \inqmlmodule QbsModules \brief Provides Qt QML support. The Qt.qml module provides support for the Qt QML module, which contains classes for QML and JavaScript languages. \note If the current value of \l{qbs::architecture}{qbs.architecture} is not supported by \c qmlcachegen, the QML cache file generator rule is disabled. \sa Qt.quick, Qt.declarative \section2 Relevant File Tags \target filetags-qml \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.qml.js"} \li \c{*.js} \li 1.10 \li QML companion JavaScript files. Source files with this tag serve as input for the QML cache file generator. \row \li \c{"qt.qml.qml"} \li \c{*.qml} \li 1.8 \li Source files with this tag serve as inputs to the QML plugin scanner. \row \li \c{"qt.qml.types"} \li n/a \li 1.16 \li This tag is attached to the files created by the \c qmltyperegistrar tool if the \l importName property is set. \endtable */ /*! \qmlproperty string Qt.qml::importName Setting this value triggers QML type registration via the \c qmltyperegistrar tool, which results in the creation of a file with the tag \c{"qt.qml.types"}. The given string is the name under which the registered types can be imported by QML code that wants to use them. \note This functionality is only available with Qt 5.15 or later. \since Qbs 1.16 \nodefaultvalue */ /*! \qmlproperty string Qt.qml::importVersion Specifies the version of the types to be registered. Values consist of a major and an optional minor number, separated by dots. This property has no effect if \l importName is not set. \since Qbs 1.16 \defaultvalue \l {Product::version}{The product version} */ /*! \qmlproperty string Qt.qml::typesFileName Specifies the name of the file that declares the types registered for this product. For applications, the default value is \c{.qmltypes}, where \c{} is the product's \l{Product::targetName}{target name}. Otherwise, the default value is "plugins.qmltypes". \note The naming conventions are still in flux. When in doubt, consult the Qt documentation. This property has no effect if \l importName is not set. \since Qbs 1.16 */ /*! \qmlproperty string Qt.qml::typesInstallDir The directory to install the qmltypes file into. If this property is empty or undefined, the file will not be installed. This property has no effect if \l importName is not set. \since Qbs 1.16 \nodefaultvalue */ /*! \qmlproperty stringList Qt.qml::extraMetaTypesFiles Specifies extra metatypes files to pass to the \c qmltyperegistrar tool via the \c{--foreign-types} option when registering QML types. \note This property is only needed for external libraries, not products or modules pulled via \c Depends items. In particular, you don't need to (and should not) use it to collect the metatypes files of Qt modules. These are found automatically. This property has no effect if \l importName is not set. \since Qbs 1.16 \nodefaultvalue */ /*! \qmlproperty string Qt.qml::qmlImportScannerName The base name of the QML import scanner. Set this value if your system uses a name different from the default value. \defaultvalue \c{"qmlimportscanner"} */ /*! \qmlproperty string Qt.qml::qmlPath The absolute path to the directory where Qt's QML files are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty bool Qt.qml::generateCacheFiles Whether QML cache files are generated. \defaultvalue \c{false} */ /*! \qmlproperty bool Qt.qml::cachingEnabled \readonly This property is \c true if \l{Qt.qml::}{generateCacheFiles} is \c{true} and the platform supports QML cache generation. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.qml::qmlCacheGenPath The absolute path to the \c qmlcachegen executable. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.qml::cacheFilesInstallDir The path to the directory where the cache files are installed. If this property is set, QML cache files are automatically installed. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/modules/nsis-module.qdoc0000644000175100017510000001315015232633614021765 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype nsis \inqmlmodule QbsModules \since Qbs 1.2 \brief Provides Nullsoft Scriptable Install System support. The \c nsis module contains properties and rules for building EXE installers for Windows using the Nullsoft Scriptable Install System (NSIS). This module is available on all platforms. \note A typical NSIS script includes an \c OutFile command to set the filename of the generated installer executable. However, \QBS overrides any \c OutFile commands found in the script, and therefore, you must use the \l{Product::targetName}{product.targetName} property to set the filename. \section2 Relevant File Tags \target filetags-nsis \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"nsh"} \li \c{*.nsh} \li 1.2 \li This tag is attached to NSIS header files. \row \li \c{"nsi"} \li \c{*.nsi} \li 1.2 \li This tag is attached to NSIS script files. \row \li \c{"nsissetup"} \li - \li 1.2 \li The rule that creates the NSIS setup executable attaches this tag to its output artifact. \endtable */ /*! \qmlproperty stringList nsis::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty bool nsis::disableConfig Whether to exclude \c nsisconf.nsh. Generally, you do not need to set this property. \defaultvalue \c{false} */ /*! \qmlproperty bool nsis::enableQbsDefines Whether to define preprocessor macros corresponding to the values from the \l{Project}{project} and \l{Product}{product} objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \defaultvalue \c{true} */ /*! \qmlproperty string nsis::warningLevel The severity of the warnings to emit. The higher the level, the more warnings will be shown. The levels \c{none}, \c{errors}, \c{warnings}, \c{info}, and \c{all} correspond to the NSIS verbosity levels 0 through 4, inclusive. \c{normal} corresponds to the default level. \defaultvalue \c{"normal"} */ /*! \qmlproperty stringList nsis::compilerFlags A list of additional flags for the NSIS compiler. \nodefaultvalue */ /*! \qmlproperty string nsis::compressor The compression algorithm used to compress files and data in the installer. Setting this property overrides any \c SetCompressor command in the NSI file being compiled. Possible values include: \c{"default"}, \c{"zlib"}, \c{"zlib-solid"}, \c{"bzip2"}, \c{"bzip2-solid"}, \c{"lzma"}, \c{"lzma-solid"}. \defaultvalue \c{"default"} */ /*! \qmlproperty string nsis::version The NSIS version. Consists of four numbers separated by dots. For example, \c "2.46.0.0". \nodefaultvalue */ /*! \qmlproperty int nsis::versionMajor The NSIS major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int nsis::versionMinor The NSIS minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list nsis::versionParts The NSIS version as a list. For example, the NSIS version 2.46.0.0 would correspond to a value of \c[2, 46, 0, 0]. \defaultvalue \c [] */ /*! \qmlproperty int nsis::versionPatch The NSIS patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int nsis::versionBuild The fourth NSIS version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path nsis::toolchainInstallPath The NSIS installation directory. Determined by searching from the known registry keys and known installation paths until a match is found. This property should not normally need to be changed. \defaultvalue Determined automatically. */ /*! \qmlproperty string nsis::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"makensis"} */ /*! \qmlproperty string nsis::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \l{nsis::}{compilerName} */ qbs-src-3.3.1/doc/reference/modules/qt-core-module.qdoc0000644000175100017510000003375015232633614022373 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.core \inqmlmodule QbsModules \brief Provides Qt Core support. All other Qt modules have a dependency on the Qt.core module, and therefore you do not need to list it in your dependencies if you depend on at least one other \l{Qt Modules}{Qt module}. Some of the Qt.core properties only need to be defined if the respective installation of Qt was built in some unusual way, for instance by setting non-default \c configure flags. \section2 Relevant File Tags \target filetags-qtcore \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qch"} \li n/a \li 1.1 \li This tag is attached to the output artifacts of the rule that runs the \c qhelpgenerator tool. \row \li \c{"qdoc"} \li \c{*.qdoc} \li 1.1 \li Source files with this tag trigger a re-execution of the rule running the \c qdoc tool when their timestamp changes. \row \li \c{"qdocconf"} \li \c{*.qdocconf} \li 1.1 \li Source files with this tag trigger a re-execution of the rule running the \c qdoc tool when their timestamp changes. \row \li \c{"qdocconf-main"} \li - \li 1.1 \li Source files with this tag serve as inputs to the rule running the \c qdoc tool. \row \li \c{"qdoc-output"} \li n/a \li 1.5 \li Use this tag to match all \c qdoc outputs, for instance in a \l{Group} using the \l{Group::fileTagsFilter}{group.fileTagsFilter} property. \row \li \c{"qhp"} \li \c{*.qhp} \li 1.1 \li Files with this tag serve as inputs to the rule running the \c qhelpgenerator tool. Such files are created by \c qdoc, but can also appear as source files. \row \li \c{"qm"} \li n/a \li 1.1 \li This tag is attached to the output artifacts of the rule that runs the \c lrelease tool. \row \li \c{"qrc"} \li \c{*.qrc} \li 1.0 \li Files with this tag serve as inputs to the rule running the \c rcc tool. \row \li \c{"qt_plugin_metadata"} \li - \li 1.0 \li Source files with this tag trigger a re-execution of the rule running the \c moc tool when their timestamp changes. \row \li \c{"qt.core.metatypes"} \li n/a \li 1.16 \li This tag is attached to the JSON files that are potentially created if \l{Qt.core::generateMetaTypesFile}{generateMetaTypesFile} is enabled. \row \li \c{"qt.core.resource_data"} \li - \li 1.7 \li Source files with this tag serve as inputs to the rule creating \c qrc files. \row \li \c{"ts"} \li \c{*.ts} \li 1.0 \li Files with this tag serve as inputs to the rule running the \c lrelease tool. \row \li \c{"mocable"} \li - \li 1.13 \li Use this tag to force \QBS to run \c moc on the respective files, even though they do not contain \c Q_OBJECT or a related macro. \row \li \c{"unmocable"} \li - \li 1.2 \li Use this tag for files that \QBS should not run \c moc on, even though they contain \c Q_OBJECT or a related macro. \endtable */ /*! \qmlproperty stringList Qt.core::availableBuildVariants The build variants that this Qt installation offers. \defaultvalue Set by \l{setup-qt}. */ /*! \qmlproperty path Qt.core::binPath The path in which Qt tools such as \c qmake, \c moc, and so on are located. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::combineMocOutput Whether the C++ sources created by \c moc are combined into a single C++ file per product. For projects where many header files are to be handled by \c moc, this can speed up compilation considerably. However, side effects may occur as a result of merging translation units. \defaultvalue \l{cpp::combineCxxSources}{cpp.combineCxxSources} */ /*! \qmlproperty bool Qt.core::enableBigResources Whether the Qt resource compiler is run in a two-pass fashion that supports the creation of big resources. \defaultvalue \c{false} */ /*! \qmlproperty stringList Qt.core::config Corresponds to the default value of qmake's \c CONFIG variable. \defaultvalue \c [] */ /*! \qmlproperty stringList Qt.core::disabledFeatures Corresponds to cmake's \c QT_DISABLED_PUBLIC_FEATURES variable. \readonly */ /*! \qmlproperty path Qt.core::docPath The path in which the Qt documentation is located. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::enabledFeatures Corresponds to cmake's \c QT_ENABLED_PUBLIC_FEATURES variable. \readonly */ /*! \qmlproperty bool Qt.core::enableKeywords Set this property to \c false if you do not want Qt to define the symbols \c {signals}, \c {slots}, and \c {emit}. This can be necessary if your project interacts with code that also defines such symbols. \defaultvalue \c true */ /*! \qmlproperty bool Qt.core::frameworkBuild Whether Qt was built as a framework. This is only relevant for Darwin systems. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::generateMetaTypesFile If this property is enabled, a JSON file tagged as \c "qt.core.metatypes" will potentially be generated from metatype information collected by \c moc. \nodefaultvalue \since Qbs 1.16 */ /*! \qmlproperty string Qt.core::generatedHeadersDir The directory where tools that generate headers (such as \c moc or \c uic) put resulting files. Normally, you don't need to change this property. The one use-case is when there are several files with the same file name in the Product. The file name produced by \c moc is based only on the source file's base file name (without the directory path) which leads to a conflict in the mentioned case. You can resolve the conflict by setting this property to a non-default value for one of the files. For example: \code QtApplication { files: ["my_cool_header.h", "main.cpp"] Group { name: "legacy" files: "legacy/my_cool_header.h" Qt.core.generatedHeadersDir: "qt.legacy.headers" } } \endcode \defaultvalue \c product.buildDirectory + "/qt.headers" */ /*! \qmlproperty bool Qt.core::metaTypesInstallDir The directory to install the metatypes file into. If this property is empty or undefined, the metatypes file will not be installed. If the \l{Qt.core::generateMetaTypesFile}{generateMetaTypesFile} property is not \c true, then this property has no effect. \nodefaultvalue \since Qbs 1.16 */ /*! \qmlproperty path Qt.core::incPath The base path of the Qt headers. \nodefaultvalue */ /*! \qmlproperty string Qt.core::libInfix The library infix can be set at Qt build time to change the name of Qt's libraries. For example, if the infix is \c "Test", on Unix systems, the Qt Core library will be in a file called \c{libQt5CoreTest.so} instead of the default \c{libQt5Core.so}. \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::libPath The path in which the Qt libraries are located. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::lreleaseMultiplexMode If this property is \c true, \c lrelease will merge all \c .ts files into one \c .qm file. Otherwise, one \c .qm file will be created for each \c .ts file. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.core::lreleaseName The base name of the \c lrelease tool. Set this if your system uses a name such as \c "lrelease-qt4". \defaultvalue \c{"lrelease"} */ /*! \qmlproperty path Qt.core::mkspecPath The path in which the Qt \c mkspecs are located. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::mocFlags A list of additional flags to \c moc. You will rarely need to set this property. \defaultvalue \c [] */ /*! \qmlproperty string Qt.core::mocName The base name of the \c moc tool. Set this if your system uses a name such as \c "moc-qt4". \defaultvalue \c{"moc"} */ /*! \qmlproperty string Qt.core::namespace The Qt namespace that can be set at build time via the \c configure script. By default, Qt is not built in a namespace. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::pluginMetaData A list of additional plugin metadata. The elements of the list are key-value pairs separated by the \c = character. A possible use case is to set the plugin URI when building a static QML plugin: \badcode Qt.core.pluginMetaData: ["uri=thePlugin"] \endcode \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::pluginPath The path in which the Qt plugins are located. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::qdocEnvironment The environment for calls to \c qdoc. Typically, you will need to set some variables here when running \c qdoc to build your project documentation. \nodefaultvalue */ /*! \qmlproperty string Qt.core::qdocName The base name of the \c qdoc tool. \defaultvalue \c{"qdoc3"} for Qt 4, \c{"qdoc"} otherwise. */ /*! \qmlproperty string Qt.core::qdocOutputDir The directory name where the \c qdoc tool writes its output. \defaultvalue \c{product.buildDirectory + "/qdoc_html"} */ /*! \qmlproperty string Qt.core::qmBaseName The base name of the \c .qm file to be built from the \c .ts files in the product. This property is ignored if \l{Qt.core::}{lreleaseMultiplexMode} is \c false. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty string Qt.core::qmDir The directory name where to put the \c .qm file to be built. \defaultvalue \l{Product::destinationDirectory}{product.destinationDirectory} */ /*! \qmlproperty string Qt.core::qtBuildVariant Specifies the type of Qt libraries to build against: \c "debug" or \c "release". \note On some systems, it is not possible to link code built in debug mode against libraries built in release mode and vice versa. \defaultvalue The build variant of the code linking against Qt. If Qt does not offer that build variant, the build variant offered by Qt is chosen instead. */ /*! \qmlproperty stringList Qt.core::qtConfig Corresponds to the default value of qmake's \c QT_CONFIG variable. \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::resourceSourceBase For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines which part of their path will end up in the generated \c .qrc file. If this property is set to \c undefined, only the file name is used. \nodefaultvalue */ /*! \qmlproperty string Qt.core::resourcePrefix For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines the prefix under which they will be available in the generated \c .qrc file. \defaultvalue \c{"/"} */ /*! \qmlproperty string Qt.core::resourceFileBaseName For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines the base name of the generated \c .qrc file. If this property needs to be changed, it must be set in the corresponding \l{Product}{product} rather than in a \l{Group}. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty bool Qt.core::staticBuild Whether Qt was built statically. \nodefaultvalue */ /*! \qmlproperty path Qt.core::translationsPath This property provides the absolute path to the directory where the Qt translation files (.qm) are installed. \nodefaultvalue \since 2.5 */ /*! \qmlproperty string Qt.core::version The Qt version. Consists of three numbers separated by dots. For example "5.9.1". \nodefaultvalue */ /*! \qmlproperty int Qt.core::versionMajor The Qt major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int Qt.core::versionMinor The Qt minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list Qt.core::versionParts The Qt version as a list. For example, Qt version 5.9.1 would correspond to a value of \c[5, 9, 1]. \defaultvalue \c [] */ /*! \qmlproperty int Qt.core::versionPatch The Qt patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty bool Qt.core::useRPaths Whether to add \l{Qt.core::libPath}{Qt.core.libPath} to \l{cpp::rpaths}{cpp.rpaths}. \defaultvalue \c true on Linux, \c false everywhere else. */ qbs-src-3.3.1/doc/reference/modules/qt-plugin_support-module.qdoc0000644000175100017510000000565715232633614024542 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.plugin_support \inqmlmodule QbsModules \since Qbs 1.13.0 \brief Allows to fine-tune which Qt plugins get pulled in. The \c Qt.plugin_support module provides properties that allow users to control which Qt plugins to pull into a product. This is mostly relevant if Qt was built statically, in which case the respective plugins are static libraries that get linked into your application or library. */ /*! \qmlproperty varList Qt.plugin_support::pluginsByType Set this property if you want to override the set of plugins for a certain plugin type. For instance, to disable all image plugins except the JPEG one: \code Qt.plugin_support.pluginsByType: ({imageformats: "qjpeg"}) \endcode For plugin types that are not specifically overridden like this, the value in defaultPluginsByType is used. \nodefaultvalue */ /*! \qmlproperty var Qt.plugin_support::allPluginsByType Provides the complete set of plugins in a statically built Qt. The value is a map. The keys are the plugin types, and the values are lists of plugin names. \readonly */ /*! \qmlproperty var Qt.plugin_support::defaultPluginsByType Provides the set of plugins that your application or library will link to if you do not set pluginsByType. The value is a map. The keys are the plugin types, and the values are lists of plugin names. The value depends on the Qt modules your product pulls in. \readonly */ /*! \qmlproperty bool Qt.plugin_support::linkPlugins Controls whether plugins of a statically built Qt should be linked into the product. \defaultvalue \c true if the product is an application or shared library, \c false otherwise. */ qbs-src-3.3.1/doc/reference/modules/exporter-pkgconfig-module.qdoc0000644000175100017510000001573615232633614024642 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Exporter.pkgconfig \inqmlmodule QbsModules \since Qbs 1.12 \brief Provides support for generating pkg-config files. The \c Exporter.pkgconfig module contains the properties and rules to create a \l{https://www.freedesktop.org/wiki/Software/pkg-config}{pkg-config} metadata (\c{.pc}) file for a \l Product. By default, \QBS will attempt to derive some of the \c {.pc} file's contents from the product's \l Export item. This behavior can be suppressed by setting the \l autoDetect property to \c false. \section2 Relevant File Tags \target filetags-exporter-pkgconfig \table \header \li Tag \li Since \li Description \row \li \c{"Exporter.pkgconfig.pc"} \li 1.12.0 \li This tag is attached to the generated \c{.pc} file. \endtable */ /*! \qmlproperty bool Exporter.pkgconfig::autoDetect If this property is enabled, then \QBS will try to derive various \c {.pc} file entries from the contents of the product's \l Export item, including the dependencies declared therein. Values for these fields can still be explicitly provided via the respective properties, in which case they will be concatenated with the auto-detected ones. If an exported dependency is known to correspond to a pkg-config module (either by pulling in the \c{Exporter.pkgconfig} module or by appearing in the \l requiresEntry property), it will end up in the \c Requires field of the \c{.pc} file, otherwise its exported \l cpp properties will be collected for use in the \c Cflags and \c Libs fields. The \l excludedDependencies property can be used to ignore specific products altogether. \defaultvalue \c true */ /*! \qmlproperty stringList Exporter.pkgconfig::cflagsEntry The value of the \c Cflags field in the \c {.pc} file. If \l autoDetect is enabled, then this value will be appended to the flags derived from the product's \l Export item and the dependencies declared therein. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::conflictsEntry The value of the \c Conflicts field in the \c {.pc} file. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::excludedDependencies If \l autoDetect is enabled, the entries of this property will be matched against the product's exported dependencies. In case such a dependency's name is present in the array, \QBS will not traverse that dependency to collect entries for the \c Cflags, \c Libs, \c Requires and \c {Requires.private} fields. This list must not contain any values that are present in \l requiresEntry. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::fileName The file name of the generated pkg-config metadata file. \defaultvalue \c {product.targetName + ".pc"} */ /*! \qmlproperty stringList Exporter.pkgconfig::libsEntry The value of the \c Libs field in the \c {.pc} file. If \l autoDetect is enabled, then this value will be appended to the flags derived from the product's \l Export item and the dependencies declared therein. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::libsPrivateEntry The value of the \c Libs.Private field in the \c {.pc} file. \defaultvalue \c {[]} */ /*! \qmlproperty string Exporter.pkgconfig::nameEntry The value of the \c Name field in the \c {.pc} file. \defaultvalue \c {product.name} */ /*! \qmlproperty stringList Exporter.pkgconfig::requiresEntry The value of the \c Requires field in the \c {.pc} file. If \l autoDetect is enabled, then those of the product's exported dependencies that pull in the \c {Exporter.pkgconfig} module will also end up in the \c Requires field, provided they are not listed in \l excludedDependencies. If an exported dependency matches an entry of this array, \QBS will not traverse that dependency to gather \l cpp properties for use in the \l cflagsEntry and \l libsEntry values, as pkg-config takes care of that itself. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::requiresPrivateEntry The value of the \c Requires.private field in the \c {.pc} file. If \l autoDetect is enabled, then those of the product's non-exported dependencies that pull in the \c {Exporter.pkgconfig} module will also end up in the \c Requires.private field, provided they are not listed in \l excludedDependencies. \defaultvalue \c {[]} */ /*! \qmlproperty var Exporter.pkgconfig::transformFunction A function with the signature \c {function(product, moduleName, propertyName, value)}. This can be useful to "fine-tune" property values if \l autoDetect is enabled, in case they need amending for the purpose of pkg-config. The \c product parameter represents the exporting product, the remaining parameters describe the module property. The modified value of the module property shall be returned. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::urlEntry The value of the \c URL field in the \c {.pc} file. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::versionEntry The value of the \c Version field in the \c {.pc} file. \defaultvalue \c {product.version} */ /*! \qmlproperty string Exporter.pkgconfig::customVariables Use this property to add arbitrary variable assignments into the \c .pc file. The property is a map that will produce one assignment per entry. The keys and values of the map represent the left-hand sides and right-hand sides of these assignments, respectively. The values are strings that will be written into the file verbatim. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/modules/android-sdk-module.qdoc0000644000175100017510000002024415232633614023212 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Android.sdk \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building Android packages. The Android.sdk module contains the properties and rules to create Android application packages from Java sources, resources, and so on. It is usually pulled in indirectly by declaring an \l Application product. \section2 Relevant File Tags \target filetags-android-sdk \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"android.aidl"} \li \c{*.aidl} \li 1.4.0 \li Attached to Android AIDL files. One Java source file will be generated for each such file. \row \li \c{"android.assets"} \li - \li 1.4.0 \li Attached to Android assets, which are typically located in an \c{assets/} subdirectory. These files are tagged automatically if the \l automaticSources property is enabled. \row \li \c{"android.manifest"} \li \c{AndroidManifest.xml} \li 1.4.0 \li Attached to the Android manifest. There must be one such file for every Android app. \row \li \c{"android.resources"} \li - \li 1.4.0 \li Attached to Android resources, which are typically located in a \c{res/} subdirectory. These files are tagged automatically if the \l automaticSources property is enabled. \endtable */ /*! \qmlproperty string Android.sdk::buildToolsVersion The version of the build tools such as \c aapt and \c dx. \defaultvalue Highest build tools version version available in the SDK. */ /*! \qmlproperty string Android.sdk::ndkDir The NDK base directory, if an NDK is present. \defaultvalue Determined automatically based on standard search paths. */ /*! \qmlproperty string Android.sdk::platform The versioned platform name (for example, \c "android-21"). \defaultvalue Highest build tools version version available in the SDK. */ /*! \qmlproperty string Android.sdk::sdkDir The SDK base directory. \defaultvalue Determined automatically based on standard search paths. */ /*! \qmlproperty bool Android.sdk::embedJar \since Qbs 1.10 If \c true, then if the dependency is a JAR file, its classes and the classes of its dependencies (if \c{embedJar} is also true for them) will be recursively processed by \c{dex} and included in the final APK. \defaultvalue \c{true} */ /*! \qmlproperty path Android.sdk::assetsDir The base directory for Android assets in the respective product. \note Android requires that the file name of this directory is always \c "assets". \defaultvalue \c "src/main/assets" in the product source directory */ /*! \qmlproperty bool Android.sdk::automaticSources If \c true, Java sources as well as Android resources, assets, and the manifest file will be automatically included in the respective product via wildcards. Set this property to \c false if you want to specify these files manually. \defaultvalue \c true */ /*! \qmlproperty string Android.sdk::manifestFile The file path to the Android manifest file. This property is only relevant if \l automaticSources is enabled. \note Android requires that the file name is always "AndroidManifest.xml". \defaultvalue \c "src/main/AndroidManifest.xml" in the product source directory */ /*! \qmlproperty string Android.sdk::packageName The package name of the respective product. The \c package attribute in the manifest file will be set to this value automatically. \defaultvalue \c name */ /*! \qmlproperty string Android.sdk::versionCode The Android Manifest version code of the respective product. The \c android:versionCode attribute in the manifest file will be set to this value if not undefined. In the following example we provide an architecture-specific value for \c android:versionCode: \code // ... property int _version: 1 property int _patchVersion: 0 Android.sdk.versionCode: { switch (Android.ndk.abi) { case "armeabi-v7a": return 132000000 | _version * 10 + _patchVersion; case "arm64-v8a": return 164000000 | _version * 10 + _patchVersion; case "x86": return 232000000 | _version * 10 + _patchVersion; case "x86_64": return 264000000 | _version * 10 + _patchVersion; } throw "Unknown architecture"; } \endcode \defaultvalue \c undefined */ /*! \qmlproperty string Android.sdk::versionName The Android Manifest version name of the respective product. The \c android:versionName attribute in the manifest file will be set to this value if not undefined. \defaultvalue \c undefined */ /*! \qmlproperty path Android.sdk::resourcesDir The base directory for Android resources in the respective product. \note Android requires that the file name of this directory is always \c "res". \defaultvalue \c "src/main/res" in the product source directory */ /*! \qmlproperty path Android.sdk::sourcesDir The base directory for Java sources. This property is only relevant if \l automaticSources is enabled. \defaultvalue \c "src/main/java" in the product source directory */ /*! \qmlproperty string Android.sdk::apkBaseName The base name of the APK file to to be built, that is, the file name without the ".apk" extension. \defaultvalue \l packageName */ /*! \qmlproperty stringList Android.sdk::aidlSearchPaths Search paths for import statements to pass to the \c aidl tool via the \c{-I} option. */ /*! \qmlproperty string Android.sdk::aaptName \since Qbs 1.17 Name of the aapt binary. Allowed options: "aapt" and "aapt2". \defaultvalue \c "aapt2" */ /*! \qmlproperty string Android.sdk::packageType \since Qbs 1.17 Type of the package. Allowed options: "apk" and "aab". Type "apk" generates a runnable package whereas "aab" generates a package for Google Play. \defaultvalue \c "apk" */ /*! \qmlproperty stringList Android.sdk::extraResourcePackages \since Qbs 2.5 List of additional Java package names to compile resources for. \defaultvalue \c undefined */ /*! \qmlproperty string Android.sdk::dexCompilerName \since Qbs 1.20 Name of the dex compiler binary. Allowed options: "dx" and "d8". \defaultvalue \c "d8" */ /*! \qmlproperty bool Android.sdk::d8Desugaring \since Qbs 2.5 Whether desugaring is enabled for "d8" dex compiler. \defaultvalue \c false */ /*! \qmlproperty string Android.sdk::minimumVersion \since Qbs 1.17 Minimum API Level required for the application to run. \defaultvalue \c "21" */ /*! \qmlproperty string Android.sdk::targetVersion \since Qbs 1.17 API Level that the application targets. \defaultvalue \c platformVersion */ qbs-src-3.3.1/doc/reference/modules/freedesktop-module.qdoc0000644000175100017510000001426615232633614023335 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Alberto Mardegan ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype freedesktop \inqmlmodule QbsModules \since Qbs 1.16 \brief Provides support for some freedesktop.org specifications. The \c freedesktop module contains properties and rules for building and working with applications compliant to freedesktop.org specifications on UNIX platforms. The areas in which this module can be of use include: \list \li Creation or post-processing of \l{https://specifications.freedesktop.org/desktop-entry-spec/latest/}{\c{.desktop} files} \li Installation of \l{https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html}{AppStream} metadata \li Defining the location for \l{https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout} {application icons} \endlist This module is available on all platforms but is currently only useful on UNIX platforms. \section2 Example usage \target example-freedesktop \code Application { ... Depends { name: "freedesktop" } Group { files: [ ... // Declare the desktop and appstream files "data/my-app.desktop", "data/my-app.metainfo.xml", ] } // Add/change some fields in the desktop file freedesktop.desktopKeys: ({ 'Exec': FileInfo.joinPaths(qbs.installPrefix, product.installDir, product.targetName) + ' --argument', 'X-Application-Version': product.version, }) // Define the source directory for application icons freedesktop.hicolorRoot: project.sourceDirectory + "/icons/" // Declare the application icons Group { prefix: project.sourceDirectory + "/icons/" files: [ "32x32/apps/my-application.png", "32x32@2/apps/my-application.png", "32x32/mimetypes/application-format.png", ... "scalable/apps/my-application.svg", ] fileTags: "freedesktop.appIcon" } } \endcode \section2 Relevant File Tags \target filetags-freedesktop \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"freedesktop.desktopfile_source"} \li \c{*.desktop} \li 1.16 \li A source file with this tag is a \c{.desktop} file or fragment that will be merged into the application's final \c{.desktop} file. \row \li \c{"freedesktop.desktopfile"} \li - \li 1.16 \li Attached to the output artifacts of the rule that produces the merged \c{.desktop} file. \row \li \c{"freedesktop.appstream"} \li \c{*.metainfo.xml}, \c{*.appdata.xml} \li 1.16 \li Source files with this tag are AppStream metadata files which will be installed under \l{qbs::}{installPrefix}\c{/share/metainfo} \row \li \c{"freedesktop.appIcon"} \li - \li 1.16 \li Source files with this tag are application icons compliant with the \l{https://specifications.freedesktop.org/icon-theme-spec/}{freedesktop.org Icon Theme Specification}. These icons will be installed under \l{qbs::}{installPrefix}\c{/share/icons/hicolor} in their respective resolution-based directories (e.g., \c{48x48/apps/}, \c{256x256/apps/}), ensuring compatibility with desktop environments following this specification. \note After Qbs version 2.5, the \c{hicolorRoot} property must be set to define the source directory for these icons. Without setting this property, icons will not be installed. \endtable */ /*! \qmlproperty string freedesktop::appName The display name of the application which will be stored in the \c{.desktop} file. \defaultvalue \l{Product::name}{product.name} */ /*! \qmlproperty var freedesktop::desktopKeys A dictionary of key-value pairs to add to the application's \c{.desktop} file. The contents of this property will be aggregated with the values from any \c{.desktop} file. If this property and any \c{.desktop} files contain the same key, this property will take precedence. \nodefaultvalue */ /*! \qmlproperty string freedesktop::hicolorRoot Defines the source directory for application icons, which are installed according to the \l{https://specifications.freedesktop.org/icon-theme-spec/}{freedesktop.org Icon Theme Specification}. It is used with the \c{freedesktop.appIcon} tag to install icons into the \c{share/icons/hicolor} directory structure (e.g., \c{48x48/apps/}, \c{256x256/apps/}). If \c{hicolorRoot} is not set, icons will not be installed. Set this property to the path containing your icon files. \nodefaultvalue \since 2.5 */ qbs-src-3.3.1/doc/reference/modules/qt-declarative-module.qdoc0000644000175100017510000000370115232633614023717 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt.declarative \inqmlmodule QbsModules \brief Provides Qt Quick 1 support. The Qt.declarative module provides support for Qt Quick 1. \sa Qt.quick, Qt.qml */ /*! \qmlproperty bool Qt.declarative::qmlDebugging Whether QML debugging support is compiled into your binaries. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.declarative::qmlImportsPath The absolute path to the directory where Qt's QML imports are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.declarative::qmlPath The absolute path to the directory where Qt's QML files are installed. This property is left undefined for Qt 4. \defaultvalue Determined by \l{setup-qt}. */ qbs-src-3.3.1/doc/reference/modules/nodejs-module.qdoc0000644000175100017510000000324115232633614022273 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype nodejs \inqmlmodule QbsModules \since Qbs 1.3 \brief Provides Node.js support. The \c nodejs module contains support for running \l{Node.js} applications from \QBS. */ /*! \qmlproperty path Node.js::applicationFile The input JavaScript file whose corresponding output will be executed when running the Node.js application. If this property is \c{undefined}, the product will not be runnable. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/modules/innosetup-module.qdoc0000644000175100017510000001144415232633614023041 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype innosetup \inqmlmodule QbsModules \since Qbs 1.7 \brief Provides Inno Setup support. The \c innosetup module contains properties and rules for building EXE setup packages with \l{Inno Setup}. Inno Setup 5 and above are supported. \note A typical Inno Setup Script includes an \c OutputBaseFilename command to set the filename of the generated installer executable. However, \QBS overrides any \c OutputBaseFilename commands found in the script by passing the \c /F option to the ISCC compiler, and therefore, you must use the \l{Product::targetName}{Product.targetName} property to set the filename. \QBS also overrides any \c Output commands by passing the \c /O option to the ISCC compiler. \section2 Relevant File Tags \target filetags-innosetup \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"innosetup.iss"} \li \c{"*.iss"} \li 1.7 \li Source files with this tag identify Inno Setup Script files, which serve as inputs to a rule invoking the Inno Setup Script Compiler. \row \li \c{"innosetup.exe"} \li n/a \li 1.7 \li The rule that creates Inno Setup executable files attaches this tag (as well as the \l{filetags-cpp}{"application"} tag) to its output artifact. \endtable */ /*! \qmlproperty stringList innosetup::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode innosetup.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty pathList innosetup::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty bool innosetup::verboseOutput Whether to display verbose output from the Inno Setup compiler. \defaultvalue \c{false} */ /*! \qmlproperty stringList innosetup::compilerFlags A list of additional flags for the Inno Setup compiler. \nodefaultvalue */ /*! \qmlproperty string innosetup::version The Inno Setup version. Consists of three numbers separated by dots, for instance \c {"5.5.9"}. \nodefaultvalue */ /*! \qmlproperty int innosetup::versionMajor The Inno Setup major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int innosetup::versionMinor The Inno Setup minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list innosetup::versionParts The Inno Setup version as a list. For instance, Inno Setup version 5.5.9 would correspond to a value of \c[5, 5, 9]. \defaultvalue \c [] */ /*! \qmlproperty int innosetup::versionPatch The Inno Setup patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty path innosetup::toolchainInstallPath The Inno Setup installation directory. Determined by searching the registry for the latest version. This property should not normally need to be changed. \defaultvalue Determined automatically. */ /*! \qmlproperty string innosetup::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"ISCC.exe"} */ /*! \qmlproperty string innosetup::compilerPath The full path of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{compilerName} */ qbs-src-3.3.1/doc/reference/commands.qdoc0000644000175100017510000002315015232633614017660 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ // TODO: "\c" markup is used for all properties in table due to QTBUG-35505. /*! \page commands.html \title Command and JavaScriptCommand \brief Types of commands to be used in rules A \e command is what \QBS executes at build time. It is represented in the language by an object of type \c Command, which runs a process, or \c JavaScriptCommand, which executes arbitrary JavaScript code. A command is always created in the prepare script of a \c Rule. \section1 Command A \c Command represents a process that will be invoked at build time. Its constructor arguments are the binary to run and a list of command-line arguments. For instance: \code var insaneCommand = new Command("rm", ["-r", "/"]); \endcode The \l{Rule} item documentation shows a \c Command in context. \section1 JavaScriptCommand A \c JavaScriptCommand represents a chunk of JavaScript code that is run at build time. For instance: \code var cmd = new JavaScriptCommand(); cmd.apology = "Sorry."; cmd.sourceCode = function() { console.info("I'm a rather pointless command."); console.info(apology); }; \endcode Within the source code, the special identifiers \c project and \c product (giving access to project and product properties, respectively) as well as \c inputs and \c outputs are available. As the example shows, arbitrary properties can be set on the command object and then used within the source code. This technique is typically used to forward values from the prepare script to the command. The \l{Rule} item documentation shows a \c JavaScriptCommand in context. \section1 Properties \section2 Common Properties The following properties are available in both \c Command and \c JavaScriptCommand. \table \header \li Property \li Type \li Default \li Description \row \li \c description \li string \li empty \li A message that is displayed when the command is executed. \row \li \c extendedDescription \li string \li empty \li A detailed description that is displayed when the command is executed. \row \li \c highlight \li string \li empty \li A tag that can be used to influence how the \c description is displayed. In principle, the values are arbitrary. The \QBS command-line tool understands the following values and maps them to different colors if the output device is a terminal: \list \li "compiler" indicates that the command processes source code \li "linker" indicates that the command links objects \li "codegen" indicates that the command generates source code \li "filegen" indicates that the command creates arbitrary files \endlist All other values are mapped to the default color. \row \li \c jobPool \li string \li empty \li Determines which job pool the command will use. An empty string, which is the default, stands for the global job pool. See \l{JobLimit}{here} and \l{job-pool-howto}{here} for more information on job pools. \row \li \c silent \li bool \li false \li A flag that controls whether the \c description is printed. Set it to \c true for commands that users need not know about. \note If this property is \c false, then \c description must not be empty. \row \li \c timeout \li int \li -1 \li Time limit for the command execution in seconds. If the command does not finish within the timeout, it is cancelled. In case of a \c Command, the process is requested to terminate. If it does not terminate within three seconds, it is killed. A value below or equal to 0 means no timeout. \br This property was introduced in Qbs 1.15. \endtable \section2 Command Properties \table \header \li Property \li Type \li Default \li Description \row \li \c arguments \li stringList \li empty \li The list of arguments to invoke the command with. Explicitly setting this property overrides an argument list provided when instantiating the object. \row \li \c environment \li stringList \li empty \li A list of environment variables that are added to the common build environment. They are provided as a list of strings in the form "varName=value". \row \li \c maxExitCode \li int \li 0 \li The maximum exit code from the process to interpret as success. Setting this should rarely be necessary, as all well-behaved applications use values other than zero to indicate failure. \row \li \c program \li string \li undefined \li The binary to invoke. Explicitly setting this property overrides a path provided when instantiating the object. \row \li \c relevantEnvironmentVariables \li stringList \li undefined \li Names of environment variables that the invoked binary considers. If one of these variables changes in the build environment, the command will be re-run even if the input files are still up to date. \row \li \c responseFileThreshold \li int \li platform-dependent \li If this value is greater than zero and less than the length of the full command line, and if \c responseFileUsagePrefix is not empty, the contents of the command line are moved to a temporary file, whose path becomes the entire contents of the argument list. The program is then supposed to read the full argument list from that file. This mechanism is mainly useful to work around Windows limitations regarding the maximum length of the command line and will only work with programs that explicitly support it. \row \li \c responseFileArgumentIndex \li int \li 0 \li Index of the first argument to include in the response file. For example this may be used in conjunction with a compiler wrapper where the first argument (the path to the compiler) must be included on the raw command line. \row \li \c responseFileUsagePrefix \li string \li empty \li The prefix that informs \c program that the rest of the argument is a path to a file containing the actual command line. \row \li \c stderrFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard error output and returns a string that is presented to the user as the command's standard error output. If it is not set, the output is shown unfiltered. \row \li \c stdoutFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard output and returns a string that is presented to the user as the command's standard output. If it is not set, the output is shown unfiltered. \row \li \c workingDirectory \li string \li empty \li The program's working directory. \row \li \c stdoutFilePath \li string \li undefined \li Redirects the filtered standard output content to \c stdoutFilePath. If \c stdoutFilePath is undefined, the filtered standard output is forwarded to \QBS, possibly to be printed to the console. \row \li \c stderrFilePath \li string \li undefined \li Redirects the filtered standard error output content to \c stderrFilePath. If \c stderrFilePath is undefined, the filtered standard error output is forwarded to \QBS, possibly to be printed to the console. \endtable \section2 JavaScriptCommand Properties \table \header \li Property \li Type \li Default \li Description \row \li \c sourceCode \li function \li undefined \li The JavaScript function to execute. \endtable */ qbs-src-3.3.1/doc/reference/cli/0000755000175100017510000000000015232633614015755 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/cli/cli-parameters.qdocinc0000644000175100017510000000721315232633614022232 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [arguments] \section2 \c -- Command-line arguments to be passed to the program to be run. //! [arguments] //! [configuration-name] \section2 \c config:configuration-name Specifies the build configuration to use. \QBS can build a project for one or multiple configurations at once, each having a different set of parameters. The \c config parameter has a special function: with each occurrence a new configuration instance begins and all subsequent parameters until the next \c config are assigned to this instance. Parameter assignments before the first occurrence of \c config are applied to all build configurations. Inside products and modules, the current active build configuration can be retrieved via \l{qbs::configurationName}{qbs.configurationName}. In the following snippet, a profile \c clang is applied to all configurations while \c cpp.optimization is different for \c debug and \c release: \code profile:clang config:debug cpp.optimization:none config:release cpp.optimization:small \endcode The value of \c config determines the name of the build folder and affects the default value of the \l{qbs::buildVariant}{qbs.buildVariant} property. \QBS knows the \c config values \c{"debug"} and \c{"release"}, but in general any name can be chosen. When naming configurations created for special purposes, follow the rules for legal names generally used in programming languages: \list \li The first character must be a letter (a-z), an underscore (_), or a dollar sign ($). \li Subsequent characters may be letters, digits, underscores, or dollar signs. \endlist //! [configuration-name] //! [key] \section2 \c Typically, a \c consists of several levels separated by periods. The first level shows a \e root value, such as \e preferences or \e profiles. The root determines whether the second-level keys are build preferences or profile names. The lower level keys consist of a module name, followed by a property name. //! [key] //! [property] \section2 \c {property:value} Property values set in project files or profiles can be overridden on the command line. The syntax is: \code .: \endcode For more information, see \l{Overriding Property Values from the Command Line}. //! [property] */ qbs-src-3.3.1/doc/reference/cli/builtin/0000755000175100017510000000000015232633614017423 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/cli/builtin/cli-update-timestamps.qdoc0000644000175100017510000000453415232633614024514 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-update-timestamps.html \ingroup cli \title update-timestamps \brief Marks the build as up-to-date. \section1 Synopsis \code qbs update-timestamps [options] [config:configuration-name] ... \endcode \section1 Description Updates the timestamps of all build \l{Artifact}{artifacts}, causing the next builds of the \l{Project}{project} to do nothing until source files are updated again. This command is useful if you know that the current changes to source files are irrelevant to the build. \note Using this command causes a discrepancy between the actual state of source files and the information in the build graph, so be careful. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc more-verbose \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-clean.qdoc0000644000175100017510000000435215232633614022126 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-clean.html \ingroup cli \title clean \brief Removes the files generated during a build. \section1 Synopsis \code qbs clean [options] [config:configuration-name] \endcode \section1 Description Removes build \l{Artifact}{artifacts} for the specified build configuration. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc dry-run \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples Removes the build artifacts in the current directory for the default build configuration: \code qbs clean \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-generate.qdoc0000644000175100017510000000514115232633614022633 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-generate.html \ingroup cli \title generate \brief Invokes a project generator, for example to create project files for another build tool. \section1 Synopsis \code qbs generate [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Invokes a project generator, for example to create project files for another build tool. For more information, see \l{Generators}. \section1 Options \target generate-generator \include cli-options.qdocinc generator \include cli-options.qdocinc build-directory \include cli-options.qdocinc project-file \include cli-options.qdocinc install-root \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Generates a project for Microsoft Visual Studio: \code qbs generate -g visualstudio2015 \endcode Generates a \l{https://clang.llvm.org/docs/JSONCompilationDatabase.html} {Clang compilation database (clangdb)}: \code qbs generate --generator clangdb \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-help.qdoc0000644000175100017510000000346715232633614022002 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-help.html \ingroup cli \title help \brief Shows general or command-specific help. \section1 Synopsis \code qbs help [] \endcode \section1 Description Shows a list of available commands with descriptions. Specify a command name to list the options that the command takes with descriptions. \section1 Options This command takes no options. \section1 Examples Shows an overview of all commands: \code qbs help \endcode Lists the options that the \c build command takes: \code qbs help build \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-list-products.qdoc0000644000175100017510000000361015232633614023654 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-list-products.html \ingroup cli \title list-products \brief Lists all products in the given project. \section1 Synopsis \code qbs list-products [options] [config:configuration-name] \endcode \section1 Description Lists all products that exist in a project. \section1 Options \include cli-options.qdocinc project-file \include cli-options.qdocinc build-directory \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples To list all products for the project in the current directory: \code qbs list-products \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-session.qdoc0000644000175100017510000000360615232633614022530 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-session.html \ingroup cli \title session \brief Starts a session for interacting with an IDE \section1 Synopsis \code qbs session \endcode \section1 Description Starts a session, communicating via standard input and standard output. In this mode, \QBS takes commands from standard input and sends replies to standard output, using a \l{Appendix C: The JSON API}{JSON-based API}. This is the recommended \QBS interface for IDEs. It can be used to retrieve information about a project and interact with it in various ways, such as building it, collecting the list of executables, adding new source files and so on. */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-run.qdoc0000644000175100017510000000631715232633614021653 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-run.html \ingroup cli \title run \brief Runs an executable generated by building a project. \section1 Synopsis \code qbs run [options] [config:configuration-name] [property:value] ... [ -- ] \endcode \section1 Description Runs the specified product's executable with the specified \c . If the project has only one product, the \c --products option may be omitted. The product will be built if it is not up to date, unless the \c --no-build option is specified. For more information, see \l{build}. For more information about running applications, see \l{Running Applications}. \section1 Options \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc install-root \include cli-options.qdocinc jobs \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-build \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-run-env-config \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Arguments \include cli-parameters.qdocinc arguments \section1 Examples Runs the Qt Creator application: \code qbs run --products qtcreator \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-resolve.qdoc0000644000175100017510000000461515232633614022525 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-resolve.html \ingroup cli \title resolve \brief Resolves a project without building it. \section1 Synopsis \code qbs resolve [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Resolves a \l{Project}{project} in one or more configurations. Run this command to change the properties of an existing build. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \include cli-options.qdocinc deprecation-warnings \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Resolves the default configuration of the project in the current directory: \code qbs resolve \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-dump-nodes-tree.qdoc0000644000175100017510000000377315232633614024062 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-dump-nodes-tree.html \ingroup cli \title dump-nodes-tree \brief Dumps the nodes in the build graph to \c stdout. \section1 Synopsis \code qbs dump-nodes-tree [options] [config:configuration-name] \endcode \section1 Description Dumps the nodes in the build graph to \c stdout. This is an internal command that is used for debugging purposes only. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples Dumps the nodes tree into a file called \c nodes-tree.log: \code qbs dump-nodes-tree >nodes-tree.log \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-build.qdoc0000644000175100017510000000771215232633614022146 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-build.html \ingroup cli \title build \brief Builds a project. \section1 Synopsis \code qbs build [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Builds projects in one or more configurations. You can specify \l{Project}{project}, \l{Product}{product}, or \l{List of Modules}{module} properties, as well as a \l{Profile} {profile} separately for each configuration. This is the default command. If the build directory does not exist, it will be created. For more information, see \l{Building Applications}. \section1 Options \target build-all-products \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \target build-force-probe-execution \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc jobs \include cli-options.qdocinc job-limits \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-install \target build-products \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Builds the application specified by the \c .qbs file in the current directory using the default profile: \code qbs \endcode Builds the application using four concurrent build jobs: \code qbs -j 4 \endcode Builds the default configuration of an application using the profile called \c Android: \code qbs build profile:Android \endcode Builds the application using different \l{cpp} module properties for debug and release configurations. For the debug configuration, warnings will cause the build to fail, whereas for the release configuration, the size of the build artifacts will be optimized. Both configurations are built with a profile named \c{"qt"}: \code qbs build profile:qt config:debug modules.cpp.treatWarningsAsErrors:true config:release modules.cpp.optimization:small \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-status.qdoc0000644000175100017510000000363315232633614022370 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-status.html \ingroup cli \title status \brief Shows the status of files in the project directory. \section1 Synopsis \code qbs status [options] [config:configuration-name] \endcode \section1 Description Lists all the files in the project directory and shows whether they are known to \QBS in the respective configuration. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples To list the files in the project directory and view their status: \code qbs status \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-install.qdoc0000644000175100017510000000544215232633614022513 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-install.html \ingroup cli \title install \brief Installs a project. \section1 Synopsis \code qbs install [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Install all files marked as installable to their respective destinations. The project is built first, if necessary, unless the \c --no-build option is given. For more information, see \l{Installing Files}. \section1 Options \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc install-root \include cli-options.qdocinc jobs \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-build \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-shell.qdoc0000644000175100017510000000412715232633614022153 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-shell.html \ingroup cli \title shell \brief Opens a shell with a product's environment. \section1 Synopsis \code qbs shell [options] [config:configuration-name] [property:value] \endcode \section1 Description Opens a shell in the environment that a build with the specified parameters would use. For more information, see \l{Using the Shell}. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc project-file \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Opens a shell with the same environment that \QBS uses when building the project: \code qbs shell \endcode */ qbs-src-3.3.1/doc/reference/cli/builtin/cli-version.qdoc0000644000175100017510000000277715232633614022542 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-version.html \ingroup cli \title show-version \brief Prints the \QBS version. \section1 Synopsis \code qbs show-version \endcode \section1 Description Prints the version of \QBS to stdout. \section1 Options This command takes no options. */ qbs-src-3.3.1/doc/reference/cli/tools/0000755000175100017510000000000015232633614017115 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/cli/tools/cli-setup-toolchains.qdoc0000644000175100017510000000573015232633614024040 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-setup-toolchains.html \ingroup cli \title setup-toolchains \brief Creates \QBS profiles for toolchains, such as GCC or MSVC. \section1 Synopsis \code qbs setup-toolchains [--settings-dir ] [--system] --detect qbs setup-toolchains [--settings-dir ] [--system] [--type ] \endcode \section1 Description The first form tries to auto-detect all known toolchains, looking them up via the PATH variable. The second form creates a profile with the name \c {} for the toolchain located at \c {}. It will attempt to determine the toolchain type automatically based on the file name or the compiler executable. If that fails, you need to provide the compiler type as a value of the \c --type option. For more information, see \l{Configuring Profiles and Preferences}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-tools-system \include cli-options.qdocinc detect-toolchains \include cli-options.qdocinc type \include cli-options.qdocinc help \section1 Examples Looks up toolchains via the PATH variable and creates profiles for them: \code qbs setup-toolchains --detect \endcode Creates a profile called \c mingw for the toolchain located in \c C:\mingw530_32\bin on Windows: \code qbs setup-toolchains C:\mingw530_32\bin\g++.exe mingw \endcode Creates a profile called \c g++-mingw-w64 for the toolchain located in \c /usr/bin/x86_64-w64-mingw32-g++ g++-mingw-w64 on Ubuntu: \code qbs setup-toolchains /usr/bin/x86_64-w64-mingw32-g++ g++-mingw-w64 \endcode */ qbs-src-3.3.1/doc/reference/cli/tools/cli-config.qdoc0000644000175100017510000001064015232633614022000 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-config.html \ingroup cli \title config \brief Manages \QBS settings, such as preferences and profiles. \section1 Synopsis \code qbs config [--settings-dir ] [--user|--system] [--list [ ...]] [--unset ] [--export ] [--import ] qbs config [--settings-dir ] [--user|--system] qbs config [--settings-dir ] [--user|--system] \endcode \section1 Description Manages \QBS settings, such as preferences and profiles. You can list all keys and remove the specified key, as well as import settings from a file or export them to a file. The second form of this command displays the specified \c . The third form sets the specified \c with the specified \c . There are two sets of settings: The system-level settings affect all users, while the user-level settings are specific to the current user. By default, the read operations consider both sources. If the same key is present in both settings, then for list values, the system value is appended to the user value, while for other types of values the user-level one takes precedence. Write operations go to the user-level settings by default. Use the \c {--user} and \c {--system} options to change this behavior. \note It is conceivable that the default system value of the \c {preferences.qbsSearchPaths} setting could pull in unwanted \QBS modules, in particular when doing cross-builds. In such a case, you can set \c {preferences.ignoreSystemSearchPaths} to exclude the search paths coming from the system settings. You'll typically do this for a specific profile: \code $ qbs config profiles.myprofile.preferences.ignoreSystemSearchPaths true \endcode You can use the \l{config-ui} command to open the Qbs Settings tool for managing settings in a hierarchical view. For more information, see \l{Configuring Profiles and Preferences}, \l{Managing Qt Versions}, \l{Modules}, \l {List of Modules}, and \l{Custom Modules and Items}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc list-root \include cli-options.qdocinc unset \include cli-options.qdocinc export \include cli-options.qdocinc import \include cli-options.qdocinc config-user \include cli-options.qdocinc config-system \include cli-options.qdocinc help \section1 Parameters \include cli-parameters.qdocinc key \section1 Examples Lists the existing profiles: \code qbs config --list profiles \endcode Shows the default profile: \code qbs config defaultProfile \endcode \note If no output is shown, the default profile used is the built-in profile \c none, which sets no properties. Sets the profile called \c gcc as the base profile of the Qt profile called \c myqt: \code qbs config profiles.myqt.baseProfile gcc \endcode Adds the location of a custom module to your preferences, to make the module accessible in several projects: \code qbs config preferences.qbsSearchPaths /usr/local/share/custom-qbs-extensions \endcode */ qbs-src-3.3.1/doc/reference/cli/tools/cli-setup-android.qdoc0000644000175100017510000000447115232633614023316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-setup-android.html \ingroup cli \title setup-android \brief Creates \QBS profiles for Android SDK and NDK installations. \section1 Synopsis \code qbs setup-android [--settings-dir ] [--ndk-dir ] [--sdk-dir ] [--qt-dir ] \endcode \section1 Description Creates \QBS profiles for Android SDK and NDK installations. If a Qt path is given, these additional profiles will be suitable for building Qt binaries for the respective architecture, if the Qt installation has support for it. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc ndk-dir \include cli-options.qdocinc sdk-dir \include cli-options.qdocinc qt-dir \include cli-options.qdocinc help \section1 Examples Creates a profile with the name \c oreo that specifies the target platforms' \l{qbs::}{architectures} and operating systems, as well as the toolchains available: \code qbs setup-android oreo \endcode */ qbs-src-3.3.1/doc/reference/cli/tools/cli-setup-qt.qdoc0000644000175100017510000000457615232633614022330 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-setup-qt.html \ingroup cli \title setup-qt \brief Creates \QBS profiles for Qt installations. \section1 Synopsis \code qbs setup-qt [--settings-dir ] [--system] --detect qbs setup-qt [--settings-dir ] [--system] \endcode \section1 Description Creates \QBS profiles for Qt installations. The first form tries to auto-detect all known Qt versions, looking them up via the PATH variable. The second form creates a profile with the name \c {} for the Qt version located at \c {}. For more information, see \l{Managing Qt Versions}. \section1 Options \include cli-options.qdocinc detect-qt-versions \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-tools-system \include cli-options.qdocinc help \section1 Examples Looks up Qt versions in the PATH and creates profiles for them: \code qbs setup-qt --detect \endcode Creates a profile called \c myqt for the Qt version located in \c /usr/bin/qmake: \code qbs setup-qt /usr/bin/qmake myqt \endcode */ qbs-src-3.3.1/doc/reference/cli/tools/cli-config-ui.qdoc0000644000175100017510000000414015232633614022411 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-config-ui.html \ingroup cli \title config-ui \brief Opens a GUI application for managing \QBS settings, such as preferences and profiles. \section1 Synopsis \code qbs config-ui [--settings-dir ] [--system] \endcode \section1 Description Opens the \QBS Settings application for managing \QBS settings, such as preferences and profiles, in a hierarchical view. This makes it easier to manage a large number of settings than using the \l{config} command from the command line. \image qbs-settings-gui.png For more information, see \l{Configuring Profiles and Preferences}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc config-ui-system \include cli-options.qdocinc help \section1 Examples Opens \QBS Settings: \code qbs config-ui \endcode */ qbs-src-3.3.1/doc/reference/cli/tools/cli-create-project.qdoc0000644000175100017510000000457515232633614023454 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page cli-create-project.html \ingroup cli \title create-project \brief Creates a \QBS project from an existing set of source files. \section1 Synopsis \code qbs create-project [--blacklist ] [--whitelist ] [--flat] \endcode \section1 Description Automatically generates \QBS project files from an arbitrary directory structure. You can filter the files to add to the project by blacklisting or whitelisting them. The command creates nested project files, unless you use the \c --flat option. This is a useful starting point when migrating from other build tools, such as qmake or CMake. \note Run this command from the project directory. After generating the initial .qbs files, add the missing configuration variables and functions to them. \section1 Options \include cli-options.qdocinc blacklist \include cli-options.qdocinc whitelist \include cli-options.qdocinc flat \include cli-options.qdocinc help \section1 Examples Creates \c .qbs files in the project directory when run from there: \code qbs create-project \endcode */ qbs-src-3.3.1/doc/reference/cli/cli-options.qdocinc0000644000175100017510000003156315232633614021567 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [all-products] \section2 \c --all-products Processes all \l{Product}{products}, even if their \c builtByDefault property is \c false. //! [all-products] //! [blacklist] \section2 \c {--blacklist } Ignores files whose names match the patterns specified by \c . The list entries can contain wildcards and are separated by commas. By default, no files are ignored. //! [blacklist] //! [build-directory] \section2 \c {--build-directory|-d } Specifies a \c where build artifacts are stored. The default value is the current directory unless \c preferences.defaultBuildDirectory is set. Relative paths will be interpreted relative to the current directory. You can use the following special values as placeholders: \list \li \c @project is expanded to the name of the project file excluding the extension \c .qbs. \li \c @path is expanded to the name of the directory containing the project file. \endlist //! [build-directory] //! [changed-files] \section2 \c {--changed-files [,...]} Assumes that the files specified by \c , and only those files, have changed. //! [changed-files] //! [check-outputs] \section2 \c --check-outputs Forces transformer output \l{Artifact}{artifact} checks. Verifies that the output artifacts declared by \l{Rule}{rules} in the \l{Project}{project} are actually created. //! [check-outputs] //! [check-timestamps] \section2 \c --check-timestamps Forces timestamp checks. Retrieves the timestamps from the file system, instead of using the file timestamps that are stored in the build graph. //! [check-timestamps] //! [clean_install_root] \section2 \c --clean-install-root Removes the installation base directory before installing. //! [clean_install_root] //! [command-echo-mode] \section2 \c {--command-echo-mode } Determines what kind of output to show when executing commands. Possible values of \c are: \list \li \c silent \li \c summary (default value) \li \c command-line \li \c command-line-with-environment \endlist //! [command-echo-mode] //! [detect-qt-versions] \section2 \c --detect Attempts to auto-detect all known Qt versions, looking them up in the PATH environment variable. //! [detect-qt-versions] //! [detect-toolchains] \section2 \c --detect Attempts to auto-detect all known toolchains, looking them up in the PATH environment variable. //! [detect-toolchains] //! [dry-run] \section2 \c --dry-run|-n Performs a dry run. No commands will be executed and no permanent changes to the build graph will be done. //! [dry-run] //! [export] \section2 \c {--export } Exports settings to the specified \c . //! [export] //! [project-file] \section2 \c {[--file|-f ]} Uses \c as the project file. If \c is a directory and it contains a single file with the extension \c .qbs, that file will be used. If this option is not given at all, the behavior is the same as for \c{-f }. //! [project-file] //! [flat] \section2 \c --flat Does not create nested project files, even if there are subdirectories and the top-level directory does not contain any files. //! [flat] //! [force-probe-execution] \section2 \c --force-probe-execution Forces re-execution of all \l{Probe} items' configure scripts, rather than using the cached data. //! [force-probe-execution] //! [generator] \section2 \c {--generator|-g } Uses the specified build system generator. Possible values of \c include: \list \li \c clangdb \li \c visualstudio2015 \li \c iarew8 \endlist The available generators are listed if you run the \c {qbs generate} command without passing a generator to it. //! [generator] //! [help] \section2 \c {--help|-h|-?} Displays help for the command. //! [help] //! [import] \section2 \c {--import } Imports settings from the specified \c . //! [import] //! [install-root] \section2 \c {--install-root } Installs into the specified \c . If the directory does not exist, it will be created. The default value is \c /install-root. Use the special value \c @sysroot to install into the \c sysroot. That is, the value of the \l{qbs::sysroot}{qbs.sysroot} property. //! [install-root] //! [jobs] \section2 \c {--jobs|-j } Uses \c concurrent build jobs, where \c must be an integer greater than zero. The default is the number of logical cores. //! [jobs] //! [job-limits] \section2 \c {--job-limits :[,:...]} Sets pool-specific job limits. See \l{job-pool-howto}{here} for more information on job pools. \section2 \c {--enforce-project-job-limits} Normally, job limits defined in project files via the \l JobLimit item get overridden by those set on the command line. If this option is passed, they get maximum priority instead. Use it if there are product-specific limits that make more sense for that part of the code base than the generic ones you'd like to apply globally. //! [job-limits] //! [keep-going] \section2 \c --keep-going|-k Keeps going when errors occur, if at all possible. //! [keep-going] //! [less-verbose] \section2 \c --less-verbose|-q Becomes more quiet by decreasing the log level by one. This option can be given more than once. Excessive occurrences have no effect. If the option \c --log-level appears anywhere on the command line in addition to this option, its value is taken as the base for the decrease. //! [less-verbose] //! [list-root] \section2 \c {--list [ ...]} Lists keys under the key \c or all keys if the root is not specified. Possible values are: \list \li \c defaultProfile is the default \l{Profile}{profile} to use if a profile is not specified \li \c preferences accepts build preferences as second-level keys \li \c profiles accepts profile names as second-level keys \endlist //! [list-root] //! [config-user] \section2 \c {--user} Causes read operations to display only the user-level settings, while the system-level settings are ignored. Write operations will target the user-level settings, which is also the default. //! [config-user] //! [config-system] \section2 \c {--system} Read and write operations will consider only the system-level settings. //! [config-system] //! [config-ui-system] \section2 \c {--system} Instructs the tool to work on the system-level settings. Otherwise, the user-level settings are presented. //! [config-ui-system] //! [deprecation-warnings] \section2 \c {--deprecation-warnings } Uses the specified deprecation warning mode, which controls what to do when deprecated items or properties are encountered in the project. By default, a warning is emitted if the item or property is scheduled for removal in the next minor version of \QBS. Warnings can also be switched on or off unconditionally, and it can be specified that project resolving should abort if deprecated constructs are present. Possible values of \c are: \list \li \c error \li \c on \li \c before-removal (default value) \li \c off \endlist //! [deprecation-warnings] //! [log-level] \section2 \c {--log-level } Uses the specified log level. Possible values of \c are: \list \li \c error \li \c warning \li \c info (default value) \li \c debug \li \c trace \endlist //! [log-level] //! [log-time] \section2 \c --log-time Logs the time that the operations involved in this command take. This option is implied in log levels \c debug and higher. This option is mutually exclusive with \c --show-progress. //! [log-time] //! [more-verbose] \section2 \c --more-verbose|-v Becomes more verbose by increasing the log level by one. This option can be given more than once. Excessive occurrences have no effect. If the option \c --log-level appears anywhere on the command line in addition to this option, its value is taken as the base for the increase. //! [more-verbose] //! [ndk-dir] \section2 \c {--ndk-dir } Specifies a \c that contains an Android NDK. //! [ndk-dir] //! [no-build] \section2 \c --no-build Does not re-build the project before installing or running it. //! [no-build] //! [no-install] \section2 \c --no-install Does not install any artifacts as part of the build process. //! [no-install] //! [products-specified] \section2 \c {--products|-p [,...]} Takes only the \l{Product}{products} specified by \c and their dependencies into account. //! [products-specified] //! [qt-dir] \section2 \c {--qt-dir } Specifies a \c that contains a Qt version. //! [qt-dir] //! [sdk-dir] \section2 \c {--sdk-dir } Specifies a \c that contains an Android SDK. //! [sdk-dir] //! [settings-dir] \section2 \c {--settings-dir } Reads all settings (such as \l{Profile}{profile} information) from the specified \c . If the directory does not exist, it will be created. The default value is system-specific. For example: \list \li Linux: \c $HOME/.config/QtProject/qbs \li Windows: \c %APPDATA%\QtProject\qbs \li macOS: \c $HOME/Library/Preferences/qbs \endlist //! [settings-dir] //! [setup-run-env-config] \target --setup-run-env-config \section2 \c --setup-run-env-config A comma-separated list of strings. They will show up in the \c config parameter of all \l{Module::}{setupRunEnvironment} scripts. //! [setup-run-env-config] //! [show-progress] \section2 \c --show-progress Shows how command execution is progressing. This option is mutually exclusive with \c --log-time. //! [show-progress] //! [setup-tools-system] \section2 \c {--system} If this option is given, the profile(s) created by this tool will end up in the system-level settings and thus be available to all users. Otherwise, they go into the user-level settings. //! [setup-tools-system] //! [type] \section2 \c {--type } Specifies the type of the toolchain. Needed if \QBS cannot determine the compiler from the name of the executable file located in the specified directory. Possible values include: \list \li \c clang \li \c gcc \li \c mingw \li \c msvc \li \c iar \li \c keil \li \c sdcc \li \c cosmic \li \c dmc \li \c watcom \endlist //! [type] //! [unset] \section2 \c {--unset } Removes the specified \c . //! [unset] //! [wait-lock] \section2 \c --wait-lock Waits indefinitely for other processes to release the build graph lock. This option is typically used by \l{Generators}{generators}, which may re-invoke multiple \QBS processes on the same project simultaneously. //! [wait-lock] //! [whitelist] \section2 \c {--whitelist } Considers only files whose names match the patterns specified by \c . The list entries can contain wildcards and are separated by commas. By default, all files are considered. //! [whitelist] */ qbs-src-3.3.1/doc/reference/cli/cli.qdoc0000644000175100017510000000325115232633614017375 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \group cli \title Command-Line Interface \brief A list of available command-line commands. The \c qbs command-line commands can be invoked as \c{qbs }. This reference summarizes the command-line commands. The authoritative source of up-to-date information is the respective help screen, which you get by calling \c{qbs help }. Some commands are described in context in the \l{Usage} section of the manual. */ qbs-src-3.3.1/doc/reference/reference.qdoc0000644000175100017510000000716415232633614020024 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage howtos.html \page reference.html \nextpage building-qbs.html \title Reference \list \li \l{List of All Items} \list \li \l{List of Language Items} \li \l{List of Convenience Items} \li \l{List of Probes} \endlist \li \l{List of Built-in Services} \li \l{Command-Line Interface} \li \l{List of Modules} \li \l{Command and JavaScriptCommand} \endlist */ /*! \group list-of-builtin-services \title List of Built-in Services \QBS provides the following built-in JavaScript extensions to simplify operations that are expected to be needed often in project files. To gain access to the operations provided by a particular Service - for example, the File service - use the following statement at the top of your \QBS project file: \code import qbs.File \endcode If you instead need to access the service from a JavaScript file, import it using the following statement at the top of your JavaScript file: \code var File = require("qbs.File"); \endcode */ /*! \qmlmodule QbsModules \title List of Modules These are the modules shipped with \QBS. For a list of \QBS modules that provide support for Qt modules, see \l{Qt Modules}. Only the Qt modules that have properties and relevant file tags are described in separate topics. */ /*! \qmlmodule QbsModuleProviders \title List of Module Providers These are the module providers shipped with \QBS. */ /*! \group list-of-items \title List of All Items \QBS provides the following \l{List of Language Items}{built-in}, \l{List of Convenience Items}{convenience}, and \l{List of Probes}{probe} items to define projects. */ /*! \qmlmodule QbsLanguageItems \title List of Language Items \QBS provides the following built-in QML items to define projects. These are the primitives upon which all other \QBS items are built. */ /*! \qmlmodule QbsConvenienceItems \title List of Convenience Items \QBS provides the following QML items for convenience. */ /*! \qmlmodule QbsProbes \title List of Probes These are the probes shipped with \QBS. Probes are used to retrieve information from the system prior to building. Typically, probes call external processes to get the required information. For details, see \l{Probe}{Probe} page. */ qbs-src-3.3.1/doc/reference/jsextensions/0000755000175100017510000000000015232633614017742 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/jsextensions/jsextension-binaryfile.qdoc0000644000175100017510000000712615232633614025313 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 Sergey Belyashov ** Copyright (C) 2017 Denis Shienkov ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-binaryfile.html \ingroup list-of-builtin-services \title BinaryFile Service \brief Provides read and write operations on binary files. The \c BinaryFile service allows you to read from and write into binary files. \section1 Related Declarations \section2 BinaryFile.OpenMode \code enum BinaryFile.OpenMode { ReadOnly, WriteOnly, ReadWrite } \endcode List of modes that a file may be opened in. The OpenMode values can be combined with the bitwise or operator. \section1 Available operations \section2 Constructor \code BinaryFile(filePath: string, openMode: OpenMode = BinaryFile.ReadOnly) \endcode Opens the file at \c filePath in the given mode and returns the object representing the file. \note The mode influences which of the operations listed below can actually be used on the file. \section2 atEof \code atEof(): boolean \endcode Returns \c{true} if no more data can be read from the file, \c{false} otherwise. \section2 close \code close(): void \endcode Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible. \section2 filePath \code filePath(): string \endcode The absolute path of the file represented by this object. \section2 size \code size(): number \endcode Returns the size of the file (in bytes). \section2 resize \code resize(size: number): void \endcode Sets the file \c size (in bytes). If \c size is larger than the file currently is, the new bytes will be set to 0; if \c size is smaller, the file is truncated. \section2 pos \code pos(): number \endcode Returns the position that data is written to or read from. \section2 seek \code seek(pos: number): void \endcode Sets the current position to \c pos. \section2 read \code read(size: number): number[] \endcode Reads at most \c size bytes of data from the file and returns it as an array. \section2 write \code write(data: number[]): void \endcode Writes \c data into the file at the current position. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextensions-general.qdoc0000644000175100017510000001153315232633614024764 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextensions-general.html \ingroup list-of-builtin-services \title General Services \brief Provides various operations. These are operations that do not fit into any of the other categories. They are automatically available in any \QBS project file or JavaScript file. \section1 Available Operations \section2 require \code require(identifier: string): any \endcode Loads an extension and returns an object representing the extension. If \a identifier is a relative or absolute file path, this function will load a JavaScript file and return an object containing the evaluated context of that file. Otherwise, loads a \QBS extension named \a identifier and returns an object that contains the extension's context. This function is only available in JavaScript files and is designed to behave similarly to the CommonJS/RequireJS/Node.js module resolution systems. \code var MyFunctions = require("./myfunctions.js"); MyFunctions.doSomething(); var FileInfo = require("qbs.FileInfo"); var fileName = FileInfo.fileName(filePath); \endcode \section1 Extensions to JavaScript Built-in Objects \section2 Array.containsAll \code Array.containsAll(other: any[]): boolean \endcode Returns \c{true} if the array contains every element in the \c{other} array. Returns \c{false} otherwise. \section2 Array.containsAny \code Array.containsAny(other: any[]): boolean \endcode Returns \c{true} if the array contains some element(s) in the \c{other} array. Returns \c{false} otherwise. \section2 Array.uniqueConcat \code Array.uniqueConcat(other: any[]): any[] \endcode Returns a copy of this array joined with the array \c{other}. Duplicates that would originate from the concatenation are removed. The order of elements is preserved. \section1 Console API \QBS provides a subset of the non-standard Console API available in most ECMAScript runtimes. The output of each of these functions will only be displayed if the logging level is at least the level which the function outputs at. Logging levels from lowest to highest are: 'error', 'warning', 'info', 'debug', and 'trace'. The default is 'info'. \warning The contents of this section are subject to change in order to align with future \l{https://www.w3.org/2011/08/browser-testing-charter.html}{standardization} \l{https://github.com/DeveloperToolsWG/console-object/blob/master/api.md}{processes}. \section2 console.debug \code console.debug(s: string): void \endcode This method is an alias for \c{console.log()}. \section2 console.error \code console.error(s: string): void \endcode Logs an \c{error} level message. Outputs to stderr when the logger output is a terminal. The string will be prefixed with \c{"ERROR: "} and colored red when the logger output is a color-capable terminal. \section2 console.info \code console.info(s: string): void \endcode Logs an \c{info} level message. Outputs to stdout when the logger output is a terminal. \section2 console.log \code console.log(s: string): void \endcode Logs a \c{debug} level message. Outputs to stderr when the logger output is a terminal. \section2 console.warn \code console.warn(s: string): void \endcode Logs a \c{warning} level message. Outputs to stderr when the logger output is a terminal. The string will be prefixed with \c{"WARNING: "} and colored yellow when the logger output is a color-capable terminal. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-process.qdoc0000644000175100017510000001461315232633614024644 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-process.html \ingroup list-of-builtin-services \title Process Service \brief Allows you to start external processes. The \c Process service allows you to start processes, track their output, and so on. \section1 Available Operations \section2 Constructor \code Process() \endcode Allocates and returns a new Process object. \section2 close \code close(): void \endcode Frees the resources associated with the process. It is recommended to always call this function as soon as you are finished with the process. \section2 closeWriteChannel \code closeWriteChannel(): void \endcode Schedules the stdin channel of process to be closed. The channel will close once all data has been written to the process. After calling this function, any attempts to write to the process will do nothing. See \c QProcess::closeWriteChannel() for more details. \section2 errorString \code errorString(): string \endcode Returns a human-readable description of the last error that occurred with the process. This can be useful when \c start() or \c exec() fails, to provide more detailed information about the reason (for example, "No such file or directory"). See \c QIODevice::errorString() for more details. \since Qbs 3.1.0 \section2 exec \code exec(filePath: string, arguments: string[], throwOnError: boolean): number \endcode Executes the program at \c filePath with the given argument list and blocks until the process is finished. If an error occurs (for example, there is no executable file at \c filePath) and \c throwOnError is true, then a JavaScript exception will be thrown. Otherwise (the default), -1 will be returned in case of an error. The normal return code is the exit code of the process. \section2 exitCode \code exitCode(): number \endcode Returns the exit code of the process. This is needed for retrieving the exit code from processes started via \c start(), rather than \c exec(). \section2 getEnv \code getEnv(varName: string): string \endcode Returns the value of the variable \c varName in the process' environment. \section2 kill \code kill(): void \endcode Kills the process, causing it to exit immediately. \section2 readLine \code readLine(): string \endcode Reads and returns one line of text from the process output, without the newline character(s). \section2 atEnd \code atEnd(): boolean \endcode Returns true if there is no more data to be read from the process output, otherwise returns false. \section2 readStdErr \code readStdErr(): string \endcode Reads and returns all data from the process' standard error channel. \section2 readStdOut \code readStdOut(): string \endcode Reads and returns all data from the process' standard output channel. \section2 setCodec \code setCodec(codec) \endcode Sets the text codec to \c codec. The codec is used for reading and writing from and to the process, respectively. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 setEnv \code setEnv(varName: string, varValue: string): string \endcode Sets the value of variable \c varName to \c varValue in the process environment. This only has an effect if called before the process is started. \section2 setWorkingDirectory \code setWorkingDirectory(path: string): void \endcode Sets the directory the process will be started in. This only has an effect if called before the process is started. \section2 start \code start(filePath: string, arguments: string[]): boolean \endcode Starts the program at \c filePath with the given list of arguments. Returns \c{true} if the process could be started and \c{false} otherwise. \note This call returns right after starting the process and should be used only if you need to interact with the process while it is running. Most of the time, you want to use \c exec() instead. \section2 terminate \code terminate(): void \endcode Tries to terminate the process. This is not guaranteed to make the process exit immediately; if you need that, use \c kill(). \section2 waitForFinished \code waitForFinished(timeout: number): boolean \endcode Blocks until the process has finished or \c timeout milliseconds have passed (default is 30000). Returns true if the process has finished and false if the operation has timed out. Calling this function only makes sense for processes started via \c start() (as opposed to \c exec()). \section2 workingDirectory \code workingDirectory(): string \endcode Returns the directory the process will be started in. \section2 write \code write(data: string): void \endcode Writes \c data into the process' input channel. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data, followed by the newline character(s), into the process' input channel. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-propertylist.qdoc0000644000175100017510000001137315232633614025746 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-propertylist.html \ingroup list-of-builtin-services \title PropertyList Service \brief Provides read, write and convert operations on property list files. The \c PropertyList service allows you to read and write property list files in all formats supported by the Core Foundation API: XML, binary, JSON, and OpenStep (read-only). This service is only available on Darwin platforms such as iOS, macOS, tvOS, and watchOS. \section1 Available operations \section2 Constructor \code PropertyList() \endcode Allocates and returns a new PropertyList object. \section2 clear \code clear(): void \endcode Voids the property list by deleting its internal object reference. \section2 isEmpty \code isEmpty(): boolean \endcode Returns true if the property list has no internal object reference set, otherwise false. \section2 format \code format(): string \endcode Returns the data format that the property list data was deserialized from. This property is set after calling \c readFromString or \c readFromFile. Possible return values include: \c "binary1", \c "json", \c "openstep", and \c "xml1". If the property list object is empty or the input format could not be determined, returns \c undefined. \section2 readFromFile \code readFromFile(filePath: string): void \endcode Parses the file and stores the result in the property list. Throws an exception if an I/O error occurs or the input is in an invalid format. \section2 readFromObject \code readFromObject(obj: any): void \endcode Sets the given object as the property list's internal object. \c format() will return \c undefined as this method does not deserialize a storage format. \section2 readFromString \code readFromString(input: string): void \endcode Parses \c input and stores the result in the property list. This is most useful for initializing a property list object from the result of a \c JSON.stringify call. Throws an exception if the input is in an invalid format. \section2 toObject \code toObject(): any \endcode Returns an object representing the property list. \section2 toJSON \code toJSON(style: string = "compact"): string \endcode Returns a string representation of the property list in JSON format. Possible values for \c style include \c "pretty" and \c "compact". The default is compact. \section2 toString \code toString(format: string): string \endcode Returns a string representation of the property list in the specified format. Possible values for \c format include: \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported. Throws an exception if the object cannot be written in the given format. \section2 toXMLString \code toXMLString(): string \endcode Returns a string representation of the property list in XML format. This function is a synonym for \c toString("xml1"). \section2 writeToFile \code writeToFile(filePath: string, format: string): void \endcode Writes the property list to the file in the given format. Possible values for \c format include: \c "binary1", \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported for writing. Throws an exception if an I/O error occurs or the object cannot be written in the given format. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-fileinfo.qdoc0000644000175100017510000001436515232633614024765 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-fileinfo.html \ingroup list-of-builtin-services \title FileInfo Service \brief Provides operations on file paths. The \c FileInfo service offers various operations on file paths, such as turning absolute paths into relative ones, splitting a path into its components, and so on. \section1 Available Operations \section2 baseName \code FileInfo.baseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the first '.' character. \section2 canonicalPath \code FileInfo.canonicalPath(filePath: string): string \endcode Returns a canonicalized \c filePath, i.e. an absolute path without symbolic links or redundant "." or ".." elements. On Windows, drive substitutions are also resolved. It is recommended to use \c{canonicalPath} in only those cases where canonical paths are really necessary. In most cases, \c{cleanPath} should be enough. \section2 cleanPath \code FileInfo.cleanPath(filePath: string): string \endcode Returns \c filePath without redundant separators and with resolved occurrences of \c{.} and \c{..} components. For instance, \c{/usr/local//../bin/} becomes \c{/usr/bin}. \section2 completeBaseName \code FileInfo.completeBaseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the last '.' character. \section2 completeSuffix \code FileInfo.completeSuffix(filePath: string): string \endcode Returns the file suffix of \c filePath from (but not including) the last '.' character. \funsince 1.12 \section2 fileName \code FileInfo.fileName(filePath: string): string \endcode Returns the last component of \c filePath, that is, everything after the last '/' character. \section2 fromNativeSeparators \code FileInfo.fromNativeSeparators(filePath: string): string \endcode On Windows hosts, this function behaves the same as \l fromWindowsSeparators. On other operating systems, it returns the input unmodified. \section2 fromWindowsSeparators \code FileInfo.fromWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '\\' characters replaced by '/'. \section2 isAbsolutePath \code FileInfo.isAbsolutePath(filePath: string, hostOS?: string[]): boolean \endcode Returns true if \c filePath is an absolute path and false if it is a relative one. If \c hostOS is specified, treats \c filePath as a file path of the kind found on that platform. This parameter defaults to the host OS on which \QBS is running and should normally be omitted. \section2 joinPaths \code FileInfo.joinPaths(...paths: string[]): string \endcode Concatenates the given paths using the '/' character. \section2 path \code FileInfo.path(filePath: string, hostOS?: string[]): string \endcode Returns the part of \c filePath that is not the file name, that is, everything up to (but not including) the last '/' character. If \c filePath is just a file name, then '.' is returned. If \c filePath ends with a '/' character, then the file name is assumed to be empty for the purpose of the above definition. If \c hostOS is specified, treats \c filePath as a file path of the kind found on that platform. This parameter defaults to the host OS on which \QBS is running and should normally be omitted. \section2 relativePath \code FileInfo.relativePath(dirPath: string, filePath: string): string \endcode Returns a relative path so that joining \c dirPath and the returned path results in \c filePath. If necessary, '..' components are inserted. The function assumes \c dirPath and \c filePath to be absolute paths and \c dirPath to be a directory. \section2 suffix \code FileInfo.suffix(filePath: string): string \endcode Returns the file suffix of \c filePath from (but not including) the first '.' character. \funsince 1.12 \section2 toNativeSeparators \code FileInfo.toNativeSeparators(filePath: string): string \endcode On Windows hosts, this function behaves the same as \l toWindowsSeparators. On other operating systems, it returns the input unmodified. \section2 toWindowsSeparators \code FileInfo.toWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '/' characters replaced by '\\'. \section2 pathListSeparator \code FileInfo.pathListSeparator(): string \endcode Returns the host operating system separator for a path list that is used in environment variables or other contexts. \funsince 1.22 \section2 pathSeparator \code FileInfo.pathSeparator(): string \endcode Returns the host operating system path separator. \funsince 1.22 \section2 executableSuffix \code FileInfo.executableSuffix(): string \endcode Returns the host operating system executable suffix. \funsince 1.23 */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-temporarydir.qdoc0000644000175100017510000000443715232633614025712 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-temporarydir.html \ingroup list-of-builtin-services \title TemporaryDir Service \brief Creates a unique directory for temporary use. The \c TemporaryDir service creates a unique directory for temporary use. \section1 Available Operations \section2 Constructor \code TemporaryDir() \endcode Allocates and returns a new TemporaryDir object. This method creates the temporary directory. \section2 isValid \code isValid(): boolean \endcode Returns \c true if the temporary directory was created successfully. \section2 path \code path(): string \endcode Returns the path to the temporary directory. Empty if the temporary directory could not be created. \section2 remove \code remove(): boolean \endcode Removes the temporary directory, including all its contents. Returns \c true if removing was successful. It is recommended to always call this function as soon as you are finished with the temporary directory. The directory will not be removed automatically. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-file.qdoc0000644000175100017510000000753615232633614024113 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-file.html \ingroup list-of-builtin-services \title File Service \brief Provides operations on the file system. The \c File service offers limited access to the file system for operations such as copying or removing files. \section1 Available Operations \section2 copy \code File.copy(sourceFilePath: string, targetFilePath: string): boolean \endcode Copies \c sourceFilePath to \c targetFilePath. Any directory components in \c targetFilePath that do not yet exist will be created. If \c sourceFilePath is a directory, a recursive copy will be made. If an error occurs, a JavaScript exception will be thrown. \note \c targetFilePath must be the counterpart of \c sourceFilePath at the new location, \b{not} the new parent directory. This allows the copy to have a different name and is true even if \c sourceFilePath is a directory. \note The file is not copied if the source file timestamp is older than the destination file timestamp. If you want to replace the newer file, you need to remove it first via File.remove(). \section2 exists \code File.exists(filePath: string): boolean \endcode Returns true if and only if there is a file at \c filePath. \section2 directoryEntries \code File.directoryEntries(path: string, filter: File.Filter): string[] \endcode Returns a sorted list of the directory \c{path}'s contents non-recursively, filtered by \c filter. The values of \c filter are equivalent to Qt's \c QDir::Filter. \section2 lastModified \code File.lastModified(filePath: string): number \endcode Returns the time of last modification for the file at \c filePath. The concrete semantics of the returned value are platform-specific. You should only rely on the property that a smaller value indicates an older timestamp. \section2 makePath \code File.makePath(path: string): boolean \endcode Makes the directory at \c path, creating intermediate directories if necessary. Conceptually equivalent to \c{mkdir -p} \section2 move \code File.move(oldPath: string, newPath: string, overwrite: boolean = true): boolean \endcode Renames the file \c oldPath to \c newPath. Returns \c true if successful; otherwise returns \c false. If a file with the name \c newPath already exists, and \c overwrite is \c false, \c move() returns \c false (that is, the file will not be overwritten). \section2 remove \code File.remove(filePath: string): boolean \endcode Removes the file at \c filePath. In case of a directory, it will be removed recursively. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-xml.qdoc0000644000175100017510000001760215232633614023767 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-xml.html \ingroup list-of-builtin-services \title Xml Service \brief Provides a DOM parser and generator to JavaScript. The \c Xml service enables you to access and manipulate XML Document Object Model (DOM) documents. The entire document is a \e {document node}, each XML element is an \e {element node}, the text paragraphs in the XML elements are \e {text nodes}, and each attribute is an \e {attribute node}. XML DOM presents documents as tree structures. The contents of the nodes can be accessed in the tree. They can be modified or deleted, and new nodes can be created. The nodes in the node tree have a hierarchical relationship to each other. The top node is called the \e root. Each node, except the root, has exactly one \e parent node, while it can have any number of \e children. Nodes with the same parent are called \e siblings. \section1 XML DOM Document Node Operations A document node represents an entire document. That is, the root of the DOM tree. \section2 Constructor \badcode Xml.DomDocument() \endcode Creates an XML DOM root node that can contain one element. \section2 createCDATASection \badcode Xml.DomDocument.createCDATASection(value: string) \endcode Creates a CDATA section that is not parsed by a parser. It can be used to include XML fragments without having to escape the delimiters, for example. Tags inside the section are not treated as markup nor are entities expanded. \section2 createElement \badcode Xml.DomDocument.createElement(tagName: string) \endcode Creates an element that can contain other elements, CDATA sections, and text nodes. \section2 createTextNode \badcode Xml.DomDocument.createTextNode(value: string) \endcode Creates a text node that represents textual content in an element or attribute. \section2 documentElement \badcode Xml.DomDocument.documentElement() \endcode Returns the document element. \section2 load \badcode Xml.DomDocument.load(filePath: string): void \endcode Loads the document specified by \c filePath. \section2 save \badcode Xml.DomDocument.save(filePath: string, indentation: int): void \endcode Saves the document at the location specified by \c filePath with the indentation specified by \c int. \section2 setContent \badcode Xml.DomDocument.setContent(content: string) \endcode Returns the content of the document. \section2 toString \badcode Xml.DomDocument.toString(indentation: int) \endcode Converts the document to a string with the indentation specified by \c int. \section1 XML DOM Node Operations A node represents a single node in the document tree. There are several different types of nodes, such as element, attribute, and text nodes. All objects inherit the node properties for handling parents and children, even if they cannot have parents or children. For example, attempting to add children to text nodes results in a DOM error. \section2 Constructor \badcode Xml.DomNode() \endcode Creates an XML DOM node. \section2 appendChild \badcode Xml.DomNode.appendChild(tagName: string) \endcode Appends a new child node to the end of the list of children of a node. \section2 attribute \badcode Xml.DomNode.attribute(name: string, defaultValue: string) \endcode Returns the name and default value of the attribute. \section2 clear \badcode Xml.DomNode.clear() \endcode Clears the contents of the node. \section2 data \badcode Xml.DomNode.data() \endcode Returns the contents of the text node, CDATA section, or character data node. \section2 firstChild \badcode Xml.DomNode.firstChild(tagName: string) \endcode Returns the first child of a node. \section2 hasAttribute \badcode Xml.DomNode.hasAttribute(name: string) boolean \endcode Returns \c true if the node has the specified attribute. \section2 hasAttributes \badcode Xml.DomNode.hasAttributes() boolean \endcode Returns \c true if the node has attributes. \section2 hasChildNodes \badcode Xml.DomNode.hasChildNodes() boolean \endcode Returns \c true if the node has children. \section2 insertAfter \badcode Xml.DomNode.insertAfter(newChild: tagName, refChild: tagName) \endcode Inserts a new child node after the child node specified by \c refChild. \section2 insertBefore \badcode Xml.DomNode.insertBefore(newChild: tagName, refChild: tagName) \endcode Inserts a new child node before the child node specified by \c refChild. \section2 isCDATASection \badcode Xml.DomNode.isCDATASection() boolean \endcode Returns \c true if this is a CDATA section. \section2 isElement \badcode Xml.DomNode.isElement() boolean \endcode Returns \c true if this is an element. \section2 isText \badcode Xml.DomNode.isText() boolean \endcode Returns \c true if this is a text node. \section2 lastChild \badcode Xml.DomNode.lastChild(tagName: string) \endcode Returns the last child of a node. \section2 nextSibling \badcode Xml.DomNode.nextSibling(tagName: string) \endcode Returns the node immediately following a node. \section2 parentNode \badcode Xml.DomNode.parentNode() \endcode Returns the parent of the node. \section2 previousSibling \badcode Xml.DomNode.previousSibling(tagName: string) \endcode Returns the node before a node. \section2 removeChild \badcode Xml.DomNode.removeChild(tagName: string) \endcode Removes the child node. \section2 replaceChild \badcode Xml.DomNode.replaceChild(newChild: tagName, oldChild: tagName) \endcode Replaces a child node with another one. \section2 setAttribute \badcode Xml.DomNode.setAttribute(name: string, value: string) \endcode Sets the name and value of an attribute. \section2 setData \badcode Xml.DomNode.setData(value: string): void \endcode Sets the data of the node to a text node, CDATA section, or character data node. \section2 setTagName \badcode Xml.DomNode.setTagName(tagName: string) \endcode Sets the tag name of the node. \section2 tagName \badcode Xml.DomNode.tagName() \endcode Returns the tag name of the node. \section2 text \badcode Xml.DomNode.text() \endcode Returns the text of the node. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-environment.qdoc0000644000175100017510000000513015232633614025524 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-environment.html \ingroup list-of-builtin-services \title Environment Service \brief Provides operations on the system environment. The \c Environment service offers access to the system environment or process environment. \section1 Available Operations \section2 currentEnv \code Environment.currentEnv(): { [key: string]: string; } \endcode Returns the environment of \QBS in the current context as an object whose properties are the environment variables. \section2 getEnv \code Environment.getEnv(key: string): string \endcode Tries to find a variable with the given name in the current context's environment and returns its value. If no such variable could be found, \c undefined is returned. \section2 putEnv \code Environment.putEnv(key: string, value: string): void \endcode Sets the value of the environment variable with the given name in the build or run environment. This method is only available in the \c Module.setupBuildEnvironment and \c Module.setupRunEnvironment scripts. \section2 unsetEnv \code Environment.unsetEnv(key: string): void \endcode Unsets the environment variable with the given name from the build or run environment. This method is only available in the \c Module.setupBuildEnvironment and \c Module.setupRunEnvironment scripts. */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-host.qdoc0000644000175100017510000001100115232633614024127 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Raphaël Cotty ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-host.html \ingroup list-of-builtin-services \title Host Service \brief Provides host information. The \c Host service offers various information about the host environment, such as operating system names, platform name. \section1 Available Operations \section2 architecture \code Host.architecture(): string \endcode Returns the host operating system architecture. See \l{qbs::architecture}{qbs.architecture} for the target-specific equivalent property. architecture. \funsince 1.22 \section2 os \code Host.os(): string[] \endcode Returns the host operating system names. See the \l{qbs::targetOS}{qbs.targetOS} for the target-specific equivalent property. \funsince 1.22 \section2 platform \code Host.platform(): string \endcode Returns the host operating system platform. See the \l{qbs::targetPlatform}{qbs.targetPlatform} for the target-specific equivalent property. \funsince 1.22 \section2 osVersion \code Host.osVersion(): string \endcode Returns the host operating system version. Currently, only defined for Windows and Apple platforms. Consists of two or three numbers separated by dots. For example, \c "10.9" or \c "6.3.9600". \funsince 1.22 \section2 osBuildVersion \code Host.osBuildVersion(): string \endcode Returns the host operating system build version. Currently, only defined for Windows and Apple platforms. On Windows, this is the 4 or 5 digit Windows build number and is equivalent to \l{qbs::}{versionPatch}. On Apple platforms, this is a standard build number in the Apple versioning scheme. For example, \c "13C64". \funsince 1.22 \section2 osVersionParts \code Host.osVersionParts(): string[] \endcode Returns the host operating system version as a list. For example, Windows 8.1 (version 6.3.9600) would correspond to a value of \c[6, 3, 9600]. \funsince 1.22 \section2 osVersionMajor \code Host.osVersionMajor(): number \endcode Returns the host operating system major version. \funsince 1.22 \section2 osVersionMinor \code Host.osVersionMinor(): number \endcode Returns the host operating system minor version. \funsince 1.22 \section2 osVersionPatch \code Host.osVersionPatch(): number \endcode Returns the host operating system patch level. \funsince 1.22 \section2 nullDevice \code Host.nullDevice(): string[] \endcode Returns the platform-specific file path corresponding to the null device. \funsince 1.22 */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-textfile.qdoc0000644000175100017510000000707515232633614025016 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-textfile.html \ingroup list-of-builtin-services \title TextFile Service \brief Provides read and write operations on text files. The \c TextFile service allows you to read from and write into text files. \section1 Related Declarations \section2 TextFile.OpenMode \code enum TextFile.OpenMode { ReadOnly, WriteOnly, ReadWrite, Append } \endcode List of modes that a file may be opened in. The OpenMode values can be combined with the bitwise or operator. \section1 Available operations \section2 Constructor \code TextFile(filePath: string, openMode: OpenMode = TextFile.ReadOnly) \endcode Opens the file at \c filePath in the given mode and returns the object representing the file. \note The mode influences which of the operations listed below can actually be used on the file. \section2 atEof \code atEof(): boolean \endcode Returns \c{true} if no more data can be read from the file, \c{false} otherwise. \section2 close \code close(): void \endcode Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible. \section2 filePath \code filePath(): string \endcode The absolute path of the file represented by this object. \section2 readAll \code readAll(): string \endcode Reads all data from the file and returns it. \section2 readLine \code readLine(): string \endcode Reads one line of text from the file and returns it. The returned string does not contain the newline characters. \section2 setCodec \code setCodec(codec: string): void \endcode Sets the text codec to \c codec. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 truncate \code truncate(): void \endcode Truncates the file, that is, gives it the size of zero, removing all content. \section2 write \code write(data: string): void \endcode Writes \c data into the file at the current position. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data into the file at the current position and appends the newline character(s). */ qbs-src-3.3.1/doc/reference/jsextensions/jsextension-utilities.qdoc0000644000175100017510000000561615232633614025204 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page jsextension-utilities.html \ingroup list-of-builtin-services \title Utilities Service \brief Provides miscellaneous operations. The \c Utilities service offers miscellaneous operations. \section1 Available Operations \section2 cStringQuote \badcode Utilities.cStringQuote(str: string): string \endcode Takes a string and escapes special characters in a way that the result is suitable for use as a C/C++ string literal. This function is typically used to specify values for \l{cpp::defines}{cpp.defines}. \section2 getHash \badcode Utilities.getHash(key: string): string \endcode Calculates a 16-byte hash of the input and returns it. Rules in modules should use this function to find unique locations for output artifacts in the build directory without duplicating the whole directory structure of the respective input file (to deal with the case of two files with the same name in different subdirectories of the same product). \section2 rfc1034Identifier \badcode Utilities.rfc1034Identifier(str: string): string \endcode Returns an RFC-1034 compliant identifier based on the given string by replacing each character that is not Latin alphanumeric or \c{.} with \c{-}. \section2 versionCompare \badcode Utilities.versionCompare(version1: string, version2: string): number \endcode Interprets the two arguments as version numbers and returns a number that is smaller than, equal to, or greater than zero if \c version1 is smaller than, equal to, or greater than \c version2, respectively. The version strings consist of up to three numbers separated by dots. */ qbs-src-3.3.1/doc/reference/items/0000755000175100017510000000000015232633614016327 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/items/probe/0000755000175100017510000000000015232633614017436 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/items/probe/pkgconfig-probe.qdoc0000644000175100017510000001566215232633614023374 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype PkgConfigProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.PkgConfigProbe \brief Retrieves the information about installed packages using the pkg-config binary. This probe takes the package name or the list of package names as input and returns the information that is required to compile and link using those packages. Usually, you can simply use a Depends item as described in \l{How do I build against libraries that provide pkg-config files?}. Alternatively, the probe can be used directly as follows: \code CppApplication { name: project.name Probes.PkgConfigProbe { id: pkgConfig name: "QtCore" minVersion: '4.0.0' maxVersion: '5.99.99' } files: 'main.cpp' cpp.defines : pkgConfig.defines cpp.includePaths: pkgConfig.includePaths cpp.dynamicLibraries: pkgConfig.libraries cpp.libraryPaths: pkgConfig.libraryPaths cpp.commonCompilerFlags: pkgConfig.compilerFlags cpp.linkerFlags: pkgConfig.linkerFlags } \endcode */ /*! \qmlproperty string PkgConfigProbe::sysroot This property sets the value of the \c PKG_CONFIG_SYSROOT_DIR environment variable passed to the \c pkg-config binary. This variable modifies -I and -L flags to use the directories located in target sysroot. This property is useful when cross-compiling packages that use \c pkg-config to determine CFLAGS and LDFLAGS. For example, if \c sysroot is set to \c /var/target, a \c -I/usr/include/libfoo will become \c -I/var/target/usr/include/libfoo. \defaultvalue \c qbs.sysroot */ /*! \qmlproperty string PkgConfigProbe::executable The name of or the path to the pkg-config executable. \defaultvalue "pkg-config" */ /*! \qmlproperty string PkgConfigProbe::name The name this probe. This property is used as \l{PkgConfigProbe::packageNames}{PkgConfigProbe.packageNames} value by default. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::packageNames The list of package names to pass to the pkg-config executable. For each package, pkg-config will return the information required to compile and link to this package. \defaultvalue [\l{PkgConfigProbe::name}{PkgConfigProbe.name}] */ /*! \qmlproperty string PkgConfigProbe::minVersion The minimum version of the required package. If set, pkg-config will ignore packages with version less than the value of this property. \nodefaultvalue */ /*! \qmlproperty string PkgConfigProbe::exactVersion The exact version of the required package. If set, pkg-config will ignore packages with version that is not equal to the value of this property. \nodefaultvalue */ /*! \qmlproperty string PkgConfigProbe::maxVersion The maximum version of the required package. If set, pkg-config will ignore packages with version greater than the value of this property. \nodefaultvalue */ /*! \qmlproperty bool PkgConfigProbe::forStaticBuild If \c true, pkg-config will return linker flags for a static linking instead of dynamic. \defaultvalue \c false */ /*! \qmlproperty stringList PkgConfigProbe::libDirs List of full, non-sysrooted paths where pkg-config should search for .pc files. This overrides the built-in path (which is usually /usr/lib/pkgconfig). This property sets the value of the \c PKG_CONFIG_LIBDIR environment variable passed to the \c pkg-config binary. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::cflags \internal This property contains the unparsed output from "pkg-config --cflags" call. Usually, you should use \l{PkgConfigProbe::defines}{PkgConfigProbe.defines}, \l{PkgConfigProbe::includePaths}{PkgConfigProbe.includePaths} and \l{PkgConfigProbe::compilerFlags}{PkgConfigProbe.compilerFlags} properties instead. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libs \internal This property contains the unparsed output from "pkg-config --libs" call. Usually, you should use \l{PkgConfigProbe::libraries}{PkgConfigProbe.libraries}, \l{PkgConfigProbe::libraryPaths}{PkgConfigProbe.libraryPaths} and \l{PkgConfigProbe::linkerFlags}{PkgConfigProbe.linkerFlags} properties instead. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::defines This output property contains the list of defines that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libraries This output property contains the list of library names that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libraryPaths This output property contains the list of library paths that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::includePaths This output property contains the list of include paths that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::compilerFlags This output property contains the list of flags that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::linkerFlags This output property contains the list of flags that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::modversion This output property contains the version of the found package. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/sdcc-probe.qdoc0000644000175100017510000000477215232633614022341 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype SdccProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.SdccProbe \inherits PathProbe \brief Collects SDCC toolchain compiler information. \since Qbs 1.14 \internal Detects the version, supported architecture and the platform endianness of the specified compiler executable file from the \l{http://sdcc.sourceforge.net/}{SDCC} toolchain. */ /*! \qmlproperty string SdccProbe::compilerFilePath An input property which is a full path to the SDCC compiler executable file. \nodefaultvalue */ /*! \qmlproperty string SdccProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "mcs51", \c "stm8", and \c "hcs8". \nodefaultvalue */ /*! \qmlproperty string SdccProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "little". \nodefaultvalue */ /*! \qmlproperty int SdccProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int SdccProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int SdccProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/binary-probe.qdoc0000644000175100017510000000607315232633614022705 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype BinaryProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.BinaryProbe \inherits PathProbe \brief Locates executable files outside the project. Finds executable files that have the specified file names. BinaryProbe searches for executable files within directories specified by the PATH environment variable. \note On Unix, also searches in the \c /usr/bin and \c /usr/local/bin directories by default. Override \l {PathProbe::platformSearchPaths}{PathProbe.platformSearchPaths} to change this behavior. \note On Windows, only files that have \e .com, \e .exe, \e .bat, \e .cmd extensions are considered \e executables. Override \l {PathProbe::nameSuffixes}{PathProbe.nameSuffixes} to change this behavior. For example, BinaryProbe can be used to search for a protobuf compiler executable as follows: \code // Assuming module is called "myproto" import qbs.File import qbs.Probes Module { // search for a protoc executable Probes.BinaryProbe { id: protocProbe names: "protoc" } property string executableFilePath: protocProbe.filePath validate: { if (!File.exists(executableFilePath)) throw "The executable '" + executableFilePath + "' does not exist."; } // use the found executable Rule { // rule input/outputs here... // run executable for the module called "myproto": prepare: { var args = // initialize arguments... var cmd = new Command(input.myproto.executableFilePath, args); cmd.highlight = "codegen"; cmd.description = "generating protobuf files for " + input.fileName; return [cmd]; } } } \endcode */ qbs-src-3.3.1/doc/reference/items/probe/framework-probe.qdoc0000644000175100017510000000433015232633614023410 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype FrameworkProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.FrameworkProbe \inherits PathProbe \brief Locates \macos frameworks outside the project. Finds \macos frameworks that have the specified file names. By default, FrameworkProbe searches for frameworks in \c ~/Library/Frameworks, \c /usr/local/lib, \c /Library/Frameworks, and in \c /System/Library/Frameworks. Also, if \l {qbs::sysroot}{qbs.sysroot} is specified (for example, when compiling using XCode SDK), the probe searches in the \c sysroot/System/Library/Frameworks folder first. For example, a simple FrameworkProbe that searches for the Foundation framework can be used as follows: \code import qbs.Probes Product { Depends { name: "cpp"; } Probes.FrameworkProbe { id: foundationProbe names: ["Foundation"] } cpp.frameworkPaths: foundationProbe.found ? [foundationProbe.path] : [] } \endcode */ qbs-src-3.3.1/doc/reference/items/probe/watcom-probe.qdoc0000644000175100017510000000622415232633614022711 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype WatcomProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.WatcomProbe \inherits PathProbe \brief Collects Oopen Watcom toolchain compiler information. \since Qbs 1.22 \internal Detects the version, supported architecture, the platform endianness, and other stuff for the specified compiler executable from the \l{https://github.com/open-watcom}{Open Watcom} toolchain. */ /*! \qmlproperty string WatcomProbe::compilerFilePath An input property which is a full path to the Digital Mars compiler executable. \nodefaultvalue */ /*! \qmlproperty string WatcomProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "x86" and \c "x86_16". \nodefaultvalue */ /*! \qmlproperty string WatcomProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "big" and \c "little". \nodefaultvalue */ /*! \qmlproperty string WatcomProbe::targetPlatform Detected target platform. The possible values are \c "windows", \c "linux", \c "os2" and \c "dos". \nodefaultvalue */ /*! \qmlproperty int WatcomProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int WatcomProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int WatcomProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ /*! \qmlproperty stringList WatcomProbe::includePaths Detected compiler include paths. \nodefaultvalue */ /*! \qmlproperty var WatcomProbe::compilerDefinesByLanguage Detected set of compiler pre-defined macros depending on the \c "C" or \c "C++" language. \nodefaultvalue */ /*! \qmlproperty var WatcomProbe::environment Detected compiler run environment. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/path-probe.qdoc0000644000175100017510000001572615232633614022362 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype PathProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.PathProbe \brief Locates files outside the project. Finds files that have the specified file name suffix, such as \e .exe, from the specified locations. PathProbe takes as input lists of paths to search files from and file name patterns. The paths are specified by using the environmentPaths, searchPaths, platformEnvironmentPaths and platformSearchPaths properties; the path are searched in the same order as listed. The file name patterns are specified by the \l names and nameSuffixes properties. Returns the first file that matches the file name patterns. If no such file is found, the \l {Probe::found}{probe.found} property is set to \c false. For example, a simple PathProbe that searches for the stdio.h header can be used as follows: \code Product { Depends { name: "cpp" } PathProbe { id: probe pathSuffixes: ["include"] names: ["stdio.h"] } cpp.includePaths: probe.found ? [probe.path] : [] } \endcode */ /*! \qmlproperty varList PathProbe::allResults This property contains the list of objects, each object representing a single found file: \code { found: true, candidatePaths: ["path1/to/file", "path2/to/file", ...] filePath: "path/to/file" fileName: "file" path: "path/to" } \endcode \sa {PathProbe::filePath}{filePath}, {PathProbe::fileName}{fileName}, {PathProbe::path}{path} */ /*! \qmlproperty var PathProbe::candidateFilter This property holds the function that can be used to filter out unsuitable candidates. For example, when searching for a library, it might be necessary to check its architecture: \code PathProbe { pathSuffixes: [".so", ".dll", ".dylib"] candidateFilter: { function getLibraryArchitecture(file) { ... } return function(file) { return Utilities.isSharedLibrary(file) && getLibraryArchitecture(file) == qbs.architecture; } } } \endcode */ /*! \qmlproperty stringList PathProbe::names The list of file names to search for. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::nameSuffixes The list of file suffixes to search for. These suffixes are appended to every file name passed via the \l names property. \nodefaultvalue */ /*! \qmlproperty script PathProbe::nameFilter A script that is executed for each file name before prepending file suffixes. Can be used to transform file names. */ /*! \qmlproperty pathList PathProbe::searchPaths The list of paths where to search files. \nodefaultvalue */ /*! \qmlproperty pathList PathProbe::platformSearchPaths The list of platform paths where to search files. \defaultvalue \c {['/usr', '/usr/local']} on Unix hosts, empty otherwise */ /*! \qmlproperty stringList PathProbe::pathSuffixes A list of relative paths that are appended to each path where PathProbe searches for files. That is, the file should be located within one of the subfolders passed using this property. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::environmentPaths The list of environment variables that contains paths where to search files. Paths in the environment variable should be separated using \l{pathListSeparator}{FileInfo.pathListSeparator()}. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::platformEnvironmentPaths The list of platform environment variables that contains paths where to search files. Paths in the environment variable should be separated using \l{pathListSeparator}{FileInfo.pathListSeparator()}. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::candidatePaths This property contains the result list of all paths that were checked before a file was found (including the file names). This property is set even if the Probe didn't find anything and can be used to give the user a hint what went wrong: \code Module { Probes.BinaryProbe { id: pythonProbe names: "python" } validate: { if (!pythonProbe.found) { throw ModUtils.ModuleError( "Could not find python binary at any of the following locations:\n\t" + pythonProbe.candidatePaths.join("\n\t")); } } } \endcode \nodefaultvalue */ /*! \qmlproperty string PathProbe::path This property contains the full path where the found file is located (that is, the file directory). \nodefaultvalue */ /*! \qmlproperty string PathProbe::filePath This property contains the full path to the found file, including the file name. \nodefaultvalue */ /*! \qmlproperty string PathProbe::fileName This property contains the found file's name (excluding the path). \nodefaultvalue */ /*! \qmlproperty varList PathProbe::selectors This property should be used to search for multiple files. It contains the list of selectors each of which describes a single file to search for. A selector can be either a string, a stringList, or a dictionary. The following example searches for three files and illustrates different ways to specify selectors: \code selectors: [ // 1st file with a single name "header.h", // 2nd file with possible name variants ["config.h", "foo-config.h", "bar-config.h"], // 3rd file with possible name and suffix variants {names: ["footk", "footk-version"], nameSuffixes: [".h", ".hpp"]} ] \endcode */ qbs-src-3.3.1/doc/reference/items/probe/iar-probe.qdoc0000644000175100017510000000527115232633614022173 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype IarProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.IarProbe \inherits PathProbe \brief Collects IAR toolchain compiler information. \since Qbs 1.13 \internal Detects the version, supported architecture and the platform endianness of the specified compiler executable file from the \l{https://www.iar.com/}{IAR} toolchain. */ /*! \qmlproperty string IarProbe::compilerFilePath An input property which is a full path to the IAR compiler executable file. \nodefaultvalue */ /*! \qmlproperty string IarProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "arm", \c "mcs51", \c "avr", \c "avr32", \c "stm8", \c "riscv", \c "rl78", \c "rx", \c "rh850", \c "v850", \c "78k", \c "sh", \c "r32c", \c "m32c", \c "m16c", \c "msp430", \c "hcs12", \c "hcs8", \c "m68k", and \c "cr16". \nodefaultvalue */ /*! \qmlproperty string IarProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "big" or \c "little". \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/keil-probe.qdoc0000644000175100017510000000501215232633614022335 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype KeilProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.KeilProbe \inherits PathProbe \brief Collects KEIL toolchain compiler information. \since Qbs 1.13 \internal Detects the version, supported architecture and the platform endianness of the specified compiler executable file from the \l{https://www.keil.com/}{KEIL} toolchain. */ /*! \qmlproperty string KeilProbe::compilerFilePath An input property which is a full path to the KEIL compiler executable file. \nodefaultvalue */ /*! \qmlproperty string KeilProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "arm", \c "mcs51", \c "mcs251" and \c "c166". \nodefaultvalue */ /*! \qmlproperty string KeilProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "big" or \c "little". \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/dmc-probe.qdoc0000644000175100017510000000543615232633614022166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype DmcProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.DmcProbe \inherits PathProbe \brief Collects Digital Mars toolchain compiler information. \since Qbs 1.13 \internal Detects the version, supported architecture, the platform endianness, and other stuff for the specified compiler executable from the \l{https://www.digitalmars.com/}{Digital Mars} toolchain. */ /*! \qmlproperty string DmcProbe::compilerFilePath An input property which is a full path to the Digital Mars compiler executable. \nodefaultvalue */ /*! \qmlproperty string DmcProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "x86" and \c "x86_16". \nodefaultvalue */ /*! \qmlproperty string DmcProbe::targetPlatform Detected target platform. The possible values are \c "windows" and \c "dos". \nodefaultvalue */ /*! \qmlproperty int DmcProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int DmcProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int DmcProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ /*! \qmlproperty stringList DmcProbe::includePaths Detected compiler include paths. \nodefaultvalue */ /*! \qmlproperty var DmcProbe::compilerDefinesByLanguage Detected set of compiler pre-defined macros depending on the \c "C" or \c "C++" language. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/probe/include-probe.qdoc0000644000175100017510000000350615232633614023042 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype IncludeProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.IncludeProbe \inherits PathProbe \brief Locates header files outside the project. This is the convenience item that searches for files in "include" directories. For example, IncludeProbe can be used to search for a zlib header as follows: \code import qbs.Probes CppApplication { Probes.IncludeProbe { id: zlibProbe names: "zlib.h" } cpp.includePaths: zlibProbe.found ? [zlibProbe.path] : [] files: 'main.cpp' } \endcode */ qbs-src-3.3.1/doc/reference/items/probe/conanfile-probe.qdoc0000644000175100017510000002234415232633614023356 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Richard Weickelt ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype ConanfileProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.ConanfileProbe \brief Extracts information about dependencies from a Conan recipe file. The \c ConanfileProbe interfaces \QBS to the \l{https://conan.io/}{Conan package manager}. It runs \l{https://docs.conan.io/en/latest/reference/commands/consumer/install.html}{conan install} on a Conan recipe file such as \c conanfile.py or \c conanfile.txt and extracts all available meta information about package dependencies using the \l{https://docs.conan.io/en/latest/reference/generators/json.html}{json generator}. The output may be used to set up \l{Profile} items or module properties in products. \c ConanfileProbe can also be used to run other Conan generators and to retrieve their output. \section1 Examples In the following examples we assume that our project contains a \c conanfile.py. This file describes all dependencies of our project. The dependency packages are expected to export meta information to be consumed by our project. \section2 Using ConanfileProbe with Conan Module Provider Conan 2.6 has a built-in \l{https://docs.conan.io/2/reference/tools/qbs/qbsdeps.html#qbsdeps}{QbsDeps} generator that creates JSON files suitable for consumption by the \l{conan}{conan} module provider. Use it to access dependencies. \qml import qbs.Probes Project { property string conanInstallPath: conanProbe.generatedFilesPath Probes.ConanfileProbe { id: conanProbe conanfilePath: project.sourceDirectory + "/conanfile.py" generators: "QbsDeps" } // somewhere in the project, maybe in a base item CppApplication { type: "application" files: "main.cpp" qbsModuleProviders: "conan" moduleProviders.conan.installDirectory: project.conanInstallPath Depends { name: "mylib" } } } \endqml \section2 Including Files Generated by Conan \note This example does not apply to Conan 2.0, or newer. Conan 1 has a built-in \l{https://docs.conan.io/en/latest/reference/generators/qbs.html}{qbs generator} that creates a project file containing dummy products. This is the easiest way to access dependencies, but also the least flexible one. It requires each Conan package to export correct meta information and works only if the dependency is a library. \qml import qbs.Probes Project { Probes.ConanfileProbe { id: conan conanfilePath: project.sourceDirectory + "/conanfile.py" generators: "qbs" } references: conan.generatedFilesPath + "/conanbuildinfo.qbs" CppApplication { type: "application" files: "main.cpp" Depends { name: "mylib" } } } \endqml \section2 Setting Module Properties in Products \note This example does not apply to Conan 2.0, or newer. When a product depends on a Conan package that does not have a dedicated \l{List of Modules}{module}, package meta information may be directly fed into the \l{cpp} module. This approach is very flexible. \qml import qbs.Probes CppApplication { Probes.ConanfileProbe { id: conan conanfilePath: product.sourceDirectory + "/conanfile.py" options: ({opt1: "True"; opt2: "TheValue"}) } cpp.includePaths: conan.dependencies["myLib"].include_paths cpp.libraryPaths: conan.dependencies["myLib"].lib_paths cpp.dynamicLibraries: conan.dependencies["mylib"].libs } \endqml \section2 Setting Up a Profile \note This example does not apply to Conan 2.0, or newer. When multiple products depend on one or more Conan packages, the dependency information may be combined in a \l{Profile}. This is especially useful when \QBS modules are available for some of the packages, but some of their properties need to be initialized. Otherwise, it would have to be done manually in global profiles. \qml import qbs.Probes Project { Probes.ConanfileProbe { id: conan conanfilePath: project.sourceDirectory + "/conanfile.py" } Profile { name: "arm-gcc" cpp.toolchainInstallPath: conan.dependencies["arm-none-eabi-gcc"].rootpath + "/bin" cpp.toolchainPrefix: "arm-linux-gnueabi-" qbs.toolchainType: "gcc" } } \endqml This allows fully automated dependency management, including compiler toolchains and is very useful when teams work in heterougeneous environments. */ /*! \qmlproperty stringList ConanfileProbe::additionalArguments Additional command line arguments that are appended to the \c{conan install} command. \defaultvalue [] */ /*! \qmlproperty path ConanfileProbe::conanfilePath Path to a \c conanfile.py or \c conanfile.txt that is used by this probe. This property cannot be set at the same time as \l{ConanfileProbe::}{packageReference}. \nodefaultvalue */ /*! \qmlproperty var ConanfileProbe::dependencies This property contains the same information as \l{ConanfileProbe::}{json}.dependencies, but instead of an array, \c dependencies is a map with package names as keys for convenient access. \note This property does not apply to Conan 2.0, or newer. \readonly \nodefaultvalue */ /*! \qmlproperty path ConanfileProbe::executable The name of or the path to the Conan executable. \defaultvalue "conan.exe" on Windows, "conan" otherwise */ /*! \qmlproperty path ConanfileProbe::generatedFilesPath The path of the folder where Conan generators store their files. Each instance of this probe creates a unique folder under \l{Project::buildDirectory}{Project.buildDirectory}. The folder name is a hash of the arguments supplied to \c{conan install}. \readonly \nodefaultvalue */ /*! \qmlproperty stringList ConanfileProbe::generators Conan generators to be executed by this probe. When using Conan 2.x, \l{https://docs.conan.io/2/reference/tools/qbs/qbsdeps.html#qbsdeps}{QbsDeps} generator is added by default. When using Conan 1.x, the \l{https://docs.conan.io/en/latest/reference/generators/json.html}{JSON generator} is always enabled. All generated files are written to the \l{ConanfileProbe::generatedFilesPath}{generatedFilesPath} folder. \sa {https://docs.conan.io/en/latest/reference/generators.html}{Available generators} \defaultvalue \c auto-detected */ /*! \qmlproperty var ConanfileProbe::json The parsed output of Conan's \l{https://docs.conan.io/en/latest/reference/generators/json.html}{JSON generator} as a JavaScript object. \note This property does not apply to Conan 2.0, or newer. \readonly \nodefaultvalue */ /*! \qmlproperty var ConanfileProbe::options Options applied to \c{conan install} via the \c{-o} flag. This property is an object in the form \c{key:value}. Example: \qml options: ({someOpt: "True", someOtherOpt: "TheValue"}) \endqml \nodefaultvalue */ /*! \qmlproperty string ConanfileProbe::packageReference Reference of a Conan package in the form \c{name/version@user/channel}. Use this property if you want to probe an existing package in the local cache or on a remote. This property cannot be set at the same time as \l{ConanfileProbe::}{conanfilePath}. \nodefaultvalue */ /*! \qmlproperty var ConanfileProbe::settings Settings applied to \c{conan install} via the \c{-s} flag. This property is an object in the form \c{key:value}. Example: \qml settings: ({os: "Linux", compiler: "gcc"}) \endqml \nodefaultvalue */ /*! \qmlproperty var ConanfileProbe::verbose Set to \c{true} to print all output of `conan install`. If this property is \c{false} only error output will be printed. \defaultvalue \c{false} */ qbs-src-3.3.1/doc/reference/items/probe/library-probe.qdoc0000644000175100017510000000432615232633614023064 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype LibraryProbe \inqmlmodule QbsProbes \ingroup list-of-items \keyword QML.IncludeProbe \inherits PathProbe \brief Locates library files outside the project. On Windows, searches for library files within directories specified by the \c PATH environment variable. On Unix, searches for library files within directories specified by the \c LIBRARY_PATH environment variable, as well as in \c "/usr/lib" and \c "/usr/local/lib". On Linux, also searches in platform-specific directories, such as \c "/usr/lib64" and \c "/usr/lib/x86_64-linux-gnu". For example, LibraryProbe can be used to search for a \c zlib library as follows: \code import qbs.Probes CppApplication { Probes.LibraryProbe { id: zlibProbe names: "z" } cpp.libraryPaths: zlibProbe.found ? [zlibProbe.path] : [] cpp.dynamicLibraries: zlibProbe.found ? [zlibProbe.names] : [] files: 'main.cpp' } \endcode */ qbs-src-3.3.1/doc/reference/items/language/0000755000175100017510000000000015232633614020112 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/items/language/probe.qdoc0000644000175100017510000000571115232633614022075 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Parameters \nextpage Product \qmltype Probe \inqmlmodule QbsLanguageItems \ingroup list-of-items \ingroup list-of-probes \keyword QML.Probe \brief Locates files outside the project. Probe items can appear inside \l{Product}, \l{Project} and \l{ModuleProvider} items. They are run prior to building, for instance to locate dependent headers, libraries, and other files outside the project directory whose locations are not known ahead of time. Probes can be parameterized via their properties and typically store results in properties as well. These results are then retrieved via the Probe's id, which is mandatory: \code Product { Probe { id: valueCalculator property string parameter: "whatever" property int value configure: { value = Utils.calculateValue(parameter); // Expensive operation found = true; } } property int theValue: valueCalculator.value } \endcode \note Because Probes often invoke external processes, which is relatively expensive compared to evaluating normal properties, their results are cached. To force re-evaluation of a Probe, you can supply the \l{build-force-probe-execution} {--force-probe-execution} command-line option to the \l{build} command. */ /*! \qmlproperty bool Probe::condition Determines whether the probe will actually be run. \defaultvalue \c true */ /*! \qmlproperty bool Probe::found Indicates whether the probe was run successfully. Set by \l{configure}. \nodefaultvalue */ /*! \qmlproperty script Probe::configure A script that is executed when the probe is run. */ qbs-src-3.3.1/doc/reference/items/language/product.qdoc0000644000175100017510000002066015232633614022446 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Probe \nextpage Profile \qmltype Product \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Product \brief Represents the result of a build process. A Product typically represents the result of a build process. It specifies a set of input and output files and a way to transform the former into the latter. For example, the following product sets up a very simple C++ application: \code Product { name: "helloworld" type: "application" files: "main.cpp" Depends { name: "cpp" } } \endcode The \l{type} property specifies what will be built (an executable). The \l{files} property specifies the input files (one C++ source file), and the \l{Depends} item pulls in the logic from the \l{cpp} module about how to do the necessary transformations. For some often-used types of products, \QBS pre-defines special derived items that save users some typing. These are: \list \li \l{Application} \li \l{CppApplication} \li \l{DynamicLibrary} \li \l{StaticLibrary} \endlist Therefore, the above example could also be written like this: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode Any property \c prop attached to this item is available in sub-items as \c product.prop, as well as in modules that are loaded from this product. \section1 Multiplexing Properties The following properties are relevant for product multiplexing only. Unless multiplexing is desired, they can be left at their default values: \list \li \l{aggregate} \li \l{multiplexedType} \li \l{multiplexByQbsProperties} \endlist \note We do not promise backwards compatibility for multiplexing properties as they are likely to change in future \QBS versions. \section1 Read-Only Properties The following properties are automatically set by \QBS and cannot be changed by the user: \list \li \l{buildDirectory} \li \l{sourceDirectory} \endlist */ /*! \qmlproperty bool Product::builtByDefault Determines whether the product will be built. If \c false, the product will only be built if this is explicitly requested, either by listing the product name as an argument to the \l{build-products}{--products} option or by using the \l{build-all-products}{--all-products} option of the \l{build} command. \defaultvalue \c true */ /*! \qmlproperty bool Product::condition Determines whether the product will be built. If \c false, the product will not be built. \defaultvalue \c true */ /*! \qmlproperty string Product::name The name of the product. Used to identify the product in a \l{Depends} item, for example. The value of this property must be a simple JavaScript expression that does not depend on module properties or values that are non-local to this product. \code CppApplication { name: "hello" + "world" // valid } CppApplication { name: "app_" + qbs.targetOS.join("_") // invalid } \endcode To change the name of your product's target artifact, modify \l{targetName} instead. \defaultvalue An empty string */ /*! \qmlproperty stringList Product::type The file tags matching the product's target artifacts. \defaultvalue An empty list */ /*! \qmlproperty string Product::targetName The base file name of the product's target artifacts. \defaultvalue The value of \l{name} with illegal file name characters replaced by underscores. */ /*! \qmlproperty string Product::destinationDirectory The directory where the target artifacts will be located. If a relative path is given, the base directory will be \l{Project::buildDirectory} {project.buildDirectory}. \defaultvalue \c{product.buildDirectory} */ /*! \qmlproperty stringList Product::files A list of source files. Syntactic sugar to save a \l{Group} item for simple products. Relative paths are resolved using the parent directory of the project file that sets the property. \defaultvalue An empty list */ /*! \qmlproperty stringList Product::excludeFiles A list of source files not to include. Useful with wildcards. For more information, see \l{Group}. \defaultvalue An empty list */ /*! \qmlproperty bool Product::consoleApplication On Windows, determines whether a console or GUI application is generated. If \c true, a console application is generated. If \c false, a GUI application is generated. On Apple platforms, influences the default application type. If \c true, a normal executable is generated. If \c false, an application bundle is generated. \defaultvalue Linker-dependent */ /*! \qmlproperty stringList Product::qbsSearchPaths A list of paths that are searched for imports, modules and module providers. The value set here will be merged with the value of \l{Project::qbsSearchPaths}{project.qbsSearchPaths}. For the details about how to add custom items, see the \l{Custom Modules and Items} page. \defaultvalue \l{Project::qbsSearchPaths}{project.qbsSearchPaths} */ /*! \qmlproperty string Product::version The version number of the product. Used in shared library filenames and generated Info.plist files in Apple application and framework bundles, for example. \nodefaultvalue */ /*! \qmlproperty bool Product::aggregate If \c{true}, an aggregate product will be created that has dependencies on all multiplex instances of this product. \note If you do not want to do multiplexing, you can use the default value \c{undefined}. */ /*! \qmlproperty stringList Product::multiplexedType Specifies the product type for the multiplexed product instances. \note If you do not want to do multiplexing, you can use the default value \c{undefined}. */ /*! \qmlproperty stringList Product::multiplexByQbsProperties Specifies which properties of the \l{qbs} module will be used for product multiplexing: \list \li \l{qbs::architectures}{architectures} \li \l{qbs::buildVariants}{buildVariants} \li \l{qbs::profiles}{profiles} \endlist The value must be a subset of the above values. \note If you do not want to do multiplexing, you can use the default value \c{["profiles"]}. */ /*! \qmlproperty path Product::buildDirectory \readonly The build directory for this product. This is the directory where generated files are placed. The value of this property is automatically set by \QBS and cannot be changed by the user. */ /*! \qmlproperty path Product::sourceDirectory \readonly The source directory for this product. This is the directory of the file where this product is defined. The value of this property is automatically set by \QBS and cannot be changed by the user. */ /*! \qmlproperty stringList Product::qbsModuleProviders The list of \l{Module Providers} to use for this product. Overrides \l{Project::qbsModuleProviders}{Project.qbsModuleProviders}. \sa Project::qbsModuleProviders \since Qbs 1.21 */ qbs-src-3.3.1/doc/reference/items/language/project.qdoc0000644000175100017510000001055515232633614022436 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Profile \nextpage Properties \qmltype Project \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Project \brief Represents a collection of products and properties. A Project item represents a collection of of products. In a non-trivial project, these products are typically defined in their own files and referenced in the main project file: \code Project { references: [ "product1/product1.qbs", "product2/product2.qbs" ] } \endcode Any property \c prop attached to this item is available in sub-items as \c project.prop. While the root of the item hierarchy is always a Project, this kind of item can also appear further down the hierarchy. Such sub-projects are usually introduced to group products. See \l{SubProject} for details. \note If your project consists of only one product, the Project item can be omitted. */ /*! \qmlproperty path Project::buildDirectory \readonly The build directory of the top-level project. */ /*! \qmlproperty string Project::name The project name. Only relevant when displaying a project tree in an IDE, for example. \defaultvalue The basename of the file that defines the project. */ /*! \qmlproperty string Project::profile \readonly The top-level \l{Profile}{profile} for building the project. This property is set by \QBS when the project is being set up. */ /*! \qmlproperty bool Project::condition Whether the project is enabled. If \c false, no \l{Product}{products} or sub-projects will be collected. \defaultvalue \c true */ /*! \qmlproperty stringList Project::qbsSearchPaths A list of paths that are searched for imports, modules and module providers in addition to the ones listed in \c{preferences.qbsSearchPaths}. The value set here is merged with the value inherited from the parent project, if there is one. The result is inherited by all products in the project. For the details about how to add custom items, see the \l{Custom Modules and Items} page. \defaultvalue An empty list */ /*! \qmlproperty pathList Project::references A list of files from which to import products. This is equivalent to defining the respective \l{Product} items directly under this Project item. \defaultvalue An empty list */ /*! \qmlproperty path Project::sourceDirectory \readonly The directory where the file containing the top-level Project item is located. */ /*! \qmlproperty string Project::minimumQbsVersion The minimum version of \QBS that is needed to build this project. \defaultvalue \c "1.3.0" */ /*! \qmlproperty stringList Project::qbsModuleProviders The list of \l{Module Providers} to use for this project. Providers contribute to the \l{Product::}{qbsSearchPaths} in the order specified here, so modules generated by providers specified earlier are prioritized. Currently, this order also corresponds with the actual execution order of the providers, but this should not be relied upon. \sa Product::qbsModuleProviders \since Qbs 1.21 */ qbs-src-3.3.1/doc/reference/items/language/group.qbs0000644000175100017510000000343015232633614021755 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Project { Product { //! [0] Group { name: "Word processing documents" files: ["*.doc", "*.rtf"] prefix: "**/" qbs.install: true qbs.installDir: "share" excludeFiles: "do_not_install_this_file.*" } //! [0] } } qbs-src-3.3.1/doc/reference/items/language/export.qdoc0000644000175100017510000001106615232633614022307 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Depends \nextpage FileTagger \qmltype Export \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Export \brief Exports dependencies and properties to other products. An Export item can appear inside a \l{Product} item. It defines a \l{Module} with the product's name that can be depended on by other products. The properties attached to the Export item will take effect in all products that depend on the product inside which the Export item is defined. As an example, consider these two products: \code Product { name: "A" Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.sourceDirectory cpp.defines: ["USING_" + exportingProduct.name.toUpperCase()] } } Product { name: "B" Depends { name: "A" } } \endcode The sources in product B will be able to use headers from product A without specifying the full path to them, because the include path has been made known to the compiler via A's Export item. Additionally, product B will be compiled with the define \c{USING_A}. The dependent \l{Product}'s modules are not exported unless explicitly specified within the \l{Export} item: \code Product { name: "B-Exporting-A" Depends { name: "A" } Export { Depends { name: "A" } } } \endcode The relationship of the exported dependencies is transitive. A product C depending on a product B-Exporting-A will also get a direct dependency on A and thus inherit include paths and preprocessor macros exported by A. \code Product { name: "C" Depends { name: "B-Exporting-A" } } \endcode Within an Export item, you can use the \c exportingProduct variable to refer to the product which defines the Export item. Use the \c{importingProduct} variable to refer to the product that pulls in the resulting module: \code Product { name: "D" Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory, importingProduct.buildDirectory] } } \endcode */ /*! \qmlproperty var Export::prefixMapping This property allows to provide a translation of exported values between non-deployed and deployed contexts. It is an array of objects with properties \c prefix and \c replacement. The array's elements get applied to all other properties set in this item such that if the property's value start with \c prefix, that prefix gets replaced with \c replacement. It is typically used for C/C++ include paths. For instance, in a library that provides header files for inclusion both directly from its source directory (when building it as part of a bigger project) and from some installed location (when building an unrelated project against it), you would write something like the following: \code Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] prefixMapping: [{ prefix: exportingProduct.sourceDirectory, replacement: FileInfo.joinPaths(qbs.installPrefix, "include") }] } \endcode \defaultvalue \c undefined \see Exporter.qbs \see Exporter.pkgconfig \since 1.12 */ qbs-src-3.3.1/doc/reference/items/language/depends.qdoc0000644000175100017510000001455115232633614022412 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Artifact \nextpage Export \qmltype Depends \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Depends \brief Represents dependencies between products and modules. A Depends item can appear inside a \l{Product} or \l{Module} item. For example, the following product will load the \l{cpp} module. In addition, it will try to load modules that may or may not exist, and pass this information on to the compiler. \code Product { Depends { name: "cpp" } Depends { name: "optional_module" versionAtLeast: "2.0" required: false } Properties { condition: optional_module.present cpp.defines: "HAS_OPTIONAL_MODULE" } // ... } \endcode \section1 Dependency Parameters Sometimes it is desirable to have certain dependencies handled differently than others. For example, one might want to depend on a dynamic library without linking it. This can be done by setting the \l{dependency-parameters-cpp}{cpp.link} dependency parameter to \c{true} in the dynamic library dependency: \code Product { Depends { name: "cpp" } Depends { name: "some_dynamic_lib"; cpp.link: false } // ... } \endcode Dependency parameters are a special type of property that can only be set within Depends and \l [QML] {Parameters} items. Dependency parameters are declared in the modules they belong to. In the example above, the \l{cpp} module declares the parameter \c{link}. The Depends item for \c{some_dynamic_lib} sets \c{cpp.link} to \c{false}, which tells the linker rule to ignore this particular dependency. */ /*! \qmlproperty bool Depends::condition Determines whether the dependency will actually be applied. \defaultvalue \c true */ /*! \qmlproperty string Depends::versionAtLeast The minimum value that the dependency's \c version property needs to have. If the actual version is lower than that, loading the dependency will fail. The value consists of integers separated by dots. \nodefaultvalue */ /*! \qmlproperty string Depends::versionBelow A value that the dependency's \c version property must be lower than. If the actual version is equal to or higher than that, loading the dependency will fail. The value consists of integers separated by dots. \nodefaultvalue */ /*! \qmlproperty stringList Depends::productTypes A list of product types. Any enabled product in the project that has a matching type will become a dependency of the product containing the Depends item. This property is mutually exclusive with the \l name and \l submodules properties. The \l required and \l profiles properties are ignored if this property is set. \note This property does not work recursively. Consider this example: \code Product { name: "A" type: "x" Depends { productTypes: "someTag" } } Product { name: "B" Depends { productTypes: "x" } } \endcode It is not guaranteed that \c A will show up in \c B's dependencies. \nodefaultvalue */ /*! \qmlproperty bool Depends::required Setting this property to \c false creates a \e{soft dependency}, meaning that it is not considered an error if the given module cannot be found. In such a case, an instance of the respective module will be created, but only the \l{Module::present}{Module.present} property will be available for querying, and it will be set to \c false. \defaultvalue \c true */ /*! \qmlproperty bool Depends::minimal Setting this property to \c false instructs \QBS to build the respective product only to the extent that is necessary for the depending product. Otherwise (the default), the dependency gets fully built. This property only has an effect if the user requested a subset of the project to be built (that is, the -p option is used), the dependency is not in that subset and no other product in the subset has a non-minimal dependency on it. \defaultvalue \c false \since Qbs 3.0 */ /*! \qmlproperty string Depends::name The name of the dependent product or module. \nodefaultvalue */ /*! \qmlproperty stringList Depends::profiles A list of profiles. If the dependency is on a product and that product is going to be built for more than one profile, you can specify here which instance of the product the dependency is on. See the \l{qbs::profiles}{qbs.profiles} property for more information. An empty list means a dependency on all instances of the product with the given name, regardless of their profile. \nodefaultvalue */ /*! \qmlproperty bool Depends::limitToSubProject If \l productTypes is set and this property is \c true, only products that are in the same sub-project as the product containing the Depends item are considered. \defaultvalue \c false */ /*! \qmlproperty stringList Depends::submodules A list of submodules of the module to depend on, if applicable. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/language/rule.qdoc0000644000175100017510000003160515232633614021736 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage PropertyOptions \nextpage Scanner \qmltype Rule \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Rule \brief Creates transformers for input tags. In \QBS, rules create \e transformers that produce output files from input files. The term \e transformer refers to a list of \l{Command and JavaScriptCommand}{commands}. These commands are created in a rule's \l{prepare} script. They do the actual work, either directly or by executing external commands. \section1 A Simple Example The following rule takes text files and replaces Windows-style line endings with their Unix-style counterparts. We will look at it one piece at a time. \quotefromfile ../examples/rule/rule.qbs \skipto Rule \printuntil multiplex: false A \e {multiplex rule} creates one transformer that takes all input artifacts with the matching input file tag and creates one or more output artifacts. We are setting the respective property to \c false here, indicating that we want to create one transformer per input file. \note This is actually the default, so the above assignment is not required. \printuntil inputs: ["txt_input"] Here we are specifying that our rule is interested in input files that have the tag \c "txt_input". Such files could be source files, in which case you would tag them using a \l{Group}. Or they could in turn get generated by a different rule, in which case that rule would assign the file tag. The files matching the tag will be available in the \l{prepare} script under the name \c inputs (see \l{inputs and outputs}{The inputs and outputs Variables}). \printuntil } Here we are specifying that for every input file, we want to create one output file whose name is the same as the input file, but with an additional extension. Because we are giving a relative path, \QBS will prepend that path by the product's build directory. In addition, we tell \QBS that the output files should get the file tag \c "txt_output". This enables other rules to use these files as inputs. You must always assign suitable file tags to your output artifacts, or the rule will not be run. See \l{Rules and Product Types} for details. If you want to create more than one output file per input file, you simply provide multiple \l Artifact items. The set of output artifacts will be available in the prepare script under the name \c outputs (see \l{inputs and outputs}{The inputs and outputs Variables}). \printuntil /^\s{4}\}/ The prepare script shown above puts everything together by creating the command that does the actual transformation of the file contents, employing the help of the \l{TextFile Service}{TextFile} class. As you can see, the return value is an array, meaning you can provide several commands to implement the rule's functionality. For instance, if we had provided two \c Artifact items, we might have also provided two commands, each of them creating one output file. For the \c input and \c output variables used in the code, see the next section. \target inputs and outputs \section1 The \c inputs and \c outputs Variables We already mentioned that the input and output artifacts are available in the prepare script via the variables \c inputs and \c outputs, respectively. These variables are JavaScript objects whose property keys are file tags and whose property values are lists of objects representing the artifacts matching these tags. In our example, the \c inputs variable has a single property \c txt_input, whose value is a list with one element. Similarly, the \c outputs variable also has one single property \c txt_output, again with a list containing one element. The actual artifact objects have the following properties: \table \header \li Property \li Description \row \li \c baseName \li The file name without any extension. \row \li \c completeBaseName \li The file name without the last extension. \row \li \c fileName \li The name of the file (that is, \c filePath without any directory components). \row \li \c filePath \li The full file path. \row \li \c fileTags \li The list of the artifact's file tags. \endtable The artifact object contains a property for every module that is used in the product. That can be used to access the module's properties. For instance, for an artifact in a C++ product, \c{artifact.cpp.defines} is the list of defines that will be passed when compiling the respective file. But what about the variables \c input and \c output that appeared in our example? These are simply convenience variables which are available in the case that the \c inputs and \c outputs variables contain only one artifact, respectively. So in our example, instead of \c input we also could have written \c {inputs.txt_input[0]}, which is considerably more verbose. \section1 Rules and Product Types It is important to know that when figuring out which rules to execute, \QBS starts at the product type and then looks for a way to produce artifacts with matching file tags from source files, using a chain of rules that are connected by their respective input and output tags. For instance, consider this simple C++ project: \code Product { type: ["application"] Depends { name: "cpp" } files: ["main.cpp"] } \endcode Here's how this product is built: \list 1 \li \QBS looks for a rule that can produce artifacts with the file tag \c{"application"}. Such a rule is found in the \l{cpp} module (namely, the rule that invokes the linker). \li Since the rule found in the previous step takes inputs of type \c{"obj"}, \QBS now looks for a rule that produces artifacts of that type. Again, such a rule is found in the \c cpp module (the rule that runs the compiler). \li The rule found in the previous step takes inputs of type \c{"cpp"}. No rule is found that creates such artifacts, but we do have a source file with a matching type (because the \c cpp module contains a \l{FileTagger} which attached that type to \c{"main.cpp"} due to its file extension). \li Now that there is a chain of rules leading from a source file tag to the product type, the commands of these rules are executed one after the other until we end up with our executable. \endlist \section1 A Complete Example The following code snippet shows a single \l{Rule} within a \l{Product} and summarizes the previous sections. \note The product's type is set up to the \c "txt_output" file tag to tell \QBS that the product depends on output artifacts produced by the custom rule. Otherwise the rule would not be executed. \quotefile ../examples/rule/rule.qbs */ /*! \qmlproperty bool Rule::multiplex Determines whether this is a multiplex rule. \defaultvalue \c false */ /*! \qmlproperty stringList Rule::inputs A list of file tags the input artifacts must match. All output artifacts will depend on all artifacts in the product with the given input file tags. Also, these artifacts are available in the \c inputs variable of the \l{prepare} script. \nodefaultvalue */ /*! \qmlproperty stringList Rule::auxiliaryInputs A list of file tags. This rule will be dependent on (that is: applied after) every other rule in the same product that (potentially) produces artifacts that are compatible with the value of this property. Unlike \l{inputs}, this property has no effect on the content of the \c inputs variable of the \l{prepare} script. \nodefaultvalue */ /*! \qmlproperty stringList Rule::auxiliaryInputsFromDependencies Like \l auxiliaryInputs, except that instead of rules from the current product, those from product dependencies are considered. \nodefaultvalue \since 2.6 */ /*! \qmlproperty stringList Rule::excludedInputs A list of file tags. Connections to rules that produce these file tags are prevented. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList Rule::inputsFromDependencies A list of file tags that the artifacts of product dependencies must match. For example, the product \a foo might appear as follows in the current product: \code Depends { name: "foo" } \endcode All artifacts of \a foo that match the given file tags will appear in the \c inputs variable of the \l{prepare} script. \nodefaultvalue */ /*! \qmlproperty var Rule::outputArtifacts An array of output artifacts, specified as JavaScript objects. For example: \code outputArtifacts: [{ filePath: "myfile.cpp", fileTags: ["cpp"], cpp: { cxxLanguageVersion: "c++11" } }] \endcode For a description of the possible properties, see the documentation of the \l{Artifact} item. Output artifacts can be specified either by this property or by \l{Artifact} items. Use this property if the set of outputs is not fixed but depends the input's content. If no file tags are provided, \QBS will apply all \l{FileTagger}{file taggers} known in the current context to the output file name. The user may set the property \c{explicitlyDependsOn} on artifact objects, which is similar to \l{Rule::explicitlyDependsOn}{Rule.explicitlyDependsOn}. \nodefaultvalue */ /*! \qmlproperty stringList Rule::outputFileTags If output artifacts are specified by \l{outputArtifacts}, this property must specify a list of file tags that the rule potentially produces. \nodefaultvalue */ /*! \qmlproperty bool Rule::condition If \c true, the rule is enabled, otherwise it does nothing. \defaultvalue \c true */ /*! \qmlproperty stringList Rule::explicitlyDependsOn A list of file tags. Each artifact that matches the file tags is added to the dependencies of each output node. All artifacts in the current product are considered. The main difference between this property and \l inputs is that all matching artifacts are dependencies for all output artifacts, regardless of whether \l multiplex is true or not. \nodefaultvalue */ /*! \qmlproperty stringList Rule::explicitlyDependsOnFromDependencies Like \l explicitlyDependsOn, except that instead of artifacts from the current product, those from product dependencies are considered. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty script Rule::prepare A script that prepares the commands to transform the inputs to outputs. The code in this script is treated as a function with the signature \c{function(project, product, inputs, outputs, input, output, explicitlyDependsOn)}. The argument \c{input} is \c{undefined} if there's more than one input artifact for this rule. Similarly, \c{output} is only defined if there is exactly one output artifact. \nodefaultvalue */ /*! \qmlproperty bool Rule::requiresInputs Specifies whether a rule's commands should be created even if no inputs are available. Enabling this property can be useful if you are not sure whether input files exist, and you want \QBS to create an output file even if they do not. Set to \c true if the rule declares any inputs, \c false otherwise. */ /*! \qmlproperty bool Rule::alwaysRun If \c true, the rule's commands are always executed, even if all output artifacts are up to date. \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/items/language/joblimit.qdoc0000644000175100017510000000732215232633614022577 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Group \nextpage Module \qmltype JobLimit \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.JobLimit \brief Restricts concurrent execution of jobs in a given pool. In addition to the global limit on concurrently running commands, a project might want to restrict concurrent execution of certain types of commands even further, for instance because they are not well-suited to share certain types of resources. In the following example, we define a rule that runs a tool of which at most one instance can be running for the same project at any given time: \code Rule { // ... prepare: { var cmd = new Command("my-exclusive-tool", [project.buildDirectory]); cmd.description = "running the exclusive tool"; cmd.jobPool = "exclusive_tool"; return cmd; } } JobLimit { jobPool: "exclusive_tool" jobCount: 1 } \endcode \c JobLimit items can appear inside \l Product, \l Project and \l Module items. In the case of collisions, that is, items matching the same job pool but setting different values, the ones defined inside products have the highest precedence, and the ones inside modules have the lowest. Items defined in sub-projects have higher precedence than those defined in parent projects. For items with the same precedence level, the most restrictive one is chosen, that is, the one with the lowest job number greater than zero. \see {How do I limit the number of concurrent jobs for the linker only?} */ /*! \qmlproperty bool JobLimit::condition Determines whether the job limit is active. If this property is set to \c false, the job limit is ignored. \defaultvalue \c true */ /*! \qmlproperty int JobLimit::jobCount The maximum number of commands in the given \l{jobPool}{job pool} that can run concurrently. A value of zero means "unlimited", negative values are not allowed. \note The global job limit always applies: For instance, if you set this property to 100 for some job pool, and "-j 8" was given on the command line, then no more than eight instances of commands from the respective job pool will run at any time. This property must always be set. \nodefaultvalue */ /*! \qmlproperty string JobLimit::jobPool The job pool to which apply the limit. This property must always be set to a non-empty value. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/language/profile.qdoc0000644000175100017510000000616315232633614022430 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Product \nextpage Project \qmltype Profile \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Profile \brief Creates a profile within the project. The profiles used by \QBS are normally set up on a user's machine and are then available to all projects. See \l{Configuring Profiles and Preferences} for information on how to set up and use profiles on the command line. In some rare cases, however, the creator of a project has complete knowledge about the system on which that project is to be built. Then it can make sense to integrate the profile into the project: \code Product { // ... Profile { name: "my-special-profile" qbs.toolchainType: "gcc" qbs.targetPlatform: "linux" qbs.architecture: "armv7a" cpp.toolchainInstallPath: "/opt/special-gcc/bin" cpp.toolchainPrefix: "arm-linux-gnueabi-" } qbs.profiles: ["my-special-profile"] // ... } \endcode The project in the above example can be built in a particular well-known environment without any additional setup. \c Profile items can appear inside \l{Product} and \l{Project} items. */ /*! \qmlproperty string Profile::baseProfile The name of a profile from which this profile inherits. If the same property is set in both this profile and the base profile, the value from this profile takes precedence. \nodefaultvalue */ /*! \qmlproperty bool Profile::condition Determines whether this profile can be used. If this property is set to \c false, the profile cannot be used. \defaultvalue \c true */ /*! \qmlproperty string Profile::name The name under which the profile can be referenced later. Setting this property is required. The value must be unique among all profiles in an entire project. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/language/subproject.qdoc0000644000175100017510000000743015232633614023146 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Scanner \qmltype SubProject \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.SubProject \brief Adds a project from a different file. A SubProject item is used to add a sub-project that is defined in a separate file. Additionally, properties of the sub-project can be set without modifying the separate project file. The following example adds a sub-project defined in \c{subdir/project.qbs} and overrides its name. \code Project { SubProject { filePath: "subdir/project.qbs" Properties { name: "A sub-project" } } ... } \endcode A typical use case for SubProject items is to conditionally include sub-projects. The following example pulls in the \e{tests} sub-project if and only if the \c{withTests} property is \c{true}. \code Project { property bool withTests: false SubProject { filePath: "tests/tests.qbs" Properties { condition: parent.withTests } } ... } \endcode If you do not need to set any properties on the sub-project, you can also use the \l{Project::references}{Project.references} property, the same way you would for a product. \code Project { references: "subdir/project.qbs" } \endcode is equivalent with \code Project { SubProject { filePath: "subdir/project.qbs" } } \endcode It is also possible to nest \l{Project} items directly in the same file. */ /*! \qmlproperty bool SubProject::condition Whether the sub-project is added. If \c false, the sub-project is not included. Setting this property has the same effect as setting the \c{condition} property within a \l{Properties} item. If both this property and the \c{condition} property within a \l{Properties} item are defined, the sub-project is included only if both properties evaluate to \c{true}. \defaultvalue \c true */ /*! \qmlproperty path SubProject::filePath The file path of the project to add as a sub-project. If the top-level item in this file is a \l{Product}, it gets wrapped automatically in a new project. \defaultvalue empty */ /*! \qmlproperty bool SubProject::inheritProperties Determines whether the sub-project should inherit the properties of the surrounding \l{Project}. You can use this feature to share global settings between projects and sub-projects. \defaultvalue \c true */ qbs-src-3.3.1/doc/reference/items/language/filetagger.qdoc0000644000175100017510000000706515232633614023103 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Export \nextpage Group \qmltype FileTagger \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.FileTagger \brief Assigns file tags to files. This item assigns file tags to files. The FileTagger item can appear in \l{Product} items or \l{Module} items. For every source artifact that has no file tag, \QBS will search for a FileTagger with a pattern that matches the file name of the source artifact. If a matching file tagger is found, then the file tags specified in the FileTagger item are assigned to the source artifact. If there is more than one matching FileTagger, all file taggers with the same highest priority are taken into account and their file tags are accumulated. The FileTagger item can be attached to a product or a module. In the latter case, its effect is the same as if it had been attached to all products having a dependency on the respective module. For instance, the \l{cpp} module of \QBS has, among others, the following file tagger: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode As a result, the \c "cpp" tag is automatically attached to all files ending with \c ".cpp" in products depending on the \c cpp module. This causes them to be compiled, because a C++ compiler rule has \c "cpp" in its list of matching input tags. File taggers are disabled if file tags are set explicitly in a \l{Product} {product} or \l{Group}{group}. For example, the \c "cpp" tag is not attached to the \c .cpp files in the following product: \code Product { Depends { name: "cpp" } Group { files: "*.cpp" fileTags: "other" } } \endcode */ /*! \qmlproperty stringList FileTagger::patterns \since Qbs 1.0 A list of patterns to match against. Supports the usual wildcards '*', '?' and '[]'. Neither the list itself nor any of its elements may be empty. */ /*! \qmlproperty list FileTagger::fileTags \since Qbs 1.0 Tags to attach to a product's files. These can then be matched by a rule. \defaultvalue An empty list */ /*! \qmlproperty int FileTagger::priority \since Qbs 1.10 The priority of the FileTagger. A higher numerical value means a higher priority. \defaultvalue 0 */ qbs-src-3.3.1/doc/reference/items/language/artifact.qdoc0000644000175100017510000000533215232633614022562 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \nextpage Depends \ingroup list-of-language-items \qmltype Artifact \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Artifact \brief Describes a file produced by a Rule. An Artifact represents a single file produced by a \l{Rule}. For example, if a rule produces three files, it needs to contain three Artifact items. In addition to Artifact properties, you can set module properties within an Artifact item, as follows: \code Artifact { filePath: "somefile.cpp" fileTags: ["cpp"] cpp.cxxLanguageVersion: "c++11" // ... } \endcode \note The code on the right-hand side of Artifact properties has access to the set of input artifacts. That is, it can refer to the \c inputs map and, if the rule is not a multiplex rule, the \c input variable. */ /*! \qmlproperty bool Artifact::alwaysUpdated Setting this property to \c false means the file is not necessarily always written to by any command run by the rule. If all artifacts of a rule have this property set to \c false, the commands of the rule are only executed if all of them are out of date compared to the inputs. \defaultvalue \c true */ /*! \qmlproperty string Artifact::filePath The file path of the target artifact. \nodefaultvalue */ /*! \qmlproperty stringList Artifact::fileTags A list of tags to attach to the target file. These can then be matched by a \l{Rule}. \defaultvalue An empty list */ qbs-src-3.3.1/doc/reference/items/language/module.qdoc0000644000175100017510000002301615232633614022251 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage JobLimit \nextpage ModuleProvider \qmltype Module \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Module \brief Represents a collection of properties and items that can be loaded into a product. A Module item is a collection of properties and language items. It contributes to building a product if the product has a \l{Depends}{dependency} on the module. Modules may contain the following items: \list \li \l{Depends} \li \l{FileTagger} \li \l{Group} \li \l{JobLimit} \li \l{Parameter} \li \l{Probe} \li \l{PropertyOptions} \li \l{Rule} \li \l{Scanner} \endlist When a product expresses a dependency on a module, \QBS will create an instance of the module item in the scope of the product. The product can then read and write properties from and to the loaded module, respectively. Modules in different products are isolated from each other, just as products cannot access each other's properties. However, products can use the \l{Export} item to pass dependencies and properties of modules to other dependent products. The following (somewhat artificial) module pre-processes text files by removing certain characters from them. The module's name is \c{txt_processor}. \qml import qbs.FileInfo import qbs.TextFile Module { property stringList unwantedCharacters: [] FileTagger { patterns: ["*.raw"] fileTags: ["raw-txt"] } Rule { inputs: ["raw-txt"] Artifact { filePath: FileInfo.relativePath(input.filePath, product.sourceDirectory) + "/" + input.fileName + ".processed" fileTags: ["processed-txt"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Processing " + input.fileName; cmd.sourceCode = function() { var inFile = new TextFile(input.filePath, TextFile.ReadOnly); var content = inFile.readAll(); inFile.close(); var unwantedChars = input.txt_processor.unwantedCharacters; for (var c in unwantedChars) content = content.replace(unwantedChars[c], ""); var outFile = new TextFile(output.filePath, TextFile.WriteOnly); outFile.write(content); outFile.close(); }; return cmd; } } } \endqml And this is how a \l{Product} would use the module: \qml Product { type: "processed-txt" Depends { name: "txt_processor" } txt_processor.unwantedCharacters: ["\r"] files: [ "file1.raw", "file2.raw" ] } \endqml The resulting files are tagged with \c{processed-txt} and might be consumed by a rule in another module. That is possible if another rule has \c{processed-txt} in its \l{Rule::inputs}{inputs} property. For more information about how you make your own modules available to \QBS, see \l{Custom Modules and Items}. \section1 Accessing Product and Module Properties When defining a property in a module item, the right-hand side expression is a binding. Bindings may reference other properties of: \list \li the current module \li other modules that this module depends on \li the dependent product \endlist Please note that this applies to bindings in modules only. Property access in rules and other nested items is different. \section2 Accessing Properties of the Current Module Sibling properties in the same module can be accessed directly by their name: \qml Module { property stringList windowsDefaults: ["\r"] property stringList unwantedCharacters: windowsDefaults } \endqml \section2 Properties of the Dependent Modules When a module loads another module through a \l{Depends} element, it can access properties of the other module through its name. Assuming there was a module \c OtherModule with a property \c otherProperty, such an access would look like this: \qml Module { Depends { name: "OtherModule" } property string myProperty: "something-" + OtherModule.otherProperty } \endqml \section2 Accessing Properties of the Dependent Product \qml Module { property bool featureEnabled: (product.type.includes("application")) ? true : false } \endqml \section2 Special Property Values For every property defined in a module, \QBS provides the special \l{Special Property Values#original}{original} value containing the value of the property in the module itself (possibly overridden from a profile). \section1 Dependency Parameters Modules can declare dependency parameters. Those parameters can be set within \l{Depends} items. \l{Rule}{Rules} of the module can read the parameters of dependencies and act accordingly. In the following example, the module \e{foo} declares the parameter \c{ignore}. A dependency to \c{bar} then sets the parameter \c{foo.ignore} to \c{true}. A rule in \c{foo} ignores all dependencies that have \c{foo.ignore} set to true. \code Module { // Definition of module 'foo'. Parameter { property bool ignore } Rule { ... prepare: { for (i in product.dependencies) { var dep = product.dependencies[i]; if (dep.foo.ignore) continue; // Do something with the dependency. } } } ... } ---------- Product { Depends { name: "foo" } Depends { name: "bar"; foo.ignore: true } } \endcode */ /*! \qmlproperty stringList Module::additionalProductTypes A list of elements that will be added to the \l{Product::type}{type} property of a product that has a dependency on the module. \defaultvalue \c [] */ /*! \qmlproperty bool Module::condition Whether the module is enabled. If this property is \c false, the surrounding Module item will not be considered in the module look-up. \defaultvalue \c true */ /*! \qmlproperty bool Module::present \readonly This property is \c false if and only if the respective \l{Depends} item had its \l{Depends::required}{required} property set to \c false and the module was not found. \defaultvalue \c true */ /*! \qmlproperty int Module::priority The priority of this module instance. If there is more than one module instance available for a module name, the module with the highest priority is chosen. \defaultvalue 0 */ /*! \qmlproperty script Module::setupBuildEnvironment A script for setting up the environment in which a product is built. The code in this script is treated as a function with the signature \c{function(project, product)}. Use the \l{Environment Service}{Environment} functions to alter the environment. The return value of this script is ignored. \nodefaultvalue */ /*! \qmlproperty script Module::setupRunEnvironment A script for setting up the environment in which a product is run. The code in this script is treated as a function with the signature \c{function(project, product, config)}. The \c config parameter is a list of arbitrary strings that can be passed via the \l{run} command. The values supported by specific modules are listed in their respective documentation. Use the \l{Environment Service}{Environment} functions to alter the environment. The return value of this script is ignored. \nodefaultvalue */ /*! \qmlproperty script Module::validate A script that is run after the module is loaded. It can be used to check property values and throw errors in unexpected cases. The return value is ignored. \nodefaultvalue */ /*! \qmlproperty string Module::version The module's version. It consists of integer values separated by dots. You can check for specific values of this property in a \l{Depends} item. */ qbs-src-3.3.1/doc/reference/items/language/moduleprovider.qdoc0000644000175100017510000001251215232633614024023 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Module \nextpage Parameter \qmltype ModuleProvider \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.ModuleProvider \brief Creates modules on demand. The \c ModuleProvider item implements the module creation part of the procedure described in the \l {Module Providers} overview. It is always located in a file called \c provider.qbs. The actual module creation is done on the right-hand side of the \l{ModuleProvider::relativeSearchPaths}{relativeSearchPaths} property. A ModuleProvider item may contain \l{Probe} items. Here is a complete minimal example of a module provider. It just creates an empty module. If you put this item into the file \c {module-providers/mymodule/provider.qbs} in your project source directory, you will be able to successfully build a product which contains a dependency on the module \c mymodule. \code import qbs.File import qbs.FileInfo import qbs.TextFile ModuleProvider { relativeSearchPaths: { var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", name); File.makePath(moduleDir); var moduleFilePath = FileInfo.joinPaths(moduleDir, name + ".qbs"); var moduleFile = new TextFile(moduleFilePath, TextFile.WriteOnly); moduleFile.writeLine("Module {"); moduleFile.writeLine("}"); moduleFile.close(); return ""; } } \endcode */ /*! \qmlproperty bool ModuleProvider::isEager Holds whether provider is eager. Eager provider is executed only once and should create multiple modules at once when executed). A non-eager provider is executed multiple times, one time for each module \QBS tries to instantiate. \sa ModuleProvider::moduleName \default true */ /*! \qmlproperty string ModuleProvider::name The name of the module provider. This property is set by \QBS. If provider is \l{How \QBS Uses Module Providers}{requested} via the \l{Product::qbsModuleProviders}{qbsModuleProviders} property, it is the name specified in this property and matches the provider file name, without the \c .qbs extension. Otherwise, it is the name of the directory the provider was found in, relative to the particular module-providers base directory. For instance, if the dependency is \c {x.m1} and the provider was found in \c {module-providers/x/m1/provider.qbs}, then \c name is \c {x.m1}. If the provider was found in \c {module-providers/x/provider.qbs}, then \c name is \c x. */ /*! \qmlproperty string ModuleProvider::moduleName This property is set by QBS for non-eager providers and contains the name of the module that is currently being instantiated by the provider. For eager providers, the value of this property is \c undefined. \sa ModuleProvider::isEager */ /*! \qmlproperty string ModuleProvider::outputBaseDir The path under which the new modules should be created when \l relativeSearchPaths is evaluated. The path is unique for the current provider in the given configuration. This property is set by \QBS. */ /*! \qmlproperty stringList ModuleProvider::relativeSearchPaths This property gets evaluated by \QBS to retrieve new search paths with which to re-attempt the module look-up. It is here where you need to put the code that creates the new module files. Use the directory structure explained in \l {Custom Modules and Items}. That is, the file for a module called \c m will be located in a directory \c {modules/m/}, anchored at \l outputBaseDir. The return value is the list of search paths required to find the new module, relative to \l outputBaseDir. In most cases, only a single search path will be required, in which case a single-element list containing an empty string should be returned (or just the empty string, because of \QBS' auto-conversion feature). The returned list can also be empty, which means that the module provider was not able to generate any modules in this environment. */ qbs-src-3.3.1/doc/reference/items/language/propertyoptions.qdoc0000644000175100017510000000401615232633614024263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Properties \nextpage Rule \inqmlmodule QbsLanguageItems \qmltype PropertyOptions \ingroup list-of-items \keyword QML.PropertyOptions \brief Provides inline documentation for properties within product and module items. A PropertyOptions item can appear inside a \l{Product} or \l{Module} item to provide inline documentation for properties. */ /*! \qmlproperty stringList PropertyOptions::allowedValues A list of the values permitted by the property. The default value, \c{undefined}, indicates that any value is permitted. */ /*! \qmlproperty string PropertyOptions::description A brief description of the property. \nodefaultvalue */ /*! \qmlproperty string PropertyOptions::name The name of the property to document. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/language/scanner.qdoc0000644000175100017510000000615315232633614022420 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Rule \nextpage SubProject \qmltype Scanner \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Scanner \brief Creates custom dependency scanners in products or modules. A Scanner item can appear inside a \l{Module} item, and allows to extract dependencies for artifacts from the artifacts' file contents. For example, this is what a scanner for "qrc" files might look like: \code import qbs.Xml Module { Scanner { inputs: 'qrc' scan: { var xml = new Xml.DomDocument(input.filePath); dependencies = []; // retrieve entries from the XML document return dependencies; } } } \endcode */ /*! \qmlproperty bool Scanner::condition If \c true, the scanner is enabled, otherwise it does nothing. \defaultvalue \c true */ /*! \qmlproperty stringList Scanner::inputs A list of \l{FileTagger}{file tags} the input artifacts must match. \nodefaultvalue */ /*! \qmlproperty bool Scanner::recursive Determines whether to scan the returned dependencies using the same scanner. \defaultvalue \c false */ /*! \qmlproperty script Scanner::searchPaths A script that returns the paths where to look for dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input)}. \nodefaultvalue */ /*! \qmlproperty script Scanner::scan A script that reads the input artifact and returns a string list with dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input, filePath)}, where \c input is the artifact at which the scan originated, and \c filePath is the currently scanned file. For non-recursive scans, \c filePath is always equal to \c{input.filePath}. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/language/parameters.qdoc0000644000175100017510000000436415232633614023134 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Parameter \nextpage Probe \qmltype Parameters \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Parameters \brief Defines default values for dependency parameters within Module and Export items. The Parameters item defines default values for dependency parameters within \l{Module} and \l{Export} items. Example: \code DynamicLibrary { name: "foo" ... Export { ... Parameters { cpp.link: false } } } \endcode Every dependency on \e{foo} has the parameter \l{dependency-parameters-cpp} {cpp.link} set to \c{false} by default. This can be overridden explicitly: \code Depends { name: "foo"; cpp.link: true } \endcode The Parameters item contains a number of property bindings where each property must be a properly declared dependency parameter. For more information, see \l{Parameter} and \l{Module#dependency-parameters}{Module - Dependency Parameters}. */ qbs-src-3.3.1/doc/reference/items/language/parameter.qdoc0000644000175100017510000000347415232633614022752 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Module \nextpage Parameters \qmltype Parameter \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Parameter \brief Declares a dependency parameter. The Parameter item declares a dependency parameter. It can appear only within \l{Module} and \l{Export} items. The Parameter item contains exactly one property declaration. Example: \code Module { Parameter { property string extra } } \endcode For more information about dependency parameters, see \l{Module#dependency-parameters}{Module - Dependency Parameters}. */ qbs-src-3.3.1/doc/reference/items/language/group.qdoc0000644000175100017510000002242515232633614022123 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage FileTagger \nextpage JobLimit \qmltype Group \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Group \brief Groups files and other items in a product or module. This item is attached to a \l{Product}{product} or \l{Module}{module} and used to group files and other items that have something in common. \section1 Typical Uses of Groups by Example \code Application { Group { name: "common files" files: ["myclass.h", "myclass_common_impl.cpp"] } Group { name: "Windows files" condition: qbs.targetOS.includes("windows") files: "myclass_win_impl.cpp" } Group { name: "Unix files" condition: qbs.targetOS.includes("unix") files: "unixhelper.cpp" Group { name: "Linux files" condition: qbs.targetOS.includes("linux") files: "myclass_linux_impl.cpp" } Group { name: "FreeBSD files" condition: qbs.targetOS.includes("freebsd") files: "myclass_freebsd_impl.cpp" } } Group { name: "Files to install" qbs.install: true qbs.installDir: "share" files: "runtime_resource.txt" } } \endcode \section1 Wildcards When specifying files, you can use the wildcards \c "*", \c "?" and \c "[]", which have their \l{https://en.wikipedia.org/wiki/Wildcard_character#File_and_directory_patterns}{usual meaning} as in Unix Shell. By default, matching files are only picked up directly from the parent directory, but you can tell \QBS to consider the whole directory tree. It is also possible to exclude certain files from the list. The pattern \c "**" used in a pathname expansion context will match all files and zero or more directories and subdirectories. For example: \snippet reference/items/language/group.qbs 0 \section1 Attaching Module Properties to Source Files Within a \c Group item, module properties can be attached either to all files in the product, or to only the files in that group. The following example demonstrates both: \code Product { // ... Group { condition: project.hasSpecialFeature cpp.defines: "FEATURE_SPECIFIC" product.cpp.defines: "WITH_FEATURE" files: "feature.cpp" } } \endcode Here, the macro \c "FEATURE_SPECIFIC" will only be visible inside \c feature.cpp, whereas \c "WITH_FEATURE" applies to all source files in the product. A group-level property binding starting with \c "product." is semantically equivalent to putting the same property binding without that prefix inside a top-level \l Properties item with the same condition as the group. The above example could therefore also have been written like this: \code Product { // ... Group { condition: project.hasSpecialFeature cpp.defines: "FEATURE_SPECIFIC" files: "feature.cpp" } Properties { condition: project.hasSpecialFeature cpp.defines: "WITH_FEATURE" } } \endcode Obviously, the original variant is to be preferred, as it does not duplicate the condition and keeps related code close together. It should be noted that there is a third way to write the same example, with a \l Properties item inside the group: \code Product { // ... Group { condition: project.hasSpecialFeature cpp.defines: "FEATURE_SPECIFIC" files: "feature.cpp" Properties { cpp.defines: "WITH_FEATURE" } } } \endcode This construct just adds verbosity here, but might be useful in cases where the product-level property binding is dependent on an additional condition. \section1 Attaching Module Properties to Generated Files A group can also be used to attach properties to build artifacts such as executables or libraries. In the following example, an application is installed to "/bin". \code Application { Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode \section1 Groups in Modules Groups may also appear in \l{Module}{modules}, which causes the respective sources to be added to the products depending on the said module, unless the \l{filesAreTargets} property is set. \section1 Grouping Related Items Groups can contain other items, namely \l Depends, \l FileTagger, \l Rule and \l Scanner items. They can also contain other groups, that is, they can be nested. The \l{condition} of a groups's child item gets logically ANDed with the one of the parent group. Additionally, if the child item is a group itself, the child group inherits the module properties and \l{FileTagger}{file tags} as well as the prefix of its parent group. */ /*! \qmlproperty string Group::name The name of the group. Not used internally; mainly useful for IDEs. \defaultvalue "Group x", where x is a unique number among all the groups in the product. */ /*! \qmlproperty pathList Group::files The files in the group. Mutually exclusive with \l{fileTagsFilter}. Relative paths are resolved using the parent directory of the file that contains the Group item. However, if the \l{prefix} property is set to an absolute path, then that one becomes the base directory. The values can contain wildcards. \defaultvalue An empty list */ /*! \qmlproperty bool Group::filesAreTargets If this property is \c true and the group is in a \l{Module}, the files in the group will not become source artifacts of the product that depends on the module. Instead, they are treated like target artifacts of products. That is, they will be matched against the \l{Rule::inputsFromDependencies}{inputsFromDependencies} file tag list of \l{Rule}{rules} in products that depend on the module. \defaultvalue \c false */ /*! \qmlproperty string Group::prefix A string to prepend to all files. Slashes are allowed and have directory semantics. \defaultvalue The prefix of the parent group if one exists, otherwise empty. */ /*! \qmlproperty stringList Group::fileTagsFilter List of \l{Artifact::fileTags}{artifact.fileTags} to match. Any properties set in this group will be applied to the product's artifacts whose file tags match the ones listed here. The file tags that the group's \l{fileTags} property specifies will be added to the matching artifacts. This property is mutually exclusive with \l{files}. \defaultvalue An empty list */ /*! \qmlproperty bool Group::condition Determines whether the files in the group are actually considered part of the project. \defaultvalue \c true */ /*! \qmlproperty stringList Group::fileTags A list of file tags to attach to the group's files. These can then be matched by a \l{Rule}{rule}. \note \l{FileTagger}{File taggers} are never applied to a file that has this property set. \defaultvalue An empty list */ /*! \qmlproperty bool Group::overrideTags Determines how tags on files that are listed both at the top level of a product (or the parent group, if there is one) and a group are handled. If this property is \c true, then the \l{FileTagger}{file tags} set via the group replace the ones set via the product or parent group. If it is \c false, the \e {group tags} are added to the \e {parent tags}. This property is ignored if \l{fileTagsFilter} is set. \defaultvalue \c true */ /*! \qmlproperty pathList Group::excludeFiles A list of files that are \e subtracted from the \l{files} list. The values can contain wildcards. This property is ignored if \l{fileTagsFilter} is set. \defaultvalue An empty list */ qbs-src-3.3.1/doc/reference/items/language/properties.qdoc0000644000175100017510000001240615232633614023161 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Project \nextpage PropertyOptions \qmltype Properties \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Properties \brief Provides conditional setting of properties. \note This topic documents the Properties item in the context of \l{Product} {products}. For more information about using it in sub-projects, see \l{SubProject}. The Properties item is an auxiliary item for setting multiple property values conditionally. In the following example, two properties are set if the project is built for Windows: \code Product { Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["extraWindowsIncludes"] } } \endcode As the above example demonstrates, the \c Properties item is especially useful if there are several properties whose values depend on the same set of conditions. These conditions do not need to be mutually exclusive, but care should be taken not to set the same scalar property in more than one matching \c Properties item. \QBS makes no guarantees about the value of the property in such cases. If the same property is set both inside and outside of a \c Properties item, the behavior depends on the type of property: \list \li For scalar values, the outside binding is only considered if none of the \c Properties conditions match, that is, it acts as an "else" case. \li For list values, the outside value is always considered. \endlist \code Product { Properties { condition: qbs.targetOS.includes("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["myWindowsIncludes"] cpp.treatWarningsAsErrors: false } Properties { condition: qbs.targetOS.includes("linux") cpp.defines: ["ON_LINUX"] cpp.includePaths: ["myLinuxIncludes"] } cpp.defines: ["ALL_PLATFORMS"] cpp.treatWarningsAsErrors: true } \endcode is roughly equivalent to \code Product { cpp.defines: { var defines = ["ALL_PLATFORMS"]; if (qbs.targetOS.includes("windows")) defines.push("ON_WINDOWS"); if (qbs.targetOS.includes("linux")) defines.push("ON_LINUX"); return defines; } cpp.includePaths: { if (qbs.targetOS.includes("windows")) return ["myWindowsIncludes"]; if (qbs.targetOS.includes("linux")) return ["myLinuxIncludes"]; return base ? base : original; } cpp.treatWarningsAsErrors: !qbs.targetOS.includes("windows") } \endcode In Properties items, one can access the \l{Special Property Values#outer}{outer} value of a property. \code Product { property string theFeature: "basic" Properties { condition: qbs.targetOS.includes("windows") theFeature: outer + "_plus_windows" // === "basic_plus_windows" } Properties { condition: qbs.targetOS.includes("linux") theFeature: outer + "_plus_linux" // === "basic_plus_linux" } cpp.defines: 'THE_FEATURE="' + theFeature + '"' } \endcode */ /*! \qmlproperty bool Properties::condition The condition to be used for the other bindings in this item. \default true \note The special value \c undefined can be used to indicate that this condition should be considered true if and only if none of the other Properties items matched for a given property binding. */ /*! \qmlproperty bool Properties::overrideListProperties List properties set within this item will override the values coming from modules, rather than getting merged with them, which is the default behavior. Use this in the rare case that a module you depend on inserts a value into a list property that is problematic for some product. \defaultvalue \c false */ qbs-src-3.3.1/doc/reference/items/convenience/0000755000175100017510000000000015232633614020623 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/items/convenience/javajarfile.qdoc0000644000175100017510000000337115232633614023755 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage JavaClassCollection \nextpage Library \qmltype JavaJarFile \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.JavaJarFile \brief Collection of Java class files bundled in a jar file. A JavaJarFile item is a \l{Product}{product} of the \l{Product::}{type} \c{java.jar}. It is used to produce a jar archive from a set of Java sources. */ /*! \qmlproperty string JavaJarFile::entryPoint The entry point for an executable jar file. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/convenience/objectlibrary.qdoc0000644000175100017510000000347715232633614024341 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage LoadableModule \nextpage Plugin \qmltype ObjectLibrary \inherits CppLibrary \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.ObjectLibrary \brief A collection of object files. An ObjectLibrary item is a \l{CppLibrary}{library} of the \l{Product::}{type} \c "objectlibrary". It behaves exactly like a \l StaticLibrary, except that the object files are not packaged into a container. It is suitable if the library does not need to be installed and distributed, for instance when it is used as an internal abstraction inside a project. */ qbs-src-3.3.1/doc/reference/items/convenience/qtlupdaterunner.qdoc0000644000175100017510000000627015232633614024735 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage QtGuiApplication \nextpage StaticLibrary \qmltype QtLupdateRunner \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.QtLupdateRunner \since 2.6 \brief A product that updates all Qt translation files in the project. A QtLupdateRunner has a dependency on all \l{Product}{products} that have a Qt dependency. Building the QtLupdateRunner product will run the \l{https://doc.qt.io/qt-6/linguist-lupdate.html}{lupdate} tool on eligible source files from these products in order to update the project's translation files with regard to the translatable strings in these sources. The \l{Product::}{builtByDefault} property is set to \c false by default, so updating the translation files has to be explicitly requested. The default name of the product is \c "lupdate-runner". To use this feature: \list 1 \li Instantiate a \c QtLupdateRunner in your project, typically at the top level: \code Project { // ... QtLupdateRunner { } // ... } \endcode \li Trigger the translation files update by building the product: \code qbs build -p lupdate-runner \endcode \endlist \section2 Relevant File Tags \table \header \li Tag \li Since \li Description \row \li \c{"qt.untranslatable"} \li 2.6 \li Attach this tag to source files that lupdate should not consider. \endtable */ /*! \qmlproperty bool QtLupdateRunner::limitToSubProject By default, only the source files of products that live in the same sub-project that QtLupdateRunner was instantiated in are looked at. Set this property to \c false to consider all products in the project. \defaultvalue \c true */ /*! \qmlproperty stringList QtLupdateRunner::extraArguments Additional arguments to pass to the \c lupdate tool. \nodefaultvalue */ qbs-src-3.3.1/doc/reference/items/convenience/plugin.qdoc0000644000175100017510000000421115232633614022767 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage ObjectLibrary \nextpage QtApplication \qmltype Plugin \inherits Library \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.Plugin \brief Plugin base item. A Plugin item is a \l{Library} that is installed to the \l{ConfigInstall::pluginsDirectory}{pluginsDirectory}. It can be built as a dynamic or static library; the behavior is controlled by the \l{ConfigBuild::pluginType}{config.build.pluginType} property. On Apple platforms, the Plugin item has the \c{"loadablemodule"} type when building as dynamic plugin. If \l{bundle::isBundle}{bundle.isBundle} is set to \c true (the default), artifacts are installed into the \l{ConfigInstall::loadableModulesDirectory}{loadableModulesDirectory}. This item exists for the convenience of project file authors. */ qbs-src-3.3.1/doc/reference/items/convenience/installpackage.qdoc0000644000175100017510000000551015232633614024456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage InnoSetup \nextpage JavaClassCollection \qmltype InstallPackage \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.InstallPackage \brief Archive of an installed project. An InstallPackage item is a \l{Product}{product} of the \l{Product::}{type} \c{archiver.archive} that has a \l{Depends}{dependency} on the \l{archiver} module. It is used to produce an archive from a set of installable files. Consider the following example project: \code Project { CppApplication { name: "myapp" Depends { name: "mylib" } files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } DynamicLibrary { name: "mylib" files: ["mylib.cpp"] Group { name: "public headers" files: ["mylib.h"] qbs.install: true qbs.installDir: "include" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } InstallPackage { archiver.type: "tar" name: "tar-package" Depends { name: "myapp" } Depends { name: "mylib" } } } \endcode Building the product \c "tar-package" on a Unix system will result in a tar file with these contents: \code include/mylib.h lib/libmylib.so bin/myapp \endcode */ qbs-src-3.3.1/doc/reference/items/convenience/innosetup.qdoc0000644000175100017510000000312715232633614023522 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage DynamicLibrary \nextpage InstallPackage \qmltype InnoSetup \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.InnoSetup \brief Inno Setup installer executable. A InnoSetup item is a \l{Product}{product} of the \l{Product::}{type} \c{"innosetup.exe"} that has a dependency on the \l{innosetup} module. */ qbs-src-3.3.1/doc/reference/items/convenience/configbuild.qdoc0000644000175100017510000000450415232633614023763 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage AutotestRunner \nextpage ConfigInstall \qmltype ConfigBuild \inqmlmodule QbsConvenienceItems \ingroup list-of-items \since Qbs 3.1 \brief This is the base item for the \l{config.build} module. This items contains properties that configure built-in items such as \l{Application}, \l{Library}, and \l{Plugin}. */ /*! \qmlproperty string ConfigBuild::libraryType Controls the default library kind produced by \l{Library} items. Allowed values are \c{"dynamic"} and \c{"static"}. \defaultvalue \c{"dynamic"}. On Apple iOS targets prior to iOS 8, dynamic libraries are not supported; in that case a static library will be produced regardless of this setting. */ /*! \qmlproperty string ConfigBuild::pluginType Controls the default library kind produced by \l{Plugin} and l{LoadableModule} items. Allowed values are \c{"dynamic"} and \c{"static"}. \defaultvalue \l{libraryType}. On Apple iOS targets prior to iOS 8, dynamic libraries are not supported; in that case a static plugin will be produced regardless of this setting. */ qbs-src-3.3.1/doc/reference/items/convenience/autotestrunner.qdoc0000644000175100017510000001340615232633614024601 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage ApplicationExtension \nextpage ConfigInstall \qmltype AutotestRunner \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AutotestRunner \brief Product that runs all autotests in the project. An AutotestRunner has a dependency on all \l{Product}{products} with the \l{Product::}{type} \c "autotest". Building the AutotestRunner product will then run the respective executables. The \l{Product::}{builtByDefault} property is set to \c false by default, so running the autotests has to be explicitly requested. The default name of the product is \c "autotest-runner". To use this feature: \list 1 \li Attach the \c "autotest" type to your autotests: \code CppApplication { name: "tst_mytest" type: ["application", "autotest"] // ... } \endcode \li Instantiate exactly one AutotestRunner in your project, typically at the top level: \code Project { // ... AutotestRunner { } // ... } \endcode \li Trigger the autotest execution by building the product: \code qbs build -p autotest-runner \endcode \endlist \section2 Setting Properties for individual Tests \target autotestrunner-autotest-module To control the behavior of individual tests, some properties of the \c AutotestRunner can be overridden by depending on the \l autotest module and setting its properties: \code CppApplication { name: "tst_mytest" type: ["application", "autotest"] Depends { name: "autotest" } autotest.timeout: 60 // ... } \endcode \section2 Relevant Job Pools \target autotestrunner-job-pools \table \header \li Pool \li Since \li Description \row \li \c{"autotest-runner"} \li 1.15 \li The job pool used to run the tests. \endtable */ /*! \qmlproperty stringList AutotestRunner::arguments The list of arguments to invoke the autotest with. A test can override this by setting the \l{autotest::arguments}{arguments} property of the \l autotest module. \defaultvalue \c [] */ /*! \qmlproperty stringList AutotestRunner::auxiliaryInputs This property can contain arbitrary file tags. The AutotestRunner will get dependencies on all products whose type matches at least one of these tags, and invocation of the test executables will happen only after all of the respective artifacts have been built. Set this property if your test executables have run-time dependencies on other products. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList AutotestRunner::environment A list of environment variables that are added to the run environment. They are provided as a list of strings in the form \c "varName=value". \defaultvalue DYLD_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, and DYLD_ROOT_PATH are set on macOS, or an empty list for other platforms. */ /*! \qmlproperty bool AutotestRunner::limitToSubProject By default, only those autotests are considered that are in the same sub-project that AutotestRunner was instantiated in. If you want to run all autotests regardless of their location in the project hierarchy, set this property to \c false. \defaultvalue \c true */ /*! \qmlproperty string AutotestRunner::workingDir If this property is set, it will be the working directory for all invoked test executables. Otherwise, the working directory will the the parent directory of the respective executable. A test can override this by setting the \l{autotest::workingDir}{workingDir} property of the \l autotest module. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList AutotestRunner::wrapper Wrapper binary and its arguments for wrapping autotest calls. This is useful for tools like Valgrind and alike. \defaultvalue empty */ /*! \qmlproperty int AutotestRunner::timeout Time limit for the execution of the individual tests. If a test does not finish within the time limit, the test is cancelled and considered failed. A value below or equal to 0 means no timeout. A test can override this by setting the \l{autotest::timeout}{timeout} property of the \l autotest module. \defaultvalue -1 \since Qbs 1.15 */ qbs-src-3.3.1/doc/reference/items/convenience/staticlibrary.qdoc0000644000175100017510000000304215232633614024346 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage QtLupdateRunner \nextpage XPCService \qmltype StaticLibrary \inherits CppLibrary \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.StaticLibrary \brief Static library. A StaticLibrary item is a \l{CppLibrary}{library} of the \l{Product::}{type} \c "staticlibrary". */ qbs-src-3.3.1/doc/reference/items/convenience/javaclasscollection.qdoc0000644000175100017510000000333615232633614025523 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage InstallPackage \nextpage JavaJarFile \qmltype JavaClassCollection \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.JavaClassCollection \brief Collection of Java class files not bundled in a jar file. A JavaClassCollection item is a \l{Product}{product} of the \l{Product::} {type} \c{"java.class"} that has a dependency on the \l{java} module. If the files should end up in a jar file, you should use \l{JavaJarFile} instead. */ qbs-src-3.3.1/doc/reference/items/convenience/cpplibrary.qdoc0000644000175100017510000000637215232633614023652 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage CppApplication \nextpage CppStd \qmltype CppLibrary \inherits Library \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.CppLibrary \brief C++ library. A CppLibrary is an \l{Library}{Library} that has a dependency on the \l{cpp} module. It also provides additional properties to ease the installation of public and private headers. \since Qbs 3.2 */ /*! \qmlproperty string CppLibrary::headersDirectoryName The name of the directory where headers are installed. \defaultvalue \l{product::targetName}{Product.targetName} \since Qbs 3.2 */ /*! \qmlproperty stringList CppLibrary::publicHeaders The list of the public headers. Files are autoatically tagged with the \c "hpp" tag and are installed to \l{publicHeadersDirectory} if library installation is requested. On Apple platforms, if \l{bundle::isBundle}{isBundle} is \c true, files are also tagged as \c "bundle.input.public_hpp" and are copied into the \c Headers directory within the bundle. \defaultvalue \c [] \since Qbs 3.2 */ /*! \qmlproperty string CppLibrary::publicHeadersDirectory The directory where to install public headers. \defaultvalue \l{installpaths.headers} + \c{"/"} + \l{headersDirectoryName} \since Qbs 3.2 */ /*! \qmlproperty stringList CppLibrary::privateHeaders The list of the private headers. Files are autoatically tagged with the \c "hpp" tag and are installed to \l{privateHeadersDirectory} if library installation is requested. On Apple platforms, if \l{bundle::isBundle}{isBundle} is \c true, files are also tagged as \c "bundle.input.public_hpp" and are copied into the \c PrivateHeaders directory within the bundle. \defaultvalue \c [] \since Qbs 3.2 */ /*! \qmlproperty string CppLibrary::privateHeadersDirectory The directory where to install private headers. \defaultvalue \l{installpaths.headers} + \c{"/"} + \l{headersDirectoryName} + \c{"/private"} \since Qbs 3.2 */ qbs-src-3.3.1/doc/reference/items/convenience/library.qdoc0000644000175100017510000001041715232633614023142 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage JavaJarFile \nextpage LoadableModule \qmltype Library \since Qbs 1.4 \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.NativeBinary \brief Generic library. A Library item is a base item for native libraries and can have \l{Product::}{type} set to one of the following values: \c "dynamiclibrary", \c "staticlibrary", \c "objectlibrary", \c "loadablemodule". The default \l{Product::}{type} value is \c "dynamiclibrary" except for iOS prior to version 8, in which case the default value is \c "staticlibrary". This item can automatically install the library target (and library symlinks on Unix) and separated debug information. For Android targets, the following applies: \list \li The \l{Product::type}{Product.type} property value contains \c "android.nativelibrary" in addition to \c "dynamiclibrary". \li There is a dependency on the \l{cpp} and \l{Android.ndk} modules. \endlist */ /*! \qmlproperty bool Library::install If \c{true}, the library will be installed to \l{Library::installDir}{installDir}. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string Library::installDir Where to install the library, if \l{Library::install}{install} is enabled. On Unix, the symbolic links are also installed to this location. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \c Library/Frameworks if the library is a \l{bundle::isBundle}{bundle}, otherwise \c bin for Windows and \c lib for Unix-like targets. \since Qbs 1.13 */ /*! \qmlproperty bool Library::installDebugInformation If \c{true}, the debug information will be installed to \l{Library::debugInformationInstallDir}{debugInformationInstallDir}. \defaultvalue \c false \since Qbs 1.16 \sa{How do I separate and install debugging symbols?} */ /*! \qmlproperty string Library::debugInformationInstallDir Where to install the debug information if \l installDebugInformation is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \l installDir. \since Qbs 1.16 \sa{How do I separate and install debugging symbols?} */ /*! \qmlproperty bool Library::installImportLib If \c{true}, the import library will be installed to \l importLibInstallDir. This property is only relevant for Windows targets. Enable it if you want to create a development package. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string Library::importLibInstallDir Where to install the import library, if \l installImportLib is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. This property is only relevant for Windows targets. \defaultvalue \c lib \since Qbs 1.13 */ qbs-src-3.3.1/doc/reference/items/convenience/appleapplicationdiskimage.qdoc0000644000175100017510000001017215232633614026677 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \nextpage AppleDiskImage \qmltype AppleApplicationDiskImage \since Qbs 1.9 \inherits AppleDiskImage \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AppleApplicationDiskImage \brief Apple application drag 'n' drop disk image installer. An AppleApplicationDiskImage item is a \l{Product}{product} of the \l{Product::}{type} \c{"dmg.dmg"} that has a dependency on the \l{dmg} module. In addition, it has rules and properties specific to building drag 'n' drop disk image installers with an application bundle and symbolic link to the \c /Applications directory. Any artifacts of product dependencies that are tagged \c{"installable"} will be copied into the disk image, provided their file paths are relative to the path specified by the \l{sourceBase} property (that is, are located in that directory). Any artifacts tagged \c{"installable"} that are not relative to \l{sourceBase} will be ignored. Here is what the project file could look like for a simple DMG installer: \code AppleApplicationDiskImage { Depends { name: "myapp" } name: "My App" dmg.volumeName: name dmg.iconSize: 128 dmg.windowWidth: 640 dmg.windowHeight: 280 dmg.iconPositions: [ {"path": "Applications", "x": 128, "y": 128}, {"path": "My App.app", "x": 256, "y": 128} ] files: ["background.tiff", "volume-icon.icns"] Group { files: ["*.lproj/**"] // licenses fileTags: ["dmg.license.input"] } } \endcode For plain disk images whose contents are not a single application bundle, consider the base \l{AppleDiskImage} item instead. */ /*! \qmlproperty string AppleApplicationDiskImage::sourceBase The base directory from which artifacts installed into the disk image will be copied. This directory is always considered to be relative to \l{qbs::installRoot} {qbs.installRoot}/\l{qbs::installPrefix} {qbs.installPrefix}. For example, if the application Example.app exists at \c{qbs.installRoot/qbs.installPrefix/Applications/Example.app}, and the value of this property is \c{"/Applications"}, the application will be located at \c{/Example.app} relative to the disk image root. Therefore, its full path when the disk image is mounted would be something like \c{/Volumes/Example-1.0/Example.app}. \defaultvalue \c{"/Applications"} */ /*! \qmlproperty stringList AppleApplicationDiskImage::symlinks List of symlinks to create in the disk image. This is specified as a list of strings, each string containing two file paths separated by a colon. The first path is the symlink target, and the second path is the name of the symlink relative to the root of the disk image. \defaultvalue \c{["/Applications:Applications"]} */ qbs-src-3.3.1/doc/reference/items/convenience/cppapplication.qdoc0000644000175100017510000000323515232633614024504 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage AutotestRunner \nextpage CppStd \qmltype CppApplication \inherits Application \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.CppApplication \brief C++ application. A CppApplication is an \l{Application}{application} that has a dependency on the \l{cpp} module. It is entirely equivalent to the following: \code Application { Depends { name: "cpp" } } \endcode */ qbs-src-3.3.1/doc/reference/items/convenience/applicationextension.qdoc0000644000175100017510000000331415232633614025734 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Application \nextpage AutotestRunner \qmltype ApplicationExtension \inherits XPCService \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.ApplicationExtension \brief Application Extension for iOS, macOS, tvOS, or watchOS. An ApplicationExtension item is a \l{Product} based on the \l{XPCService} item that sets some properties required for iOS, macOS, tvOS, or watchOS Application Extensions. */ qbs-src-3.3.1/doc/reference/items/convenience/applediskimage.qdoc0000644000175100017510000000335515232633614024460 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage AppleApplicationDiskImage \nextpage Application \qmltype AppleDiskImage \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AppleDiskImage \brief Apple disk image. An AppleDiskImage item is a is a \l{Product}{product} of the \l{Product::} {type} \c{"dmg.dmg"} that has a dependency on the \l{dmg} module. For single-application drag 'n' drop disk image installers, you will probably want to use the \l{AppleApplicationDiskImage} item instead. */ qbs-src-3.3.1/doc/reference/items/convenience/xpcservice.qdoc0000644000175100017510000000317015232633614023647 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage StaticLibrary \qmltype XPCService \inherits Application \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.XPCService \brief XPC service for macOS, iOS, tvOS, or watchOS. An XPCService item is a convenience item based on \l Application that sets some properties required for macOS, iOS, tvOS, or watchOS XPC services. */ qbs-src-3.3.1/doc/reference/items/convenience/dynamiclibrary.qdoc0000644000175100017510000000350715232633614024511 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage CppStd \nextpage InnoSetup \qmltype DynamicLibrary \inherits CppLibrary \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.DynamicLibrary \brief Dynamic library. A DynamicLibrary item is a \l{CppLibrary}{library} of the \l{Product::}{type} \c "dynamiclibrary". For Android targets, the following applies: \list \li The \l{Product::type}{Product.type} property value contains \c "android.nativelibrary" in addition to \c "dynamiclibrary". \li There is a dependency on the \l{cpp} and \l{Android.ndk} modules. \endlist */ qbs-src-3.3.1/doc/reference/items/convenience/application.qdoc0000644000175100017510000000646615232633614024012 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage AppleDiskImage \nextpage ApplicationExtension \qmltype Application \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.Application \brief Product of the type application. An Application item is a \l{Product} representing an application. The target artifact of this type of product is usually an executable binary tagged \c "application". However, on Android, unless you set \l{Product::}{consoleApplication} to \c true, the application target will be an APK or an AAB package tagged \c "android.package" according to the \l{Android.sdk}{packageType} property. A dependency to the \l{Android.sdk} module is automatically added to the product. */ /*! \qmlproperty bool Application::install If \c{true}, the executable that is produced when building the application will be installed to \l{Application::installDir}{installDir}. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string Application::installDir Where to install the executable that is produced when building the application, if \l{Application::install}{install} is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \c Applications if the app is a \l{bundle::isBundle}{bundle}, \c bin otherwise. \since Qbs 1.13 */ /*! \qmlproperty bool Application::installDebugInformation If \c{true}, the debug information will be installed to \l{Application::debugInformationInstallDir}{debugInformationInstallDir}. \defaultvalue \c false \since Qbs 1.16 \sa{How do I separate and install debugging symbols?} */ /*! \qmlproperty string Application::debugInformationInstallDir Where to install the debug information if \l installDebugInformation is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \l installDir. \since Qbs 1.16 \sa{How do I separate and install debugging symbols?} */ qbs-src-3.3.1/doc/reference/items/convenience/qtguiapplication.qdoc0000644000175100017510000000314015232633614025046 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage QtApplication \nextpage QtLupdateRunner \qmltype QtGuiApplication \inherits QtApplication \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.QtGuiApplication \brief Application with a dependency on the Qt GUI module. A QtGuiApplication is an application that extends the \l{QtApplication} item by loading the \l{Qt.gui} module. */ qbs-src-3.3.1/doc/reference/items/convenience/cppstd.qdoc0000644000175100017510000000400715232633614022771 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage CppApplication \nextpage DynamicLibrary \qmltype CppStd \inherits StaticLibrary \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.CppStd \brief A helper product for building C++ std modules. The dependencies of this product gain access to the \c{std} named \l{https://en.cppreference.com/w/cpp/standard_library.html}{module}. An example usage: \code Project { CppStd {} CppApplication { Depends { name: "CppStd" } } } \endcode See the \l{tutorial-10.html}{C++20 Modules} page in the tutorial for details. \since Qbs 3.1 */ /*! \qmlproperty bool CppStd::useStdCompat Whether to build the \c{std.compat} module. \defaultvalue \c false \since Qbs 3.1 */ qbs-src-3.3.1/doc/reference/items/convenience/loadablemodule.qdoc0000644000175100017510000000352415232633614024450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage Library \nextpage ObjectLibrary \qmltype LoadableModule \inherits DynamicLibrary \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.LoadableModule \brief Loadable module. A LoadableModule item is a \l{Product}{product} of the \l{Product::}{type} \c{"loadablemodule"}. It exists for the convenience of project file authors. Unlike the \l{Plugin} item, the LoadableModule item cannot be build as static library and is installed into the same directory as \l{DynamicLibrary} items. Prefer using \l{Plugin} item in new code. */ qbs-src-3.3.1/doc/reference/items/convenience/qtapplication.qdoc0000644000175100017510000000335515232633614024351 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage ObjectLibrary \nextpage QtGuiApplication \qmltype QtApplication \inherits CppApplication \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.QtApplication \brief Application with a dependency on the Qt Core module. A QtApplication is a \l{CppApplication}{C++ application} that has a \l{Depends}{dependency} on the \l{Qt.core} module. It is entirely equivalent to the following: \code CppApplication { Depends { name: "Qt.core" } } \endcode */ qbs-src-3.3.1/doc/reference/items/convenience/configinstall.qdoc0000644000175100017510000001140315232633614024326 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage ConfigBuild \nextpage CppApplication \qmltype ConfigInstall \inqmlmodule QbsConvenienceItems \ingroup list-of-items \since Qbs 3.1 \brief This is the base item for the \l{config.install} module. This items contains properties that configure built-in items such as \l{Application}, \l{Library}, and \l{Plugin}. */ /*! \qmlproperty string ConfigInstall::applicationsDirectory The directory where application bundles should be installed on Apple platforms. \defaultvalue \l{installpaths::applications}{installpaths.applications} */ /*! \qmlproperty string ConfigInstall::binariesDirectory The directory where binaries should be installed. \defaultvalue \l{installpaths::bin}{installpaths.bin} */ /*! \qmlproperty string ConfigInstall::debugInformationDirectory The directory where debug information should be installed. If not set, the value is auto-detected based on item type installing debug info into the same folder as the main artifact. \nodefaultvalue */ /*! \qmlproperty string ConfigInstall::dynamicLibrariesDirectory The directory where dynamic libraries should be installed. \defaultvalue \l{installpaths::bin}{installpaths.bin} on Windows, \l{installpaths::lib}{installpaths.lib} otherwise */ /*! \qmlproperty string ConfigInstall::frameworksDirectory The directory where frameworks should be installed. \defaultvalue \l{installpaths::library}{installpaths.library} + \c{"/"} + \l{installpaths::frameworks}{installpaths.frameworks} */ /*! \qmlproperty string ConfigInstall::importLibrariesDirectory The directory where import libraries should be installed. \defaultvalue \l{installpaths::lib}{installpaths.lib} */ /*! \qmlproperty bool ConfigInstall::install Controls whether products should be installed by default. \defaultvalue \c true */ /*! \qmlproperty bool ConfigInstall::debugInformation Controls whether debug information should be installed. \defaultvalue \l{install} */ /*! \qmlproperty bool ConfigInstall::dynamicLibraries Controls whether dynamic libraries should be installed. \defaultvalue \l{install} */ /*! \qmlproperty bool ConfigInstall::frameworks Controls whether frameworks should be installed. \defaultvalue \l{install} */ /*! \qmlproperty bool ConfigInstall::importLibraries Controls whether import libraries should be installed (relevant for Windows dynamic libraries). \defaultvalue \c false */ /*! \qmlproperty bool ConfigInstall::loadableModules Controls whether loadable modules should be installed. \defaultvalue \l{install} */ /*! \qmlproperty bool ConfigInstall::plugins Controls whether plugins should be installed. \defaultvalue \l{install} */ /*! \qmlproperty bool ConfigInstall::staticLibraries Controls whether static libraries should be installed. \defaultvalue \c false */ /*! \qmlproperty string ConfigInstall::loadableModulesDirectory The directory where loadable modules should be installed. \defaultvalue \l{installpaths::library}{installpaths.library} + \c{"/"} + \l{installpaths::frameworks}{installpaths.frameworks} */ /*! \qmlproperty string ConfigInstall::pluginsDirectory The directory where plugins should be installed. \defaultvalue \l{installpaths::plugins}{installpaths.plugins} */ /*! \qmlproperty string ConfigInstall::staticLibrariesDirectory The directory where static libraries should be installed. \defaultvalue \l{installpaths::lib}{installpaths.lib} */ qbs-src-3.3.1/doc/reference/module-providers/0000755000175100017510000000000015232633614020506 5ustar runnerrunnerqbs-src-3.3.1/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc0000644000175100017510000001107715232633614027154 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype qbspkgconfig \inqmlmodule QbsModuleProviders \since 1.20 \brief Module provider based on the qbspkg-config library. \QBS uses a built-in parser of the \c{*.pc} files and does not require the presence of the \c pkg-config tool in the system. However, if the \c pkg-config tool is present, \QBS will use the same libDirs as the system pkg-config uses by default; otherwise, a built-in list of paths is used. In order to enable usage of this provider in your Product, set the \l{Product::qbsModuleProviders}{qbsModuleProviders} property as shown in the example below: \snippet ../examples/pkgconfig-provider/pkgconfig-provider.qbs 0 */ /*! \qmlproperty string qbspkgconfig::executableFilePath The path to the \c {pkg-config} executable. If not set, the pkg-config from PATH is used. \defaultvalue undefined */ /*! \qmlproperty stringList qbspkgconfig::libDirs Set this if you need to overwrite the default search directories. \note You do not need to set this for cross-compilation in order to point to the sysroot. \QBS does that for you. This property is the equivalent of the \c{PKG_CONFIG_LIBDIR} variable for the \c{pkg-config} tool. \nodefaultvalue */ /*! \qmlproperty stringList qbspkgconfig::extraPaths Set this if you need to add extra search directories. This property is the equivalent of the \c{PKG_CONFIG_PATH} variable for the \c{pkg-config} tool. \nodefaultvalue */ /*! \qmlproperty bool qbspkgconfig::staticMode If this property is \c true, then \QBS will include "private" libs and dependencies of the package. This property is the equivalent of the \c{--static} option for the \c{pkg-config} tool. Set this if your product is to be linked statically. \defaultvalue \c false */ /*! \qmlproperty bool qbspkgconfig::definePrefix If this property is \c true, then \QBS will override the ${prefix} variable in the packages with a value that is guessed based on the location of the .pc file. This option corresponds to the \c --define-prefix / \c --dont-define-prefix command line options of the \c pkg-config tool. \defaultvalue \c true on Windows, \c false otherwise */ /*! \qmlproperty stringList qbspkgconfig::executableNames The names of the \c pkg-config executable to search for. Note that since newer distributions use \l{http://pkgconf.org}{pkgconf} by default, it has higher priority over \c pkg-config. \defaultvalue \c{["pkgconf", "pkg-config"]} */ /*! \qmlproperty path qbspkgconfig::sysroot Set this property if you need to overwrite the default search sysroot path used by \c pkg-config. This can be useful if \c pkg-config files are located in the directory other than qbs.sysroot. This is the case on macOS platform - all XCode profiles are sysrooted to the SDK directory, but \c pkg-config is typically intalled using Brew and resides in the \c /usr/local directory. Setting this property to \c undefined or empty (\c "") value will use pkg-config's default search paths: \code qbs resolve moduleProviders.qbspkgconfig.sysroot:undefined \endcode This property is the equivalent of the \c{PKG_CONFIG_SYSROOT_DIR} variable for the \c{pkg-config} tool. \defaultvalue \c "" on macOS, \c qbs.sysroot on other platforms */ qbs-src-3.3.1/doc/reference/module-providers/qt-module-provider.qdoc0000644000175100017510000000575015232633614025124 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype Qt \inqmlmodule QbsModuleProviders \brief Module provider that generates Qt modules. Looking up a Qt installation happens via a \l{Module Providers}{module provider}. By default, if a dependency to a Qt module is encountered, \QBS collects all Qt installations it can find. This lookup happens by searching for \c qmake executables in the \c PATH environment variable. Alternatively, you can explicitly tell \QBS which Qt installations it should consider by setting the qmakeFilePaths module provider \l{Parameterizing Module Providers}{property}. In that case, the environment will be ignored. For instance, with the following Linux command line, \QBS will build the project against a custom Qt instead of the standard one in \c{/usr/bin}: \code $ qbs moduleProviders.Qt.qmakeFilePaths:/opt/myqt/bin/qmake \endcode You can also set the module provider property in a profile. The simplest way to do this is via the \l setup-qt tool. For examples of how to use this tool, see the \l{Managing Qt Versions} section. This provider is activated automatically when encountering a dependency on the Qt module and the \l{Product::qbsModuleProviders}{qbsModuleProviders} property is \c undefined: \code CppApplication { Depends { name: "Qt.core" } files: "main.cpp" } \endcode Alternatively, you can activate this provider explicitly via the \l{Product::qbsModuleProviders}{qbsModuleProviders} property: \code CppApplication { Depends { name: "Qt.core" } files: "main.cpp" qbsModuleProviders: "Qt" } \endcode */ /*! \qmlproperty stringList Qt::qmakeFilePaths List of paths to \c qmake executables. \defaultvalue undefined */ qbs-src-3.3.1/doc/reference/module-providers/conan-module-provider.qdoc0000644000175100017510000000652015232633614025572 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \qmltype conan \inqmlmodule QbsModuleProviders \since 2.4 \brief Module provider for the Conan package manager. This module provider allows integration with the \l{https://conan.io}{Conan} package manager. \section1 Prerequisites In order to use this provider, you will need \c Conan version 2.5.0 or higher. Earlier versions do not have the \c QbsDeps generator. \section1 Example For details on how to setup a project to use with Conan, see the \ l{https://github.com/qbs/qbs/blob/master/examples/protobuf/addressbook_conan}{addressbook_conan} folder in examples. First, you will need a \l{https://docs.conan.io/2/reference/conanfile_txt.html}{conanfile} as shown below. \code [requires] protobuf/3.21.12 [tool_requires] protobuf/3.21.12 [generators] QbsDeps \endcode We use the text version for simplicity, but you can use the Python conanfile as well. Next, set the \l{Product::qbsModuleProviders}{qbsModuleProviders} property to \c "conan": \snippet ../examples/protobuf/addressbook_conan/addressbook_conan.qbs 0 Install Conan dependencies and run the QbsDeps generator from the \c addressbook_conan dir: \code $ conan install . -g=QbsDeps --output-folder=build --build missing \endcode This will create the \c{./build/qbs-deps} directory contaning files for provider. Now you can pass the conan install directory to the provider: \code $ qbs moduleProviders.conan.installDirectory:build \endcode You should see the following output if everything is correct: \code Build graph does not yet exist for configuration 'default'. Starting from scratch. Resolving project for configuration default Setting up Conan module 'protobuflib' Setting up Conan module 'zlib' ... Build done for configuration default. \endcode */ /*! \qmlproperty string conan::installDirectory The path to the conan install installDirectory. \QBS searches for files created by the QbsDeps generator in that directory. If not set, the provider will not be run. \defaultvalue undefined */ qbs-src-3.3.1/doc/qbs.qdocconf0000644000175100017510000000015115232633614015550 0ustar runnerrunnerinclude(config/qbs-project.qdocconf) include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf) qbs-src-3.3.1/doc/targets/0000755000175100017510000000000015232633614014721 5ustar runnerrunnerqbs-src-3.3.1/doc/targets/qbs-target-linux.qdoc0000644000175100017510000000266715232633614021012 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-linux.html \ingroup platforms \title Building for Linux \brief Platform notes for Linux. To develop applications for Linux, you need a GCC or Clang toolchain installed on your host machine. */ qbs-src-3.3.1/doc/targets/qbs-target-tvos.qdoc0000644000175100017510000000321015232633614020627 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-tvos.html \ingroup platforms \title Building for tvOS \brief Platform notes for tvOS. This topic describes the \QBS features specific to tvOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-3.3.1/doc/targets/qbs-target-vxworks.qdoc0000644000175100017510000000314715232633614021370 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-vxworks.html \ingroup platforms \title Building for VxWorks \brief Platform notes for VxWorks. The Wind River VxWorks RTOS is not yet supported but is planned for a future release. For more information about developing applications for the WindRiver VxWorks RTOS, see the \l{https://www.windriver.com/products/vxworks/} {VxWorks Product Documentation}. */ qbs-src-3.3.1/doc/targets/qbs-target-watchos.qdoc0000644000175100017510000000322415232633614021311 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-watchos.html \ingroup platforms \title Building for watchOS \brief Platform notes for watchOS. This topic describes the \QBS features specific to watchOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-3.3.1/doc/targets/qbs-target-qnx.qdoc0000644000175100017510000000522515232633614020452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-qnx.html \ingroup platforms \title Building for QNX \brief Platform notes for QNX. To develop applications for the QNX Neutrino RTOS, you need to install the QNX Software Development Platform (SDP) on a Linux, macOS, or Windows development host. You can deploy the QNX Neutrino RTOS on a target system, such as embedded hardware, a virtual machine, or a PC. \QBS automatically determines the location of the SDP base directory if the SDP is installed at one of the standard locations, such as \c ~/qnx700, \c /opt/qnx700, or \c C:\qnx700. In addition, \QBS uses the SDP and the information it has about the host operating system to determine the location of the QNX host and target directories. If the QNX SDP path could not be determined automatically, you must add a dependency to the \l{qnx} module to your application and set the \l{qnx::sdkDir}{qnx.sdkDir} property: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } Depends { name: "qnx" } qnx.sdkDir: "/path/to/qnx700" } \endcode Alternatively, you can set the \c qnx.sdkDir property in a profile or on the command line. \QBS supports QNX SDP version 6.5 and above. For more information about developing applications for the QNX Neutrino RTOS, see the \l{http://www.qnx.com/developers/docs/} {QNX Product Documentation}. */ qbs-src-3.3.1/doc/targets/qbs-target-windows.qdoc0000644000175100017510000000601315232633614021332 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-windows.html \ingroup platforms \title Building for Windows \brief Platform notes for Windows. This topic describes the \QBS features specific to Windows. \note \QBS does not currently support building applications using .NET technologies and languages such as C#, F#, and Visual Basic. At this time we recommend that you use MSBuild and the tools shipped with the various implementations of the .NET platform. \section1 Windows Resources The \l{ico} module contains rules and properties for building Windows icon (.ico) and cursor (.cur) files from a set of raw PNGs. \section1 Universal Windows Platform Building applications for the Universal Windows Platform is currently only partially supported. Notably, support for building APPX packages is missing, but will be added in a future release. Relevant properties include: \list \li \l{cpp::windowsApiFamily}{cpp.windowsApiFamily} \li \l{cpp::windowsApiAdditionalPartitions} {cpp.windowsApiAdditionalPartitions} \li \l{cpp::requireAppContainer}{cpp.requireAppContainer} \endlist See the \l{cpp} module for more information. \note \QBS does not (and will not) support building Windows Runtime applications targeting Windows 8 or Windows 8.1. We encourage users to instead build desktop applications for older versions of Windows, or migrate to Windows 10 and the Universal Windows Platform. \section1 Building Windows Installers The following modules contain properties and rules for building Windows installers using a number of different technologies: \list \li \l{innosetup} - Inno Setup \li \l{nsis} - Nullsoft Scriptable Install System \li \l{wix} - Windows Installer XML Toolset \endlist */ qbs-src-3.3.1/doc/targets/qbs-target-apple-common.qdocinc0000644000175100017510000001010015232633614022711 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [xcode] \note \QBS does not yet support the Swift programming language. The \l{xcode} module contains properties and rules for Xcode-based development. //! [xcode] //! [building user interfaces] \section1 Building User Interfaces The \l{ib} module contains properties and rules for building Interface Builder documents, storyboards, asset catalogs, and icon sets. //! [building user interfaces] //! [creating app bundles] \section1 Creating App Bundles The \l{bundle} module contains properties and rules for building and working with Core Foundation bundles (application bundles and frameworks) on Apple platforms. To build an application product as a bundle, or a dynamic or static library product as a framework, add a dependency on the bundle module and set the \l{bundle::isBundle}{bundle.isBundle} property to \c true: \code Depends { name: "bundle" } bundle.isBundle: true \endcode \QBS also provides a number of powerful features to assist in creating the Info.plist file that is part of your bundle. In fact, you do not need to provide an Info.plist file at all. Instead, \QBS will generate one automatically with the necessary keys, based on the values of module properties set in the product. If you do specify an Info.plist file, \QBS may still inject additional keys into the final output from other sources. One notable source of Info.plist keys are \e partial Info.plist files which are generated as a result of compiling other resources like asset catalogs, XIBs/NIBs, and storyboards. You may also use the \c bundle.infoPlist property to apply a set of key-value pairs to be added to the final Info.plist. This can be used instead of or in addition to an actual Info.plist file on disk. //! [creating app bundles] //! [architectures and variants] \section1 Multiple Architectures and Build Variants \QBS uses \l{Multiplexing}{multiplexing} to create multi-architecture \e fat binaries and multi-variant frameworks, where a single framework can contain both a release and debug build of a library on Apple platforms. You can set the \c qbs.architectures property to a list of CPU architectures (such as \c x86, \c x86_64, \c armv7a, \c armv7k, and \c arm64), and the \c qbs.buildVariants property to a list of build variants (such as \c debug and \c release), and \QBS will transparently perform the necessary steps to produce the various artifacts and combine them into a single bundle. Since the individual build configurations are completely independent of one another, you can continue to use conditional branches in your projects such as the following: \code Properties { condition: qbs.buildVariant === "release" cpp.optimization: "small" } \endcode //! [architectures and variants] */ qbs-src-3.3.1/doc/targets/qbs-target-platforms.qdoc0000644000175100017510000000427115232633614021653 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \previouspage installing-files.html \group platforms \nextpage shell.html \title Target Platforms \QBS has built-in support for building applications for all major platforms. Platform support is implemented as a set of \l{List of Modules}{modules} that products depend on. The following topics describe the features specific to a particular platform, point out things to look out for, and provide tips for fully benefiting from the \QBS functions. In addition to the platforms explicitly listed below, \QBS should generally work on other UNIX and Unix-like platforms but these are not regularly tested or officially supported. \QBS recognizes the existence of at least AIX, HP-UX, Solaris, FreeBSD, NetBSD, OpenBSD, GNU Hurd, and Haiku, but provides no explicit support (except some minimal support for FreeBSD). For instructions on how to setup the target platform, see the \l {qbs::targetPlatform}{qbs.targetPlatform} property. */ qbs-src-3.3.1/doc/targets/qbs-target-android.qdoc0000644000175100017510000000622115232633614021261 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-android.html \ingroup platforms \title Building for Android \brief Platform notes for Android. To develop applications for Android, you need development tools provided by the Android SDK from Google, and (optionally) a C/C++ toolchain provided by the Android NDK. \note \QBS does not yet support the Kotlin programming language. \section1 Creating Android Application Packages On Android, applications are distributed in a specially structured type of ZIP package called an APK. The following files should be created and bundled into an APK: \list \li Android assets. \li Android resource files. \li AndroidManifest.xml, which provides meta-information about your application. \li Compiled Java code, which serves as the entry point into your application and that automatically executes the native code in your application (if there is any). \li Shared libraries containing native code. \endlist You can use the \l{Application} item to build application packages for Android. If the \l{qbs::targetPlatform}{target platform} is \c{"android"}, then the Application item has a dependency on the \l{Android.sdk} module, which contains the properties and rules to create Android application packages from source files. You can use the \l{DynamicLibrary} item to build native Android libraries that are bundled into the APK. The \c qbs.architectures property specifies the architectures to build for, with the default value \c armv7a. If you have only one native library, you can simply list its sources within the main Application item, and it will get built and packaged automatically. The \l{DynamicLibrary} item, as well as the \l CppApplication item, has a dependency on the \l{Android.ndk} module, and contains the properties and rules to create native libraries. */ qbs-src-3.3.1/doc/targets/qbs-target-ios.qdoc0000644000175100017510000000320415232633614020431 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-ios.html \ingroup platforms \title Building for iOS \brief Platform notes for iOS. This topic describes the \QBS features specific to iOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-3.3.1/doc/targets/qbs-target-macos.qdoc0000644000175100017510000000620015232633614020740 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-macos.html \ingroup platforms \title Building for macOS \brief Platform notes for macOS. This topic describes the \QBS features specific to macOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants \section1 Building macOS Disk Images The \l{AppleDiskImage} and \l{AppleApplicationDiskImage} items have a dependency on the \l{dmg} module. The former represents a product that is a basic Apple disk image, while the latter extends the former to create a drag 'n' drop disk image installer used for installing single application bundles. For example, the following code snippet creates a macOS disk image with a custom background and icon layout: \code AppleApplicationDiskImage { targetName: "cocoa-application-" + version version: "1.0" files: [ "CocoaApplication/dmg.iconset", "CocoaApplication/en_US.lproj/LICENSE", // comment out the following line to use a solid-color background // (see dmg.backgroundColor below) "CocoaApplication/background*" ] dmg.backgroundColor: "#41cd52" dmg.badgeVolumeIcon: true dmg.iconPositions: [ {"x": 200, "y": 200, "path": "Cocoa Application.app"}, {"x": 400, "y": 200, "path": "Applications"} ] dmg.windowX: 420 dmg.windowY: 250 dmg.windowWidth: 600 dmg.windowHeight: 422 // this includes the macOS title bar height of 22 dmg.iconSize: 64 } \endcode \image qbs-dmg.png In addition, \QBS supports multi-language license agreement prompts that appear when the DMG is opened, with full Unicode and rich-text formatting support. */ qbs-src-3.3.1/doc/targets/qbs-target-integrity.qdoc0000644000175100017510000000317315232633614021662 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qbs-target-integrity.html \ingroup platforms \title Building for INTEGRITY \brief Platform notes for INTEGRITY. The Green Hills INTEGRITY RTOS is not yet supported but is planned for a future release. For more information about developing applications for the Green Hills INTEGRITY RTOS, see the \l{https://www.ghs.com/products/rtos/integrity.html} {INTEGRITY Product Documentation}. */ qbs-src-3.3.1/docker/0000755000175100017510000000000015232633614013752 5ustar runnerrunnerqbs-src-3.3.1/docker/noble/0000755000175100017510000000000015232633614015051 5ustar runnerrunnerqbs-src-3.3.1/docker/noble/test-baremetal.Dockerfile0000644000175100017510000000300115232633614021745 0ustar runnerrunner# # Baremetal toolchains for testing Qbs # FROM ubuntu:noble LABEL Description="Ubuntu baremetal test environment for Qbs" # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # Install baremetal toolchains and Qbs runtime dependencies. RUN apt-get update -qq && \ apt-get install -qq -y \ libasan5 \ libglib2.0-0 \ libgssapi-krb5-2 \ gcc-arm-none-eabi \ gcc-avr \ avr-libc \ sdcc \ binutils-xtensa-lx106 \ gcc-xtensa-lx106 \ gcc-riscv64-unknown-elf # Work-around for QTBUG-79020. RUN echo "export QT_NO_GLIB=1" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/noble/Dockerfile0000644000175100017510000000774015232633614017053 0ustar runnerrunner# # Install Qt and Qbs for Linux # FROM ubuntu:noble LABEL Description="Ubuntu development environment for Qbs with Qt and various dependencies for testing Qbs modules and functionality" ARG QT_VERSION ARG QBS_VERSION # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # Qbs build dependencies RUN apt-get update -qq && \ DEBIAN_FRONTEND="noninteractive" apt-get install -qq -y --no-install-recommends \ bison \ build-essential \ ca-certificates \ capnproto \ ccache \ clang-18 \ clang-tidy-18 \ cmake \ curl \ flex \ git \ gdb \ help2man \ icoutils \ libcapnp-dev \ libc++-18-dev \ libclang-rt-18-dev \ libdbus-1-3 \ libfreetype6 \ libfontconfig1 \ libgl1-mesa-dev \ libnanopb-dev \ libprotobuf-dev \ libgrpc++-dev \ libxkbcommon-x11-0 \ locales \ nanopb \ ninja-build \ nsis \ pkg-config \ protobuf-compiler \ protobuf-compiler-grpc \ psmisc \ python3-pip \ python3-setuptools \ python3-venv \ p7zip-full \ subversion \ unzip \ zip && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100 && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100 && \ update-alternatives --install /usr/bin/clang-check clang-check /usr/bin/clang-check-18 100 && \ update-alternatives --install /usr/bin/python python /usr/bin/python3 100 ENV LLVM_INSTALL_DIR=/usr/lib/llvm-18 # Set up Python RUN python3 -m venv /venv && \ /venv/bin/pip3 install beautifulsoup4 lxml protobuf==3.19.1 pyyaml conan mercurial ENV PATH=/venv/bin:${PATH} # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 # # Install Qt and Qbs for Linux from qt.io # COPY scripts/install-qt.sh install-qt.sh COPY scripts/install-qbs.sh install-qbs.sh RUN ./install-qt.sh --version ${QT_VERSION} qtbase qtdeclarative qttools qtx11extras qtscxml qtshadertools qt5compat icu && \ ./install-qbs.sh --version ${QBS_VERSION} && \ echo "export PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/qbs/qbs-linux-x86_64-${QBS_VERSION}/bin:\${PATH}" > /etc/profile.d/qt.sh ENV PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/qbs/qbs-linux-x86_64-${QBS_VERSION}/bin:${PATH} # Configure Qbs USER $USER_NAME RUN qbs-setup-toolchains /usr/bin/g++ gcc && \ qbs-setup-toolchains /usr/bin/clang clang && \ qbs-setup-qt /opt/Qt/${QT_VERSION}/gcc_64/bin/qmake qt-gcc_64 && \ qbs config profiles.qt-gcc_64.baseProfile gcc && \ qbs-setup-qt /opt/Qt/${QT_VERSION}/gcc_64/bin/qmake qt-clang_64 && \ qbs config profiles.qt-clang_64.baseProfile clang && \ qbs config defaultProfile qt-gcc_64 # Configure Conan RUN conan profile detect --name qbs-test # Switch back to root user for the entrypoint script. USER root # Work-around for QTBUG-79020 RUN echo "export QT_NO_GLIB=1" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/noble/test-android-no-qt.Dockerfile0000644000175100017510000001040715232633614022475 0ustar runnerrunner# # Android SDK/NDK for testing Qbs # FROM ubuntu:noble LABEL Description="Ubuntu test environment for Qbs for Android" # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # Qbs build dependencies RUN apt-get update -qq && \ apt-get install -qq -y --no-install-recommends \ ca-certificates \ curl \ gdb \ libasan5 \ libglib2.0-0 \ openjdk-8-jdk-headless \ p7zip-full \ unzip ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 RUN echo "export JAVA_HOME=${JAVA_HOME}" > /etc/profile.d/android.sh && \ echo "export PATH=${JAVA_HOME}/bin:\${PATH}" >> /etc/profile.d/android.sh ARG ANDROID_NDK_VERSION ENV ANDROID_HOME="/home/${USER_NAME}/android" ENV ANDROID_SDK_ROOT=${ANDROID_HOME} ENV ANDROID_NDK_ROOT=${ANDROID_HOME}/"ndk"/${ANDROID_NDK_VERSION} ENV PATH="${JAVA_HOME}:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/cmdline-tools/bin:$PATH" RUN echo "export ANDROID_HOME=/home/${USER_NAME}/android" >> /etc/profile.d/android.sh && \ echo "export ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}" >> /etc/profile.d/android.sh && \ echo "export ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT}" >> /etc/profile.d/android.sh && \ echo "export PATH=${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/cmdline-tools/bin:\$PATH" >> /etc/profile.d/android.sh # # We ned to run the following steps as the target user # USER ${USER_NAME} RUN mkdir ${ANDROID_HOME} # Get Android command line tools ARG COMMAND_LINE_TOOLS_VERSION="6858069" RUN curl -s https://dl.google.com/android/repository/commandlinetools-linux-${COMMAND_LINE_TOOLS_VERSION}_latest.zip > ${ANDROID_HOME}/commandlinetools.zip && \ unzip ${ANDROID_HOME}/commandlinetools.zip -d ${ANDROID_HOME} && \ rm -v ${ANDROID_HOME}/commandlinetools.zip # Accept SDK license ARG ANDROID_PLATFORM="android-29" ARG BUILD_TOOLS="29.0.2" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" --verbose --licenses && \ sdkmanager "--sdk_root=${ANDROID_HOME}" --update && \ sdkmanager "--sdk_root=${ANDROID_HOME}" "platforms;${ANDROID_PLATFORM}" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "build-tools;${BUILD_TOOLS}" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "platform-tools" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "tools" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "ndk;${ANDROID_NDK_VERSION}" RUN /usr/lib/jvm/java-8-openjdk-amd64/bin/keytool -genkey -keystore /home/${USER_NAME}/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname 'CN=Android Debug,O=Android,C=US' # Install ndk samples in ${ANDROID_NDK_ROOT}/samples RUN cd ${ANDROID_NDK_ROOT} && \ curl -sLO https://github.com/android/ndk-samples/archive/master.zip && \ unzip -q master.zip && \ rm -v master.zip && \ mv ndk-samples-master samples # Install android-BasicMediaDecoder in ${ANDROID_SDK_ROOT}/samples RUN mkdir ${ANDROID_SDK_ROOT}/samples && \ cd ${ANDROID_SDK_ROOT}/samples && \ curl -sLO https://github.com/googlearchive/android-BasicMediaDecoder/archive/master.zip && \ unzip -q master.zip && \ rm -v master.zip && \ mv android-BasicMediaDecoder-master android-BasicMediaDecoder # Download buildtool to generate aab packages in ${ANDROID_SDK_ROOT} RUN cd ${ANDROID_SDK_ROOT} && \ curl -sLO https://github.com/google/bundletool/releases/download/1.3.0/bundletool-all-1.3.0.jar USER root qbs-src-3.3.1/docker/noble/qt6.5.3-static.patch0000644000175100017510000000556515232633614020410 0ustar runnerrunnerdiff --git a/cmake/FindWrapZSTD.cmake b/cmake/FindWrapZSTD.cmake index fb86c27676..f1613543a4 100644 --- a/cmake/FindWrapZSTD.cmake +++ b/cmake/FindWrapZSTD.cmake @@ -25,14 +25,17 @@ find_package(zstd CONFIG QUIET) include(FindPackageHandleStandardArgs) -if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared) +if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared OR TARGET zstd::libzstd) find_package_handle_standard_args(WrapZSTD REQUIRED_VARS zstd_VERSION VERSION_VAR zstd_VERSION) - if(TARGET zstd::libzstd_static) - set(zstdtargetsuffix "_static") - else() + if(TARGET zstd::libzstd_shared) set(zstdtargetsuffix "_shared") + elseif(TARGET zstd::libzstd) + set(zstdtargetsuffix "") + else() + set(zstdtargetsuffix "_static") endif() + if(NOT TARGET WrapZSTD::WrapZSTD) add_library(WrapZSTD::WrapZSTD INTERFACE IMPORTED) set_target_properties(WrapZSTD::WrapZSTD PROPERTIES diff --git a/configure.cmake b/configure.cmake index be1a4f3bc3..e1ce168d26 100644 --- a/configure.cmake +++ b/configure.cmake @@ -109,8 +109,15 @@ SSL_free(SSL_new(0)); } ") -# special case end -qt_find_package(WrapZSTD 1.3 PROVIDED_TARGETS WrapZSTD::WrapZSTD MODULE_NAME global QMAKE_LIB zstd) +qt_find_package(WrapZSTD 1.3 + PROVIDED_TARGETS + WrapZSTD::WrapZSTD + zstd::libzstd + zstd::libzstd_static + zstd::libzstd_shared + MODULE_NAME global + QMAKE_LIB zstd +) qt_find_package(WrapDBus1 1.2 PROVIDED_TARGETS dbus-1 MODULE_NAME global QMAKE_LIB dbus) qt_find_package(Libudev PROVIDED_TARGETS PkgConfig::Libudev MODULE_NAME global QMAKE_LIB libudev) qt_find_package(LTTngUST PROVIDED_TARGETS LTTng::UST MODULE_NAME core QMAKE_LIB lttng-ust) diff --git a/src/gui/platform/unix/qxkbcommon.cpp b/src/gui/platform/unix/qxkbcommon.cpp index fc014b38e2..0de9e98fc7 100644 --- a/src/gui/platform/unix/qxkbcommon.cpp +++ b/src/gui/platform/unix/qxkbcommon.cpp @@ -239,10 +239,14 @@ static constexpr const auto KeyTbl = qMakeArray( Xkb2Qt, Xkb2Qt, Xkb2Qt, +/* The following four XKB_KEY_dead keys got removed in libxkbcommon 1.6.0 + The define check is kind of version check here. */ +#ifdef XKB_KEY_dead_lowline Xkb2Qt, Xkb2Qt, Xkb2Qt, Xkb2Qt, +#endif // Special keys from X.org - This include multimedia keys, // wireless/bluetooth/uwb keys, special launcher keys, etc. qbs-src-3.3.1/docker/noble/test-qt6-wasm.Dockerfile0000644000175100017510000000465215232633614021505 0ustar runnerrunner# # Testing Qbs with Web Assembly # FROM ubuntu:noble LABEL Description="Ubuntu wasm test environment for Qbs" ARG QT_VERSION ARG EMSCRIPTEN_VERSION # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] RUN sudo apt-get update -qq && \ apt-get install -qq -y \ curl \ libglib2.0-0 \ locales \ p7zip-full \ python3 \ python3-pip \ unzip # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 RUN curl -L https://github.com/emscripten-core/emsdk/archive/refs/heads/main.zip > /emsdk.zip && \ unzip /emsdk.zip && \ rm /emsdk.zip && \ mv /emsdk-main /emsdk && \ cd /emsdk && \ ./emsdk install ${EMSCRIPTEN_VERSION} && \ ./emsdk activate ${EMSCRIPTEN_VERSION} ENV EMSDK=/emsdk \ PATH="/emsdk:/emsdk/upstream/emscripten:/emsdk/node/18.20.3_64bit/bin:${PATH}" # # Install Qt for Wasm from qt.io # COPY scripts/install-qt.sh install-qt.sh RUN ./install-qt.sh --version ${QT_VERSION} qtbase qtdeclarative qttools qtx11extras qtscxml qt5compat icu && \ echo "export PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:\${PATH}" > /etc/profile.d/qt.sh RUN ./install-qt.sh --version ${QT_VERSION} --target wasm --toolchain wasm_multithread qtbase qtdeclarative qttools qtx11extras qtscxml qt5compat icu && \ echo "export PATH=/opt/Qt/${QT_VERSION}/wasm_multithread/bin:\${PATH}" > /etc/profile.d/qt.sh # Work-around for QTBUG-79020 RUN echo "export QT_NO_GLIB=1" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/noble/test-android.Dockerfile0000644000175100017510000001266215232633614021446 0ustar runnerrunner# # Android SDK/NDK + Qt for Android for testing Qbs # FROM ubuntu:noble LABEL Description="Ubuntu test environment for Qbs and Qt for Android" # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # Qbs build dependencies RUN apt-get update -qq && \ apt-get install -qq -y --no-install-recommends \ ca-certificates \ curl \ gdb \ libasan5 \ libglib2.0-0 \ locales \ openjdk-8-jdk-headless \ p7zip-full \ unzip # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 RUN echo "export JAVA_HOME=${JAVA_HOME}" > /etc/profile.d/android.sh && \ echo "export PATH=${JAVA_HOME}/bin:\${PATH}" >> /etc/profile.d/android.sh ARG ANDROID_NDK_VERSION ENV ANDROID_HOME="/home/${USER_NAME}/android" ENV ANDROID_SDK_ROOT=${ANDROID_HOME} ENV ANDROID_NDK_ROOT=${ANDROID_HOME}/"ndk"/${ANDROID_NDK_VERSION} ENV PATH="${JAVA_HOME}:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/cmdline-tools/bin:$PATH" RUN echo "export ANDROID_HOME=/home/${USER_NAME}/android" >> /etc/profile.d/android.sh && \ echo "export ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}" >> /etc/profile.d/android.sh && \ echo "export ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT}" >> /etc/profile.d/android.sh && \ echo "export PATH=${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/cmdline-tools/bin:\$PATH" >> /etc/profile.d/android.sh # # We ned to run the following steps as the target user # USER ${USER_NAME} RUN mkdir ${ANDROID_HOME} # Get Android command line tools ARG COMMAND_LINE_TOOLS_VERSION="6858069" RUN curl -s https://dl.google.com/android/repository/commandlinetools-linux-${COMMAND_LINE_TOOLS_VERSION}_latest.zip > ${ANDROID_HOME}/commandlinetools.zip && \ unzip ${ANDROID_HOME}/commandlinetools.zip -d ${ANDROID_HOME} && \ rm -v ${ANDROID_HOME}/commandlinetools.zip # Accept SDK license ARG ANDROID_PLATFORM="android-30" ARG BUILD_TOOLS="29.0.2" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" --verbose --licenses && \ sdkmanager "--sdk_root=${ANDROID_HOME}" --update && \ sdkmanager "--sdk_root=${ANDROID_HOME}" "platforms;${ANDROID_PLATFORM}" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "build-tools;${BUILD_TOOLS}" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "platform-tools" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "tools" RUN yes | sdkmanager "--sdk_root=${ANDROID_HOME}" "ndk;${ANDROID_NDK_VERSION}" RUN /usr/lib/jvm/java-8-openjdk-amd64/bin/keytool -genkey -keystore /home/${USER_NAME}/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname 'CN=Android Debug,O=Android,C=US' # Install ndk samples in ${ANDROID_NDK_ROOT}/samples RUN cd ${ANDROID_NDK_ROOT} && \ curl -sLO https://github.com/android/ndk-samples/archive/master.zip && \ unzip -q master.zip && \ rm -v master.zip && \ mv ndk-samples-master samples # Install android-BasicMediaDecoder in ${ANDROID_SDK_ROOT}/samples RUN mkdir ${ANDROID_SDK_ROOT}/samples && \ cd ${ANDROID_SDK_ROOT}/samples && \ curl -sLO https://github.com/googlearchive/android-BasicMediaDecoder/archive/master.zip && \ unzip -q master.zip && \ rm -v master.zip && \ mv android-BasicMediaDecoder-master android-BasicMediaDecoder # Download buildtool to generate aab packages in ${ANDROID_SDK_ROOT} RUN cd ${ANDROID_SDK_ROOT} && \ curl -sLO https://github.com/google/bundletool/releases/download/1.3.0/bundletool-all-1.3.0.jar USER root # # Install Qt and Qbs for Linux from qt.io # ARG QT_VERSION COPY scripts/install-qt.sh install-qt.sh RUN if [ "${QT_VERSION}" \< "5.14" ] || [ ! "${QT_VERSION}" \< "6.0.0" ]; then \ QT_ABIS="android_armv7 android_arm64_v8a android_x86 android_x86_64"; \ else \ QT_ABIS="any"; \ fi; \ if [ ! "${QT_VERSION}" \< "6.0.0" ]; then \ ./install-qt.sh --version ${QT_VERSION} qtbase qtdeclarative icu; \ if [ "${QT_VERSION}" \< "6.1.0" ]; then \ QT_COMPONENTS="qtbase qtdeclarative qttools qtquickcontrols2 qtquicktimeline svg"; \ else \ QT_COMPONENTS="qtbase qtdeclarative qttools qtquicktimeline svg"; \ fi; \ else \ QT_COMPONENTS="qtbase qtdeclarative qttools qtimageformats"; \ fi; \ for abi in ${QT_ABIS}; do \ ./install-qt.sh --version ${QT_VERSION} --target android --toolchain ${abi} ${QT_COMPONENTS}; \ done && \ echo "export QT_VERSION=${QT_VERSION}" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/noble/test-qt6-static.Dockerfile0000644000175100017510000002151115232633614022016 0ustar runnerrunner# # Testing Qbs with static qt6 # FROM ubuntu:noble LABEL Description="Ubuntu static qt6 test environment for Qbs" ARG QT_VERSION ARG QTCREATOR_VERSION # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] RUN apt-get update -qq && \ DEBIAN_FRONTEND="noninteractive" apt-get install -qq -y --no-install-recommends \ apt-transport-https \ build-essential \ clang-18 \ cmake \ git \ libassimp-dev \ libb2-dev \ libclang-18-dev \ libdbus-1-dev \ libdrm-dev \ libegl-dev \ libfontconfig1-dev \ libfreetype6-dev \ libglib2.0-dev \ libgstreamer1.0-dev \ libharfbuzz-dev \ libicu-dev \ libjpeg-dev \ libmd4c-html0-dev \ libssl-dev \ libsystemd-dev \ libudev-dev \ libvulkan-dev \ libwayland-dev \ libx11-dev \ libx11-xcb-dev \ libxcb-composite0-dev \ libxcb-cursor-dev \ libxcb-damage0-dev \ libxcb-dpms0-dev \ libxcb-dri2-0-dev \ libxcb-dri3-dev \ libxcb-ewmh-dev \ libxcb-glx0-dev \ libxcb-icccm4-dev \ libxcb-image0-dev \ libxcb-keysyms1-dev \ libxcb-present-dev \ libxcb-present-dev \ libxcb-randr0-dev \ libxcb-record0-dev \ libxcb-render-util0-dev \ libxcb-res0-dev \ libxcb-screensaver0-dev \ libxcb-shape0-dev \ libxcb-shm0-dev \ libxcb-sync-dev \ libxcb-sync0-dev \ libxcb-util-dev \ libxcb-xf86dri0-dev \ libxcb-xfixes0-dev \ libxcb-xinerama0-dev \ libxcb-xinput-dev \ libxcb-xtest0-dev \ libxcb-xv0-dev \ libxcb-xvmc0-dev \ libxcb1-dev \ libxext-dev \ libxfixes-dev \ libxi-dev \ libxkbcommon-dev \ libxkbcommon-x11-dev \ libxrender-dev \ libzstd-dev \ locales \ llvm-18-dev \ ninja-build \ perl \ python3 \ zlib1g-dev # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 ENV QT_HOME="/home/${USER_NAME}/qt" USER ${USER_NAME} RUN mkdir ${QT_HOME} RUN cd ${QT_HOME} && git clone https://code.qt.io/qt/qt5.git RUN cd ${QT_HOME}/qt5 && git checkout v${QT_VERSION} && perl init-repository COPY docker/noble/qt6.5.3-static.patch ${QT_HOME}/qt6.5.3-static.patch # fixes build with Ubuntu 24.04, see https://bugreports.qt.io/browse/QTBUG-117950 # RUN cd ${QT_HOME}/qt5/qtbase && git cherry-pick --no-commit bcdec67cd2e8063aca6beed6b301e47974bcd2ce # The following patch fixes by appling some commits # https://bugreports.qt.io/browse/QTBUG-117950 # bcdec67cd2e8063aca6beed6b301e47974bcd2ce # https://bugreports.qt.io/browse/QTBUG-119469 # 3f45905953d57e0174059d7d9d6bc75c3c1c406c # 7d9d1220f367d9275dfaa7ce12e89b0a9f4c1978 # 3073b9c4dec5e5877363794bf81cbd4b84fdb9ee RUN cd ${QT_HOME}/qt5/qtbase && git apply ${QT_HOME}/qt6.5.3-static.patch RUN mkdir ${QT_HOME}/static-build && \ cd ${QT_HOME}/static-build && \ ../qt5/configure -prefix /opt/Qt/${QT_VERSION}/gcc_64 -static \ -skip qt3d \ -skip qtactiveqt \ -skip qtcharts \ -skip qtconnectivity \ -skip qtcoap \ -skip qtdatavis3d \ -skip qthttpserver \ -skip qtimageformats \ -skip qtlanguageserver \ -skip qtlocation \ -skip qtlottie \ -skip qtmqtt \ -skip qtmultimedia \ -skip qtopcua \ -skip qtpositioning \ -skip qtqa \ -skip qtquick3d \ -skip qtquick3dphysics \ -skip qtquickeffectmaker \ -skip qtquicktimeline \ -skip qtsensors \ -skip qtspeech \ -skip qtvirtualkeyboard \ -skip qtwebchannel \ -skip qtwebview \ -skip qtwebengine RUN cd ${QT_HOME}/static-build && cmake --build . --parallel USER root RUN cd ${QT_HOME}/static-build && cmake --install . FROM ubuntu:noble LABEL Description="Ubuntu static qt6 test environment for Qbs" ARG QT_VERSION ARG QTCREATOR_VERSION RUN mkdir -p /opt/Qt COPY --from=0 /opt/Qt/${QT_VERSION} /opt/Qt/${QT_VERSION} # Allow colored output on command line. ENV TERM=xterm-color ARG USER_UID=1000 ARG USER_NAME=devel RUN apt-get update -qq && \ apt-get install -qq -y \ ca-certificates \ gosu \ sudo && \ userdel ubuntu && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G sudo ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # Qbs build dependencies RUN apt-get update -qq && \ DEBIAN_FRONTEND="noninteractive" apt-get install -qq -y --no-install-recommends \ bison \ build-essential \ ca-certificates \ capnproto \ ccache \ clang-18 \ clang-tidy-18 \ cmake \ curl \ flex \ git \ help2man \ icoutils \ libb2-dev \ libbrotli-dev \ libcapnp-dev \ libdbus-1-dev \ libdrm-dev \ libfontconfig1-dev \ libfreetype6-dev \ libgl1-mesa-dev \ libglib2.0-dev \ libgrpc++-dev \ libharfbuzz-dev \ libicu-dev \ libjpeg-dev \ libmd4c-html0 \ libnanopb-dev \ libpcre++ \ libprotobuf-dev \ libx11-xcb-dev \ libxcb-composite0-dev \ libxcb-cursor-dev \ libxcb-damage0-dev \ libxcb-dpms0-dev \ libxcb-dri2-0-dev \ libxcb-dri3-dev \ libxcb-ewmh-dev \ libxcb-glx0-dev \ libxcb-icccm4-dev \ libxcb-image0-dev \ libxcb-keysyms1-dev \ libxcb-present-dev \ libxcb-present-dev \ libxcb-randr0-dev \ libxcb-record0-dev \ libxcb-render-util0-dev \ libxcb-res0-dev \ libxcb-screensaver0-dev \ libxcb-shape0-dev \ libxcb-shm0-dev \ libxcb-sync-dev \ libxcb-sync0-dev \ libxcb-util-dev \ libxcb-xf86dri0-dev \ libxcb-xfixes0-dev \ libxcb-xinerama0-dev \ libxcb-xinput-dev \ libxcb-xtest0-dev \ libxcb-xv0-dev \ libxcb-xvmc0-dev \ libxcb1-dev \ libxkbcommon-dev \ libudev-dev \ libxkbcommon-x11-dev \ libzstd-dev \ locales \ nanopb \ ninja-build \ nsis \ p7zip-full \ pkg-config \ protobuf-compiler \ protobuf-compiler-grpc \ psmisc \ python3-pip \ python3-setuptools \ python3-venv \ subversion \ unzip \ zip && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100 && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100 && \ update-alternatives --install /usr/bin/clang-check clang-check /usr/bin/clang-check-18 100 && \ update-alternatives --install /usr/bin/python python /usr/bin/python3 100 ENV LLVM_INSTALL_DIR=/usr/lib/llvm-18 # Set up Python RUN python3 -m venv /venv && \ /venv/bin/pip3 install beautifulsoup4 lxml protobuf==3.19.1 pyyaml conan ENV PATH=/venv/bin:${PATH} # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 # # Install Qbs for Linux from qt.io # COPY scripts/install-qt.sh install-qt.sh RUN ./install-qt.sh --version ${QTCREATOR_VERSION} qtcreator && \ echo "export PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/Qt/Tools/QtCreator/bin:\${PATH}" > /etc/profile.d/qt.sh ENV PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/Qt/Tools/QtCreator/bin:${PATH} # Configure Qbs USER $USER_NAME RUN qbs-setup-toolchains /usr/bin/g++ gcc && \ qbs-setup-qt /opt/Qt/${QT_VERSION}/gcc_64/bin/qmake qt-gcc_64 && \ qbs config profiles.qt-gcc_64.baseProfile gcc && \ qbs config defaultProfile qt-gcc_64 # Switch back to root user for the entrypoint script. USER root # Work-around for QTBUG-79020 RUN echo "export QT_NO_GLIB=1" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/entrypoint.sh0000755000175100017510000000720015232633614016523 0ustar runnerrunner#!/usr/bin/env bash set -e ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# # # Entrypoint script when starting the container. The script checks the current # working directory and changes the uid/gid of developer/users to match whatever # is found in the working directory. This is useful to match the user and group # of mounted volumes into the container # # If not root, re-run script as root to fix ids # if [ "$(id -u)" != "0" ]; then exec gosu root /sbin/entrypoint.sh "$@" fi # # Try to determine the uid of the working directory and adjust the current # user's uid/gid accordingly. # USER_GID=${USER_GID:-$(stat -c "%g" .)} USER_UID=${USER_UID:-$(stat -c "%u" .)} USER_NAME=${USER_NAME:-devel} USER_GROUP=${USER_GROUP:-devel} EXEC="" export HOME=/home/${USER_NAME} # # This is a problem on Linux hosts when we mount a folder from the # user file system and write artifacts into that. Thus, we downgrade # the current user and make sure that the uid and gid matches the one # of the mounted project folder. # # This work-around is not needed on Windows hosts as Windows doesn't # have such a concept. # if [ "${USER_UID}" != "0" ]; then if [ "$(id -u ${USER_NAME})" != "${USER_UID}" ]; then usermod -o -u ${USER_UID} ${USER_NAME} # After changing the user's uid, all files in user's home directory # automatically get the new uid. fi current_gid=$(id -g ${USER_NAME}) if [ "$(id -g ${USER_NAME})" != "${USER_GID}" ]; then groupmod -o -g ${USER_GID} ${USER_GROUP} # Set the new gid on all files in the home directory that still have the # old gid. find /home/${USER_NAME} -gid "${current_gid}" ! -type l -exec chgrp ${USER_GID} {} \; fi fi EXEC="exec gosu ${USER_NAME}:${USER_GROUP}" if [ -z "$1" ]; then ${EXEC} bash -l else ${EXEC} bash -l -c "$*" fi qbs-src-3.3.1/docker/leap/0000755000175100017510000000000015232633614014673 5ustar runnerrunnerqbs-src-3.3.1/docker/leap/entrypoint.sh0000755000175100017510000000720415232633614017450 0ustar runnerrunner#!/usr/bin/env bash set -e ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# # # Entrypoint script when starting the container. The script checks the current # working directory and changes the uid/gid of developer/users to match whatever # is found in the working directory. This is useful to match the user and group # of mounted volumes into the container # # If not root, re-run script as root to fix ids # if [ "$(id -u)" != "0" ]; then exec sudo -i /sbin/entrypoint.sh "$@" fi # # Try to determine the uid of the working directory and adjust the current # user's uid/gid accordingly. # USER_GID=${USER_GID:-$(stat -c "%g" .)} USER_UID=${USER_UID:-$(stat -c "%u" .)} USER_NAME=${USER_NAME:-devel} USER_GROUP=${USER_GROUP:-devel} EXEC="" export HOME=/home/${USER_NAME} # # This is a problem on Linux hosts when we mount a folder from the # user file system and write artifacts into that. Thus, we downgrade # the current user and make sure that the uid and gid matches the one # of the mounted project folder. # # This work-around is not needed on Windows hosts as Windows doesn't # have such a concept. # if [ "${USER_UID}" != "0" ]; then if [ "$(id -u ${USER_NAME})" != "${USER_UID}" ]; then usermod -o -u ${USER_UID} ${USER_NAME} # After changing the user's uid, all files in user's home directory # automatically get the new uid. fi current_gid=$(id -g ${USER_NAME}) if [ "$(id -g ${USER_NAME})" != "${USER_GID}" ]; then groupmod -o -g ${USER_GID} ${USER_GROUP} # Set the new gid on all files in the home directory that still have the # old gid. find /home/${USER_NAME} -gid "${current_gid}" ! -type l -exec chgrp ${USER_GID} {} \; fi fi EXEC="exec sudo -u ${USER_NAME} -g ${USER_GROUP}" if [ -z "$1" ]; then ${EXEC} bash -l else ${EXEC} bash -l -c "$*" fi qbs-src-3.3.1/docker/leap/Dockerfile0000644000175100017510000000557615232633614016702 0ustar runnerrunner# # Install Qt and Qbs for Linux # FROM opensuse/leap:15.3 LABEL Description="OpenSUSE development environment for Qbs with Qt and various dependencies for testing Qbs modules and functionality" ARG QT_VERSION ARG QTCREATOR_VERSION # Allow colored output on command line. ENV TERM=xterm-color # # Make it possible to change UID/GID in the entrypoint script. The docker # container usually runs as root user on Linux hosts. When the Docker container # mounts a folder on the host and creates files there, those files would be # owned by root instead of the current user. Thus we create a user here who's # UID will be changed in the entrypoint script to match the UID of the current # host user. # ARG USER_UID=1000 ARG USER_NAME=devel RUN zypper in -y \ ca-certificates \ sudo \ system-user-mail \ system-group-wheel && \ groupadd -g ${USER_UID} ${USER_NAME} && \ useradd -s /bin/bash -u ${USER_UID} -g ${USER_NAME} -o -c "" -m ${USER_NAME} && \ usermod -a -G wheel ${USER_NAME} && \ echo "%devel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers COPY docker/leap/entrypoint.sh /sbin/entrypoint.sh ENTRYPOINT ["/sbin/entrypoint.sh"] # # Qbs build dependencies RUN zypper install -y \ bison \ capnproto \ ccache \ cmake \ command-not-found \ curl \ gcc10 \ gcc10-c++ \ glibc-devel-static \ flex \ fontconfig \ git \ gzip \ help2man \ icoutils \ libcapnp-devel \ libgthread-2_0-0 \ libfreetype6 \ Mesa-libGL-devel \ Mesa-libGL1 \ nanopb-devel \ ninja \ perl \ pkg-config \ psmisc \ python3-pip \ p7zip-full \ subversion \ tar \ unzip \ which \ zip && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 && \ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100 && \ pip install --upgrade pip && \ pip install beautifulsoup4 lxml # # Install Qt and Qbs for Linux from qt.io # COPY scripts/install-qt.sh install-qt.sh RUN ./install-qt.sh --version ${QT_VERSION} qtbase qtdeclarative qttools qtx11extras qtscxml qt5compat icu && \ ./install-qt.sh --version ${QTCREATOR_VERSION} qtcreator && \ echo "export PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/Qt/Tools/QtCreator/bin:\${PATH}" > /etc/profile.d/qt.sh ENV PATH=/opt/Qt/${QT_VERSION}/gcc_64/bin:/opt/Qt/Tools/QtCreator/bin:${PATH} # Configure Qbs USER $USER_NAME RUN qbs-setup-toolchains /usr/bin/g++ gcc && \ qbs-setup-qt /opt/Qt/${QT_VERSION}/gcc_64/bin/qmake qt-gcc_64 && \ qbs config profiles.qt-gcc_64.baseProfile gcc && \ qbs config defaultProfile qt-gcc_64 # Switch back to root user for the entrypoint script. USER root # Work-around for QTBUG-79020 RUN echo "export QT_NO_GLIB=1" >> /etc/profile.d/qt.sh qbs-src-3.3.1/docker/docker.qbs0000644000175100017510000000042115232633614015725 0ustar runnerrunner // This is a convenience product to be able to use Qt Creator for editing the docker files. // For building and managing the images, use docker-compose as explained in // https://doc.qt.io/qbs/building-qbs.html#using-docker. Product { name: "docker" files: "**" } qbs-src-3.3.1/docker/windowsservercore/0000755000175100017510000000000015232633614017544 5ustar runnerrunnerqbs-src-3.3.1/docker/windowsservercore/Dockerfile0000644000175100017510000000431215232633614021536 0ustar runnerrunner FROM mcr.microsoft.com/windows/servercore:ltsc2022 LABEL Description="Windows Server Core 2022 development environment for Qbs with Qt, Chocolatey and various dependencies for testing Qbs modules and functionality" # Disable crash dialog for release-mode runtimes RUN reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v Disabled /t REG_DWORD /d 1 /f RUN reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v DontShowUI /t REG_DWORD /d 1 /f # Install VS 2019 from the website since chocolatey has broken .NET 4.8 (dotnetfx package) which is a # dependency for the visualstudio2019buildtools package RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \ Invoke-WebRequest "https://aka.ms/vs/17/release/vs_community.exe" \ -OutFile "%TEMP%\vs_community.exe" -UseBasicParsing RUN "%TEMP%\vs_community.exe" --quiet --wait --norestart --noUpdateInstaller \ --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ --add Microsoft.VisualStudio.Component.Windows10SDK.19041 RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \ $Env:chocolateyVersion = '0.10.15' ; \ $Env:chocolateyUseWindowsCompression = 'false' ; \ "[Net.ServicePointManager]::SecurityProtocol = \"tls12, tls11, tls\"; iex ((New-Object System.Net.WebClient).DownloadString('http://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" RUN choco install -y python --version 3.13.6 && \ choco install -y 7zip --version 25.1.0 && \ choco install -y git --version 2.50.1 --params "/GitAndUnixToolsOnPath" && \ choco install -y vswhere RUN python.exe -m pip install --upgrade pip # for building the documentation RUN python.exe -m pip install beautifulsoup4 lxml ########### Install Qt ############# ARG QT_VERSION COPY scripts/install-qt.sh install-qt.sh RUN bash -c "./install-qt.sh -d /c/Qt --version ${QT_VERSION} --toolchain win64_msvc2022_64 qtbase qtdeclarative qttools qt5compat" ENV QTDIR64=C:\\Qt\\${QT_VERSION}\\msvc2022_64 ########### Install Qbs ############# ARG QBS_VERSION RUN choco install -y qbs --version %QBS_VERSION% RUN qbs setup-toolchains --detect && \ qbs setup-qt %QTDIR64%/bin/qmake.exe qt64 && \ qbs config defaultProfile qt64 qbs-src-3.3.1/share/0000755000175100017510000000000015232633614013605 5ustar runnerrunnerqbs-src-3.3.1/share/CMakeLists.txt0000644000175100017510000000712615232633614016353 0ustar runnerrunnerif(WIN32) install( FILES ../bin/ibmsvc.xml ../bin/ibqbs.bat DESTINATION "${QBS_APP_INSTALL_DIR}" ) endif() # below we copy some files that are required to run qbs from the build directory # emulating the same layout we will have after the installation # copy & install python packages set(_SITE_PACKAGES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/lib/python3.9/site-packages/) file(GLOB_RECURSE _SITE_PACKAGES_RELATIVE RELATIVE "${_SITE_PACKAGES_DIR}" "${_SITE_PACKAGES_DIR}/*.py") set(_SITE_PACKAGES_SRC ${_SITE_PACKAGES_RELATIVE}) list_transform_prepend(_SITE_PACKAGES_SRC "${_SITE_PACKAGES_DIR}/") set(_SITE_PACKAGES_DST ${_SITE_PACKAGES_RELATIVE}) list_transform_prepend(_SITE_PACKAGES_DST "${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_RESOURCES_INSTALL_DIR}/qbs/python/") add_custom_command( OUTPUT ${_SITE_PACKAGES_DST} DEPENDS ${_SITE_PACKAGES_SRC} COMMAND ${CMAKE_COMMAND} -E copy_directory "${_SITE_PACKAGES_DIR}" ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_RESOURCES_INSTALL_DIR}/qbs/python COMMENT "Copying Python packages" ) install( # trailing slash avoid copying the 'site-packages' dir and only copies its content DIRECTORY "${_SITE_PACKAGES_DIR}" DESTINATION "${QBS_RESOURCES_INSTALL_DIR}/qbs/python" FILES_MATCHING PATTERN "*.py" ) # copy & install the "share/qbs" dir file(GLOB_RECURSE _QBS_RESOURCES_RELATIVE RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/qbs/*") set(_QBS_RESOURCES_SRC ${_QBS_RESOURCES_RELATIVE}) list_transform_prepend(_QBS_RESOURCES_SRC "${CMAKE_CURRENT_SOURCE_DIR}/") set(_QBS_RESOURCES_DST ${_QBS_RESOURCES_RELATIVE}) list_transform_prepend(_QBS_RESOURCES_DST "${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_RESOURCES_INSTALL_DIR}/") add_custom_command( OUTPUT ${_QBS_RESOURCES_DST} DEPENDS ${_QBS_RESOURCES_SRC} COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/qbs ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_RESOURCES_INSTALL_DIR}/qbs COMMENT "Copying QBS resources" ) install( DIRECTORY qbs DESTINATION "${QBS_RESOURCES_INSTALL_DIR}" PATTERN ".gitignore" EXCLUDE ) # install examples dir install( DIRECTORY ../examples DESTINATION "${QBS_RESOURCES_INSTALL_DIR}/qbs" ) set(_QMLTYPES_INSTALL_PATH "${PROJECT_BINARY_DIR}/resources-build/install-root/share/qbs/qml-type-descriptions/qbs.qmltypes") get_update_path_command(UPDATE_PATH_COMMAND) get_target_property(_QBS_OUTPUT_DIR qbs RUNTIME_OUTPUT_DIRECTORY) add_custom_command( OUTPUT "${_QMLTYPES_INSTALL_PATH}" COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs resolve --settings-dir ${PROJECT_BINARY_DIR}/settings -f ${PROJECT_SOURCE_DIR}/qbs.qbs -d ${PROJECT_BINARY_DIR}/ config:resources-build qbs.installPrefix:"" project.withCode:false project.withDocumentation:false profile:none COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs build --settings-dir ${PROJECT_BINARY_DIR}/settings -f ${PROJECT_SOURCE_DIR}/qbs.qbs -d ${PROJECT_BINARY_DIR}/ config:resources-build -p "qbs resources" DEPENDS qbs "${_QBS_RESOURCES_DST}" qbs_processlauncher ) add_custom_target( BuildQbsResources ALL DEPENDS ${_SITE_PACKAGES_DST} ${_QBS_RESOURCES_DST} "${_QMLTYPES_INSTALL_PATH}" ) install( DIRECTORY ${PROJECT_BINARY_DIR}/resources-build/install-root/share/qbs/qml-type-descriptions DESTINATION "${QBS_RESOURCES_INSTALL_DIR}/qbs" ) qbs-src-3.3.1/share/qbs/0000755000175100017510000000000015232633614014372 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/0000755000175100017510000000000015232633614016042 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/texttemplate/0000755000175100017510000000000015232633614020562 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/texttemplate/texttemplate.qbs0000644000175100017510000000571415232633614024020 0ustar runnerrunnerimport qbs.TextFile Module { property string placeholder: "${}" PropertyOptions { name: "placeholder" description: "The placeholder string to use for text template files." allowedValues: ["${}", "@@"] } property var dict: ({}) property string outputTag: "text" property string outputFileName FileTagger { patterns: ["*.in"] fileTags: ["texttemplate.input"] } Rule { inputs: ["texttemplate.input"] outputFileTags: [product.texttemplate.outputTag] outputArtifacts: [ { fileTags: [product.texttemplate.outputTag], filePath: input.texttemplate.outputFileName || input.completeBaseName } ] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { try { var src = new TextFile(input.filePath, TextFile.ReadOnly); var dst = new TextFile(output.filePath, TextFile.WriteOnly); const isDefaultPlaceholder = input.texttemplate.placeholder === "${}"; var rex = isDefaultPlaceholder ? /\${(\$|\w+)}/g : /@(\@|\w+)@/g; var match; while (!src.atEof()) { rex.lastIndex = 0; var line = src.readLine(); var matches = []; while (match = rex.exec(line)) matches.push(match); for (var i = matches.length; --i >= 0;) { match = matches[i]; var replacement; if (isDefaultPlaceholder && match[1] === "$") { replacement = "$"; } else if (!isDefaultPlaceholder && match[1] === "@") { replacement = "@"; } else { replacement = input.texttemplate.dict[match[1]]; if (typeof replacement === "undefined") { throw new Error("Placeholder '" + match[1] + "' is not defined in textemplate.dict for '" + input.fileName + "'."); } } line = line.substr(0, match.index) + replacement + line.substr(match.index + match[0].length); } dst.writeLine(line); } } finally { if (src) src.close(); if (dst) dst.close(); } }; return [cmd]; } } } qbs-src-3.3.1/share/qbs/modules/typescript/0000755000175100017510000000000015232633614020250 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/typescript/typescript.js0000644000175100017510000002465015232633614023023 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); function findTscVersion(compilerFilePath, nodejsPath) { var p = new Process(); try { if (nodejsPath) p.setEnv("PATH", nodejsPath); p.exec(compilerFilePath, ["--version"]); var re = /^(?:message TS6029: )?Version (([0-9]+(?:\.[0-9]+){1,3})(?:-(.+?))?)$/m; var match = p.readStdOut().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function tscArguments(product, inputs) { var i; var args = []; if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("--noImplicitAny"); } var targetVersion = ModUtils.moduleProperty(product, "targetVersion"); if (targetVersion) { args.push("--target"); args.push(targetVersion); } var moduleLoader = ModUtils.moduleProperty(product, "moduleLoader"); if (moduleLoader) { args.push("--module"); args.push(moduleLoader); } if (ModUtils.moduleProperty(product, "stripComments")) { args.push("--removeComments"); } if (ModUtils.moduleProperty(product, "generateDeclarations")) { args.push("--declaration"); } if (ModUtils.moduleProperty(product, "generateSourceMaps")) { args.push("--sourcemap"); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } if (supportsModernFeatures(product)) { args.push("--rootDir", product.sourceDirectory); } args.push("--outDir", product.buildDirectory); if (ModUtils.moduleProperty(product, "singleFile")) { args.push(outOption(product), FileInfo.joinPaths(product.destinationDirectory, product.targetName) + ".js"); } if (inputs.typescript_declaration) { for (i = 0; i < inputs.typescript_declaration.length; ++i) { args.push(inputs.typescript_declaration[i].filePath); } } if (inputs.typescript) { for (i = 0; i < inputs.typescript.length; ++i) { args.push(inputs.typescript[i].filePath); } } if (inputs["typescript.typescript-internal"]) { for (i = 0; i < inputs["typescript.typescript-internal"].length; ++i) { args.push(inputs["typescript.typescript-internal"][i].filePath); } } return args; } function outputArtifacts(product, inputs) { if (!supportsModernFeatures(product)) { console.warn("Qbs does not properly support TypeScript versions prior to 1.5 due to " + "severe limitations in dependency tracking. This is TypeScript version " + ModUtils.moduleProperty(product, "version") + ". It is strongly recommended " + "that you upgrade TypeScript, or continue at your own risk."); return legacyOutputArtifacts(product, inputs); } var process; try { process = new Process(); process.setEnv("NODE_PATH", [ ModUtils.moduleProperty(product, "toolchainInstallPath"), product.moduleProperty("nodejs", "packageManagerRootPath") ].join(FileInfo.pathListSeparator())); process.exec(product.moduleProperty("nodejs", "interpreterFilePath"), [FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js")] .concat(tscArguments(product, inputs)), true); var artifacts = JSON.parse(process.readStdOut()); // Find and tag the "main" output file var applicationFile = product.moduleProperty("nodejs", "applicationFile"); if (applicationFile) { var i, appIndex = -1; if (product.moduleProperty("typescript", "singleFile")) { for (i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.includes("compiled_typescript")) { appIndex = i; break; } } } else { var expected = FileInfo.relativePath(product.sourceDirectory, applicationFile); if (!expected.endsWith(".ts")) // tsc doesn't allow this anyways, so it's a perfectly reasonable restriction throw "TypeScript source file name '" + applicationFile + "' does not end with .ts"; expected = expected.slice(0, -2) + "js"; for (i = 0; i < artifacts.length; ++i) { if (expected === FileInfo.relativePath(product.buildDirectory, artifacts[i].filePath)) { appIndex = i; break; } } } if (appIndex === -1 || !artifacts[appIndex].fileTags.includes("compiled_typescript")) throw "nodejs.applicationFile was set, but Qbs couldn't find the compiled " + "JavaScript file corresponding to '" + applicationFile + "'"; artifacts[appIndex].fileTags = artifacts[appIndex].fileTags.concat(["application_js"]); } return artifacts; } finally { if (process) process.close(); } } function legacyOutputArtifacts(product, inputs) { var artifacts = []; if (!inputs.typescript) { return artifacts; } var jsTags = ["js", "compiled_typescript"]; var filePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName); if (product.moduleProperty("typescript", "singleFile")) { // We could check // if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) // but since we're compiling to a single file there's no need to state it explicitly jsTags.push("application_js"); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), product.targetName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } else { for (var i = 0; i < inputs.typescript.length; ++i) { jsTags = ["js", "compiled_typescript"]; if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) jsTags.push("application_js"); var intermediatePath = FileInfo.path(FileInfo.relativePath( product.sourceDirectory, inputs.typescript[i].filePath)); var baseName = FileInfo.baseName(inputs.typescript[i].fileName); filePath = FileInfo.joinPaths(product.destinationDirectory, intermediatePath, baseName); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), intermediatePath, baseName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } } return artifacts; } function outOption(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "versionMinor") < 6) { return "--out"; } } return "--outFile"; } function supportsModernFeatures(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "versionMinor") >= 5) { return true; } } return compilerVersionMajor > 1; } qbs-src-3.3.1/share/qbs/modules/typescript/qbs-tsc-scan/0000755000175100017510000000000015232633614022546 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/typescript/qbs-tsc-scan/.gitignore0000644000175100017510000000016115232633614024534 0ustar runnerrunner# Visual Studio Code IDE tsconfig.json qbs-tsc-scan.js typings/node/node.d.ts typings/typescript/typescript.d.ts qbs-src-3.3.1/share/qbs/modules/typescript/qbs-tsc-scan/qbs-tsc-scan.ts0000644000175100017510000000516715232633614025425 0ustar runnerrunnerimport ts = require("typescript"); declare var process: any; export namespace io.qt.qbs { export class Artifact { filePath: string; fileTags: string[]; } export namespace tools { export namespace utils { function stringEndsWith(s: string, e: string) { return s.slice(-e.length) === e; } export function artifactFromFilePath(filePath: string): Artifact { var fileTags: string[] = []; if (stringEndsWith(filePath, ".js.map")) { fileTags.push("source_map"); } else if (stringEndsWith(filePath, ".js")) { fileTags.push("js", "compiled_typescript"); } else if (stringEndsWith(filePath, ".d.ts")) { fileTags.push("typescript_declaration"); } return { filePath: filePath, fileTags: fileTags }; } } function compileInternal(fileNames: string[], options: ts.CompilerOptions): qbs.Artifact[] { var outputArtifacts: qbs.Artifact[] = []; var program = ts.createProgram(fileNames, options); var emitResult = program.emit(undefined, filePath => { outputArtifacts.push(utils.artifactFromFilePath(filePath)); }); var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (diagnostic.file) { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.error(message); } }); return emitResult.emitSkipped ? undefined : outputArtifacts; } export function compile(commandLineArguments: string[]): qbs.Artifact[] { var parsedCommandLine = ts.parseCommandLine(commandLineArguments); return compileInternal(parsedCommandLine.fileNames, parsedCommandLine.options); } export function TypeScriptCompilerScannerToolMain(): void { var outputArtifacts = compile(process.argv.slice(2)); if (outputArtifacts !== undefined) { console.log(JSON.stringify(outputArtifacts)); } else { process.exit(1); } } } } io.qt.qbs.tools.TypeScriptCompilerScannerToolMain(); qbs-src-3.3.1/share/qbs/modules/typescript/TypeScriptModule.qbs0000644000175100017510000003055315232633614024241 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import "typescript.js" as TypeScript Module { // Qbs does NOT support standalone TypeScript installations // (for example, %PROGRAMFILES%\Microsoft SDKs\TypeScript and some Debian and RPM packages), // because they do not include typescript.d.ts, which is necessary for building internal tools. // Only npm-based installations of TypeScript are supported (this is also the most common). Depends { name: "nodejs" } additionalProductTypes: ["compiled_typescript"] Probes.TypeScriptProbe { id: tsc interpreterPath: FileInfo.path(nodejs.interpreterFilePath) packageManagerBinPath: nodejs.packageManagerBinPath packageManagerRootPath: nodejs.packageManagerRootPath } property path toolchainInstallPath: tsc.path property path toolchainLibDirName: (versionMajor > 1 || (versionMajor === 1 && versionMinor >= 6)) ? "lib" : "bin" property path toolchainLibInstallPath: FileInfo.joinPaths(nodejs.packageManagerRootPath, "typescript", toolchainLibDirName) version: tsc.version ? tsc.version[2] : undefined property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string versionSuffix: tsc.version ? tsc.version[3] : undefined property string compilerName: tsc.fileName property string compilerPath: tsc.filePath property string warningLevel: "normal" PropertyOptions { name: "warningLevel" description: "pedantic to warn on expressions and declarations with an implied 'any' type" allowedValues: ["normal", "pedantic"] } property string targetVersion PropertyOptions { name: "targetVersion" description: "ECMAScript target version" allowedValues: ["ES3", "ES5", "ES2015"] } property string moduleLoader PropertyOptions { name: "moduleLoader" allowedValues: ["commonjs", "amd"] } property bool stripComments: !qbs.debugInformation PropertyOptions { name: "stripComments" description: "whether to remove comments from the generated output" } property bool generateDeclarations: false PropertyOptions { name: "generateDeclarations" description: "whether to generate corresponding .d.ts files during compilation" } // In release mode, nodejs can/should default-enable minification and obfuscation, // making the source maps useless, so these default settings work out fine property bool generateSourceMaps: qbs.debugInformation PropertyOptions { name: "generateSourceMaps" description: "whether to generate corresponding .map files during compilation" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the TypeScript compiler" } property bool singleFile: false PropertyOptions { name: "singleFile" description: "whether to compile all source files to a single output file" } validate: { var interpreterMessage = "TypeScript requires the Node.js interpreter to be called 'node'."; if (File.exists("/etc/debian_version")) { interpreterMessage += " Did you forget to install the nodejs-legacy package? " + "See https://lists.debian.org/debian-devel-announce/2012/07/msg00002.html " + "for more information."; } var preValidator = new ModUtils.PropertyValidator("nodejs"); preValidator.addCustomValidator("interpreterFileName", nodejs.interpreterFileName, function (value) { return value === "node" + FileInfo.executableSuffix(); }, interpreterMessage); preValidator.addCustomValidator("interpreterFilePath", nodejs.interpreterFilePath, function (value) { return value.endsWith(nodejs.interpreterFileName); }, interpreterMessage); preValidator.validate(); var validator = new ModUtils.PropertyValidator("typescript"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("compilerName", compilerName); validator.setRequiredProperty("compilerPath", compilerPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionParts", versionParts); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } // TypeScript declaration files FileTagger { patterns: ["*.d.ts"] fileTags: ["typescript_declaration"] } // TypeScript source files FileTagger { patterns: ["*.ts"] fileTags: ["typescript"] } Group { name: "io.qt.qbs.internal.typescript-helper" files: [ FileInfo.joinPaths(path, "qbs-tsc-scan", "qbs-tsc-scan.ts"), FileInfo.joinPaths(typescript.toolchainLibInstallPath, "typescript.d.ts"), FileInfo.joinPaths(typescript.toolchainLibInstallPath, "..", "package.json") ] fileTags: ["typescript.typescript-internal"] } Rule { multiplex: true inputs: ["typescript.typescript-internal"] outputFileTags: ["typescript.compiled_typescript-internal"] outputArtifacts: { if (!TypeScript.supportsModernFeatures(product)) return []; return [{ filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.ts"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "node_modules", "typescript", "lib", "typescript.d.ts"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "node_modules", "typescript", "package.json"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js"), fileTags: ["typescript.compiled_typescript-internal"] }]; } prepare: { var inputPaths = inputs["typescript.typescript-internal"].map(function (input) { return input.filePath; }); var outputPaths = outputs["typescript.typescript-internal.copy"].map(function (output) { return output.filePath; }); var sortFunc = function (a, b) { return FileInfo.fileName(a).localeCompare(FileInfo.fileName(b)); }; var jcmd = new JavaScriptCommand(); jcmd.ignoreDryRun = true; jcmd.silent = true; jcmd.inputPaths = inputPaths.sort(sortFunc); jcmd.outputPaths = outputPaths.sort(sortFunc); jcmd.sourceCode = function() { for (var i = 0; i < inputPaths.length; ++i) File.copy(inputPaths[i], outputPaths[i]); }; var outDir = FileInfo.path( outputs["typescript.compiled_typescript-internal"][0].filePath); var args = ["--module", "commonjs", "--outDir", outDir].concat(outputPaths.filter(function (f) { return !f.endsWith(".json"); })); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.ignoreDryRun = true; cmd.silent = true; return [jcmd, cmd]; } } Rule { id: typescriptCompiler multiplex: true inputs: ["typescript"] inputsFromDependencies: ["typescript_declaration"] explicitlyDependsOn: ["typescript.compiled_typescript-internal"] outputArtifacts: TypeScript.outputArtifacts(product, inputs) outputFileTags: ["application_js", "compiled_typescript", "js", "source_map", "typescript_declaration"] prepare: { var cmd, cmds = []; cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), TypeScript.tscArguments(product, inputs)); cmd.description = "compiling " + (ModUtils.moduleProperty(product, "singleFile") ? outputs.compiled_typescript[0].fileName : inputs.typescript.map(function(obj) { return obj.fileName; }).join(", ")); cmd.highlight = "compiler"; cmds.push(cmd); // QBS-5 // Move the compiled JavaScript files compiled by TypeScript to an intermediate // directory so that the nodejs module can perform any necessary postprocessing // on the result. The nodejs module will move the files back to their original // locations after postprocessing. cmd = new JavaScriptCommand(); cmd.silent = true; cmd.outDir = product.buildDirectory; cmd.sourceCode = function() { for (var i = 0; i < outputs.compiled_typescript.length; ++i) { var output = outputs.compiled_typescript[i]; var intermediatePath = FileInfo.path(FileInfo.relativePath(product.moduleProperty("nodejs", "compiledIntermediateDir"), output.filePath)); var originalFilePath = FileInfo.joinPaths(outDir, intermediatePath, output.fileName); File.copy(originalFilePath, output.filePath); File.remove(originalFilePath); } }; cmds.push(cmd); return cmds; } } } qbs-src-3.3.1/share/qbs/modules/capnproto/0000755000175100017510000000000015232633614020047 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/capnproto/capnprotobase.qbs0000644000175100017510000000464515232633614023427 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.Probes import "capnproto.js" as HelperFunctions Module { property string compilerName: "capnpc" property string compilerPath: compilerProbe.filePath property string pluginName property string pluginPath: pluginProbe.filePath property pathList importPaths: [] property string outputDir: product.buildDirectory + "/capnp" property var _searchPaths Probes.BinaryProbe { id: compilerProbe names: compilerName ? [compilerName] : [] searchPaths: _searchPaths } Probes.BinaryProbe { id: pluginProbe names: pluginName ? [pluginName] : [] searchPaths: _searchPaths } FileTagger { patterns: ["*.capnp"] fileTags: ["capnproto.input"]; } validate: { HelperFunctions.validateCompiler(compilerName, compilerPath); HelperFunctions.validatePlugin(pluginName, pluginPath); } } qbs-src-3.3.1/share/qbs/modules/capnproto/capnproto.js0000644000175100017510000000725215232633614022420 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Utilities = require("qbs.Utilities"); function validateCompiler(name, path) { if (!File.exists(path)) throw "Cannot find executable '" + name + "'. Please set the compilerPath " + "property or make sure the compiler is found in PATH"; } function validatePlugin(name, path) { if (!name) throw "pluginName is not set"; if (!File.exists(path)) throw "Cannot find plugin '" + name + "'. Please set the pluginPath " + "property or make sure the plugin is found in PATH"; } function getOutputDir(module, input) { var outputDir = module.outputDir; var importPaths = module.importPaths; if (importPaths.length !== 0) { var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); for (var i = 0; i < importPaths.length; ++i) { var path = File.canonicalFilePath(importPaths[i]); if (canonicalInput.startsWith(path)) { return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); } } } return outputDir; } function artifact(outputDir, input, tag, suffix) { return { fileTags: [tag], filePath: FileInfo.joinPaths(outputDir, FileInfo.baseName(input.fileName) + suffix), cpp: { includePaths: [].concat(input.cpp.includePaths, outputDir), warningLevel: "none", } }; } function doPrepare(module, product, input, outputs, lang) { var outputDir = FileInfo.path(outputs["cpp"][0].filePath); var args = []; args.push("--output=" + module.pluginPath + ":" + outputDir); args.push("--src-prefix=" + FileInfo.path(input.filePath)); var importPaths = module.importPaths; importPaths.forEach(function(path) { if (!FileInfo.isAbsolutePath(path)) path = FileInfo.joinPaths(product.sourceDirectory, path); args.push("--import-path", path); }); args.push(input.filePath); var cmd = new Command(module.compilerPath, args); cmd.highlight = "codegen"; cmd.description = "generating " + lang + " files for " + input.fileName; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/capnproto/cpp/0000755000175100017510000000000015232633614020631 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs0000644000175100017510000000502615232633614024053 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "../capnprotobase.qbs" as CapnProtoBase import "../capnproto.js" as HelperFunctions CapnProtoBase { property bool useRpc: false Depends { name: "cpp" } Depends { name: "capnp" } Depends { name: "capnp-rpc"; condition: useRpc } pluginName: "capnpc-c++" version: capnp.version _searchPaths: capnp.hostBinDirs cpp.systemIncludePaths: outputDir cpp.cxxLanguageVersion: "c++14" Rule { inputs: ["capnproto.input"] outputFileTags: ["hpp", "cpp"] outputArtifacts: { var outputDir = HelperFunctions.getOutputDir(input.capnproto.cpp, input); var result = [ HelperFunctions.artifact(outputDir, input, "hpp", ".capnp.h"), HelperFunctions.artifact(outputDir, input, "cpp", ".capnp.c++") ]; return result; } prepare: { var result = HelperFunctions.doPrepare( input.capnproto.cpp, product, input, outputs, "cpp"); return result; } } } qbs-src-3.3.1/share/qbs/modules/Exporter/0000755000175100017510000000000015232633614017652 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Exporter/pkgconfig/0000755000175100017510000000000015232633614021621 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js0000644000175100017510000002320615232633614024131 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function quote(value) { if (value.includes(" ") || value.includes("'") || value.includes('"')) { return '"' + value.replace(/(["'\\])/g, "\\$1") + '"'; } return value; } function writeEntry(product, file, key, propertyName, required, additionalValues) { var value = product.Exporter.pkgconfig[propertyName]; if (additionalValues && additionalValues.length > 0) value = (value || []).concat(additionalValues); var valueIsNotEmpty = value && (!(value instanceof Array) || value.length > 0); if (valueIsNotEmpty) { if (value instanceof Array) value = value.join(' '); file.writeLine(key + ": " + value); } else if (required) { throw "Failure creating " + FileInfo.fileName(file.filePath()) + ": The entry '" + key + "' is required, but property Exporter.pkgconfig." + propertyName + " is not set."; } } function collectAutodetectedData(topLevelProduct) { var data = { libs: [], cflags: [], requires: [], requiresPrivate: [] }; if (!topLevelProduct.Exporter.pkgconfig.autoDetect) return data; var excludedDeps = topLevelProduct.Exporter.pkgconfig.excludedDependencies || []; var explicitRequires = topLevelProduct.Exporter.pkgconfig.requiresEntry || []; var explicitRequiresPrivate = topLevelProduct.Exporter.pkgconfig.requiresPrivateEntry || []; var transformFunc = topLevelProduct.Exporter.pkgconfig.transformFunction; // Make use of the "prefix" convenience variable if applicable. function quoteAndPrefixify(value) { var quotedValue = quote(value); var installPrefix = topLevelProduct.qbs.installPrefix || ""; if (!topLevelProduct.Exporter.pkgconfig._usePrefix || typeof value !== "string" || !value.startsWith(installPrefix) || (value.length > installPrefix.length && value[installPrefix.length] !== '/')) { return quotedValue; } return quotedValue.replace(topLevelProduct.qbs.installPrefix, "${prefix}"); } function transformedValue(product, moduleName, propertyName) { var originalValue = product.exports[moduleName][propertyName]; var value = transformFunc ? eval("(" + transformFunc + ")(product, moduleName, propertyName, originalValue)") : originalValue; if (value instanceof Array) value.forEach(function(v, i, a) { a[i] = quoteAndPrefixify(v); }); else if (value) value = quoteAndPrefixify(value); return value; } function collectLibs(productOrModule) { var libs = []; var libArtifacts; var isProduct = !productOrModule.present; var considerDynamicLibs = !isProduct || (productOrModule.type && productOrModule.type.includes("dynamiclibrary")); if (considerDynamicLibs) { libArtifacts = productOrModule.artifacts.dynamiclibrary; } else { var considerStaticLibs = !isProduct || (productOrModule.type && productOrModule.type.includes("staticlibrary")); if (considerStaticLibs) libArtifacts = productOrModule.artifacts.staticlibrary; } for (var i = 0; i < (libArtifacts || []).length; ++i) { var libArtifact = libArtifacts[i]; if (libArtifact.qbs.install) { var installDir = FileInfo.path(ModUtils.artifactInstalledFilePath(libArtifact)); installDir = installDir.slice(libArtifact.qbs.installRoot.length); libs.push("-L" + quoteAndPrefixify(FileInfo.cleanPath(installDir)), "-l" + quote(productOrModule.targetName)); } } if (!productOrModule.exports.cpp) return libs; var libPaths = transformedValue(productOrModule, "cpp", "libraryPaths"); if (libPaths) libs.push.apply(libs, libPaths.map(function(p) { return "-L" + p; })); function libNamesToLibEntries(libNames) { return libNames.map(function(libName) { return "-l" + libName; }); }; var dlls = transformedValue(productOrModule, "cpp", "dynamicLibraries"); if (dlls) libs.push.apply(libs, libNamesToLibEntries(dlls)); var staticLibs = transformedValue(productOrModule, "cpp", "staticLibraries"); if (staticLibs) libs.push.apply(libs, libNamesToLibEntries(staticLibs)); var lFlags = transformedValue(productOrModule, "cpp", "linkerFlags"); if (lFlags) libs.push.apply(libs, lFlags); lFlags = transformedValue(productOrModule, "cpp", "driverFlags"); if (lFlags) libs.push.apply(libs, lFlags); lFlags = transformedValue(productOrModule, "cpp", "driverLinkerFlags"); if (lFlags) libs.push.apply(libs, lFlags); return libs; } function collectCFlags(productOrModule) { if (!productOrModule.exports.cpp) return []; var flags = []; var defs = transformedValue(productOrModule, "cpp", "defines"); if (defs) flags.push.apply(flags, defs.map(function(d) { return "-D" + d; })); var incPaths = transformedValue(productOrModule, "cpp", "includePaths"); if (incPaths) flags.push.apply(flags, incPaths.map(function(p) { return "-I" + p; })); var cflags = transformedValue(productOrModule, "cpp", "commonCompilerFlags"); if (cflags) flags.push.apply(flags, cflags); cflags = transformedValue(productOrModule, "cpp", "driverFlags"); if (cflags) flags.push.apply(flags, cflags); cflags = transformedValue(productOrModule, "cpp", "cxxFlags") || transformedValue(productOrModule, "cpp", "cFlags"); if (cflags) flags.push.apply(flags, cflags); return flags; } function collectAutodetectedDataRecursive(productOrModule, privateContext) { if (!privateContext) { data.libs.push.apply(data.libs, collectLibs(productOrModule)); data.cflags.push.apply(data.cflags, collectCFlags(productOrModule)); } var exportedDeps = productOrModule.exports ? productOrModule.exports.dependencies : []; var exportedDepNames = []; var privateDeps = []; for (var i = 0; i < exportedDeps.length; ++i) exportedDepNames.push(exportedDeps[i].name); for (i = 0; i < (productOrModule.dependencies || []).length; ++i) { var dep = productOrModule.dependencies[i]; if (exportedDepNames.includes(dep.name)) continue; privateDeps.push(dep); } function gatherData(dep) { if (dep.name === "Exporter.pkgconfig") return; var depHasPkgConfig = dep.Exporter && dep.Exporter.pkgconfig; if (depHasPkgConfig) { var entry = FileInfo.completeBaseName(dep.Exporter.pkgconfig.fileName); if (excludedDeps.includes(entry)) return; if (isPrivateDep && !data.requiresPrivate.includes(entry) && !explicitRequiresPrivate.includes(entry)) { data.requiresPrivate.push(entry); } if (!isPrivateDep && !data.requires.includes(entry) && !explicitRequires.includes(entry)) { data.requires.push(entry); } } else { if (excludedDeps.includes(dep.name)) return; if (isPrivateDep && explicitRequiresPrivate.includes(dep.name)) return; if (!isPrivateDep && explicitRequires.includes(dep.name)) return; collectAutodetectedDataRecursive(dep, isPrivateDep); } } var isPrivateDep = privateContext; exportedDeps.forEach(gatherData); isPrivateDep = true; privateDeps.forEach(gatherData); } collectAutodetectedDataRecursive(topLevelProduct, false); return data; } qbs-src-3.3.1/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs0000644000175100017510000000736515232633614024312 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile import "pkgconfig.js" as HelperFunctions Module { property string fileName: product.targetName + ".pc" property bool autoDetect: true property var transformFunction // function(product, moduleName, propertyName, valueElement) property stringList excludedDependencies property string nameEntry: product.name property string descriptionEntry: product.name property string versionEntry: product.version property string urlEntry property stringList cflagsEntry: [] property stringList libsEntry: [] property stringList libsPrivateEntry: [] property stringList requiresEntry: [] property stringList requiresPrivateEntry: [] property stringList conflictsEntry: [] property var customVariables property bool _usePrefix: autoDetect && qbs.installPrefix additionalProductTypes: ["Exporter.pkgconfig.pc"] Rule { multiplex: true requiresInputs: false // Make sure all relevant library artifacts have been created by the time we run. auxiliaryInputs: { if (!autoDetect) return undefined; if (product.type.includes("staticlibrary")) return ["staticlibrary"]; if (product.type.includes("dynamiclibrary")) return ["dynamiclibrary"]; } Artifact { filePath: product.Exporter.pkgconfig.fileName fileTags: ["Exporter.pkgconfig.pc"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); if (product.Exporter.pkgconfig._usePrefix) f.writeLine("prefix=" + product.qbs.installPrefix + "\n"); var customVariables = product.Exporter.pkgconfig.customVariables; if (customVariables) { for (var customVar in customVariables) f.writeLine(customVar + "=" + customVariables[customVar]); f.writeLine(""); } var autoDetectedData = HelperFunctions.collectAutodetectedData(product); HelperFunctions.writeEntry(product, f, "Name", "nameEntry", true); HelperFunctions.writeEntry(product, f, "Description", "descriptionEntry", true); HelperFunctions.writeEntry(product, f, "Version", "versionEntry", true); HelperFunctions.writeEntry(product, f, "URL", "urlEntry"); HelperFunctions.writeEntry(product, f, "Cflags", "cflagsEntry", false, autoDetectedData.cflags); HelperFunctions.writeEntry(product, f, "Libs", "libsEntry", false, autoDetectedData.libs); HelperFunctions.writeEntry(product, f, "Libs.private", "libsPrivateEntry"); HelperFunctions.writeEntry(product, f, "Requires", "requiresEntry", false, autoDetectedData.requires); HelperFunctions.writeEntry(product, f, "Requires.private", "requiresPrivateEntry", false, autoDetectedData.requiresPrivate); HelperFunctions.writeEntry(product, f, "Conflicts", "conflictsEntry"); }; return [cmd]; } } validate: { if (requiresEntry && excludedDependencies && requiresEntry.containsAny(excludedDependencies)) { throw "The contents of Export.pkgconfig.requiresEntry and " + "Export.pkgconfig.excludedDependencies must not overlap."; } } } qbs-src-3.3.1/share/qbs/modules/Exporter/qbs/0000755000175100017510000000000015232633614020437 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Exporter/qbs/qbsexporter.js0000644000175100017510000002320315232633614023353 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var ExporterHelpers = require("../exporter.js"); function tagListToString(tagList) { return JSON.stringify(tagList); } function stringToTagList(tagListString) { return JSON.parse(tagListString); } function writeTargetArtifactGroup(output, tagList, artifactList, moduleInstallDir, moduleFile) { // Do not add our qbs module file itself. if (tagListToString(tagList) === tagListToString(output.fileTags)) return; moduleFile.writeLine(" Group {"); moduleFile.writeLine(" filesAreTargets: true"); var filteredTagList = tagList.filter(function(t) { return t !== "installable"; }); moduleFile.writeLine(" fileTags: " + JSON.stringify(filteredTagList)); moduleFile.writeLine(" files: ["); for (i = 0; i < artifactList.length; ++i) { var artifact = artifactList[i]; var installedArtifactFilePath = ModUtils.artifactInstalledFilePath(artifact); // Use relative file paths for relocatability. var relativeInstalledArtifactFilePath = FileInfo.relativePath(moduleInstallDir, installedArtifactFilePath); moduleFile.writeLine(" " + JSON.stringify(relativeInstalledArtifactFilePath) + ","); } moduleFile.writeLine(" ]"); moduleFile.writeLine(" }"); } function writeTargetArtifactGroups(product, output, moduleFile) { var relevantArtifacts = []; for (var i = 0; i < (product.Exporter.qbs._artifactTypes || []).length; ++i) { var tag = product.Exporter.qbs._artifactTypes[i]; var artifactsForTag = product.artifacts[tag] || []; for (var j = 0; j < artifactsForTag.length; ++j) { if (!relevantArtifacts.includes(artifactsForTag[j])) relevantArtifacts.push(artifactsForTag[j]); } } var artifactsByTags = {}; var artifactCount = relevantArtifacts ? relevantArtifacts.length : 0; for (i = 0; i < artifactCount; ++i) { var artifact = relevantArtifacts[i]; if (!artifact.fileTags.includes("installable")) continue; // Put all artifacts with the same set of file tags into the same group, so we don't // create more groups than necessary. var key = tagListToString(artifact.fileTags); var currentList = artifactsByTags[key]; if (currentList) currentList.push(artifact); else currentList = [artifact]; artifactsByTags[key] = currentList; } var moduleInstallDir = FileInfo.path(ModUtils.artifactInstalledFilePath(output)); for (var tagListKey in artifactsByTags) { writeTargetArtifactGroup(output, stringToTagList(tagListKey), artifactsByTags[tagListKey], moduleInstallDir, moduleFile); } } function stringifyValue(project, product, moduleInstallDir, prop, value) { if (value instanceof Array) { var repr = "["; for (var i = 0; i < value.length; ++i) { repr += stringifyValue(project, product, moduleInstallDir, prop, value[i]) + ", "; } repr += "]"; return repr; } if (typeof(value) !== "string") { var value = JSON.stringify(value); if (prop.type === "variant") value = '(' + value + ')'; return value; } var valuePrefixToStrip = ExporterHelpers.getPrefixToStrip(project, product, prop.name, value); if (valuePrefixToStrip) { var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); var deployedModuleInstallDir = moduleInstallDir.slice(fullInstallPrefix.length); return "FileInfo.cleanPath(FileInfo.joinPaths(path, FileInfo.relativePath(" + JSON.stringify(deployedModuleInstallDir) + ", " + JSON.stringify(value.slice(valuePrefixToStrip.length) || "/") + ")))"; } return JSON.stringify(value); } function writeProperty(project, product, moduleInstallDir, prop, indentation, considerValue, moduleFile) { var line = indentation; var separatorIndex = prop.name.lastIndexOf("."); var isModuleProperty = separatorIndex !== -1; var needsDeclaration = !prop.isBuiltin && !isModuleProperty; if (needsDeclaration) line += "property " + prop.type + " "; var moduleName; if (isModuleProperty) { moduleName = prop.name.slice(0, separatorIndex); if ((product.Exporter.qbs.excludedDependencies || []).includes(moduleName)) return; } line += prop.name + ": "; // We emit the literal value, unless the source code clearly refers to values from inside the // original project, in which case the evaluated value is used. if (considerValue && /(project|product|exportingProduct)\./.test(prop.sourceCode)) { var value; if (isModuleProperty) { var propertyName = prop.name.slice(separatorIndex + 1); value = product.exports[moduleName][propertyName]; } else { value = product.exports[prop.name]; } line += stringifyValue(project, product, moduleInstallDir, prop, value); } else { line += prop.sourceCode.replace(/importingProduct\./g, "product."); } moduleFile.writeLine(line); } function writeProperties(project, product, moduleInstallDir, list, indentation, considerValue, moduleFile) { for (var i = 0; i < list.length; ++i) { writeProperty(project, product, moduleInstallDir, list[i], indentation, considerValue, moduleFile); } } // This writes properties set on other modules in the Export item, i.e. property assignments // like "cpp.includePaths: '...'". function writeModuleProperties(project, product, output, moduleFile) { var moduleInstallDir = FileInfo.path(ModUtils.artifactInstalledFilePath(output)); var filteredProps = product.exports.properties.filter(function(p) { return p.name !== "name"; }); // The right-hand side can refer to values from the exporting product, in which case // the evaluated value, rather than the source code, needs to go into the module file. var considerValues = true; writeProperties(project, product, moduleInstallDir, filteredProps, " ", considerValues, moduleFile); } function writeItem(product, item, indentation, moduleFile) { moduleFile.writeLine(indentation + item.name + " {"); var newIndentation = indentation + " "; // These are sub-items of the Export item, whose properties entirely live in the context // of the importing product. Therefore, they must never use pre-evaluated values. var considerValues = false; writeProperties(undefined, product, undefined, item.properties, newIndentation, considerValues, moduleFile) for (var i = 0; i < item.childItems.length; ++i) writeItem(product, item.childItems[i], newIndentation, moduleFile); moduleFile.writeLine(indentation + "}"); } function isExcludedDependency(product, childItem) { if ((product.Exporter.qbs.excludedDependencies || []).length === 0) return false; if (childItem.name !== "Depends") return false; for (var i = 0; i < childItem.properties.length; ++i) { var prop = childItem.properties[i]; var unquotedRhs = prop.sourceCode.slice(1, -1); if (prop.name === "name" && product.Exporter.qbs.excludedDependencies.includes(unquotedRhs)) return true; } return false; } function writeChildItems(product, moduleFile) { for (var i = 0; i < product.exports.childItems.length; ++i) { var item = product.exports.childItems[i]; if (!isExcludedDependency(product, item)) writeItem(product, item, " ", moduleFile); } } function writeImportStatements(product, moduleFile) { var imports = product.exports.imports; // We potentially use FileInfo ourselves when transforming paths in stringifyValue(). if (!imports.includes("import qbs.FileInfo")) imports.push("import qbs.FileInfo"); for (var i = 0; i < imports.length; ++i) moduleFile.writeLine(imports[i]); } qbs-src-3.3.1/share/qbs/modules/Exporter/qbs/qbsexporter.qbs0000644000175100017510000000612715232633614023532 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.TextFile import "qbsexporter.js" as HelperFunctions Module { property stringList artifactTypes property string fileName: product.targetName + ".qbs" property stringList excludedDependencies property string additionalContent property stringList _artifactTypes: artifactTypes ? artifactTypes : ["installable"] additionalProductTypes: ["Exporter.qbs.module"] Rule { multiplex: true requiresInputs: false // Make sure we only run when all other artifacts are already present. auxiliaryInputs: product.type.filter(function(t) { return t !== "Exporter.qbs.module"; }) Artifact { filePath: product.Exporter.qbs.fileName fileTags: ["Exporter.qbs.module"] qbs.install: true } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); HelperFunctions.writeImportStatements(product, f); f.writeLine("\nModule {"); HelperFunctions.writeModuleProperties(project, product, output, f); HelperFunctions.writeTargetArtifactGroups(product, output, f); HelperFunctions.writeChildItems(product, f); if (product.Exporter.qbs.additionalContent) f.writeLine(product.Exporter.qbs.additionalContent); f.writeLine("}"); f.close(); }; return [cmd]; } } } qbs-src-3.3.1/share/qbs/modules/Exporter/exporter.js0000644000175100017510000000642015232633614022062 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function getPrefixToStrip(project, product, propName, value) { function checkValuePrefix(forbiddenPrefix, prefixDescription) { if (value.startsWith(forbiddenPrefix)) { throw "Value '" + value + "' for exported property '" + propName + "' in product '" + product.name + "' points into " + prefixDescription + ".\n" + "Did you forget to set the prefixMapping property in an Export item?"; } } // Catch user oversights: Paths that point into the project source or build directories // make no sense in the module. if (!value.startsWith(product.qbs.installRoot)) { checkValuePrefix(project.buildDirectory, "project build directory"); checkValuePrefix(project.sourceDirectory, "project source directory"); } // Adapt file paths pointing into the install dir, that is, make them relative to the // module file for relocatability. We accept them with or without the install root. // The latter form will typically be a result of applying the prefixMapping property, // while the first one could be an untransformed path, for instance if the project // file is written in such a way that include paths are picked up from the installed // location rather than the source directory. var result; var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) { result = fullInstallPrefix; } else { var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix); if (installPrefix.length > 1 && value.startsWith(installPrefix)) result = installPrefix; } return result; } qbs-src-3.3.1/share/qbs/modules/Exporter/cmake/0000755000175100017510000000000015232633614020732 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Exporter/cmake/cmakeexporter.js0000644000175100017510000002431315232633614024144 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Raphaël Cotty ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var ExporterHelpers = require("../exporter.js"); function tagListToString(tagList) { return JSON.stringify(tagList); } function collectAutodetectedData(project, topLevelProduct, outputs) { var packageName = topLevelProduct.Exporter.cmake.packageName; var data = {}; data.packageName = packageName; data.installPrefixDir = "_" + packageName.toUpperCase() + "_INSTALL_PREFIX"; data.packages = []; function quote(value) { return "\"" + value + "\""; } function quoteAndPrefixify(propName) { function quoteAndPrefixifyHelper(value) { var prefixToStrip = ExporterHelpers.getPrefixToStrip(project, topLevelProduct, propName, value); if (typeof value !== "string" || !prefixToStrip || (value.length > prefixToStrip.length && value[prefixToStrip.length] !== '/')) { return quote(value); } return quote("${" + data.installPrefixDir + "}" + value.slice(prefixToStrip.length)); } return quoteAndPrefixifyHelper; } var installedOutputFilePath = ModUtils.artifactInstalledFilePath( outputs["Exporter.cmake.configFile"][0]); var installedOutputPathName = FileInfo.path(installedOutputFilePath); var installRootPath = FileInfo.joinPaths(topLevelProduct.qbs.installRoot, topLevelProduct.qbs.installPrefix); data.installPrefix = FileInfo.relativePath(installedOutputPathName, installRootPath); var libArtifacts; var libImportArtifacts; var isProduct = !topLevelProduct.present; var considerFramework = !isProduct || (topLevelProduct.type && topLevelProduct.type.includes("bundle.content")) && topLevelProduct.bundle && topLevelProduct.bundle.isBundle && topLevelProduct.qbs.targetOS.includes("darwin"); var considerDynamicLibs = !isProduct || (topLevelProduct.type && topLevelProduct.type.includes("dynamiclibrary")); var considerStaticLibs = !isProduct || (topLevelProduct.type && topLevelProduct.type.includes("staticlibrary")); if (considerFramework) { libArtifacts = topLevelProduct.artifacts["bundle.symlink.executable"]; if (considerDynamicLibs) data.type = "SHARED"; else if (considerStaticLibs) data.type = "STATIC"; else data.type = "INTERFACE"; } else if (considerDynamicLibs) { libArtifacts = topLevelProduct.artifacts.dynamiclibrary; libImportArtifacts = topLevelProduct.artifacts.dynamiclibrary_import; data.type = "SHARED"; } else if (considerStaticLibs) { libArtifacts = topLevelProduct.artifacts.staticlibrary; data.type = "STATIC"; } else { data.type = "INTERFACE"; } for (var i = 0; i < (libArtifacts || []).length; ++i) { var libArtifact = libArtifacts[i]; var libImportArtifact = (libImportArtifacts || [])[i]; if (libArtifact.qbs.install) { var installPath = ModUtils.artifactInstalledFilePath(libArtifact); data.importedLocation = quoteAndPrefixify("installRoot")(installPath); data.soName = topLevelProduct.targetName; if (libImportArtifact && libImportArtifact.qbs.install) { installPath = ModUtils.artifactInstalledFilePath(libImportArtifact); data.importedImplibLocation = quoteAndPrefixify("installRoot")(installPath); } break; } } var cpp = topLevelProduct.exports.cpp; if (cpp) { data.libraryPaths = (cpp.libraryPaths || []).map(quoteAndPrefixify("cpp.libraryPaths")); data.linkLibraries = []; data.linkLibraries = data.linkLibraries.concat(cpp.dynamicLibraries || []); data.linkLibraries = data.linkLibraries.concat(cpp.staticLibraries || []); data.linkLibraries = data.linkLibraries.concat(cpp.libraries || []); data.linkLibraries = data.linkLibraries.map(quoteAndPrefixify("cpp.dynamicLibraries")); data.linkOptions = []; data.linkOptions = data.linkOptions.concat(cpp.driverLinkerFlags || []); if ((cpp.linkerFlags || []).length > 0) { data.linkOptions = data.linkOptions.concat("LINKER:" + (cpp.linkerFlags || []).join(",")); } data.linkOptions = data.linkOptions.map(quote); data.includeDirectories = (cpp.includePaths || []).map(quoteAndPrefixify("cpp.includePaths")); data.compileDefinitions = (cpp.defines || []).map(quote); data.compileOptions = []; data.compileOptions = data.compileOptions.concat(cpp.commonCompilerFlags || []); data.compileOptions = data.compileOptions.concat(cpp.driverFlags || []); data.compileOptions = data.compileOptions.concat(cpp.cxxFlags || []); data.compileOptions = data.compileOptions.concat(cpp.cFlags || []); data.compileOptions = data.compileOptions.map(quote); } function gatherDeps(dep) { if (dep.name === "Exporter.cmake") return; var depHasExporter = dep.Exporter && dep.Exporter.cmake; if (!depHasExporter) return; data.packages.push(dep.Exporter.cmake.packageName); } var exportedDeps = topLevelProduct.exports ? topLevelProduct.exports.dependencies : []; exportedDeps.forEach(gatherDeps); return data; } function writeConfigFile(project, product, outputs) { var autoDetectedData = collectAutodetectedData(project, product, outputs); var packageName = autoDetectedData.packageName; function writeCommand(command, lines) { if ((lines || []).length === 0) return; cmakeConfigFile.writeLine(command + "(" + packageName + " INTERFACE"); for (i = 0; i < lines.length; i++) { cmakeConfigFile.writeLine(" " + lines[i]); } cmakeConfigFile.writeLine(")"); } var cmakeConfigFile = new TextFile(outputs["Exporter.cmake.configFile"][0].filePath, TextFile.WriteOnly); cmakeConfigFile.writeLine("# Generated by Qbs"); cmakeConfigFile.writeLine("cmake_minimum_required(VERSION 3.5)"); cmakeConfigFile.writeLine("if(TARGET " + packageName + ")"); cmakeConfigFile.writeLine(" return()"); cmakeConfigFile.writeLine("endif()"); cmakeConfigFile.writeLine("set(" + autoDetectedData.installPrefixDir + " \"${CMAKE_CURRENT_LIST_DIR}/" + autoDetectedData.installPrefix + "\")"); autoDetectedData.packages.forEach(function(packageName) { cmakeConfigFile.writeLine("find_package(" + packageName + " REQUIRED SILENT)"); }); cmakeConfigFile.writeLine( "add_library(" + packageName + " " + autoDetectedData.type + " IMPORTED)"); var configuration = (product.qbs.buildVariant) ? product.qbs.buildVariant.toUpperCase() : "NONE"; cmakeConfigFile.writeLine("set_property(TARGET " + packageName + " APPEND PROPERTY IMPORTED_CONFIGURATIONS " + configuration + ")"); cmakeConfigFile.writeLine("set_target_properties(" + packageName + " PROPERTIES"); cmakeConfigFile.writeLine(" IMPORTED_LINK_INTERFACE_LANGUAGES_" + configuration + " CXX"); if (autoDetectedData.type !== "INTERFACE") { cmakeConfigFile.writeLine(" IMPORTED_LOCATION_" + configuration + " " + autoDetectedData.importedLocation); } if (autoDetectedData.importedImplibLocation) { cmakeConfigFile.writeLine(" IMPORTED_IMPLIB_" + configuration + " " + autoDetectedData.importedImplibLocation); } cmakeConfigFile.writeLine(")"); writeCommand("target_link_directories", autoDetectedData.libraryPaths); writeCommand("target_link_libraries", autoDetectedData.linkLibraries.concat(autoDetectedData.packages)); writeCommand("target_link_options", autoDetectedData.linkOptions); writeCommand("target_include_directories", autoDetectedData.includeDirectories); writeCommand("target_compile_definitions", autoDetectedData.compileDefinitions); writeCommand("target_compile_options", autoDetectedData.compileOptions); cmakeConfigFile.close(); } function writeVersionFile(product, outputs) { var cmakeVersionFile = new TextFile( outputs["Exporter.cmake.versionFile"][0].filePath, TextFile.WriteOnly); cmakeVersionFile.writeLine("# Generated by Qbs"); cmakeVersionFile.writeLine("set(PACKAGE_VERSION \"" + product.version + "\")"); cmakeVersionFile.close(); } qbs-src-3.3.1/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs0000644000175100017510000000643515232633614024322 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Raphaël Cotty ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.TextFile import "cmakeexporter.js" as HelperFunctions Module { property string configFileName: packageName + "Config.cmake" property string versionFileName: packageName + "ConfigVersion.cmake" property string packageName: product.targetName additionalProductTypes: ["Exporter.cmake.package"] Rule { multiplex: true requiresInputs: false auxiliaryInputs: { if (product.type.includes("staticlibrary")) return ["staticlibrary"]; if (product.type.includes("dynamiclibrary")) return ["dynamiclibrary"]; } Artifact { filePath: product.Exporter.cmake.configFileName fileTags: ["Exporter.cmake.package", "Exporter.cmake.configFile"] } Artifact { filePath: product.Exporter.cmake.versionFileName fileTags: ["Exporter.cmake.package", "Exporter.cmake.versionFile"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generate cmake package files"; cmd.sourceCode = function() { HelperFunctions.writeConfigFile(project, product, outputs); HelperFunctions.writeVersionFile(product, outputs); } return [cmd]; } } } qbs-src-3.3.1/share/qbs/modules/emsdk/0000755000175100017510000000000015232633614017145 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/emsdk/emsdk.js0000644000175100017510000001015315232633614020606 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Danya Patrushev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ var Process = require("qbs.Process"); var Host = require("qbs.Host"); var FileInfo = require("qbs.FileInfo"); var File = require("qbs.File"); var Environment = require("qbs.Environment"); function getEnvironment(shellPath, emccDir) { var winOs = Host.os().includes("windows") var emsdkEnvFileName = "emsdk_env." + (winOs ? "bat" : "sh") var sep = FileInfo.pathSeparator() //if the compiler comes from emsdk its directory should be */emsdk/upstream/emscripten/ var emsdkEnvFilePath = FileInfo.cleanPath(emccDir + sep + ".." + sep + ".." + sep + emsdkEnvFileName) if (!File.exists(emsdkEnvFilePath)) { if (!winOs) { console.info("Emcc compiler found but " + emsdkEnvFilePath + " doesn't exist - assuming compiler is provided by system package") return {} } else throw emsdkEnvFilePath + " not found"; } else { var env = {} // If the environment already contains emsdk specific variables, running the script // will return a concise message about "Setting up EMSDK environment" without all // the data that we need, so we check the environment first. var dir = Environment.getEnv("EMSDK") //use it as an indication that the environment is already set if (dir) { env["EMSDK"] = dir; var python = Environment.getEnv("EMSDK_PYTHON") if (python) env["EMSDK_PYTHON"] = python; var node = Environment.getEnv("EMSDK_NODE"); if (node) env["EMSDK_NODE"] = node; } else { var process = new Process(); process.exec(shellPath, [emsdkEnvFilePath]); var equalStr = " = "; var lines = process.readStdErr().split("\n"); for (var i in lines) { var line = lines[i]; var index = line.indexOf(equalStr); if (index === -1) continue; var key = line.slice(0, index); if (key === "PATH") continue; env[key] = line.slice(index + equalStr.length); } } return env; } } qbs-src-3.3.1/share/qbs/modules/emsdk/emsdk.qbs0000644000175100017510000000135415232633614020762 0ustar runnerrunnerimport qbs.Probes import "emsdk.js" as Emsdk Module { property string configuredInstallPath property string detectedInstallPath: emccPathProbe.found ? emccPathProbe.path : undefined Probes.BinaryProbe { id: emccPathProbe condition: !configuredInstallPath names: ["emcc"] } property var environment: emsdkEnvProbe.environment Probe { id: emsdkEnvProbe property string emccDir: configuredInstallPath || detectedInstallPath property string shellPath: product.qbs.shellPath property var environment condition: emccDir configure: { environment = Emsdk.getEnvironment(shellPath, emccDir); found = true; } } } qbs-src-3.3.1/share/qbs/modules/wix/0000755000175100017510000000000015232633614016651 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/wix/WiXModule.qbs0000644000175100017510000004205615232633614021244 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Probes import qbs.Utilities Module { condition: qbs.targetOS.includes("windows") Probes.WiXProbe { id: wixProbe } property path toolchainInstallPath: wixProbe.path property path toolchainInstallRoot: wixProbe.root version: wixProbe.version property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string compilerName: "candle.exe" property string compilerPath: FileInfo.joinPaths(toolchainInstallRoot, compilerName) property string linkerName: "light.exe" property string linkerPath: FileInfo.joinPaths(toolchainInstallRoot, linkerName) property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "pedantic"] } property bool debugInformation: qbs.debugInformation property bool treatWarningsAsErrors: false property bool verboseOutput: false PropertyOptions { name: "verboseOutput" description: "display verbose output from the compiler and linker" } property bool visualStudioCompatibility: true PropertyOptions { name: "visualStudioCompatibility" description: "whether to define most of the same variables as " + "Visual Studio when using the Candle compiler" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the Candle compiler" } property pathList includePaths PropertyOptions { name: "includePaths" description: "directories to add to the include search path" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the Candle compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the Candle compiler" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional flags for the Light linker" } property stringList cultures PropertyOptions { name: "cultures" description: "the list of localizations to build the MSI for; leave undefined to build all localizations" } property stringList extensions: product.type.includes("wixsetup") ? ["WixBalExtension"] : [] // default to WiX Standard Bootstrapper extension // private properties property string targetSuffix: { if (product.type.includes("msi")) { return windowsInstallerSuffix; } else if (product.type.includes("wixsetup")) { return executableSuffix; } } // MSI/MSM package validation only works natively on Windows property bool enablePackageValidation: Host.os().includes("windows") property string executableSuffix: ".exe" property string windowsInstallerSuffix: ".msi" validate: { var validator = new ModUtils.PropertyValidator("wix"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("toolchainInstallRoot", toolchainInstallRoot); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true); v.prepend(product.wix.toolchainInstallPath); v.prepend(product.wix.toolchainInstallRoot); v.set(); } // WiX Include Files FileTagger { patterns: ["*.wxi"] fileTags: ["wxi"] } // WiX Localization Files FileTagger { patterns: ["*.wxl"] fileTags: ["wxl"] } // WiX Source Files FileTagger { patterns: ["*.wxs"] fileTags: ["wxs"] } Rule { id: candleCompiler inputs: ["wxs"] auxiliaryInputs: ["wxi", "installable"] auxiliaryInputsFromDependencies: ["wxi", "installable"] Artifact { fileTags: ["wixobj"] filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), FileInfo.baseName(input.fileName) + ".wixobj") } prepare: { var i; var args = ["-nologo"]; if (ModUtils.moduleProperty(input, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(input, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(input, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(input, "verboseOutput")) { args.push("-v"); } var arch = product.moduleProperty("qbs", "architecture"); // http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html switch (arch) { case "x86_64": arch = "x64"; break; case "armv7": case "armv7a": arch = "arm"; break; } // Visual Studio defines these variables along with various solution and project names and paths; // we'll pass most of them to ease compatibility between QBS and WiX projects originally created // using Visual Studio. The only definitions we don't pass are the ones which make no sense at all // in QBS, like the solution and project directories since they do not exist. if (ModUtils.moduleProperty(input, "visualStudioCompatibility")) { var toolchain = product.moduleProperty("qbs", "toolchain"); var toolchainInstallPath = product.moduleProperty("cpp", "toolchainInstallPath"); if (toolchain && toolchain.includes("msvc") && toolchainInstallPath) { var vcDir = toolchainInstallPath.replace(/[\\/]bin$/i, ""); var vcRootDir = vcDir.replace(/[\\/]VC$/i, ""); args.push("-dDevEnvDir=" + FileInfo.toWindowsSeparators(FileInfo.joinPaths(vcRootDir, 'Common7', 'IDE'))); } var buildVariant = product.moduleProperty("qbs", "buildVariant"); if (buildVariant === "debug") { args.push("-dDebug"); args.push("-dConfiguration=Debug"); } else if (buildVariant === "release") { // VS doesn't define "Release" args.push("-dConfiguration=Release"); } var productTargetExt = ModUtils.moduleProperty(input, "targetSuffix"); if (!productTargetExt) { throw("WiX: Unsupported product type '" + product.type + "'"); } var builtBinaryFilePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName + productTargetExt); args.push("-dOutDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, relative to the project file by default args.push("-dPlatform=" + (arch || "x86")); args.push("-dProjectName=" + project.name); args.push("-dTargetDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, an absolute path args.push("-dTargetExt=" + productTargetExt); args.push("-dTargetFileName=" + product.targetName + productTargetExt); args.push("-dTargetName=" + product.targetName); args.push("-dTargetPath=" + FileInfo.toWindowsSeparators(builtBinaryFilePath)); } var includePaths = ModUtils.moduleProperty(input, "includePaths"); for (i in includePaths) { args.push("-I" + includePaths[i]); } var enableQbsDefines = ModUtils.moduleProperty(input, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push("-d" + prefix + prop + "=" + val); } } } // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x64" || arch === "ia64") { args.push("-dWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperty(input, "defines"); for (i in defines) { args.push("-d" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperty(input, "compilerFlags"); for (i in flags) { args.push(flags[i]); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(output.filePath)); if (arch) { args.push("-arch"); args.push(arch); } var extensions = ModUtils.moduleProperty(input, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } args.push(FileInfo.toWindowsSeparators(input.filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); // candle.exe outputs the file name. We filter that out. cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { return output.split(inputFileName + "\r\n").join(""); }; return cmd; } } Rule { id: lightLinker multiplex: true inputs: ["wixobj", "wxl"] auxiliaryInputs: ["installable"] auxiliaryInputsFromDependencies: ["installable"] inputsFromDependencies: product.type.includes("wixsetup") ? ["msi"] : [] outputArtifacts: { var artifacts = []; if (product.type.includes("wixsetup")) { artifacts.push({ fileTags: ["wixsetup", "application"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "executableSuffix")) }); } if (product.type.includes("msi")) { artifacts.push({ fileTags: ["msi"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "windowsInstallerSuffix")) }); } if (ModUtils.moduleProperty(product, "debugInformation")) { artifacts.push({ fileTags: ["wixpdb"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".wixpdb") }); } return artifacts; } outputFileTags: ["application", "msi", "wixpdb", "wixsetup"] prepare: { var i; var primaryOutput; if (product.type.includes("wixsetup")) { primaryOutput = outputs.wixsetup[0]; } else if (product.type.includes("msi")) { primaryOutput = outputs.msi[0]; } else { throw("WiX: Unsupported product type '" + product.type + "'"); } var args = ["-nologo"]; if (!ModUtils.moduleProperty(product, "enablePackageValidation")) { args.push("-sval"); } if (ModUtils.moduleProperty(product, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(product, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(product, "verboseOutput")) { args.push("-v"); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(primaryOutput.filePath)); if (ModUtils.moduleProperty(product, "debugInformation")) { args.push("-pdbout"); args.push(FileInfo.toWindowsSeparators(outputs.wixpdb[0].filePath)); } else { args.push("-spdb"); } var extensions = ModUtils.moduleProperty(product, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } for (i in inputs.wxl) { args.push("-loc"); args.push(FileInfo.toWindowsSeparators(inputs.wxl[i].filePath)); } if (product.type.includes("msi")) { var cultures = ModUtils.moduleProperty(product, "cultures"); args.push("-cultures:" + (cultures && cultures.length > 0 ? cultures.join(";") : "null")); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "linkerFlags"); for (i in flags) { args.push(flags[i]); } for (i in inputs.wixobj) { args.push(FileInfo.toWindowsSeparators(inputs.wixobj[i].filePath)); } var cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); return cmd; } } } qbs-src-3.3.1/share/qbs/modules/cli/0000755000175100017510000000000015232633614016611 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/cli/mono.qbs0000644000175100017510000000123115232633614020265 0ustar runnerrunnerimport qbs.File import qbs.Host import qbs.Probes CLIModule { condition: qbs.toolchain && qbs.toolchain.includes("mono") debugInfoSuffix: ".mdb" csharpCompilerName: "mcs" vbCompilerName: "vbnc" fsharpCompilerName: "fsharpc" Probes.PathProbe { id: monoProbe names: ["mono"] platformSearchPaths: { var paths = []; if (Host.os().includes("macos")) paths.push("/Library/Frameworks/Mono.framework/Commands"); if (Host.os().includes("unix")) paths.push("/usr/bin"); return paths; } } toolchainInstallPath: monoProbe.path } qbs-src-3.3.1/share/qbs/modules/cli/CLIModule.qbs0000644000175100017510000001553715232633614021110 0ustar runnerrunner// base for Common Language Infrastructure modules import qbs.FileInfo import qbs.Host import qbs.ModUtils import "cli.js" as CLI Module { Group { condition: qbs.targetOS.includes("darwin") Depends { name: "bundle" } product.bundle.isBundle: false } condition: false property string warningLevel: 'all' // 'none', 'all' property bool treatWarningsAsErrors: false property string architecture: "anycpu" // for the CLI this is a much better default than qbs.architecture property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property stringList defines property stringList platformDefines: qbs.enableDebugCode ? [] : ["NDEBUG"] property stringList compilerDefines PropertyOptions { name: "compilerDefines" description: "preprocessor macros that are defined when using this particular compiler" } property pathList libraryPaths property string csharpCompilerName property string csharpCompilerPath: FileInfo.joinPaths(toolchainInstallPath, csharpCompilerName) property string vbCompilerName property string vbCompilerPath: FileInfo.joinPaths(toolchainInstallPath, vbCompilerName) property string fsharpCompilerName property string fsharpCompilerPath: FileInfo.joinPaths(toolchainInstallPath, fsharpCompilerName) property string resgenName: "resgen" property string resgenPath: FileInfo.joinPaths(toolchainInstallPath, resgenName) property string dynamicLibrarySuffix: ".dll" property string executableSuffix: ".exe" property string netmoduleSuffix: ".netmodule" property string debugInfoSuffix property stringList dynamicLibraries // list of names, will be linked with /reference:name property stringList netmodules // list of netmodule files, will be linked with /addmodule:name property bool generateManifestFile: true property string toolchainInstallPath property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional compiler flags" } // Platform properties. Those are intended to be set by the toolchain setup // and are prepended to the corresponding user properties. property stringList platformCompilerFlags FileTagger { patterns: ["*.cs", "*.CS"] fileTags: ["cli.csharp"] } FileTagger { patterns: ["*.vb", "*.VB"] fileTags: ["cli.vb"] } FileTagger { patterns: ["*.fs", "*.FS"] fileTags: ["cli.fsharp"] } FileTagger { patterns: ["*.fsi", "*.FSI"] fileTags: ["cli.fsharp_signature"] } FileTagger { patterns: ["*.resx", "*.RESX"] fileTags: ["cli.resx"] } validate: { var validator = new ModUtils.PropertyValidator("cli"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.validate(); } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().includes("windows")); v.prepend(product.cli.toolchainInstallPath); v.set(); } Rule { id: cliApplication multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["application"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "executableSuffix")) } Artifact { fileTags: ["debuginfo_app"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: CLI.prepareCompiler(product, inputs, outputs.application[0]) } Rule { id: cliDynamicLibrary multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["dynamiclibrary"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "dynamicLibrarySuffix")) } Artifact { fileTags: ["debuginfo_dll"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: CLI.prepareCompiler(product, inputs, outputs.dynamiclibrary[0]) } Rule { id: netmodule multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["cli.netmodule"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "netmoduleSuffix")) } Artifact { fileTags: ["debuginfo_netmodule"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: CLI.prepareCompiler(product, inputs, outputs["cli.netmodule"][0]) } Rule { inputs: ["cli.resx"] Artifact { fileTags: ["cli.resources"] filePath: FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + ".resources") } prepare: { var args = [ input.filePath, output.filePath ]; var cmd = new Command(ModUtils.moduleProperty(product, "resgenPath"), args); cmd.description = "building " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } } qbs-src-3.3.1/share/qbs/modules/cli/windows-dotnet.qbs0000644000175100017510000000200715232633614022304 0ustar runnerrunnerimport qbs.Utilities CLIModule { condition: qbs.toolchain && qbs.toolchain.includes("dotnet") debugInfoSuffix: ".pdb" csharpCompilerName: "csc" vbCompilerName: "vbc" fsharpCompilerName: "fsc" Probe { id: dotnetProbe property string toolchainInstallPath // Output configure: { // https://msdn.microsoft.com/en-us/library/hh925568.aspx var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\NET Framework Setup\\NDP" ]; for (var i in keys) { var key = keys[i] + "\\v4\\Full"; var value = Utilities.getNativeSetting(key, "InstallPath"); if (value) { toolchainInstallPath = value; found = true; break; } } } } toolchainInstallPath: dotnetProbe.toolchainInstallPath } qbs-src-3.3.1/share/qbs/modules/cli/cli.js0000644000175100017510000001621315232633614017721 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function prepareCompiler(product, inputs, output) { var i; var args = ["/nologo"]; var platformDefines = product.moduleProperty("cli", "platformDefines"); var compilerDefines = product.moduleProperty("cli", "compilerDefines"); var defines = product.moduleProperty("cli", "defines"); var platformCompilerFlags = product.moduleProperty("cli", "platformCompilerFlags"); var compilerFlags = product.moduleProperty("cli", "compilerFlags") var libraryPaths = product.moduleProperty("cli", "libraryPaths"); var dynamicLibraries = product.moduleProperty("cli", "dynamicLibraries"); var netmodules = product.moduleProperty("cli", "netmodules"); var warnAsError = product.moduleProperty("cli", "treatWarningsAsErrors"); var warningLevel = product.moduleProperty("cli", "warningLevel"); var debugInformation = product.moduleProperty("cli", "debugInformation"); var optimization = product.moduleProperty("cli", "optimization"); var architecture = product.moduleProperty("cli", "architecture"); var csharpCompilerPath = product.moduleProperty("cli", "csharpCompilerPath"); var vbCompilerPath = product.moduleProperty("cli", "vbCompilerPath"); var fsharpCompilerPath = product.moduleProperty("cli", "fsharpCompilerPath"); var compilers = { "cli.csharp": csharpCompilerPath, "cli.vb": vbCompilerPath, "cli.fsharp": fsharpCompilerPath }; var pathFunction = product.moduleProperty("qbs", "hostOS").includes("windows") ? FileInfo.toWindowsSeparators : function (path) { return path; }; var outputDescription = "assembly"; if (output.fileTags.includes("application")) { args.push("/target:" + (product.consoleApplication === false ? "winexe" : "exe")); } else if (output.fileTags.includes("dynamiclibrary")) { args.push("/target:library"); } else if (output.fileTags.includes("cli.netmodule")) { args.push("/target:module"); outputDescription = "netmodule"; } // Make sure our input files are all the same language var keys = Object.keys(inputs); var language; for (i in keys) { if (Object.keys(compilers).includes(keys[i])) { if (language) throw("You cannot compile source files in more than one CLI language into a single " + outputDescription + "."); language = keys[i]; } } if (!compilers[language]) { throw("No CLI compiler available to compile " + language + " files."); } // docs state "/platform is not available in the development environment in Visual C# Express" // does this mean from the IDE or the compiler itself shipped with Express does not support it? if (architecture !== undefined) { if (architecture === "x86" || architecture === "anycpu" || architecture === "anycpu32bitpreferred") // requires .NET 4.5 ; else if (architecture === "x86_64") architecture = "x64"; else if (architecture === "ia64") architecture = "Itanium"; else if (architecture === "arm") architecture = "ARM"; else throw("Invalid CLI architecture: " + architecture); args.push("/platform:" + architecture); } if (debugInformation !== undefined) args.push("/debug" + (debugInformation ? "+" : "-")); if (optimization !== undefined) args.push("/optimize" + (optimization !== "none" ? "+" : "-")); if (warnAsError !== undefined) args.push("/warnaserror" + (warnAsError ? "+" : "-")); if (warningLevel !== undefined) { if (language === "cli.vb") { if (warningLevel === "none" || warningLevel === "0") args.push("/quiet"); } else { if (warningLevel === "all") warningLevel = "4"; else if (warningLevel === "none") warningLevel = "0"; args.push("/warn:" + warningLevel); } } // Preprocessor defines var allDefines = (platformDefines || []).concat(compilerDefines || []).concat(defines || []); if (allDefines.length > 0) args.push("/define:" + allDefines.join(";")); // Library search paths for (i in libraryPaths) args.push("/lib:" + libraryPaths.join(",")); // Dependent libraries for (i in dynamicLibraries) { args.push("/reference:" + dynamicLibraries[i] + product.moduleProperty("cli", "dynamicLibrarySuffix")); } for (i in inputs.dynamiclibrary) args.push("/reference:" + inputs.dynamiclibrary[i].filePath); // Dependent netmodules for (i in netmodules) { args.push("/addmodule:" + netmodules.map(function (f) { return f + product.moduleProperty("cli", "netmoduleSuffix"); }).join(";")); } if (inputs["cli.netmodule"]) { args.push("/addmodule:" + inputs["cli.netmodule"].map(function (f) { return f.filePath; }).join(";")); } // Dependent resources for (i in inputs["cli.resources"]) args.push("/resource:" + pathFunction(inputs["cli.resources"][i].filePath)); // Additional compiler flags args = args.concat((platformCompilerFlags || []).concat(compilerFlags || [])); args.push("/out:" + pathFunction(output.filePath)); for (i in inputs[keys[0]]) args.push(pathFunction(inputs[keys[0]][i].filePath)); var cmd = new Command(compilers[language], args); cmd.description = "linking " + output.fileName; cmd.highlight = "linker"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } qbs-src-3.3.1/share/qbs/modules/dmg/0000755000175100017510000000000015232633614016611 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/dmg/DMGModule.qbs0000644000175100017510000001305215232633614021076 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Process import qbs.Probes import qbs.TextFile import "dmg.js" as Dmg Module { Depends { name: "xcode"; required: false } condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin") property string volumeName: product.targetName PropertyOptions { name: "volumeName" description: "the name of the disk image (displayed in Finder when mounted)" } property bool badgeVolumeIcon: false PropertyOptions { name: "badgeVolumeIcon" description: "whether to render the user-supplied icon on top of the " + "default volume icon instead of using it directly" } property string format: "UDBZ" PropertyOptions { name: "format" description: "the format to create the disk image in" } property int compressionLevel: qbs.buildVariant === "release" ? 9 : undefined PropertyOptions { name: "compressionLevel" description: "sets the zlib or bzip2 compression level for UDZO and UDBZ disk images" } property string textutilPath: "/usr/bin/textutil" property string hdiutilPath: "/usr/bin/hdiutil" property string dmgSuffix: ".dmg" property string sourceBase Probes.BinaryProbe { id: pythonProbe names: ["python3"] } property string pythonExePath: pythonProbe.found ? pythonProbe.filePath : "python3" readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path, "..", "..", "python")) property string backgroundColor property int iconSize: 128 property int windowX: 100 property int windowY: 100 property int windowWidth: 640 property int windowHeight: 480 property var iconPositions property int iconX: windowWidth / 2 property int iconY: windowHeight / 2 property string defaultLicenseLocale property string licenseLocale property string licenseLanguageName property string licenseAgreeButtonText property string licenseDisagreeButtonText property string licensePrintButtonText property string licenseSaveButtonText property string licenseInstructionText FileTagger { patterns: [ "*.txt", "*.rtf", "*.html", "*.doc", "*.docx", "*.odt", "*.xml", "*.webarchive", "LICENSE" ] fileTags: ["dmg.license.input"] } FileTagger { patterns: ["*.icns"] fileTags: ["icns"] } FileTagger { patterns: ["*.tif", "*.tiff"] fileTags: ["tiff"] } Rule { inputs: ["dmg.license.input"] outputFileTags: ["dmg.license"] outputArtifacts: ([{ filePath: FileInfo.joinPaths(product.destinationDirectory, "licenses", FileInfo.relativePath(product.sourceDirectory, input.filePath) + ".rtf"), fileTags: ["dmg.license"], dmg: { licenseLocale: input.dmg.licenseLocale, licenseLanguageName: input.dmg.licenseLanguageName, licenseAgreeButtonText: input.dmg.licenseAgreeButtonText, licenseDisagreeButtonText: input.dmg.licenseDisagreeButtonText, licensePrintButtonText: input.dmg.licensePrintButtonText, licenseSaveButtonText: input.dmg.licenseSaveButtonText, licenseInstructionText: input.dmg.licenseInstructionText } }]) prepare: Dmg.prepareLicense.apply(Dmg, arguments) } Rule { multiplex: true inputs: ["dmg.input", "dmg.license", "icns", "tiff"] Artifact { fileTags: ["dmg.dmg"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.dmg.dmgSuffix) } prepare: Dmg.prepareDmg.apply(Dmg, arguments) } } qbs-src-3.3.1/share/qbs/modules/dmg/dmg.js0000644000175100017510000002053115232633614017717 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var DarwinTools = require("qbs.DarwinTools"); var FileInfo = require("qbs.FileInfo"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function localizationFromArtifact(input) { var locale = input.dmg.licenseLocale || DarwinTools.localizationKey(input.filePath); if (!locale) throw("Could not determine localization for license file: " + input.filePath); return locale; } function dmgbuildSettings(product, inputs) { var backgroundImages = inputs["tiff"]; var backgroundImage; if (backgroundImages) { if (backgroundImages.length > 1) throw new Error("only one background image may be specified"); backgroundImage = backgroundImages[0].filePath; } var volumeIcons = inputs["icns"]; var volumeIcon; if (volumeIcons) { if (volumeIcons.length > 1) throw new Error("only one volume icon may be specified"); volumeIcon = volumeIcons[0].filePath; } var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"] || [], function (a) { return { "dmg": { "licenseLocale": localizationFromArtifact(a), "licenseLanguageName": a.dmg.licenseLanguageName, "licenseAgreeButtonText": a.dmg.licenseAgreeButtonText, "licenseDisagreeButtonText": a.dmg.licenseDisagreeButtonText, "licensePrintButtonText": a.dmg.licensePrintButtonText, "licenseSaveButtonText": a.dmg.licenseSaveButtonText, "licenseInstructionText": a.dmg.licenseInstructionText, }, "filePath": a.filePath }; }); function reduceLicensesForKey(licenseFileObjects, key) { return licenseFileObjects.reduce(function (accumulator, currentValue) { var locale = currentValue.dmg.licenseLocale; if (accumulator[locale]) throw new Error("Multiple license files for localization '" + locale + "'"); switch (key) { case "licenses": accumulator[locale] = currentValue.filePath; break; case "buttons": var texts = [ currentValue.dmg.licenseLanguageName, currentValue.dmg.licenseAgreeButtonText, currentValue.dmg.licenseDisagreeButtonText, currentValue.dmg.licensePrintButtonText, currentValue.dmg.licenseSaveButtonText, currentValue.dmg.licenseInstructionText ]; accumulator[locale] = texts.every(function (a) { return !!a; }) ? texts : undefined; break; } return accumulator; }, {}); } var contentsArray = Array.prototype.map.call(inputs["dmg.input"] || [], function (a) { if (a.dmg.sourceBase && !a.filePath.startsWith(a.dmg.sourceBase)) { throw new Error("Cannot install '" + a.filePath + "', " + "because it doesn't start with the value of " + "dmg.sourceBase '" + a.dmg.sourceBase + "'."); } var isSymlink = a.fileTags.includes("dmg.input.symlink"); return { "x": a.dmg.iconX, "y": a.dmg.iconY, "type": isSymlink ? "link" : "file", "path": isSymlink ? a.dmg.symlinkTarget : a.filePath, "name": FileInfo.relativePath(a.dmg.sourceBase || FileInfo.path(a.filePath), a.filePath) }; }); Array.prototype.forEach.call(product.dmg.iconPositions || [], function (obj) { var existingIndex = -1; Array.prototype.forEach.call(contentsArray, function (contentsItem, i) { if (contentsItem["name"] === obj["path"]) existingIndex = i; }); if (existingIndex >= 0) { contentsArray[existingIndex]["x"] = obj["x"]; contentsArray[existingIndex]["y"] = obj["y"]; } else { contentsArray.push({ "type": "position", "name": obj["path"], // name => path is not a typo "path": obj["path"], "x": obj["x"], "y": obj["y"] }); } }); var result = { "title": product.dmg.volumeName, "icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined, "badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined, "background": backgroundImage, "background-color": product.dmg.backgroundColor, "icon-size": product.dmg.iconSize, "window": { "position": { "x": product.dmg.windowX, "y": product.dmg.windowY }, "size": { "width": product.dmg.windowWidth, "height": product.dmg.windowHeight } }, "format": product.dmg.format, "compression-level": product.dmg.compressionLevel, "contents": contentsArray }; if (licenseFileObjects.length >= 0) { result["license"] = { "default-language": product.dmg.defaultLicenseLocale, "licenses": reduceLicensesForKey(licenseFileObjects, "licenses"), "buttons": reduceLicensesForKey(licenseFileObjects, "buttons") }; } return result; } function prepareLicense(project, product, inputs, outputs, input, output) { var cmd = new Command(product.dmg.textutilPath, [ "-convert", "rtf", "-strip", "-font", "Arial", "-output", output.filePath, "--", input.filePath ]); cmd.description = "converting " + input.fileName; return [cmd]; } function prepareDmg(project, product, inputs, outputs, input, output) { var i; var cmd; var cmds = []; var settingsJsonFilePath = FileInfo.joinPaths(product.destinationDirectory, "settings.json"); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.settingsJSON = dmgbuildSettings(product, inputs); cmd.settingsJsonFilePath = settingsJsonFilePath; cmd.sourceCode = function () { var tf; try { tf = new TextFile(settingsJsonFilePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(settingsJSON, undefined, 4)); } finally { if (tf) tf.close(); } } cmds.push(cmd); // Create the actual DMG via dmgbuild cmd = new Command(product.dmg.pythonExePath, ["-m", "dmgbuild", product.dmg.volumeName, output.filePath, "--no-hidpi", // qbs handles this by itself "--settings", settingsJsonFilePath]); cmd.environment = ["PYTHONPATH=" + product.dmg.pythonPath]; cmd.description = "creating " + output.fileName; cmds.push(cmd); return cmds; } qbs-src-3.3.1/share/qbs/modules/pkgconfig/0000755000175100017510000000000015232633614020011 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/pkgconfig/pkgconfig.qbs0000644000175100017510000000507115232633614022472 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.File import qbs.Probes Module { Probes.BinaryProbe { id: pkgconfigProbe names: "pkg-config" } property path sysroot: { if (qbs.targetOS.includes("macos")) return ""; return qbs.sysroot; } property string executableFilePath: pkgconfigProbe.filePath property stringList libDirs property bool staticMode: false validate: { if (!executableFilePath) { throw "No pkg-config executable found. " + "Please set modules.pkgconfig.executableFilePath."; } if (!File.exists(executableFilePath)) throw "The pkg-config executable '" + executableFilePath + "' does not exist."; } } qbs-src-3.3.1/share/qbs/modules/flatbuf/0000755000175100017510000000000015232633614017465 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/flatbuf/flatbuffers.js0000644000175100017510000001040115232633614022322 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); function validateCompiler(compilerName, compilerPath) { if (!File.exists(compilerPath)) { throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or " + "make sure the compiler is found in PATH"; } } function getOutputDir(module, input) { var outputDir = module._outputDir; if (!module.keepPrefix) return outputDir; var importPaths = module.importPaths; if (importPaths !== undefined && importPaths.length !== 0) { var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); for (var i = 0; i < importPaths.length; ++i) { var path = File.canonicalFilePath(importPaths[i]); if (canonicalInput.startsWith(path)) { return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); } } } return outputDir; } function artifactC(module, input, tag, suffix) { var outputDir = module._outputDir; return { fileTags: [tag], filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, cpp: { warningLevel: "none"} }; } function doPrepareC(module, input) { var args = []; args.push("-a") // write all args.push("-o", input.flatbuf.c._outputDir) // output dir var importPaths = module.importPaths; importPaths.forEach(function(path) { args.push("-I", path); }); args.push(input.filePath); var cmd = new Command(module.compilerPath, args); cmd.workingDirectory = FileInfo.path(module._outputDir) cmd.highlight = "codegen"; cmd.description = "generating C files for " + input.fileName; return [cmd]; } function artifact(module, input, tag, suffix) { var outputDir = getOutputDir(module, input); return { fileTags: [tag], filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, cpp: { warningLevel: "none" } }; } function doPrepareCpp(module, input, output) { var outputDir = FileInfo.path(output.filePath); var result = []; var args = []; args.push("--cpp") var importPaths = module.importPaths; importPaths.forEach(function(path) { args.push("-I", path); }); args.push("--filename-ext", module.filenameExtension); args.push("--filename-suffix", module.filenameSuffix); if (module.includePrefix) args.push("--include-prefix", module.includePrefix); if (module.keepPrefix) args.push("--keep-prefix"); args.push(input.filePath); var cmd = new Command(input.flatbuf.cpp.compilerPath, args); cmd.workingDirectory = outputDir; cmd.highlight = "codegen"; cmd.description = "generating C++ files for " + input.fileName; result.push(cmd); return result; } qbs-src-3.3.1/share/qbs/modules/flatbuf/c/0000755000175100017510000000000015232633614017707 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs0000644000175100017510000000434315232633614023145 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.FileInfo import "../flatbuffers.js" as Flatbuf import "../flatbuffersbase.qbs" as FlatbufBase FlatbufBase { Depends { name: "cpp" } Depends { name: "flatcc" } compilerName: "flatcc" _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "c") _searchPaths: flatbuffers.hostBinDirs cpp.systemIncludePaths: base.concat([_outputDir]) Rule { inputs: ["flatbuf.input"] outputFileTags: ["hpp"] outputArtifacts: [Flatbuf.artifactC(input.flatbuf.c, input, "hpp", "_generated.h")] prepare: { return Flatbuf.doPrepareC(input.flatbuf.c, input); } } validate: { Flatbuf.validateCompiler(compilerName, compilerPath); } } qbs-src-3.3.1/share/qbs/modules/flatbuf/flatbuffersbase.qbs0000644000175100017510000000411215232633614023330 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.Probes import "flatbuffers.js" as HelperFunctions Module { property string compilerName: "flatc" property string compilerPath: compilerProbe.filePath property pathList importPaths: [] property string _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf") property stringList _searchPaths FileTagger { patterns: ["*.fbs"] fileTags: ["flatbuf.input"]; } Probes.BinaryProbe { id: compilerProbe names: [compilerName] searchPaths: _searchPaths } } qbs-src-3.3.1/share/qbs/modules/flatbuf/cpp/0000755000175100017510000000000015232633614020247 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs0000644000175100017510000000510415232633614024041 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.FileInfo import "../flatbuffers.js" as Flatbuf import "../flatbuffersbase.qbs" as FlatbufBase FlatbufBase { Depends { name: "cpp" } Depends { name: "flatbuffers" } property string filenameExtension: "h" property string filenameSuffix: "_generated" property string includePrefix // TODO: test property bool keepPrefix: false _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "cpp") _searchPaths: flatbuffers.hostBinDirs cpp.cxxLanguageVersion: "c++11" cpp.systemIncludePaths: base.concat([_outputDir]) Rule { inputs: ["flatbuf.input"] outputFileTags: ["hpp"] outputArtifacts: { var module = input.flatbuf.cpp; var fullSuffix = module.filenameSuffix + "." + module.filenameExtension; return [ Flatbuf.artifact(module, input, "hpp", fullSuffix) ]; } prepare: { return Flatbuf.doPrepareCpp(input.flatbuf.cpp, input, output); } } validate: { Flatbuf.validateCompiler(compilerName, compilerPath); } } qbs-src-3.3.1/share/qbs/modules/freedesktop/0000755000175100017510000000000015232633614020355 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/freedesktop/freedesktop.js0000644000175100017510000000731015232633614023227 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Alberto Mardegan ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var TextFile = require("qbs.TextFile"); function parseDesktopFile(filePath) { var file = new TextFile(filePath); var fileValues = {}; var currentSection = {}; var sectionRex = /^\[(.+)\]$/g; while (!file.atEof()) { var line = file.readLine().trim(); if (line.length == 0) continue; if (line[0] == '#') continue; var match = sectionRex.exec(line); if (match) { var currentSectionName = match[1]; fileValues[currentSectionName] = {}; currentSection = fileValues[currentSectionName]; continue; } var parts = line.split('=', 2); currentSection[parts[0]] = parts[1] } file.close(); return fileValues } function dumpDesktopFile(filePath, keys) { var file = new TextFile(filePath, TextFile.WriteOnly); for (var sectionName in keys) { file.writeLine('[' + sectionName + ']'); var section = keys[sectionName]; for (var key in section) { var line = key + '=' + section[key]; file.writeLine(line); } // Write an empty line between sections (and before EOF) file.writeLine(''); } file.close(); } function generateDesktopFileCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName + " from " + input.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var aggregateDesktopKeys = parseDesktopFile(input.filePath); var desktopKeys = ModUtils.moduleProperty(product, "desktopKeys") || {} var mainSection = aggregateDesktopKeys['Desktop Entry']; for (key in desktopKeys) { if (desktopKeys.hasOwnProperty(key)) { mainSection[key] = desktopKeys[key]; } } var defaultValues = product.freedesktop.defaultDesktopKeys for (key in defaultValues) { if (!(key in mainSection)) { mainSection[key] = defaultValues[key]; } } dumpDesktopFile(output.filePath, aggregateDesktopKeys); } return [cmd]; } qbs-src-3.3.1/share/qbs/modules/freedesktop/FreeDesktop.qbs0000644000175100017510000000647415232633614023312 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Alberto Mardegan ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.ModUtils import qbs.TextFile import "freedesktop.js" as Fdo Module { property string name: product.name property string appName: name property string hicolorRoot: undefined property var desktopKeys readonly property var defaultDesktopKeys: { return { 'Type': 'Application', 'Name': product.freedesktop.appName, 'Exec': product.targetName, 'Terminal': 'false', 'Version': '1.1', } } property bool _fdoSupported: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") additionalProductTypes: "freedesktop.desktopfile" FileTagger { patterns: [ "*.desktop" ] fileTags: [ "freedesktop.desktopfile_source" ] } Group { condition: _fdoSupported qbs.install: true Group { fileTagsFilter: [ "freedesktop.desktopfile" ] qbs.installDir: "share/applications" } Group { condition: product.freedesktop.hicolorRoot !== undefined fileTagsFilter: [ "freedesktop.appIcon" ] qbs.installDir: "share/icons/hicolor" qbs.installSourceBase: product.freedesktop.hicolorRoot } Group { fileTagsFilter: [ "freedesktop.appstream" ] qbs.installDir: "share/metainfo" } Rule { inputs: [ "freedesktop.desktopfile_source" ] outputFileTags: [ "freedesktop.desktopfile" ] Artifact { fileTags: [ "freedesktop.desktopfile" ] filePath: input.fileName } prepare: Fdo.generateDesktopFileCommands.apply(Fdo, arguments) } } FileTagger { patterns: [ "*.metainfo.xml", "*.appdata.xml" ] fileTags: [ "freedesktop.appstream" ] } } qbs-src-3.3.1/share/qbs/modules/ib/0000755000175100017510000000000015232633614016434 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/ib/IBModule.qbs0000644000175100017510000001526315232633614020612 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.BundleTools import qbs.DarwinTools import qbs.File import "IBModuleBase.qbs" as IBModuleBase import qbs.Host import qbs.FileInfo import qbs.ModUtils import qbs.Process import 'ib.js' as Ib IBModuleBase { Depends { name: "xcode"; required: false } Probe { id: ibProbe property string toolPath: ibtoolPath // input property string toolVersion // output configure: { toolVersion = Ib.ibtoolVersion(toolPath); found = true; } } priority: 0 condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin") warnings: true errors: true notices: true flags: [] // tiffutil specific tiffutilName: "tiffutil" tiffutilPath: FileInfo.joinPaths("/usr/bin", tiffutilName) combineHidpiImages: true // iconutil specific iconutilName: "iconutil" iconutilPath: FileInfo.joinPaths("/usr/bin", iconutilName) // XIB/NIB specific ibtoolName: "ibtool" ibtoolPath: FileInfo.joinPaths(xcode.developerPath, "/usr/bin", ibtoolName) flatten: true module: "" autoActivateCustomFonts: true // Asset catalog specific actoolName: xcode.present ? "actool" : "ictool" actoolPath: FileInfo.joinPaths(xcode.developerPath, "/usr/bin", actoolName) appIconName: "" launchImageName: "" compressPngs: true // private properties outputFormat: "human-readable-text" tiffSuffix: ".tiff" appleIconSuffix: ".icns" compiledAssetCatalogSuffix: ".car" compiledNibSuffix: ".nib" compiledStoryboardSuffix: ".storyboardc" version: ibtoolVersion ibtoolVersion: ibProbe.toolVersion ibtoolVersionParts: ibtoolVersion ? ibtoolVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] ibtoolVersionMajor: ibtoolVersionParts[0] ibtoolVersionMinor: ibtoolVersionParts[1] ibtoolVersionPatch: ibtoolVersionParts[2] targetDevices: xcode.present ? xcode.targetDevices : DarwinTools.targetDevices(qbs.targetOS) validate: { var validator = new ModUtils.PropertyValidator("ib"); validator.setRequiredProperty("ibtoolVersion", ibtoolVersion); validator.setRequiredProperty("ibtoolVersionMajor", ibtoolVersionMajor); validator.setRequiredProperty("ibtoolVersionMinor", ibtoolVersionMinor); validator.addVersionValidator("ibtoolVersion", ibtoolVersion, 2, 3); validator.addRangeValidator("ibtoolVersionMajor", ibtoolVersionMajor, 1); validator.addRangeValidator("ibtoolVersionMinor", ibtoolVersionMinor, 0); if (ibtoolVersionPatch !== undefined) validator.addRangeValidator("ibtoolVersionPatch", ibtoolVersionPatch, 0); validator.validate(); } FileTagger { patterns: ["*.png"] fileTags: ["png"] } FileTagger { patterns: ["*.iconset"] // bundle fileTags: ["iconset"] } FileTagger { patterns: ["*.nib", "*.xib"] fileTags: ["nib"] } FileTagger { patterns: ["*.storyboard"] fileTags: ["storyboard"] } FileTagger { patterns: ["*.xcassets"] // bundle fileTags: ["assetcatalog"] } FileTagger { patterns: ["*.icon"] // bundle fileTags: ["iconcomposer"] } Rule { multiplex: true inputs: ["png"] outputFileTags: ["tiff"] outputArtifacts: Ib.tiffutilArtifacts(product, inputs) prepare: Ib.prepareTiffutil.apply(Ib, arguments) } Rule { inputs: ["iconset"] outputFileTags: ["icns", "bundle.input"] outputArtifacts: ([{ filePath: FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + ModUtils.moduleProperty(product, "appleIconSuffix")), fileTags: ["icns", "bundle.input"], bundle: { _bundleFilePath: FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), input.completeBaseName + ModUtils.moduleProperty(product, "appleIconSuffix")) } }]) prepare: { var args = ["--convert", "icns", "--output", output.filePath, input.filePath]; var cmd = new Command(ModUtils.moduleProperty(product, "iconutilPath"), args); cmd.description = "compiling " + input.fileName; return cmd; } } Rule { inputs: ["nib", "storyboard"] outputFileTags: { var tags = ["partial_infoplist"]; for (var i = 0; i < inputs.length; ++i) tags = tags.uniqueConcat(ModUtils.allFileTags(Ib.ibtoolFileTaggers(inputs[i]))); return tags; } outputArtifacts: Ib.ibtoolOutputArtifacts(product, inputs, input) prepare: Ib.ibtoolCommands.apply(Ib, arguments) } Rule { inputs: ["assetcatalog", "iconcomposer"] multiplex: true outputArtifacts: Ib.actoolOutputArtifacts(product, inputs) outputFileTags: ["bundle.input", "compiled_assetcatalog", "partial_infoplist"] prepare: Ib.compileAssetCatalogCommands.apply(Ib, arguments) } } qbs-src-3.3.1/share/qbs/modules/ib/ib.js0000644000175100017510000004103315232633614017365 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var BundleTools = require("qbs.BundleTools"); var DarwinTools = require("qbs.DarwinTools"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var PropertyList = require("qbs.PropertyList"); function artifactsFromInputs(inputs) { var artifacts = []; for (var tag in inputs) { artifacts = artifacts.concat(inputs[tag]); } return artifacts; } function tiffutilScalesMap(inputs) { return artifactsFromInputs(inputs).map(function (a) { var m = a.filePath.match(/^(.+?)(@(\d+)x)?(\..+?)$/); var basePath = m[1]; var scale = m[2] || ""; var nscale = m[3]; var extension = m[4]; if (scale && scale < 1) throw new Error("Invalid scale '" + nscale + "' for image '" + a.filePath + "'"); return { basePath: basePath, extension: extension, scale: scale }; }).reduce(function (previous, current) { previous[current["basePath"]] = (previous[current["basePath"]] || []).concat([{ extension: current["extension"], scale: current["scale"] }]); return previous; }, {}); } function tiffutilOutputFilePath(product, basePath) { return FileInfo.joinPaths(product.destinationDirectory, "hidpi-images", FileInfo.relativePath(product.sourceDirectory, basePath) + product.ib.tiffSuffix); } function tiffutilArtifacts(product, inputs) { var artifacts = []; var map = tiffutilScalesMap(inputs); for (var key in map) { artifacts.push({ filePath: tiffutilOutputFilePath(product, key), fileTags: ["tiff"] }); } return artifacts; } function prepareTiffutil(project, product, inputs, outputs, input, output) { var cmds = []; var map = tiffutilScalesMap(inputs); for (var key in map) { var args = ["-cat" + (product.ib.combineHidpiImages ? "hidpicheck" : "")]; var count = 0; map[key].forEach(function (obj) { args.push(key + obj["scale"] + obj["extension"]); ++count; }); args.push("-out", tiffutilOutputFilePath(product, key)); var cmd = new Command(product.ib.tiffutilPath, args); cmd.description = "creating " + output.fileName; cmd.count = count; cmd.outputFilePath = output.filePath; cmd.stderrFilterFunction = function (output) { return output.replace(count + " images written to " + outputFilePath + ".", ""); }; cmds.push(cmd); } return cmds; } function ibtooldArguments(product, inputs, input, outputs, overrideOutput) { var i; var args = []; var allInputs = artifactsFromInputs(inputs); var outputFormat = ModUtils.moduleProperty(product, "outputFormat"); if (outputFormat) { if (!["binary1", "xml1", "human-readable-text"].includes(outputFormat)) throw("Invalid ibtoold output format: " + outputFormat + ". " + "Must be in [binary1, xml1, human-readable-text]."); args.push("--output-format", outputFormat); } var debugFlags = ["warnings", "errors", "notices"]; for (var j in debugFlags) { var flag = debugFlags[j]; if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, flag)) { args.push("--" + flag); } } if (inputs.assetcatalog || inputs.iconcomposer) { args.push("--platform", DarwinTools.applePlatformName( product.moduleProperty("qbs", "targetOS"), product.moduleProperty("xcode", "platformType"))); var appIconName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "appIconName"); if (appIconName) args.push("--app-icon", appIconName); var launchImageName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "launchImageName"); if (launchImageName) args.push("--launch-image", launchImageName); // Undocumented but used by Xcode (only for iOS?), probably runs pngcrush or equivalent if (ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "compressPngs")) args.push("--compress-pngs"); } else { var sysroot = product.moduleProperty("qbs", "sysroot"); if (sysroot) args.push("--sdk", sysroot); args.push("--flatten", ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "flatten") ? 'YES' : 'NO'); // --module and --auto-activate-custom-fonts were introduced in Xcode 6.0 if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6) { var module = ModUtils.moduleProperty(product, "module"); if (module) args.push("--module", module); if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "autoActivateCustomFonts")) args.push("--auto-activate-custom-fonts"); } } // --minimum-deployment-target was introduced in Xcode 5.0 var minimumDarwinVersion = product.moduleProperty("cpp", "minimumDarwinVersion"); if (minimumDarwinVersion && ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 5) args.push("--minimum-deployment-target", minimumDarwinVersion); // --target-device and -output-partial-info-plist were introduced in Xcode 6.0 for ibtool if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6 || inputs.assetcatalog || inputs.iconcomposer) { args.push("--output-partial-info-plist", (outputs && outputs.partial_infoplist) ? outputs.partial_infoplist[outputs.partial_infoplist.length - 1].filePath : "/dev/null"); // For iOS, we'd normally only output the devices specified in TARGETED_DEVICE_FAMILY // We can't get this info from Info.plist keys due to dependency order, so use the qbs prop var targetDevices = ModUtils.moduleProperty(product, "targetDevices"); for (i in targetDevices) { args.push("--target-device", targetDevices[i]); } } args = args.concat(ModUtils.modulePropertiesFromArtifacts(product, allInputs, product.moduleName, "flags")); if (overrideOutput) { args.push("--compile", overrideOutput); } else { if (outputs.compiled_assetcatalog) args.push("--compile", product.buildDirectory + "/actool.dir"); else // compiled_ibdoc args.push("--compile", product.buildDirectory + "/ibtool.dir/" + ibtoolCompiledDirSuffix(product, input)); } for (i in allInputs) args.push(allInputs[i].filePath); return args; } function ibtoolFileTaggers(fileTags) { var ext; if (fileTags.includes("nib") && !fileTags.includes("storyboard")) ext = "nib"; if (fileTags.includes("storyboard") && !fileTags.includes("nib")) ext = "storyboard"; if (!ext) throw "unknown ibtool input file tags: " + fileTags; var t = ["bundle.input", "compiled_ibdoc"]; return { ".nib": t.concat(["compiled_" + ext + (ext !== "nib" ? "_nib" : "")]), ".plist": t.concat(["compiled_" + ext + "_infoplist"]), ".storyboard": t.concat(["compiled_" + ext]) }; } function ibtoolCompiledDirSuffix(product, input) { var suffix = input.completeBaseName; if (input.fileTags.includes("nib")) suffix += ModUtils.moduleProperty(product, "compiledNibSuffix"); else if (input.fileTags.includes("storyboard")) suffix += ModUtils.moduleProperty(product, "compiledStoryboardSuffix"); return suffix; } function ibtoolOutputArtifacts(product, inputs, input) { var suffix = ibtoolCompiledDirSuffix(product, input); var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.fileTaggers = ibtoolFileTaggers(input.fileTags); tracker.command = ModUtils.moduleProperty(product, "ibtoolPath"); tracker.commandArgsFunction = function (outputDirectory) { // Last --output-format argument overrides any previous ones // Append the name of the base output since it can be either a file or a directory // in the case of XIB compilations return ibtooldArguments(product, inputs, input, undefined, FileInfo.joinPaths(outputDirectory, suffix)) .concat(["--output-format", "xml1"]); }; var ibtoolBuildDirectory = product.buildDirectory + "/ibtool.dir"; var main = BundleTools.destinationDirectoryForResource(product, input); var artifacts = tracker.artifacts(ibtoolBuildDirectory); if (product.moduleProperty("ib", "ibtoolVersionMajor") >= 6) { var prefix = input.fileTags.includes("storyboard") ? "SB" : ""; var path = FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + "-" + prefix + "PartialInfo.plist"); artifacts.push({ filePath: path, fileTags: ["partial_infoplist"] }); } // Let the output artifacts known the "main" output // This can be either a file or directory so the artifact might already exist in the output list for (var i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.includes("compiled_ibdoc")) artifacts[i].bundle = { _bundleFilePath: artifacts[i].filePath.replace(ibtoolBuildDirectory, main) }; } return artifacts; } function ibtoolCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new Command(ModUtils.moduleProperty(product, "ibtoolPath"), ibtooldArguments(product, inputs, input, outputs)); cmd.description = "compiling " + input.fileName; // Also display the language name of the nib/storyboard being compiled if it has one var localizationKey = DarwinTools.localizationKey(input.filePath); if (localizationKey) cmd.description += ' (' + localizationKey + ')'; cmd.highlight = 'compiler'; // May not be strictly needed, but is set by some versions of Xcode if (input.fileTags.includes("storyboard")) cmd.environment.push("IBSC_MINIMUM_COMPATIBILITY_VERSION=" + (product.moduleProperty("cpp", "minimumDarwinVersion") || "")); cmd.stdoutFilterFunction = function(output) { return ""; }; return cmd; } function actoolOutputArtifacts(product, inputs) { // actool has no --dry-run option (rdar://21786925), // so compile to a fake temporary directory in order to extract the list of output files var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.command = ModUtils.moduleProperty(product, "actoolPath"); tracker.commandArgsFunction = function (outputDirectory) { // Last --output-format argument overrides any previous ones return ibtooldArguments(product, inputs, undefined, undefined, outputDirectory).concat(["--output-format", "xml1"]); }; tracker.processStdOutFunction = parseActoolOutput; var artifacts = tracker.artifacts(product.buildDirectory + "/actool.dir"); // Newer versions of actool don't generate *anything* if there's no input; // in that case a partial Info.plist would not have been generated either if (artifacts && artifacts.length > 0) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, "assetcatalog_generated_info.plist"), fileTags: ["partial_infoplist"] }); } for (var i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.includes("compiled_assetcatalog")) { var referenceInput = inputs.assetcatalog ? inputs.assetcatalog[0] : inputs.iconcomposer[0]; artifacts[i].bundle = { _bundleFilePath: artifacts[i].filePath.replace( product.buildDirectory + "/actool.dir", BundleTools.destinationDirectoryForResource(product, referenceInput)) }; } } return artifacts; } function parseActoolOutput(output) { var propertyList = new PropertyList(); try { propertyList.readFromString(output); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.actool.compilation-results"]; if (plist) { var artifacts = []; files = plist["output-files"]; for (var i in files) { if (files[i] === "/dev/null") continue; var tags = files[i].endsWith(".plist") ? ["partial_infoplist"] : ["bundle.input", "compiled_assetcatalog"]; artifacts.push({ // Even though we pass in a canonical base dir, the paths in the XML File // are non-canonical. See QBS-1417. filePath: FileInfo.canonicalPath(files[i]), fileTags: tags }); } return artifacts; } } finally { propertyList.clear(); } } function ibtoolVersion(ibtool) { var process; var version; try { process = new Process(); if (process.exec(ibtool, ["--version", "--output-format", "xml1"], true) !== 0) console.error(process.readStdErr()); var propertyList = new PropertyList(); try { propertyList.readFromString(process.readStdOut()); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.ibtool.version"]; if (plist) version = plist["short-bundle-version"]; } finally { propertyList.clear(); } } finally { process.close(); } return version; } function compileAssetCatalogCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var mkdir = new JavaScriptCommand(); mkdir.silent = true; mkdir.sourceCode = function () { File.makePath(FileInfo.joinPaths(product.buildDirectory, "actool.dir")); }; var cmd = new Command(ModUtils.moduleProperty(product, "actoolPath"), ibtooldArguments(product, inputs, input, outputs)); const inputFiles = [].concat(inputs["assetcatalog"] || [], inputs["iconcomposer"] || []); cmd.description = inputFiles.map(function (input) { return "compiling " + input.fileName; }).join('\n'); cmd.highlight = "compiler"; cmd.stdoutFilterFunction = function(output) { return ""; }; return [mkdir, cmd]; } qbs-src-3.3.1/share/qbs/modules/ib/IBModuleBase.qbs0000644000175100017510000000533315232633614021402 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2026 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Module { priority: -100 property bool warnings property bool errors property bool notices property stringList flags // tiffutil specific property string tiffutilName property string tiffutilPath property bool combineHidpiImages // iconutil specific property string iconutilName property string iconutilPath // XIB/NIB specific property string ibtoolName property string ibtoolPath property bool flatten property string module property bool autoActivateCustomFonts // Asset catalog specific property string actoolName property string actoolPath property string appIconName property string launchImageName property bool compressPngs // private properties property string outputFormat property string tiffSuffix property string appleIconSuffix property string compiledAssetCatalogSuffix property string compiledNibSuffix property string compiledStoryboardSuffix property string ibtoolVersion property var ibtoolVersionParts property int ibtoolVersionMajor property int ibtoolVersionMinor property int ibtoolVersionPatch property stringList targetDevices } qbs-src-3.3.1/share/qbs/modules/nodejs/0000755000175100017510000000000015232633614017324 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/nodejs/nodejs.js0000644000175100017510000000360215232633614021145 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Process = require("qbs.Process"); function findLocation(packageManagerFilePath, location, nodejsPath) { var p = new Process(); try { if (nodejsPath) p.setEnv("PATH", nodejsPath); if (p.exec(packageManagerFilePath, [location, "-g"]) !== 0) console.error(p.readStdErr().trim()); return p.readStdOut().trim(); } finally { p.close(); } } qbs-src-3.3.1/share/qbs/modules/nodejs/NodeJS.qbs0000644000175100017510000001416415232633614021163 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Probes Module { // JavaScript files which have been "processed" - currently this simply means "copied to output // directory" but might later include minification and obfuscation processing additionalProductTypes: ["nodejs_processed_js"].concat(applicationFile ? ["application"] : []) Probes.NodeJsProbe { id: nodejs searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] } Probes.NpmProbe { id: npm searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] interpreterPath: FileInfo.path(nodejs.filePath) } property path applicationFile PropertyOptions { name: "applicationFile" description: "file whose corresponding output will be executed when running the Node.js app" } Group { name: "Application file"; files: nodejs.applicationFile ? [nodejs.applicationFile] : [] } property path toolchainInstallPath: { if (nodejs.path && npm.path && nodejs.path !== npm.path) throw("node and npm binaries do not belong to the same installation (" + nodejs.path + " vs " + npm.path + ")"); return nodejs.path || npm.path; } property path interpreterFileName: nodejs.fileName property path interpreterFilePath: nodejs.filePath property path packageManagerFileName: npm.fileName property path packageManagerFilePath: npm.filePath property path packageManagerBinPath: npm.npmBin property path packageManagerRootPath: npm.npmRoot property path packageManagerPrefixPath: npm.npmPrefix // private properties readonly property path compiledIntermediateDir: FileInfo.joinPaths(product.buildDirectory, "tmp", "nodejs.intermediate") setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().includes("windows")); v.prepend(product.nodejs.toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("NODE_PATH", FileInfo.pathListSeparator(), Host.os().includes("windows")); v.prepend(FileInfo.path(Environment.getEnv("QBS_RUN_FILE_PATH"))); v.set(); } FileTagger { patterns: ["*.js"] fileTags: ["js"] } validate: { var validator = new ModUtils.PropertyValidator("nodejs"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("interpreterFileName", interpreterFileName); validator.setRequiredProperty("interpreterFilePath", interpreterFilePath); validator.setRequiredProperty("packageManagerFileName", packageManagerFileName); validator.setRequiredProperty("packageManagerFilePath", packageManagerFilePath); validator.setRequiredProperty("packageManagerBinPath", packageManagerBinPath); validator.setRequiredProperty("packageManagerRootPath", packageManagerRootPath); validator.setRequiredProperty("packageManagerPrefixPath", packageManagerPrefixPath); validator.validate(); } Rule { inputs: ["js"] outputArtifacts: { var tags = ["nodejs_processed_js"]; if (input.fileTags.includes("application_js") || product.moduleProperty("nodejs", "applicationFile") === input.filePath) tags.push("application"); // Preserve directory structure of input files var intermediatePath = product.sourceDirectory; // Handle nodejs.compiledIntermediateDir (QBS-5 workaround) var compiled = product.moduleProperty("nodejs", "compiledIntermediateDir"); if (input.filePath.startsWith(compiled)) { intermediatePath = compiled; } intermediatePath = FileInfo.path(FileInfo.relativePath(intermediatePath, input.filePath)); return [{ filePath: FileInfo.joinPaths(product.destinationDirectory, intermediatePath, input.fileName), fileTags: tags }]; } outputFileTags: ["nodejs_processed_js", "application"] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-3.3.1/share/qbs/modules/bundle/0000755000175100017510000000000015232633614017313 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/bundle/BundleModule.qbs0000644000175100017510000004234015232633614022404 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.BundleTools import qbs.DarwinTools import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.PropertyList import qbs.TextFile import qbs.Utilities import "bundle.js" as Bundle import "../codesign/codesign.js" as Codesign Module { Depends { name: "xcode"; required: false; } Depends { name: "codesign"; required: false; } Depends { name: "installpaths" } Probe { id: bundleSettingsProbe condition: qbs.targetOS.includes("darwin") property string xcodeDeveloperPath: xcode.developerPath property var xcodeArchSettings: xcode._architectureSettings property string productTypeIdentifier: _productTypeIdentifier property bool useXcodeBuildSpecs: !useBuiltinXcodeBuildSpecs property bool isMacOs: qbs.targetOS.includes("macos") property bool xcodePresent: xcode.present property string xcodeVersion: xcode.version // Note that we include several settings pointing to properties which reference the output // of this probe (WRAPPER_NAME, WRAPPER_EXTENSION, etc.). This is to ensure that derived // properties take into account the value of these settings if the user customized them. property var additionalSettings: ({ "DEVELOPMENT_LANGUAGE": "English", "EXECUTABLE_VARIANT_SUFFIX": "", // e.g. _debug, _profile "FRAMEWORK_VERSION": frameworkVersion, "GENERATE_PKGINFO_FILE": generatePackageInfo !== undefined ? (generatePackageInfo ? "YES" : "NO") : undefined, "IS_MACCATALYST": "NO", "LD_RUNPATH_SEARCH_PATHS_NO": [], "PRODUCT_NAME": product.targetName, "LOCAL_APPS_DIR": FileInfo.joinPaths("/", installpaths.applications), "LOCAL_LIBRARY_DIR": FileInfo.joinPaths("/", installpaths.library), // actually, this is cpp.targetAbi, but XCode does not set it for non-simulator builds // while Qbs set it to "macho". "LLVM_TARGET_TRIPLE_SUFFIX": qbs.targetOS.includes("simulator") ? "-simulator" : "", "SWIFT_PLATFORM_TARGET_PREFIX": isMacOs ? "macos" : qbs.targetOS.includes("ios") ? "ios" : "", "TARGET_BUILD_DIR": product.buildDirectory, "WRAPPER_NAME": bundleName, "WRAPPER_EXTENSION": extension }) // Outputs property var xcodeSettings: ({}) property var productTypeIdentifierChain: [] configure: { var specsPaths = [path]; var specsSeparator = "-"; if (xcodeDeveloperPath && useXcodeBuildSpecs) { specsPaths = Bundle.macOSSpecsPaths(xcodeVersion, xcodeDeveloperPath); specsSeparator = " "; if (Utilities.versionCompare(xcodeVersion, "26.0") >= 0) specsSeparator = ""; } var reader = new Bundle.XcodeBuildSpecsReader(specsPaths, specsSeparator, additionalSettings, !isMacOs); var settings = reader.expandedSettings(productTypeIdentifier, xcodePresent ? xcodeArchSettings : {}); var chain = reader.productTypeIdentifierChain(productTypeIdentifier); if (settings && chain) { xcodeSettings = settings; productTypeIdentifierChain = chain; found = true; } else { xcodeSettings = {}; productTypeIdentifierChain = []; found = false; } } } additionalProductTypes: !(product.multiplexed || product.aggregate) || !product.multiplexConfigurationId ? ["bundle.content"] : [] property bool isBundle: !product.consoleApplication && qbs.targetOS.includes("darwin") property bool isMainBundle: false property bool isForMainBundle: true readonly property bool isShallow: bundleSettingsProbe.xcodeSettings["SHALLOW_BUNDLE"] === "YES" property string identifierPrefix: "org.example" property string identifier: [identifierPrefix, Utilities.rfc1034Identifier(product.targetName)].join(".") property string extension: bundleSettingsProbe.xcodeSettings["WRAPPER_EXTENSION"] property string packageType: Bundle.packageType(_productTypeIdentifier) property string signature: "????" // legacy creator code in Mac OS Classic (CFBundleSignature), can be ignored property string bundleName: bundleSettingsProbe.xcodeSettings["WRAPPER_NAME"] property string frameworkVersion: { var n = parseInt(product.version, 10); return isNaN(n) ? bundleSettingsProbe.xcodeSettings["FRAMEWORK_VERSION"] : String(n); } property bool generatePackageInfo: { // Make sure to return undefined as default to indicate "not set" var genPkgInfo = bundleSettingsProbe.xcodeSettings["GENERATE_PKGINFO_FILE"]; if (genPkgInfo) return genPkgInfo === "YES"; } property pathList publicHeaders property pathList privateHeaders property pathList resources property var infoPlist property bool processInfoPlist: true property bool embedInfoPlist: product.consoleApplication && !isBundle property string infoPlistFormat: qbs.targetOS.includes("macos") ? "same-as-input" : "binary1" property string localizedResourcesFolderSuffix: ".lproj" property string lsregisterName: "lsregister" property string lsregisterPath: FileInfo.joinPaths( "/System/Library/Frameworks/CoreServices.framework" + "/Versions/A/Frameworks/LaunchServices.framework" + "/Versions/A/Support", lsregisterName); // all paths are relative to the directory containing the bundle readonly property string infoPlistPath: bundleSettingsProbe.xcodeSettings["INFOPLIST_PATH"] readonly property string infoStringsPath: bundleSettingsProbe.xcodeSettings["INFOSTRINGS_PATH"] readonly property string pbdevelopmentPlistPath: bundleSettingsProbe.xcodeSettings["PBDEVELOPMENTPLIST_PATH"] readonly property string pkgInfoPath: bundleSettingsProbe.xcodeSettings["PKGINFO_PATH"] readonly property string versionPlistPath: bundleSettingsProbe.xcodeSettings["VERSIONPLIST_PATH"] readonly property string executablePath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_PATH"] readonly property string contentsFolderPath: bundleSettingsProbe.xcodeSettings["CONTENTS_FOLDER_PATH"] readonly property string applicationsFolderPath: FileInfo.joinPaths(contentsFolderPath, "Applications") readonly property string documentationFolderPath: bundleSettingsProbe.xcodeSettings["DOCUMENTATION_FOLDER_PATH"] readonly property string executableFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_FOLDER_PATH"] readonly property string executablesFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLES_FOLDER_PATH"] readonly property string frameworksFolderPath: bundleSettingsProbe.xcodeSettings["FRAMEWORKS_FOLDER_PATH"] readonly property string javaFolderPath: bundleSettingsProbe.xcodeSettings["JAVA_FOLDER_PATH"] readonly property string localizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["LOCALIZED_RESOURCES_FOLDER_PATH"] readonly property string pluginsFolderPath: bundleSettingsProbe.xcodeSettings["PLUGINS_FOLDER_PATH"] readonly property string privateHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PRIVATE_HEADERS_FOLDER_PATH"] readonly property string publicHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PUBLIC_HEADERS_FOLDER_PATH"] readonly property string scriptsFolderPath: bundleSettingsProbe.xcodeSettings["SCRIPTS_FOLDER_PATH"] readonly property string sharedFrameworksFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_FRAMEWORKS_FOLDER_PATH"] readonly property string sharedSupportFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_SUPPORT_FOLDER_PATH"] readonly property string unlocalizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["UNLOCALIZED_RESOURCES_FOLDER_PATH"] readonly property string versionsFolderPath: bundleSettingsProbe.xcodeSettings["VERSIONS_FOLDER_PATH"] property bool useBuiltinXcodeBuildSpecs: !_useXcodeBuildSpecs // true to use ONLY the qbs build specs // private properties property string _productTypeIdentifier: Bundle.productTypeIdentifier(product.type) property stringList _productTypeIdentifierChain: bundleSettingsProbe.productTypeIdentifierChain readonly property path _developerPath: xcode.developerPath readonly property path _platformInfoPlist: xcode.platformInfoPlist readonly property path _sdkSettingsPlist: xcode.sdkSettingsPlist readonly property path _toolchainInfoPlist: xcode.toolchainInfoPlist property bool _useXcodeBuildSpecs: true // TODO: remove in 1.25 property var extraEnv: ({ "PRODUCT_BUNDLE_IDENTIFIER": identifier }) readonly property var qmakeEnv: { return { "BUNDLEIDENTIFIER": identifier, "EXECUTABLE": product.targetName, "FULL_VERSION": product.version || "1.0", // CFBundleVersion "ICON": product.targetName, // ### QBS-73 "LIBRARY": product.targetName, "SHORT_VERSION": product.version || "1.0", // CFBundleShortVersionString "TYPEINFO": signature // CFBundleSignature }; } readonly property var defaultInfoPlist: { return { CFBundleDevelopmentRegion: "en", // default localization CFBundleDisplayName: product.targetName, // localizable CFBundleExecutable: product.targetName, CFBundleIdentifier: identifier, CFBundleInfoDictionaryVersion: "6.0", CFBundleName: product.targetName, // short display name of the bundle, localizable CFBundlePackageType: packageType, CFBundleShortVersionString: product.version || "1.0", // "release" version number, localizable CFBundleSignature: signature, // legacy creator code in Mac OS Classic, can be ignored CFBundleVersion: product.version || "1.0.0" // build version number, must be 3 octets }; } validate: { if (!qbs.targetOS.includes("darwin")) return; if (!bundleSettingsProbe.found) { var error = "Bundle product type " + _productTypeIdentifier + " is not supported."; if ((_productTypeIdentifier || "").startsWith("com.apple.product-type.")) error += " You may need to upgrade Xcode."; throw error; } var validator = new ModUtils.PropertyValidator("bundle"); validator.setRequiredProperty("bundleName", bundleName); validator.setRequiredProperty("infoPlistPath", infoPlistPath); validator.setRequiredProperty("pbdevelopmentPlistPath", pbdevelopmentPlistPath); validator.setRequiredProperty("pkgInfoPath", pkgInfoPath); validator.setRequiredProperty("versionPlistPath", versionPlistPath); validator.setRequiredProperty("executablePath", executablePath); validator.setRequiredProperty("contentsFolderPath", contentsFolderPath); validator.setRequiredProperty("documentationFolderPath", documentationFolderPath); validator.setRequiredProperty("executableFolderPath", executableFolderPath); validator.setRequiredProperty("executablesFolderPath", executablesFolderPath); validator.setRequiredProperty("frameworksFolderPath", frameworksFolderPath); validator.setRequiredProperty("javaFolderPath", javaFolderPath); validator.setRequiredProperty("localizedResourcesFolderPath", localizedResourcesFolderPath); validator.setRequiredProperty("pluginsFolderPath", pluginsFolderPath); validator.setRequiredProperty("privateHeadersFolderPath", privateHeadersFolderPath); validator.setRequiredProperty("publicHeadersFolderPath", publicHeadersFolderPath); validator.setRequiredProperty("scriptsFolderPath", scriptsFolderPath); validator.setRequiredProperty("sharedFrameworksFolderPath", sharedFrameworksFolderPath); validator.setRequiredProperty("sharedSupportFolderPath", sharedSupportFolderPath); validator.setRequiredProperty("unlocalizedResourcesFolderPath", unlocalizedResourcesFolderPath); if (packageType === "FMWK") { validator.setRequiredProperty("frameworkVersion", frameworkVersion); validator.setRequiredProperty("versionsFolderPath", versionsFolderPath); } // extension and infoStringsPath might not be set return validator.validate(); } FileTagger { fileTags: ["infoplist"] patterns: ["Info.plist", "*-Info.plist"] } Rule { condition: qbs.targetOS.includes("darwin") multiplex: true requiresInputs: false // TODO: The resources property should probably be a tag instead. inputs: ["infoplist", "partial_infoplist"] outputFileTags: ["bundle.input", "aggregate_infoplist"] outputArtifacts: Bundle.aggregateInfoPlistOutputs(product) prepare: Bundle.aggregateInfoPlistCommands.apply(Bundle, arguments) } Rule { condition: qbs.targetOS.includes("darwin") multiplex: true inputs: ["aggregate_infoplist"] outputFileTags: ["bundle.input", "pkginfo"] outputArtifacts: Bundle.generatePkgInfoOutputs(product) prepare: Bundle.generatePkgInfoCommands.apply(Bundle, arguments) } Rule { condition: qbs.targetOS.includes("darwin") multiplex: true inputs: ["bundle.input", "aggregate_infoplist", "pkginfo", "hpp", "icns", "codesign.xcent", "compiled_ibdoc", "compiled_assetcatalog", "codesign.embedded_provisioningprofile", "bundle.input.privacymanifest", "bundle.input.public_hpp", "bundle.input.private_hpp", "bundle.input.resources"] // Make sure the inputs of this rule are only those rules which produce outputs compatible // with the type of the bundle being produced. excludedInputs: Bundle.excludedAuxiliaryInputs(project, product) // We need to wait for the main bundle inputs to be copied before signing explicitlyDependsOn: ["bundle.content.copied.from.dependencies"] outputFileTags: [ "bundle.content", "bundle.main.input", "bundle.main.application", "bundle.main.framework", "bundle.main.plugin", "bundle.symlink.headers", "bundle.symlink.private-headers", "bundle.symlink.resources", "bundle.symlink.executable", "bundle.symlink.version", "bundle.hpp", "bundle.resource", "bundle.provisioningprofile", "bundle.content.copied", "bundle.application-executable", "bundle.code-signature", "bundle.privacymanifest"] outputArtifacts: Bundle.generateBundleOutputs(product, inputs) prepare: Bundle.generateBundleCommands.apply(Bundle, arguments) } Rule { condition: qbs.targetOS.includes("darwin") multiplex: true requiresInputs: false inputsFromDependencies: ["bundle.main.input"] outputFileTags: ["bundle.content", "bundle.content.copied.from.dependencies"] outputArtifacts: Bundle.generateMainBundleOutputs(product, inputs) prepare: Bundle.generateMainBundleCommands.apply(Bundle, arguments) } Parameter { property bool isForMainBundle: true } } qbs-src-3.3.1/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec0000644000175100017510000007550015232633614024343 0ustar runnerrunner// // MacOSX Product Types.xcspec // // Copyright © 1999-2020 Apple Inc. All rights reserved. // // Product type specifications in the macOS platform. // ( // // Single-file product types // // Tool (normal Unix command-line executable) { Type = ProductType; Identifier = com.apple.product-type.tool; Class = PBXToolProductType; Name = "Command-line Tool"; Description = "Standalone command-line tool"; IconNamePrefix = "TargetExecutable"; DefaultTargetName = "Command-line Tool"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)"; MACH_O_TYPE = "mh_execute"; EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; REZ_EXECUTABLE = YES; INSTALL_PATH = "/usr/local/bin"; FRAMEWORK_FLAG_PREFIX = "-framework"; LIBRARY_FLAG_PREFIX = "-l"; LIBRARY_FLAG_NOSPACE = YES; GCC_DYNAMIC_NO_PIC = NO; GCC_SYMBOLS_PRIVATE_EXTERN = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; STRIP_STYLE = "all"; CODE_SIGNING_ALLOWED = YES; }; PackageTypes = ( com.apple.package-type.mach-o-executable // default ); WantsSigningEditing = YES; WantsBundleIdentifierEditing = YES; }, // Java tool { Type = ProductType; Identifier = com.apple.product-type.tool.java; Name = "Java Command-line Tool"; Description = "Java Command-line tool"; IconNamePrefix = "TargetExecutable"; DefaultTargetName = "Java Command-line Tool"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)"; REZ_EXECUTABLE = YES; INSTALL_PATH = "/usr/local/bin"; }; IsJava = YES; PackageTypes = ( com.apple.package-type.jarfile, // default com.apple.package-type.zipfile, com.apple.package-type.javaclassfolder ); }, // Object file { Type = ProductType; Identifier = com.apple.product-type.objfile; Class = XCStandaloneExecutableProductType; Name = "Object File"; Description = "Object File"; IconNamePrefix = "TargetPlugin"; DefaultTargetName = "Object File"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)"; MACH_O_TYPE = "mh_object"; LINK_WITH_STANDARD_LIBRARIES = NO; REZ_EXECUTABLE = YES; EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)"; EXECUTABLE_EXTENSION = "o"; PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include"; PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include"; INSTALL_PATH = "$(HOME)/Objects"; FRAMEWORK_FLAG_PREFIX = "-framework"; LIBRARY_FLAG_PREFIX = "-l"; LIBRARY_FLAG_NOSPACE = YES; SKIP_INSTALL = YES; STRIP_STYLE = "debugging"; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; KEEP_PRIVATE_EXTERNS = YES; DEAD_CODE_STRIPPING = NO; }; PackageTypes = ( com.apple.package-type.mach-o-objfile // default ); }, // Dynamic library { Type = ProductType; Identifier = com.apple.product-type.library.dynamic; Class = PBXDynamicLibraryProductType; Name = "Dynamic Library"; Description = "Dynamic library"; IconNamePrefix = "TargetLibrary"; DefaultTargetName = "Dynamic Library"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)"; MACH_O_TYPE = "mh_dylib"; REZ_EXECUTABLE = YES; EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)"; EXECUTABLE_EXTENSION = "dylib"; PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include"; PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include"; INSTALL_PATH = "/usr/local/lib"; DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; DYLIB_COMPATIBILITY_VERSION = "1"; DYLIB_CURRENT_VERSION = "1"; FRAMEWORK_FLAG_PREFIX = "-framework"; LIBRARY_FLAG_PREFIX = "-l"; LIBRARY_FLAG_NOSPACE = YES; STRIP_STYLE = "debugging"; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; CODE_SIGNING_ALLOWED = YES; CODE_SIGNING_REQUIRED = NO; }; PackageTypes = ( com.apple.package-type.mach-o-dylib // default ); }, // Static library { Type = ProductType; Identifier = com.apple.product-type.library.static; Class = PBXStaticLibraryProductType; Name = "Static Library"; Description = "Static library"; IconNamePrefix = "TargetLibrary"; DefaultTargetName = "Static Library"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)"; MACH_O_TYPE = "staticlib"; REZ_EXECUTABLE = YES; EXECUTABLE_PREFIX = "lib"; EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)"; EXECUTABLE_EXTENSION = "a"; PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include"; PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include"; INSTALL_PATH = "/usr/local/lib"; FRAMEWORK_FLAG_PREFIX = "-framework"; LIBRARY_FLAG_PREFIX = "-l"; LIBRARY_FLAG_NOSPACE = YES; STRIP_STYLE = "debugging"; CLANG_ENABLE_MODULE_DEBUGGING = NO; CODE_SIGNING_ALLOWED = NO; }; AlwaysPerformSeparateStrip = YES; PackageTypes = ( com.apple.package-type.static-library // default ); }, // Java library (jar or zip file) { Type = ProductType; Identifier = com.apple.product-type.library.java.archive; Name = "Java Library"; Description = "Java library packaged as a Jar file, Zip file, or class folder"; IconNamePrefix = "TargetPlugin"; DefaultTargetName = "Java Library"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(PRODUCT_NAME)"; INSTALL_PATH = "/usr/local/lib"; }; IsJava = YES; PackageTypes = ( com.apple.package-type.jarfile, // default com.apple.package-type.zipfile, com.apple.package-type.javaclassfolder ); }, // // Wrapper product types // // Bundle { Type = ProductType; Identifier = com.apple.product-type.bundle; Class = PBXBundleProductType; Name = "Bundle"; Description = "Generic bundle"; IconNamePrefix = "TargetPlugin"; DefaultTargetName = "Bundle"; DefaultBuildProperties = { FULL_PRODUCT_NAME = "$(WRAPPER_NAME)"; MACH_O_TYPE = "mh_bundle"; WRAPPER_PREFIX = ""; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "bundle"; WRAPPER_NAME = "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)"; FRAMEWORK_FLAG_PREFIX = "-framework"; LIBRARY_FLAG_PREFIX = "-l"; LIBRARY_FLAG_NOSPACE = YES; STRIP_STYLE = "non-global"; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; CODE_SIGNING_ALLOWED = YES; }; PackageTypes = ( com.apple.package-type.wrapper, // default com.apple.package-type.wrapper.shallow // Not clear if this is needed in the presence of the Shallow Bundle product type below. ); IsWrapper = YES; HasInfoPlist = YES; HasInfoPlistStrings = YES; WantsBundleIdentifierEditing = YES; WantsSigningEditing = YES; }, // Shallow Bundle Product { Type = ProductType; Identifier = com.apple.product-type.bundle.shallow; BasedOn = com.apple.product-type.bundle; Class = PBXBundleProductType; Name = "Bundle (Shallow)"; Description = "Bundle (Shallow)"; PackageTypes = ( com.apple.package-type.wrapper.shallow ); }, // Application { Type = ProductType; Identifier = com.apple.product-type.application; BasedOn = com.apple.product-type.bundle; Class = PBXApplicationProductType; Name = "Application"; Description = "Application"; IconNamePrefix = "TargetApp"; DefaultTargetName = "Application"; DefaultBuildProperties = { MACH_O_TYPE = "mh_execute"; GCC_DYNAMIC_NO_PIC = NO; GCC_SYMBOLS_PRIVATE_EXTERN = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "app"; INSTALL_PATH = "$(LOCAL_APPS_DIR)"; STRIP_STYLE = "all"; CODE_SIGNING_ALLOWED = YES; LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST))"; LD_RUNPATH_SEARCH_PATHS_YES = ( "@loader_path/../Frameworks", ); }; PackageTypes = ( com.apple.package-type.wrapper.application // default ); /** Product type validation hooks */ Validation = { // Checks - a dictionary of checks that are perform just prior to building the product // Each dictionary key is the "XCPropertyMacroExpression" to evaluate // The dictionary value contains the error message to display if the condition evaluates to false. Checks = { // This is intentially empty as currently all of the checks are done in-code for this particular application type. However, we enable the plubmbing for the validation tool spec infrastructure to be called to avoid any further hacks in pbxbuild or xcbuild. This is to enable rdar://problem/45590882. }; // Determines if the legacy build system has support for this validation hook. This is a workaround for enabling additional validation in xcbuild (specifically for rdar://problem/45590882), which does not have the same plugin restriction that is imposed on pbxbuild's implementation of the validation hooks. EnabledForLegacyBuildSystem = NO; // ValidationToolSpec - the identifier of the tool (script) to run after a target is constructed. ValidationToolSpec = "com.apple.build-tools.platform.validate"; }; CanEmbedCompilerSanitizerLibraries = YES; RunpathSearchPathForEmbeddedFrameworks = "@executable_path/../Frameworks"; ValidateEmbeddedBinaries = YES; ProvisioningProfileSupported = YES; ProvisioningProfileRequired = NO; WantsBundleIdentifierEditing = YES; WantsSigningEditing = YES; }, // Shallow Application Product { Type = ProductType; Identifier = com.apple.product-type.application.shallow; BasedOn = com.apple.product-type.application; Class = PBXApplicationProductType; // see radar 5604879, this shouldn't be necesary Name = "Application (Shallow Bundle)"; Description = "Application (Shallow Bundle)"; PackageTypes = ( com.apple.package-type.wrapper.application.shallow ); }, // Java Application { Type = ProductType; Identifier = com.apple.product-type.application.java; BasedOn = com.apple.product-type.application; Name = "Java Application"; Description = "Java Application"; DefaultTargetName = "Java Application"; DefaultBuildProperties = { INFOPLIST_PATH = ""; PKGINFO_PATH = ""; }; IsJava = YES; }, // Framework { Type = ProductType; Identifier = com.apple.product-type.framework; BasedOn = com.apple.product-type.bundle; Class = PBXFrameworkProductType; Name = "Framework"; Description = "Framework"; IconNamePrefix = "TargetFramework"; DefaultTargetName = "Framework"; DefaultBuildProperties = { MACH_O_TYPE = "mh_dylib"; FRAMEWORK_VERSION = "A"; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "framework"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; STRIP_STYLE = "debugging"; CODE_SIGNING_ALLOWED = YES; CODE_SIGNING_REQUIRED = NO; ENTITLEMENTS_REQUIRED = NO; CODE_SIGNING_REQUIRES_TEAM = YES; }; PackageTypes = ( com.apple.package-type.wrapper.framework // default ); }, // Shallow Framework Product { Type = ProductType; Identifier = com.apple.product-type.framework.shallow; BasedOn = com.apple.product-type.framework; Class = PBXFrameworkProductType; Name = "Framework (Shallow Bundle)"; Description = "Framework (Shallow Bundle)"; PackageTypes = ( com.apple.package-type.wrapper.framework.shallow ); }, // Static framework { Type = ProductType; Identifier = com.apple.product-type.framework.static; BasedOn = com.apple.product-type.framework; Class = XCStaticFrameworkProductType; Name = "Static Framework"; Description = "Static Framework"; IconNamePrefix = "TargetFramework"; DefaultTargetName = "Static Framework"; DefaultBuildProperties = { MACH_O_TYPE = "staticlib"; FRAMEWORK_VERSION = "A"; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "framework"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; DYLIB_INSTALL_NAME_BASE = ""; LD_DYLIB_INSTALL_NAME = ""; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; CODE_SIGNING_ALLOWED = NO; }; AlwaysPerformSeparateStrip = YES; PackageTypes = ( com.apple.package-type.wrapper.framework.static // default ); }, // System extension { Type = ProductType; Identifier = com.apple.product-type.system-extension; BasedOn = com.apple.product-type.bundle; Name = "DriverKit Driver"; Description = "DriverKit driver"; DefaultTargetName = "DriverKit Driver"; DefaultBuildProperties = { MACH_O_TYPE = "mh_execute"; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "systemextension"; PRODUCT_NAME = "$(PRODUCT_BUNDLE_IDENTIFIER)"; }; PackageTypes = ( com.apple.package-type.wrapper.system-extension, ); ProvisioningProfileSupported = YES; ProvisioningProfileRequired = NO; }, // DriverKit driver { Type = ProductType; Identifier = com.apple.product-type.driver-extension; BasedOn = com.apple.product-type.system-extension; Name = "DriverKit Driver"; Description = "DriverKit driver"; DefaultTargetName = "DriverKit Driver"; DefaultBuildProperties = { SDKROOT = "driverkit"; MACH_O_TYPE = "mh_execute"; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "dext"; INSTALL_PATH = "$(DEFAULT_DEXT_INSTALL_PATH)"; STRIP_STYLE = "debugging"; DEXT_FRAMEWORK_NAME = "DriverKit"; DEXT_FRAMEWORK = "$(SYSTEM_LIBRARY_DIR)/Frameworks/$(DEXT_FRAMEWORK_NAME).framework"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = "$(PRODUCT_BUNDLE_IDENTIFIER)"; PRODUCT_TYPE_HEADER_SEARCH_PATHS = "$(inherited) $(IIG_HEADERS_DIR)"; }; DefaultEntitlements = { "com.apple.developer.driverkit" = YES; }; PackageTypes = ( com.apple.package-type.wrapper.driver-extension, ); }, // Kernel Extension { Type = ProductType; Identifier = com.apple.product-type.kernel-extension; BasedOn = com.apple.product-type.bundle; Class = XCKernelExtensionProductType; Name = "Kernel Extension"; Description = "Kernel extension"; DefaultTargetName = "Kernel Extension"; DefaultBuildProperties = { MACH_O_TYPE = "mh_execute"; WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)"; WRAPPER_EXTENSION = "kext"; INSTALL_PATH = "$(DEFAULT_KEXT_INSTALL_PATH)"; STRIP_STYLE = "debugging"; KEXT_FRAMEWORK_NAME = "Kernel"; KEXT_FRAMEWORK = "$(SYSTEM_LIBRARY_DIR)/Frameworks/$(KEXT_FRAMEWORK_NAME).framework"; KEXT_FAMILY_NAME = "family"; PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)"; PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)"; MODULE_NAME = "com.company.driver.modulename"; MODULE_VERSION = "1.0"; MODULE_START = "0"; MODULE_STOP = "0"; ENABLE_APPLE_KEXT_CODE_GENERATION = YES; // -fapple-kext GCC_ENABLE_KERNEL_DEVELOPMENT = YES; // -mkernel GCC_USE_STANDARD_INCLUDE_SEARCHING = NO; // -nostdinc GCC_ENABLE_PASCAL_STRINGS = NO; // Disables -fpascal-strings GCC_FORCE_CPU_SUBTYPE_ALL = YES; // -force_cpusubtype_ALL GCC_CHECK_RETURN_VALUE_OF_OPERATOR_NEW = YES; // -fcheck-new GCC_INLINES_ARE_PRIVATE_EXTERN = NO; // -fvisibility-inlines-hidden GCC_ENABLE_BUILTIN_FUNCTIONS = NO; // -fno-builtin GCC_NO_COMMON_BLOCKS = YES; // -fno-common GCC_ENABLE_CPP_EXCEPTIONS = NO; // -fno-exceptions GCC_ENABLE_CPP_RTTI = NO; // -fno-rtti // Supposedly these two flags are the default in GCC, but they're provided here for compatibility with older Xcode versions. GCC_ENABLE_FUNCTION_INLINING = YES; // -finline GCC_DISABLE_STATIC_FUNCTION_INLINING = YES; // -fno-keep-inline-functions // Per-product-type settings. // The KERNEL_*** settings are defined differently for some SDKs, so we continue to use them for compatibility reasons. KERNEL_FRAMEWORK = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework"; KERNEL_FRAMEWORK_HEADERS = "$(KERNEL_FRAMEWORK)/Headers"; KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(KERNEL_FRAMEWORK)/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)"; // These settings are reserved for use by product types. GCC_PRODUCT_TYPE_PREPROCESSOR_DEFINITIONS = "$(inherited) KERNEL KERNEL_PRIVATE DRIVER_PRIVATE APPLE NeXT"; PRODUCT_TYPE_CFLAGS = "$(inherited) $(KEXT_CFLAGS)"; PRODUCT_TYPE_CPLUSPLUSFLAGS = "$(inherited) $(KEXT_CPLUSPLUSFLAGS)"; PRODUCT_SPECIFIC_LDFLAGS = "$(inherited) $(KEXT_LDFLAGS)"; PRODUCT_TYPE_HEADER_SEARCH_PATHS = "$(inherited) $(KERNEL_EXTENSION_HEADER_SEARCH_PATHS)"; CODE_SIGNING_ALLOWED = YES; ARCHS_STANDARD = "arm64e x86_64"; ARCHS_STANDARD_64_BIT = "$(ARCHS_STANDARD)"; ARCHS_STANDARD_INCLUDING_64_BIT = "$(ARCHS_STANDARD)"; }; PackageTypes = ( com.apple.package-type.wrapper.kernel-extension, // Default com.apple.package-type.wrapper.kernel-extension.shallow, ); }, // Shallow Kernel Extension { Type = ProductType; Identifier = com.apple.product-type.kernel-extension.shallow; BasedOn = com.apple.product-type.kernel-extension; Class = XCKernelExtensionProductType; Name = "Kernel Extension (Shallow)"; Description = "Kernel extension (shallow)"; DefaultBuildProperties = { // None yet }; PackageTypes = ( com.apple.package-type.wrapper.kernel-extension.shallow, ); }, // IOKit Kernel Extension { Type = ProductType; Identifier = com.apple.product-type.kernel-extension.iokit; BasedOn = com.apple.product-type.kernel-extension; Class = XCKernelExtensionProductType; Name = "IOKit Kernel Extension"; Description = "IOKit Kernel extension"; DefaultTargetName = "IOKit Kernel Extension"; DefaultBuildProperties = { CODE_SIGNING_ALLOWED = YES; }; PackageTypes = ( com.apple.package-type.wrapper.kernel-extension, // Default com.apple.package-type.wrapper.kernel-extension.shallow, ); }, // Shallow IOKit Kernel Extension { Type = ProductType; Identifier = com.apple.product-type.kernel-extension.iokit.shallow; BasedOn = com.apple.product-type.kernel-extension; Class = XCKernelExtensionProductType; Name = "IOKit Kernel Extension (Shallow)"; Description = "IOKit Kernel extension (Shallow)"; DefaultTargetName = "IOKit Kernel Extension (Shallow)"; DefaultBuildProperties = { // None yet }; PackageTypes = ( com.apple.package-type.wrapper.kernel-extension.shallow, ); }, // Unit Test Bundle { Type = ProductType; Identifier = com.apple.product-type.bundle.unit-test; BasedOn = com.apple.product-type.bundle; Class = PBXXCTestBundleProductType; Name = "Unit Test Bundle"; Description = "Unit Test Bundle"; DefaultBuildProperties = { WRAPPER_EXTENSION = "xctest"; ENABLE_TESTING_SEARCH_PATHS = YES; PRODUCT_SPECIFIC_LDFLAGS = "-framework XCTest"; XCTRUNNER_PATH = "$(XCTRUNNER_PATH$(TEST_BUILD_STYLE))"; LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST))"; LD_RUNPATH_SEARCH_PATHS_YES = ( "@loader_path/../Frameworks", "@executable_path/../Frameworks", ); }; PackageTypes = ( com.apple.package-type.bundle.unit-test ); CanEmbedCompilerSanitizerLibraries = YES; IsUnitTest = YES; WantsBundleIdentifierEditing = NO; }, // UI Testing Bundle { Type = ProductType; Identifier = com.apple.product-type.bundle.ui-testing; BasedOn = com.apple.product-type.bundle.unit-test; Class = PBXXCTestBundleProductType; Name = "UI Testing Bundle"; Description = "UI Testing Bundle"; DefaultBuildProperties = { USES_XCTRUNNER = "YES"; }; PackageTypes = ( com.apple.package-type.bundle.unit-test ); ProvisioningProfileSupported = YES; IsUITest = YES; InfoPlistAdditions = { XCTContainsUITests = YES; }; WantsBundleIdentifierEditing = NO; }, // Legacy OCUnit Test Bundle { Type = ProductType; Identifier = com.apple.product-type.bundle.ocunit-test; BasedOn = com.apple.product-type.bundle; Class = PBXBundleProductType; Name = "OCUnit Test Bundle"; Description = "OCUnit Test Bundle"; DefaultBuildProperties = { WRAPPER_EXTENSION = "octest"; }; PackageTypes = ( com.apple.package-type.bundle.ocunit-test ); IsUnitTest = YES; }, // In-App Purchase Content { Type = ProductType; Identifier = com.apple.product-type.in-app-purchase-content; Class = PBXBundleProductType; Name = "In-App Purchase Content"; Description = "In-App Purchase Content"; DefaultBuildProperties = { CODE_SIGNING_ALLOWED = NO; FULL_PRODUCT_NAME = "$(WRAPPER_NAME)"; }; PackageTypes = ( com.apple.package-type.in-app-purchase-content, // default ); IsWrapper = YES; HasInfoPlist = YES; HasInfoPlistStrings = NO; }, // XPC Service { Type = ProductType; Identifier = "com.apple.product-type.xpc-service"; BasedOn = "com.apple.product-type.bundle"; Class = PBXBundleProductType; Name = "XPC Service"; Description = "XPC Service"; IconNamePrefix = XPCService; DefaultTargetName = "XPC Service"; CanEmbedCompilerSanitizerLibraries = YES; "DefaultBuildProperties" = { "MACH_O_TYPE" = "mh_execute"; WRAPPER_EXTENSION = "xpc"; LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST)_$(_BOOL_$(SKIP_INSTALL)))"; LD_RUNPATH_SEARCH_PATHS_YES_YES = ( "@loader_path/../Frameworks", "@loader_path/../../../../Frameworks", ); LD_RUNPATH_SEARCH_PATHS_YES_NO = ( "@loader_path/../Frameworks", ); }; PackageTypes = ( "com.apple.package-type.xpc-service", ); ProvisioningProfileSupported = YES; ProvisioningProfileRequired = NO; WantsBundleIdentifierEditing = YES; WantsSigningEditing = YES; }, // PlugIn-Kit PlugIn { Type = ProductType; Identifier = "com.apple.product-type.pluginkit-plugin"; BasedOn = "com.apple.product-type.xpc-service"; Class = PBXBundleProductType; Name = "PlugInKit PlugIn"; Description = "PlugInKit PlugIn"; IconNamePrefix = XPCService; DefaultTargetName = "PlugInKit PlugIn"; "DefaultBuildProperties" = { "PRODUCT_SPECIFIC_LDFLAGS" = "$(SDKROOT)/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit"; WRAPPER_EXTENSION = "pluginkit"; }; PackageTypes = ( "com.apple.package-type.pluginkit-plugin", ); }, // App Extension { Type = ProductType; Identifier = "com.apple.product-type.app-extension"; BasedOn = "com.apple.product-type.pluginkit-plugin"; Class = PBXBundleProductType; Name = "App Extension"; Description = "App Extension"; IconNamePrefix = AppExtension; DefaultTargetName = "App Extension"; "DefaultBuildProperties" = { "CODE_SIGNING_ALLOWED" = YES; "APPLICATION_EXTENSION_API_ONLY" = YES; "PRODUCT_SPECIFIC_LDFLAGS" = "-e _NSExtensionMain"; WRAPPER_EXTENSION = "appex"; }; PackageTypes = ( "com.apple.package-type.app-extension", ); ProvisioningProfileSupported = YES; ProvisioningProfileRequired = NO; WantsBundleIdentifierEditing = YES; WantsSigningEditing = YES; }, // Xcode Extension { Type = ProductType; Identifier = "com.apple.product-type.xcode-extension"; BasedOn = "com.apple.product-type.app-extension"; Name = "Xcode Extension"; Description = "Xcode Extension"; IconNamePrefix = XcodeExtension; DefaultTargetName = "Xcode Extension"; "DefaultBuildProperties" = { "CODE_SIGNING_ALLOWED" = YES; "APPLICATION_EXTENSION_API_ONLY" = YES; "PRODUCT_SPECIFIC_LDFLAGS" = "-e _XCExtensionMain -lXcodeExtension"; "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" = ( "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); "PRODUCT_TYPE_LIBRARY_SEARCH_PATHS" = ( "$(inherited)", "$(DEVELOPER_USR_DIR)/lib", ); LD_RUNPATH_SEARCH_PATHS = ( "@loader_path/../Frameworks", ); WRAPPER_EXTENSION = "appex"; }; PackageTypes = ( "com.apple.package-type.app-extension", ); ProvisioningProfileSupported = YES; ProvisioningProfileRequired = NO; WantsBundleIdentifierEditing = YES; WantsSigningEditing = YES; }, // Spotlight Importer { Type = ProductType; Identifier = "com.apple.product-type.spotlight-importer"; BasedOn = "com.apple.product-type.bundle"; Class = PBXBundleProductType; Name = "Spotlight Importer"; Description = "Spotlight Importer"; DefaultTargetName = "Spotlight"; "DefaultBuildProperties" = { "CODE_SIGNING_ALLOWED" = YES; }; PackageTypes = ( "com.apple.package-type.spotlight-importer", ); }, // Copied from iOS specs to aid in build system diagnostic support. // Later, we should put these in some central place. { Type = ProductType; Identifier = "com.apple.product-type.app-extension.messages"; BasedOn = "com.apple.product-type.app-extension"; }, { Type = ProductType; Identifier = "com.apple.product-type.app-extension.messages-sticker-pack"; BasedOn = "com.apple.product-type.app-extension"; IsCapabilitiesUnsupported = YES; WantsSimpleTargetEditing = YES; DefaultBuildProperties = { MESSAGES_APPLICATION_EXTENSION_PRODUCT_BINARY_SOURCE_PATH = "$(PLATFORM_DIR)/Library/Application Support/MessagesApplicationExtensionStub/MessagesApplicationExtensionStub"; ASSETCATALOG_COMPILER_INCLUDE_STICKER_CONTENT = YES; ASSETCATALOG_COMPILER_TARGET_STICKERS_ICON_ROLE = "extension"; ASSETCATALOG_COMPILER_STICKER_PACK_IDENTIFIER_PREFIX = "$(PRODUCT_BUNDLE_IDENTIFIER).sticker-pack."; }; AllowedBuildPhases = ( "com.apple.buildphase.resources", "com.apple.buildphase.shell-script", ); InfoPlistAdditions = { LSApplicationIsStickerProvider = YES; }; }, { Type = ProductType; Identifier = "com.apple.product-type.application.on-demand-install-capable"; BasedOn = "com.apple.product-type.application"; Name = "App Clip"; Description = "App Clip"; DefaultBuildProperties = { ENABLE_ON_DEMAND_RESOURCES = NO; ASSETCATALOG_COMPILER_STANDALONE_ICON_BEHAVIOR = none; // Don't include standalone icons to keep size down PRODUCT_SPECIFIC_LDFLAGS = "$(inherited) -framework AppClip"; SKIP_INSTALL = YES; }; DefaultEntitlements = { "com.apple.developer.on-demand-install-capable" = YES; }; SupportsOnDemandResources = NO; IsEmbeddable = YES; BuildPhaseInjectionsWhenEmbedding = ( { BuildPhase = "CopyFiles"; Name = "Embed App Clips"; RunOnlyForDeploymentPostprocessing = NO; DstSubFolderSpec = 16; DstPath = "$(CONTENTS_FOLDER_PATH)/AppClips"; } ); }, ) qbs-src-3.3.1/share/qbs/modules/bundle/bundle.js0000644000175100017510000011756515232633614021141 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Codesign = require("../codesign/codesign.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var DarwinTools = require("qbs.DarwinTools"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var Utilities = require("qbs.Utilities"); // HACK: Workaround until the PropertyList extension is supported cross-platform var TextFile = require("qbs.TextFile"); var PropertyList2 = (function () { function PropertyList2() { } PropertyList2.prototype.readFromFile = function (filePath) { var str; var process = new Process(); try { if (process.exec("plutil", ["-convert", "json", "-o", "-", filePath], false) === 0) { str = process.readStdOut(); } else { var tf = new TextFile(filePath); try { str = tf.readAll(); } finally { tf.close(); } } } finally { process.close(); } if (str) this.obj = JSON.parse(str); }; PropertyList2.prototype.toObject = function () { return this.obj; }; PropertyList2.prototype.clear = function () { }; return PropertyList2; }()); // Order is significant due to productTypeIdentifier() search path var _productTypeIdentifiers = { "inapppurchase": "com.apple.product-type.in-app-purchase-content", "applicationextension": "com.apple.product-type.app-extension", "xpcservice": "com.apple.product-type.xpc-service", "application": "com.apple.product-type.application", "dynamiclibrary": "com.apple.product-type.framework", "loadablemodule": "com.apple.product-type.bundle", "staticlibrary": "com.apple.product-type.framework.static", "kernelmodule": "com.apple.product-type.kernel-extension" }; function productTypeIdentifier(productType) { for (var k in _productTypeIdentifiers) { if (productType.includes(k)) return _productTypeIdentifiers[k]; } return "com.apple.package-type.wrapper"; } function excludedAuxiliaryInputs(project, product) { var chain = product.bundle._productTypeIdentifierChain; var bestPossibleType; for (var i = chain.length - 1; i >= 0; --i) { switch (chain[i]) { case "com.apple.product-type.bundle": bestPossibleType = "loadablemodule"; break; case "com.apple.product-type.framework": bestPossibleType = "dynamiclibrary"; break; case "com.apple.product-type.framework.static": bestPossibleType = "staticlibrary"; break; case "com.apple.product-type.application": case "com.apple.product-type.xpc-service": bestPossibleType = "application"; break; } } var excluded = []; var possibleTypes = ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"]; for (i = 0; i < possibleTypes.length; ++i) { if (possibleTypes[i] !== bestPossibleType) excluded.push(possibleTypes[i]); } return excluded; } function packageType(productTypeIdentifier) { switch (productTypeIdentifier) { case "com.apple.product-type.in-app-purchase-content": return undefined; case "com.apple.product-type.app-extension": case "com.apple.product-type.xpc-service": return "XPC!"; case "com.apple.product-type.application": return "APPL"; case "com.apple.product-type.framework": case "com.apple.product-type.framework.static": return "FMWK"; case "com.apple.product-type.kernel-extension": case "com.apple.product-type.kernel-extension.iokit": return "KEXT"; default: return "BNDL"; } } function _assign(target, source) { if (source) { for (var k in source) { if (source.hasOwnProperty(k)) target[k] = source[k]; } return target; } } function macOSSpecsPaths(version, developerPath) { var result = []; if (Utilities.versionCompare(version, "15.3") >= 0) { result.push(FileInfo.joinPaths( developerPath, "..", "SharedFrameworks", "XCBuild.framework", "PlugIns", "XCBBuildService.bundle", "Contents", "PlugIns", "XCBSpecifications.ideplugin", "Contents", "Resources")); } if (Utilities.versionCompare(version, "14.3") >= 0) { result.push(FileInfo.joinPaths( developerPath, "Library", "Xcode", "Plug-ins", "XCBSpecifications.ideplugin", "Contents", "Resources")); } else if (Utilities.versionCompare(version, "12.5") >= 0) { result.push(FileInfo.joinPaths( developerPath, "..", "PlugIns", "XCBSpecifications.ideplugin", "Contents", "Resources")); } else if (Utilities.versionCompare(version, "12") >= 0) { result.push(FileInfo.joinPaths( developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode", "PrivatePlugIns", "IDEOSXSupportCore.ideplugin", "Contents", "Resources")); } else { result.push(FileInfo.joinPaths( developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode", "Specifications")); } return result; } var XcodeBuildSpecsReader = (function () { function XcodeBuildSpecsReader(specsPaths, separator, additionalSettings, useShallowBundles) { this._additionalSettings = additionalSettings; this._useShallowBundles = useShallowBundles; this._packageTypes = []; this._productTypes = []; var i, j; for (i = 0; i < specsPaths.length; ++i) { var specsPath = specsPaths[i]; var names = ["", "Darwin", "MacOSX"]; for (j = 0; j < names.length; ++j) { var name = names[j]; var plist = new PropertyList2(); var plist2 = new PropertyList2(); try { var plistName = [name, "Package", "Types.xcspec"].join(name ? separator : ""); var plistName2 = [name, "Product", "Types.xcspec"].join(name ? separator : ""); var plistPath = FileInfo.joinPaths(specsPath, plistName); var plistPath2 = FileInfo.joinPaths(specsPath, plistName2); if (File.exists(plistPath)) { plist.readFromFile(plistPath); this._packageTypes = this._packageTypes.concat(plist.toObject()); } if (File.exists(plistPath2)) { plist2.readFromFile(plistPath2); this._productTypes = this._productTypes.concat(plist2.toObject()); } } finally { plist.clear(); plist2.clear(); } } } this._types = {}; for (i = 0; i < this._packageTypes.length; ++i) this._types[this._packageTypes[i]["Identifier"]] = this._packageTypes[i]; for (i = 0; i < this._productTypes.length; ++i) this._types[this._productTypes[i]["Identifier"]] = this._productTypes[i]; } XcodeBuildSpecsReader.prototype.productTypeIdentifierChain = function (typeIdentifier) { var ids = [typeIdentifier]; var obj = this._types[typeIdentifier]; var parentId = obj && obj["BasedOn"]; if (parentId) return ids.concat(this.productTypeIdentifierChain(parentId)); return ids; }; XcodeBuildSpecsReader.prototype.settings = function (typeIdentifier, recursive, skipPackageTypes) { // Silently use shallow bundles when preferred since it seems to be some sort of automatic // shadowing mechanism. For example, this matches Xcode behavior where static frameworks // are shallow even though no such product specification exists, and also seems to match // other behavior i.e. where productType in pbxproj files is never explicitly shallow. if (this._useShallowBundles && this._types[typeIdentifier + ".shallow"] && !skipPackageTypes) typeIdentifier += ".shallow"; var typesObject = this._types[typeIdentifier]; if (typesObject) { var buildProperties = {}; if (recursive) { // Get all the settings for the product's package type if (!skipPackageTypes && typesObject["PackageTypes"]) { for (var k = 0; k < typesObject["PackageTypes"].length; ++k) { var props = this.settings(typesObject["PackageTypes"][k], recursive, true); for (var y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } break; } } // Get all the settings for the product's inherited product type if (typesObject["BasedOn"]) { // We'll only do the auto shallow substitution for wrapper package types... // this ensures that in-app purchase content bundles are non-shallow on both // macOS and iOS, for example (which matches Xcode behavior) var isWrapper = false; if (typesObject["ProductReference"]) { var fileType = typesObject["ProductReference"]["FileType"]; if (fileType) isWrapper = fileType.startsWith("wrapper."); } // Prevent recursion loop if this spec's base plus .shallow would be the same // as the current spec's identifier var baseIdentifier = typesObject["BasedOn"]; if (this._useShallowBundles && isWrapper && this._types[baseIdentifier + ".shallow"] && typeIdentifier !== baseIdentifier + ".shallow") baseIdentifier += ".shallow"; props = this.settings(baseIdentifier, recursive, true); for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } } if (typesObject["Type"] === "PackageType") { props = typesObject["DefaultBuildSettings"]; for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } if (typesObject["Type"] === "ProductType") { props = typesObject["DefaultBuildProperties"]; for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } return buildProperties; } }; XcodeBuildSpecsReader.prototype.setting = function (typeIdentifier, settingName) { var obj = this.settings(typeIdentifier, false); if (obj) { return obj[settingName]; } }; XcodeBuildSpecsReader.prototype.expandedSettings = function (typeIdentifier, baseSettings) { var obj = this.settings(typeIdentifier, true); if (obj) { for (var k in obj) obj[k] = this.expandedSetting(typeIdentifier, baseSettings, k); return obj; } }; XcodeBuildSpecsReader.prototype.expandedSetting = function (typeIdentifier, baseSettings, settingName) { var obj = {}; _assign(obj, baseSettings); // todo: copy recursively obj = _assign(obj, this.settings(typeIdentifier, true)); if (obj) { for (var x in this._additionalSettings) { var additionalSetting = this._additionalSettings[x]; if (additionalSetting !== undefined) obj[x] = additionalSetting; } var setting = obj[settingName]; var original; while (original !== setting) { original = setting; setting = DarwinTools.expandPlistEnvironmentVariables({ key: setting }, obj, false)["key"]; } return setting; } }; return XcodeBuildSpecsReader; }()); function filePathToArtifactLike(filePath) { return { filePath: filePath, fileName: FileInfo.fileName(filePath), path: FileInfo.path(filePath) }; } function getMainBundleTags(product) { if (product.bundle.isMainBundle) return []; var tags = ["bundle.main.input"]; var packageType = product.bundle && product.bundle.packageType; if (packageType === "APPL") tags.push("bundle.main.application"); else if (packageType === "FMWK") tags.push("bundle.main.framework"); else if (packageType === "BNDL") tags.push("bundle.main.plugin"); return tags; } function getCopiedDepenendencyFilePath(product, input) { var filePath = FileInfo.relativePath(input.product.buildDirectory, input.filePath) if (input.fileTags.includes("bundle.main.executable")) filePath = FileInfo.joinPaths(product.bundle.executablesFolderPath, filePath); else if (input.fileTags.includes("bundle.main.application")) filePath = FileInfo.joinPaths(product.bundle.applicationsFolderPath, filePath); else if (input.fileTags.includes("bundle.main.library")) filePath = FileInfo.joinPaths(product.bundle.frameworksFolderPath, filePath); else if (input.fileTags.includes("bundle.main.framework")) filePath = FileInfo.joinPaths(product.bundle.frameworksFolderPath, filePath); else if (input.fileTags.includes("bundle.main.plugin")) filePath = FileInfo.joinPaths(product.bundle.pluginsFolderPath, filePath); else return undefined; return FileInfo.joinPaths(product.buildDirectory, filePath); } function generateMainBundleOutputs(product, inputs) { var skippedDeps = {}; product.dependencies.forEach(function(dep) { if (dep.parameters.bundle && dep.parameters.bundle.isForMainBundle === false) skippedDeps[dep.name] = true; }); var artifacts = []; if (product.bundle.isMainBundle) { (inputs["bundle.main.input"] || []).forEach(function(input) { if (!input.bundle.isForMainBundle) return; if (skippedDeps[input.product.name]) return; const filePath = getCopiedDepenendencyFilePath(product, input); // We could probably just skip such files silently if (filePath === undefined) throw("Cannot determine main bundle file path for " + input.filePath); artifacts.push({ filePath: filePath, fileTags: ["bundle.content", "bundle.content.copied.from.dependencies"], bundle: { _mainBundleInputFilePath: input.filePath }, }); }); } return artifacts; } function generateMainBundleCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { if (!product.bundle.isMainBundle) return []; const mainBundleOutputs = outputs["bundle.content.copied.from.dependencies"]; if (mainBundleOutputs.length === 0) return []; var cmd = new JavaScriptCommand(); cmd.description = "copying main bundle dependencies"; cmd.highlight = "filegen"; cmd.sources = mainBundleOutputs.map(function(output) { return output.bundle._mainBundleInputFilePath; }); cmd.destinations = mainBundleOutputs.map(function(output) { return output.filePath; }); cmd.sourceCode = function() { for (var i = 0; i < sources.length; ++i) { File.copy(sources[i], destinations[i]); } }; return [cmd]; } function generateBundleOutputs(product, inputs) { var artifacts = []; if (product.bundle.isBundle) { const mainBundleTags = getMainBundleTags(product); (inputs["bundle.input"] || []).forEach(function(input) { var fp = input.bundle._bundleFilePath; if (!fp) throw("Artifact " + input.filePath + " has no associated bundle file path"); var extraTags = input.fileTags.includes("application") ? ["bundle.application-executable"] : []; artifacts.push({ filePath: fp, fileTags: ["bundle.content", "bundle.content.copied"] .concat(extraTags).concat(mainBundleTags), }); }); (inputs["codesign.embedded_provisioningprofile"] || []).forEach(function(input) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.contentsFolderPath, input.fileName), fileTags: ["bundle.provisioningprofile", "bundle.content"].concat(mainBundleTags), }); }); (inputs["bundle.input.privacymanifest"] || []).forEach(function(input) { var filePath; if (product.qbs.targetOS.includes("macos")) { filePath = FileInfo.joinPaths(product.destinationDirectory, product.bundle.contentsFolderPath, "Resources", input.fileName); } else if (product.qbs.targetOS.includes("ios")) { filePath = FileInfo.joinPaths(product.destinationDirectory, product.bundle.contentsFolderPath, input.fileName); } if (filePath) { artifacts.push({ filePath: filePath, fileTags: ["bundle.content", "bundle.privacymanifest"].concat(mainBundleTags), }); } }); var packageType = product.bundle.packageType; var isShallow = product.bundle.isShallow; if (packageType === "FMWK" && !isShallow) { var publicHeaders = (inputs["bundle.input.public_hpp"] || []) .concat(product.bundle.publicHeaders); if (publicHeaders.length > 0) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Headers"), fileTags: ["bundle.symlink.headers", "bundle.content"].concat(mainBundleTags), }); } var privateHeaders = (inputs["bundle.input.private_hpp"] || []) .concat(product.bundle.privateHeaders); if (privateHeaders.length > 0) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "PrivateHeaders"), fileTags: ["bundle.symlink.private-headers", "bundle.content"].concat(mainBundleTags), }); } artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Resources"), fileTags: ["bundle.symlink.resources", "bundle.content"].concat(mainBundleTags), }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, product.targetName), fileTags: ["bundle.symlink.executable", "bundle.content"].concat(mainBundleTags), }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.versionsFolderPath, "Current"), fileTags: ["bundle.symlink.version", "bundle.content"].concat(mainBundleTags), }); } ["public", "private"].forEach(function(headerType) { const sources = (inputs["bundle.input." + headerType + "_hpp"] || []) .concat(product.bundle[headerType + "Headers"].map(filePathToArtifactLike)); const destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, headerType + "HeadersFolderPath")); sources.forEach(function(source) { artifacts.push({ filePath: FileInfo.joinPaths(destination, source.fileName), fileTags: ["bundle.hpp", "bundle.content"].concat(mainBundleTags), }); }); }); const resources = (inputs["bundle.input.resources"] || []) .concat(product.bundle.resources.map(filePathToArtifactLike)); resources.forEach(function(resource) { destination = BundleTools.destinationDirectoryForResource( product, {baseDir: resource.path, fileName: resource.fileName}); artifacts.push({ filePath: FileInfo.joinPaths(destination, resource.fileName), fileTags: ["bundle.resource", "bundle.content"].concat(mainBundleTags), }); }); if (Host.os().includes("darwin") && product.codesign && product.codesign.enableCodeSigning) { var signatureFiles = ["CodeResources"]; // Static libraries generate additional code signature artifacts // This is also true for any framework without a mach-o binary, but do we support those? const isStaticLibrary = product.type.includes("staticlibrary"); if (isStaticLibrary) { signatureFiles = signatureFiles.concat([ "CodeDirectory", "CodeRequirements", "CodeSignature", ]); // Up to macOS 15, codesign additionally writes the internal // requirement to a separate CodeRequirements-1 file. macOS 26 // no longer produces it, so only expect it on older hosts. if (Utilities.versionCompare(product.qbs.hostOSVersion, "26") < 0) signatureFiles.push("CodeRequirements-1"); } Array.prototype.push.apply(artifacts, signatureFiles.map(function(file) { return { filePath: FileInfo.joinPaths( product.destinationDirectory, product.bundle.contentsFolderPath, "_CodeSignature", file), fileTags: ["bundle.code-signature", "bundle.content"].concat(mainBundleTags) }; })); } } return artifacts; } function generateBundleCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var i, cmd, commands = []; var packageType = product.bundle.packageType; var bundleType = "bundle"; if (packageType === "APPL") bundleType = "application"; if (packageType === "FMWK") bundleType = "framework"; // Product is unbundled if (!product.bundle.isBundle) { cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function () { }; commands.push(cmd); } var symlinks = outputs["bundle.symlink.version"]; for (i in symlinks) { cmd = new Command("ln", ["-sfn", product.bundle.frameworkVersion, symlinks[i].filePath]); cmd.silent = true; commands.push(cmd); } var publicHeaders = outputs["bundle.symlink.headers"]; for (i in publicHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/Headers", publicHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var privateHeaders = outputs["bundle.symlink.private-headers"]; for (i in privateHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/PrivateHeaders", privateHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var resources = outputs["bundle.symlink.resources"]; for (i in resources) { cmd = new Command("ln", ["-sfn", "Versions/Current/Resources", resources[i].filePath]); cmd.silent = true; commands.push(cmd); } var executables = outputs["bundle.symlink.executable"]; for (i in executables) { cmd = new Command("ln", ["-sfn", FileInfo.joinPaths("Versions", "Current", product.targetName), executables[i].filePath]); cmd.silent = true; commands.push(cmd); } function sortedArtifactList(list, func) { if (list) { return list.sort(func || (function (a, b) { return a.filePath.localeCompare(b.filePath); })); } } var bundleInputs = sortedArtifactList(inputs["bundle.input"], function (a, b) { return a.bundle._bundleFilePath.localeCompare( b.bundle._bundleFilePath); }); var bundleContents = sortedArtifactList(outputs["bundle.content.copied"]); for (i in bundleContents) { cmd = new JavaScriptCommand(); cmd.silent = true; cmd.source = bundleInputs[i].filePath; cmd.destination = bundleContents[i].filePath; cmd.sourceCode = function() { File.copy(source, destination); }; commands.push(cmd); } cmd = new JavaScriptCommand(); cmd.description = "copying provisioning profile"; cmd.highlight = "filegen"; cmd.sources = (inputs["codesign.embedded_provisioningprofile"] || []) .map(function(artifact) { return artifact.filePath; }); cmd.destination = (outputs["bundle.provisioningprofile"] || []) .map(function(artifact) { return artifact.filePath; }); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], destination[i]); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying privacy manifest"; cmd.highlight = "filegen"; cmd.sources = (inputs["bundle.input.privacymanifest"] || []) .map(function(artifact) { return artifact.filePath; }); cmd.destination = (outputs["bundle.privacymanifest"] || []) .map(function(artifact) { return artifact.filePath; }); cmd.sourceCode = function() { var i; for (var i = 0; i < sources.length; ++i) File.copy(sources[i], destination[i]); }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying public headers"; cmd.highlight = "filegen"; cmd.sources = (inputs["bundle.input.public_hpp"] || []) .map(function(artifact) { return artifact.filePath; }) .concat(product.bundle.publicHeaders); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.publicHeadersFolderPath); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying private headers"; cmd.highlight = "filegen"; cmd.sources = (inputs["bundle.input.private_hpp"] || []) .map(function(artifact) { return artifact.filePath; }) .concat(product.bundle.privateHeaders); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.privateHeadersFolderPath); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying resources"; cmd.highlight = "filegen"; cmd.sources = (inputs["bundle.input.resources"] || []) .map(function(artifact) { return artifact.filePath; }) .concat(product.bundle.resources); cmd.sourceCode = function() { var i; for (var i in sources) { var destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); if (product.qbs.hostOS.includes("darwin")) { Array.prototype.push.apply(commands, Codesign.prepareSign( project, product, inputs, outputs, input, output)); if (bundleType === "application" && product.qbs.targetOS.includes("macos")) { var bundlePath = FileInfo.joinPaths( product.destinationDirectory, product.bundle.bundleName); cmd = new Command(product.bundle.lsregisterPath, ["-f", bundlePath]); cmd.description = "registering " + product.bundle.bundleName; commands.push(cmd); } } return commands; } function generatePkgInfoOutputs(product) { var artifacts = []; if (product.bundle.isBundle && product.bundle.generatePackageInfo) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, "PkgInfo"), fileTags: ["bundle.input", "pkginfo"], bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.pkgInfoPath) } }); } return artifacts; } function generatePkgInfoCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "generating PkgInfo for " + product.name; cmd.highlight = "codegen"; cmd.sourceCode = function() { var infoPlist = BundleTools.infoPlistContents(inputs.aggregate_infoplist[0].filePath); var pkgType = infoPlist['CFBundlePackageType']; if (!pkgType) throw("CFBundlePackageType not found in Info.plist; this should not happen"); var pkgSign = infoPlist['CFBundleSignature']; if (!pkgSign) throw("CFBundleSignature not found in Info.plist; this should not happen"); var pkginfo = new TextFile(outputs.pkginfo[0].filePath, TextFile.WriteOnly); pkginfo.write(pkgType + pkgSign); pkginfo.close(); } return cmd; } function aggregateInfoPlistOutputs(product) { var artifacts = []; var embed = product.bundle.embedInfoPlist; if (product.bundle.isBundle || embed) { artifacts.push({ filePath: FileInfo.joinPaths( product.destinationDirectory, product.name + "-Info.plist"), fileTags: ["aggregate_infoplist"].concat(!embed ? ["bundle.input"] : []), bundle: { _bundleFilePath: FileInfo.joinPaths( product.destinationDirectory, product.bundle.infoPlistPath), } }); } return artifacts; } function aggregateInfoPlistCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "generating Info.plist for " + product.name; cmd.highlight = "codegen"; cmd.infoPlist = product.bundle.infoPlist || {}; cmd.processInfoPlist = product.bundle.processInfoPlist; cmd.infoPlistFormat = product.bundle.infoPlistFormat; cmd.extraEnv = product.bundle.extraEnv; cmd.qmakeEnv = product.bundle.qmakeEnv; // TODO: bundle module should know nothing about cpp module cmd.buildEnv = product.moduleProperty("cpp", "buildEnv"); cmd.developerPath = product.bundle._developerPath; cmd.platformInfoPlist = product.bundle._platformInfoPlist; cmd.sdkSettingsPlist = product.bundle._sdkSettingsPlist; cmd.toolchainInfoPlist = product.bundle._toolchainInfoPlist; cmd.osBuildVersion = product.qbs.hostOSBuildVersion; cmd.sourceCode = function() { var plist, process, key, i; // Contains the combination of default, file, and in-source keys and values // Start out with the contents of this file as the "base", if given var aggregatePlist = {}; for (i = 0; i < (inputs.infoplist || []).length; ++i) { aggregatePlist = BundleTools.infoPlistContents(inputs.infoplist[i].filePath); infoPlistFormat = (infoPlistFormat === "same-as-input") ? BundleTools.infoPlistFormat(inputs.infoplist[i].filePath) : "xml1"; break; } // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) for (key in infoPlist) { if (infoPlist.hasOwnProperty(key)) aggregatePlist[key] = infoPlist[key]; } // Do some postprocessing if desired if (processInfoPlist) { // Add default values to the aggregate plist if the corresponding keys // for those values are not already present var defaultValues = product.bundle.defaultInfoPlist; for (key in defaultValues) { if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } // Add keys from platform's Info.plist if not already present var platformInfo = {}; var sdkSettings = {}; var toolchainInfo = {}; if (developerPath) { plist = new PropertyList(); try { plist.readFromFile(platformInfoPlist); platformInfo = plist.toObject(); } finally { plist.clear(); } var additionalProps = platformInfo["AdditionalInfo"]; for (key in additionalProps) { // override infoPlist? if (additionalProps.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } props = platformInfo['OverrideProperties']; for (key in props) { aggregatePlist[key] = props[key]; } plist = new PropertyList(); try { plist.readFromFile(sdkSettingsPlist); sdkSettings = plist.toObject(); } finally { plist.clear(); } plist = new PropertyList(); try { plist.readFromFile(toolchainInfoPlist); toolchainInfo = plist.toObject(); } finally { plist.clear(); } } aggregatePlist["BuildMachineOSBuild"] = osBuildVersion; // setup env env = { "SDK_NAME": sdkSettings["CanonicalName"], "XCODE_VERSION_ACTUAL": toolchainInfo["DTXcode"], "SDK_PRODUCT_BUILD_VERSION": toolchainInfo["DTPlatformBuild"], "GCC_VERSION": platformInfo["DTCompiler"], "XCODE_PRODUCT_BUILD_VERSION": platformInfo["DTPlatformBuild"], "PLATFORM_PRODUCT_BUILD_VERSION": platformInfo["ProductBuildVersion"], } env["MAC_OS_X_PRODUCT_BUILD_VERSION"] = osBuildVersion; for (key in extraEnv) env[key] = extraEnv[key]; for (key in buildEnv) env[key] = buildEnv[key]; for (key in qmakeEnv) env[key] = qmakeEnv[key]; var expander = new DarwinTools.PropertyListVariableExpander(); expander.undefinedVariableFunction = function (key, varName) { var msg = "Info.plist variable expansion encountered undefined variable '" + varName + "' when expanding value for key '" + key + "', defined in one of the following files:\n\t"; var allFilePaths = []; for (i = 0; i < (inputs.infoplist || []).length; ++i) allFilePaths.push(inputs.infoplist[i].filePath); if (platformInfoPlist) allFilePaths.push(platformInfoPlist); msg += allFilePaths.join("\n\t") + "\n"; msg += "or in the bundle.infoPlist property of product '" + product.name + "'"; console.warn(msg); }; aggregatePlist = expander.expand(aggregatePlist, env); // Add keys from partial Info.plists from asset catalogs, XIBs, and storyboards. for (var j = 0; j < (inputs.partial_infoplist || []).length; ++j) { var partialInfoPlist = BundleTools.infoPlistContents( inputs.partial_infoplist[j].filePath) || {}; for (key in partialInfoPlist) { if (partialInfoPlist.hasOwnProperty(key) && aggregatePlist[key] === undefined) aggregatePlist[key] = partialInfoPlist[key]; } } } // Anything with an undefined or otherwise empty value should be removed // Only JSON-formatted plists can have null values, other formats error out // This also follows Xcode behavior DarwinTools.cleanPropertyList(aggregatePlist); if (infoPlistFormat === "same-as-input") infoPlistFormat = "xml1"; var validFormats = [ "xml1", "binary1", "json" ]; if (!validFormats.includes(infoPlistFormat)) throw("Invalid Info.plist format " + infoPlistFormat + ". " + "Must be in [xml1, binary1, json]."); // Write the plist contents in the format appropriate for the current platform plist = new PropertyList(); try { plist.readFromObject(aggregatePlist); plist.writeToFile(outputs.aggregate_infoplist[0].filePath, infoPlistFormat); } finally { plist.clear(); } } return cmd; } qbs-src-3.3.1/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec0000644000175100017510000005047115232633614024256 0ustar runnerrunner/** MacOSX Package Types.xcspec Copyright (c) 1999-2015 Apple Inc. All rights reserved. Package type specifications in the Mac OS X platform. */ ( // Mach-O executable { Type = PackageType; Identifier = com.apple.package-type.mach-o-executable; Name = "Mach-O Executable"; Description = "Mach-O executable"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; }; ProductReference = { FileType = compiled.mach-o.executable; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = YES; }; }, // Mach-O object file { Type = PackageType; Identifier = com.apple.package-type.mach-o-objfile; Name = "Mach-O Object File"; Description = "Mach-O Object File"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; }; ProductReference = { FileType = compiled.mach-o.objfile; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // Mach-O dynamic library { Type = PackageType; Identifier = com.apple.package-type.mach-o-dylib; Name = "Mach-O Dynamic Library"; Description = "Mach-O dynamic library"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; }; ProductReference = { FileType = compiled.mach-o.dylib; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // Static library ('ar' archive containing .o files) { Type = PackageType; Identifier = com.apple.package-type.static-library; Name = "Mach-O Static Library"; Description = "Mach-O static library"; DefaultBuildSettings = { EXECUTABLE_PREFIX = "lib"; EXECUTABLE_SUFFIX = ".a"; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; }; ProductReference = { FileType = archive.ar; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // Mach-O bundle (not related to a CFBundle) { Type = PackageType; Identifier = com.apple.package-type.mach-o-bundle; Name = "Mach-O Loadable"; Description = "Mach-O loadable"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ".dylib"; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; }; ProductReference = { FileType = compiled.mach-o.bundle; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // CFBundle wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper; Name = "Wrapper"; Description = "Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "BNDL"; WRAPPER_PREFIX = ""; WRAPPER_SUFFIX = ".bundle"; WRAPPER_NAME = "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)"; CONTENTS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))"; EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_FOLDER_PATH = "$(EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))"; EXECUTABLE_PATH = "$(EXECUTABLE_FOLDER_PATH)/$(EXECUTABLE_NAME)"; INFOPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/Info.plist"; INFOSTRINGS_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/InfoPlist.strings"; PKGINFO_PATH = "$(CONTENTS_FOLDER_PATH)/PkgInfo"; PBDEVELOPMENTPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/pbdevelopment.plist"; VERSIONPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/version.plist"; PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; PRIVATE_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/PrivateHeaders"; EXECUTABLES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Executables"; // Not the same as EXECUTABLE_FOLDER_PATH FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Frameworks"; SHARED_FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/SharedFrameworks"; SHARED_SUPPORT_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/SharedSupport"; UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))"; LOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/$(DEVELOPMENT_LANGUAGE).lproj"; DOCUMENTATION_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/Documentation"; MODULES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Modules"; PLUGINS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/PlugIns"; SCRIPTS_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Scripts"; JAVA_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Java"; SYSTEM_EXTENSIONS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Library/SystemExtensions"; // Settings specific to deep bundles (macOS) CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(WRAPPER_NAME)/Contents"; EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)/MacOS"; UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)/Resources"; // Settings specific to shallow bundles (iOS, DriverKit on any OS) CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(WRAPPER_NAME)"; EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(CONTENTS_FOLDER_PATH)"; UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(CONTENTS_FOLDER_PATH)"; // DriverKit should always use shallow bundles SHALLOW_BUNDLE = "$(SHALLOW_BUNDLE_$(SWIFT_PLATFORM_TARGET_PREFIX))"; SHALLOW_BUNDLE_ = YES; SHALLOW_BUNDLE_macos = NO; SHALLOW_BUNDLE_ios = NO; // for macCatalyst SHALLOW_BUNDLE_driverkit = YES; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Shallow CFBundle wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.shallow; BasedOn = com.apple.package-type.wrapper; Name = "Wrapper (Shallow)"; Description = "Shallow Wrapper"; DefaultBuildSettings = { SHALLOW_BUNDLE = YES; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Application wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.application; BasedOn = com.apple.package-type.wrapper; Name = "Application Wrapper"; Description = "Application Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "APPL"; GENERATE_PKGINFO_FILE = YES; }; ProductReference = { FileType = wrapper.application; Name = "$(WRAPPER_NAME)"; IsLaunchable = YES; }; }, // Shallow Application wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.application.shallow; BasedOn = com.apple.package-type.wrapper.shallow; Name = "Application Wrapper (Shallow)"; Description = "Shallow Application Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "APPL"; GENERATE_PKGINFO_FILE = YES; SHALLOW_BUNDLE = YES; }; ProductReference = { FileType = wrapper.application; Name = "$(WRAPPER_NAME)"; IsLaunchable = YES; }; }, // System extension wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.system-extension; BasedOn = com.apple.package-type.wrapper; Name = "System Extension Wrapper"; Description = "System Extension Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "SYSX"; }; ProductReference = { FileType = wrapper.system-extension; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Driver extension wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.driver-extension; BasedOn = com.apple.package-type.wrapper.system-extension; Name = "Driver Extension Wrapper"; Description = "Driver Extension Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "DEXT"; }; ProductReference = { FileType = wrapper.driver-extension; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Kernel extension wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.kernel-extension; BasedOn = com.apple.package-type.wrapper; Name = "Kernel Extension Wrapper"; Description = "Kernel Extension Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "KEXT"; PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)"; PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)"; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Shallow Kernel extension wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.kernel-extension.shallow; BasedOn = com.apple.package-type.wrapper.shallow; Name = "Kernel Extension Wrapper (Shallow)"; Description = "Shallow Kernel Extension Wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "KEXT"; PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)"; PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)"; SHALLOW_BUNDLE = YES; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Framework wrapper { Type = PackageType; Identifier = com.apple.package-type.wrapper.framework; BasedOn = com.apple.package-type.wrapper; Name = "Framework Wrapper"; Description = "Framework wrapper"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "FMWK"; WRAPPER_SUFFIX = ".framework"; VERSIONS_FOLDER_PATH = "$(VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))"; CURRENT_VERSION = "Current"; INFOPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Info.plist"; PKGINFO_PATH = "$(WRAPPER_NAME)/PkgInfo"; VERSIONPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/version.plist"; EXECUTABLES_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)"; // Not the same as EXECUTABLE_FOLDER_PATH SHARED_SUPPORT_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)"; CODESIGNING_FOLDER_PATH = "$(TARGET_BUILD_DIR)/$(CONTENTS_FOLDER_PATH)"; // Settings specific to deep bundles (macOS) VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(WRAPPER_NAME)/Versions"; CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(VERSIONS_FOLDER_PATH)/$(FRAMEWORK_VERSION)"; EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)"; // Settings specific to shallow bundles (iOS, DriverKit on any OS) VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(WRAPPER_NAME)"; }; ProductReference = { FileType = wrapper.framework; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Static framework wrapper (like a framework, except that it contains a libX.a instead of a dylib) { Type = PackageType; Identifier = com.apple.package-type.wrapper.framework.static; Name = "Mach-O Static Framework"; Description = "Mach-O static framework"; BasedOn = com.apple.package-type.wrapper.framework; DefaultBuildSettings = { }; ProductReference = { FileType = wrapper.framework.static; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Shallow Framework Package { Type = PackageType; Identifier = com.apple.package-type.wrapper.framework.shallow; Name = "Shallow Framework Wrapper"; Description = "Shallow framework wrapper"; BasedOn = com.apple.package-type.wrapper.framework; DefaultBuildSettings = { SHALLOW_BUNDLE = YES; }; ProductReference = { FileType = wrapper.framework; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Unit Test Bundle wrapper { Type = PackageType; Identifier = com.apple.package-type.bundle.unit-test; BasedOn = com.apple.package-type.wrapper; Name = "Unit Test Bundle"; Description = "Unit Test Bundle"; DefaultBuildSettings = { WRAPPER_SUFFIX = "xctest"; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Legacy OCUnit Test Bundle wrapper { Type = PackageType; Identifier = com.apple.package-type.bundle.ocunit-test; BasedOn = com.apple.package-type.wrapper; Name = "OCUnit Test Bundle"; Description = "OCUnit Test Bundle"; DefaultBuildSettings = { WRAPPER_SUFFIX = "octest"; }; ProductReference = { FileType = wrapper.cfbundle; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // In-app Purchase Content wrapper { Type = PackageType; Identifier = com.apple.package-type.in-app-purchase-content; BasedOn = com.apple.package-type.wrapper; Name = "In-App Purchase Content"; Description = "In-App Purchase Content"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = ""; WRAPPER_SUFFIX = ""; EXECUTABLE_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; INFOPLIST_PATH = "$(WRAPPER_NAME)/ContentInfo.plist"; INFOSTRINGS_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/ContentInfo.strings"; PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; PRIVATE_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; EXECUTABLES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; SHARED_FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; SHARED_SUPPORT_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; LOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/$(DEVELOPMENT_LANGUAGE).lproj"; DOCUMENTATION_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)"; MODULES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; PLUGINS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)"; SCRIPTS_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)"; JAVA_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)"; }; ProductReference = { FileType = folder; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // XPC Service wrapper { Type = PackageType; Identifier = com.apple.package-type.xpc-service; BasedOn = com.apple.package-type.wrapper; Name = "XPC Service"; Description = "XPC Service"; DefaultBuildSettings = { PRODUCT_BUNDLE_PACKAGE_TYPE = "XPC!"; WRAPPER_SUFFIX = ".xpc"; }; ProductReference = { FileType = wrapper.xpc-service; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // PlugInKit PlugIn wrapper { Type = PackageType; Identifier = com.apple.package-type.pluginkit-plugin; BasedOn = com.apple.package-type.xpc-service; Name = "PlugInKit PlugIn"; Description = "PlugInKit PlugIn"; DefaultBuildSettings = { WRAPPER_SUFFIX = ".pluginkit"; }; ProductReference = { FileType = wrapper.app-extension; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // App Extension wrapper { Type = PackageType; Identifier = com.apple.package-type.app-extension; BasedOn = com.apple.package-type.pluginkit-plugin; Name = "App Extension"; Description = "App Extension"; DefaultBuildSettings = { WRAPPER_SUFFIX = ".appex"; }; ProductReference = { FileType = wrapper.app-extension; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Spotlight Importer wrapper { Type = PackageType; Identifier = com.apple.package-type.spotlight-importer; BasedOn = com.apple.package-type.wrapper; Name = "Spotlight Importer"; Description = "Spotlight Importer"; DefaultBuildSettings = { }; ProductReference = { FileType = wrapper.spotlight-importer; Name = "$(WRAPPER_NAME)"; IsLaunchable = NO; }; }, // Jar file { Type = PackageType; Identifier = com.apple.package-type.jarfile; Name = "Jar File"; Description = "Jar file"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ".jar"; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; JAVA_ARCHIVE_CLASSES = YES; JAVA_MAKE_ZIPFILE = NO; }; ProductReference = { FileType = archive.jar; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // Zip file { Type = PackageType; Identifier = com.apple.package-type.zipfile; Name = "Zip File"; Description = "Zip file"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ".zip"; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; JAVA_ARCHIVE_CLASSES = YES; JAVA_MAKE_ZIPFILE = YES; }; ProductReference = { FileType = archive.zip; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, // Java class folder { Type = PackageType; Identifier = com.apple.package-type.javaclassfolder; Name = "Class Folder"; Description = "Class folder"; DefaultBuildSettings = { EXECUTABLE_PREFIX = ""; EXECUTABLE_SUFFIX = ""; EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"; EXECUTABLE_PATH = "$(EXECUTABLE_NAME)"; JAVA_ARCHIVE_CLASSES = NO; }; ProductReference = { FileType = wrapper.java-classfolder; Name = "$(EXECUTABLE_NAME)"; IsLaunchable = NO; }; }, ) qbs-src-3.3.1/share/qbs/modules/qbs/0000755000175100017510000000000015232633614016627 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/qbs/common.qbs0000644000175100017510000002444515232633614020637 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Utilities Module { readonly property string configurationName: "default" property string defaultBuildVariant: { switch (configurationName.toLowerCase()) { case "release": return "release"; case "profiling": return "profiling"; default: return "debug"; } } property string buildVariant: defaultBuildVariant property bool enableDebugCode: buildVariant == "debug" property bool debugInformation: (buildVariant !== "release") property string optimization: (buildVariant === "debug" ? "none" : "fast") readonly property string hostPlatform: undefined // set internally readonly property stringList hostOS: Utilities.canonicalPlatform(hostPlatform) property string hostOSVersion: { if (hostOS && hostOS.includes("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductVersion") || Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductVersion"); } else if (hostOS && hostOS.includes("windows")) { var version = Utilities.getNativeSetting(windowsRegistryKey, "CurrentVersion"); return version + "." + hostOSBuildVersion; } } readonly property string hostArchitecture: undefined // set internally property string hostOSBuildVersion: { if (hostOS.includes("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductBuildVersion") || Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductBuildVersion"); } else if (hostOS.includes("windows")) { return Utilities.getNativeSetting(windowsRegistryKey, "CurrentBuildNumber"); } } readonly property var hostOSVersionParts: hostOSVersion ? hostOSVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] readonly property int hostOSVersionMajor: hostOSVersionParts[0] || 0 readonly property int hostOSVersionMinor: hostOSVersionParts[1] || 0 readonly property int hostOSVersionPatch: hostOSVersionParts[2] || 0 property string targetPlatform: hostPlatform readonly property stringList targetOS: Utilities.canonicalPlatform(targetPlatform) property string pathListSeparator: hostOS.includes("windows") ? ";" : ":" property string pathSeparator: hostOS.includes("windows") ? "\\" : "/" property string nullDevice: hostOS.includes("windows") ? "NUL" : "/dev/null" property path shellPath: hostOS.includes("windows") ? windowsShellPath : "/bin/sh" property string profile: project.profile property string toolchainType: { if (targetOS.includes("windows")) return hostOS.includes("windows") ? "msvc" : "mingw"; if (targetOS.includes("darwin")) return hostOS.includes("macos") ? "xcode" : "clang"; if (targetOS.includes("freebsd")) return "clang"; if (targetOS.includes("qnx")) return "qcc"; if (targetOS.containsAny(["haiku", "vxworks", "unix"])) return "gcc"; } readonly property stringList toolchain: Utilities.canonicalToolchain(toolchainType) property string architecture property bool install: false property path installSourceBase property string installRoot: project.buildDirectory + "/install-root" property string installDir property string installPrefix: targetOS.includes("unix") ? "/usr/local" : "" property path sysroot PropertyOptions { name: "buildVariant" allowedValues: ['debug', 'release', 'profiling'] description: "name of the build variant" } PropertyOptions { name: "optimization" allowedValues: ['none', 'fast', 'small'] description: "optimization level" } validate: { var validator = new ModUtils.PropertyValidator("qbs"); validator.setRequiredProperty("hostOS", hostOS); validator.setRequiredProperty("targetOS", targetOS); validator.addCustomValidator("targetOS", targetOS, function (value) { if (!value || (value.includes("osx") && !value.includes("macos"))) return false; return true; }, "the value 'osx' has been replaced by 'macos'; use that instead and update " + "hostOS and targetOS condition checks in your project accordingly"); if (hostOS && (hostOS.includes("windows") || hostOS.includes("macos"))) { validator.setRequiredProperty("hostOSVersion", hostOSVersion, "could not detect host operating system version; " + "verify that system files and registry keys have not " + "been modified."); if (hostOSVersion) validator.addVersionValidator("hostOSVersion", hostOSVersion, 2, 4); validator.setRequiredProperty("hostOSBuildVersion", hostOSBuildVersion, "could not detect host operating system build version; " + "verify that system files or registry have not been " + "tampered with."); } validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === Utilities.canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid." + (architecture ? " You must use the canonical name '" + Utilities.canonicalArchitecture(architecture) : "") + "'"); validator.addCustomValidator("toolchain", toolchain, function (value) { if (toolchain === undefined) return false; // cannot have null toolchain, empty is valid... for now var canonical = Utilities.canonicalToolchain.apply(Utilities, toolchain); for (var i = 0; i < Math.max(canonical.length, toolchain.length); ++i) { if (canonical[i] !== toolchain[i]) return false; } return true; }, "'" + toolchain + "' is invalid. You must use the canonical list '" + Utilities.canonicalToolchain.apply(Utilities, toolchain) + "'"); validator.addCustomValidator("toolchain", toolchain, function (value) { // None of the pairs listed here may appear in the same toolchain list. // Note that this check is applied AFTER canonicalization, so for example // {"clang", "msvc"} need not be checked, since a toolchain containing clang is // guaranteed to also contain gcc. var pairs = [ ["gcc", "msvc"], ["llvm", "mingw"] ]; var canonical = Utilities.canonicalToolchain.apply(Utilities, value); for (var i = 0; i < pairs.length; ++i) { if (canonical.includes(pairs[i][0]) && canonical.includes(pairs[i][1])) return false; } return true; }, "'" + toolchain + "' contains one or more mutually exclusive toolchain types."); validator.validate(); } // private properties property string windowsRegistryKey: "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion" property path windowsSystemRoot: FileInfo.fromWindowsSeparators(Utilities.getNativeSetting(windowsRegistryKey, "SystemRoot")) property path windowsShellPath: FileInfo.fromWindowsSeparators(Environment.getEnv("COMSPEC")) || FileInfo.joinPaths(windowsSystemRoot, "System32", "cmd.exe") property string windowsPathVariable: hostOS.includes("windows") ? "PATH" : "WINEPATH" property var commonRunEnvironment: ({}) setupRunEnvironment: { var env = product.qbs.commonRunEnvironment; for (var i in env) { var v = new ModUtils.EnvironmentVariable(i, product.qbs.pathListSeparator, product.qbs.hostOS.includes("windows")); v.value = env[i]; v.set(); } } // Properties that can be set for multiplexing products. property stringList profiles: [] property stringList architectures: [] property stringList buildVariants: [] // internal properties readonly property string version: [versionMajor, versionMinor, versionPatch].join(".") readonly property int versionMajor: undefined // set internally readonly property int versionMinor: undefined // set internally readonly property int versionPatch: undefined // set internally readonly property var multiplexMap: ({ profiles: "profile", architectures: "architecture", buildVariants: "buildVariant" }) } qbs-src-3.3.1/share/qbs/modules/ico/0000755000175100017510000000000015232633614016614 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/ico/IcoModule.qbs0000644000175100017510000000462615232633614021213 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import qbs.Utilities import "ico.js" as IcoUtils Module { Probes.BinaryProbe { id: icotoolProbe names: ["icotool"] } Probes.IcoUtilsVersionProbe { id: icotoolVersionProbe toolFilePath: icotoolFilePath } version: icotoolVersionProbe.version property int alphaThreshold property int cursorHotspotX property int cursorHotspotY property bool raw // private properties property string icotoolFilePath: icotoolProbe.filePath readonly property bool hasCursorHotspotBug: Utilities.versionCompare(version, "0.32") < 0 FileTagger { patterns: ["*.png"] fileTags: ["png"] } FileTagger { patterns: ["*.iconset"] // bundle fileTags: ["iconset"] } Rule { inputs: ["iconset"] Artifact { filePath: input.baseName + ".ico" fileTags: ["ico"] } prepare: IcoUtils.prepareIconset.apply(IcoUtils, arguments) } Rule { multiplex: true inputs: ["png"] Artifact { filePath: product.targetName + ".ico" fileTags: ["ico"] } prepare: IcoUtils.prepare.apply(IcoUtils, arguments) } Rule { inputs: ["iconset"] Artifact { filePath: input.baseName + ".cur" fileTags: ["cur"] } prepare: IcoUtils.prepareIconset.apply(IcoUtils, arguments) } Rule { multiplex: true inputs: ["png"] Artifact { filePath: product.targetName + ".cur" fileTags: ["cur"] } prepare: IcoUtils.prepare.apply(IcoUtils, arguments) } validate: { if (!icotoolFilePath) throw ModUtils.ModuleError("Could not find icotool in any of the following " + "locations:\n\t" + icotoolProbe.candidatePaths.join("\n\t") + "\nInstall the icoutils package on your platform."); if (!version) throw ModUtils.ModuleError("Could not determine icoutils package version."); var validator = new ModUtils.PropertyValidator("ico"); validator.setRequiredProperty("version", version); validator.addVersionValidator("version", version, 2, 3); return validator.validate() } } qbs-src-3.3.1/share/qbs/modules/ico/ico.js0000644000175100017510000000773715232633614017742 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); function prepareIconset(project, product, inputs, outputs, input, output) { inputs = File.directoryEntries(input.filePath, File.Files).map(function (p) { return { filePath: FileInfo.joinPaths(input.filePath, p), fileTags: p.endsWith(".png") ? ["png"] : [], ico: {} }; }); inputs = {"png": inputs.filter(function (a) { return a.fileTags.includes("png"); })}; input = undefined; return prepare(project, product, inputs, outputs, input, output); } function prepare(project, product, inputs, outputs, input, output) { var args = ["--create", "--output=" + output.filePath]; if (output.fileTags.includes("ico")) { args.push("--icon"); if (product.ico.alphaThreshold !== undefined) args.push("--alpha-threshold=" + product.ico.alphaThreshold); } var isCursor = output.fileTags.includes("cur"); if (isCursor) args.push("--cursor"); var hasMultipleImages = inputs["png"].length > 1; inputs["png"].map(function(inp) { if (isCursor) { var hasX = inp.ico.cursorHotspotX !== undefined; var hasY = inp.ico.cursorHotspotY !== undefined; if (hasX || hasY) { if (hasMultipleImages && product.ico.hasCursorHotspotBug) { console.warn("icotool " + product.ico.version + " does not support setting " + "the hotspot for cursor files with multiple images. Install " + "icoutils 0.32.0 or newer to use this feature."); } else { if (hasX) args.push("--hotspot-x=" + inp.ico.cursorHotspotX); if (hasY) args.push("--hotspot-y=" + inp.ico.cursorHotspotY); } } } if (inp.ico.raw) args.push("-r"); args.push(inp.filePath); }); var cmd = new Command(product.ico.icotoolFilePath, args); cmd.description = "creating " + output.fileName; return [cmd]; } function findIcoUtilsVersion(toolFilePath) { var p = new Process(); try { p.exec(toolFilePath, ["--version"]); var re = /^[a-z]+ \(icoutils\) ([0-9]+(?:\.[0-9]+){1,2})$/m; var match = p.readStdOut().trim().match(re); if (match !== null) return match[1]; } finally { p.close(); } } qbs-src-3.3.1/share/qbs/modules/cpufeatures/0000755000175100017510000000000015232633614020370 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/cpufeatures/cpufeatures.qbs0000644000175100017510000000116015232633614023423 0ustar runnerrunnerModule { property bool arm_neon property bool arm_vfpv4 property bool mips_dsp property bool mips_dspr2 property bool x86_avx property bool x86_avx2 property bool x86_avx512bw property bool x86_avx512cd property bool x86_avx512dq property bool x86_avx512er property bool x86_avx512f property bool x86_avx512ifma property bool x86_avx512pf property bool x86_avx512vbmi property bool x86_avx512vl property bool x86_f16c property bool x86_sse2 property bool x86_sse3 property bool x86_sse4_1 property bool x86_sse4_2 property bool x86_ssse3 } qbs-src-3.3.1/share/qbs/modules/xcode/0000755000175100017510000000000015232633614017144 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/xcode/xcode.js0000644000175100017510000002602215232633614020606 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var DarwinTools = require("qbs.DarwinTools"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var PropertyList = require("qbs.PropertyList"); var Utilities = require("qbs.Utilities"); var XcodeArchSpecsReader = (function () { function XcodeArchSpecsReader(specsPath) { var plist = new PropertyList(); try { plist.readFromFile(specsPath); this.specsObject = plist.toObject(); } finally { plist.clear(); } } XcodeArchSpecsReader.prototype.getArchitectureSettings = function () { if (this.specsObject) { var names = []; for (var i = 0; i < this.specsObject.length; ++i) { var dict = this.specsObject[i]; var name = dict["ArchitectureSetting"]; if (name) names.push(name); } return names; } }; XcodeArchSpecsReader.prototype.getArchitectureSettingValue = function (settingName) { // settingName can be: ARCHS_STANDARD, ARCHS_STANDARD_32_BIT, ARCHS_STANDARD_64_BIT, // ARCHS_STANDARD_32_64_BIT, ARCHS_STANDARD_INCLUDING_64_BIT, or ARCHS_UNIVERSAL_IPHONE_OS. // NATIVE_ARCH_ACTUAL doesn't have a RealArchitectures property since it's determined by // Xcode programmatically. if (this.specsObject) { for (var i = 0; i < this.specsObject.length; ++i) { var dict = this.specsObject[i]; if (dict["ArchitectureSetting"] === settingName) { var realArchs = dict["RealArchitectures"]; if (realArchs) { var effectiveRealArchs = []; for (var j = 0; j < realArchs.length; ++j) { var re = /^\$\(([A-Za-z0-9_]+)\)$/; var match = realArchs[j].match(re); if (match) { var val = this.getArchitectureSettingValue(match[1]); // Don't silently omit values if missing. For example, if // ARCHS_FOO=[x86_64, $(ARCHS_BAR)], return 'undefined' instead of // simply [x86_64]. Not known to have any real world occurrences. if (!val) return undefined; Array.prototype.push.apply(effectiveRealArchs, val); } else { effectiveRealArchs.push(realArchs[j]); } } return effectiveRealArchs; } } } } }; return XcodeArchSpecsReader; }()); function platformInfo(platformInfoPlist) { var propertyList = new PropertyList(); try { propertyList.readFromFile(platformInfoPlist); return propertyList.toObject(); } finally { propertyList.clear(); } } function sdkInfoList(sdksPath) { var sdkInfo = []; var sdks = File.directoryEntries(sdksPath, File.Dirs | File.NoDotAndDotDot); for (var i in sdks) { // SDK directory name must contain a version number; // we don't want the versionless iPhoneOS.sdk directory for example if (!sdks[i].match(/[0-9]+/)) continue; if (sdks[i].startsWith("DriverKit") || sdks[i].startsWith("AssetRuntime")) continue; var settingsPlist = FileInfo.joinPaths(sdksPath, sdks[i], "SDKSettings.plist"); var propertyList = new PropertyList(); try { propertyList.readFromFile(settingsPlist); function checkPlist(plist) { if (!plist || !plist["CanonicalName"] || !plist["Version"]) return false; var re = /^[0-9]+\.[0-9]+(\.[0-9]+)?$/; return plist["Version"].match(re); } var plist = propertyList.toObject(); if (!checkPlist(plist)) { console.warn("Skipping corrupted SDK installation: " + FileInfo.joinPaths(sdksPath, sdks[i])); continue; } sdkInfo.push(plist); } finally { propertyList.clear(); } } // Sort by SDK version number sdkInfo.sort(function (a, b) { return Utilities.versionCompare(a["Version"], b["Version"]); }); return sdkInfo; } function findSigningIdentities(security, searchString) { var process; var identities; if (searchString) { try { process = new Process(); if (process.exec(security, ["find-identity", "-p", "codesigning", "-v"], true) !== 0) console.error(process.readStdErr()); var lines = process.readStdOut().split("\n"); for (var i in lines) { // e.g. 1) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "Mac Developer: John Doe (XXXXXXXXXX) john.doe@example.org" var match = lines[i].match(/^\s*[0-9]+\)\s+([A-Fa-f0-9]{40})\s+"([^"]+)"$/); if (match !== null) { var hexId = match[1]; var displayName = match[2]; if (hexId === searchString || displayName.startsWith(searchString)) { if (!identities) identities = []; identities.push([hexId, displayName]); break; } } } } finally { process.close(); } } return identities; } function provisioningProfilePlistContents(filePath) { if (filePath === undefined || !File.exists(filePath)) return undefined; var plist = new PropertyList(); try { plist.readFromFile(filePath); return plist.toObject(); } finally { plist.clear(); } } function boolFromSdkOrPlatform(varName, sdkProps, platformProps, defaultValue) { var values = [(sdkProps || {})[varName], (platformProps || {})[varName]]; for (var i = 0; i < values.length; ++i) { if (values[i] === "YES") return true; if (values[i] === "NO") return false; } return defaultValue; } function specsBaseName(version, targetOS) { const targetPlatform = targetOS[0]; const oldSpecNames = { "macos": "MacOSX Architectures", "ios": "iOS Device", "ios-simulator": "iOS Simulator", "tvos": "tvOS Device", "tvos-simulator": "tvOS Simulator", "watchos": "watchOS Device", "watchos-simulator": "watchOS Simulator" }; const newSpecNames = { "macos": "macOSArchitectures", "ios": "iOSDevice", "ios-simulator": "iOSSimulator", "tvos": "tvOSDevice", "tvos-simulator": "tvOSSimulator", "watchos": "watchOSDevice", "watchos-simulator": "watchOSSimulator" }; if (Utilities.versionCompare(version, "26") < 0) { return oldSpecNames[targetPlatform]; } return newSpecNames[targetPlatform]; } function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath, developerPath) { if (Utilities.versionCompare(version, "13.3") >= 0) { var pluginsDir; if (Utilities.versionCompare(version, "15.3") >= 0) { pluginsDir = FileInfo.joinPaths(developerPath, "..", "SharedFrameworks", "XCBuild.framework", "PlugIns", "XCBBuildService.bundle", "Contents", "PlugIns"); } else if (Utilities.versionCompare(version, "14.3") >= 0) { pluginsDir = FileInfo.joinPaths(developerPath, "Library", "Xcode", "Plug-ins"); } else { pluginsDir = FileInfo.joinPaths(developerPath, "..", "PlugIns"); } var baseDir = FileInfo.joinPaths(pluginsDir, "XCBSpecifications.ideplugin", "Contents", "Resources"); return FileInfo.joinPaths(baseDir, specsBaseName(version, targetOS) + ".xcspec"); } var _specsPluginBaseName; if (Utilities.versionCompare(version, "12") >= 0) { if (targetOS.includes("macos")) _specsPluginBaseName = "OSX"; } if (Utilities.versionCompare(version, "7") >= 0) { if (targetOS.includes("ios")) _specsPluginBaseName = "iOSPlatform"; if (targetOS.includes("tvos")) _specsPluginBaseName = "AppleTV"; if (targetOS.includes("watchos")) _specsPluginBaseName = "Watch"; } var _archSpecsDir = _specsPluginBaseName ? FileInfo.joinPaths(devicePlatformPath, "Developer", "Library", "Xcode", "PrivatePlugIns", "IDE" + _specsPluginBaseName + "SupportCore.ideplugin", "Contents", "Resources") : FileInfo.joinPaths(platformPath, "Developer", "Library", "Xcode", "Specifications"); var _archSpecsFileBaseName = targetOS.includes("ios") ? (targetOS.includes("ios-simulator") ? "iPhone Simulator " : "iPhoneOS") : DarwinTools.applePlatformDirectoryName(targetOS, platformType) + " "; if (_specsPluginBaseName) { switch (platformType) { case "device": return FileInfo.joinPaths(_archSpecsDir, "Device.xcspec"); case "simulator": return FileInfo.joinPaths(_archSpecsDir, "Simulator.xcspec"); } } return FileInfo.joinPaths(_archSpecsDir, _archSpecsFileBaseName + "Architectures.xcspec"); } qbs-src-3.3.1/share/qbs/modules/xcode/xcode.qbs0000644000175100017510000002020515232633614020754 0ustar runnerrunnerimport qbs.BundleTools import qbs.Environment import qbs.File import qbs.FileInfo import qbs.DarwinTools import qbs.ModUtils import qbs.Probes import qbs.PropertyList import qbs.Utilities Module { Probes.XcodeLocationProbe { id: xcodeLocationProbe condition: !developerPath } Probes.XcodeProbe { id: xcodeProbe developerPath: parent.developerPath platformType: parent.platformType platformPath: parent.platformPath devicePlatformPath: parent.devicePlatformPath xcodebuildPath: parent.xcodebuildPath sdksPath: parent.sdksPath } condition: qbs.targetOS.includes("darwin") && qbs.toolchain && qbs.toolchain.includes("xcode") version: xcodeProbe.xcodeVersion property path developerPath: xcodeLocationProbe.found ? xcodeLocationProbe.developerPath : undefined property string sdk: DarwinTools.applePlatformName(qbs.targetOS, platformType) property stringList targetDevices: DarwinTools.targetDevices(qbs.targetOS) property string platformType: { if (qbs.targetOS.containsAny(["ios-simulator", "tvos-simulator", "watchos-simulator"])) return "simulator"; if (qbs.targetOS.containsAny(["ios", "tvos", "watchos"])) return "device"; } readonly property string sdkName: { if (_sdkSettings) { return _sdkSettings["CanonicalName"]; } } readonly property string sdkVersion: { if (_sdkSettings) { return _sdkSettings["Version"]; } } readonly property string shortSdkVersion: { var v = sdkVersion; if (v && v.split('.').length > 2) v = v.slice(0, v.lastIndexOf('.')); return v; } readonly property string latestSdkName: { if (_latestSdk) { return _latestSdk["CanonicalName"]; } } readonly property string latestSdkVersion: { if (_latestSdk) { return _latestSdk["Version"]; } } readonly property stringList availableSdkNames: { if (_availableSdks) { return _availableSdks.map(function (obj) { return obj["CanonicalName"]; }); } } readonly property stringList availableSdkVersions: { if (_availableSdks) { return _availableSdks.map(function (obj) { return obj["Version"]; }); } } readonly property path toolchainPath: FileInfo.joinPaths(toolchainsPath, "XcodeDefault" + ".xctoolchain") readonly property path platformPath: FileInfo.joinPaths(platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType) + ".platform") readonly property path devicePlatformPath: FileInfo.joinPaths( platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, "device") + ".platform") readonly property path simulatorPlatformPath: FileInfo.joinPaths( platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, "simulator") + ".platform") readonly property path sdkPath: FileInfo.joinPaths(sdksPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType, shortSdkVersion) + ".sdk") // private properties readonly property path toolchainsPath: FileInfo.joinPaths(developerPath, "Toolchains") readonly property path platformsPath: FileInfo.joinPaths(developerPath, "Platforms") readonly property path sdksPath: FileInfo.joinPaths(platformPath, "Developer", "SDKs") readonly property path platformInfoPlist: FileInfo.joinPaths(platformPath, "Info.plist") readonly property path sdkSettingsPlist: FileInfo.joinPaths(sdkPath, "SDKSettings.plist") readonly property path toolchainInfoPlist: FileInfo.joinPaths(toolchainPath, "ToolchainInfo.plist") readonly property var _platformSettings: xcodeProbe.platformSettings readonly property var _platformProps: { if (_platformSettings) return _platformSettings["DefaultProperties"]; } readonly property stringList standardArchitectures: _architectureSettings["ARCHS_STANDARD"] readonly property var _architectureSettings: xcodeProbe.architectureSettings readonly property var _availableSdks: xcodeProbe.availableSdks readonly property var _latestSdk: _availableSdks[_availableSdks.length - 1] readonly property var _sdkSettings: { if (_availableSdks) { // see 'sdk' property doc to understand why this loop is needed for (var i in _availableSdks) { if (_availableSdks[i]["Version"] === sdk) return _availableSdks[i]; if (_availableSdks[i]["CanonicalName"] === sdk) return _availableSdks[i]; } // Latest SDK available for the platform (default case) if (DarwinTools.applePlatformName(qbs.targetOS, platformType) === sdk) return _latestSdk; } } readonly property var _sdkProps: { if (_sdkSettings) { return _sdkSettings["DefaultProperties"]; } } qbs.sysroot: sdkPath validate: { if (!_availableSdks) { throw "There are no SDKs available for this platform in the Xcode installation."; } if (!_sdkSettings) { throw "There is no matching SDK available for " + sdk + "."; } var validator = new ModUtils.PropertyValidator("xcode"); validator.setRequiredProperty("developerPath", developerPath); validator.setRequiredProperty("sdk", sdk); validator.setRequiredProperty("sdkName", sdkName); validator.setRequiredProperty("sdkVersion", sdkVersion); validator.setRequiredProperty("toolchainsPath", toolchainsPath); validator.setRequiredProperty("toolchainPath", toolchainPath); validator.setRequiredProperty("platformsPath", platformsPath); validator.setRequiredProperty("platformPath", platformPath); validator.setRequiredProperty("sdksPath", sdkPath); validator.setRequiredProperty("sdkPath", sdkPath); validator.addVersionValidator("sdkVersion", sdkVersion, 2, 3); validator.addCustomValidator("sdkName", sdkName, function (value) { return value === DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType, shortSdkVersion, false).toLowerCase(); }, "is '" + sdkName + "', but target OS is [" + qbs.targetOS.join(",") + "] and Xcode SDK version is '" + sdkVersion + "'"); validator.addCustomValidator("sdk", sdk, function (value) { return value === sdkName || (value + shortSdkVersion) === sdkName; }, "is '" + sdk + "', but canonical SDK name is '" + sdkName + "'"); validator.validate(); } property var buildEnv: ({ "DEVELOPER_DIR": developerPath, "SDKROOT": sdkPath }) setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), false); v.prepend(product.xcode.platformPath + "/Developer/usr/bin"); v.prepend(product.xcode.developerPath + "/usr/bin"); v.set(); for (var key in product.xcode.buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = product.xcode.buildEnv[key]; v.set(); } } } qbs-src-3.3.1/share/qbs/modules/autotest/0000755000175100017510000000000015232633614017712 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/autotest/autotest.qbs0000644000175100017510000000021315232633614022265 0ustar runnerrunnerModule { property stringList arguments property bool allowFailure: false property string workingDir property int timeout } qbs-src-3.3.1/share/qbs/modules/config/0000755000175100017510000000000015232633614017307 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/config/install/0000755000175100017510000000000015232633614020755 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/config/install/module.qbs0000644000175100017510000000002215232633614022743 0ustar runnerrunnerConfigInstall { } qbs-src-3.3.1/share/qbs/modules/config/build/0000755000175100017510000000000015232633614020406 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/config/build/module.qbs0000644000175100017510000000002015232633614022372 0ustar runnerrunnerConfigBuild { } qbs-src-3.3.1/share/qbs/modules/vcs/0000755000175100017510000000000015232633614016635 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/vcs/vcs-module.qbs0000644000175100017510000002253515232633614021431 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Process import qbs.TextFile import qbs.Utilities Module { property string type: typeProbe.type property string repoDir: project.sourceDirectory property string toolFilePath: { if (type === "git") return "git"; if (type === "svn") return "svn"; if (type === "hg") return "hg"; } property string headerFileName: "vcs-repo-state.h" readonly property string repoState: gitProbe.repoState || subversionProbe.repoState || mercurialProbe.repoState readonly property string repoLatestTag: gitProbe.repoLatestTag || subversionProbe.repoLatestTag || mercurialProbe.repoLatestTag readonly property string repoCommitsSinceTag: gitProbe.repoCommitsSinceTag || subversionProbe.repoCommitsSinceTag || mercurialProbe.repoCommitsSinceTag readonly property string repoCommitSha: gitProbe.repoCommitSha || subversionProbe.repoCommitSha || mercurialProbe.repoCommitSha // Internal readonly property string includeDir: FileInfo.joinPaths(product.buildDirectory, "vcs-include") readonly property string metaDataBaseDir: typeProbe.metaDataBaseDir PropertyOptions { name: "type" allowedValues: ["git", "svn", "hg"] description: "the version control system your project is using" } Group { condition: headerFileName Depends { name: "cpp" } product.cpp.includePaths: [includeDir] Rule { multiplex: true Artifact { filePath: FileInfo.joinPaths(product.vcs.includeDir, product.vcs.headerFileName) fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.repoState = product.vcs.repoState; cmd.repoLatestTag = product.vcs.repoLatestTag; cmd.repoCommitsSinceTag = product.vcs.repoCommitsSinceTag; cmd.repoCommitSha = product.vcs.repoCommitSha; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); try { f.writeLine("#ifndef VCS_REPO_STATE_H"); f.writeLine("#define VCS_REPO_STATE_H"); f.writeLine('#define VCS_REPO_STATE "' + (repoState ? repoState : "none") + '"') f.writeLine('#define VCS_REPO_LATEST_TAG "' + (repoLatestTag ? repoLatestTag : "none") + '"') f.writeLine('#define VCS_REPO_COMMITS_SINCE_TAG "' + (repoCommitsSinceTag ? repoCommitsSinceTag : "none") + '"') f.writeLine('#define VCS_REPO_COMMIT_SHA "' + (repoCommitSha ? repoCommitSha : "none") + '"') f.writeLine("#endif"); } finally { f.close(); } }; return [cmd]; } } } Probe { id: typeProbe property string tool: toolFilePath property string theRepoDir: repoDir property string type property string metaDataBaseDir configure: { var detector = new Process(); try { detector.setWorkingDirectory(theRepoDir); if (detector.exec(tool || "git", ["rev-parse", "--git-dir"]) === 0) { found = true; type = "git"; metaDataBaseDir = detector.readStdOut().trim(); if (!FileInfo.isAbsolutePath(metaDataBaseDir)) metaDataBaseDir = FileInfo.joinPaths(theRepoDir, metaDataBaseDir); return; } if (detector.exec(tool || "svn", ["info", "--show-item", "wc-root", "--no-newline"]) === 0) { found = true type = "svn"; metaDataBaseDir = FileInfo.joinPaths(detector.readStdOut(), ".svn"); return; } else if (detector.exec(tool || "svn", ["info"]) === 0) { if (detector.exec(tool || "svn", ["--version", "--quiet"]) === 0 && Utilities.versionCompare(detector.readStdOut().trim(), "1.9") < 0) { throw "svn too old, version >= 1.9 required"; } } else if (detector.exec(tool || "hg", ["root"]) === 0) { found = true; type = "hg"; var hgRoot = detector.readStdOut().trim(); metaDataBaseDir = FileInfo.joinPaths(hgRoot, ".hg"); return; } } finally { detector.close(); } } } Probe { id: gitProbe condition: type === "git" property string tool: toolFilePath property string theRepoDir: repoDir property string filePath: FileInfo.joinPaths(metaDataBaseDir, "logs/HEAD") property var timestamp: File.lastModified(filePath) property string repoState property string repoLatestTag property string repoCommitsSinceTag property string repoCommitSha configure: { if (!File.exists(filePath)) { // it is possible that the HEAD file is not present in CI environments, in this // case we can use the commit count to determine the repo state // see https://bugreports.qt.io/projects/QBS/issues/QBS-1814 try { var proc = new Process(); proc.setWorkingDirectory(theRepoDir); proc.exec(tool, ["rev-list", "HEAD", "--count"], true); } catch (e) { return; // No commits yet. } finally { proc.close(); } } try { var proc = new Process(); proc.setWorkingDirectory(theRepoDir); proc.exec(tool, ["describe", "--always", "--long", "HEAD"], true); repoState = proc.readStdOut().trim(); if (repoState) { found = true; // tag is formatted as TAG-N-gSHA: // 1. latest tag is TAG // 2. number of commits since latest TAG is N // 3. latest commit is gSHA const tagSections = repoState.split("-").reverse(); if (tagSections.length >= 3) { repoCommitSha = tagSections[0]; repoCommitsSinceTag = tagSections[1]; repoLatestTag = tagSections.slice(2).reverse().join("-"); // Handle tags with dashes } else { repoCommitSha = "g" + tagSections[0]; } } } finally { proc.close(); } } } Probe { id: subversionProbe condition: type === "svn" property string tool: toolFilePath property string theRepoDir: repoDir property string filePath: FileInfo.joinPaths(metaDataBaseDir, "wc.db") property var timestamp: File.lastModified(filePath) property string repoState property string repoLatestTag property string repoCommitsSinceTag property string repoCommitSha configure: { var proc = new Process(); try { proc.setWorkingDirectory(theRepoDir); proc.exec(tool, ["info", "-r", "HEAD", "--show-item", "revision", "--no-newline"], true); repoState = proc.readStdOut().trim(); if (repoState) found = true; } finally { proc.close(); } } } Probe { id: mercurialProbe condition: type === "hg" property string tool: toolFilePath property string theRepoDir: repoDir property string filePath: FileInfo.joinPaths(metaDataBaseDir, "dirstate") property var timestamp: File.lastModified(filePath) property string repoState property string repoLatestTag property string repoCommitsSinceTag property string repoCommitSha configure: { if (!File.exists(filePath)) return; var proc = new Process(); try { proc.setWorkingDirectory(theRepoDir); var template = "{latesttag}-{latesttagdistance}-m{node|short}"; if (proc.exec(tool || "hg", ["log", "-r", ".", "--template", template]) === 0) { repoState = proc.readStdOut().trim(); found = true; // Parse output: TAG-N-mSHA const tagSections = repoState.split("-").reverse(); if (tagSections.length >= 3) { repoCommitSha = tagSections[0]; repoCommitsSinceTag = tagSections[1]; repoLatestTag = tagSections.slice(2).reverse().join("-"); // Handle tags with dashes } } } finally { proc.close(); } } } } qbs-src-3.3.1/share/qbs/modules/java/0000755000175100017510000000000015232633614016763 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/JavaModule.qbs0000644000175100017510000003364315232633614021532 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Probes import qbs.Process import qbs.TextFile import qbs.Utilities import "utils.js" as JavaUtils Module { Probes.JdkProbe { id: jdk environmentPaths: (jdkPath ? [jdkPath] : []).concat(base) } Probes.JdkVersionProbe { id: jdkVersionProbe javac: compilerFilePath } property stringList additionalClassPaths property stringList additionalCompilerFlags property stringList additionalJarFlags property stringList bootClassPaths property string compilerFilePath: FileInfo.joinPaths(jdkPath, "bin", compilerName) property string compilerName: "javac" property bool enableWarnings: true property string interpreterFilePath : FileInfo.joinPaths(jdkPath, "bin", interpreterName) property string interpreterName: "java" property string jarFilePath: FileInfo.joinPaths(jdkPath, "bin", jarName) property string jarName: "jar" property string jarsignerFilePath: FileInfo.joinPaths(jdkPath, "bin", jarsignerName) property string jarsignerName: "jarsigner" property string keytoolFilePath: FileInfo.joinPaths(jdkPath, "bin", keytoolName) property string keytoolName: "keytool" property bool _tagJniHeaders: true property string jdkPath: jdk.path version: [compilerVersionMajor, compilerVersionMinor, compilerVersionPatch].join(".") property string compilerVersion: jdkVersionProbe.version ? jdkVersionProbe.version[1] : undefined property var compilerVersionParts: JavaUtils.splitVersionString(compilerVersion) property int compilerVersionMajor: compilerVersionParts[0] property int compilerVersionMinor: compilerVersionParts[1] property int compilerVersionPatch: compilerVersionParts[2] property int compilerVersionUpdate: compilerVersionParts[3] property string languageVersion PropertyOptions { name: "languageVersion" description: "Java language version to interpret source code as" } property string runtimeVersion PropertyOptions { name: "runtimeVersion" description: "version of the Java runtime to generate compatible bytecode for" } property var manifest: { return { "Manifest-Version": "1.0", "Class-Path": manifestClassPath ? manifestClassPath.join(" ") : undefined }; } PropertyOptions { name: "manifest" description: "properties to add to the manifest file when building a JAR" } PropertyOptions { name: "manifestFile" description: "Use files tagged \"java.manifest\" instead." removalVersion: "1.9" } property stringList manifestClassPath PropertyOptions { name: "manifestClassPath" description: "entries to add to the manifest's Class-Path when building a JAR" } property bool warningsAsErrors: false property pathList jdkIncludePaths: { var paths = []; if (isAppleJava) { paths.push(FileInfo.joinPaths(qbs.sysroot, "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers")); } else { paths.push(FileInfo.joinPaths(jdkPath, "include")); var hostOS = Host.os().includes("windows") ? Host.os().concat(["win32"]) : Host.os(); var platforms = ["win32", "darwin", "linux", "bsd", "solaris"]; for (var i = 0; i < platforms.length; ++i) { if (hostOS.includes(platforms[i])) { // Corresponds to JDK_INCLUDE_SUBDIR in the JDK Makefiles paths.push(FileInfo.joinPaths(jdkPath, "include", platforms[i])); break; } } } return paths; } // Internal properties property path classFilesDir: FileInfo.joinPaths(product.buildDirectory, "classes") property path internalClassFilesDir: FileInfo.joinPaths(product.buildDirectory, ".classes") property bool isAppleJava: Host.os().includes("darwin") && (compilerVersionMajor < 1 || (compilerVersionMajor === 1 && compilerVersionMinor < 7)) // https://developer.apple.com/library/content/documentation/Java/Conceptual/Java14Development/02-JavaDevTools/JavaDevTools.html // tools.jar does not exist. Classes usually located here are instead included in classes.jar. // The same is true for rt.jar, although not mentioned in the documentation property path classesJarPath: { if (isAppleJava) return FileInfo.joinPaths(jdkPath, "bundle", "Classes", "classes.jar"); } property path runtimeJarPath: { if (compilerVersionMajor >= 9) return undefined; if (classesJarPath) return classesJarPath; return FileInfo.joinPaths(jdkPath, "jre", "lib", "rt.jar"); } property path toolsJarPath: { if (compilerVersionMajor >= 9) return undefined; if (classesJarPath) return classesJarPath; return FileInfo.joinPaths(jdkPath, "lib", "tools.jar"); } validate: { var validator = new ModUtils.PropertyValidator("java"); validator.setRequiredProperty("jdkPath", jdkPath); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionParts", compilerVersionParts); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); if (Utilities.versionCompare(version, "9") < 0) validator.setRequiredProperty("compilerVersionUpdate", compilerVersionUpdate); validator.addVersionValidator("compilerVersion", compilerVersion ? compilerVersion.replace("_", ".") : undefined, 1, 4); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); if (Utilities.versionCompare(version, "9") < 0) validator.addRangeValidator("compilerVersionUpdate", compilerVersionUpdate, 0); validator.validate(); } FileTagger { patterns: "*.java" fileTags: ["java.java"] } FileTagger { patterns: ["*.mf"] fileTags: ["java.manifest"] } Group { name: "io.qt.qbs.internal.java-helper" files: { return JavaUtils.helperFullyQualifiedNames("java").map(function(name) { return FileInfo.joinPaths(path, name + ".java"); }); } fileTags: ["java.java-internal"] } Rule { multiplex: true inputs: ["java.java-internal"] outputFileTags: ["java.class-internal"] outputArtifacts: { return JavaUtils.helperOutputArtifacts(product); } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs, JavaUtils.helperOverrideArgs(product, "javac"))); cmd.ignoreDryRun = true; cmd.silent = true; return [cmd]; } } Rule { multiplex: true inputs: ["java.java"] inputsFromDependencies: ["java.jar"] explicitlyDependsOn: ["java.class-internal"] outputFileTags: ["java.class"].concat(_tagJniHeaders ? ["hpp"] : ["java.jni-hpp"]) // Annotations can produce additional java source files. Ignored for now. outputArtifacts: { var artifacts = JavaUtils.outputArtifacts(product, inputs); if (!product.java._tagJniHeaders) { for (var i = 0; i < artifacts.length; ++i) { var a = artifacts[i]; if (a.fileTags instanceof Array) a.fileTags = a.fileTags.map(function(tag) { if (tag === "hpp") return "java.jni-hpp"; return tag; }); } } return artifacts; } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs)); cmd.description = "compiling Java sources"; cmd.highlight = "compiler"; return [cmd]; } } Rule { inputs: ["java.class", "java.manifest"] multiplex: true Artifact { fileTags: ["java.jar"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".jar") } prepare: { var i, key; var flags = "cf"; var args = [output.filePath]; var aggregateManifest = {}; var manifestFiles = (inputs["java.manifest"] || []).map(function (a) { return a.filePath; }); manifestFiles.forEach(function (manifestFile) { var mf = JavaUtils.manifestContents(manifestFile); for (key in mf) { if (mf.hasOwnProperty(key)) { var oldValue = aggregateManifest[key]; var newValue = mf[key]; if (oldValue !== undefined && oldValue !== newValue) { throw new Error("Conflicting values '" + oldValue + "' and '" + newValue + "' for manifest file key '" + key + "'"); } aggregateManifest[key] = newValue; } } }); // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) var manifest = product.java.manifest; for (key in manifest) { if (manifest.hasOwnProperty(key)) aggregateManifest[key] = manifest[key]; } for (key in aggregateManifest) { if (aggregateManifest.hasOwnProperty(key) && aggregateManifest[key] === undefined) delete aggregateManifest[key]; } // Use default manifest unless we actually have properties to set var needsManifestFile = manifestFiles.length > 0 || aggregateManifest !== {"Manifest-Version": "1.0"}; var manifestFile = FileInfo.joinPaths(product.buildDirectory, "manifest.mf"); var mf; try { mf = new TextFile(manifestFile, TextFile.WriteOnly); // Ensure that manifest version comes first mf.write("Manifest-Version: " + (aggregateManifest["Manifest-Version"] || "1.0") + "\n"); delete aggregateManifest["Manifest-Version"]; for (key in aggregateManifest) mf.write(key + ": " + aggregateManifest[key] + "\n"); mf.write("\n"); } finally { if (mf) { mf.close(); } } if (needsManifestFile) { flags += "m"; args.push(manifestFile); } var entryPoint = ModUtils.moduleProperty(product, "entryPoint"); var entryPoint = product.entryPoint; if (entryPoint) { flags += "e"; args.push(entryPoint); } args.unshift(flags); var otherFlags = ModUtils.moduleProperty(product, "additionalJarFlags"); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.class"]) args.push(FileInfo.relativePath(ModUtils.moduleProperty(product, "classFilesDir"), inputs["java.class"][i].filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "jarFilePath"), args); cmd.workingDirectory = ModUtils.moduleProperty(product, "classFilesDir"); cmd.description = "building " + FileInfo.fileName(output.fileName); cmd.highlight = "linker"; return cmd; } } } qbs-src-3.3.1/share/qbs/modules/java/io/0000755000175100017510000000000015232633614017372 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/io/qt/0000755000175100017510000000000015232633614020016 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/0000755000175100017510000000000015232633614020603 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/Artifact.java0000644000175100017510000000501615232633614023205 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Artifact { private String filePath; private List fileTags; public Artifact(String filePath) { if (filePath == null) throw new IllegalArgumentException("filePath"); this.filePath = filePath; this.fileTags = new ArrayList(); } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public List getFileTags() { return Collections.unmodifiableList(fileTags); } public void setFileTags(List fileTags) { this.fileTags = new ArrayList(fileTags); } public void addFileTag(String fileTag) { this.fileTags.add(fileTag); } public void removeFileTag(String fileTag) { this.fileTags.remove(fileTag); } public void clearFileTags() { this.fileTags.clear(); } } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/ArtifactListWriter.java0000644000175100017510000000334415232633614025240 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.util.List; public interface ArtifactListWriter { void write(List artifacts, OutputStream outputStream) throws IOException; } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/0000755000175100017510000000000015232633614021743 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/utils/0000755000175100017510000000000015232633614023103 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerOptions.java0000644000175100017510000000771015232633614027703 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import javax.lang.model.SourceVersion; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class JavaCompilerOptions { private final List recognizedOptions; private final List classNames; private final List files; private JavaCompilerOptions(List recognizedOptions, List classNames, List files) { this.recognizedOptions = recognizedOptions; this.classNames = classNames; this.files = files; } public static JavaCompilerOptions parse(JavaCompiler compiler, JavaFileManager fileManager, String... arguments) { List recognizedOptions = new ArrayList(); List classNames = new ArrayList(); List files = new ArrayList(); for (int i = 0; i < arguments.length; ++i) { int argumentCount = compiler.isSupportedOption(arguments[i]); if (argumentCount < 0) argumentCount = fileManager.isSupportedOption(arguments[i]); if (argumentCount >= 0) { // isSupportedOption() returns 1 for -Xlint* in Java 9. Bug? if (arguments[i].startsWith("-Xlint")) argumentCount = 0; for (int j = 0; j < argumentCount + 1; ++j) { if (i + j >= arguments.length) { throw new IllegalArgumentException(arguments[i]); } recognizedOptions.add(arguments[i + j]); } i += argumentCount; } else { File file = new File(arguments[i]); if (file.exists()) files.add(file); else if (SourceVersion.isName(arguments[i])) classNames.add(arguments[i]); else throw new IllegalArgumentException(arguments[i]); } } return new JavaCompilerOptions(recognizedOptions, classNames, files); } public List getRecognizedOptions() { return Collections.unmodifiableList(recognizedOptions); } public List getFiles() { return Collections.unmodifiableList(files); } public List getClassNames() { return Collections.unmodifiableList(classNames); } } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/utils/NullFileObject.java0000644000175100017510000001040215232633614026604 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.FileObject; import javax.tools.JavaFileObject; import java.io.*; import java.net.URI; /** * Represents a FileObject that discards its output when written. */ public class NullFileObject implements FileObject, JavaFileObject { FileObject obj; public NullFileObject(FileObject obj) { this.obj = obj; } @Override public URI toUri() { return obj.toUri(); } @Override public String getName() { return obj.getName(); } @Override public InputStream openInputStream() throws IOException { return obj.openInputStream(); } @Override public OutputStream openOutputStream() throws IOException { return new OutputStream() { @Override public void write(int b) throws IOException { } }; } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { return obj.openReader(ignoreEncodingErrors); } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return obj.getCharContent(ignoreEncodingErrors); } @Override public Writer openWriter() throws IOException { return new Writer() { @Override public void write(char[] cbuf, int off, int len) throws IOException { } @Override public void flush() throws IOException { } @Override public void close() throws IOException { } }; } @Override public long getLastModified() { return obj.getLastModified(); } @Override public boolean delete() { return true; } @Override public Kind getKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getKind(); } throw new UnsupportedOperationException(); } @Override public boolean isNameCompatible(String simpleName, Kind kind) { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).isNameCompatible(simpleName, kind); } throw new UnsupportedOperationException(); } @Override public NestingKind getNestingKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getNestingKind(); } throw new UnsupportedOperationException(); } @Override public Modifier getAccessLevel() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getAccessLevel(); } throw new UnsupportedOperationException(); } } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerScanner.java0000644000175100017510000001102315232633614027631 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import io.qt.qbs.*; import javax.tools.*; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.*; public class JavaCompilerScanner { private List artifacts = new ArrayList(); private ArtifactListWriter writer = new ArtifactListJsonWriter(); public List getArtifacts() { return this.artifacts; } public int run(List compilerArguments) { artifacts.clear(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = compiler .getStandardFileManager(null, null, null); final JavaFileManager fileManager = new ForwardingJavaFileManager( standardFileManager) { @Override public JavaFileObject getJavaFileForOutput( JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { JavaFileObject o = super.getJavaFileForOutput(location, className, kind, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (kind.equals(JavaFileObject.Kind.CLASS)) { artifact.addFileTag("java.class"); } else if (kind.equals(JavaFileObject.Kind.SOURCE)) { artifact.addFileTag("java.java"); } artifacts.add(artifact); return new NullFileObject(o); } @Override public FileObject getFileForOutput( JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { FileObject o = super.getFileForOutput(location, packageName, relativeName, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (o.getName().endsWith(".h")) { artifact.addFileTag("hpp"); } artifacts.add(artifact); return new NullFileObject(o); } }; final JavaCompilerOptions options = JavaCompilerOptions .parse(compiler, standardFileManager, compilerArguments .toArray(new String[compilerArguments.size()])); return compiler.getTask( null, fileManager, null, options.getRecognizedOptions(), options.getClassNames(), standardFileManager.getJavaFileObjectsFromFiles(options .getFiles())).call() ? 0 : 1; } public void write(OutputStream outputStream) throws IOException { writer.write(getArtifacts(), outputStream); } } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/tools/JavaCompilerScannerTool.java0000644000175100017510000000412015232633614027327 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools; import io.qt.qbs.tools.utils.JavaCompilerScanner; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; public class JavaCompilerScannerTool { public static void main(String[] args) { try { JavaCompilerScanner scanner = new JavaCompilerScanner(); int result = scanner.run(new ArrayList(Arrays.asList(args))); scanner.write(System.out); System.exit(result); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } qbs-src-3.3.1/share/qbs/modules/java/io/qt/qbs/ArtifactListJsonWriter.java0000644000175100017510000001302715232633614026071 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; /** * This uses a custom JSON implementation because the Java Standard Library does * not yet have native support for JSON, and only minimal support is required * here. */ public class ArtifactListJsonWriter implements ArtifactListWriter { private static final int TAB_WIDTH = 4; // based on escapeString from qtbase/qjsonwriter.cpp private static String escapeString(String s) { String out = ""; for (int i = 0; i < s.length();) { int u = s.codePointAt(i); // unpaired surrogate if (u >= Character.MIN_SURROGATE && u <= Character.MAX_SURROGATE) { out += "\ufffd"; i += Character.charCount(u); continue; } if (u < 0x80) { if (u < 0x20 || u == 0x22 || u == 0x5c) { out += "\\"; switch (u) { case 0x22: out += "\""; break; case 0x5c: out += "\\"; break; case 0x8: out += "b"; break; case 0xc: out += "f"; break; case 0xa: out += "n"; break; case 0xd: out += "r"; break; case 0x9: out += "t"; break; default: out += "u"; out += "0"; out += "0"; String hex = Integer.toHexString(u); if (hex.length() == 1) out += "0"; out += hex; break; } } else { out += s.substring(i, i + Character.charCount(u)); } } else { out += s.substring(i, i + Character.charCount(u)); } i += Character.charCount(u); } return out; } private static void writeString(PrintStream printWriter, String s) { printWriter.print("\""); printWriter.print(escapeString(s)); printWriter.print("\""); } private static void writeIndent(PrintStream printWriter, int level) { for (int i = 0; i < level * TAB_WIDTH; ++i) { printWriter.print(" "); } } private static void writeArtifact(Artifact artifact, PrintStream printWriter, int indentLevel, Boolean comma) { writeIndent(printWriter, indentLevel++); printWriter.print("{\n"); writeIndent(printWriter, indentLevel); writeString(printWriter, "filePath"); printWriter.print(": "); writeString(printWriter, artifact.getFilePath()); printWriter.println(","); writeIndent(printWriter, indentLevel); writeString(printWriter, "fileTags"); printWriter.print(": ["); for (int i = 0; i < artifact.getFileTags().size(); ++i) { writeString(printWriter, artifact.getFileTags().get(i)); if (i != artifact.getFileTags().size() - 1) printWriter.print(", "); } printWriter.println("]"); writeIndent(printWriter, --indentLevel); printWriter.println("}" + (comma ? "," : "")); } @Override public void write(List artifacts, OutputStream outputStream) throws IOException { PrintStream printWriter = new PrintStream(outputStream); printWriter.print("[\n"); for (int i = 0; i < artifacts.size(); ++i) { writeArtifact(artifacts.get(i), printWriter, 1, i != artifacts.size() - 1); } printWriter.println("]"); } } qbs-src-3.3.1/share/qbs/modules/java/utils.js0000644000175100017510000003576715232633614020503 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function is64bitProcess() { var y = jdkRootRegistryKey(true); var n = jdkRootRegistryKey(false); y = Utilities.getNativeSetting(y + "\\" + Utilities.getNativeSetting(y, "CurrentVersion"), "JavaHome"); n = Utilities.getNativeSetting(n + "\\" + Utilities.getNativeSetting(n, "CurrentVersion"), "JavaHome"); return y !== n; } function useWow64Key(arch) { var wow64 = false; switch (arch) { case "x86_64": case "ia64": // QTBUG-3845 if (!is64bitProcess()) return undefined; break; case "x86": case "armv7": wow64 = is64bitProcess(); break; } return wow64; } function jdkRootRegistryKey(wow64) { // If an architecture is specified, search the appropriate key for that architecture, // on this version of Windows (i.e. WOW64 or not) if compatible, // otherwise get both keys since any JDK will be usable if (wow64 === undefined) return undefined; return FileInfo.toWindowsSeparators(FileInfo.joinPaths("HKEY_LOCAL_MACHINE", "SOFTWARE", (wow64 ? "Wow6432Node" : undefined), "JavaSoft", "Java Development Kit")); } function findJdkPath(hostOS, arch, environmentPaths, searchPaths) { var i; for (i = 0; i < environmentPaths.length; ++i) { if (environmentPaths[i]) return environmentPaths[i]; } if (hostOS.includes("windows")) { var rootKey = jdkRootRegistryKey(useWow64Key(arch)); if (rootKey) { var current = Utilities.getNativeSetting(rootKey, "CurrentVersion"); // 1.8 etc. if (current) { var home = Utilities.getNativeSetting([rootKey, current].join("\\"), "JavaHome"); if (home) { return home; } } } return undefined; } if (hostOS.includes("macos")) { var p = new Process(); try { // We filter by architecture here so that we'll get a compatible JVM for JNI use. var args = []; var canonicalArch; if (arch) { // Hardcoding apple/macosx/macho here is fine because we know we're on macOS canonicalArch = Utilities.canonicalTargetArchitecture(arch, undefined, "apple", "macosx", "macho"); args.push("--arch", canonicalArch); } // --failfast doesn't print the default JVM if nothing matches the filter(s). var status = p.exec("/usr/libexec/java_home", args.concat(["--failfast"])); if (status === 0) return p.readStdOut().trim(); // It has been obvserved that java_home fails for any architecture that is passed, // so try without the filter and look up the JDK architecture manually. if (!canonicalArch) return undefined; if (p.exec("/usr/libexec/java_home", ["--failfast"]) !== 0) return undefined; var jdkPath = p.readStdOut().trim(); var releaseFile = new TextFile(jdkPath + "/release", TextFile.ReadOnly); var line; while ((line = releaseFile.readLine())) { if (!line.startsWith("OS_ARCH=")) continue; var firstQuote = line.indexOf('"'); if (firstQuote === -1) break; var secondQuote = line.indexOf('"', firstQuote + 1); if (secondQuote === -1) break; var archFromFile = line.substring(firstQuote + 1, secondQuote); if (archFromFile !== canonicalArch) break; return jdkPath; } return undefined; } finally { p.close(); } } if (hostOS.includes("unix")) { var requiredTools = ["javac", "java", "jar"]; for (i = 0; i < searchPaths.length; ++i) { function fullToolPath(tool) { return FileInfo.joinPaths(searchPaths[i], "bin", tool); } if (requiredTools.map(function(p) { return fullToolPath(p); }) .every(function(p) { return File.exists(p); })) { return searchPaths[i]; } } return undefined; } } function findJdkVersion(compilerFilePath) { var p = new Process(); try { p.exec(compilerFilePath, ["-version"]); var re = /^javac (([0-9]+(?:\.[0-9]+){0,2})(_([0-9]+))?)(.*)?$/m; var match = p.readStdErr().trim().match(re); if (!match) match = p.readStdOut().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function splitVersionString(compilerVersion) { if (!compilerVersion) return []; var result = compilerVersion.split(/[\._]/).map(function(item) { return parseInt(item, 10); }); // special case, if javac -version returned "12" instead of "12.0.0" if (result.length === 1) result.push(0, 0); return result; } function supportsGeneratedNativeHeaderFiles(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "compilerVersionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "compilerVersionMinor") >= 8) { return true; } } return compilerVersionMajor > 1; } function javacArguments(product, inputs, overrides) { function getModuleProperty(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperty(product, propertyName); } function getModuleProperties(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperty(product, propertyName); } var i; var outputDir = getModuleProperty(product, "classFilesDir", overrides); var classPaths = [outputDir]; var additionalClassPaths = getModuleProperties(product, "additionalClassPaths", overrides); if (additionalClassPaths) classPaths = classPaths.concat(additionalClassPaths); for (i in inputs["java.jar"]) classPaths.push(inputs["java.jar"][i].filePath); var debugArg = product.moduleProperty("qbs", "buildVariant") === "debug" ? "-g" : "-g:none"; var pathListSeparator = FileInfo.pathListSeparator(); var args = [ "-classpath", classPaths.join(pathListSeparator), "-s", product.buildDirectory, debugArg, "-d", outputDir ]; if (supportsGeneratedNativeHeaderFiles(product)) args.push("-h", product.buildDirectory); var runtimeVersion = getModuleProperty(product, "runtimeVersion", overrides); if (runtimeVersion) args.push("-target", runtimeVersion); var languageVersion = getModuleProperty(product, "languageVersion", overrides); if (languageVersion) args.push("-source", languageVersion); var bootClassPaths = getModuleProperties(product, "bootClassPaths", overrides); if (bootClassPaths && bootClassPaths.length > 0 && (!runtimeVersion || Utilities.versionCompare(runtimeVersion, "9") < 0)) { args.push("-bootclasspath", bootClassPaths.join(pathListSeparator)); } if (!getModuleProperty(product, "enableWarnings", overrides)) args.push("-nowarn"); if (getModuleProperty(product, "warningsAsErrors", overrides)) args.push("-Werror"); var otherFlags = getModuleProperties(product, "additionalCompilerFlags", overrides); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.java"]) args.push(inputs["java.java"][i].filePath); for (i in inputs["java.java-internal"]) args.push(inputs["java.java-internal"][i].filePath); return args; } /** * Returns a list of fully qualified Java class names for the compiler helper tool. * * @param type @c java to return names of sources, @c to return names of compiled classes */ function helperFullyQualifiedNames(type) { var names = [ "io/qt/qbs/Artifact", "io/qt/qbs/ArtifactListJsonWriter", "io/qt/qbs/ArtifactListWriter", "io/qt/qbs/tools/JavaCompilerScannerTool", "io/qt/qbs/tools/utils/JavaCompilerOptions", "io/qt/qbs/tools/utils/JavaCompilerScanner", "io/qt/qbs/tools/utils/JavaCompilerScanner$1", "io/qt/qbs/tools/utils/NullFileObject", "io/qt/qbs/tools/utils/NullFileObject$1", "io/qt/qbs/tools/utils/NullFileObject$2", ]; if (type === "java") { return names.filter(function (name) { return !name.includes("$"); }); } else if (type === "class") { return names; } } function helperOutputArtifacts(product) { File.makePath(ModUtils.moduleProperty(product, "internalClassFilesDir")); return helperFullyQualifiedNames("class").map(function (name) { return { filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"), name + ".class"), fileTags: ["java.class-internal"] }; }); } function helperOverrideArgs(product, tool) { var overrides = {}; if (tool === "javac") { // Build the helper tool with the same source and target version as the JDK it's being // compiled with. Both are irrelevant here since the resulting tool will only be run // with the same JDK as it was built with, and we know in advance the source is // compatible with all Java language versions from 1.6 and above. var jdkVersionArray = [product.java.compilerVersionMajor]; if (product.java.compilerVersionMajor < 9) jdkVersionArray.push(product.java.compilerVersionMinor); var jdkVersion = jdkVersionArray.join("."); overrides["languageVersion"] = jdkVersion; overrides["runtimeVersion"] = jdkVersion; // Build the helper tool's class files separately from the actual product's class files overrides["classFilesDir"] = ModUtils.moduleProperty(product, "internalClassFilesDir"); // Add tools.jar to the classpath as required for the tree scanner API var toolsJarPath = ModUtils.moduleProperty(product, "toolsJarPath"); if (toolsJarPath) overrides["additionalClassPaths"] = [toolsJarPath].concat( ModUtils.moduleProperty(product, "additionalClassPaths")); } // Inject the current JDK's runtime classes into the boot class path when building/running the // dependency scanner. This is normally not necessary but is important for Android platforms // where android.jar is the only JAR on the boot classpath and JSR 199 is unavailable. var rtJarPath = product.java.runtimeJarPath; overrides["bootClassPaths"] = (rtJarPath ? [rtJarPath] : []).concat( ModUtils.moduleProperty(product, "bootClassPaths")); return overrides; } function outputArtifacts(product, inputs) { // Handle the case where a product depends on Java but has no Java sources if (!inputs["java.java"] || inputs["java.java"].length === 0) return []; // We need to ensure that the output directory is created first, because the Java compiler // internally checks that it is present before performing any actions File.makePath(ModUtils.moduleProperty(product, "classFilesDir")); var process; try { process = new Process(); process.setWorkingDirectory( FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"))); var sep = FileInfo.pathListSeparator(); var toolsJarPath = ModUtils.moduleProperty(product, "toolsJarPath"); var javaArgs = [ "-classpath", process.workingDirectory() + (toolsJarPath ? (sep + toolsJarPath) : ""), "io/qt/qbs/tools/JavaCompilerScannerTool", ]; process.exec(ModUtils.moduleProperty(product, "interpreterFilePath"), javaArgs .concat(javacArguments(product, inputs, helperOverrideArgs(product))), true); var out = JSON.parse(process.readStdOut()); console.error(process.readStdErr()); return out; } finally { if (process) process.close(); } } function manifestContents(filePath) { if (filePath === undefined) return undefined; var contents, file; try { file = new TextFile(filePath); contents = file.readAll(); } finally { if (file) { file.close(); } } if (contents) { var dict = {}; var lines = contents.split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var i = 0; i < lines.length; ++i) { var kv = lines[i].split(":"); if (kv.length !== 2) throw new Error("Syntax error in manifest file '" + filePath + "'; found \"" + lines[i] + "\" on line " + parseInt(i, 10) + "; expected format \"Key: Value\""); dict[kv[0].trim()] = kv[1].trim(); } return dict; } } qbs-src-3.3.1/share/qbs/modules/archiver/0000755000175100017510000000000015232633614017645 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/archiver/archiver.qbs0000644000175100017510000002307115232633614022162 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.Host import qbs.FileInfo import qbs.Probes Module { // jar is a suitable fallback for creating zip files as they are the same format // This will most likely end up being used on Windows Depends { name: "java"; required: false } Probes.BinaryProbe { id: tarProbe names: ["tar"] } Probes.BinaryProbe { id: zipProbe names: ["zip"] } Probes.BinaryProbe { id: sevenZipProbe names: ["7z"] platformSearchPaths: { var paths = base; if (Host.os().includes("windows")) { var env32 = Environment.getEnv("PROGRAMFILES(X86)"); var env64 = Environment.getEnv("PROGRAMFILES"); if (env64 === env32 && env64.endsWith(" (x86)")) env64 = env64.slice(0, -(" (x86)".length)); // QTBUG-3845 paths.push(FileInfo.joinPaths(env64, "7-Zip")); paths.push(FileInfo.joinPaths(env32, "7-Zip")); } return paths; } } property string type property string archiveBaseName: product.targetName property string workingDirectory property stringList flags: [] property path outputDirectory: product.destinationDirectory property string archiveExtension: { if (type === "7zip") return "7z"; if (type == "tar") { var extension = "tar"; if (compressionType !== "none") extension += "." + compressionType; return extension; } if (type === "zip") return "zip"; return undefined; } property string command: { if (type === "7zip") return sevenZipProbe.filePath; if (type === "tar") { if (tarProbe.found) return tarProbe.filePath; if (sevenZipProbe.found) return sevenZipProbe.filePath; } if (type === "zip") { // Prefer zip (probably Info-Zip) and fall back to 7z or jar when it's not available // (as is the likely case on Windows) if (zipProbe.found) return zipProbe.filePath; if (sevenZipProbe.found) return sevenZipProbe.filePath; if (java.present) return java.jarFilePath; } return undefined; } property string compressionLevel property string compressionType: { if (type === "tar") return "gz"; return undefined; } PropertyOptions { name: "type" description: "The type of archive to create." allowedValues: ["7zip", "tar", "zip"] } PropertyOptions { name: "compressionLevel" description: "How much effort to put into compression.\n" + "Higher numbers mean smaller archive files at the cost of taking more time.\n" + "This property is only used for the '7zip' and 'zip' types.\n" + "'7zip' only supports 0 and odd numbers." allowedValues: [undefined, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] } PropertyOptions { name: "compressionType" description: "The compression format to use.\n" + "For tar archives, the respective tool needs to be present.\n" + "This property is only used for the 'tar' and 'zip' types." allowedValues: ["none", "gz", "bz2", "Z", "xz", "deflate", "store"] } Rule { inputs: ["archiver.input-list"] Artifact { filePath: FileInfo.joinPaths(product.moduleProperty("archiver", "outputDirectory"), product.moduleProperty("archiver", "archiveBaseName") + '.' + product.moduleProperty("archiver", "archiveExtension")); fileTags: ["archiver.archive"] } prepare: { var binary = product.moduleProperty("archiver", "command"); var binaryName = FileInfo.baseName(binary); var args = []; var commands = []; var type = product.moduleProperty("archiver", "type"); var compression = product.moduleProperty("archiver", "compressionType"); var compressionLevel = product.moduleProperty("archiver", "compressionLevel"); if (binaryName === "7z") { var rmCommand = new JavaScriptCommand(); rmCommand.silent = true; rmCommand.sourceCode = function() { if (File.exists(output.filePath)) File.remove(output.filePath); }; commands.push(rmCommand); args.push("a", "-y", "-mmt=on"); switch (type) { case "7zip": args.push("-t7z"); break; case "zip": args.push("-tzip"); break; case "tar": if (compression === "gz") args.push("-tgzip"); else if (compression === "bz2") args.push("-tbzip2"); else args.push("-ttar"); break; default: throw "7zip: unrecognized archive type: '" + type + "'"; } if (compressionLevel) args.push("-mx" + compressionLevel); args = args.concat(product.moduleProperty("archiver", "flags")); args.push(output.filePath); args.push("@" + input.filePath); } else if (binaryName === "tar" && type === "tar") { args.push("-c"); if (compression === "gz") args.push("-z"); else if (compression === "bz2") args.push("-j"); else if (compression === "Z") args.push("-Z"); else if (compression === "xz") args.push("-J"); args.push("-f", output.filePath, "-T", input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (binaryName === "jar" && type === "zip") { if (compression === "none" || compressionLevel === "0") args.push("-0"); args.push("-cfM", output.filePath, "@" + input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (binaryName === "zip" && type === "zip") { // The "zip" program included with most Linux and Unix distributions // (including macOS) is Info-ZIP's Zip, so this should be fairly portable. if (compression === "none") { args.push("-0"); } else { compression = compression === "bz2" ? "bzip2" : compression; if (["store", "deflate", "bzip2"].includes(compression)) args.push("-Z", compression); if (compressionLevel) args.push("-" + compressionLevel); } args.push("-r", output.filePath, ".", "-i@" + input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (["tar", "zip", "jar"].includes(binaryName)) { throw binaryName + ": unrecognized archive type: '" + type + "'"; } else if (binaryName) { throw "unrecognized archive tool: '" + binaryName + "'"; } else { throw "no archive tool available to produce archive type: '" + type + "'"; } var archiverCommand = new Command(binary, args); archiverCommand.description = "creating archive file " + output.fileName; archiverCommand.highlight = "linker"; archiverCommand.workingDirectory = product.moduleProperty("archiver", "workingDirectory"); commands.push(archiverCommand); return commands; } } } qbs-src-3.3.1/share/qbs/modules/protobuf/0000755000175100017510000000000015232633614017702 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/protobuf/objc/0000755000175100017510000000000015232633614020617 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/protobuf/objc/protobufobjc.qbs0000644000175100017510000000436115232633614024030 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Probes import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { property string includePath: includeProbe.path property string libraryPath: libraryProbe.path property string frameworkPath: frameworkProbe.path Depends { name: "cpp" } cpp.includePaths: [outputDir].concat(!frameworkPath && includePath ? [includePath] : []) cpp.libraryPaths: !frameworkPath && libraryPath ? [libraryPath] : [] cpp.dynamicLibraries: !frameworkPath && libraryPath ? ["ProtocolBuffers"] : [] cpp.frameworkPaths: frameworkPath ? [frameworkPath] : [] cpp.frameworks: ["Foundation"].concat(frameworkPath ? ["Protobuf"] : []) cpp.defines: frameworkPath ? ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"] : [] Rule { inputs: ["protobuf.input"] outputFileTags: ["hpp", "protobuf.hpp", "objc"] outputArtifacts: { var outputDir = HelperFunctions.getOutputDir(input.protobuf.objc, input); return [ HelperFunctions.objcArtifact(outputDir, input, ["hpp", "protobuf.hpp"], ".pbobjc.h"), HelperFunctions.objcArtifact(outputDir, input, ["objc"], ".pbobjc.m") ]; } prepare: HelperFunctions.doPrepare(input.protobuf.objc, product, input, outputs, "objc") } Probes.IncludeProbe { id: includeProbe names: "GPBMessage.h" } Probes.LibraryProbe { id: libraryProbe names: "ProtocolBuffers" } Probes.FrameworkProbe { id: frameworkProbe names: ["Protobuf"] } validate: { HelperFunctions.validateCompiler(compilerName, compilerPath); if (!HelperFunctions.checkPath(frameworkPath)) { if (!HelperFunctions.checkPath(includePath)) { throw "Can't find objective-c protobuf include files. Please set the includePath " + "or frameworkPath property."; } if (!HelperFunctions.checkPath(libraryPath)) { throw "Can't find objective-c protobuf library. Please set the libraryPath or " + "frameworkPath property."; } } } } qbs-src-3.3.1/share/qbs/modules/protobuf/protobuf.js0000644000175100017510000001106015232633614022076 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); function validateCompiler(compilerName, compilerPath) { if (!File.exists(compilerPath)) { throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or " + "make sure the compiler is found in PATH"; } } function checkPath(path) { return path && File.exists(path); }; function toCamelCase(str){ return str.split('_').map(function(word, index) { // If it is the first word make sure to lowercase all the chars. if (index === 0) { return word.toLowerCase(); } // If it is not the first word only upper case the first char and lowercase the rest. return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(''); } function getOutputDir(module, input) { var outputDir = module.outputDir; var importPaths = module.importPaths; if (importPaths.length !== 0) { var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); for (var i = 0; i < importPaths.length; ++i) { var path = File.canonicalFilePath(importPaths[i]); if (canonicalInput.startsWith(path)) { return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); } } } return outputDir; } function cppArtifact(outputDir, input, tags, suffix) { return { fileTags: tags, filePath: FileInfo.joinPaths(outputDir, FileInfo.baseName(input.fileName) + suffix), cpp: { includePaths: [].concat(input.cpp.includePaths, outputDir), defines: ["NDEBUG"], warningLevel: "none", } }; } function objcArtifact(outputDir, input, tags, suffix) { return { fileTags: tags, filePath: FileInfo.joinPaths( outputDir, toCamelCase(FileInfo.baseName(input.fileName)) + suffix), cpp: { automaticReferenceCounting: false, includePaths: [].concat(input.cpp.includePaths, outputDir), warningLevel: "none", } } } function doPrepare(module, product, input, outputs, generator, plugin, generatorOptions) { var outputDir = module.outputDir; var args = []; if (!!plugin) args.push("--plugin=" + plugin) args.push("--" + generator + "_out", outputDir); if (!!generatorOptions) { for (var i = 0; i < generatorOptions.length; ++i) args.push("--" + generator + "_opt=" + generatorOptions[i]) } var importPaths = module.importPaths; if (importPaths.length === 0) importPaths = [FileInfo.path(input.filePath)]; importPaths.forEach(function(path) { if (!FileInfo.isAbsolutePath(path)) path = FileInfo.joinPaths(product.sourceDirectory, path); args.push("--proto_path", path); }); args.push(input.filePath); var cmd = new Command(module.compilerPath, args); cmd.highlight = "codegen"; cmd.description = "generating " + generator + " files for " + input.fileName; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/protobuf/nanopb/0000755000175100017510000000000015232633614021157 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/protobuf/nanopb/nanopb.qbs0000644000175100017510000000654715232633614023157 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Probes import qbs.ModUtils import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { property string includePath: includeProbe.found ? includeProbe.path : undefined property string libraryPath: libraryProbe.found ? libraryProbe.path : undefined property string pluginPath: pluginProbe.filePath property string pluginName: "protoc-gen-nanopb" readonly property string _plugin: "protoc-gen-nanopb=" + pluginPath readonly property string _libraryName: { var libraryName; if (libraryProbe.found) { libraryName = FileInfo.baseName(libraryProbe.fileName); if (libraryName.startsWith("lib")) libraryName = libraryName.substring(3); } return libraryName; } Depends { name: "cpp" } cpp.libraryPaths: { var result = []; if (libraryProbe.found) result.push(libraryProbe.path); return result; } cpp.dynamicLibraries: { var result = []; if (_libraryName) result.push(_libraryName); return result; } cpp.includePaths: { var result = [outputDir]; if (includeProbe.found) result.push(includePath); return result; } cpp.cxxLanguageVersion: qbs.targetOS.contains("darwin") ? ["c++17"] : ["c++11"] Rule { inputs: ["protobuf.input"] outputFileTags: ["hpp", "protobuf.hpp", "cpp"] outputArtifacts: { var outputDir = HelperFunctions.getOutputDir(input.protobuf.nanopb, input); var result = [ HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"], ".pb.h"), HelperFunctions.cppArtifact(outputDir, input, ["cpp"], ".pb.c") ]; return result; } prepare: { var options = input.protobuf.nanopb.importPaths.map(function (path) { return "-I" + path; }) var result = HelperFunctions.doPrepare( input.protobuf.nanopb, product, input, outputs, "nanopb", input.protobuf.nanopb._plugin, options); return result; } } Probes.IncludeProbe { id: includeProbe names: ["pb.h", "pb_encode.h", "pb_decode.h", "pb_common.h"] platformSearchPaths: includePath ? [] : base searchPaths: includePath ? [includePath] : [] } Probes.LibraryProbe { id: libraryProbe names: [ "protobuf-nanopb", "protobuf-nanopbd", ] platformSearchPaths: libraryPath ? [] : base searchPaths: libraryPath ? [libraryPath] : [] } Probes.BinaryProbe { id: pluginProbe names: pluginName } validate: { HelperFunctions.validateCompiler(compilerName, compilerPath); if (!includeProbe.found) throw "Can't find nanopb protobuf include files. Please set the includePath property."; if (!libraryProbe.found) throw "Can't find nanopb protobuf library. Please set the libraryPath property."; if (!HelperFunctions.checkPath(pluginPath)) throw "Can't find nanopb protobuf plugin. Please set the pluginPath property."; } } qbs-src-3.3.1/share/qbs/modules/protobuf/protobufbase.qbs0000644000175100017510000000106615232633614023107 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Probes import "protobuf.js" as HelperFunctions Module { property string compilerName: "protoc" property string compilerPath: compilerProbe.filePath property var _searchPaths property pathList importPaths: [] readonly property string outputDir: product.buildDirectory + "/protobuf" FileTagger { patterns: ["*.proto"] fileTags: ["protobuf.input"] } Probes.BinaryProbe { id: compilerProbe names: [compilerName] searchPaths: _searchPaths } } qbs-src-3.3.1/share/qbs/modules/protobuf/cpp/0000755000175100017510000000000015232633614020464 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/protobuf/cpp/protobufcpp.qbs0000644000175100017510000000566115232633614023546 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Probes import qbs.ModUtils import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { property bool useGrpc: false property bool _linkLibraries: true readonly property bool _hasModules: protobuflib.present && (!useGrpc || grpcpp.present) property string _cxxLanguageVersion: "c++17" _searchPaths: protobuflib.present ? protobuflib.hostBinDirs : undefined property stringList _grpcSearchPaths: grpcpp.present ? grpcpp.hostBinDirs : undefined cpp.includePaths: outputDir Depends { name: "cpp" } Depends { name: "protobuflib"; condition: _linkLibraries; required: false } Depends { name: "grpc++"; id: grpcpp condition: _linkLibraries && useGrpc; required: false } property path grpcPluginPath: grpcPluginProbe.filePath Probes.BinaryProbe { condition: useGrpc id: grpcPluginProbe names: "grpc_cpp_plugin" searchPaths: _grpcSearchPaths } cpp.cxxLanguageVersion: _cxxLanguageVersion Rule { inputs: ["protobuf.input", "protobuf.grpc"] outputFileTags: ["hpp", "protobuf.hpp", "cpp"] outputArtifacts: { var outputDir = HelperFunctions.getOutputDir(input.protobuf.cpp, input); var result = [ HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"], ".pb.h"), HelperFunctions.cppArtifact(outputDir, input, "cpp", ".pb.cc") ]; if (input.fileTags.includes("protobuf.grpc")) { result.push( HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"], ".grpc.pb.h"), HelperFunctions.cppArtifact(outputDir, input, ["cpp"], ".grpc.pb.cc")); } return result; } prepare: { var result = HelperFunctions.doPrepare( input.protobuf.cpp, product, input, outputs, "cpp"); if (input.fileTags.includes("protobuf.grpc")) { result = ModUtils.concatAll(result, HelperFunctions.doPrepare( input.protobuf.cpp, product, input, outputs, "grpc", "protoc-gen-grpc=" + input.protobuf.cpp.grpcPluginPath)); } return result; } } validate: { HelperFunctions.validateCompiler(compilerName, compilerPath); if (_linkLibraries && ! _hasModules) { throw "Can't find cpp protobuf runtime. Make sure .pc files are present"; } if (useGrpc) { if (!File.exists(grpcPluginPath)) throw "Can't find grpc_cpp_plugin plugin. Please set the grpcPluginPath property."; } } } qbs-src-3.3.1/share/qbs/modules/codesign/0000755000175100017510000000000015232633614017635 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/codesign/android.qbs0000644000175100017510000001223115232633614021763 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Raphaël Cotty ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Probes import "codesign.js" as CodeSign CodeSignModule { condition: qbs.targetOS.includes("android") priority: 1 enableCodeSigning: true property bool useApksigner: true property path apksignerFilePath Probes.JdkProbe { id: jdk environmentPaths: (jdkPath ? [jdkPath] : []).concat(base) } property string jdkPath: jdk.path property string jarsignerFilePath: FileInfo.joinPaths(jdkPath, "bin", jarsignerName) property string jarsignerName: "jarsigner" property string keytoolFilePath: FileInfo.joinPaths(jdkPath, "bin", keytoolName) property string keytoolName: "keytool" property string debugKeystorePath: FileInfo.joinPaths( Environment.getEnv(Host.os().includes("windows") ? "USERPROFILE" : "HOME"), ".android", "debug.keystore") readonly property string debugKeystorePassword: "android" readonly property string debugPassword: "android" readonly property string debugKeyAlias: "androiddebugkey" property string keystorePath: debugKeystorePath property string keystorePassword: debugKeystorePassword property string keyPassword: debugPassword property string keyAlias: debugKeyAlias // Private property set by the Android.sdk module property string _packageName Rule { condition: useApksigner inputs: ["android.package_unsigned"] Artifact { filePath: product.codesign._packageName fileTags: "android.package" } prepare: CodeSign.signApkPackage.apply(this, arguments) } Rule { condition: !useApksigner inputs: ["android.package_unsigned"] Artifact { filePath: product.codesign._packageName fileTags: "android.package" } prepare: CodeSign.signAabPackage.apply(this, arguments) } validate: { // Typically there is a debug keystore in ~/.android/debug.keystore which gets created // by the native build tools the first time a build is done. However, we don't want to // create it ourselves, because writing to a location outside the qbs build directory is // both polluting and has the potential for race conditions. So we'll instruct the user what // to do. if (keystorePath === debugKeystorePath && !File.exists(debugKeystorePath)) { throw ModUtils.ModuleError("Could not find an Android debug keystore at " + codesign.debugKeystorePath + ". " + "If you are developing for Android on this machine for the first time and " + "have never built an application using the native Gradle / Android Studio " + "tooling, this is normal. You must create the debug keystore now using the " + "following command, in order to continue:\n\n" + CodeSign.createDebugKeyStoreCommandString(codesign.keytoolFilePath, codesign.debugKeystorePath, codesign.debugKeystorePassword, codesign.debugPassword, codesign.debugKeyAlias) + "\n\n" + "See the following URL for more information: " + "https://developer.android.com/studio/publish/app-signing.html#debug-mode"); } } } qbs-src-3.3.1/share/qbs/modules/codesign/apple.qbs0000644000175100017510000002207415232633614021452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.BundleTools import qbs.DarwinTools import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.PropertyList import qbs.Probes import qbs.Utilities import "codesign.js" as CodeSign import "../xcode/xcode.js" as XcodeUtils CodeSignModule { Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.includes("xcode") } Probes.BinaryProbe { id: codesignProbe names: [codesignName] } condition: Host.os().includes("macos") && qbs.targetOS.includes("darwin") priority: 0 enableCodeSigning: _codeSigningRequired codesignName: "codesign" codesignPath: codesignProbe.filePath _canSignArtifacts: true property string signingType: { if (_adHocCodeSigningAllowed) return "ad-hoc"; if (_codeSigningAllowed) return "app-store"; } PropertyOptions { name: "signingType" allowedValues: ["app-store", "apple-id", "ad-hoc"] } property string signingIdentity: { if (signingType === "ad-hoc") // only useful on macOS return "-"; var isDebug = qbs.buildVariant !== "release"; if (qbs.targetOS.includes("ios") || qbs.targetOS.includes("tvos") || qbs.targetOS.includes("watchos")) { switch (signingType) { case "app-store": return isDebug ? "iPhone Developer" : "iPhone Distribution"; } } if (qbs.targetOS.includes("macos")) { switch (signingType) { case "app-store": return isDebug ? "Mac Developer" : "3rd Party Mac Developer Application"; case "apple-id": return "Developer ID Application"; } } } signingTimestamp: "none" property string provisioningProfile PropertyOptions { name: "provisioningProfile" description: "Name or UUID of the provisioning profile to embed in the application; " + "typically left blank to allow automatic provisioning" } property string teamIdentifier PropertyOptions { name: "teamIdentifier" description: "Name or identifier of the development team whose identities will be used; " + "typically left blank unless signed into multiple development teams" } property path provisioningProfilesPath: { if (xcode.present && Utilities.versionCompare(xcode.version, "26.0.0") < 0) return "~/Library/MobileDevice/Provisioning Profiles"; return "~/Library/Developer/Xcode/UserData/Provisioning Profiles" } readonly property var _actualSigningIdentity: { if (signingIdentity === "-") { return { SHA1: signingIdentity, subjectInfo: { CN: "ad hoc" } } } var identities = CodeSign.findSigningIdentities(signingIdentity, teamIdentifier); if (identities && Object.keys(identities).length > 1) { throw "Multiple codesigning identities (i.e. certificate and private key pairs) " + "matching '" + signingIdentity + "' were found." + CodeSign.humanReadableIdentitySummary(identities); } for (var i in identities) return identities[i]; } // Allowed for macOS readonly property bool _adHocCodeSigningAllowed: XcodeUtils.boolFromSdkOrPlatform("AD_HOC_CODE_SIGNING_ALLOWED", xcode._sdkProps, xcode._platformProps, true) // Allowed for all device platforms (not simulators) readonly property bool _codeSigningAllowed: XcodeUtils.boolFromSdkOrPlatform("CODE_SIGNING_ALLOWED", xcode._sdkProps, xcode._platformProps, true) // Required for tvOS, iOS, and watchOS (not simulators) property bool _codeSigningRequired: { // allow to override value from Xcode so tests do not require signing var envRequired = Environment.getEnv("QBS_AUTOTEST_CODE_SIGNING_REQUIRED"); if (envRequired) return envRequired === "1"; return XcodeUtils.boolFromSdkOrPlatform("CODE_SIGNING_REQUIRED", xcode._sdkProps, xcode._platformProps, false) } // Required for tvOS, iOS, and watchOS (not simulators) readonly property bool _entitlementsRequired: XcodeUtils.boolFromSdkOrPlatform("ENTITLEMENTS_REQUIRED", xcode._sdkProps, xcode._platformProps, false) readonly property bool _provisioningProfileAllowed: product.bundle && product.bundle.isBundle && product.type.includes("application") && xcode.platformType !== "simulator" // Required for tvOS, iOS, and watchOS (not simulators) // PROVISIONING_PROFILE_REQUIRED is specified only in Embedded-Device.xcspec in the // IDEiOSSupportCore IDE plugin, so we'll just write out the logic here manually readonly property bool _provisioningProfileRequired: _provisioningProfileAllowed && !qbs.targetOS.includes("macos") // Not used on simulator platforms either but provisioning profiles aren't used there anyways readonly property string _provisioningProfilePlatform: { if (qbs.targetOS.includes("macos")) return "OSX"; if (qbs.targetOS.includes("ios") || qbs.targetOS.includes("watchos")) return "iOS"; if (qbs.targetOS.includes("tvos")) return "tvOS"; } readonly property string _embeddedProfileName: (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"] || "embedded.mobileprovision" setupBuildEnvironment: { var prefixes = product.xcode ? [ product.xcode.platformPath + "/Developer", product.xcode.toolchainPath, product.xcode.developerPath ] : []; for (var i = 0; i < prefixes.length; ++i) { var codesign_allocate = prefixes[i] + "/usr/bin/codesign_allocate"; if (File.exists(codesign_allocate)) { var v = new ModUtils.EnvironmentVariable("CODESIGN_ALLOCATE"); v.value = codesign_allocate; v.set(); break; } } } Group { name: "Provisioning Profiles" prefix: provisioningProfilesPath + "/" files: ["*.mobileprovision", "*.provisionprofile"] } FileTagger { fileTags: ["codesign.entitlements"] patterns: ["*.entitlements"] } FileTagger { fileTags: ["codesign.provisioningprofile"] patterns: ["*.mobileprovision", "*.provisionprofile"] } Group { condition: enableCodeSigning Rule { multiplex: true inputs: ["codesign.entitlements", "codesign.embedded_provisioningprofile"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".xcent") fileTags: ["codesign.xcent"] } prepare: CodeSign.generateAppleEntitlementsCommands.apply(CodeSign, arguments) } Rule { multiplex: true condition: module._provisioningProfileAllowed inputs: ["codesign.provisioningprofile"] outputFileTags: ["codesign.embedded_provisioningprofile"] outputArtifacts: CodeSign.generateAppleProvisioningProfileOutputs(product, inputs) prepare: CodeSign.generateAppleProvisioningProfileCommands.apply(CodeSign, arguments) } } } qbs-src-3.3.1/share/qbs/modules/codesign/CodeSignModule.qbs0000644000175100017510000000404015232633614023203 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import "codesign.js" as CodeSign Module { condition: false property bool enableCodeSigning: false property string codesignName property string codesignPath: codesignName property stringList codesignFlags property string signingTimestamp PropertyOptions { name: "signingTimestamp" description: "URL of the RFC 3161 time stamp server." } property bool _canSignArtifacts: false // whether can sign individual actifacts } qbs-src-3.3.1/share/qbs/modules/codesign/codesign.js0000644000175100017510000006504215232633614021775 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var PropertyList = require("qbs.PropertyList"); var Utilities = require("qbs.Utilities"); function findSigningIdentities(searchString, team) { if (!searchString) return {}; var identities = Utilities.signingIdentities(); var matchedIdentities = {}; for (var key in identities) { var identity = identities[key]; if (team && ![identity.subjectInfo.O, identity.subjectInfo.OU].includes(team)) continue; if (searchString === key || (identity.subjectInfo.CN && identity.subjectInfo.CN.startsWith(searchString))) { matchedIdentities[key] = identity; } } return matchedIdentities; } function humanReadableIdentitySummary(identities) { return "\n\t" + Object.keys(identities).map(function (key) { return identities[key].subjectInfo.CN + " in team " + identities[key].subjectInfo.O + " (" + identities[key].subjectInfo.OU + ")"; }).join("\n\t"); } /** * Returns the best provisioning profile for code signing a binary with the given parameters. * Ideally, this should behave identically as Xcode but the algorithm is not documented * \l{https://developer.apple.com/library/ios/qa/qa1814/_index.html}{Automatic Provisioning} */ function findBestProvisioningProfile(product, files) { var actualSigningIdentity = product.codesign._actualSigningIdentity || {}; var teamIdentifier = product.codesign.teamIdentifier; var bundleIdentifier = product.bundle.identifier; var targetOS = product.qbs.targetOS; var buildVariant = product.qbs.buildVariant; var query = product.codesign.provisioningProfile; var profilePlatform = product.codesign._provisioningProfilePlatform; // Read all provisioning profiles on disk into plist objects in memory var profiles = files.map(function(filePath) { var plist = new PropertyList(); try { plist.readFromData(Utilities.smimeMessageContent(filePath)); return { data: plist.toObject(), filePath: filePath }; } finally { plist.clear(); } }); // Do a simple search by matching UUID or Name if (query) { for (var i = 0; i < profiles.length; ++i) { var obj = profiles[i]; if (obj.data && (obj.data.UUID === query || obj.data.Name === query)) return obj; } // If we asked for a specific provisioning profile, don't select one automatically return undefined; } // Provisioning profiles are not normally used with ad-hoc code signing or non-apps // We do these checks down here only for the automatic selection but not above because // if the user explicitly selects a provisioning profile it should be used no matter what if (actualSigningIdentity.SHA1 === "-" || !product.type.includes("application")) return undefined; // Filter out any provisioning profiles we know to be unsuitable from the start profiles = profiles.filter(function (profile) { var data = profile.data; if (actualSigningIdentity.subjectInfo) { var certCommonNames = (data["DeveloperCertificates"] || []).map(function (cert) { return Utilities.certificateInfo(cert).subjectInfo.CN; }); if (!certCommonNames.includes(actualSigningIdentity.subjectInfo.CN)) { console.log("Skipping provisioning profile with no matching certificate names for '" + actualSigningIdentity.subjectInfo.CN + "' (found " + certCommonNames.join(", ") + "): " + profile.filePath); return false; } } var platforms = data["Platform"] || []; if (platforms.length > 0 && profilePlatform && !platforms.includes(profilePlatform)) { console.log("Skipping provisioning profile for platform " + platforms.join(", ") + " (current platform " + profilePlatform + ")" + ": " + profile.filePath); return false; } if (teamIdentifier && !data["TeamIdentifier"].includes(teamIdentifier) && data["TeamName"] !== teamIdentifier) { console.log("Skipping provisioning profile for team " + data["TeamIdentifier"] + " (" + data["TeamName"] + ") (current team " + teamIdentifier + ")" + ": " + profile.filePath); return false; } if (Date.parse(data["ExpirationDate"]) <= Date.now()) { console.log("Skipping expired provisioning profile: " + profile.filePath); return false; } // Filter development vs distribution profiles; // though the certificate common names check should have been sufficient var isDebug = buildVariant === "debug"; if (data["Entitlements"]["get-task-allow"] !== isDebug) { console.log("Skipping provisioning profile for wrong debug mode: " + profile.filePath); return false; } var prefix = data["ApplicationIdentifierPrefix"]; var fullAppId = data["Entitlements"]["application-identifier"]; if ([prefix, bundleIdentifier].join(".") !== fullAppId && [prefix, "*"].join(".") !== fullAppId) { console.log("Skipping provisioning profile not matching full (" + [prefix, bundleIdentifier].join(".") + ") or wildcard (" + [prefix, "*"].join(".") + ") app ID (found " + fullAppId + "): " + profile.filePath); return false; } return true; }); // Sort by expiration date - sooner expiration dates come last profiles.sort(function(profileA, profileB) { var expA = Date.parse(profileA.data["ExpirationDate"]); var expB = Date.parse(profileB.data["ExpirationDate"]); if (expA < expB) return -1; if (expA > expB) return 1; return 0; }); // Sort by application identifier - wildcard profiles come last profiles.sort(function(profileA, profileB) { var idA = profileA.data["Entitlements"]["application-identifier"]; var idB = profileB.data["Entitlements"]["application-identifier"]; if (!idA.endsWith(".*") && idB.endsWith(".*")) return -1; if (idA.endsWith(".*") && !idB.endsWith(".*")) return 1; return 0; }); if (profiles.length) { console.log("Automatic provisioning using profile " + profiles[0].data.UUID + " (" + profiles[0].data.TeamName + " - " + profiles[0].data.Name + ") in product " + product.name); return profiles[0]; } } /** * Finds out the search paths for the `signtool.exe` utility supplied with * the Windows SDK's. */ function findBestSignToolSearchPaths(arch) { var searchPaths = []; var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows" ]; for (var keyIndex = 0; keyIndex < keys.length; ++keyIndex) { var re = /^v([0-9]+)\.([0-9]+)$/; var groups = Utilities.nativeSettingGroups(keys[keyIndex]).filter(function(version) { return version.match(re); }); groups.sort(function(a, b) { return Utilities.versionCompare(b.substring(1), a.substring(1)); }); function addSearchPath(searchPath) { if (File.exists(searchPath) && !searchPaths.includes(searchPath)) { searchPaths.push(searchPath); return true; } return false; } for (var groupIndex = 0; groupIndex < groups.length; ++groupIndex) { var fullKey = keys[keyIndex] + "\\" + groups[groupIndex]; var fullVersion = Utilities.getNativeSetting(fullKey, "ProductVersion"); if (fullVersion) { var installRoot = FileInfo.cleanPath( Utilities.getNativeSetting(fullKey, "InstallationFolder")); if (installRoot) { // Try to add the architecture-independent path at first. var searchPath = FileInfo.joinPaths(installRoot, "App Certification Kit"); if (!addSearchPath(searchPath)) { // Try to add the architecture-dependent paths at second. var binSearchPath = FileInfo.joinPaths(installRoot, "bin/" + fullVersion); if (!File.exists(binSearchPath)) { binSearchPath += ".0"; if (!File.exists(binSearchPath)) continue; } function kitsArchitectureSubDirectory(arch) { if (arch === "x86") return "x86"; else if (arch === "x86_64") return "x64"; else if (arch.startsWith("arm64")) return "arm64"; else if (arch.startsWith("arm")) return "arm"; } var archDir = kitsArchitectureSubDirectory(arch); searchPath = FileInfo.joinPaths(binSearchPath, archDir); addSearchPath(searchPath); } } } } } return searchPaths; } function prepareSign(project, product, inputs, outputs, input, output) { var cmd, cmds = []; if (!product.codesign.enableCodeSigning) return cmds; var isBundle = "bundle.content" in outputs; var artifacts = []; if (isBundle) { artifacts = [{ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName), fileName: product.bundle.bundleName }]; } else { artifacts = outputs["codesign.signed_artifact"]; } var isProductBundle = product.bundle && product.bundle.isBundle; var shouldSignArtifact = !isProductBundle || isBundle; var enableCodeSigning = product.codesign.enableCodeSigning; if (enableCodeSigning) { var actualSigningIdentity = product.codesign._actualSigningIdentity; if (!actualSigningIdentity) { throw "No codesigning identities (i.e. certificate and private key pairs) matching “" + product.codesign.signingIdentity + "†were found."; } // If this is a framework, we need to sign its versioned directory var subpath = ""; if (isBundle) { var isFramework = product.bundle.packageType === "FMWK"; if (isFramework) { subpath = product.bundle.contentsFolderPath; subpath = subpath.substring(product.bundle.bundleName.length); } } // The codesign tool behaves weirdly. It can sign a bundle with a single artifact, but if // say debug build variant is present, it starts complaining that it is not signed. // We could always sign everything, but again, in case of a framework (but not in case of // app or loadable bundle), codesign produces a warning that artifact is already signed. // So, we skip signing the release artifact and only sign if other build variants present. if (!shouldSignArtifact && artifacts.length == 1) { artifacts = []; } for (var i = 0; i < artifacts.length; ++i) { if (!shouldSignArtifact && artifacts[i].qbs && artifacts[i].qbs.buildVariant === "release") { continue; } var outputFilePath = artifacts[i].filePath; var outputFileName = artifacts[i].fileName; var args = ["--force", "--sign", actualSigningIdentity.SHA1]; // If signingTimestamp is undefined or empty, do not specify the flag at all - // this uses the system-specific default behavior var signingTimestamp = product.codesign.signingTimestamp; if (signingTimestamp) { // If signingTimestamp is an empty string, specify the flag but do // not specify a value - this uses a default Apple-provided server var flag = "--timestamp"; if (signingTimestamp) flag += "=" + signingTimestamp; args.push(flag); } for (var j in inputs["codesign.xcent"]) { args.push("--entitlements", inputs["codesign.xcent"][j].filePath); break; // there should only be one } args = args.concat(product.codesign.codesignFlags || []); args.push(outputFilePath + subpath); cmd = new Command(product.codesign.codesignPath, args); cmd.description = "codesign " + outputFileName + " (" + actualSigningIdentity.subjectInfo.CN + ")"; cmd.outputFilePath = outputFilePath; cmd.stderrFilterFunction = function(stderr) { return stderr.replace(/^.*: replacing existing signature\n$/, ""); }; cmds.push(cmd); } } if (isBundle) { cmd = new Command("touch", ["-c", outputFilePath]); cmd.silent = true; cmds.push(cmd); } return cmds; } function signApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var apkInput = inputs["android.package_unsigned"][0]; var apkOutput = outputs["android.package"][0]; var cmd; if (product.codesign.enableCodeSigning) { var args = ["sign", "--ks", product.codesign.keystorePath, "--ks-pass", "pass:" + product.codesign.keystorePassword, "--ks-key-alias", product.codesign.keyAlias, "--key-pass", "pass:" + product.codesign.keyPassword, "--out", apkOutput.filePath, apkInput.filePath]; cmd = new Command(product.codesign.apksignerFilePath, args); cmd.description = "signing " + apkOutput.fileName; } else { cmd = new JavaScriptCommand(); cmd.description = "copying without signing " + apkOutput.fileName; cmd.source = apkInput.filePath; cmd.target = apkOutput.filePath; cmd.silent = true; cmd.sourceCode = function() { // If enableCodeSigning is changed to false without any change to unsigned package then // the copy won't happen because of timestamps. So the target file needs file needs to // be removed to avoid it. File.remove(target); File.copy(source, target); } } return cmd; } function signAabPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var aabInput = inputs["android.package_unsigned"][0]; var aabOutput = outputs["android.package"][0]; var cmd; if (product.codesign.enableCodeSigning) { args = ["-sigalg", "SHA1withRSA", "-digestalg", "SHA1", "-keystore", product.codesign.keystorePath, "-storepass", product.codesign.keystorePassword, "-keypass", product.codesign.keyPassword, "-signedjar", aabOutput.filePath, aabInput.filePath, product.codesign.keyAlias]; cmd = new Command(product.codesign.jarsignerFilePath, args); cmd.description = "signing " + aabOutput.fileName; } else { cmd = new JavaScriptCommand(); cmd.description = "copying without signing " + aabOutput.fileName; cmd.source = aabInput.filePath; cmd.target = aabOutput.filePath; cmd.silent = true; cmd.sourceCode = function() { // If enableCodeSigning is changed to false without any change to unsigned package then // the copy won't happen because of timestamps. So the target file needs file needs to // be removed to avoid it. File.remove(target); File.copy(source, target); } } return cmd; } function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath, keystorePassword, keyPassword, keyAlias) { var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", keyAlias, "-storepass", keystorePassword, "-keypass", keyPassword, "-keyalg", "RSA", "-keysize", "2048", "-validity", "10000", "-dname", "CN=Android Debug,O=Android,C=US"]; return Process.shellQuote(keytoolFilePath, args); } function prepareSigntool(project, product, inputs, outputs, input, output) { var cmd, cmds = []; if (!product.codesign.enableCodeSigning) return cmds; var args = ["sign"]; var subjectName = product.codesign.subjectName; if (subjectName) args.push("/n", subjectName); var rootSubjectName = product.codesign.rootSubjectName; if (rootSubjectName) args.push("/r", rootSubjectName); var hashAlgorithm = product.codesign.hashAlgorithm; if (hashAlgorithm) args.push("/fd", hashAlgorithm); var signingTimestamp = product.codesign.signingTimestamp; if (signingTimestamp) args.push("/tr", signingTimestamp); var timestampAlgorithm = product.codesign.timestampAlgorithm; if (timestampAlgorithm) args.push("/td", timestampAlgorithm); var certificatePath = product.codesign.certificatePath; if (certificatePath) args.push("/f", certificatePath); var certificatePassword = product.codesign.certificatePassword; if (certificatePassword) args.push("/p", certificatePassword); var crossCertificatePath = product.codesign.crossCertificatePath; if (crossCertificatePath) args.push("/ac", crossCertificatePath); args = args.concat(product.codesign.codesignFlags || []); var outputArtifact = outputs["codesign.signed_artifact"][0]; args.push(outputArtifact.filePath); cmd = new Command(product.codesign.codesignPath, args); cmd.description = "signing " + outputArtifact.fileName; cmd.highlight = "linker"; cmds.push(cmd); return cmds; } function generateAppleProvisioningProfileOutputs() { var artifacts = []; var provisioningProfiles = (inputs["codesign.provisioningprofile"] || []) .map(function (a) { return a.filePath; }); var bestProfile = findBestProvisioningProfile(product, provisioningProfiles); var uuid = product.provisioningProfile; if (bestProfile) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.codesign._embeddedProfileName), fileTags: ["codesign.embedded_provisioningprofile"], codesign: { _provisioningProfileFilePath: bestProfile.filePath, _provisioningProfileData: JSON.stringify(bestProfile.data), } }); } else if (uuid) { throw "Your build settings specify a provisioning profile with the UUID '" + uuid + "', however, no such provisioning profile was found."; } else if (product._provisioningProfileRequired) { var hasProfiles = !!((inputs["codesign.provisioningprofile"] || []).length); var teamIdentifier = product.teamIdentifier; var codeSignIdentity = product.signingIdentity; if (hasProfiles) { if (codeSignIdentity) { console.warn("No provisioning profiles matching the bundle identifier '" + product.bundle.identifier + "' were found."); } else { console.warn("No provisioning profiles matching an applicable signing " + "identity were found."); } } else { if (codeSignIdentity) { if (teamIdentifier) { console.warn("No provisioning profiles with a valid signing identity " + "(i.e. certificate and private key pair) matching the " + "team ID '" + teamIdentifier + "' were found.") } else { console.warn("No provisioning profiles with a valid signing identity " + "(i.e. certificate and private key pair) were found."); } } else { console.warn("No non-expired provisioning profiles were found."); } } } return artifacts; } function generateAppleProvisioningProfileCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); var data = JSON.parse(output.codesign._provisioningProfileData); cmd.source = output.codesign._provisioningProfileFilePath; cmd.destination = output.filePath; cmd.description = "using provisioning profile " + data.Name + " (" + data.UUID + ")"; cmd.highlight = "filegen"; cmd.sourceCode = function() { File.copy(source, destination); }; return [cmd]; } function generateAppleEntitlementsCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "generating entitlements"; cmd.highlight = "codegen"; cmd.bundleIdentifier = product.bundle.identifier; cmd.signingEntitlements = (inputs["codesign.entitlements"] || []) .map(function (a) { return a.filePath; }); cmd.provisioningProfiles = (inputs["codesign.embedded_provisioningprofile"] || []) .map(function (a) { return a.filePath; }); cmd.platformPath = product.xcode ? product.xcode.platformPath : undefined; cmd.sdkPath = product.xcode ? product.xcode.sdkPath : undefined; cmd.sourceCode = function() { var i; var provData = {}; var provisionProfiles = inputs["codesign.embedded_provisioningprofile"]; for (i in provisionProfiles) { var plist = new PropertyList(); try { plist.readFromData(Utilities.smimeMessageContent( provisionProfiles[i].filePath)); provData = plist.toObject(); } finally { plist.clear(); } } var aggregateEntitlements = {}; // Start building up an aggregate entitlements plist from the files in the SDKs, // which contain placeholders in the same manner as Info.plist function entitlementsFileContents(path) { return File.exists(path) ? BundleTools.infoPlistContents(path) : undefined; } var entitlementsSources = []; if (platformPath) { entitlementsSources.push( entitlementsFileContents( FileInfo.joinPaths(platformPath, "Entitlements.plist"))); } if (sdkPath) { entitlementsSources.push( entitlementsFileContents( FileInfo.joinPaths(sdkPath, "Entitlements.plist"))); } for (i = 0; i < signingEntitlements.length; ++i) { entitlementsSources.push(entitlementsFileContents(signingEntitlements[i])); } for (i = 0; i < entitlementsSources.length; ++i) { var contents = entitlementsSources[i]; for (var key in contents) { if (contents.hasOwnProperty(key)) aggregateEntitlements[key] = contents[key]; } } contents = provData["Entitlements"]; for (key in contents) { if (contents.hasOwnProperty(key) && !aggregateEntitlements.hasOwnProperty(key)) aggregateEntitlements[key] = contents[key]; } // Expand entitlements variables with data from the provisioning profile var env = { "AppIdentifierPrefix": (provData["ApplicationIdentifierPrefix"] || "") + ".", "CFBundleIdentifier": bundleIdentifier }; DarwinTools.expandPlistEnvironmentVariables(aggregateEntitlements, env, true); // Anything with an undefined or otherwise empty value should be removed // Only JSON-formatted plists can have null values, other formats error out // This also follows Xcode behavior DarwinTools.cleanPropertyList(aggregateEntitlements); var plist = new PropertyList(); try { plist.readFromObject(aggregateEntitlements); plist.writeToFile(outputs["codesign.xcent"][0].filePath, "xml1"); } finally { plist.clear(); } }; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/codesign/signtool.qbs0000644000175100017510000000700415232633614022203 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.Host import qbs.ModUtils import qbs.Probes import "codesign.js" as CODESIGN CodeSignModule { condition: qbs.targetOS.includes("windows") && Host.os().includes("windows") && qbs.toolchain.includes("msvc") _canSignArtifacts: true Probes.BinaryProbe { id: signtoolProbe names: [codesignName] searchPaths: CODESIGN.findBestSignToolSearchPaths(Host.architecture()) } codesignName: "signtool" codesignPath: signtoolProbe.filePath property string subjectName PropertyOptions { name: "subjectName" description: "Name of the subject of the signing certificate." } property string rootSubjectName PropertyOptions { name: "rootSubjectName" description: "Name of the subject of the root certificate that the signing " + "certificate must chain to." } property string hashAlgorithm PropertyOptions { name: "hashAlgorithm" description: "Name of the hash algorithm used on the signing certificate." allowedValues: ["sha1", "sha256", "sha384", "sha512"] } property string timestampAlgorithm PropertyOptions { name: "timestampAlgorithm" description: "Name of the timestamp algorithm." allowedValues: ["sha1", "sha256"] } property path certificatePath PropertyOptions { name: "certificatePath" description: "Path to the signing certificate PFX file." } property string certificatePassword PropertyOptions { name: "certificatePassword" description: "Password to use when opening a certificate PFX file." } property path crossCertificatePath PropertyOptions { name: "crossCertificatePath" description: "Path to the additional certificate CER file." } validate: { if (enableCodeSigning && !File.exists(codesignPath)) { throw ModUtils.ModuleError("Could not find 'signtool' utility"); } } } qbs-src-3.3.1/share/qbs/modules/codesign/noop.qbs0000644000175100017510000000313315232633614021317 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CodeSignModule { condition: true priority: -100 } qbs-src-3.3.1/share/qbs/modules/innosetup/0000755000175100017510000000000015232633614020066 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/innosetup/InnoSetupModule.qbs0000644000175100017510000001321115232633614023665 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.Probes Module { condition: qbs.targetOS.includes("windows") Probes.InnoSetupProbe { id: innoSetupProbe } property path toolchainInstallPath: innoSetupProbe.path version: innoSetupProbe.version property var versionParts: version ? version.split('.').map(function (item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property string compilerName: "ISCC.exe" property string compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) property bool verboseOutput: false PropertyOptions { name: "verboseOutput" description: "display verbose output from the Inno Setup compiler" } property pathList includePaths PropertyOptions { name: "includePaths" description: "directories to add to the include search path" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the Inno Setup compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the Inno Setup compiler" } readonly property string executableSuffix: ".exe" validate: { if (!innoSetupProbe.found) { throw ModUtils.ModuleError("Could not find InnoSetup in Windows registry. Make " + "sure InnoSetup is installed correctly."); } var validator = new ModUtils.PropertyValidator("innosetup"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 3); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.validate(); } // Inno Setup Script FileTagger { patterns: ["*.iss"] fileTags: ["innosetup.iss"] } Rule { id: innoSetupCompiler inputs: ["innosetup.iss"] auxiliaryInputs: ["installable"] auxiliaryInputsFromDependencies: ["installable"] Artifact { fileTags: ["innosetup.exe", "application"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "executableSuffix")) } prepare: { var i; var args = [ "/O" + FileInfo.toNativeSeparators(FileInfo.path(output.filePath)), "/F" + FileInfo.toNativeSeparators(FileInfo.completeBaseName(output.fileName)) ]; if (!ModUtils.moduleProperty(product, "verboseOutput")) args.push("/Q"); var includePaths = ModUtils.moduleProperty(product, "includePaths"); for (i in includePaths) args.push("/I" + FileInfo.toNativeSeparators(includePaths[i])); // User-supplied defines var defines = ModUtils.moduleProperty(product, "defines"); for (i in defines) args.push("/D" + defines[i]); // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) args.push(flags[i]); args.push(FileInfo.toNativeSeparators(input.filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(input.filePath); return cmd; } } } qbs-src-3.3.1/share/qbs/modules/lex_yacc/0000755000175100017510000000000015232633614017631 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/lex_yacc/lexyacc.qbs0000644000175100017510000000226015232633614021770 0ustar runnerrunnerimport "lexyacc.js" as HelperFunctions Module { Depends { name: "cpp" } property bool enableCompilerWarnings: false property string lexBinary: "lex" property string yaccBinary: "yacc" property string outputTag: "c" property bool uniqueSymbolPrefix: false property string lexOutputFilePath property string yaccOutputFilePath property stringList lexFlags: [] property stringList yaccFlags: [] readonly property string outputDir: product.buildDirectory + "/lexyacc" Rule { inputs: ["lex.input"] outputFileTags: [product.lex_yacc.outputTag] outputArtifacts: HelperFunctions.lexOutputArtifacts(product, input) prepare: HelperFunctions.lexCommands.apply(HelperFunctions, arguments) } Rule { inputs: ["yacc.input"] outputFileTags: [product.lex_yacc.outputTag, "hpp"] outputArtifacts: HelperFunctions.yaccOutputArtifacts(product, input) prepare: HelperFunctions.yaccCommands.apply(HelperFunctions, arguments) } FileTagger { patterns: ["*.l"] fileTags: ["lex.input"]; } FileTagger { patterns: ["*.y"] fileTags: ["yacc.input"]; } } qbs-src-3.3.1/share/qbs/modules/lex_yacc/lexyacc.js0000644000175100017510000001173015232633614021621 0ustar runnerrunnervar FileInfo = require("qbs.FileInfo"); var TextFile = require("qbs.TextFile"); function unquote(s) { return s.startsWith('"') && s.endsWith('"') ? s.substr(1, s.length - 2) : s; } function readLexOptions(filePath) { var result = {}; var f = new TextFile(filePath, TextFile.ReadOnly); var regex = /^%option\s+([^ \t=]+)(?:\s*=\s*(\S+))?/; while (!f.atEof()) { var line = f.readLine(); var m = regex.exec(line); if (!m) { if (line === "%%") break; continue; } result[m[1]] = m[2] || true; } f.close(); return result; } function lexOutputFilePath(input, posixFileName, options) { var outDir = input.lex_yacc.outputDir; var fileName; if (options.outfile) { fileName = unquote(options.outfile); } else if (options.prefix) { fileName = FileInfo.baseName(posixFileName) + '.' + unquote(options.prefix) + '.' + FileInfo.suffix(posixFileName); } else if (input.lex_yacc.uniqueSymbolPrefix) { fileName = input.baseName; fileName += posixFileName; } else { fileName = posixFileName; } return FileInfo.joinPaths(outDir, fileName); } function readYaccOptions(filePath) { var result = {}; var f = new TextFile(filePath, TextFile.ReadOnly); var regex = /^%output\s+(.+)/; while (!f.atEof()) { var line = f.readLine(); var m = regex.exec(line); if (!m) { if (line === "%%") break; continue; } result.output = m[1]; break; } f.close(); return result; } function yaccOutputFilePath(input, posixFileName, options) { var outDir = input.lex_yacc.outputDir; var fileName; if (options.output) { var outputFileName = unquote(options.output); var suffix = FileInfo.suffix(posixFileName); if (suffix === "c") { fileName = outputFileName; } else { fileName = FileInfo.completeBaseName(outputFileName) + '.' + suffix + FileInfo.suffix(outputFileName).slice(1); } } else if (input.lex_yacc.uniqueSymbolPrefix) { fileName = input.baseName + posixFileName.slice(1); } else { fileName = posixFileName; } return FileInfo.joinPaths(outDir, fileName); } function yaccOutputArtifacts(product, input) { var src = { fileTags: [product.lex_yacc.outputTag], lex_yacc: {}, }; var options = readYaccOptions(input.filePath); if (!options.output && input.lex_yacc.yaccOutputFilePath) { options.output = input.lex_yacc.yaccOutputFilePath; src.lex_yacc.useOutputFromModule = true; } var hdr = { filePath: yaccOutputFilePath(input, "y.tab.h", options), fileTags: ["hpp"], }; src.filePath = yaccOutputFilePath(input, "y.tab.c", options); src.cpp = { includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir), warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none", }; return [hdr, src]; } function yaccCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = input.lex_yacc.yaccFlags; args.push("-d"); var impl = outputs[input.lex_yacc.outputTag][0]; if (impl.lex_yacc.useOutputFromModule) args.push("-o" + input.lex_yacc.yaccOutputFilePath); else if (input.lex_yacc.uniqueSymbolPrefix) args.push("-b", input.baseName, "-p", input.baseName); args.push(input.filePath); var cmd = new Command(input.lex_yacc.yaccBinary, args); cmd.workingDirectory = input.lex_yacc.outputDir; cmd.description = "generating " + impl.fileName + " and " + outputs["hpp"][0].fileName; return [cmd]; } function lexOutputArtifacts(product, input) { var output = { fileTags: [product.lex_yacc.outputTag], lex_yacc: {}, }; var options = readLexOptions(input.filePath); if (!options.outfile && input.lex_yacc.lexOutputFilePath) { options.outfile = input.lex_yacc.lexOutputFilePath; output.lex_yacc.useOutfileFromModule = true; } output.filePath = lexOutputFilePath(input, "lex.yy.c", options); output.cpp = { includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir), warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none", }; return [output]; } function lexCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = input.lex_yacc.lexFlags; if (output.lex_yacc.useOutfileFromModule) args.push("-o" + input.lex_yacc.lexOutputFilePath); else if (input.lex_yacc.uniqueSymbolPrefix) args.push("-P" + input.baseName, "-o" + output.filePath); args.push(input.filePath); var cmd = new Command(input.lex_yacc.lexBinary, args); cmd.workingDirectory = input.lex_yacc.outputDir; cmd.description = "generating " + output.fileName; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/Sanitizers/0000755000175100017510000000000015232633614020175 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Sanitizers/address/0000755000175100017510000000000015232633614021622 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Sanitizers/address/asan.qbs0000644000175100017510000000632315232633614023257 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities Module { Depends { name: "cpp" } property bool enabled: true readonly property bool _supported: qbs.toolchain.includes("gcc") || qbs.toolchain.includes("clang-cl") || (qbs.toolchain.includes("msvc") && Utilities.versionCompare(cpp.compilerVersion, "19.28.29500.0") >= 0) readonly property bool _enabled: enabled && _supported property string detectUseAfterReturn: "always" PropertyOptions { name: "detectUseAfterReturn" description: "Whether to detect problems with stack use after return from a function" allowedValues: ["never", "runtime", "always"] } property bool detectUseAfterScope: true cpp.driverFlags: { var flags = []; if (!_enabled) return flags; if (qbs.toolchain.includes("msvc") && !qbs.toolchain.includes("clang-cl")) { flags.push("/fsanitize=address"); if (detectUseAfterReturn !== "never") flags.push("/fsanitize-address-use-after-return"); return flags; } flags.push("-fsanitize=address", "-fno-omit-frame-pointer"); if (detectUseAfterScope) flags.push("-fsanitize-address-use-after-scope"); if (detectUseAfterReturn) { if (qbs.toolchain.includes("llvm")) { var minVersion = qbs.toolchain.contains("xcode") ? "14" : "13"; if (Utilities.versionCompare(cpp.compilerVersion, minVersion) >= 0) flags.push("-fsanitize-address-use-after-return=" + detectUseAfterReturn); } else if (detectUseAfterReturn === "never") { flags.push("--param", "asan-use-after-return=0"); } } return flags; } } qbs-src-3.3.1/share/qbs/modules/qnx/0000755000175100017510000000000015232633614016650 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/qnx/qnx.qbs0000644000175100017510000001206215232633614020166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Probes import qbs.Utilities Module { Probes.PathProbe { id: qnxSdkProbe names: ["qnx700", "qnx660", "qnx650"] searchPaths: Host.os().includes("windows") ? [Environment.getEnv("USERPROFILE"), Environment.getEnv("SystemDrive")] : [Environment.getEnv("HOME"), "/opt"] } Probe { id: qnxTargetOsProbe property string qnxSdkDir: sdkDir property stringList targets: [] configure: { if (qnxSdkDir) { var validEntries = []; var entries = File.directoryEntries( FileInfo.joinPaths(qnxSdkDir, "target"), File.Dirs | File.NoDotAndDotDot); for (var i = 0; i < entries.length; ++i) { if (/^qnx[0-9]$/.test(entries[i])) validEntries.push(entries[i]); } validEntries.sort(); validEntries.reverse(); targets = validEntries; found = targets.length > 0; } else { found = false; } } } version: qnxSdkProbe.found ? qnxSdkProbe.fileName.substr(3, 3).split("").join(".") : undefined readonly property bool qnx7: version ? Utilities.versionCompare(version, "7") >= 0 : false property string sdkDir: qnxSdkProbe.filePath property string hostArch: qnx7 ? "x86_64" : "x86" property string hostOs: { if (Host.os().includes("linux")) return "linux"; if (Host.os().includes("macos")) return "darwin"; if (Host.os().includes("windows")) return qnx7 ? "win64" : "win32"; } property string targetOs: qnxTargetOsProbe.targets[0] property string compilerName: "gcc" property string configurationDir: FileInfo.joinPaths(Environment.getEnv("HOME"), ".qnx") property string hostDir: FileInfo.joinPaths(sdkDir, "host", hostOs, hostArch) property string targetDir: FileInfo.joinPaths(sdkDir, "target", targetOs) property var buildEnv: ({ "QNX_HOST": hostDir, "QNX_TARGET": targetDir, "QNX_CONFIGURATION": configurationDir }) qbs.sysroot: targetDir validate: { if (!sdkDir) { throw ModUtils.ModuleError("Could not find a QNX SDK in any of the following " + "locations:\n\t" + qnxSdkProbe.candidatePaths.join("\n\t") + "\nInstall the QNX SDK to one of the above locations, " + "or set the qnx.sdkDir property to a valid QNX SDK " + "location."); } if (!hostOs) { throw ModUtils.ModuleError("Host operating system '" + Host.os() + "' is not supported by the QNX SDK."); } else if (!File.exists(hostDir)) { throw ModUtils.ModuleError("Detected host tools operating system '" + hostOs + "' and architecture '" + hostArch + "' directory is not " + "present in the QNX SDK installed at '" + sdkDir + "' in the expected location '" + hostDir + "'; did you forget to install it?"); } if (!targetOs) throw ModUtils.ModuleError("Could not find any QNX targets in '" + targetDir + "'"); } } qbs-src-3.3.1/share/qbs/modules/nsis/0000755000175100017510000000000015232633614017016 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/nsis/NSISModule.qbs0000644000175100017510000002257015232633614021455 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Utilities Module { condition: qbs.targetOS.includes("windows") property path toolchainInstallPath: Utilities.getNativeSetting(registryKey) version: (versionMajor !== undefined && versionMinor !== undefined) ? (versionMajor + "." + versionMinor) : undefined property var versionParts: [ versionMajor, versionMinor, versionPatch, versionBuild ] property int versionMajor: Utilities.getNativeSetting(registryKey, "VersionMajor") property int versionMinor: Utilities.getNativeSetting(registryKey, "VersionMinor") property int versionPatch: Utilities.getNativeSetting(registryKey, "VersionBuild") property int versionBuild: Utilities.getNativeSetting(registryKey, "VersionRevision") property string compilerName: "makensis" property string compilerPath: compilerName property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "errors", "warnings", "info", "all"] } property bool disableConfig: false PropertyOptions { name: "disableConfig" description: "disable inclusion of nsisconf.nsh" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the NSIS compiler" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the NSIS compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the NSIS compiler" } property string compressor: "default" PropertyOptions { name: "compressor" description: "the compression algorithm used to compress files/data in the installer" allowedValues: ["default", "zlib", "zlib-solid", "bzip2", "bzip2-solid", "lzma", "lzma-solid"] } property string executableSuffix: ".exe" // Private properties property string registryKey: { if (!Host.os().includes("windows")) return undefined; var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS" ]; for (var i in keys) { if (Utilities.getNativeSetting(keys[i])) return keys[i]; } } validate: { var validator = new ModUtils.PropertyValidator("nsis"); // Only *require* the toolchain install path on Windows // On other (Unix-like) operating systems it'll probably be in the PATH if (qbs.targetOS.includes("windows")) validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.setRequiredProperty("versionBuild", versionBuild); validator.addVersionValidator("version", version, 2, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addRangeValidator("versionBuild", versionBuild, 0); validator.validate(); } setupBuildEnvironment: { if (product.nsis.toolchainInstallPath) { var v = new ModUtils.EnvironmentVariable("PATH", ";", true); v.prepend(product.nsis.toolchainInstallPath); v.prepend(FileInfo.joinPaths(product.nsis.toolchainInstallPath, "bin")); v.set(); } } // NSIS Script File FileTagger { patterns: ["*.nsi"] fileTags: ["nsi"] } // NSIS Header File FileTagger { patterns: ["*.nsh"] fileTags: ["nsh"] } Rule { id: nsisCompiler multiplex: true inputs: ["nsi"] auxiliaryInputs: ["installable"] auxiliaryInputsFromDependencies: ["installable"] Artifact { fileTags: ["nsissetup", "application"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty( product, "executableSuffix")) } prepare: { var i; var args = []; // Prefix character for makensis options var opt = product.moduleProperty("qbs", "hostOS").includes("windows") ? "/" : "-"; if (ModUtils.moduleProperty(product, "disableConfig")) { args.push(opt + "NOCONFIG"); } var warningLevel = ModUtils.moduleProperty(product, "warningLevel"); var warningLevels = ["none", "errors", "warnings", "info", "all"]; if (warningLevel !== "normal") { var level = warningLevels.indexOf(warningLevel); if (level < 0) { throw("Unexpected warning level '" + warningLevel + "'."); } else { args.push(opt + "V" + level); } } var enableQbsDefines = ModUtils.moduleProperty(product, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push(opt + "D" + prefix + prop + "=" + val); } } } // Users are likely to need this var arch = product.moduleProperty("qbs", "architecture"); args.push(opt + "Dqbs.architecture=" + arch); // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x86_64" || arch === "ia64") { args.push(opt + "DWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperty(product, "defines"); for (i in defines) { args.push(opt + "D" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } // Override the compression algorithm if needed var compressor = ModUtils.moduleProperty(product, "compressor"); if (compressor !== "default") { var compressorFlag = opt + "XSetCompressor /FINAL "; if (compressor.endsWith("-solid")) { compressorFlag += "/SOLID "; } args.push(compressorFlag + compressor.split('-')[0]); } var inputFileNames = []; for (i in inputs.nsi) { inputFileNames.push(inputs.nsi[i].fileName); args.push(FileInfo.toNativeSeparators(inputs.nsi[i].filePath, product.moduleProperty("qbs", "hostOS"))); } // Output file name - this goes last to override any OutFile command in the script args.push(opt + "XOutFile " + output.filePath); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + inputFileNames.join(", "); cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } } qbs-src-3.3.1/share/qbs/modules/installpaths/0000755000175100017510000000000015232633614020550 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/installpaths/debian.js0000644000175100017510000000154115232633614022331 0ustar runnerrunner var File = require("qbs.File"); var Process = require("qbs.Process"); const debianArchMap = { "arm": "arm", "arm64": "arm64", "hppa": "hppa", "ia64": "ia64", "mips": "mips", "mips64": "mips64", "ppc64": "ppc64", "riscv": "riscv64", "s390x": "s390x", "sparc": "sparc", "sparc64": "sparc64", "x86": "i386", "x86_64": "amd64", }; function isDebian() { return File.exists("/etc/debian_version"); } // logic yoinked from meson function getDebianLibPath(qbsArchitecture) { var proc = new Process() const debianArch = debianArchMap[qbsArchitecture] if (debianArch === undefined) return "lib"; const args = ["-qDEB_TARGET_MULTIARCH", "-A", debianArch]; if (proc.exec("dpkg-architecture", args, true) == 0) { return "lib/" + proc.readStdOut().trim(); } return "lib"; } qbs-src-3.3.1/share/qbs/modules/installpaths/linux.qbs0000644000175100017510000000113415232633614022415 0ustar runnerrunnerimport "base.qbs" as Base import "debian.js" as Debian Base { priority: 0 condition: qbs.targetOS.contains("linux") lib: libdirProbe.found ? libdirProbe.libDir : base Probe { id: libdirProbe condition: autotetect property string libDir configure: { if (Debian.isDebian()) { libDir = Debian.getDebianLibPath(qbs.architecture); } else if (File.exists("/usr/lib64")) { libDir = "lib64"; } else { libDir = "lib"; } found = true; } } } qbs-src-3.3.1/share/qbs/modules/installpaths/base.qbs0000644000175100017510000000155615232633614022200 0ustar runnerrunnerModule { priority: -100 property bool autotetect: false property string bin: "bin" property string etc: "etc" property string include: "include" property string lib: "lib" property string topLevelProjectName: { var p = project; while (p.parent !== undefined) { p = p.parent; } return p.name; } property string subdir: topLevelProjectName.toLowerCase(); property string libexec: "libexec/" + subdir property string plugins: lib + "/" + subdir + "/plugins" property string headers: include + "/" + subdir property string share: "share/" + subdir property string applications: "Applications" property string frameworks: library + "/Frameworks" property string loadableModules: library + "/" + topLevelProjectName + "/PlugIns" property string library: "Library" } qbs-src-3.3.1/share/qbs/modules/cpp/0000755000175100017510000000000015232633614016624 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/cpp/ios-gcc.qbs0000644000175100017510000000752115232633614020664 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Utilities DarwinGCC { priority: 1 condition: qbs.targetOS.includes('ios') && qbs.toolchain && qbs.toolchain.includes('gcc') minimumIosVersion: { if (Host.architecture() == "armv7a") return "6.0"; // XCode 12 requres version (at least 8.0) to be present in the -target triplet // when compiling for ios-simulator if (xcode.present && Utilities.versionCompare(xcode.version, "12.0") >= 0) return "8.0"; } targetSystem: { return "ios" + (minimumIosVersion || "") + (qbs.targetOS.includes('ios-simulator') ? "-simulator" : ""); } minimumDarwinVersion: minimumIosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("ios-simulator") ? "-mios-simulator-version-min" : "-miphoneos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("ios-simulator") ? "-ios_simulator_version_min" : "-iphoneos_version_min" libcxxAvailable: base && (!minimumDarwinVersion || Utilities.versionCompare(minimumDarwinVersion, "5") >= 0) platformObjcFlags: base.concat(simulatorObjcFlags) platformObjcxxFlags: base.concat(simulatorObjcFlags) // Private properties readonly property stringList simulatorObjcFlags: { // default in Xcode and also required for building 32-bit Simulator binaries with ARC // since the default ABI version is 0 for 32-bit targets return qbs.targetOS.includes("ios-simulator") ? ["-fobjc-abi-version=2", "-fobjc-legacy-dispatch"] : []; } Rule { condition: !product.qbs.targetOS.includes("ios-simulator") inputsFromDependencies: ["bundle.content"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".ipa") fileTags: ["ipa"] } prepare: { var cmd = new Command("PackageApplication", [input.filePath, "-o", output.filePath]); cmd.description = "creating ipa"; cmd.highlight = "codegen"; return cmd; } } } qbs-src-3.3.1/share/qbs/modules/cpp/qnx-qcc.qbs0000644000175100017510000000710115232633614020704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo UnixGCC { Depends { name: "qnx" } condition: qbs.targetOS.includes("qnx") && qbs.toolchain && qbs.toolchain.includes("qcc") priority: 1 distributionIncludePaths: FileInfo.joinPaths(qnx.targetDir, "usr", "include") toolchainInstallPath: FileInfo.joinPaths(qnx.hostDir, "usr", "bin") sysroot: qnx.targetDir sysrootFlags: sysroot ? [systemIncludeFlag + FileInfo.joinPaths(sysroot, "usr", "include")] : [] cCompilerName: "qcc" + compilerExtension cxxCompilerName: (qnx.qnx7 ? "q++" : "QCC") + compilerExtension targetDriverFlags: qnxTarget ? ["-V" + qnxTarget] : [] systemIncludeFlag: !qnx.qnx7 ? includeFlag : base property string qnxTarget: qbs.architecture ? qnx.compilerName + "_" + targetSystem + qnxTargetArchName : undefined property string qnxTargetArchName: { switch (qbs.architecture) { case "arm64": return "aarch64le"; case "armv7a": return "armv7le"; case "x86": case "x86_64": return qbs.architecture; } } // QNX doesn't support Objective-C or Objective-C++ and qcc/q++ don't use toolchainPrefix compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) compilerPathByLanguage: ({ "c": FileInfo.joinPaths(toolchainInstallPath, cCompilerName), "cpp": FileInfo.joinPaths(toolchainInstallPath, cxxCompilerName), "objc": undefined, "objcpp": undefined, "asm_cpp": FileInfo.joinPaths(toolchainInstallPath, cCompilerName) }) toolchainPrefix: target + "-" targetVendor: ["x86", "x86_64"].includes(qbs.architecture) ? "pc" : base targetSystem: "nto" targetAbi: "qnx" + qnx.version + (qnxTargetArchName === "armv7le" ? "eabi" : "") buildEnv: qnx.buildEnv probeEnv: buildEnv setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = product.cpp.buildEnv[key]; v.set(); } } } qbs-src-3.3.1/share/qbs/modules/cpp/cpp.js0000644000175100017510000006300115232633614017744 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var BinaryFile = require("qbs.BinaryFile"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function languageVersion(versionArray, knownValues, lang) { if (!versionArray) return undefined; var versions = [].uniqueConcat(versionArray); if (versions.length === 1) return versions[0]; for (var i = 0; i < knownValues.length; ++i) { var candidate = knownValues[i]; if (versions.includes(candidate)) return candidate; } var version = versions[0]; console.debug("Randomly choosing '" + version + "' from list of unknown " + lang + " version strings (" + versions + ")"); return version; } function extractMacros(output, regexp) { var m = {}; output.trim().split(/\r?\n/g).map(function(line) { if (regexp) { var match = regexp.exec(line); if (!match) return; line = match[1]; } var prefix = "#define "; if (!line.startsWith(prefix)) return; var index = line.indexOf(" ", prefix.length); if (index !== -1) m[line.substr(prefix.length, index - prefix.length)] = line.substr(index + 1); }); return m; } function relativePath(baseDirectory, filePath) { if (FileInfo.isAbsolutePath(filePath)) return FileInfo.relativePath(baseDirectory, filePath); return filePath; } function assemblerOutputTags(needsListingFiles) { var tags = ["obj"]; if (needsListingFiles) tags.push("lst"); return tags; } function compilerOutputTags(withListingFiles, withCxxModules) { var tags = ["obj", "intermediate_obj", "time_trace"]; if (withListingFiles) tags.push("lst"); if (withCxxModules) tags = tags.concat(["compiled-module", "modulemap", "moduleinfo"]); return tags; } function applicationLinkerOutputTags(needsLinkerMapFile) { var tags = ["application"]; if (needsLinkerMapFile) tags.push("mem_map"); return tags; } function dynamicLibraryLinkerOutputTags() { return ["dynamiclibrary", "dynamiclibrary_import"]; } function staticLibraryLinkerOutputTags() { return ["staticlibrary"]; } function resourceCompilerOutputTags() { return ["res"]; } function precompiledHeaderOutputTags(lang, generateObjects) { var tags = [lang + "_pch"]; if (generateObjects) tags.push("obj"); return tags; }; function assemblerOutputArtifacts(input) { var artifacts = []; artifacts.push({ fileTags: ["obj"], filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + input.cpp.objectSuffix) }); if (input.cpp.generateAssemblerListingFiles) { artifacts.push({ fileTags: ["lst"], filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + input.cpp.assemblerListingSuffix) }); } return artifacts; } function cxxModulesArtifacts(input) { var artifacts = []; if (input.cpp.forceUseCxxModules === false) return artifacts; if (input.cpp.compiledModuleSuffix === undefined || input.cpp.moduleOutputFlag === undefined || input.cpp.moduleFileFlag === undefined) { console.warn("Skip additional artifacts for '" + input.fileName + "' since '" + input.qbs.toolchainType + "' toolchain does not support C++ Modules."); return artifacts; } var moduleInformation = CppModulesScanner.apply(input); if (moduleInformation.providesModule || moduleInformation.requiresModules.length > 0) { artifacts.push({ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + input.cpp.moduleMapSuffix), fileTags: ["modulemap"], // we can't use maps here only strings and lists cpp: { _providesModule: moduleInformation.providesModule, _isInterfaceModule: moduleInformation.isInterfaceModule, _requiresModules : moduleInformation.requiresModules, }, }) } if (input.fileTags.includes("cppm")) { const moduleName = moduleInformation.providesModule ? moduleInformation.providesModule : undefined; if (moduleName) { const moduleFileName = moduleName.replace(':', '-'); artifacts.push({ filePath: FileInfo.joinPaths("cxx-modules", moduleFileName + product.cpp.compiledModuleSuffix), fileTags: ["compiled-module"], }) artifacts.push({ filePath: FileInfo.joinPaths("cxx-modules", moduleFileName + product.cpp.moduleInfoSuffix), fileTags: ["moduleinfo"], }) } else { console.warn("File '" + input.fileName + "' has 'cppm' tag, but does not " + "provide a module interface unit or partition"); } } return artifacts; } function compilerOutputArtifacts(input, inputs, withCxxModules) { var objTags = input.fileTags.includes("cpp_intermediate_object") ? ["intermediate_obj"] : ["obj"]; if (inputs) { if (inputs.c || inputs.objc) objTags.push("c_obj"); if (inputs.cpp || inputs.objcpp || inputs.cppm) objTags.push("cpp_obj"); } var artifacts = [{ fileTags: objTags, filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + input.cpp.objectSuffix) }]; if (input.cpp.generateCompilerListingFiles) { artifacts.push({ fileTags: ["lst"], filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + input.cpp.compilerListingSuffix) }); } if (input.cpp.enableTimeTrace && input.cpp._supportsTimeTrace) { artifacts.push({ fileTags: ["time_trace"], filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + ".time_trace.json") }); } if (withCxxModules) artifacts = artifacts.concat(cxxModulesArtifacts(input)); return artifacts; } function applicationLinkerOutputArtifacts(product) { var artifacts = [{ fileTags: ["application"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.applicationFilePath(product)) }]; if (product.cpp.generateLinkerMapFile) { artifacts.push({ fileTags: ["mem_map"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.cpp.linkerMapSuffix) }); } return artifacts; } function dynamicLibraryLinkerOutputArtifacts(product) { return [{ fileTags: ["dynamiclibrary"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.dynamicLibraryFilePath(product)) }, { fileTags: ["dynamiclibrary_import"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.importLibraryFilePath(product)), alwaysUpdated: false }]; } function staticLibraryLinkerOutputArtifacts(product) { return [{ fileTags: ["staticlibrary"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)) }]; } function resourceCompilerOutputArtifacts(input) { return [{ fileTags: ["res"], filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.completeBaseName + input.cpp.resourceSuffix) }]; } function precompiledHeaderOutputArtifacts(input, product, lang, generateObjects) { var artifacts = [{ fileTags: [lang + "_pch"], filePath: product.name + "_" + lang + product.cpp.precompiledHeaderSuffix }]; if (generateObjects) { artifacts.push({ fileTags: ["obj"], filePath: Utilities.getHash(input.completeBaseName) + "_" + lang + input.cpp.objectSuffix }); } return artifacts; } function collectLibraryDependencies(product) { var seen = {}; var seenObjectFiles = []; var result = []; function addFilePath(filePath, wholeArchive, productName) { result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName }); } function addArtifactFilePaths(dep, artifacts) { if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive; var artifactsAreImportLibs = artifacts.length > 0 && artifacts[0].fileTags.includes("dynamiclibrary_import"); for (var i = 0; i < artifactFilePaths.length; ++i) { addFilePath(artifactFilePaths[i], wholeArchive, artifactsAreImportLibs ? dep.name : undefined); } } function addExternalLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return (a instanceof Array) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } function handleExternalLibraries(tag, libSuffix, objSuffix) { var externalLibs = sanitizedModuleListProperty(obj, "cpp", tag) || []; externalLibs.forEach(function(libName) { var isObjectFile = objSuffix && libName.endsWith(objSuffix); if (isObjectFile) { if (seenObjectFiles.includes(libName)) return; seenObjectFiles.push(libName); } if (!libName.endsWith(libSuffix) && !isObjectFile && !libName.startsWith('@')) libName += libSuffix; addFilePath(libName, false); }); } handleExternalLibraries("staticLibraries", obj.moduleProperty("cpp", "staticLibrarySuffix"), obj.moduleProperty("cpp", "objectSuffix")); handleExternalLibraries("dynamicLibraries", obj.moduleProperty("cpp", "dynamicLibraryImportSuffix")); handleExternalLibraries("libraries", obj.moduleProperty("cpp", "dynamicLibraryImportSuffix")); } function traverse(dep) { if (seen.hasOwnProperty(dep.name)) return; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var staticLibraryArtifacts = dep.artifacts["staticlibrary"] || dep.artifacts["objectlibrary"]; var dynamicLibraryArtifacts = staticLibraryArtifacts ? null : dep.artifacts["dynamiclibrary_import"]; if (staticLibraryArtifacts) { seen[dep.name] = true; dep.dependencies.forEach(traverse); addArtifactFilePaths(dep, staticLibraryArtifacts); if (product.cpp.importPrivateLibraries) addExternalLibs(dep); } else if (dynamicLibraryArtifacts) { seen[dep.name] = true; addArtifactFilePaths(dep, dynamicLibraryArtifacts); } } product.dependencies.forEach(traverse); addExternalLibs(product); return result; } function collectAbsoluteLibraryDependencyPaths(product) { var paths = collectLibraryPaths(product); var deps = collectLibraryDependencies(product); return deps.map(function(dep) { var filePath = dep.filePath; if (FileInfo.isAbsolutePath(filePath)) return filePath; for (var i = 0; i < paths.length; ++i) { var fullPath = FileInfo.joinPaths(paths[i], filePath); if (File.exists(fullPath)) return fullPath; } return filePath; }); } function collectDefines(input) { var allDefines = []; var platformDefines = input.cpp.platformDefines; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); var defines = input.cpp.defines; if (defines) allDefines = allDefines.uniqueConcat(defines); return allDefines; } function collectIncludePaths(input) { var allIncludePaths = []; var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); var builtIns = input.cpp.compilerIncludePaths; return allIncludePaths.filter(function(p) { return !builtIns.includes(p); }); } function collectSystemIncludePaths(input) { var allIncludePaths = []; var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); var distributionIncludePaths = input.cpp.distributionIncludePaths; if (distributionIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths); var builtIns = input.cpp.compilerIncludePaths; return allIncludePaths.filter(function(p) { return !builtIns.includes(p); }); } function collectPreincludePaths(input) { return input.cpp.prefixHeaders; } function collectLibraryPaths(product) { var allLibraryPaths = []; var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths); var distributionLibraryPaths = product.cpp.distributionLibraryPaths; if (distributionLibraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths); return allLibraryPaths; } function collectLinkerScriptPaths(inputs) { return inputs.linkerscript ? inputs.linkerscript.map(function(script) { return script.filePath; }) : []; } function collectLinkerObjectPaths(inputs) { return inputs.obj ? inputs.obj.filter(function(obj) { return !obj.fileTags.includes("objectlibrary"); }) .map(function(obj) { return obj.filePath; }) : []; } function collectResourceObjectPaths(inputs) { return inputs.res ? inputs.res.map(function(res) { return res.filePath; }) : []; } function collectLibraryDependenciesArguments(product) { var deps = collectLibraryDependencies(product); return deps.map(function(dep) { return product.cpp.libraryDependencyFlag + dep.filePath }) } function collectDefinesArguments(input) { var defines = collectDefines(input); return defines.map(function(define) { return input.cpp.defineFlag + define }); } function collectIncludePathsArguments(input) { var paths = collectIncludePaths(input); return paths.map(function(path) { return input.cpp.includeFlag + path }); } function collectSystemIncludePathsArguments(input, flag) { flag = (flag === undefined) ? input.cpp.systemIncludeFlag : flag; var paths = collectSystemIncludePaths(input); return paths.map(function(path) { return flag + path }); } function collectPreincludePathsArguments(input, split) { var paths = collectPreincludePaths(input); if (split) { var args = []; for (var i = 0; i < paths.length; ++i) args.push(input.cpp.preincludeFlag, paths[i]); return args; } else { return paths.map(function(path) { return input.cpp.preincludeFlag + path }); } } function collectLibraryPathsArguments(product, flag) { flag = (flag === undefined) ? product.cpp.libraryPathFlag : flag; var paths = collectLibraryPaths(product); return paths.map(function(path) { return flag + path }); } function collectLinkerScriptPathsArguments(product, inputs, split, flag) { flag = (flag === undefined) ? product.cpp.linkerScriptFlag : flag; var paths = collectLinkerScriptPaths(inputs); if (split) { var args = []; for (var i = 0; i < paths.length; ++i) args.push(flag, paths[i]); return args; } else { return paths.map(function(path) { return flag + path }); } } function collectLinkerObjectPathsArguments(product, inputs, flag) { flag = (flag === undefined) ? "" : flag; var paths = collectLinkerObjectPaths(product); return paths.map(function(path) { return flag + path }); } function collectMiscCompilerArguments(input, tag) { if (tag === "cppm") tag = "cpp"; return [].concat(ModUtils.moduleProperty(input, "platformFlags"), ModUtils.moduleProperty(input, "flags"), ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag)); } function collectMiscAssemblerArguments(input, tag) { return [].concat(ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag)); } function collectMiscDriverArguments(config) { return [].concat(ModUtils.moduleProperty(config, "platformDriverFlags"), ModUtils.moduleProperty(config, "driverFlags"), ModUtils.moduleProperty(config, "targetDriverFlags")); } function collectMiscLinkerArguments(product) { return [].concat(ModUtils.moduleProperty(product, "driverLinkerFlags")); } function collectMiscEscapableLinkerArguments(product) { return [].concat(ModUtils.moduleProperty(product, "platformLinkerFlags"), ModUtils.moduleProperty(product, "linkerFlags")); } function supportsArchitecture(architecture, knownArchitectures) { for (var i = 0; i < knownArchitectures.length; ++i) { if (architecture.startsWith("arm")) { if (architecture.startsWith(knownArchitectures[i])) return true; } else { if (architecture === knownArchitectures[i]) return true; } } return false; } function prepareModuleInfo(moduleInformation, input, output, product) { var command = new JavaScriptCommand() command.moduleInformation = moduleInformation command.outPath = output.filePath command.description = "generating module info for " + input.fileName command.highlight = "filegen" command.sourceCode = function() { var file = new TextFile(outPath, TextFile.WriteOnly); file.write(JSON.stringify(moduleInformation, undefined, 4)); file.close(); } return command; } function prepareModuleMap(moduleInformation, input, mm, product) { var modulesFromDeps = {}; product.dependencies.forEach(function(dep){ (dep.artifacts["compiled-module"] || []).forEach(function(a) { modulesFromDeps[a.completeBaseName.replace('-', ':')] = a.filePath; }); }); var generateModuleMap = new JavaScriptCommand() generateModuleMap.outPath = mm.filePath generateModuleMap.moduleInformation = moduleInformation; generateModuleMap.compiledModuleSuffix = product.cpp.compiledModuleSuffix; generateModuleMap.moduleInfoSuffix = product.cpp.moduleInfoSuffix; generateModuleMap.moduleOutputFlag = product.cpp.moduleOutputFlag; generateModuleMap.moduleFileFlag = product.cpp.moduleFileFlag; generateModuleMap.toolchain = product.qbs.toolchain; generateModuleMap.toolchainType = product.qbs.toolchainType; generateModuleMap.modulesFromDeps = modulesFromDeps; generateModuleMap.description = "generating module map for " + input.fileName generateModuleMap.highlight = "filegen" generateModuleMap.sourceCode = function() { function moduleFileOption(moduleName) { return moduleFileFlag.replace("%module%", moduleName); } function moduleOutputOption(moduleName) { return moduleOutputFlag.replace("%module%", moduleName); } var content = ""; if (toolchainType === "gcc" || toolchainType === "mingw") content += "$root .\n"; const isModule = input.fileTags.includes("cppm"); function modulePath(moduleName) { return FileInfo.joinPaths( product.buildDirectory, "cxx-modules", moduleName.replace(':', "-") + compiledModuleSuffix); } const providesModule = moduleInformation.providesModule if (isModule && providesModule !== undefined) { if (toolchainType === "msvc") { if (moduleInformation.isInterfaceModule) content += "-interface\n"; else content += "-internalPartition\n"; } content += moduleOutputOption(providesModule) + modulePath(providesModule) + "\n"; } function isHeaderImport(mod) { return mod.length > 2 && (mod[0] == '<' && mod[mod.length - 1] == '>' || mod[0] == '"' && mod[mod.length - 1] == '"') } function processImport(mod) { if (!isHeaderImport(mod)) { const moduleFile = modulesFromDeps[mod] || modulePath(mod); content += moduleFileOption(mod) + moduleFile + "\n"; function getModuleInfo(moduleFile) { const moduleInfoPath = FileInfo.joinPaths( FileInfo.path(moduleFile), FileInfo.completeBaseName(moduleFile) + moduleInfoSuffix); var file = new TextFile(moduleInfoPath, TextFile.ReadOnly); const moduleInfo = JSON.parse(file.readAll()); file.close(); return moduleInfo; } function processImportsRecursive(moduleFile) { // can we do better rather than pass info via a file? const moduleInfo = getModuleInfo(moduleFile); const requiresModules = moduleInfo['requiresModules'] || []; requiresModules.forEach(function(importModule) { const importModuleFile = modulesFromDeps[importModule] || modulePath(importModule); content += moduleFileOption(importModule) + importModuleFile + "\n"; processImportsRecursive(importModuleFile); }); } processImportsRecursive(moduleFile); } } moduleInformation.requiresModules.forEach(processImport); // converts UTF string to an array of bytes function encode(string) { var bytes = []; for (var i = 0; i < string.length; i++) { bytes.push(string.charCodeAt(i)); } return bytes; } // MinGW fails if file contains \r on Windows, so we use Unix line-endings on all platforms // and thus we use BinaryFile instead of TextFile here var file = new BinaryFile(outPath, TextFile.WriteOnly); file.write(encode(content)); file.close(); } return generateModuleMap; } function prepareModules(project, product, inputs, outputs, input, output) { var commands = []; // module map is present for both cppm and regular cpp files if they use modules const moduleMapOutputs = outputs["modulemap"]; if (moduleMapOutputs === undefined) return commands; const cppModuleMap = moduleMapOutputs[0]; if (cppModuleMap === undefined) return commands; const moduleInformation = { providesModule: cppModuleMap.cpp._providesModule, isInterfaceModule: cppModuleMap.cpp._isInterfaceModule, requiresModules: cppModuleMap.cpp._requiresModules, }; // module info json is present only for cppm var cppModuleInfo = outputs["moduleinfo"]; if (cppModuleInfo) commands.push(prepareModuleInfo(moduleInformation, input, cppModuleInfo[0], product)); commands.push(prepareModuleMap(moduleInformation, input, cppModuleMap, product)); return commands; } qbs-src-3.3.1/share/qbs/modules/cpp/sdcc.qbs0000644000175100017510000001321215232633614020246 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Probes import "cpp.js" as Cpp import "sdcc.js" as SDCC CppModule { condition: qbs.toolchain && qbs.toolchain.includes("sdcc") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["sdcc"] } Probes.SdccProbe { id: sdccProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture } Properties { condition: sdccProbe.found qbs.architecture: sdccProbe.architecture } qbs.targetPlatform: "none" compilerVersionMajor: sdccProbe.versionMajor compilerVersionMinor: sdccProbe.versionMinor compilerVersionPatch: sdccProbe.versionPatch endianness: sdccProbe.endianness compilerDefinesByLanguage: sdccProbe.compilerDefinesByLanguage compilerIncludePaths: sdccProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName property string linkerMode: "automatic" compilerName: "sdcc" + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: toolchainDetails.assemblerName + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: toolchainDetails.linkerName + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) archiverName: "sdar" + compilerExtension archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" staticLibrarySuffix: ".lib" executableSuffix: ".ihx" objectSuffix: ".rel" imageFormat: "ihx" enableExceptions: false enableRtti: false defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-isystem" preincludeFlag: "-include" libraryDependencyFlag: "-l" libraryPathFlag: "-L" linkerScriptFlag: "-f" toolchainDetails: SDCC.toolchainDetails(qbs) knownArchitectures: ["hcs8", "mcs51", "stm8"] Rule { id: assembler inputs: ["asm"] outputFileTags: SDCC.extraCompilerOutputTags().concat( Cpp.assemblerOutputTags(generateAssemblerListingFiles)) outputArtifacts: SDCC.extraCompilerOutputArtifacts(input).concat( Cpp.assemblerOutputArtifacts(input)) prepare: SDCC.prepareAssembler.apply(SDCC, arguments) } FileTagger { patterns: ["*.s", "*.a51", "*.asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: SDCC.extraCompilerOutputTags().concat( Cpp.compilerOutputTags(generateCompilerListingFiles)) outputArtifacts: SDCC.extraCompilerOutputArtifacts(input).concat( Cpp.compilerOutputArtifacts(input)) prepare: SDCC.prepareCompiler.apply(SDCC, arguments) } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: SDCC.extraApplicationLinkerOutputTags().concat( Cpp.applicationLinkerOutputTags(generateLinkerMapFile)) outputArtifacts: SDCC.extraApplicationLinkerOutputArtifacts(product).concat( Cpp.applicationLinkerOutputArtifacts(product)) prepare: SDCC.prepareLinker.apply(SDCC, arguments) } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: SDCC.prepareArchiver.apply(SDCC, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/CppModule.qbs0000644000175100017510000006004415232633614021227 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // base for Cpp modules import qbs.FileInfo import qbs.ModUtils import qbs.Utilities import qbs.WindowsUtils import "cpp.js" as Cpp import "setuprunenv.js" as SetupRunEnv Module { condition: false Depends { name: "cpufeatures" } version: compilerVersion property string compilerVersion: [compilerVersionMajor, compilerVersionMinor, compilerVersionPatch].join(".") property int compilerVersionMajor property int compilerVersionMinor property int compilerVersionPatch property string warningLevel : 'all' // 'none', 'all' property bool treatWarningsAsErrors : false property bool enableSuspiciousLinkerFlagWarnings: true property string architecture: qbs.architecture property string endianness property string machineType // undocumented property string imageFormat // undocumented property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property bool enableReproducibleBuilds: false property bool separateDebugInformation: false property pathList prefixHeaders property bool useCPrecompiledHeader: true property bool useCxxPrecompiledHeader: true property bool useObjcPrecompiledHeader: true property bool useObjcxxPrecompiledHeader: true property bool forceUseCxxModules: false property bool forceUseImportStd: false property bool forceUseImportStdCompat: false property stringList stdModulesFiles property string moduleOutputFlag // undocumented property string moduleFileFlag // undocumented property bool treatSystemHeadersAsDependencies: false property stringList defines property stringList platformDefines: qbs.enableDebugCode ? [] : ["NDEBUG"] property stringList compilerDefines: compilerDefinesByLanguage ? ModUtils.flattenDictionary(compilerDefinesByLanguage["c"]) : [] property var compilerDefinesByLanguage: undefined PropertyOptions { name: "compilerDefinesByLanguage" description: "preprocessor macros that are defined when using this particular compiler" } property stringList enableCompilerDefinesByLanguage: [] property string windowsApiCharacterSet property string windowsApiFamily property stringList windowsApiAdditionalPartitions property bool requireAppContainer property string minimumWindowsVersion PropertyOptions { name: "minimumWindowsVersion" description: "A version number in the format [major].[minor] indicating the earliest \ version of Windows that the product should run on. Defines WINVER, \ _WIN32_WINNT, and _WIN32_WINDOWS, and applies a version number to the \ linker flags /SUBSYSTEM and /OSVERSION for MSVC or \ --major-subsystem-version, --minor-subsystem-version, \ --major-os-version and --minor-os-version for MinGW. \ If undefined, compiler defaults will be used." } property string minimumOsxVersion property string minimumMacosVersion: minimumOsxVersion PropertyOptions { name: "minimumMacosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of macOS that the product should run on. passes -mmacosx-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumIosVersion: qbs.architecture == "armv7a" ? "6.0" : undefined PropertyOptions { name: "minimumIosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of iOS that the product should run on. passes -miphoneos-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumWatchosVersion PropertyOptions { name: "minimumWatchosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of watchOS that the product should run on. if undefined, compiler \ defaults will be used." } property string minimumTvosVersion: "6.0" PropertyOptions { name: "minimumTvosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of tvOS that the product should run on. if undefined, compiler \ defaults will be used." } property string minimumAndroidVersion // not used, undocumented PropertyOptions { name: "minimumAndroidVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml." } property string maximumAndroidVersion // not used, undocumented PropertyOptions { name: "maximumAndroidVersion" description: "a version number in the format [major].[minor] indicating the latest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml. if undefined, no upper limit will \ be set." } property string toolchainInstallPath PropertyOptions { name: "toolchainInstallPath" description: "a path to the directory where the toolchain executable files are located." } property pathList includePaths property pathList systemIncludePaths property pathList distributionIncludePaths property pathList compilerIncludePaths property pathList libraryPaths property pathList distributionLibraryPaths property pathList compilerLibraryPaths property pathList frameworkPaths property pathList systemFrameworkPaths property pathList distributionFrameworkPaths property pathList compilerFrameworkPaths property stringList systemRunPaths: [] property string archiverName property string archiverPath: archiverName property string assemblerName property string assemblerPath: assemblerName property string compilerName property string compilerPath: compilerName property var compilerPathByLanguage property stringList compilerWrapper property string linkerName property string linkerPath: linkerName property stringList linkerWrapper property string staticLibraryPrefix: "" property string dynamicLibraryPrefix: "" property string loadableModulePrefix: "" property string executablePrefix: "" property string staticLibrarySuffix: "" property string dynamicLibrarySuffix: "" property string archSuffix: "" property string loadableModuleSuffix: "" property string executableSuffix: "" property string debugInfoSuffix: "" property string debugInfoBundleSuffix: "" property string variantSuffix: "" property string dynamicLibraryImportSuffix: ".lib" property string objectSuffix: ".o" property string linkerMapSuffix: ".map" property string compilerListingSuffix: ".lst" property string assemblerListingSuffix: ".lst" property string resourceSuffix: ".res" property string compiledModuleSuffix property string moduleMapSuffix: ".modulemap" property string moduleInfoSuffix: ".moduleinfo.json" property string precompiledHeaderSuffix property bool createSymlinks: true property stringList dynamicLibraries property stringList staticLibraries property stringList libraries property stringList frameworks // list of frameworks, will be linked with '-framework ' property stringList weakFrameworks // list of weakly-linked frameworks, will be linked with '-weak_framework ' property string rpathOrigin property stringList rpaths property stringList rpathLinkDirs property string sonamePrefix: "" property bool useRPaths: true property bool useRPathLink property string rpathLinkFlag property bool discardUnusedData property bool removeDuplicateLibraries: true property string defineFlag property string includeFlag property string systemIncludeFlag property string preincludeFlag property string libraryDependencyFlag property string libraryPathFlag property string linkerScriptFlag property stringList knownArchitectures: [] property var toolchainDetails property string compilerExtension: FileInfo.executableSuffix() property string linkerMode: "automatic" PropertyOptions { name: "linkerMode" allowedValues: ["automatic", "manual"] description: "Controls whether to automatically use an appropriate compiler frontend " + "in place of the system linker when linking binaries. The default is \"automatic\", " + "which chooses either the C++ compiler, C compiler, or system linker specified by " + "the linkerName/linkerPath properties, depending on the type of object files " + "present on the linker command line. \"manual\" allows you to explicitly specify " + "the linker using the linkerName/linkerPath properties, and allows linker flags " + "passed to the linkerFlags and platformLinkerFlags properties to be escaped " + "manually (using -Wl or -Xlinker) instead of automatically based on the selected " + "linker." } property stringList archiverFlags property stringList assemblerFlags PropertyOptions { name: "assemblerFlags" description: "additional flags for the assembler" } property stringList cppFlags PropertyOptions { name: "cppFlags" description: "additional flags for the C preprocessor" } property stringList cFlags PropertyOptions { name: "cFlags" description: "additional flags for the C compiler" } property stringList cxxFlags PropertyOptions { name: "cxxFlags" description: "additional flags for the C++ compiler" } property stringList objcFlags PropertyOptions { name: "objcFlags" description: "additional flags for the Objective-C compiler" } property stringList objcxxFlags PropertyOptions { name: "objcxxFlags" description: "additional flags for the Objective-C++ compiler" } property stringList commonCompilerFlags PropertyOptions { name: "commonCompilerFlags" description: "flags added to all compilation independently of the language" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional linker flags" } property stringList driverFlags PropertyOptions { name: "driverFlags" description: "additional compiler driver flags" } property stringList driverLinkerFlags PropertyOptions { name: "driverLinkerFlags" description: "additional compiler driver flags used for linking only" } property bool generateLinkerMapFile: false PropertyOptions { name: "generateLinkerMapFile" description: "generate linker map file" } property bool generateCompilerListingFiles: false PropertyOptions { name: "generateCompilerListingFiles" description: "generate compiler listing files" } property bool generateAssemblerListingFiles: false PropertyOptions { name: "generateAssemblerListingFiles" description: "generate assembler listing files" } property bool enableTimeTrace: false PropertyOptions { name: "enableTimeTrace" description: "enable Clang time trace profiling (generates .time_trace.json files)" } property bool _supportsTimeTrace: false property bool positionIndependentCode: true PropertyOptions { name: "positionIndependentCode" description: "generate position independent code" } property string entryPoint PropertyOptions { name: "entryPoint" description: "entry point symbol for an executable or dynamic library" } property string runtimeLibrary PropertyOptions { name: "runtimeLibrary" description: "determine which runtime library to use" allowedValues: ['static', 'dynamic'] } property string visibility: 'default' PropertyOptions { name: "visibility" description: "export symbols visibility level" allowedValues: ['default', 'hidden', 'hiddenInlines', 'minimal'] } property stringList cLanguageVersion PropertyOptions { name: "cLanguageVersion" description: "The version of the C standard with which the code must comply." } property stringList cxxLanguageVersion PropertyOptions { name: "cxxLanguageVersion" description: "The version of the C++ standard with which the code must comply." } property bool useLanguageVersionFallback PropertyOptions { name: "useLanguageVersionFallback" description: "whether to explicitly use the language standard version fallback values in " + "compiler command line invocations" } property string cxxStandardLibrary PropertyOptions { name: "cxxStandardLibrary" allowedValues: ["libstdc++", "libc++"] description: "version of the C++ standard library to use" } property bool enableExceptions: true PropertyOptions { name: "enableExceptions" description: "enable/disable exception handling (enabled by default)" } property string exceptionHandlingModel: "default" PropertyOptions { name: "exceptionHandlingModel" description: "the kind of exception handling to be used by the compiler" } property bool enableRtti // Platform properties. Those are intended to be set by the toolchain setup // and are prepended to the corresponding user properties. property stringList platformAssemblerFlags property stringList platformCommonCompilerFlags property stringList platformCFlags property stringList platformCxxFlags property stringList platformObjcFlags property stringList platformObjcxxFlags property stringList platformLinkerFlags property stringList platformDriverFlags // Apple platforms properties property bool automaticReferenceCounting PropertyOptions { name: "automaticReferenceCounting" description: "whether to enable Automatic Reference Counting (ARC) for Objective-C" } property bool requireAppExtensionSafeApi PropertyOptions { name: "requireAppExtensionSafeApi" description: "whether to require app-extension-safe APIs only" } property bool allowUnresolvedSymbols property bool combineCSources: false property bool combineCxxSources: false property bool combineObjcSources: false property bool combineObjcxxSources: false // Those are set internally by different cpp module implementations property stringList targetAssemblerFlags property stringList targetDriverFlags property stringList targetLinkerFlags property bool _skipAllChecks: false // Internal property bool validateTargetTriple: true // undocumented property bool importPrivateLibraries: true Group { name: "std modules" condition: stdModulesFiles !== undefined files: stdModulesFiles fileTags: "cppm" } Scanner { inputs: ["cpp", "cppm", "cpp_pch_src", "c", "c_pch_src", "objcpp", "objcpp_pch_src", "objc", "objc_pch_src", "rc"] pluginName: "cpp_include_scanner" recursive: true cacheIsPerFile: false } // TODO: The following four rules could use a convenience base item if rule properties // were available in Artifact items and prepare scripts. Rule { multiplex: true inputs: ["c.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".c" fileTags: ["c"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["c.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["cpp.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["cpp.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["objc.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".m" fileTags: ["objc"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["objc.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["objcpp.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".mm" fileTags: ["objccpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["objcpp.combine"], output.filePath); }; return [cmd]; } } // This rule does not create any commands, but is needed for transitive dependencies // on object libraries to work. While it could be argued that such dependencies // should be exported instead, we have traditionally supported the "private dependency" // use case for static libs, and we want object libraries to work as a // drop-in replacement for these. Rule { inputsFromDependencies: ["objectlibrary", "staticlibrary", "dynamiclibrary_import"] outputFileTags: "objectlibrary" outputArtifacts: [] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } FileTagger { patterns: ["*.c"] fileTags: combineCSources ? ["c.combine"] : ["c"] } FileTagger { patterns: ["*.C", "*.cpp", "*.cxx", "*.c++", "*.cc"] fileTags: combineCxxSources ? ["cpp.combine"] : ["cpp"] } FileTagger { patterns: ["*.cppm", "*.ixx"] fileTags: ["cppm"] } FileTagger { patterns: ["*.m"] fileTags: combineObjcSources ? ["objc.combine"] : ["objc"] } FileTagger { patterns: ["*.mm"] fileTags: combineObjcxxSources ? ["objcpp.combine"] : ["objcpp"] } FileTagger { patterns: ["*.h", "*.H", "*.hpp", "*.hxx", "*.h++"] fileTags: ["hpp"] } property var validateFunc: { return function() { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("architecture", architecture, "you might want to re-run 'qbs-setup-toolchains'"); validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === Utilities.canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid. You must use the canonical name '" + Utilities.canonicalArchitecture(architecture) + "'"); validator.setRequiredProperty("endianness", endianness); validator.setRequiredProperty("compilerDefinesByLanguage", compilerDefinesByLanguage); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); if (minimumWindowsVersion) { validator.addVersionValidator("minimumWindowsVersion", minimumWindowsVersion, 2, 2); validator.addCustomValidator("minimumWindowsVersion", minimumWindowsVersion, function (v) { return !v || v === WindowsUtils.canonicalizeVersion(v); }, "'" + minimumWindowsVersion + "' is invalid. Did you mean '" + WindowsUtils.canonicalizeVersion(minimumWindowsVersion) + "'?"); } validator.validate(); if (minimumWindowsVersion && !WindowsUtils.isValidWindowsVersion(minimumWindowsVersion)) { console.warn("Unknown Windows version '" + minimumWindowsVersion + "'; expected one of: " + WindowsUtils.knownWindowsVersions().map(function (a) { return '"' + a + '"'; }).join(", ") + ". See https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version"); } if (knownArchitectures && knownArchitectures.length > 0) { var isSupported = Cpp.supportsArchitecture(qbs.architecture, knownArchitectures); if (!isSupported) { throw ModUtils.ModuleError("Unsupported architecture: '" + qbs.architecture + "'"); } } } } validate: { return validateFunc(); } setupRunEnvironment: { SetupRunEnv.setupRunEnvironment(product, config); } Parameter { property bool link } Parameter { property bool linkWholeArchive } Parameter { property string symbolLinkMode } } qbs-src-3.3.1/share/qbs/modules/cpp/keil.js0000644000175100017510000011105315232633614020107 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function isMcs51Architecture(architecture) { return architecture === "mcs51"; } function isMcs251Architecture(architecture) { return architecture === "mcs251"; } function isMcsArchitecture(architecture) { return isMcs51Architecture(architecture) || isMcs251Architecture(architecture); } function isC166Architecture(architecture) { return architecture === "c166"; } function isArmArchitecture(architecture) { return architecture.startsWith("arm"); } function isMcsCompiler(compilerPath) { var base = FileInfo.baseName(compilerPath).toLowerCase(); return base === "c51" || base === "cx51" || base === "c251"; } function isC166Compiler(compilerPath) { return FileInfo.baseName(compilerPath).toLowerCase() === "c166"; } function isArmCCCompiler(compilerPath) { return FileInfo.baseName(compilerPath).toLowerCase() === "armcc"; } function isArmClangCompiler(compilerPath) { return FileInfo.baseName(compilerPath).toLowerCase() === "armclang"; } function preincludeFlag(compilerPath) { if (isArmCCCompiler(compilerPath)) return "--preinclude"; else if (isArmClangCompiler(compilerPath)) return "-include"; } function toolchainDetails(qbs) { var architecture = qbs.architecture; if (isMcs51Architecture(architecture)) { return { "imageFormat": "omf", "linkerMapSuffix":".m51", "objectSuffix": ".obj", "executableSuffix": ".abs", "compilerName": "c51", "assemblerName": "a51", "linkerName": "bl51", "archiverName": "lib51" }; } else if (isMcs251Architecture(architecture)) { return { "imageFormat": "omf", "linkerMapSuffix":".m51", "objectSuffix": ".obj", "executableSuffix": ".abs", "compilerName": "c251", "assemblerName": "a251", "linkerName": "l251", "archiverName": "lib251" }; } else if (isC166Architecture(architecture)) { return { "imageFormat": "omf", "linkerMapSuffix":".m66", "objectSuffix": ".obj", "executableSuffix": ".abs", "compilerName": "c166", "assemblerName": "a166", "linkerName": "l166", "archiverName": "lib166" }; } else if (isArmArchitecture(architecture)) { return { "imageFormat": "elf", "linkerMapSuffix":".map", "objectSuffix": ".o", "executableSuffix": ".axf", "disassemblerName": "fromelf", "compilerName": "armcc", "assemblerName": "armasm", "linkerName": "armlink", "archiverName": "armar" }; } } function guessArmCCArchitecture(targetArchArm, targetArchThumb) { var arch = "arm"; if (targetArchArm === "4" && targetArchThumb === "0") arch += "v4"; else if (targetArchArm === "4" && targetArchThumb === "1") arch += "v4t"; else if (targetArchArm === "5" && targetArchThumb === "2") arch += "v5t"; else if (targetArchArm === "6" && targetArchThumb === "3") arch += "v6"; else if (targetArchArm === "6" && targetArchThumb === "4") arch += "v6t2"; else if (targetArchArm === "0" && targetArchThumb === "3") arch += "v6m"; else if (targetArchArm === "7" && targetArchThumb === "4") arch += "v7r"; else if (targetArchArm === "0" && targetArchThumb === "4") arch += "v7m"; return arch; } function guessArmClangArchitecture(targetArchArm, targetArchProfile) { targetArchProfile = targetArchProfile.replace(/'/g, ""); var arch = "arm"; if (targetArchArm !== "" && targetArchProfile !== "") arch += "v" + targetArchArm + targetArchProfile.toLowerCase(); return arch; } function guessArchitecture(macros) { if (macros["__C51__"]) return "mcs51"; else if (macros["__C251__"]) return "mcs251"; else if (macros["__C166__"]) return "c166"; else if (macros["__CC_ARM"] === "1") return guessArmCCArchitecture(macros["__TARGET_ARCH_ARM"], macros["__TARGET_ARCH_THUMB"]); else if (macros["__clang__"] === "1" && macros["__arm__"] === "1") return guessArmClangArchitecture(macros["__ARM_ARCH"], macros["__ARM_ARCH_PROFILE"]); } function guessEndianness(macros) { if (macros["__C51__"] || macros["__C251__"]) { // The 8051 processors are 8-bit. So, the data with an integer type // represented by more than one byte is stored as big endian in the // Keil toolchain. See for more info: // * http://www.keil.com/support/man/docs/c51/c51_ap_2bytescalar.htm // * http://www.keil.com/support/man/docs/c51/c51_ap_4bytescalar.htm // * http://www.keil.com/support/man/docs/c251/c251_ap_2bytescalar.htm // * http://www.keil.com/support/man/docs/c251/c251_ap_4bytescalar.htm return "big"; } else if (macros["__C166__"]) { // The C166 processors are 16-bit. So, the data with an integer type // represented by more than one byte is stored as little endian in the // Keil toolchain. See for more info: // * http://www.keil.com/support/man/docs/c166/c166_ap_ints.htm // * http://www.keil.com/support/man/docs/c166/c166_ap_longs.htm return "little"; } else if (macros["__CC_ARM"]) { return macros["__BIG_ENDIAN"] ? "big" : "little"; } else if (macros["__clang__"] && macros["__arm__"]) { switch (macros["__BYTE_ORDER__"]) { case "__ORDER_BIG_ENDIAN__": return "big"; case "__ORDER_LITTLE_ENDIAN__": return "little"; } } } function guessVersion(macros) { if (macros["__C51__"] || macros["__C251__"]) { var mcsVersion = macros["__C51__"] || macros["__C251__"]; return { major: parseInt(mcsVersion / 100), minor: parseInt(mcsVersion % 100), patch: 0 } } else if (macros["__C166__"]) { var xcVersion = macros["__C166__"]; return { major: parseInt(xcVersion / 100), minor: parseInt(xcVersion % 100), patch: 0 } } else if (macros["__CC_ARM"] || macros["__clang__"]) { var armVersion = macros["__ARMCC_VERSION"]; return { major: parseInt(armVersion / 1000000), minor: parseInt(armVersion / 10000) % 100, patch: parseInt(armVersion) % 10000 } } } function dumpMcsCompilerMacros(compilerFilePath, tag) { // C51 or C251 compiler support only C language. if (tag === "cpp") return {}; // Note: The C51 or C251 compiler does not support the predefined // macros dumping. So, we do it with the following trick, where we try // to create and compile a special temporary file and to parse the console // output with the own magic pattern: (""|"key"|"value"|""). var outputDirectory = new TemporaryDir(); var outputFilePath = FileInfo.fromNativeSeparators(FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c")); var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly); outputFile.writeLine("#define VALUE_TO_STRING(x) #x"); outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)"); // Predefined keys for C51 and C251 compilers, see details: // * https://www.keil.com/support/man/docs/c51/c51_pp_predefmacroconst.htm // * https://www.keil.com/support/man/docs/c251/c251_pp_predefmacroconst.htm var keys = ["__C51__", "__CX51__", "__C251__", "__MODEL__", "__STDC__", "__FLOAT64__", "__MODSRC__"]; // For C51 compiler. outputFile.writeLine("#if defined(__C51__) || defined(__CX51__)"); outputFile.writeLine("# define VAR_NAME_VALUE(var) \"(\"\"\"\"|\"#var\"|\"VALUE(var)\"|\"\"\"\")\""); for (var i in keys) { var key = keys[i]; outputFile.writeLine("# if defined (" + key + ")"); outputFile.writeLine("# pragma message (VAR_NAME_VALUE(" + key + "))"); outputFile.writeLine("# endif"); } outputFile.writeLine("#endif"); // For C251 compiler. outputFile.writeLine("#if defined(__C251__)"); outputFile.writeLine("# define VAR_NAME_VALUE(var) \"\"|#var|VALUE(var)|\"\""); for (var i in keys) { var key = keys[i]; outputFile.writeLine("# if defined (" + key + ")"); outputFile.writeLine("# warning (VAR_NAME_VALUE(" + key + "))"); outputFile.writeLine("# endif"); } outputFile.writeLine("#endif"); outputFile.close(); var process = new Process(); process.exec(compilerFilePath, [outputFilePath], false); File.remove(outputFilePath); var map = {}; process.readStdOut().trim().split(/\r?\n/g).map(function(line) { var parts = line.split("\"|\"", 4); if (parts.length === 4) map[parts[1]] = parts[2]; }); return map; } function dumpC166CompilerMacros(compilerFilePath, tag) { // C166 compiler support only C language. if (tag === "cpp") return {}; // Note: The C166 compiler does not support the predefined // macros dumping. Also, it does not support the '#pragma' and // '#message|warning|error' directives properly (it is impossible // to print to console the value of macro). // So, we do it with the following trick, where we try // to create and compile a special temporary file and to parse the console // output with the own magic pattern, e.g: // // *** WARNING C320 IN LINE 41 OF c51.c: __C166__ // *** WARNING C2 IN LINE 42 OF c51.c: '757': unknown #pragma/control, line ignored // // where the '__C166__' is a key, and the '757' is a value. var outputDirectory = new TemporaryDir(); var outputFilePath = FileInfo.fromNativeSeparators(outputDirectory.path() + "/dump-macros.c"); var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly); // Predefined keys for C166 compiler, see details: // * https://www.keil.com/support/man/docs/c166/c166_pp_predefmacroconst.htm var keys = ["__C166__", "__DUS__", "__MAC__", "__MOD167__", "__MODEL__", "__MODV2__", "__SAVEMAC__", "__STDC__"]; // For C166 compiler. outputFile.writeLine("#if defined(__C166__)"); for (var i in keys) { var key = keys[i]; outputFile.writeLine("# if defined (" + key + ")"); outputFile.writeLine("# warning " + key); outputFile.writeLine("# pragma " + key); outputFile.writeLine("# endif"); } outputFile.writeLine("#endif"); outputFile.close(); function extractKey(line, knownKeys) { for (var i in keys) { var key = knownKeys[i]; var regexp = new RegExp("^\\*\\*\\* WARNING C320 IN LINE .+: (" + key + ")$"); var match = regexp.exec(line); if (match) return key; } }; function extractValue(line) { var regexp = new RegExp("^\\*\\*\\* WARNING C2 IN LINE .+'(.+)':.+$"); var match = regexp.exec(line); if (match) return match[1]; }; var process = new Process(); process.exec(compilerFilePath, [outputFilePath], false); File.remove(outputFilePath); var lines = process.readStdOut().trim().split(/\r?\n/g); var map = {}; for (var i = 0; i < lines.length; ++i) { // First line should contains the macro key. var keyLine = lines[i]; var key = extractKey(keyLine, keys); if (!key) continue; i += 1; if (i >= lines.length) break; // Second line should contains the macro value. var valueLine = lines[i]; var value = extractValue(valueLine); if (!value) continue; map[key] = value; } return map; } function dumpArmCCCompilerMacros(compilerFilePath, tag, nullDevice) { var args = [ "-E", "--list-macros", "--cpu=cortex-m0", nullDevice ]; if (tag === "cpp") args.push("--cpp"); var p = new Process(); p.exec(compilerFilePath, args, false); return Cpp.extractMacros(p.readStdOut()); } function dumpArmClangCompilerMacros(compilerFilePath, tag, nullDevice) { var args = [ "--target=arm-arm-none-eabi", "-mcpu=cortex-m0", "-dM", "-E", "-x", ((tag === "cpp") ? "c++" : "c"), nullDevice ]; var p = new Process(); p.exec(compilerFilePath, args, false); return Cpp.extractMacros(p.readStdOut()); } function dumpMacros(compilerFilePath, tag, nullDevice) { if (isMcsCompiler(compilerFilePath)) return dumpMcsCompilerMacros(compilerFilePath, tag, nullDevice); else if (isC166Compiler(compilerFilePath)) return dumpC166CompilerMacros(compilerFilePath, tag, nullDevice); else if (isArmCCCompiler(compilerFilePath)) return dumpArmCCCompilerMacros(compilerFilePath, tag, nullDevice); else if (isArmClangCompiler(compilerFilePath)) return dumpArmClangCompilerMacros(compilerFilePath, tag, nullDevice); return {}; } function dumpMcsCompilerIncludePaths(compilerFilePath) { var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, "inc"); return [includePath]; } function dumpC166CompilerIncludePaths(compilerFilePath) { // Same as for MCS compiler. return dumpMcsCompilerIncludePaths(compilerFilePath); } function dumpArmCCCompilerIncludePaths(compilerFilePath) { var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, "include"); return [includePath]; } function dumpArmClangCompilerIncludePaths(compilerFilePath, nullDevice) { var args = [ "--target=arm-arm-none-eabi", "-mcpu=cortex-m0", "-v", "-E", "-x", "c++", nullDevice ]; var p = new Process(); p.exec(compilerFilePath, args, false); var lines = p.readStdErr().trim().split(/\r?\n/g).map(function (line) { return line.trim(); }); var addIncludes = false; var includePaths = []; for (var i = 0; i < lines.length; ++i) { var line = lines[i]; if (line === "#include <...> search starts here:") addIncludes = true; else if (line === "End of search list.") addIncludes = false; else if (addIncludes) includePaths.push(line); } return includePaths; } function dumpDefaultPaths(compilerFilePath, nullDevice) { var includePaths = []; if (isMcsCompiler(compilerFilePath)) includePaths = dumpMcsCompilerIncludePaths(compilerFilePath); else if (isC166Compiler(compilerFilePath)) includePaths = dumpC166CompilerIncludePaths(compilerFilePath); else if (isArmCCCompiler(compilerFilePath)) includePaths = dumpArmCCCompilerIncludePaths(compilerFilePath); else if (isArmClangCompiler(compilerFilePath)) includePaths = dumpArmClangCompilerIncludePaths(compilerFilePath, nullDevice); return { "includePaths": includePaths }; } function filterMcsOutput(output) { var filteredLines = []; output.split(/\r\n|\r|\n/).forEach(function(line) { var regexp = /^\s*\*{3}\s|^\s{29}|^\s{4}\S|^\s{2}[0-9A-F]{4}|^\s{21,25}\d+|^[0-9A-F]{4}\s\d+/; if (regexp.exec(line)) filteredLines.push(line); }); return filteredLines.join('\n'); }; function filterC166Output(output) { var filteredLines = []; output.split(/\r\n|\r|\n/).forEach(function(line) { var regexp = /^\s*\*{3}\s|^\s{29}|^\s{27,28}\d+|^\s{21}\d+|^\s{4}\S|^\s{2}[0-9A-F]{4}|^[0-9A-F]{4}\s\d+/; if (regexp.exec(line)) filteredLines.push(line); }); return filteredLines.join('\n'); }; function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { // Determine which C-language we're compiling. var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); var args = []; var architecture = input.qbs.architecture; if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) { // Input. args.push(input.filePath); // Output. args.push("OBJECT(" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")"); // Defines. var defines = Cpp.collectDefines(input); if (defines.length > 0) args = args.concat("DEFINE (" + defines.join(",") + ")"); // Includes. var allIncludePaths = [].concat(Cpp.collectIncludePaths(input), Cpp.collectSystemIncludePaths(input)); if (allIncludePaths.length > 0) args = args.concat("INCDIR(" + allIncludePaths.map(function(path) { return FileInfo.toWindowsSeparators(path); }).join(";") + ")"); // Debug information flags. if (input.cpp.debugInformation) args.push("DEBUG"); // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("OPTIMIZE (SIZE)"); break; case "fast": args.push("OPTIMIZE (SPEED)"); break; case "none": args.push("OPTIMIZE (0)"); break; } // Warning level flags. switch (input.cpp.warningLevel) { case "none": args.push("WARNINGLEVEL (0)"); break; case "all": args.push("WARNINGLEVEL (2)"); if (isMcs51Architecture(architecture)) args.push("FARWARNING"); break; } // Listing files generation flag. if (!input.cpp.generateCompilerListingFiles) args.push("NOPRINT"); else args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath) + ")"); } else if (isArmArchitecture(architecture)) { // Input. args.push("-c", input.filePath); // Output. args.push("-o", outputs.obj[0].filePath); // Preinclude headers. args = args.concat(Cpp.collectPreincludePathsArguments(input, true)); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); var compilerPath = input.cpp.compilerPath; if (isArmCCCompiler(compilerPath)) { // Debug information flags. if (input.cpp.debugInformation) { args.push("--debug"); args.push("-g"); } // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("-Ospace") break; case "fast": args.push("-Otime") break; case "none": args.push("-O0") break; } // Warning level flags. switch (input.cpp.warningLevel) { case "none": args.push("-W"); break; default: // By default all warnings are enabled. break; } if (tag === "c") { // C language version flags. var knownCLanguageValues = ["c99", "c90"]; var cLanguageVersion = Cpp.languageVersion( input.cpp.cLanguageVersion, knownCLanguageValues, "C"); switch (cLanguageVersion) { case "c99": args.push("--c99"); break; case "c90": args.push("--c90"); break; } } else if (tag === "cpp") { // C++ language version flags. var knownCppLanguageValues = ["c++11", "c++03"]; var cppLanguageVersion = Cpp.languageVersion( input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++"); switch (cppLanguageVersion) { case "c++11": args.push("--cpp11"); break; default: // Default C++ language is C++03. args.push("--cpp"); break; } // Exceptions flags. var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) args.push(enableExceptions ? "--exceptions" : "--no_exceptions"); // RTTI flags. var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) args.push(enableRtti ? "--rtti" : "--no_rtti"); } // Listing files generation flag. if (input.cpp.generateCompilerListingFiles) { args.push("--list"); args.push("--list_dir", FileInfo.path(outputs.lst[0].filePath)); } } else if (isArmClangCompiler(compilerPath)) { // Debug information flags. if (input.cpp.debugInformation) args.push("-g"); // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("-Oz") break; case "fast": args.push("-Ofast") break; case "none": args.push("-O0") break; } // Warning level flags. switch (input.cpp.warningLevel) { case "all": args.push("-Wall"); break; default: break; } if (input.cpp.treatWarningsAsErrors) args.push("-Werror"); if (tag === "c") { // C language version flags. var knownCLanguageValues = ["c11", "c99", "c90", "c89"]; var cLanguageVersion = Cpp.languageVersion( input.cpp.cLanguageVersion, knownCLanguageValues, "C"); if (cLanguageVersion) args.push("-std=" + cLanguageVersion); } else if (tag === "cpp") { // C++ language version flags. var knownCppLanguageValues = ["c++17", "c++14", "c++11", "c++03", "c++98"]; var cppLanguageVersion = Cpp.languageVersion( input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++"); if (cppLanguageVersion) args.push("-std=" + cppLanguageVersion); // Exceptions flags. var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) args.push(enableExceptions ? "-fexceptions" : "-fno-exceptions"); // RTTI flags. var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) args.push(enableRtti ? "-frtti" : "-fno-rtti"); } // Listing files generation does not supported! // There are only a workaround: http://www.keil.com/support/docs/4152.htm } } // Misc flags. args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(input)); return args; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; var architecture = input.qbs.architecture; if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) { // Input. args.push(input.filePath); // Output. args.push("OBJECT(" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")"); // Includes. var allIncludePaths = [].concat(Cpp.collectIncludePaths(input), Cpp.collectSystemIncludePaths(input)); if (allIncludePaths.length > 0) args = args.concat("INCDIR(" + allIncludePaths.map(function(path) { return FileInfo.toWindowsSeparators(path); }).join(";") + ")"); // Debug information flags. if (input.cpp.debugInformation) args.push("DEBUG"); // Enable errors printing. args.push("EP"); // Listing files generation flag. if (!input.cpp.generateAssemblerListingFiles) args.push("NOPRINT"); else args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath) + ")"); } else if (isArmArchitecture(architecture)) { // Input. args.push(input.filePath); // Output. args.push("-o", outputs.obj[0].filePath); // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); // Debug information flags. if (input.cpp.debugInformation) { args.push("--debug"); args.push("-g"); } // Warning level flags. if (input.cpp.warningLevel === "none") args.push("--no_warn"); // Byte order flags. var endianness = input.cpp.endianness; if (endianness) args.push((endianness === "little") ? "--littleend" : "--bigend"); // Listing files generation flag. if (input.cpp.generateAssemblerListingFiles) args.push("--list", outputs.lst[0].filePath); } // Misc flags. args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); return args; } function disassemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = ["--disassemble", "--interleave=source"]; args.push(outputs.obj[0].filePath); args.push("--output=" + outputs.lst[0].filePath); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; var libraryPaths = Cpp.collectLibraryPaths(product); var architecture = product.qbs.architecture; if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) { // Semi-intelligent handling the library paths. // We need to add the full path prefix to the library file if this // file is not absolute or not relative. Reason is that the C51, C251, // and C166 linkers does not support the library paths. function collectLibraryObjectPaths(product) { var libraryObjects = Cpp.collectLibraryDependencies(product); return libraryObjects.map(function(dep) { var filePath = dep.filePath; if (FileInfo.isAbsolutePath(filePath)) return filePath; for (var i = 0; i < libraryPaths.length; ++i) { var fullPath = FileInfo.joinPaths(libraryPaths[i], filePath); if (File.exists(fullPath)) return fullPath; } return filePath; }); } // Note: The C51, C251, or C166 linker does not distinguish an object files and // a libraries, it interpret all this stuff as an input objects, // so, we need to pass it together in one string. function collectAllObjectPathsArguments(product, inputs) { return [].concat(Cpp.collectLinkerObjectPaths(inputs), collectLibraryObjectPaths(product)); } // Add all input objects as arguments (application and library object files). var allObjectPaths = collectAllObjectPathsArguments(product, inputs); if (allObjectPaths.length > 0) args = args.concat(allObjectPaths.map(function(path) { return FileInfo.toWindowsSeparators(path); }).join(",")); // Output. args.push("TO", FileInfo.toWindowsSeparators(outputs.application[0].filePath)); // Map file generation flag. if (!product.cpp.generateLinkerMapFile) args.push("NOPRINT"); else args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.mem_map[0].filePath) + ")"); } else if (isArmArchitecture(architecture)) { // Inputs. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); // Output. args.push("--output", outputs.application[0].filePath); // Library paths. if (libraryPaths.length > 0) args.push(product.cpp.libraryPathFlag + libraryPaths.join(",")); // Library dependencies. args = args.concat(Cpp.collectLibraryDependenciesArguments(product)); // Linker scripts. args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs, true)); // Map file generation flag. if (product.cpp.generateLinkerMapFile) args.push("--list", outputs.mem_map[0].filePath); // Entry point flag. if (product.cpp.entryPoint) args.push("--entry", product.cpp.entryPoint); // Debug information flag. var debugInformation = product.cpp.debugInformation; if (debugInformation !== undefined) args.push(debugInformation ? "--debug" : "--no_debug"); } // Misc flags. args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product), Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); return args; } function archiverFlags(project, product, inputs, outputs) { var args = []; // Inputs. var objectPaths = Cpp.collectLinkerObjectPaths(inputs); var architecture = product.qbs.architecture; if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) { // Library creation command. args.push("TRANSFER"); // Inputs. if (objectPaths.length > 0) args = args.concat(objectPaths.map(function(path) { return FileInfo.toWindowsSeparators(path); }).join(",")); // Output. args.push("TO", FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath)); } else if (isArmArchitecture(architecture)) { // Note: The ARM archiver command line expect the output file // first, and then a set of input objects. // Output. args.push("--create", outputs.staticlibrary[0].filePath); // Inputs. args = args.concat(objectPaths); // Debug information flag. if (product.cpp.debugInformation) args.push("--debug_symbols"); } Array.prototype.push.apply(args, product.cpp.archiverFlags); return args; } // The ARMCLANG compiler does not support generation // for the listing files: // * https://www.keil.com/support/docs/4152.htm // So, we generate the listing files from the object files // using the disassembler. function generateClangCompilerListing(project, product, inputs, outputs, input, output) { if (isArmClangCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) { var args = disassemblerFlags(project, product, input, outputs, explicitlyDependsOn); var disassemblerPath = input.cpp.disassemblerPath; var cmd = new Command(disassemblerPath, args); cmd.silent = true; return cmd; } } // The ARMCC compiler generates the listing files only in a short form, // e.g. to 'module.lst' instead of 'module.{c|cpp}.lst', that complicates // the auto-tests. Therefore we need to rename generated listing files // with correct unified names. function generateArmccCompilerListing(project, product, inputs, outputs, input, output) { if (isArmCCCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) { var listingPath = FileInfo.path(outputs.lst[0].filePath); var cmd = new JavaScriptCommand(); cmd.oldListing = FileInfo.joinPaths(listingPath, input.baseName + ".lst"); cmd.newListing = FileInfo.joinPaths( listingPath, input.fileName + input.cpp.compilerListingSuffix); cmd.silent = true; cmd.sourceCode = function() { File.move(oldListing, newListing); }; return cmd; } } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var architecture = input.cpp.architecture; var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; if (isMcsArchitecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterMcsOutput; } else if (isC166Architecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterC166Output; } cmds.push(cmd); cmd = generateClangCompilerListing(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); cmd = generateArmccCompilerListing(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); return cmds; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; var architecture = input.cpp.architecture; var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; if (isMcsArchitecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterMcsOutput; } else if (isC166Architecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterC166Output; } return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = product.cpp.linkerPath; var architecture = product.cpp.architecture; var cmd = new Command(linkerPath, args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; if (isMcsArchitecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterMcsOutput; } else if (isC166Architecture(architecture)) { cmd.maxExitCode = 1; cmd.stdoutFilterFunction = filterC166Output; } return [cmd]; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, inputs, outputs); var archiverPath = product.cpp.archiverPath; var architecture = product.cpp.architecture; var cmd = new Command(archiverPath, args); cmd.description = "creating " + output.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; if (isMcsArchitecture(architecture)) { cmd.stdoutFilterFunction = filterMcsOutput; } else if (isC166Architecture(architecture)) { cmd.stdoutFilterFunction = filterC166Output; } return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/android-gcc.qbs0000644000175100017510000001713515232633614021514 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.TextFile import qbs.Utilities import "../../modules/Android/ndk/utils.js" as NdkUtils import 'gcc.js' as Gcc LinuxGCC { Depends { name: "Android.ndk" } condition: qbs.targetOS.includes("android") && qbs.toolchain && qbs.toolchain.includes("llvm") priority: 2 rpaths: [] // toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android cxxLanguageVersion: "c++14" property string archLibsDir: { switch (qbs.architecture) { case "arm64": return "aarch64"; case "armv7a": return "arm"; case "x86_64": return qbs.architecture; case "x86": return "i686"; } } property string targetDir: "android" + (["armeabi", "armeabi-v7a"].includes(Android.ndk.abi) ? "eabi" : "") property string triple: [archLibsDir, targetSystem, targetDir].join("-") property string libsDir: FileInfo.joinPaths(sysroot, "usr", "lib", triple); property string sharedStlFilePath: (libsDir && Android.ndk.appStl.endsWith("_shared")) ? FileInfo.joinPaths(libsDir, dynamicLibraryPrefix + Android.ndk.appStl + dynamicLibrarySuffix) : undefined property string staticStlFilePath: (libsDir && Android.ndk.appStl.endsWith("_static")) ? FileInfo.joinPaths(libsDir, Android.ndk.platformVersion, NdkUtils.stlFileName(staticLibraryPrefix, Android.ndk, staticLibrarySuffix)) : undefined toolchainInstallPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt", Android.ndk.hostArch, "bin") property string toolchainTriple: [targetAbi === "androideabi" ? "arm" : targetArch, targetSystem, targetAbi].join("-") internalVersion: undefined toolchainPrefix: undefined machineType: { if (Android.ndk.abi === "armeabi-v7a") return "armv7-a"; } qbs.optimization: targetAbi === "androideabi" ? "small" : base enableExceptions: Android.ndk.appStl !== "system" enableRtti: Android.ndk.appStl !== "system" commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.toolchain, qbs.buildVariant, Android.ndk) linkerFlags: NdkUtils.commonLinkerFlags(Android.ndk); driverLinkerFlags: { var flags = ["-fuse-ld=lld", "-Wl,--exclude-libs,libgcc.a", "-nostdlib++"]; // See https://android.googlesource.com/platform/ndk/+/ndk-release-r21/docs/BuildSystemMaintainers.md#Unwinding if (Android.ndk.abi === "armeabi-v7a") { flags = flags.concat(["-Wl,--exclude-libs,libgcc_real.a"]); if (Android.ndk.appStl.startsWith("c++")) flags = flags.concat(["-Wl,--exclude-libs,libunwind.a"]); } return flags; } platformDriverFlags: ["-fdata-sections", "-ffunction-sections", "-funwind-tables", "-fstack-protector-strong", "-no-canonical-prefixes"] dynamicLibraries: { var libs = ["c", "m"]; if (sharedStlFilePath) libs.push(FileInfo.joinPaths(libsDir, Android.ndk.platformVersion, NdkUtils.stlFileName(dynamicLibraryPrefix, Android.ndk, dynamicLibrarySuffix))); return libs; } staticLibraries: staticStlFilePath // When using ndk r19c, llvm doesn't add sysroot/usr/include/c++/v1 to the path // But it works starting with ndk r20b systemIncludePaths: (Utilities.versionCompare(Android.ndk.version, "20") < 0) ? FileInfo.joinPaths(sysroot, "usr", "include", "c++", "v1") : [] defines: ["ANDROID", "__ANDROID__"] binutilsPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt", Android.ndk.hostArch, "bin"); binutilsPathPrefix: FileInfo.joinPaths(binutilsPath, "llvm-") sysroot: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt", Android.ndk.hostArch, "sysroot") targetArch: { switch (qbs.architecture) { case "arm64": return "aarch64"; case "armv5": case "armv5te": return "armv5te"; case "armv7a": case "x86_64": return qbs.architecture; case "x86": return "i686"; } } target: [targetArch, targetSystem, targetAbi].join("-") targetSystem: "linux" targetAbi: "android" + (["armeabi", "armeabi-v7a"].includes(Android.ndk.abi) ? "eabi" : "") + Android.ndk.platformVersion endianness: "little" Group { condition: shouldLink Group { name: "Android STL" condition: module.sharedStlFilePath files: module.sharedStlFilePath ? [module.sharedStlFilePath] : [] fileTags: "android.stl" } Rule { inputs: "dynamiclibrary" Artifact { filePath: FileInfo.joinPaths("stripped-libs", input.fileName) fileTags: "android.nativelibrary" } prepare: { var stripArgs = ["--strip-all", "-o", output.filePath, input.filePath]; var stripCmd = new Command(product.cpp.stripPath, stripArgs); stripCmd.description = "stripping unneeded symbols from " + input.fileName; return stripCmd; } } } _skipAllChecks: !shouldLink validate: { if (_skipAllChecks) return; var baseValidator = new ModUtils.PropertyValidator("qbs"); baseValidator.addCustomValidator("architecture", targetArch, function (value) { return value !== undefined; }, "unknown Android architecture '" + qbs.architecture + "'."); var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("targetArch", targetArch); return baseValidator.validate() && validator.validate(); } } qbs-src-3.3.1/share/qbs/modules/cpp/iar.qbs0000644000175100017510000001332515232633614020112 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.PathTools import qbs.Probes import qbs.Utilities import "cpp.js" as Cpp import "iar.js" as IAR CppModule { condition: qbs.toolchain && qbs.toolchain.includes("iar") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["iccarm"] } Probes.IarProbe { id: iarProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage } Properties { condition: iarProbe.found qbs.architecture: iarProbe.architecture } qbs.targetPlatform: "none" compilerVersionMajor: iarProbe.versionMajor compilerVersionMinor: iarProbe.versionMinor compilerVersionPatch: iarProbe.versionPatch endianness: iarProbe.endianness compilerDefinesByLanguage: iarProbe.compilerDefinesByLanguage compilerIncludePaths: iarProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: toolchainDetails.compilerName + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: toolchainDetails.assemblerName + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: toolchainDetails.linkerName + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) archiverName: toolchainDetails.archiverName + compilerExtension archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" staticLibrarySuffix: toolchainDetails.staticLibrarySuffix executableSuffix: toolchainDetails.executableSuffix objectSuffix: toolchainDetails.objectSuffix imageFormat: toolchainDetails.imageFormat enableExceptions: false enableRtti: false defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-I" preincludeFlag: "--preinclude" libraryDependencyFlag: "" libraryPathFlag: toolchainDetails.libraryPathFlag linkerScriptFlag: toolchainDetails.linkerScriptFlag property string linkerSilentFlag: toolchainDetails.linkerSilentFlag property string linkerMapFileFlag: toolchainDetails.linkerMapFileFlag property string linkerEntryPointFlag: toolchainDetails.linkerEntryPointFlag toolchainDetails: IAR.toolchainDetails(qbs) knownArchitectures: ["78k", "arm", "avr", "avr32", "cr16", "hcs12", "hcs8", "m16c", "m32c", "m68k", "mcs51", "msp430", "r32c", "rh850", "riscv", "rl78", "rx", "sh", "stm8", "v850"] Rule { id: assembler inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: IAR.prepareAssembler.apply(IAR, arguments) } FileTagger { patterns: ["*.s", "*.s43", "*.s51", "*.s90", "*.msa", "*.asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles) outputArtifacts: Cpp.compilerOutputArtifacts(input) prepare: IAR.prepareCompiler.apply(IAR, arguments) } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile) outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product) prepare: IAR.prepareLinker.apply(IAR, arguments) } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: IAR.prepareArchiver.apply(IAR, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/cosmic.qbs0000644000175100017510000001231315232633614020610 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.PathTools import qbs.Probes import qbs.Utilities import "cosmic.js" as COSMIC import "cpp.js" as Cpp CppModule { condition: qbs.toolchain && qbs.toolchain.includes("cosmic") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["cxcorm"] } Probes.CosmicProbe { id: cosmicProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage } Properties { condition: cosmicProbe.found qbs.architecture: cosmicProbe.architecture } qbs.targetPlatform: "none" compilerVersionMajor: cosmicProbe.versionMajor compilerVersionMinor: cosmicProbe.versionMinor compilerVersionPatch: cosmicProbe.versionPatch endianness: cosmicProbe.endianness compilerDefinesByLanguage: cosmicProbe.compilerDefinesByLanguage compilerIncludePaths: cosmicProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: toolchainDetails.compilerName + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: toolchainDetails.assemblerName + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: "clnk" + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) archiverName: "clib" + compilerExtension archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" staticLibrarySuffix: toolchainDetails.staticLibrarySuffix executableSuffix: toolchainDetails.executableSuffix imageFormat: "cosmic" enableExceptions: false enableRtti: false defineFlag: "-d" includeFlag: "-i" systemIncludeFlag: "-i" preincludeFlag: "-ph" libraryDependencyFlag: "" libraryPathFlag: "-l" linkerScriptFlag: "" toolchainDetails: COSMIC.toolchainDetails(qbs) knownArchitectures: ["arm", "hcs12", "hcs8", "m68k", "stm8"] Rule { id: assembler inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: COSMIC.prepareAssembler.apply(COSMIC, arguments) } FileTagger { patterns: ["*.s"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles) outputArtifacts: Cpp.compilerOutputArtifacts(input) prepare: COSMIC.prepareCompiler.apply(COSMIC, arguments) } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile) outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product) prepare: COSMIC.prepareLinker.apply(COSMIC, arguments) } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: COSMIC.prepareArchiver.apply(COSMIC, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/DarwinGCC.qbs0000644000175100017510000002730715232633614021105 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.PropertyList import qbs.TextFile import qbs.Utilities import "darwin.js" as Darwin import "gcc.js" as Gcc UnixGCC { condition: false Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.includes("xcode") } Probes.BinaryProbe { id: lipoProbe condition: !_skipAllChecks names: [lipoName] platformSearchPaths: { var paths = (xcode.present && xcode.devicePlatformPath) ? [xcode.devicePlatformPath + "/Developer/usr/bin"] : []; return paths.concat([toolchainInstallPath, "/usr/bin"]); } } property string lipoPathPrefix: Gcc.pathPrefix(lipoProbe.found ? lipoProbe.path : toolchainInstallPath, toolchainPrefix) lipoName: "lipo" lipoPath: lipoPathPrefix + lipoName property bool enableAggregationRules: product.aggregate && !product.multiplexConfigurationId targetVendor: "apple" targetSystem: "darwin" targetAbi: "macho" imageFormat: "macho" cxxStandardLibrary: libcxxAvailable ? "libc++" : base loadableModulePrefix: "" loadableModuleSuffix: ".bundle" dynamicLibrarySuffix: ".dylib" Properties { condition: product.multiplexByQbsProperties.includes("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && (!product.aggregate || !!product.multiplexConfigurationId) && qbs.buildVariant !== "release" variantSuffix: "_" + qbs.buildVariant } separateDebugInformation: true debugInfoBundleSuffix: ".dSYM" debugInfoSuffix: ".dwarf" rpathOrigin: "@loader_path" useRPathLink: !minimumDarwinVersion || Utilities.versionCompare(minimumDarwinVersion, "10.5") < 0 rpathLinkFlag: "-L" toolchainInstallPath: xcode.present ? FileInfo.joinPaths(xcode.toolchainPath, "usr", "bin") : base sysroot: xcode.present ? xcode.sdkPath : base sysrootFlags: sysroot ? ["-isysroot", sysroot] : [] setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { var v = new ModUtils.EnvironmentVariable(key); v.value = product.cpp.buildEnv[key]; v.set(); } } property var defaultInfoPlist: { var dict = {}; if (qbs.targetOS.includes("macos")) { dict["NSPrincipalClass"] = "NSApplication"; // needed for Retina display support // QBS-1670: set this flag by default to avoid extensive GPU usage dict["NSSupportsAutomaticGraphicsSwitching"] = true; if (minimumMacosVersion) dict["LSMinimumSystemVersion"] = minimumMacosVersion; } if (qbs.targetOS.includes("ios") && minimumIosVersion) dict["MinimumOSVersion"] = minimumIosVersion; else if (qbs.targetOS.includes("tvos") && minimumTvosVersion) dict["MinimumOSVersion"] = minimumTvosVersion; else if (qbs.targetOS.includes("watchos") && minimumWatchosVersion) dict["MinimumOSVersion"] = minimumWatchosVersion; if (qbs.targetOS.containsAny(["ios", "tvos"])) { dict["LSRequiresIPhoneOS"] = true; if (xcode.platformType === "device") { if (qbs.targetOS.includes("ios")) { if (qbs.architecture === "arm64") dict["UIRequiredDeviceCapabilities"] = ["arm64"]; else dict["UIRequiredDeviceCapabilities"] = ["armv7"]; } if (qbs.targetOS.includes("tvos")) dict["UIRequiredDeviceCapabilities"] = ["arm64"]; } } if (xcode.present) { var targetDevices = DarwinTools.targetedDeviceFamily(xcode.targetDevices); if (qbs.targetOS.includes("ios")) dict["UIDeviceFamily"] = targetDevices; if (qbs.targetOS.containsAny(["ios", "watchos"])) { var orientations = [ "UIInterfaceOrientationPortrait", "UIInterfaceOrientationPortraitUpsideDown", "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" ]; if (targetDevices.includes("ipad")) dict["UISupportedInterfaceOrientations~ipad"] = orientations; if (targetDevices.includes("watch")) dict["UISupportedInterfaceOrientations"] = orientations.slice(0, 2); if (targetDevices.includes("iphone")) { orientations.splice(1, 1); dict["UISupportedInterfaceOrientations"] = orientations; } } } return dict; } targetLinkerFlags: darwinArchFlags.concat(minimumDarwinVersionLinkerFlags) targetAssemblerFlags: !assemblerHasTargetOption ? darwinArchFlags : base; targetDriverFlags: !compilerHasTargetOption ? legacyTargetDriverFlags : base property stringList legacyTargetDriverFlags: base.concat(darwinArchFlags).concat(minimumDarwinVersionCompilerFlags) // private properties readonly property stringList darwinArchFlags: targetArch ? ["-arch", targetArch] : [] readonly property stringList minimumDarwinVersionCompilerFlags: (minimumDarwinVersionCompilerFlag && minimumDarwinVersion) ? [minimumDarwinVersionCompilerFlag + "=" + minimumDarwinVersion] : [] readonly property stringList minimumDarwinVersionLinkerFlags: (minimumDarwinVersionLinkerFlag && minimumDarwinVersion && compilerVersionMajor < 11) ? [minimumDarwinVersionLinkerFlag, minimumDarwinVersion] : [] readonly property var buildEnv: { var env = { "ARCHS_STANDARD": xcode.standardArchitectures, "EXECUTABLE_NAME": product.targetName, "PRODUCT_NAME": product.name } // Set the corresponding environment variable even if the minimum OS version is undefined, // because this indicates the default deployment target for that OS if (qbs.targetOS.includes("ios") && minimumIosVersion) env["IPHONEOS_DEPLOYMENT_TARGET"] = minimumIosVersion; if (qbs.targetOS.includes("macos") && minimumMacosVersion) env["MACOSX_DEPLOYMENT_TARGET"] = minimumMacosVersion; if (qbs.targetOS.includes("watchos") && minimumWatchosVersion) env["WATCHOS_DEPLOYMENT_TARGET"] = minimumWatchosVersion; if (qbs.targetOS.includes("tvos") && minimumTvosVersion) env["TVOS_DEPLOYMENT_TARGET"] = minimumTvosVersion; if (xcode.present) env["TARGETED_DEVICE_FAMILY"] = DarwinTools.targetedDeviceFamily(xcode.targetDevices).join(","); return env; } property string minimumDarwinVersion property string minimumDarwinVersionCompilerFlag property string minimumDarwinVersionLinkerFlag property bool libcxxAvailable: qbs.toolchain.includes("clang") && cxxLanguageVersion !== "c++98" Group { condition: enableAggregationRules Rule { inputsFromDependencies: ["application"] multiplex: true outputFileTags: ["bundle.input", "bundle.main.input", "bundle.main.executable", "application", "primary", "debuginfo_app", "debuginfo_bundle", "bundle.variant_copy", "debuginfo_plist", "codesign.signed_artifact"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "application", "app") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { inputsFromDependencies: ["loadablemodule"] multiplex: true outputFileTags: ["bundle.input", "bundle.main.input", "bundle.main.plugin", "loadablemodule", "primary", "debuginfo_loadablemodule", "debuginfo_bundle", "debuginfo_plist", "codesign.signed_artifact"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "loadablemodule", "loadablemodule") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { inputsFromDependencies: ["dynamiclibrary"] multiplex: true outputFileTags: ["bundle.input", "bundle.main.input", "bundle.main.library", "dynamiclibrary", "dynamiclibrary_symbols", "primary", "debuginfo_dll","debuginfo_bundle","bundle.variant_copy", "debuginfo_plist", "codesign.signed_artifact", "dynamiclibrary_symlink"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "dynamiclibrary", "dll") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { inputsFromDependencies: ["staticlibrary"] multiplex: true outputFileTags: ["bundle.input", "bundle.main.input", "bundle.main.library", "staticlibrary", "primary", "codesign.signed_artifact"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "staticlibrary") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } } Rule { condition: qbs.targetOS.includes("darwin") multiplex: true Artifact { filePath: product.name + "-cpp-Info.plist" fileTags: ["partial_infoplist"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.inputData = product.cpp.defaultInfoPlist; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { var plist = new PropertyList(); try { plist.readFromObject(inputData); plist.writeToFile(outputFilePath, "xml1"); } finally { plist.clear(); } }; return [cmd]; } } } qbs-src-3.3.1/share/qbs/modules/cpp/dmc.js0000644000175100017510000004717715232633614017745 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function targetFlags(platform, architecture, extender, consoleApp, type) { if (platform === "dos") { if (architecture === "x86_16") { if (extender === "dosz") return ["-mz"]; else if (extender === "dosr") return ["-mr"]; return ["-mc"]; } else if (architecture === "x86") { if (extender === "dosx") return ["-mx"]; else if (extender === "dosp") return ["-mp"]; } } else if (platform === "windows") { var flags = []; if (architecture === "x86_16") { flags.push("-ml"); if (type.includes("application") && !consoleApp) flags.push("-WA"); else if (type.includes("dynamiclibrary")) flags.push("-WD"); } else if (architecture === "x86") { flags.push("-mn"); if (type.includes("application")) flags.push("-WA"); else if (type.includes("dynamiclibrary")) flags.push("-WD"); } return flags; } return []; } function languageFlags(tag) { if (tag === "cpp") return ["-cpp"]; return []; } function dumpMacros(compilerPath, platform, architecture, extender, tag) { // Note: The DMC compiler does not support the predefined/ macros dumping. So, we do it // with the following trick, where we try to create and compile a special temporary file // and to parse the console output with the own magic pattern: #define . var outputDirectory = new TemporaryDir(); var outputFilePath = FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c"); var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly); outputFile.writeLine("#define VALUE_TO_STRING(x) #x"); outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)"); outputFile.writeLine("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)"); // Declare all available pre-defined macros of DMC compiler. var keys = [ // Prepare the DOS target macros. "_MSDOS", "MSDOS", // Prepare the OS/2 target macros. "__OS2__", // Prepare the Windows target macros. "WIN32", "_WIN32", "__NT__", // Prepare extended the 32 and 16 bit DOS target macros. "DOS386", "DOS16RM", // Prepare the memory model macros. "M_I86", "_M_I86", "_M_I86TM", "M_I86TM", "_M_I86SM", "M_I86SM", "_M_I86MM", "M_I86MM", "_M_I86CM", "M_I86CM", "_M_I86LM", "M_I86LM", "_M_I86VM", "M_I86VM", // Prepare 8086 macros. "_M_I8086", "M_I8086", // Prepare 286 macros. "_M_I286", "M_I286", // Prepare 32 bit macros. "_M_IX86", // Prepare compiler identification macros. "__DMC__", "__DMC_VERSION_STRING__", // Prepare common compiler macros. "_CHAR_UNSIGNED", "_CHAR_EQ_UCHAR", "_DEBUG_TRACE", "_DLL", "_ENABLE_ARRAYNEW", "_BOOL_DEFINED", "_WCHAR_T_DEFINED", "_CPPRTTI", "_CPPUNWIND", "_MD", "_PUSHPOP_SUPPORTED", "_STDCALL_SUPPORTED", "__INTSIZE", "__DEFALIGN", "_INTEGRAL_MAX_BITS", "_WINDOWS", "_WINDLL", "__INLINE_8087", "__I86__", "__SMALL__", "__MEDIUM__", "__COMPACT__", "__LARGE__", "__VCM__", "__FPCE__", "__FPCE__IEEE__", "DEBUG", // Prepare C99 and C++98 macros. "__STDC__", "__STDC_HOSTED__", "__STDC_VERSION__", "__STDC_IEC_559__", "__STDC_IEC_559_COMPLEX__", "__STDC_ISO_10646__", "__cplusplus" ]; for (var i = 0; i < keys.length; ++i) { var key = keys[i]; outputFile.writeLine("#if defined (" + key + ")"); outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))"); outputFile.writeLine("#endif"); } outputFile.close(); var process = new Process(); process.setWorkingDirectory(outputDirectory.path()); var lang = languageFlags(tag); var target = targetFlags(platform, architecture, extender, false, ["application"]); var args = ["-c"].concat(lang, target, FileInfo.toWindowsSeparators(outputFilePath)); process.exec(compilerPath, args, false); File.remove(outputFilePath); var out = process.readStdOut(); return Cpp.extractMacros(out); } function dumpDefaultPaths(compilerFilePath, tag) { var binPath = FileInfo.path(compilerFilePath); var rootPath = FileInfo.path(binPath); var includePaths = []; var cppIncludePath = FileInfo.joinPaths(rootPath, "stlport/stlport"); if (File.exists(cppIncludePath)) includePaths.push(cppIncludePath); var cIncludePath = FileInfo.joinPaths(rootPath, "include"); if (File.exists(cIncludePath)) includePaths.push(cIncludePath); var libraryPaths = []; var libraryPath = FileInfo.joinPaths(rootPath, "lib"); if (File.exists(libraryPath)) libraryPaths.push(libraryPath); return { "includePaths": includePaths, "libraryPaths": libraryPaths, } } function guessVersion(macros) { var version = macros["__DMC__"]; return { major: parseInt(version / 100), minor: parseInt(version % 100), patch: 0 }; } function effectiveLinkerPath(product) { if (product.cpp.linkerMode === "automatic") { var compilerPath = product.cpp.compilerPath; if (compilerPath) return compilerPath; console.log("Found no C-language objects, choosing system linker for " + product.name); } return product.cpp.linkerPath; } function useCompilerDriverLinker(product) { var linker = effectiveLinkerPath(product); var compilers = product.cpp.compilerPathByLanguage; if (compilers) return linker === compilers["cpp"] || linker === compilers["c"]; return linker === product.cpp.compilerPath; } function depsOutputTags() { return ["dep"]; } function depsOutputArtifacts(input, product) { return [{ fileTags: depsOutputTags(), filePath: FileInfo.joinPaths(product.destinationDirectory, input.baseName + ".dep") }]; } function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = ["-c"]; var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); args = args.concat(languageFlags(tag)); args = args.concat(targetFlags(product.qbs.targetPlatform, product.qbs.architecture, product.cpp.extenderName, product.consoleApplication, product.type)); // Input. args.push(FileInfo.toWindowsSeparators(input.filePath)); // Output. args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath)); // Preinclude headers. args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) { return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path); })); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); if (tag === "cpp") { // We need to add the paths to the STL includes, because the DMC compiler does // not handle it by default (because the STL libraries is a separate port). var compilerIncludePaths = input.cpp.compilerIncludePaths || []; args = args.concat(compilerIncludePaths.map(function(path) { return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); } // Other includes. args = args.concat(Cpp.collectIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) { return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path); })); // Debug information flags. if (input.cpp.debugInformation) args.push("-d"); // Optimization flags. switch (input.cpp.optimization) { case "small": args.push("-o+space"); break; case "fast": args.push("-o+speed"); break; case "none": args.push("-o+none"); break; } // Warning level flags. switch (input.cpp.warningLevel) { case "none": args.push("-w"); break; case "all": args.push("-w-"); break; } if (input.cpp.treatWarningsAsErrors) args.push("-wx"); if (tag === "cpp") { // Exceptions flag. if (input.cpp.enableExceptions) args.push("-Ae"); // RTTI flag. var enableRtti = input.cpp.enableRtti; if (input.cpp.enableRtti) args.push("-Ar"); } // Listing files generation flag. if (input.cpp.generateCompilerListingFiles) { // We need to use the relative path here, because the DMC compiler does not handle // a long file path for this option. var listingPath = Cpp.relativePath(product.buildDirectory, outputs.lst[0].filePath); args.push("-l" + FileInfo.toWindowsSeparators(listingPath)); } // Misc flags. args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(product)); return args; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = ["-c"]; // Input. args.push(FileInfo.toWindowsSeparators(input.filePath)); // Output. args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath)); // Preinclude headers. args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) { return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path); })); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); // Other includes. args = args.concat(Cpp.collectIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) { return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path); })); // Misc flags. args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; var useCompilerDriver = useCompilerDriverLinker(product); if (useCompilerDriver) { args = args.concat(targetFlags(product.qbs.targetPlatform, product.qbs.architecture, product.cpp.extenderName, product.consoleApplication, product.type)); // Input objects. args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) { return FileInfo.toWindowsSeparators(path); })); // Input resources. args = args.concat(Cpp.collectResourceObjectPaths(inputs).map(function(path) { return FileInfo.toWindowsSeparators(path); })); // Input libraries. args = args.concat(Cpp.collectAbsoluteLibraryDependencyPaths(product).map(function(path) { return FileInfo.toWindowsSeparators(path); })); // Output. if (product.type.includes("application")) { args.push("-o" + FileInfo.toWindowsSeparators(outputs.application[0].filePath)); args.push("-L/" + (product.cpp.generateLinkerMapFile ? "MAP" : "NOMAP")); if (product.qbs.targetPlatform === "windows" && product.qbs.architecture === "x86") args.push("-L/SUBSYSTEM:" + (product.consoleApplication ? "CONSOLE" : "WINDOWS")); } else if (product.type.includes("dynamiclibrary")) { args.push("-o" + FileInfo.toWindowsSeparators(outputs.dynamiclibrary[0].filePath)); if (product.qbs.targetPlatform === "windows" && product.qbs.architecture === "x86") { args.push("kernel32.lib"); args.push("-L/IMPLIB:" + FileInfo.toWindowsSeparators( outputs.dynamiclibrary_import[0].filePath)); } } if (product.cpp.debugInformation) args.push("-L/DEBUG"); args.push("-L/NOLOGO", "-L/SILENT"); } // Misc flags. args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product), Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); return args; } function archiverFlags(project, product, inputs, outputs) { var args = ["-c"]; Array.prototype.push.apply(args, product.cpp.archiverFlags); // Output. args.push(FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath)); // Input objects. args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) { return FileInfo.toWindowsSeparators(path); })); return args; } function rccCompilerFlags(project, product, input, outputs) { // Input. var args = [FileInfo.toWindowsSeparators(input.filePath)]; // Output. args.push("-o" + FileInfo.toWindowsSeparators(outputs.res[0].filePath)); // Bitness. args.push("-32"); // Defines args = args.concat(Cpp.collectDefinesArguments(input)); // Other includes. args = args.concat(Cpp.collectIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) { return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path); })); return args; } function buildLinkerMapFilePath(target, suffix) { return FileInfo.joinPaths(FileInfo.path(target.filePath), FileInfo.completeBaseName(target.fileName) + suffix); } // It is a workaround which removes the generated linker map file if it is disabled // by cpp.generateLinkerMapFile property. Reason is that the DMC compiler always // generates this file, and does not have an option to disable generation for a linker // map file. So, we can to remove a listing files only after the linking completes. function removeLinkerMapFile(project, product, inputs, outputs, input, output) { var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0] : outputs.application[0]; var cmd = new JavaScriptCommand(); cmd.mapFilePath = buildLinkerMapFilePath(target, ".map") cmd.silent = true; cmd.sourceCode = function() { File.remove(mapFilePath); }; return cmd; } // It is a workaround to rename the extension of the output linker map file to the // specified one, since the linker generates only files with the '.map' extension. function renameLinkerMapFile(project, product, inputs, outputs, input, output) { var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0] : outputs.application[0]; var cmd = new JavaScriptCommand(); cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix); cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map"); cmd.silent = true; cmd.sourceCode = function() { if (oldMapFilePath !== newMapFilePath) File.move(oldMapFilePath, newMapFilePath); }; return cmd; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); var cmd = new Command(input.cpp.compilerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; return [cmd]; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn); var cmd = new Command(input.cpp.assemblerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var cmds = []; var primaryOutput = outputs.dynamiclibrary ? outputs.dynamiclibrary[0] : outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = effectiveLinkerPath(product); var cmd = new Command(linkerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; cmds.push(cmd); if (product.cpp.generateLinkerMapFile) cmds.push(renameLinkerMapFile(project, product, inputs, outputs, input, output)); else cmds.push(removeLinkerMapFile(project, product, inputs, outputs, input, output)); return cmds; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, inputs, outputs); var cmd = new Command(product.cpp.archiverPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "creating " + output.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; return [cmd]; } function prepareRccCompiler(project, product, inputs, outputs, input, output) { var args = rccCompilerFlags(project, product, input, outputs); var cmd = new Command(input.cpp.rccCompilerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/freebsd-gcc.qbs0000644000175100017510000000355515232633614021507 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "freebsd.js" as FreeBSD import qbs.Host UnixGCC { condition: qbs.targetOS.includes("freebsd") && qbs.toolchain && qbs.toolchain.includes("gcc") priority: 1 targetSystem: "freebsd" + (Host.os().includes("freebsd") ? FreeBSD.hostKernelRelease() : "") distributionIncludePaths: ["/usr/local/include"] distributionLibraryPaths: ["/usr/local/lib"] } qbs-src-3.3.1/share/qbs/modules/cpp/UnixGCC.qbs0000644000175100017510000000371215232633614020576 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File GenericGCC { condition: qbs.toolchain && qbs.toolchain.includes("gcc") && qbs.targetOS.includes("unix") priority: -50 dynamicLibraryPrefix: "lib" loadableModulePrefix: "lib" dynamicLibrarySuffix: ".so" debugInfoSuffix: ".debug" imageFormat: "elf" systemRunPaths: ["/lib", "/usr/lib"].filter(function(p) { return File.exists(p); }) rpathOrigin: "$ORIGIN" useRPathLink: true rpathLinkFlag: "-rpath-link=" } qbs-src-3.3.1/share/qbs/modules/cpp/setuprunenv.js0000644000175100017510000001411115232633614021556 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var File = require("qbs.File"); var Host = require("qbs.Host"); var ModUtils = require("qbs.ModUtils"); // TODO: append/prepend functionality should go to qbs.Environment function addNewElement(list, elem) { if (!list.includes(elem)) list.push(elem); } function artifactDir(artifact) { if (!artifact.qbs.install) return FileInfo.path(artifact.filePath); return FileInfo.path(ModUtils.artifactInstalledFilePath(artifact)); } function addExternalLibPath(product, list, path) { addNewElement(list, path); if (Host.os().includes("windows") && FileInfo.fileName(path) === "lib") { var binPath = FileInfo.joinPaths(FileInfo.path(path), "bin"); if (File.exists(binPath)) addNewElement(list, binPath); } } function gatherPaths(product, libPaths, frameworkPaths, seenProducts) { if (seenProducts.includes(product.name)) return; seenProducts.push(product.name); // Gather explicitly given library paths. if (product.cpp && product.cpp.libraryPaths) product.cpp.libraryPaths.forEach(function(p) { addExternalLibPath(product, libPaths, p); }); if (product.cpp && product.cpp.frameworkPaths) product.cpp.frameworkPaths.forEach(function(p) { addNewElement(frameworkPaths, p); }); if (product.cpp && product.cpp.systemFrameworkPaths) product.cpp.systemFrameworkPaths.forEach(function(p) { addNewElement(frameworkPaths, p); }); // Extract paths from dynamic libraries, if they are given as file paths. if (product.cpp && product.cpp.dynamicLibraries) { product.cpp.dynamicLibraries.forEach(function(dll) { if (FileInfo.isAbsolutePath(dll)) addExternalLibPath(product, libPaths, FileInfo.path(dll)); }); } // Traverse library dependencies. for (var i = 0; i < product.dependencies.length; ++i) { var dep = product.dependencies[i]; var dllSymlinkArtifacts = dep.artifacts["bundle.symlink.executable"]; if (dllSymlinkArtifacts) { var addArtifact = function(artifact) { addNewElement(frameworkPaths, FileInfo.path(artifactDir(artifact))); }; dllSymlinkArtifacts.forEach(addArtifact); // TODO: Will also catch applications. Can we prevent that? } else { addArtifact = function(artifact) { addNewElement(libPaths, artifactDir(artifact)); }; var dllArtifacts = dep.artifacts["dynamiclibrary"]; if (dllArtifacts) dllArtifacts.forEach(addArtifact); var loadableModuleArtifacts = dep.artifacts["loadablemodule"]; if (loadableModuleArtifacts) loadableModuleArtifacts.forEach(addArtifact); } if (!dep.hasOwnProperty("present")) // Recurse if the dependency is a product. TODO: Provide non-heuristic way to decide whether dependency is a product. gatherPaths(dep, libPaths, frameworkPaths, seenProducts); } } function setupRunEnvironment(product, config) { if (config.includes("ignore-lib-dependencies")) return; if (Host.platform() !== product.qbs.targetPlatform) return; var libPaths = []; var frameworkPaths = []; gatherPaths(product, libPaths, frameworkPaths, []); var runPaths = product.cpp ? product.cpp.systemRunPaths : undefined; if (runPaths && runPaths.length > 0) { var canonicalRunPaths = runPaths.map(function(p) { return File.canonicalFilePath(p); }); var filterFunc = function(libPath) { return !runPaths.includes(libPath) && !canonicalRunPaths.includes(File.canonicalFilePath(libPath)); }; libPaths = libPaths.filter(filterFunc); frameworkPaths = frameworkPaths.filter(filterFunc); } if (libPaths.length > 0) { var envVarName; if (product.qbs.targetOS.includes("windows")) envVarName = "PATH"; else if (product.qbs.targetOS.includes("macos")) envVarName = "DYLD_LIBRARY_PATH"; else envVarName = "LD_LIBRARY_PATH"; var envVar = new ModUtils.EnvironmentVariable(envVarName, FileInfo.pathListSeparator(), Host.os().includes("windows")); libPaths.forEach(function(p) { envVar.prepend(p); }); envVar.set(); } if (product.qbs.targetOS.includes("macos") && frameworkPaths.length > 0) { envVar = new ModUtils.EnvironmentVariable("DYLD_FRAMEWORK_PATH", ':', false); frameworkPaths.forEach(function(p) { envVar.prepend(p); }); envVar.set(); } } qbs-src-3.3.1/share/qbs/modules/cpp/iar.js0000644000175100017510000006307515232633614017750 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); function supportXLinker(architecture) { return architecture === "78k" || architecture === "avr" || architecture === "avr32" || architecture === "cr16" || architecture === "hcs12" || architecture === "hcs8" || architecture === "m16c" || architecture === "m32c" || architecture === "m68k" || architecture === "mcs51" || architecture === "msp430" || architecture === "r32c" || architecture === "v850"; } function supportILinker(architecture) { return architecture.startsWith("arm") || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx" || architecture === "sh" || architecture === "stm8"; } function supportXArchiver(architecture) { return architecture === "78k" || architecture === "avr" || architecture === "avr32" || architecture === "cr16" || architecture === "hcs12" || architecture === "hcs8" || architecture === "m16c" || architecture === "m32c" || architecture === "m68k" || architecture === "mcs51" || architecture === "msp430" || architecture === "r32c" || architecture === "v850"; } function supportIArchiver(architecture) { return architecture.startsWith("arm") || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx" || architecture === "sh" || architecture === "stm8"; } function supportXAssembler(architecture) { return architecture.startsWith("arm") || architecture === "78k" || architecture === "avr" || architecture === "hcs12" || architecture === "m16c" || architecture === "mcs51" || architecture === "msp430" || architecture === "m32c" || architecture === "v850"; } function supportIAssembler(architecture) { return architecture === "avr32" || architecture === "cr16" || architecture === "hcs8" || architecture === "r32c" || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx" || architecture === "sh" || architecture === "stm8" || architecture === "m68k"; } function supportEndianness(architecture) { return architecture.startsWith("arm") || architecture === "rx"; } function supportCppExceptions(architecture) { return architecture.startsWith("arm") || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx"; } function supportCppRtti(architecture) { return architecture.startsWith("arm") || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx"; } function supportCppWarningAboutCStyleCast(architecture) { return architecture.startsWith("arm") || architecture === "avr" || architecture === "avr32" || architecture === "cr16" || architecture === "mcs51" || architecture === "msp430" || architecture === "rh850" || architecture === "rl78" || architecture === "rx" || architecture === "stm8" || architecture === "v850"; } function supportDeprecatedFeatureWarnings(architecture) { return architecture.startsWith("arm") || architecture === "avr" || architecture === "cr16" || architecture === "mcs51" || architecture === "msp430" || architecture === "rh850" || architecture === "rl78" || architecture === "rx" || architecture === "stm8" || architecture === "v850"; } function supportCLanguageVersion(architecture) { return architecture !== "78k"; } function supportCppLanguage(compilerFilePath) { var baseName = FileInfo.baseName(compilerFilePath); return baseName !== "iccs08"; } // It is a 'magic' IAR-specific target architecture code. function architectureCode(architecture) { switch (architecture) { case "78k": return "26"; case "avr": return "90"; case "avr32": return "82"; case "mcs51": return "51"; case "msp430": return "43"; case "v850": return "85"; case "m68k": return "68"; case "m32c": return "48"; case "r32c": return "53"; case "m16c": return "34"; case "cr16": return "45"; case "hcs12": return "12"; case "hcs8": return "78"; case "rh850": case "riscv": case "rl78": case "rx": case "sh": case "stm8": return ""; default: if (architecture.startsWith("arm")) return ""; break; } } function toolchainDetails(qbs) { var architecture = qbs.architecture; var code = architectureCode(architecture); var details = {}; if (supportXLinker(architecture)) { details.libraryPathFlag = "-I"; details.linkerScriptFlag = "-f"; details.linkerName = "xlink"; details.linkerSilentFlag = "-S"; details.linkerMapFileFlag = "-l"; details.linkerEntryPointFlag = "-s"; } else if (supportILinker(architecture)) { details.libraryPathFlag = "-L"; details.linkerScriptFlag = "--config"; details.linkerSilentFlag = "--silent"; details.linkerMapFileFlag = "--map"; details.linkerEntryPointFlag = "--entry"; details.linkerName = architecture.startsWith("arm") ? "ilinkarm" : ("ilink" + architecture); } if (supportXArchiver(architecture)) details.archiverName = "xar"; else if (supportIArchiver(architecture)) details.archiverName = "iarchive"; var hasCode = (code !== ""); details.staticLibrarySuffix = hasCode ? (".r" + code) : ".a"; details.executableSuffix = hasCode ? ((qbs.debugInformation) ? (".d" + code) : (".a" + code)) : ".out"; details.objectSuffix = hasCode ? (".r" + code) : ".o"; details.imageFormat = hasCode ? "ubrof" : "elf"; if (architecture.startsWith("arm")) { details.compilerName = "iccarm"; details.assemblerName = "iasmarm"; } else if (architecture === "78k") { details.compilerName = "icc78k"; details.assemblerName = "a78k"; } else if (architecture === "avr") { details.compilerName = "iccavr"; details.assemblerName = "aavr"; } else if (architecture === "avr32") { details.compilerName = "iccavr32"; details.assemblerName = "aavr32"; } else if (architecture === "cr16") { details.compilerName = "icccr16c"; details.assemblerName = "acr16c"; } else if (architecture === "hcs12") { details.compilerName = "icchcs12"; details.assemblerName = "ahcs12"; } else if (architecture === "hcs8") { details.compilerName = "iccs08"; details.assemblerName = "as08"; } else if (architecture === "m16c") { details.compilerName = "iccm16c"; details.assemblerName = "am16c"; } else if (architecture === "m32c") { details.compilerName = "iccm32c"; details.assemblerName = "am32c"; } else if (architecture === "m68k") { details.compilerName = "icccf"; details.assemblerName = "acf"; } else if (architecture === "mcs51") { details.compilerName = "icc8051"; details.assemblerName = "a8051"; } else if (architecture === "msp430") { details.compilerName = "icc430"; details.assemblerName = "a430"; } else if (architecture === "r32c") { details.compilerName = "iccr32c"; details.assemblerName = "ar32c"; } else if (architecture === "rh850") { details.compilerName = "iccrh850"; details.assemblerName = "iasmrh850"; } else if (architecture === "riscv") { details.compilerName = "iccriscv"; details.assemblerName = "iasmriscv"; } else if (architecture === "rl78") { details.compilerName = "iccrl78"; details.assemblerName = "iasmrl78"; } else if (architecture === "rx") { details.compilerName = "iccrx"; details.assemblerName = "iasmrx"; } else if (architecture === "sh") { details.compilerName = "iccsh"; details.assemblerName = "iasmsh"; } else if (architecture === "stm8") { details.compilerName = "iccstm8"; details.assemblerName = "iasmstm8"; } else if (architecture === "v850") { details.compilerName = "iccv850"; details.assemblerName = "av850"; } return details; } function guessArmArchitecture(core) { var arch = "arm"; if (core === "__ARM4M__") arch += "v4m"; else if (core === "__ARM4TM__") arch += "v4tm"; else if (core === "__ARM5E__") arch += "v5e"; else if (core === "__ARM5__") arch += "v5"; else if (core === "__ARM6M__") arch += "v6m"; else if (core === "__ARM6SM__") arch += "v6sm"; else if (core === "__ARM6__") arch += "v6"; else if (core === "__ARM7M__") arch += "v7m"; else if (core === "__ARM7R__") arch += "v7r"; return arch; } function guessArchitecture(macros) { if (macros["__ICC430__"] === "1") return "msp430"; else if (macros["__ICC78K__"] === "1") return "78k"; else if (macros["__ICC8051__"] === "1") return "mcs51"; else if (macros["__ICCARM__"] === "1") return guessArmArchitecture(macros["__CORE__"]); else if (macros["__ICCAVR32__"] === "1") return "avr32"; else if (macros["__ICCAVR__"] === "1") return "avr"; else if (macros["__ICCCF__"] === "1") return "m68k"; else if (macros["__ICCCR16C__"] === "1") return "cr16"; else if (macros["__ICCHCS12__"] === "1") return "hcs12"; else if (macros["__ICCM16C__"] === "1") return "m16c"; else if (macros["__ICCM32C__"] === "1") return "m32c"; else if (macros["__ICCR32C__"] === "1") return "r32c"; else if (macros["__ICCRH850__"] === "1") return "rh850"; else if (macros["__ICCRISCV__"] === "1") return "riscv"; else if (macros["__ICCRL78__"] === "1") return "rl78"; else if (macros["__ICCRX__"] === "1") return "rx"; else if (macros["__ICCS08__"] === "1") return "hcs8"; else if (macros["__ICCSH__"] === "1") return "sh"; else if (macros["__ICCSTM8__"] === "1") return "stm8"; else if (macros["__ICCV850__"] === "1") return "v850"; } function guessEndianness(macros) { if (macros["__LITTLE_ENDIAN__"] === "1") return "little"; return "big" } function guessVersion(macros, architecture) { var version = parseInt(macros["__VER__"], 10); if (architecture.startsWith("arm")) { return { major: parseInt(version / 1000000), minor: parseInt(version / 1000) % 1000, patch: parseInt(version) % 1000 } } else if (architecture === "78k" || architecture === "avr" || architecture === "avr32" || architecture === "cr16" || architecture === "hcs12" || architecture === "hcs8" || architecture === "m16c" || architecture === "m32c" || architecture === "m68k" || architecture === "mcs51" || architecture === "msp430" || architecture === "r32c" || architecture === "rh850" || architecture === "riscv" || architecture === "rl78" || architecture === "rx" || architecture === "sh" || architecture === "stm8" || architecture === "v850") { return { major: parseInt(version / 100), minor: parseInt(version % 100), patch: 0 } } } function cppLanguageOption(compilerFilePath) { var baseName = FileInfo.baseName(compilerFilePath); switch (baseName) { case "iccarm": case "iccrh850": case "iccriscv": case "iccrl78": case "iccrx": return "--c++"; case "icc430": case "icc78k": case "icc8051": case "iccavr": case "iccavr32": case "icccf": case "icccr16c": case "icchcs12": case "iccm16c": case "iccm32c": case "iccr32c": case "iccsh": case "iccstm8": case "iccv850": return "--ec++"; } } function dumpMacros(compilerFilePath, tag) { var tempDir = new TemporaryDir(); var inFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/empty-source.c"); var inFile = new TextFile(inFilePath, TextFile.WriteOnly); var outFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/iar-macros.predef"); var args = [ inFilePath, "--predef_macros", outFilePath ]; if (tag === "cpp" && supportCppLanguage(compilerFilePath)) args.push(cppLanguageOption(compilerFilePath)); var p = new Process(); p.setWorkingDirectory(tempDir.path()); p.exec(compilerFilePath, args, true); var outFile = new TextFile(outFilePath, TextFile.ReadOnly); return Cpp.extractMacros(outFile.readAll()); } function dumpCompilerIncludePaths(compilerFilePath, tag) { // We can dump the compiler include paths using the undocumented `--IDE3` flag, // e.g. which also is used in the IAR extension for the VSCode. In this case the // compiler procuces the console output in the following format: // `$$TOOL_BEGIN $$VERSION "3" $$INC_BEGIN $$FILEPATH "" $$TOOL_END` var tempDir = new TemporaryDir(); var inFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/empty-source.c"); var inFile = new TextFile(inFilePath, TextFile.WriteOnly); var args = ["--IDE3", inFilePath]; if (tag === "cpp" && supportCppLanguage(compilerFilePath)) args.push(cppLanguageOption(compilerFilePath)); var includePaths = []; var p = new Process(); p.setWorkingDirectory(tempDir.path()); // It is possible that the process can return an error code in case the // compiler does not support the `--IDE3` flag. So, don't throw an error in this case. p.exec(compilerFilePath, args, false); p.readStdOut().trim().split(/\r?\n/g).map(function(line) { var m = line.match(/\$\$INC_BEGIN\s\$\$FILEPATH\s\"([^"]*)/); if (m) { var includePath = m[1].replace(/\\\\/g, '/'); if (includePath && File.exists(includePath)) includePaths.push(includePath); } }); if (includePaths.length === 0) { // This can happen if the compiler does not support the `--IDE3` flag, // e.g. IAR for S08 architecture. In this case we use fallback to the // detection of the `inc` directory. var includePath = FileInfo.joinPaths(FileInfo.path(compilerFilePath), "../inc/"); if (File.exists(includePath)) includePaths.push(includePath); } return includePaths; } function dumpDefaultPaths(compilerFilePath, tag) { var includePaths = dumpCompilerIncludePaths(compilerFilePath, tag); return { "includePaths": includePaths }; } function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; // Input. args.push(input.filePath); // Output. args.push("-o", outputs.obj[0].filePath); // Preinclude headers. args = args.concat(Cpp.collectPreincludePathsArguments(input, true)); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); // Silent output generation flag. args.push("--silent"); // Debug information flags. if (input.cpp.debugInformation) args.push("--debug"); // Optimization flags. switch (input.cpp.optimization) { case "small": args.push("-Ohz"); break; case "fast": args.push("-Ohs"); break; case "none": args.push("-On"); break; } var architecture = input.qbs.architecture; var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); // Warning level flags. switch (input.cpp.warningLevel) { case "none": args.push("--no_warnings"); break; case "all": if (supportDeprecatedFeatureWarnings(architecture)) { args.push("--deprecated_feature_warnings=" +"+attribute_syntax," +"+preprocessor_extensions," +"+segment_pragmas"); } if (tag === "cpp" && supportCppWarningAboutCStyleCast(architecture)) args.push("--warn_about_c_style_casts"); break; } if (input.cpp.treatWarningsAsErrors) args.push("--warnings_are_errors"); // C language version flags. if (tag === "c" && supportCLanguageVersion(architecture)) { var knownValues = ["c89"]; var cLanguageVersion = Cpp.languageVersion( input.cpp.cLanguageVersion, knownValues, "C"); switch (cLanguageVersion) { case "c89": args.push("--c89"); break; default: // Default C language version is C18/C11/C99 that // depends on the IAR version. break; } } // C++ language version flags. var compilerFilePath = input.cpp.compilerPath; if (tag === "cpp" && supportCppLanguage(compilerFilePath)) { // C++ language flag. var cppOption = cppLanguageOption(compilerFilePath); args.push(cppOption); // Exceptions flag. var enableExceptions = input.cpp.enableExceptions; if (!enableExceptions && supportCppExceptions(architecture)) args.push("--no_exceptions"); // RTTI flag. var enableRtti = input.cpp.enableRtti; if (!enableRtti && supportCppRtti(architecture)) args.push("--no_rtti"); } // Byte order flags. var endianness = input.cpp.endianness; if (endianness && supportEndianness(architecture)) args.push("--endian=" + endianness); // Listing files generation flag. if (input.cpp.generateCompilerListingFiles) args.push("-l", outputs.lst[0].filePath); // Misc flags. args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(product)); return args; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; // Input. args.push(input.filePath); // Output. args.push("-o", outputs.obj[0].filePath); var architecture = input.qbs.architecture; // The `--preinclude` flag is only supported for a certain // set of assemblers, not for all. if (supportIAssembler(architecture)) args = args.concat(Cpp.collectPreincludePathsArguments(input)); // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); // Debug information flags. if (input.cpp.debugInformation) args.push("-r"); // Architecture specific flags. if (supportIAssembler(architecture)) { // Silent output generation flag. args.push("--silent"); // Warning level flags. if (input.cpp.warningLevel === "none") args.push("--no_warnings"); if (input.cpp.treatWarningsAsErrors) args.push("--warnings_are_errors"); } else if (supportXAssembler(architecture)){ // Silent output generation flag. args.push("-S"); // Warning level flags. args.push("-w" + (input.cpp.warningLevel === "none" ? "-" : "+")); } // Byte order flags. var endianness = input.cpp.endianness; if (endianness && supportEndianness(architecture)) args.push("--endian", endianness); // Listing files generation flag. if (input.cpp.generateAssemblerListingFiles) args.push("-l", outputs.lst[0].filePath); // Misc flags. args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; // Inputs. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); // Output. args.push("-o", outputs.application[0].filePath); // Library paths. args = args.concat(Cpp.collectLibraryPathsArguments(product)); // Library dependencies. args = args.concat(Cpp.collectLibraryDependenciesArguments(product)); // Linker scripts. args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs, true)); // Silent output generation flag. args.push(product.cpp.linkerSilentFlag); // Map file generation flag. if (product.cpp.generateLinkerMapFile) args.push(product.cpp.linkerMapFileFlag, outputs.mem_map[0].filePath); // Entry point flag. if (product.cpp.entryPoint) args.push(product.cpp.linkerEntryPointFlag, product.cpp.entryPoint); // Debug information flag. if (supportXLinker(product.qbs.architecture)) { if (product.cpp.debugInformation) args.push("-rt"); } // Misc flags. args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product), Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); return args; } function archiverFlags(project, product, inputs, outputs) { var args = []; // Inputs. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); // Output. var architecture = product.qbs.architecture; if (supportIArchiver(architecture)) args.push("--create"); args.push("-o", outputs.staticlibrary[0].filePath); Array.prototype.push.apply(args, product.cpp.archiverFlags); return args; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; return [cmd]; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = product.cpp.linkerPath; var cmd = new Command(linkerPath, args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; return [cmd]; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, inputs, outputs); var archiverPath = product.cpp.archiverPath; var cmd = new Command(archiverPath, args); cmd.description = "creating " + output.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; cmd.stdoutFilterFunction = function(output) { return ""; }; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/gcc.js0000644000175100017510000022313415232633614017723 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Codesign = require("../codesign/codesign.js"); var Cpp = require("cpp.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Host = require("qbs.Host"); var DarwinTools = require("qbs.DarwinTools"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var UnixUtils = require("qbs.UnixUtils"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function getLinkerTypeRecursively(product, isDep) { if (isDep) { if (!product.type || !product.artifacts || !product.type.includes("staticlibrary")) return undefined; if (product.artifacts.cpp_staticlibrary) return "cpp"; } var linkerType = undefined; for (var i = 0; i < (product.dependencies || []).length; ++i) { var depType = getLinkerTypeRecursively(product.dependencies[i], true); if (depType === "cpp") return "cpp"; if (depType === "c") linkerType = "c"; } if (!linkerType && product.artifacts.c_staticlibrary) return "c"; return linkerType; } function effectiveLinkerPath(product, inputs) { if (product.cpp.linkerMode === "automatic") { var compilers = product.cpp.compilerPathByLanguage; if (compilers) { if (inputs.cpp_obj || inputs.cpp_staticlibrary) { console.log("Found C++ or Objective-C++ objects, choosing C++ linker for " + product.name); return compilers["cpp"]; } var linkerTypeFromDeps = getLinkerTypeRecursively(product, false); if (linkerTypeFromDeps) return compilers[linkerTypeFromDeps]; if (inputs.c_obj || inputs.c_staticlibrary) { console.log("Found C or Objective-C objects, choosing C linker for " + product.name); return compilers["c"]; } } console.log("Found no C-language objects, choosing system linker for " + product.name); } return product.cpp.linkerPath; } function useCompilerDriverLinker(product, inputs) { var linker = effectiveLinkerPath(product, inputs); var compilers = product.cpp.compilerPathByLanguage; if (compilers) { return linker === compilers["cpp"] || linker === compilers["c"]; } return linker === product.cpp.compilerPath; } function collectLibraryDependencies(product, isDarwin) { var publicDeps = {}; var privateDeps = {}; var objects = []; var objectByFilePath = {}; var tagForLinkingAgainstSharedLib = product.cpp.imageFormat === "pe" ? "dynamiclibrary_import" : "dynamiclibrary"; var removeDuplicateLibraries = product.cpp.removeDuplicateLibraries function addObject(obj, addFunc) { /* If the object is already known, remove its previous usage and insert * it again in the new desired position. This preserves the order of * the other objects, and is analogous to what qmake does (see the * mergeLflags parameter in UnixMakefileGenerator::findLibraries()). */ if (removeDuplicateLibraries && (obj.filePath in objectByFilePath)) { var oldObj = objectByFilePath[obj.filePath]; var i = objects.indexOf(oldObj); if (i >= 0) objects.splice(i, 1); } addFunc.call(objects, obj); objectByFilePath[obj.filePath] = obj; } function addPublicFilePath(filePath, dep) { var existing = objectByFilePath[filePath]; var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive; var symbolLinkMode = dep.parameters.cpp && dep.parameters.cpp.symbolLinkMode; if (existing) { existing.direct = true; existing.wholeArchive = wholeArchive; existing.symbolLinkMode = symbolLinkMode; } else { addObject({ direct: true, filePath: filePath, wholeArchive: wholeArchive, symbolLinkMode: symbolLinkMode }, Array.prototype.unshift); } } function addPrivateFilePath(filePath) { var existing = objectByFilePath[filePath]; if (!existing) addObject({ direct: false, filePath: filePath }, Array.prototype.unshift); } function addArtifactFilePaths(dep, tag, addFunction) { var artifacts = dep.artifacts[tag]; if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); for (var i = 0; i < artifactFilePaths.length; ++i) addFunction(artifactFilePaths[i], dep); } function addExternalLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return (a instanceof Array) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } var externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "libraries")), ensureArray(sanitizedModuleListProperty(obj, "cpp", "staticLibraries")), ensureArray(sanitizedModuleListProperty(obj, "cpp", "dynamicLibraries"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i] }, Array.prototype.push); if (isDarwin) { externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "frameworks"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i], framework: true }, Array.prototype.push); externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "weakFrameworks"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i], framework: true, symbolLinkMode: "weak" }, Array.prototype.push); } } function traverse(dep, isBelowIndirectDynamicLib, someDepConsumesObjects) { if (publicDeps[dep.name]) return; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var isStaticLibrary = typeof dep.artifacts["staticlibrary"] !== "undefined"; var isObjectLibrary = !isStaticLibrary && typeof dep.artifacts["objectlibrary"] !== "undefined"; var isDynamicLibrary = !isStaticLibrary && !isObjectLibrary && typeof dep.artifacts[tagForLinkingAgainstSharedLib] !== "undefined"; if (!isStaticLibrary && !isObjectLibrary && !isDynamicLibrary) return; if (isBelowIndirectDynamicLib && privateDeps[dep.name]) return; var nextIsBelowIndirectDynamicLib = isBelowIndirectDynamicLib || isDynamicLibrary; dep.dependencies.forEach(function(depdep) { // If "dep" is an aggregate product, and "depdep" is one of the multiplexed variants // of the same product, we don't want to depend on the multiplexed variants, because // that could mean linking more than one time against the same library. Instead skip // the multiplexed dependency, and depend only on the aggregate one. if (depdep.name === dep.name) return; traverse(depdep, nextIsBelowIndirectDynamicLib, someDepConsumesObjects || !isObjectLibrary); }); if (isStaticLibrary || isObjectLibrary) { if (!isBelowIndirectDynamicLib) { if (isStaticLibrary || !someDepConsumesObjects) { addArtifactFilePaths(dep, isStaticLibrary ? "staticlibrary" : "objectlibrary", addPublicFilePath); } if (product.cpp.importPrivateLibraries) addExternalLibs(dep); publicDeps[dep.name] = true; } } else if (isDynamicLibrary) { if (!isBelowIndirectDynamicLib) { addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPublicFilePath); publicDeps[dep.name] = true; } else { addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath); privateDeps[dep.name] = true; } } } function traverseDirectDependency(dep) { traverse(dep, false, false); } product.dependencies.forEach(traverseDirectDependency); addExternalLibs(product); var result = { libraries: [], rpath_link: [] }; objects.forEach( function (obj) { if (obj.direct) { result.libraries.push({ filePath: obj.filePath, wholeArchive: obj.wholeArchive, symbolLinkMode: obj.symbolLinkMode, framework: obj.framework }); } else { var dirPath = FileInfo.path(obj.filePath); result.rpath_link.push(dirPath); } }); return result; } function escapeLinkerFlags(product, inputs, linkerFlags) { if (!linkerFlags || linkerFlags.length === 0) return []; if (useCompilerDriverLinker(product, inputs)) { var sep = ","; var useXlinker = linkerFlags.some(function (f) { return f.includes(sep); }); if (useXlinker) { // One or more linker arguments contain the separator character itself // Use -Xlinker to handle these var xlinkerFlags = []; linkerFlags.map(function (linkerFlag) { if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlag.startsWith("-Wl,")) { console.warn("Encountered escaped linker flag '" + linkerFlag + "'. This may " + "cause the target to fail to link. Please do not escape these " + "flags manually; qbs does that for you."); } xlinkerFlags.push("-Xlinker", linkerFlag); }); return xlinkerFlags; } if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlags.includes("-Xlinker")) { console.warn("Encountered -Xlinker linker flag escape sequence. This may cause the " + "target to fail to link. Please do not escape these flags manually; " + "qbs does that for you."); } // If no linker arguments contain the separator character we can just use -Wl, // which is more compact and easier to read in logs return [["-Wl"].concat(linkerFlags).join(sep)]; } return linkerFlags; } function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath) { var isDarwin = product.qbs.targetOS.includes("darwin"); var libraryDependencies = collectLibraryDependencies(product, isDarwin); var systemRunPaths = product.cpp.systemRunPaths || []; var canonicalSystemRunPaths = systemRunPaths.map(function(p) { return File.canonicalFilePath(p); }); var i, args = additionalCompilerAndLinkerFlags(product); var escapableLinkerFlags = []; if (primaryOutput.fileTags.includes("dynamiclibrary")) { if (isDarwin) { args.push((function () { var tags = ["c", "cpp", "cppm", "objc", "objcpp", "asm_cpp"]; for (var i = 0; i < tags.length; ++i) { if (linkerPath === product.cpp.compilerPathByLanguage[tags[i]]) return "-dynamiclib"; } return "-dylib"; // for ld64 })()); } else { args.push("-shared"); } if (isDarwin) { if (product.cpp.internalVersion) args.push("-current_version", product.cpp.internalVersion); escapableLinkerFlags.push("-install_name", UnixUtils.soname(product, primaryOutput.fileName)); } else if (product.cpp.imageFormat === "elf") { escapableLinkerFlags.push("-soname=" + UnixUtils.soname(product, primaryOutput.fileName)); } } if (primaryOutput.fileTags.includes("loadablemodule")) args.push(isDarwin ? "-bundle" : "-shared"); if (primaryOutput.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) { if (isDarwin) escapableLinkerFlags.push("-headerpad_max_install_names"); else if (product.cpp.imageFormat === "elf") escapableLinkerFlags.push("--as-needed"); } if (isLegacyQnxSdk(product)) { ["c", "cpp"].map(function (tag) { if (linkerPath === product.cpp.compilerPathByLanguage[tag]) args = args.concat(qnxLangArgs(product, tag)); }); } var targetLinkerFlags = product.cpp.targetLinkerFlags; if (targetLinkerFlags) Array.prototype.push.apply(escapableLinkerFlags, targetLinkerFlags); var sysroot = product.cpp.syslibroot; if (sysroot) { if (product.qbs.toolchain.includes("qcc")) escapableLinkerFlags.push("--sysroot=" + sysroot); else if (isDarwin) escapableLinkerFlags.push("-syslibroot", sysroot); else args.push("--sysroot=" + sysroot); // do not escape, compiler-as-linker also needs it } if (product.cpp.allowUnresolvedSymbols) { if (isDarwin) escapableLinkerFlags.push("-undefined", "suppress"); else escapableLinkerFlags.push("--unresolved-symbols=ignore-all"); } function fixupRPath(rpath) { // iOS, tvOS, watchOS, and others, are fine if (!product.qbs.targetOS.includes("macos")) return rpath; // ...as are newer versions of macOS var min = product.cpp.minimumMacosVersion; if (min && Utilities.versionCompare(min, "10.10") >= 0) return rpath; // In older versions of dyld, a trailing slash is required if (!rpath.endsWith("/")) return rpath + "/"; return rpath; } function isNotSystemRunPath(p) { return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.includes(p) && !canonicalSystemRunPaths.includes(File.canonicalFilePath(p))); }; if (product.cpp.useRPathLink && !product.cpp.rpathLinkFlag) throw new Error("cpp.useRPathLink is enabled, but cpp.rpathLinkFlag is not defined"); if (!product.qbs.targetOS.includes("windows")) { var rpaths = product.cpp.useRPaths ? product.cpp.rpaths : undefined; for (i in rpaths) { if (isNotSystemRunPath(rpaths[i])) escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i])); } var rpathLinks = product.cpp.useRPathLink ? product.cpp.rpathLinkDirs : undefined; for (i in rpathLinks) escapableLinkerFlags.push("-rpath-link", rpathLinks[i]); } if (product.cpp.entryPoint) escapableLinkerFlags.push("-e", product.cpp.entryPoint); if (product.qbs.toolchain.includes("mingw")) { if (product.consoleApplication !== undefined) escapableLinkerFlags.push("-subsystem", product.consoleApplication ? "console" : "windows"); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; if (minimumWindowsVersion) { // workaround for QBS-1724, mingw seems to be broken if (Utilities.versionCompare(minimumWindowsVersion, "6.2") > 0) minimumWindowsVersion = "6.2"; var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { var major = subsystemVersion.split('.')[0]; var minor = subsystemVersion.split('.')[1]; // http://sourceware.org/binutils/docs/ld/Options.html escapableLinkerFlags.push("--major-subsystem-version", major, "--minor-subsystem-version", minor, "--major-os-version", major, "--minor-os-version", minor); } } } if (inputs.aggregate_infoplist) args.push("-sectcreate", "__TEXT", "__info_plist", inputs.aggregate_infoplist[0].filePath); var isLinkingCppObjects = !!(inputs.cpp_obj || inputs.cpp_staticlibrary); var stdlib = isLinkingCppObjects ? product.cpp.cxxStandardLibrary : undefined; if (stdlib && product.qbs.toolchain.includes("clang")) args.push("-stdlib=" + stdlib); // Flags for library search paths var allLibraryPaths = Cpp.collectLibraryPaths(product); var builtIns = product.cpp.compilerLibraryPaths allLibraryPaths = allLibraryPaths.filter(function(p) { return !builtIns.includes(p); }); args = args.concat(allLibraryPaths.map(function(path) { return product.cpp.libraryPathFlag + path })); escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs)); var versionScripts = inputs.versionscript ? inputs.versionscript.map(function(a) { return a.filePath; }) : []; Array.prototype.push.apply(escapableLinkerFlags, [].uniqueConcat(versionScripts) .map(function(path) { return '--version-script=' + path })); if (isDarwin && product.cpp.warningLevel === "none") args.push('-w'); var useCompilerDriver = useCompilerDriverLinker(product, inputs); args = args.concat(configFlags(product, useCompilerDriver)); escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectMiscEscapableLinkerArguments(product)); // Note: due to the QCC response files hack in prepareLinker(), at least one object file or // library file must follow the output file path so that QCC has something to process before // sending the rest of the arguments through the response file. args.push("-o", primaryOutput.filePath); args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); args = args.concat(Cpp.collectResourceObjectPaths(inputs)); var wholeArchiveActive = false; var prevLib; for (i = 0; i < libraryDependencies.libraries.length; ++i) { var dep = libraryDependencies.libraries[i]; var lib = dep.filePath; if (lib === prevLib) continue; prevLib = lib; if (dep.wholeArchive && !wholeArchiveActive) { var wholeArchiveFlag; if (isDarwin) { wholeArchiveFlag = "-force_load"; } else { wholeArchiveFlag = "--whole-archive"; wholeArchiveActive = true; } Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, [wholeArchiveFlag])); } if (!dep.wholeArchive && wholeArchiveActive) { Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, ["--no-whole-archive"])); wholeArchiveActive = false; } var symbolLinkMode = dep.symbolLinkMode; if (isDarwin && symbolLinkMode) { if (!["lazy", "reexport", "upward", "weak"].includes(symbolLinkMode)) throw new Error("unknown value '" + symbolLinkMode + "' for cpp.symbolLinkMode"); } var supportsLazyMode = Utilities.versionCompare(product.cpp.compilerVersion, "15.0.0") < 0; if (isDarwin && symbolLinkMode && (symbolLinkMode !== "lazy" || supportsLazyMode)) { if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) escapableLinkerFlags.push("-" + symbolLinkMode + "_library", lib); else if (dep.framework) escapableLinkerFlags.push("-" + symbolLinkMode + "_framework", lib); else escapableLinkerFlags.push("-" + symbolLinkMode + "-l" + lib); } else if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) { args.push(dep.framework ? PathTools.frameworkExecutablePath(lib) : lib); } else if (dep.framework) { args.push("-framework", lib); } else { args.push('-l' + lib); } } if (wholeArchiveActive) { Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, ["--no-whole-archive"])); } var discardUnusedData = product.cpp.discardUnusedData; if (discardUnusedData !== undefined) { var flags = []; if (discardUnusedData === true) { if (isDarwin) escapableLinkerFlags.push("-dead_strip"); else escapableLinkerFlags.push("--gc-sections"); } else if (!isDarwin) { escapableLinkerFlags.push("--no-gc-sections"); } } if (product.cpp.useRPathLink) { Array.prototype.push.apply(escapableLinkerFlags, libraryDependencies.rpath_link.map( function(dir) { return product.cpp.rpathLinkFlag + dir; })); } var importLibs = outputs.dynamiclibrary_import; if (importLibs) escapableLinkerFlags.push("--out-implib", importLibs[0].filePath); if (outputs.application && product.cpp.generateLinkerMapFile) { if (isDarwin) escapableLinkerFlags.push("-map", outputs.mem_map[0].filePath); else escapableLinkerFlags.push("-Map=" + outputs.mem_map[0].filePath); } var escapedLinkerFlags = escapeLinkerFlags(product, inputs, escapableLinkerFlags); Array.prototype.push.apply(escapedLinkerFlags, args); if (useCompilerDriver) escapedLinkerFlags = escapedLinkerFlags.concat(Cpp.collectMiscLinkerArguments(product)); if (product.qbs.toolchain.includes("mingw") && product.cpp.runtimeLibrary === "static") escapedLinkerFlags = ['-static-libgcc', '-static-libstdc++'].concat(escapedLinkerFlags); return escapedLinkerFlags; } // for compiler AND linker function configFlags(config, isDriver) { var args = []; if (isDriver !== false) args = args.concat(Cpp.collectMiscDriverArguments(config)); var frameworkPaths = config.cpp.frameworkPaths; if (frameworkPaths) args = args.uniqueConcat(frameworkPaths.map(function(path) { return '-F' + path })); var allSystemFrameworkPaths = []; var systemFrameworkPaths = config.cpp.systemFrameworkPaths; if (systemFrameworkPaths) allSystemFrameworkPaths = allSystemFrameworkPaths.uniqueConcat(systemFrameworkPaths); var distributionFrameworkPaths = config.cpp.distributionFrameworkPaths; if (distributionFrameworkPaths) allSystemFrameworkPaths = allSystemFrameworkPaths.uniqueConcat(distributionFrameworkPaths); args = args.concat(allSystemFrameworkPaths.map(function(path) { return '-iframework' + path })); return args; } function languageTagFromFileExtension(toolchain, fileName) { var i = fileName.lastIndexOf('.'); if (i === -1) return; var m = { "c" : "c", "C" : "cpp", "cpp" : "cpp", "cxx" : "cpp", "c++" : "cpp", "cc" : "cpp", "m" : "objc", "mm" : "objcpp", "s" : "asm", "S" : "asm_cpp" }; if (!toolchain.includes("clang")) m["sx"] = "asm_cpp"; // clang does NOT recognize .sx else m["cppm"] = "cppm"; return m[fileName.substring(i + 1)]; } // Older versions of the QNX SDK have C and C++ compilers whose filenames differ only by case, // which won't work in case insensitive environments like Win32+NTFS, HFS+ and APFS function isLegacyQnxSdk(config) { return config.qbs.toolchain.includes("qcc") && config.qnx && !config.qnx.qnx7; } function effectiveCompilerInfo(toolchain, input, output) { var compilerPath, language; var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); // Whether we're compiling a precompiled header or normal source file var pchOutput = output.fileTags.includes(tag + "_pch"); var compilerPathByLanguage = input.cpp.compilerPathByLanguage; if (compilerPathByLanguage) compilerPath = compilerPathByLanguage[tag]; if (!compilerPath || tag !== languageTagFromFileExtension(toolchain, input.fileName) || isLegacyQnxSdk(input)) { if (input.qbs.toolchain.includes("qcc")) language = qnxLangArgs(input, tag); else language = ["-x", languageName(tag) + (pchOutput ? '-header' : '')]; } if (!compilerPath) // fall back to main compiler compilerPath = input.cpp.compilerPath; return { path: compilerPath, language: language, tag: tag }; } function qnxLangArgs(config, tag) { switch (tag) { case "c": return ["-lang-c"]; case "cpp": return ["-lang-c++"]; default: return []; } } function handleCpuFeatures(input, flags) { function potentiallyAddFlagForFeature(propName, flagName) { var propValue = input.cpufeatures[propName]; if (propValue === true) flags.push("-m" + flagName); else if (propValue === false) flags.push("-mno-" + flagName); } if (!input.qbs.architecture) return; if (input.qbs.architecture.startsWith("x86")) { potentiallyAddFlagForFeature("x86_avx", "avx"); potentiallyAddFlagForFeature("x86_avx2", "avx2"); potentiallyAddFlagForFeature("x86_avx512bw", "avx512bw"); potentiallyAddFlagForFeature("x86_avx512cd", "avx512cd"); potentiallyAddFlagForFeature("x86_avx512dq", "avx512dq"); potentiallyAddFlagForFeature("x86_avx512er", "avx512er"); potentiallyAddFlagForFeature("x86_avx512f", "avx512f"); potentiallyAddFlagForFeature("x86_avx512ifma", "avx512ifma"); potentiallyAddFlagForFeature("x86_avx512pf", "avx512pf"); potentiallyAddFlagForFeature("x86_avx512vbmi", "avx512vbmi"); potentiallyAddFlagForFeature("x86_avx512vl", "avx512vl"); potentiallyAddFlagForFeature("x86_f16c", "f16c"); potentiallyAddFlagForFeature("x86_sse2", "sse2"); potentiallyAddFlagForFeature("x86_sse3", "sse3"); potentiallyAddFlagForFeature("x86_sse4_1", "sse4.1"); potentiallyAddFlagForFeature("x86_sse4_2", "sse4.2"); potentiallyAddFlagForFeature("x86_ssse3", "ssse3"); } else if (input.qbs.architecture.startsWith("arm")) { if (input.cpufeatures.arm_neon === true) flags.push("-mfpu=neon"); if (input.cpufeatures.arm_vfpv4 === true) flags.push("-mfpu=vfpv4"); } else if (input.qbs.architecture.startsWith("mips")) { potentiallyAddFlagForFeature("mips_dsp", "dsp"); potentiallyAddFlagForFeature("mips_dspr2", "dspr2"); } } function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVersion, useLanguageVersionFallback) { // NEVER use the fallback values (safety brake for users in case our version map is ever wrong) if (useLanguageVersionFallback === false) return languageVersion; // Deprecated, but compatible with older compiler versions. // Note that these versions are the first to support the *value* to the -std= command line // option, not necessarily the first versions where support for that language standard was // considered fully implemented. Tested manually. var languageVersionsMap = { "c++11": { "fallback": "c++0x", "toolchains": [ {"name": "xcode", "version": "4.3"}, {"name": "clang", "version": "3.0"}, {"name": "gcc", "version": "4.7"} ] }, "c11": { "fallback": "c1x", "toolchains": [ {"name": "xcode", "version": "5.0"}, {"name": "clang", "version": "3.1"}, {"name": "gcc", "version": "4.7"} ] }, "c17": { "fallback": "c11", "toolchains": [ {"name": "xcode", "version": "10.2"}, {"name": "clang", "version": "7.0"}, {"name": "gcc", "version": "8.1"} ] }, "c2x": { "fallback": "c17", "toolchains": [ {"name": "xcode", "version": "11.4"}, {"name": "clang", "version": "9.0"}, {"name": "gcc", "version": "9.0"} ] }, "c++14": { "fallback": "c++1y", "toolchains": [ {"name": "xcode", "version": "6.3"}, {"name": "clang", "version": "3.5"}, {"name": "gcc", "version": "4.9"} ] }, "c++17": { "fallback": "c++1z", "toolchains": [ {"name": "xcode", "version": "9.3"}, {"name": "clang", "version": "5.0"}, {"name": "gcc", "version": "5.1"} ] }, "c++20": { "fallback": "c++2a", "toolchains": [ {"name": "xcode", "version": "12.5"}, {"name": "clang", "version": "11.0"}, {"name": "gcc", "version": "10.1"} ] }, "c++23": { "fallback": "c++2b", "toolchains": [ {"name": "xcode", "version": "15.0"}, {"name": "clang", "version": "13.0"}, {"name": "gcc", "version": "11.1"} ] }, "c++26": { "fallback": "c++2c", "toolchains": [ {"name": "xcode", "version": "17.0"}, {"name": "clang", "version": "19.0"}, {"name": "gcc", "version": "15.1"} ] } }; var m = languageVersionsMap[languageVersion]; if (m) { for (var idx = 0; idx < m.toolchains.length; ++idx) { var tc = m.toolchains[idx]; if (toolchain.includes(tc.name)) { // If we found our toolchain and it doesn't yet support the language standard // we're requesting, or we're using an older version that only supports the // preliminary flag, use that. if (useLanguageVersionFallback || !tc.version || Utilities.versionCompare(compilerVersion, tc.version) < 0) return m.fallback; break; } } } // If we didn't find our toolchain at all, simply use the standard value. return languageVersion; } function compilerFlags(project, product, outputs, input, output, explicitlyDependsOn) { var i; // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); if (!["c", "cpp", "cppm", "objc", "objcpp", "asm_cpp"].includes(tag)) throw ("unsupported source language: " + tag); var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain, input, output); var args = additionalCompilerAndLinkerFlags(product); Array.prototype.push.apply(args, product.cpp.sysrootFlags); handleCpuFeatures(input, args); if (input.cpp.debugInformation) args.push('-g'); var opt = input.cpp.optimization if (opt === 'fast') args.push('-O2'); if (opt === 'small') args.push('-Os'); if (opt === 'none') args.push('-O0'); if (input.cpp.forceUseCxxModules) { if (!product.qbs.toolchain.includes("clang")) args.push('-fmodules-ts') } var warnings = input.cpp.warningLevel if (warnings === 'none') args.push('-w'); if (warnings === 'all') { args.push('-Wall'); args.push('-Wextra'); } if (input.cpp.treatWarningsAsErrors) args.push('-Werror'); var moduleMap = (outputs["modulemap"] || [])[0]; if (moduleMap) { const moduleMapperFlag = product.qbs.toolchain.includes("clang") ? "@" // clang uses response file with the list of flags : "-fmodule-mapper="; // gcc uses file with special syntax args.push(moduleMapperFlag + moduleMap.filePath); } args = args.concat(configFlags(input)); if (!input.qbs.toolchain.includes("qcc")) args.push('-pipe'); if (input.cpp.enableReproducibleBuilds) { var toolchain = product.qbs.toolchain; if (!toolchain.includes("clang")) { var hashString = FileInfo.relativePath(project.sourceDirectory, input.filePath); var hash = Utilities.getHash(hashString); args.push("-frandom-seed=0x" + hash.substring(0, 8)); } var major = product.cpp.compilerVersionMajor; var minor = product.cpp.compilerVersionMinor; if ((toolchain.includes("clang") && (major > 3 || (major === 3 && minor >= 5))) || (toolchain.includes("gcc") && (major > 4 || (major === 4 && minor >= 9)))) { args.push("-Wdate-time"); } } var useArc = input.cpp.automaticReferenceCounting; if (useArc !== undefined && (tag === "objc" || tag === "objcpp")) { args.push(useArc ? "-fobjc-arc" : "-fno-objc-arc"); } var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) { if (tag === "cpp" || tag === "objcpp" || tag === "cppm") args.push(enableExceptions ? "-fexceptions" : "-fno-exceptions"); if (tag === "objc" || tag === "objcpp") { args.push(enableExceptions ? "-fobjc-exceptions" : "-fno-objc-exceptions"); if (useArc !== undefined) args.push(useArc ? "-fobjc-arc-exceptions" : "-fno-objc-arc-exceptions"); } } var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined && (tag === "cpp" || tag === "objcpp" || tag === "cppm")) { args.push(enableRtti ? "-frtti" : "-fno-rtti"); } var visibility = input.cpp.visibility; if (!product.qbs.toolchain.includes("mingw")) { if (visibility === 'hidden' || visibility === 'minimal') args.push('-fvisibility=hidden'); if ((visibility === 'hiddenInlines' || visibility === 'minimal') && tag === 'cpp') args.push('-fvisibility-inlines-hidden'); if (visibility === 'default') args.push('-fvisibility=default') } if (compilerInfo.language) // Only push language arguments if we have to. Array.prototype.push.apply(args, compilerInfo.language); args = args.concat(Cpp.collectMiscCompilerArguments(input, tag)); var pchTag = compilerInfo.tag + "_pch"; var pchOutput = output.fileTags.includes(pchTag); var pchInputs = explicitlyDependsOn[pchTag]; if (!pchOutput && pchInputs && pchInputs.length === 1 && ModUtils.moduleProperty(input, 'usePrecompiledHeader', tag)) { var pchInput = pchInputs[0]; if (input.qbs.toolchain.includes("clang")) { args.push("-include-pch", pchInput.filePath); } else { var pchFilePath = FileInfo.joinPaths(FileInfo.path(pchInput.filePath), pchInput.completeBaseName); args.push(input.cpp.preincludeFlag, pchFilePath); } } args = args.concat(Cpp.collectPreincludePathsArguments(input)); var positionIndependentCode = input.cpp.positionIndependentCode; if (positionIndependentCode && !product.qbs.targetOS.includes("windows")) args.push('-fPIC'); var cppFlags = input.cpp.cppFlags; for (i in cppFlags) args.push('-Wp,' + cppFlags[i]) args = args.concat(Cpp.collectDefinesArguments(input)); args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); var minimumWindowsVersion = input.cpp.minimumWindowsVersion; if (minimumWindowsVersion && product.qbs.targetOS.includes("windows")) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) args.push(input.cpp.defineFlag + versionDefs[i] + '=' + hexVersion); } } function currentLanguageVersion(tag) { switch (tag) { case "c": case "objc": var knownValues = ["c2x", "c17", "c11", "c99", "c90", "c89"]; return Cpp.languageVersion(input.cpp.cLanguageVersion, knownValues, "C"); case "cpp": case "cppm": case "objcpp": knownValues = ["c++26", "c++2c", "c++23", "c++2b", "c++20", "c++2a", "c++17", "c++1z", "c++14", "c++1y", "c++11", "c++0x", "c++03", "c++98"]; return Cpp.languageVersion(input.cpp.cxxLanguageVersion, knownValues, "C++"); } } var langVersion = currentLanguageVersion(tag); if (langVersion) { args.push("-std=" + standardFallbackValueOrDefault(product.qbs.toolchain, product.cpp.compilerVersion, langVersion, product.cpp.useLanguageVersionFallback)); } if (tag === "cpp" || tag === "objcpp" || tag === "cppm") { var cxxStandardLibrary = product.cpp.cxxStandardLibrary; if (cxxStandardLibrary && product.qbs.toolchain.includes("clang")) { args.push("-stdlib=" + cxxStandardLibrary); } } if (input.cpp.enableTimeTrace && product.cpp._supportsTimeTrace) { var timeTraceFileName = FileInfo.joinPaths(FileInfo.path(output.filePath), input.fileName + ".time_trace.json"); args.push("-ftime-trace=" + timeTraceFileName); } args.push("-o", output.filePath); args.push("-c", input.filePath); return args; } function additionalCompilerAndLinkerFlags(product) { var args = [] var requireAppExtensionSafeApi = product.cpp.requireAppExtensionSafeApi; if (requireAppExtensionSafeApi !== undefined && product.qbs.targetOS.includes("darwin")) { args.push(requireAppExtensionSafeApi ? "-fapplication-extension" : "-fno-application-extension"); } return args } // Returns the GCC language name equivalent to fileTag, accepted by the -x argument function languageName(fileTag) { if (fileTag === 'c') return 'c'; else if (fileTag === 'cpp') return 'c++'; else if (fileTag === 'cppm') return 'c++'; else if (fileTag === 'objc') return 'objective-c'; else if (fileTag === 'objcpp') return 'objective-c++'; else if (fileTag === 'asm') return 'assembler'; else if (fileTag === 'asm_cpp') return 'assembler-with-cpp'; } function prepareAssembler(project, product, inputs, outputs, input, output) { var assemblerPath = product.cpp.assemblerPath; var args = product.cpp.targetAssemblerFlags; if (input.cpp.debugInformation) args.push('-g'); var warnings = input.cpp.warningLevel if (warnings === 'none') args.push('-W'); args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input, input.cpp.includeFlag)); args.push("-o", output.filePath); args.push(input.filePath); var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; return cmd; } function compilerEnvVars(config, compilerInfo) { if (config.qbs.toolchain.includes("qcc")) return ["QCC_CONF_PATH"]; var list = ["CPATH", "TMPDIR"]; if (compilerInfo.tag === "c") list.push("C_INCLUDE_PATH"); else if (compilerInfo.tag === "cpp") list.push("CPLUS_INCLUDE_PATH"); else if (compilerInfo.tag === "cppm") list.push("CPLUS_INCLUDE_PATH"); else if (compilerInfo.tag === "objc") list.push("OBJC_INCLUDE_PATH"); else if (compilerInfo.tag === "objccpp") list.push("OBJCPLUS_INCLUDE_PATH"); if (config.qbs.targetOS.includes("macos")) list.push("MACOSX_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.includes("ios")) list.push("IPHONEOS_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.includes("tvos")) list.push("TVOS_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.includes("watchos")) list.push("WATCHOS_DEPLOYMENT_TARGET"); if (config.qbs.toolchain.includes("clang")) { list.push("TEMP", "TMP"); } else { list.push("LANG", "LC_CTYPE", "LC_MESSAGES", "LC_ALL", "GCC_COMPARE_DEBUG", "GCC_EXEC_PREFIX", "COMPILER_PATH", "SOURCE_DATE_EPOCH"); } return list; } function linkerEnvVars(config, inputs) { if (config.qbs.toolchain.includes("clang") || config.qbs.toolchain.includes("qcc")) return []; var list = ["GNUTARGET", "LDEMULATION", "COLLECT_NO_DEMANGLE"]; if (useCompilerDriverLinker(config, inputs)) list.push("LIBRARY_PATH"); return list; } function setResponseFileThreshold(command, product) { if (Host.os().includes("windows")) command.responseFileThreshold = 8000; } function prepareCompilerInternal(project, product, inputs, outputs, input, output_, explicitlyDependsOn) { var output = output_ || outputs["obj"][0]; var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain, input, output); var compilerPath = compilerInfo.path; var pchOutput = output.fileTags.includes(compilerInfo.tag + "_pch"); var args = compilerFlags(project, product, outputs, input, output, explicitlyDependsOn); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.compilerWrapper; var extraEnv; if (wrapperArgs && wrapperArgs.length > 0) { // distcc cannot deal with absolute compiler paths (QBS-1336). for (var i = 0; i < wrapperArgs.length; ++i) { if (FileInfo.baseName(wrapperArgs[i]) !== "distcc") continue; if (i === wrapperArgs.length - 1) { if (FileInfo.isAbsolutePath(compilerPath)) { extraEnv = ["PATH=" + FileInfo.path(compilerPath)]; compilerPath = FileInfo.fileName(compilerPath); } } else if (FileInfo.isAbsolutePath(wrapperArgs[i + 1])) { extraEnv = ["PATH=" + FileInfo.path(FileInfo.path(wrapperArgs[i + 1]))]; wrapperArgs[i + 1] = FileInfo.fileName(wrapperArgs[i + 1]); } break; } wrapperArgsLength = wrapperArgs.length; args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var cmd = new Command(compilerPath, args); cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + compilerInfo.tag + ')'; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmd.relevantEnvironmentVariables = compilerEnvVars(input, compilerInfo); if (extraEnv) cmd.environment = extraEnv; cmd.responseFileArgumentIndex = wrapperArgsLength; cmd.responseFileUsagePrefix = '@'; setResponseFileThreshold(cmd, product); return cmd; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var result = Cpp.prepareModules(project, product, inputs, outputs, input, output); result = result.concat(prepareCompilerInternal( project, product, inputs, outputs, input, output, explicitlyDependsOn)); return result; } // Concatenates two arrays of library names and preserves the dependency order that ld needs. function concatLibs(libs, deplibs) { var r = []; var s = {}; function addLibs(lst) { for (var i = lst.length; --i >= 0;) { var lib = lst[i]; if (!s[lib]) { s[lib] = true; r.unshift(lib); } } } addLibs(deplibs); addLibs(libs); return r; } function collectStdoutLines(command, args) { var p = new Process(); try { p.exec(command, args); return p.readStdOut().split(/\r?\n/g).filter(function (e) { return e; }); } finally { p.close(); } } function getSymbolInfo(product, inputFile) { var result = { }; var command = product.cpp.nmPath; var args = ["-g", "-P"]; if (product.cpp._nmHasDynamicOption) args.push("-D"); try { result.allGlobalSymbols = collectStdoutLines(command, args.concat(inputFile)); // GNU nm has the "--defined" option but POSIX nm does not, so we have to manually // construct the list of defined symbols by subtracting. var undefinedGlobalSymbols = collectStdoutLines(command, args.concat(["-u", inputFile])); result.definedGlobalSymbols = result.allGlobalSymbols.filter(function(line) { return !undefinedGlobalSymbols.includes(line); }); result.success = true; } catch (e) { console.debug("Failed to collect symbols for shared library: nm command '" + command + "' failed (" + e.toString() + ")"); result.success = false; } return result; } function createSymbolFile(filePath, allSymbols, definedSymbols) { var file; try { file = new TextFile(filePath, TextFile.WriteOnly); for (var lineNr in allSymbols) file.writeLine(allSymbols[lineNr]); file.writeLine("==="); for (lineNr in definedSymbols) file.writeLine(definedSymbols[lineNr]); } finally { if (file) file.close(); } } function readSymbolFile(filePath) { var result = { success: true, allGlobalSymbols: [], definedGlobalSymbols: [] }; var file; try { file = new TextFile(filePath, TextFile.ReadOnly); var prop = "allGlobalSymbols"; while (true) { var line = file.readLine(); if (!line) break; if (line === "===") { prop = "definedGlobalSymbols"; continue; } result[prop].push(line); } } catch (e) { console.debug("Failed to read symbols from '" + filePath + "'"); result.success = false; } finally { if (file) file.close(); } return result; } function createSymbolCheckingCommands(product, outputs) { var commands = []; if (!outputs.dynamiclibrary || !outputs.dynamiclibrary_symbols) return commands; if (outputs.dynamiclibrary.length !== outputs.dynamiclibrary_symbols.length) throw new Error("The number of outputs tagged dynamiclibrary (" + outputs.dynamiclibrary.length + ") must be equal to the number of " + "outputs tagged dynamiclibrary_symbols (" + outputs.dynamiclibrary_symbols.length + ")"); for (var d = 0; d < outputs.dynamiclibrary_symbols.length; ++d) { // Update the symbols file if the list of relevant symbols has changed. var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.d = d; cmd.sourceCode = function() { if (outputs.dynamiclibrary[d].qbs.buildVariant !== outputs.dynamiclibrary_symbols[d].qbs.buildVariant) throw new Error("Build variant of output tagged dynamiclibrary (" + outputs.dynamiclibrary[d].qbs.buildVariant + ") is not equal to " + "build variant of output tagged dynamiclibrary_symbols (" + outputs.dynamiclibrary_symbols[d].qbs.buildVariant + ") at index " + d); var libFilePath = outputs.dynamiclibrary[d].filePath; var symbolFilePath = outputs.dynamiclibrary_symbols[d].filePath; var newNmResult = getSymbolInfo(product, libFilePath); if (!newNmResult.success) return; if (!File.exists(symbolFilePath)) { console.debug("Symbol file '" + symbolFilePath + "' does not yet exist."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } var oldNmResult = readSymbolFile(symbolFilePath); var checkMode = product.cpp.exportedSymbolsCheckMode; var oldSymbols; var newSymbols; if (checkMode === "strict") { oldSymbols = oldNmResult.allGlobalSymbols; newSymbols = newNmResult.allGlobalSymbols; } else { var weakFilter = function(line) { var symbolType = line.split(/\s+/)[1]; return symbolType != "v" && symbolType != "V" && symbolType != "w" && symbolType != "W"; }; oldSymbols = oldNmResult.definedGlobalSymbols.filter(weakFilter); newSymbols = newNmResult.definedGlobalSymbols.filter(weakFilter); } if (oldSymbols.length !== newSymbols.length) { console.debug("List of relevant symbols differs for '" + libFilePath + "'."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } for (var i = 0; i < oldSymbols.length; ++i) { var oldLine = oldSymbols[i]; var newLine = newSymbols[i]; var oldLineElems = oldLine.split(/\s+/); var newLineElems = newLine.split(/\s+/); if (oldLineElems[0] !== newLineElems[0] // Object name. || oldLineElems[1] !== newLineElems[1]) { // Object type console.debug("List of relevant symbols differs for '" + libFilePath + "'."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } } } commands.push(cmd); } return commands; } function separateDebugInfoCommands(product, outputs, primaryOutput) { var commands = []; var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll || outputs.debuginfo_loadablemodule; if (debugInfo && !product.qbs.toolchain.includes("emscripten")) { var objcopy = product.cpp.objcopyPath; var cmd = new Command(objcopy, ["--only-keep-debug", primaryOutput.filePath, debugInfo[0].filePath]); cmd.silent = true; commands.push(cmd); cmd = new Command(objcopy, ["--strip-debug", primaryOutput.filePath]); cmd.silent = true; commands.push(cmd); cmd = new Command(objcopy, ["--add-gnu-debuglink=" + debugInfo[0].filePath, primaryOutput.filePath]); cmd.silent = true; commands.push(cmd); } return commands; } function separateDebugInfoCommandsDarwin(product, outputs, primaryOutputs) { var commands = []; var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll || outputs.debuginfo_loadablemodule; if (debugInfo) { var dsymPath = debugInfo[0].filePath; if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0]) dsymPath = outputs.debuginfo_bundle[0].filePath; var flags = product.cpp.dsymutilFlags || []; var files = primaryOutputs.map(function (f) { return f.filePath; }); var cmd = new Command(product.cpp.dsymutilPath, flags.concat(["-o", dsymPath].concat(files))); cmd.description = "generating dSYM for " + product.name; commands.push(cmd); // strip debug info cmd = new Command(product.cpp.stripPath, ["-S"].concat(files)); cmd.silent = true; commands.push(cmd); } return commands; } function librarySymlinkArtifacts(product, buildVariantSuffix) { var artifacts = []; if (product.cpp.shouldCreateSymlinks && (!product.bundle || !product.bundle.isBundle)) { var maxVersionParts = product.cpp.internalVersion ? 3 : 1; var primaryFileName = PathTools.dynamicLibraryFilePath(product, buildVariantSuffix, undefined); for (var i = 0; i < maxVersionParts; ++i) { var symlink = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.dynamicLibraryFilePath( product, buildVariantSuffix, undefined, i)), fileTags: ["dynamiclibrary_symlink"], cpp: { primaryFileName: primaryFileName } }; if (i > 0 && artifacts[i-1].filePath == symlink.filePath) break; // Version number has less than three components. artifacts.push(symlink); } } return artifacts; } function librarySymlinkCommands(outputs, primaryOutput) { var commands = []; // Create symlinks from {libfoo, libfoo.1, libfoo.1.0} to libfoo.1.0.0 var links = outputs["dynamiclibrary_symlink"]; var symlinkCount = links ? links.length : 0; for (i = 0; i < symlinkCount; ++i) { var cmd = new Command("ln", ["-sf", links[i].cpp.primaryFileName, links[i].filePath]); cmd.highlight = "filegen"; cmd.description = "creating symbolic link '" + links[i].fileName + "'"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); commands.push(cmd); } return commands; } function prepareLinker(project, product, inputs, outputs, input, output) { var i, primaryOutput, cmd, commands = []; if (outputs.application) { primaryOutput = outputs.application[0]; } else if (outputs.dynamiclibrary) { primaryOutput = outputs.dynamiclibrary[0]; } else if (outputs.loadablemodule) { primaryOutput = outputs.loadablemodule[0]; } var linkerPath = effectiveLinkerPath(product, inputs) var args = linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.linkerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { wrapperArgsLength = wrapperArgs.length; args.unshift(linkerPath); linkerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var responseFileArgumentIndex = wrapperArgsLength; // qcc doesn't properly handle response files, so we have to do it manually var useQnxResponseFileHack = product.qbs.toolchain.includes("qcc") && useCompilerDriverLinker(product, inputs); if (useQnxResponseFileHack) { // qcc needs to see at least one object/library file to think it has something to do, // so start the response file at the second object file (so, 3 after the last -o option) var idx = args.lastIndexOf("-o"); if (idx !== -1 && idx + 3 < args.length) responseFileArgumentIndex += idx + 3; } cmd = new Command(linkerPath, args); cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = linkerEnvVars(product, inputs); cmd.responseFileArgumentIndex = responseFileArgumentIndex; cmd.responseFileUsagePrefix = useQnxResponseFileHack ? "-Wl,@" : "@"; setResponseFileThreshold(cmd, product); commands.push(cmd); if (product.qbs.toolchain.includes("emscripten") && outputs.application && product.cpp.separateDebugInformation) { args.push("-gseparate-dwarf"); } else if (product.qbs.targetOS.includes("darwin")) { if (!product.aggregate) { commands = commands.concat(separateDebugInfoCommandsDarwin( product, outputs, [primaryOutput])); } } else { commands = commands.concat(separateDebugInfoCommands(product, outputs, primaryOutput)); } if (outputs.dynamiclibrary) { Array.prototype.push.apply(commands, createSymbolCheckingCommands(product, outputs)); Array.prototype.push.apply(commands, librarySymlinkCommands(outputs, primaryOutput)); } if (product.cpp.shouldSignArtifacts) { Array.prototype.push.apply( commands, Codesign.prepareSign(project, product, inputs, outputs, input, output)); } return commands; } function debugInfoArtifacts(product, variants, debugInfoTagSuffix) { var fileTag; switch (debugInfoTagSuffix) { case "app": fileTag = "application"; break; case "dll": fileTag = "dynamiclibrary"; break; default: fileTag = debugInfoTagSuffix; break; } variants = variants || [{}]; var artifacts = []; var separateDebugInfo = product.cpp.separateDebugInformation; if (separateDebugInfo && product.qbs.toolchain.includes("emscripten")) separateDebugInfo = fileTag === "application"; if (separateDebugInfo) { variants.map(function (variant) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product, variant.suffix, fileTag)), fileTags: ["debuginfo_" + debugInfoTagSuffix] }); }); if (PathTools.debugInfoIsBundle(product)) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product, fileTag)), fileTags: ["debuginfo_bundle"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product, fileTag)), fileTags: ["debuginfo_plist"] }); } } return artifacts; } function dumpMacros(env, compilerFilePath, args, nullDevice, tag) { var p = new Process(); try { p.setEnv("LC_ALL", "C"); for (var key in env) p.setEnv(key, env[key]); // qcc NEEDS the explicit -Wp, prefix to -dM; clang and gcc do not but all three accept it p.exec(compilerFilePath, (args || []).concat(["-Wp,-dM", "-E", "-x", languageName(tag || "c") , nullDevice]), true); return Cpp.extractMacros(p.readStdOut()); } finally { p.close(); } } function dumpDefaultPaths(env, compilerFilePath, args, nullDevice, pathListSeparator, sysroot, targetOS) { var p = new Process(); try { p.setEnv("LC_ALL", "C"); for (var key in env) p.setEnv(key, env[key]); args = args || []; p.exec(compilerFilePath, args.concat(["-v", "-E", "-x", "c++", nullDevice]), true); var suffix = " (framework directory)"; var includePaths = []; var libraryPaths = []; var frameworkPaths = []; var addIncludes = false; var lines = p.readStdErr().trim().split(/\r?\n/g).map(function (line) { return line.trim(); }); for (var i = 0; i < lines.length; ++i) { var line = lines[i]; var prefix = "LIBRARY_PATH="; if (line.startsWith(prefix)) { libraryPaths = libraryPaths.concat(line.substr(prefix.length) .split(pathListSeparator)); } else if (line === "#include <...> search starts here:") { addIncludes = true; } else if (line === "End of search list.") { addIncludes = false; } else if (addIncludes) { if (line.endsWith(suffix)) frameworkPaths.push(line.substr(0, line.length - suffix.length)); else includePaths.push(line); } } sysroot = sysroot || ""; if (includePaths.length === 0) includePaths.push(sysroot + "/usr/include", sysroot + "/usr/local/include"); if (libraryPaths.length === 0) libraryPaths.push(sysroot + "/lib", sysroot + "/usr/lib"); if (frameworkPaths.length === 0 && targetOS.includes("darwin")) frameworkPaths.push(sysroot + "/System/Library/Frameworks"); return { "includePaths": includePaths, "libraryPaths": libraryPaths, "frameworkPaths": frameworkPaths }; } finally { p.close(); } } function targetLinkerFlags(targetArch, targetOS) { var linkerFlags = { "windows": { "i386": "i386pe", "x86_64": "i386pep", }, "freebsd": { "i386": "elf_i386_fbsd", "x86_64": "elf_x86_64_fbsd", }, "other": { "i386": "elf_i386", "x86_64": "elf_x86_64", } }; if (targetOS.includes("windows")) return linkerFlags["windows"][targetArch]; else if (targetOS.includes("freebsd")) return linkerFlags["freebsd"][targetArch]; return linkerFlags["other"][targetArch]; } function targetFlags(tool, hasTargetOption, target, targetArch, machineType, targetOS) { var args = []; if (hasTargetOption) { if (target) args.push("-target", target); } else { var archArgs = { "compiler": { "i386": ["-m32"], "x86_64": ["-m64"], }, "linker": { "i386": ["-m", targetLinkerFlags("i386", targetOS)], "x86_64": ["-m", targetLinkerFlags("x86_64", targetOS)], }, "assembler": { "i386": ["--32"], "x86_64": ["--64"], }, }; var flags = archArgs[tool] ? archArgs[tool][targetArch] : undefined; if (flags) args = args.concat(flags); if (machineType && tool !== "linker") args.push("-march=" + machineType); } return args; } function toolNames(rawToolNames, toolchainPrefix) { return toolchainPrefix ? rawToolNames.map(function(rawName) { return toolchainPrefix + rawName; }) : rawToolNames; } function pathPrefix(baseDir, prefix) { var path = ''; if (baseDir) { path += baseDir; if (path.substr(-1) !== '/') path += '/'; } if (prefix) path += prefix; return path; } function appLinkerOutputArtifacts(product) { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.applicationFilePath(product)), fileTags: ["bundle.input", "application"] .concat(product.cpp.isForMainBundle ? ["bundle.main.input", "bundle.main.executable"] : []) .concat(product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } } var artifacts = [app]; if (!product.aggregate) artifacts = artifacts.concat(debugInfoArtifacts(product, undefined, "app")); if (product.cpp.generateLinkerMapFile) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.cpp.linkerMapSuffix), fileTags: ["mem_map"] }); } if (product.qbs.toolchain.includes("emscripten")) artifacts = artifacts.concat(wasmArtifacts(product)); return artifacts; } function moduleLinkerOutputArtifacts(product, inputs) { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.loadableModuleFilePath(product)), fileTags: ["bundle.input", "loadablemodule"] .concat(product.cpp.isForMainBundle ? ["bundle.main.input", "bundle.main.plugin"] : []) .concat(product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } } var artifacts = [app]; if (!product.aggregate) artifacts = artifacts.concat(debugInfoArtifacts(product, undefined, "loadablemodule")); return artifacts; } function staticLibLinkerOutputArtifacts(product) { var tags = ["bundle.input", "staticlibrary"] .concat(product.cpp.isForMainBundle ? ["bundle.main.input", "bundle.main.library"] : []) .concat(product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []); var objs = inputs["obj"]; var objCount = objs ? objs.length : 0; for (var i = 0; i < objCount; ++i) { var ft = objs[i].fileTags; if (ft.includes("c_obj")) tags.push("c_staticlibrary"); if (ft.includes("cpp_obj")) tags.push("cpp_staticlibrary"); } return [{ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)), fileTags: tags, bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } }]; } function staticLibLinkerCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var commands = []; var args = ['rcs']; Array.prototype.push.apply(args, product.cpp.archiverFlags); args.push(output.filePath); for (var i in inputs.obj) args.push(inputs.obj[i].filePath); for (var i in inputs.res) args.push(inputs.res[i].filePath); var cmd = new Command(product.cpp.archiverPath, args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'linker' cmd.jobPool = "linker"; cmd.responseFileUsagePrefix = '@'; setResponseFileThreshold(cmd, product); commands.push(cmd); if (product.cpp.shouldSignArtifacts) { Array.prototype.push.apply( commands, Codesign.prepareSign(project, product, inputs, outputs, input, output)); } return commands; } function dynamicLibLinkerOutputArtifacts(product) { var artifacts = [{ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.dynamicLibraryFilePath(product)), fileTags: ["bundle.input", "dynamiclibrary"] .concat(product.cpp.isForMainBundle ? ["bundle.main.input", "bundle.main.library"] : []) .concat(product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } }]; if (product.cpp.imageFormat === "pe") { artifacts.push({ fileTags: ["dynamiclibrary_import"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.importLibraryFilePath(product)), alwaysUpdated: false }); } else { // List of libfoo's public symbols for smart re-linking. artifacts.push({ filePath: product.destinationDirectory + "/.sosymbols/" + PathTools.dynamicLibraryFilePath(product), fileTags: ["dynamiclibrary_symbols"], alwaysUpdated: false, }); } artifacts = artifacts.concat(librarySymlinkArtifacts(product)); if (!product.aggregate) artifacts = artifacts.concat(debugInfoArtifacts(product, undefined, "dll")); return artifacts; } function wasmArtifacts(product) { var flags = product.cpp.driverLinkerFlags; var wasmoption = 1; var pthread = false; for (var index in flags) { var option = flags[index]; if (option.indexOf("WASM") !== -1) { option = option.trim(); wasmoption = option.substring(option.length - 1); } else if (option.indexOf("-pthread") !== -1) { pthread = true; } } var artifacts = []; var createAppArtifact = function(fileName) { return { filePath: FileInfo.joinPaths(product.destinationDirectory, fileName), fileTags: ["wasm"] }; }; var suffix = product.cpp.executableSuffix; if (suffix !== ".wasm") { if (suffix === ".html") artifacts.push(createAppArtifact(product.targetName + ".js")); // Emscripten 3.1.68+ no longer generates a separate worker.js file // (pthread worker bootstrap is now embedded in the main .js file) if (pthread && Utilities.versionCompare(product.cpp.compilerVersion, "3.1.68") < 0) artifacts.push(createAppArtifact(product.targetName + ".worker.js")); } if (wasmoption !== 0 && suffix !== ".wasm") //suffix .wasm will already result in "application".wasm artifacts.push(createAppArtifact(product.targetName + ".wasm")); if (wasmoption == 2) artifacts.push(createAppArtifact(product.targetName + ".wasm.js")); return artifacts; } function configureStdModules() { try { var probe = new Process(); // check which stdlib is used? this actually works: // clang-18 -print-file-name=libstdc++.modules.json --sysroot /opt/gcc-15/ const modulesJsonFiles = [ "libc++.modules.json", "libstdc++.modules.json", "../../c++/libc++.modules.json", ]; for (var i = 0; i < modulesJsonFiles.length; ++i) { const modulesJsonFile = modulesJsonFiles[i]; const result = probe.exec(_compilerPath, ["-print-file-name=" + modulesJsonFile], false); if (result !== 0) continue; const path = probe.readStdOut().trim(); if (path !== modulesJsonFile && FileInfo.isAbsolutePath(path) && File.exists(path)) { const jsonFile = new TextFile(path, TextFile.ReadOnly); const json = JSON.parse(jsonFile.readAll()); jsonFile.close(); const modules = json.modules .filter(function(module) { const logicalName = module["logical-name"]; if (logicalName === "std" && (_forceUseImportStd || _forceUseImportStdCompat)) { return true; } else if (logicalName === "std.compat" && _forceUseImportStdCompat) { return true; } return false; }) .map(function(module) { const sourcePath = module["source-path"]; if (FileInfo.isAbsolutePath(sourcePath)) return sourcePath; return FileInfo.joinPaths(FileInfo.path(path), sourcePath); }) .filter(function(module) { return File.exists(module); }); if (modules.length > 0) { found = true; _stdModulesFiles = modules; break; } } } } finally { probe.close(); } } qbs-src-3.3.1/share/qbs/modules/cpp/GenericGCC.qbs0000644000175100017510000006765015232633614021242 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Process import qbs.TextFile import qbs.Utilities import qbs.UnixUtils import qbs.WindowsUtils import 'cpp.js' as Cpp import 'gcc.js' as Gcc CppModule { condition: qbs.toolchain && qbs.toolchain.includes("gcc") priority: -100 Depends { name: "codesign" } Probes.GccBinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks _compilerName: compilerName _toolchainPrefix: toolchainPrefix } // Find the version as early as possible in case other things depend on it, // for example the question of whether certain flags are supported and which need to be used // in the GccProbe itself. Probes.GccVersionProbe { id: gccVersionProbe compilerFilePath: compilerPath environment: probeEnv } Probes.GccProbe { id: gccProbe condition: !_skipAllChecks compilerFilePathByLanguage: compilerPathByLanguage enableDefinesByLanguage: enableCompilerDefinesByLanguage environment: probeEnv flags: targetDriverFlags.concat(sysrootFlags) _sysroot: sysroot } stdModulesFiles: stdModulesProbe.found ? stdModulesProbe._stdModulesFiles : undefined Probe { // input property bool _forceUseImportStd : forceUseImportStd property bool _forceUseImportStdCompat : forceUseImportStdCompat property stringList _toolchain: qbs.toolchain property string _compilerPath : compilerPathByLanguage["cpp"] // output property stringList _stdModulesFiles id: stdModulesProbe condition: !_skipAllChecks && stdModulesFiles === undefined && !qbs.toolchain.includes("mingw") && (forceUseImportStd || forceUseImportStdCompat) configure: Gcc.configureStdModules() } property var probeEnv Probes.BinaryProbe { id: binutilsProbe condition: !File.exists(archiverPath) && !_skipAllChecks names: Gcc.toolNames([archiverName, assemblerName, linkerName, nmName, objcopyName, stripName], toolchainPrefix) } targetLinkerFlags: Gcc.targetFlags("linker", false, target, targetArch, machineType, qbs.targetOS) targetAssemblerFlags: Gcc.targetFlags("assembler", assemblerHasTargetOption, target, targetArch, machineType, qbs.targetOS) targetDriverFlags: Gcc.targetFlags("compiler", compilerHasTargetOption, target, targetArch, machineType, qbs.targetOS) Probe { id: nmProbe condition: !_skipAllChecks property string theNmPath: nmPath property bool hasDynamicOption configure: { var proc = new Process(); try { hasDynamicOption = proc.exec(theNmPath, ["-D", theNmPath], false) == 0; console.debug("nm has -D: " + hasDynamicOption); } finally { proc.close(); } } } Properties { condition: gccProbe.found qbs.architecture: gccProbe.architecture } endianness: gccProbe.endianness compilerDefinesByLanguage: gccProbe.compilerDefinesByLanguage compilerVersionMajor: gccVersionProbe.versionMajor compilerVersionMinor: gccVersionProbe.versionMinor compilerVersionPatch: gccVersionProbe.versionPatch compilerIncludePaths: gccProbe.includePaths compilerFrameworkPaths: gccProbe.frameworkPaths compilerLibraryPaths: gccProbe.libraryPaths staticLibraryPrefix: "lib" staticLibrarySuffix: ".a" precompiledHeaderSuffix: ".gch" property bool compilerHasTargetOption: qbs.toolchain.includes("clang") && Utilities.versionCompare(compilerVersion, "3.1") >= 0 property bool assemblerHasTargetOption: qbs.toolchain.includes("xcode") && Utilities.versionCompare(compilerVersion, "7") >= 0 _supportsTimeTrace: qbs.toolchain.includes("clang") property string target: targetArch ? [targetArch, targetVendor, targetSystem, targetAbi].join("-") : undefined property string targetArch: Utilities.canonicalTargetArchitecture( qbs.architecture, endianness, targetVendor, targetSystem, targetAbi) property string targetVendor: "unknown" property string targetSystem: "unknown" property string targetAbi: "unknown" property string toolchainPrefix: compilerPathProbe.found ? compilerPathProbe.tcPrefix : undefined toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined property string binutilsPath: binutilsProbe.found ? binutilsProbe.path : toolchainInstallPath assemblerName: 'as' + compilerExtension compilerName: cxxCompilerName linkerName: 'ld' + compilerExtension archiverName: 'ar' + compilerExtension property string nmName: 'nm' + compilerExtension property string objcopyName: "objcopy" + compilerExtension property string stripName: "strip" + compilerExtension property string dsymutilName: "dsymutil" + compilerExtension property string lipoName property string sysroot: qbs.sysroot property string syslibroot: sysroot property stringList sysrootFlags: sysroot ? ["--sysroot=" + sysroot] : [] property string exportedSymbolsCheckMode: "ignore-undefined" PropertyOptions { name: "exportedSymbolsCheckMode" allowedValues: ["strict", "ignore-undefined"] description: "Controls when we consider an updated dynamic library as changed with " + "regards to other binaries depending on it. The default is \"ignore-undefined\", " + "which means we do not care about undefined symbols being added or removed. " + "If you do care about that, e.g. because you link dependent products with an option " + "such as \"--no-undefined\", then you should set this property to \"strict\"." } property string linkerVariant PropertyOptions { name: "linkerVariant" allowedValues: ["bfd", "gold", "lld", "mold"] description: "Allows to specify the linker variant. Maps to gcc's and clang's -fuse-ld " + "option." } Properties { condition: linkerVariant driverLinkerFlags: "-fuse-ld=" + linkerVariant } property string toolchainPathPrefix: Gcc.pathPrefix(toolchainInstallPath, toolchainPrefix) property string binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainPrefix) property string cCompilerName: (qbs.toolchain.includes("clang") ? "clang" : "gcc") + compilerExtension property string cxxCompilerName: (qbs.toolchain.includes("clang") ? "clang++" : "g++") + compilerExtension compilerPathByLanguage: ({ "c": toolchainPathPrefix + cCompilerName, "cpp": toolchainPathPrefix + cxxCompilerName, "cppm": toolchainPathPrefix + cxxCompilerName, "objc": toolchainPathPrefix + cCompilerName, "objcpp": toolchainPathPrefix + cxxCompilerName, "asm_cpp": toolchainPathPrefix + cCompilerName }) assemblerPath: binutilsPathPrefix + assemblerName compilerPath: toolchainPathPrefix + compilerName linkerPath: binutilsPathPrefix + linkerName archiverPath: binutilsPathPrefix + archiverName property string nmPath: binutilsPathPrefix + nmName property bool _nmHasDynamicOption: nmProbe.hasDynamicOption property string objcopyPath: binutilsPathPrefix + objcopyName property string stripPath: binutilsPathPrefix + stripName property string dsymutilPath: toolchainPathPrefix + dsymutilName property string lipoPath property stringList dsymutilFlags property bool alwaysUseLipo: false defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-isystem" preincludeFlag: "-include" libraryPathFlag: "-L" linkerScriptFlag: "-T" readonly property bool shouldCreateSymlinks: { return createSymlinks && internalVersion && ["macho", "elf"].includes(imageFormat); } readonly property bool shouldSignArtifacts: codesign._canSignArtifacts && codesign.enableCodeSigning // codesigning is done during the lipo step && !product.multiplexed readonly property bool isForMainBundle: product.bundle && product.bundle.isForMainBundle && !product.bundle.isBundle && !product.multiplexed property string internalVersion: { if (product.version === undefined) return undefined; var coreVersion = product.version.match("^([0-9]+\.){0,3}[0-9]+"); if (!coreVersion) return undefined; var maxVersionParts = 3; var versionParts = coreVersion[0].split('.').slice(0, maxVersionParts); // pad if necessary for (var i = versionParts.length; i < maxVersionParts; ++i) versionParts.push("0"); return versionParts.join('.'); } property string soVersion: { if (!internalVersion) return ""; return internalVersion.split('.')[0]; } property var buildEnv: { var env = {}; if (qbs.toolchain.includes("mingw")) env.PATH = toolchainInstallPath; // For libwinpthread etc return env; } compiledModuleSuffix: qbs.toolchain.includes("clang") ? ".pcm" : ".gcm" moduleOutputFlag: qbs.toolchain.includes("clang") ? "-fmodule-output=" : "%module% " moduleFileFlag: qbs.toolchain.includes("clang") ? "-fmodule-file=%module%=" : "%module% " exceptionHandlingModel: { if (qbs.toolchain.includes("mingw")) { // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html claims // __USING_SJLJ_EXCEPTIONS__ is defined as 1 when using SJLJ exceptions, but there don't // seem to be defines for the other models, so use the presence of the DLLs for now. var prefix = toolchainInstallPath; if (!Host.os().includes("windows")) prefix = FileInfo.joinPaths(toolchainInstallPath, "..", "lib", "gcc", toolchainPrefix, [compilerVersionMajor, compilerVersionMinor].join(".")); var models = ["seh", "sjlj", "dw2"]; for (var i = 0; i < models.length; ++i) { if (File.exists(FileInfo.joinPaths(prefix, "libgcc_s_" + models[i] + "-1.dll"))) { return models[i]; } } } return base; } validate: { if (_skipAllChecks) return; if (!File.exists(compilerPath)) { var pathMessage = FileInfo.isAbsolutePath(compilerPath) ? "at '" + compilerPath + "'" : "'" + compilerPath + "' in PATH"; throw ModUtils.ModuleError("Could not find selected C++ compiler " + pathMessage + ". " + "Ensure that the compiler is properly " + "installed, or set cpp.toolchainInstallPath to a valid " + "toolchain path, or consider whether you meant to set " + "cpp.compilerName instead."); } var isWrongTriple = false; if (gccProbe.architecture) { if (Utilities.canonicalArchitecture(architecture) !== Utilities.canonicalArchitecture(gccProbe.architecture)) isWrongTriple = true; } else if (architecture) { // This is a warning and not an error on the rare chance some new architecture comes // about which qbs does not know about the macros of. But it *might* still work. console.warn("Unknown architecture '" + architecture + "' " + "may not be supported by this compiler."); } if (gccProbe.endianness) { if (endianness !== gccProbe.endianness) isWrongTriple = true; } else if (endianness) { console.warn("Could not detect endianness ('" + endianness + "' given)"); } if (gccProbe.targetPlatform) { // Can't differentiate Darwin OSes at the compiler level alone if (gccProbe.targetPlatform === "darwin" ? !qbs.targetOS.includes("darwin") : qbs.targetPlatform !== gccProbe.targetPlatform) isWrongTriple = true; } else if (qbs.targetPlatform) { console.warn("Could not detect target platform ('" + qbs.targetPlatform + "' given)"); } if (isWrongTriple) { var realTriple = [ Utilities.canonicalArchitecture(gccProbe.architecture), gccProbe.targetPlatform, gccProbe.endianness ? gccProbe.endianness + "-endian" : undefined ].join("-"); var givenTriple = [ Utilities.canonicalArchitecture(architecture), qbs.targetPlatform, endianness ? endianness + "-endian" : undefined ].join("-"); var msg = "The selected compiler '" + compilerPath + "' produces code for '" + realTriple + "', but '" + givenTriple + "' was given, which is incompatible."; if (validateTargetTriple) { msg += " If you are absolutely certain that your configuration is correct " + "(check the values of the qbs.architecture, qbs.targetPlatform, " + "and qbs.endianness properties) and that this message has been " + "emitted in error, set the cpp.validateTargetTriple property to " + "false. However, you should consider submitting a bug report in any " + "case."; throw ModUtils.ModuleError(msg); } else { console.warn(msg); } } var validateFlagsFunction = function (value) { if (value) { for (var i = 0; i < value.length; ++i) { if (["-target", "-triple", "-arch"].includes(value[i])) return false; } } return true; } var validator = new ModUtils.PropertyValidator("cpp"); var msg = "'-target', '-triple' and '-arch' cannot appear in flags; set qbs.architecture instead"; validator.addCustomValidator("assemblerFlags", assemblerFlags, validateFlagsFunction, msg); validator.addCustomValidator("cppFlags", cppFlags, validateFlagsFunction, msg); validator.addCustomValidator("cFlags", cFlags, validateFlagsFunction, msg); validator.addCustomValidator("cxxFlags", cxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("objcFlags", objcFlags, validateFlagsFunction, msg); validator.addCustomValidator("objcxxFlags", objcxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("commonCompilerFlags", commonCompilerFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformAssemblerFlags", platformAssemblerFlags, validateFlagsFunction, msg); //validator.addCustomValidator("platformCppFlags", platformCppFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCFlags", platformCFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCxxFlags", platformCxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformObjcFlags", platformObjcFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformObjcxxFlags", platformObjcxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCommonCompilerFlags", platformCommonCompilerFlags, validateFlagsFunction, msg); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); validator.setRequiredProperty("compilerIncludePaths", compilerIncludePaths); validator.setRequiredProperty("compilerFrameworkPaths", compilerFrameworkPaths); validator.setRequiredProperty("compilerLibraryPaths", compilerLibraryPaths); validator.validate(); } // Product should be linked if it's not multiplexed or aggregated at all, // or if it is multiplexed, if it's not the aggregate product readonly property bool shouldLink: !(product.multiplexed || product.aggregate) || product.multiplexConfigurationId Group { condition: shouldLink Rule { name: "dynamicLibraryLinker" multiplex: true inputs: { var tags = ["obj", "res", "linkerscript", "versionscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.includes("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: { var tags = ["bundle.input", "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_symbols", "debuginfo_dll", "debuginfo_bundle", "dynamiclibrary_import", "debuginfo_plist"]; if (product.cpp.isForMainBundle) tags = tags.concat(["bundle.main.library", "bundle.main.input"]); if (product.cpp.shouldSignArtifacts) tags.push("codesign.signed_artifact"); return tags; } outputArtifacts: Gcc.dynamicLibLinkerOutputArtifacts(product) prepare: Gcc.prepareLinker.apply(Gcc, arguments) } Rule { name: "staticLibraryLinker" multiplex: true inputs: ["obj", "res", "linkerscript"] inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary", "objectlibrary"] outputFileTags: { var tags = ["bundle.input", "bundle.main.input", "bundle.main.library", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] if (product.cpp.shouldSignArtifacts) tags.push("codesign.signed_artifact"); return tags; } outputArtifacts: Gcc.staticLibLinkerOutputArtifacts(product, inputs) prepare: Gcc.staticLibLinkerCommands.apply(Gcc, arguments) } Rule { name: "loadableModuleLinker" multiplex: true inputs: { var tags = ["obj", "res", "linkerscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.includes("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary", "objectlibrary"] outputFileTags: { var tags = ["bundle.input", "loadablemodule", "debuginfo_loadablemodule", "debuginfo_bundle", "debuginfo_plist"]; if (product.cpp.isForMainBundle) tags = tags.concat(["bundle.main.plugin", "bundle.main.input"]); if (product.cpp.shouldSignArtifacts) tags.push("codesign.signed_artifact"); return tags; } outputArtifacts: Gcc.moduleLinkerOutputArtifacts(product) prepare: Gcc.prepareLinker.apply(Gcc, arguments) } Rule { name: "applicationLinker" multiplex: true inputs: { var tags = ["obj", "res", "linkerscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.includes("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary", "objectlibrary"] outputFileTags: { var tags = ["bundle.input", "application", "debuginfo_app", "debuginfo_bundle", "debuginfo_plist"]; if (product.cpp.isForMainBundle) tags = tags.concat(["bundle.main.executable", "bundle.main.input"]); if (product.cpp.shouldSignArtifacts) tags.push("codesign.signed_artifact"); if (product.cpp.generateLinkerMapFile) tags.push("mem_map"); if(product.qbs.toolchain.includes("emscripten")) tags.push("wasm") return tags; } outputArtifacts: Gcc.appLinkerOutputArtifacts(product) prepare: Gcc.prepareLinker.apply(Gcc, arguments) } } Rule { name: "cpp_compiler" inputs: ["cpp", "cppm", "c", "objcpp", "objc", "asm_cpp"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"] outputFileTags: Cpp.compilerOutputTags(/*withListingFiles*/ false, /*withCxxModules*/ true) .concat(["c_obj", "cpp_obj"]) outputArtifacts: Cpp.compilerOutputArtifacts(input, inputs, /*withCxxModules*/ true) prepare: Gcc.prepareCompiler.apply(Gcc, arguments) } Rule { name: "assembler" inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(false) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: Gcc.prepareAssembler.apply(Gcc, arguments) } Rule { condition: useCPrecompiledHeader inputs: ["c_pch_src"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("c", false) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "c", false) prepare: Gcc.prepareCompiler.apply(Gcc, arguments) } Rule { condition: useCxxPrecompiledHeader inputs: ["cpp_pch_src"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("cpp", false) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "cpp", false) prepare: Gcc.prepareCompiler.apply(Gcc, arguments) } Rule { condition: useObjcPrecompiledHeader inputs: ["objc_pch_src"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("objc", false) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "objc", false) prepare: Gcc.prepareCompiler.apply(Gcc, arguments) } Rule { condition: useObjcxxPrecompiledHeader inputs: ["objcpp_pch_src"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("objcpp", false) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "objcpp", false) prepare: Gcc.prepareCompiler.apply(Gcc, arguments) } FileTagger { patterns: "*.s" fileTags: ["asm"] } FileTagger { patterns: "*.S" fileTags: ["asm_cpp"] } FileTagger { patterns: "*.sx" fileTags: ["asm_cpp"] } Scanner { inputs: ["linkerscript"] recursive: true scan: { console.debug("scanning linkerscript " + filePath + " for dependencies"); var retval = []; var linkerScript = new TextFile(filePath, TextFile.ReadOnly); var regexp = /[\s]*INCLUDE[\s]+(\S+).*/ // "INCLUDE filename" var match; while (!linkerScript.atEof()) { match = regexp.exec(linkerScript.readLine()); if (match) { var dependencyFileName = match[1]; retval.push(dependencyFileName); console.debug("linkerscript " + filePath + " depends on " + dependencyFileName); } } linkerScript.close(); return retval; } searchPaths: { var retval = []; for (var i = 0; i < (product.cpp.libraryPaths || []).length; i++) retval.push(product.cpp.libraryPaths[i]); var regexp = /[\s]*SEARCH_DIR\((\S+)\).*/ // "SEARCH_DIR(path)" var match; var linkerScript = new TextFile(input.filePath, TextFile.ReadOnly); while (!linkerScript.atEof()) { match = regexp.exec(linkerScript.readLine()); if(match) { var additionalPath = match[1]; // path can be quoted to use non-latin letters, remove quotes if present if (additionalPath.startsWith("\"") && additionalPath.endsWith("\"")) additionalPath = additionalPath.slice(1, additionalPath.length - 1); retval.push(additionalPath); } } linkerScript.close(); return retval; } } } qbs-src-3.3.1/share/qbs/modules/cpp/msvc.js0000644000175100017510000007747215232633614020153 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Codesign = require("../codesign/codesign.js"); var Cpp = require("cpp.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function effectiveLinkerPath(product, inputs) { if (product.cpp.linkerMode === "automatic") { var compiler = product.cpp.compilerPath; if (compiler) { if (inputs.obj || inputs.staticlibrary) { console.log("Found C/C++ objects, using compiler as a linker for " + product.name); return compiler; } } console.log("Found no C-language objects, choosing system linker for " + product.name); } return product.cpp.linkerPath; } function handleCpuFeatures(input, flags) { if (!input.qbs.architecture) return; if (input.qbs.architecture.startsWith("x86")) { if (input.qbs.architecture === "x86") { var sse2 = input.cpufeatures.x86_sse2; if (sse2 === true) flags.push("/arch:SSE2"); if (sse2 === false) flags.push("/arch:IA32"); } if (input.cpufeatures.x86_avx === true) flags.push("/arch:AVX"); if (input.cpufeatures.x86_avx2 === true) flags.push("/arch:AVX2"); } else if (input.qbs.architecture.startsWith("arm")) { if (input.cpufeatures.arm_vfpv4 === true) flags.push("/arch:VFPv4"); if (input.cpp.machineType === "armv7ve") flags.push("/arch:ARMv7VE"); } } function hasCxx17Option(input) { // Probably this is not the earliest version to support the flag, but we have tested this one // and it's a pain to find out the exact minimum. return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 7) || Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0; } function hasZCplusPlusOption(input) { // /Zc:__cplusplus is supported starting from Visual Studio 15.7 // Looks like closest MSVC version is 14.14.26428 (cl ver 19.14.26433) // At least, this version is tested // https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus // clang-cl supports this option starting around-ish versions 8/9, but it // ignores this option, so this doesn't really matter // https://reviews.llvm.org/D45877 return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 9) || Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0; } function hasCxx20Option(input) { return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13) || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30133.0") >= 0; } function hasCVerOption(input) { return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13) || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30138.0") >= 0; } function supportsExternalIncludesOption(input) { if (input.qbs.toolchain.includes("clang-cl")) return false; // Exclude clang-cl. // This option was introcuded since MSVC 2017 v15.6 (aka _MSC_VER 19.13). // But due to some MSVC bugs: // * https://developercommunity.visualstudio.com/content/problem/181006/externali-include-paths-not-working.html // this option has been fixed since MSVC 2017 update 9, v15.9 (aka _MSC_VER 19.16). return Utilities.versionCompare(input.cpp.compilerVersion, "19.16") >= 0; } function addCxxLanguageVersionFlag(input, args) { var cxxVersion = Cpp.languageVersion(input.cpp.cxxLanguageVersion, ["c++26", "c++23", "c++20", "c++17", "c++14", "c++11", "c++98"], "C++"); if (!cxxVersion) return; // Visual C++ 2013, Update 3 or clang-cl var hasStdOption = input.qbs.toolchain.includes("clang-cl") || Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0; if (!hasStdOption) return; var flag; if (cxxVersion === "c++14") flag = "/std:c++14"; else if (cxxVersion === "c++17" && hasCxx17Option(input)) flag = "/std:c++17"; else if (cxxVersion === "c++20" && hasCxx20Option(input)) flag = "/std:c++20"; else if (cxxVersion !== "c++11" && cxxVersion !== "c++98") flag = "/std:c++latest"; if (flag) args.push(flag); } function addCLanguageVersionFlag(input, args) { var cVersion = Cpp.languageVersion(input.cpp.cLanguageVersion, ["c17", "c11"], "C"); if (!cVersion) return; var hasStdOption = hasCVerOption(input); if (!hasStdOption) return; var flag; if (cVersion === "c17") flag = "/std:c17"; else if (cVersion === "c11") flag = "/std:c11"; if (flag) args.push(flag); } function handleClangClArchitectureFlags(product, architecture, flags) { if (product.qbs.toolchain.includes("clang-cl")) { if (architecture === "x86") flags.push("-m32"); else if (architecture === "x86_64") flags.push("-m64"); } } function prepareCompilerInternal(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var i; var debugInformation = input.cpp.debugInformation; var args = ['/nologo', '/c'] handleCpuFeatures(input, args); // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(Object.keys(outputs))); if (!["c", "cpp", "cppm"].includes(tag)) throw ("unsupported source language"); var enableExceptions = input.cpp.enableExceptions; if (enableExceptions) { var ehModel = input.cpp.exceptionHandlingModel; switch (ehModel) { case "default": args.push("/EHsc"); // "Yes" in VS break; case "seh": args.push("/EHa"); // "Yes with SEH exceptions" in VS break; case "externc": args.push("/EHs"); // "Yes with Extern C functions" in VS break; } } var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) { args.push(enableRtti ? "/GR" : "/GR-"); } switch (input.cpp.optimization) { case "small": args.push('/Os') break; case "fast": args.push('/O2') break; case "none": args.push("/Od"); break; } handleClangClArchitectureFlags(product, input.cpp.architecture, args); if (debugInformation) { if (product.cpp.separateDebugInformation) args.push('/Zi'); else args.push('/Z7'); } var rtl = product.cpp.runtimeLibrary; if (rtl) { rtl = (rtl === "static" ? "/MT" : "/MD"); if (product.qbs.enableDebugCode) rtl += "d"; args.push(rtl); } args = args.concat(Cpp.collectMiscDriverArguments(product)); // warnings: var warningLevel = input.cpp.warningLevel; if (warningLevel === 'none') args.push('/w') if (warningLevel === 'all') args.push('/Wall') if (input.cpp.treatWarningsAsErrors) args.push('/WX') var includePaths = Cpp.collectIncludePaths(input); args = args.concat([].uniqueConcat(includePaths).map(function(path) { return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); var includeFlag = input.qbs.toolchain.includes("clang-cl") ? input.cpp.systemIncludeFlag : input.cpp.includeFlag; if (!input.qbs.toolchain.includes("clang-cl")) { if (supportsExternalIncludesOption(input)) { args.push("/experimental:external"); var enforcesSlashW = Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30037") >= 0 if (enforcesSlashW) args.push("/external:W0") includeFlag = input.cpp.systemIncludeFlag; } } var systemIncludePaths = Cpp.collectSystemIncludePaths(input); args = args.concat([].uniqueConcat(systemIncludePaths).map(function(path) { return includeFlag + FileInfo.toWindowsSeparators(path); })); var defines = Cpp.collectDefines(input); args = args.concat([].uniqueConcat(defines).map(function(define) { return input.cpp.defineFlag + define.replace(/%/g, "%%"); })); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; if (minimumWindowsVersion) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) { args.push(input.cpp.defineFlag + versionDefs[i] + '=' + hexVersion); } } } if (product.cpp.debugInformation && product.cpp.separateDebugInformation) args.push("/Fd" + product.targetName + ".cl" + product.cpp.debugInfoSuffix); if (input.cpp.generateCompilerListingFiles) args.push("/Fa" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath)); if (input.cpp.enableCxxLanguageMacro && hasZCplusPlusOption(input)) args.push("/Zc:__cplusplus"); var objectMap = outputs.obj || outputs.intermediate_obj var objOutput = objectMap ? objectMap[0] : undefined args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.filePath)) args.push(FileInfo.toWindowsSeparators(input.filePath)) var preincludePaths = Cpp.collectPreincludePaths(input); args = args.concat([].uniqueConcat(preincludePaths).map(function(path) { return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path); })); // Language if (tag === "cpp" || tag === "cppm") { args.push("/TP"); addCxxLanguageVersionFlag(input, args); } else if (tag === "c") { args.push("/TC"); addCLanguageVersionFlag(input, args); } var moduleMap = (outputs["modulemap"] || [])[0]; if (moduleMap) { args.push("@" + moduleMap.filePath); } // Whether we're compiling a precompiled header or normal source file var pchOutput = outputs[tag + "_pch"] ? outputs[tag + "_pch"][0] : undefined; var pchInputs = explicitlyDependsOn[tag + "_pch"]; if (pchOutput) { // create PCH if (input.qbs.toolchain.includes("clang-cl")) { // clang-cl does not support /Yc flag without filename args.push("/Yc" + FileInfo.toWindowsSeparators(input.filePath)); // clang-cl complains when pch file is not included args.push("/FI" + FileInfo.toWindowsSeparators(input.filePath)); args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); } else { // real msvc args.push("/Yc"); args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); args.push(FileInfo.toWindowsSeparators(input.filePath)); } } else if (pchInputs && pchInputs.length === 1 && ModUtils.moduleProperty(input, "usePrecompiledHeader", tag)) { // use PCH var pchSourceArtifacts = product.artifacts[tag + "_pch_src"]; if (pchSourceArtifacts && pchSourceArtifacts.length > 0) { var pchSourceFilePath = pchSourceArtifacts[0].filePath; var pchFilePath = FileInfo.toWindowsSeparators(pchInputs[0].filePath); args.push("/FI" + pchSourceFilePath); args.push("/Yu" + pchSourceFilePath); args.push("/Fp" + pchFilePath); } else { console.warning("products." + product.name + ".usePrecompiledHeader is true, " + "but there is no " + tag + "_pch_src artifact."); } } args = args.concat(Cpp.collectMiscCompilerArguments(input, tag)); var compilerPath = product.cpp.compilerPath; var wrapperArgs = product.cpp.compilerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var cmd = new Command(compilerPath, args) cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + tag + ')'; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmd.workingDirectory = product.buildDirectory; cmd.responseFileUsagePrefix = '@'; // cl.exe outputs the cpp file name. We filter that out. cmd.inputFileName = input.fileName; cmd.relevantEnvironmentVariables = ["CL", "_CL_", "INCLUDE"]; cmd.stdoutFilterFunction = function(output) { return output.split(inputFileName + "\r\n").join(""); }; return [cmd]; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var result = Cpp.prepareModules(project, product, inputs, outputs, input, output); result = result.concat(prepareCompilerInternal( project, product, inputs, outputs, input, output, explicitlyDependsOn)); return result; } function linkerSupportsWholeArchive(product) { return product.qbs.toolchainType.includes("clang-cl") || Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0 } function handleDiscardProperty(product, flags) { var discardUnusedData = product.cpp.discardUnusedData; if (discardUnusedData === true) flags.push("/OPT:REF"); else if (discardUnusedData === false) flags.push("/OPT:NOREF"); } function prepareLinker(project, product, inputs, outputs, input, output) { var i; var linkDLL = (outputs.dynamiclibrary ? true : false) var primaryOutput = (linkDLL ? outputs.dynamiclibrary[0] : outputs.application[0]) var debugInformation = product.cpp.debugInformation; var additionalManifestInputs = Array.prototype.map.call(inputs["native.pe.manifest"] || [], function (a) { return a.filePath; }); var moduleDefinitionInputs = Array.prototype.map.call(inputs["def"] || [], function (a) { return a.filePath; }); var generateManifestFiles = product.cpp.generateManifestFile; var useClangCl = product.qbs.toolchain.includes("clang-cl"); var canEmbedManifest = useClangCl || product.cpp.compilerVersionMajor >= 17 // VS 2012 var linkerPath = effectiveLinkerPath(product, inputs); var useCompilerDriver = linkerPath === product.cpp.compilerPath; // args variable is built as follows: // [linkerWrapper] linkerPath /nologo [driverFlags driverLinkerFlags] // allInputs libDeps [/link] linkerArgs var args = [] if (useCompilerDriver) { args.push('/nologo'); args = args.concat(Cpp.collectMiscDriverArguments(product), Cpp.collectMiscLinkerArguments(product)); } var allInputs = [].concat(Cpp.collectLinkerObjectPaths(inputs), Cpp.collectResourceObjectPaths(inputs)); args = args.concat([].uniqueConcat(allInputs).map(function(path) { return FileInfo.toWindowsSeparators(path); })); var linkerArgs = ['/nologo'] if (linkDLL) { linkerArgs.push('/DLL'); linkerArgs.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath)); } if (debugInformation) { linkerArgs.push("/DEBUG"); var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll; if (debugInfo) linkerArgs.push("/PDB:" + debugInfo[0].fileName); } else { linkerArgs.push('/INCREMENTAL:NO') } switch (product.qbs.architecture) { case "x86": linkerArgs.push("/MACHINE:X86"); break; case "x86_64": linkerArgs.push("/MACHINE:X64"); break; case "ia64": linkerArgs.push("/MACHINE:IA64"); break; case "armv7": linkerArgs.push("/MACHINE:ARM"); break; case "arm64": linkerArgs.push("/MACHINE:ARM64"); break; } if (useCompilerDriver) handleClangClArchitectureFlags(product, product.qbs.architecture, args); var requireAppContainer = product.cpp.requireAppContainer; if (requireAppContainer !== undefined) linkerArgs.push("/APPCONTAINER" + (requireAppContainer ? "" : ":NO")); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; var subsystemSwitch = undefined; if (minimumWindowsVersion || product.consoleApplication !== undefined) { // Ensure that we default to console if product.consoleApplication is undefined // since that could still be the case if only minimumWindowsVersion had been defined subsystemSwitch = product.consoleApplication === false ? '/SUBSYSTEM:WINDOWS' : '/SUBSYSTEM:CONSOLE'; } var useLldLink = useCompilerDriver && product.cpp.linkerVariant === "lld" || !useCompilerDriver && product.cpp.linkerName === "lld-link.exe"; if (minimumWindowsVersion) { var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { subsystemSwitch += ',' + subsystemVersion; // llvm linker does not support /OSVERSION if (!useLldLink) linkerArgs.push('/OSVERSION:' + subsystemVersion); } } if (subsystemSwitch) linkerArgs.push(subsystemSwitch); var linkerOutputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); var manifestFileNames = []; if (generateManifestFiles) { if (canEmbedManifest) { linkerArgs.push("/MANIFEST:embed"); additionalManifestInputs.forEach(function (manifestFileName) { linkerArgs.push("/MANIFESTINPUT:" + manifestFileName); }); } else { linkerOutputNativeFilePath = FileInfo.toWindowsSeparators( FileInfo.path(primaryOutput.filePath) + "/intermediate." + primaryOutput.fileName); var manifestFileName = linkerOutputNativeFilePath + ".manifest"; linkerArgs.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName); manifestFileNames = [manifestFileName].concat(additionalManifestInputs); } } if (moduleDefinitionInputs.length === 1) linkerArgs.push("/DEF:" + moduleDefinitionInputs[0]); else if (moduleDefinitionInputs.length > 1) throw new Error("Only one '.def' file can be specified for linking"); var wholeArchiveSupported = linkerSupportsWholeArchive(product); var wholeArchiveRequested = false; var libDeps = Cpp.collectLibraryDependencies(product); var prevLib; for (i = 0; i < libDeps.length; ++i) { var dep = libDeps[i]; var lib = dep.filePath; if (lib === prevLib) continue; prevLib = lib; if (wholeArchiveSupported && dep.wholeArchive) { // need to pass libraries to the driver to avoid "no input files" error if no object // files are specified; thus libraries are duplicated when using "WHOLEARCHIVE" if (useCompilerDriver && allInputs.length === 0) args.push(FileInfo.toWindowsSeparators(lib)); linkerArgs.push("/WHOLEARCHIVE:" + FileInfo.toWindowsSeparators(lib)); } else { args.push(FileInfo.toWindowsSeparators(lib)); } if (dep.wholeArchive) wholeArchiveRequested = true; } if (wholeArchiveRequested && !wholeArchiveSupported) { console.warn("Product '" + product.name + "' sets cpp.linkWholeArchive on a dependency, " + "but your linker does not support the /WHOLEARCHIVE option. " + "Please upgrade to Visual Studio 2015 Update 2 or higher."); } if (product.cpp.entryPoint) linkerArgs.push("/ENTRY:" + product.cpp.entryPoint); if (outputs.application && product.cpp.generateLinkerMapFile) { if (useLldLink) linkerArgs.push("/lldmap:" + outputs.mem_map[0].filePath); else linkerArgs.push("/MAP:" + outputs.mem_map[0].filePath); } if (useCompilerDriver) args.push('/Fe' + linkerOutputNativeFilePath); else linkerArgs.push('/OUT:' + linkerOutputNativeFilePath); var libraryPaths = Cpp.collectLibraryPaths(product); linkerArgs = linkerArgs.concat([].uniqueConcat(libraryPaths).map(function(path) { return product.cpp.libraryPathFlag + FileInfo.toWindowsSeparators(path); })); handleDiscardProperty(product, linkerArgs); var linkerFlags = product.cpp.platformLinkerFlags.concat(product.cpp.linkerFlags); linkerArgs = linkerArgs.concat(linkerFlags); if (product.cpp.allowUnresolvedSymbols) linkerArgs.push("/FORCE:UNRESOLVED"); var wrapperArgs = product.cpp.linkerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(linkerPath); linkerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var commands = []; var warningCmd = new JavaScriptCommand(); warningCmd.silent = true; warningCmd.libDeps = libDeps; warningCmd.sourceCode = function() { for (var i = 0; i < libDeps.length; ++i) { if (!libDeps[i].productName || File.exists(libDeps[i].filePath)) continue; console.warn("Import library '" + FileInfo.toNativeSeparators(libDeps[i].filePath) + "' does not exist. This typically happens when a DLL does not " + "export any symbols. Please make sure the '" + libDeps[i].productName + "' library exports symbols, or, if you do not intend to actually " + "link against it, specify \"cpp.link: false\" in the Depends item."); } }; commands.push(warningCmd); if (linkerArgs.length !== 0) args = args.concat(useCompilerDriver ? ['/link'] : []).concat(linkerArgs); var cmd = new Command(linkerPath, args) cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = ["LINK", "_LINK_", "LIB", "TMP"]; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) cmd.responseFileUsagePrefix = '@'; cmd.responseFileSeparator = useCompilerDriver ? ' ' : '\n'; cmd.stdoutFilterFunction = function(output) { res = output.replace(/^.*performing full link.*\s*/, ""); res = res.replace(/^ *Creating library.*\s*/, ""); res = res.replace(/^\s*Generating code\s*/, ""); res = res.replace(/^\s*Finished generating code\s*/, ""); return res; }; commands.push(cmd); if (generateManifestFiles && !canEmbedManifest) { var outputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); cmd = new JavaScriptCommand(); cmd.src = linkerOutputNativeFilePath; cmd.dst = outputNativeFilePath; cmd.sourceCode = function() { File.copy(src, dst); } cmd.silent = true commands.push(cmd); args = ['/nologo', '/manifest'].concat(manifestFileNames); args.push("/outputresource:" + outputNativeFilePath + ";#" + (linkDLL ? "2" : "1")); cmd = new Command("mt.exe", args) cmd.description = 'embedding manifest into ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) commands.push(cmd); } if (product.cpp.shouldSignArtifacts) { Array.prototype.push.apply( commands, Codesign.prepareSigntool( project, product, inputs, outputs, input, output)); } return commands; } function createRcCommand(binary, input, output, logo) { var platformDefines = input.cpp.platformDefines; var defines = input.cpp.defines; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var args = []; if (logo === "can-suppress-logo") args.push("/nologo"); for (i in platformDefines) { args.push("/d"); args.push(platformDefines[i]); } for (i in defines) { args.push("/d"); args.push(defines[i]); } for (i in includePaths) { args.push("/I"); args.push(includePaths[i]); } for (i in systemIncludePaths) { args.push("/I"); args.push(systemIncludePaths[i]); } args = args.concat(["/FO", output.filePath, input.filePath]); var cmd = new Command(binary, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; cmd.jobPool = "compiler"; if (logo === "always-shows-logo") { // Remove the first two lines of stdout. That's the logo. cmd.stdoutFilterFunction = function(output) { var idx = 0; for (var i = 0; i < 3; ++i) idx = output.indexOf('\n', idx + 1); return output.substr(idx + 1); } } return cmd; } function assemblerCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = ["/nologo", "/c", "/Fo" + FileInfo.toWindowsSeparators(output.filePath)]; if (product.cpp.debugInformation) args.push("/Zi"); args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); args.push(FileInfo.toWindowsSeparators(input.filePath)); var cmd = new Command(product.cpp.assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.jobPool = "assembler"; cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { var lines = output.split("\r\n").filter(function (s) { return !s.endsWith(inputFileName); }); return lines.join("\r\n"); }; return cmd; } function libtoolOutputArtifacts(product) { var artifacts = [ { fileTags: ["staticlibrary"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)) } ]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { artifacts.push({ fileTags: ["debuginfo_cl"], filePath: product.targetName + ".cl" + product.cpp.debugInfoSuffix }); } return artifacts; } function libtoolCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = ['/nologo'] var lib = outputs["staticlibrary"][0]; var nativeOutputFileName = FileInfo.toWindowsSeparators(lib.filePath) args.push('/OUT:' + nativeOutputFileName) Array.prototype.push.apply(args, product.cpp.archiverFlags); for (var i in inputs.obj) { var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath) args.push(fileName) } for (var i in inputs.res) { var fileName = FileInfo.toWindowsSeparators(inputs.res[i].filePath) args.push(fileName) } var cmd = new Command(product.cpp.archiverPath, args); cmd.description = 'creating ' + lib.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.workingDirectory = FileInfo.path(lib.filePath) cmd.responseFileUsagePrefix = '@'; return cmd; } function dllLinkerOutputArtifacts(product) { var artifacts = [ { fileTags: ["dynamiclibrary"].concat( product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.dynamicLibraryFilePath(product)) }, { fileTags: ["dynamiclibrary_import"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.importLibraryFilePath(product)), alwaysUpdated: false } ]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { var lib = artifacts[0]; artifacts.push({ fileTags: ["debuginfo_dll"], filePath: lib.filePath.substr(0, lib.filePath.length - 4) + product.cpp.debugInfoSuffix }); } return artifacts; } function appLinkerOutputArtifacts(product) { var app = { fileTags: ["application"].concat( product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) }; var artifacts = [app]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { artifacts.push({ fileTags: ["debuginfo_app"], filePath: app.filePath.substr(0, app.filePath.length - 4) + product.cpp.debugInfoSuffix }); } if (product.cpp.generateLinkerMapFile) { artifacts.push({ fileTags: ["mem_map"], filePath: FileInfo.joinPaths( product.destinationDirectory, product.targetName + product.cpp.linkerMapSuffix) }); } return artifacts; } function configureStdModules() { try { const modulesJsonPath = FileInfo.joinPaths(_modulesDirPath, "modules.json"); if (File.exists(modulesJsonPath)) { const jsonFile = new TextFile(modulesJsonPath, TextFile.ReadOnly); const json = JSON.parse(jsonFile.readAll()); jsonFile.close(); const moduleSources = json["module-sources"]; if (moduleSources) { const modules = moduleSources .filter(function(module) { if (module === "std.ixx" && (_forceUseImportStd || _forceUseImportStdCompat)) { return true; } else if (module === "std.compat.ixx" && _forceUseImportStdCompat) { return true; } return false; }) .map(function(module) { return FileInfo.joinPaths(_modulesDirPath, module); }) .filter(function(module) { return File.exists(module); }); if (modules.length > 0) { found = true; _stdModulesFiles = modules; } } } } catch (e) { console.error("Error reading modules.json: " + e); } } qbs-src-3.3.1/share/qbs/modules/cpp/freebsd.js0000644000175100017510000000062715232633614020601 0ustar runnerrunnervar Utilities = require("qbs.Utilities"); function stripKernelReleaseSuffix(r) { var suffixes = ["-RELEASE", "-STABLE", "-CURRENT"]; for (var i = 0; i < suffixes.length; i++) { var idx = r.indexOf(suffixes[i]); if (idx >= 0) return r.substr(0, idx); } return r; } function hostKernelRelease() { return stripKernelReleaseSuffix(Utilities.kernelVersion()); } qbs-src-3.3.1/share/qbs/modules/cpp/cosmic.js0000644000175100017510000003730315232633614020445 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); function toolchainDetails(qbs) { var architecture = qbs.architecture; if (architecture.startsWith("arm")) { return { "executableSuffix": ".cxm", "staticLibrarySuffix": ".cxm", "assemblerName": "cacorm", "compilerName": "cxcorm" }; } else if (architecture === "stm8") { return { "executableSuffix": ".sm8", "staticLibrarySuffix": ".sm8", "assemblerName": "castm8", "compilerName": "cxstm8" }; } else if (architecture === "hcs8") { return { "executableSuffix": ".h08", "staticLibrarySuffix": ".h08", "assemblerName": "ca6808", "compilerName": "cx6808" }; } else if (architecture === "hcs12") { return { "executableSuffix": ".h12", "staticLibrarySuffix": ".h12", "assemblerName": "ca6812", "compilerName": "cx6812" }; } else if (architecture === "m68k") { return { "executableSuffix": ".332", "staticLibrarySuffix": ".332", "assemblerName": "ca332", "compilerName": "cx332" }; } } function guessArchitecture(compilerFilePath) { var baseName = FileInfo.baseName(compilerFilePath); if (baseName === "cxcorm") return "arm"; else if (baseName === "cxstm8") return "stm8"; else if (baseName === "cx6808") return "hcs8"; else if (baseName === "cx6812") return "hcs12"; else if (baseName === "cx332") return "m68k"; } function dumpMacros(compilerFilePath) { // Note: The COSMIC compiler does not support the predefined // macros dumping. So, we do it with the following trick, where we try // to create and compile a special temporary file and to parse the console // output with the own magic pattern: (""|"key"|"value"|""). var outputDirectory = new TemporaryDir(); var outputFilePath = FileInfo.fromNativeSeparators(FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c")); var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly); outputFile.writeLine("#define VALUE_TO_STRING(x) #x"); outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)"); outputFile.writeLine("#define VAR_NAME_VALUE(var) #var VALUE(var)"); // The COSMIC compiler defines only one pre-defined macro // (at least nothing is said about other macros in the documentation). var keys = ["__CSMC__"]; for (var i in keys) { var key = keys[i]; outputFile.writeLine("#if defined (" + key + ")"); outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))"); outputFile.writeLine("#endif"); } outputFile.close(); var process = new Process(); process.exec(compilerFilePath, [outputFilePath], false); File.remove(outputFilePath); var map = {}; // COSMIC compiler use the errors output! process.readStdErr().trim().split(/\r?\n/g).map(function(line) { var match = line.match(/^#message \("(.+)" "(.+)"\)$/); if (match) map[match[1]] = match[2]; }); return map; } function dumpVersion(compilerFilePath) { var p = new Process(); p.exec(compilerFilePath, ["-vers"]); // COSMIC compiler use the errors output! var output = p.readStdErr(); var match = output.match(/^COSMIC.+V(\d+)\.?(\d+)\.?(\*|\d+)?/); if (match) { var major = match[1] ? parseInt(match[1], 10) : 0; var minor = match[2] ? parseInt(match[2], 10) : 0; var patch = match[3] ? parseInt(match[3], 10) : 0; return { major: major, minor: minor, patch: patch }; } } function guessEndianness(architecture) { // There is no mention of supported endianness in the cosmic compiler. return "big"; } function dumpDefaultPaths(compilerFilePath, architecture) { var rootPath = FileInfo.path(compilerFilePath); var includePath; var includePaths = []; if (architecture.startsWith("arm")) { includePath = FileInfo.joinPaths(rootPath, "hcorm"); if (File.exists(includePath)) includePaths.push(includePath); } else if (architecture === "stm8") { includePath = FileInfo.joinPaths(rootPath, "hstm8"); if (File.exists(includePath)) includePaths.push(includePath); } else if (architecture === "hcs8") { includePath = FileInfo.joinPaths(rootPath, "h6808"); if (File.exists(includePath)) includePaths.push(includePath); } else if (architecture === "hcs12") { includePath = FileInfo.joinPaths(rootPath, "h6812"); if (File.exists(includePath)) includePaths.push(includePath); } else if (architecture === "m68k") { includePath = FileInfo.joinPaths(rootPath, "h332"); if (File.exists(includePath)) includePaths.push(includePath); } var libraryPaths = []; var libraryPath = FileInfo.joinPaths(rootPath, "lib"); if (File.exists(libraryPath)) libraryPaths.push(libraryPath); return { "includePaths": includePaths, "libraryPaths": libraryPaths, } } function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; // Up to 128 include files. args = args.concat(Cpp.collectPreincludePathsArguments(input)); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); // Up to 128 include paths. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); // Debug information flags. if (input.cpp.debugInformation) args.push("+debug"); var architecture = input.qbs.architecture; var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); // Warning level flags. switch (input.cpp.warningLevel) { case "none": // Disabled by default. break; case "all": // Highest warning level. args.push("-pw7"); break; } // C language version flags. if (tag === "c") { var knownValues = ["c99"]; var cLanguageVersion = Cpp.languageVersion( input.cpp.cLanguageVersion, knownValues, "C"); switch (cLanguageVersion) { case "c99": args.push("-p", "c99"); break; default: break; } } // Objects output directory. args.push("-co", FileInfo.path(outputs.obj[0].filePath)); // Listing files generation flag. if (input.cpp.generateCompilerListingFiles) { // Enable listings. args.push("-l"); // Listings output directory. args.push("-cl", FileInfo.path(outputs.lst[0].filePath)); } // Misc flags. args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(product)); // Input. args.push(input.filePath); return args; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; // Up to 128 include paths. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input)); // Debug information flags. if (input.cpp.debugInformation) args.push("-xx"); // Misc flags. args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); // Listing files generation flag. if (input.cpp.generateAssemblerListingFiles) { args.push("-l"); args.push("+l", outputs.lst[0].filePath); } // Objects output file path. args.push("-o", outputs.obj[0].filePath); // Input. args.push(input.filePath); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; // Library paths. args = args.concat(Cpp.collectLibraryPaths(product).map(function(path) { // It is workaround to use the relative paths avoids a strange linking // errors. Maybe it is related to the limitations on the length of the // command arguments, or on the length of the paths. return product.cpp.libraryPathFlag + Cpp.relativePath(product.buildDirectory, path); })); // Output. args.push("-o", outputs.application[0].filePath); // Map file generation flag. if (product.cpp.generateLinkerMapFile) args.push("-m", outputs.mem_map[0].filePath); // Misc flags. args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product), Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); // Linker scripts. args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs)); // Input objects. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); // Library dependencies (order has matters). args = args.concat(Cpp.collectLibraryDependencies(product).map(function(dep) { // It is workaround to use the relative paths avoids a strange linking // errors. Maybe it is related to the limitations on the length of the // command arguments, or on the length of the paths. return Cpp.relativePath(product.buildDirectory, dep.filePath); })); return args; } function archiverFlags(project, product, inputs, outputs) { var args = ["-cl"]; Array.prototype.push.apply(args, product.cpp.archiverFlags); // Output. args.push(outputs.staticlibrary[0].filePath); // Input objects. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); return args; } function createPath(fullPath) { var cmd = new JavaScriptCommand(); cmd.fullPath = fullPath; cmd.silent = true; cmd.sourceCode = function() { File.makePath(fullPath); }; return cmd; } // It is a workaround to rename the generated object file to the desired name. // Reason is that the Cosmic compiler always generates the object files in the // format of 'module.o', but we expect it in flexible format, e.g. 'module.c.obj' // or 'module.c.o' depending on the cpp.objectSuffix property. function renameObjectFile(project, product, inputs, outputs, input, output) { var object = outputs.obj[0]; var cmd = new JavaScriptCommand(); cmd.newObject = object.filePath; cmd.oldObject = FileInfo.joinPaths(FileInfo.path(object.filePath), object.baseName + ".o"); cmd.silent = true; cmd.sourceCode = function() { File.move(oldObject, newObject); }; return cmd; } // It is a workaround to rename the generated listing file to the desired name. // Reason is that the Cosmic compiler always generates the listing files in the // format of 'module.ls', but we expect it in flexible format, e.g. 'module.c.lst' // or 'module.c.ls' depending on the cpp.compilerListingSuffix property. function renameListingFile(project, product, inputs, outputs, input, output) { var listing = outputs.lst[0]; var cmd = new JavaScriptCommand(); cmd.newListing = listing.filePath; cmd.oldListing = FileInfo.joinPaths(FileInfo.path(listing.filePath), listing.baseName + ".ls"); cmd.silent = true; cmd.sourceCode = function() { File.move(oldListing, newListing); }; return cmd; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; // Create output objects path, because the Cosmic doesn't do it. var cmd = createPath(FileInfo.path(outputs.obj[0].filePath)); cmds.push(cmd); // Create output listing path, because the Cosmic doesn't do it. if (input.cpp.generateCompilerListingFiles) { cmd = createPath(FileInfo.path(outputs.lst[0].filePath)); cmds.push(cmd); } var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); cmd = new Command(input.cpp.compilerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmds.push(cmd); cmds.push(renameObjectFile(project, product, inputs, outputs, input, output)); if (input.cpp.generateCompilerListingFiles) cmds.push(renameListingFile(project, product, inputs, outputs, input, output)); return cmds; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; // Create output objects path, because the Cosmic doesn't do it. var cmd = createPath(FileInfo.path(outputs.obj[0].filePath)); cmds.push(cmd); // Create output listing path, because the Cosmic doesn't do it. if (input.cpp.generateCompilerListingFiles) { cmd = createPath(FileInfo.path(outputs.lst[0].filePath)); cmds.push(cmd); } var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn); cmd = new Command(input.cpp.assemblerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; cmds.push(cmd); return cmds; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var cmd = new Command(product.cpp.linkerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; return [cmd]; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, inputs, outputs); var cmd = new Command(product.cpp.archiverPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "creating " + output.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/darwin.js0000644000175100017510000002267715232633614020464 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Codesign = require("../codesign/codesign.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Gcc = require("./gcc.js"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); function lipoOutputArtifacts(product, inputs, fileTag, debugSuffix) { var buildVariants = []; for (var i = 0; i < inputs[fileTag].length; ++i) { var variant = inputs[fileTag][i].qbs.buildVariant; var suffix = inputs[fileTag][i].cpp.variantSuffix; if (!buildVariants.some(function (x) { return x.name === variant; })) buildVariants.push({ name: variant, suffix: suffix }); } var list = []; if (fileTag === "dynamiclibrary") { Array.prototype.push.apply(list, buildVariants.map(function (variant) { return { filePath: product.destinationDirectory + "/.sosymbols/" + PathTools.dynamicLibraryFilePath(product, variant.suffix), fileTags: ["dynamiclibrary_symbols"], qbs: { buildVariant: variant.name }, cpp: { variantSuffix: variant.suffix }, alwaysUpdated: false }; })); buildVariants.forEach(function (variant) { Array.prototype.push.apply(list, Gcc.librarySymlinkArtifacts(product, variant.suffix)); }); } // Bundles should have a "normal" variant. In the case of frameworks, they cannot normally be // linked to without a default variant unless a variant is specifically chosen at link time // by passing the full path to the shared library executable instead of the -framework switch. // Technically this doesn't affect qbs since qbs always uses full paths for internal // dependencies but the "normal" variant is always the one that is linked to, since the // alternative variants should only be chosen at runtime using the DYLD_IMAGE_SUFFIX variable. // So for frameworks we'll create a copy of the "default" variant as chosen by the user // (we cannot do this automatically since the user must tell us which variant should be // preferred, if there are multiple alternative variants). Applications are fine without a // copy but still need an explicitly chosen variant to set as the CFBundleExecutable so that // Finder/LaunchServices can launch it normally but for simplicity we'll just use the copy // approach for all bundle types. var defaultVariant; if (!buildVariants.some(function (x) { return x.name === "release"; }) && product.multiplexByQbsProperties.includes("buildVariants") && product.qbs.buildVariants && product.qbs.buildVariants.length > 1) { var defaultBuildVariant = product.qbs.defaultBuildVariant; buildVariants.map(function (variant) { if (variant.name === defaultBuildVariant) defaultVariant = variant; }); if (!defaultVariant) { throw new Error("qbs.defaultBuildVariant is '" + defaultBuildVariant + "', but this " + "variant is not in the qbs.buildVariants list (" + product.qbs.buildVariants.join(", ") + ")"); } buildVariants.push({ name: "release", suffix: "", isVariantCopy: true }); } Array.prototype.push.apply(list, buildVariants.map(function (variant) { var tags = ["bundle.input"]; if (variant.isVariantCopy) tags.push("bundle.variant_copy"); else tags.push(fileTag, "primary"); // Non-main bundles should be copyable into main bundles if (product.bundle && !product.bundle.isMainBundle && !product.bundle.isBundle) { // Static libraries are not supported as an input to main bundle since // they cannot be signed and main bundle should have all additional files signed. tags.push("bundle.main.input"); if (fileTag === "application") tags.push("bundle.main.executable"); else if (fileTag === "dynamiclibrary") tags.push("bundle.main.library"); else if (fileTag === "staticlibrary") tags.push("bundle.main.library"); else if (fileTag === "loadablemodule") tags.push("bundle.main.plugin"); } if (product.codesign.enableCodeSigning) tags.push("codesign.signed_artifact"); return { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.linkerOutputFilePath(fileTag, product, variant.suffix)), fileTags: tags, qbs: { buildVariant: variant.name, _buildVariantFilePath: variant.isVariantCopy && defaultVariant ? FileInfo.joinPaths(product.destinationDirectory, PathTools.linkerOutputFilePath( fileTag, product, defaultVariant.suffix)) : undefined }, bundle: { _bundleFilePath: product.destinationDirectory + "/" + PathTools.bundleExecutableFilePath(product, variant.suffix) }, cpp: { variantSuffix: variant.suffix } }; })); if (debugSuffix) Array.prototype.push.apply(list, Gcc.debugInfoArtifacts(product, buildVariants, debugSuffix)); return list; } function prepareLipo(project, product, inputs, outputs, input, output) { var cmd; var commands = []; for (var p in inputs) inputs[p] = inputs[p].filter(function(inp) { return inp.product.name === product.name; }); var allInputs = [].concat.apply([], Object.keys(inputs).map(function (tag) { return ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"].includes(tag) ? inputs[tag] : []; })); for (var i = 0; i < outputs.primary.length; ++i) { var vInputs = allInputs.filter(function (f) { return f.qbs.buildVariant === outputs.primary[i].qbs.buildVariant }).map(function (f) { return f.filePath }); if (vInputs.length > 1 || product.cpp.alwaysUseLipo) { cmd = new Command(ModUtils.moduleProperty(product, "lipoPath"), ["-create", "-output", outputs.primary[i].filePath].concat(vInputs)); cmd.description = "lipo " + outputs.primary[i].fileName; cmd.highlight = "linker"; } else { cmd = new JavaScriptCommand(); cmd.src = vInputs[0]; cmd.dst = outputs.primary[i].filePath; cmd.sourceCode = function () { File.copy(src, dst); }; cmd.silent = true; } Array.prototype.push.apply(commands, Gcc.librarySymlinkCommands(outputs, outputs.primary[i])); commands.push(cmd); } (outputs["bundle.variant_copy"] || []).map(function (copy) { cmd = new JavaScriptCommand(); cmd.src = copy.qbs._buildVariantFilePath; cmd.dst = copy.filePath; cmd.sourceCode = function () { File.copy(src, dst); }; cmd.silent = true; commands.push(cmd); }); commands = commands.concat( Gcc.separateDebugInfoCommandsDarwin(product, outputs, outputs.primary)); if (outputs.dynamiclibrary_symbols) Array.prototype.push.apply(commands, Gcc.createSymbolCheckingCommands(product, outputs)); if (product.codesign.enableCodeSigning) { Array.prototype.push.apply( commands, Codesign.prepareSign(project, product, inputs, outputs, input, output)); } return commands; } qbs-src-3.3.1/share/qbs/modules/cpp/keil.qbs0000644000175100017510000001304515232633614020262 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.Probes import "cpp.js" as Cpp import "keil.js" as KEIL CppModule { condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("keil") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["c51"] } Probes.KeilProbe { id: keilProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage } Properties { condition: keilProbe.found qbs.architecture: keilProbe.architecture } qbs.targetPlatform: "none" compilerVersionMajor: keilProbe.versionMajor compilerVersionMinor: keilProbe.versionMinor compilerVersionPatch: keilProbe.versionPatch endianness: keilProbe.endianness compilerDefinesByLanguage: keilProbe.compilerDefinesByLanguage compilerIncludePaths: keilProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: toolchainDetails.compilerName + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: toolchainDetails.assemblerName + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: toolchainDetails.linkerName + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) archiverName: toolchainDetails.archiverName + compilerExtension archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) property string disassemblerName: toolchainDetails.disassemblerName + compilerExtension property string disassemblerPath: FileInfo.joinPaths(toolchainInstallPath, disassemblerName) runtimeLibrary: "static" staticLibrarySuffix: ".lib" executableSuffix: toolchainDetails.executableSuffix objectSuffix: toolchainDetails.objectSuffix linkerMapSuffix: toolchainDetails.linkerMapSuffix imageFormat: toolchainDetails.imageFormat enableExceptions: false enableRtti: false defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-I" preincludeFlag: KEIL.preincludeFlag(compilerPath) libraryDependencyFlag: "" libraryPathFlag: "--userlibpath=" linkerScriptFlag: "--scatter" toolchainDetails: KEIL.toolchainDetails(qbs) knownArchitectures: ["arm", "c166", "mcs251", "mcs51"] Rule { id: assembler inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: KEIL.prepareAssembler.apply(KEIL, arguments) } FileTagger { patterns: ["*.s", "*.a51", ".asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles) outputArtifacts: Cpp.compilerOutputArtifacts(input) prepare: KEIL.prepareCompiler.apply(KEIL, arguments) } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile) outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product) prepare: KEIL.prepareLinker.apply(KEIL, arguments) } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: KEIL.prepareArchiver.apply(KEIL, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/windows-clang-mingw.qbs0000644000175100017510000000742515232633614023236 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Utilities import "msvc.js" as MSVC import "setuprunenv.js" as SetupRunEnv MingwBaseModule { condition: qbs.targetOS.includes("windows") && qbs.toolchain && qbs.toolchain.includes("clang") priority: 0 // llvm-as and llvm-objopy are not shipped with the official binaries on Windows at the // moment (8.0). We fall back to using the mingw versions in that case. assemblerName: "llvm-as" + compilerExtension assemblerPath: { if (File.exists(base)) return base; if (qbs.sysroot) return FileInfo.joinPaths(qbs.sysroot, "bin", "as" + compilerExtension); } objcopyName: "llvm-objcopy" + compilerExtension objcopyPath: { if (File.exists(base)) return base; if (qbs.sysroot) return FileInfo.joinPaths(qbs.sysroot, "bin", "objcopy" + compilerExtension); } archiverName: "llvm-ar" + compilerExtension linkerVariant: "lld" targetVendor: "pc" targetSystem: "windows" targetAbi: "gnu" property string rcFilePath: FileInfo.joinPaths(toolchainInstallPath, "llvm-rc" + compilerExtension) setupBuildEnvironment: { if (Host.os().includes("windows") && product.qbs.sysroot) { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true); v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin")); v.set(); } } setupRunEnvironment: { if (Host.os().includes("windows") && product.qbs.sysroot) { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true); v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin")); v.set(); SetupRunEnv.setupRunEnvironment(product, config); } } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] Artifact { filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.completeBaseName + ".res") fileTags: ["obj"] } prepare: MSVC.createRcCommand(product.cpp.rcFilePath, input, output) } } qbs-src-3.3.1/share/qbs/modules/cpp/watchos-gcc.qbs0000644000175100017510000000427015232633614021540 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DarwinGCC { priority: 1 condition: qbs.targetOS.includes('watchos') && qbs.toolchain && qbs.toolchain.includes('gcc') targetSystem: "watchos" + (minimumWatchosVersion || "") minimumDarwinVersion: minimumWatchosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("watchos-simulator") ? "-mwatchos-simulator-version-min" : "-mwatchos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("watchos-simulator") ? "-watchos_simulator_version_min" : "-watchos_version_min" } qbs-src-3.3.1/share/qbs/modules/cpp/windows-msvc.qbs0000644000175100017510000000713415232633614022000 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Host import qbs.Probes import "windows-msvc-base.qbs" as MsvcBaseModule import 'msvc.js' as MSVC MsvcBaseModule { condition: Host.os().includes('windows') && qbs.targetOS.includes('windows') && qbs.toolchain && qbs.toolchain.includes('msvc') priority: 50 Probes.ClBinaryProbe { id: compilerPathProbe preferredArchitecture: qbs.architecture condition: !toolchainInstallPath && !_skipAllChecks names: ["cl"] } Probes.MsvcProbe { id: msvcProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture winSdkVersion: windowsSdkVersion } Properties { condition: msvcProbe.found qbs.architecture: msvcProbe.architecture } compilerVersionMajor: msvcProbe.versionMajor compilerVersionMinor: msvcProbe.versionMinor compilerVersionPatch: msvcProbe.versionPatch compilerIncludePaths: msvcProbe.includePaths compilerDefinesByLanguage: msvcProbe.compilerDefinesByLanguage toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined buildEnv: msvcProbe.buildEnv enableCxxLanguageMacro: true compiledModuleSuffix: ".ifc" moduleOutputFlag: "-ifcOutput " moduleFileFlag: "-reference %module%=" stdModulesFiles: stdModulesProbe.found ? stdModulesProbe._stdModulesFiles : undefined Probe { id: stdModulesProbe condition: msvcProbe.found && !_skipAllChecks && stdModulesFiles === undefined && (forceUseImportStd || forceUseImportStdCompat) // input property string _modulesDirPath: msvcProbe.modulesPath property bool _forceUseImportStd : forceUseImportStd property bool _forceUseImportStdCompat : forceUseImportStdCompat // output property stringList _stdModulesFiles configure: MSVC.configureStdModules() } } qbs-src-3.3.1/share/qbs/modules/cpp/LinuxGCC.qbs0000644000175100017510000000540515232633614020753 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Host import qbs.Process UnixGCC { condition: qbs.targetOS.includes('linux') && qbs.toolchain && qbs.toolchain.includes('gcc') priority: 1 targetVendor: "pc" targetSystem: "linux" targetAbi: "gnu" Probe { id: runPathsProbe condition: !_skipAllChecks && qbs.targetPlatform === Host.platform() property stringList systemRunPaths: [] configure: { var paths = []; var ldconfig = new Process(); try { var success = ldconfig.exec("ldconfig", ["-vNX"]); if (success === -1) return; var line; do { line = ldconfig.readLine(); if (line.charAt(0) === '/') { var colonIndex = line.indexOf(':'); if (colonIndex == -1) continue; paths.push(line.slice(0, colonIndex)); } } while (line && line.length > 0) found = true; systemRunPaths = paths; } finally { ldconfig.close(); } } } systemRunPaths: runPathsProbe.found ? runPathsProbe.systemRunPaths : base } qbs-src-3.3.1/share/qbs/modules/cpp/windows-mingw.qbs0000644000175100017510000000737315232633614022156 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Utilities import 'cpp.js' as Cpp import "setuprunenv.js" as SetupRunEnv MingwBaseModule { condition: qbs.targetOS.includes("windows") && qbs.toolchain && qbs.toolchain.includes("mingw") priority: 0 probeEnv: buildEnv property string windresName: "windres" + compilerExtension property path windresPath: { var filePath = toolchainPathPrefix + windresName; if (!File.exists(filePath)) filePath = FileInfo.joinPaths(toolchainInstallPath, windresName); return filePath; } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true); v.prepend(product.cpp.toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true); v.prepend(product.cpp.toolchainInstallPath); v.set(); SetupRunEnv.setupRunEnvironment(product, config); } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.resourceCompilerOutputTags() outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input) prepare: { var platformDefines = input.cpp.platformDefines; var defines = input.cpp.defines; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var args = []; var i; for (i in platformDefines) { args.push('-D'); args.push(platformDefines[i]); } args = args.concat(Cpp.collectDefinesArguments(input)); args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input, "-I")); args.push("-O", "coff"); // Set COFF format explicitly. args = args.concat(['-i', input.filePath, '-o', output.filePath]); var cmd = new Command(product.cpp.windresPath, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; } } } qbs-src-3.3.1/share/qbs/modules/cpp/windows-clang-cl.qbs0000644000175100017510000000745415232633614022515 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Host import qbs.ModUtils import qbs.Probes import qbs.FileInfo import 'windows-msvc-base.qbs' as MsvcBaseModule MsvcBaseModule { condition: Host.os().includes('windows') && qbs.targetOS.includes('windows') && qbs.toolchain && qbs.toolchain.includes('clang-cl') priority: 100 Probes.ClangClBinaryProbe { id: clangPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["clang-cl"] } Probes.ClangClProbe { id: clangClProbe condition: !_skipAllChecks compilerFilePath: compilerPath vcvarsallFilePath: vcvarsallPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture winSdkVersion: windowsSdkVersion } Properties { condition: clangClProbe.found qbs.architecture: clangClProbe.architecture } compilerVersionMajor: clangClProbe.versionMajor compilerVersionMinor: clangClProbe.versionMinor compilerVersionPatch: clangClProbe.versionPatch compilerIncludePaths: clangClProbe.includePaths compilerDefinesByLanguage: clangClProbe.compilerDefinesByLanguage toolchainInstallPath: clangPathProbe.found ? clangPathProbe.path : undefined buildEnv: clangClProbe.buildEnv property string linkerVariant PropertyOptions { name: "linkerVariant" allowedValues: ["lld", "link"] description: "Allows to specify the linker variant. Maps to clang-cl's -fuse-ld option." } Properties { condition: linkerVariant driverLinkerFlags: "-fuse-ld=" + linkerVariant } property string vcvarsallPath : clangPathProbe.found ? clangPathProbe.vcvarsallPath : undefined archiverName: "llvm-lib.exe" compilerName: "clang-cl.exe" linkerName: "lld-link.exe" linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) systemIncludeFlag: "/imsvc" validateFunc: { var baseFunc = base; return function() { if (_skipAllChecks) return; var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("vcvarsallPath", vcvarsallPath); validator.validate(); baseFunc(); } } } qbs-src-3.3.1/share/qbs/modules/cpp/watcom.js0000644000175100017510000005470115232633614020463 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function toolchainDetails(qbs) { var platform = qbs.targetPlatform; var details = {}; if (platform === "dos") { details.imageFormat = "mz"; details.executableSuffix = ".exe"; } else if (platform === "os2") { details.imageFormat = "pe"; details.executableSuffix = ".exe"; details.dynamicLibrarySuffix = ".dll"; } else if (platform === "windows") { details.imageFormat = "pe"; details.executableSuffix = ".exe"; details.dynamicLibrarySuffix = ".dll"; } else if (platform === "linux") { details.imageFormat = "elf"; details.executableSuffix = ""; details.dynamicLibrarySuffix = ".so"; } return details; } function languageFlag(tag) { if (tag === "c") return "-xc"; else if (tag === "cpp") return "-xc++"; } function targetFlag(platform, architecture, type) { if (platform === "dos") { if (architecture === "x86_16") return "-bdos"; else if (architecture === "x86") return "-bdos4g"; } else if (platform === "os2") { if (architecture === "x86_16") return "-bos2"; else if (architecture === "x86") return "-bos2v2"; } else if (platform === "windows") { if (architecture === "x86_16") { if (type.includes("dynamiclibrary")) return "-bwindows_dll"; return "-bwindows"; } else if (architecture === "x86") { if (type.includes("dynamiclibrary")) return "-bnt_dll"; return "-bnt"; } } else if (platform === "linux") { return "-blinux"; } } function guessVersion(macros) { var version = parseInt(macros["__WATCOMC__"], 10) || parseInt(macros["__WATCOM_CPLUSPLUS__"], 10); if (version) { return { major: parseInt((version - 1100) / 100), minor: parseInt(version / 10) % 10, patch: ((version % 10) > 0) ? parseInt(version % 10) : 0 } } } function guessEnvironment(hostOs, platform, architecture, toolchainInstallPath, pathListSeparator) { var toolchainRootPath = FileInfo.path(toolchainInstallPath); if (!File.exists(toolchainRootPath)) { throw "Unable to deduce environment due to compiler root directory: '" + toolchainRootPath + "' does not exist"; } var env = {}; function setVariable(key, properties, path, separator) { var values = []; for (var i = 0; i < properties.length; ++i) { if (path) { var fullpath = FileInfo.joinPaths(path, properties[i]); values.push(FileInfo.toNativeSeparators(fullpath)); } else { values.push(properties[i]); } } env[key] = values.join(separator); } setVariable("WATCOM", [toolchainRootPath], undefined, pathListSeparator); setVariable("EDPATH", ["eddat"], toolchainRootPath, pathListSeparator); if (hostOs.includes("linux")) setVariable("PATH", ["binl64", "binl"], toolchainRootPath, pathListSeparator); else if (hostOs.includes("windows")) setVariable("PATH", ["binnt64", "binnt"], toolchainRootPath, pathListSeparator); if (platform === "linux") { setVariable("INCLUDE", ["lh"], toolchainRootPath, pathListSeparator); } else { // Common for DOS, Windows, OS/2. setVariable("WIPFC", ["wipfc"], toolchainRootPath, pathListSeparator); setVariable("WHTMLHELP", ["binnt/help"], toolchainRootPath, pathListSeparator); var includes = ["h"]; if (platform === "dos") { // Same includes as before. } else if (platform === "os2") { if (architecture === "x86") includes = includes.concat(["h/os2"]); else if (architecture === "x86_16") includes = includes.concat(["h/os21x"]); } else if (platform === "windows") { if (architecture === "x86") includes = includes.concat(["h/nt", "h/nt/directx", "h/nt/ddk"]); else if (architecture === "x86_16") includes = includes.concat(["h/win"]); } else { throw "Unable to deduce environment for unsupported target platform: '" + platform + "'"; } setVariable("INCLUDE", includes, toolchainRootPath, pathListSeparator); } return env; } function dumpMacros(environment, compilerPath, platform, architecture, tag) { // Note: The Open Watcom compiler does not support the predefined // macros dumping. So, we do it with the following trick, where we try // to create and compile a special temporary file and to parse the console // output with the own magic pattern: #define . var outputDirectory = new TemporaryDir(); var outputFilePath = FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c"); var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly); outputFile.writeLine("#define VALUE_TO_STRING(x) #x"); outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)"); outputFile.writeLine("#define VAR_NAME_VALUE(var) \"#define \"#var\" \"VALUE(var)"); // Declare all available pre-defined macros of Watcon compiler. var keys = [ // Prepare the DOS target macros. "__DOS__", "_DOS", "MSDOS", // Prepare the OS/2 target macros. "__OS2__", // Prepare the QNX target macros. "__QNX__", // Prepare the Netware target macros. "__NETWARE__", "__NETWARE_386__", // Prepare the Windows target macros. "__NT__", "__WINDOWS__", "_WINDOWS", "__WINDOWS_386__", // Prepare the Linux and Unix target macros. "__LINUX__", "__UNIX__", // Prepare the 16-bit target specific macros. "__I86__", "M_I86", "_M_I86", "_M_IX86", // Prepare the 32-bit target specific macros. "__386__", "M_I386", "_M_I386", "_M_IX86", // Prepare the indicated options macros. "_MT", "_DLL", "__FPI__", "__CHAR_SIGNED__", "__INLINE_FUNCTIONS__", "_CPPRTTI", "_CPPUNWIND", "NO_EXT_KEYS", // Prepare the common memory model macros. "__FLAT__", "__SMALL__", "__MEDIUM__", "__COMPACT__", "__LARGE__", "__HUGE__", // Prepare the 16-bit memory model macros. "M_I86SM", "_M_I86SM", "M_I86MM", "_M_I86MM", "M_I86CM", "_M_I86CM", "M_I86LM", "_M_I86LM", "M_I86HM", "_M_I86HM", // Prepare the 32-bit memory model macros. "M_386FM", "_M_386FM", "M_386SM", "M_386MM", "_M_386MM", "M_386CM", "_M_386CM", "M_386LM", "_M_386LM", // Prepare the compiler macros. "__X86__", "__cplusplus", "__WATCOMC__", "__WATCOM_CPLUSPLUS__", "_INTEGRAL_MAX_BITS", "_PUSHPOP_SUPPORTED", "_STDCALL_SUPPORTED", // Prepare the other macros. "__3R__", "_based", "_cdecl", "cdecl", "_export", "_far16", "_far", "far", "_fastcall", "_fortran", "fortran", "_huge", "huge", "_inline", "_interrupt", "interrupt", "_loadds", "_near", "near", "_pascal", "pascal", "_saveregs", "_segment", "_segname", "_self", "SOMDLINK", "_STDCALL_SUPPORTED", "__SW_0", "__SW_3R", "__SW_5", "__SW_FP287", "__SW_FP2", "__SW_FP387", "__SW_FP3", "__SW_FPI", "__SW_MF", "__SW_MS", "__SW_ZDP", "__SW_ZFP", "__SW_ZGF", "__SW_ZGP", "_stdcall", "_syscall", "__BIG_ENDIAN" ]; for (var i = 0; i < keys.length; ++i) { var key = keys[i]; outputFile.writeLine("#if defined(" + key + ")"); outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))"); outputFile.writeLine("#endif"); } outputFile.close(); var process = new Process(); process.setWorkingDirectory(outputDirectory.path()); for (var envkey in environment) process.setEnv(envkey, environment[envkey]); var target = targetFlag(platform, architecture, ["application"]); var lang = languageFlag(tag); var args = [ target, lang, outputFilePath ]; process.exec(compilerPath, args, false); var m = Cpp.extractMacros(process.readStdOut(), /"?(#define(\s\w+){1,2})"?$/); if (tag === "cpp" && m["__cplusplus"] === "1") return m; else if (tag === "c") return m; } function effectiveLinkerPath(product) { if (product.cpp.linkerMode === "automatic") { var compilerPath = product.cpp.compilerPath; if (compilerPath) return compilerPath; console.log("Found no C-language objects, choosing system linker for " + product.name); } return product.cpp.linkerPath; } function useCompilerDriverLinker(product) { var linker = effectiveLinkerPath(product); var compiler = product.cpp.compilerPath; return linker === compiler; } function escapeLinkerFlags(useCompilerDriver, linkerFlags) { if (!linkerFlags || linkerFlags.length === 0) return []; if (useCompilerDriver) { var sep = ","; return [["-Wl"].concat(linkerFlags).join(sep)]; } return linkerFlags; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = [FileInfo.toNativeSeparators(input.filePath)]; args.push("-fo=" + FileInfo.toNativeSeparators(outputs.obj[0].filePath)); args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) { return "-fi" + FileInfo.toNativeSeparators(path); })); args = args.concat(Cpp.collectDefinesArguments(input, "-d")); var includePaths = [].concat(Cpp.collectIncludePaths(input)).concat( Cpp.collectSystemIncludePaths(input)); args = args.concat(includePaths.map(function(path) { return "-i" + FileInfo.toNativeSeparators(path); })); if (input.cpp.debugInformation) args.push("-d1"); var warnings = input.cpp.warningLevel if (warnings === "none") args.push("-w0"); else if (warnings === "all") args.push("-wx"); if (input.cpp.treatWarningsAsErrors) args.push("-we"); args.push("-zq"); // Silent. args = args.concat(Cpp.collectMiscAssemblerArguments(input)); return args; } function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = ["-g" + (input.cpp.debugInformation ? "3" : "0")]; var target = targetFlag(product.qbs.targetPlatform, product.qbs.architecture, product.type); args.push(target); if (product.type.includes("application")) { if (product.qbs.targetPlatform === "windows") { var consoleApplication = product.consoleApplication; args.push(consoleApplication ? "-mconsole" : "-mwindows"); } } else if (product.type.includes("dynamiclibrary")) { args.push("-shared"); } var optimization = input.cpp.optimization if (optimization === "fast") args.push("-Ot"); else if (optimization === "small") args.push("-Os"); else if (optimization === "none") args.push("-O0"); var warnings = input.cpp.warningLevel if (warnings === "none") { args.push("-w"); } else if (warnings === "all") { args.push("-Wall"); args.push("-Wextra"); } if (input.cpp.treatWarningsAsErrors) args.push("-Werror"); var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); var langFlag = languageFlag(tag); if (langFlag) args.push(langFlag); if (tag === "cpp") { var enableExceptions = input.cpp.enableExceptions; if (enableExceptions) { var ehModel = input.cpp.exceptionHandlingModel; switch (ehModel) { case "direct": args.push("-feh-direct"); break; case "table": args.push("-feh-table"); break; default: args.push("-feh"); break; } } else { args.push("-fno-eh"); } var enableRtti = input.cpp.enableRtti; args.push(enableRtti ? "-frtti" : "-fno-rtti"); } else if (tag === "c") { var knownValues = ["c99", "c89"]; var cLanguageVersion = Cpp.languageVersion(input.cpp.cLanguageVersion, knownValues, "C"); switch (cLanguageVersion) { case "c89": args.push("-std=c89"); break; case "c99": args.push("-std=c99"); break; } } var preincludePaths = Cpp.collectPreincludePaths(input); for (var i = 0; i < preincludePaths.length; ++i) args.push(input.cpp.preincludeFlag, preincludePaths[i]); args = args.concat(Cpp.collectDefinesArguments(input)); args = args.concat(Cpp.collectIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toNativeSeparators(path); })); args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) { return input.cpp.systemIncludeFlag + FileInfo.toNativeSeparators(path); })); args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(input)); args.push("-o", FileInfo.toNativeSeparators(outputs.obj[0].filePath)); args.push("-c", FileInfo.toNativeSeparators(input.filePath)); return args; } function resourceCompilerFlags(project, product, input, outputs) { var args = [input.filePath]; args.push("-fo=" + FileInfo.toNativeSeparators(outputs.res[0].filePath)); args = args.concat(Cpp.collectDefinesArguments(input, "-d")); args = args.concat(Cpp.collectIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toNativeSeparators(path); })); args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) { return input.cpp.includeFlag + FileInfo.toNativeSeparators(path); })); args.push("-q", "-ad", "-r"); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; var useCompilerDriver = useCompilerDriverLinker(product); if (useCompilerDriver) { var target = targetFlag(product.qbs.targetPlatform, product.qbs.architecture, product.type); args.push(target); if (product.type.includes("application")) { args.push("-o", FileInfo.toNativeSeparators(outputs.application[0].filePath)); if (product.cpp.generateLinkerMapFile) args.push("-fm=" + FileInfo.toNativeSeparators(outputs.mem_map[0].filePath)); } else if (product.type.includes("dynamiclibrary")) { if (product.qbs.targetPlatform === "windows") { args.push("-Wl, option implib=" + FileInfo.toNativeSeparators( outputs.dynamiclibrary_import[0].filePath)); } args.push("-o", FileInfo.toNativeSeparators(outputs.dynamiclibrary[0].filePath)) } var escapableLinkerFlags = []; var targetLinkerFlags = product.cpp.targetLinkerFlags; if (targetLinkerFlags) escapableLinkerFlags = escapableLinkerFlags.concat(targetLinkerFlags); escapableLinkerFlags = escapableLinkerFlags.concat( Cpp.collectMiscEscapableLinkerArguments(product)); var escapedLinkerFlags = escapeLinkerFlags(useCompilerDriver, escapableLinkerFlags); if (escapedLinkerFlags) args = args.concat(escapedLinkerFlags); args = args.concat(Cpp.collectLibraryPaths(product).map(function(path) { return product.cpp.libraryPathFlag + FileInfo.toNativeSeparators(path); })); args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) { return FileInfo.toNativeSeparators(path); })); var libraryDependencies = Cpp.collectLibraryDependencies(product); for (var i = 0; i < libraryDependencies.length; ++i) { var lib = libraryDependencies[i].filePath; if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) args.push(FileInfo.toNativeSeparators(lib)); else args.push("-Wl, libfile " + lib); } var resourcePaths = Cpp.collectResourceObjectPaths(inputs).map(function(path) { return FileInfo.toNativeSeparators(path); }); if (resourcePaths.length > 0) args = args.concat("-Wl, resource " + resourcePaths.join(",")); } args = args.concat(Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); return args; } function libraryManagerFlags(project, product, inputs, outputs) { var args = ["-b", "-n", "-q"]; args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) { return "+" + FileInfo.toNativeSeparators(path); })); args.push("-o", FileInfo.toNativeSeparators(outputs.staticlibrary[0].filePath)); return args; } function disassemblerFlags(project, product, inputs, outputs) { var objectPath = Cpp.relativePath(product.buildDirectory, outputs.obj[0].filePath); var listingPath = Cpp.relativePath(product.buildDirectory, outputs.lst[0].filePath); var args = []; args.push(FileInfo.toNativeSeparators(objectPath)); args.push("-l=" + FileInfo.toNativeSeparators(listingPath)); args.push("-s", "-a"); return args; } function generateCompilerListing(project, product, inputs, outputs, input, output) { var args = disassemblerFlags(project, product, input, outputs); var cmd = new Command(input.cpp.disassemblerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.silent = true; cmd.jobPool = "watcom_job_pool"; return cmd; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = assemblerFlags(project, product, input, outputs); var cmd = new Command(input.cpp.assemblerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "watcom_job_pool"; cmds.push(cmd); if (input.cpp.generateAssemblerListingFiles) cmds.push(generateCompilerListing(project, product, inputs, outputs, input, output)); return cmds; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); var cmd = new Command(input.cpp.compilerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "watcom_job_pool"; cmds.push(cmd); if (input.cpp.generateCompilerListingFiles) cmds.push(generateCompilerListing(project, product, inputs, outputs, input, output)); return cmds; } function prepareResourceCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = resourceCompilerFlags(project, product, input, outputs); var cmd = new Command(input.cpp.resourceCompilerPath, args); // Set working directory to source directory as a workaround // to make the resources compilable by resource compiler (it is magic). cmd.workingDirectory = product.sourceDirectory; cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "watcom_job_pool"; return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.dynamiclibrary ? outputs.dynamiclibrary[0] : outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = effectiveLinkerPath(product); var cmd = new Command(linkerPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.jobPool = "watcom_job_pool"; return [cmd]; } function prepareLibraryManager(project, product, inputs, outputs, input, output) { var args = libraryManagerFlags(project, product, inputs, outputs); var cmd = new Command(product.cpp.archiverPath, args); cmd.workingDirectory = product.buildDirectory; cmd.description = "linking " + outputs.staticlibrary[0].fileName; cmd.highlight = "linker"; cmd.jobPool = "watcom_job_pool"; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/windows-msvc-base.qbs0000644000175100017510000002034215232633614022704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Utilities import qbs.WindowsUtils import 'cpp.js' as Cpp import 'msvc.js' as MSVC CppModule { condition: false Depends { name: "codesign" } windowsApiCharacterSet: "unicode" platformDefines: { var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) .concat("WIN32"); var def = WindowsUtils.winapiFamilyDefine(windowsApiFamily); if (def) defines.push("WINAPI_FAMILY=WINAPI_FAMILY_" + def); (windowsApiAdditionalPartitions || []).map(function (name) { defines.push("WINAPI_PARTITION_" + WindowsUtils.winapiPartitionDefine(name) + "=1"); }); return defines; } platformCommonCompilerFlags: { var flags = base; if (compilerVersionMajor >= 18) // 2013 flags.push("/FS"); return flags; } warningLevel: "default" compilerName: "cl.exe" compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: { switch (qbs.architecture) { case "armv7": return "armasm.exe"; case "arm64": return "armasm64.exe"; case "ia64": return "ias.exe"; case "x86": return "ml.exe"; case "x86_64": return "ml64.exe"; } } archiverName: "lib.exe" archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) linkerName: "link.exe" runtimeLibrary: "dynamic" separateDebugInformation: true property bool generateManifestFile: true architecture: qbs.architecture endianness: "little" staticLibrarySuffix: ".lib" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".pdb" objectSuffix: ".obj" precompiledHeaderSuffix: ".pch" imageFormat: "pe" Properties { condition: product.multiplexByQbsProperties.includes("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && qbs.buildVariant !== "release" && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) variantSuffix: "d" } property var buildEnv readonly property bool shouldSignArtifacts: codesign.enableCodeSigning property bool enableCxxLanguageMacro: false setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { var v = new ModUtils.EnvironmentVariable(key, ';'); v.prepend(product.cpp.buildEnv[key]); v.set(); } } property string windowsSdkVersion defineFlag: "/D" includeFlag: "/I" systemIncludeFlag: "/external:I" preincludeFlag: "/FI" libraryPathFlag: "/LIBPATH:" Rule { condition: useCPrecompiledHeader inputs: ["c_pch_src"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("c", true) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "c", true) prepare: MSVC.prepareCompiler.apply(MSVC, arguments) } Rule { condition: useCxxPrecompiledHeader inputs: ["cpp_pch_src"] explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.precompiledHeaderOutputTags("cpp", true) outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "cpp", true) prepare: MSVC.prepareCompiler.apply(MSVC, arguments) } Rule { name: "cpp_compiler" inputs: ["cpp", "cppm", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch"] outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles, /*withCxxModules*/ true) outputArtifacts: Cpp.compilerOutputArtifacts(input, undefined, /*withCxxModules*/ true) prepare: MSVC.prepareCompiler.apply(MSVC, arguments) } FileTagger { patterns: ["*.manifest"] fileTags: ["native.pe.manifest"] } FileTagger { patterns: ["*.def"] fileTags: ["def"] } Rule { name: "applicationLinker" multiplex: true inputs: ['obj', 'res', 'native.pe.manifest', 'def'] inputsFromDependencies: ['staticlibrary', 'objectlibrary', 'dynamiclibrary_import', "debuginfo_app"] outputFileTags: { var tags = ["application", "debuginfo_app"]; if (generateLinkerMapFile) tags.push("mem_map"); if (shouldSignArtifacts) tags.push("codesign.signed_artifact"); return tags; } outputArtifacts: MSVC.appLinkerOutputArtifacts(product) prepare: MSVC.prepareLinker.apply(MSVC, arguments) } Rule { name: "dynamicLibraryLinker" multiplex: true inputs: ['obj', 'res', 'native.pe.manifest', 'def'] inputsFromDependencies: ['staticlibrary', 'objectlibrary', 'dynamiclibrary_import', "debuginfo_dll"] outputFileTags: { var tags = ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"]; if (shouldSignArtifacts) tags.push("codesign.signed_artifact"); return tags; } outputArtifacts: MSVC.dllLinkerOutputArtifacts(product) prepare: MSVC.prepareLinker.apply(MSVC, arguments) } Rule { name: "libtool" multiplex: true inputs: ["obj", "res"] inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] outputFileTags: ["staticlibrary", "debuginfo_cl"] outputArtifacts: MSVC.libtoolOutputArtifacts(product) prepare: MSVC.libtoolCommands.apply(MSVC, arguments) } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.resourceCompilerOutputTags() outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input) prepare: { // From MSVC 2010 on, the logo can be suppressed. var logo = product.cpp.compilerVersionMajor >= 16 ? "can-suppress-logo" : "always-shows-logo"; return MSVC.createRcCommand("rc", input, output, logo); } } FileTagger { patterns: "*.asm" fileTags: ["asm"] } Rule { inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(false) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: MSVC.assemblerCommands.apply(MSVC, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/dmc.qbs0000644000175100017510000001565015232633614020105 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.PathTools import qbs.Probes import qbs.Utilities import "dmc.js" as DMC import "cpp.js" as Cpp CppModule { condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("dmc") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["dmc"] } Probes.DmcProbe { id: dmcProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage _targetPlatform: qbs.targetPlatform _targetArchitecture: qbs.architecture _targetExtender: extenderName } Properties { condition: dmcProbe.found qbs.architecture: dmcProbe.architecture qbs.targetPlatform: dmcProbe.targetPlatform } compilerVersionMajor: dmcProbe.versionMajor compilerVersionMinor: dmcProbe.versionMinor compilerVersionPatch: dmcProbe.versionPatch endianness: "little" compilerDefinesByLanguage: dmcProbe.compilerDefinesByLanguage compilerIncludePaths: dmcProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: "dmc.exe" compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: "dmc.exe" assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: "link.exe" linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) archiverName: "lib.exe" archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) property string rccCompilerName: "rcc.exe" property string rccCompilerPath: FileInfo.joinPaths(toolchainInstallPath, rccCompilerName) property string extenderName PropertyOptions { name: "extenderName" allowedValues: [undefined, "dosz", "dosr", "dosx", "dosp"] description: "Specifies the DOS memory extender to compile with:\n" + " - \"dosz\" is the ZPM 16 bit DOS Extender\n" + " - \"dosr\" is the Rational 16 bit DOS Extender\n" + " - \"dosx\" is the DOSX 32 bit DOS Extender\n" + " - \"dosp\" is the Pharlap 32 bit DOS Extender\n" ; } runtimeLibrary: "dynamic" staticLibrarySuffix: ".lib" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" objectSuffix: ".obj" imageFormat: { if (qbs.targetPlatform === "dos") return "mz"; else if (qbs.targetPlatform === "windows") return "pe"; } defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-I" preincludeFlag: "-HI" libraryPathFlag: "-L/packcode" knownArchitectures: ["x86", "x86_16"] Rule { id: assembler inputs: ["asm"] outputFileTags: DMC.depsOutputTags().concat( Cpp.assemblerOutputTags(generateAssemblerListingFiles)) outputArtifacts: DMC.depsOutputArtifacts(input, product).concat( Cpp.assemblerOutputArtifacts(input)) prepare: DMC.prepareAssembler.apply(DMC, arguments) } FileTagger { patterns: ["*.s", "*.asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: DMC.depsOutputTags().concat( Cpp.compilerOutputTags(generateCompilerListingFiles)) outputArtifacts: DMC.depsOutputArtifacts(input, product).concat( Cpp.compilerOutputArtifacts(input)) prepare: DMC.prepareCompiler.apply(DMC, arguments) } Rule { id: rccCompiler inputs: ["rc"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.resourceCompilerOutputTags() outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input) prepare: DMC.prepareRccCompiler.apply(DMC, arguments) } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { id: applicationLinker multiplex: true inputs: ["obj", "res", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile) outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product) prepare: DMC.prepareLinker.apply(DMC, arguments) } Rule { id: dynamicLibraryLinker multiplex: true inputs: ["obj", "res"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.dynamicLibraryLinkerOutputTags() outputArtifacts: Cpp.dynamicLibraryLinkerOutputArtifacts(product) prepare: DMC.prepareLinker.apply(DMC, arguments) } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: DMC.prepareArchiver.apply(DMC, arguments) } } qbs-src-3.3.1/share/qbs/modules/cpp/sdcc.js0000644000175100017510000005026215232633614020103 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var BinaryFile = require("qbs.BinaryFile"); var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Host = require("qbs.Host"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function toolchainDetails(qbs) { var architecture = qbs.architecture; if (architecture === "mcs51") { return { "assemblerName": "sdas8051", "linkerName": "sdld" } } else if (architecture === "stm8") { return { "assemblerName": "sdasstm8", "linkerName": "sdldstm8" } } else if (architecture === "hcs8") { return { "assemblerName": "sdas6808", "linkerName": "sdld6808" } } } function targetArchitectureFlag(architecture) { if (architecture === "mcs51") return "-mmcs51"; if (architecture === "stm8") return "-mstm8"; if (architecture === "hcs8") return "-mhc08"; } function guessArchitecture(macros) { if (macros["__SDCC_mcs51"] === "1") return "mcs51"; if (macros["__SDCC_stm8"] === "1") return "stm8"; if (macros["__SDCC_hc08"] === "1") return "hcs8"; } function guessEndianness(macros) { // SDCC stores numbers in little-endian format. return "little"; } function guessVersion(macros) { if ("__SDCC_VERSION_MAJOR" in macros && "__SDCC_VERSION_MINOR" in macros && "__SDCC_VERSION_PATCH" in macros) { return { major: parseInt(macros["__SDCC_VERSION_MAJOR"], 10), minor: parseInt(macros["__SDCC_VERSION_MINOR"], 10), patch: parseInt(macros["__SDCC_VERSION_PATCH"], 10) } } else if ("__SDCC" in macros) { var versions = macros["__SDCC"].split("_"); if (versions.length === 3) { return { major: parseInt(versions[0], 10), minor: parseInt(versions[1], 10), patch: parseInt(versions[2], 10) }; } } } function dumpMacros(compilerFilePath, architecture) { var tempDir = new TemporaryDir(); var fakeIn = new TextFile(tempDir.path() + "/empty-source.c", TextFile.WriteOnly); var args = [ fakeIn.filePath(), "-dM", "-E" ]; var targetFlag = targetArchitectureFlag(architecture); if (targetFlag) args.push(targetFlag); var p = new Process(); p.exec(compilerFilePath, args, true); return Cpp.extractMacros(p.readStdOut()); } function dumpDefaultPaths(compilerFilePath, architecture) { var args = [ "--print-search-dirs" ]; var targetFlag = targetArchitectureFlag(architecture); if (targetFlag) args.push(targetFlag); var p = new Process(); p.exec(compilerFilePath, args, true); var includePaths = []; var addIncludePaths = false; var lines = p.readStdOut().trim().split(/\r?\n/g); for (var i in lines) { var line = lines[i]; if (line.startsWith("includedir:")) { addIncludePaths = true; } else if (line.startsWith("programs:") || line.startsWith("datadir:") || line.startsWith("libdir:") || line.startsWith("libpath:")) { addIncludePaths = false; } else if (addIncludePaths) { if (File.exists(line)) includePaths.push(line); } } return { "includePaths": includePaths } } function effectiveLinkerPath(product) { if (product.cpp.linkerMode === "automatic") return product.cpp.compilerPath; return product.cpp.linkerPath; } function useCompilerDriverLinker(product) { var linker = effectiveLinkerPath(product); return linker === product.cpp.compilerPath; } function escapeLinkerFlags(product, linkerFlags) { if (!linkerFlags || linkerFlags.length === 0 || !useCompilerDriverLinker(product)) return linkerFlags; return ["-Wl " + linkerFlags.join(",")]; } function escapePreprocessorFlags(preprocessorFlags) { if (!preprocessorFlags || preprocessorFlags.length === 0) return preprocessorFlags; return ["-Wp " + preprocessorFlags.join(",")]; } // We need to use the asm_adb, asm_src, asm_sym and rst_data // artifacts without of any conditions. Because SDCC always generates // it (and seems, this behavior can not be disabled for SDCC). function extraCompilerOutputTags() { return ["asm_adb", "asm_src", "asm_sym", "rst_data"]; } // We need to use the lk_cmd, and mem_summary artifacts without // of any conditions. Because SDCC always generates // it (and seems, this behavior can not be disabled for SDCC). function extraApplicationLinkerOutputTags() { return ["lk_cmd", "mem_summary"]; } // We need to use the asm_adb, asm_src, asm_sym and rst_data // artifacts without of any conditions. Because SDCC always generates // it (and seems, this behavior can not be disabled for SDCC). function extraCompilerOutputArtifacts(input) { return [{ fileTags: ["asm_adb"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".adb" }, { fileTags: ["asm_src"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".asm" }, { fileTags: ["asm_sym"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".sym" }, { fileTags: ["rst_data"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".rst" }]; } // We need to use the lk_cmd, and mem_summary artifacts without // of any conditions. Because SDCC always generates // it (and seems, this behavior can not be disabled for SDCC). function extraApplicationLinkerOutputArtifacts(product) { return [{ fileTags: ["lk_cmd"], filePath: FileInfo.joinPaths( product.destinationDirectory, product.targetName + ".lk") }, { fileTags: ["mem_summary"], filePath: FileInfo.joinPaths( product.destinationDirectory, product.targetName + ".mem") }]; } function compilerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; var escapablePreprocessorFlags = []; // Input. args.push(input.filePath); // Output. args.push("-c"); args.push("-o", outputs.obj[0].filePath); // Prefix headers. escapablePreprocessorFlags = escapablePreprocessorFlags.concat( Cpp.collectPreincludePathsArguments(input)); // Defines. args = args.concat(Cpp.collectDefinesArguments(input)); // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); escapablePreprocessorFlags = escapablePreprocessorFlags.concat( Cpp.collectSystemIncludePathsArguments(input)); // Target MCU flag. var targetFlag = targetArchitectureFlag(input.cpp.architecture); if (targetFlag) args.push(targetFlag); // Debug information flags. if (input.cpp.debugInformation) args.push("--debug"); // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("--opt-code-size"); break; case "fast": args.push("--opt-code-speed"); break; case "none": // SDCC has not option to disable the optimization. break; } // Warning level flags. var warnings = input.cpp.warningLevel if (warnings === "none") { args.push("--less-pedantic"); escapablePreprocessorFlags.push("-w"); } else if (warnings === "all") { escapablePreprocessorFlags.push("-Wall"); } if (input.cpp.treatWarningsAsErrors) args.push("--Werror"); // Determine which C-language we"re compiling. var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags)); // C language version flags. if (tag === "c") { var knownValues = ["c2x", "c17", "c11", "c99", "c89"]; var cLanguageVersion = Cpp.languageVersion( input.cpp.cLanguageVersion, knownValues, "C"); switch (cLanguageVersion) { case "c17": cLanguageVersion = "c11"; // fall through case "c89": case "c99": case "c11": case "c2x": args.push("--std-" + cLanguageVersion); break; } } var escapedPreprocessorFlags = escapePreprocessorFlags(escapablePreprocessorFlags); if (escapedPreprocessorFlags) Array.prototype.push.apply(args, escapedPreprocessorFlags); // Misc flags. args = args.concat(Cpp.collectMiscCompilerArguments(input, tag), Cpp.collectMiscDriverArguments(input)); return args; } function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) { var args = []; // Includes. args = args.concat(Cpp.collectIncludePathsArguments(input)); args = args.concat(Cpp.collectSystemIncludePathsArguments(input, input.cpp.includeFlag)); // Misc flags. args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); args.push("-ol"); args.push(outputs.obj[0].filePath); args.push(input.filePath); return args; } function linkerFlags(project, product, inputs, outputs) { var args = []; // Target MCU flag. var targetFlag = targetArchitectureFlag(product.cpp.architecture); if (targetFlag) args.push(targetFlag); var escapableLinkerFlags = []; // Map file generation flag. if (product.cpp.generateLinkerMapFile) escapableLinkerFlags.push("-m"); escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectMiscEscapableLinkerArguments(product)); var useCompilerDriver = useCompilerDriverLinker(product); // Output. if (useCompilerDriver) args.push("-o"); args.push(outputs.application[0].filePath); // Inputs. args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); // Library paths. var libraryPathFlag = useCompilerDriver ? "-L" : "-k"; args = args.concat(Cpp.collectLibraryPathsArguments(product, libraryPathFlag)); // Linker scripts. // Note: We need to split the '-f' flag and the file path to separate // lines when we don't use the compiler driver mode. escapableLinkerFlags = escapableLinkerFlags.concat( Cpp.collectLinkerScriptPathsArguments(product, inputs, !useCompilerDriver)); // Library dependencies. args = args.concat(Cpp.collectLibraryDependenciesArguments(product)); var escapedLinkerFlags = escapeLinkerFlags(product, escapableLinkerFlags); if (escapedLinkerFlags) Array.prototype.push.apply(args, escapedLinkerFlags); // Misc flags. if (useCompilerDriver) { args = args.concat(Cpp.collectMiscLinkerArguments(product), Cpp.collectMiscDriverArguments(product)); } return args; } function archiverFlags(project, product, inputs, outputs) { var args = ["-rc"]; Array.prototype.push.apply(args, product.cpp.archiverFlags); args.push(outputs.staticlibrary[0].filePath); args = args.concat(Cpp.collectLinkerObjectPaths(inputs)); return args; } function buildLinkerMapFilePath(target, suffix) { return FileInfo.joinPaths(FileInfo.path(target.filePath), FileInfo.completeBaseName(target.fileName) + suffix); } // This is the workaround for the SDCC bug on a Windows host: // * https://sourceforge.net/p/sdcc/bugs/2970/ // We need to replace the '\r\n\' line endings with the'\n' line // endings for each generated object file. function patchObjectFile(project, product, inputs, outputs, input, output) { var isWindows = Host.os().includes("windows"); if (isWindows && input.cpp.debugInformation) { var cmd = new JavaScriptCommand(); cmd.objectPath = outputs.obj[0].filePath; cmd.silent = true; cmd.sourceCode = function() { var file = new BinaryFile(objectPath, BinaryFile.ReadWrite); var data = file.read(file.size()); file.resize(0); for (var pos = 0; pos < data.length; ++pos) { // Find the next index of CR (\r) symbol. var index = data.indexOf(0x0d, pos); if (index < 0) index = data.length; // Write next data chunk between the previous position and the CR // symbol, exclude the CR symbol. file.write(data.slice(pos, index)); pos = index; } }; return cmd; } } // It is a workaround which removes the generated linker map file // if it is disabled by cpp.generateLinkerMapFile property. // Reason is that the SDCC compiler always generates this file, // and does not have an option to disable generation for a linker // map file. So, we can to remove a listing files only after the // linking completes. function removeLinkerMapFile(project, product, inputs, outputs, input, output) { if (!product.cpp.generateLinkerMapFile) { var target = outputs.application[0]; var cmd = new JavaScriptCommand(); cmd.mapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix) cmd.silent = true; cmd.sourceCode = function() { File.remove(mapFilePath); }; return cmd; } } // It is a workaround to rename the extension of the output linker // map file to the specified one, since the linker generates only // files with the '.map' extension. function renameLinkerMapFile(project, product, inputs, outputs, input, output) { if (product.cpp.generateLinkerMapFile && (product.cpp.linkerMapSuffix !== ".map")) { var target = outputs.application[0]; var cmd = new JavaScriptCommand(); cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix); cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map"); cmd.silent = true; cmd.sourceCode = function() { File.move(oldMapFilePath, newMapFilePath); }; return cmd; } } // It is a workaround which removes the generated listing files // if it is disabled by cpp.generateCompilerListingFiles property // or when the cpp.compilerListingSuffix differs with '.lst'. // Reason is that the SDCC compiler does not have an option to // disable generation for a listing files. Besides, the SDCC // compiler use this files and for the linking. So, we can to // remove a listing files only after the linking completes. function removeCompilerListingFiles(project, product, inputs, outputs, input, output) { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { inputs.obj.forEach(function(object) { if (!object.filePath.endsWith(".c" + object.cpp.objectSuffix)) return; // Skip the assembler generated objects. if (!object.cpp.generateCompilerListingFiles || (object.cpp.compilerListingSuffix !== ".lst")) { var listingPath = FileInfo.joinPaths(FileInfo.path(object.filePath), object.completeBaseName + ".lst"); File.remove(listingPath); } }) }; return cmd; } // It is a workaround that duplicates the generated listing files // but with desired names. The problem is that the SDCC compiler does // not support an options to specify names for the generated listing // files. At the same time, the compiler always generates the listing // files in the form of 'module.c.lst', which makes it impossible to // change the file suffix to a user-specified one. In addition, these // files are also somehow used for linking. Thus, we can not rename them // on the compiling stage. function duplicateCompilerListingFile(project, product, inputs, outputs, input, output) { if (input.cpp.generateCompilerListingFiles && (input.cpp.compilerListingSuffix !== ".lst")) { var cmd = new JavaScriptCommand(); cmd.newListing = outputs.lst[0].filePath; cmd.oldListing = FileInfo.joinPaths(FileInfo.path(outputs.lst[0].filePath), outputs.lst[0].completeBaseName + ".lst"); cmd.silent = true; cmd.sourceCode = function() { File.copy(oldListing, newListing); }; return cmd; } } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmds.push(cmd); cmd = patchObjectFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); cmd = duplicateCompilerListingFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); return cmds; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; cmds.push(cmd); cmd = patchObjectFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); return cmds; } function prepareLinker(project, product, inputs, outputs, input, output) { var cmds = []; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = effectiveLinkerPath(product); var cmd = new Command(linkerPath, args); cmd.description = "linking " + outputs.application[0].fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; cmds.push(cmd); cmd = removeCompilerListingFiles(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); cmd = renameLinkerMapFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); cmd = removeLinkerMapFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); return cmds; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, inputs, outputs); var archiverPath = product.cpp.archiverPath; var cmd = new Command(archiverPath, args); cmd.description = "creating " + output.fileName; cmd.highlight = "linker"; cmd.jobPool = "linker"; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/cpp/MingwBaseModule.qbs0000644000175100017510000001023415232633614022355 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.TextFile import qbs.Utilities import qbs.WindowsUtils import "setuprunenv.js" as SetupRunEnv GenericGCC { condition: false dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".debug" imageFormat: "pe" windowsApiCharacterSet: "unicode" platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) .concat("WIN32") runtimeLibrary: "dynamic" Properties { condition: product.multiplexByQbsProperties.includes("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && qbs.buildVariant !== "release" && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) variantSuffix: "d" } FileTagger { patterns: ["*.manifest"] fileTags: ["native.pe.manifest"] } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["native.pe.manifest"] multiplex: true outputFileTags: ["rc"] outputArtifacts: { if (product.type.containsAny(["application", "dynamiclibrary"])) { return [{ filePath: input.completeBaseName + ".rc", fileTags: ["rc"] }]; } return []; } prepare: { var inputList = inputs["native.pe.manifest"]; // TODO: Emulate manifest merging like Microsoft's mt.exe tool does if (inputList.length !== 1) { throw("The MinGW toolchain does not support manifest merging; " + "you may only specify a single manifest file to embed into your assembly."); } var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.productType = product.type; cmd.inputFilePath = inputList[0].filePath; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { var tf; try { tf = new TextFile(outputFilePath, TextFile.WriteOnly); if (productType.includes("application")) tf.write("1 "); // CREATEPROCESS_MANIFEST_RESOURCE_ID else if (productType.includes("dynamiclibrary")) tf.write("2 "); // ISOLATIONAWARE_MANIFEST_RESOURCE_ID tf.write("24 "); // RT_MANIFEST tf.writeLine(Utilities.cStringQuote(inputFilePath)); } finally { if (tf) tf.close(); } }; return [cmd]; } } } qbs-src-3.3.1/share/qbs/modules/cpp/emcc.qbs0000644000175100017510000000152115232633614020241 0ustar runnerrunnerimport qbs import qbs.ModUtils GenericGCC { condition: qbs.toolchain && qbs.toolchain.includes("emscripten") priority: 100 qbs.targetPlatform: "wasm-emscripten" cCompilerName: "emcc" cxxCompilerName: "em++" archiverName: "emar" dynamicLibrarySuffix: ".so" dynamicLibraryPrefix: "lib" executableSuffix: ".js" rpathOrigin: "irrelevant"//to pass tests imageFormat: "wasm" Depends { name: "emsdk" } emsdk.configuredInstallPath: toolchainInstallPath toolchainInstallPath: emsdk.detectedInstallPath ? emsdk.detectedInstallPath : undefined probeEnv: emsdk.environment setupBuildEnvironment: { for (var key in product.cpp.probeEnv) { var v = new ModUtils.EnvironmentVariable(key); v.value = product.cpp.probeEnv[key]; v.set(); } } } qbs-src-3.3.1/share/qbs/modules/cpp/macos-gcc.qbs0000644000175100017510000000403215232633614021166 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.ModUtils import qbs.Utilities DarwinGCC { priority: 1 condition: qbs.targetOS.includes('macos') && qbs.toolchain && qbs.toolchain.includes('gcc') targetSystem: "macosx" + (minimumMacosVersion || "") minimumDarwinVersion: minimumMacosVersion minimumDarwinVersionCompilerFlag: "-mmacosx-version-min" minimumDarwinVersionLinkerFlag: "-macosx_version_min" libcxxAvailable: base && minimumDarwinVersion && Utilities.versionCompare(minimumDarwinVersion, "10.7") >= 0 } qbs-src-3.3.1/share/qbs/modules/cpp/tvos-gcc.qbs0000644000175100017510000000416415232633614021065 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DarwinGCC { priority: 1 condition: qbs.targetOS.includes('tvos') && qbs.toolchain && qbs.toolchain.includes('gcc') targetSystem: "tvos" + (minimumTvosVersion || "") minimumDarwinVersion: minimumTvosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("tvos-simulator") ? "-mtvos-simulator-version-min" : "-mtvos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("tvos-simulator") ? "-tvos_simulator_version_min" : "-tvos_version_min" } qbs-src-3.3.1/share/qbs/modules/cpp/watcom.qbs0000644000175100017510000001613715232633614020635 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import "cpp.js" as Cpp import "watcom.js" as WATCOM CppModule { condition: qbs.toolchain && qbs.toolchain.includes("watcom") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["owcc"] } Probes.WatcomProbe { id: watcomProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage _pathListSeparator: qbs.pathListSeparator _toolchainInstallPath: toolchainInstallPath _targetPlatform: qbs.targetPlatform _targetArchitecture: qbs.architecture } Properties { condition: watcomProbe.found qbs.architecture: watcomProbe.architecture qbs.targetPlatform: watcomProbe.targetPlatform } compilerVersionMajor: watcomProbe.versionMajor compilerVersionMinor: watcomProbe.versionMinor compilerVersionPatch: watcomProbe.versionPatch endianness: watcomProbe.endianness compilerDefinesByLanguage: watcomProbe.compilerDefinesByLanguage compilerIncludePaths: watcomProbe.includePaths toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: "owcc" + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: "wasm" + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: "wlink" + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) property string disassemblerName: "wdis" + compilerExtension property string disassemblerPath: FileInfo.joinPaths(toolchainInstallPath, disassemblerName) property string resourceCompilerName: "wrc" + compilerExtension property string resourceCompilerPath: FileInfo.joinPaths(toolchainInstallPath, resourceCompilerName) archiverName: "wlib" + compilerExtension archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "dynamic" staticLibrarySuffix: ".lib" dynamicLibrarySuffix: toolchainDetails.dynamicLibrarySuffix executableSuffix: toolchainDetails.executableSuffix objectSuffix: ".obj" imageFormat: toolchainDetails.imageFormat defineFlag: "-D" includeFlag: "-I" systemIncludeFlag: "-I" preincludeFlag: "-include" libraryDependencyFlag: "-l" libraryPathFlag: "-L" linkerScriptFlag: "" toolchainDetails: WATCOM.toolchainDetails(qbs) knownArchitectures: ["x86", "x86_16"] property var buildEnv: watcomProbe.environment setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { var v = new ModUtils.EnvironmentVariable(key, product.qbs.pathListSeparator); v.prepend(product.cpp.buildEnv[key]); v.set(); } } Rule { id: assembler inputs: ["asm"] outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: WATCOM.prepareAssembler.apply(WATCOM, arguments) } FileTagger { patterns: ["*.asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles) outputArtifacts: Cpp.compilerOutputArtifacts(input) prepare: WATCOM.prepareCompiler.apply(WATCOM, arguments) } Rule { id: rccCompiler inputs: ["rc"] auxiliaryInputs: ["hpp"] auxiliaryInputsFromDependencies: ["hpp"] outputFileTags: Cpp.resourceCompilerOutputTags() outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input) prepare: WATCOM.prepareResourceCompiler.apply(WATCOM, arguments) } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { id: applicationLinker multiplex: true inputs: ["obj", "res", "linkerscript"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile) outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product) prepare: WATCOM.prepareLinker.apply(WATCOM, arguments) } Rule { id: dynamicLibraryLinker condition: qbs.targetOS.includes("windows") multiplex: true inputs: ["obj", "res"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.dynamicLibraryLinkerOutputTags(); outputArtifacts: Cpp.dynamicLibraryLinkerOutputArtifacts(product) prepare: WATCOM.prepareLinker.apply(WATCOM, arguments) } Rule { id: libraryManager multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "objectlibrary", "dynamiclibrary_import"] outputFileTags: Cpp.staticLibraryLinkerOutputTags() outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product) prepare: WATCOM.prepareLibraryManager.apply(WATCOM, arguments) } JobLimit { jobPool: "watcom_job_pool" jobCount: 1 } } qbs-src-3.3.1/share/qbs/modules/Android/0000755000175100017510000000000015232633614017422 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Android/android-utils.js0000644000175100017510000000416515232633614022544 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); function availablePlatforms(baseDir) { var re = /^android-([0-9]+)$/; var platforms = File.directoryEntries(FileInfo.joinPaths(baseDir, "platforms"), File.Dirs | File.NoDotAndDotDot); var versions = []; for (var i = 0; i < platforms.length; ++i) { var match = platforms[i].match(re); if (match !== null) { versions.push(platforms[i]); } } versions.sort(function (a, b) { return parseInt(a.match(re)[1], 10) - parseInt(b.match(re)[1], 10); }); return versions; } qbs-src-3.3.1/share/qbs/modules/Android/sdk/0000755000175100017510000000000015232633614020203 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Android/sdk/utils.js0000644000175100017510000006403015232633614021704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var Xml = require("qbs.Xml"); function availableBuildToolsVersions(sdkDir) { var re = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/; var buildTools = File.directoryEntries(FileInfo.joinPaths(sdkDir, "build-tools"), File.Dirs | File.NoDotAndDotDot); var versions = []; for (var i = 0; i < buildTools.length; ++i) { var match = buildTools[i].match(re); if (match !== null) { versions.push(buildTools[i]); } } // Sort by version number versions.sort(function (a, b) { return Utilities.versionCompare(a, b); }); return versions; } function prepareDex(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var dexCompilerFilePath = product.Android.sdk._useD8 ? product.Android.sdk.d8FilePath : product.Android.sdk.dxFilePath; var args = ["--output", FileInfo.path(output.filePath)]; if (product.Android.sdk._useD8) { if (!product.Android.sdk.d8Desugaring) args.push("--no-desugaring"); if (product.Android.sdk.minimumVersion) { args.push("--min-api", product.Android.sdk.minimumVersion); } args.push("--release"); var classes = inputs["java.class"]; if (classes) { args = args.concat(classes.map(function(javaClass) { return FileInfo.relativePath(product.java.classFilesDir, javaClass.filePath) })); } } else { args.unshift("--dex"); args.push(product.java.classFilesDir); } var jarFiles = []; function traverseJarDeps(dep) { if (dep.parameters.Android && dep.parameters.Android.sdk && dep.parameters.Android.sdk.embedJar === false) return; var isJar = typeof dep.artifacts["java.jar"] !== "undefined"; if (!isJar) return; dep.artifacts["java.jar"].forEach(function(artifact) { if (!jarFiles.includes(artifact.filePath)) jarFiles.push(artifact.filePath); }); dep.dependencies.forEach(traverseJarDeps); } product.dependencies.forEach(traverseJarDeps); if (typeof product.artifacts["java.jar"] !== "undefined") { product.artifacts["java.jar"].forEach(function(artifact) { if (!jarFiles.includes(artifact.filePath)) jarFiles.push(artifact.filePath); }); } args = args.concat(jarFiles); var cmd; if (product.Android.sdk._useD8) { cmd = new JavaScriptCommand(); cmd.args = args; cmd.dexCompilerFilePath = dexCompilerFilePath; cmd.description = "creating " + output.fileName; cmd.workingDirectory = product.java.classFilesDir; cmd.extendedDescription = dexCompilerFilePath + " " + args.join(' '); cmd.highlight = "compiler"; cmd.sourceCode = function() { // androiddeployqt copied jar files in product.java.classFilesDir // but the rule only tags one jar file ("QtAndroid.jar"/"Qt6Android.jar") // So to pass all files to d8, Qbs needs to read the directory var bundledJarFilesDir = product.java.classFilesDir; var bundledJarFiles = File.directoryEntries(bundledJarFilesDir, File.Files | File.NoDotAndDotDot); args = args.concat(bundledJarFiles.map(function(jarFile) { return FileInfo.joinPaths(bundledJarFilesDir, jarFile) })); var process = new Process(); var exitCode; process.setWorkingDirectory(workingDirectory); process.exec(dexCompilerFilePath, args, true); try { process.exec(dexCompilerFilePath, args, true); } catch (e) { throw new Error("Error while running dex compiler command: '" + Process.shellQuote(dexCompilerFilePath, args) + "': " + e.toString()); } finally { process.close(); } } } else { cmd = new Command(dexCompilerFilePath, args); cmd.description = "creating " + output.fileName; cmd.workingDirectory = product.java.classFilesDir; } return [cmd]; } function findParentDir(filePath, parentDirName) { var lastDir; var currentDir = FileInfo.path(filePath); while (lastDir !== currentDir) { if (FileInfo.fileName(currentDir) === parentDirName) return currentDir; lastDir = currentDir; currentDir = FileInfo.path(currentDir); } } function commonAaptPackageArgs(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var manifestFilePath = inputs["android.manifest_final"][0].filePath; var args = ["package", "--auto-add-overlay", "-f", "-M", manifestFilePath, "-I", product.Android.sdk.androidJarFilePath]; var resources = inputs["android.resources"]; var resourceDirs = []; if (resources) { for (var i = 0; i < resources.length; ++i) { var resDir = findParentDir(resources[i].filePath, "res"); if (!resDir) { throw "File '" + resources[i].filePath + "' is tagged as an Android resource, " + "but is not located under a directory called 'res'."; } if (!resourceDirs.includes(resDir)) resourceDirs.push(resDir); } } for (i = 0; i < resourceDirs.length; ++i) args.push("-S", resourceDirs[i]); var assets = inputs["android.assets"]; var assetDirs = []; if (assets) { for (i = 0; i < assets.length; ++i) { var assetDir = findParentDir(assets[i].filePath, "assets"); if (!assetDir) { throw "File '" + assets[i].filePath + "' is tagged as an Android asset, " + "but is not located under a directory called 'assets'."; } if (!assetDirs.includes(assetDir)) assetDirs.push(assetDir); } } for (i = 0; i < assetDirs.length; ++i) args.push("-A", assetDirs[i]); if (product.qbs.buildVariant === "debug") args.push("--debug-mode"); return args; } // Rules: from https://developer.android.com/studio/command-line/aapt2 // Input Output // XML resource files, such as Resource table with *.arsc.flat as its extension. // String and Style, which are // located in the res/values/ // directory. // All other resource files. All files other than the files under res/values/ directory are // converted to binary XML files with *.flat extensions. // Additionally all PNG files are crunched by default and adopt // *.png.flat extensions. function generateAapt2ResourceFileName(filePath) { var suffix = FileInfo.suffix(filePath); if (suffix === "xml") { var data = new Xml.DomDocument(); data.load(filePath); var rootElem = data.documentElement(); if (rootElem && rootElem.isElement() && rootElem.tagName() === "resources") // This is a valid XML resource file suffix = "arsc"; // If the xml file is not a "resources" one then it's treated like any other resource file. } var dir = FileInfo.path(filePath); var baseName = FileInfo.completeBaseName(filePath) return FileInfo.fileName(dir) + "_" + baseName + "." + suffix + ".flat"; } function aapt2CompileResourceOutputs(product, inputs) { var outputs = []; var resources = inputs["android.resources"]; for (var i = 0; i < resources.length; ++i) { var filePath = resources[i].filePath; var resourceFileName = generateAapt2ResourceFileName(filePath); var compiledName = FileInfo.joinPaths(product.Android.sdk.compiledResourcesDir, resourceFileName); outputs.push({filePath: compiledName, fileTags: "android.resources_compiled"}); } return outputs; } function prepareAapt2CompileResource(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var resources = inputs["android.resources"]; var compilesResourcesDir = product.Android.sdk.compiledResourcesDir; if (!File.makePath(compilesResourcesDir)) { throw "Cannot create directory '" + FileInfo.toNativeSeparators(compilesResourcesDir) + "'."; } var args = ["compile", FileInfo.toNativeSeparators(input.filePath), "-o", FileInfo.toNativeSeparators(compilesResourcesDir)]; var cmd = new Command(product.Android.sdk.aaptFilePath, args); var outputFileName = generateAapt2ResourceFileName(input.filePath); cmd.description = "compiling resource " + input.fileName + " into " + outputFileName; cmds.push(cmd); return cmds; } function aaptLinkOutputs(product, inputs) { var artifacts = []; artifacts.push({ filePath: product.Android.sdk.apkBaseName + (product.Android.sdk._generateAab ? ".apk_aab" : ".apk_apk"), fileTags: ["android.apk_resources"] }); var resources = inputs["android.resources_compiled"]; if (resources && resources.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "R.java"), fileTags: ["java.java"] }); } for (var rp in product.Android.sdk.extraResourcePackages) { var resourcePackageName = product.Android.sdk.extraResourcePackages[rp]; artifacts.push({ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesBaseDir, resourcePackageName.split('.').join('/'), "R.java"), fileTags: ["java.java"] }); } return artifacts; } function prepareAapt2Link(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var baseOutputFilePath = outputs["android.apk_resources"][0].filePath; var manifestFilePath = inputs["android.manifest_final"][0].filePath; var compilesResourcesDir = product.Android.sdk.compiledResourcesDir; var compiledResources = inputs["android.resources_compiled"]; var args = ["link", "-o", baseOutputFilePath, "-I", product.Android.sdk.androidJarFilePath]; var i = 0; if (compiledResources) { for (i = 0; i < compiledResources.length; ++i) args.push(compiledResources[i].filePath); } args.push("--no-auto-version"); args.push("--auto-add-overlay"); args.push("--manifest", manifestFilePath); args.push("--java", product.Android.sdk.generatedJavaFilesBaseDir); var assets = inputs["android.assets"]; var assetDirs = []; if (assets) { for (i = 0; i < assets.length; ++i) { var assetDir = findParentDir(assets[i].filePath, "assets"); if (!assetDir) { throw "File '" + assets[i].filePath + "' is tagged as an Android asset, " + "but is not located under a directory called 'assets'."; } if (!assetDirs.includes(assetDir)) assetDirs.push(assetDir); } } for (i = 0; i < assetDirs.length; ++i) args.push("-A", assetDirs[i]); if (product.qbs.buildVariant === "debug") args.push("-v"); if (product.Android.sdk._generateAab) args.push("--proto-format"); if (product.Android.sdk.extraResourcePackages) { args.push("--extra-packages"); args.push(product.Android.sdk.extraResourcePackages.join(":")); } var cmd = new Command(product.Android.sdk.aaptFilePath, args); cmd.description = "linking resources"; cmd.workingDirectory = product.buildDirectory; cmds.push(cmd); return cmds; } function aaptGenerateOutputs(product, inputs) { var artifacts = []; var resources = inputs["android.resources"]; if (resources && resources.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "R.java"), fileTags: ["java.java"] }); } return artifacts; } function prepareAaptGenerate(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = commonAaptPackageArgs.apply(this, arguments); args.push("--no-crunch", "-m"); var resources = inputs["android.resources"]; if (resources && resources.length) args.push("-J", ModUtils.moduleProperty(product, "generatedJavaFilesBaseDir")); var cmd = new Command(product.Android.sdk.aaptFilePath, args); cmd.description = "processing resources"; return [cmd]; } function prepareAaptPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var apkOutput = outputs["android.package_unsigned"][0]; var args = commonAaptPackageArgs.apply(this, arguments); args.push("-F", apkOutput.filePath + ".unaligned"); args.push(product.Android.sdk.packageContentsDir); var cmd = new Command(product.Android.sdk.aaptFilePath, args); cmd.description = "generating " + apkOutput.fileName; cmds.push(cmd); cmd = new Command(product.Android.sdk.zipalignFilePath, ["-f", "4", apkOutput.filePath + ".unaligned", apkOutput.filePath]); cmd.silent = true; cmds.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.unalignedApk = apkOutput.filePath + ".unaligned"; cmd.sourceCode = function() { File.remove(unalignedApk); }; cmds.push(cmd); return cmds; } function prepareApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var apkInputFilePath = inputs["android.apk_resources"][0].filePath; var apkOutput = outputs["android.package_unsigned"][0]; var apkOutputFilePathUnaligned = apkOutput.filePath + ".unaligned"; var dexFilePath = inputs["android.dex"][0].filePath; var copyCmd = new JavaScriptCommand(); copyCmd.description = "copying apk"; copyCmd.source = apkInputFilePath; copyCmd.target = apkOutputFilePathUnaligned; copyCmd.sourceCode = function() { File.copy(source, target); } cmds.push(copyCmd); var jarArgs = ["-uvf", apkOutputFilePathUnaligned, "."]; var libPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir); var jarCmd = new Command(product.java.jarFilePath, jarArgs); jarCmd.description = "packaging files"; jarCmd.workingDirectory = libPath; cmds.push(jarCmd); cmd = new Command(product.Android.sdk.zipalignFilePath, ["-f", "4", apkOutputFilePathUnaligned, apkOutput.filePath]); cmd.silent = true; cmds.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.unalignedApk = apkOutputFilePathUnaligned; cmd.sourceCode = function() { File.remove(unalignedApk); }; cmds.push(cmd); return cmds; } function prepareBundletoolPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var baseModuleDir = product.Android.sdk.packageContentsDir; var manifestDirName = FileInfo.joinPaths(baseModuleDir, "manifest"); var pkgBaseFileName = inputs["android.apk_resources"][0].filePath; var jarResourcesArgs = ["xf", pkgBaseFileName]; var jarResourcesCmd = new Command(product.java.jarFilePath, jarResourcesArgs); jarResourcesCmd.description = "extracting resources apk"; jarResourcesCmd.workingDirectory = baseModuleDir; cmds.push(jarResourcesCmd); var moveManifestCmd = new JavaScriptCommand(); moveManifestCmd.description = "moving manifest in manifest directory"; moveManifestCmd.path = manifestDirName; moveManifestCmd.manifestFilePath = baseModuleDir + "/AndroidManifest.xml"; moveManifestCmd.sourceCode = function() { if (!File.exists(path)) File.makePath(path); if (File.exists(manifestFilePath)) File.move(manifestFilePath, path + "/AndroidManifest.xml"); } cmds.push(moveManifestCmd); var baseFilePath = FileInfo.joinPaths(product.buildDirectory, "base.zip"); var jarBaseArgs = ["cfM", baseFilePath, "."]; var jarBaseCmd = new Command(product.java.jarFilePath, jarBaseArgs); jarBaseCmd.description = "compressing base module"; jarBaseCmd.workingDirectory = baseModuleDir; cmds.push(jarBaseCmd); var aabFilePath = outputs["android.package_unsigned"][0].filePath; var removeCmd = new JavaScriptCommand(); removeCmd.description = "removing previous aab"; removeCmd.filePath = aabFilePath; removeCmd.sourceCode = function() { if (File.exists(filePath)) File.remove(filePath); } cmds.push(removeCmd); var bundleConfigFilePath = FileInfo.joinPaths(product.buildDirectory, "BundleConfig.json"); var createBundleConfigCmd = new JavaScriptCommand(); createBundleConfigCmd.description = "create BundleConfig.json"; createBundleConfigCmd.filePath = bundleConfigFilePath; createBundleConfigCmd.sourceCode = function() { var bc = new TextFile(filePath, TextFile.WriteOnly); bc.writeLine('{"optimizations": {'); bc.writeLine('"uncompress_native_libraries": {'); bc.writeLine('"enabled": false'); bc.writeLine('}}}'); } cmds.push(createBundleConfigCmd); var args = ["-jar", product.Android.sdk.bundletoolFilePath, "build-bundle"]; args.push("--modules=" + baseFilePath); args.push("--output=" + aabFilePath); args.push("--config=" + bundleConfigFilePath); var cmd = new Command(product.java.interpreterFilePath, args); cmd.description = "generating " + aabFilePath.fileName; cmds.push(cmd); return cmds; } function stlDeploymentData(product, inputs, type) { var data = { uniqueInputs: [], outputFilePaths: []}; var uniqueFilePaths = []; var theInputs = inputs["android.stl"]; if (!theInputs) return data; for (var i = 0; i < theInputs.length; ++i) { var currentInput = theInputs[i]; if (uniqueFilePaths.includes(currentInput.filePath)) continue; uniqueFilePaths.push(currentInput.filePath); data.uniqueInputs.push(currentInput); var outputFileName = currentInput.fileName; data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", currentInput.Android.ndk.abi, outputFileName)); } return data; } function elementHasBundledAttributes(element) { return element.hasAttribute("android:name") && (element.attribute("android:name") === "android.app.bundled_in_assets_resource_id") || (element.attribute("android:name") === "android.app.bundled_in_lib_resource_id"); } function deployStlOutputs(product, inputs) { var deploymentData = stlDeploymentData(product, inputs, "stl"); var outputs = []; for (var i = 0; i < deploymentData.outputFilePaths.length; ++i) { outputs.push({filePath: deploymentData.outputFilePaths[i], fileTags: "android.stl_deployed"}); } return outputs; } function deployStlCommands(product, inputs) { var cmds = []; var deploymentData = stlDeploymentData(product, inputs); for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) { var input = deploymentData.uniqueInputs[i]; var stripArgs = ["--strip-all", "-o", deploymentData.outputFilePaths[i], input.filePath]; var cmd = new Command(input.cpp.stripPath, stripArgs); cmd.description = "deploying " + input.fileName; cmds.push(cmd); } return cmds; } function generateBuildConfigJavaCommands(product, output) { var cmd = new JavaScriptCommand(); cmd.description = "generating BuildConfig.java"; cmd.sourceCode = function() { var debugValue = product.qbs.buildVariant === "debug" ? "true" : "false"; var ofile = new TextFile(output.filePath, TextFile.WriteOnly); ofile.writeLine("package " + product.Android.sdk.packageName + ";") ofile.writeLine("public final class BuildConfig {"); ofile.writeLine(" public final static boolean DEBUG = " + debugValue + ";"); ofile.writeLine("}"); ofile.close(); }; return [cmd]; } function generateProcessedManifestCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "ensuring correct package name in Android manifest file"; cmd.sourceCode = function() { var manifestData = new Xml.DomDocument(); manifestData.load(input.filePath); var rootElem = manifestData.documentElement(); if (!rootElem || !rootElem.isElement() || rootElem.tagName() !== "manifest") throw "No manifest tag found in '" + input.filePath + "'."; // Quick sanity check. Don't try to be fancy; let's not risk rejecting valid names. var packageName = product.Android.sdk.packageName; if (!packageName.match(/^[^.]+(?:\.[^.]+)+$/)) { throw "Package name '" + packageName + "' is not valid. Please set " + "Android.sdk.packageName to a name following the " + "'com.mycompany.myproduct' pattern." } rootElem.setAttribute("package", packageName); if (product.Android.sdk.versionCode !== undefined) rootElem.setAttribute("android:versionCode", product.Android.sdk.versionCode); if (product.Android.sdk.versionName !== undefined) rootElem.setAttribute("android:versionName", product.Android.sdk.versionName); if (product.Android.sdk._bundledInAssets) { // Remove // custom AndroidManifest.xml because assets are in rcc files for qt >= 5.14 var appElem = rootElem.firstChild("application"); if (!appElem || !appElem.isElement() || appElem.tagName() !== "application") throw "No application tag found in '" + input.filePath + "'."; var activityElem = appElem.firstChild("activity"); if (!activityElem || !activityElem.isElement() || activityElem.tagName() !== "activity") throw "No activity tag found in '" + input.filePath + "'."; var metaDataElem = activityElem.firstChild("meta-data"); while (metaDataElem && metaDataElem.isElement()) { if (elementHasBundledAttributes(metaDataElem)) { var elemToRemove = metaDataElem; metaDataElem = metaDataElem.nextSibling("meta-data"); activityElem.removeChild(elemToRemove); } else { metaDataElem = metaDataElem.nextSibling("meta-data"); } } } var usedSdkElem = rootElem.firstChild("uses-sdk"); if (!usedSdkElem || !usedSdkElem.isElement()) { usedSdkElem = manifestData.createElement("uses-sdk"); rootElem.appendChild(usedSdkElem); } else { if (!usedSdkElem.isElement()) throw "Tag uses-sdk is not an element in '" + input.filePath + "'."; } usedSdkElem.setAttribute("android:minSdkVersion", product.Android.sdk.minimumVersion); usedSdkElem.setAttribute("android:targetSdkVersion", product.Android.sdk.targetVersion); rootElem.appendChild(usedSdkElem); manifestData.save(output.filePath, 4); } return cmd; } function processAidlCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var aidl = product.Android.sdk.aidlFilePath; var args = ["-p" + product.Android.sdk.frameworkAidlFilePath]; var aidlSearchPaths = input.Android.sdk.aidlSearchPaths; for (var i = 0; i < (aidlSearchPaths ? aidlSearchPaths.length : 0); ++i) args.push("-I" + aidlSearchPaths[i]); args.push(input.filePath, output.filePath); var cmd = new Command(aidl, args); cmd.description = "processing " + input.fileName; return [cmd]; } qbs-src-3.3.1/share/qbs/modules/Android/sdk/sdk.qbs0000644000175100017510000004061015232633614021474 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.TextFile import qbs.Utilities import qbs.Xml import "utils.js" as SdkUtils Module { Probes.AndroidSdkProbe { id: sdkProbe environmentPaths: (sdkDir ? [sdkDir] : []).concat(base) } Probes.AndroidNdkProbe { id: ndkProbe sdkPath: sdkProbe.path environmentPaths: (ndkDir ? [ndkDir] : []).concat(base) } Probes.PathProbe { id: bundletoolProbe platformSearchPaths: [sdkDir] names: ["bundletool-all"] nameSuffixes: ["-0.11.0.jar", "-0.12.0.jar", "-0.13.0.jar", "-0.13.3.jar", "-0.13.4.jar", "-0.14.0.jar", "-0.15.0.jar", "-1.0.0.jar", "-1.1.0.jar", "-1.2.0.jar", "-1.3.0.jar", "-1.4.0.jar", "-1.5.0.jar", "-1.6.0.jar", "-1.6.1.jar", "-1.7.0.jar", "-1.7.1.jar", "-1.8.0.jar"] } property path sdkDir: sdkProbe.path property path ndkDir: ndkProbe.path property path ndkSamplesDir: ndkProbe.samplesDir property string buildToolsVersion: sdkProbe.buildToolsVersion property var buildToolsVersionParts: buildToolsVersion ? buildToolsVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int buildToolsVersionMajor: buildToolsVersionParts[0] property int buildToolsVersionMinor: buildToolsVersionParts[1] property int buildToolsVersionPatch: buildToolsVersionParts[2] property string platform: sdkProbe.platform property string minimumVersion: "21" property string targetVersion: platformVersion.toString() property path bundletoolFilePath: bundletoolProbe.filePath // Product-specific properties and files property string packageName: { var idx = product.name.indexOf(".") if (idx > 0 && idx < product.name.length) return product.name; return "com.example." + product.name; } property int versionCode property string versionName property string apkBaseName: packageName property bool automaticSources: true property bool legacyLayout: false property path sourceSetDir: legacyLayout ? product.sourceDirectory : FileInfo.joinPaths(product.sourceDirectory, "src/main") property path resourcesDir: FileInfo.joinPaths(sourceSetDir, "res") property path assetsDir: FileInfo.joinPaths(sourceSetDir, "assets") property path sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java") property string manifestFile: defaultManifestFile readonly property string defaultManifestFile: FileInfo.joinPaths(sourceSetDir, "AndroidManifest.xml") property bool customManifestProcessing: false property bool _enableRules: !product.multiplexConfigurationId && !!packageName property bool _bundledInAssets: true // Internal properties. property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property string platformJavaVersion: { if (platformVersion >= 21) return "1.7"; return "1.5"; } property path buildToolsDir: FileInfo.joinPaths(sdkDir, "build-tools", buildToolsVersion) property string aaptName: "aapt2" PropertyOptions { name: "aaptName" allowedValues: ["aapt", "aapt2"] } property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, aaptName) readonly property bool _enableAapt2: aaptName === "aapt2" property string packageType: "apk" PropertyOptions { name: "packageType" allowedValues: ["apk", "aab"] } readonly property bool _generateAab: packageType == "aab" property stringList extraResourcePackages PropertyOptions { name: "extraResourcePackages" description: "extra resource packages to compile resources for" } property path apksignerFilePath: FileInfo.joinPaths(buildToolsDir, "apksigner") property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl") property path dxFilePath: FileInfo.joinPaths(buildToolsDir, "dx") property path d8FilePath: FileInfo.joinPaths(buildToolsDir, "d8") property string dexCompilerName: "d8" PropertyOptions { name: "dexCompilerName" allowedValues: ["dx", "d8"] } readonly property bool _useD8: dexCompilerName === "d8" property bool d8Desugaring: false PropertyOptions { name: "d8Desugaring" description: "enable desugaring in d8 dex compiler" } property path zipalignFilePath: FileInfo.joinPaths(buildToolsDir, "zipalign") property path androidJarFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "android.jar") property path frameworkAidlFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "framework.aidl") property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen") property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir, (packageName || "").split('.').join('/')) property path compiledResourcesDir: FileInfo.joinPaths(product.buildDirectory, "compiled_resources") property string packageContentsDir: FileInfo.joinPaths(product.buildDirectory, packageType) property stringList aidlSearchPaths Group { condition: automaticSources Group { name: "java sources" prefix: FileInfo.resolvePath(product.sourceDirectory, module.sourcesDir + '/') files: "**/*.java" } Group { name: "android resources" fileTags: ["android.resources"] prefix: FileInfo.resolvePath(product.sourceDirectory, module.resourcesDir + '/') files: "**/*" } Group { name: "android assets" fileTags: ["android.assets"] prefix: FileInfo.resolvePath(product.sourceDirectory, module.assetsDir + '/') files: "**/*" } Group { name: "manifest" fileTags: ["android.manifest"] files: module.manifestFile && module.manifestFile !== module.defaultManifestFile ? [module.manifestFile] : (File.exists(module.defaultManifestFile) ? [module.defaultManifestFile] : []) } } Group { condition: !customManifestProcessing fileTagsFilter: "android.manifest_processed" fileTags: "android.manifest_final" } Group { condition: _enableRules Depends { name: "java" } Depends { name: "codesign" } product.java.languageVersion: platformJavaVersion product.java.runtimeVersion: platformJavaVersion product.java.bootClassPaths: androidJarFilePath product.codesign.apksignerFilePath: apksignerFilePath product.codesign._packageName: apkBaseName + (_generateAab ? ".aab" : ".apk") product.codesign.useApksigner: !_generateAab Rule { inputs: ["android.aidl"] Artifact { filePath: FileInfo.joinPaths(Utilities.getHash(input.filePath), input.completeBaseName + ".java") fileTags: ["java.java"] } prepare: SdkUtils.processAidlCommands.apply(SdkUtils, arguments) } Rule { inputs: "android.manifest" Artifact { filePath: FileInfo.joinPaths("processed_manifest", input.fileName) fileTags: "android.manifest_processed" } prepare: SdkUtils.generateProcessedManifestCommands.apply(SdkUtils, arguments) } Rule { multiplex: true Artifact { filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "BuildConfig.java") fileTags: ["java.java"] } prepare: SdkUtils.generateBuildConfigJavaCommands(product, output) } Rule { multiplex: true inputs: ["java.class"] inputsFromDependencies: ["java.jar", "bundled_jar"] Artifact { filePath: product.Android.sdk._generateAab ? FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "dex", "classes.dex") : FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "classes.dex") fileTags: ["android.dex"] } prepare: SdkUtils.prepareDex.apply(SdkUtils, arguments) } Rule { property stringList inputTags: "android.nativelibrary" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { filePath: FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", input.Android.ndk.abi, product.Android.sdk._archInName ? input.baseName + "_" + input.Android.ndk.abi + ".so" : input.fileName) fileTags: "android.nativelibrary_deployed" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName + " for packaging"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { multiplex: true property stringList inputTags: "android.stl" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags outputFileTags: "android.stl_deployed" outputArtifacts: SdkUtils.deployStlOutputs(product, inputs) prepare: SdkUtils.deployStlCommands(product, inputs) } Group { condition: module._enableAapt2 Rule { inputs: ["android.resources"] outputFileTags: ["android.resources_compiled"] outputArtifacts: SdkUtils.aapt2CompileResourceOutputs(product, inputs) prepare: SdkUtils.prepareAapt2CompileResource.apply(SdkUtils, arguments) } Rule { multiplex: true inputs: ["android.resources_compiled", "android.assets", "android.manifest_final"] outputFileTags: ["java.java", "android.apk_resources"] outputArtifacts: SdkUtils.aaptLinkOutputs(product, inputs) prepare: SdkUtils.prepareAapt2Link.apply(SdkUtils, arguments) } Rule { condition: module._generateAab multiplex: true inputs: [ "android.apk_resources", "android.manifest_final", "android.dex", "android.stl_deployed", "android.nativelibrary_deployed" ] Artifact { filePath: product.Android.sdk.apkBaseName + ".aab_unsigned" fileTags: "android.package_unsigned" } prepare: SdkUtils.prepareBundletoolPackage.apply(SdkUtils, arguments) } Rule { condition: !module._generateAab multiplex: true inputs: [ "android.apk_resources", "android.manifest_final", "android.dex", "android.stl_deployed", "android.nativelibrary_deployed" ] Artifact { filePath: product.Android.sdk.apkBaseName + ".apk_unsigned" fileTags: "android.package_unsigned" } prepare: SdkUtils.prepareApkPackage.apply(SdkUtils, arguments) } } Group { condition: !module._enableAapt2 Rule { multiplex: true inputs: ["android.resources", "android.assets", "android.manifest_final"] outputFileTags: ["java.java"] outputArtifacts: SdkUtils.aaptGenerateOutputs(product, inputs) prepare: SdkUtils.prepareAaptGenerate.apply(SdkUtils, arguments) } Rule { condition: !module._generateAab multiplex: true inputs: [ "android.resources", "android.assets", "android.manifest_final", "android.dex", "android.stl_deployed", "android.nativelibrary_deployed" ] Artifact { filePath: product.Android.sdk.apkBaseName + ".apk_unsigned" fileTags: "android.package_unsigned" } prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments) } } } validate: { if (!sdkDir) { throw ModUtils.ModuleError("Could not find an Android SDK at any of the following " + "locations:\n\t" + sdkProbe.candidatePaths.join("\n\t") + "\nInstall the Android SDK to one of the above locations, " + "or set the Android.sdk.sdkDir property or " + "ANDROID_HOME environment variable to a valid " + "Android SDK location."); } if (!bundletoolFilePath && _generateAab) { throw ModUtils.ModuleError("Could not find Android bundletool at the following " + "location:\n\t" + Android.sdk.sdkDir + "\nInstall the Android bundletool to the above location, " + "or set the Android.sdk.bundletoolFilePath property.\n" + "Android bundletool can be downloaded from " + "https://github.com/google/bundletool"); } if (Utilities.versionCompare(buildToolsVersion, "24.0.3") < 0) { throw ModUtils.ModuleError("Version of Android SDK build tools too old. This version " + "is " + buildToolsVersion + " and minimum version is " + "24.0.3. Please update the Android SDK.") } } FileTagger { patterns: ["AndroidManifest.xml"] fileTags: ["android.manifest"] } FileTagger { patterns: ["*.aidl"] fileTags: ["android.aidl"] } Parameter { property bool embedJar: true } } qbs-src-3.3.1/share/qbs/modules/Android/ndk/0000755000175100017510000000000015232633614020176 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/modules/Android/ndk/utils.js0000644000175100017510000000646315232633614021705 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Utilities = require("qbs.Utilities") function abiNameToDirName(abiName) { switch (abiName) { case "armeabi": case "armeabi-v7a": return "arm"; case "arm64-v8a": return "arm64"; default: return abiName; } } function androidAbi(arch) { switch (arch) { case "arm64": return "arm64-v8a"; case "armv5": case "armv5te": return "armeabi"; case "armv7": case "armv7a": return "armeabi-v7a"; default: return arch; } } function commonCompilerFlags(toolchain, buildVariant, ndk) { var flags = ["-Werror=format-security"]; var abi = ndk.abi; var armMode = ndk.armMode; if (abi === "arm64-v8a") flags.push("-fpic"); if (abi === "armeabi" || abi === "armeabi-v7a") { flags.push("-fpic"); if (abi === "armeabi") flags.push("-mtune=xscale", "-msoft-float"); if (abi === "armeabi-v7a") { flags.push("-mfpu=vfpv3-d16"); flags.push("-mfloat-abi=softfp"); } } if (abi === "x86" || abi === "x86_64") flags.push("-fPIC"); flags.push("-fno-limit-debug-info"); if (armMode) flags.push("-m" + armMode); // https://github.com/android-ndk/ndk/issues/884 is fixed in r21 if (ndk.version < 21) flags.push("-fno-addrsig"); // https://github.com/android/ndk/issues/635 is fixed in api 24 if (abi === "x86" && ndk.platformVersion < 24) flags.push("-mstackrealign"); return flags; } function commonLinkerFlags(ndk) { var buildId = (ndk.buildId) ? "--build-id=" + ndk.buildId : "--build-id"; return ["-z", "noexecstack", "-z", "relro", "-z", "now", buildId, "--gc-sections"]; } function stlFileName(prefix, ndk, suffix) { return prefix + ndk.appStl.slice(0, ndk.appStl.indexOf('_')) + suffix; } qbs-src-3.3.1/share/qbs/modules/Android/ndk/ndk.qbs0000644000175100017510000001322015232633614021457 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Utilities import "utils.js" as NdkUtils Module { Probes.AndroidNdkProbe { id: ndkProbe environmentPaths: (ndkDir ? [ndkDir] : []).concat(base) } version: ndkProbe.ndkVersion readonly property string abi: NdkUtils.androidAbi(qbs.architecture) PropertyOptions { name: "abi" description: "Supported Android ABIs" allowedValues: ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"] } // From https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md // Android Studio‘s LLDB debugger uses a binary’s build ID to locate debug information. To // ensure that LLDB works with a binary, pass an option like -Wl,--build-id=sha1 to Clang when // linking. Other --build-id= modes are OK, but avoid a plain --build-id argument when using // LLD, because Android Studio‘s version of LLDB doesn’t recognize LLD's default 8-byte build // ID. See Issue 885. // Plain --build-id option is nevertheless implemented when buildId property is empty. // Possible values (from man page of ld.lld — ELF linker from the LLVM project): // one of fast, md5, sha1, tree, uuid, 0xhex-string, and none. tree is an alias for sha1. // Build-IDs of type fast, md5, sha1, and tree are calculated from the object contents. fast is // not intended to be cryptographically secure. property string buildId: "sha1" // See https://developer.android.com/ndk/guides/cpp-support.html property string appStl: "c++_shared" PropertyOptions { name: "appStl" description: "C++ Runtime Libraries." allowedValues: ["c++_static", "c++_shared"] } property string hostArch: ndkProbe.hostArch property string ndkDir: ndkProbe.path property string ndkSamplesDir: ndkProbe.samplesDir property string platform: { switch (abi) { case "armeabi-v7a": // case "x86": // x86 has broken wstring support return "android-19"; default: return "android-21"; } } property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property stringList abis: { var list = ["armeabi-v7a"]; if (platformVersion >= 16) list.push("x86"); if (platformVersion >= 21) list.push("arm64-v8a", "x86_64"); return list; } property string armMode: abi && abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; PropertyOptions { name: "armMode" description: "Determines the instruction set for armeabi configurations." allowedValues: ["arm", "thumb"] } validate: { if (!ndkDir) { throw ModUtils.ModuleError("Could not find an Android NDK at any of the following " + "locations:\n\t" + ndkProbe.candidatePaths.join("\n\t") + "\nInstall the Android NDK to one of the above locations, " + "or set the Android.ndk.ndkDir property or " + "ANDROID_NDK_ROOT environment variable to a valid " + "Android NDK location."); } if (Utilities.versionCompare(version, "19") < 0) throw ModUtils.ModuleError("Unsupported NDK version " + Android.ndk.version + ", please upgrade your NDK to r19+"); if (product.aggregate && !product.multiplexConfigurationId) return; var validator = new ModUtils.PropertyValidator("Android.ndk"); validator.setRequiredProperty("abi", abi); validator.setRequiredProperty("appStl", appStl); validator.setRequiredProperty("hostArch", hostArch); validator.setRequiredProperty("platform", platform); return validator.validate(); } } qbs-src-3.3.1/share/qbs/imports/0000755000175100017510000000000015232633614016067 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/0000755000175100017510000000000015232633614016654 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/WindowsUtils/0000755000175100017510000000000015232633614021327 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/WindowsUtils/windows-utils.js0000644000175100017510000000662415232633614024525 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function winapiFamilyDefine(name) { return { "desktop": "DESKTOP_APP", "phone": "PHONE_APP", "pc": "PC_APP", "server": "SERVER", "system": "SYSTEM" }[name]; } function winapiPartitionDefine(name) { return { "app": "APP", "desktop": "DESKTOP", "phone": "PHONE_APP", "pc": "PC_APP", "server": "SERVER", "system": "SYSTEM" }[name]; } function characterSetDefines(charset) { var defines = []; if (charset === "unicode") defines.push("UNICODE", "_UNICODE"); else if (charset === "mbcs") defines.push("_MBCS"); return defines; } function canonicalizeVersion(version) { switch (version) { case "7": return "6.1"; case "8": return "6.2"; case "8.1": return "6.3"; default: return version; } } function knownWindowsVersions() { // Add new Windows versions to this list when they are released return ['10.0', '6.3', '6.2', '6.1', '6.0', '5.2', '5.1', '5.0', '4.0']; } function isValidWindowsVersion(systemVersion) { var realVersions = knownWindowsVersions(); for (i in realVersions) if (systemVersion === realVersions[i]) return true; return false; } function getWindowsVersionInFormat(systemVersion, format) { if (!systemVersion) return undefined; var major = parseInt(systemVersion.split('.')[0], 10); var minor = parseInt(systemVersion.split('.')[1], 10); switch (format) { case "hex": // https://msdn.microsoft.com/en-us/library/6sehtctf.aspx return "0x" + ("0000" + ((major << 8) | minor).toString(16)).slice(-4); case "subsystem": // https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx return major + '.' + (minor < 10 ? '0' : '') + minor; default: throw ("Unrecognized Windows version format " + format + ". Must be in {hex, subsystem}."); } } qbs-src-3.3.1/share/qbs/imports/qbs/base/0000755000175100017510000000000015232633614017566 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/base/QtPlugin.qbs0000644000175100017510000000324315232633614022042 0ustar runnerrunnerimport qbs.FileInfo import qbs.TextFile QtModule { isPlugin: true property string className property stringList extendsModules enableLinking: { if (!base) return false; if (!isStaticLibrary) return false; if (!Qt.plugin_support.linkPlugins) return false; if (!(Qt.plugin_support.enabledPlugins || []).contains(qtModuleName)) return false; if (!extendsModules || extendsModules.length === 0) return true; for (var i = 0; i < extendsModules.length; ++i) { var moduleName = extendsModules[i]; if (product.Qt[moduleName] && product.Qt[moduleName].present) return true; } return false; } Rule { condition: enableLinking multiplex: true Artifact { filePath: product.targetName + "_qt_plugin_import_" + product.moduleProperty(product.moduleName, "qtModuleName") + ".cpp" fileTags: ["cpp", "qt.untranslatable"] } prepare: { var cmd = new JavaScriptCommand(); var pluginName = product.moduleProperty(product.moduleName, "qtModuleName"); cmd.description = "creating static import for plugin '" + pluginName + "'"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); var className = product.moduleProperty(product.moduleName, "className"); f.writeLine("#include \n\nQ_IMPORT_PLUGIN(" + className + ")"); f.close(); }; return cmd; } } } qbs-src-3.3.1/share/qbs/imports/qbs/base/QtGuiApplication.qbs0000644000175100017510000000303015232633614023506 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ QtApplication { Depends { name: "Qt.gui" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/InnoSetup.qbs0000644000175100017510000000326415232633614022226 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { condition: qbs.targetOS.contains("windows") && innosetup.present Depends { name: "innosetup"; condition: qbs.targetOS.contains("windows"); required: false } type: ["innosetup.exe"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/WindowsSetupPackage.qbs0000644000175100017510000000312315232633614024223 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["wixsetup"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/NativeBinary.qbs0000644000175100017510000000571615232633614022701 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { property bool isForAndroid: qbs.targetOS.contains("android") property bool isForDarwin: qbs.targetOS.contains("darwin") property bool isBundle: isForDarwin && bundle.isBundle property bool install: !isForAndroid property string installDir // Product artifacts should be installed if it's not multiplexed or aggregated, // or if it is multiplexed and it's the aggregate product readonly property bool _installable: type && !type.includes("objectlibrary") && (!multiplexed || !aggregate || !multiplexConfigurationId) property bool installDebugInformation: install property string debugInformationInstallDir: installDir Depends { name: "bundle"; condition: isForDarwin } aggregate: { if (!isForDarwin) return false; var multiplexProps = multiplexByQbsProperties; if (!multiplexProps) return false; if (multiplexProps.contains("architectures")) { var archs = qbs.architectures; if (archs && archs.length > 1) return true; } if (multiplexProps.contains("buildVariants")) { var variants = qbs.buildVariants; return variants && variants.length > 1; } return false; } multiplexByQbsProperties: { if (isForDarwin) return ["profiles", "architectures", "buildVariants"]; if (isForAndroid) return ["architectures"] return ["profiles"]; } } qbs-src-3.3.1/share/qbs/imports/qbs/base/JavaClassCollection.qbs0000644000175100017510000000305115232633614024157 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.class"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/CppApplication.qbs0000644000175100017510000000305515232633614023206 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Application { Depends { name: "cpp" } usesNativeCode: true } qbs-src-3.3.1/share/qbs/imports/qbs/base/LoadableModule.qbs0000644000175100017510000000305415232633614023150 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DynamicLibrary { type: isForDarwin ? ["loadablemodule"] : base } qbs-src-3.3.1/share/qbs/imports/qbs/base/CppLibrary.qbs0000644000175100017510000000175515232633614022354 0ustar runnerrunnerLibrary { property stringList publicHeaders property stringList privateHeaders property string headersDirectoryName: targetName property string publicHeadersDirectory: installpaths.headers + "/" + headersDirectoryName property string privateHeadersDirectory: installpaths.headers + "/" + headersDirectoryName + "/private" Depends { name: "cpp" } Depends { name: "installpaths" } Group { name: "Public Headers" files: publicHeaders fileTags: ["bundle.input.public_hpp", "hpp"] prefix: product.sourceDirectory + "/" qbs.install: install && !(isForDarwin && bundle.isBundle) qbs.installDir: publicHeadersDirectory } Group { name: "Private Headers" files: privateHeaders fileTags: ["bundle.input.private_hpp", "hpp"] prefix: product.sourceDirectory + "/" qbs.install: install && !(isForDarwin && bundle.isBundle) qbs.installDir: privateHeadersDirectory } } qbs-src-3.3.1/share/qbs/imports/qbs/base/NSISSetup.qbs0000644000175100017510000000312515232633614022073 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nsis"; condition: qbs.targetOS.contains("windows") } type: ["nsissetup"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/ObjectLibrary.qbs0000644000175100017510000000314315232633614023031 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppLibrary { type: "objectlibrary" Group { fileTagsFilter: "obj" fileTags: "objectlibrary" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/StaticLibrary.qbs0000644000175100017510000000302215232633614023046 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppLibrary { type: ["staticlibrary"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/QtLupdateRunner.qbs0000644000175100017510000001435215232633614023377 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.TextFile import qbs.Utilities Product { condition: Utilities.versionCompare(Qt.core.version, "5.13") >= 0 name: "lupdate-runner" type: "lupdate-result" builtByDefault: false property bool limitToSubProject: true property stringList extraArguments Depends { name: "Qt.core" } Depends { productTypes: "qm"; minimal: true; limitToSubProject: product.limitToSubProject } Rule { multiplex: true auxiliaryInputsFromDependencies: ["cpp", "objcpp", "qt.qml.qml", "qt.qml.js", "ui"] excludedInputs: "qt.untranslatable" Artifact { filePath: "lupdate.json" fileTags: "lupdate_json" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating lupdate project file"; cmd.highlight = "filegen"; cmd.sourceCode = function() { /* * From the original commit message in qttools: * Project ::= { * string projectFile // Name of the project file. * string codec // Source code codec. Valid values are * // currently "utf-16" or "utf-8" (default). * string[] translations // List of .ts files of the project. * string[] includePaths // List of include paths. * string[] sources // List of source files. * string[] excluded // List of source files, which are * // excluded for translation. * Project[] subProjects // List of sub-projects. * } */ var mainProject = { projectFile: "main", sources: [], translations: [], subProjects: [] }; var cxxArtifactsByIncludePaths = {}; function handleProduct(product) { (product.artifacts["ts"] || []).forEach(function(artifact) { mainProject.translations.push(artifact.filePath); }); ["qt.qml.qml", "qt.qml.js", "ui"].forEach(function(tag) { (product.artifacts[tag] || []).forEach(function(artifact) { mainProject.sources.push(artifact.filePath); }); }); ["cpp", "objcpp"].forEach(function(tag) { (product.artifacts[tag] || []).forEach(function(artifact) { if (!artifact.cpp || artifact.fileTags.contains("qt.untranslatable")) return; var key = (artifact.cpp.includePaths || []).join(""); var current = cxxArtifactsByIncludePaths[key] || []; current.push(artifact); cxxArtifactsByIncludePaths[key] = current; }); }); }; product.dependencies.forEach(function(dep) { if (!dep.present) handleProduct(dep); }); var cxxProductNr = 0; for (key in cxxArtifactsByIncludePaths) { var artifactList = cxxArtifactsByIncludePaths[key]; var cxxProject = { projectFile: "cxx " + ++cxxProductNr, includePaths: artifactList[0].cpp.includePaths, sources: [] }; artifactList.forEach(function(artifact) { cxxProject.sources.push(artifact.filePath); }); mainProject.subProjects.push(cxxProject); } (new TextFile(output.filePath, TextFile.WriteOnly)).write( JSON.stringify(mainProject)); } return cmd; } } // This is a pure action target that intentionally does not do any change tracking. // It is implemented this way because it writes source files and therefore needs to be able // to overwrite user edits (e.g. accidental removal of a source string). Rule { inputs: "lupdate_json" outputFileTags: "lupdate-result" prepare: { var tool = product.Qt.core.binPath + '/' + product.Qt.core.lupdateName; var args = ["-project", inputs.lupdate_json[0].filePath] .concat(product.extraArguments || []); var cmd = new Command(tool, args); cmd.description = "updating translation files"; return cmd; } } } qbs-src-3.3.1/share/qbs/imports/qbs/base/QtApplication.qbs0000644000175100017510000000303215232633614023043 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppApplication { Depends { name: "Qt.core" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/ConfigBuild.qbs0000644000175100017510000000045315232633614022464 0ustar runnerrunnerModule { property string libraryType: "dynamic" PropertyOptions { name: "libraryType" allowedValues: ["static", "dynamic"] } property string pluginType: libraryType PropertyOptions { name: "pluginType" allowedValues: ["static", "dynamic"] } } qbs-src-3.3.1/share/qbs/imports/qbs/base/AndroidApk.qbs0000644000175100017510000000317415232633614022316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo Product { type: ["android.package"] qbs.targetPlatform: "android" Depends { name: "Android.sdk" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/ConfigInstall.qbs0000644000175100017510000000174515232633614023040 0ustar runnerrunnerModule { Depends { name: "installpaths" } property bool install: true property string binariesDirectory: installpaths.bin property string applicationsDirectory: installpaths.applications property bool dynamicLibraries: install property string dynamicLibrariesDirectory: qbs.targetOS.contains("windows") ? installpaths.bin : installpaths.lib property bool staticLibraries: false property string staticLibrariesDirectory: installpaths.lib property bool frameworks: install property string frameworksDirectory: installpaths.frameworks property bool importLibraries: false property string importLibrariesDirectory: installpaths.lib property bool plugins: install property string pluginsDirectory: installpaths.plugins property bool loadableModules: install property string loadableModulesDirectory: installpaths.loadableModules property bool debugInformation: install property string debugInformationDirectory } qbs-src-3.3.1/share/qbs/imports/qbs/base/DynamicLibrary.qbs0000644000175100017510000000311115232633614023202 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppLibrary { type: ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []) } qbs-src-3.3.1/share/qbs/imports/qbs/base/ApplicationExtension.qbs0000644000175100017510000000550015232633614024435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ XPCService { Depends { name: "xcode" } type: base.concat(["applicationextension"]) property bool _useLegacyExtensionLibraries: qbs.targetOS.contains("macos") && xcode.present && parseInt(xcode.sdkVersion.split(".")[1], 10) < 11 || qbs.targetOS.contains("ios") && xcode.present && parseInt(xcode.sdkVersion.split(".")[0], 10) < 9 cpp.entryPoint: "_NSExtensionMain" cpp.frameworkPaths: base.concat(_useLegacyExtensionLibraries ? qbs.sysroot + "/System/Library/PrivateFrameworks/" : []) cpp.frameworks: { var frameworks = base.concat(["Foundation"]); if (_useLegacyExtensionLibraries) frameworks.push("PlugInKit"); return frameworks; } cpp.requireAppExtensionSafeApi: true xpcServiceType: undefined property var extensionAttributes property string extensionPointIdentifier property string extensionPrincipalClass bundle.infoPlist: { var infoPlist = base; infoPlist["NSExtension"] = { "NSExtensionAttributes": extensionAttributes || {}, "NSExtensionPointIdentifier": extensionPointIdentifier, "NSExtensionPrincipalClass": extensionPrincipalClass }; return infoPlist; } } qbs-src-3.3.1/share/qbs/imports/qbs/base/AutotestRunner.qbs0000644000175100017510000001101015232633614023270 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2019 Jochen Ulrich ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils Product { name: "autotest-runner" type: ["autotest-result"] builtByDefault: false property stringList arguments: [] property stringList environment: ModUtils.flattenDictionary(qbs.commonRunEnvironment) property bool limitToSubProject: true property stringList wrapper: [] property string workingDir property stringList auxiliaryInputs property int timeout: -1 Depends { productTypes: "autotest" limitToSubProject: product.limitToSubProject } Depends { productTypes: auxiliaryInputs limitToSubProject: product.limitToSubProject } Rule { inputsFromDependencies: "application" auxiliaryInputsFromDependencies: product.auxiliaryInputs outputFileTags: "autotest-result" prepare: { // TODO: This is hacky. Possible solution: Add autotest tag to application // in autotest module and have that as inputsFromDependencies instead of application. if (!input.product.type.contains("autotest")) { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } var commandFilePath; var installed = input.moduleProperty("qbs", "install"); if (installed) commandFilePath = ModUtils.artifactInstalledFilePath(input); if (!commandFilePath || !File.exists(commandFilePath)) commandFilePath = input.filePath; var workingDir = product.workingDir ? product.workingDir : FileInfo.path(commandFilePath); var arguments = product.arguments; var allowFailure = false; var timeout = product.timeout; if (input.autotest) { // FIXME: We'd like to let the user override with an empty list, but // qbscore turns undefined lists into empty ones at the moment. if (input.autotest.arguments && input.autotest.arguments.length > 0) arguments = input.autotest.arguments; if (input.autotest.workingDir) workingDir = input.autotest.workingDir; allowFailure = input.autotest.allowFailure; if (input.autotest.timeout !== undefined) timeout = input.autotest.timeout; } var fullCommandLine = product.wrapper .concat([commandFilePath]) .concat(arguments); var cmd = new Command(fullCommandLine[0], fullCommandLine.slice(1)); cmd.description = "running test " + input.fileName; cmd.environment = product.environment; cmd.workingDirectory = workingDir; cmd.timeout = timeout; cmd.jobPool = "autotest-runner"; if (allowFailure) cmd.maxExitCode = 32767; return cmd; } } } qbs-src-3.3.1/share/qbs/imports/qbs/base/QtModule.qbs0000644000175100017510000000736215232633614022037 0ustar runnerrunnerimport qbs.FileInfo Module { condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild) && (!qbs.architecture || architectures.length === 0 || architectures.contains(qbs.architecture)) readonly property bool isCombinedUIKitBuild: ["ios", "tvos", "watchos"].contains(targetPlatform) && (!qbs.architecture || ["x86", "x86_64"].contains(qbs.architecture)) && qbs.targetPlatform === targetPlatform + "-simulator" Depends { name: "cpp" } Depends { name: "Qt.core" } Depends { name: "Qt.plugin_support" } property stringList pluginTypes Qt.plugin_support.pluginTypes: pluginTypes Depends { condition: Qt.core.staticBuild && !isPlugin name: "Qt"; submodules: { // We have to pull in all plugins here, because dependency resolving happens // before module merging, and we don't know yet if someone set // Qt.pluginSupport.pluginsByType in the product. // TODO: We might be able to use Qt.pluginSupport.pluginsByType now. // The real filtering is done later by the plugin module files themselves. var list = []; var allPlugins = Qt.plugin_support.allPluginsByType; for (var i = 0; i < (pluginTypes || []).length; ++i) Array.prototype.push.apply(list, allPlugins[pluginTypes[i]]) return list; } } property string qtModuleName property path binPath: Qt.core.binPath property path incPath: Qt.core.incPath property path libPath: Qt.core.libPath property string qtLibInfix: Qt.core.libInfix property string libNameForLinkerDebug property string libNameForLinkerRelease property string libNameForLinker: Qt.core.qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug property string libFilePathRelease property string libFilePath: Qt.core.qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease property bool hasLibrary: true property bool isStaticLibrary: false property bool isFramework: false property bool isPlugin: false property stringList architectures property string targetPlatform property stringList staticLibsDebug property stringList staticLibsRelease property stringList dynamicLibsDebug property stringList dynamicLibsRelease property stringList linkerFlagsDebug property stringList linkerFlagsRelease property stringList staticLibs: Qt.core.qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: Qt.core.qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList frameworksDebug property stringList frameworksRelease property stringList frameworkPathsDebug property stringList frameworkPathsRelease property stringList mFrameworks: Qt.core.qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList mFrameworkPaths: Qt.core.qtBuildVariant === "debug" ? frameworkPathsDebug: frameworkPathsRelease cpp.linkerFlags: Qt.core.qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease property bool enableLinking: qtModuleName != undefined && hasLibrary property stringList moduleConfig Properties { condition: enableLinking cpp.staticLibraries: staticLibs cpp.dynamicLibraries: dynamicLibs cpp.frameworks: mFrameworks.concat(isFramework ? [libNameForLinker] : []) cpp.systemFrameworkPaths: mFrameworkPaths } } qbs-src-3.3.1/share/qbs/imports/qbs/base/Application.qbs0000644000175100017510000000703715232633614022547 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ NativeBinary { type: isForAndroid && !consoleApplication ? ["android.package"] : ["application"] property bool usesNativeCode Depends { // Note: If we are multiplexing, then this dependency is technically only needed in // the aggregate. However, the user should not have to write the respective // condition when assigning to properties of this module, so we load it // regardless and turn off its rules for the native part of the build. name: "Android.sdk" condition: isForAndroid && !consoleApplication } Properties { condition: isForAndroid && !consoleApplication && !usesNativeCode multiplexByQbsProperties: [] aggregate: false } Properties { condition: isForAndroid && !consoleApplication && usesNativeCode && multiplexByQbsProperties && multiplexByQbsProperties.contains("architectures") && qbs.architectures && qbs.architectures.length > 1 aggregate: true multiplexedType: "android.nativelibrary" } Properties { condition: undefined multiplexByQbsProperties: base multiplexedType: base } aggregate: base Depends { name: "config.install" } install: config.install.install && !isForAndroid installDir: isBundle ? config.install.applicationsDirectory : config.install.binariesDirectory installDebugInformation: config.install.debugInformation && !isForAndroid debugInformationInstallDir: config.install.debugInformationDirectory || installDir Group { condition: install && _installable fileTagsFilter: isBundle ? "bundle.content" : "application" qbs.install: true qbs.installDir: installDir qbs.installSourceBase: isBundle ? destinationDirectory : outer } Group { condition: installDebugInformation && _installable fileTagsFilter: ["debuginfo_app"] qbs.install: true qbs.installDir: debugInformationInstallDir qbs.installSourceBase: destinationDirectory } } qbs-src-3.3.1/share/qbs/imports/qbs/base/AppleDiskImage.qbs0000644000175100017510000000304515232633614023116 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "dmg" } type: ["dmg.dmg"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/InstallPackage.qbs0000644000175100017510000000530615232633614023163 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.TextFile Product { type: ["archiver.archive"] builtByDefault: false Depends { name: "archiver" } archiver.type: "tar" archiver.workingDirectory: qbs.installRoot Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: product.name + ".tarlist" fileTags: ["archiver.input-list"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode =function() { var ofile = new TextFile(output.filePath, TextFile.WriteOnly); try { for (var i = 0; i < inputs["installable"].length; ++i) { var inp = inputs["installable"][i]; var installRoot = inp.moduleProperty("qbs", "installRoot"); var installedFilePath = ModUtils.artifactInstalledFilePath(inp); ofile.writeLine(FileInfo.relativePath(installRoot, installedFilePath)); } } finally { ofile.close(); } }; return [cmd]; } } } qbs-src-3.3.1/share/qbs/imports/qbs/base/WindowsInstallerPackage.qbs0000644000175100017510000000311615232633614025062 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["msi"] } qbs-src-3.3.1/share/qbs/imports/qbs/base/CppStd.qbs0000644000175100017510000000064515232633614021477 0ustar runnerrunnerStaticLibrary { name: "CppStd" property bool useStdCompat: false Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++23" cpp.forceUseCxxModules: true cpp.forceUseImportStd: true cpp.forceUseImportStdCompat: useStdCompat Properties { condition: qbs.toolchainType === "clang" cpp.cxxFlags: ["-Wno-reserved-module-identifier"] cpp.cxxStandardLibrary: "libc++" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/XPCService.qbs0000644000175100017510000000354415232633614022256 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Application { type: base.concat(["xpcservice"]) condition: qbs.targetOS.contains("darwin") property string xpcServiceType: "Application" bundle.infoPlist: { var infoPlist = base; if (xpcServiceType) { infoPlist["XPCService"] = { "ServiceType": xpcServiceType }; } return infoPlist; } } qbs-src-3.3.1/share/qbs/imports/qbs/base/JavaJarFile.qbs0000644000175100017510000000310615232633614022413 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.jar"] property string entryPoint } qbs-src-3.3.1/share/qbs/imports/qbs/base/Plugin.qbs0000644000175100017510000000470715232633614021543 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Library { Depends { name: "config.install" } Depends { name: "config.build" } type: { var defaultType = config.build.pluginType + "library"; if (qbs.targetOS.contains("ios") && parseInt(cpp.minimumIosVersion, 10) < 8) return ["staticlibrary"]; if (defaultType === "dynamiclibrary") { if (isForDarwin) return ["loadablemodule"]; if (isForAndroid) return [defaultType, "android.nativelibrary"]; } return [defaultType]; } installDir: { if (config.build.pluginType == "dynamic" && config.install.plugins) { if (isForDarwin && bundle.isBundle) return config.install.loadableModulesDirectory return config.install.pluginsDirectory; } return undefined; } debugInformationInstallDir: config.install.debugInformationDirectory || installDir } qbs-src-3.3.1/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs0000644000175100017510000001170715232633614025306 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils AppleDiskImage { property string sourceBase: "/Applications" readonly property string absoluteSourceBase: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, sourceBase) property stringList symlinks: ["/Applications:Applications"] readonly property string stageDirectory: FileInfo.joinPaths(destinationDirectory, "Volumes", dmg.volumeName) Rule { multiplex: true outputFileTags: ["dmg.input", "dmg.input.symlink"] outputArtifacts: Array.prototype.map.call(product.symlinks, function (symlink) { var symlinkTarget = symlink.split(':')[0]; var symlinkName = symlink.split(':')[1] || symlinkTarget; if (FileInfo.isAbsolutePath(symlinkName)) throw(symlink + " is an invalid symlink; the destination must be a relative path"); return { filePath: FileInfo.joinPaths(product.stageDirectory, symlinkName), fileTags: ["dmg.input", "dmg.input.symlink"], dmg: { symlinkTarget: symlinkTarget, sourceBase: product.stageDirectory }, }; }) prepare: Array.prototype.map.call(outputs["dmg.input"], function (symlink) { var cmd = new Command("ln", ["-sfn", symlink.dmg.symlinkTarget, symlink.filePath]); cmd.workingDirectory = product.stageDirectory; cmd.description = "symlinking " + symlink.fileName + " to " + symlink.dmg.symlinkTarget; return cmd; }); } Rule { multiplex: true inputs: ["dmg.input.symlink"] inputsFromDependencies: ["installable"] outputFileTags: ["dmg.input"] outputArtifacts: { var absSourceBase = product.absoluteSourceBase; var symlinkPaths = (inputs["dmg.input.symlink"] || []).map(function (s) { return s.filePath; }); return Array.prototype.map.call(inputs["installable"], function (a) { var fp = ModUtils.artifactInstalledFilePath(a); if (fp.startsWith(absSourceBase)) { var outputFilePath = fp.replace(absSourceBase, product.stageDirectory); // Check for symlink conflicts for (var i in symlinkPaths) { if (outputFilePath.startsWith(symlinkPaths[i])) throw new Error("Cannot install '" + a.filePath + "' to '" + outputFilePath + "' because it " + "would conflict with the symlink at '" + symlinkPaths[i] + "'"); } return { filePath: outputFilePath, fileTags: ["dmg.input"], dmg: { sourceBase: product.stageDirectory } } } }).filter(function (a) { return !!a; }); } prepare: { var absSourceBase = product.absoluteSourceBase; var cmds = [], dmgs = outputs["dmg.input"]; for (var i in dmgs) { var a = dmgs[i]; var cmd = new JavaScriptCommand(); cmd.src = a.filePath.replace(product.stageDirectory, absSourceBase); cmd.dst = a.filePath; cmd.silent = true; cmd.sourceCode = function () { File.copy(src, dst); }; cmds.push(cmd); } return cmds; } } } qbs-src-3.3.1/share/qbs/imports/qbs/base/NodeJSApplication.qbs0000644000175100017510000000302215232633614023600 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nodejs" } } qbs-src-3.3.1/share/qbs/imports/qbs/base/Library.qbs0000644000175100017510000001034515232633614021704 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ NativeBinary { Depends { name: "config.build" } type: { var defaultType = config.build.libraryType + "library"; if (qbs.targetOS.contains("ios") && parseInt(cpp.minimumIosVersion, 10) < 8) return ["staticlibrary"]; if (defaultType === "dynamiclibrary" && isForAndroid) return [defaultType, "android.nativelibrary"]; return [defaultType]; } readonly property bool isDynamicLibrary: type.contains("dynamiclibrary") readonly property bool isStaticLibrary: type.contains("staticlibrary") readonly property bool isLoadableModule: type.contains("loadablemodule") Depends { name: "config.install" } install: installDir !== undefined installDir: { if (isForAndroid) return undefined; if (isForDarwin && bundle.isBundle && config.install.frameworks) return config.install.frameworksDirectory; if (isStaticLibrary && config.install.staticLibraries) return config.install.staticLibrariesDirectory; if (isDynamicLibrary && config.install.dynamicLibraries) return config.install.dynamicLibrariesDirectory; return undefined; } property bool installImportLib: config.install.importLibraries property string importLibInstallDir: config.install.importLibrariesDirectory debugInformationInstallDir: config.install.debugInformationDirectory || installDir Group { condition: install && _installable fileTagsFilter: { if (isBundle) return ["bundle.content"]; if (isDynamicLibrary) return ["dynamiclibrary", "dynamiclibrary_symlink"]; if (isStaticLibrary) return ["staticlibrary"]; if (isLoadableModule) return ["loadablemodule"]; return []; } qbs.install: true qbs.installDir: installDir qbs.installSourceBase: isBundle ? destinationDirectory : outer } Group { condition: installImportLib && type.contains("dynamiclibrary") && _installable fileTagsFilter: "dynamiclibrary_import" qbs.install: true qbs.installDir: importLibInstallDir } Group { condition: installDebugInformation && _installable fileTagsFilter: { if (isDynamicLibrary) return ["debuginfo_dll"]; else if (isLoadableModule) return ["debuginfo_loadablemodule"]; return []; } qbs.install: true qbs.installDir: debugInformationInstallDir qbs.installSourceBase: destinationDirectory } Group { condition: isBundle product.bundle.isForMainBundle: !isStaticLibrary } } qbs-src-3.3.1/share/qbs/imports/qbs/base/NetModule.qbs0000644000175100017510000000010415232633614022164 0ustar runnerrunnerProduct { Depends { name: "cli" } type: ["cli.netmodule"] } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/0000755000175100017510000000000015232633614020106 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/Probes/XcodeProbe.qbs0000644000175100017510000001034515232633614022652 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Process import qbs.PropertyList import "../../../modules/xcode/xcode.js" as Xcode Probe { // Inputs property string sdksPath property string developerPath property string xcodebuildPath property stringList targetOS: qbs.targetOS property string platformType property string platformPath property string devicePlatformPath property string _xcodeInfoPlist: FileInfo.joinPaths(developerPath, "..", "Info.plist") // Outputs property var architectureSettings property var availableSdks property var platformSettings property string xcodeVersion configure: { if (File.exists(_xcodeInfoPlist)) { // Optimized case (no forking): reads CFBundleShortVersionString from // Xcode.app/Contents/Info.plist var propertyList = new PropertyList(); try { propertyList.readFromFile(_xcodeInfoPlist); var plist = propertyList.toObject(); if (plist) xcodeVersion = plist["CFBundleShortVersionString"]; } finally { propertyList.clear(); } } else { // Fallback case: execute xcodebuild -version if Xcode.app/Contents/Info.plist is // missing; this can happen if developerPath is /, for example var process; try { process = new Process(); process.exec(xcodebuildPath, ["-version"], true); var lines = process.readStdOut().trim().split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var l = 0; l < lines.length; ++l) { var m = lines[l].match(/^Xcode ([0-9\.]+)$/); if (m) { xcodeVersion = m[1]; break; } } } finally { process.close(); } } architectureSettings = {}; var archSpecsPath = Xcode.archsSpecsPath(xcodeVersion, targetOS, platformType, platformPath, devicePlatformPath, developerPath); var archSpecsReader = new Xcode.XcodeArchSpecsReader(archSpecsPath); archSpecsReader.getArchitectureSettings().map(function (setting) { var val = archSpecsReader.getArchitectureSettingValue(setting); if (val) architectureSettings[setting] = val; }); availableSdks = Xcode.sdkInfoList(sdksPath); var platformInfoPlist = FileInfo.joinPaths(platformPath, "Info.plist"); platformSettings = Xcode.platformInfo(platformInfoPlist); found = !!xcodeVersion; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/NpmProbe.qbs0000644000175100017510000000650015232633614022340 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.Host import qbs.ModUtils import "path-probe.js" as PathProbeConfigure import "../../../modules/nodejs/nodejs.js" as NodeJs NodeJsProbe { names: ["npm"] // Inputs property string interpreterPath // Outputs property path npmBin property path npmRoot property path npmPrefix configure: { if (!interpreterPath) throw '"interpreterPath" must be specified'; var selectors; var results = PathProbeConfigure.configure( selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().contains("windows")); v.prepend(interpreterPath); var resultsMapper = function(result) { result.npmBin = result.found ? NodeJs.findLocation(result.filePath, "bin", v.value) : undefined; result.npmRoot = result.found ? NodeJs.findLocation(result.filePath, "root", v.value) : undefined; result.npmPrefix = result.found ? NodeJs.findLocation(result.filePath, "prefix", v.value) : undefined; return result; }; results.files = results.files.map(resultsMapper); found = results.found; allResults = results.files; var result = results.files[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; npmBin = result.npmBin; npmRoot = result.npmRoot; npmPrefix = result.npmPrefix; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/qmake-probe.js0000644000175100017510000016315615232633614022663 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Host = require("qbs.Host"); var Process = require("qbs.Process"); var ProviderUtils = require("qbs.ProviderUtils"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }); } function getQmakeFilePaths(qmakeFilePaths) { if (qmakeFilePaths && qmakeFilePaths.length > 0) return qmakeFilePaths; console.info("Detecting Qt installations..."); var filePaths = []; var pathValue = Environment.getEnv("PATH"); if (pathValue) { var dirs = splitNonEmpty(pathValue, FileInfo.pathListSeparator()); for (var i = 0; i < dirs.length; ++i) { var candidate = FileInfo.joinPaths(dirs[i], "qmake" + FileInfo.executableSuffix()); var canonicalCandidate = FileInfo.canonicalPath(candidate); if (!canonicalCandidate || !File.exists(canonicalCandidate)) continue; if (FileInfo.completeBaseName(canonicalCandidate) !== "qtchooser") candidate = canonicalCandidate; if (!filePaths.contains(candidate)) { console.info("Found Qt at '" + FileInfo.toNativeSeparators(candidate) + "'."); filePaths.push(candidate); } } } if (filePaths.length === 0) { console.warn("Could not find any qmake executables in PATH. Either make sure a qmake " + "executable is present in PATH or set the moduleProviders.Qt.qmakeFilePaths property " + "to point to a qmake executable."); } return filePaths; } function queryQmake(qmakeFilePath) { var qmakeProcess = new Process; qmakeProcess.exec(qmakeFilePath, ["-query"]); if (qmakeProcess.exitCode() !== 0) { throw "The qmake executable '" + FileInfo.toNativeSeparators(qmakeFilePath) + "' failed with exit code " + qmakeProcess.exitCode() + "."; } var queryResult = {}; while (!qmakeProcess.atEnd()) { var line = qmakeProcess.readLine(); var index = (line || "").indexOf(":"); if (index !== -1) queryResult[line.slice(0, index)] = line.slice(index + 1).trim(); } return queryResult; } function pathQueryValue(queryResult, key) { var p = queryResult[key]; if (p) return FileInfo.fromNativeSeparators(p); } function readFileContent(filePath) { var f = new TextFile(filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); return content; } // TODO: Don't do the split every time... function configVariable(configContent, key) { var configContentLines = configContent.split('\n'); var regexp = new RegExp("^\\s*" + key + "\\s*\\+{0,1}=(.*)"); for (var i = 0; i < configContentLines.length; ++i) { var line = configContentLines[i]; var match = regexp.exec(line); if (match) return match[1].trim(); } } function configVariableItems(configContent, key) { var list = []; var configContentLines = configContent.split('\n'); var regexp = new RegExp("^\\s*" + key + "\\s*([+-]?=)(.*)"); for (var i = 0; i < configContentLines.length; ++i) { var line = configContentLines[i]; var match = regexp.exec(line); if (!match) continue; var op = match[1]; var lineList = splitNonEmpty(match[2], ' '); if (op === '=') { list = lineList; continue; } if (op === '+=') { list = list.concat(lineList); continue; } if (op === '-=') { for (var j = 0; j < lineList.length; ++j) { var idx = list.indexOf(lineList[j]); if (idx !== -1) list.splice(idx, 1); } } } return list; } function msvcCompilerVersionForYear(year) { var mapping = { "2005": "14", "2008": "15", "2010": "16", "2012": "17", "2013": "18", "2015": "19", "2017": "19.1", "2019": "19.2" }; return mapping[year]; } function msvcPrefix() { return "win32-msvc"; } function msvcCompilerVersionFromMkspecName(mkspecName) { if (mkspecName.startsWith(msvcPrefix())) { return msvcCompilerVersionForYear(mkspecName.slice(msvcPrefix().length)); } return undefined; } function addQtBuildVariant(qtProps, buildVariantName) { if (qtProps.qtConfigItems.contains(buildVariantName)) qtProps.buildVariant.push(buildVariantName); } function checkForStaticBuild(qtProps) { if (qtProps.qtMajorVersion >= 5) return qtProps.qtConfigItems.contains("static"); if (qtProps.frameworkBuild) return false; // there are no Qt4 static frameworks var isWin = qtProps.mkspecName.startsWith("win"); var libDir = isWin ? qtProps.binaryPath : qtProps.libraryPath; var coreLibFiles = File.directoryEntries(libDir, File.Files) .filter(function(fp) { return fp.contains("Core"); }); if (coreLibFiles.length === 0) throw "Could not determine whether Qt is a static build."; for (var i = 0; i < coreLibFiles.length; ++i) { if (Utilities.isSharedLibrary(coreLibFiles[i])) return false; } return true; } function guessMinimumWindowsVersion(qtProps) { if (qtProps.mkspecName.startsWith("winrt-")) return "10.0"; if (!ProviderUtils.isDesktopWindowsQt(qtProps)) return ""; if (qtProps.qtMajorVersion >= 6) return "10.0"; if (qtProps.architecture === "x86_64" || qtProps.architecture === "ia64") return "5.2" var match = qtProps.mkspecName.match(/^win32-msvc(\d+)$/); if (match) { var msvcVersion = match[1]; if (msvcVersion < 2012) return "5.0"; return "5.1"; } return qtProps.qtMajorVersion < 5 ? "5.0" : "5.1"; } function fillEntryPointLibs(qtProps, debug) { result = []; var isMinGW = ProviderUtils.isMinGwQt(qtProps); // Some Linux distributions rename the qtmain library. var qtMainCandidates = ["qtmain"]; if (isMinGW && qtProps.qtMajorVersion === 5) qtMainCandidates.push("qt5main"); if (qtProps.qtMajorVersion === 6) qtMainCandidates.push("Qt6EntryPoint"); for (var i = 0; i < qtMainCandidates.length; ++i) { var baseNameCandidate = qtMainCandidates[i]; var qtmain = qtProps.libraryPath + '/'; if (isMinGW) qtmain += "lib"; qtmain += baseNameCandidate + qtProps.qtLibInfix; if (debug && ProviderUtils.qtNeedsDSuffix(qtProps)) qtmain += 'd'; if (isMinGW) { qtmain += ".a"; } else { qtmain += ".lib"; if (Utilities.versionCompare(qtProps.qtVersion, "5.4.0") >= 0) result.push("Shell32.lib"); } if (File.exists(qtmain)) { result.push(qtmain); break; } } if (result.length === 0) { console.warn("Could not find the qtmain library at '" + FileInfo.toNativeSeparators(qtProps.libraryPath) + "'. You will not be able to link Qt applications."); } return result; } function getQtProperties(qmakeFilePath) { var queryResult = queryQmake(qmakeFilePath); var qtProps = {}; qtProps.installPrefixPath = pathQueryValue(queryResult, "QT_INSTALL_PREFIX"); qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS"); qtProps.translationsPath = pathQueryValue(queryResult, "QT_INSTALL_TRANSLATIONS"); qtProps.includePath = pathQueryValue(queryResult, "QT_INSTALL_HEADERS"); qtProps.libraryPath = pathQueryValue(queryResult, "QT_INSTALL_LIBS"); qtProps.hostLibraryPath = pathQueryValue(queryResult, "QT_HOST_LIBS"); qtProps.binaryPath = pathQueryValue(queryResult, "QT_HOST_BINS") || pathQueryValue(queryResult, "QT_INSTALL_BINS"); qtProps.installPath = pathQueryValue(queryResult, "QT_INSTALL_BINS"); qtProps.pluginPath = pathQueryValue(queryResult, "QT_INSTALL_PLUGINS"); qtProps.qmlPath = pathQueryValue(queryResult, "QT_INSTALL_QML"); qtProps.qmlImportPath = pathQueryValue(queryResult, "QT_INSTALL_IMPORTS"); qtProps.qtVersion = queryResult.QT_VERSION; var mkspecsBaseSrcPath; if (Utilities.versionCompare(qtProps.qtVersion, "5") >= 0) { qtProps.mkspecBasePath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA"), "mkspecs"); mkspecsBaseSrcPath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA/src"), "mkspecs"); } else { qtProps.mkspecBasePath = FileInfo.joinPaths (pathQueryValue(queryResult, "QT_INSTALL_DATA"), "mkspecs"); } if (Utilities.versionCompare(qtProps.qtVersion, "6") >= 0) { qtProps.libExecPath = pathQueryValue(queryResult, "QT_HOST_LIBEXECS") || pathQueryValue(queryResult, "QT_INSTALL_LIBEXECS"); } // QML tools were only moved in Qt 6.2. qtProps.qmlLibExecPath = Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0 ? qtProps.libExecPath : qtProps.binaryPath; // qhelpgenerator was only moved in Qt 6.3. qtProps.helpGeneratorLibExecPath = Utilities.versionCompare(qtProps.qtVersion, "6.3") >= 0 ? qtProps.libExecPath : qtProps.binaryPath; if (!File.exists(qtProps.mkspecBasePath)) throw "Cannot extract the mkspecs directory."; var qconfigContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath, "qconfig.pri")); qtProps.qtMajorVersion = parseInt(configVariable(qconfigContent, "QT_MAJOR_VERSION")); qtProps.qtMinorVersion = parseInt(configVariable(qconfigContent, "QT_MINOR_VERSION")); qtProps.qtPatchVersion = parseInt(configVariable(qconfigContent, "QT_PATCH_VERSION")); qtProps.qtNameSpace = configVariable(qconfigContent, "QT_NAMESPACE"); qtProps.qtLibInfix = configVariable(qconfigContent, "QT_LIBINFIX") || ""; qtProps.architecture = configVariable(qconfigContent, "QT_TARGET_ARCH") || configVariable(qconfigContent, "QT_ARCH") || "x86"; qtProps.configItems = configVariableItems(qconfigContent, "CONFIG"); qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG"); qtProps.enabledFeatures = configVariableItems(qconfigContent, "QT.global.enabled_features"); qtProps.disabledFeatures = configVariableItems(qconfigContent, "QT.global.disabled_features"); // retrieve the mkspec if (qtProps.qtMajorVersion >= 5) { qtProps.mkspecName = queryResult.QMAKE_XSPEC; qtProps.mkspecPath = FileInfo.joinPaths(qtProps.mkspecBasePath, qtProps.mkspecName); if (mkspecsBaseSrcPath && !File.exists(qtProps.mkspecPath)) qtProps.mkspecPath = FileInfo.joinPaths(mkspecsBaseSrcPath, qtProps.mkspecName); } else { if (Host.os().contains("windows")) { var baseDirPath = FileInfo.joinPaths(qtProps.mkspecBasePath, "default"); var fileContent = readFileContent(FileInfo.joinPaths(baseDirPath, "qmake.conf")); qtProps.mkspecPath = configVariable(fileContent, "QMAKESPEC_ORIGINAL"); if (!File.exists(qtProps.mkspecPath)) { // Work around QTBUG-28792. // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me? var match = fileContent.exec(/\binclude\(([^)]+)\/qmake\.conf\)/m); if (match) { qtProps.mkspecPath = FileInfo.cleanPath(FileInfo.joinPaths( baseDirPath, match[1])); } } } else { qtProps.mkspecPath = FileInfo.canonicalPath( FileInfo.joinPaths(qtProps.mkspecBasePath, "default")); } // E.g. in qmake.conf for Qt 4.8/mingw we find this gem: // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++ qtProps.mkspecPath = FileInfo.cleanPath(qtProps.mkspecPath); qtProps.mkspecName = qtProps.mkspecPath; var idx = qtProps.mkspecName.lastIndexOf('/'); if (idx !== -1) qtProps.mkspecName = qtProps.mkspecName.slice(idx + 1); } if (!File.exists(qtProps.mkspecPath)) throw "mkspec '" + FileInfo.toNativeSeparators(qtProps.mkspecPath) + "' does not exist"; // Starting with qt 5.14, android sdk provides multi-abi if (Utilities.versionCompare(qtProps.qtVersion, "5.14.0") >= 0 && qtProps.mkspecPath.contains("android")) { var qdeviceContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath, "qdevice.pri")); qtProps.androidAbis = configVariable(qdeviceContent, "DEFAULT_ANDROID_ABIS").split(' '); } // determine MSVC version if (ProviderUtils.isMsvcQt(qtProps)) { var msvcMajor = configVariable(qconfigContent, "QT_MSVC_MAJOR_VERSION"); var msvcMinor = configVariable(qconfigContent, "QT_MSVC_MINOR_VERSION"); var msvcPatch = configVariable(qconfigContent, "QT_MSVC_PATCH_VERSION"); if (msvcMajor && msvcMinor && msvcPatch) qtProps.msvcVersion = msvcMajor + "." + msvcMinor + "." + msvcPatch; else qtProps.msvcVersion = msvcCompilerVersionFromMkspecName(qtProps.mkspecName); } // determine whether we have a framework build qtProps.frameworkBuild = qtProps.mkspecPath.contains("macx") && qtProps.configItems.contains("qt_framework"); // determine whether Qt is built with debug, release or both qtProps.buildVariant = []; addQtBuildVariant(qtProps, "debug"); addQtBuildVariant(qtProps, "release"); qtProps.staticBuild = checkForStaticBuild(qtProps); qtProps.multiThreading = qtProps.enabledFeatures.contains("thread"); // determine whether user apps require C++11 if (qtProps.qtConfigItems.contains("c++11") && qtProps.staticBuild) qtProps.configItems.push("c++11"); // Set the minimum operating system versions appropriate for this Qt version qtProps.windowsVersion = guessMinimumWindowsVersion(qtProps); if (qtProps.windowsVersion) { // Is target OS Windows? if (qtProps.buildVariant.contains("debug")) qtProps.entryPointLibsDebug = fillEntryPointLibs(qtProps, true); if (qtProps.buildVariant.contains("release")) qtProps.entryPointLibsRelease = fillEntryPointLibs(qtProps, false); } else if (qtProps.mkspecPath.contains("macx")) { if (qtProps.qtMajorVersion >= 5) { // Since Qt 6.7.1, QMAKE_MACOSX|IOS_DEPLOYMENT_TARGET is no longer present in // qmake.conf. But it is also present in qconfig.pri, so first try to read it from there qtProps.macosVersion = configVariable(qconfigContent, "QMAKE_MACOSX_DEPLOYMENT_TARGET"); qtProps.iosVersion = configVariable(qconfigContent, "QMAKE_IOS_DEPLOYMENT_TARGET"); // Next, we override the value from qmake.conf, if present there // Note, that TVOS/WATCHOS variables are only present in qmake.conf (as of Qt 6.7.1) var lines = getFileContentsRecursively(FileInfo.joinPaths(qtProps.mkspecPath, "qmake.conf")); for (var i = 0; i < lines.length; ++i) { var line = lines[i].trim(); match = line.match (/^QMAKE_(MACOSX|IOS|TVOS|WATCHOS)_DEPLOYMENT_TARGET\s*=\s*(.*)\s*$/); if (match) { var platform = match[1]; var version = match[2]; if (platform === "MACOSX") qtProps.macosVersion = version; else if (platform === "IOS") qtProps.iosVersion = version; else if (platform === "TVOS") qtProps.tvosVersion = version; else if (platform === "WATCHOS") qtProps.watchosVersion = version; } } var isMac = qtProps.mkspecName !== "macx-ios-clang" && qtProps.mkspecName !== "macx-tvos-clang" && qtProps.mkspecName !== "macx-watchos-clang"; if (isMac) { // Qt 5.0.x placed the minimum version in a different file if (!qtProps.macosVersion) qtProps.macosVersion = "10.6"; // If we're using C++11 with libc++, make sure the deployment target is >= 10.7 if (Utilities.versionCompare(qtProps.macosVersion, "10, 7") < 0 && qtProps.qtConfigItems.contains("c++11")) { qtProps.macosVersion = "10.7"; } } } else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 6) { var qconfigDir = qtProps.frameworkBuild ? FileInfo.joinPaths(qtProps.libraryPath, "QtCore.framework", "Headers") : FileInfo.joinPaths(qtProps.includePath, "Qt"); try { var qconfig = new TextFile(FileInfo.joinPaths(qconfigDir, "qconfig.h"), TextFile.ReadOnly); var qtCocoaBuild = false; var ok = true; do { line = qconfig.readLine(); if (line.match(/\s*#define\s+QT_MAC_USE_COCOA\s+1\s*/)) { qtCocoaBuild = true; break; } } while (!qconfig.atEof()); qtProps.macosVersion = qtCocoaBuild ? "10.5" : "10.4"; } catch (e) {} finally { if (qconfig) qconfig.close(); } if (!qtProps.macosVersion) { throw "Could not determine whether Qt is using Cocoa or Carbon from '" + FileInfo.toNativeSeparators(qconfig.filePath()) + "'."; } } } else if (qtProps.mkspecPath.contains("android")) { if (qtProps.qtMajorVersion >= 5) qtProps.androidVersion = "2.3"; else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 8) qtProps.androidVersion = "1.6"; // Necessitas } if (qtProps.qtMajorVersion > 5) { qtProps.archData = pathQueryValue(queryResult, "QT_INSTALL_ARCHDATA"); // Qt 6.5 moved the metatypes files from the libraries directory to // the arch-specific data directory (qtbase commit 4234ce12dc819). qtProps.metaTypesPath = Utilities.versionCompare(qtProps.qtVersion, "6.5") >= 0 ? qtProps.archData + "/metatypes" : qtProps.libraryPath + "/metatypes"; qtProps.metaTypeFiles = File.directoryEntries(qtProps.metaTypesPath, File.Files); } return qtProps; } function makePluginData() { var pluginData = {}; pluginData.type = undefined; pluginData.className = undefined; pluginData.autoLoad = true; pluginData["extends"] = []; return pluginData; } function makeQtModuleInfo(name, qbsName, deps) { var moduleInfo = {}; moduleInfo.name = name; // As in the path to the headers and ".name" in the pri files. if (moduleInfo.name === undefined) moduleInfo.name = ""; moduleInfo.qbsName = qbsName; // Lower-case version without "qt" prefix. moduleInfo.dependencies = deps || []; // qbs names. if (moduleInfo.qbsName && moduleInfo.qbsName !== "core" && !moduleInfo.dependencies.contains("core")) { moduleInfo.dependencies.unshift("core"); } moduleInfo.isPrivate = qbsName && qbsName.endsWith("-private"); moduleInfo.hasLibrary = !moduleInfo.isPrivate; moduleInfo.isStaticLibrary = false; moduleInfo.isPlugin = false; moduleInfo.mustExist = true; moduleInfo.modulePrefix = ""; // empty value means "Qt". moduleInfo.version = undefined; moduleInfo.includePaths = []; moduleInfo.compilerDefines = []; moduleInfo.staticLibrariesDebug = []; moduleInfo.staticLibrariesRelease = []; moduleInfo.dynamicLibrariesDebug = []; moduleInfo.dynamicLibrariesRelease = []; moduleInfo.linkerFlagsDebug = []; moduleInfo.linkerFlagsRelease = []; moduleInfo.libFilePathDebug = undefined; moduleInfo.libFilePathRelease = undefined; moduleInfo.frameworksDebug = []; moduleInfo.frameworksRelease = []; moduleInfo.frameworkPathsDebug = []; moduleInfo.frameworkPathsRelease = []; moduleInfo.libraryPaths = []; moduleInfo.libDir = ""; moduleInfo.config = []; moduleInfo.supportedPluginTypes = []; moduleInfo.pluginData = makePluginData(); return moduleInfo; } function frameworkHeadersPath(qtModuleInfo, qtProps) { return FileInfo.joinPaths(qtProps.libraryPath, qtModuleInfo.name + ".framework", "Headers"); } function qt4ModuleIncludePaths(qtModuleInfo, qtProps) { var paths = []; if (ProviderUtils.qtIsFramework(qtModuleInfo, qtProps)) paths.push(frameworkHeadersPath(qtModuleInfo, qtProps)); else paths.push(qtProps.includePath, FileInfo.joinPaths(qtProps.includePath, qtModuleInfo.name)); return paths; } // We erroneously called the "testlib" module "test" for quite a while. Let's not punish users // for that. function addTestModule(modules) { var testModule = makeQtModuleInfo("QtTest", "test", ["testlib"]); testModule.hasLibrary = false; modules.push(testModule); } // See above. function addDesignerComponentsModule(modules) { var module = makeQtModuleInfo("QtDesignerComponents", "designercomponents", ["designercomponents-private"]); module.hasLibrary = false; modules.push(module); } function guessLibraryFilePath(prlFilePath, libDir, qtProps) { var baseName = FileInfo.baseName(prlFilePath); var prefixCandidates = ["", "lib"]; var suffixCandidates = ["so." + qtProps.qtVersion, "so", "a", "lib", "dll.a"]; for (var i = 0; i < prefixCandidates.length; ++i) { var prefix = prefixCandidates[i]; for (var j = 0; j < suffixCandidates.length; ++j) { var suffix = suffixCandidates[j]; var candidate = FileInfo.joinPaths(libDir, prefix + baseName + '.' + suffix); if (File.exists(candidate)) return candidate; } } } function doReplaceQtLibNamesWithFilePath(namePathMap, libList) { for (var i = 0; i < libList.length; ++i) { var lib = libList[i]; var path = namePathMap[lib]; if (path) libList[i] = path; } } function replaceQtLibNamesWithFilePath(modules, qtProps) { // We don't want to add the libraries for Qt modules via "-l", because of the // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead, // we pull them in using the full file path. var linkerNamesToFilePathsDebug = {}; var linkerNamesToFilePathsRelease = {}; for (var i = 0; i < modules.length; ++i) { var m = modules[i]; linkerNamesToFilePathsDebug[ ProviderUtils.qtLibNameForLinker(m, qtProps, true)] = m.libFilePathDebug; linkerNamesToFilePathsRelease[ ProviderUtils.qtLibNameForLinker(m, qtProps, false)] = m.libFilePathRelease; } for (i = 0; i < modules.length; ++i) { var module = modules[i]; doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.dynamicLibrariesDebug); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.staticLibrariesDebug); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, module.dynamicLibrariesRelease); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, module.staticLibrariesRelease); } } function doSetupLibraries(modInfo, qtProps, debugBuild, nonExistingPrlFiles, androidAbi) { if (!modInfo.hasLibrary) return; // Can happen for Qt4 convenience modules, like "widgets". if (debugBuild) { if (!qtProps.buildVariant.contains("debug")) return; var modulesNeverBuiltAsDebug = ["bootstrap", "qmldevtools"]; for (var i = 0; i < modulesNeverBuiltAsDebug.length; ++i) { var m = modulesNeverBuiltAsDebug[i]; if (modInfo.qbsName === m || modInfo.qbsName === m + "-private") return; } } else if (!qtProps.buildVariant.contains("release")) { return; } var libs = modInfo.isStaticLibrary ? (debugBuild ? modInfo.staticLibrariesDebug : modInfo.staticLibrariesRelease) : (debugBuild ? modInfo.dynamicLibrariesDebug : modInfo.dynamicLibrariesRelease); var frameworks = debugBuild ? modInfo.frameworksDebug : modInfo.frameworksRelease; var frameworkPaths = debugBuild ? modInfo.frameworkPathsDebug : modInfo.frameworkPathsRelease; var flags = debugBuild ? modInfo.linkerFlagsDebug : modInfo.linkerFlagsRelease; var libFilePath; if (qtProps.mkspecName.contains("ios") && modInfo.isStaticLibrary) { libs.push("z", "m"); if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) { var platformSupportModule = makeQtModuleInfo("QtPlatformSupport", "platformsupport"); libs.push(ProviderUtils.qtLibNameForLinker(platformSupportModule, qtProps, debugBuild)); } if (modInfo.name === "qios") { flags.push("-force_load", FileInfo.joinPaths( qtProps.pluginPath, "platforms", ProviderUtils.qtLibBaseName( modInfo, "libqios", debugBuild, qtProps) + ".a")); } } var prlFilePath = modInfo.isPlugin ? FileInfo.joinPaths(qtProps.pluginPath, modInfo.pluginData.type) : (modInfo.libDir ? modInfo.libDir : qtProps.libraryPath); var libDir = prlFilePath; if (ProviderUtils.qtIsFramework(modInfo, qtProps)) { prlFilePath = FileInfo.joinPaths( prlFilePath, ProviderUtils.qtLibraryBaseName(modInfo, qtProps, false) + ".framework"); libDir = prlFilePath; if (Utilities.versionCompare(qtProps.qtVersion, "5.14") >= 0) { var candidates = [ FileInfo.joinPaths(prlFilePath, "Resources"), // E.g. 5.15.9, 6.8.0/macOS FileInfo.joinPaths(prlFilePath, "Versions/A/Resources") // E.g. 6.8.0/iOS ]; for (i = 0; i < candidates.length; ++i) { if (File.exists(candidates[i])) { prlFilePath = candidates[i]; break; } } } } var baseName = ProviderUtils.qtLibraryBaseName(modInfo, qtProps, debugBuild); if (!qtProps.mkspecName.startsWith("win") && !ProviderUtils.qtIsFramework(modInfo, qtProps)) baseName = "lib" + baseName; prlFilePath = FileInfo.joinPaths(prlFilePath, baseName); var isNonStaticQt4OnWindows = qtProps.mkspecName.startsWith("win") && !modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5; if (isNonStaticQt4OnWindows) prlFilePath = prlFilePath.slice(0, prlFilePath.length - 1); // The prl file base name does *not* contain the version number... // qt for android versions 6.0 and 6.1 don't have the architecture suffix in the prl file if (androidAbi.length > 0 && modInfo.name !== "QtBootstrap" && (modInfo.name !== "QtQmlDevTools" || modInfo.name === "QtQmlDevTools" && Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0) && (Utilities.versionCompare(qtProps.qtVersion, "6.0") < 0 || Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0)) { prlFilePath += "_"; prlFilePath += androidAbi; } prlFilePath += ".prl"; try { var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly); while (!prlFile.atEof()) { var line = prlFile.readLine().trim(); var equalsOffset = line.indexOf('='); if (equalsOffset === -1) continue; if (line.startsWith("QMAKE_PRL_TARGET")) { var isMingw = qtProps.mkspecName.startsWith("win") && qtProps.mkspecName.contains("g++"); var isQtVersionBefore56 = qtProps.qtMajorVersion < 5 || (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 6); // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw. // Of course, the exception has an exception too: For static libs, mingw *does* // have the "lib" prefix. var libFileName = ""; if (isQtVersionBefore56 && qtProps.qtMajorVersion === 5 && isMingw && !modInfo.isStaticLibrary) { libFileName += "lib"; } libFileName += line.slice(equalsOffset + 1).trim(); if (isNonStaticQt4OnWindows) libFileName += 4; // This is *not* part of QMAKE_PRL_TARGET... if (isQtVersionBefore56) { if (qtProps.mkspecName.contains("msvc")) { libFileName += ".lib"; } else if (isMingw) { libFileName += ".a"; if (!File.exists(FileInfo.joinPaths(libDir, libFileName))) libFileName = libFileName.slice(0, -2) + ".dll"; } } libFilePath = FileInfo.joinPaths(libDir, libFileName); continue; } if (line.startsWith("QMAKE_PRL_CONFIG")) { modInfo.config = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' '); continue; } if (!line.startsWith("QMAKE_PRL_LIBS =")) continue; var parts = extractPaths(line.slice(equalsOffset + 1).trim(), prlFilePath); for (i = 0; i < parts.length; ++i) { var part = parts[i]; part = part.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath); part = part.replace("$$[QT_INSTALL_PLUGINS]", qtProps.pluginPath); part = part.replace("$$[QT_INSTALL_PREFIX]", qtProps.installPrefixPath); if (part.startsWith("-l")) { libs.push(part.slice(2)); } else if (part.startsWith("-L")) { modInfo.libraryPaths.push(part.slice(2)); } else if (part.startsWith("-F")) { frameworkPaths.push(part.slice(2)); } else if (part === "-framework") { if (++i < parts.length) frameworks.push(parts[i]); } else if (part === "-pthread") { // prl files for android have QMAKE_PRL_LIBS = -llog -pthread but the pthread // functionality is included in libc. if (androidAbi.length === 0) libs.push("pthread"); } else if (part.startsWith('-')) { // Some other option console.debug("QMAKE_PRL_LIBS contains non-library option '" + part + "' in file '" + prlFilePath + "'"); flags.push(part); } else if (part.startsWith("/LIBPATH:")) { libraryPaths.push(part.slice(9).replace(/\\/g, '/')); } else { // Assume it's a file path/name. libs.push(part.replace(/\\/g, '/')); } } } } catch (e) { // qt_ext_lib_extX.pri (usually) don't have a corresponding prl file. // So the pri file variable QMAKE_LIBS_LIBX points to the library if (modInfo.isExternal) { libFilePath = debugBuild ? modInfo.staticLibrariesDebug[0] : modInfo.staticLibrariesRelease[0]; } if (!libFilePath || !File.exists(libFilePath)) libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtProps); if (nonExistingPrlFiles.contains(prlFilePath)) return; nonExistingPrlFiles.push(prlFilePath); if (modInfo.mustExist) { console.warn("Could not open prl file '" + FileInfo.toNativeSeparators(prlFilePath) + "' for module '" + modInfo.name + "' (" + e + "), and failed to deduce the library file path. " + " This module will likely not be usable by qbs."); } } finally { if (prlFile) prlFile.close(); } if (debugBuild) modInfo.libFilePathDebug = libFilePath; else modInfo.libFilePathRelease = libFilePath; } function setupLibraries(qtModuleInfo, qtProps, nonExistingPrlFiles, androidAbi) { doSetupLibraries(qtModuleInfo, qtProps, true, nonExistingPrlFiles, androidAbi); doSetupLibraries(qtModuleInfo, qtProps, false, nonExistingPrlFiles, androidAbi); } function allQt4Modules(qtProps) { // as per http://doc.qt.io/qt-4.8/modules.html + private stuff. var modules = []; var core = makeQtModuleInfo("QtCore", "core"); core.compilerDefines.push("QT_CORE_LIB"); if (qtProps.qtNameSpace) core.compilerDefines.push("QT_NAMESPACE=" + qtProps.qtNameSpace); modules.push(core, makeQtModuleInfo("QtCore", "core-private", ["core"]), makeQtModuleInfo("QtGui", "gui"), makeQtModuleInfo("QtGui", "gui-private", ["gui"]), makeQtModuleInfo("QtMultimedia", "multimedia", ["gui", "network"]), makeQtModuleInfo("QtMultimedia", "multimedia-private", ["multimedia"]), makeQtModuleInfo("QtNetwork", "network"), makeQtModuleInfo("QtNetwork", "network-private", ["network"]), makeQtModuleInfo("QtOpenGL", "opengl", ["gui"]), makeQtModuleInfo("QtOpenGL", "opengl-private", ["opengl"]), makeQtModuleInfo("QtOpenVG", "openvg", ["gui"]), makeQtModuleInfo("QtScript", "script"), makeQtModuleInfo("QtScript", "script-private", ["script"]), makeQtModuleInfo("QtScriptTools", "scripttools", ["script", "gui"]), makeQtModuleInfo("QtScriptTools", "scripttools-private", ["scripttools"]), makeQtModuleInfo("QtSql", "sql"), makeQtModuleInfo("QtSql", "sql-private", ["sql"]), makeQtModuleInfo("QtSvg", "svg", ["gui"]), makeQtModuleInfo("QtSvg", "svg-private", ["svg"]), makeQtModuleInfo("QtWebKit", "webkit", ["gui", "network"]), makeQtModuleInfo("QtWebKit", "webkit-private", ["webkit"]), makeQtModuleInfo("QtXml", "xml"), makeQtModuleInfo("QtXml", "xml-private", ["xml"]), makeQtModuleInfo("QtXmlPatterns", "xmlpatterns", ["network"]), makeQtModuleInfo("QtXmlPatterns", "xmlpatterns-private", ["xmlpatterns"]), makeQtModuleInfo("QtDeclarative", "declarative", ["gui", "script"]), makeQtModuleInfo("QtDeclarative", "declarative-private", ["declarative"]), makeQtModuleInfo("QtDesigner", "designer", ["gui", "xml"]), makeQtModuleInfo("QtDesigner", "designer-private", ["designer"]), makeQtModuleInfo("QtUiTools", "uitools"), makeQtModuleInfo("QtUiTools", "uitools-private", ["uitools"]), makeQtModuleInfo("QtHelp", "help", ["network", "sql"]), makeQtModuleInfo("QtHelp", "help-private", ["help"]), makeQtModuleInfo("QtTest", "testlib"), makeQtModuleInfo("QtTest", "testlib-private", ["testlib"])); if (qtProps.mkspecName.startsWith("win")) { var axcontainer = makeQtModuleInfo("QAxContainer", "axcontainer"); axcontainer.modulePrefix = "Q"; axcontainer.isStaticLibrary = true; axcontainer.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt")); modules.push(axcontainer); var axserver = makeQtModuleInfo("QAxServer", "axserver"); axserver.modulePrefix = "Q"; axserver.isStaticLibrary = true; axserver.compilerDefines.push("QAXSERVER"); axserver.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt")); modules.push(axserver); } else { modules.push(makeQtModuleInfo("QtDBus", "dbus")); modules.push(makeQtModuleInfo("QtDBus", "dbus-private", ["dbus"])); } var designerComponentsPrivate = makeQtModuleInfo( "QtDesignerComponents", "designercomponents-private", ["gui-private", "designer-private"]); designerComponentsPrivate.hasLibrary = true; modules.push(designerComponentsPrivate); var phonon = makeQtModuleInfo("Phonon", "phonon"); phonon.includePaths = qt4ModuleIncludePaths(phonon, qtProps); modules.push(phonon); // Set up include paths that haven't been set up before this point. for (i = 0; i < modules.length; ++i) { var module = modules[i]; if (module.includePaths.length > 0) continue; module.includePaths = qt4ModuleIncludePaths(module, qtProps); } // Set up compiler defines haven't been set up before this point. for (i = 0; i < modules.length; ++i) { module = modules[i]; if (module.compilerDefines.length > 0) continue; module.compilerDefines.push("QT_" + module.qbsName.toUpperCase() + "_LIB"); } // These are for the convenience of project file authors. It allows them // to add a dependency to e.g. "Qt.widgets" without a version check. var virtualModule = makeQtModuleInfo(undefined, "widgets", ["core", "gui"]); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "quick", ["declarative"]); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "concurrent"); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "printsupport", ["core", "gui"]); virtualModule.hasLibrary = false; modules.push(virtualModule); addTestModule(modules); addDesignerComponentsModule(modules); var modulesThatCanBeDisabled = [ "xmlpatterns", "multimedia", "phonon", "svg", "webkit", "script", "scripttools", "declarative", "gui", "dbus", "opengl", "openvg"]; var nonExistingPrlFiles = []; for (i = 0; i < modules.length; ++i) { module = modules[i]; var name = module.qbsName; var privateIndex = name.indexOf("-private"); if (privateIndex !== -1) name = name.slice(0, privateIndex); if (modulesThatCanBeDisabled.contains(name)) module.mustExist = false; if (qtProps.staticBuild) module.isStaticLibrary = true; setupLibraries(module, qtProps, nonExistingPrlFiles, ""); } replaceQtLibNamesWithFilePath(modules, qtProps); return modules; } function getFileContentsRecursively(filePath) { var file = new TextFile(filePath, TextFile.ReadOnly); var lines = splitNonEmpty(file.readAll(), '\n'); for (var i = 0; i < lines.length; ++i) { var includeString = "include("; var line = lines[i].trim(); if (!line.startsWith(includeString)) continue; var offset = includeString.length; var closingParenPos = line.indexOf(')', offset); if (closingParenPos === -1) { console.warn("Invalid include statement in '" + FileInfo.toNativeSeparators(filePath) + "'"); continue; } var includedFilePath = line.slice(offset, closingParenPos); if (!FileInfo.isAbsolutePath(includedFilePath)) includedFilePath = FileInfo.joinPaths(FileInfo.path(filePath), includedFilePath); var includedContents = getFileContentsRecursively(includedFilePath); var j = i; for (var k = 0; k < includedContents.length; ++k) lines.splice(++j, 0, includedContents[k]); lines.splice(i--, 1); } file.close(); return lines; } function extractPaths(rhs, filePath) { var paths = []; var startIndex = 0; for (;;) { while (startIndex < rhs.length && rhs.charAt(startIndex) === ' ') ++startIndex; if (startIndex >= rhs.length) break; var endIndex; if (rhs.charAt(startIndex) === '"') { ++startIndex; endIndex = rhs.indexOf('"', startIndex); if (endIndex === -1) { console.warn("Unmatched quote in file '" + FileInfo.toNativeSeparators(filePath) + "'"); break; } } else { endIndex = rhs.indexOf(' ', startIndex + 1); if (endIndex === -1) endIndex = rhs.length; } paths.push(FileInfo.cleanPath(rhs.slice(startIndex, endIndex) .replace("$$PWD", FileInfo.path(filePath)))); startIndex = endIndex + 1; } return paths; } function removeDuplicatedDependencyLibs(modules) { var revDeps = {}; var currentPath = []; var getLibraries; var getLibFilePath; function setupReverseDependencies(modules) { var moduleByName = {}; for (var i = 0; i < modules.length; ++i) moduleByName[modules[i].qbsName] = modules[i]; for (i = 0; i < modules.length; ++i) { var module = modules[i]; for (var j = 0; j < module.dependencies.length; ++j) { var depmod = moduleByName[module.dependencies[j]]; if (!depmod) continue; if (!revDeps[depmod.qbsName]) revDeps[depmod.qbsName] = []; revDeps[depmod.qbsName].push(module); } } } function roots(modules) { var result = []; for (i = 0; i < modules.length; ++i) { var module = modules[i] if (module.dependencies.length === 0) result.push(module); } return result; } function traverse(module, libs) { if (currentPath.contains(module)) return; currentPath.push(module); var moduleLibraryLists = getLibraries(module); for (var i = 0; i < moduleLibraryLists.length; ++i) { var modLibList = moduleLibraryLists[i]; for (j = modLibList.length - 1; j >= 0; --j) { if (libs.contains(modLibList[j])) modLibList.splice(j, 1); } } var libFilePath = getLibFilePath(module); if (libFilePath) libs.push(libFilePath); for (i = 0; i < moduleLibraryLists.length; ++i) libs = libs.concat(moduleLibraryLists[i]); libs.sort(); var deps = revDeps[module.qbsName]; for (i = 0; i < (deps || []).length; ++i) traverse(deps[i], libs); currentPath.pop(); } setupReverseDependencies(modules); // Traverse the debug variants of modules. getLibraries = function(module) { return [module.dynamicLibrariesDebug, module.staticLibrariesDebug]; }; getLibFilePath = function(module) { return module.libFilePathDebug; }; var rootModules = roots(modules); for (var i = 0; i < rootModules.length; ++i) traverse(rootModules[i], []); // Traverse the release variants of modules. getLibraries = function(module) { return [module.dynamicLibrariesRelease, module.staticLibrariesRelease]; }; getLibFilePath = function(module) { return module.libFilePathRelease; }; for (i = 0; i < rootModules.length; ++i) traverse(rootModules[i], []); } function allQt5Modules(qtProps, androidAbi) { var nonExistingPrlFiles = []; var modules = []; var modulesDir = FileInfo.joinPaths(qtProps.mkspecBasePath, "modules"); var modulePriFiles = File.directoryEntries(modulesDir, File.Files); for (var i = 0; i < modulePriFiles.length; ++i) { var priFileName = modulePriFiles[i]; var priFilePath = FileInfo.joinPaths(modulesDir, priFileName); var externalFileNamePrefix = "qt_ext_"; var moduleFileNamePrefix = "qt_lib_"; var pluginFileNamePrefix = "qt_plugin_"; var moduleFileNameSuffix = ".pri"; var fileHasExternalPrefix = priFileName.startsWith(externalFileNamePrefix); var fileHasModulePrefix = priFileName.startsWith(moduleFileNamePrefix); var fileHasPluginPrefix = priFileName.startsWith(pluginFileNamePrefix); if (!fileHasPluginPrefix && !fileHasModulePrefix && !fileHasExternalPrefix || !priFileName.endsWith(moduleFileNameSuffix)) { continue; } var moduleInfo = makeQtModuleInfo(); moduleInfo.isPlugin = fileHasPluginPrefix; moduleInfo.isExternal = !moduleInfo.isPlugin && !fileHasModulePrefix; var fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleInfo.isExternal ? externalFileNamePrefix : moduleFileNamePrefix; moduleInfo.qbsName = priFileName.slice(fileNamePrefix.length, -moduleFileNameSuffix.length); if (moduleInfo.isPlugin) { moduleInfo.name = moduleInfo.qbsName; moduleInfo.isStaticLibrary = true; } var moduleKeyPrefix = (moduleInfo.isPlugin ? "QT_PLUGIN" : "QT") + '.' + moduleInfo.qbsName + '.'; moduleInfo.qbsName = moduleInfo.qbsName.replace("_private", "-private"); var hasV2 = false; var hasModuleEntry = false; var lines = getFileContentsRecursively(priFilePath); if (moduleInfo.isExternal) { moduleInfo.name = "qt" + moduleInfo.qbsName; moduleInfo.isStaticLibrary = true; for (var k = 0; k < lines.length; ++k) { var extLine = lines[k].trim(); var extFirstEqualsOffset = extLine.indexOf('='); if (extFirstEqualsOffset === -1) continue; var extKey = extLine.slice(0, extFirstEqualsOffset).trim(); var extValue = extLine.slice(extFirstEqualsOffset + 1).trim(); if (!extKey.startsWith("QMAKE_") || !extValue) continue; var elements = extKey.split('_'); if (elements.length >= 3) { if (elements[1] === "LIBS") { extValue = extValue.replace("/home/qt/work/qt/qtbase/lib", qtProps.libraryPath); extValue = extValue.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath); extValue = extValue.replace("$$[QT_INSTALL_LIBS/get]", qtProps.libraryPath); if (elements.length === 4 ) { if (elements[3] === androidAbi) { moduleInfo.staticLibrariesRelease.push(extValue); moduleInfo.staticLibrariesDebug.push(extValue); } } else if (elements.length === 5 ) { // That's for "x86_64" var abi = elements[3] + '_' + elements[4]; if (abi === androidAbi) { moduleInfo.staticLibrariesRelease.push(extValue); moduleInfo.staticLibrariesDebug.push(extValue); } } else { moduleInfo.staticLibrariesRelease.push(extValue); moduleInfo.staticLibrariesDebug.push(extValue); } } else if (elements[1] === "INCDIR") { moduleInfo.includePaths.push(extValue.replace("$$[QT_INSTALL_HEADERS]", qtProps.includePath)); } } } moduleInfo.compilerDefines.push("QT_" + moduleInfo.qbsName.toUpperCase() + "_LIB"); moduleInfo.mustExist = false; } else { for (var j = 0; j < lines.length; ++j) { var line = lines[j].trim(); var firstEqualsOffset = line.indexOf('='); if (firstEqualsOffset === -1) continue; var key = line.slice(0, firstEqualsOffset).trim(); var value = line.slice(firstEqualsOffset + 1).trim(); if (!key.startsWith(moduleKeyPrefix) || !value) continue; if (key.endsWith(".name")) { moduleInfo.name = value; } else if (key.endsWith(".module")) { hasModuleEntry = true; } else if (key.endsWith(".depends")) { moduleInfo.dependencies = splitNonEmpty(value, ' '); for (var k = 0; k < moduleInfo.dependencies.length; ++k) { moduleInfo.dependencies[k] = moduleInfo.dependencies[k].replace("_private", "-private"); } } else if (key.endsWith(".module_config")) { var elems = splitNonEmpty(value, ' '); for (k = 0; k < elems.length; ++k) { var elem = elems[k]; if (elem === "no_link") moduleInfo.hasLibrary = false; else if (elem === "staticlib") moduleInfo.isStaticLibrary = true; else if (elem === "internal_module") moduleInfo.isPrivate = true; else if (elem === "v2") hasV2 = true; else if (elem === "lib_bundle") moduleInfo.isFramework = true; } } else if (key.endsWith(".includes")) { moduleInfo.includePaths = extractPaths(value, priFilePath); for (k = 0; k < moduleInfo.includePaths.length; ++k) { moduleInfo.includePaths[k] = moduleInfo.includePaths[k] .replace("$$QT_MODULE_INCLUDE_BASE", qtProps.includePath) .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath) .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath); } } else if (key.endsWith(".libs")) { var libDirs = extractPaths(value, priFilePath); if (libDirs.length === 1) { moduleInfo.libDir = libDirs[0] .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath) .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath); } else { moduleInfo.libDir = qtProps.libraryPath; } } else if (key.endsWith(".DEFINES")) { moduleInfo.compilerDefines = splitNonEmpty(value, ' '); } else if (key.endsWith(".VERSION")) { moduleInfo.version = value; } else if (key.endsWith(".plugin_types")) { moduleInfo.supportedPluginTypes = splitNonEmpty(value, ' '); } else if (key.endsWith(".TYPE")) { moduleInfo.pluginData.type = value; } else if (key.endsWith(".EXTENDS")) { moduleInfo.pluginData["extends"] = splitNonEmpty(value, ' '); for (k = 0; k < moduleInfo.pluginData["extends"].length; ++k) { if (moduleInfo.pluginData["extends"][k] === "-") { moduleInfo.pluginData["extends"].splice(k, 1); moduleInfo.pluginData.autoLoad = false; break; } } } else if (key.endsWith(".CLASS_NAME")) { moduleInfo.pluginData.className = value; } } } if (hasV2 && !hasModuleEntry && !moduleInfo.isStaticLibrary) moduleInfo.hasLibrary = false; // Fix include paths for Apple frameworks. // The qt_lib_XXX.pri files contain wrong values for versions < 5.6. if (!hasV2 && ProviderUtils.qtIsFramework(moduleInfo, qtProps)) { moduleInfo.includePaths = []; var baseIncDir = frameworkHeadersPath(moduleInfo, qtProps); if (moduleInfo.isPrivate) { baseIncDir = FileInfo.joinPaths(baseIncDir, moduleInfo.version); moduleInfo.includePaths.push(baseIncDir, FileInfo.joinPaths(baseIncDir, moduleInfo.name)); } else { moduleInfo.includePaths.push(baseIncDir); } } setupLibraries(moduleInfo, qtProps, nonExistingPrlFiles, androidAbi); modules.push(moduleInfo); if (moduleInfo.qbsName === "testlib") addTestModule(modules); if (moduleInfo.qbsName === "designercomponents-private") addDesignerComponentsModule(modules); } replaceQtLibNamesWithFilePath(modules, qtProps); removeDuplicatedDependencyLibs(modules); return modules; } function getQtInfo(qmakeFilePath) { if (!File.exists(qmakeFilePath)) { throw "The specified qmake file path '" + FileInfo.toNativeSeparators(qmakeFilePath) + "' does not exist."; } var qtProps = getQtProperties(qmakeFilePath); var androidAbis = []; if (qtProps.androidAbis !== undefined) { // Multiple androidAbis detected: Qt >= 5.14 androidAbis = qtProps.androidAbis; } else { // Single abi detected: Qt < 5.14 androidAbis.push(''); } if (androidAbis.length > 1) console.info("Qt with multiple abi detected: '" + androidAbis + "'"); var result = {}; result.qtProps = qtProps; result.abiInfos = []; result.qmakeFilePath = qmakeFilePath; for (a = 0; a < androidAbis.length; ++a) { var abiInfo = {}; if (androidAbis.length > 1) console.info("Found abi '" + androidAbis[a] + "'..."); abiInfo.androidAbi = androidAbis[a]; var allModules = qtProps.qtMajorVersion < 5 ? allQt4Modules(qtProps) : allQt5Modules(qtProps, androidAbis[a]);; abiInfo.modules = {}; for (var i = 0; i < allModules.length; ++i) { var module = allModules[i]; abiInfo.modules[module.qbsName] = module; } abiInfo.pluginsByType = {}; abiInfo.nonEssentialPlugins = []; for (var moduleName in abiInfo.modules) { var m = abiInfo.modules[moduleName]; if (m.isPlugin) { if (!abiInfo.pluginsByType[m.pluginData.type]) abiInfo.pluginsByType[m.pluginData.type] = []; abiInfo.pluginsByType[m.pluginData.type].push(m.name); if (!m.pluginData.autoLoad) abiInfo.nonEssentialPlugins.push(m.name); } } result.abiInfos.push(abiInfo); } return result; } function configure(qmakeFilePaths) { var result = []; qmakeFilePaths = getQmakeFilePaths(qmakeFilePaths); if (!qmakeFilePaths || qmakeFilePaths.length === 0) return result; for (var i = 0; i < qmakeFilePaths.length; ++i) { var qtInfo = {}; try { console.info("Getting info about Qt at '" + FileInfo.toNativeSeparators(qmakeFilePaths[i]) + "'..."); qtInfo = getQtInfo(qmakeFilePaths[i]); result.push(qtInfo); } catch (e) { console.warn("Error getting info about Qt for '" + FileInfo.toNativeSeparators(qmakeFilePaths[i]) + "': " + e); throw e; } } return result; } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/IncludeProbe.qbs0000644000175100017510000000345315232633614023175 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { platformSearchPaths: qbs.targetOS.contains("unix") ? [ "/usr/include", "/usr/local/include", "/include", "/app/include", ] : [] platformEnvironmentPaths: { if (qbs.toolchain.contains('msvc')) return [ "INCLUDE" ]; return undefined; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs0000644000175100017510000000577015232633614023640 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import "../../../modules/Android/sdk/utils.js" as SdkUtils import "../../../modules/Android/android-utils.js" as AndroidUtils PathProbe { environmentPaths: Environment.getEnv("ANDROID_HOME") platformSearchPaths: { if (Host.os().contains("windows")) return [FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"), "Android", "sdk")]; if (Host.os().contains("macos")) return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Library", "Android", "sdk")]; if (Host.os().contains("linux")) return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Android", "Sdk")]; } // Outputs property stringList candidatePaths property var buildToolsVersions property string buildToolsVersion property var platforms property string platform configure: { var i, allPaths = (environmentPaths || []).concat(platformSearchPaths || []); candidatePaths = allPaths; for (i in allPaths) { if (File.exists(FileInfo.joinPaths(allPaths[i], "build-tools"))) { path = allPaths[i]; buildToolsVersions = SdkUtils.availableBuildToolsVersions(path) buildToolsVersion = buildToolsVersions[buildToolsVersions.length - 1]; platforms = AndroidUtils.availablePlatforms(path) platform = platforms[platforms.length - 1]; found = true; return; } } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/QbsPkgConfigProbe.qbs0000644000175100017510000000455515232633614024133 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "qbs-pkg-config-probe.js" as PkgConfigProbeConfigure Probe { // Inputs property string _executableFilePath property stringList _extraPaths property stringList _libDirs property bool _staticMode: false property bool _definePrefix: false property path _sysroot // Output property var packages property var packagesByModuleName property var brokenPackages property stringList qmakePaths configure: { var result = PkgConfigProbeConfigure.configure( _executableFilePath, _extraPaths, _libDirs, _staticMode, _definePrefix, _sysroot); packages = result.packages; packagesByModuleName = result.packagesByModuleName; brokenPackages = result.brokenPackages; qmakePaths = result.qmakePaths; found = true; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/IcoUtilsVersionProbe.qbs0000644000175100017510000000335415232633614024713 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "../../../modules/ico/ico.js" as IcoUtils Probe { // Inputs property string toolFilePath // Outputs property var version configure: { version = IcoUtils.findIcoUtilsVersion(toolFilePath); found = !!version; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs0000644000175100017510000000457615232633614023545 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities PathProbe { // Outputs property var version configure: { var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\" ]; var keySuffixes = [ "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1", "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 6_is1" ]; for (var i = 0; i < keys.length; ++i) { for (var j = 0; j < keySuffixes.length; ++j) { var key = keys[i] + keySuffixes[j]; var v = Utilities.getNativeSetting(key, "DisplayVersion"); if (v) { path = Utilities.getNativeSetting(key, "InstallLocation"); version = v; found = path && version; return; } } } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs0000644000175100017510000001320115232633614023617 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.TextFile import "../../../modules/Android/android-utils.js" as AndroidUtils PathProbe { // Inputs property path sdkPath environmentPaths: Environment.getEnv("ANDROID_NDK_ROOT") platformSearchPaths: { var paths = []; if (sdkPath) paths.push(FileInfo.joinPaths(sdkPath, "ndk-bundle")); if (Host.os().contains("windows")) paths.push(FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"), "Android", "sdk", "ndk-bundle")); if (Host.os().contains("macos")) paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"), "Library", "Android", "sdk", "ndk-bundle")); if (Host.os().contains("linux")) paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"), "Android", "Sdk", "ndk-bundle")); return paths; } // Outputs property stringList candidatePaths property string samplesDir property var hostArch property stringList toolchains: [] property string ndkVersion configure: { function readFileContent(filePath) { var result = null; if (!File.exists(filePath)) return result; try { var tf = new TextFile(filePath, TextFile.ReadOnly); result = tf.readAll(); } finally { if (tf) tf.close(); } return result; } var i, j, allPaths = (environmentPaths || []).concat(platformSearchPaths || []); candidatePaths = allPaths; for (i in allPaths) { var platforms = []; if (Host.os().contains("windows")) platforms.push("windows-x86_64", "windows"); if (Host.os().contains("darwin")) platforms.push("darwin-x86_64", "darwin-x86"); if (Host.os().contains("linux")) platforms.push("linux-x86_64", "linux-x86"); for (j in platforms) { if (File.exists(FileInfo.joinPaths(allPaths[i], "prebuilt", platforms[j]))) { path = allPaths[i]; if (File.exists(FileInfo.joinPaths(path, "samples"))) samplesDir = FileInfo.joinPaths(path, "samples"); // removed in r11 hostArch = platforms[j]; toolchains = File.directoryEntries(FileInfo.joinPaths(path, "toolchains"), File.Dirs | File.NoDotAndDotDot); // NDK r11 and above var content = readFileContent(path + "/source.properties"); if (content) { var lines = content.trim().split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var l = 0; l < lines.length; ++l) { var m = lines[l].match(/^Pkg\.Revision\s*=\s*([0-9\.]+)$/); if (m) { ndkVersion = m[1]; found = true; return; } } } // NDK r10 and below var releaseTextFileCandidates = ["RELEASE.txt", "RELEASE.TXT"] .map(function(v) { return FileInfo.joinPaths(path, v); }) .filter(File.exists); content = releaseTextFileCandidates.length ? readFileContent(releaseTextFileCandidates[0]) : null; if (content) { var m = content.trim().match(/^r([0-9]+[a-z]?).*/); if (m) { ndkVersion = m[1]; found = true; return; } } } } } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/IarProbe.qbs0000644000175100017510000000626115232633614022325 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/iar.js" as IAR PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage // Outputs property string architecture property string endianness property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; var defaultPathsByLanguage = {}; for (var i = 0; i < languages.length; ++i) { var tag = languages[i]; compilerDefinesByLanguage[tag] = IAR.dumpMacros( compilerFilePath, tag); var paths = IAR.dumpDefaultPaths(compilerFilePath, tag); defaultPathsByLanguage[tag] = paths; } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"]; architecture = IAR.guessArchitecture(macros); endianness = IAR.guessEndianness(macros); var defaultPaths = defaultPathsByLanguage["cpp"] || defaultPathsByLanguage["c"]; includePaths = defaultPaths.includePaths; var version = IAR.guessVersion(macros, architecture); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture && !!endianness; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/XcodeLocationProbe.qbs0000644000175100017510000000364015232633614024343 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Process Probe { property path developerPath configure: { var p = new Process(); try { p.exec("/usr/bin/xcode-select", ["--print-path"], true); developerPath = p.readStdOut().trim(); } catch (e) { developerPath = "/Applications/Xcode.app/Contents/Developer"; } finally { p.close(); found = true; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs0000644000175100017510000000342115232633614023542 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { platformSearchPaths: (qbs.sysroot ? [qbs.sysroot + "/System/Library/Frameworks"] : []).concat([ "~/Library/Frameworks", "/usr/local/lib", "/Library/Frameworks", "/System/Library/Frameworks" ]) nameSuffixes: ".framework" } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/ConanfileProbe.qbs0000644000175100017510000001414415232633614023507 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Richard Weickelt ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Process import qbs.File import qbs.FileInfo import qbs.TextFile import qbs.Utilities Probe { // Inputs property stringList additionalArguments: [] property path conanfilePath property path packageReference property path executable: "conan" + FileInfo.executableSuffix() property stringList generators property var options property var settings property string profileAll property bool verbose: false // Output property path generatedFilesPath property var dependencies property var json // Internal // Ensure that the probe is re-run automatically whenever conanfile changes // by making a file system property part of the probe's signature. property int _conanfileLastModified: conanfilePath ? File.lastModified(conanfilePath) : 0 property path _projectBuildDirectory: project.buildDirectory configure: { if (conanfilePath && packageReference) throw("conanfilePath and packageReference must not be defined at the same time."); if (!conanfilePath && !packageReference) throw("Either conanfilePath or packageReference must be defined."); var reference = packageReference || FileInfo.cleanPath(conanfilePath); console.info("Probing '" + reference + "'. This might take a while..."); if (conanfilePath && !File.exists(reference)) throw("The conanfile '" + reference + "' does not exist."); function getConanVersion() { var p = new Process(); p.exec(executable, ["--version"], true); return p.readStdOut().trim().replace("Conan version", "").trim(); } const isConan2 = Utilities.versionCompare(getConanVersion(), "2.0.0") >= 0; var args = [ "install", reference, ]; if (options) { if (typeof options !== "object") throw("The property 'options' must be an object."); Object.keys(options).forEach(function(key,index) { args.push("-o"); args.push(key + "=" + options[key]); }); } if (settings) { if (typeof settings !== "object") throw("The property 'settings' must be an object."); Object.keys(settings).forEach(function(key,index) { args.push("-s"); args.push(key + "=" + settings[key]); }); } if (generators === undefined) { if (isConan2) generators = ["QbsDeps"]; else generators = ["json"]; } if (!isConan2 && !generators.contains("json")) generators.push("json"); for (var i = 0; i < generators.length; i++) args = args.concat(["-g", generators[i]]); for (var i = 0; i < additionalArguments.length; i++) args.push(additionalArguments[i]); generatedFilesPath = FileInfo.cleanPath(_projectBuildDirectory + "/genconan/" + Utilities.getHash(args.join())); const outputFolderOption = isConan2 ? "--output-folder" : "--install-folder"; args = args.concat([outputFolderOption, generatedFilesPath]); var p = new Process(); p.start(executable, args); while (!p.waitForFinished(500)) { const output = isConan2 ? p.readStdErr() : p.readStdOut(); if (verbose && output) { console.info(output); } } while (!p.atEnd()) { const output = isConan2 ? p.readStdErr() : p.readStdOut(); if (verbose && output) { console.info(output); } } if (p.exitCode()) { const errorOutput = p.readStdErr(); p.close(); throw errorOutput; } const output = isConan2 ? p.readStdErr() : p.readStdOut(); if (verbose && output) { console.info(output); } p.close(); if (!isConan2 && generators.contains("json")) { if (!File.exists(generatedFilesPath + "/conanbuildinfo.json")) throw("No conanbuildinfo.json has been generated."); var jsonFile = new TextFile(generatedFilesPath + "/conanbuildinfo.json", TextFile.ReadOnly); json = JSON.parse(jsonFile.readAll()); jsonFile.close(); dependencies = {}; for (var i = 0; i < json.dependencies.length; ++i) { var dep = json.dependencies[i]; dependencies[dep.name] = dep; } } found = true; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/JdkProbe.qbs0000644000175100017510000000443615232633614022324 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.Host import "../../../modules/java/utils.js" as JavaUtils PathProbe { // Inputs property string architecture: !_androidCrossCompiling ? qbs.architecture : undefined property bool _androidCrossCompiling: qbs.targetOS.contains("android") && !Host.os().contains("android") environmentPaths: Environment.getEnv("JAVA_HOME") platformSearchPaths: [ "/usr/lib/jvm/default-java", // Debian/Ubuntu "/etc/alternatives/java_sdk_openjdk", // Fedora "/usr/lib/jvm/default" // Arch ] configure: { path = JavaUtils.findJdkPath(Host.os(), architecture, environmentPaths, platformSearchPaths); found = !!path; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs0000644000175100017510000000412315232633614022767 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.FileInfo import qbs.Host BinaryProbe { names: ["node", "nodejs"] platformSearchPaths: { var paths = base; if (Host.os().contains("windows")) { var env32 = Environment.getEnv("PROGRAMFILES(X86)"); var env64 = Environment.getEnv("PROGRAMFILES"); if (env64 === env32 && env64.endsWith(" (x86)")) env64 = env64.slice(0, -(" (x86)".length)); // QTBUG-3845 paths.push(FileInfo.joinPaths(env64, "nodejs")); paths.push(FileInfo.joinPaths(env32, "nodejs")); } return paths; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/SdccProbe.qbs0000644000175100017510000000613215232633614022463 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/sdcc.js" as SDCC PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage property string preferredArchitecture // Outputs property string architecture property string endianness property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; // SDCC compiler support only the C-language. if (!languages.contains("c")) { found = false; return; } var macros = SDCC.dumpMacros(compilerFilePath, preferredArchitecture); if (!macros) { found = false; return; } compilerDefinesByLanguage["c"] = macros; architecture = SDCC.guessArchitecture(macros); endianness = SDCC.guessEndianness(macros); var defaultPaths = SDCC.dumpDefaultPaths(compilerFilePath, architecture); includePaths = defaultPaths.includePaths; var version = SDCC.guessVersion(macros); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture && !!endianness; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/GccProbe.qbs0000644000175100017510000001131215232633614022277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property var compilerFilePathByLanguage property stringList enableDefinesByLanguage property stringList flags: [] property var environment property string _sysroot: qbs.sysroot property stringList _targetOS: qbs.targetOS // Outputs property string architecture property string endianness property string targetPlatform property stringList includePaths property stringList libraryPaths property stringList frameworkPaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; for (var i = 0; i < languages.length; ++i) { var fp = compilerFilePathByLanguage[languages[i]]; if (fp && File.exists(fp)) { try { compilerDefinesByLanguage[languages[i]] = Gcc.dumpMacros(environment, fp, flags, Host.nullDevice(), languages[i]); } catch (e) { // Only throw errors when determining the compiler defines for the C language; // for other languages we presume it is an indication that the language is not // installed (as is typically the case for Objective-C/C++ on non-Apple systems) if (languages[i] === "c") throw e; } } else if (languages[i] === "c") { found = false; return; } } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"] || compilerDefinesByLanguage["objc"] || compilerDefinesByLanguage["objcpp"]; var defaultPaths = Gcc.dumpDefaultPaths(environment, compilerFilePathByLanguage["cpp"] || compilerFilePathByLanguage["c"], flags, Host.nullDevice(), FileInfo.pathListSeparator(), _sysroot, _targetOS); found = !!macros && !!defaultPaths; includePaths = defaultPaths.includePaths; libraryPaths = defaultPaths.libraryPaths; frameworkPaths = defaultPaths.frameworkPaths; // We have to dump the compiler's macros; -dumpmachine is not suitable because it is not // always complete (for example, the subarch is not included for arm architectures). architecture = ModUtils.guessArchitecture(macros); targetPlatform = ModUtils.guessTargetPlatform(macros); switch (macros["__BYTE_ORDER__"]) { case "__ORDER_BIG_ENDIAN__": endianness = "big"; break; case "__ORDER_LITTLE_ENDIAN__": endianness = "little"; break; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/KeilProbe.qbs0000644000175100017510000000607515232633614022501 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.Host import "../../../modules/cpp/keil.js" as KEIL PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage // Outputs property string architecture property string endianness property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; for (var i = 0; i < languages.length; ++i) { var tag = languages[i]; compilerDefinesByLanguage[tag] = KEIL.dumpMacros( compilerFilePath, tag, Host.nullDevice()); } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"]; architecture = KEIL.guessArchitecture(macros); endianness = KEIL.guessEndianness(macros); var defaultPaths = KEIL.dumpDefaultPaths( compilerFilePath, Host.nullDevice()); includePaths = defaultPaths.includePaths; var version = KEIL.guessVersion(macros); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture && !!endianness; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/ClBinaryProbe.qbs0000644000175100017510000000556315232633614023321 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.Utilities import "path-probe.js" as PathProbeConfigure BinaryProbe { // input property string preferredArchitecture configure: { var _selectors; var results = PathProbeConfigure.configure(_selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); if (!results.found) { var msvcs = Utilities.installedMSVCs(preferredArchitecture); if (msvcs.length >= 1) { var result = {}; result.fileName = "cl.exe"; result.path = msvcs[0].binPath; result.filePath = FileInfo.joinPaths(path, fileName); result.candidatePaths = result.filePath; results.found = true; results.files = [result]; } } found = results.found; allResults = results.files; if (allResults.length === 1) { var result = allResults[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/QmakeProbe.qbs0000644000175100017510000000335315232633614022647 0ustar runnerrunner /**************************************************************************** ** ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "qmake-probe.js" as QmakeProbeConfigure Probe { property stringList qmakePaths property varList qtInfos configure: { qtInfos = QmakeProbeConfigure.configure(qmakePaths); found = qtInfos.length > 0; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs0000644000175100017510000000712215232633614023715 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import "path-probe.js" as PathProbeConfigure import "../../../modules/typescript/typescript.js" as TypeScript BinaryProbe { id: tsc names: ["tsc"] searchPaths: packageManagerBinPath ? [packageManagerBinPath] : [] // Inputs property path interpreterPath property path packageManagerBinPath property path packageManagerRootPath // Outputs property var version configure: { if (!condition) return; if (!interpreterPath) throw '"interpreterPath" must be specified'; if (!packageManagerBinPath) throw '"packageManagerBinPath" must be specified'; if (!packageManagerRootPath) throw '"packageManagerRootPath" must be specified'; var selectors; var results = PathProbeConfigure.configure( selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().contains("windows")); v.prepend(interpreterPath); var resultsMapper = function(result) { result.version = result.found ? TypeScript.findTscVersion(result.filePath, v.value) : undefined; if (FileInfo.fromNativeSeparators(packageManagerBinPath) !== result.path || !File.exists( FileInfo.fromNativeSeparators(packageManagerRootPath, "typescript"))) { result = { found: false }; } return result; }; results.files = results.files.map(resultsMapper); found = results.found; allResults = results.files; var result = results.files[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; version = result.version; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js0000644000175100017510000001201115232633614024353 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var PkgConfig = require("qbs.PkgConfig"); var ProviderUtils = require("qbs.ProviderUtils"); var Process = require("qbs.Process"); function getQmakePaths(pkg) { var packageName = pkg.baseFileName; if (packageName === "QtCore" || packageName === "Qt5Core" || packageName === "Qt6Core") { var binDir = pkg.variables["bindir"] || pkg.variables["host_bins"]; if (!binDir) { if (packageName === "QtCore") { // Qt4 does not have host_bins var mocLocation = pkg.variables["moc_location"]; if (!mocLocation) { console.warn("No moc_location variable in " + packageName); return; } binDir = FileInfo.path(mocLocation); } else { console.warn("No 'bindir' or 'host_bins' variable in " + packageName); return; } } var suffix = FileInfo.executableSuffix(); var ret = []; const infixes = ["", "5", "6"]; for (var index in infixes) { const infix = infixes[index]; var fileName = FileInfo.joinPaths(binDir, "qmake" + infix + suffix); if (File.exists(fileName)) { ret.push(fileName); } } return ret; } } function configure( executableFilePath, extraPaths, libDirs, staticMode, definePrefix, sysroot) { var result = {}; result.packages = []; result.packagesByModuleName = {}; result.brokenPackages = []; result.qtInfos = []; var options = {}; options.libDirs = libDirs; options.sysroot = sysroot; options.definePrefix = definePrefix; if (options.sysroot) options.allowSystemLibraryPaths = true; options.staticMode = staticMode; options.extraPaths = extraPaths; if (options.sysroot && !options.libDirs) { options.libDirs = [ options.sysroot + "/usr/lib/pkgconfig", options.sysroot + "/usr/share/pkgconfig" ]; } if (!options.libDirs) { // if we have pkg-config/pkgconf installed, let's ask it for its search paths (since // built-in search paths can differ between platforms) if (executableFilePath) { var p = new Process() if (p.exec(executableFilePath, ['pkg-config', '--variable=pc_path']) === 0) { var stdout = p.readStdOut().trim(); options.libDirs = stdout ? stdout.split(FileInfo.pathListSeparator()): []; var installDir = FileInfo.path(executableFilePath); options.libDirs = options.libDirs.map(function(path){ if (FileInfo.isAbsolutePath(path)) return path; return FileInfo.cleanPath(FileInfo.joinPaths(installDir, path)); }); } } } var pkgConfig = new PkgConfig(options); result.packages = pkgConfig.packages(); for (var packageName in result.packages) { var pkg = result.packages[packageName]; var moduleName = ProviderUtils.pkgConfigToModuleName(packageName); result.packagesByModuleName[moduleName] = pkg; if (packageName.startsWith("Qt")) { if (!sysroot) { var qmakePaths = getQmakePaths(pkg); if (qmakePaths !== undefined) result.qmakePaths = qmakePaths; } } } return result; } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/CosmicProbe.qbs0000644000175100017510000000610115232633614023020 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/cosmic.js" as COSMIC PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage // Outputs property string architecture property string endianness property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; // COSMIC compiler support only the C-language. if (!languages.contains("c")) { found = false; return; } var macros = COSMIC.dumpMacros(compilerFilePath); if (!macros) { found = false; return; } compilerDefinesByLanguage["c"] = macros; architecture = COSMIC.guessArchitecture(compilerFilePath); endianness = COSMIC.guessEndianness(architecture); var defaultPaths = COSMIC.dumpDefaultPaths(compilerFilePath, architecture); includePaths = defaultPaths.includePaths; var version = COSMIC.dumpVersion(compilerFilePath); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture && !!endianness; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/JdkVersionProbe.qbs0000644000175100017510000000333615232633614023670 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "../../../modules/java/utils.js" as JavaUtils Probe { // Inputs property string javac // Outputs property var version configure: { version = JavaUtils.findJdkVersion(javac); found = !!version; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/ClangClBinaryProbe.qbs0000644000175100017510000000603615232633614024262 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.Utilities import "path-probe.js" as PathProbeConfigure BinaryProbe { // output property string vcvarsallPath configure: { var _selectors; var results = PathProbeConfigure.configure(_selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); var compilerPath; if (results.found) compilerPath = results.files[0].filePath; var compilers = Utilities.installedClangCls(compilerPath); if (compilers.length >= 1) { var result = {}; result.fileName = "clang-cl.exe"; result.path = compilers[0].toolchainInstallPath; result.filePath = FileInfo.joinPaths(result.path, result.fileName); result.candidatePaths = result.filePath; result.vcvarsallPath = compilers[0].vcvarsallPath; results.found = true; results.files = [result]; } found = results.found; allResults = results.files; if (allResults.length === 1) { var result = allResults[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; vcvarsallPath = result.vcvarsallPath; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/DmcProbe.qbs0000644000175100017510000000675015232633614022320 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.ModUtils import "../../../modules/cpp/dmc.js" as DMC PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage property string _targetPlatform property string _targetArchitecture property string _targetExtender // Only for DOS 16/32 bit. // Outputs property string architecture property string targetPlatform property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; var defaultPathsByLanguage = {}; for (var i = 0; i < languages.length; ++i) { var tag = languages[i]; compilerDefinesByLanguage[tag] = DMC.dumpMacros( compilerFilePath, _targetPlatform, _targetArchitecture, _targetExtender, tag); var paths = DMC.dumpDefaultPaths(compilerFilePath, tag); defaultPathsByLanguage[tag] = paths; } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"]; architecture = ModUtils.guessArchitecture(macros); targetPlatform = ModUtils.guessTargetPlatform(macros); var defaultPaths = defaultPathsByLanguage["cpp"] || defaultPathsByLanguage["c"]; includePaths = defaultPaths.includePaths; var version = DMC.guessVersion(macros); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs0000644000175100017510000000526115232633614023452 0ustar runnerrunnerimport qbs.Environment import qbs.FileInfo import qbs.Host import "path-probe.js" as PathProbeConfigure BinaryProbe { nameSuffixes: undefined // _compilerName already contains ".exe" suffix on Windows // Inputs property string _compilerName property string _toolchainPrefix // Outputs property string tcPrefix platformSearchPaths: { var paths = base; if (qbs.targetOS.contains("windows") && Host.os().contains("windows")) paths.push(FileInfo.joinPaths( Environment.getEnv("SystemDrive"), "MinGW", "bin")); return paths; } names: { var prefixes = []; if (_toolchainPrefix) { prefixes.push(_toolchainPrefix); } else { var arch = qbs.architecture; if (qbs.targetOS.contains("windows")) { if (!arch || arch === "x86") { prefixes.push("mingw32-", "i686-w64-mingw32-", "i686-w64-mingw32.shared-", "i686-w64-mingw32.static-", "i686-mingw32-", "i586-mingw32msvc-"); } if (!arch || arch === "x86_64") { prefixes.push("x86_64-w64-mingw32-", "x86_64-w64-mingw32.shared-", "x86_64-w64-mingw32.static-", "amd64-mingw32msvc-"); } } } return prefixes.map(function(prefix) { return prefix + _compilerName; }).concat([_compilerName]); } configure: { var selectors; var results = PathProbeConfigure.configure( selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); found = results.found; if (!found) return; var resultsMapper = function(result) { (nameSuffixes || [""]).forEach(function(suffix) { var end = _compilerName + suffix; if (result.fileName.endsWith(end)) result.tcPrefix = result.fileName.slice(0, -end.length); }); return result; }; results.files = results.files.map(resultsMapper); allResults = results.files; var result = results.files[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; tcPrefix = result.tcPrefix; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs0000644000175100017510000000504615232633614023654 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.Host import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property string compilerFilePath property var environment property stringList _toolchain: qbs.toolchain // Outputs property int versionMajor property int versionMinor property int versionPatch configure: { if (!File.exists(compilerFilePath)) { found = false; return; } var macros = Gcc.dumpMacros(environment, compilerFilePath, undefined, Host.nullDevice()); if (_toolchain.contains("clang")) { versionMajor = parseInt(macros["__clang_major__"], 10); versionMinor = parseInt(macros["__clang_minor__"], 10); versionPatch = parseInt(macros["__clang_patchlevel__"], 10); found = true; } else { versionMajor = parseInt(macros["__GNUC__"], 10); versionMinor = parseInt(macros["__GNUC_MINOR__"], 10); versionPatch = parseInt(macros["__GNUC_PATCHLEVEL__"], 10); found = true; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/WiXProbe.qbs0000644000175100017510000000563715232633614022327 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities PathProbe { // Inputs property string registryKey: { var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML" ]; for (var i in keys) { var groups = Utilities.nativeSettingGroups(keys[i]).filter(function (v) { return v.match(/^([0-9]+)\.([0-9]+)$/); }); groups.sort(function (a, b) { var re = /^([0-9]+)\.([0-9]+)$/; a = a.match(re); b = b.match(re); a = {major: a[1], minor: a[2]}; b = {major: b[1], minor: b[2]}; if (a.major === b.major) return b.minor - a.minor; return b.major - a.major; }); for (var j in groups) { var fullKey = keys[i] + "\\" + groups[j]; if (Utilities.getNativeSetting(fullKey, "ProductVersion")) return fullKey; } } } // Outputs property var root property var version configure: { var key = registryKey; path = Utilities.getNativeSetting(key, "InstallFolder"); root = Utilities.getNativeSetting(key, "InstallRoot"); version = Utilities.getNativeSetting(key, "ProductVersion"); found = path && root && version; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/path-probe.js0000644000175100017510000001370215232633614022510 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function asStringList(key, value) { if (typeof(value) === "string") return [value]; if (value instanceof Array) return value; throw key + " must be a string or a stringList"; } function canonicalSelectors(selectors, nameSuffixes) { var mapper = function(selector) { if (typeof(selector) === "string") return {names : [selector]}; if (selector instanceof Array) return {names : selector}; // dict if (!selector.names) throw '"names" must be specified'; selector.names = asStringList("names", selector.names); if (selector.nameSuffixes) selector.nameSuffixes = asStringList("nameSuffixes", selector.nameSuffixes); else selector.nameSuffixes = nameSuffixes; return selector; }; return selectors.map(mapper); } function pathsFromEnvs(envs, pathListSeparator) { envs = envs || []; var result = []; for (var i = 0; i < envs.length; ++i) { var value = Environment.getEnv(envs[i]) || ''; if (value.length > 0) result = result.concat(value.split(pathListSeparator)); } return result; } function configure(selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths) { var result = { found: false, files: [] }; if (!selectors && !names) throw '"names" or "selectors" must be specified'; if (!selectors) { selectors = [ {names: names, nameSuffixes: nameSuffixes} ]; } else { selectors = canonicalSelectors(selectors, nameSuffixes); } if (nameFilter) { selectors.forEach(function(selector) { selector.names = ModUtils.concatAll.apply(undefined, selector.names.map(nameFilter)); }); } selectors.forEach(function(selector) { selector.names = ModUtils.concatAll.apply(undefined, selector.names.map(function(name) { return (selector.nameSuffixes || [""]).map(function(suffix) { return name + suffix; }); })); }); // FIXME: Suggest how to obtain paths from system var _paths = ModUtils.concatAll( pathsFromEnvs(environmentPaths, FileInfo.pathListSeparator()), searchPaths, pathsFromEnvs(platformEnvironmentPaths, FileInfo.pathListSeparator()), platformSearchPaths); var _suffixes = ModUtils.concatAll('', pathSuffixes); _paths = _paths.map(function(p) { return FileInfo.fromNativeSeparators(p); }); _suffixes = _suffixes.map(function(p) { return FileInfo.fromNativeSeparators(p); }); var findFile = function(selector) { var file = { found: false, candidatePaths: [] }; for (var i = 0; i < selector.names.length; ++i) { for (var j = 0; j < _paths.length; ++j) { for (var k = 0; k < _suffixes.length; ++k) { var _filePath = FileInfo.joinPaths(_paths[j], _suffixes[k], selector.names[i]); file.candidatePaths.push(_filePath); if (File.exists(_filePath) && (!candidateFilter || candidateFilter(_filePath))) { file.found = true; file.filePath = _filePath; // Manually specify the path components that constitute _filePath rather // than using the FileInfo.path and FileInfo.fileName functions because we // want to break _filePath into its constituent parts based on the input // originally given by the user. For example, the FileInfo functions would // produce a different result if any of the items in the names property // contained more than a single path component. file.fileName = selector.names[i]; file.path = FileInfo.joinPaths(_paths[j], _suffixes[k]); return file; } } } } return file; }; result.files = selectors.map(findFile); result.found = result.files.reduce(function(acc, value) { return acc && value.found }, true); return result; } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs0000644000175100017510000001365715232633614023470 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Host import qbs.Process import qbs.FileInfo Probe { // Inputs property string sysroot: qbs.sysroot property string executable: 'pkg-config' property string name property stringList packageNames: [name] property string minVersion property string exactVersion property string maxVersion property bool forStaticBuild: false property stringList libDirs // Full, non-sysrooted paths, mirroring the environment variable // Output property stringList cflags // Unmodified --cflags output property stringList libs // Unmodified --libs output property stringList defines property stringList libraries property stringList libraryPaths property stringList includePaths property stringList compilerFlags property stringList linkerFlags property string modversion configure: { if (!packageNames || packageNames.length === 0) throw 'PkgConfigProbe.packageNames must be specified.'; var p = new Process(); var stdout; try { var libDirsToSet = libDirs; if (sysroot) { p.setEnv("PKG_CONFIG_SYSROOT_DIR", sysroot); if (!libDirsToSet) { libDirsToSet = [ sysroot + "/usr/lib/pkgconfig", sysroot + "/usr/share/pkgconfig" ]; } } if (libDirsToSet) p.setEnv("PKG_CONFIG_LIBDIR", libDirsToSet.join(FileInfo.pathListSeparator())); var versionArgs = []; if (minVersion !== undefined) versionArgs.push("--atleast-version=" + minVersion); if (exactVersion !== undefined) versionArgs.push("--exact-version=" + exactVersion); if (maxVersion !== undefined) versionArgs.push("--max-version=" + maxVersion); if (versionArgs.length !== 0 && p.exec(executable, versionArgs.concat(packageNames)) !== 0) { return; } // protobuf is reserved as qbs module name, which depends on the protobuflib module packageNames = packageNames.map(function(name) { return name === "protobuflib" ? "protobuf" : name; }); var args = packageNames; if (p.exec(executable, args.concat([ '--cflags' ])) === 0) { stdout = p.readStdOut().trim(); cflags = stdout ? stdout.split(/\s/): []; var libsArgs = args.concat("--libs"); if (forStaticBuild) libsArgs.push("--static"); if (p.exec(executable, libsArgs) === 0) { stdout = p.readStdOut().trim(); libs = stdout ? stdout.split(/\s/): []; if (p.exec(executable, [packageNames[0]].concat([ '--modversion' ])) === 0) { modversion = p.readStdOut().trim(); found = true; includePaths = []; defines = [] compilerFlags = []; for (var i = 0; i < cflags.length; ++i) { var flag = cflags[i]; if (flag.startsWith("-I")) includePaths.push(flag.slice(2)); else if (flag.startsWith("-D")) defines.push(flag.slice(2)); else compilerFlags.push(flag); } libraries = []; libraryPaths = []; linkerFlags = []; for (i = 0; i < libs.length; ++i) { flag = libs[i]; if (flag.startsWith("-l")) libraries.push(flag.slice(2)); else if (flag.startsWith("-L")) libraryPaths.push(flag.slice(2)); else linkerFlags.push(flag); } console.debug("PkgConfigProbe: found packages " + packageNames); return; } } } found = false; cflags = undefined; libs = undefined; } finally { p.close(); } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/LibraryProbe.qbs0000644000175100017510000000635715232633614023224 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.PathTools PathProbe { property string endianness nameSuffixes: PathTools.librarySuffixes(qbs.targetOS, ["shared", "static"], true) platformSearchPaths: { var result = []; if (qbs.targetOS.contains("unix")) { if (qbs.targetOS.contains("linux") && qbs.architecture) { if (qbs.architecture === "armv7") result = ["/usr/lib/arm-linux-gnueabihf"] else if (qbs.architecture === "arm64") result = ["/usr/lib/aarch64-linux-gnu"] else if (qbs.architecture === "mips" && endianness === "big") result = ["/usr/lib/mips-linux-gnu"] else if (qbs.architecture === "mips" && endianness === "little") result = ["/usr/lib/mipsel-linux-gnu"] else if (qbs.architecture === "mips64") result = ["/usr/lib/mips64el-linux-gnuabi64"] else if (qbs.architecture === "ppc") result = ["/usr/lib/powerpc-linux-gnu"] else if (qbs.architecture === "ppc64") result = ["/usr/lib/powerpc64le-linux-gnu"] else if (qbs.architecture === "x86_64") result = ["/usr/lib64", "/usr/lib/x86_64-linux-gnu"] else if (qbs.architecture === "x86") result = ["/usr/lib32", "/usr/lib/i386-linux-gnu"] } result = result.concat(["/usr/lib", "/usr/local/lib", "/lib", "/app/lib"]); } return result; } nameFilter: PathTools.libraryNameFilter() platformEnvironmentPaths: { if (qbs.targetOS.contains("windows")) return [ "PATH" ]; else return [ "LIBRARY_PATH" ]; } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/BinaryProbe.qbs0000644000175100017510000000335015232633614023032 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Host PathProbe { nameSuffixes: Host.os().contains("windows") ? [".com", ".exe", ".bat", ".cmd"] : undefined platformSearchPaths: Host.os().contains("unix") ? ["/usr/bin", "/usr/local/bin"] : [] platformEnvironmentPaths: [ "PATH" ] } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/WatcomProbe.qbs0000644000175100017510000000716415232633614023047 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.Host import qbs.ModUtils import "../../../modules/cpp/watcom.js" as WATCOM PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage property string _pathListSeparator property string _toolchainInstallPath property string _targetPlatform property string _targetArchitecture // Outputs property string architecture property string endianness property string targetPlatform property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var compilerDefinesByLanguage property var environment configure: { compilerDefinesByLanguage = {}; if (!File.exists(compilerFilePath)) { found = false; return; } var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; environment = WATCOM.guessEnvironment(Host.os(), _targetPlatform, _targetArchitecture, _toolchainInstallPath, _pathListSeparator); includePaths = environment["INCLUDE"].split(_pathListSeparator).filter(function(path) { return File.exists(path); }); for (var i = 0; i < languages.length; ++i) { var tag = languages[i]; compilerDefinesByLanguage[tag] = WATCOM.dumpMacros( environment, compilerFilePath, _targetPlatform, _targetArchitecture, tag); } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"]; endianness = macros["__BIG_ENDIAN"] ? "big" : "little"; architecture = ModUtils.guessArchitecture(macros); targetPlatform = ModUtils.guessTargetPlatform(macros); var version = WATCOM.guessVersion(macros); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; found = !!architecture && !!targetPlatform; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/MsvcProbe.qbs0000644000175100017510000001012315232633614022512 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Utilities PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage property string preferredArchitecture property string winSdkVersion // Outputs property string architecture property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property string modulesPath property var buildEnv property var compilerDefinesByLanguage configure: { var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; var info = languages.contains("c") ? Utilities.msvcCompilerInfo(compilerFilePath, "c", winSdkVersion) : {}; var infoCpp = languages.contains("cpp") ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp", winSdkVersion) : {}; found = (!languages.contains("c") || (!!info && !!info.macros && !!info.buildEnvironment)) && (!languages.contains("cpp") || (!!infoCpp && !!infoCpp.macros && !!infoCpp.buildEnvironment)); compilerDefinesByLanguage = { "c": info.macros, "cpp": infoCpp.macros, }; var macros = info.macros || infoCpp.macros; architecture = ModUtils.guessArchitecture(macros); var ver = macros["_MSC_FULL_VER"]; versionMajor = parseInt(ver.substr(0, 2), 10); versionMinor = parseInt(ver.substr(2, 2), 10); versionPatch = parseInt(ver.substr(4), 10); buildEnv = info.buildEnvironment || infoCpp.buildEnvironment; var clParentDir = FileInfo.joinPaths(FileInfo.path(compilerFilePath), ".."); var inclPath = FileInfo.joinPaths(clParentDir, "INCLUDE"); if (!File.exists(inclPath)) inclPath = FileInfo.joinPaths(clParentDir, "..", "INCLUDE"); if (!File.exists(inclPath)) inclPath = FileInfo.joinPaths(clParentDir, "..", "..", "INCLUDE"); if (File.exists(inclPath)) includePaths = [inclPath]; var modsPath = FileInfo.joinPaths(clParentDir, "..", "..", "modules"); if (File.exists(modsPath)) modulesPath = modsPath; if (preferredArchitecture && Utilities.canonicalArchitecture(preferredArchitecture) !== Utilities.canonicalArchitecture(architecture)) { throw "'" + preferredArchitecture + "' differs from the architecture produced by this compiler (" + architecture + ")"; } } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/ClangClProbe.qbs0000644000175100017510000001001415232633614023104 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Utilities import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property string compilerFilePath property string vcvarsallFilePath property stringList enableDefinesByLanguage property string preferredArchitecture property string winSdkVersion // Outputs property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property string architecture property var buildEnv property var compilerDefinesByLanguage configure: { var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; var info = languages.contains("c") ? Utilities.clangClCompilerInfo( compilerFilePath, preferredArchitecture, vcvarsallFilePath, "c", winSdkVersion) : {}; var infoCpp = languages.contains("cpp") ? Utilities.clangClCompilerInfo( compilerFilePath, preferredArchitecture, vcvarsallFilePath, "cpp", winSdkVersion) : {}; found = (!languages.contains("c") || (!!info && !!info.macros && !!info.buildEnvironment)) && (!languages.contains("cpp") || (!!infoCpp && !!infoCpp.macros && !!infoCpp.buildEnvironment)); compilerDefinesByLanguage = { "c": info.macros, "cpp": infoCpp.macros, }; var macros = info.macros || infoCpp.macros; versionMajor = parseInt(macros["__clang_major__"], 10); versionMinor = parseInt(macros["__clang_minor__"], 10); versionPatch = parseInt(macros["__clang_patchlevel__"], 10); buildEnv = info.buildEnvironment || infoCpp.buildEnvironment; // clang-cl is just a wrapper around clang.exe, so the includes *should be* the same var clangPath = FileInfo.joinPaths(FileInfo.path(compilerFilePath), "clang.exe"); var defaultPaths = Gcc.dumpDefaultPaths(buildEnv, clangPath, [], Host.nullDevice(), FileInfo.pathListSeparator(), "", ""); includePaths = defaultPaths.includePaths; architecture = ModUtils.guessArchitecture(macros); } } qbs-src-3.3.1/share/qbs/imports/qbs/Probes/PathProbe.qbs0000644000175100017510000000553615232633614022512 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "path-probe.js" as PathProbeConfigure import qbs.Host import qbs.ModUtils Probe { // Inputs property stringList names property stringList nameSuffixes property var nameFilter property var candidateFilter property varList selectors property pathList searchPaths property stringList pathSuffixes property pathList platformSearchPaths: Host.os().contains("unix") ? ['/usr', '/usr/local'] : [] property stringList environmentPaths property stringList platformEnvironmentPaths // Output property stringList candidatePaths property string path property string filePath property string fileName property varList allResults configure: { var results = PathProbeConfigure.configure(selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths); found = results.found; allResults = results.files; if (allResults.length === 1) { var result = allResults[0]; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; } } } qbs-src-3.3.1/share/qbs/imports/qbs/PathTools/0000755000175100017510000000000015232633614020571 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/PathTools/path-tools.js0000644000175100017510000002473115232633614023230 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function _bundleExecutableTemporaryFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; return ".tmp/" + FileInfo.fileName(bundleExecutableFilePath(product, variantSuffix)); } function bundleExecutableFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; return product.moduleProperty("bundle", "executablePath") + (variantSuffix || ""); } function applicationFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "executablePrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "executableSuffix"); } function loadableModuleFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "loadableModulePrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "loadableModuleSuffix"); } function staticLibraryFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "staticLibraryPrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "staticLibrarySuffix"); } function dynamicLibraryFilePath(product, variantSuffix, version, maxParts) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); // If no override version was given, use the product's version // We specifically want to differentiate between undefined and i.e. // empty string as empty string should be taken to mean "no version" // and undefined should be taken to mean "use the product's version" // (which could still end up being "no version") if (version === undefined) version = product.moduleProperty("cpp", "internalVersion"); // If we have a version number, potentially strip off some components if (maxParts === 0) version = undefined; else if (maxParts && version) version = version.split('.').slice(0, maxParts).join('.'); // Start with prefix + name (i.e. libqbs, qbs) var fileName = product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName + (variantSuffix || ""); // For Mach-O images, append the version number if there is one (i.e. libqbs.1.0.0) var imageFormat = product.moduleProperty("cpp", "imageFormat"); if (version && imageFormat === "macho") { fileName += "." + version; version = undefined; } fileName += product.moduleProperty("cpp", "archSuffix"); // Append the suffix (i.e. libqbs.1.0.0.dylib, libqbs.so, qbs.dll) fileName += product.moduleProperty("cpp", "dynamicLibrarySuffix"); // For ELF images, append the version number if there is one (i.e. libqbs.so.1.0.0) if (version && (imageFormat === "elf" || imageFormat === "wasm")) fileName += "." + version; return fileName; } function linkerOutputFilePath(fileTag, product, variantSuffix, version, maxParts) { switch (fileTag) { case "application": return applicationFilePath(product, variantSuffix); case "loadablemodule": return loadableModuleFilePath(product, variantSuffix); case "staticlibrary": return staticLibraryFilePath(product, variantSuffix); case "dynamiclibrary": return dynamicLibraryFilePath(product, variantSuffix, version, maxParts); default: throw new Error("Unknown linker output file tag: " + fileTag); } } function importLibraryFilePath(product) { return product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName + (product.cpp.variantSuffix || "") + product.moduleProperty("cpp", "dynamicLibraryImportSuffix"); } function debugInfoIsBundle(product) { if (!product.moduleProperty("qbs", "targetOS").contains("darwin")) return false; var flags = product.moduleProperty("cpp", "dsymutilFlags") || []; return !flags.contains("-f") && !flags.contains("--flat"); } function debugInfoFileName(product, variantSuffix, fileTag) { var suffix = ""; // For dSYM bundles, the DWARF debug info file has no suffix if (!product.moduleProperty("qbs", "targetOS").contains("darwin") || !debugInfoIsBundle(product)) suffix = product.moduleProperty("cpp", "debugInfoSuffix"); if (product.qbs.toolchain.includes("emscripten")) return product.targetName + ".wasm.debug.wasm"; if (product.moduleProperty("bundle", "isBundle")) { return FileInfo.fileName(bundleExecutableFilePath(product, variantSuffix)) + suffix; } else { switch (fileTag) { case "application": return applicationFilePath(product, variantSuffix) + suffix; case "dynamiclibrary": return dynamicLibraryFilePath(product, variantSuffix) + suffix; case "loadablemodule": return loadableModuleFilePath(product, variantSuffix) + suffix; case "staticlibrary": return staticLibraryFilePath(product, variantSuffix) + suffix; default: return product.targetName + (variantSuffix || "") + suffix; } } } function debugInfoBundlePath(product, fileTag) { if (!debugInfoIsBundle(product)) return undefined; var suffix = product.moduleProperty("cpp", "debugInfoBundleSuffix"); if (product.moduleProperty("qbs", "targetOS").contains("darwin") && product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "bundleName") + suffix; return debugInfoFileName(product, undefined, fileTag) + suffix; } function debugInfoFilePath(product, variantSuffix, fileTag) { var name = debugInfoFileName(product, variantSuffix, fileTag); if (product.moduleProperty("qbs", "targetOS").contains("darwin") && debugInfoIsBundle(product)) { return FileInfo.joinPaths(debugInfoBundlePath(product, fileTag), "Contents", "Resources", "DWARF", name); } else if (product.moduleProperty("bundle", "isBundle")) { return FileInfo.joinPaths(product.moduleProperty("bundle", "executableFolderPath"), name); } return name; } function debugInfoPlistFilePath(product, fileTag) { if (!debugInfoIsBundle(product)) return undefined; return FileInfo.joinPaths(debugInfoBundlePath(product, fileTag), "Contents", "Info.plist"); } // Returns whether the string looks like a library filename function isLibraryFileName(product, fileName, prefix, suffixes, isShared) { var suffix, i; var os = product.moduleProperty("qbs", "targetOS"); for (i = 0; i < suffixes.length; ++i) { suffix = suffixes[i]; if (isShared && os.contains("unix") && !os.contains("darwin")) suffix += "(\\.[0-9]+){0,3}"; if (fileName.match("^" + prefix + ".+?\\" + suffix + "$")) return true; } return false; } function frameworkExecutablePath(frameworkPath) { var suffix = ".framework"; var isAbsoluteFrameworkPath = frameworkPath.slice(-suffix.length) === suffix; if (isAbsoluteFrameworkPath) { var frameworkName = FileInfo.fileName(frameworkPath).slice(0, -suffix.length); return FileInfo.joinPaths(frameworkPath, frameworkName); } return undefined; } // pathList is also a string, using the respective separator function prependOrSetPath(path, pathList, separator) { if (!pathList || pathList.length === 0) return path; return path + separator + pathList; } function librarySuffixes(targetOS, types, forImport) { if (targetOS.includes("windows")) { if (forImport) { return [] .concat(types.includes("shared") ? [".lib"] : []) // mingw uses .a for static libs .concat(types.includes("static") ? [".lib", ".a"] : []); } return [].concat(types.includes("shared") ? [".dll"] : []); } if (targetOS.includes("darwin")) { return [] .concat(types.includes("shared") ? [".dylib"] : []) .concat(types.includes("static") ? [".a"] : []); } return [] .concat(types.includes("shared") ? [".so"] : []) .concat(types.includes("static") ? [".a"] : []); } function libraryNameFilter() { return function(name) { return [name, "lib" + name]; } } qbs-src-3.3.1/share/qbs/imports/qbs/UnixUtils/0000755000175100017510000000000015232633614020620 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/UnixUtils/unix-utils.js0000644000175100017510000000533015232633614023300 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function soname(product, outputFileName) { var soVersion = product.moduleProperty("cpp", "soVersion"); if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { // If this is a bundle, ignore the parameter and use the relative path to the bundle binary // For example: qbs.framework/Versions/1/qbs if (product.moduleProperty("bundle", "isBundle")) outputFileName = product.moduleProperty("bundle", "executablePath"); } else if (soVersion) { // For non-Darwin platforms, append the shared library major version number to the soname // For example: libqbscore.so.1 var version = product.moduleProperty("cpp", "internalVersion"); if (version) { outputFileName = outputFileName.substr(0, outputFileName.length - version.length) + soVersion; } else { outputFileName += "." + soVersion; } } // Prepend the soname prefix // For example, @rpath/libqbscore.dylib or /usr/lib/libqbscore.so.1 var prefix = product.moduleProperty("cpp", "sonamePrefix"); if (prefix) outputFileName = FileInfo.joinPaths(prefix, outputFileName); return outputFileName; } qbs-src-3.3.1/share/qbs/imports/qbs/DarwinTools/0000755000175100017510000000000015232633614021121 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/DarwinTools/darwin-tools.js0000644000175100017510000002355215232633614024110 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var Utilities = require("qbs.Utilities"); var _deviceMap = { "mac": undefined, // only devices have an ID "iphone": 1, "ipad": 2, "tv": 3, "watch": 4, "car": 5 }; var _platformMap = { "ios": "iPhone", "macos": "MacOSX", "tvos": "AppleTV", "watchos": "Watch" }; var _platformDeviceMap = { "ios": ["iphone", "ipad"], "macos": ["mac"], "tvos": ["tv"], "watchos": ["watch"] } /** * Returns the numeric identifier corresponding to an Apple device name * (i.e. for use by TARGETED_DEVICE_FAMILY). */ function appleDeviceNumber(deviceName) { return _deviceMap[deviceName]; } /** * Returns the list of target devices available for the given qbs target OS list. */ function targetDevices(targetOS) { for (var key in _platformDeviceMap) { if (targetOS.contains(key)) return _platformDeviceMap[key]; } } /** * Returns the TARGETED_DEVICE_FAMILY string given a list of target device names. */ function targetedDeviceFamily(deviceNames) { return deviceNames.map(function (deviceName) { return appleDeviceNumber(deviceName); }); } /** * Returns the most appropriate Apple platform name given a targetOS list. */ function applePlatformName(targetOSList, platformType) { return applePlatformDirectoryName(targetOSList, platformType).toLowerCase(); } /** * Returns the most appropriate Apple platform directory name given a targetOS list and version. */ function applePlatformDirectoryName(targetOSList, platformType, version, throwOnError) { var suffixMap = { "device": "OS", "simulator": "Simulator" }; for (var key in _platformMap) { if (targetOSList.contains(key)) { // there are no MacOSXOS or MacOSXSimulator platforms var suffix = (key !== "macos") ? (suffixMap[platformType] || "") : ""; return _platformMap[key] + suffix + (version || ""); } } if (throwOnError || throwOnError === undefined) throw("No Apple platform corresponds to target OS list: " + targetOSList); } /** * Returns the localization of the resource at the given path, * or undefined if the path does not contain an {xx}.lproj path segment. */ function localizationKey(path) { return _resourceFileProperties(path)[0]; } /** * Returns the path of a localized resource at the given path, * relative to its containing {xx}.lproj directory, or '.' * if the resource is unlocalized (not contained in an lproj directory). */ function relativeResourcePath(path) { return _resourceFileProperties(path)[1]; } function _resourceFileProperties(path) { var lprojKey = ".lproj/"; var lproj = path.indexOf(lprojKey); if (lproj >= 0) { // The slash preceding XX.lproj var slashIndex = path.slice(0, lproj).lastIndexOf('/'); if (slashIndex >= 0) { var localizationKey = path.slice(slashIndex + 1, lproj); var relativeResourcePath = FileInfo.path(path.slice(lproj + lprojKey.length)); return [ localizationKey, relativeResourcePath ]; } } return [ undefined, '.' ]; } var PropertyListVariableExpander = (function () { function PropertyListVariableExpander() { } /** * Recursively perform variable replacements in an environment dictionary. */ PropertyListVariableExpander.prototype.expand = function (obj, env) { var $this = this; // Possible syntaxes for wrapping an environment variable name var syntaxes = [ {"open": "${", "close": "}"}, {"open": "$(", "close": ")"}, {"open": "@", "close": "@"} ]; /** * Finds the first index of a replacement starting with one of the supported syntaxes * This is needed so we don't do recursive substitutions */ function indexOfReplacementStart(syntaxes, str) { var syntax; var idx = -1; for (var i in syntaxes) { var j; // normal case - we search for the last occurrence to do a correct replacement // for nested variables, e.g. ${VAR1_${VAR2}}. This doesn't work in case // when start == end, e.g. @VAR@ - in that case we search from the start if (syntaxes[i].open !== syntaxes[i].close) j = str.lastIndexOf(syntaxes[i].open); else j = str.indexOf(syntaxes[i].open); if (j > idx) { syntax = syntaxes[i]; idx = j; } } return { "syntax": syntax, "index": idx }; } function expandString(key, str, env, seenVars) { if (!str) return str; var repl = indexOfReplacementStart(syntaxes, str); var i = repl.index; while (i !== -1) { var j = str.indexOf(repl.syntax.close, i + repl.syntax.open.length); if (j === -1) return str; var varParts = str.slice(i + repl.syntax.open.length, j).split(':'); var varName = varParts[0]; var varFormatter = varParts[1]; var envValue = env[varName]; // if we end up expanding the same variable again, break the recursion if (seenVars.indexOf(varName) !== -1) envValue = ""; else seenVars.push(varName); var varValue = expandString(key, envValue, env, seenVars); seenVars.pop(); if (undefined === varValue) { // skip replacement if ($this.undefinedVariableFunction) $this.undefinedVariableFunction(key, varName); varValue = ""; } varValue = String(varValue); if (varFormatter !== undefined) { // TODO: XCode supports multiple formatters separated by a comma var varFormatterLower = varFormatter.toLowerCase(); if (varFormatterLower === "rfc1034identifier" || varFormatterLower === "identifier") varValue = Utilities.rfc1034Identifier(varValue); if (varValue === "" && varFormatterLower.startsWith("default=")) varValue = varFormatter.split("=")[1]; } str = str.slice(0, i) + varValue + str.slice(j + repl.syntax.close.length); repl = indexOfReplacementStart(syntaxes, str); i = repl.index; } return str; } function expandRecursive(obj, env, checked) { checked.push(obj); for (var key in obj) { var value = obj[key]; var type = typeof(value); if (type === "object") { if (checked.indexOf(value) !== -1) continue; expandRecursive(value, env, checked); } if (type !== "string") continue; var expandedValue = expandString(key, value, env, []); if (expandedValue !== value) obj[key] = expandedValue; } } expandRecursive(obj, env, []); return obj; }; return PropertyListVariableExpander; }()); /** * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}}, * {x:"X",y:"Y"}, true)) * Warning undefined variable k in variable expansion * => {"a":"X3$Y","b":{"t":"%Y $(k)"}} */ function expandPlistEnvironmentVariables(obj, env, warn) { var expander = new PropertyListVariableExpander(); expander.undefinedVariableFunction = function (key, varName) { if (warn) console.warn("undefined variable " + varName + " in variable expansion"); }; return expander.expand(obj, env); } /** * Recursively removes any undefined, null, or empty string values from the property list. */ function cleanPropertyList(plist) { if (typeof(plist) !== "object") return; for (var key in plist) { if (plist[key] === undefined || plist[key] === null || plist[key] === "") delete plist[key]; else cleanPropertyList(plist[key]); } } qbs-src-3.3.1/share/qbs/imports/qbs/ModUtils/0000755000175100017510000000000015232633614020414 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/ModUtils/utils.js0000644000175100017510000006320715232633614022122 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function mergeCFiles(inputs, outputFilePath) { var f = new TextFile(outputFilePath, TextFile.WriteOnly); try { for (var i = 0; i < inputs.length; ++i) f.writeLine('#include ' + Utilities.cStringQuote(inputs[i].filePath)); } finally { f.close(); } } function sanitizedList(list, product, fullPropertyName) { if (!(list instanceof Array)) return list; var filterFunc = function(elem) { if (typeof elem === "string" && elem.length === 0) { var msg = "Removing empty string from value of property '" + fullPropertyName + "'"; // product might actually be a module if (product.name) msg += " in product '" + product.name + "'."; console.warn(msg); return false; } return true; } return list.filter(filterFunc); } function checkCompatibilityMode(project, minimumQbsVersion, message) { if (Utilities.versionCompare(project.minimumQbsVersion || "1.3", minimumQbsVersion) < 0) { console.warn([message || "", "This message can be silenced by setting your Project's " + "minimumQbsVersion to " + minimumQbsVersion + " (and the new behavior will take effect)."].join(" ")); return true; } return false; } function artifactInstalledFilePath(artifact) { var relativeInstallDir = artifact.moduleProperty("qbs", "installDir"); var installPrefix = artifact.moduleProperty("qbs", "installPrefix"); var installSourceBase = artifact.moduleProperty("qbs", "installSourceBase"); var targetDir = FileInfo.joinPaths(artifact.moduleProperty("qbs", "installRoot"), installPrefix, relativeInstallDir); if (installSourceBase) { if (!FileInfo.isAbsolutePath(installSourceBase)) throw "installSourceBase is not an absolute path"; if (!artifact.filePath.startsWith(installSourceBase)) throw "artifact file path doesn't start with the value of qbs.installSourceBase"; return FileInfo.joinPaths(targetDir, artifact.filePath.substr(installSourceBase.length)); } return FileInfo.joinPaths(targetDir, artifact.fileName); } /** * Given a list of file tags, returns the file tag (one of [c, cpp, objc, objcpp]) * corresponding to the C-family language the file should be compiled as. * * If no such tag is found, undefined is returned. If more than one match is * found, an exception is thrown. */ function fileTagForTargetLanguage(fileTags) { var srcTags = ["c", "cpp", "objc", "objcpp", "asm", "asm_cpp", "cppm"]; var pchTags = ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"]; var canonicalTag = undefined; var foundTagCount = 0; for (var i = 0; i < fileTags.length; ++i) { var idx = srcTags.indexOf(fileTags[i]); if (idx === -1) idx = pchTags.indexOf(fileTags[i]); if (idx !== -1) { canonicalTag = srcTags[idx]; if (++foundTagCount > 1) break; } } if (foundTagCount > 1) throw ("source files cannot be identified as more than one language"); return foundTagCount == 1 ? canonicalTag : undefined; } /** * Returns the name of a language-specific property given the file tag * for that property, and the base property name. * * If \a fileTag is undefined, the language-agnostic property name is returned. */ function languagePropertyName(propertyName, fileTag) { if (!fileTag) fileTag = "common"; var asm = { "flags": "assemblerFlags", "platformFlags": "platformAssemblerFlags" }; var map = { "c": { "flags": "cFlags", "platformFlags": "platformCFlags", "usePrecompiledHeader": "useCPrecompiledHeader" }, "cpp": { "flags": "cxxFlags", "platformFlags": "platformCxxFlags", "usePrecompiledHeader": "useCxxPrecompiledHeader" }, "objc": { "flags": "objcFlags", "platformFlags": "platformObjcFlags", "usePrecompiledHeader": "useObjcPrecompiledHeader" }, "objcpp": { "flags": "objcxxFlags", "platformFlags": "platformObjcxxFlags", "usePrecompiledHeader": "useObjcxxPrecompiledHeader" }, "common": { "flags": "commonCompilerFlags", "platformFlags": "platformCommonCompilerFlags" }, "asm": asm, "asm_cpp": asm }; var lang = map[fileTag]; if (!lang) return propertyName; return lang[propertyName] || propertyName; } function modulePropertiesFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var result = product.moduleProperty( moduleName, languagePropertyName(propertyName, langFilter)) || []; for (var i in artifacts) { var artifactProp = artifacts[i].moduleProperty( moduleName, languagePropertyName(propertyName, langFilter)); if (artifactProp) result = result.concat(artifactProp); } return sanitizedList(result, product, moduleName + "." + propertyName); } function moduleProperty(product, propertyName, langFilter) { return sanitizedModuleProperty(product, product.moduleName, propertyName, langFilter); } function sanitizedModuleProperty(obj, moduleName, propertyName, langFilter) { return sanitizedList(obj.moduleProperty(moduleName, languagePropertyName(propertyName, langFilter)), obj, moduleName + "." + propertyName); } /** * Returns roughly the same value as moduleProperty for a product, but ensures that all of the * given input artifacts share the same value of said property, as a sort of sanity check. * * This allows us to verify that users do not, for example, try to set different values on input * artifacts for which the value is input specific (not product specific), but which must be the * same for all inputs. */ function modulePropertyFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var values = [product.moduleProperty(moduleName, languagePropertyName(propertyName, langFilter))]; for (var i in artifacts) { var value = artifacts[i].moduleProperty(moduleName, languagePropertyName(propertyName, langFilter)); if (!values.contains(value)) { values.push(value); } } if (values.length !== 1) { throw "The value of " + [moduleName, propertyName].join(".") + " must be identical for the following input artifacts: " + artifacts.map(function (artifact) { return artifact.filePath; }); } return values[0]; } function concatAll() { var result = []; for (var i = 0; i < arguments.length; ++i) { var arg = arguments[i]; if (arg === undefined) continue; else if (arg instanceof Array) result = result.concat(arg); else result.push(arg); } return result; } function allFileTags(fileTaggers) { var tags = []; for (var ext in fileTaggers) tags = tags.uniqueConcat(fileTaggers[ext]); return tags; } /** * Flattens a dictionary (string keys to strings) * into a string list containing items like \c key=value1 */ function flattenDictionary(dict, separator) { separator = separator || "="; var list = []; for (var i in dict) { var value = i; if (dict[i] !== undefined) // allow differentiation between undefined and empty string value += separator + dict[i]; list.push(value); } return list; } function ModuleError(message) { var e = new Error(message); e.fileName = ""; return e; } var EnvironmentVariable = (function () { function EnvironmentVariable(name, separator, convertPathSeparators) { if (!name) throw "EnvironmentVariable c'tor needs a name as first argument."; this.name = name; this.value = Environment.getEnv(name) || ""; this.separator = separator || ""; this.convertPathSeparators = convertPathSeparators || false; } EnvironmentVariable.prototype.prepend = function (v) { if (this.value.length > 0 && this.value.charAt(0) !== this.separator) this.value = this.separator + this.value; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value = v + this.value; }; EnvironmentVariable.prototype.append = function (v) { if (this.value.length > 0) this.value += this.separator; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value += v; }; EnvironmentVariable.prototype.set = function () { Environment.putEnv(this.name, this.value); }; EnvironmentVariable.prototype.unset = function () { Environment.unsetEnv(this.name); }; return EnvironmentVariable; })(); var PropertyValidator = (function () { function PropertyValidator(moduleName) { this.requiredProperties = {}; this.propertyValidators = []; if (!moduleName) throw "PropertyValidator c'tor needs a module name as a first argument."; this.moduleName = moduleName; } PropertyValidator.prototype.setRequiredProperty = function (propertyName, propertyValue, message) { this.requiredProperties[propertyName] = { propertyValue: propertyValue, message: message }; }; PropertyValidator.prototype.addRangeValidator = function (propertyName, propertyValue, min, max, allowFloats) { var message = []; if (min !== undefined) message.push(">= " + min); if (max !== undefined) message.push("<= " + max); this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "number") return false; if (!allowFloats && value % 1 !== 0) return false; if (min !== undefined && value < min) return false; if (max !== undefined && value > max) return false; return true; }, "must be " + (!allowFloats ? "an integer " : "") + message.join(" and ") + ", actual value: " + propertyValue); }; PropertyValidator.prototype.addVersionValidator = function (propertyName, propertyValue, minComponents, maxComponents, allowSuffixes) { if (minComponents !== undefined && (typeof minComponents !== "number" || minComponents % 1 !== 0 || minComponents < 1)) throw "minComponents must be at least 1"; if (maxComponents !== undefined && (typeof maxComponents !== "number" || maxComponents % 1 !== 0 || maxComponents < minComponents)) throw "maxComponents must be >= minComponents"; this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "string") return false; return value && value.match("^[0-9]+(\\.[0-9]+){" + ((minComponents - 1) || 0) + "," + ((maxComponents - 1) || "") + "}" + (!allowSuffixes ? "$" : "")) !== null; }, "must be a version number with " + (minComponents === maxComponents ? minComponents : (minComponents + " to " + maxComponents)) + (minComponents === maxComponents && minComponents === 1 ? " component" : " components") + ", actual value: " + propertyValue); }; PropertyValidator.prototype.addFileNameValidator = function (propertyName, propertyValue) { this.addCustomValidator(propertyName, propertyValue, function (value) { return !/[/?<>\\:*|"\u0000-\u001f\u0080-\u009f]/.test(propertyValue) && propertyValue !== "." && propertyValue !== ".."; }, "cannot contain reserved or control characters and cannot be \".\" or \"..\""); }; PropertyValidator.prototype.addCustomValidator = function (propertyName, propertyValue, validator, message) { this.propertyValidators.push({ propertyName: propertyName, propertyValue: propertyValue, validator: validator, message: message }); }; PropertyValidator.prototype.validate = function (throwOnError) { var i; var lines; // Find any missing properties var missingProperties = {}; for (i in this.requiredProperties) { var propValue = this.requiredProperties[i].propertyValue; if (propValue === undefined || propValue === null || propValue === "") { missingProperties[i] = this.requiredProperties[i]; } } // Find any properties that don't satisfy their validator function var invalidProperties = {}; for (var j = 0; j < this.propertyValidators.length; ++j) { var v = this.propertyValidators[j]; if (!v.validator(v.propertyValue)) { var messages = invalidProperties[v.propertyName] || []; messages.push(v.message); invalidProperties[v.propertyName] = messages; } } var errorMessage = ""; if (Object.keys(missingProperties).length > 0) { errorMessage += "The following properties are not set. Set them in your profile or product:\n"; lines = []; for (i in missingProperties) { var obj = missingProperties[i]; lines.push(this.moduleName + "." + i + ((obj && obj.message) ? (": " + obj.message) : "")); } errorMessage += lines.join("\n"); } if (Object.keys(invalidProperties).length > 0) { if (errorMessage) errorMessage += "\n"; errorMessage += "The following properties have invalid values:\n"; lines = []; for (i in invalidProperties) { for (j = 0; j < invalidProperties[i].length; ++j) { lines.push(this.moduleName + "." + i + ": " + invalidProperties[i][j]); } } errorMessage += lines.join("\n"); } if (throwOnError !== false && errorMessage.length > 0) throw errorMessage; return errorMessage.length == 0; }; return PropertyValidator; })(); var BlackboxOutputArtifactTracker = (function () { function BlackboxOutputArtifactTracker() { } BlackboxOutputArtifactTracker.prototype.artifacts = function (outputDirectory) { var process; var fakeOutputDirectory; try { fakeOutputDirectory = new TemporaryDir(); if (!fakeOutputDirectory.isValid()) throw "could not create temporary directory"; process = new Process(); if (this.commandEnvironmentFunction) { var env = this.commandEnvironmentFunction(fakeOutputDirectory.path()); for (var key in env) process.setEnv(key, env[key]); } process.exec(this.command, this.commandArgsFunction(fakeOutputDirectory.path()), true); var artifacts = []; if (this.fileTaggers) { var files = this.findFiles(fakeOutputDirectory.path()); for (var i = 0; i < files.length; ++i) artifacts.push(this.createArtifact(fakeOutputDirectory.path(), files[i])); } if (this.processStdOutFunction) artifacts = artifacts.concat(this.processStdOutFunction(process.readStdOut())); artifacts = this.fixArtifactPaths(artifacts, outputDirectory, fakeOutputDirectory.path()); return artifacts; } finally { if (process) process.close(); if (fakeOutputDirectory) fakeOutputDirectory.remove(); } }; BlackboxOutputArtifactTracker.prototype.createArtifact = function (root, filePath) { for (var ext in this.fileTaggers) { if (filePath.endsWith(ext)) { return { filePath: filePath, fileTags: this.fileTaggers[ext] }; } } if (!this.defaultFileTags) { var relFilePath = (filePath.startsWith(root + '/') || filePath.startsWith(root + '\\')) ? filePath.substring(root.length + 1) : filePath; throw "BlackboxOutputArtifactTracker: no matching file taggers for path '" + relFilePath + "'. Set defaultFileTags to an array of file tags to " + "apply to files not tagged by the fileTaggers map, which was:\n" + JSON.stringify(this.fileTaggers, undefined, 4); } return { filePath: filePath, fileTags: this.defaultFileTags }; }; BlackboxOutputArtifactTracker.prototype.findFiles = function (dir) { var fileList = File.directoryEntries(dir, File.Files).map(function (p) { return FileInfo.joinPaths(dir, p); }); var dirList = File.directoryEntries(dir, File.Dirs | File.NoDotAndDotDot).map(function (p) { return FileInfo.joinPaths(dir, p); }); for (var i = 0; i < dirList.length; ++i) fileList = fileList.concat(this.findFiles(dirList[i])); return fileList; }; BlackboxOutputArtifactTracker.prototype.fixArtifactPaths = function (artifacts, realBasePath, fakeBasePath) { for (var i = 0; i < artifacts.length; ++i) { artifacts[i].filePath = FileInfo.joinPaths( realBasePath, FileInfo.relativePath(fakeBasePath, artifacts[i].filePath)) } return artifacts; }; return BlackboxOutputArtifactTracker; })(); function hasAnyOf(m, tokens) { for (var i = 0; i < tokens.length; ++i) { if (m[tokens[i]] !== undefined) return true; } } function guessArchitecture(m) { var architecture; if (m) { // based on the search algorithm from qprocessordetection.h in qtbase var arm64Defs = ["_M_ARM64", "__aarch64__", "__ARM64__", "__ARM_ARCH_ISA_A64"]; if (hasAnyOf(m, ["__arm__", "__TARGET_ARCH_ARM", "_M_ARM"].concat(arm64Defs))) { if (hasAnyOf(m, arm64Defs)) { architecture = "arm64"; } else { architecture = "arm"; var foundSubarch = false; for (var i = 8; i >= 4; --i) { var codes = ["zk", "tej", "te", "t2"].concat([].concat.apply([], new Array(26)).map(function(_, i) { return String.fromCharCode(122 - i); })); for (var j = 0; j < codes.length; ++j) { if (m["__ARM_ARCH_" + i + codes[j].toUpperCase() + "__"] !== undefined) { architecture += "v" + i + codes[j].toLowerCase(); foundSubarch = true; break; } } if (i === 7 && (m["_ARM_ARCH_7"] !== undefined || m["_M_ARM"] === "7")) { architecture += "v7"; foundSubarch = true; } if (foundSubarch) break; } } } else if (hasAnyOf(m, ["__i386", "__i386__", "__386__"])) { architecture = "x86"; } else if (hasAnyOf(m, ["_M_IX86"])) { var code = parseInt(m["_M_IX86"]); architecture = (code < 300) ? "x86_16" : "x86"; } else if (hasAnyOf(m, ["_M_I86"])) { architecture = "x86_16"; } else if (hasAnyOf(m, ["__x86_64", "__x86_64__", "__amd64", "_M_X64", "_M_AMD64"])) { architecture = "x86_64"; if (hasAnyOf(m, ["__x86_64h", "__x86_64h__"])) architecture = "x86_64h"; } else if (hasAnyOf(m, ["__ia64", "__ia64__", "_M_IA64"])) { architecture = "ia64"; } else if (hasAnyOf(m, ["__mips", "__mips__", "_M_MRX000"])) { architecture = "mips"; if (hasAnyOf(m, ["_MIPS_ARCH_MIPS64", "__mips64"])) architecture += "64"; } else if (hasAnyOf(m, ["__ppc__", "__ppc", "__powerpc__", "_ARCH_COM", "_ARCH_PWR", "_ARCH_PPC", "_M_MPPC", "_M_PPC"])) { architecture = "ppc"; if (hasAnyOf(m, ["__ppc64__", "__powerpc64__", "__64BIT__"])) architecture += "64"; } else if (hasAnyOf(m, ["__s390__"])) { if (hasAnyOf(m, ["__s390x__"])) architecture = "s390x"; } else if (hasAnyOf(m, ["__sparc__"])) { architecture = "sparc"; if (hasAnyOf(m, ["__sparc64__"])) architecture += "64"; } else if (hasAnyOf(m, ["__AVR__"])) { architecture = "avr"; } else if (hasAnyOf(m, ["__AVR32__"])) { architecture = "avr32"; } else if (hasAnyOf(m, ["__MSP430__"])) { architecture = "msp430"; } else if (hasAnyOf(m, ["__RL78__"])) { architecture = "rl78"; } else if (hasAnyOf(m, ["__RX__"])) { architecture = "rx"; } else if (hasAnyOf(m, ["__v850__"])) { architecture = "v850"; } else if (hasAnyOf(m, ["__riscv"])) { architecture = "riscv"; } else if (hasAnyOf(m, ["__xtensa__", "__XTENSA__"])) { architecture = "xtensa"; } else if (hasAnyOf(m, ["__m68k__"])) { architecture = "m68k"; } else if (hasAnyOf(m, ["__m32c__"])) { architecture = "m32c"; } else if (hasAnyOf(m, ["__m32r__", "__M32R__"])) { architecture = "m32r"; } else if (hasAnyOf(m, ["__sh__", "__SH__"])) { architecture = "sh"; } else if (hasAnyOf(m, ["__CR16__"])) { architecture = "cr16"; } else if (hasAnyOf(m, ["__mc68hc1x__", "__mc68hc1x"])) { architecture = "hcs12"; } else if (hasAnyOf(m, ["__e2k__"])) { architecture = "e2k"; } else if (hasAnyOf(m, ["__hppa__"])) { architecture = "hppa"; } else if (hasAnyOf(m, ["__alpha__"])) { architecture = "alpha"; } else if (hasAnyOf(m, ["__loongarch__"])) { architecture = "loongarch"; if (hasAnyOf(m, ["__loongarch_lp64"])) architecture += "64"; } } return Utilities.canonicalArchitecture(architecture); } function guessTargetPlatform(m) { if (m) { if (hasAnyOf(m, ["__ANDROID__", "ANDROID"])) return "android"; if (hasAnyOf(m, ["__QNXNTO__"])) return "qnx"; if (hasAnyOf(m, ["__INTEGRITY"])) return "integrity"; if (hasAnyOf(m, ["__vxworks"])) return "vxworks"; if (hasAnyOf(m, ["__APPLE__"])) return "darwin"; if (hasAnyOf(m, ["WIN32", "_WIN32", "__WIN32__", "__NT__", "__WINDOWS__", "_WINDOWS"])) return "windows"; if (hasAnyOf(m, ["MSDOS", "__DOS__", "DOS386"])) return "dos"; if (hasAnyOf(m, ["__OS2__"])) return "os2"; if (hasAnyOf(m, ["_AIX"])) return "aix"; if (hasAnyOf(m, ["hpux", "__hpux"])) return "hpux"; if (hasAnyOf(m, ["__sun", "sun"])) return "solaris"; if (hasAnyOf(m, ["__linux__", "__linux", "__LINUX__"])) return "linux"; if (hasAnyOf(m, ["__FreeBSD__", "__DragonFly__", "__FreeBSD_kernel__"])) return "freebsd"; if (hasAnyOf(m, ["__NetBSD__"])) return "netbsd"; if (hasAnyOf(m, ["__OpenBSD__"])) return "openbsd"; if (hasAnyOf(m, ["__GNU__"])) return "hurd"; if (hasAnyOf(m, ["__HAIKU__"])) return "haiku"; if (hasAnyOf(m, ["__wasm__"])) return "wasm-emscripten" } } function toJSLiteral(v) { if (v === undefined) return "undefined"; return JSON.stringify(v); } qbs-src-3.3.1/share/qbs/imports/qbs/ProviderUtils/0000755000175100017510000000000015232633614021467 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/ProviderUtils/provider-utils.js0000644000175100017510000001160015232633614025013 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Utilities = require("qbs.Utilities"); function pkgConfigToModuleName(packageName) { return packageName.replace(/\./g, '-'); } function isMsvcQt(qtProps) { return qtProps.mkspecName.contains("-msvc"); } function isMinGwQt(qtProps) { return qtProps.mkspecName.startsWith("win32-g++") || qtProps.mkspecName.startsWith("mingw"); } function isDesktopWindowsQt(qtProps) { return qtProps.mkspecName.startsWith("win32-") || isMinGwQt(qtProps); } function qtNeedsDSuffix(qtProps) { return !isMinGwQt(qtProps) || Utilities.versionCompare(qtProps.qtVersion, "5.14.0") < 0 || qtProps.configItems.contains("debug_and_release"); } function qtIsFramework(modInfo, qtProps) { if (modInfo.isFramework) return true; if (!qtProps.frameworkBuild || modInfo.isStaticLibrary) return false; var modulesNeverBuiltAsFrameworks = [ "bootstrap", "openglextensions", "platformsupport", "qmldevtools", "harfbuzzng" ]; if (qtProps.qtMajorVersion <= 5) { modulesNeverBuiltAsFrameworks.push("uitools"); // is framework since qt6 } return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName); } function qtLibBaseName(modInfo, libName, debugBuild, qtProps) { var name = libName; if (qtProps.mkspecName.startsWith("win")) { if (debugBuild && qtNeedsDSuffix(qtProps)) name += 'd'; if (!modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5) name += qtProps.qtMajorVersion; } if (qtProps.mkspecName.contains("macx") || qtProps.mkspecName.contains("ios") || qtProps.mkspecName.contains("darwin")) { if (!qtIsFramework(modInfo, qtProps) && qtProps.buildVariant.contains("debug") && (!qtProps.buildVariant.contains("release") || debugBuild)) { name += "_debug"; } } return name; } function qtModuleNameWithoutPrefix(modInfo) { if (modInfo.name === "Phonon") return "phonon"; if (!modInfo.modulePrefix && modInfo.name.startsWith("Qt")) return modInfo.name.slice(2); // Strip off "Qt". if (modInfo.name.startsWith(modInfo.modulePrefix)) return modInfo.name.slice(modInfo.modulePrefix.length); return modInfo.name; } function qtLibraryBaseName(modInfo, qtProps, debugBuild) { if (modInfo.isPlugin) return qtLibBaseName(modInfo, modInfo.name, debugBuild, qtProps); // Some modules use a different naming scheme, so it doesn't get boring. var libNameBroken = modInfo.name === "Enginio" || modInfo.name === "DataVisualization" || modInfo.name === "Phonon"; var libName = ""; if (!modInfo.isExternal) { libName += !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix; if (qtProps.qtMajorVersion >= 5 && !qtIsFramework(modInfo, qtProps) && !libNameBroken) libName += qtProps.qtMajorVersion; } libName += qtModuleNameWithoutPrefix(modInfo); if (!modInfo.isExternal) libName += qtProps.qtLibInfix; return qtLibBaseName(modInfo, libName, debugBuild, qtProps); } function qtLibNameForLinker(modInfo, qtProps, debugBuild) { if (!modInfo.hasLibrary) return undefined; var libName = qtLibraryBaseName(modInfo, qtProps, debugBuild); if (qtProps.mkspecName.contains("msvc")) libName += ".lib"; return libName; } qbs-src-3.3.1/share/qbs/imports/qbs/BundleTools/0000755000175100017510000000000015232633614021106 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/imports/qbs/BundleTools/bundle-tools.js0000644000175100017510000000603515232633614024057 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var DarwinTools = require("qbs.DarwinTools"); var PropertyList = require("qbs.PropertyList"); function destinationDirectoryForResource(product, input) { var path = product.destinationDirectory; var inputFilePath = FileInfo.joinPaths(input.baseDir, input.fileName); var key = DarwinTools.localizationKey(inputFilePath); if (key) { path = FileInfo.joinPaths(path, localizedResourcesFolderPath(product, key)); var subPath = DarwinTools.relativeResourcePath(inputFilePath); if (subPath && subPath !== '.') path = FileInfo.joinPaths(path, subPath); } else { path = FileInfo.joinPaths(path, product.moduleProperty("bundle", "unlocalizedResourcesFolderPath")); } return path; } function localizedResourcesFolderPath(product, key) { return FileInfo.joinPaths(product.moduleProperty("bundle", "unlocalizedResourcesFolderPath"), key + product.moduleProperty("bundle", "localizedResourcesFolderSuffix")); } function infoPlistContents(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.toObject(); } finally { plist.clear(); } } function infoPlistFormat(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.format(); } finally { plist.clear(); } } qbs-src-3.3.1/share/qbs/module-providers/0000755000175100017510000000000015232633614017672 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/module-providers/qbspkgconfig.qbs0000644000175100017510000002123615232633614023062 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.PkgConfig import qbs.ProviderUtils import qbs.Probes import qbs.Process import qbs.TextFile import "Qt/setup-qt.js" as SetupQt ModuleProvider { property stringList executableNames: ["pkgconf", "pkg-config"] property string executableFilePath: pkgConfigProbe.filePath property stringList extraPaths property stringList libDirs property bool staticMode: false property bool definePrefix: Host.os().includes("windows") // We take the sysroot default from qbs.sysroot, except for Xcode toolchains, where // the sysroot points into the Xcode installation and does not contain .pc files. property path sysroot: qbs.toolchain && qbs.toolchain.includes("xcode") ? undefined : qbs.sysroot Probes.BinaryProbe { id: pkgConfigProbe condition: !executableFilePath names: executableNames } Probes.QbsPkgConfigProbe { id: theProbe _executableFilePath: executableFilePath _extraPaths: extraPaths _sysroot: sysroot _libDirs: libDirs _staticMode: staticMode _definePrefix: definePrefix } Probes.QmakeProbe { id: qmakeProbe condition: moduleName.startsWith("Qt") && theProbe.qmakePaths qmakePaths: theProbe.qmakePaths } isEager: false relativeSearchPaths: { function getModuleInfo(pkg, staticMode) { var result = {}; var mapper = function(flag) { return flag.value; } var typeFilter = function(type) { return function(flag) { return flag.type === type; } } function getLibsInfo(libs) { var result = {}; result.dynamicLibraries = libs.filter(typeFilter(PkgConfig.LibraryName)).map(mapper); result.staticLibraries = libs.filter(typeFilter(PkgConfig.StaticLibraryName)).map(mapper); result.libraryPaths = libs.filter(typeFilter(PkgConfig.LibraryPath)).map(mapper); result.frameworks = libs.filter(typeFilter(PkgConfig.Framework)).map(mapper); result.frameworkPaths = libs.filter(typeFilter(PkgConfig.FrameworkPath)).map(mapper); result.driverLinkerFlags = libs.filter(typeFilter(PkgConfig.LinkerFlag)).map(mapper); return result; } result.version = pkg.version; result.includePaths = pkg.cflags.filter(typeFilter(PkgConfig.IncludePath)).map(mapper); result.systemIncludePaths = pkg.cflags.filter(typeFilter(PkgConfig.SystemIncludePath)).map(mapper); result.defines = pkg.cflags.filter(typeFilter(PkgConfig.Define)).map(mapper); result.commonCompilerFlags = pkg.cflags.filter(typeFilter(PkgConfig.CompilerFlag)).map(mapper); var allLibs = pkg.libs; if (staticMode) allLibs = allLibs.concat(pkg.libsPrivate); var libsInfo = getLibsInfo(allLibs); for (var key in libsInfo) { result[key] = libsInfo[key]; } return result; } function getModuleDependencies(pkg, staticMode) { var mapper = function(p) { var result = {}; for (var key in p) result[key] = p[key]; result.name = ProviderUtils.pkgConfigToModuleName(result.name); return result; } var result = pkg.requires.map(mapper); if (staticMode) result = result.concat(pkg.requiresPrivate.map(mapper)); return result; } console.debug("Running pkgconfig provider for " + moduleName + "."); var outputDir = FileInfo.joinPaths(outputBaseDir, "modules"); File.makePath(outputDir); var moduleMapping = { "protobuf": "protobuflib" } var reverseMapping = {} for (var key in moduleMapping) reverseMapping[moduleMapping[key]] = key if (moduleName.startsWith("Qt")) { function setupQt(packageName, qtInfos) { if (qtInfos === undefined || qtInfos.length === 0) return []; var qtProviderDir = FileInfo.joinPaths(path, "Qt"); return SetupQt.doSetup(packageName, qtInfos, outputBaseDir, qtProviderDir); } if (!sysroot) { return setupQt(moduleName, qmakeProbe.qtInfos); } return []; } var pkg; pkg = theProbe.packages[reverseMapping[moduleName]]; if (pkg === undefined) pkg = theProbe.packagesByModuleName[moduleName]; if (pkg === undefined) return []; if (pkg.isBroken) { console.warn("Failed to load " + moduleName + " as it's pkg-config package is broken"); return []; } var moduleInfo = getModuleInfo(pkg, staticMode); var deps = getModuleDependencies(pkg, staticMode); var moduleDir = FileInfo.joinPaths(outputDir, moduleName); File.makePath(moduleDir); var module = new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); module.writeLine("Module {"); module.writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version)); module.writeLine(" Depends { name: 'cpp' }"); deps.forEach(function(dep) { var depName = ProviderUtils.pkgConfigToModuleName( moduleMapping[dep.name] ? moduleMapping[dep.name] : dep.name); module.write(" Depends { name: '" + depName + "'"); for (var k in dep) { if (k === "name") continue; module.write("; " + k + ": " + ModUtils.toJSLiteral(dep[k])); } module.writeLine(" }"); }) function writeProperty(propertyName) { var value = moduleInfo[propertyName]; if (value.length !== 0) { // skip empty props for simplicity of the module file module.writeLine( " cpp." + propertyName + ":" + ModUtils.toJSLiteral(value)); } } writeProperty("includePaths"); writeProperty("systemIncludePaths"); writeProperty("defines"); writeProperty("commonCompilerFlags"); writeProperty("dynamicLibraries"); writeProperty("staticLibraries"); writeProperty("libraryPaths"); writeProperty("frameworks"); writeProperty("frameworkPaths"); writeProperty("driverLinkerFlags"); module.writeLine("}"); module.close(); return ""; } } qbs-src-3.3.1/share/qbs/module-providers/Qt/0000755000175100017510000000000015232633614020256 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/module-providers/Qt/provider.qbs0000644000175100017510000000065015232633614022620 0ustar runnerrunnerimport "setup-qt.js" as SetupQt import qbs.Probes ModuleProvider { Probes.QmakeProbe { condition: moduleName.startsWith("Qt.") id: probe qmakePaths: qmakeFilePaths } property stringList qmakeFilePaths readonly property varList _qtInfos: probe.qtInfos condition: probe.found isEager: false relativeSearchPaths: SetupQt.doSetup(moduleName, _qtInfos, outputBaseDir, path) } qbs-src-3.3.1/share/qbs/module-providers/Qt/setup-qt.js0000644000175100017510000005776015232633614022415 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var ProviderUtils = require("qbs.ProviderUtils"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function extractQbsArchs(module, qtProps) { if (qtProps.mkspecName.startsWith("macx-")) { var archs = []; if (module.libFilePathRelease) archs = Utilities.getArchitecturesFromBinary(module.libFilePathRelease); return archs; } var qbsArch = Utilities.canonicalArchitecture(qtProps.architecture); if (qbsArch === "arm" && qtProps.mkspecPath.contains("android")) qbsArch = "armv7a"; // Qt4 has "QT_ARCH = windows" in qconfig.pri for both MSVC and mingw. if (qbsArch === "windows") return [] return [qbsArch]; } function qbsTargetPlatformFromQtMkspec(qtProps) { var mkspec = qtProps.mkspecName; var idx = mkspec.lastIndexOf('/'); if (idx !== -1) mkspec = mkspec.slice(idx + 1); if (mkspec.startsWith("aix-")) return "aix"; if (mkspec.startsWith("android-")) return "android"; if (mkspec.startsWith("cygwin-")) return "windows"; if (mkspec.startsWith("darwin-")) return "macos"; if (mkspec.startsWith("freebsd-")) return "freebsd"; if (mkspec.startsWith("haiku-")) return "haiku"; if (mkspec.startsWith(("hpux-")) || mkspec.startsWith(("hpuxi-"))) return "hpux"; if (mkspec.startsWith("hurd-")) return "hurd"; if (mkspec.startsWith("integrity-")) return "integrity"; if (mkspec.startsWith("linux-")) return "linux"; if (mkspec.startsWith("macx-")) { if (mkspec.startsWith("macx-ios-")) return "ios"; if (mkspec.startsWith("macx-tvos-")) return "tvos"; if (mkspec.startsWith("macx-watchos-")) return "watchos"; return "macos"; } if (mkspec.startsWith("netbsd-")) return "netbsd"; if (mkspec.startsWith("openbsd-")) return "openbsd"; if (mkspec.startsWith("qnx-")) return "qnx"; if (mkspec.startsWith("solaris-")) return "solaris"; if (mkspec.startsWith("vxworks-")) return "vxworks"; if (ProviderUtils.isDesktopWindowsQt(qtProps) || mkspec.startsWith("winrt-")) return "windows"; if (mkspec.startsWith("wasm-")) return "wasm-emscripten"; } function pathToJSLiteral(path) { return JSON.stringify(FileInfo.fromNativeSeparators(path)); } function defaultQpaPlugin(module, qtProps) { if (qtProps.qtMajorVersion < 5) return undefined; function findInPriFile(filePath) { var priFile = new TextFile(filePath); var magicString = "QT_DEFAULT_QPA_PLUGIN ="; while (!priFile.atEof()) { var line = priFile.readLine().trim(); if (line.startsWith(magicString)) return line.slice(magicString.length).trim(); } }; if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) { var pluginName = findInPriFile(FileInfo.joinPaths(qtProps.mkspecBasePath, "qconfig.pri")); if (pluginName) return pluginName; } else { pluginName = findInPriFile(FileInfo.joinPaths(qtProps.mkspecBasePath, "modules", "qt_lib_gui.pri")); if (pluginName) return pluginName; var gtGuiHeadersPath = qtProps.frameworkBuild ? FileInfo.joinPaths(qtProps.libraryPath, "QtGui.framework", "Headers") : FileInfo.joinPaths(qtProps.includePath, "QtGui"); var qtGuiConfigHeader = FileInfo.joinPaths(gtGuiHeadersPath, "qtgui-config.h"); var headerFiles = []; headerFiles.push(qtGuiConfigHeader); while (headerFiles.length > 0) { var filePath = headerFiles.shift(); var headerFile = new TextFile(filePath, TextFile.ReadOnly); var regexp = /^#define QT_QPA_DEFAULT_PLATFORM_NAME "(.+)".*$/; var includeRegexp = /^#include "(.+)".*$/; while (!headerFile.atEof()) { var line = headerFile.readLine().trim(); var match = line.match(regexp); if (match) return 'q' + match[1]; match = line.match(includeRegexp); if (match) { var includedFile = match[1]; if (!FileInfo.isAbsolutePath(includedFile)) { includedFile = FileInfo.cleanPath( FileInfo.joinPaths(FileInfo.path(filePath), includedFile)); } headerFiles.push(includedFile); } } headerFile.close(); } } if (module.isStaticLibrary) console.warn("Could not determine default QPA plugin for static Qt."); } function libraryFileTag(module, qtProps) { if (module.isStaticLibrary) return "staticlibrary"; return ProviderUtils.isMsvcQt(qtProps) || qtProps.mkspecName.startsWith("win32-g++") ? "dynamiclibrary_import" : "dynamiclibrary"; } function findVariable(content, start) { var result = [-1, -1]; result[0] = content.indexOf('@', start); if (result[0] === -1) return result; result[1] = content.indexOf('@', result[0] + 1); if (result[1] === -1) { result[0] = -1; return result; } var forbiddenChars = [' ', '\n']; for (var i = 0; i < forbiddenChars.length; ++i) { var forbidden = forbiddenChars[i]; var k = content.indexOf(forbidden, result[0] + 1); if (k !== -1 && k < result[1]) return findVariable(content, result[0] + 1); } return result; } function minVersionJsString(minVersion) { return !minVersion ? "" : ModUtils.toJSLiteral(minVersion); } function abiToArchitecture(abi) { switch (abi) { case "armeabi-v7a": return "armv7a"; case "arm64-v8a": return "arm64"; case "x86": case "x86_64": default: return abi; } } function replaceSpecialValues(content, module, qtProps, abi) { var architectures = []; if (abi.length > 0) architectures.push(abiToArchitecture(abi)); else architectures = extractQbsArchs(module, qtProps); var dict = { archs: ModUtils.toJSLiteral(architectures), targetPlatform: ModUtils.toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)), config: ModUtils.toJSLiteral(qtProps.configItems), qtConfig: ModUtils.toJSLiteral(qtProps.qtConfigItems), enabledFeatures: ModUtils.toJSLiteral(qtProps.enabledFeatures), disabledFeatures: ModUtils.toJSLiteral(qtProps.disabledFeatures), binPath: ModUtils.toJSLiteral(qtProps.binaryPath), installPath: ModUtils.toJSLiteral(qtProps.installPath), installPrefixPath: ModUtils.toJSLiteral(qtProps.installPrefixPath), libPath: ModUtils.toJSLiteral(qtProps.libraryPath), libExecPath: ModUtils.toJSLiteral(qtProps.libExecPath), qmlLibExecPath: ModUtils.toJSLiteral(qtProps.qmlLibExecPath), pluginPath: ModUtils.toJSLiteral(qtProps.pluginPath), incPath: ModUtils.toJSLiteral(qtProps.includePath), docPath: ModUtils.toJSLiteral(qtProps.documentationPath), translationsPath: ModUtils.toJSLiteral(qtProps.translationsPath), helpGeneratorLibExecPath: ModUtils.toJSLiteral(qtProps.helpGeneratorLibExecPath), mkspecName: ModUtils.toJSLiteral(qtProps.mkspecName), mkspecPath: ModUtils.toJSLiteral(qtProps.mkspecPath), version: ModUtils.toJSLiteral(qtProps.qtVersion), libInfix: ModUtils.toJSLiteral(qtProps.qtLibInfix), availableBuildVariants: ModUtils.toJSLiteral(qtProps.buildVariant), staticBuild: ModUtils.toJSLiteral(qtProps.staticBuild), multiThreading: ModUtils.toJSLiteral(qtProps.multiThreading), frameworkBuild: ModUtils.toJSLiteral(qtProps.frameworkBuild), name: ModUtils.toJSLiteral(ProviderUtils.qtModuleNameWithoutPrefix(module)), has_library: ModUtils.toJSLiteral(module.hasLibrary), dependencies: ModUtils.toJSLiteral(module.dependencies), includes: ModUtils.toJSLiteral(module.includePaths), staticLibsDebug: ModUtils.toJSLiteral(module.staticLibrariesDebug), staticLibsRelease: ModUtils.toJSLiteral(module.staticLibrariesRelease), dynamicLibsDebug: ModUtils.toJSLiteral(module.dynamicLibrariesDebug), dynamicLibsRelease: ModUtils.toJSLiteral(module.dynamicLibrariesRelease), linkerFlagsDebug: ModUtils.toJSLiteral(module.linkerFlagsDebug), linkerFlagsRelease: ModUtils.toJSLiteral(module.linkerFlagsRelease), libraryPaths: ModUtils.toJSLiteral(module.libraryPaths), frameworkPathsDebug: ModUtils.toJSLiteral(module.frameworkPathsDebug), frameworkPathsRelease: ModUtils.toJSLiteral(module.frameworkPathsRelease), frameworksDebug: ModUtils.toJSLiteral(module.frameworksDebug), frameworksRelease: ModUtils.toJSLiteral(module.frameworksRelease), libFilePathDebug: ModUtils.toJSLiteral(module.libFilePathDebug), libFilePathRelease: ModUtils.toJSLiteral(module.libFilePathRelease), libNameForLinkerDebug: ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, true)), pluginTypes: ModUtils.toJSLiteral(module.supportedPluginTypes), moduleConfig: ModUtils.toJSLiteral(module.config), libNameForLinkerRelease: ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, false)), entryPointLibsDebug: ModUtils.toJSLiteral(qtProps.entryPointLibsDebug), entryPointLibsRelease: ModUtils.toJSLiteral(qtProps.entryPointLibsRelease), minWinVersion_optional: minVersionJsString(qtProps.windowsVersion), minMacVersion_optional: minVersionJsString(qtProps.macosVersion), minIosVersion_optional: minVersionJsString(qtProps.iosVersion), minTvosVersion_optional: minVersionJsString(qtProps.tvosVersion), minWatchosVersion_optional: minVersionJsString(qtProps.watchosVersion), minAndroidVersion_optional: minVersionJsString(qtProps.androidVersion), }; var additionalContent = ""; var compilerDefines = ModUtils.toJSLiteral(module.compilerDefines); if (module.qbsName === "declarative" || module.qbsName === "quick") { var debugMacro = module.qbsName === "declarative" || qtProps.qtMajorVersion < 5 ? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG"; var indent = " "; additionalContent = "property bool qmlDebugging: false\n" + indent + "property string qmlPath"; if (qtProps.qmlPath) additionalContent += ": " + pathToJSLiteral(qtProps.qmlPath) + '\n'; else additionalContent += '\n'; additionalContent += indent + "property string qmlImportsPath: " + pathToJSLiteral(qtProps.qmlImportPath); compilerDefines = "{\n" + indent + indent + "var result = " + compilerDefines + ";\n" + indent + indent + "if (qmlDebugging)\n" + indent + indent + indent + "result.push(\"" + debugMacro + "\");\n" + indent + indent + "return result;\n" + indent + "}"; } dict.defines = compilerDefines; if (module.qbsName === "gui") dict.defaultQpaPlugin = ModUtils.toJSLiteral(defaultQpaPlugin(module, qtProps)); if (module.qbsName === "qml") dict.qmlPath = pathToJSLiteral(qtProps.qmlPath); if (module.isFramework && module.qbsName !== "core") { if (additionalContent) additionalContent += "\n "; additionalContent += "isFramework: true"; } if (module.isStaticLibrary && module.qbsName !== "core") { if (additionalContent) additionalContent += "\n "; additionalContent += "isStaticLibrary: true"; } if (module.isPlugin) { dict.className = ModUtils.toJSLiteral(module.pluginData.className); dict["extends"] = ModUtils.toJSLiteral(module.pluginData["extends"]); } indent = " "; var useMajorVersion = qtProps.qtMajorVersion > 5 || !qtProps.mkspecPath.contains("macx"); var metaTypesFileNamePrefix = "qt" + (useMajorVersion ? qtProps.qtMajorVersion : "") + module.qbsName + '_'; var metatypesFileNameSuffix = "metatypes.json"; var metaTypesFile; if (qtProps.qtMajorVersion > 5) { function isMetaTypesFileForModule(fileName) { return fileName.startsWith(metaTypesFileNamePrefix) && fileName.endsWith(metatypesFileNameSuffix); }; metaTypesFile = qtProps.metaTypesPath + "/" + qtProps.metaTypeFiles.find(isMetaTypesFileForModule); } else { metaTypesFile = qtProps.libraryPath + "/metatypes/" + metaTypesFileNamePrefix + metatypesFileNameSuffix; } if (File.exists(metaTypesFile)) { if (additionalContent) additionalContent += "\n" + indent; additionalContent += "Group {\n"; additionalContent += indent + indent + "files: " + JSON.stringify(metaTypesFile) + "\n" + indent + indent + "filesAreTargets: true\n" + indent + indent + "fileTags: [\"qt.core.metatypes\"]\n" + indent + "}"; } if (module.hasLibrary && !ProviderUtils.qtIsFramework(module, qtProps)) { if (additionalContent) additionalContent += "\n" + indent; additionalContent += "Group {\n"; if (module.isPlugin) { additionalContent += indent + indent + "condition: enableLinking\n"; } additionalContent += indent + indent + "files: libFilePath\n" + indent + indent + "filesAreTargets: true\n" + indent + indent + "fileTags: [\"" + libraryFileTag(module, qtProps) + "\"]\n" + indent + "}"; } dict.additionalContent = additionalContent; for (var pos = findVariable(content, 0); pos[0] !== -1; pos = findVariable(content, pos[0])) { var varName = content.slice(pos[0] + 1, pos[1]); var replacement = dict[varName] || ""; if (!replacement && varName.endsWith("_optional")) { var prevNewline = content.lastIndexOf('\n', pos[0]); if (prevNewline === -1) prevNewline = 0; var nextNewline = content.indexOf('\n', pos[0]); if (nextNewline === -1) prevNewline = content.length; content = content.slice(0, prevNewline) + content.slice(nextNewline); pos[0] = prevNewline; } else { content = content.slice(0, pos[0]) + replacement + content.slice(pos[1] + 1); pos[0] += replacement.length; } } return content; } function copyTemplateFile(fileName, targetDirectory, qtProps, abi, location, allFiles, module, pluginMap, nonEssentialPlugins) { if (!File.makePath(targetDirectory)) { throw "Cannot create directory '" + FileInfo.toNativeSeparators(targetDirectory) + "'."; } var sourceFile = new TextFile(FileInfo.joinPaths(location, "templates", fileName), TextFile.ReadOnly); var newContent = sourceFile.readAll(); if (module) { newContent = replaceSpecialValues(newContent, module, qtProps, abi); } else { newContent = newContent.replace("@allPluginsByType@", '(' + ModUtils.toJSLiteral(pluginMap) + ')'); newContent = newContent.replace("@nonEssentialPlugins@", ModUtils.toJSLiteral(nonEssentialPlugins)); newContent = newContent.replace("@version@", ModUtils.toJSLiteral(qtProps.qtVersion)); } sourceFile.close(); var targetPath = FileInfo.joinPaths(targetDirectory, fileName); allFiles.push(targetPath); var targetFile = new TextFile(targetPath, TextFile.WriteOnly); targetFile.write(newContent); targetFile.close(); } function setupOneQt(moduleName, qtInfo, outputBaseDir, uniquify, location) { var qtProps = qtInfo.qtProps; var relativeSearchPaths = []; for (a = 0; a < qtInfo.abiInfos.length; ++a) { var abiInfo = qtInfo.abiInfos[a]; var androidAbi = abiInfo.androidAbi; if (qtInfo.abiInfos.length > 1) console.info("Configuring abi '" + androidAbi + "'..."); var relativeSearchPath = uniquify ? Utilities.getHash(qtInfo.qmakeFilePath) : ""; relativeSearchPath = FileInfo.joinPaths(relativeSearchPath, androidAbi); var qbsQtModuleBaseDir = FileInfo.joinPaths(outputBaseDir, relativeSearchPath, "modules", "Qt"); // TODO: // if (File.exists(qbsQtModuleBaseDir)) // File.remove(qbsQtModuleBaseDir); var allFiles = []; if (moduleName === "plugin_support") { copyTemplateFile("plugin_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"), qtProps, androidAbi, location, allFiles, undefined, abiInfo.pluginsByType, abiInfo.nonEssentialPlugins); relativeSearchPaths.push(relativeSearchPath); return relativeSearchPaths; } else if (moduleName === "android_support") { // Note that it's not strictly necessary to copy this one, as it has no variable content. // But we do it anyway for consistency. copyTemplateFile("android_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"), qtProps, androidAbi, location, allFiles); copyTemplateFile("android_support.js", FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"), qtProps, androidAbi, location, allFiles); relativeSearchPaths.push(relativeSearchPath); return relativeSearchPaths; } else if (moduleName === "qmlcache") { var qmlcacheStr = "qmlcache"; if (File.exists(FileInfo.joinPaths(qtProps.qmlLibExecPath, "qmlcachegen" + FileInfo.executableSuffix()))) { copyTemplateFile(qmlcacheStr + ".qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps, androidAbi, location, allFiles); } relativeSearchPaths.push(relativeSearchPath); return relativeSearchPaths; } if (abiInfo.modules[moduleName] !== undefined) { var module = abiInfo.modules[moduleName]; var qbsQtModuleDir = FileInfo.joinPaths(qbsQtModuleBaseDir, module.qbsName); var moduleTemplateFileName; if (module.qbsName === "core") { moduleTemplateFileName = "core.qbs"; copyTemplateFile("core.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); } else if (module.qbsName === "gui") { moduleTemplateFileName = "gui.qbs"; } else if (module.qbsName === "scxml") { moduleTemplateFileName = "scxml.qbs"; } else if (module.qbsName === "dbus") { moduleTemplateFileName = "dbus.qbs"; copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); } else if (module.qbsName === "qml") { moduleTemplateFileName = "qml.qbs"; copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); } else if (module.qbsName === "quick") { moduleTemplateFileName = "quick.qbs"; copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); } else if (module.qbsName === "shadertools") { moduleTemplateFileName = "shadertools.qbs"; copyTemplateFile("shadertools.js", qbsQtModuleDir, qtProps, androidAbi, location, allFiles); } else if (module.isPlugin) { moduleTemplateFileName = "plugin.qbs"; } else { moduleTemplateFileName = "module.qbs"; } copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, androidAbi, location, allFiles, module); relativeSearchPaths.push(relativeSearchPath); } } return relativeSearchPaths; } function doSetup(moduleName, qtInfos, outputBaseDir, location) { if (!qtInfos || qtInfos.length === 0) return []; var uniquifySearchPath = qtInfos.length > 1; var allSearchPaths = []; moduleName = moduleName.substring(3); for (var i = 0; i < qtInfos.length; ++i) { try { console.info("Setting up Qt module '" + moduleName + "' for Qt located at '" + FileInfo.toNativeSeparators(qtInfos[i].qmakeFilePath) + "'."); var searchPaths = setupOneQt(moduleName, qtInfos[i], outputBaseDir, uniquifySearchPath, location); if (searchPaths.length > 0) { for (var j = 0; j < searchPaths.length; ++j ) allSearchPaths.push(searchPaths[j]); } } catch (e) { console.warn("Error setting up Qt module '" + moduleName + "' for '" + FileInfo.toNativeSeparators(qtInfos[i].qmakeFilePath) + "': " + e); throw e; } } return allSearchPaths; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/0000755000175100017510000000000015232633614022254 5ustar runnerrunnerqbs-src-3.3.1/share/qbs/module-providers/Qt/templates/plugin_support.qbs0000644000175100017510000000544215232633614026062 0ustar runnerrunnerModule { // Set by user. property varList pluginsByType property bool linkPlugins: product.type && (product.type.contains("application") || product.type.contains("sharedlibrary")) // Set by Qt modules. property stringList pluginTypes // Set by setup-qt. readonly property var allPluginsByType: @allPluginsByType@ readonly property stringList nonEssentialPlugins: @nonEssentialPlugins@ // Derived. readonly property var defaultPluginsByType: { var map = {}; for (var i = 0; i < (pluginTypes || []).length; ++i) { var pType = pluginTypes[i]; map[pType] = (allPluginsByType[pType] || []).filter(function(p) { return !nonEssentialPlugins.contains(p); }); } return map; } readonly property var effectivePluginsByType: { var ppt = pluginsByType || []; var eppt = {}; for (var i = 0; i < ppt.length; ++i) { var listEntry = ppt[i]; for (var pluginType in listEntry) { var newValue = listEntry[pluginType]; if (!newValue) newValue = []; else if (typeof newValue == "string") newValue = [newValue]; if (!newValue instanceof Array) throw "Invalid value '" + newValue + "' in Qt.plugin_support.pluginsByType"; eppt[pluginType] = (eppt[pluginType] || []).uniqueConcat(newValue); } } var dppt = defaultPluginsByType; for (var pluginType in dppt) { if (!eppt[pluginType]) eppt[pluginType] = dppt[pluginType]; } return eppt; } readonly property stringList enabledPlugins: { var list = []; var eppt = effectivePluginsByType; for (var t in eppt) Array.prototype.push.apply(list, eppt[t]); return list; } validate: { var ppt = pluginsByType; if (!ppt) return; var appt = allPluginsByType; for (var i = 0; i < ppt.length; ++i) { for (var pluginType in ppt[i]) { var requestedPlugins = ppt[i][pluginType]; if (!requestedPlugins) continue; var availablePlugins = appt[pluginType] || []; if (typeof requestedPlugins === "string") requestedPlugins = [requestedPlugins]; for (var j = 0; j < requestedPlugins.length; ++j) { if (!availablePlugins.contains(requestedPlugins[j])) { throw "Plugin '" + requestedPlugins[j] + "' of type '" + pluginType + "' was requested, but is not available."; } } } } } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/module.qbs0000644000175100017510000000200315232633614024243 0ustar runnerrunnerQtModule { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} version: @version@ architectures: @archs@ targetPlatform: @targetPlatform@ hasLibrary: @has_library@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/dbus.qbs0000644000175100017510000000420115232633614023715 0ustar runnerrunnerimport qbs.FileInfo import qbs.ModUtils import "dbus.js" as DBus QtModule { qtModuleName: "DBus" property string xml2cppName: "qdbusxml2cpp" property stringList xml2CppHeaderFlags: [] property stringList xml2CppSourceFlags: [] Rule { inputs: ["qt.dbus.adaptor"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), DBus.outputFileName(input, "_adaptor.h")) fileTags: ["hpp"] } Artifact { filePath: DBus.outputFileName(input, "_adaptor.cpp") fileTags: ["cpp", "qt.untranslatable"] } prepare: DBus.createCommands(product, input, outputs, "-a") } Rule { inputs: ["qt.dbus.interface"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), DBus.outputFileName(input, "_interface.h")) fileTags: ["hpp"] } Artifact { filePath: DBus.outputFileName(input, "_interface.cpp") fileTags: ["cpp", "qt.untranslatable"] } prepare: DBus.createCommands(product, input, outputs, "-p") } version: @version@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/shadertools.qbs0000644000175100017510000000564515232633614025324 0ustar runnerrunnerimport "shadertools.js" as ShaderTools QtModule { qtModuleName: "ShaderTools" additionalProductTypes: ["qt.compiled_shader"] property string generatedShadersDir: "shaders" property string qsbName: "qsb" property stringList glslVersions property stringList hlslVersions property stringList mslVersions property bool useQt6Versions: true property bool tessellation: true property string tessellationMode PropertyOptions { name: "tessellationMode" allowedValues: ["triangles", "quads"] } property int tessellationVertexCount property int viewCount property bool batchable: false property int zOrderLocation property bool optimized: false property stringList defines property bool debugInformation: false property bool addResourceData: true property bool useCompiler: !enableLinking Depends { name: "Qt"; submodules: @dependencies@ } version: @version@ hasLibrary: @has_library@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ enableLinking: false Group { condition: useCompiler FileTagger { patterns: ["*.vert"] fileTags: ["qt.shader.vertex", "qt.shader"] } FileTagger { patterns: ["*.tesc", "*.tese"] fileTags: ["qt.shader.tessellation", "qt.shader"] } FileTagger { patterns: ["*.frag"] fileTags: ["qt.shader.fragment", "qt.shader"] } FileTagger { patterns: ["*.comp"] fileTags: ["qt.shader.compute", "qt.shader"] } Rule { inputs: ["qt.shader"] outputFileTags: [ "qt.compiled_shader", "qt.compiled_shader.vertex", "qt.compiled_shader.tessellation", "qt.compiled_shader.fragment", "qt.compiled_shader.compute", "qt.core.resource_data", ] outputArtifacts: ShaderTools.compilerOutputArtifacts(input) prepare: ShaderTools.compilerCommands.apply(ShaderTools, arguments) } } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/shadertools.js0000644000175100017510000001173015232633614025143 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require('qbs.FileInfo'); function getOutputFileTags(input) { const tags = ["qt.compiled_shader"]; if (input.fileTags.includes("qt.shader.vertex")) { tags.push("qt.compiled_shader.vertex"); } if (input.fileTags.includes("qt.shader.tessellation")) { tags.push("qt.compiled_shader.tessellation"); } if (input.fileTags.includes("qt.shader.fragment")) { tags.push("qt.compiled_shader.fragment"); } if (input.fileTags.includes("qt.shader.compute")) { tags.push("qt.compiled_shader.compute"); } return tags; } function compilerOutputArtifacts(input) { var artifacts = []; const addResourceData = input.Qt.shadertools.addResourceData; artifacts.push({ filePath: FileInfo.joinPaths(input.Qt.shadertools.generatedShadersDir, input.fileName + '.qsb'), fileTags: getOutputFileTags(input).concat(addResourceData ? ["qt.core.resource_data"] : []), Qt: addResourceData ? { core: { resourcePrefix: input.Qt.core.resourcePrefix } } : {} }); return artifacts; } function compilerCommands(project, product, inputs, outputs, input, output) { const qsbPath = FileInfo.joinPaths(input.Qt.core.binPath, input.Qt.shadertools.qsbName); var glslVersions = input.Qt.shadertools.glslVersions; var hlslVersions = input.Qt.shadertools.hlslVersions; var mslVersions = input.Qt.shadertools.mslVersions; var args = [input.filePath, '-o', output.filePath]; if (input.Qt.shadertools.useQt6Versions && glslVersions.length === 0 && hlslVersions.length === 0 && mslVersions.length === 0) { glslVersions = ['100 es', '120', '150']; hlslVersions = ['50']; mslVersions = ['20']; } if (glslVersions.length > 0) { args.push('--glsl', glslVersions.join(',')); } if (hlslVersions.length > 0) { args.push('--hlsl', hlslVersions.join(',')); } if (mslVersions.length > 0) { args.push('--msl', mslVersions.join(',')); } if (input.Qt.shadertools.batchable) { args.push('-b'); if (input.Qt.shadertools.zOrderLocation !== undefined) { args.push('--zorder-loc', input.Qt.shadertools.zOrderLocation); } } if (input.Qt.shadertools.tessellation && input.fileTags.includes("qt.shader.tessellation")) { args.push('--msltess'); const tessellationMode = input.Qt.shadertools.tessellationMode; if (tessellationMode !== undefined) { args.push('--tess-mode', tessellationMode); } const tessellationVertexCount = input.Qt.shadertools.tessellationVertexCount; if (tessellationVertexCount !== undefined) { args.push('--tess-vertex-count', tessellationVertexCount); } } const viewCount = input.Qt.shadertools.viewCount; if (viewCount !== undefined) { args.push('--view-count', viewCount); } if (input.Qt.shadertools.optimized) { args.push('-O'); } const defines = input.Qt.shadertools.defines || []; if (defines.length > 0) { args = args.concat(defines.map(function(define) { return '-D' + define; })); } if (input.Qt.shadertools.debugInformation) { args.push('-g'); } var cmd = new Command(qsbPath, args); cmd.description = 'compiling ' + output.fileName; cmd.highlight = 'codegen'; cmd.environment = ["LANG=en_US.UTF-8"]; return [cmd]; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/quick.js0000644000175100017510000001571015232633614023732 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var Rcc = require("rcc.js"); var TextFile = require("qbs.TextFile"); function scanQrc(product, qrcFilePath) { var absInputDir = FileInfo.path(qrcFilePath); var result = []; var process = new Process(); try { var rcc = FileInfo.joinPaths(Rcc.fullPath(product) + FileInfo.executableSuffix()); var exitCode = process.exec(rcc, ["--list", qrcFilePath], true); for (;;) { var line = process.readLine(); if (!line) break; line = line.trim(); line = FileInfo.relativePath(absInputDir, line); result.push(line); } } finally { process.close(); } return result; } function qtQuickCompilerOutputName(filePath) { var str = filePath.replace(/\//g, '_'); var i = str.lastIndexOf('.'); if (i != -1) str = str.substr(0, i) + '_' + str.substr(i + 1); str += ".cpp"; return str; } function qtQuickResourceFileOutputName(fileName) { return fileName.replace(/\.qrc$/, "_qtquickcompiler.qrc"); } function contentFromQrc(product, qrcFilePath) { var supportsFiltering = product.Qt.quick._supportsQmlJsFiltering; var filesInQrc = scanQrc(product, qrcFilePath); var qmlJsFiles = filesInQrc.filter(function (filePath) { return (/\.(mjs|js|qml)$/).test(filePath); } ); var content = {}; if (!supportsFiltering || filesInQrc.length - qmlJsFiles.length > 0) { content.newQrcFileName = qtQuickResourceFileOutputName(input.fileName); } content.qmlJsFiles = qmlJsFiles.map(function (filePath) { return { input: filePath, output: qtQuickCompilerOutputName(filePath) }; }); return content; } function generateCompilerInputCommands(product, input, output) { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var content = contentFromQrc(product, input.filePath); content.qrcFilePath = input.filePath; var tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.write(JSON.stringify(content)); tf.close(); } return cmd; } function compilerOutputArtifacts(product, inputs) { var infos = []; inputs["qt.quick.qrcinfo"].forEach(function (input) { var tf = new TextFile(input.filePath, TextFile.ReadOnly); infos.push(JSON.parse(tf.readAll())); tf.close(); }); var result = []; infos.forEach(function (info) { if (info.newQrcFileName) { result.push({ filePath: info.newQrcFileName, fileTags: ["qrc"] }); } info.qmlJsFiles.forEach(function (qmlJsFile) { result.push({ filePath: qmlJsFile.output, fileTags: ["cpp"] }); }); }); result.push({ filePath: product.Qt.quick._generatedLoaderFileName, fileTags: ["cpp"] }); return result; } function compilerCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var infos = []; inputs["qt.quick.qrcinfo"].forEach(function (input) { var tf = new TextFile(input.filePath, TextFile.ReadOnly); infos.push(JSON.parse(tf.readAll())); tf.close(); }); var cmds = []; var qmlCompiler = product.Qt.quick.compilerFilePath; var useCacheGen = product.Qt.quick._compilerIsQmlCacheGen; var cmd; var loaderFlags = []; function findOutput(fileName) { for (var k in outputs) { for (var i in outputs[k]) { if (outputs[k][i].fileName === fileName) return outputs[k][i]; } } throw new Error("Qt Quick compiler rule: Cannot find output artifact " + fileName + "."); } infos.forEach(function (info) { if (info.newQrcFileName) { loaderFlags.push("--resource-file-mapping=" + FileInfo.fileName(info.qrcFilePath) + '=' + info.newQrcFileName); // Qt 5.15 doesn't really filter anyting but merely copies the qrc // content to the new location var args = ["--filter-resource-file", info.qrcFilePath]; if (useCacheGen) args.push("-o"); args.push(findOutput(info.newQrcFileName).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating " + info.newQrcFileName; cmds.push(cmd); } else { loaderFlags.push("--resource-file-mapping=" + info.qrcFilePath); } info.qmlJsFiles.forEach(function (qmlJsFile) { var args = ["--resource=" + info.qrcFilePath, qmlJsFile.input]; if (useCacheGen) args.push("-o"); args.push(findOutput(qmlJsFile.output).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating " + qmlJsFile.output; cmd.workingDirectory = FileInfo.path(info.qrcFilePath); cmds.push(cmd); }); }); var args = loaderFlags.concat(infos.map(function (info) { return info.qrcFilePath; })); if (useCacheGen) args.push("-o"); args.push(findOutput(product.Qt.quick._generatedLoaderFileName).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating loader source"; cmds.push(cmd); return cmds; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/scxml.qbs0000644000175100017510000000605215232633614024114 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities QtModule { qtModuleName: "Scxml" property string _qscxmlcDir: Utilities.versionCompare(Qt.core.version, "6.3") >= 0 ? Qt.core.libExecPath : Qt.core.binPath property string qscxmlcName: "qscxmlc" property string className property string namespace property bool generateStateMethods property stringList additionalCompilerFlags Rule { inputs: ["qt.scxml.compilable"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), input.baseName + ".h") fileTags: ["hpp", "unmocable"] } Artifact { filePath: input.baseName + ".cpp" fileTags: ["cpp", "unmocable", "qt.untranslatable"] } prepare: { var compilerName = product.moduleProperty("Qt.scxml", "qscxmlcName"); var compilerPath = FileInfo.joinPaths(input.Qt.scxml._qscxmlcDir, compilerName); var args = ["--header", outputs["hpp"][0].filePath, "--impl", outputs["cpp"][0].filePath]; var cxx98 = input.moduleProperty("cpp", "cxxLanguageVersion") === "c++98"; if (cxx98) args.push("-no-c++11"); var className = input.moduleProperty("Qt.scxml", "className"); if (className) args.push("--classname", className); var namespace = input.moduleProperty("Qt.scxml", "namespace"); if (namespace) args.push("--namespace", namespace); if (input.Qt.scxml.generateStateMethods && Utilities.versionCompare(product.Qt.scxml.version, "5.9") >= 0) { args.push("--statemethods"); } if (input.Qt.scxml.additionalCompilerFlags) args = args.concat(input.Qt.scxml.additionalCompilerFlags); args.push(input.filePath); var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "codegen"; return [cmd]; } } version: @version@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/quick.qbs0000644000175100017510000001116415232633614024102 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Utilities import 'quick.js' as QC QtModule { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@ } version: @version@ hasLibrary: @has_library@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ readonly property bool _compilerIsQmlCacheGen: Utilities.versionCompare(Qt.core.version, "5.11") >= 0 readonly property bool _supportsQmlJsFiltering: Utilities.versionCompare(Qt.core.version, "5.15") < 0 readonly property string _generatedLoaderFileName: _compilerIsQmlCacheGen ? "qmlcache_loader.cpp" : "qtquickcompiler_loader.cpp" property string _compilerBaseDir: _compilerIsQmlCacheGen ? Qt.core.qmlLibExecPath : Qt.core.binPath property string compilerBaseName: (_compilerIsQmlCacheGen ? "qmlcachegen" : "qtquickcompiler") property string compilerFilePath: FileInfo.joinPaths(_compilerBaseDir, compilerBaseName + FileInfo.executableSuffix()) property bool compilerAvailable: File.exists(compilerFilePath); property bool useCompiler: compilerAvailable && !_compilerIsQmlCacheGen Group { condition: useCompiler FileTagger { patterns: "*.qrc" fileTags: ["qt.quick.qrc"] priority: 100 } Scanner { inputs: 'qt.quick.qrc' searchPaths: [FileInfo.path(input.filePath)] scan: QC.scanQrc(product, input.filePath) } Rule { inputs: ["qt.quick.qrc"] Artifact { filePath: input.fileName + ".json" fileTags: ["qt.quick.qrcinfo"] } prepare: QC.generateCompilerInputCommands(product, input, output) } Rule { inputs: ["qt.quick.qrcinfo"] outputFileTags: ["cpp", "qrc", "qt.untranslatable"] multiplex: true outputArtifacts: QC.compilerOutputArtifacts(product, inputs) prepare: QC.compilerCommands.apply(QC, arguments) } } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/qdoc.js0000644000175100017510000000754015232633614023546 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function qdocArgs(product, input, outputDir) { var args = [input.filePath]; var qtVersion = ModUtils.moduleProperty(product, "versionMajor"); if (qtVersion >= 5) { args.push("-outputdir"); args.push(outputDir); } return args; } var _qdocDefaultFileTag = "qdoc-output"; function qdocFileTaggers() { var t = _qdocDefaultFileTag; return { ".qhp": [t, "qhp"], ".qhp.sha1": [t, "qhp-sha1"], ".css": [t, "qdoc-css"], ".html": [t, "qdoc-html"], ".index": [t, "qdoc-index"], ".png": [t, "qdoc-png"] }; } function outputArtifacts(product, input) { var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.defaultFileTags = [_qdocDefaultFileTag]; tracker.fileTaggers = qdocFileTaggers(); tracker.command = FileInfo.joinPaths(ModUtils.moduleProperty(product, "binPath"), ModUtils.moduleProperty(product, "qdocName")); tracker.commandArgsFunction = function (outputDirectory) { return qdocArgs(product, input, outputDirectory); }; tracker.commandEnvironmentFunction = function (outputDirectory) { var env = {}; var qdocEnv = ModUtils.moduleProperty(product, "qdocEnvironment"); for (var j = 0; j < qdocEnv.length; ++j) { var e = qdocEnv[j]; var idx = e.indexOf("="); var name = e.slice(0, idx); var value = e.slice(idx + 1, e.length); env[name] = value; } env["OUTDIR"] = outputDirectory; // Qt 4 replacement for -outputdir return env; }; return tracker.artifacts(ModUtils.moduleProperty(product, "qdocOutputDir")); } function commands(product, input) { var outputDir = product.Qt.core.qdocOutputDir; var args = qdocArgs(product, input, outputDir); var cmd = new Command(product.Qt.core.binPath + '/' + product.Qt.core.qdocName, args); cmd.description = 'qdoc ' + input.fileName; cmd.highlight = 'filegen'; cmd.environment = product.Qt.core.qdocEnvironment; cmd.environment.push("OUTDIR=" + outputDir); // Qt 4 replacement for -outputdir return cmd; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/rcc.js0000644000175100017510000001005215232633614023357 0ustar runnerrunnervar FileInfo = require("qbs.FileInfo"); var Utilities = require("qbs.Utilities"); var Xml = require("qbs.Xml"); function fullPath(product) { if (Utilities.versionCompare(product.Qt.core.version, "6.1") < 0) return product.Qt.core.binPath + '/' + product.Qt.core.rccName; return product.Qt.core.libExecPath + '/' + product.Qt.core.rccName; } function generateQrcFileCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var doc = new Xml.DomDocument("RCC"); var rccNode = doc.createElement("RCC"); rccNode.setAttribute("version", "1.0"); doc.appendChild(rccNode); var inputsByPrefix = {} for (var i = 0; i < inputs["qt.core.resource_data"].length; ++i) { var inp = inputs["qt.core.resource_data"][i]; var prefix = inp.Qt.core.resourcePrefix; var inputsList = inputsByPrefix[prefix] || []; inputsList.push(inp); inputsByPrefix[prefix] = inputsList; } for (var prefix in inputsByPrefix) { var qresourceNode = doc.createElement("qresource"); qresourceNode.setAttribute("prefix", prefix); rccNode.appendChild(qresourceNode); for (var i = 0; i < inputsByPrefix[prefix].length; ++i) { var inp = inputsByPrefix[prefix][i]; var fullResPath = inp.filePath; var baseDir = inp.Qt.core.resourceSourceBase; var resAlias = baseDir ? FileInfo.relativePath(baseDir, fullResPath) : inp.fileName; var fileNode = doc.createElement("file"); fileNode.setAttribute("alias", resAlias); qresourceNode.appendChild(fileNode); var fileTextNode = doc.createTextNode(fullResPath); fileNode.appendChild(fileTextNode); } } doc.save(output.filePath, 4); }; return [cmd]; } function rccOutputArtifacts(input) { var artifact = { filePath: "qrc_" + input.completeBaseName + ".cpp", fileTags: ["cpp"] }; if (input.Qt.core.enableBigResources) artifact.fileTags.push("cpp_intermediate_object"); return [artifact]; } function rccCommands(product, input, output) { var args = [input.filePath, "-name", FileInfo.completeBaseName(input.filePath), "-o", output.filePath]; if (input.Qt.core.enableBigResources) args.push("-pass", "1"); if (product.Qt.core.disabledFeatures.contains("zstd") && Utilities.versionCompare(product.Qt.core.version, "5.13") >= 0) { args.push("--no-zstd"); } var cmd = new Command(fullPath(product), args); cmd.description = "rcc " + (input.Qt.core.enableBigResources ? "(pass 1) " : "") + input.fileName; cmd.highlight = 'codegen'; return cmd; } function rccPass2Commands(product, input, output) { function findChild(artifact, predicate) { var children = artifact.children; var len = children.length; for (var i = 0; i < len; ++i) { var child = children[i]; if (predicate(child)) return child; child = findChild(child, predicate); if (child) return child; } return undefined; } var qrcArtifact = findChild(input, function(c) { return c.fileTags.contains("qrc"); }); var cppArtifact = findChild(input, function(c) { return c.fileTags.contains("cpp"); }); var cmd = new Command(fullPath(product), [qrcArtifact.filePath, "-temp", input.filePath, "-name", FileInfo.completeBaseName(input.filePath), "-o", output.filePath, "-pass", "2"]); cmd.description = "rcc (pass 2) " + qrcArtifact.fileName; cmd.highlight = 'codegen'; return cmd; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/core.js0000644000175100017510000000364215232633614023547 0ustar runnerrunnervar TextFile = require("qbs.TextFile"); function lreleaseCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var inputFilePaths; if (product.Qt.core.lreleaseMultiplexMode) inputFilePaths = inputs["ts"].map(function(artifact) { return artifact.filePath; }); else inputFilePaths = [input.filePath]; var args = ['-silent', '-qm', output.filePath].concat(inputFilePaths); var cmd = new Command(product.Qt.core.binPath + '/' + product.Qt.core.lreleaseName, args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'filegen'; return cmd; } function qhelpGeneratorCommands(product, input, output) { var args = [input.filePath]; args = args.concat(product.Qt.core.helpGeneratorArgs); args.push("-o"); args.push(output.filePath); var cmd = new Command( product.Qt.core.helpGeneratorLibExecPath + "/qhelpgenerator", args); cmd.description = 'qhelpgenerator ' + input.fileName; cmd.highlight = 'filegen'; cmd.stdoutFilterFunction = function(output) { return ""; }; return cmd; } function wasmQtHtmlCommands(product, output) { var cmd = new JavaScriptCommand(); cmd.description = "Generating Qt html for " + product.targetName; cmd.highlight = "filegen"; cmd.sourceCode = function() { var platformsPath = product.Qt.core.pluginPath + "/platforms"; var wasmShellFile = new TextFile(platformsPath + "/wasm_shell.html"); var content = wasmShellFile.readAll(); var appNameTemplate = "@APPNAME@"; var finalContent = content.replaceAll(appNameTemplate, product.name); var preload = "@PRELOAD@";//TODO: figure out what it's for finalContent = finalContent.replace(preload, ""); var finalHtmlFile = new TextFile(output.filePath, OpenMode = TextFile.WriteOnly); finalHtmlFile.write(finalContent); } return cmd; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/qmlcache.qbs0000644000175100017510000000563015232633614024544 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Process import qbs.Utilities Module { additionalProductTypes: ["qt.qml.qmlc", "qt.qml.jsc"] validate: { if (!qmlcachegenProbe.found) throw "qmlcachegen unsupported for this target"; } property string qmlCacheGenPath: FileInfo.joinPaths(Qt.core.qmlLibExecPath, "qmlcachegen") + FileInfo.executableSuffix() property bool supportsAllArchitectures: Utilities.versionCompare(Qt.core.version, "5.11") >= 0 property string installDir readonly property stringList _targetArgs: { if (supportsAllArchitectures) return []; function translateArch(arch) { if (arch === "x86") return "i386"; if (arch.startsWith("armv")) return "arm"; return arch; } var args = ["--target-architecture", translateArch(qbs.architecture)]; return args; } Depends { name: "Qt.core" } Probe { id: qmlcachegenProbe property string arch: qbs.architecture property string _qmlCacheGenPath: qmlCacheGenPath property stringList targetArgs: _targetArgs property bool _supportsAllArchitectures: supportsAllArchitectures configure: { if (_supportsAllArchitectures) { found = File.exists(_qmlCacheGenPath); return; } var process = new Process(); found = false; try { found = process.exec(_qmlCacheGenPath, targetArgs.concat("--check-if-supported")) == 0; if (!found) { var msg = "QML cache generation was requested but is unsupported on " + "architecture '" + arch + "'."; console.warn(msg); } } finally { process.close(); } } } Rule { condition: qmlcachegenProbe.found inputs: ["qt.qml.qml", "qt.qml.js"] outputArtifacts: [{ filePath: input.fileName + 'c', fileTags: input.fileTags.filter(function(tag) { return tag === "qt.qml.qml" || tag === "qt.qml.js"; })[0] + 'c' }] outputFileTags: ["qt.qml.qmlc", "qt.qml.jsc"] prepare: { var args = input.Qt.qmlcache._targetArgs.concat(input.filePath, "-o", output.filePath); var cmd = new Command(input.Qt.qmlcache.qmlCacheGenPath, args); cmd.description = "precompiling " + input.fileName; cmd.highlight = "compiler"; return cmd; } } Group { condition: product.Qt.qmlcache.installDir !== undefined fileTagsFilter: product.Qt.qmlcache.additionalProductTypes qbs.install: true qbs.installDir: product.Qt.qmlcache.installDir } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/android_support.qbs0000644000175100017510000001306215232633614026201 0ustar runnerrunnerimport qbs.FileInfo import qbs.ModUtils import qbs.Utilities import qbs.Xml import "android_support.js" as Impl Module { version: @version@ property string qmlRootDir: product.sourceDirectory property stringList extraPrefixDirs property stringList qmlImportPaths property stringList deploymentDependencies // qmake: ANDROID_DEPLOYMENT_DEPENDENCIES property stringList extraPlugins // qmake: ANDROID_EXTRA_PLUGINS property stringList extraLibs // qmake: ANDROID_EXTRA_LIBS property bool verboseAndroidDeployQt: false property string _androidDeployQtFilePath: FileInfo.joinPaths(_qtBinaryDir, "bin", "androiddeployqt") property string rccFilePath property string _qtBinaryDir property string _qtInstallDir property bool _enableSdkSupport: product.type && product.type.contains("android.package") && !product.consoleApplication property bool _enableNdkSupport: !product.aggregate || product.multiplexConfigurationId property string _templatesBaseDir: FileInfo.joinPaths(_qtInstallDir, "src", "android") property string _deployQtOutDir: FileInfo.joinPaths(product.buildDirectory, "deployqt_out") property bool _multiAbi: Utilities.versionCompare(version, "5.14") >= 0 // QTBUG-87288: correct QtNetwork jar dependencies for 5.15.0 < Qt < 5.15.3 property bool _correctQtNetworkDependencies: Utilities.versionCompare(version, "5.15.0") > 0 && Utilities.versionCompare(version, "5.15.3") < 0 readonly property string _qtAndroidJarFileName: Utilities.versionCompare(version, "6.0") >= 0 ? "Qt6Android.jar" : "QtAndroid.jar" Group { condition: _enableSdkSupport name: "helper sources from qt" Depends { name: "Android.sdk" } Depends { name: "java" } product.Android.sdk.customManifestProcessing: true product.Android.sdk._bundledInAssets: _multiAbi product.java._tagJniHeaders: false // prevent rule cycle Properties { condition: Utilities.versionCompare(version, "5.15") >= 0 && Utilities.versionCompare(version, "6.0") < 0 java.additionalClassPaths: [FileInfo.joinPaths(_qtInstallDir, "jar", "QtAndroid.jar")] } Properties { condition: Utilities.versionCompare(version, "6.0") >= 0 java.additionalClassPaths: [FileInfo.joinPaths(_qtInstallDir, "jar", "Qt6Android.jar")] Android.sdk.minimumVersion: "23" } Properties { condition: Utilities.versionCompare(version, "6.0") < 0 Android.sdk.minimumVersion: "21" } prefix: Qt.android_support._templatesBaseDir + "/java/" Android.sdk.aidlSearchPaths: prefix + "src" files: [ "**/*.java", "**/*.aidl", ] Rule { multiplex: true property stringList inputTags: ["android.nativelibrary", "qrc"] inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { filePath: "androiddeployqt.json" fileTags: "qt_androiddeployqt_input" } prepare: Impl.prepareDeployQtCommands.apply(Impl, arguments) } // We use the manifest template from the Qt installation if and only if the project // does not provide a manifest file. Rule { multiplex: true requiresInputs: false inputs: "android.manifest" excludedInputs: "qt.android_manifest" outputFileTags: ["android.manifest", "qt.android_manifest"] outputArtifacts: Impl.qtManifestOutputArtifacts(inputs) prepare: Impl.qtManifestCommands(product, output) } Rule { multiplex: true property stringList defaultInputs: ["qt_androiddeployqt_input", "android.manifest_processed"] property stringList allInputs: ["qt_androiddeployqt_input", "android.manifest_processed", "android.nativelibrary"] inputsFromDependencies: "android.nativelibrary" inputs: product.aggregate ? defaultInputs : allInputs outputFileTags: [ "android.manifest_final", "android.resources", "android.assets", "bundled_jar", "android.deployqt_list", ] outputArtifacts: Impl.deployQtOutputArtifacts(product) prepare: Impl.deployQtCommands.apply(Impl, arguments) } } Group { condition: _enableNdkSupport Depends { name: "cpp" } Depends { name: "Android.ndk" } product.Android.ndk.appStl: qbs.toolchain.contains("clang") ? "c++_shared" : "gnustl_shared" Properties { condition: _multiAbi cpp.archSuffix: "_" + Android.ndk.abi } // "ANDROID_HAS_WSTRING" was removed from qtcore qstring.h in Qt 5.14.0 Properties { condition: Utilities.versionCompare(version, "5.14.0") < 0 && (Android.ndk.abi === "armeabi-v7a" || Android.ndk.abi === "x86") cpp.defines: "ANDROID_HAS_WSTRING" } } validate: { if (Utilities.versionCompare(version, "5.12") < 0) throw ModUtils.ModuleError("Cannot use Qt " + version + " with Android. " + "Version 5.12 or later is required."); } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/qml.js0000644000175100017510000002204115232633614023402 0ustar runnerrunnervar File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); function scannerData(scannerFilePath, qmlFiles, qmlPath, hostOS) { var p; try { p = new Process(); if (!hostOS.contains("windows")) { p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]), true); return JSON.parse(p.readStdOut()); } var data = []; var nextFileIndex = 0; while (nextFileIndex < qmlFiles.length) { var currentFileList = []; var currentFileListStringLength = 0; while (nextFileIndex < qmlFiles.length && currentFileListStringLength < 30000) { var currentFile = qmlFiles[nextFileIndex++]; currentFileList.push(currentFile); currentFileListStringLength += currentFile.length; } p.exec(scannerFilePath, ["-qmlFiles"].concat(currentFileList) .concat(["-importPath", qmlPath]), true); data = data.concat(JSON.parse(p.readStdOut())); } return data; } finally { if (p) p.close(); } } function getPrlRhs(line) { return line.split('=')[1].trim(); } function getLibsForPlugin(pluginData, product) { var targetOS = product.qbs.targetOS; var toolchain = product.qbs.toolchain; var buildVariant = product.Qt.core.qtBuildVariant; var qtLibDir = product.Qt.core.libPath; var qtPluginDir = product.Qt.core.pluginPath; var qtDir = product.Qt.core.installPrefixPath; var qtQmlPath = product.Qt.qml.qmlPath; if (!pluginData.path) return ""; var prlFileName = ""; if (!targetOS.contains("windows")) prlFileName += "lib"; prlFileName += pluginData.plugin; if (buildVariant === "debug") { if (targetOS.contains("windows")) { prlFileName += "d"; } else if (product.Qt.core.versionMajor >= 6 && (targetOS.contains("ios") || targetOS.contains("tvos") || targetOS.contains("watchos"))) { prlFileName += "_debug"; } } prlFileName += ".prl"; var prlFilePath = FileInfo.joinPaths(pluginData.path, prlFileName); if (!File.exists(prlFilePath)) { console.warn("prl file for QML plugin '" + pluginData.plugin + "' not present at '" + prlFilePath + "'. Linking may fail."); return ""; } var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly); try { var pluginLib; var otherLibs = []; var line; while (!prlFile.atEof()) { line = prlFile.readLine().trim(); if (!line) continue; if (line.startsWith("QMAKE_PRL_TARGET")) pluginLib = FileInfo.joinPaths(pluginData.path, getPrlRhs(line)); if (line.startsWith("QMAKE_PRL_LIBS = ")) { var otherLibsLine = ' ' + getPrlRhs(line); if (toolchain.contains("msvc")) { otherLibsLine = otherLibsLine.replace(/ -L/g, " /LIBPATH:"); otherLibsLine = otherLibsLine.replace(/-l([^ ]+)/g, "$1" + ".lib"); } otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_LIBS\]/g, qtLibDir); otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PLUGINS\]/g, qtPluginDir); otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PREFIX\]/g, qtDir); otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_QML\]/g, qtQmlPath); otherLibs = otherLibs.concat(otherLibsLine.split(' ').map(FileInfo.cleanPath)); } } if (!pluginLib) throw "Malformed prl file '" + prlFilePath + "'."; return [pluginLib].concat(otherLibs); } finally { prlFile.close(); } } function typeRegistrarCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var versionParts = product.Qt.qml._importVersionParts; var args = [ "--generate-qmltypes=" + outputs["qt.qml.types"][0].filePath, "--import-name=" + product.Qt.qml.importName, "--major-version=" + versionParts[0], "--minor-version=" + (versionParts.length > 1 ? versionParts[1] : "0") ]; var foreignTypes = product.Qt.qml.extraMetaTypesFiles || []; var metaTypeArtifactsFromDeps = explicitlyDependsOn["qt.core.metatypes"] || []; var filePathFromArtifact = function(a) { return a.filePath; }; foreignTypes = foreignTypes.uniqueConcat(metaTypeArtifactsFromDeps.map(filePathFromArtifact)); if (foreignTypes.length > 0) args.push("--foreign-types=" + foreignTypes.join(",")); args.push("-o", outputs.cpp[0].filePath); args = args.concat(inputs["qt.core.metatypes"].map(filePathFromArtifact)); var cmd = new Command(product.Qt.core.qmlLibExecPath + "/qmltyperegistrar", args); cmd.description = "running qmltyperegistrar"; cmd.highlight = "codegen"; return cmd; } function generatePluginImportOutputArtifacts(product, inputs) { var list = []; if (inputs["qt.qml.qml"]) list.push({ filePath: "qml_plugin_import.cpp", fileTags: ["cpp"] }); list.push({ filePath: product.Qt.core.qtBuildVariant === "debug" ? product.Qt.qml.pluginListFilePathDebug : product.Qt.qml.pluginListFilePathRelease, fileTags: ["qt.qml.pluginlist"] }); return list; } function getCppLibsAndFrameworks(cpp) { var libs = {"frameworks": {}, "libraries": {}}; for (var i = 0; i < cpp.frameworks.length; ++i) libs.frameworks[cpp.frameworks[i]] = true; for (i = 0; i < cpp.staticLibraries.length; ++i) libs.libraries[cpp.staticLibraries[i]] = true; for (i = 0; i < cpp.dynamicLibraries.length; ++i) libs.libraries[cpp.dynamicLibraries[i]] = true; for (i = 0; i < cpp.libraries.length; ++i) libs.libraries[cpp.libraries[i]] = true; return libs; } function getUniqueLibs(libs, seen) { var uniqueLibs = []; for (var i = 0; i < libs.length; ++i) { if (libs[i] == "-framework") { var frameworkName = libs[i + 1]; if (frameworkName && !seen.frameworks[frameworkName]) { seen.frameworks[frameworkName] = true; uniqueLibs.push("-framework", frameworkName); } ++i; // Skip framework name } else { var libName; if (libs[i].startsWith("-l")) libName = libs[i].substr(2); else libName = libs[i]; if (!seen.libraries[libName]) { seen.libraries[libName] = true; uniqueLibs.push(libs[i]); } } } return uniqueLibs; } function generatePluginImportCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); if (inputs["qt.qml.qml"]) cmd.description = "creating " + outputs["cpp"][0].fileName; else cmd.silent = true; cmd.sourceCode = function() { var qmlInputs = inputs["qt.qml.qml"]; if (!qmlInputs) qmlInputs = []; var scannerData = Qml.scannerData(product.Qt.qml.qmlImportScannerFilePath, qmlInputs.map(function(inp) { return inp.filePath; }), product.Qt.qml.qmlPath, Host.os()); var cppFile; var listFile; try { if (qmlInputs.length > 0) cppFile = new TextFile(outputs["cpp"][0].filePath, TextFile.WriteOnly); listFile = new TextFile(outputs["qt.qml.pluginlist"][0].filePath, TextFile.WriteOnly); if (cppFile) cppFile.writeLine("#include "); var plugins = { }; var seen = Qml.getCppLibsAndFrameworks(product.cpp); var libsWithUniqueObjects = []; for (var p in scannerData) { var plugin = scannerData[p].plugin; if (!plugin || plugins[plugin]) continue; plugins[plugin] = true; var className = scannerData[p].classname; if (!className) { throw "QML plugin '" + plugin + "' is missing a classname entry. " + "Please add one to the qmldir file."; } if (cppFile) cppFile.writeLine("Q_IMPORT_PLUGIN(" + className + ")"); var libs = Qml.getLibsForPlugin(scannerData[p], product); var uniqueLibs = Qml.getUniqueLibs(libs, seen); libsWithUniqueObjects = libsWithUniqueObjects.concat(uniqueLibs); } listFile.write(libsWithUniqueObjects.join("\n")); } finally { if (cppFile) cppFile.close(); if (listFile) listFile.close(); }; }; return [cmd]; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/android_support.js0000644000175100017510000004664315232633614026043 0ustar runnerrunnervar File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function prepareDeployQtCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var theBinary; var nativeLibs = inputs["android.nativelibrary"]; var architectures = []; var triples = []; var qtInstallDirectories = []; var hostArch; var targetArchitecture; if (nativeLibs.length === 1) { theBinary = nativeLibs[0]; hostArch = theBinary.Android.ndk.hostArch; targetArchitecture = theBinary.Android.ndk.abi; if (product.Qt.android_support._multiAbi) { architectures.push(theBinary.Android.ndk.abi); triples.push(theBinary.cpp.toolchainTriple); qtInstallDirectories.push(theBinary.Qt.android_support._qtInstallDir); } } else { for (i = 0; i < nativeLibs.length; ++i) { var candidate = nativeLibs[i]; if (product.Qt.android_support._multiAbi) { if (candidate.product.name === product.name) { architectures.push(candidate.Android.ndk.abi); triples.push(candidate.cpp.toolchainTriple); qtInstallDirectories.push( candidate.Qt.android_support._qtInstallDir); hostArch = candidate.Android.ndk.hostArch; targetArchitecture = candidate.Android.ndk.abi; theBinary = candidate; } } else { if (!candidate.fileName.contains(candidate.product.targetName)) continue; if (!theBinary) { theBinary = candidate; hostArch = theBinary.Android.ndk.hostArch; targetArchitecture = theBinary.Android.ndk.abi; continue; } if (candidate.product.name !== product.name) { continue; // This is not going to be a match } if (candidate.product.name === product.name && theBinary.product.name !== product.name) { theBinary = candidate; // The new candidate is a better match. hostArch = theBinary.Android.ndk.hostArch; targetArchitecture = theBinary.Android.ndk.abi; continue; } throw "Qt applications for Android support only one native binary " + "per package.\n" + "In particular, you cannot build a Qt app for more than " + "one architecture at the same time."; } } } var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("{"); f.writeLine('"description": "This file was generated by qbs to be read by ' + 'androiddeployqt and should not be modified by hand.",'); if (Utilities.versionCompare(product.Qt.core.version, "6.3.0") >= 0) { var line = '"qt": {'; for (var i = 0; i < qtInstallDirectories.length && i < architectures.length; ++i) { line = line + '"' + architectures[i] + '":"' + qtInstallDirectories[i] + '"'; if (i < qtInstallDirectories.length-1 || i < architectures.length-1) line = line + ','; } line = line + "},"; f.writeLine(line); } else { f.writeLine('"qt": "' + product.Qt.android_support._qtInstallDir + '",'); } f.writeLine('"sdk": "' + product.Android.sdk.sdkDir + '",'); f.writeLine('"sdkBuildToolsRevision": "' + product.Android.sdk.buildToolsVersion + '",'); f.writeLine('"ndk": "' + product.Android.sdk.ndkDir + '",'); f.writeLine('"toolchain-prefix": "llvm",'); f.writeLine('"tool-prefix": "llvm",'); f.writeLine('"useLLVM": true,'); f.writeLine('"ndk-host": "' + hostArch + '",'); if (!product.Qt.android_support._multiAbi) { f.writeLine('"target-architecture": "' + targetArchitecture + '",'); } else { var line = '"architectures": {'; for (var i in architectures) { line = line + '"' + architectures[i] + '":"' + triples[i] + '"'; if (i < architectures.length-1) line = line + ','; } line = line + "},"; f.writeLine(line); } f.writeLine('"qml-root-path": "' + product.Qt.android_support.qmlRootDir + '",'); var deploymentDeps = product.Qt.android_support.deploymentDependencies; if (deploymentDeps && deploymentDeps.length > 0) f.writeLine('"deployment-dependencies": "' + deploymentDeps.join() + '",'); var extraPlugins = product.Qt.android_support.extraPlugins; if (extraPlugins && extraPlugins.length > 0) f.writeLine('"android-extra-plugins": "' + extraPlugins.join() + '",'); var extraLibs = product.Qt.android_support.extraLibs; if (extraLibs && extraLibs.length > 0) { for (var i = 0; i < extraLibs.length; ++i) { if (!FileInfo.isAbsolutePath(extraLibs[i])) { extraLibs[i] = FileInfo.joinPaths(product.sourceDirectory, extraLibs[i]); } } f.writeLine('"android-extra-libs": "' + extraLibs.join() + '",'); } var prefixDirs = product.Qt.android_support.extraPrefixDirs; if (prefixDirs && prefixDirs.length > 0) f.writeLine('"extraPrefixDirs": ' + JSON.stringify(prefixDirs) + ','); var qmlImportPaths = product.Qt.android_support.qmlImportPaths; if (qmlImportPaths && qmlImportPaths.length > 0) f.writeLine('"qml-import-paths": "' + qmlImportPaths.join(',') + '",'); else if ((product.qmlImportPaths instanceof Array) && product.qmlImportPaths.length > 0) f.writeLine('"qml-import-paths": "' + product.qmlImportPaths.join(',') + '",'); if (Utilities.versionCompare(product.Qt.android_support.version, "6.0") >= 0) { f.writeLine('"qml-importscanner-binary": "' + product.Qt.core.qmlImportScannerFilePath + FileInfo.executableSuffix() + '",'); f.writeLine('"rcc-binary": "' + product.Qt.android_support.rccFilePath + FileInfo.executableSuffix() + '",'); if (inputs["qrc"] && inputs["qrc"].length > 0) { var qrcFiles = []; var qrcInputs = inputs["qrc"]; for (i = 0; i < qrcInputs.length; ++i) { qrcFiles.push(qrcInputs[i].filePath); } f.writeLine('"qrcFiles": "' + qrcFiles.join(',') + '",'); } } // QBS-1429 if (!product.Qt.android_support._multiAbi) { f.writeLine('"stdcpp-path": "' + (product.cpp.sharedStlFilePath ? product.cpp.sharedStlFilePath : product.cpp.staticStlFilePath) + '",'); f.writeLine('"application-binary": "' + theBinary.filePath + '"'); } else { f.writeLine('"stdcpp-path": "' + product.Android.sdk.ndkDir + '/toolchains/llvm/prebuilt/' + hostArch + '/sysroot/usr/lib/",'); f.writeLine('"application-binary": "' + theBinary.product.targetName + '"'); } f.writeLine("}"); f.close(); }; return cmd; } function qtManifestOutputArtifacts(inputs) { if (inputs["android.manifest"]) return []; return [{ filePath: "qt_manifest/AndroidManifest.xml", fileTags: ["android.manifest", "qt.android_manifest"] }]; } function qtManifestCommands(product, output) { var cmd = new JavaScriptCommand(); cmd.description = "copying Qt Android manifest template"; cmd.sourceCode = function() { File.copy(FileInfo.joinPaths(product.Qt.android_support._templatesBaseDir, "templates", "AndroidManifest.xml"), output.filePath); }; return cmd; } function deployQtOutputArtifacts(product) { return [ { filePath: "AndroidManifest.xml", fileTags: "android.manifest_final" }, { filePath: product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml", fileTags: "android.resources" }, { filePath: product.Qt.android_support._deployQtOutDir + "/res/values/strings.xml", fileTags: "android.resources" }, { filePath: product.Qt.android_support._deployQtOutDir + "/assets/.dummy", fileTags: "android.assets" }, { filePath: "deployqt.list", fileTags: "android.deployqt_list" }, // androiddeployqt potentially copies more jar files but this one will always be there // since it comes with Qt.core { filePath: FileInfo.joinPaths(product.java.classFilesDir, product.Qt.android_support._qtAndroidJarFileName), fileTags: "bundled_jar" } ]; } function deployQtCommands(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var copyCmd = new JavaScriptCommand(); copyCmd.description = "copying Qt resource templates"; copyCmd.sourceCode = function() { File.copy(inputs["android.manifest_processed"][0].filePath, product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml"); File.copy(product.Qt.android_support._templatesBaseDir + "/java/res", product.Qt.android_support._deployQtOutDir + "/res"); File.copy(product.Qt.android_support._templatesBaseDir + "/templates/res/values/libs.xml", product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml"); if (!product.Qt.android_support._multiAbi) { try { File.remove(FileInfo.path(outputs["android.assets"][0].filePath)); } catch (e) { } } else { for (var i in inputs["android.nativelibrary"]) { var input = inputs["android.nativelibrary"][i]; File.copy(input.filePath, FileInfo.joinPaths(product.Qt.android_support._deployQtOutDir, "libs", input.Android.ndk.abi, input.fileName)); } } }; cmds.push(copyCmd); var androidDeployQtArgs = [ "--output", product.Qt.android_support._deployQtOutDir, "--input", inputs["qt_androiddeployqt_input"][0].filePath, "--aux-mode", "--deployment", "bundled", "--android-platform", product.Android.sdk.platform, ]; if (product.Qt.android_support.verboseAndroidDeployQt) androidDeployQtArgs.push("--verbose"); var androidDeployQtCmd = new Command( product.Qt.android_support._androidDeployQtFilePath, androidDeployQtArgs); androidDeployQtCmd.description = "running androiddeployqt"; cmds.push(androidDeployQtCmd); // We do not want androiddeployqt to write directly into our APK base dir, so // we ran it on an isolated directory and now we move stuff over. // We remember the files for which we do that, so if the next invocation // of androiddeployqt creates fewer files, the other ones are removed from // the APK base dir. var moveCmd = new JavaScriptCommand(); moveCmd.description = "processing androiddeployqt output"; moveCmd.sourceCode = function() { File.makePath(product.java.classFilesDir); var libsDir = product.Qt.android_support._deployQtOutDir + "/libs"; var libDir = product.Android.sdk.packageContentsDir + "/lib"; var listFilePath = outputs["android.deployqt_list"][0].filePath; var oldLibs = []; try { var listFile = new TextFile(listFilePath, TextFile.ReadOnly); var listFileLine = listFile.readLine(); while (listFileLine) { oldLibs.push(listFileLine); listFileLine = listFile.readLine(); } listFile.close(); } catch (e) { } listFile = new TextFile(listFilePath, TextFile.WriteOnly); var newLibs = []; var moveLibFiles = function(prefix) { var fullSrcPrefix = FileInfo.joinPaths(libsDir, prefix); var files = File.directoryEntries(fullSrcPrefix, File.Files); for (var i = 0; i < files.length; ++i) { var file = files[i]; var srcFilePath = FileInfo.joinPaths(fullSrcPrefix, file); var targetFilePath; if (file.endsWith(".jar")) targetFilePath = FileInfo.joinPaths(product.java.classFilesDir, file); else targetFilePath = FileInfo.joinPaths(libDir, prefix, file); File.move(srcFilePath, targetFilePath); listFile.writeLine(targetFilePath); newLibs.push(targetFilePath); } var dirs = File.directoryEntries(fullSrcPrefix, File.Dirs | File.NoDotAndDotDot); for (i = 0; i < dirs.length; ++i) moveLibFiles(FileInfo.joinPaths(prefix, dirs[i])); }; moveLibFiles(""); listFile.close(); for (i = 0; i < oldLibs.length; ++i) { if (!newLibs.contains(oldLibs[i])) File.remove(oldLibs[i]); } }; cmds.push(moveCmd); // androiddeployqt doesn't strip the deployed libraries anymore so it has to done here // but only for release build if (product.qbs.buildVariant == "release") { var stripLibsCmd = new JavaScriptCommand(); stripLibsCmd.description = "stripping unneeded symbols from deployed qt libraries"; stripLibsCmd.sourceCode = function() { var stripArgs = ["--strip-all"]; var architectures = []; for (var i in inputs["android.nativelibrary"]) architectures.push(inputs["android.nativelibrary"][i].Android.ndk.abi); for (var i in architectures) { var abiDirPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", architectures[i]); var files = File.directoryEntries(abiDirPath, File.Files); for (var i = 0; i < files.length; ++i) { var filePath = FileInfo.joinPaths(abiDirPath, files[i]); if (FileInfo.suffix(filePath) == "so") { stripArgs.push(filePath); } } } var process = new Process(); process.exec(product.cpp.stripPath, stripArgs, false); } cmds.push(stripLibsCmd); } var correctingCmd = new JavaScriptCommand(); if (product.Qt.android_support._correctQtNetworkDependencies) { correctingCmd.description = "correcting network jar dependency"; correctingCmd.sourceCode = function() { var findNetworkLib = function() { var libsDir = product.Android.sdk.packageContentsDir + "/lib"; var dirList = File.directoryEntries(libsDir, File.Dirs | File.NoDotAndDotDot); for (var i = 0; i < dirList.length; ++i) { var archDir = FileInfo.joinPaths(libsDir, dirList[i]); var fileList = File.directoryEntries(archDir, File.Files); if (fileList) { for (var j = 0; j < fileList.length; ++j) { if (fileList[j].contains("libQt5Network")) { return true; } } } } return false; } if (findNetworkLib()) { var manifestData = new Xml.DomDocument(); var manifestFilePath = product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml" manifestData.load(manifestFilePath); var rootElem = manifestData.documentElement(); if (!rootElem || !rootElem.isElement() || rootElem.tagName() != "manifest") throw "No manifest tag found in '" + manifestFilePath + "'."; var appElem = rootElem.firstChild("application"); if (!appElem || !appElem.isElement() || appElem.tagName() != "application") throw "No application tag found in '" + manifestFilePath + "'."; var activityElem = appElem.firstChild("activity"); if (!activityElem || !activityElem.isElement() || activityElem.tagName() != "activity") throw "No activity tag found in '" + manifestFilePath + "'."; var metaDataElem = activityElem.firstChild("meta-data"); while (metaDataElem && metaDataElem.isElement()) { if (metaDataElem.attribute("android:name") == "android.app.load_local_jars" ) { var value = metaDataElem.attribute("android:value"); var fileName = "QtAndroidNetwork.jar"; metaDataElem.setAttribute("android:value", value + ":jar/" + fileName); var jarFilePath = FileInfo.joinPaths( product.Qt.android_support._qtInstallDir, "jar", fileName); var targetFilePath = FileInfo.joinPaths(product.java.classFilesDir, fileName); File.copy(jarFilePath, targetFilePath); break; } metaDataElem = metaDataElem.nextSibling("meta-data"); } manifestData.save(outputs["android.manifest_final"][0].filePath, 4); } else { File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", outputs["android.manifest_final"][0].filePath); } }; } else { correctingCmd.description = "copying manifest"; correctingCmd.sourceCode = function() { File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", outputs["android.manifest_final"][0].filePath); } } cmds.push(correctingCmd); return cmds; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/moc.js0000644000175100017510000001320615232633614023372 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var ModUtils = require("qbs.ModUtils"); var Utilities = require("qbs.Utilities"); function args(product, input, outputs) { var defines = product.cpp.compilerDefinesByLanguage; if (input.fileTags.contains("objcpp")) defines = ModUtils.flattenDictionary(defines["objcpp"]) || []; else if (input.fileTags.contains("cpp") || input.fileTags.contains("hpp")) defines = ModUtils.flattenDictionary(defines["cpp"]) || []; else defines = []; defines = defines.uniqueConcat(product.cpp.platformDefines); defines = defines.uniqueConcat(input.cpp.defines); var includePaths = input.cpp.includePaths; includePaths = includePaths.uniqueConcat(input.cpp.systemIncludePaths); var useCompilerPaths = product.Qt.core.versionMajor >= 5; if (useCompilerPaths) { includePaths = includePaths.uniqueConcat(input.cpp.compilerIncludePaths); } var frameworkPaths = product.cpp.frameworkPaths; frameworkPaths = frameworkPaths.uniqueConcat( product.cpp.systemFrameworkPaths); if (useCompilerPaths) { frameworkPaths = frameworkPaths.uniqueConcat( product.cpp.compilerFrameworkPaths); } var pluginMetaData = product.Qt.core.pluginMetaData; var args = []; if (product.Qt.core._generateMetaTypesFile) args.push("--output-json"); var outputFileName; for (tag in outputs) { if (tag !== "qt.core.metatypes.in") { outputFileName = outputs[tag][0].filePath; break; } } args = args.concat( defines.map(function(item) { return '-D' + item; }), includePaths.map(function(item) { return '-I' + item; }), frameworkPaths.map(function(item) { return '-F' + item; }), pluginMetaData.map(function(item) { return '-M' + item; }), product.Qt.core.mocFlags, '-o', outputFileName, input.filePath); return args; } function fullPath(product) { if (Utilities.versionCompare(product.Qt.core.version, "6.1") < 0) return product.Qt.core.binPath + '/' + product.Qt.core.mocName; return product.Qt.core.libExecPath + '/' + product.Qt.core.mocName; } function outputArtifacts(project, product, inputs, input) { var mocInfo = QtMocScanner.apply(input); if (!mocInfo.hasQObjectMacro) return []; var artifact = { fileTags: ["unmocable"] }; if (mocInfo.hasPluginMetaDataMacro) artifact.explicitlyDependsOn = ["qt_plugin_metadata"]; if (input.fileTags.contains("hpp")) { artifact.filePath = input.Qt.core.generatedHeadersDir + "/moc_" + input.completeBaseName + ".cpp"; var amalgamate = input.Qt.core.combineMocOutput; artifact.fileTags.push(mocInfo.mustCompile ? (amalgamate ? "moc_cpp" : "cpp") : "hpp"); } else { artifact.filePath = input.Qt.core.generatedHeadersDir + '/' + input.completeBaseName + ".moc"; artifact.fileTags.push("hpp"); } var artifacts = [artifact]; if (product.Qt.core._generateMetaTypesFile) artifacts.push({filePath: artifact.filePath + ".json", fileTags: "qt.core.metatypes.in"}); return artifacts; } function commands(project, product, inputs, outputs, input, output) { var cmd = new Command(fullPath(product), args(product, input, outputs)); cmd.description = 'moc ' + input.fileName; cmd.highlight = 'codegen'; cmd.responseFileUsagePrefix = "@"; return cmd; } function generateMocCppCommands(inputs, output) { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["moc_cpp"], output.filePath); }; return [cmd]; } function generateMetaTypesCommands(inputs, output) { var inputFilePaths = inputs["qt.core.metatypes.in"].map(function(a) { return a.filePath; }); var cmd = new Command(fullPath(product), ["--collect-json", "-o", output.filePath].concat(inputFilePaths)); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.responseFileUsagePrefix = "@"; return cmd; } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/qml.qbs0000644000175100017510000001074015232633614023556 0ustar runnerrunnerimport qbs.FileInfo import qbs.Host import qbs.TextFile import "qml.js" as Qml QtModule { qtModuleName: "Qml" Depends { name: "Qt"; submodules: @dependencies@} property string qmlImportScannerName: Qt.core.qmlImportScannerName property string qmlImportScannerFilePath: Qt.core.qmlImportScannerFilePath property string qmlPath: @qmlPath@ property bool generateCacheFiles: false Depends { name: "Qt.qmlcache"; condition: generateCacheFiles; required: false } readonly property bool cachingEnabled: generateCacheFiles && Qt.qmlcache.present property string qmlCacheGenPath Properties { condition: cachingEnabled Qt.qmlcache.qmlCacheGenPath: qmlCacheGenPath || original Qt.qmlcache.installDir: cacheFilesInstallDir || original } property string cacheFilesInstallDir readonly property string pluginListFilePathDebug: product.buildDirectory + "/plugins.list.d" readonly property string pluginListFilePathRelease: product.buildDirectory + "/plugins.list" property bool linkPlugins: isStaticLibrary && Qt.plugin_support.linkPlugins version: @version@ hasLibrary: @has_library@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: (linkPlugins ? ['@' + pluginListFilePathDebug] : []).concat(@staticLibsDebug@) staticLibsRelease: (linkPlugins ? ['@' + pluginListFilePathRelease] : []).concat(@staticLibsRelease@) dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ FileTagger { patterns: ["*.qml"] fileTags: ["qt.qml.qml"] } FileTagger { patterns: ["*.js"] fileTags: ["qt.qml.js"] } // Type registration property string importName property string importVersion: product.version readonly property stringList _importVersionParts: (importVersion || "").split(".") property string typesFileName: { if (product.type && product.type.contains("application")) return product.targetName + ".qmltypes"; return "plugins.qmltypes"; } property string typesInstallDir property stringList extraMetaTypesFiles Group { condition: importName product.Qt.core.generateMetaTypesFile: true Rule { inputs: "qt.core.metatypes" multiplex: true explicitlyDependsOnFromDependencies: "qt.core.metatypes" Artifact { filePath: product.targetName.toLowerCase() + "_qmltyperegistrations.cpp" fileTags: ["cpp", "unmocable", "qt.untranslatable"] } Artifact { filePath: product.Qt.qml.typesFileName fileTags: "qt.qml.types" qbs.install: product.Qt.qml.typesInstallDir qbs.installDir: product.Qt.qml.typesInstallDir } prepare: Qml.typeRegistrarCommands.apply(Qml, arguments) } } Rule { condition: linkPlugins multiplex: true requiresInputs: false inputs: ["qt.qml.qml"] outputFileTags: ["cpp", "qt.qml.pluginlist", "qt.untranslatable"] outputArtifacts: Qml.generatePluginImportOutputArtifacts(product, inputs) prepare: Qml.generatePluginImportCommands.apply(Qml, arguments) } validate: { if (importName) { if (!importVersion) throw "Qt.qml.importVersion must be set if Qt.qml.importName is set."; var isInt = function(value) { return !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10)); } if (!isInt(_importVersionParts[0]) || (_importVersionParts.length > 1 && !isInt(_importVersionParts[1]))) { throw "Qt.qml.importVersion must be of the form x.y, where x and y are integers."; } } } } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/core.qbs0000644000175100017510000004631015232633614023717 0ustar runnerrunnerimport qbs.FileInfo import qbs.ModUtils import qbs.TextFile import qbs.Utilities import "core.js" as Core import "moc.js" as Moc import "qdoc.js" as Qdoc import "rcc.js" as Rcc Module { condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild) && (!qbs.architecture || architectures.length === 0 || architectures.contains(qbs.architecture)) readonly property bool isCombinedUIKitBuild: ["ios", "tvos", "watchos"].contains(targetPlatform) && (!qbs.architecture || ["x86", "x86_64"].contains(qbs.architecture)) && qbs.targetPlatform === targetPlatform + "-simulator" Depends { name: "cpp" } Depends { name: "Sanitizers.address"; condition: config.contains("sanitize_address") } Group { condition: qbs.targetOS.contains("android") Depends { name: "Qt.android_support" } product.Qt.android_support._qtBinaryDir: FileInfo.path(binPath) product.Qt.android_support._qtInstallDir: FileInfo.path(installPath) product.Qt.android_support.version: version product.Qt.android_support.rccFilePath: Rcc.fullPath(product) } // qmlImportScanner is required by androiddeployqt even if the project doesn't // depend on qml. That's why the scannerName must be defined here and not in the // qml module property string qmlImportScannerName: "qmlimportscanner" property string qmlImportScannerFilePath: qmlLibExecPath + '/' + qmlImportScannerName version: @version@ property stringList architectures: @archs@ property string targetPlatform: @targetPlatform@ property string libInfix: @libInfix@ property stringList config: @config@ property stringList qtConfig: @qtConfig@ readonly property stringList enabledFeatures: @enabledFeatures@ readonly property stringList disabledFeatures: @disabledFeatures@ property path binPath: @binPath@ property path installPath: @installPath@ property path incPath: @incPath@ property path libPath: @libPath@ property path installPrefixPath: @installPrefixPath@ property path libExecPath: @libExecPath@ property path qmlLibExecPath: @qmlLibExecPath@ property path pluginPath: @pluginPath@ property string mkspecName: @mkspecName@ property path mkspecPath: @mkspecPath@ property string mocName: "moc" property stringList mocFlags: [] property string lreleaseName: "lrelease" property string lupdateName: "lupdate" property string rccName: "rcc" property string qdocName: versionMajor >= 5 ? "qdoc" : "qdoc3" property stringList qdocEnvironment property path docPath: @docPath@ property path translationsPath: @translationsPath@ property string helpGeneratorLibExecPath: @helpGeneratorLibExecPath@ property stringList helpGeneratorArgs: versionMajor >= 5 ? ["-platform", "minimal"] : [] property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property bool frameworkBuild: @frameworkBuild@ property bool staticBuild: @staticBuild@ property bool multiThreading: @multiThreading@ property stringList pluginMetaData: [] property bool enableKeywords: true property bool generateMetaTypesFile readonly property bool _generateMetaTypesFile: generateMetaTypesFile && Utilities.versionCompare(version, "5.15") >= 0 property string metaTypesInstallDir property stringList availableBuildVariants: @availableBuildVariants@ property string qtBuildVariant: { if (availableBuildVariants.contains(qbs.buildVariant)) return qbs.buildVariant; if (qbs.buildVariant === "profiling" && availableBuildVariants.contains("release")) return "release"; return availableBuildVariants.length > 0 ? availableBuildVariants[0] : ""; } property stringList staticLibsDebug: @staticLibsDebug@ property stringList staticLibsRelease: @staticLibsRelease@ property stringList dynamicLibsDebug: @dynamicLibsDebug@ property stringList dynamicLibsRelease: @dynamicLibsRelease@ property stringList staticLibs: qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList linkerFlagsDebug: @linkerFlagsDebug@ property stringList linkerFlagsRelease: @linkerFlagsRelease@ property stringList coreLinkerFlags: qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease property stringList frameworksDebug: @frameworksDebug@ property stringList frameworksRelease: @frameworksRelease@ property stringList coreFrameworks: qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList frameworkPathsDebug: @frameworkPathsDebug@ property stringList frameworkPathsRelease: @frameworkPathsRelease@ property stringList coreFrameworkPaths: qtBuildVariant === "debug" ? frameworkPathsDebug : frameworkPathsRelease property string libNameForLinkerDebug: @libNameForLinkerDebug@ property string libNameForLinkerRelease: @libNameForLinkerRelease@ property string libNameForLinker: qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug: @libFilePathDebug@ property string libFilePathRelease: @libFilePathRelease@ property string libFilePath: qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease property bool useRPaths: qbs.targetOS.contains("linux") && !qbs.targetOS.contains("android") property stringList coreLibPaths: @libraryPaths@ property bool hasLibrary: true // These are deliberately not path types // We don't want to resolve them against the source directory property string generatedHeadersDir: product.buildDirectory + "/qt.headers" property string qdocOutputDir: product.buildDirectory + "/qdoc_html" property string qmDir: product.destinationDirectory property string qmBaseName: product.targetName property bool lreleaseMultiplexMode: false property stringList moduleConfig: @moduleConfig@ Properties { condition: moduleConfig.contains("use_gold_linker") cpp.linkerVariant: "gold" } Properties { condition: Utilities.versionCompare(version, "6") >= 0 cpp.cxxLanguageVersion: "c++17" } Properties { condition: Utilities.versionCompare(version, "6") < 0 && Utilities.versionCompare(version, "5.7.0") >= 0 cpp.cxxLanguageVersion: "c++11" } cpp.enableCompilerDefinesByLanguage: ["cpp"].concat( qbs.targetOS.contains("darwin") ? ["objcpp"] : []) cpp.defines: { var defines = @defines@; // ### QT_NO_DEBUG must be added if the current build variant is not derived // from the build variant "debug" if (!qbs.enableDebugCode) defines.push("QT_NO_DEBUG"); if (!enableKeywords) defines.push("QT_NO_KEYWORDS"); if (qbs.targetOS.containsAny(["ios", "tvos"])) { defines = defines.concat(["DARWIN_NO_CARBON", "QT_NO_CORESERVICES", "QT_NO_PRINTER", "QT_NO_PRINTDIALOG"]); if (Utilities.versionCompare(version, "5.6.0") < 0) defines.push("main=qtmn"); } if (qbs.toolchain.contains("msvc")) defines.push("_ENABLE_EXTENDED_ALIGNED_STORAGE"); return defines; } cpp.driverFlags: { var flags = []; if (qbs.toolchain.contains("gcc")) { if (config.contains("sanitize_undefined")) flags.push("-fsanitize=undefined"); if (config.contains("sanitize_thread")) flags.push("-fsanitize=thread"); if (config.contains("sanitize_memory")) flags.push("-fsanitize=memory"); } return flags; } cpp.includePaths: generatedHeadersDir cpp.systemIncludePaths: @includes@.concat(mkspecPath) cpp.libraryPaths: { var libPaths = [libPath]; if (staticBuild && pluginPath) libPaths.push(pluginPath + "/platforms"); libPaths = libPaths.concat(coreLibPaths); return libPaths; } cpp.staticLibraries: { var libs = []; if (qbs.targetOS.contains('windows') && !product.consoleApplication) { libs = libs.concat(qtBuildVariant === "debug" ? @entryPointLibsDebug@ : @entryPointLibsRelease@); } libs = libs.concat(staticLibs); return libs; } cpp.dynamicLibraries: dynamicLibs cpp.linkerFlags: coreLinkerFlags cpp.systemFrameworkPaths: coreFrameworkPaths.concat(frameworkBuild ? [libPath] : []) cpp.frameworks: { var frameworks = coreFrameworks if (frameworkBuild) frameworks.push(libNameForLinker); if (qbs.targetOS.contains('ios') && staticBuild) frameworks = frameworks.concat(["Foundation", "CoreFoundation"]); if (frameworks.length === 0) return undefined; return frameworks; } cpp.rpaths: useRPaths ? libPath : undefined cpp.rpathLinkDirs: useRPaths ? undefined : libPath Properties { condition: qbs.toolchain.contains("msvc") && config.contains("static_runtime") cpp.runtimeLibrary: "static" } Properties { condition: qbs.toolchain.contains("msvc") && !config.contains("static_runtime") cpp.runtimeLibrary: "dynamic" } Properties { condition: versionMajor >= 5 cpp.positionIndependentCode: true } cpp.cxxFlags: { var flags = []; if (qbs.toolchain.contains('msvc')) { if (versionMajor < 5) flags.push('/Zc:wchar_t-'); if (Utilities.versionCompare(version, "6.3") >= 0 && Utilities.versionCompare(cpp.compilerVersion, "19.10") >= 0) { flags.push("/permissive-"); } } if (qbs.toolchain.includes("emscripten") && multiThreading) flags.push("-pthread"); return flags; } Properties { condition: qbs.targetOS.contains('darwin') && qbs.toolchain.contains('clang') && config.contains('c++11') cpp.cxxStandardLibrary: "libc++" } Properties { condition: qbs.toolchain.includes("emscripten") cpp.driverLinkerFlags: { var flags = [ "-sMAX_WEBGL_VERSION=2", "-sFETCH=1", "-sWASM_BIGINT=1", "-sMODULARIZE", "-sEXPORT_NAME=createQtAppInstance", "-sALLOW_MEMORY_GROWTH", '-sASYNCIFY_IMPORTS=["qt_asyncify_suspend_js", "qt_asyncify_resume_js"]', '-sEXPORTED_RUNTIME_METHODS=["UTF16ToString", "stringToUTF16", "JSEvents", "specialHTMLTargets", "FS", "callMain"]', "-lembind" ]; if (multiThreading) flags.push("-pthread") return flags; } } cpp.minimumWindowsVersion: @minWinVersion_optional@ cpp.minimumMacosVersion: @minMacVersion_optional@ cpp.minimumIosVersion: @minIosVersion_optional@ cpp.minimumTvosVersion: @minTvosVersion_optional@ cpp.minimumWatchosVersion: @minWatchosVersion_optional@ cpp.minimumAndroidVersion: @minAndroidVersion_optional@ // Universal Windows Platform support cpp.windowsApiFamily: mkspecName.startsWith("winrt-") ? "pc" : undefined cpp.windowsApiAdditionalPartitions: mkspecPath.startsWith("winrt-") ? ["phone"] : undefined cpp.requireAppContainer: mkspecName.startsWith("winrt-") additionalProductTypes: ["qm", "qt.core.metatypes"] validate: { var validator = new ModUtils.PropertyValidator("Qt.core"); validator.setRequiredProperty("binPath", binPath); validator.setRequiredProperty("incPath", incPath); validator.setRequiredProperty("libPath", libPath); validator.setRequiredProperty("mkspecPath", mkspecPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("config", config); validator.setRequiredProperty("qtConfig", qtConfig); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); if (!staticBuild) validator.setRequiredProperty("pluginPath", pluginPath); // Allow custom version suffix since some distributions might want to do this, // but otherwise the version must start with a valid 3-component string validator.addVersionValidator("version", version, 3, 3, true); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addCustomValidator("availableBuildVariants", availableBuildVariants, function (v) { return v.length > 0; }, "the Qt installation supports no build variants"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return availableBuildVariants.contains(variant); }, "'" + qtBuildVariant + "' is not supported by this Qt installation"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return variant === qbs.buildVariant || !qbs.toolchain.contains("msvc"); }, " is '" + qtBuildVariant + "', but qbs.buildVariant is '" + qbs.buildVariant + "', which is not allowed when using MSVC"); validator.addFileNameValidator("resourceFileBaseName", resourceFileBaseName); validator.validate(); } FileTagger { patterns: ["*.qrc"] fileTags: ["qrc"] } Scanner { inputs: ["qrc"] pluginName: "qt_qrc_scanner" } FileTagger { patterns: ["*.ts"] fileTags: ["ts"] } FileTagger { patterns: ["*.qdoc", "*.qdocinc"] fileTags: ["qdoc"] } FileTagger { patterns: ["*.qdocconf"] fileTags: ["qdocconf"] } FileTagger { patterns: ["*.qhp"] fileTags: ["qhp"] } property bool combineMocOutput: cpp.combineCxxSources property bool enableBigResources: false // Product should not moc in the aggregate when multiplexing. property bool enableMoc: !(product.multiplexed || product.aggregate) || product.multiplexConfigurationId Group { condition: enableMoc Rule { name: "QtCoreMocRuleCpp" property string cppInput: cpp.combineCxxSources ? "cpp.combine" : "cpp" property string objcppInput: cpp.combineObjcxxSources ? "objcpp.combine" : "objcpp" inputs: [objcppInput, cppInput] auxiliaryInputs: "qt_plugin_metadata" excludedInputs: "unmocable" outputFileTags: ["hpp", "unmocable", "qt.core.metatypes.in", "qt.untranslatable"] outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments) prepare: Moc.commands.apply(Moc, arguments) } Rule { name: "QtCoreMocRuleHpp" inputs: "hpp" auxiliaryInputs: ["qt_plugin_metadata", "cpp", "objcpp"] excludedInputs: "unmocable" outputFileTags: ["hpp", "cpp", "moc_cpp", "unmocable", "qt.core.metatypes.in", "qt.untranslatable"] outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments) prepare: Moc.commands.apply(Moc, arguments) } } Rule { multiplex: true inputs: ["moc_cpp"] Artifact { filePath: "amalgamated_moc_" + product.targetName + ".cpp" fileTags: ["cpp", "unmocable", "qt.untranslatable"] } prepare: Moc.generateMocCppCommands(inputs, output) } Rule { multiplex: true inputs: "qt.core.metatypes.in" Artifact { filePath: product.targetName.toLowerCase() + "_metatypes.json" fileTags: "qt.core.metatypes" qbs.install: product.Qt.core.metaTypesInstallDir qbs.installDir: product.Qt.core.metaTypesInstallDir } prepare: Moc.generateMetaTypesCommands(inputs, output) } property path resourceSourceBase property string resourcePrefix: "/" property string resourceFileBaseName: product.targetName Rule { multiplex: true inputs: ["qt.core.resource_data"] Artifact { filePath: product.Qt.core.resourceFileBaseName + ".qrc" fileTags: ["qrc"] } prepare: Rcc.generateQrcFileCommands.apply(Rcc, arguments) } Rule { inputs: ["qrc"] outputFileTags: ["cpp", "cpp_intermediate_object", "qt.untranslatable"] outputArtifacts: Rcc.rccOutputArtifacts(input) prepare: Rcc.rccCommands(product, input, output) } Rule { inputs: ["intermediate_obj"] Artifact { filePath: input.completeBaseName + ".2" + input.cpp.objectSuffix fileTags: ["obj"] } prepare: Rcc.rccPass2Commands(product, input, output) } Rule { inputs: ["ts"] multiplex: lreleaseMultiplexMode Artifact { filePath: FileInfo.joinPaths(product.Qt.core.qmDir, (product.Qt.core.lreleaseMultiplexMode ? product.Qt.core.qmBaseName : input.baseName) + ".qm") fileTags: ["qm"] } prepare: Core.lreleaseCommands.apply(Core, arguments) } Rule { inputs: "qdocconf-main" explicitlyDependsOn: ["qdoc", "qdocconf"] outputFileTags: ModUtils.allFileTags(Qdoc.qdocFileTaggers()) outputArtifacts: Qdoc.outputArtifacts(product, input) prepare: Qdoc.commands(product, input) } Rule { inputs: "qhp" auxiliaryInputs: ModUtils.allFileTags(Qdoc.qdocFileTaggers()) .filter(function(tag) { return tag !== "qhp"; }) Artifact { filePath: input.completeBaseName + ".qch" fileTags: ["qch"] } prepare: Core.qhelpGeneratorCommands(product, input, output) } Group { condition: qbs.toolchain.includes("emscripten") && (product.type.includes("application") && product.type.includes("qthtml")) Rule { inputs: ["application"] multiplex: true Artifact { filePath : FileInfo.joinPaths(product.buildDirectory, product.targetName + ".html") fileTags : ["qthtml"] } prepare: Core.wasmQtHtmlCommands(product, output) } Group { fileTags: ["qthtml"] files: [ module.pluginPath + "/platforms/qtloader.js", module.pluginPath + "/platforms/qtlogo.svg" ] } } @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/gui.qbs0000644000175100017510000000466315232633614023560 0ustar runnerrunnerimport qbs.FileInfo import qbs.ModUtils import qbs.Utilities QtModule { qtModuleName: "Gui" property string uicName: "uic" FileTagger { patterns: ["*.ui"] fileTags: ["ui"] } Rule { inputs: ["ui"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), 'ui_' + input.completeBaseName + '.h') fileTags: ["hpp", "qt.untranslatable"] } prepare: { var uicPath = Utilities.versionCompare(product.Qt.gui.version, "6.1") < 0 ? product.Qt.core.binPath + '/' + product.Qt.gui.uicName : product.Qt.core.libExecPath + '/' + product.Qt.gui.uicName; var cmd = new Command(uicPath, [input.filePath, '-o', output.filePath]); cmd.description = 'generating ' + output.fileName; cmd.highlight = 'codegen'; return cmd; } } property string defaultQpaPlugin: @defaultQpaPlugin@ version: @version@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ cpp.entryPoint: qbs.targetOS.containsAny(["ios", "tvos"]) && Utilities.versionCompare(version, "5.6.0") >= 0 ? "_qt_main_wrapper" : undefined cpp.defines: @defines@ cpp.systemIncludePaths: @includes@ cpp.libraryPaths: @libraryPaths@ Properties { condition: Qt.core.staticBuild && qbs.targetOS.contains("ios") cpp.frameworks: base.concat(["UIKit", "QuartzCore", "CoreText", "CoreGraphics", "Foundation", "CoreFoundation", "AudioToolbox"]) } Properties { condition: undefined cpp.frameworks: base } @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/plugin.qbs0000644000175100017510000000163415232633614024265 0ustar runnerrunnerQtPlugin { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} version: @version@ className: @className@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ cpp.libraryPaths: @libraryPaths@ extendsModules: @extends@ @additionalContent@ } qbs-src-3.3.1/share/qbs/module-providers/Qt/templates/dbus.js0000644000175100017510000000600415232633614023547 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function outputFileName(input, suffix) { var parts = input.fileName.split('.').filter(function(s) { return s.length > 0; }); if (parts.length === 0) throw "Cannot run qdbusxml2cpp on '" + input.filePath + "': Unsuitable file name."; var outputBaseName = parts.length === 1 ? parts[0] : parts[parts.length - 2]; return outputBaseName.toLowerCase() + suffix; } function createCommands(product, input, outputs, option) { var exe = ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "xml2cppName"); var hppOutput = outputs["hpp"][0]; var hppArgs = ModUtils.moduleProperty(product, "xml2CppHeaderFlags"); hppArgs.push(option, hppOutput.fileName + ':', input.filePath); // Can't use filePath on Windows var hppCmd = new Command(exe, hppArgs) hppCmd.description = "qdbusxml2cpp " + input.fileName + " -> " + hppOutput.fileName; hppCmd.highlight = "codegen"; hppCmd.workingDirectory = FileInfo.path(hppOutput.filePath); var cppOutput = outputs["cpp"][0]; var cppArgs = ModUtils.moduleProperty(product, "xml2CppSourceFlags"); cppArgs.push("-i", hppOutput.filePath, option, ':' + cppOutput.fileName, input.filePath); var cppCmd = new Command(exe, cppArgs) cppCmd.description = "qdbusxml2cpp " + input.fileName + " -> " + cppOutput.fileName; cppCmd.highlight = "codegen"; cppCmd.workingDirectory = FileInfo.path(cppOutput.filePath); return [hppCmd, cppCmd]; } qbs-src-3.3.1/share/qbs/module-providers/conan.qbs0000644000175100017510000000036115232633614021477 0ustar runnerrunnerimport "conan.js" as ConanHelper ModuleProvider { /* input */ property path installDirectory isEager: false relativeSearchPaths: { return ConanHelper.configure(installDirectory, moduleName, outputBaseDir); } } qbs-src-3.3.1/share/qbs/module-providers/conan.js0000644000175100017510000002323015232633614021326 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2024 Kai Dohmen ** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var PathProbe = require("../imports/qbs/Probes/path-probe.js") var PathTools = require("qbs.PathTools"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); const architectureMap = { 'x86': 'x86', 'x86_64': 'x86_64', 'ppc32be': 'ppc', 'ppc32': 'ppc', 'ppc64le': 'ppc64', 'ppc64': 'ppc64', 'armv4': 'arm', 'armv4i': 'arm', 'armv5el': 'arm', 'armv5hf': 'arm', 'armv6': 'arm', 'armv7': 'arm', 'armv7hf': 'arm', 'armv7s': 'arm', 'armv7k': 'arm', 'armv8': 'arm64', 'armv8_32': 'arm64', 'armv8.3': 'arm64', 'sparc': 'sparc', 'sparcv9': 'sparc64', 'mips': 'mips', 'mips64': 'mips64', 'avr': 'avr', 's390': 's390x', 's390x': 's390x', 'sh4le': 'sh' } const platformMap = { 'Windows': 'windows', 'WindowsStore': 'windows', 'WindowsCE': 'windows', 'Linux': 'linux', 'Macos': 'macos', 'Android': 'android', 'iOS': 'ios', 'watchOS': 'watchos', 'tvOS': 'tvos', 'FreeBSD': 'freebsd', 'SunOS': 'solaris', 'AIX': 'aix', 'Emscripten': undefined, 'Arduino': 'none', 'Neutrino': 'qnx', 'VxWorks': 'vxworks', } function findLibs(libnames, libdirs, libtypes, targetOS, forImport) { var result = []; if (libnames === null || libdirs === null) return result; libnames.forEach(function(libraryName) { const suffixes = PathTools.librarySuffixes(targetOS, libtypes, forImport); const lib = PathProbe.configure( undefined, // selectors [libraryName], suffixes, PathTools.libraryNameFilter(), undefined, // candidateFilter libdirs, // searchPaths undefined, // pathSuffixes [], // platformSearchPaths undefined, // environmentPaths undefined // platformEnvironmentPaths ); if (lib.found) result.push(lib.files[0].filePath); }); return result; } function getLibraryTypes(options) { if (options !== undefined && options !== null) { if (options.shared === undefined) return ["shared", "static"]; else if (options.shared === "True") return ["shared"]; else if (options.shared === "False") return ["static"]; } return ["shared", "static"]; } function configure(installDirectory, moduleName, outputBaseDir, jsonProbe) { if (!installDirectory || installDirectory.trim() === "") throw "Conan install directory is not set. Please define moduleProviders.conan.installDirectory in your product."; const depsDir = FileInfo.joinPaths(installDirectory, "conan-qbs-deps"); if (!File.exists(depsDir)) throw "The directory '" + depsDir + "' does not exist. Ensure moduleProviders.conan.installDirectory points to a valid Conan install output."; const moduleMapping = {"protobuflib": "protobuf"} const realModuleName = moduleMapping[moduleName] || moduleName; const moduleFilePath = FileInfo.joinPaths(depsDir, realModuleName + ".json") if (!File.exists(moduleFilePath)) return []; var reverseMapping = {} for (var key in moduleMapping) reverseMapping[moduleMapping[key]] = key console.info("Setting up Conan module '" + moduleName + "'"); var moduleFile = new TextFile(moduleFilePath, TextFile.ReadOnly); const moduleInfo = JSON.parse(moduleFile.readAll()); const outputDir = FileInfo.joinPaths(outputBaseDir, "modules", moduleName.replace(".", "/")); File.makePath(outputDir); const outputFilePath = FileInfo.joinPaths(outputDir, "module.qbs"); const cppInfo = moduleInfo.cpp_info; var moduleContent = ""; // function write(data) { moduleContent = moduleContent + data } function writeLine(data) { moduleContent = moduleContent + data + "\n"; } function writeProperty(propertyName, propertyValue) { if (propertyValue === undefined || propertyValue === null) propertyValue = []; writeLine(" readonly property stringList " + propertyName + ": " + ModUtils.toJSLiteral(propertyValue)); } function writeCppProperty(propertyName, propertyValue) { writeProperty(propertyName, propertyValue); // skip empty props for simplicity of the module file if (propertyValue !== undefined && propertyValue != null && propertyValue.length !== 0) { writeLine(" cpp." + propertyName + ": " + propertyName); } } writeLine("Module {"); writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version)); const architecture = architectureMap[moduleInfo.settings.arch]; const platform = platformMap[moduleInfo.settings.os]; const targetOS = Utilities.canonicalPlatform(platform); writeLine(" readonly property string architecture: " + ModUtils.toJSLiteral(architecture)); if (platform !== undefined) writeLine(" readonly property string platform: " + ModUtils.toJSLiteral(platform)); writeLine(" condition: true"); if (architecture !== undefined) { writeLine(" && (!qbs.architecture || qbs.architecture === architecture)"); } if (platform !== undefined) { if (["ios", "tvos", "watchos"].includes(platform)) { writeLine(" && (qbs.targetPlatform === platform || qbs.targetPlatform === platform + \"-simulator\")"); } else { writeLine(" && qbs.targetPlatform === platform"); } } writeLine(" Depends { name: 'cpp' }"); moduleInfo.dependencies.reverse().forEach(function(dep) { const realDepName = reverseMapping[dep.name] || dep.name; writeLine(" Depends { name: " + ModUtils.toJSLiteral(realDepName) + "; version: " + ModUtils.toJSLiteral(dep.version) + "}"); }); const buildBindirs = moduleInfo.build_bindirs.map(FileInfo.fromNativeSeparators); writeLine(" readonly property stringList hostBinDirs: (" + ModUtils.toJSLiteral(buildBindirs) + ")"); const targetBindirs = cppInfo.bindirs.map(FileInfo.fromNativeSeparators); writeLine(" readonly property stringList binDirs: (" + ModUtils.toJSLiteral(targetBindirs) + ")"); // TODO: there's a weird issue with system include dirs with xcode-less clang - incorrect include order? writeCppProperty("includePaths", cppInfo.includedirs.map(FileInfo.fromNativeSeparators)); writeProperty("libraryPaths", cppInfo.libdirs.map(FileInfo.fromNativeSeparators)); writeCppProperty("frameworkPaths", cppInfo.frameworkdirs.map(FileInfo.fromNativeSeparators)); writeCppProperty("frameworks", cppInfo.frameworks); writeCppProperty("defines", cppInfo.defines); writeCppProperty("cFlags", cppInfo.cflags); writeCppProperty("cxxFlags", cppInfo.cxxflags); writeCppProperty("linkerFlags", (cppInfo.sharedlinkflags || []).concat(cppInfo.exelinkflags || [])); writeProperty("resources", cppInfo.resdirs.map(FileInfo.fromNativeSeparators)); const isForImport = targetOS.includes("windows") const libraryTypes = getLibraryTypes(moduleInfo.options); libraryTypes.forEach(function(libraryType){ const cppInfoLibs = cppInfo.libs === null ? [] : cppInfo.libs; const libdirs = cppInfo.libdirs.map(FileInfo.fromNativeSeparators); const libs = findLibs(cppInfoLibs, libdirs, libraryType, targetOS, isForImport) .concat(cppInfo.system_libs === null ? [] : cppInfo.system_libs); const property = libraryType === "shared" ? "dynamicLibraries" : "staticLibraries"; writeCppProperty(property, libs); }); writeLine("}"); var moduleFile = new TextFile(outputFilePath, TextFile.WriteOnly); moduleFile.write(moduleContent); moduleFile.close(); return ""; } qbs-src-3.3.1/share/share.qbs0000644000175100017510000001103115232633614015412 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.TextFile import qbs.Utilities Product { name: "qbs resources" type: ["qbs qml type descriptions", "qbs qml type bundle"] Depends { name: "qbsbuildconfig" } Group { name: "Incredibuild" prefix: "../bin/" files: ["ibmsvc.xml", "ibqbs.bat"] fileTags: [] qbs.install: qbs.targetOS.contains("windows") qbs.installDir: qbsbuildconfig.appInstallDir } Group { name: "CMake" files: "CMakeLists.txt" } Group { name: "Python packages" prefix: "../src/3rdparty/python/**/" files: ["*.py"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs/python" qbs.installSourceBase: "../src/3rdparty/python/lib/python3.9/site-packages" } Group { name: "Imports" files: ["qbs/imports/qbs/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Modules" files: ["qbs/modules/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Module providers" files: ["qbs/module-providers/*", "qbs/module-providers/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Examples as resources" files: ["../examples/**/*"] fileTags: [] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs" qbs.installSourceBase: ".." } Rule { condition: Utilities.versionCompare(product.qbs.version, "1.9.1") >= 0 multiplex: true Artifact { filePath: "qbs.qmltypes" fileTags: ["qbs qml type descriptions"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(Utilities.qmlTypeInfo()); } finally { if (tf) tf.close(); } }; return cmd; } } Rule { condition: Utilities.versionCompare(product.qbs.version, "1.9.1") >= 0 multiplex: true Artifact { filePath: "qbs-bundle.json" fileTags: ["qbs qml type bundle"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var tf; try { var imports = File.directoryEntries(FileInfo.joinPaths(product.sourceDirectory, "qbs", "imports", "qbs"), File.Dirs | File.NoDotAndDotDot).filter( function(i) { return i !== "base"; }).concat( Utilities.builtinExtensionNames()).map( function(i) { return "qbs." + i; }); imports.sort(); var obj = { "name": "qbs", "searchPaths": ["$(QBS_IMPORT_PATH)"], "installPaths": ["$(QBS_IMPORT_PATH)"], "implicitImports": ["__javascriptQt5__"], "supportedImports": ["qbs"].concat(imports) }; tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(obj, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } Group { name: "QML Type Info" fileTagsFilter: ["qbs qml type descriptions", "qbs qml type bundle"] qbs.install: true qbs.installDir: qbsbuildconfig.qmlTypeDescriptionsInstallDir } } qbs-src-3.3.1/tutorial/0000755000175100017510000000000015232633614014346 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/0000755000175100017510000000000015232633614016135 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/myproject.qbs0000644000175100017510000000025015232633614020655 0ustar runnerrunner//! [0] Project { name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs", "lib/lib.qbs" ] qbsSearchPaths: "qbs" } //! [0] qbs-src-3.3.1/tutorial/chapter-4/lib/0000755000175100017510000000000015232633614016703 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/lib/lib.c0000644000175100017510000000022415232633614017613 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-4/lib/lib_global.h0000644000175100017510000000071715232633614021147 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H qbs-src-3.3.1/tutorial/chapter-4/lib/lib.h0000644000175100017510000000015615232633614017624 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-4/lib/lib.qbs0000644000175100017510000000031215232633614020154 0ustar runnerrunner//! [0] // lib/lib.qbs MyLibrary { name: "mylib" files: ["lib.c"] publicHeaders: [ "lib.h", "lib_global.h", ] cpp.defines: base.concat(["CRUCIAL_DEFINE"]) } //! [0] qbs-src-3.3.1/tutorial/chapter-4/qbs/0000755000175100017510000000000015232633614016722 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/qbs/imports/0000755000175100017510000000000015232633614020417 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/qbs/imports/MyLibrary.qbs0000644000175100017510000000074015232633614023041 0ustar runnerrunner//! [0] // qbs/imports/MyLibrary.qbs DynamicLibrary { version: "1.0.0" Depends { name: 'cpp' } property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY" cpp.defines: [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } Depends { name: 'bundle' } bundle.isBundle: false } //! [0] qbs-src-3.3.1/tutorial/chapter-4/qbs/imports/MyApplication.qbs0000644000175100017510000000072415232633614023702 0ustar runnerrunner//! [0] // qbs/imports/MyApplication.qbs import qbs.FileInfo CppApplication { version: "1.0.0" consoleApplication: true cpp.rpaths: { if (!cpp.rpathOrigin) return []; return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths("/", product.installDir), FileInfo.joinPaths("/", "lib"))) ]; } } //! [0] qbs-src-3.3.1/tutorial/chapter-4/app/0000755000175100017510000000000015232633614016715 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-4/app/main.c0000644000175100017510000000020315232633614020000 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-4/app/app.qbs0000644000175100017510000000022715232633614020205 0ustar runnerrunner//! [0] // app/app.qbs MyApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" } //! [0] qbs-src-3.3.1/tutorial/chapter-7/0000755000175100017510000000000015232633614016140 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/myproject.qbs0000644000175100017510000000106215232633614020662 0ustar runnerrunnerProject { property bool withTests: true property stringList autotestArguments: [] property stringList autotestWrapper: [] name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs", "lib/lib.qbs", ] qbsSearchPaths: "qbs" SubProject { filePath: "test/test.qbs" Properties { condition: parent.withTests } } AutotestRunner { condition: parent.withTests arguments: parent.autotestArguments wrapper: parent.autotestWrapper } } qbs-src-3.3.1/tutorial/chapter-7/lib/0000755000175100017510000000000015232633614016706 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/lib/lib.c0000644000175100017510000000022415232633614017616 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-7/lib/lib_global.h0000644000175100017510000000071715232633614021152 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H qbs-src-3.3.1/tutorial/chapter-7/lib/lib.h0000644000175100017510000000015615232633614017627 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-7/lib/lib.qbs0000644000175100017510000000510115232633614020160 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ //! [0] // lib/lib.qbs MyLibrary { name: "mylib" files: [ "lib.c" ] publicHeaders: [ "lib.h" ] Depends { name: 'cpp' } cpp.defines: ['CRUCIAL_DEFINE'] } //! [0] qbs-src-3.3.1/tutorial/chapter-7/qbs/0000755000175100017510000000000015232633614016725 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/modules/0000755000175100017510000000000015232633614020375 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/modules/config/0000755000175100017510000000000015232633614021642 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/modules/config/myproject/0000755000175100017510000000000015232633614023656 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/modules/config/myproject/module.qbs0000644000175100017510000000011715232633614025651 0ustar runnerrunner//! [0] // qbs/modules/config/myproject/module.qbs ConfigMyProject { } //! [0] qbs-src-3.3.1/tutorial/chapter-7/qbs/modules/config/install/0000755000175100017510000000000015232633614023310 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/modules/config/install/module.qbs0000644000175100017510000000016215232633614025303 0ustar runnerrunnerimport qbs.FileInfo //! [0] // qbs/modules/config/install/module.qbs ConfigInstall { importLibraries: true } qbs-src-3.3.1/tutorial/chapter-7/qbs/imports/0000755000175100017510000000000015232633614020422 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/qbs/imports/MyLibrary.qbs0000644000175100017510000000103315232633614023040 0ustar runnerrunner//! [0] // qbs/imports/MyLibrary.qbs DynamicLibrary { version: project.version Depends { name: "config.myproject" } // ... //! [0] Depends { name: "cpp" } property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY" cpp.defines: [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } Depends { name: 'bundle' } bundle.isBundle: false } qbs-src-3.3.1/tutorial/chapter-7/qbs/imports/MyApplication.qbs0000644000175100017510000000023715232633614023704 0ustar runnerrunner//! [0] // qbs/imports/MyApplication.qbs CppApplication { Depends { name: "config.myproject" } version: "1.0.0" consoleApplication: true } //! [0] qbs-src-3.3.1/tutorial/chapter-7/qbs/imports/ConfigMyProject.qbs0000644000175100017510000000210015232633614024164 0ustar runnerrunner//! [1] import qbs.FileInfo //! [0] // qbs/imports/ConfigMyProject.qbs Module { property bool enableAddressSanitizer: false Depends { name: "Sanitizers.address"; condition: enableAddressSanitizer } //! [0] Depends { name: "cpp" } Depends { name: "config.install" } property bool enableRPath: true property stringList libRPaths: { if (enableRPath && cpp.rpathOrigin && product.installDir) { console.info(FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.installDir), FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory)))); return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.installDir), FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory)))]; } return []; } cpp.rpaths: libRPaths } //! [1] qbs-src-3.3.1/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs0000644000175100017510000000007015232633614023204 0ustar runnerrunnerMyApplication { type: ["application", "autotest"] } qbs-src-3.3.1/tutorial/chapter-7/app/0000755000175100017510000000000015232633614016720 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/app/main.c0000644000175100017510000000020315232633614020003 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-7/app/app.qbs0000644000175100017510000000016715232633614020213 0ustar runnerrunnerMyApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" } qbs-src-3.3.1/tutorial/chapter-7/test/0000755000175100017510000000000015232633614017117 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-7/test/test.qbs0000644000175100017510000000012415232633614020602 0ustar runnerrunnerMyAutoTest { Depends { name: "mylib" } name: "mytest" files: "test.c" } qbs-src-3.3.1/tutorial/chapter-7/test/test.c0000644000175100017510000000056215232633614020245 0ustar runnerrunner#include "lib.h" #include #include int main(int argc, char *argv[]) { if (argc > 2) { printf("usage: test [value]\n"); return 1; } const char *expected = argc == 2 ? argv[1] : "Hello from library"; if (strcmp(get_string(), expected) != 0) { printf("text differs\n"); return 1; } return 0; } qbs-src-3.3.1/tutorial/chapter-2/0000755000175100017510000000000015232633614016133 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-2/myproject.qbs0000644000175100017510000000021715232633614020656 0ustar runnerrunner//! [0] Project { name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs", "lib/lib.qbs" ] } //! [0] qbs-src-3.3.1/tutorial/chapter-2/lib/0000755000175100017510000000000015232633614016701 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-2/lib/lib.c0000644000175100017510000000026515232633614017616 0ustar runnerrunner//! [0] // lib/lib.cpp #include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } //! [0] qbs-src-3.3.1/tutorial/chapter-2/lib/lib.h0000644000175100017510000000014715232633614017622 0ustar runnerrunner//! [0] // lib/lib.h #ifndef LIB_H #define LIB_H const char *get_string(); #endif // LIB_H //! [0] qbs-src-3.3.1/tutorial/chapter-2/lib/lib.qbs0000644000175100017510000000062715232633614020163 0ustar runnerrunner//! [0] StaticLibrary { name: "mylib" files: [ "lib.c", "lib.h", ] version: "1.0.0" //! [1] cpp.defines: ['CRUCIAL_DEFINE'] //! [1] //! [2] Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } //! [2] //! [3] Depends { name: 'bundle' } bundle.isBundle: false //! [3] } //! [0] qbs-src-3.3.1/tutorial/chapter-2/app/0000755000175100017510000000000015232633614016713 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-2/app/main.c0000644000175100017510000000020315232633614017776 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-2/app/app.qbs0000644000175100017510000000025315232633614020202 0ustar runnerrunnerCppApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" version: "1.0.0" consoleApplication: true } qbs-src-3.3.1/tutorial/chapter-1/0000755000175100017510000000000015232633614016132 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-1/myproject.qbs0000644000175100017510000000017115232633614020654 0ustar runnerrunner//! [0] Project { name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs" ] } //! [0] qbs-src-3.3.1/tutorial/chapter-1/app/0000755000175100017510000000000015232633614016712 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-1/app/main.c0000644000175100017510000000013715232633614020003 0ustar runnerrunner//! [0] #include int main() { printf("Hello, world\n"); return 0; } //! [0] qbs-src-3.3.1/tutorial/chapter-1/app/app.qbs0000644000175100017510000000023515232633614020201 0ustar runnerrunner//! [0] CppApplication { name: "My Application" targetName: "myapp" files: "main.c" version: "1.0.0" consoleApplication: true } //! [0] qbs-src-3.3.1/tutorial/chapter-6/0000755000175100017510000000000015232633614016137 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/myproject.qbs0000644000175100017510000000124715232633614020666 0ustar runnerrunner//! [0] Project { property string version: "1.0.0" property bool withTests: false property stringList autotestArguments: [] property stringList autotestWrapper: [] name: "My Project" minimumQbsVersion: "2.0" // ... //! [0] references: [ "app/app.qbs", "lib/lib.qbs", ] qbsSearchPaths: "qbs" //! [1] SubProject { filePath: "test/test.qbs" Properties { condition: parent.withTests } } //! [1] //! [2] AutotestRunner { condition: parent.withTests arguments: parent.autotestArguments wrapper: parent.autotestWrapper } //! [2] } qbs-src-3.3.1/tutorial/chapter-6/lib/0000755000175100017510000000000015232633614016705 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/lib/lib.c0000644000175100017510000000022415232633614017615 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-6/lib/lib_global.h0000644000175100017510000000071715232633614021151 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H qbs-src-3.3.1/tutorial/chapter-6/lib/lib.h0000644000175100017510000000015615232633614017626 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-6/lib/lib.qbs0000644000175100017510000000025215232633614020161 0ustar runnerrunnerMyLibrary { name: "mylib" files: ["lib.c"] publicHeaders: [ "lib.h", "lib_global.h", ] cpp.defines: base.concat(['CRUCIAL_DEFINE']) } qbs-src-3.3.1/tutorial/chapter-6/qbs/0000755000175100017510000000000015232633614016724 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/qbs/imports/0000755000175100017510000000000015232633614020421 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/qbs/imports/MyLibrary.qbs0000644000175100017510000000067215232633614023047 0ustar runnerrunnerDynamicLibrary { version: project.version Depends { name: 'cpp' } property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY" cpp.defines: [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } Depends { name: 'bundle' } bundle.isBundle: false } qbs-src-3.3.1/tutorial/chapter-6/qbs/imports/MyApplication.qbs0000644000175100017510000000071115232633614023700 0ustar runnerrunnerimport qbs.FileInfo //! [0] CppApplication { version: project.version consoleApplication: true // ... //! [0] cpp.rpaths: { if (!cpp.rpathOrigin) return []; return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths("/", product.installDir), FileInfo.joinPaths("/", "lib"))) ]; } } qbs-src-3.3.1/tutorial/chapter-6/qbs/imports/MyAutoTest.qbs0000644000175100017510000000006615232633614023210 0ustar runnerrunnerMyApplication { type: base.concat(["autotest"]) } qbs-src-3.3.1/tutorial/chapter-6/app/0000755000175100017510000000000015232633614016717 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/app/main.c0000644000175100017510000000020315232633614020002 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-6/app/app.qbs0000644000175100017510000000016715232633614020212 0ustar runnerrunnerMyApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" } qbs-src-3.3.1/tutorial/chapter-6/test/0000755000175100017510000000000015232633614017116 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-6/test/test.qbs0000644000175100017510000000012415232633614020601 0ustar runnerrunnerMyAutoTest { Depends { name: "mylib" } name: "mytest" files: "test.c" } qbs-src-3.3.1/tutorial/chapter-6/test/test.c0000644000175100017510000000056215232633614020244 0ustar runnerrunner#include "lib.h" #include #include int main(int argc, char *argv[]) { if (argc > 2) { printf("usage: test [value]\n"); return 1; } const char *expected = argc == 2 ? argv[1] : "Hello from library"; if (strcmp(get_string(), expected) != 0) { printf("text differs\n"); return 1; } return 0; } qbs-src-3.3.1/tutorial/chapter-10-2/0000755000175100017510000000000015232633614016351 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-10-2/myproject.qbs0000644000175100017510000000017715232633614021101 0ustar runnerrunnerProject { name: "My Project" minimumQbsVersion: "2.5" references: [ "app/app.qbs", "lib/lib.qbs" ] } qbs-src-3.3.1/tutorial/chapter-10-2/lib/0000755000175100017510000000000015232633614017117 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-10-2/lib/hello.cppm0000644000175100017510000000044215232633614021103 0ustar runnerrunner//![0] // lib/hello.cppm module; #include "lib_global.h" #include #include export module hello; export namespace Hello { void MYLIB_EXPORT printHello(std::string_view name) { std::cout << "Hello, " << name << '!' << std::endl; } } // namespace Hello //![0]qbs-src-3.3.1/tutorial/chapter-10-2/lib/lib_global.h0000644000175100017510000000076515232633614021366 0ustar runnerrunner//! [0] // lib/lib_global.h #ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H //! [0] qbs-src-3.3.1/tutorial/chapter-10-2/lib/lib.qbs0000644000175100017510000000147315232633614020401 0ustar runnerrunner//! [0] // lib/lib.qbs DynamicLibrary { condition: { if (qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } name: "mylib" files: ["hello.cppm", "lib_global.h"] version: "1.0.0" Depends { name: "cpp" } cpp.defines: "MYLIB_LIBRARY" cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true Depends { name: "bundle" } bundle.isBundle: false } qbs-src-3.3.1/tutorial/chapter-10-2/app/0000755000175100017510000000000015232633614017131 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-10-2/app/app.qbs0000644000175100017510000000104115232633614020414 0ustar runnerrunnerCppApplication { condition: qbs.toolchainType === "msvc" || (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "mingw" && cpp.compilerVersionMajor >= 13) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16) consoleApplication: true name: "app" files: ["main.cpp"] cpp.rpaths: [cpp.rpathOrigin + "/../lib"] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true cpp.treatWarningsAsErrors: true Depends { name: "mylib" } } qbs-src-3.3.1/tutorial/chapter-10-2/app/main.cpp0000644000175100017510000000007615232633614020564 0ustar runnerrunnerimport hello; int main() { Hello::printHello("world"); } qbs-src-3.3.1/tutorial/chapter-10-1/0000755000175100017510000000000015232633614016350 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-10-1/myproject.qbs0000644000175100017510000000110415232633614021067 0ustar runnerrunner// myproject.qbs CppApplication { condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc" || qbs.toolchainType === "mingw") && cpp.compilerVersionMajor >= 11) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 16)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true files: ["hello.cppm", "main.cpp" ] cpp.cxxLanguageVersion: "c++20" cpp.forceUseCxxModules: true } qbs-src-3.3.1/tutorial/chapter-10-1/hello.cppm0000644000175100017510000000037115232633614020335 0ustar runnerrunner//![0] // hello.cppm module; #include #include export module hello; export namespace Hello { void printHello(std::string_view name) { std::cout << "Hello, " << name << '!' << std::endl; } } // namespace Hello //![0]qbs-src-3.3.1/tutorial/chapter-10-1/main.cpp0000644000175100017510000000013015232633614017772 0ustar runnerrunner//![0] // main.cpp import hello; int main() { Hello::printHello("World"); } //![0]qbs-src-3.3.1/tutorial/LICENSE0000644000175100017510000000465715232633614015367 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) ** Contact: https://www.qt.io/licensing/ ** ** Files in this directory are part of the Qbs tutorial. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use these files in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this these files under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/qbs-src-3.3.1/tutorial/chapter-3/0000755000175100017510000000000015232633614016134 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-3/myproject.qbs0000644000175100017510000000017715232633614020664 0ustar runnerrunnerProject { name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs", "lib/lib.qbs" ] } qbs-src-3.3.1/tutorial/chapter-3/lib/0000755000175100017510000000000015232633614016702 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-3/lib/lib.c0000644000175100017510000000026615232633614017620 0ustar runnerrunner //! [0] // lib/lib.cpp #include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } //! [0] qbs-src-3.3.1/tutorial/chapter-3/lib/lib_global.h0000644000175100017510000000076515232633614021151 0ustar runnerrunner//! [0] // lib/lib_global.h #ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H //! [0] qbs-src-3.3.1/tutorial/chapter-3/lib/lib.h0000644000175100017510000000021315232633614017615 0ustar runnerrunner#ifndef LIB_H #define LIB_H //! [0] // lib/lib.h #include "lib_global.h" MYLIB_EXPORT const char *get_string(); //! [0] #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-3/lib/lib.qbs0000644000175100017510000000074715232633614020167 0ustar runnerrunner//! [0] // lib/lib.qbs DynamicLibrary { name: "mylib" files: ["lib.c"] publicHeaders: ["lib.h", "lib_global.h"] version: "1.0.0" Depends { name: "cpp" } cpp.defines: ["MYLIB_LIBRARY", "CRUCIAL_DEFINE"] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } Depends { name: "bundle" } bundle.isBundle: false } //! [0] qbs-src-3.3.1/tutorial/chapter-3/app/0000755000175100017510000000000015232633614016714 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-3/app/main.c0000644000175100017510000000020315232633614017777 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-3/app/app.qbs0000644000175100017510000000107715232633614020210 0ustar runnerrunner//! [1] // app/app.qbs import qbs.FileInfo CppApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" version: "1.0.0" consoleApplication: true //! [0] cpp.rpaths: { if (!cpp.rpathOrigin) return []; return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths("/", product.installDir), FileInfo.joinPaths("/", "lib"))) ]; } //! [0] } //! [1] qbs-src-3.3.1/tutorial/chapter-10-3/0000755000175100017510000000000015232633614016352 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-10-3/myproject.qbs0000644000175100017510000000165215232633614021101 0ustar runnerrunner//![1] // myproject.qbs Project { CppStd {} CppApplication { name: "myapp" Depends { name: "CppStd" } condition: { if (qbs.toolchainType === "msvc" || ((qbs.toolchainType === "gcc") && cpp.compilerVersionMajor >= 15) || (qbs.toolchainType === "clang" && cpp.compilerVersionMajor >= 18)) { return true; } console.info("Unsupported toolchainType " + qbs.toolchainType); return false; } consoleApplication: true install: true files: ["main.cpp" ] //![0] cpp.forceUseCxxModules: true cpp.cxxLanguageVersion: "c++23" //![0] Properties { condition: qbs.toolchainType === "clang" cpp.cxxFlags: ["-Wno-reserved-module-identifier"] cpp.cxxStandardLibrary: "libc++" } } } //![1] qbs-src-3.3.1/tutorial/chapter-10-3/main.cpp0000644000175100017510000000033315232633614020001 0ustar runnerrunner//![0] // main.cpp import std; int main() { std::vector numbers = {1, 2, 3, 4, 5}; std::ranges::for_each(numbers, [](int n) { std::cout << n << ' '; }); std::cout << std::endl; return 0; } //![0] qbs-src-3.3.1/tutorial/chapter-5/0000755000175100017510000000000015232633614016136 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/myproject.qbs0000644000175100017510000000040015232633614020653 0ustar runnerrunnerProject { name: "My Project" minimumQbsVersion: "2.0" // ![0] references: [ "app/app.qbs", "lib/lib.qbs", "test/test.qbs", ] // ![0] qbsSearchPaths: "qbs" AutotestRunner { timeout: 60 } } qbs-src-3.3.1/tutorial/chapter-5/lib/0000755000175100017510000000000015232633614016704 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/lib/lib.c0000644000175100017510000000022415232633614017614 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-5/lib/lib_global.h0000644000175100017510000000071715232633614021150 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MYLIB_DECL_EXPORT __declspec(dllexport) #define MYLIB_DECL_IMPORT __declspec(dllimport) #else #define MYLIB_DECL_EXPORT __attribute__((visibility("default"))) #define MYLIB_DECL_IMPORT __attribute__((visibility("default"))) #endif #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MYLIB_DECL_EXPORT #else #define MYLIB_EXPORT MYLIB_DECL_IMPORT #endif #endif // LIB_GLOBAL_H qbs-src-3.3.1/tutorial/chapter-5/lib/lib.h0000644000175100017510000000015615232633614017625 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-5/lib/lib.qbs0000644000175100017510000000025215232633614020160 0ustar runnerrunnerMyLibrary { name: "mylib" files: ["lib.c"] publicHeaders: [ "lib.h", "lib_global.h", ] cpp.defines: base.concat(['CRUCIAL_DEFINE']) } qbs-src-3.3.1/tutorial/chapter-5/qbs/0000755000175100017510000000000015232633614016723 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/qbs/imports/0000755000175100017510000000000015232633614020420 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/qbs/imports/MyLibrary.qbs0000644000175100017510000000066215232633614023045 0ustar runnerrunnerDynamicLibrary { version: "1.0.0" Depends { name: 'cpp' } property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY" cpp.defines: [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] } Depends { name: 'bundle' } bundle.isBundle: false } qbs-src-3.3.1/tutorial/chapter-5/qbs/imports/MyApplication.qbs0000644000175100017510000000064215232633614023702 0ustar runnerrunnerimport qbs.FileInfo CppApplication { version: "1.0.0" consoleApplication: true cpp.rpaths: { if (!cpp.rpathOrigin) return []; return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths("/", product.installDir), FileInfo.joinPaths("/", "lib"))) ]; } } qbs-src-3.3.1/tutorial/chapter-5/qbs/imports/MyAutoTest.qbs0000644000175100017510000000014515232633614023205 0ustar runnerrunner//! [0] // qbs/imports/MyAutoTest.qbs MyApplication { type: base.concat(["autotest"]) } //! [0] qbs-src-3.3.1/tutorial/chapter-5/app/0000755000175100017510000000000015232633614016716 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/app/main.c0000644000175100017510000000020315232633614020001 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-5/app/app.qbs0000644000175100017510000000016715232633614020211 0ustar runnerrunnerMyApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" } qbs-src-3.3.1/tutorial/chapter-5/test/0000755000175100017510000000000015232633614017115 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-5/test/test.qbs0000644000175100017510000000016615232633614020606 0ustar runnerrunner//! [0] // test/test.qbs MyAutoTest { Depends { name: "mylib" } name: "mytest" files: "test.c" } //! [0] qbs-src-3.3.1/tutorial/chapter-5/test/test.c0000644000175100017510000000062115232633614020237 0ustar runnerrunner//! [0] // test/test.c #include "lib.h" #include #include int main(int argc, char *argv[]) { if (argc > 2) { printf("usage: test [value]\n"); return 1; } const char *expected = argc == 2 ? argv[1] : "Hello from library"; if (strcmp(get_string(), expected) != 0) { printf("text differs\n"); return 1; } return 0; } //! [0]qbs-src-3.3.1/tutorial/tutorial.qbs0000644000175100017510000000005715232633614016722 0ustar runnerrunnerProduct { files: [ "*/**", ] } qbs-src-3.3.1/tutorial/chapter-8/0000755000175100017510000000000015232633614016141 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/myproject.qbs0000644000175100017510000000106215232633614020663 0ustar runnerrunnerProject { property bool withTests: true property stringList autotestArguments: [] property stringList autotestWrapper: [] name: "My Project" minimumQbsVersion: "2.0" references: [ "app/app.qbs", "lib/lib.qbs", ] qbsSearchPaths: "qbs" SubProject { filePath: "test/test.qbs" Properties { condition: parent.withTests } } AutotestRunner { condition: parent.withTests arguments: parent.autotestArguments wrapper: parent.autotestWrapper } } qbs-src-3.3.1/tutorial/chapter-8/lib/0000755000175100017510000000000015232633614016707 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/lib/lib.c0000644000175100017510000000022415232633614017617 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-8/lib/lib_global.h0000644000175100017510000000107415232633614021150 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MY_LIB_DECL_EXPORT __declspec(dllexport) #define MY_LIB_DECL_IMPORT __declspec(dllimport) #else #define MY_LIB_DECL_EXPORT __attribute__((visibility("default"))) #define MY_LIB_DECL_IMPORT __attribute__((visibility("default"))) #endif // ![0] // lib/lib_global.h #if defined(MYLIB_STATIC_LIBRARY) #define MYLIB_EXPORT #else #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MY_LIB_DECL_EXPORT #else #define MYLIB_EXPORT MY_LIB_DECL_IMPORT #endif #endif // ![0] #endif // LIB_GLOBAL_Hqbs-src-3.3.1/tutorial/chapter-8/lib/lib.h0000644000175100017510000000015615232633614017630 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-8/lib/lib.qbs0000644000175100017510000000022715232633614020165 0ustar runnerrunnerMyLibrary { name: "mylib" files: [ "lib.c" ] publicHeaders: [ "lib.h" ] Depends { name: 'cpp' } cpp.defines: ['CRUCIAL_DEFINE'] } qbs-src-3.3.1/tutorial/chapter-8/qbs/0000755000175100017510000000000015232633614016726 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/modules/0000755000175100017510000000000015232633614020376 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/modules/config/0000755000175100017510000000000015232633614021643 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/modules/config/myproject/0000755000175100017510000000000015232633614023657 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/modules/config/myproject/module.qbs0000644000175100017510000000002415232633614025647 0ustar runnerrunnerConfigMyProject { } qbs-src-3.3.1/tutorial/chapter-8/qbs/modules/config/install/0000755000175100017510000000000015232633614023311 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/modules/config/install/module.qbs0000644000175100017510000000005415232633614025304 0ustar runnerrunnerConfigInstall { importLibraries: true } qbs-src-3.3.1/tutorial/chapter-8/qbs/imports/0000755000175100017510000000000015232633614020423 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/qbs/imports/MyLibrary.qbs0000644000175100017510000000220715232633614023045 0ustar runnerrunner// ![0] Library { version: project.version property pathList publicHeaders Depends { name: "cpp" } Depends { name: "config.myproject" } Depends { name: "installpaths" } Group { condition: publicHeaders.length > 0 name: "Public Headers" prefix: product.sourceDirectory + "/" files: publicHeaders qbs.install: config.myproject.installPublicHeaders qbs.installDir: installpaths.include } readonly property string _nameUpper : name.replace(" ", "_").toUpperCase() property string libraryMacro: _nameUpper + "_LIBRARY" property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY" cpp.defines: config.build.libraryType === "static" ? [staticLibraryMacro] : [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] cpp.defines: exportingProduct.config.build.libraryType === "static" ? [exportingProduct.staticLibraryMacro] : [] } Depends { name: "bundle" } bundle.isBundle: false } // ![0] qbs-src-3.3.1/tutorial/chapter-8/qbs/imports/MyApplication.qbs0000644000175100017510000000015615232633614023705 0ustar runnerrunnerCppApplication { Depends { name: "config.myproject" } version: "1.0.0" consoleApplication: true } qbs-src-3.3.1/tutorial/chapter-8/qbs/imports/ConfigMyProject.qbs0000644000175100017510000000133215232633614024173 0ustar runnerrunnerimport qbs.FileInfo Module { property bool enableAddressSanitizer: false Depends { name: "Sanitizers.address"; condition: enableAddressSanitizer } Depends { name: "cpp" } Depends { name: "config.install" } property bool enableRPath: true property stringList libRPaths: { if (enableRPath && cpp.rpathOrigin && product.installDir) { return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.installDir), FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory)))]; } return []; } cpp.rpaths: libRPaths } qbs-src-3.3.1/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs0000644000175100017510000000007015232633614023205 0ustar runnerrunnerMyApplication { type: ["application", "autotest"] } qbs-src-3.3.1/tutorial/chapter-8/app/0000755000175100017510000000000015232633614016721 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/app/main.c0000644000175100017510000000020315232633614020004 0ustar runnerrunner#include #include "lib.h" int main() { printf("Hello, world\n"); printf("%s\n", get_string()); return 0; } qbs-src-3.3.1/tutorial/chapter-8/app/app.qbs0000644000175100017510000000016715232633614020214 0ustar runnerrunnerMyApplication { Depends { name: "mylib" } name: "My Application" targetName: "myapp" files: "main.c" } qbs-src-3.3.1/tutorial/chapter-8/test/0000755000175100017510000000000015232633614017120 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-8/test/test.qbs0000644000175100017510000000012415232633614020603 0ustar runnerrunnerMyAutoTest { Depends { name: "mylib" } name: "mytest" files: "test.c" } qbs-src-3.3.1/tutorial/chapter-8/test/test.c0000644000175100017510000000056215232633614020246 0ustar runnerrunner#include "lib.h" #include #include int main(int argc, char *argv[]) { if (argc > 2) { printf("usage: test [value]\n"); return 1; } const char *expected = argc == 2 ? argv[1] : "Hello from library"; if (strcmp(get_string(), expected) != 0) { printf("text differs\n"); return 1; } return 0; } qbs-src-3.3.1/tutorial/chapter-9/0000755000175100017510000000000015232633614016142 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/myproject.qbs0000644000175100017510000000126115232633614020665 0ustar runnerrunnerProject { property string version: "1.0.0" property bool withTests: true property stringList autotestArguments: [] property stringList autotestWrapper: [] name: "My Project" minimumQbsVersion: "2.0" //! [0] // myproject.qbs references: [ "app/app.qbs", "lib/lib.qbs", "version-header/version-header.qbs", ] //! [0] qbsSearchPaths: "qbs" SubProject { filePath: "test/test.qbs" Properties { condition: parent.withTests } } AutotestRunner { condition: parent.withTests arguments: parent.autotestArguments wrapper: parent.autotestWrapper } } qbs-src-3.3.1/tutorial/chapter-9/lib/0000755000175100017510000000000015232633614016710 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/lib/lib.c0000644000175100017510000000022415232633614017620 0ustar runnerrunner#include "lib.h" #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif const char *get_string() { return "Hello from library"; } qbs-src-3.3.1/tutorial/chapter-9/lib/lib_global.h0000644000175100017510000000107515232633614021152 0ustar runnerrunner#ifndef LIB_GLOBAL_H #define LIB_GLOBAL_H #if defined(_WIN32) || defined(WIN32) #define MY_LIB_DECL_EXPORT __declspec(dllexport) #define MY_LIB_DECL_IMPORT __declspec(dllimport) #else #define MY_LIB_DECL_EXPORT __attribute__((visibility("default"))) #define MY_LIB_DECL_IMPORT __attribute__((visibility("default"))) #endif // ![0] // lib/lib_global.h #if defined(MYLIB_STATIC_LIBRARY) #define MYLIB_EXPORT #else #if defined(MYLIB_LIBRARY) #define MYLIB_EXPORT MY_LIB_DECL_EXPORT #else #define MYLIB_EXPORT MY_LIB_DECL_IMPORT #endif #endif // ![0] #endif // LIB_GLOBAL_H qbs-src-3.3.1/tutorial/chapter-9/lib/lib.h0000644000175100017510000000015615232633614017631 0ustar runnerrunner#ifndef LIB_H #define LIB_H #include "lib_global.h" MYLIB_EXPORT const char *get_string(); #endif // LIB_H qbs-src-3.3.1/tutorial/chapter-9/lib/lib.qbs0000644000175100017510000000022615232633614020165 0ustar runnerrunnerMyLibrary { name: "mylib" files: [ "lib.c", "lib.h", ] Depends { name: 'cpp' } cpp.defines: ['CRUCIAL_DEFINE'] } qbs-src-3.3.1/tutorial/chapter-9/qbs/0000755000175100017510000000000015232633614016727 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/modules/0000755000175100017510000000000015232633614020377 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/modules/config/0000755000175100017510000000000015232633614021644 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/modules/config/myproject/0000755000175100017510000000000015232633614023660 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/modules/config/myproject/module.qbs0000644000175100017510000000002415232633614025650 0ustar runnerrunnerConfigMyProject { } qbs-src-3.3.1/tutorial/chapter-9/qbs/modules/config/install/0000755000175100017510000000000015232633614023312 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/modules/config/install/module.qbs0000644000175100017510000000005415232633614025305 0ustar runnerrunnerConfigInstall { importLibraries: true } qbs-src-3.3.1/tutorial/chapter-9/qbs/imports/0000755000175100017510000000000015232633614020424 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/qbs/imports/MyLibrary.qbs0000644000175100017510000000144315232633614023047 0ustar runnerrunner// ![0] CppLibrary { Depends { name: "config.myproject" } version: config.myproject.productVersion readonly property string _nameUpper : name.replace(" ", "_").toUpperCase() property string libraryMacro: _nameUpper + "_LIBRARY" property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY" cpp.defines: config.build.libraryType === "static" ? [staticLibraryMacro] : [libraryMacro] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Export { Depends { name: "cpp" } cpp.includePaths: [exportingProduct.sourceDirectory] cpp.defines: exportingProduct.config.build.libraryType === "static" ? [exportingProduct.staticLibraryMacro] : [] } Depends { name: "bundle" } bundle.isBundle: false } // ![0] qbs-src-3.3.1/tutorial/chapter-9/qbs/imports/MyApplication.qbs0000644000175100017510000000020715232633614023703 0ustar runnerrunnerCppApplication { Depends { name: "config.myproject" } version: config.myproject.productVersion consoleApplication: true } qbs-src-3.3.1/tutorial/chapter-9/qbs/imports/ConfigMyProject.qbs0000644000175100017510000000151115232633614024173 0ustar runnerrunnerimport qbs.FileInfo //! [0] // qbs/imports/ConfigMyProject.qbs Module { property string productVersion: "1.0.0" // ... //! [0] property bool enableAddressSanitizer: false Depends { name: "Sanitizers.address"; condition: enableAddressSanitizer } Depends { name: "cpp" } Depends { name: "config.install" } property bool enableRPath: true property stringList libRPaths: { if (enableRPath && cpp.rpathOrigin && product.installDir) { return [ FileInfo.joinPaths( cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.installDir), FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory)))]; } return []; } cpp.rpaths: libRPaths } qbs-src-3.3.1/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs0000644000175100017510000000007015232633614023206 0ustar runnerrunnerMyApplication { type: ["application", "autotest"] } qbs-src-3.3.1/tutorial/chapter-9/app/0000755000175100017510000000000015232633614016722 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/app/main.c0000644000175100017510000000033415232633614020012 0ustar runnerrunner//![0] #include #include #include int main() { printf("Hello, world\n"); printf("%s\n", get_string()); printf("ProductVersion = %s\n", kProductVersion); return 0; } //![0] qbs-src-3.3.1/tutorial/chapter-9/app/app.qbs0000644000175100017510000000025615232633614020214 0ustar runnerrunner//! [0] MyApplication { Depends { name: "mylib" } Depends { name: "version_header" } name: "My Application" targetName: "myapp" files: "main.c" } //! [0] qbs-src-3.3.1/tutorial/chapter-9/test/0000755000175100017510000000000015232633614017121 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/test/test.qbs0000644000175100017510000000012415232633614020604 0ustar runnerrunnerMyAutoTest { Depends { name: "mylib" } name: "mytest" files: "test.c" } qbs-src-3.3.1/tutorial/chapter-9/test/test.c0000644000175100017510000000056215232633614020247 0ustar runnerrunner#include "lib.h" #include #include int main(int argc, char *argv[]) { if (argc > 2) { printf("usage: test [value]\n"); return 1; } const char *expected = argc == 2 ? argv[1] : "Hello from library"; if (strcmp(get_string(), expected) != 0) { printf("text differs\n"); return 1; } return 0; } qbs-src-3.3.1/tutorial/chapter-9/version-header/0000755000175100017510000000000015232633614021055 5ustar runnerrunnerqbs-src-3.3.1/tutorial/chapter-9/version-header/version.h.in0000644000175100017510000000023615232633614023321 0ustar runnerrunner//! [0] // version-header/version.h.in #ifndef VERSION_H #define VERSION_H const char kProductVersion[] = "${PRODUCT_VERSION}"; #endif // VERSION_H //! [0] qbs-src-3.3.1/tutorial/chapter-9/version-header/version-header.qbs0000644000175100017510000000235315232633614024502 0ustar runnerrunner//! [5] // version-header/version-header.qbs //! [0] import qbs.TextFile Product { name: "version_header" type: "hpp" Depends { name: "config.myproject" } //! [0] //! [1] Group { files: ["version.h.in"] fileTags: ["version_h_in"] } //! [1] //! [2] Rule { inputs: ["version_h_in"] Artifact { filePath: "version.h" fileTags: "hpp" } //! [2] //! [3] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(input.filePath, TextFile.ReadOnly); var content = file.readAll(); content = content.replace( "${PRODUCT_VERSION}", product.config.myproject.productVersion); file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(content); file.close(); } return cmd; } //! [3] } //! [4] Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.buildDirectory } //! [4] } //! [5] qbs-src-3.3.1/bin/0000755000175100017510000000000015232633614013253 5ustar runnerrunnerqbs-src-3.3.1/bin/ibqbs.bat0000644000175100017510000000007515232633614015045 0ustar runnerrunner@xgConsole /profile=%~dp0\ibmsvc.xml /command="qbs -j 20 %*" qbs-src-3.3.1/bin/ibmsvc.xml0000644000175100017510000000112215232633614015254 0ustar runnerrunner qbs-src-3.3.1/LGPL_EXCEPTION.txt0000644000175100017510000000225015232633614015417 0ustar runnerrunnerThe Qt Company LGPL Exception version 1.1 As an additional permission to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that: (i) the header files of the Library have not been modified; and (ii) the incorporated material is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the GNU Lesser General Public License version 2.1. Moreover, you may apply this exception to a modified version of the Library, provided that such modification does not involve copying material from the Library into the modified Library's header files unless such material is limited to (i) numerical parameters; (ii) data structure layouts; (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length. Furthermore, you are not required to apply this additional permission to a modified version of the Library. qbs-src-3.3.1/scripts/0000755000175100017510000000000015232633614014172 5ustar runnerrunnerqbs-src-3.3.1/scripts/build-qbs-with-qbs.sh0000755000175100017510000001206115232633614020147 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -e # # Qbs is built with the address sanitizer enabled. # Suppress findings in some parts of Qbs / dependencies. # export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" if [ -z "${QBS_BUILD_PROFILE}" ]; then QBS_BUILD_PROFILE=$(qbs config defaultProfile | cut -d: -f2 | tr -d '[:space:]') fi if [ -z "${QBS_BUILD_PROFILE}" ]; then echo "Either QBS_BUILD_PROFILE or a defaultProfile must be set." exit 1 fi # # Additional build options # BUILD_OPTIONS="\ profile:${QBS_BUILD_PROFILE} \ modules.qbsbuildconfig.enableUnitTests:true \ modules.cpp.treatWarningsAsErrors:true \ modules.qbsbuildconfig.enableBundledQt:true \ modules.cpp.separateDebugInformation:true \ ${BUILD_OPTIONS} \ config:release \ " # # Build all default products of Qbs # qbs resolve ${BUILD_OPTIONS} qbs build ${BUILD_OPTIONS} WITH_DOCS=${WITH_DOCS:-1} if [ "$WITH_DOCS" -ne 0 ]; then qbs build -p "qbs documentation" ${BUILD_OPTIONS} fi WITH_ARCHIVE=${WITH_ARCHIVE:-1} if [ "$WITH_ARCHIVE" -ne 0 ]; then qbs build -p "qbs_archive" ${BUILD_OPTIONS} fi WITH_TESTS=${WITH_TESTS:-1} if [ "$WITH_TESTS" -eq 0 ]; then exit 0 fi QMAKE_PATH=${QMAKE_PATH:-$(which qmake)} # # Set up profiles for the freshly built Qbs if not # explicitly specified otherwise # if [ -z "${QBS_AUTOTEST_PROFILE}" ]; then export QBS_AUTOTEST_PROFILE=autotestprofile export QBS_AUTOTEST_SETTINGS_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'qbs-settings'` QBS_AUTOTEST_QMAKE_PATH=${QBS_AUTOTEST_QMAKE_PATH:-${QMAKE_PATH}} RUN_OPTIONS="\ --settings-dir ${QBS_AUTOTEST_SETTINGS_DIR} \ " qbs run -p qbs_app ${BUILD_OPTIONS} -- setup-toolchains \ ${RUN_OPTIONS} \ --detect qbs run -p qbs_app ${BUILD_OPTIONS} -- setup-qt \ ${RUN_OPTIONS} \ "${QBS_AUTOTEST_QMAKE_PATH}" ${QBS_AUTOTEST_PROFILE} # Make sure that the Qt profile uses the same toolchain profile # that was used for building in case a custom QBS_BUILD_PROFILE # was set. Otherwise setup-qt automatically uses the default # toolchain profile. if [ -z "${QBS_AUTOTEST_BASE_PROFILE}" ]; then QBS_AUTOTEST_BASE_PROFILE=$(qbs config profiles.${QBS_BUILD_PROFILE}.baseProfile | cut -d: -f2) fi if [ ! -z "${QBS_AUTOTEST_BASE_PROFILE}" ]; then echo "Setting base profile for ${QBS_AUTOTEST_PROFILE} to ${QBS_AUTOTEST_BASE_PROFILE}" qbs run -p qbs_app ${BUILD_OPTIONS} -- config \ ${RUN_OPTIONS} \ profiles.${QBS_AUTOTEST_PROFILE}.baseProfile ${QBS_AUTOTEST_BASE_PROFILE} fi qbs run -p qbs_app ${BUILD_OPTIONS} -- config \ ${RUN_OPTIONS} \ --list # QBS_AUTOTEST_PROFILE has been added to the environment # which requires a resolve step qbs resolve ${BUILD_OPTIONS} fi # # Run all autotests with QBS_AUTOTEST_PROFILE. Some test cases might run for # over 10 minutes. Output an empty line every 9:50 minutes to prevent a 10min # timeout on Travis CI. # (while true; do echo "" && sleep 590; done) & trap "kill $!; wait $! 2>/dev/null || true; killall sleep || true" EXIT qbs build -p "autotest-runner" ${BUILD_OPTIONS} qbs-src-3.3.1/scripts/test-baremetal.sh0000755000175100017510000000447515232633614017454 0ustar runnerrunner#!/usr/bin/env bash set -eu ############################################################################# ## ## Copyright (C) 2020 Denis Shienkov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" export PATH="$1:$PATH" export QBS_AUTOTEST_ALWAYS_LOG_STDERR=true echo "Auto-detecting the Qbs profiles." qbs-setup-toolchains --detect qbs-config --list profiles echo "Testing the Qbs toolchains." export QBS_AUTOTEST_PROFILE=${QBS_AUTOTEST_PROFILE:-arm-none-eabi-gcc-9_2} tst_blackbox-baremetal qbs-src-3.3.1/scripts/install-qt.sh0000755000175100017510000004262315232633614016630 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu function help() { cat < Root directory where to install the components. Maps to C:/Qt on Windows, /opt/Qt on Linux, /usr/local/Qt on Mac by default. -f, --force Force download and do not attempt to re-use an existing installation. --host The host operating system. Can be one of linux_x64, mac_x64, windows_x86. Auto-detected by default. --target The desired target platform. Can be one of desktop, android, ios. The default value is desktop. --toolchain The toolchain that has been used to build the binaries. Possible values depend on --host and --target, respectively: linux_x64 android any, android_armv7, android_arm64_v8a desktop gcc_64 (default) mac_x64 android any, android_armv7, android_arm64_v8a desktop clang_64 (default) ios ios windows_x86 android any, android_armv7, android_arm64_v8a desktop win64_mingw73, win64_msvc2017_64 (default) --version The desired Qt version. Currently supported are all versions above 5.9.0. EOF } TARGET_PLATFORM=desktop COMPONENTS= VERSION= FORCE_DOWNLOAD=false MD5_TOOL=md5sum case "$OSTYPE" in *linux*) HOST_OS=linux_x64 INSTALL_DIR=/opt/Qt TOOLCHAIN=gcc_64 ;; *darwin*) HOST_OS=mac_x64 INSTALL_DIR=/usr/local/Qt TOOLCHAIN=clang_64 MD5_TOOL="md5 -r" ;; msys|cygwin) HOST_OS=windows_x86 INSTALL_DIR=/c/Qt TOOLCHAIN=win64_msvc2015_64 ;; *) HOST_OS= INSTALL_DIR= ;; esac while [ $# -gt 0 ]; do case "$1" in --directory|-d) INSTALL_DIR="$2" shift ;; --force|-f) FORCE_DOWNLOAD=true ;; --host) HOST_OS="$2" shift ;; --target) TARGET_PLATFORM="$2" shift ;; --toolchain) TOOLCHAIN=$(echo $2 | tr '[:upper:]' '[:lower:]') shift ;; --version) VERSION="$2" shift ;; --help|-h) help exit 0 ;; *) COMPONENTS="${COMPONENTS} $1" ;; esac shift done if [ -z "${HOST_OS}" ]; then echo "No --host specified or auto-detection failed." >&2 exit 1 fi if [ -z "${INSTALL_DIR}" ]; then echo "No --directory specified or auto-detection failed." >&2 exit 1 fi if [ -z "${VERSION}" ]; then echo "No --version specified." >&2 exit 1 fi if [ -z "${COMPONENTS}" ]; then echo "No components specified." >&2 exit 1 fi case "$TARGET_PLATFORM" in android) ;; ios) ;; desktop) ;; wasm) ;; *) echo "Error: TARGET_PLATFORM=${TARGET_PLATFORM} is not valid." >&2 exit 1 ;; esac HASH=$(echo "${OSTYPE} ${TARGET_PLATFORM} ${TOOLCHAIN} ${VERSION} ${INSTALL_DIR}" | ${MD5_TOOL} | head -c 16) HASH_FILEPATH="${INSTALL_DIR}/${HASH}.manifest" INSTALLATION_IS_VALID=false if ! ${FORCE_DOWNLOAD} && [ -f "${HASH_FILEPATH}" ]; then INSTALLATION_IS_VALID=true while read filepath; do if [ ! -e "${filepath}" ]; then INSTALLATION_IS_VALID=false break fi done <"${HASH_FILEPATH}" fi if ${INSTALLATION_IS_VALID}; then echo "Already installed. Skipping download." >&2 exit 0 fi MIRRORS="\ http://ftp.acc.umu.se/mirror/qt.io/qtproject \ http://ftp.fau.de/qtproject \ http://download.qt.io \ " for MIRROR in ${MIRRORS}; do if curl "${MIRROR}/online" -s -f -o /dev/null; then break; else echo "Server ${MIRROR} not availabe. Trying next alternative..." >&2 MIRROR="" fi done DOWNLOAD_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'install-qt'` # # The repository structure is a mess. Try different URL variants # function compute_url(){ local COMPONENT=$1 local CURL="curl -s -L" local BASE_URL="${MIRROR}/online/qtsdkrepository/${HOST_OS}/${TARGET_PLATFORM}" local ANDROID_ARCH=$(echo ${TOOLCHAIN##android_}) if [[ "${COMPONENT}" =~ "qtcreator" ]]; then if [[ "${HOST_OS}" == "windows_x86" ]]; then # newer QtC versions do not supported x86 version anymore HOST_OS="windows_x64" fi SHORT_VERSION=${VERSION%??} BASE_URL="${MIRROR}/official_releases/qtcreator" REMOTE_PATH="${SHORT_VERSION}/${VERSION}/installer_source/${HOST_OS}/qtcreator.7z" echo "${BASE_URL}/${REMOTE_PATH}" return 0 elif [[ "${COMPONENT}" =~ "mingw" ]]; then REMOTE_BASE="tools_mingw90/qt.tools.${TOOLCHAIN}${VERSION//./}" REMOTE_PATH="$(${CURL} ${BASE_URL}/${REMOTE_BASE}/ | grep -o -E "[[:alnum:]_.\-]*7z" | grep -v "meta" | head -1)" if [ ! -z "${REMOTE_PATH}" ]; then echo "${BASE_URL}/${REMOTE_BASE}/${REMOTE_PATH}" return 0 fi else HOST_OS_NAME=${HOST_OS//_x64/} HOST_OS_NAME=${HOST_OS_NAME//_arm64/} REMOTE_BASES=( # New repository format (>=6.8.0) # qt6_680/qt6_680/qt.qt6.680.clang_64/6.8.3-0-*qtbase-*.7z "qt6_${VERSION//./}/qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${TOOLCHAIN}" # qt6_680/qt6_680/qt.qt6.680.linux_gcc_64/6.8.3-0-*qtbase-*.7z "qt6_${VERSION//./}/qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${HOST_OS_NAME}_${TOOLCHAIN}" # qt6_680/qt6_680/qt.qt6.680.addons.qt5compat.clang_64/6.8.3-0-*.7z "qt6_${VERSION//./}/qt6_${VERSION//./}/qt.qt6.${VERSION//./}.addons.${COMPONENT}.${TOOLCHAIN}" # qt6_680/qt6_680/qt.qt6.680.addons.qt5compat.linux_gcc_64/6.8.3-0-*.7z "qt6_${VERSION//./}/qt6_${VERSION//./}/qt.qt6.${VERSION//./}.addons.${COMPONENT}.${HOST_OS_NAME}_${TOOLCHAIN}" # New repository format (>=6.0.0) "qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${TOOLCHAIN}" "qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${HOST_OS_NAME}_${TOOLCHAIN}" "qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${COMPONENT}.${TOOLCHAIN}" "qt6_${VERSION//./}/qt.qt6.${VERSION//./}.${COMPONENT}.${HOST_OS_NAME}_${TOOLCHAIN}" "qt6_${VERSION//./}_${ANDROID_ARCH}/qt.qt6.${VERSION//./}.${TOOLCHAIN}" "qt6_${VERSION//./}_${ANDROID_ARCH}/qt.qt6.${VERSION//./}.${COMPONENT}.${TOOLCHAIN}" "qt${VERSION//./_}/qt6_${VERSION//./}_${TOOLCHAIN}/qt.qt6.${VERSION//./}.${TOOLCHAIN}" "qt${VERSION//./_}/qt6_${VERSION//./}_${TOOLCHAIN}/qt.qt6.${VERSION//./}.${COMPONENT}" "qt${VERSION//./_}/qt6_${VERSION//./}_${TOOLCHAIN}/qt.qt6.${VERSION//./}.${COMPONENT}.${TOOLCHAIN}" # New repository format (>=5.9.6) "qt5_${VERSION//./}/qt.qt5.${VERSION//./}.${TOOLCHAIN}" "qt5_${VERSION//./}/qt.qt5.${VERSION//./}.${COMPONENT}.${TOOLCHAIN}" # Multi-abi Android since 5.14 "qt5_${VERSION//./}/qt.qt5.${VERSION//./}.${TARGET_PLATFORM}" "qt5_${VERSION//./}/qt.qt5.${VERSION//./}.${COMPONENT}.${TARGET_PLATFORM}" # Older repository format (<5.9.0) "qt5_${VERSION//./}/qt.${VERSION//./}.${TOOLCHAIN}" "qt5_${VERSION//./}/qt.${VERSION//./}.${COMPONENT}.${TOOLCHAIN}" ) for REMOTE_BASE in ${REMOTE_BASES[*]}; do REMOTE_PATH="$(${CURL} ${BASE_URL}/${REMOTE_BASE}/ | grep -o -E "[[:alnum:]_.\-]*7z" | grep "${COMPONENT}" | tail -1)" if [ ! -z "${REMOTE_PATH}" ]; then echo "${BASE_URL}/${REMOTE_BASE}/${REMOTE_PATH}" return 0 fi done fi echo "Could not determine a remote URL for ${COMPONENT} with version ${VERSION}">&2 exit 1 } function version { echo "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }'; } mkdir -p ${INSTALL_DIR} rm -f "${HASH_FILEPATH}" for COMPONENT in ${COMPONENTS}; do if [[ "${TOOLCHAIN}" =~ "win64_mingw" ]]; then TOOLCHAIN_DIR="${TOOLCHAIN/win64_/}_64" elif [[ "${TOOLCHAIN}" =~ "win32_mingw" ]]; then TOOLCHAIN_DIR="${TOOLCHAIN/win32_/}_32" elif [[ "${TOOLCHAIN}" =~ "win64_msvc" ]]; then TOOLCHAIN_DIR="${TOOLCHAIN/win64_/}" elif [[ "${TOOLCHAIN}" =~ "win32_msvc" ]]; then TOOLCHAIN_DIR="${TOOLCHAIN/win32_/}" elif [[ "${TOOLCHAIN}" =~ "any" ]] && [[ "${TARGET_PLATFORM}" == "android" ]]; then TOOLCHAIN_DIR="android" elif [[ "${HOST_OS}" == "mac_x64" ]] && [[ ! "$(version "${VERSION}")" < "$(version "6.1.2")" ]] && [[ "${TARGET_PLATFORM}" == "desktop" ]]; then TOOLCHAIN_DIR="macos" else TOOLCHAIN_DIR="${TOOLCHAIN}" fi if [[ "${COMPONENT}" =~ "qtcreator" ]] && [[ "${HOST_OS}" != "mac_x64" ]]; then UNPACK_DIR="${INSTALL_DIR}/Tools/QtCreator" ARCHIVER_DIR="${UNPACK_DIR}" mkdir -p ${UNPACK_DIR} elif [[ ! "${COMPONENT}" =~ "qtcreator" ]] && [[ "$(version "${VERSION}")" > "$(version "6.8.0")" ]]; then UNPACK_DIR="${INSTALL_DIR}" ARCHIVER_DIR="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}" if [[ "${COMPONENT}" =~ "icu" ]]; then ARCHIVER_DIR="${ARCHIVER_DIR}/lib" fi mkdir -p ${ARCHIVER_DIR} else UNPACK_DIR="${INSTALL_DIR}" ARCHIVER_DIR="${UNPACK_DIR}" fi if [ "$(version "${VERSION}")" -ge "$(version "6.0.0")" ]; then if [[ "${COMPONENT}" =~ "qtscript" ]] || [[ "${COMPONENT}" =~ "qtscxml" ]] || [[ "${COMPONENT}" =~ "qtx11extras" ]]; then echo "Component ${COMPONENT} was removed in Qt6, skipping" >&2 continue fi if [[ "${COMPONENT}" =~ "icu" ]] && [[ "${TARGET_PLATFORM}" =~ "wasm" ]]; then echo "Component ${COMPONENT} is not present in Qt6 (${TARGET_PLATFORM}), skipping" >&2 continue fi else if [[ "${COMPONENT}" =~ "qt5compat" ]] || [[ "${COMPONENT}" =~ "shadertools" ]]; then echo "Component ${COMPONENT} is not present in Qt ${VERSION}, skipping" >&2 continue fi fi URL="$(compute_url ${COMPONENT})" echo "Downloading ${COMPONENT} ${URL}..." >&2 curl --progress-bar -L -o ${DOWNLOAD_DIR}/package.7z ${URL} >&2 7z x -y -o${ARCHIVER_DIR} ${DOWNLOAD_DIR}/package.7z >/dev/null 2>&1 7z l -ba -slt -y ${DOWNLOAD_DIR}/package.7z | tr '\\' '/' | sed -n -e "s|^Path\ =\ |${ARCHIVER_DIR}/|p" >> "${HASH_FILEPATH}" 2>/dev/null rm -f ${DOWNLOAD_DIR}/package.7z # # conf file is needed for qmake # if [[ "${COMPONENT}" == "qtbase" ]]; then if [ "${TARGET_PLATFORM}" == "android" ] && [ ! "$(version "${VERSION}")" < "$(version "6.0.0")" ]; then CONF_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/target_qt.conf" ANDROID_QMAKE_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/qmake" if [ "${TOOLCHAIN}" == "android_armv7" ] && [ ! "$(version "${VERSION}")" < "$(version "6.4.2")" ]; then sed -i "s/\r//" "${CONF_FILE}" sed -i "s|HostLibraryExecutables=.\/bin|HostLibraryExecutables=.\/libexec|g" "${CONF_FILE}" chmod +x "${ANDROID_QMAKE_FILE}" sed -i "s|\\\|\/|g" "${ANDROID_QMAKE_FILE}" fi sed -i "s|target|../$TOOLCHAIN|g" "${CONF_FILE}" sed -i "/HostPrefix/ s|$|gcc_64|g" "${CONF_FILE}" QMAKE_FILE="${UNPACK_DIR}/${VERSION}/gcc_64/bin/qmake" sed -i "s|\/home\/qt\/work\/install\/bin\/qmake|$QMAKE_FILE|g" "${ANDROID_QMAKE_FILE}" sed -i "s|\/Users\/qt\/work\/install\/bin\/qmake|$QMAKE_FILE|g" "${ANDROID_QMAKE_FILE}" elif [ "${TARGET_PLATFORM}" == "ios" ] && [ ! "${VERSION}" \< "6.0.0" ]; then CONF_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/target_qt.conf" sed -i.bak "s|HostData=target|HostData=../$TOOLCHAIN|g" "${CONF_FILE}" sed -i.bak "s|HostPrefix=..\/..\/|HostPrefix=..\/..\/macos|g" "${CONF_FILE}" IOS_QMAKE_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/qmake" QMAKE_FILE="${UNPACK_DIR}/${VERSION}/macos/bin/qmake" sed -i.bak "s|\/Users\/qt\/work\/install\/bin\/qmake|${QMAKE_FILE}|g" "${IOS_QMAKE_FILE}" elif [ "${TARGET_PLATFORM}" == "wasm" ] && [ ! "${VERSION}" \< "6.0.0" ]; then CONF_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/target_qt.conf" sed -i.bak "s|HostData=target|HostData=../$TOOLCHAIN|g" "${CONF_FILE}" sed -i.bak "s|HostPrefix=..\/..\/|HostPrefix=..\/..\/gcc_64|g" "${CONF_FILE}" WASM_QMAKE_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/qmake" QMAKE_FILE="${UNPACK_DIR}/${VERSION}/gcc_64/bin/qmake" sed -i.bak "s|\/home\/qt\/work\/install\/bin\/qmake|${QMAKE_FILE}|g" "${WASM_QMAKE_FILE}" elif [ "${TARGET_PLATFORM}" == "desktop" ] && [ "${TOOLCHAIN}" == "win64_msvc2022_arm64_cross_compiled" ] && [ ! "${VERSION}" \< "6.0.0" ]; then CONF_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/target_qt.conf" sed -i.bak "s|HostData=target|HostData=../msvc2022_arm64_cross_compiled|g" "${CONF_FILE}" sed -i.bak "s|HostPrefix=..\/..\/|HostPrefix=..\/..\/msvc2022_64|g" "${CONF_FILE}" ARM64_QMAKE_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/qmake.bat" QMAKE_FILE='"%~dp0\\\\..\\\\..\\\\msvc2022_64\\\\bin\\\\qmake6.exe"' sed -i.bak "s|\\\\Users\\\\qt\\\\work\\\\install\\\\bin\\\\qmake6.exe|${QMAKE_FILE}|g" "${ARM64_QMAKE_FILE}" else CONF_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/bin/qt.conf" echo "[Paths]" > ${CONF_FILE} echo "Prefix = .." >> ${CONF_FILE} fi # Adjust the license to be able to run qmake # sed with -i requires intermediate file on Mac OS PRI_FILE="${UNPACK_DIR}/${VERSION}/${TOOLCHAIN_DIR}/mkspecs/qconfig.pri" sed -i.bak 's/Enterprise/OpenSource/g' "${PRI_FILE}" sed -i.bak 's/licheck.*//g' "${PRI_FILE}" rm "${PRI_FILE}.bak" # Print the directory so that the caller can # adjust the PATH variable. echo $(dirname "${CONF_FILE}") elif [[ "${COMPONENT}" =~ "mingw" ]]; then VERSION_DIR="${VERSION//./}" if [[ "${TOOLCHAIN}" =~ "win64_mingw" ]]; then if [[ "${VERSION}" == "9.0.0" ]]; then VERSION_DIR="1120" fi echo "${UNPACK_DIR}/Tools/mingw${VERSION_DIR}_64/bin" elif [[ "${TOOLCHAIN}" =~ "win32_mingw" ]]; then echo "${UNPACK_DIR}/Tools/mingw${VERSION_DIR}_32/bin" fi elif [[ "${COMPONENT}" =~ "qtcreator" ]]; then if [ "${HOST_OS}" == "mac_x64" ]; then echo "${UNPACK_DIR}/Qt Creator.app/Contents/MacOS" else echo "${UNPACK_DIR}/bin" fi fi done qbs-src-3.3.1/scripts/test-qt4.sh0000755000175100017510000000454015232633614016221 0ustar runnerrunner#!/usr/bin/env bash set -eu ############################################################################# ## ## Copyright (C) 2020 Raphael Cotty. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# export PATH="$1:$PATH" export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" # Creating the qt4 profile qbs-setup-toolchains /usr/bin/g++ gcc qbs-setup-qt /usr/lib/x86_64-linux-gnu/qt4/bin/qmake qt4 # To avoid warnings due to qt4 include files qbs config profiles.gcc.cpp.cxxFlags "-Wno-deprecated-copy" qbs config profiles.qt4.baseProfile gcc qbs config --list export QBS_AUTOTEST_PROFILE=qt4 tst_blackbox-qt qbs-src-3.3.1/scripts/install-qbs.sh0000755000175100017510000001077415232633614016773 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu set -o pipefail function help() { cat < Root directory where to install the components. Maps to C:/qbs on Windows, /opt/qbs on Linux by default. --host The host operating system. Can be one of linux-x86_64, windows-x86_64. Auto-detected by default. --version The desired Qbs version. EOF } case "$OSTYPE" in *linux*) HOST_OS=linux-x86_64 INSTALL_DIR=/opt/qbs ;; msys|cygwin) HOST_OS=windows-x86_64 INSTALL_DIR=/c/qbs ;; *) HOST_OS= INSTALL_DIR= ;; esac while [ $# -gt 0 ]; do case "$1" in --directory|-d) INSTALL_DIR="$2" shift ;; --host) HOST_OS="$2" shift ;; --version) VERSION="$2" shift ;; --help|-h) help exit 0 ;; *) echo "Unknown option: $1" >&2 help exit 1 ;; esac shift done if [ -z "${HOST_OS}" ]; then echo "No --host specified and auto-detection failed." >&2 exit 1 fi if [ -z "${INSTALL_DIR}" ]; then echo "No --directory specified and auto-detection failed." >&2 exit 1 fi if [ -z "${VERSION}" ]; then echo "No --version specified." >&2 exit 1 fi MIRRORS="\ http://ftp.acc.umu.se/mirror/qt.io/qtproject \ http://ftp.fau.de/qtproject \ http://download.qt.io \ " for MIRROR in ${MIRRORS}; do if curl "${MIRROR}/official_releases/qbs/${VERSION}/" -s -f -o /dev/null; then echo "Selected mirror: ${MIRROR}" >&2 break; else echo "Server ${MIRROR} not availabe. Trying next alternative..." >&2 MIRROR="" fi done BASE_FILENAME="qbs-${HOST_OS}-${VERSION}" DOWNLOAD_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'install-qbs'` rm -rf ${INSTALL_DIR}/${BASE_FILENAME} mkdir -p ${INSTALL_DIR} echo "Downloading Qbs ${VERSION}..." >&2 cd ${DOWNLOAD_DIR} if [[ ${HOST_OS} == "linux-x86_64" ]]; then FILENAME="${BASE_FILENAME}.tar.gz" curl -L "${MIRROR}/official_releases/qbs/${VERSION}/${FILENAME}" > ${FILENAME} tar -xzf ${FILENAME} elif [[ ${HOST_OS} == "windows-x86_64" ]]; then FILENAME="${BASE_FILENAME}.zip" curl -L "${MIRROR}/official_releases/qbs/${VERSION}/${FILENAME}" > ${FILENAME} 7z x -y -o${BASE_FILENAME} ${FILENAME} >/dev/null 2>&1 fi mv ${BASE_FILENAME} ${INSTALL_DIR} rm ${FILENAME} echo "${INSTALL_DIR}/${BASE_FILENAME}/bin" qbs-src-3.3.1/scripts/conan-profiles/0000755000175100017510000000000015232633614017111 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/mac_x64/0000755000175100017510000000000015232633614020352 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/mac_x64/clang_64/0000755000175100017510000000000015232633614021747 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/mac_x64/clang_64/qbs-test0000644000175100017510000000020615232633614023432 0ustar runnerrunner[settings] arch=x86_64 build_type=Release compiler=apple-clang compiler.cppstd=17 compiler.libcxx=libc++ compiler.version=13 os=Macos qbs-src-3.3.1/scripts/conan-profiles/mac_x64/clang_64/qbs-test-libs0000644000175100017510000000020615232633614024361 0ustar runnerrunner[settings] arch=x86_64 build_type=Release compiler=apple-clang compiler.cppstd=17 compiler.libcxx=libc++ compiler.version=13 os=Macos qbs-src-3.3.1/scripts/conan-profiles/win_x64/0000755000175100017510000000000015232633614020407 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/win_x64/mingw_64/0000755000175100017510000000000015232633614022041 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/win_x64/mingw_64/qbs-test0000644000175100017510000000020715232633614023525 0ustar runnerrunner[settings] arch=x86_64 build_type=Release compiler=gcc compiler.cppstd=17 compiler.libcxx=libstdc++11 compiler.version=11.2 os=Windows qbs-src-3.3.1/scripts/conan-profiles/win_x64/msvc_64/0000755000175100017510000000000015232633614021670 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/win_x64/msvc_64/qbs-test0000644000175100017510000000024215232633614023353 0ustar runnerrunner[settings] arch=x86_64 build_type=Release compiler=msvc compiler.cppstd=14 compiler.runtime=dynamic compiler.runtime_type=Release compiler.version=194 os=Windows qbs-src-3.3.1/scripts/conan-profiles/win_x64/msvc_64/qbs-test-libs0000644000175100017510000000024215232633614024302 0ustar runnerrunner[settings] arch=x86_64 build_type=Release compiler=msvc compiler.cppstd=14 compiler.runtime=dynamic compiler.runtime_type=Release compiler.version=193 os=Windows qbs-src-3.3.1/scripts/conan-profiles/mac_arm64/0000755000175100017510000000000015232633614020662 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/mac_arm64/clang_64/0000755000175100017510000000000015232633614022257 5ustar runnerrunnerqbs-src-3.3.1/scripts/conan-profiles/mac_arm64/clang_64/qbs-test0000644000175100017510000000020515232633614023741 0ustar runnerrunner[settings] arch=armv8 build_type=Release compiler=apple-clang compiler.cppstd=17 compiler.libcxx=libc++ compiler.version=13 os=Macos qbs-src-3.3.1/scripts/conan-profiles/mac_arm64/clang_64/qbs-test-libs0000644000175100017510000000020515232633614024670 0ustar runnerrunner[settings] arch=armv8 build_type=Release compiler=apple-clang compiler.cppstd=17 compiler.libcxx=libc++ compiler.version=13 os=Macos qbs-src-3.3.1/scripts/build-qbs-doc.sh0000755000175100017510000000450115232633614017156 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com). ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -e if [ -z "${QBS_BUILD_PROFILE}" ]; then QBS_BUILD_PROFILE=$(qbs config defaultProfile | cut -d: -f2 | tr -d '[:space:]') fi if [ -z "${QBS_BUILD_PROFILE}" ]; then echo "Either QBS_BUILD_PROFILE or a defaultProfile must be set." exit 1 fi # # Additional build options # BUILD_OPTIONS="\ profile:${QBS_BUILD_PROFILE} \ ${BUILD_OPTIONS} \ config:documentation \ " qbs build -p "qbs documentation" ${BUILD_OPTIONS} qbs-src-3.3.1/scripts/git-clang-format0000755000175100017510000006137215232633614017264 0ustar runnerrunner#!/usr/bin/env python3 # #===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===# # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# r""" clang-format git integration ============================ This file provides a clang-format integration for git. Put it somewhere in your path and ensure that it is executable. Then, "git clang-format" will invoke clang-format on the changes in current files or a specific commit. For further details, run: git clang-format -h Requires Python 2.7 or Python 3 """ from __future__ import absolute_import, division, print_function import argparse import collections import contextlib import errno import os import re import subprocess import sys usage = ('git clang-format [OPTIONS] [] [|--staged] ' '[--] [...]') desc = ''' If zero or one commits are given, run clang-format on all lines that differ between the working directory and , which defaults to HEAD. Changes are only applied to the working directory, or in the stage/index. Examples: To format staged changes, i.e everything that's been `git add`ed: git clang-format To also format everything touched in the most recent commit: git clang-format HEAD~1 If you're on a branch off main, to format everything touched on your branch: git clang-format main If two commits are given (requires --diff), run clang-format on all lines in the second that differ from the first . The following git-config settings set the default of the corresponding option: clangFormat.binary clangFormat.commit clangFormat.extensions clangFormat.style ''' # Name of the temporary index file in which save the output of clang-format. # This file is created within the .git directory. temp_index_basename = 'clang-format-index' Range = collections.namedtuple('Range', 'start, count') def main(): config = load_git_config() # In order to keep '--' yet allow options after positionals, we need to # check for '--' ourselves. (Setting nargs='*' throws away the '--', while # nargs=argparse.REMAINDER disallows options after positionals.) argv = sys.argv[1:] try: idx = argv.index('--') except ValueError: dash_dash = [] else: dash_dash = argv[idx:] argv = argv[:idx] default_extensions = ','.join([ # From clang/lib/Frontend/FrontendOptions.cpp, all lower case 'c', 'h', # C 'm', # ObjC 'mm', # ObjC++ 'cc', 'cp', 'cpp', 'c++', 'cxx', 'hh', 'hpp', 'hxx', 'inc', # C++ 'ccm', 'cppm', 'cxxm', 'c++m', # C++ Modules 'cu', 'cuh', # CUDA # Other languages that clang-format supports 'proto', 'protodevel', # Protocol Buffers 'java', # Java 'js', # JavaScript 'ts', # TypeScript 'cs', # C Sharp 'json', # Json 'sv', 'svh', 'v', 'vh', # Verilog ]) p = argparse.ArgumentParser( usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter, description=desc) p.add_argument('--binary', default=config.get('clangformat.binary', 'clang-format'), help='path to clang-format'), p.add_argument('--commit', default=config.get('clangformat.commit', 'HEAD'), help='default commit to use if none is specified'), p.add_argument('--diff', action='store_true', help='print a diff instead of applying the changes') p.add_argument('--diffstat', action='store_true', help='print a diffstat instead of applying the changes') p.add_argument('--extensions', default=config.get('clangformat.extensions', default_extensions), help=('comma-separated list of file extensions to format, ' 'excluding the period and case-insensitive')), p.add_argument('-f', '--force', action='store_true', help='allow changes to unstaged files') p.add_argument('-p', '--patch', action='store_true', help='select hunks interactively') p.add_argument('-q', '--quiet', action='count', default=0, help='print less information') p.add_argument('--staged', '--cached', action='store_true', help='format lines in the stage instead of the working dir') p.add_argument('--style', default=config.get('clangformat.style', None), help='passed to clang-format'), p.add_argument('-v', '--verbose', action='count', default=0, help='print extra information') p.add_argument('--diff_from_common_commit', action='store_true', help=('diff from the last common commit for commits in ' 'separate branches rather than the exact point of the ' 'commits')) # We gather all the remaining positional arguments into 'args' since we need # to use some heuristics to determine whether or not was present. # However, to print pretty messages, we make use of metavar and help. p.add_argument('args', nargs='*', metavar='', help='revision from which to compute the diff') p.add_argument('ignored', nargs='*', metavar='...', help='if specified, only consider differences in these files') opts = p.parse_args(argv) opts.verbose -= opts.quiet del opts.quiet commits, files = interpret_args(opts.args, dash_dash, opts.commit) if len(commits) > 2: die('at most two commits allowed; %d given' % len(commits)) if len(commits) == 2: if opts.staged: die('--staged is not allowed when two commits are given') if not opts.diff: die('--diff is required when two commits are given') elif opts.diff_from_common_commit: die('--diff_from_common_commit is only allowed when two commits are given') if os.path.dirname(opts.binary): opts.binary = os.path.abspath(opts.binary) changed_lines = compute_diff_and_extract_lines(commits, files, opts.staged, opts.diff_from_common_commit) if opts.verbose >= 1: ignored_files = set(changed_lines) filter_by_extension(changed_lines, opts.extensions.lower().split(',')) # The computed diff outputs absolute paths, so we must cd before accessing # those files. cd_to_toplevel() filter_symlinks(changed_lines) if opts.verbose >= 1: ignored_files.difference_update(changed_lines) if ignored_files: print( 'Ignoring changes in the following files (wrong extension or symlink):') for filename in ignored_files: print(' %s' % filename) if changed_lines: print('Running clang-format on the following files:') for filename in changed_lines: print(' %s' % filename) if not changed_lines: if opts.verbose >= 0: print('no modified files to format') return 0 if len(commits) > 1: old_tree = commits[1] revision = old_tree elif opts.staged: old_tree = create_tree_from_index(changed_lines) revision = '' else: old_tree = create_tree_from_workdir(changed_lines) revision = None new_tree = run_clang_format_and_save_to_tree(changed_lines, revision, binary=opts.binary, style=opts.style) if opts.verbose >= 1: print('old tree: %s' % old_tree) print('new tree: %s' % new_tree) if old_tree == new_tree: if opts.verbose >= 0: print('clang-format did not modify any files') return 0 if opts.diff: return print_diff(old_tree, new_tree) if opts.diffstat: return print_diffstat(old_tree, new_tree) changed_files = apply_changes(old_tree, new_tree, force=opts.force, patch_mode=opts.patch) if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1: print('changed files:') for filename in changed_files: print(' %s' % filename) return 1 def load_git_config(non_string_options=None): """Return the git configuration as a dictionary. All options are assumed to be strings unless in `non_string_options`, in which is a dictionary mapping option name (in lower case) to either "--bool" or "--int".""" if non_string_options is None: non_string_options = {} out = {} for entry in run('git', 'config', '--list', '--null').split('\0'): if entry: if '\n' in entry: name, value = entry.split('\n', 1) else: # A setting with no '=' ('\n' with --null) is implicitly 'true' name = entry value = 'true' if name in non_string_options: value = run('git', 'config', non_string_options[name], name) out[name] = value return out def interpret_args(args, dash_dash, default_commit): """Interpret `args` as "[commits] [--] [files]" and return (commits, files). It is assumed that "--" and everything that follows has been removed from args and placed in `dash_dash`. If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its left (if present) are taken as commits. Otherwise, the arguments are checked from left to right if they are commits or files. If commits are not given, a list with `default_commit` is used.""" if dash_dash: if len(args) == 0: commits = [default_commit] else: commits = args for commit in commits: object_type = get_object_type(commit) if object_type not in ('commit', 'tag'): if object_type is None: die("'%s' is not a commit" % commit) else: die("'%s' is a %s, but a commit was expected" % (commit, object_type)) files = dash_dash[1:] elif args: commits = [] while args: if not disambiguate_revision(args[0]): break commits.append(args.pop(0)) if not commits: commits = [default_commit] files = args else: commits = [default_commit] files = [] return commits, files def disambiguate_revision(value): """Returns True if `value` is a revision, False if it is a file, or dies.""" # If `value` is ambiguous (neither a commit nor a file), the following # command will die with an appropriate error message. run('git', 'rev-parse', value, verbose=False) object_type = get_object_type(value) if object_type is None: return False if object_type in ('commit', 'tag'): return True die('`%s` is a %s, but a commit or filename was expected' % (value, object_type)) def get_object_type(value): """Returns a string description of an object's type, or None if it is not a valid git object.""" cmd = ['git', 'cat-file', '-t', value] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: return None return convert_string(stdout.strip()) def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit): """Calls compute_diff() followed by extract_lines().""" diff_process = compute_diff(commits, files, staged, diff_common_commit) changed_lines = extract_lines(diff_process.stdout) diff_process.stdout.close() diff_process.wait() if diff_process.returncode != 0: # Assume error was already printed to stderr. sys.exit(2) return changed_lines def compute_diff(commits, files, staged, diff_common_commit): """Return a subprocess object producing the diff from `commits`. The return value's `stdin` file object will produce a patch with the differences between the working directory (or stage if --staged is used) and the first commit if a single one was specified, or the difference between both specified commits, filtered on `files` (if non-empty). Zero context lines are used in the patch.""" git_tool = 'diff-index' extra_args = [] if len(commits) == 2: git_tool = 'diff-tree' if diff_common_commit: commits = [f'{commits[0]}...{commits[1]}'] elif staged: extra_args += ['--cached'] cmd = ['git', git_tool, '-p', '-U0'] + extra_args + commits + ['--'] cmd.extend(files) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) p.stdin.close() return p def extract_lines(patch_file): """Extract the changed lines in `patch_file`. The return value is a dictionary mapping filename to a list of (start_line, line_count) pairs. The input must have been produced with ``-U0``, meaning unidiff format with zero lines of context. The return value is a dict mapping filename to a list of line `Range`s.""" matches = {} for line in patch_file: line = convert_string(line) match = re.search(r'^\+\+\+\ [^/]+/(.*)', line) if match: filename = match.group(1).rstrip('\r\n\t') match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line) if match: start_line = int(match.group(1)) line_count = 1 if match.group(3): line_count = int(match.group(3)) if line_count == 0: line_count = 1 if start_line == 0: continue matches.setdefault(filename, []).append(Range(start_line, line_count)) return matches def filter_by_extension(dictionary, allowed_extensions): """Delete every key in `dictionary` that doesn't have an allowed extension. `allowed_extensions` must be a collection of lowercase file extensions, excluding the period.""" allowed_extensions = frozenset(allowed_extensions) for filename in list(dictionary.keys()): base_ext = filename.rsplit('.', 1) if len(base_ext) == 1 and '' in allowed_extensions: continue if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions: del dictionary[filename] def filter_symlinks(dictionary): """Delete every key in `dictionary` that is a symlink.""" for filename in list(dictionary.keys()): if os.path.islink(filename): del dictionary[filename] def cd_to_toplevel(): """Change to the top level of the git repository.""" toplevel = run('git', 'rev-parse', '--show-toplevel') os.chdir(toplevel) def create_tree_from_workdir(filenames): """Create a new git tree with the given files from the working directory. Returns the object ID (SHA-1) of the created tree.""" return create_tree(filenames, '--stdin') def create_tree_from_index(filenames): # Copy the environment, because the files have to be read from the original # index. env = os.environ.copy() def index_contents_generator(): for filename in filenames: git_ls_files_cmd = ['git', 'ls-files', '--stage', '-z', '--', filename] git_ls_files = subprocess.Popen(git_ls_files_cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdout = git_ls_files.communicate()[0] yield convert_string(stdout.split(b'\0')[0]) return create_tree(index_contents_generator(), '--index-info') def run_clang_format_and_save_to_tree(changed_lines, revision=None, binary='clang-format', style=None): """Run clang-format on each file and save the result to a git tree. Returns the object ID (SHA-1) of the created tree.""" # Copy the environment when formatting the files in the index, because the # files have to be read from the original index. env = os.environ.copy() if revision == '' else None def iteritems(container): try: return container.iteritems() # Python 2 except AttributeError: return container.items() # Python 3 def index_info_generator(): for filename, line_ranges in iteritems(changed_lines): if revision is not None: if len(revision) > 0: git_metadata_cmd = ['git', 'ls-tree', '%s:%s' % (revision, os.path.dirname(filename)), os.path.basename(filename)] else: git_metadata_cmd = ['git', 'ls-files', '--stage', '--', filename] git_metadata = subprocess.Popen(git_metadata_cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdout = git_metadata.communicate()[0] mode = oct(int(stdout.split()[0], 8)) else: mode = oct(os.stat(filename).st_mode) # Adjust python3 octal format so that it matches what git expects if mode.startswith('0o'): mode = '0' + mode[2:] blob_id = clang_format_to_blob(filename, line_ranges, revision=revision, binary=binary, style=style, env=env) yield '%s %s\t%s' % (mode, blob_id, filename) return create_tree(index_info_generator(), '--index-info') def create_tree(input_lines, mode): """Create a tree object from the given input. If mode is '--stdin', it must be a list of filenames. If mode is '--index-info' is must be a list of values suitable for "git update-index --index-info", such as " ". Any other mode is invalid.""" assert mode in ('--stdin', '--index-info') cmd = ['git', 'update-index', '--add', '-z', mode] with temporary_index_file(): p = subprocess.Popen(cmd, stdin=subprocess.PIPE) for line in input_lines: p.stdin.write(to_bytes('%s\0' % line)) p.stdin.close() if p.wait() != 0: die('`%s` failed' % ' '.join(cmd)) tree_id = run('git', 'write-tree') return tree_id def clang_format_to_blob(filename, line_ranges, revision=None, binary='clang-format', style=None, env=None): """Run clang-format on the given file and save the result to a git blob. Runs on the file in `revision` if not None, or on the file in the working directory if `revision` is None. Revision can be set to an empty string to run clang-format on the file in the index. Returns the object ID (SHA-1) of the created blob.""" clang_format_cmd = [binary] if style: clang_format_cmd.extend(['-style='+style]) clang_format_cmd.extend([ '-lines=%s:%s' % (start_line, start_line+line_count-1) for start_line, line_count in line_ranges]) if revision is not None: clang_format_cmd.extend(['-assume-filename='+filename]) git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)] git_show = subprocess.Popen(git_show_cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE) git_show.stdin.close() clang_format_stdin = git_show.stdout else: clang_format_cmd.extend([filename]) git_show = None clang_format_stdin = subprocess.PIPE try: clang_format = subprocess.Popen(clang_format_cmd, stdin=clang_format_stdin, stdout=subprocess.PIPE) if clang_format_stdin == subprocess.PIPE: clang_format_stdin = clang_format.stdin except OSError as e: if e.errno == errno.ENOENT: die('cannot find executable "%s"' % binary) else: raise clang_format_stdin.close() hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin'] hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout, stdout=subprocess.PIPE) clang_format.stdout.close() stdout = hash_object.communicate()[0] if hash_object.returncode != 0: die('`%s` failed' % ' '.join(hash_object_cmd)) if clang_format.wait() != 0: die('`%s` failed' % ' '.join(clang_format_cmd)) if git_show and git_show.wait() != 0: die('`%s` failed' % ' '.join(git_show_cmd)) return convert_string(stdout).rstrip('\r\n') @contextlib.contextmanager def temporary_index_file(tree=None): """Context manager for setting GIT_INDEX_FILE to a temporary file and deleting the file afterward.""" index_path = create_temporary_index(tree) old_index_path = os.environ.get('GIT_INDEX_FILE') os.environ['GIT_INDEX_FILE'] = index_path try: yield finally: if old_index_path is None: del os.environ['GIT_INDEX_FILE'] else: os.environ['GIT_INDEX_FILE'] = old_index_path os.remove(index_path) def create_temporary_index(tree=None): """Create a temporary index file and return the created file's path. If `tree` is not None, use that as the tree to read in. Otherwise, an empty index is created.""" gitdir = run('git', 'rev-parse', '--git-dir') path = os.path.join(gitdir, temp_index_basename) if tree is None: tree = '--empty' run('git', 'read-tree', '--index-output='+path, tree) return path def print_diff(old_tree, new_tree): """Print the diff between the two trees to stdout.""" # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output # is expected to be viewed by the user, and only the former does nice things # like color and pagination. # # We also only print modified files since `new_tree` only contains the files # that were modified, so unmodified files would show as deleted without the # filter. return subprocess.run(['git', 'diff', '--diff-filter=M', '--exit-code', old_tree, new_tree]).returncode def print_diffstat(old_tree, new_tree): """Print the diffstat between the two trees to stdout.""" # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output # is expected to be viewed by the user, and only the former does nice things # like color and pagination. # # We also only print modified files since `new_tree` only contains the files # that were modified, so unmodified files would show as deleted without the # filter. return subprocess.run(['git', 'diff', '--diff-filter=M', '--exit-code', '--stat', old_tree, new_tree]).returncode def apply_changes(old_tree, new_tree, force=False, patch_mode=False): """Apply the changes in `new_tree` to the working directory. Bails if there are local changes in those files and not `force`. If `patch_mode`, runs `git checkout --patch` to select hunks interactively.""" changed_files = run('git', 'diff-tree', '--diff-filter=M', '-r', '-z', '--name-only', old_tree, new_tree).rstrip('\0').split('\0') if not force: unstaged_files = run('git', 'diff-files', '--name-status', *changed_files) if unstaged_files: print('The following files would be modified but ' 'have unstaged changes:', file=sys.stderr) print(unstaged_files, file=sys.stderr) print('Please commit, stage, or stash them first.', file=sys.stderr) sys.exit(2) if patch_mode: # In patch mode, we could just as well create an index from the new tree # and checkout from that, but then the user will be presented with a # message saying "Discard ... from worktree". Instead, we use the old # tree as the index and checkout from new_tree, which gives the slightly # better message, "Apply ... to index and worktree". This is not quite # right, since it won't be applied to the user's index, but oh well. with temporary_index_file(old_tree): subprocess.run(['git', 'checkout', '--patch', new_tree], check=True) index_tree = old_tree else: with temporary_index_file(new_tree): run('git', 'checkout-index', '-f', '--', *changed_files) return changed_files def run(*args, **kwargs): stdin = kwargs.pop('stdin', '') verbose = kwargs.pop('verbose', True) strip = kwargs.pop('strip', True) for name in kwargs: raise TypeError("run() got an unexpected keyword argument '%s'" % name) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate(input=stdin) stdout = convert_string(stdout) stderr = convert_string(stderr) if p.returncode == 0: if stderr: if verbose: print('`%s` printed to stderr:' % ' '.join(args), file=sys.stderr) print(stderr.rstrip(), file=sys.stderr) if strip: stdout = stdout.rstrip('\r\n') return stdout if verbose: print('`%s` returned %s' % (' '.join(args), p.returncode), file=sys.stderr) if stderr: print(stderr.rstrip(), file=sys.stderr) sys.exit(2) def die(message): print('error:', message, file=sys.stderr) sys.exit(2) def to_bytes(str_input): # Encode to UTF-8 to get binary data. if isinstance(str_input, bytes): return str_input return str_input.encode('utf-8') def to_string(bytes_input): if isinstance(bytes_input, str): return bytes_input return bytes_input.encode('utf-8') def convert_string(bytes_input): try: return to_string(bytes_input.decode('utf-8')) except AttributeError: # 'str' object has no attribute 'decode'. return str(bytes_input) except UnicodeError: return str(bytes_input) if __name__ == '__main__': sys.exit(main()) qbs-src-3.3.1/scripts/print-cores.sh0000755000175100017510000000040315232633614016773 0ustar runnerrunner#!/bin/bash for file in $(find /cores -maxdepth 1 -name 'core.*' -print); do echo "================================ $file ================================" gdb -ex 'thread apply all bt' -ex 'quit' ./release/install-root/usr/local/bin/qbs $file done; qbs-src-3.3.1/scripts/test-qt-for-android.sh0000755000175100017510000000671115232633614020341 0ustar runnerrunner#!/usr/bin/env bash set -eu ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# export PATH="$1:$PATH" export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" # # These are set outside of this script, for instance in the Docker image # QT_INSTALL_DIR=/opt/Qt/${QT_VERSION} echo "Android SDK installed at ${ANDROID_SDK_ROOT}" echo "Android NDK installed at ${ANDROID_NDK_ROOT}" echo "Qt installed at ${QT_INSTALL_DIR}" # Cleaning profiles qbs config --unset profiles.qbs_autotests-android qbs config --unset profiles.qbs_autotests-android-qt # Setting auto test profiles qbs setup-android --ndk-dir ${ANDROID_NDK_ROOT} --sdk-dir ${ANDROID_SDK_ROOT} qbs_autotests-android qbs setup-android --ndk-dir ${ANDROID_NDK_ROOT} --sdk-dir ${ANDROID_SDK_ROOT} --qt-dir ${QT_INSTALL_DIR} qbs_autotests-android-qt export QBS_AUTOTEST_PROFILE=qbs_autotests-android export QBS_AUTOTEST_ALWAYS_LOG_STDERR=true export QTEST_FUNCTION_TIMEOUT=9000000 if [ ! "${QT_VERSION}" \< "5.14.0" ] && [ "${QT_VERSION}" \< "6.0.0" ]; then echo "Using multi-arch data sets for qml tests (only for qt version >= 5.14 and < 6.0.0) with all architectures" qbs config --list tst_blackbox-android fi; if [ ! "${QT_VERSION}" \< "6.3.0" ]; then echo "Using multi-arch data sets for qml tests (only for qt version >= 6.3.0) with all architectures" qbs config --list tst_blackbox-android fi; echo "Using single-arch (armv7a) data sets for qml tests" qbs config --unset profiles.qbs_autotests-android-qt.qbs.architectures qbs config profiles.qbs_autotests-android-qt.qbs.architecture armv7a qbs config --list tst_blackbox-android qbs-src-3.3.1/scripts/test-qt.sh0000755000175100017510000000433615232633614016140 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2021 Ivan Komissarov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu # # Qbs is built with the address sanitizer enabled. # Suppress findings in some parts of Qbs / dependencies. # export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" export PATH="$1:$PATH" export QBS_AUTOTEST_PROFILE=${QBS_AUTOTEST_PROFILE:-qt} tst_blackbox-qt qbs-src-3.3.1/scripts/update-dmgbuild.sh0000755000175100017510000000441715232633614017606 0ustar runnerrunner#!/bin/bash set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# python_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../src/3rdparty/python" repos=(biplist.git@v1.0.3 dmgbuild.git@v1.3.2 ds_store@v1.1.2 mac_alias.git@v2.0.7) for repo in "${repos[@]}" ; do pip install -U --isolated "--prefix=$python_dir" --no-binary :all: --no-compile --no-deps \ "git+git://github.com/qbs/$repo" done rm "$python_dir/lib/python2.7/site-packages/dmgbuild/resources/"*.tiff qbs-src-3.3.1/scripts/install-dm.sh0000644000175100017510000001042315232633614016572 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2022 Denis Shienkov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu function show_help() { cat < Root directory where to install the components. Maps to c:/dm on Windows by default. --version The desired toolchain version. Currently supported only 8.57 version. EOF } VERSION="8.57" INSTALL_DIR="/c/dm" while [ $# -gt 0 ]; do case "$1" in --directory|-d) INSTALL_DIR="$2" shift ;; --version) VERSION="$2" shift ;; --help|-h) show_help exit 0 ;; *) ;; esac shift done if [ -z "${INSTALL_DIR}" ]; then echo "No --directory specified or auto-detection failed." >&2 exit 1 fi if [ -z "${VERSION}" ]; then echo "No --version specified." >&2 exit 1 fi DOWNLOAD_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'dm-tmp'` DM_URL="http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm${VERSION//./}c.zip" UTILS_URL="http://ftp.digitalmars.com/bup.zip" DOS_LIBS_URL="http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm850dos.zip" DOSX_LIBS_URL="http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm831x.zip" DM_ZIP="${DOWNLOAD_DIR}/dm.zip" UTILS_ZIP="${DOWNLOAD_DIR}/utils.zip" DOS_LIBS_ZIP="${DOWNLOAD_DIR}/doslibs.zip" DOSX_LIBS_ZIP="${DOWNLOAD_DIR}/dosxlibs.zip" echo "Downloading compiler from ${DM_URL}..." >&2 curl --progress-bar -L -o ${DM_ZIP} ${DM_URL} >&2 echo "Downloading utils from ${UTILS_URL}..." >&2 curl --progress-bar -L -o ${UTILS_ZIP} ${UTILS_URL} >&2 echo "Downloading DOS libs from ${DOS_LIBS_URL}..." >&2 curl --progress-bar -L -o ${DOS_LIBS_ZIP} ${DOS_LIBS_URL} >&2 echo "Downloading DOSX libs from ${DOSX_LIBS_URL}..." >&2 curl --progress-bar -L -o ${DOSX_LIBS_ZIP} ${DOSX_LIBS_URL} >&2 echo "Unpacking compiler to ${INSTALL_DIR}..." >&2 7z x -y -o${INSTALL_DIR} ${DM_ZIP} >/dev/null 2>&1 echo "Unpacking utils to ${INSTALL_DIR}..." >&2 7z x -y -o${INSTALL_DIR} ${UTILS_ZIP} >/dev/null 2>&1 echo "Unpacking DOS libs to ${INSTALL_DIR}..." >&2 7z x -y -o${INSTALL_DIR} ${DOS_LIBS_ZIP} >/dev/null 2>&1 echo "Unpacking DOSX libs to ${INSTALL_DIR}..." >&2 7z x -y -o${INSTALL_DIR} ${DOSX_LIBS_ZIP} >/dev/null 2>&1 echo "${INSTALL_DIR}/dm/bin" rm -f ${DM_ZIP} rm -f ${UTILS_ZIP} rm -f ${DOS_LIBS_ZIP} rm -f ${DOSX_LIBS_ZIP} qbs-src-3.3.1/scripts/cpu-count.sh0000755000175100017510000000414415232633614016451 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2020 Ivan Komissarov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# NPROC=`which nproc` SYSCTL=`which sysctl` CPU_COUNT=2 if [ ! -z "$NPROC" ]; then # Linux CPU_COUNT=`$NPROC --all` elif [ ! -z "$SYSCTL" ]; then # macOS CPU_COUNT=`$SYSCTL -n hw.physicalcpu_max` fi echo $CPU_COUNT qbs-src-3.3.1/scripts/test-qbs.sh0000755000175100017510000000444615232633614016303 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2020 Ivan Komissarov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu -o pipefail # # Qbs is built with the address sanitizer enabled. # Suppress findings in some parts of Qbs / dependencies. # export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" export PATH="$1:$PATH" export QBS_AUTOTEST_PROFILE=${QBS_AUTOTEST_PROFILE:-qt} echo "Running Qbs tests." find $1 -name "tst*" | xargs -I{} -n1 bash -c "{}" qbs-src-3.3.1/scripts/setup-conan-profiles.sh0000755000175100017510000000557615232633614020623 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com). ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH=x64 ;; arm64) ARCH=arm64 ;; esac case "$OSTYPE" in *darwin*) HOST_OS=mac_$ARCH TOOLCHAIN=clang_64 ;; msys|cygwin) HOST_OS=win_x64 TOOLCHAIN=msvc_64 ;; *) HOST_OS= ;; esac while [ $# -gt 0 ]; do case "$1" in --host) HOST_OS="$2" shift ;; --toolchain) TOOLCHAIN=$(echo $2 | tr '[A-Z]' '[a-z]') shift ;; esac shift done if [ -z "${HOST_OS}" ]; then echo "No --host specified or auto-detection failed." >&2 exit 1 fi if [ -z "${TOOLCHAIN}" ]; then echo "No --toolchain specified or auto-detection failed." >&2 exit 1 fi echo $ARCH echo $HOST_OS echo $TOOLCHAIN mkdir -p "${HOME}/.conan2/profiles" SCRIPT_DIR=$( cd "$(dirname "$0")" ; pwd -P ) cp ${SCRIPT_DIR}/conan-profiles/${HOST_OS}/${TOOLCHAIN}/* "${HOME}/.conan2/profiles" qbs-src-3.3.1/scripts/test-wasm.sh0000755000175100017510000000467015232633614016464 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2024 Ivan Komissarov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu -o pipefail export PATH="$1:$PATH" SCRIPT_DIR=$( cd "$(dirname "$0")" ; pwd -P ) qbs config --unset profiles.qbs_autotests_wasm qbs config --unset profiles.qbs_autotests_wasm_qt export QBS_AUTOTEST_PROFILE=qbs_autotests_wasm_qt EMCC_PATH=${EMCC_PATH:-$(which emcc)} QMAKE_PATH=${QMAKE_PATH:-$(which qmake)} qbs setup-toolchains --type emscripten ${EMCC_PATH} qbs_autotests_wasm qbs setup-qt ${QMAKE_PATH} qbs_autotests_wasm_qt qbs config profiles.qbs_autotests_wasm_qt.baseProfile qbs_autotests_wasm qbs config --list ${SCRIPT_DIR}/test-qbs.sh $1 qbs-src-3.3.1/scripts/update-xcspecs.sh0000755000175100017510000000507315232633614017466 0ustar runnerrunner#!/bin/bash set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# # Update build specs from Xcode - this script should be run when new Xcode releases are made. specs_dir="$(xcrun --sdk macosx --show-sdk-platform-path)/Developer/Library/Xcode/Specifications" specs_out_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../share/qbs/modules/bundle" spec_files=("MacOSX Package Types.xcspec" "MacOSX Product Types.xcspec") for spec_file in "${spec_files[@]}" ; do printf "%s\\n" "$(plutil -convert json -r -o - "$specs_dir/$spec_file")" > \ "$specs_out_dir/${spec_file// /-}" done xcode_version="$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' \ "$(xcode-select --print-path)/../Info.plist")" echo "Updated build specs from Xcode $xcode_version" qbs-src-3.3.1/scripts/scripts.qbs0000644000175100017510000000013415232633614016366 0ustar runnerrunnerProduct { name: "qbs dev scripts" files: [ "*.bat", "*.sh", ] } qbs-src-3.3.1/scripts/build-qbs-with-cmake.sh0000755000175100017510000000736415232633614020454 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com). ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu # # It might be desired to keep settings for Qbs testing # in a separate folder. # export QBS_AUTOTEST_SETTINGS_DIR="${QBS_AUTOTEST_SETTINGS_DIR:-/tmp/qbs-settings}" BUILD_OPTIONS="\ -DWITH_UNIT_TESTS=1 \ -DQBS_INSTALL_HTML_DOCS=1 \ -DQBS_INSTALL_QCH_DOCS=1 \ ${BUILD_OPTIONS:-} \ " EXE_SUFFIX="" if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then EXE_SUFFIX=".exe" else BUILD_OPTIONS="\ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ ${BUILD_OPTIONS} \ " fi QMAKE_PATH="${QMAKE_PATH:-$(which qmake)${EXE_SUFFIX}}" QT_DIR=$(dirname ${QMAKE_PATH})/../ # Use shadow build mkdir -p build pushd build # # Build all default products of Qbs # cmake -GNinja -DQt5_DIR=${QT_DIR}/lib/cmake/Qt5/ ${BUILD_OPTIONS} .. cmake --build . cmake --install . --prefix "install-root" WITH_TESTS=${WITH_TESTS:-1} if [ "$WITH_TESTS" -eq 0 ]; then exit 0 fi QBS_AUTOTEST_PROFILE="${QBS_AUTOTEST_PROFILE:-}" # # Set up profiles for the freshly built Qbs if not # explicitly specified otherwise # if [[ "${QBS_AUTOTEST_PROFILE}" == "" ]]; then export QBS_AUTOTEST_PROFILE=autotestprofile RUN_OPTIONS="\ --settings-dir ${QBS_AUTOTEST_SETTINGS_DIR} \ " ./bin/qbs setup-toolchains \ ${RUN_OPTIONS} \ --detect ./bin/qbs setup-qt \ ${RUN_OPTIONS} \ "${QMAKE_PATH}" ${QBS_AUTOTEST_PROFILE} ./bin/qbs config \ ${RUN_OPTIONS} \ ${QBS_AUTOTEST_PROFILE}.baseProfile gcc fi # # Run all autotests with QBS_AUTOTEST_PROFILE. Some test cases might run for # over 10 minutes. Output an empty line every 9:50 minutes to prevent a 10min # timeout on Travis CI. # (while true; do echo "" && sleep 590; done) & trap "kill $!; wait $! 2>/dev/null || true; killall sleep || true" EXIT ctest -j $(nproc --all) --output-on-failure qbs-src-3.3.1/scripts/make-release-archives.sh0000755000175100017510000000424015232633614020666 0ustar runnerrunner#!/bin/sh set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# test $# -eq 1 || { echo "Usage: $(basename "$0") " >&2; exit 1; } tag=${1} version=${tag#v} dir_name=qbs-src-${version} git archive --format=tar.gz "--prefix=${dir_name}/" -o "dist/${dir_name}.tar.gz" "${tag}" git archive --format=zip "--prefix=${dir_name}/" -o "dist/${dir_name}.zip" "${tag}" qbs-src-3.3.1/scripts/make-release-archives.bat0000644000175100017510000000670015232633614021022 0ustar runnerrunner@echo off REM Copyright (C) 2017 The Qt Company Ltd. REM Contact: https://www.qt.io/licensing/ REM REM This file is part of Qbs. REM REM $QT_BEGIN_LICENSE:LGPL$ REM Commercial License Usage REM Licensees holding valid commercial Qt licenses may use this file in REM accordance with the commercial license agreement provided with the REM Software or, alternatively, in accordance with the terms contained in REM a written agreement between you and The Qt Company. For licensing terms REM and conditions see https://www.qt.io/terms-conditions. For further REM information use the contact form at https://www.qt.io/contact-us. REM REM GNU Lesser General Public License Usage REM Alternatively, this file may be used under the terms of the GNU Lesser REM General Public License version 3 as published by the Free Software REM Foundation and appearing in the file LICENSE.LGPL3 included in the REM packaging of this file. Please review the following information to REM ensure the GNU Lesser General Public License version 3 requirements REM will be met: https://www.gnu.org/licenses/lgpl-3.0.html. REM REM GNU General Public License Usage REM Alternatively, this file may be used under the terms of the GNU REM General Public License version 2.0 or (at your option) the GNU General REM Public license version 3 or any later version approved by the KDE Free REM Qt Foundation. The licenses are as published by the Free Software REM Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 REM included in the packaging of this file. Please review the following REM information to ensure the GNU General Public License requirements will REM be met: https://www.gnu.org/licenses/gpl-2.0.html and REM https://www.gnu.org/licenses/gpl-3.0.html. REM REM $QT_END_LICENSE$ setlocal enabledelayedexpansion || exit /b if not exist VERSION ( echo This script must be run from the qbs source directory 1>&2 && exit /b 1 ) for /f %%j in (VERSION) do ( set "version=!version!%%j," ) set "version=%version:~0,-1%" set builddir=%TEMP%\qbs-release-%version% if exist "%builddir%" ( del /s /q "%builddir%" || exit /b ) qbs setup-toolchains --settings-dir "%builddir%\.settings" --detect || exit /b if exist "%QTDIR%" ( qbs setup-qt --settings-dir "%builddir%\.settings"^ "%QTDIR%\bin\qmake.exe" qt || exit /b ) else ( echo QTDIR environment variable not set or does not exist: %QTDIR% exit /b 1 ) if exist "%QTDIR64%" ( qbs setup-qt --settings-dir "%builddir%\.settings"^ "%QTDIR64%\bin\qmake.exe" qt64 || exit /b ) else ( echo QTDIR64 environment variable not set or does not exist: %QTDIR64% exit /b 1 ) REM Work around QBS-1142, where symlinks to UNC named paths aren't resolved REM properly, for example if this command is being run in a Docker container REM where the current directory is a symlink subst Q: "%CD%" && Q: qbs build --settings-dir "%builddir%\.settings"^ -f qbs.qbs -d "%builddir%\build"^ -p dist qbs.buildVariant:release project.withDocumentation:false products.qbs_archive.includeTopLevelDir:true^ modules.qbsbuildconfig.enableBundledQt:true^ config:release "qbs.installRoot:%builddir%\qbs-windows-x86-%version%" profile:qt^ config:release-64 "qbs.installRoot:%builddir%\qbs-windows-x86_64-%version%" profile:qt64 || exit /b copy /y "%builddir%\build\release\qbs.%version%.nupkg" dist || exit /b copy /y "%builddir%\build\release\qbs-windows-x86-%version%.zip" dist || exit /b copy /y "%builddir%\build\release-64\qbs-windows-x86_64-%version%.zip" dist || exit /b qbs-src-3.3.1/scripts/test-for-android.sh0000755000175100017510000000507315232633614017717 0ustar runnerrunner#!/usr/bin/env bash set -eu ############################################################################# ## ## Copyright (C) 2019 Richard Weickelt. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# export PATH="$1:$PATH" export LSAN_OPTIONS="suppressions=$( cd "$(dirname "$0")" ; pwd -P )/address-sanitizer-suppressions.txt:print_suppressions=0" # # These are set outside of this script, for instance in the Docker image # echo "Android SDK installed at ${ANDROID_SDK_ROOT}" echo "Android NDK installed at ${ANDROID_NDK_ROOT}" # Cleaning profiles qbs config --unset profiles.qbs_autotests-android # Setting auto test profiles qbs setup-android --ndk-dir ${ANDROID_NDK_ROOT} --sdk-dir ${ANDROID_HOME} qbs_autotests-android export QBS_AUTOTEST_PROFILE=qbs_autotests-android export QBS_AUTOTEST_ALWAYS_LOG_STDERR=true export QTEST_FUNCTION_TIMEOUT=9000000 qbs config --list tst_blackbox-android qbs-src-3.3.1/scripts/address-sanitizer-suppressions.txt0000644000175100017510000000012415232633614023136 0ustar runnerrunnerleak:QThread::QThread leak:QThreadPrivate::QThreadPrivate leak:QArrayData::allocate qbs-src-3.3.1/scripts/install-ow.sh0000755000175100017510000000756615232633614016640 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2022 Denis Shienkov ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# set -eu set -o pipefail function show_help() { cat < Root directory where to install the components. Maps to c:/watcom on Windows, /opt/watcom on Linux by default. --version The desired toolchain version. Currently supported only 2.0 version. EOF } VERSION=2.0 INSTALL_DIR= BIN_DIR= if [[ "$OSTYPE" =~ "linux" ]]; then INSTALL_DIR="/opt/watcom" if [[ "$HOSTTYPE" == "x86_64" ]]; then BIN_DIR="binl64" elif [[ "$HOSTTYPE" == "x86" ]]; then BIN_DIR="binl" fi elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then INSTALL_DIR="/c/watcom" if [[ "$HOSTTYPE" == "x86_64" ]]; then BIN_DIR="binnt64" elif [[ "$HOSTTYPE" == "x86" ]]; then BIN_DIR="binnt" fi fi while [ $# -gt 0 ]; do case "$1" in --directory|-d) INSTALL_DIR="$2" shift ;; --version) VERSION="$2" shift ;; --help|-h) show_help exit 0 ;; *) ;; esac shift done if [ -z "${INSTALL_DIR}" ]; then echo "No --directory specified or auto-detection failed." >&2 exit 1 fi if [ -z "${VERSION}" ]; then echo "No --version specified." >&2 exit 1 fi DOWNLOAD_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'ow-tmp'` VERSION_MAJOR=`echo $VERSION | cut -d. -f1` VERSION_MINOR=`echo $VERSION | cut -d. -f2` OW_URL="https://github.com/open-watcom/open-watcom-v${VERSION_MAJOR}/releases/download/Current-build/ow-snapshot.tar.xz" OW_TAR="${DOWNLOAD_DIR}/ow.tar.xz" echo "Downloading compiler from ${OW_URL}..." >&2 curl --progress-bar -L -o ${OW_TAR} ${OW_URL} >&2 echo "Unpacking compiler to ${INSTALL_DIR}..." >&2 7z x "${OW_TAR}" -so | 7z x -aoa -si -ttar -o"${INSTALL_DIR}" >/dev/null 2>&1 echo "${INSTALL_DIR}/${BIN_DIR}" rm -f ${OW_TAR} qbs-src-3.3.1/scripts/thread-sanitizer-suppressions.txt0000644000175100017510000000003315232633614022757 0ustar runnerrunnercalled_from_lib:libtsan.so qbs-src-3.3.1/scripts/run-analyzer.sh0000755000175100017510000000766315232633614017174 0ustar runnerrunner#!/usr/bin/env bash ############################################################################# ## ## Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:-""} # on Debian, it might be necessary to setup which version of clang-tidy and run-clang-tidy.py # is desired: # update-alternatives --install /usr/bin/run-clang-tidy.py run-clang-tidy.py /usr/bin/run-clang-tidy-4.0.py 1 CLANG_TIDY=`which clang-tidy` RUN_CLANG_TIDY=`which run-clang-tidy` if [ -z "$RUN_CLANG_TIDY" ] || [ -z "$CLANG_TIDY" ]; then if [ ! -z "$LLVM_INSTALL_DIR" ]; then CLANG_TIDY="$LLVM_INSTALL_DIR/bin/clang-tidy" RUN_CLANG_TIDY="$LLVM_INSTALL_DIR/bin/run-clang-tidy" else echo "Can't find clang-tidy and/or run-clang-tidy.py in PATH, try setting LLVM_INSTALL_DIR" exit 1 fi fi SCRIPT_DIR=$(dirname "$0") CPU_COUNT=$("${SCRIPT_DIR}/cpu-count.sh") BUILD_OPTIONS="\ ${QBS_BUILD_PROFILE:+profile:${QBS_BUILD_PROFILE}} \ modules.cpp.treatWarningsAsErrors:true \ modules.qbs.buildVariant:release \ project.withTests:false \ ${BUILD_OPTIONS} \ config:analyzer " QBS_SRC_DIR=${QBS_SRC_DIR:-`pwd`} if [ ! -f "$QBS_SRC_DIR/qbs.qbs" ]; then echo "Can't find qbs.qbs in $QBS_SRC_DIR, try setting QBS_SRC_DIR" exit 1 fi set -e set -o pipefail qbs resolve -f "$QBS_SRC_DIR/qbs.qbs" $BUILD_OPTIONS qbs build -f "$QBS_SRC_DIR/qbs.qbs" $BUILD_OPTIONS qbs generate -g clangdb -f "$QBS_SRC_DIR/qbs.qbs" $BUILD_OPTIONS SCRIPT=" import json import os import sys dbFile = sys.argv[1] blacklist = ['qmljsgrammar.cpp', 'qmljsparser.cpp'] seenFiles = set() patched_db = [] with open(dbFile, 'r') as f: db = json.load(f) for item in db: file = item['file'] if (os.path.basename(file) not in blacklist) and (file not in seenFiles): seenFiles.add(file) patched_db.append(item) with open(dbFile, 'w') as f: f.write(json.dumps(patched_db, indent=2)) " python3 -c "${SCRIPT}" analyzer/compile_commands.json RUN_CLANG_TIDY+=" -p analyzer -clang-tidy-binary ${CLANG_TIDY} -j ${CPU_COUNT} -header-filter=\".*qbs.*\.h$\" -quiet" ${RUN_CLANG_TIDY} 2>/dev/null | tee results.txt echo "$(grep -c 'warning:' results.txt) warnings in total" qbs-src-3.3.1/src/0000755000175100017510000000000015232633614013272 5ustar runnerrunnerqbs-src-3.3.1/src/libexec/0000755000175100017510000000000015232633614014705 5ustar runnerrunnerqbs-src-3.3.1/src/libexec/libexec.qbs0000644000175100017510000000013315232633614017024 0ustar runnerrunnerProject { references: [ "qbs_processlauncher/qbs_processlauncher.qbs", ] } qbs-src-3.3.1/src/libexec/CMakeLists.txt0000644000175100017510000000004615232633614017445 0ustar runnerrunneradd_subdirectory(qbs_processlauncher) qbs-src-3.3.1/src/libexec/qbs_processlauncher/0000755000175100017510000000000015232633614020752 5ustar runnerrunnerqbs-src-3.3.1/src/libexec/qbs_processlauncher/qbs_processlauncher.qbs0000644000175100017510000000172515232633614025533 0ustar runnerrunnerimport qbs.FileInfo QbsProduct { type: "application" name: "qbs_processlauncher" consoleApplication: true Depends { name: "Qt.network" } cpp.includePaths: base.concat(pathToProtocolSources) files: [ "launcherlogging.cpp", "launcherlogging.h", "launchersockethandler.cpp", "launchersockethandler.h", "processlauncher-main.cpp", ] property string pathToProtocolSources: sourceDirectory + "/../../lib/corelib/tools" Group { name: "protocol sources" prefix: pathToProtocolSources + '/' files: [ "launcherpackets.cpp", "launcherpackets.h", ] } Group { fileTagsFilter: product.type .concat(qbs.buildVariant === "debug" ? ["debuginfo_app"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.libexecInstallDir } qbs-src-3.3.1/src/libexec/qbs_processlauncher/launcherlogging.h0000644000175100017510000000450115232633614024273 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUCHERLOGGING_H #define QBS_LAUCHERLOGGING_H #include #include namespace qbs { namespace Internal { Q_DECLARE_LOGGING_CATEGORY(launcherLog) template void logDebug(const T &msg) { qCDebug(launcherLog) << msg; } template void logWarn(const T &msg) { qCWarning(launcherLog) << msg; } template void logError(const T &msg) { qCCritical(launcherLog) << msg; } } } #endif // Include guard qbs-src-3.3.1/src/libexec/qbs_processlauncher/CMakeLists.txt0000644000175100017510000000136315232633614023515 0ustar runnerrunnerset(SOURCES launcherlogging.cpp launcherlogging.h launchersockethandler.cpp launchersockethandler.h processlauncher-main.cpp ) set(PATH_TO_PROTOCOL_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../lib/corelib/tools") set(PROTOCOL_SOURCES launcherpackets.cpp launcherpackets.h ) list_transform_prepend(PROTOCOL_SOURCES ${PATH_TO_PROTOCOL_SOURCES}/) add_qbs_app(qbs_processlauncher DESTINATION ${QBS_LIBEXEC_INSTALL_DIR} DEPENDS Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network INCLUDES ${PATH_TO_PROTOCOL_SOURCES} SOURCES ${SOURCES} ${PROTOCOL_SOURCES} ) set_target_properties(qbs_processlauncher PROPERTIES BUILD_RPATH "${QBS_LIBEXEC_RPATH}" INSTALL_RPATH "${QBS_LIBEXEC_RPATH}" ) qbs-src-3.3.1/src/libexec/qbs_processlauncher/processlauncher-main.cpp0000644000175100017510000000520015232633614025575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherlogging.h" #include "launchersockethandler.h" #include #include #ifdef Q_OS_WIN #include BOOL WINAPI consoleCtrlHandler(DWORD) { // Ignore Ctrl-C / Ctrl-Break. Qbs will tell us to exit gracefully. return TRUE; } #endif int main(int argc, char *argv[]) { #ifdef Q_OS_WIN SetConsoleCtrlHandler(consoleCtrlHandler, TRUE); #endif QCoreApplication app(argc, argv); if (app.arguments().size() != 2) { qbs::Internal::logError("Need exactly one argument (path to socket)"); return 1; } qbs::Internal::LauncherSocketHandler launcher(app.arguments().constLast()); QTimer::singleShot(0, &launcher, &qbs::Internal::LauncherSocketHandler::start); return app.exec(); } qbs-src-3.3.1/src/libexec/qbs_processlauncher/launchersockethandler.h0000644000175100017510000000573215232633614025502 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUNCHERSOCKETHANDLER_H #define QBS_LAUNCHERSOCKETHANDLER_H #include #include #include #include QT_BEGIN_NAMESPACE class QLocalSocket; QT_END_NAMESPACE namespace qbs { namespace Internal { class Process; class LauncherSocketHandler : public QObject { Q_OBJECT public: explicit LauncherSocketHandler(QString socketPath, QObject *parent = nullptr); ~LauncherSocketHandler() override; void start(); private: void handleSocketData(); void handleSocketError(); void handleSocketClosed(); void handleProcessError(); void handleProcessFinished(); void handleStopFailure(); void handleStartPacket(); void handleStopPacket(); void handleShutdownPacket(); void sendPacket(const LauncherPacket &packet); Process *setupProcess(quintptr token); Process *senderProcess() const; const QString m_serverPath; QLocalSocket * const m_socket; PacketParser m_packetParser; QHash m_processes; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-3.3.1/src/libexec/qbs_processlauncher/launchersockethandler.cpp0000644000175100017510000002246215232633614026034 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launchersockethandler.h" #include "launcherlogging.h" #include #include #include #include namespace qbs { namespace Internal { class Process : public QProcess { Q_OBJECT public: Process(quintptr token, QObject *parent = nullptr) : QProcess(parent), m_token(token), m_stopTimer(new QTimer(this)) { m_stopTimer->setSingleShot(true); connect(m_stopTimer, &QTimer::timeout, this, &Process::cancel); } void cancel() { switch (m_stopState) { case StopState::Inactive: m_stopState = StopState::Terminating; m_stopTimer->start(3000); terminate(); break; case StopState::Terminating: m_stopState = StopState::Killing; m_stopTimer->start(3000); kill(); break; case StopState::Killing: m_stopState = StopState::Inactive; emit failedToStop(); break; } } void stopStopProcedure() { m_stopState = StopState::Inactive; m_stopTimer->stop(); } quintptr token() const { return m_token; } signals: void failedToStop(); private: const quintptr m_token; QTimer * const m_stopTimer; enum class StopState { Inactive, Terminating, Killing } m_stopState = StopState::Inactive; }; LauncherSocketHandler::LauncherSocketHandler(QString serverPath, QObject *parent) : QObject(parent), m_serverPath(std::move(serverPath)), m_socket(new QLocalSocket(this)) { m_packetParser.setDevice(m_socket); } LauncherSocketHandler::~LauncherSocketHandler() { m_socket->disconnect(); if (m_socket->state() != QLocalSocket::UnconnectedState) { logWarn("socket handler destroyed while connection was active"); m_socket->close(); } for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) it.value()->disconnect(); } void LauncherSocketHandler::start() { connect(m_socket, &QLocalSocket::disconnected, this, &LauncherSocketHandler::handleSocketClosed); connect(m_socket, &QLocalSocket::readyRead, this, &LauncherSocketHandler::handleSocketData); connect(m_socket, &QLocalSocket::errorOccurred, this, &LauncherSocketHandler::handleSocketError); m_socket->connectToServer(m_serverPath); } void LauncherSocketHandler::handleSocketData() { try { if (!m_packetParser.parse()) return; } catch (const PacketParser::InvalidPacketSizeException &e) { logWarn(QStringLiteral("Internal protocol error: invalid packet size %1.") .arg(e.size)); return; } switch (m_packetParser.type()) { case LauncherPacketType::StartProcess: handleStartPacket(); break; case LauncherPacketType::StopProcess: handleStopPacket(); break; case LauncherPacketType::Shutdown: handleShutdownPacket(); return; default: logWarn(QStringLiteral("Internal protocol error: invalid packet type %1.") .arg(static_cast(m_packetParser.type()))); return; } handleSocketData(); } void LauncherSocketHandler::handleSocketError() { if (m_socket->error() != QLocalSocket::PeerClosedError) { logError(QStringLiteral("socket error: %1").arg(m_socket->errorString())); m_socket->disconnect(); qApp->quit(); } } void LauncherSocketHandler::handleSocketClosed() { for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) { if (it.value()->state() != QProcess::NotRunning) { logWarn("client closed connection while process still running"); break; } } m_socket->disconnect(); qApp->quit(); } void LauncherSocketHandler::handleProcessError() { Process * proc = senderProcess(); if (proc->error() != QProcess::FailedToStart) return; proc->stopStopProcedure(); ProcessErrorPacket packet(proc->token()); packet.error = proc->error(); packet.errorString = proc->errorString(); sendPacket(packet); } void LauncherSocketHandler::handleProcessFinished() { Process * proc = senderProcess(); proc->stopStopProcedure(); ProcessFinishedPacket packet(proc->token()); packet.error = proc->error(); packet.errorString = proc->errorString(); packet.exitCode = proc->exitCode(); packet.exitStatus = proc->exitStatus(); packet.stdErr = proc->readAllStandardError(); packet.stdOut = proc->readAllStandardOutput(); sendPacket(packet); } void LauncherSocketHandler::handleStopFailure() { // Process did not react to a kill signal. Rare, but not unheard of. // Forget about the associated Process object and report process exit to the client. Process * proc = senderProcess(); proc->disconnect(); m_processes.remove(proc->token()); ProcessFinishedPacket packet(proc->token()); packet.error = QProcess::Crashed; packet.exitCode = -1; packet.exitStatus = QProcess::CrashExit; packet.stdErr = proc->readAllStandardError(); packet.stdOut = proc->readAllStandardOutput(); sendPacket(packet); } void LauncherSocketHandler::handleStartPacket() { Process *& process = m_processes[m_packetParser.token()]; if (!process) process = setupProcess(m_packetParser.token()); if (process->state() != QProcess::NotRunning) { logWarn("got start request while process was running"); return; } const auto packet = LauncherPacket::extractPacket( m_packetParser.token(), m_packetParser.packetData()); process->setEnvironment(packet.env); process->setWorkingDirectory(packet.workingDir); process->start(packet.command, packet.arguments); } void LauncherSocketHandler::handleStopPacket() { Process * const process = m_processes.value(m_packetParser.token()); if (!process) { logWarn("got stop request for unknown process"); return; } if (process->state() == QProcess::NotRunning) { // This can happen if the process finishes on its own at about the same time the client // sends the request. logDebug("got stop request when process was not running"); return; } process->cancel(); } void LauncherSocketHandler::handleShutdownPacket() { logDebug("got shutdown request, closing down"); for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) { it.value()->disconnect(); if (it.value()->state() != QProcess::NotRunning) { logWarn("got shutdown request while process was running"); it.value()->terminate(); } } m_socket->disconnect(); qApp->quit(); } void LauncherSocketHandler::sendPacket(const LauncherPacket &packet) { m_socket->write(packet.serialize()); } Process *LauncherSocketHandler::setupProcess(quintptr token) { const auto p = new Process(token, this); connect(p, &QProcess::errorOccurred, this, &LauncherSocketHandler::handleProcessError); connect(p, static_cast(&QProcess::finished), this, &LauncherSocketHandler::handleProcessFinished); connect(p, &Process::failedToStop, this, &LauncherSocketHandler::handleStopFailure); return p; } Process *LauncherSocketHandler::senderProcess() const { return static_cast(sender()); } } // namespace Internal } // namespace qbs #include qbs-src-3.3.1/src/libexec/qbs_processlauncher/launcherlogging.cpp0000644000175100017510000000374615232633614024640 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherlogging.h" namespace qbs { namespace Internal { Q_LOGGING_CATEGORY(launcherLog, "qbs.launcher", QtWarningMsg) } } qbs-src-3.3.1/src/plugins/0000755000175100017510000000000015232633614014753 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/CMakeLists.txt0000644000175100017510000000006615232633614017515 0ustar runnerrunneradd_subdirectory(generator) add_subdirectory(scanner) qbs-src-3.3.1/src/plugins/qbsplugin.qbs0000644000175100017510000000326615232633614017475 0ustar runnerrunnerimport qbs.FileInfo QbsProduct { property bool isForDarwin: qbs.targetOS.contains("darwin") property bool staticBuild: Qt.core.staticBuild || qbsbuildconfig.staticBuild Depends { name: "cpp" } Depends { name: "bundle"; condition: isForDarwin } Depends { name: "Qt.core" } Depends { name: "qbsbuildconfig" } Depends { name: "qbscore"; condition: !staticBuild } type: (staticBuild ? ["staticlibrary"] : [isForDarwin ? "loadablemodule" : "dynamiclibrary"]) .concat(["qbsplugin"]) Properties { condition: staticBuild cpp.defines: ["QBS_STATIC_LIB"] } cpp.includePaths: base.concat(["../../../lib/corelib"]) cpp.visibility: "minimal" Group { fileTagsFilter: [isForDarwin ? "loadablemodule" : "dynamiclibrary"] .concat(qbs.buildVariant === "debug" ? [isForDarwin ? "debuginfo_loadablemodule" : "debuginfo_dll"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.pluginsInstallDir Properties { condition: isForDarwin bundle.isBundle: false } Export { Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") cpp.linkerFlags: ["-u", "_qbs_static_plugin_register_" + name] } Properties { condition: qbs.toolchain.contains("gcc") cpp.linkerFlags: "--require-defined=qbs_static_plugin_register_" + name } Properties { condition: qbs.toolchain.contains("msvc") cpp.linkerFlags: "/INCLUDE:qbs_static_plugin_register_" + name } } } qbs-src-3.3.1/src/plugins/generator/0000755000175100017510000000000015232633614016741 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/graphviz/0000755000175100017510000000000015232633614020573 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/graphviz/graphviz.qbs0000644000175100017510000000041215232633614023131 0ustar runnerrunnerimport qbs import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "graphvizgenerator" files: [ "dotgraph.cpp", "dotgraph.h", "graphvizgenerator.cpp", "graphvizgenerator.h", "graphvizgeneratorplugin.cpp", ] } qbs-src-3.3.1/src/plugins/generator/graphviz/CMakeLists.txt0000644000175100017510000000026015232633614023331 0ustar runnerrunnerset(SOURCES dotgraph.cpp graphvizgenerator.cpp graphvizgeneratorplugin.cpp ) add_qbs_plugin(graphvizgenerator DEPENDS qbscore SOURCES ${SOURCES} ) qbs-src-3.3.1/src/plugins/generator/graphviz/dotgraph.cpp0000644000175100017510000000564215232633614023116 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "dotgraph.h" #include #include #include #include #include namespace qbs { namespace Internal { void DotGraph::write(QFile &file) { const auto indent = " "; file.write("digraph G {\n"); file.write(indent); for (const auto &node : m_nodes) { file.write(indent); file.write(node.toString()); file.write("\n"); } for (const auto &relation : m_relations) { file.write(indent); file.write(relation.toString()); file.write("\n"); } file.write("}\n"); } void DotGraph::write(const QString &filePath) { QFileInfo fileInfo(filePath); const auto directory = fileInfo.path(); if (!QDir(fileInfo.path()).exists()) { QDir().mkpath(directory); } QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { throw ErrorInfo(Tr::tr("Failed to create '%1': %2").arg(filePath, file.errorString())); } write(file); } } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/plugins/generator/graphviz/graphvizgenerator.cpp0000644000175100017510000002672215232633614025051 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "graphvizgenerator.h" #include "dotgraph.h" #include #include #include #include namespace qbs { using namespace Internal; static DotGraphNode makeProjectNode(size_t node, const ProjectData &project) { DotGraphNode result; result.id = node; result.label = project.name(); result.enabled = true; result.type = DotGraphNode::Type::Project; return result; } static DotGraphNode makeProductNode(size_t node, const ProductData &product) { DotGraphNode result; result.id = node; result.label = product.name(); result.enabled = product.isEnabled(); result.type = DotGraphNode::Type::Product; return result; } static DotGraphNode makeModuleNode(size_t node, const QString &module) { DotGraphNode result; result.id = node; result.label = module; result.type = DotGraphNode::Type::Module; return result; } static std::unordered_map createProductMap(const QList &products) { std::unordered_map result; for (const auto &product : products) result[product.name()] = product; return result; } static QString getFileName(const ProjectData &projectData, const QString &suffix) { return projectData.buildDirectory() + QStringLiteral("/graphviz/") + projectData.name() + suffix + QStringLiteral(".dot"); } QString GraphvizGenerator::generatorName() const { return QStringLiteral("graphviz"); } void GraphvizGenerator::generate() { const auto projects = project().projects.values(); for (const Project &theProject : projects) { writeProjectsGraph(theProject.projectData()); writeProductsGraph(theProject.projectData()); } } void GraphvizGenerator::writeProjectsGraph(const ProjectData &projectData) { DotGraph dotGraph; std::unordered_map projectToNode; std::unordered_map projectParentMap; iterateProjects(projectData, [&](const ProjectData ¤tProjectData) { projectToNode[currentProjectData.name()] = dotGraph.addNode( makeProjectNode(dotGraph.createNodeId(), currentProjectData)); const auto subProjects = currentProjectData.subProjects(); for (const auto &subProject : subProjects) projectParentMap[subProject.name()] = currentProjectData.name(); }); std::unordered_map productToNode; std::unordered_map productParentMap; iterateProjects(projectData, [&](const ProjectData ¤tProjectData) { const auto &products = currentProjectData.products(); for (const auto &product : products) { productToNode[product.name()] = dotGraph.addNode( makeProductNode(dotGraph.createNodeId(), product)); productParentMap[product.name()] = currentProjectData.name(); } }); for (const auto &item : projectParentMap) { const auto childNode = projectToNode[item.first]; const auto parentNode = projectToNode[item.second]; dotGraph.addRelation({parentNode, childNode}); } for (const auto &item : productParentMap) { const auto childNode = productToNode[item.first]; const auto parentNode = projectToNode[item.second]; dotGraph.addRelation({parentNode, childNode}); } const QString graphFilePath = getFileName(projectData, QLatin1String(".projects")); dotGraph.write(graphFilePath); } void GraphvizGenerator::writeProductsGraph(const ProjectData &projectData) { DotGraph dotGraph; const auto allProducts = projectData.allProducts(); const auto productMap = createProductMap(allProducts); std::unordered_map productToNode; for (const auto &product : allProducts) { productToNode[product.name()] = dotGraph.addNode( makeProductNode(dotGraph.createNodeId(), product)); } for (const auto &product : allProducts) { const auto parentNode = productToNode[product.name()]; for (const auto &dep : product.dependencies()) { const auto it = productMap.find(dep); if (it == productMap.end()) continue; const auto childProduct = it->second; if (product.type().contains(QStringLiteral("autotest-result")) && childProduct.type().contains(QStringLiteral("autotest"))) { continue; } const auto childNode = productToNode[dep]; dotGraph.addRelation({parentNode, childNode}); } } dotGraph.write(getFileName(projectData, QLatin1String(".products"))); for (const auto &product : allProducts) { writeProductGraph(projectData, product, productMap); } } void GraphvizGenerator::writeProductGraph( const ProjectData &projectData, const ProductData &product, const std::unordered_map &productMap) { DotGraph dotGraph; std::unordered_map productToNode; std::set deps; iterateProducts(product, productMap, [&](const ProductData ¤tProduct) { deps.insert(currentProduct.name()); }); for (const auto &dep : deps) { productToNode[dep] = dotGraph.addNode( makeProductNode(dotGraph.createNodeId(), productMap.at(dep))); } for (const auto &productName : deps) { const auto currentProduct = productMap.at(productName); const auto parentNode = productToNode[productName]; for (const auto &dep : currentProduct.dependencies()) { const auto childNode = productToNode[dep]; dotGraph.addRelation({parentNode, childNode}); } } const auto productNode = dotGraph.addNode( makeProductNode(dotGraph.createNodeId(), productMap.at(product.name()))); for (const auto &module : product.moduleProperties().allModules()) { const auto childNode = dotGraph.addNode(makeModuleNode(dotGraph.createNodeId(), module)); dotGraph.addRelation({productNode, childNode}); } const auto fileTagsString = [](const ArtifactData &artifact) { return QStringLiteral("[%1]").arg(artifact.fileTags().join(QLatin1String(", "))); }; const auto productNode2 = dotGraph.addNode( makeProductNode(dotGraph.createNodeId(), productMap.at(product.name()))); std::unordered_map artifactToNode; std::unordered_map artifactMap; for (const auto &group : product.groups()) { for (const auto &artifact : group.allSourceArtifacts()) { artifactMap[artifact.filePath()] = artifact; } } std::deque> artifactQueue; for (const auto &artifact : product.generatedArtifacts()) { artifactMap[artifact.filePath()] = artifact; if (artifact.isTargetArtifact()) artifactQueue.push_back({artifact, productNode2}); } // Traverse artifacts starting from target artifacts down to their dependencies. // This way we create nodes only for artifacts reachable from the top of the graph. // Otherwise, graph becomes too complicated. while (!artifactQueue.empty()) { const auto &[artifact, parentNodeId] = artifactQueue.front(); const auto currentPath = artifact.filePath(); auto &nodeId = artifactToNode[currentPath]; if (nodeId) { dotGraph.addRelation({parentNodeId, nodeId}); artifactQueue.pop_front(); continue; } DotGraphNode node; node.id = dotGraph.createNodeId(); node.label = QFileInfo(currentPath).fileName() + QLatin1String("\n") + fileTagsString(artifact); node.type = artifact.isGenerated() ? DotGraphNode::Type::Artifact : DotGraphNode::Type::File; nodeId = dotGraph.addNode(std::move(node)); dotGraph.addRelation({parentNodeId, nodeId}); for (const auto &childPath : artifact.childPaths()) { auto it = artifactMap.find(childPath); if (it != artifactMap.end()) { artifactQueue.push_back({it->second, nodeId}); } } artifactQueue.pop_front(); } const QString graphFilePath = getFileName( projectData, QLatin1String(".products/") + product.name()); dotGraph.write(graphFilePath); } void GraphvizGenerator::iterateProjects( const ProjectData &projectData, std::function func) { std::deque queue; queue.push_back(projectData); while (!queue.empty()) { const auto size = queue.size(); for (size_t i = 0; i < size; ++i) { const auto ¤tProjectData = queue[i]; func(currentProjectData); const auto subProjects = currentProjectData.subProjects(); std::copy(subProjects.begin(), subProjects.end(), std::back_inserter(queue)); } queue.erase(queue.begin(), queue.begin() + size); } } void GraphvizGenerator::iterateProducts( const ProductData &product, const std::unordered_map &productMap, std::function func) { std::deque productQueue{product}; while (!productQueue.empty()) { const auto ¤tProduct = productQueue.front(); func(currentProduct); for (const auto &dep : currentProduct.dependencies()) { const auto it = productMap.find(dep); if (it != productMap.end()) productQueue.push_back(it->second); } productQueue.pop_front(); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/graphviz/graphvizgeneratorplugin.cpp0000644000175100017510000000470415232633614026264 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "graphvizgenerator.h" #include #include static void GraphvizPluginLoad() { qbs::ProjectGeneratorManager::registerGenerator(std::make_shared()); } static void GraphvizPluginUnload() {} #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN( extern "C" GENERATOR_EXPORT, graphviz, GraphvizPluginLoad, GraphvizPluginUnload) qbs-src-3.3.1/src/plugins/generator/graphviz/graphvizgenerator.h0000644000175100017510000000542515232633614024513 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GRAPHVIZGENERATOR_H #define GRAPHVIZGENERATOR_H #include #include namespace qbs { class GraphvizGenerator : public ProjectGenerator { public: QString generatorName() const override; void generate() override; private: void writeProductsGraph(const ProjectData &projectData); void writeProjectsGraph(const ProjectData &projectData); void writeProductGraph( const ProjectData &projectData, const ProductData &theProject, const std::unordered_map &productMap); void iterateProjects( const ProjectData &projectData, std::function func); void iterateProducts( const ProductData &product, const std::unordered_map &productMap, std::function func); }; } // namespace qbs #endif // GRAPHVIZGENERATOR_H qbs-src-3.3.1/src/plugins/generator/graphviz/dotgraph.h0000644000175100017510000000727015232633614022562 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2025 Ivan Komissarov (abbapoh@gmail.com). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #include #include class QFile; namespace qbs { namespace Internal { struct DotGraphNode { size_t id{0}; QString label; bool enabled{true}; enum class Type { Product, Project, Module, Artifact, File }; Type type; static QByteArray typeToString(Type type) { if (type == Type::Project) return QByteArray("ellipse"); if (type == Type::Product) return QByteArray("box"); if (type == Type::Module) return QByteArray("diamond"); if (type == Type::Artifact) return QByteArray("pentagon"); if (type == Type::File) return QByteArray("note"); return QByteArray("box"); } QByteArray toString() const { QByteArray result; result += QByteArray::number(quintptr(id)) + " ["; result += "shape=" + typeToString(type); if (!enabled) { result += " fontcolor=grey"; result += " color=grey"; } result += " label=\"" + label.toUtf8() + "\""; result += "]"; return result; } }; struct Relation { size_t from{0}; size_t to{0}; QByteArray toString() const { return QByteArray::number(quintptr(from)) + " -> " + QByteArray::number(quintptr(to)); } }; class DotGraph { public: void write(QFile &file); void write(const QString &filePath); size_t addNode(DotGraphNode &&node) { m_nodes.push_back(std::move(node)); return m_nodes.back().id; } void addRelation(Relation &&relation) { m_relations.push_back(std::move(relation)); } size_t createNodeId() { return m_nodeIds++; } private: std::vector m_nodes; std::vector m_relations; size_t m_nodeIds = 1; }; } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/plugins/generator/CMakeLists.txt0000644000175100017510000000026415232633614021503 0ustar runnerrunneradd_subdirectory(clangcompilationdb) add_subdirectory(graphviz) add_subdirectory(iarew) add_subdirectory(keiluv) add_subdirectory(makefilegenerator) add_subdirectory(visualstudio) qbs-src-3.3.1/src/plugins/generator/visualstudio/0000755000175100017510000000000015232633614021474 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudiogeneratorplugin.cpp0000644000175100017510000000530115232633614030060 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "visualstudiogenerator.h" #include #include static void QbsVisualStudioGeneratorPluginLoad() { for (const auto &info : qbs::Internal::VisualStudioVersionInfo::knownVersions()) { if (info.usesMsBuild()) qbs::ProjectGeneratorManager::registerGenerator( std::make_shared(info)); } } static void QbsVisualStudioGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, visualstudiogenerator, QbsVisualStudioGeneratorPluginLoad, QbsVisualStudioGeneratorPluginUnload) qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildqbsgenerateproject.h0000644000175100017510000000367515232633614027127 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDQBSGENERATEPROJECT_H #define MSBUILDQBSGENERATEPROJECT_H #include "msbuildtargetproject.h" #include #include namespace qbs { class MSBuildQbsGenerateProject : public MSBuildTargetProject { public: MSBuildQbsGenerateProject( const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo); }; } // namespace qbs #endif // MSBUILDQBSGENERATEPROJECT_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildsolutionpropertiesproject.h0000644000175100017510000000424015232633614030605 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDSOLUTIONPROPERTIESPROJECT_H #define MSBUILDSOLUTIONPROPERTIESPROJECT_H #include "msbuild/msbuildproject.h" #include #include #include namespace qbs { class MSBuildSolutionPropertiesProject : public MSBuildProject { public: MSBuildSolutionPropertiesProject(const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir); }; } // namespace qbs #endif // MSBUILDSOLUTIONPROPERTIESPROJECT_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildqbsproductproject.cpp0000644000175100017510000004757315232633614027355 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildqbsproductproject.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildimportgroup.h" #include "msbuild/msbuilditemdefinitiongroup.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/msbuilditemmetadata.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" #include "msbuild/items/msbuildclcompile.h" #include "msbuild/items/msbuildclinclude.h" #include "msbuild/items/msbuildlink.h" #include "msbuild/items/msbuildnone.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include #include #include #include #include #include #include namespace qbs { using namespace Internal; MSBuildQbsProductProject::MSBuildQbsProductProject( const GeneratableProject &project, const GeneratableProductData &product, const Internal::VisualStudioVersionInfo &versionInfo) : MSBuildTargetProject(project, versionInfo) { Q_ASSERT(project.projects.size() == project.commandLines.size()); Q_ASSERT(project.projects.size() == product.data.size()); const int count = std::max(project.projects.size(), product.data.size()); globalsPropertyGroup()->appendProperty(QStringLiteral("QbsProductName"), product.name()); const auto cppDefaultProps = makeChild(); cppDefaultProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); for (int i = 0; i < count; ++i) { addConfiguration( project, project.projects.values().at(i), product.data.values().at(i), project.commandLines.values().at(i)); } const auto cppProps = makeChild(); cppProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.props")); for (int i = 0; i < count; ++i) addItemDefGroup(project.projects.values().at(i), product.data.values().at(i)); addFiles(project, product); } static QString productTargetPath(const qbs::ProductData &productData) { const QString fullPath = productData.targetExecutable(); if (!fullPath.isEmpty()) return QFileInfo(fullPath).absolutePath(); return productData.properties().value(QStringLiteral("buildDirectory")).toString(); } static bool listEnvironmentVariableContainsValue(const QString &environmentVariable, const QString &value) { return environmentVariable.contains(QLatin1Char(';') + value + QLatin1Char(';')) || environmentVariable.startsWith(value + QLatin1Char(';')) || environmentVariable.endsWith(QLatin1Char(';') + value); } void MSBuildQbsProductProject::addConfiguration(const GeneratableProject &project, const Project &buildTask, const ProductData &productData, const QStringList &buildConfigurationCommandLine) { const auto targetDir = Internal::PathUtils::toNativeSeparators( productTargetPath(productData), Internal::HostOsInfo::HostOsWindows); auto configurationDir = Internal::PathUtils::toNativeSeparators( project.baseBuildDirectory().absolutePath() + QLatin1Char('\\') + MSBuildUtils::configurationName(buildTask), Internal::HostOsInfo::HostOsWindows); auto relativeTargetDir = targetDir; if (targetDir.startsWith(configurationDir)) relativeTargetDir = QStringLiteral("$(SolutionDir)$(Configuration)") + relativeTargetDir.mid(configurationDir.size()); const auto &properties = productData.moduleProperties(); const bool debugBuild = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("debugInformation")) .toBool(); const auto includePaths = QStringList() << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("includePaths")) << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("systemIncludePaths")); const auto cppDefines = properties .getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("defines")); const auto sep = Internal::HostOsInfo::pathListSeparator(Internal::HostOsInfo::HostOsWindows); const auto propertyGroup1 = makeChild(); propertyGroup1->setCondition(MSBuildUtils::buildTaskCondition(buildTask)); propertyGroup1->setLabel(QStringLiteral("Configuration")); propertyGroup1->appendProperty(QStringLiteral("UseDebugLibraries"), debugBuild ? QStringLiteral("true") : QStringLiteral("false")); // General - General // We need a trailing backslash for $(OutDir); See also the VS documentation: // https://docs.microsoft.com/en-us/cpp/ide/common-macros-for-build-commands-and-properties propertyGroup1->appendProperty( QStringLiteral("OutDir"), QString(relativeTargetDir + QLatin1Char('\\'))); propertyGroup1->appendProperty(QStringLiteral("TargetName"), productData.targetName()); propertyGroup1->appendProperty( QStringLiteral("PlatformToolset"), versionInfo().platformToolsetVersion()); propertyGroup1->appendProperty(QStringLiteral("ConfigurationType"), QStringLiteral("Makefile")); // VS possible values: Unicode|MultiByte|NotSet propertyGroup1->appendProperty(QStringLiteral("CharacterSet"), properties.getModuleProperty(QStringLiteral("cpp"), QStringLiteral("windowsApiCharacterSet")) == QStringLiteral("unicode") ? QStringLiteral("MultiByte") : QStringLiteral("NotSet")); // Debugging propertyGroup1->appendProperty(QStringLiteral("DebuggerFlavor"), QStringLiteral("WindowsLocalDebugger")); propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerCommand"), QStringLiteral("$(OutDir)$(TargetName)$(TargetExt)")); propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerWorkingDirectory"), QStringLiteral("$(OutDir)")); auto env = buildTask.getRunEnvironment(productData, project.installOptions, QProcessEnvironment(), QStringList(), nullptr) .runEnvironment(); if (!env.isEmpty()) { const auto systemEnv = QProcessEnvironment::systemEnvironment(); const auto keys = systemEnv.keys(); for (const auto &key : keys) { if (!env.contains(key)) continue; // Don't duplicate keys from the system environment if (env.value(key) == systemEnv.value(key)) { env.remove(key); continue; } // Cleverly concatenate list variables to avoid duplicating system environment const QString systemValue = systemEnv.value(key); QString overriddenValue = env.value(key); if (listEnvironmentVariableContainsValue(overriddenValue, systemValue)) { env.insert(key, overriddenValue.replace(systemValue, QLatin1Char('%') + key + QLatin1Char('%'))); } QString installRoot = project.installOptions.installRoot(); if (!installRoot.isEmpty()) { if (listEnvironmentVariableContainsValue(overriddenValue, installRoot)) { env.insert(key, overriddenValue.replace(installRoot, QStringLiteral("$(QbsInstallRoot)"))); } } else { installRoot = Internal::PathUtils::toNativeSeparators( QDir(buildTask.projectData().buildDirectory()).absoluteFilePath( project.installOptions.defaultInstallRoot()), Internal::HostOsInfo::HostOsWindows); if (listEnvironmentVariableContainsValue(overriddenValue, installRoot)) { env.insert(key, overriddenValue.replace(installRoot, QStringLiteral("$(SolutionDir)$(Configuration)\\install-root"))); } } } propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerEnvironment"), env.toStringList().join(QLatin1String("\n"))); } // NMake - General // Skip configuration name, that's handled in qbs-shared.props const auto params = Internal::shellQuote( buildConfigurationCommandLine.mid(1), Internal::HostOsInfo::HostOsWindows); propertyGroup1->appendProperty( QStringLiteral("NMakeBuildCommandLine"), QString(QStringLiteral("$(QbsBuildCommandLine) ") + params)); propertyGroup1->appendProperty( QStringLiteral("NMakeReBuildCommandLine"), QString(QStringLiteral("$(QbsReBuildCommandLine) ") + params)); propertyGroup1->appendProperty( QStringLiteral("NMakeCleanCommandLine"), QString(QStringLiteral("$(QbsCleanCommandLine) ") + params)); propertyGroup1->appendProperty( QStringLiteral("NMakeOutput"), QStringLiteral("$(OutDir)$(TargetName)$(TargetExt)")); // NMake - IntelliSense propertyGroup1->appendProperty(QStringLiteral("NMakePreprocessorDefinitions"), cppDefines.join(sep)); propertyGroup1->appendProperty(QStringLiteral("NMakeIncludeSearchPath"), includePaths.join(sep)); } static QString subsystemVersion(const QString &version) { const auto v = Version::fromString(version); return QStringLiteral("%1.%2").arg( QString::number(v.majorVersion()), QString::number(v.minorVersion()).rightJustified(2, QLatin1Char('0'))); } void MSBuildQbsProductProject::addItemDefGroup(const Project &project, const ProductData &productData) { const auto &properties = productData.moduleProperties(); const bool consoleApp = productData.properties().value(QStringLiteral("consoleApplication")) .toBool(); const bool debugBuild = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("debugInformation")) .toBool(); const auto optimizationLevel = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("optimization")) .toString(); const auto warningLevel = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("warningLevel")) .toString(); const auto includePaths = QStringList() << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("includePaths")) << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("systemIncludePaths")); const auto cppDefines = properties.getModulePropertiesAsStringList( QStringLiteral("cpp"), QStringLiteral("defines")); const auto sep = Internal::HostOsInfo::pathListSeparator(Internal::HostOsInfo::HostOsWindows); const auto itemDefGroup = makeChild(); itemDefGroup->setCondition(MSBuildUtils::buildTaskCondition(project)); const auto compile = itemDefGroup->makeChild(); // C++ - General compile->appendProperty( QStringLiteral("AdditionalIncludeDirectories"), QString(includePaths.join(sep) + sep + QStringLiteral("%(AdditionalIncludeDirectories)"))); if (warningLevel == QStringLiteral("none")) compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("TurnOffAllWarnings")); else if (warningLevel == QStringLiteral("all")) compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("EnableAllWarnings")); else compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("Level3")); // this is VS default. // C++ - Optimization compile->appendProperty(QStringLiteral("Optimization"), optimizationLevel == QStringLiteral("none") ? QStringLiteral("Disabled") : QStringLiteral("MaxSpeed")); // C++ - Preprocessor compile->appendProperty( QStringLiteral("PreprocessorDefinitions"), QString(cppDefines.join(sep) + sep + QStringLiteral("%(PreprocessorDefinitions)"))); // C++ - Code Generation compile->appendProperty(QStringLiteral("RuntimeLibrary"), debugBuild ? QStringLiteral("MultiThreadedDebugDLL") : QStringLiteral("MultiThreadedDLL")); const auto link = itemDefGroup->makeChild(); // Linker - General link->appendProperty(QStringLiteral("AdditionalLibraryDirectories"), properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("libraryPaths")).join(sep)); // Linker - Input link->appendProperty( QStringLiteral("AdditionalDependencies"), QString( properties .getModulePropertiesAsStringList( QStringLiteral("cpp"), QStringLiteral("staticLibraries")) .join(sep) + sep + QStringLiteral("%(AdditionalDependencies)"))); // Linker - Debugging link->appendProperty(QStringLiteral("GenerateDebugInformation"), debugBuild ? QStringLiteral("true") : QStringLiteral("false")); // Linker - System link->appendProperty(QStringLiteral("SubSystem"), consoleApp ? QStringLiteral("Console") : QStringLiteral("Windows")); const auto subsysVersion = properties.getModuleProperty( QStringLiteral("cpp"), QStringLiteral("minimumWindowsVersion")).toString(); if (!subsysVersion.isEmpty()) link->appendProperty(QStringLiteral("MinimumRequiredVersion"), subsystemVersion(subsysVersion)); // Linker - Optimization link->appendProperty(QStringLiteral("OptimizeReferences"), debugBuild ? QStringLiteral("false") : QStringLiteral("true")); } static MSBuildFileItem *fileItemForFileTags( const QList &fileTags, MSBuildItemGroup *parent) { if (fileTags.contains(QStringLiteral("hpp"))) return parent->makeChild(); if (fileTags.contains(QStringLiteral("c")) || fileTags.contains(QStringLiteral("cpp"))) return parent->makeChild(); return parent->makeChild(); } void MSBuildQbsProductProject::addFiles(const GeneratableProject &project, const GeneratableProductData &product) { const auto itemGroup = makeChild(); addQbsFile(project, product, itemGroup); std::map sourceFileNodes; std::map sourceFileEnabledConfigurations; // Create a ClCompile item for each source file, keeping track of which configurations that // file's containing group is enabled in for (auto productDataIt = product.data.cbegin(), end = product.data.cend(); productDataIt != end; ++productDataIt) { const auto groups = productDataIt.value().groups(); for (const auto &group : groups) { const auto sourceArtifacts = group.allSourceArtifacts(); for (const auto &sourceArtifact : sourceArtifacts) { const auto filePath = sourceArtifact.filePath(); if (sourceFileNodes.find(filePath) == sourceFileNodes.end()) { sourceFileNodes.insert({ filePath, fileItemForFileTags(sourceArtifact.fileTags(), itemGroup) }); } auto fileItem = sourceFileNodes[filePath]; QString path = project.baseBuildDirectory().relativeFilePath(filePath); // The path still might not be relative (for example if the file item is // located on a different drive) if (QFileInfo(path).isRelative()) path = QStringLiteral("$(ProjectDir)") + path; fileItem->setFilePath(path); if (group.isEnabled()) sourceFileEnabledConfigurations[filePath] << productDataIt.key(); } } } // Add ExcludedFromBuild item metadata to each file for each configuration // where that file's containing group is disabled for (const auto &sourceFileNode : sourceFileNodes) { for (auto it = project.projects.cbegin(), end = project.projects.cend(); it != end; ++it) { if (!sourceFileEnabledConfigurations[sourceFileNode.first].contains(it.key())) { const auto metadata = sourceFileNode.second->makeChild( QStringLiteral("ExcludedFromBuild"), QStringLiteral("true")); metadata->setCondition( QStringLiteral("'$(Configuration)|$(Platform)'=='") + MSBuildUtils::fullName(it.value()) + QStringLiteral("'")); } } } const auto import = makeChild(); import->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.targets")); } void MSBuildQbsProductProject::addQbsFile(const GeneratableProject &project, const GeneratableProductData &product, MSBuildItemGroup *itemGroup) { const auto fileItem = itemGroup->makeChild(); QString path = project.baseBuildDirectory().relativeFilePath(product.location().filePath()); // The path still might not be relative (for example if the file item is // located on a different drive) if (QFileInfo(path).isRelative()) path = QStringLiteral("$(ProjectDir)") + path; fileItem->setFilePath(path); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudiogenerator.cpp0000644000175100017510000003651215232633614026651 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfiltersproject.h" #include "msbuildqbsgenerateproject.h" #include "msbuildsharedsolutionpropertiesproject.h" #include "msbuildsolutionpropertiesproject.h" #include "msbuildqbsproductproject.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include "visualstudioguidpool.h" #include "msbuild/msbuildpropertygroup.h" #include "msbuild/msbuildproject.h" #include "solution/visualstudiosolution.h" #include "solution/visualstudiosolutionfileproject.h" #include "solution/visualstudiosolutionglobalsection.h" #include "solution/visualstudiosolutionfolderproject.h" #include "io/msbuildprojectwriter.h" #include "io/visualstudiosolutionwriter.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; class VisualStudioGeneratorPrivate { friend class SolutionDependenciesVisitor; public: VisualStudioGeneratorPrivate(const Internal::VisualStudioVersionInfo &versionInfo) : versionInfo(versionInfo) {} Internal::VisualStudioVersionInfo versionInfo; std::shared_ptr guidPool; std::shared_ptr solution; QString solutionFilePath; QMap> msbuildProjects; QMap solutionProjects; QMap solutionFolders; QList> propertySheetNames; void reset(); }; void VisualStudioGeneratorPrivate::reset() { guidPool.reset(); solution.reset(); solutionFilePath.clear(); msbuildProjects.clear(); solutionProjects.clear(); solutionFolders.clear(); propertySheetNames.clear(); } class SolutionDependenciesVisitor : public IGeneratableProjectVisitor { public: SolutionDependenciesVisitor(VisualStudioGenerator *generator) : generator(generator) { } void visitProject(const GeneratableProject &project) override { Q_UNUSED(project); nestedProjects = new VisualStudioSolutionGlobalSection( QStringLiteral("NestedProjects"), generator->d->solution.get()); generator->d->solution->appendGlobalSection(nestedProjects); } void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &parentProjectData, const GeneratableProjectData &projectData) override { Q_UNUSED(project); // The root project will have a null GeneratableProjectData // as its parent object (so skip giving it a parent folder) if (!parentProjectData.name().isEmpty()) { nestedProjects->appendProperty( generator->d->solutionFolders.value(projectData.uniqueName())->guid() .toString(), generator->d->solutionFolders.value(parentProjectData.uniqueName())->guid() .toString()); } } void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) override { Q_UNUSED(project); Q_UNUSED(projectData); const auto dependencies = productData.dependencies(); for (const auto &dep : dependencies) { generator->d->solution->addDependency( generator->d->solutionProjects.value(productData.name()), generator->d->solutionProjects.value(dep)); } nestedProjects->appendProperty( generator->d->solutionProjects.value(productData.name())->guid().toString(), generator->d->solutionFolders.value(projectData.uniqueName())->guid() .toString()); } private: VisualStudioGenerator *generator = nullptr; VisualStudioSolutionGlobalSection *nestedProjects = nullptr; }; VisualStudioGenerator::VisualStudioGenerator(const VisualStudioVersionInfo &versionInfo) : d(new VisualStudioGeneratorPrivate(versionInfo)) { if (d->versionInfo.usesVcBuild()) throw ErrorInfo(Tr::tr("VCBuild (Visual Studio 2008 and below) is not supported")); if (!d->versionInfo.usesMsBuild()) throw ErrorInfo(Tr::tr("Unknown/unsupported build engine")); Q_ASSERT(d->versionInfo.usesSolutions()); } VisualStudioGenerator::~VisualStudioGenerator() = default; QString VisualStudioGenerator::generatorName() const { return QStringLiteral("visualstudio%1").arg(d->versionInfo.marketingVersion()); } void VisualStudioGenerator::addPropertySheets(const GeneratableProject &project) { { const auto fileName = QStringLiteral("qbs.props"); d->propertySheetNames.push_back({ fileName, true }); d->msbuildProjects.insert(project.baseBuildDirectory().absoluteFilePath(fileName), std::make_shared( d->versionInfo, project, qbsExecutableFilePath(), qbsSettingsDir())); } { const auto fileName = QStringLiteral("qbs-shared.props"); d->propertySheetNames.push_back({ fileName, false }); d->msbuildProjects.insert(project.baseBuildDirectory().absoluteFilePath(fileName), std::make_shared( d->versionInfo, project, qbsExecutableFilePath(), qbsSettingsDir())); } } void VisualStudioGenerator::addPropertySheets( const std::shared_ptr &targetProject) { for (const auto &pair : std::as_const(d->propertySheetNames)) { targetProject->appendPropertySheet( QStringLiteral("$(SolutionDir)\\") + pair.first, pair.second); } } static QString targetFilePath(const QString &baseName, const QString &baseBuildDirectory) { return QDir(baseBuildDirectory).absoluteFilePath(baseName + QStringLiteral(".vcxproj")); } static QString targetFilePath(const GeneratableProductData &product, const QString &baseBuildDirectory) { return targetFilePath(product.name(), baseBuildDirectory); } static void addDefaultGlobalSections(const GeneratableProject &topLevelProject, VisualStudioSolution *solution) { const auto configurationPlatformsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("SolutionConfigurationPlatforms"), solution); solution->appendGlobalSection(configurationPlatformsSection); for (const auto &qbsProject : topLevelProject.projects) configurationPlatformsSection->appendProperty(MSBuildUtils::fullName(qbsProject), MSBuildUtils::fullName(qbsProject)); const auto projectConfigurationPlatformsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("ProjectConfigurationPlatforms"), solution); solution->appendGlobalSection(projectConfigurationPlatformsSection); projectConfigurationPlatformsSection->setPost(true); const auto projects = solution->fileProjects(); for (const auto project : projects) { for (const auto &qbsProject : topLevelProject.projects) { projectConfigurationPlatformsSection->appendProperty( QStringLiteral("%1.%2.ActiveCfg").arg(project->guid().toString(), MSBuildUtils::fullDisplayName(qbsProject)), MSBuildUtils::fullName(qbsProject)); projectConfigurationPlatformsSection->appendProperty( QStringLiteral("%1.%2.Build.0").arg(project->guid().toString(), MSBuildUtils::fullDisplayName(qbsProject)), MSBuildUtils::fullName(qbsProject)); } } const auto solutionPropsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("SolutionProperties"), solution); solution->appendGlobalSection(solutionPropsSection); solutionPropsSection->appendProperty(QStringLiteral("HideSolutionNode"), QStringLiteral("FALSE")); } static void writeProjectFiles(const QMap> &projects) { // Write out all the MSBuild project files to disk for (auto it = projects.cbegin(), end = projects.cend(); it != end; ++it) { const auto projectFilePath = it.key(); Internal::FileSaver file(projectFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Tr::tr("Cannot open %s for writing").arg(projectFilePath)); std::shared_ptr project = it.value(); MSBuildProjectWriter writer(file.device()); if (!(writer.write(project.get()) && file.commit())) throw ErrorInfo(Tr::tr("Failed to generate %1").arg(projectFilePath)); } } static void writeSolution(const std::shared_ptr &solution, const QString &solutionFilePath, const Internal::Logger &logger) { Internal::FileSaver file(solutionFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Tr::tr("Cannot open %s for writing").arg(solutionFilePath)); VisualStudioSolutionWriter writer(file.device()); writer.setProjectBaseDirectory(QFileInfo(solutionFilePath).path().toStdString()); if (!(writer.write(solution.get()) && file.commit())) throw ErrorInfo(Tr::tr("Failed to generate %1").arg(solutionFilePath)); logger.qbsInfo() << Tr::tr("Generated %1").arg(QFileInfo(solutionFilePath).fileName()); } void VisualStudioGenerator::generate() { GeneratableProjectIterator it(project()); it.accept(this); addDefaultGlobalSections(project(), d->solution.get()); // Second pass: connection solution project interdependencies and project nesting hierarchy SolutionDependenciesVisitor solutionDependenciesVisitor(this); it.accept(&solutionDependenciesVisitor); writeProjectFiles(d->msbuildProjects); writeSolution(d->solution, d->solutionFilePath, logger()); d->reset(); } void VisualStudioGenerator::visitProject(const GeneratableProject &project) { addPropertySheets(project); const auto buildDir = project.baseBuildDirectory(); d->guidPool = std::make_shared( buildDir.absoluteFilePath(project.name() + QStringLiteral(".guid.txt")).toStdString()); d->solutionFilePath = buildDir.absoluteFilePath(project.name() + QStringLiteral(".sln")); d->solution = std::make_shared(d->versionInfo); // Create a helper project to re-run qbs generate const auto qbsGenerate = QStringLiteral("qbs-generate"); const auto projectFilePath = targetFilePath(qbsGenerate, buildDir.absolutePath()); const auto relativeProjectFilePath = QFileInfo(d->solutionFilePath).dir() .relativeFilePath(projectFilePath); auto targetProject = std::make_shared(project, d->versionInfo); targetProject->setGuid(d->guidPool->drawProductGuid(relativeProjectFilePath.toStdString())); d->msbuildProjects.insert(projectFilePath, targetProject); addPropertySheets(targetProject); const auto solutionProject = new VisualStudioSolutionFileProject( targetFilePath(qbsGenerate, project.baseBuildDirectory().absolutePath()), d->solution.get()); solutionProject->setGuid(targetProject->guid()); d->solution->appendProject(solutionProject); d->solutionProjects.insert(qbsGenerate, solutionProject); } void VisualStudioGenerator::visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) { Q_UNUSED(project); const auto solutionFolder = new VisualStudioSolutionFolderProject(d->solution.get()); solutionFolder->setName(projectData.name()); d->solution->appendProject(solutionFolder); QBS_CHECK(!d->solutionFolders.contains(projectData.uniqueName())); d->solutionFolders.insert(projectData.uniqueName(), solutionFolder); } void VisualStudioGenerator::visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) { Q_UNUSED(projectData); const auto projectFilePath = targetFilePath(productData, project.baseBuildDirectory().absolutePath()); const auto relativeProjectFilePath = QFileInfo(d->solutionFilePath) .dir().relativeFilePath(projectFilePath); auto targetProject = std::make_shared(project, productData, d->versionInfo); targetProject->setGuid(d->guidPool->drawProductGuid(relativeProjectFilePath.toStdString())); addPropertySheets(targetProject); d->msbuildProjects.insert(projectFilePath, targetProject); d->msbuildProjects.insert(projectFilePath + QStringLiteral(".filters"), std::make_shared(productData)); const auto solutionProject = new VisualStudioSolutionFileProject( targetFilePath(productData, project.baseBuildDirectory().absolutePath()), d->solution.get()); solutionProject->setGuid(targetProject->guid()); d->solution->appendProject(solutionProject); d->solutionProjects.insert(productData.name(), solutionProject); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudioguidpool.cpp0000644000175100017510000000657315232633614026511 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudioguidpool.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { class VisualStudioGuidPoolPrivate { public: std::string storeFilePath; std::map productGuids; }; VisualStudioGuidPool::VisualStudioGuidPool(const std::string &storeFilePath) : d(std::make_shared()) { // Read any existing GUIDs from the on-disk store std::ifstream file(Internal::utf8_to_native_path(d->storeFilePath = storeFilePath)); if (file.is_open()) { const auto data = std::string( std::istreambuf_iterator(file), std::istreambuf_iterator()); const auto json = QJsonDocument::fromJson(QByteArray(data.data(), data.size())).object(); for (auto it = json.begin(), end = json.end(); it != end; ++it) { d->productGuids.insert({it.key().toStdString(), QUuid(it.value().toString())}); } } } VisualStudioGuidPool::~VisualStudioGuidPool() { Internal::FileSaver file(d->storeFilePath); if (file.open()) { QJsonObject productData; for (const auto &it : d->productGuids) productData[QString::fromStdString(it.first)] = it.second.toString(); const auto data = QJsonDocument(productData).toJson(); file.write({data.data(), size_t(data.size())}); file.commit(); } } QUuid VisualStudioGuidPool::drawProductGuid(const std::string &productName) { if (d->productGuids.find(productName) == d->productGuids.cend()) d->productGuids.insert({productName, QUuid::createUuid()}); return d->productGuids.at(productName); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudioguidpool.h0000644000175100017510000000441515232633614026147 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOGUIDPOOL_H #define VISUALSTUDIOGUIDPOOL_H #include #include namespace qbs { class VisualStudioGuidPoolPrivate; /*! * Provides persistent storage for GUIDs related to Visual Studio project file nodes. * These are stored on disk separately from project files and so allow projects to be * regenerated while retaining the same GUIDs. This helps avoid unnecessary project * reloads in Visual Studio, and helps ease source control usage. */ class VisualStudioGuidPool { public: explicit VisualStudioGuidPool(const std::string &storeFilePath); ~VisualStudioGuidPool(); QUuid drawProductGuid(const std::string &productName); private: std::shared_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOGUIDPOOL_H qbs-src-3.3.1/src/plugins/generator/visualstudio/CMakeLists.txt0000644000175100017510000000127515232633614024241 0ustar runnerrunnerset(SOURCES msbuildfiltersproject.cpp msbuildfiltersproject.h msbuildqbsgenerateproject.cpp msbuildqbsgenerateproject.h msbuildqbsproductproject.cpp msbuildqbsproductproject.h msbuildsharedsolutionpropertiesproject.cpp msbuildsharedsolutionpropertiesproject.h msbuildsolutionpropertiesproject.cpp msbuildsolutionpropertiesproject.h msbuildtargetproject.cpp msbuildtargetproject.h msbuildutils.h visualstudiogenerator.cpp visualstudiogenerator.h visualstudioguidpool.cpp visualstudioguidpool.h visualstudiogeneratorplugin.cpp ) add_qbs_plugin(visualstudiogenerator DEPENDS qbscore qbsmsbuild SOURCES ${SOURCES} ) qbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudio.qbs0000644000175100017510000000174515232633614024745 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { Depends { name: "qbsmsbuild" } name: "visualstudiogenerator" files: ["visualstudiogeneratorplugin.cpp"] Group { name: "Visual Studio generator" files: [ "msbuildfiltersproject.cpp", "msbuildfiltersproject.h", "msbuildqbsgenerateproject.cpp", "msbuildqbsgenerateproject.h", "msbuildqbsproductproject.cpp", "msbuildqbsproductproject.h", "msbuildsharedsolutionpropertiesproject.cpp", "msbuildsharedsolutionpropertiesproject.h", "msbuildsolutionpropertiesproject.cpp", "msbuildsolutionpropertiesproject.h", "msbuildtargetproject.cpp", "msbuildtargetproject.h", "msbuildutils.h", "visualstudiogenerator.cpp", "visualstudiogenerator.h", "visualstudioguidpool.cpp", "visualstudioguidpool.h", ] } } qbs-src-3.3.1/src/plugins/generator/visualstudio/visualstudiogenerator.h0000644000175100017510000000611715232633614026314 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_VISUALSTUDIOGENERATOR_H #define QBS_VISUALSTUDIOGENERATOR_H #include #include #include #include "visualstudioguidpool.h" #include #include #include namespace qbs { namespace Internal { class VisualStudioVersionInfo; } class MSBuildProject; class MSBuildTargetProject; class VisualStudioGeneratorPrivate; class VisualStudioSolution; class VisualStudioSolutionFileProject; class VisualStudioSolutionFolderProject; class VisualStudioGenerator : public ProjectGenerator, private IGeneratableProjectVisitor { friend class SolutionDependenciesVisitor; public: explicit VisualStudioGenerator(const Internal::VisualStudioVersionInfo &versionInfo); ~VisualStudioGenerator() override; QString generatorName() const override; void generate() override; private: void visitProject(const GeneratableProject &project) override; void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) override; void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) override; void addPropertySheets(const GeneratableProject &project); void addPropertySheets(const std::shared_ptr &targetProject); std::unique_ptr d; }; } // namespace qbs #endif // QBS_VISUALSTUDIOGENERATOR_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildfiltersproject.h0000644000175100017510000000361115232633614026265 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDFILTERSPROJECT_H #define MSBUILDFILTERSPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildFilter; class MSBuildFiltersProject : public MSBuildProject { public: explicit MSBuildFiltersProject(const GeneratableProductData &product); }; } // namespace qbs #endif // MSBUILDFILTERSPROJECT_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildfiltersproject.cpp0000644000175100017510000001777715232633614026642 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfiltersproject.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/items/msbuildclcompile.h" #include "msbuild/items/msbuildclinclude.h" #include "msbuild/items/msbuildfilter.h" #include "msbuild/items/msbuildnone.h" #include #include #include namespace qbs { namespace { const QStringList & sourceFileExtensions() { static const QStringList EXTENSIONS{ QStringLiteral("c"), QStringLiteral("C"), QStringLiteral("cpp"), QStringLiteral("cxx"), QStringLiteral("c++"), QStringLiteral("cc"), QStringLiteral("cs"), QStringLiteral("def"), QStringLiteral("java"), QStringLiteral("m"), QStringLiteral("mm")}; return EXTENSIONS; } const QStringList & headerFileExtensions() { static const QStringList EXTENSIONS{ QStringLiteral("h"), QStringLiteral("H"), QStringLiteral("hpp"), QStringLiteral("hxx"), QStringLiteral("h++")}; return EXTENSIONS; } struct FilterInfo { QString name; QList extensions; bool parseFiles{ true }; bool sourceControlFiles{ true }; }; const std::vector & getDefaultFilterInfo() { static const std::vector INFOS { {QStringLiteral("Source Files"), sourceFileExtensions()}, {QStringLiteral("Header Files"), headerFileExtensions()}, {QStringLiteral("Form Files"), QStringList() << QStringLiteral("ui")}, {QStringLiteral("Resource Files"), QStringList() << QStringLiteral("qrc") << QStringLiteral("rc") << QStringLiteral("*"), false}, {QStringLiteral("Generated Files"), QStringList() << QStringLiteral("moc"), true, false}, {QStringLiteral("Translation Files"), QStringList() << QStringLiteral("ts"), false}, }; return INFOS; } MSBuildFilter * makeBuildFilter(const FilterInfo &filterInfo, MSBuildItemGroup *itemFiltersGroup) { const auto filter = itemFiltersGroup->makeChild( filterInfo.name, filterInfo.extensions); filter->appendProperty(QStringLiteral("ParseFiles"), filterInfo.parseFiles); filter->appendProperty(QStringLiteral("SourceControlFiles"), filterInfo.sourceControlFiles); return filter; } bool matchesFilter(const FilterInfo &filterInfo, const QString &filePath) { return filterInfo.extensions.contains(QFileInfo(filePath).completeSuffix()); } bool isHeaderFile(const QString &filePath) { return headerFileExtensions().contains(QFileInfo(filePath).completeSuffix()); } bool isSourceFile(const QString &filePath) { return sourceFileExtensions().contains(QFileInfo(filePath).completeSuffix()); } MSBuildFileItem * makeFileItem(const QString& filePath, MSBuildItemGroup *itemGroup) { if (isHeaderFile(filePath)) return itemGroup->makeChild(); if (isSourceFile(filePath)) return itemGroup->makeChild(); return itemGroup->makeChild(); } class ProductProcessor { public: using StringSet = Internal::Set; ProductProcessor(MSBuildProject *parent) : m_parent(parent) , m_itemFiltersGroup(m_parent->makeChild()) { } void operator()(const QList &productDatas) { for (const auto &productData : productDatas) { const auto &productName = productData.name(); for (const auto &groupData : productData.groups()) { if (groupData.name() == productName) { processProductFiles(Internal::rangeTo(groupData.allFilePaths())); } else { processGroup(groupData); } } } } void processProductFiles(const StringSet &files) { for (const auto &filePath : files) { MSBuildFileItem *fileItem = nullptr; for (const auto &filterInfo : getDefaultFilterInfo()) { if (matchesFilter(filterInfo, filePath)) { makeFilter(filterInfo); if (filterInfo.name == QStringLiteral("Header Files")) { if (!m_headerFilesGroup) m_headerFilesGroup = m_parent->makeChild(); fileItem = m_headerFilesGroup->makeChild(); } else if (filterInfo.name == QStringLiteral("Source Files")) { if (!m_sourceFilesGroup) m_sourceFilesGroup = m_parent->makeChild(); fileItem = m_sourceFilesGroup->makeChild(); } if (fileItem) { fileItem->setFilterName(filterInfo.name); break; } } } if (!fileItem) { if (!m_filesGroup) { m_filesGroup = m_parent->makeChild(); } fileItem = m_filesGroup->makeChild(); } fileItem->setFilePath(filePath); } } void processGroup(const GroupData &groupData) { makeFilter({groupData.name(), QStringList() << QStringLiteral("*")}); auto *itemGroup = m_parent->makeChild(); const auto &files = groupData.allFilePaths(); for (const auto &filePath : files) { auto *fileItem = makeFileItem(filePath, itemGroup); fileItem->setFilePath(filePath); fileItem->setFilterName(groupData.name()); } } void makeFilter(const FilterInfo &filterInfo) { if (!m_createdFilters.contains(filterInfo.name)) { makeBuildFilter(filterInfo, m_itemFiltersGroup); m_createdFilters.insert(filterInfo.name); } } private: MSBuildProject *m_parent = nullptr; MSBuildItemGroup *m_itemFiltersGroup = nullptr; MSBuildItemGroup *m_headerFilesGroup = nullptr; MSBuildItemGroup *m_sourceFilesGroup = nullptr; MSBuildItemGroup *m_filesGroup = nullptr; QSet m_createdFilters; }; } // namespace MSBuildFiltersProject::MSBuildFiltersProject(const GeneratableProductData &product) { // Normally this would be versionInfo.toolsVersion() but for some reason it seems // filters projects are always v4.0 setToolsVersion(QStringLiteral("4.0")); ProductProcessor(this)(product.data.values()); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildsharedsolutionpropertiesproject.cpp0000644000175100017510000001602215232633614032330 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildsharedsolutionpropertiesproject.h" #include "msbuild/msbuildpropertygroup.h" #include #include #include namespace qbs { static QString qbsCommandLine(const GeneratableProject &project, const QString &subCommand, const QString &qbsSettingsDir, const Internal::VisualStudioVersionInfo &versionInfo) { auto addEnvironmentVariableArgument = [](Internal::CommandLine &cl, const QString &var, const QString &prefix = QString()) { cl.appendRawArgument(QStringLiteral("\"%1$(%2)\"").arg(prefix, var)); }; auto realSubCommand = subCommand; if (subCommand == QStringLiteral("rebuild")) realSubCommand = QStringLiteral("build"); // "path/to/qbs.exe" {build|clean} // --settings-dir "path/to/settings/directory/" // -f "path/to/project.qbs" -d "/build/directory/" // -p product_name [[configuration key:value]...] Internal::CommandLine commandLine; commandLine.setProgram(QStringLiteral("\"$(QbsExecutablePath)\""), true); commandLine.appendArgument(realSubCommand); if (!qbsSettingsDir.isEmpty()) { commandLine.appendArgument(QStringLiteral("--settings-dir")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsSettingsDir")); } commandLine.appendArgument(QStringLiteral("-f")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsProjectFile")); commandLine.appendArgument(QStringLiteral("-d")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsBuildDir")); if (subCommand == QStringLiteral("generate")) { commandLine.appendArgument(QStringLiteral("-g")); commandLine.appendArgument(QStringLiteral("visualstudio%1") .arg(versionInfo.marketingVersion())); } else { commandLine.appendArgument(QStringLiteral("-p")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsProductName")); commandLine.appendArgument(QStringLiteral("--wait-lock")); } if (realSubCommand == QStringLiteral("build") && !project.installOptions.installRoot().isEmpty()) { commandLine.appendArgument(QStringLiteral("--install-root")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsInstallRoot")); } if (realSubCommand == QStringLiteral("build") && subCommand == QStringLiteral("rebuild")) { commandLine.appendArgument(QStringLiteral("--check-timestamps")); commandLine.appendArgument(QStringLiteral("--force-probe-execution")); } addEnvironmentVariableArgument(commandLine, QStringLiteral("Configuration"), QStringLiteral("config:")); return commandLine.toCommandLine(Internal::HostOsInfo::HostOsWindows); } MSBuildSharedSolutionPropertiesProject::MSBuildSharedSolutionPropertiesProject( const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto group = makeChild(); group->setLabel(QStringLiteral("UserMacros")); // Order's important here... a variable must be listed before one that uses it group->appendProperty( QStringLiteral("QbsExecutablePath"), QString(QStringLiteral("$(QbsExecutableDir)") + qbsExecutable.fileName())); if (!project.installOptions.installRoot().isEmpty()) { group->appendProperty( QStringLiteral("QbsInstallRoot"), Internal::PathUtils::toNativeSeparators( project.installOptions.installRoot(), Internal::HostOsInfo::HostOsWindows)); } group->appendProperty( QStringLiteral("QbsProjectFile"), QString(QStringLiteral("$(QbsProjectDir)") + project.filePath().fileName())); // Trailing '.' is not a typo. It prevents the trailing slash from combining with the closing // quote to form an escape sequence. Unfortunately, Visual Studio expands variables *before* // passing them to the underlying command shell, so there's not much we can do with regard to // doing it "properly". Setting environment variables through MSBuild and using them in place // of actual arguments does not work either, as Visual Studio apparently expands the environment // variables as well, before passing them to the underlying shell. group->appendProperty(QStringLiteral("QbsBuildDir"), QStringLiteral("$(SolutionDir).")); group->appendProperty(QStringLiteral("QbsBuildCommandLine"), qbsCommandLine(project, QStringLiteral("build"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsReBuildCommandLine"), qbsCommandLine(project, QStringLiteral("rebuild"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsCleanCommandLine"), qbsCommandLine(project, QStringLiteral("clean"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsGenerateCommandLine"), qbsCommandLine(project, QStringLiteral("generate"), qbsSettingsDir, versionInfo)); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildqbsgenerateproject.cpp0000644000175100017510000000601015232633614027444 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildqbsgenerateproject.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" #include #include #include namespace qbs { MSBuildQbsGenerateProject::MSBuildQbsGenerateProject( const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo) : MSBuildTargetProject(project, versionInfo) { const auto cppDefaultProps = makeChild(); cppDefaultProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); const auto group = makeChild(); group->setLabel(QStringLiteral("Configuration")); group->appendProperty(QStringLiteral("PlatformToolset"), versionInfo.platformToolsetVersion()); group->appendProperty(QStringLiteral("ConfigurationType"), QStringLiteral("Makefile")); const auto params = Internal::shellQuote(project.commandLine(), Internal::HostOsInfo::HostOsWindows); group->appendProperty( QStringLiteral("NMakeBuildCommandLine"), QString(QStringLiteral("$(QbsGenerateCommandLine) ") + params)); const auto cppProps = makeChild(); cppProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.props")); const auto import = makeChild(); import->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.targets")); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildtargetproject.cpp0000644000175100017510000001141015232633614026432 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildtargetproject.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildimportgroup.h" #include "msbuild/msbuilditem.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" namespace qbs { class MSBuildTargetProjectPrivate { public: MSBuildTargetProjectPrivate(const Internal::VisualStudioVersionInfo &versionInfo) : versionInfo(versionInfo) {} MSBuildPropertyGroup *globalsPropertyGroup = nullptr; MSBuildProperty *projectGuidProperty = nullptr; const Internal::VisualStudioVersionInfo &versionInfo; }; MSBuildTargetProject::MSBuildTargetProject( const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo) : d(new MSBuildTargetProjectPrivate(versionInfo)) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto projectConfigurationsGroup = makeChild(); projectConfigurationsGroup->setLabel(QStringLiteral("ProjectConfigurations")); for (auto it = project.projects.cbegin(), end = project.projects.cend(); it != end; ++it) { const auto item = projectConfigurationsGroup->makeChild( QStringLiteral("ProjectConfiguration")); item->setInclude(MSBuildUtils::fullName(it.value())); item->appendProperty(QStringLiteral("Configuration"), it.key()); item->appendProperty(QStringLiteral("Platform"), MSBuildUtils::platform(it.value())); } d->globalsPropertyGroup = makeChild(); d->globalsPropertyGroup->setLabel(QStringLiteral("Globals")); d->projectGuidProperty = d->globalsPropertyGroup->makeChild( QStringLiteral("ProjectGuid"), QUuid::createUuid().toString()); // Trigger creation of the property sheets ImportGroup propertySheetsImportGroup(); } MSBuildTargetProject::~MSBuildTargetProject() = default; const Internal::VisualStudioVersionInfo &MSBuildTargetProject::versionInfo() const { return d->versionInfo; } QUuid MSBuildTargetProject::guid() const { return QUuid{d->projectGuidProperty->value().toString()}; } void MSBuildTargetProject::setGuid(const QUuid &guid) { d->projectGuidProperty->setValue(guid.toString()); } MSBuildPropertyGroup *MSBuildTargetProject::globalsPropertyGroup() { return d->globalsPropertyGroup; } MSBuildImportGroup *MSBuildTargetProject::propertySheetsImportGroup() { MSBuildImportGroup *importGroup = nullptr; for (const auto &child : children()) { if (auto group = dynamic_cast(child.get())) { if (group->label() == QStringLiteral("PropertySheets")) { importGroup = group; break; } } } if (!importGroup) { importGroup = makeChild(); importGroup->setLabel(QStringLiteral("PropertySheets")); } return importGroup; } void MSBuildTargetProject::appendPropertySheet(const QString &path, bool optional) { const auto import = propertySheetsImportGroup()->makeChild(); import->setProject(path); if (optional) import->setCondition(QStringLiteral("Exists('%1')").arg(path)); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildsolutionpropertiesproject.cpp0000644000175100017510000000564515232633614031152 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildsolutionpropertiesproject.h" #include "msbuild/msbuildpropertygroup.h" #include #include namespace qbs { MSBuildSolutionPropertiesProject::MSBuildSolutionPropertiesProject( const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto group = makeChild(); group->setLabel(QStringLiteral("UserMacros")); static const auto win = Internal::HostOsInfo::HostOsWindows; group->appendProperty( QStringLiteral("QbsExecutableDir"), QString( Internal::PathUtils::toNativeSeparators(qbsExecutable.path(), win) + Internal::HostOsInfo::pathSeparator(win))); group->appendProperty( QStringLiteral("QbsProjectDir"), QString( Internal::PathUtils::toNativeSeparators(project.filePath().path(), win) + Internal::HostOsInfo::pathSeparator(win))); if (!qbsSettingsDir.isEmpty()) { group->appendProperty( QStringLiteral("QbsSettingsDir"), QString( Internal::PathUtils::toNativeSeparators(qbsSettingsDir, win) + Internal::HostOsInfo::pathSeparator(win) + QLatin1Char('.'))); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildtargetproject.h0000644000175100017510000000467215232633614026113 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDTARGETPROJECT_H #define MSBUILDTARGETPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildImportGroup; class MSBuildPropertyGroup; class MSBuildTargetProjectPrivate; class VisualStudioGenerator; class MSBuildTargetProject : public MSBuildProject { protected: MSBuildTargetProject( const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo); public: ~MSBuildTargetProject() override; const Internal::VisualStudioVersionInfo &versionInfo() const; QUuid guid() const; void setGuid(const QUuid &guid); MSBuildPropertyGroup *globalsPropertyGroup(); MSBuildImportGroup *propertySheetsImportGroup(); void appendPropertySheet(const QString &path, bool optional = false); private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDTARGETPROJECT_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildqbsproductproject.h0000644000175100017510000000535515232633614027012 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDQBSPRODUCTPROJECT_H #define MSBUILDQBSPRODUCTPROJECT_H #include "msbuildtargetproject.h" #include #include #include namespace qbs { class MSBuildImportGroup; class MSBuildItemGroup; class MSBuildProperty; class VisualStudioGenerator; class MSBuildQbsProductProject : public MSBuildTargetProject { public: MSBuildQbsProductProject( const GeneratableProject &project, const GeneratableProductData &product, const Internal::VisualStudioVersionInfo &versionInfo); private: using ProjectConfigurations = QHash>; void addConfiguration(const GeneratableProject &project, const Project &buildTask, const ProductData &productData, const QStringList &buildConfigurationCommandLine); void addItemDefGroup(const Project &project, const ProductData &productData); void addFiles(const GeneratableProject &project, const GeneratableProductData &product); void addQbsFile(const GeneratableProject &project, const GeneratableProductData &product, MSBuildItemGroup *itemGroup); }; } // namespace qbs #endif // MSBUILDQBSPRODUCTPROJECT_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildutils.h0000644000175100017510000001016615232633614024371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDUTILS_H #define MSBUILDUTILS_H #include namespace qbs { class MSBuildUtils { public: static QString _qbsArchitecture(const qbs::Project &project) { return project.projectConfiguration() .value(QStringLiteral("qbs")).toMap() .value(QStringLiteral("architecture")).toString(); } static const QString visualStudioArchitectureName(const QString &qbsArch, bool useDisplayName) { if (qbsArch == QStringLiteral("x86") && useDisplayName) return qbsArch; // map of qbs architecture names to MSBuild architecture names static const QMap map { {QStringLiteral("x86"), QStringLiteral("Win32")}, {QStringLiteral("x86_64"), QStringLiteral("x64")}, {QStringLiteral("ia64"), QStringLiteral("Itanium")}, {QStringLiteral("arm"), QStringLiteral("ARM")}, {QStringLiteral("arm64"), QStringLiteral("ARM64")} }; return map[qbsArch]; } static QString configurationName(const qbs::Project &project) { return project.projectConfiguration() .value(QStringLiteral("qbs")).toMap() .value(QStringLiteral("configurationName")).toString(); } static QString displayPlatform(const qbs::Project &project) { const auto architecture = _qbsArchitecture(project); auto displayPlatform = visualStudioArchitectureName(architecture, true); if (displayPlatform.isEmpty()) displayPlatform = architecture; return displayPlatform; } static QString platform(const qbs::Project &project) { const auto architecture = _qbsArchitecture(project); auto platform = visualStudioArchitectureName(architecture, false); if (platform.isEmpty()) { qWarning() << "WARNING: Unsupported architecture \"" << architecture << "\"; using \"Win32\" platform."; platform = QStringLiteral("Win32"); } return platform; } static QString fullDisplayName(const qbs::Project &project) { return QStringLiteral("%1|%2").arg(configurationName(project), displayPlatform(project)); } static QString fullName(const qbs::Project &project) { return QStringLiteral("%1|%2").arg(configurationName(project), platform(project)); } static QString buildTaskCondition(const Project &buildTask) { return QStringLiteral("'$(Configuration)|$(Platform)'=='") + MSBuildUtils::fullName(buildTask) + QStringLiteral("'"); } }; } // namespace qbs #endif // MSBUILDUTILS_H qbs-src-3.3.1/src/plugins/generator/visualstudio/msbuildsharedsolutionpropertiesproject.h0000644000175100017510000000420615232633614031776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H #define MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildSharedSolutionPropertiesProject : public MSBuildProject { public: MSBuildSharedSolutionPropertiesProject(const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir); }; } // namespace qbs #endif // MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H qbs-src-3.3.1/src/plugins/generator/keiluv/0000755000175100017510000000000015232633614020240 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h0000644000175100017510000000405215232633614027056 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVFILESGROUPSPROPERTYGROUP_H #define QBS_KEILUVFILESGROUPSPROPERTYGROUP_H #include #include namespace qbs { class KeiluvFilesGroupsPropertyGroup final : public gen::xml::PropertyGroup { public: explicit KeiluvFilesGroupsPropertyGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps); }; } // namespace qbs #endif // QBS_KEILUVFILESGROUPSPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp0000644000175100017510000000445315232633614025425 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvworkspacewriter.h" namespace qbs { KeiluvWorkspaceWriter::KeiluvWorkspaceWriter(std::ostream *device) : gen::xml::WorkspaceWriter(device) { } void KeiluvWorkspaceWriter::visitWorkspaceStart(const gen::xml::Workspace *workspace) { Q_UNUSED(workspace) writer()->writeStartElement(QStringLiteral("ProjectWorkspace")); writer()->writeAttribute( QStringLiteral("xmlns:xsi"), QStringLiteral("http://www.w3.org/2001/XMLSchema-instance")); writer()->writeAttribute( QStringLiteral("xsi:noNamespaceSchemaLocation"), QStringLiteral("project_mpw.xsd")); } void KeiluvWorkspaceWriter::visitWorkspaceEnd(const gen::xml::Workspace *workspace) { Q_UNUSED(workspace) writer()->writeEndElement(); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvworkspace.cpp0000644000175100017510000000546115232633614024170 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "keiluvworkspace.h" #include namespace qbs { KeiluvWorkspace::KeiluvWorkspace(const QString &workspacePath) : gen::xml::Workspace(workspacePath) { // Construct schema version item. appendChild(QByteArrayLiteral("SchemaVersion"), QStringLiteral("1.0")); // Construct workspace name item. appendChild(QByteArrayLiteral("WorkspaceName"), QStringLiteral("WorkSpace")); } void KeiluvWorkspace::addProject(const QString &projectFilePath) { const QString relativeProjectPath = QDir::toNativeSeparators( m_baseDirectory.relativeFilePath(projectFilePath)); const auto projectGroup = appendChild( QByteArrayLiteral("project")); projectGroup->appendProperty("PathAndName", relativeProjectPath); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp0000644000175100017510000000522215232633614025372 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "keiluvgenerator.h" #include "keiluvversioninfo.h" #include #include static void QbsKeiluvGeneratorPluginLoad() { for (const auto &info : qbs::KeiluvVersionInfo::knownVersions) { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared(info)); } } static void QbsKeiluvGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, keiluvgenerator, QbsKeiluvGeneratorPluginLoad, QbsKeiluvGeneratorPluginUnload) qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvproject.h0000644000175100017510000000413215232633614023277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVPROJECT_H #define QBS_KEILUVPROJECT_H #include #include #include #include namespace qbs { class KeiluvProject final : public gen::xml::Project { public: explicit KeiluvProject( const qbs::GeneratableProject &genProject, const qbs::GeneratableProductData &genProduct, const gen::VersionInfo &versionInfo); private: std::vector> m_factories; }; } // namespace qbs #endif // QBS_KEILUVPROJECT_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp0000644000175100017510000001637015232633614027417 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvfilesgroupspropertygroup.h" #include "keiluvutils.h" #include #include #include namespace qbs { class KeiluvFilePropertyGroup final : public gen::xml::PropertyGroup { public: explicit KeiluvFilePropertyGroup( const QString &fullFilePath, const QString &baseDirectory) : gen::xml::PropertyGroup("File") { const QFileInfo fileInfo(fullFilePath); const auto fileName = fileInfo.fileName(); const auto fileType = encodeFileType(fileInfo.suffix()); const auto filePath = QDir::toNativeSeparators( gen::utils::relativeFilePath( baseDirectory, fileInfo.absoluteFilePath())); appendChild(QByteArrayLiteral("FileName"), fileName); appendChild(QByteArrayLiteral("FileType"), fileType); appendChild(QByteArrayLiteral("FilePath"), filePath); } private: enum FileType { UnknownFileType = 0, CSourceFileType = 1, AssemblerFileType = 2, LibraryFileType = 4, TextFileType = 5, CppSourceFileType = 8, }; static FileType encodeFileType(const QString &fileSuffix) { if (fileSuffix.compare(QLatin1String("c"), Qt::CaseInsensitive) == 0) { return CSourceFileType; } if (fileSuffix.compare(QLatin1String("cpp"), Qt::CaseInsensitive) == 0) { return CppSourceFileType; } if (fileSuffix.compare(QLatin1String("s"), Qt::CaseInsensitive) == 0 || fileSuffix.compare(QLatin1String("a51"), Qt::CaseInsensitive) == 0) { return AssemblerFileType; } if (fileSuffix.compare(QLatin1String("lib"), Qt::CaseInsensitive) == 0) { return LibraryFileType; } // All header files, text files and include files // interpretes as a text file types. return TextFileType; } }; class KeiluvFilesPropertyGroup final : public gen::xml::PropertyGroup { public: explicit KeiluvFilesPropertyGroup( const QList &sourceArtifacts, const QString &baseDirectory) : gen::xml::PropertyGroup("Files") { for (const auto &artifact : sourceArtifacts) appendChild(artifact.filePath(), baseDirectory); } explicit KeiluvFilesPropertyGroup( const QStringList &filePaths, const QString &baseDirectory) : gen::xml::PropertyGroup("Files") { for (const auto &filePath : filePaths) appendChild(filePath, baseDirectory); } }; class KeiluvFileGroupPropertyGroup final : public gen::xml::PropertyGroup { public: explicit KeiluvFileGroupPropertyGroup( const QString &groupName, const QList &sourceArtifacts, const QString &baseDirectory) : gen::xml::PropertyGroup("Group") { appendChild(QByteArrayLiteral("GroupName"), groupName); appendChild(sourceArtifacts, baseDirectory); } explicit KeiluvFileGroupPropertyGroup( const QString &groupName, const QStringList &filePaths, const QString &baseDirectory) : gen::xml::PropertyGroup("Group") { appendChild(QByteArrayLiteral("GroupName"), groupName); appendChild(filePaths, baseDirectory); } }; KeiluvFilesGroupsPropertyGroup::KeiluvFilesGroupsPropertyGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup(QByteArrayLiteral("Groups")) { const auto baseDirectory = gen::utils::buildRootPath(qbsProject); // Build source items. for (const auto &group : qbsProduct.groups()) { // Ignore disabled groups (e.g. when its condition property is false). if (!group.isEnabled()) continue; auto sourceArtifacts = group.sourceArtifacts(); // Remove the linker script artifacts. Internal::removeIf(sourceArtifacts, [](const auto &artifact){ const auto tags = artifact.fileTags(); return tags.contains(QLatin1String("linkerscript")); }); if (sourceArtifacts.isEmpty()) continue; appendChild( group.name(), sourceArtifacts, baseDirectory); } // Build local static library items. const auto &qbsProps = qbsProduct.moduleProperties(); const auto staticLibs = KeiluvUtils::staticLibraries(qbsProps); if (!staticLibs.isEmpty()) { appendChild( QStringLiteral("Static Libs"), staticLibs, baseDirectory); } // Build dependency library items. const auto deps = KeiluvUtils::dependencies(qbsProductDeps); if (!deps.isEmpty()) { appendChild( QStringLiteral("Dependencies"), deps, baseDirectory); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/CMakeLists.txt0000644000175100017510000000423115232633614023000 0ustar runnerrunnerset(COMMON_SOURCES keiluvfilesgroupspropertygroup.cpp keiluvfilesgroupspropertygroup.h keiluvgenerator.cpp keiluvgenerator.h keiluvgeneratorplugin.cpp keiluvproject.cpp keiluvproject.h keiluvprojectwriter.cpp keiluvprojectwriter.h keiluvutils.cpp keiluvutils.h keiluvversioninfo.h keiluvworkspace.cpp keiluvworkspace.h keiluvworkspacewriter.cpp keiluvworkspacewriter.h ) set(ARCHS_ARM_SOURCES armbuildtargetgroup_v5.cpp armbuildtargetgroup_v5.h armcommonpropertygroup_v5.cpp armcommonpropertygroup_v5.h armdebugoptiongroup_v5.cpp armdebugoptiongroup_v5.h armdlloptiongroup_v5.cpp armdlloptiongroup_v5.h armtargetassemblergroup_v5.cpp armtargetassemblergroup_v5.h armtargetcommonoptionsgroup_v5.cpp armtargetcommonoptionsgroup_v5.h armtargetcompilergroup_v5.cpp armtargetcompilergroup_v5.h armtargetgroup_v5.cpp armtargetgroup_v5.h armtargetlinkergroup_v5.cpp armtargetlinkergroup_v5.h armtargetmiscgroup_v5.cpp armtargetmiscgroup_v5.h armutilitiesgroup_v5.cpp armutilitiesgroup_v5.h ) list_transform_prepend(ARCHS_ARM_SOURCES archs/arm/) set(ARCHS_MCS51_SOURCES mcs51buildtargetgroup_v5.cpp mcs51buildtargetgroup_v5.h mcs51commonpropertygroup_v5.cpp mcs51commonpropertygroup_v5.h mcs51debugoptiongroup_v5.cpp mcs51debugoptiongroup_v5.h mcs51dlloptiongroup_v5.cpp mcs51dlloptiongroup_v5.h mcs51targetassemblergroup_v5.cpp mcs51targetassemblergroup_v5.h mcs51targetcommonoptionsgroup_v5.cpp mcs51targetcommonoptionsgroup_v5.h mcs51targetcompilergroup_v5.cpp mcs51targetcompilergroup_v5.h mcs51targetgroup_v5.cpp mcs51targetgroup_v5.h mcs51targetlinkergroup_v5.cpp mcs51targetlinkergroup_v5.h mcs51targetmiscgroup_v5.cpp mcs51targetmiscgroup_v5.h mcs51utilitiesgroup_v5.cpp mcs51utilitiesgroup_v5.h mcs51utils.cpp mcs51utils.h ) list_transform_prepend(ARCHS_MCS51_SOURCES archs/mcs51/) add_qbs_plugin(keiluvgenerator DEPENDS qbscore SOURCES ${COMMON_SOURCES} ${ARCHS_ARM_SOURCES} ${ARCHS_MCS51_SOURCES} ) qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvprojectwriter.h0000644000175100017510000000376415232633614024546 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVPROJECTWRITER_H #define QBS_KEILUVPROJECTWRITER_H #include namespace qbs { class KeiluvProjectWriter final : public gen::xml::ProjectWriter { Q_DISABLE_COPY(KeiluvProjectWriter) public: explicit KeiluvProjectWriter(std::ostream *device); private: void visitProjectStart(const gen::xml::Project *project) final; void visitProjectEnd(const gen::xml::Project *project) final; }; } // namespace qbs #endif // QBS_KEILUVPROJECTWRITER_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluv.qbs0000644000175100017510000000557515232633614022262 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "keiluvgenerator" files: ["keiluvgeneratorplugin.cpp"] Group { name: "KEIL UV generator common" files: [ "keiluvfilesgroupspropertygroup.cpp", "keiluvfilesgroupspropertygroup.h", "keiluvgenerator.cpp", "keiluvgenerator.h", "keiluvproject.cpp", "keiluvproject.h", "keiluvprojectwriter.cpp", "keiluvprojectwriter.h", "keiluvutils.cpp", "keiluvutils.h", "keiluvversioninfo.h", "keiluvworkspace.cpp", "keiluvworkspace.h", "keiluvworkspacewriter.cpp", "keiluvworkspacewriter.h", ] } Group { name: "KEIL UV generator for MCS51" prefix: "archs/mcs51/" files: [ "mcs51buildtargetgroup_v5.cpp", "mcs51buildtargetgroup_v5.h", "mcs51commonpropertygroup_v5.cpp", "mcs51commonpropertygroup_v5.h", "mcs51debugoptiongroup_v5.cpp", "mcs51debugoptiongroup_v5.h", "mcs51dlloptiongroup_v5.cpp", "mcs51dlloptiongroup_v5.h", "mcs51targetassemblergroup_v5.cpp", "mcs51targetassemblergroup_v5.h", "mcs51targetcommonoptionsgroup_v5.cpp", "mcs51targetcommonoptionsgroup_v5.h", "mcs51targetcompilergroup_v5.cpp", "mcs51targetcompilergroup_v5.h", "mcs51targetgroup_v5.cpp", "mcs51targetgroup_v5.h", "mcs51targetlinkergroup_v5.cpp", "mcs51targetlinkergroup_v5.h", "mcs51targetmiscgroup_v5.cpp", "mcs51targetmiscgroup_v5.h", "mcs51utilitiesgroup_v5.cpp", "mcs51utilitiesgroup_v5.h", "mcs51utils.cpp", "mcs51utils.h", ] } Group { name: "KEIL UV generator for ARM" prefix: "archs/arm/" files: [ "armbuildtargetgroup_v5.cpp", "armbuildtargetgroup_v5.h", "armcommonpropertygroup_v5.cpp", "armcommonpropertygroup_v5.h", "armdebugoptiongroup_v5.cpp", "armdebugoptiongroup_v5.h", "armdlloptiongroup_v5.cpp", "armdlloptiongroup_v5.h", "armtargetassemblergroup_v5.cpp", "armtargetassemblergroup_v5.h", "armtargetcommonoptionsgroup_v5.cpp", "armtargetcommonoptionsgroup_v5.h", "armtargetcompilergroup_v5.cpp", "armtargetcompilergroup_v5.h", "armtargetgroup_v5.cpp", "armtargetgroup_v5.h", "armtargetlinkergroup_v5.cpp", "armtargetlinkergroup_v5.h", "armtargetmiscgroup_v5.cpp", "armtargetmiscgroup_v5.h", "armutilitiesgroup_v5.cpp", "armutilitiesgroup_v5.h", ] } } qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvgenerator.cpp0000644000175100017510000001240215232633614024151 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvgenerator.h" #include "keiluvproject.h" #include "keiluvprojectwriter.h" #include "keiluvworkspace.h" #include "keiluvworkspacewriter.h" #include #include #include #include #include namespace qbs { static void writeProjectFiles(const std::map> &projects, const Internal::Logger &logger) { for (const auto &item : projects) { const QString projectFilePath = item.first; Internal::FileSaver file(projectFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") .arg(projectFilePath)); std::shared_ptr project = item.second; KeiluvProjectWriter writer(file.device()); if (!(writer.write(project.get()) && file.commit())) throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") .arg(projectFilePath)); logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( QFileInfo(projectFilePath).fileName()); } } static void writeWorkspace(const std::shared_ptr &wokspace, const QString &workspaceFilePath, const Internal::Logger &logger) { Internal::FileSaver file(workspaceFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") .arg(workspaceFilePath)); KeiluvWorkspaceWriter writer(file.device()); if (!(writer.write(wokspace.get()) && file.commit())) throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") .arg(workspaceFilePath)); logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( QFileInfo(workspaceFilePath).fileName()); } KeiluvGenerator::KeiluvGenerator(const gen::VersionInfo &versionInfo) : m_versionInfo(versionInfo) { } QString KeiluvGenerator::generatorName() const { return QStringLiteral("keiluv%1").arg(m_versionInfo.marketingVersion()); } void KeiluvGenerator::reset() { m_workspace.reset(); m_workspaceFilePath.clear(); m_projects.clear(); } void KeiluvGenerator::generate() { GeneratableProjectIterator it(project()); it.accept(this); writeProjectFiles(m_projects, logger()); writeWorkspace(m_workspace, m_workspaceFilePath, logger()); reset(); } void KeiluvGenerator::visitProject(const GeneratableProject &project) { const QDir buildDir = project.baseBuildDirectory(); m_workspaceFilePath = buildDir.absoluteFilePath( project.name() + QStringLiteral(".uvmpw")); m_workspace = std::make_shared(m_workspaceFilePath); } void KeiluvGenerator::visitProjectData( const GeneratableProject &project, const GeneratableProjectData &projectData) { Q_UNUSED(project) Q_UNUSED(projectData) } void KeiluvGenerator::visitProduct( const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) { Q_UNUSED(projectData); const QDir baseBuildDir(project.baseBuildDirectory().absolutePath()); const QString projFileName = productData.name() + QLatin1String(".uvprojx"); const QString projectFilePath = baseBuildDir.absoluteFilePath(projFileName); const auto targetProject = std::make_shared( project, productData, m_versionInfo); m_projects.insert({projectFilePath, targetProject}); m_workspace->addProject(projectFilePath); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvversioninfo.h0000644000175100017510000000454615232633614024203 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_KEILUVVERSIONINFO_H #define QBS_KEILUVVERSIONINFO_H #include "keiluvconstants.h" #include #include namespace qbs { namespace KeiluvVersionInfo { constexpr gen::VersionInfo knownVersions[] = { {Version(KeiluvConstants::v5::kUVisionVersion), {gen::utils::Architecture::Mcs51, gen::utils::Architecture::Arm}}, }; } // namespace KeiluvVersionInfo } // namespace qbs #endif // QBS_KEILUVVERSIONINFO_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvproject.cpp0000644000175100017510000001153715232633614023641 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvconstants.h" #include "keiluvproject.h" #include "keiluvutils.h" #include "keiluvversioninfo.h" #include "archs/mcs51/mcs51buildtargetgroup_v5.h" #include "archs/arm/armbuildtargetgroup_v5.h" #include namespace qbs { static QString keilProjectSchema(const gen::VersionInfo &info) { const auto v = info.marketingVersion(); switch (v) { case KeiluvConstants::v5::kUVisionVersion: return QStringLiteral("2.1"); default: return {}; } } KeiluvProject::KeiluvProject(const qbs::GeneratableProject &genProject, const qbs::GeneratableProductData &genProduct, const gen::VersionInfo &versionInfo) { Q_ASSERT(genProject.projects.size() == genProject.commandLines.size()); Q_ASSERT(genProject.projects.size() == genProduct.data.size()); // Create available configuration group factories. m_factories.push_back(std::make_unique< keiluv::mcs51::v5::Mcs51BuildTargetGroupFactory>()); m_factories.push_back(std::make_unique< keiluv::arm::v5::ArmBuildTargetGroupFactory>()); // Construct schema version item (is it depends on a project version?). const auto schema = keilProjectSchema(versionInfo); appendChild(QByteArrayLiteral("SchemaVersion"), schema); // Construct targets group. const auto targetsGroup = appendChild( QByteArrayLiteral("Targets")); // Construct all build target items. const int configsCount = std::max(genProject.projects.size(), genProduct.data.size()); for (auto configIndex = 0; configIndex < configsCount; ++configIndex) { const qbs::Project qbsProject = genProject.projects .values().at(configIndex); const qbs::ProductData qbsProduct = genProduct.data .values().at(configIndex); const QString confName = gen::utils::buildConfigurationName(qbsProject); const std::vector qbsProductDeps = gen::utils::dependenciesOf (qbsProduct, genProject, confName); const auto arch = gen::utils::architecture(qbsProject); if (arch == gen::utils::Architecture::Unknown) throw ErrorInfo(Internal::Tr::tr("Target architecture is not set," " please use the 'profile' option")); // Construct the build target item, which are depend from // the architecture and the version. const auto factoryEnd = m_factories.cend(); const auto factoryIt = std::find_if(m_factories.cbegin(), factoryEnd, [arch, versionInfo](const auto &factory) { return factory->canCreate(arch, versionInfo.version()); }); if (factoryIt == factoryEnd) { throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'" " for KEIL UV version %2") .arg(gen::utils::architectureName(arch)) .arg(versionInfo.marketingVersion())); } auto targetGroup = (*factoryIt)->create( qbsProject, qbsProduct, qbsProductDeps); targetsGroup->appendChild(std::move(targetGroup)); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvgenerator.h0000644000175100017510000000520215232633614023616 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVGENERATOR_H #define QBS_KEILUVGENERATOR_H #include "keiluvversioninfo.h" #include #include namespace qbs { class KeiluvProject; class KeiluvWorkspace; class KeiluvGenerator final : public ProjectGenerator, private IGeneratableProjectVisitor { public: explicit KeiluvGenerator(const gen::VersionInfo &versionInfo); QString generatorName() const final; void generate() final; private: void reset(); void visitProject(const GeneratableProject &project) final; void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) final; void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) final; const gen::VersionInfo m_versionInfo; std::shared_ptr m_workspace; QString m_workspaceFilePath; std::map> m_projects; }; } // namespace qbs #endif // QBS_KEILUVGENERATOR_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvworkspacewriter.h0000644000175100017510000000402015232633614025060 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVWORKSPACEWRITER_H #define QBS_KEILUVWORKSPACEWRITER_H #include namespace qbs { class KeiluvWorkspaceWriter final : public gen::xml::WorkspaceWriter { Q_DISABLE_COPY(KeiluvWorkspaceWriter) public: explicit KeiluvWorkspaceWriter(std::ostream *device); private: void visitWorkspaceStart(const gen::xml::Workspace *workspace) final; void visitWorkspaceEnd(const gen::xml::Workspace *workspace) final; }; } // namespace qbs #endif // QBS_KEILUVWORKSPACEWRITER_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/0000755000175100017510000000000015232633614021340 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/0000755000175100017510000000000015232633614022117 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.cpp0000644000175100017510000001742715232633614031140 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetcommonoptionsgroup_v5.h" #include "../../keiluvutils.h" #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { namespace { const struct DeviceEntry { QByteArray cpu; // CPU option. std::set fpus; // FPU's options. QByteArray device; // Project file entry. } deviceDict[] = { {"8-M.Base", {}, "ARMv8MBL"}, {"8-M.Main", {"FPv5-SP"}, "ARMv8MML_SP"}, {"8-M.Main", {"FPv5_D16"}, "ARMv8MML_DP"}, {"8-M.Main", {"SoftVFP"},"ARMv8MML"}, {"8-M.Main.dsp", {"FPv5-SP"}, "ARMv8MML_DSP_SP"}, {"8-M.Main.dsp", {"FPv5_D16"}, "ARMv8MML_DSP_DP"}, {"8-M.Main.dsp", {"SoftVFP"}, "ARMv8MML_DSP"}, {"Cortex-M0", {}, "ARMCM0"}, {"Cortex-M0+", {}, "ARMCM0P"}, {"Cortex-M0plus", {}, "ARMCM0P"}, {"Cortex-M23", {}, "ARMCM23"}, // same as ARMCM23_TZ {"Cortex-M3", {}, "ARMCM3"}, {"Cortex-M4", {}, "ARMCM4"}, {"Cortex-M4.fp", {}, "ARMCM4_FP"}, {"Cortex-M7", {"SoftVFP"}, "ARMCM7"}, {"Cortex-M7.fp.dp", {}, "ARMCM7_DP"}, {"Cortex-M7.fp.sp", {}, "ARMCM7_SP"}, {"SC000", {}, "ARMSC000"}, {"SC300", {}, "ARMSC300"}, {"Cortex-M33.no_dsp", {"SoftVFP"}, "ARMCM33"}, // same as ARMCM33_TZ {"Cortex-M33", {"FPv5-SP", "softvfp+vfpv2"}, "ARMCM33_DSP_FP"}, // same as ARMCM33_DSP_FP_TZ }; struct CommonPageOptions final { explicit CommonPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = KeiluvUtils::cppModuleCompilerFlags(qbsProps); // Browse information. // ??? // Debug information. debugInfo = gen::utils::debugInformation(qbsProduct); // Output parameters. executableName = gen::utils::targetBinary(qbsProduct); // Fix output binary name if it is a library. Because // the IDE appends an additional suffix (.LIB) to end // of an output library name. if (executableName.endsWith(QLatin1String(".lib"))) executableName = qbsProduct.targetName(); const QString baseDirectory = gen::utils::buildRootPath(qbsProject); objectDirectory = QDir::toNativeSeparators( gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct)); listingDirectory = QDir::toNativeSeparators( gen::utils::listingOutputDirectory( baseDirectory, qbsProduct)); // Target type. targetType = KeiluvUtils::outputBinaryType(qbsProduct); // Detect the device name from the command line options // (like --cpu and --fpu). const auto cpu = gen::utils::firstFlagValue( flags, QStringLiteral("--cpu")).toLatin1(); const auto fpus = gen::utils::allFlagValues( flags, QStringLiteral("--fpu")); for (const auto &deviceEntry : deviceDict) { // Since Qt 5.12 we can use QByteArray::compare(..., Qt::CaseInsensitive) // instead. if (cpu.toLower() != deviceEntry.cpu.toLower()) continue; size_t fpuMatches = 0; const auto dictFpuBegin = std::cbegin(deviceDict->fpus); const auto dictFpuEnd = std::cend(deviceDict->fpus); for (const auto &fpu : fpus) { const auto dictFpuIt = std::find_if( dictFpuBegin, dictFpuEnd, [fpu](const QByteArray &dictFpu) { return fpu.compare(QString::fromLatin1(dictFpu), Qt::CaseInsensitive) == 0; }); if (dictFpuIt != dictFpuEnd) ++fpuMatches; } if (fpuMatches < deviceEntry.fpus.size()) continue; deviceName = QString::fromLatin1(deviceEntry.device); cpuType = QString::fromLatin1(deviceEntry.cpu); break; } } int debugInfo = false; int browseInfo = false; QString deviceName; QString cpuType; QString executableName; QString objectDirectory; QString listingDirectory; KeiluvUtils::OutputBinaryType targetType = KeiluvUtils::ApplicationOutputType; }; } // namespace ArmTargetCommonOptionsGroup::ArmTargetCommonOptionsGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("TargetCommonOption") { const CommonPageOptions opts(qbsProject, qbsProduct); // Fill device items. appendProperty(QByteArrayLiteral("Device"), opts.deviceName); appendProperty(QByteArrayLiteral("Vendor"), QByteArrayLiteral("ARM")); appendProperty(QByteArrayLiteral("PackID"), QByteArrayLiteral("ARM.CMSIS.5.6.0")); appendProperty(QByteArrayLiteral("PackURL"), QByteArrayLiteral("http://www.keil.com/pack/")); const auto cpuType = QStringLiteral("CPUTYPE(\"%1\")") .arg(opts.cpuType); appendProperty(QByteArrayLiteral("Cpu"), cpuType); // Add 'Debug Information' item. appendProperty(QByteArrayLiteral("DebugInformation"), opts.debugInfo); // Add 'Browse Information' item. appendProperty(QByteArrayLiteral("BrowseInformation"), opts.browseInfo); // Add 'Name of Executable'. appendProperty(QByteArrayLiteral("OutputName"), opts.executableName); // Add 'Output objects directory'. appendProperty(QByteArrayLiteral("OutputDirectory"), opts.objectDirectory); // Add 'Output listing directory'. appendProperty(QByteArrayLiteral("ListingPath"), opts.listingDirectory); // Add 'Create Executable/Library' item. const int isExecutable = (opts.targetType == KeiluvUtils::ApplicationOutputType); const int isLibrary = (opts.targetType == KeiluvUtils::LibraryOutputType); appendProperty(QByteArrayLiteral("CreateExecutable"), isExecutable); appendProperty(QByteArrayLiteral("CreateLib"), isLibrary); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.h0000644000175100017510000000400115232633614026456 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMDLLOPTIONGROUP_V5_H #define QBS_KEILUVARMDLLOPTIONGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmDllOptionGroup final : public gen::xml::PropertyGroup { public: explicit ArmDllOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMDLLOPTIONGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.h0000644000175100017510000000505215232633614026767 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMBUILDTARGETGROUP_V5_H #define QBS_KEILUVARMBUILDTARGETGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmBuildTargetGroup final : public gen::xml::PropertyGroup { private: explicit ArmBuildTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class ArmBuildTargetGroupFactory; }; class ArmBuildTargetGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMBUILDTARGETGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.cpp0000644000175100017510000002114115232633614030032 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetcompilergroup_v5.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { namespace { struct CompilerPageOptions final { enum WarningLevel { WarningLevelUnspecified = 0, WarningLevelNone, WarningLevelAll }; enum OptimizationLevel { OptimizationLevelUnspecified = 0, OptimizationLevelNone, OptimizationLevelOne, OptimizationLevelTwo, OptimizationLevelThree, }; explicit CompilerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); // Warning levels. const QString wLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (wLevel == QLatin1String("none")) warningLevel = WarningLevelNone; else if (wLevel == QLatin1String("all")) warningLevel = WarningLevelAll; else warningLevel = WarningLevelUnspecified; // Generation code. generateExecuteOnlyCode = flags.contains(QLatin1String("--execute_only")); // Optimization levels. const QString oLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (oLevel == QLatin1String("fast")) enableTimeOptimization = 1; else if (oLevel == QLatin1String("small")) optimizationLevel = OptimizationLevelThree; else if (oLevel == QLatin1String("none")) optimizationLevel = OptimizationLevelNone; // Split load and store multiple. splitLdm = flags.contains(QLatin1String("--split_ldm")); // One ELF section per function. splitSections = flags.contains(QLatin1String("--split_sections")); // String ANSI C. useStrictAnsiC = flags.contains(QLatin1String("--strict")); // Enum container always int. forceEnumAsInt = flags.contains(QLatin1String("--enum_is_int")); // Plain char is signed. useSignedChar = flags.contains(QLatin1String("--signed_chars")); // Read-only position independent. enableRopi = flags.contains(QLatin1String("/ropi")); // Read-write position independent. enableRwpi = flags.contains(QLatin1String("/rwpi")); // C-language version. const QString clVersion = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("cLanguageVersion")); // C99 mode. useC99Language = clVersion.contains(QLatin1String("c99")); // Define symbols. defineSymbols = qbs::KeiluvUtils::defines(qbsProps); // Include paths. includePaths = qbs::KeiluvUtils::includes(qbsProps); // Interpret other compiler flags as a misc controls (exclude only // that flags which are was already handled). for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (flagIt->contains(QLatin1String("--execute_only")) || flagIt->contains(QLatin1String("--split_ldm")) || flagIt->contains(QLatin1String("--split_sections")) || flagIt->contains(QLatin1String("--strict")) || flagIt->contains(QLatin1String("--enum_is_int")) || flagIt->contains(QLatin1String("--signed_chars")) || flagIt->contains(QLatin1String("/ropi")) || flagIt->contains(QLatin1String("/rwpi")) || flagIt->contains(QLatin1String("--c99")) ) { continue; } if (flagIt->startsWith(QLatin1String("-O")) || flagIt->startsWith(QLatin1String("-W")) || flagIt->startsWith(QLatin1String("-D")) || flagIt->startsWith(QLatin1String("-I")) || flagIt->startsWith(QLatin1String("--cpu")) || flagIt->startsWith(QLatin1String("--fpu")) ) { ++flagIt; continue; } miscControls.push_back(*flagIt); } } WarningLevel warningLevel = WarningLevelAll; OptimizationLevel optimizationLevel = OptimizationLevelUnspecified; int enableTimeOptimization = 0; int generateExecuteOnlyCode = 0; int splitLdm = 0; int splitSections = 0; int useStrictAnsiC = 0; int forceEnumAsInt = 0; int useSignedChar = 0; int enableRopi = 0; int enableRwpi = 0; int useC99Language = 0; QStringList defineSymbols; QStringList includePaths; QStringList miscControls; }; } // namespace ArmTargetCompilerGroup::ArmTargetCompilerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Cads") { const CompilerPageOptions opts(qbsProject, qbsProduct); // Add 'Code Optimization' items. appendProperty(QByteArrayLiteral("Optim"), opts.optimizationLevel); appendProperty(QByteArrayLiteral("oTime"), opts.enableTimeOptimization); // Add 'Slpit LDM' item. appendProperty(QByteArrayLiteral("SplitLS"), opts.splitLdm); // Add 'Slpit sections' item. appendProperty(QByteArrayLiteral("OneElfS"), opts.splitSections); // Add 'Strict ANSI C' item. appendProperty(QByteArrayLiteral("Strict"), opts.useStrictAnsiC); // Add 'Enums as int' item. appendProperty(QByteArrayLiteral("EnumInt"), opts.forceEnumAsInt); // Add 'Plain char as signed' item. appendProperty(QByteArrayLiteral("PlainCh"), opts.useSignedChar); // Add 'ROPI' item. appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); // Add 'RWPI' item. appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); // Add 'Warnings' item. appendProperty(QByteArrayLiteral("wLevel"), opts.warningLevel); // Add 'Use C99' item. appendProperty(QByteArrayLiteral("uC99"), opts.useC99Language); // Add 'Generate code exedutable only' item. appendProperty(QByteArrayLiteral("useXo"), opts.generateExecuteOnlyCode); // Add other various controls. // Note: A sub-items order makes sense! const auto variousControlsGroup = appendChild( QByteArrayLiteral("VariousControls")); // Add 'Misc Controls' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("MiscControls"), opts.miscControls, QLatin1Char(' ')); // Add 'Define' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("Define"), opts.defineSymbols); // Add an empty 'Undefine' item. variousControlsGroup->appendProperty( QByteArrayLiteral("Undefine"), {}); // Add 'Include Paths' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("IncludePath"), opts.includePaths, QLatin1Char(';')); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.cpp0000644000175100017510000001422615232633614027512 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetlinkergroup_v5.h" #include "../../keiluvutils.h" #include #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { namespace { struct LinkerPageOptions final { explicit LinkerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleLinkerFlags(qbsProps); // Read-only position independent. enableRopi = flags.contains(QLatin1String("--ropi")); // Read-write position independent. enableRwpi = flags.contains(QLatin1String("--rwpi")); // Don't search standard libraries. dontSearchLibs = flags.contains(QLatin1String("--noscanlib")); // Report 'might fail' conditions as errors. enableReportMightFail = flags.contains(QLatin1String("--strict")); QStringList scatterFiles; // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { if (!qbsGroup.isEnabled()) continue; const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString scatterFile = QFileInfo(qbsArtifact.filePath()) .absoluteFilePath(); scatterFiles.push_back(scatterFile); } } // Enumerate all scatter files // (which are set trough '--scatter' option). const QStringList scatters = gen::utils::allFlagValues( flags, QStringLiteral("--scatter")); for (const auto &scatter : scatters) { const QString scatterFile = QFileInfo(scatter) .absoluteFilePath(); if (!scatterFiles.contains(scatterFile)) scatterFiles.push_back(scatterFile); } // Transform all paths to relative. const QString baseDirectory = qbs::gen::utils::buildRootPath(qbsProject); Internal::transform(scatterFiles, [&baseDirectory](const auto &file) { return gen::utils::relativeFilePath(baseDirectory, file); }); // Make a first scatter file as a main scatter file. // Other scatter files will be interpretes as a misc controls. if (scatterFiles.count() > 0) mainScatterFile = scatterFiles.takeFirst(); for (const auto &scatterFile : std::as_const(scatterFiles)) { const auto control = QStringLiteral("--scatter %1").arg(scatterFile); miscControls.push_back(control); } // Interpret other compiler flags as a misc controls (exclude only // that flags which are was already handled). for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (flagIt->contains(QLatin1String("--ropi")) || flagIt->contains(QLatin1String("--rwpi")) || flagIt->contains(QLatin1String("--noscanlib")) || flagIt->contains(QLatin1String("--strict")) ) { continue; } if (flagIt->startsWith(QLatin1String("--scatter")) ) { ++flagIt; continue; } miscControls.push_back(*flagIt); } } int enableRopi = 0; int enableRwpi = 0; int dontSearchLibs = 0; int enableReportMightFail = 0; QString mainScatterFile; QStringList miscControls; }; } // namespace ArmTargetLinkerGroup::ArmTargetLinkerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("LDads") { const LinkerPageOptions opts(qbsProject, qbsProduct); // Add 'ROPI' item. appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); // Add 'RWPI' item. appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); // Add 'Don't search standard libraries' item. appendProperty(QByteArrayLiteral("noStLib"), opts.dontSearchLibs); // Add 'Report might fail' item. appendProperty(QByteArrayLiteral("RepFail"), opts.enableReportMightFail); // Add 'Scatter file' item. appendProperty(QByteArrayLiteral("ScatterFile"), QDir::toNativeSeparators(opts.mainScatterFile)); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.cpp0000644000175100017510000001367515232633614030212 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetassemblergroup_v5.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { namespace { struct AssemblerPageOptions final { explicit AssemblerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleAssemblerFlags(qbsProps); // Read-only position independent. enableRopi = flags.contains(QLatin1String("/ropi")); // Read-write position independent. enableRwpi = flags.contains(QLatin1String("/rwpi")); // Enable thumb mode. enableThumbMode = flags.contains(QLatin1String("--16")); // Split load and store multiple. splitLdm = flags.contains(QLatin1String("--split_ldm")); // Generation code. generateExecuteOnlyCode = flags.contains(QLatin1String("--execute_only")); // Warning levels. const QString wLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); disableWarnings = wLevel == QLatin1String("none"); // Define symbols. defineSymbols = qbs::KeiluvUtils::defines(qbsProps); // Include paths. includePaths = qbs::KeiluvUtils::includes(qbsProps); // Interpret other compiler flags as a misc controls (exclude only // that flags which are was already handled). for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (flagIt->contains(QLatin1String("/ropi")) || flagIt->contains(QLatin1String("/rwpi")) || flagIt->contains(QLatin1String("--16")) || flagIt->contains(QLatin1String("--split_ldm")) || flagIt->contains(QLatin1String("--execute_only")) || flagIt->contains(QLatin1String("--nowarn")) ) { continue; } if (flagIt->startsWith(QLatin1String("-I")) || flagIt->startsWith(QLatin1String("--cpu")) || flagIt->startsWith(QLatin1String("--fpu")) || flagIt->startsWith(QLatin1String("-pd")) ) { ++flagIt; continue; } miscControls.push_back(*flagIt); } } int enableRopi = 0; int enableRwpi = 0; int enableThumbMode = 0; int disableWarnings = 0; int splitLdm = 0; int generateExecuteOnlyCode = 0; QStringList defineSymbols; QStringList includePaths; QStringList miscControls; }; } // namespace ArmTargetAssemblerGroup::ArmTargetAssemblerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Aads") { const AssemblerPageOptions opts(qbsProject, qbsProduct); // Add 'ROPI' item. appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); // Add 'RWPI' item. appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); // Add 'Use thumb mode' item. appendProperty(QByteArrayLiteral("thumb"), opts.enableThumbMode); // Add 'Slpit LDM' item. appendProperty(QByteArrayLiteral("SplitLS"), opts.splitLdm); // Add 'Disable warnings' item. appendProperty(QByteArrayLiteral("NoWarn"), opts.disableWarnings); // Add 'Generate code exedutable only' item. appendProperty(QByteArrayLiteral("useXo"), opts.generateExecuteOnlyCode); // Add other various controls. // Note: A sub-items order makes sense! const auto variousControlsGroup = appendChild( QByteArrayLiteral("VariousControls")); // Add 'Misc Controls' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("MiscControls"), opts.miscControls, QLatin1Char(' ')); // Add 'Define' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("Define"), opts.defineSymbols); // Add an empty 'Undefine' item. variousControlsGroup->appendProperty( QByteArrayLiteral("Undefine"), {}); // Add 'Include Paths' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("IncludePath"), opts.includePaths, QLatin1Char(';')); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.cpp0000644000175100017510000000362515232633614027337 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armdebugoptiongroup_v5.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmDebugOptionGroup::ArmDebugOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("DebugOption") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.cpp0000644000175100017510000000361515232633614027023 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armdlloptiongroup_v5.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmDllOptionGroup::ArmDllOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("DllOption") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.cpp0000644000175100017510000000361515232633614027032 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armutilitiesgroup_v5.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmUtilitiesGroup::ArmUtilitiesGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Utilities") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.h0000644000175100017510000000406315232633614030575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H #define QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetCommonOptionsGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetCommonOptionsGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.cpp0000644000175100017510000000364115232633614030113 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armcommonpropertygroup_v5.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmCommonPropertyGroup::ArmCommonPropertyGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("CommonProperty") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.cpp0000644000175100017510000001046615232633614027327 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armbuildtargetgroup_v5.h" #include "armcommonpropertygroup_v5.h" #include "armdebugoptiongroup_v5.h" #include "armdlloptiongroup_v5.h" #include "armtargetcommonoptionsgroup_v5.h" #include "armtargetgroup_v5.h" #include "armutilitiesgroup_v5.h" #include "../../keiluvconstants.h" #include "../../keiluvfilesgroupspropertygroup.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmBuildTargetGroup::ArmBuildTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("Target") { // Append target name item (it is a build configuration name). const QString targetName = gen::utils::buildConfigurationName( qbsProject); appendProperty(QByteArrayLiteral("TargetName"), targetName); // Append toolset number group item. appendChild(QByteArrayLiteral("ToolsetNumber"), QByteArrayLiteral("0x4")); // Append toolset name group item. appendChild(QByteArrayLiteral("ToolsetName"), QByteArrayLiteral("ARM-ADS")); // Append target option group item. const auto targetOptionGroup = appendChild( QByteArrayLiteral("TargetOption")); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); // Append files group. appendChild(qbsProject, qbsProduct, qbsProductDeps); } bool ArmBuildTargetGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Arm && version.majorVersion() == qbs::KeiluvConstants::v5::kUVisionVersion; } std::unique_ptr ArmBuildTargetGroupFactory::create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new ArmBuildTargetGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.h0000644000175100017510000000402615232633614027556 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMCOMMONPROPERTYGROUP_V5_H #define QBS_KEILUVARMCOMMONPROPERTYGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmCommonPropertyGroup final : public gen::xml::PropertyGroup { public: explicit ArmCommonPropertyGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_MCS51COMMONPROPERTYGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.cpp0000644000175100017510000000435315232633614026305 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetassemblergroup_v5.h" #include "armtargetcompilergroup_v5.h" #include "armtargetgroup_v5.h" #include "armtargetlinkergroup_v5.h" #include "armtargetmiscgroup_v5.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { ArmTargetGroup::ArmTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("TargetArmAds") { appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.h0000644000175100017510000000401315232633614026774 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H #define QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmDebugOptionGroup final : public gen::xml::PropertyGroup { public: explicit ArmDebugOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.cpp0000644000175100017510000000510415232633614027154 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armtargetmiscgroup_v5.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace arm { namespace v5 { namespace { struct MiscPageOptions final { explicit MiscPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); generateLinkerMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")); } int generateLinkerMap = 0; }; } // namespace ArmTargetMiscGroup::ArmTargetMiscGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("ArmAdsMisc") { const MiscPageOptions opts(qbsProject, qbsProduct); // Add 'Generate linker map file' item. appendProperty(QByteArrayLiteral("AdsLLst"), opts.generateLinkerMap); } } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.h0000644000175100017510000000403215232633614027477 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H #define QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetCompilerGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetCompilerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.h0000644000175100017510000000400115232633614026465 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMUTILITIESGROUP_V5_H #define QBS_KEILUVARMUTILITIESGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmUtilitiesGroup final : public gen::xml::PropertyGroup { public: explicit ArmUtilitiesGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMUTILITIESGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.h0000644000175100017510000000403115232633614027641 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 #define QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetAssemblerGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetAssemblerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.h0000644000175100017510000000376215232633614025755 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETGROUP_V5_H #define QBS_KEILUVARMTARGETGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.h0000644000175100017510000000402015232633614027146 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETLINKERGROUP_V5_H #define QBS_KEILUVARMTARGETLINKERGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetLinkerGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetLinkerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETLINKERGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.h0000644000175100017510000000400615232633614026621 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVARMTARGETMISCGROUP_V5_H #define QBS_KEILUVARMTARGETMISCGROUP_V5_H #include namespace qbs { namespace keiluv { namespace arm { namespace v5 { class ArmTargetMiscGroup final : public gen::xml::PropertyGroup { public: explicit ArmTargetMiscGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace arm } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVARMTARGETMISCGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/0000755000175100017510000000000015232633614022270 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp0000644000175100017510000001263415232633614030526 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetassemblergroup_v5.h" #include "mcs51utils.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { namespace { struct AssemblerPageOptions final { explicit AssemblerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleAssemblerFlags(qbsProps); // Don't use standard macro. if (flags.contains(QLatin1String("NOMACRO"), Qt::CaseInsensitive)) useStandardMacroProcessor = false; // Use MPL. if (flags.contains(QLatin1String("MPL"), Qt::CaseInsensitive)) useMacroProcessingLanguage = true; // Define 8051 SFR names. if (flags.contains(QLatin1String("NOMOD51"), Qt::CaseInsensitive)) suppressSfrNames = true; // Define symbols. defineSymbols = qbs::KeiluvUtils::defines(qbsProps); // Include paths. includePaths = qbs::KeiluvUtils::includes(qbsProps); // Interpret other assembler flags as a misc controls (exclude only // that flags which are was already handled). for (const auto &flag : flags) { if (flag.compare(QLatin1String("NOMACRO"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("MACRO"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("NOMPL"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("MPL"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("NOMOD51"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("MOD51"), Qt::CaseInsensitive) == 0 ) { continue; } miscControls.push_back(flag); } } int useStandardMacroProcessor = true; int useMacroProcessingLanguage = false; int suppressSfrNames = false; QStringList defineSymbols; QStringList includePaths; QStringList miscControls; }; } // namespace Mcs51TargetAssemblerGroup::Mcs51TargetAssemblerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Ax51") { const AssemblerPageOptions opts(qbsProject, qbsProduct); // Add 'Macro processor (Standard)' appendProperty(QByteArrayLiteral("UseStandard"), opts.useStandardMacroProcessor); // Add 'Macro processor (MPL)' appendProperty(QByteArrayLiteral("UseMpl"), opts.useMacroProcessingLanguage); // Add 'Define 8051 SFR names' appendProperty(QByteArrayLiteral("UseMod51"), opts.suppressSfrNames); // Add other various controls. // Note: A sub-items order makes sense! const auto variousControlsGroup = appendChild( QByteArrayLiteral("VariousControls")); // Add 'Misc Controls' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("MiscControls"), opts.miscControls, QLatin1Char(' ')); // Add 'Define' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("Define"), opts.defineSymbols); // Add an empty 'Undefine' item. variousControlsGroup->appendProperty( QByteArrayLiteral("Undefine"), {}); // Add 'Include Paths' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("IncludePath"), opts.includePaths, QLatin1Char(';')); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp0000644000175100017510000002300515232633614030027 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetlinkergroup_v5.h" #include "mcs51utils.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { namespace { struct LinkerPageOptions final { explicit LinkerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleLinkerFlags(qbsProps); // Handle all 'BIT' memory flags. parseMemory(flags, QStringLiteral("BIT"), bitAddresses, bitSegments); // Handle all 'CODE' memory flags. parseMemory(flags, QStringLiteral("CODE"), codeAddresses, codeSegments); // Handle all 'DATA' memory flags. parseMemory(flags, QStringLiteral("DATA"), dataAddresses, dataSegments); // Handle all 'IDATA' memory flags. parseMemory(flags, QStringLiteral("IDATA"), idataAddresses, idataSegments); // Handle all 'PDATA' memory flags. parseMemory(flags, QStringLiteral("PDATA"), pdataAddresses, pdataSegments); // Handle all 'XDATA' memory flags. parseMemory(flags, QStringLiteral("XDATA"), xdataAddresses, xdataSegments); // Enumerate all flags in a form like: // 'PRECEDE(foo, bar) PRECEDE(baz)'. const auto precedeValues = KeiluvUtils::flagValues( flags, QStringLiteral("PRECEDE")); for (const auto &precedeValue : precedeValues) { const auto parts = KeiluvUtils::flagValueParts(precedeValue); precedeSegments.reserve(precedeSegments.size() + parts.count()); std::copy(parts.cbegin(), parts.cend(), std::back_inserter(precedeSegments)); } // Enumerate all flags in a form like: // 'STACK(foo, bar) STACK(baz)'. const auto stackValues = KeiluvUtils::flagValues( flags, QStringLiteral("STACK")); for (const auto &stackValue : stackValues) { const auto parts = KeiluvUtils::flagValueParts(stackValue); stackSegments.reserve(stackSegments.size() + parts.count()); std::copy(parts.cbegin(), parts.cend(), std::back_inserter(stackSegments)); } // Interpret other linker flags as a misc controls (exclude only // that flags which are was already handled). for (const auto &flag : flags) { if (flag.startsWith(QLatin1String("BIT"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("CODE"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("DATA"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("IDATA"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("PDATA"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("XDATA"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("PRECEDE"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("STACK"), Qt::CaseInsensitive) ) { continue; } miscControls.push_back(flag); } } static void parseMemory(const QStringList &flags, const QString &flagKey, QStringList &destAddresses, QStringList &destSegments) { // Handle all flags in a form like: // 'FLAGKEY(0x00-0x20, 30, foo, bar(0x40)) FLAGKEY(baz)'. const auto values = KeiluvUtils::flagValues(flags, flagKey); for (const auto &value : values) { const auto parts = KeiluvUtils::flagValueParts(value); for (const auto &part : parts) { if (part.contains(QLatin1Char('-'))) { // Seems, it is an address range. destAddresses.push_back(part); } else { // Check on address (specified in decimal // or hexadecimal form). bool ok = false; part.toInt(&ok, 16); if (!ok) part.toInt(&ok, 10); if (ok) { // Seems, it is just a single address. destAddresses.push_back(part); } else { // Seems it is a segment name. destSegments.push_back(part); } } } } } QStringList bitAddresses; QStringList bitSegments; QStringList codeAddresses; QStringList codeSegments; QStringList dataAddresses; QStringList dataSegments; QStringList idataAddresses; QStringList idataSegments; QStringList pdataAddresses; QStringList pdataSegments; QStringList xdataAddresses; QStringList xdataSegments; QStringList precedeSegments; QStringList stackSegments; QStringList miscControls; }; } // namespace Mcs51TargetLinkerGroup::Mcs51TargetLinkerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Lx51") { const LinkerPageOptions opts(qbsProject, qbsProduct); // Add 'Misc Controls' item. appendMultiLineProperty(QByteArrayLiteral("MiscControls"), opts.miscControls, QLatin1Char(' ')); // Add 'Use Memory Layout from Target Dialog' item. // Note: we always disable it, as we expect that // the layout will be specified from the linker's // command line. appendProperty(QByteArrayLiteral("UseMemoryFromTarget"), 0); // Add 'Bit Range' item. appendMultiLineProperty(QByteArrayLiteral("BitBaseAddress"), opts.bitAddresses); // Add 'Code Range' item. appendMultiLineProperty(QByteArrayLiteral("CodeBaseAddress"), opts.codeAddresses); // Add 'Data Range' item. appendMultiLineProperty(QByteArrayLiteral("DataBaseAddress"), opts.dataAddresses); // Add 'IData Range' item. appendMultiLineProperty(QByteArrayLiteral("IDataBaseAddress"), opts.idataAddresses); // Add 'PData Range' item. appendMultiLineProperty(QByteArrayLiteral("PDataBaseAddress"), opts.pdataAddresses); // Add 'XData Range' item. appendMultiLineProperty(QByteArrayLiteral("XDataBaseAddress"), opts.xdataAddresses); // Add 'Bit Segment' item. appendMultiLineProperty(QByteArrayLiteral("BitSegmentName"), opts.bitSegments); // Add 'Code Segment' item. appendMultiLineProperty(QByteArrayLiteral("CodeSegmentName"), opts.codeSegments); // Add 'Data Segment' item. appendMultiLineProperty(QByteArrayLiteral("DataSegmentName"), opts.dataSegments); // Add 'IData Segment' item. appendMultiLineProperty(QByteArrayLiteral("IDataSegmentName"), opts.idataSegments); // Note: PData has not segments! // Add 'XData Segment' item. appendMultiLineProperty(QByteArrayLiteral("XDataSegmentName"), opts.xdataSegments); // Add 'Precede' item. appendMultiLineProperty(QByteArrayLiteral("Precede"), opts.precedeSegments); // Add 'Stack' item. appendMultiLineProperty(QByteArrayLiteral("Stack"), opts.stackSegments); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp0000644000175100017510000000362715232633614027350 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51dlloptiongroup_v5.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51DllOptionGroup::Mcs51DllOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("DllOption") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h0000644000175100017510000000410115232633614031110 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H #define QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetCommonOptionsGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetCommonOptionsGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h0000644000175100017510000000400015232633614026261 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETGROUP_V5_H #define QBS_KEILUVMCS51TARGETGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h0000644000175100017510000000403115232633614027316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H #define QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51DebugOptionGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51DebugOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp0000644000175100017510000000570215232633614025011 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51utils.h" #include namespace qbs { namespace keiluv { namespace mcs51 { namespace KeiluvUtils { static QString extractValue(const QString &flag) { const auto openBracketIndex = flag.indexOf(QLatin1Char('(')); const auto closeBracketIndex = flag.indexOf(QLatin1Char(')')); const auto n = closeBracketIndex - openBracketIndex - 1; return flag.mid(openBracketIndex + 1, n); } QStringList flagValues(const QStringList &flags, const QString &flagKey) { QStringList values; for (const auto &flag : flags) { if (!flag.startsWith(flagKey, Qt::CaseInsensitive)) continue; const auto value = extractValue(flag); values.push_back(value); } return values; } QString flagValue(const QStringList &flags, const QString &flagKey) { const auto flagEnd = flags.cend(); const auto flagIt = std::find_if(flags.cbegin(), flagEnd, [flagKey](const auto &flag) { return flag.startsWith(flagKey, Qt::CaseInsensitive); }); if (flagIt == flagEnd) return {}; // Flag key not found. return extractValue(*flagIt); } QStringList flagValueParts(const QString &flagValue, const QLatin1Char &sep) { auto parts = flagValue.split(sep); Internal::transform(parts, [](const auto &part) { return part.trimmed(); }); return parts; } } // namespace KeiluvUtils } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp0000644000175100017510000000365315232633614030440 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51commonpropertygroup_v5.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51CommonPropertyGroup::Mcs51CommonPropertyGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("CommonProperty") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h0000644000175100017510000000402415232633614027143 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETMISCGROUP_V5_H #define QBS_KEILUVMCS51TARGETMISCGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetMiscGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetMiscGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETMISCGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h0000644000175100017510000000507415232633614027315 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H #define QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51BuildTargetGroup final : public gen::xml::PropertyGroup { private: explicit Mcs51BuildTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class Mcs51BuildTargetGroupFactory; }; class Mcs51BuildTargetGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp0000644000175100017510000001221515232633614031450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetcommonoptionsgroup_v5.h" #include "../../keiluvutils.h" #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { namespace { struct CommonPageOptions final { explicit CommonPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = KeiluvUtils::cppModuleCompilerFlags(qbsProps); // Browse information. if (flags.contains(QLatin1String("BROWSE"), Qt::CaseInsensitive)) browseInfo = true; // Debug information. debugInfo = gen::utils::debugInformation(qbsProduct); // Output parameters. executableName = gen::utils::targetBinary(qbsProduct); // Fix output binary name if it is a library. Because // the IDE appends an additional suffix (.LIB) to end // of an output library name. if (executableName.endsWith(QLatin1String(".lib"))) executableName = qbsProduct.targetName(); const QString baseDirectory = gen::utils::buildRootPath(qbsProject); objectDirectory = QDir::toNativeSeparators( gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct)); listingDirectory = QDir::toNativeSeparators( gen::utils::listingOutputDirectory( baseDirectory, qbsProduct)); // Target type. targetType = KeiluvUtils::outputBinaryType(qbsProduct); } int browseInfo = false; int debugInfo = false; QString executableName; QString objectDirectory; QString listingDirectory; KeiluvUtils::OutputBinaryType targetType = KeiluvUtils::ApplicationOutputType; }; } // namespace Mcs51TargetCommonOptionsGroup::Mcs51TargetCommonOptionsGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("TargetCommonOption") { const CommonPageOptions opts(qbsProject, qbsProduct); // Add 'Generic 8051 device' items, // because we can't detect a target device // form the present command lines. appendProperty(QByteArrayLiteral("Device"), QByteArrayLiteral("8051 (all Variants)")); appendProperty(QByteArrayLiteral("Vendor"), QByteArrayLiteral("Generic")); appendProperty(QByteArrayLiteral("DeviceId"), QByteArrayLiteral("2994")); // Add 'Debug Information' item. appendProperty(QByteArrayLiteral("DebugInformation"), opts.debugInfo); // Add 'Browse Information' item. appendProperty(QByteArrayLiteral("BrowseInformation"), opts.browseInfo); // Add 'Name of Executable'. appendProperty(QByteArrayLiteral("OutputName"), opts.executableName); // Add 'Output objects directory'. appendProperty(QByteArrayLiteral("OutputDirectory"), opts.objectDirectory); // Add 'Output listing directory'. appendProperty(QByteArrayLiteral("ListingPath"), opts.listingDirectory); // Add 'Create Executable/Library' item. const int isExecutable = (opts.targetType == KeiluvUtils::ApplicationOutputType); const int isLibrary = (opts.targetType == KeiluvUtils::LibraryOutputType); appendProperty(QByteArrayLiteral("CreateExecutable"), isExecutable); appendProperty(QByteArrayLiteral("CreateLib"), isLibrary); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp0000644000175100017510000000673715232633614027513 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetmiscgroup_v5.h" #include "mcs51utils.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { namespace { struct MiscPageOptions final { enum MemoryModel { SmallMemoryModel = 0, CompactMemoryModel, LargeMemoryModel }; enum CodeRomSize { SmallCodeRomSize = 0, CompactCodeRomSize, LargeCodeRomSize }; explicit MiscPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); // Memory model. if (flags.contains(QLatin1String("COMPACT"), Qt::CaseInsensitive)) memoryModel = CompactMemoryModel; else if (flags.contains(QLatin1String("LARGE"), Qt::CaseInsensitive)) memoryModel = LargeMemoryModel; // Code ROM size. const auto sizeValue = KeiluvUtils::flagValue( flags, QStringLiteral("ROM")); if (sizeValue == QLatin1String("SMALL")) coderomSize = SmallCodeRomSize; else if (sizeValue == QLatin1String("COMPACT")) coderomSize = CompactCodeRomSize; } MemoryModel memoryModel = SmallMemoryModel; CodeRomSize coderomSize = LargeCodeRomSize; }; } // namespace Mcs51TargetMiscGroup::Mcs51TargetMiscGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Target51Misc") { const MiscPageOptions opts(qbsProject, qbsProduct); // Add 'Memory Model' options item. appendProperty(QByteArrayLiteral("MemoryModel"), opts.memoryModel); // Add 'ROM Size' options item. appendProperty(QByteArrayLiteral("RomSize"), opts.coderomSize); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp0000644000175100017510000000362715232633614027357 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51utilitiesgroup_v5.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51UtilitiesGroup::Mcs51UtilitiesGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Utilities") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h0000644000175100017510000000405015232633614030021 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H #define QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetCompilerGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetCompilerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h0000644000175100017510000000404715232633614030172 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 #define QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetAssemblerGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetAssemblerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h0000644000175100017510000000401715232633614027016 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51UTILITIESGROUP_V5_H #define QBS_KEILUVMCS51UTILITIESGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51UtilitiesGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51UtilitiesGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51UTILITIESGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h0000644000175100017510000000404215232633614030076 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H #define QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51CommonPropertyGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51CommonPropertyGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_MCS51COMMONPROPERTYGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h0000644000175100017510000000403615232633614027477 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H #define QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51TargetLinkerGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51TargetLinkerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp0000644000175100017510000002672515232633614030371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetcompilergroup_v5.h" #include "mcs51utils.h" #include "../../keiluvutils.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { namespace { struct CompilerPageOptions final { enum WarningLevel { WarningLevelNone = 0, WarningLevelOne, WarningLevelTwo }; enum OptimizationLevel { ConstantFoldingOptimizationLevel = 0, DeadCodeEliminationOptimizationLevel, DataOverlayingOptimizationLevel, PeepholeOptimizationLevel, RegisterVariablesOptimizationLevel, CommonSubexpressionEliminationOptimizationLevel, LoopRotationOptimizationLevel, ExtendedIndexAccessOptimizationLevel, ReuseCommonEntryCodeOptimizationLevel, CommonBlockSubroutinesOptimizationLevel, RearrangeCodeOptimizationLevel, ReuseCommonExitCodeOptimizationLevel }; enum OptimizationEmphasis { FavorSizeOptimizationEmphasis = 0, FavorSpeedOptimizationEmphasis }; enum FloatFuzzyBits { NoFloatFuzzyBits = 0, OneFloatFuzzyBit, TwoFloatFuzzyBits, ThreeFloatFuzzyBits, FourFloatFuzzyBits, FiveFloatFuzzyBits, SixFloatFuzzyBits, SevenFloatFuzzyBits }; explicit CompilerPageOptions(const Project &qbsProject, const ProductData &qbsProduct) { Q_UNUSED(qbsProject) const auto &qbsProps = qbsProduct.moduleProperties(); const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); // Warnings. const QString level = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (level == QLatin1String("none")) { warningLevel = WarningLevelNone; } else if (level == QLatin1String("all")) { warningLevel = WarningLevelTwo; } else { // In this case take it directly from the compiler command line, // e.g. parse the line in a form: 'WARNINGLEVEL (2)' const auto warnValue = KeiluvUtils::flagValue( flags, QStringLiteral("WARNINGLEVEL")); bool ok = false; const auto level = warnValue.toInt(&ok); if (ok && gen::utils::inBounds( level, int(WarningLevelNone),int(WarningLevelTwo))) { warningLevel = static_cast(level); } } // Optimizations. const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("fast")) { optimizationEmphasis = FavorSpeedOptimizationEmphasis; } else if (level == QLatin1String("small")) { optimizationEmphasis = FavorSizeOptimizationEmphasis; } else if (level == QLatin1String("small")) { // Don't supported by C51 compiler. } else { // In this case take it directly from the compiler command line, // e.g. parse the line in a form: 'OPTIMIZE (8, SPEED)' const auto optValue = KeiluvUtils::flagValue( flags, QStringLiteral("OPTIMIZE")); const auto parts = KeiluvUtils::flagValueParts(optValue); for (const auto &part : parts) { bool ok = false; const auto level = part.toInt(&ok); if (ok && (level >= ConstantFoldingOptimizationLevel) && (level <= ReuseCommonExitCodeOptimizationLevel)) { optimizationLevel = static_cast(level); } else if (part.compare(QLatin1String("SIZE"), Qt::CaseInsensitive) == 0) { optimizationEmphasis = FavorSizeOptimizationEmphasis; } else if (part.compare(QLatin1String("SPEED"), Qt::CaseInsensitive) == 0) { optimizationEmphasis = FavorSpeedOptimizationEmphasis; } } } // Don't use absolute register accesses. if (flags.contains(QLatin1String("NOAREGS"), Qt::CaseInsensitive)) dontuseAbsoluteRegsAccess = true; // Enable ANSI integer promotion rules. if (flags.contains(QLatin1String("NOINTPROMOTE"), Qt::CaseInsensitive)) enableIntegerPromotionRules = false; // Keep variables in order. if (flags.contains(QLatin1String("ORDER"), Qt::CaseInsensitive)) keepVariablesInOrder = true; // Don't use interrupt vector. if (flags.contains(QLatin1String("NOINTVECTOR"), Qt::CaseInsensitive)) useInterruptVector = false; // Interrupt vector address. interruptVectorAddress = KeiluvUtils::flagValue( flags, QStringLiteral("INTVECTOR")); // Float fuzzy bits count. const auto bitsValue = KeiluvUtils::flagValue( flags, QStringLiteral("FLOATFUZZY")); bool ok = false; const auto bits = bitsValue.toInt(&ok); if (ok && gen::utils::inBounds( bits, int(NoFloatFuzzyBits), int(SevenFloatFuzzyBits))) { floatFuzzyBits = static_cast(bits); } // Define symbols. defineSymbols = qbs::KeiluvUtils::defines(qbsProps); // Include paths. includePaths = qbs::KeiluvUtils::includes(qbsProps); // Interpret other compiler flags as a misc controls (exclude only // that flags which are was already handled). for (const auto &flag : flags) { if (flag.startsWith(QLatin1String("WARNINGLEVEL"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("OPTIMIZE"), Qt::CaseInsensitive) || flag.startsWith(QLatin1String("FLOATFUZZY"), Qt::CaseInsensitive) || flag.compare(QLatin1String("NOAREGS"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("AREGS"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("NOINTPROMOTE"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("INTPROMOTE"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("NOINTVECTOR"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("INTVECTOR"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("ORDER"), Qt::CaseInsensitive) == 0 || flag.compare(QLatin1String("BROSWE"), Qt::CaseInsensitive) == 0 ) { continue; } miscControls.push_back(flag); } } WarningLevel warningLevel = WarningLevelTwo; OptimizationLevel optimizationLevel = ReuseCommonEntryCodeOptimizationLevel; OptimizationEmphasis optimizationEmphasis = FavorSpeedOptimizationEmphasis; FloatFuzzyBits floatFuzzyBits = ThreeFloatFuzzyBits; int dontuseAbsoluteRegsAccess = false; int enableIntegerPromotionRules = true; int keepVariablesInOrder = false; int useInterruptVector = true; QString interruptVectorAddress; QStringList defineSymbols; QStringList includePaths; QStringList miscControls; }; } // namespace Mcs51TargetCompilerGroup::Mcs51TargetCompilerGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("C51") { const CompilerPageOptions opts(qbsProject, qbsProduct); // Add 'Code Optimization' options. appendProperty(QByteArrayLiteral("Optimize"), opts.optimizationLevel); appendProperty(QByteArrayLiteral("SizeSpeed"), opts.optimizationEmphasis); // Add 'Warnings' options. appendProperty(QByteArrayLiteral("WarningLevel"), opts.warningLevel); // Add 'Don't use absolute register access' item. appendProperty(QByteArrayLiteral("uAregs"), opts.dontuseAbsoluteRegsAccess); // Add 'Enable integer promotion rules' item. appendProperty(QByteArrayLiteral("IntegerPromotion"), opts.enableIntegerPromotionRules); // Add 'Keep variables in order' item. appendProperty(QByteArrayLiteral("VariablesInOrder"), opts.keepVariablesInOrder); // Add 'Use interrupt vector' item. appendProperty(QByteArrayLiteral("UseInterruptVector"), opts.useInterruptVector); appendProperty(QByteArrayLiteral("InterruptVectorAddress"), opts.interruptVectorAddress); // Add 'Float fuzzy bits' item. appendProperty(QByteArrayLiteral("Fuzzy"), opts.floatFuzzyBits); // Add other various controls. // Note: A sub-items order makes sense! const auto variousControlsGroup = appendChild( QByteArrayLiteral("VariousControls")); // Add 'Misc Controls' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("MiscControls"), opts.miscControls, QLatin1Char(' ')); // Add 'Define' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("Define"), opts.defineSymbols); // Add an empty 'Undefine' item. variousControlsGroup->appendProperty( QByteArrayLiteral("Undefine"), {}); // Add 'Include Paths' item. variousControlsGroup->appendMultiLineProperty( QByteArrayLiteral("IncludePath"), opts.includePaths, QLatin1Char(';')); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h0000644000175100017510000000406715232633614024461 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51UTILS_H #define QBS_KEILUVMCS51UTILS_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace KeiluvUtils { QStringList flagValues(const QStringList &flags, const QString &flagKey); QString flagValue(const QStringList &flags, const QString &flagKey); QStringList flagValueParts(const QString &flagValue, const QLatin1Char &sep = QLatin1Char(',')); } // namespace KeiluvUtils } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51UTILS_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp0000644000175100017510000000363715232633614027664 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51debugoptiongroup_v5.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51DebugOptionGroup::Mcs51DebugOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("DebugOption") { Q_UNUSED(qbsProject) Q_UNUSED(qbsProduct) } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h0000644000175100017510000000401715232633614027007 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H #define QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H #include namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { class Mcs51DllOptionGroup final : public gen::xml::PropertyGroup { public: explicit Mcs51DllOptionGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct); }; } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs #endif // QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp0000644000175100017510000001057115232633614027646 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51buildtargetgroup_v5.h" #include "mcs51commonpropertygroup_v5.h" #include "mcs51debugoptiongroup_v5.h" #include "mcs51dlloptiongroup_v5.h" #include "mcs51targetcommonoptionsgroup_v5.h" #include "mcs51targetgroup_v5.h" #include "mcs51utilitiesgroup_v5.h" #include "mcs51utils.h" #include "../../keiluvconstants.h" #include "../../keiluvfilesgroupspropertygroup.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51BuildTargetGroup::Mcs51BuildTargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("Target") { // Append target name item (it is a build configuration name). const QString targetName = gen::utils::buildConfigurationName( qbsProject); appendProperty(QByteArrayLiteral("TargetName"), targetName); // Append toolset number group item. appendChild(QByteArrayLiteral("ToolsetNumber"), QByteArrayLiteral("0x0")); // Append toolset name group item. appendChild(QByteArrayLiteral("ToolsetName"), QByteArrayLiteral("MCS-51")); // Append target option group item. const auto targetOptionGroup = appendChild( QByteArrayLiteral("TargetOption")); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); targetOptionGroup->appendChild( qbsProject, qbsProduct); // Append files group. appendChild(qbsProject, qbsProduct, qbsProductDeps); } bool Mcs51BuildTargetGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Mcs51 && version.majorVersion() == qbs::KeiluvConstants::v5::kUVisionVersion; } std::unique_ptr Mcs51BuildTargetGroupFactory::create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new Mcs51BuildTargetGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp0000644000175100017510000000440115232633614026621 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51targetassemblergroup_v5.h" #include "mcs51targetcompilergroup_v5.h" #include "mcs51targetgroup_v5.h" #include "mcs51targetlinkergroup_v5.h" #include "mcs51targetmiscgroup_v5.h" namespace qbs { namespace keiluv { namespace mcs51 { namespace v5 { Mcs51TargetGroup::Mcs51TargetGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct) : gen::xml::PropertyGroup("Target51") { appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); appendChild(qbsProject, qbsProduct); } } // namespace v5 } // namespace mcs51 } // namespace keiluv } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvprojectwriter.cpp0000644000175100017510000000440715232633614025074 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvprojectwriter.h" namespace qbs { KeiluvProjectWriter::KeiluvProjectWriter(std::ostream *device) : gen::xml::ProjectWriter(device) { } void KeiluvProjectWriter::visitProjectStart(const gen::xml::Project *project) { Q_UNUSED(project) writer()->writeStartElement(QStringLiteral("Project")); writer()->writeAttribute( QStringLiteral("xmlns:xsi"), QStringLiteral("http://www.w3.org/2001/XMLSchema-instance")); writer()->writeAttribute( QStringLiteral("xsi:noNamespaceSchemaLocation"), QStringLiteral("project_proj.xsd")); } void KeiluvProjectWriter::visitProjectEnd(const gen::xml::Project *project) { Q_UNUSED(project) writer()->writeEndElement(); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvworkspace.h0000644000175100017510000000433115232633614023630 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_KEILUVWORKSPACE_H #define QBS_KEILUVWORKSPACE_H #include namespace qbs { class KeiluvWorkspace final : public gen::xml::Workspace { public: explicit KeiluvWorkspace(const QString &workspacePath); void addProject(const QString &projectPath) final; }; } // namespace qbs #endif // QBS_KEILUVWORKSPACE_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvutils.h0000644000175100017510000000452415232633614022776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVUTILS_H #define QBS_KEILUVUTILS_H #include #include namespace qbs { namespace KeiluvUtils { enum OutputBinaryType { ApplicationOutputType, LibraryOutputType }; OutputBinaryType outputBinaryType(const ProductData &qbsProduct); QString toolkitRootPath(const ProductData &qbsProduct); QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps); QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps); QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps); QStringList includes(const PropertyMap &qbsProps); QStringList defines(const PropertyMap &qbsProps); QStringList staticLibraries(const PropertyMap &qbsProps); QStringList dependencies(const std::vector &qbsProductDeps); } // namespace KeiluvUtils } // namespace qbs #endif // QBS_KEILUVUTILS_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvconstants.h0000644000175100017510000000335715232633614023655 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_KEILUVCONSTANTS_H #define QBS_KEILUVCONSTANTS_H namespace qbs { namespace KeiluvConstants { namespace v5 { constexpr int kUVisionVersion = 5; } } // namespace KeiluvConstants } // namespace qbs #endif // QBS_KEILUVCONSTANTS_H qbs-src-3.3.1/src/plugins/generator/keiluv/keiluvutils.cpp0000644000175100017510000001053715232633614023332 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "keiluvutils.h" #include #include namespace qbs { namespace KeiluvUtils { OutputBinaryType outputBinaryType(const ProductData &qbsProduct) { const auto &qbsProductType = qbsProduct.type(); if (qbsProductType.contains(QLatin1String("application"))) return ApplicationOutputType; if (qbsProductType.contains(QLatin1String("staticlibrary"))) return LibraryOutputType; return ApplicationOutputType; } QString toolkitRootPath(const ProductData &qbsProduct) { QDir dir(qbsProduct.moduleProperties() .getModuleProperty(Internal::StringConstants::cppModule(), QStringLiteral("toolchainInstallPath")) .toString()); dir.cdUp(); const auto path = dir.absolutePath(); return QDir::toNativeSeparators(path); } QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"), QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"), QStringLiteral("commonCompilerFlags")}); } QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); } QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverLinkerFlags")}); } QStringList includes(const PropertyMap &qbsProps) { auto paths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); // Transform include path separators to native. Internal::transform(paths, [](const auto &path) { return QDir::toNativeSeparators(path); }); return paths; } QStringList defines(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("defines")}); } QStringList staticLibraries(const PropertyMap &qbsProps) { auto libs = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); // Transform library path separators to native. Internal::transform(libs, [](const auto &path) { return QDir::toNativeSeparators(path); }); return libs; } QStringList dependencies(const std::vector &qbsProductDeps) { return Internal::transformed(qbsProductDeps, [](const auto &dep) { const QString path = dep.buildDirectory() + QStringLiteral("/obj/") + gen::utils::targetBinary(dep); return QDir::toNativeSeparators(path); }); } } // namespace KeiluvUtils } // namespace qbs qbs-src-3.3.1/src/plugins/generator/clangcompilationdb/0000755000175100017510000000000015232633614022572 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/clangcompilationdb/clangcompilationdb.qbs0000644000175100017510000000037015232633614027132 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "clangcompilationdbgenerator" files: [ "clangcompilationdbgenerator.cpp", "clangcompilationdbgenerator.h", "clangcompilationdbgeneratorplugin.cpp" ] } qbs-src-3.3.1/src/plugins/generator/clangcompilationdb/CMakeLists.txt0000644000175100017510000000033715232633614025335 0ustar runnerrunnerset(SOURCES clangcompilationdbgenerator.cpp clangcompilationdbgenerator.h clangcompilationdbgeneratorplugin.cpp ) add_qbs_plugin(clangcompilationdbgenerator DEPENDS qbscore SOURCES ${SOURCES} ) qbs-src-3.3.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgenerator.cpp0000644000175100017510000001375615232633614031052 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "clangcompilationdbgenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; const QString ClangCompilationDatabaseGenerator::DefaultDatabaseFileName = QStringLiteral("compile_commands.json"); ClangCompilationDatabaseGenerator::ClangCompilationDatabaseGenerator() = default; QString ClangCompilationDatabaseGenerator::generatorName() const { return QStringLiteral("clangdb"); } void ClangCompilationDatabaseGenerator::generate() { const auto projects = project().projects.values(); for (const Project &theProject : projects) { QJsonArray database; const ProjectData projectData = theProject.projectData(); const QString &buildDir = projectData.buildDirectory(); for (const ProductData &productData : projectData.allProducts()) { for (const GroupData &groupData : productData.groups()) { const auto sourceArtifacts = groupData.allSourceArtifacts(); for (const ArtifactData &sourceArtifact : sourceArtifacts) { if (!hasValidInputFileTag(sourceArtifact.fileTags())) continue; const QString filePath = sourceArtifact.filePath(); ErrorInfo errorInfo; const RuleCommandList rules = theProject.ruleCommands(productData, filePath, QStringLiteral("obj"), &errorInfo); if (errorInfo.hasError()) throw errorInfo; for (const RuleCommand &rule : rules) { if (rule.type() != RuleCommand::ProcessCommandType) continue; database.push_back(createEntry(filePath, buildDir, rule)); } } } } writeProjectDatabase(QDir(buildDir).filePath(DefaultDatabaseFileName), database); } } // See http://clang.llvm.org/docs/JSONCompilationDatabase.html QJsonObject ClangCompilationDatabaseGenerator::createEntry(const QString &filePath, const QString &buildDir, const RuleCommand &ruleCommand) { QString workDir = ruleCommand.workingDirectory(); if (workDir.isEmpty()) workDir = buildDir; const QStringList arguments = QStringList() << ruleCommand.executable() << ruleCommand.arguments(); return QJsonObject{ { QStringLiteral("directory"), QJsonValue(workDir) }, { QStringLiteral("arguments"), QJsonArray::fromStringList(arguments) }, { QStringLiteral("file"), QJsonValue(filePath) } }; } void ClangCompilationDatabaseGenerator::writeProjectDatabase(const QString &filePath, const QJsonArray &entries) { const QJsonDocument database(entries); QFile databaseFile(filePath); if (!databaseFile.open(QFile::WriteOnly)) throw ErrorInfo(Tr::tr("Cannot open '%1' for writing: %2") .arg(filePath, databaseFile.errorString())); if (databaseFile.write(database.toJson()) == -1) throw ErrorInfo(Tr::tr("Error while writing '%1': %2") .arg(filePath, databaseFile.errorString())); } bool ClangCompilationDatabaseGenerator::hasValidInputFileTag(const QStringList &fileTags) const { static const QStringList validFileTags = { QStringLiteral("c"), QStringLiteral("cpp"), QStringLiteral("objc"), QStringLiteral("objcpp") }; return Internal::any_of(fileTags, [](const auto &tag) { return validFileTags.contains(tag); }); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgeneratorplugin.cpp0000644000175100017510000000506415232633614032262 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "clangcompilationdbgenerator.h" #include #include static void QbsClangDbGeneratorPluginLoad() { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared()); } static void QbsClangDbGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, clangcompilationdbgenerator, QbsClangDbGeneratorPluginLoad, QbsClangDbGeneratorPluginUnload) qbs-src-3.3.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgenerator.h0000644000175100017510000000517115232633614030507 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CLANGCOMPILATIONDATABASEGENERATOR_H #define QBS_CLANGCOMPILATIONDATABASEGENERATOR_H #include namespace qbs { class SourceArtifact; class ProjectData; class ClangCompilationDatabaseGenerator : public ProjectGenerator { public: ClangCompilationDatabaseGenerator(); private: QString generatorName() const override; void generate() override; static const QString DefaultDatabaseFileName; QJsonObject createEntry(const QString &filePath, const QString &buildDir, const RuleCommand &ruleCommand); void writeProjectDatabase(const QString &filePath, const QJsonArray &entries); bool hasValidInputFileTag(const QStringList &fileTags) const; }; } // namespace qbs #endif // QBS_VISUALSTUDIOGENERATOR_H qbs-src-3.3.1/src/plugins/generator/makefilegenerator/0000755000175100017510000000000015232633614022425 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/makefilegenerator/makefilegenerator.h0000644000175100017510000000420515232633614026263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MAKEFILEGENERATOR_H #define QBS_MAKEFILEGENERATOR_H #include namespace qbs { class MakefileGenerator : public ProjectGenerator { QString generatorName() const override; void generate() override; }; } // namespace qbs #endif // Include guard. qbs-src-3.3.1/src/plugins/generator/makefilegenerator/makefilegeneratorplugin.cpp0000644000175100017510000000501015232633614030030 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "makefilegenerator.h" #include #include static void MakefileGeneratorPluginLoad() { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared()); } static void MakefileGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, makefilegenerator, MakefileGeneratorPluginLoad, MakefileGeneratorPluginUnload) qbs-src-3.3.1/src/plugins/generator/makefilegenerator/CMakeLists.txt0000644000175100017510000000026715232633614025172 0ustar runnerrunnerset(SOURCES makefilegenerator.cpp makefilegenerator.h makefilegeneratorplugin.cpp ) add_qbs_plugin(makefilegenerator DEPENDS qbscore SOURCES ${SOURCES} ) qbs-src-3.3.1/src/plugins/generator/makefilegenerator/makefilegenerator.cpp0000644000175100017510000004212115232633614026615 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "makefilegenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; QString qbs::MakefileGenerator::generatorName() const { return QStringLiteral("makefile"); } static QString quote(const QString &s) { QString quoted = shellQuote(s); quoted.replace(QLatin1Char('$'), QLatin1String("$$")); // For make quoted.replace(QLatin1String("$$(SRCDIR)"), QLatin1String("$(SRCDIR)")); quoted.replace(QLatin1String("$$(BUILD_ROOT)"), QLatin1String("$(BUILD_ROOT)")); quoted.replace(QLatin1String("$$(INSTALL_ROOT)"), QLatin1String("$(INSTALL_ROOT)")); return quoted; } enum class TargetType { Product, Path }; static QString makeValidTargetName(const QString &name, TargetType targetType) { QString modifiedName = name; switch (targetType) { case TargetType::Product: { static const QRegularExpression illegalChar(QStringLiteral("[^_.0-9A-Za-z]")); modifiedName.replace(illegalChar, QStringLiteral("_")); break; } case TargetType::Path: if (HostOsInfo::isWindowsHost()) { modifiedName = QDir::toNativeSeparators(modifiedName); modifiedName = quote(modifiedName); } else { modifiedName.replace(QLatin1Char(' '), QStringLiteral("\\ ")); } } return modifiedName; } static QString makeValidTargetName(const ProductData &product) { QString name = makeValidTargetName(product.name(), TargetType::Product); if (!product.multiplexConfigurationId().isEmpty()) name.append(QLatin1Char('_')).append(product.multiplexConfigurationId()); return name; } using PrefixSpec = std::pair; static QString replacePrefix(const QString &path, const std::vector &candidates) { for (const PrefixSpec &prefixSpec : candidates) { if (path.startsWith(prefixSpec.first) && (path.size() == prefixSpec.first.size() || path.at(prefixSpec.first.size()) == QLatin1Char('/'))) { QString p = path; return p.replace(0, prefixSpec.first.size(), QLatin1String("$(") + prefixSpec.second + QLatin1Char(')')); } } return path; } static QString bruteForcePathReplace(const QString &value, const QString &srcDir, const QString &buildDir, const QString &installRoot) { QString transformedValue = value; if (!installRoot.isEmpty()) transformedValue.replace(installRoot, QStringLiteral("$(INSTALL_ROOT)")); transformedValue.replace(buildDir, QStringLiteral("$(BUILD_ROOT)")); transformedValue.replace(srcDir, QStringLiteral("$(SRCDIR)")); return transformedValue; } static QString mkdirCmdLine(const QString &dir) { if (HostOsInfo::isWindowsHost()) return QStringLiteral("if not exist %1 mkdir %1 & if not exist %1 exit 1").arg(dir); return QStringLiteral("mkdir -p ") + dir; } static QString installFileCommand() { return HostOsInfo::isWindowsHost() ? QStringLiteral("copy /Y") : QStringLiteral("install -m 644 -p"); } static QString installProgramCommand() { return HostOsInfo::isWindowsHost() ? installFileCommand() : QStringLiteral("install -m 755 -p"); } static QString removeCommand() { return HostOsInfo::isWindowsHost() ? QStringLiteral("del") : QStringLiteral("rm -f"); } void qbs::MakefileGenerator::generate() { const auto projects = project().projects.values(); for (const Project &theProject : projects) { const QString makefileFilePath = theProject.projectData().buildDirectory() + QLatin1String("/Makefile"); QFile makefile(makefileFilePath); if (!makefile.open(QIODevice::WriteOnly)) { throw ErrorInfo(Tr::tr("Failed to create '%1': %2") .arg(makefileFilePath, makefile.errorString())); } QTextStream stream(&makefile); ErrorInfo error; const ProjectTransformerData projectTransformerData = theProject.transformerData(&error); if (error.hasError()) throw error; stream << "# This file was generated by qbs" << "\n\n"; stream << "INSTALL_FILE = " << installFileCommand() << '\n'; stream << "INSTALL_PROGRAM = " << installProgramCommand() << '\n'; stream << "RM = " << removeCommand() << '\n'; stream << '\n'; const ProjectData projectData = theProject.projectData(); const QString srcDir = QFileInfo(projectData.location().filePath()).path(); if (srcDir.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The project directory '%1' contains space characters, which" "is not supported by this generator.").arg(srcDir)); } stream << "SRCDIR = " << QDir::toNativeSeparators(srcDir) << '\n'; const QString &buildDir = projectData.buildDirectory(); if (buildDir.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The build directory '%1' contains space characters, which" "is not supported by this generator.").arg(buildDir)); } stream << "BUILD_ROOT = " << QDir::toNativeSeparators(buildDir) << '\n'; QString installRoot; const QList allInstallables = projectData.installableArtifacts(); if (!allInstallables.empty()) { installRoot = allInstallables.first().installData().installRoot(); if (installRoot.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The install root '%1' contains space characters, which" "is not supported by this generator.").arg(installRoot)); } stream << "INSTALL_ROOT = " << QDir::toNativeSeparators(installRoot) << '\n'; } stream << "\nall:\n"; const std::vector srcDirPrefixSpecs{std::make_pair(srcDir, QStringLiteral("SRCDIR"))}; const auto prefixifiedSrcDirPath = [&srcDirPrefixSpecs](const QString &path) { return replacePrefix(path, srcDirPrefixSpecs); }; const std::vector buildRootPrefixSpecs{ std::make_pair(buildDir, QStringLiteral("BUILD_ROOT"))}; const auto prefixifiedBuildDirPath = [&buildRootPrefixSpecs](const QString &path) { return replacePrefix(path, buildRootPrefixSpecs); }; const std::vector installRootPrefixSpecs{ std::make_pair(installRoot, QStringLiteral("INSTALL_ROOT"))}; const auto prefixifiedInstallDirPath = [&installRoot, &installRootPrefixSpecs](const QString &path) { if (installRoot.isEmpty()) return path; return replacePrefix(path, installRootPrefixSpecs); }; const auto transformedOutputFilePath = [=](const ArtifactData &output) { return makeValidTargetName(prefixifiedBuildDirPath(output.filePath()), TargetType::Path); }; const auto transformedInputFilePath = [=](const ArtifactData &input) { return makeValidTargetName(prefixifiedSrcDirPath(input.filePath()), TargetType::Path); }; const auto transformedArtifactFilePath = [=](const ArtifactData &artifact) { return artifact.isGenerated() ? transformedOutputFilePath(artifact) : transformedInputFilePath(artifact); }; QStringList allTargets; QStringList allDefaultTargets; QStringList filesCreatedByJsCommands; bool jsCommandsEncountered = false; for (const auto &d : projectTransformerData) { const ProductData productData = d.first; const QString productTarget = makeValidTargetName(productData); const ProductTransformerData productTransformerData = d.second; const bool builtByDefault = productData.properties().value( StringConstants::builtByDefaultProperty()).toBool(); if (builtByDefault) allDefaultTargets.push_back(productTarget); allTargets.push_back(productTarget); stream << productTarget << ':'; const auto targetArtifacts = productData.targetArtifacts(); for (const ArtifactData &ta : targetArtifacts) stream << ' ' << transformedOutputFilePath(ta); stream << '\n'; for (const TransformerData &transformerData : productTransformerData) { stream << transformedOutputFilePath(transformerData.outputs().constFirst()) << ":"; const auto inputs = transformerData.inputs(); for (const ArtifactData &input : inputs) stream << ' ' << transformedArtifactFilePath(input); stream << '\n'; Set createdDirs; const auto outputs = transformerData.outputs(); for (const ArtifactData &output : outputs) { const QString outputDir = QFileInfo(output.filePath()).path(); if (createdDirs.insert(outputDir).second) stream << "\t" << mkdirCmdLine(QDir::toNativeSeparators( prefixifiedBuildDirPath(outputDir))) << '\n'; } bool processCommandEncountered = false; const auto commands = transformerData.commands(); for (const RuleCommand &command : commands) { if (command.type() == RuleCommand::JavaScriptCommandType) { jsCommandsEncountered = true; continue; } processCommandEncountered = true; stream << '\t' << QDir::toNativeSeparators( quote(bruteForcePathReplace(command.executable(), srcDir, buildDir, installRoot))); // TODO: Optionally use environment? const auto args = command.arguments(); for (const QString &arg : args) { stream << ' ' << quote(bruteForcePathReplace(arg, srcDir, buildDir, installRoot)); } stream << '\n'; } for (int i = 1; i < transformerData.outputs().size(); ++i) { stream << transformedOutputFilePath(transformerData.outputs().at(i)) << ": " << transformedOutputFilePath(transformerData.outputs().at(i-1)) << '\n'; } if (!processCommandEncountered && builtByDefault) { const auto outputs = transformerData.outputs(); transform(outputs, filesCreatedByJsCommands, [](const auto &output) { return output.filePath(); }); } } stream << "install-" << productTarget << ": " << productTarget << '\n'; Set createdDirs; const auto installableArtifacts = productData.installableArtifacts(); for (const ArtifactData &artifact : installableArtifacts) { const QString &outputDir = artifact.installData().localInstallDir(); if (outputDir.contains(QLatin1Char(' '))) { logger().qbsWarning() << Tr::tr("Skipping installation of '%1', because " "target directory '%2' contains spaces.") .arg(artifact.filePath(), outputDir); continue; } if (createdDirs.insert(outputDir).second) stream << "\t" << mkdirCmdLine(QDir::toNativeSeparators( prefixifiedInstallDirPath(outputDir))) << '\n'; const QFileInfo fileInfo(artifact.filePath()); const QString transformedInputFilePath = QDir::toNativeSeparators((artifact.isGenerated() ? prefixifiedBuildDirPath(fileInfo.path()) : prefixifiedSrcDirPath(fileInfo.path())) + QLatin1Char('/') + quote(fileInfo.fileName())); const QString transformedOutputDir = QDir::toNativeSeparators(prefixifiedInstallDirPath( artifact.installData().localInstallDir())); stream << "\t" << (artifact.isExecutable() ? "$(INSTALL_PROGRAM) " : "$(INSTALL_FILE) ") << transformedInputFilePath << ' ' << transformedOutputDir << '\n'; } stream << "clean-" << productTarget << ":\n"; for (const ArtifactData &artifact : productData.generatedArtifacts()) { const QFileInfo fileInfo(artifact.filePath()); const QString transformedFilePath = QDir::toNativeSeparators( prefixifiedBuildDirPath(fileInfo.path()) + QLatin1Char('/') + quote(fileInfo.fileName())); stream << '\t'; if (HostOsInfo::isWindowsHost()) stream << '-'; stream << "$(RM) " << transformedFilePath << '\n'; } } stream << "all:"; for (const QString &target : std::as_const(allDefaultTargets)) stream << ' ' << target; stream << '\n'; stream << "install:"; for (const QString &target : std::as_const(allDefaultTargets)) stream << ' ' << "install-" << target; stream << '\n'; stream << "clean:"; for (const QString &target : std::as_const(allTargets)) stream << ' ' << "clean-" << target; stream << '\n'; if (!filesCreatedByJsCommands.empty()) { logger().qbsWarning() << Tr::tr("Some rules used by this project are not " "Makefile-compatible, because they depend entirely on JavaScriptCommands. " "The build is probably not fully functional. " "Affected build artifacts:\n\t%1") .arg(filesCreatedByJsCommands.join(QLatin1String("\n\t"))); } else if (jsCommandsEncountered) { logger().qbsWarning() << Tr::tr("Some rules in this project use JavaScriptCommands, " "which cannot be converted to Makefile-compatible constructs. The build may " "not be fully functional."); } logger().qbsInfo() << Tr::tr("Makefile successfully generated at '%1'.") .arg(makefileFilePath); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/makefilegenerator/makefilegenerator.qbs0000644000175100017510000000032115232633614026614 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "makefilegenerator" files: [ "makefilegenerator.cpp", "makefilegenerator.h", "makefilegeneratorplugin.cpp", ] } qbs-src-3.3.1/src/plugins/generator/iarew/0000755000175100017510000000000015232633614020050 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/iarewprojectwriter.cpp0000644000175100017510000000372515232633614024516 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewprojectwriter.h" namespace qbs { IarewProjectWriter::IarewProjectWriter(std::ostream *device) : gen::xml::ProjectWriter(device) { } void IarewProjectWriter::visitProjectStart(const gen::xml::Project *project) { Q_UNUSED(project) writer()->writeStartElement(QStringLiteral("project")); } void IarewProjectWriter::visitProjectEnd(const gen::xml::Project *project) { Q_UNUSED(project) writer()->writeEndElement(); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewfileversionproperty.cpp0000644000175100017510000000412115232633614025734 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewfileversionproperty.h" #include "iarewversioninfo.h" namespace qbs { static QByteArray buildFileVersion(const gen::VersionInfo &versionInfo) { switch (versionInfo.marketingVersion()) { case 3: case 7: case 8: case 10: return QByteArrayLiteral("3"); default: return {}; } } IarewFileVersionProperty::IarewFileVersionProperty( const gen::VersionInfo &versionInfo) { setName(QByteArrayLiteral("fileVersion")); const QByteArray fileVersion = buildFileVersion(versionInfo); setValue(fileVersion); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewproject.h0000644000175100017510000000413115232633614022716 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWPROJECT_H #define QBS_IAREWPROJECT_H #include #include #include #include namespace qbs { class IarewProject final : public gen::xml::Project { public: explicit IarewProject(const GeneratableProject &genProject, const GeneratableProductData &genProduct, const gen::VersionInfo &versionInfo); private: std::vector> m_factories; }; } // namespace qbs #endif // QBS_IAREWPROJECT_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewutils.h0000644000175100017510000000523515232633614022416 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWUTILS_H #define QBS_IAREWUTILS_H #include #include namespace qbs { namespace IarewUtils { enum OutputBinaryType { ApplicationOutputType, LibraryOutputType }; OutputBinaryType outputBinaryType(const ProductData &qbsProduct); QString toolkitRootPath(const ProductData &qbsProduct); QString dlibToolkitRootPath(const ProductData &qbsProduct); QString clibToolkitRootPath(const ProductData &qbsProduct); QString libToolkitRootPath(const ProductData &qbsProduct); QString toolkitRelativeFilePath(const QString &basePath, const QString &fullFilePath); QString projectRelativeFilePath(const QString &basePath, const QString &fullFilePath); QString flagValue(const QStringList &flags, const QString &flagKey); QVariantList flagValues(const QStringList &flags, const QString &flagKey); QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps); QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps); QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps); } // namespace IarewUtils } // namespace qbs #endif // QBS_IAREWUTILS_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewoptionpropertygroup.h0000644000175100017510000000366215232633614025452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWOPTIONPROPERTYGROUP_H #define QBS_IAREWOPTIONPROPERTYGROUP_H #include //#include namespace qbs { class IarewOptionPropertyGroup final : public gen::xml::PropertyGroup { public: explicit IarewOptionPropertyGroup(const QByteArray &name, QVariantList states, int version = -1); }; } // namespace qbs #endif // QBS_IAREWOPTIONPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewutils.cpp0000644000175100017510000001265115232633614022751 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewutils.h" #include namespace qbs { namespace IarewUtils { QString toolkitRootPath(const ProductData &qbsProduct) { QDir dir(qbsProduct.moduleProperties() .getModuleProperty(Internal::StringConstants::cppModule(), QStringLiteral("toolchainInstallPath")) .toString()); dir.cdUp(); return dir.absolutePath(); } QString dlibToolkitRootPath(const ProductData &qbsProduct) { return toolkitRootPath(qbsProduct) + QLatin1String("/lib/dlib"); } QString clibToolkitRootPath(const ProductData &qbsProduct) { return toolkitRootPath(qbsProduct) + QLatin1String("/lib/clib"); } QString libToolkitRootPath(const ProductData &qbsProduct) { return toolkitRootPath(qbsProduct) + QLatin1String("/lib"); } QString toolkitRelativeFilePath(const QString &basePath, const QString &fullFilePath) { return QLatin1String("$TOOLKIT_DIR$/") + gen::utils::relativeFilePath(basePath, fullFilePath); } QString projectRelativeFilePath(const QString &basePath, const QString &fullFilePath) { return QLatin1String("$PROJ_DIR$/") + gen::utils::relativeFilePath(basePath, fullFilePath); } OutputBinaryType outputBinaryType(const ProductData &qbsProduct) { const auto &qbsProductType = qbsProduct.type(); if (qbsProductType.contains(QLatin1String("application"))) return ApplicationOutputType; if (qbsProductType.contains(QLatin1String("staticlibrary"))) return LibraryOutputType; return ApplicationOutputType; } QString flagValue(const QStringList &flags, const QString &flagKey) { // Seach for full 'flagKey' option matching. const auto flagBegin = flags.cbegin(); const auto flagEnd = flags.cend(); auto flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) { return flag == flagKey; }); if (flagIt == flagEnd) { // Search for start/end of 'flagKey' matching. flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) { return flag.startsWith(flagKey) || flag.endsWith(flagKey); }); if (flagIt == flagEnd) return {}; } QString value; // Check that option is in form of 'flagKey='. if (flagIt->contains(QLatin1Char('='))) { value = flagIt->split(QLatin1Char('=')).at(1).trimmed(); } else if (flagKey.size() < flagIt->size()) { // In this case an option is in form of 'flagKey'. value = flagIt->mid(flagKey.size()).trimmed(); } else { // In this case an option is in form of 'flagKey '. ++flagIt; if (flagIt < flagEnd) value = (*flagIt).trimmed(); else return {}; } return value; } QVariantList flagValues(const QStringList &flags, const QString &flagKey) { QVariantList values; for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (*flagIt != flagKey) continue; ++flagIt; values.push_back(*flagIt); } return values; } QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"), QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"), QStringLiteral("commonCompilerFlags")}); } QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); } QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps) { return gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("driverLinkerFlags")}); } } // namespace IarewUtils } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewgeneratorplugin.cpp0000644000175100017510000000521115232633614025010 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "iarewgenerator.h" #include "iarewversioninfo.h" #include #include static void QbsIarewGeneratorPluginLoad() { for (const auto &info : qbs::IarewVersionInfo::knownVersions) { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared(info)); } } static void QbsIarewGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, iarewgenerator, QbsIarewGeneratorPluginLoad, QbsIarewGeneratorPluginUnload) qbs-src-3.3.1/src/plugins/generator/iarew/iarewworkspacewriter.cpp0000644000175100017510000000376315232633614025050 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewworkspacewriter.h" namespace qbs { IarewWorkspaceWriter::IarewWorkspaceWriter(std::ostream *device) : gen::xml::WorkspaceWriter(device) { } void IarewWorkspaceWriter::visitWorkspaceStart(const gen::xml::Workspace *workspace) { Q_UNUSED(workspace) writer()->writeStartElement(QStringLiteral("workspace")); } void IarewWorkspaceWriter::visitWorkspaceEnd(const gen::xml::Workspace *workspace) { Q_UNUSED(workspace) writer()->writeEndElement(); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewversioninfo.h0000644000175100017510000000470515232633614023620 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_IAREWVERSIONINFO_H #define QBS_IAREWVERSIONINFO_H #include #include namespace qbs { namespace IarewVersionInfo { constexpr gen::VersionInfo knownVersions[] = { {Version(8), {gen::utils::Architecture::Arm}}, {Version(7), {gen::utils::Architecture::Avr, gen::utils::Architecture::Msp430}}, {Version(10), {gen::utils::Architecture::Mcs51}}, {Version(3), {gen::utils::Architecture::Stm8}}, }; } // namespace IarewVersionInfo } // namespace qbs #endif // QBS_IAREWVERSIONINFO_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp0000644000175100017510000000447315232633614026006 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewoptionpropertygroup.h" namespace qbs { IarewOptionPropertyGroup::IarewOptionPropertyGroup( const QByteArray &name, QVariantList states, int version) : gen::xml::PropertyGroup(QByteArrayLiteral("option")) { // Append name property item. appendChild(QByteArrayLiteral("name"), name); // Append version property item. if (version >= 0) appendChild(QByteArrayLiteral("version"), version); // Append state property items. for (auto &state : states) { if (state.isNull()) continue; appendChild(QByteArrayLiteral("state"), std::move(state)); } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/CMakeLists.txt0000644000175100017510000000704315232633614022614 0ustar runnerrunnerset(COMMON_SOURCES iarewfileversionproperty.cpp iarewfileversionproperty.h iarewgenerator.cpp iarewgenerator.h iarewgeneratorplugin.cpp iarewoptionpropertygroup.cpp iarewoptionpropertygroup.h iarewproject.cpp iarewproject.h iarewprojectwriter.cpp iarewprojectwriter.h iarewsettingspropertygroup.cpp iarewsettingspropertygroup.h iarewsourcefilepropertygroup.cpp iarewsourcefilepropertygroup.h iarewsourcefilespropertygroup.cpp iarewsourcefilespropertygroup.h iarewtoolchainpropertygroup.cpp iarewtoolchainpropertygroup.h iarewutils.cpp iarewutils.h iarewversioninfo.h iarewworkspace.cpp iarewworkspace.h iarewworkspacewriter.cpp iarewworkspacewriter.h ) set(ARCHS_ARM_SOURCES armarchiversettingsgroup_v8.cpp armarchiversettingsgroup_v8.h armassemblersettingsgroup_v8.cpp armassemblersettingsgroup_v8.h armbuildconfigurationgroup_v8.cpp armbuildconfigurationgroup_v8.h armcompilersettingsgroup_v8.cpp armcompilersettingsgroup_v8.h armgeneralsettingsgroup_v8.cpp armgeneralsettingsgroup_v8.h armlinkersettingsgroup_v8.cpp armlinkersettingsgroup_v8.h ) list_transform_prepend(ARCHS_ARM_SOURCES archs/arm/) set(ARCHS_AVR_SOURCES avrarchiversettingsgroup_v7.cpp avrarchiversettingsgroup_v7.h avrassemblersettingsgroup_v7.cpp avrassemblersettingsgroup_v7.h avrbuildconfigurationgroup_v7.cpp avrbuildconfigurationgroup_v7.h avrcompilersettingsgroup_v7.cpp avrcompilersettingsgroup_v7.h avrgeneralsettingsgroup_v7.cpp avrgeneralsettingsgroup_v7.h avrlinkersettingsgroup_v7.cpp avrlinkersettingsgroup_v7.h ) list_transform_prepend(ARCHS_AVR_SOURCES archs/avr/) set(ARCHS_MCS51_SOURCES mcs51archiversettingsgroup_v10.cpp mcs51archiversettingsgroup_v10.h mcs51assemblersettingsgroup_v10.cpp mcs51assemblersettingsgroup_v10.h mcs51buildconfigurationgroup_v10.cpp mcs51buildconfigurationgroup_v10.h mcs51compilersettingsgroup_v10.cpp mcs51compilersettingsgroup_v10.h mcs51generalsettingsgroup_v10.cpp mcs51generalsettingsgroup_v10.h mcs51linkersettingsgroup_v10.cpp mcs51linkersettingsgroup_v10.h ) list_transform_prepend(ARCHS_MCS51_SOURCES archs/mcs51/) set(ARCHS_STM8_SOURCES stm8archiversettingsgroup_v3.cpp stm8archiversettingsgroup_v3.h stm8assemblersettingsgroup_v3.cpp stm8assemblersettingsgroup_v3.h stm8buildconfigurationgroup_v3.cpp stm8buildconfigurationgroup_v3.h stm8compilersettingsgroup_v3.cpp stm8compilersettingsgroup_v3.h stm8generalsettingsgroup_v3.cpp stm8generalsettingsgroup_v3.h stm8linkersettingsgroup_v3.cpp stm8linkersettingsgroup_v3.h ) list_transform_prepend(ARCHS_STM8_SOURCES archs/stm8/) set(ARCHS_MSP430_SOURCES msp430archiversettingsgroup_v7.cpp msp430archiversettingsgroup_v7.h msp430assemblersettingsgroup_v7.cpp msp430assemblersettingsgroup_v7.h msp430buildconfigurationgroup_v7.cpp msp430buildconfigurationgroup_v7.h msp430compilersettingsgroup_v7.cpp msp430compilersettingsgroup_v7.h msp430generalsettingsgroup_v7.cpp msp430generalsettingsgroup_v7.h msp430linkersettingsgroup_v7.cpp msp430linkersettingsgroup_v7.h ) list_transform_prepend(ARCHS_MSP430_SOURCES archs/msp430/) add_qbs_plugin(iarewgenerator DEPENDS qbscore SOURCES ${COMMON_SOURCES} ${ARCHS_ARM_SOURCES} ${ARCHS_AVR_SOURCES} ${ARCHS_MCS51_SOURCES} ${ARCHS_STM8_SOURCES} ${ARCHS_MSP430_SOURCES} ) qbs-src-3.3.1/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp0000644000175100017510000000353315232633614026452 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewtoolchainpropertygroup.h" namespace qbs { IarewToolchainPropertyGroup::IarewToolchainPropertyGroup( const QByteArray &toolchainName) : gen::xml::PropertyGroup(QByteArrayLiteral("toolchain")) { // Append toolchain name property item. appendProperty(QByteArrayLiteral("name"), toolchainName); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp0000644000175100017510000000440515232633614026631 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewsourcefilepropertygroup.h" #include "iarewutils.h" #include #include namespace qbs { IarewSourceFilePropertyGroup::IarewSourceFilePropertyGroup( const GeneratableProject &genProject, const ArtifactData &sourceArtifact) : gen::xml::PropertyGroup(QByteArrayLiteral("file")) { // Create file path property item. const QString fullFilePath = sourceArtifact.filePath(); const QString relativeFilePath = IarewUtils::projectRelativeFilePath( genProject.baseBuildDirectory().absolutePath(), fullFilePath); appendChild(QByteArrayLiteral("name"), relativeFilePath); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewworkspace.h0000644000175100017510000000435615232633614023257 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_IAREWWORKSPACE_H #define QBS_IAREWWORKSPACE_H #include #include namespace qbs { class IarewWorkspace final : public gen::xml::Workspace { public: explicit IarewWorkspace(const QString &workspacePath); void addProject(const QString &projectPath) final; }; } // namespace qbs #endif // QBS_IAREWWORKSPACE_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewsettingspropertygroup.h0000644000175100017510000000500715232633614025775 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSETTINGSPROPERTYGROUP_H #define QBS_IAREWSETTINGSPROPERTYGROUP_H #include namespace qbs { class IarewSettingsPropertyGroup : public gen::xml::PropertyGroup { public: explicit IarewSettingsPropertyGroup(); void setName(const QByteArray &name); QByteArray name() const; void setArchiveVersion(int archiveVersion); int archiveVersion() const; protected: void setDataVersion(int dataVersion); void setDataDebugInfo(int debugInfo); void addOptionsGroup(const QByteArray &name, QVariantList states, int version = -1); private: // Don't delete all this RAW pointers explicitly! gen::xml::Property *m_nameProperty = nullptr; gen::xml::Property *m_archiveVersionProperty = nullptr; gen::xml::Property *m_dataPropertyGroup = nullptr; gen::xml::Property *m_dataVersionProperty = nullptr; gen::xml::Property *m_dataDebugProperty = nullptr; }; } // namespace qbs #endif // QBS_IAREWSETTINGSPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp0000644000175100017510000000446615232633614027023 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewsourcefilepropertygroup.h" #include "iarewsourcefilespropertygroup.h" #include #include namespace qbs { IarewSourceFilesPropertyGroup::IarewSourceFilesPropertyGroup( const GeneratableProject &genProject, const QString &filesGroupName, const QList &sourceFiles) : gen::xml::PropertyGroup(QByteArrayLiteral("group")) { // Create group name property item. appendChild(QByteArrayLiteral("name"), filesGroupName); // Create file paths property items. for (const auto &sourceFile : sourceFiles) appendChild(genProject, sourceFile); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewprojectwriter.h0000644000175100017510000000375615232633614024167 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWPROJECTWRITER_H #define QBS_IAREWPROJECTWRITER_H #include namespace qbs { class IarewProjectWriter final : public gen::xml::ProjectWriter { Q_DISABLE_COPY(IarewProjectWriter) public: explicit IarewProjectWriter(std::ostream *device); private: void visitProjectStart(const gen::xml::Project *project) final; void visitProjectEnd(const gen::xml::Project *project) final; }; } // namespace qbs #endif // QBS_IAREWPROJECTWRITER_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewgenerator.h0000644000175100017510000000516015232633614023241 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWGENERATOR_H #define QBS_IAREWGENERATOR_H #include "iarewversioninfo.h" #include #include namespace qbs { class IarewProject; class IarewWorkspace; class IarewGenerator final : public ProjectGenerator, private IGeneratableProjectVisitor { public: explicit IarewGenerator(const gen::VersionInfo &versionInfo); QString generatorName() const final; void generate() final; private: void reset(); void visitProject(const GeneratableProject &project) final; void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) final; void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) final; const gen::VersionInfo m_versionInfo; std::shared_ptr m_workspace; QString m_workspaceFilePath; std::map> m_projects; }; } // namespace qbs #endif // QBS_IAREWGENERATOR_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewworkspace.cpp0000644000175100017510000000504515232633614023606 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "iarewworkspace.h" #include namespace qbs { IarewWorkspace::IarewWorkspace(const QString &workspacePath) : gen::xml::Workspace(workspacePath) { appendChild( QByteArrayLiteral("batchBuild")); } void IarewWorkspace::addProject(const QString &projectFilePath) { const QString relativeProjectPath = QLatin1String("$WS_DIR$/") + m_baseDirectory.relativeFilePath(projectFilePath); const auto projectGroup = appendChild( QByteArrayLiteral("project")); projectGroup->appendProperty("path", relativeProjectPath); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewworkspacewriter.h0000644000175100017510000000401215232633614024501 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWWORKSPACEWRITER_H #define QBS_IAREWWORKSPACEWRITER_H #include namespace qbs { class IarewWorkspaceWriter final : public gen::xml::WorkspaceWriter { Q_DISABLE_COPY(IarewWorkspaceWriter) public: explicit IarewWorkspaceWriter(std::ostream *device); private: void visitWorkspaceStart(const gen::xml::Workspace *workspace) final; void visitWorkspaceEnd(const gen::xml::Workspace *workspace) final; }; } // namespace qbs #endif // QBS_IAREWWORKSPACEWRITER_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/0000755000175100017510000000000015232633614021150 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/0000755000175100017510000000000015232633614021727 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h0000644000175100017510000000463615232633614030041 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H #define QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmAssemblerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit ArmAssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildLanguagePage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h0000644000175100017510000000506215232633614027473 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMGENERALSETTINGSGROUP_V8_H #define QBS_IAREWARMGENERALSETTINGSGROUP_V8_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmGeneralSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit ArmGeneralSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildTargetPage(const ProductData &qbsProduct); void buildLibraryOptionsOnePage(const ProductData &qbsProduct); void buildLibraryOptionsTwoPage(const ProductData &qbsProduct); void buildLibraryConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMGENERALSETTINGSGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h0000644000175100017510000000437515232633614027667 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H #define QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmArchiverSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit ArmArchiverSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h0000644000175100017510000000512115232633614027664 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H #define QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmCompilerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit ArmCompilerSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const ProductData &qbsProduct); void buildLanguageOnePage(const ProductData &qbsProduct); void buildLanguageTwoPage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildCodePage(const ProductData &qbsProduct); }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp0000644000175100017510000004703715232633614030036 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armgeneralsettingsgroup_v8.h" #include "../../iarewutils.h" #include namespace qbs { namespace iarew { namespace arm { namespace v8 { constexpr int kGeneralArchiveVersion = 3; constexpr int kGeneralDataVersion = 30; namespace { struct CpuCoreEntry final { enum CpuCoreCode { Arm7tdmi = 0, Arm7tdmis = 1, Arm710t = 2, Arm720t = 3, Arm740t = 4, Arm7ejs = 5, Arm9tdmi = 6, Arm920t = 7, Arm922t = 8, Arm940t = 9, Arm9e = 10, Arm9es = 11, Arm926ejs = 12, Arm946es = 13, Arm966es = 14, Arm968es = 15, Arm10e = 16, Arm1020e = 17, Arm1022e = 18, Arm1026ejs = 19, Arm1136j = 20, Arm1136js = 21, Arm1176j = 24, Arm1176js = 25, Xscale = 32, XscaleIr7 = 33, CortexM0 = 34, CortexM0Plus = 35, CortexM1 = 36, CortexMs1 = 37, CortexM3 = 38, CortexM4 = 39, CortexM7 = 41, CortexR4 = 42, CortexR5 = 44, CortexR7 = 46, CortexR8 = 48, CortexR52 = 49, CortexA5 = 50, CortexA7 = 52, CortexA8 = 53, CortexA9 = 54, CortexA15 = 55, CortexA17 = 56, CortexM23 = 58, CortexM33 = 59 }; // Required to compile in MSVC2015. CpuCoreEntry(CpuCoreCode cc, QByteArray tf) : coreCode(cc), targetFlag(std::move(tf)) {} CpuCoreCode coreCode = Arm7tdmi; QByteArray targetFlag; }; // Dictionary of known ARM CPU cores and its compiler options. const CpuCoreEntry cpusDict[] = { {CpuCoreEntry::Arm7tdmi, "arm7tdmi"}, // same as 'sc100' {CpuCoreEntry::Arm7tdmis, "arm7tdmi-s"}, {CpuCoreEntry::Arm710t, "arm710t"}, {CpuCoreEntry::Arm720t, "arm720t"}, {CpuCoreEntry::Arm740t, "arm740t"}, {CpuCoreEntry::Arm7ejs, "arm7ej-s"}, {CpuCoreEntry::Arm9tdmi, "arm9tdmi"}, {CpuCoreEntry::Arm920t, "arm920t"}, {CpuCoreEntry::Arm922t, "arm922t"}, {CpuCoreEntry::Arm940t, "arm940t"}, {CpuCoreEntry::Arm9e, "arm9e"}, {CpuCoreEntry::Arm9es, "arm9e-s"}, {CpuCoreEntry::Arm926ejs, "arm926ej-s"}, {CpuCoreEntry::Arm946es, "arm946e-s"}, {CpuCoreEntry::Arm966es, "arm966e-s"}, {CpuCoreEntry::Arm968es, "arm968e-s"}, {CpuCoreEntry::Arm10e, "arm10e"}, {CpuCoreEntry::Arm1020e, "arm1020e"}, {CpuCoreEntry::Arm1022e, "arm1022e"}, {CpuCoreEntry::Arm1026ejs, "arm1026ej-s"}, {CpuCoreEntry::Arm1136j, "arm1136j"}, {CpuCoreEntry::Arm1136js, "arm1136j-s"}, {CpuCoreEntry::Arm1176j, "arm1176j"}, {CpuCoreEntry::Arm1176js, "arm1176j-s"}, {CpuCoreEntry::Xscale, "xscale"}, {CpuCoreEntry::XscaleIr7, "xscale-ir7"}, {CpuCoreEntry::CortexM0, "cortex-m0"}, {CpuCoreEntry::CortexM0Plus, "cortex-m0+"}, // same as 'sc000' {CpuCoreEntry::CortexM1, "cortex-m1"}, {CpuCoreEntry::CortexMs1, "cortex-ms1"}, {CpuCoreEntry::CortexM3, "cortex-m3"}, // same as 'sc300' {CpuCoreEntry::CortexM4, "cortex-m4"}, {CpuCoreEntry::CortexM7, "cortex-m7"}, {CpuCoreEntry::CortexR4, "cortex-r4"}, {CpuCoreEntry::CortexR5, "cortex-r5"}, {CpuCoreEntry::CortexR7, "cortex-r7"}, {CpuCoreEntry::CortexR8, "cortex-r8"}, {CpuCoreEntry::CortexR52, "cortex-r52"}, {CpuCoreEntry::CortexA5, "cortex-a5"}, {CpuCoreEntry::CortexA7, "cortex-a7"}, {CpuCoreEntry::CortexA8, "cortex-a8"}, {CpuCoreEntry::CortexA9, "cortex-a9"}, {CpuCoreEntry::CortexA15, "cortex-a15"}, {CpuCoreEntry::CortexA17, "cortex-a17"}, {CpuCoreEntry::CortexM23, "cortex-m23"}, {CpuCoreEntry::CortexM33, "cortex-m33"}, }; struct FpuCoreEntry final { enum FpuRegistersCount { NoFpuRegisters, Fpu16Registers, Fpu32Registers }; enum FpuCoreCode { NoVfp = 0, Vfp2 = 2, Vfp3d16 = 3, Vfp3 = 3, Vfp4sp = 4, Vfp4d16 = 5, Vfp4 = 5, Vfp5sp = 6, Vfp5d16 = 7, Vfp9s = 8 }; // Required to compile in MSVC2015. FpuCoreEntry(FpuCoreCode cc, FpuRegistersCount rc, QByteArray tf) : coreCode(cc), regsCount(rc), targetFlag(std::move(tf)) {} FpuCoreCode coreCode = NoVfp; FpuRegistersCount regsCount = NoFpuRegisters; QByteArray targetFlag; }; // Dictionary of known ARM FPU cores and its compiler options. const FpuCoreEntry fpusDict[] = { {FpuCoreEntry::Vfp2, FpuCoreEntry::NoFpuRegisters, "vfpv2"}, {FpuCoreEntry::Vfp3d16, FpuCoreEntry::Fpu16Registers, "vfpv3_d16"}, {FpuCoreEntry::Vfp3, FpuCoreEntry::Fpu32Registers, "vfpv3"}, {FpuCoreEntry::Vfp4sp, FpuCoreEntry::Fpu16Registers, "vfpv4_sp"}, {FpuCoreEntry::Vfp4d16, FpuCoreEntry::Fpu16Registers, "vfpv4_d16"}, {FpuCoreEntry::Vfp4, FpuCoreEntry::Fpu32Registers, "vfpv4"}, {FpuCoreEntry::Vfp5sp, FpuCoreEntry::Fpu16Registers, "vfpv5_sp"}, {FpuCoreEntry::Vfp5d16, FpuCoreEntry::Fpu16Registers, "vfpv5_d16"}, {FpuCoreEntry::Vfp9s, FpuCoreEntry::NoFpuRegisters, "vfp9-s"}, }; // Target page options. struct TargetPageOptions final { enum Endianness { LittleEndian, BigEndian }; explicit TargetPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags")}); // Detect target CPU code. const QString cpuValue = IarewUtils::flagValue( flags, QStringLiteral("--cpu")) .toLower(); const auto cpuEnd = std::cend(cpusDict); const auto cpuIt = std::find_if(std::cbegin(cpusDict), cpuEnd, [cpuValue]( const CpuCoreEntry &entry) { return entry.targetFlag == cpuValue.toLatin1(); }); if (cpuIt != cpuEnd) targetCpu = cpuIt->coreCode; // Detect target FPU code. const QString fpuValue = IarewUtils::flagValue( flags, QStringLiteral("--fpu")) .toLower(); const auto fpuEnd = std::cend(fpusDict); const auto fpuIt = std::find_if(std::cbegin(fpusDict), fpuEnd, [fpuValue]( const FpuCoreEntry &entry) { return entry.targetFlag == fpuValue.toLatin1(); }); if (fpuIt != fpuEnd) { targetFpu = fpuIt->coreCode; targetFpuRegs = fpuIt->regsCount; } // Detect endian. const QString prop = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("endianness")); if (prop == QLatin1String("big")) endianness = TargetPageOptions::BigEndian; else if (prop == QLatin1String("little")) endianness = TargetPageOptions::LittleEndian; } CpuCoreEntry::CpuCoreCode targetCpu = CpuCoreEntry::Arm7tdmi; FpuCoreEntry::FpuCoreCode targetFpu = FpuCoreEntry::NoVfp; FpuCoreEntry::FpuRegistersCount targetFpuRegs = FpuCoreEntry::NoFpuRegisters; Endianness endianness = LittleEndian; }; // Library 1 page options. struct LibraryOnePageOptions final { enum PrintfFormatter { PrintfAutoFormatter, PrintfFullFormatter, PrintfLargeFormatter, PrintfSmallFormatter, PrintfTinyFormatter }; enum ScanfFormatter { ScanfAutoFormatter, ScanfFullFormatter, ScanfLargeFormatter, ScanfSmallFormatter }; explicit LibraryOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (*flagIt != QLatin1String("--redirect")) continue; ++flagIt; if (flagIt->startsWith(QLatin1String("_printf="), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(1).toLower(); if (prop == QLatin1String("_printffullnomb")) printfFormatter = LibraryOnePageOptions::PrintfFullFormatter; else if (prop == QLatin1String("_printflargenomb")) printfFormatter = LibraryOnePageOptions::PrintfLargeFormatter; else if (prop == QLatin1String("_printfsmallnomb")) printfFormatter = LibraryOnePageOptions::PrintfSmallFormatter; else if (prop == QLatin1String("_printftiny")) printfFormatter = LibraryOnePageOptions::PrintfTinyFormatter; } else if (flagIt->startsWith(QLatin1String("_scanf="), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(1).toLower();; if (prop == QLatin1String("_scanffullnomb")) scanfFormatter = LibraryOnePageOptions::ScanfFullFormatter; else if (prop == QLatin1String("_scanflargenomb")) scanfFormatter = LibraryOnePageOptions::ScanfLargeFormatter; else if (prop == QLatin1String("_scanfsmallnomb")) scanfFormatter = LibraryOnePageOptions::ScanfSmallFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Library 2 page options. struct LibraryTwoPageOptions final { enum HeapType { AutomaticHeap, AdvancedHeap, BasicHeap, NoFreeHeap }; explicit LibraryTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); if (flags.contains(QLatin1String("--advanced_heap"))) heapType = LibraryTwoPageOptions::AdvancedHeap; else if (flags.contains(QLatin1String("--basic_heap"))) heapType = LibraryTwoPageOptions::BasicHeap; else if (flags.contains(QLatin1String("--no_free_heap"))) heapType = LibraryTwoPageOptions::NoFreeHeap; else heapType = LibraryTwoPageOptions::AutomaticHeap; } HeapType heapType = AutomaticHeap; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalLibrary, FullLibrary, CustomLibrary }; enum ThreadSupport { NoThread, EnableThread }; enum LowLevelInterface { NoInterface, SemihostedInterface }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QFileInfo dlibFileInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); if (!dlibFileInfo.exists()) { dlibType = LibraryConfigPageOptions::NoLibrary; } else { const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QString dlibFilePath = dlibFileInfo.absoluteFilePath(); if (dlibFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { if (dlibFilePath.endsWith(QLatin1String("dlib_config_normal.h"), Qt::CaseInsensitive)) { dlibType = LibraryConfigPageOptions::NormalLibrary; } else if (dlibFilePath.endsWith( QLatin1String("dlib_config_full.h"), Qt::CaseInsensitive)) { dlibType = LibraryConfigPageOptions::FullLibrary; } else { dlibType = LibraryConfigPageOptions::CustomLibrary; } dlibConfigPath = IarewUtils::toolkitRelativeFilePath( toolkitPath, dlibFilePath); } else { dlibType = LibraryConfigPageOptions::CustomLibrary; dlibConfigPath = IarewUtils::projectRelativeFilePath( baseDirectory, dlibFilePath); } } threadSupport = flags.contains(QLatin1String("--threaded_lib")) ? LibraryConfigPageOptions::EnableThread : LibraryConfigPageOptions::NoThread; lowLevelInterface = flags.contains(QLatin1String("--semihosting")) ? LibraryConfigPageOptions::SemihostedInterface : LibraryConfigPageOptions::NoInterface; } RuntimeLibrary dlibType = NoLibrary; QString dlibConfigPath; ThreadSupport threadSupport = NoThread; LowLevelInterface lowLevelInterface = NoInterface; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; } // namespace // ArmGeneralSettingsGroup ArmGeneralSettingsGroup::ArmGeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildLibraryOptionsOnePage(qbsProduct); buildLibraryOptionsTwoPage(qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); } void ArmGeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'GBECoreSlave', 'CoreVariant', 'GFPUCoreSlave2' items // (Processor variant chooser). addOptionsGroup(QByteArrayLiteral("GBECoreSlave"), {opts.targetCpu}, 26); addOptionsGroup(QByteArrayLiteral("CoreVariant"), {opts.targetCpu}, 26); addOptionsGroup(QByteArrayLiteral("GFPUCoreSlave2"), {opts.targetCpu}, 26); // Add 'FPU2', 'NrRegs' item (Floating point settings chooser). addOptionsGroup(QByteArrayLiteral("FPU2"), {opts.targetFpu}, 0); addOptionsGroup(QByteArrayLiteral("NrRegs"), {opts.targetFpuRegs}, 0); // Add 'GEndianMode' item (Endian mode chooser). addOptionsGroup(QByteArrayLiteral("GEndianMode"), {opts.endianness}); } void ArmGeneralSettingsGroup::buildLibraryOptionsOnePage( const ProductData &qbsProduct) { const LibraryOnePageOptions opts(qbsProduct); // Add 'OGPrintfVariant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("OGPrintfVariant"), {opts.printfFormatter}); // Add 'OGScanfVariant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("OGScanfVariant"), {opts.scanfFormatter}); } void ArmGeneralSettingsGroup::buildLibraryOptionsTwoPage( const ProductData &qbsProduct) { const LibraryTwoPageOptions opts(qbsProduct); // Add 'OgLibHeap' item (Heap selection: // auto/advanced/basic/nofree). addOptionsGroup(QByteArrayLiteral("OgLibHeap"), {opts.heapType}); } void ArmGeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GRuntimeLibSelect', 'GRuntimeLibSelectSlave' // and 'RTConfigPath2' items // (Link with runtime: none/normal/full/custom). addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), {opts.dlibType}); addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), {opts.dlibType}); addOptionsGroup(QByteArrayLiteral("RTConfigPath2"), {opts.dlibConfigPath}); // Add 'GRuntimeLibThreads'item // (Enable thread support in library). addOptionsGroup(QByteArrayLiteral("GRuntimeLibThreads"), {opts.threadSupport}); // Add 'GenLowLevelInterface' item (Library low-level // interface: none/semihosted/breakpoint). addOptionsGroup(QByteArrayLiteral("GenLowLevelInterface"), {opts.lowLevelInterface}); } void ArmGeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item // (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item // (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item // (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item // (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h0000644000175100017510000000564415232633614027350 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMLINKERSETTINGSGROUP_V8_H #define QBS_IAREWARMLINKERSETTINGSGROUP_V8_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmLinkerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit ArmLinkerSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryPage(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps); void buildOutputPage(const ProductData &qbsProduct); void buildInputPage(const ProductData &qbsProduct); void buildListPage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildAdvancedPage(const ProductData &qbsProduct); void buildDefinesPage(const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildExtraOptionsPage(const ProductData &qbsProduct); QVariantList m_extraOptions; }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMLINKERSETTINGSGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp0000644000175100017510000002052515232633614030367 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armassemblersettingsgroup_v8.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { constexpr int kAssemblerArchiveVersion = 2; constexpr int kAssemblerDataVersion = 10; namespace { // Language page options. struct LanguagePageOptions final { enum MacroQuoteCharacter { AngleBracketsQuote, RoundBracketsQuote, SquareBracketsQuote, FigureBracketsQuote }; explicit LanguagePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleAssemblerFlags(qbsProps); enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); allowAlternativeRegister = flags.contains(QLatin1String("-j")); disableCodeMemoryDataReads = flags.contains( QLatin1String("--no_literal_pool")); if (flags.contains(QLatin1String("-M<>"))) macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; else if (flags.contains(QLatin1String("-M()"))) macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; else if (flags.contains(QLatin1String("-M[]"))) macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; else if (flags.contains(QLatin1String("-M{}"))) macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; } MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; int enableSymbolsCaseSensitive = 0; int allowAlternativeRegister = 0; int disableCodeMemoryDataReads = 0; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (warningLevel == QLatin1String("all")) { enableWarnings = 0; enableAllWarnings = 0; } else if (warningLevel == QLatin1String("none")) { enableWarnings = 1; enableAllWarnings = 0; } else { enableWarnings = 0; enableAllWarnings = 1; } } int enableWarnings = 0; int enableAllWarnings = 0; }; } // namespace // ArmAssemblerSettingsGroup ArmAssemblerSettingsGroup::ArmAssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("AARM")); setArchiveVersion(kAssemblerArchiveVersion); setDataVersion(kAssemblerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildLanguagePage(qbsProduct); buildOutputPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void ArmAssemblerSettingsGroup::buildLanguagePage( const ProductData &qbsProduct) { const LanguagePageOptions opts(qbsProduct); // Add 'ACaseSensitivity' item (User symbols are case sensitive). addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), {opts.enableSymbolsCaseSensitive}); // Add 'AltRegisterNames' item (Allow alternative register names, // mnemonics and operands). addOptionsGroup(QByteArrayLiteral("AltRegisterNames"), {opts.allowAlternativeRegister}); // Add 'AsmNoLiteralPool' item (No data reads in code memory). addOptionsGroup(QByteArrayLiteral("AsmNoLiteralPool"), {opts.disableCodeMemoryDataReads}); // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). addOptionsGroup(QByteArrayLiteral("MacroChars"), {opts.macroQuoteCharacter}, 0); } void ArmAssemblerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'ADebug' item (Generate debug information). addOptionsGroup(QByteArrayLiteral("ADebug"), {opts.debugInfo}); } void ArmAssemblerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'ADefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("ADefines"), opts.defineSymbols); // Add 'AUserIncludes' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("AUserIncludes"), opts.includePaths); } void ArmAssemblerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'AWarnEnable' item (Enable/disable warnings). addOptionsGroup(QByteArrayLiteral("AWarnEnable"), {opts.enableWarnings}); // Add 'AWarnWhat' item (Enable/disable all warnings). addOptionsGroup(QByteArrayLiteral("AWarnWhat"), {opts.enableAllWarnings}); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp0000644000175100017510000000630115232633614030211 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armarchiversettingsgroup_v8.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { constexpr int kArchiverArchiveVersion = 0; constexpr int kArchiverDataVersion = 0; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { outputFile = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); } QString outputFile; }; } // namespace // ArmArchiverSettingsGroup ArmArchiverSettingsGroup::ArmArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("IARCHIVE")); setArchiveVersion(kArchiverArchiveVersion); setDataVersion(kArchiverDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(buildRootDirectory, qbsProduct); } void ArmArchiverSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'IarchiveOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("IarchiveOverride"), {1}); // Add 'IarchiveOutput' item (Output filename). addOptionsGroup(QByteArrayLiteral("IarchiveOutput"), {opts.outputFile}); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h0000644000175100017510000000512415232633614030163 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H #define QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H #include namespace qbs { namespace iarew { namespace arm { namespace v8 { class ArmBuildConfigurationGroup final : public gen::xml::PropertyGroup { private: explicit ArmBuildConfigurationGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class ArmBuildConfigurationGroupFactory; }; class ArmBuildConfigurationGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs #endif // QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp0000644000175100017510000000734015232633614030520 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armarchiversettingsgroup_v8.h" #include "armassemblersettingsgroup_v8.h" #include "armbuildconfigurationgroup_v8.h" #include "armcompilersettingsgroup_v8.h" #include "armgeneralsettingsgroup_v8.h" #include "armlinkersettingsgroup_v8.h" #include "../../iarewtoolchainpropertygroup.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { ArmBuildConfigurationGroup::ArmBuildConfigurationGroup( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("configuration") { // Append configuration name item. const QString cfgName = gen::utils::buildConfigurationName(qbsProject); appendProperty("name", cfgName); // Apend toolchain name group item. appendChild("ARM"); // Append debug info item. const int debugBuild = gen::utils::debugInformation(qbsProduct); appendProperty("debug", debugBuild); // Append settings group items. appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); } bool ArmBuildConfigurationGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Arm && version.majorVersion() == 8; } std::unique_ptr ArmBuildConfigurationGroupFactory::create( const qbs::Project &qbsProject, const qbs::ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new ArmBuildConfigurationGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp0000644000175100017510000004420015232633614030220 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armcompilersettingsgroup_v8.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace arm { namespace v8 { constexpr int kCompilerArchiveVersion = 2; constexpr int kCompilerDataVersion = 34; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Language 1 page options. struct LanguageOnePageOptions final { enum LanguageExtension { CLanguageExtension, CxxLanguageExtension, AutoLanguageExtension }; enum CLanguageDialect { C89LanguageDialect, C11LanguageDialect }; enum LanguageConformance { AllowIarExtension, RelaxedStandard, StrictStandard }; explicit LanguageOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); // File extension based by default. languageExtension = LanguageOnePageOptions::AutoLanguageExtension; // Language dialect. const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("cLanguageVersion")}); cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89")) ? LanguageOnePageOptions::C89LanguageDialect : LanguageOnePageOptions::C11LanguageDialect; const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // Language conformance. if (flags.contains(QLatin1String("-e"))) languageConformance = LanguageOnePageOptions::AllowIarExtension; else if (flags.contains(QLatin1String("--strict"))) languageConformance = LanguageOnePageOptions::StrictStandard; else languageConformance = LanguageOnePageOptions::RelaxedStandard; // Exceptions, rtti, static desrtuction. enableExceptions = !flags.contains(QLatin1String("--no_exceptions")); enableRtti = !flags.contains(QLatin1String("--no_rtti")); destroyStaticObjects = !flags.contains( QLatin1String("--no_static_destruction")); allowVla = flags.contains(QLatin1String("--vla")); enableInlineSemantics = flags.contains(QLatin1String("--use_c++_inline")); requirePrototypes = flags.contains(QLatin1String("--require_prototypes")); } LanguageExtension languageExtension = AutoLanguageExtension; CLanguageDialect cLanguageDialect = C89LanguageDialect; LanguageConformance languageConformance = AllowIarExtension; // C++ options. int enableExceptions = 0; int enableRtti = 0; int destroyStaticObjects = 0; int allowVla = 0; int enableInlineSemantics = 0; int requirePrototypes = 0; }; // Language 2 page options. struct LanguageTwoPageOptions final { enum PlainCharacter { SignedCharacter, UnsignedCharacter }; enum FloatingPointSemantic { StrictSemantic, RelaxedSemantic }; explicit LanguageTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); plainCharacter = flags.contains(QLatin1String("--char_is_signed")) ? LanguageTwoPageOptions::SignedCharacter : LanguageTwoPageOptions::UnsignedCharacter; floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) ? LanguageTwoPageOptions::RelaxedSemantic : LanguageTwoPageOptions::StrictSemantic; } PlainCharacter plainCharacter = SignedCharacter; FloatingPointSemantic floatingPointSemantic = StrictSemantic; }; // Optimizations page options. struct OptimizationsPageOptions final { // Optimizations level radio-buttons with // combo-box on "level" widget. enum Strategy { StrategyBalanced, StrategySize, StrategySpeed }; enum Level { LevelNone, LevelLow, LevelMedium, LevelHigh }; enum LevelSlave { LevelSlave0, LevelSlave1, LevelSlave2, LevelSlave3 }; explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("none")) { optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; optimizationLevel = OptimizationsPageOptions::LevelNone; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; } else if (optimization == QLatin1String("fast")) { optimizationStrategy = OptimizationsPageOptions::StrategySpeed; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } else if (optimization == QLatin1String("small")) { optimizationStrategy = OptimizationsPageOptions::StrategySize; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); enableCommonSubexpressionElimination = !flags.contains( QLatin1String("--no_cse")); enableLoopUnroll = !flags.contains( QLatin1String("--no_unroll")); enableFunctionInlining = !flags.contains( QLatin1String("--no_inline")); enableCodeMotion = !flags.contains( QLatin1String("--no_code_motion")); enableTypeBasedAliasAnalysis = !flags.contains( QLatin1String("--no_tbaa")); enableStaticClustering = !flags.contains( QLatin1String("--no_clustering")); enableInstructionScheduling = !flags.contains( QLatin1String("--no_scheduling")); enableVectorization = flags.contains( QLatin1String("--vectorize")); disableSizeConstraints = flags.contains( QLatin1String("--no_size_constraints")); } Strategy optimizationStrategy = StrategyBalanced; Level optimizationLevel = LevelNone; LevelSlave optimizationLevelSlave = LevelSlave0; // Eight bit-field flags on "enabled optimizations" widget. int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. int enableLoopUnroll = 0; // Loop unrolling. int enableFunctionInlining = 0; // Function inlining. int enableCodeMotion = 0; // Code motion. int enableTypeBasedAliasAnalysis = 0; // Type-based alias analysis. int enableStaticClustering = 0; // Static clustering. int enableInstructionScheduling = 0; // Instruction scheduling. int enableVectorization = 0; // Vectorization. // Separate "no size constraints" checkbox. int disableSizeConstraints = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int treatWarningsAsErrors = 0; }; // Code page options. struct CodePageOptions final { enum ProcessorMode { CpuArmMode, CpuThumbMode }; explicit CodePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QString cpuModeValue = IarewUtils::flagValue( flags, QStringLiteral("--cpu_mode")); if (cpuModeValue == QLatin1String("thumb")) cpuMode = CodePageOptions::CpuThumbMode; else if (cpuModeValue == QLatin1String("arm")) cpuMode = CodePageOptions::CpuArmMode; generateReadOnlyPosIndependentCode = flags.contains( QLatin1String("--ropi")); generateReadWritePosIndependentCode = flags.contains( QLatin1String("--rwpi")); disableDynamicReadWriteInitialization = flags.contains( QLatin1String("--no_rw_dynamic_init")); disableCodeMemoryDataReads = flags.contains( QLatin1String("--no_literal_pool")); } ProcessorMode cpuMode = CpuThumbMode; int generateReadOnlyPosIndependentCode = 0; int generateReadWritePosIndependentCode = 0; int disableDynamicReadWriteInitialization = 0; int disableCodeMemoryDataReads = 0; }; } // namespace // ArmCompilerSettingsGroup ArmCompilerSettingsGroup::ArmCompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProject) Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ICCARM")); setArchiveVersion(kCompilerArchiveVersion); setDataVersion(kCompilerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(qbsProduct); buildLanguageOnePage(qbsProduct); buildLanguageTwoPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); buildCodePage(qbsProduct); } void ArmCompilerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'CCDebugInfo' item (Generate debug info). addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), {opts.debugInfo}); } void ArmCompilerSettingsGroup::buildLanguageOnePage( const ProductData &qbsProduct) { const LanguageOnePageOptions opts(qbsProduct); // Add 'IccLang' item with 'auto-extension based' // value (Language: C/C++/Auto). addOptionsGroup(QByteArrayLiteral("IccLang"), {opts.languageExtension}); // Add 'IccCDialect' item (C dialect: c89/99/11). addOptionsGroup(QByteArrayLiteral("IccCDialect"), {opts.cLanguageDialect}); // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). addOptionsGroup(QByteArrayLiteral("CCLangConformance"), {opts.languageConformance}); // Add 'IccExceptions2' item (Enable exceptions). addOptionsGroup(QByteArrayLiteral("IccExceptions2"), {opts.enableExceptions}); // Add 'IccRTTI2' item (Enable RTTI). addOptionsGroup(QByteArrayLiteral("IccRTTI2"), {opts.enableRtti}); // Add 'IccStaticDestr' item (Destroy static objects). addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), {opts.destroyStaticObjects}); // Add 'IccAllowVLA' item (Allow VLA). addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), {opts.allowVla}); // Add 'IccCppInlineSemantics' item (C++ inline semantics). addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), {opts.enableInlineSemantics}); // Add 'CCRequirePrototypes' item (Require prototypes). addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), {opts.requirePrototypes}); } void ArmCompilerSettingsGroup::buildLanguageTwoPage( const ProductData &qbsProduct) { const LanguageTwoPageOptions opts(qbsProduct); // Add 'CCSignedPlainChar' item (Plain char is: signed/unsigned). addOptionsGroup(QByteArrayLiteral("CCSignedPlainChar"), {opts.plainCharacter}); // Add 'IccFloatSemantics' item // (Floating-point semantic: strict/relaxed). addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), {opts.floatingPointSemantic}); } void ArmCompilerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'CCOptStrategy', 'CCOptLevel' // and 'CCOptLevelSlave' items (Level). addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), {opts.optimizationStrategy}); addOptionsGroup(QByteArrayLiteral("CCOptLevel"), {opts.optimizationLevel}); addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), {opts.optimizationLevelSlave}); // Add 'CCAllowList' item (Enabled optimizations: 6 check boxes). const QString transformations = QStringLiteral("%1%2%3%4%5%6%7%8") .arg(opts.enableCommonSubexpressionElimination) .arg(opts.enableLoopUnroll) .arg(opts.enableFunctionInlining) .arg(opts.enableCodeMotion) .arg(opts.enableTypeBasedAliasAnalysis) .arg(opts.enableStaticClustering) .arg(opts.enableInstructionScheduling) .arg(opts.enableVectorization); addOptionsGroup(QByteArrayLiteral("CCAllowList"), {transformations}); // Add 'CCOptimizationNoSizeConstraints' item (No size constraints). addOptionsGroup(QByteArrayLiteral("CCOptimizationNoSizeConstraints"), {opts.disableSizeConstraints}); } void ArmCompilerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'CCDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("CCDefines"), opts.defineSymbols); // Add 'CCIncludePath2' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), opts.includePaths); } void ArmCompilerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), {opts.treatWarningsAsErrors}); } void ArmCompilerSettingsGroup::buildCodePage( const ProductData &qbsProduct) { const CodePageOptions opts(qbsProduct); // Add 'IProcessorMode2' item (Processor mode: arm/thumb). addOptionsGroup(QByteArrayLiteral("IProcessorMode2"), {opts.cpuMode}); // Add 'CCPosIndRopi' item (Code and read-only data "ropi"). addOptionsGroup(QByteArrayLiteral("CCPosIndRopi"), {opts.generateReadOnlyPosIndependentCode}); // Add 'CCPosIndRwpi' item (Read/write data "rwpi"). addOptionsGroup(QByteArrayLiteral("CCPosIndRwpi"), {opts.generateReadWritePosIndependentCode}); // Add 'CCPosIndNoDynInit' item (No dynamic read/write initialization). addOptionsGroup(QByteArrayLiteral("CCPosIndNoDynInit"), {opts.disableDynamicReadWriteInitialization}); // Add 'CCNoLiteralPool' item (No data reads in code memory). addOptionsGroup(QByteArrayLiteral("CCNoLiteralPool"), {opts.disableCodeMemoryDataReads}); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp0000644000175100017510000004336515232633614027705 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "armlinkersettingsgroup_v8.h" #include "../../iarewutils.h" #include namespace qbs { namespace iarew { namespace arm { namespace v8 { constexpr int kLinkerArchiveVersion = 0; constexpr int kLinkerDataVersion = 20; namespace { // Config page options. struct ConfigPageOptions final { explicit ConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); // Accumulate config definitions (if exists). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); configDefines = IarewUtils::flagValues( flags, QStringLiteral("--config_def")); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { if (!qbsGroup.isEnabled()) continue; const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); configFilePaths.push_back(path); } } } // Enumerate all product linker config files // (which are set trough '--config' option). const QVariantList configPathValues = IarewUtils::flagValues( flags, QStringLiteral("--config")); for (const auto &configPathValue : configPathValues) { const QString fullConfigPath = configPathValue.toString(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } } } QVariantList configFilePaths; QVariantList configDefines; }; // Library page options. struct LibraryPageOptions final { explicit LibraryPageOptions(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { const auto &qbsProps = qbsProduct.moduleProperties(); entryPoint = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("entryPoint")); // Add libraries search paths. const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList libraryPaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("libraryPaths")}); for (const QString &libraryPath : libraryPaths) { const QFileInfo libraryPathInfo(libraryPath); const QString fullLibrarySearchPath = libraryPathInfo.absoluteFilePath(); if (fullLibrarySearchPath.startsWith( toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullLibrarySearchPath); librarySearchPaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory,fullLibrarySearchPath); librarySearchPaths.push_back(path); } } // Add static libraries paths. const QStringList staticLibrariesProps = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); for (const QString &staticLibrary : staticLibrariesProps) { const QFileInfo staticLibraryInfo(staticLibrary); if (staticLibraryInfo.isAbsolute()) { const QString fullStaticLibraryPath = staticLibraryInfo.absoluteFilePath(); if (fullStaticLibraryPath.startsWith( toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullStaticLibraryPath); staticLibraries.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullStaticLibraryPath); staticLibraries.push_back(path); } } else { staticLibraries.push_back(staticLibrary); } } // Add static libraries from product dependencies. for (const ProductData &qbsProductDep : qbsProductDeps) { const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProductDep); staticLibraries.push_back(depBinaryPath); } const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); enableRuntimeLibsSearch = !flags.contains( QLatin1String("--no_library_search")); } QString entryPoint; QVariantList staticLibraries; QVariantList librarySearchPaths; int enableRuntimeLibsSearch = 0; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); debugInfo = !flags.contains(QLatin1String("--strip")); outputFile = gen::utils::targetBinary(qbsProduct); } int debugInfo = 0; QString outputFile; }; // Input page options. struct InputPageOptions final { explicit InputPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); keepSymbols = IarewUtils::flagValues(flags, QStringLiteral("--keep")); } QVariantList keepSymbols; }; // List page options. struct ListPageOptions final { enum ListingAction { NoListing, GenerateListing }; explicit ListPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); generateMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")) ? ListPageOptions::GenerateListing : ListPageOptions::NoListing; } ListingAction generateMap = GenerateListing; }; // Optimizations page options. struct OptimizationsPageOptions final { explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); inlineSmallRoutines = flags.contains(QLatin1String("--inline")); mergeDuplicateSections = flags.contains( QLatin1String("--merge_duplicate_sections")); virtualFuncElimination = flags.contains(QLatin1String("--vfe")); } int inlineSmallRoutines = 0; int mergeDuplicateSections = 0; int virtualFuncElimination = 0; }; // Advanced page options. struct AdvancedPageOptions final { explicit AdvancedPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); allowExceptions = !flags.contains(QLatin1String("--no_exceptions")); } int allowExceptions = 0; }; // Defines page options. struct DefinesPageOptions final { explicit DefinesPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); defineSymbols = IarewUtils::flagValues( flags, QStringLiteral("--define_symbol")); } QVariantList defineSymbols; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int treatWarningsAsErrors = 0; }; } // namespace // ArmLinkerSettingsGroup ArmLinkerSettingsGroup::ArmLinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { setName(QByteArrayLiteral("ILINK")); setArchiveVersion(kLinkerArchiveVersion); setDataVersion(kLinkerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildConfigPage(buildRootDirectory, qbsProduct); buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps); buildOutputPage(qbsProduct); buildInputPage(qbsProduct); buildListPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildAdvancedPage(qbsProduct); buildDefinesPage(qbsProduct); // Should be called as latest stage! buildExtraOptionsPage(qbsProduct); } void ArmLinkerSettingsGroup::buildConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { ConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'IlinkConfigDefines' item // (Configuration file symbol definitions). addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"), opts.configDefines); if (opts.configFilePaths.count() > 0) { // Note: IAR IDE does not allow to specify a multiple config files, // although the IAR linker support it. So, we use followig 'trick': // we take a first config file and to add it as usual to required items; // and then an other remainders we forward to the "Extra options page". const QVariant configPath = opts.configFilePaths.takeFirst(); // Add 'IlinkIcfOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"), {1}); // Add 'IlinkIcfFile' item (Linker configuration file). addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"), {configPath}); // Add remainder configuration files to the "Extra options page". if (!opts.configFilePaths.isEmpty()) { for (QVariant &configPath : opts.configFilePaths) configPath = QString(QStringLiteral("--config ") + configPath.toString()); m_extraOptions << opts.configFilePaths; } } } void ArmLinkerSettingsGroup::buildLibraryPage( const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); // Add 'IlinkOverrideProgramEntryLabel' item // (Override default program entry). addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"), {1}); const int select = opts.entryPoint.isEmpty() ? 1 : 0; addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"), {select}); // Add 'IlinkProgramEntryLabel' item (Entry point name). addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"), {opts.entryPoint}); if (!opts.staticLibraries.isEmpty()) { // Add 'IlinkAdditionalLibs' item (Additional libraries). addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"), opts.staticLibraries); } // Add 'IlinkAutoLibEnable' item // (Automatic runtime library selection). addOptionsGroup(QByteArrayLiteral("IlinkAutoLibEnable"), {opts.enableRuntimeLibsSearch}); // Add library searh directories to the // "Extra options page", because IAR IDE // has not other options to add this paths. for (QVariant &libraryPath : opts.librarySearchPaths) libraryPath = QString(QStringLiteral("-L ") + libraryPath.toString()); m_extraOptions << opts.librarySearchPaths; } void ArmLinkerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'IlinkDebugInfoEnable' item // (Include debug information in output). addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"), {opts.debugInfo}); // Add 'IlinkOutputFile' item (Output filename). addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"), {opts.outputFile}); } void ArmLinkerSettingsGroup::buildInputPage( const ProductData &qbsProduct) { const InputPageOptions opts(qbsProduct); // Add 'IlinkKeepSymbols' item (). addOptionsGroup(QByteArrayLiteral("IlinkKeepSymbols"), opts.keepSymbols); } void ArmLinkerSettingsGroup::buildListPage( const ProductData &qbsProduct) { const ListPageOptions opts(qbsProduct); // Add 'IlinkMapFile' item (Generate linker map file). addOptionsGroup(QByteArrayLiteral("IlinkMapFile"), {opts.generateMap}); } void ArmLinkerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'IlinkOptInline' item (Inline small routines). addOptionsGroup(QByteArrayLiteral("IlinkOptInline"), {opts.inlineSmallRoutines}); // Add 'IlinkOptMergeDuplSections'item // (Merge duplicate sections). addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"), {opts.mergeDuplicateSections}); // Add 'IlinkOptUseVfe' item // (Perform C++ virtual functions elimination). addOptionsGroup(QByteArrayLiteral("IlinkOptUseVfe"), {opts.virtualFuncElimination}); } void ArmLinkerSettingsGroup::buildAdvancedPage( const ProductData &qbsProduct) { const AdvancedPageOptions opts(qbsProduct); // Add 'IlinkOptExceptionsAllow' item (Allow C++ exceptions). addOptionsGroup(QByteArrayLiteral("IlinkOptExceptionsAllow"), {opts.allowExceptions}); } void ArmLinkerSettingsGroup::buildDefinesPage( const ProductData &qbsProduct) { const DefinesPageOptions opts(qbsProduct); // Add 'IlinkDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("IlinkDefines"), {opts.defineSymbols}); } void ArmLinkerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'IlinkWarningsAreErrors' item // (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"), {opts.treatWarningsAsErrors}); } void ArmLinkerSettingsGroup::buildExtraOptionsPage( const ProductData &qbsProduct) { Q_UNUSED(qbsProduct) // Add 'IlinkUseExtraOptions' and 'IlinkExtraOptions' items. addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"), {1}); addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"), m_extraOptions); } } // namespace v8 } // namespace arm } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/0000755000175100017510000000000015232633614021740 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h0000644000175100017510000000514715232633614030211 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H #define QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H #include #include namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrBuildConfigurationGroup final : public gen::xml::PropertyGroup { private: explicit AvrBuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class AvrBuildConfigurationGroupFactory; }; class AvrBuildConfigurationGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp0000644000175100017510000004554415232633614030255 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrcompilersettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { constexpr int kCompilerArchiveVersion = 6; constexpr int kCompilerDataVersion = 17; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); moduleType = flags.contains(QLatin1String("--library_module")) ? OutputPageOptions::LibraryModule : OutputPageOptions::ProgramModule; debugInfo = gen::utils::debugInformation(qbsProduct); disableErrorMessages = flags.contains( QLatin1String("--no_ubrof_messages")); } int debugInfo = 0; int disableErrorMessages = 0; enum ModuleType { ProgramModule, LibraryModule}; ModuleType moduleType = ProgramModule; }; // Language one page options. struct LanguageOnePageOptions final { enum LanguageExtension { CLanguageExtension, CxxLanguageExtension, AutoLanguageExtension }; enum CLanguageDialect { C89LanguageDialect, C99LanguageDialect }; enum CxxLanguageDialect { EmbeddedCPlusPlus, ExtendedEmbeddedCPlusPlus }; enum LanguageConformance { AllowIarExtension, RelaxedStandard, StrictStandard }; explicit LanguageOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // File extension based by default. languageExtension = LanguageOnePageOptions::AutoLanguageExtension; // C language dialect. const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("cLanguageVersion")}); if (cLanguageVersion.contains(QLatin1String("c89"))) cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; else if (cLanguageVersion.contains(QLatin1String("c99"))) cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; // C++ language dialect. if (flags.contains(QLatin1String("--ec++"))) cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; else if (flags.contains(QLatin1String("--eec++"))) cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; // Language conformance. if (flags.contains(QLatin1String("-e"))) languageConformance = LanguageOnePageOptions::AllowIarExtension; else if (flags.contains(QLatin1String("--strict"))) languageConformance = LanguageOnePageOptions::StrictStandard; else languageConformance = LanguageOnePageOptions::RelaxedStandard; allowVla = flags.contains(QLatin1String("--vla")); useCppInlineSemantics = flags.contains( QLatin1String("--use_c++_inline")); requirePrototypes = flags.contains( QLatin1String("--require_prototypes")); destroyStaticObjects = !flags.contains( QLatin1String("--no_static_destruction")); } LanguageExtension languageExtension = AutoLanguageExtension; CLanguageDialect cLanguageDialect = C89LanguageDialect; CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; LanguageConformance languageConformance = AllowIarExtension; int allowVla = 0; int useCppInlineSemantics = 0; int requirePrototypes = 0; int destroyStaticObjects = 0; }; // Language two page options. struct LanguageTwoPageOptions final { enum PlainCharacter { SignedCharacter, UnsignedCharacter }; enum FloatingPointSemantic { StrictSemantic, RelaxedSemantic }; explicit LanguageTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); plainCharacter = flags.contains(QLatin1String("--char_is_signed")) ? LanguageTwoPageOptions::SignedCharacter : LanguageTwoPageOptions::UnsignedCharacter; floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) ? LanguageTwoPageOptions::RelaxedSemantic : LanguageTwoPageOptions::StrictSemantic; enableMultibyteSupport = flags.contains( QLatin1String("--enable_multibytes")); } PlainCharacter plainCharacter = SignedCharacter; FloatingPointSemantic floatingPointSemantic = StrictSemantic; int enableMultibyteSupport = 0; }; // Optimizations page options. struct OptimizationsPageOptions final { // Optimizations level radio-buttons with // combo-box on "level" widget. enum Strategy { StrategyBalanced, StrategySize, StrategySpeed }; enum Level { LevelNone, LevelLow, LevelMedium, LevelHigh }; enum LevelSlave { LevelSlave0, LevelSlave1, LevelSlave2, LevelSlave3 }; explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("none")) { optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; optimizationLevel = OptimizationsPageOptions::LevelNone; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; } else if (optimization == QLatin1String("fast")) { optimizationStrategy = OptimizationsPageOptions::StrategySpeed; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } else if (optimization == QLatin1String("small")) { optimizationStrategy = OptimizationsPageOptions::StrategySize; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); enableCommonSubexpressionElimination = !flags.contains( QLatin1String("--no_cse")); enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); enableVariableClustering = !flags.contains( QLatin1String("--no_clustering")); enableTypeBasedAliasAnalysis = !flags.contains( QLatin1String("--no_tbaa")); enableForceCrossCall = flags.contains( QLatin1String("--do_cross_call")); } Strategy optimizationStrategy = StrategyBalanced; Level optimizationLevel = LevelNone; LevelSlave optimizationLevelSlave = LevelSlave0; // Six bit-field flags on "enabled optimizations" widget. int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. int enableFunctionInlining = 0; // Function inlining. int enableCodeMotion = 0; // Code motion. int enableCrossCall = 0; // Cross call optimization. int enableVariableClustering = 0; // Variable clustering. int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. // Force cross-call optimization. int enableForceCrossCall = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; // Code page options. struct CodePageOptions final { explicit CodePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); placeConstantsInRam = flags.contains(QLatin1String("-y")); placeInitializiersInFlash = flags.contains( QLatin1String("--initializiers_in_flash")); forceVariablesGeneration = flags.contains( QLatin1String("--root_variables")); useIccA90CallingConvention = flags.contains( QLatin1String("--version1_calls")); lockRegistersCount = IarewUtils::flagValue( flags, QStringLiteral("--lock_regs")).toInt(); } int placeConstantsInRam = 0; int placeInitializiersInFlash = 0; int forceVariablesGeneration = 0; int useIccA90CallingConvention = 0; int lockRegistersCount = 0; }; } // namespace // AvrCompilerSettingsGroup AvrCompilerSettingsGroup::AvrCompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ICCAVR")); setArchiveVersion(kCompilerArchiveVersion); setDataVersion(kCompilerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(qbsProduct); buildLanguageOnePage(qbsProduct); buildLanguageTwoPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); buildCodePage(qbsProduct); } void AvrCompilerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'CCDebugInfo' item (Generate debug info). addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), {opts.debugInfo}); // Add 'CCNoErrorMsg' item (No error messages in output files). addOptionsGroup(QByteArrayLiteral("CCNoErrorMsg"), {opts.disableErrorMessages}); // Add 'CCOverrideModuleTypeDefault' item // (Override default module type). addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"), {1}); // Add 'CCRadioModuleType' item (Module type: program/library). addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"), {opts.moduleType}); } void AvrCompilerSettingsGroup::buildLanguageOnePage( const ProductData &qbsProduct) { const LanguageOnePageOptions opts(qbsProduct); // Add 'IccLang' item with 'auto-extension based' // value (Language: C/C++/Auto). addOptionsGroup(QByteArrayLiteral("IccLang"), {opts.languageExtension}); // Add 'IccCDialect' item (C dialect: c89/99/11). addOptionsGroup(QByteArrayLiteral("IccCDialect"), {opts.cLanguageDialect}); // Add 'IccCppDialect' item (C++ dialect: embedded/extended). addOptionsGroup(QByteArrayLiteral("IccCppDialect"), {opts.cxxLanguageDialect}); // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). addOptionsGroup(QByteArrayLiteral("CCExt"), {opts.languageConformance}); // Add 'IccAllowVLA' item (Allow VLA). addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), {opts.allowVla}); // Add 'IccCppInlineSemantics' item (C++ inline semantics). addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), {opts.useCppInlineSemantics}); // Add 'CCRequirePrototypes' item (Require prototypes). addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), {opts.requirePrototypes}); // Add 'IccStaticDestr' item (Destroy static objects). addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), {opts.destroyStaticObjects}); } void AvrCompilerSettingsGroup::buildLanguageTwoPage( const ProductData &qbsProduct) { const LanguageTwoPageOptions opts(qbsProduct); // Add 'CCCharIs' item (Plain char is: signed/unsigned). addOptionsGroup(QByteArrayLiteral("CCCharIs"), {opts.plainCharacter}); // Add 'IccFloatSemantics' item (Floatic-point // semantics: strict/relaxed conformance). addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), {opts.floatingPointSemantic}); // Add 'CCMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), {opts.enableMultibyteSupport}); } void AvrCompilerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'CCOptStrategy', 'CCOptLevel' and // 'CCOptLevelSlave' items (Level). addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), {opts.optimizationStrategy}); addOptionsGroup(QByteArrayLiteral("CCOptLevel"), {opts.optimizationLevel}); addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), {opts.optimizationLevelSlave}); // Add 'CCAllowList' item // (Enabled optimizations: 6 check boxes). const QString bitflags = QStringLiteral("%1%2%3%4%5%6") .arg(opts.enableCommonSubexpressionElimination) .arg(opts.enableFunctionInlining) .arg(opts.enableCodeMotion) .arg(opts.enableCrossCall) .arg(opts.enableVariableClustering) .arg(opts.enableTypeBasedAliasAnalysis); addOptionsGroup(QByteArrayLiteral("CCAllowList"), {bitflags}); // Add 'CCOptForceCrossCall' item // (Always do cross call optimization). addOptionsGroup(QByteArrayLiteral("CCOptForceCrossCall"), {opts.enableForceCrossCall}); } void AvrCompilerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'CCDefines' item (Defines symbols). addOptionsGroup(QByteArrayLiteral("CCDefines"), opts.defineSymbols); // Add 'newCCIncludePaths' item // (Additional include directories). addOptionsGroup(QByteArrayLiteral("newCCIncludePaths"), opts.includePaths); } void AvrCompilerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'CCWarnAsError' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("CCWarnAsError"), {opts.warningsAsErrors}); } void AvrCompilerSettingsGroup::buildCodePage( const ProductData &qbsProduct) { const CodePageOptions opts(qbsProduct); // Add 'CCConstInRAM' item (Place string literals // and constants in initialized RAM). addOptionsGroup(QByteArrayLiteral("CCConstInRAM"), {opts.placeConstantsInRam}); // Add 'CCInitInFlash' item (Place aggregate // initializiers in flash memory). addOptionsGroup(QByteArrayLiteral("CCInitInFlash"), {opts.placeInitializiersInFlash}); // Add 'CCForceVariables' item (Force generation of // all global and static variables). addOptionsGroup(QByteArrayLiteral("CCForceVariables"), {opts.forceVariablesGeneration}); // Add 'CCOldCallConv' item (Use ICCA90 1.x // calling convention). addOptionsGroup(QByteArrayLiteral("CCOldCallConv"), {opts.useIccA90CallingConvention}); // Add 'CCLockRegs' item (Number of registers to // lock for global variables). addOptionsGroup(QByteArrayLiteral("CCLockRegs"), {opts.lockRegistersCount}); } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp0000644000175100017510000002003315232633614030402 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrassemblersettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { constexpr int kAssemblerArchiveVersion = 5; constexpr int kAssemblerDataVersion = 11; namespace { // Language page options. struct LanguagePageOptions final { enum MacroQuoteCharacter { AngleBracketsQuote, RoundBracketsQuote, SquareBracketsQuote, FigureBracketsQuote }; explicit LanguagePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); enableMultibyteSupport = flags.contains(QLatin1String("-n")); if (flags.contains(QLatin1String("-M<>"))) macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; else if (flags.contains(QLatin1String("-M()"))) macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; else if (flags.contains(QLatin1String("-M[]"))) macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; else if (flags.contains(QLatin1String("-M{}"))) macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; } MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; int enableSymbolsCaseSensitive = 0; int enableMultibyteSupport = 0; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const auto &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (warningLevel == QLatin1String("all")) { enableWarnings = 0; enableAllWarnings = 0; } else if (warningLevel == QLatin1String("none")) { enableWarnings = 1; enableAllWarnings = 0; } else { enableWarnings = 0; enableAllWarnings = 1; } } int enableWarnings = 0; int enableAllWarnings = 0; }; } // namespace // AvrAssemblerSettingsGroup AvrAssemblerSettingsGroup::AvrAssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("AAVR")); setArchiveVersion(kAssemblerArchiveVersion); setDataVersion(kAssemblerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildLanguagePage(qbsProduct); buildOutputPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void AvrAssemblerSettingsGroup::buildLanguagePage( const ProductData &qbsProduct) { const LanguagePageOptions opts(qbsProduct); // Add 'ACaseSensitivity' item (User symbols are case sensitive). addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), {opts.enableSymbolsCaseSensitive}); // Add 'AsmMultiByteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("AsmMultiByteSupport"), {opts.enableMultibyteSupport}); // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). addOptionsGroup(QByteArrayLiteral("MacroChars"), {opts.macroQuoteCharacter}, 0); } void AvrAssemblerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'CDebug' item (Generate debug information). addOptionsGroup(QByteArrayLiteral("CDebug"), {opts.debugInfo}); } void AvrAssemblerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'ADefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("ADefines"), opts.defineSymbols); // Add 'AUserIncludes' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("ANewIncludes"), opts.includePaths); } void AvrAssemblerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'AWarnEnable' item (Enable/disable warnings). addOptionsGroup(QByteArrayLiteral("AWarnEnable"), {opts.enableWarnings}); // Add 'AWarnWhat' item (Enable/disable all warnings). addOptionsGroup(QByteArrayLiteral("AWarnWhat"), {opts.enableAllWarnings}); } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h0000644000175100017510000000504415232633614027514 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H #define QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrGeneralSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit AvrGeneralSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildTargetPage(const ProductData &qbsProduct); void buildSystemPage(const ProductData &qbsProduct); void buildLibraryOptionsPage(const ProductData &qbsProduct); void buildLibraryConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp0000644000175100017510000000631615232633614030240 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrarchiversettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { constexpr int kArchiverArchiveVersion = 2; constexpr int kArchiverDataVersion = 0; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { outputFile = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); } QString outputFile; }; } // namespace // AvrArchiverSettingsGroup AvrArchiverSettingsGroup::AvrArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("XAR")); setArchiveVersion(kArchiverArchiveVersion); setDataVersion(kArchiverDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(buildRootDirectory, qbsProduct); } void AvrArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'XAROutOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XAROutOverride"), {1}); // Add 'OutputFile' item (Output filename). addOptionsGroup(QByteArrayLiteral("OutputFile"), {opts.outputFile}); } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp0000644000175100017510000006645515232633614030064 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrgeneralsettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { constexpr int kGeneralArchiveVersion = 12; constexpr int kGeneralDataVersion = 10; namespace { struct TargetMcuEntry final { QByteArray targetName; QByteArray targetFlag; }; // Dictionary of known AVR MCU's and its compiler options. const TargetMcuEntry mcusDict[] = { {"AT43USB320A", "at43usb320a"}, {"AT43USB325", "at43usb325"}, {"AT43USB326", "at43usb326"}, {"AT43USB351M", "at43usb351m"}, {"AT43USB353M", "at43usb353m"}, {"AT43USB355", "at43usb355"}, {"AT76C712", "at76c712"}, {"AT76C713", "at76c713"}, {"AT86RF401", "at86rf401"}, {"AT90CAN128", "can128"}, {"AT90CAN32", "can32"}, {"AT90CAN64", "can64"}, {"AT90PWM1", "pwm1"}, {"AT90PWM161", "pwm161"}, {"AT90PWM2", "pwm2"}, {"AT90PWM216", "pwm216"}, {"AT90PWM2B", "pwm2b"}, {"AT90PWM3", "pwm3"}, {"AT90PWM316", "pwm316"}, {"AT90PWM3B", "pwm3b"}, {"AT90PWM81", "pwm81"}, {"AT90S1200", "1200"}, {"AT90S2313", "2313"}, {"AT90S2323", "2323"}, {"AT90S2333", "2333"}, {"AT90S2343", "2343"}, {"AT90S4414", "4414"}, {"AT90S4433", "4433"}, {"AT90S4434", "4434"}, {"AT90S8515", "8515"}, {"AT90S8534", "8534"}, {"AT90S8535", "8535"}, {"AT90SCR050", "scr050"}, {"AT90SCR075", "scr075"}, {"AT90SCR100", "scr100"}, {"AT90SCR200", "scr200"}, {"AT90SCR400", "scr400"}, {"AT90USB128", "usb128"}, {"AT90USB1286", "usb1286"}, {"AT90USB1287", "usb1287"}, {"AT90USB162", "usb162"}, {"AT90USB64", "usb64"}, {"AT90USB646", "usb646"}, {"AT90USB647", "usb647"}, {"AT90USB82", "usb82"}, {"AT94Kxx", "at94k"}, {"ATA5272", "ata5272"}, {"ATA5505", "ata5505"}, {"ATA5700M322", "ata5700m322"}, {"ATA5702M322", "ata5702m322"}, {"ATA5781", "ata5781"}, {"ATA5782", "ata5782"}, {"ATA5783", "ata5783"}, {"ATA5785", "ata5785"}, {"ATA5787", "ata5787"}, {"ATA5790", "ata5790"}, {"ATA5790N", "ata5790n"}, {"ATA5795", "ata5795"}, {"ATA5830", "ata5830"}, {"ATA5831", "ata5831"}, {"ATA5832", "ata5832"}, {"ATA5833", "ata5833"}, {"ATA5835", "ata5835"}, {"ATA6285", "ata6285"}, {"ATA6286", "ata6286"}, {"ATA6289", "ata6289"}, {"ATA8210", "ata8210"}, {"ATA8215", "ata8215"}, {"ATA8510", "ata8510"}, {"ATA8515", "ata8515"}, {"ATmX224E", "mx224e"}, {"ATmXT112SL", "mxt112sl"}, {"ATmXT224", "mxt224"}, {"ATmXT224E", "mxt224e"}, {"ATmXT336S", "mxt336s"}, {"ATmXT540S", "mxt540s"}, {"ATmXT540S_RevA", "mxt540s_reva"}, {"ATmXTS200", "mxts200"}, {"ATmXTS220", "mxts220"}, {"ATmXTS220E", "mxts220e"}, {"ATmega007", "m007"}, {"ATmega103", "m103"}, {"ATmega128", "m128"}, {"ATmega1280", "m1280"}, {"ATmega1281", "m1281"}, {"ATmega1284", "m1284"}, {"ATmega1284P", "m1284p"}, {"ATmega1284RFR2", "m1284rfr2"}, {"ATmega128A", "m128a"}, {"ATmega128RFA1", "m128rfa1"}, {"ATmega128RFA2", "m128rfa2"}, {"ATmega128RFR2", "m128rfr2"}, {"ATmega16", "m16"}, {"ATmega1608", "m1608"}, {"ATmega1609", "m1609"}, {"ATmega161", "m161"}, {"ATmega162", "m162"}, {"ATmega163", "m163"}, {"ATmega164", "m164"}, {"ATmega164A", "m164a"}, {"ATmega164P", "m164p"}, {"ATmega164PA", "m164pa"}, {"ATmega165", "m165"}, {"ATmega165A", "m165a"}, {"ATmega165P", "m165p"}, {"ATmega165PA", "m165pa"}, {"ATmega168", "m168"}, {"ATmega168A", "m168a"}, {"ATmega168P", "m168p"}, {"ATmega168PA", "m168pa"}, {"ATmega168PB", "m168pb"}, {"ATmega169", "m169"}, {"ATmega169A", "m169a"}, {"ATmega169P", "m169p"}, {"ATmega169PA", "m169pa"}, {"ATmega16A", "m16a"}, {"ATmega16HVA", "m16hva"}, {"ATmega16HVA2", "m16hva2"}, {"ATmega16HVB", "m16hvb"}, {"ATmega16M1", "m16m1"}, {"ATmega16U2", "m16u2"}, {"ATmega16U4", "m16u4"}, {"ATmega2560", "m2560"}, {"ATmega2561", "m2561"}, {"ATmega2564RFR2", "m2564rfr2"}, {"ATmega256RFA2", "m256rfa2"}, {"ATmega256RFR2", "m256rfr2"}, {"ATmega26HVG", "m26hvg"}, {"ATmega32", "m32"}, {"ATmega3208", "m3208"}, {"ATmega3209", "m3209"}, {"ATmega323", "m323"}, {"ATmega324", "m324"}, {"ATmega324A", "m324a"}, {"ATmega324P", "m324p"}, {"ATmega324PA", "m324pa"}, {"ATmega324PB", "m324pb"}, {"ATmega325", "m325"}, {"ATmega3250", "m3250"}, {"ATmega3250A", "m3250a"}, {"ATmega3250P", "m3250p"}, {"ATmega3250PA", "m3250pa"}, {"ATmega325A", "m325a"}, {"ATmega325P", "m325p"}, {"ATmega325PA", "m325pa"}, {"ATmega328", "m328"}, {"ATmega328P", "m328p"}, {"ATmega328PB", "m328pb"}, {"ATmega329", "m329"}, {"ATmega3290", "m3290"}, {"ATmega3290A", "m3290a"}, {"ATmega3290P", "m3290p"}, {"ATmega3290PA", "m3290pa"}, {"ATmega329A", "m329a"}, {"ATmega329P", "m329p"}, {"ATmega329PA", "m329pa"}, {"ATmega32A", "m32a"}, {"ATmega32C1", "m32c1"}, {"ATmega32HVB", "m32hvb"}, {"ATmega32M1", "m32m1"}, {"ATmega32U2", "m32u2"}, {"ATmega32U4", "m32u4"}, {"ATmega32U6", "m32u6"}, {"ATmega406", "m406"}, {"ATmega48", "m48"}, {"ATmega4808", "m4808"}, {"ATmega4809", "m4809"}, {"ATmega48A", "m48a"}, {"ATmega48HVF", "m48hvf"}, {"ATmega48P", "m48p"}, {"ATmega48PA", "m48pa"}, {"ATmega48PB", "m48pb"}, {"ATmega4HVD", "m4hvd"}, {"ATmega603", "m603"}, {"ATmega64", "m64"}, {"ATmega640", "m640"}, {"ATmega644", "m644"}, {"ATmega644A", "m644a"}, {"ATmega644P", "m644p"}, {"ATmega644PA", "m644pa"}, {"ATmega644RFR2", "m644rfr2"}, {"ATmega645", "m645"}, {"ATmega6450", "m6450"}, {"ATmega6450A", "m6450a"}, {"ATmega6450P", "m6450p"}, {"ATmega645A", "m645a"}, {"ATmega645P", "m645p"}, {"ATmega649", "m649"}, {"ATmega6490", "m6490"}, {"ATmega6490A", "m6490a"}, {"ATmega6490P", "m6490p"}, {"ATmega649A", "m649a"}, {"ATmega649P", "m649p"}, {"ATmega64A", "m64a"}, {"ATmega64C1", "m64c1"}, {"ATmega64HVE", "m256rfa2"}, {"ATmega64HVE", "m64hve"}, {"ATmega64HVE2", "m64hve2"}, {"ATmega64M1", "m64m1"}, {"ATmega64RFA2", "m64rfa2"}, {"ATmega64RFR2", "m64rfr2"}, {"ATmega8", "m8"}, {"ATmega808", "m808"}, {"ATmega809", "m809"}, {"ATmega83", "m83"}, {"ATmega8515", "m8515"}, {"ATmega8535", "m8535"}, {"ATmega88", "m88"}, {"ATmega88A", "m88a"}, {"ATmega88P", "m88p"}, {"ATmega88PA", "m88pa"}, {"ATmega88PB", "m88pb"}, {"ATmega8A", "m8a"}, {"ATmega8HVA", "m8hva"}, {"ATmega8HVD", "m8hvd"}, {"ATmega8U2", "m8u2"}, {"ATtiny10", "tiny10"}, {"ATtiny102", "tiny102"}, {"ATtiny104", "tiny104"}, {"ATtiny11", "tiny11"}, {"ATtiny12", "tiny12"}, {"ATtiny13", "tiny13"}, {"ATtiny13A", "tiny13a"}, {"ATtiny15", "tiny15"}, {"ATtiny1604", "tiny1604"}, {"ATtiny1606", "tiny1606"}, {"ATtiny1607", "tiny1607"}, {"ATtiny1614", "tiny1614"}, {"ATtiny1616", "tiny1616"}, {"ATtiny1617", "tiny1617"}, {"ATtiny1634", "tiny1634"}, {"ATtiny167", "tiny167"}, {"ATtiny20", "tiny20"}, {"ATtiny202", "tiny202"}, {"ATtiny204", "tiny204"}, {"ATtiny212", "tiny212"}, {"ATtiny214", "tiny214"}, {"ATtiny22", "tiny22"}, {"ATtiny2313", "tiny2313"}, {"ATtiny2313A", "tiny2313a"}, {"ATtiny23U", "tiny23u"}, {"ATtiny24", "tiny24"}, {"ATtiny24A", "tiny24a"}, {"ATtiny25", "tiny25"}, {"ATtiny26", "tiny26"}, {"ATtiny261", "tiny261"}, {"ATtiny261A", "tiny261a"}, {"ATtiny28", "tiny28"}, {"ATtiny3214", "tiny3214"}, {"ATtiny3216", "tiny3216"}, {"ATtiny3217", "tiny3217"}, {"ATtiny4", "tiny4"}, {"ATtiny40", "tiny40"}, {"ATtiny402", "tiny402"}, {"ATtiny404", "tiny404"}, {"ATtiny406", "tiny406"}, {"ATtiny412", "tiny412"}, {"ATtiny414", "tiny414"}, {"ATtiny416", "tiny416"}, {"ATtiny417", "tiny417"}, {"ATtiny4313", "tiny4313"}, {"ATtiny43U", "tiny43u"}, {"ATtiny44", "tiny44"}, {"ATtiny441", "tiny441"}, {"ATtiny44A", "tiny44a"}, {"ATtiny45", "tiny45"}, {"ATtiny461", "tiny461"}, {"ATtiny461A", "tiny461a"}, {"ATtiny474", "tiny474"}, {"ATtiny48", "tiny48"}, {"ATtiny5", "tiny5"}, {"ATtiny80", "tiny80"}, {"ATtiny804", "tiny804"}, {"ATtiny806", "tiny806"}, {"ATtiny807", "tiny807"}, {"ATtiny80_pre_2015", "tiny80_pre_2015"}, {"ATtiny814", "tiny814"}, {"ATtiny816", "tiny816"}, {"ATtiny817", "tiny817"}, {"ATtiny828", "tiny828"}, {"ATtiny84", "tiny84"}, {"ATtiny840", "tiny840"}, {"ATtiny841", "tiny841"}, {"ATtiny84A", "tiny84a"}, {"ATtiny85", "tiny85"}, {"ATtiny861", "tiny861"}, {"ATtiny861A", "tiny861a"}, {"ATtiny87", "tiny87"}, {"ATtiny88", "tiny88"}, {"ATtiny9", "tiny9"}, {"ATxmega128A1", "xm128a1"}, {"ATxmega128A1U", "xm128a1u"}, {"ATxmega128A3", "xm128a3"}, {"ATxmega128A3U", "xm128a3u"}, {"ATxmega128A4", "xm128a4"}, {"ATxmega128A4U", "xm128a4u"}, {"ATxmega128B1", "xm128b1"}, {"ATxmega128B3", "xm128b3"}, {"ATxmega128C3", "xm128c3"}, {"ATxmega128D3", "xm128d3"}, {"ATxmega128D4", "xm128d4"}, {"ATxmega16A4", "xm16a4"}, {"ATxmega16A4U", "xm16a4u"}, {"ATxmega16C4", "xm16c4"}, {"ATxmega16D4", "xm16d4"}, {"ATxmega16E5", "xm16e5"}, {"ATxmega192A1", "xm192a1"}, {"ATxmega192A3", "xm192a3"}, {"ATxmega192A3U", "xm192a3u"}, {"ATxmega192C3", "xm192c3"}, {"ATxmega192D3", "xm192d3"}, {"ATxmega256A1", "xm256a1"}, {"ATxmega256A3", "xm256a3"}, {"ATxmega256A3B", "xm256a3b"}, {"ATxmega256A3BU", "xm256a3bu"}, {"ATxmega256A3U", "xm256a3u"}, {"ATxmega256B1", "xm256b1"}, {"ATxmega256C3", "xm256c3"}, {"ATxmega256D3", "xm256d3"}, {"ATxmega32A4", "xm32a4"}, {"ATxmega32A4U", "xm32a4u"}, {"ATxmega32C3", "xm32c3"}, {"ATxmega32C4", "xm32c4"}, {"ATxmega32D3", "xm32d3"}, {"ATxmega32D4", "xm32d4"}, {"ATxmega32D4P", "xm32d4p"}, {"ATxmega32E5", "xm32e5"}, {"ATxmega32X1", "xm32x1"}, {"ATxmega384A1", "xm384a1"}, {"ATxmega384C3", "xm384c3"}, {"ATxmega384D3", "xm384d3"}, {"ATxmega64A1", "xm64a1"}, {"ATxmega64A1U", "xm64a1u"}, {"ATxmega64A3", "xm64a3"}, {"ATxmega64A3U", "xm64a3u"}, {"ATxmega64A4", "xm64a4"}, {"ATxmega64A4U", "xm64a4u"}, {"ATxmega64B1", "xm64b1"}, {"ATxmega64B3", "xm64b3"}, {"ATxmega64C3", "xm64c3"}, {"ATxmega64D3", "xm64d3"}, {"ATxmega64D4", "xm64d4"}, {"ATxmega8E5", "xm8e5"}, {"M3000", "m3000"}, {"MaxBSE", "maxbse"}, }; // Target page options. struct TargetPageOptions final { enum MemoryModel { TinyModel, SmallModel, LargeModel, HugeModel }; explicit TargetPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags")}); // Detect target MCU record. const QString mcuValue = IarewUtils::flagValue( flags, QStringLiteral("--cpu")).toLower(); targetMcu = mcuStringFromFlagValue(mcuValue); // Detect target memory model. const QString modelValue = IarewUtils::flagValue( flags, QStringLiteral("-m")); if (modelValue == QLatin1Char('t')) memoryModel = TargetPageOptions::TinyModel; else if (modelValue == QLatin1Char('s')) memoryModel = TargetPageOptions::SmallModel; else if (modelValue == QLatin1Char('l')) memoryModel = TargetPageOptions::LargeModel; else if (modelValue == QLatin1Char('h')) memoryModel = TargetPageOptions::HugeModel; // Detect target EEPROM util size. eepromUtilSize = IarewUtils::flagValue( flags, QStringLiteral("--eeprom_size")).toInt(); } static QString mcuStringFromFlagValue(const QString &mcuValue) { const auto targetBegin = std::cbegin(mcusDict); const auto targetEnd = std::cend(mcusDict); const auto targetIt = std::find_if(targetBegin, targetEnd, [mcuValue]( const TargetMcuEntry &entry) { return entry.targetFlag == mcuValue.toLatin1(); }); if (targetIt != targetEnd) { return QStringLiteral("%1\t%2") .arg(QString::fromLatin1(targetIt->targetFlag), QString::fromLatin1(targetIt->targetName)); } return {}; } QString targetMcu; MemoryModel memoryModel = TinyModel; int eepromUtilSize = 0; }; // System page options. struct SystemPageOptions final { explicit SystemPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverLinkerFlags"), QStringLiteral("defines")}); cstackSize = IarewUtils::flagValue( flags, QStringLiteral("_..X_CSTACK_SIZE")).toInt(); rstackSize = IarewUtils::flagValue( flags, QStringLiteral("_..X_RSTACK_SIZE")).toInt(); } int cstackSize = 0; int rstackSize = 0; }; // Library options page options. struct LibraryOptionsPageOptions final { enum PrintfFormatter { PrintfAutoFormatter = 0, PrintfFullFormatter = 1, PrintfFullNoMultibytesFormatter = 2, PrintfLargeFormatter = 3, PrintfLargeNoMultibytesFormatter = 4, PrintfSmallFormatter = 6, PrintfSmallNoMultibytesFormatter = 7, PrintfTinyFormatter = 8 }; enum ScanfFormatter { ScanfAutoFormatter = 0, ScanfFullFormatter = 1, ScanfFullNoMultibytesFormatter = 2, ScanfLargeFormatter = 3, ScanfLargeNoMultibytesFormatter = 4, ScanfSmallFormatter = 6, ScanfSmallNoMultibytesFormatter = 7 }; explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (const QString &flag : flags) { if (flag.endsWith(QLatin1String("_printf"), Qt::CaseInsensitive)) { const QString prop = flag.split(QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("-e_printffull")) printfFormatter = LibraryOptionsPageOptions::PrintfFullFormatter; else if (prop == QLatin1String("-e_printffullnomb")) printfFormatter = LibraryOptionsPageOptions::PrintfFullNoMultibytesFormatter; else if (prop == QLatin1String("-e_printflarge")) printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter; else if (prop == QLatin1String("-e_printflargenomb")) printfFormatter = LibraryOptionsPageOptions::PrintfLargeNoMultibytesFormatter; else if (prop == QLatin1String("-e_printfsmall")) printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter; else if (prop == QLatin1String("-e_printfsmallnomb")) printfFormatter = LibraryOptionsPageOptions::PrintfSmallNoMultibytesFormatter; else if (prop == QLatin1String("-printftiny")) printfFormatter = LibraryOptionsPageOptions::PrintfTinyFormatter; } else if (flag.endsWith(QLatin1String("_scanf"), Qt::CaseInsensitive)) { const QString prop = flag.split(QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("-e_scanffull")) scanfFormatter = LibraryOptionsPageOptions::ScanfFullFormatter; else if (prop == QLatin1String("-e_scanffullnomb")) scanfFormatter = LibraryOptionsPageOptions::ScanfFullNoMultibytesFormatter; else if (prop == QLatin1String("-e_scanflarge")) scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter; else if (prop == QLatin1String("-e_scanflargenomb")) scanfFormatter = LibraryOptionsPageOptions::ScanfLargeNoMultibytesFormatter; else if (prop == QLatin1String("-e_scanfsmall")) scanfFormatter = LibraryOptionsPageOptions::ScanfSmallFormatter; else if (prop == QLatin1String("-e_scanfsmallnomb")) scanfFormatter = LibraryOptionsPageOptions::ScanfSmallNoMultibytesFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalDlibLibrary, FullDlibLibrary, CustomDlibLibrary, ClibLibrary, CustomClibLibrary, ThirdPartyLibrary }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QStringList libraryPaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); const auto libraryBegin = libraryPaths.cbegin(); const auto libraryEnd = libraryPaths.cend(); if (flags.contains(QLatin1String("--dlib"))) { const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath(qbsProduct); const QFileInfo configInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); const QString configFilePath = configInfo.absoluteFilePath(); if (configFilePath.startsWith(dlibToolkitPath, Qt::CaseInsensitive)) { if (configFilePath.endsWith(QLatin1String("-n.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::NormalDlibLibrary; } else if (configFilePath.endsWith(QLatin1String("-f.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::FullDlibLibrary; } else { libraryType = LibraryConfigPageOptions::CustomDlibLibrary; } configPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, configFilePath); // Find dlib library inside of IAR toolkit directory. const auto libraryIt = std::find_if(libraryBegin, libraryEnd, [dlibToolkitPath]( const QString &libraryPath) { return libraryPath.startsWith(dlibToolkitPath); }); if (libraryIt != libraryEnd) { // This means that dlib library is 'standard' (placed inside // of IAR toolkit directory). libraryPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, *libraryIt); } } else { // This means that dlib library is 'custom' // (but we don't know its path). libraryType = LibraryConfigPageOptions::CustomDlibLibrary; configPath = IarewUtils::projectRelativeFilePath( baseDirectory, configFilePath); } } else if (flags.contains(QLatin1String("--clib"))) { const QString clibToolkitPath = IarewUtils::clibToolkitRootPath(qbsProduct); // Find clib library inside of IAR toolkit directory. const auto libraryIt = std::find_if(libraryBegin, libraryEnd, [clibToolkitPath]( const QString &libraryPath) { return libraryPath.startsWith(clibToolkitPath); }); if (libraryIt != libraryEnd) { // This means that clib library is 'standard' (placed inside // of IAR toolkit directory). libraryType = LibraryConfigPageOptions::ClibLibrary; libraryPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, *libraryIt); } else { // This means that clib library is 'custom' // (but we don't know its path). libraryType = LibraryConfigPageOptions::CustomClibLibrary; } } else { libraryType = LibraryConfigPageOptions::NoLibrary; } } RuntimeLibrary libraryType = NoLibrary; QString configPath; QString libraryPath; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; } // namespace // AvrGeneralSettingsGroup AvrGeneralSettingsGroup::AvrGeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildSystemPage(qbsProduct); buildLibraryOptionsPage(qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); } void AvrGeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'GenDeviceSelectMenu' item // (Processor configuration chooser). addOptionsGroup(QByteArrayLiteral("GenDeviceSelectMenu"), {opts.targetMcu}); // Add 'Variant Memory' item // (Memory model: tiny/small/large/huge). addOptionsGroup(QByteArrayLiteral("Variant Memory"), {opts.memoryModel}); // Add 'GGEepromUtilSize' item // (Utilize inbuilt EEPROM size, in bytes). addOptionsGroup(QByteArrayLiteral("GGEepromUtilSize"), {opts.eepromUtilSize}); } void AvrGeneralSettingsGroup::buildSystemPage( const ProductData &qbsProduct) { const SystemPageOptions opts (qbsProduct); // Add 'SCCStackSize' item (Data stack // - CSTACK size in bytes). addOptionsGroup(QByteArrayLiteral("SCCStackSize"), {opts.cstackSize}); // Add 'SCRStackSize' item (Return address stack // - RSTACK depth in bytes). addOptionsGroup(QByteArrayLiteral("SCRStackSize"), {opts.rstackSize}); } void AvrGeneralSettingsGroup::buildLibraryOptionsPage( const ProductData &qbsProduct) { const LibraryOptionsPageOptions opts(qbsProduct); // Add 'Output variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Output variant"), {opts.printfFormatter}); // Add 'Input variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Input variant"), {opts.scanfFormatter}); } void AvrGeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items // (Link with runtime: none/dlib/clib/etc). addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), {opts.libraryType}); addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), {opts.libraryType}); // Add 'RTConfigPath' item (Runtime configuration file). addOptionsGroup(QByteArrayLiteral("RTConfigPath"), {opts.configPath}); // Add 'RTLibraryPath' item (Runtime library file). addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), {opts.libraryPath}); } void AvrGeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h0000644000175100017510000000437215232633614027705 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H #define QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrArchiverSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit AvrArchiverSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h0000644000175100017510000000516015232633614027710 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H #define QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrCompilerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit AvrCompilerSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const ProductData &qbsProduct); void buildLanguageOnePage(const ProductData &qbsProduct); void buildLanguageTwoPage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildCodePage(const ProductData &qbsProduct); }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp0000644000175100017510000000731415232633614030542 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrarchiversettingsgroup_v7.h" #include "avrassemblersettingsgroup_v7.h" #include "avrbuildconfigurationgroup_v7.h" #include "avrcompilersettingsgroup_v7.h" #include "avrgeneralsettingsgroup_v7.h" #include "avrlinkersettingsgroup_v7.h" #include "../../iarewtoolchainpropertygroup.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { AvrBuildConfigurationGroup::AvrBuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("configuration") { // Append configuration name item. const QString cfgName = gen::utils::buildConfigurationName(qbsProject); appendProperty("name", cfgName); // Apend toolchain name group item. appendChild("AVR"); // Append debug info item. const int debugBuild = gen::utils::debugInformation(qbsProduct); appendProperty("debug", debugBuild); // Append settings group items. appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); } bool AvrBuildConfigurationGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Avr && version.majorVersion() == 7; } std::unique_ptr AvrBuildConfigurationGroupFactory::create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new AvrBuildConfigurationGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp0000644000175100017510000003622515232633614027723 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "avrlinkersettingsgroup_v7.h" #include "../../iarewutils.h" #include namespace qbs { namespace iarew { namespace avr { namespace v7 { constexpr int kLinkerArchiveVersion = 3; constexpr int kLinkerDataVersion = 16; namespace { // Config page options. struct ConfigPageOptions final { explicit ConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); entryPoint = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("entryPoint")); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); configFilePaths.push_back(path); } } } // Enumerate all product linker config files // (which are set trough '-f' option). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); const QVariantList configPathValues = IarewUtils::flagValues( flags, QStringLiteral("-f")); for (const QVariant &configPathValue : configPathValues) { const QString fullConfigPath = configPathValue.toString(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } } // Add libraries search paths. const QStringList libraryPaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("libraryPaths")}); for (const QString &libraryPath : libraryPaths) { const QFileInfo libraryPathInfo(libraryPath); const QString fullLibrarySearchPath = libraryPathInfo.absoluteFilePath(); if (fullLibrarySearchPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullLibrarySearchPath); librarySearchPaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullLibrarySearchPath); librarySearchPaths.push_back(path); } } // Add static libraries paths. const QStringList staticLibrariesProps = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); for (const QString &staticLibrary : staticLibrariesProps) { const QFileInfo staticLibraryInfo(staticLibrary); if (staticLibraryInfo.isAbsolute()) { const QString fullStaticLibraryPath = staticLibraryInfo.absoluteFilePath(); if (fullStaticLibraryPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullStaticLibraryPath); staticLibraries.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullStaticLibraryPath); staticLibraries.push_back(path); } } else { staticLibraries.push_back(staticLibrary); } } // Add static libraries from product dependencies. for (const ProductData &qbsProductDep : qbsProductDeps) { const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProductDep); staticLibraries.push_back(depBinaryPath); } } QVariantList configFilePaths; QVariantList librarySearchPaths; QVariantList staticLibraries; QString entryPoint; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { outputFile = gen::utils::targetBinary(qbsProduct); } QString outputFile; }; // List page options. struct ListPageOptions final { enum ListingAction { NoListing, GenerateListing }; explicit ListPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); generateMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")) ? ListPageOptions::GenerateListing : ListPageOptions::NoListing; } ListingAction generateMap = NoListing; }; // Define page options. struct DefinePageOptions final { explicit DefinePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); // Enumerate all linker defines. for (const QString &flag : flags) { if (!flag.startsWith(QLatin1String("-D"))) continue; const auto symbol = flag.mid(2); // Ignore system-defined macroses. if (symbol.startsWith(QLatin1String("_..X_HEAP_SIZE")) || symbol.startsWith(QLatin1String("_..X_TINY_HEAP_SIZE")) || symbol.startsWith(QLatin1String("_..X_NEAR_HEAP_SIZE")) || symbol.startsWith(QLatin1String("_..X_FAR_HEAP_SIZE")) || symbol.startsWith(QLatin1String("_..X_HUGE_HEAP_SIZE")) || symbol.startsWith(QLatin1String("_..X_CSTACK_SIZE")) || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE")) || symbol.startsWith(QLatin1String("_..X_FLASH_CODE_END")) || symbol.startsWith(QLatin1String("_..X_FLASH_BASE")) || symbol.startsWith(QLatin1String("_..X_CSTACK_BASE")) || symbol.startsWith(QLatin1String("_..X_CSTACK_END")) || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE")) || symbol.startsWith(QLatin1String("_..X_RSTACK_END")) || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_BASE")) || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_SIZE")) || symbol.startsWith(QLatin1String("_..X_EXT_ROM_BASE")) || symbol.startsWith(QLatin1String("_..X_EXT_ROM_SIZE")) || symbol.startsWith(QLatin1String("_..X_EXT_NV_BASE")) || symbol.startsWith(QLatin1String("_..X_EXT_NV_SIZE")) || symbol.startsWith(QLatin1String("_..X_SRAM_BASE")) || symbol.startsWith(QLatin1String("_..X_SRAM_SIZE")) || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE")) || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE")) ) { continue; } defineSymbols.push_back(symbol); } } QVariantList defineSymbols; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); suppressAllWarnings = (warningLevel == QLatin1String("none")); } int suppressAllWarnings = 0; }; } // namespace // AvrLinkerSettingsGroup AvrLinkerSettingsGroup::AvrLinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { setName(QByteArrayLiteral("XLINK")); setArchiveVersion(kLinkerArchiveVersion); setDataVersion(kLinkerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildConfigPage(buildRootDirectory, qbsProduct, qbsProductDeps); buildOutputPage(qbsProduct); buildListPage(qbsProduct); buildDefinePage(qbsProduct); buildDiagnosticsPage(qbsProduct); // Should be called as latest stage! buildExtraOptionsPage(qbsProduct); } void AvrLinkerSettingsGroup::buildConfigPage( const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { ConfigPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); if (opts.configFilePaths.count() > 0) { // Note: IAR IDE does not allow to specify a multiple config files, // although the IAR linker support it. So, we use followig 'trick': // we take a first config file and to add it as usual to required items; // and then an other remainders we forward to the "Extra options page". const QVariant configPath = opts.configFilePaths.takeFirst(); // Add 'XclOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XclOverride"), {1}); // Add 'XclFile' item (Linke configuration file). addOptionsGroup(QByteArrayLiteral("XclFile"), {configPath}); // Add remainder configuration files to the "Extra options page". if (!opts.configFilePaths.isEmpty()) { for (QVariant &configPath : opts.configFilePaths) configPath = QString(QStringLiteral("-f ") + configPath.toString()); m_extraOptions << opts.configFilePaths; } } if (opts.staticLibraries.count() > 0) m_extraOptions << opts.staticLibraries; if (!opts.entryPoint.isEmpty()) { // Add 'xcProgramEntryLabel' item (Entry symbol). addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), {opts.entryPoint}); // Add 'xcOverrideProgramEntryLabel' item // (Override default program entry). addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), {1}); // Add 'xcProgramEntryLabelSelect' item. addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"), {0}); } // Add 'XIncludes' item (Libraries search paths). addOptionsGroup(QByteArrayLiteral("XIncludes"), opts.librarySearchPaths); } void AvrLinkerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'XOutOverride' item (Override default output file). addOptionsGroup(QByteArrayLiteral("XOutOverride"), {1}); // Add 'OutputFile' item (Output file name). addOptionsGroup(QByteArrayLiteral("OutputFile"), {opts.outputFile}); } void AvrLinkerSettingsGroup::buildListPage( const ProductData &qbsProduct) { const ListPageOptions opts(qbsProduct); // Add 'XList' item (Generate linker listing). addOptionsGroup(QByteArrayLiteral("XList"), {opts.generateMap}); } void AvrLinkerSettingsGroup::buildDefinePage( const ProductData &qbsProduct) { const DefinePageOptions opts(qbsProduct); // Add 'XDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("XDefines"), opts.defineSymbols); } void AvrLinkerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'SuppressAllWarn' item (Suppress all warnings). addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"), {opts.suppressAllWarnings}); } void AvrLinkerSettingsGroup::buildExtraOptionsPage(const ProductData &qbsProduct) { Q_UNUSED(qbsProduct) if (!m_extraOptions.isEmpty()) { // Add 'XExtraOptionsCheck' (Use command line options). addOptionsGroup(QByteArrayLiteral("XExtraOptionsCheck"), {1}); // Add 'XExtraOptions' item (Command line options). addOptionsGroup(QByteArrayLiteral("XExtraOptions"), m_extraOptions); } } } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h0000644000175100017510000000467715232633614030067 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H #define QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrAssemblerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit AvrAssemblerSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildLanguagePage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h0000644000175100017510000000517515232633614027370 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H #define QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace avr { namespace v7 { class AvrLinkerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit AvrLinkerSettingsGroup(const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildConfigPage(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps); void buildOutputPage(const ProductData &qbsProduct); void buildListPage(const ProductData &qbsProduct); void buildDefinePage(const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildExtraOptionsPage(const ProductData &qbsProduct); QVariantList m_extraOptions; }; } // namespace v7 } // namespace avr } // namespace iarew } // namespace qbs #endif // QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/0000755000175100017510000000000015232633614022100 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h0000644000175100017510000000434615232633614030260 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H #define QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51ArchiverSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Mcs51ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp0000644000175100017510000012510115232633614030416 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51generalsettingsgroup_v10.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { constexpr int kGeneralArchiveVersion = 4; constexpr int kGeneralDataVersion = 9; namespace { // Target page options. struct TargetPageOptions final { enum CpuCore { CorePlain = 1, CoreExtended1, CoreExtended2 }; enum CodeModel { CodeModelNear = 1, CodeModelBanked, CodeModelFar, CodeModelBankedExtended2 }; enum DataModel { DataModelTiny = 0, DataModelSmall, DataModelLarge, DataModelGeneric, DataModelFarGeneric, DataModelFar }; enum ConstantsMemoryPlacement { RamMemoryPlace = 0, RomMemoryPlace, CodeMemoryPlace }; enum CallingConvention { DataOverlayConvention = 0, IDataOverlayConvention, IDataReentrantConvention, PDataReentrantConvention, XDataReentrantConvention, ExtendedStackReentrantConvention }; explicit TargetPageOptions(const ProductData &qbsProduct) { chipInfoPath = detectChipInfoPath(qbsProduct); const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // Should be parsed before the 'code_model' and // 'data_model' options, as that options are depends on it. const QString core = IarewUtils::flagValue( flags, QStringLiteral("--core")) .toLower(); // If the core variant is not set, then choose the // default value, CorePlain (see the compiler datasheet for // '--core' option). if (core == QLatin1String("plain") || core.isEmpty()) { cpuCore = TargetPageOptions::CorePlain; } else if (core == QLatin1String("extended1")) { cpuCore = TargetPageOptions::CoreExtended1; } else if (core == QLatin1String("extended2")) { cpuCore = TargetPageOptions::CoreExtended2; } const QString cm = IarewUtils::flagValue( flags, QStringLiteral("--code_model")) .toLower(); if (cm == QLatin1String("near")) { codeModel = TargetPageOptions::CodeModelNear; } else if (cm == QLatin1String("banked")) { codeModel = TargetPageOptions::CodeModelBanked; } else if (cm == QLatin1String("far")) { codeModel = TargetPageOptions::CodeModelFar; } else if (cm == QLatin1String("banked_ext2")) { codeModel = TargetPageOptions::CodeModelBankedExtended2; } else if (cm.isEmpty()) { // If the code model is not set, then choose the // default values (see the compiler datasheet for // '--code_model' option). if (cpuCore == TargetPageOptions::CorePlain) codeModel = TargetPageOptions::CodeModelNear; else if (cpuCore == TargetPageOptions::CoreExtended1) codeModel = TargetPageOptions::CodeModelFar; else if (cpuCore == TargetPageOptions::CoreExtended2) codeModel = TargetPageOptions::CodeModelBankedExtended2; } const QString dm = IarewUtils::flagValue( flags, QStringLiteral("--data_model")).toLower(); if (dm == QLatin1String("tiny")) { dataModel = TargetPageOptions::DataModelTiny; } else if (dm == QLatin1String("small")) { dataModel = TargetPageOptions::DataModelSmall; } else if (dm == QLatin1String("large")) { dataModel = TargetPageOptions::DataModelLarge; } else if (dm == QLatin1String("generic")) { dataModel = TargetPageOptions::DataModelGeneric; } else if (dm == QLatin1String("far_generic")) { dataModel = TargetPageOptions::DataModelFarGeneric; } else if (dm == QLatin1String("far")) { dataModel = TargetPageOptions::DataModelFar; } else if (dm.isEmpty()) { // If the data model is not set, then choose the // default values (see the compiler datasheet for // '--data_model' option). if (cpuCore == TargetPageOptions::CorePlain) dataModel = TargetPageOptions::DataModelSmall; else if (cpuCore == TargetPageOptions::CoreExtended1) dataModel = TargetPageOptions::DataModelFar; else if (cpuCore == TargetPageOptions::CoreExtended2) dataModel = TargetPageOptions::DataModelLarge; } useExtendedStack = flags.contains(QLatin1String("--extended_stack")); const int regsCount = IarewUtils::flagValue( flags, QStringLiteral("--nr_virtual_regs")) .toInt(); enum { MinVRegsCount = 8, MaxVRegsCount = 32, VRegsOffset = 8 }; // The registers index starts with 0: 0 - means 8 registers, // 1 - means 9 registers and etc. Any invalid values we interpret // as a default value in 8 registers. virtualRegisters = (regsCount < MinVRegsCount || regsCount > MaxVRegsCount) ? 0 : (regsCount - VRegsOffset); const QString constPlace = IarewUtils::flagValue( flags, QStringLiteral("--place_constants")) .toLower(); // If this option is not set, then choose the // default value (see the compiler datasheet for // '--place_constants' option). if (constPlace == QLatin1String("data") || constPlace.isEmpty()) { constPlacement = TargetPageOptions::RamMemoryPlace; } else if (constPlace == QLatin1String("data_rom")) { constPlacement = TargetPageOptions::RomMemoryPlace; } else if (constPlace == QLatin1String("code")) { constPlacement = TargetPageOptions::CodeMemoryPlace; } const QString cc = IarewUtils::flagValue( flags, QStringLiteral("--calling_convention")).toLower(); if (cc == QLatin1String("data_overlay")) { callingConvention = TargetPageOptions::DataOverlayConvention; } else if (cc == QLatin1String("idata_overlay")) { callingConvention = TargetPageOptions::IDataOverlayConvention; } else if (cc == QLatin1String("idata_reentrant") || cc.isEmpty()) { // If this option is not set, then choose the // default value (see the compiler datasheet for // '--calling_convention' option). callingConvention = TargetPageOptions::IDataReentrantConvention; } else if (cc == QLatin1String("pdata_reentrant")) { callingConvention = TargetPageOptions::PDataReentrantConvention; } else if (cc == QLatin1String("xdata_reentrant")) { callingConvention = TargetPageOptions::XDataReentrantConvention; } else if (cc == QLatin1String("ext_stack_reentrant")) { callingConvention = TargetPageOptions::ExtendedStackReentrantConvention; } } // Trying to indirectly detect and build the chip config path, // which uses to show a device name in "Device information" group box. static QString detectChipInfoPath(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); QVariantList configPaths; // Enumerate all product linker config files // (which are set trough '-f' option). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); configPaths << IarewUtils::flagValues(flags, QStringLiteral("-f")); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const auto configPath = qbsArtifact.filePath(); // Skip duplicates. if (configPaths.contains(configPath)) continue; configPaths << qbsArtifact.filePath(); } } const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); for (const QVariant &configPath : std::as_const(configPaths)) { const QString fullConfigPath = configPath.toString(); // We interested only in a config paths shipped inside of a toolkit. if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) continue; // Extract the chip name from the linker script name. const int underscoreIndex = fullConfigPath.lastIndexOf(QLatin1Char('_')); if (underscoreIndex == -1) continue; const int dotIndex = fullConfigPath.lastIndexOf(QLatin1Char('.')); if (dotIndex == -1) continue; if (dotIndex <= underscoreIndex) continue; const QString chipName = fullConfigPath.mid( underscoreIndex + 1, dotIndex - underscoreIndex - 1); // Construct full chip info path. const QFileInfo fullChipInfoPath(QFileInfo(fullConfigPath).absolutePath() + QLatin1Char('/') + chipName + QLatin1String(".i51")); if (fullChipInfoPath.exists()) return fullChipInfoPath.absoluteFilePath(); } return {}; } QString chipInfoPath; CpuCore cpuCore = CorePlain; CodeModel codeModel = CodeModelNear; DataModel dataModel = DataModelTiny; int useExtendedStack = 0; int virtualRegisters = 0; ConstantsMemoryPlacement constPlacement = RamMemoryPlace; CallingConvention callingConvention = DataOverlayConvention; }; // System page options. struct StackHeapPageOptions final { explicit StackHeapPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList defineSymbols = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("defines")}); const QStringList linkerFlags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverLinkerFlags")}); idataStack = IarewUtils::flagValue( defineSymbols, QStringLiteral("_IDATA_STACK_SIZE")); if (idataStack.isEmpty()) idataStack = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_IDATA_STACK_SIZE")); if (idataStack.isEmpty()) idataStack = QLatin1String("0x40"); // Default IDATA stack size. pdataStack = IarewUtils::flagValue( defineSymbols, QStringLiteral("_PDATA_STACK_SIZE")); if (pdataStack.isEmpty()) pdataStack = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_PDATA_STACK_SIZE")); if (pdataStack.isEmpty()) pdataStack = QLatin1String("0x80"); // Default PDATA stack size. xdataStack = IarewUtils::flagValue( defineSymbols, QStringLiteral("_XDATA_STACK_SIZE")); if (xdataStack.isEmpty()) xdataStack = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_XDATA_STACK_SIZE")); if (xdataStack.isEmpty()) xdataStack = QLatin1String("0xEFF"); // Default XDATA stack size. extendedStack = IarewUtils::flagValue( defineSymbols, QStringLiteral("_EXTENDED_STACK_SIZE")); if (extendedStack.isEmpty()) extendedStack = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_EXTENDED_STACK_SIZE")); if (extendedStack.isEmpty()) extendedStack = QLatin1String("0x3FF"); // Default EXTENDED stack size. xdataHeap = IarewUtils::flagValue( defineSymbols, QStringLiteral("_XDATA_HEAP_SIZE")); if (xdataHeap.isEmpty()) xdataHeap = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_XDATA_HEAP_SIZE")); if (xdataHeap.isEmpty()) xdataHeap = QLatin1String("0xFF"); // Default XDATA heap size. farHeap = IarewUtils::flagValue( defineSymbols, QStringLiteral("_FAR_HEAP_SIZE")); if (farHeap.isEmpty()) farHeap = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_FAR_HEAP_SIZE")); if (farHeap.isEmpty()) farHeap = QLatin1String("0xFFF"); // Default FAR heap size. far22Heap = IarewUtils::flagValue( defineSymbols, QStringLiteral("_FAR22_HEAP_SIZE")); if (far22Heap.isEmpty()) far22Heap = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_FAR22_HEAP_SIZE")); if (far22Heap.isEmpty()) far22Heap = QLatin1String("0xFFF"); // Default FAR22 heap size. hugeHeap = IarewUtils::flagValue( defineSymbols, QStringLiteral("_HUGE_HEAP_SIZE")); if (hugeHeap.isEmpty()) hugeHeap = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_HUGE_HEAP_SIZE")); if (hugeHeap.isEmpty()) hugeHeap = QLatin1String("0xFFF"); // Default HUGE heap size. extStackAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?ESP")); if (extStackAddress.isEmpty()) extStackAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?ESP")); if (extStackAddress.isEmpty()) extStackAddress = QLatin1String("0x9B"); // Default extended stack pointer address. extStackMask = IarewUtils::flagValue( defineSymbols, QStringLiteral("?ESP_MASK")); if (extStackMask.isEmpty()) extStackMask = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?ESP_MASK")); if (extStackMask.isEmpty()) extStackMask = QLatin1String("0x03"); // Default extended stack pointer mask. } // Stack sizes. QString idataStack; QString pdataStack; QString xdataStack; QString extendedStack; // Heap sizes. QString xdataHeap; QString farHeap; QString far22Heap; QString hugeHeap; // Extended stack. QString extStackAddress; QString extStackMask; int extStackOffset = 0; int extStackStartAddress = 0; }; // Data pointer page options. struct DptrPageOptions final { enum DptrSize { Dptr16, Dptr24 }; enum DptrVisibility { DptrShadowed, DptrSeparate }; enum SwitchMethod { DptrIncludeMethod, DptrMaskMethod }; explicit DptrPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QString core = IarewUtils::flagValue( flags, QStringLiteral("--core")); const QString dptr = IarewUtils::flagValue( flags, QStringLiteral("--dptr")); enum ValueIndex { SizeIndex, NumbersIndex, VisibilityIndex, SwitchMethodIndex }; const QStringList dptrparts = dptr.split(QLatin1Char(',')); for (auto index = 0; index < dptrparts.count(); ++index) { const QString part = dptrparts.at(index).toLower(); switch (index) { case SizeIndex: if (part == QLatin1String("16")) { dptrSize = DptrPageOptions::Dptr16; } else if (part == QLatin1String("24")) { dptrSize = DptrPageOptions::Dptr24; } else { // If this option is not set, then choose the // default value (see the compiler datasheet for // '--dptr' option). if (core == QLatin1String("extended1")) dptrSize = DptrPageOptions::Dptr24; else dptrSize = DptrPageOptions::Dptr16; } break; case NumbersIndex: { const int count = part.toInt(); if (count < 1 || count > 8) { // If this option is not set, then choose the // default value (see the compiler datasheet for // '--dptr' option). if (core == QLatin1String("extended1")) dptrsCountIndex = 1; // 2 DPTR's else dptrsCountIndex = 0; // 1 DPTR's } else { dptrsCountIndex = (count - 1); // DPTR's count - 1 } } break; case VisibilityIndex: if (part == QLatin1String("shadowed")) dptrVisibility = DptrPageOptions::DptrShadowed; else if (part == QLatin1String("separate") || part.isEmpty()) { // If this option is not set or set to "separate", then choose the // default value (see the compiler datasheet for // '--dptr' option). dptrVisibility = DptrPageOptions::DptrSeparate; } break; case SwitchMethodIndex: if (part == QLatin1String("inc")) { dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod; } else if (part.startsWith(QLatin1String("xor"))) { dptrSwitchMethod = DptrPageOptions::DptrMaskMethod; const int firstIndex = part.indexOf(QLatin1Char('(')); const int lastIndex = part.indexOf(QLatin1Char(')')); dptrMask = part.mid(firstIndex + 1, part.size() - lastIndex); } else { // If this option is not set, then choose the // default value (see the compiler datasheet for // '--dptr' option). if (core == QLatin1String("extended1")) { dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod; } else if (core == QLatin1String("plain")) { dptrSwitchMethod = DptrPageOptions::DptrMaskMethod; dptrMask = QLatin1String("0x01"); } } break; default: break; } } const QStringList defineSymbols = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("defines")}); const QStringList linkerFlags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverLinkerFlags")}); dptrPbank = IarewUtils::flagValue( defineSymbols, QStringLiteral("?PBANK")); if (dptrPbank.isEmpty()) dptrPbank = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?PBANK")); if (dptrPbank.isEmpty()) dptrPbank = QLatin1String("0x93"); // Default 8-15 regs address. dptrPbankExt = IarewUtils::flagValue( defineSymbols, QStringLiteral("?PBANK_EXT")); if (dptrPbankExt.isEmpty()) dptrPbankExt = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?PBANK_EXT")); dpsAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPS")); if (dpsAddress.isEmpty()) dpsAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPS")); dpcAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPC")); if (dpcAddress.isEmpty()) dpcAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPC")); for (auto index = 0; index < 8; ++index) { if (index == 0) { QString dpxAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPX")); if (dpxAddress.isEmpty()) dpxAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPX")); if (!dpxAddress.isEmpty()) dpxAddress.prepend(QLatin1String("-D?DPX=")); if (!dptrAddresses.contains(dpxAddress)) dptrAddresses.push_back(dpxAddress); } else { QString dplAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPL%1").arg(index)); if (dplAddress.isEmpty()) dplAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPL%1").arg(index)); if (!dplAddress.isEmpty()) dplAddress.prepend(QStringLiteral("-D?DPL%1=").arg(index)); if (!dptrAddresses.contains(dplAddress)) dptrAddresses.push_back(dplAddress); QString dphAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPH%1").arg(index)); if (dphAddress.isEmpty()) dphAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPH%1").arg(index)); if (!dphAddress.isEmpty()) dphAddress.prepend(QStringLiteral("-D?DPH%1=").arg(index)); if (!dptrAddresses.contains(dphAddress)) dptrAddresses.push_back(dphAddress); QString dpxAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?DPX%1").arg(index)); if (dpxAddress.isEmpty()) dpxAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?DPX%1").arg(index)); if (!dpxAddress.isEmpty()) dpxAddress.prepend(QStringLiteral("-D?DPX%1=").arg(index)); if (!dptrAddresses.contains(dpxAddress)) dptrAddresses.push_back(dpxAddress); } } } int dptrsCountIndex = 0; DptrSize dptrSize = Dptr16; DptrVisibility dptrVisibility = DptrShadowed; SwitchMethod dptrSwitchMethod = DptrIncludeMethod; QString dptrMask; QString dptrPbank; QString dptrPbankExt; QString dpsAddress; QString dpcAddress; QStringList dptrAddresses; }; // Code bank page options. struct CodeBankPageOptions final { explicit CodeBankPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList defineSymbols = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("defines")}); const QStringList linkerFlags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverLinkerFlags")}); banksCount = IarewUtils::flagValue( defineSymbols, QStringLiteral("_NR_OF_BANKS")); if (banksCount.isEmpty()) banksCount = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_NR_OF_BANKS")); if (banksCount.isEmpty()) banksCount = QLatin1String("0x03"); registerAddress = IarewUtils::flagValue( defineSymbols, QStringLiteral("?CBANK")); if (registerAddress.isEmpty()) registerAddress = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?CBANK")); if (registerAddress.isEmpty()) registerAddress = QLatin1String("0xF0"); registerMask = IarewUtils::flagValue( defineSymbols, QStringLiteral("?CBANK_MASK")); if (registerMask.isEmpty()) registerMask = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D?CBANK_MASK")); if (registerMask.isEmpty()) registerMask = QLatin1String("0xFF"); bankStart = IarewUtils::flagValue( defineSymbols, QStringLiteral("_CODEBANK_START")); if (bankStart.isEmpty()) bankStart = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_CODEBANK_START")); if (bankStart.isEmpty()) bankStart = QLatin1String("0x8000"); bankEnd = IarewUtils::flagValue( defineSymbols, QStringLiteral("_CODEBANK_END")); if (bankEnd.isEmpty()) bankEnd = IarewUtils::flagValue( linkerFlags, QStringLiteral("-D_CODEBANK_END")); if (bankEnd.isEmpty()) bankEnd = QLatin1String("0xFFFF"); } QString banksCount; QString registerAddress; QString registerMask; QString bankStart; QString bankEnd; }; // Library options page options. struct LibraryOptionsPageOptions final { enum PrintfFormatter { PrintfAutoFormatter = 0, PrintfLargeFormatter = 3, PrintfMediumFormatter = 5, PrintfSmallFormatter = 6 }; enum ScanfFormatter { ScanfAutoFormatter = 0, ScanfLargeFormatter = 3, ScanfMediumFormatter = 5 }; explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (const QString &flag : flags) { if (flag.endsWith(QLatin1String("_formatted_write"), Qt::CaseInsensitive)) { const QString prop = flag.split( QLatin1Char('=')).at(0).toLower(); // see the compiler datasheet for the '_formatted_write' option. if (prop == QLatin1String("-e_large_write")) printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter; else if (prop == QLatin1String("-e_medium_write")) printfFormatter = LibraryOptionsPageOptions::PrintfMediumFormatter; else if (prop == QLatin1String("-e_small_write")) printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter; } else if (flag.endsWith(QLatin1String("_formatted_read"), Qt::CaseInsensitive)) { const QString prop = flag.split(QLatin1Char('=')) .at(0).toLower(); // see the compiler datasheet for the '_formatted_read' option. if (prop == QLatin1String("-e_large_read")) scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter; else if (prop == QLatin1String("-e_medium_read")) scanfFormatter = LibraryOptionsPageOptions::ScanfMediumFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalDlibLibrary, CustomDlibLibrary, ClibLibrary, CustomClibLibrary }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QStringList libraryPaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); const auto libraryBegin = libraryPaths.cbegin(); const auto libraryEnd = libraryPaths.cend(); const QFileInfo dlibConfigInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); const QString dlibConfigFilePath = dlibConfigInfo.absoluteFilePath(); if (!dlibConfigFilePath.isEmpty()) { const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath( qbsProduct); if (dlibConfigFilePath.startsWith(dlibToolkitPath, Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::NormalDlibLibrary; configPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, dlibConfigFilePath); // Find dlib library inside of IAR toolkit directory. const auto libraryIt = std::find_if(libraryBegin, libraryEnd, [dlibToolkitPath]( const QString &libraryPath) { return libraryPath.startsWith(dlibToolkitPath); }); if (libraryIt != libraryEnd) { // This means that dlib library is 'standard' (placed inside // of IAR toolkit directory). libraryPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, *libraryIt); } } else { // This means that dlib library is 'custom' // (but we don't know its path). libraryType = LibraryConfigPageOptions::CustomDlibLibrary; configPath = IarewUtils::projectRelativeFilePath( baseDirectory, dlibConfigFilePath); } } else { // Find clib library inside of IAR toolkit directory. const QString clibToolkitPath = IarewUtils::clibToolkitRootPath( qbsProduct); const auto libraryIt = std::find_if(libraryBegin, libraryEnd, [clibToolkitPath]( const QString &libraryPath) { return libraryPath.startsWith(clibToolkitPath); }); if (libraryIt != libraryEnd) { // This means that clib library is 'standard' (placed inside // of IAR toolkit directory). libraryType = LibraryConfigPageOptions::ClibLibrary; libraryPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, *libraryIt); } else { // This means that no any libraries are used . libraryType = LibraryConfigPageOptions::NoLibrary; } } } RuntimeLibrary libraryType = NoLibrary; QString configPath; QString libraryPath; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; } // namespace // Mcs51GeneralSettingsGroup Mcs51GeneralSettingsGroup::Mcs51GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProject) Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildStackHeapPage(qbsProduct); buildDataPointerPage(qbsProduct); buildCodeBankPage(qbsProduct); buildLibraryOptionsPage(qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); } void Mcs51GeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'OGChipConfigPath' item (Device: ). addOptionsGroup(QByteArrayLiteral("OGChipConfigPath"), {opts.chipInfoPath}); // Add 'CPU Core' and 'CPU Core Slave' items // (CPU core: plain/extended{1|2}). addOptionsGroup(QByteArrayLiteral("CPU Core"), {opts.cpuCore}); addOptionsGroup(QByteArrayLiteral("CPU Core Slave"), {opts.cpuCore}); // Add 'Code Memory Model' and 'Code Memory Model slave' items // (Code model: near/banked/far/banked extended). addOptionsGroup(QByteArrayLiteral("Code Memory Model"), {opts.codeModel}); addOptionsGroup(QByteArrayLiteral("Code Memory Model slave"), {opts.codeModel}); // Add 'Data Memory Model' and 'Data Memory Model slave' items // (Data model: tiny/small/large/generic/far). addOptionsGroup(QByteArrayLiteral("Data Memory Model"), {opts.dataModel}); addOptionsGroup(QByteArrayLiteral("Data Memory Model slave"), {opts.dataModel}); // Add 'Use extended stack' and 'Use extended stack slave' items // (Use extended stack). addOptionsGroup(QByteArrayLiteral("Use extended stack"), {opts.useExtendedStack}); addOptionsGroup(QByteArrayLiteral("Use extended stack slave"), {opts.useExtendedStack}); // Add 'Workseg Size' item (Number of virtual registers: 8...32). addOptionsGroup(QByteArrayLiteral("Workseg Size"), {opts.virtualRegisters}); // Add 'Constant Placement' item // (Location of constants and strings: ram/rom/code memories). addOptionsGroup(QByteArrayLiteral("Constant Placement"), {opts.constPlacement}); // Add 'Calling convention' item (Calling convention). addOptionsGroup(QByteArrayLiteral("Calling convention"), {opts.callingConvention}); } void Mcs51GeneralSettingsGroup::buildStackHeapPage( const ProductData &qbsProduct) { const StackHeapPageOptions opts(qbsProduct); // Add 'General Idata Stack Size' item (Stack size: IDATA). addOptionsGroup(QByteArrayLiteral("General Idata Stack Size"), {opts.idataStack}); // Add 'General Pdata Stack Size' item (Stack size: PDATA). addOptionsGroup(QByteArrayLiteral("General Pdata Stack Size"), {opts.pdataStack}); // Add 'General Xdata Stack Size' item (Stack size: XDATA). addOptionsGroup(QByteArrayLiteral("General Xdata Stack Size"), {opts.xdataStack}); // Add 'General Ext Stack Size' item (Stack size: Extended). addOptionsGroup(QByteArrayLiteral("General Ext Stack Size"), {opts.extendedStack}); // Add 'General Xdata Heap Size' item (Heap size: XDATA). addOptionsGroup(QByteArrayLiteral("General Xdata Heap Size"), {opts.xdataHeap}); // Add 'General Far Heap Size' item (Heap size: Far). addOptionsGroup(QByteArrayLiteral("General Far Heap Size"), {opts.farHeap}); // Add 'General Far22 Heap Size' item (Heap size: Far22). addOptionsGroup(QByteArrayLiteral("General Far22 Heap Size"), {opts.far22Heap}); // Add 'General Huge Heap Size' item (Heap size: Huge). addOptionsGroup(QByteArrayLiteral("General Huge Heap Size"), {opts.hugeHeap}); // Add 'Extended stack address' item // (Extended stack pointer address). addOptionsGroup(QByteArrayLiteral("Extended stack address"), {opts.extStackAddress}); // Add 'Extended stack mask' item (Extended stack pointer mask). addOptionsGroup(QByteArrayLiteral("Extended stack mask"), {opts.extStackMask}); // Add 'Extended stack is offset' item // (Extended stack pointer is an offset). addOptionsGroup(QByteArrayLiteral("Extended stack is offset"), {opts.extStackOffset}); } void Mcs51GeneralSettingsGroup::buildDataPointerPage( const ProductData &qbsProduct) { const DptrPageOptions opts(qbsProduct); // Add 'Nr of Datapointers' item (Number of DPTRs: 1...8). addOptionsGroup(QByteArrayLiteral("Nr of Datapointers"), {opts.dptrsCountIndex}); // Add 'Datapointer Size' item (DPTR size: 16/24). addOptionsGroup(QByteArrayLiteral("Datapointer Size"), {opts.dptrSize}); // Add 'Sfr Visibility' item (DPTR address: shadowed/separate). addOptionsGroup(QByteArrayLiteral("Sfr Visibility"), {opts.dptrVisibility}); // Add 'Switch Method' item (Switch method: inc/mask). addOptionsGroup(QByteArrayLiteral("Switch Method"), {opts.dptrSwitchMethod}); // Add 'Mask Value' item (Switch method mask). addOptionsGroup(QByteArrayLiteral("Mask Value"), {opts.dptrMask}); // Add 'PDATA 8-15 register address' item (Page register // address (for bits 8-15). addOptionsGroup(QByteArrayLiteral("PDATA 8-15 register address"), {opts.dptrPbank}); // Add 'PDATA 16-31 register address' item (Page register // address (for bits 16-31). addOptionsGroup(QByteArrayLiteral("PDATA 16-31 register address"), {opts.dptrPbankExt}); // Add 'DPS Address' item (Selected DPTR register). addOptionsGroup(QByteArrayLiteral("DPS Address"), {opts.dpsAddress}); // Add 'DPC Address' item (Separate DPTR control register). addOptionsGroup(QByteArrayLiteral("DPC Address"), {opts.dpcAddress}); // Add 'DPTR Addresses' item (DPTR addresses: Low/High/Ext). const QString dptrAddresses = opts.dptrAddresses.join(QLatin1Char(' ')); addOptionsGroup(QByteArrayLiteral("DPTR Addresses"), {dptrAddresses}); } void Mcs51GeneralSettingsGroup::buildCodeBankPage( const ProductData &qbsProduct) { const CodeBankPageOptions opts(qbsProduct); // Add 'CodeBankReg' item (Register address). addOptionsGroup(QByteArrayLiteral("CodeBankReg"), {opts.registerAddress}); // Add 'CodeBankRegMask' item (Register mask). addOptionsGroup(QByteArrayLiteral("CodeBankRegMask"), {opts.registerMask}); // Add 'CodeBankNrOfs' item (Number of banks). addOptionsGroup(QByteArrayLiteral("CodeBankNrOfs"), {opts.banksCount}); // Add 'CodeBankStart' item (Bank start). addOptionsGroup(QByteArrayLiteral("CodeBankStart"), {opts.bankStart}); // Add 'CodeBankSize' item (Bank end). addOptionsGroup(QByteArrayLiteral("CodeBankSize"), {opts.bankEnd}); } void Mcs51GeneralSettingsGroup::buildLibraryOptionsPage( const ProductData &qbsProduct) { const LibraryOptionsPageOptions opts(qbsProduct); // Add 'Output variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Output variant"), {opts.printfFormatter}); // Add 'Input variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Input variant"), {opts.scanfFormatter}); } void Mcs51GeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GRuntimeLibSelect2' and 'GRuntimeLibSelectSlave2' items // (Link with runtime: none/dlib/clib/etc). addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect2"), {opts.libraryType}); addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave2"), {opts.libraryType}); // Add 'RTConfigPath' item (Runtime configuration file). addOptionsGroup(QByteArrayLiteral("RTConfigPath"), {opts.configPath}); // Add 'RTLibraryPath' item (Runtime library file). addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), {opts.libraryPath}); } void Mcs51GeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h0000644000175100017510000000465115232633614030431 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H #define QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51AssemblerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Mcs51AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildLanguagePage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h0000644000175100017510000000513415232633614030263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H #define QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51CompilerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Mcs51CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const ProductData &qbsProduct); void buildLanguageOnePage(const ProductData &qbsProduct); void buildLanguageTwoPage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildCodePage(const ProductData &qbsProduct); }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp0000644000175100017510000000737615232633614031124 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51archiversettingsgroup_v10.h" #include "mcs51assemblersettingsgroup_v10.h" #include "mcs51buildconfigurationgroup_v10.h" #include "mcs51compilersettingsgroup_v10.h" #include "mcs51generalsettingsgroup_v10.h" #include "mcs51linkersettingsgroup_v10.h" #include "../../iarewtoolchainpropertygroup.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { Mcs51BuildConfigurationGroup::Mcs51BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("configuration") { // Append configuration name item. const QString cfgName = gen::utils::buildConfigurationName(qbsProject); appendProperty("name", cfgName); // Apend toolchain name group item. appendChild("8051"); // Append debug info item. const int debugBuild = gen::utils::debugInformation(qbsProduct); appendProperty("debug", debugBuild); // Append settings group items. appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); } bool Mcs51BuildConfigurationGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Mcs51 && version.majorVersion() == 10; } std::unique_ptr Mcs51BuildConfigurationGroupFactory::create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new Mcs51BuildConfigurationGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h0000644000175100017510000000512715232633614030561 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H #define QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H #include namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51BuildConfigurationGroup final : public gen::xml::PropertyGroup { private: explicit Mcs51BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class Mcs51BuildConfigurationGroupFactory; }; class Mcs51BuildConfigurationGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h0000644000175100017510000000511415232633614027733 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H #define QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51LinkerSettingsGroupPrivate; class Mcs51LinkerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Mcs51LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildListPage(const ProductData &qbsProduct); void buildDefinePage(const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildExtraOptionsPage(const ProductData &qbsProduct); QVariantList m_extraOptions; }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp0000644000175100017510000002017615232633614030764 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51assemblersettingsgroup_v10.h" //#include "../../iarewproperty.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { constexpr int kAssemblerArchiveVersion = 2; constexpr int kAssemblerDataVersion = 6; namespace { // Language page options. struct LanguagePageOptions final { enum MacroQuoteCharacter { AngleBracketsQuote, RoundBracketsQuote, SquareBracketsQuote, FigureBracketsQuote }; explicit LanguagePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); enableMultibyteSupport = flags.contains(QLatin1String("-n")); if (flags.contains(QLatin1String("-M<>"))) macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; else if (flags.contains(QLatin1String("-M()"))) macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; else if (flags.contains(QLatin1String("-M[]"))) macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; else if (flags.contains(QLatin1String("-M{}"))) macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; } MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; int enableSymbolsCaseSensitive = 0; int enableMultibyteSupport = 0; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const auto &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (warningLevel == QLatin1String("all")) { enableWarnings = 0; enableAllWarnings = 0; } else if (warningLevel == QLatin1String("none")) { enableWarnings = 1; enableAllWarnings = 0; } else { enableWarnings = 0; enableAllWarnings = 1; } } int enableWarnings = 0; int enableAllWarnings = 0; }; } // namespace // Mcs51AssemblerSettingsGroup Mcs51AssemblerSettingsGroup::Mcs51AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProject) Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("A8051")); setArchiveVersion(kAssemblerArchiveVersion); setDataVersion(kAssemblerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildLanguagePage(qbsProduct); buildOutputPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Mcs51AssemblerSettingsGroup::buildLanguagePage( const ProductData &qbsProduct) { const LanguagePageOptions opts(qbsProduct); // Add 'ACaseSensitivity' item (User symbols are case sensitive). addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), {opts.enableSymbolsCaseSensitive}); // Add 'Asm multibyte support' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("Asm multibyte support"), {opts.enableMultibyteSupport}); // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). addOptionsGroup(QByteArrayLiteral("MacroChars"), {!opts.macroQuoteCharacter}, 0); } void Mcs51AssemblerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'Debug' item (Generate debug information). addOptionsGroup(QByteArrayLiteral("Debug"), {opts.debugInfo}); } void Mcs51AssemblerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'ADefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("ADefines"), opts.defineSymbols); // Add 'Include directories' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("Include directories"), opts.includePaths); } void Mcs51AssemblerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'AWarnEnable' item (Enable/disable warnings). addOptionsGroup(QByteArrayLiteral("AWarnEnable"), {opts.enableWarnings}); // Add 'AWarnWhat' item (Enable/disable all warnings). addOptionsGroup(QByteArrayLiteral("AWarnWhat"), {opts.enableAllWarnings}); } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp0000644000175100017510000000627315232633614030614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51archiversettingsgroup_v10.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { constexpr int kArchiverArchiveVersion = 2; constexpr int kArchiverDataVersion = 1; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { outputFile = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); } QString outputFile; }; } // namespace // Mcs51ArchiverSettingsGroup Mcs51ArchiverSettingsGroup::Mcs51ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("XAR")); setArchiveVersion(kArchiverArchiveVersion); setDataVersion(kArchiverDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(buildRootDirectory, qbsProduct); } void Mcs51ArchiverSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'XAROverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XAROverride"), {1}); // Add 'XAROutput2' item (Output filename). addOptionsGroup(QByteArrayLiteral("XAROutput2"), {opts.outputFile}); } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h0000644000175100017510000000521615232633614030067 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H #define QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { class Mcs51GeneralSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Mcs51GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildTargetPage(const ProductData &qbsProduct); void buildStackHeapPage(const ProductData &qbsProduct); void buildDataPointerPage(const ProductData &qbsProduct); void buildCodeBankPage(const ProductData &qbsProduct); void buildLibraryOptionsPage(const ProductData &qbsProduct); void buildLibraryConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp0000644000175100017510000003005315232633614030266 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51linkersettingsgroup_v10.h" #include "../../iarewutils.h" #include namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { constexpr int kLinkerArchiveVersion = 4; constexpr int kLinkerDataVersion = 21; namespace { // Config page options. struct ConfigPageOptions final { explicit ConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); entryPoint = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("entryPoint")); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); configFilePaths.push_back(path); } } } // Enumerate all product linker config files // (which are set trough '-f' option). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); const QVariantList configPathValues = IarewUtils::flagValues( flags, QStringLiteral("-f")); for (const QVariant &configPathValue : configPathValues) { const QString fullConfigPath = configPathValue.toString(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } else { const QString path =IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } } // Add libraries search paths. const QStringList libraryPaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("libraryPaths")}); for (const QString &libraryPath : libraryPaths) { const QFileInfo libraryPathInfo(libraryPath); const QString fullLibrarySearchPath = libraryPathInfo.absoluteFilePath(); if (fullLibrarySearchPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullLibrarySearchPath); librarySearchPaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullLibrarySearchPath); librarySearchPaths.push_back(path); } } } QVariantList configFilePaths; QVariantList librarySearchPaths; QString entryPoint; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { outputFile = gen::utils::targetBinary(qbsProduct); } QString outputFile; }; // List page options. struct ListPageOptions final { enum ListingAction { NoListing, GenerateListing }; explicit ListPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); generateMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")) ? ListPageOptions::GenerateListing : ListPageOptions::NoListing; } ListingAction generateMap = NoListing; }; // Define page options. struct DefinePageOptions final { explicit DefinePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); // Enumerate all linker defines. for (const QString &flag : flags) { if (!flag.startsWith(QLatin1String("-D"))) continue; const QString symbol = flag.mid(2); // Ignore system-defined macroses, because its already // handled in "General Options" page. if (symbol.startsWith(QLatin1Char('?')) || symbol.startsWith(QLatin1Char('_')) ) { continue; } defineSymbols.push_back(symbol); } } QVariantList defineSymbols; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); suppressAllWarnings = (warningLevel == QLatin1String("none")); } int suppressAllWarnings = 0; }; } // namespace // Mcs51LinkerSettingsGroup Mcs51LinkerSettingsGroup::Mcs51LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProject) Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("XLINK")); setArchiveVersion(kLinkerArchiveVersion); setDataVersion(kLinkerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildConfigPage(buildRootDirectory, qbsProduct); buildOutputPage(qbsProduct); buildListPage(qbsProduct); buildDefinePage(qbsProduct); buildDiagnosticsPage(qbsProduct); // Should be called as latest stage! buildExtraOptionsPage(qbsProduct); } void Mcs51LinkerSettingsGroup::buildConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { ConfigPageOptions opts(baseDirectory, qbsProduct); if (opts.configFilePaths.count() > 0) { // Note: IAR IDE does not allow to specify a multiple config files, // although the IAR linker support it. So, we use followig 'trick': // we take a first config file and to add it as usual to required items; // and then an other remainders we forward to the "Extra options page". const QVariant configPath = opts.configFilePaths.takeFirst(); // Add 'XclOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XclOverride"), {1}); // Add 'XclFile' item (Linke configuration file). addOptionsGroup(QByteArrayLiteral("XclFile"), {configPath}); // Add remainder configuration files to the "Extra options page". if (!opts.configFilePaths.isEmpty()) { for (QVariant &configPath : opts.configFilePaths) configPath = QString(QStringLiteral("-f ") + configPath.toString()); m_extraOptions << opts.configFilePaths; } } // Add 'xcProgramEntryLabel' item (Entry symbol). addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), {opts.entryPoint}); // Add 'xcOverrideProgramEntryLabel' item // (Override default program entry). addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), {1}); // Add 'xcProgramEntryLabelSelect' item. addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"), {0}); // Add 'XIncludes' item (Libraries search paths). addOptionsGroup(QByteArrayLiteral("XIncludes"), opts.librarySearchPaths); } void Mcs51LinkerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'XOutOverride' item (Override default output file). addOptionsGroup(QByteArrayLiteral("XOutOverride"), {1}); // Add 'OutputFile' item (Output file name). addOptionsGroup(QByteArrayLiteral("OutputFile"), {opts.outputFile}); } void Mcs51LinkerSettingsGroup::buildListPage( const ProductData &qbsProduct) { const ListPageOptions opts(qbsProduct); // Add 'XList' item (Generate linker listing). addOptionsGroup(QByteArrayLiteral("XList"), {opts.generateMap}); } void Mcs51LinkerSettingsGroup::buildDefinePage( const ProductData &qbsProduct) { const DefinePageOptions opts(qbsProduct); // Add 'XDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("XDefines"), opts.defineSymbols); } void Mcs51LinkerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'SuppressAllWarn' item (Suppress all warnings). addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"), {opts.suppressAllWarnings}); } void Mcs51LinkerSettingsGroup::buildExtraOptionsPage( const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (const QString &flag : flags) { if (flag.startsWith(QLatin1String("-Z"))) m_extraOptions.push_back(flag); } if (!m_extraOptions.isEmpty()) { // Add 'Linker Extra Options Check' (Use command line options). addOptionsGroup(QByteArrayLiteral("Linker Extra Options Check"), {1}); // Add 'Linker Extra Options Edit' item (Command line options). addOptionsGroup(QByteArrayLiteral("Linker Extra Options Edit"), m_extraOptions); } } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp0000644000175100017510000004421615232633614030622 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mcs51compilersettingsgroup_v10.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace mcs51 { namespace v10 { constexpr int kCompilerArchiveVersion = 7; constexpr int kCompilerDataVersion = 12; namespace { // Output page options. struct OutputPageOptions final { enum ModuleType { ProgramModule, LibraryModule }; explicit OutputPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); moduleType = flags.contains(QLatin1String("--library_module")) ? OutputPageOptions::LibraryModule : OutputPageOptions::ProgramModule; debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; ModuleType moduleType = ProgramModule; }; // Language one page options. struct LanguageOnePageOptions final { enum LanguageExtension { CLanguageExtension, CxxLanguageExtension, AutoLanguageExtension }; enum CLanguageDialect { C89LanguageDialect, C99LanguageDialect }; enum CxxLanguageDialect { EmbeddedCPlusPlus, ExtendedEmbeddedCPlusPlus }; enum LanguageConformance { AllowIarExtension, RelaxedStandard, StrictStandard }; explicit LanguageOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // File extension based by default. languageExtension = LanguageOnePageOptions::AutoLanguageExtension; // C language dialect. const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("cLanguageVersion")}); cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89")) ? LanguageOnePageOptions::C89LanguageDialect : LanguageOnePageOptions::C99LanguageDialect; // C++ language dialect. if (flags.contains(QLatin1String("--ec++"))) cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; else if (flags.contains(QLatin1String("--eec++"))) cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; // Language conformance. if (flags.contains(QLatin1String("-e"))) languageConformance = LanguageOnePageOptions::AllowIarExtension; else if (flags.contains(QLatin1String("--strict"))) languageConformance = LanguageOnePageOptions::StrictStandard; else languageConformance = LanguageOnePageOptions::RelaxedStandard; allowVla = flags.contains(QLatin1String("--vla")); useCppInlineSemantics = flags.contains( QLatin1String("--use_c++_inline")); requirePrototypes = flags.contains( QLatin1String("--require_prototypes")); destroyStaticObjects = !flags.contains( QLatin1String("--no_static_destruction")); } LanguageExtension languageExtension = AutoLanguageExtension; CLanguageDialect cLanguageDialect = C89LanguageDialect; CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; LanguageConformance languageConformance = AllowIarExtension; int allowVla = 0; int useCppInlineSemantics = 0; int requirePrototypes = 0; int destroyStaticObjects = 0; }; // Language two page options. struct LanguageTwoPageOptions final { enum PlainCharacter { SignedCharacter, UnsignedCharacter }; enum FloatingPointSemantic { StrictSemantic, RelaxedSemantic }; explicit LanguageTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); plainCharacter = flags.contains( QLatin1String("--char_is_signed")) ? LanguageTwoPageOptions::SignedCharacter : LanguageTwoPageOptions::UnsignedCharacter; floatingPointSemantic = flags.contains( QLatin1String("--relaxed_fp")) ? LanguageTwoPageOptions::RelaxedSemantic : LanguageTwoPageOptions::StrictSemantic; enableMultibyteSupport = flags.contains( QLatin1String("--enable_multibytes")); } PlainCharacter plainCharacter = SignedCharacter; FloatingPointSemantic floatingPointSemantic = StrictSemantic; int enableMultibyteSupport = 0; }; // Optimizations page options. struct OptimizationsPageOptions final { // Optimizations level radio-buttons with combo-box // on "level" widget. enum Strategy { StrategyBalanced, StrategySize, StrategySpeed }; enum Level { LevelNone, LevelLow, LevelMedium, LevelHigh }; enum LevelSlave { LevelSlave0, LevelSlave1, LevelSlave2, LevelSlave3 }; explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("none")) { optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; optimizationLevel = OptimizationsPageOptions::LevelNone; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; } else if (optimization == QLatin1String("fast")) { optimizationStrategy = OptimizationsPageOptions::StrategySpeed; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } else if (optimization == QLatin1String("small")) { optimizationStrategy = OptimizationsPageOptions::StrategySize; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); enableCommonSubexpressionElimination = !flags.contains( QLatin1String("--no_cse")); enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); enableTypeBasedAliasAnalysis = !flags.contains( QLatin1String("--no_tbaa")); enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); disableRegisterBanks = flags.contains( QLatin1String("--disable_register_banks")); disableSizeConstrains = flags.contains( QLatin1String("--no_size_constraints")); } Strategy optimizationStrategy = StrategyBalanced; Level optimizationLevel = LevelNone; LevelSlave optimizationLevelSlave = LevelSlave0; // Seven bit-field flags on "enabled transformations" widget. int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. int enableLoopUnroll = 0; // Loop unrolling. int enableFunctionInlining = 0; // Function inlining. int enableCodeMotion = 0; // Code motion. int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. int enableCrossCall = 0; // Cross call optimization. int disableRegisterBanks = 0; // Disabled register banks. int disableSizeConstrains = 0; // No size constraints. }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); // TODO: Need to exclude the pre-defined maroses which are handled // in 'General Options'. defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath(qbsProduct); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); // Exclude dlib config includes because it already handled in // 'General Options->Library configuration page'. if (includeFilePath.startsWith(dlibToolkitPath)) continue; if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; // Code page options. struct CodePageOptions final { explicit CodePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); paddingForRomMonitorBreakpoints = flags.contains( QLatin1String("--rom_mon_bp_padding")); excludeUbrofMessagesInOutput = flags.contains( QLatin1String("--no_ubrof_messages")); } int paddingForRomMonitorBreakpoints = 0; int excludeUbrofMessagesInOutput = 0; }; } // namespace // Mcs51CompilerSettingsGroup Mcs51CompilerSettingsGroup::Mcs51CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProject) Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ICC8051")); setArchiveVersion(kCompilerArchiveVersion); setDataVersion(kCompilerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(qbsProduct); buildLanguageOnePage(qbsProduct); buildLanguageTwoPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Mcs51CompilerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'CCDebugInfo' item (Generate debug info). addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), {opts.debugInfo}); // Add 'CCOverrideModuleTypeDefault' item // (Override default module type). addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"), {1}); // Add 'CCRadioModuleType' item (Module type: program/library). addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"), {opts.moduleType}); } void Mcs51CompilerSettingsGroup::buildLanguageOnePage( const ProductData &qbsProduct) { const LanguageOnePageOptions opts(qbsProduct); // Add 'IccLang' item with 'auto-extension based' // value (Language: C/C++/Auto). addOptionsGroup(QByteArrayLiteral("IccLang"), {opts.languageExtension}); // Add 'IccCDialect' item (C dialect: c89/99/11). addOptionsGroup(QByteArrayLiteral("IccCDialect"), {opts.cLanguageDialect}); // Add 'IccCppDialect' item (C++ dialect: embedded/extended). addOptionsGroup(QByteArrayLiteral("IccCppDialect"), {opts.cxxLanguageDialect}); // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). addOptionsGroup(QByteArrayLiteral("LangConform"), {opts.languageConformance}); // Add 'IccAllowVLA' item (Allow VLA). addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), {opts.allowVla}); // Add 'IccCppInlineSemantics' item (C++ inline semantics). addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), {opts.useCppInlineSemantics}); // Add 'CCRequirePrototypes' item (Require prototypes). addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), {opts.requirePrototypes}); // Add 'IccStaticDestr' item (Destroy static objects). addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), {opts.destroyStaticObjects}); } void Mcs51CompilerSettingsGroup::buildLanguageTwoPage( const ProductData &qbsProduct) { const LanguageTwoPageOptions opts(qbsProduct); // Add 'CharIs' item (Plain char is: signed/unsigned). addOptionsGroup(QByteArrayLiteral("CharIs"), {opts.plainCharacter}); // Add 'IccFloatSemantics' item // (Floatic-point semantics: strict/relaxed conformance). addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), {opts.floatingPointSemantic}); // Add 'CCMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), {opts.enableMultibyteSupport}); } void Mcs51CompilerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'CCOptStrategy', 'CCOptLevel' and // 'CCOptLevelSlave' items (Level). addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), {opts.optimizationStrategy}); addOptionsGroup(QByteArrayLiteral("CCOptLevel"), {opts.optimizationLevel}); addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), {opts.optimizationLevelSlave}); // Add 'CCAllowList2' item (Enabled transformations: 7 check boxes). const QString transformations = QStringLiteral("%1%2%3%4%5%6%7") .arg(opts.enableCommonSubexpressionElimination) .arg(opts.enableLoopUnroll) .arg(opts.enableFunctionInlining) .arg(opts.enableCodeMotion) .arg(opts.enableTypeBasedAliasAnalysis) .arg(opts.enableCrossCall) .arg(opts.disableRegisterBanks); addOptionsGroup(QByteArrayLiteral("CCAllowList2"), {transformations}); // Add 'NoSizeConstraints' item (No size constraints). addOptionsGroup(QByteArrayLiteral("NoSizeConstraints"), {opts.disableSizeConstrains}); } void Mcs51CompilerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'CCDefines' item (Defines symbols). addOptionsGroup(QByteArrayLiteral("CCDefines"), opts.defineSymbols); // Add 'CCIncludePath2' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), opts.includePaths); } void Mcs51CompilerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), {opts.warningsAsErrors}); } void Mcs51CompilerSettingsGroup::buildCodePage( const ProductData &qbsProduct) { const CodePageOptions opts(qbsProduct); // Add 'RomMonBpPadding' item (Padding for ROM-monitor breakpoints). addOptionsGroup(QByteArrayLiteral("RomMonBpPadding"), {opts.paddingForRomMonitorBreakpoints}); // Add 'NoUBROFMessages' item (No UBROF messages in output files). addOptionsGroup(QByteArrayLiteral("NoUBROFMessages"), {opts.excludeUbrofMessagesInOutput}); } } // namespace v10 } // namespace mcs51 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/0000755000175100017510000000000015232633614022176 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.h0000644000175100017510000000475015232633614030062 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H #define QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430LinkerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Msp430LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildListPage(const ProductData &qbsProduct); void buildDefinePage(const ProductData &qbsProduct); void buildExtraOptionsPage(const ProductData &qbsProduct); QVariantList m_extraOptions; }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.cpp0000644000175100017510000000741315232633614031236 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430archiversettingsgroup_v7.h" #include "msp430assemblersettingsgroup_v7.h" #include "msp430buildconfigurationgroup_v7.h" #include "msp430compilersettingsgroup_v7.h" #include "msp430generalsettingsgroup_v7.h" #include "msp430linkersettingsgroup_v7.h" #include "../../iarewtoolchainpropertygroup.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { Msp430BuildConfigurationGroup::Msp430BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("configuration") { // Append configuration name item. const QString cfgName = gen::utils::buildConfigurationName(qbsProject); appendProperty("name", cfgName); // Apend toolchain name group item. appendChild("MSP430"); // Append debug info item. const int debugBuild = gen::utils::debugInformation(qbsProduct); appendProperty("debug", debugBuild); // Append settings group items. appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); } bool Msp430BuildConfigurationGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Msp430 && version.majorVersion() == 7; } std::unique_ptr Msp430BuildConfigurationGroupFactory::create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new Msp430BuildConfigurationGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.cpp0000644000175100017510000002013515232633614031101 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430assemblersettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kAssemblerArchiveVersion = 5; constexpr int kAssemblerDataVersion = 14; namespace { // Language page options. struct LanguagePageOptions final { enum MacroQuoteCharacter { AngleBracketsQuote, RoundBracketsQuote, SquareBracketsQuote, FigureBracketsQuote }; explicit LanguagePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); enableSymbolsCaseSensitive = flags.contains( QLatin1String("-s+")); enableMultibyteSupport = flags.contains( QLatin1String("-n")); if (flags.contains(QLatin1String("-M<>"))) macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; else if (flags.contains(QLatin1String("-M()"))) macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; else if (flags.contains(QLatin1String("-M[]"))) macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; else if (flags.contains(QLatin1String("-M{}"))) macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; } int enableSymbolsCaseSensitive = 1; int enableMultibyteSupport = 0; MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const auto &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString warningLevel = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("warningLevel")); if (warningLevel == QLatin1String("all")) { enableWarnings = 0; enableAllWarnings = 0; } else if (warningLevel == QLatin1String("none")) { enableWarnings = 1; enableAllWarnings = 0; } else { enableWarnings = 0; enableAllWarnings = 1; } } int enableWarnings = 0; int enableAllWarnings = 0; }; } // namespace //Msp430AssemblerSettingsGroup Msp430AssemblerSettingsGroup::Msp430AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("A430")); setArchiveVersion(kAssemblerArchiveVersion); setDataVersion(kAssemblerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildLanguagePage(qbsProduct); buildOutputPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Msp430AssemblerSettingsGroup::buildLanguagePage( const ProductData &qbsProduct) { const LanguagePageOptions opts(qbsProduct); // Add 'ACaseSensitivity' item (User symbols are case sensitive). addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), {opts.enableSymbolsCaseSensitive}); // Add 'AMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("AMultibyteSupport"), {opts.enableMultibyteSupport}); // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). addOptionsGroup(QByteArrayLiteral("MacroChars"), {opts.macroQuoteCharacter}); } void Msp430AssemblerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'ADebug' item (Generate debug information). addOptionsGroup(QByteArrayLiteral("ADebug"), {opts.debugInfo}); } void Msp430AssemblerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'ADefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("ADefines"), opts.defineSymbols); // Add 'AUserIncludes' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("AUserIncludes"), opts.includePaths); } void Msp430AssemblerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'AWarnEnable' item (Enable/disable warnings). addOptionsGroup(QByteArrayLiteral("AWarnEnable"), {opts.enableWarnings}); // Add 'AWarnWhat' item (Enable/disable all warnings). addOptionsGroup(QByteArrayLiteral("AWarnWhat"), {opts.enableAllWarnings}); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.h0000644000175100017510000000465315232633614030555 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H #define QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430AssemblerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Msp430AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildLanguagePage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.cpp0000644000175100017510000000634315232633614030734 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430archiversettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kArchiverArchiveVersion = 4; constexpr int kArchiverDataVersion = 0; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { outputFile = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); } QString outputFile; }; } // namespace //Msp430ArchiverSettingsGroup Msp430ArchiverSettingsGroup::Msp430ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("XAR")); setArchiveVersion(kArchiverArchiveVersion); setDataVersion(kArchiverDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(buildRootDirectory, qbsProduct); } void Msp430ArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'XAROutOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XAROutOverride"), {1}); // Add 'OutputFile' item (Output filename). addOptionsGroup(QByteArrayLiteral("OutputFile"), {opts.outputFile}); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.cpp0000644000175100017510000002406515232633614030416 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430linkersettingsgroup_v7.h" #include "../../iarewutils.h" #include namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kLinkerArchiveVersion = 4; constexpr int kLinkerDataVersion = 30; namespace { // Config page options. struct ConfigPageOptions final { explicit ConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); configFilePaths.push_back(path); } } } // Enumerate all product linker config files // (which are set trough '-f' option). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); const QVariantList configPathValues = IarewUtils::flagValues( flags, QStringLiteral("-f")); for (const QVariant &configPathValue : configPathValues) { const QString fullConfigPath = configPathValue.toString(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } } // Library search paths. librarySearchPaths = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("libraryPaths")}); // Entry point. entryPoint = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("entryPoint")); } QVariantList configFilePaths; QVariantList librarySearchPaths; QString entryPoint; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { outputFile = gen::utils::targetBinary(qbsProduct); } QString outputFile; }; // List page options. struct ListPageOptions final { enum ListingAction { NoListing, GenerateListing }; explicit ListPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); generateMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")) ? ListPageOptions::GenerateListing : ListPageOptions::NoListing; } ListingAction generateMap = NoListing; }; // Define page options. struct DefinePageOptions final { explicit DefinePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); // Enumerate all linker defines. for (const QString &flag : flags) { if (!flag.startsWith(QLatin1String("-D"))) continue; const QString symbol = flag.mid(2); // Ignore system-defined macroses, because its already // handled in "General Options" page. if (symbol.startsWith(QLatin1Char('?')) || symbol.startsWith(QLatin1Char('_')) ) { continue; } defineSymbols.push_back(symbol); } } QVariantList defineSymbols; }; } // namespace //Msp430LinkerSettingsGroup Msp430LinkerSettingsGroup::Msp430LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("XLINK")); setArchiveVersion(kLinkerArchiveVersion); setDataVersion(kLinkerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildConfigPage(buildRootDirectory, qbsProduct); buildOutputPage(qbsProduct); buildListPage(qbsProduct); buildDefinePage(qbsProduct); // Should be called as latest stage! buildExtraOptionsPage(qbsProduct); } void Msp430LinkerSettingsGroup::buildConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { ConfigPageOptions opts(baseDirectory, qbsProduct); if (opts.configFilePaths.count() > 0) { // Note: IAR IDE does not allow to specify a multiple config files, // although the IAR linker support it. So, we use followig 'trick': // we take a first config file and to add it as usual to required items; // and then an other remainders we forward to the "Extra options page". const QVariant configPath = opts.configFilePaths.takeFirst(); // Add 'XclOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("XclOverride"), {1}); // Add 'XclFile' item (Linke configuration file). addOptionsGroup(QByteArrayLiteral("XclFile"), {configPath}); // Add remainder configuration files to the "Extra options page". if (!opts.configFilePaths.isEmpty()) { for (QVariant &configPath : opts.configFilePaths) configPath = QString(QStringLiteral("-f ") + configPath.toString()); m_extraOptions << opts.configFilePaths; } } // Add 'xcOverrideProgramEntryLabel' item // (Override default program entry). addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), {1}); // Add 'xcProgramEntryLabel' item (Entry point name). addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), {opts.entryPoint}); // Add 'XIncludes' item (Entry point name). addOptionsGroup(QByteArrayLiteral("XIncludes"), {opts.librarySearchPaths}); } void Msp430LinkerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'XOutOverride' item (Output file name). addOptionsGroup(QByteArrayLiteral("XOutOverride"), {1}); // Add 'OutputFile' item (Output file name). addOptionsGroup(QByteArrayLiteral("OutputFile"), {opts.outputFile}); } void Msp430LinkerSettingsGroup::buildListPage( const ProductData &qbsProduct) { const ListPageOptions opts(qbsProduct); // Add 'XList' item (Generate linker map file). addOptionsGroup(QByteArrayLiteral("XList"), {opts.generateMap}); } void Msp430LinkerSettingsGroup::buildDefinePage( const ProductData &qbsProduct) { const DefinePageOptions opts(qbsProduct); // Add 'XDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("XDefines"), opts.defineSymbols); } void Msp430LinkerSettingsGroup::buildExtraOptionsPage( const ProductData &qbsProduct) { Q_UNUSED(qbsProduct) if (m_extraOptions.isEmpty()) return; // Add 'XExtraOptionsCheck' (Use command line options). addOptionsGroup(QByteArrayLiteral("XExtraOptionsCheck"), {1}); // Add 'XExtraOptions' item (Command line options). addOptionsGroup(QByteArrayLiteral("XExtraOptions"), m_extraOptions); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.h0000644000175100017510000000435015232633614030375 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H #define QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430ArchiverSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Msp430ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.h0000644000175100017510000000513615232633614030407 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H #define QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430CompilerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Msp430CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const ProductData &qbsProduct); void buildLanguageOnePage(const ProductData &qbsProduct); void buildLanguageTwoPage(const ProductData &qbsProduct); void buildCodePage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.cpp0000644000175100017510000004404515232633614030744 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430compilersettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kCompilerArchiveVersion = 4; constexpr int kCompilerDataVersion = 38; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Language one page options. struct LanguageOnePageOptions final { enum LanguageExtension { CLanguageExtension, CxxLanguageExtension, AutoLanguageExtension }; enum CLanguageDialect { C89LanguageDialect, C99LanguageDialect }; enum CxxLanguageDialect { EmbeddedCPlusPlus, ExtendedEmbeddedCPlusPlus }; enum LanguageConformance { AllowIarExtension, RelaxedStandard, StrictStandard }; explicit LanguageOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // File extension based by default. languageExtension = LanguageOnePageOptions::AutoLanguageExtension; // C language dialect. const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("cLanguageVersion")}); if (cLanguageVersion.contains(QLatin1String("c89"))) cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; else if (cLanguageVersion.contains(QLatin1String("c99"))) cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; // C++ language dialect. if (flags.contains(QLatin1String("--ec++"))) cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; else if (flags.contains(QLatin1String("--eec++"))) cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; // Language conformance. if (flags.contains(QLatin1String("-e"))) languageConformance = LanguageOnePageOptions::AllowIarExtension; else if (flags.contains(QLatin1String("--strict"))) languageConformance = LanguageOnePageOptions::StrictStandard; else languageConformance = LanguageOnePageOptions::RelaxedStandard; allowVla = flags.contains(QLatin1String("--vla")); useCppInlineSemantics = flags.contains( QLatin1String("--use_c++_inline")); requirePrototypes = flags.contains( QLatin1String("--require_prototypes")); destroyStaticObjects = !flags.contains( QLatin1String("--no_static_destruction")); } LanguageExtension languageExtension = AutoLanguageExtension; CLanguageDialect cLanguageDialect = C99LanguageDialect; CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; LanguageConformance languageConformance = AllowIarExtension; int allowVla = 0; int useCppInlineSemantics = 0; int requirePrototypes = 0; int destroyStaticObjects = 0; }; // Language two page options. struct LanguageTwoPageOptions final { enum PlainCharacter { SignedCharacter, UnsignedCharacter }; enum FloatingPointSemantic { StrictSemantic, RelaxedSemantic }; explicit LanguageTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); plainCharacter = flags.contains(QLatin1String("--char_is_signed")) ? LanguageTwoPageOptions::SignedCharacter : LanguageTwoPageOptions::UnsignedCharacter; floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) ? LanguageTwoPageOptions::RelaxedSemantic : LanguageTwoPageOptions::StrictSemantic; enableMultibyteSupport = flags.contains( QLatin1String("--enable_multibytes")); guardCalls = flags.contains( QLatin1String("--guard_calls")); } PlainCharacter plainCharacter = UnsignedCharacter; FloatingPointSemantic floatingPointSemantic = StrictSemantic; int enableMultibyteSupport = 0; int guardCalls = 0; }; // Code page options. struct CodePageOptions final { enum Utilization { UtilizationNormalUse, UtilizationRegVarVariables, UtilizationNotUsed }; explicit CodePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // Detect R4 utilization. if (flags.contains(QLatin1String("--lock_r4"))) r4utilization = UtilizationNotUsed; else if (flags.contains(QLatin1String("--regvar_r4"))) r4utilization = UtilizationRegVarVariables; // Detect R5 utilization. if (flags.contains(QLatin1String("--lock_r5"))) r5utilization = UtilizationNotUsed; else if (flags.contains(QLatin1String("--regvar_r54"))) r5utilization = UtilizationRegVarVariables; // Detect reduce stack usage. reduceStackUsage = flags.contains( QLatin1String("--reduce_stack_usage")); // Detect 20-bit context save on interrupt. save20BitContextOnInterrupt = flags.contains( QLatin1String("--save_reg20")); } Utilization r4utilization = UtilizationNormalUse; Utilization r5utilization = UtilizationNormalUse; int reduceStackUsage = 0; int save20BitContextOnInterrupt = 0; }; // Optimizations page options. struct OptimizationsPageOptions final { // Optimizations level radio-buttons with // combo-box on "level" widget. enum Strategy { StrategyBalanced, StrategySize, StrategySpeed }; enum Level { LevelNone, LevelLow, LevelMedium, LevelHigh }; enum LevelSlave { LevelSlave0, LevelSlave1, LevelSlave2, LevelSlave3 }; explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("none")) { optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; optimizationLevel = OptimizationsPageOptions::LevelNone; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; } else if (optimization == QLatin1String("fast")) { optimizationStrategy = OptimizationsPageOptions::StrategySpeed; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } else if (optimization == QLatin1String("small")) { optimizationStrategy = OptimizationsPageOptions::StrategySize; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); disableSizeConstraints = flags.contains( QLatin1String("--no_size_constraints")); enableCommonSubexpressionElimination = !flags.contains( QLatin1String("--no_cse")); enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); enableTypeBasedAliasAnalysis = !flags.contains( QLatin1String("--no_tbaa")); } Strategy optimizationStrategy = StrategyBalanced; Level optimizationLevel = LevelNone; LevelSlave optimizationLevelSlave = LevelSlave0; // Separate "no size constraints" checkbox. int disableSizeConstraints = 0; // Five bit-field flags on "enabled transformations" widget. int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. int enableLoopUnroll = 0; // Loop unrolling. int enableFunctionInlining = 0; // Function inlining. int enableCodeMotion = 0; // Code motion. int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; } // namespace //Msp430CompilerSettingsGroup Msp430CompilerSettingsGroup::Msp430CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ICC430")); setArchiveVersion(kCompilerArchiveVersion); setDataVersion(kCompilerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(qbsProduct); buildLanguageOnePage(qbsProduct); buildLanguageTwoPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Msp430CompilerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'CCDebugInfo' item (Generate debug info). addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), {opts.debugInfo}); } void Msp430CompilerSettingsGroup::buildLanguageOnePage( const ProductData &qbsProduct) { const LanguageOnePageOptions opts(qbsProduct); // Add 'IccLang' item with 'auto-extension based' // value (Language: C/C++/Auto). addOptionsGroup(QByteArrayLiteral("IccLang"), {opts.languageExtension}); // Add 'IccCDialect' item (C dialect: c89/99/11). addOptionsGroup(QByteArrayLiteral("IccCDialect"), {opts.cLanguageDialect}); // Add 'IccCppDialect' item (C++ dialect: embedded/extended). addOptionsGroup(QByteArrayLiteral("IccCppDialect"), {opts.cxxLanguageDialect}); // Add 'CCExt' item // (Language conformance: IAR/relaxed/strict). addOptionsGroup(QByteArrayLiteral("CCExt"), {opts.languageConformance}); // Add 'IccAllowVLA' item (Allow VLA). addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), {opts.allowVla}); // Add 'IccCppInlineSemantics' item (C++ inline semantics). addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), {opts.useCppInlineSemantics}); // Add 'IccRequirePrototypes' item (Require prototypes). addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), {opts.requirePrototypes}); // Add 'IccStaticDestr' item (Destroy static objects). addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), {opts.destroyStaticObjects}); } void Msp430CompilerSettingsGroup::buildLanguageTwoPage( const ProductData &qbsProduct) { const LanguageTwoPageOptions opts(qbsProduct); // Add 'IccCharIs' item (Plain char is: signed/unsigned). addOptionsGroup(QByteArrayLiteral("CCCharIs"), {opts.plainCharacter}); // Add 'IccFloatSemantics' item (Floatic-point // semantics: strict/relaxed conformance). addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), {opts.floatingPointSemantic}); // Add 'IccMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), {opts.enableMultibyteSupport}); // Add 'CCGuardCalls' and 'OCGuardCallsSlave' item (Guard calls). addOptionsGroup(QByteArrayLiteral("CCGuardCalls"), {opts.guardCalls}); } void Msp430CompilerSettingsGroup::buildCodePage( const ProductData &qbsProduct) { const CodePageOptions opts(qbsProduct); // Add 'OCCR4Utilize' item // (R4 utilization: normal/regvar/disabled). addOptionsGroup(QByteArrayLiteral("OCCR4Utilize"), {opts.r4utilization}); // Add 'OCCR5Utilize' item // (R5 utilization: normal/regvar/disabled). addOptionsGroup(QByteArrayLiteral("OCCR5Utilize"), {opts.r5utilization}); // Add 'ReduceStack' item // (Reduce stack usage). addOptionsGroup(QByteArrayLiteral("ReduceStack"), {opts.reduceStackUsage}); // Add 'Save20bit' item // (20-bit context save on interrupt). addOptionsGroup(QByteArrayLiteral("Save20bit"), {opts.save20BitContextOnInterrupt}); } void Msp430CompilerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'CCOptStrategy', 'CCOptLevel' and // 'CCOptLevelSlave' items (Level). addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), {opts.optimizationStrategy}); addOptionsGroup(QByteArrayLiteral("CCOptLevel"), {opts.optimizationLevel}); addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), {opts.optimizationLevelSlave}); // Add 'CCOptimizationNoSizeConstraints' item (no size constraints). addOptionsGroup(QByteArrayLiteral("CCOptimizationNoSizeConstraints"), {opts.disableSizeConstraints}); // Add 'CCAllowList' item // (Enabled transformations: 5 check boxes). const QString bitflags = QStringLiteral("%1%2%3%4%5%6") .arg(opts.enableCommonSubexpressionElimination) .arg(opts.enableLoopUnroll) .arg(opts.enableFunctionInlining) .arg(opts.enableCodeMotion) .arg(opts.enableTypeBasedAliasAnalysis); addOptionsGroup(QByteArrayLiteral("CCAllowList"), {bitflags}); } void Msp430CompilerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'CCDefines' item (Defines symbols). addOptionsGroup(QByteArrayLiteral("CCDefines"), opts.defineSymbols); // Add 'newCCIncludePaths' item // (Additional include directories). addOptionsGroup(QByteArrayLiteral("newCCIncludePaths"), opts.includePaths); } void Msp430CompilerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), {opts.warningsAsErrors}); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.h0000644000175100017510000000502715232633614030211 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H #define QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430GeneralSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Msp430GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildTargetPage(const ProductData &qbsProduct); void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryOptionsPage(const ProductData &qbsProduct); void buildStackHeapPage(const ProductData &qbsProduct); }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.h0000644000175100017510000000520215232633614030675 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H #define QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H #include #include namespace qbs { namespace iarew { namespace msp430 { namespace v7 { class Msp430BuildConfigurationGroup final : public gen::xml::PropertyGroup { private: explicit Msp430BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class Msp430BuildConfigurationGroupFactory; }; class Msp430BuildConfigurationGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs #endif // QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.cpp0000644000175100017510000004532415232633614030550 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430generalsettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kGeneralArchiveVersion = 21; constexpr int kGeneralDataVersion = 34; namespace { // Target page options. struct TargetPageOptions final { enum CodeModel { SmallCodeModel, LargeCodeModel }; enum DataModel { SmallDataModel, MediumDataModel, LargeDataModel }; enum FloatingPointDoubleSize { DoubleSize32Bits, DoubleSize64Bits }; enum HardwareMultiplierType { AllowDirectAccessMultiplier, UseOnlyLibraryCallsMultiplier }; explicit TargetPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags")}); // Detect target code model. const QString codeModelValue = IarewUtils::flagValue( flags, QStringLiteral("--code_model")); if (codeModelValue == QLatin1String("small")) codeModel = TargetPageOptions::SmallCodeModel; else if (codeModelValue == QLatin1String("large")) codeModel = TargetPageOptions::LargeCodeModel; // Detect target data model. const QString dataModelValue = IarewUtils::flagValue( flags, QStringLiteral("--data_model")); if (dataModelValue == QLatin1String("small")) dataModel = TargetPageOptions::SmallDataModel; else if (dataModelValue == QLatin1String("medium")) dataModel = TargetPageOptions::MediumDataModel; else if (dataModelValue == QLatin1String("large")) dataModel = TargetPageOptions::LargeDataModel; // Detect floating point double size. const int doubleSize = IarewUtils::flagValue( flags, QStringLiteral("--double")).toInt(); if (doubleSize == 32) floatingPointDoubleSize = DoubleSize32Bits; else if (doubleSize == 64) floatingPointDoubleSize = DoubleSize64Bits; // Detect hardware multiplier. const QString multiplier = IarewUtils::flagValue( flags, QStringLiteral("--multiplier")); enableHardwareMultiplier = (multiplier.compare(QLatin1String("16")) == 0 || multiplier.compare(QLatin1String("16s")) == 0 || multiplier.compare(QLatin1String("32")) == 0); // Detect code and read-only data position-independence. enableRopi = flags.contains(QLatin1String("--ropi")); // No dynamic read-write initialization. disableDynamicReadWriteInitialization = flags.contains( QLatin1String("--no_rw_dynamic_init")); // Detect target device name. detectDeviceMenu(qbsProduct); } void detectDeviceMenu(const ProductData &qbsProduct) { const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) continue; const QFileInfo configInfo(fullConfigPath); const QString configBase = configInfo.baseName(); if (!configBase.startsWith(QLatin1String("lnk"))) continue; // Remove 'lnk' prefix. const QString deviceName = QStringLiteral("MSP%1") .arg(configBase.mid(3).toUpper()); deviceMenu = QStringLiteral("%1\t%1").arg(deviceName); return; } } // Falling back to generic menu. if (deviceMenu.isEmpty()) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QString cpuCore = IarewUtils::flagValue(flags, QStringLiteral("--core")); if (cpuCore.isEmpty()) return; deviceMenu = QStringLiteral("MSP%1\tGeneric MSP%1 device").arg(cpuCore); return; } } CodeModel codeModel = LargeCodeModel; DataModel dataModel = SmallDataModel; FloatingPointDoubleSize floatingPointDoubleSize = DoubleSize32Bits; HardwareMultiplierType hardwareMultiplierType = AllowDirectAccessMultiplier; int enableHardwareMultiplier = 0; int enableRopi = 0; int disableDynamicReadWriteInitialization = 0; QString deviceMenu; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalDLibrary, FullDLibrary, CustomDLibrary, CLibrary, // deprecated CustomCLibrary, // deprecated }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QFileInfo configInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); const QString configFilePath = configInfo.absoluteFilePath(); if (!configFilePath.isEmpty()) { const QString libToolkitPath = IarewUtils::libToolkitRootPath(qbsProduct); if (configFilePath.startsWith(libToolkitPath, Qt::CaseInsensitive)) { if (configFilePath.endsWith(QLatin1String("n.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::NormalDLibrary; } else if (configFilePath.endsWith(QLatin1String("f.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::FullDLibrary; } else { libraryType = LibraryConfigPageOptions::CustomDLibrary; } configPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, configFilePath); } else { libraryType = LibraryConfigPageOptions::CustomDLibrary; configPath = configFilePath; } } } RuntimeLibrary libraryType = NormalDLibrary; QString libraryPath; QString configPath; }; // Library options page options. struct LibraryOptionsPageOptions final { enum PrintfFormatter { PrintfAutoFormatter = 0, PrintfFullFormatter = 1, PrintfFullNoMultibytesFormatter = 2, PrintfLargeFormatter = 3, PrintfLargeNoMultibytesFormatter = 4, PrintfSmallFormatter = 5, PrintfSmallNoMultibytesFormatter = 6, PrintfTinyFormatter = 7 }; enum ScanfFormatter { ScanfAutoFormatter = 0, ScanfFullFormatter = 1, ScanfFullNoMultibytesFormatter = 2, ScanfLargeFormatter = 3, ScanfLargeNoMultibytesFormatter = 4, ScanfSmallFormatter = 5, ScanfSmallNoMultibytesFormatter = 6 }; explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (flagIt->endsWith(QLatin1String("=_printf"), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("_printffull")) printfFormatter = PrintfFullFormatter; else if (prop == QLatin1String("_printffullnomb")) printfFormatter = PrintfFullNoMultibytesFormatter; else if (prop == QLatin1String("_printflarge")) printfFormatter = PrintfLargeFormatter; else if (prop == QLatin1String("_printflargenomb")) printfFormatter = PrintfLargeNoMultibytesFormatter; else if (prop == QLatin1String("_printfsmall")) printfFormatter = PrintfSmallFormatter; else if (prop == QLatin1String("_printfsmallnomb")) printfFormatter = PrintfSmallNoMultibytesFormatter; else if (prop == QLatin1String("_printftiny")) printfFormatter = PrintfTinyFormatter; } else if (flagIt->endsWith(QLatin1String("=_scanf"), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("_scanffull")) scanfFormatter = ScanfFullFormatter; else if (prop == QLatin1String("_scanffullnomb")) scanfFormatter = ScanfFullNoMultibytesFormatter; else if (prop == QLatin1String("_scanflarge")) scanfFormatter = ScanfLargeFormatter; else if (prop == QLatin1String("_scanflargenomb")) scanfFormatter = ScanfLargeNoMultibytesFormatter; else if (prop == QLatin1String("_scanfsmall")) scanfFormatter = ScanfSmallFormatter; else if (prop == QLatin1String("_scanfsmallnomb")) scanfFormatter = ScanfSmallNoMultibytesFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Stack/heap page options. struct StackHeapPageOptions final { explicit StackHeapPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); // Detect stack size. stackSize = IarewUtils::flagValue( flags, QStringLiteral("-D_STACK_SIZE")); if (stackSize.isEmpty()) stackSize = QLatin1String("A0"); // Detect data heap16 size. data16HeapSize = IarewUtils::flagValue( flags, QStringLiteral("-D_DATA16_HEAP_SIZE")); if (data16HeapSize.isEmpty()) stackSize = QLatin1String("A0"); // Detect data heap20 size. data20HeapSize = IarewUtils::flagValue( flags, QStringLiteral("-D_DATA20_HEAP_SIZE")); if (data20HeapSize.isEmpty()) stackSize = QLatin1String("50"); } QString stackSize; QString data16HeapSize; QString data20HeapSize; }; } // namespace //Msp430GeneralSettingsGroup Msp430GeneralSettingsGroup::Msp430GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildLibraryOptionsPage(qbsProduct); buildStackHeapPage(qbsProduct); } void Msp430GeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'OGChipSelectMenu' item // (Device: xxx). addOptionsGroup(QByteArrayLiteral("OGChipSelectMenu"), {opts.deviceMenu}); // Add 'RadioCodeModelType' item // (Code model: small/large). addOptionsGroup(QByteArrayLiteral("RadioCodeModelType"), {opts.codeModel}); // Add 'RadioDataModelType' item // (Data model: small/medium/large). addOptionsGroup(QByteArrayLiteral("RadioDataModelType"), {opts.dataModel}); // Add 'OGDouble' item // (Floating point double size: 32/64 bits). addOptionsGroup(QByteArrayLiteral("OGDouble"), {opts.floatingPointDoubleSize}); // Add 'Hardware Multiplier' item // (Hardware multiplier). addOptionsGroup(QByteArrayLiteral("Hardware Multiplier"), {opts.enableHardwareMultiplier}); if (opts.enableHardwareMultiplier) { // Add 'RadioHardwareMultiplierType' item. addOptionsGroup(QByteArrayLiteral("Hardware RadioHardwareMultiplierType"), {opts.hardwareMultiplierType}); } // Add 'Ropi' item. // (Position independence: Code and read-only data). addOptionsGroup(QByteArrayLiteral("Ropi"), {opts.enableRopi}); // Add 'NoRwDynamicInit' item. // (Position independence: No dynamic read/write initialization). addOptionsGroup(QByteArrayLiteral("NoRwDynamicInit"), {opts.disableDynamicReadWriteInitialization}); } void Msp430GeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } void Msp430GeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items // (Link with runtime: none/normal/full/custom). addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), {opts.libraryType}); addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), {opts.libraryType}); // Add 'RTConfigPath' item (Runtime configuration file). addOptionsGroup(QByteArrayLiteral("RTConfigPath"), {opts.configPath}); // Add 'RTLibraryPath' item (Runtime library file). addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), {opts.libraryPath}); } void Msp430GeneralSettingsGroup::buildLibraryOptionsPage( const ProductData &qbsProduct) { const LibraryOptionsPageOptions opts(qbsProduct); // Add 'Output variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Output variant"), {opts.printfFormatter}); // Add 'Input variant' item (Scanf formatter). addOptionsGroup(QByteArrayLiteral("Input variant"), {opts.scanfFormatter}); } void Msp430GeneralSettingsGroup::buildStackHeapPage( const ProductData &qbsProduct) { const StackHeapPageOptions opts(qbsProduct); // Add 'GStackHeapOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("GStackHeapOverride"), {1}); // Add 'GStackSize2' item (Stack size). addOptionsGroup(QByteArrayLiteral("GStackSize2"), {opts.stackSize}); // Add 'GHeapSize2' item (Heap16 size). addOptionsGroup(QByteArrayLiteral("GHeapSize2"), {opts.data16HeapSize}); // Add 'GHeap20Size' item (Heap16 size). addOptionsGroup(QByteArrayLiteral("GHeap20Size"), {opts.data20HeapSize}); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/0000755000175100017510000000000015232633614022043 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp0000644000175100017510000003350715232633614030256 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8generalsettingsgroup_v3.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { constexpr int kGeneralArchiveVersion = 4; constexpr int kGeneralDataVersion = 2; namespace { // Target page options. struct TargetPageOptions final { enum CodeModel { SmallCodeModel, MediumCodeModel, LargeCodeModel }; enum DataModel { SmallDataModel, MediumDataModel, LargeDataModel }; explicit TargetPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags")}); // Detect target code model. const QString codeModelValue = IarewUtils::flagValue( flags, QStringLiteral("--code_model")); if (codeModelValue == QLatin1String("small")) codeModel = TargetPageOptions::SmallCodeModel; else if (codeModelValue == QLatin1String("medium")) codeModel = TargetPageOptions::MediumCodeModel; else if (codeModelValue == QLatin1String("large")) codeModel = TargetPageOptions::LargeCodeModel; // Detect target data model. const QString dataModelValue = IarewUtils::flagValue( flags, QStringLiteral("--data_model")); if (dataModelValue == QLatin1String("small")) dataModel = TargetPageOptions::SmallDataModel; else if (dataModelValue == QLatin1String("medium")) dataModel = TargetPageOptions::MediumDataModel; else if (dataModelValue == QLatin1String("large")) dataModel = TargetPageOptions::LargeDataModel; } CodeModel codeModel = MediumCodeModel; DataModel dataModel = MediumDataModel; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalLibrary, FullLibrary, CustomLibrary }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QFileInfo configInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); const QString configFilePath = configInfo.absoluteFilePath(); if (!configFilePath.isEmpty()) { const QString libToolkitPath = IarewUtils::libToolkitRootPath(qbsProduct); if (configFilePath.startsWith(libToolkitPath, Qt::CaseInsensitive)) { if (configFilePath.endsWith(QLatin1String("n.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::NormalLibrary; } else if (configFilePath.endsWith(QLatin1String("f.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::FullLibrary; } else { libraryType = LibraryConfigPageOptions::CustomLibrary; } configPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, configFilePath); } else { libraryType = LibraryConfigPageOptions::CustomLibrary; configPath = configFilePath; } } else { libraryType = LibraryConfigPageOptions::NoLibrary; } } RuntimeLibrary libraryType = NoLibrary; QString configPath; }; // Library options page options. struct LibraryOptionsPageOptions final { enum PrintfFormatter { PrintfAutoFormatter = 0, PrintfFullFormatter = 1, PrintfFullNoMultibytesFormatter = 2, PrintfLargeFormatter = 3, PrintfLargeNoMultibytesFormatter = 4, PrintfSmallFormatter = 5, PrintfSmallNoMultibytesFormatter = 6, PrintfTinyFormatter = 7 }; enum ScanfFormatter { ScanfAutoFormatter = 0, ScanfFullFormatter = 1, ScanfFullNoMultibytesFormatter = 2, ScanfLargeFormatter = 3, ScanfLargeNoMultibytesFormatter = 4, ScanfSmallFormatter = 5, ScanfSmallNoMultibytesFormatter = 6 }; explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (*flagIt != QLatin1String("--redirect")) continue; ++flagIt; if (flagIt->startsWith(QLatin1String("_printf="), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(1).toLower(); if (prop == QLatin1String("_printffull")) printfFormatter = PrintfFullFormatter; else if (prop == QLatin1String("_printffullnomb")) printfFormatter = PrintfFullNoMultibytesFormatter; else if (prop == QLatin1String("_printflarge")) printfFormatter = PrintfLargeNoMultibytesFormatter; else if (prop == QLatin1String("_printflargenomb")) printfFormatter = PrintfLargeFormatter; else if (prop == QLatin1String("_printfsmall")) printfFormatter = PrintfSmallFormatter; else if (prop == QLatin1String("_printfsmallnomb")) printfFormatter = PrintfSmallNoMultibytesFormatter; else if (prop == QLatin1String("_printftiny")) printfFormatter = PrintfTinyFormatter; } else if (flagIt->startsWith(QLatin1String("_scanf="), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(1).toLower(); if (prop == QLatin1String("_scanffull")) scanfFormatter = ScanfFullFormatter; else if (prop == QLatin1String("_scanffullnomb")) scanfFormatter = ScanfFullNoMultibytesFormatter; else if (prop == QLatin1String("_scanflarge")) scanfFormatter = ScanfLargeNoMultibytesFormatter; else if (prop == QLatin1String("_scanflargenomb")) scanfFormatter = ScanfLargeFormatter; else if (prop == QLatin1String("_scanfsmall")) scanfFormatter = ScanfSmallFormatter; else if (prop == QLatin1String("_scanfsmallnomb")) scanfFormatter = ScanfSmallNoMultibytesFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Stack/heap page options. struct StackHeapPageOptions final { explicit StackHeapPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); const auto configDefs = IarewUtils::flagValues( flags, QStringLiteral("--config_def")); for (const auto &configDef : configDefs) { const auto def = configDef.toString(); if (def.startsWith(QLatin1String("_CSTACK_SIZE="))) { stackSize = def.split(QLatin1Char('=')).at(1); } else if (def.startsWith(QLatin1String("_HEAP_SIZE="))) { heapSize = def.split(QLatin1Char('=')).at(1); } } } QString stackSize; QString heapSize; }; } // namespace // Stm8GeneralSettingsGroup Stm8GeneralSettingsGroup::Stm8GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildLibraryOptionsPage(qbsProduct); buildStackHeapPage(qbsProduct); } void Stm8GeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'GenCodeModel' item // (Code model: small/medium/large). addOptionsGroup(QByteArrayLiteral("GenCodeModel"), {opts.codeModel}); // Add 'GenDataModel' item // (Data model: small/medium/large). addOptionsGroup(QByteArrayLiteral("GenDataModel"), {opts.dataModel}); } void Stm8GeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } void Stm8GeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GenRuntimeLibSelect' and 'GenRuntimeLibSelectSlave' items // (Link with runtime: none/normal/full/custom). addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelect"), {opts.libraryType}); addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelectSlave"), {opts.libraryType}); // Add 'GenRTConfigPath' item (Runtime configuration file). addOptionsGroup(QByteArrayLiteral("GenRTConfigPath"), {opts.configPath}); } void Stm8GeneralSettingsGroup::buildLibraryOptionsPage( const ProductData &qbsProduct) { const LibraryOptionsPageOptions opts(qbsProduct); // Add 'GenLibOutFormatter' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("GenLibOutFormatter"), {opts.printfFormatter}); // Add 'GenLibInFormatter' item (Scanf formatter). addOptionsGroup(QByteArrayLiteral("GenLibInFormatter"), {opts.scanfFormatter}); } void Stm8GeneralSettingsGroup::buildStackHeapPage( const ProductData &qbsProduct) { const StackHeapPageOptions opts(qbsProduct); // Add 'GenStackSize' item (Stack size). addOptionsGroup(QByteArrayLiteral("GenStackSize"), {opts.stackSize}); // Add 'GenHeapSize' item (Heap size). addOptionsGroup(QByteArrayLiteral("GenHeapSize"), {opts.heapSize}); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h0000644000175100017510000000501115232633614027710 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H #define QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8GeneralSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Stm8GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildTargetPage(const ProductData &qbsProduct); void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryOptionsPage(const ProductData &qbsProduct); void buildStackHeapPage(const ProductData &qbsProduct); }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp0000644000175100017510000002051315232633614030607 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8assemblersettingsgroup_v3.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { constexpr int kAssemblerArchiveVersion = 3; constexpr int kAssemblerDataVersion = 2; namespace { // Language page options. struct LanguagePageOptions final { enum MacroQuoteCharacter { AngleBracketsQuote, RoundBracketsQuote, SquareBracketsQuote, FigureBracketsQuote }; explicit LanguagePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("assemblerFlags")}); enableSymbolsCaseSensitive = !flags.contains( QLatin1String("--case_insensitive")); enableMultibyteSupport = flags.contains( QLatin1String("--enable_multibytes")); allowFirstColumnMnemonics = flags.contains( QLatin1String("--mnem_first")); allowFirstColumnDirectives = flags.contains( QLatin1String("--dir_first")); if (flags.contains(QLatin1String("-M<>"))) macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; else if (flags.contains(QLatin1String("-M()"))) macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; else if (flags.contains(QLatin1String("-M[]"))) macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; else if (flags.contains(QLatin1String("-M{}"))) macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; } int enableSymbolsCaseSensitive = 1; int enableMultibyteSupport = 0; int allowFirstColumnMnemonics = 0; int allowFirstColumnDirectives = 0; MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const auto &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; } // namespace // Stm8AssemblerSettingsGroup Stm8AssemblerSettingsGroup::Stm8AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ASTM8")); setArchiveVersion(kAssemblerArchiveVersion); setDataVersion(kAssemblerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildLanguagePage(qbsProduct); buildOutputPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Stm8AssemblerSettingsGroup::buildLanguagePage( const ProductData &qbsProduct) { const LanguagePageOptions opts(qbsProduct); // Add 'AsmCaseSensitivity' item (User symbols are case sensitive). addOptionsGroup(QByteArrayLiteral("AsmCaseSensitivity"), {opts.enableSymbolsCaseSensitive}); // Add 'AsmMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("AsmMultibyteSupport"), {opts.enableMultibyteSupport}); // Add 'AsmAllowMnemonics' item (Allow mnemonics in first column). addOptionsGroup(QByteArrayLiteral("AsmAllowMnemonics"), {opts.allowFirstColumnMnemonics}); // Add 'AsmAllowDirectives' item (Allow directives in first column). addOptionsGroup(QByteArrayLiteral("AsmAllowDirectives"), {opts.allowFirstColumnDirectives}); // Add 'AsmMacroChars' item (Macro quote characters: ()/[]/{}/<>). addOptionsGroup(QByteArrayLiteral("AsmMacroChars"), {opts.macroQuoteCharacter}); } void Stm8AssemblerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'AsmDebugInfo' item (Generate debug information). addOptionsGroup(QByteArrayLiteral("AsmDebugInfo"), {opts.debugInfo}); } void Stm8AssemblerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'AsmDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("AsmDefines"), opts.defineSymbols); // Add 'AsmIncludePath' item (Additional include directories). addOptionsGroup(QByteArrayLiteral("AsmIncludePath"), opts.includePaths); } void Stm8AssemblerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'AsmDiagnosticsWarningsAreErrors' item. // (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("AsmDiagnosticsWarningsAreErrors"), {opts.warningsAsErrors}); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h0000644000175100017510000000503115232633614030107 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H #define QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8CompilerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Stm8CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const ProductData &qbsProduct); void buildLanguageOnePage(const ProductData &qbsProduct); void buildLanguageTwoPage(const ProductData &qbsProduct); void buildOptimizationsPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h0000644000175100017510000000433215232633614030103 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H #define QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8ArchiverSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Stm8ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct); }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp0000644000175100017510000000634715232633614030446 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8archiversettingsgroup_v3.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { constexpr int kArchiverArchiveVersion = 3; constexpr int kArchiverDataVersion = 0; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { outputFile = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); } QString outputFile; }; } // namespace // Stm8ArchiverSettingsGroup Stm8ArchiverSettingsGroup::Stm8ArchiverSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("IARCHIVE")); setArchiveVersion(kArchiverArchiveVersion); setDataVersion(kArchiverDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(buildRootDirectory, qbsProduct); } void Stm8ArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'IarchiveOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("IarchiveOverride"), {1}); // Add 'IarchiveOutput' item (Output filename). addOptionsGroup(QByteArrayLiteral("IarchiveOutput"), {opts.outputFile}); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp0000644000175100017510000003514615232633614030126 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8linkersettingsgroup_v3.h" #include "../../iarewutils.h" #include #include namespace qbs { namespace iarew { namespace stm8 { namespace v3 { constexpr int kLinkerArchiveVersion = 5; constexpr int kLinkerDataVersion = 4; namespace { // Config page options. struct ConfigPageOptions final { explicit ConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). for (const auto &qbsGroup : qbsProduct.groups()) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); configFilePaths.push_back(path); } } } // Enumerate all product linker config files // (which are set trough '-config' option). const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); const QVariantList configPathValues = IarewUtils::flagValues( flags, QStringLiteral("--config")); for (const QVariant &configPathValue : configPathValues) { const QString fullConfigPath = configPathValue.toString(); if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullConfigPath); if (!configFilePaths.contains(path)) configFilePaths.push_back(path); } } // Enumerate all config definition symbols (except // the CSTACK_SIZE and HEAP_SIZE which are handles // on the general page). configDefinitions = IarewUtils::flagValues( flags, QStringLiteral("--config_def")); Internal::removeIf(configDefinitions, [](const auto &definition){ const auto def = definition.toString(); return def.startsWith(QLatin1String("_CSTACK_SIZE")) || def.startsWith(QLatin1String("_HEAP_SIZE")); }); } QVariantList configFilePaths; QVariantList configDefinitions; }; struct LibraryPageOptions final { explicit LibraryPageOptions(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); entryPoint = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("entryPoint")); // Add static libraries paths. const QStringList staticLibrariesProps = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("staticLibraries")}); for (const QString &staticLibrary : staticLibrariesProps) { const QFileInfo staticLibraryInfo(staticLibrary); if (staticLibraryInfo.isAbsolute()) { const QString fullStaticLibraryPath = staticLibraryInfo.absoluteFilePath(); if (fullStaticLibraryPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, fullStaticLibraryPath); staticLibraries.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, fullStaticLibraryPath); staticLibraries.push_back(path); } } else { staticLibraries.push_back(staticLibrary); } } // Add static libraries from product dependencies. for (const ProductData &qbsProductDep : qbsProductDeps) { const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + gen::utils::targetBinaryPath(baseDirectory, qbsProductDep); staticLibraries.push_back(depBinaryPath); } } QString entryPoint; QVariantList staticLibraries; }; struct OptimizationsPageOptions final { explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); mergeDuplicateSections = flags.contains( QLatin1String("--merge_duplicate_sections")); } bool mergeDuplicateSections = true; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { outputFile = gen::utils::targetBinary(qbsProduct); const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); enableDebugInfo = !flags.contains(QLatin1String("--strip")); } QString outputFile; bool enableDebugInfo = true; }; // List page options. struct ListPageOptions final { enum ListingAction { NoListing, GenerateListing }; explicit ListPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); generateMap = gen::utils::cppBooleanModuleProperty( qbsProps, QStringLiteral("generateLinkerMapFile")) ? ListPageOptions::GenerateListing : ListPageOptions::NoListing; } ListingAction generateMap = NoListing; }; // Define page options. struct DefinePageOptions final { explicit DefinePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); defineSymbols = IarewUtils::flagValues( flags, QStringLiteral("--define_symbol")); } QVariantList defineSymbols; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; } // namespace // Stm8LinkerSettingsGroup Stm8LinkerSettingsGroup::Stm8LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { setName(QByteArrayLiteral("ILINK")); setArchiveVersion(kLinkerArchiveVersion); setDataVersion(kLinkerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildConfigPage(buildRootDirectory, qbsProduct); buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps); buildOptimizationsPage(qbsProduct); buildOutputPage(qbsProduct); buildListPage(qbsProduct); buildDefinePage(qbsProduct); buildDiagnosticsPage(qbsProduct); // Should be called as latest stage! buildExtraOptionsPage(qbsProduct); } void Stm8LinkerSettingsGroup::buildConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { ConfigPageOptions opts(baseDirectory, qbsProduct); if (opts.configFilePaths.count() > 0) { // Note: IAR IDE does not allow to specify a multiple config files, // although the IAR linker support it. So, we use followig 'trick': // we take a first config file and to add it as usual to required items; // and then an other remainders we forward to the "Extra options page". const QVariant configPath = opts.configFilePaths.takeFirst(); // Add 'IlinkIcfOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"), {1}); // Add 'IlinkIcfFile' item (Linke configuration file). addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"), {configPath}); // Add remainder configuration files to the "Extra options page". if (!opts.configFilePaths.isEmpty()) { for (QVariant &configPath : opts.configFilePaths) configPath = QString(QStringLiteral("--config ") + configPath.toString()); m_extraOptions << opts.configFilePaths; } } // Add 'IlinkConfigDefines' item (Configuration file // symbol definitions). addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"), opts.configDefinitions); } void Stm8LinkerSettingsGroup::buildLibraryPage( const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); // Add 'IlinkOverrideProgramEntryLabel' item // (Override default program entry). addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"), {1}); if (opts.entryPoint.isEmpty()) { // Add 'IlinkProgramEntryLabelSelect' item // (Defined by application). addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"), {1}); } else { // Add 'IlinkProgramEntryLabel' item // (Entry symbol). addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"), {opts.entryPoint}); } // Add 'IlinkAdditionalLibs' item (Additional libraries). addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"), {opts.staticLibraries}); } void Stm8LinkerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { OptimizationsPageOptions opts(qbsProduct); // Add 'IlinkOptMergeDuplSections' item // (Merge duplicate sections). addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"), {opts.mergeDuplicateSections}); } void Stm8LinkerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'IlinkOutputFile' item (Output file name). addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"), {opts.outputFile}); // Add 'IlinkDebugInfoEnable' item // (Include debug information in output). addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"), {opts.enableDebugInfo}); } void Stm8LinkerSettingsGroup::buildListPage( const ProductData &qbsProduct) { const ListPageOptions opts(qbsProduct); // Add 'IlinkMapFile' item (Generate linker map file). addOptionsGroup(QByteArrayLiteral("IlinkMapFile"), {opts.generateMap}); } void Stm8LinkerSettingsGroup::buildDefinePage( const ProductData &qbsProduct) { const DefinePageOptions opts(qbsProduct); // Add 'IlinkDefines' item (Defined symbols). addOptionsGroup(QByteArrayLiteral("IlinkDefines"), opts.defineSymbols); } void Stm8LinkerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'IlinkWarningsAreErrors' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"), {opts.warningsAsErrors}); } void Stm8LinkerSettingsGroup::buildExtraOptionsPage( const ProductData &qbsProduct) { Q_UNUSED(qbsProduct) if (m_extraOptions.isEmpty()) return; // Add 'IlinkUseExtraOptions' (Use command line options). addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"), {1}); // Add 'IlinkExtraOptions' item (Command line options). addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"), m_extraOptions); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h0000644000175100017510000000542515232633614027570 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H #define QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8LinkerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Stm8LinkerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildConfigPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildLibraryPage(const QString &baseDirectory, const ProductData &qbsProduct, const std::vector &qbsProductDeps); void buildOptimizationsPage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildListPage(const ProductData &qbsProduct); void buildDefinePage(const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); void buildExtraOptionsPage(const ProductData &qbsProduct); QVariantList m_extraOptions; }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h0000644000175100017510000000516015232633614030406 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H #define QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H #include #include namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8BuildConfigurationGroup final : public gen::xml::PropertyGroup { private: explicit Stm8BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); friend class Stm8BuildConfigurationGroupFactory; }; class Stm8BuildConfigurationGroupFactory final : public gen::xml::PropertyGroupFactory { public: bool canCreate(gen::utils::Architecture arch, const Version &version) const final; std::unique_ptr create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const final; }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h0000644000175100017510000000463515232633614030263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H #define QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H #include "../../iarewsettingspropertygroup.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { class Stm8AssemblerSettingsGroup final : public IarewSettingsPropertyGroup { public: explicit Stm8AssemblerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps); private: void buildLanguagePage(const ProductData &qbsProduct); void buildOutputPage(const ProductData &qbsProduct); void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); void buildDiagnosticsPage(const ProductData &qbsProduct); }; } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs #endif // QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp0000644000175100017510000004044315232633614030450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8compilersettingsgroup_v3.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { constexpr int kCompilerArchiveVersion = 3; constexpr int kCompilerDataVersion = 9; namespace { // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const ProductData &qbsProduct) { debugInfo = gen::utils::debugInformation(qbsProduct); } int debugInfo = 0; }; // Language one page options. struct LanguageOnePageOptions final { enum LanguageExtension { CLanguageExtension, CxxLanguageExtension, AutoLanguageExtension }; enum CLanguageDialect { C89LanguageDialect, C99LanguageDialect }; enum CxxLanguageDialect { EmbeddedCPlusPlus, ExtendedEmbeddedCPlusPlus }; enum LanguageConformance { AllowIarExtension, RelaxedStandard, StrictStandard }; explicit LanguageOnePageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); // File extension based by default. languageExtension = LanguageOnePageOptions::AutoLanguageExtension; // C language dialect. const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("cLanguageVersion")}); if (cLanguageVersion.contains(QLatin1String("c89"))) cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; else if (cLanguageVersion.contains(QLatin1String("c99"))) cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; // C++ language dialect. if (flags.contains(QLatin1String("--ec++"))) cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; else if (flags.contains(QLatin1String("--eec++"))) cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; // Language conformance. if (flags.contains(QLatin1String("-e"))) languageConformance = LanguageOnePageOptions::AllowIarExtension; else if (flags.contains(QLatin1String("--strict"))) languageConformance = LanguageOnePageOptions::StrictStandard; else languageConformance = LanguageOnePageOptions::RelaxedStandard; allowVla = flags.contains(QLatin1String("--vla")); useCppInlineSemantics = flags.contains( QLatin1String("--use_c++_inline")); requirePrototypes = flags.contains( QLatin1String("--require_prototypes")); destroyStaticObjects = !flags.contains( QLatin1String("--no_static_destruction")); } LanguageExtension languageExtension = AutoLanguageExtension; CLanguageDialect cLanguageDialect = C99LanguageDialect; CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; LanguageConformance languageConformance = AllowIarExtension; int allowVla = 0; int useCppInlineSemantics = 0; int requirePrototypes = 0; int destroyStaticObjects = 0; }; // Language two page options. struct LanguageTwoPageOptions final { enum PlainCharacter { SignedCharacter, UnsignedCharacter }; enum FloatingPointSemantic { StrictSemantic, RelaxedSemantic }; explicit LanguageTwoPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); plainCharacter = flags.contains(QLatin1String("--char_is_signed")) ? LanguageTwoPageOptions::SignedCharacter : LanguageTwoPageOptions::UnsignedCharacter; floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) ? LanguageTwoPageOptions::RelaxedSemantic : LanguageTwoPageOptions::StrictSemantic; enableMultibyteSupport = flags.contains( QLatin1String("--enable_multibytes")); } PlainCharacter plainCharacter = UnsignedCharacter; FloatingPointSemantic floatingPointSemantic = StrictSemantic; int enableMultibyteSupport = 0; }; // Optimizations page options. struct OptimizationsPageOptions final { // Optimizations level radio-buttons with // combo-box on "level" widget. enum Strategy { StrategyBalanced, StrategySize, StrategySpeed }; enum Level { LevelNone, LevelLow, LevelMedium, LevelHigh }; enum LevelSlave { LevelSlave0, LevelSlave1, LevelSlave2, LevelSlave3 }; enum VRegsNumber { VRegs12, VRegs16 }; explicit OptimizationsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QString optimization = gen::utils::cppStringModuleProperty( qbsProps, QStringLiteral("optimization")); if (optimization == QLatin1String("none")) { optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; optimizationLevel = OptimizationsPageOptions::LevelNone; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; } else if (optimization == QLatin1String("fast")) { optimizationStrategy = OptimizationsPageOptions::StrategySpeed; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } else if (optimization == QLatin1String("small")) { optimizationStrategy = OptimizationsPageOptions::StrategySize; optimizationLevel = OptimizationsPageOptions::LevelHigh; optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; } const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); disableSizeConstraints = flags.contains( QLatin1String("--no_size_constraints")); enableCommonSubexpressionElimination = !flags.contains( QLatin1String("--no_cse")); enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); enableTypeBasedAliasAnalysis = !flags.contains( QLatin1String("--no_tbaa")); enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); const auto vregsCount = IarewUtils::flagValue( flags, QStringLiteral("--vregs")).toInt(); if (vregsCount == 12) vregsNumber = VRegs12; else if (vregsCount == 16) vregsNumber = VRegs16; } Strategy optimizationStrategy = StrategyBalanced; Level optimizationLevel = LevelNone; LevelSlave optimizationLevelSlave = LevelSlave0; // Separate "no size constraints" checkbox. int disableSizeConstraints = 0; // Six bit-field flags on "enabled transformations" widget. int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. int enableLoopUnroll = 0; // Loop unrolling. int enableFunctionInlining = 0; // Function inlining. int enableCodeMotion = 0; // Code motion. int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. int enableCrossCall = 0; // Cross call. VRegsNumber vregsNumber = VRegs16; }; // Preprocessor page options. struct PreprocessorPageOptions final { explicit PreprocessorPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); defineSymbols = gen::utils::cppVariantModuleProperties( qbsProps, {QStringLiteral("defines")}); const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("includePaths"), QStringLiteral("systemIncludePaths")}); for (const QString &fullIncludePath : fullIncludePaths) { const QFileInfo includeFileInfo(fullIncludePath); const QString includeFilePath = includeFileInfo.absoluteFilePath(); if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { const QString path = IarewUtils::toolkitRelativeFilePath( toolkitPath, includeFilePath); includePaths.push_back(path); } else { const QString path = IarewUtils::projectRelativeFilePath( baseDirectory, includeFilePath); includePaths.push_back(path); } } } QVariantList defineSymbols; QVariantList includePaths; }; // Diagnostics page options. struct DiagnosticsPageOptions final { explicit DiagnosticsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); warningsAsErrors = gen::utils::cppIntegerModuleProperty( qbsProps, QStringLiteral("treatWarningsAsErrors")); } int warningsAsErrors = 0; }; } // namespace // Stm8CompilerSettingsGroup Stm8CompilerSettingsGroup::Stm8CompilerSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("ICCSTM8")); setArchiveVersion(kCompilerArchiveVersion); setDataVersion(kCompilerDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildOutputPage(qbsProduct); buildLanguageOnePage(qbsProduct); buildLanguageTwoPage(qbsProduct); buildOptimizationsPage(qbsProduct); buildPreprocessorPage(buildRootDirectory, qbsProduct); buildDiagnosticsPage(qbsProduct); } void Stm8CompilerSettingsGroup::buildOutputPage( const ProductData &qbsProduct) { const OutputPageOptions opts(qbsProduct); // Add 'IccGenerateDebugInfo' item (Generate debug info). addOptionsGroup(QByteArrayLiteral("IccGenerateDebugInfo"), {opts.debugInfo}); } void Stm8CompilerSettingsGroup::buildLanguageOnePage( const ProductData &qbsProduct) { const LanguageOnePageOptions opts(qbsProduct); // Add 'IccLang' item with 'auto-extension based' // value (Language: C/C++/Auto). addOptionsGroup(QByteArrayLiteral("IccLang"), {opts.languageExtension}); // Add 'IccCDialect' item (C dialect: c89/99/11). addOptionsGroup(QByteArrayLiteral("IccCDialect"), {opts.cLanguageDialect}); // Add 'IccCppDialect' item (C++ dialect: embedded/extended). addOptionsGroup(QByteArrayLiteral("IccCppDialect"), {opts.cxxLanguageDialect}); // Add 'IccLanguageConformance' item // (Language conformance: IAR/relaxed/strict). addOptionsGroup(QByteArrayLiteral("IccLanguageConformance"), {opts.languageConformance}); // Add 'IccAllowVLA' item (Allow VLA). addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), {opts.allowVla}); // Add 'IccCppInlineSemantics' item (C++ inline semantics). addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), {opts.useCppInlineSemantics}); // Add 'IccRequirePrototypes' item (Require prototypes). addOptionsGroup(QByteArrayLiteral("IccRequirePrototypes"), {opts.requirePrototypes}); // Add 'IccStaticDestr' item (Destroy static objects). addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), {opts.destroyStaticObjects}); } void Stm8CompilerSettingsGroup::buildLanguageTwoPage( const ProductData &qbsProduct) { const LanguageTwoPageOptions opts(qbsProduct); // Add 'IccCharIs' item (Plain char is: signed/unsigned). addOptionsGroup(QByteArrayLiteral("IccCharIs"), {opts.plainCharacter}); // Add 'IccFloatSemantics' item (Floatic-point // semantics: strict/relaxed conformance). addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), {opts.floatingPointSemantic}); // Add 'IccMultibyteSupport' item (Enable multibyte support). addOptionsGroup(QByteArrayLiteral("IccMultibyteSupport"), {opts.enableMultibyteSupport}); } void Stm8CompilerSettingsGroup::buildOptimizationsPage( const ProductData &qbsProduct) { const OptimizationsPageOptions opts(qbsProduct); // Add 'IccOptStrategy', 'IccOptLevel' and // 'CCOptLevelSlave' items (Level). addOptionsGroup(QByteArrayLiteral("IccOptStrategy"), {opts.optimizationStrategy}); addOptionsGroup(QByteArrayLiteral("IccOptLevel"), {opts.optimizationLevel}); addOptionsGroup(QByteArrayLiteral("IccOptLevelSlave"), {opts.optimizationLevelSlave}); // Add 'IccOptNoSizeConstraints' iten (no size constraints). addOptionsGroup(QByteArrayLiteral("IccOptNoSizeConstraints"), {opts.disableSizeConstraints}); // Add 'IccOptAllowList' item // (Enabled optimizations: 6 check boxes). const QString bitflags = QStringLiteral("%1%2%3%4%5%6") .arg(opts.enableCommonSubexpressionElimination) .arg(opts.enableLoopUnroll) .arg(opts.enableFunctionInlining) .arg(opts.enableCodeMotion) .arg(opts.enableTypeBasedAliasAnalysis) .arg(opts.enableCrossCall); addOptionsGroup(QByteArrayLiteral("IccOptAllowList"), {bitflags}); // Add 'IccNoVregs' item // (Number of virtual registers (12/16). addOptionsGroup(QByteArrayLiteral("IccNoVregs"), {opts.vregsNumber}); } void Stm8CompilerSettingsGroup::buildPreprocessorPage( const QString &baseDirectory, const ProductData &qbsProduct) { const PreprocessorPageOptions opts(baseDirectory, qbsProduct); // Add 'CCDefines' item (Defines symbols). addOptionsGroup(QByteArrayLiteral("CCDefines"), opts.defineSymbols); // Add 'CCIncludePath2' item // (Additional include directories). addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), opts.includePaths); } void Stm8CompilerSettingsGroup::buildDiagnosticsPage( const ProductData &qbsProduct) { const DiagnosticsPageOptions opts(qbsProduct); // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), {opts.warningsAsErrors}); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp0000644000175100017510000000734115232633614030744 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "stm8archiversettingsgroup_v3.h" #include "stm8assemblersettingsgroup_v3.h" #include "stm8buildconfigurationgroup_v3.h" #include "stm8compilersettingsgroup_v3.h" #include "stm8generalsettingsgroup_v3.h" #include "stm8linkersettingsgroup_v3.h" #include "../../iarewtoolchainpropertygroup.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace stm8 { namespace v3 { Stm8BuildConfigurationGroup::Stm8BuildConfigurationGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) : gen::xml::PropertyGroup("configuration") { // Append configuration name item. const QString cfgName = gen::utils::buildConfigurationName(qbsProject); appendProperty("name", cfgName); // Apend toolchain name group item. appendChild("STM8"); // Append debug info item. const int debugBuild = gen::utils::debugInformation(qbsProduct); appendProperty("debug", debugBuild); // Append settings group items. appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); appendChild( qbsProject, qbsProduct, qbsProductDeps); } bool Stm8BuildConfigurationGroupFactory::canCreate( gen::utils::Architecture arch, const Version &version) const { return arch == gen::utils::Architecture::Stm8 && version.majorVersion() == 3; } std::unique_ptr Stm8BuildConfigurationGroupFactory::create( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) const { const auto group = new Stm8BuildConfigurationGroup( qbsProject, qbsProduct, qbsProductDeps); return std::unique_ptr(group); } } // namespace v3 } // namespace stm8 } // namespace iarew } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarew.qbs0000644000175100017510000001102015232633614021660 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "iarewgenerator" files: ["iarewgeneratorplugin.cpp"] Group { name: "IAR EW generator common" files: [ "iarewfileversionproperty.cpp", "iarewfileversionproperty.h", "iarewgenerator.cpp", "iarewgenerator.h", "iarewoptionpropertygroup.cpp", "iarewoptionpropertygroup.h", "iarewproject.cpp", "iarewproject.h", "iarewprojectwriter.cpp", "iarewprojectwriter.h", "iarewsettingspropertygroup.cpp", "iarewsettingspropertygroup.h", "iarewsourcefilepropertygroup.cpp", "iarewsourcefilepropertygroup.h", "iarewsourcefilespropertygroup.cpp", "iarewsourcefilespropertygroup.h", "iarewtoolchainpropertygroup.cpp", "iarewtoolchainpropertygroup.h", "iarewutils.cpp", "iarewutils.h", "iarewversioninfo.h", "iarewworkspace.cpp", "iarewworkspace.h", "iarewworkspacewriter.cpp", "iarewworkspacewriter.h", ] } Group { name: "IAR EW generator for ARM" prefix: "archs/arm/" files: [ "armarchiversettingsgroup_v8.cpp", "armarchiversettingsgroup_v8.h", "armassemblersettingsgroup_v8.cpp", "armassemblersettingsgroup_v8.h", "armbuildconfigurationgroup_v8.cpp", "armbuildconfigurationgroup_v8.h", "armcompilersettingsgroup_v8.cpp", "armcompilersettingsgroup_v8.h", "armgeneralsettingsgroup_v8.cpp", "armgeneralsettingsgroup_v8.h", "armlinkersettingsgroup_v8.cpp", "armlinkersettingsgroup_v8.h", ] } Group { name: "IAR EW generator for AVR" prefix: "archs/avr/" files: [ "avrarchiversettingsgroup_v7.cpp", "avrarchiversettingsgroup_v7.h", "avrassemblersettingsgroup_v7.cpp", "avrassemblersettingsgroup_v7.h", "avrbuildconfigurationgroup_v7.cpp", "avrbuildconfigurationgroup_v7.h", "avrcompilersettingsgroup_v7.cpp", "avrcompilersettingsgroup_v7.h", "avrgeneralsettingsgroup_v7.cpp", "avrgeneralsettingsgroup_v7.h", "avrlinkersettingsgroup_v7.cpp", "avrlinkersettingsgroup_v7.h", ] } Group { name: "IAR EW generator for MCS51" prefix: "archs/mcs51/" files: [ "mcs51archiversettingsgroup_v10.cpp", "mcs51archiversettingsgroup_v10.h", "mcs51assemblersettingsgroup_v10.cpp", "mcs51assemblersettingsgroup_v10.h", "mcs51buildconfigurationgroup_v10.cpp", "mcs51buildconfigurationgroup_v10.h", "mcs51compilersettingsgroup_v10.cpp", "mcs51compilersettingsgroup_v10.h", "mcs51generalsettingsgroup_v10.cpp", "mcs51generalsettingsgroup_v10.h", "mcs51linkersettingsgroup_v10.cpp", "mcs51linkersettingsgroup_v10.h", ] } Group { name: "IAR EW generator for STM8" prefix: "archs/stm8/" files: [ "stm8archiversettingsgroup_v3.cpp", "stm8archiversettingsgroup_v3.h", "stm8assemblersettingsgroup_v3.cpp", "stm8assemblersettingsgroup_v3.h", "stm8buildconfigurationgroup_v3.cpp", "stm8buildconfigurationgroup_v3.h", "stm8compilersettingsgroup_v3.cpp", "stm8compilersettingsgroup_v3.h", "stm8generalsettingsgroup_v3.cpp", "stm8generalsettingsgroup_v3.h", "stm8linkersettingsgroup_v3.cpp", "stm8linkersettingsgroup_v3.h", ] } Group { name: "IAR EW generator for MSP430" prefix: "archs/msp430/" files: [ "msp430archiversettingsgroup_v7.cpp", "msp430archiversettingsgroup_v7.h", "msp430assemblersettingsgroup_v7.cpp", "msp430assemblersettingsgroup_v7.h", "msp430buildconfigurationgroup_v7.cpp", "msp430buildconfigurationgroup_v7.h", "msp430compilersettingsgroup_v7.cpp", "msp430compilersettingsgroup_v7.h", "msp430generalsettingsgroup_v7.cpp", "msp430generalsettingsgroup_v7.h", "msp430linkersettingsgroup_v7.cpp", "msp430linkersettingsgroup_v7.h", ] } } qbs-src-3.3.1/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h0000644000175100017510000000375615232633614026306 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSOURCEFILEPROPERTYGROUP_H #define QBS_IAREWSOURCEFILEPROPERTYGROUP_H #include namespace qbs { class ArtifactData; struct GeneratableProject; class IarewSourceFilePropertyGroup final : public gen::xml::PropertyGroup { public: explicit IarewSourceFilePropertyGroup( const GeneratableProject &genProject, const ArtifactData &sourceArtifact); }; } // namespace qbs #endif // QBS_IAREWSOURCEFILEPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h0000644000175100017510000000376215232633614026466 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWSOURCEFILESPROPERTYGROUP_H #define QBS_IAREWSOURCEFILESPROPERTYGROUP_H #include namespace qbs { class IarewSourceFilesPropertyGroup final : public gen::xml::PropertyGroup { public: explicit IarewSourceFilesPropertyGroup( const GeneratableProject &genProject, const QString &filesGroupName, const QList &sourceFiles); }; } // namespace qbs #endif // QBS_IAREWSOURCEFILESPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewfileversionproperty.h0000644000175100017510000000362415232633614025410 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWFILEVERSIONPROPERTY_H #define QBS_IAREWFILEVERSIONPROPERTY_H #include #include namespace qbs { class IarewFileVersionProperty final : public gen::xml::Property { public: explicit IarewFileVersionProperty( const gen::VersionInfo &versionInfo); }; } // namespace qbs #endif // QBS_IAREWFILEVERSIONPROPERTY_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewgenerator.cpp0000644000175100017510000001312615232633614023575 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewgenerator.h" #include "iarewproject.h" #include "iarewprojectwriter.h" #include "iarewworkspace.h" #include "iarewworkspacewriter.h" #include #include #include #include namespace qbs { static QString targetFilePath(const QString &baseName, const QString &baseBuildDirectory) { return QDir(baseBuildDirectory).absoluteFilePath( baseName + QStringLiteral(".ewp")); } static QString targetFilePath(const GeneratableProductData &product, const QString &baseBuildDirectory) { return targetFilePath(product.name(), baseBuildDirectory); } static void writeProjectFiles(const std::map> &projects, const Internal::Logger &logger) { for (const auto &item : projects) { const QString projectFilePath = item.first; Internal::FileSaver file(projectFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") .arg(projectFilePath)); std::shared_ptr project = item.second; IarewProjectWriter writer(file.device()); if (!(writer.write(project.get()) && file.commit())) throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") .arg(projectFilePath)); logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( QFileInfo(projectFilePath).fileName()); } } static void writeWorkspace(const std::shared_ptr &wokspace, const QString &workspaceFilePath, const Internal::Logger &logger) { Internal::FileSaver file(workspaceFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") .arg(workspaceFilePath)); IarewWorkspaceWriter writer(file.device()); if (!(writer.write(wokspace.get()) && file.commit())) throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") .arg(workspaceFilePath)); logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( QFileInfo(workspaceFilePath).fileName()); } IarewGenerator::IarewGenerator(const gen::VersionInfo &versionInfo) : m_versionInfo(versionInfo) { } QString IarewGenerator::generatorName() const { return QStringLiteral("iarew%1").arg(m_versionInfo.marketingVersion()); } void IarewGenerator::reset() { m_workspace.reset(); m_workspaceFilePath.clear(); m_projects.clear(); } void IarewGenerator::generate() { GeneratableProjectIterator it(project()); it.accept(this); writeProjectFiles(m_projects, logger()); writeWorkspace(m_workspace, m_workspaceFilePath, logger()); reset(); } void IarewGenerator::visitProject(const GeneratableProject &project) { const QDir buildDir = project.baseBuildDirectory(); m_workspaceFilePath = buildDir.absoluteFilePath( project.name() + QStringLiteral(".eww")); m_workspace = std::make_shared(m_workspaceFilePath); } void IarewGenerator::visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) { Q_UNUSED(project) Q_UNUSED(projectData) } void IarewGenerator::visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) { Q_UNUSED(projectData); const QString projectFilePath = targetFilePath( productData, project.baseBuildDirectory().absolutePath()); const auto targetProject = std::make_shared( project, productData, m_versionInfo); m_projects.insert({projectFilePath, targetProject}); m_workspace->addProject(projectFilePath); } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewproject.cpp0000644000175100017510000001352515232633614023260 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewfileversionproperty.h" #include "iarewproject.h" #include "iarewsourcefilespropertygroup.h" #include "iarewutils.h" #include "iarewversioninfo.h" #include "archs/arm/armbuildconfigurationgroup_v8.h" #include "archs/avr/avrbuildconfigurationgroup_v7.h" #include "archs/mcs51/mcs51buildconfigurationgroup_v10.h" #include "archs/stm8/stm8buildconfigurationgroup_v3.h" #include "archs/msp430/msp430buildconfigurationgroup_v7.h" #include #include namespace qbs { IarewProject::IarewProject(const GeneratableProject &genProject, const GeneratableProductData &genProduct, const gen::VersionInfo &versionInfo) { Q_ASSERT(genProject.projects.size() == genProject.commandLines.size()); Q_ASSERT(genProject.projects.size() == genProduct.data.size()); // Create available configuration group factories. m_factories.push_back(std::make_unique< iarew::arm::v8::ArmBuildConfigurationGroupFactory>()); m_factories.push_back(std::make_unique< iarew::avr::v7::AvrBuildConfigurationGroupFactory>()); m_factories.push_back(std::make_unique< iarew::mcs51::v10::Mcs51BuildConfigurationGroupFactory>()); m_factories.push_back(std::make_unique< iarew::stm8::v3::Stm8BuildConfigurationGroupFactory>()); m_factories.push_back(std::make_unique< iarew::msp430::v7::Msp430BuildConfigurationGroupFactory>()); // Construct file version item. appendChild(versionInfo); // Construct all build configurations items. const int configsCount = std::max(genProject.projects.size(), genProduct.data.size()); for (auto configIndex = 0; configIndex < configsCount; ++configIndex) { const qbs::Project qbsProject = genProject.projects .values().at(configIndex); const ProductData qbsProduct = genProduct.data.values().at(configIndex); const QString confName = gen::utils::buildConfigurationName(qbsProject); const std::vector qbsProductDeps = gen::utils::dependenciesOf (qbsProduct, genProject, confName); const auto arch = gen::utils::architecture(qbsProject); if (arch == gen::utils::Architecture::Unknown) throw ErrorInfo(Internal::Tr::tr("Target architecture is not set," " please use the 'profile' option")); // Construct the build configuration item, which are depend from // the architecture and the version. const auto factoryEnd = m_factories.cend(); const auto factoryIt = std::find_if( m_factories.cbegin(), factoryEnd, [arch, versionInfo](const auto &factory) { return factory->canCreate(arch, versionInfo.version()); }); if (factoryIt == factoryEnd) { throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'" " for IAR EW version %2xxx") .arg(gen::utils::architectureName(arch)) .arg(versionInfo.marketingVersion())); } auto configGroup = (*factoryIt)->create( qbsProject, qbsProduct, qbsProductDeps); appendChild(std::move(configGroup)); } // Construct all file groups items. for (auto it = genProduct.data.cbegin(), end = genProduct.data.cend(); it != end; ++it) { const auto groups = it.value().groups(); for (const auto &group : groups) { // Ignore disabled groups (e.g. when its condition property is false). if (!group.isEnabled()) continue; auto sourceArtifacts = group.sourceArtifacts(); // Remove the linker script artifacts. Internal::removeIf(sourceArtifacts, [](const auto &artifact) { const auto tags = artifact.fileTags(); return tags.contains(QLatin1String("linkerscript")); }); if (sourceArtifacts.isEmpty()) continue; appendChild( genProject, group.name(), sourceArtifacts); } } } } // namespace qbs qbs-src-3.3.1/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h0000644000175100017510000000360415232633614026116 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IAREWTOOLCHAINPROPERTYGROUP_H #define QBS_IAREWTOOLCHAINPROPERTYGROUP_H #include namespace qbs { class IarewToolchainPropertyGroup final : public gen::xml::PropertyGroup { public: explicit IarewToolchainPropertyGroup( const QByteArray &toolchainName); }; } // namespace qbs #endif // QBS_IAREWTOOLCHAINPROPERTYGROUP_H qbs-src-3.3.1/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp0000644000175100017510000000752115232633614026333 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "iarewoptionpropertygroup.h" #include "iarewsettingspropertygroup.h" namespace qbs { constexpr int kDataWantNonLocalPropertyValue = 1; IarewSettingsPropertyGroup::IarewSettingsPropertyGroup() : gen::xml::PropertyGroup(QByteArrayLiteral("settings")) { // Append name property item. m_nameProperty = appendChild( QByteArrayLiteral("name"), QVariant{}); // Append archive version property item. m_archiveVersionProperty = appendChild( QByteArrayLiteral("archiveVersion"), QVariant{}); // Append data property group item. m_dataPropertyGroup = appendChild( QByteArrayLiteral("data")); // Append data version property item. m_dataVersionProperty = m_dataPropertyGroup->appendChild< gen::xml::Property>( QByteArrayLiteral("version"), QVariant{}); // Append data want non-local property item. m_dataPropertyGroup->appendChild( QByteArrayLiteral("wantNonLocal"), kDataWantNonLocalPropertyValue); // Append data debug property item. m_dataDebugProperty = m_dataPropertyGroup->appendChild< gen::xml::Property>( QByteArrayLiteral("debug"), QVariant{}); } void IarewSettingsPropertyGroup::setName(const QByteArray &name) { // There is no way to move-construct a QVariant from T, thus name is shallow-copied m_nameProperty->setValue(QVariant(name)); } QByteArray IarewSettingsPropertyGroup::name() const { return m_nameProperty->value().toByteArray(); } void IarewSettingsPropertyGroup::setArchiveVersion( int archiveVersion) { m_archiveVersionProperty->setValue(archiveVersion); } int IarewSettingsPropertyGroup::archiveVersion() const { return m_archiveVersionProperty->value().toInt(); } void IarewSettingsPropertyGroup::setDataVersion(int dataVersion) { m_dataVersionProperty->setValue(dataVersion); } void IarewSettingsPropertyGroup::setDataDebugInfo(int debugInfo) { m_dataDebugProperty->setValue(debugInfo); } void IarewSettingsPropertyGroup::addOptionsGroup( const QByteArray &name, QVariantList states, int version) { m_dataPropertyGroup->appendChild(name, std::move(states), version); } } // namespace qbs qbs-src-3.3.1/src/plugins/scanner/0000755000175100017510000000000015232633614016404 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/scanner/CMakeLists.txt0000644000175100017510000000005315232633614021142 0ustar runnerrunneradd_subdirectory(cpp) add_subdirectory(qt) qbs-src-3.3.1/src/plugins/scanner/scanner.h0000644000175100017510000000470315232633614020212 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H #include #include #include #define SC_LOCAL_INCLUDE_FLAG 0x1 #define SC_GLOBAL_INCLUDE_FLAG 0x2 class ScannerPlugin { public: virtual ~ScannerPlugin() = default; virtual QString name() const = 0; virtual QStringList scan( const QString &filePath, const char *fileTags, const QVariantMap &properties) const = 0; virtual QStringList collectSearchPaths( const QVariantMap &properties, const QStringList &productBuildDirectories) const = 0; }; #endif // SCANNER_H qbs-src-3.3.1/src/plugins/scanner/qt/0000755000175100017510000000000015232633614017030 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/scanner/qt/CMakeLists.txt0000644000175100017510000000013715232633614021571 0ustar runnerrunneradd_qbs_plugin(qbs_qt_scanner DEPENDS qbscore SOURCES ../scanner.h qtscanner.cpp ) qbs-src-3.3.1/src/plugins/scanner/qt/qt.qbs0000644000175100017510000000023015232633614020156 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "qbs_qt_scanner" files: [ "../scanner.h", "qtscanner.cpp" ] } qbs-src-3.3.1/src/plugins/scanner/qt/qtscanner.cpp0000644000175100017510000001366115232633614021541 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #if defined(WIN32) || defined(_WIN32) #define SCANNER_EXPORT __declspec(dllexport) #else #define SCANNER_EXPORT __attribute__((visibility("default"))) #endif #include "../scanner.h" #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #else #include #endif #include #include #include #include struct QrcScannerFile { #ifdef Q_OS_UNIX int fd = 0; size_t mapLength = 0; #else std::unique_ptr file; #endif char *mapData = nullptr; int fileSize = 0; QrcScannerFile() = default; QrcScannerFile(const QrcScannerFile &) = delete; QrcScannerFile &operator=(const QrcScannerFile &) = delete; ~QrcScannerFile() { close(); } bool open(const QString &filePath); void close(); const char *data() const { return mapData; } int size() const { return fileSize; } }; bool QrcScannerFile::open(const QString &filePath) { close(); #ifdef Q_OS_UNIX fd = ::open(qPrintable(filePath), O_RDONLY); if (fd == -1) { fd = 0; return false; } struct stat s {}; if (fstat(fd, &s) != 0) return false; fileSize = static_cast(s.st_size); mapLength = s.st_size; void *map = mmap(nullptr, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == nullptr || map == MAP_FAILED) return false; mapData = static_cast(map); #else file = std::make_unique(filePath); if (!file->open(QFile::ReadOnly)) return false; fileSize = file->size(); uchar *map = file->map(0, fileSize); if (!map) return false; mapData = reinterpret_cast(map); #endif return true; } void QrcScannerFile::close() { #ifdef Q_OS_UNIX if (mapData) { munmap(mapData, mapLength); mapData = nullptr; } if (fd) { ::close(fd); fd = 0; } #else file.reset(); #endif fileSize = 0; } class QrcScannerPlugin : public ScannerPlugin { public: QString name() const override { return QStringLiteral("qt_qrc_scanner"); } QStringList scan(const QString &filePath, const char *fileTags, const QVariantMap &properties) const override; QStringList collectSearchPaths( const QVariantMap &properties, const QStringList &productBuildDirectories) const override; }; QStringList QrcScannerPlugin::scan( const QString &filePath, const char *fileTags, const QVariantMap &properties) const { Q_UNUSED(fileTags); Q_UNUSED(properties); QStringList results; QrcScannerFile context; if (!context.open(filePath)) return results; const QString baseDir = QFileInfo(filePath).path(); QXmlStreamReader xml(QByteArray::fromRawData(context.data(), context.size())); while (!xml.atEnd()) { xml.readNext(); if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QLatin1String("file")) { QString fileRef = xml.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement); if (!fileRef.isEmpty()) { // QRC file references are always relative to the QRC file location const QString resolvedPath = baseDir + QLatin1Char('/') + fileRef; if (QFile::exists(resolvedPath)) fileRef = resolvedPath; results.append(fileRef); } } } return results; } QStringList QrcScannerPlugin::collectSearchPaths( const QVariantMap &properties, const QStringList &productBuildDirectories) const { Q_UNUSED(properties); Q_UNUSED(productBuildDirectories); return {}; } static void QbsQtScannerPluginLoad() { qbs::Internal::ScannerPluginManager::instance()->registerScanner( std::make_unique()); } static void QbsQtScannerPluginUnload() {} QBS_REGISTER_STATIC_PLUGIN( extern "C" SCANNER_EXPORT, qbs_qt_scanner, QbsQtScannerPluginLoad, QbsQtScannerPluginUnload) qbs-src-3.3.1/src/plugins/scanner/cpp/0000755000175100017510000000000015232633614017166 5ustar runnerrunnerqbs-src-3.3.1/src/plugins/scanner/cpp/CMakeLists.txt0000644000175100017510000000030015232633614021717 0ustar runnerrunnerset(SOURCES ../scanner.h cpp_global.h cppscannerplugin.cpp ) add_qbs_plugin(qbs_cpp_scanner DEFINES "CPLUSPLUS_NO_PARSER" DEPENDS qbscore SOURCES ${SOURCES} ) qbs-src-3.3.1/src/plugins/scanner/cpp/cppscannerplugin.cpp0000644000175100017510000001434215232633614023251 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../scanner.h" #include "cpp_global.h" #include #include #include #include #include class CppScannerPlugin : public ScannerPlugin { public: QString name() const override { return QStringLiteral("cpp_include_scanner"); } QStringList scan(const QString &filePath, const char *fileTags, const QVariantMap &properties) const override; QStringList collectSearchPaths( const QVariantMap &properties, const QStringList &productBuildDirectories) const override; private: static QString getCompiledModuleSuffix(const QVariantMap &properties); static QStringList collectCppIncludePaths(const QVariantMap &properties); static bool modulesEnabled(const QVariantMap &properties); }; QStringList CppScannerPlugin::scan( const QString &filePath, const char *fileTags, const QVariantMap &properties) const { qbs::Internal::CppScannerContext context; const bool ok = qbs::Internal::scanCppFile(context, filePath, fileTags, false, true); if (!ok) return {}; const QString baseDir = QFileInfo(filePath).path(); const QString compiledModuleSuffix = getCompiledModuleSuffix(properties); QStringList results; results.reserve(context.includedFiles.size() + context.requiresModules.size()); for (const auto &include : context.includedFiles) { QString includePath = QString::fromUtf8(include.fileName.data(), include.fileName.size()); if (includePath.isEmpty()) continue; // Resolve local includes relative to file directory if (include.flags & SC_LOCAL_INCLUDE_FLAG) { const QString localPath = baseDir + QLatin1Char('/') + includePath; if (QFile::exists(localPath)) includePath = localPath; } results.append(includePath); } for (const auto &module : context.requiresModules) { QString modulePath = QString::fromUtf8(module.data(), module.size()); if (!modulePath.isEmpty()) { // Convert module name to file path modulePath = modulePath.replace(QLatin1Char(':'), QLatin1Char('-')) + compiledModuleSuffix; results.append(modulePath); } } return results; } QStringList CppScannerPlugin::collectSearchPaths( const QVariantMap &properties, const QStringList &productBuildDirectories) const { QStringList result = collectCppIncludePaths(properties); if (modulesEnabled(properties)) { // Add cxx-modules subdirectory for each product build directory for (const QString &buildDir : productBuildDirectories) { result << buildDir + QStringLiteral("/cxx-modules"); } } return result; } QStringList CppScannerPlugin::collectCppIncludePaths(const QVariantMap &properties) { QStringList result; const QVariantMap cpp = properties.value(QStringLiteral("cpp")).toMap(); if (cpp.empty()) return result; result << cpp.value(QStringLiteral("includePaths")).toStringList(); const bool useSystemHeaders = cpp.value(QStringLiteral("treatSystemHeadersAsDependencies")).toBool(); if (useSystemHeaders) { result << cpp.value(QStringLiteral("systemIncludePaths")).toStringList() << cpp.value(QStringLiteral("distributionIncludePaths")).toStringList() << cpp.value(QStringLiteral("compilerIncludePaths")).toStringList(); } result.removeDuplicates(); return result; } bool CppScannerPlugin::modulesEnabled(const QVariantMap &properties) { const QVariantMap cpp = properties.value(QStringLiteral("cpp")).toMap(); if (cpp.empty()) return false; return cpp.value(QStringLiteral("forceUseCxxModules")).toBool(); } QString CppScannerPlugin::getCompiledModuleSuffix(const QVariantMap &properties) { const QVariantMap cpp = properties.value(QStringLiteral("cpp")).toMap(); if (cpp.empty()) return {}; return cpp.value(QStringLiteral("compiledModuleSuffix")).toString(); } static void QbsCppScannerPluginLoad() { qbs::Internal::ScannerPluginManager::instance()->registerScanner( std::make_unique()); } static void QbsCppScannerPluginUnload() {} QBS_REGISTER_STATIC_PLUGIN( extern "C" CPPSCANNER_EXPORT, qbs_cpp_scanner, QbsCppScannerPluginLoad, QbsCppScannerPluginUnload) qbs-src-3.3.1/src/plugins/scanner/cpp/cpp_global.h0000644000175100017510000000411015232633614021435 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CPP_GLOBAL_H #define CPP_GLOBAL_H #if defined(WIN32) || defined(_WIN32) #define CPPSCANNER_EXPORT __declspec(dllexport) #else #define CPPSCANNER_EXPORT __attribute__((visibility("default"))) #endif #endif // CPP_GLOBAL_H qbs-src-3.3.1/src/plugins/scanner/cpp/cpp.qbs0000644000175100017510000000032715232633614020461 0ustar runnerrunnerimport "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { Depends { name: "qbscore" } name: "qbs_cpp_scanner" files: [ "../scanner.h", "cpp_global.h", "cppscannerplugin.cpp" ] } qbs-src-3.3.1/src/plugins/plugins.qbs0000644000175100017510000000063515232633614017147 0ustar runnerrunnerProject { name: "qbs plugins" references: [ "generator/graphviz/graphviz.qbs", "generator/clangcompilationdb/clangcompilationdb.qbs", "generator/makefilegenerator/makefilegenerator.qbs", "generator/visualstudio/visualstudio.qbs", "generator/iarew/iarew.qbs", "generator/keiluv/keiluv.qbs", "scanner/cpp/cpp.qbs", "scanner/qt/qt.qbs" ] } qbs-src-3.3.1/src/CMakeLists.txt0000644000175100017510000000017115232633614016031 0ustar runnerrunneradd_subdirectory(app) add_subdirectory(lib) add_subdirectory(libexec) add_subdirectory(plugins) add_subdirectory(shared) qbs-src-3.3.1/src/shared/0000755000175100017510000000000015232633614014540 5ustar runnerrunnerqbs-src-3.3.1/src/shared/lsp/0000755000175100017510000000000015232633614015336 5ustar runnerrunnerqbs-src-3.3.1/src/shared/lsp/jsonkeys.h0000644000175100017510000002564615232633614017371 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once namespace lsp { constexpr char actionsKey[] = "actions"; constexpr char activeParameterKey[] = "activeParameter"; constexpr char activeParameterSupportKey[] = "activeParameterSupport"; constexpr char activeSignatureKey[] = "activeSignature"; constexpr char addedKey[] = "added"; constexpr char additionalTextEditsKey[] = "additionalTextEdits"; constexpr char alphaKey[] = "alpha"; constexpr char appliedKey[] = "applied"; constexpr char applyEditKey[] = "applyEdit"; constexpr char argumentsKey[] = "arguments"; constexpr char blueKey[] = "blue"; constexpr char callHierarchyKey[] = "callHierarchy"; constexpr char callHierarchyProviderKey[] = "callHierarchyProvider"; constexpr char cancellableKey[] = "cancellable"; constexpr char capabilitiesKey[] = "capabilities"; constexpr char chKey[] = "ch"; constexpr char changeKey[] = "change"; constexpr char changeNotificationsKey[] = "changeNotifications"; constexpr char changesKey[] = "changes"; constexpr char characterKey[] = "character"; constexpr char childrenKey[] = "children"; constexpr char clientInfoKey[] = "clientInfo"; constexpr char codeActionKey[] = "codeAction"; constexpr char codeActionKindKey[] = "codeActionKind"; constexpr char codeActionKindsKey[] = "codeActionKinds"; constexpr char codeActionLiteralSupportKey[] = "codeActionLiteralSupport"; constexpr char codeActionProviderKey[] = "codeActionProvider"; constexpr char codeKey[] = "code"; constexpr char codeLensKey[] = "codeLens"; constexpr char codeLensProviderKey[] = "codeLensProvider"; constexpr char colorInfoKey[] = "colorInfo"; constexpr char colorKey[] = "color"; constexpr char colorProviderKey[] = "colorProvider"; constexpr char commandKey[] = "command"; constexpr char commandsKey[] = "commands"; constexpr char commitCharacterSupportKey[] = "commitCharacterSupport"; constexpr char commitCharactersKey[] = "commitCharacters"; constexpr char completionItemKey[] = "completionItem"; constexpr char completionItemKindKey[] = "completionItemKind"; constexpr char completionKey[] = "completion"; constexpr char completionProviderKey[] = "completionProvider"; constexpr char configurationKey[] = "configuration"; constexpr char containerNameKey[] = "containerName"; constexpr char contentChangesKey[] = "contentChanges"; constexpr char contentFormatKey[] = "contentFormat"; constexpr char contentKey[] = "value"; constexpr char contentsKey[] = "contents"; constexpr char contextKey[] = "context"; constexpr char contextSupportKey[] = "contextSupport"; constexpr char dataKey[] = "data"; constexpr char definitionKey[] = "definition"; constexpr char definitionProviderKey[] = "definitionProvider"; constexpr char deleteCountKey[] = "deleteCount"; constexpr char deltaKey[] = "delta"; constexpr char deprecatedKey[] = "deprecated"; constexpr char detailKey[] = "detail"; constexpr char diagnosticsKey[] = "diagnostics"; constexpr char didChangeConfigurationKey[] = "didChangeConfiguration"; constexpr char didChangeWatchedFilesKey[] = "didChangeWatchedFiles"; constexpr char didSaveKey[] = "didSave"; constexpr char documentChangesKey[] = "documentChanges"; constexpr char documentFormattingProviderKey[] = "documentFormattingProvider"; constexpr char documentHighlightKey[] = "documentHighlight"; constexpr char documentHighlightProviderKey[] = "documentHighlightProvider"; constexpr char documentLinkKey[] = "documentLink"; constexpr char documentLinkProviderKey[] = "documentLinkProvider"; constexpr char documentRangeFormattingProviderKey[] = "documentRangeFormattingProvider"; constexpr char documentSelectorKey[] = "documentSelector"; constexpr char documentSymbolKey[] = "documentSymbol"; constexpr char documentSymbolProviderKey[] = "documentSymbolProvider"; constexpr char documentationFormatKey[] = "documentationFormat"; constexpr char documentationKey[] = "documentation"; constexpr char dynamicRegistrationKey[] = "dynamicRegistration"; constexpr char editKey[] = "edit"; constexpr char editsKey[] = "edits"; constexpr char endKey[] = "end"; constexpr char errorKey[] = "error"; constexpr char eventKey[] = "event"; constexpr char executeCommandKey[] = "executeCommand"; constexpr char executeCommandProviderKey[] = "executeCommandProvider"; constexpr char experimentalKey[] = "experimental"; constexpr char filterTextKey[] = "filterText"; constexpr char firstTriggerCharacterKey[] = "firstTriggerCharacter"; constexpr char formatsKey[] = "formats"; constexpr char formattingKey[] = "formatting"; constexpr char fromKey[] = "from"; constexpr char fromRangesKey[] = "fromRanges"; constexpr char fullKey[] = "full"; constexpr char greenKey[] = "green"; constexpr char hierarchicalDocumentSymbolSupportKey[] = "hierarchicalDocumentSymbolSupport"; constexpr char hoverKey[] = "hover"; constexpr char hoverProviderKey[] = "hoverProvider"; constexpr char idKey[] = "id"; constexpr char ignoreIfExistsKey[] = "ignoreIfExists"; constexpr char ignoreIfNotExistsKey[] = "ignoreIfNotExists"; constexpr char implementationKey[] = "implementation"; constexpr char implementationProviderKey[] = "implementationProvider"; constexpr char includeDeclarationKey[] = "includeDeclaration"; constexpr char includeTextKey[] = "includeText"; constexpr char initializationOptionsKey[] = "initializationOptions"; constexpr char insertFinalNewlineKey[] = "insertFinalNewline"; constexpr char insertSpaceKey[] = "insertSpace"; constexpr char insertTextFormatKey[] = "insertTextFormat"; constexpr char insertTextKey[] = "insertText"; constexpr char isIncompleteKey[] = "isIncomplete"; constexpr char itemKey[] = "item"; constexpr char itemsKey[] = "items"; constexpr char jsonRpcVersionKey[] = "jsonrpc"; constexpr char kindKey[] = "kind"; constexpr char labelKey[] = "label"; constexpr char languageIdKey[] = "languageId"; constexpr char languageKey[] = "language"; constexpr char legendKey[] = "legend"; constexpr char limitKey[] = "limit"; constexpr char lineKey[] = "line"; constexpr char linesKey[] = "lines"; constexpr char locationKey[] = "location"; constexpr char messageKey[] = "message"; constexpr char methodKey[] = "method"; constexpr char moreTriggerCharacterKey[] = "moreTriggerCharacter"; constexpr char multiLineTokenSupportKey[] = "multiLineTokenSupport"; constexpr char nameKey[] = "name"; constexpr char newNameKey[] = "newName"; constexpr char newTextKey[] = "newText"; constexpr char newUriKey[] = "newUri"; constexpr char oldUriKey[] = "oldUri"; constexpr char onTypeFormattingKey[] = "onTypeFormatting"; constexpr char onlyKey[] = "only"; constexpr char openCloseKey[] = "openClose"; constexpr char optionsKey[] = "options"; constexpr char overlappingTokenSupportKey[] = "overlappingTokenSupport"; constexpr char overwriteKey[] = "overwrite"; constexpr char parametersKey[] = "parameters"; constexpr char paramsKey[] = "params"; constexpr char patternKey[] = "pattern"; constexpr char percentageKey[] = "percentage"; constexpr char placeHolderKey[] = "placeHolder"; constexpr char positionKey[] = "position"; constexpr char prepareProviderKey[] = "prepareProvider"; constexpr char prepareSupportKey[] = "prepareSupport"; constexpr char previousResultIdKey[] = "previousResultId"; constexpr char processIdKey[] = "processId"; constexpr char queryKey[] = "query"; constexpr char rangeFormattingKey[] = "rangeFormatting"; constexpr char rangeKey[] = "range"; constexpr char rangeLengthKey[] = "rangeLength"; constexpr char reasonKey[] = "reason"; constexpr char recursiveKey[] = "recursive"; constexpr char redKey[] = "red"; constexpr char referencesKey[] = "references"; constexpr char referencesProviderKey[] = "referencesProvider"; constexpr char refreshSupportKey[] = "refreshSupport"; constexpr char registerOptionsKey[] = "registerOptions"; constexpr char registrationsKey[] = "registrations"; constexpr char removedKey[] = "removed"; constexpr char renameKey[] = "rename"; constexpr char renameProviderKey[] = "renameProvider"; constexpr char requestsKey[] = "requests"; constexpr char resolveProviderKey[] = "resolveProvider"; constexpr char resourceOperationsKey[] = "resourceOperations"; constexpr char resultIdKey[] = "resultId"; constexpr char resultKey[] = "result"; constexpr char retryKey[] = "retry"; constexpr char rootPathKey[] = "rootPath"; constexpr char rootUriKey[] = "rootUri"; constexpr char saveKey[] = "save"; constexpr char schemeKey[] = "scheme"; constexpr char scopeUriKey[] = "scopeUri"; constexpr char sectionKey[] = "section"; constexpr char selectionRangeKey[] = "selectionRange"; constexpr char semanticTokensKey[] = "semanticTokens"; constexpr char semanticTokensProviderKey[] = "semanticTokensProvider"; constexpr char serverInfoKey[] = "serverInfo"; constexpr char settingsKey[] = "settings"; constexpr char severityKey[] = "severity"; constexpr char signatureHelpKey[] = "signatureHelp"; constexpr char signatureHelpProviderKey[] = "signatureHelpProvider"; constexpr char signatureInformationKey[] = "signatureInformation"; constexpr char signaturesKey[] = "signatures"; constexpr char snippetSupportKey[] = "snippetSupport"; constexpr char sortTextKey[] = "sortText"; constexpr char sourceKey[] = "source"; constexpr char startKey[] = "start"; constexpr char supportedKey[] = "supported"; constexpr char symbolKey[] = "symbol"; constexpr char symbolKindKey[] = "symbolKind"; constexpr char syncKindKey[] = "syncKind"; constexpr char synchronizationKey[] = "synchronization"; constexpr char tabSizeKey[] = "tabSize"; constexpr char tagsKey[] = "tags"; constexpr char targetKey[] = "target"; constexpr char textDocumentKey[] = "textDocument"; constexpr char textDocumentSyncKey[] = "textDocumentSync"; constexpr char textEditKey[] = "textEdit"; constexpr char textKey[] = "text"; constexpr char titleKey[] = "title"; constexpr char toKey[] = "to"; constexpr char tokenKey[] = "token"; constexpr char tokenModifiersKey[] = "tokenModifiers"; constexpr char tokenTypesKey[] = "tokenTypes"; constexpr char traceKey[] = "trace"; constexpr char triggerCharacterKey[] = "triggerCharacter"; constexpr char triggerCharactersKey[] = "triggerCharacters"; constexpr char triggerKindKey[] = "triggerKind"; constexpr char trimFinalNewlinesKey[] = "trimFinalNewlines"; constexpr char trimTrailingWhitespaceKey[] = "trimTrailingWhitespace"; constexpr char typeDefinitionKey[] = "typeDefinition"; constexpr char typeDefinitionProviderKey[] = "typeDefinitionProvider"; constexpr char typeKey[] = "type"; constexpr char unregistrationsKey[] = "unregistrations"; constexpr char uriKey[] = "uri"; constexpr char valueKey[] = "value"; constexpr char valueSetKey[] = "valueSet"; constexpr char versionKey[] = "version"; constexpr char willSaveKey[] = "willSave"; constexpr char willSaveWaitUntilKey[] = "willSaveWaitUntil"; constexpr char windowKey[] = "window"; constexpr char workDoneProgressKey[] = "workDoneProgress"; constexpr char workspaceEditKey[] = "workspaceEdit"; constexpr char workspaceFoldersKey[] = "workspaceFolders"; constexpr char workspaceKey[] = "workspace"; constexpr char workspaceSymbolProviderKey[] = "workspaceSymbolProvider"; } // namespace lsp qbs-src-3.3.1/src/shared/lsp/lsptypes.h0000644000175100017510000005677715232633614017420 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonkeys.h" #include "jsonobject.h" #include "lsputils.h" #include "filepath.h" #include "link.h" #include #include #include #include #include namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl { public: DocumentUri() = default; using PathMapper = std::function; Utils::FilePath toFilePath(const PathMapper &mapToHostPath) const; static DocumentUri fromProtocol(const QString &uri); static DocumentUri fromFilePath(const Utils::FilePath &file, const PathMapper &mapToServerPath); operator QJsonValue() const { return QJsonValue(toString()); } private: DocumentUri(const QString &other); DocumentUri(const Utils::FilePath &other, const PathMapper &mapToServerPath); friend class LanguageClientValue; }; class LANGUAGESERVERPROTOCOL_EXPORT Position : public JsonObject { public: Position() = default; Position(int line, int character); using JsonObject::JsonObject; // Line position in a document (zero-based). int line() const { return typedValue(lineKey); } void setLine(int line) { insert(lineKey, line); } /* * Character offset on a line in a document (zero-based). Assuming that the line is * represented as a string, the `character` value represents the gap between the * `character` and `character + 1`. * * If the character value is greater than the line length it defaults back to the * line length. */ int character() const { return typedValue(characterKey); } void setCharacter(int character) { insert(characterKey, character); } bool isValid() const override { return contains(lineKey) && contains(characterKey); } }; inline bool operator<(const Position &first, const Position &second) { return first.line() < second.line() || (first.line() == second.line() && first.character() < second.character()); } inline bool operator>(const Position &first, const Position &second) { return second < first; } inline bool operator>=(const Position &first, const Position &second) { return !(first < second); } inline bool operator<=(const Position &first, const Position &second) { return !(first > second); } class LANGUAGESERVERPROTOCOL_EXPORT Range : public JsonObject { public: Range() = default; Range(const Position &start, const Position &end); using JsonObject::JsonObject; // The range's start position. Position start() const { return typedValue(startKey); } void setStart(const Position &start) { insert(startKey, start); } // The range's end position. Position end() const { return typedValue(endKey); } void setEnd(const Position &end) { insert(endKey, end); } bool isEmpty() const { return start() == end(); } bool contains(const Position &pos) const { return start() <= pos && pos <= end(); } bool contains(const Range &other) const; bool overlaps(const Range &range) const; bool isLeftOf(const Range &other) const { return isEmpty() || other.isEmpty() ? end() < other.start() : end() <= other.start(); } bool isValid() const override { return JsonObject::contains(startKey) && JsonObject::contains(endKey); } }; inline bool operator==(const Range &r1, const Range &r2) { return r1.contains(r2) && r2.contains(r1); } inline bool operator!=(const Range &r1, const Range &r2) { return !(r1 == r2); } class LANGUAGESERVERPROTOCOL_EXPORT Location : public JsonObject { public: using JsonObject::JsonObject; DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } Utils::Link toLink(const DocumentUri::PathMapper &mapToHostPath) const; bool isValid() const override { return contains(uriKey) && contains(rangeKey); } }; enum class DiagnosticSeverity { Error = 1, Warning = 2, Information = 3, Hint = 4 }; class LANGUAGESERVERPROTOCOL_EXPORT Diagnostic : public JsonObject { public: using JsonObject::JsonObject; // The range at which the message applies. Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } // The diagnostic's severity. Can be omitted. If omitted it is up to the // client to interpret diagnostics as error, warning, info or hint. std::optional severity() const; void setSeverity(const DiagnosticSeverity &severity) { insert(severityKey, static_cast(severity)); } void clearSeverity() { remove(severityKey); } // The diagnostic's code, which might appear in the user interface. using Code = std::variant; std::optional code() const; void setCode(const Code &code); void clearCode() { remove(codeKey); } // A human-readable string describing the source of this // diagnostic, e.g. 'typescript' or 'super lint'. std::optional source() const { return optionalValue(sourceKey); } void setSource(const QString &source) { insert(sourceKey, source); } void clearSource() { remove(sourceKey); } // The diagnostic's message. QString message() const { return typedValue(messageKey); } void setMessage(const QString &message) { insert(messageKey, message); } bool isValid() const override { return contains(rangeKey) && contains(messageKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT Command : public JsonObject { public: using JsonObject::JsonObject; // Title of the command, like `save`. QString title() const { return typedValue(titleKey); } void setTitle(const QString &title) { insert(titleKey, title); } void clearTitle() { remove(titleKey); } // The identifier of the actual command handler. QString command() const { return typedValue(commandKey); } void setCommand(const QString &command) { insert(commandKey, command); } void clearCommand() { remove(commandKey); } // Arguments that the command handler should be invoked with. std::optional arguments() const { return typedValue(argumentsKey); } void setArguments(const QJsonArray &arguments) { insert(argumentsKey, arguments); } void clearArguments() { remove(argumentsKey); } bool isValid() const override { return contains(titleKey) && contains(commandKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextEdit : public JsonObject { public: using JsonObject::JsonObject; // The range of the text document to be manipulated. To insert // text into a document create a range where start === end. Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } // The string to be inserted. For delete operations use an empty string. QString newText() const { return typedValue(newTextKey); } void setNewText(const QString &text) { insert(newTextKey, text); } bool isValid() const override { return contains(rangeKey) && contains(newTextKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentIdentifier : public JsonObject { public: TextDocumentIdentifier() : TextDocumentIdentifier(DocumentUri()) {} explicit TextDocumentIdentifier(const DocumentUri &uri) { setUri(uri); } using JsonObject::JsonObject; // The text document's URI. DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } bool isValid() const override { return contains(uriKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT VersionedTextDocumentIdentifier : public TextDocumentIdentifier { public: using TextDocumentIdentifier::TextDocumentIdentifier; /* * The version number of this document. If a versioned text document identifier * is sent from the server to the client and the file is not open in the editor * (the server has not received an open notification before) the server can send * `null` to indicate that the version is known and the content on disk is the * truth (as speced with document content ownership) */ LanguageClientValue version() const { return clientValue(versionKey); } void setVersion(LanguageClientValue version) { insert(versionKey, version); } bool isValid() const override { return TextDocumentIdentifier::isValid() && contains(versionKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentEdit : public JsonObject { public: using JsonObject::JsonObject; // The text document to change. VersionedTextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const VersionedTextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } // The edits to be applied. QList edits() const { return array(editsKey); } void setEdits(const QList edits) { insertArray(editsKey, edits); } bool isValid() const override { return contains(textDocumentKey) && contains(editsKey); } }; class CreateFileOptions : public JsonObject { public: using JsonObject::JsonObject; std::optional overwrite() const { return optionalValue(overwriteKey); } void setOverwrite(bool overwrite) { insert(overwriteKey, overwrite); } void clearOverwrite() { remove(overwriteKey); } std::optional ignoreIfExists() const { return optionalValue(ignoreIfExistsKey); } void setIgnoreIfExists(bool ignoreIfExists) { insert(ignoreIfExistsKey, ignoreIfExists); } void clearIgnoreIfExists() { remove(ignoreIfExistsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CreateFileOperation : public JsonObject { public: using JsonObject::JsonObject; CreateFileOperation(); DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } std::optional options() const { return optionalValue(optionsKey); } void setOptions(const CreateFileOptions &options) { insert(optionsKey, options); } void clearOptions() { remove(optionsKey); } QString message(const DocumentUri::PathMapper &mapToHostPath) const; bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT RenameFileOperation : public JsonObject { public: using JsonObject::JsonObject; RenameFileOperation(); DocumentUri oldUri() const { return DocumentUri::fromProtocol(typedValue(oldUriKey)); } void setOldUri(const DocumentUri &oldUri) { insert(oldUriKey, oldUri); } DocumentUri newUri() const { return DocumentUri::fromProtocol(typedValue(newUriKey)); } void setNewUri(const DocumentUri &newUri) { insert(newUriKey, newUri); } std::optional options() const { return optionalValue(optionsKey); } void setOptions(const CreateFileOptions &options) { insert(optionsKey, options); } void clearOptions() { remove(optionsKey); } QString message(const DocumentUri::PathMapper &mapToHostPath) const; bool isValid() const override; }; class DeleteFileOptions : public JsonObject { public: using JsonObject::JsonObject; std::optional recursive() const { return optionalValue(recursiveKey); } void setRecursive(bool recursive) { insert(recursiveKey, recursive); } void clearRecursive() { remove(recursiveKey); } std::optional ignoreIfNotExists() const { return optionalValue(ignoreIfNotExistsKey); } void setIgnoreIfNotExists(bool ignoreIfNotExists) { insert(ignoreIfNotExistsKey, ignoreIfNotExists); } void clearIgnoreIfNotExists() { remove(ignoreIfNotExistsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DeleteFileOperation : public JsonObject { public: using JsonObject::JsonObject; DeleteFileOperation(); DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } std::optional options() const { return optionalValue(optionsKey); } void setOptions(const DeleteFileOptions &options) { insert(optionsKey, options); } void clearOptions() { remove(optionsKey); } QString message(const DocumentUri::PathMapper &mapToHostPath) const; bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentChange : public std::variant { public: using variant::variant; DocumentChange(const QJsonValue &value); bool isValid() const; operator const QJsonValue() const; }; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceEdit : public JsonObject { public: using JsonObject::JsonObject; // Holds changes to existing resources. using Changes = QMap>; std::optional changes() const; void setChanges(const Changes &changes); /* * Depending on the client capability * `workspace.workspaceEdit.resourceOperations` document changes are either * an array of `TextDocumentEdit`s to express changes to n different text * documents where each text document edit addresses a specific version of * a text document. Or it can contain above `TextDocumentEdit`s mixed with * create, rename and delete file / folder operations. * * Whether a client supports versioned document edits is expressed via * `workspace.workspaceEdit.documentChanges` client capability. * * If a client neither supports `documentChanges` nor * `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s * using the `changes` property are supported. */ std::optional> documentChanges() const { return optionalArray(documentChangesKey); } void setDocumentChanges(const QList &changes) { insertArray(documentChangesKey, changes); } }; LANGUAGESERVERPROTOCOL_EXPORT QMap languageIds(); class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentItem : public JsonObject { public: using JsonObject::JsonObject; // The text document's URI. DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } // The text document's language identifier. QString languageId() const { return typedValue(languageIdKey); } void setLanguageId(const QString &id) { insert(languageIdKey, id); } // The version number of this document (it will increase after each change, including undo/redo int version() const { return typedValue(versionKey); } void setVersion(int version) { insert(versionKey, version); } // The content of the opened text document. QString text() const { return typedValue(textKey); } void setText(const QString &text) { insert(textKey, text); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentPositionParams : public JsonObject { public: TextDocumentPositionParams(); TextDocumentPositionParams(const TextDocumentIdentifier &document, const Position &position); using JsonObject::JsonObject; // The text document. TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &id) { insert(textDocumentKey, id); } // The position inside the text document. Position position() const { return typedValue(positionKey); } void setPosition(const Position &position) { insert(positionKey, position); } bool isValid() const override { return contains(textDocumentKey) && contains(positionKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentFilter : public JsonObject { public: using JsonObject::JsonObject; // A language id, like `typescript`. std::optional language() const { return optionalValue(languageKey); } void setLanguage(const QString &language) { insert(languageKey, language); } void clearLanguage() { remove(languageKey); } // A Uri [scheme](#Uri.scheme), like `file` or `untitled`. std::optional scheme() const { return optionalValue(schemeKey); } void setScheme(const QString &scheme) { insert(schemeKey, scheme); } void clearScheme() { remove(schemeKey); } /** * A glob pattern, like `*.{ts,js}`. * * Glob patterns can have the following syntax: * - `*` to match one or more characters in a path segment * - `?` to match on one character in a path segment * - `**` to match any number of path segments, including none * - `{}` to group sub patterns into an OR expression. (e.g. `*.{ts,js}` * matches all TypeScript and JavaScript files) * - `[]` to declare a range of characters to match in a path segment * (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) * - `[!...]` to negate a range of characters to match in a path segment * (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but * not `example.0`) */ std::optional pattern() const { return optionalValue(patternKey); } void setPattern(const QString &pattern) { insert(patternKey, pattern); } void clearPattern() { remove(patternKey); } bool applies(const Utils::FilePath &fileName) const; }; class LANGUAGESERVERPROTOCOL_EXPORT MarkupKind { public: enum Value { plaintext, markdown }; MarkupKind() = default; MarkupKind(const Value value) : m_value(value) {} explicit MarkupKind(const QJsonValue &value); operator QJsonValue() const; Value value() const { return m_value; } bool operator==(const Value &value) const { return m_value == value; } bool isValid() const { return true; } private: Value m_value = plaintext; }; class LANGUAGESERVERPROTOCOL_EXPORT MarkupContent : public JsonObject { public: using JsonObject::JsonObject; // The type of the Markup MarkupKind kind() const { return MarkupKind(value(kindKey)); } void setKind(MarkupKind kind) { insert(kindKey, kind); } Qt::TextFormat textFormat() const { return kind() == MarkupKind::markdown ? Qt::MarkdownText : Qt::PlainText; } // The content itself QString content() const { return typedValue(contentKey); } void setContent(const QString &content) { insert(contentKey, content); } bool isValid() const override { return contains(kindKey) && contains(contentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT MarkupOrString : public std::variant { public: MarkupOrString() = default; explicit MarkupOrString(const std::variant &val); explicit MarkupOrString(const QString &val); explicit MarkupOrString(const MarkupContent &val); MarkupOrString(const QJsonValue &val); bool isValid() const { return true; } QJsonValue toJson() const; }; class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolder : public JsonObject { public: WorkSpaceFolder() = default; WorkSpaceFolder(const DocumentUri &uri, const QString &name); using JsonObject::JsonObject; // The associated URI for this workspace folder. DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } // The name of the workspace folder. Defaults to the uri's basename. QString name() const { return typedValue(nameKey); } void setName(const QString &name) { insert(nameKey, name); } bool isValid() const override { return contains(uriKey) && contains(nameKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SymbolInformation : public JsonObject { public: using JsonObject::JsonObject; QString name() const { return typedValue(nameKey); } void setName(const QString &name) { insert(nameKey, name); } int kind() const { return typedValue(kindKey); } void setKind(int kind) { insert(kindKey, kind); } std::optional deprecated() const { return optionalValue(deprecatedKey); } void setDeprecated(bool deprecated) { insert(deprecatedKey, deprecated); } void clearDeprecated() { remove(deprecatedKey); } Location location() const { return typedValue(locationKey); } void setLocation(const Location &location) { insert(locationKey, location); } std::optional containerName() const { return optionalValue(containerNameKey); } void setContainerName(const QString &containerName) { insert(containerNameKey, containerName); } void clearContainerName() { remove(containerNameKey); } bool isValid() const override { return contains(nameKey) && contains(kindKey) && contains(locationKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbol : public JsonObject { public: using JsonObject::JsonObject; QString name() const { return typedValue(nameKey); } void setName(const QString &name) { insert(nameKey, name); } std::optional detail() const { return optionalValue(detailKey); } void setDetail(const QString &detail) { insert(detailKey, detail); } void clearDetail() { remove(detailKey); } int kind() const { return typedValue(kindKey); } void setKind(int kind) { insert(kindKey, kind); } std::optional deprecated() const { return optionalValue(deprecatedKey); } void setDeprecated(bool deprecated) { insert(deprecatedKey, deprecated); } void clearDeprecated() { remove(deprecatedKey); } Range range() const { return typedValue(rangeKey); } void setRange(Range range) { insert(rangeKey, range); } Range selectionRange() const { return typedValue(selectionRangeKey); } void setSelectionRange(Range selectionRange) { insert(selectionRangeKey, selectionRange); } std::optional> children() const { return optionalArray(childrenKey); } void setChildren(QList children) { insertArray(childrenKey, children); } void clearChildren() { remove(childrenKey); } }; enum class SymbolKind { File = 1, FirstSymbolKind = File, Module = 2, Namespace = 3, Package = 4, Class = 5, Method = 6, Property = 7, Field = 8, Constructor = 9, Enum = 10, Interface = 11, Function = 12, Variable = 13, Constant = 14, String = 15, Number = 16, Boolean = 17, Array = 18, Object = 19, Key = 20, Null = 21, EnumMember = 22, Struct = 23, Event = 24, Operator = 25, TypeParameter = 26, LastSymbolKind = TypeParameter, }; namespace CompletionItemKind { enum Kind { Text = 1, Method = 2, Function = 3, Constructor = 4, Field = 5, Variable = 6, Class = 7, Interface = 8, Module = 9, Property = 10, Unit = 11, Value = 12, Enum = 13, Keyword = 14, Snippet = 15, Color = 16, File = 17, Reference = 18, Folder = 19, EnumMember = 20, Constant = 21, Struct = 22, Event = 23, Operator = 24, TypeParameter = 25 }; } // namespace CompletionItemKind } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/jsonrpcmessages.cpp0000644000175100017510000000556315232633614021261 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "jsonrpcmessages.h" #include "initializemessages.h" #include "languageserverprotocoltr.h" #include "lsputils.h" #include #include #include #include namespace lsp { Q_LOGGING_CATEGORY(timingLog, "qtc.languageserverprotocol.timing", QtWarningMsg) constexpr const char CancelRequest::methodName[]; QByteArray JsonRpcMessage::toRawData() const { return QJsonDocument(m_jsonObject).toJson(QJsonDocument::Compact); } bool JsonRpcMessage::isValid(QString *errorMessage) const { if (!m_parseError.isEmpty()) { if (errorMessage) *errorMessage = m_parseError; return false; } return m_jsonObject[jsonRpcVersionKey] == "2.0"; } const QJsonObject &JsonRpcMessage::toJsonObject() const { return m_jsonObject; } JsonRpcMessage::JsonRpcMessage() { // The language server protocol always uses “2.0†as the jsonrpc version m_jsonObject[jsonRpcVersionKey] = "2.0"; } constexpr int utf8mib = 106; static QString docType(const QJsonDocument &doc) { if (doc.isArray()) return QString("array"); if (doc.isEmpty()) return QString("empty"); if (doc.isNull()) return QString("null"); if (doc.isObject()) return QString("object"); return {}; } JsonRpcMessage::JsonRpcMessage(const BaseMessage &message) { if (message.content.isEmpty()) return; QByteArray content; if (message.codec && message.codec->mibEnum() != utf8mib) { QTextCodec *utf8 = QTextCodec::codecForMib(utf8mib); if (utf8) content = utf8->fromUnicode(message.codec->toUnicode(message.content)); } if (content.isEmpty()) content = message.content; QJsonParseError error = {0, QJsonParseError::NoError}; const QJsonDocument doc = QJsonDocument::fromJson(content, &error); if (doc.isObject()) m_jsonObject = doc.object(); else if (doc.isNull()) m_parseError = Tr::tr("Could not parse JSON message: \"%1\".").arg(error.errorString()); else m_parseError = Tr::tr("Expected a JSON object, but got a JSON \"%1\" value.").arg(docType(doc)); } JsonRpcMessage::JsonRpcMessage(const QJsonObject &jsonObject) : m_jsonObject(jsonObject) { } JsonRpcMessage::JsonRpcMessage(QJsonObject &&jsonObject) : m_jsonObject(std::move(jsonObject)) { } QByteArray JsonRpcMessage::jsonRpcMimeType() { return "application/vscode-jsonrpc"; } CancelRequest::CancelRequest(const CancelParameter ¶ms) : Notification(methodName, params) { } void logElapsedTime(const QString &method, const QElapsedTimer &t) { qCDebug(timingLog) << "received server reply to" << method << "after" << t.elapsed() << "ms"; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/jsonrpcmessages.h0000644000175100017510000003145215232633614020722 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "basemessage.h" #include "jsonkeys.h" #include "lsptypes.h" #include #include #include #include #include #include #include #include #include namespace lsp { class JsonRpcMessage; class LANGUAGESERVERPROTOCOL_EXPORT MessageId : public std::variant { public: MessageId() : variant(QString()) {} explicit MessageId(int id) : variant(id) {} explicit MessageId(const QString &id) : variant(id) {} explicit MessageId(const QJsonValue &value) { if (value.isDouble()) emplace(value.toInt()); else emplace(value.toString()); } operator QJsonValue() const { if (auto id = std::get_if(this)) return *id; if (auto id = std::get_if(this)) return *id; return QJsonValue(); } bool isValid() const { if (std::holds_alternative(*this)) return true; const QString *id = std::get_if(this); QBS_ASSERT(id, return false); return !id->isEmpty(); } QString toString() const { if (auto id = std::get_if(this)) return *id; if (auto id = std::get_if(this)) return QString::number(*id); return {}; } private: friend size_t qHash(const MessageId &id) { if (std::holds_alternative(id)) return QT_PREPEND_NAMESPACE(qHash(std::get(id))); if (std::holds_alternative(id)) return QT_PREPEND_NAMESPACE(qHash(std::get(id))); return QT_PREPEND_NAMESPACE(qHash(0)); } friend QDebug operator<<(QDebug stream, const MessageId &id) { if (std::holds_alternative(id)) stream << std::get(id); else stream << std::get(id); return stream; } }; struct ResponseHandler { MessageId id; using Callback = std::function; Callback callback; }; class LANGUAGESERVERPROTOCOL_EXPORT JsonRpcMessage { public: JsonRpcMessage(); explicit JsonRpcMessage(const BaseMessage &message); explicit JsonRpcMessage(const QJsonObject &jsonObject); explicit JsonRpcMessage(QJsonObject &&jsonObject); virtual ~JsonRpcMessage() = default; static QByteArray jsonRpcMimeType(); QByteArray toRawData() const; virtual bool isValid(QString *errorMessage) const; const QJsonObject &toJsonObject() const; const QString parseError() { return m_parseError; } virtual std::optional responseHandler() const { return std::nullopt; } BaseMessage toBaseMessage() const { return BaseMessage(jsonRpcMimeType(), toRawData()); } protected: QJsonObject m_jsonObject; private: QString m_parseError; }; template class Notification : public JsonRpcMessage { public: Notification(const QString &methodName, const Params ¶ms) { setMethod(methodName); setParams(params); } explicit Notification(const QJsonObject &jsonObject) : JsonRpcMessage(jsonObject) {} explicit Notification(QJsonObject &&jsonObject) : JsonRpcMessage(std::move(jsonObject)) {} QString method() const { return fromJsonValue(m_jsonObject.value(methodKey)); } void setMethod(const QString &method) { m_jsonObject.insert(methodKey, method); } using Parameters = Params; std::optional params() const { const QJsonValue ¶ms = m_jsonObject.value(paramsKey); return params.isUndefined() ? std::nullopt : std::make_optional(Params(params)); } void setParams(const Params ¶ms) { m_jsonObject.insert(paramsKey, QJsonValue(params)); } void clearParams() { m_jsonObject.remove(paramsKey); } bool isValid(QString *errorMessage) const override { return JsonRpcMessage::isValid(errorMessage) && m_jsonObject.value(methodKey).isString() && parametersAreValid(errorMessage); } virtual bool parametersAreValid(QString *errorMessage) const { if (auto parameter = params()) return parameter->isValid(); if (errorMessage) *errorMessage = QCoreApplication::translate("QtC::LanguageServerProtocol", "No parameters in \"%1\".").arg(method()); return false; } }; template <> class Notification : public JsonRpcMessage { public: Notification() : Notification(QString()) {} explicit Notification(const QString &methodName, const std::nullptr_t &/*params*/ = nullptr) { setMethod(methodName); setParams(nullptr); } using JsonRpcMessage::JsonRpcMessage; QString method() const { return fromJsonValue(m_jsonObject.value(methodKey)); } void setMethod(const QString &method) { m_jsonObject.insert(methodKey, method); } std::optional params() const { return nullptr; } void setParams(const std::nullptr_t &/*params*/) { m_jsonObject.insert(paramsKey, QJsonValue::Null); } void clearParams() { m_jsonObject.remove(paramsKey); } bool isValid(QString *errorMessage) const override { return JsonRpcMessage::isValid(errorMessage) && m_jsonObject.value(methodKey).isString() && parametersAreValid(errorMessage); } virtual bool parametersAreValid(QString * /*errorMessage*/) const { return true; } }; template class ResponseError : public JsonObject { public: using JsonObject::JsonObject; int code() const { return typedValue(codeKey); } void setCode(int code) { insert(codeKey, code); } QString message() const { return typedValue(messageKey); } void setMessage(const QString &message) { insert(messageKey, message); } std::optional data() const { return optionalValue(dataKey); } void setData(const Error &data) { insert(dataKey, data); } void clearData() { remove(dataKey); } bool isValid() const override { return contains(codeKey) && contains(messageKey); } QString toString() const { return errorCodesToString(code()) + ": " + message(); } // predefined error codes enum ErrorCodes { // Defined by JSON RPC ParseError = -32700, InvalidRequest = -32600, MethodNotFound = -32601, InvalidParams = -32602, InternalError = -32603, serverErrorStart = -32099, serverErrorEnd = -32000, ServerNotInitialized = -32002, UnknownErrorCode = -32001, // Defined by the protocol. RequestCancelled = -32800 }; #define CASE_ERRORCODES(x) case ErrorCodes::x: return QLatin1String(#x) static QString errorCodesToString(int code) { switch (code) { CASE_ERRORCODES(ParseError); CASE_ERRORCODES(InvalidRequest); CASE_ERRORCODES(MethodNotFound); CASE_ERRORCODES(InvalidParams); CASE_ERRORCODES(InternalError); CASE_ERRORCODES(serverErrorStart); CASE_ERRORCODES(serverErrorEnd); CASE_ERRORCODES(ServerNotInitialized); CASE_ERRORCODES(RequestCancelled); default: return QCoreApplication::translate("QtC::LanguageClient", "Error %1").arg(code); } } #undef CASE_ERRORCODES }; template class Response : public JsonRpcMessage { public: explicit Response(const MessageId &id) { setId(id); } using JsonRpcMessage::JsonRpcMessage; MessageId id() const { return MessageId(m_jsonObject.value(idKey)); } void setId(MessageId id) { this->m_jsonObject.insert(idKey, id); } std::optional result() const { const QJsonValue &result = m_jsonObject.value(resultKey); if (result.isUndefined()) return std::nullopt; return std::make_optional(Result(result)); } void setResult(const Result &result) { m_jsonObject.insert(resultKey, QJsonValue(result)); } void clearResult() { m_jsonObject.remove(resultKey); } using Error = ResponseError; std::optional error() const { const QJsonValue &val = m_jsonObject.value(errorKey); return val.isUndefined() ? std::nullopt : std::make_optional(fromJsonValue(val)); } void setError(const Error &error) { m_jsonObject.insert(errorKey, QJsonValue(error)); } void clearError() { m_jsonObject.remove(errorKey); } bool isValid(QString *errorMessage) const override { return JsonRpcMessage::isValid(errorMessage) && id().isValid(); } }; template class Response : public JsonRpcMessage { public: explicit Response(const MessageId &id) { setId(id); } using JsonRpcMessage::JsonRpcMessage; MessageId id() const { return MessageId(m_jsonObject.value(idKey)); } void setId(MessageId id) { this->m_jsonObject.insert(idKey, id); } std::optional result() const { return m_jsonObject.value(resultKey).isNull() ? std::make_optional(nullptr) : std::nullopt; } void setResult(const std::nullptr_t &) { m_jsonObject.insert(resultKey, QJsonValue::Null); } void clearResult() { m_jsonObject.remove(resultKey); } using Error = ResponseError; std::optional error() const { const QJsonValue &val = m_jsonObject.value(errorKey); return val.isUndefined() ? std::nullopt : std::make_optional(fromJsonValue(val)); } void setError(const Error &error) { m_jsonObject.insert(errorKey, QJsonValue(error)); } void clearError() { m_jsonObject.remove(errorKey); } bool isValid(QString *errorMessage) const override { return JsonRpcMessage::isValid(errorMessage) && id().isValid(); } }; void LANGUAGESERVERPROTOCOL_EXPORT logElapsedTime(const QString &method, const QElapsedTimer &t); template class Request : public Notification { public: Request(const QString &methodName, const Params ¶ms) : Notification(methodName, params) { setId(MessageId(QUuid::createUuid().toString())); } explicit Request(const QJsonObject &jsonObject) : Notification(jsonObject) { } explicit Request(QJsonObject &&jsonObject) : Notification(std::move(jsonObject)) { } MessageId id() const { return MessageId(JsonRpcMessage::m_jsonObject.value(idKey)); } void setId(const MessageId &id) { JsonRpcMessage::m_jsonObject.insert(idKey, id); } using Response = lsp::Response; using ResponseCallback = std::function; void setResponseCallback(const ResponseCallback &callback) { m_callBack = callback; } std::optional responseHandler() const final { QElapsedTimer timer; timer.start(); auto callback = [callback = m_callBack, method = this->method(), t = std::move(timer)] (const JsonRpcMessage &message) { if (!callback) return; logElapsedTime(method, t); callback(Response(message.toJsonObject())); }; return std::make_optional(ResponseHandler{id(), callback}); } bool isValid(QString *errorMessage) const override { if (!Notification::isValid(errorMessage)) return false; if (id().isValid()) return true; if (errorMessage) *errorMessage = QCoreApplication::translate("QtC::LanguageServerProtocol", "No ID set in \"%1\".").arg(this->method()); return false; } private: ResponseCallback m_callBack; }; class LANGUAGESERVERPROTOCOL_EXPORT CancelParameter : public JsonObject { public: explicit CancelParameter(const MessageId &id) { setId(id); } CancelParameter() = default; using JsonObject::JsonObject; MessageId id() const { return typedValue(idKey); } void setId(const MessageId &id) { insert(idKey, id); } bool isValid() const override { return contains(idKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CancelRequest : public Notification { public: explicit CancelRequest(const CancelParameter ¶ms); using Notification::Notification; constexpr static const char methodName[] = "$/cancelRequest"; }; } // namespace lsp template inline QDebug operator<<(QDebug stream, const lsp::ResponseError &error) { stream.nospace() << error.toString(); return stream; } Q_DECLARE_METATYPE(lsp::JsonRpcMessage) qbs-src-3.3.1/src/shared/lsp/basemessage.cpp0000644000175100017510000001467215232633614020333 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "basemessage.h" #include "jsonrpcmessages.h" #include "languageserverprotocoltr.h" #include #include #include #include namespace lsp { Q_LOGGING_CATEGORY(parseLog, "qtc.languageserverprotocol.parse", QtWarningMsg) constexpr char headerFieldSeparator[] = ": "; constexpr char contentCharsetName[] = "charset"; constexpr char defaultCharset[] = "utf-8"; constexpr char contentLengthFieldName[] = "Content-Length"; constexpr char headerSeparator[] = "\r\n"; constexpr char contentTypeFieldName[] = "Content-Type"; BaseMessage::BaseMessage() : mimeType(JsonRpcMessage::jsonRpcMimeType()) { } BaseMessage::BaseMessage(const QByteArray &mimeType, const QByteArray &content, int expectedLength, QTextCodec *codec) : mimeType(mimeType.isEmpty() ? JsonRpcMessage::jsonRpcMimeType() : mimeType) , content(content) , contentLength(expectedLength) , codec(codec) { } BaseMessage::BaseMessage(const QByteArray &mimeType, const QByteArray &content) : BaseMessage(mimeType, content, content.length(), defaultCodec()) { } bool BaseMessage::operator==(const BaseMessage &other) const { if (mimeType != other.mimeType || content != other.content) return false; if (codec) { if (other.codec) return codec->mibEnum() == other.codec->mibEnum(); return codec->mibEnum() == defaultCodec()->mibEnum(); } if (other.codec) return other.codec->mibEnum() == defaultCodec()->mibEnum(); return true; } static QPair splitHeaderFieldLine(const QByteArray &headerFieldLine) { static const int fieldSeparatorLength = int(std::strlen(headerFieldSeparator)); int assignmentIndex = headerFieldLine.indexOf(headerFieldSeparator); if (assignmentIndex >= 0) { return {headerFieldLine.mid(0, assignmentIndex), headerFieldLine.mid(assignmentIndex + fieldSeparatorLength)}; } qCWarning(parseLog) << "Unexpected header line:" << QLatin1String(headerFieldLine); return {}; } static void parseContentType(BaseMessage &message, QByteArray contentType, QString &parseError) { if (contentType.startsWith('"') && contentType.endsWith('"')) contentType = contentType.mid(1, contentType.length() - 2); QList contentTypeElements = contentType.split(';'); QByteArray mimeTypeName = contentTypeElements.takeFirst(); QTextCodec *codec = nullptr; for (const QByteArray &_contentTypeElement : contentTypeElements) { const QByteArray &contentTypeElement = _contentTypeElement.trimmed(); if (contentTypeElement.startsWith(contentCharsetName)) { const int equalindex = contentTypeElement.indexOf('='); const QByteArray charset = contentTypeElement.mid(equalindex + 1); if (equalindex > 0) codec = QTextCodec::codecForName(charset); if (!codec) { parseError = Tr::tr("Cannot decode content with \"%1\". Falling back to \"%2\".") .arg(QLatin1String(charset), QLatin1String(defaultCharset)); } } } message.mimeType = mimeTypeName; message.codec = codec ? codec : BaseMessage::defaultCodec(); } static void parseContentLength(BaseMessage &message, QByteArray contentLength, QString &parseError) { bool ok = true; message.contentLength = contentLength.toInt(&ok); if (!ok) { parseError = Tr::tr("Expected an integer in \"%1\", but got \"%2\".") .arg(QString::fromLatin1(contentLengthFieldName), QString::fromLatin1(contentLength)); } } void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message) { const qint64 startPos = data->pos(); if (message.isValid()) { // incomplete message from last parse message.content.append(data->read(message.contentLength - message.content.length())); return; } while (!data->atEnd()) { const QByteArray &headerFieldLine = data->readLine(); if (headerFieldLine == headerSeparator) { if (message.isValid()) message.content = data->read(message.contentLength); return; } const QPair nameAndValue = splitHeaderFieldLine(headerFieldLine); const QByteArray &headerFieldName = nameAndValue.first.trimmed(); const QByteArray &headerFieldValue = nameAndValue.second.trimmed(); if (headerFieldName.isEmpty()) continue; if (headerFieldName == contentLengthFieldName) { parseContentLength(message, headerFieldValue, parseError); } else if (headerFieldName == contentTypeFieldName) { parseContentType(message, headerFieldValue, parseError); } else { qCWarning(parseLog) << "Unexpected header field" << QLatin1String(headerFieldName) << "in" << QLatin1String(headerFieldLine); } } // the complete header wasn't received jet, waiting for the rest of it and reparse message = BaseMessage(); data->seek(startPos); } QTextCodec *BaseMessage::defaultCodec() { static QTextCodec *codec = QTextCodec::codecForName(defaultCharset); return codec; } bool BaseMessage::isComplete() const { if (!isValid()) return false; QBS_ASSERT(content.length() <= contentLength, return true); return content.length() == contentLength; } bool BaseMessage::isValid() const { return contentLength >= 0; } QByteArray BaseMessage::header() const { QByteArray header; header.append(lengthHeader()); if (codec != defaultCodec() || (!mimeType.isEmpty() && mimeType != JsonRpcMessage::jsonRpcMimeType())) { header.append(typeHeader()); } header.append(headerSeparator); return header; } QByteArray BaseMessage::lengthHeader() const { return QByteArray(contentLengthFieldName) + QByteArray(headerFieldSeparator) + QString::number(content.size()).toLatin1() + QByteArray(headerSeparator); } QByteArray BaseMessage::typeHeader() const { return QByteArray(contentTypeFieldName) + QByteArray(headerFieldSeparator) + mimeType + "; " + contentCharsetName + "=" + codec->name() + QByteArray(headerSeparator); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/diagnostics.cpp0000644000175100017510000000063715232633614020357 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "diagnostics.h" namespace lsp { constexpr const char PublishDiagnosticsNotification::methodName[]; PublishDiagnosticsNotification::PublishDiagnosticsNotification(const PublishDiagnosticsParams ¶ms) : Notification(methodName, params) { } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/semantictokens.h0000644000175100017510000001624615232633614020547 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonkeys.h" #include "jsonobject.h" #include "jsonrpcmessages.h" #include "languageserverprotocol_global.h" #include "lsptypes.h" namespace lsp { struct LANGUAGESERVERPROTOCOL_EXPORT SemanticToken { int deltaLine = 0; int deltaStart = 0; int length = 0; int tokenIndex = 0; int tokenType = 0; int rawTokenModifiers = 0; int tokenModifiers = 0; }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensLegend : public JsonObject { public: using JsonObject::JsonObject; // The token types a server uses. QList tokenTypes() const { return array(tokenTypesKey); } void setTokenTypes(const QList &tokenTypes) { insertArray(tokenTypesKey, tokenTypes); } // The token modifiers a server uses. QList tokenModifiers() const { return array(tokenModifiersKey); } void setTokenModifiers(const QList &value) { insertArray(tokenModifiersKey, value); } bool isValid() const override; }; enum SemanticTokenTypes { namespaceToken, typeToken, classToken, enumToken, interfaceToken, structToken, typeParameterToken, parameterToken, variableToken, propertyToken, enumMemberToken, eventToken, functionToken, methodToken, macroToken, keywordToken, modifierToken, commentToken, stringToken, numberToken, regexpToken, operatorToken }; enum SemanticTokenModifiers { declarationModifier = 0x1, definitionModifier = 0x2, readonlyModifier = 0x4, staticModifier = 0x8, deprecatedModifier = 0x10, abstractModifier = 0x20, asyncModifier = 0x40, modificationModifier = 0x80, documentationModifier = 0x100, defaultLibraryModifier = 0x200 }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } bool isValid() const override { return contains(textDocumentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensDeltaParams : public SemanticTokensParams { public: using SemanticTokensParams::SemanticTokensParams; QString previousResultId() const { return typedValue(previousResultIdKey); } void setPreviousResultId(const QString &previousResultId) { insert(previousResultIdKey, previousResultId); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensRangeParams : public SemanticTokensParams { public: using SemanticTokensParams::SemanticTokensParams; Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokens : public JsonObject { public: using JsonObject::JsonObject; /** * An optional result id. If provided and clients support delta updating * the client will include the result id in the next semantic token request. * A server can then instead of computing all semantic tokens again simply * send a delta. */ std::optional resultId() const { return optionalValue(resultIdKey); } void setResultId(const QString &resultId) { insert(resultIdKey, resultId); } void clearResultId() { remove(resultIdKey); } /// The actual tokens. QList data() const { return array(dataKey); } void setData(const QList &value) { insertArray(dataKey, value); } bool isValid() const override { return contains(dataKey); } QList toTokens(const QList &tokenTypes, const QList &tokenModifiers) const; static QMap defaultTokenTypesMap(); static QMap defaultTokenModifiersMap(); }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensResult : public std::variant { public: using variant::variant; explicit SemanticTokensResult(const QJsonValue &value); }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensFullRequest : public Request { public: explicit SemanticTokensFullRequest(const SemanticTokensParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/semanticTokens/full"; }; class SemanticTokensEdit : public JsonObject { public: using JsonObject::JsonObject; int start() const { return typedValue(startKey); } void setStart(int start) { insert(startKey, start); } int deleteCount() const { return typedValue(deleteCountKey); } void setDeleteCount(int deleteCount) { insert(deleteCountKey, deleteCount); } std::optional> data() const { return optionalArray(dataKey); } void setData(const QList &value) { insertArray(dataKey, value); } void clearData() { remove(dataKey); } int dataSize() const { return contains(dataKey) ? value(dataKey).toArray().size() : 0; } bool isValid() const override { return contains(dataKey) && contains(deleteCountKey); } }; class SemanticTokensDelta : public JsonObject { public: using JsonObject::JsonObject; QString resultId() const { return typedValue(resultIdKey); } void setResultId(const QString &resultId) { insert(resultIdKey, resultId); } QList edits() const { return array(editsKey); } void setEdits(const QList &edits) { insertArray(editsKey, edits); } bool isValid() const override { return contains(resultIdKey) && contains(editsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensDeltaResult : public std::variant { public: using variant::variant; explicit SemanticTokensDeltaResult(const QJsonValue &value); }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensFullDeltaRequest : public Request { public: explicit SemanticTokensFullDeltaRequest(const SemanticTokensDeltaParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/semanticTokens/full/delta"; }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensRangeRequest : public Request { public: explicit SemanticTokensRangeRequest(const SemanticTokensRangeParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/semanticTokens/range"; }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensRefreshRequest : public Request { public: explicit SemanticTokensRefreshRequest(); using Request::Request; constexpr static const char methodName[] = "workspace/semanticTokens/refresh"; }; } // namespace lsp qbs-src-3.3.1/src/shared/lsp/jsonobject.h0000644000175100017510000001433615232633614017656 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "algorithm.h" #include "languageserverprotocol_global.h" #include "lsputils.h" #include #include #include #include namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT JsonObject { public: using iterator = QJsonObject::iterator; using const_iterator = QJsonObject::const_iterator; JsonObject() = default; explicit JsonObject(const QJsonObject &object) : m_jsonObject(object) { } explicit JsonObject(QJsonObject &&object) : m_jsonObject(std::move(object)) { } JsonObject(const JsonObject &object) : m_jsonObject(object.m_jsonObject) { } JsonObject(JsonObject &&object) : m_jsonObject(std::move(object.m_jsonObject)) { } explicit JsonObject(const QJsonValue &value) : m_jsonObject(value.toObject()) { } virtual ~JsonObject() = default; JsonObject &operator=(const JsonObject &other); JsonObject &operator=(JsonObject &&other); bool operator==(const JsonObject &other) const { return m_jsonObject == other.m_jsonObject; } operator const QJsonObject&() const { return m_jsonObject; } virtual bool isValid() const { return true; } iterator end() { return m_jsonObject.end(); } const_iterator end() const { return m_jsonObject.end(); } iterator insert(const std::string_view key, const JsonObject &value); iterator insert(const std::string_view key, const QJsonValue &value); protected: template iterator insertVariant(const std::string_view key, const V &variant); template iterator insertVariant(const std::string_view key, const V &variant); // QJSonObject redirections QJsonValue value(const std::string_view key) const { return m_jsonObject.value(QLatin1String(key.data())); } bool contains(const std::string_view key) const { return m_jsonObject.contains(QLatin1String(key.data())); } iterator find(const std::string_view key) { return m_jsonObject.find(QLatin1String(key.data())); } const_iterator find(const std::string_view key) const { return m_jsonObject.find(QLatin1String(key.data())); } void remove(const std::string_view key) { m_jsonObject.remove(QLatin1String(key.data())); } QStringList keys() const { return m_jsonObject.keys(); } // convenience value access template T typedValue(const std::string_view key) const; template std::optional optionalValue(const std::string_view key) const; template LanguageClientValue clientValue(const std::string_view key) const; template std::optional> optionalClientValue(const std::string_view key) const; template QList array(const std::string_view key) const; template std::optional> optionalArray(const std::string_view key) const; template LanguageClientArray clientArray(const std::string_view key) const; template std::optional> optionalClientArray(const std::string_view key) const; template void insertArray(const std::string_view key, const QList &array); template void insertArray(const std::string_view key, const QList &array); private: QJsonObject m_jsonObject; }; template JsonObject::iterator JsonObject::insertVariant(const std::string_view key, const V &variant) { return std::holds_alternative(variant) ? insert(key, std::get(variant)) : end(); } template JsonObject::iterator JsonObject::insertVariant(const std::string_view key, const V &variant) { auto result = insertVariant(key, variant); return result != end() ? result : insertVariant(key, variant); } template T JsonObject::typedValue(const std::string_view key) const { return fromJsonValue(value(key)); } template std::optional JsonObject::optionalValue(const std::string_view key) const { const QJsonValue &val = value(key); return val.isUndefined() ? std::nullopt : std::make_optional(fromJsonValue(val)); } template LanguageClientValue JsonObject::clientValue(const std::string_view key) const { return LanguageClientValue(value(key)); } template std::optional> JsonObject::optionalClientValue(const std::string_view key) const { return contains(key) ? std::make_optional(clientValue(key)) : std::nullopt; } template QList JsonObject::array(const std::string_view key) const { if (const std::optional> &array = optionalArray(key)) return *array; qCDebug(conversionLog) << QString("Expected array under %1 in:") .arg(QLatin1String(key.data())) << *this; return {}; } template std::optional> JsonObject::optionalArray(const std::string_view key) const { const QJsonValue &jsonValue = value(key); if (jsonValue.isUndefined()) return std::nullopt; return Utils::transform>(jsonValue.toArray(), &fromJsonValue); } template LanguageClientArray JsonObject::clientArray(const std::string_view key) const { return LanguageClientArray(value(key)); } template std::optional> JsonObject::optionalClientArray(const std::string_view key) const { const QJsonValue &val = value(key); return !val.isUndefined() ? std::make_optional(LanguageClientArray(value(key))) : std::nullopt; } template void JsonObject::insertArray(const std::string_view key, const QList &array) { QJsonArray jsonArray; for (const T &item : array) jsonArray.append(QJsonValue(item)); insert(key, jsonArray); } template void JsonObject::insertArray(const std::string_view key, const QList &array) { QJsonArray jsonArray; for (const JsonObject &item : array) jsonArray.append(item.m_jsonObject); insert(key, jsonArray); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/completion.cpp0000644000175100017510000000353115232633614020215 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "completion.h" namespace lsp { constexpr const char CompletionRequest::methodName[]; constexpr const char CompletionItemResolveRequest::methodName[]; CompletionRequest::CompletionRequest(const CompletionParams ¶ms) : Request(methodName, params) { } std::optional CompletionItem::documentation() const { QJsonValue documentation = value(documentationKey); if (documentation.isUndefined()) return std::nullopt; return MarkupOrString(documentation); } std::optional CompletionItem::insertTextFormat() const { if (std::optional value = optionalValue(insertTextFormatKey)) return std::make_optional(CompletionItem::InsertTextFormat(*value)); return std::nullopt; } std::optional> CompletionItem::tags() const { if (const auto value = optionalValue(tagsKey)) { QList tags; for (auto it = value->cbegin(); it != value->cend(); ++it) tags << static_cast(it->toInt()); return tags; } return {}; } CompletionItemResolveRequest::CompletionItemResolveRequest(const CompletionItem ¶ms) : Request(methodName, params) { } CompletionResult::CompletionResult(const QJsonValue &value) { if (value.isNull()) { emplace(nullptr); } else if (value.isArray()) { QList items; for (auto arrayElement : value.toArray()) items << CompletionItem(arrayElement); emplace>(items); } else if (value.isObject()) { emplace(CompletionList(value)); } } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/link.h0000644000175100017510000000375015232633614016451 0ustar runnerrunner// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "filepath.h" #include #include #include #include namespace lsp::Utils { class Link { public: Link() = default; Link(const FilePath &filePath, int line = 0, int column = 0) : targetFilePath(filePath) , targetLine(line) , targetColumn(column) {} static Link fromString(const QString &filePathWithNumbers, bool canContainLineNumber = false); bool hasValidTarget() const { if (!targetFilePath.isEmpty()) return true; return !targetFilePath.scheme().isEmpty() || !targetFilePath.host().isEmpty(); } bool hasValidLinkText() const { return linkTextStart != linkTextEnd; } bool operator==(const Link &other) const { return hasSameLocation(other) && linkTextStart == other.linkTextStart && linkTextEnd == other.linkTextEnd; } bool operator!=(const Link &other) const { return !(*this == other); } bool hasSameLocation(const Link &other) const { return targetFilePath == other.targetFilePath && targetLine == other.targetLine && targetColumn == other.targetColumn; } friend size_t qHash(const Link &l, uint seed = 0) { return QT_PREPEND_NAMESPACE(qHash)(l.targetFilePath, seed) | QT_PREPEND_NAMESPACE(qHash(l.targetLine, seed)) | QT_PREPEND_NAMESPACE(qHash(l.targetColumn, seed)); } int linkTextStart = -1; int linkTextEnd = -1; FilePath targetFilePath; int targetLine = 0; int targetColumn = 0; }; using LinkHandler = std::function; using Links = QList; } // namespace lsp::Utils namespace std { template<> struct hash { size_t operator()(const lsp::Utils::Link &fn) const { return qHash(fn); } }; } // std qbs-src-3.3.1/src/shared/lsp/.clang-tidy0000644000175100017510000000014515232633614017372 0ustar runnerrunnerChecks: '-*,misc-definitions-in-headers' CheckOptions: - { key: HeaderFileExtensions, value: "x" } qbs-src-3.3.1/src/shared/lsp/algorithm.h0000644000175100017510000013544515232633614017511 0ustar runnerrunner// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "predicates.h" #include // for Q_REQUIRED_RESULT #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace lsp::Utils { ///////////////////////// // anyOf ///////////////////////// template bool anyOf(const T &container, F predicate); template bool anyOf(const T &container, R (S::*predicate)() const); template bool anyOf(const T &container, R S::*member); ///////////////////////// // count ///////////////////////// template int count(const T &container, F predicate); ///////////////////////// // allOf ///////////////////////// template bool allOf(const T &container, F predicate); ///////////////////////// // erase ///////////////////////// template void erase(T &container, F predicate); template bool eraseOne(T &container, F predicate); ///////////////////////// // contains ///////////////////////// template bool contains(const T &container, F function); template bool contains(const T &container, R (S::*function)() const); template bool contains(const C &container, R S::*member); ///////////////////////// // findOr ///////////////////////// template Q_REQUIRED_RESULT typename C::value_type findOr(const C &container, typename C::value_type other, F function); template Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, typename T::value_type other, R (S::*function)() const); template Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, typename T::value_type other, R S::*member); ///////////////////////// // findOrDefault ///////////////////////// template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, F function); template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, R (S::*function)() const); template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, R S::*member); ///////////////////////// // indexOf ///////////////////////// template Q_REQUIRED_RESULT int indexOf(const C &container, F function); ///////////////////////// // maxElementOr ///////////////////////// template typename T::value_type maxElementOr(const T &container, typename T::value_type other); ///////////////////////// // filtered ///////////////////////// template Q_REQUIRED_RESULT C filtered(const C &container, F predicate); template Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const); ///////////////////////// // partition ///////////////////////// // Recommended usage: // C hit; // C miss; // std::tie(hit, miss) = Utils::partition(container, predicate); template Q_REQUIRED_RESULT std::tuple partition(const C &container, F predicate); template Q_REQUIRED_RESULT std::tuple partition(const C &container, R (S::*predicate)() const); ///////////////////////// // filteredUnique ///////////////////////// template Q_REQUIRED_RESULT C filteredUnique(const C &container); ///////////////////////// // qobject_container_cast ///////////////////////// template class Container, typename Base> Container qobject_container_cast(const Container &container); ///////////////////////// // static_container_cast ///////////////////////// template class Container, typename Base> Container static_container_cast(const Container &container); ///////////////////////// // sort ///////////////////////// template inline void sort(Container &container); template inline void sort(Container &container, Predicate p); template inline void sort(Container &container, R S::*member); template inline void sort(Container &container, R (S::*function)() const); ///////////////////////// // reverseForeach ///////////////////////// template inline void reverseForeach(const Container &c, const Op &operation); ///////////////////////// // toReferences ///////////////////////// template class ResultContainer, typename SourceContainer> auto toReferences(SourceContainer &sources); template auto toReferences(SourceContainer &sources); ///////////////////////// // toConstReferences ///////////////////////// template class ResultContainer, typename SourceContainer> auto toConstReferences(const SourceContainer &sources); template auto toConstReferences(const SourceContainer &sources); ///////////////////////// // take ///////////////////////// template Q_REQUIRED_RESULT std::optional take(C &container, P predicate); template Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member); template Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const); ///////////////////////// // setUnionMerge ///////////////////////// // Works like std::set_union but provides a merge function for items that match // !(a > b) && !(b > a) which normally means that there is an "equal" match. // It uses iterators to support move_iterators. template OutputIt setUnionMerge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge, Compare comp); template OutputIt setUnionMerge( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge); template OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge, Compare comp); template OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge); ///////////////////////// // setUnion ///////////////////////// template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); ///////////////////////// // transform ///////////////////////// // function without result type deduction: template // function type Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); // function with result type deduction: template< template class C, // result container type typename SC, // input container type typename F, // function type typename Value = typename std::decay_t::value_type, typename Result = std::decay_t>, typename ResultContainer = C> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); #ifdef Q_CC_CLANG // "Matching of template template-arguments excludes compatible templates" // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0522r0.html (P0522R0) // in C++17 makes the above match e.g. C=std::vector even though that takes two // template parameters. Unfortunately the following one matches too, and there is no additional // partial ordering rule, resulting in an ambiguous call for this previously valid code. // GCC and MSVC ignore that issue and follow the standard to the letter, but Clang only // enables the new behavior when given -frelaxed-template-template-args . // To avoid requiring everyone using this header to enable that feature, keep the old implementation // for Clang. template< template class C, // result container type typename SC, // input container type typename F, // function type typename Value = typename std::decay_t::value_type, typename Result = std::decay_t>, typename ResultContainer = C>> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); #endif // member function without result type deduction: template class C, // result container type typename SC, // input container type typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const); // member function with result type deduction: template Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const); // member without result type deduction: template Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p); // member with result type deduction: template class C, // result container typename SC, // input container typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p); // same container types for input and output, const input // function: template class C, // container type typename F, // function type typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, F function); // same container types for input and output, const input // member function: template class C, // container type typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, R (S::*p)() const); // same container types for input and output, const input // members: template class C, // container typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, R S::*p); // same container types for input and output, non-const input // function: template class C, // container type typename F, // function type typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, F function); // same container types for input and output, non-const input // member function: template class C, // container type typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, R (S::*p)() const); // same container types for input and output, non-const input // members: template class C, // container typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, R S::*p); ///////////////////////////////////////////////////////////////////////////// //////// Implementations ////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ////////////////// // anyOf ///////////////// template bool anyOf(const T &container, F predicate) { return std::any_of(std::begin(container), std::end(container), predicate); } // anyOf taking a member function pointer template bool anyOf(const T &container, R (S::*predicate)() const) { return std::any_of(std::begin(container), std::end(container), std::mem_fn(predicate)); } // anyOf taking a member pointer template bool anyOf(const T &container, R S::*member) { return std::any_of(std::begin(container), std::end(container), std::mem_fn(member)); } ////////////////// // count ///////////////// template int count(const T &container, F predicate) { return std::count_if(std::begin(container), std::end(container), predicate); } ////////////////// // allOf ///////////////// template bool allOf(const T &container, F predicate) { return std::all_of(std::begin(container), std::end(container), predicate); } // allOf taking a member function pointer template bool allOf(const T &container, R (S::*predicate)() const) { return std::all_of(std::begin(container), std::end(container), std::mem_fn(predicate)); } // allOf taking a member pointer template bool allOf(const T &container, R S::*member) { return std::all_of(std::begin(container), std::end(container), std::mem_fn(member)); } ////////////////// // erase ///////////////// template void erase(T &container, F predicate) { container.erase(std::remove_if(std::begin(container), std::end(container), predicate), std::end(container)); } template bool eraseOne(T &container, F predicate) { const auto it = std::find_if(std::begin(container), std::end(container), predicate); if (it == std::end(container)) return false; container.erase(it); return true; } ////////////////// // contains ///////////////// template bool contains(const T &container, F function) { return anyOf(container, function); } template bool contains(const T &container, R (S::*function)() const) { return anyOf(container, function); } template bool contains(const C &container, R S::*member) { return anyOf(container, std::mem_fn(member)); } ////////////////// // findOr ///////////////// template Q_REQUIRED_RESULT typename C::value_type findOr(const C &container, typename C::value_type other, F function) { typename C::const_iterator begin = std::begin(container); typename C::const_iterator end = std::end(container); typename C::const_iterator it = std::find_if(begin, end, function); return it == end ? other : *it; } template Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, typename T::value_type other, R (S::*function)() const) { return findOr(container, other, std::mem_fn(function)); } template Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, typename T::value_type other, R S::*member) { return findOr(container, other, std::mem_fn(member)); } ////////////////// // findOrDefault ////////////////// // Default implementation: template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, F function) { return findOr(container, typename C::value_type(), function); } template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, R (S::*function)() const) { return findOr(container, typename C::value_type(), std::mem_fn(function)); } template Q_REQUIRED_RESULT typename std::enable_if_t::value, typename C::value_type> findOrDefault(const C &container, R S::*member) { return findOr(container, typename C::value_type(), std::mem_fn(member)); } ////////////////// // index of: ////////////////// template Q_REQUIRED_RESULT int indexOf(const C& container, F function) { typename C::const_iterator begin = std::begin(container); typename C::const_iterator end = std::end(container); typename C::const_iterator it = std::find_if(begin, end, function); return it == end ? -1 : std::distance(begin, it); } ////////////////// // max element ////////////////// template typename T::value_type maxElementOr(const T &container, typename T::value_type other) { typename T::const_iterator begin = std::begin(container); typename T::const_iterator end = std::end(container); typename T::const_iterator it = std::max_element(begin, end); if (it == end) return other; return *it; } ////////////////// // transform ///////////////// namespace { ///////////////// // helper code for transform to use back_inserter and thus push_back for everything // and insert for QSet<> // // SetInsertIterator, straight from the standard for insert_iterator // just without the additional parameter to insert template class SetInsertIterator { protected: Container *container; public: using iterator_category = std::output_iterator_tag; using container_type = Container; explicit SetInsertIterator(Container &x) : container(&x) {} SetInsertIterator &operator=(const typename Container::value_type &value) { container->insert(value); return *this; } SetInsertIterator &operator=(typename Container::value_type &&value) { container->insert(std::move(value)); return *this; } SetInsertIterator &operator*() { return *this; } SetInsertIterator &operator++() { return *this; } SetInsertIterator operator++(int) { return *this; } }; // for QMap / QHash, inserting a std::pair / QPair template class MapInsertIterator { protected: Container *container; public: using iterator_category = std::output_iterator_tag; using container_type = Container; explicit MapInsertIterator(Container &x) : container(&x) {} MapInsertIterator &operator=( const std::pair &value) { container->insert(value.first, value.second); return *this; } MapInsertIterator &operator=( const QPair &value) { container->insert(value.first, value.second); return *this; } MapInsertIterator &operator*() { return *this; } MapInsertIterator &operator++() { return *this; } MapInsertIterator operator++(int) { return *this; } }; // because Qt container are not implementing the standard interface we need // this helper functions for generic code template void append(QList *container, QList &&input) { container->append(std::move(input)); } template void append(QList *container, const QList &input) { container->append(input); } template void append(Container *container, Container &&input) { container->insert(container->end(), std::make_move_iterator(input.begin()), std::make_move_iterator(input.end())); } template void append(Container *container, const Container &input) { container->insert(container->end(), input.begin(), input.end()); } // BackInsertIterator behaves like std::back_insert_iterator except is adds the back insertion for // container of the same type template class BackInsertIterator { public: using iterator_category = std::output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using container_type = Container; explicit constexpr BackInsertIterator(Container &container) : m_container(std::addressof(container)) {} constexpr BackInsertIterator &operator=(const typename Container::value_type &value) { m_container->push_back(value); return *this; } constexpr BackInsertIterator &operator=(typename Container::value_type &&value) { m_container->push_back(std::move(value)); return *this; } constexpr BackInsertIterator &operator=(const Container &container) { append(m_container, container); return *this; } constexpr BackInsertIterator &operator=(Container &&container) { append(m_container, container); return *this; } [[nodiscard]] constexpr BackInsertIterator &operator*() { return *this; } constexpr BackInsertIterator &operator++() { return *this; } constexpr BackInsertIterator operator++(int) { return *this; } private: Container *m_container; }; // inserter helper function, returns a BackInsertIterator for most containers // and is overloaded for QSet<> and other containers without push_back, returning custom inserters template inline BackInsertIterator inserter(Container &container) { return BackInsertIterator(container); } template inline SetInsertIterator> inserter(QSet &container) { return SetInsertIterator>(container); } template inline SetInsertIterator> inserter(std::set &container) { return SetInsertIterator>(container); } template inline SetInsertIterator> inserter(std::unordered_set &container) { return SetInsertIterator>(container); } template inline SetInsertIterator> inserter(std::map &container) { return SetInsertIterator>(container); } template inline SetInsertIterator> inserter(std::unordered_map &container) { return SetInsertIterator>(container); } template inline MapInsertIterator> inserter(QMap &container) { return MapInsertIterator>(container); } template inline MapInsertIterator> inserter(QHash &container) { return MapInsertIterator>(container); } // Helper code for container.reserve that makes it possible to effectively disable it for // specific cases // default: do reserve // Template arguments are more specific than the second version below, so this is tried first template class C, typename... CArgs, typename = decltype(&C::reserve)> void reserve(C &c, typename C::size_type s) { c.reserve(s); } // containers that don't have reserve() template void reserve(C &, typename C::size_type) { } } // anonymous // -------------------------------------------------------------------- // Different containers for input and output: // -------------------------------------------------------------------- // different container types for input and output, e.g. transforming a QList into a QSet // function without result type deduction: template // function type Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function) { ResultContainer result; reserve(result, typename ResultContainer::size_type(container.size())); std::transform(std::begin(container), std::end(container), inserter(result), function); return result; } // function with result type deduction: template class C, // result container type typename SC, // input container type typename F, // function type typename Value, typename Result, typename ResultContainer> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function) { return transform(std::forward(container), function); } #ifdef Q_CC_CLANG template class C, // result container type typename SC, // input container type typename F, // function type typename Value, typename Result, typename ResultContainer> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function) { return transform(std::forward(container), function); } #endif // member function without result type deduction: template class C, // result container type typename SC, // input container type typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const) { return transform(std::forward(container), std::mem_fn(p)); } // member function with result type deduction: template Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const) { return transform(std::forward(container), std::mem_fn(p)); } // member without result type deduction: template Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p) { return transform(std::forward(container), std::mem_fn(p)); } // member with result type deduction: template class C, // result container typename SC, // input container typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p) { return transform(std::forward(container), std::mem_fn(p)); } // same container types for input and output, const input // function: template class C, // container type typename F, // function type typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, F function) { return transform &>(container, function); } // member function: template class C, // container type typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, R (S::*p)() const) { return transform &>(container, std::mem_fn(p)); } // members: template class C, // container typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(const C &container, R S::*p) { return transform &>(container, std::mem_fn(p)); } // same container types for input and output, non-const input // function: template class C, // container type typename F, // function type typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, F function) { return transform &>(container, function); } // member function: template class C, // container type typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, R (S::*p)() const) { return transform &>(container, std::mem_fn(p)); } // members: template class C, // container typename R, typename S, typename... CArgs> // Arguments to SC Q_REQUIRED_RESULT decltype(auto) transform(C &container, R S::*p) { return transform &>(container, std::mem_fn(p)); } // Specialization for QStringList: template class C = QList, // result container typename F> // Arguments to C Q_REQUIRED_RESULT decltype(auto) transform(const QStringList &container, F function) { return transform &>(static_cast>(container), function); } // member function: template class C = QList, // result container type typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(const QStringList &container, R (S::*p)() const) { return transform &>(static_cast>(container), std::mem_fn(p)); } // members: template class C = QList, // result container typename R, typename S> Q_REQUIRED_RESULT decltype(auto) transform(const QStringList &container, R S::*p) { return transform &>(static_cast>(container), std::mem_fn(p)); } ////////////////// // filtered ///////////////// template Q_REQUIRED_RESULT C filtered(const C &container, F predicate) { C out; std::copy_if(std::begin(container), std::end(container), inserter(out), predicate); return out; } template Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const) { C out; std::copy_if(std::begin(container), std::end(container), inserter(out), std::mem_fn(predicate)); return out; } ////////////////// // filteredCast ///////////////// template Q_REQUIRED_RESULT R filteredCast(const C &container, F predicate) { R out; std::copy_if(std::begin(container), std::end(container), inserter(out), predicate); return out; } ////////////////// // partition ///////////////// // Recommended usage: // C hit; // C miss; // std::tie(hit, miss) = Utils::partition(container, predicate); template Q_REQUIRED_RESULT std::tuple partition(const C &container, F predicate) { C hit; C miss; reserve(hit, container.size()); reserve(miss, container.size()); auto hitIns = inserter(hit); auto missIns = inserter(miss); for (const auto &i : container) { if (predicate(i)) hitIns = i; else missIns = i; } return std::make_tuple(hit, miss); } template Q_REQUIRED_RESULT std::tuple partition(const C &container, R (S::*predicate)() const) { return partition(container, std::mem_fn(predicate)); } ////////////////// // filteredUnique ///////////////// template Q_REQUIRED_RESULT C filteredUnique(const C &container) { C result; auto ins = inserter(result); QSet seen; int setSize = 0; auto endIt = std::end(container); for (auto it = std::begin(container); it != endIt; ++it) { seen.insert(*it); if (setSize == seen.size()) // unchanged size => was already seen continue; ++setSize; ins = *it; } return result; } ////////////////// // qobject_container_cast ///////////////// template class Container, typename Base> Container qobject_container_cast(const Container &container) { Container result; auto ins = inserter(result); for (Base val : container) { if (T target = qobject_cast(val)) ins = target; } return result; } ////////////////// // static_container_cast ///////////////// template class Container, typename Base> Container static_container_cast(const Container &container) { Container result; reserve(result, container.size()); auto ins = inserter(result); for (Base val : container) ins = static_cast(val); return result; } ////////////////// // sort ///////////////// template inline void sort(Container &container) { std::stable_sort(std::begin(container), std::end(container)); } template inline void sort(Container &container, Predicate p) { std::stable_sort(std::begin(container), std::end(container), p); } // const lvalue template inline Container sorted(const Container &container) { Container c = container; sort(c); return c; } // non-const lvalue // This is needed because otherwise the "universal" reference below is used, modifying the input // container. template inline Container sorted(Container &container) { Container c = container; sort(c); return c; } // non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) template inline Container sorted(Container &&container) { sort(container); return std::move(container); } // const rvalue template inline Container sorted(const Container &&container) { return sorted(container); } // const lvalue template inline Container sorted(const Container &container, Predicate p) { Container c = container; sort(c, p); return c; } // non-const lvalue // This is needed because otherwise the "universal" reference below is used, modifying the input // container. template inline Container sorted(Container &container, Predicate p) { Container c = container; sort(c, p); return c; } // non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) template inline Container sorted(Container &&container, Predicate p) { sort(container, p); return std::move(container); } // const rvalue template inline Container sorted(const Container &&container, Predicate p) { return sorted(container, p); } // pointer to member template inline void sort(Container &container, R S::*member) { auto f = std::mem_fn(member); using const_ref = typename Container::const_reference; std::stable_sort(std::begin(container), std::end(container), [&f](const_ref a, const_ref b) { return f(a) < f(b); }); } // const lvalue template inline Container sorted(const Container &container, R S::*member) { Container c = container; sort(c, member); return c; } // non-const lvalue // This is needed because otherwise the "universal" reference below is used, modifying the input // container. template inline Container sorted(Container &container, R S::*member) { Container c = container; sort(c, member); return c; } // non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) template inline Container sorted(Container &&container, R S::*member) { sort(container, member); return std::move(container); } // const rvalue template inline Container sorted(const Container &&container, R S::*member) { return sorted(container, member); } // pointer to member function template inline void sort(Container &container, R (S::*function)() const) { auto f = std::mem_fn(function); using const_ref = typename Container::const_reference; std::stable_sort(std::begin(container), std::end(container), [&f](const_ref a, const_ref b) { return f(a) < f(b); }); } // const lvalue template inline Container sorted(const Container &container, R (S::*function)() const) { Container c = container; sort(c, function); return c; } // non-const lvalue // This is needed because otherwise the "universal" reference below is used, modifying the input // container. template inline Container sorted(Container &container, R (S::*function)() const) { Container c = container; sort(c, function); return c; } // non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) template inline Container sorted(Container &&container, R (S::*function)() const) { sort(container, function); return std::move(container); } // const rvalue template inline Container sorted(const Container &&container, R (S::*function)() const) { return sorted(container, function); } ////////////////// // reverseForeach ///////////////// template inline void reverseForeach(const Container &c, const Op &operation) { auto rend = c.rend(); for (auto it = c.rbegin(); it != rend; ++it) operation(*it); } ////////////////// // toReferences ///////////////// template class ResultContainer, typename SourceContainer> auto toReferences(SourceContainer &sources) { return transform(sources, [] (auto &value) { return std::ref(value); }); } template auto toReferences(SourceContainer &sources) { return transform(sources, [] (auto &value) { return std::ref(value); }); } ////////////////// // toConstReferences ///////////////// template class ResultContainer, typename SourceContainer> auto toConstReferences(const SourceContainer &sources) { return transform(sources, [] (const auto &value) { return std::cref(value); }); } template auto toConstReferences(const SourceContainer &sources) { return transform(sources, [] (const auto &value) { return std::cref(value); }); } ////////////////// // take: ///////////////// template Q_REQUIRED_RESULT std::optional take(C &container, P predicate) { const auto end = std::end(container); const auto it = std::find_if(std::begin(container), end, predicate); if (it == end) return std::nullopt; std::optional result = std::make_optional(std::move(*it)); container.erase(it); return result; } // pointer to member template Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member) { return take(container, std::mem_fn(member)); } // pointer to member function template Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const) { return take(container, std::mem_fn(function)); } ////////////////// // setUnionMerge: Works like std::set_union but provides a merge function for items that match // !(a > b) && !(b > a) which normally means that there is an "equal" match. // It uses iterators to support move_iterators. ///////////////// template OutputIt setUnionMerge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge, Compare comp) { for (; first1 != last1; ++d_first) { if (first2 == last2) return std::copy(first1, last1, d_first); if (comp(*first2, *first1)) { *d_first = *first2++; } else { if (comp(*first1, *first2)) { *d_first = *first1; } else { *d_first = merge(*first1, *first2); ++first2; } ++first1; } } return std::copy(first2, last2, d_first); } template OutputIt setUnionMerge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge) { return setUnionMerge(first1, last1, first2, last2, d_first, merge, std::less>{}); } template OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge, Compare comp) { OutputContainer results; results.reserve(input1.size() + input2.size()); setUnionMerge(std::make_move_iterator(std::begin(input1)), std::make_move_iterator(std::end(input1)), std::make_move_iterator(std::begin(input2)), std::make_move_iterator(std::end(input2)), std::back_inserter(results), merge, comp); return results; } template OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge) { return setUnionMerge(std::forward(input1), std::forward(input2), merge, std::less>{}); } template auto usize(const Container &container) { return static_cast>(std::size(container)); } template auto ssize(const Container &container) { return static_cast>(std::size(container)); } template struct CompareIter { Compare compare; explicit constexpr CompareIter(Compare compare) : compare(std::move(compare)) {} template constexpr bool operator()(Iterator1 it1, Iterator2 it2) { return bool(compare(*it1, *it2)); } }; template OutputIterator set_union_impl(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { auto compare = CompareIter(comp); while (first1 != last1 && first2 != last2) { if (compare(first1, first2)) { *result = *first1; ++first1; } else if (compare(first2, first1)) { *result = *first2; ++first2; } else { *result = *first1; ++first1; ++first2; } ++result; } return std::copy(first2, last2, std::copy(first1, last1, result)); } template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { return set_union_impl(first1, last1, first2, last2, result, comp); } template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { return set_union_impl( first1, last1, first2, last2, result, std::less{}); } // Replacement for deprecated Qt functionality template QSet toSet(const QList &list) { return QSet(list.begin(), list.end()); } template QList toList(const QSet &set) { return QList(set.begin(), set.end()); } template void addToHash(QHash *result, const QHash &additionalContents) { result->insert(additionalContents); } // Workaround for missing information from QSet::insert() // Return type could be a pair like for std::set, but we never use the iterator anyway. template [[nodiscard]] bool insert(QSet &s, const U &v) { const int oldSize = s.size(); s.insert(v); return s.size() > oldSize; } } // namespace lsp::Utils qbs-src-3.3.1/src/shared/lsp/progresssupport.h0000644000175100017510000001220415232633614021007 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" #include #include namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT ProgressToken : public std::variant { public: using variant::variant; explicit ProgressToken(const QJsonValue &value); bool isValid() { return true; } operator QJsonValue() const; }; class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressReport : public JsonObject { public: using JsonObject::JsonObject; /** * Controls if a cancel button should be shown to allow the user to cancel the * long running operation. * Clients that don't support cancellation can ignore the setting. */ std::optional cancellable() const { return optionalValue(cancellableKey); } void setCancellable(bool cancellable) { insert(cancellableKey, cancellable); } void clearCancellable() { remove(cancellableKey); } /** * Optional, more detailed associated progress message. Contains * complementary information to the `title`. * * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". * If unset, the previous progress message (if any) is still valid. */ std::optional message() const { return optionalValue(messageKey); } void setMessage(const QString &message) { insert(messageKey, message); } void clearMessage() { remove(messageKey); } /** * Optional progress percentage to display (value 100 is considered 100%). * If not provided infinite progress is assumed and clients are allowed * to ignore the `percentage` value in subsequent in report notifications. * * The value should be steadily rising. Clients are free to ignore values * that are not following this rule. */ // Allthough percentage is defined as an uint by the protocol some server // return a double here. Be less strict and also use a double. // CAUTION: the range is still 0 - 100 and not 0 - 1 std::optional percentage() const { return optionalValue(percentageKey); } void setPercentage(double percentage) { insert(percentageKey, percentage); } void clearPercentage() { remove(percentageKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressBegin : public WorkDoneProgressReport { public: using WorkDoneProgressReport::WorkDoneProgressReport; /** * Mandatory title of the progress operation. Used to briefly inform about * the kind of operation being performed. * * Examples: "Indexing" or "Linking dependencies". */ QString title() const { return typedValue(titleKey); } void setTitle(const QString &title) { insert(titleKey, title); } }; class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressEnd : public JsonObject { public: using JsonObject::JsonObject; /** * Optional, a final message indicating to for example indicate the outcome * of the operation. */ std::optional message() const { return optionalValue(messageKey); } void setMessage(const QString &message) { insert(messageKey, message); } void clearMessage() { remove(messageKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ProgressParams : public JsonObject { public: using JsonObject::JsonObject; ProgressToken token() const { return ProgressToken(JsonObject::value(tokenKey)); } void setToken(const ProgressToken &token) { insert(tokenKey, token); } using ProgressType = std::variant; ProgressType value() const; void setValue(const ProgressType &value); bool isValid() const override { return contains(tokenKey) && contains(valueKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ProgressNotification : public Notification { public: ProgressNotification(const ProgressParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "$/progress"; }; class LANGUAGESERVERPROTOCOL_EXPORT ProgressTokenParams : public JsonObject { public: using JsonObject::JsonObject; // The token to be used to report progress. ProgressToken token() const { return typedValue(tokenKey); } void setToken(const ProgressToken &token) { insert(tokenKey, token); } }; using WorkDoneProgressCreateParams = ProgressTokenParams; class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressCreateRequest : public Request { public: WorkDoneProgressCreateRequest(const WorkDoneProgressCreateParams ¶ms); using Request::Request; constexpr static const char methodName[] = "window/workDoneProgress/create"; }; using WorkDoneProgressCancelParams = ProgressTokenParams; class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressCancelRequest : public Request { public: using Request::Request; constexpr static const char methodName[] = "window/workDoneProgress/cancel"; }; } // namespace lsp qbs-src-3.3.1/src/shared/lsp/lsp.qbs0000644000175100017510000000354415232633614016651 0ustar runnerrunnerimport qbs.Utilities QbsStaticLibrary { name: "qtclsp" Depends { name: "qbscore"; cpp.link: false } Depends { condition: Utilities.versionCompare(Qt.core.version, "6") >= 0 name: "Qt.core5compat" } cpp.defines: base.filter(function(d) { return d !== "QT_NO_CAST_FROM_ASCII"; }) .concat("LANGUAGESERVERPROTOCOL_STATIC_LIBRARY") files: [ "algorithm.h", "basemessage.cpp", "basemessage.h", "callhierarchy.cpp", "callhierarchy.h", "client.cpp", "client.h", "clientcapabilities.cpp", "clientcapabilities.h", "completion.cpp", "completion.h", "diagnostics.cpp", "diagnostics.h", "filepath.h", "initializemessages.cpp", "initializemessages.h", "jsonkeys.h", "jsonobject.cpp", "jsonobject.h", "jsonrpcmessages.cpp", "jsonrpcmessages.h", "languagefeatures.cpp", "languagefeatures.h", "languageserverprotocol_global.h", "languageserverprotocoltr.h", "link.cpp", "link.h", "lsptypes.cpp", "lsptypes.h", "lsputils.cpp", "lsputils.h", "messages.cpp", "messages.h", "predicates.h", "progresssupport.cpp", "progresssupport.h", "semantictokens.cpp", "semantictokens.h", "servercapabilities.cpp", "servercapabilities.h", "shutdownmessages.cpp", "shutdownmessages.h", "textsynchronization.cpp", "textsynchronization.h", "textutils.cpp", "textutils.h", "workspace.cpp", "workspace.h", ] Export { Depends { name: "cpp" } cpp.defines: "LANGUAGESERVERPROTOCOL_STATIC_LIBRARY" cpp.includePaths: exportingProduct.sourceDirectory + "/.." } } qbs-src-3.3.1/src/shared/lsp/clientcapabilities.cpp0000644000175100017510000001000315232633614021664 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "clientcapabilities.h" namespace lsp { std::optional> SymbolCapabilities::SymbolKindCapabilities::valueSet() const { if (std::optional> array = optionalArray(valueSetKey)) { return std::make_optional( Utils::transform(*array, [](int value) { return static_cast(value); })); } return std::nullopt; } void SymbolCapabilities::SymbolKindCapabilities::setValueSet(const QList &valueSet) { insert(valueSetKey, enumArrayToJsonArray(valueSet)); } WorkspaceClientCapabilities::WorkspaceClientCapabilities() { setWorkspaceFolders(true); } std::optional> SemanticTokensClientCapabilities::Requests::range() const { using RetType = std::variant; const QJsonValue &rangeOptions = value(rangeKey); if (rangeOptions.isBool()) return RetType(rangeOptions.toBool()); if (rangeOptions.isObject()) return RetType(rangeOptions.toObject()); return std::nullopt; } void SemanticTokensClientCapabilities::Requests::setRange( const std::variant &range) { insertVariant(rangeKey, range); } std::optional> SemanticTokensClientCapabilities::Requests::full() const { using RetType = std::variant; const QJsonValue &fullOptions = value(fullKey); if (fullOptions.isBool()) return RetType(fullOptions.toBool()); if (fullOptions.isObject()) return RetType(FullSemanticTokenOptions(fullOptions.toObject())); return std::nullopt; } void SemanticTokensClientCapabilities::Requests::setFull( const std::variant &full) { insertVariant(fullKey, full); } std::optional TextDocumentClientCapabilities::semanticTokens() const { return optionalValue(semanticTokensKey); } void TextDocumentClientCapabilities::setSemanticTokens( const SemanticTokensClientCapabilities &semanticTokens) { insert(semanticTokensKey, semanticTokens); } bool SemanticTokensClientCapabilities::isValid() const { return contains(requestsKey) && contains(tokenTypesKey) && contains(tokenModifiersKey) && contains(formatsKey); } const char resourceOperationCreate[] = "create"; const char resourceOperationRename[] = "rename"; const char resourceOperationDelete[] = "delete"; std::optional> WorkspaceClientCapabilities::WorkspaceEditCapabilities::resourceOperations() const { if (!contains(resourceOperationsKey)) return std::nullopt; QList result; for (const QJsonValue &value : this->value(resourceOperationsKey).toArray()) { const QString str = value.toString(); if (str == resourceOperationCreate) result << ResourceOperationKind::Create; else if (str == resourceOperationRename) result << ResourceOperationKind::Rename; else if (str == resourceOperationDelete) result << ResourceOperationKind::Delete; } return result; } void WorkspaceClientCapabilities::WorkspaceEditCapabilities::setResourceOperations( const QList &resourceOperations) { QJsonArray array; for (const auto &kind : resourceOperations) { switch (kind) { case ResourceOperationKind::Create: array << resourceOperationCreate; break; case ResourceOperationKind::Rename: array << resourceOperationRename; break; case ResourceOperationKind::Delete: array << resourceOperationDelete; break; } } insert(resourceOperationsKey, array); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/shutdownmessages.cpp0000644000175100017510000000070115232633614021443 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "shutdownmessages.h" namespace lsp { constexpr const char ShutdownRequest::methodName[]; constexpr const char ExitNotification::methodName[]; ShutdownRequest::ShutdownRequest() : Request(methodName, nullptr) { } ExitNotification::ExitNotification() : Notification(methodName) { } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/shutdownmessages.h0000644000175100017510000000142315232633614021112 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT ShutdownRequest : public Request< std::nullptr_t, std::nullptr_t, std::nullptr_t> { public: ShutdownRequest(); using Request::Request; constexpr static const char methodName[] = "shutdown"; }; class LANGUAGESERVERPROTOCOL_EXPORT ExitNotification : public Notification { public: ExitNotification(); using Notification::Notification; constexpr static const char methodName[] = "exit"; bool parametersAreValid(QString * /*errorMessage*/) const final { return true; } }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/CMakeLists.txt0000644000175100017510000000247515232633614020106 0ustar runnerrunneradd_qbs_library(qtclsp STATIC DEPENDS Qt${QT_VERSION_MAJOR}::Core Qt6Core5Compat SOURCES algorithm.h basemessage.cpp basemessage.h callhierarchy.cpp callhierarchy.h client.cpp client.h clientcapabilities.cpp clientcapabilities.h completion.cpp completion.h diagnostics.cpp diagnostics.h initializemessages.cpp initializemessages.h jsonkeys.h jsonobject.cpp jsonobject.h jsonrpcmessages.cpp jsonrpcmessages.h languagefeatures.cpp languagefeatures.h languageserverprotocol_global.h languageserverprotocoltr.h lsptypes.cpp lsptypes.h lsputils.cpp lsputils.h messages.cpp messages.h progresssupport.cpp progresssupport.h semantictokens.cpp semantictokens.h servercapabilities.cpp servercapabilities.h shutdownmessages.cpp shutdownmessages.h textsynchronization.cpp textsynchronization.h textutils.cpp textutils.h workspace.cpp workspace.h ) target_include_directories( qtclsp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/corelib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ) target_compile_definitions(qtclsp PUBLIC "LANGUAGESERVERPROTOCOL_STATIC_LIBRARY" ) qbs-src-3.3.1/src/shared/lsp/callhierarchy.h0000644000175100017510000001027615232633614020327 0ustar runnerrunner// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyItem : public JsonObject { public: using JsonObject::JsonObject; QString name() const { return typedValue(nameKey); } void setName(const QString &name) { insert(nameKey, name); } SymbolKind symbolKind() const { return SymbolKind(typedValue(symbolKindKey)); } void setSymbolKind(const SymbolKind &symbolKind) { insert(symbolKindKey, int(symbolKind)); } Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } Range selectionRange() const { return typedValue(selectionRangeKey); } void setSelectionRange(Range selectionRange) { insert(selectionRangeKey, selectionRange); } std::optional detail() const { return optionalValue(detailKey); } void setDetail(const QString &detail) { insert(detailKey, detail); } void clearDetail() { remove(detailKey); } std::optional> children() const { return optionalArray(childrenKey); } void setChildren(const QList &children) { insertArray(childrenKey, children); } void clearChildren() { remove(childrenKey); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT PrepareCallHierarchyRequest : public Request< LanguageClientArray, std::nullptr_t, TextDocumentPositionParams> { public: explicit PrepareCallHierarchyRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/prepareCallHierarchy"; }; class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyCallsParams : public JsonObject { public: using JsonObject::JsonObject; CallHierarchyItem item() const { return typedValue(itemKey); } void setItem(const CallHierarchyItem &item) { insert(itemKey, item); } bool isValid() const override { return contains(itemKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyIncomingCall : public JsonObject { public: using JsonObject::JsonObject; CallHierarchyItem from() const { return typedValue(fromKey); } void setFrom(const CallHierarchyItem &from) { insert(fromKey, from); } QList fromRanges() const { return array(fromRangesKey); } void setFromRanges(const QList &fromRanges) { insertArray(fromRangesKey, fromRanges); } bool isValid() const override { return contains(fromRangesKey) && contains(fromRangesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyIncomingCallsRequest : public Request< LanguageClientArray, std::nullptr_t, CallHierarchyCallsParams> { public: explicit CallHierarchyIncomingCallsRequest(const CallHierarchyCallsParams ¶ms); using Request::Request; constexpr static const char methodName[] = "callHierarchy/incomingCalls"; }; class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyOutgoingCall : public JsonObject { public: using JsonObject::JsonObject; CallHierarchyItem to() const { return typedValue(toKey); } void setTo(const CallHierarchyItem &to) { insert(toKey, to); } QList fromRanges() const { return array(fromRangesKey); } void setFromRanges(const QList &fromRanges) { insertArray(fromRangesKey, fromRanges); } bool isValid() const override { return contains(fromRangesKey) && contains(fromRangesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CallHierarchyOutgoingCallsRequest : public Request< LanguageClientArray, std::nullptr_t, CallHierarchyCallsParams> { public: explicit CallHierarchyOutgoingCallsRequest(const CallHierarchyCallsParams ¶ms); using Request::Request; constexpr static const char methodName[] = "callHierarchy/outgoingCalls"; }; } // namespace lsp qbs-src-3.3.1/src/shared/lsp/lsptypes.cpp0000644000175100017510000002731515232633614017735 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "lsptypes.h" #include "languageserverprotocoltr.h" #include "lsputils.h" #include "textutils.h" #include #include #include #include #include #include namespace lsp { std::optional Diagnostic::severity() const { if (auto val = optionalValue(severityKey)) return std::make_optional(static_cast(*val)); return std::nullopt; } std::optional Diagnostic::code() const { QJsonValue codeValue = value(codeKey); auto it = find(codeKey); if (codeValue.isUndefined()) return std::nullopt; QJsonValue::Type type = it.value().type(); if (type != QJsonValue::String && type != QJsonValue::Double) return std::make_optional(Code(QString())); return std::make_optional(codeValue.isDouble() ? Code(codeValue.toInt()) : Code(codeValue.toString())); } void Diagnostic::setCode(const Diagnostic::Code &code) { insertVariant(codeKey, code); } std::optional WorkspaceEdit::changes() const { auto it = find(changesKey); if (it == end()) return std::nullopt; const QJsonObject &changesObject = it.value().toObject(); Changes changesResult; for (const QString &key : changesObject.keys()) changesResult[DocumentUri::fromProtocol(key)] = LanguageClientArray(changesObject.value(key)).toList(); return std::make_optional(changesResult); } void WorkspaceEdit::setChanges(const Changes &changes) { QJsonObject changesObject; const auto end = changes.end(); for (auto it = changes.begin(); it != end; ++it) { QJsonArray edits; for (const TextEdit &edit : it.value()) edits.append(QJsonValue(edit)); changesObject.insert(QJsonValue(it.key()).toString(), edits); } insert(changesKey, changesObject); } WorkSpaceFolder::WorkSpaceFolder(const DocumentUri &uri, const QString &name) { setUri(uri); setName(name); } MarkupOrString::MarkupOrString(const std::variant &val) : std::variant(val) { } MarkupOrString::MarkupOrString(const QString &val) : std::variant(val) { } MarkupOrString::MarkupOrString(const MarkupContent &val) : std::variant(val) { } MarkupOrString::MarkupOrString(const QJsonValue &val) { if (val.isString()) { emplace(val.toString()); } else { MarkupContent markupContent(val.toObject()); if (markupContent.isValid()) emplace(MarkupContent(val.toObject())); } } QJsonValue MarkupOrString::toJson() const { if (std::holds_alternative(*this)) return std::get(*this); if (std::holds_alternative(*this)) return QJsonValue(std::get(*this)); return {}; } QMap languageIds() { static const QMap languages({ {"Windows Bat","bat" }, {"BibTeX","bibtex" }, {"Clojure","clojure" }, {"Coffeescript","coffeescript" }, {"C","c" }, {"C++","cpp" }, {"C#","csharp" }, {"CSS","css" }, {"Diff","diff" }, {"Dockerfile","dockerfile" }, {"F#","fsharp" }, {"Git commit","git-commit" }, {"Git rebase","git-rebase" }, {"Go","go" }, {"Groovy","groovy" }, {"Handlebars","handlebars" }, {"HTML","html" }, {"Ini","ini" }, {"Java","java" }, {"JavaScript","javascript" }, {"JSON","json" }, {"LaTeX","latex" }, {"Less","less" }, {"Lua","lua" }, {"Makefile","makefile" }, {"Markdown","markdown" }, {"Objective-C","objective-c" }, {"Objective-C++","objective-cpp" }, {"Perl6","perl6" }, {"Perl","perl" }, {"PHP","php" }, {"Powershell","powershell" }, {"Pug","jade" }, {"Python","python" }, {"R","r" }, {"Razor (cshtml)","razor" }, {"Ruby","ruby" }, {"Rust","rust" }, {"Scss (syntax using curly brackets)","scss"}, {"Sass (indented syntax)","sass" }, {"ShaderLab","shaderlab" }, {"Shell Script (Bash)","shellscript" }, {"SQL","sql" }, {"Swift","swift" }, {"TypeScript","typescript" }, {"TeX","tex" }, {"Visual Basic","vb" }, {"XML","xml" }, {"XSL","xsl" }, {"YAML","yaml" } }); return languages; } bool TextDocumentItem::isValid() const { return contains(uriKey) && contains(languageIdKey) && contains(versionKey) && contains(textKey); } TextDocumentPositionParams::TextDocumentPositionParams() : TextDocumentPositionParams(TextDocumentIdentifier(), Position()) { } TextDocumentPositionParams::TextDocumentPositionParams( const TextDocumentIdentifier &document, const Position &position) { setTextDocument(document); setPosition(position); } Position::Position(int line, int character) { setLine(line); setCharacter(character); } Range::Range(const Position &start, const Position &end) { setStart(start); setEnd(end); } bool Range::contains(const Range &other) const { if (start() > other.start()) return false; if (end() < other.end()) return false; return true; } bool Range::overlaps(const Range &range) const { return !isLeftOf(range) && !range.isLeftOf(*this); } QString expressionForGlob(QString globPattern) { const QString anySubDir("qtc_anysubdir_id"); globPattern.replace("**/", anySubDir); QString regexp = QRegularExpression::wildcardToRegularExpression(globPattern); regexp.replace(anySubDir,"(.*[/\\\\])*"); regexp.replace("\\{", "("); regexp.replace("\\}", ")"); regexp.replace(",", "|"); return regexp; } bool DocumentFilter::applies(const Utils::FilePath &fileName) const { if (std::optional _pattern = pattern()) { QRegularExpression::PatternOption option = QRegularExpression::NoPatternOption; if (fileName.caseSensitivity() == Qt::CaseInsensitive) option = QRegularExpression::CaseInsensitiveOption; const QRegularExpression regexp(expressionForGlob(*_pattern), option); if (regexp.isValid() && regexp.match(fileName.toString()).hasMatch()) return true; } // return false when any of the filter didn't match but return true when no filter was defined return !contains(schemeKey) && !contains(languageKey) && !contains(patternKey); } Utils::Link Location::toLink(const DocumentUri::PathMapper &mapToHostPath) const { if (!isValid()) return Utils::Link(); return Utils::Link(uri().toFilePath(mapToHostPath), range().start().line() + 1, range().start().character()); } // Ensure %xx like %20 are really decoded using fromPercentEncoding // Else, a path with spaces would keep its %20 which would cause failure // to open the file by the text editor. This is the cases with compilers in // C:\Programs Files on Windows. DocumentUri::DocumentUri(const QString &other) : QUrl(QUrl::fromPercentEncoding(other.toUtf8())) { } DocumentUri::DocumentUri(const Utils::FilePath &other, const PathMapper &mapToServerPath) : QUrl(QUrl::fromLocalFile(mapToServerPath(other).path())) { } Utils::FilePath DocumentUri::toFilePath(const PathMapper &mapToHostPath) const { if (isLocalFile()) { const Utils::FilePath serverPath = Utils::FilePath::fromUserInput(toLocalFile()); QBS_ASSERT(mapToHostPath, return serverPath); return mapToHostPath(serverPath); } return {}; } DocumentUri DocumentUri::fromProtocol(const QString &uri) { return DocumentUri(uri); } DocumentUri DocumentUri::fromFilePath(const Utils::FilePath &file, const PathMapper &mapToServerPath) { return DocumentUri(file, mapToServerPath); } MarkupKind::MarkupKind(const QJsonValue &value) { m_value = value.toString() == "markdown" ? markdown : plaintext; } MarkupKind::operator QJsonValue() const { switch (m_value) { case MarkupKind::markdown: return "markdown"; case MarkupKind::plaintext: return "plaintext"; } return {}; } DocumentChange::DocumentChange(const QJsonValue &value) { const QString kind = value["kind"].toString(); if (kind == "create") emplace(value); else if (kind == "rename") emplace(value); else if (kind == "delete") emplace(value); else emplace(value); } using DocumentChangeBase = std::variant; bool DocumentChange::isValid() const { return std::visit([](const auto &v) { return v.isValid(); }, DocumentChangeBase(*this)); } DocumentChange::operator const QJsonValue () const { return std::visit([](const auto &v) { return QJsonValue(v); }, DocumentChangeBase(*this)); } CreateFileOperation::CreateFileOperation() { insert(kindKey, "create"); } QString CreateFileOperation::message(const DocumentUri::PathMapper &mapToHostPath) const { return Tr::tr("Create %1").arg(uri().toFilePath(mapToHostPath).toUserOutput()); } bool CreateFileOperation::isValid() const { return contains(uriKey) && value(kindKey) == "create"; } RenameFileOperation::RenameFileOperation() { insert(kindKey, "rename"); } QString RenameFileOperation::message(const DocumentUri::PathMapper &mapToHostPath) const { return Tr::tr("Rename %1 to %2") .arg(oldUri().toFilePath(mapToHostPath).toUserOutput(), newUri().toFilePath(mapToHostPath).toUserOutput()); } bool RenameFileOperation::isValid() const { return contains(oldUriKey) && contains(newUriKey) && value(kindKey) == "rename"; } DeleteFileOperation::DeleteFileOperation() { insert(kindKey, "delete"); } QString DeleteFileOperation::message(const DocumentUri::PathMapper &mapToHostPath) const { return Tr::tr("Delete %1").arg(uri().toFilePath(mapToHostPath).toUserOutput()); } bool DeleteFileOperation::isValid() const { return contains(uriKey) && value(kindKey) == "delete"; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/servercapabilities.h0000644000175100017510000004740015232633614021374 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "lsptypes.h" #include "semantictokens.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT WorkDoneProgressOptions : public JsonObject { public: using JsonObject::JsonObject; std::optional workDoneProgress() const { return optionalValue(workDoneProgressKey); } void setWorkDoneProgress(bool workDoneProgress) { insert(workDoneProgressKey, workDoneProgress); } void clearWorkDoneProgress() { remove(workDoneProgressKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ResolveProviderOption : public JsonObject { public: using JsonObject::JsonObject; std::optional resolveProvider() const { return optionalValue(resolveProviderKey); } void setResolveProvider(bool resolveProvider) { insert(resolveProviderKey, resolveProvider); } void clearResolveProvider() { remove(resolveProviderKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentRegistrationOptions : public JsonObject { public: using JsonObject::JsonObject; LanguageClientArray documentSelector() const { return clientArray(documentSelectorKey); } void setDocumentSelector(const LanguageClientArray &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } bool filterApplies(const Utils::FilePath &fileName) const; bool isValid() const override { return contains(documentSelectorKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SaveOptions : public JsonObject { public: using JsonObject::JsonObject; // The client is supposed to include the content on save. std::optional includeText() const { return optionalValue(includeTextKey); } void setIncludeText(bool includeText) { insert(includeTextKey, includeText); } void clearIncludeText() { remove(includeTextKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentSyncOptions : public JsonObject { public: using JsonObject::JsonObject; // Open and close notifications are sent to the server. std::optional openClose() const { return optionalValue(openCloseKey); } void setOpenClose(bool openClose) { insert(openCloseKey, openClose); } void clearOpenClose() { remove(openCloseKey); } // Change notifications are sent to the server. See TextDocumentSyncKind.None, // TextDocumentSyncKind.Full and TextDocumentSyncKind.Incremental. std::optional change() const { return optionalValue(changeKey); } void setChange(int change) { insert(changeKey, change); } void clearChange() { remove(changeKey); } // Will save notifications are sent to the server. std::optional willSave() const { return optionalValue(willSaveKey); } void setWillSave(bool willSave) { insert(willSaveKey, willSave); } void clearWillSave() { remove(willSaveKey); } // Will save wait until requests are sent to the server. std::optional willSaveWaitUntil() const { return optionalValue(willSaveWaitUntilKey); } void setWillSaveWaitUntil(bool willSaveWaitUntil) { insert(willSaveWaitUntilKey, willSaveWaitUntil); } void clearWillSaveWaitUntil() { remove(willSaveWaitUntilKey); } // Save notifications are sent to the server. std::optional save() const { return optionalValue(saveKey); } void setSave(const SaveOptions &save) { insert(saveKey, save); } void clearSave() { remove(saveKey); } }; enum class TextDocumentSyncKind { // Documents should not be synced at all. None = 0, // Documents are synced by always sending the full content of the document. Full = 1, // Documents are synced by sending the full content on open. // After that only incremental updates to the document are send. Incremental = 2 }; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; QList codeActionKinds() const { return array(codeActionKindsKey); } void setCodeActionKinds(const QList &codeActionKinds) { insertArray(codeActionKindsKey, codeActionKinds); } bool isValid() const override; }; enum class SemanticRequestType { None = 0x0, Full = 0x1, FullDelta = 0x2, Range = 0x4 }; Q_DECLARE_FLAGS(SemanticRequestTypes, SemanticRequestType) class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; /// The legend used by the server SemanticTokensLegend legend() const { return typedValue(legendKey); } void setLegend(const SemanticTokensLegend &legend) { insert(legendKey, legend); } /// Server supports providing semantic tokens for a specific range of a document. std::optional> range() const; void setRange(const std::variant &range); void clearRange() { remove(rangeKey); } class FullSemanticTokenOptions : public JsonObject { public: using JsonObject::JsonObject; /// The server supports deltas for full documents. std::optional delta() const { return optionalValue(deltaKey); } void setDelta(bool delta) { insert(deltaKey, delta); } void clearDelta() { remove(deltaKey); } }; /// Server supports providing semantic tokens for a full document. std::optional> full() const; void setFull(const std::variant &full); void clearFull() { remove(fullKey); } bool isValid() const override { return contains(legendKey); } SemanticRequestTypes supportedRequests() const; }; class LANGUAGESERVERPROTOCOL_EXPORT ServerCapabilities : public JsonObject { public: using JsonObject::JsonObject; // Defines how the host (editor) should sync document changes to the language server. class LANGUAGESERVERPROTOCOL_EXPORT CompletionOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; // The characters that trigger completion automatically. std::optional> triggerCharacters() const { return optionalArray(triggerCharactersKey); } void setTriggerCharacters(const QList &triggerCharacters) { insertArray(triggerCharactersKey, triggerCharacters); } void clearTriggerCharacters() { remove(triggerCharactersKey); } std::optional resolveProvider() const { return optionalValue(resolveProviderKey); } void setResolveProvider(bool resolveProvider) { insert(resolveProviderKey, resolveProvider); } void clearResolveProvider() { remove(resolveProviderKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; // The characters that trigger signature help automatically. std::optional> triggerCharacters() const { return optionalArray(triggerCharactersKey); } void setTriggerCharacters(const QList &triggerCharacters) { insertArray(triggerCharactersKey, triggerCharacters); } void clearTriggerCharacters() { remove(triggerCharactersKey); } }; using CodeLensOptions = ResolveProviderOption; class LANGUAGESERVERPROTOCOL_EXPORT DocumentOnTypeFormattingOptions : public JsonObject { public: using JsonObject::JsonObject; // A character on which formatting should be triggered, like `}`. QString firstTriggerCharacter() const { return typedValue(firstTriggerCharacterKey); } void setFirstTriggerCharacter(QString firstTriggerCharacter) { insert(firstTriggerCharacterKey, firstTriggerCharacter); } // More trigger characters. std::optional> moreTriggerCharacter() const { return optionalArray(moreTriggerCharacterKey); } void setMoreTriggerCharacter(const QList &moreTriggerCharacter) { insertArray(moreTriggerCharacterKey, moreTriggerCharacter); } void clearMoreTriggerCharacter() { remove(moreTriggerCharacterKey); } bool isValid() const override { return contains(firstTriggerCharacterKey); } }; using DocumentLinkOptions = ResolveProviderOption; class LANGUAGESERVERPROTOCOL_EXPORT ExecuteCommandOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; QList commands() const { return array(commandsKey); } void setCommands(const QList &commands) { insertArray(commandsKey, commands); } bool isValid() const override; }; using ColorProviderOptions = JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT StaticRegistrationOptions : public JsonObject { public: using JsonObject::JsonObject; // The id used to register the request. The id can be used to deregister // the request again. See also Registration#id. std::optional id() const { return optionalValue(idKey); } void setId(const QString &id) { insert(idKey, id); } void clearId() { remove(idKey); } }; // Defines how text documents are synced. Is either a detailed structure defining each // notification or for backwards compatibility the TextDocumentSyncKind number. using TextDocumentSync = std::variant; std::optional textDocumentSync() const; void setTextDocumentSync(const TextDocumentSync &textDocumentSync); void clearTextDocumentSync() { remove(textDocumentSyncKey); } TextDocumentSyncKind textDocumentSyncKindHelper(); // The server provides hover support. std::optional> hoverProvider() const; void setHoverProvider(const std::variant &hoverProvider); void clearHoverProvider() { remove(hoverProviderKey); } // The server provides completion support. std::optional completionProvider() const { return optionalValue(completionProviderKey); } void setCompletionProvider(const CompletionOptions &completionProvider) { insert(completionProviderKey, completionProvider); } void clearCompletionProvider() { remove(completionProviderKey); } // The server provides signature help support. std::optional signatureHelpProvider() const { return optionalValue(signatureHelpProviderKey); } void setSignatureHelpProvider(const SignatureHelpOptions &signatureHelpProvider) { insert(signatureHelpProviderKey, signatureHelpProvider); } void clearSignatureHelpProvider() { remove(signatureHelpProviderKey); } class LANGUAGESERVERPROTOCOL_EXPORT RegistrationOptions : public JsonObject { public: using JsonObject::JsonObject; LanguageClientArray documentSelector() const { return clientArray(documentSelectorKey); } void setDocumentSelector(const LanguageClientArray &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } bool filterApplies(const Utils::FilePath &fileName) const; // The id used to register the request. The id can be used to deregister // the request again. See also Registration#id. std::optional id() const { return optionalValue(idKey); } void setId(const QString &id) { insert(idKey, id); } void clearId() { remove(idKey); } bool isValid() const override { return contains(documentSelectorKey); } }; // The server provides goto definition support. std::optional> definitionProvider() const; void setDefinitionProvider(const std::variant &typeDefinitionProvider); void clearDefinitionProvider() { remove(typeDefinitionProviderKey); } // The server provides Goto Type Definition support. std::optional> typeDefinitionProvider() const; void setTypeDefinitionProvider(const std::variant &typeDefinitionProvider); void clearTypeDefinitionProvider() { remove(typeDefinitionProviderKey); } // The server provides Goto Implementation support. std::optional> implementationProvider() const; void setImplementationProvider(const std::variant &implementationProvider); void clearImplementationProvider() { remove(implementationProviderKey); } // The server provides find references support. std::optional> referencesProvider() const; void setReferencesProvider(const std::variant &referencesProvider); void clearReferencesProvider() { remove(referencesProviderKey); } // The server provides document highlight support. std::optional> documentHighlightProvider() const; void setDocumentHighlightProvider( const std::variant &documentHighlightProvider); void clearDocumentHighlightProvider() { remove(documentHighlightProviderKey); } // The server provides document symbol support. std::optional> documentSymbolProvider() const; void setDocumentSymbolProvider(std::variant documentSymbolProvider); void clearDocumentSymbolProvider() { remove(documentSymbolProviderKey); } std::optional semanticTokensProvider() const; void setSemanticTokensProvider(const SemanticTokensOptions &semanticTokensProvider); void clearSemanticTokensProvider() { remove(semanticTokensProviderKey); } std::optional> callHierarchyProvider() const; void setCallHierarchyProvider(const std::variant &callHierarchyProvider); void clearCallHierarchyProvider() { remove(callHierarchyProviderKey); } // The server provides workspace symbol support. std::optional> workspaceSymbolProvider() const; void setWorkspaceSymbolProvider(std::variant workspaceSymbolProvider); void clearWorkspaceSymbolProvider() { remove(workspaceSymbolProviderKey); } // The server provides code actions. std::optional> codeActionProvider() const; void setCodeActionProvider(bool codeActionProvider) { insert(codeActionProviderKey, codeActionProvider); } void setCodeActionProvider(CodeActionOptions options) { insert(codeActionProviderKey, options); } void clearCodeActionProvider() { remove(codeActionProviderKey); } // The server provides code lens. std::optional codeLensProvider() const { return optionalValue(codeLensProviderKey); } void setCodeLensProvider(CodeLensOptions codeLensProvider) { insert(codeLensProviderKey, codeLensProvider); } void clearCodeLensProvider() { remove(codeLensProviderKey); } // The server provides document formatting. std::optional> documentFormattingProvider() const; void setDocumentFormattingProvider( const std::variant &documentFormattingProvider); void clearDocumentFormattingProvider() { remove(documentFormattingProviderKey); } // The server provides document formatting on typing. std::optional> documentRangeFormattingProvider() const; void setDocumentRangeFormattingProvider(std::variant documentRangeFormattingProvider); void clearDocumentRangeFormattingProvider() { remove(documentRangeFormattingProviderKey); } class LANGUAGESERVERPROTOCOL_EXPORT RenameOptions : public WorkDoneProgressOptions { public: using WorkDoneProgressOptions::WorkDoneProgressOptions; // Renames should be checked and tested before being executed. std::optional prepareProvider() const { return optionalValue(prepareProviderKey); } void setPrepareProvider(bool prepareProvider) { insert(prepareProviderKey, prepareProvider); } void clearPrepareProvider() { remove(prepareProviderKey); } }; // The server provides rename support. std::optional> renameProvider() const; void setRenameProvider(std::variant renameProvider); void clearRenameProvider() { remove(renameProviderKey); } // The server provides document link support. std::optional documentLinkProvider() const { return optionalValue(documentLinkProviderKey); } void setDocumentLinkProvider(const DocumentLinkOptions &documentLinkProvider) { insert(documentLinkProviderKey, documentLinkProvider); } void clearDocumentLinkProvider() { remove(documentLinkProviderKey); } // The server provides color provider support. std::optional> colorProvider() const; void setColorProvider(std::variant colorProvider); void clearColorProvider() { remove(colorProviderKey); } // The server provides execute command support. std::optional executeCommandProvider() const { return optionalValue(executeCommandProviderKey); } void setExecuteCommandProvider(ExecuteCommandOptions executeCommandProvider) { insert(executeCommandProviderKey, executeCommandProvider); } void clearExecuteCommandProvider() { remove(executeCommandProviderKey); } class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceServerCapabilities : public JsonObject { public: using JsonObject::JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceFoldersCapabilities : public JsonObject { public: using JsonObject::JsonObject; // The server has support for workspace folders std::optional supported() const { return optionalValue(supportedKey); } void setSupported(bool supported) { insert(supportedKey, supported); } void clearSupported() { remove(supportedKey); } std::optional> changeNotifications() const; void setChangeNotifications(std::variant changeNotifications); void clearChangeNotifications() { remove(changeNotificationsKey); } }; std::optional workspaceFolders() const { return optionalValue(workspaceFoldersKey); } void setWorkspaceFolders(const WorkspaceFoldersCapabilities &workspaceFolders) { insert(workspaceFoldersKey, workspaceFolders); } void clearWorkspaceFolders() { remove(workspaceFoldersKey); } }; std::optional workspace() const { return optionalValue(workspaceKey); } void setWorkspace(const WorkspaceServerCapabilities &workspace) { insert(workspaceKey, workspace); } void clearWorkspace() { remove(workspaceKey); } std::optional experimental() const { return optionalValue(experimentalKey); } void setExperimental(const JsonObject &experimental) { insert(experimentalKey, experimental); } void clearExperimental() { remove(experimentalKey); } }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/servercapabilities.cpp0000644000175100017510000003541315232633614021730 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "servercapabilities.h" namespace lsp { std::optional ServerCapabilities::textDocumentSync() const { const QJsonValue &sync = value(textDocumentSyncKey); if (sync.isUndefined()) return std::nullopt; return std::make_optional(sync.isDouble() ? TextDocumentSync(sync.toInt()) : TextDocumentSync(TextDocumentSyncOptions(sync.toObject()))); } void ServerCapabilities::setTextDocumentSync(const ServerCapabilities::TextDocumentSync &textDocumentSync) { insertVariant(textDocumentSyncKey, textDocumentSync); } TextDocumentSyncKind ServerCapabilities::textDocumentSyncKindHelper() { if (std::optional sync = textDocumentSync()) { if (auto kind = std::get_if(&*sync)) return static_cast(*kind); if (auto options = std::get_if(&*sync)) { if (const std::optional &change = options->change()) return static_cast(*change); } } return TextDocumentSyncKind::None; } std::optional> ServerCapabilities::hoverProvider() const { using RetType = std::variant; const QJsonValue &provider = value(hoverProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setHoverProvider( const std::variant &hoverProvider) { insertVariant(hoverProviderKey, hoverProvider); } std::optional> ServerCapabilities::definitionProvider() const { using RetType = std::variant; const QJsonValue &provider = value(definitionProviderKey); if (provider.isUndefined() || !(provider.isBool() || provider.isObject())) return std::nullopt; return std::make_optional(provider.isBool() ? RetType(provider.toBool()) : RetType(RegistrationOptions(provider.toObject()))); } void ServerCapabilities::setDefinitionProvider( const std::variant &definitionProvider) { insertVariant(definitionProviderKey, definitionProvider); } std::optional> ServerCapabilities::typeDefinitionProvider() const { using RetType = std::variant; const QJsonValue &provider = value(typeDefinitionProviderKey); if (provider.isUndefined() || !(provider.isBool() || provider.isObject())) return std::nullopt; return std::make_optional(provider.isBool() ? RetType(provider.toBool()) : RetType(RegistrationOptions(provider.toObject()))); } void ServerCapabilities::setTypeDefinitionProvider( const std::variant &typeDefinitionProvider) { insertVariant(typeDefinitionProviderKey, typeDefinitionProvider); } std::optional> ServerCapabilities::implementationProvider() const { using RetType = std::variant; const QJsonValue &provider = value(implementationProviderKey); if (provider.isUndefined() || !(provider.isBool() || provider.isObject())) return std::nullopt; return std::make_optional(provider.isBool() ? RetType(provider.toBool()) : RetType(RegistrationOptions(provider.toObject()))); } void ServerCapabilities::setImplementationProvider( const std::variant &implementationProvider) { insertVariant(implementationProviderKey, implementationProvider); } std::optional> ServerCapabilities::referencesProvider() const { using RetType = std::variant; const QJsonValue &provider = value(referencesProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setReferencesProvider( const std::variant &referencesProvider) { insertVariant(referencesProviderKey, referencesProvider); } std::optional> ServerCapabilities::documentHighlightProvider() const { using RetType = std::variant; const QJsonValue &provider = value(documentHighlightProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setDocumentHighlightProvider( const std::variant &documentHighlightProvider) { insertVariant(documentHighlightProviderKey, documentHighlightProvider); } std::optional> ServerCapabilities::documentSymbolProvider() const { using RetType = std::variant; const QJsonValue &provider = value(documentSymbolProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setDocumentSymbolProvider( std::variant documentSymbolProvider) { insertVariant(documentSymbolProviderKey, documentSymbolProvider); } std::optional ServerCapabilities::semanticTokensProvider() const { return optionalValue(semanticTokensProviderKey); } void ServerCapabilities::setSemanticTokensProvider( const SemanticTokensOptions &semanticTokensProvider) { insert(semanticTokensProviderKey, semanticTokensProvider); } std::optional > ServerCapabilities::callHierarchyProvider() const { const QJsonValue &provider = value(callHierarchyProviderKey); if (provider.isBool()) return provider.toBool(); else if (provider.isObject()) return WorkDoneProgressOptions(provider.toObject()); return std::nullopt; } void ServerCapabilities::setCallHierarchyProvider( const std::variant &callHierarchyProvider) { QJsonValue val; if (std::holds_alternative(callHierarchyProvider)) val = std::get(callHierarchyProvider); else if (std::holds_alternative(callHierarchyProvider)) val = QJsonObject(std::get(callHierarchyProvider)); insert(callHierarchyProviderKey, val); } std::optional> ServerCapabilities::workspaceSymbolProvider() const { using RetType = std::variant; const QJsonValue &provider = value(workspaceSymbolProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setWorkspaceSymbolProvider( std::variant workspaceSymbolProvider) { insertVariant(workspaceSymbolProviderKey, workspaceSymbolProvider); } std::optional> ServerCapabilities::codeActionProvider() const { const QJsonValue &provider = value(codeActionProviderKey); if (provider.isBool()) return std::make_optional(std::variant(provider.toBool())); if (provider.isObject()) { CodeActionOptions options(provider); if (options.isValid()) return std::make_optional(std::variant(options)); } return std::nullopt; } std::optional> ServerCapabilities::documentFormattingProvider() const { using RetType = std::variant; const QJsonValue &provider = value(documentFormattingProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setDocumentFormattingProvider( const std::variant &documentFormattingProvider) { insertVariant(documentFormattingProviderKey, documentFormattingProvider); } std::optional> ServerCapabilities::documentRangeFormattingProvider() const { using RetType = std::variant; const QJsonValue &provider = value(documentRangeFormattingProviderKey); if (provider.isBool()) return std::make_optional(RetType(provider.toBool())); if (provider.isObject()) return std::make_optional(RetType(WorkDoneProgressOptions(provider.toObject()))); return std::nullopt; } void ServerCapabilities::setDocumentRangeFormattingProvider( std::variant documentRangeFormattingProvider) { insertVariant(documentRangeFormattingProviderKey, documentRangeFormattingProvider); } std::optional> ServerCapabilities::renameProvider() const { using RetType = std::variant; const QJsonValue &localValue = value(renameProviderKey); if (localValue.isBool()) return RetType(localValue.toBool()); if (localValue.isObject()) return RetType(RenameOptions(localValue.toObject())); return std::nullopt; } void ServerCapabilities::setRenameProvider(std::variant renameProvider) { insertVariant(renameProviderKey, renameProvider); } std::optional> ServerCapabilities::colorProvider() const { using RetType = std::variant; const QJsonValue &localValue = value(colorProviderKey); if (localValue.isBool()) return RetType(localValue.toBool()); if (localValue.isObject()) return RetType(JsonObject(localValue.toObject())); return std::nullopt; } void ServerCapabilities::setColorProvider(std::variant colorProvider) { insertVariant(renameProviderKey, colorProvider); } std::optional > ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabilities::changeNotifications() const { using RetType = std::variant; const QJsonValue &change = value(changeNotificationsKey); if (change.isUndefined()) return std::nullopt; return std::make_optional(change.isBool() ? RetType(change.toBool()) : RetType(change.toString())); } void ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabilities::setChangeNotifications( std::variant changeNotifications) { insertVariant(changeNotificationsKey, changeNotifications); } bool TextDocumentRegistrationOptions::filterApplies(const Utils::FilePath &fileName) const { Q_UNUSED(fileName) return true; } bool ServerCapabilities::ExecuteCommandOptions::isValid() const { return WorkDoneProgressOptions::isValid() && contains(commandsKey); } bool CodeActionOptions::isValid() const { return WorkDoneProgressOptions::isValid() && contains(codeActionKindsKey); } std::optional> SemanticTokensOptions::range() const { using RetType = std::variant; const QJsonValue &rangeOptions = value(rangeKey); if (rangeOptions.isBool()) return RetType(rangeOptions.toBool()); if (rangeOptions.isObject()) return RetType(rangeOptions.toObject()); return std::nullopt; } void SemanticTokensOptions::setRange(const std::variant &range) { insertVariant(rangeKey, range); } std::optional> SemanticTokensOptions::full() const { using RetType = std::variant; const QJsonValue &fullOptions = value(fullKey); if (fullOptions.isBool()) return RetType(fullOptions.toBool()); if (fullOptions.isObject()) return RetType(FullSemanticTokenOptions(fullOptions.toObject())); return std::nullopt; } void SemanticTokensOptions::setFull( const std::variant &full) { insertVariant(fullKey, full); } SemanticRequestTypes SemanticTokensOptions::supportedRequests() const { SemanticRequestTypes result; QJsonValue rangeValue = value(rangeKey); if (rangeValue.isObject() || rangeValue.toBool()) result |= SemanticRequestType::Range; QJsonValue fullValue = value(fullKey); if (fullValue.isObject()) { SemanticTokensOptions::FullSemanticTokenOptions options(fullValue.toObject()); if (options.delta().value_or(false)) result |= SemanticRequestType::FullDelta; result |= SemanticRequestType::Full; } else if (fullValue.toBool()) { result |= SemanticRequestType::Full; } return result; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/clientcapabilities.h0000644000175100017510000007710215232633614021346 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonkeys.h" #include "lsptypes.h" #include "semantictokens.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT DynamicRegistrationCapabilities : public JsonObject { public: using JsonObject::JsonObject; std::optional dynamicRegistration() const { return optionalValue(dynamicRegistrationKey); } void setDynamicRegistration(bool dynamicRegistration) { insert(dynamicRegistrationKey, dynamicRegistration); } void clearDynamicRegistration() { remove(dynamicRegistrationKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT FullSemanticTokenOptions : public JsonObject { public: using JsonObject::JsonObject; /** * The client will send the `textDocument/semanticTokens/full/delta` * request if the server provides a corresponding handler. */ std::optional delta() const { return optionalValue(deltaKey); } void setDelta(bool delta) { insert(deltaKey, delta); } void clearDelta() { remove(deltaKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensClientCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; class LANGUAGESERVERPROTOCOL_EXPORT Requests : public JsonObject { /** * Which requests the client supports and might send to the server * depending on the server's capability. Please note that clients might not * show semantic tokens or degrade some of the user experience if a range * or full request is advertised by the client but not provided by the * server. If for example the client capability `requests.full` and * `request.range` are both set to true but the server only provides a * range provider the client might not render a minimap correctly or might * even decide to not show any semantic tokens at all. */ public: using JsonObject::JsonObject; /** * The client will send the `textDocument/semanticTokens/range` request * if the server provides a corresponding handler. */ std::optional> range() const; void setRange(const std::variant &range); void clearRange() { remove(rangeKey); } /** * The client will send the `textDocument/semanticTokens/full` request * if the server provides a corresponding handler. */ std::optional> full() const; void setFull(const std::variant &full); void clearFull() { remove(fullKey); } }; Requests requests() const { return typedValue(requestsKey); } void setRequests(const Requests &requests) { insert(requestsKey, requests); } /// The token types that the client supports. QList tokenTypes() const { return array(tokenTypesKey); } void setTokenTypes(const QList &value) { insertArray(tokenTypesKey, value); } /// The token modifiers that the client supports. QList tokenModifiers() const { return array(tokenModifiersKey); } void setTokenModifiers(const QList &value) { insertArray(tokenModifiersKey, value); } /// The formats the clients supports. QList formats() const { return array(formatsKey); } void setFormats(const QList &value) { insertArray(formatsKey, value); } /// Whether the client supports tokens that can overlap each other. std::optional overlappingTokenSupport() const { return optionalValue(overlappingTokenSupportKey); } void setOverlappingTokenSupport(bool overlappingTokenSupport) { insert(overlappingTokenSupportKey, overlappingTokenSupport); } void clearOverlappingTokenSupport() { remove(overlappingTokenSupportKey); } /// Whether the client supports tokens that can span multiple lines. std::optional multiLineTokenSupport() const { return optionalValue(multiLineTokenSupportKey); } void setMultiLineTokenSupport(bool multiLineTokenSupport) { insert(multiLineTokenSupportKey, multiLineTokenSupport); } void clearMultiLineTokenSupport() { remove(multiLineTokenSupportKey); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT SymbolCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; class LANGUAGESERVERPROTOCOL_EXPORT SymbolKindCapabilities : public JsonObject { public: using JsonObject::JsonObject; /* * The symbol kind values the client supports. When this * property exists the client also guarantees that it will * handle values outside its set gracefully and falls back * to a default value when unknown. * * If this property is not present the client only supports * the symbol kinds from `File` to `Array` as defined in * the initial version of the protocol. */ std::optional> valueSet() const; void setValueSet(const QList &valueSet); void clearValueSet() { remove(valueSetKey); } }; // Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. std::optional symbolKind() const { return optionalValue(symbolKindKey); } void setSymbolKind(const SymbolKindCapabilities &symbolKind) { insert(symbolKindKey, symbolKind); } void clearSymbolKind() { remove(symbolKindKey); } std::optional hierarchicalDocumentSymbolSupport() const { return optionalValue(hierarchicalDocumentSymbolSupportKey); } void setHierarchicalDocumentSymbolSupport(bool hierarchicalDocumentSymbolSupport) { insert(hierarchicalDocumentSymbolSupportKey, hierarchicalDocumentSymbolSupport); } void clearHierachicalDocumentSymbolSupport() { remove(hierarchicalDocumentSymbolSupportKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentClientCapabilities : public JsonObject { public: using JsonObject::JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT SynchronizationCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; // The client supports sending will save notifications. std::optional willSave() const { return optionalValue(willSaveKey); } void setWillSave(bool willSave) { insert(willSaveKey, willSave); } void clearWillSave() { remove(willSaveKey); } /* * The client supports sending a will save request and * waits for a response providing text edits which will * be applied to the document before it is saved. */ std::optional willSaveWaitUntil() const { return optionalValue(willSaveWaitUntilKey); } void setWillSaveWaitUntil(bool willSaveWaitUntil) { insert(willSaveWaitUntilKey, willSaveWaitUntil); } void clearWillSaveWaitUntil() { remove(willSaveWaitUntilKey); } // The client supports did save notifications. std::optional didSave() const { return optionalValue(didSaveKey); } void setDidSave(bool didSave) { insert(didSaveKey, didSave); } void clearDidSave() { remove(didSaveKey); } }; std::optional synchronization() const { return optionalValue(synchronizationKey); } void setSynchronization(const SynchronizationCapabilities &synchronization) { insert(synchronizationKey, synchronization); } void clearSynchronization() { remove(synchronizationKey); } class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemCapbilities : public JsonObject { public: using JsonObject::JsonObject; /* * Client supports snippets as insert text. * * A snippet can define tab stops and placeholders with `$1`, `$2` * and `${3:foo}`. `$0` defines the final tab stop, it defaults to * the end of the snippet. Placeholders with equal identifiers are linked, * that is typing in one will update others too. */ std::optional snippetSupport() const { return optionalValue(snippetSupportKey); } void setSnippetSupport(bool snippetSupport) { insert(snippetSupportKey, snippetSupport); } void clearSnippetSupport() { remove(snippetSupportKey); } // Client supports commit characters on a completion item. std::optional commitCharacterSupport() const { return optionalValue(commitCharacterSupportKey); } void setCommitCharacterSupport(bool commitCharacterSupport) { insert(commitCharacterSupportKey, commitCharacterSupport); } void clearCommitCharacterSupport() { remove(commitCharacterSupportKey); } /* * Client supports the follow content formats for the documentation * property. The order describes the preferred format of the client. */ std::optional> documentationFormat() const; void setDocumentationFormat(const QList &documentationFormat); void clearDocumentationFormat() { remove(documentationFormatKey); } }; // The client supports the following `CompletionItem` specific capabilities. std::optional completionItem() const { return optionalValue(completionItemKey); } void setCompletionItem(const CompletionItemCapbilities &completionItem) { insert(completionItemKey, completionItem); } void clearCompletionItem() { remove(completionItemKey); } class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemKindCapabilities : public JsonObject { public: CompletionItemKindCapabilities(); using JsonObject::JsonObject; /* * The completion item kind values the client supports. When this * property exists the client also guarantees that it will * handle values outside its set gracefully and falls back * to a default value when unknown. * * If this property is not present the client only supports * the completion items kinds from `Text` to `Reference` as defined in * the initial version of the protocol. */ std::optional> valueSet() const; void setValueSet(const QList &valueSet); void clearValueSet() { remove(valueSetKey); } }; std::optional completionItemKind() const { return optionalValue(completionItemKindKey); } void setCompletionItemKind(const CompletionItemKindCapabilities &completionItemKind) { insert(completionItemKindKey, completionItemKind); } void clearCompletionItemKind() { remove(completionItemKindKey); } /* * The client supports to send additional context information for a * `textDocument/completion` request. */ std::optional contextSupport() const { return optionalValue(contextSupportKey); } void setContextSupport(bool contextSupport) { insert(contextSupportKey, contextSupport); } void clearContextSupport() { remove(contextSupportKey); } }; // Capabilities specific to the `textDocument/completion` std::optional completion() const { return optionalValue(completionKey); } void setCompletion(const CompletionCapabilities &completion) { insert(completionKey, completion); } void clearCompletion() { remove(completionKey); } class LANGUAGESERVERPROTOCOL_EXPORT HoverCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; /* * Client supports the follow content formats for the content * property. The order describes the preferred format of the client. */ std::optional> contentFormat() const; void setContentFormat(const QList &contentFormat); void clearContentFormat() { remove(contentFormatKey); } }; std::optional hover() const { return optionalValue(hoverKey); } void setHover(const HoverCapabilities &hover) { insert(hoverKey, hover); } void clearHover() { remove(hoverKey); } class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; class LANGUAGESERVERPROTOCOL_EXPORT SignatureInformationCapabilities : public JsonObject { public: using JsonObject::JsonObject; /* * Client supports the follow content formats for the documentation * property. The order describes the preferred format of the client. */ std::optional> documentationFormat() const; void setDocumentationFormat(const QList &documentationFormat); void clearDocumentationFormat() { remove(documentationFormatKey); } std::optional activeParameterSupport() const { return optionalValue(activeParameterSupportKey); } void setActiveParameterSupport(bool activeParameterSupport) { insert(activeParameterSupportKey, activeParameterSupport); } void clearActiveParameterSupport() { remove(activeParameterSupportKey); } }; // The client supports the following `SignatureInformation` specific properties. std::optional signatureInformation() const { return optionalValue(signatureInformationKey); } void setSignatureInformation(const SignatureInformationCapabilities &signatureInformation) { insert(signatureInformationKey, signatureInformation); } void clearSignatureInformation() { remove(signatureInformationKey); } }; // Capabilities specific to the `textDocument/signatureHelp` std::optional signatureHelp() const { return optionalValue(signatureHelpKey); } void setSignatureHelp(const SignatureHelpCapabilities &signatureHelp) { insert(signatureHelpKey, signatureHelp); } void clearSignatureHelp() { remove(signatureHelpKey); } // Whether references supports dynamic registration. std::optional references() const { return optionalValue(referencesKey); } void setReferences(const DynamicRegistrationCapabilities &references) { insert(referencesKey, references); } void clearReferences() { remove(referencesKey); } // Whether document highlight supports dynamic registration. std::optional documentHighlight() const { return optionalValue(documentHighlightKey); } void setDocumentHighlight(const DynamicRegistrationCapabilities &documentHighlight) { insert(documentHighlightKey, documentHighlight); } void clearDocumentHighlight() { remove(documentHighlightKey); } // Capabilities specific to the `textDocument/documentSymbol` std::optional documentSymbol() const { return optionalValue(documentSymbolKey); } void setDocumentSymbol(const SymbolCapabilities &documentSymbol) { insert(documentSymbolKey, documentSymbol); } void clearDocumentSymbol() { remove(documentSymbolKey); } // Whether formatting supports dynamic registration. std::optional formatting() const { return optionalValue(formattingKey); } void setFormatting(const DynamicRegistrationCapabilities &formatting) { insert(formattingKey, formatting); } void clearFormatting() { remove(formattingKey); } // Whether range formatting supports dynamic registration. std::optional rangeFormatting() const { return optionalValue(rangeFormattingKey); } void setRangeFormatting(const DynamicRegistrationCapabilities &rangeFormatting) { insert(rangeFormattingKey, rangeFormatting); } void clearRangeFormatting() { remove(rangeFormattingKey); } // Whether on type formatting supports dynamic registration. std::optional onTypeFormatting() const { return optionalValue(onTypeFormattingKey); } void setOnTypeFormatting(const DynamicRegistrationCapabilities &onTypeFormatting) { insert(onTypeFormattingKey, onTypeFormatting); } void clearOnTypeFormatting() { remove(onTypeFormattingKey); } // Whether definition supports dynamic registration. std::optional definition() const { return optionalValue(definitionKey); } void setDefinition(const DynamicRegistrationCapabilities &definition) { insert(definitionKey, definition); } void clearDefinition() { remove(definitionKey); } /* * Whether typeDefinition supports dynamic registration. If this is set to `true` * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` * return value for the corresponding server capability as well. */ std::optional typeDefinition() const { return optionalValue(typeDefinitionKey); } void setTypeDefinition(const DynamicRegistrationCapabilities &typeDefinition) { insert(typeDefinitionKey, typeDefinition); } void clearTypeDefinition() { remove(typeDefinitionKey); } /* * Whether implementation supports dynamic registration. If this is set to `true` * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` * return value for the corresponding server capability as well. */ std::optional implementation() const { return optionalValue(implementationKey); } void setImplementation(const DynamicRegistrationCapabilities &implementation) { insert(implementationKey, implementation); } void clearImplementation() { remove(implementationKey); } class LANGUAGESERVERPROTOCOL_EXPORT CodeActionCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionLiteralSupport : public JsonObject { public: using JsonObject::JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionKind : public JsonObject { public: using JsonObject::JsonObject; CodeActionKind() : CodeActionKind(QList()) {} explicit CodeActionKind(const QList &kinds) { setValueSet(kinds); } QList valueSet() const { return array(valueSetKey); } void setValueSet(const QList &valueSet) { insertArray(valueSetKey, valueSet); } bool isValid() const override { return contains(valueSetKey); } }; CodeActionKind codeActionKind() const { return typedValue(codeActionKindKey); } void setCodeActionKind(const CodeActionKind &codeActionKind) { insert(codeActionKindKey, codeActionKind); } bool isValid() const override { return contains(codeActionKindKey); } }; std::optional codeActionLiteralSupport() const { return optionalValue(codeActionLiteralSupportKey); } void setCodeActionLiteralSupport(const CodeActionLiteralSupport &codeActionLiteralSupport) { insert(codeActionLiteralSupportKey, codeActionLiteralSupport); } void clearCodeActionLiteralSupport() { remove(codeActionLiteralSupportKey); } }; // Whether code action supports dynamic registration. std::optional codeAction() const { return optionalValue(codeActionKey); } void setCodeAction(const CodeActionCapabilities &codeAction) { insert(codeActionKey, codeAction); } void clearCodeAction() { remove(codeActionKey); } // Whether code lens supports dynamic registration. std::optional codeLens() const { return optionalValue(codeLensKey); } void setCodeLens(const DynamicRegistrationCapabilities &codeLens) { insert(codeLensKey, codeLens); } void clearCodeLens() { remove(codeLensKey); } // Whether document link supports dynamic registration. std::optional documentLink() const { return optionalValue(documentLinkKey); } void setDocumentLink(const DynamicRegistrationCapabilities &documentLink) { insert(documentLinkKey, documentLink); } void clearDocumentLink() { remove(documentLinkKey); } /* * Whether colorProvider supports dynamic registration. If this is set to `true` * the client supports the new `(ColorProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)` * return value for the corresponding server capability as well. */ std::optional colorProvider() const { return optionalValue(colorProviderKey); } void setColorProvider(const DynamicRegistrationCapabilities &colorProvider) { insert(colorProviderKey, colorProvider); } void clearColorProvider() { remove(colorProviderKey); } class LANGUAGESERVERPROTOCOL_EXPORT RenameClientCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; /** * Client supports testing for validity of rename operations * before execution. * * @since version 3.12.0 */ std::optional prepareSupport() const { return optionalValue(prepareSupportKey); } void setPrepareSupport(bool prepareSupport) { insert(prepareSupportKey, prepareSupport); } void clearPrepareSupport() { remove(prepareSupportKey); } }; // Whether rename supports dynamic registration. std::optional rename() const { return optionalValue(renameKey); } void setRename(const RenameClientCapabilities &rename) { insert(renameKey, rename); } void clearRename() { remove(renameKey); } std::optional semanticTokens() const; void setSemanticTokens(const SemanticTokensClientCapabilities &semanticTokens); void clearSemanticTokens() { remove(semanticTokensKey); } std::optional callHierarchy() const { return optionalValue(callHierarchyKey); } void setCallHierarchy(const DynamicRegistrationCapabilities &callHierarchy) { insert(callHierarchyKey, callHierarchy); } void clearCallHierarchy() { remove(callHierarchyKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensWorkspaceClientCapabilities : public JsonObject { public: using JsonObject::JsonObject; /** * Whether the client implementation supports a refresh request sent from * the server to the client. * * Note that this event is global and will force the client to refresh all * semantic tokens currently shown. It should be used with absolute care * and is useful for situation where a server for example detect a project * wide change that requires such a calculation. */ std::optional refreshSupport() const { return optionalValue(refreshSupportKey); } void setRefreshSupport(bool refreshSupport) { insert(refreshSupportKey, refreshSupport); } void clearRefreshSupport() { remove(refreshSupportKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceClientCapabilities : public JsonObject { public: WorkspaceClientCapabilities(); using JsonObject::JsonObject; /* * The client supports applying batch edits to the workspace by supporting the request * 'workspace/applyEdit' */ std::optional applyEdit() const { return optionalValue(applyEditKey); } void setApplyEdit(bool applyEdit) { insert(applyEditKey, applyEdit); } void clearApplyEdit() { remove(applyEditKey); } class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceEditCapabilities : public JsonObject { public: using JsonObject::JsonObject; // The client supports versioned document changes in `WorkspaceEdit`s std::optional documentChanges() const { return optionalValue(documentChangesKey); } void setDocumentChanges(bool documentChanges) { insert(documentChangesKey, documentChanges); } void clearDocumentChanges() { remove(documentChangesKey); } enum class ResourceOperationKind { Create, Rename, Delete }; // The resource operations the client supports. Clients should at least support 'create', // 'rename' and 'delete' files and folders. std::optional> resourceOperations() const; void setResourceOperations(const QList &resourceOperations); void clearResourceOperations() { remove(resourceOperationsKey); } }; // Capabilities specific to `WorkspaceEdit`s std::optional workspaceEdit() const { return optionalValue(workspaceEditKey); } void setWorkspaceEdit(const WorkspaceEditCapabilities &workspaceEdit) { insert(workspaceEditKey, workspaceEdit); } void clearWorkspaceEdit() { remove(workspaceEditKey); } // Capabilities specific to the `workspace/didChangeConfiguration` notification. std::optional didChangeConfiguration() const { return optionalValue(didChangeConfigurationKey); } void setDidChangeConfiguration(const DynamicRegistrationCapabilities &didChangeConfiguration) { insert(didChangeConfigurationKey, didChangeConfiguration); } void clearDidChangeConfiguration() { remove(didChangeConfigurationKey); } // Capabilities specific to the `workspace/didChangeWatchedFiles` notification. std::optional didChangeWatchedFiles() const { return optionalValue(didChangeWatchedFilesKey); } void setDidChangeWatchedFiles(const DynamicRegistrationCapabilities &didChangeWatchedFiles) { insert(didChangeWatchedFilesKey, didChangeWatchedFiles); } void clearDidChangeWatchedFiles() { remove(didChangeWatchedFilesKey); } // Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. std::optional symbol() const { return optionalValue(symbolKey); } void setSymbol(const SymbolCapabilities &symbol) { insert(symbolKey, symbol); } void clearSymbol() { remove(symbolKey); } // Capabilities specific to the `workspace/executeCommand` request. std::optional executeCommand() const { return optionalValue(executeCommandKey); } void setExecuteCommand(const DynamicRegistrationCapabilities &executeCommand) { insert(executeCommandKey, executeCommand); } void clearExecuteCommand() { remove(executeCommandKey); } // The client has support for workspace folders. Since 3.6.0 std::optional workspaceFolders() const { return optionalValue(workspaceFoldersKey); } void setWorkspaceFolders(bool workspaceFolders) { insert(workspaceFoldersKey, workspaceFolders); } void clearWorkspaceFolders() { remove(workspaceFoldersKey); } // The client supports `workspace/configuration` requests. Since 3.6.0 std::optional configuration() const { return optionalValue(configurationKey); } void setConfiguration(bool configuration) { insert(configurationKey, configuration); } void clearConfiguration() { remove(configurationKey); } std::optional semanticTokens() const { return optionalValue(semanticTokensKey); } void setSemanticTokens(const SemanticTokensWorkspaceClientCapabilities &semanticTokens) { insert(semanticTokensKey, semanticTokens); } void clearSemanticTokens() { remove(semanticTokensKey); } }; class WindowClientClientCapabilities : public JsonObject { public: using JsonObject::JsonObject; /** * Whether client supports handling progress notifications. * If set, servers are allowed to report in `workDoneProgress` property * in the request specific server capabilities. * */ std::optional workDoneProgress() const { return optionalValue(workDoneProgressKey); } void setWorkDoneProgress(bool workDoneProgress) { insert(workDoneProgressKey, workDoneProgress); } void clearWorkDoneProgress() { remove(workDoneProgressKey); } private: constexpr static const char workDoneProgressKey[] = "workDoneProgress"; }; class LANGUAGESERVERPROTOCOL_EXPORT ClientCapabilities : public JsonObject { public: using JsonObject::JsonObject; // Workspace specific client capabilities. std::optional workspace() const { return optionalValue(workspaceKey); } void setWorkspace(const WorkspaceClientCapabilities &workspace) { insert(workspaceKey, workspace); } void clearWorkspace() { remove(workspaceKey); } // Text document specific client capabilities. std::optional textDocument() const { return optionalValue(textDocumentKey); } void setTextDocument(const TextDocumentClientCapabilities &textDocument) { insert(textDocumentKey, textDocument); } void clearTextDocument() { remove(textDocumentKey); } // Window specific client capabilities. std::optional window() const { return optionalValue(windowKey); } void setWindow(const WindowClientClientCapabilities &window) { insert(windowKey, window); } void clearWindow() { remove(windowKey); } // Experimental client capabilities. QJsonValue experimental() const { return value(experimentalKey); } void setExperimental(const QJsonValue &experimental) { insert(experimentalKey, experimental); } void clearExperimental() { remove(experimentalKey); } }; } // namespace lsp qbs-src-3.3.1/src/shared/lsp/jsonobject.cpp0000644000175100017510000000137415232633614020207 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "jsonobject.h" #include namespace lsp { JsonObject &JsonObject::operator=(const JsonObject &other) = default; JsonObject &JsonObject::operator=(JsonObject &&other) { m_jsonObject.swap(other.m_jsonObject); return *this; } QJsonObject::iterator JsonObject::insert(const std::string_view key, const JsonObject &object) { return m_jsonObject.insert(QLatin1String(key.data()), object.m_jsonObject); } QJsonObject::iterator JsonObject::insert(const std::string_view key, const QJsonValue &value) { return m_jsonObject.insert(QLatin1String(key.data()), value); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/lsputils.h0000644000175100017510000001062215232633614017367 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "languageserverprotocol_global.h" #include #include #include #include #include namespace lsp { LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(conversionLog) template T fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isObject()) qCDebug(conversionLog) << "Expected Object in json value but got: " << value; T result(value.toObject()); if (conversionLog().isDebugEnabled() && !result.isValid()) qCDebug(conversionLog) << typeid(result).name() << " is not valid: " << result; return result; } template<> LANGUAGESERVERPROTOCOL_EXPORT QString fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT int fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT double fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT bool fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT QJsonObject fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT QJsonArray fromJsonValue(const QJsonValue &value); template<> LANGUAGESERVERPROTOCOL_EXPORT QJsonValue fromJsonValue(const QJsonValue &value); template class LanguageClientArray : public std::variant, std::nullptr_t> { public: using std::variant, std::nullptr_t>::variant; using std::variant, std::nullptr_t>::operator=; LanguageClientArray() {} explicit LanguageClientArray(const QList &list) { *this = list; } explicit LanguageClientArray(const QJsonValue &value) { if (value.isArray()) { QList values; values.reserve(value.toArray().count()); for (auto arrayValue : value.toArray()) values << fromJsonValue(arrayValue); *this = values; } else { *this = nullptr; } } QJsonValue toJson() const { if (const auto list = std::get_if>(this)) { QJsonArray array; for (const T &value : *list) array.append(QJsonValue(value)); return array; } return QJsonValue(); } QList toListOrEmpty() const { if (std::holds_alternative>(*this)) return std::get>(*this); return {}; } QList toList() const { QBS_ASSERT(std::holds_alternative>(*this), return {}); return std::get>(*this); } bool isNull() const { return std::holds_alternative(*this); } }; template class LanguageClientValue : public std::variant { public: using std::variant::operator=; LanguageClientValue() : std::variant(nullptr) { } LanguageClientValue(const T &value) : std::variant(value) { } LanguageClientValue(const QJsonValue &value) { if (!QBS_GUARD(!value.isUndefined()) || value.isNull()) *this = nullptr; else *this = fromJsonValue(value); } operator const QJsonValue() const { if (auto val = std::get_if(this)) return QJsonValue(*val); return QJsonValue(); } T value(const T &defaultValue = T()) const { QBS_ASSERT(std::holds_alternative(*this), return defaultValue); return std::get(*this); } template LanguageClientValue transform() { QBS_ASSERT(!std::holds_alternative(*this), return LanguageClientValue()); return Type(std::get(*this)); } bool isNull() const { return std::holds_alternative(*this); } }; template QJsonArray enumArrayToJsonArray(const QList &values) { QJsonArray array; for (T value : values) array.append(static_cast(value)); return array; } template QList jsonArrayToList(const QJsonArray &array) { QList list; for (const QJsonValue &val : array) list << fromJsonValue(val); return list; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/initializemessages.cpp0000644000175100017510000001104415232633614021733 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "initializemessages.h" #include namespace lsp { constexpr const char InitializeRequest::methodName[]; constexpr const char InitializeNotification::methodName[]; constexpr Trace::Values s_trace = Trace::off; Trace Trace::fromString(const QString &val) { if (val == "messages") return messages; if (val == "verbose") return verbose; return off; } #define RETURN_CASE(name) case Trace::name: return QString(#name); QString Trace::toString() const { switch (m_value) { RETURN_CASE(off); RETURN_CASE(messages); RETURN_CASE(verbose); } return QString("off"); } #undef RETURN_CASE std::optional> TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities:: documentationFormat() const { return optionalArray(documentationFormatKey); } void TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities:: setDocumentationFormat(const QList &documentationFormat) { insertArray(documentationFormatKey, documentationFormat); } TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities::CompletionItemKindCapabilities() { setValueSet({CompletionItemKind::Text, CompletionItemKind::Method, CompletionItemKind::Function, CompletionItemKind::Constructor, CompletionItemKind::Field, CompletionItemKind::Variable, CompletionItemKind::Class, CompletionItemKind::Interface, CompletionItemKind::Module, CompletionItemKind::Property, CompletionItemKind::Unit, CompletionItemKind::Value, CompletionItemKind::Enum, CompletionItemKind::Keyword, CompletionItemKind::Snippet, CompletionItemKind::Color, CompletionItemKind::File, CompletionItemKind::Reference, CompletionItemKind::Folder, CompletionItemKind::EnumMember, CompletionItemKind::Constant, CompletionItemKind::Struct, CompletionItemKind::Event, CompletionItemKind::Operator, CompletionItemKind::TypeParameter}); } std::optional> TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities:: valueSet() const { if (std::optional> array = optionalArray(valueSetKey)) { return std::make_optional(Utils::transform(*array, [](int value) { return static_cast(value); })); } return std::nullopt; } void TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities:: setValueSet(const QList &valueSet) { insert(valueSetKey, enumArrayToJsonArray(valueSet)); } std::optional > TextDocumentClientCapabilities::HoverCapabilities::contentFormat() const { return optionalArray(contentFormatKey); } void TextDocumentClientCapabilities::HoverCapabilities::setContentFormat(const QList &contentFormat) { insertArray(contentFormatKey, contentFormat); } std::optional> TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities:: documentationFormat() const { return optionalArray(documentationFormatKey); } void TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities:: setDocumentationFormat(const QList &documentationFormat) { insertArray(documentationFormatKey, documentationFormat); } InitializeParams::InitializeParams() { setProcessId(int(QCoreApplication::applicationPid())); setRootUri(LanguageClientValue()); setCapabilities(ClientCapabilities()); setTrace(s_trace); } std::optional InitializeParams::initializationOptions() const { const QJsonValue &optionsValue = value(initializationOptionsKey); if (optionsValue.isObject()) return optionsValue.toObject(); return std::nullopt; } std::optional InitializeParams::trace() const { const QJsonValue &traceValue = value(traceKey); if (traceValue.isUndefined()) return std::nullopt; return std::make_optional(Trace(traceValue.toString())); } InitializeRequest::InitializeRequest(const InitializeParams ¶ms) : Request(methodName, params) { } InitializeNotification::InitializeNotification(const InitializedParams ¶ms) : Notification(methodName, params) { } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/progresssupport.cpp0000644000175100017510000000311415232633614021342 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "progresssupport.h" #include namespace lsp { ProgressToken::ProgressToken(const QJsonValue &value) { if (!QBS_GUARD(value.isDouble() || value.isString())) emplace(QUuid::createUuid().toString()); else if (value.isDouble()) emplace(value.toInt()); else emplace(value.toString()); } ProgressToken::operator QJsonValue() const { if (std::holds_alternative(*this)) return QJsonValue(std::get(*this)); return QJsonValue(std::get(*this)); } ProgressParams::ProgressType ProgressParams::value() const { QJsonObject paramsValue = JsonObject::value(valueKey).toObject(); if (paramsValue[kindKey] == "begin") return ProgressParams::ProgressType(WorkDoneProgressBegin(paramsValue)); if (paramsValue[kindKey] == "report") return ProgressParams::ProgressType(WorkDoneProgressReport(paramsValue)); return ProgressParams::ProgressType(WorkDoneProgressEnd(paramsValue)); } void ProgressParams::setValue(const ProgressParams::ProgressType &value) { insertVariant(valueKey, value); } ProgressNotification::ProgressNotification(const ProgressParams ¶ms) : Notification(methodName, params) { } WorkDoneProgressCreateRequest::WorkDoneProgressCreateRequest(const WorkDoneProgressCreateParams ¶ms) : Request(methodName, params) { } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/client.h0000644000175100017510000000610515232633614016767 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { class Registration : public JsonObject { public: Registration() : Registration(QString()) {} explicit Registration(const QString &method) { setId(QUuid::createUuid().toString()); setMethod(method); } using JsonObject::JsonObject; QString id() const { return typedValue(idKey); } void setId(const QString &id) { insert(idKey, id); } QString method() const { return typedValue(methodKey); } void setMethod(const QString &method) { insert(methodKey, method); } QJsonValue registerOptions() const { return value(registerOptionsKey); } void setRegisterOptions(const QJsonValue ®isterOptions) { insert(registerOptionsKey, registerOptions); } bool isValid() const override { return contains(idKey) && contains(methodKey); } }; class RegistrationParams : public JsonObject { public: RegistrationParams() : RegistrationParams(QList()) {} explicit RegistrationParams(const QList ®istrations) { setRegistrations(registrations); } using JsonObject::JsonObject; QList registrations() const { return array(registrationsKey); } void setRegistrations(const QList ®istrations) { insertArray(registrationsKey, registrations); } bool isValid() const override { return contains(registrationsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT RegisterCapabilityRequest : public Request< std::nullptr_t, std::nullptr_t, RegistrationParams> { public: explicit RegisterCapabilityRequest(const RegistrationParams ¶ms); using Request::Request; constexpr static const char methodName[] = "client/registerCapability"; }; class Unregistration : public JsonObject { public: using JsonObject::JsonObject; QString id() const { return typedValue(idKey); } void setId(const QString &id) { insert(idKey, id); } QString method() const { return typedValue(methodKey); } void setMethod(const QString &method) { insert(methodKey, method); } bool isValid() const override { return contains(idKey) && contains(methodKey); } }; class UnregistrationParams : public JsonObject { public: using JsonObject::JsonObject; QList unregistrations() const { return array(unregistrationsKey); } void setUnregistrations(const QList &unregistrations) { insertArray(unregistrationsKey, unregistrations); } bool isValid() const override { return contains(unregistrationsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT UnregisterCapabilityRequest : public Request< std::nullptr_t, std::nullptr_t, UnregistrationParams> { public: explicit UnregisterCapabilityRequest(const UnregistrationParams ¶ms); using Request::Request; constexpr static const char methodName[] = "client/unregisterCapability"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/completion.h0000644000175100017510000002550415232633614017666 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" #include "languagefeatures.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT CompletionParams : public TextDocumentPositionParams { public: using TextDocumentPositionParams::TextDocumentPositionParams; enum CompletionTriggerKind { /** * Completion was triggered by typing an identifier (24x7 code * complete), manual invocation (e.g Ctrl+Space) or via API. */ Invoked = 1, /** * Completion was triggered by a trigger character specified by * the `triggerCharacters` properties of the `CompletionRegistrationOptions`. */ TriggerCharacter = 2, /// Completion was re-triggered as the current completion list is incomplete. TriggerForIncompleteCompletions = 3 }; class CompletionContext : public JsonObject { public: using JsonObject::JsonObject; /// How the completion was triggered. CompletionTriggerKind triggerKind() const { return CompletionTriggerKind(typedValue(triggerKindKey)); } void setTriggerKind(CompletionTriggerKind triggerKind) { insert(triggerKindKey, triggerKind); } /** * The trigger character (a single character) that has trigger code complete. * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` */ std::optional triggerCharacter() const { return optionalValue(triggerCharacterKey); } void setTriggerCharacter(const QString &triggerCharacter) { insert(triggerCharacterKey, triggerCharacter); } void clearTriggerCharacter() { remove(triggerCharacterKey); } bool isValid() const override { return contains(triggerKindKey); } }; /** * The completion context. This is only available it the client specifies * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true` */ std::optional context() const { return optionalValue(contextKey); } void setContext(const CompletionContext &context) { insert(contextKey, context); } void clearContext() { remove(contextKey); } // clangd extension void setLimit(int limit) { insert(limitKey, limit); } }; class LANGUAGESERVERPROTOCOL_EXPORT CompletionItem : public JsonObject { public: using JsonObject::JsonObject; /** * The label of this completion item. By default also the text that is inserted when selecting * this completion. */ QString label() const { return typedValue(labelKey); } void setLabel(const QString &label) { insert(labelKey, label); } /// The kind of this completion item. Based of the kind an icon is chosen by the editor. std::optional kind() const { return optionalValue(kindKey); } void setKind(int kind) { insert(kindKey, kind); } void clearKind() { remove(kindKey); } /// A human-readable string with additional information about this item, like type information. std::optional detail() const { return optionalValue(detailKey); } void setDetail(const QString &detail) { insert(detailKey, detail); } void clearDetail() { remove(detailKey); } /// A human-readable string that represents a doc-comment. std::optional documentation() const; void setDocumentation(const MarkupOrString &documentation) { insert(documentationKey, documentation.toJson()); } void cleatDocumentation() { remove(documentationKey); } /// A string that should be used when comparing this item /// with other items. When `falsy` the label is used. std::optional sortText() const { return optionalValue(sortTextKey); } void setSortText(const QString &sortText) { insert(sortTextKey, sortText); } void clearSortText() { remove(sortTextKey); } /// A string that should be used when filtering a set of /// completion items. When `falsy` the label is used. std::optional filterText() const { return optionalValue(filterTextKey); } void setFilterText(const QString &filterText) { insert(filterTextKey, filterText); } void clearFilterText() { remove(filterTextKey); } /** * A string that should be inserted into a document when selecting * this completion. When `falsy` the label is used. * * The `insertText` is subject to interpretation by the client side. * Some tools might not take the string literally. For example * VS Code when code complete is requested in this example `con` * and a completion item with an `insertText` of `console` is provided it * will only insert `sole`. Therefore it is recommended to use `textEdit` instead * since it avoids additional client side interpretation. * * @deprecated Use textEdit instead. */ std::optional insertText() const { return optionalValue(insertTextKey); } void setInsertText(const QString &insertText) { insert(insertTextKey, insertText); } void clearInsertText() { remove(insertTextKey); } enum InsertTextFormat { /// The primary text to be inserted is treated as a plain string. PlainText = 1, /** * The primary text to be inserted is treated as a snippet. * * A snippet can define tab stops and placeholders with `$1`, `$2` * and `${3:foo}`. `$0` defines the final tab stop, it defaults to * the end of the snippet. Placeholders with equal identifiers are linked, * that is typing in one will update others too. */ Snippet = 2 }; /// The format of the insert text. The format applies to both the `insertText` property /// and the `newText` property of a provided `textEdit`. std::optional insertTextFormat() const; void setInsertTextFormat(const InsertTextFormat &insertTextFormat) { insert(insertTextFormatKey, insertTextFormat); } void clearInsertTextFormat() { remove(insertTextFormatKey); } /** * An edit which is applied to a document when selecting this completion. When an edit is provided the value of * `insertText` is ignored. * * *Note:* The range of the edit must be a single line range and it must contain the position at which completion * has been requested. */ std::optional textEdit() const { return optionalValue(textEditKey); } void setTextEdit(const TextEdit &textEdit) { insert(textEditKey, textEdit); } void clearTextEdit() { remove(textEditKey); } /** * An optional array of additional text edits that are applied when * selecting this completion. Edits must not overlap with the main edit * nor with themselves. */ std::optional> additionalTextEdits() const { return optionalArray(additionalTextEditsKey); } void setAdditionalTextEdits(const QList &additionalTextEdits) { insertArray(additionalTextEditsKey, additionalTextEdits); } void clearAdditionalTextEdits() { remove(additionalTextEditsKey); } /** * An optional set of characters that when pressed while this completion is active will accept it first and * then type that character. *Note* that all commit characters should have `length=1` and that superfluous * characters will be ignored. */ std::optional> commitCharacters() const { return optionalArray(commitCharactersKey); } void setCommitCharacters(const QList &commitCharacters) { insertArray(commitCharactersKey, commitCharacters); } void clearCommitCharacters() { remove(commitCharactersKey); } /** * An optional command that is executed *after* inserting this completion. *Note* that * additional modifications to the current document should be described with the * additionalTextEdits-property. */ std::optional command() const { return optionalValue(commandKey); } void setCommand(const Command &command) { insert(commandKey, command); } void clearCommand() { remove(commandKey); } /** * An data entry field that is preserved on a completion item between * a completion and a completion resolve request. */ std::optional data() const { return optionalValue(dataKey); } void setData(const QJsonValue &data) { insert(dataKey, data); } void clearData() { remove(dataKey); } /** * Completion item tags are extra annotations that tweak the rendering of a * completion item. * @since 3.15.0 */ enum CompletionItemTag { Deprecated = 1, }; /** * Tags for this completion item. * @since 3.15.0 */ std::optional> tags() const; /** * Indicates if this item is deprecated. * @deprecated Use `tags` instead if supported. */ std::optional deprecated() const { return optionalValue(deprecatedKey); } bool isValid() const override { return contains(labelKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CompletionList : public JsonObject { public: using JsonObject::JsonObject; /** * This list it not complete. Further typing should result in recomputing * this list. */ bool isIncomplete() const { return typedValue(isIncompleteKey); } void setIsIncomplete(bool isIncomplete) { insert(isIncompleteKey, isIncomplete); } /// The completion items. std::optional> items() const { return array(itemsKey); } void setItems(const QList &items) { insertArray(itemsKey, items); } void clearItems() { remove(itemsKey); } bool isValid() const override { return contains(isIncompleteKey); } }; /// The result of a completion is CompletionItem[] | CompletionList | null class LANGUAGESERVERPROTOCOL_EXPORT CompletionResult : public std::variant, CompletionList, std::nullptr_t> { public: using variant::variant; explicit CompletionResult(const QJsonValue &value); }; class LANGUAGESERVERPROTOCOL_EXPORT CompletionRequest : public Request< CompletionResult, std::nullptr_t, CompletionParams> { public: explicit CompletionRequest(const CompletionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/completion"; }; class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemResolveRequest : public Request< CompletionItem, std::nullptr_t, CompletionItem> { public: explicit CompletionItemResolveRequest(const CompletionItem ¶ms); using Request::Request; constexpr static const char methodName[] = "completionItem/resolve"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/lsputils.cpp0000644000175100017510000000361615232633614017727 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "lsputils.h" #include #include #include namespace lsp { Q_LOGGING_CATEGORY(conversionLog, "qtc.languageserverprotocol.conversion", QtWarningMsg) template<> QString fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isString()) qCDebug(conversionLog) << "Expected String in json value but got: " << value; return value.toString(); } template<> int fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isDouble()) qCDebug(conversionLog) << "Expected double in json value but got: " << value; return value.toInt(); } template<> double fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isDouble()) qCDebug(conversionLog) << "Expected double in json value but got: " << value; return value.toDouble(); } template<> bool fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isBool()) qCDebug(conversionLog) << "Expected bool in json value but got: " << value; return value.toBool(); } template<> QJsonArray fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isArray()) qCDebug(conversionLog) << "Expected Array in json value but got: " << value; return value.toArray(); } template<> QJsonObject fromJsonValue(const QJsonValue &value) { if (conversionLog().isDebugEnabled() && !value.isObject()) qCDebug(conversionLog) << "Expected Object in json value but got: " << value; return value.toObject(); } template<> QJsonValue fromJsonValue(const QJsonValue &value) { return value; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/textutils.cpp0000644000175100017510000000761015232633614020113 0ustar runnerrunner// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "textutils.h" #include #include #include namespace lsp::Utils::Text { bool Position::operator==(const Position &other) const { return line == other.line && column == other.column; } /*! Returns the text position of a \a fileName and sets the \a postfixPos if it can find a positional postfix. The following patterns are supported: \c {filepath.txt:19}, \c{filepath.txt:19:12}, \c {filepath.txt+19}, \c {filepath.txt+19+12}, and \c {filepath.txt(19)}. */ Position Position::fromFileName(QStringView fileName, int &postfixPos) { static const auto regexp = QRegularExpression("[:+](\\d+)?([:+](\\d+)?)?$"); // (10) MSVC-style static const auto vsRegexp = QRegularExpression("[(]((\\d+)[)]?)?$"); const QRegularExpressionMatch match = regexp.match(fileName); Position pos; if (match.hasMatch()) { postfixPos = match.capturedStart(0); if (match.lastCapturedIndex() > 0) { pos.line = match.captured(1).toInt(); if (match.lastCapturedIndex() > 2) // index 2 includes the + or : for the column number pos.column = match.captured(3).toInt() - 1; //column is 0 based, despite line being 1 based } } else { const QRegularExpressionMatch vsMatch = vsRegexp.match(fileName); postfixPos = vsMatch.capturedStart(0); if (vsMatch.lastCapturedIndex() > 1) // index 1 includes closing ) pos.line = vsMatch.captured(2).toInt(); } if (pos.line > 0 && pos.column < 0) pos.column = 0; // if we got a valid line make sure to return a valid TextPosition return pos; } int Range::length(const QString &text) const { if (end.line < begin.line) return -1; if (begin.line == end.line) return end.column - begin.column; int index = 0; int currentLine = 1; while (currentLine < begin.line) { index = text.indexOf(QChar::LineFeed, index); if (index < 0) return -1; ++index; ++currentLine; } const int beginIndex = index + begin.column; while (currentLine < end.line) { index = text.indexOf(QChar::LineFeed, index); if (index < 0) return -1; ++index; ++currentLine; } return index + end.column - beginIndex; } bool Range::operator==(const Range &other) const { return begin == other.begin && end == other.end; } QString utf16LineTextInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset) { const int lineStartUtf8Offset = currentUtf8Offset ? (utf8Buffer.lastIndexOf('\n', currentUtf8Offset - 1) + 1) : 0; const int lineEndUtf8Offset = utf8Buffer.indexOf('\n', currentUtf8Offset); return QString::fromUtf8( utf8Buffer.mid(lineStartUtf8Offset, lineEndUtf8Offset - lineStartUtf8Offset)); } static bool isByteOfMultiByteCodePoint(unsigned char byte) { return byte & 0x80; // Check if most significant bit is set } bool utf8AdvanceCodePoint(const char *¤t) { if (Q_UNLIKELY(*current == '\0')) return false; // Process multi-byte UTF-8 code point (non-latin1) if (Q_UNLIKELY(isByteOfMultiByteCodePoint(*current))) { unsigned trailingBytesCurrentCodePoint = 1; for (unsigned char c = (*current) << 2; isByteOfMultiByteCodePoint(c); c <<= 1) ++trailingBytesCurrentCodePoint; current += trailingBytesCurrentCodePoint + 1; // Process single-byte UTF-8 code point (latin1) } else { ++current; } return true; } QDebug &operator<<(QDebug &stream, const Position &pos) { stream << "line: " << pos.line << ", column: " << pos.column; return stream; } } // namespace Utils::Text qbs-src-3.3.1/src/shared/lsp/link.cpp0000644000175100017510000000221215232633614016774 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "link.h" #include "textutils.h" namespace lsp::Utils { /*! Returns the Link to \a filePath. If \a canContainLineNumber is true the line number, and column number components are extracted from the \a filePath's \c path() and the found \a postfix is set. The following patterns are supported: \c {filepath.txt:19}, \c{filepath.txt:19:12}, \c {filepath.txt+19}, \c {filepath.txt+19+12}, and \c {filepath.txt(19)}. */ Link Link::fromString(const QString &filePathWithNumbers, bool canContainLineNumber) { Link link; if (!canContainLineNumber) { link.targetFilePath = FilePath::fromUserInput(filePathWithNumbers); } else { int postfixPos = -1; const Text::Position pos = Text::Position::fromFileName(filePathWithNumbers, postfixPos); link.targetFilePath = FilePath::fromUserInput(filePathWithNumbers.left(postfixPos)); link.targetLine = pos.line; link.targetColumn = pos.column; } return link; } } // namespace lsp::Utils qbs-src-3.3.1/src/shared/lsp/semantictokens.cpp0000644000175100017510000001065515232633614021100 0ustar runnerrunner// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "semantictokens.h" namespace lsp { bool SemanticTokensLegend::isValid() const { return contains(tokenTypesKey) && contains(tokenModifiersKey); } QMap SemanticTokens::defaultTokenTypesMap() { QMap map; map.insert("namespace", namespaceToken); map.insert("type", typeToken); map.insert("class", classToken); map.insert("enum", enumToken); map.insert("interface", interfaceToken); map.insert("struct", structToken); map.insert("typeParameter", typeParameterToken); map.insert("parameter", parameterToken); map.insert("variable", variableToken); map.insert("property", propertyToken); map.insert("enumMember", enumMemberToken); map.insert("event", eventToken); map.insert("function", functionToken); map.insert("method", methodToken); map.insert("macro", macroToken); map.insert("keyword", keywordToken); map.insert("modifier", modifierToken); map.insert("comment", commentToken); map.insert("string", stringToken); map.insert("number", numberToken); map.insert("regexp", regexpToken); map.insert("operator", operatorToken); return map; } QMap SemanticTokens::defaultTokenModifiersMap() { QMap map; map.insert("declaration", declarationModifier); map.insert("definition", definitionModifier); map.insert("readonly", readonlyModifier); map.insert("static", staticModifier); map.insert("deprecated", deprecatedModifier); map.insert("abstract", abstractModifier); map.insert("async", asyncModifier); map.insert("modification", modificationModifier); map.insert("documentation", documentationModifier); map.insert("defaultLibrary", defaultLibraryModifier); return map; } static int convertModifiers(int modifiersData, const QList &tokenModifiers) { int result = 0; for (int i = 0; i < tokenModifiers.size() && modifiersData > 0; ++i) { if (modifiersData & 0x1) { const int modifier = tokenModifiers[i]; if (modifier > 0) result |= modifier; } modifiersData = modifiersData >> 1; } return result; } QList SemanticTokens::toTokens(const QList &tokenTypes, const QList &tokenModifiers) const { const QList &data = this->data(); if (data.size() % 5 != 0) return {}; QList tokens; tokens.reserve(int(data.size() / 5)); auto end = data.end(); for (auto it = data.begin(); it != end; it += 5) { SemanticToken token; token.deltaLine = *(it); token.deltaStart = *(it + 1); token.length = *(it + 2); token.tokenIndex = *(it + 3); token.tokenType = tokenTypes.value(token.tokenIndex, -1); token.rawTokenModifiers = *(it + 4); token.tokenModifiers = convertModifiers(token.rawTokenModifiers, tokenModifiers); tokens << token; } return tokens; } bool SemanticTokensRangeParams::isValid() const { return SemanticTokensParams::isValid() && contains(rangeKey); } SemanticTokensFullRequest::SemanticTokensFullRequest(const SemanticTokensParams ¶ms) : Request(methodName, params) {} SemanticTokensRangeRequest::SemanticTokensRangeRequest(const SemanticTokensRangeParams ¶ms) : Request(methodName, params) {} SemanticTokensResult::SemanticTokensResult(const QJsonValue &value) { if (value.isObject()) emplace(SemanticTokens(value.toObject())); else emplace(nullptr); } SemanticTokensFullDeltaRequest::SemanticTokensFullDeltaRequest(const SemanticTokensDeltaParams ¶ms) : Request(methodName, params) {} bool SemanticTokensDeltaParams::isValid() const { return SemanticTokensParams::isValid() && contains(previousResultIdKey); } SemanticTokensDeltaResult::SemanticTokensDeltaResult(const QJsonValue &value) { if (value.isObject()) { QJsonObject object = value.toObject(); if (object.contains(editsKey)) emplace(object); else emplace(object); } else { emplace(nullptr); } } SemanticTokensRefreshRequest::SemanticTokensRefreshRequest() : Request(methodName, nullptr) {} } // namespace lsp qbs-src-3.3.1/src/shared/lsp/workspace.h0000644000175100017510000002073715232633614017516 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderResult : public std::variant, std::nullptr_t> { public: using variant::variant; using variant::operator=; operator const QJsonValue() const; }; class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderRequest : public Request< WorkSpaceFolderResult, std::nullptr_t, std::nullptr_t> { public: WorkSpaceFolderRequest(); using Request::Request; constexpr static const char methodName[] = "workspace/workspaceFolders"; bool parametersAreValid(QString * /*errorMessage*/) const override { return true; } }; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceFoldersChangeEvent : public JsonObject { public: using JsonObject::JsonObject; WorkspaceFoldersChangeEvent(); QList added() const { return array(addedKey); } void setAdded(const QList &added) { insertArray(addedKey, added); } QList removed() const { return array(removedKey); } void setRemoved(const QList &removed) { insertArray(removedKey, removed); } bool isValid() const override { return contains(addedKey) && contains(removedKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeWorkspaceFoldersParams : public JsonObject { public: using JsonObject::JsonObject; WorkspaceFoldersChangeEvent event() const { return typedValue(eventKey); } void setEvent(const WorkspaceFoldersChangeEvent &event) { insert(eventKey, event); } bool isValid() const override { return contains(eventKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeWorkspaceFoldersNotification : public Notification< DidChangeWorkspaceFoldersParams> { public: explicit DidChangeWorkspaceFoldersNotification(const DidChangeWorkspaceFoldersParams ¶ms); constexpr static const char methodName[] = "workspace/didChangeWorkspaceFolders"; using Notification::Notification; }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeConfigurationParams : public JsonObject { public: using JsonObject::JsonObject; QJsonValue settings() const { return value(settingsKey); } void setSettings(QJsonValue settings) { insert(settingsKey, settings); } bool isValid() const override { return contains(settingsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeConfigurationNotification : public Notification< DidChangeConfigurationParams> { public: explicit DidChangeConfigurationNotification(const DidChangeConfigurationParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "workspace/didChangeConfiguration"; }; class LANGUAGESERVERPROTOCOL_EXPORT ConfigurationParams : public JsonObject { public: using JsonObject::JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT ConfigurationItem : public JsonObject { public: using JsonObject::JsonObject; std::optional scopeUri() const; void setScopeUri(const DocumentUri &scopeUri) { insert(scopeUriKey, scopeUri); } void clearScopeUri() { remove(scopeUriKey); } std::optional section() const { return optionalValue(sectionKey); } void setSection(const QString §ion) { insert(sectionKey, section); } void clearSection() { remove(sectionKey); } bool isValid() const override { return contains(scopeUriKey); } }; QList items() const { return array(itemsKey); } void setItems(const QList &items) { insertArray(itemsKey, items); } bool isValid() const override { return contains(itemsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ConfigurationRequest : public Request { public: explicit ConfigurationRequest(const ConfigurationParams ¶ms); using Request::Request; constexpr static const char methodName[] = "workspace/configuration"; }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeWatchedFilesParams : public JsonObject { public: using JsonObject::JsonObject; class FileEvent : public JsonObject { public: using JsonObject::JsonObject; DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } int type() const { return typedValue(typeKey); } void setType(int type) { insert(typeKey, type); } enum FileChangeType { Created = 1, Changed = 2, Deleted = 3 }; bool isValid() const override { return contains(uriKey) && contains(typeKey); } }; QList changes() const { return array(changesKey); } void setChanges(const QList &changes) { insertArray(changesKey, changes); } bool isValid() const override { return contains(changesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeWatchedFilesNotification : public Notification< DidChangeWatchedFilesParams> { public: explicit DidChangeWatchedFilesNotification(const DidChangeWatchedFilesParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "workspace/didChangeWatchedFiles"; }; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceSymbolParams : public JsonObject { public: using JsonObject::JsonObject; QString query() const { return typedValue(queryKey); } void setQuery(const QString &query) { insert(queryKey, query); } void setLimit(int limit) { insert("limit", limit); } // clangd extension bool isValid() const override { return contains(queryKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceSymbolRequest : public Request< LanguageClientArray, std::nullptr_t, WorkspaceSymbolParams> { public: explicit WorkspaceSymbolRequest(const WorkspaceSymbolParams ¶ms); using Request::Request; constexpr static const char methodName[] = "workspace/symbol"; }; class LANGUAGESERVERPROTOCOL_EXPORT ExecuteCommandParams : public JsonObject { public: explicit ExecuteCommandParams(const Command &command); explicit ExecuteCommandParams(const QJsonValue &value) : JsonObject(value) {} ExecuteCommandParams() : JsonObject() {} QString command() const { return typedValue(commandKey); } void setCommand(const QString &command) { insert(commandKey, command); } void clearCommand() { remove(commandKey); } std::optional arguments() const { return typedValue(argumentsKey); } void setArguments(const QJsonArray &arguments) { insert(argumentsKey, arguments); } void clearArguments() { remove(argumentsKey); } bool isValid() const override { return contains(commandKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ExecuteCommandRequest : public Request< QJsonValue, std::nullptr_t, ExecuteCommandParams> { public: explicit ExecuteCommandRequest(const ExecuteCommandParams ¶ms); using Request::Request; constexpr static const char methodName[] = "workspace/executeCommand"; }; class LANGUAGESERVERPROTOCOL_EXPORT ApplyWorkspaceEditParams : public JsonObject { public: using JsonObject::JsonObject; std::optional label() const { return optionalValue(labelKey); } void setLabel(const QString &label) { insert(labelKey, label); } void clearLabel() { remove(labelKey); } WorkspaceEdit edit() const { return typedValue(editKey); } void setEdit(const WorkspaceEdit &edit) { insert(editKey, edit); } bool isValid() const override { return contains(editKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ApplyWorkspaceEditResult : public JsonObject { public: using JsonObject::JsonObject; bool applied() const { return typedValue(appliedKey); } void setApplied(bool applied) { insert(appliedKey, applied); } bool isValid() const override { return contains(appliedKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ApplyWorkspaceEditRequest : public Request< ApplyWorkspaceEditResult, std::nullptr_t, ApplyWorkspaceEditParams> { public: explicit ApplyWorkspaceEditRequest(const ApplyWorkspaceEditParams ¶ms); using Request::Request; constexpr static const char methodName[] = "workspace/applyEdit"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/textsynchronization.h0000644000175100017510000002054115232633614021657 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" #include "servercapabilities.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT DidOpenTextDocumentParams : public JsonObject { public: DidOpenTextDocumentParams() = default; explicit DidOpenTextDocumentParams(const TextDocumentItem &document); using JsonObject::JsonObject; TextDocumentItem textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(TextDocumentItem textDocument) { insert(textDocumentKey, textDocument); } bool isValid() const override { return contains(textDocumentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidOpenTextDocumentNotification : public Notification< DidOpenTextDocumentParams> { public: explicit DidOpenTextDocumentNotification(const DidOpenTextDocumentParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/didOpen"; }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentChangeRegistrationOptions : public JsonObject { public: TextDocumentChangeRegistrationOptions(); explicit TextDocumentChangeRegistrationOptions(TextDocumentSyncKind kind); using JsonObject::JsonObject; TextDocumentSyncKind syncKind() const { return static_cast(typedValue(syncKindKey)); } void setSyncKind(TextDocumentSyncKind syncKind) { insert(syncKindKey, static_cast(syncKind)); } bool isValid() const override { return contains(syncKindKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeTextDocumentParams : public JsonObject { public: DidChangeTextDocumentParams(); explicit DidChangeTextDocumentParams(const VersionedTextDocumentIdentifier &docId, const QString &text = QString()); using JsonObject::JsonObject; VersionedTextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const VersionedTextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentContentChangeEvent : public JsonObject { /* * An event describing a change to a text document. If range and rangeLength are omitted * the new text is considered to be the full content of the document. */ public: TextDocumentContentChangeEvent() = default; explicit TextDocumentContentChangeEvent(const QString &text); using JsonObject::JsonObject; // The range of the document that changed. std::optional range() const { return optionalValue(rangeKey); } void setRange(Range range) { insert(rangeKey, range); } void clearRange() { remove(rangeKey); } // The length of the range that got replaced. std::optional rangeLength() const { return optionalValue(rangeLengthKey); } void setRangeLength(int rangeLength) { insert(rangeLengthKey, rangeLength); } void clearRangeLength() { remove(rangeLengthKey); } // The new text of the range/document. QString text() const { return typedValue(textKey); } void setText(const QString &text) { insert(textKey, text); } bool isValid() const override { return contains(textKey); } }; QList contentChanges() const { return array(contentChangesKey); } void setContentChanges(const QList &contentChanges) { insertArray(contentChangesKey, contentChanges); } bool isValid() const override { return contains(textDocumentKey) && contains(contentChangesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidChangeTextDocumentNotification : public Notification< DidChangeTextDocumentParams> { public: explicit DidChangeTextDocumentNotification(const DidChangeTextDocumentParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/didChange"; }; class LANGUAGESERVERPROTOCOL_EXPORT WillSaveTextDocumentParams : public JsonObject { public: enum class TextDocumentSaveReason { Manual = 1, AfterDelay = 2, FocusOut = 3 }; WillSaveTextDocumentParams() : WillSaveTextDocumentParams(TextDocumentIdentifier()) {} explicit WillSaveTextDocumentParams( const TextDocumentIdentifier &document, const TextDocumentSaveReason &reason = TextDocumentSaveReason::Manual); using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } TextDocumentSaveReason reason() const { return static_cast(typedValue(reasonKey)); } void setReason(TextDocumentSaveReason reason) { insert(reasonKey, static_cast(reason)); } bool isValid() const override { return contains(textDocumentKey) && contains(reasonKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT WillSaveTextDocumentNotification : public Notification< WillSaveTextDocumentParams> { public: explicit WillSaveTextDocumentNotification(const WillSaveTextDocumentParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/willSave"; }; class LANGUAGESERVERPROTOCOL_EXPORT WillSaveWaitUntilTextDocumentRequest : public Request< LanguageClientArray, std::nullptr_t, WillSaveTextDocumentParams> { public: explicit WillSaveWaitUntilTextDocumentRequest(const WillSaveTextDocumentParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/willSaveWaitUntil"; }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentSaveRegistrationOptions : public TextDocumentRegistrationOptions { public: using TextDocumentRegistrationOptions::TextDocumentRegistrationOptions; std::optional includeText() const { return optionalValue(includeTextKey); } void setIncludeText(bool includeText) { insert(includeTextKey, includeText); } void clearIncludeText() { remove(includeTextKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidSaveTextDocumentParams : public JsonObject { public: DidSaveTextDocumentParams() : DidSaveTextDocumentParams(TextDocumentIdentifier()) {} explicit DidSaveTextDocumentParams(const TextDocumentIdentifier &document); using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(TextDocumentIdentifier textDocument) { insert(textDocumentKey, textDocument); } std::optional text() const { return optionalValue(textKey); } void setText(const QString &text) { insert(textKey, text); } void clearText() { remove(textKey); } bool isValid() const override { return contains(textDocumentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidSaveTextDocumentNotification : public Notification< DidSaveTextDocumentParams> { public: explicit DidSaveTextDocumentNotification(const DidSaveTextDocumentParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/didSave"; }; class LANGUAGESERVERPROTOCOL_EXPORT DidCloseTextDocumentParams : public JsonObject { public: DidCloseTextDocumentParams() = default; explicit DidCloseTextDocumentParams(const TextDocumentIdentifier &document); using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } bool isValid() const override { return contains(textDocumentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DidCloseTextDocumentNotification : public Notification< DidCloseTextDocumentParams> { public: explicit DidCloseTextDocumentNotification(const DidCloseTextDocumentParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/didClose"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/languagefeatures.cpp0000644000175100017510000003000715232633614021364 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "languagefeatures.h" #include namespace lsp { constexpr const char HoverRequest::methodName[]; constexpr const char GotoDefinitionRequest::methodName[]; constexpr const char GotoTypeDefinitionRequest::methodName[]; constexpr const char GotoImplementationRequest::methodName[]; constexpr const char FindReferencesRequest::methodName[]; constexpr const char DocumentHighlightsRequest::methodName[]; constexpr const char DocumentSymbolsRequest::methodName[]; constexpr const char CodeActionRequest::methodName[]; constexpr const char CodeLensRequest::methodName[]; constexpr const char CodeLensResolveRequest::methodName[]; constexpr const char DocumentLinkRequest::methodName[]; constexpr const char DocumentLinkResolveRequest::methodName[]; constexpr const char DocumentColorRequest::methodName[]; constexpr const char ColorPresentationRequest::methodName[]; constexpr const char DocumentFormattingRequest::methodName[]; constexpr const char DocumentRangeFormattingRequest::methodName[]; constexpr const char DocumentOnTypeFormattingRequest::methodName[]; constexpr const char RenameRequest::methodName[]; constexpr const char SignatureHelpRequest::methodName[]; constexpr const char PrepareRenameRequest::methodName[]; HoverContent Hover::content() const { return HoverContent(value(contentsKey)); } void Hover::setContent(const HoverContent &content) { if (auto val = std::get_if(&content)) insert(contentsKey, *val); else if (auto val = std::get_if(&content)) insert(contentsKey, *val); else if (auto val = std::get_if>(&content)) insert(contentsKey, LanguageClientArray(*val).toJson()); else QBS_ASSERT("LanguageClient Using unknown type Hover::setContent",;); } HoverRequest::HoverRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } std::optional ParameterInformation::documentation() const { QJsonValue documentation = value(documentationKey); if (documentation.isUndefined()) return std::nullopt; return MarkupOrString(documentation); } GotoDefinitionRequest::GotoDefinitionRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } GotoTypeDefinitionRequest::GotoTypeDefinitionRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } GotoImplementationRequest::GotoImplementationRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } FindReferencesRequest::FindReferencesRequest(const ReferenceParams ¶ms) : Request(methodName, params) { } DocumentHighlightsRequest::DocumentHighlightsRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } DocumentSymbolsRequest::DocumentSymbolsRequest(const DocumentSymbolParams ¶ms) : Request(methodName, params) { } std::optional > CodeActionParams::CodeActionContext::only() const { return optionalArray(onlyKey); } void CodeActionParams::CodeActionContext::setOnly(const QList &only) { insertArray(onlyKey, only); } CodeActionRequest::CodeActionRequest(const CodeActionParams ¶ms) : Request(methodName, params) { } CodeLensRequest::CodeLensRequest(const CodeLensParams ¶ms) : Request(methodName, params) { } CodeLensResolveRequest::CodeLensResolveRequest(const CodeLens ¶ms) : Request(methodName, params) { } DocumentLinkRequest::DocumentLinkRequest(const DocumentLinkParams ¶ms) : Request(methodName, params) { } DocumentLinkResolveRequest::DocumentLinkResolveRequest(const DocumentLink ¶ms) : Request(methodName, params) { } DocumentColorRequest::DocumentColorRequest(const DocumentColorParams ¶ms) : Request(methodName, params) { } ColorPresentationRequest::ColorPresentationRequest(const ColorPresentationParams ¶ms) : Request(methodName, params) { } QHash FormattingOptions::properties() const { QHash ret; for (const QString &key : keys()) { if (key == tabSizeKey || key == insertSpaceKey) continue; QJsonValue property = value(key.toStdString()); if (property.isBool()) ret[key] = property.toBool(); if (property.isDouble()) ret[key] = property.toDouble(); if (property.isString()) ret[key] = property.toString(); } return ret; } void FormattingOptions::setProperty(const std::string_view key, const DocumentFormattingProperty &property) { using namespace std; if (auto val = get_if(&property)) insert(key, *val); else if (auto val = get_if(&property)) insert(key, *val); else if (auto val = get_if(&property)) insert(key, *val); } DocumentFormattingRequest::DocumentFormattingRequest(const DocumentFormattingParams ¶ms) : Request(methodName, params) { } DocumentRangeFormattingRequest::DocumentRangeFormattingRequest( const DocumentRangeFormattingParams ¶ms) : Request(methodName, params) { } bool DocumentOnTypeFormattingParams::isValid() const { return contains(textDocumentKey) && contains(positionKey) && contains(chKey) && contains(optionsKey); } DocumentOnTypeFormattingRequest::DocumentOnTypeFormattingRequest( const DocumentOnTypeFormattingParams ¶ms) : Request(methodName, params) { } PrepareRenameRequest::PrepareRenameRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } bool RenameParams::isValid() const { return contains(textDocumentKey) && contains(positionKey) && contains(newNameKey); } RenameRequest::RenameRequest(const RenameParams ¶ms) : Request(methodName, params) { } std::optional DocumentLink::target() const { if (std::optional optionalTarget = optionalValue(targetKey)) return std::make_optional(DocumentUri::fromProtocol(*optionalTarget)); return std::nullopt; } std::optional DocumentLink::data() const { return contains(dataKey) ? std::make_optional(value(dataKey)) : std::nullopt; } TextDocumentParams::TextDocumentParams() : TextDocumentParams(TextDocumentIdentifier()) { } TextDocumentParams::TextDocumentParams(const TextDocumentIdentifier &identifier) : JsonObject() { setTextDocument(identifier); } GotoResult::GotoResult(const QJsonValue &value) { if (value.isArray()) { QList locations; for (auto arrayValue : value.toArray()) { if (arrayValue.isObject()) locations.append(Location(arrayValue.toObject())); } emplace>(locations); } else if (value.isObject()) { emplace(value.toObject()); } else { emplace(nullptr); } } template QList documentSymbolsResultArray(const QJsonArray &array) { QList ret; for (const auto &arrayValue : array) { if (arrayValue.isObject()) ret << Symbol(arrayValue.toObject()); } return ret; } DocumentSymbolsResult::DocumentSymbolsResult(const QJsonValue &value) { if (value.isArray()) { QJsonArray array = value.toArray(); if (array.isEmpty()) { *this = QList(); } else { QJsonObject arrayObject = array.first().toObject(); if (arrayObject.contains(rangeKey)) *this = documentSymbolsResultArray(array); else *this = documentSymbolsResultArray(array); } } else { *this = nullptr; } } DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value) { if (value.isArray()) { QList highlights; for (auto arrayValue : value.toArray()) { if (arrayValue.isObject()) highlights.append(DocumentHighlight(arrayValue.toObject())); } *this = highlights; } else { *this = nullptr; } } MarkedString::MarkedString(const QJsonValue &value) { if (value.isObject()) emplace(MarkedLanguageString(value.toObject())); else emplace(value.toString()); } bool MarkedString::isValid() const { if (auto markedLanguageString = std::get_if(this)) return markedLanguageString->isValid(); return true; } MarkedString::operator QJsonValue() const { if (auto val = std::get_if(this)) return *val; if (auto val = std::get_if(this)) return QJsonValue(*val); return {}; } HoverContent::HoverContent(const QJsonValue &value) { if (value.isArray()) { emplace>(LanguageClientArray(value).toList()); } else if (value.isObject()) { const QJsonObject &object = value.toObject(); MarkedLanguageString markedLanguageString(object); if (markedLanguageString.isValid()) emplace(markedLanguageString); else emplace(MarkupContent(object)); } else if (value.isString()) { emplace(MarkedString(value.toString())); } } bool HoverContent::isValid() const { if (std::holds_alternative(*this)) return std::get(*this).isValid(); return true; } DocumentFormattingProperty::DocumentFormattingProperty(const QJsonValue &value) { if (value.isBool()) *this = value.toBool(); if (value.isDouble()) *this = value.toDouble(); if (value.isString()) *this = value.toString(); } SignatureHelpRequest::SignatureHelpRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } CodeActionResult::CodeActionResult(const QJsonValue &val) { using ResultArray = QList>; if (val.isArray()) { const QJsonArray array = val.toArray(); ResultArray result; for (const QJsonValue &val : array) { if (val.toObject().value(commandKey).isString()) { const Command command(val); if (command.isValid()) result << command; } else { const CodeAction action(val); if (action.isValid()) result << action; } } emplace(result); return; } emplace(nullptr); } PrepareRenameResult::PrepareRenameResult() : std::variant(nullptr) {} PrepareRenameResult::PrepareRenameResult( const std::variant &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const PlaceHolderResult &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const Range &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const QJsonValue &val) { if (val.isNull()) { emplace(nullptr); } else if (val.isObject()) { const QJsonObject object = val.toObject(); if (object.keys().contains(rangeKey)) emplace(PlaceHolderResult(object)); else emplace(Range(object)); } } std::optional CodeLens::data() const { return contains(dataKey) ? std::make_optional(value(dataKey)) : std::nullopt; } HoverResult::HoverResult(const QJsonValue &value) { if (value.isObject()) emplace(Hover(value.toObject())); else emplace(nullptr); } bool HoverResult::isValid() const { if (auto hover = std::get_if(this)) return hover->isValid(); return true; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/client.cpp0000644000175100017510000000113015232633614017313 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "client.h" namespace lsp { constexpr const char RegisterCapabilityRequest::methodName[]; constexpr const char UnregisterCapabilityRequest::methodName[]; RegisterCapabilityRequest::RegisterCapabilityRequest(const RegistrationParams ¶ms) : Request(methodName, params) { } UnregisterCapabilityRequest::UnregisterCapabilityRequest(const UnregistrationParams ¶ms) : UnregisterCapabilityRequest(methodName, params) { } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/predicates.h0000644000175100017510000000674415232633614017645 0ustar runnerrunner// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include #include #include namespace lsp::Utils { ////////////////// // find helpers ////////////////// template decltype(auto) equal(R (S::*function)() const, T value) { // This should use std::equal_to<> instead of std::equal_to, // but that's not supported everywhere yet, since it is C++14 return std::bind(std::equal_to(), value, std::bind(function, std::placeholders::_1)); } template decltype(auto) equal(R S::*member, T value) { return std::bind(std::equal_to(), value, std::bind(member, std::placeholders::_1)); } ////////////////// // comparison predicates ////////////////// template auto equalTo(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of equalTo should be the same to prevent " "unnecessary conversion."); return entry == value; }; } template auto unequalTo(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of unequalTo should be the same to prevent " "unnecessary conversion."); return !(entry == value); }; } template auto lessThan(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of unequalTo should be the same to prevent " "unnecessary conversion."); return entry < value; }; } template auto lessEqualThan(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of lessEqualThan should be the same to " "prevent unnecessary conversion."); return !(value < entry); }; } template auto greaterThan(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of greaterThan should be the same to " "prevent unnecessary conversion."); return value < entry; }; } template auto greaterEqualThan(Type &&value) { return [value = std::forward(value)] (const auto &entry) { static_assert(std::is_same, std::decay_t>::value, "The container and predicate type of greaterEqualThan should be the same to " "prevent unnecessary conversion."); return !(entry < value); }; } } // namespace Utils qbs-src-3.3.1/src/shared/lsp/workspace.cpp0000644000175100017510000000524415232633614020045 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "workspace.h" namespace lsp { constexpr const char WorkSpaceFolderRequest::methodName[]; constexpr const char DidChangeWorkspaceFoldersNotification::methodName[]; constexpr const char DidChangeConfigurationNotification::methodName[]; constexpr const char ConfigurationRequest::methodName[]; constexpr const char WorkspaceSymbolRequest::methodName[]; constexpr const char ExecuteCommandRequest::methodName[]; constexpr const char ApplyWorkspaceEditRequest::methodName[]; constexpr const char DidChangeWatchedFilesNotification::methodName[]; WorkSpaceFolderRequest::WorkSpaceFolderRequest() : Request(methodName, nullptr) { } DidChangeWorkspaceFoldersNotification::DidChangeWorkspaceFoldersNotification( const DidChangeWorkspaceFoldersParams ¶ms) : Notification(methodName, params) { } DidChangeConfigurationNotification::DidChangeConfigurationNotification( const DidChangeConfigurationParams ¶ms) : Notification(methodName, params) { } ConfigurationRequest::ConfigurationRequest(const ConfigurationParams ¶ms) : Request(methodName, params) { } WorkspaceSymbolRequest::WorkspaceSymbolRequest(const WorkspaceSymbolParams ¶ms) : Request(methodName, params) { } ExecuteCommandRequest::ExecuteCommandRequest(const ExecuteCommandParams ¶ms) : Request(methodName, params) { } ApplyWorkspaceEditRequest::ApplyWorkspaceEditRequest(const ApplyWorkspaceEditParams ¶ms) : Request(methodName, params) { } WorkspaceFoldersChangeEvent::WorkspaceFoldersChangeEvent() { insert(addedKey, QJsonArray()); insert(removedKey, QJsonArray()); } DidChangeWatchedFilesNotification::DidChangeWatchedFilesNotification( const DidChangeWatchedFilesParams ¶ms) : Notification(methodName, params) { } ExecuteCommandParams::ExecuteCommandParams(const Command &command) { setCommand(command.command()); if (command.arguments().has_value()) setArguments(*command.arguments()); } WorkSpaceFolderResult::operator const QJsonValue() const { if (!std::holds_alternative>(*this)) return QJsonValue::Null; QJsonArray array; for (const auto &folder : std::get>(*this)) array.append(QJsonValue(folder)); return array; } std::optional ConfigurationParams::ConfigurationItem::scopeUri() const { if (const std::optional optionalScope = optionalValue(scopeUriKey)) return std::make_optional(DocumentUri::fromProtocol(*optionalScope)); return std::nullopt; } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/initializemessages.h0000644000175100017510000001455615232633614021413 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "clientcapabilities.h" #include "jsonrpcmessages.h" #include "lsptypes.h" #include "servercapabilities.h" namespace lsp { class LANGUAGESERVERPROTOCOL_EXPORT Trace { public: enum Values { off, messages, verbose }; Trace() = default; Trace(Values val) : m_value(val) {} Trace(QString val) : Trace(fromString(val)) {} static Trace fromString(const QString& val); QString toString() const; private: Values m_value = off; }; class LANGUAGESERVERPROTOCOL_EXPORT ClientInfo : public JsonObject { public: using JsonObject::JsonObject; QString name() const { return typedValue(nameKey); } void setName(const QString &name) { insert(nameKey, name); } std::optional version() const { return optionalValue(versionKey); } void setVersion(const QString &version) { insert(versionKey, version); } void clearVersion() { remove(versionKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT InitializeParams : public JsonObject { public: InitializeParams(); using JsonObject::JsonObject; /* * The process Id of the parent process that started * the server. Is null if the process has not been started by another process. * If the parent process is not alive then the server should exit (see exit notification) * its process. */ LanguageClientValue processId() const { return clientValue(processIdKey); } void setProcessId(const LanguageClientValue &id) { insert(processIdKey, id); } /* * The rootPath of the workspace. Is null * if no folder is open. * * @deprecated in favor of rootUri. */ std::optional> rootPath() const { return optionalClientValue(rootPathKey); } void setRootPath(const LanguageClientValue &path) { insert(rootPathKey, path); } void clearRootPath() { remove(rootPathKey); } /* * The rootUri of the workspace. Is null if no * folder is open. If both `rootPath` and `rootUri` are set * `rootUri` wins. */ LanguageClientValue rootUri() const { return clientValue(rootUriKey).transform(); } void setRootUri(const LanguageClientValue &uri) { insert(rootUriKey, uri); } // User provided initialization options. std::optional initializationOptions() const; void setInitializationOptions(const QJsonObject &options) { insert(initializationOptionsKey, options); } void clearInitializationOptions() { remove(initializationOptionsKey); } // The capabilities provided by the client (editor or tool) ClientCapabilities capabilities() const { return typedValue(capabilitiesKey); } void setCapabilities(const ClientCapabilities &capabilities) { insert(capabilitiesKey, capabilities); } // The initial trace setting. If omitted trace is disabled ('off'). std::optional trace() const; void setTrace(Trace trace) { insert(traceKey, trace.toString()); } void clearTrace() { remove(traceKey); } /* * The workspace folders configured in the client when the server starts. * This property is only available if the client supports workspace folders. * It can be `null` if the client supports workspace folders but none are * configured. * * Since 3.6.0 */ std::optional> workspaceFolders() const { return optionalClientArray(workspaceFoldersKey); } void setWorkSpaceFolders(const LanguageClientArray &folders) { insert(workspaceFoldersKey, folders.toJson()); } void clearWorkSpaceFolders() { remove(workspaceFoldersKey); } std::optional clientInfo() const { return optionalValue(clientInfoKey); } void setClientInfo(const ClientInfo &clientInfo) { insert(clientInfoKey, clientInfo); } void clearClientInfo() { remove(clientInfoKey); } bool isValid() const override { return contains(processIdKey) && contains(rootUriKey) && contains(capabilitiesKey); } }; using InitializedParams = JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT InitializeNotification : public Notification { public: explicit InitializeNotification(const InitializedParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "initialized"; bool parametersAreValid(QString * /*errorMessage*/) const final { return true; } }; class LANGUAGESERVERPROTOCOL_EXPORT ServerInfo : public JsonObject { public: using JsonObject::JsonObject; QString name() const { return typedValue(nameKey); } std::optional version() const { return optionalValue(versionKey); } bool isValid() const override { return contains(nameKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT InitializeResult : public JsonObject { public: using JsonObject::JsonObject; ServerCapabilities capabilities() const { return typedValue(capabilitiesKey); } void setCapabilities(const ServerCapabilities &capabilities) { insert(capabilitiesKey, capabilities); } std::optional serverInfo() const { return optionalValue(serverInfoKey); } bool isValid() const override { return contains(capabilitiesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT InitializeError : public JsonObject { public: using JsonObject::JsonObject; /* * Indicates whether the client execute the following retry logic: * (1) show the message provided by the ResponseError to the user * (2) user selects retry or cancel * (3) if user selected retry the initialize method is sent again. */ bool retry() const { return typedValue(retryKey); } void setRetry(const bool &retry) { insert(retryKey, retry); } bool isValid() const override { return contains(retryKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT InitializeRequest : public Request< InitializeResult, InitializeError, InitializeParams> { public: explicit InitializeRequest(const InitializeParams ¶ms); using Request::Request; constexpr static const char methodName[] = "initialize"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/callhierarchy.cpp0000644000175100017510000000147015232633614020656 0ustar runnerrunner// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include "callhierarchy.h" namespace lsp { bool CallHierarchyItem::isValid() const { return contains(nameKey) && contains(symbolKindKey) && contains(rangeKey) && contains(uriKey) && contains(selectionRangeKey); } PrepareCallHierarchyRequest::PrepareCallHierarchyRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) {} CallHierarchyIncomingCallsRequest::CallHierarchyIncomingCallsRequest( const CallHierarchyCallsParams ¶ms) : Request(methodName, params) {} CallHierarchyOutgoingCallsRequest::CallHierarchyOutgoingCallsRequest( const CallHierarchyCallsParams ¶ms) : Request(methodName, params) {} } // namespace lsp qbs-src-3.3.1/src/shared/lsp/messages.h0000644000175100017510000000552515232633614017325 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { enum MessageType { Error = 1, Warning = 2, Info = 3, Log = 4, }; class LANGUAGESERVERPROTOCOL_EXPORT ShowMessageParams : public JsonObject { public: using JsonObject::JsonObject; int type() const { return typedValue(typeKey); } void setType(int type) { insert(typeKey, type); } QString message() const { return typedValue(messageKey); } void setMessage(QString message) { insert(messageKey, message); } QString toString() const; bool isValid() const override { return contains(typeKey) && contains(messageKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ShowMessageNotification : public Notification { public: explicit ShowMessageNotification(const ShowMessageParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "window/showMessage"; }; class LANGUAGESERVERPROTOCOL_EXPORT MessageActionItem : public JsonObject { public: using JsonObject::JsonObject; QString title() const { return typedValue(titleKey); } void setTitle(QString title) { insert(titleKey, title); } bool isValid() const override { return contains(titleKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ShowMessageRequestParams : public ShowMessageParams { public: using ShowMessageParams::ShowMessageParams; std::optional> actions() const { return optionalArray(actionsKey); } void setActions(const QList &actions) { insertArray(actionsKey, actions); } void clearActions() { remove(actionsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ShowMessageRequest : public Request< LanguageClientValue, std::nullptr_t, ShowMessageRequestParams> { public: explicit ShowMessageRequest(const ShowMessageRequestParams ¶ms); using Request::Request; constexpr static const char methodName[] = "window/showMessageRequest"; }; using LogMessageParams = ShowMessageParams; class LANGUAGESERVERPROTOCOL_EXPORT LogMessageNotification : public Notification { public: explicit LogMessageNotification(const LogMessageParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "window/logMessage"; }; class LANGUAGESERVERPROTOCOL_EXPORT TelemetryNotification : public Notification { public: explicit TelemetryNotification(const JsonObject ¶ms); using Notification::Notification; constexpr static const char methodName[] = "telemetry/event"; bool parametersAreValid(QString * /*error*/) const override { return params().has_value(); } }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/languagefeatures.h0000644000175100017510000007436315232633614021046 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" namespace lsp { /** * MarkedString can be used to render human readable text. It is either a markdown string * or a code-block that provides a language and a code snippet. The language identifier * is semantically equal to the optional language identifier in fenced code blocks in GitHub * issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting * * The pair of a language and a value is an equivalent to markdown: * ```${language} * ${value} * ``` * * Note that markdown strings will be sanitized - that means html will be escaped. * @deprecated use MarkupContent instead. */ class LANGUAGESERVERPROTOCOL_EXPORT MarkedLanguageString : public JsonObject { public: using JsonObject::JsonObject; QString language() const { return typedValue(languageKey); } void setLanguage(const QString &language) { insert(languageKey, language); } QString value() const { return typedValue(valueKey); } void setValue(const QString &value) { insert(valueKey, value); } bool isValid() const override { return contains(languageKey) && contains(valueKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT MarkedString : public std::variant { public: MarkedString() = default; explicit MarkedString(const MarkedLanguageString &other) : variant(other) {} explicit MarkedString(const QString &other) : variant(other) {} explicit MarkedString(const QJsonValue &value); bool isValid() const; operator QJsonValue() const; }; class LANGUAGESERVERPROTOCOL_EXPORT HoverContent : public std::variant, MarkupContent> { public: HoverContent() = default; explicit HoverContent(const MarkedString &other) : variant(other) {} explicit HoverContent(const QList &other) : variant(other) {} explicit HoverContent(const MarkupContent &other) : variant(other) {} explicit HoverContent(const QJsonValue &value); bool isValid() const; }; class LANGUAGESERVERPROTOCOL_EXPORT Hover : public JsonObject { public: using JsonObject::JsonObject; HoverContent content() const; void setContent(const HoverContent &content); std::optional range() const { return optionalValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } void clearRange() { remove(rangeKey); } bool isValid() const override { return contains(contentsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT HoverResult : public std::variant { public: HoverResult() : variant(nullptr) {} explicit HoverResult(const Hover &hover) : variant(hover) {} explicit HoverResult(const QJsonValue &value); bool isValid() const; }; class LANGUAGESERVERPROTOCOL_EXPORT HoverRequest : public Request { public: explicit HoverRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/hover"; }; /** * Represents a parameter of a callable-signature. A parameter can * have a label and a doc-comment. */ class LANGUAGESERVERPROTOCOL_EXPORT ParameterInformation : public JsonObject { public: using JsonObject::JsonObject; QString label() const { return typedValue(labelKey); } void setLabel(const QString &label) { insert(labelKey, label); } std::optional documentation() const; void setDocumentation(const MarkupOrString &documentation) { insert(documentationKey, documentation.toJson()); } void clearDocumentation() { remove(documentationKey); } bool isValid() const override { return contains(labelKey); } }; /** * Represents the signature of something callable. A signature * can have a label, like a function-name, a doc-comment, and * a set of parameters. */ class LANGUAGESERVERPROTOCOL_EXPORT SignatureInformation : public ParameterInformation { public: using ParameterInformation::ParameterInformation; std::optional> parameters() const { return optionalArray(parametersKey); } void setParameters(const QList ¶meters) { insertArray(parametersKey, parameters); } void clearParameters() { remove(parametersKey); } std::optional activeParameter() const { return optionalValue(activeParameterKey); } void setActiveParameter(int activeParameter) { insert(activeParameterKey, activeParameter); } void clearActiveParameter() { remove(activeParameterKey); } }; /** * Signature help represents the signature of something * callable. There can be multiple signature but only one * active and only one active parameter. */ class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelp : public JsonObject { public: using JsonObject::JsonObject; /// One or more signatures. QList signatures() const { return array(signaturesKey); } void setSignatures(const QList &signatures) { insertArray(signaturesKey, signatures); } /** * The active signature. If omitted or the value lies outside the * range of `signatures` the value defaults to zero or is ignored if * `signatures.length === 0`. Whenever possible implementors should * make an active decision about the active signature and shouldn't * rely on a default value. * In future version of the protocol this property might become * mandatory to better express this. */ std::optional activeSignature() const { return optionalValue(activeSignatureKey); } void setActiveSignature(int activeSignature) { insert(activeSignatureKey, activeSignature); } void clearActiveSignature() { remove(activeSignatureKey); } /** * The active parameter of the active signature. If omitted or the value * lies outside the range of `signatures[activeSignature].parameters` * defaults to 0 if the active signature has parameters. If * the active signature has no parameters it is ignored. * In future version of the protocol this property might become * mandatory to better express the active parameter if the * active signature does have any. */ std::optional activeParameter() const { return optionalValue(activeParameterKey); } void setActiveParameter(int activeParameter) { insert(activeParameterKey, activeParameter); } void clearActiveParameter() { remove(activeParameterKey); } bool isValid() const override { return contains(signaturesKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpRequest : public Request, std::nullptr_t, TextDocumentPositionParams> { public: explicit SignatureHelpRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/signatureHelp"; }; /// The result of a goto request can either be a location, a list of locations or null class LANGUAGESERVERPROTOCOL_EXPORT GotoResult : public std::variant, std::nullptr_t> { public: explicit GotoResult(const QJsonValue &value); using variant::variant; }; class LANGUAGESERVERPROTOCOL_EXPORT GotoDefinitionRequest : public Request { public: explicit GotoDefinitionRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/definition"; }; class LANGUAGESERVERPROTOCOL_EXPORT GotoTypeDefinitionRequest : public Request< GotoResult, std::nullptr_t, TextDocumentPositionParams> { public: explicit GotoTypeDefinitionRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/typeDefinition"; }; class LANGUAGESERVERPROTOCOL_EXPORT GotoImplementationRequest : public Request< GotoResult, std::nullptr_t, TextDocumentPositionParams> { public: explicit GotoImplementationRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/implementation"; }; class LANGUAGESERVERPROTOCOL_EXPORT ReferenceParams : public TextDocumentPositionParams { public: using TextDocumentPositionParams::TextDocumentPositionParams; class ReferenceContext : public JsonObject { public: explicit ReferenceContext(bool includeDeclaration) { setIncludeDeclaration(includeDeclaration); } ReferenceContext() = default; using JsonObject::JsonObject; bool includeDeclaration() const { return typedValue(includeDeclarationKey); } void setIncludeDeclaration(bool includeDeclaration) { insert(includeDeclarationKey, includeDeclaration); } bool isValid() const override { return contains(includeDeclarationKey); } }; ReferenceContext context() const { return typedValue(contextKey); } void setContext(const ReferenceContext &context) { insert(contextKey, context); } bool isValid() const override { return TextDocumentPositionParams::isValid() && contains(contextKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT FindReferencesRequest : public Request< LanguageClientArray, std::nullptr_t, ReferenceParams> { public: explicit FindReferencesRequest(const ReferenceParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/references"; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentHighlight : public JsonObject { public: using JsonObject::JsonObject; enum DocumentHighlightKind { Text = 1, Read = 2, Write = 3 }; Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } std::optional kind() const { return optionalValue(kindKey); } void setKind(int kind) { insert(kindKey, kind); } void clearKind() { remove(kindKey); } bool isValid() const override { return contains(rangeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentHighlightsResult : public std::variant, std::nullptr_t> { public: using variant::variant; DocumentHighlightsResult() : variant(nullptr) {} explicit DocumentHighlightsResult(const QJsonValue &value); using variant::operator=; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentHighlightsRequest : public Request< DocumentHighlightsResult, std::nullptr_t, TextDocumentPositionParams> { public: explicit DocumentHighlightsRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/documentHighlight"; }; class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentParams : public JsonObject { public: TextDocumentParams(); explicit TextDocumentParams(const TextDocumentIdentifier &identifier); using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } bool isValid() const override { return contains(textDocumentKey); } }; using DocumentSymbolParams = TextDocumentParams; class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbolsResult : public std::variant, QList, std::nullptr_t> { public: using variant::variant; DocumentSymbolsResult() : variant(nullptr) {} explicit DocumentSymbolsResult(const QJsonValue &value); DocumentSymbolsResult(const DocumentSymbolsResult &other) : variant(other) {} DocumentSymbolsResult(DocumentSymbolsResult &&other) : variant(std::move(other)) {} using variant::operator=; DocumentSymbolsResult &operator =(DocumentSymbolsResult &&other) { variant::operator=(std::move(other)); return *this; } DocumentSymbolsResult &operator =(const DocumentSymbolsResult &other) { variant::operator=(other); return *this; } // Needed to make it usable in Qt 6 signals. bool operator<(const DocumentSymbolsResult &other) const = delete; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbolsRequest : public Request { public: explicit DocumentSymbolsRequest(const DocumentSymbolParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/documentSymbol"; }; /** * The kind of a code action. * * Kinds are a hierarchical list of identifiers separated by `.`, e.g. `"refactor.extract.function"`. * * The set of kinds is open and client needs to announce the kinds it supports to the server during * initialization. */ using CodeActionKind = QString; /** * A set of predefined code action kinds */ namespace CodeActionKinds { constexpr char QuickFix[] = "quickfix"; constexpr char Refactor[] = "refactor"; constexpr char RefactorExtract[] = "refactor.extract"; constexpr char RefactorInline[] = "refactor.inline"; constexpr char RefactorRewrite[] = "refactor.rewrite"; constexpr char Source[] = "source"; constexpr char SourceOrganizeImports[] = "source.organizeImports"; } class LANGUAGESERVERPROTOCOL_EXPORT CodeActionParams : public JsonObject { public: using JsonObject::JsonObject; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionContext : public JsonObject { public: using JsonObject::JsonObject; QList diagnostics() const { return array(diagnosticsKey); } void setDiagnostics(const QList &diagnostics) { insertArray(diagnosticsKey, diagnostics); } std::optional> only() const; void setOnly(const QList &only); void clearOnly() { remove(onlyKey); } bool isValid() const override { return contains(diagnosticsKey); } }; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } CodeActionContext context() const { return typedValue(contextKey); } void setContext(const CodeActionContext &context) { insert(contextKey, context); } bool isValid() const override { return contains(textDocumentKey) && contains(rangeKey) && contains(contextKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CodeAction : public JsonObject { public: using JsonObject::JsonObject; QString title() const { return typedValue(titleKey); } void setTitle(QString title) { insert(titleKey, title); } std::optional kind() const { return optionalValue(kindKey); } void setKind(const CodeActionKind &kind) { insert(kindKey, kind); } void clearKind() { remove(kindKey); } std::optional> diagnostics() const { return optionalArray(diagnosticsKey); } void setDiagnostics(const QList &diagnostics) { insertArray(diagnosticsKey, diagnostics); } void clearDiagnostics() { remove(diagnosticsKey); } std::optional edit() const { return optionalValue(editKey); } void setEdit(const WorkspaceEdit &edit) { insert(editKey, edit); } void clearEdit() { remove(editKey); } std::optional command() const { return optionalValue(commandKey); } void setCommand(const Command &command) { insert(commandKey, command); } void clearCommand() { remove(commandKey); } bool isValid() const override { return contains(titleKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionResult : public std::variant>, std::nullptr_t> { public: using variant::variant; explicit CodeActionResult(const QJsonValue &val); }; class LANGUAGESERVERPROTOCOL_EXPORT CodeActionRequest : public Request< CodeActionResult, std::nullptr_t, CodeActionParams> { public: explicit CodeActionRequest(const CodeActionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/codeAction"; }; using CodeLensParams = TextDocumentParams; class LANGUAGESERVERPROTOCOL_EXPORT CodeLens : public JsonObject { public: using JsonObject::JsonObject; Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } std::optional command() const { return optionalValue(commandKey); } void setCommand(const Command &command) { insert(commandKey, command); } void clearCommand() { remove(commandKey); } std::optional data() const; void setData(const QJsonValue &data) { insert(dataKey, data); } void clearData() { remove(dataKey); } bool isValid() const override { return contains(rangeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT CodeLensRequest : public Request< LanguageClientArray, std::nullptr_t, CodeLensParams> { public: explicit CodeLensRequest(const CodeLensParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/codeLens"; }; class LANGUAGESERVERPROTOCOL_EXPORT CodeLensResolveRequest : public Request< CodeLens, std::nullptr_t, CodeLens> { public: explicit CodeLensResolveRequest(const CodeLens ¶ms); using Request::Request; constexpr static const char methodName[] = "codeLens/resolve"; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentLink : public JsonObject { public: using JsonObject::JsonObject; Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } std::optional target() const; void setTarget(const DocumentUri &target) { insert(targetKey, target.toString()); } void clearTarget() { remove(targetKey); } std::optional data() const; void setData(const QJsonValue &data) { insert(dataKey, data); } void clearData() { remove(dataKey); } bool isValid() const override { return contains(rangeKey); } }; using DocumentLinkParams = TextDocumentParams; class LANGUAGESERVERPROTOCOL_EXPORT DocumentLinkRequest : public Request< LanguageClientValue, std::nullptr_t, DocumentLinkParams> { public: explicit DocumentLinkRequest(const DocumentLinkParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/documentLink"; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentLinkResolveRequest : public Request< DocumentLink, std::nullptr_t, DocumentLink> { public: explicit DocumentLinkResolveRequest(const DocumentLink ¶ms); using Request::Request; constexpr static const char methodName[] = "documentLink/resolve"; }; using DocumentColorParams = TextDocumentParams; class LANGUAGESERVERPROTOCOL_EXPORT Color : public JsonObject { public: using JsonObject::JsonObject; double red() const { return typedValue(redKey); } void setRed(double red) { insert(redKey, red); } double green() const { return typedValue(greenKey); } void setGreen(double green) { insert(greenKey, green); } double blue() const { return typedValue(blueKey); } void setBlue(double blue) { insert(blueKey, blue); } double alpha() const { return typedValue(alphaKey); } void setAlpha(double alpha) { insert(alphaKey, alpha); } bool isValid() const override { return contains(redKey) && contains(greenKey) && contains(blueKey) && contains(alphaKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ColorInformation : public JsonObject { public: using JsonObject::JsonObject; Range range() const { return typedValue(rangeKey); } void setRange(Range range) { insert(rangeKey, range); } Color color() const { return typedValue(colorKey); } void setColor(const Color &color) { insert(colorKey, color); } bool isValid() const override { return contains(rangeKey) && contains(colorKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentColorRequest : public Request< QList, std::nullptr_t, DocumentColorParams> { public: explicit DocumentColorRequest(const DocumentColorParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/documentColor"; }; class LANGUAGESERVERPROTOCOL_EXPORT ColorPresentationParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } Color colorInfo() const { return typedValue(colorInfoKey); } void setColorInfo(const Color &colorInfo) { insert(colorInfoKey, colorInfo); } Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } bool isValid() const override { return contains(textDocumentKey) && contains(colorInfoKey) && contains(rangeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ColorPresentation : public JsonObject { public: using JsonObject::JsonObject; QString label() const { return typedValue(labelKey); } void setLabel(const QString &label) { insert(labelKey, label); } std::optional textEdit() const { return optionalValue(textEditKey); } void setTextEdit(const TextEdit &textEdit) { insert(textEditKey, textEdit); } void clearTextEdit() { remove(textEditKey); } std::optional> additionalTextEdits() const { return optionalArray(additionalTextEditsKey); } void setAdditionalTextEdits(const QList &additionalTextEdits) { insertArray(additionalTextEditsKey, additionalTextEdits); } void clearAdditionalTextEdits() { remove(additionalTextEditsKey); } bool isValid() const override { return contains(labelKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT ColorPresentationRequest : public Request< QList, std::nullptr_t, ColorPresentationParams> { public: explicit ColorPresentationRequest(const ColorPresentationParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/colorPresentation"; }; class DocumentFormattingProperty : public std::variant { public: DocumentFormattingProperty() = default; explicit DocumentFormattingProperty(const QJsonValue &value); explicit DocumentFormattingProperty(const DocumentFormattingProperty &other) : std::variant(other) {} using variant::variant; using variant::operator=; }; class LANGUAGESERVERPROTOCOL_EXPORT FormattingOptions : public JsonObject { public: using JsonObject::JsonObject; int tabSize() const { return typedValue(tabSizeKey); } void setTabSize(int tabSize) { insert(tabSizeKey, tabSize); } bool insertSpace() const { return typedValue(insertSpaceKey); } void setInsertSpace(bool insertSpace) { insert(insertSpaceKey, insertSpace); } std::optional trimTrailingWhitespace() const { return optionalValue(trimTrailingWhitespaceKey); } void setTrimTrailingWhitespace(bool trimTrailingWhitespace) { insert(trimTrailingWhitespaceKey, trimTrailingWhitespace); } void clearTrimTrailingWhitespace() { remove(trimTrailingWhitespaceKey); } std::optional insertFinalNewline() const { return optionalValue(insertFinalNewlineKey); } void setInsertFinalNewline(bool insertFinalNewline) { insert(insertFinalNewlineKey, insertFinalNewline); } void clearInsertFinalNewline() { remove(insertFinalNewlineKey); } std::optional trimFinalNewlines() const { return optionalValue(trimFinalNewlinesKey); } void setTrimFinalNewlines(bool trimFinalNewlines) { insert(trimFinalNewlinesKey, trimFinalNewlines); } void clearTrimFinalNewlines() { remove(trimFinalNewlinesKey); } QHash properties() const; void setProperty(const std::string_view key, const DocumentFormattingProperty &property); void removeProperty(const std::string_view &key) { remove(key); } bool isValid() const override { return contains(insertSpaceKey) && contains(tabSizeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentFormattingParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } FormattingOptions options() const { return typedValue(optionsKey); } void setOptions(const FormattingOptions &options) { insert(optionsKey, options); } bool isValid() const override { return contains(textDocumentKey) && contains(optionsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentFormattingRequest : public Request< LanguageClientArray, std::nullptr_t, DocumentFormattingParams> { public: explicit DocumentFormattingRequest(const DocumentFormattingParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/formatting"; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentRangeFormattingParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } FormattingOptions options() const { return typedValue(optionsKey); } void setOptions(const FormattingOptions &options) { insert(optionsKey, options); } bool isValid() const override { return contains(textDocumentKey) && contains(rangeKey) && contains(optionsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentRangeFormattingRequest : public Request< LanguageClientArray, std::nullptr_t, DocumentRangeFormattingParams> { public: explicit DocumentRangeFormattingRequest(const DocumentRangeFormattingParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/rangeFormatting"; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentOnTypeFormattingParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } Position position() const { return typedValue(positionKey); } void setPosition(const Position &position) { insert(positionKey, position); } QString ch() const { return typedValue(chKey); } void setCh(const QString &ch) { insert(chKey, ch); } FormattingOptions options() const { return typedValue(optionsKey); } void setOptions(const FormattingOptions &options) { insert(optionsKey, options); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT DocumentOnTypeFormattingRequest : public Request< LanguageClientArray, std::nullptr_t, DocumentOnTypeFormattingParams> { public: explicit DocumentOnTypeFormattingRequest(const DocumentOnTypeFormattingParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/onTypeFormatting"; }; class PlaceHolderResult : public JsonObject { public: using JsonObject::JsonObject; Range range() const { return typedValue(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } QString placeHolder() const { return typedValue(placeHolderKey); } void setPlaceHolder(const QString &placeHolder) { insert(placeHolderKey, placeHolder); } bool isValid() const override { return contains(rangeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT PrepareRenameResult : public std::variant { public: PrepareRenameResult(); PrepareRenameResult(const std::variant &val); explicit PrepareRenameResult(const PlaceHolderResult &val); explicit PrepareRenameResult(const Range &val); explicit PrepareRenameResult(const QJsonValue &val); bool isValid() const; }; class LANGUAGESERVERPROTOCOL_EXPORT PrepareRenameRequest : public Request { public: explicit PrepareRenameRequest(const TextDocumentPositionParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/prepareRename"; }; class LANGUAGESERVERPROTOCOL_EXPORT RenameParams : public JsonObject { public: using JsonObject::JsonObject; TextDocumentIdentifier textDocument() const { return typedValue(textDocumentKey); } void setTextDocument(const TextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } Position position() const { return typedValue(positionKey); } void setPosition(const Position &position) { insert(positionKey, position); } QString newName() const { return typedValue(newNameKey); } void setNewName(const QString &newName) { insert(newNameKey, newName); } bool isValid() const override; }; class LANGUAGESERVERPROTOCOL_EXPORT RenameRequest : public Request< WorkspaceEdit, std::nullptr_t, RenameParams> { public: explicit RenameRequest(const RenameParams ¶ms); using Request::Request; constexpr static const char methodName[] = "textDocument/rename"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/languageserverprotocol_global.h0000644000175100017510000000065715232633614023633 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include #if defined(LANGUAGESERVERPROTOCOL_LIBRARY) # define LANGUAGESERVERPROTOCOL_EXPORT Q_DECL_EXPORT #elif defined(LANGUAGESERVERPROTOCOL_STATIC_LIBRARY) # define LANGUAGESERVERPROTOCOL_EXPORT #else # define LANGUAGESERVERPROTOCOL_EXPORT Q_DECL_IMPORT #endif qbs-src-3.3.1/src/shared/lsp/messages.cpp0000644000175100017510000000241015232633614017646 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "messages.h" namespace lsp { constexpr const char ShowMessageNotification::methodName[]; constexpr const char ShowMessageRequest::methodName[]; constexpr const char LogMessageNotification::methodName[]; constexpr const char TelemetryNotification::methodName[]; ShowMessageNotification::ShowMessageNotification(const ShowMessageParams ¶ms) : Notification(methodName, params) { } ShowMessageRequest::ShowMessageRequest(const ShowMessageRequestParams ¶ms) : Request(methodName, params) { } LogMessageNotification::LogMessageNotification(const LogMessageParams ¶ms) : Notification(methodName, params) { } TelemetryNotification::TelemetryNotification(const JsonObject ¶ms) : Notification(methodName, params) { } static QString messageTypeName(int messageType) { switch (messageType) { case Error: return QString("Error"); case Warning: return QString("Warning"); case Info: return QString("Info"); case Log: return QString("Log"); } return QString(""); } QString ShowMessageParams::toString() const { return messageTypeName(type()) + ": " + message(); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/diagnostics.h0000644000175100017510000000245315232633614020022 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "jsonrpcmessages.h" #include "languagefeatures.h" namespace lsp { class PublishDiagnosticsParams : public JsonObject { public: using JsonObject::JsonObject; DocumentUri uri() const { return DocumentUri::fromProtocol(typedValue(uriKey)); } void setUri(const DocumentUri &uri) { insert(uriKey, uri); } QList diagnostics() const { return array(diagnosticsKey); } void setDiagnostics(const QList &diagnostics) { insertArray(diagnosticsKey, diagnostics); } std::optional version() const { return optionalValue(versionKey); } void setVersion(int version) { insert(versionKey, version); } void clearVersion() { remove(versionKey); } bool isValid() const override { return contains(diagnosticsKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT PublishDiagnosticsNotification : public Notification { public: explicit PublishDiagnosticsNotification(const PublishDiagnosticsParams ¶ms); using Notification::Notification; constexpr static const char methodName[] = "textDocument/publishDiagnostics"; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/basemessage.h0000644000175100017510000000226215232633614017770 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "languageserverprotocol_global.h" #include #include #include QT_BEGIN_NAMESPACE class QBuffer; class QTextCodec; QT_END_NAMESPACE namespace lsp { LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(parseLog) class LANGUAGESERVERPROTOCOL_EXPORT BaseMessage { public: BaseMessage(); BaseMessage(const QByteArray &mimeType, const QByteArray &content, int expectedLength, QTextCodec *codec); BaseMessage(const QByteArray &mimeType, const QByteArray &content); bool operator==(const BaseMessage &other) const; static void parse(QBuffer *data, QString &parseError, BaseMessage &message); static QTextCodec *defaultCodec(); bool isComplete() const; bool isValid() const; QByteArray header() const; QByteArray mimeType; QByteArray content; int contentLength = -1; QTextCodec *codec = defaultCodec(); private: QByteArray lengthHeader() const; QByteArray typeHeader() const; }; } // namespace LanguageClient qbs-src-3.3.1/src/shared/lsp/languageserverprotocoltr.h0000644000175100017510000000045215232633614022652 0ustar runnerrunner// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include namespace lsp { struct Tr { Q_DECLARE_TR_FUNCTIONS(QtC::LanguageServerProtocol) }; } // LanguageServerProtocol qbs-src-3.3.1/src/shared/lsp/filepath.h0000644000175100017510000000511315232633614017303 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #include #include #include #include namespace lsp::Utils { class FilePath : public QString { public: FilePath() = default; FilePath(const QString &s) : QString(s) {} QString scheme() const { return {}; } QString host() const { return {}; } Qt::CaseSensitivity caseSensitivity() const { return qbs::Internal::HostOsInfo::fileNameCaseSensitivity(); } QString toString() const { return *this; } QString path() const { return toString(); } static FilePath fromUserInput(const QString &s) { return QDir::fromNativeSeparators(s); } QString toUserOutput() const { return QDir::toNativeSeparators(*this); } }; } // namespace lsp::Utils qbs-src-3.3.1/src/shared/lsp/textsynchronization.cpp0000644000175100017510000000525615232633614022220 0ustar runnerrunner// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "textsynchronization.h" namespace lsp { constexpr const char DidOpenTextDocumentNotification::methodName[]; constexpr const char DidChangeTextDocumentNotification::methodName[]; constexpr const char WillSaveTextDocumentNotification::methodName[]; constexpr const char WillSaveWaitUntilTextDocumentRequest::methodName[]; constexpr const char DidSaveTextDocumentNotification::methodName[]; constexpr const char DidCloseTextDocumentNotification::methodName[]; DidOpenTextDocumentNotification::DidOpenTextDocumentNotification( const DidOpenTextDocumentParams ¶ms) : Notification(methodName, params) { } DidChangeTextDocumentNotification::DidChangeTextDocumentNotification( const DidChangeTextDocumentParams ¶ms) : DidChangeTextDocumentNotification(methodName, params) { } WillSaveTextDocumentNotification::WillSaveTextDocumentNotification( const WillSaveTextDocumentParams ¶ms) : Notification(methodName, params) { } WillSaveWaitUntilTextDocumentRequest::WillSaveWaitUntilTextDocumentRequest(const WillSaveTextDocumentParams ¶ms) : Request(methodName, params) { } DidSaveTextDocumentNotification::DidSaveTextDocumentNotification( const DidSaveTextDocumentParams ¶ms) : Notification(methodName, params) { } DidCloseTextDocumentNotification::DidCloseTextDocumentNotification( const DidCloseTextDocumentParams ¶ms) : Notification(methodName, params) { } DidChangeTextDocumentParams::DidChangeTextDocumentParams() : DidChangeTextDocumentParams(VersionedTextDocumentIdentifier()) { } DidChangeTextDocumentParams::DidChangeTextDocumentParams( const VersionedTextDocumentIdentifier &docId, const QString &text) { setTextDocument(docId); setContentChanges({TextDocumentContentChangeEvent(text)}); } DidOpenTextDocumentParams::DidOpenTextDocumentParams(const TextDocumentItem &document) { setTextDocument(document); } DidCloseTextDocumentParams::DidCloseTextDocumentParams(const TextDocumentIdentifier &document) { setTextDocument(document); } DidChangeTextDocumentParams::TextDocumentContentChangeEvent::TextDocumentContentChangeEvent( const QString &text) { setText(text); } DidSaveTextDocumentParams::DidSaveTextDocumentParams(const TextDocumentIdentifier &document) { setTextDocument(document); } WillSaveTextDocumentParams::WillSaveTextDocumentParams( const TextDocumentIdentifier &document, const WillSaveTextDocumentParams::TextDocumentSaveReason &reason) { setTextDocument(document); setReason(reason); } } // namespace lsp qbs-src-3.3.1/src/shared/lsp/textutils.h0000644000175100017510000000224015232633614017552 0ustar runnerrunner// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include #include namespace lsp::Utils::Text { class Position { public: int line = 0; // 1-based int column = -1; // 0-based bool operator<(const Position &other) const { return line < other.line || (line == other.line && column < other.column); } bool operator==(const Position &other) const; bool operator!=(const Position &other) const { return !(operator==(other)); } bool isValid() const { return line > 0 && column >= 0; } static Position fromFileName(QStringView fileName, int &postfixPos); }; class Range { public: int length(const QString &text) const; Position begin; Position end; bool operator<(const Range &other) const { return begin < other.begin; } bool operator==(const Range &other) const; bool operator!=(const Range &other) const { return !(operator==(other)); } }; QString utf16LineTextInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset); QDebug &operator<<(QDebug &stream, const Position &pos); } // Text qbs-src-3.3.1/src/shared/span/0000755000175100017510000000000015232633614015501 5ustar runnerrunnerqbs-src-3.3.1/src/shared/span/LICENSE_1_0.txt0000644000175100017510000000247215232633614017770 0ustar runnerrunnerBoost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qbs-src-3.3.1/src/shared/span/CMakeLists.txt0000644000175100017510000000017715232633614020246 0ustar runnerrunneradd_library(span INTERFACE) target_include_directories( span INTERFACE $) qbs-src-3.3.1/src/shared/span/span.qbs0000644000175100017510000000034215232633614017150 0ustar runnerrunnerProduct { name: "span" files: [ "LICENSE_1_0.txt", "README.md", "span.hpp", ] Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.sourceDirectory } } qbs-src-3.3.1/src/shared/span/span.hpp0000644000175100017510000015331315232633614017161 0ustar runnerrunner// // span for C++98 and later. // Based on http://wg21.link/p0122r7 // For more information see https://github.com/martinmoene/span-lite // // Copyright 2018-2021 Martin Moene // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef NONSTD_SPAN_HPP_INCLUDED #define NONSTD_SPAN_HPP_INCLUDED #define span_lite_MAJOR 0 #define span_lite_MINOR 11 #define span_lite_PATCH 0 #define span_lite_VERSION span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH) #define span_STRINGIFY( x ) span_STRINGIFY_( x ) #define span_STRINGIFY_( x ) #x // span configuration: #define span_SPAN_DEFAULT 0 #define span_SPAN_NONSTD 1 #define span_SPAN_STD 2 // tweak header support: #ifdef __has_include # if __has_include() # include # endif #define span_HAVE_TWEAK_HEADER 1 #else #define span_HAVE_TWEAK_HEADER 0 //# pragma message("span.hpp: Note: Tweak header not supported.") #endif // span selection and configuration: #define span_HAVE( feature ) ( span_HAVE_##feature ) #ifndef span_CONFIG_SELECT_SPAN # define span_CONFIG_SELECT_SPAN ( span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD ) #endif #ifndef span_CONFIG_EXTENT_TYPE # define span_CONFIG_EXTENT_TYPE std::size_t #endif #ifndef span_CONFIG_SIZE_TYPE # define span_CONFIG_SIZE_TYPE std::size_t #endif #ifdef span_CONFIG_INDEX_TYPE # error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`. #endif // span configuration (features): #ifndef span_FEATURE_WITH_INITIALIZER_LIST_P2447 # define span_FEATURE_WITH_INITIALIZER_LIST_P2447 0 #endif #ifndef span_FEATURE_WITH_CONTAINER #ifdef span_FEATURE_WITH_CONTAINER_TO_STD # define span_FEATURE_WITH_CONTAINER span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD ) #else # define span_FEATURE_WITH_CONTAINER 0 # define span_FEATURE_WITH_CONTAINER_TO_STD 0 #endif #endif #ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE # define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0 #endif #ifndef span_FEATURE_MEMBER_AT # define span_FEATURE_MEMBER_AT 0 #endif #ifndef span_FEATURE_MEMBER_BACK_FRONT # define span_FEATURE_MEMBER_BACK_FRONT 1 #endif #ifndef span_FEATURE_MEMBER_CALL_OPERATOR # define span_FEATURE_MEMBER_CALL_OPERATOR 0 #endif #ifndef span_FEATURE_MEMBER_SWAP # define span_FEATURE_MEMBER_SWAP 0 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0 #elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0 #endif #ifndef span_FEATURE_COMPARISON # define span_FEATURE_COMPARISON 0 // Note: C++20 does not provide comparison #endif #ifndef span_FEATURE_SAME # define span_FEATURE_SAME 0 #endif #if span_FEATURE_SAME && !span_FEATURE_COMPARISON # error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON` #endif #ifndef span_FEATURE_MAKE_SPAN #ifdef span_FEATURE_MAKE_SPAN_TO_STD # define span_FEATURE_MAKE_SPAN span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD ) #else # define span_FEATURE_MAKE_SPAN 0 # define span_FEATURE_MAKE_SPAN_TO_STD 0 #endif #endif #ifndef span_FEATURE_BYTE_SPAN # define span_FEATURE_BYTE_SPAN 0 #endif // Control presence of exception handling (try and auto discover): #ifndef span_CONFIG_NO_EXCEPTIONS # if defined(_MSC_VER) # include // for _HAS_EXCEPTIONS # endif # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) # define span_CONFIG_NO_EXCEPTIONS 0 # else # define span_CONFIG_NO_EXCEPTIONS 1 # undef span_CONFIG_CONTRACT_VIOLATION_THROWS # undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES # define span_CONFIG_CONTRACT_VIOLATION_THROWS 0 # define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1 # endif #endif // Control pre- and postcondition violation behaviour: #if defined( span_CONFIG_CONTRACT_LEVEL_ON ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 #elif defined( span_CONFIG_CONTRACT_LEVEL_OFF ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x00 #elif defined( span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x01 #elif defined( span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x10 #else # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 #endif #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS #else # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 #endif #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) && span_CONFIG_CONTRACT_VIOLATION_THROWS && \ defined( span_CONFIG_CONTRACT_VIOLATION_TERMINATES ) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES # error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both. #endif // C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. #ifndef span_CPLUSPLUS # if defined(_MSVC_LANG ) && !defined(__clang__) # define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) # else # define span_CPLUSPLUS __cplusplus # endif #endif #define span_CPP98_OR_GREATER ( span_CPLUSPLUS >= 199711L ) #define span_CPP11_OR_GREATER ( span_CPLUSPLUS >= 201103L ) #define span_CPP14_OR_GREATER ( span_CPLUSPLUS >= 201402L ) #define span_CPP17_OR_GREATER ( span_CPLUSPLUS >= 201703L ) #define span_CPP20_OR_GREATER ( span_CPLUSPLUS >= 202002L ) #define span_CPP23_OR_GREATER ( span_CPLUSPLUS >= 202300L ) // C++ language version (represent 98 as 3): #define span_CPLUSPLUS_V ( span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994) ) #define span_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V ) #define span_CONFIG( feature ) ( span_CONFIG_##feature ) #define span_FEATURE( feature ) ( span_FEATURE_##feature ) #define span_FEATURE_TO_STD( feature ) ( span_IN_STD( span_FEATURE( feature##_TO_STD ) ) ) // Use C++20 std::span if available and requested: #if span_CPP20_OR_GREATER && defined(__has_include ) # if __has_include( ) # define span_HAVE_STD_SPAN 1 # else # define span_HAVE_STD_SPAN 0 # endif #else # define span_HAVE_STD_SPAN 0 #endif #define span_USES_STD_SPAN ( (span_CONFIG_SELECT_SPAN == span_SPAN_STD) || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN) ) // // Use C++20 std::span: // #if span_USES_STD_SPAN #include namespace nonstd { using std::span; using std::dynamic_extent; // Note: C++20 does not provide comparison // using std::operator==; // using std::operator!=; // using std::operator<; // using std::operator<=; // using std::operator>; // using std::operator>=; } // namespace nonstd #else // span_USES_STD_SPAN #include // Compiler versions: // // MSVC++ 6.0 _MSC_VER == 1200 span_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) // MSVC++ 7.0 _MSC_VER == 1300 span_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) // MSVC++ 7.1 _MSC_VER == 1310 span_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) // MSVC++ 8.0 _MSC_VER == 1400 span_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) // MSVC++ 9.0 _MSC_VER == 1500 span_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) // MSVC++ 10.0 _MSC_VER == 1600 span_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) // MSVC++ 11.0 _MSC_VER == 1700 span_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) // MSVC++ 12.0 _MSC_VER == 1800 span_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) // MSVC++ 14.0 _MSC_VER == 1900 span_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) // MSVC++ 14.1 _MSC_VER >= 1910 span_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) // MSVC++ 14.2 _MSC_VER >= 1920 span_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) #if defined(_MSC_VER ) && !defined(__clang__) # define span_COMPILER_MSVC_VER (_MSC_VER ) # define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) #else # define span_COMPILER_MSVC_VER 0 # define span_COMPILER_MSVC_VERSION 0 #endif #define span_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) #if defined(__clang__) # define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else # define span_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) # define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else # define span_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): #define span_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) // Compiler warning suppression: #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wundef" # pragma clang diagnostic ignored "-Wmismatched-tags" # define span_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" ) #elif defined __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wundef" # define span_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" ) #elif span_COMPILER_MSVC_VER >= 1900 # define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) # define span_RESTORE_WARNINGS() __pragma(warning(pop )) // Suppress the following MSVC GSL warnings: // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept' // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept' // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; // use brace initialization, gsl::narrow_cast or gsl::narrow // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead // - C26490: gsl::t.1 : don't use reinterpret_cast span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) #else # define span_RESTORE_WARNINGS() /*empty*/ #endif // Presence of language and library features: #ifdef _HAS_CPP0X # define span_HAS_CPP0X _HAS_CPP0X #else # define span_HAS_CPP0X 0 #endif #define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400) #define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500) #define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600) #define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700) #define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) #define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) #define span_CPP14_000 (span_CPP14_OR_GREATER) #define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) #define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) #define span_CPP17_000 (span_CPP17_OR_GREATER) // Presence of C++11 language features: #define span_HAVE_ALIAS_TEMPLATE span_CPP11_140 #define span_HAVE_AUTO span_CPP11_100 #define span_HAVE_CONSTEXPR_11 span_CPP11_140 #define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120 #define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140 #define span_HAVE_INITIALIZER_LIST span_CPP11_120 #define span_HAVE_IS_DEFAULT span_CPP11_140 #define span_HAVE_IS_DELETE span_CPP11_140 #define span_HAVE_NOEXCEPT span_CPP11_140 #define span_HAVE_NORETURN ( span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 480 ) ) #define span_HAVE_NULLPTR span_CPP11_100 #define span_HAVE_STATIC_ASSERT span_CPP11_100 // Presence of C++14 language features: #define span_HAVE_CONSTEXPR_14 span_CPP14_000 // Presence of C++17 language features: #define span_HAVE_DEPRECATED span_CPP17_000 #define span_HAVE_NODISCARD span_CPP17_000 // MSVC: template parameter deduction guides since Visual Studio 2017 v15.7 #if defined(__cpp_deduction_guides) # define span_HAVE_DEDUCTION_GUIDES 1 #else # define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 )) #endif // Presence of C++ library features: #define span_HAVE_ADDRESSOF span_CPP17_000 #define span_HAVE_ARRAY span_CPP11_110 #define span_HAVE_BYTE span_CPP17_000 #define span_HAVE_CONDITIONAL span_CPP11_120 #define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X )) #define span_HAVE_DATA span_CPP17_000 #define span_HAVE_LONGLONG span_CPP11_80 #define span_HAVE_REMOVE_CONST span_CPP11_110 #define span_HAVE_SNPRINTF span_CPP11_140 #define span_HAVE_STRUCT_BINDING span_CPP11_120 #define span_HAVE_TYPE_TRAITS span_CPP11_90 // Presence of byte-lite: #ifdef NONSTD_BYTE_LITE_HPP # define span_HAVE_NONSTD_BYTE 1 #else # define span_HAVE_NONSTD_BYTE 0 #endif // C++ feature usage: #if span_HAVE_ADDRESSOF # define span_ADDRESSOF(x) std::addressof(x) #else # define span_ADDRESSOF(x) (&x) #endif #if span_HAVE_CONSTEXPR_11 # define span_constexpr constexpr #else # define span_constexpr /*span_constexpr*/ #endif #if span_HAVE_CONSTEXPR_14 # define span_constexpr14 constexpr #else # define span_constexpr14 /*span_constexpr*/ #endif #if span_HAVE_EXPLICIT_CONVERSION # define span_explicit explicit #else # define span_explicit /*explicit*/ #endif #if span_HAVE_IS_DELETE # define span_is_delete = delete #else # define span_is_delete #endif #if span_HAVE_IS_DELETE # define span_is_delete_access public #else # define span_is_delete_access private #endif #if span_HAVE_NOEXCEPT && ! span_CONFIG_CONTRACT_VIOLATION_THROWS_V # define span_noexcept noexcept #else # define span_noexcept /*noexcept*/ #endif #if span_HAVE_NULLPTR # define span_nullptr nullptr #else # define span_nullptr NULL #endif #if span_HAVE_DEPRECATED # define span_deprecated(msg) [[deprecated(msg)]] #else # define span_deprecated(msg) /*[[deprecated]]*/ #endif #if span_HAVE_NODISCARD # define span_nodiscard [[nodiscard]] #else # define span_nodiscard /*[[nodiscard]]*/ #endif #if span_HAVE_NORETURN # define span_noreturn [[noreturn]] #else # define span_noreturn /*[[noreturn]]*/ #endif // Other features: #define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG #define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG // Additional includes: #if span_HAVE( ADDRESSOF ) # include #endif #if span_HAVE( ARRAY ) # include #endif #if span_HAVE( BYTE ) # include #endif #if span_HAVE( DATA ) # include // for std::data(), std::size() #endif #if span_HAVE( TYPE_TRAITS ) # include #endif #if ! span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) # include #endif #if span_FEATURE( MEMBER_AT ) > 1 # include #endif #if ! span_CONFIG( NO_EXCEPTIONS ) # include #endif // Contract violation #define span_ELIDE_CONTRACT_EXPECTS ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) ) #define span_ELIDE_CONTRACT_ENSURES ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) ) #if span_ELIDE_CONTRACT_EXPECTS # define span_constexpr_exp span_constexpr # define span_EXPECTS( cond ) /* Expect elided */ #else # define span_constexpr_exp span_constexpr14 # define span_EXPECTS( cond ) span_CONTRACT_CHECK( "Precondition", cond ) #endif #if span_ELIDE_CONTRACT_ENSURES # define span_constexpr_ens span_constexpr # define span_ENSURES( cond ) /* Ensures elided */ #else # define span_constexpr_ens span_constexpr14 # define span_ENSURES( cond ) span_CONTRACT_CHECK( "Postcondition", cond ) #endif #define span_CONTRACT_CHECK( type, cond ) \ cond ? static_cast< void >( 0 ) \ : nonstd::span_lite::detail::report_contract_violation( span_LOCATION( __FILE__, __LINE__ ) ": " type " violation." ) #ifdef __GNUG__ # define span_LOCATION( file, line ) file ":" span_STRINGIFY( line ) #else # define span_LOCATION( file, line ) file "(" span_STRINGIFY( line ) ")" #endif // Method enabling #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) #define span_REQUIRES_0(VA) \ template< bool B = (VA), typename std::enable_if::type = 0 > # if span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 140 ) // VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments # define span_REQUIRES_T(VA) \ , typename = typename std::enable_if< ( VA ), nonstd::span_lite::detail::enabler >::type # else # define span_REQUIRES_T(VA) \ , typename std::enable_if< (VA), int >::type = 0 # endif #define span_REQUIRES_R(R, VA) \ typename std::enable_if< (VA), R>::type #define span_REQUIRES_A(VA) \ , typename std::enable_if< (VA), void*>::type = nullptr #else # define span_REQUIRES_0(VA) /*empty*/ # define span_REQUIRES_T(VA) /*empty*/ # define span_REQUIRES_R(R, VA) R # define span_REQUIRES_A(VA) /*empty*/ #endif namespace nonstd { namespace span_lite { // [views.constants], constants typedef span_CONFIG_EXTENT_TYPE extent_t; typedef span_CONFIG_SIZE_TYPE size_t; span_constexpr const extent_t dynamic_extent = static_cast( -1 ); template< class T, extent_t Extent = dynamic_extent > class span; // Tag to select span constructor taking a container (prevent ms-gsl warning C26426): struct with_container_t { span_constexpr with_container_t() span_noexcept {} }; const span_constexpr with_container_t with_container; // C++11 emulation: namespace std11 { #if span_HAVE( REMOVE_CONST ) using std::remove_cv; using std::remove_const; using std::remove_volatile; #else template< class T > struct remove_const { typedef T type; }; template< class T > struct remove_const< T const > { typedef T type; }; template< class T > struct remove_volatile { typedef T type; }; template< class T > struct remove_volatile< T volatile > { typedef T type; }; template< class T > struct remove_cv { typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type; }; #endif // span_HAVE( REMOVE_CONST ) #if span_HAVE( TYPE_TRAITS ) using std::is_same; using std::is_signed; using std::integral_constant; using std::true_type; using std::false_type; using std::remove_reference; #else template< class T, T v > struct integral_constant { enum { value = v }; }; typedef integral_constant< bool, true > true_type; typedef integral_constant< bool, false > false_type; template< class T, class U > struct is_same : false_type{}; template< class T > struct is_same : true_type{}; template< typename T > struct is_signed : false_type {}; template<> struct is_signed : true_type {}; template<> struct is_signed : true_type {}; template<> struct is_signed : true_type {}; #endif } // namespace std11 // C++17 emulation: namespace std17 { template< bool v > struct bool_constant : std11::integral_constant{}; #if span_CPP11_120 template< class...> using void_t = void; #endif #if span_HAVE( DATA ) using std::data; using std::size; #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< typename T, std::size_t N > inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t { return N; } template< typename C > inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() ) { return cont.size(); } template< typename T, std::size_t N > inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T* { return &arr[0]; } template< typename C > inline span_constexpr auto data( C & cont ) -> decltype( cont.data() ) { return cont.data(); } template< typename C > inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() ) { return cont.data(); } template< typename E > inline span_constexpr auto data( std::initializer_list il ) span_noexcept -> E const * { return il.begin(); } #endif // span_HAVE( DATA ) #if span_HAVE( BYTE ) using std::byte; #elif span_HAVE( NONSTD_BYTE ) using nonstd::byte; #endif } // namespace std17 // C++20 emulation: namespace std20 { #if span_HAVE( DEDUCTION_GUIDES ) template< class T > using iter_reference_t = decltype( *std::declval() ); #endif } // namespace std20 // Implementation details: namespace detail { /*enum*/ struct enabler{}; template< typename T > span_constexpr bool is_positive( T x ) { return std11::is_signed::value ? x >= 0 : true; } #if span_HAVE( TYPE_TRAITS ) template< class Q > struct is_span_oracle : std::false_type{}; template< class T, span_CONFIG_EXTENT_TYPE Extent > struct is_span_oracle< span > : std::true_type{}; template< class Q > struct is_span : is_span_oracle< typename std::remove_cv::type >{}; template< class Q > struct is_std_array_oracle : std::false_type{}; #if span_HAVE( ARRAY ) template< class T, std::size_t Extent > struct is_std_array_oracle< std::array > : std::true_type{}; #endif template< class Q > struct is_std_array : is_std_array_oracle< typename std::remove_cv::type >{}; template< class Q > struct is_array : std::false_type {}; template< class T > struct is_array : std::true_type {}; template< class T, std::size_t N > struct is_array : std::true_type {}; #if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 ) template< class, class = void > struct has_size_and_data : std::false_type{}; template< class C > struct has_size_and_data < C, std17::void_t< decltype( std17::size(std::declval()) ), decltype( std17::data(std::declval()) ) > > : std::true_type{}; template< class, class, class = void > struct is_compatible_element : std::false_type {}; template< class C, class E > struct is_compatible_element < C, E, std17::void_t< decltype( std17::data(std::declval()) ) > > : std::is_convertible< typename std::remove_pointer() ) )>::type(*)[], E(*)[] >{}; template< class C > struct is_container : std17::bool_constant < ! is_span< C >::value && ! is_array< C >::value && ! is_std_array< C >::value && has_size_and_data< C >::value >{}; template< class C, class E > struct is_compatible_container : std17::bool_constant < is_container::value && is_compatible_element::value >{}; #else // span_CPP11_140 template< class C, class E span_REQUIRES_T(( ! is_span< C >::value && ! is_array< C >::value && ! is_std_array< C >::value && ( std::is_convertible< typename std::remove_pointer() ) )>::type(*)[], E(*)[] >::value) // && has_size_and_data< C >::value )) , class = decltype( std17::size(std::declval()) ) , class = decltype( std17::data(std::declval()) ) > struct is_compatible_container : std::true_type{}; #endif // span_CPP11_140 #endif // span_HAVE( TYPE_TRAITS ) #if ! span_CONFIG( NO_EXCEPTIONS ) #if span_FEATURE( MEMBER_AT ) > 1 // format index and size: #if defined(__clang__) # pragma clang diagnostic ignored "-Wlong-long" #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wformat=ll" # pragma GCC diagnostic ignored "-Wlong-long" #endif span_noreturn inline void throw_out_of_range( size_t idx, size_t size ) { const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)"; char buffer[ 2 * 20 + sizeof fmt ]; sprintf( buffer, fmt, static_cast(idx), static_cast(size) ); throw std::out_of_range( buffer ); } #else // MEMBER_AT span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ ) { throw std::out_of_range( "span::at(): index outside span" ); } #endif // MEMBER_AT #endif // NO_EXCEPTIONS #if span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) struct contract_violation : std::logic_error { explicit contract_violation( char const * const message ) : std::logic_error( message ) {} }; inline void report_contract_violation( char const * msg ) { throw contract_violation( msg ); } #else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept { std::terminate(); } #endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) } // namespace detail // Prevent signed-unsigned mismatch: #define span_sizeof(T) static_cast( sizeof(T) ) template< class T > inline span_constexpr size_t to_size( T size ) { return static_cast( size ); } // // [views.span] - A view over a contiguous, single-dimension sequence of objects // template< class T, extent_t Extent /*= dynamic_extent*/ > class span { public: // constants and types typedef T element_type; typedef typename std11::remove_cv< T >::type value_type; typedef T & reference; typedef T * pointer; typedef T const * const_pointer; typedef T const & const_reference; typedef size_t size_type; typedef extent_t extent_type; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::ptrdiff_t difference_type; typedef std::reverse_iterator< iterator > reverse_iterator; typedef std::reverse_iterator< const_iterator > const_reverse_iterator; // static constexpr extent_type extent = Extent; enum { extent = Extent }; // 26.7.3.2 Constructors, copy, and assignment [span.cons] span_REQUIRES_0( ( Extent == 0 ) || ( Extent == dynamic_extent ) ) span_constexpr span() span_noexcept : data_( span_nullptr ) , size_( 0 ) { // span_EXPECTS( data() == span_nullptr ); // span_EXPECTS( size() == 0 ); } #if span_HAVE( ITERATOR_CTOR ) // Didn't yet succeed in combining the next two constructors: span_constexpr_exp span( std::nullptr_t, size_type count ) : data_( span_nullptr ) , size_( count ) { span_EXPECTS( data_ == span_nullptr && count == 0 ); } template< typename It span_REQUIRES_T(( std::is_convertible()), element_type &>::value )) > span_constexpr_exp span( It first, size_type count ) : data_( to_address( first ) ) , size_( count ) { span_EXPECTS( ( data_ == span_nullptr && count == 0 ) || ( data_ != span_nullptr && detail::is_positive( count ) ) ); } #else span_constexpr_exp span( pointer ptr, size_type count ) : data_( ptr ) , size_( count ) { span_EXPECTS( ( ptr == span_nullptr && count == 0 ) || ( ptr != span_nullptr && detail::is_positive( count ) ) ); } #endif #if span_HAVE( ITERATOR_CTOR ) template< typename It, typename End span_REQUIRES_T(( std::is_convertible()), element_type *>::value && ! std::is_convertible::value )) > span_constexpr_exp span( It first, End last ) : data_( to_address( first ) ) , size_( to_size( last - first ) ) { span_EXPECTS( last - first >= 0 ); } #else span_constexpr_exp span( pointer first, pointer last ) : data_( first ) , size_( to_size( last - first ) ) { span_EXPECTS( last - first >= 0 ); } #endif template< std::size_t N span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) > span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept : data_( span_ADDRESSOF( arr[0] ) ) , size_( N ) {} #if span_HAVE( ARRAY ) template< std::size_t N span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) > # if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE ) span_constexpr span( std::array< element_type, N > & arr ) span_noexcept # else span_constexpr span( std::array< value_type, N > & arr ) span_noexcept # endif : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} template< std::size_t N # if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) # endif > span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} #endif // span_HAVE( ARRAY ) #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< class Container span_REQUIRES_T(( detail::is_compatible_container< Container, element_type >::value )) > span_constexpr span( Container & cont ) : data_( std17::data( cont ) ) , size_( to_size( std17::size( cont ) ) ) {} template< class Container span_REQUIRES_T(( std::is_const< element_type >::value && detail::is_compatible_container< Container, element_type >::value )) > span_constexpr span( Container const & cont ) : data_( std17::data( cont ) ) , size_( to_size( std17::size( cont ) ) ) {} #endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) #if span_FEATURE( WITH_CONTAINER ) template< class Container > span_constexpr span( with_container_t, Container & cont ) : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) ) , size_( to_size( cont.size() ) ) {} template< class Container > span_constexpr span( with_container_t, Container const & cont ) : data_( cont.size() == 0 ? span_nullptr : const_cast( span_ADDRESSOF( cont[0] ) ) ) , size_( to_size( cont.size() ) ) {} #endif #if span_FEATURE( WITH_INITIALIZER_LIST_P2447 ) && span_HAVE( INITIALIZER_LIST ) // constexpr explicit(extent != dynamic_extent) span(std::initializer_list il) noexcept; #if !span_BETWEEN( span_COMPILER_MSVC_VERSION, 120, 130 ) template< extent_t U = Extent span_REQUIRES_T(( U != dynamic_extent )) > #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime" span_constexpr14 explicit span( std::initializer_list il ) span_noexcept { data_ = il.begin(); size_ = il.size(); } #else span_constexpr explicit span( std::initializer_list il ) span_noexcept : data_( il.begin() ) , size_( il.size() ) {} #endif #endif // MSVC 120 (VS2013) template< extent_t U = Extent span_REQUIRES_T(( U == dynamic_extent )) > #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime" span_constexpr14 /*explicit*/ span( std::initializer_list il ) span_noexcept { data_ = il.begin(); size_ = il.size(); } #else span_constexpr /*explicit*/ span( std::initializer_list il ) span_noexcept : data_( il.begin() ) , size_( il.size() ) {} #endif #endif // P2447 #if span_HAVE( IS_DEFAULT ) span_constexpr span( span const & other ) span_noexcept = default; ~span() span_noexcept = default; span_constexpr14 span & operator=( span const & other ) span_noexcept = default; #else span_constexpr span( span const & other ) span_noexcept : data_( other.data_ ) , size_( other.size_ ) {} ~span() span_noexcept {} span_constexpr14 span & operator=( span const & other ) span_noexcept { data_ = other.data_; size_ = other.size_; return *this; } #endif template< class OtherElementType, extent_type OtherExtent span_REQUIRES_T(( (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) && std::is_convertible::value )) > span_constexpr_exp span( span const & other ) span_noexcept : data_( other.data() ) , size_( other.size() ) { span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) ); } // 26.7.3.3 Subviews [span.sub] template< extent_type Count > span_constexpr_exp span< element_type, Count > first() const { span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); return span< element_type, Count >( data(), Count ); } template< extent_type Count > span_constexpr_exp span< element_type, Count > last() const { span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); return span< element_type, Count >( data() + (size() - Count), Count ); } #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) template< size_type Offset, extent_type Count = dynamic_extent > #else template< size_type Offset, extent_type Count /*= dynamic_extent*/ > #endif span_constexpr_exp span< element_type, Count > subspan() const { span_EXPECTS( ( detail::is_positive( Offset ) && Offset <= size() ) && ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) ) ); return span< element_type, Count >( data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) ); } span_constexpr_exp span< element_type, dynamic_extent > first( size_type count ) const { span_EXPECTS( detail::is_positive( count ) && count <= size() ); return span< element_type, dynamic_extent >( data(), count ); } span_constexpr_exp span< element_type, dynamic_extent > last( size_type count ) const { span_EXPECTS( detail::is_positive( count ) && count <= size() ); return span< element_type, dynamic_extent >( data() + ( size() - count ), count ); } span_constexpr_exp span< element_type, dynamic_extent > subspan( size_type offset, size_type count = static_cast(dynamic_extent) ) const { span_EXPECTS( ( ( detail::is_positive( offset ) && offset <= size() ) ) && ( count == static_cast(dynamic_extent) || ( detail::is_positive( count ) && offset + count <= size() ) ) ); return span< element_type, dynamic_extent >( data() + offset, count == static_cast(dynamic_extent) ? size() - offset : count ); } // 26.7.3.4 Observers [span.obs] span_constexpr size_type size() const span_noexcept { return size_; } span_constexpr std::ptrdiff_t ssize() const span_noexcept { return static_cast( size_ ); } span_constexpr size_type size_bytes() const span_noexcept { return size() * to_size( sizeof( element_type ) ); } span_nodiscard span_constexpr bool empty() const span_noexcept { return size() == 0; } // 26.7.3.5 Element access [span.elem] span_constexpr_exp reference operator[]( size_type idx ) const { span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } #if span_FEATURE( MEMBER_CALL_OPERATOR ) span_deprecated("replace operator() with operator[]") span_constexpr_exp reference operator()( size_type idx ) const { span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } #endif #if span_FEATURE( MEMBER_AT ) span_constexpr14 reference at( size_type idx ) const { #if span_CONFIG( NO_EXCEPTIONS ) return this->operator[]( idx ); #else if ( !detail::is_positive( idx ) || size() <= idx ) { detail::throw_out_of_range( idx, size() ); } return *( data() + idx ); #endif } #endif span_constexpr pointer data() const span_noexcept { return data_; } #if span_FEATURE( MEMBER_BACK_FRONT ) span_constexpr_exp reference front() const span_noexcept { span_EXPECTS( ! empty() ); return *data(); } span_constexpr_exp reference back() const span_noexcept { span_EXPECTS( ! empty() ); return *( data() + size() - 1 ); } #endif // xx.x.x.x Modifiers [span.modifiers] #if span_FEATURE( MEMBER_SWAP ) span_constexpr14 void swap( span & other ) span_noexcept { using std::swap; swap( data_, other.data_ ); swap( size_, other.size_ ); } #endif // 26.7.3.6 Iterator support [span.iterators] span_constexpr iterator begin() const span_noexcept { #if span_CPP11_OR_GREATER return { data() }; #else return iterator( data() ); #endif } span_constexpr iterator end() const span_noexcept { #if span_CPP11_OR_GREATER return { data() + size() }; #else return iterator( data() + size() ); #endif } span_constexpr const_iterator cbegin() const span_noexcept { #if span_CPP11_OR_GREATER return { data() }; #else return const_iterator( data() ); #endif } span_constexpr const_iterator cend() const span_noexcept { #if span_CPP11_OR_GREATER return { data() + size() }; #else return const_iterator( data() + size() ); #endif } span_constexpr reverse_iterator rbegin() const span_noexcept { return reverse_iterator( end() ); } span_constexpr reverse_iterator rend() const span_noexcept { return reverse_iterator( begin() ); } span_constexpr const_reverse_iterator crbegin() const span_noexcept { return const_reverse_iterator ( cend() ); } span_constexpr const_reverse_iterator crend() const span_noexcept { return const_reverse_iterator( cbegin() ); } private: // Note: C++20 has std::pointer_traits::to_address( it ); #if span_HAVE( ITERATOR_CTOR ) static inline span_constexpr pointer to_address( std::nullptr_t ) span_noexcept { return nullptr; } template< typename U > static inline span_constexpr U * to_address( U * p ) span_noexcept { return p; } template< typename Ptr span_REQUIRES_T(( ! std::is_pointer::value )) > static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept { return to_address( it.operator->() ); } #endif // span_HAVE( ITERATOR_CTOR ) private: pointer data_; size_type size_; }; // class template argument deduction guides: #if span_HAVE( DEDUCTION_GUIDES ) template< class T, size_t N > span( T (&)[N] ) -> span(N)>; template< class T, size_t N > span( std::array & ) -> span(N)>; template< class T, size_t N > span( std::array const & ) -> span(N)>; #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< class Container > span( Container& ) -> span; template< class Container > span( Container const & ) -> span; #endif // iterator: constraints: It satisfies contiguous_­iterator. template< class It, class EndOrSize > span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t >::type >; #endif // span_HAVE( DEDUCTION_GUIDES ) // 26.7.3.7 Comparison operators [span.comparison] #if span_FEATURE( COMPARISON ) #if span_FEATURE( SAME ) template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool same( span const & l, span const & r ) span_noexcept { return std11::is_same::value && l.size() == r.size() && static_cast( l.data() ) == r.data(); } #endif template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator==( span const & l, span const & r ) { return #if span_FEATURE( SAME ) same( l, r ) || #endif ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator<( span const & l, span const & r ) { return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator!=( span const & l, span const & r ) { return !( l == r ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator<=( span const & l, span const & r ) { return !( r < l ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator>( span const & l, span const & r ) { return ( r < l ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator>=( span const & l, span const & r ) { return !( l < r ); } #endif // span_FEATURE( COMPARISON ) // 26.7.2.6 views of object representation [span.objectrep] #if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) // Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow: template< typename T, extent_t Extent > struct BytesExtent { #if span_CPP11_OR_GREATER enum ET : extent_t { value = span_sizeof(T) * Extent }; #else enum ET { value = span_sizeof(T) * Extent }; #endif }; template< typename T > struct BytesExtent< T, dynamic_extent > { #if span_CPP11_OR_GREATER enum ET : extent_t { value = dynamic_extent }; #else enum ET { value = dynamic_extent }; #endif }; template< class T, extent_t Extent > inline span_constexpr span< const std17::byte, BytesExtent::value > as_bytes( span spn ) span_noexcept { #if 0 return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() }; #else return span< const std17::byte, BytesExtent::value >( reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() ); // NOLINT #endif } template< class T, extent_t Extent > inline span_constexpr span< std17::byte, BytesExtent::value > as_writable_bytes( span spn ) span_noexcept { #if 0 return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() }; #else return span< std17::byte, BytesExtent::value >( reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() ); // NOLINT #endif } #endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) // 27.8 Container and view access [iterator.container] template< class T, extent_t Extent /*= dynamic_extent*/ > span_constexpr std::size_t size( span const & spn ) { return static_cast( spn.size() ); } template< class T, extent_t Extent /*= dynamic_extent*/ > span_constexpr std::ptrdiff_t ssize( span const & spn ) { return static_cast( spn.size() ); } } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::dynamic_extent; using span_lite::span; using span_lite::with_container; #if span_FEATURE( COMPARISON ) #if span_FEATURE( SAME ) using span_lite::same; #endif using span_lite::operator==; using span_lite::operator!=; using span_lite::operator<; using span_lite::operator<=; using span_lite::operator>; using span_lite::operator>=; #endif #if span_HAVE( BYTE ) using span_lite::as_bytes; using span_lite::as_writable_bytes; #endif using span_lite::size; using span_lite::ssize; } // namespace nonstd #endif // span_USES_STD_SPAN // make_span() [span-lite extension]: #if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) #if span_USES_STD_SPAN # define span_constexpr constexpr # define span_noexcept noexcept # define span_nullptr nullptr # ifndef span_CONFIG_EXTENT_TYPE # define span_CONFIG_EXTENT_TYPE std::size_t # endif using extent_t = span_CONFIG_EXTENT_TYPE; #endif // span_USES_STD_SPAN namespace nonstd { namespace span_lite { template< class T > inline span_constexpr span make_span( T * ptr, size_t count ) span_noexcept { return span( ptr, count ); } template< class T > inline span_constexpr span make_span( T * first, T * last ) span_noexcept { return span( first, last ); } template< class T, std::size_t N > inline span_constexpr span(N)> make_span( T ( &arr )[ N ] ) span_noexcept { return span(N)>( &arr[ 0 ], N ); } #if span_USES_STD_SPAN || span_HAVE( ARRAY ) template< class T, std::size_t N > inline span_constexpr span(N)> make_span( std::array< T, N > & arr ) span_noexcept { return span(N)>( arr ); } template< class T, std::size_t N > inline span_constexpr span< const T, static_cast(N) > make_span( std::array< T, N > const & arr ) span_noexcept { return span(N)>( arr ); } #endif // span_HAVE( ARRAY ) #if span_USES_STD_SPAN || span_HAVE( INITIALIZER_LIST ) template< class T > inline span_constexpr span< const T > make_span( std::initializer_list il ) span_noexcept { return span( il.begin(), il.size() ); } #endif // span_HAVE( INITIALIZER_LIST ) #if span_USES_STD_SPAN template< class Container, class EP = decltype( std::data(std::declval())) > inline span_constexpr auto make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > { return span< typename std::remove_pointer::type >( cont ); } template< class Container, class EP = decltype( std::data(std::declval())) > inline span_constexpr auto make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > { return span< const typename std::remove_pointer::type >( cont ); } #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO ) template< class Container, class EP = decltype( std17::data(std::declval())) > inline span_constexpr auto make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > { return span< typename std::remove_pointer::type >( cont ); } template< class Container, class EP = decltype( std17::data(std::declval())) > inline span_constexpr auto make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > { return span< const typename std::remove_pointer::type >( cont ); } #else template< class T > inline span_constexpr span make_span( span spn ) span_noexcept { return spn; } template< class T, class Allocator > inline span_constexpr span make_span( std::vector & cont ) span_noexcept { return span( with_container, cont ); } template< class T, class Allocator > inline span_constexpr span make_span( std::vector const & cont ) span_noexcept { return span( with_container, cont ); } #endif // span_USES_STD_SPAN || ( ... ) #if ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) template< class Container > inline span_constexpr span make_span( with_container_t, Container & cont ) span_noexcept { return span< typename Container::value_type >( with_container, cont ); } template< class Container > inline span_constexpr span make_span( with_container_t, Container const & cont ) span_noexcept { return span< const typename Container::value_type >( with_container, cont ); } #endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) // extensions: non-member views: // this feature implies the presence of make_span() #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) template< extent_t Count, class T, extent_t Extent > span_constexpr span first( span spn ) { return spn.template first(); } template< class T, extent_t Extent > span_constexpr span first( span spn, size_t count ) { return spn.first( count ); } template< extent_t Count, class T, extent_t Extent > span_constexpr span last( span spn ) { return spn.template last(); } template< class T, extent_t Extent > span_constexpr span last( span spn, size_t count ) { return spn.last( count ); } template< size_t Offset, extent_t Count, class T, extent_t Extent > span_constexpr span subspan( span spn ) { return spn.template subspan(); } template< class T, extent_t Extent > span_constexpr span subspan( span spn, size_t offset, extent_t count = dynamic_extent ) { return spn.subspan( offset, count ); } #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 template< extent_t Count, class T > span_constexpr auto first( T & t ) -> decltype( make_span(t).template first() ) { return make_span( t ).template first(); } template< class T > span_constexpr auto first( T & t, size_t count ) -> decltype( make_span(t).first(count) ) { return make_span( t ).first( count ); } template< extent_t Count, class T > span_constexpr auto last( T & t ) -> decltype( make_span(t).template last() ) { return make_span(t).template last(); } template< class T > span_constexpr auto last( T & t, extent_t count ) -> decltype( make_span(t).last(count) ) { return make_span( t ).last( count ); } template< size_t Offset, extent_t Count = dynamic_extent, class T > span_constexpr auto subspan( T & t ) -> decltype( make_span(t).template subspan() ) { return make_span( t ).template subspan(); } template< class T > span_constexpr auto subspan( T & t, size_t offset, extent_t count = dynamic_extent ) -> decltype( make_span(t).subspan(offset, count) ) { return make_span( t ).subspan( offset, count ); } #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::make_span; #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || ( span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 ) using span_lite::first; using span_lite::last; using span_lite::subspan; #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] ) } // namespace nonstd #endif // #if span_FEATURE_TO_STD( MAKE_SPAN ) #if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) ) namespace nonstd { namespace span_lite { template< class T > inline span_constexpr auto byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) > { return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) ); } template< class T > inline span_constexpr auto byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) > { return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) ); } } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::byte_span; } // namespace nonstd #endif // span_FEATURE( BYTE_SPAN ) #if !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING ) #if span_CPP14_OR_GREATER # include #elif span_CPP11_OR_GREATER # include namespace std { template< std::size_t I, typename T > using tuple_element_t = typename tuple_element::type; } #else namespace std { template< typename T > class tuple_size; /*undefined*/ template< std::size_t I, typename T > class tuple_element; /* undefined */ } #endif // span_CPP14_OR_GREATER namespace std { // 26.7.X Tuple interface // std::tuple_size<>: template< typename ElementType, nonstd::span_lite::extent_t Extent > class tuple_size< nonstd::span > : public integral_constant(Extent)> {}; // std::tuple_size<>: Leave undefined for dynamic extent: template< typename ElementType > class tuple_size< nonstd::span >; // std::tuple_element<>: template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > class tuple_element< I, nonstd::span > { public: #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "tuple_element: dynamic extent or index out of range" ); #endif using type = ElementType; }; // std::get<>(), 2 variants: template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > span_constexpr ElementType & get( nonstd::span & spn ) span_noexcept { #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" ); #endif return spn[I]; } template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > span_constexpr ElementType const & get( nonstd::span const & spn ) span_noexcept { #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" ); #endif return spn[I]; } } // end namespace std #endif // !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING ) #if ! span_USES_STD_SPAN span_RESTORE_WARNINGS() #endif // span_USES_STD_SPAN #endif // NONSTD_SPAN_HPP_INCLUDED qbs-src-3.3.1/src/shared/span/README.md0000644000175100017510000010654515232633614016773 0ustar runnerrunner # span lite: A single-file header-only version of a C++20-like span for C++98, C++11 and later [![Language](https://img.shields.io/badge/C%2B%2B-98/11/14/17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://github.com/martinmoene/span-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martinmoene/span-lite/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/1ha3wnxtam547m8p?svg=true)](https://ci.appveyor.com/project/martinmoene/span-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Fspan-lite.svg)](https://github.com/martinmoene/span-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://github.com/martinmoene/span-lite/blob/master/include/nonstd/span.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://conan.io/center/span-lite) [![Try it on wandbox](https://img.shields.io/badge/on-wandbox-blue.svg)](https://wandbox.org/permlink/venR3Ko2Q4tlvcVk) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/htwpnb) **Contents** - [Example usage](#example-usage) - [In a nutshell](#in-a-nutshell) - [License](#license) - [Dependencies](#dependencies) - [Installation and use](#installation-and-use) - [Synopsis](#synopsis) - [Reported to work with](#reported-to-work-with) - [Building the tests](#building-the-tests) - [Other implementations of span](#other-implementations-of-span) - [Notes and references](#notes-and-references) - [Appendix](#appendix) ## Example usage ```cpp #include "nonstd/span.hpp" #include #include #include std::ptrdiff_t size( nonstd::span spn ) { return spn.size(); } int main() { int arr[] = { 1, }; std::cout << "C-array:" << size( arr ) << " array:" << size( std::array { 1, 2, } ) << " vector:" << size( std::vector{ 1, 2, 3, } ); } ``` ### Compile and run ```bash prompt> g++ -std=c++11 -Wall -I../include -o 01-basic.exe 01-basic.cpp && 01-basic.exe C-array:1 array:2 vector:3 ``` ## In a nutshell **span lite** is a single-file header-only library to provide a bounds-safe view for sequences of objects. The library provides a [C++20-like span](http://en.cppreference.com/w/cpp/container/span) for use with C++98 and later. If available, `std::span` is used, unless [configured otherwise](#configuration). *span-lite* can detect the presence of [*byte-lite*](https://github.com/martinmoene/byte-lite) and if present, it provides `as_bytes()` and `as_writable_bytes()` also for C++14 and earlier. **Features and properties of span lite** are ease of installation (single header), freedom of dependencies other than the standard library. To compensate for the class template argument deduction that is missing from pre-C++17 compilers, `nonstd::span` can provide `make_span` functions. See [configuration](#configuration). ## License *span lite* is distributed under the [Boost Software License](https://github.com/martinmoene/span-lite/blob/master/LICENSE.txt). ## Dependencies *span lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header). ## Installation and use *span lite* is a single-file header-only library. Put `span.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project. ## Synopsis **Contents** [Documentation of `std::span`](#documentation-of-stdspan) [Later additions](#later-additions) [Non-standard extensions](#non-standard-extensions) [Configuration](#configuration) ## Documentation of `std::span` Depending on the compiler and C++-standard used, `nonstd::span` behaves less or more like `std::span`. To get an idea of the capabilities of `nonstd::span` with your configuration, look at the output of the [tests](test/span.t.cpp), issuing `span-main.t --pass @`. For `std::span`, see its [documentation at cppreference](http://en.cppreference.com/w/cpp/container/span). ## Later additions ### `back()` and `front()` *span lite* can provide `back()` and `front()` member functions for element access. See the table below and section [configuration](#configuration). ## Non-standard extensions ### Construct from std::initializer_list (p2447) *span lite* can provide construction from a std::initializer_list<> as a constant set of values as proposed in [p2447](https://wg21.link/p2447). See the table below and section [configuration](#configuration). ### Construct from container To construct a span from a container with compilers that cannot constrain such a single-parameter constructor to containers, *span lite* provides a constructor that takes an additional parameter of type `with_container_t`. Use `with_container` as value for this parameter. See the table below and section [configuration](#configuration). ### Construct from `std::array` with const data *span lite* can provide construction of a span from a `std::array` with const data. See the table below and section [configuration](#configuration). ### `operator()` *span lite* can provide member function call `operator()` for element access. It is equivalent to `operator[]` and has been marked `[[deprecated]]`. Its main purpose is to provide a migration path. ### `at()` *span lite* can provide member function `at()` for element access. Unless exceptions have been disabled, `at()` throws std::out_of_range if the index falls outside the span. With exceptions disabled, `at(index_t)` delegates bounds checking to `operator[](index_t)`. See the table below and sections [configuration](#configuration) and [disable exceptions](#disable-exceptions). ### `swap()` *span lite* can provide a `swap()`member function. See the table below and section [configuration](#configuration). ### `operator==()` and other comparison functions *span lite* can provide functions to compare the content of two spans. However, C++20's span will not provide comparison and _span lite_ will omit comparison at default in the near future. See the table below and section [configuration](#configuration). See also [Revisiting Regular Types](#regtyp). ### `same()` *span lite* can provide function `same()` to determine if two spans refer as identical spans to the same data via the same type. If `same()` is enabled, `operator==()` incorporates it in its comparison. See the table below and section [configuration](#configuration). ### `first()`, `last()` and `subspan()` *span lite* can provide functions `first()`, `last()` and `subspan()` to avoid having to use the *dot template* syntax when the span is a dependent type. See the table below and section [configuration](#configuration). ### `make_span()` *span lite* can provide `make_span()` creator functions to compensate for the class template argument deduction that is missing from pre-C++17 compilers. See the table below and section [configuration](#configuration). ### `byte_span()` *span lite* can provide `byte_span()` creator functions to represent an object as a span of bytes. This requires the C++17 type `std::byte` to be available. See the table below and section [configuration](#configuration). | Kind | std | Function or method | |--------------------|------|--------------------| | **Macro** | | macro **`span_FEATURE_WITH_INITIALIZER_LIST_P2447`** | | **Constructor**
  | | constexpr explicit **span**( std::initializer_list<value_type> il ) noexcept
explicit for non-dynamic extent | |   | |   | | **Macro**
 | | macro **`span_FEATURE_WITH_CONTAINER`**
macro **`span_FEATURE_WITH_CONTAINER_TO_STD`** | | **Types** | | **with_container_t** type to disambiguate below constructors | | **Objects** | | **with_container** value to disambiguate below constructors | | **Constructors** | | macro **`span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE`**| |   | | template<class Container>
constexpr **span**(with_container_t, Container & cont) | |   | | template<class Container>
constexpr **span**(with_container_t, Container const & cont) | |   | |   | | **Methods** | | macro **`span_FEATURE_MEMBER_CALL_OPERATOR`** | |   | | constexpr reference **operator()**(index_t idx) const
Equivalent to **operator[]**(), marked `[[deprecated]]` | |   | |   | | **Methods** | | macro **`span_FEATURE_MEMBER_AT`** | |   | | constexpr reference **at**(index_t idx) const
May throw std::out_of_range exception | |   | |   | | **Methods** | | macro **`span_FEATURE_MEMBER_BACK_FRONT`** (on since v0.5.0) | |   | | constexpr reference **back()** const noexcept | |   | | constexpr reference **front()** const noexcept | |   | |   | | **Method** | | macro **`span_FEATURE_MEMBER_SWAP`** | |   | | constexpr void **swap**(span & other) noexcept | |   | |   | | **Free functions** | | macro **`span_FEATURE_COMPARISON`** | |

== != < > <= >= | | template<class T1, index_t E1, class T2, index_t E2>
constexpr bool
**operator==**( span const & l, span const & r) noexcept | |   | |   | | **Free function** | | macro **`span_FEATURE_SAME`** | |   | | template<class T1, index_t E1, class T2, index_t E2>
constexpr bool
**same**( span const & l, span const & r) noexcept | |   | |   | | **Free functions**
 
  | | macros **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB`**,
**`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN`**,
**`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`** | |   | |   | | **Free functions** | | macro **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN`** | |   |   | template<extent_t Count, class T, extent_t Extent>
constexpr span<T,Count>
**first**(span<T,Extent> spn) | |   |   | template<class T, extent_t Extent >
constexpr span<T>
**first**(span<T,Extent> spn, size_t count) | |   |   | template<extent_t Count, class T, extent_t Extent>
constexpr span<T,Count>
**last**(span<T,Extent> spn) | |   |   | template<class T, extent_t Extent >
constexpr span<T>
**last**(span<T,Extent> spn, size_t count) | |   |   | template<size_t Offset, extent_t Count, class T, extent_t Extent>
constexpr span<T, Count>
**subspan**(span<T, Extent> spn) | |   |   | template<class T, extent_t Extent>
constexpr span<T>
**subspan**( span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent) | |   | |   | | **Free functions** | | macro **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`** | |   | >= C++11 | template<extent_t Count, class T>
constexpr auto
**first**(T & t) ->... | |   | >= C++11 | template<class T>
constexpr auto
**first**(T & t, index_t count) ->... | |   | >= C++11 | template<extent_t Count, class T>
constexpr auto
**last**(T & t) ->... | |   | >= C++11 | template<class T>
constexpr auto
**last**(T & t, extent_t count) ->... | |   | >= C++11 | template<index_t Offset, extent_t Count = dynamic_extent, class T>
constexpr auto
**subspan**(T & t) ->... | |   | >= C++11 | template<class T>
constexpr auto
**subspan**(T & t, index_t offset, extent_t count = dynamic_extent) ->... | |   |   |   | | **Free functions**
  | | macro **`span_FEATURE_MAKE_SPAN`**
macro **`span_FEATURE_MAKE_SPAN_TO_STD`** | |   |   | template<class T>
constexpr span<T>
**make_span**(T \* first, T \* last) noexcept | |   |   | template<class T>
constexpr span<T>
**make_span**(T \* ptr, index_t count) noexcept | |   |   | template<class T, size_t N>
constexpr span<T,N>
**make_span**(T (&arr)[N]) noexcept | |   | >= C++11 | template<class T, size_t N>
constexpr span<T,N>
**make_span**(std::array<T,N> & arr) noexcept | |   | >= C++11 | template<class T, size_t N>
constexpr span<const T,N>
**make_span**(std::array<T,N > const & arr) noexcept | |   | >= C++11 | template<class T>
constexpr span<T>
**make_span**(std::initializer_list<T> il) noexcept | |   | >= C++11 | template<class Container>
constexpr auto
**make_span**(Container & cont) ->
 span<typename Container::value_type> noexcept | |   | >= C++11 | template<class Container>
constexpr auto
**make_span**(Container const & cont) ->
 span<const typename Container::value_type> noexcept | |   |   | template<class Container>
span<typename Container::value_type>
**make_span**( with_container_t, Container & cont ) | |   |   | template<class Container>
span<const typename Container::value_type>
**make_span**( with_container_t, Container const & cont ) | |   | < C++11 | template<class T, Allocator>
span<T>
**make_span**(std::vector<T, Allocator> & cont) | |   | < C++11 | template<class T, Allocator>
span<const T>
**make_span**(std::vector<T, Allocator> const & cont) | |   |   |   | | **Free functions** | | macro **`span_FEATURE_BYTE_SPAN`** | |   | >= C++11 | template<class T>
span<T, sizeof(T)>
**byte_span**(T & t) | |   | >= C++11 | template<class T>
span<const T, sizeof(T)>
**byte_span**(T const & t) | ## Configuration ### Tweak header If the compiler supports [`__has_include()`](https://en.cppreference.com/w/cpp/preprocessor/include), *span lite* supports the [tweak header](https://vector-of-bool.github.io/2020/10/04/lib-configuration.html) mechanism. Provide your *tweak header* as `nonstd/span.tweak.hpp` in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like `#define span_CONFIG_NO_EXCEPTIONS 1`. ### Standard selection macro \-Dspan\_CPLUSPLUS=199711L Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the `__cplusplus` macro correctly. ### Select `std::span` or `nonstd::span` At default, *span lite* uses `std::span` if it is available and lets you use it via namespace `nonstd`. You can however override this default and explicitly request to use `std::span` or span lite's `nonstd::span` as `nonstd::span` via the following macros. -Dspan\_CONFIG\_SELECT\_SPAN=span_SPAN_DEFAULT Define this to `span_SPAN_STD` to select `std::span` as `nonstd::span`. Define this to `span_SPAN_NONSTD` to select `nonstd::span` as `nonstd::span`. Default is undefined, which has the same effect as defining to `span_SPAN_DEFAULT`. ### Select extent type -Dspan_CONFIG_EXTENT_TYPE=std::size_t Define this to `std::ptrdiff_t` to use the signed type. The default is `std::size_t`, as in C++20 (since v0.7.0). ### Select size type -Dspan_CONFIG_SIZE_TYPE=std::size_t Define this to `std::ptrdiff_t` to use the signed type. The default is `std::size_t`, as in C++20 (since v0.7.0). Note `span_CONFIG_SIZE_TYPE` replaces `span_CONFIG_INDEX_TYPE` which is deprecated. ### Disable exceptions -Dspan_CONFIG_NO_EXCEPTIONS=0 Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via `-fno-exceptions`). Disabling exceptions will force contract violation to use termination, see [contract violation macros](#contract-violation-response-macros). Default is undefined. ### Provide construction from std::initializer_list (p2447) -Dspan_FEATURE_WITH_INITIALIZER_LIST_P2447=0 Define this to 1 to enable constructing a span from a std::initializer_list<> as a constant set of values. See proposal [p2447](https://wg21.link/p2447). Default is undefined. ### Provide construction using `with_container_t` -Dspan_FEATURE_WITH_CONTAINER=0 Define this to 1 to enable constructing a span using `with_container_t`. Note that `span_FEATURE_WITH_CONTAINER` takes precedence over `span_FEATURE_WITH_CONTAINER_TO_STD`. Default is undefined. -Dspan_FEATURE_WITH_CONTAINER_TO_STD=*n* Define this to the highest C++ language version for which to enable constructing a span using `with_container_t`, like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use `span_FEATURE_WITH_CONTAINER` for this. Note that `span_FEATURE_WITH_CONTAINER` takes precedence over `span_FEATURE_WITH_CONTAINER_TO_STD`. Default is undefined. ### Provide construction from `std::array` with const data -Dspan_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE=0 Define this to 1 to enable constructing a span from a std::array with const data. Default is undefined. ### Provide `operator()` member function -Dspan_FEATURE_MEMBER_CALL_OPERATOR=0 Define this to 1 to provide member function `operator()`for element access. It is equivalent to `operator[]` and has been marked `[[deprecated]]`. Its main purpose is to provide a migration path. Default is undefined. ### Provide `at()` member function -Dspan_FEATURE_MEMBER_AT=0 Define this to 1 to provide member function `at()`. Define this to 2 to include index and size in message of std::out_of_range exception. Default is undefined. ### Provide `back()` and `front()` member functions -Dspan_FEATURE_MEMBER_BACK_FRONT=1 _(on since v0.5.0)_ Define this to 0 to omit member functions `back()` and `front()`. Default is undefined. ### Provide `swap()` member function -Dspan_FEATURE_MEMBER_SWAP=0 Define this to 1 to provide member function `swap()`. Default is undefined. ### Provide `operator==()` and other comparison functions -Dspan_FEATURE_COMPARISON=0 Define this to 1 to include the comparison functions to compare the content of two spans. C++20's span does not provide comparison and _span lite_ omits comparison from v0.7.0. Default is undefined. ### Provide `same()` function -Dspan_FEATURE_SAME=0 Define this to 1 to provide function `same()` to test if two spans refer as identical spans to the same data via the same type. If `same()` is enabled, `operator==()` incorporates it in its comparison. Default is undefined. ### Provide `first()`, `last()` and `subspan()` functions -Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB=0 Define this to 1 to enable both `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN` and `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`. Default is undefined. -Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN=0 Define this to 1 to provide functions `first()`, `last()` and `subspan()` that take a `span<>` (work with C++98). This implies `span_FEATURE_MAKE_SPAN` to provide functions `make_span()` that are required for this feature. Default is undefined. -Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER=0 Define this to 1 to provide functions `first()`, `last()` and `subspan()` that take a compatible container (requires C++11). This implies `span_FEATURE_MAKE_SPAN` to provide functions `make_span()` that are required for this feature. Default is undefined. ### Provide `make_span()` functions -Dspan_FEATURE_MAKE_SPAN=0 Define this to 1 to provide creator functions `nonstd::make_span()`. This feature is implied by using `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1`. Note that `span_FEATURE_MAKE_SPAN` takes precedence over `span_FEATURE_MAKE_SPAN_TO_STD`. Default is undefined. -Dspan_FEATURE_MAKE_SPAN_TO_STD=*n* Define this to the highest C++ language version for which to provide creator functions `nonstd::make_span()`, like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use `span_FEATURE_MAKE_SPAN` for this. Note that `span_FEATURE_MAKE_SPAN` takes precedence over `span_FEATURE_MAKE_SPAN_TO_STD`. Default is undefined. ### Provide `byte_span()` functions -Dspan_FEATURE_BYTE_SPAN=0 Define this to 1 to provide creator functions `nonstd::byte_span()`. Default is undefined. ### Contract violation response macros *span-lite* provides contract violation response control as suggested in proposal [N4415](http://wg21.link/n4415). \-Dspan\_CONFIG\_CONTRACT\_LEVEL\_ON (*default*) Define this macro to include both `span_EXPECTS` and `span_ENSURES` in the code. This is the default case. \-Dspan\_CONFIG\_CONTRACT\_LEVEL\_OFF Define this macro to exclude both `span_EXPECTS` and `span_ENSURES` from the code. \-Dspan\_CONFIG_CONTRACT\_LEVEL\_EXPECTS\_ONLY Define this macro to include `span_EXPECTS` in the code and exclude `span_ENSURES` from the code. \-Dspan\_CONFIG\_CONTRACT\_LEVEL\_ENSURES\_ONLY Define this macro to exclude `span_EXPECTS` from the code and include `span_ENSURES` in the code. \-Dspan\_CONFIG\_CONTRACT\_VIOLATION\_TERMINATES (*default*) Define this macro to call `std::terminate()` on a contract violation in `span_EXPECTS`, `span_ENSURES`. This is the default case. \-Dspan\_CONFIG\_CONTRACT\_VIOLATION\_THROWS Define this macro to throw an exception of implementation-defined type that is derived from `std::runtime_exception` instead of calling `std::terminate()` on a contract violation in `span_EXPECTS` and `span_ENSURES`. See also [disable exceptions](#disable-exceptions). Reported to work with -------------------- The table below mentions the compiler versions *span lite* is reported to work with. OS | Compiler | Where | Versions | ------------:|:-----------|:--------|:---------| **GNU/Linux**| Clang/LLVM | Travis | 3.5.0, 3.6.2, 3.7.1, 3.8.0, 3.9.1, 4.0.1 |   | GCC | Travis | 5.5.0, 6.4.0, 7.3.0 | **OS X** | ? | Local | ? | **Windows** | Clang/LLVM | Local | 6.0.0 |   | GCC | Local | 7.2.0 |   | Visual C++
(Visual Studio)| Local | 8 (2005), 10 (2010), 11 (2012),
12 (2013), 14 (2015), 15 (2017) |   | Visual C++
(Visual Studio)| AppVeyor | 10 (2010), 11 (2012),
12 (2013), 14 (2015), 15 (2017) | ## Building the tests To build the tests you need: - [CMake](http://cmake.org), version 3.0 or later to be installed and in your PATH. - A [suitable compiler](#reported-to-work-with). The [*lest* test framework](https://github.com/martinmoene/lest) is included in the [test folder](test). The following steps assume that the [*span lite* source code](https://github.com/martinmoene/span-lite) has been cloned into a directory named `./span-lite`. 1. Create a directory for the build outputs. cd ./span-lite md build && cd build 2. Configure CMake to use the compiler of your choice (run `cmake --help` for a list). cmake -G "Unix Makefiles" -DSPAN_LITE_OPT_BUILD_TESTS=ON .. 3. Optional. You can control above configuration through the following options: `-DSPAN_LITE_OPT_BUILD_TESTS=ON`: build the tests for span, default off `-DSPAN_LITE_OPT_BUILD_EXAMPLES=OFF`: build the examples, default off 4. Build the test suite. cmake --build . 5. Run the test suite. ctest -V All tests should pass, indicating your platform is supported and you are ready to use *span lite*. ## Other implementations of span - *gsl-lite* [span](https://github.com/martinmoene/gsl-lite/blob/73c4f16f2b35fc174fc2f09d44d5ab13e5c638c3/include/gsl/gsl-lite.hpp#L1221). - Microsoft GSL [span](https://github.com/Microsoft/GSL/blob/master/include/gsl/span). - Google Abseil [span](https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h). - Marshall Clow's [libc++ span snippet](https://github.com/mclow/snippets/blob/master/span.cpp). - Tristan Brindle's [Implementation of C++20's std::span for older compilers](https://github.com/tcbrindle/span). - [Search _span c++_ on GitHub](https://github.com/search?l=C%2B%2B&q=span+c%2B%2B&type=Repositories&utf8=%E2%9C%93). ## Notes and references *Interface and specification* - [span on cppreference](https://en.cppreference.com/w/cpp/container/span). - [p0122 - C++20 Proposal](http://wg21.link/p0122). - [span in C++20 Working Draft](http://eel.is/c++draft/views). *Presentations* - TBD *Proposals* - [p0122 - span: bounds-safe views for sequences of objects](http://wg21.link/p0122). - [p1024 - Usability Enhancements for std::span](http://wg21.link/p1024). - [p1419 - A SFINAE-friendly trait to determine the extent of statically sized containers](http://wg21.link/p1419). - [p0805 - Comparing Containers](http://wg21.link/p0805). - [p1085 - Should Span be Regular?](http://wg21.link/p0805). - [p0091 - Template argument deduction for class templates](http://wg21.link/p0091). - [p0856 - Restrict Access Property for mdspan and span](http://wg21.link/p0856). - [p1428 - Subscripts and sizes should be signed](http://wg21.link/p1428). - [p1089 - Sizes Should Only span Unsigned](http://wg21.link/p1089). - [p1227 - Signed size() functions](http://wg21.link/p1227). - [p1872 - span should have size_type, not index_type](http://wg21.link/p1872). - [p2447 - std::span and the missing constructor](https://wg21.link/p2447). - [lwg 3101 - span's Container constructors need another constraint](https://cplusplus.github.io/LWG/issue3101). - [Reddit - 2018-06 Rapperswil ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/8prqzm/2018_rapperswil_iso_c_committee_trip_report/) - [Reddit - 2018-11 San Diego ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/9vwvbz/2018_san_diego_iso_c_committee_trip_report_ranges/). - [Reddit - 2019-02 Kona ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/au0c4x/201902_kona_iso_c_committee_trip_report_c20/). - [Reddit - 2019-07 Cologne ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/cfk9de/201907_cologne_iso_c_committee_trip_report_the/) - [Reddit - 2019-11 Belfast ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/dtuov8/201911_belfast_iso_c_committee_trip_report/) - Titus Winters. [Revisiting Regular Types](https://abseil.io/blog/20180531-regular-types). Abseil Blog. 31 May 2018. ## Appendix ### A.1 Compile-time information The version of *span lite* is available via tag `[.version]`. The following tags are available for information on the compiler and on the C++ standard library used: `[.compiler]`, `[.stdc++]`, `[.stdlanguage]` and `[.stdlibrary]`. ### A.2 Span lite test specification
click to expand

```Text span<>: Terminates construction from a nullptr and a non-zero size (C++11) span<>: Terminates construction from two pointers in the wrong order span<>: Terminates construction from a null pointer and a non-zero size span<>: Terminates creation of a sub span of the first n elements for n exceeding the span span<>: Terminates creation of a sub span of the last n elements for n exceeding the span span<>: Terminates creation of a sub span outside the span span<>: Terminates access outside the span span<>: Throws on access outside the span via at(): std::out_of_range [span_FEATURE_MEMBER_AT>0][span_CONFIG_NO_EXCEPTIONS=0] span<>: Termination throws std::logic_error-derived exception [span_CONFIG_CONTRACT_VIOLATION_THROWS=1] span<>: Allows to default-construct span<>: Allows to construct from a nullptr and a zero size (C++11) span<>: Allows to construct from two pointers span<>: Allows to construct from two iterators span<>: Allows to construct from two iterators - empty range span<>: Allows to construct from two iterators - move-only element span<>: Allows to construct from an iterator and a size span<>: Allows to construct from an iterator and a size - empty range span<>: Allows to construct from an iterator and a size - move-only element span<>: Allows to construct from two pointers to const span<>: Allows to construct from a non-null pointer and a size span<>: Allows to construct from a non-null pointer to const and a size span<>: Allows to construct from a temporary pointer and a size span<>: Allows to construct from a temporary pointer to const and a size span<>: Allows to construct from any pointer and a zero size (C++98) span<>: Allows to construct from a pointer and a size via a deduction guide (C++17) span<>: Allows to construct from an iterator and a size via a deduction guide (C++17) span<>: Allows to construct from two iterators via a deduction guide (C++17) span<>: Allows to construct from a C-array span<>: Allows to construct from a C-array via a deduction guide (C++17) span<>: Allows to construct from a const C-array span<>: Allows to construct from a C-array with size via decay to pointer (potentially dangerous) span<>: Allows to construct from a const C-array with size via decay to pointer (potentially dangerous) span<>: Allows to construct from a std::initializer_list<> (C++11) span<>: Allows to construct from a std::initializer_list<> as a constant set of values (C++11, p2447) span<>: Allows to construct from a std::array<> (C++11) span<>: Allows to construct from a std::array via a deduction guide (C++17) span<>: Allows to construct from a std::array<> with const data (C++11, span_FEATURE_CONSTR..._ELEMENT_TYPE=1) span<>: Allows to construct from an empty std::array<> (C++11) span<>: Allows to construct from a container (std::vector<>) span<>: Allows to construct from a container via a deduction guide (std::vector<>, C++17) span<>: Allows to tag-construct from a container (std::vector<>) span<>: Allows to tag-construct from a const container (std::vector<>) span<>: Allows to copy-construct from another span of the same type span<>: Allows to copy-construct from another span of a compatible type span<>: Allows to copy-construct from a temporary span of the same type (C++11) span<>: Allows to copy-assign from another span of the same type span<>: Allows to copy-assign from a temporary span of the same type (C++11) span<>: Allows to create a sub span of the first n elements span<>: Allows to create a sub span of the last n elements span<>: Allows to create a sub span starting at a given offset span<>: Allows to create a sub span starting at a given offset with a given length span<>: Allows to observe an element via array indexing span<>: Allows to observe an element via call indexing span<>: Allows to observe an element via at() [span_FEATURE_MEMBER_AT>0] span<>: Allows to observe an element via data() span<>: Allows to observe the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1] span<>: Allows to observe the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1] span<>: Allows to change an element via array indexing span<>: Allows to change an element via call indexing span<>: Allows to change an element via at() [span_FEATURE_MEMBER_AT>0] span<>: Allows to change an element via data() span<>: Allows to change the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1] span<>: Allows to change the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1] span<>: Allows to swap with another span [span_FEATURE_MEMBER_SWAP=1] span<>: Allows forward iteration span<>: Allows const forward iteration span<>: Allows reverse iteration span<>: Allows const reverse iteration span<>: Allows to identify if a span is the same as another span [span_FEATURE_SAME=1] span<>: Allows to compare equal to another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare unequal to another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare less than another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare less than or equal to another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare greater than another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare greater than or equal to another span of the same type [span_FEATURE_COMPARISON=1] span<>: Allows to compare to another span of the same type and different cv-ness [span_FEATURE_SAME=0] span<>: Allows to compare empty spans as equal [span_FEATURE_COMPARISON=1] span<>: Allows to test for empty span via empty(), empty case span<>: Allows to test for empty span via empty(), non-empty case span<>: Allows to obtain the number of elements via size() span<>: Allows to obtain the number of elements via ssize() span<>: Allows to obtain the number of bytes via size_bytes() span<>: Allows to view the elements as read-only bytes span<>: Allows to view and change the elements as writable bytes make_span() [span_FEATURE_MAKE_SPAN_TO_STD=99] make_span(): Allows building from two pointers make_span(): Allows building from two const pointers make_span(): Allows building from a non-null pointer and a size make_span(): Allows building from a non-null const pointer and a size make_span(): Allows building from a C-array make_span(): Allows building from a const C-array make_span(): Allows building from a std::initializer_list<> (C++11) make_span(): Allows building from a std::initializer_list<> as a constant set of values (C++11) make_span(): Allows building from a std::array<> (C++11) make_span(): Allows building from a const std::array<> (C++11) make_span(): Allows building from a container (std::vector<>) make_span(): Allows building from a const container (std::vector<>) make_span(): Allows building from a container (with_container_t, std::vector<>) make_span(): Allows building from a const container (with_container_t, std::vector<>) byte_span() [span_FEATURE_BYTE_SPAN=1] byte_span(): Allows building a span of std::byte from a single object (C++17, byte-lite) byte_span(): Allows building a span of const std::byte from a single const object (C++17, byte-lite) first(), last(), subspan() [span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1] first(): Allows to create a sub span of the first n elements (span, template parameter) first(): Allows to create a sub span of the first n elements (span, function parameter) first(): Allows to create a sub span of the first n elements (compatible container, template parameter) first(): Allows to create a sub span of the first n elements (compatible container, function parameter) last(): Allows to create a sub span of the last n elements (span, template parameter) last(): Allows to create a sub span of the last n elements (span, function parameter) last(): Allows to create a sub span of the last n elements (compatible container, template parameter) last(): Allows to create a sub span of the last n elements (compatible container, function parameter) subspan(): Allows to create a sub span starting at a given offset (span, template parameter) subspan(): Allows to create a sub span starting at a given offset (span, function parameter) subspan(): Allows to create a sub span starting at a given offset (compatible container, template parameter) subspan(): Allows to create a sub span starting at a given offset (compatible container, function parameter) size(): Allows to obtain the number of elements via size() ssize(): Allows to obtain the number of elements via ssize() tuple_size<>: Allows to obtain the number of elements via std::tuple_size<> (C++11) tuple_element<>: Allows to obtain an element via std::tuple_element<> (C++11) tuple_element<>: Allows to obtain an element via std::tuple_element_t<> (C++11) get(spn): Allows to access an element via std::get<>() tweak header: reads tweak header if supported [tweak] ```

qbs-src-3.3.1/src/shared/span/.clang-format0000644000175100017510000000005015232633614020047 0ustar runnerrunnerDisableFormat: true SortIncludes: Never qbs-src-3.3.1/src/shared/bundledqt/0000755000175100017510000000000015232633614016522 5ustar runnerrunnerqbs-src-3.3.1/src/shared/bundledqt/qt.conf0000644000175100017510000000002415232633614020011 0ustar runnerrunner[Paths] Prefix = .. qbs-src-3.3.1/src/shared/bundledqt/bundledqt.qbs0000644000175100017510000001634715232633614021226 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.Utilities Product { Depends { name: "qbsbuildconfig" } Depends { name: "Qt"; submodules: ["core", "gui", "network", "printsupport", "widgets", "xml"] } Depends { name: "Qt.test"; condition: project.withTests === true } Depends { name: "Qt.core5compat"; condition: Utilities.versionCompare(Qt.core.version, "6") >= 0 } Depends { name: "Qt"; submodules: [ "dbus", "xcb_qpa_lib-private" ]; required: false } condition: { if (!qbsbuildconfig.enableBundledQt) return false; if (Qt.core.staticBuild) throw("Cannot bundle static Qt libraries"); return true; } readonly property string qtDebugLibrarySuffix: { if (Qt.core.qtBuildVariant !== "debug") return ""; if (qbs.targetOS.contains("windows")) return "d"; if (qbs.targetOS.contains("darwin")) return "_debug"; return ""; } readonly property string styleName: { if (Utilities.versionCompare(Qt.core.version, "6.7.0") >= 0) return "qmodernwindowsstyle"; return "qwindowsvistastyle"; } Group { name: "qt.conf" files: ["qt.conf"] qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } Group { name: "Qt libraries" files: { function getLibsForQtModule(mod) { if (mod === "script" && !Qt[mod].present) return []; if ((mod !== "core") && !Qt[mod].hasLibrary) return []; if (Qt[mod].isStaticLibrary) return []; var list = []; if (qbs.targetOS.contains("windows")) { var basename = FileInfo.baseName(Qt[mod].libNameForLinker); var dir = Qt.core.binPath; list.push(dir + "/" + basename + ".dll"); } else if (qbs.targetOS.contains("linux")) { var fp = Qt[mod].libFilePath; var basename = FileInfo.baseName(fp); var dir = FileInfo.path(fp); list.push(dir + "/" + basename + ".so"); list.push(dir + "/" + basename + ".so." + Qt.core.versionMajor); if (Utilities.versionCompare(Qt.core.version, "6") < 0) { list.push(dir + "/" + basename + ".so." + Qt.core.versionMajor + "." + Qt.core.versionMinor); } list.push(dir + "/" + basename + ".so." + Qt.core.versionMajor + "." + Qt.core.versionMinor + "." + Qt.core.versionPatch); } else if (Qt.core.frameworkBuild) { var fp = Qt[mod].libFilePathRelease; var fpd = fp + "_debug"; if (qtDebugLibrarySuffix) list.push(fpd); var suffix = ".framework/"; var frameworkPath = fp.substr(0, fp.lastIndexOf(suffix) + suffix.length - 1); var versionsPath = frameworkPath + "/Versions"; var versionName = Utilities.versionCompare(Qt.core.version, "6") >= 0 ? "A" : Qt.core.versionMajor; var versionPath = versionsPath + "/" + versionName; list.push(frameworkPath + "/Resources"); list.push(versionPath + "/Resources/Info.plist"); list.push(versionPath + "/" + FileInfo.fileName(fp)); if (qtDebugLibrarySuffix) list.push(versionPath + "/" + FileInfo.fileName(fpd)); if (qbsbuildconfig.installApiHeaders) { list.push(frameworkPath + "/Headers"); list.push(versionPath + "/Headers/**"); } } return list; } var qtModules = Object.getOwnPropertyNames(Qt); var libraries = Array.prototype.concat.apply([], qtModules.map(getLibsForQtModule)); // Qt might be bundled with additional libraries if (qbs.targetOS.contains("linux")) { var dir = FileInfo.path(Qt.core.libFilePathRelease); var addons = [ "libicui18n", "libicuuc", "libicudata" ]; addons.forEach(function(lib) { libraries.push(dir + "/" + lib + ".so*"); }); } return libraries; } fileTags: [] qbs.install: true qbs.installDir: qbsbuildconfig.libInstallDir qbs.installSourceBase: qbs.targetOS.contains("windows") ? Qt.core.binPath : Qt.core.libPath } Group { name: "Windows Plugins" condition: qbs.targetOS.contains("windows") prefix: Qt.core.pluginPath + "/" files: [ "platforms/qwindows" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix, "styles/" + styleName + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix ].concat(Utilities.versionCompare(Qt.core.version, "6.2.0") >= 0 ? [ "tls/qschannelbackend" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix ] : []) qbs.install: true qbs.installDir: "plugins" qbs.installSourceBase: prefix } Group { name: "macOS Plugins" condition: qbs.targetOS.contains("darwin") prefix: Qt.core.pluginPath + "/" files: [ "platforms/libqcocoa" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix, "styles/libqmacstyle" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix ].concat(Utilities.versionCompare(Qt.core.version, "6.2.0") >= 0 ? [ "tls/libqsecuretransportbackend" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix ] : []) qbs.install: true qbs.installDir: "plugins" qbs.installSourceBase: prefix } Group { name: "Linux Plugins" condition: qbs.targetOS.contains("linux") prefix: Qt.core.pluginPath + "/" files: [ "platforms/libqxcb" + cpp.dynamicLibrarySuffix, "platformthemes/libqgtk3" + cpp.dynamicLibrarySuffix ].concat(Utilities.versionCompare(Qt.core.version, "6.2.0") >= 0 ? [ "tls/libqopensslbackend" + cpp.dynamicLibrarySuffix ] : []) qbs.install: true qbs.installDir: "plugins" qbs.installSourceBase: prefix } Group { name: "MinGW Runtime DLLs" condition: qbs.targetOS.contains("windows") && qbs.toolchain.contains("mingw") files: { var libFileGlobs = [ "*libgcc_s*.dll", "*libstdc++-6.dll", "*libwinpthread-1.dll" ]; var searchPaths = cpp.compilerLibraryPaths; return Array.prototype.concat.apply([], searchPaths.map(function(path) { return libFileGlobs.map(function(glob) { return path + "/" + glob; }); })); } qbs.install: true qbs.installDir: "bin" } } qbs-src-3.3.1/src/shared/CMakeLists.txt0000644000175100017510000000010715232633614017276 0ustar runnerrunneradd_subdirectory(lsp) add_subdirectory(quickjs) add_subdirectory(span) qbs-src-3.3.1/src/shared/quickjs/0000755000175100017510000000000015232633614016211 5ustar runnerrunnerqbs-src-3.3.1/src/shared/quickjs/dtoa.c0000644000175100017510000012753415232633614017320 0ustar runnerrunner/* * Tiny float64 printing and parsing library * * Copyright (c) 2024 Fabrice Bellard * * 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. */ #include #include #include #include #include #include #include // #include #include // #include #include "cutils.h" #include "dtoa.h" /* TODO: - test n_digits=101 instead of 100 - simplify subnormal handling - reduce max memory usage - free format: could add shortcut if exact result - use 64 bit limb_t when possible - use another algorithm for free format dtoa in base 10 (ryu ?) */ #define USE_POW5_TABLE /* use fast path to print small integers in free format */ #define USE_FAST_INT #define LIMB_LOG2_BITS 5 #define LIMB_BITS (1 << LIMB_LOG2_BITS) typedef int32_t slimb_t; typedef uint32_t limb_t; typedef uint64_t dlimb_t; #define LIMB_DIGITS 9 #define JS_RADIX_MAX 36 #define DBIGNUM_LEN_MAX 52 /* ~ 2^(1072+53)*36^100 (dtoa) */ #define MANT_LEN_MAX 18 /* < 36^100 */ typedef intptr_t mp_size_t; /* the represented number is sum(i, tab[i]*2^(LIMB_BITS * i)) */ typedef struct { int len; /* >= 1 */ limb_t tab[]; } mpb_t; static limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n) { size_t i; limb_t k, a; k=b; for(i=0;i> LIMB_BITS; } return l; } /* WARNING: d must be >= 2^(LIMB_BITS-1) */ static inline limb_t udiv1norm_init(limb_t d) { limb_t a0, a1; a1 = -d - 1; a0 = -1; return (((dlimb_t)a1 << LIMB_BITS) | a0) / d; } /* return the quotient and the remainder in '*pr'of 'a1*2^LIMB_BITS+a0 / d' with 0 <= a1 < d. */ static inline limb_t udiv1norm(limb_t *pr, limb_t a1, limb_t a0, limb_t d, limb_t d_inv) { limb_t n1m, n_adj, q, r, ah; dlimb_t a; n1m = ((slimb_t)a0 >> (LIMB_BITS - 1)); n_adj = a0 + (n1m & d); a = (dlimb_t)d_inv * (a1 - n1m) + n_adj; q = (a >> LIMB_BITS) + a1; /* compute a - q * r and update q so that the remainder is between 0 and d - 1 */ a = ((dlimb_t)a1 << LIMB_BITS) | a0; a = a - (dlimb_t)q * d - d; ah = a >> LIMB_BITS; q += 1 + ah; r = (limb_t)a + (ah & d); *pr = r; return q; } static limb_t mp_div1(limb_t *tabr, const limb_t *taba, limb_t n, limb_t b, limb_t r) { slimb_t i; dlimb_t a1; for(i = n - 1; i >= 0; i--) { a1 = ((dlimb_t)r << LIMB_BITS) | taba[i]; tabr[i] = a1 / b; r = a1 % b; } return r; } /* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). 1 <= shift <= LIMB_BITS - 1 */ static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, int shift, limb_t high) { mp_size_t i; limb_t l, a; assert(shift >= 1 && shift < LIMB_BITS); l = high; for(i = n - 1; i >= 0; i--) { a = tab[i]; tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift)); l = a; } return l & (((limb_t)1 << shift) - 1); } /* r = (a << shift) + low. 1 <= shift <= LIMB_BITS - 1, 0 <= low < 2^shift. */ static limb_t mp_shl(limb_t *tab_r, const limb_t *tab, mp_size_t n, int shift, limb_t low) { mp_size_t i; limb_t l, a; assert(shift >= 1 && shift < LIMB_BITS); l = low; for(i = 0; i < n; i++) { a = tab[i]; tab_r[i] = (a << shift) | l; l = (a >> (LIMB_BITS - shift)); } return l; } static no_inline limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n, limb_t b, limb_t r, limb_t b_inv, int shift) { slimb_t i; if (shift != 0) { r = (r << shift) | mp_shl(tabr, taba, n, shift, 0); } for(i = n - 1; i >= 0; i--) { tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv); } r >>= shift; return r; } static __maybe_unused void mpb_dump(const char *str, const mpb_t *a) { int i; printf("%s= 0x", str); for(i = a->len - 1; i >= 0; i--) { printf("%08x", a->tab[i]); if (i != 0) printf("_"); } printf("\n"); } static void mpb_renorm(mpb_t *r) { while (r->len > 1 && r->tab[r->len - 1] == 0) r->len--; } #ifdef USE_POW5_TABLE static const uint32_t pow5_table[17] = { 0x00000005, 0x00000019, 0x0000007d, 0x00000271, 0x00000c35, 0x00003d09, 0x0001312d, 0x0005f5e1, 0x001dcd65, 0x009502f9, 0x02e90edd, 0x0e8d4a51, 0x48c27395, 0x6bcc41e9, 0x1afd498d, 0x86f26fc1, 0xa2bc2ec5, }; static const uint8_t pow5h_table[4] = { 0x00000001, 0x00000007, 0x00000023, 0x000000b1, }; static const uint32_t pow5_inv_table[13] = { 0x99999999, 0x47ae147a, 0x0624dd2f, 0xa36e2eb1, 0x4f8b588e, 0x0c6f7a0b, 0xad7f29ab, 0x5798ee23, 0x12e0be82, 0xb7cdfd9d, 0x5fd7fe17, 0x19799812, 0xc25c2684, }; #endif /* return a^b */ static uint64_t pow_ui(uint32_t a, uint32_t b) { int i, n_bits; uint64_t r; if (b == 0) return 1; if (b == 1) return a; #ifdef USE_POW5_TABLE if ((a == 5 || a == 10) && b <= 17) { r = pow5_table[b - 1]; if (b >= 14) { r |= (uint64_t)pow5h_table[b - 14] << 32; } if (a == 10) r <<= b; return r; } #endif r = a; n_bits = 32 - clz32(b); for(i = n_bits - 2; i >= 0; i--) { r *= r; if ((b >> i) & 1) r *= a; } return r; } static uint32_t pow_ui_inv(uint32_t *pr_inv, int *pshift, uint32_t a, uint32_t b) { uint32_t r_inv, r; int shift; #ifdef USE_POW5_TABLE if (a == 5 && b >= 1 && b <= 13) { r = pow5_table[b - 1]; shift = clz32(r); r <<= shift; r_inv = pow5_inv_table[b - 1]; } else #endif { r = pow_ui(a, b); shift = clz32(r); r <<= shift; r_inv = udiv1norm_init(r); } *pshift = shift; *pr_inv = r_inv; return r; } enum { JS_RNDN, /* round to nearest, ties to even */ JS_RNDNA, /* round to nearest, ties away from zero */ JS_RNDZ, }; static int mpb_get_bit(const mpb_t *r, int k) { int l; l = (unsigned)k / LIMB_BITS; k = k & (LIMB_BITS - 1); if (l >= r->len) return 0; else return (r->tab[l] >> k) & 1; } /* compute round(r / 2^shift). 'shift' can be negative */ static void mpb_shr_round(mpb_t *r, int shift, int rnd_mode) { int l, i; if (shift == 0) return; if (shift < 0) { shift = -shift; l = (unsigned)shift / LIMB_BITS; shift = shift & (LIMB_BITS - 1); if (shift != 0) { r->tab[r->len] = mp_shl(r->tab, r->tab, r->len, shift, 0); r->len++; mpb_renorm(r); } if (l > 0) { for(i = r->len - 1; i >= 0; i--) r->tab[i + l] = r->tab[i]; for(i = 0; i < l; i++) r->tab[i] = 0; r->len += l; } } else { limb_t bit1, bit2; int k, add_one; switch(rnd_mode) { default: case JS_RNDZ: add_one = 0; break; case JS_RNDN: case JS_RNDNA: bit1 = mpb_get_bit(r, shift - 1); if (bit1) { if (rnd_mode == JS_RNDNA) { bit2 = 1; } else { /* bit2 = oring of all the bits after bit1 */ bit2 = 0; if (shift >= 2) { k = shift - 1; l = (unsigned)k / LIMB_BITS; k = k & (LIMB_BITS - 1); for(i = 0; i < min_int(l, r->len); i++) bit2 |= r->tab[i]; if (l < r->len) bit2 |= r->tab[l] & (((limb_t)1 << k) - 1); } } if (bit2) { add_one = 1; } else { /* round to even */ add_one = mpb_get_bit(r, shift); } } else { add_one = 0; } break; } l = (unsigned)shift / LIMB_BITS; shift = shift & (LIMB_BITS - 1); if (l >= r->len) { r->len = 1; r->tab[0] = add_one; } else { if (l > 0) { r->len -= l; for(i = 0; i < r->len; i++) r->tab[i] = r->tab[i + l]; } if (shift != 0) { mp_shr(r->tab, r->tab, r->len, shift, 0); mpb_renorm(r); } if (add_one) { limb_t a; a = mp_add_ui(r->tab, 1, r->len); if (a) r->tab[r->len++] = a; } } } } /* return -1, 0 or 1 */ static int mpb_cmp(const mpb_t *a, const mpb_t *b) { mp_size_t i; if (a->len < b->len) return -1; else if (a->len > b->len) return 1; for(i = a->len - 1; i >= 0; i--) { if (a->tab[i] != b->tab[i]) { if (a->tab[i] < b->tab[i]) return -1; else return 1; } } return 0; } static void mpb_set_u64(mpb_t *r, uint64_t m) { #if LIMB_BITS == 64 r->tab[0] = m; r->len = 1; #else r->tab[0] = m; r->tab[1] = m >> LIMB_BITS; if (r->tab[1] == 0) r->len = 1; else r->len = 2; #endif } static uint64_t mpb_get_u64(mpb_t *r) { #if LIMB_BITS == 64 return r->tab[0]; #else if (r->len == 1) { return r->tab[0]; } else { return r->tab[0] | ((uint64_t)r->tab[1] << LIMB_BITS); } #endif } /* floor_log2() = position of the first non zero bit or -1 if zero. */ static int mpb_floor_log2(mpb_t *a) { limb_t v; v = a->tab[a->len - 1]; if (v == 0) return -1; else return a->len * LIMB_BITS - 1 - clz32(v); } #define MUL_LOG2_RADIX_BASE_LOG2 24 /* round((1 << MUL_LOG2_RADIX_BASE_LOG2)/log2(i + 2)) */ static const uint32_t mul_log2_radix_table[JS_RADIX_MAX - 1] = { 0x000000, 0xa1849d, 0x000000, 0x6e40d2, 0x6308c9, 0x5b3065, 0x000000, 0x50c24e, 0x4d104d, 0x4a0027, 0x4768ce, 0x452e54, 0x433d00, 0x418677, 0x000000, 0x3ea16b, 0x3d645a, 0x3c43c2, 0x3b3b9a, 0x3a4899, 0x39680b, 0x3897b3, 0x37d5af, 0x372069, 0x367686, 0x35d6df, 0x354072, 0x34b261, 0x342bea, 0x33ac62, 0x000000, 0x32bfd9, 0x3251dd, 0x31e8d6, 0x318465, }; /* return floor(a / log2(radix)) for -2048 <= a <= 2047 */ static int mul_log2_radix(int a, int radix) { int radix_bits, mult; if ((radix & (radix - 1)) == 0) { /* if the radix is a power of two better to do it exactly */ radix_bits = 31 - clz32(radix); if (a < 0) a -= radix_bits - 1; return a / radix_bits; } else { mult = mul_log2_radix_table[radix - 2]; return ((int64_t)a * mult) >> MUL_LOG2_RADIX_BASE_LOG2; } } #if 0 static void build_mul_log2_radix_table(void) { int base, radix, mult, col, base_log2; base_log2 = 24; base = 1 << base_log2; col = 0; for(radix = 2; radix <= 36; radix++) { if ((radix & (radix - 1)) == 0) mult = 0; else mult = lrint((double)base / log2(radix)); printf("0x%06x, ", mult); if (++col == 4) { printf("\n"); col = 0; } } printf("\n"); } static void mul_log2_radix_test(void) { int radix, i, ref, r; for(radix = 2; radix <= 36; radix++) { for(i = -2048; i <= 2047; i++) { ref = (int)floor((double)i / log2(radix)); r = mul_log2_radix(i, radix); if (ref != r) { printf("ERROR: radix=%d i=%d r=%d ref=%d\n", radix, i, r, ref); exit(1); } } } if (0) build_mul_log2_radix_table(); } #endif static void u32toa_len(char *buf, uint32_t n, size_t len) { int digit, i; for(i = len - 1; i >= 0; i--) { digit = n % 10; n = n / 10; buf[i] = digit + '0'; } } /* for power of 2 radixes. len >= 1 */ static void u64toa_bin_len(char *buf, uint64_t n, unsigned int radix_bits, int len) { int digit, i; unsigned int mask; mask = (1 << radix_bits) - 1; for(i = len - 1; i >= 0; i--) { digit = n & mask; n >>= radix_bits; if (digit < 10) digit += '0'; else digit += 'a' - 10; buf[i] = digit; } } /* len >= 1. 2 <= radix <= 36 */ static void limb_to_a(char *buf, limb_t n, unsigned int radix, int len) { int digit, i; if (radix == 10) { /* specific case with constant divisor */ #if LIMB_BITS == 32 u32toa_len(buf, n, len); #else /* XXX: optimize */ for(i = len - 1; i >= 0; i--) { digit = (limb_t)n % 10; n = (limb_t)n / 10; buf[i] = digit + '0'; } #endif } else { for(i = len - 1; i >= 0; i--) { digit = (limb_t)n % radix; n = (limb_t)n / radix; if (digit < 10) digit += '0'; else digit += 'a' - 10; buf[i] = digit; } } } size_t u32toa(char *buf, uint32_t n) { char buf1[10], *q; size_t len; q = buf1 + sizeof(buf1); do { *--q = n % 10 + '0'; n /= 10; } while (n != 0); len = buf1 + sizeof(buf1) - q; memcpy(buf, q, len); return len; } size_t i32toa(char *buf, int32_t n) { if (n >= 0) { return u32toa(buf, n); } else { buf[0] = '-'; return u32toa(buf + 1, -(uint32_t)n) + 1; } } #ifdef USE_FAST_INT size_t u64toa(char *buf, uint64_t n) { if (n < 0x100000000) { return u32toa(buf, n); } else { uint64_t n1; char *q = buf; uint32_t n2; n1 = n / 1000000000; n %= 1000000000; if (n1 >= 0x100000000) { n2 = n1 / 1000000000; n1 = n1 % 1000000000; /* at most two digits */ if (n2 >= 10) { *q++ = n2 / 10 + '0'; n2 %= 10; } *q++ = n2 + '0'; u32toa_len(q, n1, 9); q += 9; } else { q += u32toa(q, n1); } u32toa_len(q, n, 9); q += 9; return q - buf; } } size_t i64toa(char *buf, int64_t n) { if (n >= 0) { return u64toa(buf, n); } else { buf[0] = '-'; return u64toa(buf + 1, -(uint64_t)n) + 1; } } /* XXX: only tested for 1 <= n < 2^53 */ size_t u64toa_radix(char *buf, uint64_t n, unsigned int radix) { int radix_bits, l; if (likely(radix == 10)) return u64toa(buf, n); if ((radix & (radix - 1)) == 0) { radix_bits = 31 - clz32(radix); if (n == 0) l = 1; else l = (64 - clz64(n) + radix_bits - 1) / radix_bits; u64toa_bin_len(buf, n, radix_bits, l); return l; } else { char buf1[41], *q; /* maximum length for radix = 3 */ size_t len; int digit; q = buf1 + sizeof(buf1); do { digit = n % radix; n /= radix; if (digit < 10) digit += '0'; else digit += 'a' - 10; *--q = digit; } while (n != 0); len = buf1 + sizeof(buf1) - q; memcpy(buf, q, len); return len; } } size_t i64toa_radix(char *buf, int64_t n, unsigned int radix) { if (n >= 0) { return u64toa_radix(buf, n, radix); } else { buf[0] = '-'; return u64toa_radix(buf + 1, -(uint64_t)n, radix) + 1; } } #endif /* USE_FAST_INT */ static const uint8_t digits_per_limb_table[JS_RADIX_MAX - 1] = { #if LIMB_BITS == 32 32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, #else 64,40,32,27,24,22,21,20,19,18,17,17,16,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,13,12,12,12,12,12,12, #endif }; static const uint32_t radix_base_table[JS_RADIX_MAX - 1] = { 0x00000000, 0xcfd41b91, 0x00000000, 0x48c27395, 0x81bf1000, 0x75db9c97, 0x40000000, 0xcfd41b91, 0x3b9aca00, 0x8c8b6d2b, 0x19a10000, 0x309f1021, 0x57f6c100, 0x98c29b81, 0x00000000, 0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d, 0x94ace180, 0xcaf18367, 0x0b640000, 0x0e8d4a51, 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x81bf1000, }; /* XXX: remove the table ? */ static uint8_t dtoa_max_digits_table[JS_RADIX_MAX - 1] = { 54, 35, 28, 24, 22, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, }; /* we limit the maximum number of significant digits for atod to about 128 bits of precision for non power of two bases. The only requirement for Javascript is at least 20 digits in base 10. For power of two bases, we do an exact rounding in all the cases. */ static uint8_t atod_max_digits_table[JS_RADIX_MAX - 1] = { 64, 80, 32, 55, 49, 45, 21, 40, 38, 37, 35, 34, 33, 32, 16, 31, 30, 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 12, 25, 25, 24, 24, }; /* if abs(d) >= B^max_exponent, it is an overflow */ static const int16_t max_exponent[JS_RADIX_MAX - 1] = { 1024, 647, 512, 442, 397, 365, 342, 324, 309, 297, 286, 277, 269, 263, 256, 251, 246, 242, 237, 234, 230, 227, 224, 221, 218, 216, 214, 211, 209, 207, 205, 203, 202, 200, 199, }; /* if abs(d) <= B^min_exponent, it is an underflow */ static const int16_t min_exponent[JS_RADIX_MAX - 1] = { -1075, -679, -538, -463, -416, -383, -359, -340, -324, -311, -300, -291, -283, -276, -269, -263, -258, -254, -249, -245, -242, -238, -235, -232, -229, -227, -224, -222, -220, -217, -215, -214, -212, -210, -208, }; #if 0 void build_tables(void) { int r, j, radix, n, col, i; /* radix_base_table */ for(radix = 2; radix <= 36; radix++) { r = 1; for(j = 0; j < digits_per_limb_table[radix - 2]; j++) { r *= radix; } printf(" 0x%08x,", r); if ((radix % 4) == 1) printf("\n"); } printf("\n"); /* dtoa_max_digits_table */ for(radix = 2; radix <= 36; radix++) { /* Note: over estimated when the radix is a power of two */ printf(" %d,", 1 + (int)ceil(53.0 / log2(radix))); } printf("\n"); /* atod_max_digits_table */ for(radix = 2; radix <= 36; radix++) { if ((radix & (radix - 1)) == 0) { /* 64 bits is more than enough */ n = (int)floor(64.0 / log2(radix)); } else { n = (int)floor(128.0 / log2(radix)); } printf(" %d,", n); } printf("\n"); printf("static const int16_t max_exponent[JS_RADIX_MAX - 1] = {\n"); col = 0; for(radix = 2; radix <= 36; radix++) { printf("%5d, ", (int)ceil(1024 / log2(radix))); if (++col == 8) { col = 0; printf("\n"); } } printf("\n};\n\n"); printf("static const int16_t min_exponent[JS_RADIX_MAX - 1] = {\n"); col = 0; for(radix = 2; radix <= 36; radix++) { printf("%5d, ", (int)floor(-1075 / log2(radix))); if (++col == 8) { col = 0; printf("\n"); } } printf("\n};\n\n"); printf("static const uint32_t pow5_table[16] = {\n"); col = 0; for(i = 2; i <= 17; i++) { r = 1; for(j = 0; j < i; j++) { r *= 5; } printf("0x%08x, ", r); if (++col == 4) { col = 0; printf("\n"); } } printf("\n};\n\n"); /* high part */ printf("static const uint8_t pow5h_table[4] = {\n"); col = 0; for(i = 14; i <= 17; i++) { uint64_t r1; r1 = 1; for(j = 0; j < i; j++) { r1 *= 5; } printf("0x%08x, ", (uint32_t)(r1 >> 32)); if (++col == 4) { col = 0; printf("\n"); } } printf("\n};\n\n"); } #endif /* n_digits >= 1. 0 <= dot_pos <= n_digits. If dot_pos == n_digits, the dot is not displayed. 'a' is modified. */ static int output_digits(char *buf, mpb_t *a, int radix, int n_digits1, int dot_pos) { int n_digits, digits_per_limb, radix_bits, n, len; n_digits = n_digits1; if ((radix & (radix - 1)) == 0) { /* radix = 2^radix_bits */ radix_bits = 31 - clz32(radix); } else { radix_bits = 0; } digits_per_limb = digits_per_limb_table[radix - 2]; if (radix_bits != 0) { for(;;) { n = min_int(n_digits, digits_per_limb); n_digits -= n; u64toa_bin_len(buf + n_digits, a->tab[0], radix_bits, n); if (n_digits == 0) break; mpb_shr_round(a, digits_per_limb * radix_bits, JS_RNDZ); } } else { limb_t r; while (n_digits != 0) { n = min_int(n_digits, digits_per_limb); n_digits -= n; r = mp_div1(a->tab, a->tab, a->len, radix_base_table[radix - 2], 0); mpb_renorm(a); limb_to_a(buf + n_digits, r, radix, n); } } /* add the dot */ len = n_digits1; if (dot_pos != n_digits1) { memmove(buf + dot_pos + 1, buf + dot_pos, n_digits1 - dot_pos); buf[dot_pos] = '.'; len++; } return len; } /* return (a, e_offset) such that a = a * (radix1*2^radix_shift)^f * 2^-e_offset. 'f' can be negative. */ static int mul_pow(mpb_t *a, int radix1, int radix_shift, int f, bool is_int, int e) { int e_offset, d, n, n0; e_offset = -f * radix_shift; if (radix1 != 1) { d = digits_per_limb_table[radix1 - 2]; if (f >= 0) { limb_t h, b; b = 0; n0 = 0; while (f != 0) { n = min_int(f, d); if (n != n0) { b = pow_ui(radix1, n); n0 = n; } h = mp_mul1(a->tab, a->tab, a->len, b, 0); if (h != 0) { a->tab[a->len++] = h; } f -= n; } } else { int extra_bits, l, shift; limb_t r, rem, b, b_inv; f = -f; l = (f + d - 1) / d; /* high bound for the number of limbs (XXX: make it better) */ e_offset += l * LIMB_BITS; if (!is_int) { /* at least 'e' bits are needed in the final result for rounding */ extra_bits = max_int(e - mpb_floor_log2(a), 0); } else { /* at least two extra bits are needed in the final result for rounding */ extra_bits = max_int(2 + e - e_offset, 0); } e_offset += extra_bits; mpb_shr_round(a, -(l * LIMB_BITS + extra_bits), JS_RNDZ); b = 0; b_inv = 0; shift = 0; n0 = 0; rem = 0; while (f != 0) { n = min_int(f, d); if (n != n0) { b = pow_ui_inv(&b_inv, &shift, radix1, n); n0 = n; } r = mp_div1norm(a->tab, a->tab, a->len, b, 0, b_inv, shift); rem |= r; mpb_renorm(a); f -= n; } /* if the remainder is non zero, use it for rounding */ a->tab[0] |= (rem != 0); } } return e_offset; } /* tmp1 = round(m*2^e*radix^f). 'tmp0' is a temporary storage */ static void mul_pow_round(mpb_t *tmp1, uint64_t m, int e, int radix1, int radix_shift, int f, int rnd_mode) { int e_offset; mpb_set_u64(tmp1, m); e_offset = mul_pow(tmp1, radix1, radix_shift, f, true, e); mpb_shr_round(tmp1, -e + e_offset, rnd_mode); } /* return round(a*2^e_offset) rounded as a float64. 'a' is modified */ static uint64_t round_to_d(int *pe, mpb_t *a, int e_offset, int rnd_mode) { int e; uint64_t m; if (a->tab[0] == 0 && a->len == 1) { /* zero result */ m = 0; e = 0; /* don't care */ } else { int prec, prec1, e_min; e = mpb_floor_log2(a) + 1 - e_offset; prec1 = 53; e_min = -1021; if (e < e_min) { /* subnormal result or zero */ prec = prec1 - (e_min - e); } else { prec = prec1; } mpb_shr_round(a, e + e_offset - prec, rnd_mode); m = mpb_get_u64(a); m <<= (53 - prec); /* mantissa overflow due to rounding */ if (m >= (uint64_t)1 << 53) { m >>= 1; e++; } } *pe = e; return m; } /* return (m, e) such that m*2^(e-53) = round(a * radix^f) with 2^52 <= m < 2^53 or m = 0. 'a' is modified. */ static uint64_t mul_pow_round_to_d(int *pe, mpb_t *a, int radix1, int radix_shift, int f, int rnd_mode) { int e_offset; e_offset = mul_pow(a, radix1, radix_shift, f, false, 55); return round_to_d(pe, a, e_offset, rnd_mode); } #ifdef JS_DTOA_DUMP_STATS static int out_len_count[17]; void js_dtoa_dump_stats(void) { int i, sum; sum = 0; for(i = 0; i < 17; i++) sum += out_len_count[i]; for(i = 0; i < 17; i++) { printf("%2d %8d %5.2f%%\n", i + 1, out_len_count[i], (double)out_len_count[i] / sum * 100); } } #endif /* return a maximum bound of the string length. The bound depends on 'd' only if format = JS_DTOA_FORMAT_FRAC or if JS_DTOA_EXP_DISABLED is enabled. */ int js_dtoa_max_len(double d, int radix, int n_digits, int flags) { int fmt = flags & JS_DTOA_FORMAT_MASK; int n, e; uint64_t a; if (fmt != JS_DTOA_FORMAT_FRAC) { if (fmt == JS_DTOA_FORMAT_FREE) { n = dtoa_max_digits_table[radix - 2]; } else { n = n_digits; } if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_DISABLED) { /* no exponential */ a = float64_as_uint64(d); e = (a >> 52) & 0x7ff; if (e == 0x7ff) { /* NaN, Infinity */ n = 0; } else { e -= 1023; /* XXX: adjust */ n += 10 + abs(mul_log2_radix(e - 1, radix)); } } else { /* extra: sign, 1 dot and exponent "e-1000" */ n += 1 + 1 + 6; } } else { a = float64_as_uint64(d); e = (a >> 52) & 0x7ff; if (e == 0x7ff) { /* NaN, Infinity */ n = 0; } else { /* high bound for the integer part */ e -= 1023; /* x < 2^(e + 1) */ if (e < 0) { n = 1; } else { n = 2 + mul_log2_radix(e - 1, radix); } /* sign, extra digit, 1 dot */ n += 1 + 1 + 1 + n_digits; } } return max_int(n, 9); /* also include NaN and [-]Infinity */ } #if defined(__SANITIZE_ADDRESS__) && 0 static void *dtoa_malloc(uint64_t **pptr, size_t size) { return malloc(size); } static void dtoa_free(void *ptr) { free(ptr); } #else static void *dtoa_malloc(uint64_t **pptr, size_t size) { void *ret; ret = *pptr; *pptr += (size + 7) / 8; return ret; } static void dtoa_free(void *ptr) { } #endif /* return the length */ int js_dtoa(char *buf, double d, int radix, int n_digits, int flags, JSDTOATempMem *tmp_mem) { uint64_t a, m, *mptr = tmp_mem->mem; int e, sgn, l, E, P, i, E_max, radix1, radix_shift; char *q; mpb_t *tmp1, *mant_max; int fmt = flags & JS_DTOA_FORMAT_MASK; tmp1 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX); mant_max = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * MANT_LEN_MAX); assert((mptr - tmp_mem->mem) <= sizeof(JSDTOATempMem) / sizeof(mptr[0])); radix_shift = ctz32(radix); radix1 = radix >> radix_shift; a = float64_as_uint64(d); sgn = a >> 63; e = (a >> 52) & 0x7ff; m = a & (((uint64_t)1 << 52) - 1); q = buf; if (e == 0x7ff) { if (m == 0) { if (sgn) *q++ = '-'; memcpy(q, "Infinity", 8); q += 8; } else { memcpy(q, "NaN", 3); q += 3; } goto done; } else if (e == 0) { if (m == 0) { tmp1->len = 1; tmp1->tab[0] = 0; E = 1; if (fmt == JS_DTOA_FORMAT_FREE) P = 1; else if (fmt == JS_DTOA_FORMAT_FRAC) P = n_digits + 1; else P = n_digits; /* "-0" is displayed as "0" if JS_DTOA_MINUS_ZERO is not present */ if (sgn && (flags & JS_DTOA_MINUS_ZERO)) *q++ = '-'; goto output; } /* denormal number: convert to a normal number */ l = clz64(m) - 11; e -= l - 1; m <<= l; } else { m |= (uint64_t)1 << 52; } if (sgn) *q++ = '-'; /* remove the bias */ e -= 1022; /* d = 2^(e-53)*m */ // printf("m=0x%016" PRIx64 " e=%d\n", m, e); #ifdef USE_FAST_INT if (fmt == JS_DTOA_FORMAT_FREE && e >= 1 && e <= 53 && (m & (((uint64_t)1 << (53 - e)) - 1)) == 0 && (flags & JS_DTOA_EXP_MASK) != JS_DTOA_EXP_ENABLED) { m >>= 53 - e; /* 'm' is never zero */ q += u64toa_radix(q, m, radix); goto done; } #endif /* this choice of E implies F=round(x*B^(P-E) is such as: B^(P-1) <= F < 2.B^P. */ E = 1 + mul_log2_radix(e - 1, radix); if (fmt == JS_DTOA_FORMAT_FREE) { int P_max, E0, e1, E_found, P_found; uint64_t m1, mant_found, mant, mant_max1; /* P_max is guarranteed to work by construction */ P_max = dtoa_max_digits_table[radix - 2]; E0 = E; E_found = 0; P_found = 0; mant_found = 0; /* find the minimum number of digits by successive tries */ P = P_max; /* P_max is guarateed to work */ for(;;) { /* mant_max always fits on 64 bits */ mant_max1 = pow_ui(radix, P); /* compute the mantissa in base B */ E = E0; for(;;) { /* XXX: add inexact flag */ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDN); mant = mpb_get_u64(tmp1); if (mant < mant_max1) break; E++; /* at most one iteration is possible */ } /* remove useless trailing zero digits */ while ((mant % radix) == 0) { mant /= radix; P--; } /* garanteed to work for P = P_max */ if (P_found == 0) goto prec_found; /* convert back to base 2 */ mpb_set_u64(tmp1, mant); m1 = mul_pow_round_to_d(&e1, tmp1, radix1, radix_shift, E - P, JS_RNDN); // printf("P=%2d: m=0x%016" PRIx64 " e=%d m1=0x%016" PRIx64 " e1=%d\n", P, m, e, m1, e1); /* Note: (m, e) is never zero here, so the exponent for m1 = 0 does not matter */ if (m1 == m && e1 == e) { prec_found: P_found = P; E_found = E; mant_found = mant; if (P == 1) break; P--; /* try lower exponent */ } else { break; } } P = P_found; E = E_found; mpb_set_u64(tmp1, mant_found); #ifdef JS_DTOA_DUMP_STATS if (radix == 10) { out_len_count[P - 1]++; } #endif } else if (fmt == JS_DTOA_FORMAT_FRAC) { int len; assert(n_digits >= 0 && n_digits <= JS_DTOA_MAX_DIGITS); /* P = max_int(E, 1) + n_digits; */ /* frac is rounded using RNDNA */ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, n_digits, JS_RNDNA); /* we add one extra digit on the left and remove it if needed to avoid testing if the result is < radix^P */ len = output_digits(q, tmp1, radix, max_int(E + 1, 1) + n_digits, max_int(E + 1, 1)); if (q[0] == '0' && len >= 2 && q[1] != '.') { len--; memmove(q, q + 1, len); } q += len; goto done; } else { int pow_shift; assert(n_digits >= 1 && n_digits <= JS_DTOA_MAX_DIGITS); P = n_digits; /* mant_max = radix^P */ mant_max->len = 1; mant_max->tab[0] = 1; pow_shift = mul_pow(mant_max, radix1, radix_shift, P, false, 0); mpb_shr_round(mant_max, pow_shift, JS_RNDZ); for(;;) { /* fixed and frac are rounded using RNDNA */ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDNA); if (mpb_cmp(tmp1, mant_max) < 0) break; E++; /* at most one iteration is possible */ } } output: if (fmt == JS_DTOA_FORMAT_FIXED) E_max = n_digits; else E_max = dtoa_max_digits_table[radix - 2] + 4; if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_ENABLED || ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_AUTO && (E <= -6 || E > E_max))) { q += output_digits(q, tmp1, radix, P, 1); E--; if (radix == 10) { *q++ = 'e'; } else if (radix1 == 1 && radix_shift <= 4) { E *= radix_shift; *q++ = 'p'; } else { *q++ = '@'; } if (E < 0) { *q++ = '-'; E = -E; } else { *q++ = '+'; } q += u32toa(q, E); } else if (E <= 0) { *q++ = '0'; *q++ = '.'; for(i = 0; i < -E; i++) *q++ = '0'; q += output_digits(q, tmp1, radix, P, P); } else { q += output_digits(q, tmp1, radix, P, min_int(P, E)); for(i = 0; i < E - P; i++) *q++ = '0'; } done: *q = '\0'; dtoa_free(mant_max); dtoa_free(tmp1); return q - buf; } static inline int to_digit(int c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'Z') return c - 'A' + 10; else if (c >= 'a' && c <= 'z') return c - 'a' + 10; else return 36; } /* r = r * radix_base + a. radix_base = 0 means radix_base = 2^32 */ static void mpb_mul1_base(mpb_t *r, limb_t radix_base, limb_t a) { int i; if (r->tab[0] == 0 && r->len == 1) { r->tab[0] = a; } else { if (radix_base == 0) { for(i = r->len; i >= 0; i--) { r->tab[i + 1] = r->tab[i]; } r->tab[0] = a; } else { r->tab[r->len] = mp_mul1(r->tab, r->tab, r->len, radix_base, a); } r->len++; mpb_renorm(r); } } /* XXX: add fast path for small integers */ double js_atod(const char *str, const char **pnext, int radix, int flags, JSATODTempMem *tmp_mem) { uint64_t *mptr = tmp_mem->mem; const char *p, *p_start; limb_t cur_limb, radix_base, extra_digits; int is_neg, digit_count, limb_digit_count, digits_per_limb, sep, radix1, radix_shift; int radix_bits, expn, e, max_digits, expn_offset, dot_pos, sig_pos, pos; mpb_t *tmp0; double dval; bool is_bin_exp, is_zero, expn_overflow; uint64_t m, a; tmp0 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX); assert((mptr - tmp_mem->mem) <= sizeof(JSATODTempMem) / sizeof(mptr[0])); /* optional separator between digits */ sep = (flags & JS_ATOD_ACCEPT_UNDERSCORES) ? '_' : 256; p = str; is_neg = 0; if (p[0] == '+') { p++; p_start = p; } else if (p[0] == '-') { is_neg = 1; p++; p_start = p; } else { p_start = p; } if (p[0] == '0') { if ((p[1] == 'x' || p[1] == 'X') && (radix == 0 || radix == 16)) { p += 2; radix = 16; } else if ((p[1] == 'o' || p[1] == 'O') && radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) { p += 2; radix = 8; } else if ((p[1] == 'b' || p[1] == 'B') && radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) { p += 2; radix = 2; } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & JS_ATOD_ACCEPT_LEGACY_OCTAL)) { int i; sep = 256; for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) continue; if (p[i] == '8' || p[i] == '9') goto no_prefix; p += 1; radix = 8; } else { goto no_prefix; } /* there must be a digit after the prefix */ if (to_digit((uint8_t)*p) >= radix) goto fail; no_prefix: ; } else { if (!(flags & JS_ATOD_INT_ONLY) && js__strstart(p, "Infinity", &p)) goto overflow; } if (radix == 0) radix = 10; cur_limb = 0; expn_offset = 0; digit_count = 0; limb_digit_count = 0; max_digits = atod_max_digits_table[radix - 2]; digits_per_limb = digits_per_limb_table[radix - 2]; radix_base = radix_base_table[radix - 2]; radix_shift = ctz32(radix); radix1 = radix >> radix_shift; if (radix1 == 1) { /* radix = 2^radix_bits */ radix_bits = radix_shift; } else { radix_bits = 0; } tmp0->len = 1; tmp0->tab[0] = 0; extra_digits = 0; pos = 0; dot_pos = -1; /* skip leading zeros */ for(;;) { if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) && !(flags & JS_ATOD_INT_ONLY)) { if (*p == sep) goto fail; if (dot_pos >= 0) break; dot_pos = pos; p++; } if (*p == sep && p > p_start && p[1] == '0') p++; if (*p != '0') break; p++; pos++; } sig_pos = pos; for(;;) { limb_t c; if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) && !(flags & JS_ATOD_INT_ONLY)) { if (*p == sep) goto fail; if (dot_pos >= 0) break; dot_pos = pos; p++; } if (*p == sep && p > p_start && to_digit(p[1]) < radix) p++; c = to_digit(*p); if (c >= radix) break; p++; pos++; if (digit_count < max_digits) { /* XXX: could be faster when radix_bits != 0 */ cur_limb = cur_limb * radix + c; limb_digit_count++; if (limb_digit_count == digits_per_limb) { mpb_mul1_base(tmp0, radix_base, cur_limb); cur_limb = 0; limb_digit_count = 0; } digit_count++; } else { extra_digits |= c; } } if (limb_digit_count != 0) { mpb_mul1_base(tmp0, pow_ui(radix, limb_digit_count), cur_limb); } if (digit_count == 0) { is_zero = true; expn_offset = 0; } else { is_zero = false; if (dot_pos < 0) dot_pos = pos; expn_offset = sig_pos + digit_count - dot_pos; } /* Use the extra digits for rounding if the base is a power of two. Otherwise they are just truncated. */ if (radix_bits != 0 && extra_digits != 0) { tmp0->tab[0] |= 1; } /* parse the exponent, if any */ expn = 0; expn_overflow = false; is_bin_exp = false; if (!(flags & JS_ATOD_INT_ONLY) && ((radix == 10 && (*p == 'e' || *p == 'E')) || (radix != 10 && (*p == '@' || (radix_bits >= 1 && radix_bits <= 4 && (*p == 'p' || *p == 'P'))))) && p > p_start) { bool exp_is_neg; int c; is_bin_exp = (*p == 'p' || *p == 'P'); p++; exp_is_neg = false; if (*p == '+') { p++; } else if (*p == '-') { exp_is_neg = true; p++; } c = to_digit(*p); if (c >= 10) goto fail; /* XXX: could stop before the exponent part */ expn = c; p++; for(;;) { if (*p == sep && to_digit(p[1]) < 10) p++; c = to_digit(*p); if (c >= 10) break; if (!expn_overflow) { if (unlikely(expn > ((INT32_MAX - 2 - 9) / 10))) { expn_overflow = true; } else { expn = expn * 10 + c; } } p++; } if (exp_is_neg) expn = -expn; /* if zero result, the exponent can be arbitrarily large */ if (!is_zero && expn_overflow) { if (exp_is_neg) a = 0; else a = (uint64_t)0x7ff << 52; /* infinity */ goto done; } } if (p == p_start) goto fail; if (is_zero) { a = 0; } else { int expn1; if (radix_bits != 0) { if (!is_bin_exp) expn *= radix_bits; expn -= expn_offset * radix_bits; expn1 = expn + digit_count * radix_bits; if (expn1 >= 1024 + radix_bits) goto overflow; else if (expn1 <= -1075) goto underflow; m = round_to_d(&e, tmp0, -expn, JS_RNDN); } else { expn -= expn_offset; expn1 = expn + digit_count; if (expn1 >= max_exponent[radix - 2] + 1) goto overflow; else if (expn1 <= min_exponent[radix - 2]) goto underflow; m = mul_pow_round_to_d(&e, tmp0, radix1, radix_shift, expn, JS_RNDN); } if (m == 0) { underflow: a = 0; } else if (e > 1024) { overflow: /* overflow */ a = (uint64_t)0x7ff << 52; } else if (e < -1073) { /* underflow */ /* XXX: check rounding */ a = 0; } else if (e < -1021) { /* subnormal */ a = m >> (-e - 1021); } else { a = ((uint64_t)(e + 1022) << 52) | (m & (((uint64_t)1 << 52) - 1)); } } done: a |= (uint64_t)is_neg << 63; dval = uint64_as_float64(a); done1: if (pnext) *pnext = p; dtoa_free(tmp0); return dval; fail: dval = NAN; goto done1; } qbs-src-3.3.1/src/shared/quickjs/libbf.h0000644000175100017510000004314215232633614017444 0ustar runnerrunner/* * Tiny arbitrary precision floating point library * * Copyright (c) 2017-2021 Fabrice Bellard * * 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. */ #ifndef LIBBF_H #define LIBBF_H #include #include #ifdef __cplusplus extern "C" { #endif #if INTPTR_MAX >= INT64_MAX && !defined(_WIN32) && !defined(__TINYC__) #define LIMB_LOG2_BITS 6 #else #define LIMB_LOG2_BITS 5 #endif #define LIMB_BITS (1 << LIMB_LOG2_BITS) #if LIMB_BITS == 64 #ifndef INT128_MAX __extension__ typedef __int128 int128_t; __extension__ typedef unsigned __int128 uint128_t; #endif typedef int64_t slimb_t; typedef uint64_t limb_t; typedef uint128_t dlimb_t; #define BF_RAW_EXP_MIN INT64_MIN #define BF_RAW_EXP_MAX INT64_MAX #define LIMB_DIGITS 19 #define BF_DEC_BASE UINT64_C(10000000000000000000) #else typedef int32_t slimb_t; typedef uint32_t limb_t; typedef uint64_t dlimb_t; #define BF_RAW_EXP_MIN INT32_MIN #define BF_RAW_EXP_MAX INT32_MAX #define LIMB_DIGITS 9 #define BF_DEC_BASE 1000000000U #endif /* in bits */ /* minimum number of bits for the exponent */ #define BF_EXP_BITS_MIN 3 /* maximum number of bits for the exponent */ #define BF_EXP_BITS_MAX (LIMB_BITS - 3) /* extended range for exponent, used internally */ #define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1) /* minimum possible precision */ #define BF_PREC_MIN 2 /* minimum possible precision */ #define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2) /* some operations support infinite precision */ #define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */ #if LIMB_BITS == 64 #define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197)) #else #define BF_CHKSUM_MOD 975620677U #endif #define BF_EXP_ZERO BF_RAW_EXP_MIN #define BF_EXP_INF (BF_RAW_EXP_MAX - 1) #define BF_EXP_NAN BF_RAW_EXP_MAX /* +/-zero is represented with expn = BF_EXP_ZERO and len = 0, +/-infinity is represented with expn = BF_EXP_INF and len = 0, NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored) */ typedef struct { struct bf_context_t *ctx; int sign; slimb_t expn; limb_t len; limb_t *tab; } bf_t; typedef struct { /* must be kept identical to bf_t */ struct bf_context_t *ctx; int sign; slimb_t expn; limb_t len; limb_t *tab; } bfdec_t; typedef enum { BF_RNDN, /* round to nearest, ties to even */ BF_RNDZ, /* round to zero */ BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */ BF_RNDU, /* round to +inf */ BF_RNDNA, /* round to nearest, ties away from zero */ BF_RNDA, /* round away from zero */ BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU, inexact flag is always set) */ } bf_rnd_t; /* allow subnormal numbers. Only available if the number of exponent bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */ #define BF_FLAG_SUBNORMAL (1 << 3) /* 'prec' is the precision after the radix point instead of the whole mantissa. Can only be used with bf_round() and bfdec_[add|sub|mul|div|sqrt|round](). */ #define BF_FLAG_RADPNT_PREC (1 << 4) #define BF_RND_MASK 0x7 #define BF_EXP_BITS_SHIFT 5 #define BF_EXP_BITS_MASK 0x3f /* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */ #define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT) /* contains the rounding mode and number of exponents bits */ typedef uint32_t bf_flags_t; typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size); typedef struct { bf_t val; limb_t prec; } BFConstCache; typedef struct bf_context_t { void *realloc_opaque; bf_realloc_func_t *realloc_func; BFConstCache log2_cache; BFConstCache pi_cache; struct BFNTTState *ntt_state; } bf_context_t; static inline int bf_get_exp_bits(bf_flags_t flags) { int e; e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK; if (e == BF_EXP_BITS_MASK) return BF_EXP_BITS_MAX + 1; else return BF_EXP_BITS_MAX - e; } static inline bf_flags_t bf_set_exp_bits(int n) { return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT; } /* returned status */ #define BF_ST_INVALID_OP (1 << 0) #define BF_ST_DIVIDE_ZERO (1 << 1) #define BF_ST_OVERFLOW (1 << 2) #define BF_ST_UNDERFLOW (1 << 3) #define BF_ST_INEXACT (1 << 4) /* indicate that a memory allocation error occured. NaN is returned */ #define BF_ST_MEM_ERROR (1 << 5) #define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */ static inline slimb_t bf_max(slimb_t a, slimb_t b) { if (a > b) return a; else return b; } static inline slimb_t bf_min(slimb_t a, slimb_t b) { if (a < b) return a; else return b; } void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func, void *realloc_opaque); void bf_context_end(bf_context_t *s); /* free memory allocated for the bf cache data */ void bf_clear_cache(bf_context_t *s); static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size) { return s->realloc_func(s->realloc_opaque, ptr, size); } /* 'size' must be != 0 */ static inline void *bf_malloc(bf_context_t *s, size_t size) { return bf_realloc(s, NULL, size); } static inline void bf_free(bf_context_t *s, void *ptr) { /* must test ptr otherwise equivalent to malloc(0) */ if (ptr) bf_realloc(s, ptr, 0); } void bf_init(bf_context_t *s, bf_t *r); static inline void bf_delete(bf_t *r) { bf_context_t *s = r->ctx; /* we accept to delete a zeroed bf_t structure */ if (s && r->tab) { bf_realloc(s, r->tab, 0); } } static inline void bf_neg(bf_t *r) { r->sign ^= 1; } static inline int bf_is_finite(const bf_t *a) { return (a->expn < BF_EXP_INF); } static inline int bf_is_nan(const bf_t *a) { return (a->expn == BF_EXP_NAN); } static inline int bf_is_zero(const bf_t *a) { return (a->expn == BF_EXP_ZERO); } static inline void bf_memcpy(bf_t *r, const bf_t *a) { *r = *a; } int bf_set_ui(bf_t *r, uint64_t a); int bf_set_si(bf_t *r, int64_t a); void bf_set_nan(bf_t *r); void bf_set_zero(bf_t *r, int is_neg); void bf_set_inf(bf_t *r, int is_neg); int bf_set(bf_t *r, const bf_t *a); void bf_move(bf_t *r, bf_t *a); int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode); int bf_set_float64(bf_t *a, double d); int bf_cmpu(const bf_t *a, const bf_t *b); int bf_cmp_full(const bf_t *a, const bf_t *b); int bf_cmp(const bf_t *a, const bf_t *b); static inline int bf_cmp_eq(const bf_t *a, const bf_t *b) { return bf_cmp(a, b) == 0; } static inline int bf_cmp_le(const bf_t *a, const bf_t *b) { return bf_cmp(a, b) <= 0; } static inline int bf_cmp_lt(const bf_t *a, const bf_t *b) { return bf_cmp(a, b) < 0; } int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags); int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags); int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); #define BF_DIVREM_EUCLIDIAN BF_RNDF int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags, int rnd_mode); int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags, int rnd_mode); int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags, int rnd_mode); /* round to integer with infinite precision */ int bf_rint(bf_t *r, int rnd_mode); int bf_round(bf_t *r, limb_t prec, bf_flags_t flags); int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a); int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); slimb_t bf_get_exp_min(const bf_t *a); int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b); int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b); int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b); /* additional flags for bf_atof */ /* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */ #define BF_ATOF_NO_HEX (1 << 16) /* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */ #define BF_ATOF_BIN_OCT (1 << 17) /* Do not parse NaN or Inf */ #define BF_ATOF_NO_NAN_INF (1 << 18) /* return the exponent separately */ #define BF_ATOF_EXPONENT (1 << 19) int bf_atof(bf_t *a, const char *str, const char **pnext, int radix, limb_t prec, bf_flags_t flags); /* this version accepts prec = BF_PREC_INF and returns the radix exponent */ int bf_atof2(bf_t *r, slimb_t *pexponent, const char *str, const char **pnext, int radix, limb_t prec, bf_flags_t flags); int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, slimb_t expn, limb_t prec, bf_flags_t flags); /* Conversion of floating point number to string. Return a null terminated string or NULL if memory error. *plen contains its length if plen != NULL. The exponent letter is "e" for base 10, "p" for bases 2, 8, 16 with a binary exponent and "@" for the other bases. */ #define BF_FTOA_FORMAT_MASK (3 << 16) /* fixed format: prec significant digits rounded with (flags & BF_RND_MASK). Exponential notation is used if too many zeros are needed.*/ #define BF_FTOA_FORMAT_FIXED (0 << 16) /* fractional format: prec digits after the decimal point rounded with (flags & BF_RND_MASK) */ #define BF_FTOA_FORMAT_FRAC (1 << 16) /* free format: For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum number of digits to represent 'a'. The precision and the rounding mode are ignored. For the non binary radices with bf_ftoa(): use as many digits as necessary so that bf_atof() return the same number when using precision 'prec', rounding to nearest and the subnormal configuration of 'flags'. The result is meaningful only if 'a' is already rounded to 'prec' bits. If the subnormal flag is set, the exponent in 'flags' must also be set to the desired exponent range. */ #define BF_FTOA_FORMAT_FREE (2 << 16) /* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits (takes more computation time). Identical to BF_FTOA_FORMAT_FREE for binary radices with bf_ftoa() and for bfdec_ftoa(). */ #define BF_FTOA_FORMAT_FREE_MIN (3 << 16) /* force exponential notation for fixed or free format */ #define BF_FTOA_FORCE_EXP (1 << 20) /* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for base 2 if non zero value */ #define BF_FTOA_ADD_PREFIX (1 << 21) /* return "Infinity" instead of "Inf" and add a "+" for positive exponents */ #define BF_FTOA_JS_QUIRKS (1 << 22) char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec, bf_flags_t flags); /* modulo 2^n instead of saturation. NaN and infinity return 0 */ #define BF_GET_INT_MOD (1 << 0) int bf_get_int32(int *pres, const bf_t *a, int flags); int bf_get_int64(int64_t *pres, const bf_t *a, int flags); int bf_get_uint64(uint64_t *pres, const bf_t *a); /* the following functions are exported for testing only. */ void mp_print_str(const char *str, const limb_t *tab, limb_t n); void bf_print_str(const char *str, const bf_t *a); int bf_resize(bf_t *r, limb_t len); int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len); int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags); int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k); slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, int is_ceil1); int mp_mul(bf_context_t *s, limb_t *result, const limb_t *op1, limb_t op1_size, const limb_t *op2, limb_t op2_size); limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, limb_t n, limb_t carry); limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n); int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n); int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n); limb_t bf_isqrt(limb_t a); /* transcendental functions */ int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags); int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags); int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); #define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags); int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x, limb_t prec, bf_flags_t flags); int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); /* decimal floating point */ static inline void bfdec_init(bf_context_t *s, bfdec_t *r) { bf_init(s, (bf_t *)r); } static inline void bfdec_delete(bfdec_t *r) { bf_delete((bf_t *)r); } static inline void bfdec_neg(bfdec_t *r) { r->sign ^= 1; } static inline int bfdec_is_finite(const bfdec_t *a) { return (a->expn < BF_EXP_INF); } static inline int bfdec_is_nan(const bfdec_t *a) { return (a->expn == BF_EXP_NAN); } static inline int bfdec_is_zero(const bfdec_t *a) { return (a->expn == BF_EXP_ZERO); } static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a) { bf_memcpy((bf_t *)r, (const bf_t *)a); } int bfdec_set_ui(bfdec_t *r, uint64_t a); int bfdec_set_si(bfdec_t *r, int64_t a); static inline void bfdec_set_nan(bfdec_t *r) { bf_set_nan((bf_t *)r); } static inline void bfdec_set_zero(bfdec_t *r, int is_neg) { bf_set_zero((bf_t *)r, is_neg); } static inline void bfdec_set_inf(bfdec_t *r, int is_neg) { bf_set_inf((bf_t *)r, is_neg); } static inline int bfdec_set(bfdec_t *r, const bfdec_t *a) { return bf_set((bf_t *)r, (bf_t *)a); } static inline void bfdec_move(bfdec_t *r, bfdec_t *a) { bf_move((bf_t *)r, (bf_t *)a); } static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b) { return bf_cmpu((const bf_t *)a, (const bf_t *)b); } static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b) { return bf_cmp_full((const bf_t *)a, (const bf_t *)b); } static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b) { return bf_cmp((const bf_t *)a, (const bf_t *)b); } static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b) { return bfdec_cmp(a, b) == 0; } static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b) { return bfdec_cmp(a, b) <= 0; } static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b) { return bfdec_cmp(a, b) < 0; } int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags); int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags); int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags); int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags); int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags, int rnd_mode); int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags, int rnd_mode); int bfdec_rint(bfdec_t *r, int rnd_mode); int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags); int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags); int bfdec_get_int32(int *pres, const bfdec_t *a); int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b); char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags); int bfdec_atof(bfdec_t *r, const char *str, const char **pnext, limb_t prec, bf_flags_t flags); /* the following functions are exported for testing only. */ extern const limb_t mp_pow_dec[LIMB_DIGITS + 1]; void bfdec_print_str(const char *str, const bfdec_t *a); static inline int bfdec_resize(bfdec_t *r, limb_t len) { return bf_resize((bf_t *)r, len); } int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags); #ifdef __cplusplus } /* extern "C" { */ #endif #endif /* LIBBF_H */ qbs-src-3.3.1/src/shared/quickjs/sync.sh0000755000175100017510000000100115232633614017514 0ustar runnerrunner#!/bin/bash SOURCE_DIR=$1 if [[ -z "${SOURCE_DIR}" ]]; then echo "Usage: ./sync path/to/quickjs/" exit 1 fi; TARGET_DIR=$(dirname "$0") FILES=" builtin-array-fromasync.h cutils.c cutils.h dtoa.c dtoa.h libregexp-opcode.h libregexp.c libregexp.h libunicode-table.h libunicode.c libunicode.h LICENSE list.h quickjs-atom.h quickjs-c-atomics.h quickjs-opcode.h quickjs.c quickjs.h " for FILE in $FILES do echo "$SOURCE_DIR/$FILE -> $TARGET_DIR/$FILE" cp "$SOURCE_DIR/$FILE" "$TARGET_DIR/$FILE" done qbs-src-3.3.1/src/shared/quickjs/quickjs.c0000644000175100017510000721074315232633614020044 0ustar runnerrunner/* * QuickJS Javascript Engine * * Copyright (c) 2017-2025 Fabrice Bellard * Copyright (c) 2017-2025 Charlie Gordon * Copyright (c) 2023-2025 Ben Noordhuis * Copyright (c) 2023-2025 Saúl Ibarra Corretgé * * 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. */ #include #include #include #include #include #include #if !defined(_MSC_VER) #include #if defined(_WIN32) #include #endif #endif #if defined(_WIN32) #include #endif #include #include #include #include "cutils.h" #include "list.h" #include "quickjs.h" #include "libregexp.h" #include "dtoa.h" #if defined(EMSCRIPTEN) || defined(_MSC_VER) #define DIRECT_DISPATCH 0 #else #define DIRECT_DISPATCH 1 #endif #if defined(__APPLE__) #define MALLOC_OVERHEAD 0 #else #define MALLOC_OVERHEAD 8 #endif #if defined(__NEWLIB__) #define NO_TM_GMTOFF #endif // atomic_store etc. are completely busted in recent versions of tcc; // somehow the compiler forgets to load |ptr| into %rdi when calling // the __atomic_*() helpers in its lib/stdatomic.c and lib/atomic.S #if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !__STDC_NO_ATOMICS__ #include "quickjs-c-atomics.h" #define CONFIG_ATOMICS #endif #ifndef __GNUC__ #define __extension__ #endif #ifndef NDEBUG #define ENABLE_DUMPS #endif //#define FORCE_GC_AT_MALLOC /* test the GC by forcing it before each object allocation */ #define check_dump_flag(rt, flag) ((rt->dump_flags & (flag +0)) == (flag +0)) #define STRINGIFY_(x) #x #define STRINGIFY(x) STRINGIFY_(x) #define QJS_VERSION_STRING \ STRINGIFY(QJS_VERSION_MAJOR) "." STRINGIFY(QJS_VERSION_MINOR) "." STRINGIFY(QJS_VERSION_PATCH) QJS_VERSION_SUFFIX const char* JS_GetVersion(void) { return QJS_VERSION_STRING; } #undef STRINFIGY_ #undef STRINGIFY static inline JSValueConst *vc(JSValue *vals) { return (JSValueConst *)vals; } static inline JSValue unsafe_unconst(JSValueConst v) { #ifdef JS_CHECK_JSVALUE return (JSValue)v; #else return v; #endif } static inline JSValueConst safe_const(JSValue v) { #ifdef JS_CHECK_JSVALUE return (JSValueConst)v; #else return v; #endif } enum { /* classid tag */ /* union usage | properties */ JS_CLASS_OBJECT = 1, /* must be first */ JS_CLASS_ARRAY, /* u.array | length */ JS_CLASS_ERROR, JS_CLASS_NUMBER, /* u.object_data */ JS_CLASS_STRING, /* u.object_data */ JS_CLASS_BOOLEAN, /* u.object_data */ JS_CLASS_SYMBOL, /* u.object_data */ JS_CLASS_ARGUMENTS, /* u.array | length */ JS_CLASS_MAPPED_ARGUMENTS, /* | length */ JS_CLASS_DATE, /* u.object_data */ JS_CLASS_MODULE_NS, JS_CLASS_C_FUNCTION, /* u.cfunc */ JS_CLASS_BYTECODE_FUNCTION, /* u.func */ JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ JS_CLASS_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ JS_CLASS_REGEXP, /* u.regexp */ JS_CLASS_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_SHARED_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_UINT8C_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_DATAVIEW, /* u.typed_array */ JS_CLASS_BIG_INT, /* u.object_data */ JS_CLASS_MAP, /* u.map_state */ JS_CLASS_SET, /* u.map_state */ JS_CLASS_WEAKMAP, /* u.map_state */ JS_CLASS_WEAKSET, /* u.map_state */ JS_CLASS_ITERATOR, JS_CLASS_ITERATOR_CONCAT, /* u.iterator_concat_data */ JS_CLASS_ITERATOR_HELPER, /* u.iterator_helper_data */ JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */ JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ JS_CLASS_GENERATOR, /* u.generator_data */ JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_PROMISE, /* u.promise_data */ JS_CLASS_PROMISE_RESOLVE_FUNCTION, /* u.promise_function_data */ JS_CLASS_PROMISE_REJECT_FUNCTION, /* u.promise_function_data */ JS_CLASS_ASYNC_FUNCTION, /* u.func */ JS_CLASS_ASYNC_FUNCTION_RESOLVE, /* u.async_function_data */ JS_CLASS_ASYNC_FUNCTION_REJECT, /* u.async_function_data */ JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ JS_CLASS_WEAK_REF, JS_CLASS_FINALIZATION_REGISTRY, JS_CLASS_DOM_EXCEPTION, JS_CLASS_CALL_SITE, JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; /* number of typed array types */ #define JS_TYPED_ARRAY_COUNT (JS_CLASS_FLOAT64_ARRAY - JS_CLASS_UINT8C_ARRAY + 1) static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT]; #define typed_array_size_log2(classid) (typed_array_size_log2[(classid)- JS_CLASS_UINT8C_ARRAY]) typedef enum JSErrorEnum { JS_EVAL_ERROR, JS_RANGE_ERROR, JS_REFERENCE_ERROR, JS_SYNTAX_ERROR, JS_TYPE_ERROR, JS_URI_ERROR, JS_INTERNAL_ERROR, JS_AGGREGATE_ERROR, JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ JS_PLAIN_ERROR = JS_NATIVE_ERROR_COUNT } JSErrorEnum; #define JS_MAX_LOCAL_VARS 65535 #define JS_STACK_SIZE_MAX 65534 #define JS_STRING_LEN_MAX ((1 << 30) - 1) // 1,024 bytes is about the cutoff point where it starts getting // more profitable to ref slice than to copy #define JS_STRING_SLICE_LEN_MAX 1024 // in bytes #define __exception __attribute__((warn_unused_result)) typedef struct JSShape JSShape; typedef struct JSString JSString; typedef struct JSString JSAtomStruct; #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) typedef enum { JS_GC_PHASE_NONE, JS_GC_PHASE_DECREF, JS_GC_PHASE_REMOVE_CYCLES, } JSGCPhaseEnum; typedef struct JSMallocState { size_t malloc_count; size_t malloc_size; size_t malloc_limit; void *opaque; /* user opaque */ } JSMallocState; typedef struct JSRuntimeFinalizerState { struct JSRuntimeFinalizerState *next; JSRuntimeFinalizer *finalizer; void *arg; } JSRuntimeFinalizerState; typedef struct JSValueLink { struct JSValueLink *next; JSValueConst value; } JSValueLink; struct JSRuntime { JSMallocFunctions mf; JSMallocState malloc_state; const char *rt_info; int atom_hash_size; /* power of two */ int atom_count; int atom_size; int atom_count_resize; /* resize hash table at this count */ uint32_t *atom_hash; JSAtomStruct **atom_array; int atom_free_index; /* 0 = none */ JSClassID js_class_id_alloc; /* counter for user defined classes */ int class_count; /* size of class_array */ JSClass *class_array; struct list_head context_list; /* list of JSContext.link */ /* list of JSGCObjectHeader.link. List of allocated GC objects (used by the garbage collector) */ struct list_head gc_obj_list; /* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */ struct list_head gc_zero_ref_count_list; struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS struct list_head string_list; /* list of JSString.link */ #endif /* stack limitation */ uintptr_t stack_size; /* in bytes, 0 if no limit */ uintptr_t stack_top; uintptr_t stack_limit; /* lower stack limit */ JSValue current_exception; /* true if inside an out of memory error, to avoid recursing */ bool in_out_of_memory; /* true if inside build_backtrace, to avoid recursing */ bool in_build_stack_trace; /* true if inside JS_FreeRuntime */ bool in_free; struct JSStackFrame *current_stack_frame; JSInterruptHandler *interrupt_handler; void *interrupt_opaque; JSPromiseHook *promise_hook; void *promise_hook_opaque; // for smuggling the parent promise from js_promise_then // to js_promise_constructor JSValueLink *parent_promise; JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; JSModuleLoaderFunc *module_loader_func; void *module_loader_opaque; /* timestamp for internal use in module evaluation */ int64_t module_async_evaluation_next_timestamp; /* used to allocate, free and clone SharedArrayBuffers */ JSSharedArrayBufferFunctions sab_funcs; bool can_block; /* true if Atomics.wait can block */ uint32_t dump_flags : 24; /* Shape hash table */ int shape_hash_bits; int shape_hash_size; int shape_hash_count; /* number of hashed shapes */ JSShape **shape_hash; void *user_opaque; void *libc_opaque; JSRuntimeFinalizerState *finalizers; }; struct JSClass { uint32_t class_id; /* 0 means free entry */ JSAtom class_name; JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; JSClassCall *call; /* pointers for exotic behavior, can be NULL if none are present */ const JSClassExoticMethods *exotic; }; typedef struct JSStackFrame { struct JSStackFrame *prev_frame; /* NULL if first stack frame */ JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue *arg_buf; /* arguments */ JSValue *var_buf; /* variables */ struct list_head var_ref_list; /* list of JSVarRef.link */ uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ uint32_t arg_count : 31; uint32_t is_strict_mode : 1; /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; } JSStackFrame; typedef enum { JS_GC_OBJ_TYPE_JS_OBJECT, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE, JS_GC_OBJ_TYPE_SHAPE, JS_GC_OBJ_TYPE_VAR_REF, JS_GC_OBJ_TYPE_ASYNC_FUNCTION, JS_GC_OBJ_TYPE_JS_CONTEXT, } JSGCObjectTypeEnum; /* header for GC objects. GC objects are C data structures with a reference count that can reference other GC objects. JS Objects are a particular type of GC object. */ struct JSGCObjectHeader { int ref_count; /* must come first, 32-bit */ JSGCObjectTypeEnum gc_obj_type : 4; uint8_t mark : 4; /* used by the GC */ uint8_t dummy1; /* not used by the GC */ uint16_t dummy2; /* not used by the GC */ struct list_head link; }; typedef struct JSVarRef { union { JSGCObjectHeader header; /* must come first */ struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ uint8_t is_detached; }; }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ JSValue value; /* used when the variable is no longer on the stack */ } JSVarRef; typedef struct JSRefCountHeader { int ref_count; } JSRefCountHeader; /* bigint */ typedef int32_t js_slimb_t; typedef uint32_t js_limb_t; typedef int64_t js_sdlimb_t; typedef uint64_t js_dlimb_t; #define JS_LIMB_DIGITS 9 /* Must match the size of short_big_int in JSValueUnion */ #define JS_LIMB_BITS 32 #define JS_SHORT_BIG_INT_BITS JS_LIMB_BITS #define JS_BIGINT_MAX_SIZE ((1024 * 1024) / JS_LIMB_BITS) /* in limbs */ #define JS_SHORT_BIG_INT_MIN INT32_MIN #define JS_SHORT_BIG_INT_MAX INT32_MAX typedef struct JSBigInt { JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len; /* number of limbs, >= 1 */ js_limb_t tab[]; /* two's complement representation, always normalized so that 'len' is the minimum possible length >= 1 */ } JSBigInt; /* this bigint structure can hold a 64 bit integer */ typedef struct { js_limb_t big_int_buf[sizeof(JSBigInt) / sizeof(js_limb_t)]; /* for JSBigInt */ /* must come just after */ js_limb_t tab[(64 + JS_LIMB_BITS - 1) / JS_LIMB_BITS]; } JSBigIntBuf; typedef enum { JS_AUTOINIT_ID_PROTOTYPE, JS_AUTOINIT_ID_MODULE_NS, JS_AUTOINIT_ID_PROP, JS_AUTOINIT_ID_BYTECODE, } JSAutoInitIDEnum; enum { JS_BUILTIN_ARRAY_FROMASYNC = 1, }; /* must be large enough to have a negligible runtime cost and small enough to call the interrupt callback often. */ #define JS_INTERRUPT_COUNTER_INIT 10000 struct JSContext { JSGCObjectHeader header; /* must come first */ JSRuntime *rt; struct list_head link; uint16_t binary_object_count; int binary_object_size; JSShape *array_shape; /* initial shape for Array objects */ JSValue *class_proto; JSValue function_proto; JSValue function_ctor; JSValue array_ctor; JSValue regexp_ctor; JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; JSValue error_ctor; JSValue error_back_trace; JSValue error_prepare_stack; JSValue error_stack_trace_limit; JSValue iterator_ctor; JSValue iterator_ctor_getset; JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; JSValue throw_type_error; JSValue eval_obj; JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ double time_origin; uint64_t random_state; /* when the counter reaches zero, JSRutime.interrupt_handler is called */ int interrupt_counter; struct list_head loaded_modules; /* list of JSModuleDef.link */ /* if NULL, RegExp compilation is not supported */ JSValue (*compile_regexp)(JSContext *ctx, JSValueConst pattern, JSValueConst flags); /* if NULL, eval is not supported */ JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int line, int flags, int scope_idx); void *user_opaque; ScopeLookup *scopeLookup; FoundUndefinedHandler *handleUndefined; FunctionEnteredHandler *handleFunctionEntered; FunctionExitedHandler *handleFunctionExited; }; typedef union JSFloat64Union { double d; uint64_t u64; uint32_t u32[2]; } JSFloat64Union; typedef enum { JS_WEAK_REF_KIND_MAP, JS_WEAK_REF_KIND_WEAK_REF, JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY, } JSWeakRefKindEnum; typedef struct JSWeakRefRecord { JSWeakRefKindEnum kind; struct JSWeakRefRecord *next_weak_ref; union { struct JSMapRecord *map_record; struct JSWeakRefData *weak_ref_data; struct JSFinRecEntry *fin_rec_entry; } u; } JSWeakRefRecord; typedef struct JSMapRecord { int ref_count; /* used during enumeration to avoid freeing the record */ bool empty; /* true if the record is deleted */ struct JSMapState *map; struct list_head link; struct list_head hash_link; JSValue key; JSValue value; } JSMapRecord; typedef struct JSMapState { bool is_weak; /* true if WeakSet/WeakMap */ struct list_head records; /* list of JSMapRecord.link */ uint32_t record_count; struct list_head *hash_table; uint32_t hash_size; /* must be a power of two */ uint32_t record_count_threshold; /* count at which a hash table resize is needed */ } JSMapState; enum { JS_TO_STRING_IS_PROPERTY_KEY = 1 << 0, JS_TO_STRING_NO_SIDE_EFFECTS = 1 << 1, }; enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, JS_ATOM_TYPE_SYMBOL, JS_ATOM_TYPE_PRIVATE, }; enum { JS_ATOM_HASH_SYMBOL, JS_ATOM_HASH_PRIVATE, }; typedef enum { JS_ATOM_KIND_STRING, JS_ATOM_KIND_SYMBOL, JS_ATOM_KIND_PRIVATE, } JSAtomKindEnum; typedef enum { JS_STRING_KIND_NORMAL, JS_STRING_KIND_SLICE, } JSStringKind; #define JS_ATOM_HASH_MASK ((1 << 29) - 1) struct JSString { JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len : 31; uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 XXX: could change encoding to have one more bit in hash */ uint32_t hash : 29; uint8_t kind : 1; uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ JSWeakRefRecord *first_weak_ref; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS struct list_head link; /* string list */ #endif }; typedef struct JSStringSlice { JSString *parent; uint32_t start; // in bytes, not characters } JSStringSlice; static inline void *strv(JSString *p) { JSStringSlice *slice; switch (p->kind) { case JS_STRING_KIND_NORMAL: return (void *)&p[1]; case JS_STRING_KIND_SLICE: slice = (void *)&p[1]; return (char *)&slice->parent[1] + slice->start; } abort(); return NULL; } static inline uint8_t *str8(JSString *p) { return strv(p); } static inline uint16_t *str16(JSString *p) { return strv(p); } typedef struct JSClosureVar { uint8_t is_local : 1; uint8_t is_arg : 1; uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t var_kind : 4; /* see JSVarKindEnum */ /* 8 bits available */ uint16_t var_idx; /* is_local = true: index to a normal variable of the parent function. otherwise: index to a closure variable of the parent function */ JSAtom var_name; } JSClosureVar; #define ARG_SCOPE_INDEX 1 #define ARG_SCOPE_END (-2) typedef struct JSVarScope { int parent; /* index into fd->scopes of the enclosing scope */ int first; /* index into fd->vars of the last variable in this scope */ } JSVarScope; typedef enum { /* XXX: add more variable kinds here instead of using bit fields */ JS_VAR_NORMAL, JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */ JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator function declaration */ JS_VAR_CATCH, JS_VAR_FUNCTION_NAME, /* function expression name */ JS_VAR_PRIVATE_FIELD, JS_VAR_PRIVATE_METHOD, JS_VAR_PRIVATE_GETTER, JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */ JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */ } JSVarKindEnum; /* XXX: could use a different structure in bytecode functions to save memory */ typedef struct JSVarDef { JSAtom var_name; /* index into fd->scopes of this variable lexical scope */ int scope_level; /* during compilation: - if scope_level = 0: scope in which the variable is defined - if scope_level != 0: index into fd->vars of the next variable in the same or enclosing lexical scope in a bytecode function: index into fd->vars of the next variable in the same or enclosing lexical scope */ int scope_next; uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t is_captured : 1; uint8_t is_static_private : 1; /* only used during private class field parsing */ uint8_t var_kind : 4; /* see JSVarKindEnum */ /* only used during compilation: function pool index for lexical variables with var_kind = JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of the definition of the 'var' variables (they have scope_level = 0) */ int func_pool_idx : 24; /* only used during compilation : index in the constant pool for hoisted function definition */ } JSVarDef; /* for the encoding of the pc2line table */ #define PC2LINE_BASE (-1) #define PC2LINE_RANGE 5 #define PC2LINE_OP_FIRST 1 #define PC2LINE_DIFF_PC_MAX ((255 - PC2LINE_OP_FIRST) / PC2LINE_RANGE) typedef enum JSFunctionKindEnum { JS_FUNC_NORMAL = 0, JS_FUNC_GENERATOR = (1 << 0), JS_FUNC_ASYNC = (1 << 1), JS_FUNC_ASYNC_GENERATOR = (JS_FUNC_GENERATOR | JS_FUNC_ASYNC), } JSFunctionKindEnum; typedef struct JSFunctionBytecode { JSGCObjectHeader header; /* must come first */ uint8_t is_strict_mode : 1; uint8_t has_prototype : 1; /* true if a prototype field is necessary */ uint8_t has_simple_parameter_list : 1; uint8_t is_derived_class_constructor : 1; /* true if home_object needs to be initialized */ uint8_t need_home_object : 1; uint8_t func_kind : 2; uint8_t new_target_allowed : 1; uint8_t super_call_allowed : 1; uint8_t super_allowed : 1; uint8_t arguments_allowed : 1; uint8_t backtrace_barrier : 1; /* stop backtrace on this function */ /* XXX: 5 bits available */ uint8_t *byte_code_buf; /* (self pointer) */ int byte_code_len; JSAtom func_name; JSVarDef *vardefs; /* arguments + local variables (arg_count + var_count) (self pointer) */ JSClosureVar *closure_var; /* list of variables in the closure (self pointer) */ uint16_t arg_count; uint16_t var_count; uint16_t defined_arg_count; /* for length function property */ uint16_t stack_size; /* maximum stack size */ JSContext *realm; /* function realm */ JSValue *cpool; /* constant pool (self pointer) */ int cpool_count; int closure_var_count; JSAtom filename; int line_num; int col_num; int source_len; int pc2line_len; uint8_t *pc2line_buf; char *source; } JSFunctionBytecode; typedef struct JSBoundFunction { JSValue func_obj; JSValue this_val; int argc; JSValue argv[]; } JSBoundFunction; typedef enum JSIteratorKindEnum { JS_ITERATOR_KIND_KEY, JS_ITERATOR_KIND_VALUE, JS_ITERATOR_KIND_KEY_AND_VALUE, } JSIteratorKindEnum; typedef enum JSIteratorHelperKindEnum { JS_ITERATOR_HELPER_KIND_DROP, JS_ITERATOR_HELPER_KIND_EVERY, JS_ITERATOR_HELPER_KIND_FILTER, JS_ITERATOR_HELPER_KIND_FIND, JS_ITERATOR_HELPER_KIND_FLAT_MAP, JS_ITERATOR_HELPER_KIND_FOR_EACH, JS_ITERATOR_HELPER_KIND_MAP, JS_ITERATOR_HELPER_KIND_SOME, JS_ITERATOR_HELPER_KIND_TAKE, } JSIteratorHelperKindEnum; typedef struct JSForInIterator { JSValue obj; bool is_array; uint32_t array_length; uint32_t idx; } JSForInIterator; typedef struct JSRegExp { JSString *pattern; JSString *bytecode; /* also contains the flags */ } JSRegExp; typedef struct JSProxyData { JSValue target; JSValue handler; uint8_t is_func; uint8_t is_revoked; } JSProxyData; typedef struct JSArrayBuffer { int byte_length; /* 0 if detached */ int max_byte_length; /* -1 if not resizable; >= byte_length otherwise */ uint8_t detached; uint8_t shared; /* if shared, the array buffer cannot be detached */ uint8_t *data; /* NULL if detached */ struct list_head array_list; void *opaque; JSFreeArrayBufferDataFunc *free_func; } JSArrayBuffer; typedef struct JSTypedArray { struct list_head link; /* link to arraybuffer */ JSObject *obj; /* back pointer to the TypedArray/DataView object */ JSObject *buffer; /* based array buffer */ uint32_t offset; /* byte offset in the array buffer */ uint32_t length; /* byte length in the array buffer */ bool track_rab; /* auto-track length of backing array buffer */ } JSTypedArray; typedef struct JSAsyncFunctionState { JSValue this_val; /* 'this' generator argument */ int argc; /* number of function arguments */ bool throw_flag; /* used to throw an exception in JS_CallInternal() */ JSStackFrame frame; } JSAsyncFunctionState; /* XXX: could use an object instead to avoid the JS_TAG_ASYNC_FUNCTION tag for the GC */ typedef struct JSAsyncFunctionData { JSGCObjectHeader header; /* must come first */ JSValue resolving_funcs[2]; bool is_active; /* true if the async function state is valid */ JSAsyncFunctionState func_state; } JSAsyncFunctionData; typedef struct JSReqModuleEntry { JSAtom module_name; JSModuleDef *module; /* used using resolution */ } JSReqModuleEntry; typedef enum JSExportTypeEnum { JS_EXPORT_TYPE_LOCAL, JS_EXPORT_TYPE_INDIRECT, } JSExportTypeEnum; typedef struct JSExportEntry { union { struct { int var_idx; /* closure variable index */ JSVarRef *var_ref; /* if != NULL, reference to the variable */ } local; /* for local export */ int req_module_idx; /* module for indirect export */ } u; JSExportTypeEnum export_type; JSAtom local_name; /* '*' if export ns from. not used for local export after compilation */ JSAtom export_name; /* exported variable name */ } JSExportEntry; typedef struct JSStarExportEntry { int req_module_idx; /* in req_module_entries */ } JSStarExportEntry; typedef struct JSImportEntry { int var_idx; /* closure variable index */ JSAtom import_name; int req_module_idx; /* in req_module_entries */ } JSImportEntry; typedef enum { JS_MODULE_STATUS_UNLINKED, JS_MODULE_STATUS_LINKING, JS_MODULE_STATUS_LINKED, JS_MODULE_STATUS_EVALUATING, JS_MODULE_STATUS_EVALUATING_ASYNC, JS_MODULE_STATUS_EVALUATED, } JSModuleStatus; struct JSModuleDef { JSRefCountHeader header; /* must come first, 32-bit */ JSAtom module_name; struct list_head link; JSReqModuleEntry *req_module_entries; int req_module_entries_count; int req_module_entries_size; JSExportEntry *export_entries; int export_entries_count; int export_entries_size; JSStarExportEntry *star_export_entries; int star_export_entries_count; int star_export_entries_size; JSImportEntry *import_entries; int import_entries_count; int import_entries_size; JSValue module_ns; JSValue func_obj; /* only used for JS modules */ JSModuleInitFunc *init_func; /* only used for C modules */ bool has_tla; /* true if func_obj contains await */ bool resolved; bool func_created; JSModuleStatus status : 8; /* temp use during js_module_link() & js_module_evaluate() */ int dfs_index, dfs_ancestor_index; JSModuleDef *stack_prev; /* temp use during js_module_evaluate() */ JSModuleDef **async_parent_modules; int async_parent_modules_count; int async_parent_modules_size; int pending_async_dependencies; bool async_evaluation; int64_t async_evaluation_timestamp; JSModuleDef *cycle_root; JSValue promise; /* corresponds to spec field: capability */ JSValue resolving_funcs[2]; /* corresponds to spec field: capability */ /* true if evaluation yielded an exception. It is saved in eval_exception */ bool eval_has_exception; JSValue eval_exception; JSValue meta_obj; /* for import.meta */ }; typedef struct JSJobEntry { struct list_head link; JSContext *ctx; JSJobFunc *job_func; int argc; JSValue argv[]; } JSJobEntry; typedef struct JSProperty { union { JSValue value; /* JS_PROP_NORMAL */ struct { /* JS_PROP_GETSET */ JSObject *getter; /* NULL if undefined */ JSObject *setter; /* NULL if undefined */ } getset; JSVarRef *var_ref; /* JS_PROP_VARREF */ struct { /* JS_PROP_AUTOINIT */ /* in order to use only 2 pointers, we compress the realm and the init function pointer */ uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x) in the 2 low bits */ void *opaque; } init; } u; } JSProperty; #define JS_PROP_INITIAL_SIZE 2 #define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */ #define JS_ARRAY_INITIAL_SIZE 2 typedef struct JSShapeProperty { uint32_t hash_next : 26; /* 0 if last in list */ uint32_t flags : 6; /* JS_PROP_XXX */ JSAtom atom; /* JS_ATOM_NULL = free property entry */ } JSShapeProperty; struct JSShape { /* hash table of size hash_mask + 1 before the start of the structure (see prop_hash_end()). */ JSGCObjectHeader header; /* true if the shape is inserted in the shape hash table. If not, JSShape.hash is not valid */ uint8_t is_hashed; /* If true, the shape may have small array index properties 'n' with 0 <= n <= 2^31-1. If false, the shape is guaranteed not to have small array index properties */ uint8_t has_small_array_index; uint32_t hash; /* current hash value */ uint32_t prop_hash_mask; int prop_size; /* allocated properties */ int prop_count; /* include deleted properties */ int deleted_prop_count; JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ JSObject *proto; JSShapeProperty prop[]; /* prop_size elements */ }; struct JSObject { union { JSGCObjectHeader header; struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ uint8_t extensible : 1; uint8_t free_mark : 1; /* only used when freeing objects with cycles */ uint8_t is_exotic : 1; /* true if object has exotic property handlers */ uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */ uint8_t is_constructor : 1; /* true if object is a constructor function */ uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */ uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */ uint16_t class_id; /* see JS_CLASS_x */ }; }; /* byte offsets: 16/24 */ JSShape *shape; /* prototype and property names + flag */ JSProperty *prop; /* array of properties */ /* byte offsets: 24/40 */ JSWeakRefRecord *first_weak_ref; /* byte offsets: 28/48 */ union { void *opaque; struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */ struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */ struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */ struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */ struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */ struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */ struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */ struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */ struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */ struct JSIteratorConcatData *iterator_concat_data; /* JS_CLASS_ITERATOR_CONCAT */ struct JSIteratorHelperData *iterator_helper_data; /* JS_CLASS_ITERATOR_HELPER */ struct JSIteratorWrapData *iterator_wrap_data; /* JS_CLASS_ITERATOR_WRAP */ struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */ struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */ struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */ struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */ struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */ struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */ struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */ /* also used by JS_CLASS_GENERATOR_FUNCTION, JS_CLASS_ASYNC_FUNCTION and JS_CLASS_ASYNC_GENERATOR_FUNCTION */ struct JSFunctionBytecode *function_bytecode; JSVarRef **var_refs; JSObject *home_object; /* for 'super' access */ } func; struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */ JSContext *realm; JSCFunctionType c_function; uint8_t length; uint8_t cproto; int16_t magic; } cfunc; /* array part for fast arrays and typed arrays */ struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ union { uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ } u1; union { JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ int16_t *int16_ptr; /* JS_CLASS_INT16_ARRAY */ uint16_t *uint16_ptr; /* JS_CLASS_UINT16_ARRAY */ int32_t *int32_ptr; /* JS_CLASS_INT32_ARRAY */ uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */ int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */ uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */ uint16_t *fp16_ptr; /* JS_CLASS_FLOAT16_ARRAY */ float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */ double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */ } u; uint32_t count; /* <= 2^31-1. 0 for a detached typed array */ } array; /* 12/20 bytes */ JSRegExp regexp; /* JS_CLASS_REGEXP: 8/16 bytes */ JSValue object_data; /* for JS_SetObjectData(): 8/16/16 bytes */ } u; /* byte sizes: 40/48/72 */ }; typedef struct JSCallSiteData { JSValue filename; JSValue func; JSValue func_name; bool native; int line_num; int col_num; } JSCallSiteData; enum { __JS_ATOM_NULL = JS_ATOM_NULL, #define DEF(name, str) JS_ATOM_ ## name, #include "quickjs-atom.h" #undef DEF JS_ATOM_END, }; #define JS_ATOM_LAST_KEYWORD JS_ATOM_super #define JS_ATOM_LAST_STRICT_KEYWORD JS_ATOM_yield static const char js_atom_init[] = #define DEF(name, str) str "\0" #include "quickjs-atom.h" #undef DEF ; typedef enum OPCodeFormat { #define FMT(f) OP_FMT_ ## f, #define DEF(id, size, n_pop, n_push, f) #include "quickjs-opcode.h" #undef DEF #undef FMT } OPCodeFormat; typedef enum OPCodeEnum { #define FMT(f) #define DEF(id, size, n_pop, n_push, f) OP_ ## id, #define def(id, size, n_pop, n_push, f) #include "quickjs-opcode.h" #undef def #undef DEF #undef FMT OP_COUNT, /* excluding temporary opcodes */ /* temporary opcodes : overlap with the short opcodes */ OP_TEMP_START = OP_nop + 1, OP___dummy = OP_TEMP_START - 1, #define FMT(f) #define DEF(id, size, n_pop, n_push, f) #define def(id, size, n_pop, n_push, f) OP_ ## id, #include "quickjs-opcode.h" #undef def #undef DEF #undef FMT OP_TEMP_END, } OPCodeEnum; #ifndef NDEBUG void notifyRefCountIncrease(JSRefCountHeader *p); void notifyRefCountDecrease(JSRefCountHeader *p); #endif static int JS_InitAtoms(JSRuntime *rt); static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, int atom_type); static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p); static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b); static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags); static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags); static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, JSValueConst new_target, int argc, JSValueConst *argv, int flags); static JSValue JS_CallConstructorInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, int argc, JSValueConst *argv, int flags); static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj, int argc, JSValueConst *argv); static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, int argc, JSValueConst *argv); static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, JSValue val, bool is_array_ctor); static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, JSValueConst val, int flags, int scope_idx); static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p); static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt); static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p); static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p); static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val); static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); static __maybe_unused void JS_DumpShapes(JSRuntime *rt); static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static void js_array_finalizer(JSRuntime *rt, JSValueConst val); static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_object_data_finalizer(JSRuntime *rt, JSValueConst val); static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_c_function_finalizer(JSRuntime *rt, JSValueConst val); static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_bytecode_function_finalizer(JSRuntime *rt, JSValueConst val); static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_bound_function_finalizer(JSRuntime *rt, JSValueConst val); static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValueConst val); static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_regexp_finalizer(JSRuntime *rt, JSValueConst val); static void js_array_buffer_finalizer(JSRuntime *rt, JSValueConst val); static void js_typed_array_finalizer(JSRuntime *rt, JSValueConst val); static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_proxy_finalizer(JSRuntime *rt, JSValueConst val); static void js_proxy_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_map_finalizer(JSRuntime *rt, JSValueConst val); static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_map_iterator_finalizer(JSRuntime *rt, JSValueConst val); static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_array_iterator_finalizer(JSRuntime *rt, JSValueConst val); static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_iterator_concat_finalizer(JSRuntime *rt, JSValueConst val); static void js_iterator_concat_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_iterator_helper_finalizer(JSRuntime *rt, JSValueConst val); static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValueConst val); static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValueConst val); static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_generator_finalizer(JSRuntime *rt, JSValueConst val); static void js_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_promise_finalizer(JSRuntime *rt, JSValueConst val); static void js_promise_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValueConst val); static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); #define HINT_STRING 0 #define HINT_NUMBER 1 #define HINT_NONE 2 #define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint); static JSValue JS_ToStringFree(JSContext *ctx, JSValue val); static int JS_ToBoolFree(JSContext *ctx, JSValue val); static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val); static int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val); static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val); static JSValue JS_ToPropertyKeyInternal(JSContext *ctx, JSValueConst val, int flags); static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len); static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, JSValueConst flags); static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, JSValue pattern, JSValue bc); static void gc_decref(JSRuntime *rt); static int JS_NewClass1(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, JSAtom name); static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int unshift); static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv); static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); typedef enum JSStrictEqModeEnum { JS_EQ_STRICT, JS_EQ_SAME_VALUE, JS_EQ_SAME_VALUE_ZERO, } JSStrictEqModeEnum; static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode); static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2); static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2); static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2); static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); static JSValue JS_ThrowStackOverflow(JSContext *ctx); static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, JSValueConst proto_val, bool throw_flag); static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj); static int js_proxy_isArray(JSContext *ctx, JSValueConst obj); static int JS_CreateProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags); static int js_string_memcmp(JSString *p1, JSString *p2, int len); static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref); static bool is_valid_weakref_target(JSValueConst val); static void insert_weakref_record(JSValueConst target, struct JSWeakRefRecord *wr); static JSValue js_array_buffer_constructor3(JSContext *ctx, JSValueConst new_target, uint64_t len, uint64_t *max_len, JSClassID class_id, uint8_t *buf, JSFreeArrayBufferDataFunc *free_func, void *opaque, bool alloc_flag); static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr); static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); static bool array_buffer_is_resizable(const JSArrayBuffer *abuf); static JSValue js_typed_array_constructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int classid); static JSValue js_typed_array_constructor_ta(JSContext *ctx, JSValueConst new_target, JSValueConst src_obj, int classid, uint32_t len); static bool is_typed_array(JSClassID class_id); static bool typed_array_is_oob(JSObject *p); static uint32_t typed_array_length(JSObject *p); static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx); static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, bool is_arg); static JSValue js_call_generator_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags); static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValueConst val); static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int line, int flags, int scope_idx); static void js_free_module_def(JSContext *ctx, JSModuleDef *m); static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkFunc *mark_func); static JSValue js_import_meta(JSContext *ctx); static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, JSValueConst ctor); static __exception int perform_promise_then(JSContext *ctx, JSValueConst promise, JSValueConst *resolve_reject, JSValueConst *cap_resolving_funcs); static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); static JSValue js_promise_resolve_thenable_job(JSContext *ctx, int argc, JSValueConst *argv); static bool js_string_eq(JSString *p1, JSString *p2); static int js_string_compare(JSString *p1, JSString *p2); static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val, int flags); static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val); static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val); static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop); static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc); static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, JS_MarkFunc *mark_func); static void JS_AddIntrinsicBasicObjects(JSContext *ctx); static void js_free_shape(JSRuntime *rt, JSShape *sh); static void js_free_shape_null(JSRuntime *rt, JSShape *sh); static int js_shape_prepare_update(JSContext *ctx, JSObject *p, JSShapeProperty **pprs); static int init_shape_hash(JSRuntime *rt); static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, JSValueConst obj); static __exception int js_get_length64(JSContext *ctx, int64_t *pres, JSValueConst obj); static __exception int js_set_length64(JSContext *ctx, JSValueConst obj, int64_t len); static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len); static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, JSValueConst array_arg); static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab); static bool js_get_fast_array(JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp); static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len); static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, JSValue sync_iter); static void js_c_function_data_finalizer(JSRuntime *rt, JSValueConst val); static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static JSValue js_call_c_function_data(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags); static JSAtom js_symbol_to_atom(JSContext *ctx, JSValueConst val); static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type); static void remove_gc_object(JSGCObjectHeader *h); static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s); static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, bool flag); static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd); static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf); static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num); static void _JS_AddIntrinsicCallSite(JSContext *ctx); static void JS_SetOpaqueInternal(JSValueConst obj, void *opaque); static const JSClassExoticMethods js_arguments_exotic_methods; static const JSClassExoticMethods js_string_exotic_methods; static const JSClassExoticMethods js_proxy_exotic_methods; static const JSClassExoticMethods js_module_ns_exotic_methods; static inline bool double_is_int32(double d) { uint64_t u, e; JSFloat64Union t; t.d = d; u = t.u64; e = ((u >> 52) & 0x7FF) - 1023; if (e > 30) { // accept 0, INT32_MIN, reject too large, too small, nan, inf, -0 return !u || (u == 0xc1e0000000000000); } else { // shift out sign, exponent and whole part bits // value is fractional if remaining low bits are non-zero return !(u << 12 << e); } } static JSValue js_float64(double d) { return __JS_NewFloat64(d); } static int compare_u32(uint32_t a, uint32_t b) { return -(a < b) + (b < a); // -1, 0 or 1 } static JSValue js_int32(int32_t v) { return JS_MKVAL(JS_TAG_INT, v); } static JSValue js_uint32(uint32_t v) { if (v <= INT32_MAX) return js_int32(v); else return js_float64(v); } static JSValue js_int64(int64_t v) { if (v >= INT32_MIN && v <= INT32_MAX) return js_int32(v); else return js_float64(v); } static JSValue js_number(double d) { if (double_is_int32(d)) return js_int32((int32_t)d); else return js_float64(d); } JSValue JS_NewNumber(JSContext *ctx, double d) { return js_number(d); } static JSValue js_bool(bool v) { return JS_MKVAL(JS_TAG_BOOL, (v != 0)); } static JSValue js_dup(JSValueConst v) { if (JS_VALUE_HAS_REF_COUNT(v)) { JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); #ifndef NDEBUG notifyRefCountIncrease(p); #endif p->ref_count++; } return unsafe_unconst(v); } JSValue JS_DupValue(JSContext *ctx, JSValueConst v) { return js_dup(v); } JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) { return js_dup(v); } static void js_trigger_gc(JSRuntime *rt, size_t size) { bool force_gc; #ifdef FORCE_GC_AT_MALLOC force_gc = true; #else force_gc = ((rt->malloc_state.malloc_size + size) > rt->malloc_gc_threshold); #endif if (force_gc) { #ifdef ENABLE_DUMPS // JS_DUMP_GC if (check_dump_flag(rt, JS_DUMP_GC)) { printf("GC: size=%zd\n", rt->malloc_state.malloc_size); } #endif JS_RunGC(rt); rt->malloc_gc_threshold = rt->malloc_state.malloc_size + (rt->malloc_state.malloc_size >> 1); } } static size_t js_malloc_usable_size_unknown(const void *ptr) { return 0; } void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size) { void *ptr; JSMallocState *s; /* Do not allocate zero bytes: behavior is platform dependent */ assert(count != 0 && size != 0); if (size > 0) if (unlikely(count != (count * size) / size)) return NULL; s = &rt->malloc_state; /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1)) return NULL; ptr = rt->mf.js_calloc(s->opaque, count, size); if (!ptr) return NULL; s->malloc_count++; s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; return ptr; } void *js_malloc_rt(JSRuntime *rt, size_t size) { void *ptr; JSMallocState *s; /* Do not allocate zero bytes: behavior is platform dependent */ assert(size != 0); s = &rt->malloc_state; /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ if (unlikely(s->malloc_size + size > s->malloc_limit - 1)) return NULL; ptr = rt->mf.js_malloc(s->opaque, size); if (!ptr) return NULL; s->malloc_count++; s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; return ptr; } void js_free_rt(JSRuntime *rt, void *ptr) { JSMallocState *s; if (!ptr) return; s = &rt->malloc_state; s->malloc_count--; s->malloc_size -= rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; rt->mf.js_free(s->opaque, ptr); } void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size) { size_t old_size; JSMallocState *s; if (!ptr) { if (size == 0) return NULL; return js_malloc_rt(rt, size); } if (unlikely(size == 0)) { js_free_rt(rt, ptr); return NULL; } old_size = rt->mf.js_malloc_usable_size(ptr); s = &rt->malloc_state; /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ if (s->malloc_size + size - old_size > s->malloc_limit - 1) return NULL; ptr = rt->mf.js_realloc(s->opaque, ptr, size); if (!ptr) return NULL; s->malloc_size += rt->mf.js_malloc_usable_size(ptr) - old_size; return ptr; } size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr) { return rt->mf.js_malloc_usable_size(ptr); } /** * This used to be implemented as malloc + memset, but using calloc * yields better performance in initial, bursty allocations, something useful * for QuickJS. * * More information: https://github.com/quickjs-ng/quickjs/pull/519 */ void *js_mallocz_rt(JSRuntime *rt, size_t size) { return js_calloc_rt(rt, 1, size); } /* Throw out of memory in case of error */ void *js_calloc(JSContext *ctx, size_t count, size_t size) { void *ptr; ptr = js_calloc_rt(ctx->rt, count, size); if (unlikely(!ptr)) { JS_ThrowOutOfMemory(ctx); return NULL; } return ptr; } /* Throw out of memory in case of error */ void *js_malloc(JSContext *ctx, size_t size) { void *ptr; ptr = js_malloc_rt(ctx->rt, size); if (unlikely(!ptr)) { JS_ThrowOutOfMemory(ctx); return NULL; } return ptr; } /* Throw out of memory in case of error */ void *js_mallocz(JSContext *ctx, size_t size) { void *ptr; ptr = js_mallocz_rt(ctx->rt, size); if (unlikely(!ptr)) { JS_ThrowOutOfMemory(ctx); return NULL; } return ptr; } void js_free(JSContext *ctx, void *ptr) { js_free_rt(ctx->rt, ptr); } /* Throw out of memory in case of error */ void *js_realloc(JSContext *ctx, void *ptr, size_t size) { void *ret; ret = js_realloc_rt(ctx->rt, ptr, size); if (unlikely(!ret && size != 0)) { JS_ThrowOutOfMemory(ctx); return NULL; } return ret; } /* store extra allocated size in *pslack if successful */ void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack) { void *ret; ret = js_realloc_rt(ctx->rt, ptr, size); if (unlikely(!ret && size != 0)) { JS_ThrowOutOfMemory(ctx); return NULL; } if (pslack) { size_t new_size = js_malloc_usable_size_rt(ctx->rt, ret); *pslack = (new_size > size) ? new_size - size : 0; } return ret; } size_t js_malloc_usable_size(JSContext *ctx, const void *ptr) { return js_malloc_usable_size_rt(ctx->rt, ptr); } /* Throw out of memory exception in case of error */ char *js_strndup(JSContext *ctx, const char *s, size_t n) { char *ptr; ptr = js_malloc(ctx, n + 1); if (ptr) { memcpy(ptr, s, n); ptr[n] = '\0'; } return ptr; } char *js_strdup(JSContext *ctx, const char *str) { return js_strndup(ctx, str, strlen(str)); } static no_inline int js_realloc_array(JSContext *ctx, void **parray, int elem_size, int *psize, int req_size) { int new_size; size_t slack; void *new_array; /* XXX: potential arithmetic overflow */ new_size = max_int(req_size, *psize * 3 / 2); new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack); if (!new_array) return -1; new_size += slack / elem_size; *psize = new_size; *parray = new_array; return 0; } /* resize the array and update its size if req_size > *psize */ static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size, int *psize, int req_size) { if (unlikely(req_size > *psize)) return js_realloc_array(ctx, parray, elem_size, psize, req_size); else return 0; } static void *js_dbuf_realloc(void *ctx, void *ptr, size_t size) { return js_realloc(ctx, ptr, size); } static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) { dbuf_init2(s, ctx, js_dbuf_realloc); } static inline int is_digit(int c) { return c >= '0' && c <= '9'; } static inline int string_get(JSString *p, int idx) { return p->is_wide_char ? str16(p)[idx] : str8(p)[idx]; } typedef struct JSClassShortDef { JSAtom class_name; JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; } JSClassShortDef; static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */ { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */ { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */ { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */ { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */ { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ { JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */ { JS_ATOM_Arguments, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARGUMENTS */ { JS_ATOM_Arguments, NULL, NULL }, /* JS_CLASS_MAPPED_ARGUMENTS */ { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */ { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_MODULE_NS */ { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */ { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */ { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */ { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */ { JS_ATOM_GeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_GENERATOR_FUNCTION */ { JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark }, /* JS_CLASS_FOR_IN_ITERATOR */ { JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */ { JS_ATOM_ArrayBuffer, js_array_buffer_finalizer, NULL }, /* JS_CLASS_ARRAY_BUFFER */ { JS_ATOM_SharedArrayBuffer, js_array_buffer_finalizer, NULL }, /* JS_CLASS_SHARED_ARRAY_BUFFER */ { JS_ATOM_Uint8ClampedArray, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8C_ARRAY */ { JS_ATOM_Int8Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT8_ARRAY */ { JS_ATOM_Uint8Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8_ARRAY */ { JS_ATOM_Int16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT16_ARRAY */ { JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT16_ARRAY */ { JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT32_ARRAY */ { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */ { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */ { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */ { JS_ATOM_Float16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT16_ARRAY */ { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */ { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */ { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */ { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */ { JS_ATOM_Map, js_map_finalizer, js_map_mark }, /* JS_CLASS_MAP */ { JS_ATOM_Set, js_map_finalizer, js_map_mark }, /* JS_CLASS_SET */ { JS_ATOM_WeakMap, js_map_finalizer, NULL }, /* JS_CLASS_WEAKMAP */ { JS_ATOM_WeakSet, js_map_finalizer, NULL }, /* JS_CLASS_WEAKSET */ { JS_ATOM_Iterator, NULL, NULL }, /* JS_CLASS_ITERATOR */ { JS_ATOM_IteratorConcat, js_iterator_concat_finalizer, js_iterator_concat_mark }, /* JS_CLASS_ITERATOR_CONCAT */ { JS_ATOM_IteratorHelper, js_iterator_helper_finalizer, js_iterator_helper_mark }, /* JS_CLASS_ITERATOR_HELPER */ { JS_ATOM_IteratorWrap, js_iterator_wrap_finalizer, js_iterator_wrap_mark }, /* JS_CLASS_ITERATOR_WRAP */ { JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */ { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */ { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */ { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */ { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */ }; static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab, int start, int count) { JSClassDef cm_s, *cm = &cm_s; int i, class_id; for(i = 0; i < count; i++) { class_id = i + start; memset(cm, 0, sizeof(*cm)); cm->finalizer = tab[i].finalizer; cm->gc_mark = tab[i].gc_mark; if (JS_NewClass1(rt, class_id, cm, tab[i].class_name) < 0) return -1; } return 0; } /* Uses code from LLVM project. */ static inline uintptr_t js_get_stack_pointer(void) { #if defined(__clang__) || defined(__GNUC__) return (uintptr_t)__builtin_frame_address(0); #elif defined(_MSC_VER) return (uintptr_t)_AddressOfReturnAddress(); #else char CharOnStack = 0; // The volatile store here is intended to escape the local variable, to // prevent the compiler from optimizing CharOnStack into anything other // than a char on the stack. // // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19. char *volatile Ptr = &CharOnStack; return (uintptr_t) Ptr; #endif } static inline bool js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) { uintptr_t sp; sp = js_get_stack_pointer() - alloca_size; return unlikely(sp < rt->stack_limit); } JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) { JSRuntime *rt; JSMallocState ms; memset(&ms, 0, sizeof(ms)); ms.opaque = opaque; ms.malloc_limit = 0; rt = mf->js_calloc(opaque, 1, sizeof(JSRuntime)); if (!rt) return NULL; rt->mf = *mf; if (!rt->mf.js_malloc_usable_size) { /* use dummy function if none provided */ rt->mf.js_malloc_usable_size = js_malloc_usable_size_unknown; } /* Inline what js_malloc_rt does since we cannot use it here. */ ms.malloc_count++; ms.malloc_size += rt->mf.js_malloc_usable_size(rt) + MALLOC_OVERHEAD; rt->malloc_state = ms; rt->malloc_gc_threshold = 256 * 1024; init_list_head(&rt->context_list); init_list_head(&rt->gc_obj_list); init_list_head(&rt->gc_zero_ref_count_list); rt->gc_phase = JS_GC_PHASE_NONE; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS init_list_head(&rt->string_list); #endif init_list_head(&rt->job_list); if (JS_InitAtoms(rt)) goto fail; /* create the object, array and function classes */ if (init_class_range(rt, js_std_class_def, JS_CLASS_OBJECT, countof(js_std_class_def)) < 0) goto fail; rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods; rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods; rt->class_array[JS_CLASS_MODULE_NS].exotic = &js_module_ns_exotic_methods; rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function; rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_call_c_function_data; rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function; rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_call_generator_function; if (init_shape_hash(rt)) goto fail; rt->js_class_id_alloc = JS_CLASS_INIT_COUNT; rt->stack_size = JS_DEFAULT_STACK_SIZE; #ifdef __wasi__ rt->stack_size = 0; #endif JS_UpdateStackTop(rt); rt->current_exception = JS_UNINITIALIZED; return rt; fail: JS_FreeRuntime(rt); return NULL; } void *JS_GetRuntimeOpaque(JSRuntime *rt) { return rt->user_opaque; } void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque) { rt->user_opaque = opaque; } int JS_AddRuntimeFinalizer(JSRuntime *rt, JSRuntimeFinalizer *finalizer, void *arg) { JSRuntimeFinalizerState *fs = js_malloc_rt(rt, sizeof(*fs)); if (!fs) return -1; fs->next = rt->finalizers; fs->finalizer = finalizer; fs->arg = arg; rt->finalizers = fs; return 0; } static void *js_def_calloc(void *opaque, size_t count, size_t size) { return calloc(count, size); } static void *js_def_malloc(void *opaque, size_t size) { return malloc(size); } static void js_def_free(void *opaque, void *ptr) { free(ptr); } static void *js_def_realloc(void *opaque, void *ptr, size_t size) { return realloc(ptr, size); } static const JSMallocFunctions def_malloc_funcs = { js_def_calloc, js_def_malloc, js_def_free, js_def_realloc, js__malloc_usable_size }; JSRuntime *JS_NewRuntime(void) { return JS_NewRuntime2(&def_malloc_funcs, NULL); } void JS_SetMemoryLimit(JSRuntime *rt, size_t limit) { rt->malloc_state.malloc_limit = limit; } void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags) { #ifdef ENABLE_DUMPS rt->dump_flags = flags; #endif } uint64_t JS_GetDumpFlags(JSRuntime *rt) { #ifdef ENABLE_DUMPS return rt->dump_flags; #else return 0; #endif } size_t JS_GetGCThreshold(JSRuntime *rt) { return rt->malloc_gc_threshold; } /* use -1 to disable automatic GC */ void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold) { rt->malloc_gc_threshold = gc_threshold; } #define malloc(s) malloc_is_forbidden(s) #define free(p) free_is_forbidden(p) #define realloc(p,s) realloc_is_forbidden(p,s) void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque) { rt->interrupt_handler = cb; rt->interrupt_opaque = opaque; } void JS_SetCanBlock(JSRuntime *rt, bool can_block) { rt->can_block = can_block; } void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf) { rt->sab_funcs = *sf; } /* return 0 if OK, < 0 if exception */ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv) { JSRuntime *rt = ctx->rt; JSJobEntry *e; int i; assert(!rt->in_free); e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue)); if (!e) return -1; e->ctx = ctx; e->job_func = job_func; e->argc = argc; for(i = 0; i < argc; i++) { e->argv[i] = js_dup(argv[i]); } list_add_tail(&e->link, &rt->job_list); return 0; } bool JS_IsJobPending(JSRuntime *rt) { return !list_empty(&rt->job_list); } /* return < 0 if exception, 0 if no job pending, 1 if a job was executed successfully. the context of the job is stored in '*pctx' */ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) { JSContext *ctx; JSJobEntry *e; JSValue res; int i, ret; if (list_empty(&rt->job_list)) { *pctx = NULL; return 0; } /* get the first pending job and execute it */ e = list_entry(rt->job_list.next, JSJobEntry, link); list_del(&e->link); ctx = e->ctx; res = e->job_func(e->ctx, e->argc, vc(e->argv)); for(i = 0; i < e->argc; i++) JS_FreeValue(ctx, e->argv[i]); if (JS_IsException(res)) ret = -1; else ret = 1; JS_FreeValue(ctx, res); js_free(ctx, e); *pctx = ctx; return ret; } static inline uint32_t atom_get_free(const JSAtomStruct *p) { return (uintptr_t)p >> 1; } static inline bool atom_is_free(const JSAtomStruct *p) { return (uintptr_t)p & 1; } static inline JSAtomStruct *atom_set_free(uint32_t v) { return (JSAtomStruct *)(((uintptr_t)v << 1) | 1); } /* Note: the string contents are uninitialized */ static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char) { JSString *str; str = js_malloc_rt(rt, sizeof(JSString) + (max_len << is_wide_char) + 1 - is_wide_char); if (unlikely(!str)) return NULL; str->header.ref_count = 1; str->is_wide_char = is_wide_char; str->len = max_len; str->kind = JS_STRING_KIND_NORMAL; str->atom_type = 0; str->hash = 0; /* optional but costless */ str->hash_next = 0; /* optional */ #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&str->link, &rt->string_list); #endif return str; } static JSString *js_alloc_string(JSContext *ctx, int max_len, int is_wide_char) { JSString *p; p = js_alloc_string_rt(ctx->rt, max_len, is_wide_char); if (unlikely(!p)) { JS_ThrowOutOfMemory(ctx); return NULL; } return p; } static inline void js_free_string0(JSRuntime *rt, JSString *str); /* same as JS_FreeValueRT() but faster */ static inline void js_free_string(JSRuntime *rt, JSString *str) { if (--str->header.ref_count <= 0) js_free_string0(rt, str); } static inline void js_free_string0(JSRuntime *rt, JSString *str) { if (str->atom_type) { JS_FreeAtomStruct(rt, str); } else { #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_del(&str->link); #endif if (str->kind == JS_STRING_KIND_SLICE) { JSStringSlice *slice = (void *)&str[1]; js_free_string(rt, slice->parent); // safe, recurses only 1 level } js_free_rt(rt, str); } } void JS_SetRuntimeInfo(JSRuntime *rt, const char *s) { if (rt) rt->rt_info = s; } void JS_FreeRuntime(JSRuntime *rt) { struct list_head *el, *el1; int i; rt->in_free = true; JS_FreeValueRT(rt, rt->current_exception); list_for_each_safe(el, el1, &rt->job_list) { JSJobEntry *e = list_entry(el, JSJobEntry, link); for(i = 0; i < e->argc; i++) JS_FreeValueRT(rt, e->argv[i]); js_free_rt(rt, e); } init_list_head(&rt->job_list); JS_RunGC(rt); #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS /* leaking objects */ if (check_dump_flag(rt, JS_DUMP_LEAKS)) { bool header_done; JSGCObjectHeader *p; int count; /* remove the internal refcounts to display only the object referenced externally */ list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); p->mark = 0; } gc_decref(rt); header_done = false; list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); if (p->ref_count != 0) { if (!header_done) { printf("Object leaks:\n"); JS_DumpObjectHeader(rt); header_done = true; } JS_DumpGCObject(rt, p); } } count = 0; list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); if (p->ref_count == 0) { count++; } } if (count != 0) printf("Secondary object leaks: %d\n", count); } #endif assert(list_empty(&rt->gc_obj_list)); /* free the classes */ for(i = 0; i < rt->class_count; i++) { JSClass *cl = &rt->class_array[i]; if (cl->class_id != 0) { JS_FreeAtomRT(rt, cl->class_name); } } js_free_rt(rt, rt->class_array); #ifdef ENABLE_DUMPS // JS_DUMP_ATOM_LEAKS /* only the atoms defined in JS_InitAtoms() should be left */ if (check_dump_flag(rt, JS_DUMP_ATOM_LEAKS)) { bool header_done = false; for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p) /* && p->str*/) { if (i >= JS_ATOM_END || p->header.ref_count != 1) { if (!header_done) { header_done = true; if (rt->rt_info) { printf("%s:1: atom leakage:", rt->rt_info); } else { printf("Atom leaks:\n" " %6s %6s %s\n", "ID", "REFCNT", "NAME"); } } if (rt->rt_info) { printf(" "); } else { printf(" %6u %6u ", i, p->header.ref_count); } switch (p->atom_type) { case JS_ATOM_TYPE_STRING: JS_DumpString(rt, p); break; case JS_ATOM_TYPE_GLOBAL_SYMBOL: printf("Symbol.for("); JS_DumpString(rt, p); printf(")"); break; case JS_ATOM_TYPE_SYMBOL: if (p->hash == JS_ATOM_HASH_SYMBOL) { printf("Symbol("); JS_DumpString(rt, p); printf(")"); } else { printf("Private("); JS_DumpString(rt, p); printf(")"); } break; } if (rt->rt_info) { printf(":%u", p->header.ref_count); } else { printf("\n"); } } } } if (rt->rt_info && header_done) printf("\n"); } #endif /* free the atoms */ for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p)) { #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_del(&p->link); #endif js_free_rt(rt, p); } } js_free_rt(rt, rt->atom_array); js_free_rt(rt, rt->atom_hash); js_free_rt(rt, rt->shape_hash); #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS if (check_dump_flag(rt, JS_DUMP_LEAKS) && !list_empty(&rt->string_list)) { if (rt->rt_info) { printf("%s:1: string leakage:", rt->rt_info); } else { printf("String leaks:\n" " %6s %s\n", "REFCNT", "VALUE"); } list_for_each_safe(el, el1, &rt->string_list) { JSString *str = list_entry(el, JSString, link); if (rt->rt_info) { printf(" "); } else { printf(" %6u ", str->header.ref_count); } JS_DumpString(rt, str); if (rt->rt_info) { printf(":%u", str->header.ref_count); } else { printf("\n"); } list_del(&str->link); js_free_rt(rt, str); } if (rt->rt_info) printf("\n"); } #endif while (rt->finalizers) { JSRuntimeFinalizerState *fs = rt->finalizers; rt->finalizers = fs->next; fs->finalizer(rt, fs->arg); js_free_rt(rt, fs); } #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS if (check_dump_flag(rt, JS_DUMP_LEAKS)) { JSMallocState *s = &rt->malloc_state; if (s->malloc_count > 1) { if (rt->rt_info) printf("%s:1: ", rt->rt_info); printf("Memory leak: %zd bytes lost in %zd block%s\n", s->malloc_size - sizeof(JSRuntime), s->malloc_count - 1, &"s"[s->malloc_count == 2]); } } #endif { JSMallocState *ms = &rt->malloc_state; rt->mf.js_free(ms->opaque, rt); } fflush(stdout); } JSContext *JS_NewContextRaw(JSRuntime *rt) { JSContext *ctx; int i; ctx = js_mallocz_rt(rt, sizeof(JSContext)); if (!ctx) return NULL; ctx->header.ref_count = 1; add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT); ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) * rt->class_count); if (!ctx->class_proto) { js_free_rt(rt, ctx); return NULL; } ctx->rt = rt; list_add_tail(&ctx->link, &rt->context_list); for(i = 0; i < rt->class_count; i++) ctx->class_proto[i] = JS_NULL; ctx->array_ctor = JS_NULL; ctx->iterator_ctor = JS_NULL; ctx->iterator_ctor_getset = JS_NULL; ctx->regexp_ctor = JS_NULL; ctx->promise_ctor = JS_NULL; ctx->error_ctor = JS_NULL; ctx->error_back_trace = JS_UNDEFINED; ctx->error_prepare_stack = JS_UNDEFINED; ctx->error_stack_trace_limit = js_int32(10); init_list_head(&ctx->loaded_modules); JS_AddIntrinsicBasicObjects(ctx); return ctx; } JSContext *JS_NewContext(JSRuntime *rt) { JSContext *ctx; ctx = JS_NewContextRaw(rt); if (!ctx) return NULL; JS_AddIntrinsicBaseObjects(ctx); JS_AddIntrinsicDate(ctx); JS_AddIntrinsicEval(ctx); JS_AddIntrinsicRegExp(ctx); JS_AddIntrinsicJSON(ctx); JS_AddIntrinsicProxy(ctx); JS_AddIntrinsicMapSet(ctx); JS_AddIntrinsicTypedArrays(ctx); JS_AddIntrinsicPromise(ctx); JS_AddIntrinsicBigInt(ctx); JS_AddIntrinsicWeakRef(ctx); JS_AddIntrinsicDOMException(ctx); JS_AddPerformance(ctx); return ctx; } void *JS_GetContextOpaque(JSContext *ctx) { return ctx->user_opaque; } void JS_SetContextOpaque(JSContext *ctx, void *opaque) { ctx->user_opaque = opaque; } /* set the new value and free the old value after (freeing the value can reallocate the object data) */ static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val) { JSValue old_val; old_val = *pval; *pval = new_val; JS_FreeValue(ctx, old_val); } void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj) { assert(class_id < ctx->rt->class_count); set_value(ctx, &ctx->class_proto[class_id], obj); } JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id) { assert(class_id < ctx->rt->class_count); return js_dup(ctx->class_proto[class_id]); } JSValue JS_GetFunctionProto(JSContext *ctx) { return js_dup(ctx->function_proto); } typedef enum JSFreeModuleEnum { JS_FREE_MODULE_ALL, JS_FREE_MODULE_NOT_RESOLVED, } JSFreeModuleEnum; /* XXX: would be more efficient with separate module lists */ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag) { struct list_head *el, *el1; list_for_each_safe(el, el1, &ctx->loaded_modules) { JSModuleDef *m = list_entry(el, JSModuleDef, link); if (flag == JS_FREE_MODULE_ALL || (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) { js_free_module_def(ctx, m); } } } JSContext *JS_DupContext(JSContext *ctx) { ctx->header.ref_count++; return ctx; } /* used by the GC */ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx, JS_MarkFunc *mark_func) { int i; struct list_head *el; /* modules are not seen by the GC, so we directly mark the objects referenced by each module */ list_for_each(el, &ctx->loaded_modules) { JSModuleDef *m = list_entry(el, JSModuleDef, link); js_mark_module_def(rt, m, mark_func); } JS_MarkValue(rt, ctx->global_obj, mark_func); JS_MarkValue(rt, ctx->global_var_obj, mark_func); JS_MarkValue(rt, ctx->throw_type_error, mark_func); JS_MarkValue(rt, ctx->eval_obj, mark_func); JS_MarkValue(rt, ctx->array_proto_values, mark_func); for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { JS_MarkValue(rt, ctx->native_error_proto[i], mark_func); } JS_MarkValue(rt, ctx->error_ctor, mark_func); JS_MarkValue(rt, ctx->error_back_trace, mark_func); JS_MarkValue(rt, ctx->error_prepare_stack, mark_func); JS_MarkValue(rt, ctx->error_stack_trace_limit, mark_func); for(i = 0; i < rt->class_count; i++) { JS_MarkValue(rt, ctx->class_proto[i], mark_func); } JS_MarkValue(rt, ctx->iterator_ctor, mark_func); JS_MarkValue(rt, ctx->iterator_ctor_getset, mark_func); JS_MarkValue(rt, ctx->async_iterator_proto, mark_func); JS_MarkValue(rt, ctx->promise_ctor, mark_func); JS_MarkValue(rt, ctx->array_ctor, mark_func); JS_MarkValue(rt, ctx->regexp_ctor, mark_func); JS_MarkValue(rt, ctx->function_ctor, mark_func); JS_MarkValue(rt, ctx->function_proto, mark_func); if (ctx->array_shape) mark_func(rt, &ctx->array_shape->header); } void JS_FreeContext(JSContext *ctx) { JSRuntime *rt = ctx->rt; int i; if (--ctx->header.ref_count > 0) return; assert(ctx->header.ref_count == 0); #ifdef ENABLE_DUMPS // JS_DUMP_ATOMS if (check_dump_flag(rt, JS_DUMP_ATOMS)) JS_DumpAtoms(ctx->rt); #endif #ifdef ENABLE_DUMPS // JS_DUMP_SHAPES if (check_dump_flag(rt, JS_DUMP_SHAPES)) JS_DumpShapes(ctx->rt); #endif #ifdef ENABLE_DUMPS // JS_DUMP_OBJECTS if (check_dump_flag(rt, JS_DUMP_OBJECTS)) { struct list_head *el; JSGCObjectHeader *p; printf("JSObjects: {\n"); JS_DumpObjectHeader(ctx->rt); list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); JS_DumpGCObject(rt, p); } printf("}\n"); } #endif #ifdef ENABLE_DUMPS // JS_DUMP_MEM if (check_dump_flag(rt, JS_DUMP_MEM)) { JSMemoryUsage stats; JS_ComputeMemoryUsage(rt, &stats); JS_DumpMemoryUsage(stdout, &stats, rt); } #endif js_free_modules(ctx, JS_FREE_MODULE_ALL); JS_FreeValue(ctx, ctx->global_obj); JS_FreeValue(ctx, ctx->global_var_obj); JS_FreeValue(ctx, ctx->throw_type_error); JS_FreeValue(ctx, ctx->eval_obj); JS_FreeValue(ctx, ctx->array_proto_values); for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { JS_FreeValue(ctx, ctx->native_error_proto[i]); } JS_FreeValue(ctx, ctx->error_ctor); JS_FreeValue(ctx, ctx->error_back_trace); JS_FreeValue(ctx, ctx->error_prepare_stack); JS_FreeValue(ctx, ctx->error_stack_trace_limit); for(i = 0; i < rt->class_count; i++) { JS_FreeValue(ctx, ctx->class_proto[i]); } js_free_rt(rt, ctx->class_proto); JS_FreeValue(ctx, ctx->iterator_ctor); JS_FreeValue(ctx, ctx->iterator_ctor_getset); JS_FreeValue(ctx, ctx->async_iterator_proto); JS_FreeValue(ctx, ctx->promise_ctor); JS_FreeValue(ctx, ctx->array_ctor); JS_FreeValue(ctx, ctx->regexp_ctor); JS_FreeValue(ctx, ctx->function_ctor); JS_FreeValue(ctx, ctx->function_proto); js_free_shape_null(ctx->rt, ctx->array_shape); list_del(&ctx->link); remove_gc_object(&ctx->header); js_free_rt(ctx->rt, ctx); } JSRuntime *JS_GetRuntime(JSContext *ctx) { return ctx->rt; } static void update_stack_limit(JSRuntime *rt) { #if defined(__wasi__) rt->stack_limit = 0; /* no limit */ #else if (rt->stack_size == 0) { rt->stack_limit = 0; /* no limit */ } else { rt->stack_limit = rt->stack_top - rt->stack_size; } #endif } void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size) { rt->stack_size = stack_size; update_stack_limit(rt); } void JS_UpdateStackTop(JSRuntime *rt) { rt->stack_top = js_get_stack_pointer(); update_stack_limit(rt); } static inline bool is_strict_mode(JSContext *ctx) { JSStackFrame *sf = ctx->rt->current_stack_frame; return sf && sf->is_strict_mode; } /* JSAtom support */ #define JS_ATOM_TAG_INT (1U << 31) #define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1) #define JS_ATOM_MAX ((1U << 30) - 1) /* return the max count from the hash size */ #define JS_ATOM_COUNT_RESIZE(n) ((n) * 2) static inline bool __JS_AtomIsConst(JSAtom v) { return (int32_t)v < JS_ATOM_END; } static inline bool __JS_AtomIsTaggedInt(JSAtom v) { return (v & JS_ATOM_TAG_INT) != 0; } static inline JSAtom __JS_AtomFromUInt32(uint32_t v) { return v | JS_ATOM_TAG_INT; } static inline uint32_t __JS_AtomToUInt32(JSAtom atom) { return atom & ~JS_ATOM_TAG_INT; } static inline int is_num(int c) { return c >= '0' && c <= '9'; } /* return true if the string is a number n with 0 <= n <= 2^32-1 */ static inline bool is_num_string(uint32_t *pval, JSString *p) { uint32_t n; uint64_t n64; int c, i, len; len = p->len; if (len == 0 || len > 10) return false; c = string_get(p, 0); if (is_num(c)) { if (c == '0') { if (len != 1) return false; n = 0; } else { n = c - '0'; for(i = 1; i < len; i++) { c = string_get(p, i); if (!is_num(c)) return false; n64 = (uint64_t)n * 10 + (c - '0'); if ((n64 >> 32) != 0) return false; n = n64; } } *pval = n; return true; } else { return false; } } /* XXX: could use faster version ? */ static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h) { size_t i; for(i = 0; i < len; i++) h = h * 263 + str[i]; return h; } static inline uint32_t hash_string16(const uint16_t *str, size_t len, uint32_t h) { size_t i; for(i = 0; i < len; i++) h = h * 263 + str[i]; return h; } static uint32_t hash_string(JSString *str, uint32_t h) { if (str->is_wide_char) h = hash_string16(str16(str), str->len, h); else h = hash_string8(str8(str), str->len, h); return h; } static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p) { int i, c, sep; if (p == NULL) { printf(""); return; } if (p->header.ref_count != 1) printf("%d", p->header.ref_count); if (p->is_wide_char) putchar('L'); sep = '\"'; putchar(sep); for(i = 0; i < p->len; i++) { c = string_get(p, i); if (c == sep || c == '\\') { putchar('\\'); putchar(c); } else if (c >= ' ' && c <= 126) { putchar(c); } else if (c == '\n') { putchar('\\'); putchar('n'); } else { printf("\\u%04x", c); } } putchar(sep); } static __maybe_unused void JS_DumpAtoms(JSRuntime *rt) { JSAtomStruct *p; int h, i; /* This only dumps hashed atoms, not JS_ATOM_TYPE_SYMBOL atoms */ printf("JSAtom count=%d size=%d hash_size=%d:\n", rt->atom_count, rt->atom_size, rt->atom_hash_size); printf("JSAtom hash table: {\n"); for(i = 0; i < rt->atom_hash_size; i++) { h = rt->atom_hash[i]; if (h) { printf(" %d:", i); while (h) { p = rt->atom_array[h]; printf(" "); JS_DumpString(rt, p); h = p->hash_next; } printf("\n"); } } printf("}\n"); printf("JSAtom table: {\n"); for(i = 0; i < rt->atom_size; i++) { p = rt->atom_array[i]; if (!atom_is_free(p)) { printf(" %d: { %d %08x ", i, p->atom_type, p->hash); if (!(p->len == 0 && p->is_wide_char != 0)) JS_DumpString(rt, p); printf(" %d }\n", p->hash_next); } } printf("}\n"); } static int JS_ResizeAtomHash(JSRuntime *rt, int new_hash_size) { JSAtomStruct *p; uint32_t new_hash_mask, h, i, hash_next1, j, *new_hash; assert((new_hash_size & (new_hash_size - 1)) == 0); /* power of two */ new_hash_mask = new_hash_size - 1; new_hash = js_mallocz_rt(rt, sizeof(rt->atom_hash[0]) * new_hash_size); if (!new_hash) return -1; for(i = 0; i < rt->atom_hash_size; i++) { h = rt->atom_hash[i]; while (h != 0) { p = rt->atom_array[h]; hash_next1 = p->hash_next; /* add in new hash table */ j = p->hash & new_hash_mask; p->hash_next = new_hash[j]; new_hash[j] = h; h = hash_next1; } } js_free_rt(rt, rt->atom_hash); rt->atom_hash = new_hash; rt->atom_hash_size = new_hash_size; rt->atom_count_resize = JS_ATOM_COUNT_RESIZE(new_hash_size); // JS_DumpAtoms(rt); return 0; } static int JS_InitAtoms(JSRuntime *rt) { int i, len, atom_type; const char *p; rt->atom_hash_size = 0; rt->atom_hash = NULL; rt->atom_count = 0; rt->atom_size = 0; rt->atom_free_index = 0; if (JS_ResizeAtomHash(rt, 256)) /* there are at least 195 predefined atoms */ return -1; p = js_atom_init; for(i = 1; i < JS_ATOM_END; i++) { if (i == JS_ATOM_Private_brand) atom_type = JS_ATOM_TYPE_PRIVATE; else if (i >= JS_ATOM_Symbol_toPrimitive) atom_type = JS_ATOM_TYPE_SYMBOL; else atom_type = JS_ATOM_TYPE_STRING; len = strlen(p); if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL) return -1; p = p + len + 1; } return 0; } static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v) { JSAtomStruct *p; if (!__JS_AtomIsConst(v)) { p = rt->atom_array[v]; p->header.ref_count++; } return v; } JSAtom JS_DupAtom(JSContext *ctx, JSAtom v) { JSRuntime *rt; JSAtomStruct *p; if (!__JS_AtomIsConst(v)) { rt = ctx->rt; p = rt->atom_array[v]; p->header.ref_count++; } return v; } static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v) { JSRuntime *rt; JSAtomStruct *p; rt = ctx->rt; if (__JS_AtomIsTaggedInt(v)) return JS_ATOM_KIND_STRING; p = rt->atom_array[v]; switch(p->atom_type) { case JS_ATOM_TYPE_STRING: return JS_ATOM_KIND_STRING; case JS_ATOM_TYPE_GLOBAL_SYMBOL: return JS_ATOM_KIND_SYMBOL; case JS_ATOM_TYPE_SYMBOL: switch(p->hash) { case JS_ATOM_HASH_SYMBOL: return JS_ATOM_KIND_SYMBOL; case JS_ATOM_HASH_PRIVATE: return JS_ATOM_KIND_PRIVATE; default: abort(); } default: abort(); } return (JSAtomKindEnum){-1}; // pacify compiler } static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p) { uint32_t i = p->hash_next; /* atom_index */ if (p->atom_type != JS_ATOM_TYPE_SYMBOL) { JSAtomStruct *p1; i = rt->atom_hash[p->hash & (rt->atom_hash_size - 1)]; p1 = rt->atom_array[i]; while (p1 != p) { assert(i != 0); i = p1->hash_next; p1 = rt->atom_array[i]; } } return i; } /* string case (internal). Return JS_ATOM_NULL if error. 'str' is freed. */ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) { uint32_t h, h1, i; JSAtomStruct *p; int len; if (atom_type < JS_ATOM_TYPE_SYMBOL) { /* str is not NULL */ if (str->atom_type == atom_type) { /* str is the atom, return its index */ i = js_get_atom_index(rt, str); /* reduce string refcount and increase atom's unless constant */ if (__JS_AtomIsConst(i)) str->header.ref_count--; return i; } /* try and locate an already registered atom */ len = str->len; h = hash_string(str, atom_type); h &= JS_ATOM_HASH_MASK; h1 = h & (rt->atom_hash_size - 1); i = rt->atom_hash[h1]; while (i != 0) { p = rt->atom_array[i]; if (p->hash == h && p->atom_type == atom_type && p->len == len && js_string_memcmp(p, str, len) == 0) { if (!__JS_AtomIsConst(i)) p->header.ref_count++; goto done; } i = p->hash_next; } } else { h1 = 0; /* avoid warning */ if (atom_type == JS_ATOM_TYPE_SYMBOL) { h = JS_ATOM_HASH_SYMBOL; } else { h = JS_ATOM_HASH_PRIVATE; atom_type = JS_ATOM_TYPE_SYMBOL; } } if (rt->atom_free_index == 0) { /* allow new atom entries */ uint32_t new_size, start; JSAtomStruct **new_array; /* alloc new with size progression 3/2: 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092 preallocating space for predefined atoms (at least 195). */ new_size = max_int(211, rt->atom_size * 3 / 2); if (new_size > JS_ATOM_MAX) goto fail; /* XXX: should use realloc2 to use slack space */ new_array = js_realloc_rt(rt, rt->atom_array, sizeof(*new_array) * new_size); if (!new_array) goto fail; /* Note: the atom 0 is not used */ start = rt->atom_size; if (start == 0) { /* JS_ATOM_NULL entry */ p = js_mallocz_rt(rt, sizeof(JSAtomStruct)); if (!p) { js_free_rt(rt, new_array); goto fail; } p->header.ref_count = 1; /* not refcounted */ p->atom_type = JS_ATOM_TYPE_SYMBOL; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif new_array[0] = p; rt->atom_count++; start = 1; } rt->atom_size = new_size; rt->atom_array = new_array; rt->atom_free_index = start; for(i = start; i < new_size; i++) { uint32_t next; if (i == (new_size - 1)) next = 0; else next = i + 1; rt->atom_array[i] = atom_set_free(next); } } if (str) { if (str->atom_type == 0) { p = str; p->atom_type = atom_type; } else { p = js_malloc_rt(rt, sizeof(JSString) + (str->len << str->is_wide_char) + 1 - str->is_wide_char); if (unlikely(!p)) goto fail; p->header.ref_count = 1; p->is_wide_char = str->is_wide_char; p->len = str->len; p->kind = JS_STRING_KIND_NORMAL; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif memcpy(str8(p), str8(str), (str->len << str->is_wide_char) + 1 - str->is_wide_char); js_free_string(rt, str); } } else { p = js_malloc_rt(rt, sizeof(JSAtomStruct)); /* empty wide string */ if (!p) return JS_ATOM_NULL; p->header.ref_count = 1; p->is_wide_char = 1; /* Hack to represent NULL as a JSString */ p->len = 0; p->kind = JS_STRING_KIND_NORMAL; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif } /* use an already free entry */ i = rt->atom_free_index; rt->atom_free_index = atom_get_free(rt->atom_array[i]); rt->atom_array[i] = p; p->hash = h; p->hash_next = i; /* atom_index */ p->atom_type = atom_type; p->first_weak_ref = NULL; rt->atom_count++; if (atom_type != JS_ATOM_TYPE_SYMBOL) { p->hash_next = rt->atom_hash[h1]; rt->atom_hash[h1] = i; if (unlikely(rt->atom_count >= rt->atom_count_resize)) JS_ResizeAtomHash(rt, rt->atom_hash_size * 2); } // JS_DumpAtoms(rt); return i; fail: i = JS_ATOM_NULL; done: if (str) js_free_string(rt, str); return i; } // XXX: `str` must be pure ASCII. No UTF-8 encoded strings // XXX: `str` must not be the string representation of a small integer static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, int atom_type) { JSString *p; p = js_alloc_string_rt(rt, len, 0); if (!p) return JS_ATOM_NULL; memcpy(str8(p), str, len); str8(p)[len] = '\0'; return __JS_NewAtom(rt, p, atom_type); } // XXX: `str` must be raw 8-bit contents. No UTF-8 encoded strings static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, int atom_type) { uint32_t h, h1, i; JSAtomStruct *p; h = hash_string8((const uint8_t *)str, len, JS_ATOM_TYPE_STRING); h &= JS_ATOM_HASH_MASK; h1 = h & (rt->atom_hash_size - 1); i = rt->atom_hash[h1]; while (i != 0) { p = rt->atom_array[i]; if (p->hash == h && p->atom_type == JS_ATOM_TYPE_STRING && p->len == len && p->is_wide_char == 0 && memcmp(str8(p), str, len) == 0) { if (!__JS_AtomIsConst(i)) p->header.ref_count++; return i; } i = p->hash_next; } return JS_ATOM_NULL; } static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p) { uint32_t i = p->hash_next; /* atom_index */ if (p->atom_type != JS_ATOM_TYPE_SYMBOL) { JSAtomStruct *p0, *p1; uint32_t h0; h0 = p->hash & (rt->atom_hash_size - 1); i = rt->atom_hash[h0]; p1 = rt->atom_array[i]; if (p1 == p) { rt->atom_hash[h0] = p1->hash_next; } else { for(;;) { assert(i != 0); p0 = p1; i = p1->hash_next; p1 = rt->atom_array[i]; if (p1 == p) { p0->hash_next = p1->hash_next; break; } } } } /* insert in free atom list */ rt->atom_array[i] = atom_set_free(rt->atom_free_index); rt->atom_free_index = i; if (unlikely(p->first_weak_ref)) { reset_weak_ref(rt, &p->first_weak_ref); } /* free the string structure */ #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_del(&p->link); #endif js_free_rt(rt, p); rt->atom_count--; assert(rt->atom_count >= 0); } static void __JS_FreeAtom(JSRuntime *rt, uint32_t i) { JSAtomStruct *p; p = rt->atom_array[i]; if (--p->header.ref_count > 0) return; JS_FreeAtomStruct(rt, p); } /* Warning: 'p' is freed */ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p) { JSRuntime *rt = ctx->rt; uint32_t n; if (is_num_string(&n, p)) { if (n <= JS_ATOM_MAX_INT) { js_free_string(rt, p); return __JS_AtomFromUInt32(n); } } /* XXX: should generate an exception */ return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING); } /* `str` may be pure ASCII or UTF-8 encoded */ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len) { JSValue val; if (len == 0 || !is_digit(*str)) { // TODO(chqrlie): this does not work if `str` has UTF-8 encoded contents // bug example: `({ "\u00c3\u00a9": 1 }).\u00e9` evaluates to `1`. JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING); if (atom) return atom; } val = JS_NewStringLen(ctx, str, len); if (JS_IsException(val)) return JS_ATOM_NULL; return JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(val)); } /* `str` may be pure ASCII or UTF-8 encoded */ JSAtom JS_NewAtom(JSContext *ctx, const char *str) { return JS_NewAtomLen(ctx, str, strlen(str)); } JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n) { if (n <= JS_ATOM_MAX_INT) { return __JS_AtomFromUInt32(n); } else { char buf[16]; size_t len = u32toa(buf, n); JSValue val = js_new_string8_len(ctx, buf, len); if (JS_IsException(val)) return JS_ATOM_NULL; return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), JS_ATOM_TYPE_STRING); } } static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) { if ((uint64_t)n <= JS_ATOM_MAX_INT) { return __JS_AtomFromUInt32((uint32_t)n); } else { char buf[24]; size_t len = i64toa(buf, n); JSValue val = js_new_string8_len(ctx, buf, len); if (JS_IsException(val)) return JS_ATOM_NULL; return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), JS_ATOM_TYPE_STRING); } } /* 'p' is freed */ static JSValue JS_NewSymbolInternal(JSContext *ctx, JSString *p, int atom_type) { JSRuntime *rt = ctx->rt; JSAtom atom; atom = __JS_NewAtom(rt, p, atom_type); if (atom == JS_ATOM_NULL) return JS_ThrowOutOfMemory(ctx); return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]); } /* descr must be a non-numeric string atom */ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr, int atom_type) { JSRuntime *rt = ctx->rt; JSString *p; assert(!__JS_AtomIsTaggedInt(descr)); assert(descr < rt->atom_size); p = rt->atom_array[descr]; js_dup(JS_MKPTR(JS_TAG_STRING, p)); return JS_NewSymbolInternal(ctx, p, atom_type); } /* `description` may be pure ASCII or UTF-8 encoded */ JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global) { JSAtom atom = JS_NewAtom(ctx, description); if (atom == JS_ATOM_NULL) return JS_EXCEPTION; return JS_NewSymbolFromAtom(ctx, atom, is_global ? JS_ATOM_TYPE_GLOBAL_SYMBOL : JS_ATOM_TYPE_SYMBOL); } #define ATOM_GET_STR_BUF_SIZE 64 static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, JSAtom atom) { if (__JS_AtomIsTaggedInt(atom)) { snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); } else if (atom == JS_ATOM_NULL) { snprintf(buf, buf_size, ""); } else if (atom >= rt->atom_size) { assert(atom < rt->atom_size); snprintf(buf, buf_size, "", atom); } else { JSAtomStruct *p = rt->atom_array[atom]; *buf = '\0'; if (atom_is_free(p)) { snprintf(buf, buf_size, "", atom); } else if (p != NULL) { JSString *str = p; if (str->is_wide_char) { /* encode surrogates correctly */ utf8_encode_buf16(buf, buf_size, str16(str), str->len); } else { utf8_encode_buf8(buf, buf_size, str8(str), str->len); } } } return buf; } static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom atom) { return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom); } static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, bool force_string) { char buf[ATOM_GET_STR_BUF_SIZE]; if (__JS_AtomIsTaggedInt(atom)) { size_t len = u32toa(buf, __JS_AtomToUInt32(atom)); return js_new_string8_len(ctx, buf, len); } else { JSRuntime *rt = ctx->rt; JSAtomStruct *p; assert(atom < rt->atom_size); p = rt->atom_array[atom]; if (p->atom_type == JS_ATOM_TYPE_STRING) { goto ret_string; } else if (force_string) { if (p->len == 0 && p->is_wide_char != 0) { /* no description string */ p = rt->atom_array[JS_ATOM_empty_string]; } ret_string: return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } else { return js_dup(JS_MKPTR(JS_TAG_SYMBOL, p)); } } } JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom) { return __JS_AtomToValue(ctx, atom, false); } JSValue JS_AtomToString(JSContext *ctx, JSAtom atom) { return __JS_AtomToValue(ctx, atom, true); } /* return true if the atom is an array index (i.e. 0 <= index <= 2^32-2 and return its value */ static bool JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) { if (__JS_AtomIsTaggedInt(atom)) { *pval = __JS_AtomToUInt32(atom); return true; } else { JSRuntime *rt = ctx->rt; JSAtomStruct *p; uint32_t val; assert(atom < rt->atom_size); p = rt->atom_array[atom]; if (p->atom_type == JS_ATOM_TYPE_STRING && is_num_string(&val, p) && val != -1) { *pval = val; return true; } else { *pval = 0; return false; } } } /* This test must be fast if atom is not a numeric index (e.g. a method name). Return JS_UNDEFINED if not a numeric index. JS_EXCEPTION can also be returned. */ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) { JSRuntime *rt = ctx->rt; JSAtomStruct *p1; JSString *p; int c, len, ret; JSValue num, str; if (__JS_AtomIsTaggedInt(atom)) return js_int32(__JS_AtomToUInt32(atom)); assert(atom < rt->atom_size); p1 = rt->atom_array[atom]; if (p1->atom_type != JS_ATOM_TYPE_STRING) return JS_UNDEFINED; p = p1; len = p->len; if (p->is_wide_char) { const uint16_t *r = str16(p), *r_end = str16(p) + len; if (r >= r_end) return JS_UNDEFINED; c = *r; if (c == '-') { if (r >= r_end) return JS_UNDEFINED; r++; c = *r; /* -0 case is specific */ if (c == '0' && len == 2) goto minus_zero; } /* XXX: should test NaN, but the tests do not check it */ if (!is_num(c)) { /* XXX: String should be normalized, therefore 8-bit only */ const uint16_t nfinity16[7] = { 'n', 'f', 'i', 'n', 'i', 't', 'y' }; if (!(c =='I' && (r_end - r) == 8 && !memcmp(r + 1, nfinity16, sizeof(nfinity16)))) return JS_UNDEFINED; } } else { const uint8_t *r = str8(p), *r_end = str8(p) + len; if (r >= r_end) return JS_UNDEFINED; c = *r; if (c == '-') { if (r >= r_end) return JS_UNDEFINED; r++; c = *r; /* -0 case is specific */ if (c == '0' && len == 2) { minus_zero: return js_float64(-0.0); } } if (!is_num(c)) { if (!(c =='I' && (r_end - r) == 8 && !memcmp(r + 1, "nfinity", 7))) return JS_UNDEFINED; } } /* this is ECMA CanonicalNumericIndexString primitive */ num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p)); if (JS_IsException(num)) return num; str = JS_ToString(ctx, num); if (JS_IsException(str)) { JS_FreeValue(ctx, num); return str; } ret = js_string_eq(p, JS_VALUE_GET_STRING(str)); JS_FreeValue(ctx, str); if (ret) { return num; } else { JS_FreeValue(ctx, num); return JS_UNDEFINED; } } /* return -1 if exception or true/false */ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom) { JSValue num; num = JS_AtomIsNumericIndex1(ctx, atom); if (likely(JS_IsUndefined(num))) return false; if (JS_IsException(num)) return -1; JS_FreeValue(ctx, num); return true; } void JS_FreeAtom(JSContext *ctx, JSAtom v) { if (!__JS_AtomIsConst(v)) __JS_FreeAtom(ctx->rt, v); } void JS_FreeAtomRT(JSRuntime *rt, JSAtom v) { if (!__JS_AtomIsConst(v)) __JS_FreeAtom(rt, v); } /* return true if 'v' is a symbol with a string description */ static bool JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) { JSRuntime *rt; JSAtomStruct *p; rt = ctx->rt; if (__JS_AtomIsTaggedInt(v)) return false; p = rt->atom_array[v]; return (((p->atom_type == JS_ATOM_TYPE_SYMBOL && p->hash == JS_ATOM_HASH_SYMBOL) || p->atom_type == JS_ATOM_TYPE_GLOBAL_SYMBOL) && !(p->len == 0 && p->is_wide_char != 0)); } static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom) { char buf[ATOM_GET_STR_BUF_SIZE]; const char *p; int i; /* XXX: should handle embedded null characters */ /* XXX: should move encoding code to JS_AtomGetStr */ p = JS_AtomGetStr(ctx, buf, sizeof(buf), atom); for (i = 0; p[i]; i++) { int c = (unsigned char)p[i]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0))) break; } if (i > 0 && p[i] == '\0') { printf("%s", p); } else { putchar('"'); printf("%.*s", i, p); for (; p[i]; i++) { int c = (unsigned char)p[i]; if (c == '\"' || c == '\\') { putchar('\\'); putchar(c); } else if (c >= ' ' && c <= 126) { putchar(c); } else if (c == '\n') { putchar('\\'); putchar('n'); } else { printf("\\u%04x", c); } } putchar('\"'); } } /* free with JS_FreeCString() */ const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom) { JSValue str; const char *cstr; str = JS_AtomToString(ctx, atom); if (JS_IsException(str)) { if (plen) *plen = 0; return NULL; } cstr = JS_ToCStringLen(ctx, plen, str); JS_FreeValue(ctx, str); return cstr; } #ifndef QJS_DISABLE_PARSER /* return a string atom containing name concatenated with str1 */ /* `str1` may be pure ASCII or UTF-8 encoded */ // TODO(chqrlie): use string concatenation instead of UTF-8 conversion static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) { JSValue str; JSAtom atom; const char *cstr; char *cstr2; size_t len, len1; str = JS_AtomToString(ctx, name); if (JS_IsException(str)) return JS_ATOM_NULL; cstr = JS_ToCStringLen(ctx, &len, str); if (!cstr) goto fail; len1 = strlen(str1); cstr2 = js_malloc(ctx, len + len1 + 1); if (!cstr2) goto fail; memcpy(cstr2, cstr, len); memcpy(cstr2 + len, str1, len1); cstr2[len + len1] = '\0'; atom = JS_NewAtomLen(ctx, cstr2, len + len1); js_free(ctx, cstr2); JS_FreeCString(ctx, cstr); JS_FreeValue(ctx, str); return atom; fail: JS_FreeCString(ctx, cstr); JS_FreeValue(ctx, str); return JS_ATOM_NULL; } static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n) { char buf[16]; size_t len; len = u32toa(buf, n); buf[len] = '\0'; return js_atom_concat_str(ctx, name, buf); } #endif // QJS_DISABLE_PARSER static inline bool JS_IsEmptyString(JSValueConst v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0; } /* JSClass support */ /* a new class ID is allocated if *pclass_id == 0, otherwise *pclass_id is left unchanged */ JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id) { JSClassID class_id = *pclass_id; if (class_id == 0) { class_id = rt->js_class_id_alloc++; *pclass_id = class_id; } return class_id; } JSClassID JS_GetClassID(JSValueConst v) { JSObject *p; if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) return JS_INVALID_CLASS_ID; p = JS_VALUE_GET_OBJ(v); return p->class_id; } bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id) { return (class_id < rt->class_count && rt->class_array[class_id].class_id != 0); } /* create a new object internal class. Return -1 if error, 0 if OK. The finalizer can be NULL if none is needed. */ static int JS_NewClass1(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, JSAtom name) { int new_size, i; JSClass *cl, *new_class_array; struct list_head *el; if (class_id >= (1 << 16)) return -1; if (class_id < rt->class_count && rt->class_array[class_id].class_id != 0) return -1; if (class_id >= rt->class_count) { new_size = max_int(JS_CLASS_INIT_COUNT, max_int(class_id + 1, rt->class_count * 3 / 2)); /* reallocate the context class prototype array, if any */ list_for_each(el, &rt->context_list) { JSContext *ctx = list_entry(el, JSContext, link); JSValue *new_tab; new_tab = js_realloc_rt(rt, ctx->class_proto, sizeof(ctx->class_proto[0]) * new_size); if (!new_tab) return -1; for(i = rt->class_count; i < new_size; i++) new_tab[i] = JS_NULL; ctx->class_proto = new_tab; } /* reallocate the class array */ new_class_array = js_realloc_rt(rt, rt->class_array, sizeof(JSClass) * new_size); if (!new_class_array) return -1; memset(new_class_array + rt->class_count, 0, (new_size - rt->class_count) * sizeof(JSClass)); rt->class_array = new_class_array; rt->class_count = new_size; } cl = &rt->class_array[class_id]; cl->class_id = class_id; cl->class_name = JS_DupAtomRT(rt, name); cl->finalizer = class_def->finalizer; cl->gc_mark = class_def->gc_mark; cl->call = class_def->call; cl->exotic = class_def->exotic; return 0; } int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def) { int ret, len; JSAtom name; // XXX: class_def->class_name must be raw 8-bit contents. No UTF-8 encoded strings len = strlen(class_def->class_name); name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING); if (name == JS_ATOM_NULL) { name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING); if (name == JS_ATOM_NULL) return -1; } ret = JS_NewClass1(rt, class_id, class_def, name); JS_FreeAtomRT(rt, name); return ret; } static inline JSValue js_empty_string(JSRuntime *rt) { JSAtomStruct *p = rt->atom_array[JS_ATOM_empty_string]; return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } // XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed // XXX: no special case for len == 0 static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len) { JSString *str; str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; memcpy(str8(str), buf, len); str8(str)[len] = '\0'; return JS_MKPTR(JS_TAG_STRING, str); } // XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed // XXX: no special case for the empty string static inline JSValue js_new_string8(JSContext *ctx, const char *str) { return js_new_string8_len(ctx, str, strlen(str)); } static JSValue js_new_string16_len(JSContext *ctx, const uint16_t *buf, int len) { JSString *str; str = js_alloc_string(ctx, len, 1); if (!str) return JS_EXCEPTION; memcpy(str16(str), buf, len * 2); return JS_MKPTR(JS_TAG_STRING, str); } static JSValue js_new_string_char(JSContext *ctx, uint16_t c) { if (c < 0x100) { char ch8 = c; return js_new_string8_len(ctx, &ch8, 1); } else { uint16_t ch16 = c; return js_new_string16_len(ctx, &ch16, 1); } } static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) { JSStringSlice *slice; JSString *q; int len; len = end - start; if (start == 0 && end == p->len) { return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } if (len <= 0) { return js_empty_string(ctx->rt); } if (len > (JS_STRING_SLICE_LEN_MAX >> p->is_wide_char)) { if (p->kind == JS_STRING_KIND_SLICE) { slice = (void *)&p[1]; p = slice->parent; start += slice->start >> p->is_wide_char; // bytes -> chars } // allocate as 16 bit wide string to avoid wastage; // js_alloc_string allocates 1 byte extra for 8 bit strings; q = js_alloc_string(ctx, sizeof(*slice)/2, /*is_wide_char*/true); if (!q) return JS_EXCEPTION; q->is_wide_char = p->is_wide_char; q->kind = JS_STRING_KIND_SLICE; q->len = len; slice = (void *)&q[1]; slice->parent = p; slice->start = start << p->is_wide_char; // chars -> bytes p->header.ref_count++; return JS_MKPTR(JS_TAG_STRING, q); } if (p->is_wide_char) { JSString *str; int i; uint16_t c = 0; for (i = start; i < end; i++) { c |= str16(p)[i]; } if (c > 0xFF) return js_new_string16_len(ctx, str16(p) + start, len); str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; for (i = 0; i < len; i++) { str8(str)[i] = str16(p)[start + i]; } str8(str)[len] = '\0'; return JS_MKPTR(JS_TAG_STRING, str); } else { return js_new_string8_len(ctx, (const char *)(str8(p) + start), len); } } typedef struct StringBuffer { JSContext *ctx; JSString *str; int len; int size; int is_wide_char; int error_status; } StringBuffer; /* It is valid to call string_buffer_end() and all string_buffer functions even if string_buffer_init() or another string_buffer function returns an error. If the error_status is set, string_buffer_end() returns JS_EXCEPTION. */ static int string_buffer_init2(JSContext *ctx, StringBuffer *s, int size, int is_wide) { s->ctx = ctx; s->size = size; s->len = 0; s->is_wide_char = is_wide; s->error_status = 0; s->str = js_alloc_string(ctx, size, is_wide); if (unlikely(!s->str)) { s->size = 0; return s->error_status = -1; } #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS /* the StringBuffer may reallocate the JSString, only link it at the end */ list_del(&s->str->link); #endif return 0; } static inline int string_buffer_init(JSContext *ctx, StringBuffer *s, int size) { return string_buffer_init2(ctx, s, size, 0); } static void string_buffer_free(StringBuffer *s) { js_free(s->ctx, s->str); s->str = NULL; } static int string_buffer_set_error(StringBuffer *s) { js_free(s->ctx, s->str); s->str = NULL; s->size = 0; s->len = 0; return s->error_status = -1; } static no_inline int string_buffer_widen(StringBuffer *s, int size) { JSString *str; size_t slack; int i; if (s->error_status) return -1; str = js_realloc2(s->ctx, s->str, sizeof(JSString) + (size << 1), &slack); if (!str) return string_buffer_set_error(s); size += slack >> 1; for(i = s->len; i-- > 0;) { str16(str)[i] = str8(str)[i]; } s->is_wide_char = 1; s->size = size; s->str = str; return 0; } static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) { JSString *new_str; int new_size; size_t new_size_bytes, slack; if (s->error_status) return -1; if (new_len > JS_STRING_LEN_MAX) { JS_ThrowRangeError(s->ctx, "invalid string length"); return string_buffer_set_error(s); } new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX); if (!s->is_wide_char && c >= 0x100) { return string_buffer_widen(s, new_size); } new_size_bytes = sizeof(JSString) + (new_size << s->is_wide_char) + 1 - s->is_wide_char; new_str = js_realloc2(s->ctx, s->str, new_size_bytes, &slack); if (!new_str) return string_buffer_set_error(s); new_size = min_int(new_size + (slack >> s->is_wide_char), JS_STRING_LEN_MAX); s->size = new_size; s->str = new_str; return 0; } static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c) { if (unlikely(s->len >= s->size)) { if (string_buffer_realloc(s, s->len + 1, c)) return -1; } if (s->is_wide_char) { str16(s->str)[s->len++] = c; } else if (c < 0x100) { str8(s->str)[s->len++] = c; } else { if (string_buffer_widen(s, s->size)) return -1; str16(s->str)[s->len++] = c; } return 0; } /* 0 <= c <= 0xff */ static int string_buffer_putc8(StringBuffer *s, uint32_t c) { if (unlikely(s->len >= s->size)) { if (string_buffer_realloc(s, s->len + 1, c)) return -1; } if (s->is_wide_char) { str16(s->str)[s->len++] = c; } else { str8(s->str)[s->len++] = c; } return 0; } /* 0 <= c <= 0xffff */ static int string_buffer_putc16(StringBuffer *s, uint32_t c) { if (likely(s->len < s->size)) { if (s->is_wide_char) { str16(s->str)[s->len++] = c; return 0; } else if (c < 0x100) { str8(s->str)[s->len++] = c; return 0; } } return string_buffer_putc_slow(s, c); } /* 0 <= c <= 0x10ffff */ static int string_buffer_putc(StringBuffer *s, uint32_t c) { if (unlikely(c >= 0x10000)) { /* surrogate pair */ if (string_buffer_putc16(s, get_hi_surrogate(c))) return -1; c = get_lo_surrogate(c); } return string_buffer_putc16(s, c); } static int string_getc(JSString *p, int *pidx) { int idx, c, c1; idx = *pidx; if (p->is_wide_char) { c = str16(p)[idx++]; if (is_hi_surrogate(c) && idx < p->len) { c1 = str16(p)[idx]; if (is_lo_surrogate(c1)) { c = from_surrogate(c, c1); idx++; } } } else { c = str8(p)[idx++]; } *pidx = idx; return c; } static int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len) { int i; if (s->len + len > s->size) { if (string_buffer_realloc(s, s->len + len, 0)) return -1; } if (s->is_wide_char) { for (i = 0; i < len; i++) { str16(s->str)[s->len + i] = p[i]; } s->len += len; } else { memcpy(&str8(s->str)[s->len], p, len); s->len += len; } return 0; } static int string_buffer_write16(StringBuffer *s, const uint16_t *p, int len) { int c = 0, i; for (i = 0; i < len; i++) { c |= p[i]; } if (s->len + len > s->size) { if (string_buffer_realloc(s, s->len + len, c)) return -1; } else if (!s->is_wide_char && c >= 0x100) { if (string_buffer_widen(s, s->size)) return -1; } if (s->is_wide_char) { memcpy(&str16(s->str)[s->len], p, len << 1); s->len += len; } else { for (i = 0; i < len; i++) { str8(s->str)[s->len + i] = p[i]; } s->len += len; } return 0; } /* appending an ASCII string */ static int string_buffer_puts8(StringBuffer *s, const char *str) { return string_buffer_write8(s, (const uint8_t *)str, strlen(str)); } static int string_buffer_concat(StringBuffer *s, JSString *p, uint32_t from, uint32_t to) { if (to <= from) return 0; if (p->is_wide_char) return string_buffer_write16(s, str16(p) + from, to - from); else return string_buffer_write8(s, str8(p) + from, to - from); } static int string_buffer_concat_value(StringBuffer *s, JSValueConst v) { JSString *p; JSValue v1; int res; if (s->error_status) { /* prevent exception overload */ return -1; } if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) { v1 = JS_ToString(s->ctx, v); if (JS_IsException(v1)) return string_buffer_set_error(s); p = JS_VALUE_GET_STRING(v1); res = string_buffer_concat(s, p, 0, p->len); JS_FreeValue(s->ctx, v1); return res; } p = JS_VALUE_GET_STRING(v); return string_buffer_concat(s, p, 0, p->len); } static int string_buffer_concat_value_free(StringBuffer *s, JSValue v) { JSString *p; int res; if (s->error_status) { /* prevent exception overload */ JS_FreeValue(s->ctx, v); return -1; } if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) { v = JS_ToStringFree(s->ctx, v); if (JS_IsException(v)) return string_buffer_set_error(s); } p = JS_VALUE_GET_STRING(v); res = string_buffer_concat(s, p, 0, p->len); JS_FreeValue(s->ctx, v); return res; } static int string_buffer_fill(StringBuffer *s, int c, int count) { /* XXX: optimize */ if (s->len + count > s->size) { if (string_buffer_realloc(s, s->len + count, c)) return -1; } while (count-- > 0) { if (string_buffer_putc16(s, c)) return -1; } return 0; } static JSValue string_buffer_end(StringBuffer *s) { JSString *str; str = s->str; if (s->error_status) return JS_EXCEPTION; if (s->len == 0) { js_free(s->ctx, str); s->str = NULL; return js_empty_string(s->ctx->rt); } if (s->len < s->size) { /* smaller size so js_realloc should not fail, but OK if it does */ /* XXX: should add some slack to avoid unnecessary calls */ /* XXX: might need to use malloc+free to ensure smaller size */ str = js_realloc_rt(s->ctx->rt, str, sizeof(JSString) + (s->len << s->is_wide_char) + 1 - s->is_wide_char); if (str == NULL) str = s->str; s->str = str; } if (!s->is_wide_char) str8(str)[s->len] = 0; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&str->link, &s->ctx->rt->string_list); #endif str->is_wide_char = s->is_wide_char; str->len = s->len; s->str = NULL; return JS_MKPTR(JS_TAG_STRING, str); } /* create a string from a UTF-8 buffer */ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) { JSString *str; size_t len; int kind; if (buf_len <= 0) { return js_empty_string(ctx->rt); } /* Compute string kind and length: 7-bit, 8-bit, 16-bit, 16-bit UTF-16 */ kind = utf8_scan(buf, buf_len, &len); if (len > JS_STRING_LEN_MAX) return JS_ThrowRangeError(ctx, "invalid string length"); switch (kind) { case UTF8_PLAIN_ASCII: str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; memcpy(str8(str), buf, len); str8(str)[len] = '\0'; break; case UTF8_NON_ASCII: /* buf contains non-ASCII code-points, but limited to 8-bit values */ str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; utf8_decode_buf8(str8(str), len + 1, buf, buf_len); break; default: // This causes a potential problem in JS_ThrowError if message is invalid //if (kind & UTF8_HAS_ERRORS) // return JS_ThrowRangeError(ctx, "invalid UTF-8 sequence"); str = js_alloc_string(ctx, len, 1); if (!str) return JS_EXCEPTION; utf8_decode_buf16(str16(str), len, buf, buf_len); break; } return JS_MKPTR(JS_TAG_STRING, str); } JSValue JS_NewTwoByteString(JSContext *ctx, const uint16_t *buf, size_t len) { JSString *str; if (!len) return js_empty_string(ctx->rt); str = js_alloc_string(ctx, len, 1); if (!str) return JS_EXCEPTION; memcpy(str16(str), buf, len * sizeof(*buf)); return JS_MKPTR(JS_TAG_STRING, str); } static JSValue JS_ConcatString3(JSContext *ctx, const char *str1, JSValue str2, const char *str3) { StringBuffer b_s, *b = &b_s; int len1, len3; JSString *p; if (unlikely(JS_VALUE_GET_TAG(str2) != JS_TAG_STRING)) { str2 = JS_ToStringFree(ctx, str2); if (JS_IsException(str2)) goto fail; } p = JS_VALUE_GET_STRING(str2); len1 = strlen(str1); len3 = strlen(str3); if (string_buffer_init2(ctx, b, len1 + p->len + len3, p->is_wide_char)) goto fail; string_buffer_write8(b, (const uint8_t *)str1, len1); string_buffer_concat(b, p, 0, p->len); string_buffer_write8(b, (const uint8_t *)str3, len3); JS_FreeValue(ctx, str2); return string_buffer_end(b); fail: JS_FreeValue(ctx, str2); return JS_EXCEPTION; } /* `str` may be pure ASCII or UTF-8 encoded */ JSValue JS_NewAtomString(JSContext *ctx, const char *str) { JSAtom atom = JS_NewAtom(ctx, str); if (atom == JS_ATOM_NULL) return JS_EXCEPTION; JSValue val = JS_AtomToString(ctx, atom); JS_FreeAtom(ctx, atom); return val; } /* return (NULL, 0) if exception. */ /* return pointer into a JSString with a live ref_count */ /* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, bool cesu8) { JSValue val; JSString *str, *str_new; int pos, len, c, c1; JSObject *p; uint8_t *q; if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) { val = js_dup(val1); goto go; } val = JS_ToString(ctx, val1); if (!JS_IsException(val)) goto go; // Stringification can fail when there is an exception pending, // e.g. a stack overflow InternalError. Special-case exception // objects to make debugging easier, look up the .message property // and stringify that. if (JS_VALUE_GET_TAG(val1) != JS_TAG_OBJECT) goto fail; p = JS_VALUE_GET_OBJ(val1); if (p->class_id != JS_CLASS_ERROR) goto fail; val = JS_GetProperty(ctx, val1, JS_ATOM_message); if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) { JS_FreeValue(ctx, val); goto fail; } go: str = JS_VALUE_GET_STRING(val); len = str->len; if (!str->is_wide_char) { const uint8_t *src = str8(str); int count; /* count the number of non-ASCII characters */ /* Scanning the whole string is required for ASCII strings, and computing the number of non-ASCII bytes is less expensive than testing each byte, hence this method is faster for ASCII strings, which is the most common case. */ count = 0; for (pos = 0; pos < len; pos++) { count += src[pos] >> 7; } if (count == 0 && str->kind == JS_STRING_KIND_NORMAL) { if (plen) *plen = len; return (const char *)src; } str_new = js_alloc_string(ctx, len + count, 0); if (!str_new) goto fail; q = str8(str_new); for (pos = 0; pos < len; pos++) { c = src[pos]; if (c < 0x80) { *q++ = c; } else { *q++ = (c >> 6) | 0xc0; *q++ = (c & 0x3f) | 0x80; } } } else { const uint16_t *src = str16(str); /* Allocate 3 bytes per 16 bit code point. Surrogate pairs may produce 4 bytes but use 2 code points. */ str_new = js_alloc_string(ctx, len * 3, 0); if (!str_new) goto fail; q = str8(str_new); pos = 0; while (pos < len) { c = src[pos++]; if (c < 0x80) { *q++ = c; } else { if (is_hi_surrogate(c)) { if (pos < len && !cesu8) { c1 = src[pos]; if (is_lo_surrogate(c1)) { pos++; c = from_surrogate(c, c1); } else { /* Keep unmatched surrogate code points */ /* c = 0xfffd; */ /* error */ } } else { /* Keep unmatched surrogate code points */ /* c = 0xfffd; */ /* error */ } } q += utf8_encode(q, c); } } } *q = '\0'; str_new->len = q - str8(str_new); JS_FreeValue(ctx, val); if (plen) *plen = str_new->len; return (const char *)str8(str_new); fail: if (plen) *plen = 0; return NULL; } void JS_FreeCString(JSContext *ctx, const char *ptr) { if (!ptr) return; /* purposely removing constness */ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, (JSString *)ptr - 1)); } static int memcmp16_8(const uint16_t *src1, const uint8_t *src2, int len) { int c, i; for(i = 0; i < len; i++) { c = src1[i] - src2[i]; if (c != 0) return c; } return 0; } static int memcmp16(const uint16_t *src1, const uint16_t *src2, int len) { int c, i; for(i = 0; i < len; i++) { c = src1[i] - src2[i]; if (c != 0) return c; } return 0; } static int js_string_memcmp(JSString *p1, JSString *p2, int len) { int res; if (likely(!p1->is_wide_char)) { if (likely(!p2->is_wide_char)) res = memcmp(str8(p1), str8(p2), len); else res = -memcmp16_8(str16(p2), str8(p1), len); } else { if (!p2->is_wide_char) res = memcmp16_8(str16(p1), str8(p2), len); else res = memcmp16(str16(p1), str16(p2), len); } return res; } static bool js_string_eq(JSString *p1, JSString *p2) { if (p1->len != p2->len) return false; return js_string_memcmp(p1, p2, p1->len) == 0; } /* return < 0, 0 or > 0 */ static int js_string_compare(JSString *p1, JSString *p2) { int res, len; len = min_int(p1->len, p2->len); res = js_string_memcmp(p1, p2, len); if (res == 0) res = compare_u32(p1->len, p2->len); return res; } static void copy_str16(uint16_t *dst, JSString *p, int offset, int len) { if (p->is_wide_char) { memcpy(dst, str16(p) + offset, len * 2); } else { const uint8_t *src1 = str8(p) + offset; int i; for(i = 0; i < len; i++) dst[i] = src1[i]; } } static JSValue JS_ConcatString1(JSContext *ctx, JSString *p1, JSString *p2) { JSString *p; uint32_t len; int is_wide_char; len = p1->len + p2->len; if (len > JS_STRING_LEN_MAX) return JS_ThrowRangeError(ctx, "invalid string length"); is_wide_char = p1->is_wide_char | p2->is_wide_char; p = js_alloc_string(ctx, len, is_wide_char); if (!p) return JS_EXCEPTION; if (!is_wide_char) { memcpy(str8(p), str8(p1), p1->len); memcpy(str8(p) + p1->len, str8(p2), p2->len); str8(p)[len] = '\0'; } else { copy_str16(str16(p), p1, 0, p1->len); copy_str16(str16(p) + p1->len, p2, 0, p2->len); } return JS_MKPTR(JS_TAG_STRING, p); } /* op1 and op2 are converted to strings. For convience, op1 or op2 = JS_EXCEPTION are accepted and return JS_EXCEPTION. */ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) { JSValue ret; JSString *p1, *p2; if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING)) { op1 = JS_ToStringFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); return JS_EXCEPTION; } } if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING)) { op2 = JS_ToStringFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); return JS_EXCEPTION; } } p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); /* XXX: could also check if p1 is empty */ if (p2->len == 0) { goto ret_op1; } if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) { /* Concatenate in place in available space at the end of p1 */ if (p1->is_wide_char) { memcpy(str16(p1) + p1->len, str16(p2), p2->len << 1); p1->len += p2->len; } else { memcpy(str8(p1) + p1->len, str8(p2), p2->len); p1->len += p2->len; str8(p1)[p1->len] = '\0'; } ret_op1: JS_FreeValue(ctx, op2); return op1; } ret = JS_ConcatString1(ctx, p1, p2); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); return ret; } /* Shape support */ static inline size_t get_shape_size(size_t hash_size, size_t prop_size) { return hash_size * sizeof(uint32_t) + sizeof(JSShape) + prop_size * sizeof(JSShapeProperty); } static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size) { return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size); } static inline uint32_t *prop_hash_end(JSShape *sh) { return (uint32_t *)sh; } static inline void *get_alloc_from_shape(JSShape *sh) { return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1); } static inline JSShapeProperty *get_shape_prop(JSShape *sh) { return sh->prop; } static int init_shape_hash(JSRuntime *rt) { rt->shape_hash_bits = 6; /* 64 shapes */ rt->shape_hash_size = 1 << rt->shape_hash_bits; rt->shape_hash_count = 0; rt->shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) * rt->shape_hash_size); if (!rt->shape_hash) return -1; return 0; } /* same magic hash multiplier as the Linux kernel */ static uint32_t shape_hash(uint32_t h, uint32_t val) { return (h + val) * 0x9e370001; } /* truncate the shape hash to 'hash_bits' bits */ static uint32_t get_shape_hash(uint32_t h, int hash_bits) { return h >> (32 - hash_bits); } static uint32_t shape_initial_hash(JSObject *proto) { uint32_t h; h = shape_hash(1, (uintptr_t)proto); if (sizeof(proto) > 4) h = shape_hash(h, (uint64_t)(uintptr_t)proto >> 32); return h; } static int resize_shape_hash(JSRuntime *rt, int new_shape_hash_bits) { int new_shape_hash_size, i; uint32_t h; JSShape **new_shape_hash, *sh, *sh_next; new_shape_hash_size = 1 << new_shape_hash_bits; new_shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) * new_shape_hash_size); if (!new_shape_hash) return -1; for(i = 0; i < rt->shape_hash_size; i++) { for(sh = rt->shape_hash[i]; sh != NULL; sh = sh_next) { sh_next = sh->shape_hash_next; h = get_shape_hash(sh->hash, new_shape_hash_bits); sh->shape_hash_next = new_shape_hash[h]; new_shape_hash[h] = sh; } } js_free_rt(rt, rt->shape_hash); rt->shape_hash_bits = new_shape_hash_bits; rt->shape_hash_size = new_shape_hash_size; rt->shape_hash = new_shape_hash; return 0; } static void js_shape_hash_link(JSRuntime *rt, JSShape *sh) { uint32_t h; h = get_shape_hash(sh->hash, rt->shape_hash_bits); sh->shape_hash_next = rt->shape_hash[h]; rt->shape_hash[h] = sh; rt->shape_hash_count++; } static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh) { uint32_t h; JSShape **psh; h = get_shape_hash(sh->hash, rt->shape_hash_bits); psh = &rt->shape_hash[h]; while (*psh != sh) psh = &(*psh)->shape_hash_next; *psh = sh->shape_hash_next; rt->shape_hash_count--; } /* create a new empty shape with prototype 'proto' */ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, int hash_size, int prop_size) { JSRuntime *rt = ctx->rt; void *sh_alloc; JSShape *sh; /* resize the shape hash table if necessary */ if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { resize_shape_hash(rt, rt->shape_hash_bits + 1); } sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size)); if (!sh_alloc) return NULL; sh = get_shape_from_alloc(sh_alloc, hash_size); sh->header.ref_count = 1; add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); if (proto) js_dup(JS_MKPTR(JS_TAG_OBJECT, proto)); sh->proto = proto; memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) * hash_size); sh->prop_hash_mask = hash_size - 1; sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = true; sh->has_small_array_index = false; js_shape_hash_link(ctx->rt, sh); return sh; } static JSShape *js_new_shape(JSContext *ctx, JSObject *proto) { return js_new_shape2(ctx, proto, JS_PROP_INITIAL_HASH_SIZE, JS_PROP_INITIAL_SIZE); } /* The shape is cloned. The new shape is not inserted in the shape hash table */ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) { JSShape *sh; void *sh_alloc, *sh_alloc1; size_t size; JSShapeProperty *pr; uint32_t i, hash_size; hash_size = sh1->prop_hash_mask + 1; size = get_shape_size(hash_size, sh1->prop_size); sh_alloc = js_malloc(ctx, size); if (!sh_alloc) return NULL; sh_alloc1 = get_alloc_from_shape(sh1); memcpy(sh_alloc, sh_alloc1, size); sh = get_shape_from_alloc(sh_alloc, hash_size); sh->header.ref_count = 1; add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); sh->is_hashed = false; if (sh->proto) { js_dup(JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { JS_DupAtom(ctx, pr->atom); } return sh; } static JSShape *js_dup_shape(JSShape *sh) { sh->header.ref_count++; return sh; } static void js_free_shape0(JSRuntime *rt, JSShape *sh) { uint32_t i; JSShapeProperty *pr; assert(sh->header.ref_count == 0); if (sh->is_hashed) js_shape_hash_unlink(rt, sh); if (sh->proto != NULL) { JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } pr = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JS_FreeAtomRT(rt, pr->atom); pr++; } remove_gc_object(&sh->header); js_free_rt(rt, get_alloc_from_shape(sh)); } static void js_free_shape(JSRuntime *rt, JSShape *sh) { if (unlikely(--sh->header.ref_count <= 0)) { js_free_shape0(rt, sh); } } static void js_free_shape_null(JSRuntime *rt, JSShape *sh) { if (sh) js_free_shape(rt, sh); } /* make space to hold at least 'count' properties */ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, JSObject *p, uint32_t count) { JSShape *sh; uint32_t new_size, new_hash_size, new_hash_mask, i; JSShapeProperty *pr; void *sh_alloc; intptr_t h; sh = *psh; new_size = max_int(count, sh->prop_size * 3 / 2); /* Reallocate prop array first to avoid crash or size inconsistency in case of memory allocation failure */ if (p) { JSProperty *new_prop; new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size); if (unlikely(!new_prop)) return -1; p->prop = new_prop; } new_hash_size = sh->prop_hash_mask + 1; while (new_hash_size < new_size) new_hash_size = 2 * new_hash_size; if (new_hash_size != (sh->prop_hash_mask + 1)) { JSShape *old_sh; /* resize the hash table and the properties */ old_sh = sh; sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); if (!sh_alloc) return -1; sh = get_shape_from_alloc(sh_alloc, new_hash_size); list_del(&old_sh->header.link); /* copy all the fields and the properties */ memcpy(sh, old_sh, sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); new_hash_mask = new_hash_size - 1; sh->prop_hash_mask = new_hash_mask; memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL) { h = ((uintptr_t)pr->atom & new_hash_mask); pr->hash_next = prop_hash_end(sh)[-h - 1]; prop_hash_end(sh)[-h - 1] = i + 1; } } js_free(ctx, get_alloc_from_shape(old_sh)); } else { /* only resize the properties */ list_del(&sh->header.link); sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh), get_shape_size(new_hash_size, new_size)); if (unlikely(!sh_alloc)) { /* insert again in the GC list */ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); return -1; } sh = get_shape_from_alloc(sh_alloc, new_hash_size); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); } *psh = sh; sh->prop_size = new_size; return 0; } /* remove the deleted properties. */ static int compact_properties(JSContext *ctx, JSObject *p) { JSShape *sh, *old_sh; void *sh_alloc; intptr_t h; uint32_t new_hash_size, i, j, new_hash_mask, new_size; JSShapeProperty *old_pr, *pr; JSProperty *prop, *new_prop; sh = p->shape; assert(!sh->is_hashed); new_size = max_int(JS_PROP_INITIAL_SIZE, sh->prop_count - sh->deleted_prop_count); assert(new_size <= sh->prop_size); new_hash_size = sh->prop_hash_mask + 1; while ((new_hash_size / 2) >= new_size) new_hash_size = new_hash_size / 2; new_hash_mask = new_hash_size - 1; /* resize the hash table and the properties */ old_sh = sh; sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); if (!sh_alloc) return -1; sh = get_shape_from_alloc(sh_alloc, new_hash_size); list_del(&old_sh->header.link); memcpy(sh, old_sh, sizeof(JSShape)); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); j = 0; old_pr = old_sh->prop; pr = sh->prop; prop = p->prop; for(i = 0; i < sh->prop_count; i++) { if (old_pr->atom != JS_ATOM_NULL) { pr->atom = old_pr->atom; pr->flags = old_pr->flags; h = ((uintptr_t)old_pr->atom & new_hash_mask); pr->hash_next = prop_hash_end(sh)[-h - 1]; prop_hash_end(sh)[-h - 1] = j + 1; prop[j] = prop[i]; j++; pr++; } old_pr++; } assert(j == (sh->prop_count - sh->deleted_prop_count)); sh->prop_hash_mask = new_hash_mask; sh->prop_size = new_size; sh->deleted_prop_count = 0; sh->prop_count = j; p->shape = sh; js_free(ctx, get_alloc_from_shape(old_sh)); /* reduce the size of the object properties */ new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size); if (new_prop) p->prop = new_prop; return 0; } static int add_shape_property(JSContext *ctx, JSShape **psh, JSObject *p, JSAtom atom, int prop_flags) { JSRuntime *rt = ctx->rt; JSShape *sh = *psh; JSShapeProperty *pr, *prop; uint32_t hash_mask, new_shape_hash = 0; intptr_t h; /* update the shape hash */ if (sh->is_hashed) { js_shape_hash_unlink(rt, sh); new_shape_hash = shape_hash(shape_hash(sh->hash, atom), prop_flags); } if (unlikely(sh->prop_count >= sh->prop_size)) { if (resize_properties(ctx, psh, p, sh->prop_count + 1)) { /* in case of error, reinsert in the hash table. sh is still valid if resize_properties() failed */ if (sh->is_hashed) js_shape_hash_link(rt, sh); return -1; } sh = *psh; } if (sh->is_hashed) { sh->hash = new_shape_hash; js_shape_hash_link(rt, sh); } /* Initialize the new shape property. The object property at p->prop[sh->prop_count] is uninitialized */ prop = get_shape_prop(sh); pr = &prop[sh->prop_count++]; pr->atom = JS_DupAtom(ctx, atom); pr->flags = prop_flags; sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); /* add in hash table */ hash_mask = sh->prop_hash_mask; h = atom & hash_mask; pr->hash_next = prop_hash_end(sh)[-h - 1]; prop_hash_end(sh)[-h - 1] = sh->prop_count; return 0; } /* find a hashed empty shape matching the prototype. Return NULL if not found */ static JSShape *find_hashed_shape_proto(JSRuntime *rt, JSObject *proto) { JSShape *sh1; uint32_t h, h1; h = shape_initial_hash(proto); h1 = get_shape_hash(h, rt->shape_hash_bits); for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) { if (sh1->hash == h && sh1->proto == proto && sh1->prop_count == 0) { return sh1; } } return NULL; } /* find a hashed shape matching sh + (prop, prop_flags). Return NULL if not found */ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh, JSAtom atom, int prop_flags) { JSShape *sh1; uint32_t h, h1, i, n; h = sh->hash; h = shape_hash(h, atom); h = shape_hash(h, prop_flags); h1 = get_shape_hash(h, rt->shape_hash_bits); for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) { /* we test the hash first so that the rest is done only if the shapes really match */ if (sh1->hash == h && sh1->proto == sh->proto && sh1->prop_count == ((n = sh->prop_count) + 1)) { for(i = 0; i < n; i++) { if (unlikely(sh1->prop[i].atom != sh->prop[i].atom) || unlikely(sh1->prop[i].flags != sh->prop[i].flags)) goto next; } if (unlikely(sh1->prop[n].atom != atom) || unlikely(sh1->prop[n].flags != prop_flags)) goto next; return sh1; } next: ; } return NULL; } static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh) { char atom_buf[ATOM_GET_STR_BUF_SIZE]; int j; /* XXX: should output readable class prototype */ printf("%5d %3d%c %14p %5d %5d", i, sh->header.ref_count, " *"[sh->is_hashed], (void *)sh->proto, sh->prop_size, sh->prop_count); for(j = 0; j < sh->prop_count; j++) { printf(" %s", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), sh->prop[j].atom)); } printf("\n"); } static __maybe_unused void JS_DumpShapes(JSRuntime *rt) { int i; JSShape *sh; struct list_head *el; JSObject *p; JSGCObjectHeader *gp; printf("JSShapes: {\n"); printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS"); for(i = 0; i < rt->shape_hash_size; i++) { for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) { JS_DumpShape(rt, i, sh); assert(sh->is_hashed); } } /* dump non-hashed shapes */ list_for_each(el, &rt->gc_obj_list) { gp = list_entry(el, JSGCObjectHeader, link); if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { p = (JSObject *)gp; if (!p->shape->is_hashed) { JS_DumpShape(rt, -1, p->shape); } } } printf("}\n"); } static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id) { JSObject *p; js_trigger_gc(ctx->rt, sizeof(JSObject)); p = js_malloc(ctx, sizeof(JSObject)); if (unlikely(!p)) goto fail; p->class_id = class_id; p->extensible = true; p->free_mark = 0; p->is_exotic = 0; p->fast_array = 0; p->is_constructor = 0; p->is_uncatchable_error = 0; p->tmp_mark = 0; p->is_HTMLDDA = 0; p->first_weak_ref = NULL; p->u.opaque = NULL; p->shape = sh; p->prop = js_malloc(ctx, sizeof(JSProperty) * sh->prop_size); if (unlikely(!p->prop)) { js_free(ctx, p); fail: js_free_shape(ctx->rt, sh); return JS_EXCEPTION; } switch(class_id) { case JS_CLASS_OBJECT: break; case JS_CLASS_ARRAY: { JSProperty *pr; p->is_exotic = 1; p->fast_array = 1; p->u.array.u.values = NULL; p->u.array.count = 0; p->u.array.u1.size = 0; /* the length property is always the first one */ if (likely(sh == ctx->array_shape)) { pr = &p->prop[0]; } else { /* only used for the first array */ /* cannot fail */ pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); } pr->u.value = js_int32(0); } break; case JS_CLASS_C_FUNCTION: p->prop[0].u.value = JS_UNDEFINED; break; case JS_CLASS_ARGUMENTS: case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: case JS_CLASS_INT16_ARRAY: case JS_CLASS_UINT16_ARRAY: case JS_CLASS_INT32_ARRAY: case JS_CLASS_UINT32_ARRAY: case JS_CLASS_BIG_INT64_ARRAY: case JS_CLASS_BIG_UINT64_ARRAY: case JS_CLASS_FLOAT16_ARRAY: case JS_CLASS_FLOAT32_ARRAY: case JS_CLASS_FLOAT64_ARRAY: p->is_exotic = 1; p->fast_array = 1; p->u.array.u.ptr = NULL; p->u.array.count = 0; break; case JS_CLASS_DATAVIEW: p->u.array.u.ptr = NULL; p->u.array.count = 0; break; case JS_CLASS_NUMBER: case JS_CLASS_STRING: case JS_CLASS_BOOLEAN: case JS_CLASS_SYMBOL: case JS_CLASS_DATE: case JS_CLASS_BIG_INT: p->u.object_data = JS_UNDEFINED; goto set_exotic; case JS_CLASS_REGEXP: p->u.regexp.pattern = NULL; p->u.regexp.bytecode = NULL; goto set_exotic; default: set_exotic: if (ctx->rt->class_array[class_id].exotic) { p->is_exotic = 1; } break; } p->header.ref_count = 1; add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT); return JS_MKPTR(JS_TAG_OBJECT, p); } static JSObject *get_proto_obj(JSValueConst proto_val) { if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) return NULL; else return JS_VALUE_GET_OBJ(proto_val); } /* WARNING: proto must be an object or JS_NULL */ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, JSClassID class_id) { JSShape *sh; JSObject *proto; proto = get_proto_obj(proto_val); sh = find_hashed_shape_proto(ctx->rt, proto); if (likely(sh)) { sh = js_dup_shape(sh); } else { sh = js_new_shape(ctx, proto); if (!sh) return JS_EXCEPTION; } return JS_NewObjectFromShape(ctx, sh, class_id); } static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(obj); switch(p->class_id) { case JS_CLASS_NUMBER: case JS_CLASS_STRING: case JS_CLASS_BOOLEAN: case JS_CLASS_SYMBOL: case JS_CLASS_DATE: case JS_CLASS_BIG_INT: JS_FreeValue(ctx, p->u.object_data); p->u.object_data = val; return 0; } } JS_FreeValue(ctx, val); if (!JS_IsException(obj)) JS_ThrowTypeError(ctx, "invalid object type"); return -1; } JSValue JS_NewObjectClass(JSContext *ctx, JSClassID class_id) { return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id); } JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto) { return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT); } JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props, const JSValue *values) { JSShapeProperty *pr; uint32_t *hash; JSRuntime *rt; JSObject *p; JSShape *sh; JSValue obj; JSAtom atom; intptr_t h; int i; rt = ctx->rt; obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; if (count > 0) { p = JS_VALUE_GET_OBJ(obj); sh = p->shape; assert(sh->is_hashed); assert(sh->header.ref_count == 1); js_shape_hash_unlink(rt, sh); if (resize_properties(ctx, &sh, p, count)) { js_shape_hash_link(rt, sh); JS_FreeValue(ctx, obj); return JS_EXCEPTION; } p->shape = sh; for (i = 0; i < count; i++) { atom = props[i]; pr = &sh->prop[i]; sh->hash = shape_hash(shape_hash(sh->hash, atom), JS_PROP_C_W_E); sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); h = atom & sh->prop_hash_mask; hash = &prop_hash_end(sh)[-h - 1]; pr->hash_next = *hash; *hash = i + 1; pr->atom = JS_DupAtom(ctx, atom); pr->flags = JS_PROP_C_W_E; p->prop[i].u.value = values[i]; } js_shape_hash_link(rt, sh); sh->prop_count = count; } return obj; } JSValue JS_NewObjectFromStr(JSContext *ctx, int count, const char **props, const JSValue *values) { JSAtom atoms_s[16], *atoms = atoms_s; JSValue ret; int i; i = 0; ret = JS_EXCEPTION; if (count < 1) goto out; if (count > (int)countof(atoms_s)) { atoms = js_malloc(ctx, count * sizeof(*atoms)); if (!atoms) return JS_EXCEPTION; } for (i = 0; i < count; i++) { atoms[i] = JS_NewAtom(ctx, props[i]); if (atoms[i] == JS_ATOM_NULL) goto out; } ret = JS_NewObjectFrom(ctx, count, atoms, values); out: while (i-- > 0) JS_FreeAtom(ctx, atoms[i]); if (atoms != atoms_s) js_free(ctx, atoms); return ret; } JSValue JS_NewArray(JSContext *ctx) { return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape), JS_CLASS_ARRAY); } // note: takes ownership of |values|, unlike js_create_array JSValue JS_NewArrayFrom(JSContext *ctx, int count, const JSValue *values) { JSObject *p; JSValue obj; int i; obj = JS_NewArray(ctx); if (JS_IsException(obj)) goto exception; if (count > 0) { p = JS_VALUE_GET_OBJ(obj); if (expand_fast_array(ctx, p, count)) { JS_FreeValue(ctx, obj); goto exception; } p->u.array.count = count; p->prop[0].u.value = js_int32(count); memcpy(p->u.array.u.values, values, count * sizeof(*values)); } return obj; exception: for (i = 0; i < count; i++) JS_FreeValue(ctx, values[i]); return JS_EXCEPTION; } JSValue JS_NewObject(JSContext *ctx) { /* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */ return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT); } static void js_function_set_properties(JSContext *ctx, JSValue func_obj, JSAtom name, int len) { /* ES6 feature non compatible with ES5.1: length is configurable */ JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, js_int32(len), JS_PROP_CONFIGURABLE); JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE); } static bool js_class_has_bytecode(JSClassID class_id) { return (class_id == JS_CLASS_BYTECODE_FUNCTION || class_id == JS_CLASS_GENERATOR_FUNCTION || class_id == JS_CLASS_ASYNC_FUNCTION || class_id == JS_CLASS_ASYNC_GENERATOR_FUNCTION); } /* return NULL without exception if not a function or no bytecode */ static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return NULL; p = JS_VALUE_GET_OBJ(val); if (!js_class_has_bytecode(p->class_id)) return NULL; return p->u.func.function_bytecode; } static void js_method_set_home_object(JSContext *ctx, JSValue func_obj, JSValue home_obj) { JSObject *p, *p1; JSFunctionBytecode *b; if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) return; p = JS_VALUE_GET_OBJ(func_obj); if (!js_class_has_bytecode(p->class_id)) return; b = p->u.func.function_bytecode; if (b->need_home_object) { p1 = p->u.func.home_object; if (p1) { JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); } if (JS_VALUE_GET_TAG(home_obj) == JS_TAG_OBJECT) p1 = JS_VALUE_GET_OBJ(js_dup(home_obj)); else p1 = NULL; p->u.func.home_object = p1; } } static JSValue js_get_function_name(JSContext *ctx, JSAtom name) { JSValue name_str; name_str = JS_AtomToString(ctx, name); if (JS_AtomSymbolHasDescription(ctx, name)) { name_str = JS_ConcatString3(ctx, "[", name_str, "]"); } return name_str; } /* Modify the name of a method according to the atom and 'flags'. 'flags' is a bitmask of JS_PROP_HAS_GET and JS_PROP_HAS_SET. Also set the home object of the method. Return < 0 if exception. */ static int js_method_set_properties(JSContext *ctx, JSValue func_obj, JSAtom name, int flags, JSValue home_obj) { JSValue name_str; name_str = js_get_function_name(ctx, name); if (flags & JS_PROP_HAS_GET) { name_str = JS_ConcatString3(ctx, "get ", name_str, ""); } else if (flags & JS_PROP_HAS_SET) { name_str = JS_ConcatString3(ctx, "set ", name_str, ""); } if (JS_IsException(name_str)) return -1; if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name_str, JS_PROP_CONFIGURABLE) < 0) return -1; js_method_set_home_object(ctx, func_obj, home_obj); return 0; } /* Note: at least 'length' arguments will be readable in 'argv' */ /* `name` may be NULL, pure ASCII or UTF-8 encoded */ JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic, JSValueConst proto_val) { JSValue func_obj; JSObject *p; JSAtom name_atom; func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); if (JS_IsException(func_obj)) return func_obj; p = JS_VALUE_GET_OBJ(func_obj); p->u.cfunc.realm = JS_DupContext(ctx); p->u.cfunc.c_function.generic = func; p->u.cfunc.length = length; p->u.cfunc.cproto = cproto; p->u.cfunc.magic = magic; p->is_constructor = (cproto == JS_CFUNC_constructor || cproto == JS_CFUNC_constructor_magic || cproto == JS_CFUNC_constructor_or_func || cproto == JS_CFUNC_constructor_or_func_magic); name_atom = JS_ATOM_empty_string; if (name && *name) { name_atom = JS_NewAtom(ctx, name); if (name_atom == JS_ATOM_NULL) { JS_FreeValue(ctx, func_obj); return JS_EXCEPTION; } } js_function_set_properties(ctx, func_obj, name_atom, length); JS_FreeAtom(ctx, name_atom); return func_obj; } /* Note: at least 'length' arguments will be readable in 'argv' */ JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic) { return JS_NewCFunction3(ctx, func, name, length, cproto, magic, ctx->function_proto); } typedef struct JSCFunctionDataRecord { JSCFunctionData *func; uint8_t length; uint8_t data_len; uint16_t magic; JSValue data[]; } JSCFunctionDataRecord; static void js_c_function_data_finalizer(JSRuntime *rt, JSValueConst val) { JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); int i; if (s) { for(i = 0; i < s->data_len; i++) { JS_FreeValueRT(rt, s->data[i]); } js_free_rt(rt, s); } } static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); int i; if (s) { for(i = 0; i < s->data_len; i++) { JS_MarkValue(rt, s->data[i], mark_func); } } } static JSValue js_call_c_function_data(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags) { JSRuntime *rt = ctx->rt; JSStackFrame sf_s, *sf = &sf_s, *prev_sf; JSCFunctionDataRecord *s; JSValueConst *arg_buf; JSValue ret; size_t stack_size; int arg_count; int i; s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA); if (!s) return JS_EXCEPTION; // can't really happen arg_buf = argv; arg_count = s->length; if (unlikely(argc < arg_count)) { stack_size = arg_count * sizeof(arg_buf[0]); if (js_check_stack_overflow(rt, stack_size)) return JS_ThrowStackOverflow(ctx); arg_buf = alloca(stack_size); for(i = 0; i < argc; i++) arg_buf[i] = argv[i]; for(i = argc; i < arg_count; i++) arg_buf[i] = JS_UNDEFINED; } prev_sf = rt->current_stack_frame; sf->prev_frame = prev_sf; rt->current_stack_frame = sf; // TODO(bnoordhuis) switch realms like js_call_c_function does sf->is_strict_mode = false; sf->cur_func = unsafe_unconst(func_obj); sf->arg_count = argc; ret = s->func(ctx, this_val, argc, arg_buf, s->magic, vc(s->data)); rt->current_stack_frame = sf->prev_frame; return ret; } JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func, const char *name, int length, int magic, int data_len, JSValueConst *data) { JSCFunctionDataRecord *s; JSAtom name_atom; JSValue func_obj; int i; func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto, JS_CLASS_C_FUNCTION_DATA); if (JS_IsException(func_obj)) return func_obj; s = js_malloc(ctx, sizeof(*s) + data_len * sizeof(JSValue)); if (!s) { JS_FreeValue(ctx, func_obj); return JS_EXCEPTION; } s->func = func; s->length = length; s->data_len = data_len; s->magic = magic; for(i = 0; i < data_len; i++) s->data[i] = js_dup(data[i]); JS_SetOpaqueInternal(func_obj, s); name_atom = JS_ATOM_empty_string; if (name && *name) { name_atom = JS_NewAtom(ctx, name); if (name_atom == JS_ATOM_NULL) { JS_FreeValue(ctx, func_obj); return JS_EXCEPTION; } } js_function_set_properties(ctx, func_obj, name_atom, length); JS_FreeAtom(ctx, name_atom); return func_obj; } JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, int length, int magic, int data_len, JSValueConst *data) { return JS_NewCFunctionData2(ctx, func, NULL, length, magic, data_len, data); } static JSContext *js_autoinit_get_realm(JSProperty *pr) { return (JSContext *)(pr->u.init.realm_and_id & ~3); } static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr) { return pr->u.init.realm_and_id & 3; } static void js_autoinit_free(JSRuntime *rt, JSProperty *pr) { JS_FreeContext(js_autoinit_get_realm(pr)); } static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr, JS_MarkFunc *mark_func) { mark_func(rt, &js_autoinit_get_realm(pr)->header); } static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags) { if (unlikely(prop_flags & JS_PROP_TMASK)) { if ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET) { if (pr->u.getset.getter) JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (pr->u.getset.setter) JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) { free_var_ref(rt, pr->u.var_ref); } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { js_autoinit_free(rt, pr); } } else { JS_FreeValueRT(rt, pr->u.value); } } static force_inline JSShapeProperty *find_own_property1(JSObject *p, JSAtom atom) { JSShape *sh; JSShapeProperty *pr, *prop; intptr_t h; sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; prop = get_shape_prop(sh); while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { return pr; } h = pr->hash_next; } return NULL; } static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, JSObject *p, JSAtom atom) { JSShape *sh; JSShapeProperty *pr, *prop; intptr_t h; sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; prop = get_shape_prop(sh); while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { *ppr = &p->prop[h - 1]; /* the compiler should be able to assume that pr != NULL here */ return pr; } h = pr->hash_next; } *ppr = NULL; return NULL; } static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) { if (var_ref) { assert(var_ref->header.ref_count > 0); if (--var_ref->header.ref_count == 0) { if (var_ref->is_detached) { JS_FreeValueRT(rt, var_ref->value); remove_gc_object(&var_ref->header); } else { list_del(&var_ref->header.link); /* still on the stack */ } js_free_rt(rt, var_ref); } } } static void js_array_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); int i; for(i = 0; i < p->u.array.count; i++) { JS_FreeValueRT(rt, p->u.array.u.values[i]); } js_free_rt(rt, p->u.array.u.values); } static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); int i; for(i = 0; i < p->u.array.count; i++) { JS_MarkValue(rt, p->u.array.u.values[i], mark_func); } } static void js_object_data_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); JS_FreeValueRT(rt, p->u.object_data); p->u.object_data = JS_UNDEFINED; } static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JS_MarkValue(rt, p->u.object_data, mark_func); } static void js_c_function_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); if (p->u.cfunc.realm) JS_FreeContext(p->u.cfunc.realm); } static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); if (p->u.cfunc.realm) mark_func(rt, &p->u.cfunc.realm->header); } static void js_bytecode_function_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p1, *p = JS_VALUE_GET_OBJ(val); JSFunctionBytecode *b; JSVarRef **var_refs; int i; p1 = p->u.func.home_object; if (p1) { JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, p1)); } b = p->u.func.function_bytecode; if (b) { var_refs = p->u.func.var_refs; if (var_refs) { for(i = 0; i < b->closure_var_count; i++) free_var_ref(rt, var_refs[i]); js_free_rt(rt, var_refs); } JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b)); } } static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSVarRef **var_refs = p->u.func.var_refs; JSFunctionBytecode *b = p->u.func.function_bytecode; int i; if (p->u.func.home_object) { JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object), mark_func); } if (b) { if (var_refs) { for(i = 0; i < b->closure_var_count; i++) { JSVarRef *var_ref = var_refs[i]; if (var_ref && var_ref->is_detached) { mark_func(rt, &var_ref->header); } } } /* must mark the function bytecode because template objects may be part of a cycle */ JS_MarkValue(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), mark_func); } } static void js_bound_function_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSBoundFunction *bf = p->u.bound_function; int i; JS_FreeValueRT(rt, bf->func_obj); JS_FreeValueRT(rt, bf->this_val); for(i = 0; i < bf->argc; i++) { JS_FreeValueRT(rt, bf->argv[i]); } js_free_rt(rt, bf); } static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSBoundFunction *bf = p->u.bound_function; int i; JS_MarkValue(rt, bf->func_obj, mark_func); JS_MarkValue(rt, bf->this_val, mark_func); for(i = 0; i < bf->argc; i++) JS_MarkValue(rt, bf->argv[i], mark_func); } static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSForInIterator *it = p->u.for_in_iterator; JS_FreeValueRT(rt, it->obj); js_free_rt(rt, it); } static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSForInIterator *it = p->u.for_in_iterator; JS_MarkValue(rt, it->obj, mark_func); } static void free_object(JSRuntime *rt, JSObject *p) { int i; JSClassFinalizer *finalizer; JSShape *sh; JSShapeProperty *pr; p->free_mark = 1; /* used to tell the object is invalid when freeing cycles */ /* free all the fields */ sh = p->shape; pr = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { free_property(rt, &p->prop[i], pr->flags); pr++; } js_free_rt(rt, p->prop); /* as an optimization we destroy the shape immediately without putting it in gc_zero_ref_count_list */ js_free_shape(rt, sh); /* fail safe */ p->shape = NULL; p->prop = NULL; if (unlikely(p->first_weak_ref)) { reset_weak_ref(rt, &p->first_weak_ref); } finalizer = rt->class_array[p->class_id].finalizer; if (finalizer) (*finalizer)(rt, JS_MKPTR(JS_TAG_OBJECT, p)); /* fail safe */ p->class_id = 0; p->u.opaque = NULL; p->u.func.var_refs = NULL; p->u.func.home_object = NULL; remove_gc_object(&p->header); if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && p->header.ref_count != 0) { list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list); } else { js_free_rt(rt, p); } } static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp) { switch(gp->gc_obj_type) { case JS_GC_OBJ_TYPE_JS_OBJECT: free_object(rt, (JSObject *)gp); break; case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: free_function_bytecode(rt, (JSFunctionBytecode *)gp); break; default: abort(); } } static void free_zero_refcount(JSRuntime *rt) { struct list_head *el; JSGCObjectHeader *p; rt->gc_phase = JS_GC_PHASE_DECREF; for(;;) { el = rt->gc_zero_ref_count_list.next; if (el == &rt->gc_zero_ref_count_list) break; p = list_entry(el, JSGCObjectHeader, link); assert(p->ref_count == 0); free_gc_object(rt, p); } rt->gc_phase = JS_GC_PHASE_NONE; } /* called with the ref_count of 'v' reaches zero. */ static void js_free_value_rt(JSRuntime *rt, JSValue v) { uint32_t tag = JS_VALUE_GET_TAG(v); #ifdef ENABLE_DUMPS // JS_DUMP_FREE if (check_dump_flag(rt, JS_DUMP_FREE)) { /* Prevent invalid object access during GC */ if ((rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) || (tag != JS_TAG_OBJECT && tag != JS_TAG_FUNCTION_BYTECODE)) { printf("Freeing "); if (tag == JS_TAG_OBJECT) { JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); } else { JS_DumpValue(rt, v); printf("\n"); } } } #endif switch(tag) { case JS_TAG_STRING: js_free_string0(rt, JS_VALUE_GET_STRING(v)); break; case JS_TAG_OBJECT: case JS_TAG_FUNCTION_BYTECODE: { JSGCObjectHeader *p = JS_VALUE_GET_PTR(v); if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) { list_del(&p->link); list_add(&p->link, &rt->gc_zero_ref_count_list); if (rt->gc_phase == JS_GC_PHASE_NONE) { free_zero_refcount(rt); } } } break; case JS_TAG_MODULE: abort(); /* never freed here */ break; case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(v); js_free_rt(rt, p); } break; case JS_TAG_SYMBOL: { JSAtomStruct *p = JS_VALUE_GET_PTR(v); JS_FreeAtomStruct(rt, p); } break; default: printf("js_free_value_rt: unknown tag=%d\n", tag); abort(); } } void JS_FreeValueRT(JSRuntime *rt, JSValue v) { if (JS_VALUE_HAS_REF_COUNT(v)) { JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); #ifndef NDEBUG notifyRefCountDecrease(p); #endif if (--p->ref_count <= 0) { js_free_value_rt(rt, v); } } } void JS_FreeValue(JSContext *ctx, JSValue v) { JS_FreeValueRT(ctx->rt, v); } /* garbage collection */ static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type) { h->mark = 0; h->gc_obj_type = type; list_add_tail(&h->link, &rt->gc_obj_list); } static void remove_gc_object(JSGCObjectHeader *h) { list_del(&h->link); } void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { if (JS_VALUE_HAS_REF_COUNT(val)) { switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_OBJECT: case JS_TAG_FUNCTION_BYTECODE: mark_func(rt, JS_VALUE_GET_PTR(val)); break; default: break; } } } static void mark_weak_map_value(JSRuntime *rt, JSWeakRefRecord *first_weak_ref, JS_MarkFunc *mark_func) { JSWeakRefRecord *wr; JSMapRecord *mr; JSMapState *s; for (wr = first_weak_ref; wr != NULL; wr = wr->next_weak_ref) { if (wr->kind == JS_WEAK_REF_KIND_MAP) { mr = wr->u.map_record; s = mr->map; assert(s->is_weak); assert(!mr->empty); /* no iterator on WeakMap/WeakSet */ JS_MarkValue(rt, mr->value, mark_func); } } } static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkFunc *mark_func) { switch(gp->gc_obj_type) { case JS_GC_OBJ_TYPE_JS_OBJECT: { JSObject *p = (JSObject *)gp; JSShapeProperty *prs; JSShape *sh; int i; sh = p->shape; mark_func(rt, &sh->header); /* mark all the fields */ prs = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL) { if (prs->flags & JS_PROP_TMASK) { if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { if (pr->u.getset.getter) mark_func(rt, &pr->u.getset.getter->header); if (pr->u.getset.setter) mark_func(rt, &pr->u.getset.setter->header); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { if (pr->u.var_ref->is_detached) { /* Note: the tag does not matter provided it is a GC object */ mark_func(rt, &pr->u.var_ref->header); } } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { js_autoinit_mark(rt, pr, mark_func); } } else { JS_MarkValue(rt, pr->u.value, mark_func); } } prs++; } if (unlikely(p->first_weak_ref)) { mark_weak_map_value(rt, p->first_weak_ref, mark_func); } if (p->class_id != JS_CLASS_OBJECT) { JSClassGCMark *gc_mark; gc_mark = rt->class_array[p->class_id].gc_mark; if (gc_mark) gc_mark(rt, JS_MKPTR(JS_TAG_OBJECT, p), mark_func); } } break; case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: /* the template objects can be part of a cycle */ { JSFunctionBytecode *b = (JSFunctionBytecode *)gp; int i; for(i = 0; i < b->cpool_count; i++) { JS_MarkValue(rt, b->cpool[i], mark_func); } if (b->realm) mark_func(rt, &b->realm->header); } break; case JS_GC_OBJ_TYPE_VAR_REF: { JSVarRef *var_ref = (JSVarRef *)gp; /* only detached variable referenced are taken into account */ assert(var_ref->is_detached); JS_MarkValue(rt, *var_ref->pvalue, mark_func); } break; case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: { JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp; if (s->is_active) async_func_mark(rt, &s->func_state, mark_func); JS_MarkValue(rt, s->resolving_funcs[0], mark_func); JS_MarkValue(rt, s->resolving_funcs[1], mark_func); } break; case JS_GC_OBJ_TYPE_SHAPE: { JSShape *sh = (JSShape *)gp; if (sh->proto != NULL) { mark_func(rt, &sh->proto->header); } } break; case JS_GC_OBJ_TYPE_JS_CONTEXT: { JSContext *ctx = (JSContext *)gp; JS_MarkContext(rt, ctx, mark_func); } break; default: abort(); } } static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p) { #ifndef NDEBUG notifyRefCountDecrease((JSRefCountHeader*)p); #endif assert(p->ref_count > 0); p->ref_count--; if (p->ref_count == 0 && p->mark == 1) { list_del(&p->link); list_add_tail(&p->link, &rt->tmp_obj_list); } } static void gc_decref(JSRuntime *rt) { struct list_head *el, *el1; JSGCObjectHeader *p; init_list_head(&rt->tmp_obj_list); /* decrement the refcount of all the children of all the GC objects and move the GC objects with zero refcount to tmp_obj_list */ list_for_each_safe(el, el1, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); assert(p->mark == 0); mark_children(rt, p, gc_decref_child); p->mark = 1; if (p->ref_count == 0) { list_del(&p->link); list_add_tail(&p->link, &rt->tmp_obj_list); } } } static void gc_scan_incref_child(JSRuntime *rt, JSGCObjectHeader *p) { #ifndef NDEBUG notifyRefCountIncrease((JSRefCountHeader*)p); #endif p->ref_count++; if (p->ref_count == 1) { /* ref_count was 0: remove from tmp_obj_list and add at the end of gc_obj_list */ list_del(&p->link); list_add_tail(&p->link, &rt->gc_obj_list); p->mark = 0; /* reset the mark for the next GC call */ } } static void gc_scan_incref_child2(JSRuntime *rt, JSGCObjectHeader *p) { #ifndef NDEBUG notifyRefCountIncrease((JSRefCountHeader*)p); #endif p->ref_count++; } static void gc_scan(JSRuntime *rt) { struct list_head *el; JSGCObjectHeader *p; /* keep the objects with a refcount > 0 and their children. */ list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); assert(p->ref_count > 0); p->mark = 0; /* reset the mark for the next GC call */ mark_children(rt, p, gc_scan_incref_child); } /* restore the refcount of the objects to be deleted. */ list_for_each(el, &rt->tmp_obj_list) { p = list_entry(el, JSGCObjectHeader, link); mark_children(rt, p, gc_scan_incref_child2); } } static void gc_free_cycles(JSRuntime *rt) { struct list_head *el, *el1; JSGCObjectHeader *p; #ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE bool header_done = false; #endif rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES; for(;;) { el = rt->tmp_obj_list.next; if (el == &rt->tmp_obj_list) break; p = list_entry(el, JSGCObjectHeader, link); /* Only need to free the GC object associated with JS values. The rest will be automatically removed because they must be referenced by them. */ switch(p->gc_obj_type) { case JS_GC_OBJ_TYPE_JS_OBJECT: case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: #ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE if (check_dump_flag(rt, JS_DUMP_GC_FREE)) { if (!header_done) { printf("Freeing cycles:\n"); JS_DumpObjectHeader(rt); header_done = true; } JS_DumpGCObject(rt, p); } #endif free_gc_object(rt, p); break; default: list_del(&p->link); list_add_tail(&p->link, &rt->gc_zero_ref_count_list); break; } } rt->gc_phase = JS_GC_PHASE_NONE; list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) { p = list_entry(el, JSGCObjectHeader, link); assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT || p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); js_free_rt(rt, p); } init_list_head(&rt->gc_zero_ref_count_list); } void JS_RunGC(JSRuntime *rt) { /* decrement the reference of the children of each object. mark = 1 after this pass. */ gc_decref(rt); /* keep the GC objects with a non zero refcount and their childs */ gc_scan(rt); /* free the GC objects in a cycle */ gc_free_cycles(rt); } /* Return false if not an object or if the object has already been freed (zombie objects are visible in finalizers when freeing cycles). */ bool JS_IsLiveObject(JSRuntime *rt, JSValueConst obj) { JSObject *p; if (!JS_IsObject(obj)) return false; p = JS_VALUE_GET_OBJ(obj); return !p->free_mark; } /* Compute memory used by various object types */ /* XXX: poor man's approach to handling multiply referenced objects */ typedef struct JSMemoryUsage_helper { double memory_used_count; double str_count; double str_size; int64_t js_func_count; double js_func_size; int64_t js_func_code_size; int64_t js_func_pc2line_count; int64_t js_func_pc2line_size; } JSMemoryUsage_helper; static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp); static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp) { if (!str->atom_type) { /* atoms are handled separately */ double s_ref_count = str->header.ref_count; hp->str_count += 1 / s_ref_count; hp->str_size += ((sizeof(*str) + (str->len << str->is_wide_char) + 1 - str->is_wide_char) / s_ref_count); } } static void compute_bytecode_size(JSFunctionBytecode *b, JSMemoryUsage_helper *hp) { int memory_used_count, js_func_size, i; memory_used_count = 0; js_func_size = sizeof(*b); if (b->vardefs) { js_func_size += (b->arg_count + b->var_count) * sizeof(*b->vardefs); } if (b->cpool) { js_func_size += b->cpool_count * sizeof(*b->cpool); for (i = 0; i < b->cpool_count; i++) { JSValue val = b->cpool[i]; compute_value_size(val, hp); } } if (b->closure_var) { js_func_size += b->closure_var_count * sizeof(*b->closure_var); } if (b->byte_code_buf) { hp->js_func_code_size += b->byte_code_len; } memory_used_count++; js_func_size += b->source_len + 1; if (b->pc2line_len) { memory_used_count++; hp->js_func_pc2line_count += 1; hp->js_func_pc2line_size += b->pc2line_len; } hp->js_func_size += js_func_size; hp->js_func_count += 1; hp->memory_used_count += memory_used_count; } static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp) { switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_STRING: compute_jsstring_size(JS_VALUE_GET_STRING(val), hp); break; case JS_TAG_BIG_INT: /* should track JSBigInt usage */ break; } } void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) { struct list_head *el, *el1; int i; JSMemoryUsage_helper mem = { 0 }, *hp = &mem; memset(s, 0, sizeof(*s)); s->malloc_count = rt->malloc_state.malloc_count; s->malloc_size = rt->malloc_state.malloc_size; s->malloc_limit = rt->malloc_state.malloc_limit; s->memory_used_count = 2; /* rt + rt->class_array */ s->memory_used_size = sizeof(JSRuntime) + sizeof(JSClass) * rt->class_count; list_for_each(el, &rt->context_list) { JSContext *ctx = list_entry(el, JSContext, link); JSShape *sh = ctx->array_shape; s->memory_used_count += 2; /* ctx + ctx->class_proto */ s->memory_used_size += sizeof(JSContext) + sizeof(JSValue) * rt->class_count; s->binary_object_count += ctx->binary_object_count; s->binary_object_size += ctx->binary_object_size; /* the hashed shapes are counted separately */ if (sh && !sh->is_hashed) { int hash_size = sh->prop_hash_mask + 1; s->shape_count++; s->shape_size += get_shape_size(hash_size, sh->prop_size); } list_for_each(el1, &ctx->loaded_modules) { JSModuleDef *m = list_entry(el1, JSModuleDef, link); s->memory_used_count += 1; s->memory_used_size += sizeof(*m); if (m->req_module_entries) { s->memory_used_count += 1; s->memory_used_size += m->req_module_entries_count * sizeof(*m->req_module_entries); } if (m->export_entries) { s->memory_used_count += 1; s->memory_used_size += m->export_entries_count * sizeof(*m->export_entries); for (i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL && me->u.local.var_ref) { /* potential multiple count */ s->memory_used_count += 1; compute_value_size(me->u.local.var_ref->value, hp); } } } if (m->star_export_entries) { s->memory_used_count += 1; s->memory_used_size += m->star_export_entries_count * sizeof(*m->star_export_entries); } if (m->import_entries) { s->memory_used_count += 1; s->memory_used_size += m->import_entries_count * sizeof(*m->import_entries); } compute_value_size(m->module_ns, hp); compute_value_size(m->func_obj, hp); } } list_for_each(el, &rt->gc_obj_list) { JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link); JSObject *p; JSShape *sh; JSShapeProperty *prs; /* XXX: could count the other GC object types too */ if (gp->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE) { compute_bytecode_size((JSFunctionBytecode *)gp, hp); continue; } else if (gp->gc_obj_type != JS_GC_OBJ_TYPE_JS_OBJECT) { continue; } p = (JSObject *)gp; sh = p->shape; s->obj_count++; if (p->prop) { s->memory_used_count++; s->prop_size += sh->prop_size * sizeof(*p->prop); s->prop_count += sh->prop_count; prs = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL && !(prs->flags & JS_PROP_TMASK)) { compute_value_size(pr->u.value, hp); } prs++; } } /* the hashed shapes are counted separately */ if (!sh->is_hashed) { int hash_size = sh->prop_hash_mask + 1; s->shape_count++; s->shape_size += get_shape_size(hash_size, sh->prop_size); } switch(p->class_id) { case JS_CLASS_ARRAY: /* u.array | length */ case JS_CLASS_ARGUMENTS: /* u.array | length */ s->array_count++; if (p->fast_array) { s->fast_array_count++; if (p->u.array.u.values) { s->memory_used_count++; s->memory_used_size += p->u.array.count * sizeof(*p->u.array.u.values); s->fast_array_elements += p->u.array.count; for (i = 0; i < p->u.array.count; i++) { compute_value_size(p->u.array.u.values[i], hp); } } } break; case JS_CLASS_NUMBER: /* u.object_data */ case JS_CLASS_STRING: /* u.object_data */ case JS_CLASS_BOOLEAN: /* u.object_data */ case JS_CLASS_SYMBOL: /* u.object_data */ case JS_CLASS_DATE: /* u.object_data */ case JS_CLASS_BIG_INT: /* u.object_data */ compute_value_size(p->u.object_data, hp); break; case JS_CLASS_C_FUNCTION: /* u.cfunc */ s->c_func_count++; break; case JS_CLASS_BYTECODE_FUNCTION: /* u.func */ { JSFunctionBytecode *b = p->u.func.function_bytecode; JSVarRef **var_refs = p->u.func.var_refs; /* home_object: object will be accounted for in list scan */ if (var_refs) { s->memory_used_count++; s->js_func_size += b->closure_var_count * sizeof(*var_refs); for (i = 0; i < b->closure_var_count; i++) { if (var_refs[i]) { double ref_count = var_refs[i]->header.ref_count; s->memory_used_count += 1 / ref_count; s->js_func_size += sizeof(*var_refs[i]) / ref_count; /* handle non object closed values */ if (var_refs[i]->pvalue == &var_refs[i]->value) { /* potential multiple count */ compute_value_size(var_refs[i]->value, hp); } } } } } break; case JS_CLASS_BOUND_FUNCTION: /* u.bound_function */ { JSBoundFunction *bf = p->u.bound_function; /* func_obj and this_val are objects */ for (i = 0; i < bf->argc; i++) { compute_value_size(bf->argv[i], hp); } s->memory_used_count += 1; s->memory_used_size += sizeof(*bf) + bf->argc * sizeof(*bf->argv); } break; case JS_CLASS_C_FUNCTION_DATA: /* u.c_function_data_record */ { JSCFunctionDataRecord *fd = p->u.c_function_data_record; if (fd) { for (i = 0; i < fd->data_len; i++) { compute_value_size(fd->data[i], hp); } s->memory_used_count += 1; s->memory_used_size += sizeof(*fd) + fd->data_len * sizeof(*fd->data); } } break; case JS_CLASS_REGEXP: /* u.regexp */ compute_jsstring_size(p->u.regexp.pattern, hp); compute_jsstring_size(p->u.regexp.bytecode, hp); break; case JS_CLASS_FOR_IN_ITERATOR: /* u.for_in_iterator */ { JSForInIterator *it = p->u.for_in_iterator; if (it) { compute_value_size(it->obj, hp); s->memory_used_count += 1; s->memory_used_size += sizeof(*it); } } break; case JS_CLASS_ARRAY_BUFFER: /* u.array_buffer */ case JS_CLASS_SHARED_ARRAY_BUFFER: /* u.array_buffer */ { JSArrayBuffer *abuf = p->u.array_buffer; if (abuf) { s->memory_used_count += 1; s->memory_used_size += sizeof(*abuf); if (abuf->data) { s->memory_used_count += 1; s->memory_used_size += abuf->byte_length; } } } break; case JS_CLASS_GENERATOR: /* u.generator_data */ case JS_CLASS_UINT8C_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_INT8_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_UINT8_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_INT16_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_UINT16_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_INT32_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_FLOAT16_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_DATAVIEW: /* u.typed_array */ case JS_CLASS_MAP: /* u.map_state */ case JS_CLASS_SET: /* u.map_state */ case JS_CLASS_WEAKMAP: /* u.map_state */ case JS_CLASS_WEAKSET: /* u.map_state */ case JS_CLASS_MAP_ITERATOR: /* u.map_iterator_data */ case JS_CLASS_SET_ITERATOR: /* u.map_iterator_data */ case JS_CLASS_ARRAY_ITERATOR: /* u.array_iterator_data */ case JS_CLASS_STRING_ITERATOR: /* u.array_iterator_data */ case JS_CLASS_PROXY: /* u.proxy_data */ case JS_CLASS_PROMISE: /* u.promise_data */ case JS_CLASS_PROMISE_RESOLVE_FUNCTION: /* u.promise_function_data */ case JS_CLASS_PROMISE_REJECT_FUNCTION: /* u.promise_function_data */ case JS_CLASS_ASYNC_FUNCTION_RESOLVE: /* u.async_function_data */ case JS_CLASS_ASYNC_FUNCTION_REJECT: /* u.async_function_data */ case JS_CLASS_ASYNC_FROM_SYNC_ITERATOR: /* u.async_from_sync_iterator_data */ case JS_CLASS_ASYNC_GENERATOR: /* u.async_generator_data */ /* TODO */ default: /* XXX: class definition should have an opaque block size */ if (p->u.opaque) { s->memory_used_count += 1; } break; } } s->obj_size += s->obj_count * sizeof(JSObject); /* hashed shapes */ s->memory_used_count++; /* rt->shape_hash */ s->memory_used_size += sizeof(rt->shape_hash[0]) * rt->shape_hash_size; for(i = 0; i < rt->shape_hash_size; i++) { JSShape *sh; for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) { int hash_size = sh->prop_hash_mask + 1; s->shape_count++; s->shape_size += get_shape_size(hash_size, sh->prop_size); } } /* atoms */ s->memory_used_count += 2; /* rt->atom_array, rt->atom_hash */ s->atom_count = rt->atom_count; s->atom_size = sizeof(rt->atom_array[0]) * rt->atom_size + sizeof(rt->atom_hash[0]) * rt->atom_hash_size; for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p)) { s->atom_size += (sizeof(*p) + (p->len << p->is_wide_char) + 1 - p->is_wide_char); } } s->str_count = round(mem.str_count); s->str_size = round(mem.str_size); s->js_func_count = mem.js_func_count; s->js_func_size = round(mem.js_func_size); s->js_func_code_size = mem.js_func_code_size; s->js_func_pc2line_count = mem.js_func_pc2line_count; s->js_func_pc2line_size = mem.js_func_pc2line_size; s->memory_used_count += round(mem.memory_used_count) + s->atom_count + s->str_count + s->obj_count + s->shape_count + s->js_func_count + s->js_func_pc2line_count; s->memory_used_size += s->atom_size + s->str_size + s->obj_size + s->prop_size + s->shape_size + s->js_func_size + s->js_func_code_size + s->js_func_pc2line_size; } void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) { fprintf(fp, "QuickJS-ng memory usage -- %s version, %d-bit, %s Endian, malloc limit: %"PRId64"\n\n", JS_GetVersion(), (int)sizeof(void *) * 8, is_be() ? "Big" : "Little", s->malloc_limit); if (rt) { static const struct { const char *name; size_t size; } object_types[] = { { "JSRuntime", sizeof(JSRuntime) }, { "JSContext", sizeof(JSContext) }, { "JSObject", sizeof(JSObject) }, { "JSString", sizeof(JSString) }, { "JSFunctionBytecode", sizeof(JSFunctionBytecode) }, }; int i, usage_size_ok = 0; for(i = 0; i < countof(object_types); i++) { unsigned int size = object_types[i].size; void *p = js_malloc_rt(rt, size); if (p) { unsigned int size1 = js_malloc_usable_size_rt(rt, p); if (size1 >= size) { usage_size_ok = 1; fprintf(fp, " %3u + %-2u %s\n", size, size1 - size, object_types[i].name); } js_free_rt(rt, p); } } if (!usage_size_ok) { fprintf(fp, " malloc_usable_size unavailable\n"); } { int obj_classes[JS_CLASS_INIT_COUNT + 1] = { 0 }; int class_id; struct list_head *el; list_for_each(el, &rt->gc_obj_list) { JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link); JSObject *p; if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { p = (JSObject *)gp; obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++; } } fprintf(fp, "\n" "JSObject classes\n"); if (obj_classes[0]) fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none"); for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) { if (obj_classes[class_id] && class_id < rt->class_count) { char buf[ATOM_GET_STR_BUF_SIZE]; fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id, JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name)); } } if (obj_classes[JS_CLASS_INIT_COUNT]) fprintf(fp, " %5d %2.0d %s\n", obj_classes[JS_CLASS_INIT_COUNT], 0, "other"); } fprintf(fp, "\n"); } fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE"); if (s->malloc_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per block)\n", "memory allocated", s->malloc_count, s->malloc_size, (double)s->malloc_size / s->malloc_count); fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%d overhead, %0.1f average slack)\n", "memory used", s->memory_used_count, s->memory_used_size, MALLOC_OVERHEAD, ((double)(s->malloc_size - s->memory_used_size) / s->memory_used_count)); } if (s->atom_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per atom)\n", "atoms", s->atom_count, s->atom_size, (double)s->atom_size / s->atom_count); } if (s->str_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per string)\n", "strings", s->str_count, s->str_size, (double)s->str_size / s->str_count); } if (s->obj_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n", "objects", s->obj_count, s->obj_size, (double)s->obj_size / s->obj_count); fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n", " properties", s->prop_count, s->prop_size, (double)s->prop_count / s->obj_count); fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per shape)\n", " shapes", s->shape_count, s->shape_size, (double)s->shape_size / s->shape_count); } if (s->js_func_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n", "bytecode functions", s->js_func_count, s->js_func_size); fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n", " bytecode", s->js_func_count, s->js_func_code_size, (double)s->js_func_code_size / s->js_func_count); if (s->js_func_pc2line_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n", " pc2line", s->js_func_pc2line_count, s->js_func_pc2line_size, (double)s->js_func_pc2line_size / s->js_func_pc2line_count); } } if (s->c_func_count) { fprintf(fp, "%-20s %8"PRId64"\n", "C functions", s->c_func_count); } if (s->array_count) { fprintf(fp, "%-20s %8"PRId64"\n", "arrays", s->array_count); if (s->fast_array_count) { fprintf(fp, "%-20s %8"PRId64"\n", " fast arrays", s->fast_array_count); fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per fast array)\n", " elements", s->fast_array_elements, s->fast_array_elements * (int)sizeof(JSValue), (double)s->fast_array_elements / s->fast_array_count); } } if (s->binary_object_count) { fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n", "binary objects", s->binary_object_count, s->binary_object_size); } } JSValue JS_GetGlobalObject(JSContext *ctx) { return js_dup(ctx->global_obj); } /* WARNING: obj is freed */ JSValue JS_Throw(JSContext *ctx, JSValue obj) { JSRuntime *rt = ctx->rt; JS_FreeValue(ctx, rt->current_exception); rt->current_exception = obj; return JS_EXCEPTION; } /* return the pending exception (cannot be called twice). */ JSValue JS_GetException(JSContext *ctx) { JSValue val; JSRuntime *rt = ctx->rt; val = rt->current_exception; rt->current_exception = JS_UNINITIALIZED; return val; } bool JS_HasException(JSContext *ctx) { return !JS_IsUninitialized(ctx->rt->current_exception); } /* returns the pending backtrace (cannot be called twice). */ JSValue JS_GetBacktrace(JSContext *ctx) { JSValue val = ctx->error_back_trace; ctx->error_back_trace = JS_UNDEFINED; return val; } static void dbuf_put_leb128(DynBuf *s, uint32_t v) { uint32_t a; for(;;) { a = v & 0x7f; v >>= 7; if (v != 0) { dbuf_putc(s, a | 0x80); } else { dbuf_putc(s, a); break; } } } static void dbuf_put_sleb128(DynBuf *s, int32_t v1) { uint32_t v = v1; dbuf_put_leb128(s, (2 * v) ^ -(v >> 31)); } static int get_leb128(uint32_t *pval, const uint8_t *buf, const uint8_t *buf_end) { const uint8_t *ptr = buf; uint32_t v, a, i; v = 0; for(i = 0; i < 5; i++) { if (unlikely(ptr >= buf_end)) break; a = *ptr++; v |= (a & 0x7f) << (i * 7); if (!(a & 0x80)) { *pval = v; return ptr - buf; } } *pval = 0; return -1; } static int get_sleb128(int32_t *pval, const uint8_t *buf, const uint8_t *buf_end) { int ret; uint32_t val; ret = get_leb128(&val, buf, buf_end); if (ret < 0) { *pval = 0; return -1; } *pval = (val >> 1) ^ -(val & 1); return ret; } static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, uint32_t pc_value, int *col) { const uint8_t *p_end, *p; int new_line_num, new_col_num, line_num, col_num, pc, v, ret; unsigned int op; *col = 1; p = b->pc2line_buf; if (!p) goto fail; p_end = p + b->pc2line_len; pc = 0; line_num = b->line_num; col_num = b->col_num; while (p < p_end) { op = *p++; if (op == 0) { uint32_t val; ret = get_leb128(&val, p, p_end); if (ret < 0) goto fail; pc += val; p += ret; ret = get_sleb128(&v, p, p_end); if (ret < 0) goto fail; p += ret; new_line_num = line_num + v; } else { op -= PC2LINE_OP_FIRST; pc += (op / PC2LINE_RANGE); new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE; } ret = get_sleb128(&v, p, p_end); if (ret < 0) goto fail; p += ret; new_col_num = col_num + v; if (pc_value < pc) break; line_num = new_line_num; col_num = new_col_num; } *col = col_num; return line_num; fail: /* should never happen */ return b->line_num; } /* in order to avoid executing arbitrary code during the stack trace generation, we only look at simple 'name' properties containing a string. */ static const char *get_func_name(JSContext *ctx, JSValueConst func) { JSProperty *pr; JSShapeProperty *prs; JSValue val; if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT) return NULL; prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name); if (!prs) return NULL; if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) return NULL; val = pr->u.value; if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) return NULL; return JS_ToCString(ctx, val); } /* Note: it is important that no exception is returned by this function */ static bool can_add_backtrace(JSValueConst obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(obj); if (p->class_id != JS_CLASS_ERROR && p->class_id != JS_CLASS_DOM_EXCEPTION) return false; if (find_own_property1(p, JS_ATOM_stack)) return false; return true; } #define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0) /* only taken into account if filename is provided */ #define JS_BACKTRACE_FLAG_SINGLE_LEVEL (1 << 1) #define JS_BACKTRACE_FLAG_FILTER_FUNC (1 << 2) /* if filename != NULL, an additional level is added with the filename and line number information (used for parse error). */ static void build_backtrace(JSContext *ctx, JSValueConst error_val, JSValueConst filter_func, const char *filename, int line_num, int col_num, int backtrace_flags) { JSStackFrame *sf, *sf_start; JSValue stack, prepare, saved_exception; DynBuf dbuf; const char *func_name_str; const char *str1; JSObject *p; JSFunctionBytecode *b; bool backtrace_barrier, has_prepare, has_filter_func; JSRuntime *rt; JSCallSiteData csd[64]; uint32_t i; double d; int stack_trace_limit; rt = ctx->rt; if (rt->in_build_stack_trace) return; rt->in_build_stack_trace = true; // Save exception because conversion to double may fail. saved_exception = JS_GetException(ctx); // Extract stack trace limit. // Ignore error since it sets d to NAN anyway. // coverity[check_return] JS_ToFloat64(ctx, &d, ctx->error_stack_trace_limit); if (isnan(d) || d < 0.0) stack_trace_limit = 0; else if (d > INT32_MAX) stack_trace_limit = INT32_MAX; else stack_trace_limit = fabs(d); // Restore current exception. JS_Throw(ctx, saved_exception); saved_exception = JS_UNINITIALIZED; stack_trace_limit = min_int(stack_trace_limit, countof(csd)); stack_trace_limit = max_int(stack_trace_limit, 0); has_prepare = false; has_filter_func = backtrace_flags & JS_BACKTRACE_FLAG_FILTER_FUNC; i = 0; if (!JS_IsNull(ctx->error_ctor)) { prepare = js_dup(ctx->error_prepare_stack); has_prepare = JS_IsFunction(ctx, prepare); } if (has_prepare) { saved_exception = JS_GetException(ctx); if (stack_trace_limit == 0) goto done; if (filename) js_new_callsite_data2(ctx, &csd[i++], filename, line_num, col_num); } else { js_dbuf_init(ctx, &dbuf); if (stack_trace_limit == 0) goto done; if (filename) { i++; dbuf_printf(&dbuf, " at %s", filename); if (line_num != -1) dbuf_printf(&dbuf, ":%d:%d", line_num, col_num); dbuf_putc(&dbuf, '\n'); } } if (filename && (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)) goto done; sf_start = rt->current_stack_frame; /* Find the frame we want to start from. Note that when a filter is used the filter function will be the first, but we also specify we want to skip the first one. */ if (has_filter_func) { for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) { if (js_same_value(ctx, sf->cur_func, filter_func)) { sf_start = sf; break; } } } for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) { if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) { backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL; continue; } p = JS_VALUE_GET_OBJ(sf->cur_func); b = NULL; backtrace_barrier = false; if (js_class_has_bytecode(p->class_id)) { b = p->u.func.function_bytecode; backtrace_barrier = b->backtrace_barrier; } if (has_prepare) { js_new_callsite_data(ctx, &csd[i], sf); } else { /* func_name_str is UTF-8 encoded if needed */ func_name_str = get_func_name(ctx, sf->cur_func); if (!func_name_str || func_name_str[0] == '\0') str1 = ""; else str1 = func_name_str; dbuf_printf(&dbuf, " at %s", str1); JS_FreeCString(ctx, func_name_str); if (b && sf->cur_pc) { const char *atom_str; int line_num1, col_num1; uint32_t pc; pc = sf->cur_pc - b->byte_code_buf - 1; line_num1 = find_line_num(ctx, b, pc, &col_num1); atom_str = b->filename ? JS_AtomToCString(ctx, b->filename) : NULL; dbuf_printf(&dbuf, " (%s", atom_str ? atom_str : ""); JS_FreeCString(ctx, atom_str); if (line_num1 != -1) dbuf_printf(&dbuf, ":%d:%d", line_num1, col_num1); dbuf_putc(&dbuf, ')'); } else if (b) { // FIXME(bnoordhuis) Missing `sf->cur_pc = pc` in bytecode // handler in JS_CallInternal. Almost never user observable // except with intercepting JS proxies that throw exceptions. dbuf_printf(&dbuf, " (missing)"); } else { dbuf_printf(&dbuf, " (native)"); } dbuf_putc(&dbuf, '\n'); } i++; /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */ if (backtrace_barrier) break; } done: if (has_prepare) { int j = 0, k; stack = JS_NewArray(ctx); if (JS_IsException(stack)) { stack = JS_NULL; } else { for (; j < i; j++) { JSValue v = js_new_callsite(ctx, &csd[j]); if (JS_IsException(v)) break; if (JS_DefinePropertyValueUint32(ctx, stack, j, v, JS_PROP_C_W_E) < 0) { JS_FreeValue(ctx, v); break; } } } // Clear the csd's we didn't use in case of error. for (k = j; k < i; k++) { JS_FreeValue(ctx, csd[k].filename); JS_FreeValue(ctx, csd[k].func); JS_FreeValue(ctx, csd[k].func_name); } JSValueConst args[] = { error_val, stack, }; JSValue stack2 = JS_Call(ctx, prepare, ctx->error_ctor, countof(args), args); JS_FreeValue(ctx, stack); if (JS_IsException(stack2)) stack = JS_NULL; else stack = stack2; JS_FreeValue(ctx, prepare); JS_Throw(ctx, saved_exception); } else { if (dbuf_error(&dbuf)) stack = JS_NULL; else stack = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); dbuf_free(&dbuf); } if (JS_IsUndefined(ctx->error_back_trace)) ctx->error_back_trace = js_dup(stack); if (has_filter_func || can_add_backtrace(error_val)) { JS_DefinePropertyValue(ctx, error_val, JS_ATOM_stack, stack, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } else { JS_FreeValue(ctx, stack); } rt->in_build_stack_trace = false; } JSValue JS_NewError(JSContext *ctx) { JSValue obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR); if (JS_IsException(obj)) return JS_EXCEPTION; build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0); return obj; } static JSValue JS_MakeError2(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, const char *message) { JSValue obj, msg; if (error_num == JS_PLAIN_ERROR) { obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR); } else { obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num], JS_CLASS_ERROR); } if (JS_IsException(obj)) return JS_EXCEPTION; msg = JS_NewString(ctx, message); if (JS_IsException(msg)) msg = JS_NewString(ctx, "Invalid error message"); if (!JS_IsException(msg)) { JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } if (add_backtrace) build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0); return obj; } static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) JS_MakeError(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, JS_PRINTF_FORMAT const char *fmt, va_list ap) { char buf[256]; vsnprintf(buf, sizeof(buf), fmt, ap); return JS_MakeError2(ctx, error_num, add_backtrace, buf); } /* fmt and arguments may be pure ASCII or UTF-8 encoded contents */ static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, JS_PRINTF_FORMAT const char *fmt, va_list ap) { JSValue obj; obj = JS_MakeError(ctx, error_num, add_backtrace, fmt, ap); if (unlikely(JS_IsException(obj))) { /* out of memory: throw JS_NULL to avoid recursing */ obj = JS_NULL; } return JS_Throw(ctx, obj); } static JSValue JS_PRINTF_FORMAT_ATTR(3, 0) JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, JS_PRINTF_FORMAT const char *fmt, va_list ap) { JSRuntime *rt = ctx->rt; JSStackFrame *sf; bool add_backtrace; /* the backtrace is added later if called from a bytecode function */ sf = rt->current_stack_frame; add_backtrace = !rt->in_out_of_memory && (!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL)); return JS_ThrowError2(ctx, error_num, add_backtrace, fmt, ap); } #define JS_ERROR_MAP(X) \ X(Internal, INTERNAL) \ X(Plain, PLAIN) \ X(Range, RANGE) \ X(Reference, REFERENCE) \ X(Syntax, SYNTAX) \ X(Type, TYPE) \ #define X(lc, uc) \ JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ JS_New##lc##Error(JSContext *ctx, \ JS_PRINTF_FORMAT const char *fmt, ...) \ { \ JSValue val; \ va_list ap; \ \ va_start(ap, fmt); \ val = JS_MakeError(ctx, JS_##uc##_ERROR, \ /*add_backtrace*/true, fmt, ap); \ va_end(ap); \ return val; \ } \ JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ JS_Throw##lc##Error(JSContext *ctx, \ JS_PRINTF_FORMAT const char *fmt, ...) \ { \ JSValue val; \ va_list ap; \ \ va_start(ap, fmt); \ val = JS_ThrowError(ctx, JS_##uc##_ERROR, fmt, ap); \ va_end(ap); \ return val; \ } \ JS_ERROR_MAP(X) #undef X #undef JS_ERROR_MAP static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, JS_PRINTF_FORMAT const char *fmt, ...) { va_list ap; if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { va_start(ap, fmt); JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap); va_end(ap); return -1; } else { return false; } } #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif // __GNUC__ static JSValue JS_ThrowTypeErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom) { char buf[ATOM_GET_STR_BUF_SIZE]; JS_AtomGetStr(ctx, buf, sizeof(buf), atom); return JS_ThrowTypeError(ctx, fmt, buf); } static JSValue JS_ThrowSyntaxErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom) { char buf[ATOM_GET_STR_BUF_SIZE]; JS_AtomGetStr(ctx, buf, sizeof(buf), atom); return JS_ThrowSyntaxError(ctx, fmt, buf); } #ifdef __GNUC__ #pragma GCC diagnostic pop // ignored "-Wformat-nonliteral" #endif // __GNUC__ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) { if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom); return -1; } else { return false; } } JSValue JS_ThrowOutOfMemory(JSContext *ctx) { JSRuntime *rt = ctx->rt; if (!rt->in_out_of_memory) { rt->in_out_of_memory = true; JS_ThrowInternalError(ctx, "out of memory"); rt->in_out_of_memory = false; } return JS_EXCEPTION; } static JSValue JS_ThrowStackOverflow(JSContext *ctx) { return JS_ThrowRangeError(ctx, "Maximum call stack size exceeded"); } static JSValue JS_ThrowTypeErrorNotAConstructor(JSContext *ctx, JSValueConst func_obj) { JSObject *p; JSAtom name; if (JS_TAG_OBJECT != JS_VALUE_GET_TAG(func_obj)) goto fini; p = JS_VALUE_GET_OBJ(func_obj); if (!js_class_has_bytecode(p->class_id)) goto fini; name = p->u.func.function_bytecode->func_name; if (name == JS_ATOM_NULL) goto fini; return JS_ThrowTypeErrorAtom(ctx, "%s is not a constructor", name); fini: return JS_ThrowTypeError(ctx, "not a constructor"); } static JSValue JS_ThrowTypeErrorNotAFunction(JSContext *ctx) { return JS_ThrowTypeError(ctx, "not a function"); } static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx) { return JS_ThrowTypeError(ctx, "not an object"); } static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx) { return JS_ThrowTypeError(ctx, "not a symbol"); } static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name) { char buf[ATOM_GET_STR_BUF_SIZE]; return JS_ThrowReferenceError(ctx, "%s is not defined", JS_AtomGetStr(ctx, buf, sizeof(buf), name)); } static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name) { char buf[ATOM_GET_STR_BUF_SIZE]; return JS_ThrowReferenceError(ctx, "%s is not initialized", name == JS_ATOM_NULL ? "lexical variable" : JS_AtomGetStr(ctx, buf, sizeof(buf), name)); } static JSValue JS_ThrowReferenceErrorUninitialized2(JSContext *ctx, JSFunctionBytecode *b, int idx, bool is_ref) { JSAtom atom = JS_ATOM_NULL; if (is_ref) { atom = b->closure_var[idx].var_name; } else { /* not present if the function is stripped and contains no eval() */ if (b->vardefs) atom = b->vardefs[b->arg_count + idx].var_name; } return JS_ThrowReferenceErrorUninitialized(ctx, atom); } static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id) { JSRuntime *rt = ctx->rt; JSAtom name; name = rt->class_array[class_id].class_name; return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name); } static void JS_ThrowInterrupted(JSContext *ctx) { JS_ThrowInternalError(ctx, "interrupted"); JS_SetUncatchableError(ctx, ctx->rt->current_exception); } static no_inline __exception int __js_poll_interrupts(JSContext *ctx) { JSRuntime *rt = ctx->rt; ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT; if (rt->interrupt_handler) { if (rt->interrupt_handler(rt, rt->interrupt_opaque)) { JS_ThrowInterrupted(ctx); return -1; } } return 0; } static inline __exception int js_poll_interrupts(JSContext *ctx) { if (unlikely(--ctx->interrupt_counter <= 0)) { return __js_poll_interrupts(ctx); } else { return 0; } } /* return -1 (exception) or true/false */ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, JSValueConst proto_val, bool throw_flag) { JSObject *proto, *p, *p1; JSShape *sh; if (throw_flag) { if (JS_VALUE_GET_TAG(obj) == JS_TAG_NULL || JS_VALUE_GET_TAG(obj) == JS_TAG_UNDEFINED) goto not_obj; } else { if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) goto not_obj; } p = JS_VALUE_GET_OBJ(obj); if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) { if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_NULL) { not_obj: JS_ThrowTypeErrorNotAnObject(ctx); return -1; } proto = NULL; } else { proto = JS_VALUE_GET_OBJ(proto_val); } if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return true; if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag); sh = p->shape; if (sh->proto == proto) return true; if (p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) { if (throw_flag) { JS_ThrowTypeError(ctx, "'Immutable prototype object \'Object.prototype\' cannot have their prototype set'"); return -1; } return false; } if (!p->extensible) { if (throw_flag) { JS_ThrowTypeError(ctx, "object is not extensible"); return -1; } else { return false; } } if (proto) { /* check if there is a cycle */ p1 = proto; do { if (p1 == p) { if (throw_flag) { JS_ThrowTypeError(ctx, "circular prototype chain"); return -1; } else { return false; } } /* Note: for Proxy objects, proto is NULL */ p1 = p1->shape->proto; } while (p1 != NULL); js_dup(proto_val); } if (js_shape_prepare_update(ctx, p, NULL)) return -1; sh = p->shape; if (sh->proto) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); sh->proto = proto; return true; } /* return -1 (exception) or true/false */ int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val) { return JS_SetPrototypeInternal(ctx, obj, proto_val, true); } /* Only works for primitive types, otherwise return JS_NULL. */ static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val) { JSValue ret; switch(JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: ret = ctx->class_proto[JS_CLASS_BIG_INT]; break; case JS_TAG_INT: case JS_TAG_FLOAT64: ret = ctx->class_proto[JS_CLASS_NUMBER]; break; case JS_TAG_BOOL: ret = ctx->class_proto[JS_CLASS_BOOLEAN]; break; case JS_TAG_STRING: ret = ctx->class_proto[JS_CLASS_STRING]; break; case JS_TAG_SYMBOL: ret = ctx->class_proto[JS_CLASS_SYMBOL]; break; case JS_TAG_OBJECT: case JS_TAG_NULL: case JS_TAG_UNDEFINED: default: ret = JS_NULL; break; } return ret; } /* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) { JSValue val; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p; p = JS_VALUE_GET_OBJ(obj); if (unlikely(p->class_id == JS_CLASS_PROXY)) { val = js_proxy_getPrototypeOf(ctx, obj); } else { p = p->shape->proto; if (!p) val = JS_NULL; else val = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); } } else { val = js_dup(JS_GetPrototypePrimitive(ctx, obj)); } return val; } static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj) { JSValue obj1; obj1 = JS_GetPrototype(ctx, obj); JS_FreeValue(ctx, obj); return obj1; } int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres) { return js_get_length64(ctx, pres, obj); } int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len) { return js_set_length64(ctx, obj, len); } /* return true, false or (-1) in case of exception */ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) { JSValue obj_proto; JSObject *proto; const JSObject *p, *proto1; int ret; if (!JS_IsFunction(ctx, obj)) return false; p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_BOUND_FUNCTION) { JSBoundFunction *s = p->u.bound_function; return JS_IsInstanceOf(ctx, val, s->func_obj); } /* Only explicitly boxed values are instances of constructors */ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return false; obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype); if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) { if (!JS_IsException(obj_proto)) JS_ThrowTypeError(ctx, "operand 'prototype' property is not an object"); ret = -1; goto done; } proto = JS_VALUE_GET_OBJ(obj_proto); p = JS_VALUE_GET_OBJ(val); for(;;) { proto1 = p->shape->proto; if (!proto1) { /* slow case if proxy in the prototype chain */ if (unlikely(p->class_id == JS_CLASS_PROXY)) { JSValue obj1; obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); for(;;) { obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsException(obj1)) { ret = -1; break; } if (JS_IsNull(obj1)) { ret = false; break; } if (proto == JS_VALUE_GET_OBJ(obj1)) { JS_FreeValue(ctx, obj1); ret = true; break; } /* must check for timeout to avoid infinite loop */ if (js_poll_interrupts(ctx)) { JS_FreeValue(ctx, obj1); ret = -1; break; } } } else { ret = false; } break; } p = proto1; if (proto == p) { ret = true; break; } } done: JS_FreeValue(ctx, obj_proto); return ret; } /* return true, false or (-1) in case of exception */ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) { JSValue method; if (!JS_IsObject(obj)) goto fail; method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_hasInstance); if (JS_IsException(method)) return -1; if (!JS_IsNull(method) && !JS_IsUndefined(method)) { JSValue ret; ret = JS_CallFree(ctx, method, obj, 1, &val); return JS_ToBoolFree(ctx, ret); } /* legacy case */ if (!JS_IsFunction(ctx, obj)) { fail: JS_ThrowTypeError(ctx, "invalid 'instanceof' right operand"); return -1; } return JS_OrdinaryIsInstanceOf(ctx, val, obj); } #include "builtin-array-fromasync.h" static JSValue js_bytecode_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { switch ((uintptr_t)opaque) { default: abort(); case JS_BUILTIN_ARRAY_FROMASYNC: { JSValue obj = JS_ReadObject(ctx, qjsc_builtin_array_fromasync, sizeof(qjsc_builtin_array_fromasync), JS_READ_OBJ_BYTECODE); if (JS_IsException(obj)) return JS_EXCEPTION; JSValue fun = JS_EvalFunction(ctx, obj); if (JS_IsException(fun)) return JS_EXCEPTION; assert(JS_IsFunction(ctx, fun)); JSValue args[] = { JS_NewCFunction(ctx, js_array_constructor, "Array", 0), JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", 1, JS_CFUNC_constructor_or_func_magic, JS_TYPE_ERROR), JS_AtomToValue(ctx, JS_ATOM_Symbol_asyncIterator), JS_NewCFunctionMagic(ctx, js_object_defineProperty, "Object.defineProperty", 3, JS_CFUNC_generic_magic, 0), JS_AtomToValue(ctx, JS_ATOM_Symbol_iterator), }; JSValue result = JS_Call(ctx, fun, JS_UNDEFINED, countof(args), vc(args)); for (size_t i = 0; i < countof(args); i++) JS_FreeValue(ctx, args[i]); JS_FreeValue(ctx, fun); if (JS_SetPrototypeInternal(ctx, result, ctx->function_proto, /*throw_flag*/true) < 0) { JS_FreeValue(ctx, result); return JS_EXCEPTION; } return result; } } return JS_UNDEFINED; } /* return the value associated to the autoinit property or an exception */ typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSAutoInitFunc *const js_autoinit_func_table[] = { js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */ js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */ JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */ js_bytecode_autoinit, /* JS_AUTOINIT_ID_BYTECODE */ }; /* warning: 'prs' is reallocated after it */ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSProperty *pr, JSShapeProperty *prs) { JSValue val; JSContext *realm; JSAutoInitFunc *func; if (js_shape_prepare_update(ctx, p, &prs)) return -1; realm = js_autoinit_get_realm(pr); func = js_autoinit_func_table[js_autoinit_get_id(pr)]; /* 'func' shall not modify the object properties 'pr' */ val = func(realm, p, prop, pr->u.init.opaque); js_autoinit_free(ctx->rt, pr); prs->flags &= ~JS_PROP_TMASK; pr->u.value = JS_UNDEFINED; if (JS_IsException(val)) return -1; pr->u.value = val; return 0; } static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst this_obj, bool throw_ref_error) { JSObject *p; JSProperty *pr; JSShapeProperty *prs; uint32_t tag; tag = JS_VALUE_GET_TAG(obj); if (unlikely(tag != JS_TAG_OBJECT)) { switch(tag) { case JS_TAG_NULL: return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop); case JS_TAG_UNDEFINED: return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", prop); case JS_TAG_EXCEPTION: return JS_EXCEPTION; case JS_TAG_STRING: { JSString *p1 = JS_VALUE_GET_STRING(obj); if (__JS_AtomIsTaggedInt(prop)) { uint32_t idx, ch; idx = __JS_AtomToUInt32(prop); if (idx < p1->len) { ch = string_get(p1, idx); return js_new_string_char(ctx, ch); } } else if (prop == JS_ATOM_length) { return js_int32(p1->len); } } break; default: break; } /* cannot raise an exception */ p = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj)); if (!p) return JS_UNDEFINED; } else { p = JS_VALUE_GET_OBJ(obj); } for(;;) { prs = find_own_property(&pr, p, prop); if (prs) { /* found */ if (unlikely(prs->flags & JS_PROP_TMASK)) { if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { if (unlikely(!pr->u.getset.getter)) { return JS_UNDEFINED; } else { JSValue func = JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter); /* Note: the field could be removed in the getter */ func = js_dup(func); return JS_CallFree(ctx, func, this_obj, 0, NULL); } } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { JSValue val = *pr->u.var_ref->pvalue; if (unlikely(JS_IsUninitialized(val))) return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return js_dup(val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) return JS_EXCEPTION; continue; } } else { if (JS_IsUndefined(pr->u.value) && ctx->handleUndefined) ctx->handleUndefined(ctx); return js_dup(pr->u.value); } } if (unlikely(p->is_exotic)) { /* exotic behaviors */ if (p->fast_array) { if (__JS_AtomIsTaggedInt(prop)) { uint32_t idx = __JS_AtomToUInt32(prop); if (idx < p->u.array.count) { /* we avoid duplicating the code */ return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); } else if (is_typed_array(p->class_id)) { return JS_UNDEFINED; } } else if (is_typed_array(p->class_id)) { int ret; ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) return JS_EXCEPTION; return JS_UNDEFINED; } } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { if (em->get_property) { JSValue obj1, retval; /* XXX: should pass throw_ref_error */ /* Note: if 'p' is a prototype, it can be freed in the called function */ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); retval = em->get_property(ctx, obj1, prop, this_obj); JS_FreeValue(ctx, obj1); return retval; } if (em->get_own_property) { JSPropertyDescriptor desc; int ret; JSValue obj1; /* Note: if 'p' is a prototype, it can be freed in the called function */ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); if (ret < 0) return JS_EXCEPTION; if (ret) { if (desc.flags & JS_PROP_GETSET) { JS_FreeValue(ctx, desc.setter); return JS_CallFree(ctx, desc.getter, this_obj, 0, NULL); } else { return desc.value; } } } } } } p = p->shape->proto; if (!p) break; } if (unlikely(throw_ref_error)) { return JS_ThrowReferenceErrorNotDefined(ctx, prop); } else { return JS_UNDEFINED; } } JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop) { return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, false); } static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) { return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist", atom); } /* Private fields can be added even on non extensible objects or Proxies */ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, JSValue name, JSValue val) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; JSAtom prop; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); goto fail; } /* safety check */ if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) { JS_ThrowTypeErrorNotASymbol(ctx); goto fail; } prop = js_symbol_to_atom(ctx, name); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (prs) { JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists", prop); goto fail; } pr = add_property(ctx, p, prop, JS_PROP_C_W_E); if (unlikely(!pr)) { fail: JS_FreeValue(ctx, val); return -1; } pr->u.value = val; return 0; } static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj, JSValueConst name) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; JSAtom prop; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return JS_ThrowTypeErrorNotAnObject(ctx); /* safety check */ if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) return JS_ThrowTypeErrorNotASymbol(ctx); prop = js_symbol_to_atom(ctx, name); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (!prs) { JS_ThrowTypeErrorPrivateNotFound(ctx, prop); return JS_EXCEPTION; } return js_dup(pr->u.value); } static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, JSValueConst name, JSValue val) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; JSAtom prop; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); goto fail; } /* safety check */ if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) { JS_ThrowTypeErrorNotASymbol(ctx); goto fail; } prop = js_symbol_to_atom(ctx, name); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (!prs) { JS_ThrowTypeErrorPrivateNotFound(ctx, prop); fail: JS_FreeValue(ctx, val); return -1; } set_value(ctx, &pr->u.value, val); return 0; } /* add a private brand field to 'home_obj' if not already present and if obj is != null add a private brand to it */ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) { JSObject *p, *p1; JSShapeProperty *prs; JSProperty *pr; JSValue brand; JSAtom brand_atom; if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; } p = JS_VALUE_GET_OBJ(home_obj); prs = find_own_property(&pr, p, JS_ATOM_Private_brand); if (!prs) { /* if the brand is not present, add it */ brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE); if (JS_IsException(brand)) return -1; pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E); if (!pr) { JS_FreeValue(ctx, brand); return -1; } pr->u.value = js_dup(brand); } else { brand = js_dup(pr->u.value); } brand_atom = js_symbol_to_atom(ctx, brand); if (JS_IsObject(obj)) { p1 = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p1, brand_atom); if (unlikely(prs)) { JS_FreeAtom(ctx, brand_atom); JS_ThrowTypeError(ctx, "private method is already present"); return -1; } pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E); JS_FreeAtom(ctx, brand_atom); if (!pr) return -1; pr->u.value = JS_UNDEFINED; } else { JS_FreeAtom(ctx, brand_atom); } return 0; } /* return a boolean telling if the brand of the home object of 'func' is present on 'obj' or -1 in case of exception */ static int JS_CheckBrand(JSContext *ctx, JSValue obj, JSValue func) { JSObject *p, *p1, *home_obj; JSShapeProperty *prs; JSProperty *pr; JSValue brand; /* get the home object of 'func' */ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) goto not_obj; p1 = JS_VALUE_GET_OBJ(func); if (!js_class_has_bytecode(p1->class_id)) goto not_obj; home_obj = p1->u.func.home_object; if (!home_obj) goto not_obj; prs = find_own_property(&pr, home_obj, JS_ATOM_Private_brand); if (!prs) { JS_ThrowTypeError(ctx, "expecting private field"); return -1; } brand = pr->u.value; /* safety check */ if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL)) goto not_obj; /* get the brand array of 'obj' */ if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { not_obj: JS_ThrowTypeErrorNotAnObject(ctx); return -1; } p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand)); return (prs != NULL); } static uint32_t js_string_obj_get_length(JSContext *ctx, JSValueConst obj) { JSObject *p; JSString *p1; uint32_t len = 0; /* This is a class exotic method: obj class_id is JS_CLASS_STRING */ p = JS_VALUE_GET_OBJ(obj); if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) { p1 = JS_VALUE_GET_STRING(p->u.object_data); len = p1->len; } return len; } static int num_keys_cmp(const void *p1, const void *p2, void *opaque) { JSContext *ctx = opaque; JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom; JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom; uint32_t v1, v2; bool atom1_is_integer, atom2_is_integer; atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1); atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2); assert(atom1_is_integer && atom2_is_integer); if (v1 < v2) return -1; else if (v1 == v2) return 0; else return 1; } static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) { uint32_t i; if (tab) { for(i = 0; i < len; i++) JS_FreeAtom(ctx, tab[i].atom); js_free(ctx, tab); } } /* return < 0 in case if exception, 0 if OK. ptab and its atoms must be freed by the user. */ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, JSObject *p, int flags) { int i, j; JSShape *sh; JSShapeProperty *prs; JSPropertyEnum *tab_atom, *tab_exotic; JSAtom atom; uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count; uint32_t num_index, str_index, sym_index, exotic_count, exotic_keys_count; bool is_enumerable, num_sorted; uint32_t num_key; JSAtomKindEnum kind; /* clear pointer for consistency in case of failure */ *ptab = NULL; *plen = 0; /* compute the number of returned properties */ num_keys_count = 0; str_keys_count = 0; sym_keys_count = 0; exotic_keys_count = 0; exotic_count = 0; tab_exotic = NULL; sh = p->shape; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && ((flags >> kind) & 1) != 0) { /* need to raise an exception in case of the module name space (implicit GetOwnProperty) */ if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) && (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY))) { JSVarRef *var_ref = p->prop[i].u.var_ref; if (unlikely(JS_IsUninitialized(*var_ref->pvalue))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } } if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { num_keys_count++; } else if (kind == JS_ATOM_KIND_STRING) { str_keys_count++; } else { sym_keys_count++; } } } } if (p->is_exotic) { if (p->fast_array) { if (flags & JS_GPN_STRING_MASK) { num_keys_count += p->u.array.count; } } else if (p->class_id == JS_CLASS_STRING) { if (flags & JS_GPN_STRING_MASK) { num_keys_count += js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->get_own_property_names) { if (em->get_own_property_names(ctx, &tab_exotic, &exotic_count, JS_MKPTR(JS_TAG_OBJECT, p))) return -1; for(i = 0; i < exotic_count; i++) { atom = tab_exotic[i].atom; kind = JS_AtomGetKind(ctx, atom); if (((flags >> kind) & 1) != 0) { is_enumerable = false; if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) { JSPropertyDescriptor desc; int res; /* set the "is_enumerable" field if necessary */ res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); if (res < 0) { js_free_prop_enum(ctx, tab_exotic, exotic_count); return -1; } if (res) { is_enumerable = ((desc.flags & JS_PROP_ENUMERABLE) != 0); js_free_desc(ctx, &desc); } tab_exotic[i].is_enumerable = is_enumerable; } if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) { exotic_keys_count++; } } } } } } /* fill them */ atom_count = num_keys_count + str_keys_count + sym_keys_count + exotic_keys_count; /* avoid allocating 0 bytes */ tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1)); if (!tab_atom) { js_free_prop_enum(ctx, tab_exotic, exotic_count); return -1; } num_index = 0; str_index = num_keys_count; sym_index = str_index + str_keys_count; num_sorted = true; sh = p->shape; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && ((flags >> kind) & 1) != 0) { if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; num_sorted = false; } else if (kind == JS_ATOM_KIND_STRING) { j = str_index++; } else { j = sym_index++; } tab_atom[j].atom = JS_DupAtom(ctx, atom); tab_atom[j].is_enumerable = is_enumerable; } } } if (p->is_exotic) { int len; if (p->fast_array) { if (flags & JS_GPN_STRING_MASK) { len = p->u.array.count; goto add_array_keys; } } else if (p->class_id == JS_CLASS_STRING) { if (flags & JS_GPN_STRING_MASK) { len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); add_array_keys: for(i = 0; i < len; i++) { tab_atom[num_index].atom = __JS_AtomFromUInt32(i); if (tab_atom[num_index].atom == JS_ATOM_NULL) { js_free_prop_enum(ctx, tab_atom, num_index); return -1; } tab_atom[num_index].is_enumerable = true; num_index++; } } } else { /* Note: exotic keys are not reordered and comes after the object own properties. */ for(i = 0; i < exotic_count; i++) { atom = tab_exotic[i].atom; is_enumerable = tab_exotic[i].is_enumerable; kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && ((flags >> kind) & 1) != 0) { tab_atom[sym_index].atom = atom; tab_atom[sym_index].is_enumerable = is_enumerable; sym_index++; } else { JS_FreeAtom(ctx, atom); } } js_free(ctx, tab_exotic); } } assert(num_index == num_keys_count); assert(str_index == num_keys_count + str_keys_count); assert(sym_index == atom_count); if (num_keys_count != 0 && !num_sorted) { rqsort(tab_atom, num_keys_count, sizeof(tab_atom[0]), num_keys_cmp, ctx); } *ptab = tab_atom; *plen = atom_count; return 0; } int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, JSValueConst obj, int flags) { if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; } return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen, JS_VALUE_GET_OBJ(obj), flags); } /* Return -1 if exception, false if the property does not exist, true if it exists. If true is returned, the property descriptor 'desc' is filled present. */ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop) { JSShapeProperty *prs; JSProperty *pr; retry: prs = find_own_property(&pr, p, prop); if (prs) { if (desc) { desc->flags = prs->flags & JS_PROP_C_W_E; desc->getter = JS_UNDEFINED; desc->setter = JS_UNDEFINED; desc->value = JS_UNDEFINED; if (unlikely(prs->flags & JS_PROP_TMASK)) { if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { desc->flags |= JS_PROP_GETSET; if (pr->u.getset.getter) desc->getter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (pr->u.getset.setter) desc->setter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { JSValue val = *pr->u.var_ref->pvalue; if (unlikely(JS_IsUninitialized(val))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } desc->value = js_dup(val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) return -1; goto retry; } } else { desc->value = js_dup(pr->u.value); } } else { /* for consistency, send the exception even if desc is NULL */ if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF)) { if (unlikely(JS_IsUninitialized(*pr->u.var_ref->pvalue))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* nothing to do: delay instantiation until actual value and/or attributes are read */ } } return true; } if (p->is_exotic) { if (p->fast_array) { /* specific case for fast arrays */ if (__JS_AtomIsTaggedInt(prop)) { uint32_t idx; idx = __JS_AtomToUInt32(prop); if (idx < p->u.array.count) { if (desc) { desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE; desc->getter = JS_UNDEFINED; desc->setter = JS_UNDEFINED; desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); } return true; } } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->get_own_property) { return em->get_own_property(ctx, desc, JS_MKPTR(JS_TAG_OBJECT, p), prop); } } } return false; } int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) { if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; } return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop); } void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) { js_free_prop_enum(ctx, tab, len); } /* return -1 if exception (Proxy object only) or true/false */ int JS_IsExtensible(JSContext *ctx, JSValueConst obj) { JSObject *p; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return false; p = JS_VALUE_GET_OBJ(obj); if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_isExtensible(ctx, obj); else return p->extensible; } /* return -1 if exception (Proxy object only) or true/false */ int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) { JSObject *p; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return false; p = JS_VALUE_GET_OBJ(obj); if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_preventExtensions(ctx, obj); p->extensible = false; return true; } /* return -1 if exception otherwise true or false */ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) { JSObject *p; int ret; JSValue obj1; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return false; p = JS_VALUE_GET_OBJ(obj); for(;;) { if (p->is_exotic) { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->has_property) { /* has_property can free the prototype */ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); ret = em->has_property(ctx, obj1, prop); JS_FreeValue(ctx, obj1); return ret; } } /* JS_GetOwnPropertyInternal can free the prototype */ js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop); JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); if (ret != 0) return ret; if (is_typed_array(p->class_id)) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) return -1; return false; } } p = p->shape->proto; if (!p) break; } return false; } /* val must be a symbol */ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValueConst val) { JSAtomStruct *p = JS_VALUE_GET_PTR(val); return js_get_atom_index(ctx->rt, p); } /* return JS_ATOM_NULL in case of exception */ static JSAtom JS_ValueToAtomInternal(JSContext *ctx, JSValueConst val, int flags) { JSAtom atom; uint32_t tag; tag = JS_VALUE_GET_TAG(val); if (tag == JS_TAG_INT && (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) { /* fast path for integer values */ atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val)); } else if (tag == JS_TAG_SYMBOL) { JSAtomStruct *p = JS_VALUE_GET_PTR(val); atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p)); } else { JSValue str; str = JS_ToPropertyKeyInternal(ctx, val, flags); if (JS_IsException(str)) return JS_ATOM_NULL; if (JS_VALUE_GET_TAG(str) == JS_TAG_SYMBOL) { atom = js_symbol_to_atom(ctx, str); } else { atom = JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(str)); } } return atom; } JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) { return JS_ValueToAtomInternal(ctx, val, /*flags*/0); } static bool js_get_fast_array_element(JSContext *ctx, JSObject *p, uint32_t idx, JSValue *pval) { switch(p->class_id) { case JS_CLASS_ARRAY: case JS_CLASS_ARGUMENTS: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_dup(p->u.array.u.values[idx]); return true; case JS_CLASS_INT8_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.int8_ptr[idx]); return true; case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_UINT8_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.uint8_ptr[idx]); return true; case JS_CLASS_INT16_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.int16_ptr[idx]); return true; case JS_CLASS_UINT16_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.uint16_ptr[idx]); return true; case JS_CLASS_INT32_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.int32_ptr[idx]); return true; case JS_CLASS_UINT32_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_uint32(p->u.array.u.uint32_ptr[idx]); return true; case JS_CLASS_BIG_INT64_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]); return true; case JS_CLASS_BIG_UINT64_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]); return true; case JS_CLASS_FLOAT16_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_float64(fromfp16(p->u.array.u.fp16_ptr[idx])); return true; case JS_CLASS_FLOAT32_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_float64(p->u.array.u.float_ptr[idx]); return true; case JS_CLASS_FLOAT64_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_float64(p->u.array.u.double_ptr[idx]); return true; default: return false; } } static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop) { JSAtom atom; JSValue ret; uint32_t tag; tag = JS_VALUE_GET_TAG(this_obj); if (likely(tag == JS_TAG_OBJECT)) { if (JS_VALUE_GET_TAG(prop) == JS_TAG_INT) { JSObject *p = JS_VALUE_GET_OBJ(this_obj); uint32_t idx = JS_VALUE_GET_INT(prop); JSValue val; /* fast path for array and typed array access */ if (js_get_fast_array_element(ctx, p, idx, &val)) return val; } } else if (unlikely(tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)) { // per spec: not allowed to call ToPropertyKey before ToObject // so we must ensure to not invoke JS anything that's observable // from JS code atom = JS_ValueToAtomInternal(ctx, prop, JS_TO_STRING_NO_SIDE_EFFECTS); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; if (tag == JS_TAG_NULL) { JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", atom); } else { JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", atom); } JS_FreeAtom(ctx, atom); return JS_EXCEPTION; } atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; ret = JS_GetProperty(ctx, this_obj, atom); JS_FreeAtom(ctx, atom); return ret; } JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx) { return JS_GetPropertyInt64(ctx, this_obj, idx); } /* Check if an object has a generalized numeric property. Return value: -1 for exception, *pval set to JS_EXCEPTION true if property exists, stored into *pval, false if property does not exist. *pval set to JS_UNDEFINED. */ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval) { JSValue val; JSAtom prop; int present; if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT && (uint64_t)idx <= INT32_MAX)) { /* fast path for array and typed array access */ JSObject *p = JS_VALUE_GET_OBJ(obj); if (js_get_fast_array_element(ctx, p, idx, pval)) return true; } val = JS_EXCEPTION; present = -1; prop = JS_NewAtomInt64(ctx, idx); if (likely(prop != JS_ATOM_NULL)) { present = JS_HasProperty(ctx, obj, prop); if (present > 0) { val = JS_GetProperty(ctx, obj, prop); if (unlikely(JS_IsException(val))) present = -1; } else if (present == false) { val = JS_UNDEFINED; } JS_FreeAtom(ctx, prop); } *pval = val; return present; } JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) { JSAtom prop; JSValue val; if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT && (uint64_t)idx <= INT32_MAX)) { /* fast path for array and typed array access */ JSObject *p = JS_VALUE_GET_OBJ(obj); if (js_get_fast_array_element(ctx, p, idx, &val)) return val; } prop = JS_NewAtomInt64(ctx, idx); if (prop == JS_ATOM_NULL) return JS_EXCEPTION; val = JS_GetProperty(ctx, obj, prop); JS_FreeAtom(ctx, prop); return val; } /* `prop` may be pure ASCII or UTF-8 encoded */ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop) { JSAtom atom; JSValue ret; atom = JS_NewAtom(ctx, prop); if (atom == JS_ATOM_NULL) return JS_EXCEPTION; ret = JS_GetProperty(ctx, this_obj, atom); JS_FreeAtom(ctx, atom); return ret; } /* Note: the property value is not initialized. Return NULL if memory error. */ static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags) { JSShape *sh, *new_sh; sh = p->shape; if (sh->is_hashed) { /* try to find an existing shape */ new_sh = find_hashed_shape_prop(ctx->rt, sh, prop, prop_flags); if (new_sh) { /* matching shape found: use it */ /* the property array may need to be resized */ if (new_sh->prop_size != sh->prop_size) { JSProperty *new_prop; new_prop = js_realloc(ctx, p->prop, sizeof(p->prop[0]) * new_sh->prop_size); if (!new_prop) return NULL; p->prop = new_prop; } p->shape = js_dup_shape(new_sh); js_free_shape(ctx->rt, sh); return &p->prop[new_sh->prop_count - 1]; } else if (sh->header.ref_count != 1) { /* if the shape is shared, clone it */ new_sh = js_clone_shape(ctx, sh); if (!new_sh) return NULL; /* hash the cloned shape */ new_sh->is_hashed = true; js_shape_hash_link(ctx->rt, new_sh); js_free_shape(ctx->rt, p->shape); p->shape = new_sh; } } assert(p->shape->header.ref_count == 1); if (add_shape_property(ctx, &p->shape, p, prop, prop_flags)) return NULL; return &p->prop[p->shape->prop_count - 1]; } /* can be called on Array or Arguments objects. return < 0 if memory alloc error. */ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx, JSObject *p) { JSProperty *pr; JSShape *sh; JSValue *tab; uint32_t i, len, new_count; if (js_shape_prepare_update(ctx, p, NULL)) return -1; len = p->u.array.count; /* resize the properties once to simplify the error handling */ sh = p->shape; new_count = sh->prop_count + len; if (new_count > sh->prop_size) { if (resize_properties(ctx, &p->shape, p, new_count)) return -1; } tab = p->u.array.u.values; for(i = 0; i < len; i++) { /* add_property cannot fail here but __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E); pr->u.value = *tab++; } js_free(ctx, p->u.array.u.values); p->u.array.count = 0; p->u.array.u.values = NULL; /* fail safe */ p->u.array.u1.size = 0; p->fast_array = 0; return 0; } static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) { JSShape *sh; JSShapeProperty *pr, *lpr, *prop; JSProperty *pr1; uint32_t lpr_idx; intptr_t h, h1; redo: sh = p->shape; h1 = atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h1 - 1]; prop = get_shape_prop(sh); lpr = NULL; lpr_idx = 0; /* prevent warning */ while (h != 0) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { /* found ! */ if (!(pr->flags & JS_PROP_CONFIGURABLE)) return false; /* realloc the shape if needed */ if (lpr) lpr_idx = lpr - get_shape_prop(sh); if (js_shape_prepare_update(ctx, p, &pr)) return -1; sh = p->shape; /* remove property */ if (lpr) { lpr = get_shape_prop(sh) + lpr_idx; lpr->hash_next = pr->hash_next; } else { prop_hash_end(sh)[-h1 - 1] = pr->hash_next; } sh->deleted_prop_count++; /* free the entry */ pr1 = &p->prop[h - 1]; free_property(ctx->rt, pr1, pr->flags); JS_FreeAtom(ctx, pr->atom); /* put default values */ pr->flags = 0; pr->atom = JS_ATOM_NULL; pr1->u.value = JS_UNDEFINED; /* compact the properties if too many deleted properties */ if (sh->deleted_prop_count >= 8 && sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) { compact_properties(ctx, p); } return true; } lpr = pr; h = pr->hash_next; } if (p->is_exotic) { if (p->fast_array) { uint32_t idx; if (JS_AtomIsArrayIndex(ctx, &idx, atom) && idx < p->u.array.count) { if (p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) { /* Special case deleting the last element of a fast Array */ if (idx == p->u.array.count - 1) { JS_FreeValue(ctx, p->u.array.u.values[idx]); p->u.array.count = idx; return true; } if (convert_fast_array_to_array(ctx, p)) return -1; goto redo; } else { return false; } } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->delete_property) { return em->delete_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), atom); } } } /* not found */ return true; } static int call_setter(JSContext *ctx, JSObject *setter, JSValueConst this_obj, JSValue val, int flags) { JSValue ret, func; if (likely(setter)) { func = JS_MKPTR(JS_TAG_OBJECT, setter); /* Note: the field could be removed in the setter */ func = js_dup(func); ret = JS_CallFree(ctx, func, this_obj, 1, vc(&val)); JS_FreeValue(ctx, val); if (JS_IsException(ret)) return -1; JS_FreeValue(ctx, ret); return true; } else { JS_FreeValue(ctx, val); if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { JS_ThrowTypeError(ctx, "no setter for property"); return -1; } return false; } } /* set the array length and remove the array elements if necessary. */ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int flags) { uint32_t len, idx, cur_len; int i, ret; /* Note: this call can reallocate the properties of 'p' */ ret = JS_ToArrayLengthFree(ctx, &len, val, false); if (ret) return -1; /* JS_ToArrayLengthFree() must be done before the read-only test */ if (unlikely(!(p->shape->prop[0].flags & JS_PROP_WRITABLE))) return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); if (likely(p->fast_array)) { uint32_t old_len = p->u.array.count; if (len < old_len) { for(i = len; i < old_len; i++) { JS_FreeValue(ctx, p->u.array.u.values[i]); } p->u.array.count = len; } p->prop[0].u.value = js_uint32(len); } else { /* Note: length is always a uint32 because the object is an array */ JS_ToUint32(ctx, &cur_len, p->prop[0].u.value); if (len < cur_len) { uint32_t d; JSShape *sh; JSShapeProperty *pr; d = cur_len - len; sh = p->shape; if (d <= sh->prop_count) { JSAtom atom; /* faster to iterate */ while (cur_len > len) { atom = JS_NewAtomUInt32(ctx, cur_len - 1); ret = delete_property(ctx, p, atom); JS_FreeAtom(ctx, atom); if (unlikely(!ret)) { /* unlikely case: property is not configurable */ break; } cur_len--; } } else { /* faster to iterate thru all the properties. Need two passes in case one of the property is not configurable */ cur_len = len; for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { if (idx >= cur_len && !(pr->flags & JS_PROP_CONFIGURABLE)) { cur_len = idx + 1; } } } for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { if (idx >= cur_len) { /* remove the property */ delete_property(ctx, p, pr->atom); /* WARNING: the shape may have been modified */ sh = p->shape; pr = get_shape_prop(sh) + i; } } } } } else { cur_len = len; } set_value(ctx, &p->prop[0].u.value, js_uint32(cur_len)); if (unlikely(cur_len > len)) { return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable"); } } return true; } /* return -1 if exception */ static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len) { uint32_t new_size; size_t slack; JSValue *new_array_prop; /* XXX: potential arithmetic overflow */ new_size = max_int(new_len, p->u.array.u1.size * 3 / 2); new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack); if (!new_array_prop) return -1; new_size += slack / sizeof(*new_array_prop); p->u.array.u.values = new_array_prop; p->u.array.u1.size = new_size; return 0; } /* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array = true and p->extensible = true */ static int add_fast_array_element(JSContext *ctx, JSObject *p, JSValue val, int flags) { uint32_t new_len, array_len; /* extend the array by one */ /* XXX: convert to slow array if new_len > 2^31-1 elements */ new_len = p->u.array.count + 1; /* update the length if necessary. We assume that if the length is not an integer, then if it >= 2^31. */ if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) { array_len = JS_VALUE_GET_INT(p->prop[0].u.value); if (new_len > array_len) { if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) { JS_FreeValue(ctx, val); return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); } p->prop[0].u.value = js_int32(new_len); } } if (unlikely(new_len > p->u.array.u1.size)) { if (expand_fast_array(ctx, p, new_len)) { JS_FreeValue(ctx, val); return -1; } } p->u.array.u.values[new_len - 1] = val; p->u.array.count = new_len; return true; } static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) { JS_FreeValue(ctx, desc->getter); JS_FreeValue(ctx, desc->setter); JS_FreeValue(ctx, desc->value); } /* return -1 in case of exception or true or false. Warning: 'val' is freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD, JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set, the new property is not added and an error is raised. 'obj' must be an object when obj != this_obj. */ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValue val, JSValueConst this_obj, int flags) { JSObject *p, *p1; JSShapeProperty *prs; JSProperty *pr; JSPropertyDescriptor desc; int ret; switch(JS_VALUE_GET_TAG(this_obj)) { case JS_TAG_NULL: JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); goto fail; case JS_TAG_UNDEFINED: JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop); goto fail; case JS_TAG_OBJECT: p = JS_VALUE_GET_OBJ(this_obj); p1 = JS_VALUE_GET_OBJ(obj); if (p == p1) break; goto retry2; default: if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) obj = JS_GetPrototypePrimitive(ctx, obj); p = NULL; p1 = JS_VALUE_GET_OBJ(obj); goto prototype_lookup; } retry: prs = find_own_property(&pr, p1, prop); if (prs) { if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { /* fast case */ set_value(ctx, &pr->u.value, val); return true; } else if (prs->flags & JS_PROP_LENGTH) { assert(p->class_id == JS_CLASS_ARRAY); assert(prop == JS_ATOM_length); return set_array_length(ctx, p, val, flags); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { /* JS_PROP_WRITABLE is always true for variable references, but they are write protected in module name spaces. */ if (p->class_id == JS_CLASS_MODULE_NS) goto read_only_prop; set_value(ctx, pr->u.var_ref->pvalue, val); return true; } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry (potentially useless) */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) goto fail; goto retry; } else { goto read_only_prop; } } for(;;) { if (p1->is_exotic) { if (p1->fast_array) { if (__JS_AtomIsTaggedInt(prop)) { uint32_t idx = __JS_AtomToUInt32(prop); if (idx < p1->u.array.count) { if (unlikely(p == p1)) return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, flags); else break; } else if (is_typed_array(p1->class_id)) { goto typed_array_oob; } } else if (is_typed_array(p1->class_id)) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) goto fail; typed_array_oob: // per spec: evaluate value for side effects if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { int64_t v; if (JS_ToBigInt64Free(ctx, &v, val)) return -1; } else { val = JS_ToNumberFree(ctx, val); JS_FreeValue(ctx, val); if (JS_IsException(val)) return -1; } return true; } } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic; if (em) { JSValue obj1; if (em->set_property) { /* set_property can free the prototype */ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->set_property(ctx, obj1, prop, val, this_obj, flags); JS_FreeValue(ctx, obj1); JS_FreeValue(ctx, val); return ret; } if (em->get_own_property) { /* get_own_property can free the prototype */ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); if (ret < 0) goto fail; if (ret) { if (desc.flags & JS_PROP_GETSET) { JSObject *setter; if (JS_IsUndefined(desc.setter)) setter = NULL; else setter = JS_VALUE_GET_OBJ(desc.setter); ret = call_setter(ctx, setter, this_obj, val, flags); JS_FreeValue(ctx, desc.getter); JS_FreeValue(ctx, desc.setter); return ret; } else { JS_FreeValue(ctx, desc.value); if (!(desc.flags & JS_PROP_WRITABLE)) goto read_only_prop; if (likely(p == p1)) { ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED, JS_PROP_HAS_VALUE); JS_FreeValue(ctx, val); return ret; } else { break; } } } } } } } p1 = p1->shape->proto; prototype_lookup: if (!p1) break; retry2: prs = find_own_property(&pr, p1, prop); if (prs) { if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry (potentially useless) */ if (JS_AutoInitProperty(ctx, p1, prop, pr, prs)) return -1; goto retry2; } else if (!(prs->flags & JS_PROP_WRITABLE)) { goto read_only_prop; } else { break; } } } if (unlikely(flags & JS_PROP_NO_ADD)) { JS_ThrowReferenceErrorNotDefined(ctx, prop); goto fail; } if (unlikely(!p)) { ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); goto done; } if (unlikely(!p->extensible)) { ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); goto done; } if (p == JS_VALUE_GET_OBJ(obj)) { if (p->is_exotic) { if (p->class_id == JS_CLASS_ARRAY && p->fast_array && __JS_AtomIsTaggedInt(prop)) { uint32_t idx = __JS_AtomToUInt32(prop); if (idx == p->u.array.count) { /* fast case */ return add_fast_array_element(ctx, p, val, flags); } } goto generic_create_prop; } else { pr = add_property(ctx, p, prop, JS_PROP_C_W_E); if (!pr) goto fail; pr->u.value = val; return true; } } // TODO(bnoordhuis) return JSProperty slot and update in place // when plain property (not is_exotic/setter/etc.) to avoid // calling find_own_property() thrice? ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (ret < 0) goto fail; if (ret) { JS_FreeValue(ctx, desc.value); if (desc.flags & JS_PROP_GETSET) { JS_FreeValue(ctx, desc.getter); JS_FreeValue(ctx, desc.setter); ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden"); goto done; } else if (!(desc.flags & JS_PROP_WRITABLE) || p->class_id == JS_CLASS_MODULE_NS) { read_only_prop: ret = JS_ThrowTypeErrorReadOnly(ctx, flags, prop); goto done; } ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED, JS_PROP_HAS_VALUE); } else { generic_create_prop: ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED, flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_ENUMERABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_C_W_E); } done: JS_FreeValue(ctx, val); return ret; fail: JS_FreeValue(ctx, val); return -1; } static int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValue val, int flags) { return JS_SetPropertyInternal2(ctx, obj, prop, val, obj, flags); } int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val) { return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW); } /* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val, int flags) { if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT && JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) { JSObject *p; uint32_t idx; double d; int32_t v; /* fast path for array access */ p = JS_VALUE_GET_OBJ(this_obj); idx = JS_VALUE_GET_INT(prop); switch(p->class_id) { case JS_CLASS_ARRAY: if (unlikely(idx >= (uint32_t)p->u.array.count)) { JSObject *p1; JSShape *sh1; /* fast path to add an element to the array */ if (idx != (uint32_t)p->u.array.count || !p->fast_array || !p->extensible) goto slow_path; /* check if prototype chain has a numeric property */ p1 = p->shape->proto; while (p1 != NULL) { sh1 = p1->shape; if (p1->class_id == JS_CLASS_ARRAY) { if (unlikely(!p1->fast_array)) goto slow_path; } else if (p1->class_id == JS_CLASS_OBJECT) { if (unlikely(sh1->has_small_array_index)) goto slow_path; } else { goto slow_path; } p1 = sh1->proto; } /* add element */ return add_fast_array_element(ctx, p, val, flags); } set_value(ctx, &p->u.array.u.values[idx], val); break; case JS_CLASS_ARGUMENTS: if (unlikely(idx >= (uint32_t)p->u.array.count)) goto slow_path; set_value(ctx, &p->u.array.u.values[idx], val); break; case JS_CLASS_UINT8C_ARRAY: if (JS_ToUint8ClampFree(ctx, &v, val)) goto ta_cvt_fail; /* Note: the conversion can detach the typed array, so the array bound check must be done after */ if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint8_ptr[idx] = v; break; case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint8_ptr[idx] = v; break; case JS_CLASS_INT16_ARRAY: case JS_CLASS_UINT16_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint16_ptr[idx] = v; break; case JS_CLASS_INT32_ARRAY: case JS_CLASS_UINT32_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint32_ptr[idx] = v; break; case JS_CLASS_BIG_INT64_ARRAY: case JS_CLASS_BIG_UINT64_ARRAY: /* XXX: need specific conversion function */ { int64_t v; if (JS_ToBigInt64Free(ctx, &v, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint64_ptr[idx] = v; } break; case JS_CLASS_FLOAT16_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.fp16_ptr[idx] = tofp16(d); break; case JS_CLASS_FLOAT32_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.float_ptr[idx] = d; break; case JS_CLASS_FLOAT64_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) { ta_cvt_fail: if (flags & JS_PROP_REFLECT_DEFINE_PROPERTY) { JS_FreeValue(ctx, JS_GetException(ctx)); return false; } return -1; } if (unlikely(idx >= (uint32_t)p->u.array.count)) { ta_out_of_bound: if (typed_array_is_oob(p)) if (flags & JS_PROP_DEFINE_PROPERTY) return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index"); return true; // per spec: no OOB exception } p->u.array.u.double_ptr[idx] = d; break; default: goto slow_path; } return true; } else { JSAtom atom; int ret; slow_path: atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) { JS_FreeValue(ctx, val); return -1; } ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags); JS_FreeAtom(ctx, atom); return ret; } } int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val) { return JS_SetPropertyValue(ctx, this_obj, js_uint32(idx), val, JS_PROP_THROW); } int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val) { JSAtom prop; int res; if ((uint64_t)idx <= INT32_MAX) { /* fast path for fast arrays */ return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, JS_PROP_THROW); } prop = JS_NewAtomInt64(ctx, idx); if (prop == JS_ATOM_NULL) { JS_FreeValue(ctx, val); return -1; } res = JS_SetProperty(ctx, this_obj, prop, val); JS_FreeAtom(ctx, prop); return res; } /* `prop` may be pure ASCII or UTF-8 encoded */ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val) { JSAtom atom; int ret; atom = JS_NewAtom(ctx, prop); if (atom == JS_ATOM_NULL) { JS_FreeValue(ctx, val); return -1; } ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW); JS_FreeAtom(ctx, atom); return ret; } /* compute the property flags. For each flag: (JS_PROP_HAS_x forces it, otherwise def_flags is used) Note: makes assumption about the bit pattern of the flags */ static int get_prop_flags(int flags, int def_flags) { int mask; mask = (flags >> JS_PROP_HAS_SHIFT) & JS_PROP_C_W_E; return (flags & mask) | (def_flags & ~mask); } static int JS_CreateProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags) { JSProperty *pr; int ret, prop_flags; /* add a new property or modify an existing exotic one */ if (p->is_exotic) { if (p->class_id == JS_CLASS_ARRAY) { uint32_t idx, len; if (p->fast_array) { if (__JS_AtomIsTaggedInt(prop)) { idx = __JS_AtomToUInt32(prop); if (idx == p->u.array.count) { if (!p->extensible) goto not_extensible; if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) goto convert_to_array; prop_flags = get_prop_flags(flags, 0); if (prop_flags != JS_PROP_C_W_E) goto convert_to_array; return add_fast_array_element(ctx, p, js_dup(val), flags); } else { goto convert_to_array; } } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) { /* convert the fast array to normal array */ convert_to_array: if (convert_fast_array_to_array(ctx, p)) return -1; goto generic_array; } } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) { JSProperty *plen; JSShapeProperty *pslen; generic_array: /* update the length field */ plen = &p->prop[0]; JS_ToUint32(ctx, &len, plen->u.value); if ((idx + 1) > len) { pslen = get_shape_prop(p->shape); if (unlikely(!(pslen->flags & JS_PROP_WRITABLE))) return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); /* XXX: should update the length after defining the property */ len = idx + 1; set_value(ctx, &plen->u.value, js_uint32(len)); } } } else if (is_typed_array(p->class_id)) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) return -1; return JS_ThrowTypeErrorOrFalse(ctx, flags, "cannot create numeric index in typed array"); } } else if (!(flags & JS_PROP_NO_EXOTIC)) { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { if (em->define_own_property) { return em->define_own_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop, val, getter, setter, flags); } ret = JS_IsExtensible(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); if (ret < 0) return -1; if (!ret) goto not_extensible; } } } if (!p->extensible) { not_extensible: return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); } if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { prop_flags = (flags & (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) | JS_PROP_GETSET; } else { prop_flags = flags & JS_PROP_C_W_E; } pr = add_property(ctx, p, prop, prop_flags); if (unlikely(!pr)) return -1; if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { pr->u.getset.getter = NULL; if ((flags & JS_PROP_HAS_GET) && JS_IsFunction(ctx, getter)) { pr->u.getset.getter = JS_VALUE_GET_OBJ(js_dup(getter)); } pr->u.getset.setter = NULL; if ((flags & JS_PROP_HAS_SET) && JS_IsFunction(ctx, setter)) { pr->u.getset.setter = JS_VALUE_GET_OBJ(js_dup(setter)); } } else { if (flags & JS_PROP_HAS_VALUE) { pr->u.value = js_dup(val); } else { pr->u.value = JS_UNDEFINED; } } return true; } /* return false if not OK */ static bool check_define_prop_flags(int prop_flags, int flags) { bool has_accessor, is_getset; if (!(prop_flags & JS_PROP_CONFIGURABLE)) { if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) == (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) { return false; } if ((flags & JS_PROP_HAS_ENUMERABLE) && (flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE)) return false; } if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { if (!(prop_flags & JS_PROP_CONFIGURABLE)) { has_accessor = ((flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) != 0); is_getset = ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET); if (has_accessor != is_getset) return false; if (!has_accessor && !is_getset && !(prop_flags & JS_PROP_WRITABLE)) { /* not writable: cannot set the writable bit */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) return false; } } } return true; } /* ensure that the shape can be safely modified */ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, JSShapeProperty **pprs) { JSShape *sh; uint32_t idx = 0; /* prevent warning */ sh = p->shape; if (sh->is_hashed) { if (sh->header.ref_count != 1) { if (pprs) idx = *pprs - get_shape_prop(sh); /* clone the shape (the resulting one is no longer hashed) */ sh = js_clone_shape(ctx, sh); if (!sh) return -1; js_free_shape(ctx->rt, p->shape); p->shape = sh; if (pprs) *pprs = get_shape_prop(sh) + idx; } else { js_shape_hash_unlink(ctx->rt, sh); sh->is_hashed = false; } } return 0; } static int js_update_property_flags(JSContext *ctx, JSObject *p, JSShapeProperty **pprs, int flags) { if (flags != (*pprs)->flags) { if (js_shape_prepare_update(ctx, p, pprs)) return -1; (*pprs)->flags = flags; } return 0; } /* allowed flags: JS_PROP_CONFIGURABLE, JS_PROP_WRITABLE, JS_PROP_ENUMERABLE JS_PROP_HAS_GET, JS_PROP_HAS_SET, JS_PROP_HAS_VALUE, JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE, JS_PROP_THROW, JS_PROP_NO_EXOTIC. If JS_PROP_THROW is set, return an exception instead of false. if JS_PROP_NO_EXOTIC is set, do not call the exotic define_own_property callback. return -1 (exception), false or true. */ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; int mask, res; if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; } p = JS_VALUE_GET_OBJ(this_obj); redo_prop_update: prs = find_own_property(&pr, p, prop); if (prs) { /* the range of the Array length property is always tested before */ if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) { uint32_t array_length; if (JS_ToArrayLengthFree(ctx, &array_length, js_dup(val), false)) { return -1; } /* this code relies on the fact that Uint32 are never allocated */ val = js_uint32(array_length); /* prs may have been modified */ prs = find_own_property(&pr, p, prop); assert(prs != NULL); } /* property already exists */ if (!check_define_prop_flags(prs->flags, flags)) { not_configurable: return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable"); } if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) return -1; goto redo_prop_update; } if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { JSObject *new_getter, *new_setter; if (JS_IsFunction(ctx, getter)) { new_getter = JS_VALUE_GET_OBJ(getter); } else { new_getter = NULL; } if (JS_IsFunction(ctx, setter)) { new_setter = JS_VALUE_GET_OBJ(setter); } else { new_setter = NULL; } if ((prs->flags & JS_PROP_TMASK) != JS_PROP_GETSET) { if (js_shape_prepare_update(ctx, p, &prs)) return -1; /* convert to getset */ if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { free_var_ref(ctx->rt, pr->u.var_ref); } else { JS_FreeValue(ctx, pr->u.value); } prs->flags = (prs->flags & (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) | JS_PROP_GETSET; pr->u.getset.getter = NULL; pr->u.getset.setter = NULL; } else { if (!(prs->flags & JS_PROP_CONFIGURABLE)) { if ((flags & JS_PROP_HAS_GET) && new_getter != pr->u.getset.getter) { goto not_configurable; } if ((flags & JS_PROP_HAS_SET) && new_setter != pr->u.getset.setter) { goto not_configurable; } } } if (flags & JS_PROP_HAS_GET) { if (pr->u.getset.getter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (new_getter) js_dup(getter); pr->u.getset.getter = new_getter; } if (flags & JS_PROP_HAS_SET) { if (pr->u.getset.setter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); if (new_setter) js_dup(setter); pr->u.getset.setter = new_setter; } } else { if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { /* convert to data descriptor */ if (js_shape_prepare_update(ctx, p, &prs)) return -1; if (pr->u.getset.getter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (pr->u.getset.setter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE); pr->u.value = JS_UNDEFINED; } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { /* Note: JS_PROP_VARREF is always writable */ } else { if ((prs->flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 && (flags & JS_PROP_HAS_VALUE)) { if (!js_same_value(ctx, val, pr->u.value)) { goto not_configurable; } else { return true; } } } if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { if (flags & JS_PROP_HAS_VALUE) { if (p->class_id == JS_CLASS_MODULE_NS) { /* JS_PROP_WRITABLE is always true for variable references, but they are write protected in module name spaces. */ if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue)) goto not_configurable; } /* update the reference */ set_value(ctx, pr->u.var_ref->pvalue, js_dup(val)); } /* if writable is set to false, no longer a reference (for mapped arguments) */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { JSValue val1; if (js_shape_prepare_update(ctx, p, &prs)) return -1; val1 = js_dup(*pr->u.var_ref->pvalue); free_var_ref(ctx->rt, pr->u.var_ref); pr->u.value = val1; prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE); } } else if (prs->flags & JS_PROP_LENGTH) { if (flags & JS_PROP_HAS_VALUE) { /* Note: no JS code is executable because 'val' is guaranted to be a Uint32 */ res = set_array_length(ctx, p, js_dup(val), flags); } else { res = true; } /* still need to reset the writable flag if needed. The JS_PROP_LENGTH is kept because the Uint32 test is still done if the length property is read-only. */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { prs = get_shape_prop(p->shape); if (js_update_property_flags(ctx, p, &prs, prs->flags & ~JS_PROP_WRITABLE)) return -1; } return res; } else { if (flags & JS_PROP_HAS_VALUE) { JS_FreeValue(ctx, pr->u.value); pr->u.value = js_dup(val); } if (flags & JS_PROP_HAS_WRITABLE) { if (js_update_property_flags(ctx, p, &prs, (prs->flags & ~JS_PROP_WRITABLE) | (flags & JS_PROP_WRITABLE))) return -1; } } } } mask = 0; if (flags & JS_PROP_HAS_CONFIGURABLE) mask |= JS_PROP_CONFIGURABLE; if (flags & JS_PROP_HAS_ENUMERABLE) mask |= JS_PROP_ENUMERABLE; if (js_update_property_flags(ctx, p, &prs, (prs->flags & ~mask) | (flags & mask))) return -1; return true; } /* handle modification of fast array elements */ if (p->fast_array) { uint32_t idx; uint32_t prop_flags; if (p->class_id == JS_CLASS_ARRAY) { if (__JS_AtomIsTaggedInt(prop)) { idx = __JS_AtomToUInt32(prop); if (idx < p->u.array.count) { prop_flags = get_prop_flags(flags, JS_PROP_C_W_E); if (prop_flags != JS_PROP_C_W_E) goto convert_to_slow_array; if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { convert_to_slow_array: if (convert_fast_array_to_array(ctx, p)) return -1; else goto redo_prop_update; } if (flags & JS_PROP_HAS_VALUE) { set_value(ctx, &p->u.array.u.values[idx], js_dup(val)); } return true; } } } else if (is_typed_array(p->class_id)) { JSValue num; int ret; if (!__JS_AtomIsTaggedInt(prop)) { /* slow path with to handle all numeric indexes */ num = JS_AtomIsNumericIndex1(ctx, prop); if (JS_IsUndefined(num)) goto typed_array_done; if (JS_IsException(num)) return -1; ret = JS_NumberIsInteger(ctx, num); if (ret < 0) { JS_FreeValue(ctx, num); return -1; } if (!ret) { JS_FreeValue(ctx, num); return JS_ThrowTypeErrorOrFalse(ctx, flags, "non integer index in typed array"); } ret = JS_NumberIsNegativeOrMinusZero(ctx, num); JS_FreeValue(ctx, num); if (ret) { return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array"); } if (!__JS_AtomIsTaggedInt(prop)) goto typed_array_oob; } idx = __JS_AtomToUInt32(prop); /* if the typed array is detached, p->u.array.count = 0 */ if (idx >= p->u.array.count) { typed_array_oob: return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array"); } prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET) || prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) { return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags"); } if (flags & JS_PROP_HAS_VALUE) { return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), js_dup(val), flags); } return true; typed_array_done: ; } } return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags); } static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSAutoInitIDEnum id, void *opaque, int flags) { JSObject *p; JSProperty *pr; if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(this_obj); if (find_own_property(&pr, p, prop)) { /* property already exists */ abort(); return false; } /* Specialized CreateProperty */ pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT); if (unlikely(!pr)) return -1; pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx); assert((pr->u.init.realm_and_id & 3) == 0); assert(id <= 3); pr->u.init.realm_and_id |= id; pr->u.init.opaque = opaque; return true; } /* shortcut to add or redefine a new property value */ int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val, int flags) { int ret; ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED, flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE); JS_FreeValue(ctx, val); return ret; } int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val, int flags) { JSAtom atom; int ret; atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) { JS_FreeValue(ctx, val); return -1; } ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags); JS_FreeAtom(ctx, atom); return ret; } int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val, int flags) { return JS_DefinePropertyValueValue(ctx, this_obj, js_uint32(idx), val, flags); } int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val, int flags) { return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx), val, flags); } /* `prop` may be pure ASCII or UTF-8 encoded */ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val, int flags) { JSAtom atom; int ret; atom = JS_NewAtom(ctx, prop); if (atom == JS_ATOM_NULL) { JS_FreeValue(ctx, val); return -1; } ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags); JS_FreeAtom(ctx, atom); return ret; } /* shortcut to add getter & setter */ int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue getter, JSValue setter, int flags) { int ret; ret = JS_DefineProperty(ctx, this_obj, prop, JS_UNDEFINED, getter, setter, flags | JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE); JS_FreeValue(ctx, getter); JS_FreeValue(ctx, setter); return ret; } static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val, int flags) { return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx), val, flags | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); } /* return true if 'obj' has a non empty 'name' string */ static bool js_object_has_name(JSContext *ctx, JSValue obj) { JSProperty *pr; JSShapeProperty *prs; JSValue val; JSString *p; prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name); if (!prs) return false; if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) return true; val = pr->u.value; if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) return true; p = JS_VALUE_GET_STRING(val); return (p->len != 0); } static int JS_DefineObjectName(JSContext *ctx, JSValue obj, JSAtom name, int flags) { if (name != JS_ATOM_NULL && JS_IsObject(obj) && !js_object_has_name(ctx, obj) && JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name), flags) < 0) { return -1; } return 0; } static int JS_DefineObjectNameComputed(JSContext *ctx, JSValue obj, JSValue str, int flags) { if (JS_IsObject(obj) && !js_object_has_name(ctx, obj)) { JSAtom prop; JSValue name_str; prop = JS_ValueToAtom(ctx, str); if (prop == JS_ATOM_NULL) return -1; name_str = js_get_function_name(ctx, prop); JS_FreeAtom(ctx, prop); if (JS_IsException(name_str)) return -1; if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, name_str, flags) < 0) return -1; } return 0; } #define DEFINE_GLOBAL_LEX_VAR (1 << 7) #define DEFINE_GLOBAL_FUNC_VAR (1 << 6) static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop) { return JS_ThrowSyntaxErrorAtom(ctx, "redeclaration of '%s'", prop); } /* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */ /* XXX: could support exotic global object. */ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) { JSObject *p; JSShapeProperty *prs; p = JS_VALUE_GET_OBJ(ctx->global_obj); prs = find_own_property1(p, prop); /* XXX: should handle JS_PROP_AUTOINIT */ if (flags & DEFINE_GLOBAL_LEX_VAR) { if (prs && !(prs->flags & JS_PROP_CONFIGURABLE)) goto fail_redeclaration; } else { if (!prs && !p->extensible) goto define_error; if (flags & DEFINE_GLOBAL_FUNC_VAR) { if (prs) { if (!(prs->flags & JS_PROP_CONFIGURABLE) && ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET || ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) != (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) { define_error: JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'", prop); return -1; } } } } /* check if there already is a lexical declaration */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property1(p, prop); if (prs) { fail_redeclaration: JS_ThrowSyntaxErrorVarRedeclaration(ctx, prop); return -1; } return 0; } /* def_flags is (0, DEFINE_GLOBAL_LEX_VAR) | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE */ /* XXX: could support exotic global object. */ static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; JSValue val; int flags; if (def_flags & DEFINE_GLOBAL_LEX_VAR) { p = JS_VALUE_GET_OBJ(ctx->global_var_obj); flags = JS_PROP_ENUMERABLE | (def_flags & JS_PROP_WRITABLE) | JS_PROP_CONFIGURABLE; val = JS_UNINITIALIZED; } else { p = JS_VALUE_GET_OBJ(ctx->global_obj); flags = JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | (def_flags & JS_PROP_CONFIGURABLE); val = JS_UNDEFINED; } prs = find_own_property1(p, prop); if (prs) return 0; if (!p->extensible) return 0; pr = add_property(ctx, p, prop, flags); if (unlikely(!pr)) return -1; pr->u.value = val; return 0; } /* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */ /* XXX: could support exotic global object. */ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop, JSValue func, int def_flags) { JSObject *p; JSShapeProperty *prs; int flags; p = JS_VALUE_GET_OBJ(ctx->global_obj); prs = find_own_property1(p, prop); flags = JS_PROP_HAS_VALUE | JS_PROP_THROW; if (!prs || (prs->flags & JS_PROP_CONFIGURABLE)) { flags |= JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | def_flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE; } if (JS_DefineProperty(ctx, ctx->global_obj, prop, func, JS_UNDEFINED, JS_UNDEFINED, flags) < 0) return -1; return 0; } static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop, bool throw_ref_error) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) { /* XXX: should handle JS_PROP_TMASK properties */ if (unlikely(JS_IsUninitialized(pr->u.value))) return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return js_dup(pr->u.value); } if (ctx->scopeLookup) { struct LookupResult result = ctx->scopeLookup(ctx, prop); if (result.useResult) return result.value; } return JS_GetPropertyInternal(ctx, ctx->global_obj, prop, ctx->global_obj, throw_ref_error); } /* construct a reference to a global variable */ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) { /* XXX: should handle JS_PROP_AUTOINIT properties? */ /* XXX: conformance: do these tests in OP_put_var_ref/OP_get_var_ref ? */ if (unlikely(JS_IsUninitialized(pr->u.value))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) { return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop); } sp[0] = js_dup(ctx->global_var_obj); } else { int ret; ret = JS_HasProperty(ctx, ctx->global_obj, prop); if (ret < 0) return -1; if (ret) { sp[0] = js_dup(ctx->global_obj); } else { sp[0] = JS_UNDEFINED; } } sp[1] = JS_AtomToValue(ctx, prop); return 0; } /* use for strict variable access: test if the variable exists */ static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop) { JSObject *p; JSShapeProperty *prs; int ret; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property1(p, prop); if (prs) { ret = true; } else { ret = JS_HasProperty(ctx, ctx->global_obj, prop); if (ret < 0) return -1; } return ret; } /* flag = 0: normal variable write flag = 1: initialize lexical variable flag = 2: normal variable write, strict check was done before */ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, int flag) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; int flags; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) { /* XXX: should handle JS_PROP_AUTOINIT properties? */ if (flag != 1) { if (unlikely(JS_IsUninitialized(pr->u.value))) { JS_FreeValue(ctx, val); JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) { JS_FreeValue(ctx, val); return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop); } } set_value(ctx, &pr->u.value, val); return 0; } flags = JS_PROP_THROW_STRICT; if (is_strict_mode(ctx)) flags |= JS_PROP_NO_ADD; if (ctx->scopeLookup) { struct LookupResult result = ctx->scopeLookup(ctx, prop); if (result.useResult) { JS_FreeValue(ctx, result.value); return JS_SetPropertyInternal2(ctx, ctx->global_obj, prop, val, result.scope, flags); } } return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags); } /* return -1, false or true */ static int JS_DeleteGlobalVar(JSContext *ctx, JSAtom prop) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; int ret; /* 9.1.1.4.7 DeleteBinding ( N ) */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) return false; /* lexical variables cannot be deleted */ ret = JS_HasProperty(ctx, ctx->global_obj, prop); if (ret < 0) return -1; if (ret) { return JS_DeleteProperty(ctx, ctx->global_obj, prop, 0); } else { return true; } } /* return -1, false or true. return false if not configurable or invalid object. return -1 in case of exception. flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) { JSValue obj1; JSObject *p; int res; obj1 = JS_ToObject(ctx, obj); if (JS_IsException(obj1)) return -1; p = JS_VALUE_GET_OBJ(obj1); res = delete_property(ctx, p, prop); JS_FreeValue(ctx, obj1); if (res != false) return res; if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { JS_ThrowTypeError(ctx, "could not delete property"); return -1; } return false; } int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags) { JSAtom prop; int res; if ((uint64_t)idx <= JS_ATOM_MAX_INT) { /* fast path for fast arrays */ return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags); } prop = JS_NewAtomInt64(ctx, idx); if (prop == JS_ATOM_NULL) return -1; res = JS_DeleteProperty(ctx, obj, prop, flags); JS_FreeAtom(ctx, prop); return res; } bool JS_IsFunction(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(val); switch(p->class_id) { case JS_CLASS_BYTECODE_FUNCTION: return true; case JS_CLASS_PROXY: return p->u.proxy_data->is_func; default: return (ctx->rt->class_array[p->class_id].call != NULL); } } static bool JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(val); if (p->class_id == JS_CLASS_C_FUNCTION) return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic); else return false; } bool JS_IsConstructor(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(val); return p->is_constructor; } bool JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, bool val) { JSObject *p; if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(func_obj); p->is_constructor = val; return true; } bool JS_IsRegExp(JSValueConst val) { return JS_CLASS_REGEXP == JS_GetClassID(val); } bool JS_IsMap(JSValueConst val) { return JS_CLASS_MAP == JS_GetClassID(val); } bool JS_IsSet(JSValueConst val) { return JS_CLASS_SET == JS_GetClassID(val); } bool JS_IsWeakRef(JSValueConst val) { return JS_CLASS_WEAK_REF == JS_GetClassID(val); } bool JS_IsWeakSet(JSValueConst val) { return JS_CLASS_WEAKSET == JS_GetClassID(val); } bool JS_IsWeakMap(JSValueConst val) { return JS_CLASS_WEAKMAP == JS_GetClassID(val); } bool JS_IsDataView(JSValueConst val) { return JS_CLASS_DATAVIEW == JS_GetClassID(val); } int JS_IsSimpleValue(JSContext* ctx, JSValueConst v) { JSObject *p; if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) return 1; p = JS_VALUE_GET_OBJ(v); return p->class_id >= JS_CLASS_OBJECT && p->class_id <= JS_CLASS_BOOLEAN; } bool JS_IsError(JSValueConst val) { return JS_CLASS_ERROR == JS_GetClassID(val); } /* used to avoid catching interrupt exceptions */ bool JS_IsUncatchableError(JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(val); return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error; } static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, bool flag) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return; p = JS_VALUE_GET_OBJ(val); if (p->class_id == JS_CLASS_ERROR) p->is_uncatchable_error = flag; } void JS_SetUncatchableError(JSContext *ctx, JSValueConst val) { js_set_uncatchable_error(ctx, val, true); } void JS_ClearUncatchableError(JSContext *ctx, JSValueConst val) { js_set_uncatchable_error(ctx, val, false); } void JS_ResetUncatchableError(JSContext *ctx) { js_set_uncatchable_error(ctx, ctx->rt->current_exception, false); } int JS_SetOpaque(JSValueConst obj, void *opaque) { JSObject *p; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(obj); // User code can't set the opaque of internal objects. if (p->class_id >= JS_CLASS_INIT_COUNT) { p->u.opaque = opaque; return 0; } } return -1; } /* |obj| must be a JSObject of an internal class. */ static void JS_SetOpaqueInternal(JSValueConst obj, void *opaque) { JSObject *p; assert(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT); p = JS_VALUE_GET_OBJ(obj); assert(p->class_id < JS_CLASS_INIT_COUNT); p->u.opaque = opaque; } /* return NULL if not an object of class class_id */ void *JS_GetOpaque(JSValueConst obj, JSClassID class_id) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return NULL; p = JS_VALUE_GET_OBJ(obj); if (p->class_id != class_id) return NULL; return p->u.opaque; } void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id) { void *p = JS_GetOpaque(obj, class_id); if (unlikely(!p)) { JS_ThrowTypeErrorInvalidClass(ctx, class_id); } return p; } void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { *class_id = 0; return NULL; } p = JS_VALUE_GET_OBJ(obj); *class_id = p->class_id; return p->u.opaque; } static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) { int i; bool force_ordinary; JSAtom method_name; JSValue method, ret; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) return val; force_ordinary = hint & HINT_FORCE_ORDINARY; hint &= ~HINT_FORCE_ORDINARY; if (!force_ordinary) { method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_toPrimitive); if (JS_IsException(method)) goto exception; /* ECMA says *If exoticToPrim is not undefined* but tests in test262 use null as a non callable converter */ if (!JS_IsUndefined(method) && !JS_IsNull(method)) { JSAtom atom; JSValue arg; switch(hint) { case HINT_STRING: atom = JS_ATOM_string; break; case HINT_NUMBER: atom = JS_ATOM_number; break; default: case HINT_NONE: atom = JS_ATOM_default; break; } arg = JS_AtomToString(ctx, atom); ret = JS_CallFree(ctx, method, val, 1, vc(&arg)); JS_FreeValue(ctx, arg); if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, val); if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) return ret; JS_FreeValue(ctx, ret); return JS_ThrowTypeError(ctx, "toPrimitive"); } } if (hint != HINT_STRING) hint = HINT_NUMBER; for(i = 0; i < 2; i++) { if ((i ^ hint) == 0) { method_name = JS_ATOM_toString; } else { method_name = JS_ATOM_valueOf; } method = JS_GetProperty(ctx, val, method_name); if (JS_IsException(method)) goto exception; if (JS_IsFunction(ctx, method)) { ret = JS_CallFree(ctx, method, val, 0, NULL); if (JS_IsException(ret)) goto exception; if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) { JS_FreeValue(ctx, val); return ret; } JS_FreeValue(ctx, ret); } else { JS_FreeValue(ctx, method); } } JS_ThrowTypeError(ctx, "toPrimitive"); exception: JS_FreeValue(ctx, val); return JS_EXCEPTION; } static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint) { return JS_ToPrimitiveFree(ctx, js_dup(val), hint); } void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return; p = JS_VALUE_GET_OBJ(obj); p->is_HTMLDDA = true; } static inline bool JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(obj); return p->is_HTMLDDA; } static int JS_ToBoolFree(JSContext *ctx, JSValue val) { uint32_t tag = JS_VALUE_GET_TAG(val); switch(tag) { case JS_TAG_INT: return JS_VALUE_GET_INT(val) != 0; case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: return JS_VALUE_GET_INT(val); case JS_TAG_EXCEPTION: return -1; case JS_TAG_STRING: { bool ret = JS_VALUE_GET_STRING(val)->len != 0; JS_FreeValue(ctx, val); return ret; } case JS_TAG_SHORT_BIG_INT: return JS_VALUE_GET_SHORT_BIG_INT(val) != 0; case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(val); bool ret; int i; /* fail safe: we assume it is not necessarily normalized. Beginning from the MSB ensures that the test is fast. */ ret = false; for(i = p->len - 1; i >= 0; i--) { if (p->tab[i] != 0) { ret = true; break; } } JS_FreeValue(ctx, val); return ret; } case JS_TAG_OBJECT: { JSObject *p = JS_VALUE_GET_OBJ(val); bool ret = !p->is_HTMLDDA; JS_FreeValue(ctx, val); return ret; } break; default: if (JS_TAG_IS_FLOAT64(tag)) { double d = JS_VALUE_GET_FLOAT64(val); return !isnan(d) && d != 0; } else { JS_FreeValue(ctx, val); return true; } } } int JS_ToBool(JSContext *ctx, JSValueConst val) { return JS_ToBoolFree(ctx, js_dup(val)); } /* pc points to pure ASCII or UTF-8, null terminated contents */ static int skip_spaces(const char *pc) { const uint8_t *p, *p_next, *p_start; uint32_t c; p = p_start = (const uint8_t *)pc; for (;;) { c = *p++; if (c < 0x80) { if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20))) break; } else { c = utf8_decode(p - 1, &p_next); /* no need to test for invalid UTF-8, 0xFFFD is not a space */ if (!lre_is_space(c)) break; p = p_next; } } return p - 1 - p_start; } static inline int js_to_digit(int c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'Z') return c - 'A' + 10; else if (c >= 'a' && c <= 'z') return c - 'a' + 10; else return 36; } /* bigint support */ #define ADDC(res, carry_out, op1, op2, carry_in) \ do { \ js_limb_t __v, __a, __k, __k1; \ __v = (op1); \ __a = __v + (op2); \ __k1 = __a < __v; \ __k = (carry_in); \ __a = __a + __k; \ carry_out = (__a < __k) | __k1; \ res = __a; \ } while (0) /* a != 0 */ static inline js_limb_t js_limb_clz(js_limb_t a) { if (!a) return JS_LIMB_BITS; return clz32(a); } static js_limb_t js_mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, js_limb_t n, js_limb_t carry) { int i; for(i = 0;i < n; i++) { ADDC(res[i], carry, op1[i], op2[i], carry); } return carry; } static js_limb_t js_mp_sub(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, int n, js_limb_t carry) { int i; js_limb_t k, a, v, k1; k = carry; for(i=0;i v; v = a - k; k = (v > a) | k1; res[i] = v; } return k; } /* compute 0 - op2. carry = 0 or 1. */ static js_limb_t js_mp_neg(js_limb_t *res, const js_limb_t *op2, int n) { int i; js_limb_t v, carry; carry = 1; for(i=0;i> JS_LIMB_BITS; } return l; } static js_limb_t js_mp_div1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b, js_limb_t r) { js_slimb_t i; js_dlimb_t a1; for(i = n - 1; i >= 0; i--) { a1 = ((js_dlimb_t)r << JS_LIMB_BITS) | taba[i]; tabr[i] = a1 / b; r = a1 % b; } return r; } /* tabr[] += taba[] * b, return the high word. */ static js_limb_t js_mp_add_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b) { js_limb_t i, l; js_dlimb_t t; l = 0; for(i = 0; i < n; i++) { t = (js_dlimb_t)taba[i] * (js_dlimb_t)b + l + tabr[i]; tabr[i] = t; l = t >> JS_LIMB_BITS; } return l; } /* size of the result : op1_size + op2_size. */ static void js_mp_mul_basecase(js_limb_t *result, const js_limb_t *op1, js_limb_t op1_size, const js_limb_t *op2, js_limb_t op2_size) { int i; js_limb_t r; result[op1_size] = js_mp_mul1(result, op1, op1_size, op2[0], 0); for(i=1;i> JS_LIMB_BITS); } return l; } /* WARNING: d must be >= 2^(JS_LIMB_BITS-1) */ static inline js_limb_t js_udiv1norm_init(js_limb_t d) { js_limb_t a0, a1; a1 = -d - 1; a0 = -1; return (((js_dlimb_t)a1 << JS_LIMB_BITS) | a0) / d; } /* return the quotient and the remainder in '*pr'of 'a1*2^JS_LIMB_BITS+a0 / d' with 0 <= a1 < d. */ static inline js_limb_t js_udiv1norm(js_limb_t *pr, js_limb_t a1, js_limb_t a0, js_limb_t d, js_limb_t d_inv) { js_limb_t n1m, n_adj, q, r, ah; js_dlimb_t a; n1m = ((js_slimb_t)a0 >> (JS_LIMB_BITS - 1)); n_adj = a0 + (n1m & d); a = (js_dlimb_t)d_inv * (a1 - n1m) + n_adj; q = (a >> JS_LIMB_BITS) + a1; /* compute a - q * r and update q so that the remainder is\ between 0 and d - 1 */ a = ((js_dlimb_t)a1 << JS_LIMB_BITS) | a0; a = a - (js_dlimb_t)q * d - d; ah = a >> JS_LIMB_BITS; q += 1 + ah; r = (js_limb_t)a + (ah & d); *pr = r; return q; } #define UDIV1NORM_THRESHOLD 3 /* b must be >= 1 << (JS_LIMB_BITS - 1) */ static js_limb_t js_mp_div1norm(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b, js_limb_t r) { js_slimb_t i; if (n >= UDIV1NORM_THRESHOLD) { js_limb_t b_inv; b_inv = js_udiv1norm_init(b); for(i = n - 1; i >= 0; i--) { tabr[i] = js_udiv1norm(&r, r, taba[i], b, b_inv); } } else { js_dlimb_t a1; for(i = n - 1; i >= 0; i--) { a1 = ((js_dlimb_t)r << JS_LIMB_BITS) | taba[i]; tabr[i] = a1 / b; r = a1 % b; } } return r; } /* base case division: divides taba[0..na-1] by tabb[0..nb-1]. tabb[nb - 1] must be >= 1 << (JS_LIMB_BITS - 1). na - nb must be >= 0. 'taba' is modified and contains the remainder (nb limbs). tabq[0..na-nb] contains the quotient with tabq[na - nb] <= 1. */ static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, const js_limb_t *tabb, js_limb_t nb) { js_limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r; int i, j; b1 = tabb[nb - 1]; if (nb == 1) { taba[0] = js_mp_div1norm(tabq, taba, na, b1, 0); return; } n = na - nb; if (n >= UDIV1NORM_THRESHOLD) b1_inv = js_udiv1norm_init(b1); else b1_inv = 0; /* first iteration: the quotient is only 0 or 1 */ q = 1; for(j = nb - 1; j >= 0; j--) { if (taba[n + j] != tabb[j]) { if (taba[n + j] < tabb[j]) q = 0; break; } } tabq[n] = q; if (q) { js_mp_sub(taba + n, taba + n, tabb, nb, 0); } for(i = n - 1; i >= 0; i--) { if (unlikely(taba[i + nb] >= b1)) { q = -1; } else if (b1_inv) { q = js_udiv1norm(&dummy_r, taba[i + nb], taba[i + nb - 1], b1, b1_inv); } else { js_dlimb_t al; al = ((js_dlimb_t)taba[i + nb] << JS_LIMB_BITS) | taba[i + nb - 1]; q = al / b1; r = al % b1; } r = js_mp_sub_mul1(taba + i, tabb, nb, q); v = taba[i + nb]; a = v - r; c = (a > v); taba[i + nb] = a; if (c != 0) { /* negative result */ for(;;) { q--; c = js_mp_add(taba + i, taba + i, tabb, nb, 0); /* propagate carry and test if positive result */ if (c != 0) { if (++taba[i + nb] == 0) { break; } } } } tabq[i] = q; } } /* 1 <= shift <= JS_LIMB_BITS - 1 */ static js_limb_t js_mp_shl(js_limb_t *tabr, const js_limb_t *taba, int n, int shift) { int i; js_limb_t l, v; l = 0; for(i = 0; i < n; i++) { v = taba[i]; tabr[i] = (v << shift) | l; l = v >> (JS_LIMB_BITS - shift); } return l; } /* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). 1 <= shift <= LIMB_BITS - 1 */ static js_limb_t js_mp_shr(js_limb_t *tab_r, const js_limb_t *tab, int n, int shift, js_limb_t high) { int i; js_limb_t l, a; l = high; for(i = n - 1; i >= 0; i--) { a = tab[i]; tab_r[i] = (a >> shift) | (l << (JS_LIMB_BITS - shift)); l = a; } return l & (((js_limb_t)1 << shift) - 1); } static JSBigInt *js_bigint_new(JSContext *ctx, int len) { JSBigInt *r; if (len > JS_BIGINT_MAX_SIZE) { JS_ThrowRangeError(ctx, "BigInt is too large to allocate"); return NULL; } r = js_malloc(ctx, sizeof(JSBigInt) + len * sizeof(js_limb_t)); if (!r) return NULL; r->header.ref_count = 1; r->len = len; return r; } static JSBigInt *js_bigint_set_si(JSBigIntBuf *buf, js_slimb_t a) { JSBigInt *r = (JSBigInt *)buf->big_int_buf; r->header.ref_count = 0; /* fail safe */ r->len = 1; r->tab[0] = a; return r; } static JSBigInt *js_bigint_set_si64(JSBigIntBuf *buf, int64_t a) { JSBigInt *r = (JSBigInt *)buf->big_int_buf; r->header.ref_count = 0; /* fail safe */ if (a >= INT32_MIN && a <= INT32_MAX) { r->len = 1; r->tab[0] = a; } else { r->len = 2; r->tab[0] = a; r->tab[1] = a >> JS_LIMB_BITS; } return r; } /* val must be a short big int */ static JSBigInt *js_bigint_set_short(JSBigIntBuf *buf, JSValueConst val) { return js_bigint_set_si(buf, JS_VALUE_GET_SHORT_BIG_INT(val)); } static __maybe_unused void js_bigint_dump1(JSContext *ctx, const char *str, const js_limb_t *tab, int len) { int i; printf("%s: ", str); for(i = len - 1; i >= 0; i--) { printf(" %08x", tab[i]); } printf("\n"); } static __maybe_unused void js_bigint_dump(JSContext *ctx, const char *str, const JSBigInt *p) { js_bigint_dump1(ctx, str, p->tab, p->len); } static JSBigInt *js_bigint_new_si(JSContext *ctx, js_slimb_t a) { JSBigInt *r; r = js_bigint_new(ctx, 1); if (!r) return NULL; r->tab[0] = a; return r; } static JSBigInt *js_bigint_new_si64(JSContext *ctx, int64_t a) { if (a >= INT32_MIN && a <= INT32_MAX) { return js_bigint_new_si(ctx, a); } else { JSBigInt *r; r = js_bigint_new(ctx, 2); if (!r) return NULL; r->tab[0] = a; r->tab[1] = a >> 32; return r; } } static JSBigInt *js_bigint_new_ui64(JSContext *ctx, uint64_t a) { if (a <= INT64_MAX) { return js_bigint_new_si64(ctx, a); } else { JSBigInt *r; r = js_bigint_new(ctx, (65 + JS_LIMB_BITS - 1) / JS_LIMB_BITS); if (!r) return NULL; r->tab[0] = a; r->tab[1] = a >> 32; r->tab[2] = 0; return r; } } static JSBigInt *js_bigint_new_di(JSContext *ctx, js_sdlimb_t a) { JSBigInt *r; if (a == (js_slimb_t)a) { r = js_bigint_new(ctx, 1); if (!r) return NULL; r->tab[0] = a; } else { r = js_bigint_new(ctx, 2); if (!r) return NULL; r->tab[0] = a; r->tab[1] = a >> JS_LIMB_BITS; } return r; } /* Remove redundant high order limbs. Warning: 'a' may be reallocated. Can never fail. */ static JSBigInt *js_bigint_normalize1(JSContext *ctx, JSBigInt *a, int l) { js_limb_t v; assert(a->header.ref_count == 1); while (l > 1) { v = a->tab[l - 1]; if ((v != 0 && v != -1) || (v & 1) != (a->tab[l - 2] >> (JS_LIMB_BITS - 1))) { break; } l--; } if (l != a->len) { JSBigInt *a1; /* realloc to reduce the size */ a->len = l; a1 = js_realloc(ctx, a, sizeof(JSBigInt) + l * sizeof(js_limb_t)); if (a1) a = a1; } return a; } static JSBigInt *js_bigint_normalize(JSContext *ctx, JSBigInt *a) { return js_bigint_normalize1(ctx, a, a->len); } /* return 0 or 1 depending on the sign */ static inline int js_bigint_sign(const JSBigInt *a) { return a->tab[a->len - 1] >> (JS_LIMB_BITS - 1); } static js_slimb_t js_bigint_get_si_sat(const JSBigInt *a) { if (a->len == 1) { return a->tab[0]; } else { if (js_bigint_sign(a)) return INT32_MIN; else return INT32_MAX; } } /* add the op1 limb */ static JSBigInt *js_bigint_extend(JSContext *ctx, JSBigInt *r, js_limb_t op1) { int n2 = r->len; if ((op1 != 0 && op1 != -1) || (op1 & 1) != r->tab[n2 - 1] >> (JS_LIMB_BITS - 1)) { JSBigInt *r1; r1 = js_realloc(ctx, r, sizeof(JSBigInt) + (n2 + 1) * sizeof(js_limb_t)); if (!r1) { js_free(ctx, r); return NULL; } r = r1; r->len = n2 + 1; r->tab[n2] = op1; } else { /* otherwise still need to normalize the result */ r = js_bigint_normalize(ctx, r); } return r; } /* return NULL in case of error. Compute a + b (b_neg = 0) or a - b (b_neg = 1) */ /* XXX: optimize */ static JSBigInt *js_bigint_add(JSContext *ctx, const JSBigInt *a, const JSBigInt *b, int b_neg) { JSBigInt *r; int n1, n2, i; js_limb_t carry, op1, op2, a_sign, b_sign; n2 = max_int(a->len, b->len); n1 = min_int(a->len, b->len); r = js_bigint_new(ctx, n2); if (!r) return NULL; /* XXX: optimize */ /* common part */ carry = b_neg; for(i = 0; i < n1; i++) { op1 = a->tab[i]; op2 = b->tab[i] ^ (-b_neg); ADDC(r->tab[i], carry, op1, op2, carry); } a_sign = -js_bigint_sign(a); b_sign = (-js_bigint_sign(b)) ^ (-b_neg); /* part with sign extension of one operand */ if (a->len > b->len) { for(i = n1; i < n2; i++) { op1 = a->tab[i]; ADDC(r->tab[i], carry, op1, b_sign, carry); } } else if (a->len < b->len) { for(i = n1; i < n2; i++) { op2 = b->tab[i] ^ (-b_neg); ADDC(r->tab[i], carry, a_sign, op2, carry); } } /* part with sign extension for both operands. Extend the result if necessary */ return js_bigint_extend(ctx, r, a_sign + b_sign + carry); } /* XXX: optimize */ static JSBigInt *js_bigint_neg(JSContext *ctx, const JSBigInt *a) { JSBigIntBuf buf; JSBigInt *b; b = js_bigint_set_si(&buf, 0); return js_bigint_add(ctx, b, a, 1); } static JSBigInt *js_bigint_mul(JSContext *ctx, const JSBigInt *a, const JSBigInt *b) { JSBigInt *r; r = js_bigint_new(ctx, a->len + b->len); if (!r) return NULL; js_mp_mul_basecase(r->tab, a->tab, a->len, b->tab, b->len); /* correct the result if negative operands (no overflow is possible) */ if (js_bigint_sign(a)) js_mp_sub(r->tab + a->len, r->tab + a->len, b->tab, b->len, 0); if (js_bigint_sign(b)) js_mp_sub(r->tab + b->len, r->tab + b->len, a->tab, a->len, 0); return js_bigint_normalize(ctx, r); } /* return the division or the remainder. 'b' must be != 0. return NULL in case of exception (division by zero or memory error) */ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, const JSBigInt *b, bool is_rem) { JSBigInt *r, *q; js_limb_t *tabb, h; int na, nb, a_sign, b_sign, shift; if (b->len == 1 && b->tab[0] == 0) { JS_ThrowRangeError(ctx, "BigInt division by zero"); return NULL; } a_sign = js_bigint_sign(a); b_sign = js_bigint_sign(b); na = a->len; nb = b->len; r = js_bigint_new(ctx, na + 2); if (!r) return NULL; if (a_sign) { js_mp_neg(r->tab, a->tab, na); } else { memcpy(r->tab, a->tab, na * sizeof(a->tab[0])); } /* normalize */ while (na > 1 && r->tab[na - 1] == 0) na--; tabb = js_malloc(ctx, nb * sizeof(tabb[0])); if (!tabb) { js_free(ctx, r); return NULL; } if (b_sign) { js_mp_neg(tabb, b->tab, nb); } else { memcpy(tabb, b->tab, nb * sizeof(tabb[0])); } /* normalize */ while (nb > 1 && tabb[nb - 1] == 0) nb--; /* trivial case if 'a' is small */ if (na < nb) { js_free(ctx, r); js_free(ctx, tabb); if (is_rem) { /* r = a */ r = js_bigint_new(ctx, a->len); if (!r) return NULL; memcpy(r->tab, a->tab, a->len * sizeof(a->tab[0])); return r; } else { /* q = 0 */ return js_bigint_new_si(ctx, 0); } } /* normalize 'b' */ shift = js_limb_clz(tabb[nb - 1]); if (shift != 0) { js_mp_shl(tabb, tabb, nb, shift); h = js_mp_shl(r->tab, r->tab, na, shift); if (h != 0) r->tab[na++] = h; } q = js_bigint_new(ctx, na - nb + 2); /* one more limb for the sign */ if (!q) { js_free(ctx, r); js_free(ctx, tabb); return NULL; } // js_bigint_dump1(ctx, "a", r->tab, na); // js_bigint_dump1(ctx, "b", tabb, nb); js_mp_divnorm(q->tab, r->tab, na, tabb, nb); js_free(ctx, tabb); if (is_rem) { js_free(ctx, q); if (shift != 0) js_mp_shr(r->tab, r->tab, nb, shift, 0); r->tab[nb++] = 0; if (a_sign) js_mp_neg(r->tab, r->tab, nb); r = js_bigint_normalize1(ctx, r, nb); return r; } else { js_free(ctx, r); q->tab[na - nb + 1] = 0; if (a_sign ^ b_sign) { js_mp_neg(q->tab, q->tab, q->len); } q = js_bigint_normalize(ctx, q); return q; } } /* and, or, xor */ static JSBigInt *js_bigint_logic(JSContext *ctx, const JSBigInt *a, const JSBigInt *b, OPCodeEnum op) { JSBigInt *r; js_limb_t b_sign; int a_len, b_len, i; if (a->len < b->len) { const JSBigInt *tmp; tmp = a; a = b; b = tmp; } /* a_len >= b_len */ a_len = a->len; b_len = b->len; b_sign = -js_bigint_sign(b); r = js_bigint_new(ctx, a_len); if (!r) return NULL; switch(op) { case OP_or: for(i = 0; i < b_len; i++) { r->tab[i] = a->tab[i] | b->tab[i]; } for(i = b_len; i < a_len; i++) { r->tab[i] = a->tab[i] | b_sign; } break; case OP_and: for(i = 0; i < b_len; i++) { r->tab[i] = a->tab[i] & b->tab[i]; } for(i = b_len; i < a_len; i++) { r->tab[i] = a->tab[i] & b_sign; } break; case OP_xor: for(i = 0; i < b_len; i++) { r->tab[i] = a->tab[i] ^ b->tab[i]; } for(i = b_len; i < a_len; i++) { r->tab[i] = a->tab[i] ^ b_sign; } break; default: abort(); } return js_bigint_normalize(ctx, r); } static JSBigInt *js_bigint_not(JSContext *ctx, const JSBigInt *a) { JSBigInt *r; int i; r = js_bigint_new(ctx, a->len); if (!r) return NULL; for(i = 0; i < a->len; i++) { r->tab[i] = ~a->tab[i]; } /* no normalization is needed */ return r; } static JSBigInt *js_bigint_shl(JSContext *ctx, const JSBigInt *a, unsigned int shift1) { int d, i, shift; JSBigInt *r; js_limb_t l; if (a->len == 1 && a->tab[0] == 0) return js_bigint_new_si(ctx, 0); /* zero case */ d = shift1 / JS_LIMB_BITS; shift = shift1 % JS_LIMB_BITS; r = js_bigint_new(ctx, a->len + d); if (!r) return NULL; for(i = 0; i < d; i++) r->tab[i] = 0; if (shift == 0) { for(i = 0; i < a->len; i++) { r->tab[i + d] = a->tab[i]; } } else { l = js_mp_shl(r->tab + d, a->tab, a->len, shift); if (js_bigint_sign(a)) l |= (js_limb_t)(-1) << shift; r = js_bigint_extend(ctx, r, l); } return r; } static JSBigInt *js_bigint_shr(JSContext *ctx, const JSBigInt *a, unsigned int shift1) { int d, i, shift, a_sign, n1; JSBigInt *r; d = shift1 / JS_LIMB_BITS; shift = shift1 % JS_LIMB_BITS; a_sign = js_bigint_sign(a); if (d >= a->len) return js_bigint_new_si(ctx, -a_sign); n1 = a->len - d; r = js_bigint_new(ctx, n1); if (!r) return NULL; if (shift == 0) { for(i = 0; i < n1; i++) { r->tab[i] = a->tab[i + d]; } /* no normalization is needed */ } else { js_mp_shr(r->tab, a->tab + d, n1, shift, -a_sign); r = js_bigint_normalize(ctx, r); } return r; } static JSBigInt *js_bigint_pow(JSContext *ctx, const JSBigInt *a, JSBigInt *b) { uint32_t e; int n_bits, i; JSBigInt *r, *r1; /* b must be >= 0 */ if (js_bigint_sign(b)) { JS_ThrowRangeError(ctx, "BigInt negative exponent"); return NULL; } if (b->len == 1 && b->tab[0] == 0) { /* a^0 = 1 */ return js_bigint_new_si(ctx, 1); } else if (a->len == 1) { js_limb_t v; bool is_neg; v = a->tab[0]; if (v <= 1) return js_bigint_new_si(ctx, v); else if (v == -1) return js_bigint_new_si(ctx, 1 - 2 * (b->tab[0] & 1)); is_neg = (js_slimb_t)v < 0; if (is_neg) v = -v; if ((v & (v - 1)) == 0) { uint64_t e1; int n; /* v = 2^n */ n = JS_LIMB_BITS - 1 - js_limb_clz(v); if (b->len > 1) goto overflow; if (b->tab[0] > INT32_MAX) goto overflow; e = b->tab[0]; e1 = (uint64_t)e * n; if (e1 > JS_BIGINT_MAX_SIZE * JS_LIMB_BITS) goto overflow; e = e1; if (is_neg) is_neg = b->tab[0] & 1; r = js_bigint_new(ctx, (e + JS_LIMB_BITS + 1 - is_neg) / JS_LIMB_BITS); if (!r) return NULL; memset(r->tab, 0, sizeof(r->tab[0]) * r->len); r->tab[e / JS_LIMB_BITS] = (js_limb_t)(1 - 2 * is_neg) << (e % JS_LIMB_BITS); return r; } } if (b->len > 1) goto overflow; if (b->tab[0] > INT32_MAX) goto overflow; e = b->tab[0]; n_bits = 32 - clz32(e); r = js_bigint_new(ctx, a->len); if (!r) return NULL; memcpy(r->tab, a->tab, a->len * sizeof(a->tab[0])); for(i = n_bits - 2; i >= 0; i--) { r1 = js_bigint_mul(ctx, r, r); if (!r1) return NULL; js_free(ctx, r); r = r1; if ((e >> i) & 1) { r1 = js_bigint_mul(ctx, r, a); if (!r1) return NULL; js_free(ctx, r); r = r1; } } return r; overflow: JS_ThrowRangeError(ctx, "BigInt is too large"); return NULL; } /* return (mant, exp) so that abs(a) ~ mant*2^(exp - (limb_bits - 1). a must be != 0. */ static uint64_t js_bigint_get_mant_exp(JSContext *ctx, int *pexp, const JSBigInt *a) { js_limb_t t[4 - JS_LIMB_BITS / 32], carry, v, low_bits; int n1, n2, sgn, shift, i, j, e; uint64_t a1, a0; n2 = 4 - JS_LIMB_BITS / 32; n1 = a->len - n2; sgn = js_bigint_sign(a); /* low_bits != 0 if there are a non zero low bit in abs(a) */ low_bits = 0; carry = sgn; for(i = 0; i < n1; i++) { v = (a->tab[i] ^ (-sgn)) + carry; carry = v < carry; low_bits |= v; } /* get the n2 high limbs of abs(a) */ for(j = 0; j < n2; j++) { i = j + n1; if (i < 0) { v = 0; } else { v = (a->tab[i] ^ (-sgn)) + carry; carry = v < carry; } t[j] = v; } a1 = ((uint64_t)t[2] << 32) | t[1]; a0 = (uint64_t)t[0] << 32; a0 |= (low_bits != 0); /* normalize */ { shift = clz64(a1); if (shift != 0) { a1 = (a1 << shift) | (a0 >> (64 - shift)); a0 <<= shift; } } a1 |= (a0 != 0); /* keep the bits for the final rounding */ /* compute the exponent */ e = a->len * JS_LIMB_BITS - shift - 1; *pexp = e; return a1; } /* shift left with round to nearest, ties to even. n >= 1 */ static uint64_t shr_rndn(uint64_t a, int n) { uint64_t addend = ((a >> n) & 1) + ((1 << (n - 1)) - 1); return (a + addend) >> n; } /* convert to float64 with round to nearest, ties to even. Return +/-infinity if too large. */ static double js_bigint_to_float64(JSContext *ctx, const JSBigInt *a) { int sgn, e; uint64_t mant; if (a->len == 1) { /* fast case, including zero */ return (double)(js_slimb_t)a->tab[0]; } sgn = js_bigint_sign(a); mant = js_bigint_get_mant_exp(ctx, &e, a); if (e > 1023) { /* overflow: return infinity */ mant = 0; e = 1024; } else { mant = (mant >> 1) | (mant & 1); /* avoid overflow in rounding */ mant = shr_rndn(mant, 10); /* rounding can cause an overflow */ if (mant >= ((uint64_t)1 << 53)) { mant >>= 1; e++; } mant &= (((uint64_t)1 << 52) - 1); } return uint64_as_float64(((uint64_t)sgn << 63) | ((uint64_t)(e + 1023) << 52) | mant); } /* return (1, NULL) if not an integer, (2, NULL) if NaN or Infinity, (0, n) if an integer, (0, NULL) in case of memory error */ static JSBigInt *js_bigint_from_float64(JSContext *ctx, int *pres, double a1) { uint64_t a = float64_as_uint64(a1); int sgn, e, shift; uint64_t mant; JSBigIntBuf buf; JSBigInt *r; sgn = a >> 63; e = (a >> 52) & ((1 << 11) - 1); mant = a & (((uint64_t)1 << 52) - 1); if (e == 2047) { /* NaN, Infinity */ *pres = 2; return NULL; } if (e == 0 && mant == 0) { /* zero */ *pres = 0; return js_bigint_new_si(ctx, 0); } e -= 1023; /* 0 < a < 1 : not an integer */ if (e < 0) goto not_an_integer; mant |= (uint64_t)1 << 52; if (e < 52) { shift = 52 - e; /* check that there is no fractional part */ if (mant & (((uint64_t)1 << shift) - 1)) { not_an_integer: *pres = 1; return NULL; } mant >>= shift; e = 0; } else { e -= 52; } if (sgn) mant = -mant; /* the integer is mant*2^e */ r = js_bigint_set_si64(&buf, (int64_t)mant); *pres = 0; return js_bigint_shl(ctx, r, e); } /* return -1, 0, 1 or (2) (unordered) */ static int js_bigint_float64_cmp(JSContext *ctx, const JSBigInt *a, double b) { int b_sign, a_sign, e, f; uint64_t mant, b1, a_mant; b1 = float64_as_uint64(b); b_sign = b1 >> 63; e = (b1 >> 52) & ((1 << 11) - 1); mant = b1 & (((uint64_t)1 << 52) - 1); a_sign = js_bigint_sign(a); if (e == 2047) { if (mant != 0) { /* NaN */ return 2; } else { /* +/- infinity */ return 2 * b_sign - 1; } } else if (e == 0 && mant == 0) { /* b = +/-0 */ if (a->len == 1 && a->tab[0] == 0) return 0; else return 1 - 2 * a_sign; } else if (a->len == 1 && a->tab[0] == 0) { /* a = 0, b != 0 */ return 2 * b_sign - 1; } else if (a_sign != b_sign) { return 1 - 2 * a_sign; } else { e -= 1023; /* Note: handling denormals is not necessary because we compare to integers hence f >= 0 */ /* compute f so that 2^f <= abs(a) < 2^(f+1) */ a_mant = js_bigint_get_mant_exp(ctx, &f, a); if (f != e) { if (f < e) return -1; else return 1; } else { mant = (mant | ((uint64_t)1 << 52)) << 11; /* align to a_mant */ if (a_mant < mant) return 2 * a_sign - 1; else if (a_mant > mant) return 1 - 2 * a_sign; else return 0; } } } /* return -1, 0 or 1 */ static int js_bigint_cmp(JSContext *ctx, const JSBigInt *a, const JSBigInt *b) { int a_sign, b_sign, res, i; a_sign = js_bigint_sign(a); b_sign = js_bigint_sign(b); if (a_sign != b_sign) { res = 1 - 2 * a_sign; } else { /* we assume the numbers are normalized */ if (a->len != b->len) { if (a->len < b->len) res = 2 * a_sign - 1; else res = 1 - 2 * a_sign; } else { res = 0; for(i = a->len -1; i >= 0; i--) { if (a->tab[i] != b->tab[i]) { if (a->tab[i] < b->tab[i]) res = -1; else res = 1; break; } } } } return res; } /* contains 10^i */ static const js_limb_t js_pow_dec[JS_LIMB_DIGITS + 1] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U, 1000000000U, }; /* syntax: [-]digits in base radix. Return NULL if memory error. radix = 10, 2, 8 or 16. */ static JSBigInt *js_bigint_from_string(JSContext *ctx, const char *str, int radix) { const char *p = str; size_t n_digits1; int is_neg, n_digits, n_limbs, len, log2_radix, n_bits, i; JSBigInt *r; js_limb_t v, c, h; is_neg = 0; if (*p == '-') { is_neg = 1; p++; } while (*p == '0') p++; n_digits1 = strlen(p); /* the real check for overflox is done js_bigint_new(). Here we just avoid integer overflow */ if (n_digits1 > JS_BIGINT_MAX_SIZE * JS_LIMB_BITS) { JS_ThrowRangeError(ctx, "BigInt is too large to allocate"); return NULL; } n_digits = n_digits1; log2_radix = 32 - clz32(radix - 1); /* ceil(log2(radix)) */ /* compute the maximum number of limbs */ if (radix == 10) { n_bits = (n_digits * 27 + 7) / 8; /* >= ceil(n_digits * log2(10)) */ } else { n_bits = n_digits * log2_radix; } /* we add one extra bit for the sign */ n_limbs = max_int(1, n_bits / JS_LIMB_BITS + 1); r = js_bigint_new(ctx, n_limbs); if (!r) return NULL; if (radix == 10) { int digits_per_limb = JS_LIMB_DIGITS; len = 1; r->tab[0] = 0; for(;;) { /* XXX: slow */ v = 0; for(i = 0; i < digits_per_limb; i++) { c = js_to_digit(*p); if (c >= radix) break; p++; v = v * 10 + c; } if (i == 0) break; if (len == 1 && r->tab[0] == 0) { r->tab[0] = v; } else { h = js_mp_mul1(r->tab, r->tab, len, js_pow_dec[i], v); if (h != 0) { r->tab[len++] = h; } } } /* add one extra limb to have the correct sign*/ if ((r->tab[len - 1] >> (JS_LIMB_BITS - 1)) != 0) r->tab[len++] = 0; r->len = len; } else { unsigned int bit_pos, shift, pos; /* power of two base: no multiplication is needed */ r->len = n_limbs; memset(r->tab, 0, sizeof(r->tab[0]) * n_limbs); for(i = 0; i < n_digits; i++) { c = js_to_digit(p[n_digits - 1 - i]); assert(c < radix); bit_pos = i * log2_radix; shift = bit_pos & (JS_LIMB_BITS - 1); pos = bit_pos / JS_LIMB_BITS; r->tab[pos] |= c << shift; /* if log2_radix does not divide JS_LIMB_BITS, needed an additional op */ if (shift + log2_radix > JS_LIMB_BITS) { r->tab[pos + 1] |= c >> (JS_LIMB_BITS - shift); } } } r = js_bigint_normalize(ctx, r); /* XXX: could do it in place */ if (is_neg) { JSBigInt *r1; r1 = js_bigint_neg(ctx, r); js_free(ctx, r); r = r1; } return r; } /* 2 <= base <= 36 */ static char const digits[36] = { '0','1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f','g','h','i','j', 'k','l','m','n','o','p','q','r','s','t', 'u','v','w','x','y','z' }; /* special version going backwards */ /* XXX: use dtoa.c */ static char *js_u64toa(char *q, int64_t n, unsigned int base) { int digit; if (base == 10) { /* division by known base uses multiplication */ do { digit = (uint64_t)n % 10; n = (uint64_t)n / 10; *--q = '0' + digit; } while (n != 0); } else { do { digit = (uint64_t)n % base; n = (uint64_t)n / base; *--q = digits[digit]; } while (n != 0); } return q; } /* len >= 1. 2 <= radix <= 36 */ static char *js_limb_to_a(char *q, js_limb_t n, unsigned int radix, int len) { int digit, i; if (radix == 10) { /* specific case with constant divisor */ /* XXX: optimize */ for(i = 0; i < len; i++) { digit = (js_limb_t)n % 10; n = (js_limb_t)n / 10; *--q = digit + '0'; } } else { for(i = 0; i < len; i++) { digit = (js_limb_t)n % radix; n = (js_limb_t)n / radix; *--q = digits[digit]; } } return q; } #define JS_RADIX_MAX 36 static const uint8_t js_digits_per_limb_table[JS_RADIX_MAX - 1] = { 32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, }; static const js_limb_t js_radix_base_table[JS_RADIX_MAX - 1] = { 0x00000000, 0xcfd41b91, 0x00000000, 0x48c27395, 0x81bf1000, 0x75db9c97, 0x40000000, 0xcfd41b91, 0x3b9aca00, 0x8c8b6d2b, 0x19a10000, 0x309f1021, 0x57f6c100, 0x98c29b81, 0x00000000, 0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d, 0x94ace180, 0xcaf18367, 0x0b640000, 0x0e8d4a51, 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x81bf1000, }; static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) { if (JS_VALUE_GET_TAG(val) == JS_TAG_SHORT_BIG_INT) { char buf[66]; int len; len = i64toa_radix(buf, JS_VALUE_GET_SHORT_BIG_INT(val), radix); return js_new_string8_len(ctx, buf, len); } else { JSBigInt *r, *tmp = NULL; char *buf, *q, *buf_end; int is_neg, n_bits, log2_radix, n_digits; bool is_binary_radix; JSValue res; assert(JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT); r = JS_VALUE_GET_PTR(val); if (r->len == 1 && r->tab[0] == 0) { /* '0' case */ return js_new_string8_len(ctx, "0", 1); } is_binary_radix = ((radix & (radix - 1)) == 0); is_neg = js_bigint_sign(r); if (is_neg) { tmp = js_bigint_neg(ctx, r); if (!tmp) return JS_EXCEPTION; r = tmp; } else if (!is_binary_radix) { /* need to modify 'r' */ tmp = js_bigint_new(ctx, r->len); if (!tmp) return JS_EXCEPTION; memcpy(tmp->tab, r->tab, r->len * sizeof(r->tab[0])); r = tmp; } log2_radix = 31 - clz32(radix); /* floor(log2(radix)) */ n_bits = r->len * JS_LIMB_BITS - js_limb_clz(r->tab[r->len - 1]); /* n_digits is exact only if radix is a power of two. Otherwise it is >= the exact number of digits */ n_digits = (n_bits + log2_radix - 1) / log2_radix; /* XXX: could directly build the JSString */ buf = js_malloc(ctx, n_digits + is_neg + 1); if (!buf) { js_free(ctx, tmp); return JS_EXCEPTION; } q = buf + n_digits + is_neg + 1; *--q = '\0'; buf_end = q; if (!is_binary_radix) { int len; js_limb_t radix_base, v; radix_base = js_radix_base_table[radix - 2]; len = r->len; for(;;) { /* remove leading zero limbs */ while (len > 1 && r->tab[len - 1] == 0) len--; if (len == 1 && r->tab[0] < radix_base) { v = r->tab[0]; if (v != 0) { q = js_u64toa(q, v, radix); } break; } else { v = js_mp_div1(r->tab, r->tab, len, radix_base, 0); q = js_limb_to_a(q, v, radix, js_digits_per_limb_table[radix - 2]); } } } else { int i, shift; unsigned int bit_pos, pos, c; /* radix is a power of two */ for(i = 0; i < n_digits; i++) { bit_pos = i * log2_radix; pos = bit_pos / JS_LIMB_BITS; shift = bit_pos % JS_LIMB_BITS; c = r->tab[pos] >> shift; if ((shift + log2_radix) > JS_LIMB_BITS && (pos + 1) < r->len) { c |= r->tab[pos + 1] << (JS_LIMB_BITS - shift); } c &= (radix - 1); *--q = digits[c]; } } if (is_neg) *--q = '-'; js_free(ctx, tmp); res = js_new_string8_len(ctx, q, buf_end - q); js_free(ctx, buf); return res; } } /* if possible transform a BigInt to short big and free it, otherwise return a normal bigint */ static JSValue JS_CompactBigInt(JSContext *ctx, JSBigInt *p) { JSValue res; if (p->len == 1) { res = __JS_NewShortBigInt(ctx, (js_slimb_t)p->tab[0]); js_free(ctx, p); return res; } else { return JS_MKPTR(JS_TAG_BIG_INT, p); } } #define ATOD_INT_ONLY (1 << 0) /* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */ #define ATOD_ACCEPT_BIN_OCT (1 << 2) /* accept O prefix as octal if radix == 0 and properly formed (Annex B) */ #define ATOD_ACCEPT_LEGACY_OCTAL (1 << 4) /* accept _ between digits as a digit separator */ #define ATOD_ACCEPT_UNDERSCORES (1 << 5) /* allow a suffix to override the type */ #define ATOD_ACCEPT_SUFFIX (1 << 6) /* default type */ #define ATOD_TYPE_MASK (3 << 7) #define ATOD_TYPE_FLOAT64 (0 << 7) #define ATOD_TYPE_BIG_INT (1 << 7) /* accept -0x1 */ #define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10) /* return an exception in case of memory error. Return JS_NAN if invalid syntax */ /* XXX: directly use js_atod() */ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, int radix, int flags) { const char *p, *p_start; int sep, is_neg; bool is_float, has_legacy_octal; int atod_type = flags & ATOD_TYPE_MASK; char buf1[64], *buf; int i, j, len; bool buf_allocated = false; JSValue val; JSATODTempMem atod_mem; /* optional separator between digits */ sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256; has_legacy_octal = false; p = str; p_start = p; is_neg = 0; if (p[0] == '+') { p++; p_start++; if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN)) goto no_radix_prefix; } else if (p[0] == '-') { p++; p_start++; is_neg = 1; if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN)) goto no_radix_prefix; } if (p[0] == '0') { if ((p[1] == 'x' || p[1] == 'X') && (radix == 0 || radix == 16)) { p += 2; radix = 16; } else if ((p[1] == 'o' || p[1] == 'O') && radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) { p += 2; radix = 8; } else if ((p[1] == 'b' || p[1] == 'B') && radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) { p += 2; radix = 2; } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) { int i; has_legacy_octal = true; sep = 256; for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) continue; if (p[i] == '8' || p[i] == '9') goto no_prefix; p += 1; radix = 8; } else { goto no_prefix; } /* there must be a digit after the prefix */ if (js_to_digit((uint8_t)*p) >= radix) goto fail; no_prefix: ; } else { no_radix_prefix: if (!(flags & ATOD_INT_ONLY) && (atod_type == ATOD_TYPE_FLOAT64) && js__strstart(p, "Infinity", &p)) { double d = INF; if (is_neg) d = -d; val = js_float64(d); goto done; } } if (radix == 0) radix = 10; is_float = false; p_start = p; while (js_to_digit((uint8_t)*p) < radix || (*p == sep && (radix != 10 || p != p_start + 1 || p[-1] != '0') && js_to_digit((uint8_t)p[1]) < radix)) { p++; } if (!(flags & ATOD_INT_ONLY) && radix == 10) { if (*p == '.' && (p > p_start || js_to_digit((uint8_t)p[1]) < radix)) { is_float = true; p++; if (*p == sep) goto fail; while (js_to_digit((uint8_t)*p) < radix || (*p == sep && js_to_digit((uint8_t)p[1]) < radix)) p++; } if (p > p_start && (*p == 'e' || *p == 'E')) { const char *p1 = p + 1; is_float = true; if (*p1 == '+') { p1++; } else if (*p1 == '-') { p1++; } if (is_digit((uint8_t)*p1)) { p = p1 + 1; while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1]))) p++; } } } if (p == p_start) goto fail; buf = buf1; buf_allocated = false; len = p - p_start; if (unlikely((len + 2) > sizeof(buf1))) { buf = js_malloc_rt(ctx->rt, len + 2); /* no exception raised */ if (!buf) goto mem_error; buf_allocated = true; } /* remove the separators and the radix prefixes */ j = 0; if (is_neg) buf[j++] = '-'; for (i = 0; i < len; i++) { if (p_start[i] != '_') buf[j++] = p_start[i]; } buf[j] = '\0'; if (flags & ATOD_ACCEPT_SUFFIX) { if (*p == 'n') { p++; atod_type = ATOD_TYPE_BIG_INT; } } switch(atod_type) { case ATOD_TYPE_FLOAT64: { double d; d = js_atod(buf, NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY, &atod_mem); /* return int or float64 */ val = js_number(d); } break; case ATOD_TYPE_BIG_INT: { JSBigInt *r; if (has_legacy_octal || is_float) goto fail; r = js_bigint_from_string(ctx, buf, radix); if (!r) { val = JS_EXCEPTION; goto done; } val = JS_CompactBigInt(ctx, r); } break; default: abort(); } done: if (buf_allocated) js_free_rt(ctx->rt, buf); if (pp) *pp = p; return val; fail: val = JS_NAN; goto done; mem_error: val = JS_ThrowOutOfMemory(ctx); goto done; } typedef enum JSToNumberHintEnum { TON_FLAG_NUMBER, TON_FLAG_NUMERIC, } JSToNumberHintEnum; static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, JSToNumberHintEnum flag) { uint32_t tag; JSValue ret; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_BIG_INT: case JS_TAG_SHORT_BIG_INT: if (flag != TON_FLAG_NUMERIC) { JS_FreeValue(ctx, val); return JS_ThrowTypeError(ctx, "cannot convert BigInt to number"); } ret = val; break; case JS_TAG_FLOAT64: case JS_TAG_INT: case JS_TAG_EXCEPTION: ret = val; break; case JS_TAG_BOOL: case JS_TAG_NULL: ret = js_int32(JS_VALUE_GET_INT(val)); break; case JS_TAG_UNDEFINED: ret = JS_NAN; break; case JS_TAG_OBJECT: val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER); if (JS_IsException(val)) return JS_EXCEPTION; goto redo; case JS_TAG_STRING: { const char *str; const char *p; size_t len; str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) return JS_EXCEPTION; p = str; p += skip_spaces(p); if ((p - str) == len) { ret = JS_NewInt32(ctx, 0); } else { int flags = ATOD_ACCEPT_BIN_OCT; ret = js_atof(ctx, p, &p, 0, flags); if (!JS_IsException(ret)) { p += skip_spaces(p); if ((p - str) != len) { JS_FreeValue(ctx, ret); ret = JS_NAN; } } } JS_FreeCString(ctx, str); } break; case JS_TAG_SYMBOL: JS_FreeValue(ctx, val); return JS_ThrowTypeError(ctx, "cannot convert symbol to number"); default: JS_FreeValue(ctx, val); ret = JS_NAN; break; } return ret; } static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val) { return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMBER); } static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val) { return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMERIC); } static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val) { return JS_ToNumericFree(ctx, js_dup(val)); } static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val) { double d; uint32_t tag; val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) goto fail; tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: d = JS_VALUE_GET_INT(val); break; case JS_TAG_FLOAT64: d = JS_VALUE_GET_FLOAT64(val); break; default: abort(); } *pres = d; return 0; fail: *pres = NAN; return -1; } static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val) { uint32_t tag; tag = JS_VALUE_GET_TAG(val); if (tag <= JS_TAG_NULL) { *pres = JS_VALUE_GET_INT(val); return 0; } else if (JS_TAG_IS_FLOAT64(tag)) { *pres = JS_VALUE_GET_FLOAT64(val); return 0; } else { return __JS_ToFloat64Free(ctx, pres, val); } } int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val) { return JS_ToFloat64Free(ctx, pres, js_dup(val)); } JSValue JS_ToNumber(JSContext *ctx, JSValueConst val) { return JS_ToNumberFree(ctx, js_dup(val)); } /* same as JS_ToNumber() but return 0 in case of NaN/Undefined */ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) { uint32_t tag; JSValue ret; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: ret = js_int32(JS_VALUE_GET_INT(val)); break; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { ret = js_int32(0); } else { /* convert -0 to +0 */ d = trunc(d) + 0.0; ret = js_number(d); } } break; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) return val; goto redo; } return ret; } /* Note: the integer value is satured to 32 bits */ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val) { uint32_t tag; int ret; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: ret = JS_VALUE_GET_INT(val); break; case JS_TAG_EXCEPTION: *pres = 0; return -1; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { ret = 0; } else { if (d < INT32_MIN) ret = INT32_MIN; else if (d > INT32_MAX) ret = INT32_MAX; else ret = (int)d; } } break; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } goto redo; } *pres = ret; return 0; } static int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val) { return JS_ToInt32SatFree(ctx, pres, js_dup(val)); } static int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val, int min, int max, int min_offset) { int res = JS_ToInt32SatFree(ctx, pres, js_dup(val)); if (res == 0) { if (*pres < min) { *pres += min_offset; if (*pres < min) *pres = min; } else { if (*pres > max) *pres = max; } } return res; } static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val) { uint32_t tag; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: *pres = JS_VALUE_GET_INT(val); return 0; case JS_TAG_EXCEPTION: *pres = 0; return -1; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { *pres = 0; } else { if (d < INT64_MIN) *pres = INT64_MIN; else if (d >= 0x1p63) *pres = INT64_MAX; else *pres = (int64_t)d; } } return 0; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } goto redo; } } int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val) { return JS_ToInt64SatFree(ctx, pres, js_dup(val)); } int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val, int64_t min, int64_t max, int64_t neg_offset) { int res = JS_ToInt64SatFree(ctx, pres, js_dup(val)); if (res == 0) { if (*pres < 0) *pres += neg_offset; if (*pres < min) *pres = min; else if (*pres > max) *pres = max; } return res; } /* Same as JS_ToInt32Free() but with a 64 bit result. Return (<0, 0) in case of exception */ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val) { uint32_t tag; int64_t ret; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: ret = JS_VALUE_GET_INT(val); break; case JS_TAG_FLOAT64: { JSFloat64Union u; double d; int e; d = JS_VALUE_GET_FLOAT64(val); u.d = d; /* we avoid doing fmod(x, 2^64) */ e = (u.u64 >> 52) & 0x7ff; if (likely(e <= (1023 + 62))) { /* fast case */ ret = (int64_t)d; } else if (e <= (1023 + 62 + 53)) { uint64_t v; /* remainder modulo 2^64 */ v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); ret = v << ((e - 1023) - 52); /* take the sign into account */ if (u.u64 >> 63) if (ret != INT64_MIN) ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } } break; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } goto redo; } *pres = ret; return 0; } int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val) { return JS_ToInt64Free(ctx, pres, js_dup(val)); } int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val) { if (JS_IsBigInt(val)) return JS_ToBigInt64(ctx, pres, val); else return JS_ToInt64(ctx, pres, val); } /* return (<0, 0) in case of exception */ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) { uint32_t tag; int32_t ret; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: ret = JS_VALUE_GET_INT(val); break; case JS_TAG_FLOAT64: { JSFloat64Union u; double d; int e; d = JS_VALUE_GET_FLOAT64(val); u.d = d; /* we avoid doing fmod(x, 2^32) */ e = (u.u64 >> 52) & 0x7ff; if (likely(e <= (1023 + 30))) { /* fast case */ ret = (int32_t)d; } else if (e <= (1023 + 30 + 53)) { uint64_t v; /* remainder modulo 2^32 */ v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); v = v << ((e - 1023) - 52 + 32); ret = v >> 32; /* take the sign into account */ if (u.u64 >> 63) if (ret != INT32_MIN) ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } } break; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } goto redo; } *pres = ret; return 0; } int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val) { return JS_ToInt32Free(ctx, pres, js_dup(val)); } static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val) { return JS_ToInt32Free(ctx, (int32_t *)pres, val); } static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val) { uint32_t tag; int res; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: res = JS_VALUE_GET_INT(val); res = max_int(0, min_int(255, res)); break; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { res = 0; } else { if (d < 0) res = 0; else if (d > 255) res = 255; else res = lrint(d); } } break; default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } goto redo; } *pres = res; return 0; } static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, JSValue val, bool is_array_ctor) { uint32_t tag, len; tag = JS_VALUE_GET_TAG(val); switch(tag) { case JS_TAG_INT: case JS_TAG_BOOL: case JS_TAG_NULL: { int v; v = JS_VALUE_GET_INT(val); if (v < 0) goto fail; len = v; } break; default: if (JS_TAG_IS_FLOAT64(tag)) { double d; d = JS_VALUE_GET_FLOAT64(val); if (!(d >= 0 && d <= UINT32_MAX)) goto fail; len = (uint32_t)d; if (len != d) goto fail; } else { uint32_t len1; if (is_array_ctor) { val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) return -1; /* cannot recurse because val is a number */ if (JS_ToArrayLengthFree(ctx, &len, val, true)) return -1; } else { /* legacy behavior: must do the conversion twice and compare */ if (JS_ToUint32(ctx, &len, val)) { JS_FreeValue(ctx, val); return -1; } val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) return -1; /* cannot recurse because val is a number */ if (JS_ToArrayLengthFree(ctx, &len1, val, false)) return -1; if (len1 != len) { fail: JS_ThrowRangeError(ctx, "invalid array length"); return -1; } } } break; } *plen = len; return 0; } #define MAX_SAFE_INTEGER (((int64_t)1 << 53) - 1) static bool is_safe_integer(double d) { return isfinite(d) && floor(d) == d && fabs(d) <= (double)MAX_SAFE_INTEGER; } int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val) { int64_t v; if (JS_ToInt64Sat(ctx, &v, val)) return -1; if (v < 0 || v > MAX_SAFE_INTEGER) { JS_ThrowRangeError(ctx, "invalid array index"); *plen = 0; return -1; } *plen = v; return 0; } /* convert a value to a length between 0 and MAX_SAFE_INTEGER. return -1 for exception */ static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen, JSValue val) { int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0); JS_FreeValue(ctx, val); return res; } /* Note: can return an exception */ static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val) { double d; if (!JS_IsNumber(val)) return false; if (unlikely(JS_ToFloat64(ctx, &d, val))) return -1; return isfinite(d) && floor(d) == d; } static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) { uint32_t tag; tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_INT: { int v; v = JS_VALUE_GET_INT(val); return (v < 0); } case JS_TAG_FLOAT64: { JSFloat64Union u; u.d = JS_VALUE_GET_FLOAT64(val); return (u.u64 >> 63); } case JS_TAG_SHORT_BIG_INT: return (JS_VALUE_GET_SHORT_BIG_INT(val) < 0); case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(val); return js_bigint_sign(p); } default: return false; } } static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val) { return js_bigint_to_string1(ctx, val, 10); } /*---- floating point number to string conversions ----*/ static JSValue js_dtoa2(JSContext *ctx, double d, int radix, int n_digits, int flags) { char static_buf[128], *buf, *tmp_buf; int len, len_max; JSValue res; JSDTOATempMem dtoa_mem; len_max = js_dtoa_max_len(d, radix, n_digits, flags); /* longer buffer may be used if radix != 10 */ if (len_max > sizeof(static_buf) - 1) { tmp_buf = js_malloc(ctx, len_max + 1); if (!tmp_buf) return JS_EXCEPTION; buf = tmp_buf; } else { tmp_buf = NULL; buf = static_buf; } len = js_dtoa(buf, d, radix, n_digits, flags, &dtoa_mem); res = js_new_string8_len(ctx, buf, len); js_free(ctx, tmp_buf); return res; } static JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, int flags) { uint32_t tag; char buf[32]; size_t len; tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_STRING: return js_dup(val); case JS_TAG_INT: len = i32toa(buf, JS_VALUE_GET_INT(val)); return js_new_string8_len(ctx, buf, len); case JS_TAG_BOOL: return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ? JS_ATOM_true : JS_ATOM_false); case JS_TAG_NULL: return JS_AtomToString(ctx, JS_ATOM_null); case JS_TAG_UNDEFINED: return JS_AtomToString(ctx, JS_ATOM_undefined); case JS_TAG_EXCEPTION: return JS_EXCEPTION; case JS_TAG_OBJECT: if (flags & JS_TO_STRING_NO_SIDE_EFFECTS) { return js_new_string8(ctx, "{}"); } else { JSValue val1, ret; val1 = JS_ToPrimitive(ctx, val, HINT_STRING); if (JS_IsException(val1)) return val1; ret = JS_ToStringInternal(ctx, val1, flags); JS_FreeValue(ctx, val1); return ret; } break; case JS_TAG_FUNCTION_BYTECODE: return js_new_string8(ctx, "[function bytecode]"); case JS_TAG_SYMBOL: if (flags & JS_TO_STRING_IS_PROPERTY_KEY) { return js_dup(val); } else { return JS_ThrowTypeError(ctx, "cannot convert symbol to string"); } case JS_TAG_FLOAT64: return js_dtoa2(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0, JS_DTOA_FORMAT_FREE); case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: return js_bigint_to_string(ctx, val); case JS_TAG_UNINITIALIZED: return js_new_string8(ctx, "[uninitialized]"); default: return js_new_string8(ctx, "[unsupported type]"); } } JSValue JS_ToString(JSContext *ctx, JSValueConst val) { return JS_ToStringInternal(ctx, val, /*flags*/0); } static JSValue JS_ToStringFree(JSContext *ctx, JSValue val) { JSValue ret; ret = JS_ToString(ctx, val); JS_FreeValue(ctx, val); return ret; } static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val) { if (JS_IsUndefined(val) || JS_IsNull(val)) return JS_ToStringFree(ctx, val); return JS_InvokeFree(ctx, val, JS_ATOM_toLocaleString, 0, NULL); } static JSValue JS_ToPropertyKeyInternal(JSContext *ctx, JSValueConst val, int flags) { return JS_ToStringInternal(ctx, val, flags | JS_TO_STRING_IS_PROPERTY_KEY); } JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val) { return JS_ToPropertyKeyInternal(ctx, val, /*flags*/0); } static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val) { uint32_t tag = JS_VALUE_GET_TAG(val); if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) return JS_ThrowTypeError(ctx, "null or undefined are forbidden"); return JS_ToString(ctx, val); } static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) { JSValue val; JSString *p; int i; uint32_t c; StringBuffer b_s, *b = &b_s; char buf[16]; val = JS_ToStringCheckObject(ctx, val1); if (JS_IsException(val)) return val; p = JS_VALUE_GET_STRING(val); if (string_buffer_init(ctx, b, p->len + 2)) goto fail; if (string_buffer_putc8(b, '\"')) goto fail; for(i = 0; i < p->len; ) { c = string_getc(p, &i); switch(c) { case '\t': c = 't'; goto quote; case '\r': c = 'r'; goto quote; case '\n': c = 'n'; goto quote; case '\b': c = 'b'; goto quote; case '\f': c = 'f'; goto quote; case '\"': case '\\': quote: if (string_buffer_putc8(b, '\\')) goto fail; if (string_buffer_putc8(b, c)) goto fail; break; default: if (c < 32 || is_surrogate(c)) { snprintf(buf, sizeof(buf), "\\u%04x", c); if (string_buffer_write8(b, (uint8_t*)buf, 6)) goto fail; } else { if (string_buffer_putc(b, c)) goto fail; } break; } } if (string_buffer_putc8(b, '\"')) goto fail; JS_FreeValue(ctx, val); return string_buffer_end(b); fail: JS_FreeValue(ctx, val); string_buffer_free(b); return JS_EXCEPTION; } static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt) { printf("%14s %4s %4s %14s %10s %s\n", "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS"); } /* for debug only: dump an object without side effect */ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) { uint32_t i; char atom_buf[ATOM_GET_STR_BUF_SIZE]; JSShape *sh; JSShapeProperty *prs; JSProperty *pr; bool is_first = true; /* XXX: should encode atoms with special characters */ sh = p->shape; /* the shape can be NULL while freeing an object */ printf("%14p %4d ", (void *)p, p->header.ref_count); if (sh) { printf("%3d%c %14p ", sh->header.ref_count, " *"[sh->is_hashed], (void *)sh->proto); } else { printf("%3s %14s ", "-", "-"); } printf("%10s ", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name)); if (p->is_exotic && p->fast_array) { printf("[ "); for(i = 0; i < p->u.array.count; i++) { if (i != 0) printf(", "); switch (p->class_id) { case JS_CLASS_ARRAY: case JS_CLASS_ARGUMENTS: JS_DumpValue(rt, p->u.array.u.values[i]); break; case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: case JS_CLASS_INT16_ARRAY: case JS_CLASS_UINT16_ARRAY: case JS_CLASS_INT32_ARRAY: case JS_CLASS_UINT32_ARRAY: case JS_CLASS_BIG_INT64_ARRAY: case JS_CLASS_BIG_UINT64_ARRAY: case JS_CLASS_FLOAT16_ARRAY: case JS_CLASS_FLOAT32_ARRAY: case JS_CLASS_FLOAT64_ARRAY: { int size = 1 << typed_array_size_log2(p->class_id); const uint8_t *b = p->u.array.u.uint8_ptr + i * size; while (size-- > 0) printf("%02X", *b++); } break; } } printf(" ] "); } if (sh) { printf("{ "); for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->atom != JS_ATOM_NULL) { pr = &p->prop[i]; if (!is_first) printf(", "); printf("%s: ", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom)); if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { printf("[getset %p %p]", (void *)pr->u.getset.getter, (void *)pr->u.getset.setter); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { printf("[varref %p]", (void *)pr->u.var_ref); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { printf("[autoinit %p %d %p]", (void *)js_autoinit_get_realm(pr), js_autoinit_get_id(pr), (void *)pr->u.init.opaque); } else { JS_DumpValue(rt, pr->u.value); } is_first = false; } } printf(" }"); } if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; JSVarRef **var_refs; if (b->closure_var_count) { var_refs = p->u.func.var_refs; printf(" Closure:"); for(i = 0; i < b->closure_var_count; i++) { printf(" "); JS_DumpValue(rt, var_refs[i]->value); } if (p->u.func.home_object) { printf(" HomeObject: "); JS_DumpValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object)); } } } printf("\n"); } static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) { if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { JS_DumpObject(rt, (JSObject *)p); } else { printf("%14p %4d ", (void *)p, p->ref_count); switch(p->gc_obj_type) { case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: printf("[function bytecode]"); break; case JS_GC_OBJ_TYPE_SHAPE: printf("[shape]"); break; case JS_GC_OBJ_TYPE_VAR_REF: printf("[var_ref]"); break; case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: printf("[async_function]"); break; case JS_GC_OBJ_TYPE_JS_CONTEXT: printf("[js_context]"); break; default: printf("[unknown %d]", p->gc_obj_type); break; } printf("\n"); } } static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val) { uint32_t tag = JS_VALUE_GET_NORM_TAG(val); const char *str; switch(tag) { case JS_TAG_INT: printf("%d", JS_VALUE_GET_INT(val)); break; case JS_TAG_BOOL: if (JS_VALUE_GET_BOOL(val)) str = "true"; else str = "false"; goto print_str; case JS_TAG_NULL: str = "null"; goto print_str; case JS_TAG_EXCEPTION: str = "exception"; goto print_str; case JS_TAG_UNINITIALIZED: str = "uninitialized"; goto print_str; case JS_TAG_UNDEFINED: str = "undefined"; print_str: printf("%s", str); break; case JS_TAG_FLOAT64: printf("%.14g", JS_VALUE_GET_FLOAT64(val)); break; case JS_TAG_SHORT_BIG_INT: printf("%" PRId64 "n", (int64_t)JS_VALUE_GET_SHORT_BIG_INT(val)); break; case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(val); int sgn, i; /* In order to avoid allocations we just dump the limbs */ sgn = js_bigint_sign(p); if (sgn) printf("BigInt.asIntN(%d,", p->len * JS_LIMB_BITS); printf("0x"); for(i = p->len - 1; i >= 0; i--) { if (i != p->len - 1) printf("_"); printf("%08x", p->tab[i]); } printf("n"); if (sgn) printf(")"); } break; case JS_TAG_STRING: { JSString *p; p = JS_VALUE_GET_STRING(val); JS_DumpString(rt, p); } break; case JS_TAG_FUNCTION_BYTECODE: { JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); char buf[ATOM_GET_STR_BUF_SIZE]; if (b->func_name) { printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); } else { printf("[bytecode (anonymous)]"); } } break; case JS_TAG_OBJECT: { JSObject *p = JS_VALUE_GET_OBJ(val); JSAtom atom = rt->class_array[p->class_id].class_name; char atom_buf[ATOM_GET_STR_BUF_SIZE]; printf("[%s %p]", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p); } break; case JS_TAG_SYMBOL: { JSAtomStruct *p = JS_VALUE_GET_PTR(val); char atom_buf[ATOM_GET_STR_BUF_SIZE]; printf("Symbol(%s)", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p))); } break; case JS_TAG_MODULE: printf("[module]"); break; default: printf("[unknown tag %d]", tag); break; } } bool JS_IsArray(JSValueConst val) { if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(val); return p->class_id == JS_CLASS_ARRAY; } return false; } /* return -1 if exception (proxy case) or true/false */ static int js_is_array(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(val); if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_isArray(ctx, val); else return p->class_id == JS_CLASS_ARRAY; } else { return false; } } static double js_math_pow(double a, double b) { if (unlikely(!isfinite(b)) && fabs(a) == 1) { /* not compatible with IEEE 754 */ return NAN; } else { return pow(a, b); } } JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) { if (v >= JS_SHORT_BIG_INT_MIN && v <= JS_SHORT_BIG_INT_MAX) { return __JS_NewShortBigInt(ctx, v); } else { JSBigInt *p; p = js_bigint_new_si64(ctx, v); if (!p) return JS_EXCEPTION; return JS_MKPTR(JS_TAG_BIG_INT, p); } } JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) { if (v <= JS_SHORT_BIG_INT_MAX) { return __JS_NewShortBigInt(ctx, v); } else { JSBigInt *p; p = js_bigint_new_ui64(ctx, v); if (!p) return JS_EXCEPTION; return JS_MKPTR(JS_TAG_BIG_INT, p); } } /* return NaN if bad bigint literal */ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val) { const char *str, *p; size_t len; int flags; str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) return JS_EXCEPTION; p = str; p += skip_spaces(p); if ((p - str) == len) { val = JS_NewBigInt64(ctx, 0); } else { flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT; val = js_atof(ctx, p, &p, 0, flags); p += skip_spaces(p); if (!JS_IsException(val)) { if ((p - str) != len) { JS_FreeValue(ctx, val); val = JS_NAN; } } } JS_FreeCString(ctx, str); return val; } static JSValue JS_StringToBigIntErr(JSContext *ctx, JSValue val) { val = JS_StringToBigInt(ctx, val); if (JS_VALUE_IS_NAN(val)) return JS_ThrowSyntaxError(ctx, "invalid BigInt literal"); return val; } /* JS Numbers are not allowed */ static JSValue JS_ToBigIntFree(JSContext *ctx, JSValue val) { uint32_t tag; redo: tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: break; case JS_TAG_INT: case JS_TAG_NULL: case JS_TAG_UNDEFINED: case JS_TAG_FLOAT64: goto fail; case JS_TAG_BOOL: val = __JS_NewShortBigInt(ctx, JS_VALUE_GET_INT(val)); break; case JS_TAG_STRING: val = JS_StringToBigIntErr(ctx, val); if (JS_IsException(val)) return val; goto redo; case JS_TAG_OBJECT: val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER); if (JS_IsException(val)) return val; goto redo; default: fail: JS_FreeValue(ctx, val); return JS_ThrowTypeError(ctx, "cannot convert to bigint"); } return val; } static JSValue JS_ToBigInt(JSContext *ctx, JSValueConst val) { return JS_ToBigIntFree(ctx, js_dup(val)); } /* XXX: merge with JS_ToInt64Free with a specific flag */ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) { uint64_t res; val = JS_ToBigIntFree(ctx, val); if (JS_IsException(val)) { *pres = 0; return -1; } if (JS_VALUE_GET_TAG(val) == JS_TAG_SHORT_BIG_INT) { res = JS_VALUE_GET_SHORT_BIG_INT(val); } else { JSBigInt *p = JS_VALUE_GET_PTR(val); /* return the value mod 2^64 */ res = p->tab[0]; if (p->len >= 2) res |= (uint64_t)p->tab[1] << 32; JS_FreeValue(ctx, val); } *pres = res; return 0; } int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) { return JS_ToBigInt64Free(ctx, pres, js_dup(val)); } int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValueConst val) { return JS_ToBigInt64Free(ctx, (int64_t *)pres, js_dup(val)); } static no_inline __exception int js_unary_arith_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { JSValue op1; int v; uint32_t tag; JSBigIntBuf buf1; JSBigInt *p1; op1 = sp[-1]; /* fast path for float64 */ if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1))) goto handle_float64; op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) goto exception; tag = JS_VALUE_GET_TAG(op1); switch(tag) { case JS_TAG_INT: { int64_t v64; v64 = JS_VALUE_GET_INT(op1); switch(op) { case OP_inc: case OP_dec: v = 2 * (op - OP_dec) - 1; v64 += v; break; case OP_plus: break; case OP_neg: if (v64 == 0) { sp[-1] = js_float64(-0.0); return 0; } else { v64 = -v64; } break; default: abort(); } sp[-1] = js_int64(v64); } break; case JS_TAG_SHORT_BIG_INT: { int64_t v; v = JS_VALUE_GET_SHORT_BIG_INT(op1); switch(op) { case OP_plus: JS_ThrowTypeError(ctx, "bigint argument with unary +"); goto exception; case OP_inc: if (v == JS_SHORT_BIG_INT_MAX) goto bigint_slow_case; sp[-1] = __JS_NewShortBigInt(ctx, v + 1); break; case OP_dec: if (v == JS_SHORT_BIG_INT_MIN) goto bigint_slow_case; sp[-1] = __JS_NewShortBigInt(ctx, v - 1); break; case OP_neg: v = JS_VALUE_GET_SHORT_BIG_INT(op1); if (v == JS_SHORT_BIG_INT_MIN) { bigint_slow_case: p1 = js_bigint_set_short(&buf1, op1); goto bigint_slow_case1; } sp[-1] = __JS_NewShortBigInt(ctx, -v); break; default: abort(); } } break; case JS_TAG_BIG_INT: { JSBigInt *r; p1 = JS_VALUE_GET_PTR(op1); bigint_slow_case1: switch(op) { case OP_plus: JS_ThrowTypeError(ctx, "bigint argument with unary +"); JS_FreeValue(ctx, op1); goto exception; case OP_inc: case OP_dec: { JSBigIntBuf buf2; JSBigInt *p2; p2 = js_bigint_set_si(&buf2, 2 * (op - OP_dec) - 1); r = js_bigint_add(ctx, p1, p2, 0); } break; case OP_neg: r = js_bigint_neg(ctx, p1); break; case OP_not: r = js_bigint_not(ctx, p1); break; default: abort(); } JS_FreeValue(ctx, op1); if (!r) goto exception; sp[-1] = JS_CompactBigInt(ctx, r); } break; default: handle_float64: { double d; d = JS_VALUE_GET_FLOAT64(op1); switch(op) { case OP_inc: case OP_dec: v = 2 * (op - OP_dec) - 1; d += v; break; case OP_plus: break; case OP_neg: d = -d; break; default: abort(); } sp[-1] = js_float64(d); } break; } return 0; exception: sp[-1] = JS_UNDEFINED; return -1; } static __exception int js_post_inc_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { JSValue op1; /* XXX: allow custom operators */ op1 = sp[-1]; op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { sp[-1] = JS_UNDEFINED; return -1; } sp[-1] = op1; sp[0] = js_dup(op1); return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec); } static no_inline int js_not_slow(JSContext *ctx, JSValue *sp) { JSValue op1; op1 = sp[-1]; op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) goto exception; if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) { sp[-1] = __JS_NewShortBigInt(ctx, ~JS_VALUE_GET_SHORT_BIG_INT(op1)); } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) { JSBigInt *r; r = js_bigint_not(ctx, JS_VALUE_GET_PTR(op1)); JS_FreeValue(ctx, op1); if (!r) goto exception; sp[-1] = JS_CompactBigInt(ctx, r); } else { int32_t v1; if (unlikely(JS_ToInt32Free(ctx, &v1, op1))) goto exception; sp[-1] = js_int32(~v1); } return 0; exception: sp[-1] = JS_UNDEFINED; return -1; } static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { JSValue op1, op2; uint32_t tag1, tag2; double d1, d2; op1 = sp[-2]; op2 = sp[-1]; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); /* fast path for float operations */ if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) { d1 = JS_VALUE_GET_FLOAT64(op1); d2 = JS_VALUE_GET_FLOAT64(op2); goto handle_float64; } /* fast path for short big int operations */ if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) { js_slimb_t v1, v2; js_sdlimb_t v; v1 = JS_VALUE_GET_SHORT_BIG_INT(op1); v2 = JS_VALUE_GET_SHORT_BIG_INT(op2); switch(op) { case OP_sub: v = (js_sdlimb_t)v1 - (js_sdlimb_t)v2; break; case OP_mul: v = (js_sdlimb_t)v1 * (js_sdlimb_t)v2; break; case OP_div: if (v2 == 0 || ((js_limb_t)v1 == (js_limb_t)1 << (JS_LIMB_BITS - 1) && v2 == -1)) { goto slow_big_int; } sp[-2] = __JS_NewShortBigInt(ctx, v1 / v2); return 0; case OP_mod: if (v2 == 0 || ((js_limb_t)v1 == (js_limb_t)1 << (JS_LIMB_BITS - 1) && v2 == -1)) { goto slow_big_int; } sp[-2] = __JS_NewShortBigInt(ctx, v1 % v2); return 0; case OP_pow: goto slow_big_int; default: abort(); } if (likely(v >= JS_SHORT_BIG_INT_MIN && v <= JS_SHORT_BIG_INT_MAX)) { sp[-2] = __JS_NewShortBigInt(ctx, v); } else { JSBigInt *r = js_bigint_new_di(ctx, v); if (!r) goto exception; sp[-2] = JS_MKPTR(JS_TAG_BIG_INT, r); } return 0; } op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) { int32_t v1, v2; int64_t v; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); switch(op) { case OP_sub: v = (int64_t)v1 - (int64_t)v2; break; case OP_mul: v = (int64_t)v1 * (int64_t)v2; if (v == 0 && (v1 | v2) < 0) { sp[-2] = js_float64(-0.0); return 0; } break; case OP_div: sp[-2] = js_number((double)v1 / (double)v2); return 0; case OP_mod: if (v1 < 0 || v2 <= 0) { sp[-2] = js_number(fmod(v1, v2)); return 0; } else { v = (int64_t)v1 % (int64_t)v2; } break; case OP_pow: sp[-2] = js_number(js_math_pow(v1, v2)); return 0; default: abort(); } sp[-2] = js_int64(v); } else if ((tag1 == JS_TAG_SHORT_BIG_INT || tag1 == JS_TAG_BIG_INT) && (tag2 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT)) { JSBigInt *p1, *p2, *r; JSBigIntBuf buf1, buf2; slow_big_int: /* bigint result */ if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else p1 = JS_VALUE_GET_PTR(op1); if (JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) p2 = js_bigint_set_short(&buf2, op2); else p2 = JS_VALUE_GET_PTR(op2); switch(op) { case OP_add: r = js_bigint_add(ctx, p1, p2, 0); break; case OP_sub: r = js_bigint_add(ctx, p1, p2, 1); break; case OP_mul: r = js_bigint_mul(ctx, p1, p2); break; case OP_div: r = js_bigint_divrem(ctx, p1, p2, false); break; case OP_mod: r = js_bigint_divrem(ctx, p1, p2, true); break; case OP_pow: r = js_bigint_pow(ctx, p1, p2); break; default: abort(); } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); if (!r) goto exception; sp[-2] = JS_CompactBigInt(ctx, r); } else { double dr; /* float64 result */ if (JS_ToFloat64Free(ctx, &d1, op1)) { JS_FreeValue(ctx, op2); goto exception; } if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; handle_float64: switch(op) { case OP_sub: dr = d1 - d2; break; case OP_mul: dr = d1 * d2; break; case OP_div: dr = d1 / d2; break; case OP_mod: dr = fmod(d1, d2); break; case OP_pow: dr = js_math_pow(d1, d2); break; default: abort(); } sp[-2] = js_float64(dr); } return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) { JSValue op1, op2; uint32_t tag1, tag2; op1 = sp[-2]; op2 = sp[-1]; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); /* fast path for float64 */ if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) { double d1, d2; d1 = JS_VALUE_GET_FLOAT64(op1); d2 = JS_VALUE_GET_FLOAT64(op2); sp[-2] = js_float64(d1 + d2); return 0; } /* fast path for short bigint */ if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) { js_slimb_t v1, v2; js_sdlimb_t v; v1 = JS_VALUE_GET_SHORT_BIG_INT(op1); v2 = JS_VALUE_GET_SHORT_BIG_INT(op2); v = (js_sdlimb_t)v1 + (js_sdlimb_t)v2; if (likely(v >= JS_SHORT_BIG_INT_MIN && v <= JS_SHORT_BIG_INT_MAX)) { sp[-2] = __JS_NewShortBigInt(ctx, v); } else { JSBigInt *r = js_bigint_new_di(ctx, v); if (!r) goto exception; sp[-2] = JS_MKPTR(JS_TAG_BIG_INT, r); } return 0; } if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) { op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); } if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) { sp[-2] = JS_ConcatString(ctx, op1, op2); if (JS_IsException(sp[-2])) goto exception; return 0; } op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) { int32_t v1, v2; int64_t v; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); v = (int64_t)v1 + (int64_t)v2; sp[-2] = js_int64(v); } else if ((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) && (tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT)) { JSBigInt *p1, *p2, *r; JSBigIntBuf buf1, buf2; /* bigint result */ if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else p1 = JS_VALUE_GET_PTR(op1); if (JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) p2 = js_bigint_set_short(&buf2, op2); else p2 = JS_VALUE_GET_PTR(op2); r = js_bigint_add(ctx, p1, p2, 0); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); if (!r) goto exception; sp[-2] = JS_CompactBigInt(ctx, r); } else { double d1, d2; /* float64 result */ if (JS_ToFloat64Free(ctx, &d1, op1)) { JS_FreeValue(ctx, op2); goto exception; } if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; sp[-2] = js_float64(d1 + d2); } return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static no_inline __exception int js_binary_logic_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { JSValue op1, op2; uint32_t tag1, tag2; uint32_t v1, v2, r; op1 = sp[-2]; op2 = sp[-1]; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) { js_slimb_t v1, v2, v; js_sdlimb_t vd; v1 = JS_VALUE_GET_SHORT_BIG_INT(op1); v2 = JS_VALUE_GET_SHORT_BIG_INT(op2); /* bigint fast path */ switch(op) { case OP_and: v = v1 & v2; break; case OP_or: v = v1 | v2; break; case OP_xor: v = v1 ^ v2; break; case OP_sar: if (v2 > (JS_LIMB_BITS - 1)) { goto slow_big_int; } else if (v2 < 0) { if (v2 < -(JS_LIMB_BITS - 1)) goto slow_big_int; v2 = -v2; goto bigint_shl; } bigint_sar: v = v1 >> v2; break; case OP_shl: if (v2 > (JS_LIMB_BITS - 1)) { goto slow_big_int; } else if (v2 < 0) { if (v2 < -(JS_LIMB_BITS - 1)) goto slow_big_int; v2 = -v2; goto bigint_sar; } bigint_shl: vd = (js_dlimb_t)v1 << v2; if (likely(vd >= JS_SHORT_BIG_INT_MIN && vd <= JS_SHORT_BIG_INT_MAX)) { v = vd; } else { JSBigInt *r = js_bigint_new_di(ctx, vd); if (!r) goto exception; sp[-2] = JS_MKPTR(JS_TAG_BIG_INT, r); return 0; } break; default: abort(); } sp[-2] = __JS_NewShortBigInt(ctx, v); return 0; } op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } tag1 = JS_VALUE_GET_TAG(op1); tag2 = JS_VALUE_GET_TAG(op2); if ((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) && (tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT)) { JSBigInt *p1, *p2, *r; JSBigIntBuf buf1, buf2; slow_big_int: if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else p1 = JS_VALUE_GET_PTR(op1); if (JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) p2 = js_bigint_set_short(&buf2, op2); else p2 = JS_VALUE_GET_PTR(op2); switch(op) { case OP_and: case OP_or: case OP_xor: r = js_bigint_logic(ctx, p1, p2, op); break; case OP_shl: case OP_sar: { js_slimb_t shift; shift = js_bigint_get_si_sat(p2); if (shift > INT32_MAX) shift = INT32_MAX; else if (shift < -INT32_MAX) shift = -INT32_MAX; if (op == OP_sar) shift = -shift; if (shift >= 0) r = js_bigint_shl(ctx, p1, shift); else r = js_bigint_shr(ctx, p1, -shift); } break; default: abort(); } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); if (!r) goto exception; sp[-2] = JS_CompactBigInt(ctx, r); } else { if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) { JS_FreeValue(ctx, op2); goto exception; } if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2))) goto exception; switch(op) { case OP_shl: r = v1 << (v2 & 0x1f); break; case OP_sar: r = (int)v1 >> (v2 & 0x1f); break; case OP_and: r = v1 & v2; break; case OP_or: r = v1 | v2; break; case OP_xor: r = v1 ^ v2; break; default: abort(); } sp[-2] = js_int32(r); } return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } /* op1 must be a bigint or int. */ static JSBigInt *JS_ToBigIntBuf(JSContext *ctx, JSBigIntBuf *buf1, JSValue op1) { JSBigInt *p1; switch(JS_VALUE_GET_TAG(op1)) { case JS_TAG_INT: p1 = js_bigint_set_si(buf1, JS_VALUE_GET_INT(op1)); break; case JS_TAG_SHORT_BIG_INT: p1 = js_bigint_set_short(buf1, op1); break; case JS_TAG_BIG_INT: p1 = JS_VALUE_GET_PTR(op1); break; default: abort(); } return p1; } /* op1 and op2 must be numeric types and at least one must be a bigint. No exception is generated. */ static int js_compare_bigint(JSContext *ctx, OPCodeEnum op, JSValue op1, JSValue op2) { int res, val, tag1, tag2; JSBigIntBuf buf1, buf2; JSBigInt *p1, *p2; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if ((tag1 == JS_TAG_SHORT_BIG_INT || tag1 == JS_TAG_INT) && (tag2 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_INT)) { /* fast path */ js_slimb_t v1, v2; if (tag1 == JS_TAG_INT) v1 = JS_VALUE_GET_INT(op1); else v1 = JS_VALUE_GET_SHORT_BIG_INT(op1); if (tag2 == JS_TAG_INT) v2 = JS_VALUE_GET_INT(op2); else v2 = JS_VALUE_GET_SHORT_BIG_INT(op2); val = (v1 > v2) - (v1 < v2); } else { if (tag1 == JS_TAG_FLOAT64) { p2 = JS_ToBigIntBuf(ctx, &buf2, op2); val = js_bigint_float64_cmp(ctx, p2, JS_VALUE_GET_FLOAT64(op1)); if (val == 2) goto unordered; val = -val; } else if (tag2 == JS_TAG_FLOAT64) { p1 = JS_ToBigIntBuf(ctx, &buf1, op1); val = js_bigint_float64_cmp(ctx, p1, JS_VALUE_GET_FLOAT64(op2)); if (val == 2) { unordered: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); return false; } } else { p1 = JS_ToBigIntBuf(ctx, &buf1, op1); p2 = JS_ToBigIntBuf(ctx, &buf2, op2); val = js_bigint_cmp(ctx, p1, p2); } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); } switch(op) { case OP_lt: res = val < 0; break; case OP_lte: res = val <= 0; break; case OP_gt: res = val > 0; break; case OP_gte: res = val >= 0; break; case OP_eq: res = val == 0; break; default: abort(); } return res; } static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { JSValue op1, op2; int res; uint32_t tag1, tag2; op1 = sp[-2]; op2 = sp[-1]; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { JSString *p1, *p2; p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); res = js_string_compare(p1, p2); switch(op) { case OP_lt: res = (res < 0); break; case OP_lte: res = (res <= 0); break; case OP_gt: res = (res > 0); break; default: case OP_gte: res = (res >= 0); break; } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) && (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) { /* fast path for float64/int */ goto float64_compare; } else { if ((((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) && tag2 == JS_TAG_STRING) || ((tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) && tag1 == JS_TAG_STRING))) { if (tag1 == JS_TAG_STRING) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op1) != JS_TAG_SHORT_BIG_INT) goto invalid_bigint_string; } if (tag2 == JS_TAG_STRING) { op2 = JS_StringToBigInt(ctx, op2); if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op2) != JS_TAG_SHORT_BIG_INT) { invalid_bigint_string: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); res = false; goto done; } } } else { op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } } tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) { res = js_compare_bigint(ctx, op, op1, op2); } else { double d1, d2; float64_compare: /* can use floating point comparison */ if (tag1 == JS_TAG_FLOAT64) { d1 = JS_VALUE_GET_FLOAT64(op1); } else { d1 = JS_VALUE_GET_INT(op1); } if (tag2 == JS_TAG_FLOAT64) { d2 = JS_VALUE_GET_FLOAT64(op2); } else { d2 = JS_VALUE_GET_INT(op2); } switch(op) { case OP_lt: res = (d1 < d2); /* if NaN return false */ break; case OP_lte: res = (d1 <= d2); /* if NaN return false */ break; case OP_gt: res = (d1 > d2); /* if NaN return false */ break; default: case OP_gte: res = (d1 >= d2); /* if NaN return false */ break; } } } done: sp[-2] = js_bool(res); return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static bool tag_is_number(uint32_t tag) { return (tag == JS_TAG_INT || tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT); } static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, bool is_neq) { JSValue op1, op2; int res; uint32_t tag1, tag2; op1 = sp[-2]; op2 = sp[-1]; redo: tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if (tag_is_number(tag1) && tag_is_number(tag2)) { if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) { res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2); } else if ((tag1 == JS_TAG_FLOAT64 && (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64)) || (tag2 == JS_TAG_FLOAT64 && (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64))) { double d1, d2; if (tag1 == JS_TAG_FLOAT64) { d1 = JS_VALUE_GET_FLOAT64(op1); } else { d1 = JS_VALUE_GET_INT(op1); } if (tag2 == JS_TAG_FLOAT64) { d2 = JS_VALUE_GET_FLOAT64(op2); } else { d2 = JS_VALUE_GET_INT(op2); } res = (d1 == d2); } else { res = js_compare_bigint(ctx, OP_eq, op1, op2); if (res < 0) goto exception; } } else if (tag1 == tag2) { res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) || (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) { res = true; } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) || (tag2 == JS_TAG_STRING && tag_is_number(tag1))) { if (tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) { if (tag1 == JS_TAG_STRING) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op1) != JS_TAG_SHORT_BIG_INT) goto invalid_bigint_string; } if (tag2 == JS_TAG_STRING) { op2 = JS_StringToBigInt(ctx, op2); if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op2) != JS_TAG_SHORT_BIG_INT ) { invalid_bigint_string: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); res = false; goto done; } } } else { op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } } res = js_strict_eq(ctx, op1, op2); } else if (tag1 == JS_TAG_BOOL) { op1 = js_int32(JS_VALUE_GET_INT(op1)); goto redo; } else if (tag2 == JS_TAG_BOOL) { op2 = js_int32(JS_VALUE_GET_INT(op2)); goto redo; } else if ((tag1 == JS_TAG_OBJECT && (tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) || (tag2 == JS_TAG_OBJECT && (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) { op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } goto redo; } else { /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */ if ((JS_IsHTMLDDA(ctx, op1) && (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) || (JS_IsHTMLDDA(ctx, op2) && (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) { res = true; } else { res = false; } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); } done: sp[-2] = js_bool(res ^ is_neq); return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) { JSValue op1, op2; uint32_t v1, v2, r; op1 = sp[-2]; op2 = sp[-1]; op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); goto exception; } op2 = JS_ToNumericFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); goto exception; } if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT || JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT || JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT || JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) { JS_ThrowTypeError(ctx, "BigInt operands are forbidden for >>>"); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); goto exception; } /* cannot give an exception */ JS_ToUint32Free(ctx, &v1, op1); JS_ToUint32Free(ctx, &v2, op2); r = v1 >> (v2 & 0x1f); sp[-2] = js_uint32(r); return 0; exception: sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode) { bool res; int tag1, tag2; double d1, d2; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); switch(tag1) { case JS_TAG_BOOL: if (tag1 != tag2) { res = false; } else { res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2); goto done_no_free; } break; case JS_TAG_NULL: case JS_TAG_UNDEFINED: res = (tag1 == tag2); break; case JS_TAG_STRING: { JSString *p1, *p2; if (tag1 != tag2) { res = false; } else { p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); res = js_string_eq(p1, p2); } } break; case JS_TAG_SYMBOL: { JSAtomStruct *p1, *p2; if (tag1 != tag2) { res = false; } else { p1 = JS_VALUE_GET_PTR(op1); p2 = JS_VALUE_GET_PTR(op2); res = (p1 == p2); } } break; case JS_TAG_OBJECT: if (tag1 != tag2) res = false; else res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2); break; case JS_TAG_INT: d1 = JS_VALUE_GET_INT(op1); if (tag2 == JS_TAG_INT) { d2 = JS_VALUE_GET_INT(op2); goto number_test; } else if (tag2 == JS_TAG_FLOAT64) { d2 = JS_VALUE_GET_FLOAT64(op2); goto number_test; } else { res = false; } break; case JS_TAG_FLOAT64: d1 = JS_VALUE_GET_FLOAT64(op1); if (tag2 == JS_TAG_FLOAT64) { d2 = JS_VALUE_GET_FLOAT64(op2); } else if (tag2 == JS_TAG_INT) { d2 = JS_VALUE_GET_INT(op2); } else { res = false; break; } number_test: if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) { JSFloat64Union u1, u2; /* NaN is not always normalized, so this test is necessary */ if (isnan(d1) || isnan(d2)) { res = isnan(d1) == isnan(d2); } else if (eq_mode == JS_EQ_SAME_VALUE_ZERO) { res = (d1 == d2); /* +0 == -0 */ } else { u1.d = d1; u2.d = d2; res = (u1.u64 == u2.u64); /* +0 != -0 */ } } else { res = (d1 == d2); /* if NaN return false and +0 == -0 */ } goto done_no_free; case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: { JSBigIntBuf buf1, buf2; JSBigInt *p1, *p2; if (tag2 != JS_TAG_SHORT_BIG_INT && tag2 != JS_TAG_BIG_INT) { res = false; break; } if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else p1 = JS_VALUE_GET_PTR(op1); if (JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) p2 = js_bigint_set_short(&buf2, op2); else p2 = JS_VALUE_GET_PTR(op2); res = (js_bigint_cmp(ctx, p1, p2) == 0); } break; default: res = false; break; } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); done_no_free: return res; } static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2) { return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) { return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE); } static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) { return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE_ZERO); } static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, bool is_neq) { bool res; res = js_strict_eq(ctx, sp[-2], sp[-1]); sp[-2] = js_bool(res ^ is_neq); return 0; } static __exception int js_operator_in(JSContext *ctx, JSValue *sp) { JSValue op1, op2; JSAtom atom; int ret; op1 = sp[-2]; op2 = sp[-1]; if (JS_VALUE_GET_TAG(op2) != JS_TAG_OBJECT) { JS_ThrowTypeError(ctx, "invalid 'in' operand"); return -1; } atom = JS_ValueToAtom(ctx, op1); if (unlikely(atom == JS_ATOM_NULL)) return -1; ret = JS_HasProperty(ctx, op2, atom); JS_FreeAtom(ctx, atom); if (ret < 0) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); sp[-2] = js_bool(ret); return 0; } static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp) { JSValue op1, op2; int ret; op1 = sp[-2]; /* object */ op2 = sp[-1]; /* field name or method function */ if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) { JS_ThrowTypeError(ctx, "invalid 'in' operand"); return -1; } if (JS_IsObject(op2)) { /* method: use the brand */ ret = JS_CheckBrand(ctx, op1, op2); if (ret < 0) return -1; } else { JSAtom atom; JSObject *p; JSShapeProperty *prs; JSProperty *pr; /* field */ atom = JS_ValueToAtom(ctx, op2); if (unlikely(atom == JS_ATOM_NULL)) return -1; p = JS_VALUE_GET_OBJ(op1); prs = find_own_property(&pr, p, atom); JS_FreeAtom(ctx, atom); ret = (prs != NULL); } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); sp[-2] = js_bool(ret); return 0; } static __exception int js_has_unscopable(JSContext *ctx, JSValue obj, JSAtom atom) { JSValue arr, val; int ret; arr = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_unscopables); if (JS_IsException(arr)) return -1; ret = 0; if (JS_IsObject(arr)) { val = JS_GetProperty(ctx, arr, atom); ret = JS_ToBoolFree(ctx, val); } JS_FreeValue(ctx, arr); return ret; } static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) { JSValue op1, op2; int ret; op1 = sp[-2]; op2 = sp[-1]; ret = JS_IsInstanceOf(ctx, op1, op2); if (ret < 0) return ret; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); sp[-2] = js_bool(ret); return 0; } static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) { JSAtom atom; uint32_t tag; tag = JS_VALUE_GET_NORM_TAG(op1); switch(tag) { case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: atom = JS_ATOM_bigint; break; case JS_TAG_INT: case JS_TAG_FLOAT64: atom = JS_ATOM_number; break; case JS_TAG_UNDEFINED: atom = JS_ATOM_undefined; break; case JS_TAG_BOOL: atom = JS_ATOM_boolean; break; case JS_TAG_STRING: atom = JS_ATOM_string; break; case JS_TAG_OBJECT: { JSObject *p; p = JS_VALUE_GET_OBJ(op1); if (unlikely(p->is_HTMLDDA)) atom = JS_ATOM_undefined; else if (JS_IsFunction(ctx, op1)) atom = JS_ATOM_function; else goto obj_type; } break; case JS_TAG_NULL: obj_type: atom = JS_ATOM_object; break; case JS_TAG_SYMBOL: atom = JS_ATOM_symbol; break; default: atom = JS_ATOM_unknown; break; } return atom; } static __exception int js_operator_delete(JSContext *ctx, JSValue *sp) { JSValue op1, op2; JSAtom atom; int ret; op1 = sp[-2]; op2 = sp[-1]; atom = JS_ValueToAtom(ctx, op2); if (unlikely(atom == JS_ATOM_NULL)) return -1; ret = JS_DeleteProperty(ctx, op1, atom, JS_PROP_THROW_STRICT); JS_FreeAtom(ctx, atom); if (unlikely(ret < 0)) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); sp[-2] = js_bool(ret); return 0; } static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); if (!b || b->is_strict_mode || !b->has_prototype) { return JS_ThrowTypeError(ctx, "invalid property access"); } return JS_UNDEFINED; } static JSValue js_function_proto_fileName(JSContext *ctx, JSValueConst this_val) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); if (b) { return JS_AtomToString(ctx, b->filename); } return JS_UNDEFINED; } static JSValue js_function_proto_int32(JSContext *ctx, JSValueConst this_val, int magic) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); if (b) { int *field = (int *) ((char *)b + magic); return js_int32(*field); } return JS_UNDEFINED; } static int js_arguments_define_own_property(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags) { JSObject *p; uint32_t idx; p = JS_VALUE_GET_OBJ(this_obj); /* convert to normal array when redefining an existing numeric field */ if (p->fast_array && JS_AtomIsArrayIndex(ctx, &idx, prop) && idx < p->u.array.count) { if (convert_fast_array_to_array(ctx, p)) return -1; } /* run the default define own property */ return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, flags | JS_PROP_NO_EXOTIC); } static const JSClassExoticMethods js_arguments_exotic_methods = { .define_own_property = js_arguments_define_own_property, }; static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) { JSValue val, *tab; JSProperty *pr; JSObject *p; int i; val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_ARGUMENTS); if (JS_IsException(val)) return val; p = JS_VALUE_GET_OBJ(val); /* add the length field (cannot fail) */ pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (!pr) { JS_FreeValue(ctx, val); return JS_EXCEPTION; } pr->u.value = js_int32(argc); /* initialize the fast array part */ tab = NULL; if (argc > 0) { tab = js_malloc(ctx, sizeof(tab[0]) * argc); if (!tab) { JS_FreeValue(ctx, val); return JS_EXCEPTION; } for(i = 0; i < argc; i++) { tab[i] = js_dup(argv[i]); } } p->u.array.u.values = tab; p->u.array.count = argc; JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, js_dup(ctx->array_proto_values), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); /* add callee property to throw a TypeError in strict mode */ JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED, ctx->throw_type_error, ctx->throw_type_error, JS_PROP_HAS_GET | JS_PROP_HAS_SET); return val; } #define GLOBAL_VAR_OFFSET 0x40000000 #define ARGUMENT_VAR_OFFSET 0x20000000 /* legacy arguments object: add references to the function arguments */ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, JSValueConst *argv, JSStackFrame *sf, int arg_count) { JSValue val; JSProperty *pr; JSObject *p; int i; val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_MAPPED_ARGUMENTS); if (JS_IsException(val)) return val; p = JS_VALUE_GET_OBJ(val); /* add the length field (cannot fail) */ pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (!pr) goto fail; pr->u.value = js_int32(argc); for(i = 0; i < arg_count; i++) { JSVarRef *var_ref; var_ref = get_var_ref(ctx, sf, i, true); if (!var_ref) goto fail; pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); if (!pr) { free_var_ref(ctx->rt, var_ref); goto fail; } pr->u.var_ref = var_ref; } /* the arguments not mapped to the arguments of the function can be normal properties */ for(i = arg_count; i < argc; i++) { if (JS_DefinePropertyValueUint32(ctx, val, i, js_dup(argv[i]), JS_PROP_C_W_E) < 0) goto fail; } JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, js_dup(ctx->array_proto_values), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); /* callee returns this function in non strict mode */ JS_DefinePropertyValue(ctx, val, JS_ATOM_callee, js_dup(ctx->rt->current_stack_frame->cur_func), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); return val; fail: JS_FreeValue(ctx, val); return JS_EXCEPTION; } static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) { JSObject *p; JSPropertyEnum *tab_atom; int i; JSValue enum_obj, obj1; JSForInIterator *it; uint32_t tag, tab_atom_count; tag = JS_VALUE_GET_TAG(obj); if (tag != JS_TAG_OBJECT && tag != JS_TAG_NULL && tag != JS_TAG_UNDEFINED) { obj = JS_ToObjectFree(ctx, obj); } it = js_malloc(ctx, sizeof(*it)); if (!it) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } enum_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_FOR_IN_ITERATOR); if (JS_IsException(enum_obj)) { js_free(ctx, it); JS_FreeValue(ctx, obj); return JS_EXCEPTION; } it->is_array = false; it->obj = obj; it->idx = 0; p = JS_VALUE_GET_OBJ(enum_obj); p->u.for_in_iterator = it; if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) return enum_obj; /* fast path: assume no enumerable properties in the prototype chain */ obj1 = js_dup(obj); for(;;) { obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsNull(obj1)) break; if (JS_IsException(obj1)) goto fail; if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, JS_VALUE_GET_OBJ(obj1), JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) { JS_FreeValue(ctx, obj1); goto fail; } js_free_prop_enum(ctx, tab_atom, tab_atom_count); if (tab_atom_count != 0) { JS_FreeValue(ctx, obj1); goto slow_path; } /* must check for timeout to avoid infinite loop */ if (js_poll_interrupts(ctx)) { JS_FreeValue(ctx, obj1); goto fail; } } p = JS_VALUE_GET_OBJ(obj); if (p->fast_array) { JSShape *sh; JSShapeProperty *prs; /* check that there are no enumerable normal fields */ sh = p->shape; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->flags & JS_PROP_ENUMERABLE) goto normal_case; } /* for fast arrays, we only store the number of elements */ it->is_array = true; it->array_length = p->u.array.count; } else { normal_case: if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) goto fail; for(i = 0; i < tab_atom_count; i++) { JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0); } js_free_prop_enum(ctx, tab_atom, tab_atom_count); } return enum_obj; slow_path: /* non enumerable properties hide the enumerables ones in the prototype chain */ obj1 = js_dup(obj); for(;;) { if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, JS_VALUE_GET_OBJ(obj1), JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { JS_FreeValue(ctx, obj1); goto fail; } for(i = 0; i < tab_atom_count; i++) { JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL, (tab_atom[i].is_enumerable ? JS_PROP_ENUMERABLE : 0)); } js_free_prop_enum(ctx, tab_atom, tab_atom_count); obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsNull(obj1)) break; if (JS_IsException(obj1)) goto fail; /* must check for timeout to avoid infinite loop */ if (js_poll_interrupts(ctx)) { JS_FreeValue(ctx, obj1); goto fail; } } return enum_obj; fail: JS_FreeValue(ctx, enum_obj); return JS_EXCEPTION; } /* obj -> enum_obj */ static __exception int js_for_in_start(JSContext *ctx, JSValue *sp) { sp[-1] = build_for_in_iterator(ctx, sp[-1]); if (JS_IsException(sp[-1])) return -1; return 0; } /* enum_obj -> enum_obj value done */ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) { JSValue enum_obj; JSObject *p; JSAtom prop; JSForInIterator *it; int ret; enum_obj = sp[-1]; /* fail safe */ if (JS_VALUE_GET_TAG(enum_obj) != JS_TAG_OBJECT) goto done; p = JS_VALUE_GET_OBJ(enum_obj); if (p->class_id != JS_CLASS_FOR_IN_ITERATOR) goto done; it = p->u.for_in_iterator; for(;;) { if (it->is_array) { if (it->idx >= it->array_length) goto done; prop = __JS_AtomFromUInt32(it->idx); it->idx++; } else { JSShape *sh = p->shape; JSShapeProperty *prs; if (it->idx >= sh->prop_count) goto done; prs = get_shape_prop(sh) + it->idx; prop = prs->atom; it->idx++; if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE)) continue; } // check if the property was deleted unless we're dealing with a proxy JSValue obj = it->obj; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_PROXY) break; } ret = JS_HasProperty(ctx, obj, prop); if (ret < 0) return ret; if (ret) break; } /* return the property */ sp[0] = JS_AtomToValue(ctx, prop); sp[1] = JS_FALSE; return 0; done: /* return the end */ sp[0] = JS_UNDEFINED; sp[1] = JS_TRUE; return 0; } static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj, JSValueConst method) { JSValue enum_obj; enum_obj = JS_Call(ctx, method, obj, 0, NULL); if (JS_IsException(enum_obj)) return enum_obj; if (!JS_IsObject(enum_obj)) { JS_FreeValue(ctx, enum_obj); return JS_ThrowTypeErrorNotAnObject(ctx); } return enum_obj; } static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, bool is_async) { JSValue method, ret, sync_iter; if (is_async) { method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_asyncIterator); if (JS_IsException(method)) return method; if (JS_IsUndefined(method) || JS_IsNull(method)) { method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); if (JS_IsException(method)) return method; sync_iter = JS_GetIterator2(ctx, obj, method); JS_FreeValue(ctx, method); if (JS_IsException(sync_iter)) return sync_iter; ret = JS_CreateAsyncFromSyncIterator(ctx, sync_iter); JS_FreeValue(ctx, sync_iter); return ret; } } else { method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); if (JS_IsException(method)) return method; } if (!JS_IsFunction(ctx, method)) { JS_FreeValue(ctx, method); return JS_ThrowTypeError(ctx, "value is not iterable"); } ret = JS_GetIterator2(ctx, obj, method); JS_FreeValue(ctx, method); return ret; } /* return *pdone = 2 if the iterator object is not parsed */ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj, JSValueConst method, int argc, JSValueConst *argv, int *pdone) { JSValue obj; /* fast path for the built-in iterators (avoid creating the intermediate result object) */ if (JS_IsObject(method)) { JSObject *p = JS_VALUE_GET_OBJ(method); if (p->class_id == JS_CLASS_C_FUNCTION && p->u.cfunc.cproto == JS_CFUNC_iterator_next) { JSCFunctionType func; JSValueConst args[1]; /* in case the function expects one argument */ if (argc == 0) { args[0] = JS_UNDEFINED; argv = args; } func = p->u.cfunc.c_function; return func.iterator_next(ctx, enum_obj, argc, argv, pdone, p->u.cfunc.magic); } } obj = JS_Call(ctx, method, enum_obj, argc, argv); if (JS_IsException(obj)) goto fail; if (!JS_IsObject(obj)) { JS_FreeValue(ctx, obj); JS_ThrowTypeError(ctx, "iterator must return an object"); goto fail; } *pdone = 2; return obj; fail: *pdone = false; return JS_EXCEPTION; } static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, JSValueConst method, int argc, JSValueConst *argv, int *pdone) { JSValue obj, value, done_val; int done; obj = JS_IteratorNext2(ctx, enum_obj, method, argc, argv, &done); if (JS_IsException(obj)) goto fail; if (likely(done == 0)) { *pdone = false; return obj; } else if (done != 2) { JS_FreeValue(ctx, obj); *pdone = true; return JS_UNDEFINED; } else { done_val = JS_GetProperty(ctx, obj, JS_ATOM_done); if (JS_IsException(done_val)) goto fail; *pdone = JS_ToBoolFree(ctx, done_val); value = JS_UNDEFINED; if (!*pdone) { value = JS_GetProperty(ctx, obj, JS_ATOM_value); } JS_FreeValue(ctx, obj); return value; } fail: JS_FreeValue(ctx, obj); *pdone = false; return JS_EXCEPTION; } /* return < 0 in case of exception */ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj, bool is_exception_pending) { JSValue method, ret, ex_obj; int res; if (is_exception_pending) { ex_obj = ctx->rt->current_exception; ctx->rt->current_exception = JS_UNINITIALIZED; res = -1; } else { ex_obj = JS_UNDEFINED; res = 0; } method = JS_GetProperty(ctx, enum_obj, JS_ATOM_return); if (JS_IsException(method)) { res = -1; goto done; } if (JS_IsUndefined(method) || JS_IsNull(method)) { goto done; } ret = JS_CallFree(ctx, method, enum_obj, 0, NULL); if (!is_exception_pending) { if (JS_IsException(ret)) { res = -1; } else if (!JS_IsObject(ret)) { JS_ThrowTypeErrorNotAnObject(ctx); res = -1; } } JS_FreeValue(ctx, ret); done: if (is_exception_pending) { JS_Throw(ctx, ex_obj); } return res; } /* obj -> enum_rec (3 slots) */ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp, bool is_async) { JSValue op1, obj, method; op1 = sp[-1]; obj = JS_GetIterator(ctx, op1, is_async); if (JS_IsException(obj)) return -1; JS_FreeValue(ctx, op1); sp[-1] = obj; method = JS_GetProperty(ctx, obj, JS_ATOM_next); if (JS_IsException(method)) return -1; sp[0] = method; return 0; } /* enum_rec [objs] -> enum_rec [objs] value done. There are 'offset' objs. If 'done' is true or in case of exception, 'enum_rec' is set to undefined. If 'done' is true, 'value' is always set to undefined. */ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset) { JSValue value = JS_UNDEFINED; int done = 1; if (likely(!JS_IsUndefined(sp[offset]))) { value = JS_IteratorNext(ctx, sp[offset], sp[offset + 1], 0, NULL, &done); if (JS_IsException(value)) done = -1; if (done) { /* value is JS_UNDEFINED or JS_EXCEPTION */ /* replace the iteration object with undefined */ JS_FreeValue(ctx, sp[offset]); sp[offset] = JS_UNDEFINED; if (done < 0) { return -1; } else { JS_FreeValue(ctx, value); value = JS_UNDEFINED; } } } sp[0] = value; sp[1] = js_bool(done); return 0; } static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj, int *pdone) { JSValue done_val, value; int done; done_val = JS_GetProperty(ctx, obj, JS_ATOM_done); if (JS_IsException(done_val)) goto fail; done = JS_ToBoolFree(ctx, done_val); value = JS_GetProperty(ctx, obj, JS_ATOM_value); if (JS_IsException(value)) goto fail; *pdone = done; return value; fail: *pdone = false; return JS_EXCEPTION; } static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) { JSValue obj, value; int done; obj = sp[-1]; if (!JS_IsObject(obj)) { JS_ThrowTypeError(ctx, "iterator must return an object"); return -1; } value = JS_IteratorGetCompleteValue(ctx, obj, &done); if (JS_IsException(value)) return -1; JS_FreeValue(ctx, obj); sp[-1] = value; sp[0] = js_bool(done); return 0; } static JSValue js_create_iterator_result(JSContext *ctx, JSValue val, bool done) { JSValue obj; obj = JS_NewObject(ctx); if (JS_IsException(obj)) { JS_FreeValue(ctx, val); return obj; } if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_value, val, JS_PROP_C_W_E) < 0) { goto fail; } if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done, js_bool(done), JS_PROP_C_W_E) < 0) { fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } return obj; } static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int *pdone, int magic); static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static bool js_is_fast_array(JSContext *ctx, JSValue obj) { /* Try and handle fast arrays explicitly */ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_ARRAY && p->fast_array) { return true; } } return false; } /* Access an Array's internal JSValue array if available */ static bool js_get_fast_array(JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp) { /* Try and handle fast arrays explicitly */ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_ARRAY && p->fast_array) { *countp = p->u.array.count; *arrpp = p->u.array.u.values; return true; } } return false; } static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) { JSValue iterator, enumobj, method, value; int is_array_iterator; JSValue *arrp; uint32_t i, count32, pos; if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) { JS_ThrowInternalError(ctx, "invalid index for append"); return -1; } pos = JS_VALUE_GET_INT(sp[-2]); /* XXX: further optimisations: - use ctx->array_proto_values? - check if array_iterator_prototype next method is built-in and avoid constructing actual iterator object? - build this into js_for_of_start and use in all `for (x of o)` loops */ iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator); if (JS_IsException(iterator)) return -1; /* Used to squelch a -Wcast-function-type warning. */ JSCFunctionType ft = { .generic_magic = js_create_array_iterator }; is_array_iterator = JS_IsCFunction(ctx, iterator, ft.generic, JS_ITERATOR_KIND_VALUE); JS_FreeValue(ctx, iterator); enumobj = JS_GetIterator(ctx, sp[-1], false); if (JS_IsException(enumobj)) return -1; method = JS_GetProperty(ctx, enumobj, JS_ATOM_next); if (JS_IsException(method)) { JS_FreeValue(ctx, enumobj); return -1; } /* Used to squelch a -Wcast-function-type warning. */ JSCFunctionType ft2 = { .iterator_next = js_array_iterator_next }; if (is_array_iterator && JS_IsCFunction(ctx, method, ft2.generic, 0) && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) { uint32_t len; if (js_get_length32(ctx, &len, sp[-1])) goto exception; /* if len > count32, the elements >= count32 might be read in the prototypes and might have side effects */ if (len != count32) goto general_case; /* Handle fast arrays explicitly */ for (i = 0; i < count32; i++) { if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, js_dup(arrp[i]), JS_PROP_C_W_E) < 0) goto exception; } } else { general_case: for (;;) { int done; value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done); if (JS_IsException(value)) goto exception; if (done) { /* value is JS_UNDEFINED */ break; } if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, value, JS_PROP_C_W_E) < 0) goto exception; } } /* Note: could raise an error if too many elements */ sp[-2] = js_int32(pos); JS_FreeValue(ctx, enumobj); JS_FreeValue(ctx, method); return 0; exception: JS_IteratorClose(ctx, enumobj, true); JS_FreeValue(ctx, enumobj); JS_FreeValue(ctx, method); return -1; } static __exception int JS_CopyDataProperties(JSContext *ctx, JSValue target, JSValue source, JSValue excluded, bool setprop) { JSPropertyEnum *tab_atom; JSValue val; uint32_t i, tab_atom_count; JSObject *p; JSObject *pexcl = NULL; int ret, gpn_flags; JSPropertyDescriptor desc; bool is_enumerable; if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT) return 0; if (JS_VALUE_GET_TAG(excluded) == JS_TAG_OBJECT) pexcl = JS_VALUE_GET_OBJ(excluded); p = JS_VALUE_GET_OBJ(source); gpn_flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY; if (p->is_exotic) { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; /* cannot use JS_GPN_ENUM_ONLY with e.g. proxies because it introduces a visible change */ if (em && em->get_own_property_names) { gpn_flags &= ~JS_GPN_ENUM_ONLY; } } if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, gpn_flags)) return -1; for (i = 0; i < tab_atom_count; i++) { if (pexcl) { ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom); if (ret) { if (ret < 0) goto exception; continue; } } if (!(gpn_flags & JS_GPN_ENUM_ONLY)) { /* test if the property is enumerable */ ret = JS_GetOwnPropertyInternal(ctx, &desc, p, tab_atom[i].atom); if (ret < 0) goto exception; if (!ret) continue; is_enumerable = (desc.flags & JS_PROP_ENUMERABLE) != 0; js_free_desc(ctx, &desc); if (!is_enumerable) continue; } val = JS_GetProperty(ctx, source, tab_atom[i].atom); if (JS_IsException(val)) goto exception; if (setprop) ret = JS_SetProperty(ctx, target, tab_atom[i].atom, val); else ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val, JS_PROP_C_W_E); if (ret < 0) goto exception; } js_free_prop_enum(ctx, tab_atom, tab_atom_count); return 0; exception: js_free_prop_enum(ctx, tab_atom, tab_atom_count); return -1; } /* only valid inside C functions */ static JSValueConst JS_GetActiveFunction(JSContext *ctx) { return ctx->rt->current_stack_frame->cur_func; } static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, bool is_arg) { JSVarRef *var_ref; struct list_head *el; JSValue *pvalue; if (is_arg) pvalue = &sf->arg_buf[var_idx]; else pvalue = &sf->var_buf[var_idx]; list_for_each(el, &sf->var_ref_list) { var_ref = list_entry(el, JSVarRef, header.link); if (var_ref->pvalue == pvalue) { var_ref->header.ref_count++; return var_ref; } } /* create a new one */ var_ref = js_malloc(ctx, sizeof(JSVarRef)); if (!var_ref) return NULL; var_ref->header.ref_count = 1; var_ref->is_detached = false; list_add_tail(&var_ref->header.link, &sf->var_ref_list); var_ref->pvalue = pvalue; var_ref->value = JS_UNDEFINED; return var_ref; } static JSValue js_closure2(JSContext *ctx, JSValue func_obj, JSFunctionBytecode *b, JSVarRef **cur_var_refs, JSStackFrame *sf) { JSObject *p; JSVarRef **var_refs; int i; p = JS_VALUE_GET_OBJ(func_obj); p->u.func.function_bytecode = b; p->u.func.home_object = NULL; p->u.func.var_refs = NULL; if (b->closure_var_count) { var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count); if (!var_refs) goto fail; p->u.func.var_refs = var_refs; for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; JSVarRef *var_ref; if (cv->is_local) { /* reuse the existing variable reference if it already exists */ var_ref = get_var_ref(ctx, sf, cv->var_idx, cv->is_arg); if (!var_ref) goto fail; } else { var_ref = cur_var_refs[cv->var_idx]; var_ref->header.ref_count++; } var_refs[i] = var_ref; } } return func_obj; fail: /* bfunc is freed when func_obj is freed */ JS_FreeValue(ctx, func_obj); return JS_EXCEPTION; } static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { JSValue obj, this_val; int ret; this_val = JS_MKPTR(JS_TAG_OBJECT, p); obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor, js_dup(this_val), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (ret < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } return obj; } static const uint16_t func_kind_to_class_id[] = { [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION, [JS_FUNC_GENERATOR] = JS_CLASS_GENERATOR_FUNCTION, [JS_FUNC_ASYNC] = JS_CLASS_ASYNC_FUNCTION, [JS_FUNC_ASYNC_GENERATOR] = JS_CLASS_ASYNC_GENERATOR_FUNCTION, }; static JSValue js_closure(JSContext *ctx, JSValue bfunc, JSVarRef **cur_var_refs, JSStackFrame *sf) { JSFunctionBytecode *b; JSValue func_obj; JSAtom name_atom; b = JS_VALUE_GET_PTR(bfunc); func_obj = JS_NewObjectClass(ctx, func_kind_to_class_id[b->func_kind]); if (JS_IsException(func_obj)) { JS_FreeValue(ctx, bfunc); return JS_EXCEPTION; } func_obj = js_closure2(ctx, func_obj, b, cur_var_refs, sf); if (JS_IsException(func_obj)) { /* bfunc has been freed */ goto fail; } name_atom = b->func_name; if (name_atom == JS_ATOM_NULL) name_atom = JS_ATOM_empty_string; js_function_set_properties(ctx, func_obj, name_atom, b->defined_arg_count); if (b->func_kind & JS_FUNC_GENERATOR) { JSValue proto; int proto_class_id; /* generators have a prototype field which is used as prototype for the generator object */ if (b->func_kind == JS_FUNC_ASYNC_GENERATOR) proto_class_id = JS_CLASS_ASYNC_GENERATOR; else proto_class_id = JS_CLASS_GENERATOR; proto = JS_NewObjectProto(ctx, ctx->class_proto[proto_class_id]); if (JS_IsException(proto)) goto fail; JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, proto, JS_PROP_WRITABLE); } else if (b->has_prototype) { /* add the 'prototype' property: delay instantiation to avoid creating cycles for every javascript function. The prototype object is created on the fly when first accessed */ JS_SetConstructorBit(ctx, func_obj, true); JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype, JS_AUTOINIT_ID_PROTOTYPE, NULL, JS_PROP_WRITABLE); } return func_obj; fail: /* bfunc is freed when func_obj is freed */ JS_FreeValue(ctx, func_obj); return JS_EXCEPTION; } #define JS_DEFINE_CLASS_HAS_HERITAGE (1 << 0) static int js_op_define_class(JSContext *ctx, JSValue *sp, JSAtom class_name, int class_flags, JSVarRef **cur_var_refs, JSStackFrame *sf, bool is_computed_name) { JSValue bfunc, parent_class, proto = JS_UNDEFINED; JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED; JSFunctionBytecode *b; parent_class = sp[-2]; bfunc = sp[-1]; if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE) { if (JS_IsNull(parent_class)) { parent_proto = JS_NULL; parent_class = js_dup(ctx->function_proto); } else { if (!JS_IsConstructor(ctx, parent_class)) { JS_ThrowTypeError(ctx, "parent class must be constructor"); goto fail; } parent_proto = JS_GetProperty(ctx, parent_class, JS_ATOM_prototype); if (JS_IsException(parent_proto)) goto fail; if (!JS_IsNull(parent_proto) && !JS_IsObject(parent_proto)) { JS_ThrowTypeError(ctx, "parent prototype must be an object or null"); goto fail; } } } else { /* parent_class is JS_UNDEFINED in this case */ parent_proto = js_dup(ctx->class_proto[JS_CLASS_OBJECT]); parent_class = js_dup(ctx->function_proto); } proto = JS_NewObjectProto(ctx, parent_proto); if (JS_IsException(proto)) goto fail; b = JS_VALUE_GET_PTR(bfunc); assert(b->func_kind == JS_FUNC_NORMAL); ctor = JS_NewObjectProtoClass(ctx, parent_class, JS_CLASS_BYTECODE_FUNCTION); if (JS_IsException(ctor)) goto fail; ctor = js_closure2(ctx, ctor, b, cur_var_refs, sf); bfunc = JS_UNDEFINED; if (JS_IsException(ctor)) goto fail; js_method_set_home_object(ctx, ctor, proto); JS_SetConstructorBit(ctx, ctor, true); JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length, js_int32(b->defined_arg_count), JS_PROP_CONFIGURABLE); if (is_computed_name) { if (JS_DefineObjectNameComputed(ctx, ctor, sp[-3], JS_PROP_CONFIGURABLE) < 0) goto fail; } else { if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0) goto fail; } /* the constructor property must be first. It can be overriden by computed property names */ if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, js_dup(ctor), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_THROW) < 0) goto fail; /* set the prototype property */ if (JS_DefinePropertyValue(ctx, ctor, JS_ATOM_prototype, js_dup(proto), JS_PROP_THROW) < 0) goto fail; JS_FreeValue(ctx, parent_proto); JS_FreeValue(ctx, parent_class); sp[-2] = ctor; sp[-1] = proto; return 0; fail: JS_FreeValue(ctx, parent_class); JS_FreeValue(ctx, parent_proto); JS_FreeValue(ctx, bfunc); JS_FreeValue(ctx, proto); JS_FreeValue(ctx, ctor); sp[-2] = JS_UNDEFINED; sp[-1] = JS_UNDEFINED; return -1; } static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) { struct list_head *el, *el1; JSVarRef *var_ref; list_for_each_safe(el, el1, &sf->var_ref_list) { var_ref = list_entry(el, JSVarRef, header.link); var_ref->value = js_dup(*var_ref->pvalue); var_ref->pvalue = &var_ref->value; /* the reference is no longer to a local variable */ var_ref->is_detached = true; add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); } } static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx) { JSValue *pvalue; struct list_head *el, *el1; JSVarRef *var_ref; pvalue = &sf->var_buf[var_idx]; list_for_each_safe(el, el1, &sf->var_ref_list) { var_ref = list_entry(el, JSVarRef, header.link); if (var_ref->pvalue == pvalue) { var_ref->value = js_dup(*var_ref->pvalue); var_ref->pvalue = &var_ref->value; list_del(&var_ref->header.link); /* the reference is no longer to a local variable */ var_ref->is_detached = true; add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); } } } #define JS_CALL_FLAG_COPY_ARGV (1 << 1) #define JS_CALL_FLAG_GENERATOR (1 << 2) static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSRuntime *rt = ctx->rt; JSCFunctionType func; JSObject *p; JSStackFrame sf_s, *sf = &sf_s, *prev_sf; JSValue ret_val; JSValueConst *arg_buf; int arg_count, i; JSCFunctionEnum cproto; p = JS_VALUE_GET_OBJ(func_obj); cproto = p->u.cfunc.cproto; arg_count = p->u.cfunc.length; /* better to always check stack overflow */ if (js_check_stack_overflow(rt, sizeof(arg_buf[0]) * arg_count)) return JS_ThrowStackOverflow(ctx); prev_sf = rt->current_stack_frame; sf->prev_frame = prev_sf; rt->current_stack_frame = sf; ctx = p->u.cfunc.realm; /* change the current realm */ sf->is_strict_mode = false; sf->cur_func = unsafe_unconst(func_obj); sf->arg_count = argc; arg_buf = argv; if (unlikely(argc < arg_count)) { /* ensure that at least argc_count arguments are readable */ arg_buf = alloca(sizeof(arg_buf[0]) * arg_count); for(i = 0; i < argc; i++) arg_buf[i] = argv[i]; for(i = argc; i < arg_count; i++) arg_buf[i] = JS_UNDEFINED; sf->arg_count = arg_count; } sf->arg_buf = (JSValue *)arg_buf; func = p->u.cfunc.c_function; switch(cproto) { case JS_CFUNC_constructor: case JS_CFUNC_constructor_or_func: if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) { if (cproto == JS_CFUNC_constructor) { not_a_constructor: ret_val = JS_ThrowTypeError(ctx, "must be called with new"); break; } else { this_obj = JS_UNDEFINED; } } /* here this_obj is new_target */ /* fall thru */ case JS_CFUNC_generic: ret_val = func.generic(ctx, this_obj, argc, arg_buf); break; case JS_CFUNC_constructor_magic: case JS_CFUNC_constructor_or_func_magic: if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) { if (cproto == JS_CFUNC_constructor_magic) { goto not_a_constructor; } else { this_obj = JS_UNDEFINED; } } /* fall thru */ case JS_CFUNC_generic_magic: ret_val = func.generic_magic(ctx, this_obj, argc, arg_buf, p->u.cfunc.magic); break; case JS_CFUNC_getter: ret_val = func.getter(ctx, this_obj); break; case JS_CFUNC_setter: ret_val = func.setter(ctx, this_obj, arg_buf[0]); break; case JS_CFUNC_getter_magic: ret_val = func.getter_magic(ctx, this_obj, p->u.cfunc.magic); break; case JS_CFUNC_setter_magic: ret_val = func.setter_magic(ctx, this_obj, arg_buf[0], p->u.cfunc.magic); break; case JS_CFUNC_f_f: { double d1; if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) { ret_val = JS_EXCEPTION; break; } ret_val = js_number(func.f_f(d1)); } break; case JS_CFUNC_f_f_f: { double d1, d2; if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) { ret_val = JS_EXCEPTION; break; } if (unlikely(JS_ToFloat64(ctx, &d2, arg_buf[1]))) { ret_val = JS_EXCEPTION; break; } ret_val = js_number(func.f_f_f(d1, d2)); } break; case JS_CFUNC_iterator_next: { int done; ret_val = func.iterator_next(ctx, this_obj, argc, arg_buf, &done, p->u.cfunc.magic); if (!JS_IsException(ret_val) && done != 2) { ret_val = js_create_iterator_result(ctx, ret_val, done); } } break; default: abort(); } rt->current_stack_frame = sf->prev_frame; return ret_val; } static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSObject *p; JSBoundFunction *bf; JSValueConst *arg_buf, new_target; int arg_count, i; p = JS_VALUE_GET_OBJ(func_obj); bf = p->u.bound_function; arg_count = bf->argc + argc; if (js_check_stack_overflow(ctx->rt, sizeof(JSValue) * arg_count)) return JS_ThrowStackOverflow(ctx); arg_buf = alloca(sizeof(JSValue) * arg_count); for(i = 0; i < bf->argc; i++) { arg_buf[i] = bf->argv[i]; } for(i = 0; i < argc; i++) { arg_buf[bf->argc + i] = argv[i]; } if (flags & JS_CALL_FLAG_CONSTRUCTOR) { new_target = this_obj; if (js_same_value(ctx, func_obj, new_target)) new_target = bf->func_obj; return JS_CallConstructor2(ctx, bf->func_obj, new_target, arg_count, arg_buf); } else { return JS_Call(ctx, bf->func_obj, bf->this_val, arg_count, arg_buf); } } /* argument of OP_special_object */ typedef enum { OP_SPECIAL_OBJECT_ARGUMENTS, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS, OP_SPECIAL_OBJECT_THIS_FUNC, OP_SPECIAL_OBJECT_NEW_TARGET, OP_SPECIAL_OBJECT_HOME_OBJECT, OP_SPECIAL_OBJECT_VAR_OBJECT, OP_SPECIAL_OBJECT_IMPORT_META, OP_SPECIAL_OBJECT_NULL_PROTO, } OPSpecialObjectEnum; #define FUNC_RET_AWAIT 0 #define FUNC_RET_YIELD 1 #define FUNC_RET_YIELD_STAR 2 #ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* static void dump_single_byte_code(JSContext *ctx, const uint8_t *pc, JSFunctionBytecode *b, int start_pos); static void print_func_name(JSFunctionBytecode *b); #endif static bool needs_backtrace(JSValue exc) { JSObject *p; if (JS_VALUE_GET_TAG(exc) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(exc); if (p->class_id != JS_CLASS_ERROR) return false; return !find_own_property1(p, JS_ATOM_stack); } /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSValueConst this_obj, JSValueConst new_target, int argc, JSValueConst *argv, int flags) { JSRuntime *rt = caller_ctx->rt; JSContext *ctx; JSObject *p; JSFunctionBytecode *b; JSStackFrame sf_s, *sf = &sf_s; uint8_t *pc; int opcode, arg_allocated_size, i; JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval; JSVarRef **var_refs; size_t alloca_size; #ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP #define DUMP_BYTECODE_OR_DONT(pc) \ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP)) dump_single_byte_code(ctx, pc, b, 0); #else #define DUMP_BYTECODE_OR_DONT(pc) #endif #if !DIRECT_DISPATCH #define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) switch (opcode = *pc++) #define CASE(op) case op #define DEFAULT default #define BREAK break #else __extension__ static const void * const dispatch_table[256] = { #define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id, #define def(id, size, n_pop, n_push, f) #include "quickjs-opcode.h" [ OP_COUNT ... 255 ] = &&case_default }; #define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) __extension__ ({ goto *dispatch_table[opcode = *pc++]; }); #define CASE(op) case_ ## op #define DEFAULT case_default #define BREAK SWITCH(pc) #endif if (js_poll_interrupts(caller_ctx)) return JS_EXCEPTION; if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) { if (flags & JS_CALL_FLAG_GENERATOR) { JSAsyncFunctionState *s = JS_VALUE_GET_PTR(func_obj); /* func_obj get contains a pointer to JSFuncAsyncState */ /* the stack frame is already allocated */ sf = &s->frame; p = JS_VALUE_GET_OBJ(sf->cur_func); b = p->u.func.function_bytecode; ctx = b->realm; var_refs = p->u.func.var_refs; local_buf = arg_buf = sf->arg_buf; var_buf = sf->var_buf; stack_buf = sf->var_buf + b->var_count; sp = sf->cur_sp; sf->cur_sp = NULL; /* cur_sp is NULL if the function is running */ pc = sf->cur_pc; sf->prev_frame = rt->current_stack_frame; rt->current_stack_frame = sf; if (s->throw_flag) goto exception; else goto restart; } else { goto not_a_function; } } p = JS_VALUE_GET_OBJ(func_obj); if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) { JSClassCall *call_func; call_func = rt->class_array[p->class_id].call; if (!call_func) { not_a_function: return JS_ThrowTypeErrorNotAFunction(caller_ctx); } return call_func(caller_ctx, func_obj, this_obj, argc, argv, flags); } b = p->u.func.function_bytecode; if (unlikely(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) { arg_allocated_size = b->arg_count; } else { arg_allocated_size = 0; } alloca_size = sizeof(JSValue) * (arg_allocated_size + b->var_count + b->stack_size); if (js_check_stack_overflow(rt, alloca_size)) return JS_ThrowStackOverflow(caller_ctx); sf->is_strict_mode = b->is_strict_mode; arg_buf = (JSValue *)argv; sf->arg_count = argc; sf->cur_func = unsafe_unconst(func_obj); init_list_head(&sf->var_ref_list); var_refs = p->u.func.var_refs; local_buf = alloca(alloca_size); if (unlikely(arg_allocated_size)) { int n = min_int(argc, b->arg_count); arg_buf = local_buf; for(i = 0; i < n; i++) arg_buf[i] = js_dup(argv[i]); for(; i < b->arg_count; i++) arg_buf[i] = JS_UNDEFINED; sf->arg_count = b->arg_count; } var_buf = local_buf + arg_allocated_size; sf->var_buf = var_buf; sf->arg_buf = arg_buf; for(i = 0; i < b->var_count; i++) var_buf[i] = JS_UNDEFINED; stack_buf = var_buf + b->var_count; sp = stack_buf; pc = b->byte_code_buf; /* sf->cur_pc must we set to pc before any recursive calls to JS_CallInternal. */ sf->cur_pc = NULL; sf->prev_frame = rt->current_stack_frame; rt->current_stack_frame = sf; ctx = b->realm; /* set the current realm */ if (ctx->handleFunctionEntered) ctx->handleFunctionEntered(ctx, this_obj); #ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP)) print_func_name(b); #endif restart: for(;;) { int call_argc; JSValue *call_argv; SWITCH(pc) { CASE(OP_push_i32): *sp++ = js_int32(get_u32(pc)); pc += 4; BREAK; CASE(OP_push_bigint_i32): *sp++ = __JS_NewShortBigInt(ctx, (int)get_u32(pc)); pc += 4; BREAK; CASE(OP_push_const): *sp++ = js_dup(b->cpool[get_u32(pc)]); pc += 4; BREAK; CASE(OP_push_minus1): CASE(OP_push_0): CASE(OP_push_1): CASE(OP_push_2): CASE(OP_push_3): CASE(OP_push_4): CASE(OP_push_5): CASE(OP_push_6): CASE(OP_push_7): *sp++ = js_int32(opcode - OP_push_0); BREAK; CASE(OP_push_i8): *sp++ = js_int32(get_i8(pc)); pc += 1; BREAK; CASE(OP_push_i16): *sp++ = js_int32(get_i16(pc)); pc += 2; BREAK; CASE(OP_push_const8): *sp++ = js_dup(b->cpool[*pc++]); BREAK; CASE(OP_fclosure8): *sp++ = js_closure(ctx, js_dup(b->cpool[*pc++]), var_refs, sf); if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; CASE(OP_push_empty_string): *sp++ = js_empty_string(rt); BREAK; CASE(OP_get_length): { JSValue val; sf->cur_pc = pc; val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length); if (unlikely(JS_IsException(val))) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } BREAK; CASE(OP_push_atom_value): *sp++ = JS_AtomToValue(ctx, get_u32(pc)); pc += 4; BREAK; CASE(OP_undefined): *sp++ = JS_UNDEFINED; BREAK; CASE(OP_null): *sp++ = JS_NULL; BREAK; CASE(OP_push_this): /* OP_push_this is only called at the start of a function */ { JSValue val; if (!b->is_strict_mode) { uint32_t tag = JS_VALUE_GET_TAG(this_obj); if (likely(tag == JS_TAG_OBJECT)) goto normal_this; if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) { val = js_dup(ctx->global_obj); } else { val = JS_ToObject(ctx, this_obj); if (JS_IsException(val)) goto exception; } } else { normal_this: val = js_dup(this_obj); } *sp++ = val; } BREAK; CASE(OP_push_false): *sp++ = JS_FALSE; BREAK; CASE(OP_push_true): *sp++ = JS_TRUE; BREAK; CASE(OP_object): *sp++ = JS_NewObject(ctx); if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; CASE(OP_special_object): { int arg = *pc++; switch(arg) { case OP_SPECIAL_OBJECT_ARGUMENTS: *sp++ = js_build_arguments(ctx, argc, argv); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS: *sp++ = js_build_mapped_arguments(ctx, argc, argv, sf, min_int(argc, b->arg_count)); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_THIS_FUNC: *sp++ = js_dup(sf->cur_func); break; case OP_SPECIAL_OBJECT_NEW_TARGET: *sp++ = js_dup(new_target); break; case OP_SPECIAL_OBJECT_HOME_OBJECT: { JSObject *p1; p1 = p->u.func.home_object; if (unlikely(!p1)) *sp++ = JS_UNDEFINED; else *sp++ = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); } break; case OP_SPECIAL_OBJECT_VAR_OBJECT: *sp++ = JS_NewObjectProto(ctx, JS_NULL); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_IMPORT_META: *sp++ = js_import_meta(ctx); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_NULL_PROTO: *sp++ = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OBJECT); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; default: abort(); } } BREAK; CASE(OP_rest): { int i, n, first = get_u16(pc); pc += 2; i = min_int(first, argc); n = argc - i; *sp++ = js_create_array(ctx, n, &argv[i]); if (unlikely(JS_IsException(sp[-1]))) goto exception; } BREAK; CASE(OP_drop): JS_FreeValue(ctx, sp[-1]); sp--; BREAK; CASE(OP_nip): JS_FreeValue(ctx, sp[-2]); sp[-2] = sp[-1]; sp--; BREAK; CASE(OP_nip1): /* a b c -> b c */ JS_FreeValue(ctx, sp[-3]); sp[-3] = sp[-2]; sp[-2] = sp[-1]; sp--; BREAK; CASE(OP_dup): sp[0] = js_dup(sp[-1]); sp++; BREAK; CASE(OP_dup2): /* a b -> a b a b */ sp[0] = js_dup(sp[-2]); sp[1] = js_dup(sp[-1]); sp += 2; BREAK; CASE(OP_dup3): /* a b c -> a b c a b c */ sp[0] = js_dup(sp[-3]); sp[1] = js_dup(sp[-2]); sp[2] = js_dup(sp[-1]); sp += 3; BREAK; CASE(OP_dup1): /* a b -> a a b */ sp[0] = sp[-1]; sp[-1] = js_dup(sp[-2]); sp++; BREAK; CASE(OP_insert2): /* obj a -> a obj a (dup_x1) */ sp[0] = sp[-1]; sp[-1] = sp[-2]; sp[-2] = js_dup(sp[0]); sp++; BREAK; CASE(OP_insert3): /* obj prop a -> a obj prop a (dup_x2) */ sp[0] = sp[-1]; sp[-1] = sp[-2]; sp[-2] = sp[-3]; sp[-3] = js_dup(sp[0]); sp++; BREAK; CASE(OP_insert4): /* this obj prop a -> a this obj prop a */ sp[0] = sp[-1]; sp[-1] = sp[-2]; sp[-2] = sp[-3]; sp[-3] = sp[-4]; sp[-4] = js_dup(sp[0]); sp++; BREAK; CASE(OP_perm3): /* obj a b -> a obj b (213) */ { JSValue tmp; tmp = sp[-2]; sp[-2] = sp[-3]; sp[-3] = tmp; } BREAK; CASE(OP_rot3l): /* x a b -> a b x (231) */ { JSValue tmp; tmp = sp[-3]; sp[-3] = sp[-2]; sp[-2] = sp[-1]; sp[-1] = tmp; } BREAK; CASE(OP_rot4l): /* x a b c -> a b c x */ { JSValue tmp; tmp = sp[-4]; sp[-4] = sp[-3]; sp[-3] = sp[-2]; sp[-2] = sp[-1]; sp[-1] = tmp; } BREAK; CASE(OP_rot5l): /* x a b c d -> a b c d x */ { JSValue tmp; tmp = sp[-5]; sp[-5] = sp[-4]; sp[-4] = sp[-3]; sp[-3] = sp[-2]; sp[-2] = sp[-1]; sp[-1] = tmp; } BREAK; CASE(OP_rot3r): /* a b x -> x a b (312) */ { JSValue tmp; tmp = sp[-1]; sp[-1] = sp[-2]; sp[-2] = sp[-3]; sp[-3] = tmp; } BREAK; CASE(OP_perm4): /* obj prop a b -> a obj prop b */ { JSValue tmp; tmp = sp[-2]; sp[-2] = sp[-3]; sp[-3] = sp[-4]; sp[-4] = tmp; } BREAK; CASE(OP_perm5): /* this obj prop a b -> a this obj prop b */ { JSValue tmp; tmp = sp[-2]; sp[-2] = sp[-3]; sp[-3] = sp[-4]; sp[-4] = sp[-5]; sp[-5] = tmp; } BREAK; CASE(OP_swap): /* a b -> b a */ { JSValue tmp; tmp = sp[-2]; sp[-2] = sp[-1]; sp[-1] = tmp; } BREAK; CASE(OP_swap2): /* a b c d -> c d a b */ { JSValue tmp1, tmp2; tmp1 = sp[-4]; tmp2 = sp[-3]; sp[-4] = sp[-2]; sp[-3] = sp[-1]; sp[-2] = tmp1; sp[-1] = tmp2; } BREAK; CASE(OP_fclosure): { JSValue bfunc = js_dup(b->cpool[get_u32(pc)]); pc += 4; *sp++ = js_closure(ctx, bfunc, var_refs, sf); if (unlikely(JS_IsException(sp[-1]))) goto exception; } BREAK; CASE(OP_call0): CASE(OP_call1): CASE(OP_call2): CASE(OP_call3): call_argc = opcode - OP_call0; goto has_call_argc; CASE(OP_call): CASE(OP_tail_call): { call_argc = get_u16(pc); pc += 2; goto has_call_argc; has_call_argc: call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED, JS_UNDEFINED, call_argc, vc(call_argv), 0); if (unlikely(JS_IsException(ret_val))) goto exception; if (opcode == OP_tail_call) goto done; for(i = -1; i < call_argc; i++) JS_FreeValue(ctx, call_argv[i]); sp -= call_argc + 1; *sp++ = ret_val; } BREAK; CASE(OP_call_constructor): { call_argc = get_u16(pc); pc += 2; call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallConstructorInternal(ctx, call_argv[-2], call_argv[-1], call_argc, vc(call_argv), 0); if (unlikely(JS_IsException(ret_val))) goto exception; for(i = -2; i < call_argc; i++) JS_FreeValue(ctx, call_argv[i]); sp -= call_argc + 2; *sp++ = ret_val; } BREAK; CASE(OP_call_method): CASE(OP_tail_call_method): { call_argc = get_u16(pc); pc += 2; call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2], JS_UNDEFINED, call_argc, vc(call_argv), 0); if (unlikely(JS_IsException(ret_val))) goto exception; if (opcode == OP_tail_call_method) goto done; for(i = -2; i < call_argc; i++) JS_FreeValue(ctx, call_argv[i]); sp -= call_argc + 2; *sp++ = ret_val; } BREAK; CASE(OP_array_from): { call_argc = get_u16(pc); pc += 2; call_argv = sp - call_argc; ret_val = JS_NewArrayFrom(ctx, call_argc, call_argv); sp -= call_argc; if (unlikely(JS_IsException(ret_val))) goto exception; *sp++ = ret_val; } BREAK; CASE(OP_apply): { int magic; magic = get_u16(pc); pc += 2; sf->cur_pc = pc; ret_val = js_function_apply(ctx, sp[-3], 2, vc(&sp[-2]), magic); if (unlikely(JS_IsException(ret_val))) goto exception; JS_FreeValue(ctx, sp[-3]); JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-1]); sp -= 3; *sp++ = ret_val; } BREAK; CASE(OP_return): ret_val = *--sp; goto done; CASE(OP_return_undef): ret_val = JS_UNDEFINED; goto done; CASE(OP_check_ctor_return): /* return true if 'this' should be returned */ if (!JS_IsObject(sp[-1])) { if (!JS_IsUndefined(sp[-1])) { JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined"); goto exception; } sp[0] = JS_TRUE; } else { sp[0] = JS_FALSE; } sp++; BREAK; CASE(OP_check_ctor): if (JS_IsUndefined(new_target)) { non_ctor_call: JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'"); goto exception; } BREAK; CASE(OP_init_ctor): { JSValue super, ret; sf->cur_pc = pc; if (JS_IsUndefined(new_target)) goto non_ctor_call; super = JS_GetPrototype(ctx, func_obj); if (JS_IsException(super)) goto exception; ret = JS_CallConstructor2(ctx, super, new_target, argc, argv); JS_FreeValue(ctx, super); if (JS_IsException(ret)) goto exception; *sp++ = ret; } BREAK; CASE(OP_check_brand): { int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]); if (ret < 0) goto exception; if (!ret) { JS_ThrowTypeError(ctx, "invalid brand on object"); goto exception; } } BREAK; CASE(OP_add_brand): if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0) goto exception; JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-1]); sp -= 2; BREAK; CASE(OP_throw): JS_Throw(ctx, *--sp); goto exception; CASE(OP_throw_error): #define JS_THROW_VAR_RO 0 #define JS_THROW_VAR_REDECL 1 #define JS_THROW_VAR_UNINITIALIZED 2 #define JS_THROW_ERROR_DELETE_SUPER 3 #define JS_THROW_ERROR_ITERATOR_THROW 4 { JSAtom atom; int type; atom = get_u32(pc); type = pc[4]; pc += 5; if (type == JS_THROW_VAR_RO) JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, atom); else if (type == JS_THROW_VAR_REDECL) JS_ThrowSyntaxErrorVarRedeclaration(ctx, atom); else if (type == JS_THROW_VAR_UNINITIALIZED) JS_ThrowReferenceErrorUninitialized(ctx, atom); else if (type == JS_THROW_ERROR_DELETE_SUPER) JS_ThrowReferenceError(ctx, "unsupported reference to 'super'"); else if (type == JS_THROW_ERROR_ITERATOR_THROW) JS_ThrowTypeError(ctx, "iterator does not have a throw method"); else JS_ThrowInternalError(ctx, "invalid throw var type %d", type); } goto exception; CASE(OP_eval): { JSValue obj; int scope_idx; call_argc = get_u16(pc); scope_idx = get_u16(pc + 2) - 1; pc += 4; call_argv = sp - call_argc; sf->cur_pc = pc; if (js_same_value(ctx, call_argv[-1], ctx->eval_obj)) { if (call_argc >= 1) obj = call_argv[0]; else obj = JS_UNDEFINED; ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj, JS_EVAL_TYPE_DIRECT, scope_idx); } else { ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED, JS_UNDEFINED, call_argc, vc(call_argv), 0); } if (unlikely(JS_IsException(ret_val))) goto exception; for(i = -1; i < call_argc; i++) JS_FreeValue(ctx, call_argv[i]); sp -= call_argc + 1; *sp++ = ret_val; } BREAK; /* could merge with OP_apply */ CASE(OP_apply_eval): { int scope_idx; uint32_t len; JSValue *tab; JSValue obj; scope_idx = get_u16(pc) - 1; pc += 2; sf->cur_pc = pc; tab = build_arg_list(ctx, &len, sp[-1]); if (!tab) goto exception; if (js_same_value(ctx, sp[-2], ctx->eval_obj)) { if (len >= 1) obj = tab[0]; else obj = JS_UNDEFINED; ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj, JS_EVAL_TYPE_DIRECT, scope_idx); } else { ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len, vc(tab)); } free_arg_list(ctx, tab, len); if (unlikely(JS_IsException(ret_val))) goto exception; JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-1]); sp -= 2; *sp++ = ret_val; } BREAK; CASE(OP_regexp): { sp[-2] = js_regexp_constructor_internal(ctx, JS_UNDEFINED, sp[-2], sp[-1]); sp--; } BREAK; CASE(OP_get_super): { JSValue proto; proto = JS_GetPrototype(ctx, sp[-1]); if (JS_IsException(proto)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = proto; } BREAK; CASE(OP_import): { JSValue val; sf->cur_pc = pc; val = js_dynamic_import(ctx, sp[-1]); if (JS_IsException(val)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } BREAK; CASE(OP_check_var): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; ret = JS_CheckGlobalVar(ctx, atom); if (ret < 0) goto exception; *sp++ = js_bool(ret); } BREAK; CASE(OP_get_var_undef): CASE(OP_get_var): { JSValue val; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef); if (unlikely(JS_IsException(val))) goto exception; *sp++ = val; } BREAK; CASE(OP_put_var): CASE(OP_put_var_init): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var); sp--; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_put_var_strict): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; /* sp[-2] is JS_TRUE or JS_FALSE */ if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) { JS_ThrowReferenceErrorNotDefined(ctx, atom); goto exception; } ret = JS_SetGlobalVar(ctx, atom, sp[-1], 2); sp -= 2; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_check_define_var): { JSAtom atom; int flags; atom = get_u32(pc); flags = pc[4]; pc += 5; if (JS_CheckDefineGlobalVar(ctx, atom, flags)) goto exception; } BREAK; CASE(OP_define_var): { JSAtom atom; int flags; atom = get_u32(pc); flags = pc[4]; pc += 5; if (JS_DefineGlobalVar(ctx, atom, flags)) goto exception; } BREAK; CASE(OP_define_func): { JSAtom atom; int flags; atom = get_u32(pc); flags = pc[4]; pc += 5; if (JS_DefineGlobalFunction(ctx, atom, sp[-1], flags)) goto exception; JS_FreeValue(ctx, sp[-1]); sp--; } BREAK; CASE(OP_get_loc): { int idx; idx = get_u16(pc); pc += 2; sp[0] = js_dup(var_buf[idx]); sp++; } BREAK; CASE(OP_put_loc): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, &var_buf[idx], sp[-1]); sp--; } BREAK; CASE(OP_set_loc): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, &var_buf[idx], js_dup(sp[-1])); } BREAK; CASE(OP_get_arg): { int idx; idx = get_u16(pc); pc += 2; sp[0] = js_dup(arg_buf[idx]); sp++; } BREAK; CASE(OP_put_arg): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, &arg_buf[idx], sp[-1]); sp--; } BREAK; CASE(OP_set_arg): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, &arg_buf[idx], js_dup(sp[-1])); } BREAK; CASE(OP_get_loc8): *sp++ = js_dup(var_buf[*pc++]); BREAK; CASE(OP_put_loc8): set_value(ctx, &var_buf[*pc++], *--sp); BREAK; CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], js_dup(sp[-1])); BREAK; // Observation: get_loc0 and get_loc1 are individually very // frequent opcodes _and_ they are very often paired together, // making them ideal candidates for opcode fusion. CASE(OP_get_loc0_loc1): *sp++ = js_dup(var_buf[0]); *sp++ = js_dup(var_buf[1]); BREAK; CASE(OP_get_loc0): *sp++ = js_dup(var_buf[0]); BREAK; CASE(OP_get_loc1): *sp++ = js_dup(var_buf[1]); BREAK; CASE(OP_get_loc2): *sp++ = js_dup(var_buf[2]); BREAK; CASE(OP_get_loc3): *sp++ = js_dup(var_buf[3]); BREAK; CASE(OP_put_loc0): set_value(ctx, &var_buf[0], *--sp); BREAK; CASE(OP_put_loc1): set_value(ctx, &var_buf[1], *--sp); BREAK; CASE(OP_put_loc2): set_value(ctx, &var_buf[2], *--sp); BREAK; CASE(OP_put_loc3): set_value(ctx, &var_buf[3], *--sp); BREAK; CASE(OP_set_loc0): set_value(ctx, &var_buf[0], js_dup(sp[-1])); BREAK; CASE(OP_set_loc1): set_value(ctx, &var_buf[1], js_dup(sp[-1])); BREAK; CASE(OP_set_loc2): set_value(ctx, &var_buf[2], js_dup(sp[-1])); BREAK; CASE(OP_set_loc3): set_value(ctx, &var_buf[3], js_dup(sp[-1])); BREAK; CASE(OP_get_arg0): *sp++ = js_dup(arg_buf[0]); BREAK; CASE(OP_get_arg1): *sp++ = js_dup(arg_buf[1]); BREAK; CASE(OP_get_arg2): *sp++ = js_dup(arg_buf[2]); BREAK; CASE(OP_get_arg3): *sp++ = js_dup(arg_buf[3]); BREAK; CASE(OP_put_arg0): set_value(ctx, &arg_buf[0], *--sp); BREAK; CASE(OP_put_arg1): set_value(ctx, &arg_buf[1], *--sp); BREAK; CASE(OP_put_arg2): set_value(ctx, &arg_buf[2], *--sp); BREAK; CASE(OP_put_arg3): set_value(ctx, &arg_buf[3], *--sp); BREAK; CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], js_dup(sp[-1])); BREAK; CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], js_dup(sp[-1])); BREAK; CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], js_dup(sp[-1])); BREAK; CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], js_dup(sp[-1])); BREAK; CASE(OP_get_var_ref0): *sp++ = js_dup(*var_refs[0]->pvalue); BREAK; CASE(OP_get_var_ref1): *sp++ = js_dup(*var_refs[1]->pvalue); BREAK; CASE(OP_get_var_ref2): *sp++ = js_dup(*var_refs[2]->pvalue); BREAK; CASE(OP_get_var_ref3): *sp++ = js_dup(*var_refs[3]->pvalue); BREAK; CASE(OP_put_var_ref0): set_value(ctx, var_refs[0]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref1): set_value(ctx, var_refs[1]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref2): set_value(ctx, var_refs[2]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref3): set_value(ctx, var_refs[3]->pvalue, *--sp); BREAK; CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, js_dup(sp[-1])); BREAK; CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, js_dup(sp[-1])); BREAK; CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, js_dup(sp[-1])); BREAK; CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, js_dup(sp[-1])); BREAK; CASE(OP_get_var_ref): { int idx; JSValue val; idx = get_u16(pc); pc += 2; val = *var_refs[idx]->pvalue; sp[0] = js_dup(val); sp++; } BREAK; CASE(OP_put_var_ref): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, var_refs[idx]->pvalue, sp[-1]); sp--; } BREAK; CASE(OP_set_var_ref): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, var_refs[idx]->pvalue, js_dup(sp[-1])); } BREAK; CASE(OP_get_var_ref_check): { int idx; JSValue val; idx = get_u16(pc); pc += 2; val = *var_refs[idx]->pvalue; if (unlikely(JS_IsUninitialized(val))) { JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); goto exception; } sp[0] = js_dup(val); sp++; } BREAK; CASE(OP_put_var_ref_check): { int idx; idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) { JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); goto exception; } set_value(ctx, var_refs[idx]->pvalue, sp[-1]); sp--; } BREAK; CASE(OP_put_var_ref_check_init): { int idx; idx = get_u16(pc); pc += 2; if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) { JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); goto exception; } set_value(ctx, var_refs[idx]->pvalue, sp[-1]); sp--; } BREAK; CASE(OP_set_loc_uninitialized): { int idx; idx = get_u16(pc); pc += 2; set_value(ctx, &var_buf[idx], JS_UNINITIALIZED); } BREAK; CASE(OP_get_loc_check): { int idx; idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(var_buf[idx]))) { JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, false); goto exception; } sp[0] = js_dup(var_buf[idx]); sp++; } BREAK; CASE(OP_put_loc_check): { int idx; idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(var_buf[idx]))) { JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, false); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); sp--; } BREAK; CASE(OP_put_loc_check_init): { int idx; idx = get_u16(pc); pc += 2; if (unlikely(!JS_IsUninitialized(var_buf[idx]))) { JS_ThrowReferenceError(caller_ctx, "'this' can be initialized only once"); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); sp--; } BREAK; CASE(OP_close_loc): { int idx; idx = get_u16(pc); pc += 2; close_lexical_var(ctx, sf, idx); } BREAK; CASE(OP_make_loc_ref): CASE(OP_make_arg_ref): CASE(OP_make_var_ref_ref): { JSVarRef *var_ref; JSProperty *pr; JSAtom atom; int idx; atom = get_u32(pc); idx = get_u16(pc + 4); pc += 6; *sp++ = JS_NewObjectProto(ctx, JS_NULL); if (unlikely(JS_IsException(sp[-1]))) goto exception; if (opcode == OP_make_var_ref_ref) { var_ref = var_refs[idx]; var_ref->header.ref_count++; } else { var_ref = get_var_ref(ctx, sf, idx, opcode == OP_make_arg_ref); if (!var_ref) goto exception; } pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom, JS_PROP_WRITABLE | JS_PROP_VARREF); if (!pr) { free_var_ref(rt, var_ref); goto exception; } pr->u.var_ref = var_ref; *sp++ = JS_AtomToValue(ctx, atom); } BREAK; CASE(OP_make_var_ref): { JSAtom atom; atom = get_u32(pc); pc += 4; if (JS_GetGlobalVarRef(ctx, atom, sp)) goto exception; sp += 2; } BREAK; CASE(OP_goto): pc += (int32_t)get_u32(pc); if (unlikely(js_poll_interrupts(ctx))) goto exception; BREAK; CASE(OP_goto16): pc += (int16_t)get_u16(pc); if (unlikely(js_poll_interrupts(ctx))) goto exception; BREAK; CASE(OP_goto8): pc += (int8_t)pc[0]; if (unlikely(js_poll_interrupts(ctx))) goto exception; BREAK; CASE(OP_if_true): { int res; JSValue op1; op1 = sp[-1]; pc += 4; if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1); } else { res = JS_ToBoolFree(ctx, op1); } sp--; if (res) { pc += (int32_t)get_u32(pc - 4) - 4; } if (unlikely(js_poll_interrupts(ctx))) goto exception; } BREAK; CASE(OP_if_false): { int res; JSValue op1; op1 = sp[-1]; pc += 4; if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1); } else { res = JS_ToBoolFree(ctx, op1); } sp--; if (!res) { pc += (int32_t)get_u32(pc - 4) - 4; } if (unlikely(js_poll_interrupts(ctx))) goto exception; } BREAK; CASE(OP_if_true8): { int res; JSValue op1; op1 = sp[-1]; pc += 1; if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1); } else { res = JS_ToBoolFree(ctx, op1); } sp--; if (res) { pc += (int8_t)pc[-1] - 1; } if (unlikely(js_poll_interrupts(ctx))) goto exception; } BREAK; CASE(OP_if_false8): { int res; JSValue op1; op1 = sp[-1]; pc += 1; if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1); } else { res = JS_ToBoolFree(ctx, op1); } sp--; if (!res) { pc += (int8_t)pc[-1] - 1; } if (unlikely(js_poll_interrupts(ctx))) goto exception; } BREAK; CASE(OP_catch): { int32_t diff; diff = get_u32(pc); sp[0] = JS_NewCatchOffset(ctx, pc + diff - b->byte_code_buf); sp++; pc += 4; } BREAK; CASE(OP_gosub): { int32_t diff; diff = get_u32(pc); /* XXX: should have a different tag to avoid security flaw */ sp[0] = js_int32(pc + 4 - b->byte_code_buf); sp++; pc += diff; } BREAK; CASE(OP_ret): { JSValue op1; uint32_t pos; op1 = sp[-1]; if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_INT)) goto ret_fail; pos = JS_VALUE_GET_INT(op1); if (unlikely(pos >= b->byte_code_len)) { ret_fail: JS_ThrowInternalError(ctx, "invalid ret value"); goto exception; } sp--; pc = b->byte_code_buf + pos; } BREAK; CASE(OP_for_in_start): sf->cur_pc = pc; if (js_for_in_start(ctx, sp)) goto exception; BREAK; CASE(OP_for_in_next): sf->cur_pc = pc; if (js_for_in_next(ctx, sp)) goto exception; sp += 2; BREAK; CASE(OP_for_of_start): sf->cur_pc = pc; if (js_for_of_start(ctx, sp, false)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); BREAK; CASE(OP_for_of_next): { int offset = -3 - pc[0]; pc += 1; sf->cur_pc = pc; if (js_for_of_next(ctx, sp, offset)) goto exception; sp += 2; } BREAK; CASE(OP_for_await_of_start): sf->cur_pc = pc; if (js_for_of_start(ctx, sp, true)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); BREAK; CASE(OP_iterator_get_value_done): sf->cur_pc = pc; if (js_iterator_get_value_done(ctx, sp)) goto exception; sp += 1; BREAK; CASE(OP_iterator_check_object): if (unlikely(!JS_IsObject(sp[-1]))) { JS_ThrowTypeError(ctx, "iterator must return an object"); goto exception; } BREAK; CASE(OP_iterator_close): /* iter_obj next catch_offset -> */ sp--; /* drop the catch offset to avoid getting caught by exception */ JS_FreeValue(ctx, sp[-1]); /* drop the next method */ sp--; if (!JS_IsUndefined(sp[-1])) { sf->cur_pc = pc; if (JS_IteratorClose(ctx, sp[-1], false)) goto exception; JS_FreeValue(ctx, sp[-1]); } sp--; BREAK; CASE(OP_nip_catch): { JSValue ret_val; /* catch_offset ... ret_val -> ret_eval */ ret_val = *--sp; while (sp > stack_buf && JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_CATCH_OFFSET) { JS_FreeValue(ctx, *--sp); } if (unlikely(sp == stack_buf)) { JS_ThrowInternalError(ctx, "nip_catch"); JS_FreeValue(ctx, ret_val); goto exception; } sp[-1] = ret_val; } BREAK; CASE(OP_iterator_next): /* stack: iter_obj next catch_offset val */ { JSValue ret; sf->cur_pc = pc; ret = JS_Call(ctx, sp[-3], sp[-4], 1, vc(sp - 1)); if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret; } BREAK; CASE(OP_iterator_call): /* stack: iter_obj next catch_offset val */ { JSValue method, ret; bool ret_flag; int flags; flags = *pc++; sf->cur_pc = pc; method = JS_GetProperty(ctx, sp[-4], (flags & 1) ? JS_ATOM_throw : JS_ATOM_return); if (JS_IsException(method)) goto exception; if (JS_IsUndefined(method) || JS_IsNull(method)) { ret_flag = true; } else { if (flags & 2) { /* no argument */ ret = JS_CallFree(ctx, method, sp[-4], 0, NULL); } else { ret = JS_CallFree(ctx, method, sp[-4], 1, vc(sp - 1)); } if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret; ret_flag = false; } sp[0] = js_bool(ret_flag); sp += 1; } BREAK; CASE(OP_lnot): { int res; JSValue op1; op1 = sp[-1]; if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1) != 0; } else { res = JS_ToBoolFree(ctx, op1); } sp[-1] = js_bool(!res); } BREAK; CASE(OP_get_field): { JSValue val; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); if (unlikely(JS_IsException(val))) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } BREAK; CASE(OP_get_field2): { JSValue val; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); if (unlikely(JS_IsException(val))) goto exception; *sp++ = val; } BREAK; CASE(OP_put_field): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; ret = JS_SetPropertyInternal2(ctx, sp[-2], atom, sp[-1], sp[-2], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-2]); sp -= 2; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_private_symbol): { JSAtom atom; JSValue val; atom = get_u32(pc); pc += 4; val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE); if (JS_IsException(val)) goto exception; *sp++ = val; } BREAK; CASE(OP_get_private_field): { JSValue val; sf->cur_pc = pc; val = JS_GetPrivateField(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-1]); JS_FreeValue(ctx, sp[-2]); sp[-2] = val; sp--; if (unlikely(JS_IsException(val))) goto exception; } BREAK; CASE(OP_put_private_field): { int ret; sf->cur_pc = pc; ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]); JS_FreeValue(ctx, sp[-3]); JS_FreeValue(ctx, sp[-1]); sp -= 3; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_define_private_field): { int ret; ret = JS_DefinePrivateField(ctx, sp[-3], sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-2]); sp -= 2; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_define_field): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; ret = JS_DefinePropertyValue(ctx, sp[-2], atom, sp[-1], JS_PROP_C_W_E | JS_PROP_THROW); sp--; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_set_name): { int ret; JSAtom atom; atom = get_u32(pc); pc += 4; ret = JS_DefineObjectName(ctx, sp[-1], atom, JS_PROP_CONFIGURABLE); if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_set_name_computed): { int ret; ret = JS_DefineObjectNameComputed(ctx, sp[-1], sp[-2], JS_PROP_CONFIGURABLE); if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_set_proto): { JSValue proto; proto = sp[-1]; if (JS_IsObject(proto) || JS_IsNull(proto)) { if (JS_SetPrototypeInternal(ctx, sp[-2], proto, true) < 0) goto exception; } JS_FreeValue(ctx, proto); sp--; } BREAK; CASE(OP_set_home_object): js_method_set_home_object(ctx, sp[-1], sp[-2]); BREAK; CASE(OP_define_method): CASE(OP_define_method_computed): { JSValue getter, setter, value; JSValue obj; JSAtom atom; int flags, ret, op_flags; bool is_computed; #define OP_DEFINE_METHOD_METHOD 0 #define OP_DEFINE_METHOD_GETTER 1 #define OP_DEFINE_METHOD_SETTER 2 #define OP_DEFINE_METHOD_ENUMERABLE 4 is_computed = (opcode == OP_define_method_computed); if (is_computed) { atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; opcode += OP_define_method - OP_define_method_computed; } else { atom = get_u32(pc); pc += 4; } op_flags = *pc++; obj = sp[-2 - is_computed]; flags = JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE | JS_PROP_THROW; if (op_flags & OP_DEFINE_METHOD_ENUMERABLE) flags |= JS_PROP_ENUMERABLE; op_flags &= 3; value = JS_UNDEFINED; getter = JS_UNDEFINED; setter = JS_UNDEFINED; if (op_flags == OP_DEFINE_METHOD_METHOD) { value = sp[-1]; flags |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE; } else if (op_flags == OP_DEFINE_METHOD_GETTER) { getter = sp[-1]; flags |= JS_PROP_HAS_GET; } else { setter = sp[-1]; flags |= JS_PROP_HAS_SET; } ret = js_method_set_properties(ctx, sp[-1], atom, flags, obj); if (ret >= 0) { ret = JS_DefineProperty(ctx, obj, atom, value, getter, setter, flags); } JS_FreeValue(ctx, sp[-1]); if (is_computed) { JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, sp[-2]); } sp -= 1 + is_computed; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_define_class): CASE(OP_define_class_computed): { int class_flags; JSAtom atom; atom = get_u32(pc); class_flags = pc[4]; pc += 5; if (js_op_define_class(ctx, sp, atom, class_flags, var_refs, sf, (opcode == OP_define_class_computed)) < 0) goto exception; } BREAK; CASE(OP_get_array_el): { JSValue val; sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-2]); sp[-2] = val; sp--; if (unlikely(JS_IsException(val))) goto exception; } BREAK; CASE(OP_get_array_el2): { JSValue val; sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); sp[-1] = val; if (unlikely(JS_IsException(val))) goto exception; } BREAK; CASE(OP_get_ref_value): { JSValue val; sf->cur_pc = pc; if (unlikely(JS_IsUndefined(sp[-2]))) { JSAtom atom = JS_ValueToAtom(ctx, sp[-1]); if (atom != JS_ATOM_NULL) { JS_ThrowReferenceErrorNotDefined(ctx, atom); JS_FreeAtom(ctx, atom); } goto exception; } val = JS_GetPropertyValue(ctx, sp[-2], js_dup(sp[-1])); if (unlikely(JS_IsException(val))) goto exception; sp[0] = val; sp++; } BREAK; CASE(OP_get_super_value): { JSValue val; JSAtom atom; sf->cur_pc = pc; atom = JS_ValueToAtom(ctx, sp[-1]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], false); JS_FreeAtom(ctx, atom); if (unlikely(JS_IsException(val))) goto exception; JS_FreeValue(ctx, sp[-1]); JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-3]); sp[-3] = val; sp -= 2; } BREAK; CASE(OP_put_array_el): { int ret; sf->cur_pc = pc; ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-3]); sp -= 3; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_put_ref_value): { int ret, flags; sf->cur_pc = pc; flags = JS_PROP_THROW_STRICT; if (unlikely(JS_IsUndefined(sp[-3]))) { if (is_strict_mode(ctx)) { JSAtom atom = JS_ValueToAtom(ctx, sp[-2]); if (atom != JS_ATOM_NULL) { JS_ThrowReferenceErrorNotDefined(ctx, atom); JS_FreeAtom(ctx, atom); } goto exception; } else { sp[-3] = js_dup(ctx->global_obj); } } else { if (is_strict_mode(ctx)) flags |= JS_PROP_NO_ADD; } ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], flags); JS_FreeValue(ctx, sp[-3]); sp -= 3; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_put_super_value): { int ret; JSAtom atom; sf->cur_pc = pc; if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); goto exception; } atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; ret = JS_SetPropertyInternal2(ctx, sp[-3], atom, sp[-1], sp[-4], JS_PROP_THROW_STRICT); JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, sp[-4]); JS_FreeValue(ctx, sp[-3]); JS_FreeValue(ctx, sp[-2]); sp -= 4; if (ret < 0) goto exception; } BREAK; CASE(OP_define_array_el): { int ret; ret = JS_DefinePropertyValueValue(ctx, sp[-3], js_dup(sp[-2]), sp[-1], JS_PROP_C_W_E | JS_PROP_THROW); sp -= 1; if (unlikely(ret < 0)) goto exception; } BREAK; CASE(OP_append): /* array pos enumobj -- array pos */ { sf->cur_pc = pc; if (js_append_enumerate(ctx, sp)) goto exception; JS_FreeValue(ctx, *--sp); } BREAK; CASE(OP_copy_data_properties): /* target source excludeList */ { /* stack offsets (-1 based): 2 bits for target, 3 bits for source, 2 bits for exclusionList */ int mask; mask = *pc++; sf->cur_pc = pc; if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)], sp[-1 - ((mask >> 2) & 7)], sp[-1 - ((mask >> 5) & 7)], 0)) goto exception; } BREAK; CASE(OP_add): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int64_t r; r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto add_slow; sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) + JS_VALUE_GET_FLOAT64(op2)); sp--; } else { add_slow: sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; sp--; } } BREAK; CASE(OP_add_loc): { JSValue *pv; int idx; idx = *pc; pc += 1; pv = &var_buf[idx]; if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) { int64_t r; r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(sp[-1]); if (unlikely((int)r != r)) goto add_loc_slow; *pv = js_int32(r); sp--; } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { JSValue op1; op1 = sp[-1]; sp--; sf->cur_pc = pc; op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) goto exception; op1 = JS_ConcatString(ctx, js_dup(*pv), op1); if (JS_IsException(op1)) goto exception; set_value(ctx, pv, op1); } else { JSValue ops[2]; add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ sf->cur_pc = pc; ops[0] = js_dup(*pv); ops[1] = sp[-1]; sp--; if (js_add_slow(ctx, ops + 2)) goto exception; set_value(ctx, pv, ops[0]); } } BREAK; CASE(OP_sub): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int64_t r; r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto binary_arith_slow; sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) - JS_VALUE_GET_FLOAT64(op2)); sp--; } else { goto binary_arith_slow; } } BREAK; CASE(OP_mul): { JSValue op1, op2; double d; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int32_t v1, v2; int64_t r; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); r = (int64_t)v1 * v2; if (unlikely((int)r != r)) { d = (double)r; goto mul_fp_res; } /* need to test zero case for -0 result */ if (unlikely(r == 0 && (v1 | v2) < 0)) { d = -0.0; goto mul_fp_res; } sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2); mul_fp_res: sp[-2] = js_float64(d); sp--; } else { goto binary_arith_slow; } } BREAK; CASE(OP_div): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int v1, v2; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); sp[-2] = js_number((double)v1 / (double)v2); sp--; } else { goto binary_arith_slow; } } BREAK; CASE(OP_mod): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int v1, v2, r; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); /* We must avoid v2 = 0, v1 = INT32_MIN and v2 = -1 and the cases where the result is -0. */ if (unlikely(v1 < 0 || v2 <= 0)) goto binary_arith_slow; r = v1 % v2; sp[-2] = js_int32(r); sp--; } else { goto binary_arith_slow; } } BREAK; CASE(OP_pow): binary_arith_slow: sf->cur_pc = pc; if (js_binary_arith_slow(ctx, sp, opcode)) goto exception; sp--; BREAK; CASE(OP_plus): { JSValue op1; uint32_t tag; op1 = sp[-1]; tag = JS_VALUE_GET_TAG(op1); if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) { } else { sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } } BREAK; CASE(OP_neg): { JSValue op1; uint32_t tag; int val; double d; op1 = sp[-1]; tag = JS_VALUE_GET_TAG(op1); if (tag == JS_TAG_INT) { val = JS_VALUE_GET_INT(op1); /* Note: -0 cannot be expressed as integer */ if (unlikely(val == 0)) { d = -0.0; goto neg_fp_res; } if (unlikely(val == INT32_MIN)) { d = -(double)val; goto neg_fp_res; } sp[-1] = js_int32(-val); } else if (JS_TAG_IS_FLOAT64(tag)) { d = -JS_VALUE_GET_FLOAT64(op1); neg_fp_res: sp[-1] = js_float64(d); } else { sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } } BREAK; CASE(OP_inc): { JSValue op1; int val; op1 = sp[-1]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MAX)) goto inc_slow; sp[-1] = js_int32(val + 1); } else { inc_slow: sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } } BREAK; CASE(OP_dec): { JSValue op1; int val; op1 = sp[-1]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MIN)) goto dec_slow; sp[-1] = js_int32(val - 1); } else { dec_slow: sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } } BREAK; CASE(OP_post_inc): CASE(OP_post_dec): sf->cur_pc = pc; if (js_post_inc_slow(ctx, sp, opcode)) goto exception; sp++; BREAK; CASE(OP_inc_loc): { JSValue op1; int val; int idx; idx = *pc; pc += 1; op1 = var_buf[idx]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MAX)) goto inc_loc_slow; var_buf[idx] = js_int32(val + 1); } else { inc_loc_slow: sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ op1 = js_dup(op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc)) goto exception; set_value(ctx, &var_buf[idx], op1); } } BREAK; CASE(OP_dec_loc): { JSValue op1; int val; int idx; idx = *pc; pc += 1; op1 = var_buf[idx]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MIN)) goto dec_loc_slow; var_buf[idx] = js_int32(val - 1); } else { dec_loc_slow: sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ op1 = js_dup(op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec)) goto exception; set_value(ctx, &var_buf[idx], op1); } } BREAK; CASE(OP_not): { JSValue op1; op1 = sp[-1]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { sp[-1] = js_int32(~JS_VALUE_GET_INT(op1)); } else { sf->cur_pc = pc; if (js_not_slow(ctx, sp)) goto exception; } } BREAK; CASE(OP_shl): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { uint32_t v1, v2; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2) & 0x1f; sp[-2] = js_int32(v1 << v2); sp--; } else { sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; } } BREAK; CASE(OP_shr): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { uint32_t v2; v2 = JS_VALUE_GET_INT(op2); v2 &= 0x1f; sp[-2] = js_uint32((uint32_t)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { sf->cur_pc = pc; if (js_shr_slow(ctx, sp)) goto exception; sp--; } } BREAK; CASE(OP_sar): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { uint32_t v2; v2 = JS_VALUE_GET_INT(op2); if (unlikely(v2 > 0x1f)) { v2 &= 0x1f; } sp[-2] = js_int32((int)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; } } BREAK; CASE(OP_and): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { sp[-2] = js_int32(JS_VALUE_GET_INT(op1) & JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; } } BREAK; CASE(OP_or): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { sp[-2] = js_int32(JS_VALUE_GET_INT(op1) | JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; } } BREAK; CASE(OP_xor): { JSValue op1, op2; op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { sp[-2] = js_int32(JS_VALUE_GET_INT(op1) ^ JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; } } BREAK; #define OP_CMP(opcode, binary_op, slow_call) \ CASE(opcode): \ { \ JSValue op1, op2; \ op1 = sp[-2]; \ op2 = sp[-1]; \ if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { \ sp[-2] = js_bool(JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ sp--; \ } else { \ sf->cur_pc = pc; \ if (slow_call) \ goto exception; \ sp--; \ } \ } \ BREAK OP_CMP(OP_lt, <, js_relational_slow(ctx, sp, opcode)); OP_CMP(OP_lte, <=, js_relational_slow(ctx, sp, opcode)); OP_CMP(OP_gt, >, js_relational_slow(ctx, sp, opcode)); OP_CMP(OP_gte, >=, js_relational_slow(ctx, sp, opcode)); OP_CMP(OP_eq, ==, js_eq_slow(ctx, sp, 0)); OP_CMP(OP_neq, !=, js_eq_slow(ctx, sp, 1)); OP_CMP(OP_strict_eq, ==, js_strict_eq_slow(ctx, sp, 0)); OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1)); CASE(OP_in): sf->cur_pc = pc; if (js_operator_in(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_private_in): if (js_operator_private_in(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_instanceof): sf->cur_pc = pc; if (js_operator_instanceof(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_typeof): { JSValue op1; JSAtom atom; op1 = sp[-1]; atom = js_operator_typeof(ctx, op1); JS_FreeValue(ctx, op1); sp[-1] = JS_AtomToString(ctx, atom); } BREAK; CASE(OP_delete): sf->cur_pc = pc; if (js_operator_delete(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_delete_var): { JSAtom atom; int ret; atom = get_u32(pc); pc += 4; sf->cur_pc = pc; ret = JS_DeleteGlobalVar(ctx, atom); if (unlikely(ret < 0)) goto exception; *sp++ = js_bool(ret); } BREAK; CASE(OP_to_object): if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) { sf->cur_pc = pc; ret_val = JS_ToObject(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret_val; } BREAK; CASE(OP_to_propkey): switch (JS_VALUE_GET_TAG(sp[-1])) { case JS_TAG_INT: case JS_TAG_STRING: case JS_TAG_SYMBOL: break; default: sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret_val; break; } BREAK; CASE(OP_to_propkey2): /* must be tested first */ if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) { JS_ThrowTypeError(ctx, "value has no property"); goto exception; } switch (JS_VALUE_GET_TAG(sp[-1])) { case JS_TAG_INT: case JS_TAG_STRING: case JS_TAG_SYMBOL: break; default: sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret_val; break; } BREAK; CASE(OP_with_get_var): CASE(OP_with_put_var): CASE(OP_with_delete_var): CASE(OP_with_make_ref): CASE(OP_with_get_ref): CASE(OP_with_get_ref_undef): { JSAtom atom; int32_t diff; JSValue obj, val; int ret, is_with; atom = get_u32(pc); diff = get_u32(pc + 4); is_with = pc[8]; pc += 9; sf->cur_pc = pc; obj = sp[-1]; ret = JS_HasProperty(ctx, obj, atom); if (unlikely(ret < 0)) goto exception; if (ret) { if (is_with) { ret = js_has_unscopable(ctx, obj, atom); if (unlikely(ret < 0)) goto exception; if (ret) goto no_with; } switch (opcode) { case OP_with_get_var: val = JS_GetProperty(ctx, obj, atom); if (unlikely(JS_IsException(val))) goto exception; set_value(ctx, &sp[-1], val); break; case OP_with_put_var: /* XXX: check if strict mode */ ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-1]); sp -= 2; if (unlikely(ret < 0)) goto exception; break; case OP_with_delete_var: ret = JS_DeleteProperty(ctx, obj, atom, 0); if (unlikely(ret < 0)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = js_bool(ret); break; case OP_with_make_ref: /* produce a pair object/propname on the stack */ *sp++ = JS_AtomToValue(ctx, atom); break; case OP_with_get_ref: /* produce a pair object/method on the stack */ val = JS_GetProperty(ctx, obj, atom); if (unlikely(JS_IsException(val))) goto exception; *sp++ = val; break; case OP_with_get_ref_undef: /* produce a pair undefined/function on the stack */ val = JS_GetProperty(ctx, obj, atom); if (unlikely(JS_IsException(val))) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = JS_UNDEFINED; *sp++ = val; break; } pc += diff - 5; } else { no_with: /* if not jumping, drop the object argument */ JS_FreeValue(ctx, sp[-1]); sp--; } } BREAK; CASE(OP_await): ret_val = js_int32(FUNC_RET_AWAIT); goto done_generator; CASE(OP_yield): ret_val = js_int32(FUNC_RET_YIELD); goto done_generator; CASE(OP_yield_star): CASE(OP_async_yield_star): ret_val = js_int32(FUNC_RET_YIELD_STAR); goto done_generator; CASE(OP_return_async): CASE(OP_initial_yield): ret_val = JS_UNDEFINED; goto done_generator; CASE(OP_nop): BREAK; CASE(OP_is_undefined_or_null): if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED || JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) { goto set_true; } else { goto free_and_set_false; } CASE(OP_is_undefined): if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED) { goto set_true; } else { goto free_and_set_false; } CASE(OP_is_null): if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) { goto set_true; } else { goto free_and_set_false; } /* XXX: could merge to a single opcode */ CASE(OP_typeof_is_undefined): /* different from OP_is_undefined because of isHTMLDDA */ if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_undefined) { goto free_and_set_true; } else { goto free_and_set_false; } CASE(OP_typeof_is_function): if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) { goto free_and_set_true; } else { goto free_and_set_false; } free_and_set_true: JS_FreeValue(ctx, sp[-1]); set_true: sp[-1] = JS_TRUE; BREAK; free_and_set_false: JS_FreeValue(ctx, sp[-1]); sp[-1] = JS_FALSE; BREAK; CASE(OP_invalid): DEFAULT: JS_ThrowInternalError(ctx, "invalid opcode: pc=%u opcode=0x%02x", (int)(pc - b->byte_code_buf - 1), opcode); goto exception; } } exception: if (needs_backtrace(rt->current_exception) || JS_IsUndefined(ctx->error_back_trace)) { sf->cur_pc = pc; build_backtrace(ctx, rt->current_exception, JS_UNDEFINED, NULL, 0, 0, 0); } if (!JS_IsUncatchableError(rt->current_exception)) { while (sp > stack_buf) { JSValue val = *--sp; JS_FreeValue(ctx, val); if (JS_VALUE_GET_TAG(val) == JS_TAG_CATCH_OFFSET) { int pos = JS_VALUE_GET_INT(val); if (pos == 0) { /* enumerator: close it with a throw */ JS_FreeValue(ctx, sp[-1]); /* drop the next method */ sp--; JS_IteratorClose(ctx, sp[-1], true); } else { *sp++ = rt->current_exception; rt->current_exception = JS_UNINITIALIZED; JS_FreeValueRT(rt, ctx->error_back_trace); ctx->error_back_trace = JS_UNDEFINED; pc = b->byte_code_buf + pos; goto restart; } } } } ret_val = JS_EXCEPTION; /* the local variables are freed by the caller in the generator case. Hence the label 'done' should never be reached in a generator function. */ if (b->func_kind != JS_FUNC_NORMAL) { done_generator: sf->cur_pc = pc; sf->cur_sp = sp; } else { done: if (unlikely(!list_empty(&sf->var_ref_list))) { /* variable references reference the stack: must close them */ close_var_refs(rt, sf); } /* free the local variables and stack */ for(pval = local_buf; pval < sp; pval++) { JS_FreeValue(ctx, *pval); } } rt->current_stack_frame = sf->prev_frame; if (ctx->handleFunctionExited) ctx->handleFunctionExited(ctx); return ret_val; } JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) { return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, argc, argv, JS_CALL_FLAG_COPY_ARGV); } static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) { JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, argc, argv, JS_CALL_FLAG_COPY_ARGV); JS_FreeValue(ctx, func_obj); return res; } /* warning: the refcount of the context is not incremented. Return NULL in case of exception (case of revoked proxy only) */ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) { JSObject *p; JSContext *realm; if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) return ctx; p = JS_VALUE_GET_OBJ(func_obj); switch(p->class_id) { case JS_CLASS_C_FUNCTION: realm = p->u.cfunc.realm; break; case JS_CLASS_BYTECODE_FUNCTION: case JS_CLASS_GENERATOR_FUNCTION: case JS_CLASS_ASYNC_FUNCTION: case JS_CLASS_ASYNC_GENERATOR_FUNCTION: { JSFunctionBytecode *b; b = p->u.func.function_bytecode; realm = b->realm; } break; case JS_CLASS_PROXY: { JSProxyData *s = p->u.opaque; if (!s) return ctx; if (s->is_revoked) { JS_ThrowTypeErrorRevokedProxy(ctx); return NULL; } else { realm = JS_GetFunctionRealm(ctx, s->target); } } break; case JS_CLASS_BOUND_FUNCTION: { JSBoundFunction *bf = p->u.bound_function; realm = JS_GetFunctionRealm(ctx, bf->func_obj); } break; default: realm = ctx; break; } return realm; } static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, int class_id) { JSValue proto, obj; JSContext *realm; if (JS_IsUndefined(ctor)) { proto = js_dup(ctx->class_proto[class_id]); } else { proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype); if (JS_IsException(proto)) return proto; if (!JS_IsObject(proto)) { JS_FreeValue(ctx, proto); realm = JS_GetFunctionRealm(ctx, ctor); if (!realm) return JS_EXCEPTION; proto = js_dup(realm->class_proto[class_id]); } } obj = JS_NewObjectProtoClass(ctx, proto, class_id); JS_FreeValue(ctx, proto); return obj; } /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */ static JSValue JS_CallConstructorInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, int argc, JSValueConst *argv, int flags) { JSObject *p; JSFunctionBytecode *b; if (js_poll_interrupts(ctx)) return JS_EXCEPTION; flags |= JS_CALL_FLAG_CONSTRUCTOR; if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) goto not_a_function; p = JS_VALUE_GET_OBJ(func_obj); if (unlikely(!p->is_constructor)) return JS_ThrowTypeErrorNotAConstructor(ctx, func_obj); if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) { JSClassCall *call_func; call_func = ctx->rt->class_array[p->class_id].call; if (!call_func) { not_a_function: return JS_ThrowTypeErrorNotAFunction(ctx); } return call_func(ctx, func_obj, new_target, argc, argv, flags); } b = p->u.func.function_bytecode; if (b->is_derived_class_constructor) { return JS_CallInternal(ctx, func_obj, JS_UNDEFINED, new_target, argc, argv, flags); } else { JSValue obj, ret; /* legacy constructor behavior */ obj = js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT); if (JS_IsException(obj)) return JS_EXCEPTION; ret = JS_CallInternal(ctx, func_obj, obj, new_target, argc, argv, flags); if (JS_VALUE_GET_TAG(ret) == JS_TAG_OBJECT || JS_IsException(ret)) { JS_FreeValue(ctx, obj); return ret; } else { JS_FreeValue(ctx, ret); return obj; } } } JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, int argc, JSValueConst *argv) { return JS_CallConstructorInternal(ctx, func_obj, new_target, argc, argv, JS_CALL_FLAG_COPY_ARGV); } JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, int argc, JSValueConst *argv) { return JS_CallConstructorInternal(ctx, func_obj, func_obj, argc, argv, JS_CALL_FLAG_COPY_ARGV); } JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, int argc, JSValueConst *argv) { JSValue func_obj; func_obj = JS_GetProperty(ctx, this_val, atom); if (JS_IsException(func_obj)) return func_obj; return JS_CallFree(ctx, func_obj, this_val, argc, argv); } static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, int argc, JSValueConst *argv) { JSValue res = JS_Invoke(ctx, this_val, atom, argc, argv); JS_FreeValue(ctx, this_val); return res; } /* JSAsyncFunctionState (used by generator and async functions) */ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) { JSObject *p; JSFunctionBytecode *b; JSStackFrame *sf; int local_count, i, arg_buf_len, n; sf = &s->frame; init_list_head(&sf->var_ref_list); p = JS_VALUE_GET_OBJ(func_obj); b = p->u.func.function_bytecode; sf->is_strict_mode = b->is_strict_mode; sf->cur_pc = b->byte_code_buf; arg_buf_len = max_int(b->arg_count, argc); local_count = arg_buf_len + b->var_count + b->stack_size; sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1)); if (!sf->arg_buf) return -1; sf->cur_func = js_dup(func_obj); s->this_val = js_dup(this_obj); s->argc = argc; sf->arg_count = arg_buf_len; sf->var_buf = sf->arg_buf + arg_buf_len; sf->cur_sp = sf->var_buf + b->var_count; for(i = 0; i < argc; i++) sf->arg_buf[i] = js_dup(argv[i]); n = arg_buf_len + b->var_count; for(i = argc; i < n; i++) sf->arg_buf[i] = JS_UNDEFINED; return 0; } static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, JS_MarkFunc *mark_func) { JSStackFrame *sf; JSValue *sp; sf = &s->frame; JS_MarkValue(rt, sf->cur_func, mark_func); JS_MarkValue(rt, s->this_val, mark_func); if (sf->cur_sp) { /* if the function is running, cur_sp is not known so we cannot mark the stack. Marking the variables is not needed because a running function cannot be part of a removable cycle */ for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) JS_MarkValue(rt, *sp, mark_func); } } static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) { JSStackFrame *sf; JSValue *sp; sf = &s->frame; /* close the closure variables. */ close_var_refs(rt, sf); if (sf->arg_buf) { /* cannot free the function if it is running */ assert(sf->cur_sp != NULL); for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) { JS_FreeValueRT(rt, *sp); } js_free_rt(rt, sf->arg_buf); } JS_FreeValueRT(rt, sf->cur_func); JS_FreeValueRT(rt, s->this_val); } static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) { JSValue func_obj; if (js_check_stack_overflow(ctx->rt, 0)) return JS_ThrowStackOverflow(ctx); /* the tag does not matter provided it is not an object */ func_obj = JS_MKPTR(JS_TAG_INT, s); return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED, s->argc, vc(s->frame.arg_buf), JS_CALL_FLAG_GENERATOR); } /* Generators */ typedef enum JSGeneratorStateEnum { JS_GENERATOR_STATE_SUSPENDED_START, JS_GENERATOR_STATE_SUSPENDED_YIELD, JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR, JS_GENERATOR_STATE_EXECUTING, JS_GENERATOR_STATE_COMPLETED, } JSGeneratorStateEnum; typedef struct JSGeneratorData { JSGeneratorStateEnum state; JSAsyncFunctionState func_state; } JSGeneratorData; static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s) { if (s->state == JS_GENERATOR_STATE_COMPLETED) return; async_func_free(rt, &s->func_state); s->state = JS_GENERATOR_STATE_COMPLETED; } static void js_generator_finalizer(JSRuntime *rt, JSValueConst obj) { JSGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_GENERATOR); if (s) { free_generator_stack_rt(rt, s); js_free_rt(rt, s); } } static void free_generator_stack(JSContext *ctx, JSGeneratorData *s) { free_generator_stack_rt(ctx->rt, s); } static void js_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSGeneratorData *s = p->u.generator_data; if (!s || s->state == JS_GENERATOR_STATE_COMPLETED) return; async_func_mark(rt, &s->func_state, mark_func); } /* XXX: use enum */ #define GEN_MAGIC_NEXT 0 #define GEN_MAGIC_RETURN 1 #define GEN_MAGIC_THROW 2 static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int *pdone, int magic) { JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR); JSStackFrame *sf; JSValue ret, func_ret; *pdone = true; if (!s) return JS_ThrowTypeError(ctx, "not a generator"); sf = &s->func_state.frame; switch(s->state) { default: case JS_GENERATOR_STATE_SUSPENDED_START: if (magic == GEN_MAGIC_NEXT) { goto exec_no_arg; } else { free_generator_stack(ctx, s); goto done; } break; case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR: case JS_GENERATOR_STATE_SUSPENDED_YIELD: /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */ ret = js_dup(argv[0]); if (magic == GEN_MAGIC_THROW && s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) { JS_Throw(ctx, ret); s->func_state.throw_flag = true; } else { sf->cur_sp[-1] = ret; sf->cur_sp[0] = js_int32(magic); sf->cur_sp++; exec_no_arg: s->func_state.throw_flag = false; } s->state = JS_GENERATOR_STATE_EXECUTING; func_ret = async_func_resume(ctx, &s->func_state); s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD; if (JS_IsException(func_ret)) { /* finalize the execution in case of exception */ free_generator_stack(ctx, s); return func_ret; } if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) { /* get the returned yield value at the top of the stack */ ret = sf->cur_sp[-1]; sf->cur_sp[-1] = JS_UNDEFINED; if (JS_VALUE_GET_INT(func_ret) == FUNC_RET_YIELD_STAR) { s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR; /* return (value, done) object */ *pdone = 2; } else { *pdone = false; } } else { /* end of iterator */ ret = sf->cur_sp[-1]; sf->cur_sp[-1] = JS_UNDEFINED; JS_FreeValue(ctx, func_ret); free_generator_stack(ctx, s); } break; case JS_GENERATOR_STATE_COMPLETED: done: /* execution is finished */ switch(magic) { default: case GEN_MAGIC_NEXT: ret = JS_UNDEFINED; break; case GEN_MAGIC_RETURN: ret = js_dup(argv[0]); break; case GEN_MAGIC_THROW: ret = JS_Throw(ctx, js_dup(argv[0])); break; } break; case JS_GENERATOR_STATE_EXECUTING: ret = JS_ThrowTypeError(ctx, "cannot invoke a running generator"); break; } return ret; } static JSValue js_call_generator_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSValue obj, func_ret; JSGeneratorData *s; s = js_mallocz(ctx, sizeof(*s)); if (!s) return JS_EXCEPTION; s->state = JS_GENERATOR_STATE_SUSPENDED_START; if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { s->state = JS_GENERATOR_STATE_COMPLETED; goto fail; } /* execute the function up to 'OP_initial_yield' */ func_ret = async_func_resume(ctx, &s->func_state); if (JS_IsException(func_ret)) goto fail; JS_FreeValue(ctx, func_ret); obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR); if (JS_IsException(obj)) goto fail; JS_SetOpaqueInternal(obj, s); return obj; fail: free_generator_stack_rt(ctx->rt, s); js_free(ctx, s); return JS_EXCEPTION; } /* AsyncFunction */ static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s) { if (s->is_active) { async_func_free(rt, &s->func_state); s->is_active = false; } } static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s) { js_async_function_terminate(rt, s); JS_FreeValueRT(rt, s->resolving_funcs[0]); JS_FreeValueRT(rt, s->resolving_funcs[1]); remove_gc_object(&s->header); js_free_rt(rt, s); } static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s) { if (--s->header.ref_count == 0) { js_async_function_free0(rt, s); } } static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSAsyncFunctionData *s = p->u.async_function_data; if (s) { js_async_function_free(rt, s); } } static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSAsyncFunctionData *s = p->u.async_function_data; if (s) { mark_func(rt, &s->header); } } static int js_async_function_resolve_create(JSContext *ctx, JSAsyncFunctionData *s, JSValue *resolving_funcs) { int i; JSObject *p; for(i = 0; i < 2; i++) { resolving_funcs[i] = JS_NewObjectProtoClass(ctx, ctx->function_proto, JS_CLASS_ASYNC_FUNCTION_RESOLVE + i); if (JS_IsException(resolving_funcs[i])) { if (i == 1) JS_FreeValue(ctx, resolving_funcs[0]); return -1; } p = JS_VALUE_GET_OBJ(resolving_funcs[i]); s->header.ref_count++; p->u.async_function_data = s; } return 0; } static bool js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s) { bool is_success = true; JSValue func_ret, ret2; func_ret = async_func_resume(ctx, &s->func_state); if (JS_IsException(func_ret)) { fail: if (unlikely(JS_IsUncatchableError(ctx->rt->current_exception))) { is_success = false; } else { JSValue error = JS_GetException(ctx); ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED, 1, vc(&error)); JS_FreeValue(ctx, error); resolved: if (unlikely(JS_IsException(ret2))) { if (JS_IsUncatchableError(ctx->rt->current_exception)) { is_success = false; } else { abort(); /* BUG */ } } JS_FreeValue(ctx, ret2); } js_async_function_terminate(ctx->rt, s); } else { JSValue value; value = s->func_state.frame.cur_sp[-1]; s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; if (JS_IsUndefined(func_ret)) { /* function returned */ ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED, 1, vc(&value)); JS_FreeValue(ctx, value); goto resolved; } else { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int i, res; /* await */ JS_FreeValue(ctx, func_ret); /* not used */ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&value), 0); JS_FreeValue(ctx, value); if (JS_IsException(promise)) goto fail; if (js_async_function_resolve_create(ctx, s, resolving_funcs)) { JS_FreeValue(ctx, promise); goto fail; } /* Note: no need to create 'thrownawayCapability' as in the spec */ for(i = 0; i < 2; i++) resolving_funcs1[i] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, vc(resolving_funcs), vc(resolving_funcs1)); JS_FreeValue(ctx, promise); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); if (res) goto fail; } } return is_success; } static JSValue js_async_function_resolve_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSObject *p = JS_VALUE_GET_OBJ(func_obj); JSAsyncFunctionData *s = p->u.async_function_data; bool is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE; JSValueConst arg; if (argc > 0) arg = argv[0]; else arg = JS_UNDEFINED; s->func_state.throw_flag = is_reject; if (is_reject) { JS_Throw(ctx, js_dup(arg)); } else { /* return value of await */ s->func_state.frame.cur_sp[-1] = js_dup(arg); } if (!js_async_function_resume(ctx, s)) return JS_EXCEPTION; return JS_UNDEFINED; } static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSValue promise; JSAsyncFunctionData *s; s = js_mallocz(ctx, sizeof(*s)); if (!s) return JS_EXCEPTION; s->header.ref_count = 1; add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION); s->is_active = false; s->resolving_funcs[0] = JS_UNDEFINED; s->resolving_funcs[1] = JS_UNDEFINED; promise = JS_NewPromiseCapability(ctx, s->resolving_funcs); if (JS_IsException(promise)) goto fail; if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { fail: JS_FreeValue(ctx, promise); js_async_function_free(ctx->rt, s); return JS_EXCEPTION; } s->is_active = true; if (!js_async_function_resume(ctx, s)) goto fail; js_async_function_free(ctx->rt, s); return promise; } /* AsyncGenerator */ typedef enum JSAsyncGeneratorStateEnum { JS_ASYNC_GENERATOR_STATE_SUSPENDED_START, JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD, JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR, JS_ASYNC_GENERATOR_STATE_EXECUTING, JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN, JS_ASYNC_GENERATOR_STATE_COMPLETED, } JSAsyncGeneratorStateEnum; typedef struct JSAsyncGeneratorRequest { struct list_head link; /* completion */ int completion_type; /* GEN_MAGIC_x */ JSValue result; /* promise capability */ JSValue promise; JSValue resolving_funcs[2]; } JSAsyncGeneratorRequest; typedef struct JSAsyncGeneratorData { JSObject *generator; /* back pointer to the object (const) */ JSAsyncGeneratorStateEnum state; JSAsyncFunctionState func_state; struct list_head queue; /* list of JSAsyncGeneratorRequest.link */ } JSAsyncGeneratorData; static void js_async_generator_free(JSRuntime *rt, JSAsyncGeneratorData *s) { struct list_head *el, *el1; JSAsyncGeneratorRequest *req; list_for_each_safe(el, el1, &s->queue) { req = list_entry(el, JSAsyncGeneratorRequest, link); JS_FreeValueRT(rt, req->result); JS_FreeValueRT(rt, req->promise); JS_FreeValueRT(rt, req->resolving_funcs[0]); JS_FreeValueRT(rt, req->resolving_funcs[1]); js_free_rt(rt, req); } if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED && s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) { async_func_free(rt, &s->func_state); } js_free_rt(rt, s); } static void js_async_generator_finalizer(JSRuntime *rt, JSValueConst obj) { JSAsyncGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_ASYNC_GENERATOR); if (s) { js_async_generator_free(rt, s); } } static void js_async_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSAsyncGeneratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_GENERATOR); struct list_head *el; JSAsyncGeneratorRequest *req; if (s) { list_for_each(el, &s->queue) { req = list_entry(el, JSAsyncGeneratorRequest, link); JS_MarkValue(rt, req->result, mark_func); JS_MarkValue(rt, req->promise, mark_func); JS_MarkValue(rt, req->resolving_funcs[0], mark_func); JS_MarkValue(rt, req->resolving_funcs[1], mark_func); } if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED && s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) { async_func_mark(rt, &s->func_state, mark_func); } } } static JSValue js_async_generator_resolve_function(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv, int magic, JSValueConst *func_data); static int js_async_generator_resolve_function_create(JSContext *ctx, JSValue generator, JSValue *resolving_funcs, bool is_resume_next) { int i; JSValue func; for(i = 0; i < 2; i++) { func = JS_NewCFunctionData(ctx, js_async_generator_resolve_function, 1, i + is_resume_next * 2, 1, vc(&generator)); if (JS_IsException(func)) { if (i == 1) JS_FreeValue(ctx, resolving_funcs[0]); return -1; } resolving_funcs[i] = func; } return 0; } static int js_async_generator_await(JSContext *ctx, JSAsyncGeneratorData *s, JSValue value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int i, res; promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&value), 0); if (JS_IsException(promise)) goto fail; if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs, false)) { JS_FreeValue(ctx, promise); goto fail; } /* Note: no need to create 'thrownawayCapability' as in the spec */ for(i = 0; i < 2; i++) resolving_funcs1[i] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, vc(resolving_funcs), vc(resolving_funcs1)); JS_FreeValue(ctx, promise); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); if (res) goto fail; return 0; fail: return -1; } static void js_async_generator_resolve_or_reject(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst result, int is_reject) { JSAsyncGeneratorRequest *next; JSValue ret; next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link); list_del(&next->link); ret = JS_Call(ctx, next->resolving_funcs[is_reject], JS_UNDEFINED, 1, &result); JS_FreeValue(ctx, ret); JS_FreeValue(ctx, next->result); JS_FreeValue(ctx, next->promise); JS_FreeValue(ctx, next->resolving_funcs[0]); JS_FreeValue(ctx, next->resolving_funcs[1]); js_free(ctx, next); } static void js_async_generator_resolve(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst value, bool done) { JSValue result; result = js_create_iterator_result(ctx, js_dup(value), done); /* XXX: better exception handling ? */ js_async_generator_resolve_or_reject(ctx, s, result, 0); JS_FreeValue(ctx, result); } static void js_async_generator_reject(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst exception) { js_async_generator_resolve_or_reject(ctx, s, exception, 1); } static void js_async_generator_complete(JSContext *ctx, JSAsyncGeneratorData *s) { if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) { s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; async_func_free(ctx->rt, &s->func_state); } } static int js_async_generator_completed_return(JSContext *ctx, JSAsyncGeneratorData *s, JSValue value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int res; // Can fail looking up JS_ATOM_constructor when is_reject==0. promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&value), /*is_reject*/0); // A poisoned .constructor property is observable and the resulting // exception should be delivered to the catch handler. if (JS_IsException(promise)) { JSValue err = JS_GetException(ctx); promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&err), /*is_reject*/1); JS_FreeValue(ctx, err); if (JS_IsException(promise)) return -1; } if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs1, true)) { JS_FreeValue(ctx, promise); return -1; } resolving_funcs[0] = JS_UNDEFINED; resolving_funcs[1] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, vc(resolving_funcs1), vc(resolving_funcs)); JS_FreeValue(ctx, resolving_funcs1[0]); JS_FreeValue(ctx, resolving_funcs1[1]); JS_FreeValue(ctx, promise); return res; } static void js_async_generator_resume_next(JSContext *ctx, JSAsyncGeneratorData *s) { JSAsyncGeneratorRequest *next; JSValue func_ret, value; for(;;) { if (list_empty(&s->queue)) break; next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link); switch(s->state) { case JS_ASYNC_GENERATOR_STATE_EXECUTING: /* only happens when restarting execution after await() */ goto resume_exec; case JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN: goto done; case JS_ASYNC_GENERATOR_STATE_SUSPENDED_START: if (next->completion_type == GEN_MAGIC_NEXT) { goto exec_no_arg; } else { js_async_generator_complete(ctx, s); } break; case JS_ASYNC_GENERATOR_STATE_COMPLETED: if (next->completion_type == GEN_MAGIC_NEXT) { js_async_generator_resolve(ctx, s, JS_UNDEFINED, true); } else if (next->completion_type == GEN_MAGIC_RETURN) { s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN; js_async_generator_completed_return(ctx, s, next->result); } else { js_async_generator_reject(ctx, s, next->result); } goto done; case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD: case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR: value = js_dup(next->result); if (next->completion_type == GEN_MAGIC_THROW && s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) { JS_Throw(ctx, value); s->func_state.throw_flag = true; } else { /* 'yield' returns a value. 'yield *' also returns a value in case the 'throw' method is called */ s->func_state.frame.cur_sp[-1] = value; s->func_state.frame.cur_sp[0] = js_int32(next->completion_type); s->func_state.frame.cur_sp++; exec_no_arg: s->func_state.throw_flag = false; } s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING; resume_exec: func_ret = async_func_resume(ctx, &s->func_state); if (JS_IsException(func_ret)) { value = JS_GetException(ctx); js_async_generator_complete(ctx, s); js_async_generator_reject(ctx, s, value); JS_FreeValue(ctx, value); } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) { int func_ret_code, ret; value = s->func_state.frame.cur_sp[-1]; s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; func_ret_code = JS_VALUE_GET_INT(func_ret); switch(func_ret_code) { case FUNC_RET_YIELD: case FUNC_RET_YIELD_STAR: if (func_ret_code == FUNC_RET_YIELD_STAR) s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR; else s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD; js_async_generator_resolve(ctx, s, value, false); JS_FreeValue(ctx, value); break; case FUNC_RET_AWAIT: ret = js_async_generator_await(ctx, s, value); JS_FreeValue(ctx, value); if (ret < 0) { /* exception: throw it */ s->func_state.throw_flag = true; goto resume_exec; } goto done; default: abort(); } } else { assert(JS_IsUndefined(func_ret)); /* end of function */ value = s->func_state.frame.cur_sp[-1]; s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; js_async_generator_complete(ctx, s); js_async_generator_resolve(ctx, s, value, true); JS_FreeValue(ctx, value); } break; default: abort(); } } done: ; } static JSValue js_async_generator_resolve_function(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv, int magic, JSValueConst *func_data) { bool is_reject = magic & 1; JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR); JSValueConst arg = argv[0]; /* XXX: what if s == NULL */ if (magic >= 2) { /* resume next case in AWAITING_RETURN state */ assert(s->state == JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN || s->state == JS_ASYNC_GENERATOR_STATE_COMPLETED); s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; if (is_reject) { js_async_generator_reject(ctx, s, arg); } else { js_async_generator_resolve(ctx, s, arg, true); } } else { /* restart function execution after await() */ assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING); s->func_state.throw_flag = is_reject; if (is_reject) { JS_Throw(ctx, js_dup(arg)); } else { /* return value of await */ s->func_state.frame.cur_sp[-1] = js_dup(arg); } js_async_generator_resume_next(ctx, s); } return JS_UNDEFINED; } /* magic = GEN_MAGIC_x */ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSAsyncGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_GENERATOR); JSValue promise, resolving_funcs[2]; JSAsyncGeneratorRequest *req; promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; if (!s) { JSValue err, res2; JS_ThrowTypeError(ctx, "not an AsyncGenerator object"); err = JS_GetException(ctx); res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&err)); JS_FreeValue(ctx, err); JS_FreeValue(ctx, res2); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); return promise; } req = js_mallocz(ctx, sizeof(*req)); if (!req) goto fail; req->completion_type = magic; req->result = js_dup(argv[0]); req->promise = js_dup(promise); req->resolving_funcs[0] = resolving_funcs[0]; req->resolving_funcs[1] = resolving_funcs[1]; list_add_tail(&req->link, &s->queue); if (s->state != JS_ASYNC_GENERATOR_STATE_EXECUTING) { js_async_generator_resume_next(ctx, s); } return promise; fail: JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); JS_FreeValue(ctx, promise); return JS_EXCEPTION; } static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) { JSValue obj, func_ret; JSAsyncGeneratorData *s; s = js_mallocz(ctx, sizeof(*s)); if (!s) return JS_EXCEPTION; s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START; init_list_head(&s->queue); if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; goto fail; } /* execute the function up to 'OP_initial_yield' (no yield nor await are possible) */ func_ret = async_func_resume(ctx, &s->func_state); if (JS_IsException(func_ret)) goto fail; JS_FreeValue(ctx, func_ret); obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_ASYNC_GENERATOR); if (JS_IsException(obj)) goto fail; s->generator = JS_VALUE_GET_OBJ(obj); JS_SetOpaqueInternal(obj, s); return obj; fail: js_async_generator_free(ctx->rt, s); return JS_EXCEPTION; } /* JS parser */ enum { TOK_NUMBER = -128, TOK_STRING, TOK_TEMPLATE, TOK_IDENT, TOK_REGEXP, /* warning: order matters (see js_parse_assign_expr) */ TOK_MUL_ASSIGN, TOK_DIV_ASSIGN, TOK_MOD_ASSIGN, TOK_PLUS_ASSIGN, TOK_MINUS_ASSIGN, TOK_SHL_ASSIGN, TOK_SAR_ASSIGN, TOK_SHR_ASSIGN, TOK_AND_ASSIGN, TOK_XOR_ASSIGN, TOK_OR_ASSIGN, TOK_POW_ASSIGN, TOK_LAND_ASSIGN, TOK_LOR_ASSIGN, TOK_DOUBLE_QUESTION_MARK_ASSIGN, TOK_DEC, TOK_INC, TOK_SHL, TOK_SAR, TOK_SHR, TOK_LT, TOK_LTE, TOK_GT, TOK_GTE, TOK_EQ, TOK_STRICT_EQ, TOK_NEQ, TOK_STRICT_NEQ, TOK_LAND, TOK_LOR, TOK_POW, TOK_ARROW, TOK_ELLIPSIS, TOK_DOUBLE_QUESTION_MARK, TOK_QUESTION_MARK_DOT, TOK_ERROR, TOK_PRIVATE_NAME, TOK_EOF, /* keywords: WARNING: same order as atoms */ TOK_NULL, /* must be first */ TOK_FALSE, TOK_TRUE, TOK_IF, TOK_ELSE, TOK_RETURN, TOK_VAR, TOK_THIS, TOK_DELETE, TOK_VOID, TOK_TYPEOF, TOK_NEW, TOK_IN, TOK_INSTANCEOF, TOK_DO, TOK_WHILE, TOK_FOR, TOK_BREAK, TOK_CONTINUE, TOK_SWITCH, TOK_CASE, TOK_DEFAULT, TOK_THROW, TOK_TRY, TOK_CATCH, TOK_FINALLY, TOK_FUNCTION, TOK_DEBUGGER, TOK_WITH, /* FutureReservedWord */ TOK_CLASS, TOK_CONST, TOK_ENUM, TOK_EXPORT, TOK_EXTENDS, TOK_IMPORT, TOK_SUPER, /* FutureReservedWords when parsing strict mode code */ TOK_IMPLEMENTS, TOK_INTERFACE, TOK_LET, TOK_PACKAGE, TOK_PRIVATE, TOK_PROTECTED, TOK_PUBLIC, TOK_STATIC, TOK_YIELD, TOK_AWAIT, /* must be last */ TOK_OF, /* only used for js_parse_skip_parens_token() */ }; #define TOK_FIRST_KEYWORD TOK_NULL #define TOK_LAST_KEYWORD TOK_AWAIT /* unicode code points */ #define CP_NBSP 0x00a0 #define CP_BOM 0xfeff #define CP_LS 0x2028 #define CP_PS 0x2029 typedef struct BlockEnv { struct BlockEnv *prev; JSAtom label_name; /* JS_ATOM_NULL if none */ int label_break; /* -1 if none */ int label_cont; /* -1 if none */ int drop_count; /* number of stack elements to drop */ int label_finally; /* -1 if none */ int scope_level; uint8_t has_iterator : 1; uint8_t is_regular_stmt : 1; // i.e. not a loop statement } BlockEnv; typedef struct JSGlobalVar { int cpool_idx; /* if >= 0, index in the constant pool for hoisted function defintion*/ uint8_t force_init : 1; /* force initialization to undefined */ uint8_t is_lexical : 1; /* global let/const definition */ uint8_t is_const : 1; /* const definition */ int scope_level; /* scope of definition */ JSAtom var_name; /* variable name */ } JSGlobalVar; typedef struct RelocEntry { struct RelocEntry *next; uint32_t addr; /* address to patch */ int size; /* address size: 1, 2 or 4 bytes */ } RelocEntry; typedef struct JumpSlot { int op; int size; int pos; int label; } JumpSlot; typedef struct LabelSlot { int ref_count; int pos; /* phase 1 address, -1 means not resolved yet */ int pos2; /* phase 2 address, -1 means not resolved yet */ int addr; /* phase 3 address, -1 means not resolved yet */ RelocEntry *first_reloc; } LabelSlot; typedef struct SourceLocSlot { uint32_t pc; int line_num; int col_num; } SourceLocSlot; typedef enum JSParseFunctionEnum { JS_PARSE_FUNC_STATEMENT, JS_PARSE_FUNC_VAR, JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW, JS_PARSE_FUNC_GETTER, JS_PARSE_FUNC_SETTER, JS_PARSE_FUNC_METHOD, JS_PARSE_FUNC_CLASS_STATIC_INIT, JS_PARSE_FUNC_CLASS_CONSTRUCTOR, JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR, } JSParseFunctionEnum; typedef enum JSParseExportEnum { JS_PARSE_EXPORT_NONE, JS_PARSE_EXPORT_NAMED, JS_PARSE_EXPORT_DEFAULT, } JSParseExportEnum; typedef struct JSFunctionDef { JSContext *ctx; struct JSFunctionDef *parent; int parent_cpool_idx; /* index in the constant pool of the parent or -1 if none */ int parent_scope_level; /* scope level in parent at point of definition */ struct list_head child_list; /* list of JSFunctionDef.link */ struct list_head link; bool is_eval; /* true if eval code */ int eval_type; /* only valid if is_eval = true */ bool is_global_var; /* true if variables are not defined locally: eval global, eval module or non strict eval */ bool is_func_expr; /* true if function expression */ bool has_home_object; /* true if the home object is available */ bool has_prototype; /* true if a prototype field is necessary */ bool has_simple_parameter_list; bool has_parameter_expressions; /* if true, an argument scope is created */ bool has_use_strict; /* to reject directive in special cases */ bool has_eval_call; /* true if the function contains a call to eval() */ bool has_arguments_binding; /* true if the 'arguments' binding is available in the function */ bool has_this_binding; /* true if the 'this' and new.target binding are available in the function */ bool new_target_allowed; /* true if the 'new.target' does not throw a syntax error */ bool super_call_allowed; /* true if super() is allowed */ bool super_allowed; /* true if super. or super[] is allowed */ bool arguments_allowed; /* true if the 'arguments' identifier is allowed */ bool is_derived_class_constructor; bool in_function_body; bool backtrace_barrier; JSFunctionKindEnum func_kind : 8; JSParseFunctionEnum func_type : 7; uint8_t is_strict_mode : 1; JSAtom func_name; /* JS_ATOM_NULL if no name */ JSVarDef *vars; uint32_t *vars_htab; // indexes into vars[] int var_size; /* allocated size for vars[] */ int var_count; JSVarDef *args; int arg_size; /* allocated size for args[] */ int arg_count; /* number of arguments */ int defined_arg_count; int var_object_idx; /* -1 if none */ int arg_var_object_idx; /* -1 if none (var object for the argument scope) */ int arguments_var_idx; /* -1 if none */ int arguments_arg_idx; /* argument variable definition in argument scope, -1 if none */ int func_var_idx; /* variable containing the current function (-1 if none, only used if is_func_expr is true) */ int eval_ret_idx; /* variable containing the return value of the eval, -1 if none */ int this_var_idx; /* variable containg the 'this' value, -1 if none */ int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */ int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */ int home_object_var_idx; bool need_home_object; int scope_level; /* index into fd->scopes if the current lexical scope */ int scope_first; /* index into vd->vars of first lexically scoped variable */ int scope_size; /* allocated size of fd->scopes array */ int scope_count; /* number of entries used in the fd->scopes array */ JSVarScope *scopes; JSVarScope def_scope_array[4]; int body_scope; /* scope of the body of the function or eval */ int global_var_count; int global_var_size; JSGlobalVar *global_vars; DynBuf byte_code; int last_opcode_pos; /* -1 if no last opcode */ bool use_short_opcodes; /* true if short opcodes are used in byte_code */ LabelSlot *label_slots; int label_size; /* allocated size for label_slots[] */ int label_count; BlockEnv *top_break; /* break/continue label stack */ /* constant pool (strings, functions, numbers) */ JSValue *cpool; int cpool_count; int cpool_size; /* list of variables in the closure */ int closure_var_count; int closure_var_size; JSClosureVar *closure_var; JumpSlot *jump_slots; int jump_size; int jump_count; SourceLocSlot *source_loc_slots; int source_loc_size; int source_loc_count; int line_number_last; int line_number_last_pc; int col_number_last; /* pc2line table */ JSAtom filename; int line_num; int col_num; DynBuf pc2line; char *source; /* raw source, utf-8 encoded */ int source_len; JSModuleDef *module; /* != NULL when parsing a module */ bool has_await; /* true if await is used (used in module eval) */ } JSFunctionDef; typedef struct JSToken { int val; int line_num; /* line number of token start */ int col_num; /* column number of token start */ const uint8_t *ptr; union { struct { JSValue str; int sep; } str; struct { JSValue val; } num; struct { JSAtom atom; bool has_escape; bool is_reserved; } ident; struct { JSValue body; JSValue flags; } regexp; } u; } JSToken; typedef struct JSParseState { JSContext *ctx; int last_line_num; /* line number of last token */ int last_col_num; /* column number of last token */ int line_num; /* line number of current offset */ int col_num; /* column number of current offset */ const char *filename; JSToken token; bool got_lf; /* true if got line feed before the current token */ const uint8_t *last_ptr; const uint8_t *buf_start; const uint8_t *buf_ptr; const uint8_t *buf_end; const uint8_t *eol; // most recently seen end-of-line character const uint8_t *mark; // first token character, invariant: eol < mark /* current function code */ JSFunctionDef *cur_func; bool is_module; /* parsing a module */ bool allow_html_comments; } JSParseState; typedef struct JSOpCode { #ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* const char *name; #endif uint8_t size; /* in bytes */ /* the opcodes remove n_pop items from the top of the stack, then pushes n_push items */ uint8_t n_pop; uint8_t n_push; uint8_t fmt; } JSOpCode; static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { #define FMT(f) #ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* #define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f }, #else #define DEF(id, size, n_pop, n_push, f) { size, n_pop, n_push, OP_FMT_ ## f }, #endif #include "quickjs-opcode.h" #undef DEF #undef FMT }; /* After the final compilation pass, short opcodes are used. Their opcodes overlap with the temporary opcodes which cannot appear in the final bytecode. Their description is after the temporary opcodes in opcode_info[]. */ #define short_opcode_info(op) \ opcode_info[(op) >= OP_TEMP_START ? \ (op) + (OP_TEMP_END - OP_TEMP_START) : (op)] static void free_token(JSParseState *s, JSToken *token) { switch(token->val) { case TOK_NUMBER: JS_FreeValue(s->ctx, token->u.num.val); break; case TOK_STRING: case TOK_TEMPLATE: JS_FreeValue(s->ctx, token->u.str.str); break; case TOK_REGEXP: JS_FreeValue(s->ctx, token->u.regexp.body); JS_FreeValue(s->ctx, token->u.regexp.flags); break; case TOK_IDENT: case TOK_PRIVATE_NAME: JS_FreeAtom(s->ctx, token->u.ident.atom); break; default: if (token->val >= TOK_FIRST_KEYWORD && token->val <= TOK_LAST_KEYWORD) { JS_FreeAtom(s->ctx, token->u.ident.atom); } break; } } static void __attribute((unused)) dump_token(JSParseState *s, const JSToken *token) { printf("%d:%d ", token->line_num, token->col_num); switch(token->val) { case TOK_NUMBER: { double d; JS_ToFloat64(s->ctx, &d, token->u.num.val); /* no exception possible */ printf("number: %.14g\n", d); } break; case TOK_IDENT: dump_atom: { char buf[ATOM_GET_STR_BUF_SIZE]; printf("ident: '%s'\n", JS_AtomGetStr(s->ctx, buf, sizeof(buf), token->u.ident.atom)); } break; case TOK_STRING: { const char *str; /* XXX: quote the string */ str = JS_ToCString(s->ctx, token->u.str.str); printf("string: '%s'\n", str); JS_FreeCString(s->ctx, str); } break; case TOK_TEMPLATE: { const char *str; str = JS_ToCString(s->ctx, token->u.str.str); printf("template: `%s`\n", str); JS_FreeCString(s->ctx, str); } break; case TOK_REGEXP: { const char *str, *str2; str = JS_ToCString(s->ctx, token->u.regexp.body); str2 = JS_ToCString(s->ctx, token->u.regexp.flags); printf("regexp: '%s' '%s'\n", str, str2); JS_FreeCString(s->ctx, str); JS_FreeCString(s->ctx, str2); } break; case TOK_EOF: printf("eof\n"); break; default: if (s->token.val >= TOK_NULL && s->token.val <= TOK_LAST_KEYWORD) { goto dump_atom; } else if (s->token.val >= 256) { printf("token: %d\n", token->val); } else { printf("token: '%c'\n", token->val); } break; } } int JS_PRINTF_FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, JS_PRINTF_FORMAT const char *fmt, ...) { JSContext *ctx = s->ctx; va_list ap; int backtrace_flags; va_start(ap, fmt); JS_ThrowError2(ctx, JS_SYNTAX_ERROR, false, fmt, ap); va_end(ap); backtrace_flags = 0; if (s->cur_func && s->cur_func->backtrace_barrier) backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL; build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename, s->line_num, s->col_num, backtrace_flags); return -1; } #ifndef QJS_DISABLE_PARSER static __exception int next_token(JSParseState *s); static int js_parse_expect(JSParseState *s, int tok) { char buf[ATOM_GET_STR_BUF_SIZE]; if (s->token.val == tok) return next_token(s); switch(s->token.val) { case TOK_EOF: return js_parse_error(s, "Unexpected end of input"); case TOK_NUMBER: return js_parse_error(s, "Unexpected number"); case TOK_STRING: return js_parse_error(s, "Unexpected string"); case TOK_TEMPLATE: return js_parse_error(s, "Unexpected string template"); case TOK_REGEXP: return js_parse_error(s, "Unexpected regexp"); case TOK_IDENT: return js_parse_error(s, "Unexpected identifier '%s'", JS_AtomGetStr(s->ctx, buf, sizeof(buf), s->token.u.ident.atom)); case TOK_ERROR: return js_parse_error(s, "Invalid or unexpected token"); default: return js_parse_error(s, "Unexpected token '%.*s'", (int)(s->buf_ptr - s->token.ptr), (const char *)s->token.ptr); } } static int js_parse_expect_semi(JSParseState *s) { if (s->token.val != ';') { /* automatic insertion of ';' */ if (s->token.val == TOK_EOF || s->token.val == '}' || s->got_lf) { return 0; } return js_parse_error(s, "expecting '%c'", ';'); } return next_token(s); } static int js_parse_error_reserved_identifier(JSParseState *s) { char buf1[ATOM_GET_STR_BUF_SIZE]; return js_parse_error(s, "'%s' is a reserved identifier", JS_AtomGetStr(s->ctx, buf1, sizeof(buf1), s->token.u.ident.atom)); } static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p) { const uint8_t *p_next; uint32_t c; StringBuffer b_s, *b = &b_s; JSValue str; /* p points to the first byte of the template part */ if (string_buffer_init(s->ctx, b, 32)) goto fail; for(;;) { if (p >= s->buf_end) goto unexpected_eof; c = *p++; if (c == '`') { /* template end part */ break; } if (c == '$' && *p == '{') { /* template start or middle part */ p++; break; } if (c == '\\') { if (string_buffer_putc8(b, c)) goto fail; if (p >= s->buf_end) goto unexpected_eof; c = *p++; } /* newline sequences are normalized as single '\n' bytes */ if (c == '\r') { if (*p == '\n') p++; c = '\n'; } if (c == '\n') { s->line_num++; s->eol = &p[-1]; s->mark = p; } else if (c >= 0x80) { c = utf8_decode(p - 1, &p_next); if (p_next == p) { js_parse_error(s, "invalid UTF-8 sequence"); goto fail; } p = p_next; } if (string_buffer_putc(b, c)) goto fail; } str = string_buffer_end(b); if (JS_IsException(str)) return -1; s->token.val = TOK_TEMPLATE; s->token.u.str.sep = c; s->token.u.str.str = str; s->buf_ptr = p; return 0; unexpected_eof: js_parse_error(s, "unexpected end of string"); fail: string_buffer_free(b); return -1; } static __exception int js_parse_string(JSParseState *s, int sep, bool do_throw, const uint8_t *p, JSToken *token, const uint8_t **pp) { const uint8_t *p_next; int ret; uint32_t c; StringBuffer b_s, *b = &b_s; JSValue str; /* string */ if (string_buffer_init(s->ctx, b, 32)) goto fail; for(;;) { if (p >= s->buf_end) goto invalid_char; c = *p; if (c < 0x20) { if (sep == '`') { if (c == '\r') { if (p[1] == '\n') p++; c = '\n'; } /* do not update s->line_num */ } else if (c == '\n' || c == '\r') goto invalid_char; } p++; if (c == sep) break; if (c == '$' && *p == '{' && sep == '`') { /* template start or middle part */ p++; break; } if (c == '\\') { c = *p; switch(c) { case '\0': if (p >= s->buf_end) { if (sep != '`') goto invalid_char; if (do_throw) js_parse_error(s, "Unexpected end of input"); goto fail; } p++; break; case '\'': case '\"': case '\\': p++; break; case '\r': /* accept DOS and MAC newline sequences */ if (p[1] == '\n') { p++; } /* fall thru */ case '\n': /* ignore escaped newline sequence */ p++; if (sep != '`') { s->line_num++; s->eol = &p[-1]; s->mark = p; } continue; default: if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) { /* accept isolated \0 */ p++; c = '\0'; } else if ((c >= '0' && c <= '9') && (s->cur_func->is_strict_mode || sep == '`')) { if (do_throw) { js_parse_error(s, "%s are not allowed in %s", (c >= '8') ? "\\8 and \\9" : "Octal escape sequences", (sep == '`') ? "template strings" : "strict mode"); } goto fail; } else if (c >= 0x80) { c = utf8_decode(p, &p_next); if (p_next == p + 1) { goto invalid_utf8; } p = p_next; /* LS or PS are skipped */ if (c == CP_LS || c == CP_PS) continue; } else { ret = lre_parse_escape(&p, true); if (ret == -1) { if (do_throw) { js_parse_error(s, "Invalid %s escape sequence", c == 'u' ? "Unicode" : "hexadecimal"); } goto fail; } else if (ret < 0) { /* ignore the '\' (could output a warning) */ p++; } else { c = ret; } } break; } } else if (c >= 0x80) { c = utf8_decode(p - 1, &p_next); if (p_next == p) goto invalid_utf8; p = p_next; } if (string_buffer_putc(b, c)) goto fail; } str = string_buffer_end(b); if (JS_IsException(str)) return -1; token->val = TOK_STRING; token->u.str.sep = c; token->u.str.str = str; *pp = p; return 0; invalid_utf8: if (do_throw) js_parse_error(s, "invalid UTF-8 sequence"); goto fail; invalid_char: if (do_throw) js_parse_error(s, "unexpected end of string"); fail: string_buffer_free(b); return -1; } static inline bool token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { return s->token.val == TOK_IDENT && s->token.u.ident.atom == atom && !s->token.u.ident.has_escape; } static __exception int js_parse_regexp(JSParseState *s) { const uint8_t *p, *p_next; bool in_class; StringBuffer b_s, *b = &b_s; StringBuffer b2_s, *b2 = &b2_s; uint32_t c; JSValue body_str, flags_str; p = s->buf_ptr; p++; in_class = false; if (string_buffer_init(s->ctx, b, 32)) return -1; if (string_buffer_init(s->ctx, b2, 1)) goto fail; for(;;) { if (p >= s->buf_end) { eof_error: js_parse_error(s, "unexpected end of regexp"); goto fail; } c = *p++; if (c == '\n' || c == '\r') { goto eol_error; } else if (c == '/') { if (!in_class) break; } else if (c == '[') { in_class = true; } else if (c == ']') { /* XXX: incorrect as the first character in a class */ in_class = false; } else if (c == '\\') { if (string_buffer_putc8(b, c)) goto fail; c = *p++; if (c == '\n' || c == '\r') goto eol_error; else if (c == '\0' && p >= s->buf_end) goto eof_error; else if (c >= 0x80) { c = utf8_decode(p - 1, &p_next); if (p_next == p) { goto invalid_utf8; } p = p_next; if (c == CP_LS || c == CP_PS) goto eol_error; } } else if (c >= 0x80) { c = utf8_decode(p - 1, &p_next); if (p_next == p) { invalid_utf8: js_parse_error(s, "invalid UTF-8 sequence"); goto fail; } p = p_next; /* LS or PS are considered as line terminator */ if (c == CP_LS || c == CP_PS) { eol_error: js_parse_error(s, "unexpected line terminator in regexp"); goto fail; } } if (string_buffer_putc(b, c)) goto fail; } /* flags */ for(;;) { c = utf8_decode(p, &p_next); /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ if (!lre_js_is_ident_next(c)) break; if (string_buffer_putc(b2, c)) goto fail; p = p_next; } body_str = string_buffer_end(b); flags_str = string_buffer_end(b2); if (JS_IsException(body_str) || JS_IsException(flags_str)) { JS_FreeValue(s->ctx, body_str); JS_FreeValue(s->ctx, flags_str); return -1; } s->token.val = TOK_REGEXP; s->token.u.regexp.body = body_str; s->token.u.regexp.flags = flags_str; s->buf_ptr = p; return 0; fail: string_buffer_free(b); string_buffer_free(b2); return -1; } #endif // QJS_DISABLE_PARSER static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, char *static_buf) { char *buf, *new_buf; size_t size, new_size; buf = *pbuf; size = *psize; if (size >= (SIZE_MAX / 3) * 2) new_size = SIZE_MAX; else new_size = size + (size >> 1); if (buf == static_buf) { new_buf = js_malloc(ctx, new_size); if (!new_buf) return -1; memcpy(new_buf, buf, size); } else { new_buf = js_realloc(ctx, buf, new_size); if (!new_buf) return -1; } *pbuf = new_buf; *psize = new_size; return 0; } #ifndef QJS_DISABLE_PARSER /* convert a TOK_IDENT to a keyword when needed */ static void update_token_ident(JSParseState *s) { if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && s->cur_func->is_strict_mode) || (s->token.u.ident.atom == JS_ATOM_yield && ((s->cur_func->func_kind & JS_FUNC_GENERATOR) || (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && !s->cur_func->in_function_body && s->cur_func->parent && (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) || (s->token.u.ident.atom == JS_ATOM_await && (s->is_module || (s->cur_func->func_kind & JS_FUNC_ASYNC) || s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT || (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && !s->cur_func->in_function_body && s->cur_func->parent && ((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) || s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) { if (s->token.u.ident.has_escape) { s->token.u.ident.is_reserved = true; s->token.val = TOK_IDENT; } else { /* The keywords atoms are pre allocated */ s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD; } } } /* if the current token is an identifier or keyword, reparse it according to the current function type */ static void reparse_ident_token(JSParseState *s) { if (s->token.val == TOK_IDENT || (s->token.val >= TOK_FIRST_KEYWORD && s->token.val <= TOK_LAST_KEYWORD)) { s->token.val = TOK_IDENT; s->token.u.ident.is_reserved = false; update_token_ident(s); } } /* 'c' is the first character. Return JS_ATOM_NULL in case of error */ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, bool *pident_has_escape, int c, bool is_private) { const uint8_t *p, *p_next; char ident_buf[128], *buf; size_t ident_size, ident_pos; JSAtom atom = JS_ATOM_NULL; p = *pp; buf = ident_buf; ident_size = sizeof(ident_buf); ident_pos = 0; if (is_private) buf[ident_pos++] = '#'; for(;;) { if (c < 0x80) { buf[ident_pos++] = c; } else { ident_pos += utf8_encode((uint8_t*)buf + ident_pos, c); } c = *p; p_next = p + 1; if (c == '\\' && *p_next == 'u') { c = lre_parse_escape(&p_next, true); *pident_has_escape = true; } else if (c >= 0x80) { c = utf8_decode(p, &p_next); /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ } if (!lre_js_is_ident_next(c)) break; p = p_next; if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) goto done; } } /* buf is pure ASCII or UTF-8 encoded */ atom = JS_NewAtomLen(s->ctx, buf, ident_pos); done: if (unlikely(buf != ident_buf)) js_free(s->ctx, buf); *pp = p; return atom; } static __exception int next_token(JSParseState *s) { const uint8_t *p, *p_next; int c; bool ident_has_escape; JSAtom atom; if (js_check_stack_overflow(s->ctx->rt, 1000)) { JS_ThrowStackOverflow(s->ctx); return -1; } free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; s->got_lf = false; s->last_line_num = s->token.line_num; s->last_col_num = s->token.col_num; redo: s->token.line_num = s->line_num; s->token.col_num = s->col_num; s->token.ptr = p; c = *p; switch(c) { case 0: if (p >= s->buf_end) { s->token.val = TOK_EOF; } else { goto def_token; } break; case '`': if (js_parse_template_part(s, p + 1)) goto fail; p = s->buf_ptr; break; case '\'': case '\"': if (js_parse_string(s, c, true, p + 1, &s->token, &p)) goto fail; break; case '\r': /* accept DOS and MAC newline sequences */ if (p[1] == '\n') { p++; } /* fall thru */ case '\n': p++; line_terminator: s->eol = &p[-1]; s->mark = p; s->got_lf = true; s->line_num++; goto redo; case '\f': case '\v': case ' ': case '\t': s->mark = ++p; goto redo; case '/': if (p[1] == '*') { /* comment */ p += 2; for(;;) { if (*p == '\0' && p >= s->buf_end) { js_parse_error(s, "unexpected end of comment"); goto fail; } if (p[0] == '*' && p[1] == '/') { p += 2; break; } if (*p == '\n') { s->line_num++; s->got_lf = true; /* considered as LF for ASI */ s->eol = p++; s->mark = p; } else if (*p == '\r') { s->got_lf = true; /* considered as LF for ASI */ p++; } else if (*p >= 0x80) { c = utf8_decode(p, &p); /* ignore invalid UTF-8 in comments */ if (c == CP_LS || c == CP_PS) { s->got_lf = true; /* considered as LF for ASI */ } } else { p++; } } s->mark = p; goto redo; } else if (p[1] == '/') { /* line comment */ p += 2; skip_line_comment: for(;;) { if (*p == '\0' && p >= s->buf_end) break; if (*p == '\r' || *p == '\n') break; if (*p >= 0x80) { c = utf8_decode(p, &p); /* ignore invalid UTF-8 in comments */ /* LS or PS are considered as line terminator */ if (c == CP_LS || c == CP_PS) { break; } } else { p++; } } s->mark = p; goto redo; } else if (p[1] == '=') { p += 2; s->token.val = TOK_DIV_ASSIGN; } else { p++; s->token.val = c; } break; case '\\': if (p[1] == 'u') { const uint8_t *p1 = p + 1; int c1 = lre_parse_escape(&p1, true); if (c1 >= 0 && lre_js_is_ident_first(c1)) { c = c1; p = p1; ident_has_escape = true; goto has_ident; } else { /* XXX: syntax error? */ } } goto def_token; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case '$': /* identifier */ s->mark = p; p++; ident_has_escape = false; has_ident: atom = parse_ident(s, &p, &ident_has_escape, c, false); if (atom == JS_ATOM_NULL) goto fail; s->token.u.ident.atom = atom; s->token.u.ident.has_escape = ident_has_escape; s->token.u.ident.is_reserved = false; s->token.val = TOK_IDENT; update_token_ident(s); break; case '#': /* private name */ { p++; c = *p; p_next = p + 1; if (c == '\\' && *p_next == 'u') { c = lre_parse_escape(&p_next, true); } else if (c >= 0x80) { c = utf8_decode(p, &p_next); if (p_next == p + 1) goto invalid_utf8; } if (!lre_js_is_ident_first(c)) { js_parse_error(s, "invalid first character of private name"); goto fail; } p = p_next; ident_has_escape = false; /* not used */ atom = parse_ident(s, &p, &ident_has_escape, c, true); if (atom == JS_ATOM_NULL) goto fail; s->token.u.ident.atom = atom; s->token.val = TOK_PRIVATE_NAME; } break; case '.': if (p[1] == '.' && p[2] == '.') { p += 3; s->token.val = TOK_ELLIPSIS; break; } if (p[1] >= '0' && p[1] <= '9') { goto parse_number; } else { goto def_token; } break; case '0': /* in strict mode, octal literals are not accepted */ if (is_digit(p[1]) && (s->cur_func->is_strict_mode)) { js_parse_error(s, "Octal literals are not allowed in strict mode"); goto fail; } goto parse_number; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* number */ parse_number: { JSValue ret; const uint8_t *p1; int flags; flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX; ret = js_atof(s->ctx, (const char *)p, (const char **)&p, 0, flags); if (JS_IsException(ret)) goto fail; /* reject `10instanceof Number` */ if (JS_VALUE_IS_NAN(ret) || lre_js_is_ident_next(utf8_decode(p, &p1))) { JS_FreeValue(s->ctx, ret); js_parse_error(s, "invalid number literal"); goto fail; } s->token.val = TOK_NUMBER; s->token.u.num.val = ret; } break; case '*': if (p[1] == '=') { p += 2; s->token.val = TOK_MUL_ASSIGN; } else if (p[1] == '*') { if (p[2] == '=') { p += 3; s->token.val = TOK_POW_ASSIGN; } else { p += 2; s->token.val = TOK_POW; } } else { goto def_token; } break; case '%': if (p[1] == '=') { p += 2; s->token.val = TOK_MOD_ASSIGN; } else { goto def_token; } break; case '+': if (p[1] == '=') { p += 2; s->token.val = TOK_PLUS_ASSIGN; } else if (p[1] == '+') { p += 2; s->token.val = TOK_INC; } else { goto def_token; } break; case '-': if (p[1] == '=') { p += 2; s->token.val = TOK_MINUS_ASSIGN; } else if (p[1] == '-') { if (s->allow_html_comments && p[2] == '>' && (s->got_lf || s->last_ptr == s->buf_start)) { /* Annex B: `-->` at beginning of line is an html comment end. It extends to the end of the line. */ goto skip_line_comment; } p += 2; s->token.val = TOK_DEC; } else { goto def_token; } break; case '<': if (p[1] == '=') { p += 2; s->token.val = TOK_LTE; } else if (p[1] == '<') { if (p[2] == '=') { p += 3; s->token.val = TOK_SHL_ASSIGN; } else { p += 2; s->token.val = TOK_SHL; } } else if (s->allow_html_comments && p[1] == '!' && p[2] == '-' && p[3] == '-') { /* Annex B: handle ` qbs Qbs Qt Project qbs Build tool that helps simplify the build process for developing projects across multiple platforms. Qbs is a tool that helps simplify the build process for developing projects across multiple platforms. https://wiki.qt.io/Qbs https://code.qt.io/cgit/qbs/qbs.git https://code.qt.io/cgit/qbs/qbs.git https://doc.qt.io/qbs/ http://lists.qt-project.org/mailman/listinfo/qbs https://bugreports.qt.io/browse/QBS qbs qt build © 2017 The Qt Company Ltd. http://doc.qt.io/qt-5/licensing.html false https://rawcdn.githack.com/qbs/qbs/v1.17.0/src/packages/chocolatey/icon.png qbs-src-3.3.1/src/packages/chocolatey/chocolatey.qbs0000644000175100017510000001160615232633614022047 0ustar runnerrunnerimport qbs.Environment import qbs.File import qbs.FileInfo import qbs.Probes import qbs.TextFile import qbs.Utilities import qbs.Xml Product { Depends { name: "qbsversion" } Probes.BinaryProbe { id: choco condition: qbs.targetOS.contains("windows") names: ["choco"] platformSearchPaths: { var chocolateyInstall = Environment.getEnv("ChocolateyInstall"); if (chocolateyInstall) return [FileInfo.joinPaths(chocolateyInstall, "bin")]; else return [FileInfo.joinPaths(Environment.getEnv("PROGRAMDATA"), "chocolatey", "bin")]; } } condition: choco.found builtByDefault: false name: "qbs chocolatey" type: ["chocolatey.nupkg"] targetName: "qbs." + qbsversion.version destinationDirectory: project.buildDirectory property string chocoFilePath: choco.filePath Group { files: ["qbs.nuspec"] fileTags: ["chocolatey.nuspec"] } Group { files: ["chocolateyinstall.ps1"] fileTags: ["powershell.source"] } Group { files: ["../../../changelogs/*"] fileTags: ["changelog"] } Rule { inputs: ["chocolatey.nuspec", "powershell.source", "changelog"] multiplex: true Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".nupkg") fileTags: ["chocolatey.nupkg"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.qbsVersion = product.qbsversion.version; cmd.powershellFilePath = inputs["powershell.source"][0].filePath; cmd.nuspecFileName = inputs["chocolatey.nuspec"][0].fileName; cmd.nuspecFilePath = inputs["chocolatey.nuspec"][0].filePath; cmd.chocoBuildDirectory = FileInfo.joinPaths(product.buildDirectory, "choco"); cmd.chocoOutDirectory = FileInfo.path(outputs["chocolatey.nupkg"][0].filePath); cmd.changelogs = (inputs["changelog"] || []).map(function (a) { return { filePath: a.filePath, version: a.fileName.replace(/^changes-([0-9](\.[0-9]+)*)(\.md)?$/, "$1") }; }).sort(function(a, b) { return Utilities.versionCompare(b.version, a.version); }); cmd.sourceCode = function () { File.makePath(chocoBuildDirectory); File.makePath(FileInfo.joinPaths(chocoBuildDirectory, "tools")); var tf = new TextFile(FileInfo.joinPaths( chocoBuildDirectory, "tools", "chocolateyinstall.ps1"), TextFile.WriteOnly); try { tf.writeLine("$qbsVersion = '" + qbsVersion + "'"); tf.writeLine(""); var tf2 = new TextFile(powershellFilePath, TextFile.ReadOnly); try { tf.write(tf2.readAll()); } finally { tf2.close(); } } finally { tf.close(); } var doc = new Xml.DomDocument(); doc.load(nuspecFilePath); var versionNode = doc.createElement("version"); versionNode.appendChild(doc.createTextNode(qbsVersion)); var releaseNotesNode = doc.createElement("releaseNotes"); var releaseNotesText = ""; changelogs.map(function (changelog) { releaseNotesText += "qbs " + changelog.version + "\n\n"; var tf = new TextFile(changelog.filePath, TextFile.ReadOnly); try { releaseNotesText += tf.readAll() + "\n"; } finally { tf.close(); } }); releaseNotesNode.appendChild(doc.createTextNode(releaseNotesText.trim())); var metadataNode = doc.documentElement().firstChild("metadata"); metadataNode.appendChild(versionNode); metadataNode.appendChild(releaseNotesNode); doc.save(FileInfo.joinPaths(chocoBuildDirectory, nuspecFileName)); }; var cmd2 = new Command(product.chocoFilePath, ["pack", FileInfo.joinPaths(cmd.chocoBuildDirectory, cmd.nuspecFileName), "--limitoutput", "--outputdirectory", cmd.chocoOutDirectory]); cmd2.description = "packing choco " + inputs["chocolatey.nuspec"][0].fileName; return [cmd, cmd2]; } } } qbs-src-3.3.1/src/packages/chocolatey/icon.png0000644000175100017510000001540315232633614020643 0ustar runnerrunner‰PNG  IHDR€€Ã>aËsBIT|dˆ pHYsììu85tEXtSoftwarewww.inkscape.org›î<€IDATxœí{\•UºÇïT”Doˆ©ÜÄ ‰&‚¡I^5ËÄgç¤aÙ™š²¢ù¨i:ÎXã%œÓ¦ž“Z6êJâŒxñVl‚EH.!›Ëþ?¶”Cì½×»¯ûûù¬¿öZï»Özž½Ö³Öû¬g’¡$3ø$C­]/f†¤ÉXj'žäHk×Ó†‰!Ù“ä$t¿…†{y{Z»Þ6Œ„¤‚d8ÉÁ·æ’¯’´·v;lÉÉ$Ó |k²h³Ú$½H2à[sˆ¤—µÛgC $»“|Ÿ¤JT¢IIILJJ’£ª{ïèníöÚ¸šç¿•baa!ÃÃÃ)IpΜ9¼~ýºE(§Æ>°³vû;4$I¦ˆJ­¶¶–7n¤““üGrttddd$ïܹ#G¾!ù¸u{¡BÒän’jQIÅÆÆrðàÁ?|ë4`ÀîÞ½›jµð£IÍÞÂëõHdW’kIÞ•ÌåË—9a½‚o˜œœ,G T$£H>dÞùCR"F2_TÅÅÅŒˆˆ B¡-ü–$IÃÂÂXPP GŠHFTX£¯~qKRØTW©TŒŠŠb÷îÝ |ëÔµkW®]»–uuuráÉ –î¯_ $ÝHF“líñØØXzxx˜Lð­ÓÀåÚj’ûI²dßµkH:’Œ$)lŽgffrÆŒf|ë4iÒ$¦¦¦ŠV$kIn$éd©~lwP3ÏF–}II #""hggg1á·$;;;FDD°¤DÖgõ½6J–éÕvÉGIf‹ö¢J¥â¦M›èììlqÁ·NÎÎÎÜ´iU*á HÞkë£æïÙ’ýHyþÈ‘#ôññ±ºà['9rDŽ4ßk{?óö²n¬²T!Ù™d$€«ž­I”••!//Ϭõ3„¼¼<”••¤h4m¿JÍÓÙ|µ{€ 9‡ä59•ÖÔÖÖrùòåVÿ×·¤^xÕÕÕÆ4‰$o 7wÿ[ ’~$OÛK÷SPPÀ   « >((Hî&‘'IúYB&¤ 5[¤¦î©RRRØ¿‹ ÞÕÕ•qqqr¿È¡™šo},%'“CÒš-Ñ2sõÒý455qÏž=´··7›à ·lÙÂÆF³érkn³=ÚÔ¸] /ëªjî²^Õ¶¿fyU ›„ ¬®®æÒ¥KM.üððpYŸŠU ¬ªiû›UUMë´´W ÙlniÔïvý4«Õ=z4333e½ûøùtŽÿÝ*¯¶mdæÏwwÅ1éÛ\6Ë›FNÐÄnë&ñx¥Æ…:Àk:‰”9÷mÞùø 2óŠôæ­ª©ÃþSßàë+70û±‘èßËYowww¤¤¤ 11óæÍCEE…Hµ~ÄÉÉ »wïÆÓO? IÛ¸»v³k¢ÿ‰Ó—3õ潫j@lr:.dæcöc#á3PhºŸ •ä.«$I*ª˜ŒÚà=w,ÙÐ(€^á—ÝÆ«›ö`þ[QB¿ŸÜ¢rl;˜ˆý§¾AMJ¨Ì¤I“PZZŠèèh(bÍ]¿~=***ðÌ3Ï ¿²ú.Þùø &¿¸AHø÷Sz»»Ž¦àÓcPq§V¤ˆ=€Ù4ÛºÁ @r2€TŸЫ¾wë°yo‚—¬Ã }-H⛫7±ù‹“HLÍAS³Zo;;;DDD ªª K—.ÕšoáÂ…¨¬¬ÄªU«ààà ÷¹MÍØ—Œ KÖaÇ¡¡ºh#«à6q ±ÉéP54‰q𣎵ÉVjÜ®÷8 àüˆ=›ŠÇ_XÍ{ã jh4¤ž?£NÕˆc2ñÁþSHÏ-*ãää„O>ù¹¹¹x䑟ªîíí ¥R‰Ï?ÿÎÎú§8›zÓ_Þˆ·¶íCŃÚКfµÉéyØôÅI\Ì̇ZlWq(€£Ôk.÷ÂÃÉnÞð6¡e‰òjVt_g]—[/aÊ«jñYü%xeöÆœà‘èë¢ßcÛÃÃJ¥§NB]]fÍš%<Ïç•âÝí1ˆ¿alÕµR}·1gÒ4öA°†ôï%Rl*%ɼ#IR•H!½ @ͧËçlÐWä¡Åe·ñ§‡q8ñk9{ãFq­¨ Û&"hÄ`Lë Çκ‡pI’0eÊáçWÕÜÅæ½qøô«³hlj6¶ºB•Waûá$<âåŽÐ ápvrÔWÄÀ+~Er%€]÷\ßµ"2üÀ ‘ שð÷'ð÷'P§j)bRZ†ÐÔœBL ðEà°ÁP(ŒûôÞÔ¬ÆÞcIøë-f¤™H»VˆÌüï1Éß “ü½á`¯÷8B_; ð†®Œ:€äh–vº+IâPÂר°ë0ŠËnëËnvîÖ7àðÙoqþ»|Ìyl$¼Ü{ôœ³©W°&úŸÈγ1ÌIcS3N\¾‚KÙ703p8Fy»C@µ_#¹U’$­Ë-}#€/ôŠ–˜ç ¥¤âv|uÃ÷ìñ#Ñ˹›P¹üâ2¬ÝƒãçÓÍ\CùTÕÔá‹“_ã\Æu<ì÷>=teW@#Cƒ@ëXSRQ…Í{ãðù±s¢ÖªÕÈÌ¿…+7J4b0¦ø¢K§¶íƒ:U#þ~ ûÇq44 -Ŭƒ |“ˆ‘žn˜5~$zh·tÎm"45«1aÉ:Ô nÆ<´Ø¹EåøÃ‚'Ú̳tÝvœþ:ËÂ53HÏ-Æ•¥Xû_¡Ù;m‘lW¿•Žvm½å WSÐÐØ°QØvz¥ƒcS€ŽM:86èàØ ƒcS€ŽM:86èàØ ƒóà(€‡ QGm5—D¾ãY«+@ß^Îxÿ•…píÑvl¥ñ#‡`N°ŸÖ8"Ý;cÅs¡áéÞæïCõÅo§èú€c1¬¹s',›7¿ÿÕttsÔîaf§P ØÏ£¼àøÅ,\ʾa1/#¹($ Ÿ| ‘‹gkUh@32øyºaèÃ}p:5gÓ®åPj VQ€ÙGcõÒ§1°¯¯Àɱ3æMòGЈ!øê\òŠËÍXCùŒ÷óƺŸÕú¯o‹Nö˜1nÆ „¸”ïžgyÇ‹*ÀHOw¼ûâ³ïçmð3Ü\ñT0ÒóŠ—ònWß5a å3°o/¬^ú4fOmð3z>Ô¿€¼âr|u.ÅåBþœ&Á" àÚã!D.ž…O>…‰Œ:?7 ÔgÓ®átjŽÅ8º9vÆï5ËæMFgÙ'n®øý³“p)ûŽ_Ì>üb fU{;,ž=o,š…îÝÄ ž††¤¤¤`„ °³Óíüho§Àc|0Ö÷aÄ_¾‚KYf·$IÂì þxç…yÐGìR‘ææf¤¤¤ ;ëö¨—$ ㆠ‚¿·;Î(¯!!õªYí³­&ŽŠø¿ÿë^œ/$|’8vìzõê…ôë׉‰‰Bïz¨kÌ{|þ{ÞãÜOÜ®‹¿Ï Þü¢W.~ZZ „‰'¢GØ»w/Ôjýído‡©c‡âµ“áçéflÕµbrðtï‹=ë_Â?þò{ø<,ÿ(//#GŽDhh(jj4§lÊËË‚qãÆ Çл^|zÏ Dχº܆ÖôëÕÛÞ ÇѨ70v¸‡P™’’„„„ÀßßEEŸÌúúz,Z´>>>HKKzN/çnøí´¼0'ý{™þš“)€³SW¬i>NG¯Ä”€Benß¾°°0xzz"3³íC•—.]‚§§'–,Yò£rècØ ~xýW“13p8:9>Ëué䀗LÙ«0Ê8¡M©ºº:¼úê«:G°ÜÜ\øûûcÖ¬Y(+;àë9À¯ÌÁ‚Écà¤cÙ,£ÀÞNçBƒ‘´ó,™{;ýlllÄÖ­[áâ₃ ½g×®]èÙ³'¶oß.4„:ØÛaÒho¼ñë)ã3PöÞÛ´ ?$~² +ŸŸ 'Ç.zó“Ä—_~‰=z`Û¶mB‹CŸ>} •J¿Á'IÆø ÄŠ_OÁ¤ÑÞ°<íl0$§·¥ ¡±‰ýg¼Ì°Èm̺^$'ÀŒäܧO&$$ÈzïÍ’Ûü0æ 7î=®5ÏÜ×·púËy>]^3¥RÉÕ¦®]»2&&FVÜ¡²ÛÕü¿¸óŒü蛚µFQ™nrhljfü…tY”““C???“†m™:u*‹ŠÄP­V33_ûÍ2g¿É–±£´´”3gÎ4i›|}}™‘‘¡ÿå÷‘•‹ÍÍZëmzƒ¹böÜŸV¬X!7”»Q¨T*®Y³Æ¬mZ¸p!+++MQ]ë(@SS£££º°AN²··gtt4›µ…F£V«Ã.]ºX¤M¸~ýz64È (ÕË+@||<]\\,ÖI÷'OOO*•Jc:¬M”J%===­Ò&ÆÇÇZu£àI9oÊÏÏç¸qã¬ÒI­ÓÌ™3YZZjh§ýHyy9Ÿzê)«·ÇŒëW¯ÊmÂLcà}‘7ÔÔÔ˜}ž74­\¹’õõõ²¯R©ø—¿üÅêõo+-^¼XNÌÂ÷tÉXßB’z~ÿ‘ÕsG©T¢  ÀÚÕ0)2ûÚpÁœ)ç_“ŸŸÏÀÀ@«ÿCpذaü׿þ%ûŸßšòòrÎ;×êí žž4FÚèâ⨨(c-çŸÑQÀv³ T( —{‡,¬µ 428õ/#hòäÉLKK3¶ªÂtø æf5³òoɪ…9¶‚½¼¼¸ÿ~Yõ(Ñ”šÔq–³ÿ lÇ_H×QÝô ÐÔÜÌÈñ“#ÉüþíÚ ìÑ£‡QÔ­[7®]»VÖò®¶®žo|ð9ç¾¾Ekž{sÛÓÌ+.—Õ&k} Ê-,á¢Õ±ÿŒ—ÙÐØ¤-›N0ê{¢&8cbΤ ‡Œi Þ¼eËÙïS(Gnn.Ö¬Y£×½ ÐÄÚ{,>óÞÄgÇ’õæ/*¯Bôá$MðfA‡ÓQ£F¡  111èÔI(XúðÖ[oÉ N]UsvÆË6àÄEã"–ýAY­&.fæcÓ'‘œžµšzË888àµ×^CEEæÏŸ/ôžÀÀ@œ;wŸ~ú)úö XŠo²ó1æ·«ðVÔ>!‚ûÉ*¸…­ÿ8…c2uÆjA’$<óÌ3¨¬¬Ä+¯¼"ôŽÐÐP”––â½÷ÞRf5‰ƒ'/bÂ’uøp¼I"–šÌ£ NÕˆØätlÝ Wn”•éÙ³'8€ÜÜ\ ÞvœcwwwìÞ½))) znqy%æ¾¾³ÿ° e·ï·¡5MÍHLÍÁæ{Á›)àpêè舨¨(ܺu “&Mj3§§'”J%Ž=ŠÞ½Å‚X&)¯bÚòx寻ñC•i‚Sfð ,«¬ÁÿÆÇŽ¯Î¡ôvµPddd ..NNšëu»v튵k×"''‹-sÇR5àÿ³cŸ[…K™¦»[ðN­&xó‡_žAÁ-±‹'úöí‹„„(•J 0Ð¥KìÙ³W¯^ŨQ£„ž“_\†evbÁÛÛu]Þý "˜Í-üZa¢$è ÎØ‚$I˜9s&~øáìÛ·Ó¦Mƒ››˜7¬Z­Æ“ñÆÖÏÑ,s¨—Cai%>>tV$8ã´ØçÏŸÇØ±c…†z@îö£ƒ'Ì´Ò¬çZ‚3¦]+ÂôqÃàû°Þr§N°xñbáw\ÊÌÃÒõ;Œêå@üœñ‰ÑÞ˜8ÊK¯¤‚ƒƒ…ž¯&±ï_çðÞ§_¡¼Rl5‹œ ª©S!&Q‰óß]ÇìÇFÂÃÍÕèg–TTá¥?ÿ/Îg\3A åÓÐØ„_ÌÂŬ„Ž?ã}÷SÒs°æã"#·Ð5âg‹Ë«°ýH2ü<Ü:~„A¾ûõªFüy×aì8œ`ú Àíê»øìø%x¸¹böc#áæ*vãÈýÜ,ùëwÂWgSÍPCÝXåtpz^1² naâ(/<1Ú[Èw_M"æÔ%¼¾y/šÌ8ÏJ^q9þöÏDø>Œéㆠùî×Ö©ð·GtÌ)“]¥#«ÅhjVãô7Wq9û¦Š€aƒ´Úßåâwk¢QôÜE  ’¸˜UeN!÷÷FÈho­öAìÙT¬û$E¥Öm“Õ …–ûqºws„ï Ÿoð\ÉÿÓ–o´BÍ §¡©'.g£K'{LxÄóg¿—UVcÙ†V¨Ùϱzˆ˜´E»®o´ÎÐh ´n=@N°al ÐÁ±)@Ǧ›tpl ÐÁ±)@Ǧ›tp R ’QÁ—¬I·.Ú6;·×69v6øl¦A  PHxsáŒ>Ød‘?̓½–>‚è•K´æY>ïqLë+èêA@’$Ì™8 Ñ« ®³>•×êvÚœqœï INÇ1_9k0=Èk#æa°›nÌ–àŒ£½Ýq4%™ù·,TCù<:lÖ¿4þ>ƒôeÕé:¬O²¨¡c¤pïÓ/=3i9…8v!U5uú*d1|»áÝeÏbâ衲Êõrî†ð'q­° ±ç2PRaw3Üz÷ÄÊççâéGE†}542ÔŠN$©ˆäV+tæàïíŽCú#Q™ƒDå5“ø¬JÏîÝðfø,<7s‚Qù—{o¼:?²ò)w­x·°cçNX6Ëæ±³ðá“­’$ét%±zÞ`'2ìí0u¬/|!î|&¾½V¨å#¯yh N½â¹P8;™&T¬B!aüˆ!ð÷rljËÙ8ÿ]¾Y=[#IæNz«–Ì…[o±øÄJ¬°K_F½ Iì$ù4Ê @gèLg'G,œú(&>âi1û`âè¡xwÙ³ð,æœI'OžD}}=fÍš¥w8uìì€9Á~?bަ|‡¬óÛ~^±îÅùùs§-4øÀ;’$ ]: ¼î‘$©ÀZ’{ü@˜¾2-öAFn1ަd Ò öÁ½ñöïžÂ6äååaîܹÈÈМ«óööÆ„k¸öpÂâ™-öA:J*LïºÝ×Å+ž ÅÂ'ÇË {À«’$µtY ²'HI’®I’´ÀßêÍÍý8¯ÿzŠI—Xݱòù¹8ýñJaá×ÔÔ`É’%ðôôüQø““üæ7¿Aee¥Ð³¼Ü{ã•ù!˜÷ø({ rhYªžÙ±Ï…‹ ?À,I’¦É>`ÄN $I§Œ°@©¾ü-K¬7N5(xs IBØÔ@$íx//˜&´!ÕÜÜŒíÛ·ÃÙÙ»viŸ÷íÛ‡ž={âOú\Ñì Œ>+NA°Ÿ Ã÷D¦ùáÌ'«±îÅùx¨«þàÔ*ü€Ÿ$Iq†¾×¨¿£$IjI’v à=zÍdg'G,˜</<,Û‡>x”Žø6¢ÞX¤óV®ûILL„««+–-[&|BxõêÕpqqÁ—_~)t ´kçN˜ì‡×LÆÐ‡ÅN.·àýp?|¾áe|ºvõ:0Ó`;€¡’$EI’dÙ»rtAÒ‡d¬h€µZͯ¯Üàúÿ;¦5ˆ³òjÇ.ZÅ'.N É›7o2((ÈèˆþþþÌÌÌ”õîÌüïùþgñ<£Ìió÷ÒŠ*{‹;Öå»-âIŽ´¼deB2”d¶h«êT ¬ªi;ØsUÍ]ªă$™+&Qxx¸œàŒlljfyUM›¿Õ«XUsWøYÔôe¨e¥h$$HF,“ÓRCijjâž={hooorá·$…BÁ-[¶µK·IF’4Ý!–†¤ É(’fëµ””öïßßl‚o\]]'+žLšIî&ÙÇRr2;$ýHž4e/˜dž74±  À”M"5}äg ™X’sHÊ»“¥µµµ\¾|¹Õß:-]º”ÕÕÕÆ ¾€d¸¹ûÿ€dgjæ6q«ŠšUÃÎ;Í:Ïšìíí¹sçNC¦…;´ânÝ^èàT '©ýZðV2<<œ÷<ž9gÎ^¿~]ŽàËI¾JÒÎÚí·q’Ý©¹éTxK.))‰II Þ{öû$»[»½6´@Ò‹ä!9RäI/k·Ï† $Ÿ iŠ»ä²hÌÌ6¬² ¹Mòjæùö4ÀÆOìIò’"÷É6ÜË+|ÏF;úÝÖÛ‡Ûµ ã Æmýþë93ØÞÜ®MÄÿ¥2Üi|êIEND®B`‚qbs-src-3.3.1/src/src.qbs0000644000175100017510000000050115232633614014564 0ustar runnerrunnerProject { references: [ "app/apps.qbs", "lib/libs.qbs", "libexec/libexec.qbs", "packages/packages.qbs", "plugins/plugins.qbs", "shared/bundledqt/bundledqt.qbs", "shared/lsp/lsp.qbs", "shared/quickjs/quickjs.qbs", "shared/span/span.qbs", ] } qbs-src-3.3.1/src/app/0000755000175100017510000000000015232633614014052 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs-setup-qt/0000755000175100017510000000000015232633614016417 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs-setup-qt/commandlineparser.cpp0000644000175100017510000001241615232633614022632 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString detectOption() { return QStringLiteral("--detect"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_qmakePath.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == systemOption()) m_settingsScope = qbs::Settings::SystemScope; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_qmakePath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Qt versions.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%4] %3\n") .arg(m_command, settingsDirOption(), detectOption(), systemOption()); s += Tr::tr(" %1 [%2 ] [%4] \n") .arg(m_command, settingsDirOption(), systemOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known Qt versions, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one Qt version."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-3.3.1/src/app/qbs-setup-qt/qbs-setup-qt.qbs0000644000175100017510000000077315232633614021502 0ustar runnerrunnerQbsApp { name: "qbs-setup-qt" files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "setupqt.cpp", "setupqt.h" ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: "qbs-setup-qt.rc" Group { name: "qbs-setup-qt manifest" files: "qbs-setup-qt.exe.manifest" fileTags: [] // the manifest is referenced by the rc file } } } qbs-src-3.3.1/src/app/qbs-setup-qt/CMakeLists.txt0000644000175100017510000000031315232633614021154 0ustar runnerrunnerset(SOURCES commandlineparser.cpp commandlineparser.h main.cpp setupqt.cpp setupqt.h ) add_qbs_app(qbs-setup-qt DEPENDS qbscore qbsconsolelogger SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/qbs-setup-qt/qbs-setup-qt.exe.manifest0000644000175100017510000000072615232633614023301 0ustar runnerrunner qbs-src-3.3.1/src/app/qbs-setup-qt/qbs-setup-qt.rc0000644000175100017510000000022015232633614021304 0ustar runnerrunner#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-qt.exe.manifest" qbs-src-3.3.1/src/app/qbs-setup-qt/commandlineparser.h0000644000175100017510000000573115232633614022301 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString qmakePath() const { return m_qmakePath; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested = false; bool m_autoDetectionMode = false; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_qmakePath; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-3.3.1/src/app/qbs-setup-qt/main.cpp0000644000175100017510000001074315232633614020054 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "setupqt.h" #include "commandlineparser.h" #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; int main(int argc, char *argv[]) { QCoreApplication application(argc, argv); try { CommandLineParser clParser; clParser.parse(application.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); settings.setScopeForWriting(clParser.settingsScope()); if (clParser.autoDetectionMode()) { // search all Qt's in path and dump their settings const std::vector qtEnvironments = SetupQt::fetchEnvironments(); if (qtEnvironments.empty()) { std::cout << qPrintable(Tr::tr("No Qt installations detected. " "No profiles created.")) << std::endl; } for (const QtEnvironment &qtEnvironment : qtEnvironments) { QString profileName = QLatin1String("qt-") + qtEnvironment.qtVersion.toString(); if (SetupQt::checkIfMoreThanOneQtWithTheSameVersion(qtEnvironment.qtVersion, qtEnvironments)) { QStringList prefixPathParts = QFileInfo(qtEnvironment.qmakeFilePath).path() .split(QLatin1Char('/'), Qt::SkipEmptyParts); if (!prefixPathParts.empty()) profileName += QLatin1String("-") + prefixPathParts.last(); } SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); } return EXIT_SUCCESS; } if (!SetupQt::isQMakePathValid(clParser.qmakePath())) { std::cerr << qPrintable(Tr::tr("'%1' does not seem to be a qmake executable.") .arg(clParser.qmakePath())) << std::endl; return EXIT_FAILURE; } const QtEnvironment qtEnvironment = SetupQt::fetchEnvironment(clParser.qmakePath()); QString profileName = clParser.profileName(); profileName.replace(QLatin1Char('.'), QLatin1Char('-')); SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); return EXIT_SUCCESS; } catch (const ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-3.3.1/src/app/qbs-setup-qt/setupqt.h0000644000175100017510000000557315232633614020307 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPQT_H #define QBS_SETUPQT_H #include #include #include #include #include namespace qbs { class Settings; class QtEnvironment { public: QString qmakeFilePath; QStringList qbsToolchain; QString architecture; QString targetPlatform; Version qtVersion; Version vcVersion; }; class SetupQt { Q_DECLARE_TR_FUNCTIONS(SetupQt) public: static bool isQMakePathValid(const QString &qmakePath); static std::vector fetchEnvironments(); static QtEnvironment fetchEnvironment(const QString &qmakePath); static bool checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion, const std::vector &qtEnvironments); static void saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment, Settings *settings); }; } // namespace qbs #endif // QBS_SETUPQT_H qbs-src-3.3.1/src/app/qbs-setup-qt/setupqt.cpp0000644000175100017510000003542115232633614020635 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "setupqt.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using Internal::none_of; using Internal::contains; using Internal::HostOsInfo; using Internal::Tr; using Internal::rangeTo; static QStringList qmakeExecutableNames() { const QString baseName = HostOsInfo::appendExecutableSuffix(QStringLiteral("qmake")); QStringList lst(baseName); if (HostOsInfo::isLinuxHost()) { // Some distributions ship binaries called qmake-qt5 or qmake-qt4. lst << baseName + QLatin1String("-qt5") << baseName + QLatin1String("-qt4"); } return lst; } static QStringList collectQmakePaths() { const QStringList qmakeExeNames = qmakeExecutableNames(); QStringList qmakePaths; QByteArray environmentPath = qgetenv("PATH"); const QList environmentPaths = environmentPath.split(HostOsInfo::pathListSeparator().toLatin1()); for (const QByteArray &path : environmentPaths) { for (const QString &qmakeExecutableName : qmakeExeNames) { QFileInfo pathFileInfo(QDir(QLatin1String(path)), qmakeExecutableName); if (pathFileInfo.exists()) { QString qmakePath = pathFileInfo.absoluteFilePath(); if (!qmakePaths.contains(qmakePath)) qmakePaths.push_back(qmakePath); } } } return qmakePaths; } bool SetupQt::isQMakePathValid(const QString &qmakePath) { QFileInfo qmakeFileInfo(qmakePath); return qmakeFileInfo.exists() && qmakeFileInfo.isFile() && qmakeFileInfo.isExecutable(); } std::vector SetupQt::fetchEnvironments() { std::vector qtEnvironments; const auto qmakePaths = collectQmakePaths(); for (const QString &qmakePath : qmakePaths) { const QtEnvironment env = fetchEnvironment(qmakePath); if (none_of(qtEnvironments, [&env](const QtEnvironment &otherEnv) { return env.qmakeFilePath == otherEnv.qmakeFilePath; })) { qtEnvironments.push_back(env); } } return qtEnvironments; } // These functions work only for Qt from installer. static QStringList qbsToolchainFromDirName(const QString &dir) { if (dir.startsWith(QLatin1String("msvc"))) return {QStringLiteral("msvc")}; if (dir.startsWith(QLatin1String("mingw"))) return {QStringLiteral("mingw"), QStringLiteral("gcc")}; if (dir.startsWith(QLatin1String("clang"))) return {QStringLiteral("clang"), QStringLiteral("llvm"), QStringLiteral("gcc")}; if (dir.startsWith(QLatin1String("gcc"))) return {QStringLiteral("gcc")}; return {}; } static Version vcVersionFromDirName(const QString &dir) { static const std::regex regexp("^msvc(\\d\\d\\d\\d).*$"); std::smatch match; const std::string dirString = dir.toStdString(); if (!std::regex_match(dirString, match, regexp)) return Version{}; // see https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd QMap mapping{ std::make_pair("2005", "8"), std::make_pair("2008", "9"), std::make_pair("2010", "10"), std::make_pair("2012", "11"), std::make_pair("2013", "12"), std::make_pair("2015", "14"), std::make_pair("2017", "14.10"), std::make_pair("2019", "14.20"), std::make_pair("2022", "14.30")}; return Version::fromString(QString::fromStdString(mapping.value(match[1].str()))); } static Version vcVersionFromToolchainInstallPath(const QString &toolchainPath) { // e.g. 14.40.33807\bin\Hostx64\x64 QDir dir(toolchainPath); dir.cdUp(); dir.cdUp(); dir.cdUp(); return Version::fromString(dir.dirName()); } static QString archFromDirName(const QString &dir) { static const std::regex regexp("^[^_]+_(.*).*$"); std::smatch match; const std::string dirString = dir.toStdString(); if (!std::regex_match(dirString, match, regexp)) return {}; QString arch = QString::fromStdString(match[1]); if (arch == QLatin1String("32")) return QStringLiteral("x86"); if (arch == QLatin1String("64")) return QStringLiteral("x86_64"); if (arch.contains(QLatin1String("arm64"))) return QStringLiteral("arm64"); return arch; } static QString platformFromDirName(const QString &dir) { if (dir.startsWith(QLatin1String("android"))) return QStringLiteral("android"); if (dir == QLatin1String("Boot2Qt")) return QStringLiteral("linux"); return HostOsInfo::hostOSIdentifier(); } QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath) { QtEnvironment env; env.qmakeFilePath = qmakePath; QDir qtDir = QFileInfo(qmakePath).dir(); if (qtDir.dirName() == QLatin1String("bin")) { qtDir.cdUp(); env.qbsToolchain = qbsToolchainFromDirName(qtDir.dirName()); env.vcVersion = vcVersionFromDirName(qtDir.dirName()); env.architecture = archFromDirName(qtDir.dirName()); if (env.vcVersion.isValid() && env.architecture.isEmpty()) env.architecture = QStringLiteral("x86"); env.targetPlatform = platformFromDirName(qtDir.dirName()); qtDir.cdUp(); env.qtVersion = Version::fromString(qtDir.dirName()); } return env; } static bool isToolchainProfile(const Profile &profile) { const auto actual = rangeTo>( profile.allKeys(Profile::KeySelectionRecursive)); Internal::Set expected{ QStringLiteral("qbs.toolchainType") }; if (HostOsInfo::isMacosHost()) expected.insert(QStringLiteral("qbs.targetPlatform")); // match only Xcode profiles return Internal::Set(actual).unite(expected) == actual; } static bool isQtProfile(const Profile &profile) { if (!profile.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")).toStringList() .empty()) { return true; } // For Profiles created with setup-qt < 5.13. const QStringList searchPaths = profile.value(QStringLiteral("preferences.qbsSearchPaths")).toStringList(); return Internal::any_of(searchPaths, [] (const QString &path) { return QFileInfo(path + QStringLiteral("/modules/Qt")).isDir(); }); } template bool areProfilePropertiesIncompatible(const T &set1, const T &set2) { // Two objects are only considered incompatible if they are both non empty and compare inequal // This logic is used for comparing target OS, toolchain lists, and architectures return set1.size() > 0 && set2.size() > 0 && set1 != set2; } enum Match { MatchFull, MatchPartial, MatchNone }; static Match compatibility(const QtEnvironment &env, const Profile &toolchainProfile) { Match match = MatchFull; const auto toolchainType = toolchainProfile.value(QStringLiteral("qbs.toolchainType")).toString(); const auto toolchain = !toolchainType.isEmpty() ? canonicalToolchain(toolchainType) : toolchainProfile.value(QStringLiteral("qbs.toolchain")).toStringList(); const auto toolchainNames = rangeTo>(toolchain); const auto qtToolchainNames = rangeTo>(env.qbsToolchain); if (areProfilePropertiesIncompatible(toolchainNames, qtToolchainNames)) { auto intersection = toolchainNames; intersection.intersect(qtToolchainNames); if (!intersection.empty()) match = MatchPartial; else return MatchNone; } const auto targetPlatform = toolchainProfile.value( QStringLiteral("qbs.targetPlatform")).toString(); if (!targetPlatform.isEmpty() && targetPlatform != env.targetPlatform) return MatchNone; const QString toolchainArchitecture = toolchainProfile.value(QStringLiteral("qbs.architecture")) .toString(); if (areProfilePropertiesIncompatible(canonicalArchitecture(env.architecture), canonicalArchitecture(toolchainArchitecture))) return MatchNone; if (toolchainType == QStringLiteral("msvc") && env.vcVersion.isValid()) { // We want to know for sure that MSVC compiler versions match, // because it's especially important for this toolchain const Version compilerVersion = vcVersionFromToolchainInstallPath( toolchainProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString()); static const Version vs2017Version{14, 10}; if (env.vcVersion >= vs2017Version) { if (env.vcVersion.majorVersion() != compilerVersion.majorVersion() || compilerVersion < vs2017Version) { return MatchNone; } } else if ( env.vcVersion.majorVersion() != compilerVersion.majorVersion() || env.vcVersion.minorVersion() != compilerVersion.minorVersion()) { return MatchNone; } } return match; } QString profileNameWithoutHostArch(const QString &profileName) { QString result; int i = profileName.indexOf(QLatin1Char('-')); if (i == -1) return result; ++i; int j = profileName.indexOf(QLatin1Char('_'), i); if (j == -1) return result; result = profileName.mid(0, i) + profileName.mid(j + 1); return result; } // "Compressing" MSVC profiles means that if MSVC2017-x64 and MSVC2017-x86_x64 fully match, // then we drop the crosscompiling toolchain MSVC2017-x86_x64. static void compressMsvcProfiles(QStringList &profiles) { Internal::removeIf(profiles, [&profiles] (const QString &profileName) { int idx = profileName.indexOf(QLatin1Char('_')); if (idx == -1) return false; return contains(profiles, profileNameWithoutHostArch(profileName)); }); } void SetupQt::saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment, Settings *settings) { const QString cleanQtVersionName = Profile::cleanName(qtVersionName); QString msg = QCoreApplication::translate("SetupQt", "Creating profile '%1'.") .arg(cleanQtVersionName); std::printf("%s\n", qPrintable(msg)); Profile profile(cleanQtVersionName, settings); profile.removeProfile(); profile.setValue(QStringLiteral("moduleProviders.Qt.qmakeFilePaths"), QStringList(qtEnvironment.qmakeFilePath)); if (!profile.baseProfile().isEmpty()) return; if (isToolchainProfile(profile)) return; QStringList fullMatches; QStringList partialMatches; const auto profileNames = settings->profiles(); for (const QString &profileName : profileNames) { const Profile otherProfile(profileName, settings); if (profileName == profile.name() || !isToolchainProfile(otherProfile) || isQtProfile(otherProfile)) continue; switch (compatibility(qtEnvironment, otherProfile)) { case MatchFull: fullMatches << profileName; break; case MatchPartial: partialMatches << profileName; break; default: break; } } if (fullMatches.size() > 1) compressMsvcProfiles(fullMatches); QString bestMatch; if (fullMatches.size() == 1) bestMatch = fullMatches.front(); else if (fullMatches.empty() && partialMatches.size() == 1) bestMatch = partialMatches.front(); if (bestMatch.isEmpty()) { QString message = Tr::tr("You may want to set up toolchain information " "for the generated Qt profile. "); if (!fullMatches.empty() || !partialMatches.empty()) { message += Tr::tr("Consider setting one of these profiles as this profile's base " "profile: %1.").arg((fullMatches + partialMatches) .join(QLatin1String(", "))); } qbsInfo() << message; } else { profile.setBaseProfile(bestMatch); qbsInfo() << Tr::tr("Setting profile '%1' as the base profile for this profile.") .arg(bestMatch); } } bool SetupQt::checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion, const std::vector &qtEnvironments) { bool foundOneVersion = false; for (const QtEnvironment &qtEnvironment : qtEnvironments) { if (qtEnvironment.qtVersion == qtVersion) { if (foundOneVersion) return true; foundOneVersion = true; } } return false; } } // namespace qbs qbs-src-3.3.1/src/app/CMakeLists.txt0000644000175100017510000000036315232633614016614 0ustar runnerrunneradd_subdirectory(config) add_subdirectory(config-ui) add_subdirectory(qbs) add_subdirectory(qbs-create-project) add_subdirectory(qbs-setup-android) add_subdirectory(qbs-setup-qt) add_subdirectory(qbs-setup-toolchains) add_subdirectory(shared) qbs-src-3.3.1/src/app/shared/0000755000175100017510000000000015232633614015320 5ustar runnerrunnerqbs-src-3.3.1/src/app/shared/shared.qbs0000644000175100017510000000010315232633614017267 0ustar runnerrunnerProject { references: [ "logging/logging.qbs", ] } qbs-src-3.3.1/src/app/shared/CMakeLists.txt0000644000175100017510000000003215232633614020053 0ustar runnerrunneradd_subdirectory(logging) qbs-src-3.3.1/src/app/shared/logging/0000755000175100017510000000000015232633614016746 5ustar runnerrunnerqbs-src-3.3.1/src/app/shared/logging/coloredoutput.h0000644000175100017510000000616315232633614022035 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COLOREDOUTPUT_H #define QBS_COLOREDOUTPUT_H #include #include // http://en.wikipedia.org/wiki/ANSI_escape_code#Colors enum TextColor { TextColorDefault = -1, TextColorBlack = 0, TextColorDarkRed = 1, TextColorDarkGreen = 2, TextColorDarkBlue = 4, TextColorDarkCyan = TextColorDarkGreen | TextColorDarkBlue, TextColorDarkMagenta = TextColorDarkRed | TextColorDarkBlue, TextColorDarkYellow = TextColorDarkRed | TextColorDarkGreen, TextColorGray = 7, TextColorBright = 8, TextColorRed = TextColorDarkRed | TextColorBright, TextColorGreen = TextColorDarkGreen | TextColorBright, TextColorBlue = TextColorDarkBlue | TextColorBright, TextColorCyan = TextColorDarkCyan | TextColorBright, TextColorMagenta = TextColorDarkMagenta | TextColorBright, TextColorYellow = TextColorDarkYellow | TextColorBright, TextColorWhite = TextColorGray | TextColorBright }; void printfColored(TextColor color, const char *str, va_list vl); void printfColored(TextColor color, const char *str, ...); void fprintfColored(TextColor color, std::FILE *file, const char *str, va_list vl); void fprintfColored(TextColor color, std::FILE *file, const char *str, ...); bool terminalSupportsColor(); #endif // QBS_COLOREDOUTPUT_H qbs-src-3.3.1/src/app/shared/logging/CMakeLists.txt0000644000175100017510000000030315232633614021502 0ustar runnerrunnerset(SOURCES coloredoutput.cpp coloredoutput.h consolelogger.cpp consolelogger.h ) add_qbs_library(qbsconsolelogger STATIC DEPENDS qbscore SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/shared/logging/consolelogger.h0000644000175100017510000000637315232633614021772 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LOGSINK_H #define QBS_LOGSINK_H #include "coloredoutput.h" #include namespace qbs { class Settings; } class ConsoleLogSink : public qbs::ILogSink { public: ConsoleLogSink(); void setColoredOutputEnabled(bool enabled) { m_coloredOutputEnabled = enabled; } void setEnabled(bool enabled) { m_enabled = enabled; } private: void doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag) override; void fprintfWrapper(TextColor color, FILE *file, const char *str, ...); private: bool m_coloredOutputEnabled; bool m_enabled; }; class ConsoleLogger : public qbs::Internal::Logger { public: static ConsoleLogger &instance(qbs::Settings *settings = 0); ConsoleLogSink *logSink() { return &m_logSink; } void setSettings(qbs::Settings *settings); private: ConsoleLogger(qbs::Settings *settings); ConsoleLogSink m_logSink; }; inline qbs::Internal::LogWriter qbsError() { return ConsoleLogger::instance().qbsLog(qbs::LoggerError); } inline qbs::Internal::LogWriter qbsWarning() { return ConsoleLogger::instance().qbsWarning(); } inline qbs::Internal::LogWriter qbsInfo() { return ConsoleLogger::instance().qbsInfo(); } inline qbs::Internal::LogWriter qbsDebug() { return ConsoleLogger::instance().qbsDebug(); } inline qbs::Internal::LogWriter qbsTrace() { return ConsoleLogger::instance().qbsTrace(); } #endif // QBS_LOGSINK_H qbs-src-3.3.1/src/app/shared/logging/consolelogger.cpp0000644000175100017510000000773215232633614022325 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consolelogger.h" #include #include #include static QHash setupColorTable() { QHash colorTable; colorTable[QStringLiteral("compiler")] = TextColorDefault; colorTable[QStringLiteral("linker")] = TextColorDarkGreen; colorTable[QStringLiteral("codegen")] = TextColorDarkYellow; colorTable[QStringLiteral("filegen")] = TextColorDarkYellow; return colorTable; } ConsoleLogSink::ConsoleLogSink() : m_coloredOutputEnabled(true), m_enabled(true) { } void ConsoleLogSink::doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag) { if (!m_enabled) return; std::FILE * const file = level == qbs::LoggerInfo && tag != QStringLiteral("stdErr") ? stdout : stderr; const QString levelTag = logLevelTag(level); TextColor color = TextColorDefault; switch (level) { case qbs::LoggerError: color = TextColorRed; break; case qbs::LoggerWarning: color = TextColorYellow; break; default: break; } fprintfWrapper(color, file, levelTag.toLocal8Bit().constData()); static QHash colorTable = setupColorTable(); fprintfWrapper(colorTable.value(tag, TextColorDefault), file, "%s\n", message.toLocal8Bit().constData()); std::fflush(file); } void ConsoleLogSink::fprintfWrapper(TextColor color, std::FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); if (m_coloredOutputEnabled && terminalSupportsColor()) fprintfColored(color, file, str, vl); else std::vfprintf(file, str, vl); va_end(vl); } ConsoleLogger &ConsoleLogger::instance(qbs::Settings *settings) { static ConsoleLogger logger(settings); return logger; } void ConsoleLogger::setSettings(qbs::Settings *settings) { if (settings) m_logSink.setColoredOutputEnabled(qbs::Preferences(settings).useColoredOutput()); } ConsoleLogger::ConsoleLogger(qbs::Settings *settings) : Logger(&m_logSink) { setSettings(settings); } qbs-src-3.3.1/src/app/shared/logging/coloredoutput.cpp0000644000175100017510000000741015232633614022364 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coloredoutput.h" #include #ifdef Q_OS_WIN32 # include #endif #include #ifdef Q_OS_UNIX #include #endif void printfColored(TextColor color, const char *str, va_list vl) { fprintfColored(color, stdout, str, vl); } void printfColored(TextColor color, const char *str, ...) { va_list vl; va_start(vl, str); printfColored(color, str, vl); va_end(vl); } void fprintfColored(TextColor color, std::FILE *file, const char *str, va_list vl) { #if defined(Q_OS_UNIX) if (color != TextColorDefault && isatty(fileno(file))) { unsigned char bright = (color & TextColorBright) >> 3; std::fprintf(file, "\033[%d;%dm", bright, 30 + (color & ~TextColorBright)); std::vfprintf(file, str, vl); std::fprintf(stdout, "\033[0m"); std::fprintf(stderr, "\033[0m"); } else #elif defined(Q_OS_WIN32) HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbiInfo; if (color != TextColorDefault && hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) { WORD bgrColor = ((color & 1) << 2) | (color & 2) | ((color & 4) >> 2); // BGR instead of RGB. if (color & TextColorBright) bgrColor += FOREGROUND_INTENSITY; SetConsoleTextAttribute(hStdout, (csbiInfo.wAttributes & 0xf0) | bgrColor); std::vfprintf(file, str, vl); SetConsoleTextAttribute(hStdout, csbiInfo.wAttributes); } else #endif { std::vfprintf(file, str, vl); } } void fprintfColored(TextColor color, std::FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); fprintfColored(color, file, str, vl); va_end(vl); } bool terminalSupportsColor() { #if defined(Q_OS_UNIX) const QByteArray &term = qgetenv("TERM"); return !term.isEmpty() && term != "dumb"; #else return true; #endif } qbs-src-3.3.1/src/app/shared/logging/logging.qbs0000644000175100017510000000050215232633614021100 0ustar runnerrunnerQbsStaticLibrary { Depends { name: "qbscore" } name: "qbsconsolelogger" files: [ "coloredoutput.cpp", "coloredoutput.h", "consolelogger.cpp", "consolelogger.h" ] Export { Depends { name: "cpp" } cpp.includePaths: exportingProduct.sourceDirectory } } qbs-src-3.3.1/src/app/qbs/0000755000175100017510000000000015232633614014637 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs/consoleprogressobserver.cpp0000644000175100017510000001007415232633614022344 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consoleprogressobserver.h" #include #include #include namespace qbs { void ConsoleProgressObserver::initialize(const QString &task, int max) { m_maximum = max; m_value = 0; m_percentage = 0; m_hashesPrinted = 0; std::cout << task.toLocal8Bit().constData() << ": 0%" << std::flush; setMaximum(max); } void ConsoleProgressObserver::setMaximum(int maximum) { m_maximum = maximum; if (maximum == 0) { m_percentage = 100; updateProgressBarIfNecessary(); writePercentageString(); std::cout << std::endl; } } void ConsoleProgressObserver::setProgressValue(int value) { if (value > m_maximum || value <= m_value) return; // TODO: Should be an assertion, but the executor currently breaks it. m_value = value; const int newPercentage = (100 * m_value) / m_maximum; if (newPercentage == m_percentage) return; eraseCurrentPercentageString(); m_percentage = newPercentage; updateProgressBarIfNecessary(); writePercentageString(); if (m_value == m_maximum) std::cout << std::endl; else std::cout << std::flush; } void ConsoleProgressObserver::eraseCurrentPercentageString() { const int charsToErase = m_percentage == 0 ? 2 : m_percentage < 10 ? 3 : 4; const QByteArray backspaceCommand(charsToErase, '\b'); // Move cursor before the old percentage string. std::cout << backspaceCommand.constData(); // Erase old percentage string. std::cout << QByteArray(charsToErase, ' ').constData(); // Move cursor before the erased string. std::cout << backspaceCommand.constData(); } void ConsoleProgressObserver::updateProgressBarIfNecessary() { static const int TotalHashCount = 50; // Should fit on most terminals without a line break. const int hashesNeeded = (m_percentage * TotalHashCount) / 100; if (m_hashesPrinted < hashesNeeded) { std::cout << QByteArray(hashesNeeded - m_hashesPrinted, '#').constData(); m_hashesPrinted = hashesNeeded; } } void ConsoleProgressObserver::writePercentageString() { std::cout << QStringLiteral(" %1%").arg(m_percentage).toLocal8Bit().constData(); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/stdinreader.cpp0000644000175100017510000002475115232633614017660 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "stdinreader.h" #include #include #include #include #include #include #include #ifdef Q_OS_WIN32 #include #else #include #endif namespace qbs { namespace Internal { class UnixStdinReader : public StdinReader { public: UnixStdinReader(QObject *parent) : StdinReader(parent), m_notifier(0, QSocketNotifier::Read) {} private: void start() override { if (!m_stdIn.open(stdin, QIODevice::ReadOnly)) { emit errorOccurred(tr("Cannot read from standard input.")); return; } #ifdef Q_OS_UNIX const auto emitError = [this] { emit errorOccurred(tr("Failed to make standard input non-blocking: %1") .arg(QLatin1String(std::strerror(errno)))); }; const int flags = fcntl(0, F_GETFL, 0); if (flags == -1) { emitError(); return; } if (fcntl(0, F_SETFL, flags | O_NONBLOCK)) { emitError(); return; } #endif connect(&m_notifier, &QSocketNotifier::activated, this, [this] { emit dataAvailable(m_stdIn.readAll()); }); // Neither the aboutToClose() nor the readChannelFinished() signals // are triggering, so we need a timer to check whether the controlling // process disappeared. const auto stdinClosedChecker = new QTimer(this); connect(stdinClosedChecker, &QTimer::timeout, this, [this, stdinClosedChecker] { if (m_stdIn.atEnd()) { stdinClosedChecker->stop(); emit errorOccurred(tr("Input channel closed unexpectedly.")); } }); stdinClosedChecker->start(1000); } QFile m_stdIn; QSocketNotifier m_notifier; }; class WindowsStdinReader : public StdinReader { public: WindowsStdinReader(QObject *parent) : StdinReader(parent) {} private: #ifdef Q_OS_WIN32 class FileReaderThread : public QThread { public: FileReaderThread(WindowsStdinReader &parent, HANDLE stdInHandle, HANDLE exitEventHandle) : QThread(&parent), m_stdIn{stdInHandle}, m_exitEvent{exitEventHandle} { } ~FileReaderThread() { wait(); CloseHandle(m_exitEvent); } void run() override { WindowsStdinReader *r = static_cast(parent()); char buf[1024]; while (true) { DWORD bytesRead = 0; if (!ReadFile(m_stdIn, buf, sizeof buf, &bytesRead, nullptr)) { emit r->errorOccurred(tr("Failed to read from input channel.")); break; } if (!bytesRead) break; emit r->dataAvailable(QByteArray(buf, bytesRead)); } } private: HANDLE m_stdIn; HANDLE m_exitEvent; }; class ConsoleReaderThread : public QThread { public: ConsoleReaderThread(WindowsStdinReader &parent, HANDLE stdInHandle, HANDLE exitEventHandle) : QThread(&parent), m_stdIn{stdInHandle}, m_exitEvent{exitEventHandle} { } virtual ~ConsoleReaderThread() override { SetEvent(m_exitEvent); wait(); CloseHandle(m_exitEvent); } void run() override { WindowsStdinReader *r = static_cast(parent()); DWORD origConsoleMode; GetConsoleMode(m_stdIn, &origConsoleMode); DWORD consoleMode = ENABLE_PROCESSED_INPUT; SetConsoleMode(m_stdIn, consoleMode); HANDLE handles[2] = {m_exitEvent, m_stdIn}; char buf[1024]; while (true) { auto result = WaitForMultipleObjects(2, handles, FALSE, INFINITE); if (result == WAIT_OBJECT_0) break; INPUT_RECORD consoleInput; DWORD inputsRead = 0; if (!PeekConsoleInputA(m_stdIn, &consoleInput, 1, &inputsRead)) { emit r->errorOccurred(tr("Failed to read from input channel.")); break; } if (inputsRead) { if (consoleInput.EventType != KEY_EVENT || !consoleInput.Event.KeyEvent.bKeyDown || !consoleInput.Event.KeyEvent.uChar.AsciiChar) { if (!ReadConsoleInputA(m_stdIn, &consoleInput, 1, &inputsRead)) { emit r->errorOccurred(tr("Failed to read console input.")); break; } } else { DWORD bytesRead = 0; if (!ReadConsoleA(m_stdIn, buf, sizeof buf, &bytesRead, nullptr)) { emit r->errorOccurred(tr("Failed to read console.")); break; } emit r->dataAvailable(QByteArray(buf, bytesRead)); } } } SetConsoleMode(m_stdIn, origConsoleMode); } private: HANDLE m_stdIn; HANDLE m_exitEvent; }; class PipeReaderThread : public QThread { public: PipeReaderThread(WindowsStdinReader &parent, HANDLE stdInHandle, HANDLE exitEventHandle) : QThread(&parent), m_stdIn{stdInHandle}, m_exitEvent{exitEventHandle} { } virtual ~PipeReaderThread() override { SetEvent(m_exitEvent); wait(); CloseHandle(m_exitEvent); } void run() override { WindowsStdinReader *r = static_cast(parent()); OVERLAPPED overlapped = {}; overlapped.hEvent = CreateEventA(NULL, TRUE, TRUE, NULL); if (!overlapped.hEvent) { emit r->errorOccurred(StdinReader::tr("Failed to create handle for overlapped event.")); return; } char buf[1024]; DWORD bytesRead; HANDLE handles[2] = {m_exitEvent, overlapped.hEvent}; while (true) { bytesRead = 0; auto readResult = ReadFile(m_stdIn, buf, sizeof buf, NULL, &overlapped); if (!readResult) { if (GetLastError() != ERROR_IO_PENDING) { emit r->errorOccurred(StdinReader::tr("ReadFile Failed.")); break; } auto result = WaitForMultipleObjects(2, handles, FALSE, INFINITE); if (result == WAIT_OBJECT_0) break; } if (!GetOverlappedResult(m_stdIn, &overlapped, &bytesRead, FALSE)) { if (GetLastError() != ERROR_HANDLE_EOF) emit r->errorOccurred(StdinReader::tr("Error GetOverlappedResult.")); break; } emit r->dataAvailable(QByteArray(buf, bytesRead)); } CancelIo(m_stdIn); CloseHandle(overlapped.hEvent); } private: HANDLE m_stdIn; HANDLE m_exitEvent; }; #endif void start() override { #ifdef Q_OS_WIN32 HANDLE stdInHandle = GetStdHandle(STD_INPUT_HANDLE); if (!stdInHandle) { emit errorOccurred(StdinReader::tr("Failed to create handle for standard input.")); return; } HANDLE exitEventHandle = CreateEventA(NULL, TRUE, FALSE, NULL); if (!exitEventHandle) { emit errorOccurred(StdinReader::tr("Failed to create handle for exit event.")); return; } auto result = GetFileType(stdInHandle); switch (result) { case FILE_TYPE_CHAR: (new ConsoleReaderThread(*this, stdInHandle, exitEventHandle))->start(); return; case FILE_TYPE_PIPE: (new PipeReaderThread(*this, stdInHandle, exitEventHandle))->start(); return; case FILE_TYPE_DISK: (new FileReaderThread(*this, stdInHandle, exitEventHandle))->start(); return; default: emit errorOccurred(StdinReader::tr("Unable to handle unknown input type")); return; } #endif } }; StdinReader *StdinReader::create(QObject *parent) { if (HostOsInfo::isWindowsHost()) return new WindowsStdinReader(parent); return new UnixStdinReader(parent); } StdinReader::StdinReader(QObject *parent) : QObject(parent) { } } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/app/qbs/qbs.qbs0000644000175100017510000000370215232633614016135 0ustar runnerrunnerimport qbs.Utilities QbsApp { name: "qbs_app" targetName: "qbs" Depends { name: "qbs resources" } Depends { name: "qtclsp" } Depends { name: "Qt.network" } Depends { condition: Qt.core.staticBuild || qbsbuildconfig.staticBuild productTypes: ["qbsplugin"] } cpp.defines: base.concat([ "QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version), "QBS_RELATIVE_LIBEXEC_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeLibexecPath), "QBS_RELATIVE_SEARCH_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeSearchPath), "QBS_RELATIVE_PLUGINS_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativePluginsPath), ]) files: [ "application.cpp", "application.h", "commandlinefrontend.cpp", "commandlinefrontend.h", "consoleprogressobserver.cpp", "consoleprogressobserver.h", "ctrlchandler.cpp", "ctrlchandler.h", "main.cpp", "qbstool.cpp", "qbstool.h", "session.cpp", "session.h", "sessionpacket.cpp", "sessionpacket.h", "sessionpacketreader.cpp", "sessionpacketreader.h", "status.cpp", "status.h", "stdinreader.cpp", "stdinreader.h", ] Group { name: "parser" prefix: name + '/' files: [ "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", "parsercommand.cpp", "parsercommand.h", ] } Group { name: "lsp" cpp.defines: outer.filter(function(d) { return d !== "QT_NO_CAST_FROM_ASCII"; }) files: [ "lspserver.cpp", "lspserver.h", ] } } qbs-src-3.3.1/src/app/qbs/session.h0000644000175100017510000000401615232633614016474 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SESSION_H #define QBS_SESSION_H namespace qbs { namespace Internal { void startSession(); } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-3.3.1/src/app/qbs/qbstool.cpp0000644000175100017510000001023715232633614017031 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbstool.h" #include #include #include #include #include #include #include static QString toolPrefix() { return QStringLiteral("qbs-"); } static QString qbsToolFilePath(const QString &toolName) { return qbs::qbsApplicationDirPath() + QLatin1Char('/') + toolPrefix() + qbs::Internal::HostOsInfo::appendExecutableSuffix(toolName); } void QbsTool::runTool(const QString &toolName, const QStringList &arguments) { m_failedToStart = false; m_exitCode = -1; const QString filePath = qbsToolFilePath(toolName); const QFileInfo fi(filePath); if (!fi.exists() || !fi.isFile() || !fi.isExecutable()) { m_failedToStart = true; return; } QProcess toolProc; toolProc.start(filePath, arguments); if (!toolProc.waitForStarted()) m_failedToStart = true; toolProc.waitForFinished(-1); m_exitCode = toolProc.exitCode(); m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput()); m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError()); } bool QbsTool::tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode) { QbsTool tool; tool.runTool(toolName, arguments); if (exitCode) *exitCode = tool.exitCode(); if (tool.failedToStart()) return false; std::cout << qPrintable(tool.stdOut()); std::cerr << qPrintable(tool.stdErr()); return true; } QStringList QbsTool::allToolNames() { const QString suffix = QLatin1String(QBS_HOST_EXE_SUFFIX); const QStringList toolFileNames = QDir(qbs::qbsApplicationDirPath()) .entryList( QStringList( toolPrefix() + QStringLiteral("*%1").arg(suffix)), QDir::Files, QDir::Name); QStringList toolNames; const int prefixLength = toolPrefix().size(); for (const QString &toolFileName : toolFileNames) { toolNames << toolFileName.mid(prefixLength, toolFileName.size() - prefixLength - suffix.size()); } return toolNames; } qbs-src-3.3.1/src/app/qbs/session.cpp0000644000175100017510000010306715232633614017035 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "session.h" #include "lspserver.h" #include "sessionpacket.h" #include "sessionpacketreader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN32 #include #include #include #include #include #endif namespace qbs { namespace Internal { using FilePair = std::pair; class SessionLogSink : public QObject, public ILogSink { Q_OBJECT signals: void newMessage(const QJsonObject &msg); private: static const QString &warningString() { static const QString warning(QLatin1String("warning")); return warning; } void doPrintMessage(LoggerLevel, const QString &message, const QString &) override { QJsonObject msg; msg.insert(StringConstants::type(), QLatin1String("log-data")); msg.insert(StringConstants::messageKey(), message); emit newMessage(msg); } void doPrintWarning(const ErrorInfo &warning) override { QJsonObject msg; msg.insert(StringConstants::type(), warningString()); msg.insert(warningString(), warning.toJson()); emit newMessage(msg); } void doPrintError(const ErrorInfo &error) override { QJsonObject msg; msg.insert(StringConstants::type(), warningString()); static const QString errorString(QLatin1String("error")); msg.insert(errorString, error.toJson()); msg.insert(warningString(), error.toJson()); // Backward compatibility emit newMessage(msg); } }; class Session : public QObject { Q_OBJECT public: Session(); private: enum class ProjectDataMode { Never, Always, OnlyIfChanged }; ProjectDataMode dataModeFromRequest(const QJsonObject &request); QStringList modulePropertiesFromRequest(const QJsonObject &request); void insertProjectDataIfNecessary( QJsonObject &reply, ProjectDataMode dataMode, const ProjectData &oldProjectData, bool includeTopLevelData ); void setLogLevelFromRequest(const QJsonObject &request); bool checkNormalRequestPrerequisites(const char *replyType); void sendPacket(const QJsonObject &message); void setupProject(const QJsonObject &request); void buildProject(const QJsonObject &request); void cleanProject(const QJsonObject &request); void installProject(const QJsonObject &request); void addFiles(const QJsonObject &request); void removeFiles(const QJsonObject &request); void renameFiles(const QJsonObject &request); void addDependencies(const QJsonObject &request); void getRunEnvironment(const QJsonObject &request); void getGeneratedFilesForSources(const QJsonObject &request); void releaseProject(); void cancelCurrentJob(); void quitSession(); void sendErrorReply(const char *replyType, const QString &message); void sendErrorReply(const char *replyType, const ErrorInfo &error); void insertErrorInfoIfNecessary(QJsonObject &reply, const ErrorInfo &error); void connectProgressSignals(AbstractJob *job); QList getProductsByName(const QStringList &productNames) const; ProductData getProductByName(const QString &productName) const; struct ProductSelection { ProductSelection(Project::ProductSelection s) : selection(s) {} ProductSelection(QList p) : products(std::move(p)) {} Project::ProductSelection selection = Project::ProductSelectionDefaultOnly; QList products; }; ProductSelection getProductSelection(const QJsonObject &request); template struct FileUpdateData { QJsonObject createErrorReply( const char *type, const QString &mainMessage, bool addFailedFiles) const; ProductData product; GroupData group; QList arguments; ErrorInfo error; }; template FileUpdateData prepareFileUpdate(const QJsonObject &request, const QString ¶mKey); SessionPacketReader m_packetReader; LspServer m_lspServer; SessionLogSink m_logSink; Project m_project; ProjectData m_projectData; std::unique_ptr m_settings; QJsonObject m_resolveRequest; QStringList m_moduleProperties; AbstractJob *m_currentJob = nullptr; }; void startSession() { const auto session = new Session; QObject::connect(qApp, &QCoreApplication::aboutToQuit, session, [session] { delete session; }); } Session::Session() { #ifdef Q_OS_WIN32 // Make sure the line feed character appears as itself. if (_setmode(_fileno(stdout), _O_BINARY) == -1) { constexpr size_t errmsglen = FILENAME_MAX; char errmsg[errmsglen]; strerror_s(errmsg, errmsglen, errno); std::cerr << "Failed to set stdout to binary mode: " << errmsg << std::endl; qApp->exit(EXIT_FAILURE); } #endif sendPacket(SessionPacket::helloMessage(m_lspServer.socketPath())); connect(&m_logSink, &SessionLogSink::newMessage, this, &Session::sendPacket); connect(&m_packetReader, &SessionPacketReader::errorOccurred, this, [](const QString &msg) { std::cerr << qPrintable(tr("Error: %1").arg(msg)); qApp->exit(EXIT_FAILURE); }); connect(&m_packetReader, &SessionPacketReader::packetReceived, this, [this](const QJsonObject &packet) { // qDebug() << "got packet:" << packet; // Uncomment for debugging. const QString type = packet.value(StringConstants::type()).toString(); if (type == QLatin1String("resolve-project")) setupProject(packet); else if (type == QLatin1String("build-project")) buildProject(packet); else if (type == QLatin1String("clean-project")) cleanProject(packet); else if (type == QLatin1String("install-project")) installProject(packet); else if (type == QLatin1String("add-files")) addFiles(packet); else if (type == QLatin1String("remove-files")) removeFiles(packet); else if (type == QLatin1String("rename-files")) renameFiles(packet); else if (type == QLatin1String("add-dependencies")) addDependencies(packet); else if (type == QLatin1String("get-run-environment")) getRunEnvironment(packet); else if (type == QLatin1String("get-generated-files-for-sources")) getGeneratedFilesForSources(packet); else if (type == QLatin1String("release-project")) releaseProject(); else if (type == QLatin1String("quit")) quitSession(); else if (type == QLatin1String("cancel-job")) cancelCurrentJob(); else sendErrorReply("protocol-error", tr("Unknown request type '%1'.").arg(type)); }); m_packetReader.start(); } Session::ProjectDataMode Session::dataModeFromRequest(const QJsonObject &request) { const QString modeString = request.value(QLatin1String("data-mode")).toString(); if (modeString == QLatin1String("only-if-changed")) return ProjectDataMode::OnlyIfChanged; if (modeString == QLatin1String("always")) return ProjectDataMode::Always; return ProjectDataMode::Never; } void Session::sendPacket(const QJsonObject &message) { std::cout << SessionPacket::createPacket(message).constData() << std::flush; } void Session::setupProject(const QJsonObject &request) { if (m_currentJob) { if (qobject_cast(m_currentJob) && m_currentJob->state() == AbstractJob::StateCanceling) { m_resolveRequest = request; return; } sendErrorReply("project-resolved", tr("Cannot start resolving while another job is still running.")); return; } m_moduleProperties = modulePropertiesFromRequest(request); auto params = SetupProjectParameters::fromJson(request); const ProjectDataMode dataMode = dataModeFromRequest(request); m_settings = std::make_unique(params.settingsDirectory()); const Preferences prefs(m_settings.get()); const QString appDir = QDir::cleanPath(qbsApplicationDirPath()); params.setSearchPaths(prefs.searchPaths(appDir + QLatin1String( "/" QBS_RELATIVE_SEARCH_PATH))); params.setPluginPaths(prefs.pluginPaths(appDir + QLatin1String( "/" QBS_RELATIVE_PLUGINS_PATH))); params.setLibexecPath(appDir + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH)); params.setOverrideBuildGraphData(true); setLogLevelFromRequest(request); SetupProjectJob * const setupJob = m_project.setupProject(params, &m_logSink, this); m_currentJob = setupJob; connectProgressSignals(setupJob); connect(setupJob, &AbstractJob::finished, this, [this, setupJob, dataMode](bool success) { if (!m_resolveRequest.isEmpty()) { // Canceled job was superseded. const QJsonObject newRequest = std::move(m_resolveRequest); m_resolveRequest = QJsonObject(); m_currentJob->deleteLater(); m_currentJob = nullptr; setupProject(newRequest); return; } const ProjectData oldProjectData = m_projectData; m_project = setupJob->project(); m_projectData = m_project.projectData(); m_lspServer.updateProjectData(m_projectData, m_project.codeLinks()); QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("project-resolved")); if (success) insertProjectDataIfNecessary(reply, dataMode, oldProjectData, true); else insertErrorInfoIfNecessary(reply, setupJob->error()); sendPacket(reply); m_currentJob->deleteLater(); m_currentJob = nullptr; }); } void Session::buildProject(const QJsonObject &request) { if (!checkNormalRequestPrerequisites("project-built")) return; const ProductSelection productSelection = getProductSelection(request); setLogLevelFromRequest(request); auto options = BuildOptions::fromJson(request); options.setSettingsDirectory(m_settings->baseDirectory()); BuildJob * const buildJob = productSelection.products.empty() ? m_project.buildAllProducts(options, productSelection.selection, this) : m_project.buildSomeProducts(productSelection.products, options, this); m_currentJob = buildJob; m_moduleProperties = modulePropertiesFromRequest(request); const ProjectDataMode dataMode = dataModeFromRequest(request); connectProgressSignals(buildJob); connect(buildJob, &BuildJob::reportCommandDescription, this, [this](const QString &highlight, const QString &message) { QJsonObject descData; descData.insert(StringConstants::type(), QLatin1String("command-description")); descData.insert(QLatin1String("highlight"), highlight); descData.insert(StringConstants::messageKey(), message); sendPacket(descData); }); connect(buildJob, &BuildJob::reportProcessResult, this, [this](const ProcessResult &result) { if (result.success() && result.stdOut().isEmpty() && result.stdErr().isEmpty()) return; QJsonObject resultData = result.toJson(); resultData.insert(StringConstants::type(), QLatin1String("process-result")); sendPacket(resultData); }); connect(buildJob, &BuildJob::finished, this, [this, dataMode](bool success) { QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("project-built")); const ProjectData oldProjectData = m_projectData; m_projectData = m_project.projectData(); if (success) insertProjectDataIfNecessary(reply, dataMode, oldProjectData, false); else insertErrorInfoIfNecessary(reply, m_currentJob->error()); sendPacket(reply); m_currentJob->deleteLater(); m_currentJob = nullptr; }); } void Session::cleanProject(const QJsonObject &request) { if (!checkNormalRequestPrerequisites("project-cleaned")) return; setLogLevelFromRequest(request); const ProductSelection productSelection = getProductSelection(request); const auto options = CleanOptions::fromJson(request); m_currentJob = productSelection.products.empty() ? m_project.cleanAllProducts(options, this) : m_project.cleanSomeProducts(productSelection.products, options, this); connectProgressSignals(m_currentJob); connect(m_currentJob, &AbstractJob::finished, this, [this](bool success) { QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("project-cleaned")); if (!success) insertErrorInfoIfNecessary(reply, m_currentJob->error()); sendPacket(reply); m_currentJob->deleteLater(); m_currentJob = nullptr; }); } void Session::installProject(const QJsonObject &request) { if (!checkNormalRequestPrerequisites("install-done")) return; setLogLevelFromRequest(request); const ProductSelection productSelection = getProductSelection(request); const auto options = InstallOptions::fromJson(request); m_currentJob = productSelection.products.empty() ? m_project.installAllProducts(options, productSelection.selection, this) : m_project.installSomeProducts(productSelection.products, options, this); connectProgressSignals(m_currentJob); connect(m_currentJob, &AbstractJob::finished, this, [this](bool success) { QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("install-done")); if (!success) insertErrorInfoIfNecessary(reply, m_currentJob->error()); sendPacket(reply); m_currentJob->deleteLater(); m_currentJob = nullptr; }); } void Session::addFiles(const QJsonObject &request) { const FileUpdateData data = prepareFileUpdate(request, QLatin1String("files")); if (data.error.hasError()) { sendPacket(data.createErrorReply( "files-added", tr("Failed to add files to project: %1").arg(data.error.toString()), true)); return; } ErrorInfo error; QStringList failedFiles; for (const QString &filePath : data.arguments) { const ErrorInfo e = m_project.addFiles(data.product, data.group, {filePath}); if (e.hasError()) { for (const ErrorItem &ei : e.items()) error.append(ei); failedFiles.push_back(filePath); } } QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("files-added")); insertErrorInfoIfNecessary(reply, error); if (failedFiles.size() != data.arguments.size()) { // Note that Project::addFiles() directly changes the existing project data object, so // there's no need to retrieve it from m_project. insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); } if (!failedFiles.isEmpty()) reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); sendPacket(reply); } void Session::removeFiles(const QJsonObject &request) { const FileUpdateData data = prepareFileUpdate(request, QLatin1String("files")); if (data.error.hasError()) { sendPacket(data.createErrorReply( "files-removed", tr("Failed to remove files from project: %1").arg(data.error.toString()), true)); return; } ErrorInfo error; QStringList failedFiles; for (const QString &filePath : data.arguments) { const ErrorInfo e = m_project.removeFiles(data.product, data.group, {filePath}); if (e.hasError()) { for (const ErrorItem &ei : e.items()) error.append(ei); failedFiles.push_back(filePath); } } QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("files-removed")); insertErrorInfoIfNecessary(reply, error); if (failedFiles.size() != data.arguments.size()) insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); if (!failedFiles.isEmpty()) reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); sendPacket(reply); } void Session::renameFiles(const QJsonObject &request) { const FileUpdateData data = prepareFileUpdate(request, QLatin1String("files")); if (data.error.hasError()) { sendPacket(data.createErrorReply( "files-renamed", tr("Failed to rename files in project: %1").arg(data.error.toString()), true)); return; } ErrorInfo error; QStringList failedFiles; for (const FilePair &sourceAndTarget : data.arguments) { const ErrorInfo removeError = m_project.removeFiles( data.product, data.group, {sourceAndTarget.first}); if (removeError.hasError()) { for (const ErrorItem &ei : removeError.items()) error.append(ei); failedFiles.push_back(sourceAndTarget.first); } else { const ErrorInfo addError = m_project.addFiles( data.product, data.group, {sourceAndTarget.second}); if (addError.hasError()) { for (const ErrorItem &ei : addError.items()) error.append(ei); failedFiles.push_back(sourceAndTarget.first); } } } QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("files-renamed")); insertErrorInfoIfNecessary(reply, error); if (failedFiles.size() != data.arguments.size()) insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); if (!failedFiles.isEmpty()) reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); sendPacket(reply); } void Session::addDependencies(const QJsonObject &request) { const FileUpdateData data = prepareFileUpdate(request, QLatin1String("dependencies")); if (data.error.hasError()) { sendPacket(data.createErrorReply( "dependencies-added", tr("Failed to add dependencies to project: %1").arg(data.error.toString()), false)); return; } ErrorInfo error; const ErrorInfo e = m_project.addDependencies(data.product, data.group, data.arguments); QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String("dependencies-added")); insertErrorInfoIfNecessary(reply, error); insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); sendPacket(reply); } void Session::connectProgressSignals(AbstractJob *job) { static QString maxProgressString(QLatin1String("max-progress")); connect(job, &AbstractJob::taskStarted, this, [this](const QString &description, int maxProgress) { QJsonObject msg; msg.insert(StringConstants::type(), QLatin1String("task-started")); msg.insert(StringConstants::descriptionProperty(), description); msg.insert(maxProgressString, maxProgress); sendPacket(msg); }); connect(job, &AbstractJob::totalEffortChanged, this, [this](int maxProgress) { QJsonObject msg; msg.insert(StringConstants::type(), QLatin1String("new-max-progress")); msg.insert(maxProgressString, maxProgress); sendPacket(msg); }); connect(job, &AbstractJob::taskProgress, this, [this](int progress) { QJsonObject msg; msg.insert(StringConstants::type(), QLatin1String("task-progress")); msg.insert(QLatin1String("progress"), progress); sendPacket(msg); }); } static QList getProductsByNameForProject(const ProjectData &project, QStringList &productNames) { QList products; if (productNames.empty()) return products; for (const ProductData &p : project.products()) { for (auto it = productNames.begin(); it != productNames.end(); ++it) { if (*it == p.fullDisplayName()) { products << p; productNames.erase(it); if (productNames.empty()) return products; break; } } } for (const ProjectData &p : project.subProjects()) { products << getProductsByNameForProject(p, productNames); if (productNames.empty()) break; } return products; } QList Session::getProductsByName(const QStringList &productNames) const { QStringList remainingNames = productNames; return getProductsByNameForProject(m_projectData, remainingNames); } ProductData Session::getProductByName(const QString &productName) const { const QList products = getProductsByName({productName}); return products.empty() ? ProductData() : products.first(); } void Session::getRunEnvironment(const QJsonObject &request) { const char * const replyType = "run-environment"; if (!checkNormalRequestPrerequisites(replyType)) return; const QString productName = request.value(QLatin1String("product")).toString(); const ProductData product = getProductByName(productName); if (!product.isValid()) { sendErrorReply(replyType, tr("No such product '%1'.").arg(productName)); return; } const auto inEnv = fromJson( request.value(QLatin1String("base-environment"))); const QStringList config = fromJson(request.value(QLatin1String("config"))); const RunEnvironment runEnv = m_project.getRunEnvironment(product, InstallOptions(), inEnv, config, m_settings.get()); ErrorInfo error; const QProcessEnvironment outEnv = runEnv.runEnvironment(&error); if (error.hasError()) { sendErrorReply(replyType, error); return; } QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String(replyType)); QJsonObject outEnvObj; const QStringList keys = outEnv.keys(); for (const QString &key : keys) outEnvObj.insert(key, outEnv.value(key)); reply.insert(QLatin1String("full-environment"), outEnvObj); sendPacket(reply); } void Session::getGeneratedFilesForSources(const QJsonObject &request) { const char * const replyType = "generated-files-for-sources"; if (!checkNormalRequestPrerequisites(replyType)) return; QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String(replyType)); const QJsonArray specs = request.value(StringConstants::productsKey()).toArray(); QJsonArray resultProducts; for (const auto &p : specs) { const QJsonObject productObject = p.toObject(); const ProductData product = getProductByName( productObject.value(StringConstants::fullDisplayNameKey()).toString()); if (!product.isValid()) continue; QJsonObject resultProduct; resultProduct.insert(StringConstants::fullDisplayNameKey(), product.fullDisplayName()); QJsonArray results; const QJsonArray requests = productObject.value(QLatin1String("requests")).toArray(); for (const auto &r : requests) { const QJsonObject request = r.toObject(); const QString filePath = request.value(QLatin1String("source-file")).toString(); const QStringList tags = fromJson(request.value(QLatin1String("tags"))); const bool recursive = request.value(QLatin1String("recursive")).toBool(); const QStringList generatedFiles = m_project.generatedFiles(product, filePath, recursive, tags); if (!generatedFiles.isEmpty()) { QJsonObject result; result.insert(QLatin1String("source-file"), filePath); result.insert(QLatin1String("generated-files"), QJsonArray::fromStringList(generatedFiles)); results << result; } } if (!results.isEmpty()) { resultProduct.insert(QLatin1String("results"), results); resultProducts << resultProduct; } } reply.insert(StringConstants::productsKey(), resultProducts); sendPacket(reply); } void Session::releaseProject() { const char * const replyType = "project-released"; if (!m_project.isValid()) { sendErrorReply(replyType, tr("No open project.")); return; } if (m_currentJob) { m_currentJob->disconnect(this); m_currentJob->cancel(); m_currentJob = nullptr; } m_project = Project(); m_projectData = ProjectData(); m_resolveRequest = QJsonObject(); QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String(replyType)); sendPacket(reply); } void Session::cancelCurrentJob() { if (m_currentJob) { if (!m_resolveRequest.isEmpty()) m_resolveRequest = QJsonObject(); m_currentJob->cancel(); } } Session::ProductSelection Session::getProductSelection(const QJsonObject &request) { const QJsonValue productSelection = request.value(StringConstants::productsKey()); if (productSelection.isArray()) return {getProductsByName(fromJson(productSelection))}; return { productSelection.toString() == QLatin1String("all") ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly}; } template Session::FileUpdateData Session::prepareFileUpdate( const QJsonObject &request, const QString ¶mKey) { FileUpdateData data; const QString productName = request.value(QLatin1String("product")).toString(); data.product = getProductByName(productName); if (data.product.isValid()) { const QString groupName = request.value(QLatin1String("group")).toString(); for (const GroupData &g : data.product.groups()) { if (g.name() == groupName) { data.group = g; break; } } if (!data.group.isValid()) data.error = tr("Group '%1' not found in product '%2'.").arg(groupName, productName); } else { data.error = tr("Product '%1' not found in project.").arg(productName); } const QJsonArray argsArray = request.value(paramKey).toArray(); for (const auto &v : argsArray) if constexpr (std::is_same_v) { data.arguments << v.toString(); } else if constexpr (std::is_same_v) { const QJsonObject file = v.toObject(); data.arguments << std::make_pair( file.value(QLatin1String("source-path")).toString(), file.value(QLatin1String("target-path")).toString()); } if (m_currentJob) data.error = tr("Cannot update the project while a job is running."); if (!m_project.isValid()) data.error = tr("No valid project. You need to resolve first."); return data; } void Session::insertProjectDataIfNecessary(QJsonObject &reply, ProjectDataMode dataMode, const ProjectData &oldProjectData, bool includeTopLevelData) { const bool sendProjectData = dataMode == ProjectDataMode::Always || (dataMode == ProjectDataMode::OnlyIfChanged && m_projectData != oldProjectData); if (!sendProjectData) return; QJsonObject projectData = m_projectData.toJson(m_moduleProperties); if (includeTopLevelData) { QJsonArray buildSystemFiles; for (const QString &f : m_project.buildSystemFiles()) buildSystemFiles.push_back(f); projectData.insert(StringConstants::buildDirectoryKey(), m_projectData.buildDirectory()); projectData.insert(QLatin1String("build-system-files"), buildSystemFiles); const Project::BuildGraphInfo bgInfo = m_project.getBuildGraphInfo(); projectData.insert(QLatin1String("build-graph-file-path"), bgInfo.bgFilePath); projectData.insert(QLatin1String("profile-data"), QJsonObject::fromVariantMap(bgInfo.profileData)); projectData.insert(QLatin1String("overridden-properties"), QJsonObject::fromVariantMap(bgInfo.overriddenProperties)); } reply.insert(QLatin1String("project-data"), projectData); } void Session::setLogLevelFromRequest(const QJsonObject &request) { const QString logLevelString = request.value(QLatin1String("log-level")).toString(); if (logLevelString.isEmpty()) return; for (const LoggerLevel l : {LoggerError, LoggerWarning, LoggerInfo, LoggerDebug, LoggerTrace}) { if (logLevelString == logLevelName(l)) { m_logSink.setLogLevel(l); return; } } } bool Session::checkNormalRequestPrerequisites(const char *replyType) { if (m_currentJob) { sendErrorReply(replyType, tr("Another job is still running.")); return false; } if (!m_project.isValid()) { sendErrorReply(replyType, tr("No valid project. You need to resolve first.")); return false; } return true; } QStringList Session::modulePropertiesFromRequest(const QJsonObject &request) { return fromJson(request.value(StringConstants::modulePropertiesKey())); } void Session::sendErrorReply(const char *replyType, const ErrorInfo &error) { QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String(replyType)); insertErrorInfoIfNecessary(reply, error); sendPacket(reply); } void Session::sendErrorReply(const char *replyType, const QString &message) { sendErrorReply(replyType, ErrorInfo(message)); } void Session::insertErrorInfoIfNecessary(QJsonObject &reply, const ErrorInfo &error) { if (error.hasError()) reply.insert(QLatin1String("error"), error.toJson()); } void Session::quitSession() { m_logSink.disconnect(this); m_packetReader.disconnect(this); if (m_currentJob) { m_currentJob->disconnect(this); connect(m_currentJob, &AbstractJob::finished, qApp, QCoreApplication::quit); m_currentJob->cancel(); } else { qApp->quit(); } } template QJsonObject Session::FileUpdateData::createErrorReply( const char *type, const QString &mainMessage, bool addFailedFiles) const { QBS_ASSERT(error.hasError(), return QJsonObject()); ErrorInfo error(mainMessage); for (const ErrorItem &ei : error.items()) error.append(ei); QJsonObject reply; reply.insert(StringConstants::type(), QLatin1String(type)); reply.insert(QLatin1String("error"), error.toJson()); if (addFailedFiles) { QStringList failedFiles; if constexpr (std::is_same_v) { failedFiles = arguments; } else if constexpr (std::is_same_v) { failedFiles = transformed(arguments, [](const FilePair &fp) { return fp.first; }); } reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); } return reply; } } // namespace Internal } // namespace qbs #include qbs-src-3.3.1/src/app/qbs/CMakeLists.txt0000644000175100017510000000241515232633614017401 0ustar runnerrunnerset(SOURCES application.cpp application.h commandlinefrontend.cpp commandlinefrontend.h consoleprogressobserver.cpp consoleprogressobserver.h ctrlchandler.cpp ctrlchandler.h lspserver.cpp lspserver.h main.cpp qbstool.cpp qbstool.h session.cpp session.h sessionpacket.cpp sessionpacket.h sessionpacketreader.cpp sessionpacketreader.h status.cpp status.h stdinreader.cpp stdinreader.h ) set(PARSER_SOURCES commandlineoption.cpp commandlineoption.h commandlineoptionpool.cpp commandlineoptionpool.h commandlineparser.cpp commandlineparser.h commandpool.cpp commandpool.h commandtype.h parsercommand.cpp parsercommand.h ) list_transform_prepend(PARSER_SOURCES parser/) add_qbs_app(qbs DEFINES "QBS_VERSION=\"${QBS_VERSION}\"" "QBS_RELATIVE_LIBEXEC_PATH=\"${QBS_RELATIVE_LIBEXEC_PATH}\"" "QBS_RELATIVE_SEARCH_PATH=\"${QBS_RELATIVE_SEARCH_PATH}\"" "QBS_RELATIVE_PLUGINS_PATH=\"${QBS_RELATIVE_PLUGINS_PATH}\"" DEPENDS qbscore qbsconsolelogger qtclsp Qt${QT_VERSION_MAJOR}::Network SOURCES ${SOURCES} ${PARSER_SOURCES} ) add_dependencies(qbs qbs_cpp_scanner qbs_qt_scanner) qbs-src-3.3.1/src/app/qbs/application.cpp0000644000175100017510000000535015232633614017651 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "ctrlchandler.h" namespace qbs { Application::Application(int &argc, char **argv) : QCoreApplication(argc, argv), m_clFrontend(nullptr), m_canceled(false) { setApplicationName(QStringLiteral("qbs")); setOrganizationName(QStringLiteral("QtProject")); setOrganizationDomain(QStringLiteral("qt-project.org")); } Application *Application::instance() { return qobject_cast(QCoreApplication::instance()); } void Application::setCommandLineFrontend(CommandLineFrontend *clFrontend) { installCtrlCHandler(); m_clFrontend = clFrontend; } /** * Interrupt the application. This is directly called from a signal handler. */ void Application::userInterrupt() { if (m_canceled) return; Q_ASSERT(m_clFrontend); m_canceled = true; m_clFrontend->cancel(); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/lspserver.cpp0000644000175100017510000010233215232633614017371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lspserver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WINDOWS #include #else #include #endif #include namespace qbs::Internal { static int getPid() { #ifdef Q_OS_WINDOWS return _getpid(); #else return getpid(); #endif } using LspErrorResponse = lsp::ResponseError; using LspErrorCode = LspErrorResponse::ErrorCodes; class Document { public: bool isPositionUpToDate(const CodePosition &pos) const; bool isPositionUpToDate(const lsp::Position &pos) const; QString savedContent; QString currentContent; }; static CodePosition posFromLspPos(const lsp::Position &pos) { return {pos.line() + 1, pos.character() + 1}; } static lsp::Position lspPosFromCodeLocation(const CodeLocation &loc) { return {loc.line() - 1, loc.column() - 1}; } static QString uriToString(const lsp::DocumentUri &uri) { return uri.toFilePath([](const lsp::Utils::FilePath &fp) { return fp; }); } static int posToOffset(const CodePosition &pos, const QString &doc); static int posToOffset(const lsp::Position &pos, const QString &doc) { return posToOffset(posFromLspPos(pos), doc); } class AstNodeLocator : public QbsQmlJS::AST::Visitor { public: AstNodeLocator(int position, QbsQmlJS::AST::UiProgram &ast) : m_position(position) { ast.accept(this); } QList path() const { return m_path; } private: bool preVisit(QbsQmlJS::AST::Node *node) override { if (int(node->firstSourceLocation().offset) > m_position) return false; if (int(node->lastSourceLocation().offset) < m_position) return false; m_path << node; return true; } const int m_position; QList m_path; }; static QJsonArray toLspLocations(const QList &locations) { struct JsonArray : public QJsonArray { void reserve(std::size_t) {} }; return transformed(locations, [](const CodeLocation &loc) { const lsp::Position startPos = lspPosFromCodeLocation(loc); const lsp::Position endPos(startPos.line(), startPos.character() + 1); lsp::Location targetLocation; targetLocation.setUri( lsp::DocumentUri::fromProtocol(QUrl::fromLocalFile(loc.filePath()).toString())); targetLocation.setRange({startPos, endPos}); return QJsonObject(targetLocation); }); } class LspServer::Private { public: void setupConnection(); void handleIncomingData(); void discardSocket(); template void sendResponse(const T &msg); void sendErrorResponse(LspErrorCode code, const QString &message); void sendErrorNotification(const QString &message); void sendNoSuchDocumentError(const QString &filePath); void sendMessage(const lsp::JsonObject &msg); void sendMessage(const lsp::JsonRpcMessage &msg); void handleCurrentMessage(); void handleInitializeRequest(); void handleInitializedNotification(); void handleGotoDefinitionRequest(); void handleCompletionRequest(); void handleShutdownRequest(); void handleDidOpenNotification(); void handleDidChangeNotification(); void handleDidSaveNotification(); void handleDidCloseNotification(); bool handleGotoDefViaCodeLinks( const QString &sourceFile, const Document *sourceDoc, const CodePosition &sourcePos); void handleGotoDefForModuleProperties( const QString &sourceFile, const QbsQmlJS::AST::UiQualifiedId *node, int offset); QList getRelevantProducts(const QString &sourceFile); QLocalServer server; QBuffer incomingData; lsp::BaseMessage currentMessage; QJsonObject messageObject; QLocalSocket *socket = nullptr; ProjectData projectData; CodeLinks codeLinks; std::unordered_map documents; enum class State { None, InitRequest, InitNotification, Shutdown }; State state = State::None; }; LspServer::LspServer() : d(new Private) { if (!d->server.listen(QString::fromLatin1("qbs-lsp-%1").arg(getPid()))) { // This is not fatal, qbs main operation can continue. qWarning() << "failed to open lsp socket:" << d->server.errorString(); return; } QObject::connect(&d->server, &QLocalServer::newConnection, [this] { d->socket = d->server.nextPendingConnection(); d->setupConnection(); d->server.close(); }); } LspServer::~LspServer() { delete d; } void LspServer::updateProjectData(const ProjectData &projectData, const CodeLinks &codeLinks) { d->projectData = projectData; d->codeLinks = codeLinks; } QString LspServer::socketPath() const { return d->server.fullServerName(); } void LspServer::Private::setupConnection() { QBS_ASSERT(socket, return); QObject::connect(socket, &QLocalSocket::errorOccurred, [this] { discardSocket(); }); QObject::connect(socket, &QLocalSocket::disconnected, [this] { discardSocket(); }); QObject::connect(socket, &QLocalSocket::readyRead, [this] { handleIncomingData(); }); incomingData.open(QIODevice::ReadWrite | QIODevice::Append); handleIncomingData(); } void LspServer::Private::handleIncomingData() { const int pos = incomingData.pos(); incomingData.write(socket->readAll()); incomingData.seek(pos); QString parseError; lsp::BaseMessage::parse(&incomingData, parseError, currentMessage); if (!parseError.isEmpty()) return sendErrorResponse(LspErrorResponse::ParseError, parseError); if (currentMessage.isComplete()) { incomingData.buffer().remove(0, incomingData.pos()); incomingData.seek(0); handleCurrentMessage(); currentMessage = {}; messageObject = {}; if (socket) handleIncomingData(); } } void LspServer::Private::discardSocket() { socket->disconnect(); socket->deleteLater(); socket = nullptr; } template void LspServer::Private::sendResponse(const T &msg) { lsp::Response response(lsp::MessageId(messageObject.value(lsp::idKey))); response.setResult(msg); sendMessage(response); } void LspServer::Private::sendErrorResponse(LspErrorCode code, const QString &message) { lsp::Response response(lsp::MessageId( messageObject.value(lsp::idKey))); lsp::ResponseError error; error.setCode(code); error.setMessage(message); response.setError(error); sendMessage(response); } void LspServer::Private::sendErrorNotification(const QString &message) { lsp::ShowMessageParams params; params.setType(lsp::Error); params.setMessage(message); sendMessage(lsp::ShowMessageNotification(params)); } void LspServer::Private::sendNoSuchDocumentError(const QString &filePath) { sendErrorNotification(Tr::tr("No such document: '%1'").arg(filePath)); } void LspServer::Private::sendMessage(const lsp::JsonObject &msg) { sendMessage(lsp::JsonRpcMessage(msg)); } void LspServer::Private::sendMessage(const lsp::JsonRpcMessage &msg) { lsp::BaseMessage baseMsg = msg.toBaseMessage(); socket->write(baseMsg.header()); socket->write(baseMsg.content); } void LspServer::Private::handleCurrentMessage() { messageObject = lsp::JsonRpcMessage(currentMessage).toJsonObject(); const QString method = messageObject.value(lsp::methodKey).toString(); if (method == QLatin1String("exit")) return discardSocket(); if (state == State::Shutdown) { return sendErrorResponse(LspErrorResponse::InvalidRequest, Tr::tr("Method '%1' not allowed after shutdown.")); } if (method == "shutdown") return handleShutdownRequest(); if (method == QLatin1String("initialize")) return handleInitializeRequest(); if (state == State::None) { return sendErrorResponse(LspErrorResponse::ServerNotInitialized, Tr::tr("First message must be initialize request.")); } if (method == "initialized") return handleInitializedNotification(); if (method == "textDocument/didOpen") return handleDidOpenNotification(); if (method == "textDocument/didChange") return handleDidChangeNotification(); if (method == "textDocument/didSave") return handleDidSaveNotification(); if (method == "textDocument/didClose") return handleDidCloseNotification(); if (method == "textDocument/definition") return handleGotoDefinitionRequest(); if (method == "textDocument/completion") return handleCompletionRequest(); sendErrorResponse(LspErrorResponse::MethodNotFound, Tr::tr("This server can do very little.")); } void LspServer::Private::handleInitializeRequest() { if (state != State::None) { return sendErrorResponse(LspErrorResponse::InvalidRequest, Tr::tr("Received initialize request in initialized state.")); } state = State::InitRequest; lsp::ServerInfo serverInfo; serverInfo.insert(lsp::nameKey, "qbs"); serverInfo.insert(lsp::versionKey, QBS_VERSION); lsp::InitializeResult result; result.insert(lsp::serverInfoKey, serverInfo); lsp::ServerCapabilities capabilities; // TODO: hover capabilities.setDefinitionProvider(true); capabilities.setTextDocumentSync({int(lsp::TextDocumentSyncKind::Incremental)}); lsp::ServerCapabilities::CompletionOptions completionOptions; completionOptions.setTriggerCharacters({"."}); capabilities.setCompletionProvider(completionOptions); result.setCapabilities(capabilities); sendResponse(result); } void LspServer::Private::handleInitializedNotification() { if (state != State::InitRequest) { return sendErrorResponse(LspErrorResponse::InvalidRequest, Tr::tr("Unexpected initialized notification.")); } state = State::InitNotification; } void LspServer::Private::handleGotoDefinitionRequest() { const lsp::TextDocumentPositionParams params(messageObject.value(lsp::paramsKey)); const QString sourceFile = params.textDocument().uri().toLocalFile(); const CodePosition sourcePos = posFromLspPos(params.position()); const Document *sourceDoc = nullptr; if (const auto it = documents.find(sourceFile); it != documents.end()) sourceDoc = &it->second; // First check the codeLinks, where we map locations of Depends items // to the location of the corresponding product or module. // For a cursor such as this: // Depends { name: "cpp" } // ^ // We return the location of the module file that implements the cpp // backend for that particular product, e.g. GenericGCC.qbs. // In addition, items provided via import paths are looked up here. if (handleGotoDefViaCodeLinks(sourceFile, sourceDoc, sourcePos)) return; if (!sourceDoc) return sendResponse(nullptr); // Now check for // a) elements of the "files" and "references" properties. // b) usages of module properties, e.g. "qbs.toolchain" // For a cursor such as this: // Group { prefix: "sources/"; files: "main.cpp" } // ^ // We return the absolute path of the file, including the // group prefix. // Note that if we recorded the location of all source artifacts, // we would not need to do any parsing here and also we wouldn't // be limited to string literals. But that's probably not worth // the additional overhead. // For case a), the AST path looks as follows: // ... -> UiObjectDefinition -> UiObjectInitializer -> ObjectMemberList // -> UiScriptBinding -> ExpressionStatement [-> ArrayLiteral] // If the project file employs the syntactical sugar of using a single // string for one-element arrays, then there is no ArrayLiteral; instead, // the ExpressionStatement's expression is a StringLiteral that contains // the file path. // Sometimes, the AST path also ends in an ElementList instead of an ArrayLiteral. // This discrepancy is probably a bug in the path() function. // Case b) is simpler: We just check whether the last element of the AST path is a // qualified id or a script binding. Apparently, we get the former if there are three // or more components, and the latter otherwise. Again, this looks like a bug // in the locator. const int offset = posToOffset(params.position(), sourceDoc->currentContent) - 1; if (offset < 0 || offset >= sourceDoc->currentContent.length()) return sendResponse(nullptr); using namespace QbsQmlJS; using namespace QbsQmlJS::AST; Engine engine; Lexer lexer(&engine); lexer.setCode(sourceDoc->currentContent, 1); Parser parser(&engine); parser.parse(); if (!parser.ast()) return sendResponse(nullptr); AstNodeLocator locator(offset, *parser.ast()); const QList &astPath = locator.path(); if (astPath.isEmpty()) return sendResponse(nullptr); const StringLiteral *filePathLiteral = nullptr; const ElementList *elementList = nullptr; int bindingNodeIndex = 0; int objectNodeIndex = 0; const Node * const lastNode = astPath.last(); if (lastNode->kind == Node::Kind_UiQualifiedId) { return handleGotoDefForModuleProperties( sourceFile, static_cast(lastNode), offset); } if (lastNode->kind == Node::Kind_UiScriptBinding) { return handleGotoDefForModuleProperties( sourceFile, static_cast(lastNode)->qualifiedId, offset); } if (lastNode->kind == Node::Kind_ArrayLiteral) { bindingNodeIndex = astPath.size() - 3; objectNodeIndex = astPath.size() - 6; elementList = static_cast(lastNode)->elements; } else if (lastNode->kind == Node::Kind_ElementList) { bindingNodeIndex = astPath.size() - 4; objectNodeIndex = astPath.size() - 7; elementList = static_cast(lastNode); } else if (lastNode->kind == Node::Kind_ExpressionStatement) { bindingNodeIndex = astPath.size() - 2; objectNodeIndex = astPath.size() - 5; const auto filePathExpr = static_cast(lastNode)->expression; if (filePathExpr && filePathExpr->kind == Node::Kind_StringLiteral) filePathLiteral = static_cast(filePathExpr); } if (elementList) { for (const ElementList *l = elementList; l; l = l->next) { if (l->expression->kind != Node::Kind_StringLiteral) continue; const auto s = static_cast(l->expression); if (int(s->firstSourceLocation().offset) > offset) break; if (int(s->lastSourceLocation().offset + s->lastSourceLocation().length) > offset) { filePathLiteral = s; break; } } } if (!filePathLiteral) return sendResponse(nullptr); if (objectNodeIndex < 0) return sendResponse(nullptr); const auto filesNode = astPath.at(bindingNodeIndex); if (filesNode->kind != Node::Kind_UiScriptBinding) return sendResponse(nullptr); const QStringRef bindingName = static_cast(filesNode)->qualifiedId->name; const bool isFilesProperty = bindingName == "files"; const bool isReferencesProperty = bindingName == "references"; if (!isFilesProperty && !isReferencesProperty) return sendResponse(nullptr); const Node * const objectNode = astPath.at(objectNodeIndex); if (objectNode->kind != Node::Kind_UiObjectDefinition) return sendResponse(nullptr); const SourceLocation loc = objectNode->firstSourceLocation(); QString absoluteFilePath = filePathLiteral->value.toString(); const auto sendFilePath = [&] { const lsp::Position startPos(0, 0); const lsp::Position endPos(0, 1); lsp::Location targetLocation; targetLocation.setUri( lsp::DocumentUri::fromProtocol(QUrl::fromLocalFile(absoluteFilePath).toString())); targetLocation.setRange({lsp::Position(0, 0), lsp::Position(0, 1)}); sendResponse(QJsonObject(targetLocation)); }; if (QFileInfo(absoluteFilePath).isAbsolute()) return sendFilePath(); if (isFilesProperty) { using GroupAndProduct = std::optional>; const std::function findGroup = [&](const ProjectData &project) -> GroupAndProduct { for (const ProductData &product : project.products()) { for (const GroupData &group : product.groups()) { if (group.location().filePath() == sourceFile && group.location().line() == int(loc.startLine) && group.location().column() == int(loc.startColumn)) return std::make_pair(group, product); } } for (const ProjectData &subProject : project.subProjects()) { if (const auto &g = findGroup(subProject)) return g; } return {}; }; const auto groupAndProduct = findGroup(projectData); if (!groupAndProduct) return sendResponse(nullptr); absoluteFilePath.prepend(groupAndProduct->first.prefix()); if (QFileInfo(absoluteFilePath).isAbsolute()) return sendFilePath(); } else { const std::function(const ProjectData &)> findProject = [&](const ProjectData &project) -> std::optional { if (project.location().filePath() == sourceFile && project.location().line() == int(loc.startLine) && project.location().column() == int(loc.startColumn)) { return project; } for (const ProjectData &subProject : project.subProjects()) { if (const auto &p = findProject(subProject)) return p; } return {}; }; const auto project = findProject(projectData); if (!project) return sendResponse(nullptr); } absoluteFilePath = QFileInfo(sourceFile).absoluteDir().filePath(absoluteFilePath); sendFilePath(); } // We operate under the assumption that the client has basic QML support. // Therefore, we only provide completion for qbs modules and their properties. // Only a simple prefix match is implemented, with no regard to the contents after the cursor. void LspServer::Private::handleCompletionRequest() { if (!projectData.isValid()) return sendResponse(nullptr); const lsp::CompletionParams params(messageObject.value(lsp::paramsKey)); const QString sourceFile = params.textDocument().uri().toLocalFile(); const Document *sourceDoc = nullptr; if (const auto it = documents.find(sourceFile); it != documents.end()) sourceDoc = &it->second; if (!sourceDoc) return sendResponse(nullptr); const QList relevantProducts = getRelevantProducts(sourceFile); if (relevantProducts.isEmpty()) return sendResponse(nullptr); QString identifierPrefix; QStringList modulePrefixes; const int offset = posToOffset(params.position(), sourceDoc->currentContent) - 1; if (offset < 0 || offset >= sourceDoc->currentContent.length()) return sendResponse(nullptr); const auto collectFromRawString = [&] { int currentPos = offset; const auto constructIdentifier = [&] { QString id; while (currentPos >= 0) { const QChar c = sourceDoc->currentContent.at(currentPos); if (!c.isLetterOrNumber() && c != '_') break; id.prepend(c); --currentPos; } return id; }; identifierPrefix = constructIdentifier(); while (true) { if (currentPos <= 0 || sourceDoc->currentContent.at(currentPos) != '.') return; --currentPos; const QString modulePrefix = constructIdentifier(); if (modulePrefix.isEmpty()) return; modulePrefixes.prepend(modulePrefix); } }; // Parse the current file. Note that completion usually happens on invalid code, which // often confuses the parser so much that it yields unusable results. Therefore, we always // gather our input parameters from the raw string. We only use the parse result to skip // completion in contexts where it is undesirable. QbsQmlJS::Engine engine; QbsQmlJS::Lexer lexer(&engine); lexer.setCode(sourceDoc->currentContent, 1); QbsQmlJS::Parser parser(&engine); parser.parse(); if (parser.ast()) { AstNodeLocator locator(offset, *parser.ast()); const QList &astPath = locator.path(); if (!astPath.isEmpty()) { switch (astPath.last()->kind) { case QbsQmlJS::AST::Node::Kind_FieldMemberExpression: case QbsQmlJS::AST::Node::Kind_UiObjectDefinition: case QbsQmlJS::AST::Node::Kind_UiQualifiedId: case QbsQmlJS::AST::Node::Kind_UiScriptBinding: break; default: return sendResponse(nullptr); } } } collectFromRawString(); if (modulePrefixes.isEmpty() && identifierPrefix.isEmpty()) return sendResponse(nullptr); // We do not want to start completion from nothing. QJsonArray results; QMap namesAndTypes; for (const ProductData &product : relevantProducts) { const PropertyMap &moduleProps = product.moduleProperties(); const QStringList allModules = moduleProps.allModules(); const QString moduleNameOrPrefix = modulePrefixes.join('.'); // Case 1: Prefixes match a module name. Identifier can only expand to the name // of a module property. // Example: "Qt.core.a^" -> "Qt.core.availableBuildVariants" if (!modulePrefixes.isEmpty() && allModules.contains(moduleNameOrPrefix)) { for (const PropertyMap::PropertyInfo &info : moduleProps.allPropertiesForModule(moduleNameOrPrefix)) { if (info.isBuiltin) continue; if (!identifierPrefix.isEmpty() && !info.name.startsWith(identifierPrefix)) continue; namesAndTypes.insert(info.name, info.type); } continue; } // Case 2: Isolated identifier. Can only expand to a module name. // Example: "Q^" -> "Qt.core", "Qt.widgets", ... // Case 3: Prefixes match a module prefix. Identifier can only expand to a module name. // Example: "Qt.c^" -> "Qt.core", "Qt.concurrent", ... QString fullPrefix = identifierPrefix; int nameOffset = 0; if (!modulePrefixes.isEmpty()) { fullPrefix.prepend(moduleNameOrPrefix + '.'); nameOffset = moduleNameOrPrefix.length() + 1; } for (const QString &module : allModules) { if (module.startsWith(fullPrefix)) namesAndTypes.insert(module.mid(nameOffset), {}); } } for (auto it = namesAndTypes.cbegin(); it != namesAndTypes.cend(); ++it) { lsp::CompletionItem item; item.setLabel(it.key()); if (!it.value().isEmpty()) item.setDetail(it.value()); results.append(QJsonObject(item)); }; sendResponse(results); } void LspServer::Private::handleShutdownRequest() { state = State::Shutdown; sendResponse(nullptr); } void LspServer::Private::handleDidOpenNotification() { const lsp::TextDocumentItem docItem = lsp::DidOpenTextDocumentNotification(messageObject) .params().value_or(lsp::DidOpenTextDocumentParams()) .textDocument(); if (!docItem.isValid()) return sendErrorNotification(Tr::tr("Invalid didOpen parameters.")); const QString filePath = uriToString(docItem.uri()); Document &doc = documents[filePath]; doc.savedContent = doc.currentContent = docItem.text(); } void LspServer::Private::handleDidChangeNotification() { const auto params = lsp::DidChangeTextDocumentNotification(messageObject) .params().value_or(lsp::DidChangeTextDocumentParams()); if (!params.isValid()) return sendErrorNotification(Tr::tr("Invalid didChange parameters.")); const QString filePath = uriToString(params.textDocument().uri()); const auto docIt = documents.find(filePath); if (docIt == documents.end()) return sendNoSuchDocumentError(filePath); Document &doc = docIt->second; const auto changes = params.contentChanges(); for (const auto &change : changes) { const auto range = change.range(); if (!range) { doc.currentContent = change.text(); continue; } const int startPos = posToOffset(range->start(), doc.currentContent); const int endPos = posToOffset(range->end(), doc.currentContent); if (startPos == -1 || endPos == -1 || startPos > endPos) return sendErrorResponse(LspErrorResponse::InvalidParams, Tr::tr("Invalid range.")); doc.currentContent.replace(startPos, endPos - startPos, change.text()); } } void LspServer::Private::handleDidSaveNotification() { const QString filePath = uriToString(lsp::DidSaveTextDocumentNotification(messageObject) .params().value_or(lsp::DidSaveTextDocumentParams()) .textDocument().uri()); const auto docIt = documents.find(filePath); if (docIt == documents.end()) return sendNoSuchDocumentError(filePath); docIt->second.savedContent = docIt->second.currentContent; // TODO: Mark the project data as out of date until the next update(),if the document // is in buildSystemFiles(). } void LspServer::Private::handleDidCloseNotification() { const QString filePath = uriToString(lsp::DidCloseTextDocumentNotification(messageObject) .params().value_or(lsp::DidCloseTextDocumentParams()) .textDocument().uri()); const auto docIt = documents.find(filePath); if (docIt == documents.end()) return sendNoSuchDocumentError(filePath); documents.erase(docIt); } bool LspServer::Private::handleGotoDefViaCodeLinks( const QString &sourceFile, const Document *sourceDoc, const CodePosition &sourcePos) { if (sourceDoc && !sourceDoc->isPositionUpToDate(sourcePos)) return false; const auto fileEntry = codeLinks.constFind(sourceFile); if (fileEntry == codeLinks.constEnd()) return false; for (auto it = fileEntry->begin(); it != fileEntry->cend(); ++it) { if (!it.key().contains(sourcePos)) continue; if (sourceDoc && !sourceDoc->isPositionUpToDate(it.key().end())) return false; QList targets = it.value(); QBS_ASSERT(!targets.isEmpty(), return false); for (auto it = targets.begin(); it != targets.end();) { const Document *targetDoc = nullptr; if (it->filePath() == sourceFile) targetDoc = sourceDoc; else if (const auto docIt = documents.find(it->filePath()); docIt != documents.end()) targetDoc = &docIt->second; if (targetDoc && !targetDoc->isPositionUpToDate(CodePosition(it->line(), it->column()))) it = targets.erase(it); else ++it; } const QJsonArray locations = toLspLocations(targets); if (locations.size() == 1) sendResponse(locations.first().toObject()); else sendResponse(locations); return true; } return false; } void LspServer::Private::handleGotoDefForModuleProperties( const QString &sourceFile, const QbsQmlJS::AST::UiQualifiedId *node, int offset) { QStringList qualifiedProperty; bool cursorIsOnProperty = false; for (const QbsQmlJS::AST::UiQualifiedId *qid = node; qid; qid = qid->next) { qualifiedProperty << qid->name.toString(); if (!qid->next && int(qid->firstSourceLocation().offset) <= offset) cursorIsOnProperty = true; } if (qualifiedProperty.size() < 2) return sendResponse(nullptr); const QList relevantProducts = getRelevantProducts(sourceFile); if (relevantProducts.isEmpty()) return sendResponse(nullptr); const QString moduleName = qualifiedProperty.mid(0, qualifiedProperty.size() - 1).join('.'); const QString propertyName = qualifiedProperty.last(); QSet locations; for (const ProductData &p : relevantProducts) { for (const ModuleData &m : p.modules()) { if (m.name() != moduleName) continue; if (cursorIsOnProperty) { for (const auto &prop : m.properties()) { if (prop.first == propertyName) { locations << prop.second; break; } } } else { locations << m.location(); } break; } } if (locations.isEmpty()) return sendResponse(nullptr); const QJsonArray lspLocations = toLspLocations(toList(locations)); if (lspLocations.size() == 1) return sendResponse(lspLocations.first().toObject()); sendResponse(lspLocations); } // If there are products corresponding to the given source file, return only these. // Otherwise, return all products. QList LspServer::Private::getRelevantProducts(const QString &sourceFile) { const QList allProducts = projectData.allProducts(); QList relevantProducts; for (const ProductData &p : allProducts) { if (p.location().filePath() == sourceFile) relevantProducts << p; } if (relevantProducts.isEmpty()) return allProducts; return relevantProducts; } static int posToOffset(const CodePosition &pos, const QString &doc) { int offset = 0; for (int newlines = 0, next = 0; newlines < pos.line() - 1; ++newlines) { offset = doc.indexOf('\n', next); if (offset == -1) return -1; next = offset + 1; } return offset + pos.column(); } bool Document::isPositionUpToDate(const CodePosition &pos) const { const int origOffset = posToOffset(pos, savedContent); if (origOffset > int(currentContent.size())) return false; return QStringView(currentContent).left(origOffset) == QStringView(savedContent).left(origOffset); } bool Document::isPositionUpToDate(const lsp::Position &pos) const { return isPositionUpToDate(posFromLspPos(pos)); } } // namespace qbs::Internal qbs-src-3.3.1/src/app/qbs/commandlinefrontend.h0000644000175100017510000001070415232633614021040 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDLINEFRONTEND_H #define COMMANDLINEFRONTEND_H #include "parser/commandlineparser.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE namespace qbs { class AbstractJob; class ConsoleProgressObserver; class ErrorInfo; class ProcessResult; class ProjectGenerator; class Settings; class CommandLineFrontend : public QObject { Q_OBJECT public: explicit CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent = nullptr); ~CommandLineFrontend() override; void cancel(); void start(); private: void handleCommandDescriptionReport(const QString &highlight, const QString &message); void handleJobFinished(bool success, qbs::AbstractJob *job); void handleNewTaskStarted(const QString &description, int totalEffort); void handleTotalEffortChanged(int totalEffort); void handleTaskProgress(int value, qbs::AbstractJob *job); void handleProcessResultReport(const qbs::ProcessResult &result); void checkCancelStatus(); using ProductMap = QHash>; ProductMap productsToUse() const; bool resolvingMultipleProjects() const; bool isResolving() const; bool isBuilding() const; void handleProjectsResolved(); void makeClean(); int runShell(); void build(); void checkGeneratorName(); void generate(); int runTarget(); void updateTimestamps(); void dumpNodesTree(); void listProducts(); void connectBuildJobs(); void connectBuildJob(AbstractJob *job); void connectJob(AbstractJob *job); ProductData getTheOneRunnableProduct(); void install(); BuildOptions buildOptions(const Project &project) const; QString buildDirectory(const QString &profileName) const; const CommandLineParser &m_parser; Settings * const m_settings; QList m_resolveJobs; QList m_buildJobs; QList m_projects; ConsoleProgressObserver *m_observer = nullptr; enum CancelStatus { CancelStatusNone, CancelStatusRequested, CancelStatusCanceling }; CancelStatus m_cancelStatus = CancelStatus::CancelStatusNone; QTimer * const m_cancelTimer; int m_buildEffortsNeeded = 0; int m_buildEffortsRetrieved = 0; int m_totalBuildEffort = 0; int m_currentBuildEffort = 0; QHash m_buildEfforts; std::shared_ptr m_generator; }; } // namespace qbs #endif // COMMANDLINEFRONTEND_H qbs-src-3.3.1/src/app/qbs/stdinreader.h0000644000175100017510000000451115232633614017315 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_STDINREADER_H #define QBS_STDINREADER_H #include namespace qbs { namespace Internal { class StdinReader : public QObject { Q_OBJECT public: static StdinReader *create(QObject *parent); virtual void start() = 0; signals: void errorOccurred(const QString &error); void dataAvailable(const QByteArray &data); protected: explicit StdinReader(QObject *parent); }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-3.3.1/src/app/qbs/lspserver.h0000644000175100017510000000436615232633614017046 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #include #include namespace qbs { class ProjectData; namespace Internal { class LspServer { public: LspServer(); ~LspServer(); void updateProjectData(const ProjectData &projectData, const CodeLinks &codeLinks); QString socketPath() const; private: class Private; Private * const d; }; } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/app/qbs/qbstool.h0000644000175100017510000000502515232633614016475 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QBSTOOL_H #define QBS_QBSTOOL_H #include class QbsTool { public: void runTool(const QString &toolName, const QStringList &arguments); bool failedToStart() const { return m_failedToStart; } int exitCode() const { return m_exitCode; } QString stdOut() const { return m_stdout; } QString stdErr() const { return m_stderr; } static QStringList allToolNames(); static bool tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode = 0); private: bool m_failedToStart = false; int m_exitCode = 0; QString m_stdout; QString m_stderr; }; #endif // QBS_QBSTOOL_H qbs-src-3.3.1/src/app/qbs/sessionpacket.cpp0000644000175100017510000001041115232633614020213 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "sessionpacket.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { const QByteArray packetStart = "qbsmsg:"; SessionPacket::Status SessionPacket::parseInput(QByteArray &input) { //qDebug() << m_expectedPayloadLength << m_payload << input; if (m_expectedPayloadLength == -1) { const int packetStartOffset = input.indexOf(packetStart); if (packetStartOffset == -1) return Status::Incomplete; const int numberOffset = packetStartOffset + packetStart.length(); const int newLineOffset = input.indexOf('\n', numberOffset); if (newLineOffset == -1) return Status::Incomplete; const QByteArray sizeString = input.mid(numberOffset, newLineOffset - numberOffset); bool isNumber; const int payloadLen = sizeString.toInt(&isNumber); if (!isNumber || payloadLen < 0) return Status::Invalid; m_expectedPayloadLength = payloadLen; input.remove(0, newLineOffset + 1); } const int bytesToAdd = m_expectedPayloadLength - m_payload.length(); QBS_ASSERT(bytesToAdd >= 0, return Status::Invalid); m_payload += input.left(bytesToAdd); input.remove(0, bytesToAdd); return isComplete() ? Status::Complete : Status::Incomplete; } QJsonObject SessionPacket::retrievePacket() { QBS_ASSERT(isComplete(), return QJsonObject()); auto packet = QJsonDocument::fromJson(QByteArray::fromBase64(m_payload)).object(); m_payload.clear(); m_expectedPayloadLength = -1; return packet; } QByteArray SessionPacket::createPacket(const QJsonObject &packet) { const QByteArray jsonData = QJsonDocument(packet).toJson(QJsonDocument::Compact).toBase64(); return QByteArray(packetStart).append(QByteArray::number(jsonData.length())).append('\n') .append(jsonData); } QJsonObject SessionPacket::helloMessage(const QString &lspSocket) { return QJsonObject{ {StringConstants::type(), QLatin1String("hello")}, {QLatin1String("api-level"), 9}, {QLatin1String("api-compat-level"), 2}, {QLatin1String("lsp-socket"), lspSocket}}; } bool SessionPacket::isComplete() const { return m_payload.length() == m_expectedPayloadLength; } } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/app/qbs/status.h0000644000175100017510000000377515232633614016347 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef STATUS_H #define STATUS_H namespace qbs { class ProjectData; int printStatus(const ProjectData &project); } // namespace qbs #endif // STATUS_H qbs-src-3.3.1/src/app/qbs/sessionpacketreader.cpp0000644000175100017510000000702315232633614021403 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "sessionpacketreader.h" #include "sessionpacket.h" #include "stdinreader.h" #include namespace qbs { namespace Internal { class SessionPacketReader::Private { public: QByteArray incomingData; SessionPacket currentPacket; }; SessionPacketReader::SessionPacketReader(QObject *parent) : QObject(parent) , d(std::make_unique()) { } SessionPacketReader::~SessionPacketReader() = default; void SessionPacketReader::start() { StdinReader * const stdinReader = StdinReader::create(this); connect(stdinReader, &StdinReader::errorOccurred, this, &SessionPacketReader::errorOccurred); connect(stdinReader, &StdinReader::dataAvailable, this, [this](const QByteArray &data) { /* Because this SessionPacketReader can be destroyed in the emit packetReceived, * use a `QPointer self(this)` to check whether this instance still exists. * When self evaluates to false, this instance should no longer be referenced, * so the parent QObject and d should no longer be used in any way. */ QPointer self(this); d->incomingData += data; while (self && !d->incomingData.isEmpty()) { switch (d->currentPacket.parseInput(d->incomingData)) { case SessionPacket::Status::Invalid: emit errorOccurred(tr("Received invalid input.")); return; case SessionPacket::Status::Complete: emit packetReceived(d->currentPacket.retrievePacket()); break; case SessionPacket::Status::Incomplete: return; } } }); stdinReader->start(); } } // namespace Internal } // namespace qbs qbs-src-3.3.1/src/app/qbs/ctrlchandler.h0000644000175100017510000000370615232633614017463 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CTRLCHANDLER_H #define CTRLCHANDLER_H void installCtrlCHandler(); #endif // CTRLCHANDLER_H qbs-src-3.3.1/src/app/qbs/sessionpacketreader.h0000644000175100017510000000471015232633614021050 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SESSIONPACKETREADER_H #define QBS_SESSIONPACKETREADER_H #include #include #include namespace qbs { namespace Internal { class SessionPacketReader : public QObject { Q_OBJECT public: explicit SessionPacketReader(QObject *parent = nullptr); ~SessionPacketReader() override; void start(); signals: void packetReceived(const QJsonObject &packet); void errorOccurred(const QString &msg); private: class Private; const std::unique_ptr d; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-3.3.1/src/app/qbs/main.cpp0000644000175100017510000000660615232633614016277 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "qbstool.h" #include "parser/commandlineparser.h" #include "../shared/logging/consolelogger.h" #include #include #include using namespace qbs; static bool tryToRunTool(const QStringList &arguments, int &exitCode) { if (arguments.empty()) return false; QStringList toolArgs = arguments; const QString toolName = toolArgs.takeFirst(); if (toolName.startsWith(QLatin1Char('-'))) return false; return QbsTool::tryToRunTool(toolName, toolArgs, &exitCode); } int main(int argc, char *argv[]) { ConsoleLogger::instance(); try { Application app(argc, argv); QStringList arguments = app.arguments(); arguments.removeFirst(); int toolExitCode = 0; if (tryToRunTool(arguments, toolExitCode)) return toolExitCode; CommandLineParser parser; if (!parser.parseCommandLine(arguments)) return EXIT_FAILURE; if (parser.command() == HelpCommandType) { parser.printHelp(); return 0; } Settings settings(parser.settingsDir()); ConsoleLogger::instance().setSettings(&settings); CommandLineFrontend clFrontend(parser, &settings); app.setCommandLineFrontend(&clFrontend); QTimer::singleShot(0, &clFrontend, &CommandLineFrontend::start); return app.exec(); } catch (const ErrorInfo &error) { qbsError() << error.toString(); return EXIT_FAILURE; } } qbs-src-3.3.1/src/app/qbs/parser/0000755000175100017510000000000015232633614016133 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs/parser/commandpool.h0000644000175100017510000000453215232633614020620 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDPOOL_H #define QBS_COMMANDPOOL_H #include "commandtype.h" #include namespace qbs { class Command; class CommandLineOptionPool; class CommandPool { Q_DISABLE_COPY(CommandPool) public: CommandPool(CommandLineOptionPool &optionPool); ~CommandPool(); Command *getCommand(CommandType type) const; private: CommandLineOptionPool &m_optionPool; mutable QHash m_commands; }; } // namespace qbs #endif // QBS_COMMANDPOOL_H qbs-src-3.3.1/src/app/qbs/parser/commandlineparser.cpp0000644000175100017510000005517615232633614022360 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include "commandpool.h" #include "parsercommand.h" #include "../qbstool.h" #include "../../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif namespace qbs { using Internal::Tr; class CommandLineParser::CommandLineParserPrivate { public: CommandLineParserPrivate(); void doParse(); Command *commandFromString(const QString &commandString) const; QList allCommands() const; QString generalHelp() const; void setupProjectFile(); void setupBuildDirectory(); void setupProgress(); void setupLogLevel(); void setupBuildOptions(); void setupBuildConfigurations(); bool checkForExistingBuildConfiguration(const QList &buildConfigs, const QString &configurationName); bool withNonDefaultProducts() const; bool dryRun() const; QString settingsDir() const { return optionPool.settingsDirOption()->settingsDir(); } CommandEchoMode echoMode() const; QString propertyName(const QString &aCommandLineName) const; QStringList commandLine; Command *command; QString projectFilePath; QString projectBuildDirectory; BuildOptions buildOptions; QList buildConfigurations; CommandLineOptionPool optionPool; CommandPool commandPool; bool showProgress; bool logTime; }; CommandLineParser::CommandLineParser() = default; CommandLineParser::~CommandLineParser() = default; void CommandLineParser::printHelp() const { QTextStream stream(stdout); Q_ASSERT(d->command == d->commandPool.getCommand(HelpCommandType)); const auto helpCommand = static_cast(d->command); if (helpCommand->commandToDescribe().isEmpty()) { stream << "Qbs " QBS_VERSION ", a cross-platform build tool.\n"; stream << d->generalHelp(); } else { const Command * const commandToDescribe = d->commandFromString(helpCommand->commandToDescribe()); if (commandToDescribe) { stream << commandToDescribe->longDescription(); } else if (!QbsTool::tryToRunTool(helpCommand->commandToDescribe(), QStringList(QStringLiteral("--help")))) { throw ErrorInfo(Tr::tr("No such command '%1'.\n%2") .arg(helpCommand->commandToDescribe(), d->generalHelp())); } } } CommandType CommandLineParser::command() const { return d->command->type(); } QString CommandLineParser::projectFilePath() const { return d->projectFilePath; } QString CommandLineParser::projectBuildDirectory() const { return d->projectBuildDirectory; } BuildOptions CommandLineParser::buildOptions(const QString &profile) const { d->buildOptions.setMaxJobCount(jobCount(profile)); if (d->buildOptions.echoMode() < 0) { Settings settings(settingsDir()); d->buildOptions.setEchoMode(Preferences(&settings, profile).defaultEchoMode()); } return d->buildOptions; } CleanOptions CommandLineParser::cleanOptions(const QString &profile) const { CleanOptions options; options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } GenerateOptions CommandLineParser::generateOptions() const { GenerateOptions options; options.setGeneratorName(d->optionPool.generatorOption()->generatorName()); return options; } InstallOptions CommandLineParser::installOptions(const QString &profile) const { InstallOptions options; options.setRemoveExistingInstallation(d->optionPool.removeFirstoption()->enabled()); options.setInstallRoot(d->optionPool.installRootOption()->installRoot()); options.setInstallIntoSysroot(d->optionPool.installRootOption()->useSysroot()); if (!options.installRoot().isEmpty()) { QFileInfo fi(options.installRoot()); if (!fi.isAbsolute()) options.setInstallRoot(fi.absoluteFilePath()); } options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } int CommandLineParser::jobCount(const QString &profile) const { if (const int explicitJobCount = d->optionPool.jobsOption()->jobCount(); explicitJobCount > 0) return explicitJobCount; Settings settings(settingsDir()); return Preferences(&settings, profile).jobs(); } bool CommandLineParser::forceTimestampCheck() const { return d->optionPool.forceTimestampCheckOption()->enabled(); } bool CommandLineParser::forceOutputCheck() const { return d->optionPool.forceOutputCheckOption()->enabled(); } bool CommandLineParser::dryRun() const { return d->dryRun(); } bool CommandLineParser::forceProbesExecution() const { return d->optionPool.forceProbesOption()->enabled(); } bool CommandLineParser::waitLockBuildGraph() const { return d->optionPool.waitLockOption()->enabled(); } bool CommandLineParser::logTime() const { return d->logTime; } bool CommandLineParser::withNonDefaultProducts() const { return d->withNonDefaultProducts(); } bool CommandLineParser::buildBeforeInstalling() const { return !d->optionPool.noBuildOption()->enabled(); } QStringList CommandLineParser::runArgs() const { Q_ASSERT(d->command->type() == RunCommandType); return static_cast(d->command)->targetParameters(); } QStringList CommandLineParser::products() const { return d->optionPool.productsOption()->arguments(); } QStringList CommandLineParser::runEnvConfig() const { return d->optionPool.runEnvConfigOption()->arguments(); } bool CommandLineParser::showProgress() const { return d->showProgress; } bool CommandLineParser::showVersion() const { return d->command->type() == VersionCommandType; } QString CommandLineParser::settingsDir() const { return d->settingsDir(); } DeprecationWarningMode CommandLineParser::deprecationWarningMode() const { return d->optionPool.deprecationWarningsOption()->mode(); } QString CommandLineParser::commandName() const { return d->command->representation(); } bool CommandLineParser::commandCanResolve() const { return d->command->canResolve(); } QString CommandLineParser::commandDescription() const { return d->command->longDescription(); } static QString getBuildConfigurationName(const QVariantMap &buildConfig) { return buildConfig.value(QStringLiteral("qbs.configurationName")).toString(); } QList CommandLineParser::buildConfigurations() const { return d->buildConfigurations; } bool CommandLineParser::parseCommandLine(const QStringList &args) { d = std::make_unique(); d->commandLine = args; try { d->doParse(); return true; } catch (const ErrorInfo &error) { qbsError() << error.toString(); return false; } } CommandLineParser::CommandLineParserPrivate::CommandLineParserPrivate() : command(nullptr), commandPool(optionPool), showProgress(false), logTime(false) { } void CommandLineParser::CommandLineParserPrivate::doParse() { if (commandLine.empty()) { // No command given, use default. command = commandPool.getCommand(BuildCommandType); } else { command = commandFromString(commandLine.front()); if (command) { const QString commandName = commandLine.takeFirst(); // if the command line contains a `` with // either `-h` or `--help` switch, we transform // it to corresponding `help ` instead const QStringList helpSwitches = {QStringLiteral("-h"), QStringLiteral("--help")}; if (auto it = std::find_first_of( commandLine.begin(), commandLine.end(), helpSwitches.begin(), helpSwitches.end()); it != commandLine.end()) { command = commandPool.getCommand(HelpCommandType); commandLine = QList{commandName}; // keep only command's name } } else { // No command given. if (commandLine.front() == QLatin1String("-h") || commandLine.front() == QLatin1String("--help")) { command = commandPool.getCommand(HelpCommandType); commandLine.takeFirst(); } else if (commandLine.front() == QLatin1String("-V") || commandLine.front() == QLatin1String("--version")) { command = commandPool.getCommand(VersionCommandType); commandLine.takeFirst(); } else { command = commandPool.getCommand(BuildCommandType); } } } command->parse(commandLine); if (command->type() == HelpCommandType || command->type() == VersionCommandType) return; setupBuildDirectory(); setupBuildConfigurations(); setupProjectFile(); setupProgress(); setupLogLevel(); setupBuildOptions(); } Command *CommandLineParser::CommandLineParserPrivate::commandFromString(const QString &commandString) const { const auto commands = allCommands(); for (Command * const command : commands) { if (command->representation() == commandString) return command; } return nullptr; } QList CommandLineParser::CommandLineParserPrivate::allCommands() const { return {commandPool.getCommand(GenerateCommandType), commandPool.getCommand(ResolveCommandType), commandPool.getCommand(BuildCommandType), commandPool.getCommand(CleanCommandType), commandPool.getCommand(RunCommandType), commandPool.getCommand(ShellCommandType), commandPool.getCommand(StatusCommandType), commandPool.getCommand(UpdateTimestampsCommandType), commandPool.getCommand(InstallCommandType), commandPool.getCommand(DumpNodesTreeCommandType), commandPool.getCommand(ListProductsCommandType), commandPool.getCommand(VersionCommandType), commandPool.getCommand(SessionCommandType), commandPool.getCommand(HelpCommandType)}; } static QString extractToolDescription(const QString &tool, const QString &output) { if (tool == QLatin1String("create-project")) { // This command uses QCommandLineParser, where the description is not in the first line. const int eol1Pos = output.indexOf(QLatin1Char('\n')); const int eol2Pos = output.indexOf(QLatin1Char('\n'), eol1Pos + 1); return output.mid(eol1Pos + 1, eol2Pos - eol1Pos - 1); } return output.left(output.indexOf(QLatin1Char('\n'))); } QString CommandLineParser::CommandLineParserPrivate::generalHelp() const { QString help = Tr::tr("Usage: qbs [command] [command parameters]\n"); help += Tr::tr("Built-in commands:\n"); const int rhsIndentation = 30; // Sorting the commands by name is nicer for the user. QMap commandMap; const auto commands = allCommands(); for (const Command * command : commands) commandMap.insert(command->representation(), command); for (const Command * command : std::as_const(commandMap)) { help.append(QLatin1String(" ")).append(command->representation()); const QString whitespace = QString(rhsIndentation - 2 - command->representation().size(), QLatin1Char(' ')); help.append(whitespace).append(command->shortDescription()).append(QLatin1Char('\n')); } QStringList toolNames = QbsTool::allToolNames(); toolNames.sort(); if (!toolNames.empty()) { help.append(QLatin1Char('\n')).append(Tr::tr("Auxiliary commands:\n")); for (const QString &toolName : std::as_const(toolNames)) { help.append(QLatin1String(" ")).append(toolName); const QString whitespace = QString(rhsIndentation - 2 - toolName.size(), QLatin1Char(' ')); QbsTool tool; tool.runTool(toolName, QStringList(QStringLiteral("--help"))); if (tool.exitCode() != 0) continue; const QString shortDescription = extractToolDescription(toolName, tool.stdOut()); help.append(whitespace).append(shortDescription).append(QLatin1Char('\n')); } } return help; } void CommandLineParser::CommandLineParserPrivate::setupProjectFile() { projectFilePath = optionPool.fileOption()->projectFilePath(); } void CommandLineParser::CommandLineParserPrivate::setupBuildDirectory() { projectBuildDirectory = optionPool.buildDirectoryOption()->projectBuildDirectory(); } void CommandLineParser::CommandLineParserPrivate::setupBuildOptions() { buildOptions.setDryRun(dryRun()); QStringList changedFiles = optionPool.changedFilesOption()->arguments(); QDir currentDir; for (QString &file : changedFiles) file = QDir::fromNativeSeparators(currentDir.absoluteFilePath(file)); buildOptions.setChangedFiles(changedFiles); buildOptions.setKeepGoing(optionPool.keepGoingOption()->enabled()); buildOptions.setForceTimestampCheck(optionPool.forceTimestampCheckOption()->enabled()); buildOptions.setForceOutputCheck(optionPool.forceOutputCheckOption()->enabled()); const JobsOption * jobsOption = optionPool.jobsOption(); buildOptions.setMaxJobCount(jobsOption->jobCount()); buildOptions.setLogElapsedTime(logTime); buildOptions.setEchoMode(echoMode()); buildOptions.setInstall(!optionPool.noInstallOption()->enabled()); buildOptions.setRemoveExistingInstallation(optionPool.removeFirstoption()->enabled()); buildOptions.setJobLimits(optionPool.jobLimitsOption()->jobLimits()); buildOptions.setProjectJobLimitsTakePrecedence( optionPool.respectProjectJobLimitsOption()->enabled()); buildOptions.setSettingsDirectory(settingsDir()); } void CommandLineParser::CommandLineParserPrivate::setupBuildConfigurations() { // first: configuration name, second: properties. // Empty configuration name used for global properties. using PropertyListItem = std::pair; QList propertiesPerConfiguration; const QString configurationNameKey = QStringLiteral("qbs.configurationName"); QString currentConfigurationName; QVariantMap currentProperties; const auto args = command->additionalArguments(); for (const QString &arg : args) { const int sepPos = arg.indexOf(QLatin1Char(':')); QBS_CHECK(sepPos > 0); const QString key = arg.left(sepPos); const QString rawValue = arg.mid(sepPos + 1); if (key == QLatin1String("config") || key == configurationNameKey) { propertiesPerConfiguration.push_back(std::make_pair(currentConfigurationName, currentProperties)); currentConfigurationName = rawValue; currentProperties.clear(); continue; } currentProperties.insert(propertyName(key), representationToVariant(rawValue)); } propertiesPerConfiguration.push_back(std::make_pair(currentConfigurationName, currentProperties)); if (propertiesPerConfiguration.size() == 1) // No configuration name specified on command line. propertiesPerConfiguration.push_back(PropertyListItem(QStringLiteral("default"), QVariantMap())); const QVariantMap globalProperties = propertiesPerConfiguration.takeFirst().second; QList buildConfigs; for (const PropertyListItem &item : std::as_const(propertiesPerConfiguration)) { QVariantMap properties = item.second; for (QVariantMap::ConstIterator globalPropIt = globalProperties.constBegin(); globalPropIt != globalProperties.constEnd(); ++globalPropIt) { if (!properties.contains(globalPropIt.key())) properties.insert(globalPropIt.key(), globalPropIt.value()); } const QString configurationName = item.first; if (checkForExistingBuildConfiguration(buildConfigs, configurationName)) { qbsWarning() << Tr::tr("Ignoring redundant request to build for configuration '%1'.") .arg(configurationName); continue; } properties.insert(configurationNameKey, configurationName); buildConfigs.push_back(properties); } buildConfigurations = buildConfigs; } void CommandLineParser::CommandLineParserPrivate::setupProgress() { const ShowProgressOption * const option = optionPool.showProgressOption(); showProgress = option->enabled(); #ifdef Q_OS_UNIX if (showProgress && !isatty(STDOUT_FILENO)) { showProgress = false; qbsWarning() << Tr::tr("Ignoring option '%1', because standard output is " "not connected to a terminal.").arg(option->longRepresentation()); } #endif } void CommandLineParser::CommandLineParserPrivate::setupLogLevel() { const LogLevelOption * const logLevelOption = optionPool.logLevelOption(); const VerboseOption * const verboseOption = optionPool.verboseOption(); const QuietOption * const quietOption = optionPool.quietOption(); int logLevel = logLevelOption->logLevel(); logLevel += verboseOption->count(); logLevel -= quietOption->count(); if (showProgress && logLevel != LoggerMinLevel) { const bool logLevelWasSetByUser = logLevelOption->logLevel() != defaultLogLevel() || verboseOption->count() > 0 || quietOption->count() > 0; if (logLevelWasSetByUser) { qbsInfo() << Tr::tr("Setting log level to '%1', because option '%2'" " has been given.").arg(logLevelName(LoggerMinLevel), optionPool.showProgressOption()->longRepresentation()); } logLevel = LoggerMinLevel; } if (logLevel < LoggerMinLevel) { qbsWarning() << Tr::tr("Cannot decrease log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMinLevel)); logLevel = LoggerMinLevel; } else if (logLevel > LoggerMaxLevel) { qbsWarning() << Tr::tr("Cannot increase log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMaxLevel)); logLevel = LoggerMaxLevel; } logTime = optionPool.logTimeOption()->enabled(); if (showProgress && logTime) { qbsWarning() << Tr::tr("Options '%1' and '%2' are incompatible. Ignoring '%2'.") .arg(optionPool.showProgressOption()->longRepresentation(), optionPool.logTimeOption()->longRepresentation()); logTime = false; } ConsoleLogger::instance().logSink()->setLogLevel(static_cast(logLevel)); } QString CommandLineParser::CommandLineParserPrivate::propertyName(const QString &aCommandLineName) const { // Make fully-qualified, ie "platform" -> "qbs.platform" if (aCommandLineName.contains(QLatin1Char('.'))) return aCommandLineName; return QLatin1String("qbs.") + aCommandLineName; } bool CommandLineParser::CommandLineParserPrivate::checkForExistingBuildConfiguration( const QList &buildConfigs, const QString &configurationName) { return Internal::any_of(buildConfigs, [&configurationName](const auto &buildConfig) { return configurationName == getBuildConfigurationName(buildConfig); }); } bool CommandLineParser::CommandLineParserPrivate::withNonDefaultProducts() const { if (command->type() == GenerateCommandType) return true; return optionPool.buildNonDefaultOption()->enabled(); } bool CommandLineParser::CommandLineParserPrivate::dryRun() const { if (command->type() == GenerateCommandType || command->type() == ListProductsCommandType) return true; return optionPool.dryRunOption()->enabled(); } CommandEchoMode CommandLineParser::CommandLineParserPrivate::echoMode() const { if (command->type() == GenerateCommandType) return CommandEchoModeSilent; if (optionPool.commandEchoModeOption()->commandEchoMode() < CommandEchoModeInvalid) return optionPool.commandEchoModeOption()->commandEchoMode(); return defaultCommandEchoMode(); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/parser/parsercommand.cpp0000644000175100017510000005073515232633614021504 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "parsercommand.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include #include #include #include #include #include #include namespace qbs { using namespace Internal; Command::~Command() = default; void Command::parse(QStringList &input) { while (!input.empty()) parseNext(input); } bool Command::canResolve() const { return supportedOptions().contains(CommandLineOption::FileOptionType); } void Command::parsePropertyAssignment(const QString &argument) { const auto throwError = [argument](const QString &msgTemplate) { ErrorInfo error(msgTemplate.arg(argument)); error.append(QLatin1String("Expected an assignment of the form :, " "profile: or config:.")); throw error; }; if (argument.startsWith(QLatin1Char('-'))) throwError(Tr::tr("Unexpected option '%1'.")); const int sepPos = argument.indexOf(QLatin1Char(':')); if (sepPos == -1) throwError(Tr::tr("Unexpected command line parameter '%1'.")); if (sepPos == 0) throwError(Tr::tr("Empty key not allowed in assignment '%1'.")); if (!canResolve() && argument.contains(QLatin1Char(':')) && !argument.startsWith(QLatin1String("config:"))) { throw ErrorInfo(Tr::tr("The '%1' command does not support property assignments.") .arg(representation())); } m_additionalArguments << argument; } QList Command::actualSupportedOptions() const { QList options = supportedOptions(); if (type() != HelpCommandType) options.push_back(CommandLineOption::SettingsDirOptionType); // Valid for almost all commands. return options; } void Command::parseOption(QStringList &input) { const QString optionString = input.front(); QBS_CHECK(optionString.startsWith(QLatin1Char('-'))); input.removeFirst(); if (optionString.size() == 1) throwError(Tr::tr("Empty options are not allowed.")); // Split up grouped short options. if (optionString.at(1) != QLatin1Char('-') && optionString.size() > 2) { QString parameter; for (int i = optionString.size(); --i > 0;) { const QChar c = optionString.at(i); if (c.isDigit()) { parameter.prepend(c); } else { if (!parameter.isEmpty()) { input.prepend(parameter); parameter.clear(); } input.prepend(QLatin1Char('-') + c); } } if (!parameter.isEmpty()) throwError(Tr::tr("Unknown numeric option '%1'.").arg(parameter)); return; } bool matchFound = false; const auto optionTypes = actualSupportedOptions(); for (const CommandLineOption::Type optionType : optionTypes) { CommandLineOption * const option = optionPool().getOption(optionType); if (option->shortRepresentation() != optionString && option->longRepresentation() != optionString) { continue; } if (contains(m_usedOptions, option) && !option->canAppearMoreThanOnce()) throwError(Tr::tr("Option '%1' cannot appear more than once.").arg(optionString)); option->parse(type(), optionString, input); m_usedOptions.insert(option); matchFound = true; break; } if (!matchFound) throwError(Tr::tr("Unknown option '%1'.").arg(optionString)); } void Command::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); if (input.front().startsWith(QLatin1Char('-'))) parseOption(input); else parsePropertyAssignment(input.takeFirst()); } QString Command::supportedOptionsDescription() const { // Sorting the options by name is nicer for the user. QMap optionMap; const auto opTypes = actualSupportedOptions(); for (const CommandLineOption::Type opType : opTypes) { const CommandLineOption * const option = optionPool().getOption(opType); optionMap.insert(option->longRepresentation(), option); } QString s = Tr::tr("The possible options are:\n"); for (const CommandLineOption *option : std::as_const(optionMap)) s += option->description(type()); return s; } void Command::throwError(const QString &reason) { ErrorInfo error(Tr::tr("Invalid use of command '%1': %2").arg(representation(), reason)); error.append(Tr::tr("Type 'qbs help %1' to see how to use this command.") .arg(representation())); throw error; } QString ResolveCommand::shortDescription() const { return Tr::tr("Resolve a project without building it."); } QString ResolveCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Resolves a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } QString ResolveCommand::representation() const { return QStringLiteral("resolve"); } static QList resolveOptions() { return { CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::DryRunOptionType, CommandLineOption::ForceProbesOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::DeprecationWarningsOptionType, CommandLineOption::JobsOptionType}; } QList ResolveCommand::supportedOptions() const { return resolveOptions(); } QString GenerateCommand::shortDescription() const { return Tr::tr("Generate project files for another build tool."); } QString GenerateCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Generates files to build the project using another build tool.\n"); return description += supportedOptionsDescription(); } QString GenerateCommand::representation() const { return QStringLiteral("generate"); } QList GenerateCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::InstallRootOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::GeneratorOptionType}; } QString BuildCommand::shortDescription() const { return Tr::tr("Build (parts of) a project. This is the default command."); } QString BuildCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Builds a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } static QString buildCommandRepresentation() { return QStringLiteral("build"); } QString BuildCommand::representation() const { return buildCommandRepresentation(); } static QList buildOptions() { QList options = resolveOptions(); return options << CommandLineOption::KeepGoingOptionType << CommandLineOption::ProductsOptionType << CommandLineOption::ChangedFilesOptionType << CommandLineOption::ForceTimestampCheckOptionType << CommandLineOption::ForceOutputCheckOptionType << CommandLineOption::BuildNonDefaultOptionType << CommandLineOption::CommandEchoModeOptionType << CommandLineOption::NoInstallOptionType << CommandLineOption::RemoveFirstOptionType << CommandLineOption::JobLimitsOptionType << CommandLineOption::RespectProjectJobLimitsOptionType << CommandLineOption::WaitLockOptionType; } QList BuildCommand::supportedOptions() const { return buildOptions(); } QString CleanCommand::shortDescription() const { return Tr::tr("Remove the files generated during a build."); } QString CleanCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Removes build artifacts for the given configuration(s).\n"); return description += supportedOptionsDescription(); } QString CleanCommand::representation() const { return QStringLiteral("clean"); } QList CleanCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::DryRunOptionType, CommandLineOption::KeepGoingOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::ProductsOptionType, CommandLineOption::QuietOptionType, CommandLineOption::SettingsDirOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::VerboseOptionType}; } QString InstallCommand::shortDescription() const { return Tr::tr("Install (parts of) a project."); } QString InstallCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...]\n") .arg(representation()); description += Tr::tr("Install all files marked as installable " "to their respective destinations.\n" "The project is built first, if necessary, unless the '%1' option " "is given.\n").arg(optionPool().noBuildOption()->longRepresentation()); return description += supportedOptionsDescription(); } QString InstallCommand::representation() const { return QStringLiteral("install"); } QList installOptions() { QList options = buildOptions() << CommandLineOption::InstallRootOptionType << CommandLineOption::NoBuildOptionType; options.removeOne(CommandLineOption::NoInstallOptionType); return options; } QList InstallCommand::supportedOptions() const { return installOptions(); } QString RunCommand::shortDescription() const { return QStringLiteral("Run an executable generated by building a project."); } QString RunCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] [:] ... " "[ -- ]\n").arg(representation()); description += Tr::tr("Run the specified product's executable with the specified arguments.\n"); description += Tr::tr("If the project has only one product, the '%1' option may be omitted.\n") .arg(optionPool().productsOption()->longRepresentation()); description += Tr::tr("The product will be built if it is not up to date; " "see the '%2' command.\n").arg(buildCommandRepresentation()); return description += supportedOptionsDescription(); } QString RunCommand::representation() const { return QStringLiteral("run"); } QList RunCommand::supportedOptions() const { return QList() << installOptions() << CommandLineOption::RunEnvConfigOptionType; } void RunCommand::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); if (input.front() != QLatin1String("--")) { Command::parseNext(input); return; } input.removeFirst(); m_targetParameters = input; input.clear(); } QString ShellCommand::shortDescription() const { return Tr::tr("Open a shell with a product's environment."); } QString ShellCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] [:] ...\n") .arg(representation()); description += Tr::tr("Opens a shell in the same environment that a build with the given " "parameters would use.\n"); return description += supportedOptionsDescription(); } QString ShellCommand::representation() const { return QStringLiteral("shell"); } QList ShellCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::ProductsOptionType}; } QString StatusCommand::shortDescription() const { return Tr::tr("Show the status of files in the project directory."); } QString StatusCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [config:]\n") .arg(representation()); description += Tr::tr("Lists all the files in the project directory and shows whether " "they are known to qbs in the respective configuration.\n"); return description += supportedOptionsDescription(); } QString StatusCommand::representation() const { return QStringLiteral("status"); } QList StatusCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType}; } QString UpdateTimestampsCommand::shortDescription() const { return Tr::tr("Mark the build as up to date."); } QString UpdateTimestampsCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Update the timestamps of all build artifacts, causing the next " "builds of the project to do nothing if no updates to source files happen in between.\n" "This functionality is useful if you know that the current changes to source files " "are irrelevant to the build.\n" "NOTE: Doing this causes a discrepancy between the \"real world\" and the information " "in the build graph, so use with care.\n"); return description += supportedOptionsDescription(); } QString UpdateTimestampsCommand::representation() const { return QStringLiteral("update-timestamps"); } QList UpdateTimestampsCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ProductsOptionType}; } QString DumpNodesTreeCommand::shortDescription() const { return Tr::tr("Dumps the nodes in the build graph to stdout."); } QString DumpNodesTreeCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Internal command; for debugging purposes only.\n"); return description += supportedOptionsDescription(); } QString DumpNodesTreeCommand::representation() const { return QStringLiteral("dump-nodes-tree"); } QList DumpNodesTreeCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::ProductsOptionType}; } QString ListProductsCommand::shortDescription() const { return Tr::tr("Lists all products in the project, including sub-projects."); } QString ListProductsCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[config:] " "[:] ...] ...\n").arg(representation()); return description += supportedOptionsDescription(); } QString ListProductsCommand::representation() const { return QStringLiteral("list-products"); } QList ListProductsCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType}; } QString HelpCommand::shortDescription() const { return Tr::tr("Show general or command-specific help."); } QString HelpCommand::longDescription() const { QString description = Tr::tr("qbs %1 []\n").arg(representation()); return description += Tr::tr("Shows either the general help or a description of " "the given command.\n"); } QString HelpCommand::representation() const { return QStringLiteral("help"); } QList HelpCommand::supportedOptions() const { return {}; } void HelpCommand::parseNext(QStringList &input) { if (input.empty()) return; if (input.size() > 1) throwError(Tr::tr("Cannot describe more than one command.")); m_command = input.takeFirst(); QBS_CHECK(input.empty()); } QString VersionCommand::shortDescription() const { return Tr::tr("Print the Qbs version number to stdout."); } QString VersionCommand::longDescription() const { QString description = Tr::tr("qbs %1\n").arg(representation()); return description += Tr::tr("%1\n").arg(shortDescription()); } QString VersionCommand::representation() const { return QStringLiteral("show-version"); } QList VersionCommand::supportedOptions() const { return {}; } void VersionCommand::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); throwError(Tr::tr("This command takes no arguments.")); } QString SessionCommand::shortDescription() const { return Tr::tr("Starts a session for an IDE."); } QString SessionCommand::longDescription() const { QString description = Tr::tr("qbs %1\n").arg(representation()); return description += Tr::tr("Communicates on stdin and stdout via a JSON-based API.\n" "Intended for use with other tools, such as IDEs.\n"); } QString SessionCommand::representation() const { return QLatin1String("session"); } void SessionCommand::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); throwError(Tr::tr("This command takes no arguments.")); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/parser/commandlineoptionpool.h0000644000175100017510000000717515232633614022727 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTIONPOOL_H #define QBS_COMMANDLINEOPTIONPOOL_H #include "commandlineoption.h" #include namespace qbs { class CommandLineOptionPool { public: ~CommandLineOptionPool(); CommandLineOption *getOption(CommandLineOption::Type type) const; FileOption *fileOption() const; BuildDirectoryOption *buildDirectoryOption() const; LogLevelOption *logLevelOption() const; VerboseOption *verboseOption() const; QuietOption *quietOption() const; ShowProgressOption *showProgressOption() const; DryRunOption *dryRunOption() const; ForceProbesOption *forceProbesOption() const; ChangedFilesOption *changedFilesOption() const; KeepGoingOption *keepGoingOption() const; JobsOption *jobsOption() const; ProductsOption *productsOption() const; NoInstallOption *noInstallOption() const; InstallRootOption *installRootOption() const; RemoveFirstOption *removeFirstoption() const; NoBuildOption *noBuildOption() const; ForceTimeStampCheckOption *forceTimestampCheckOption() const; ForceOutputCheckOption *forceOutputCheckOption() const; BuildNonDefaultOption *buildNonDefaultOption() const; LogTimeOption *logTimeOption() const; CommandEchoModeOption *commandEchoModeOption() const; SettingsDirOption *settingsDirOption() const; JobLimitsOption *jobLimitsOption() const; RespectProjectJobLimitsOption *respectProjectJobLimitsOption() const; GeneratorOption *generatorOption() const; WaitLockOption *waitLockOption() const; RunEnvConfigOption *runEnvConfigOption() const; DeprecationWarningsOption *deprecationWarningsOption() const; private: mutable QHash m_options; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTIONPOOL_H qbs-src-3.3.1/src/app/qbs/parser/parsercommand.h0000644000175100017510000002266215232633614021147 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PARSER_COMMAND_H #define QBS_PARSER_COMMAND_H #include "commandlineoption.h" #include "commandtype.h" #include namespace qbs { class CommandLineOptionPool; class Command { public: virtual ~Command(); virtual CommandType type() const = 0; virtual QString shortDescription() const = 0; virtual QString longDescription() const = 0; virtual QString representation() const = 0; void parse(QStringList &input); QStringList additionalArguments() const { return m_additionalArguments; } bool canResolve() const; protected: Command(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) {} const CommandLineOptionPool &optionPool() const { return m_optionPool; } QString supportedOptionsDescription() const; [[noreturn]] void throwError(const QString &reason); virtual void parseNext(QStringList &input); private: QList actualSupportedOptions() const; void parseOption(QStringList &input); void parsePropertyAssignment(const QString &argument); virtual QList supportedOptions() const = 0; QStringList m_additionalArguments; std::set m_usedOptions; const CommandLineOptionPool &m_optionPool; }; class ResolveCommand : public Command { public: ResolveCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ResolveCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class GenerateCommand : public Command { public: GenerateCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return GenerateCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class BuildCommand : public Command { public: BuildCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return BuildCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class CleanCommand : public Command { public: CleanCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return CleanCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class InstallCommand : public Command { public: InstallCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return InstallCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class RunCommand : public Command { public: RunCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QStringList targetParameters() const { return m_targetParameters; } private: CommandType type() const override { return RunCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; QStringList m_targetParameters; }; class ShellCommand : public Command { public: ShellCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ShellCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; // TODO: It seems wrong that a configuration has to be given here. Ideally, this command would just track *all* files regardless of conditions. Is that possible? class StatusCommand : public Command { public: StatusCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return StatusCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class UpdateTimestampsCommand : public Command { public: UpdateTimestampsCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return UpdateTimestampsCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class DumpNodesTreeCommand : public Command { public: DumpNodesTreeCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override{ return DumpNodesTreeCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class ListProductsCommand : public Command { public: ListProductsCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ListProductsCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class HelpCommand : public Command { public: HelpCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QString commandToDescribe() const { return m_command; } private: CommandType type() const override { return HelpCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; QString m_command; }; class VersionCommand : public Command { public: VersionCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return VersionCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; }; class SessionCommand : public Command { public: SessionCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return SessionCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override { return {}; } void parseNext(QStringList &input) override; }; } // namespace qbs #endif // QBS_PARSER_COMMAND_H qbs-src-3.3.1/src/app/qbs/parser/commandtype.h0000644000175100017510000000442015232633614020624 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDTYPE_H #define COMMANDTYPE_H namespace qbs { enum CommandType { ResolveCommandType, BuildCommandType, CleanCommandType, RunCommandType, ShellCommandType, StatusCommandType, UpdateTimestampsCommandType, DumpNodesTreeCommandType, InstallCommandType, HelpCommandType, GenerateCommandType, ListProductsCommandType, VersionCommandType, SessionCommandType, }; } // namespace qbs #endif // COMMANDTYPE_H qbs-src-3.3.1/src/app/qbs/parser/commandpool.cpp0000644000175100017510000000740715232633614021157 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandpool.h" #include "parsercommand.h" namespace qbs { CommandPool::CommandPool(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) { } CommandPool::~CommandPool() { qDeleteAll(m_commands); } qbs::Command *CommandPool::getCommand(CommandType type) const { Command *& command = m_commands[type]; if (!command) { switch (type) { case ResolveCommandType: command = new ResolveCommand(m_optionPool); break; case GenerateCommandType: command = new GenerateCommand(m_optionPool); break; case BuildCommandType: command = new BuildCommand(m_optionPool); break; case CleanCommandType: command = new CleanCommand(m_optionPool); break; case RunCommandType: command = new RunCommand(m_optionPool); break; case ShellCommandType: command = new ShellCommand(m_optionPool); break; case StatusCommandType: command = new StatusCommand(m_optionPool); break; case UpdateTimestampsCommandType: command = new UpdateTimestampsCommand(m_optionPool); break; case InstallCommandType: command = new InstallCommand(m_optionPool); break; case DumpNodesTreeCommandType: command = new DumpNodesTreeCommand(m_optionPool); break; case ListProductsCommandType: command = new ListProductsCommand(m_optionPool); break; case HelpCommandType: command = new HelpCommand(m_optionPool); break; case VersionCommandType: command = new VersionCommand(m_optionPool); break; case SessionCommandType: command = new SessionCommand(m_optionPool); break; } } return command; } } // namespace qbs qbs-src-3.3.1/src/app/qbs/parser/commandlineoption.h0000644000175100017510000003145315232633614022031 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTION_H #define QBS_COMMANDLINEOPTION_H #include "commandtype.h" #include #include #include #include namespace qbs { class CommandLineOption { public: enum Type { FileOptionType, BuildDirectoryOptionType, LogLevelOptionType, VerboseOptionType, QuietOptionType, JobsOptionType, KeepGoingOptionType, DryRunOptionType, ForceProbesOptionType, ShowProgressOptionType, ChangedFilesOptionType, ProductsOptionType, NoInstallOptionType, InstallRootOptionType, RemoveFirstOptionType, NoBuildOptionType, ForceTimestampCheckOptionType, ForceOutputCheckOptionType, BuildNonDefaultOptionType, LogTimeOptionType, CommandEchoModeOptionType, SettingsDirOptionType, JobLimitsOptionType, RespectProjectJobLimitsOptionType, GeneratorOptionType, WaitLockOptionType, RunEnvConfigOptionType, DeprecationWarningsOptionType, }; virtual ~CommandLineOption(); virtual QString description(CommandType command) const = 0; virtual QString shortRepresentation() const = 0; virtual QString longRepresentation() const = 0; virtual bool canAppearMoreThanOnce() const { return false; } void parse(CommandType command, const QString &representation, QStringList &input); protected: CommandLineOption(); QString getArgument(const QString &representation, QStringList &input); CommandType command() const { return m_command; } private: virtual void doParse(const QString &representation, QStringList &input) = 0; CommandType m_command; }; class FileOption : public CommandLineOption { public: QString projectFilePath() const { return m_projectFilePath; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_projectFilePath; }; class BuildDirectoryOption : public CommandLineOption { public: QString projectBuildDirectory() const { return m_projectBuildDirectory; } static QString magicProjectString(); static QString magicProjectDirString(); private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_projectBuildDirectory; }; class GeneratorOption : public CommandLineOption { public: QString generatorName() const { return m_generatorName; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_generatorName; }; class CountingOption : public CommandLineOption { public: int count() const { return m_count; } protected: CountingOption() : m_count(0) {} private: bool canAppearMoreThanOnce() const override{ return true; } void doParse(const QString &, QStringList &) override { ++m_count; } int m_count; }; class VerboseOption : public CountingOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class QuietOption : public CountingOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class JobsOption : public CommandLineOption { public: JobsOption() : m_jobCount(0) {} int jobCount() const { return m_jobCount; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; int m_jobCount; }; class OnOffOption : public CommandLineOption { public: bool enabled() const { return m_enabled; } protected: OnOffOption() : m_enabled(false) {} private: void doParse(const QString &, QStringList &) override { m_enabled = true; } bool m_enabled; }; class KeepGoingOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class DryRunOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class ForceProbesOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class NoInstallOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ShowProgressOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ForceTimeStampCheckOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ForceOutputCheckOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class BuildNonDefaultOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class StringListOption : public CommandLineOption { public: QStringList arguments() const { return m_arguments; } private: void doParse(const QString &representation, QStringList &input) override; QStringList m_arguments; }; class ChangedFilesOption : public StringListOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ProductsOption : public StringListOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class RunEnvConfigOption : public StringListOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class LogLevelOption : public CommandLineOption { public: LogLevelOption(); int logLevel() const { return m_logLevel; } private: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; int m_logLevel; }; class InstallRootOption : public CommandLineOption { public: InstallRootOption(); QString installRoot() const { return m_installRoot; } bool useSysroot() const { return m_useSysroot; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; QString m_installRoot; bool m_useSysroot; }; class RemoveFirstOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class NoBuildOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class LogTimeOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class CommandEchoModeOption : public CommandLineOption { public: CommandEchoModeOption(); QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; CommandEchoMode commandEchoMode() const; private: void doParse(const QString &representation, QStringList &input) override; CommandEchoMode m_echoMode = CommandEchoModeInvalid; }; class DeprecationWarningsOption : public CommandLineOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; DeprecationWarningMode mode() const { return m_mode; } private: void doParse(const QString &representation, QStringList &input) override; DeprecationWarningMode m_mode = defaultDeprecationWarningMode(); }; class SettingsDirOption : public CommandLineOption { public: SettingsDirOption(); QString settingsDir() const { return m_settingsDir; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; QString m_settingsDir; }; class JobLimitsOption : public CommandLineOption { public: JobLimits jobLimits() const { return m_jobLimits; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; JobLimits m_jobLimits; }; class RespectProjectJobLimitsOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class WaitLockOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTION_H qbs-src-3.3.1/src/app/qbs/parser/commandlineparser.h0000644000175100017510000000713015232633614022010 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEPARSER_H #define QBS_COMMANDLINEPARSER_H #include "commandtype.h" #include #include #include #include namespace qbs { class BuildOptions; class CleanOptions; class GenerateOptions; class InstallOptions; class Settings; class CommandLineParser { Q_DISABLE_COPY(CommandLineParser) public: CommandLineParser(); ~CommandLineParser(); bool parseCommandLine(const QStringList &args); void printHelp() const; CommandType command() const; QString commandName() const; bool commandCanResolve() const; QString commandDescription() const; QString projectFilePath() const; QString projectBuildDirectory() const; BuildOptions buildOptions(const QString &profile) const; CleanOptions cleanOptions(const QString &profile) const; GenerateOptions generateOptions() const; InstallOptions installOptions(const QString &profile) const; int jobCount(const QString &profile) const; bool forceTimestampCheck() const; bool forceOutputCheck() const; bool dryRun() const; bool forceProbesExecution() const; bool waitLockBuildGraph() const; bool logTime() const; bool withNonDefaultProducts() const; bool buildBeforeInstalling() const; QStringList runArgs() const; QStringList products() const; QStringList runEnvConfig() const; QList buildConfigurations() const; bool showProgress() const; bool showVersion() const; QString settingsDir() const; DeprecationWarningMode deprecationWarningMode() const; private: class CommandLineParserPrivate; std::unique_ptr d; }; } // namespace qbs #endif // QBS_COMMANDLINEPARSER_H qbs-src-3.3.1/src/app/qbs/parser/commandlineoption.cpp0000644000175100017510000005710515232633614022366 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineoption.h" #include #include #include #include #include namespace qbs { using namespace Internal; CommandLineOption::~CommandLineOption() = default; void CommandLineOption::parse(CommandType command, const QString &representation, QStringList &input) { m_command = command; doParse(representation, input); } CommandLineOption::CommandLineOption() : m_command(static_cast(-1)) { } QString CommandLineOption::getArgument(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Missing argument.\nUsage: %2") .arg(representation, description(command()))); } return input.takeFirst(); } QString FileOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse as the project file.\n" "\tIf is a directory and it contains a single file ending in '.qbs',\n" "\tthat file will be used.\n" "\tIf this option is not given at all, behavior is the same as for '-f .'.\n") .arg(longRepresentation(), shortRepresentation()); } QString FileOption::shortRepresentation() const { return QStringLiteral("-f"); } QString FileOption::longRepresentation() const { return QStringLiteral("--file"); } void FileOption::doParse(const QString &representation, QStringList &input) { m_projectFilePath = getArgument(representation, input); } QString BuildDirectoryOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tBuild in the given directory. The default value is the current directory\n" "\tunless preferences.defaultBuildDirectory is set.\n" "\tRelative paths will be interpreted relative to the current directory.\n" "\tIf the directory does not exist, it will be created. Use the following\n" "\tspecial values as placeholders:\n" "\t%3: name of the project file excluding the extension\n" "\t%4: directory containing the project file\n") .arg(longRepresentation(), shortRepresentation(), magicProjectString(), magicProjectDirString()); } QString BuildDirectoryOption::shortRepresentation() const { return QStringLiteral("-d"); } QString BuildDirectoryOption::longRepresentation() const { return QStringLiteral("--build-directory"); } QString BuildDirectoryOption::magicProjectString() { return QStringLiteral("@project"); } QString BuildDirectoryOption::magicProjectDirString() { return QStringLiteral("@path"); } void BuildDirectoryOption::doParse(const QString &representation, QStringList &input) { m_projectBuildDirectory = getArgument(representation, input); } QString GeneratorOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse the given build system generator.\n") .arg(longRepresentation(), shortRepresentation()); } QString GeneratorOption::shortRepresentation() const { return QStringLiteral("-g"); } QString GeneratorOption::longRepresentation() const { return QStringLiteral("--generator"); } void GeneratorOption::doParse(const QString &representation, QStringList &input) { m_generatorName = getArgument(representation, input); if (m_generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No generator given.\nUsage: %2") .arg(representation, description(command()))); } } static QString loglevelLongRepresentation() { return QStringLiteral("--log-level"); } QString VerboseOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more verbose. Increases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to increase.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString VerboseOption::shortRepresentation() const { return QStringLiteral("-v"); } QString VerboseOption::longRepresentation() const { return QStringLiteral("--more-verbose"); } QString QuietOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more quiet. Decreases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to decrease.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString QuietOption::shortRepresentation() const { return QStringLiteral("-q"); } QString QuietOption::longRepresentation() const { return QStringLiteral("--less-verbose"); } QString JobsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse concurrent build jobs. must be an integer greater than zero.\n" "\tThe default is the number of cores.\n") .arg(longRepresentation(), shortRepresentation()); } QString JobsOption::shortRepresentation() const { return QStringLiteral("-j"); } QString JobsOption::longRepresentation() const { return QStringLiteral("--jobs"); } void JobsOption::doParse(const QString &representation, QStringList &input) { const QString jobCountString = getArgument(representation, input); bool stringOk; m_jobCount = jobCountString.toInt(&stringOk); if (!stringOk || m_jobCount <= 0) throw ErrorInfo(Tr::tr("Invalid use of option '%1': Illegal job count '%2'.\nUsage: %3") .arg(representation, jobCountString, description(command()))); } QString KeepGoingOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tKeep going when errors occur (if at all possible).\n") .arg(longRepresentation(), shortRepresentation()); } QString KeepGoingOption::shortRepresentation() const { return QStringLiteral("-k"); } QString KeepGoingOption::longRepresentation() const { return QStringLiteral("--keep-going"); } QString DryRunOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tDry run. No commands will be executed and no permanent changes to the\n" "\tbuild graph will be done.\n") .arg(longRepresentation(), shortRepresentation()); } QString DryRunOption::shortRepresentation() const { return QStringLiteral("-n"); } QString DryRunOption::longRepresentation() const { return QStringLiteral("--dry-run"); } QString ForceProbesOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tForce re-execution of all Probe items' configure scripts, rather than using the\n" "\tcached data.\n") .arg(longRepresentation()); } QString ForceProbesOption::longRepresentation() const { return QStringLiteral("--force-probe-execution"); } QString NoInstallOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tDo not install any artifacts as part of the build process.\n") .arg(longRepresentation()); } QString NoInstallOption::longRepresentation() const { return QStringLiteral("--no-install"); } static QString logTimeRepresentation() { return QStringLiteral("--log-time"); } QString ShowProgressOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n" "\tShow a progress bar. Implies '%2=%3'.\n").arg(longRepresentation(), loglevelLongRepresentation(), logLevelName(LoggerMinLevel)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(logTimeRepresentation()); } static QString showProgressRepresentation() { return QStringLiteral("--show-progress"); } QString ShowProgressOption::longRepresentation() const { return showProgressRepresentation(); } void StringListOption::doParse(const QString &representation, QStringList &input) { m_arguments = getArgument(representation, input).split(QLatin1Char(',')); if (m_arguments.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not be empty.\n" "Usage: %2").arg(representation, description(command()))); } for (const QString &element : std::as_const(m_arguments)) { if (element.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not contain " "empty elements.\nUsage: %2") .arg(representation, description(command()))); } } } QString ChangedFilesOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 [,...]\n" "\tAssume these and only these files have changed.\n").arg(longRepresentation()); } QString ChangedFilesOption::longRepresentation() const { return QStringLiteral("--changed-files"); } QString ProductsOption::description(CommandType command) const { const QString prefix = Tr::tr("%1|%2").arg(longRepresentation(), shortRepresentation()); switch (command) { case InstallCommandType: case RunCommandType: case ShellCommandType: return Tr::tr("%1 \n\tUse the specified product.\n").arg(prefix); default: return Tr::tr("%1 [,...]\n" "\tTake only the specified products into account.\n").arg(prefix); } } QString ProductsOption::shortRepresentation() const { return QStringLiteral("-p"); } QString ProductsOption::longRepresentation() const { return QStringLiteral("--products"); } static QStringList allLogLevelStrings() { QStringList result; for (int i = static_cast(LoggerMinLevel); i <= static_cast(LoggerMaxLevel); ++i) result << logLevelName(static_cast(i)); return result; } LogLevelOption::LogLevelOption() : m_logLevel(defaultLogLevel()) { } QString LogLevelOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tUse the specified log level.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n").arg(longRepresentation(), allLogLevelStrings().join(QLatin1String("', '")), logLevelName(defaultLogLevel())); } QString LogLevelOption::longRepresentation() const { return loglevelLongRepresentation(); } void LogLevelOption::doParse(const QString &representation, QStringList &input) { const QString levelString = getArgument(representation, input); const QList levels = QList() << LoggerError << LoggerWarning << LoggerInfo << LoggerDebug << LoggerTrace; for (const LoggerLevel &l : levels) { if (logLevelName(l) == levelString) { m_logLevel = l; return; } } throw ErrorInfo(Tr::tr("Invalid use of option '%1': Unknown log level '%2'.\nUsage: %3") .arg(representation, levelString, description(command()))); } QString ForceTimeStampCheckOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tForce timestamp checks.\n" "\tInstead of using the file timestamps that are stored in the build graph,\n" "\tretrieve the timestamps from the file system.\n").arg(longRepresentation()); } QString ForceTimeStampCheckOption::longRepresentation() const { return QStringLiteral("--check-timestamps"); } QString ForceOutputCheckOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tForce transformer output artifact checks.\n" "\tVerify that the output artifacts declared by rules in the\n" "\tproject are actually created.\n").arg(longRepresentation()); } QString ForceOutputCheckOption::longRepresentation() const { return QStringLiteral("--check-outputs"); } QString BuildNonDefaultOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tBuild all products, even if their builtByDefault property is false.\n") .arg(longRepresentation()); } QString BuildNonDefaultOption::longRepresentation() const { return QStringLiteral("--all-products"); } InstallRootOption::InstallRootOption() : m_useSysroot(false) { } static QString magicSysrootString() { return QStringLiteral("@sysroot"); } QString InstallRootOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tInstall into the given directory.\n" "\tThe default value is '/%2'.\n" "\tIf the directory does not exist, it will be created. Use the special\n" "\tvalue '%3' to install into the sysroot (i.e. the value of the\n" "\tproperty qbs.sysroot).\n") .arg(longRepresentation(), InstallOptions::defaultInstallRoot(), magicSysrootString()); } QString InstallRootOption::longRepresentation() const { return QStringLiteral("--install-root"); } void InstallRootOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } const QString installRoot = input.takeFirst(); if (installRoot == magicSysrootString()) m_useSysroot = true; else m_installRoot = installRoot; } QString RemoveFirstOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tRemove the installation base directory before installing.\n") .arg(longRepresentation()); } QString RemoveFirstOption::longRepresentation() const { return QStringLiteral("--clean-install-root"); } QString NoBuildOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tDo not build before installing.\n") .arg(longRepresentation()); } QString NoBuildOption::longRepresentation() const { return QStringLiteral("--no-build"); } QString LogTimeOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n\tLog the time that the operations involved in this command take.\n") .arg(longRepresentation()); desc += Tr::tr("\tThis option is implied in log levels '%1' and higher.\n") .arg(logLevelName(LoggerDebug)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(showProgressRepresentation()); } QString LogTimeOption::shortRepresentation() const { return QStringLiteral("-t"); } QString LogTimeOption::longRepresentation() const { return logTimeRepresentation(); } SettingsDirOption::SettingsDirOption() = default; QString SettingsDirOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tRead all settings (such as profile information) from the given directory.\n" "\tThe default value is system-specific (see the QSettings documentation).\n" "\tIf the directory does not exist, it will be created.\n") .arg(longRepresentation()); } QString SettingsDirOption::longRepresentation() const { return QStringLiteral("--settings-dir"); } void SettingsDirOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } m_settingsDir = input.takeFirst(); } QString JobLimitsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 :[,:...]\n" "\tSet pool-specific job limits.\n").arg(longRepresentation()); } QString JobLimitsOption::longRepresentation() const { return QStringLiteral("--job-limits"); } void JobLimitsOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } const QString jobLimitsSpec = input.takeFirst(); const QStringList jobLimitStrings = jobLimitsSpec.split(QLatin1Char(',')); for (const QString &jobLimitString : jobLimitStrings) { const int sepIndex = jobLimitString.indexOf(QLatin1Char(':')); if (sepIndex <= 0 || sepIndex == jobLimitString.size() - 1) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: " "Invalid job limits specification '%2'.\n" "Usage: %3").arg(representation, jobLimitsSpec, description(command()))); } const QString pool = jobLimitString.left(sepIndex); const QString limitString = jobLimitString.mid(sepIndex + 1); bool isValidNumber; const int limit = limitString.toInt(&isValidNumber); if (!isValidNumber) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: '%2' is not a number.\n" "Usage: %3").arg(representation, limitString, description(command()))); } m_jobLimits.setJobLimit(pool, limit); } } QString RespectProjectJobLimitsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tGive maximum priority to job limits defined inside the project.\n") .arg(longRepresentation()); } QString RespectProjectJobLimitsOption::longRepresentation() const { return QStringLiteral("--enforce-project-job-limits"); } CommandEchoModeOption::CommandEchoModeOption() = default; QString CommandEchoModeOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tKind of output to show when executing commands.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n") .arg(longRepresentation(), allCommandEchoModeStrings().join(QLatin1String("', '")), commandEchoModeName(defaultCommandEchoMode())); } QString CommandEchoModeOption::longRepresentation() const { return QStringLiteral("--command-echo-mode"); } CommandEchoMode CommandEchoModeOption::commandEchoMode() const { return m_echoMode; } void CommandEchoModeOption::doParse(const QString &representation, QStringList &input) { const QString mode = getArgument(representation, input); if (mode.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No command echo mode given.\nUsage: %2") .arg(representation, description(command()))); } if (!allCommandEchoModeStrings().contains(mode)) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': " "Invalid command echo mode '%2' given.\nUsage: %3") .arg(representation, mode, description(command()))); } m_echoMode = commandEchoModeFromName(mode); } QString DeprecationWarningsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tWhat to do when encountering deprecated items or properties.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n") .arg(longRepresentation(), allDeprecationWarningModeStrings().join(QLatin1String("', '")), deprecationWarningModeName(defaultDeprecationWarningMode())); } QString DeprecationWarningsOption::longRepresentation() const { return QStringLiteral("--deprecation-warnings"); } void DeprecationWarningsOption::doParse(const QString &representation, QStringList &input) { const QString mode = getArgument(representation, input); if (mode.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No deprecation warning mode given.\n" "Usage: %2") .arg(representation, description(command()))); } if (!allDeprecationWarningModeStrings().contains(mode)) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': " "Invalid deprecation warning mode '%2' given.\nUsage: %3") .arg(representation, mode, description(command()))); } m_mode = deprecationWarningModeFromName(mode); } QString WaitLockOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tWait indefinitely for other processes to release the build graph lock.\n") .arg(longRepresentation()); } QString WaitLockOption::longRepresentation() const { return QStringLiteral("--wait-lock"); } QString RunEnvConfigOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tComma-separated list of strings to pass to all modules' " "setupRunEnvironment scripts.\n").arg(longRepresentation()); } QString RunEnvConfigOption::longRepresentation() const { return QStringLiteral("--setup-run-env-config"); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/parser/commandlineoptionpool.cpp0000644000175100017510000002435715232633614023263 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineoptionpool.h" namespace qbs { CommandLineOptionPool::~CommandLineOptionPool() { qDeleteAll(m_options); } CommandLineOption *CommandLineOptionPool::getOption(CommandLineOption::Type type) const { CommandLineOption *& option = m_options[type]; if (!option) { switch (type) { case CommandLineOption::FileOptionType: option = new FileOption; break; case CommandLineOption::BuildDirectoryOptionType: option = new BuildDirectoryOption; break; case CommandLineOption::LogLevelOptionType: option = new LogLevelOption; break; case CommandLineOption::VerboseOptionType: option = new VerboseOption; break; case CommandLineOption::QuietOptionType: option = new QuietOption; break; case CommandLineOption::JobsOptionType: option = new JobsOption; break; case CommandLineOption::KeepGoingOptionType: option = new KeepGoingOption; break; case CommandLineOption::DryRunOptionType: option = new DryRunOption; break; case CommandLineOption::ForceProbesOptionType: option = new ForceProbesOption; break; case CommandLineOption::ShowProgressOptionType: option = new ShowProgressOption; break; case CommandLineOption::ChangedFilesOptionType: option = new ChangedFilesOption; break; case CommandLineOption::ProductsOptionType: option = new ProductsOption; break; case CommandLineOption::NoInstallOptionType: option = new NoInstallOption; break; case CommandLineOption::InstallRootOptionType: option = new InstallRootOption; break; case CommandLineOption::RemoveFirstOptionType: option = new RemoveFirstOption; break; case CommandLineOption::NoBuildOptionType: option = new NoBuildOption; break; case CommandLineOption::ForceTimestampCheckOptionType: option = new ForceTimeStampCheckOption; break; case CommandLineOption::ForceOutputCheckOptionType: option = new ForceOutputCheckOption; break; case CommandLineOption::BuildNonDefaultOptionType: option = new BuildNonDefaultOption; break; case CommandLineOption::LogTimeOptionType: option = new LogTimeOption; break; case CommandLineOption::CommandEchoModeOptionType: option = new CommandEchoModeOption; break; case CommandLineOption::SettingsDirOptionType: option = new SettingsDirOption; break; case CommandLineOption::JobLimitsOptionType: option = new JobLimitsOption; break; case CommandLineOption::RespectProjectJobLimitsOptionType: option = new RespectProjectJobLimitsOption; break; case CommandLineOption::GeneratorOptionType: option = new GeneratorOption; break; case CommandLineOption::WaitLockOptionType: option = new WaitLockOption; break; case CommandLineOption::RunEnvConfigOptionType: option = new RunEnvConfigOption; break; case CommandLineOption::DeprecationWarningsOptionType: option = new DeprecationWarningsOption; break; default: qFatal("Unknown option type %d", type); } } return option; } FileOption *CommandLineOptionPool::fileOption() const { return static_cast(getOption(CommandLineOption::FileOptionType)); } BuildDirectoryOption *CommandLineOptionPool::buildDirectoryOption() const { return static_cast(getOption(CommandLineOption::BuildDirectoryOptionType)); } LogLevelOption *CommandLineOptionPool::logLevelOption() const { return static_cast(getOption(CommandLineOption::LogLevelOptionType)); } VerboseOption *CommandLineOptionPool::verboseOption() const { return static_cast(getOption(CommandLineOption::VerboseOptionType)); } QuietOption *CommandLineOptionPool::quietOption() const { return static_cast(getOption(CommandLineOption::QuietOptionType)); } ShowProgressOption *CommandLineOptionPool::showProgressOption() const { return static_cast(getOption(CommandLineOption::ShowProgressOptionType)); } DryRunOption *CommandLineOptionPool::dryRunOption() const { return static_cast(getOption(CommandLineOption::DryRunOptionType)); } ForceProbesOption *CommandLineOptionPool::forceProbesOption() const { return static_cast(getOption(CommandLineOption::ForceProbesOptionType)); } ChangedFilesOption *CommandLineOptionPool::changedFilesOption() const { return static_cast(getOption(CommandLineOption::ChangedFilesOptionType)); } KeepGoingOption *CommandLineOptionPool::keepGoingOption() const { return static_cast(getOption(CommandLineOption::KeepGoingOptionType)); } JobsOption *CommandLineOptionPool::jobsOption() const { return static_cast(getOption(CommandLineOption::JobsOptionType)); } ProductsOption *CommandLineOptionPool::productsOption() const { return static_cast(getOption(CommandLineOption::ProductsOptionType)); } NoInstallOption *CommandLineOptionPool::noInstallOption() const { return static_cast(getOption(CommandLineOption::NoInstallOptionType)); } InstallRootOption *CommandLineOptionPool::installRootOption() const { return static_cast(getOption(CommandLineOption::InstallRootOptionType)); } RemoveFirstOption *CommandLineOptionPool::removeFirstoption() const { return static_cast(getOption(CommandLineOption::RemoveFirstOptionType)); } NoBuildOption *CommandLineOptionPool::noBuildOption() const { return static_cast(getOption(CommandLineOption::NoBuildOptionType)); } ForceTimeStampCheckOption *CommandLineOptionPool::forceTimestampCheckOption() const { return static_cast( getOption(CommandLineOption::ForceTimestampCheckOptionType)); } ForceOutputCheckOption *CommandLineOptionPool::forceOutputCheckOption() const { return static_cast( getOption(CommandLineOption::ForceOutputCheckOptionType)); } BuildNonDefaultOption *CommandLineOptionPool::buildNonDefaultOption() const { return static_cast( getOption(CommandLineOption::BuildNonDefaultOptionType)); } LogTimeOption *CommandLineOptionPool::logTimeOption() const { return static_cast(getOption(CommandLineOption::LogTimeOptionType)); } CommandEchoModeOption *CommandLineOptionPool::commandEchoModeOption() const { return static_cast( getOption(CommandLineOption::CommandEchoModeOptionType)); } SettingsDirOption *CommandLineOptionPool::settingsDirOption() const { return static_cast(getOption(CommandLineOption::SettingsDirOptionType)); } JobLimitsOption *CommandLineOptionPool::jobLimitsOption() const { return static_cast(getOption(CommandLineOption::JobLimitsOptionType)); } RespectProjectJobLimitsOption *CommandLineOptionPool::respectProjectJobLimitsOption() const { return static_cast( getOption(CommandLineOption::RespectProjectJobLimitsOptionType)); } GeneratorOption *CommandLineOptionPool::generatorOption() const { return static_cast(getOption(CommandLineOption::GeneratorOptionType)); } WaitLockOption *CommandLineOptionPool::waitLockOption() const { return static_cast(getOption(CommandLineOption::WaitLockOptionType)); } RunEnvConfigOption *CommandLineOptionPool::runEnvConfigOption() const { return static_cast(getOption(CommandLineOption::RunEnvConfigOptionType)); } DeprecationWarningsOption *CommandLineOptionPool::deprecationWarningsOption() const { return static_cast (getOption(CommandLineOption::DeprecationWarningsOptionType)); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/status.cpp0000644000175100017510000001552115232633614016672 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "status.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include namespace qbs { static QList createIgnoreList(const QString &projectRootPath) { QList ignoreRegularExpressionList { QRegularExpression(QRegularExpression::anchoredPattern(projectRootPath + QLatin1String("/build.*"))), QRegularExpression(QRegularExpression::wildcardToRegularExpression(QStringLiteral("*.qbs"))), QRegularExpression(QRegularExpression::wildcardToRegularExpression(QStringLiteral("*.pro"))), QRegularExpression(QRegularExpression::wildcardToRegularExpression(QStringLiteral("*Makefile"))), QRegularExpression(QRegularExpression::wildcardToRegularExpression(QStringLiteral("*.so*"))), QRegularExpression(QRegularExpression::wildcardToRegularExpression(QStringLiteral("*.o"))) }; QString ignoreFilePath = projectRootPath + QLatin1String("/.qbsignore"); QFile ignoreFile(ignoreFilePath); if (ignoreFile.open(QFile::ReadOnly)) { const QList ignoreTokenList = ignoreFile.readAll().split('\n'); for (const QByteArray &btoken : ignoreTokenList) { const QString token = QString::fromLatin1(btoken); if (token.startsWith(QLatin1String("/"))) ignoreRegularExpressionList.push_back( QRegularExpression(QRegularExpression::anchoredPattern( projectRootPath + token + QLatin1String(".*")))); else if (!token.isEmpty()) ignoreRegularExpressionList.push_back( QRegularExpression(QRegularExpression::anchoredPattern(token))); } } return ignoreRegularExpressionList; } static QStringList allFilesInDirectoryRecursive( const QDir &rootDirecory, const QList &ignoreRegularExpressionList) { QStringList fileList; const auto fileInfos = rootDirecory.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name); for (const QFileInfo &fileInfo : fileInfos) { QString absoluteFilePath = fileInfo.absoluteFilePath(); bool inIgnoreList = false; for (const QRegularExpression &ignoreRegularExpression : ignoreRegularExpressionList) { if (ignoreRegularExpression.match(absoluteFilePath).hasMatch()) { inIgnoreList = true; break; } } if (!inIgnoreList) { if (fileInfo.isFile()) fileList.push_back(absoluteFilePath); else if (fileInfo.isDir()) fileList << allFilesInDirectoryRecursive(QDir(absoluteFilePath), ignoreRegularExpressionList); } } return fileList; } static QStringList allFilesInProject(const QString &projectRootPath) { QList ignoreRegularExpressionList = createIgnoreList(projectRootPath); return allFilesInDirectoryRecursive(QDir(projectRootPath), ignoreRegularExpressionList); } QStringList allFiles(const ProductData &product) { QStringList files; for (const GroupData &group : product.groups()) files += group.allFilePaths(); return files; } int printStatus(const ProjectData &project) { const QString projectFilePath = project.location().filePath(); QString projectDirectory = QFileInfo(projectFilePath).dir().path(); int projectDirectoryPathLength = projectDirectory.length(); QStringList untrackedFilesInProject = allFilesInProject(projectDirectory); QStringList missingFiles; for (const ProductData &product : project.allProducts()) { qbsInfo() << "\nProduct: " << product.name() << " (" << product.location().filePath() << ":" << product.location().line() << ")"; for (const GroupData &group : product.groups()) { qbsInfo() << " Group: " << group.name() << " (" << group.location().filePath() << ":" << group.location().line() << ")"; const QStringList sourceFiles = Internal::sorted(group.allFilePaths()); for (const QString &sourceFile : sourceFiles) { if (!QFileInfo::exists(sourceFile)) missingFiles.push_back(sourceFile); qbsInfo() << " " << sourceFile.mid(projectDirectoryPathLength + 1); untrackedFilesInProject.removeOne(sourceFile); } } } qbsInfo() << "\nMissing files:"; for (const QString &untrackedFile : std::as_const(missingFiles)) qbsInfo() << " " << untrackedFile.mid(projectDirectoryPathLength + 1); qbsInfo() << "\nUntracked files:"; for (const QString &missingFile : std::as_const(untrackedFilesInProject)) qbsInfo() << " " << missingFile.mid(projectDirectoryPathLength + 1); return 0; } } // namespace qbs qbs-src-3.3.1/src/app/qbs/sessionpacket.h0000644000175100017510000000472315232633614017671 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SESSIONPACKET_H #define QBS_SESSIONPACKET_H #include #include namespace qbs { namespace Internal { class SessionPacket { public: enum class Status { Incomplete, Complete, Invalid }; Status parseInput(QByteArray &input); QJsonObject retrievePacket(); static QByteArray createPacket(const QJsonObject &packet); static QJsonObject helloMessage(const QString &lspSocket); private: bool isComplete() const; QByteArray m_payload; int m_expectedPayloadLength = -1; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-3.3.1/src/app/qbs/consoleprogressobserver.h0000644000175100017510000000477515232633614022024 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONSOLEPROGRESSOBSERVER_H #define CONSOLEPROGRESSOBSERVER_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class ConsoleProgressObserver { public: void initialize(const QString &task, int max); void setMaximum(int maximum); void setProgressValue(int value); void incrementProgressValue() { setProgressValue(m_value + 1); } private: void eraseCurrentPercentageString(); void updateProgressBarIfNecessary(); void writePercentageString(); int m_maximum; int m_value; int m_percentage; int m_hashesPrinted; }; } // namespace qbs #endif // CONSOLEPROGRESSOBSERVER_H qbs-src-3.3.1/src/app/qbs/ctrlchandler.cpp0000644000175100017510000000473415232633614020020 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" static void cancel() { qbs::Application * const app = qbs::Application::instance(); if (app) app->userInterrupt(); } #if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #include static BOOL WINAPI consoleCtrlHandlerRoutine(__in DWORD dwCtrlType) { Q_UNUSED(dwCtrlType); cancel(); return TRUE; } void installCtrlCHandler() { SetConsoleCtrlHandler(&consoleCtrlHandlerRoutine, TRUE); } #else #include static void sigIntHandler(int sig) { Q_UNUSED(sig); cancel(); } void installCtrlCHandler() { signal(SIGINT, sigIntHandler); } #endif qbs-src-3.3.1/src/app/qbs/commandlinefrontend.cpp0000644000175100017510000006660415232633614021405 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlinefrontend.h" #include "application.h" #include "consoleprogressobserver.h" #include "session.h" #include "status.h" #include "parser/commandlineoption.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; CommandLineFrontend::CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent) : QObject(parent) , m_parser(parser) , m_settings(settings) , m_observer(nullptr) , m_cancelStatus(CancelStatusNone) , m_cancelTimer(new QTimer(this)) { } CommandLineFrontend::~CommandLineFrontend() { m_cancelTimer->stop(); delete m_observer; } // Called from interrupt handler. Don't do anything non-trivial here. void CommandLineFrontend::cancel() { m_cancelStatus = CancelStatusRequested; } void CommandLineFrontend::checkCancelStatus() { switch (m_cancelStatus) { case CancelStatusNone: break; case CancelStatusRequested: m_cancelStatus = CancelStatusCanceling; m_cancelTimer->stop(); if (m_resolveJobs.empty() && m_buildJobs.empty()) std::exit(EXIT_FAILURE); for (AbstractJob * const job : std::as_const(m_resolveJobs)) job->cancel(); for (AbstractJob * const job : std::as_const(m_buildJobs)) job->cancel(); break; case CancelStatusCanceling: QBS_ASSERT(false, return); break; } } void CommandLineFrontend::start() { try { switch (m_parser.command()) { case RunCommandType: case ShellCommandType: if (m_parser.products().size() > 1) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Cannot use more than one " "product.\nUsage: %2") .arg(m_parser.commandName(), m_parser.commandDescription())); } Q_FALLTHROUGH(); case StatusCommandType: case InstallCommandType: case DumpNodesTreeCommandType: case ListProductsCommandType: if (m_parser.buildConfigurations().size() > 1) { QString error = Tr::tr("Invalid use of command '%1': There can be only one " "build configuration.\n").arg(m_parser.commandName()); error += Tr::tr("Usage: %1").arg(m_parser.commandDescription()); throw ErrorInfo(error); } break; case SessionCommandType: { startSession(); return; } default: break; } if (m_parser.showVersion()) { std::puts(QBS_VERSION); qApp->exit(EXIT_SUCCESS); return; } if (m_parser.showProgress()) m_observer = new ConsoleProgressObserver; SetupProjectParameters params; params.setEnvironment(QProcessEnvironment::systemEnvironment()); params.setProjectFilePath(m_parser.projectFilePath()); params.setDryRun(m_parser.dryRun()); params.setForceProbeExecution(m_parser.forceProbesExecution()); params.setWaitLockBuildGraph(m_parser.waitLockBuildGraph()); params.setLogElapsedTime(m_parser.logTime()); params.setSettingsDirectory(m_settings->baseDirectory()); params.setOverrideBuildGraphData(m_parser.command() == ResolveCommandType); params.setPropertyCheckingMode(ErrorHandlingMode::Strict); params.setDeprecationWarningMode(m_parser.deprecationWarningMode()); if (!m_parser.buildBeforeInstalling() || !m_parser.commandCanResolve()) params.setRestoreBehavior(SetupProjectParameters::RestoreOnly); const auto buildConfigs = m_parser.buildConfigurations(); for (const QVariantMap &buildConfig : buildConfigs) { QVariantMap userConfig = buildConfig; const QString configurationKey = QStringLiteral("qbs.configurationName"); const QString profileKey = QStringLiteral("qbs.profile"); const QString installRootKey = QStringLiteral("qbs.installRoot"); QString installRoot = userConfig.value(installRootKey).toString(); if (!installRoot.isEmpty() && QFileInfo(installRoot).isRelative()) { installRoot.prepend(QLatin1Char('/')).prepend(QDir::currentPath()); userConfig.insert(installRootKey, installRoot); } const QString configurationName = userConfig.take(configurationKey).toString(); const QString profileName = userConfig.take(profileKey).toString(); const Preferences prefs(m_settings); params.setSearchPaths(prefs.searchPaths(QDir::cleanPath( qbsApplicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); params.setPluginPaths(prefs.pluginPaths(QDir::cleanPath( qbsApplicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); params.setLibexecPath(QDir::cleanPath( qbsApplicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); params.setTopLevelProfile(profileName); params.setConfigurationName(configurationName); params.setBuildRoot(buildDirectory(profileName)); params.setOverriddenValues(userConfig); params.setMaxJobCount(m_parser.jobCount(profileName)); SetupProjectJob * const job = Project().setupProject(params, ConsoleLogger::instance().logSink(), this); connectJob(job); m_resolveJobs.push_back(job); } /* * Progress reporting on the terminal gets a bit tricky when resolving several projects * concurrently, since we cannot show multiple progress bars at the same time. Instead, * we just set the total effort to the number of projects and increase the progress * every time one of them finishes, ignoring the progress reports from the jobs themselves. * (Yes, that does mean it will take disproportionately long for the first progress * notification to arrive.) */ if (m_parser.showProgress() && resolvingMultipleProjects()) m_observer->initialize(tr("Setting up projects"), m_resolveJobs.size()); // Check every two seconds whether we received a cancel request. This value has been // experimentally found to be acceptable. // Note that this polling approach is not problematic here, since we are doing work anyway, // so there's no danger of waking up the processor for no reason. connect(m_cancelTimer, &QTimer::timeout, this, &CommandLineFrontend::checkCancelStatus); m_cancelTimer->start(2000); } catch (const ErrorInfo &error) { qbsError() << error.toString(); if (m_buildJobs.empty() && m_resolveJobs.empty()) { qApp->exit(EXIT_FAILURE); } else { cancel(); checkCancelStatus(); } } } void CommandLineFrontend::handleCommandDescriptionReport(const QString &highlight, const QString &message) { qbsInfo() << MessageTag(highlight) << message; } void CommandLineFrontend::handleJobFinished(bool success, AbstractJob *job) { try { job->deleteLater(); if (!success) { qbsError() << job->error().toString(); m_resolveJobs.removeOne(job); m_buildJobs.removeOne(job); if (m_resolveJobs.empty() && m_buildJobs.empty()) { qApp->exit(EXIT_FAILURE); return; } cancel(); } else if (const auto setupJob = qobject_cast(job)) { m_resolveJobs.removeOne(job); m_projects.push_back(setupJob->project()); if (m_observer && resolvingMultipleProjects()) m_observer->incrementProgressValue(); if (m_resolveJobs.empty()) handleProjectsResolved(); } else if (qobject_cast(job)) { if (m_parser.command() == RunCommandType) qApp->exit(runTarget()); else qApp->quit(); } else { // Build or clean. m_buildJobs.removeOne(job); if (m_buildJobs.empty()) { switch (m_parser.command()) { case RunCommandType: case InstallCommandType: install(); break; case GenerateCommandType: generate(); // fall through case BuildCommandType: case CleanCommandType: qApp->exit(m_cancelStatus == CancelStatusNone ? EXIT_SUCCESS : EXIT_FAILURE); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Missing case in switch statement"); } } } } catch (const ErrorInfo &error) { qbsError() << error.toString(); qApp->exit(EXIT_FAILURE); } } void CommandLineFrontend::handleNewTaskStarted(const QString &description, int totalEffort) { // If the user does not want a progress bar, we just print the current activity. if (!m_parser.showProgress()) { if (!m_parser.logTime()) qbsInfo() << description; return; } if (isBuilding()) { m_totalBuildEffort += totalEffort; if (++m_buildEffortsRetrieved == m_buildEffortsNeeded) { m_observer->initialize(tr("Building"), m_totalBuildEffort); if (m_currentBuildEffort > 0) m_observer->setProgressValue(m_currentBuildEffort); } } else if (!resolvingMultipleProjects()) { m_observer->initialize(description, totalEffort); } } void CommandLineFrontend::handleTotalEffortChanged(int totalEffort) { // Can only happen when resolving. if (m_parser.showProgress() && !isBuilding() && !resolvingMultipleProjects()) m_observer->setMaximum(totalEffort); } void CommandLineFrontend::handleTaskProgress(int value, AbstractJob *job) { if (isBuilding()) { int ¤tJobEffort = m_buildEfforts[job]; m_currentBuildEffort += value - currentJobEffort; currentJobEffort = value; if (m_buildEffortsRetrieved == m_buildEffortsNeeded) m_observer->setProgressValue(m_currentBuildEffort); } else if (!resolvingMultipleProjects()) { m_observer->setProgressValue(value); } } void CommandLineFrontend::handleProcessResultReport(const qbs::ProcessResult &result) { bool hasOutput = !result.stdOut().empty() || !result.stdErr().empty(); if (!hasOutput && result.success()) return; LogWriter w = result.success() ? qbsInfo() : qbsError(); w << shellQuote(QDir::toNativeSeparators(result.executableFilePath()), result.arguments()) << (hasOutput ? QStringLiteral("\n") : QString()) << (result.stdOut().empty() ? QString() : result.stdOut().join(QLatin1Char('\n'))); if (!result.stdErr().empty()) w << result.stdErr().join(QLatin1Char('\n')) << MessageTag(QStringLiteral("stdErr")); } bool CommandLineFrontend::resolvingMultipleProjects() const { return isResolving() && m_resolveJobs.size() + m_projects.size() > 1; } bool CommandLineFrontend::isResolving() const { return !m_resolveJobs.empty(); } bool CommandLineFrontend::isBuilding() const { return !m_buildJobs.empty(); } CommandLineFrontend::ProductMap CommandLineFrontend::productsToUse() const { ProductMap products; QStringList productNames; const bool useAll = m_parser.products().empty(); for (const Project &project : std::as_const(m_projects)) { QList &productList = products[project]; const ProjectData projectData = project.projectData(); for (const ProductData &product : projectData.allProducts()) { productNames << product.fullDisplayName(); if (useAll || m_parser.products().contains(product.fullDisplayName())) { productList.push_back(product); } } } const auto parsedProductNames = m_parser.products(); for (const QString &productName : parsedProductNames) { if (!productNames.contains(productName)) { QString msg; if (productNames.size() <= 10) { productNames.sort(); const QString available = productNames.join(QLatin1String("', '")); msg = Tr::tr("No such product '%1'. " "Available products: '%2'").arg(productName, available); } else { msg = Tr::tr("No such product '%1'. Use 'list-products' to see " "all available products.").arg(productName); } throw ErrorInfo(msg); } } return products; } void CommandLineFrontend::handleProjectsResolved() { if (m_cancelStatus != CancelStatusNone) throw ErrorInfo(Tr::tr("Execution canceled.")); switch (m_parser.command()) { case ResolveCommandType: qApp->quit(); break; case CleanCommandType: makeClean(); break; case ShellCommandType: qApp->exit(runShell()); break; case StatusCommandType: qApp->exit(printStatus(m_projects.front().projectData())); break; case GenerateCommandType: checkGeneratorName(); Q_FALLTHROUGH(); case BuildCommandType: build(); break; case InstallCommandType: case RunCommandType: if (m_parser.buildBeforeInstalling()) build(); else install(); break; case UpdateTimestampsCommandType: updateTimestamps(); qApp->quit(); break; case DumpNodesTreeCommandType: dumpNodesTree(); qApp->quit(); break; case ListProductsCommandType: listProducts(); qApp->quit(); break; case HelpCommandType: case VersionCommandType: case SessionCommandType: Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible."); } } void CommandLineFrontend::makeClean() { if (m_parser.products().empty()) { for (const Project &project : std::as_const(m_projects)) { m_buildJobs << project.cleanAllProducts(m_parser.cleanOptions(project.profile()), this); } } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) { m_buildJobs.push_back(it.key().cleanSomeProducts( it.value(), m_parser.cleanOptions(it.key().profile()), this)); } } connectBuildJobs(); } int CommandLineFrontend::runShell() { ProductData productToRun; switch (m_parser.products().size()) { case 0: // No specific product, use project-global environment. break; case 1: productToRun = productsToUse().values().front().front(); break; default: throw ErrorInfo(Tr::tr("The command '%1' cannot take more than one product.")); } RunEnvironment runEnvironment = m_projects.front().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.front().profile()), QProcessEnvironment::systemEnvironment(), QStringList(), m_settings); return runEnvironment.doRunShell(); } BuildOptions CommandLineFrontend::buildOptions(const Project &project) const { BuildOptions options = m_parser.buildOptions(m_projects.front().profile()); if (options.maxJobCount() <= 0) { const QString profileName = project.profile(); QBS_CHECK(!profileName.isEmpty()); options.setMaxJobCount(Preferences(m_settings, profileName).jobs()); } return options; } QString CommandLineFrontend::buildDirectory(const QString &profileName) const { QString buildDir = m_parser.projectBuildDirectory(); if (buildDir.isEmpty()) { buildDir = Preferences(m_settings, profileName).defaultBuildDirectory(); if (buildDir.isEmpty()) { qbsDebug() << "No project build directory given; using current directory."; buildDir = QDir::currentPath(); } else { qbsDebug() << "No project build directory given; using directory from preferences."; } } QString projectName(QFileInfo(m_parser.projectFilePath()).baseName()); QString originalBuildDir = buildDir; buildDir.replace(BuildDirectoryOption::magicProjectString(), projectName); const QString buildDirPlaceHolderMsgTemplate = Tr::tr( "You must provide the path to the project file when using build directory " "placeholder '%1'."); if (buildDir != originalBuildDir && projectName.isEmpty()) { throw ErrorInfo( buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectString())); } QString projectDir(QFileInfo(m_parser.projectFilePath()).path()); originalBuildDir = buildDir; buildDir.replace(BuildDirectoryOption::magicProjectDirString(), projectDir); if (buildDir != originalBuildDir && projectDir.isEmpty()) { throw ErrorInfo( buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectDirString())); } if (!QFileInfo(buildDir).isAbsolute()) buildDir = QDir::currentPath() + QLatin1Char('/') + buildDir; buildDir = QDir::cleanPath(buildDir); return buildDir; } void CommandLineFrontend::build() { if (m_parser.products().empty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; for (const Project &project : std::as_const(m_projects)) m_buildJobs << project.buildAllProducts(buildOptions(project), productSelection, this); } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) m_buildJobs.push_back(it.key().buildSomeProducts(it.value(), buildOptions(it.key()), this)); } connectBuildJobs(); /* * Progress reporting for the build jobs works as follows: We know that for every job, * the newTaskStarted() signal is emitted exactly once (unless there's an error). So we add up * the respective total efforts as they come in. Once all jobs have reported their total * efforts, we can start the overall progress report. */ m_buildEffortsNeeded = m_buildJobs.size(); m_buildEffortsRetrieved = 0; m_totalBuildEffort = 0; m_currentBuildEffort = 0; } void CommandLineFrontend::checkGeneratorName() { const QString generatorName = m_parser.generateOptions().generatorName(); m_generator = ProjectGeneratorManager::findGenerator(generatorName); if (m_generator) return; const auto generatorNames = ProjectGeneratorManager::loadedGeneratorNames(); if (!generatorNames.empty()) { const QString generatorNamesString = generatorNames.join(QLatin1String("\n\t")); if (!generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("No generator named '%1'. Available generators:\n\t%2") .arg(generatorName, generatorNamesString)); } throw ErrorInfo(Tr::tr("No generator specified. Available generators:\n\t%1") .arg(generatorNamesString)); } throw ErrorInfo(Tr::tr("No generator specified or no generators are available.")); } void CommandLineFrontend::generate() { QBS_CHECK(!!m_generator); const ErrorInfo error = m_generator->generate(m_projects, m_parser.buildConfigurations(), m_parser.installOptions(QString()), m_parser.settingsDir(), ConsoleLogger::instance(m_settings)); if (error.hasError()) throw error; } int CommandLineFrontend::runTarget() { const ProductData productToRun = getTheOneRunnableProduct(); const QString executableFilePath = productToRun.targetExecutable(); if (executableFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Cannot run: Product '%1' is not an application.") .arg(productToRun.fullDisplayName())); } RunEnvironment runEnvironment = m_projects.front().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.front().profile()), QProcessEnvironment::systemEnvironment(), m_parser.runEnvConfig(), m_settings); return runEnvironment.doRunTarget(executableFilePath, m_parser.runArgs(), m_parser.dryRun()); } void CommandLineFrontend::updateTimestamps() { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.constBegin(); it != products.constEnd(); ++it) { Project p = it.key(); p.updateTimestamps(it.value()); } } void CommandLineFrontend::dumpNodesTree() { QFile stdOut; if (!stdOut.open(stdout, QIODevice::WriteOnly)) throw ErrorInfo(Tr::tr("Cannot write to standard output.")); const ErrorInfo error = m_projects.front().dumpNodesTree(stdOut, productsToUse() .value(m_projects.front())); if (error.hasError()) throw error; } void CommandLineFrontend::listProducts() { const QList products = productsToUse().constBegin().value(); QStringList output; for (const ProductData &p : products) { QString productInfo = p.fullDisplayName(); if (!p.isEnabled()) productInfo.append(QLatin1Char(' ')).append(Tr::tr("[disabled]")); else if (!p.properties().value(QStringLiteral("builtByDefault")).toBool()) productInfo.append(QLatin1Char(' ')).append(Tr::tr("[not built by default]")); output += productInfo; } output.sort(); qbsInfo() << output.join(QLatin1Char('\n')); } void CommandLineFrontend::connectBuildJobs() { for (AbstractJob * const job : std::as_const(m_buildJobs)) connectBuildJob(job); } void CommandLineFrontend::connectBuildJob(AbstractJob *job) { connectJob(job); const auto bjob = qobject_cast(job); if (!bjob) return; connect(bjob, &BuildJob::reportCommandDescription, this, &CommandLineFrontend::handleCommandDescriptionReport); connect(bjob, &BuildJob::reportProcessResult, this, &CommandLineFrontend::handleProcessResultReport); } void CommandLineFrontend::connectJob(AbstractJob *job) { connect(job, &AbstractJob::finished, this, &CommandLineFrontend::handleJobFinished); connect(job, &AbstractJob::taskStarted, this, &CommandLineFrontend::handleNewTaskStarted); connect(job, &AbstractJob::totalEffortChanged, this, &CommandLineFrontend::handleTotalEffortChanged); if (m_parser.showProgress()) { connect(job, &AbstractJob::taskProgress, this, &CommandLineFrontend::handleTaskProgress); } } ProductData CommandLineFrontend::getTheOneRunnableProduct() { QBS_CHECK(m_projects.size() == 1); // Has been checked earlier. if (m_parser.products().size() == 1) { for (const ProductData &p : m_projects.front().projectData().allProducts()) { if (p.fullDisplayName() == m_parser.products().constFirst()) return p; } QBS_CHECK(false); } QBS_CHECK(m_parser.products().isEmpty()); QList runnableProducts; for (const ProductData &p : m_projects.front().projectData().allProducts()) { if (p.isRunnable()) runnableProducts.push_back(p); } if (runnableProducts.size() == 1) return runnableProducts.front(); if (runnableProducts.empty()) { throw ErrorInfo(Tr::tr("Cannot execute command '%1': Project has no runnable product.") .arg(m_parser.commandName())); } ErrorInfo error(Tr::tr("Ambiguous use of command '%1': No product given, but project " "has more than one runnable product.").arg(m_parser.commandName())); error.append(Tr::tr("Use the '--products' option with one of the following products:")); for (const ProductData &p : std::as_const(runnableProducts)) error.append(QLatin1String("\t") + p.fullDisplayName()); throw error; } void CommandLineFrontend::install() { Q_ASSERT(m_projects.size() == 1); const Project project = m_projects.front(); InstallJob *installJob; if (m_parser.products().empty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; installJob = project.installAllProducts(m_parser.installOptions(project.profile()), productSelection); } else { const Project project = m_projects.front(); const ProductMap products = productsToUse(); installJob = project.installSomeProducts(products.value(project), m_parser.installOptions(project.profile())); } connectJob(installJob); } } // namespace qbs qbs-src-3.3.1/src/app/qbs/application.h0000644000175100017510000000450415232633614017316 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef APPLICATION_H #define APPLICATION_H #include namespace qbs { class CommandLineFrontend; class Application : public QCoreApplication { Q_OBJECT public: Application(int &argc, char **argv); static Application *instance(); void setCommandLineFrontend(CommandLineFrontend *clFrontend); void userInterrupt(); private: CommandLineFrontend *m_clFrontend; bool m_canceled; }; } // namespace qbs #endif // APPLICATION_H qbs-src-3.3.1/src/app/qbs-create-project/0000755000175100017510000000000015232633614017544 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs-create-project/CMakeLists.txt0000644000175100017510000000027215232633614022305 0ustar runnerrunnerset(SOURCES createproject.cpp createproject.h create-project-main.cpp ) add_qbs_app(qbs-create-project DEPENDS qbscore qbsconsolelogger SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/qbs-create-project/createproject.h0000644000175100017510000000651615232633614022557 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CREATEPROJECT_H #define QBS_CREATEPROJECT_H #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QDir; class QTextStream; QT_END_NAMESPACE enum class ProjectStructure { Flat, Composite }; class ProjectCreator { public: void run(const QString &topLevelDir, ProjectStructure projectStructure, const QStringList &whiteList, const QStringList &blacklist); private: enum ProductFlag { IsApp = 1, NeedsCpp = 2, NeedsQt = 4 }; Q_DECLARE_FLAGS(ProductFlags, ProductFlag) struct Project; void setupProject(Project *project); void serializeProject(const Project &project); void addGroups(QTextStream &stream, const QDir &baseDir, const Project &subProject); bool isSourceFile(const QString &fileName); ProductFlags getFlags(const Project &project); void getFlagsFromFileNames(const Project &project, ProductFlags &flags); void getFlagsFromFileContents(const Project &project, ProductFlags &flags); using ProjectPtr = std::unique_ptr; struct Project { QString dirPath; QString dirName; QStringList fileNames; std::vector subProjects; }; Project m_topLevelProject; ProjectStructure m_projectStructure = ProjectStructure::Flat; QList m_whiteList; QList m_blackList; }; #endif // QBS_CREATEPROJECT_H qbs-src-3.3.1/src/app/qbs-create-project/qbs-create-project.qbs0000644000175100017510000000023015232633614023740 0ustar runnerrunnerQbsApp { name: "qbs-create-project" files: [ "createproject.cpp", "createproject.h", "create-project-main.cpp", ] } qbs-src-3.3.1/src/app/qbs-create-project/create-project-main.cpp0000644000175100017510000001051715232633614024105 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "createproject.h" #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { using qbs::ErrorInfo; using qbs::Internal::Tr; QCoreApplication app(argc, argv); const QCommandLineOption flatOpt(QStringLiteral("flat"), Tr::tr("Do not create nested project files, even if there are subdirectories and " "the top-level directory does not contain any files.")); const QCommandLineOption whiteListOpt(QStringLiteral("whitelist"), Tr::tr("Only consider files whose names match these patterns. The list entries " "can contain wildcards and are separated by commas. By default, all files " "are considered."), QStringLiteral("whitelist")); const QCommandLineOption blackListOpt(QStringLiteral("blacklist"), Tr::tr("Ignore files whose names match these patterns. The list entries " "can contain wildcards and are separated by commas. By default, no files " "are ignored."), QStringLiteral("blacklist")); QCommandLineParser parser; parser.setApplicationDescription(Tr::tr("This tool creates a qbs project from an existing " "source tree.\nNote: The resulting project file(s) " "will likely require manual editing.")); parser.addOption(flatOpt); parser.addOption(whiteListOpt); parser.addOption(blackListOpt); parser.addHelpOption(); parser.process(app); const ProjectStructure projectStructure = parser.isSet(flatOpt) ? ProjectStructure::Flat : ProjectStructure::Composite; const QStringList whiteList = parser.value(whiteListOpt).split(QLatin1Char(','), Qt::SkipEmptyParts); const QStringList blackList = parser.value(blackListOpt).split(QLatin1Char(','), Qt::SkipEmptyParts); try { ProjectCreator().run(QDir::currentPath(), projectStructure, whiteList, blackList); } catch (const ErrorInfo &e) { std::cerr << qPrintable(Tr::tr("Error creating project: %1").arg(e.toString())) << std::endl; return 1; } } qbs-src-3.3.1/src/app/qbs-create-project/createproject.cpp0000644000175100017510000002332415232633614023106 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "createproject.h" #include #include #include #include #include #include #include #include #include #include #include using qbs::ErrorInfo; using qbs::Internal::Tr; static const char *indent = " "; void ProjectCreator::run(const QString &topLevelDir, ProjectStructure projectStructure, const QStringList &whiteList, const QStringList &blackList) { m_projectStructure = projectStructure; qbs::Internal::transform(whiteList, m_whiteList, [](const QString &s) { return QRegularExpression(QRegularExpression::wildcardToRegularExpression(s)); }); qbs::Internal::transform(blackList, m_blackList, [](const QString &s) { return QRegularExpression(QRegularExpression::wildcardToRegularExpression(s)); }); m_topLevelProject.dirPath = topLevelDir; setupProject(&m_topLevelProject); serializeProject(m_topLevelProject); } void ProjectCreator::setupProject(Project *project) { QDirIterator dit(project->dirPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); while (dit.hasNext()) { dit.next(); if (dit.fileInfo().isFile()) { if (dit.fileName().endsWith(QLatin1String(".qbs"))) throw ErrorInfo(Tr::tr("Project already contains qbs files, aborting.")); if (isSourceFile(dit.fileName())) project->fileNames << dit.fileName(); } else if (dit.fileInfo().isDir()) { ProjectPtr subProject(new Project); subProject->dirName = dit.fileName(); subProject->dirPath = dit.filePath(); setupProject(subProject.get()); if (!subProject->fileNames.empty() || !subProject->subProjects.empty()) project->subProjects.push_back(std::move(subProject)); } } project->fileNames.sort(); std::sort(project->subProjects.begin(), project->subProjects.end(), [](const ProjectPtr &p1, const ProjectPtr &p2) { return p1->dirName < p2->dirName; }); } void ProjectCreator::serializeProject(const ProjectCreator::Project &project) { const QString fileName = QFileInfo(project.dirPath).baseName() + QLatin1String(".qbs"); QFile projectFile(project.dirPath + QLatin1Char('/') + fileName); if (!projectFile.open(QIODevice::WriteOnly)) { throw ErrorInfo(Tr::tr("Failed to open '%1' for writing: %2") .arg(projectFile.fileName(), projectFile.errorString())); } QTextStream fileContents(&projectFile); qbs::setupDefaultCodec(fileContents); if (!project.fileNames.empty() || m_projectStructure == ProjectStructure::Flat) { fileContents << "Product {\n"; const ProductFlags productFlags = getFlags(project); if (productFlags.testFlag(IsApp)) { fileContents << indent << "type: [\"application\"]\n"; } else { fileContents << indent << "type: [\"unknown\"] // E.g. \"application\", " "\"dynamiclibrary\", \"staticlibrary\"\n"; } if (productFlags.testFlag(NeedsQt)) { fileContents << indent << "Depends {\n"; fileContents << indent << indent << "name: \"Qt\"\n"; fileContents << indent << indent << "submodules: [\"core\"] " "// Add more here if needed\n"; fileContents << indent << "}\n"; } else if (productFlags.testFlag(NeedsCpp)) { fileContents << indent << "Depends { name: \"cpp\" }\n"; } fileContents << indent << "files: [\n"; for (const QString &fileName : std::as_const(project.fileNames)) fileContents << indent << indent << qbs::toJSLiteral(fileName) << ",\n"; fileContents << indent << "]\n"; for (const ProjectPtr &p : project.subProjects) addGroups(fileContents, QDir(project.dirPath), *p); } else { fileContents << "Project {\n"; fileContents << indent << "references: [\n"; for (const ProjectPtr &p : project.subProjects) { serializeProject(*p); fileContents << indent << indent << qbs::toJSLiteral(QFileInfo(p->dirPath).fileName()) << ",\n"; } fileContents << indent << "]\n"; } fileContents << "}\n"; } void ProjectCreator::addGroups(QTextStream &stream, const QDir &baseDir, const ProjectCreator::Project &subProject) { stream << indent << "Group {\n"; stream << indent << indent << "name: " << qbs::toJSLiteral(QFileInfo(subProject.dirPath).fileName()) << "\n"; stream << indent << indent << "prefix: " << qbs::toJSLiteral(baseDir.relativeFilePath(subProject.dirPath) + QLatin1Char('/')) << '\n'; stream << indent << indent << "files: [\n"; for (const QString &fileName : std::as_const(subProject.fileNames)) stream << indent << indent << indent << qbs::toJSLiteral(fileName) << ",\n"; stream << indent << indent << "]\n"; stream << indent << "}\n"; for (const ProjectPtr &p : subProject.subProjects) addGroups(stream, baseDir, *p); } bool ProjectCreator::isSourceFile(const QString &fileName) { const auto isMatch = [fileName](const QRegularExpression &rex) { return rex.match(fileName).hasMatch(); }; return !qbs::Internal::any_of(m_blackList, isMatch) && (m_whiteList.empty() || qbs::Internal::any_of(m_whiteList, isMatch)); } ProjectCreator::ProductFlags ProjectCreator::getFlags(const ProjectCreator::Project &project) { ProductFlags flags; getFlagsFromFileNames(project, flags); if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return flags; if (!flags.testFlag(NeedsCpp)) return flags; getFlagsFromFileContents(project, flags); return flags; } void ProjectCreator::getFlagsFromFileNames(const ProjectCreator::Project &project, ProductFlags &flags) { for (const QString &fileName : std::as_const(project.fileNames)) { if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return; const QFileInfo fi(project.dirPath + QLatin1Char('/') + fileName); const QString &suffix = fi.suffix(); if (suffix == QLatin1String("qrc")) { flags |= NeedsQt; continue; } if (suffix == QLatin1String("cpp") || suffix == QLatin1String("c") || suffix == QLatin1String("m") || suffix == QLatin1String("mm")) { flags |= NeedsCpp; } if (flags.testFlag(NeedsCpp) && fi.completeBaseName() == QLatin1String("main")) flags |= IsApp; } for (const ProjectPtr &p : project.subProjects) { getFlagsFromFileNames(*p, flags); if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return; } } void ProjectCreator::getFlagsFromFileContents(const ProjectCreator::Project &project, ProductFlags &flags) { for (const QString &fileName : std::as_const(project.fileNames)) { QFile f (project.dirPath + QLatin1Char('/') + fileName); if (!f.open(QIODevice::ReadOnly)) { qDebug() << "Ignoring failure to read" << f.fileName(); continue; } while (!f.atEnd()) { const QByteArray &line = f.readLine(); if (line.contains("#include #include #include class ConfigCommand { public: enum Command { CfgSet, CfgUnset, CfgList, CfgExport, CfgImport, CfgAddProfile, CfgNone }; ConfigCommand() : command(CfgNone) {} Command command; QStringList varNames; QString varValue; QString fileName; }; #endif // CONFIGCOMMAND_H qbs-src-3.3.1/src/app/config/config.qbs0000644000175100017510000000037615232633614017301 0ustar runnerrunnerQbsApp { name: "qbs-config" files: [ "configcommand.h", "configcommandexecutor.cpp", "configcommandexecutor.h", "configcommandlineparser.cpp", "configcommandlineparser.h", "configmain.cpp" ] } qbs-src-3.3.1/src/app/config/CMakeLists.txt0000644000175100017510000000041315232633614020055 0ustar runnerrunnerset(SOURCES configcommand.h configcommandexecutor.cpp configcommandexecutor.h configcommandlineparser.cpp configcommandlineparser.h configmain.cpp ) add_qbs_app(qbs-config DEPENDS qbscore qbsconsolelogger SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/config/configmain.cpp0000644000175100017510000000565415232633614020147 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandlineparser.h" #include "configcommandexecutor.h" #include #include #include #include #include #include using qbs::Internal::Tr; using qbs::Settings; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); ConfigCommandLineParser parser; try { parser.parse(app.arguments().mid(1)); if (parser.helpRequested()) { std::cout << qPrintable(Tr::tr("This tool manages qbs settings.")) << std::endl; parser.printUsage(); return EXIT_SUCCESS; } Settings settings(parser.settingsDir()); ConfigCommandExecutor(&settings, parser.scope()).execute(parser.command()); } catch (const ConfigCommandLineParser::Error &e) { std::cerr << qPrintable(e.message()) << std::endl; parser.printUsage(); return EXIT_FAILURE; } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-3.3.1/src/app/config/configcommandexecutor.h0000644000175100017510000000512515232633614022056 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONFIGCOMMANDEXECUTOR_H #define CONFIGCOMMANDEXECUTOR_H #include #include class ConfigCommand; class ConfigCommandExecutor { Q_DECLARE_TR_FUNCTIONS(ConfigCommandExecutor) public: ConfigCommandExecutor(qbs::Settings *settings, qbs::Settings::Scopes scope); void execute(const ConfigCommand &command); private: void setValue(const QString &key, const QString &rawInput); void printSettings(const ConfigCommand &command); void printOneSetting(const QString &key); void exportSettings(const QString &filename); void importSettings(const QString &filename); qbs::Settings *m_settings; const qbs::Settings::Scopes m_scope; }; #endif // CONFIGCOMMANDEXECUTOR_H qbs-src-3.3.1/src/app/config/configcommandlineparser.h0000644000175100017510000000566115232633614022371 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDLINEPARSER_H #define COMMANDLINEPARSER_H #include "configcommand.h" #include #include class ConfigCommandLineParser { public: void parse(const QStringList &commandLine); ConfigCommand command() const { return m_command; } qbs::Settings::Scopes scope() const { return m_scope; } QString settingsDir() const { return m_settingsDir; } bool helpRequested() const { return m_helpRequested; } void printUsage() const; class Error { public: Error(QString message) : m_message(std::move(message)) { } QString message() const { return m_message; } private: QString m_message; }; private: void assignOptionArgument(const QString &option, QString &argument); void setCommand(ConfigCommand::Command command); void setScope(qbs::Settings::Scope scope); ConfigCommand m_command; qbs::Settings::Scopes m_scope = qbs::Settings::allScopes(); bool m_helpRequested = false; QString m_settingsDir; QStringList m_commandLine; }; #endif // COMMANDLINEPARSER_H qbs-src-3.3.1/src/app/config/configcommandlineparser.cpp0000644000175100017510000001635415232633614022725 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandlineparser.h" #include #include #include using namespace qbs; using namespace Internal; void ConfigCommandLineParser::parse(const QStringList &commandLine) { m_command = ConfigCommand(); m_helpRequested = false; m_settingsDir.clear(); m_commandLine = commandLine; if (m_commandLine.empty()) throw Error(Tr::tr("No parameters supplied.")); if (m_commandLine.size() == 1 && (m_commandLine.front() == QLatin1String("--help") || m_commandLine.front() == QLatin1String("-h"))) { m_helpRequested = true; return; } while (!m_commandLine.empty() && m_commandLine.front().startsWith(QLatin1String("--"))) { const QString arg = m_commandLine.takeFirst().mid(2); if (arg == QLatin1String("list")) setCommand(ConfigCommand::CfgList); else if (arg == QLatin1String("unset")) setCommand(ConfigCommand::CfgUnset); else if (arg == QLatin1String("export")) setCommand(ConfigCommand::CfgExport); else if (arg == QLatin1String("import")) setCommand(ConfigCommand::CfgImport); else if (arg == QLatin1String("add-profile")) setCommand(ConfigCommand::CfgAddProfile); else if (arg == QLatin1String("settings-dir")) assignOptionArgument(arg, m_settingsDir); else if (arg == QLatin1String("user")) setScope(qbs::Settings::UserScope); else if (arg == QLatin1String("system")) setScope(qbs::Settings::SystemScope); else throw Error(Tr::tr("Unknown option for config command.")); } switch (command().command) { case ConfigCommand::CfgNone: if (m_commandLine.empty()) throw Error(Tr::tr("No parameters supplied.")); if (m_commandLine.size() > 2) throw Error(Tr::tr("Too many arguments.")); m_command.varNames << m_commandLine.front(); if (m_commandLine.size() == 1) { setCommand(ConfigCommand::CfgList); } else { m_command.varValue = m_commandLine.at(1); setCommand(ConfigCommand::CfgSet); } break; case ConfigCommand::CfgUnset: if (m_commandLine.empty()) throw Error(Tr::tr("Need name of variable to unset.")); m_command.varNames = m_commandLine; break; case ConfigCommand::CfgExport: if (m_commandLine.size() != 1) throw Error(Tr::tr("Need name of file to which to export.")); m_command.fileName = m_commandLine.front(); break; case ConfigCommand::CfgImport: if (m_commandLine.size() != 1) throw Error(Tr::tr("Need name of file from which to import.")); m_command.fileName = m_commandLine.front(); break; case ConfigCommand::CfgList: m_command.varNames = m_commandLine; break; case ConfigCommand::CfgAddProfile: if (m_commandLine.empty()) throw Error(Tr::tr("Profile name missing.")); m_command.varValue = m_commandLine.takeFirst(); if (m_command.varValue.isEmpty()) throw Error(Tr::tr("Profile name must not be empty.")); m_command.varNames = m_commandLine; if (m_command.varNames.isEmpty()) throw Error(Tr::tr("Profile properties must be provided.")); if (m_command.varNames.size() % 2 != 0) throw Error(Tr::tr("Profile properties must be key/value pairs.")); for (const auto &varName : std::as_const(m_command.varNames)) { if (varName.isEmpty()) throw Error(Tr::tr("Property names must not be empty.")); } break; default: break; } } void ConfigCommandLineParser::setCommand(ConfigCommand::Command command) { if (m_command.command != ConfigCommand::CfgNone) throw Error(Tr::tr("You cannot specify more than one command.")); m_command.command = command; } void ConfigCommandLineParser::setScope(Settings::Scope scope) { if (m_scope != qbs::Settings::allScopes()) throw Error(Tr::tr("The --user and --system options can only appear once.")); m_scope = scope; } void ConfigCommandLineParser::printUsage() const { std::puts("Usage:\n" " qbs config [--settings-dir \n" " qbs config [--settings-dir \n" " qbs config [--settings-dir " "\n" "Options:\n" " --list [ ...] list keys under key or all keys\n" " --user consider only user-level settings\n" " --system consider only system-level settings\n" " --unset remove key with given name\n" " --add-profile ... add profile with the given name and properties\n" " --import import settings from given file\n" " --export export settings to given file\n"); } void ConfigCommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throw Error(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throw Error(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } qbs-src-3.3.1/src/app/config/configcommandexecutor.cpp0000644000175100017510000002053215232633614022410 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandexecutor.h" #include "configcommand.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include using namespace qbs; static QJsonObject settingsToJSONObject( Settings &settings, qbs::Settings::Scopes scopes, const QString &parentGroup = {}) { QJsonObject result; const auto allKeys = settings.directChildren(parentGroup, scopes); for (const auto& key : allKeys) { const auto fullKey = parentGroup.isEmpty() ? key : QStringLiteral("%1.%2").arg(parentGroup, key); const auto value = settings.value(fullKey, scopes); if (value.isValid()) { // looks like a real value result[key] = QJsonValue::fromVariant(value); } else { // looks like a group result[key] = settingsToJSONObject(settings, scopes, fullKey); } } return result; } static void settingsFromJSONObject( Settings &settings, const QJsonObject &object, const QString &parentGroup = {}) { for (auto it = object.begin(), end = object.end(); it != end; ++it) { const auto key = it.key(); const auto value = it.value(); const auto fullKey = parentGroup.isEmpty() ? key : QStringLiteral("%1.%2").arg(parentGroup, key); if (value.isObject()) { settingsFromJSONObject(settings, it.value().toObject(), fullKey); } else { settings.setValue(fullKey, value.toVariant()); } } } ConfigCommandExecutor::ConfigCommandExecutor(Settings *settings, Settings::Scopes scope) : m_settings(settings), m_scope(scope) { if (m_scope == qbs::Settings::SystemScope) m_settings->setScopeForWriting(qbs::Settings::SystemScope); } void ConfigCommandExecutor::execute(const ConfigCommand &command) { switch (command.command) { case ConfigCommand::CfgList: printSettings(command); break; case ConfigCommand::CfgSet: setValue(command.varNames.front(), command.varValue); break; case ConfigCommand::CfgUnset: for (const QString &varName : command.varNames) m_settings->remove(varName); break; case ConfigCommand::CfgAddProfile: { Profile profile(command.varValue, m_settings); profile.removeProfile(); Q_ASSERT(command.varNames.size() % 2 == 0); for (int i = 0; i < command.varNames.size(); i += 2) { const QString &key = command.varNames.at(i); const QString &rawValue = command.varNames.at(i + 1); profile.setValue(key, representationToSettingsValue(rawValue)); } break; } case ConfigCommand::CfgExport: exportSettings(command.fileName); break; case ConfigCommand::CfgImport: // Display old and new settings, in case import fails or user accidentally nukes everything std::printf("old "); // Will end up as "old settings:" printSettings(command); importSettings(command.fileName); std::printf("\nnew "); printSettings(command); break; case ConfigCommand::CfgNone: qFatal("%s: Impossible command value.", Q_FUNC_INFO); break; } } void ConfigCommandExecutor::setValue(const QString &key, const QString &rawInput) { m_settings->setValue(key, representationToSettingsValue(rawInput)); } void ConfigCommandExecutor::printSettings(const ConfigCommand &command) { if (command.varNames.empty()) { const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) printOneSetting(key); } else { for (const QString &parentKey : command.varNames) { if (m_settings->value(parentKey, m_scope).isValid()) { // Key is a leaf. printOneSetting(parentKey); } else { // Key is a node. const auto keys = m_settings->allKeysWithPrefix(parentKey, m_scope); for (const QString &key : keys) printOneSetting(parentKey + QLatin1Char('.') + key); } } } } void ConfigCommandExecutor::printOneSetting(const QString &key) { std::printf("%s: %s\n", qPrintable(key), qPrintable(qbs::settingsValueToRepresentation(m_settings->value(key, m_scope)))); } void ConfigCommandExecutor::exportSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::Truncate | QFile::WriteOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for writing: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } if (QFileInfo(filename).suffix() == u"json") { QJsonDocument doc; doc.setObject(settingsToJSONObject(*m_settings, m_scope)); file.write(doc.toJson()); } else { QTextStream stream(&file); setupDefaultCodec(stream); const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) stream << key << ": " << qbs::settingsValueToRepresentation(m_settings->value(key, m_scope)) << Qt::endl; } } void ConfigCommandExecutor::importSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for reading: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } // Remove all current settings const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) m_settings->remove(key); if (QFileInfo(filename).suffix() == u"json") { const auto doc = QJsonDocument::fromJson(file.readAll()); const auto object = doc.object(); settingsFromJSONObject(*m_settings, doc.object()); } else { QTextStream stream(&file); setupDefaultCodec(stream); while (!stream.atEnd()) { QString line = stream.readLine(); int colon = line.indexOf(QLatin1Char(':')); if (colon >= 0 && !line.startsWith(QLatin1Char('#'))) { const QString key = line.left(colon).trimmed(); const QString value = line.mid(colon + 1).trimmed(); m_settings->setValue(key, representationToSettingsValue(value)); } } } } qbs-src-3.3.1/src/app/qbs-setup-android/0000755000175100017510000000000015232633614017413 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs-setup-android/android-setup.h0000644000175100017510000000435015232633614022344 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_SDKSETUP_H #define QBS_SETUP_ANDROID_SDKSETUP_H #include namespace qbs { class Settings; } QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE void setupAndroid(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath, const QString &qtSdkDirPath); #endif // Include guard. qbs-src-3.3.1/src/app/qbs-setup-android/commandlineparser.cpp0000644000175100017510000001336715232633614023634 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include CommandLineParser::CommandLineParser() = default; using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString sdkDirOption() { return QStringLiteral("--sdk-dir"); } static QString ndkDirOption() { return QStringLiteral("--ndk-dir"); } static QString qtSdkDirOption() { return QStringLiteral("--qt-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_sdkDir.clear(); m_ndkDir.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); else if (arg == systemOption()) m_settingsScope = qbs::Settings::SystemScope; else if (arg == sdkDirOption()) assignOptionArgument(sdkDirOption(), m_sdkDir); else if (arg == ndkDirOption()) assignOptionArgument(ndkDirOption(), m_ndkDir); else if (arg == qtSdkDirOption()) assignOptionArgument(arg, m_qtSdkDir); else throwError(Tr::tr("Unknown option '%1'.").arg(arg)); } if (m_helpRequested) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: throwError(Tr::tr("No profile name supplied.")); case 1: m_profileName = m_commandLine.takeFirst(); m_profileName.replace(QLatin1Char('.'), QLatin1Char('-')); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Android SDK and NDK installations.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%6] [%3 ] [%4 ] [%5 ] " "\n") .arg(m_command, settingsDirOption(), ndkDirOption(), sdkDirOption(), qtSdkDirOption(), systemOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("If an NDK path is given, the profile will be suitable for use with Android " "projects that contain native C/C++ code.\n"); s += Tr::tr("If a Qt path is also given, the profile will be suitable for developing " "Qt applications for Android.\n"); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-3.3.1/src/app/qbs-setup-android/CMakeLists.txt0000644000175100017510000000033415232633614022153 0ustar runnerrunnerset(SOURCES android-setup.cpp android-setup.h commandlineparser.cpp commandlineparser.h main.cpp ) add_qbs_app(qbs-setup-android DEPENDS qbscore qbsconsolelogger SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/qbs-setup-android/qbs-setup-android.exe.manifest0000644000175100017510000000073315232633614025267 0ustar runnerrunner qbs-src-3.3.1/src/app/qbs-setup-android/qbs-setup-android.qbs0000644000175100017510000000103415232633614023461 0ustar runnerrunnerQbsApp { name: "qbs-setup-android" files: [ "android-setup.cpp", "android-setup.h", "commandlineparser.cpp", "commandlineparser.h", "main.cpp", ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: "qbs-setup-android.rc" Group { name: "qbs-setup-android manifest" files: "qbs-setup-android.exe.manifest" fileTags: [] // the manifest is referenced by the rc file } } } qbs-src-3.3.1/src/app/qbs-setup-android/android-setup.cpp0000644000175100017510000002313215232633614022676 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "android-setup.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using qbs::Internal::Tr; static QString qls(const char *s) { return QLatin1String(s); } static QStringList expectedArchs() { return {QStringLiteral("arm64"), QStringLiteral("armv7a"), QStringLiteral("x86"), QStringLiteral("x86_64")}; } void setupSdk(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath) { if (!QDir(sdkDirPath).exists()) { throw ErrorInfo(Tr::tr("SDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(sdkDirPath))); } Profile profile(profileName, settings); profile.removeProfile(); if (!sdkDirPath.isEmpty()) profile.setValue(qls("Android.sdk.sdkDir"), QDir::cleanPath(sdkDirPath)); profile.setValue(qls("qbs.targetPlatform"), qls("android")); } static QString mapArch(const QString &androidName) { if (androidName == qls("arm64-v8a")) return qls("arm64"); if (androidName == qls("armeabi")) return qls("armv5te"); if (androidName == qls("armeabi-v7a")) return qls("armv7a"); return androidName; } struct QtAndroidInfo { bool isValid() const { return !archs.isEmpty(); } QString qmakePath; QStringList archs; QString platform; }; static QtAndroidInfo getInfoForQtDir(const QString &qtDir) { QtAndroidInfo info; info.qmakePath = qbs::Internal::HostOsInfo::appendExecutableSuffix(qtDir + qls("/bin/qmake")); if (!QFile::exists(info.qmakePath)) return info; QFile qdevicepri(qtDir + qls("/mkspecs/qdevice.pri")); if (!qdevicepri.open(QIODevice::ReadOnly)) return info; while (!qdevicepri.atEnd()) { // For Qt < 5.14 use DEFAULT_ANDROID_TARGET_ARCH (which is the abi) to compute // the architecture // DEFAULT_ANDROID_ABIS doesn't exit // For Qt >= 5.14: // DEFAULT_ANDROID_TARGET_ARCH doesn't exist, use DEFAULT_ANDROID_ABIS to compute // the architectures const QByteArray line = qdevicepri.readLine().simplified(); const bool isArchLine = line.startsWith("DEFAULT_ANDROID_TARGET_ARCH"); const bool isAbisLine = line.startsWith("DEFAULT_ANDROID_ABIS"); const bool isPlatformLine = line.startsWith("DEFAULT_ANDROID_PLATFORM"); if (!isArchLine && !isPlatformLine && !isAbisLine) continue; const QList elems = line.split('='); if (elems.size() != 2) continue; const QString rhs = QString::fromLatin1(elems.at(1).trimmed()); if (isArchLine) { info.archs << mapArch(rhs); } else if (isAbisLine) { const auto abis = rhs.split(QLatin1Char(' ')); for (const QString &abi: abis) info.archs << mapArch(abi); } else { info.platform = rhs; } } return info; } using QtInfoPerArch = QHash; static QtInfoPerArch getQtAndroidInfo(const QString &qtSdkDir) { QtInfoPerArch archs; if (qtSdkDir.isEmpty()) return archs; QStringList qtDirs(qtSdkDir); const QStringList nameFilters{QStringLiteral("android_*"), QStringLiteral("android")}; QDirIterator dit(qtSdkDir, nameFilters, QDir::Dirs); while (dit.hasNext()) qtDirs << dit.next(); for (const auto &qtDir : std::as_const(qtDirs)) { const QtAndroidInfo info = getInfoForQtDir(qtDir); if (info.isValid()) { for (const QString &arch: info.archs) archs.insert(arch, info); } } return archs; } static QString maximumPlatform(const QString &platform1, const QString &platform2) { if (platform1.isEmpty()) return platform2; if (platform2.isEmpty()) return platform1; static const QString prefix = qls("android-"); const QString numberString1 = platform1.mid(prefix.size()); const QString numberString2 = platform2.mid(prefix.size()); bool ok; const int value1 = numberString1.toInt(&ok); if (!ok) { qWarning("Ignoring malformed Android platform string '%s'.", qPrintable(platform1)); return platform2; } const int value2 = numberString2.toInt(&ok); if (!ok) { qWarning("Ignoring malformed Android platform string '%s'.", qPrintable(platform2)); return platform1; } return prefix + QString::number(std::max(value1, value2)); } static QString getToolchainType(const QString &ndkDirPath) { QFile sourceProperties(ndkDirPath + qls("/source.properties")); if (!sourceProperties.open(QIODevice::ReadOnly)) return QStringLiteral("gcc"); // <= r10 while (!sourceProperties.atEnd()) { const QByteArray curLine = sourceProperties.readLine().simplified(); static const QByteArray prefix = "Pkg.Revision = "; if (!curLine.startsWith(prefix)) continue; qbs::Version ndkVersion = qbs::Version::fromString( QString::fromLatin1(curLine.mid(prefix.size()))); if (!ndkVersion.isValid()) { qWarning("Unexpected format of NDK revision string in '%s'", qPrintable(sourceProperties.fileName())); return QStringLiteral("clang"); } return qls(ndkVersion.majorVersion() >= 18 ? "clang" : "gcc"); } qWarning("No revision entry found in '%s'", qPrintable(sourceProperties.fileName())); return QStringLiteral("clang"); } static void setupNdk(qbs::Settings *settings, const QString &profileName, const QString &ndkDirPath, const QString &qtSdkDirPath) { if (!QDir(ndkDirPath).exists()) { throw ErrorInfo(Tr::tr("NDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(ndkDirPath))); } Profile mainProfile(profileName, settings); if (!ndkDirPath.isEmpty()) { mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath)); } mainProfile.setValue(qls("qbs.toolchainType"), getToolchainType(ndkDirPath)); const QStringList archs = expectedArchs(); const QtInfoPerArch infoPerArch = getQtAndroidInfo(qtSdkDirPath); const QStringList archsForProfile = infoPerArch.empty() ? archs : QStringList(infoPerArch.keys()); if (archsForProfile.size() == 1) mainProfile.setValue(qls("qbs.architecture"), archsForProfile.front()); else mainProfile.setValue(qls("qbs.architectures"), archsForProfile); QStringList qmakeFilePaths; QString platform; for (const QString &arch : archs) { const QtAndroidInfo qtAndroidInfo = infoPerArch.value(arch); if (!qtAndroidInfo.isValid()) continue; qmakeFilePaths << qtAndroidInfo.qmakePath; platform = maximumPlatform(platform, qtAndroidInfo.platform); } if (!qmakeFilePaths.empty()) { qmakeFilePaths.removeDuplicates(); mainProfile.setValue(qls("moduleProviders.Qt.qmakeFilePaths"), qmakeFilePaths); } if (!platform.isEmpty()) mainProfile.setValue(qls("Android.ndk.platform"), platform); } void setupAndroid(Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath, const QString &qtSdkDirPath) { setupSdk(settings, profileName, sdkDirPath); setupNdk(settings, profileName, ndkDirPath, qtSdkDirPath); } qbs-src-3.3.1/src/app/qbs-setup-android/commandlineparser.h0000644000175100017510000000602015232633614023265 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #define QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString sdkDir() const { return m_sdkDir; } QString ndkDir() const { return m_ndkDir; } QString qtSdkDir() const { return m_qtSdkDir; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested = false; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_sdkDir; QString m_ndkDir; QString m_qtSdkDir; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard. qbs-src-3.3.1/src/app/qbs-setup-android/main.cpp0000644000175100017510000000545215232633614021051 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "android-setup.h" #include #include #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } qbs::Settings settings(clParser.settingsDir()); settings.setScopeForWriting(clParser.settingsScope()); setupAndroid(&settings, clParser.profileName(), clParser.sdkDir(), clParser.ndkDir(), clParser.qtSdkDir()); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(qbs::Internal::Tr::tr("Error: %1").arg(e.toString())) << std::endl; return EXIT_FAILURE; } } qbs-src-3.3.1/src/app/qbs-setup-android/qbs-setup-android.rc0000644000175100017510000000022515232633614023301 0ustar runnerrunner#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-android.exe.manifest" qbs-src-3.3.1/src/app/qbs-setup-toolchains/0000755000175100017510000000000015232633614020136 5ustar runnerrunnerqbs-src-3.3.1/src/app/qbs-setup-toolchains/commandlineparser.cpp0000644000175100017510000001342115232633614024346 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString detectOption() { return QStringLiteral("--detect"); } static QString typeOption() { return QStringLiteral("--type"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_compilerPath.clear(); m_toolchainType.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == systemOption()) m_settingsScope = qbs::Settings::SystemScope; else if (arg == typeOption()) assignOptionArgument(typeOption(), m_toolchainType); else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_compilerPath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); m_profileName.replace(QLatin1Char('.'), QLatin1Char('-')); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from toolchains.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%4] %3\n") .arg(m_command, settingsDirOption(), detectOption(), systemOption()); s += Tr::tr(" %1 [%3 ] [%4] [%2 ] " " \n") .arg(m_command, typeOption(), settingsDirOption(), systemOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known toolchains, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one toolchain. It will attempt " "to find out the toolchain type automatically.\nIn case the compiler has " "an unusual file name, you may need to provide the '--type' option."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/dmcprobe.h0000644000175100017510000000453315232633614022107 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_DMCPROBE_H #define QBS_SETUPTOOLCHAINS_DMCPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } bool isDmcCompiler(const QString &compilerName); void createDmcProfile(const QFileInfo &compiler, qbs::Settings *settings, QStringView profileName); void dmcProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/msvcprobe.h0000644000175100017510000000445615232633614022320 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_MSVCPROBE_H #define QBS_SETUPTOOLCHAINS_MSVCPROBE_H #include #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } void createMsvcProfile(const QFileInfo &compiler, qbs::Settings *settings, const QString &profileName); void msvcProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/watcomprobe.h0000644000175100017510000000455015232633614022635 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_WATCOMPROBE_H #define QBS_SETUPTOOLCHAINS_WATCOMPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } // namespace qbs bool isWatcomCompiler(const QString &compilerName); void createWatcomProfile( const QFileInfo &compiler, qbs::Settings *settings, QStringView profileName); void watcomProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/xcodeprobe.h0000644000175100017510000000415015232633614022441 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_XCODEPROBE_H #define QBS_SETUPTOOLCHAINS_XCODEPROBE_H #include namespace qbs { class Profile; class Settings; } void xcodeProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/watcomprobe.cpp0000644000175100017510000002341415232633614023170 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2022 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "watcomprobe.h" #include "probe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; namespace { struct Details { QStringView architecture; QStringView platform; }; constexpr struct Platform { QStringView flag; Details keys; Details target; } knownPlatforms[] = { // DOS 16/32 bit. {u"-bdos", {u"__I86__", u"__DOS__"}, {u"x86_16", u"dos"}}, {u"-bdos4g", {u"__386__", u"__DOS__"}, {u"x86", u"dos"}}, // Windows 16/32 bit. {u"-bwindows", {u"__I86__", u"__WINDOWS__"}, {u"x86_16", u"windows"}}, {u"-bnt", {u"__386__", u"__NT__"}, {u"x86", u"windows"}}, // OS/2 16/32 bit. {u"-bos2", {u"__I86__", u"__OS2__"}, {u"x86_16", u"os2"}}, {u"-bos2v2", {u"__386__", u"__OS2__"}, {u"x86", u"os2"}}, // Linux 32 bit. {u"-blinux", {u"__386__", u"__LINUX__"}, {u"x86", u"linux"}}, }; } // namespace static QStringList knownWatcomCompilerNames() { return {QStringLiteral("owcc")}; } static QStringList dumpOutput(const QFileInfo &compiler, QStringView flag, const QList &keys) { const QString filePath = QDir(QDir::tempPath()).absoluteFilePath( QLatin1String("watcom-dump.c")); QFile fakeIn(filePath); if (!fakeIn.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) { qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") .arg(fakeIn.fileName(), fakeIn.errorString()); return {}; } fakeIn.write("#define VALUE_TO_STRING(x) #x\n"); fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n"); fakeIn.write("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)\n"); for (const auto &key : keys) { fakeIn.write("#if defined(" + key.toLatin1() + ")\n"); fakeIn.write("#pragma message (VAR_NAME_VALUE(" + key.toLatin1() + "))\n"); fakeIn.write("#endif\n"); } fakeIn.close(); QProcess p; QStringList args; if (!flag.isEmpty()) args.push_back(flag.toString()); args.push_back(QDir::toNativeSeparators(filePath)); p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); fakeIn.remove(); QStringList lines = QString::fromUtf8(p.readAllStandardOutput()) .split(QRegularExpression(QLatin1String("\\r?\\n"))); return lines; } static bool supportsWatcomPlatform(const QFileInfo &compiler, const Platform &platform) { const auto macros = dumpMacros([&compiler, &platform]() { const QList keys = {platform.keys.architecture, platform.keys.platform}; return dumpOutput(compiler, platform.flag, keys); }); auto matches = [¯os](QStringView key) { const auto k = key.toString(); if (!macros.contains(k)) return false; return macros.value(k) == QLatin1String("1"); }; return matches(platform.keys.architecture) && matches(platform.keys.platform); } static std::vector createWatcomProfileHelper(const ToolchainInstallInfo &info, Settings *settings, QStringView profileName = {}) { const QFileInfo compiler = info.compilerPath; std::vector profiles; for (const auto &knownPlatform : knownPlatforms) { // Don't create a profile in case the compiler does // not support the proposed architecture. if (!supportsWatcomPlatform(compiler, knownPlatform)) continue; QString fullProfilename; if (profileName.isEmpty()) { // Create a full profile name in case we is in auto-detecting mode. if (!info.compilerVersion.isValid()) { fullProfilename = QStringLiteral("watcom-unknown-%1-%2") .arg(knownPlatform.target.platform) .arg(knownPlatform.target.architecture); } else { const QString version= info.compilerVersion.toString(QLatin1Char('_'), QLatin1Char('_')); fullProfilename = QStringLiteral("watcom-%1-%2-%3") .arg(version) .arg(knownPlatform.target.platform) .arg(knownPlatform.target.architecture); } } else { // Append the detected actual architecture name to the proposed profile name. fullProfilename = QStringLiteral("%1-%2-%3") .arg(profileName) .arg(knownPlatform.target.platform) .arg(knownPlatform.target.architecture); } Profile profile(fullProfilename, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("watcom")); profile.setValue(QStringLiteral("qbs.architecture"), knownPlatform.target.architecture.toString()); profile.setValue(QStringLiteral("qbs.targetPlatform"), knownPlatform.target.platform.toString()); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profile.name(), compiler.absoluteFilePath()); profiles.push_back(std::move(profile)); } return profiles; } static Version dumpWatcomVersion(const QFileInfo &compiler) { const QList keys = {u"__WATCOMC__", u"__WATCOM_CPLUSPLUS__"}; const auto macros = dumpMacros([&compiler, &keys]() { return dumpOutput(compiler, u"", keys); }); for (const auto ¯o : macros) { const int verCode = macro.toInt(); return Version{(verCode - 1100) / 100, (verCode / 10) % 10, ((verCode % 10) > 0) ? (verCode % 10) : 0}; } qbsWarning() << Tr::tr("No __WATCOMC__ or __WATCOM_CPLUSPLUS__ tokens was found" " in the compiler dump"); return Version{}; } static std::vector installedWatcomsFromPath() { std::vector infos; const auto compilerNames = knownWatcomCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo watcomPath(findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!watcomPath.exists()) continue; const Version version = dumpWatcomVersion(watcomPath); infos.push_back({watcomPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } bool isWatcomCompiler(const QString &compilerName) { return Internal::any_of(knownWatcomCompilerNames(), [compilerName](const QString &knownName) { return compilerName.contains(knownName); }); } void createWatcomProfile(const QFileInfo &compiler, Settings *settings, QStringView profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createWatcomProfileHelper(info, settings, profileName); } void watcomProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect WATCOM toolchains..."); const std::vector allInfos = installedWatcomsFromPath(); if (allInfos.empty()) { qbsInfo() << Tr::tr("No WATCOM toolchains found."); return; } for (const ToolchainInstallInfo &info : allInfos) { const auto newProfiles = createWatcomProfileHelper(info, settings); profiles.reserve(profiles.size() + int(newProfiles.size())); std::copy(newProfiles.cbegin(), newProfiles.cend(), std::back_inserter(profiles)); } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/keilprobe.cpp0000644000175100017510000004077515232633614022633 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "keilprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; using Internal::HostOsInfo; static QStringList knownKeilCompilerNames() { return {QStringLiteral("c51"), QStringLiteral("c251"), QStringLiteral("c166"), QStringLiteral("armcc"), QStringLiteral("armclang")}; } static QString guessKeilArchitecture(const QFileInfo &compiler) { const auto baseName = compiler.baseName(); if (baseName == QLatin1String("c51")) return QStringLiteral("mcs51"); if (baseName == QLatin1String("c251")) return QStringLiteral("mcs251"); if (baseName == QLatin1String("c166")) return QStringLiteral("c166"); if (baseName == QLatin1String("armcc")) return QStringLiteral("arm"); if (baseName == QLatin1String("armclang")) return QStringLiteral("arm"); return {}; } static bool isArmClangCompiler(const QFileInfo &compiler) { return compiler.baseName() == QLatin1String("armclang"); } static Profile createKeilProfileHelper(const ToolchainInstallInfo &info, Settings *settings, QString profileName = QString()) { const QFileInfo compiler = info.compilerPath; const QString architecture = guessKeilArchitecture(compiler); // In case the profile is auto-detected. if (profileName.isEmpty()) { if (!info.compilerVersion.isValid()) { profileName = QStringLiteral("keil-unknown-%1").arg(architecture); } else { const QString version = info.compilerVersion.toString(QLatin1Char('_'), QLatin1Char('_')); if (architecture == QLatin1String("arm") && isArmClangCompiler(compiler)) { profileName = QStringLiteral("keil-llvm-%1-%2").arg( version, architecture); } else { profileName = QStringLiteral("keil-%1-%2").arg( version, architecture); } } } Profile profile(profileName, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("cpp.compilerName"), compiler.fileName()); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("keil")); if (!architecture.isEmpty()) profile.setValue(QStringLiteral("qbs.architecture"), architecture); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()); return profile; } static Version dumpMcsCompilerVersion(const QFileInfo &compiler) { QTemporaryFile fakeIn; if (!fakeIn.open()) { qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") .arg(fakeIn.fileName(), fakeIn.errorString()); return Version{}; } fakeIn.write("#define VALUE_TO_STRING(x) #x\n"); fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n"); // Prepare for C51 compiler. fakeIn.write("#if defined(__C51__) || defined(__CX51__)\n"); fakeIn.write("# define VAR_NAME_VALUE(var) \"(\"\"\"\"|\"#var\"|\"VALUE(var)\"|\"\"\"\")\"\n"); fakeIn.write("# if defined (__C51__)\n"); fakeIn.write("# pragma message (VAR_NAME_VALUE(__C51__))\n"); fakeIn.write("# endif\n"); fakeIn.write("# if defined(__CX51__)\n"); fakeIn.write("# pragma message (VAR_NAME_VALUE(__CX51__))\n"); fakeIn.write("# endif\n"); fakeIn.write("#endif\n"); // Prepare for C251 compiler. fakeIn.write("#if defined(__C251__)\n"); fakeIn.write("# define VAR_NAME_VALUE(var) \"\"|#var|VALUE(var)|\"\"\n"); fakeIn.write("# if defined(__C251__)\n"); fakeIn.write("# warning (VAR_NAME_VALUE(__C251__))\n"); fakeIn.write("# endif\n"); fakeIn.write("#endif\n"); fakeIn.close(); const QStringList args = {fakeIn.fileName()}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const QStringList knownKeys = {QStringLiteral("__C51__"), QStringLiteral("__CX51__"), QStringLiteral("__C251__")}; auto extractVersion = [&knownKeys](const QByteArray &output) { QTextStream stream(output); QString line; while (stream.readLineInto(&line)) { if (!line.startsWith(QLatin1String("***"))) continue; enum { KEY_INDEX = 1, VALUE_INDEX = 2, ALL_PARTS = 4 }; const QStringList parts = line.split(QLatin1String("\"|\"")); if (parts.count() != ALL_PARTS) continue; if (!knownKeys.contains(parts.at(KEY_INDEX))) continue; return parts.at(VALUE_INDEX).toInt(); } return -1; }; const QByteArray dump = p.readAllStandardOutput(); const int verCode = extractVersion(dump); if (verCode < 0) { qbsWarning() << Tr::tr("No %1 tokens was found" " in the compiler dump:\n%2") .arg(knownKeys.join(QLatin1Char(',')), QString::fromUtf8(dump)); return Version{}; } return Version{verCode / 100, verCode % 100}; } static Version dumpC166CompilerVersion(const QFileInfo &compiler) { QTemporaryFile fakeIn; if (!fakeIn.open()) { qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") .arg(fakeIn.fileName(), fakeIn.errorString()); return Version{}; } fakeIn.write("#if defined(__C166__)\n"); fakeIn.write("# warning __C166__\n"); fakeIn.write("# pragma __C166__\n"); fakeIn.write("#endif\n"); fakeIn.close(); const QStringList args = {fakeIn.fileName()}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); // Extract the compiler version pattern in the form, like: // // *** WARNING C320 IN LINE 41 OF c51.c: __C166__ // *** WARNING C2 IN LINE 42 OF c51.c: '757': unknown #pragma/control, line ignored // // where the '__C166__' is a key, and the '757' is a value (aka version). auto extractVersion = [](const QString &output) { const QStringList lines = output.split(QStringLiteral("\r\n")); for (auto it = lines.cbegin(); it != lines.cend();) { if (it->startsWith(QLatin1String("***")) && it->endsWith(QLatin1String("__C166__"))) { ++it; if (it == lines.cend() || !it->startsWith(QLatin1String("***"))) break; const int startIndex = it->indexOf(QLatin1Char('\'')); if (startIndex == -1) break; const int stopIndex = it->indexOf(QLatin1Char('\''), startIndex + 1); if (stopIndex == -1) break; const QString v = it->mid(startIndex + 1, stopIndex - startIndex - 1); return v.toInt(); } ++it; } return -1; }; const QByteArray dump = p.readAllStandardOutput(); const int verCode = extractVersion(QString::fromUtf8(dump)); if (verCode < 0) { qbsWarning() << Tr::tr("No __C166__ token was found" " in the compiler dump:\n%1") .arg(QString::fromUtf8(dump)); return Version{}; } return Version{verCode / 100, verCode % 100}; } static Version dumpArmCCCompilerVersion(const QFileInfo &compiler) { const QStringList args = {QStringLiteral("-E"), QStringLiteral("--list-macros"), QStringLiteral("nul")}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const auto es = p.exitStatus(); if (es != QProcess::NormalExit) { const QByteArray out = p.readAll(); qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") .arg(QString::fromUtf8(out)); return Version{}; } const QByteArray dump = p.readAll(); const int verCode = extractVersion(dump, "__ARMCC_VERSION "); if (verCode < 0) { qbsWarning() << Tr::tr("No '__ARMCC_VERSION' token was found " "in the compiler dump:\n%1") .arg(QString::fromUtf8(dump)); return Version{}; } return Version{verCode / 1000000, (verCode / 10000) % 100, verCode % 10000}; } static Version dumpArmClangCompilerVersion(const QFileInfo &compiler) { const QStringList args = {QStringLiteral("-dM"), QStringLiteral("-E"), QStringLiteral("-xc"), QStringLiteral("--target=arm-arm-none-eabi"), QStringLiteral("-mcpu=cortex-m0"), QStringLiteral("nul")}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const auto es = p.exitStatus(); if (es != QProcess::NormalExit) { const QByteArray out = p.readAll(); qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") .arg(QString::fromUtf8(out)); return Version{}; } const QByteArray dump = p.readAll(); const int verCode = extractVersion(dump, "__ARMCC_VERSION "); if (verCode < 0) { qbsWarning() << Tr::tr("No '__ARMCC_VERSION' token was found " "in the compiler dump:\n%1") .arg(QString::fromUtf8(dump)); return Version{}; } return Version{verCode / 1000000, (verCode / 10000) % 100, verCode % 10000}; } static Version dumpKeilCompilerVersion(const QFileInfo &compiler) { const QString arch = guessKeilArchitecture(compiler); if (arch == QLatin1String("mcs51") || arch == QLatin1String("mcs251")) return dumpMcsCompilerVersion(compiler); if (arch == QLatin1String("c166")) return dumpC166CompilerVersion(compiler); if (arch == QLatin1String("arm")) { if (isArmClangCompiler(compiler)) return dumpArmClangCompilerVersion(compiler); return dumpArmCCCompilerVersion(compiler); } return Version{}; } static std::vector installedKeilsFromPath() { std::vector infos; const auto compilerNames = knownKeilCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo keilPath( findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!keilPath.exists()) continue; const Version version = dumpKeilCompilerVersion(keilPath); infos.push_back({keilPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } static std::vector installedKeilsFromRegistry() { std::vector infos; if (HostOsInfo::isWindowsHost()) { #ifdef Q_OS_WIN64 static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Keil\\Products"; #else static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Keil\\Products"; #endif QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat); const auto productGroups = registry.childGroups(); for (const QString &productKey : productGroups) { registry.beginGroup(productKey); const QString productPath = registry.value(QStringLiteral("Path")) .toString(); QString productVersion = registry.value(QStringLiteral("Version")) .toString(); if (productVersion.startsWith(QLatin1Char('V'))) productVersion.remove(0, 1); if (productKey == QLatin1String("MDK")) { const QFileInfo ccPath(productPath + QStringLiteral("/ARMCC/bin/armcc.exe")); if (ccPath.exists()) infos.push_back({ccPath, Version::fromString(productVersion)}); const QFileInfo clangPath(productPath + QStringLiteral("/ARMCLANG/bin/armclang.exe")); if (clangPath.exists()) infos.push_back({clangPath, Version::fromString(productVersion)}); } if (productKey == QLatin1String("C51")) { const QFileInfo cPath(productPath + QStringLiteral("/BIN/c51.exe")); if (cPath.exists()) infos.push_back({cPath, Version::fromString(productVersion)}); } if (productKey == QLatin1String("C251")) { const QFileInfo cPath(productPath + QStringLiteral("/BIN/c251.exe")); if (cPath.exists()) infos.push_back({cPath, Version::fromString(productVersion)}); } if (productKey == QLatin1String("C166")) { const QFileInfo cPath(productPath + QStringLiteral("/BIN/c166.exe")); if (cPath.exists()) infos.push_back({cPath, Version::fromString(productVersion)}); } registry.endGroup(); } } std::sort(infos.begin(), infos.end()); return infos; } bool isKeilCompiler(const QString &compilerName) { return Internal::any_of(knownKeilCompilerNames(), [compilerName]( const QString &knownName) { return compilerName.contains(knownName); }); } void createKeilProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createKeilProfileHelper(info, settings, std::move(profileName)); } void keilProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect KEIL toolchains..."); // Make sure that a returned infos are sorted before using the std::set_union! const std::vector regInfos = installedKeilsFromRegistry(); const std::vector pathInfos = installedKeilsFromPath(); std::vector allInfos; allInfos.reserve(regInfos.size() + pathInfos.size()); std::set_union(regInfos.cbegin(), regInfos.cend(), pathInfos.cbegin(), pathInfos.cend(), std::back_inserter(allInfos)); qbs::Internal::transform(allInfos, profiles, [settings](const auto &info) { return createKeilProfileHelper(info, settings); }); if (allInfos.empty()) qbsInfo() << Tr::tr("No KEIL toolchains found."); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/dmcprobe.cpp0000644000175100017510000002462715232633614022450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "dmcprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; using Internal::HostOsInfo; namespace { struct Target { QString platform; QString architecture; QString extender; }; } static QStringList knownDmcCompilerNames() { return {QStringLiteral("dmc")}; } static QStringList dumpOutput(const QFileInfo &compiler, const QStringList &flags, const QStringList &keys) { const QString filePath = QDir(QDir::tempPath()).absoluteFilePath( QLatin1String("dmc-dump.c")); QFile fakeIn(filePath); if (!fakeIn.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) { qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") .arg(fakeIn.fileName(), fakeIn.errorString()); return {}; } fakeIn.write("#define VALUE_TO_STRING(x) #x\n"); fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n"); fakeIn.write("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)\n"); for (const auto &key : keys) { const auto content = key.toLatin1(); fakeIn.write("#if defined(" + content + ")\n"); fakeIn.write("#pragma message (VAR_NAME_VALUE(" + content + "))\n"); fakeIn.write("#endif\n"); } fakeIn.close(); QStringList args = {QStringLiteral("-e")}; args.reserve(args.size() + int(flags.size())); std::copy(flags.cbegin(), flags.cend(), std::back_inserter(args)); args.push_back(QDir::toNativeSeparators(filePath)); QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); fakeIn.remove(); static QRegularExpression re(QLatin1String("\\r?\\n")); return QString::fromUtf8(p.readAllStandardOutput()).split(re); } static std::optional dumpDmcTarget(const QFileInfo &compiler, const QStringList &flags) { const QStringList keys = { QStringLiteral("DOS16RM"), QStringLiteral("DOS386"), QStringLiteral("MSDOS"), QStringLiteral("__NT__"), QStringLiteral("_WINDOWS"), }; const auto macros = dumpMacros([&compiler, &flags, &keys]() { return dumpOutput(compiler, flags, keys); }); if (macros.contains(QLatin1String("__NT__"))) { return Target{QLatin1String("windows"), QLatin1String("x86"), QLatin1String("")}; } else if (macros.contains(QLatin1String("_WINDOWS"))) { return Target{QLatin1String("windows"), QLatin1String("x86_16"), QLatin1String("")}; } else if (macros.contains(QLatin1String("DOS386"))) { if (flags.contains(QLatin1String("-mx"))) return Target{QLatin1String("dos"), QLatin1String("x86"), QLatin1String("dosx")}; else if (flags.contains(QLatin1String("-mp"))) return Target{QLatin1String("dos"), QLatin1String("x86"), QLatin1String("dosp")}; } else if (macros.contains(QLatin1String("DOS16RM"))) { if (flags.contains(QLatin1String("-mz"))) return Target{QLatin1String("dos"), QLatin1String("x86_16"), QLatin1String("dosz")}; else if (flags.contains(QLatin1String("-mr"))) return Target{QLatin1String("dos"), QLatin1String("x86_16"), QLatin1String("dosr")}; } else if (macros.contains(QLatin1String("MSDOS"))) { return Target{QLatin1String("dos"), QLatin1String("x86_16"), QLatin1String("")}; } return {}; } static std::vector createDmcProfileHelper(const ToolchainInstallInfo &info, Settings *settings, QStringView profileName = {}) { const QFileInfo compiler = info.compilerPath; std::vector profiles; const QVector probes = { { QStringLiteral("-mn"), QStringLiteral("-WA") }, // Windows NT 32 bit. { QStringLiteral("-ml"), QStringLiteral("-WA") }, // Windows 3.x 16 bit. { QStringLiteral("-mx") }, // DOS with DOSX extender 32 bit. { QStringLiteral("-mp") }, // DOS with Phar Lap extender 32 bit. { QStringLiteral("-mr") }, // DOS with Rational DOS Extender 16 bit. { QStringLiteral("-mz") }, // DOS with ZPM DOS Extender 16 bit. { QStringLiteral("-mc") }, // DOS 16 bit. }; for (const auto &flags : probes) { const auto target = dumpDmcTarget(compiler, flags); if (!target) continue; QString fullProfilename; QString platform = target->extender.isEmpty() ? target->platform : target->extender; if (profileName.isEmpty()) { // Create a full profile name in case we is in auto-detecting mode. if (!info.compilerVersion.isValid()) { fullProfilename = QStringLiteral("dmc-unknown-%1-%2") .arg(platform, target->architecture); } else { const QString version = info.compilerVersion.toString(QLatin1Char('_'), QLatin1Char('_')); fullProfilename = QStringLiteral("dmc-%1-%2-%3") .arg(version, platform, target->architecture); } } else { // Append the detected actual architecture name to the proposed profile name. fullProfilename = QStringLiteral("%1-%2-%3") .arg(profileName, platform, target->architecture); } Profile profile(fullProfilename, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("dmc")); profile.setValue(QStringLiteral("qbs.architecture"), target->architecture); profile.setValue(QStringLiteral("qbs.targetPlatform"), target->platform); if (!target->extender.isEmpty()) profile.setValue(QStringLiteral("cpp.extenderName"), target->extender); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profile.name(), compiler.absoluteFilePath()); profiles.push_back(std::move(profile)); } return profiles; } static Version dumpDmcVersion(const QFileInfo &compiler) { const QStringList keys = {QStringLiteral("__DMC__")}; const auto macros = dumpMacros([&compiler, keys]() { return dumpOutput(compiler, {}, keys); }); for (const auto ¯o : macros) { if (!macro.startsWith(QLatin1String("0x"))) continue; const int verCode = macro.mid(2).toInt(); return Version{(verCode / 100), (verCode % 100), 0}; } qbsWarning() << Tr::tr("No __DMC__ token was found in the compiler dump"); return Version{}; } static std::vector installedDmcsFromPath() { std::vector infos; const auto compilerNames = knownDmcCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo dmcPath( findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!dmcPath.exists()) continue; const Version version = dumpDmcVersion(dmcPath); infos.push_back({dmcPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } bool isDmcCompiler(const QString &compilerName) { return Internal::any_of(knownDmcCompilerNames(), [compilerName](const QString &knownName) { return compilerName.contains(knownName); }); } void createDmcProfile(const QFileInfo &compiler, Settings *settings, QStringView profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createDmcProfileHelper(info, settings, profileName); } void dmcProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect DMC toolchains..."); const std::vector allInfos = installedDmcsFromPath(); if (allInfos.empty()) { qbsInfo() << Tr::tr("No DMC toolchains found."); return; } for (const ToolchainInstallInfo &info : allInfos) { const auto newProfiles = createDmcProfileHelper(info, settings); profiles.reserve(profiles.size() + int(newProfiles.size())); std::copy(newProfiles.cbegin(), newProfiles.cend(), std::back_inserter(profiles)); } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.rc0000644000175100017510000000023015232633614024543 0ustar runnerrunner#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-toolchains.exe.manifest" qbs-src-3.3.1/src/app/qbs-setup-toolchains/CMakeLists.txt0000644000175100017510000000113715232633614022700 0ustar runnerrunnerset(SOURCES clangclprobe.cpp clangclprobe.h commandlineparser.cpp commandlineparser.h cosmicprobe.cpp cosmicprobe.h dmcprobe.cpp dmcprobe.h emscriptenprobe.cpp emscriptenprobe.h gccprobe.cpp gccprobe.h iarewprobe.cpp iarewprobe.h keilprobe.cpp keilprobe.h main.cpp msvcprobe.cpp msvcprobe.h probe.cpp probe.h sdccprobe.cpp sdccprobe.h watcomprobe.cpp watcomprobe.h xcodeprobe.cpp xcodeprobe.h ) add_qbs_app(qbs-setup-toolchains DEPENDS qbscore qbsconsolelogger SOURCES ${SOURCES} ) qbs-src-3.3.1/src/app/qbs-setup-toolchains/xcodeprobe.cpp0000644000175100017510000002262015232633614022776 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "xcodeprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; static const QString defaultDeveloperPath = QStringLiteral("/Applications/Xcode.app/Contents/Developer"); static const std::regex defaultDeveloperPathRegex( "^/Applications/Xcode([a-zA-Z0-9 ._-]+)\\.app/Contents/Developer$"); static QString targetOS(const QString &applePlatformName) { if (applePlatformName == QStringLiteral("macosx")) return QStringLiteral("macos"); if (applePlatformName == QStringLiteral("iphoneos")) return QStringLiteral("ios"); if (applePlatformName == QStringLiteral("iphonesimulator")) return QStringLiteral("ios-simulator"); if (applePlatformName == QStringLiteral("appletvos")) return QStringLiteral("tvos"); if (applePlatformName == QStringLiteral("appletvsimulator")) return QStringLiteral("tvos-simulator"); if (applePlatformName == QStringLiteral("watchos")) return QStringLiteral("watchos"); if (applePlatformName == QStringLiteral("watchsimulator")) return QStringLiteral("watchos-simulator"); return {}; } static QStringList archList(const QString &applePlatformName) { QStringList archs; if (applePlatformName == QStringLiteral("macosx") || applePlatformName == QStringLiteral("iphonesimulator") || applePlatformName == QStringLiteral("appletvsimulator") || applePlatformName == QStringLiteral("watchsimulator")) { if (applePlatformName != QStringLiteral("appletvsimulator")) archs << QStringLiteral("x86"); if (applePlatformName != QStringLiteral("watchsimulator")) archs << QStringLiteral("x86_64"); if (applePlatformName == QStringLiteral("macosx") || QSysInfo::buildCpuArchitecture() == QStringLiteral("arm64")) { archs << QStringLiteral("arm64"); } } else if (applePlatformName == QStringLiteral("iphoneos") || applePlatformName == QStringLiteral("appletvos")) { if (applePlatformName != QStringLiteral("appletvos")) archs << QStringLiteral("armv7a"); archs << QStringLiteral("arm64"); } else if (applePlatformName == QStringLiteral("watchos")) { archs << QStringLiteral("armv7k"); } return archs; } namespace { class XcodeProbe { public: XcodeProbe(qbs::Settings *settings, std::vector &profiles) : settings(settings), profiles(profiles) { } bool addDeveloperPath(const QString &path); void detectDeveloperPaths(); void setupDefaultToolchains(const QString &devPath, const QString &xCodeName); void detectAll(); private: qbs::Settings *settings; std::vector &profiles; QStringList developerPaths; }; bool XcodeProbe::addDeveloperPath(const QString &path) { if (path.isEmpty()) return false; QFileInfo pInfo(path); if (!pInfo.exists() || !pInfo.isDir()) return false; if (developerPaths.contains(path)) return false; developerPaths.push_back(path); qbsInfo() << Tr::tr("Added developer path %1").arg(path); return true; } void XcodeProbe::detectDeveloperPaths() { QProcess selectedXcode; QString program = QStringLiteral("/usr/bin/xcode-select"); QStringList arguments(QStringLiteral("--print-path")); selectedXcode.start(program, arguments, QProcess::ReadOnly); if (!selectedXcode.waitForFinished(-1) || selectedXcode.exitCode()) { qbsInfo() << Tr::tr("Could not detect selected Xcode with /usr/bin/xcode-select"); } else { QString path = QString::fromLocal8Bit(selectedXcode.readAllStandardOutput().trimmed()); addDeveloperPath(path); } addDeveloperPath(defaultDeveloperPath); QProcess launchServices; program = QStringLiteral("/usr/bin/mdfind"); arguments = QStringList(QStringLiteral("kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'")); launchServices.start(program, arguments, QProcess::ReadOnly); if (!launchServices.waitForFinished(-1) || launchServices.exitCode()) { qbsInfo() << Tr::tr("Could not detect additional Xcode installations with /usr/bin/mdfind"); } else { const auto paths = QString::fromLocal8Bit(launchServices.readAllStandardOutput()) .split(QLatin1Char('\n'), Qt::SkipEmptyParts); for (const QString &path : paths) addDeveloperPath(path + QStringLiteral("/Contents/Developer")); } } void XcodeProbe::setupDefaultToolchains(const QString &devPath, const QString &xcodeName) { qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg(xcodeName, devPath); Profile installationProfile(xcodeName, settings); installationProfile.removeProfile(); installationProfile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("xcode")); if (devPath != defaultDeveloperPath) installationProfile.setValue(QStringLiteral("xcode.developerPath"), devPath); profiles.push_back(installationProfile); QStringList platforms; platforms << QStringLiteral("macosx") << QStringLiteral("iphoneos") << QStringLiteral("iphonesimulator") << QStringLiteral("appletvos") << QStringLiteral("appletvsimulator") << QStringLiteral("watchos") << QStringLiteral("watchsimulator"); for (const QString &platform : std::as_const(platforms)) { Profile platformProfile(xcodeName + QLatin1Char('-') + platform, settings); platformProfile.removeProfile(); platformProfile.setBaseProfile(installationProfile.name()); platformProfile.setValue(QStringLiteral("qbs.targetPlatform"), targetOS(platform)); profiles.push_back(platformProfile); const auto architectures = archList(platform); for (const QString &arch : architectures) { Profile archProfile(xcodeName + QLatin1Char('-') + platform + QLatin1Char('-') + arch, settings); archProfile.removeProfile(); archProfile.setBaseProfile(platformProfile.name()); archProfile.setValue(QStringLiteral("qbs.architecture"), qbs::canonicalArchitecture(arch)); profiles.push_back(archProfile); } } } void XcodeProbe::detectAll() { int i = 1; detectDeveloperPaths(); for (const QString &developerPath : std::as_const(developerPaths)) { QString profileName = QStringLiteral("xcode"); if (developerPath != defaultDeveloperPath) { const auto devPath = developerPath.toStdString(); std::smatch match; if (std::regex_match(devPath, match, defaultDeveloperPathRegex)) profileName += QString::fromStdString(match[1]).toLower(). replace(QLatin1Char(' '), QLatin1Char('-')). replace(QLatin1Char('.'), QLatin1Char('_')); else profileName += QString::number(i++); } setupDefaultToolchains(developerPath, profileName); } } } // end anonymous namespace void xcodeProbe(qbs::Settings *settings, std::vector &profiles) { XcodeProbe probe(settings, profiles); probe.detectAll(); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.exe.manifest0000644000175100017510000000073615232633614026540 0ustar runnerrunner qbs-src-3.3.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs0000644000175100017510000000223415232633614024732 0ustar runnerrunnerQbsApp { name: "qbs-setup-toolchains" cpp.dynamicLibraries: qbs.targetOS.contains("windows") ? base.concat("shell32") : base files: [ "clangclprobe.cpp", "clangclprobe.h", "commandlineparser.cpp", "commandlineparser.h", "cosmicprobe.cpp", "cosmicprobe.h", "dmcprobe.cpp", "dmcprobe.h", "emscriptenprobe.cpp", "emscriptenprobe.h", "gccprobe.cpp", "gccprobe.h", "iarewprobe.cpp", "iarewprobe.h", "keilprobe.cpp", "keilprobe.h", "main.cpp", "msvcprobe.cpp", "msvcprobe.h", "probe.cpp", "probe.h", "sdccprobe.cpp", "sdccprobe.h", "watcomprobe.cpp", "watcomprobe.h", "xcodeprobe.cpp", "xcodeprobe.h", ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: "qbs-setup-toolchains.rc" Group { name: "qbs-setup-toolchains manifest" files: "qbs-setup-toolchains.exe.manifest" fileTags: [] // the manifest is referenced by the rc file } } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/probe.cpp0000644000175100017510000002763015232633614021761 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "clangclprobe.h" #include "cosmicprobe.h" #include "dmcprobe.h" #include "emscriptenprobe.h" #include "gccprobe.h" #include "iarewprobe.h" #include "keilprobe.h" #include "msvcprobe.h" #include "sdccprobe.h" #include "watcomprobe.h" #include "xcodeprobe.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN // We need defines for Windows 8. #undef _WIN32_WINNT #define _WIN32_WINNT _WIN32_WINNT_WIN8 #include #include #else #include #endif // Q_OS_WIN using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; static QTextStream qStdout(stdout); static QTextStream qStderr(stderr); QStringList systemSearchPaths() { return QString::fromLocal8Bit(qgetenv("PATH")).split(HostOsInfo::pathListSeparator()); } QString findExecutable(const QString &fileName) { QStringList suffixList{QString()}; if (HostOsInfo::isWindowsHost()) { if (!fileName.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive) && !fileName.endsWith(QLatin1String(".bat"), Qt::CaseInsensitive)) suffixList = QStringList{QStringLiteral(".exe"), QStringLiteral(".bat")}; } const auto ppaths = systemSearchPaths(); for (const QString &ppath : ppaths) { for (const auto &suffix : suffixList) { const QString fullPath = ppath + QLatin1Char('/') + fileName + suffix; if (QFileInfo::exists(fullPath)) return QDir::cleanPath(fullPath); } } return {}; } QString toolchainTypeFromCompilerName(const QString &compilerName) { if (compilerName == QLatin1String("cl.exe")) return QStringLiteral("msvc"); if (compilerName == QLatin1String("clang-cl.exe")) return QStringLiteral("clang-cl"); const auto types = { QStringLiteral("clang"), QStringLiteral("llvm"), QStringLiteral("mingw"), QStringLiteral("gcc") }; for (const auto &type : types) { if (compilerName.contains(type)) return type; } if (compilerName == QLatin1String("g++")) return QStringLiteral("gcc"); if (isEmscriptenCompiler(compilerName)) return QStringLiteral("emscripten"); if (isIarCompiler(compilerName)) return QStringLiteral("iar"); if (isKeilCompiler(compilerName)) return QStringLiteral("keil"); if (isSdccCompiler(compilerName)) return QStringLiteral("sdcc"); if (isCosmicCompiler(compilerName)) return QStringLiteral("cosmic"); if (isDmcCompiler(compilerName)) return QStringLiteral("dmc"); if (isWatcomCompiler(compilerName)) return QStringLiteral("watcom"); return {}; } void probe(Settings *settings) { std::vector profiles; if (HostOsInfo::isWindowsHost()) { msvcProbe(settings, profiles); clangClProbe(settings, profiles); } else if (HostOsInfo::isMacosHost()) { xcodeProbe(settings, profiles); } gccProbe(settings, profiles, QStringLiteral("gcc")); gccProbe(settings, profiles, QStringLiteral("clang")); iarProbe(settings, profiles); keilProbe(settings, profiles); sdccProbe(settings, profiles); cosmicProbe(settings, profiles); dmcProbe(settings, profiles); watcomProbe(settings, profiles); emscriptenProbe(settings, profiles); if (profiles.empty()) { qStderr << Tr::tr("Could not detect any toolchains. No profile created.") << Qt::endl; } else if (profiles.size() == 1 && settings->defaultProfile().isEmpty()) { const QString profileName = profiles.front().name(); qStdout << Tr::tr("Making profile '%1' the default.").arg(profileName) << Qt::endl; settings->setValue(QStringLiteral("defaultProfile"), profileName); } } void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, Settings *settings) { QFileInfo compiler(compilerFilePath); if (compilerFilePath == compiler.fileName() && !compiler.exists()) compiler = QFileInfo(findExecutable(compilerFilePath)); if (!compiler.exists()) { throw qbs::ErrorInfo(Tr::tr("Compiler '%1' not found") .arg(compilerFilePath)); } const QString realToolchainType = !toolchainType.isEmpty() ? toolchainType : toolchainTypeFromCompilerName(compiler.fileName()); const QStringList toolchain = canonicalToolchain(realToolchainType); if (toolchain.contains(QLatin1String("clang-cl"))) createClangClProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("msvc"))) createMsvcProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("emscripten"))) createEmscriptenProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("gcc"))) createGccProfile(compiler, settings, realToolchainType, profileName); else if (toolchain.contains(QLatin1String("iar"))) createIarProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("keil"))) createKeilProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("sdcc"))) createSdccProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("cosmic"))) createCosmicProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("dmc"))) createDmcProfile(compiler, settings, profileName); else if (toolchain.contains(QLatin1String("watcom"))) createWatcomProfile(compiler, settings, profileName); else throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type.")); } int extractVersion(const QByteArray ¯oDump, const QByteArray &keyToken) { const int startIndex = macroDump.indexOf(keyToken); if (startIndex == -1) return -1; const int endIndex = macroDump.indexOf('\n', startIndex); if (endIndex == -1) return -1; const auto keyLength = keyToken.length(); const int version = macroDump.mid(startIndex + keyLength, endIndex - startIndex - keyLength) .toInt(); return version; } static QString resolveSymlinks(const QString &filePath) { QFileInfo fi(filePath); int links = 16; while (links-- && fi.isSymLink()) fi.setFile(fi.dir(), fi.symLinkTarget()); if (links <= 0) return {}; return fi.filePath(); } // Copied from qfilesystemengine_win.cpp. #ifdef Q_OS_WIN // File ID for Windows up to version 7. static inline QByteArray fileIdWin7(HANDLE handle) { BY_HANDLE_FILE_INFORMATION info; if (GetFileInformationByHandle(handle, &info)) { char buffer[sizeof "01234567:0123456701234567\0"]; std::snprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx", info.dwVolumeSerialNumber, info.nFileIndexHigh, info.nFileIndexLow); return QByteArray(buffer); } return {}; } // File ID for Windows starting from version 8. static QByteArray fileIdWin8(HANDLE handle) { QByteArray result; FILE_ID_INFO infoEx = {}; if (::GetFileInformationByHandleEx( handle, static_cast(18), // FileIdInfo in Windows 8 &infoEx, sizeof(FILE_ID_INFO))) { result = QByteArray::number(infoEx.VolumeSerialNumber, 16); result += ':'; // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one. result += QByteArray(reinterpret_cast(&infoEx.FileId), int(sizeof(infoEx.FileId))).toHex(); } return result; } static QByteArray fileIdWin(HANDLE fHandle) { return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? fileIdWin8(HANDLE(fHandle)) : fileIdWin7(HANDLE(fHandle)); } static QByteArray fileId(const QString &filePath) { QByteArray result; const HANDLE handle = ::CreateFile( reinterpret_cast(filePath.utf16()), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (handle != INVALID_HANDLE_VALUE) { result = fileIdWin(handle); ::CloseHandle(handle); } return result; } static qint64 fileSize(const QString &filePath) { return QFileInfo(filePath).size(); } #else static QByteArray fileId(const QString &filePath) { QByteArray result; if (Q_UNLIKELY(filePath.isEmpty())) return {}; QT_STATBUF statResult = {}; if (QT_STAT(filePath.toLocal8Bit().constData(), &statResult)) return {}; result = QByteArray::number(quint64(statResult.st_dev), 16); result += ':'; result += QByteArray::number(quint64(statResult.st_ino)); return result; } #endif // Q_OS_WIN bool isSameExecutable(const QString &filePath1, const QString &filePath2) { if (filePath1 == filePath2) return true; if (resolveSymlinks(filePath1) == resolveSymlinks(filePath2)) return true; if (fileId(filePath1) == fileId(filePath2)) return true; #ifdef Q_OS_WIN if (fileSize(filePath1) == fileSize(filePath2)) return true; #endif return false; } MacrosMap dumpMacros(const std::function &func) { MacrosMap macros; const QStringList lines = func(); for (const QString &line : lines) { const QString prefix = QLatin1String("#define "); if (!line.startsWith(prefix)) return macros; const auto index = line.indexOf(QLatin1String(" "), prefix.length()); if (index != -1) { const auto key = line.mid(prefix.length(), index - prefix.length()); const auto value = line.mid(index + 1); macros.insert(key, value); } } return macros; } qbs-src-3.3.1/src/app/qbs-setup-toolchains/clangclprobe.h0000644000175100017510000000450415232633614022745 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H #define QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H #include #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } void createClangClProfile(const QFileInfo &compiler, qbs::Settings *settings, const QString &profileName); void clangClProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/clangclprobe.cpp0000644000175100017510000001224115232633614023275 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "clangclprobe.h" #include "msvcprobe.h" #include "probe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include using qbs::Settings; using qbs::Profile; using qbs::Internal::ClangClInfo; using qbs::Internal::HostOsInfo; using qbs::Internal::Tr; namespace { Profile createProfileHelper( Settings *settings, const QString &profileName, const QString &toolchainInstallPath, const QString &vcvarsallPath, const QString &architecture) { Profile profile(profileName, settings); profile.removeProfile(); profile.setValue(QStringLiteral("qbs.architecture"), architecture); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("clang-cl")); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), toolchainInstallPath); profile.setValue(QStringLiteral("cpp.vcvarsallPath"), vcvarsallPath); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profile.name(), QDir::toNativeSeparators(toolchainInstallPath)); return profile; } QString findClangCl() { const auto compilerName = HostOsInfo::appendExecutableSuffix(QStringLiteral("clang-cl")); auto compilerFromPath = findExecutable(compilerName); if (!compilerFromPath.isEmpty()) return compilerFromPath; return {}; } } // namespace void createClangClProfile(const QFileInfo &compiler, Settings *settings, const QString &profileName) { const auto clangCl = ClangClInfo::fromCompilerFilePath( compiler.filePath(), ConsoleLogger::instance()); if (clangCl.isEmpty()) return; const auto hostArch = HostOsInfo::hostOSArchitecture(); createProfileHelper( settings, profileName, clangCl.toolchainInstallPath, clangCl.vcvarsallPath, hostArch); } /*! \brief Creates a clang-cl profile based on auto-detected vsversion. \internal */ void clangClProbe(Settings *settings, std::vector &profiles) { const auto compilerName = QStringLiteral("clang-cl"); qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName); const auto clangCls = ClangClInfo::installedCompilers( {findClangCl()}, ConsoleLogger::instance()); if (clangCls.empty()) { qbsInfo() << Tr::tr("%1 was not found.").arg(compilerName); return; } const QString architectures[] = { QStringLiteral("x86_64"), QStringLiteral("x86") }; for (size_t index = 0; index < clangCls.size(); ++index) { const auto &clangCl = clangCls[index]; const QString suffix = index == 0 ? QString() : QStringLiteral("-%1").arg(index); qbs::Internal::transform( architectures, profiles, [settings, clangCl, suffix](const auto &arch) { const auto profileName = QStringLiteral("clang-cl%1-%2").arg(suffix, arch); return createProfileHelper( settings, profileName, clangCl.toolchainInstallPath, clangCl.vcvarsallPath, arch); }); } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/cosmicprobe.h0000644000175100017510000000455115232633614022621 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COSMICPROBE_H #define QBS_SETUPTOOLCHAINS_COSMICPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } bool isCosmicCompiler(const QString &compilerName); void createCosmicProfile(const QFileInfo &compiler, qbs::Settings *settings, QString profileName); void cosmicProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/sdccprobe.cpp0000644000175100017510000002521215232633614022610 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "sdccprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; using Internal::HostOsInfo; static QStringList knownSdccCompilerNames() { return {QStringLiteral("sdcc")}; } static QStringList dumpOutput(const QFileInfo &compiler, const QString &targetFlag = QString()) { QTemporaryFile fakeIn(QStringLiteral("XXXXXX.c")); if (!fakeIn.open()) { qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") .arg(fakeIn.fileName(), fakeIn.errorString()); return {}; } fakeIn.close(); const QStringList args = {QStringLiteral("-dM"), QStringLiteral("-E"), targetFlag, fakeIn.fileName()}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const auto es = p.exitStatus(); if (es != QProcess::NormalExit) { const QByteArray out = p.readAll(); qbsWarning() << Tr::tr("Compiler dumping failed:\n%1").arg(QString::fromUtf8(out)); return {}; } static QRegularExpression re(QStringLiteral("\\r?\\n")); return QString::fromUtf8(p.readAllStandardOutput()).split(re); } static bool supportsSdccArchitecture(const QFileInfo &compiler, QStringView flag) { const auto target = QStringLiteral("-m%1").arg(flag); const auto macros = dumpMacros([&compiler, &target]() { return dumpOutput(compiler, target); }); const auto token = QStringLiteral("__SDCC_%1").arg(flag); return macros.contains(token); } static std::vector createSdccProfileHelper(const ToolchainInstallInfo &info, Settings *settings, const QString &profileName = QString()) { const QFileInfo compiler = info.compilerPath; std::vector profiles; static constexpr struct KnownArch { QStringView architecture; QStringView flag; } knownArchs[] = {{u"mcs51", u"mcs51"}, {u"stm8", u"stm8"}, {u"hcs8", u"hc08"}}; for (const auto &knownArch : knownArchs) { // Don't create a profile in case the compiler does // not support the proposed architecture. if (!supportsSdccArchitecture(compiler, knownArch.flag)) continue; QString fullProfileName; if (profileName.isEmpty()) { // Create a full profile name in case we is // in auto-detecting mode. if (!info.compilerVersion.isValid()) { fullProfileName = QStringLiteral("sdcc-unknown-%1").arg(knownArch.architecture); } else { const QString version = info.compilerVersion.toString( QLatin1Char('_'), QLatin1Char('_')); fullProfileName = QStringLiteral("sdcc-%1-%2").arg( version, knownArch.architecture); } } else { // Append the detected actual architecture name // to the proposed profile name. fullProfileName = QStringLiteral("%1-%2").arg(profileName, knownArch.architecture); } Profile profile(fullProfileName, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("sdcc")); profile.setValue(QStringLiteral("qbs.architecture"), knownArch.architecture.toString()); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()); profiles.push_back(std::move(profile)); } return profiles; } static Version dumpSdccVersion(const QFileInfo &compiler) { const auto macros = dumpMacros([&compiler]() { return dumpOutput(compiler); }); if (!macros.contains(QLatin1String("__SDCC"))) { qbsWarning() << Tr::tr("No __SDCC token was found in the compiler dump"); return Version{}; } auto value = macros.value(QLatin1String("__SDCC")); value.replace(QLatin1Char('_'), QLatin1Char('.')); return Version::fromString(value); } static std::vector installedSdccsFromPath() { std::vector infos; const auto compilerNames = knownSdccCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo sdccPath( findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!sdccPath.exists()) continue; const Version version = dumpSdccVersion(sdccPath); infos.push_back({sdccPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } static std::vector installedSdccsFromRegistry() { std::vector infos; if (HostOsInfo::isWindowsHost()) { // Tries to detect the candidate from the 32-bit // or 64-bit system registry format. auto probeSdccToolchainInfo = [](QSettings::Format format) { SdccInstallInfo info; QSettings registry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\SDCC"), format); const QString rootPath = registry.value(QStringLiteral("Default")) .toString(); if (rootPath.isEmpty()) return info; // Build full compiler path. const QFileInfo sdccPath(rootPath + QLatin1String("\\bin\\sdcc.exe")); if (!sdccPath.exists()) return info; info.compilerPath = sdccPath.filePath(); // Build compiler version. const QString version = QStringLiteral("%1.%2.%3").arg( registry.value(QStringLiteral("VersionMajor")).toString(), registry.value(QStringLiteral("VersionMinor")).toString(), registry.value(QStringLiteral("VersionRevision")).toString()); info.version = version; return info; }; static constexpr QSettings::Format allowedFormats[] = { QSettings::NativeFormat, #ifdef Q_OS_WIN QSettings::Registry32Format, QSettings::Registry64Format, #endif }; for (const QSettings::Format format : allowedFormats) { const SdccInstallInfo candidate = probeSdccToolchainInfo(format); if (candidate.compilerPath.isEmpty()) continue; const auto infosEnd = infos.cend(); const auto infosIt = std::find_if(infos.cbegin(), infosEnd, [candidate](const ToolchainInstallInfo &info) { return candidate == SdccInstallInfo{ info.compilerPath.filePath(), info.compilerVersion.toString()}; }); if (infosIt == infosEnd) { infos.push_back({QFileInfo(candidate.compilerPath), Version::fromString(candidate.version)}); } } } std::sort(infos.begin(), infos.end()); return infos; } bool isSdccCompiler(const QString &compilerName) { return Internal::any_of(knownSdccCompilerNames(), [compilerName]( const QString &knownName) { return compilerName.contains(knownName); }); } void createSdccProfile(const QFileInfo &compiler, Settings *settings, const QString &profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createSdccProfileHelper(info, settings, profileName); } void sdccProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect SDCC toolchains..."); // Make sure that a returned infos are sorted before using the std::set_union! const std::vector regInfos = installedSdccsFromRegistry(); const std::vector pathInfos = installedSdccsFromPath(); std::vector allInfos; allInfos.reserve(regInfos.size() + pathInfos.size()); std::set_union(regInfos.cbegin(), regInfos.cend(), pathInfos.cbegin(), pathInfos.cend(), std::back_inserter(allInfos)); if (allInfos.empty()) qbsInfo() << Tr::tr("No SDCC toolchains found."); for (const ToolchainInstallInfo &info : allInfos) { const auto newProfiles = createSdccProfileHelper(info, settings); profiles.reserve(profiles.size() + int(newProfiles.size())); std::copy(newProfiles.cbegin(), newProfiles.cend(), std::back_inserter(profiles)); } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/msvcprobe.cpp0000644000175100017510000002117715232633614022652 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "msvcprobe.h" #include "probe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; using Internal::Tr; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(WinSDK, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(MSVC, Q_MOVABLE_TYPE); QT_END_NAMESPACE // Not necessary but helps setup-qt automatically associate base profiles static void setQtHelperProperties(Profile &p, const MSVC *msvc) { QString targetArch = msvc->architecture.split(QLatin1Char('_')).last(); if (targetArch.isEmpty()) targetArch = QStringLiteral("x86"); if (targetArch == QStringLiteral("arm")) targetArch = QStringLiteral("armv7"); p.setValue(QStringLiteral("qbs.architecture"), canonicalArchitecture(targetArch)); } static void addMSVCPlatform(Settings *settings, std::vector &profiles, QString name, MSVC *msvc) { qbsInfo() << Tr::tr("Setting up profile '%1'.").arg(name); Profile p(std::move(name), settings); p.removeProfile(); p.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows")); p.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("msvc")); p.setValue(QStringLiteral("cpp.toolchainInstallPath"), msvc->binPath); setQtHelperProperties(p, msvc); profiles.push_back(p); } static QString wow6432Key() { #ifdef Q_OS_WIN64 return QStringLiteral("\\Wow6432Node"); #else return {}; #endif } void msvcProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Detecting MSVC toolchains..."); // 1) Installed SDKs preferred over standalone Visual studio std::vector winSDKs; WinSDK defaultWinSDK; const QSettings sdkRegistry(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QLatin1String("\\Microsoft\\Microsoft SDKs\\Windows"), QSettings::NativeFormat); const QString defaultSdkPath = sdkRegistry.value(QStringLiteral("CurrentInstallFolder")).toString(); if (!defaultSdkPath.isEmpty()) { const auto sdkKeys = sdkRegistry.childGroups(); for (const QString &sdkKey : sdkKeys) { WinSDK sdk; sdk.version = sdkKey; sdk.vcInstallPath = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder")).toString(); sdk.isDefault = (sdk.vcInstallPath == defaultSdkPath); if (sdk.vcInstallPath.isEmpty()) continue; if (sdk.vcInstallPath.endsWith(QLatin1Char('\\'))) sdk.vcInstallPath.chop(1); if (sdk.isDefault) defaultWinSDK = sdk; const auto ais = MSVC::findSupportedArchitectures(sdk); qbs::Internal::transform(ais, winSDKs, [&sdk](const auto &ai) { WinSDK specificSDK = sdk; specificSDK.architecture = ai.arch; specificSDK.binPath = ai.binPath; return specificSDK; }); } } for (const WinSDK &sdk : std::as_const(winSDKs)) { qbsInfo() << Tr::tr(" Windows SDK %1 detected:\n" " installed in %2").arg(sdk.version, sdk.vcInstallPath); if (sdk.isDefault) qbsInfo() << Tr::tr(" This is the default SDK on this machine."); } // 2) Installed MSVCs std::vector msvcs = MSVC::installedCompilers(ConsoleLogger::instance()); for (const MSVC &msvc : std::as_const(msvcs)) { qbsInfo() << Tr::tr(" MSVC %1 (%2) detected in\n" " %3").arg(msvc.version, msvc.architecture, QDir::toNativeSeparators(msvc.binPath)); } if (winSDKs.empty() && msvcs.empty()) { qbsInfo() << Tr::tr("Could not detect an installation of " "the Windows SDK or Visual Studio."); return; } qbsInfo() << Tr::tr("Detecting build environment..."); std::vector msvcPtrs; msvcPtrs.reserve(winSDKs.size() + msvcs.size()); std::transform(winSDKs.begin(), winSDKs.end(), std::back_inserter(msvcPtrs), [] (WinSDK &sdk) -> MSVC * { return &sdk; }); std::transform(msvcs.begin(), msvcs.end(), std::back_inserter(msvcPtrs), [] (MSVC &msvc) -> MSVC * { return &msvc; }); for (WinSDK &sdk : winSDKs) { const QString name = QLatin1String("WinSDK") + sdk.version + QLatin1Char('-') + sdk.architecture; try { addMSVCPlatform(settings, profiles, name, &sdk); } catch (const ErrorInfo &error) { qbsWarning() << Tr::tr("Failed to set up %1: %2").arg(name, error.toString()); } } // we want the same MSVC version share the same suffix in profiles, thus use // a set to know the number of versions processed so far std::map> msvcCounters; for (MSVC &msvc : msvcs) { // each VS needs its own counter auto &msvcVersions = msvcCounters[msvc.version]; // vcInstallPath is "Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.16.27023/bin" // Since msvcs are sorted by version, when the new vcInstallPath is inserted, we start // a new group of compilers of the same version incrementing the set size msvcVersions.insert(msvc.vcInstallPath); // index is the number of specific vcInstallPaths (e.g. compiler versions) seen so far const size_t index = msvcVersions.size() - 1; const QString suffix = index == 0 ? QString() : QStringLiteral("-%1").arg(index); const QString name = QLatin1String("MSVC") + msvc.version + suffix + QLatin1Char('-') + msvc.architecture; try { addMSVCPlatform(settings, profiles, name, &msvc); } catch (const ErrorInfo &error) { qbsWarning() << Tr::tr("Failed to set up %1: %2").arg(name, error.toString()); } } } void createMsvcProfile(const QFileInfo &compiler, Settings *settings, const QString &profileName) { const auto compilerFilePath = compiler.absoluteFilePath(); MSVC msvc(compilerFilePath, MSVC::architectureFromClPath(compilerFilePath)); msvc.init(); std::vector dummy; addMSVCPlatform(settings, dummy, profileName, &msvc); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profileName, QDir::toNativeSeparators(compilerFilePath)); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/probe.h0000644000175100017510000000746715232633614021434 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_PROBE_H #define QBS_SETUPTOOLCHAINS_PROBE_H #include #include #include #include #include #include // for std::function #include // for std::tie namespace qbs { class Settings; } QStringList systemSearchPaths(); QString findExecutable(const QString &fileName); QString toolchainTypeFromCompilerName(const QString &compilerName); void createProfile( const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, qbs::Settings *settings); void probe(qbs::Settings *settings); struct ToolchainInstallInfo { QFileInfo compilerPath; qbs::Version compilerVersion; }; inline bool operator==(const ToolchainInstallInfo &lhs, const ToolchainInstallInfo &rhs) { const auto lp = lhs.compilerPath.absoluteFilePath(); const auto rp = rhs.compilerPath.absoluteFilePath(); return std::tie(lp, lhs.compilerVersion) == std::tie(rp, rhs.compilerVersion); } inline bool operator<(const ToolchainInstallInfo &lhs, const ToolchainInstallInfo &rhs) { const auto lp = lhs.compilerPath.absoluteFilePath(); const auto rp = rhs.compilerPath.absoluteFilePath(); return std::tie(lp, lhs.compilerVersion) < std::tie(rp, rhs.compilerVersion); } int extractVersion(const QByteArray ¯oDump, const QByteArray &keyToken); bool isSameExecutable(const QString &exe1, const QString &exe2); using MacrosMap = QMap; MacrosMap dumpMacros(const std::function &func); namespace std { template<> struct hash { std::size_t operator()(const ToolchainInstallInfo &v) const noexcept { std::size_t seed = 0; qbs::Internal::hashCombineHelper(seed, v.compilerPath.absoluteFilePath()); qbs::Internal::hashCombineHelper(seed, v.compilerVersion); return seed; } }; } // namespace std #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/emscriptenprobe.h0000644000175100017510000000466715232633614023525 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Danya Patrushev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_EMSCRIPTENPROBE_H #define QBS_SETUPTOOLCHAINS_EMSCRIPTENPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; class QString; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } // namespace qbs bool isEmscriptenCompiler(const QString &compilerName); qbs::Profile createEmscriptenProfile( const QFileInfo &compiler, qbs::Settings *settings, const QString &profileName = QString()); void emscriptenProbe(qbs::Settings *settings, std::vector &profiles); #endif // QBS_SETUPTOOLCHAINS_EMSCRIPTENPROBE_H qbs-src-3.3.1/src/app/qbs-setup-toolchains/emscriptenprobe.cpp0000644000175100017510000000767315232633614024060 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2023 Danya Patrushev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "emscriptenprobe.h" #include "../shared/logging/consolelogger.h" #include "probe.h" #include #include #include #include #include #include #include #include using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; namespace { qbs::Profile writeProfile( const QString &profileName, const QFileInfo &compiler, qbs::Settings *settings) { qbs::Profile profile(profileName, settings); profile.setValue(QStringLiteral("qbs.architecture"), QStringLiteral("wasm")); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("emscripten")); profile.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("wasm-emscripten")); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); return profile; } } //namespace bool isEmscriptenCompiler(const QString &compilerName) { return compilerName.startsWith(QLatin1String("emcc")) || compilerName.startsWith(QLatin1String("em++")); } qbs::Profile createEmscriptenProfile( const QFileInfo &compiler, qbs::Settings *settings, const QString &profileName) { qbs::Profile profile = writeProfile(profileName, compiler, settings); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profile.name(), compiler.absoluteFilePath()); return profile; } void emscriptenProbe(qbs::Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect emscripten toolchain..."); const QString emcc = HostOsInfo::isWindowsHost() ? QStringLiteral("emcc.bat") : QStringLiteral("emcc"); const QString compilerPath = findExecutable(emcc); if (compilerPath.isEmpty()) { qbsInfo() << Tr::tr("No emscripten toolchain found."); return; } const qbs::Profile profile = createEmscriptenProfile( QFileInfo(compilerPath), settings, QLatin1String("wasm")); profiles.push_back(profile); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/commandlineparser.h0000644000175100017510000000607515232633614024022 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString compilerPath() const { return m_compilerPath; } QString toolchainType() const { return m_toolchainType; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested = false; bool m_autoDetectionMode = false; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_compilerPath; QString m_toolchainType; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/main.cpp0000644000175100017510000000571715232633614021600 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "probe.h" #include #include #include #include #include #include using qbs::Settings; static void printUsage(const QString &usageString) { std::cout << qPrintable(usageString) << std::endl; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { printUsage(clParser.usageString()); return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); settings.setScopeForWriting(clParser.settingsScope()); if (clParser.autoDetectionMode()) { probe(&settings); return EXIT_SUCCESS; } createProfile(clParser.profileName(), clParser.toolchainType(), clParser.compilerPath(), &settings); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/gccprobe.h0000644000175100017510000000466715232633614022110 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_GCCPROBE_H #define QBS_SETUPTOOLCHAINS_GCCPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } qbs::Profile createGccProfile(const QFileInfo &compiler, qbs::Settings *settings, const QString &toolchainType, const QString &profileName = QString()); void gccProbe(qbs::Settings *settings, std::vector &profiles, const QString &compilerName); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/keilprobe.h0000644000175100017510000000453515232633614022272 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_KEILPROBE_H #define QBS_SETUPTOOLCHAINS_KEILPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } bool isKeilCompiler(const QString &compilerName); void createKeilProfile(const QFileInfo &compiler, qbs::Settings *settings, QString profileName); void keilProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/iarewprobe.h0000644000175100017510000000453315232633614022453 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_IAREWPROBE_H #define QBS_SETUPTOOLCHAINS_IAREWPROBE_H #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } bool isIarCompiler(const QString &compilerName); void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings, QString profileName); void iarProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/iarewprobe.cpp0000644000175100017510000003347515232633614023015 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "iarewprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include using namespace qbs; using Internal::Tr; using Internal::HostOsInfo; static QStringList knownIarCompilerNames() { return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), QStringLiteral("iccavr"), QStringLiteral("iccstm8"), QStringLiteral("icc430"), QStringLiteral("iccrl78"), QStringLiteral("iccrx"), QStringLiteral("iccrh850"), QStringLiteral("iccv850"), QStringLiteral("icc78k"), QStringLiteral("iccavr32"), QStringLiteral("iccsh"), QStringLiteral("iccriscv"), QStringLiteral("icccf"), QStringLiteral("iccm32c"), QStringLiteral("iccr32c"), QStringLiteral("iccm16c"), QStringLiteral("icccr16c"), QStringLiteral("icchcs12"), QStringLiteral("iccs08")}; } static QString guessIarArchitecture(const QFileInfo &compiler) { const auto baseName = compiler.baseName(); if (baseName == QLatin1String("icc8051")) return QStringLiteral("mcs51"); if (baseName == QLatin1String("iccarm")) return QStringLiteral("arm"); if (baseName == QLatin1String("iccavr")) return QStringLiteral("avr"); if (baseName == QLatin1String("iccstm8")) return QStringLiteral("stm8"); if (baseName == QLatin1String("icc430")) return QStringLiteral("msp430"); if (baseName == QLatin1String("iccrl78")) return QStringLiteral("rl78"); if (baseName == QLatin1String("iccrx")) return QStringLiteral("rx"); if (baseName == QLatin1String("iccrh850")) return QStringLiteral("rh850"); if (baseName == QLatin1String("iccv850")) return QStringLiteral("v850"); if (baseName == QLatin1String("icc78k")) return QStringLiteral("78k"); if (baseName == QLatin1String("iccavr32")) return QStringLiteral("avr32"); if (baseName == QLatin1String("iccsh")) return QStringLiteral("sh"); if (baseName == QLatin1String("iccriscv")) return QStringLiteral("riscv"); if (baseName == QLatin1String("icccf")) return QStringLiteral("m68k"); if (baseName == QLatin1String("iccm32c")) return QStringLiteral("m32c"); if (baseName == QLatin1String("iccr32c")) return QStringLiteral("r32c"); if (baseName == QLatin1String("iccm16c")) return QStringLiteral("m16c"); if (baseName == QLatin1String("icccr16c")) return QStringLiteral("cr16"); if (baseName == QLatin1String("icchcs12")) return QStringLiteral("hcs12"); if (baseName == QLatin1String("iccs08")) return QStringLiteral("hcs8"); return {}; } static Profile createIarProfileHelper(const ToolchainInstallInfo &info, Settings *settings, QString profileName = QString()) { const QFileInfo compiler = info.compilerPath; const QString architecture = guessIarArchitecture(compiler); // In case the profile is auto-detected. if (profileName.isEmpty()) { if (!info.compilerVersion.isValid()) { profileName = QStringLiteral("iar-unknown-%1").arg(architecture); } else { const QString version = info.compilerVersion.toString(QLatin1Char('_'), QLatin1Char('_')); profileName = QStringLiteral("iar-%1-%2").arg( version, architecture); } } Profile profile(profileName, settings); profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QLatin1String("qbs.toolchainType"), QLatin1String("iar")); if (!architecture.isEmpty()) profile.setValue(QLatin1String("qbs.architecture"), architecture); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()); return profile; } static Version dumpIarCompilerVersion(const QFileInfo &compiler) { const QString outFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + QLatin1String("/macros.dump"); const QStringList args = {QStringLiteral("."), QStringLiteral("--predef_macros"), outFilePath}; QProcess p; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const auto es = p.exitStatus(); if (es != QProcess::NormalExit) { const QByteArray out = p.readAll(); qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") .arg(QString::fromUtf8(out)); return Version{}; } QByteArray dump; QFile out(outFilePath); if (out.open(QIODevice::ReadOnly)) dump = out.readAll(); out.remove(); const int verCode = extractVersion(dump, "__VER__ "); if (verCode < 0) { qbsWarning() << Tr::tr("No '__VER__' token was found in a compiler dump:\n%1") .arg(QString::fromUtf8(dump)); return Version{}; } const QString arch = guessIarArchitecture(compiler); if (arch == QLatin1String("arm")) return Version{verCode / 1000000, (verCode / 1000) % 1000, verCode % 1000}; if (arch == QLatin1String("avr") || arch == QLatin1String("mcs51") || arch == QLatin1String("stm8") || arch == QLatin1String("msp430") || arch == QLatin1String("rl78") || arch == QLatin1String("rx") || arch == QLatin1String("rh850") || arch == QLatin1String("v850") || arch == QLatin1String("78k") || arch == QLatin1String("avr32") || arch == QLatin1String("sh") || arch == QLatin1String("riscv") || arch == QLatin1String("m68k") || arch == QLatin1String("m32c") || arch == QLatin1String("r32c") || arch == QLatin1String("m16c") || arch == QLatin1String("rc16") || arch == QLatin1String("hcs12") || arch == QLatin1String("hcs8")) { return Version{verCode / 100, verCode % 100}; } return Version{}; } static std::vector installedIarsFromPath() { std::vector infos; const auto compilerNames = knownIarCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo iarPath( findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!iarPath.exists()) continue; const Version version = dumpIarCompilerVersion(iarPath); infos.push_back({iarPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } static std::vector installedIarsFromRegistry() { std::vector infos; if (HostOsInfo::isWindowsHost()) { #ifdef Q_OS_WIN64 static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\IAR Systems\\Embedded Workbench"; #else static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\IAR Systems\\Embedded Workbench"; #endif // Dictionary for know toolchains. static const struct Entry { QString registryKey; QString subExePath; } knowToolchains[] = { {QStringLiteral("EWARM"), QStringLiteral("/arm/bin/iccarm.exe")}, {QStringLiteral("EWAVR"), QStringLiteral("/avr/bin/iccavr.exe")}, {QStringLiteral("EW8051"), QStringLiteral("/8051/bin/icc8051.exe")}, {QStringLiteral("EWSTM8"), QStringLiteral("/stm8/bin/iccstm8.exe")}, {QStringLiteral("EW430"), QStringLiteral("/430/bin/icc430.exe")}, {QStringLiteral("EWRL78"), QStringLiteral("/rl78/bin/iccrl78.exe")}, {QStringLiteral("EWRX"), QStringLiteral("/rx/bin/iccrx.exe")}, {QStringLiteral("EWRH850"), QStringLiteral("/rh850/bin/iccrh850.exe")}, {QStringLiteral("EWV850"), QStringLiteral("/v850/bin/iccv850.exe")}, {QStringLiteral("EW78K"), QStringLiteral("/78k/bin/icc78k.exe")}, {QStringLiteral("EWAVR32"), QStringLiteral("/avr32/bin/iccavr32.exe")}, {QStringLiteral("EWSH"), QStringLiteral("/sh/bin/iccsh.exe")}, {QStringLiteral("EWRISCV"), QStringLiteral("/riscv/bin/iccriscv.exe")}, {QStringLiteral("EWCF"), QStringLiteral("/cf/bin/icccf.exe")}, {QStringLiteral("EWM32C"), QStringLiteral("/m32c/bin/iccm32c.exe")}, {QStringLiteral("EWR32C"), QStringLiteral("/r32c/bin/iccr32c.exe")}, {QStringLiteral("EWM16C"), QStringLiteral("/m16c/bin/iccm16c.exe")}, {QStringLiteral("EWCR16C"), QStringLiteral("/cr16c/bin/icccr16c.exe")}, {QStringLiteral("EWHCS12"), QStringLiteral("/hcs12/bin/icchcs12.exe")}, {QStringLiteral("EWS08"), QStringLiteral("/s08/bin/iccs08.exe")}, }; QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat); const auto oneLevelGroups = registry.childGroups(); for (const QString &oneLevelKey : oneLevelGroups) { registry.beginGroup(oneLevelKey); const auto twoLevelGroups = registry.childGroups(); for (const Entry &entry : knowToolchains) { if (twoLevelGroups.contains(entry.registryKey)) { registry.beginGroup(entry.registryKey); const auto threeLevelGroups = registry.childGroups(); for (const QString &threeLevelKey : threeLevelGroups) { registry.beginGroup(threeLevelKey); const QString rootPath = registry.value( QStringLiteral("InstallPath")).toString(); if (!rootPath.isEmpty()) { // Build full compiler path. const QFileInfo iarPath(rootPath + entry.subExePath); if (iarPath.exists()) { // Note: threeLevelKey is a guessed toolchain version. infos.push_back({iarPath, Version::fromString(threeLevelKey, true)}); } } registry.endGroup(); } registry.endGroup(); } } registry.endGroup(); } } std::sort(infos.begin(), infos.end()); return infos; } bool isIarCompiler(const QString &compilerName) { return Internal::any_of(knownIarCompilerNames(), [compilerName]( const QString &knownName) { return compilerName.contains(knownName); }); } void createIarProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createIarProfileHelper(info, settings, std::move(profileName)); } void iarProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect IAR toolchains..."); // Make sure that a returned infos are sorted before using the std::set_union! const std::vector regInfos = installedIarsFromRegistry(); const std::vector pathInfos = installedIarsFromPath(); std::vector allInfos; allInfos.reserve(regInfos.size() + pathInfos.size()); std::set_union(regInfos.cbegin(), regInfos.cend(), pathInfos.cbegin(), pathInfos.cend(), std::back_inserter(allInfos)); qbs::Internal::transform(allInfos, profiles, [settings](const auto &info) { return createIarProfileHelper(info, settings); }); if (allInfos.empty()) qbsInfo() << Tr::tr("No IAR toolchains found."); } qbs-src-3.3.1/src/app/qbs-setup-toolchains/gccprobe.cpp0000644000175100017510000005547715232633614022450 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "gccprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; constexpr char kUninstallRegistryKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \ "Windows\\CurrentVersion\\Uninstall\\"; static QString qsystem(const QString &exe, const QStringList &args = QStringList()) { QProcess p; p.setProcessChannelMode(QProcess::MergedChannels); p.start(exe, args); if (!p.waitForStarted()) { throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2") .arg(exe, p.errorString())); } if (!p.waitForFinished(-1) || p.exitCode() != 0) throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2") .arg(exe, p.errorString())); return QString::fromLocal8Bit(p.readAll()); } static QStringList validMinGWMachines() { // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs return {QStringLiteral("mingw32"), QStringLiteral("mingw64"), QStringLiteral("i686-w64-mingw32"), QStringLiteral("x86_64-w64-mingw32"), QStringLiteral("i686-w64-mingw32.shared"), QStringLiteral("x86_64-w64-mingw32.shared"), QStringLiteral("i686-w64-mingw32.static"), QStringLiteral("x86_64-w64-mingw32.static"), QStringLiteral("i586-mingw32msvc"), QStringLiteral("amd64-mingw32msvc")}; } static QString gccMachineName(const QFileInfo &compiler) { return qsystem(compiler.absoluteFilePath(), {QStringLiteral("-dumpmachine")}) .trimmed(); } static QStringList standardCompilerFileNames() { return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")), HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")), HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")), HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))}; } class ToolchainDetails { public: explicit ToolchainDetails(const QFileInfo &compiler) { auto baseName = HostOsInfo::stripExecutableSuffix(compiler.fileName()); // Extract the version sub-string if it exists. We assume that a version // sub-string located after the compiler prefix && suffix. E.g. this code // parses a version from the compiler names, like this: // - avr-gcc-4.9.2.exe // - arm-none-eabi-gcc-8.2.1 // - rl78-elf-gcc-4.9.2.201902-GNURL78 const QRegularExpression re(QLatin1String("-(\\d+|\\d+\\.\\d+|" \ "\\d+\\.\\d+\\.\\d+|" \ "\\d+\\.\\d+\\.\\d+\\.\\d+)" \ "[-[0-9a-zA-Z]*]?$")); const QRegularExpressionMatch match = re.match(baseName); if (match.hasMatch()) { version = match.captured(1); baseName = baseName.left(match.capturedStart()); } const auto dashIndex = baseName.lastIndexOf(QLatin1Char('-')); suffix = baseName.mid(dashIndex + 1); prefix = baseName.left(dashIndex + 1); } QString prefix; QString suffix; QString version; }; static void setCommonProperties(Profile &profile, const QFileInfo &compiler, const QString &toolchainType, const ToolchainDetails &details) { if (toolchainType == QStringLiteral("mingw")) profile.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows")); if (!details.prefix.isEmpty()) profile.setValue(QStringLiteral("cpp.toolchainPrefix"), details.prefix); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchainType"), toolchainType); if (!standardCompilerFileNames().contains( HostOsInfo::appendExecutableSuffix(details.suffix))) { qWarning("%s", qPrintable( QStringLiteral("'%1' is not a standard compiler file name; " "you must set the cpp.cCompilerName and " "cpp.cxxCompilerName properties of this profile " "manually").arg(compiler.fileName()))); } } class ToolPathSetup { public: explicit ToolPathSetup(Profile *profile, QString path, ToolchainDetails details) : m_profile(profile), m_compilerDirPath(std::move(path)), m_details(std::move(details)) { } void apply(const QString &toolName, const QString &propertyName) const { // Check for full tool name at first (includes suffix and version). QString filePath = toolFilePath(toolName, UseFullToolName); if (filePath.isEmpty()) { // Check for base tool name at second (without of suffix and version). filePath = toolFilePath(toolName, UseBaseToolName); if (filePath.isEmpty()) { // Check for short tool name at third (only a tool name). filePath = toolFilePath(toolName, UseOnlyShortToolName); } } if (filePath.isEmpty()) { qWarning("%s", qPrintable( QStringLiteral("'%1' not found in '%2'. " "Qbs will try to find it in PATH at build time.") .arg(toolName, m_compilerDirPath))); } else { m_profile->setValue(propertyName, filePath); } } private: enum ToolNameParts : quint8 { UseOnlyShortToolName = 0x0, UseToolPrefix = 0x01, UseToolSuffix = 0x02, UseToolVersion = 0x04, UseFullToolName = UseToolPrefix | UseToolSuffix | UseToolVersion, UseBaseToolName = UseToolPrefix, }; QString toolFilePath(const QString &toolName, int parts) const { QString fileName; if ((parts & UseToolPrefix) && !m_details.prefix.isEmpty()) fileName += m_details.prefix; if ((parts & UseToolSuffix) && !m_details.suffix.isEmpty()) fileName += m_details.suffix + QLatin1Char('-'); fileName += toolName; if ((parts & UseToolVersion) && !m_details.version.isEmpty()) fileName += QLatin1Char('-') + m_details.version; fileName = HostOsInfo::appendExecutableSuffix(fileName); QString filePath = QDir(m_compilerDirPath).absoluteFilePath(fileName); if (QFile::exists(filePath)) return filePath; return {}; } Profile * const m_profile; QString m_compilerDirPath; ToolchainDetails m_details; }; static bool doesProfileTargetOS(const Profile &profile, const QString &os) { const auto target = profile.value(QStringLiteral("qbs.targetPlatform")); if (target.isValid()) return Internal::contains(HostOsInfo::canonicalOSIdentifiers(target.toString()), os); return Internal::contains(HostOsInfo::hostOSIdentifiers(), os); } static QString buildProfileName(const QFileInfo &cfi) { // We need to replace a dot-separated compiler version string // with a underscore-separated string, because the profile // name does not allow a dots. auto result = cfi.completeBaseName(); result.replace(QLatin1Char('.'), QLatin1Char('_')); return result; } static QStringList buildCompilerNameFilters(const QString &compilerName) { QStringList filters = { // "clang", "gcc" compilerName, // "clang-8", "gcc-5" compilerName + QLatin1String("-[1-9]*"), // "avr-gcc" QLatin1String("*-") + compilerName, // "avr-gcc-5.4.0" QLatin1String("*-") + compilerName + QLatin1String("-[1-9]*"), // "arm-none-eabi-gcc" QLatin1String("*-*-*-") + compilerName, // "arm-none-eabi-gcc-9.1.0" QLatin1String("*-*-*-") + compilerName + QLatin1String("-[1-9]*"), // "x86_64-pc-linux-gnu-gcc" QLatin1String("*-*-*-*-") + compilerName, // "x86_64-pc-linux-gnu-gcc-7.4.1" QLatin1String("*-*-*-*-") + compilerName + QLatin1String("-[1-9]*") }; Internal::transform(filters, [](const auto &filter) { return HostOsInfo::appendExecutableSuffix(filter); }); return filters; } static QStringList gnuRegistrySearchPaths() { if (!HostOsInfo::isWindowsHost()) return {}; #ifdef Q_OS_WIN64 static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\ARM"; #else static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\ARM"; #endif QStringList searchPaths; QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat); const auto groupKeys = registry.childGroups(); for (const QString &groupKey : groupKeys) { registry.beginGroup(groupKey); const QString rootPath = registry.value(QStringLiteral("InstallFolder")).toString(); if (!rootPath.isEmpty()) { const QFileInfo toolchainPath(rootPath + QLatin1String("/bin")); if (toolchainPath.exists()) { const auto filePath = toolchainPath.absoluteFilePath(); if (!searchPaths.contains(filePath)) searchPaths.push_back(filePath); } } registry.endGroup(); } return searchPaths; } static QStringList atmelRegistrySearchPaths() { if (!HostOsInfo::isWindowsHost()) return {}; // Registry token for the "Atmel" toolchains, e.g. provided by installed // "Atmel Studio" IDE. static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Atmel\\"; QStringList searchPaths; QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat); // This code enumerate the installed toolchains provided // by the Atmel Studio v6.x. const auto toolchainGroups = registry.childGroups(); for (const QString &toolchainKey : toolchainGroups) { if (!toolchainKey.endsWith(QLatin1String("GCC"))) continue; registry.beginGroup(toolchainKey); const auto entries = registry.childGroups(); for (const auto &entryKey : entries) { registry.beginGroup(entryKey); const QString installDir = registry.value( QStringLiteral("Native/InstallDir")).toString(); const QString version = registry.value( QStringLiteral("Native/Version")).toString(); registry.endGroup(); QString toolchainPath = installDir + QLatin1String("/Atmel Toolchain/") + toolchainKey + QLatin1String("/Native/") + version; if (toolchainKey.startsWith(QLatin1String("ARM"))) toolchainPath += QLatin1String("/arm-gnu-toolchain"); else if (toolchainKey.startsWith(QLatin1String("AVR32"))) toolchainPath += QLatin1String("/avr32-gnu-toolchain"); else if (toolchainKey.startsWith(QLatin1String("AVR8)"))) toolchainPath += QLatin1String("/avr8-gnu-toolchain"); else break; toolchainPath += QLatin1String("/bin"); if (QFileInfo::exists(toolchainPath)) { searchPaths.push_back(toolchainPath); break; } } registry.endGroup(); } // This code enumerate the installed toolchains provided // by the Atmel Studio v7. registry.beginGroup(QStringLiteral("AtmelStudio")); const auto productVersions = registry.childGroups(); for (const auto &productVersionKey : productVersions) { registry.beginGroup(productVersionKey); const QString installDir = registry.value( QStringLiteral("InstallDir")).toString(); registry.endGroup(); const QStringList knownToolchainSubdirs = { QStringLiteral("/toolchain/arm/arm-gnu-toolchain/bin/"), QStringLiteral("/toolchain/avr8/avr8-gnu-toolchain/bin/"), QStringLiteral("/toolchain/avr32/avr32-gnu-toolchain/bin/"), }; for (const auto &subdir : knownToolchainSubdirs) { const QString toolchainPath = installDir + subdir; if (!QFileInfo::exists(toolchainPath)) continue; searchPaths.push_back(toolchainPath); } } registry.endGroup(); return searchPaths; } static QStringList renesasRl78RegistrySearchPaths() { if (!HostOsInfo::isWindowsHost()) return {}; QStringList searchPaths; QSettings registry(QLatin1String(kUninstallRegistryKey), QSettings::NativeFormat); const auto productGroups = registry.childGroups(); for (const QString &productKey : productGroups) { // Registry token for the "Renesas RL78" toolchain. if (!productKey.startsWith( QLatin1String("GCC for Renesas RL78"))) { continue; } registry.beginGroup(productKey); const QString installLocation = registry.value( QLatin1String("InstallLocation")).toString(); registry.endGroup(); if (installLocation.isEmpty()) continue; const QFileInfo toolchainPath(QDir(installLocation).absolutePath() + QLatin1String("/rl78-elf/rl78-elf/bin")); if (!toolchainPath.exists()) continue; searchPaths.push_back(toolchainPath.absoluteFilePath()); } return searchPaths; } static QStringList mplabX32RegistrySearchPaths() { if (!HostOsInfo::isWindowsHost()) return {}; QStringList searchPaths; QSettings registry(QLatin1String(kUninstallRegistryKey), QSettings::NativeFormat); const auto productGroups = registry.childGroups(); for (const QString &productKey : productGroups) { // Registry token for the "MPLAB X32" toolchain. if (!productKey.startsWith( QLatin1String("MPLAB XC32 Compiler"))) { continue; } registry.beginGroup(productKey); const QString installLocation = registry.value( QLatin1String("InstallLocation")).toString(); registry.endGroup(); if (installLocation.isEmpty()) continue; const QFileInfo toolchainPath(QDir(installLocation).absolutePath() + QLatin1String("/bin")); if (!toolchainPath.exists()) continue; searchPaths.push_back(toolchainPath.absoluteFilePath()); } return searchPaths; } Profile createGccProfile(const QFileInfo &compiler, Settings *settings, const QString &toolchainType, const QString &profileName) { const QString machineName = gccMachineName(compiler); if (toolchainType == QLatin1String("mingw")) { if (!validMinGWMachines().contains(machineName)) { throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") .arg(machineName)); } } Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); profile.removeProfile(); const ToolchainDetails details(compiler); setCommonProperties(profile, compiler, toolchainType, details); if (HostOsInfo::isWindowsHost() && toolchainType == QLatin1String("clang")) { const QStringList profileNames = settings->profiles(); bool foundMingw = false; for (const QString &profileName : profileNames) { const Profile otherProfile(profileName, settings); if (otherProfile.value(QLatin1String("qbs.toolchainType")).toString() == QLatin1String("mingw") || otherProfile.value(QLatin1String("qbs.toolchain")) .toStringList().contains(QLatin1String("mingw"))) { const QFileInfo tcDir(otherProfile.value(QLatin1String("cpp.toolchainInstallPath")) .toString()); if (!tcDir.fileName().isEmpty() && tcDir.exists()) { profile.setValue(QLatin1String("qbs.sysroot"), tcDir.path()); foundMingw = true; break; } } } if (!foundMingw) { qbsWarning() << Tr::tr("Using clang on Windows requires a mingw installation. " "Please set qbs.sysroot accordingly for profile '%1'.") .arg(profile.name()); } } if (toolchainType != QLatin1String("clang")) { // Check whether auxiliary tools reside within the toolchain's install path. // This might not be the case when using icecc or another compiler wrapper. const QString compilerDirPath = compiler.absolutePath(); const ToolPathSetup toolPathSetup(&profile, compilerDirPath, details); toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath")); toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath")); toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath")); if (doesProfileTargetOS(profile, QStringLiteral("darwin"))) toolPathSetup.apply(QStringLiteral("dsymutil"), QStringLiteral("cpp.dsymutilPath")); else toolPathSetup.apply(QStringLiteral("objcopy"), QStringLiteral("cpp.objcopyPath")); toolPathSetup.apply(QStringLiteral("strip"), QStringLiteral("cpp.stripPath")); } qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profile.name(), compiler.absoluteFilePath()); return profile; } void gccProbe(Settings *settings, std::vector &profiles, const QString &compilerName) { qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName); QStringList searchPaths; searchPaths << systemSearchPaths() << gnuRegistrySearchPaths() << atmelRegistrySearchPaths() << renesasRl78RegistrySearchPaths() << mplabX32RegistrySearchPaths(); std::vector candidates; const auto filters = buildCompilerNameFilters(compilerName); for (const auto &searchPath : std::as_const(searchPaths)) { const QDir dir(searchPath); const QStringList fileNames = dir.entryList( filters, QDir::Files | QDir::Executable); for (const QString &fileName : fileNames) { // Ignore unexpected compiler names. if (fileName.startsWith(QLatin1String("c89-gcc")) || fileName.startsWith(QLatin1String("c99-gcc"))) { continue; } const QFileInfo candidate(dir.filePath(fileName)); // Filter duplicates. const auto existingEnd = candidates.end(); const auto existingIt = std::find_if( candidates.begin(), existingEnd, [candidate](const QFileInfo &existing) { return isSameExecutable(candidate.absoluteFilePath(), existing.absoluteFilePath()); }); if (existingIt == existingEnd) { // No duplicates are found, just add a new candidate. candidates.push_back(candidate); } else { // Replace the existing entry if a candidate name more than // an existing name. const auto candidateName = candidate.completeBaseName(); const auto existingName = existingIt->completeBaseName(); if (candidateName > existingName) *existingIt = candidate; } } } if (candidates.empty()) { qbsInfo() << Tr::tr("No %1 toolchains found.").arg(compilerName); return; } // Sort candidates so that mingw comes first. Information from mingw profiles is potentially // used for setting up clang profiles. if (HostOsInfo::isWindowsHost()) { std::sort(candidates.begin(), candidates.end(), [](const QFileInfo &fi1, const QFileInfo &fi2) { return fi1.absoluteFilePath().contains(QLatin1String("mingw")) && !fi2.absoluteFilePath().contains(QLatin1String("mingw")); }); } for (const auto &candidate : std::as_const(candidates)) { const QString toolchainType = toolchainTypeFromCompilerName( candidate.baseName()); const QString profileName = buildProfileName(candidate); try { auto profile = createGccProfile(candidate, settings, toolchainType, profileName); profiles.push_back(std::move(profile)); } catch (const qbs::ErrorInfo &info) { qbsWarning() << Tr::tr("Skipping %1: %2").arg(profileName, info.toString()); } } } qbs-src-3.3.1/src/app/qbs-setup-toolchains/sdccprobe.h0000644000175100017510000000520115232633614022251 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_SDCCPROBE_H #define QBS_SETUPTOOLCHAINS_SDCCPROBE_H #include #include QT_BEGIN_NAMESPACE class QFileInfo; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; } struct SdccInstallInfo { QString compilerPath; QString version; }; inline bool operator==(const SdccInstallInfo &lhs, const SdccInstallInfo &rhs) { return std::tie(lhs.compilerPath, lhs.version) == std::tie(rhs.compilerPath, rhs.version); } bool isSdccCompiler(const QString &compilerName); void createSdccProfile(const QFileInfo &compiler, qbs::Settings *settings, const QString &profileName); void sdccProbe(qbs::Settings *settings, std::vector &profiles); #endif // Header guard qbs-src-3.3.1/src/app/qbs-setup-toolchains/cosmicprobe.cpp0000644000175100017510000001526315232633614023156 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2021 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "cosmicprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; using Internal::HostOsInfo; static QStringList knownCosmicCompilerNames() { return {QStringLiteral("cxcorm"), QStringLiteral("cxstm8"), QStringLiteral("cx6808"), QStringLiteral("cx6812"), QStringLiteral("cx332")}; } static QString guessCosmicArchitecture(const QFileInfo &compiler) { const auto baseName = compiler.baseName(); if (baseName == QLatin1String("cxcorm")) return QStringLiteral("arm"); if (baseName == QLatin1String("cxstm8")) return QStringLiteral("stm8"); if (baseName == QLatin1String("cx6808")) return QStringLiteral("hcs8"); if (baseName == QLatin1String("cx6812")) return QStringLiteral("hcs12"); if (baseName == QLatin1String("cx332")) return QStringLiteral("m68k"); return {}; } static Profile createCosmicProfileHelper(const ToolchainInstallInfo &info, Settings *settings, QString profileName = QString()) { const QFileInfo compiler = info.compilerPath; const QString architecture = guessCosmicArchitecture(compiler); // In case the profile is auto-detected. if (profileName.isEmpty()) { if (!info.compilerVersion.isValid()) { profileName = QStringLiteral("cosmic-unknown-%1").arg(architecture); } else { const QString version = info.compilerVersion.toString(QLatin1Char('_'), QLatin1Char('_')); profileName = QStringLiteral("cosmic-%1-%2").arg( version, architecture); } } Profile profile(profileName, settings); profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QLatin1String("qbs.toolchainType"), QLatin1String("cosmic")); if (!architecture.isEmpty()) profile.setValue(QLatin1String("qbs.architecture"), architecture); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()); return profile; } static Version dumpCosmicCompilerVersion(const QFileInfo &compiler) { QProcess p; QStringList args; p.start(compiler.absoluteFilePath(), args); p.waitForFinished(3000); const auto es = p.exitStatus(); if (es != QProcess::NormalExit) { const QByteArray out = p.readAll(); qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") .arg(QString::fromUtf8(out)); return Version{}; } const QByteArray output = p.readAllStandardError(); const QRegularExpression re(QLatin1String("^COSMIC.+V(\\d+)\\.?(\\d+)\\.?(\\*|\\d+)?")); const QRegularExpressionMatch match = re.match(QString::fromLatin1(output)); if (!match.hasMatch()) return Version{}; const auto major = match.captured(1).toInt(); const auto minor = match.captured(2).toInt(); const auto patch = match.captured(3).toInt(); return Version{major, minor, patch}; } static std::vector installedCosmicsFromPath() { std::vector infos; const auto compilerNames = knownCosmicCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo cosmicPath( findExecutable( HostOsInfo::appendExecutableSuffix(compilerName))); if (!cosmicPath.exists()) continue; const Version version = dumpCosmicCompilerVersion(cosmicPath); infos.push_back({cosmicPath, version}); } std::sort(infos.begin(), infos.end()); return infos; } bool isCosmicCompiler(const QString &compilerName) { return Internal::any_of(knownCosmicCompilerNames(), [compilerName](const QString &knownName) { return compilerName.contains(knownName); }); } void createCosmicProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { const ToolchainInstallInfo info = {compiler, Version{}}; createCosmicProfileHelper(info, settings, std::move(profileName)); } void cosmicProbe(Settings *settings, std::vector &profiles) { qbsInfo() << Tr::tr("Trying to detect COSMIC toolchains..."); const std::vector allInfos = installedCosmicsFromPath(); qbs::Internal::transform(allInfos, profiles, [settings](const auto &info) { return createCosmicProfileHelper(info, settings); }); if (allInfos.empty()) qbsInfo() << Tr::tr("No COSMIC toolchains found."); } qbs-src-3.3.1/src/app/config-ui/0000755000175100017510000000000015232633614015732 5ustar runnerrunnerqbs-src-3.3.1/src/app/config-ui/commandlineparser.cpp0000644000175100017510000001047415232633614022147 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_settingsDir.clear(); if (m_commandLine.empty()) return; const QString &arg = m_commandLine.front(); if (arg == helpOptionShort() || arg == helpOptionLong()) { m_commandLine.removeFirst(); m_helpRequested = true; } else if (arg == systemOption()) { m_commandLine.removeFirst(); m_settingsScope = qbs::Settings::SystemScope; } else if (arg == settingsDirOption()) { m_commandLine.removeFirst(); assignOptionArgument(settingsDirOption(), m_settingsDir); } if (!m_commandLine.empty()) complainAboutExtraArguments(); } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool displays qbs settings in a GUI.\n" "If you have more than a few settings, this might be preferable to " "plain \"qbs config\", as it presents a hierarchical view.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%5] [%3|%4]\n") .arg(m_command, settingsDirOption(), helpOptionShort(), helpOptionLong(), systemOption()); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-3.3.1/src/app/config-ui/fgapp.mm0000644000175100017510000000426115232633614017365 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import #include extern "C" void qt_macos_forceTransformProcessToForegroundApplicationAndActivate() { [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; } qbs-src-3.3.1/src/app/config-ui/Info.plist0000644000175100017510000000070615232633614017705 0ustar runnerrunner CFBundleIdentifier org.qt-project.qbs-config-ui CFBundleInfoDictionaryVersion 6.0 CFBundleName Qbs Settings LSUIElement 1 qbs-src-3.3.1/src/app/config-ui/CMakeLists.txt0000644000175100017510000000070415232633614020473 0ustar runnerrunnerset(SOURCES commandlineparser.cpp commandlineparser.h main.cpp mainwindow.cpp mainwindow.h mainwindow.ui ) # TODO: support Info.plist if(APPLE) set(MACOS_SOURCES fgapp.mm) set(MACOS_FRAMEWORKS "-framework ApplicationServices" "-framework Cocoa") endif() add_qbs_app(qbs-config-ui DEPENDS qbscore qbsconsolelogger Qt${QT_VERSION_MAJOR}::Widgets ${MACOS_FRAMEWORKS} SOURCES ${SOURCES} ${MACOS_SOURCES} ) qbs-src-3.3.1/src/app/config-ui/config-ui.qbs0000644000175100017510000000126515232633614020325 0ustar runnerrunnerQbsApp { Depends { name: "Qt.widgets" } name: "qbs-config-ui" consoleApplication: false files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "mainwindow.cpp", "mainwindow.h", "mainwindow.ui", ] Group { condition: qbs.targetOS.contains("macos") files: [ "fgapp.mm", "Info.plist" ] } Properties { condition: qbs.targetOS.contains("macos") cpp.frameworks: ["ApplicationServices", "Cocoa"] bundle.isBundle: false } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } qbs-src-3.3.1/src/app/config-ui/commandlineparser.h0000644000175100017510000000527515232633614021617 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CONFIGUI_COMMANDLINEPARSER_H #define QBS_CONFIGUI_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested = false; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-3.3.1/src/app/config-ui/main.cpp0000644000175100017510000000507015232633614017364 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "commandlineparser.h" #include #include #include #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()); return EXIT_SUCCESS; } } catch (const qbs::ErrorInfo &error) { std::cerr << qPrintable(error.toString()); return EXIT_FAILURE; } MainWindow mw(clParser.settingsDir(), clParser.settingsScope()); mw.show(); return app.exec(); } qbs-src-3.3.1/src/app/config-ui/mainwindow.cpp0000644000175100017510000002163015232633614020614 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include #else #include #endif #include #include #include #include #include namespace { class TrimValidator : public QValidator { public: explicit TrimValidator(QObject *parent = nullptr) : QValidator(parent) {} // QValidator interface State validate(QString &input, int &pos) const override { Q_UNUSED(pos); if (input.startsWith(QLatin1Char(' ')) || input.endsWith(QLatin1Char(' '))) return State::Intermediate; return State::Acceptable; } void fixup(QString &input) const override { input = input.trimmed(); } }; class SettingsItemDelegate: public QStyledItemDelegate { public: explicit SettingsItemDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { const auto editor = QStyledItemDelegate::createEditor(parent, option, index); const auto lineEdit = qobject_cast(editor); if (lineEdit) lineEdit->setValidator(new TrimValidator(lineEdit)); return editor; } }; } // namespace MainWindow::MainWindow(const QString &settingsDir, qbs::Settings::Scope scope, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_model = new qbs::SettingsModel(settingsDir, scope, this); ui->treeView->setModel(m_model); ui->treeView->setItemDelegate(new SettingsItemDelegate(ui->treeView)); ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->treeView, &QTreeView::expanded, this, &MainWindow::adjustColumns); connect(ui->treeView, &QWidget::customContextMenuRequested, this, &MainWindow::provideContextMenu); adjustColumns(); QMenu * const fileMenu = menuBar()->addMenu(tr("&File")); QMenu * const viewMenu = menuBar()->addMenu(tr("&View")); const auto reloadAction = new QAction(tr("&Reload"), this); reloadAction->setShortcut(QKeySequence::Refresh); connect(reloadAction, &QAction::triggered, this, &MainWindow::reloadSettings); const auto saveAction = new QAction(tr("&Save"), this); saveAction->setShortcut(QKeySequence::Save); connect(saveAction, &QAction::triggered, this, &MainWindow::saveSettings); const auto expandAllAction = new QAction(tr("&Expand All"), this); expandAllAction->setShortcut(int(Qt::CTRL) | int(Qt::Key_E)); connect(expandAllAction, &QAction::triggered, this, &MainWindow::expandAll); const auto collapseAllAction = new QAction(tr("C&ollapse All"), this); collapseAllAction->setShortcut(int(Qt::CTRL) | int(Qt::Key_O)); connect(collapseAllAction, &QAction::triggered, this, &MainWindow::collapseAll); const auto exitAction = new QAction(tr("E&xit"), this); exitAction->setShortcut(QKeySequence::Quit); exitAction->setMenuRole(QAction::QuitRole); connect(exitAction, &QAction::triggered, this, &MainWindow::exit); fileMenu->addAction(reloadAction); fileMenu->addAction(saveAction); fileMenu->addSeparator(); fileMenu->addAction(exitAction); viewMenu->addAction(expandAllAction); viewMenu->addAction(collapseAllAction); ui->treeView->installEventFilter(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::adjustColumns() { for (int column = 0; column < m_model->columnCount(); ++column) ui->treeView->resizeColumnToContents(column); } void MainWindow::expandAll() { ui->treeView->expandAll(); adjustColumns(); } void MainWindow::collapseAll() { ui->treeView->collapseAll(); adjustColumns(); } void MainWindow::reloadSettings() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to discard them?")); if (answer != QMessageBox::Yes) return; } m_model->reload(); } void MainWindow::saveSettings() { m_model->save(); } void MainWindow::exit() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to save them now?")); if (answer == QMessageBox::Yes) m_model->save(); } qApp->quit(); } void MainWindow::provideContextMenu(const QPoint &pos) { const QModelIndex index = ui->treeView->indexAt(pos); if (index.isValid() && index.column() != m_model->keyColumn()) return; const QString settingsKey = m_model->data(index).toString(); QMenu contextMenu; QAction addKeyAction(this); QAction removeKeyAction(this); if (index.isValid()) { addKeyAction.setText(tr("Add new key below '%1'").arg(settingsKey)); removeKeyAction.setText(tr("Remove key '%1' and all its sub-keys").arg(settingsKey)); contextMenu.addAction(&addKeyAction); contextMenu.addAction(&removeKeyAction); } else { addKeyAction.setText(tr("Add new top-level key")); contextMenu.addAction(&addKeyAction); } const QAction *action = contextMenu.exec(ui->treeView->mapToGlobal(pos)); if (action == &addKeyAction) m_model->addNewKey(index); else if (action == &removeKeyAction) m_model->removeKey(index); } extern "C" void qt_macos_forceTransformProcessToForegroundApplicationAndActivate(); bool MainWindow::eventFilter(QObject *watched, QEvent *event) { if (ui->treeView->hasFocus() && event->type() == QEvent::KeyPress) { const auto keyEvent = static_cast(event); if (keyEvent->matches(QKeySequence::Delete)) { const QModelIndexList indexes = ui->treeView->selectionModel()->selectedRows(); if (indexes.size() == 1) { const QModelIndex index = indexes.front(); if (index.isValid()) { m_model->removeKey(index); return true; } } } } if (event->type() == QEvent::WindowActivate) { // Effectively delay the foreground process transformation from QApplication construction to // when the UI is shown - this prevents the application icon from popping up in the Dock // when running `qbs help`, and QCoreApplication::arguments() requires the application // object to be constructed, so it is not easily worked around #if defined(Q_OS_MACOS) qt_macos_forceTransformProcessToForegroundApplicationAndActivate(); #endif } return QMainWindow::eventFilter(watched, event); } qbs-src-3.3.1/src/app/config-ui/mainwindow.ui0000644000175100017510000000151415232633614020446 0ustar runnerrunner MainWindow 0 0 800 600 Qbs Settings 0 0 800 27 qbs-src-3.3.1/src/app/config-ui/mainwindow.h0000644000175100017510000000520515232633614020261 0ustar runnerrunner/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include namespace qbs { class SettingsModel; } QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } class QPoint; QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(const QString &settingsDir, qbs::Settings::Scope scope, QWidget *parent = nullptr); ~MainWindow() override; bool eventFilter(QObject *watched, QEvent *event) override; private: void adjustColumns(); void expandAll(); void collapseAll(); void reloadSettings(); void saveSettings(); void exit(); void provideContextMenu(const QPoint &pos); Ui::MainWindow *ui; qbs::SettingsModel *m_model; }; #endif // MAINWINDOW_H qbs-src-3.3.1/src/3rdparty/0000755000175100017510000000000015232633614015042 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/0000755000175100017510000000000015232633614016363 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/0000755000175100017510000000000015232633614017131 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/python3.9/0000755000175100017510000000000015232633614020704 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/0000755000175100017510000000000015232633614023424 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/0000755000175100017510000000000015232633614025335 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py0000644000175100017510000007723215232633614026533 0ustar runnerrunnerimport datetime import os import uuid from ctypes import ( POINTER, Structure, Union, byref, c_byte, c_char, c_char_p, c_int, c_long, c_longlong, c_short, c_uint, c_ulong, c_ulonglong, c_ushort, c_void_p, cdll, create_string_buffer, sizeof, ) from .utils import unix_epoch libc = cdll.LoadLibrary("/usr/lib/libc.dylib") # Constants FSOPT_NOFOLLOW = 0x00000001 FSOPT_NOINMEMUPDATE = 0x00000002 FSOPT_REPORT_FULLSIZE = 0x00000004 FSOPT_PACK_INVAL_ATTRS = 0x00000008 FSOPT_ATTR_CMN_EXTENDED = 0x00000020 FSOPT_RETURN_REALDEV = 0x00000200 VOL_CAPABILITIES_FORMAT = 0 VOL_CAPABILITIES_INTERFACES = 1 VOL_CAP_FMT_PERSISTENTOBJECTIDS = 0x00000001 VOL_CAP_FMT_SYMBOLICLINKS = 0x00000002 VOL_CAP_FMT_HARDLINKS = 0x00000004 VOL_CAP_FMT_JOURNAL = 0x00000008 VOL_CAP_FMT_JOURNAL_ACTIVE = 0x00000010 VOL_CAP_FMT_NO_ROOT_TIMES = 0x00000020 VOL_CAP_FMT_SPARSE_FILES = 0x00000040 VOL_CAP_FMT_ZERO_RUNS = 0x00000080 VOL_CAP_FMT_CASE_SENSITIVE = 0x00000100 VOL_CAP_FMT_CASE_PRESERVING = 0x00000200 VOL_CAP_FMT_FAST_STATFS = 0x00000400 VOL_CAP_FMT_2TB_FILESIZE = 0x00000800 VOL_CAP_FMT_OPENDENYMODES = 0x00001000 VOL_CAP_FMT_HIDDEN_FILES = 0x00002000 VOL_CAP_FMT_PATH_FROM_ID = 0x00004000 VOL_CAP_FMT_NO_VOLUME_SIZES = 0x00008000 VOL_CAP_FMT_DECMPFS_COMPRESSION = 0x00010000 VOL_CAP_FMT_64BIT_OBJECT_IDS = 0x00020000 VOL_CAP_INT_SEARCHFS = 0x00000001 VOL_CAP_INT_ATTRLIST = 0x00000002 VOL_CAP_INT_NFSEXPORT = 0x00000004 VOL_CAP_INT_READDIRATTR = 0x00000008 VOL_CAP_INT_EXCHANGEDATA = 0x00000010 VOL_CAP_INT_COPYFILE = 0x00000020 VOL_CAP_INT_ALLOCATE = 0x00000040 VOL_CAP_INT_VOL_RENAME = 0x00000080 VOL_CAP_INT_ADVLOCK = 0x00000100 VOL_CAP_INT_FLOCK = 0x00000200 VOL_CAP_INT_EXTENDED_SECURITY = 0x00000400 VOL_CAP_INT_USERACCESS = 0x00000800 VOL_CAP_INT_MANLOCK = 0x00001000 VOL_CAP_INT_NAMEDSTREAMS = 0x00002000 VOL_CAP_INT_EXTENDED_ATTR = 0x00004000 VOL_CAP_INT_CLONE = 0x00010000 VOL_CAP_INT_SNAPSHOT = 0x00020000 VOL_CAP_INT_RENAME_SWAP = 0x00040000 VOL_CAP_INT_RENAME_EXCL = 0x00080000 VOL_CAP_INT_RENAME_OPENFAIL = 0x00100000 ATTR_CMN_NAME = 0x00000001 ATTR_CMN_DEVID = 0x00000002 ATTR_CMN_FSID = 0x00000004 ATTR_CMN_OBJTYPE = 0x00000008 ATTR_CMN_OBJTAG = 0x00000010 ATTR_CMN_OBJID = 0x00000020 ATTR_CMN_OBJPERMANENTID = 0x00000040 ATTR_CMN_PAROBJID = 0x00000080 ATTR_CMN_SCRIPT = 0x00000100 ATTR_CMN_CRTIME = 0x00000200 ATTR_CMN_MODTIME = 0x00000400 ATTR_CMN_CHGTIME = 0x00000800 ATTR_CMN_ACCTIME = 0x00001000 ATTR_CMN_BKUPTIME = 0x00002000 ATTR_CMN_FNDRINFO = 0x00004000 ATTR_CMN_OWNERID = 0x00008000 ATTR_CMN_GRPID = 0x00010000 ATTR_CMN_ACCESSMASK = 0x00020000 ATTR_CMN_FLAGS = 0x00040000 ATTR_CMN_GEN_COUNT = 0x00080000 ATTR_CMN_DOCUMENT_ID = 0x00100000 ATTR_CMN_USERACCESS = 0x00200000 ATTR_CMN_EXTENDED_SECURITY = 0x00400000 ATTR_CMN_UUID = 0x00800000 ATTR_CMN_GRPUUID = 0x01000000 ATTR_CMN_FILEID = 0x02000000 ATTR_CMN_PARENTID = 0x04000000 ATTR_CMN_FULLPATH = 0x08000000 ATTR_CMN_ADDEDTIME = 0x10000000 ATTR_CMN_ERROR = 0x20000000 ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 ATTR_CMN_RETURNED_ATTRS = 0x80000000 ATTR_CMN_ALL_ATTRS = 0xFFFFFFFF ATTR_CMN_VALIDMASK = 0xFFFFFFFF ATTR_CMN_SETMASK = 0x51C7FF00 ATTR_CMN_VOLSETMASK = 0x00006700 ATTR_VOL_FSTYPE = 0x00000001 ATTR_VOL_SIGNATURE = 0x00000002 ATTR_VOL_SIZE = 0x00000004 ATTR_VOL_SPACEFREE = 0x00000008 ATTR_VOL_SPACEAVAIL = 0x00000010 ATTR_VOL_MINALLOCATION = 0x00000020 ATTR_VOL_ALLOCATIONCLUMP = 0x00000040 ATTR_VOL_IOBLOCKSIZE = 0x00000080 ATTR_VOL_OBJCOUNT = 0x00000100 ATTR_VOL_FILECOUNT = 0x00000200 ATTR_VOL_DIRCOUNT = 0x00000400 ATTR_VOL_MAXOBJCOUNT = 0x00000800 ATTR_VOL_MOUNTPOINT = 0x00001000 ATTR_VOL_NAME = 0x00002000 ATTR_VOL_MOUNTFLAGS = 0x00004000 ATTR_VOL_MOUNTEDDEVICE = 0x00008000 ATTR_VOL_ENCODINGSUSED = 0x00010000 ATTR_VOL_CAPABILITIES = 0x00020000 ATTR_VOL_UUID = 0x00040000 ATTR_VOL_QUOTA_SIZE = 0x10000000 ATTR_VOL_RESERVED_SIZE = 0x20000000 ATTR_VOL_ATTRIBUTES = 0x40000000 ATTR_VOL_INFO = 0x80000000 ATTR_VOL_ALL_ATTRS = 0xF007FFFF ATTR_DIR_LINKCOUNT = 0x00000001 ATTR_DIR_ENTRYCOUNT = 0x00000002 ATTR_DIR_MOUNTSTATUS = 0x00000004 DIR_MNTSTATUS_MNTPOINT = 0x00000001 DIR_MNTSTATUS_TRIGGER = 0x00000002 ATTR_DIR_ALLOCSIZE = 0x00000008 ATTR_DIR_IOBLOCKSIZE = 0x00000010 ATTR_DIR_DATALENGTH = 0x00000020 ATTR_DIR_ALL_ATTRS = 0x0000003F ATTR_DIR_VALIDMASK = 0x0000003F ATTR_DIR_SETMASK = 0x00000000 ATTR_FILE_LINKCOUNT = 0x00000001 ATTR_FILE_TOTALSIZE = 0x00000002 ATTR_FILE_ALLOCSIZE = 0x00000004 ATTR_FILE_IOBLOCKSIZE = 0x00000008 ATTR_FILE_DEVTYPE = 0x00000020 ATTR_FILE_FORKCOUNT = 0x00000080 ATTR_FILE_FORKLIST = 0x00000100 ATTR_FILE_DATALENGTH = 0x00000200 ATTR_FILE_DATAALLOCSIZE = 0x00000400 ATTR_FILE_RSRCLENGTH = 0x00001000 ATTR_FILE_RSRCALLOCSIZE = 0x00002000 ATTR_FILE_ALL_ATTRS = 0x000037FF ATTR_FILE_VALIDMASK = 0x000037FF ATTR_FILE_SETMASK = 0x00000020 # These are deprecated ATTR_FORK_TOTALSIZE = 0x00000001 ATTR_FORK_ALLOCSIZE = 0x00000002 ATTR_FORK_ALL_ATTRS = 0x00000003 # These go in the fork attribute field ATTR_CMNEXT_RELPATH = 0x00000004 ATTR_CMNEXT_PRIVATESIZE = 0x00000008 ATTR_CMNEXT_LINKID = 0x0000010 ATTR_CMNEXT_NOFIRMLINKPATH = 0x00000020 ATTR_CMNEXT_REALDEVID = 0x00000040 ATTR_CMNEXT_REALFSID = 0x00000080 ATTR_CMNEXT_CLONEID = 0x00000100 ATTR_CMNEXT_EXT_FLAGS = 0x00000200 ATTR_CMNEXT_RECURSIVE_GENCOUNT = 0x00000400 ATTR_CMNEXT_ALL_ATTRS = 0x000007FC ATTR_CMNEXT_VALIDMASK = 0x000007FC ATTR_CMNEXT_SETMASK = 0x00000000 ATTR_FORK_VALIDMASK = 0x00000003 ATTR_FORK_SETMASK = 0x00000000 # These can't be used ATTR_CMN_NAMEDATTRCOUNT = 0x00080000 ATTR_CMN_NAMEDATTRLIST = 0x00100000 ATTR_FILE_CLUMPSIZE = 0x00000010 ATTR_FILE_FILETYPE = 0x00000040 ATTR_FILE_DATAEXTENTS = 0x00000800 ATTR_FILE_RSRCEXTENTS = 0x00004000 class attrlist(Structure): _fields_ = [ ("bitmapcount", c_ushort), ("reserved", c_ushort), ("commonattr", c_uint), ("volattr", c_uint), ("dirattr", c_uint), ("fileattr", c_uint), ("forkattr", c_uint), ] class attribute_set_t(Structure): _fields_ = [ ("commonattr", c_uint), ("volattr", c_uint), ("dirattr", c_uint), ("fileattr", c_uint), ("forkattr", c_uint), ] class fsobj_id_t(Structure): _fields_ = [ ("fid_objno", c_uint), ("fid_generation", c_uint), ] class timespec(Structure): _fields_ = [ ("tv_sec", c_long), ("tv_nsec", c_long), ] class attrreference_t(Structure): _fields_ = [ ("attr_dataoffset", c_int), ("attr_length", c_uint), ] class fsid_t(Structure): _fields_ = [ ("val", c_uint * 2), ] class guid_t(Structure): _fields_ = [ ("g_guid", c_byte * 16), ] class kauth_ace(Structure): _fields_ = [ ("ace_applicable", guid_t), ("ace_flags", c_uint), ] class kauth_acl(Structure): _fields_ = [ ("acl_entrycount", c_uint), ("acl_flags", c_uint), ("acl_ace", kauth_ace * 128), ] class kauth_filesec(Structure): _fields_ = [ ("fsec_magic", c_uint), ("fsec_owner", guid_t), ("fsec_group", guid_t), ("fsec_acl", kauth_acl), ] class diskextent(Structure): _fields_ = [ ("startblock", c_uint), ("blockcount", c_uint), ] OSType = c_uint UInt16 = c_ushort SInt16 = c_short SInt32 = c_int class Point(Structure): _fields_ = [ ("x", SInt16), ("y", SInt16), ] class Rect(Structure): _fields_ = [ ("x", SInt16), ("y", SInt16), ("w", SInt16), ("h", SInt16), ] class FileInfo(Structure): _fields_ = [ ("fileType", OSType), ("fileCreator", OSType), ("finderFlags", UInt16), ("location", Point), ("reservedField", UInt16), ("reserved1", SInt16 * 4), ("extendedFinderFlags", UInt16), ("reserved2", SInt16), ("putAwayFolderID", SInt32), ] class FolderInfo(Structure): _fields_ = [ ("windowBounds", Rect), ("finderFlags", UInt16), ("location", Point), ("reservedField", UInt16), ("scrollPosition", Point), ("reserved1", SInt32), ("extendedFinderFlags", UInt16), ("reserved2", SInt16), ("putAwayFolderID", SInt32), ] class FinderInfo(Union): _fields_ = [ ("fileInfo", FileInfo), ("folderInfo", FolderInfo), ] extentrecord = diskextent * 8 vol_capabilities_set_t = c_uint * 4 class vol_capabilities_attr_t(Structure): _fields_ = [ ("capabilities", vol_capabilities_set_t), ("valid", vol_capabilities_set_t), ] class vol_attributes_attr_t(Structure): _fields_ = [ ("validattr", attribute_set_t), ("nativeattr", attribute_set_t), ] dev_t = c_uint fsobj_type_t = c_uint VNON = 0 VREG = 1 VDIR = 2 VBLK = 3 VCHR = 4 VLNK = 5 VSOCK = 6 VFIFO = 7 VBAD = 8 VSTR = 9 VCPLX = 10 fsobj_tag_t = c_uint VT_NON = 0 VT_UFS = 1 VT_NFS = 2 VT_MFS = 3 VT_MSDOSFS = 4 VT_LFS = 5 VT_LOFS = 6 VT_FDESC = 7 VT_PORTAL = 8 VT_NULL = 9 VT_UMAP = 10 VT_KERNFS = 11 VT_PROCFS = 12 VT_AFS = 13 VT_ISOFS = 14 VT_UNION = 15 VT_HFS = 16 VT_ZFS = 17 VT_DEVFS = 18 VT_WEBDAV = 19 VT_UDF = 20 VT_AFP = 21 VT_CDDA = 22 VT_CIFS = 23 VT_OTHER = 24 fsfile_type_t = c_uint fsvolid_t = c_uint text_encoding_t = c_uint uid_t = c_uint gid_t = c_uint int32_t = c_int uint32_t = c_uint int64_t = c_longlong uint64_t = c_ulonglong off_t = c_long size_t = c_ulong uuid_t = c_byte * 16 NAME_MAX = 255 PATH_MAX = 1024 FSTYPE_MAX = 16 class struct_statfs(Structure): _fields_ = [ ("f_bsize", uint32_t), ("f_iosize", int32_t), ("f_blocks", uint64_t), ("f_bfree", uint64_t), ("f_bavail", uint64_t), ("f_files", uint64_t), ("f_ffree", uint64_t), ("f_fsid", fsid_t), ("f_owner", uid_t), ("f_type", uint32_t), ("f_flags", uint32_t), ("f_fssubtype", uint32_t), ("f_fstypename", c_char * FSTYPE_MAX), ("f_mntonname", c_char * PATH_MAX), ("f_mntfromname", c_char * PATH_MAX), ("f_flags_ext", uint32_t), ("f_reserved", uint32_t * 7), ] # Calculate the maximum number of bytes required for the attribute buffer _attr_info = ( # Common attributes (0, ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t)), (0, ATTR_CMN_NAME, sizeof(attrreference_t) + NAME_MAX * 3 + 1), (0, ATTR_CMN_DEVID, sizeof(dev_t)), (0, ATTR_CMN_FSID, sizeof(fsid_t)), (0, ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t)), (0, ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t)), (0, ATTR_CMN_OBJID, sizeof(fsobj_id_t)), (0, ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t)), (0, ATTR_CMN_PAROBJID, sizeof(fsobj_id_t)), (0, ATTR_CMN_SCRIPT, sizeof(text_encoding_t)), (0, ATTR_CMN_CRTIME, sizeof(timespec)), (0, ATTR_CMN_MODTIME, sizeof(timespec)), (0, ATTR_CMN_CHGTIME, sizeof(timespec)), (0, ATTR_CMN_ACCTIME, sizeof(timespec)), (0, ATTR_CMN_BKUPTIME, sizeof(timespec)), (0, ATTR_CMN_FNDRINFO, sizeof(FinderInfo)), (0, ATTR_CMN_OWNERID, sizeof(uid_t)), (0, ATTR_CMN_GRPID, sizeof(gid_t)), (0, ATTR_CMN_ACCESSMASK, sizeof(uint32_t)), (0, ATTR_CMN_NAMEDATTRCOUNT, None), (0, ATTR_CMN_NAMEDATTRLIST, None), (0, ATTR_CMN_FLAGS, sizeof(uint32_t)), (0, ATTR_CMN_GEN_COUNT, sizeof(uint32_t)), (0, ATTR_CMN_DOCUMENT_ID, sizeof(uint32_t)), (0, ATTR_CMN_USERACCESS, sizeof(uint32_t)), (0, ATTR_CMN_EXTENDED_SECURITY, sizeof(attrreference_t) + sizeof(kauth_filesec)), (0, ATTR_CMN_UUID, sizeof(guid_t)), (0, ATTR_CMN_GRPUUID, sizeof(guid_t)), (0, ATTR_CMN_FILEID, sizeof(uint64_t)), (0, ATTR_CMN_PARENTID, sizeof(uint64_t)), (0, ATTR_CMN_FULLPATH, sizeof(attrreference_t) + PATH_MAX), (0, ATTR_CMN_ADDEDTIME, sizeof(timespec)), (0, ATTR_CMN_DATA_PROTECT_FLAGS, sizeof(uint32_t)), # Volume attributes (1, ATTR_VOL_FSTYPE, sizeof(uint32_t)), (1, ATTR_VOL_SIGNATURE, sizeof(uint32_t)), (1, ATTR_VOL_SIZE, sizeof(off_t)), (1, ATTR_VOL_SPACEFREE, sizeof(off_t)), (1, ATTR_VOL_SPACEAVAIL, sizeof(off_t)), (1, ATTR_VOL_MINALLOCATION, sizeof(off_t)), (1, ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t)), (1, ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t)), (1, ATTR_VOL_OBJCOUNT, sizeof(uint32_t)), (1, ATTR_VOL_FILECOUNT, sizeof(uint32_t)), (1, ATTR_VOL_DIRCOUNT, sizeof(uint32_t)), (1, ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t)), (1, ATTR_VOL_MOUNTPOINT, sizeof(attrreference_t) + PATH_MAX), (1, ATTR_VOL_NAME, sizeof(attrreference_t) + NAME_MAX + 1), (1, ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t)), (1, ATTR_VOL_MOUNTEDDEVICE, sizeof(attrreference_t) + PATH_MAX), (1, ATTR_VOL_ENCODINGSUSED, sizeof(c_ulonglong)), (1, ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t)), (1, ATTR_VOL_UUID, sizeof(uuid_t)), (1, ATTR_VOL_QUOTA_SIZE, sizeof(off_t)), (1, ATTR_VOL_RESERVED_SIZE, sizeof(off_t)), (1, ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t)), # Directory attributes (2, ATTR_DIR_LINKCOUNT, sizeof(uint32_t)), (2, ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t)), (2, ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t)), (2, ATTR_DIR_ALLOCSIZE, sizeof(off_t)), (2, ATTR_DIR_IOBLOCKSIZE, sizeof(uint32_t)), (2, ATTR_DIR_DATALENGTH, sizeof(off_t)), # File attributes (3, ATTR_FILE_LINKCOUNT, sizeof(uint32_t)), (3, ATTR_FILE_TOTALSIZE, sizeof(off_t)), (3, ATTR_FILE_ALLOCSIZE, sizeof(off_t)), (3, ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t)), (3, ATTR_FILE_CLUMPSIZE, sizeof(uint32_t)), (3, ATTR_FILE_DEVTYPE, sizeof(uint32_t)), (3, ATTR_FILE_FILETYPE, sizeof(uint32_t)), (3, ATTR_FILE_FORKCOUNT, sizeof(uint32_t)), (3, ATTR_FILE_FORKLIST, None), (3, ATTR_FILE_DATALENGTH, sizeof(off_t)), (3, ATTR_FILE_DATAALLOCSIZE, sizeof(off_t)), (3, ATTR_FILE_DATAEXTENTS, sizeof(extentrecord)), (3, ATTR_FILE_RSRCLENGTH, sizeof(off_t)), (3, ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t)), (3, ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord)), # Fork attributes (4, ATTR_FORK_TOTALSIZE, sizeof(off_t)), (4, ATTR_FORK_ALLOCSIZE, sizeof(off_t)), # Extended common attributes (4, ATTR_CMNEXT_RELPATH, sizeof(attrreference_t) + PATH_MAX), (4, ATTR_CMNEXT_PRIVATESIZE, sizeof(off_t)), (4, ATTR_CMNEXT_LINKID, sizeof(uint64_t)), (4, ATTR_CMNEXT_NOFIRMLINKPATH, sizeof(attrreference_t) + PATH_MAX), (4, ATTR_CMNEXT_REALDEVID, sizeof(dev_t)), (4, ATTR_CMNEXT_REALFSID, sizeof(fsid_t)), (4, ATTR_CMNEXT_CLONEID, sizeof(uint64_t)), (4, ATTR_CMNEXT_EXT_FLAGS, sizeof(uint64_t)), ) def _attrbuf_size(attrs): size = 4 for entry in _attr_info: if attrs[entry[0]] & entry[1]: if entry[2] is None: raise ValueError( "Unsupported attribute (%u, %x)" % (entry[0], entry[1]) ) size += entry[2] return size _getattrlist = libc.getattrlist _getattrlist.argtypes = [c_char_p, POINTER(attrlist), c_void_p, c_ulong, c_ulong] _getattrlist.restype = c_int _fgetattrlist = libc.fgetattrlist _fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong] _fgetattrlist.restype = c_int try: _statfs = libc["statfs$INODE64"] except (KeyError, AttributeError): _statfs = libc["statfs"] _statfs.argtypes = [ c_char_p, POINTER(struct_statfs), ] _statfs.restype = c_int try: _fstatfs = libc["fstatfs$INODE64"] except (KeyError, AttributeError): _fstatfs = libc["fstatfs"] _fstatfs.argtypes = [ c_int, POINTER(struct_statfs), ] _fstatfs.restype = c_int def _datetime_from_timespec(ts): td = datetime.timedelta(seconds=ts.tv_sec + 1.0e-9 * ts.tv_nsec) return unix_epoch + td def _decode_utf8_nul(sz): nul = sz.find(b"\0") if nul > -1: sz = sz[:nul] return sz.decode("utf-8") def _decode_attrlist_result(buf, attrs, options): result = [] assert len(buf) >= 4 total_size = uint32_t.from_buffer(buf, 0).value assert total_size <= len(buf) offset = 4 # Common attributes if attrs[0] & ATTR_CMN_RETURNED_ATTRS: a = attribute_set_t.from_buffer(buf, offset) result.append(a) offset += sizeof(attribute_set_t) if not (options & FSOPT_PACK_INVAL_ATTRS): attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr] if attrs[0] & ATTR_CMN_NAME: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset name = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(name) if attrs[0] & ATTR_CMN_DEVID: a = dev_t.from_buffer(buf, offset) offset += sizeof(dev_t) result.append(a.value) if attrs[0] & ATTR_CMN_FSID: a = fsid_t.from_buffer(buf, offset) offset += sizeof(fsid_t) result.append(a) if attrs[0] & ATTR_CMN_OBJTYPE: a = fsobj_type_t.from_buffer(buf, offset) offset += sizeof(fsobj_type_t) result.append(a.value) if attrs[0] & ATTR_CMN_OBJTAG: a = fsobj_tag_t.from_buffer(buf, offset) offset += sizeof(fsobj_tag_t) result.append(a.value) if attrs[0] & ATTR_CMN_OBJID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_OBJPERMANENTID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_PAROBJID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_SCRIPT: a = text_encoding_t.from_buffer(buf, offset) offset += sizeof(text_encoding_t) result.append(a.value) if attrs[0] & ATTR_CMN_CRTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_MODTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_CHGTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_ACCTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_BKUPTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_FNDRINFO: a = FinderInfo.from_buffer(buf, offset) offset += sizeof(FinderInfo) result.append(a) if attrs[0] & ATTR_CMN_OWNERID: a = uid_t.from_buffer(buf, offset) offset += sizeof(uid_t) result.append(a.value) if attrs[0] & ATTR_CMN_GRPID: a = gid_t.from_buffer(buf, offset) offset += sizeof(gid_t) result.append(a.value) if attrs[0] & ATTR_CMN_ACCESSMASK: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_FLAGS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_GEN_COUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_DOCUMENT_ID: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_USERACCESS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_EXTENDED_SECURITY: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset offset += sizeof(attrreference_t) ec = uint32_t.from_buffer(buf, ofs + 36).value class kauth_acl(Structure): _fields_ = [ ("acl_entrycount", c_uint), ("acl_flags", c_uint), ("acl_ace", kauth_ace * ec), ] class kauth_filesec(Structure): _fields_ = [ ("fsec_magic", c_uint), ("fsec_owner", guid_t), ("fsec_group", guid_t), ("fsec_acl", kauth_acl), ] a = kauth_filesec.from_buffer(buf, ofs) result.append(a) if attrs[0] & ATTR_CMN_UUID: result.append(uuid.UUID(bytes=buf[offset : offset + 16])) offset += sizeof(guid_t) if attrs[0] & ATTR_CMN_GRPUUID: result.append(uuid.UUID(bytes=buf[offset : offset + 16])) offset += sizeof(guid_t) if attrs[0] & ATTR_CMN_FILEID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[0] & ATTR_CMN_PARENTID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[0] & ATTR_CMN_FULLPATH: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(path) if attrs[0] & ATTR_CMN_ADDEDTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_DATA_PROTECT_FLAGS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) # Volume attributes if attrs[1] & ATTR_VOL_FSTYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_SIGNATURE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_SIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_SPACEFREE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_SPACEAVAIL: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_MINALLOCATION: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_IOBLOCKSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_OBJCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_FILECOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_DIRCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MAXOBJCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MOUNTPOINT: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(path) if attrs[1] & ATTR_VOL_NAME: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset name = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(name) if attrs[1] & ATTR_VOL_MOUNTFLAGS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MOUNTEDDEVICE: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(path) if attrs[1] & ATTR_VOL_ENCODINGSUSED: a = c_ulonglong.from_buffer(buf, offset) offset += sizeof(c_ulonglong) result.append(a.value) if attrs[1] & ATTR_VOL_CAPABILITIES: a = vol_capabilities_attr_t.from_buffer(buf, offset) offset += sizeof(vol_capabilities_attr_t) result.append(a) if attrs[1] & ATTR_VOL_UUID: result.append(uuid.UUID(bytes=buf[offset : offset + 16])) offset += sizeof(uuid_t) if attrs[1] & ATTR_VOL_QUOTA_SIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_RESERVED_SIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_ATTRIBUTES: a = vol_attributes_attr_t.from_buffer(buf, offset) offset += sizeof(vol_attributes_attr_t) result.append(a) # Directory attributes if attrs[2] & ATTR_DIR_LINKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_ENTRYCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_MOUNTSTATUS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_ALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[2] & ATTR_DIR_IOBLOCKSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_DATALENGTH: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) # File attributes if attrs[3] & ATTR_FILE_LINKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_TOTALSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_ALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_IOBLOCKSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_CLUMPSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_DEVTYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_FILETYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_FORKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATALENGTH: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATAALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATAEXTENTS: a = extentrecord.from_buffer(buf, offset) offset += sizeof(extentrecord) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCLENGTH: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCEXTENTS: a = extentrecord.from_buffer(buf, offset) offset += sizeof(extentrecord) result.append(a.value) # Fork attributes if attrs[4] & ATTR_FORK_TOTALSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[4] & ATTR_FORK_ALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) # Extended common attributes if attrs[4] & ATTR_CMNEXT_RELPATH: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(path) if attrs[4] & ATTR_CMNEXT_PRIVATESIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[4] & ATTR_CMNEXT_LINKID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[4] & ATTR_CMNEXT_NOFIRMLINKPATH: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) offset += sizeof(attrreference_t) result.append(path) if attrs[4] & ATTR_CMNEXT_REALDEVID: a = dev_t.from_buffer(buf, offset) offset += sizeof(dev_t) result.append(a.value) if attrs[4] & ATTR_CMNEXT_REALFSID: a = fsid_t.from_buffer(buf, offset) offset += sizeof(fsid_t) result.append(a.value) if attrs[4] & ATTR_CMNEXT_CLONEID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[4] & ATTR_CMNEXT_EXT_FLAGS: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) return result # Sadly, ctypes.get_errno() seems not to work __error = libc.__error __error.restype = POINTER(c_int) def _get_errno(): return __error().contents.value def getattrlist(path, attrs, options): if not isinstance(path, bytes): path = path.encode("utf-8") attrs = list(attrs) if attrs[1]: attrs[1] |= ATTR_VOL_INFO alist = attrlist( bitmapcount=5, commonattr=attrs[0], volattr=attrs[1], dirattr=attrs[2], fileattr=attrs[3], forkattr=attrs[4], ) bufsize = _attrbuf_size(attrs) buf = create_string_buffer(bufsize) ret = _getattrlist( path, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE ) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err), path) return _decode_attrlist_result(buf, attrs, options) def fgetattrlist(fd, attrs, options): if hasattr(fd, "fileno"): fd = fd.fileno() attrs = list(attrs) if attrs[1]: attrs[1] |= ATTR_VOL_INFO alist = attrlist( bitmapcount=5, commonattr=attrs[0], volattr=attrs[1], dirattr=attrs[2], fileattr=attrs[3], forkattr=attrs[4], ) bufsize = _attrbuf_size(attrs) buf = create_string_buffer(bufsize) ret = _fgetattrlist(fd, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err)) return _decode_attrlist_result(buf, attrs, options) def statfs(path): if not isinstance(path, bytes): path = path.encode("utf-8") result = struct_statfs() ret = _statfs(path, byref(result)) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err), path) return result def fstatfs(fd): if hasattr(fd, "fileno"): fd = fd.fileno() result = struct_statfs() ret = _fstatfs(fd, byref(result)) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err)) return result qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/__init__.py0000644000175100017510000000210215232633614027441 0ustar runnerrunner# flake8: noqa from .alias import * from .bookmark import * __version__ = "2.2.2" __all__ = [ "__version__", "ALIAS_KIND_FILE", "ALIAS_KIND_FOLDER", "ALIAS_HFS_VOLUME_SIGNATURE", "ALIAS_FIXED_DISK", "ALIAS_NETWORK_DISK", "ALIAS_400KB_FLOPPY_DISK", "ALIAS_800KB_FLOPPY_DISK", "ALIAS_1_44MB_FLOPPY_DISK", "ALIAS_EJECTABLE_DISK", "ALIAS_NO_CNID", "kBookmarkPath", "kBookmarkCNIDPath", "kBookmarkFileProperties", "kBookmarkFileName", "kBookmarkFileID", "kBookmarkFileCreationDate", "kBookmarkTOCPath", "kBookmarkVolumePath", "kBookmarkVolumeURL", "kBookmarkVolumeName", "kBookmarkVolumeUUID", "kBookmarkVolumeSize", "kBookmarkVolumeCreationDate", "kBookmarkVolumeProperties", "kBookmarkContainingFolder", "kBookmarkUserName", "kBookmarkUID", "kBookmarkWasFileReference", "kBookmarkCreationOptions", "kBookmarkURLLengths", "kBookmarkSecurityExtension", "AppleShareInfo", "VolumeInfo", "TargetInfo", "Alias", "Bookmark", "Data", "URL", ] qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/qt_attribution.json0000644000175100017510000000067515232633614031310 0ustar runnerrunner{ "Id": "mac_alias", "Name": "mac_alias", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "Generate/parse Mac OS Alias records from Python", "Homepage": "https://github.com/al45tair/mac_alias", "Version": "2.0.6", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/alias.py0000644000175100017510000006047015232633614027007 0ustar runnerrunnerimport datetime import io import os import os.path import struct import sys from unicodedata import normalize if sys.platform == "darwin": from . import osx from .utils import mac_epoch ALIAS_KIND_FILE = 0 ALIAS_KIND_FOLDER = 1 ALIAS_HFS_VOLUME_SIGNATURE = b"H+" ALIAS_FILESYSTEM_UDF = "UDF (CD/DVD)" ALIAS_FILESYSTEM_FAT32 = "FAT32" ALIAS_FILESYSTEM_EXFAT = "exFAT" ALIAS_FILESYSTEM_HFSX = "HFSX" ALIAS_FILESYSTEM_HFSPLUS = "HFS+" ALIAS_FILESYSTEM_FTP = "FTP" ALIAS_FILESYSTEM_NTFS = "NTFS" ALIAS_FILESYSTEM_UNKNOWN = "unknown" ALIAS_FIXED_DISK = 0 ALIAS_NETWORK_DISK = 1 ALIAS_400KB_FLOPPY_DISK = 2 ALIAS_800KB_FLOPPY_DISK = 3 ALIAS_1_44MB_FLOPPY_DISK = 4 ALIAS_EJECTABLE_DISK = 5 ALIAS_NO_CNID = 0xFFFFFFFF ALIAS_FSTYPE_MAP = { # Version 2 aliases b"HX": ALIAS_FILESYSTEM_HFSX, b"H+": ALIAS_FILESYSTEM_HFSPLUS, # Version 3 aliases b"BDcu": ALIAS_FILESYSTEM_UDF, b"BDIS": ALIAS_FILESYSTEM_FAT32, b"BDxF": ALIAS_FILESYSTEM_EXFAT, b"HX\0\0": ALIAS_FILESYSTEM_HFSX, b"H+\0\0": ALIAS_FILESYSTEM_HFSPLUS, b"KG\0\0": ALIAS_FILESYSTEM_FTP, b"NTcu": ALIAS_FILESYSTEM_NTFS, } def encode_utf8(s): if isinstance(s, bytes): return s return s.encode("utf-8") def decode_utf8(s): if isinstance(s, bytes): return s.decode("utf-8") return s class AppleShareInfo: def __init__(self, zone=None, server=None, user=None): #: The AppleShare zone self.zone = zone #: The AFP server self.server = server #: The username self.user = user def __repr__(self): return "AppleShareInfo({!r},{!r},{!r})".format( self.zone, self.server, self.user ) class VolumeInfo: def __init__( self, name, creation_date, fs_type, disk_type, attribute_flags, fs_id, appleshare_info=None, driver_name=None, posix_path=None, disk_image_alias=None, dialup_info=None, network_mount_info=None, ): #: The name of the volume on which the target resides self.name = name #: The creation date of the target's volume self.creation_date = creation_date #: The filesystem type #: (for v2 aliases, this is a 2-character code; for v3 aliases, a #: 4-character code). self.fs_type = fs_type #: The type of disk; should be one of #: #: * ALIAS_FIXED_DISK #: * ALIAS_NETWORK_DISK #: * ALIAS_400KB_FLOPPY_DISK #: * ALIAS_800KB_FLOPPY_DISK #: * ALIAS_1_44MB_FLOPPY_DISK #: * ALIAS_EJECTABLE_DISK self.disk_type = disk_type #: Filesystem attribute flags (from HFS volume header) self.attribute_flags = attribute_flags #: Filesystem identifier self.fs_id = fs_id #: AppleShare information (for automatic remounting of network shares) #: *(optional)* self.appleshare_info = appleshare_info #: Driver name (*probably* contains a disk driver name on older Macs) #: *(optional)* self.driver_name = driver_name #: POSIX path of the mount point of the target's volume #: *(optional)* self.posix_path = posix_path #: :class:`Alias` object pointing at the disk image on which the #: target's volume resides *(optional)* self.disk_image_alias = disk_image_alias #: Dialup information (for automatic establishment of dialup connections) self.dialup_info = dialup_info #: Network mount information (for automatic remounting) self.network_mount_info = network_mount_info @property def filesystem_type(self): return ALIAS_FSTYPE_MAP.get(self.fs_type, ALIAS_FILESYSTEM_UNKNOWN) def __repr__(self): args = [ "name", "creation_date", "fs_type", "disk_type", "attribute_flags", "fs_id", ] values = [] for a in args: v = getattr(self, a) values.append(repr(v)) kwargs = [ "appleshare_info", "driver_name", "posix_path", "disk_image_alias", "dialup_info", "network_mount_info", ] for a in kwargs: v = getattr(self, a) if v is not None: values.append(f"{a}={v!r}") return "VolumeInfo(%s)" % ",".join(values) class TargetInfo: def __init__( self, kind, filename, folder_cnid, cnid, creation_date, creator_code, type_code, levels_from=-1, levels_to=-1, folder_name=None, cnid_path=None, carbon_path=None, posix_path=None, user_home_prefix_len=None, ): #: Either ALIAS_KIND_FILE or ALIAS_KIND_FOLDER self.kind = kind #: The filename of the target self.filename = filename #: The CNID (Catalog Node ID) of the target's containing folder; #: CNIDs are similar to but different than traditional UNIX inode #: numbers self.folder_cnid = folder_cnid #: The CNID (Catalog Node ID) of the target self.cnid = cnid #: The target's *creation* date. self.creation_date = creation_date #: The target's Mac creator code (a four-character binary string) self.creator_code = creator_code #: The target's Mac type code (a four-character binary string) self.type_code = type_code #: The depth of the alias? Always seems to be -1 on OS X. self.levels_from = levels_from #: The depth of the target? Always seems to be -1 on OS X. self.levels_to = levels_to #: The (POSIX) name of the target's containing folder. *(optional)* self.folder_name = folder_name #: The path from the volume root as a sequence of CNIDs. *(optional)* self.cnid_path = cnid_path #: The Carbon path of the target *(optional)* self.carbon_path = carbon_path #: The POSIX path of the target relative to the volume root. Note #: that this may or may not have a leading '/' character, but it is #: always relative to the containing volume. *(optional)* self.posix_path = posix_path #: If the path points into a user's home folder, the number of folders #: deep that we go before we get to that home folder. *(optional)* self.user_home_prefix_len = user_home_prefix_len def __repr__(self): args = [ "kind", "filename", "folder_cnid", "cnid", "creation_date", "creator_code", "type_code", ] values = [] for a in args: v = getattr(self, a) values.append(repr(v)) if self.levels_from != -1: values.append("levels_from=%r" % self.levels_from) if self.levels_to != -1: values.append("levels_to=%r" % self.levels_to) kwargs = [ "folder_name", "cnid_path", "carbon_path", "posix_path", "user_home_prefix_len", ] for a in kwargs: v = getattr(self, a) values.append(f"{a}={v!r}") return "TargetInfo(%s)" % ",".join(values) TAG_CARBON_FOLDER_NAME = 0 TAG_CNID_PATH = 1 TAG_CARBON_PATH = 2 TAG_APPLESHARE_ZONE = 3 TAG_APPLESHARE_SERVER_NAME = 4 TAG_APPLESHARE_USERNAME = 5 TAG_DRIVER_NAME = 6 TAG_NETWORK_MOUNT_INFO = 9 TAG_DIALUP_INFO = 10 TAG_UNICODE_FILENAME = 14 TAG_UNICODE_VOLUME_NAME = 15 TAG_HIGH_RES_VOLUME_CREATION_DATE = 16 TAG_HIGH_RES_CREATION_DATE = 17 TAG_POSIX_PATH = 18 TAG_POSIX_PATH_TO_MOUNTPOINT = 19 TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE = 20 TAG_USER_HOME_LENGTH_PREFIX = 21 class Alias: def __init__( self, appinfo=b"\0\0\0\0", version=2, volume=None, target=None, extra=[], ): """Construct a new :class:`Alias` object with the specified contents.""" #: Application specific information (four byte byte-string) self.appinfo = appinfo #: Version (we support versions 2 and 3) self.version = version #: A :class:`VolumeInfo` object describing the target's volume self.volume = volume #: A :class:`TargetInfo` object describing the target self.target = target #: A list of extra `(tag, value)` pairs self.extra = list(extra) @classmethod def _from_fd(cls, b): appinfo, recsize, version = struct.unpack(b">4shh", b.read(8)) if recsize < 150: raise ValueError("Incorrect alias length") if version not in (2, 3): raise ValueError("Unsupported alias version %u" % version) if version == 2: ( kind, # h volname, # 28p voldate, # I fstype, # 2s disktype, # h folder_cnid, # I filename, # 64p cnid, # I crdate, # I creator_code, # 4s type_code, # 4s levels_from, # h levels_to, # h volattrs, # I volfsid, # 2s reserved, # 10s ) = struct.unpack(b">h28pI2shI64pII4s4shhI2s10s", b.read(142)) else: ( kind, # h voldate_hr, # Q fstype, # 4s disktype, # h folder_cnid, # I cnid, # I crdate_hr, # Q volattrs, # I reserved, # 14s ) = struct.unpack(b">hQ4shIIQI14s", b.read(46)) volname = b"" filename = b"" creator_code = None type_code = None voldate = voldate_hr / 65536.0 crdate = crdate_hr / 65536.0 voldate = mac_epoch + datetime.timedelta(seconds=voldate) crdate = mac_epoch + datetime.timedelta(seconds=crdate) alias = Alias() alias.appinfo = appinfo alias.volume = VolumeInfo( volname.decode().replace("/", ":"), voldate, fstype, disktype, volattrs, volfsid, ) alias.target = TargetInfo( kind, filename.decode().replace("/", ":"), folder_cnid, cnid, crdate, creator_code, type_code, ) alias.target.levels_from = levels_from alias.target.levels_to = levels_to tag = struct.unpack(b">h", b.read(2))[0] while tag != -1: length = struct.unpack(b">h", b.read(2))[0] value = b.read(length) if length & 1: b.read(1) if tag == TAG_CARBON_FOLDER_NAME: alias.target.folder_name = value.decode().replace("/", ":") elif tag == TAG_CNID_PATH: alias.target.cnid_path = struct.unpack(">%uI" % (length // 4), value) elif tag == TAG_CARBON_PATH: alias.target.carbon_path = value elif tag == TAG_APPLESHARE_ZONE: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.zone = value elif tag == TAG_APPLESHARE_SERVER_NAME: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.server = value elif tag == TAG_APPLESHARE_USERNAME: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.user = value elif tag == TAG_DRIVER_NAME: alias.volume.driver_name = value elif tag == TAG_NETWORK_MOUNT_INFO: alias.volume.network_mount_info = value elif tag == TAG_DIALUP_INFO: alias.volume.dialup_info = value elif tag == TAG_UNICODE_FILENAME: alias.target.filename = value[2:].decode("utf-16be") elif tag == TAG_UNICODE_VOLUME_NAME: alias.volume.name = value[2:].decode("utf-16be") elif tag == TAG_HIGH_RES_VOLUME_CREATION_DATE: seconds = struct.unpack(b">Q", value)[0] / 65536.0 alias.volume.creation_date = mac_epoch + datetime.timedelta( seconds=seconds ) elif tag == TAG_HIGH_RES_CREATION_DATE: seconds = struct.unpack(b">Q", value)[0] / 65536.0 alias.target.creation_date = mac_epoch + datetime.timedelta( seconds=seconds ) elif tag == TAG_POSIX_PATH: alias.target.posix_path = value.decode() elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT: alias.volume.posix_path = value.decode() elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE: alias.volume.disk_image_alias = Alias.from_bytes(value) elif tag == TAG_USER_HOME_LENGTH_PREFIX: alias.target.user_home_prefix_len = struct.unpack(b">h", value)[0] else: alias.extra.append((tag, value)) tag = struct.unpack(b">h", b.read(2))[0] return alias @classmethod def from_bytes(cls, bytes): """Construct an :class:`Alias` object given binary Alias data.""" with io.BytesIO(bytes) as b: return cls._from_fd(b) @classmethod def for_file(cls, path): """Create an :class:`Alias` that points at the specified file.""" if sys.platform != "darwin": raise Exception("Not implemented (requires special support)") path = encode_utf8(path) a = Alias() # Find the filesystem st = osx.statfs(path) vol_path = st.f_mntonname # File and folder names in HFS+ are normalized to a form similar to NFD. # Must be normalized (NFD->NFC) before use to avoid unicode string comparison issues. vol_path = normalize("NFC", vol_path.decode("utf-8")).encode("utf-8") # Grab its attributes attrs = [osx.ATTR_CMN_CRTIME, osx.ATTR_VOL_NAME, 0, 0, 0] volinfo = osx.getattrlist(vol_path, attrs, 0) vol_crtime = volinfo[0] vol_name = encode_utf8(volinfo[1]) # Also grab various attributes of the file attrs = [ osx.ATTR_CMN_OBJTYPE | osx.ATTR_CMN_CRTIME | osx.ATTR_CMN_FNDRINFO | osx.ATTR_CMN_FILEID | osx.ATTR_CMN_PARENTID, 0, 0, 0, 0, ] info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW) if info[0] == osx.VDIR: kind = ALIAS_KIND_FOLDER else: kind = ALIAS_KIND_FILE cnid = info[3] folder_cnid = info[4] dirname, filename = os.path.split(path) if dirname == b"" or dirname == b".": dirname = os.getcwd() foldername = os.path.basename(dirname) creation_date = info[1] if kind == ALIAS_KIND_FILE: creator_code = struct.pack(b"I", info[2].fileInfo.fileCreator) type_code = struct.pack(b"I", info[2].fileInfo.fileType) else: creator_code = b"\0\0\0\0" type_code = b"\0\0\0\0" a.target = TargetInfo( kind, filename, folder_cnid, cnid, creation_date, creator_code, type_code ) a.volume = VolumeInfo(vol_name, vol_crtime, b"H+", ALIAS_FIXED_DISK, 0, b"\0\0") a.target.folder_name = foldername a.volume.posix_path = vol_path rel_path = os.path.relpath(path, vol_path) # Leave off the initial '/' if vol_path is '/' (no idea why) if vol_path == b"/": a.target.posix_path = rel_path else: a.target.posix_path = b"/" + rel_path # Construct the Carbon and CNID paths carbon_path = [] cnid_path = [] head, tail = os.path.split(rel_path) if not tail: head, tail = os.path.split(head) while head or tail: if head: attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0] info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0) cnid_path.append(info[0]) carbon_tail = tail.replace(b":", b"/") carbon_path.insert(0, carbon_tail) head, tail = os.path.split(head) carbon_path = vol_name + b":" + b":\0".join(carbon_path) a.target.carbon_path = carbon_path a.target.cnid_path = cnid_path return a def _to_fd(self, b): # We'll come back and fix the length when we're done pos = b.tell() b.write(struct.pack(b">4shh", self.appinfo, 0, self.version)) carbon_volname = encode_utf8(self.volume.name).replace(b":", b"/") carbon_filename = encode_utf8(self.target.filename).replace(b":", b"/") voldate = (self.volume.creation_date - mac_epoch).total_seconds() crdate = (self.target.creation_date - mac_epoch).total_seconds() if self.version == 2: # NOTE: crdate should be in local time, but that's system dependent # (so doing so is ridiculous, and nothing could rely on it). b.write( struct.pack( b">h28pI2shI64pII4s4shhI2s10s", self.target.kind, # h carbon_volname, # 28p int(voldate), # I self.volume.fs_type, # 2s self.volume.disk_type, # h self.target.folder_cnid, # I carbon_filename, # 64p self.target.cnid, # I int(crdate), # I self.target.creator_code, # 4s self.target.type_code, # 4s self.target.levels_from, # h self.target.levels_to, # h self.volume.attribute_flags, # I self.volume.fs_id, # 2s b"\0" * 10, # 10s ) ) else: b.write( struct.pack( b">hQ4shIIQI14s", self.target.kind, # h int(voldate * 65536), # Q self.volume.fs_type, # 4s self.volume.disk_type, # h self.target.folder_cnid, # I self.target.cnid, # I int(crdate * 65536), # Q self.volume.attribute_flags, # I b"\0" * 14, # 14s ) ) # Excuse the odd order; we're copying Finder if self.target.folder_name: carbon_foldername = encode_utf8(self.target.folder_name).replace(b":", b"/") b.write(struct.pack(b">hh", TAG_CARBON_FOLDER_NAME, len(carbon_foldername))) b.write(carbon_foldername) if len(carbon_foldername) & 1: b.write(b"\0") b.write( struct.pack( b">hhQhhQ", TAG_HIGH_RES_VOLUME_CREATION_DATE, 8, int(voldate * 65536), TAG_HIGH_RES_CREATION_DATE, 8, int(crdate * 65536), ) ) if self.target.cnid_path: cnid_path = struct.pack( ">%uI" % len(self.target.cnid_path), *self.target.cnid_path ) b.write(struct.pack(b">hh", TAG_CNID_PATH, len(cnid_path))) b.write(cnid_path) if self.target.carbon_path: carbon_path = encode_utf8(self.target.carbon_path) b.write(struct.pack(b">hh", TAG_CARBON_PATH, len(carbon_path))) b.write(carbon_path) if len(carbon_path) & 1: b.write(b"\0") if self.volume.appleshare_info: ai = self.volume.appleshare_info if ai.zone: b.write(struct.pack(b">hh", TAG_APPLESHARE_ZONE, len(ai.zone))) b.write(ai.zone) if len(ai.zone) & 1: b.write(b"\0") if ai.server: b.write(struct.pack(b">hh", TAG_APPLESHARE_SERVER_NAME, len(ai.server))) b.write(ai.server) if len(ai.server) & 1: b.write(b"\0") if ai.username: b.write(struct.pack(b">hh", TAG_APPLESHARE_USERNAME, len(ai.username))) b.write(ai.username) if len(ai.username) & 1: b.write(b"\0") if self.volume.driver_name: driver_name = encode_utf8(self.volume.driver_name) b.write(struct.pack(b">hh", TAG_DRIVER_NAME, len(driver_name))) b.write(driver_name) if len(driver_name) & 1: b.write(b"\0") if self.volume.network_mount_info: b.write( struct.pack( b">hh", TAG_NETWORK_MOUNT_INFO, len(self.volume.network_mount_info) ) ) b.write(self.volume.network_mount_info) if len(self.volume.network_mount_info) & 1: b.write(b"\0") if self.volume.dialup_info: b.write( struct.pack( b">hh", TAG_DIALUP_INFO, len(self.volume.network_mount_info) ) ) b.write(self.volume.network_mount_info) if len(self.volume.network_mount_info) & 1: b.write(b"\0") utf16 = decode_utf8(self.target.filename).replace(":", "/").encode("utf-16-be") b.write( struct.pack(b">hhh", TAG_UNICODE_FILENAME, len(utf16) + 2, len(utf16) // 2) ) b.write(utf16) utf16 = decode_utf8(self.volume.name).replace(":", "/").encode("utf-16-be") b.write( struct.pack( b">hhh", TAG_UNICODE_VOLUME_NAME, len(utf16) + 2, len(utf16) // 2 ) ) b.write(utf16) if self.target.posix_path: posix_path = encode_utf8(self.target.posix_path) b.write(struct.pack(b">hh", TAG_POSIX_PATH, len(posix_path))) b.write(posix_path) if len(posix_path) & 1: b.write(b"\0") if self.volume.posix_path: posix_path = encode_utf8(self.volume.posix_path) b.write(struct.pack(b">hh", TAG_POSIX_PATH_TO_MOUNTPOINT, len(posix_path))) b.write(posix_path) if len(posix_path) & 1: b.write(b"\0") if self.volume.disk_image_alias: d = self.volume.disk_image_alias.to_bytes() b.write(struct.pack(b">hh", TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE, len(d))) b.write(d) if len(d) & 1: b.write(b"\0") if self.target.user_home_prefix_len is not None: b.write( struct.pack( b">hhh", TAG_USER_HOME_LENGTH_PREFIX, 2, self.target.user_home_prefix_len, ) ) for t, v in self.extra: b.write(struct.pack(b">hh", t, len(v))) b.write(v) if len(v) & 1: b.write(b"\0") b.write(struct.pack(b">hh", -1, 0)) blen = b.tell() - pos b.seek(pos + 4, os.SEEK_SET) b.write(struct.pack(b">h", blen)) def to_bytes(self): """Returns the binary representation for this :class:`Alias`.""" with io.BytesIO() as b: self._to_fd(b) return b.getvalue() def __str__(self): return "" % self.target.filename def __repr__(self): values = [] if self.appinfo != b"\0\0\0\0": values.append("appinfo=%r" % self.appinfo) if self.version != 2: values.append("version=%r" % self.version) if self.volume is not None: values.append("volume=%r" % self.volume) if self.target is not None: values.append("target=%r" % self.target) if self.extra: values.append("extra=%r" % self.extra) return "Alias(%s)" % ",".join(values) qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/LICENSE0000644000175100017510000000204515232633614026343 0ustar runnerrunnerCopyright (c) 2014 Alastair Houghton 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. qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/bookmark.py0000644000175100017510000005454715232633614027533 0ustar runnerrunner# This file implements the Apple "bookmark" format, which is the replacement # for the old-fashioned alias format. The details of this format were # reverse engineered; some things are still not entirely clear. # import datetime import os import struct import sys import uuid from urllib.parse import urljoin if sys.platform == "darwin": from . import osx from .utils import osx_epoch BMK_DATA_TYPE_MASK = 0xFFFFFF00 BMK_DATA_SUBTYPE_MASK = 0x000000FF BMK_STRING = 0x0100 BMK_DATA = 0x0200 BMK_NUMBER = 0x0300 BMK_DATE = 0x0400 BMK_BOOLEAN = 0x0500 BMK_ARRAY = 0x0600 BMK_DICT = 0x0700 BMK_UUID = 0x0800 BMK_URL = 0x0900 BMK_NULL = 0x0A00 BMK_ST_ZERO = 0x0000 BMK_ST_ONE = 0x0001 BMK_BOOLEAN_ST_FALSE = 0x0000 BMK_BOOLEAN_ST_TRUE = 0x0001 # Subtypes for BMK_NUMBER are really CFNumberType values kCFNumberSInt8Type = 1 kCFNumberSInt16Type = 2 kCFNumberSInt32Type = 3 kCFNumberSInt64Type = 4 kCFNumberFloat32Type = 5 kCFNumberFloat64Type = 6 kCFNumberCharType = 7 kCFNumberShortType = 8 kCFNumberIntType = 9 kCFNumberLongType = 10 kCFNumberLongLongType = 11 kCFNumberFloatType = 12 kCFNumberDoubleType = 13 kCFNumberCFIndexType = 14 kCFNumberNSIntegerType = 15 kCFNumberCGFloatType = 16 # Resource property flags (from CFURLPriv.h) kCFURLResourceIsRegularFile = 0x00000001 kCFURLResourceIsDirectory = 0x00000002 kCFURLResourceIsSymbolicLink = 0x00000004 kCFURLResourceIsVolume = 0x00000008 kCFURLResourceIsPackage = 0x00000010 kCFURLResourceIsSystemImmutable = 0x00000020 kCFURLResourceIsUserImmutable = 0x00000040 kCFURLResourceIsHidden = 0x00000080 kCFURLResourceHasHiddenExtension = 0x00000100 kCFURLResourceIsApplication = 0x00000200 kCFURLResourceIsCompressed = 0x00000400 kCFURLResourceIsSystemCompressed = 0x00000400 kCFURLCanSetHiddenExtension = 0x00000800 kCFURLResourceIsReadable = 0x00001000 kCFURLResourceIsWriteable = 0x00002000 kCFURLResourceIsExecutable = 0x00004000 kCFURLIsAliasFile = 0x00008000 kCFURLIsMountTrigger = 0x00010000 # Volume property flags (from CFURLPriv.h) kCFURLVolumeIsLocal = 0x1 kCFURLVolumeIsAutomount = 0x2 kCFURLVolumeDontBrowse = 0x4 kCFURLVolumeIsReadOnly = 0x8 kCFURLVolumeIsQuarantined = 0x10 kCFURLVolumeIsEjectable = 0x20 kCFURLVolumeIsRemovable = 0x40 kCFURLVolumeIsInternal = 0x80 kCFURLVolumeIsExternal = 0x100 kCFURLVolumeIsDiskImage = 0x200 kCFURLVolumeIsFileVault = 0x400 kCFURLVolumeIsLocaliDiskMirror = 0x800 kCFURLVolumeIsiPod = 0x1000 kCFURLVolumeIsiDisk = 0x2000 kCFURLVolumeIsCD = 0x4000 kCFURLVolumeIsDVD = 0x8000 kCFURLVolumeIsDeviceFileSystem = 0x10000 kCFURLVolumeSupportsPersistentIDs = 0x100000000 kCFURLVolumeSupportsSearchFS = 0x200000000 kCFURLVolumeSupportsExchange = 0x400000000 # reserved 0x800000000 kCFURLVolumeSupportsSymbolicLinks = 0x1000000000 kCFURLVolumeSupportsDenyModes = 0x2000000000 kCFURLVolumeSupportsCopyFile = 0x4000000000 kCFURLVolumeSupportsReadDirAttr = 0x8000000000 kCFURLVolumeSupportsJournaling = 0x10000000000 kCFURLVolumeSupportsRename = 0x20000000000 kCFURLVolumeSupportsFastStatFS = 0x40000000000 kCFURLVolumeSupportsCaseSensitiveNames = 0x80000000000 kCFURLVolumeSupportsCasePreservedNames = 0x100000000000 kCFURLVolumeSupportsFLock = 0x200000000000 kCFURLVolumeHasNoRootDirectoryTimes = 0x400000000000 kCFURLVolumeSupportsExtendedSecurity = 0x800000000000 kCFURLVolumeSupports2TBFileSize = 0x1000000000000 kCFURLVolumeSupportsHardLinks = 0x2000000000000 kCFURLVolumeSupportsMandatoryByteRangeLocks = 0x4000000000000 kCFURLVolumeSupportsPathFromID = 0x8000000000000 # reserved 0x10000000000000 kCFURLVolumeIsJournaling = 0x20000000000000 kCFURLVolumeSupportsSparseFiles = 0x40000000000000 kCFURLVolumeSupportsZeroRuns = 0x80000000000000 kCFURLVolumeSupportsVolumeSizes = 0x100000000000000 kCFURLVolumeSupportsRemoteEvents = 0x200000000000000 kCFURLVolumeSupportsHiddenFiles = 0x400000000000000 kCFURLVolumeSupportsDecmpFSCompression = 0x800000000000000 kCFURLVolumeHas64BitObjectIDs = 0x1000000000000000 kCFURLVolumePropertyFlagsAll = 0xFFFFFFFFFFFFFFFF BMK_URL_ST_ABSOLUTE = 0x0001 BMK_URL_ST_RELATIVE = 0x0002 # Bookmark keys kBookmarkURL = 0x1003 # A URL kBookmarkPath = 0x1004 # Array of path components kBookmarkCNIDPath = 0x1005 # Array of CNIDs kBookmarkFileProperties = ( 0x1010 # (CFURL rp flags, CFURL rp flags asked for, 8 bytes NULL) ) kBookmarkFileName = 0x1020 kBookmarkFileID = 0x1030 kBookmarkFileCreationDate = 0x1040 # = 0x1054 # ? # = 0x1055 # ? # = 0x1056 # ? # = 0x1101 # ? # = 0x1102 # ? kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs kBookmarkVolumePath = 0x2002 kBookmarkVolumeURL = 0x2005 kBookmarkVolumeName = 0x2010 kBookmarkVolumeUUID = 0x2011 # Stored (perversely) as a string kBookmarkVolumeSize = 0x2012 kBookmarkVolumeCreationDate = 0x2013 kBookmarkVolumeProperties = ( 0x2020 # (CFURL vp flags, CFURL vp flags asked for, 8 bytes NULL) ) kBookmarkVolumeIsRoot = 0x2030 # True if volume is FS root kBookmarkVolumeBookmark = 0x2040 # Embedded bookmark for disk image (TOC id) kBookmarkVolumeMountPoint = 0x2050 # A URL # = 0x2070 kBookmarkContainingFolder = 0xC001 # Index of containing folder in path kBookmarkUserName = 0xC011 # User that created bookmark kBookmarkUID = 0xC012 # UID that created bookmark kBookmarkWasFileReference = 0xD001 # True if the URL was a file reference kBookmarkCreationOptions = 0xD010 kBookmarkURLLengths = 0xE003 # See below kBookmarkDisplayName = 0xF017 kBookmarkIconData = 0xF020 kBookmarkIconRef = 0xF021 kBookmarkTypeBindingData = 0xF022 kBookmarkCreationTime = 0xF030 kBookmarkSandboxRwExtension = 0xF080 kBookmarkSandboxRoExtension = 0xF081 kBookmarkAliasData = 0xFE00 # Alias for backwards compatibility kBookmarkSecurityExtension = kBookmarkSandboxRwExtension # kBookmarkURLLengths is an array that is set if the URL encoded by the # bookmark had a base URL; in that case, each entry is the length of the # base URL in question. Thus a URL # # file:///foo/bar/baz blam/blat.html # # will result in [3, 2], while the URL # # file:///foo bar/baz blam blat.html # # would result in [1, 2, 1, 1] class Data: def __init__(self, bytedata=None): #: The bytes, stored as a byte string self.bytes = bytes(bytedata) def __repr__(self): return "Data(%r)" % self.bytes class URL: def __init__(self, base, rel=None): if rel is not None: #: The base URL, if any (a :class:`URL`) self.base = base #: The rest of the URL (a string) self.relative = rel else: self.base = None self.relative = base @property def absolute(self): """Return an absolute URL.""" if self.base is None: return self.relative else: return urljoin(self.base.absolute, self.relative) def __repr__(self): return "URL(%r)" % self.absolute class Bookmark: def __init__(self, tocs=None): if tocs is None: #: The TOCs for this Bookmark self.tocs = [] else: self.tocs = tocs @classmethod def _get_item(cls, data, hdrsize, offset): offset += hdrsize if offset > len(data) - 8: raise ValueError("Offset out of range") length, typecode = struct.unpack(b"d", databytes)[0]) return osx_epoch + secs elif dtype == BMK_BOOLEAN: if dsubtype == BMK_BOOLEAN_ST_TRUE: return True elif dsubtype == BMK_BOOLEAN_ST_FALSE: return False elif dtype == BMK_UUID: return uuid.UUID(bytes=databytes) elif dtype == BMK_URL: if dsubtype == BMK_URL_ST_ABSOLUTE: return URL(databytes.decode("utf-8")) elif dsubtype == BMK_URL_ST_RELATIVE: baseoff, reloff = struct.unpack(b" size: raise ValueError("Not a bookmark file (header size too large)") if size != len(data): raise ValueError("Not a bookmark file (truncated)") (tocoffset,) = struct.unpack(b" size - hdrsize) or (size - tocbase < 20): raise ValueError("TOC offset out of range") (tocsize, tocmagic, tocid, nexttoc, toccount) = struct.unpack( b" -0x80000000 and item < 0x7FFFFFFF: result = struct.pack(b"d", float(secs.total_seconds()) ) elif isinstance(item, uuid.UUID): result = struct.pack(b"= 6: hue -= 6 if hue < 1: return (t2 - t1) * hue + t1 elif hue < 3: return t2 elif hue < 4: return (t2 - t1) * (4 - hue) + t1 else: return t1 def to_rgb(self): hue = self.h / 60.0 if self.l <= 0.5: # noqa: E741 t2 = self.l * (self.s + 1) else: t2 = self.l + self.s - (self.l * self.s) t1 = self.l * 2 - t2 r = self._hue_to_rgb(t1, t2, hue + 2) g = self._hue_to_rgb(t1, t2, hue) b = self._hue_to_rgb(t1, t2, hue - 2) return RGB(r, g, b) class HWB(Color): def __init__(self, h, w, b): self.h = h self.w = w self.b = b @staticmethod def _hue_to_rgb(hue): if hue < 0: hue += 6 elif hue >= 6: hue -= 6 if hue < 1: return hue elif hue < 3: return 1 elif hue < 4: return 4 - hue else: return 0 def to_rgb(self): hue = self.h / 60.0 t1 = 1 - self.w - self.b r = self._hue_to_rgb(hue + 2) * t1 + self.w g = self._hue_to_rgb(hue) * t1 + self.w b = self._hue_to_rgb(hue - 2) * t1 + self.w return RGB(r, g, b) class CMYK(Color): def __init__(self, c, m, y, k): self.c = c self.m = m self.y = y self.k = k def to_rgb(self): r = 1.0 - min(1.0, self.c + self.k) g = 1.0 - min(1.0, self.m + self.k) b = 1.0 - min(1.0, self.y + self.k) return RGB(r, g, b) class Gray(Color): def __init__(self, g): self.g = g def to_rgb(self): return RGB(self.g, self.g, self.g) _x11_colors = { "aliceblue": (240, 248, 255), "antiquewhite": (250, 235, 215), "aqua": (0, 255, 255), "aquamarine": (127, 255, 212), "azure": (240, 255, 255), "beige": (245, 245, 220), "bisque": (255, 228, 196), "black": (0, 0, 0), "blanchedalmond": (255, 235, 205), "blue": (0, 0, 255), "blueviolet": (138, 43, 226), "brown": (165, 42, 42), "burlywood": (222, 184, 135), "cadetblue": (95, 158, 160), "chartreuse": (127, 255, 0), "chocolate": (210, 105, 30), "coral": (255, 127, 80), "cornflowerblue": (100, 149, 237), "cornsilk": (255, 248, 220), "crimson": (220, 20, 60), "cyan": (0, 255, 255), "darkblue": (0, 0, 139), "darkcyan": (0, 139, 139), "darkgoldenrod": (184, 134, 11), "darkgray": (169, 169, 169), "darkgreen": (0, 100, 0), "darkgrey": (169, 169, 169), "darkkhaki": (189, 183, 107), "darkmagenta": (139, 0, 139), "darkolivegreen": (85, 107, 47), "darkorange": (255, 140, 0), "darkorchid": (153, 50, 204), "darkred": (139, 0, 0), "darksalmon": (233, 150, 122), "darkseagreen": (143, 188, 143), "darkslateblue": (72, 61, 139), "darkslategray": (47, 79, 79), "darkslategrey": (47, 79, 79), "darkturquoise": (0, 206, 209), "darkviolet": (148, 0, 211), "deeppink": (255, 20, 147), "deepskyblue": (0, 191, 255), "dimgray": (105, 105, 105), "dimgrey": (105, 105, 105), "dodgerblue": (30, 144, 255), "firebrick": (178, 34, 34), "floralwhite": (255, 250, 240), "forestgreen": (34, 139, 34), "fuchsia": (255, 0, 255), "gainsboro": (220, 220, 220), "ghostwhite": (248, 248, 255), "gold": (255, 215, 0), "goldenrod": (218, 165, 32), "gray": (128, 128, 128), "grey": (128, 128, 128), "green": (0, 128, 0), "greenyellow": (173, 255, 47), "honeydew": (240, 255, 240), "hotpink": (255, 105, 180), "indianred": (205, 92, 92), "indigo": (75, 0, 130), "ivory": (255, 255, 240), "khaki": (240, 230, 140), "lavender": (230, 230, 250), "lavenderblush": (255, 240, 245), "lawngreen": (124, 252, 0), "lemonchiffon": (255, 250, 205), "lightblue": (173, 216, 230), "lightcoral": (240, 128, 128), "lightcyan": (224, 255, 255), "lightgoldenrodyellow": (250, 250, 210), "lightgray": (211, 211, 211), "lightgreen": (144, 238, 144), "lightgrey": (211, 211, 211), "lightpink": (255, 182, 193), "lightsalmon": (255, 160, 122), "lightseagreen": (32, 178, 170), "lightskyblue": (135, 206, 250), "lightslategray": (119, 136, 153), "lightslategrey": (119, 136, 153), "lightsteelblue": (176, 196, 222), "lightyellow": (255, 255, 224), "lime": (0, 255, 0), "limegreen": (50, 205, 50), "linen": (250, 240, 230), "magenta": (255, 0, 255), "maroon": (128, 0, 0), "mediumaquamarine": (102, 205, 170), "mediumblue": (0, 0, 205), "mediumorchid": (186, 85, 211), "mediumpurple": (147, 112, 219), "mediumseagreen": (60, 179, 113), "mediumslateblue": (123, 104, 238), "mediumspringgreen": (0, 250, 154), "mediumturquoise": (72, 209, 204), "mediumvioletred": (199, 21, 133), "midnightblue": (25, 25, 112), "mintcream": (245, 255, 250), "mistyrose": (255, 228, 225), "moccasin": (255, 228, 181), "navajowhite": (255, 222, 173), "navy": (0, 0, 128), "oldlace": (253, 245, 230), "olive": (128, 128, 0), "olivedrab": (107, 142, 35), "orange": (255, 165, 0), "orangered": (255, 69, 0), "orchid": (218, 112, 214), "palegoldenrod": (238, 232, 170), "palegreen": (152, 251, 152), "paleturquoise": (175, 238, 238), "palevioletred": (219, 112, 147), "papayawhip": (255, 239, 213), "peachpuff": (255, 218, 185), "peru": (205, 133, 63), "pink": (255, 192, 203), "plum": (221, 160, 221), "powderblue": (176, 224, 230), "purple": (128, 0, 128), "red": (255, 0, 0), "rosybrown": (188, 143, 143), "royalblue": (65, 105, 225), "saddlebrown": (139, 69, 19), "salmon": (250, 128, 114), "sandybrown": (244, 164, 96), "seagreen": (46, 139, 87), "seashell": (255, 245, 238), "sienna": (160, 82, 45), "silver": (192, 192, 192), "skyblue": (135, 206, 235), "slateblue": (106, 90, 205), "slategray": (112, 128, 144), "slategrey": (112, 128, 144), "snow": (255, 250, 250), "springgreen": (0, 255, 127), "steelblue": (70, 130, 180), "tan": (210, 180, 140), "teal": (0, 128, 128), "thistle": (216, 191, 216), "tomato": (255, 99, 71), "turquoise": (64, 224, 208), "violet": (238, 130, 238), "wheat": (245, 222, 179), "white": (255, 255, 255), "whitesmoke": (245, 245, 245), "yellow": (255, 255, 0), "yellowgreen": (154, 205, 50), } _ws_re = re.compile(r"\s+") _token_re = re.compile(r"[A-Za-z_][A-Za-z0-9_]*") _hex_re = re.compile(r"#([0-9a-f]{3}(?:[0-9a-f]{3})?)$", re.IGNORECASE) _number_re = re.compile(r"[0-9]*(\.[0-9]*)") class ColorParser: def __init__(self, s): self._string = s self._pos = 0 def skipws(self): m = _ws_re.match(self._string, self._pos) if m: self._pos = m.end(0) def expect(self, s, context=""): if ( len(self._string) - self._pos < len(s) or self._string[self._pos : self._pos + len(s)] != s ): raise ValueError(f'bad color "{self._string}" - expected "{s}"{context}') self._pos += len(s) def expectEnd(self): if self._pos != len(self._string): raise ValueError(f'junk at end of color "{self._string}"') def getToken(self): m = _token_re.match(self._string, self._pos) if m: token = m.group(0) self._pos = m.end(0) return token return None def parseNumber(self, context=""): m = _number_re.match(self._string, self._pos) if m: self._pos = m.end(0) return float(m.group(0)) raise ValueError(f'bad color "{self._string}" - expected a number{context}') def parseColor(self): self.skipws() token = self.getToken() if token: if token == "rgb": return self.parseRGB() elif token == "hsl": return self.parseHSL() elif token == "hwb": return self.parseHWB() elif token == "cmyk": return self.parseCMYK() elif token == "gray" or token == "grey": return self.parseGray() try: r, g, b = _x11_colors[token] except KeyError: raise ValueError(f'unknown color name "{token}"') self.expectEnd() return RGB(r / 255.0, g / 255.0, b / 255.0) m = _hex_re.match(self._string, self._pos) if m: hrgb = m.group(1) if len(hrgb) == 3: r = int("0x" + 2 * hrgb[0], 16) g = int("0x" + 2 * hrgb[1], 16) b = int("0x" + 2 * hrgb[2], 16) else: r = int("0x" + hrgb[0:2], 16) g = int("0x" + hrgb[2:4], 16) b = int("0x" + hrgb[4:6], 16) self._pos = m.end(0) self.skipws() self.expectEnd() return RGB(r / 255.0, g / 255.0, b / 255.0) raise ValueError(f'bad color syntax "{self._string}"') def parseRGB(self): self.expect("(", 'after "rgb"') self.skipws() r = self.parseValue() self.skipws() self.expect(",", 'in "rgb"') self.skipws() g = self.parseValue() self.skipws() self.expect(",", 'in "rgb"') self.skipws() b = self.parseValue() self.skipws() self.expect(")", 'at end of "rgb"') self.skipws() self.expectEnd() return RGB(r, g, b) def parseHSL(self): self.expect("(", 'after "hsl"') self.skipws() h = self.parseAngle() self.skipws() self.expect(",", 'in "hsl"') self.skipws() s = self.parseValue() self.skipws() self.expect(",", 'in "hsl"') self.skipws() l = self.parseValue() # noqa: E741 self.skipws() self.expect(")", 'at end of "hsl"') self.skipws() self.expectEnd() return HSL(h, s, l) def parseHWB(self): self.expect("(", 'after "hwb"') self.skipws() h = self.parseAngle() self.skipws() self.expect(",", 'in "hwb"') self.skipws() w = self.parseValue() self.skipws() self.expect(",", 'in "hwb"') self.skipws() b = self.parseValue() self.skipws() self.expect(")", 'at end of "hwb"') self.skipws() self.expectEnd() return HWB(h, w, b) def parseCMYK(self): self.expect("(", 'after "cmyk"') self.skipws() c = self.parseValue() self.skipws() self.expect(",", 'in "cmyk"') self.skipws() m = self.parseValue() self.skipws() self.expect(",", 'in "cmyk"') self.skipws() y = self.parseValue() self.skipws() self.expect(",", 'in "cmyk"') self.skipws() k = self.parseValue() self.skipws() self.expect(")", 'at end of "cmyk"') self.skipws() self.expectEnd() return CMYK(c, m, y, k) def parseGray(self): self.expect("(", 'after "gray"') self.skipws() g = self.parseValue() self.skipws() self.expect(")", 'at end of "gray') self.skipws() self.expectEnd() return Gray(g) def parseValue(self): n = self.parseNumber() self.skipws() if self._string[self._pos] == "%": n = n / 100.0 self.pos += 1 return n def parseAngle(self): n = self.parseNumber() self.skipws() tok = self.getToken() if tok == "rad": n = n * 180.0 / math.pi elif tok == "grad" or tok == "gon": n = n * 0.9 elif tok != "deg": raise ValueError(f'bad angle unit "{tok}"') return n _color_re = re.compile( r"\s*(#|rgb|hsl|hwb|cmyk|gray|grey|{})".format("|".join(_x11_colors.keys())) ) def isAColor(s): return _color_re.match(s) def parseColor(s): return ColorParser(s).parseColor() qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__init__.py0000644000175100017510000000013315232633614027321 0ustar runnerrunnerfrom .core import build_dmg __version__ = "1.6.7" __all__ = ["__version__", "build_dmg"] qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/qt_attribution.json0000644000175100017510000000067215232633614031163 0ustar runnerrunner{ "Id": "dmgbuild", "Name": "dmgbuild", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "macOS command line utility to build disk images", "Homepage": "https://github.com/al45tair/dmgbuild", "Version": "1.3.1", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/core.py0000644000175100017510000007035215232633614026524 0ustar runnerrunnerimport json import os import platform import plistlib import re import shutil import subprocess import tempfile import time import tokenize try: import importlib_resources as resources except ImportError: from importlib import resources from ds_store import DSStore from mac_alias import Alias from . import colors, licensing try: from . import badge except ImportError: badge = None # The first element in the platform.mac_ver() tuple is a string containing the # macOS version (e.g., '10.15.6'). Parse into an integer tuple. MACOS_VERSION = tuple(int(v) for v in platform.mac_ver()[0].split(".")) class DMGError(Exception): def __init__(self, callback, message): self.message = message callback({"type": "error::fatal", "message": message}) def __str__(self): return str(self.message) def quiet_callback(info): pass def hdiutil(cmd, *args, **kwargs): plist = kwargs.get("plist", True) all_args = ["/usr/bin/hdiutil", cmd] all_args.extend(args) if plist: all_args.append("-plist") p = subprocess.Popen( all_args, stdout=subprocess.PIPE, stderr=None if plist else subprocess.STDOUT, close_fds=True, ) output, _ = p.communicate() if plist: results = plistlib.loads(output) else: results = output.decode() retcode = p.wait() return retcode, results def load_settings(filename, settings): encoding = "utf-8" with open(filename, "rb") as fp: try: encoding = tokenize.detect_encoding(fp.readline)[0] except SyntaxError: pass with open(filename, encoding=encoding) as fp: exec(compile(fp.read(), filename, "exec"), settings, settings) def load_json(filename, settings): """Read an appdmg .json spec. Uses the defaults for appdmg, rather than the usual defaults for dmgbuild. """ with open(filename) as fp: json_data = json.load(fp) if "title" not in json_data: raise ValueError("missing 'title' in JSON settings file") if "contents" not in json_data: raise ValueError("missing 'contents' in JSON settings file") settings["volume_name"] = json_data["title"] settings["icon"] = json_data.get("icon", None) settings["badge_icon"] = json_data.get("badge-icon", None) bk = json_data.get("background", None) if bk is None: bk = json_data.get("background-color", None) if bk is not None: settings["background"] = bk settings["icon_size"] = json_data.get("icon-size", 80) tsize = json_data.get("text-size", None) if tsize is not None: settings["text_size"] = tsize wnd = json_data.get( "window", { "position": {"x": 100, "y": 100}, "size": {"width": 640, "height": 480}, }, ) pos = wnd.get("position", {"x": 100, "y": 100}) siz = wnd.get("size", {"width": 640, "height": 480}) settings["window_rect"] = ( (pos.get("x", 100), pos.get("y", 100)), (siz.get("width", 640), siz.get("height", 480)), ) settings["format"] = json_data.get("format", "UDZO") settings["filesystem"] = json_data.get("filesystem", "HFS+") settings["compression_level"] = json_data.get("compression-level", None) settings["license"] = json_data.get("license", None) settings["size"] = json_data.get("size", None) settings["shrink"] = json_data.get("shrink", True) files = [] hide = [] hide_extensions = [] symlinks = {} icon_locations = {} for fileinfo in json_data.get("contents", []): if "path" not in fileinfo: raise ValueError("missing 'path' in contents in JSON settings file") if "x" not in fileinfo: raise ValueError("missing 'x' in contents in JSON settings file") if "y" not in fileinfo: raise ValueError("missing 'y' in contents in JSON settings file") kind = fileinfo.get("type", "file") path = fileinfo["path"] name = fileinfo.get("name", os.path.basename(path.rstrip("/"))) if kind == "file": files.append((path, name)) elif kind == "link": symlinks[name] = path elif kind == "position": pass icon_locations[name] = (fileinfo["x"], fileinfo["y"]) hide_ext = fileinfo.get("hide_extension", False) if hide_ext: hide_extensions.append(name) hidden = fileinfo.get("hidden", False) if hidden: hide.append(name) settings["files"] = files settings["hide_extensions"] = hide_extensions settings["hide"] = hide settings["symlinks"] = symlinks settings["icon_locations"] = icon_locations def build_dmg( # noqa: C901 filename, volume_name, settings_file=None, settings=None, defines=None, lookForHiDPI=True, detach_retries=12, callback=quiet_callback, ): if defines is None: defines = {} if settings is None: settings = {} options = { # Default settings "filename": filename, "volume_name": volume_name, "format": "UDBZ", "filesystem": "HFS+", "compression_level": None, "size": None, "shrink": True, "files": [], "symlinks": {}, "hide": [], "hide_extensions": [], "icon": None, "badge_icon": None, "background": None, "show_status_bar": False, "show_tab_view": False, "show_toolbar": False, "show_pathbar": False, "show_sidebar": False, "sidebar_width": 180, "arrange_by": None, "grid_offset": (0, 0), "grid_spacing": 100.0, "scroll_position": (0.0, 0.0), "show_icon_preview": False, "show_item_info": False, "label_pos": "bottom", "text_size": 16.0, "icon_size": 128.0, "include_icon_view_settings": "auto", "include_list_view_settings": "auto", "list_icon_size": 16.0, "list_text_size": 12.0, "list_scroll_position": (0, 0), "list_sort_by": "name", "list_use_relative_dates": True, "list_calculate_all_sizes": False, "list_columns": ("name", "date-modified", "size", "kind", "date-added"), "list_column_widths": { "name": 300, "date-modified": 181, "date-created": 181, "date-added": 181, "date-last-opened": 181, "size": 97, "kind": 115, "label": 100, "version": 75, "comments": 300, }, "list_column_sort_directions": { "name": "ascending", "date-modified": "descending", "date-created": "descending", "date-added": "descending", "date-last-opened": "descending", "size": "descending", "kind": "ascending", "label": "ascending", "version": "ascending", "comments": "ascending", }, "window_rect": ((100, 100), (640, 280)), "default_view": "icon-view", "icon_locations": {}, "license": None, "defines": defines, } callback({"type": "build::started"}) # Execute the settings file if settings_file: callback( { "type": "operation::start", "operation": "settings::load", } ) # We now support JSON settings files using appdmg's format if settings_file.endswith(".json"): load_json(settings_file, options) else: load_settings(settings_file, options) callback( { "type": "operation::finished", "operation": "settings::load", } ) # Add any overrides options.update(settings) # Set up the finder data bounds = options["window_rect"] bounds_string = ( f"{{{{{bounds[0][0]}, {bounds[0][1]}}}, {{{bounds[1][0]}, {bounds[1][1]}}}}}" ) bwsp = { "ShowStatusBar": options["show_status_bar"], "WindowBounds": bounds_string, "ContainerShowSidebar": False, "PreviewPaneVisibility": False, "SidebarWidth": options["sidebar_width"], "ShowTabView": options["show_tab_view"], "ShowToolbar": options["show_toolbar"], "ShowPathbar": options["show_pathbar"], "ShowSidebar": options["show_sidebar"], } arrange_options = { "name": "name", "date-modified": "dateModified", "date-created": "dateCreated", "date-added": "dateAdded", "date-last-opened": "dateLastOpened", "size": "size", "kind": "kind", "label": "label", } icvp = { "viewOptionsVersion": 1, "backgroundType": 0, "backgroundColorRed": 1.0, "backgroundColorGreen": 1.0, "backgroundColorBlue": 1.0, "gridOffsetX": float(options["grid_offset"][0]), "gridOffsetY": float(options["grid_offset"][1]), "gridSpacing": float(options["grid_spacing"]), "arrangeBy": str(arrange_options.get(options["arrange_by"], "none")), "showIconPreview": bool(options["show_icon_preview"]), "showItemInfo": bool(options["show_item_info"]), "labelOnBottom": options["label_pos"] == "bottom", "textSize": float(options["text_size"]), "iconSize": float(options["icon_size"]), "scrollPositionX": float(options["scroll_position"][0]), "scrollPositionY": float(options["scroll_position"][1]), } background = options["background"] columns = { "name": "name", "date-modified": "dateModified", "date-created": "dateCreated", "date-added": "dateAdded", "date-last-opened": "dateLastOpened", "size": "size", "kind": "kind", "label": "label", "version": "version", "comments": "comments", } default_widths = { "name": 300, "date-modified": 181, "date-created": 181, "date-added": 181, "date-last-opened": 181, "size": 97, "kind": 115, "label": 100, "version": 75, "comments": 300, } default_sort_directions = { "name": "ascending", "date-modified": "descending", "date-created": "descending", "date-added": "descending", "date-last-opened": "descending", "size": "descending", "kind": "ascending", "label": "ascending", "version": "ascending", "comments": "ascending", } lsvp = { "viewOptionsVersion": 1, "sortColumn": columns.get(options["list_sort_by"], "name"), "textSize": float(options["list_text_size"]), "iconSize": float(options["list_icon_size"]), "showIconPreview": options["show_icon_preview"], "scrollPositionX": options["list_scroll_position"][0], "scrollPositionY": options["list_scroll_position"][1], "useRelativeDates": options["list_use_relative_dates"], "calculateAllSizes": options["list_calculate_all_sizes"], } lsvp["columns"] = {} cndx = {} for n, column in enumerate(options["list_columns"]): cndx[column] = n width = options["list_column_widths"].get(column, default_widths[column]) asc = ( options["list_column_sort_directions"].get( column, default_sort_directions[column] ) == "ascending" ) lsvp["columns"][columns[column]] = { "index": n, "width": width, "identifier": columns[column], "visible": True, "ascending": asc, } n = len(options["list_columns"]) for k in columns: if cndx.get(k) is None: cndx[k] = n width = default_widths[k] asc = default_sort_directions[k] == "ascending" lsvp["columns"][columns[column]] = { "index": n, "width": width, "identifier": columns[column], "visible": False, "ascending": asc, } n += 1 default_view = options["default_view"] views = { "icon-view": b"icnv", "column-view": b"clmv", "list-view": b"Nlsv", "coverflow": b"Flwv", } icvl = (b"type", views.get(default_view, "icnv")) include_icon_view_settings = default_view == "icon-view" or options[ "include_icon_view_settings" ] not in ("auto", "no", 0, False, None) include_list_view_settings = default_view in ("list-view", "coverflow") or options[ "include_list_view_settings" ] not in ("auto", "no", 0, False, None) filename = options["filename"] volume_name = options["volume_name"] # Construct a writeable image to start with dirname, basename = os.path.split(os.path.realpath(filename)) if not basename.endswith(".dmg"): basename += ".dmg" writableFile = tempfile.NamedTemporaryFile( dir=dirname, prefix=".temp", suffix=basename ) callback( { "type": "operation::start", "operation": "size::calculate", } ) total_size = options["size"] if total_size is None: # Start with a size of 128MB - this way we don't need to calculate the # size of the background image, volume icon, and .DS_Store file (and # 128 MB should be well sufficient for even the most outlandish image # sizes, like an uncompressed 5K multi-resolution TIFF) total_size = 128 * 1024 * 1024 def roundup(x, n): return x if x % n == 0 else x + n - x % n for path in options["files"]: if isinstance(path, tuple): path = path[0] if not os.path.islink(path) and os.path.isdir(path): for dirpath, _dirnames, filenames in os.walk(path): for f in filenames: fp = os.path.join(dirpath, f) total_size += roundup(os.lstat(fp).st_size, 4096) else: total_size += roundup(os.lstat(path).st_size, 4096) for name, target in options["symlinks"].items(): total_size += 4096 total_size = str(max(total_size / 1000, 1024)) + "K" callback( { "type": "operation::finished", "operation": "size::calculate", "size": total_size, } ) callback( { "type": "command::start", "command": "hdiutil::create", } ) filesystem = options["filesystem"].upper() fs_args = "-c c=64,a=16,e=16" if filesystem != "APFS" else "" ret, output = hdiutil( "create", "-ov", "-volname", volume_name, "-fs", filesystem, "-fsargs", fs_args, "-size", total_size, writableFile.name, ) callback( { "type": "command::finished", "command": "hdiutil::create", "ret": ret, "output": output, } ) if ret: raise DMGError(callback, f"Unable to create disk image: {output}") callback( { "type": "command::start", "command": "hdiutil::attach", } ) # IDME was deprecated in macOS 10.15/Catalina; as a result, use of -noidme # started raising a warning. if MACOS_VERSION >= (10, 15): ret, output = hdiutil( "attach", "-nobrowse", "-owners", "off", writableFile.name ) else: ret, output = hdiutil( "attach", "-nobrowse", "-owners", "off", "-noidme", writableFile.name ) callback( { "type": "command::finished", "command": "hdiutil::attach", "ret": ret, "output": output, } ) if ret: raise DMGError(callback, f"Unable to attach disk image: {output}") callback( { "type": "operation::start", "operation": "dmg::create", } ) try: for info in output["system-entities"]: if info.get("mount-point", None): device = info["dev-entry"] mount_point = info["mount-point"] icon = options["icon"] if badge: badge_icon = options["badge_icon"] else: badge_icon = None icon_target_path = os.path.join(mount_point, ".VolumeIcon.icns") if icon: shutil.copyfile(icon, icon_target_path) elif badge_icon: badge.badge_disk_icon(badge_icon, icon_target_path) if icon or badge_icon: subprocess.call(["/usr/bin/SetFile", "-a", "C", mount_point]) callback( { "type": "operation::start", "operation": "background::create", } ) if not isinstance(background, str): pass elif colors.isAColor(background): c = colors.parseColor(background).to_rgb() icvp["backgroundType"] = 1 icvp["backgroundColorRed"] = float(c.r) icvp["backgroundColorGreen"] = float(c.g) icvp["backgroundColorBlue"] = float(c.b) else: if os.path.isfile(background): # look to see if there are HiDPI resources available if lookForHiDPI is True: name, extension = os.path.splitext(os.path.basename(background)) orderedImages = [background] imageDirectory = os.path.dirname(background) if imageDirectory == "": imageDirectory = "." for candidateName in os.listdir(imageDirectory): hasScale = re.match( r"^(?P.+)@(?P\d+)x(?P\.\w+)$", candidateName, ) if ( hasScale and name == hasScale.group("name") and extension == hasScale.group("extension") ): scale = int(hasScale.group("scale")) if len(orderedImages) < scale: orderedImages += [None] * (scale - len(orderedImages)) orderedImages[scale - 1] = os.path.join( imageDirectory, candidateName ) if len(orderedImages) > 1: # compile the grouped tiff backgroundFile = tempfile.NamedTemporaryFile(suffix=".tiff") background = backgroundFile.name output = tempfile.TemporaryFile(mode="w+") try: subprocess.check_call( ["/usr/bin/tiffutil", "-cathidpicheck"] + list(filter(None, orderedImages)) + ["-out", background], stdout=output, stderr=output, ) except Exception as e: output.seek(0) raise ValueError( f"unable to compile combined HiDPI file {background!r} " f"got error: {str(e)}\noutput: {output.read()}" ) _, kind = os.path.splitext(background) path_in_image = os.path.join(mount_point, ".background" + kind) shutil.copyfile(background, path_in_image) else: dmg_resources = resources.files("dmgbuild") bg_resource = dmg_resources.joinpath( "resources/" + background + ".tiff" ) if bg_resource.is_file(): path_in_image = os.path.join(mount_point, ".background.tiff") with bg_resource.open("rb") as in_file: with open(path_in_image, "wb") as out_file: out_file.write(in_file.read()) else: raise ValueError(f'background file "{background}" not found') alias = Alias.for_file(path_in_image) icvp["backgroundType"] = 2 icvp["backgroundImageAlias"] = alias.to_bytes() callback( { "type": "operation::finished", "operation": "background::create", } ) callback( { "type": "operation::start", "operation": "files::add", "total": len(options["files"]), } ) for f in options["files"]: if isinstance(f, tuple): f_in_image = os.path.join(mount_point, f[1]) f = f[0] else: basename = os.path.basename(f.rstrip("/")) f_in_image = os.path.join(mount_point, basename) callback( { "type": "operation::start", "operation": "file::add", "file": f_in_image, } ) # use system ditto command to preserve code signing, etc. subprocess.call(["/usr/bin/ditto", f, f_in_image]) callback( { "type": "operation::finished", "operation": "file::add", "file": f_in_image, } ) callback( { "type": "operation::finished", "operation": "files::add", } ) callback( { "type": "operation::start", "operation": "symlinks::add", "total": len(options["symlinks"]), } ) for name, target in options["symlinks"].items(): name_in_image = os.path.join(mount_point, name) callback( { "type": "operation::start", "operation": "symlink::add", "file": name_in_image, "target": target, } ) os.symlink(target, name_in_image) callback( { "type": "operation::finished", "operation": "symlink::add", "file": name_in_image, "target": target, } ) callback( { "type": "operation::finished", "operation": "symlinks::add", } ) callback( { "type": "operation::start", "operation": "extensions::hide", } ) to_hide = [] for name in options["hide_extensions"]: name_in_image = os.path.join(mount_point, name) to_hide.append(name_in_image) if to_hide: subprocess.call(["/usr/bin/SetFile", "-a", "E"] + to_hide) to_hide = [] for name in options["hide"]: name_in_image = os.path.join(mount_point, name) to_hide.append(name_in_image) if to_hide: subprocess.call(["/usr/bin/SetFile", "-a", "V"] + to_hide) callback( { "type": "operation::finished", "operation": "extensions::hide", } ) userfn = options.get("create_hook") if callable(userfn): userfn(mount_point, options) callback( { "type": "operation::start", "operation": "dsstore::create", } ) image_dsstore = os.path.join(mount_point, ".DS_Store") with DSStore.open(image_dsstore, "w+") as d: d["."]["vSrn"] = ("long", 1) d["."]["bwsp"] = bwsp if include_icon_view_settings: d["."]["icvp"] = icvp if include_list_view_settings: d["."]["lsvp"] = lsvp d["."]["icvl"] = icvl for k, v in options["icon_locations"].items(): d[k]["Iloc"] = v callback( { "type": "operation::finished", "operation": "dsstore::create", } ) # Delete .Trashes, if it gets created shutil.rmtree(os.path.join(mount_point, ".Trashes"), True) except Exception: # Always try to detach hdiutil("detach", "-force", device, plist=False) raise callback( { "type": "operation::finished", "operation": "dmg::create", } ) # Flush writes before attempting to detach. subprocess.check_call(("sync", "--file-system", mount_point)) retry_time = 1 for _ in range(detach_retries): callback( { "type": "command::start", "command": "hdiutil::detach", } ) ret, output = hdiutil("detach", device, plist=False) callback( { "type": "command::finished", "command": "hdiutil::detach", "ret": ret, "output": output, } ) if not ret: break # Exponentially backoff retries retry_time *= 1.5 time.sleep(retry_time) if ret: hdiutil("detach", "-force", device, plist=False) raise DMGError(callback, f"Unable to detach device cleanly: {output}") # Shrink the output to the minimum possible size if options["shrink"]: callback( { "type": "command::start", "command": "hdiutil::resize", } ) ret, output = hdiutil( "resize", "-quiet", "-sectors", "min", writableFile.name, plist=False ) callback( { "type": "command::finished", "command": "hdiutil::resize", "ret": ret, "output": output, } ) if ret: raise DMGError(callback, f"Unable to shrink: {output}") callback( { "type": "operation::start", "operation": "dmg::shrink", } ) key_prefix = {"UDZO": "zlib", "UDBZ": "bzip2", "ULFO": "lzfse", "ULMO": "lzma"} compression_level = options["compression_level"] if options["format"] in key_prefix and compression_level: compression_args = [ "-imagekey", key_prefix[options["format"]] + "-level=" + str(compression_level), ] else: compression_args = [] callback( { "type": "command::start", "command": "hdiutil::convert", } ) ret, output = hdiutil( "convert", writableFile.name, "-format", options["format"], "-ov", "-o", filename, *compression_args, ) callback( { "type": "command::finished", "command": "hdiutil::convert", "ret": ret, "output": output, } ) if ret: raise DMGError(callback, f"Unable to convert: {output}") callback( { "type": "operation::finished", "operation": "dmg::shrink", } ) if options["license"]: callback( { "type": "operation::start", "command": "dmg::addlicense", } ) licenseDict = licensing.build_license(options["license"]) tempLicenseFile = open(os.path.join(dirname, "license.plist"), "wb") plistlib.dump(licenseDict, tempLicenseFile) tempLicenseFile.close() # see https://developer.apple.com/forums/thread/668084 ret, output = hdiutil( "udifrez", "-xml", tempLicenseFile.name, "", "-quiet", filename, plist=False ) os.remove(tempLicenseFile.name) if ret: raise DMGError(callback, f"Unable to add license: {output}") callback( { "type": "operation::finished", "command": "dmg::addlicense", } ) callback({"type": "build::finished"}) qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/LICENSE0000644000175100017510000000204515232633614026221 0ustar runnerrunnerCopyright (c) 2014 Alastair Houghton 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. qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__main__.py0000644000175100017510000000344215232633614027310 0ustar runnerrunner#! /usr/bin/env python3 import argparse from .core import build_dmg def main(): parser = argparse.ArgumentParser(description="Construct a disk image file.") parser.add_argument( "volume_name", metavar="volume-name", help=( "The name to give to the volume (this will appear in the title " "bar when the user mounts the disk image)." ), ) parser.add_argument( "filename", metavar="output.dmg", help="The filename of the disk image to create.", ) parser.add_argument("-s", "--settings", help="The path of the settings file.") parser.add_argument( "-D", dest="defines", action="append", default=[], help="Define a value for the settings file (e.g. -Dfoo=bar).", ) parser.add_argument( "--no-hidpi", dest="lookForHiDPI", action="store_false", default=True, help="Do not search for HiDPI versions of the background image (if specified)", ) parser.add_argument( "--detach-retries", dest="detachRetries", type=int, default=5, choices=range(1, 31), help="Number of attempts to detach disk volume (1 sec. interval)", ) args = parser.parse_args() defines = {} for d in args.defines: k, v = d.split("=", 1) k = k.strip() v = v.strip() if (v.startswith("'") and v.endswith("'")) or ( v.startswith('"') and v.endswith('"') ): v = v[1:-1] defines[k] = v build_dmg( args.filename, args.volume_name, args.settings, defines=defines, lookForHiDPI=args.lookForHiDPI, detach_retries=args.detachRetries, ) if __name__ == "__main__": main() qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/badge.py0000644000175100017510000001403615232633614026633 0ustar runnerrunnerimport math from Quartz import ( CFURLCreateWithFileSystemPath, CGBitmapContextCreate, CGBitmapContextCreateImage, CGColorSpaceCreateWithName, CGImageDestinationAddImage, CGImageDestinationCreateWithURL, CGImageDestinationFinalize, CGImageSourceCopyPropertiesAtIndex, CGImageSourceCreateImageAtIndex, CGImageSourceCreateWithURL, CGImageSourceGetCount, CIContext, CIFilter, CIImage, CIVector, NSAffineTransform, kCFURLPOSIXPathStyle, kCGColorSpaceGenericRGB, kCGImageAlphaPremultipliedLast, kCIInputAspectRatioKey, kCIInputBackgroundImageKey, kCIInputImageKey, kCIInputScaleKey, kCIOutputImageKey, ) _REMOVABLE_DISK_PATH = ( "/System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Removable.icns" ) def badge_disk_icon(badge_file, output_file): # Load the Removable disk icon url = CFURLCreateWithFileSystemPath( None, _REMOVABLE_DISK_PATH, kCFURLPOSIXPathStyle, False ) backdrop = CGImageSourceCreateWithURL(url, None) backdropCount = CGImageSourceGetCount(backdrop) # Load the badge url = CFURLCreateWithFileSystemPath(None, badge_file, kCFURLPOSIXPathStyle, False) badge = CGImageSourceCreateWithURL(url, None) assert badge is not None, f"Unable to process image file: {badge_file}" badgeCount = CGImageSourceGetCount(badge) # Set up a destination for our target url = CFURLCreateWithFileSystemPath(None, output_file, kCFURLPOSIXPathStyle, False) target = CGImageDestinationCreateWithURL(url, "com.apple.icns", backdropCount, None) # Get the RGB colorspace rgbColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) # Scale scale = 1.0 # Perspective transform corners = ((0.2, 0.95), (0.8, 0.95), (0.85, 0.35), (0.15, 0.35)) # Translation position = (0.5, 0.5) for n in range(backdropCount): props = CGImageSourceCopyPropertiesAtIndex(backdrop, n, None) width = props["PixelWidth"] height = props["PixelHeight"] dpi = props["DPIWidth"] depth = props["Depth"] # Choose the best sized badge image bestWidth = None # ?? bestHeight = None bestBadge = None bestDepth = None # ?? bestDPI = None for m in range(badgeCount): badgeProps = CGImageSourceCopyPropertiesAtIndex(badge, m, None) badgeWidth = badgeProps["PixelWidth"] # ?? badgeHeight = badgeProps['PixelHeight'] badgeDPI = badgeProps["DPIWidth"] badgeDepth = badgeProps["Depth"] if bestBadge is None or ( badgeWidth <= width and ( bestWidth > width or badgeWidth > bestWidth or ( badgeWidth == bestWidth and badgeDPI == dpi and badgeDepth <= depth and (bestDepth is None or badgeDepth > bestDepth) ) ) ): bestBadge = m bestWidth = badgeWidth # ?? bestHeight = badgeHeight # ?? bestDPI = badgeDPI bestDepth = badgeDepth badgeImage = CGImageSourceCreateImageAtIndex(badge, bestBadge, None) badgeCI = CIImage.imageWithCGImage_(badgeImage) backgroundImage = CGImageSourceCreateImageAtIndex(backdrop, n, None) backgroundCI = CIImage.imageWithCGImage_(backgroundImage) compositor = CIFilter.filterWithName_("CISourceOverCompositing") lanczos = CIFilter.filterWithName_("CILanczosScaleTransform") perspective = CIFilter.filterWithName_("CIPerspectiveTransform") transform = CIFilter.filterWithName_("CIAffineTransform") lanczos.setValue_forKey_(badgeCI, kCIInputImageKey) lanczos.setValue_forKey_(scale * float(width) / bestWidth, kCIInputScaleKey) lanczos.setValue_forKey_(1.0, kCIInputAspectRatioKey) topLeft = (width * scale * corners[0][0], width * scale * corners[0][1]) topRight = (width * scale * corners[1][0], width * scale * corners[1][1]) bottomRight = (width * scale * corners[2][0], width * scale * corners[2][1]) bottomLeft = (width * scale * corners[3][0], width * scale * corners[3][1]) out = lanczos.valueForKey_(kCIOutputImageKey) if width >= 16: perspective.setValue_forKey_(out, kCIInputImageKey) perspective.setValue_forKey_( CIVector.vectorWithX_Y_(*topLeft), "inputTopLeft" ) perspective.setValue_forKey_( CIVector.vectorWithX_Y_(*topRight), "inputTopRight" ) perspective.setValue_forKey_( CIVector.vectorWithX_Y_(*bottomRight), "inputBottomRight" ) perspective.setValue_forKey_( CIVector.vectorWithX_Y_(*bottomLeft), "inputBottomLeft" ) out = perspective.valueForKey_(kCIOutputImageKey) tfm = NSAffineTransform.transform() tfm.translateXBy_yBy_( math.floor((position[0] - 0.5 * scale) * width), math.floor((position[1] - 0.5 * scale) * height), ) transform.setValue_forKey_(out, kCIInputImageKey) transform.setValue_forKey_(tfm, "inputTransform") out = transform.valueForKey_(kCIOutputImageKey) compositor.setValue_forKey_(out, kCIInputImageKey) compositor.setValue_forKey_(backgroundCI, kCIInputBackgroundImageKey) result = compositor.valueForKey_(kCIOutputImageKey) cgContext = CGBitmapContextCreate( None, width, height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast ) context = CIContext.contextWithCGContext_options_(cgContext, None) context.drawImage_inRect_fromRect_( result, ((0, 0), (width, height)), ((0, 0), (width, height)) ) image = CGBitmapContextCreateImage(cgContext) CGImageDestinationAddImage(target, image, props) CGImageDestinationFinalize(target) qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/0000755000175100017510000000000015232633614025246 5ustar runnerrunnerqbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__init__.py0000644000175100017510000000016615232633614027362 0ustar runnerrunnerfrom .store import DSStore, DSStoreEntry __version__ = "1.3.1" __all__ = ["__version__", "DSStore", "DSStoreEntry"] qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/qt_attribution.json0000644000175100017510000000067015232633614031214 0ustar runnerrunner{ "Id": "ds_store", "Name": "ds_store", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "Manipulate Finder .DS_Store files from Python", "Homepage": "https://github.com/al45tair/ds_store", "Version": "1.1.2", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/LICENSE0000644000175100017510000000204515232633614026254 0ustar runnerrunnerCopyright (c) 2014 Alastair Houghton 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. qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__main__.py0000644000175100017510000000537315232633614027350 0ustar runnerrunner#!/usr/bin/env python # # ds_store: Examine .DS_Store files. # import argparse import os import os.path import pprint import re import sys from ds_store import DSStore from ds_store.buddy import BuddyError _not_printable_re = re.compile(rb"[\x00-\x1f\x7f-\x9f]") def usage(): print(main.__doc__) sys.exit(0) def chunks(iterable, length): for i in range(0, len(iterable), length): yield i, iterable[i : i + length] def pretty(value): if isinstance(value, dict): return f"{{\n {pprint.pformat(value, indent=4)[1:-1]}\n}}" elif isinstance(value, bytearray): lines = ["["] for offset, chunk in chunks(value, 16): printable_chunk = _not_printable_re.sub(b".", chunk).decode("latin-1") hex_line = " ".join([f"{b:02x}" for b in chunk]) line = f" {offset:08x} {hex_line:<47s} {printable_chunk}" lines.append(line) lines.append("]") return "\n".join(lines) elif isinstance(value, bytes): return value.decode("latin-1") else: return value def main(argv): """Display the contents of the .DS_Store file at the specified path. If you specify just a directory, ds_store will inspect the .DS_Store file in that directory. If no paths are specified, ds_store will display the contents of the .DS_Store file in the current directory. """ parser = argparse.ArgumentParser(description=main.__doc__) parser.add_argument("paths", nargs="*") args = parser.parse_args(argv) if len(args.paths) == 0: args.paths = ["."] failed = False for path in args.paths: if os.path.isdir(path): path = os.path.join(path, ".DS_Store") if not os.path.exists(path) or not os.path.isfile(path): print(f"ds_store: {path} not found", file=sys.stderr) failed = True continue try: with DSStore.open(path, "r") as d: print(path) print("") max_name_len = 0 for entry in d: name_len = len(entry.filename) if name_len > max_name_len: max_name_len = name_len for entry in d: print( "{:<{width}} {} {}".format( entry.filename, entry.code.decode("latin-1"), pretty(entry.value), width=max_name_len, ) ) print("") except BuddyError as e: print(f"ds_store: {path}: {e}") failed = True if failed: sys.exit(1) if __name__ == "__main__": main(sys.argv[1:]) qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/store.py0000644000175100017510000012626715232633614026772 0ustar runnerrunnerimport plistlib import struct import mac_alias from . import buddy class ILocCodec: @staticmethod def encode(point): return struct.pack(b">IIII", point[0], point[1], 0xFFFFFFFF, 0xFFFF0000) @staticmethod def decode(bytesData): if isinstance(bytesData, bytearray): x, y = struct.unpack_from(b">II", bytes(bytesData[:8])) else: x, y = struct.unpack(b">II", bytesData[:8]) return (x, y) class PlistCodec: @staticmethod def encode(plist): return plistlib.dumps(plist, fmt=plistlib.FMT_BINARY) @staticmethod def decode(bytes): return plistlib.loads(bytes) class BookmarkCodec: @staticmethod def encode(bmk): return bmk.to_bytes() @staticmethod def decode(bytes): return mac_alias.Bookmark.from_bytes(bytes) # This list tells the code how to decode particular kinds of entry in the # .DS_Store file. This is really a convenience, and we currently only # support a tiny subset of the possible entry types. codecs = { b"Iloc": ILocCodec, b"bwsp": PlistCodec, b"lsvp": PlistCodec, b"lsvP": PlistCodec, b"icvp": PlistCodec, b"pBBk": BookmarkCodec, } class DSStoreEntry: """Holds the data from an entry in a ``.DS_Store`` file. Note that this is not meant to represent the entry itself---i.e. if you change the type or value, your changes will *not* be reflected in the underlying file. If you want to make a change, you should either use the :class:`DSStore` object's :meth:`DSStore.insert` method (which will replace a key if it already exists), or the mapping access mode for :class:`DSStore` (often simpler anyway). """ def __init__(self, filename, code, typecode, value=None): if str != bytes and type(filename) == bytes: filename = filename.decode("utf-8") if not isinstance(code, bytes): code = code.encode("latin_1") self.filename = filename self.code = code self.type = typecode self.value = value @classmethod def read(cls, block): """Read a ``.DS_Store`` entry from the containing Block.""" # First read the filename nlen = block.read(b">I")[0] filename = block.read(2 * nlen).decode("utf-16be") # Next, read the code and type code, typecode = block.read(b">4s4s") # Finally, read the data if typecode == b"bool": value = block.read(b">?")[0] elif typecode == b"long" or typecode == b"shor": value = block.read(b">I")[0] elif typecode == b"blob": vlen = block.read(b">I")[0] value = block.read(vlen) codec = codecs.get(code, None) if codec: value = codec.decode(value) typecode = codec elif typecode == b"ustr": vlen = block.read(b">I")[0] value = block.read(2 * vlen).decode("utf-16be") elif typecode == b"type": value = block.read(b">4s")[0] elif typecode == b"comp" or typecode == b"dutc": value = block.read(b">Q")[0] else: raise ValueError('Unknown type code "%s"' % typecode) return DSStoreEntry(filename, code, typecode, value) def __lt__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() return sfl < ofl or (self.filename == other.filename and self.code < other.code) def __le__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() return sfl < ofl or (sfl == ofl and self.code <= other.code) def __eq__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() return sfl == ofl and self.code == other.code def __ne__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() return sfl != ofl or self.code != other.code def __gt__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() selfCode = self.code if str != bytes and type(selfCode) is bytes: selfCode = selfCode.decode("utf-8") otherCode = other.code if str != bytes and type(otherCode) is bytes: otherCode = otherCode.decode("utf-8") return sfl > ofl or (sfl == ofl and selfCode > otherCode) def __ge__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError("Can only compare against other DSStoreEntry objects") sfl = self.filename.lower() ofl = other.filename.lower() return sfl > ofl or (sfl == ofl and self.code >= other.code) def byte_length(self): """Compute the length of this entry, in bytes.""" utf16 = self.filename.encode("utf-16be") length = 4 + len(utf16) + 8 if isinstance(self.type, str): entry_type = self.type.encode("latin_1") value = self.value elif isinstance(self.type, (bytes, str)): entry_type = self.type value = self.value else: entry_type = b"blob" value = self.type.encode(self.value) if entry_type == b"bool": length += 1 elif entry_type == b"long" or entry_type == b"shor": length += 4 elif entry_type == b"blob": length += 4 + len(value) elif entry_type == b"ustr": utf16 = value.encode("utf-16be") length += 4 + len(utf16) elif entry_type == b"type": length += 4 elif entry_type == b"comp" or entry_type == b"dutc": length += 8 else: raise ValueError('Unknown type code "%s"' % entry_type) return length def write(self, block, insert=False): """Write this entry to the specified Block.""" if insert: w = block.insert else: w = block.write if isinstance(self.type, str): entry_type = self.type.encode("latin_1") value = self.value elif isinstance(self.type, (bytes, str)): entry_type = self.type value = self.value else: entry_type = b"blob" value = self.type.encode(self.value) utf16 = self.filename.encode("utf-16be") w(b">I", len(utf16) // 2) w(utf16) w(b">4s4s", self.code, entry_type) if entry_type == b"bool": w(b">?", value) elif entry_type == b"long" or entry_type == b"shor": w(b">I", value) elif entry_type == b"blob": w(b">I", len(value)) w(value) elif entry_type == b"ustr": utf16 = value.encode("utf-16be") w(b">I", len(utf16) // 2) w(utf16) elif entry_type == b"type": if isinstance(value, str): value = value.encode("latin_1") w(b">4s", value) elif entry_type == b"comp" or entry_type == b"dutc": w(b">Q", value) else: raise ValueError('Unknown type code "%s"' % entry_type) def __repr__(self): return f"<{self.filename} {self.code}>" class DSStore: """Python interface to a ``.DS_Store`` file. Works by manipulating the file on the disk---so this code will work with ``.DS_Store`` files for. *very* large directories. A :class:`DSStore` object can be used as if it was a mapping, e.g.:: d['foobar.dat']['Iloc'] will fetch the "Iloc" record for "foobar.dat", or raise :class:`KeyError` if there is no such record. If used in this manner, the :class:`DSStore` object will return (type, value) tuples, unless the type is "blob" and the module knows how to decode it. Currently, we know how to decode "Iloc", "bwsp", "lsvp", "lsvP" and "icvp" blobs. "Iloc" decodes to an (x, y) tuple, while the others are all decoded using ``biplist`` or ``plistlib`` depending on Python version. Assignment also works, e.g.:: d['foobar.dat']['note'] = ('ustr', u'Hello World!') as does deletion with ``del``:: del d['foobar.dat']['note'] This is usually going to be the most convenient interface, though occasionally (for instance when creating a new ``.DS_Store`` file) you may wish to drop down to using :class:`DSStoreEntry` objects directly. """ def __init__(self, store): self._store = store self._superblk = self._store["DSDB"] with self._get_block(self._superblk) as s: ( self._rootnode, self._levels, self._records, self._nodes, self._page_size, ) = s.read(b">IIIII") self._min_usage = 2 * self._page_size // 3 self._dirty = False @classmethod def open(cls, file_or_name, mode="r+", initial_entries=None): """Open a ``.DS_Store`` file; pass either a Python file object, or a filename in the ``file_or_name`` argument and a file access mode in the ``mode`` argument. If you are creating a new file using the "w" or "w+" modes, you may also specify a list of entries with which to initialise the file. """ store = buddy.Allocator.open(file_or_name, mode) if mode == "w" or mode == "w+": superblk = store.allocate(20) store["DSDB"] = superblk page_size = 4096 if not initial_entries: root = store.allocate(page_size) with store.get_block(root) as rootblk: rootblk.zero_fill() with store.get_block(superblk) as s: s.write(b">IIIII", root, 0, 0, 1, page_size) else: # Make sure they're in sorted order initial_entries = list(initial_entries) initial_entries.sort() # Construct the tree current_level = initial_entries next_level = [] levels = [] ptr_size = 0 node_count = 0 while True: total = 8 nodes = [] node = [] for e in current_level: new_total = total + ptr_size + e.byte_length() if new_total > page_size: nodes.append(node) next_level.append(e) total = 8 node = [] else: total = new_total node.append(e) if node: nodes.append(node) node_count += len(nodes) levels.append(nodes) if len(nodes) == 1: break current_level = next_level next_level = [] ptr_size = 4 # Allocate nodes ptrs = [store.allocate(page_size) for n in range(node_count)] # Generate nodes pointers = [] prev_pointers = None for level in levels: ppndx = 0 lptrs = ptrs[-len(level) :] del ptrs[-len(level) :] for node in level: ndx = lptrs.pop(0) if prev_pointers is None: with store.get_block(ndx) as block: block.write(b">II", 0, len(node)) for e in node: e.write(block) else: next_node = prev_pointers[ppndx + len(node)] node_ptrs = prev_pointers[ppndx : ppndx + len(node)] with store.get_block(ndx) as block: block.write(b">II", next_node, len(node)) for ptr, e in zip(node_ptrs, node): block.write(b">I", ptr) e.write(block) pointers.append(ndx) prev_pointers = pointers pointers = [] root = prev_pointers[0] with store.get_block(superblk) as s: s.write( b">IIIII", root, len(levels), len(initial_entries), node_count, page_size, ) return DSStore(store) def _get_block(self, number): return self._store.get_block(number) def flush(self): """Flush any dirty data back to the file.""" if self._dirty: self._dirty = False with self._get_block(self._superblk) as s: s.write( b">IIIII", self._rootnode, self._levels, self._records, self._nodes, self._page_size, ) self._store.flush() def close(self): """Flush dirty data and close the underlying file.""" self.flush() self._store.close() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() # Internal B-Tree nodes look like this: # # [ next | count | (ptr0 | rec0) | (ptr1 | rec1) ... (ptrN | recN) ] # Leaf nodes look like this: # # [ 0 | count | rec0 | rec1 ... recN ] # Iterate over the tree, starting at `node' def _traverse(self, node): if node is None: node = self._rootnode with self._get_block(node) as block: next_node, count = block.read(b">II") if next_node: for n in range(count): ptr = block.read(b">I")[0] for e in self._traverse(ptr): yield e e = DSStoreEntry.read(block) yield e for e in self._traverse(next_node): yield e else: for n in range(count): e = DSStoreEntry.read(block) yield e # Display the data in `node' def _dump_node(self, node): with self._get_block(node) as block: next_node, count = block.read(b">II") print("next: %u\ncount: %u\n" % (next_node, count)) for n in range(count): if next_node: ptr = block.read(b">I")[0] print("%8u " % ptr, end=" ") else: print(" ", end=" ") e = DSStoreEntry.read(block) print(e, " (%u)" % e.byte_length()) print("used: %u" % block.tell()) # Display the data in the super block def _dump_super(self): print( "root: %u\nlevels: %u\nrecords: %u\nnodes: %u\npage-size: %u" % ( self._rootnode, self._levels, self._records, self._nodes, self._page_size, ) ) # Splits entries across two blocks, returning one pivot # # Tries to balance the block usage across the two as best it can def _split2(self, blocks, entries, pointers, before, internal): left_block = blocks[0] right_block = blocks[1] count = len(entries) # Find the feasible splits best_split = None best_diff = None total = before[count] if 8 + total <= self._page_size: # We can use a *single* node for this best_split = count else: # Split into two nodes for n in range(1, count - 1): left_size = 8 + before[n] right_size = 8 + total - before[n + 1] if left_size > self._page_size: break if right_size > self._page_size: continue diff = abs(left_size - right_size) if best_split is None or diff < best_diff: best_split = n best_diff = diff if best_split is None: return None # Write the nodes left_block.seek(0) if internal: next_node = pointers[best_split] else: next_node = 0 left_block.write(b">II", next_node, best_split) for n in range(best_split): if internal: left_block.write(b">I", pointers[n]) entries[n].write(left_block) left_block.zero_fill() if best_split == count: return [] right_block.seek(0) if internal: next_node = pointers[count] else: next_node = 0 right_block.write(b">II", next_node, count - best_split - 1) for n in range(best_split + 1, count): if internal: right_block.write(b">I", pointers[n]) entries[n].write(right_block) right_block.zero_fill() pivot = entries[best_split] return [pivot] def _split(self, node, entry, right_ptr=0): self._nodes += 1 self._dirty = True new_right = self._store.allocate(self._page_size) with self._get_block(node) as block, self._get_block(new_right) as right_block: # First, measure and extract all the elements entry_size = entry.byte_length() # ?? entry_pos = None next_node, count = block.read(b">II") if next_node: entry_size += 4 pointers = [] entries = [] before = [] total = 0 for n in range(count): pos = block.tell() if next_node: ptr = block.read(b">I")[0] pointers.append(ptr) e = DSStoreEntry.read(block) if e > entry: # ?? entry_pos = n entries.append(entry) pointers.append(right_ptr) before.append(total) total += entry_size entries.append(e) before.append(total) total += block.tell() - pos before.append(total) if next_node: pointers.append(next_node) pivot = self._split2( [block, right_block], entries, pointers, before, bool(next_node) )[0] self._records += 1 self._nodes += 1 self._dirty = True return (pivot, new_right) # Allocate a new root node containing the element `pivot' and the pointers # `left' and `right' def _new_root(self, left, pivot, right): new_root = self._store.allocate(self._page_size) with self._get_block(new_root) as block: block.write(b">III", right, 1, left) pivot.write(block) self._rootnode = new_root self._levels += 1 self._nodes += 1 self._dirty = True # Insert an entry into an inner node; `path' is the path from the root # to `node', not including `node' itself. `right_ptr' is the new node # pointer (inserted to the RIGHT of `entry') def _insert_inner(self, path, node, entry, right_ptr): with self._get_block(node) as block: next_node, count = block.read(b">II") insert_pos = None insert_ndx = None n = 0 while n < count: pos = block.tell() ptr = block.read(b">I")[0] e = DSStoreEntry.read(block) if e == entry: if n == count - 1: right_ptr = next_node next_node = ptr block.seek(pos) else: right_ptr = block.read(b">I")[0] block.seek(pos + 4) insert_pos = pos insert_ndx = n block.delete(e.byte_length() + 4) count -= 1 self._records += 1 self._dirty = True continue elif insert_pos is None and e > entry: insert_pos = pos insert_ndx = n n += 1 if insert_pos is None: insert_pos = block.tell() insert_ndx = count remaining = self._page_size - block.tell() if remaining < entry.byte_length() + 4: pivot, new_right = self._split(node, entry, right_ptr) if path: self._insert_inner(path[:-1], path[-1], pivot, new_right) else: self._new_root(node, pivot, new_right) else: if insert_ndx == count: block.seek(insert_pos) block.write(b">I", next_node) entry.write(block) next_node = right_ptr else: block.seek(insert_pos + 4) entry.write(block, True) block.insert(">I", right_ptr) block.seek(0) count += 1 block.write(b">II", next_node, count) self._records += 1 self._dirty = True # Insert `entry' into the leaf node `node' def _insert_leaf(self, path, node, entry): with self._get_block(node) as block: next_node, count = block.read(b">II") insert_pos = None # ?? insert_ndx = None n = 0 while n < count: pos = block.tell() e = DSStoreEntry.read(block) if e == entry: insert_pos = pos # ?? insert_ndx = n block.seek(pos) block.delete(e.byte_length()) count -= 1 self._records += 1 self._dirty = True continue elif insert_pos is None and e > entry: insert_pos = pos # ?? insert_ndx = n n += 1 if insert_pos is None: insert_pos = block.tell() # ?? insert_ndx = count remaining = self._page_size - block.tell() if remaining < entry.byte_length(): pivot, new_right = self._split(node, entry) if path: self._insert_inner(path[:-1], path[-1], pivot, new_right) else: self._new_root(node, pivot, new_right) else: block.seek(insert_pos) entry.write(block, True) block.seek(0) count += 1 block.write(b">II", next_node, count) self._records += 1 self._dirty = True def insert(self, entry): """Insert ``entry`` (which should be a :class:`DSStoreEntry`) into the B-Tree.""" path = [] node = self._rootnode while True: with self._get_block(node) as block: next_node, count = block.read(b">II") if next_node: for n in range(count): ptr = block.read(b">I")[0] e = DSStoreEntry.read(block) if entry < e: next_node = ptr break elif entry == e: # If we find an existing entry the same, replace it self._insert_inner(path, node, entry, None) return path.append(node) node = next_node else: self._insert_leaf(path, node, entry) return # Return usage information for the specified `node' def _block_usage(self, node): with self._get_block(node) as block: next_node, count = block.read(b">II") for n in range(count): if next_node: block.read(b">I")[0] DSStoreEntry.read(block) used = block.tell() return (count, used) # Splits entries across three blocks, returning two pivots def _split3(self, blocks, entries, pointers, before, internal): count = len(entries) # Find the feasible splits best_split = None best_diff = None total = before[count] for n in range(1, count - 3): left_size = 8 + before[n] remaining = 16 + total - before[n + 1] if left_size > self._page_size: break if remaining > 2 * self._page_size: continue for m in range(n + 2, count - 1): mid_size = 8 + before[m] - before[n + 1] right_size = 8 + total - before[m + 1] if mid_size > self._page_size: break if right_size > self._page_size: continue diff = abs(left_size - mid_size) * abs(right_size - mid_size) if best_split is None or diff < best_diff: best_split = (n, m, count) best_diff = diff if best_split is None: return None # Write the nodes prev_split = -1 for block, split in zip(blocks, best_split): block.seek(0) if internal: next_node = pointers[split] else: next_node = 0 block.write(b">II", next_node, split) for n in range(prev_split + 1, split): if internal: block.write(b">I", pointers[n]) entries[n].write(block) block.zero_fill() prev_split = split return (entries[best_split[0]], entries[best_split[1]]) # Extract all of the entries from the specified list of `blocks', # separating them by the specified `pivots'. Also computes the # amount of space used before each entry. def _extract(self, blocks, pivots): pointers = [] entries = [] before = [] total = 0 ppivots = pivots + [None] for b, p in zip(blocks, ppivots): b.seek(0) next_node, count = b.read(b">II") for n in range(count): pos = b.tell() if next_node: ptr = b.read(b">I")[0] pointers.append(ptr) e = DSStoreEntry.read(b) entries.append(e) before.append(total) total += b.tell() - pos if next_node: pointers.append(next_node) if p: entries.append(p) before.append(total) total += p.byte_length() if next_node: total += 4 before.append(total) return (entries, pointers, before) # Rebalance the specified `node', whose path from the root is `path'. def _rebalance(self, path, node): # Can't rebalance the root if not path: return with self._get_block(node) as block: next_node, count = block.read(b">II") with self._get_block(path[-1]) as parent: # Find the left and right siblings and respective pivots parent_next, parent_count = parent.read(b">II") left_pos = None left_node = None left_pivot = None node_pos = None right_pos = None right_node = None right_pivot = None prev_e = prev_ptr = prev_pos = None for n in range(parent_count): pos = parent.tell() ptr = parent.read(b">I")[0] e = DSStoreEntry.read(parent) if ptr == node: node_pos = pos right_pivot = e left_pos = prev_pos left_pivot = prev_e left_node = prev_ptr elif prev_ptr == node: right_node = ptr right_pos = pos break prev_e = e prev_ptr = ptr prev_pos = pos if parent_next == node: node_pos = parent.tell() left_pos = prev_pos left_pivot = prev_e left_node = prev_ptr elif right_node is None: right_node = parent_next right_pos = parent.tell() _ = parent.tell() if left_node and right_node: with self._get_block(left_node) as left, self._get_block( right_node ) as right: blocks = [left, block, right] pivots = [left_pivot, right_pivot] entries, pointers, before = self._extract(blocks, pivots) # If there's a chance that we could use two pages instead # of three, go for it pivots = self._split2( blocks, entries, pointers, before, bool(next_node) ) if pivots is None: ptrs = [left_node, node, right_node] pivots = self._split3( blocks, entries, pointers, before, bool(next_node) ) else: if pivots: ptrs = [left_node, node] else: ptrs = [left_node] self._store.release(node) self._nodes -= 1 node = left_node self._store.release(right_node) self._nodes -= 1 self._dirty = True # Remove the pivots from the parent with self._get_block(path[-1]) as parent: if right_node == parent_next: parent.seek(left_pos) parent.delete(right_pos - left_pos) parent_next = left_node else: parent.seek(left_pos + 4) parent.delete(right_pos - left_pos) parent.seek(0) parent_count -= 2 parent.write(b">II", parent_next, parent_count) self._records -= 2 # Replace with those in pivots for e, rp in zip(pivots, ptrs[1:]): self._insert_inner(path[:-1], path[-1], e, rp) elif left_node: with self._get_block(left_node) as left: blocks = [left, block] pivots = [left_pivot] entries, pointers, before = self._extract(blocks, pivots) pivots = self._split2( blocks, entries, pointers, before, bool(next_node) ) # Remove the pivot from the parent with self._get_block(path[-1]) as parent: if node == parent_next: parent.seek(left_pos) parent.delete(node_pos - left_pos) parent_next = left_node else: parent.seek(left_pos + 4) parent.delete(node_pos - left_pos) parent.seek(0) parent_count -= 1 parent.write(b">II", parent_next, parent_count) self._records -= 1 # Replace the pivot if pivots: self._insert_inner(path[:-1], path[-1], pivots[0], node) elif right_node: with self._get_block(right_node) as right: blocks = [block, right] pivots = [right_pivot] entries, pointers, before = self._extract(blocks, pivots) pivots = self._split2( blocks, entries, pointers, before, bool(next_node) ) # Remove the pivot from the parent with self._get_block(path[-1]) as parent: if right_node == parent_next: parent.seek(pos) parent.delete(right_pos - node_pos) parent_next = node else: parent.seek(pos + 4) parent.delete(right_pos - node_pos) parent.seek(0) parent_count -= 1 parent.write(b">II", parent_next, parent_count) self._records -= 1 # Replace the pivot if pivots: self._insert_inner(path[:-1], path[-1], pivots[0], right_node) if not path and not parent_count: self._store.release(path[-1]) self._nodes -= 1 self._dirty = True self._rootnode = node else: count, used = self._block_usage(path[-1]) if used < self._page_size // 2: self._rebalance(path[:-1], path[-1]) # Delete from the leaf node `node'. `filename_lc' has already been # lower-cased. def _delete_leaf(self, node, filename_lc, code): found = False with self._get_block(node) as block: next_node, count = block.read(b">II") for n in range(count): pos = block.tell() e = DSStoreEntry.read(block) if e.filename.lower() == filename_lc and ( code is None or e.code == code ): block.seek(pos) block.delete(e.byte_length()) found = True # This does not affect the loop; THIS IS NOT A BUG count -= 1 self._records -= 1 self._dirty = True if found: used = block.tell() block.seek(0) block.write(b">II", next_node, count) return used < self._page_size // 2 else: return False # Remove the largest entry from the subtree starting at `node' (with # path from root `path'). Returns a tuple (rebalance, entry) where # rebalance is either None if no rebalancing is required, or a # (path, node) tuple giving the details of the node to rebalance. def _take_largest(self, path, node): path = list(path) rebalance = None while True: with self._get_block(node) as block: next_node, count = block.read(b">II") if next_node: path.append(node) node = next_node continue for n in range(count): pos = block.tell() e = DSStoreEntry.read(block) count -= 1 block.seek(0) block.write(b">II", next_node, count) if pos < self._page_size // 2: rebalance = (path, node) break return rebalance, e # Delete an entry from an inner node, `node' def _delete_inner(self, path, node, filename_lc, code): rebalance = False with self._get_block(node) as block: next_node, count = block.read(b">II") for n in range(count): pos = block.tell() ptr = block.read(b">I")[0] e = DSStoreEntry.read(block) if e.filename.lower() == filename_lc and ( code is None or e.code == code ): # Take the largest from the left subtree rebalance, largest = self._take_largest(path, ptr) # Delete this entry if n == count - 1: right_ptr = next_node next_node = ptr block.seek(pos) else: right_ptr = block.read(b">I")[0] block.seek(pos + 4) block.delete(e.byte_length() + 4) count -= 1 block.seek(0) block.write(b">II", next_node, count) self._records -= 1 self._dirty = True break # Replace the pivot value self._insert_inner(path, node, largest, right_ptr) # Rebalance from the node we stole from if rebalance: self._rebalance(rebalance[0], rebalance[1]) return True return False def delete(self, filename, code): """Delete an item, identified by ``filename`` and ``code`` from the B-Tree.""" if isinstance(filename, DSStoreEntry): code = filename.code filename = filename.filename # If we're deleting *every* node for "filename", we must recurse if code is None: # TODO: Fix this so we can do bulk deletes raise ValueError("You must delete items individually. Sorry") # Otherwise, we're deleting *one* specific node filename_lc = filename.lower() path = [] node = self._rootnode while True: with self._get_block(node) as block: next_node, count = block.read(b">II") if next_node: for n in range(count): ptr = block.read(b">I")[0] e = DSStoreEntry.read(block) e_lc = e.filename.lower() if filename_lc < e_lc or ( filename_lc == e_lc and code < e.code ): next_node = ptr break elif filename_lc == e_lc and code == e.code: self._delete_inner(path, node, filename_lc, code) return path.append(node) node = next_node else: if self._delete_leaf(node, filename_lc, code): self._rebalance(path, node) return # Find implementation def _find(self, node, filename_lc, code=None): if code is not None and not isinstance(code, bytes): code = code.encode("latin_1") with self._get_block(node) as block: next_node, count = block.read(b">II") if next_node: for n in range(count): ptr = block.read(b">I")[0] e = DSStoreEntry.read(block) if filename_lc < e.filename.lower(): for e in self._find(ptr, filename_lc, code): yield e return elif filename_lc == e.filename.lower(): if code is None or (code and code < e.code): for e in self._find(ptr, filename_lc, code): yield e if code is None or code == e.code: yield e elif code < e.code: return for e in self._find(next_node, filename_lc, code): yield e else: for n in range(count): e = DSStoreEntry.read(block) if filename_lc == e.filename.lower(): if code is None or code == e.code: yield e elif code < e.code: return def find(self, filename, code=None): """Returns a generator that will iterate over matching entries in the B-Tree.""" if isinstance(filename, DSStoreEntry): code = filename.code filename = filename.filename filename_lc = filename.lower() return self._find(self._rootnode, filename_lc, code) def __len__(self): return self._records def __iter__(self): return self._traverse(self._rootnode) class Partial: """This is used to implement indexing.""" def __init__(self, store, filename): self._store = store self._filename = filename def __getitem__(self, code): if code is None: raise KeyError("no such key - [%s][None]" % self._filename) if not isinstance(code, bytes): code = code.encode("latin_1") try: item = next(self._store.find(self._filename, code)) except StopIteration: raise KeyError(f"no such key - [{self._filename}][{code}]") if not isinstance(item.type, (bytes, str)): return item.value return (item.type, item.value) def __setitem__(self, code, value): if code is None: raise KeyError("bad key - [%s][None]" % self._filename) if not isinstance(code, bytes): code = code.encode("latin_1") codec = codecs.get(code, None) if codec: entry_type = codec entry_value = value else: entry_type = value[0] entry_value = value[1] self._store.insert( DSStoreEntry(self._filename, code, entry_type, entry_value) ) def __delitem__(self, code): if code is None: raise KeyError("no such key - [%s][None]" % self._filename) self._store.delete(self._filename, code) def __iter__(self): yield from self._store.find(self._filename) def __getitem__(self, filename): return self.Partial(self, filename) qbs-src-3.3.1/src/3rdparty/python/lib/python3.9/site-packages/ds_store/buddy.py0000644000175100017510000003310715232633614026733 0ustar runnerrunnerimport binascii import bisect import os import struct class BuddyError(Exception): pass class Block: def __init__(self, allocator, offset, size): self._allocator = allocator self._offset = offset self._size = size self._value = bytearray(allocator.read(offset, size)) self._pos = 0 self._dirty = False def __len__(self): return self._size def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def close(self): if self._dirty: self.flush() def flush(self): if self._dirty: self._dirty = False self._allocator.write(self._offset, self._value) def invalidate(self): self._dirty = False def zero_fill(self): len = self._size - self._pos zeroes = b"\0" * len self._value[self._pos : self._size] = zeroes self._dirty = True def tell(self): return self._pos def seek(self, pos, whence=os.SEEK_SET): if whence == os.SEEK_CUR: pos += self._pos elif whence == os.SEEK_END: pos = self._size - pos if pos < 0 or pos > self._size: raise ValueError("Seek out of range in Block instance") self._pos = pos def read(self, size_or_format): if isinstance(size_or_format, (str, bytes)): size = struct.calcsize(size_or_format) fmt = size_or_format else: size = size_or_format fmt = None if self._size - self._pos < size: raise BuddyError("Unable to read %lu bytes in block" % size) data = self._value[self._pos : self._pos + size] self._pos += size if fmt is not None: if isinstance(data, bytearray): return struct.unpack_from(fmt, bytes(data)) else: return struct.unpack(fmt, data) else: return data def write(self, data_or_format, *args): if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format if self._pos + len(data) > self._size: raise ValueError("Attempt to write past end of Block") self._value[self._pos : self._pos + len(data)] = data self._pos += len(data) self._dirty = True def insert(self, data_or_format, *args): if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format del self._value[-len(data) :] self._value[self._pos : self._pos] = data self._pos += len(data) self._dirty = True def delete(self, size): if self._pos + size > self._size: raise ValueError("Attempt to delete past end of Block") del self._value[self._pos : self._pos + size] self._value += b"\0" * size self._dirty = True def __str__(self): return binascii.b2a_hex(self._value) class Allocator: def __init__(self, the_file): self._file = the_file self._dirty = False self._file.seek(0) # Read the header (magic1, magic2, offset, size, offset2, self._unknown1) = self.read( -4, ">I4sIII16s" ) if magic2 != b"Bud1" or magic1 != 1: raise BuddyError("Not a buddy file") if offset != offset2: raise BuddyError("Root addresses differ") self._root = Block(self, offset, size) # Read the block offsets count, self._unknown2 = self._root.read(">II") self._offsets = [] c = (count + 255) & ~255 while c: self._offsets += self._root.read(">256I") c -= 256 self._offsets = self._offsets[:count] # Read the TOC self._toc = {} count = self._root.read(">I")[0] for n in range(count): nlen = self._root.read("B")[0] name = bytes(self._root.read(nlen)) value = self._root.read(">I")[0] self._toc[name] = value # Read the free lists self._free = [] for n in range(32): count = self._root.read(">I") self._free.append(list(self._root.read(">%uI" % count))) @classmethod def open(cls, file_or_name, mode="r+"): if isinstance(file_or_name, str): if "b" not in mode: mode = mode[:1] + "b" + mode[1:] f = open(file_or_name, mode) else: f = file_or_name if "w" in mode: # Create an empty file in this case f.truncate() # An empty root block needs 1264 bytes: # # 0 4 offset count # 4 4 unknown # 8 4 root block offset (2048) # 12 255 * 4 padding (offsets are in multiples of 256) # 1032 4 toc count (0) # 1036 228 free list # total 1264 # The free list will contain the following: # # 0 5 * 4 no blocks of width less than 5 # 20 6 * 8 1 block each of widths 5 to 10 # 68 4 no blocks of width 11 (allocated for the root) # 72 19 * 8 1 block each of widths 12 to 30 # 224 4 no blocks of width 31 # total 228 # # (The reason for this layout is that we allocate 2**5 bytes for # the header, which splits the initial 2GB region into every size # below 2**31, including *two* blocks of size 2**5, one of which # we take. The root block itself then needs a block of size # 2**11. Conveniently, each of these initial blocks will be # located at offset 2**n where n is its width.) # Write the header header = struct.pack( b">I4sIII16s", 1, b"Bud1", 2048, 1264, 2048, b"\x00\x00\x10\x0c" b"\x00\x00\x00\x87" b"\x00\x00\x20\x0b" b"\x00\x00\x00\x00", ) f.write(header) f.write(b"\0" * 2016) # Write the root block free_list = [struct.pack(b">5I", 0, 0, 0, 0, 0)] for n in range(5, 11): free_list.append(struct.pack(b">II", 1, 2**n)) free_list.append(struct.pack(b">I", 0)) for n in range(12, 31): free_list.append(struct.pack(b">II", 1, 2**n)) free_list.append(struct.pack(b">I", 0)) root = b"".join( [ struct.pack(b">III", 1, 0, 2048 | 5), struct.pack(b">I", 0) * 255, struct.pack(b">I", 0), ] + free_list ) f.write(root) return Allocator(f) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def close(self): self.flush() self._file.close() def flush(self): if self._dirty: size = self._root_block_size() self.allocate(size, 0) with self.get_block(0) as rblk: self._write_root_block_into(rblk) addr = self._offsets[0] offset = addr & ~0x1F size = 1 << (addr & 0x1F) self._file.seek(0, os.SEEK_SET) self._file.write( struct.pack( b">I4sIII16s", 1, b"Bud1", offset, size, offset, self._unknown1 ) ) self._dirty = False self._file.flush() def read(self, offset, size_or_format): """Read data at `offset', or raise an exception. `size_or_format' may either be a byte count, in which case we return raw data, or a format string for `struct.unpack', in which case we work out the size and unpack the data before returning it. """ # N.B. There is a fixed offset of four bytes(!) self._file.seek(offset + 4, os.SEEK_SET) if isinstance(size_or_format, str): size = struct.calcsize(size_or_format) fmt = size_or_format else: size = size_or_format fmt = None ret = self._file.read(size) if len(ret) < size: ret += b"\0" * (size - len(ret)) if fmt is not None: if isinstance(ret, bytearray): ret = struct.unpack_from(fmt, bytes(ret)) else: ret = struct.unpack(fmt, ret) return ret def write(self, offset, data_or_format, *args): """Write data at `offset', or raise an exception. `data_or_format' may either be the data to write, or a format string for `struct.pack', in which case we pack the additional arguments and write the resulting data. """ # N.B. There is a fixed offset of four bytes(!) self._file.seek(offset + 4, os.SEEK_SET) if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format self._file.write(data) def get_block(self, block): try: addr = self._offsets[block] except IndexError: return None offset = addr & ~0x1F size = 1 << (addr & 0x1F) return Block(self, offset, size) def _root_block_size(self): """Return the number of bytes required by the root block.""" # Offsets size = 8 size += 4 * ((len(self._offsets) + 255) & ~255) # TOC size += 4 size += sum([5 + len(s) for s in self._toc]) # Free list size += sum([4 + 4 * len(fl) for fl in self._free]) return size def _write_root_block_into(self, block): # Offsets block.write(">II", len(self._offsets), self._unknown2) block.write(">%uI" % len(self._offsets), *self._offsets) extra = len(self._offsets) & 255 if extra: block.write(b"\0\0\0\0" * (256 - extra)) # TOC keys = list(self._toc.keys()) keys.sort() block.write(">I", len(keys)) for k in keys: block.write("B", len(k)) block.write(k) block.write(">I", self._toc[k]) # Free list for w, f in enumerate(self._free): block.write(">I", len(f)) if len(f): block.write(">%uI" % len(f), *f) def _buddy(self, offset, width): f = self._free[width] b = offset ^ (1 << width) try: ndx = f.index(b) except ValueError: ndx = None return (f, b, ndx) def _release(self, offset, width): # Coalesce while True: f, b, ndx = self._buddy(offset, width) if ndx is None: break offset &= b width += 1 del f[ndx] # Add to the list bisect.insort(f, offset) # Mark as dirty self._dirty = True def _alloc(self, width): w = width while not self._free[w]: w += 1 while w > width: offset = self._free[w].pop(0) w -= 1 self._free[w] = [offset, offset ^ (1 << w)] self._dirty = True return self._free[width].pop(0) def allocate(self, bytes, block=None): """Allocate or reallocate a block such that it has space for at least `bytes' bytes.""" if block is None: # Find the first unused block try: block = self._offsets.index(0) except ValueError: block = len(self._offsets) self._offsets.append(0) # Compute block width width = max(bytes.bit_length(), 5) addr = self._offsets[block] offset = addr & ~0x1F if addr: blkwidth = addr & 0x1F if blkwidth == width: return block self._release(offset, width) self._offsets[block] = 0 offset = self._alloc(width) self._offsets[block] = offset | width return block def release(self, block): addr = self._offsets[block] if addr: width = addr & 0x1F offset = addr & ~0x1F self._release(offset, width) if block == len(self._offsets): del self._offsets[block] else: self._offsets[block] = 0 def __len__(self): return len(self._toc) def __getitem__(self, key): if not isinstance(key, str): raise TypeError("Keys must be of string type") if not isinstance(key, bytes): key = key.encode("latin_1") return self._toc[key] def __setitem__(self, key, value): if not isinstance(key, str): raise TypeError("Keys must be of string type") if not isinstance(key, bytes): key = key.encode("latin_1") self._toc[key] = value self._dirty = True def __delitem__(self, key): if not isinstance(key, str): raise TypeError("Keys must be of string type") if not isinstance(key, bytes): key = key.encode("latin_1") del self._toc[key] self._dirty = True def iterkeys(self): return self._toc.keys() def keys(self): return self._toc.keys() def __iter__(self): return self._toc.keys() def __contains__(self, key): return key in self._toc qbs-src-3.3.1/src/3rdparty/python/.gitignore0000644000175100017510000000003515232633614020351 0ustar runnerrunner*.pyc *.dist-info *.egg-info qbs-src-3.3.1/LICENSE.LGPLv30000644000175100017510000001756015232633614014527 0ustar runnerrunner GNU LESSER GENERAL PUBLIC LICENSE The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. Contact: http://www.qt.io/licensing You may use, distribute and copy the Qt GUI Toolkit under the terms of GNU Lesser General Public License version 3, which is displayed below. ------------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this licensedocument, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, “this License†refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL†refers to version 3 of the GNU General Public License. “The Library†refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An “Application†is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A “Combined Work†is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Versionâ€. The “Minimal Corresponding Source†for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The “Corresponding Application Code†for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version†applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. qbs-src-3.3.1/qbs-resources/0000755000175100017510000000000015232633614015300 5ustar runnerrunnerqbs-src-3.3.1/qbs-resources/modules/0000755000175100017510000000000015232633614016750 5ustar runnerrunnerqbs-src-3.3.1/qbs-resources/modules/qbsbuildconfig/0000755000175100017510000000000015232633614021743 5ustar runnerrunnerqbs-src-3.3.1/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs0000644000175100017510000001152215232633614025446 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities Module { Depends { condition: project.withCode name: "cpp" } property bool enableAddressSanitizer: false property bool enableUbSanitizer: false property bool enableThreadSanitizer: false property bool enableUnitTests: false property bool enableProjectFileUpdates: true property bool enableRPath: true property bool installApiHeaders: true property bool enableBundledQt: false property bool staticBuild: false property string libDirName: "lib" property string appInstallDir: "bin" property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName property string importLibInstallDir: libDirName property string libexecInstallDir: qbs.targetOS.contains("windows") ? appInstallDir : "libexec/qbs" property string systemSettingsDir property bool installManPage: qbs.targetOS.contains("unix") property bool installHtml: true property bool installQch: false property bool generatePkgConfigFiles: installApiHeaders && qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin") property bool generateQbsModules: installApiHeaders property string docInstallDir: "share/doc/qbs/html" property string pkgConfigInstallDir: FileInfo.joinPaths(libDirName, "pkgconfig") property string qbsModulesBaseDir: FileInfo.joinPaths(libDirName, "qbs", "modules") property string relativeLibexecPath: "../" + libexecInstallDir property string relativePluginsPath: "../" + libDirName property string relativeSearchPath: ".." property stringList libRPaths: { if (enableRPath && project.withCode && cpp.rpathOrigin && product.targetInstallDir) { return [FileInfo.joinPaths(cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.targetInstallDir), FileInfo.joinPaths('/', libDirName)))]; } return []; } property string resourcesInstallDir: "" property string pluginsInstallDir: libDirName + "/qbs/plugins" property string qmlTypeDescriptionsInstallDir: FileInfo.joinPaths(resourcesInstallDir, "share/qbs/qml-type-descriptions") property bool dumpJsLeaks: qbs.buildVariant === "debug" Properties { condition: project.withCode && qbs.toolchain.contains("gcc") property bool isClang: qbs.toolchain.contains("clang") property bool isMingw: qbs.toolchain.contains("mingw") property var versionAtLeast: { return function(v) { return Utilities.versionCompare(cpp.compilerVersion, v) >= 0 } } property var versionBelow: { return function(v) { return Utilities.versionCompare(cpp.compilerVersion, v) < 0 } } cpp.commonCompilerFlags: { var flags = ["-Wno-missing-field-initializers"]; if (enableAddressSanitizer) flags.push("-fno-omit-frame-pointer"); if (isClang) flags.push("-Wno-constant-logical-operand"); // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105616 if (enableAddressSanitizer && !isClang && versionAtLeast("13")) { flags.push("-Wno-maybe-uninitialized"); } // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106395 if (isMingw && versionAtLeast("12") && versionBelow("13")) { flags.push("-Wno-attributes"); } return flags; } cpp.cxxFlags: { var flags = []; if ((!isClang && versionAtLeast("9")) || (isClang && !qbs.hostOS.contains("darwin") && versionAtLeast("10"))) { flags.push("-Wno-deprecated-copy"); } return flags; } cpp.driverFlags: { var flags = []; if (enableAddressSanitizer) flags.push("-fsanitize=address"); if (enableUbSanitizer) { flags.push("-fsanitize=undefined"); flags.push("-fno-sanitize=vptr"); } if (enableThreadSanitizer) flags.push("-fsanitize=thread"); return flags; } } Properties { condition: project.withCode && qbs.toolchain.contains("msvc") && product.Qt && Utilities.versionCompare(product.Qt.core.version, "6.3") >= 0 && Utilities.versionCompare(cpp.compilerVersion, "19.10") >= 0 && Utilities.versionCompare(qbs.version, "1.23") < 0 cpp.cxxFlags: "/permissive-" } Properties { condition: project.withCode && qbs.toolchain.contains("msvc") cpp.defines: "_UCRT_NOISY_NAN" } } qbs-src-3.3.1/qbs-resources/modules/qbsversion/0000755000175100017510000000000015232633614021143 5ustar runnerrunnerqbs-src-3.3.1/qbs-resources/modules/qbsversion/qbsversion.qbs0000644000175100017510000000115115232633614024043 0ustar runnerrunnerimport qbs.File import qbs.FileInfo import qbs.TextFile Module { Probe { id: qbsVersionProbe property var lastModified: File.lastModified(versionFilePath) property string versionFilePath: FileInfo.joinPaths(path, "..", "..", "..", "VERSION") property string version configure: { var tf = new TextFile(versionFilePath, TextFile.ReadOnly); try { version = tf.readAll().trim(); found = !!version; } finally { tf.close(); } } } version: qbsVersionProbe.version } qbs-src-3.3.1/qbs-resources/imports/0000755000175100017510000000000015232633614016775 5ustar runnerrunnerqbs-src-3.3.1/qbs-resources/imports/QbsAutotest.qbs0000644000175100017510000000145615232633614021770 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities QbsProduct { type: ["application", "autotest"] consoleApplication: true property string testName name: "tst_" + testName property string targetInstallDir: qbsbuildconfig.appInstallDir Depends { name: "Qt.testlib" } Depends { name: "qbscore" } Depends { name: "qbsbuildconfig" } cpp.defines: [ // deliberately override base defines "QBS_TEST_SUITE_NAME=" + Utilities.cStringQuote(testName.toUpperCase().replace("-", "_")) ] cpp.includePaths: [ "../../../src", ] qbs.commonRunEnvironment: ({ "QBS_INSTALL_DIR": FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) }) Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: targetInstallDir } } qbs-src-3.3.1/qbs-resources/imports/QbsProduct.qbs0000644000175100017510000000247415232633614021601 0ustar runnerrunnerProduct { Depends { name: "qbsbuildconfig" } Depends { name: "qbsversion" } Depends { name: "Qt.core"; versionAtLeast: minimumQtVersion } property string minimumQtVersion: "5.15.2" property bool install: true property bool hasCMakeFile: true property string targetInstallDir cpp.defines: { var res = [ "QT_NO_CAST_FROM_ASCII", "QT_NO_CAST_FROM_BYTEARRAY", "QT_NO_JAVA_STYLE_ITERATORS", "QT_NO_PROCESS_COMBINED_ARGUMENT_START", "QT_USE_QSTRINGBUILDER", "QT_DISABLE_DEPRECATED_BEFORE=0x050f00", "QT_DISABLE_DEPRECATED_UP_TO=0x050f00", "QT_WARN_DEPRECATED_BEFORE=0x060700", "QT_WARN_DEPRECATED_UP_TO=0x060700" ]; if (qbs.toolchain.contains("msvc")) res.push("_SCL_SECURE_NO_WARNINGS"); if (qbs.enableDebugCode) res.push("QT_STRICT_ITERATORS"); return res; } cpp.cxxLanguageVersion: "c++20" cpp.enableExceptions: true cpp.rpaths: qbsbuildconfig.libRPaths cpp.minimumMacosVersion: "11.0" Group { name: "CMake" condition: hasCMakeFile prefix: product.sourceDirectory + '/' files: "CMakeLists.txt" } } qbs-src-3.3.1/qbs-resources/imports/QbsStaticLibrary.qbs0000644000175100017510000000031715232633614022727 0ustar runnerrunnerQbsProduct { type: "staticlibrary" Export { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["core"] } cpp.includePaths: [exportingProduct.sourceDirectory] } } qbs-src-3.3.1/qbs-resources/imports/QbsLibrary.qbs0000644000175100017510000000556615232633614021572 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities QbsProduct { Depends { name: "cpp" } Depends { name: "Exporter.pkgconfig"; condition: generatePkgConfigFile } Depends { name: "Exporter.qbs"; condition: generateQbsModule } Depends { name: "span" } property string visibilityType: staticBuild ? "static" : "dynamic" property string headerInstallPrefix: "/include/qbs" property bool hasExporter: Utilities.versionCompare(qbs.version, "1.12") >= 0 property bool generatePkgConfigFile: qbsbuildconfig.generatePkgConfigFiles && hasExporter property bool generateQbsModule: install && qbsbuildconfig.generateQbsModules && hasExporter property bool staticBuild: Qt.core.staticBuild || qbsbuildconfig.staticBuild property stringList libType: [staticBuild ? "staticlibrary" : "dynamiclibrary"] version: qbsversion.version type: libType targetName: (qbs.enableDebugCode && qbs.targetOS.contains("windows")) ? (name + 'd') : name cpp.visibility: "minimal" cpp.defines: base.concat(visibilityType === "static" ? ["QBS_STATIC_LIB"] : ["QBS_LIBRARY"]) cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Properties { condition: qbs.toolchain.contains("gcc") cpp.soVersion: version.replace(/\.\d+$/, '') } Group { fileTagsFilter: libType.concat("dynamiclibrary_symlink") .concat(qbs.debugInformation ? ["debuginfo_dll"] : []) qbs.install: install qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.libInstallDir Group { fileTagsFilter: ["dynamiclibrary_import"] qbs.install: install qbs.installDir: qbsbuildconfig.importLibInstallDir } Group { fileTagsFilter: "Exporter.pkgconfig.pc" qbs.install: install qbs.installDir: qbsbuildconfig.pkgConfigInstallDir } Group { fileTagsFilter: "Exporter.qbs.module" qbs.install: install qbs.installDir: FileInfo.joinPaths(qbsbuildconfig.qbsModulesBaseDir, product.name) } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false cpp.linkerFlags: ["-compatibility_version", cpp.soVersion] } Export { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["core"] } Depends { name: "span" } Properties { condition: exportingProduct.hasExporter prefixMapping: [{ prefix: exportingProduct.sourceDirectory, replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headerInstallPrefix) }] } cpp.includePaths: [exportingProduct.sourceDirectory] cpp.defines: exportingProduct.visibilityType === "static" ? ["QBS_STATIC_LIB"] : [] } } qbs-src-3.3.1/qbs-resources/imports/QbsApp.qbs0000644000175100017510000000102715232633614020672 0ustar runnerrunnerimport qbs.FileInfo QbsProduct { Depends { name: "qbscore" } Depends { name: "qbsversion" } Depends { name: "qbsconsolelogger" } type: ["application", "qbsapplication"] version: qbsversion.version consoleApplication: true Group { fileTagsFilter: product.type .concat(qbs.debugInformation ? ["debuginfo_app"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.appInstallDir } qbs-src-3.3.1/qbs-resources/imports/QbsUnittest.qbs0000644000175100017510000000035215232633614021771 0ustar runnerrunnerimport qbs.FileInfo import qbs.Utilities QbsAutotest { Depends { name: "Qt.core5compat"; condition: Utilities.versionCompare(Qt.core.version, "6.0.0") >= 0 } Depends { name: "quickjs"; cpp.link: false } } qbs-src-3.3.1/VERSION0000644000175100017510000000000615232633614013547 0ustar runnerrunner3.3.1 qbs-src-3.3.1/dist/0000755000175100017510000000000015232633614013446 5ustar runnerrunnerqbs-src-3.3.1/dist/.gitignore0000644000175100017510000000000215232633614015426 0ustar runnerrunner* qbs-src-3.3.1/LICENSE.GPL3-EXCEPT0000644000175100017510000010701315232633614015204 0ustar runnerrunnerThis is the GNU General Public License version 3, annotated with The Qt Company GPL Exception 1.0: ------------------------------------------------------------------------- The Qt Company GPL Exception 1.0 Exception 1: As a special exception you may create a larger work which contains the output of this application and distribute that work under terms of your choice, so long as the work is not otherwise derived from or based on this application and so long as the work does not in itself generate output that contains the output from this application in its original or modified form. Exception 2: As a special exception, you have permission to combine this application with Plugins licensed under the terms of your choice, to produce an executable, and to copy and distribute the resulting executable under the terms of your choice. However, the executable must be accompanied by a prominent notice offering all users of the executable the entire source code to this application, excluding the source code of the independent modules, but including any changes you have made to this application, under the terms of this license. ------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . qbs-src-3.3.1/cmake/0000755000175100017510000000000015232633614013563 5ustar runnerrunnerqbs-src-3.3.1/cmake/QbsBuildConfig.cmake0000644000175100017510000002506715232633614017432 0ustar runnerrunneroption(WITH_TESTS "Build Tests" ON) option(WITH_UNIT_TESTS "Build Unit Tests" OFF) option(INSTALL_PUBLIC_HEADERS "Whether to install public headers" ON) option(QBS_ENABLE_RPATH "Whether to enable RPATH" ON) include(CMakeDependentOption) cmake_dependent_option(QBS_QUICKJS_LEAK_CHECK "Whether to check for quickjs leaks at the end" ON "CMAKE_BUILD_TYPE STREQUAL Debug" OFF) set(QBS_APP_INSTALL_DIR "bin" CACHE STRING "Relative install location for Qbs binaries.") # default paths set(QBS_LIBDIR_NAME "lib") if(WIN32) set(_DEFAULT_LIB_INSTALL_DIR ${QBS_APP_INSTALL_DIR}) set(_DEFAULT_LIBEXEC_INSTALL_DIR ${QBS_APP_INSTALL_DIR}) else() set(_DEFAULT_LIB_INSTALL_DIR ${QBS_LIBDIR_NAME}) set(_DEFAULT_LIBEXEC_INSTALL_DIR "libexec/qbs") endif() # path options set(QBS_OUTPUT_PREFIX "" CACHE STRING "Qbs build output location relative to CMAKE_BINARY_DIR.") set(QBS_LIB_INSTALL_DIR "${_DEFAULT_LIB_INSTALL_DIR}" CACHE STRING "Relative install location for Qbs libraries.") set(QBS_DLL_INSTALL_DIR "${QBS_LIB_INSTALL_DIR}" CACHE STRING "Relative install location for Qbs DLLs.") set(QBS_LIBEXEC_INSTALL_DIR "${_DEFAULT_LIBEXEC_INSTALL_DIR}" CACHE STRING "Relative install location for Qbs libexec.") set(QBS_PLUGINS_INSTALL_BASE "${QBS_LIBDIR_NAME}" CACHE STRING "Relative install location for Qbs plugins.") set(QBS_RESOURCES_INSTALL_BASE "." CACHE STRING "Relative install location for Qbs resources.") set(QBS_HEADERS_INSTALL_DIR "include/qbs" CACHE STRING "Relative install location for Qbs headers.") set(QBS_DOC_INSTALL_DIR "${QBS_RESOURCES_INSTALL_BASE}/share/doc/qbs" CACHE STRING "Relative install location for Qbs documentation.") set(QBS_DOC_HTML_DIR_NAME "html" CACHE STRING "The name of the dir with HTML files, appended to QBS_DOC_INSTALL_DIR.") set(QBS_PLUGINS_INSTALL_DIR "${QBS_PLUGINS_INSTALL_BASE}/qbs/plugins") set(QBS_RESOURCES_INSTALL_DIR "${QBS_RESOURCES_INSTALL_BASE}/share") # rpaths file(RELATIVE_PATH QBS_RELATIVE_LIBEXEC_RPATH "/${QBS_LIBEXEC_INSTALL_DIR}" "/${QBS_LIB_INSTALL_DIR}") file(RELATIVE_PATH QBS_RELATIVE_APP_RPATH "/${QBS_APP_INSTALL_DIR}" "/${QBS_LIB_INSTALL_DIR}") file(RELATIVE_PATH QBS_RELATIVE_PLUGINS_RPATH "/${QBS_PLUGINS_INSTALL_DIR}" "/${QBS_LIB_INSTALL_DIR}") if(WIN32 OR NOT QBS_ENABLE_RPATH) set(QBS_MACOSX_RPATH OFF) set(QBS_LIB_RPATH "") set(QBS_LIBEXEC_RPATH "") set(QBS_APP_RPATH "") set(QBS_PLUGINS_RPATH "") elseif(APPLE) set(QBS_MACOSX_RPATH ON) set(QBS_LIB_RPATH "@loader_path") set(QBS_LIBEXEC_RPATH "@loader_path/${QBS_RELATIVE_LIBEXEC_RPATH}") set(QBS_APP_RPATH "@loader_path/${QBS_RELATIVE_APP_RPATH}") set(QBS_PLUGINS_RPATH "@loader_path/${QBS_RELATIVE_PLUGINS_RPATH}") else() set(QBS_MACOSX_RPATH OFF) set(QBS_LIB_RPATH "\$ORIGIN") set(QBS_LIBEXEC_RPATH "\$ORIGIN/${QBS_RELATIVE_LIBEXEC_RPATH}") set(QBS_APP_RPATH "\$ORIGIN/${QBS_RELATIVE_APP_RPATH}") set(QBS_PLUGINS_RPATH "\$ORIGIN/${QBS_RELATIVE_PLUGINS_RPATH}") endif() function(get_update_path_command var) if(WIN32) get_target_property(_QTCORE_LIBRARY Qt${QT_VERSION_MAJOR}::Core IMPORTED_LOCATION_RELEASE) if(NOT _QTCORE_LIBRARY) get_target_property(_QTCORE_LIBRARY Qt${QT_VERSION_MAJOR}::Core IMPORTED_LOCATION_DEBUG) endif() get_filename_component(_QT_LIBRARY_PATH "${_QTCORE_LIBRARY}" DIRECTORY) get_target_property(_QBS_LIBRARY_PATH qbscore LIBRARY_OUTPUT_DIRECTORY) file(TO_NATIVE_PATH "${_QT_LIBRARY_PATH}\;${_QBS_LIBRARY_PATH}\;$ENV{PATH}" _NEW_PATH) set(${var} "PATH=${_NEW_PATH}" PARENT_SCOPE) else() set(${var} "") endif() endfunction() if(WITH_UNIT_TESTS) set(QBS_UNIT_TESTS_DEFINES "QBS_ENABLE_UNIT_TESTS") else() set(QBS_UNIT_TESTS_DEFINES "") endif() file(RELATIVE_PATH QBS_RELATIVE_LIBEXEC_PATH "/${QBS_APP_INSTALL_DIR}" "/${QBS_LIBEXEC_INSTALL_DIR}") file(RELATIVE_PATH QBS_RELATIVE_SEARCH_PATH "/${QBS_APP_INSTALL_DIR}" "/${QBS_RESOURCES_INSTALL_BASE}") file(RELATIVE_PATH QBS_RELATIVE_PLUGINS_PATH "/${QBS_APP_INSTALL_DIR}" "/${QBS_PLUGINS_INSTALL_BASE}") set(DEFAULT_DEFINES QT_DISABLE_DEPRECATED_BEFORE=0x050f00 QT_DISABLE_DEPRECATED_UP_TO=0x050f00 QT_WARN_DEPRECATED_BEFORE=0x060700 QT_WARN_DEPRECATED_UP_TO=0x060700 QT_NO_JAVA_STYLE_ITERATORS QT_USE_QSTRINGBUILDER ) if(WIN32) list(APPEND DEFAULT_DEFINES UNICODE _UNICODE _SCL_SECURE_NO_WARNINGS) endif() if(WITH_TESTS) list(APPEND DEFAULT_DEFINES QBS_WITH_TESTS) endif() # CMake 3.10 doesn't have list(TRANSFORM) function(list_transform_prepend var prefix) set(temp "") foreach(f ${${var}}) list(APPEND temp "${prefix}${f}") endforeach() set(${var} "${temp}" PARENT_SCOPE) endfunction() function(add_qbs_app target_name) cmake_parse_arguments(_arg "" "DESTINATION" "DEFINES;PUBLIC_DEFINES;DEPENDS;PUBLIC_DEPENDS;INCLUDES;PUBLIC_INCLUDES;SOURCES;" ${ARGN} ) if (${_arg_UNPARSED_ARGUMENTS}) message(FATAL_ERROR "add_qbs_app had unparsed arguments") endif() set(_DESTINATION "${QBS_APP_INSTALL_DIR}") if(_arg_DESTINATION) set(_DESTINATION "${_arg_DESTINATION}") endif() add_executable(${target_name} ${_arg_SOURCES}) target_compile_definitions( ${target_name} PRIVATE ${_arg_DEFINES} ${DEFAULT_DEFINES} PUBLIC ${_arg_PUBLIC_DEFINES}) target_include_directories( ${target_name} PRIVATE ${_arg_INCLUDES} PUBLIC ${_arg_PUBLIC_INCLUDES}) target_link_libraries(${target_name} PRIVATE ${_arg_DEPENDS} PUBLIC ${_arg_PUBLIC_DEPENDS}) set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${_DESTINATION} BUILD_RPATH "${QBS_APP_RPATH}" INSTALL_RPATH "${QBS_APP_RPATH}" MACOSX_RPATH ${QBS_MACOSX_RPATH} ) install(TARGETS ${target_name} RUNTIME DESTINATION ${_DESTINATION}) endfunction() function(add_qbs_library target_name) cmake_parse_arguments(_arg "STATIC" "" "DEFINES;PUBLIC_DEFINES;DEPENDS;PUBLIC_DEPENDS;INCLUDES;PUBLIC_INCLUDES;SOURCES;" ${ARGN} ) if (${_arg_UNPARSED_ARGUMENTS}) message(FATAL_ERROR "add_qbs_library had unparsed arguments") endif() set(library_type SHARED) if (_arg_STATIC) set(library_type STATIC) endif() string(REGEX REPLACE "\\.[0-9]+$" "" _SOVERSION ${QBS_VERSION}) add_library(${target_name} ${library_type} ${_arg_SOURCES}) target_compile_definitions( ${target_name} PRIVATE ${_arg_DEFINES} ${DEFAULT_DEFINES} PUBLIC ${_arg_PUBLIC_DEFINES}) target_include_directories( ${target_name} PRIVATE ${_arg_INCLUDES} PUBLIC ${_arg_PUBLIC_INCLUDES} INTERFACE $) target_link_libraries(${target_name} PRIVATE ${_arg_DEPENDS} PUBLIC ${_arg_PUBLIC_DEPENDS}) set_target_properties(${target_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_LIB_INSTALL_DIR} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_LIB_INSTALL_DIR} RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_DLL_INSTALL_DIR} BUILD_RPATH "${QBS_LIB_RPATH}" INSTALL_RPATH "${QBS_LIB_RPATH}" MACOSX_RPATH ${QBS_MACOSX_RPATH} SOVERSION ${_SOVERSION} VERSION ${QBS_VERSION} ) if (NOT _arg_STATIC) install(TARGETS ${target_name} LIBRARY DESTINATION ${QBS_LIB_INSTALL_DIR} RUNTIME DESTINATION ${QBS_DLL_INSTALL_DIR} ) endif() if(MSVC) target_compile_options(${target_name} PUBLIC /EHsc) endif() endfunction() function(add_qbs_plugin target_name) cmake_parse_arguments(_arg "" "" "DEFINES;PUBLIC_DEFINES;DEPENDS;PUBLIC_DEPENDS;INCLUDES;PUBLIC_INCLUDES;SOURCES;" ${ARGN} ) if (${_arg_UNPARSED_ARGUMENTS}) message(FATAL_ERROR "add_qbs_plugin had unparsed arguments") endif() add_library(${target_name} MODULE ${_arg_SOURCES}) target_compile_definitions( ${target_name} PRIVATE ${_arg_DEFINES} ${DEFAULT_DEFINES} PUBLIC ${_arg_PUBLIC_DEFINES}) target_include_directories( ${target_name} PRIVATE ${_arg_INCLUDES} PUBLIC ${_arg_PUBLIC_INCLUDES}) target_link_libraries(${target_name} PRIVATE ${_arg_DEPENDS} PUBLIC ${_arg_PUBLIC_DEPENDS}) add_dependencies(qbs ${target_name}) set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_PLUGINS_INSTALL_DIR} RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_PLUGINS_INSTALL_DIR} BUILD_RPATH "${QBS_PLUGINS_RPATH}" INSTALL_RPATH "${QBS_PLUGINS_RPATH}" MACOSX_RPATH ${QBS_MACOSX_RPATH} ) install(TARGETS ${target_name} LIBRARY DESTINATION ${QBS_PLUGINS_INSTALL_DIR} RUNTIME DESTINATION ${QBS_PLUGINS_INSTALL_DIR} ) endfunction() function(add_qbs_test test_name) cmake_parse_arguments(_arg "" "" "DEFINES;PUBLIC_DEFINES;DEPENDS;PUBLIC_DEPENDS;INCLUDES;PUBLIC_INCLUDES;SOURCES;" ${ARGN} ) if (${_arg_UNPARSED_ARGUMENTS}) message(FATAL_ERROR "add_qbs_test had unparsed arguments") endif() set(target_name "tst_${test_name}") string(TOUPPER ${test_name} suite_name) # cmake is beatiful, here we have string(REPLACE - _ suite_name ${suite_name}) # and here we have add_executable(${target_name} ${_arg_SOURCES}) target_compile_definitions(${target_name} PRIVATE "QBS_TEST_SUITE_NAME=\"${suite_name}\"" "SRCDIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"" ) set(TEST_DEFINES ${DEFAULT_DEFINES}) list(REMOVE_ITEM TEST_DEFINES QT_USE_QSTRINGBUILDER) target_compile_definitions( ${target_name} PRIVATE ${_arg_DEFINES} ${TEST_DEFINES} PUBLIC ${_arg_PUBLIC_DEFINES}) target_include_directories( ${target_name} PRIVATE ${_arg_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/../../../src" PUBLIC ${_arg_PUBLIC_INCLUDES} ) target_link_libraries( ${target_name} PRIVATE ${_arg_DEPENDS} qbscore qbsconsolelogger Qt${QT_VERSION_MAJOR}::Test PUBLIC ${_arg_PUBLIC_DEPENDS} ) set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_APP_INSTALL_DIR} BUILD_RPATH "${QBS_APP_RPATH}" INSTALL_RPATH "${QBS_APP_RPATH}" MACOSX_RPATH ${QBS_MACOSX_RPATH} ) install(TARGETS ${target_name} RUNTIME DESTINATION ${QBS_APP_INSTALL_DIR}) add_test(NAME ${target_name} COMMAND ${target_name}) endfunction() qbs-src-3.3.1/cmake/QbsDocumentation.cmake0000644000175100017510000002634015232633614020051 0ustar runnerrunner# Options: option(QBS_INSTALL_HTML_DOCS "Whether to install Qbs HTML Documentation" OFF) option(QBS_INSTALL_QCH_DOCS "Whether to install Qbs QCH Documentation" OFF) option(QBS_INSTALL_MAN_PAGE "Whether to install Qbs man page" OFF) # Get information on directories from qmake # as this is not yet exported by cmake. # Used for QT_INSTALL_DOCS function(qt_query_qmake) if (NOT TARGET Qt${QT_VERSION_MAJOR}::qmake) message(FATAL_ERROR "Qmake was not found. Add find_package(Qt5 COMPONENTS Core) to CMake to enable.") endif() # dummy check for if we already queried qmake if (QT_INSTALL_BINS) return() endif() get_target_property(_qmake_binary Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) execute_process(COMMAND "${_qmake_binary}" "-query" TIMEOUT 10 RESULT_VARIABLE _qmake_result OUTPUT_VARIABLE _qmake_stdout OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT "${_qmake_result}" STREQUAL "0") message(FATAL_ERROR "Qmake did not execute successfully: ${_qmake_result}.") endif() # split into lines: string(REPLACE "\n" ";" _lines "${_qmake_stdout}") foreach(_line ${_lines}) # split line into key/value pairs string(REPLACE ":" ";" _parts "${_line}") list(GET _parts 0 _key) list(REMOVE_AT _parts 0) string(REPLACE ";" ":" _value "${_parts}") set("${_key}" "${_value}" CACHE PATH "qmake import of ${_key}" FORCE) endforeach() endfunction() function(_qbs_setup_doc_targets) # Set up important targets: if (NOT TARGET qbs_html_docs) add_custom_target(qbs_html_docs COMMENT "Build HTML documentation") endif() if (NOT TARGET qbs_qch_docs) add_custom_target(qbs_qch_docs COMMENT "Build QCH documentation") endif() if (NOT TARGET BuildQbsDocumentation) add_custom_target( BuildQbsDocumentation ALL COMMENT "Build Qbs documentation") add_dependencies(BuildQbsDocumentation qbs_html_docs qbs_qch_docs) endif() if (NOT TARGET qbs_docs) add_custom_target( qbs_docs ALL COMMENT "Build Qbs documentation") add_dependencies(qbs_docs BuildQbsDocumentation) endif() endfunction() function(_find_python_module module) string(TOUPPER ${module} module_upper) if (NOT PY_${module_upper}) if (ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") set(${module}_FIND_REQUIRED TRUE) endif() # A module's location is usually a directory, but for binary modules # it's a .so file. execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" RESULT_VARIABLE _${module}_status OUTPUT_VARIABLE _${module}_location ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT _${module}_status) set(PY_${module_upper} ${_${module}_location} CACHE STRING "Location of Python module ${module}") endif() endif() find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) endfunction() function(_qbs_setup_qdoc_targets _qdocconf_file _retval) cmake_parse_arguments(_arg "" "HTML_DIR;INSTALL_DIR;POSTFIX" "INDEXES;INCLUDE_DIRECTORIES;FRAMEWORK_PATHS;ENVIRONMENT_EXPORTS;SOURCES" ${ARGN}) foreach(_index ${_arg_INDEXES}) list(APPEND _qdoc_index_args "-indexdir;${_index}") endforeach() set(_env "") foreach(_export ${_arg_ENVIRONMENT_EXPORTS}) if (NOT DEFINED "${_export}") message(FATAL_ERROR "${_export} is not known when trying to export it to qdoc.") endif() list(APPEND _env "${_export}=${${_export}}") endforeach() get_target_property(_qdoc Qt${QT_VERSION_MAJOR}::qdoc IMPORTED_LOCATION) set(_full_qdoc_command "${_qdoc}") if (_env) set(_full_qdoc_command "${CMAKE_COMMAND}" "-E" "env" ${_env} "${_qdoc}") endif() if (_arg_HTML_DIR STREQUAL "") set(_arg_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc") endif() get_filename_component(_target "${_qdocconf_file}" NAME_WE) set(_html_outputdir "${_arg_HTML_DIR}") file(MAKE_DIRECTORY "${_html_outputdir}") set(_qdoc_include_args "") if (_arg_INCLUDE_DIRECTORIES OR _arg_FRAMEWORK_PATHS) # pass include directories to qdoc via hidden @ option, since we need to generate a file # to be able to resolve the generators inside the include paths set(_qdoc_includes "${CMAKE_CURRENT_BINARY_DIR}/cmake/qdoc_${_target}.inc") set(_qdoc_include_args "@${_qdoc_includes}") set(_includes "") if (_arg_INCLUDE_DIRECTORIES) set(_includes "-I$\n") endif() set(_frameworks "") if (_arg_FRAMEWORK_PATHS) set(_frameworks "-F$\n") endif() file(GENERATE OUTPUT "${_qdoc_includes}" CONTENT "${_includes}${_frameworks}" ) endif() set(_html_artifact "${_html_outputdir}/index.html") add_custom_command( OUTPUT "${_html_artifact}" COMMAND cmake -E remove_directory "${_html_outputdir}" COMMAND ${_full_qdoc_command} -outputdir "${_html_outputdir}" "${_qdocconf_file}" ${_qdoc_index_args} ${_qdoc_include_args} DEPENDS "${_qdocconf_file}" ${_arg_SOURCES} COMMENT "Build HTML documentation from ${_qdocconf_file}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM ) if (NOT Python3_Interpreter_FOUND) message(WARNING "Cannot find python3 binary. Qbs documentation will not be built.") return() endif() _find_python_module(lxml) _find_python_module(bs4) if (NOT PY_LXML OR NOT PY_BS4) message(WARNING "Cannot import lxml and bs4 python modules. Qbs documentation will not be built.") return() endif() set(_fixed_html_artifact "${CMAKE_CURRENT_BINARY_DIR}/qbsdoc.dummy") set(_fix_qml_imports_script ${Qbs_SOURCE_DIR}/doc/fix-qmlimports.py) add_custom_command( OUTPUT "${_fixed_html_artifact}" COMMAND ${Python3_EXECUTABLE} "${_fix_qml_imports_script}" ${_html_outputdir} COMMAND cmake -E touch ${_fixed_html_artifact} DEPENDS "${_html_artifact}" "${_fix_qml_imports_script}" COMMENT "Fixing bogus QML import statements" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM ) set(_html_target "qbs_html_docs_${_target}") add_custom_target(${_html_target} DEPENDS "${_fixed_html_artifact}") add_dependencies(qbs_html_docs "${_html_target}") # artifacts might be required for QCH-only installation, so we build them # always, and skip HTML docs installation here if (QBS_INSTALL_HTML_DOCS) install(DIRECTORY "${_html_outputdir}" DESTINATION "${_arg_INSTALL_DIR}" COMPONENT qbs_docs) endif() set("${_retval}" "${_html_outputdir}" PARENT_SCOPE) endfunction() function(_qbs_setup_qhelpgenerator_targets _qdocconf_file _html_outputdir) cmake_parse_arguments(_arg "" "QCH_DIR;INSTALL_DIR" "" ${ARGN}) if (_arg_UNPARSED_ARGUMENTS) message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") endif() if (NOT _arg_QCH_DIR) set(_arg_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc") endif() if (NOT TARGET Qt${QT_VERSION_MAJOR}::qhelpgenerator) message(WARNING "qhelpgenerator missing: No QCH documentation targets were generated. Add find_package(Qt5 COMPONENTS Help) to CMake to enable.") return() endif() get_filename_component(_target "${_qdocconf_file}" NAME_WE) set(_html_target "qbs_html_docs_${_target}") if (NOT TARGET ${_html_target}) return() endif() set(_qch_outputdir "${_arg_QCH_DIR}") file(MAKE_DIRECTORY "${_qch_outputdir}") set(_fixed_html_artifact "${CMAKE_CURRENT_BINARY_DIR}/qbsdoc.dummy") set(_qhp_artifact "${_html_outputdir}/${_target}.qhp") set(_qch_artifact "${_qch_outputdir}/${_target}.qch") add_custom_command( OUTPUT "${_qch_artifact}" COMMAND Qt${QT_VERSION_MAJOR}::qhelpgenerator "${_qhp_artifact}" -o "${_qch_artifact}" DEPENDS "${_fixed_html_artifact}" COMMENT "Build QCH documentation from ${_qdocconf_file}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" VERBATIM ) set(_qch_target "qbs_qch_docs_${_target}") add_custom_target("${_qch_target}" DEPENDS "${_qch_artifact}") add_dependencies(qbs_qch_docs "${_qch_target}") install(FILES "${_qch_outputdir}/${_target}.qch" DESTINATION "${_arg_INSTALL_DIR}" COMPONENT qbs_docs) endfunction() # Helper functions: function(_qbs_qdoc_build_qdocconf_file _qdocconf_file) _qbs_setup_doc_targets() if (NOT TARGET Qt${QT_VERSION_MAJOR}::qdoc) message(WARNING "No qdoc binary found: No documentation targets were generated") return() endif() cmake_parse_arguments(_arg "QCH" "HTML_DIR;QCH_DIR;INSTALL_DIR;POSTFIX" "INDEXES;INCLUDE_DIRECTORIES;FRAMEWORK_PATHS;ENVIRONMENT_EXPORTS;SOURCES" ${ARGN}) if (_arg_UNPARSED_ARGUMENTS) message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") endif() if (NOT _arg_INSTALL_DIR) message(FATAL_ERROR "No INSTALL_DIR set when calling qdoc_build_qdocconf_file") endif() _qbs_setup_qdoc_targets("${_qdocconf_file}" _html_outputdir HTML_DIR "${_arg_HTML_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}" INDEXES ${_arg_INDEXES} ENVIRONMENT_EXPORTS ${_arg_ENVIRONMENT_EXPORTS} POSTFIX "${_arg_POSTFIX}" INCLUDE_DIRECTORIES ${_arg_INCLUDE_DIRECTORIES} FRAMEWORK_PATHS ${_arg_FRAMEWORK_PATHS} SOURCES ${_arg_SOURCES} ) if (_arg_QCH) _qbs_setup_qhelpgenerator_targets("${_qdocconf_file}" "${_html_outputdir}" QCH_DIR "${_arg_QCH_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}") endif() endfunction() function(add_qbs_documentation qdocconf_file) cmake_parse_arguments(_arg "" "" "INCLUDE_DIRECTORIES;FRAMEWORK_PATHS;SOURCES" ${ARGN}) if (_arg_UNPARSED_ARGUMENTS) message(FATAL_ERROR "add_qbs_documentation has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") endif() ### Skip docs setup if that is not needed! if (NOT QBS_INSTALL_HTML_DOCS AND NOT QBS_INSTALL_QCH_DOCS) return() endif() qt_query_qmake() set(SRCDIR "${Qbs_SOURCE_DIR}/doc") set(_qch_params) # if QBS_INSTALL_QCH_DOCS is No, qch generation will be skipped entirely if (QBS_INSTALL_QCH_DOCS) set(_qch_params QCH QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}") endif() set(_qdoc_params HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/${QBS_DOC_HTML_DIR_NAME}") list(APPEND _qdoc_params INSTALL_DIR "${QBS_DOC_INSTALL_DIR}") # Set up environment for qdoc: string(REPLACE "." "" QBS_VERSION_TAG "${QBS_VERSION}") list(APPEND _qdoc_params ENVIRONMENT_EXPORTS SRCDIR QBS_VERSION QBS_VERSION_TAG QT_INSTALL_DOCS ) _qbs_qdoc_build_qdocconf_file(${qdocconf_file} ${_qch_params} ${_qdoc_params} INCLUDE_DIRECTORIES ${_arg_INCLUDE_DIRECTORIES} FRAMEWORK_PATHS ${_arg_FRAMEWORK_PATHS} SOURCES ${_arg_SOURCES} ) endfunction() qbs-src-3.3.1/LICENSE.LGPLv210000644000175100017510000006350215232633614014604 0ustar runnerrunner GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qbs-src-3.3.1/README.md0000644000175100017510000000222315232633614013761 0ustar runnerrunner# Qbs Qbs is a build automation tool designed to conveniently manage the build process of software projects across multiple platforms. Qbs can be used for any software project, regardless of programming language, toolkit, or libraries used. ## Documentation Qbs product documentation is available at [doc.qt.io/qbs](http://doc.qt.io/qbs/index.html) The project's homepage is [wiki.qt.io/qbs](http://wiki.qt.io/qbs) ## Supported platforms Qbs binaries are available for Windows, macOS, Linux, and FreeBSD. For more information about how to install Qbs on your platform, see the [Installing](https://doc.qt.io/qbs/installing.html) page in the documentation. Qbs allows to build applications for different platforms, for the list of supported platforms and the details about each platform, see the [Target Platforms](https://doc.qt.io/qbs/platforms.html) page. ## Building Qbs For information about building Qbs from sources, see ["Appendix A: Building Qbs"](http://doc.qt.io/qbs/building-qbs.html). ## Reporting Bugs Please report any bugs in our [bug tracker](https://bugreports.qt.io/browse/QBS). ## Contributing See [Contributing to Qbs](CONTRIBUTING.md) qbs-src-3.3.1/RELEASE.md0000644000175100017510000000670515232633614014115 0ustar runnerrunner# Release Instructions This file contains instructions how to publish a Qbs release into various package systems. ## Building packages Release packages are built automatically by the [Build release packages](https://github.com/qbs/qbs/actions/workflows/release.yml) job on GitHub actions. The job builds every commit, so you'll need to find a specific run triggered by pushing a git tag instead of a commit. The only interesting artifact is qbs-release-v1.x.y - it contains Windows binary packages as well as source packages. Packages should then be uploaded to the [Qt Website](https://download.qt.io/official_releases/qbs/). ## Chocolatey For updating Qbs in [Chocolatey](https://community.chocolatey.org/packages/qbs), you'll need to be a maintainer of the Qbs project. You'll also will need an API key from your [account](https://community.chocolatey.org/account) (make sure you have one). Get the qbs.1.x.y.nupkg file from the qbs-release-v1.x.y.zip archive and run the following command: ``` choco push --api-key qbs.1.x.y.nupkg" ``` Choco will upload the file, download binary packages from the Qt Website and publish Qbs automatically. ## Homebrew First, you'll need to [install](https://docs.brew.sh/Installation) Homewbrew. Second, you'll need to fork the [homebrew-core](https://github.com/Homebrew/homebrew-core) repo to you GitHub account. Next you'll need to add your remote to the existing repo: ``` $ brew update $ cd "$(brew --repository homebrew/core)" $ git remote add github git@github.com:/homebrew-core.git # Create a new git branch for your formula so your pull request is easy to # modify if any changes come up during review. $ git checkout -b origin/master ``` You'll need a SHA-256 sum for the qbs-src-1.x.y.tar.gz source package. SHA-256 sum can be found in the sha256sums.txt file from the qbs-release-v1.x.y.zip. Check if the same upgrade has been already submitted by searching the open pull requests for [Qbs](https://github.com/Homebrew/homebrew-core/pulls?q=is%3Apr+is%3Aopen+qbs). Run the following command, replacing the version and SHA-256 sum: ``` $ brew bump-formula-pr --strict qbs \ --url https://download.qt.io/official_releases/qbs/1.x.y/qbs-src-1.x.y.tar.gz \ --sha256= ``` The above can also be done manually by editing the formula source code and creating a pull request. Some useful commands to build/test formula locally: ``` $ brew install --build-from-source qbs $ brew test qbs $ brew audit --strict qbs ``` ## Mac Ports Fork [macports-ports](https://github.com/macports/macports-ports) to your GitHub account and clone the repo. Run the following command in the repo dir (must be done only once): ``` $ sudo /opt/local/bin/portindex ``` Make sure that /opt/local/etc/macports/sources.conf contains a line like file:///Users/abbapoh/dev/macports-ports [default] pointing to your local repo. Get the qbs-src-1.x.y.tar.gz source package from the archive or from the [Qt Website](https://download.qt.io/official_releases/qbs/) and make note of the file size: ``` $ ls -l qbs-src-1.x.y.tar.gz ``` Get checksums: ``` $ openssl sha256 qbs-src-1.x.y.tar.gz $ openssl rmd160 qbs-src-1.x.y.tar.gz ``` Update the devel/qbs/Portfile file with the new url, filesize and checksums. Build the package: ``` $ /opt/local/bin/port lint qbs $ sudo /opt/local/bin/port -vst install qbs $ /opt/local/bin/qbs --version # Check that this reports the right version ``` Commit. Push. Create merge request. qbs-src-3.3.1/.gitignore0000644000175100017510000000075415232633614014501 0ustar runnerrunner.qmake.cache .qmake.stash .qbs .vscode* /build *.dll *.dylib *.exe *.exp *.ilk *.manifest *.obj *.pdb *.pro.user* *.qbs.user* CMakeLists.txt.user* *.xcodeproj/ target_wrapper.sh *~ *.o *.lib *.so moc_*.cpp qrc_*.cpp *.moc *.qch *.a *.cpp.orig ui_*.h Makefile* debug/ release/ /tests/auto/blackbox/testWorkDir /tests/auto/blackbox/tst_blackbox /tests/auto/buildgraph/tst_buildgraph /tests/auto/language/tst_language /tests/auto/tools/tst_tools *.app/ *_resource.rc bin/* doc/qbs/html/* /lib qbs-src-3.3.1/.clang-format0000644000175100017510000000636115232633614015064 0ustar runnerrunner# .clang-format for Qbs # based on https://github.com/qt-creator/qt-creator/blob/v12.0.1/.clang-format # # This is for clang-format >= 5.0. # # Use ../../tests/clang-format-test/clang-format-test.cpp for documenting problems # or testing changes. # --- Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: AlwaysBreak AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: DontAlign AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false BraceWrapping: AfterClass: true AfterControlStatement: Never AfterEnum: false AfterFunction: true AfterNamespace: false AfterObjCDeclaration: false AfterStruct: true AfterUnion: false BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false BreakBeforeBinaryOperators: All BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 100 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - forever # avoids { wrapped to next line - foreach - Q_FOREACH - BOOST_FOREACH IncludeCategories: - Regex: '^

\n" \ " © 2022 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners. " \ " The documentation provided herein is licensed under the terms of the" \ " GNU Free Documentation" \ " License version 1.3 as published by the Free Software Foundation. " \ " Qt and respective logos are trademarks of The Qt Company Ltd " \ " in Finland and/or other countries worldwide. All other trademarks are property\n" \ " of their respective owners.